Message ID | 20190829205635.20189-5-krish.sadhukhan@oracle.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Series | KVM: nVMX: Check GUEST_DEBUGCTL and GUEST_DR7 on vmentry of nested guests | expand |
On Thu, Aug 29, 2019 at 2:30 PM Krish Sadhukhan <krish.sadhukhan@oracle.com> wrote: > > 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@oracle.com> > Reviewed-by: Karl Heubaum <karl.heubaum@oracle.com> > --- > ... > +#define DEBUGCTL_RESERVED_BITS 0xFFFFFFFFFFFF203C For the virtual CPU implemented by kvm today, only bits 0 and 1 are allowed.
> On Aug 29, 2019, at 4:17 PM, Jim Mattson <jmattson@google.com> wrote: > > On Thu, Aug 29, 2019 at 2:30 PM Krish Sadhukhan > <krish.sadhukhan@oracle.com> wrote: >> 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@oracle.com> >> Reviewed-by: Karl Heubaum <karl.heubaum@oracle.com> >> --- >> ... >> +#define DEBUGCTL_RESERVED_BITS 0xFFFFFFFFFFFF203C > > For the virtual CPU implemented by kvm today, only bits 0 and 1 are allowed. Please build the tests so they would pass on bare-metal.
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)