According to section "Checks Related to Address-Space Size" in Intel SDM vol 3C, the following checks are performed on vmentry of nested guests: If the "host address-space size" VM-exit control is 0, the following must hold: - The "IA-32e mode guest" VM-entry control is 0. - Bit 17 of the CR4 field (corresponding to CR4.PCIDE) is 0. - Bits 63:32 in the RIP field are 0. If the "host address-space size" VM-exit control is 1, the following must hold: - Bit 5 of the CR4 field (corresponding to CR4.PAE) is 1. - The RIP field contains a canonical address. Signed-off-by: Krish Sadhukhan <krish.sadhukhan@xxxxxxxxxx> Reviewed-by: Karl Heubaum <karl.heubaum@xxxxxxxxxx> --- x86/vmx_tests.c | 63 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 63 insertions(+) diff --git a/x86/vmx_tests.c b/x86/vmx_tests.c index 8ad2674..fae00d3 100644 --- a/x86/vmx_tests.c +++ b/x86/vmx_tests.c @@ -7108,6 +7108,68 @@ static void test_host_desc_tables(void) #endif } +/* + * If the "host address-space size" VM-exit control is 0, the following must + * hold: + * - The "IA-32e mode guest" VM-entry control is 0. + * - Bit 17 of the CR4 field (corresponding to CR4.PCIDE) is 0. + * - Bits 63:32 in the RIP field are 0. + * + * If the "host address-space size" VM-exit control is 1, the following must + * hold: + * - Bit 5 of the CR4 field (corresponding to CR4.PAE) is 1. + * - The RIP field contains a canonical address. + * + */ +static void test_host_addr_size(void) +{ + u64 cr4_saved = vmcs_read(HOST_CR4); + u64 rip_saved = vmcs_read(HOST_RIP); + u64 entry_ctrl_saved = vmcs_read(ENT_CONTROLS); + int i; + u64 tmp; + + if (vmcs_read(EXI_CONTROLS) & EXI_HOST_64) { + vmcs_write(ENT_CONTROLS, entry_ctrl_saved | ENT_GUEST_64); + report_prefix_pushf("\"IA-32e mode guest\" enabled"); + test_vmx_vmlaunch(0, false); + report_prefix_pop(); + + vmcs_write(HOST_CR4, cr4_saved | X86_CR4_PCIDE); + report_prefix_pushf("\"CR4.PCIDE\" set"); + test_vmx_vmlaunch(0, false); + report_prefix_pop(); + + for (i = 32; i <= 63; i = i + 4) { + tmp = rip_saved | 1ull << i; + vmcs_write(HOST_RIP, tmp); + report_prefix_pushf("HOST_RIP %lx", tmp); + test_vmx_vmlaunch(0, false); + report_prefix_pop(); + } + + if (cr4_saved & X86_CR4_PAE) { + vmcs_write(HOST_CR4, cr4_saved & ~X86_CR4_PAE); + report_prefix_pushf("\"CR4.PAE\" unset"); + test_vmx_vmlaunch( + VMXERR_ENTRY_INVALID_HOST_STATE_FIELD, false); + } else { + report_prefix_pushf("\"CR4.PAE\" set"); + test_vmx_vmlaunch(0, false); + } + report_prefix_pop(); + + vmcs_write(HOST_RIP, NONCANONICAL); + report_prefix_pushf("HOST_RIP %llx", NONCANONICAL); + test_vmx_vmlaunch(VMXERR_ENTRY_INVALID_HOST_STATE_FIELD, false); + report_prefix_pop(); + + vmcs_write(ENT_CONTROLS, entry_ctrl_saved | ENT_GUEST_64); + vmcs_write(HOST_RIP, rip_saved); + vmcs_write(HOST_CR4, cr4_saved); + } +} + /* * Check that the virtual CPU checks the VMX Host State Area as * documented in the Intel SDM. @@ -7130,6 +7192,7 @@ static void vmx_host_state_area_test(void) test_load_host_pat(); test_host_segment_regs(); test_host_desc_tables(); + test_host_addr_size(); } /* -- 2.20.1