diff mbox series

[kvm-unit-tests,5/8] nVMX: Expose __enter_guest() and consolidate guest state test code

Message ID 20200312232745.884-6-sean.j.christopherson@intel.com (mailing list archive)
State New, archived
Headers show
Series nVMX: Clean up __enter_guest() and co. | expand

Commit Message

Sean Christopherson March 12, 2020, 11:27 p.m. UTC
Expose __enter_guest() outside of vmx.c and use it in a new wrapper for
testing guest state.  Handling both success and failure paths in a
common helper eliminates a lot of boilerplate code in the tests
themselves.

Signed-off-by: Sean Christopherson <sean.j.christopherson@intel.com>
---
 x86/vmx.c       |  12 +----
 x86/vmx.h       |   5 ++-
 x86/vmx_tests.c | 115 +++++++++++++++---------------------------------
 3 files changed, 40 insertions(+), 92 deletions(-)
diff mbox series

Patch

diff --git a/x86/vmx.c b/x86/vmx.c
index d92350d..1c837f0 100644
--- a/x86/vmx.c
+++ b/x86/vmx.c
@@ -1840,14 +1840,11 @@  static void check_for_guest_termination(void)
 	}
 }
 
-#define        ABORT_ON_EARLY_VMENTRY_FAIL     0x1
-#define        ABORT_ON_INVALID_GUEST_STATE    0x2
-
 /*
  * Enters the guest (or launches it for the first time). Error to call once the
  * guest has returned (i.e., run past the end of its guest() function).
  */
-static void __enter_guest(u8 abort_flag, struct vmentry_result *result)
+void __enter_guest(u8 abort_flag, struct vmentry_result *result)
 {
 	TEST_ASSERT_MSG(v2_guest_main,
 			"Never called test_set_guest_func!");
@@ -1905,13 +1902,6 @@  void enter_guest(void)
 		      ABORT_ON_INVALID_GUEST_STATE, &result);
 }
 
-void enter_guest_with_invalid_guest_state(void)
-{
-	struct vmentry_result result;
-
-	__enter_guest(ABORT_ON_EARLY_VMENTRY_FAIL, &result);
-}
-
 extern struct vmx_test vmx_tests[];
 
 static bool
diff --git a/x86/vmx.h b/x86/vmx.h
index c4a0fb4..73979f7 100644
--- a/x86/vmx.h
+++ b/x86/vmx.h
@@ -855,9 +855,12 @@  bool ept_huge_pages_supported(int level);
 bool ept_execute_only_supported(void);
 bool ept_ad_bits_supported(void);
 
+#define        ABORT_ON_EARLY_VMENTRY_FAIL     0x1
+#define        ABORT_ON_INVALID_GUEST_STATE    0x2
+
+void __enter_guest(u8 abort_flag, struct vmentry_result *result);
 void enter_guest(void);
 void enter_guest_with_bad_controls(void);
-void enter_guest_with_invalid_guest_state(void);
 
 typedef void (*test_guest_func)(void);
 typedef void (*test_teardown_func)(void *data);
diff --git a/x86/vmx_tests.c b/x86/vmx_tests.c
index ac02b9d..5befcd3 100644
--- a/x86/vmx_tests.c
+++ b/x86/vmx_tests.c
@@ -5239,23 +5239,25 @@  static void guest_state_test_main(void)
 	asm volatile("fnop");
 }
 
-static void advance_guest_state_test(void)
+static void test_guest_state(const char *test, bool xfail, u64 field,
+			     const char * field_name)
 {
-	u32 reason = vmcs_read(EXI_REASON);
-	if (! (reason & 0x80000000)) {
-		u64 guest_rip = vmcs_read(GUEST_RIP);
-		u32 insn_len = vmcs_read(EXI_INST_LEN);
-		vmcs_write(GUEST_RIP, guest_rip + insn_len);
-	}
-}
+	struct vmentry_result result;
+	u8 abort_flags;
 
-static void report_guest_state_test(const char *test, u32 xreason,
-				    u64 field, const char * field_name)
-{
-	u32 reason = vmcs_read(EXI_REASON);
+	abort_flags = ABORT_ON_EARLY_VMENTRY_FAIL;
+	if (!xfail)
+		abort_flags = ABORT_ON_INVALID_GUEST_STATE;
+
+	__enter_guest(abort_flags, &result);
+
+	report(result.exit_reason.failed_vmentry == xfail &&
+	       ((xfail && result.exit_reason.basic == VMX_FAIL_STATE) ||
+	        (!xfail && result.exit_reason.basic == VMX_VMCALL)),
+	        "%s, %s %lx", test, field_name, field);
 
-	report(reason == xreason, "%s, %s %lx", test, field_name, field);
-	advance_guest_state_test();
+	if (!result.exit_reason.failed_vmentry)
+		skip_exit_insn();
 }
 
 /*
@@ -6911,16 +6913,7 @@  static void test_efer_vmlaunch(u32 fld, bool ok)
 		else
 			test_vmx_vmlaunch(VMXERR_ENTRY_INVALID_HOST_STATE_FIELD);
 	} else {
-		if (ok) {
-			enter_guest();
-			report(vmcs_read(EXI_REASON) == VMX_VMCALL,
-			       "vmlaunch succeeds");
-		} else {
-			enter_guest_with_invalid_guest_state();
-			report(vmcs_read(EXI_REASON) == (VMX_ENTRY_FAILURE | VMX_FAIL_STATE),
-			       "vmlaunch fails");
-		}
-		advance_guest_state_test();
+		test_guest_state("EFER test", !ok, GUEST_EFER, "GUEST_EFER");
 	}
 }
 
@@ -7124,10 +7117,8 @@  static void test_pat(u32 field, const char * field_name, u32 ctrl_field,
 				report_prefix_pop();
 
 			} else {	// GUEST_PAT
-				enter_guest();
-				report_guest_state_test("ENT_LOAD_PAT enabled",
-							VMX_VMCALL, val,
-							"GUEST_PAT");
+				test_guest_state("ENT_LOAD_PAT enabled", false,
+						 val, "GUEST_PAT");
 			}
 		}
 	}
@@ -7151,21 +7142,9 @@  static void test_pat(u32 field, const char * field_name, u32 ctrl_field,
 				report_prefix_pop();
 
 			} else {	// GUEST_PAT
-				if (i == 0x2 || i == 0x3 || i >= 0x8) {
-					enter_guest_with_invalid_guest_state();
-					report_guest_state_test("ENT_LOAD_PAT "
-							        "enabled",
-							        VMX_FAIL_STATE | VMX_ENTRY_FAILURE,
-							        val,
-							        "GUEST_PAT");
-				} else {
-					enter_guest();
-					report_guest_state_test("ENT_LOAD_PAT "
-							        "enabled",
-							        VMX_VMCALL,
-							        val,
-							        "GUEST_PAT");
-				}
+				error = (i == 0x2 || i == 0x3 || i >= 0x8);
+				test_guest_state("ENT_LOAD_PAT enabled", !!error,
+						 val, "GUEST_PAT");
 			}
 
 		}
@@ -7254,14 +7233,9 @@  static void test_pgc_vmlaunch(u32 xerror, u32 xreason, bool xfail, bool host)
 			report(success != xfail, "vmlaunch succeeded");
 		}
 	} else {
-		if (xfail) {
-			enter_guest_with_invalid_guest_state();
-		} else {
-			enter_guest();
-		}
-		report_guest_state_test("load GUEST_PERF_GLOBAL_CTRL",
-					xreason, GUEST_PERF_GLOBAL_CTRL,
-					"GUEST_PERF_GLOBAL_CTRL");
+		test_guest_state("load GUEST_PERF_GLOBAL_CTRL", xfail,
+				 GUEST_PERF_GLOBAL_CTRL,
+				 "GUEST_PERF_GLOBAL_CTRL");
 	}
 }
 
@@ -7422,10 +7396,8 @@  static void test_canonical(u64 field, const char * field_name, bool host)
 			test_vmx_vmlaunch(0);
 			report_prefix_pop();
 		} else {
-			enter_guest();
-			report_guest_state_test("Test canonical address",
-						VMX_VMCALL, addr_saved,
-						field_name);
+			test_guest_state("Test canonical address", false,
+					 addr_saved, field_name);
 		}
 	}
 
@@ -7436,10 +7408,8 @@  static void test_canonical(u64 field, const char * field_name, bool host)
 		test_vmx_vmlaunch(VMXERR_ENTRY_INVALID_HOST_STATE_FIELD);
 		report_prefix_pop();
 	} else {
-		enter_guest_with_invalid_guest_state();
-		report_guest_state_test("Test non-canonical address",
-					VMX_FAIL_STATE | VMX_ENTRY_FAILURE,
-					NONCANONICAL, field_name);
+		test_guest_state("Test non-canonical address", true,
+				 NONCANONICAL, field_name);
 	}
 
 	vmcs_write(field, addr_saved);
@@ -7626,9 +7596,8 @@  static void test_guest_dr7(void)
 		for (i = 0; i < 64; i++) {
 			val = 1ull << i;
 			vmcs_write(GUEST_DR7, val);
-			enter_guest();
-			report_guest_state_test("ENT_LOAD_DBGCTLS disabled",
-						VMX_VMCALL, val, "GUEST_DR7");
+			test_guest_state("ENT_LOAD_DBGCTLS disabled", false,
+					 val, "GUEST_DR7");
 		}
 	}
 	if (ctrl_enter_rev.clr & ENT_LOAD_DBGCTLS) {
@@ -7636,15 +7605,8 @@  static void test_guest_dr7(void)
 		for (i = 0; i < 64; i++) {
 			val = 1ull << i;
 			vmcs_write(GUEST_DR7, val);
-			if (i < 32)
-				enter_guest();
-			else
-				enter_guest_with_invalid_guest_state();
-			report_guest_state_test("ENT_LOAD_DBGCTLS enabled",
-						i < 32 ? VMX_VMCALL :
-						VMX_ENTRY_FAILURE |
-						VMX_FAIL_STATE,
-						val, "GUEST_DR7");
+			test_guest_state("ENT_LOAD_DBGCTLS enabled", i >= 32,
+					 val, "GUEST_DR7");
 		}
 	}
 	vmcs_write(GUEST_DR7, dr7_saved);
@@ -9516,17 +9478,10 @@  static void atomic_switch_msrs_test(int count)
 		assert_exit_reason(VMX_VMCALL);
 		skip_exit_vmcall();
 	} else {
-		u32 exit_reason;
-		u32 exit_reason_want;
 		u32 exit_qual;
 
-		enter_guest_with_invalid_guest_state();
-
-		exit_reason = vmcs_read(EXI_REASON);
-		exit_reason_want = VMX_FAIL_MSR | VMX_ENTRY_FAILURE;
-		report(exit_reason == exit_reason_want,
-		       "exit_reason, %u, is %u.", exit_reason,
-		       exit_reason_want);
+		test_guest_state("Invalid MSR Load Count", true, count,
+				 "ENT_MSR_LD_CNT");
 
 		exit_qual = vmcs_read(EXI_QUALIFICATION);
 		report(exit_qual == max_allowed + 1, "exit_qual, %u, is %u.",