Introduce a new test for mode-based execute control (MBEC) in the VMX controls, validating the dependency between MBEC and EPT VM-execution controls. The test ensures that VM entry fails when MBEC is enabled without EPT, and succeeds in valid combinations. Update the unit test configuration to include a specific test case for MBEC on Skylake-Server CPU model, as that was the first CPU series to have MBEC. Tested on Intel SPR Gold 5416S. Passing test result Test suite: vmx_controls_test_mbec PASS: MBEC disabled, EPT disabled (valid combination): vmlaunch succeeds PASS: MBEC enabled, EPT disabled (invalid combination): vmlaunch fails PASS: MBEC enabled, EPT disabled (invalid combination): VMX inst error is 7 (actual 7) PASS: MBEC enabled, EPT enabled (valid combination): vmlaunch succeeds PASS: MBEC disabled, EPT enabled (valid combination): vmlaunch succeeds Test ran with "-vmx-mbec": Test suite: vmx_controls_test_mbec SKIP: test_mode_based_execute_control : "Secondary execution" or "enable EPT" or "enable mode-based execute control" control not supported Note, all other tests pass (including EPT with MBEC enabled and disabled) with MBEC v1 series. Signed-off-by: Jon Kohler --- x86/unittests.cfg | 9 ++++++ x86/vmx.h | 8 +++++ x86/vmx_tests.c | 76 +++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 93 insertions(+) diff --git a/x86/unittests.cfg b/x86/unittests.cfg index 522318d3..b82bbc4e 100644 --- a/x86/unittests.cfg +++ b/x86/unittests.cfg @@ -324,6 +324,15 @@ qemu_params = -cpu max,+vmx arch = x86_64 groups = vmx +# VMX controls is a generic test; however, mode-based execute control +# aka MBEC is only available on Skylake and above, be specific about +# the CPU model and test it directly. +[vmx_controls_test_mbec] +file = vmx.flat +extra_params = -cpu Skylake-Server,+vmx,+vmx-mbec -append "vmx_controls_test_mbec" +arch = x86_64 +groups = vmx + [ept] file = vmx.flat test_args = "ept_access*" diff --git a/x86/vmx.h b/x86/vmx.h index 33373bd1..75667ccc 100644 --- a/x86/vmx.h +++ b/x86/vmx.h @@ -510,6 +510,7 @@ enum Ctrl1 { CPU_SHADOW_VMCS = 1ul << 14, CPU_RDSEED = 1ul << 16, CPU_PML = 1ul << 17, + CPU_MODE_BASED_EPT_EXEC = 1ul << 22, CPU_USE_TSC_SCALING = 1ul << 25, }; @@ -842,6 +843,13 @@ static inline bool is_invvpid_type_supported(unsigned long type) return ept_vpid.val & (VPID_CAP_INVVPID_ADDR << (type - INVVPID_ADDR)); } +static inline bool is_mbec_supported(void) +{ + return (ctrl_cpu_rev[0].clr & CPU_SECONDARY) && + (ctrl_cpu_rev[1].clr & CPU_EPT) && + (ctrl_cpu_rev[1].clr & CPU_MODE_BASED_EPT_EXEC); +} + extern u64 *bsp_vmxon_region; extern bool launched; diff --git a/x86/vmx_tests.c b/x86/vmx_tests.c index 5ffb80a3..ad7cfe83 100644 --- a/x86/vmx_tests.c +++ b/x86/vmx_tests.c @@ -4867,6 +4867,69 @@ skip_unrestricted_guest: vmcs_write(EPTP, eptp_saved); } +/* + * Test the dependency between mode-based execute control for EPT (MBEC) and + * enable EPT VM-execution controls. + * + * When MBEC (bit 22 of secondary processor-based VM-execution controls) is enabled, + * it allows separate execute permissions for supervisor-mode and user-mode linear + * addresses in EPT paging structures. However, per Intel SDM requirement: + * + * "If the 'mode-based execute control for EPT' VM-execution control is 1, + * the 'enable EPT' VM-execution control must also be 1." + * + * This test validates that VM entry fails when MBEC is enabled without EPT, + * and succeeds in all other valid combinations. + * + * [Intel SDM Vol. 3C, Section 26.6.2, Table 26-7] + */ +static void test_mode_based_execute_control(void) +{ + u32 primary_saved = vmcs_read(CPU_EXEC_CTRL0); + u32 secondary_saved = vmcs_read(CPU_EXEC_CTRL1); + u32 primary = primary_saved; + u32 secondary = secondary_saved; + + /* Skip test if required VM-execution controls are not supported */ + if (!is_mbec_supported()) { + report_skip("MBEC not supported"); + return; + } + + /* Test case 1: MBEC disabled, EPT disabled - should be valid */ + primary |= CPU_SECONDARY; + vmcs_write(CPU_EXEC_CTRL0, primary); + secondary &= ~(CPU_MODE_BASED_EPT_EXEC | CPU_EPT); + vmcs_write(CPU_EXEC_CTRL1, secondary); + report_prefix_pushf("MBEC disabled, EPT disabled (valid combination)"); + test_vmx_valid_controls(); + report_prefix_pop(); + + /* Test case 2: MBEC enabled, EPT disabled - should be invalid per SDM */ + secondary |= CPU_MODE_BASED_EPT_EXEC; + vmcs_write(CPU_EXEC_CTRL1, secondary); + report_prefix_pushf("MBEC enabled, EPT disabled (invalid combination)"); + test_vmx_invalid_controls(); + report_prefix_pop(); + + /* Test case 3: MBEC enabled, EPT enabled - should be valid */ + secondary |= CPU_EPT; + setup_dummy_ept(); + report_prefix_pushf("MBEC enabled, EPT enabled (valid combination)"); + test_vmx_valid_controls(); + report_prefix_pop(); + + /* Test case 4: MBEC disabled, EPT enabled - should be valid */ + secondary &= ~CPU_MODE_BASED_EPT_EXEC; + vmcs_write(CPU_EXEC_CTRL1, secondary); + report_prefix_pushf("MBEC disabled, EPT enabled (valid combination)"); + test_vmx_valid_controls(); + report_prefix_pop(); + + vmcs_write(CPU_EXEC_CTRL0, primary_saved); + vmcs_write(CPU_EXEC_CTRL1, secondary_saved); +} + /* * If the 'enable PML' VM-execution control is 1, the 'enable EPT' * VM-execution control must also be 1. In addition, the PML address @@ -5327,6 +5390,7 @@ static void test_vm_execution_ctls(void) test_pml(); test_vpid(); test_ept_eptp(); + test_mode_based_execute_control(); test_vmx_preemption_timer(); } @@ -5551,6 +5615,17 @@ static void vmx_controls_test(void) test_vm_entry_ctls(); } +/* + * Check that Intel MBEC controls function properly, which is a + * Skylake and above feature, and is not supported on older CPUs. + */ +static void vmx_controls_test_mbec(void) +{ + vmcs_write(GUEST_RFLAGS, 0); + + test_mode_based_execute_control(); +} + struct apic_reg_virt_config { bool apic_register_virtualization; bool use_tpr_shadow; @@ -11506,6 +11581,7 @@ struct vmx_test vmx_tests[] = { TEST(invvpid_test), /* VM-entry tests */ TEST(vmx_controls_test), + TEST(vmx_controls_test_mbec), TEST(vmx_host_state_area_test), TEST(vmx_guest_state_area_test), TEST(vmentry_movss_shadow_test), -- 2.43.0