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@xxxxxxxxxx> > Signed-off-by: Krish Sadhukhan <krish.sadhukhan@xxxxxxxxxx> 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 >