Message ID | 20200921081027.23047-4-krish.sadhukhan@oracle.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Series | kvm-unit-test: nVMX: Test Selector and Base Address fields of Guest Segment registers | expand |
On Mon, Sep 21, 2020 at 08:10:27AM +0000, Krish Sadhukhan wrote: > According to section "UNRESTRICTED GUESTS" in SDM vol 3c, if the > "unrestricted guest" secondary VM-execution control is set, guests can run > in unpaged protected mode or in real mode. This patch tests vmetnry of an > unrestricted guest in unpaged protected mode. > > Signed-off-by: Jim Mattson <jmattson@google.com> > Signed-off-by: Krish Sadhukhan <krish.sadhukhan@oracle.com> SOB chain is wrong. Missing a Co-developed-by? Or is Jim supposed to be the author? > --- > x86/vmx.c | 2 +- > x86/vmx.h | 1 + > x86/vmx_tests.c | 48 ++++++++++++++++++++++++++++++++++++++++++++++++ > 3 files changed, 50 insertions(+), 1 deletion(-) > > diff --git a/x86/vmx.c b/x86/vmx.c > index 07415b4..1a84a74 100644 > --- a/x86/vmx.c > +++ b/x86/vmx.c > @@ -1699,7 +1699,7 @@ static void test_vmx_caps(void) > } > > /* This function can only be called in guest */ > -static void __attribute__((__used__)) hypercall(u32 hypercall_no) > +void __attribute__((__used__)) hypercall(u32 hypercall_no) > { > u64 val = 0; > val = (hypercall_no & HYPERCALL_MASK) | HYPERCALL_BIT; > diff --git a/x86/vmx.h b/x86/vmx.h > index d1c2436..e29301e 100644 > --- a/x86/vmx.h > +++ b/x86/vmx.h > @@ -895,6 +895,7 @@ bool ept_ad_bits_supported(void); > void __enter_guest(u8 abort_flag, struct vmentry_result *result); > void enter_guest(void); > void enter_guest_with_bad_controls(void); > +void hypercall(u32 hypercall_no); > > typedef void (*test_guest_func)(void); > typedef void (*test_teardown_func)(void *data); > diff --git a/x86/vmx_tests.c b/x86/vmx_tests.c > index 22f0c7b..1cadc56 100644 > --- a/x86/vmx_tests.c > +++ b/x86/vmx_tests.c > @@ -8029,6 +8029,53 @@ static void vmx_guest_state_area_test(void) > enter_guest(); > } > > +extern void unrestricted_guest_main(void); > +asm (".code32\n" > + "unrestricted_guest_main:\n" > + "vmcall\n" > + "nop\n" > + "mov $1, %edi\n" > + "call hypercall\n" > + ".code64\n"); > + > +static void setup_unrestricted_guest(void) > +{ > + vmcs_write(GUEST_CR0, vmcs_read(GUEST_CR0) & ~(X86_CR0_PG)); > + vmcs_write(ENT_CONTROLS, vmcs_read(ENT_CONTROLS) & ~ENT_GUEST_64); > + vmcs_write(GUEST_EFER, vmcs_read(GUEST_EFER) & ~EFER_LMA); > + vmcs_write(GUEST_RIP, virt_to_phys(unrestricted_guest_main)); > +} > + > +static void unsetup_unrestricted_guest(void) > +{ > + vmcs_write(GUEST_CR0, vmcs_read(GUEST_CR0) | X86_CR0_PG); > + vmcs_write(ENT_CONTROLS, vmcs_read(ENT_CONTROLS) | ENT_GUEST_64); > + vmcs_write(GUEST_EFER, vmcs_read(GUEST_EFER) | EFER_LMA); > + vmcs_write(GUEST_RIP, (u64) phys_to_virt(vmcs_read(GUEST_RIP))); > + vmcs_write(GUEST_RSP, (u64) phys_to_virt(vmcs_read(GUEST_RSP))); > +} > + > +/* > + * If "unrestricted guest" secondary VM-execution control is set, guests > + * can run in unpaged protected mode. > + */ > +static void vmentry_unrestricted_guest_test(void) > +{ > + test_set_guest(unrestricted_guest_main); > + setup_unrestricted_guest(); > + if (setup_ept(false)) > + test_skip("EPT not supported"); > + vmcs_write(CPU_EXEC_CTRL1, vmcs_read(CPU_EXEC_CTRL1) | CPU_URG); > + test_guest_state("Unrestricted guest test", false, CPU_URG, "CPU_URG"); Indentation looks funky. > + > + /* > + * Let the guest finish execution as a regular guest > + */ > + unsetup_unrestricted_guest(); > + vmcs_write(CPU_EXEC_CTRL1, vmcs_read(CPU_EXEC_CTRL1) & ~CPU_URG); > + enter_guest(); > +} > + > static bool valid_vmcs_for_vmentry(void) > { > struct vmcs *current_vmcs = NULL; > @@ -10234,6 +10281,7 @@ struct vmx_test vmx_tests[] = { > TEST(vmx_host_state_area_test), > TEST(vmx_guest_state_area_test), > TEST(vmentry_movss_shadow_test), > + TEST(vmentry_unrestricted_guest_test), > /* APICv tests */ > TEST(vmx_eoi_bitmap_ioapic_scan_test), > TEST(vmx_hlt_with_rvi_test), > -- > 2.18.4 >
diff --git a/x86/vmx.c b/x86/vmx.c index 07415b4..1a84a74 100644 --- a/x86/vmx.c +++ b/x86/vmx.c @@ -1699,7 +1699,7 @@ static void test_vmx_caps(void) } /* This function can only be called in guest */ -static void __attribute__((__used__)) hypercall(u32 hypercall_no) +void __attribute__((__used__)) hypercall(u32 hypercall_no) { u64 val = 0; val = (hypercall_no & HYPERCALL_MASK) | HYPERCALL_BIT; diff --git a/x86/vmx.h b/x86/vmx.h index d1c2436..e29301e 100644 --- a/x86/vmx.h +++ b/x86/vmx.h @@ -895,6 +895,7 @@ bool ept_ad_bits_supported(void); void __enter_guest(u8 abort_flag, struct vmentry_result *result); void enter_guest(void); void enter_guest_with_bad_controls(void); +void hypercall(u32 hypercall_no); typedef void (*test_guest_func)(void); typedef void (*test_teardown_func)(void *data); diff --git a/x86/vmx_tests.c b/x86/vmx_tests.c index 22f0c7b..1cadc56 100644 --- a/x86/vmx_tests.c +++ b/x86/vmx_tests.c @@ -8029,6 +8029,53 @@ static void vmx_guest_state_area_test(void) enter_guest(); } +extern void unrestricted_guest_main(void); +asm (".code32\n" + "unrestricted_guest_main:\n" + "vmcall\n" + "nop\n" + "mov $1, %edi\n" + "call hypercall\n" + ".code64\n"); + +static void setup_unrestricted_guest(void) +{ + vmcs_write(GUEST_CR0, vmcs_read(GUEST_CR0) & ~(X86_CR0_PG)); + vmcs_write(ENT_CONTROLS, vmcs_read(ENT_CONTROLS) & ~ENT_GUEST_64); + vmcs_write(GUEST_EFER, vmcs_read(GUEST_EFER) & ~EFER_LMA); + vmcs_write(GUEST_RIP, virt_to_phys(unrestricted_guest_main)); +} + +static void unsetup_unrestricted_guest(void) +{ + vmcs_write(GUEST_CR0, vmcs_read(GUEST_CR0) | X86_CR0_PG); + vmcs_write(ENT_CONTROLS, vmcs_read(ENT_CONTROLS) | ENT_GUEST_64); + vmcs_write(GUEST_EFER, vmcs_read(GUEST_EFER) | EFER_LMA); + vmcs_write(GUEST_RIP, (u64) phys_to_virt(vmcs_read(GUEST_RIP))); + vmcs_write(GUEST_RSP, (u64) phys_to_virt(vmcs_read(GUEST_RSP))); +} + +/* + * If "unrestricted guest" secondary VM-execution control is set, guests + * can run in unpaged protected mode. + */ +static void vmentry_unrestricted_guest_test(void) +{ + test_set_guest(unrestricted_guest_main); + setup_unrestricted_guest(); + if (setup_ept(false)) + test_skip("EPT not supported"); + vmcs_write(CPU_EXEC_CTRL1, vmcs_read(CPU_EXEC_CTRL1) | CPU_URG); + test_guest_state("Unrestricted guest test", false, CPU_URG, "CPU_URG"); + + /* + * Let the guest finish execution as a regular guest + */ + unsetup_unrestricted_guest(); + vmcs_write(CPU_EXEC_CTRL1, vmcs_read(CPU_EXEC_CTRL1) & ~CPU_URG); + enter_guest(); +} + static bool valid_vmcs_for_vmentry(void) { struct vmcs *current_vmcs = NULL; @@ -10234,6 +10281,7 @@ struct vmx_test vmx_tests[] = { TEST(vmx_host_state_area_test), TEST(vmx_guest_state_area_test), TEST(vmentry_movss_shadow_test), + TEST(vmentry_unrestricted_guest_test), /* APICv tests */ TEST(vmx_eoi_bitmap_ioapic_scan_test), TEST(vmx_hlt_with_rvi_test),