On Thu, Aug 15, 2013 at 3:17 PM, Jan Kiszka <jan.kiszka@xxxxxx> wrote: > 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. What do you mean by "safe"? Arthur > > 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} }, >> }; >> > > -- Arthur Chunqi Li Department of Computer Science School of EECS Peking University Beijing, China -- To unsubscribe from this list: send the line "unsubscribe kvm" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html