All of lore.kernel.org
 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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.