[PATCH 4/4 v2][kvm-unit-test nVMX]: Test HOST_SYSENTER_ESP and HOST_SYSENTER_EIP fields on vmentry of L2 guests

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

 



According to section "Checks on VMX Controls" in Intel SDM vol 3C, the
following check is performed on vmentry of L2 guests:

    On processors that support Intel 64 architecture, the IA32_SYSENTER_ESP
    field and the IA32_SYSENTER_EIP field must each contain a canonical
    address.

Signed-off-by: Krish Sadhukhan <krish.sadhukhan@xxxxxxxxxx>
Reviewed-by: Mihai Carabas <mihai.carabas@xxxxxxxxxx>
---
 x86/unittests.cfg |  6 ++++
 x86/vmx_tests.c   | 75 +++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 81 insertions(+)

diff --git a/x86/unittests.cfg b/x86/unittests.cfg
index d7975e9..580dd8c 100644
--- a/x86/unittests.cfg
+++ b/x86/unittests.cfg
@@ -542,6 +542,12 @@ extra_params = -cpu host,+vmx -m 2560 -append vmx_controls_test
 arch = x86_64
 groups = vmx
 
+[vmx_host_state_area]
+file = vmx.flat
+extra_params = -cpu host,+vmx -m 2560 -append vmx_host_state_area_test
+arch = x86_64
+groups = vmx
+
 [vmx_vmentry_movss_shadow_test]
 file = vmx.flat
 extra_params = -cpu host,+vmx -m 2560 -append vmentry_movss_shadow_test
diff --git a/x86/vmx_tests.c b/x86/vmx_tests.c
index b69a7d9..487eb6f 100644
--- a/x86/vmx_tests.c
+++ b/x86/vmx_tests.c
@@ -4935,6 +4935,80 @@ static void vmx_controls_test(void)
 	test_vm_entry_ctls();
 }
 
+/*
+ * On processors that support Intel 64 architecture, the IA32_SYSENTER_ESP
+ * field and the IA32_SYSENTER_EIP field must each contain a canonical
+ * address.
+ *
+ *  [Intel SDM]
+ */
+static void test_host_ctl_regs(void)
+{
+	u64 addr_saved = vmcs_read(HOST_SYSENTER_ESP);
+	u64 addr = addr_saved;
+
+	if (!is_canonical(addr)) {
+		report_prefix_pushf("HOST_SYSENTER_ESP non-canonical");
+		test_vmlaunch(false, false,
+				VMXERR_ENTRY_INVALID_HOST_STATE_FIELD);
+		report_prefix_pop();
+	} else {
+		report_prefix_pushf("HOST_SYSENTER_ESP canonical");
+		test_vmlaunch(true, false,
+				VMXERR_ENTRY_INVALID_HOST_STATE_FIELD);
+		report_prefix_pop();
+
+		addr |= 1ull << 48;
+		vmcs_write(HOST_SYSENTER_ESP, addr);
+		report_prefix_pushf("HOST_SYSENTER_ESP non-canonical");
+		test_vmlaunch(false, false,
+				VMXERR_ENTRY_INVALID_HOST_STATE_FIELD);
+		report_prefix_pop();
+
+		vmcs_write(HOST_SYSENTER_ESP, addr_saved);
+	}
+
+	addr_saved = vmcs_read(HOST_SYSENTER_EIP);
+	addr = addr_saved;
+
+	if (!is_canonical(addr)) {
+		report_prefix_pushf("HOST_SYSENTER_EIP non-canonical");
+		test_vmlaunch(false, false,
+				VMXERR_ENTRY_INVALID_HOST_STATE_FIELD);
+		report_prefix_pop();
+	} else {
+		report_prefix_pushf("HOST_SYSENTER_EIP canonical");
+		test_vmlaunch(true, false,
+				VMXERR_ENTRY_INVALID_HOST_STATE_FIELD);
+		report_prefix_pop();
+
+		addr |= 1ull << 48;
+		vmcs_write(HOST_SYSENTER_EIP, addr);
+		report_prefix_pushf("HOST_SYSENTER_EIP non-canonical");
+		test_vmlaunch(false, false,
+				VMXERR_ENTRY_INVALID_HOST_STATE_FIELD);
+		report_prefix_pop();
+
+		vmcs_write(HOST_SYSENTER_EIP, addr_saved);
+	}
+}
+
+/*
+ * Check that the virtual CPU checks the VMX Host State Area as
+ * documented in the Intel SDM.
+ */
+static void vmx_host_state_area_test(void)
+{
+	/*
+	 * Bit 1 of the guest's RFLAGS must be 1, or VM-entry will
+	 * fail due to invalid guest state, should we make it that
+	 * far.
+	 */
+	vmcs_write(GUEST_RFLAGS, 0);
+
+	test_host_ctl_regs();
+}
+
 static bool valid_vmcs_for_vmentry(void)
 {
 	struct vmcs *current_vmcs = NULL;
@@ -6356,6 +6430,7 @@ struct vmx_test vmx_tests[] = {
 	TEST(invvpid_test_v2),
 	/* VM-entry tests */
 	TEST(vmx_controls_test),
+	TEST(vmx_host_state_area_test),
 	TEST(vmentry_movss_shadow_test),
 	/* APICv tests */
 	TEST(vmx_eoi_bitmap_ioapic_scan_test),
-- 
2.17.2




[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