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