[kvm-unit-tests PATCH v4 1/2] nSVM: Add helper to report fatal errors in guest

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



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@xxxxxxxxxx>
---
 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




[Index of Archives]     [KVM ARM]     [KVM ia64]     [KVM ppc]     [Virtualization Tools]     [Spice Development]     [Libvirt]     [Libvirt Users]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite Questions]     [Linux Kernel]     [Linux SCSI]     [XFree86]

  Powered by Linux