Re: [PATCH 1/4] kvm-unit-tests: VMX: Add test cases for PAT and EFER

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



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




[Index of Archives]     [KVM ARM]     [KVM ia64]     [KVM ppc]     [Virtualization Tools]     [Spice Development]     [Libvirt]     [Libvirt Users]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite Questions]     [Linux Kernel]     [Linux SCSI]     [XFree86]
  Powered by Linux