On 2013-08-13 17:56, Arthur Chunqi Li wrote: > Add test cases for ENT_LOAD_PAT, ENT_LOAD_EFER, EXI_LOAD_PAT, > EXI_SAVE_PAT, EXI_LOAD_EFER, EXI_SAVE_PAT flags in enter/exit > control fields. > > Signed-off-by: Arthur Chunqi Li <yzt356@xxxxxxxxx> > --- > x86/vmx.h | 7 +++ > x86/vmx_tests.c | 185 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ > 2 files changed, 192 insertions(+) > > diff --git a/x86/vmx.h b/x86/vmx.h > index 28595d8..18961f1 100644 > --- a/x86/vmx.h > +++ b/x86/vmx.h > @@ -152,10 +152,12 @@ enum Encoding { > GUEST_DEBUGCTL = 0x2802ul, > GUEST_DEBUGCTL_HI = 0x2803ul, > GUEST_EFER = 0x2806ul, > + GUEST_PAT = 0x2804ul, > GUEST_PERF_GLOBAL_CTRL = 0x2808ul, > GUEST_PDPTE = 0x280aul, > > /* 64-Bit Host State */ > + HOST_PAT = 0x2c00ul, > HOST_EFER = 0x2c02ul, > HOST_PERF_GLOBAL_CTRL = 0x2c04ul, > > @@ -330,11 +332,15 @@ enum Ctrl_exi { > EXI_HOST_64 = 1UL << 9, > EXI_LOAD_PERF = 1UL << 12, > EXI_INTA = 1UL << 15, > + EXI_SAVE_PAT = 1UL << 18, > + EXI_LOAD_PAT = 1UL << 19, > + EXI_SAVE_EFER = 1UL << 20, > EXI_LOAD_EFER = 1UL << 21, > }; > > enum Ctrl_ent { > ENT_GUEST_64 = 1UL << 9, > + ENT_LOAD_PAT = 1UL << 14, > ENT_LOAD_EFER = 1UL << 15, > }; > > @@ -354,6 +360,7 @@ enum Ctrl0 { > CPU_NMI_WINDOW = 1ul << 22, > CPU_IO = 1ul << 24, > CPU_IO_BITMAP = 1ul << 25, > + CPU_MSR_BITMAP = 1ul << 28, > CPU_SECONDARY = 1ul << 31, > }; > > diff --git a/x86/vmx_tests.c b/x86/vmx_tests.c > index c1b39f4..61b0cef 100644 > --- a/x86/vmx_tests.c > +++ b/x86/vmx_tests.c > @@ -1,4 +1,15 @@ > #include "vmx.h" > +#include "msr.h" > +#include "processor.h" > +#include "vm.h" > + > +u64 ia32_pat; > +u64 ia32_efer; > + > +static inline void vmcall() > +{ > + asm volatile("vmcall"); > +} > > void basic_init() > { > @@ -76,6 +87,176 @@ int vmenter_exit_handler() > return VMX_TEST_VMEXIT; > } > > +void msr_bmp_init() > +{ > + void *msr_bitmap; > + u32 ctrl_cpu0; > + > + msr_bitmap = alloc_page(); > + memset(msr_bitmap, 0x0, PAGE_SIZE); > + ctrl_cpu0 = vmcs_read(CPU_EXEC_CTRL0); > + ctrl_cpu0 |= CPU_MSR_BITMAP; > + vmcs_write(CPU_EXEC_CTRL0, ctrl_cpu0); > + vmcs_write(MSR_BITMAP, (u64)msr_bitmap); > +} Better safe this function for the test case where you actually stress the bitmap. Jan > + > +static void test_ctrl_pat_init() > +{ > + u64 ctrl_ent; > + u64 ctrl_exi; > + > + msr_bmp_init(); > + ctrl_ent = vmcs_read(ENT_CONTROLS); > + ctrl_exi = vmcs_read(EXI_CONTROLS); > + vmcs_write(ENT_CONTROLS, ctrl_ent | ENT_LOAD_PAT); > + vmcs_write(EXI_CONTROLS, ctrl_exi | (EXI_SAVE_PAT | EXI_LOAD_PAT)); > + ia32_pat = rdmsr(MSR_IA32_CR_PAT); > + vmcs_write(GUEST_PAT, 0x0); > + vmcs_write(HOST_PAT, ia32_pat); > +} > + > +static void test_ctrl_pat_main() > +{ > + u64 guest_ia32_pat; > + > + guest_ia32_pat = rdmsr(MSR_IA32_CR_PAT); > + if (!(ctrl_enter_rev.clr & ENT_LOAD_PAT)) > + printf("\tENT_LOAD_PAT is not supported.\n"); > + else { > + if (guest_ia32_pat != 0) { > + report("Entry load PAT", 0); > + return; > + } > + } > + wrmsr(MSR_IA32_CR_PAT, 0x6); > + vmcall(); > + guest_ia32_pat = rdmsr(MSR_IA32_CR_PAT); > + if (ctrl_enter_rev.clr & ENT_LOAD_PAT) { > + if (guest_ia32_pat != ia32_pat) { > + report("Entry load PAT", 0); > + return; > + } > + report("Entry load PAT", 1); > + } > +} > + > +static int test_ctrl_pat_exit_handler() > +{ > + u64 guest_rip; > + ulong reason; > + u64 guest_pat; > + > + guest_rip = vmcs_read(GUEST_RIP); > + reason = vmcs_read(EXI_REASON) & 0xff; > + switch (reason) { > + case VMX_VMCALL: > + guest_pat = vmcs_read(GUEST_PAT); > + if (!(ctrl_exit_rev.clr & EXI_SAVE_PAT)) { > + printf("\tEXI_SAVE_PAT is not supported\n"); > + vmcs_write(GUEST_PAT, 0x6); > + } else { > + if (guest_pat == 0x6) > + report("Exit save PAT", 1); > + else > + report("Exit save PAT", 0); > + } > + if (!(ctrl_exit_rev.clr & EXI_LOAD_PAT)) > + printf("\tEXI_LOAD_PAT is not supported\n"); > + else { > + if (rdmsr(MSR_IA32_CR_PAT) == ia32_pat) > + report("Exit load PAT", 1); > + else > + report("Exit load PAT", 0); > + } > + vmcs_write(GUEST_PAT, ia32_pat); > + vmcs_write(GUEST_RIP, guest_rip + 3); > + return VMX_TEST_RESUME; > + default: > + printf("ERROR : Undefined exit reason, reason = %d.\n", reason); > + break; > + } > + return VMX_TEST_VMEXIT; > +} > + > +static void test_ctrl_efer_init() > +{ > + u64 ctrl_ent; > + u64 ctrl_exi; > + > + msr_bmp_init(); > + ctrl_ent = vmcs_read(ENT_CONTROLS) | ENT_LOAD_EFER; > + ctrl_exi = vmcs_read(EXI_CONTROLS) | EXI_SAVE_EFER | EXI_LOAD_EFER; > + vmcs_write(ENT_CONTROLS, ctrl_ent & ctrl_enter_rev.clr); > + vmcs_write(EXI_CONTROLS, ctrl_exi & ctrl_exit_rev.clr); > + ia32_efer = rdmsr(MSR_EFER); > + vmcs_write(GUEST_EFER, ia32_efer ^ EFER_NX); > + vmcs_write(HOST_EFER, ia32_efer ^ EFER_NX); > +} > + > +static void test_ctrl_efer_main() > +{ > + u64 guest_ia32_efer; > + > + guest_ia32_efer = rdmsr(MSR_EFER); > + if (!(ctrl_enter_rev.clr & ENT_LOAD_EFER)) > + printf("\tENT_LOAD_EFER is not supported.\n"); > + else { > + if (guest_ia32_efer != (ia32_efer ^ EFER_NX)) { > + report("Entry load EFER", 0); > + return; > + } > + } > + wrmsr(MSR_EFER, ia32_efer); > + vmcall(); > + guest_ia32_efer = rdmsr(MSR_EFER); > + if (ctrl_enter_rev.clr & ENT_LOAD_EFER) { > + if (guest_ia32_efer != ia32_efer) { > + report("Entry load EFER", 0); > + return; > + } > + report("Entry load EFER", 1); > + } > +} > + > +static int test_ctrl_efer_exit_handler() > +{ > + u64 guest_rip; > + ulong reason; > + u64 guest_efer; > + > + guest_rip = vmcs_read(GUEST_RIP); > + reason = vmcs_read(EXI_REASON) & 0xff; > + switch (reason) { > + case VMX_VMCALL: > + guest_efer = vmcs_read(GUEST_EFER); > + if (!(ctrl_exit_rev.clr & EXI_SAVE_EFER)) { > + printf("\tEXI_SAVE_EFER is not supported\n"); > + vmcs_write(GUEST_EFER, ia32_efer); > + } else { > + if (guest_efer == ia32_efer) > + report("Exit save EFER", 1); > + else > + report("Exit save EFER", 0); > + } > + if (!(ctrl_exit_rev.clr & EXI_LOAD_EFER)) { > + printf("\tEXI_LOAD_EFER is not supported\n"); > + wrmsr(MSR_EFER, ia32_efer ^ EFER_NX); > + } else { > + if (rdmsr(MSR_EFER) == (ia32_efer ^ EFER_NX)) > + report("Exit load EFER", 1); > + else > + report("Exit load EFER", 0); > + } > + vmcs_write(GUEST_PAT, ia32_efer); > + vmcs_write(GUEST_RIP, guest_rip + 3); > + return VMX_TEST_RESUME; > + default: > + printf("ERROR : Undefined exit reason, reason = %d.\n", reason); > + break; > + } > + return VMX_TEST_VMEXIT; > +} > + > /* name/init/guest_main/exit_handler/syscall_handler/guest_regs > basic_* just implement some basic functions */ > struct vmx_test vmx_tests[] = { > @@ -83,5 +264,9 @@ struct vmx_test vmx_tests[] = { > basic_syscall_handler, {0} }, > { "vmenter", basic_init, vmenter_main, vmenter_exit_handler, > basic_syscall_handler, {0} }, > + { "control field PAT", test_ctrl_pat_init, test_ctrl_pat_main, > + test_ctrl_pat_exit_handler, basic_syscall_handler, {0} }, > + { "control field EFER", test_ctrl_efer_init, test_ctrl_efer_main, > + test_ctrl_efer_exit_handler, basic_syscall_handler, {0} }, > { NULL, NULL, NULL, NULL, NULL, {0} }, > }; >
Attachment:
signature.asc
Description: OpenPGP digital signature