[kvm-unit-tests PATCH v3 3/9] nVMX: Move #OF test to generic exceptions test

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

 



Move the INTO=>#OF test, along with its more precise checking of the
exit interrupt info, to the generic nVMX exceptions test.

Move the  helper that generates #OF to processor.h so that it can be
reused by nSVM for an identical test.

Note, this effectively adds new checks for all other vectors, i.e.
affects more vectors than just #OF.

Signed-off-by: Sean Christopherson <seanjc@xxxxxxxxxx>
---
 lib/x86/processor.h | 35 +++++++++++++++++++++++
 x86/vmx_tests.c     | 67 +++++++++------------------------------------
 2 files changed, 48 insertions(+), 54 deletions(-)

diff --git a/lib/x86/processor.h b/lib/x86/processor.h
index c3d112f..5865933 100644
--- a/lib/x86/processor.h
+++ b/lib/x86/processor.h
@@ -834,6 +834,41 @@ static inline uint64_t generate_usermode_ac(void)
 	return 0;
 }
 
+/*
+ * Switch from 64-bit to 32-bit mode and generate #OF via INTO.  Note, if RIP
+ * or RSP holds a 64-bit value, this helper will NOT generate #OF.
+ */
+static inline void generate_of(void)
+{
+	struct far_pointer32 fp = {
+		.offset = (uintptr_t)&&into,
+		.selector = KERNEL_CS32,
+	};
+	uintptr_t rsp;
+
+	asm volatile ("mov %%rsp, %0" : "=r"(rsp));
+
+	if (fp.offset != (uintptr_t)&&into) {
+		printf("Code address too high.\n");
+		return;
+	}
+	if ((u32)rsp != rsp) {
+		printf("Stack address too high.\n");
+		return;
+	}
+
+	asm goto ("lcall *%0" : : "m" (fp) : "rax" : into);
+	return;
+into:
+	asm volatile (".code32;"
+		      "movl $0x7fffffff, %eax;"
+		      "addl %eax, %eax;"
+		      "into;"
+		      "lret;"
+		      ".code64");
+	__builtin_unreachable();
+}
+
 static inline u8 pmu_version(void)
 {
 	return cpuid(10).a & 0xff;
diff --git a/x86/vmx_tests.c b/x86/vmx_tests.c
index 2ed20ec..edb8062 100644
--- a/x86/vmx_tests.c
+++ b/x86/vmx_tests.c
@@ -2161,57 +2161,6 @@ static int int3_exit_handler(union exit_reason exit_reason)
 	return VMX_TEST_VMEXIT;
 }
 
-static int into_init(struct vmcs *vmcs)
-{
-	vmcs_write(EXC_BITMAP, ~0u);
-	return VMX_TEST_START;
-}
-
-static void into_guest_main(void)
-{
-	struct far_pointer32 fp = {
-		.offset = (uintptr_t)&&into,
-		.selector = KERNEL_CS32,
-	};
-	uintptr_t rsp;
-
-	asm volatile ("mov %%rsp, %0" : "=r"(rsp));
-
-	if (fp.offset != (uintptr_t)&&into) {
-		printf("Code address too high.\n");
-		return;
-	}
-	if ((u32)rsp != rsp) {
-		printf("Stack address too high.\n");
-		return;
-	}
-
-	asm goto ("lcall *%0" : : "m" (fp) : "rax" : into);
-	return;
-into:
-	asm volatile (".code32;"
-		      "movl $0x7fffffff, %eax;"
-		      "addl %eax, %eax;"
-		      "into;"
-		      "lret;"
-		      ".code64");
-	__builtin_unreachable();
-}
-
-static int into_exit_handler(union exit_reason exit_reason)
-{
-	u32 intr_info = vmcs_read(EXI_INTR_INFO);
-
-	report(exit_reason.basic == VMX_EXC_NMI &&
-	       (intr_info & INTR_INFO_VALID_MASK) &&
-	       (intr_info & INTR_INFO_VECTOR_MASK) == OF_VECTOR &&
-	       ((intr_info & INTR_INFO_INTR_TYPE_MASK) >>
-	        INTR_INFO_INTR_TYPE_SHIFT) == VMX_INTR_TYPE_SOFT_EXCEPTION,
-	       "L1 intercepts #OF");
-
-	return VMX_TEST_VMEXIT;
-}
-
 static void exit_monitor_from_l2_main(void)
 {
 	printf("Calling exit(0) from l2...\n");
@@ -10741,6 +10690,7 @@ struct vmx_exception_test vmx_exception_tests[] = {
 	{ DB_VECTOR, generate_single_step_db },
 	{ BP_VECTOR, generate_bp },
 	{ AC_VECTOR, vmx_l2_ac_test },
+	{ OF_VECTOR, generate_of },
 };
 
 static u8 vmx_exception_test_vector;
@@ -10769,14 +10719,24 @@ static void handle_exception_in_l2(u8 vector)
 static void handle_exception_in_l1(u32 vector)
 {
 	u32 old_eb = vmcs_read(EXC_BITMAP);
+	u32 intr_type;
+	u32 intr_info;
 
 	vmcs_write(EXC_BITMAP, old_eb | (1u << vector));
 
 	enter_guest();
 
+	if (vector == BP_VECTOR || vector == OF_VECTOR)
+		intr_type = VMX_INTR_TYPE_SOFT_EXCEPTION;
+	else
+		intr_type = VMX_INTR_TYPE_HARD_EXCEPTION;
+
+	intr_info = vmcs_read(EXI_INTR_INFO);
 	report((vmcs_read(EXI_REASON) == VMX_EXC_NMI) &&
-	       ((vmcs_read(EXI_INTR_INFO) & 0xff) == vector),
-	       "%s handled by L1", exception_mnemonic(vector));
+	       (intr_info & INTR_INFO_VALID_MASK) &&
+	       (intr_info & INTR_INFO_VECTOR_MASK) == vector &&
+	       ((intr_info & INTR_INFO_INTR_TYPE_MASK) >> INTR_INFO_INTR_TYPE_SHIFT) == intr_type,
+	       "%s correctly routed to L1", exception_mnemonic(vector));
 
 	vmcs_write(EXC_BITMAP, old_eb);
 }
@@ -10836,7 +10796,6 @@ struct vmx_test vmx_tests[] = {
 	{ "disable RDTSCP", disable_rdtscp_init, disable_rdtscp_main,
 		disable_rdtscp_exit_handler, NULL, {0} },
 	{ "int3", int3_init, int3_guest_main, int3_exit_handler, NULL, {0} },
-	{ "into", into_init, into_guest_main, into_exit_handler, NULL, {0} },
 	{ "exit_monitor_from_l2_test", NULL, exit_monitor_from_l2_main,
 		exit_monitor_from_l2_handler, NULL, {0} },
 	{ "invalid_msr", invalid_msr_init, invalid_msr_main,
-- 
2.38.0.rc1.362.ged0d419d3c-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