kvm.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [kvm-unit-tests PATCH v4 0/2] nSVM: vNMI testcase
@ 2023-04-05 20:51 Sean Christopherson
  2023-04-05 20:51 ` [kvm-unit-tests PATCH v4 1/2] nSVM: Add helper to report fatal errors in guest Sean Christopherson
                   ` (2 more replies)
  0 siblings, 3 replies; 7+ messages in thread
From: Sean Christopherson @ 2023-04-05 20:51 UTC (permalink / raw)
  To: Paolo Bonzini; +Cc: kvm, Sean Christopherson, Santosh Shukla

Santosh's vNMI test, plus a prep patch to dedup a pile of copy+paste code
in the SVM test for handling fatal errors in the guest.

Santosh, can you check that I didn't break anything in the vNMI test?  I
don't have access to the necessary hardware.

Thanks!

Santosh Shukla (1):
  x86: nSVM: Add support for VNMI test

Sean Christopherson (1):
  nSVM: Add helper to report fatal errors in guest

 lib/x86/processor.h |   1 +
 x86/svm.c           |   5 ++
 x86/svm.h           |   8 ++
 x86/svm_tests.c     | 205 ++++++++++++++++++++++++++------------------
 4 files changed, 134 insertions(+), 85 deletions(-)


base-commit: 723a5703848d91f7aea8bc01d12fe8b1a6fc2391
-- 
2.40.0.348.gf938b09366-goog


^ permalink raw reply	[flat|nested] 7+ messages in thread

* [kvm-unit-tests PATCH v4 1/2] nSVM: Add helper to report fatal errors in guest
  2023-04-05 20:51 [kvm-unit-tests PATCH v4 0/2] nSVM: vNMI testcase Sean Christopherson
@ 2023-04-05 20:51 ` Sean Christopherson
  2023-04-06  8:31   ` Mathias Krause
  2023-04-05 20:51 ` [kvm-unit-tests PATCH v4 2/2] x86: nSVM: Add support for VNMI test Sean Christopherson
  2023-06-07 23:26 ` [kvm-unit-tests PATCH v4 0/2] nSVM: vNMI testcase Sean Christopherson
  2 siblings, 1 reply; 7+ messages in thread
From: Sean Christopherson @ 2023-04-05 20:51 UTC (permalink / raw)
  To: Paolo Bonzini; +Cc: kvm, Sean Christopherson, Santosh Shukla

Add a helper macro to dedup nSVM test code that handles fatal errors
by reporting the failure, setting the test stage to a magic number, and
invoking VMMCALL to bail to the host and terminate.

Note, the V_TPR fails if report() is invoked.  Punt on the issue for
now as most users already report only failures, but leave a TODO for
future developers.

Signed-off-by: Sean Christopherson <seanjc@google.com>
---
 x86/svm_tests.c | 127 ++++++++++++++++--------------------------------
 1 file changed, 42 insertions(+), 85 deletions(-)

diff --git a/x86/svm_tests.c b/x86/svm_tests.c
index 27ce47b4..e87db3fa 100644
--- a/x86/svm_tests.c
+++ b/x86/svm_tests.c
@@ -947,6 +947,21 @@ static bool lat_svm_insn_check(struct svm_test *test)
 	return true;
 }
 
+/*
+ * Report failures from SVM guest code, and on failure, set the stage to -1 and
+ * do VMMCALL to terminate the test (host side must treat -1 as "finished").
+ * TODO: fix the tests that don't play nice with a straight report, e.g. the
+ * V_TPR test fails if report() is invoked.
+ */
+#define report_svm_guest(cond, test, fmt, args...)	\
+do {							\
+	if (!(cond)) {					\
+		report_fail("why didn't my format '" fmt "' format?", ##args);\
+		set_test_stage(test, -1);		\
+		vmmcall();				\
+	}						\
+} while (0)
+
 bool pending_event_ipi_fired;
 bool pending_event_guest_run;
 
@@ -1049,22 +1064,16 @@ static void pending_event_cli_prepare_gif_clear(struct svm_test *test)
 
 static void pending_event_cli_test(struct svm_test *test)
 {
-	if (pending_event_ipi_fired == true) {
-		set_test_stage(test, -1);
-		report_fail("Interrupt preceeded guest");
-		vmmcall();
-	}
+	report_svm_guest(!pending_event_ipi_fired, test,
+			 "IRQ should NOT be delivered while IRQs disabled");
 
 	/* VINTR_MASKING is zero.  This should cause the IPI to fire.  */
 	irq_enable();
 	asm volatile ("nop");
 	irq_disable();
 
-	if (pending_event_ipi_fired != true) {
-		set_test_stage(test, -1);
-		report_fail("Interrupt not triggered by guest");
-	}
-
+	report_svm_guest(pending_event_ipi_fired, test,
+			 "IRQ should be delivered after enabling IRQs");
 	vmmcall();
 
 	/*
@@ -1079,11 +1088,9 @@ static void pending_event_cli_test(struct svm_test *test)
 
 static bool pending_event_cli_finished(struct svm_test *test)
 {
-	if ( vmcb->control.exit_code != SVM_EXIT_VMMCALL) {
-		report_fail("VM_EXIT return to host is not EXIT_VMMCALL exit reason 0x%x",
-			    vmcb->control.exit_code);
-		return true;
-	}
+	report_svm_guest(vmcb->control.exit_code == SVM_EXIT_VMMCALL, test,
+			 "Wanted VMMCALL VM-Exit, got ext reason 0x%x",
+			 vmcb->control.exit_code);
 
 	switch (get_test_stage(test)) {
 	case 0:
@@ -1158,12 +1165,8 @@ static void interrupt_test(struct svm_test *test)
 	for (loops = 0; loops < 10000000 && !timer_fired; loops++)
 		asm volatile ("nop");
 
-	report(timer_fired, "direct interrupt while running guest");
-
-	if (!timer_fired) {
-		set_test_stage(test, -1);
-		vmmcall();
-	}
+	report_svm_guest(timer_fired, test,
+			 "direct interrupt while running guest");
 
 	apic_write(APIC_TMICT, 0);
 	irq_disable();
@@ -1174,12 +1177,8 @@ static void interrupt_test(struct svm_test *test)
 	for (loops = 0; loops < 10000000 && !timer_fired; loops++)
 		asm volatile ("nop");
 
-	report(timer_fired, "intercepted interrupt while running guest");
-
-	if (!timer_fired) {
-		set_test_stage(test, -1);
-		vmmcall();
-	}
+	report_svm_guest(timer_fired, test,
+			 "intercepted interrupt while running guest");
 
 	irq_enable();
 	apic_write(APIC_TMICT, 0);
@@ -1190,13 +1189,8 @@ static void interrupt_test(struct svm_test *test)
 	apic_write(APIC_TMICT, 1000000);
 	safe_halt();
 
-	report(rdtsc() - start > 10000 && timer_fired,
-	       "direct interrupt + hlt");
-
-	if (!timer_fired) {
-		set_test_stage(test, -1);
-		vmmcall();
-	}
+	report_svm_guest(timer_fired, test, "direct interrupt + hlt");
+	report(rdtsc() - start > 10000, "IRQ arrived after expected delay");
 
 	apic_write(APIC_TMICT, 0);
 	irq_disable();
@@ -1207,13 +1201,8 @@ static void interrupt_test(struct svm_test *test)
 	apic_write(APIC_TMICT, 1000000);
 	asm volatile ("hlt");
 
-	report(rdtsc() - start > 10000 && timer_fired,
-	       "intercepted interrupt + hlt");
-
-	if (!timer_fired) {
-		set_test_stage(test, -1);
-		vmmcall();
-	}
+	report_svm_guest(timer_fired, test, "intercepted interrupt + hlt");
+	report(rdtsc() - start > 10000, "IRQ arrived after expected delay");
 
 	apic_write(APIC_TMICT, 0);
 	irq_disable();
@@ -1287,10 +1276,7 @@ static void nmi_test(struct svm_test *test)
 {
 	apic_icr_write(APIC_DEST_SELF | APIC_DEST_PHYSICAL | APIC_DM_NMI | APIC_INT_ASSERT, 0);
 
-	report(nmi_fired, "direct NMI while running guest");
-
-	if (!nmi_fired)
-		set_test_stage(test, -1);
+	report_svm_guest(nmi_fired, test, "direct NMI while running guest");
 
 	vmmcall();
 
@@ -1298,11 +1284,7 @@ static void nmi_test(struct svm_test *test)
 
 	apic_icr_write(APIC_DEST_SELF | APIC_DEST_PHYSICAL | APIC_DM_NMI | APIC_INT_ASSERT, 0);
 
-	if (!nmi_fired) {
-		report(nmi_fired, "intercepted pending NMI not dispatched");
-		set_test_stage(test, -1);
-	}
-
+	report_svm_guest(nmi_fired, test, "intercepted pending NMI delivered to guest");
 }
 
 static bool nmi_finished(struct svm_test *test)
@@ -1379,11 +1361,8 @@ static void nmi_hlt_test(struct svm_test *test)
 
 	asm volatile ("hlt");
 
-	report((rdtsc() - start > NMI_DELAY) && nmi_fired,
-	       "direct NMI + hlt");
-
-	if (!nmi_fired)
-		set_test_stage(test, -1);
+	report_svm_guest(nmi_fired, test, "direct NMI + hlt");
+	report(rdtsc() - start > NMI_DELAY, "direct NMI after expected delay");
 
 	nmi_fired = false;
 
@@ -1395,14 +1374,8 @@ static void nmi_hlt_test(struct svm_test *test)
 
 	asm volatile ("hlt");
 
-	report((rdtsc() - start > NMI_DELAY) && nmi_fired,
-	       "intercepted NMI + hlt");
-
-	if (!nmi_fired) {
-		report(nmi_fired, "intercepted pending NMI not dispatched");
-		set_test_stage(test, -1);
-		vmmcall();
-	}
+	report_svm_guest(nmi_fired, test, "intercepted NMI + hlt");
+	report(rdtsc() - start > NMI_DELAY, "intercepted NMI after expected delay");
 
 	set_test_stage(test, 3);
 }
@@ -1534,37 +1507,23 @@ static void virq_inject_prepare(struct svm_test *test)
 
 static void virq_inject_test(struct svm_test *test)
 {
-	if (virq_fired) {
-		report_fail("virtual interrupt fired before L2 sti");
-		set_test_stage(test, -1);
-		vmmcall();
-	}
+	report_svm_guest(!virq_fired, test, "virtual IRQ blocked after L2 cli");
 
 	irq_enable();
 	asm volatile ("nop");
 	irq_disable();
 
-	if (!virq_fired) {
-		report_fail("virtual interrupt not fired after L2 sti");
-		set_test_stage(test, -1);
-	}
+	report_svm_guest(virq_fired, test, "virtual IRQ fired after L2 sti");
 
 	vmmcall();
 
-	if (virq_fired) {
-		report_fail("virtual interrupt fired before L2 sti after VINTR intercept");
-		set_test_stage(test, -1);
-		vmmcall();
-	}
+	report_svm_guest(!virq_fired, test, "intercepted VINTR blocked after L2 cli");
 
 	irq_enable();
 	asm volatile ("nop");
 	irq_disable();
 
-	if (!virq_fired) {
-		report_fail("virtual interrupt not fired after return from VINTR intercept");
-		set_test_stage(test, -1);
-	}
+	report_svm_guest(virq_fired, test, "intercepted VINTR fired after L2 sti");
 
 	vmmcall();
 
@@ -1572,10 +1531,8 @@ static void virq_inject_test(struct svm_test *test)
 	asm volatile ("nop");
 	irq_disable();
 
-	if (virq_fired) {
-		report_fail("virtual interrupt fired when V_IRQ_PRIO less than V_TPR");
-		set_test_stage(test, -1);
-	}
+	report_svm_guest(!virq_fired, test,
+			  "virtual IRQ blocked V_IRQ_PRIO less than V_TPR");
 
 	vmmcall();
 	vmmcall();
-- 
2.40.0.348.gf938b09366-goog


^ permalink raw reply related	[flat|nested] 7+ messages in thread

* [kvm-unit-tests PATCH v4 2/2] x86: nSVM: Add support for VNMI test
  2023-04-05 20:51 [kvm-unit-tests PATCH v4 0/2] nSVM: vNMI testcase Sean Christopherson
  2023-04-05 20:51 ` [kvm-unit-tests PATCH v4 1/2] nSVM: Add helper to report fatal errors in guest Sean Christopherson
@ 2023-04-05 20:51 ` Sean Christopherson
  2023-04-06 10:42   ` Santosh Shukla
  2023-06-07 23:26 ` [kvm-unit-tests PATCH v4 0/2] nSVM: vNMI testcase Sean Christopherson
  2 siblings, 1 reply; 7+ messages in thread
From: Sean Christopherson @ 2023-04-05 20:51 UTC (permalink / raw)
  To: Paolo Bonzini; +Cc: kvm, Sean Christopherson, Santosh Shukla

From: Santosh Shukla <santosh.shukla@amd.com>

Add a VNMI test case to test Virtual NMI in a nested environment,
The test covers the Virtual NMI (VNMI) delivery.

Signed-off-by: Santosh Shukla <santosh.shukla@amd.com>
[sean: reuse pieces of NMI test framework, fix formatting issues]
Signed-off-by: Sean Christopherson <seanjc@google.com>
---
 lib/x86/processor.h |  1 +
 x86/svm.c           |  5 +++
 x86/svm.h           |  8 +++++
 x86/svm_tests.c     | 78 +++++++++++++++++++++++++++++++++++++++++++++
 4 files changed, 92 insertions(+)

diff --git a/lib/x86/processor.h b/lib/x86/processor.h
index 3d58ef72..3802c1e2 100644
--- a/lib/x86/processor.h
+++ b/lib/x86/processor.h
@@ -267,6 +267,7 @@ static inline bool is_intel(void)
 #define X86_FEATURE_PAUSEFILTER		(CPUID(0x8000000A, 0, EDX, 10))
 #define X86_FEATURE_PFTHRESHOLD		(CPUID(0x8000000A, 0, EDX, 12))
 #define	X86_FEATURE_VGIF		(CPUID(0x8000000A, 0, EDX, 16))
+#define X86_FEATURE_V_NMI               (CPUID(0x8000000A, 0, EDX, 25))
 #define	X86_FEATURE_AMD_PMU_V2		(CPUID(0x80000022, 0, EAX, 0))
 
 static inline bool this_cpu_has(u64 feature)
diff --git a/x86/svm.c b/x86/svm.c
index ba435b4a..022a0fde 100644
--- a/x86/svm.c
+++ b/x86/svm.c
@@ -99,6 +99,11 @@ bool npt_supported(void)
 	return this_cpu_has(X86_FEATURE_NPT);
 }
 
+bool vnmi_supported(void)
+{
+       return this_cpu_has(X86_FEATURE_V_NMI);
+}
+
 int get_test_stage(struct svm_test *test)
 {
 	barrier();
diff --git a/x86/svm.h b/x86/svm.h
index 766ff7e3..4631c2ff 100644
--- a/x86/svm.h
+++ b/x86/svm.h
@@ -131,6 +131,13 @@ struct __attribute__ ((__packed__)) vmcb_control_area {
 #define V_INTR_MASKING_SHIFT 24
 #define V_INTR_MASKING_MASK (1 << V_INTR_MASKING_SHIFT)
 
+#define V_NMI_PENDING_SHIFT	11
+#define V_NMI_PENDING_MASK	(1 << V_NMI_PENDING_SHIFT)
+#define V_NMI_BLOCKING_SHIFT	12
+#define V_NMI_BLOCKING_MASK	(1 << V_NMI_BLOCKING_SHIFT)
+#define V_NMI_ENABLE_SHIFT	26
+#define V_NMI_ENABLE_MASK	(1 << V_NMI_ENABLE_SHIFT)
+
 #define SVM_INTERRUPT_SHADOW_MASK 1
 
 #define SVM_IOIO_STR_SHIFT 2
@@ -419,6 +426,7 @@ void default_prepare(struct svm_test *test);
 void default_prepare_gif_clear(struct svm_test *test);
 bool default_finished(struct svm_test *test);
 bool npt_supported(void);
+bool vnmi_supported(void);
 int get_test_stage(struct svm_test *test);
 void set_test_stage(struct svm_test *test, int s);
 void inc_test_stage(struct svm_test *test);
diff --git a/x86/svm_tests.c b/x86/svm_tests.c
index e87db3fa..3d2ca0f6 100644
--- a/x86/svm_tests.c
+++ b/x86/svm_tests.c
@@ -1419,6 +1419,81 @@ static bool nmi_hlt_check(struct svm_test *test)
 	return get_test_stage(test) == 3;
 }
 
+static void vnmi_prepare(struct svm_test *test)
+{
+	nmi_prepare(test);
+
+	/*
+	 * Disable NMI interception to start.  Enabling vNMI without
+	 * intercepting "real" NMIs should result in an ERR VM-Exit.
+	 */
+	vmcb->control.intercept &= ~(1ULL << INTERCEPT_NMI);
+	vmcb->control.int_ctl = V_NMI_ENABLE_MASK;
+	vmcb->control.int_vector = NMI_VECTOR;
+}
+
+static void vnmi_test(struct svm_test *test)
+{
+	report_svm_guest(!nmi_fired, test, "No vNMI before injection");
+	vmmcall();
+
+	report_svm_guest(nmi_fired, test, "vNMI delivered after injection");
+	vmmcall();
+}
+
+static bool vnmi_finished(struct svm_test *test)
+{
+	switch (get_test_stage(test)) {
+	case 0:
+		if (vmcb->control.exit_code != SVM_EXIT_ERR) {
+			report_fail("Wanted ERR VM-Exit, got 0x%x",
+				    vmcb->control.exit_code);
+			return true;
+		}
+		report(!nmi_fired, "vNMI enabled but NMI_INTERCEPT unset!");
+		vmcb->control.intercept |= (1ULL << INTERCEPT_NMI);
+		vmcb->save.rip += 3;
+		break;
+
+	case 1:
+		if (vmcb->control.exit_code != SVM_EXIT_VMMCALL) {
+			report_fail("Wanted VMMCALL VM-Exit, got 0x%x",
+				    vmcb->control.exit_code);
+			return true;
+		}
+		report(!nmi_fired, "vNMI with vector 2 not injected");
+		vmcb->control.int_ctl |= V_NMI_PENDING_MASK;
+		vmcb->save.rip += 3;
+		break;
+
+	case 2:
+		if (vmcb->control.exit_code != SVM_EXIT_VMMCALL) {
+			report_fail("Wanted VMMCALL VM-Exit, got 0x%x",
+				    vmcb->control.exit_code);
+			return true;
+		}
+		if (vmcb->control.int_ctl & V_NMI_BLOCKING_MASK) {
+			report_fail("V_NMI_BLOCKING_MASK not cleared on VMEXIT");
+			return true;
+		}
+		report_pass("VNMI serviced");
+		vmcb->save.rip += 3;
+		break;
+
+	default:
+		return true;
+	}
+
+	inc_test_stage(test);
+
+	return get_test_stage(test) == 3;
+}
+
+static bool vnmi_check(struct svm_test *test)
+{
+	return get_test_stage(test) == 3;
+}
+
 static volatile int count_exc = 0;
 
 static void my_isr(struct ex_regs *r)
@@ -3298,6 +3373,9 @@ struct svm_test svm_tests[] = {
 	{ "nmi_hlt", smp_supported, nmi_prepare,
 	  default_prepare_gif_clear, nmi_hlt_test,
 	  nmi_hlt_finished, nmi_hlt_check },
+        { "vnmi", vnmi_supported, vnmi_prepare,
+          default_prepare_gif_clear, vnmi_test,
+          vnmi_finished, vnmi_check },
 	{ "virq_inject", default_supported, virq_inject_prepare,
 	  default_prepare_gif_clear, virq_inject_test,
 	  virq_inject_finished, virq_inject_check },
-- 
2.40.0.348.gf938b09366-goog


^ permalink raw reply related	[flat|nested] 7+ messages in thread

* Re: [kvm-unit-tests PATCH v4 1/2] nSVM: Add helper to report fatal errors in guest
  2023-04-05 20:51 ` [kvm-unit-tests PATCH v4 1/2] nSVM: Add helper to report fatal errors in guest Sean Christopherson
@ 2023-04-06  8:31   ` Mathias Krause
  2023-04-06 16:31     ` Sean Christopherson
  0 siblings, 1 reply; 7+ messages in thread
From: Mathias Krause @ 2023-04-06  8:31 UTC (permalink / raw)
  To: Sean Christopherson; +Cc: kvm, Santosh Shukla, Paolo Bonzini

On 05.04.23 22:51, Sean Christopherson wrote:
> Add a helper macro to dedup nSVM test code that handles fatal errors
> by reporting the failure, setting the test stage to a magic number, and
> invoking VMMCALL to bail to the host and terminate.
> 
> Note, the V_TPR fails if report() is invoked.  Punt on the issue for
> now as most users already report only failures, but leave a TODO for
> future developers.
> 
> Signed-off-by: Sean Christopherson <seanjc@google.com>
> ---
>  x86/svm_tests.c | 127 ++++++++++++++++--------------------------------
>  1 file changed, 42 insertions(+), 85 deletions(-)
> 
> diff --git a/x86/svm_tests.c b/x86/svm_tests.c
> index 27ce47b4..e87db3fa 100644
> --- a/x86/svm_tests.c
> +++ b/x86/svm_tests.c
> @@ -947,6 +947,21 @@ static bool lat_svm_insn_check(struct svm_test *test)
>  	return true;
>  }
>  
> +/*
> + * Report failures from SVM guest code, and on failure, set the stage to -1 and
> + * do VMMCALL to terminate the test (host side must treat -1 as "finished").
> + * TODO: fix the tests that don't play nice with a straight report, e.g. the
> + * V_TPR test fails if report() is invoked.
> + */
> +#define report_svm_guest(cond, test, fmt, args...)	\
> +do {							\
> +	if (!(cond)) {					\

> +		report_fail("why didn't my format '" fmt "' format?", ##args);\
                            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Debug artifact? Should probably be this instead (making use of C99):

   #define report_svm_guest(cond, test, fmt,...)	\
   do {							\
    	if (!(cond)) {					\
   		report_fail((fmt), ##__VA_ARGS__);	\
   		set_test_stage((test), -1);		\
   		vmmcall();				\
   	}						\
   } while (0)

> +		set_test_stage(test, -1);		\
> +		vmmcall();				\
> +	}						\
> +} while (0)
> +
>  bool pending_event_ipi_fired;
>  bool pending_event_guest_run;
>  
> @@ -1049,22 +1064,16 @@ static void pending_event_cli_prepare_gif_clear(struct svm_test *test)
>  
>  static void pending_event_cli_test(struct svm_test *test)
>  {
> -	if (pending_event_ipi_fired == true) {
> -		set_test_stage(test, -1);
> -		report_fail("Interrupt preceeded guest");
> -		vmmcall();
> -	}
> +	report_svm_guest(!pending_event_ipi_fired, test,
> +			 "IRQ should NOT be delivered while IRQs disabled");
>  
>  	/* VINTR_MASKING is zero.  This should cause the IPI to fire.  */
>  	irq_enable();
>  	asm volatile ("nop");
>  	irq_disable();
>  
> -	if (pending_event_ipi_fired != true) {
> -		set_test_stage(test, -1);
> -		report_fail("Interrupt not triggered by guest");
> -	}
> -
> +	report_svm_guest(pending_event_ipi_fired, test,
> +			 "IRQ should be delivered after enabling IRQs");
>  	vmmcall();
>  
>  	/*
> @@ -1079,11 +1088,9 @@ static void pending_event_cli_test(struct svm_test *test)
>  
>  static bool pending_event_cli_finished(struct svm_test *test)
>  {
> -	if ( vmcb->control.exit_code != SVM_EXIT_VMMCALL) {
> -		report_fail("VM_EXIT return to host is not EXIT_VMMCALL exit reason 0x%x",
> -			    vmcb->control.exit_code);
> -		return true;
> -	}
> +	report_svm_guest(vmcb->control.exit_code == SVM_EXIT_VMMCALL, test,
> +			 "Wanted VMMCALL VM-Exit, got ext reason 0x%x",
> +			 vmcb->control.exit_code);
>  
>  	switch (get_test_stage(test)) {
>  	case 0:
> @@ -1158,12 +1165,8 @@ static void interrupt_test(struct svm_test *test)
>  	for (loops = 0; loops < 10000000 && !timer_fired; loops++)
>  		asm volatile ("nop");
>  
> -	report(timer_fired, "direct interrupt while running guest");
> -
> -	if (!timer_fired) {
> -		set_test_stage(test, -1);
> -		vmmcall();
> -	}
> +	report_svm_guest(timer_fired, test,
> +			 "direct interrupt while running guest");
>  
>  	apic_write(APIC_TMICT, 0);
>  	irq_disable();
> @@ -1174,12 +1177,8 @@ static void interrupt_test(struct svm_test *test)
>  	for (loops = 0; loops < 10000000 && !timer_fired; loops++)
>  		asm volatile ("nop");
>  
> -	report(timer_fired, "intercepted interrupt while running guest");
> -
> -	if (!timer_fired) {
> -		set_test_stage(test, -1);
> -		vmmcall();
> -	}
> +	report_svm_guest(timer_fired, test,
> +			 "intercepted interrupt while running guest");
>  
>  	irq_enable();
>  	apic_write(APIC_TMICT, 0);
> @@ -1190,13 +1189,8 @@ static void interrupt_test(struct svm_test *test)
>  	apic_write(APIC_TMICT, 1000000);
>  	safe_halt();
>  
> -	report(rdtsc() - start > 10000 && timer_fired,
> -	       "direct interrupt + hlt");
> -
> -	if (!timer_fired) {
> -		set_test_stage(test, -1);
> -		vmmcall();
> -	}
> +	report_svm_guest(timer_fired, test, "direct interrupt + hlt");
> +	report(rdtsc() - start > 10000, "IRQ arrived after expected delay");
>  
>  	apic_write(APIC_TMICT, 0);
>  	irq_disable();
> @@ -1207,13 +1201,8 @@ static void interrupt_test(struct svm_test *test)
>  	apic_write(APIC_TMICT, 1000000);
>  	asm volatile ("hlt");
>  
> -	report(rdtsc() - start > 10000 && timer_fired,
> -	       "intercepted interrupt + hlt");
> -
> -	if (!timer_fired) {
> -		set_test_stage(test, -1);
> -		vmmcall();
> -	}
> +	report_svm_guest(timer_fired, test, "intercepted interrupt + hlt");
> +	report(rdtsc() - start > 10000, "IRQ arrived after expected delay");
>  
>  	apic_write(APIC_TMICT, 0);
>  	irq_disable();
> @@ -1287,10 +1276,7 @@ static void nmi_test(struct svm_test *test)
>  {
>  	apic_icr_write(APIC_DEST_SELF | APIC_DEST_PHYSICAL | APIC_DM_NMI | APIC_INT_ASSERT, 0);
>  
> -	report(nmi_fired, "direct NMI while running guest");
> -
> -	if (!nmi_fired)
> -		set_test_stage(test, -1);
> +	report_svm_guest(nmi_fired, test, "direct NMI while running guest");
>  
>  	vmmcall();
>  
> @@ -1298,11 +1284,7 @@ static void nmi_test(struct svm_test *test)
>  
>  	apic_icr_write(APIC_DEST_SELF | APIC_DEST_PHYSICAL | APIC_DM_NMI | APIC_INT_ASSERT, 0);
>  
> -	if (!nmi_fired) {
> -		report(nmi_fired, "intercepted pending NMI not dispatched");
> -		set_test_stage(test, -1);
> -	}
> -
> +	report_svm_guest(nmi_fired, test, "intercepted pending NMI delivered to guest");
>  }
>  
>  static bool nmi_finished(struct svm_test *test)
> @@ -1379,11 +1361,8 @@ static void nmi_hlt_test(struct svm_test *test)
>  
>  	asm volatile ("hlt");
>  
> -	report((rdtsc() - start > NMI_DELAY) && nmi_fired,
> -	       "direct NMI + hlt");
> -
> -	if (!nmi_fired)
> -		set_test_stage(test, -1);
> +	report_svm_guest(nmi_fired, test, "direct NMI + hlt");
> +	report(rdtsc() - start > NMI_DELAY, "direct NMI after expected delay");
>  
>  	nmi_fired = false;
>  
> @@ -1395,14 +1374,8 @@ static void nmi_hlt_test(struct svm_test *test)
>  
>  	asm volatile ("hlt");
>  
> -	report((rdtsc() - start > NMI_DELAY) && nmi_fired,
> -	       "intercepted NMI + hlt");
> -
> -	if (!nmi_fired) {
> -		report(nmi_fired, "intercepted pending NMI not dispatched");
> -		set_test_stage(test, -1);
> -		vmmcall();
> -	}
> +	report_svm_guest(nmi_fired, test, "intercepted NMI + hlt");
> +	report(rdtsc() - start > NMI_DELAY, "intercepted NMI after expected delay");
>  
>  	set_test_stage(test, 3);
>  }
> @@ -1534,37 +1507,23 @@ static void virq_inject_prepare(struct svm_test *test)
>  
>  static void virq_inject_test(struct svm_test *test)
>  {
> -	if (virq_fired) {
> -		report_fail("virtual interrupt fired before L2 sti");
> -		set_test_stage(test, -1);
> -		vmmcall();
> -	}
> +	report_svm_guest(!virq_fired, test, "virtual IRQ blocked after L2 cli");
>  
>  	irq_enable();
>  	asm volatile ("nop");
>  	irq_disable();
>  
> -	if (!virq_fired) {
> -		report_fail("virtual interrupt not fired after L2 sti");
> -		set_test_stage(test, -1);
> -	}
> +	report_svm_guest(virq_fired, test, "virtual IRQ fired after L2 sti");
>  
>  	vmmcall();
>  
> -	if (virq_fired) {
> -		report_fail("virtual interrupt fired before L2 sti after VINTR intercept");
> -		set_test_stage(test, -1);
> -		vmmcall();
> -	}
> +	report_svm_guest(!virq_fired, test, "intercepted VINTR blocked after L2 cli");
>  
>  	irq_enable();
>  	asm volatile ("nop");
>  	irq_disable();
>  
> -	if (!virq_fired) {
> -		report_fail("virtual interrupt not fired after return from VINTR intercept");
> -		set_test_stage(test, -1);
> -	}
> +	report_svm_guest(virq_fired, test, "intercepted VINTR fired after L2 sti");
>  
>  	vmmcall();
>  
> @@ -1572,10 +1531,8 @@ static void virq_inject_test(struct svm_test *test)
>  	asm volatile ("nop");
>  	irq_disable();
>  
> -	if (virq_fired) {
> -		report_fail("virtual interrupt fired when V_IRQ_PRIO less than V_TPR");
> -		set_test_stage(test, -1);
> -	}
> +	report_svm_guest(!virq_fired, test,
> +			  "virtual IRQ blocked V_IRQ_PRIO less than V_TPR");
>  
>  	vmmcall();
>  	vmmcall();

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [kvm-unit-tests PATCH v4 2/2] x86: nSVM: Add support for VNMI test
  2023-04-05 20:51 ` [kvm-unit-tests PATCH v4 2/2] x86: nSVM: Add support for VNMI test Sean Christopherson
@ 2023-04-06 10:42   ` Santosh Shukla
  0 siblings, 0 replies; 7+ messages in thread
From: Santosh Shukla @ 2023-04-06 10:42 UTC (permalink / raw)
  To: Sean Christopherson, Paolo Bonzini; +Cc: kvm, Santosh Shukla

Hi Sean,

On 4/6/2023 2:21 AM, Sean Christopherson wrote:
> From: Santosh Shukla <santosh.shukla@amd.com>
> 
> Add a VNMI test case to test Virtual NMI in a nested environment,
> The test covers the Virtual NMI (VNMI) delivery.
> 
> Signed-off-by: Santosh Shukla <santosh.shukla@amd.com>
> [sean: reuse pieces of NMI test framework, fix formatting issues]
> Signed-off-by: Sean Christopherson <seanjc@google.com>

Tested on Genoa system, Test passed, Thank-you!.,

Renaming comment inline -

> ---
>  lib/x86/processor.h |  1 +
>  x86/svm.c           |  5 +++
>  x86/svm.h           |  8 +++++
>  x86/svm_tests.c     | 78 +++++++++++++++++++++++++++++++++++++++++++++
>  4 files changed, 92 insertions(+)
> 
> diff --git a/lib/x86/processor.h b/lib/x86/processor.h
> index 3d58ef72..3802c1e2 100644
> --- a/lib/x86/processor.h
> +++ b/lib/x86/processor.h
> @@ -267,6 +267,7 @@ static inline bool is_intel(void)
>  #define X86_FEATURE_PAUSEFILTER		(CPUID(0x8000000A, 0, EDX, 10))
>  #define X86_FEATURE_PFTHRESHOLD		(CPUID(0x8000000A, 0, EDX, 12))
>  #define	X86_FEATURE_VGIF		(CPUID(0x8000000A, 0, EDX, 16))
> +#define X86_FEATURE_V_NMI               (CPUID(0x8000000A, 0, EDX, 25))

s/X86_FEATURE_V_NMI/X86_FEATURE_VNMI

>  #define	X86_FEATURE_AMD_PMU_V2		(CPUID(0x80000022, 0, EAX, 0))
>  
>  static inline bool this_cpu_has(u64 feature)
> diff --git a/x86/svm.c b/x86/svm.c
> index ba435b4a..022a0fde 100644
> --- a/x86/svm.c
> +++ b/x86/svm.c
> @@ -99,6 +99,11 @@ bool npt_supported(void)
>  	return this_cpu_has(X86_FEATURE_NPT);
>  }
>  
> +bool vnmi_supported(void)
> +{
> +       return this_cpu_has(X86_FEATURE_V_NMI);

ditto..

Thanks,
Santosh

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [kvm-unit-tests PATCH v4 1/2] nSVM: Add helper to report fatal errors in guest
  2023-04-06  8:31   ` Mathias Krause
@ 2023-04-06 16:31     ` Sean Christopherson
  0 siblings, 0 replies; 7+ messages in thread
From: Sean Christopherson @ 2023-04-06 16:31 UTC (permalink / raw)
  To: Mathias Krause; +Cc: kvm, Santosh Shukla, Paolo Bonzini

On Thu, Apr 06, 2023, Mathias Krause wrote:
> On 05.04.23 22:51, Sean Christopherson wrote:
> > Add a helper macro to dedup nSVM test code that handles fatal errors
> > by reporting the failure, setting the test stage to a magic number, and
> > invoking VMMCALL to bail to the host and terminate.
> > 
> > Note, the V_TPR fails if report() is invoked.  Punt on the issue for
> > now as most users already report only failures, but leave a TODO for
> > future developers.
> > 
> > Signed-off-by: Sean Christopherson <seanjc@google.com>
> > ---
> >  x86/svm_tests.c | 127 ++++++++++++++++--------------------------------
> >  1 file changed, 42 insertions(+), 85 deletions(-)
> > 
> > diff --git a/x86/svm_tests.c b/x86/svm_tests.c
> > index 27ce47b4..e87db3fa 100644
> > --- a/x86/svm_tests.c
> > +++ b/x86/svm_tests.c
> > @@ -947,6 +947,21 @@ static bool lat_svm_insn_check(struct svm_test *test)
> >  	return true;
> >  }
> >  
> > +/*
> > + * Report failures from SVM guest code, and on failure, set the stage to -1 and
> > + * do VMMCALL to terminate the test (host side must treat -1 as "finished").
> > + * TODO: fix the tests that don't play nice with a straight report, e.g. the
> > + * V_TPR test fails if report() is invoked.
> > + */
> > +#define report_svm_guest(cond, test, fmt, args...)	\
> > +do {							\
> > +	if (!(cond)) {					\
> 
> > +		report_fail("why didn't my format '" fmt "' format?", ##args);\
>                             ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
> Debug artifact? Should probably be this instead (making use of C99):

Yes.  I'm just glad I posted the PG version and not the rated R version.

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [kvm-unit-tests PATCH v4 0/2] nSVM: vNMI testcase
  2023-04-05 20:51 [kvm-unit-tests PATCH v4 0/2] nSVM: vNMI testcase Sean Christopherson
  2023-04-05 20:51 ` [kvm-unit-tests PATCH v4 1/2] nSVM: Add helper to report fatal errors in guest Sean Christopherson
  2023-04-05 20:51 ` [kvm-unit-tests PATCH v4 2/2] x86: nSVM: Add support for VNMI test Sean Christopherson
@ 2023-06-07 23:26 ` Sean Christopherson
  2 siblings, 0 replies; 7+ messages in thread
From: Sean Christopherson @ 2023-06-07 23:26 UTC (permalink / raw)
  To: Sean Christopherson, Paolo Bonzini; +Cc: kvm, Santosh Shukla

On Wed, 05 Apr 2023 13:51:36 -0700, Sean Christopherson wrote:
> Santosh's vNMI test, plus a prep patch to dedup a pile of copy+paste code
> in the SVM test for handling fatal errors in the guest.
> 
> Santosh, can you check that I didn't break anything in the vNMI test?  I
> don't have access to the necessary hardware.
> 
> Thanks!
> 
> [...]

Applied to kvm-x86 next, with fixups for the goofs pointed out by Mathias and
Santosh.

[1/2] nSVM: Add helper to report fatal errors in guest
      https://github.com/kvm-x86/kvm-unit-tests/commit/76c60c49ebfd
[2/2] x86: nSVM: Add support for VNMI test
      https://github.com/kvm-x86/kvm-unit-tests/commit/928fec073045

--
https://github.com/kvm-x86/kvm-unit-tests/tree/next

^ permalink raw reply	[flat|nested] 7+ messages in thread

end of thread, other threads:[~2023-06-07 23:29 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2023-04-05 20:51 [kvm-unit-tests PATCH v4 0/2] nSVM: vNMI testcase Sean Christopherson
2023-04-05 20:51 ` [kvm-unit-tests PATCH v4 1/2] nSVM: Add helper to report fatal errors in guest Sean Christopherson
2023-04-06  8:31   ` Mathias Krause
2023-04-06 16:31     ` Sean Christopherson
2023-04-05 20:51 ` [kvm-unit-tests PATCH v4 2/2] x86: nSVM: Add support for VNMI test Sean Christopherson
2023-04-06 10:42   ` Santosh Shukla
2023-06-07 23:26 ` [kvm-unit-tests PATCH v4 0/2] nSVM: vNMI testcase Sean Christopherson

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).