According to section "Checks on Guest Control Registers, Debug Registers, and and MSRs" in Intel SDM vol 3C, the following checks are performed on vmentry of nested guests: If the "load debug controls" VM-entry control is 1, - bits reserved in the IA32_DEBUGCTL MSR must be 0 in the field for that register. The first processors to support the virtual-machine extensions supported only the 1-setting of this control and thus performed this check unconditionally. - bits 63:32 in the DR7 field must be 0. Signed-off-by: Krish Sadhukhan <krish.sadhukhan@xxxxxxxxxx> Reviewed-by: Karl Heubaum <karl.heubaum@xxxxxxxxxx> --- x86/vmx_tests.c | 59 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 59 insertions(+) diff --git a/x86/vmx_tests.c b/x86/vmx_tests.c index 8ad2674..0207caf 100644 --- a/x86/vmx_tests.c +++ b/x86/vmx_tests.c @@ -7154,6 +7154,64 @@ static void test_load_guest_pat(void) test_pat(GUEST_PAT, "GUEST_PAT", ENT_CONTROLS, ENT_LOAD_PAT); } +/* + * If the “load debug controls” VM-entry control is 1, + * + * - bits reserved in the IA32_DEBUGCTL MSR must be 0 in the field for + * that register. + * - bits 63:32 in the DR7 field must be 0. + */ +static void test_debugctl(void) +{ + u64 debugctl_saved = vmcs_read(GUEST_DEBUGCTL); + u32 entry_ctl_saved = vmcs_read(ENT_CONTROLS); + u64 tmp; + int i; + u64 dr7_saved = vmcs_read(GUEST_DR7); + + if (!(ctrl_exit_rev.clr & ENT_LOAD_DBGCTLS)) { + printf("\"IA32_DEBUGCTL\" VM-entry control not supported\n"); + return; + } + + vmx_set_test_stage(1); + test_set_guest(guest_state_test_main); + +#define DEBUGCTL_RESERVED_BITS 0xFFFFFFFFFFFF203C + + if (!(entry_ctl_saved & ENT_LOAD_DBGCTLS)) + vmcs_write(ENT_CONTROLS, entry_ctl_saved | ENT_LOAD_DBGCTLS); + + for (i = 2; i < 32; (i >= 16 ? i = i + 4 : i++)) { + if (!((1 << i) & DEBUGCTL_RESERVED_BITS)) + continue; + tmp = debugctl_saved | (1 << i); + vmcs_write(GUEST_DEBUGCTL, tmp); + enter_guest_with_invalid_guest_state(); + report_guest_state_test("ENT_LOAD_DBGCTLS enabled", + VMX_FAIL_STATE | VMX_ENTRY_FAILURE, + tmp, "GUEST_DEBUGCTL"); + } + + for (i = 32; i < 64; i = i + 4) { + tmp = dr7_saved | (1ull << i); + vmcs_write(GUEST_DR7, tmp); + enter_guest_with_invalid_guest_state(); + report_guest_state_test("ENT_LOAD_DBGCTLS enabled", + VMX_FAIL_STATE | VMX_ENTRY_FAILURE, + tmp, "GUEST_DR7"); + } + + /* + * Let the guest finish execution + */ + vmx_set_test_stage(2); + vmcs_write(GUEST_DEBUGCTL, debugctl_saved); + vmcs_write(ENT_CONTROLS, entry_ctl_saved); + vmcs_write(GUEST_DR7, dr7_saved); + enter_guest(); +} + /* * Check that the virtual CPU checks the VMX Guest State Area as * documented in the Intel SDM. @@ -7161,6 +7219,7 @@ static void test_load_guest_pat(void) static void vmx_guest_state_area_test(void) { test_load_guest_pat(); + test_debugctl(); } static bool valid_vmcs_for_vmentry(void) -- 2.20.1