On 10/11/2015 13:55, Wanpeng Li wrote:
> VPID test case for invvpid single and invvpid all.
> 
> Signed-off-by: Wanpeng Li <wanpeng...@hotmail.com>
> ---
>  x86/vmx.c       | 17 ++++++++++++++++
>  x86/vmx.h       | 17 ++++++++++++++++
>  x86/vmx_tests.c | 63 
> +++++++++++++++++++++++++++++++++++++++++++++++++++++++++
>  3 files changed, 97 insertions(+)
> 
> diff --git a/x86/vmx.c b/x86/vmx.c
> index 51e63a0..f05cd33 100644
> --- a/x86/vmx.c
> +++ b/x86/vmx.c
> @@ -386,6 +386,23 @@ int set_ept_pte(unsigned long *pml4, unsigned long 
> guest_addr,
>       return 0;
>  }
>  
> +void vpid_sync(int type, u16 vpid)
> +{
> +     switch(type) {
> +     case INVVPID_SINGLE:
> +             if (ept_vpid.val & VPID_CAP_INVVPID_SINGLE) {
> +                     invvpid(INVVPID_SINGLE, vpid, 0);
> +                     break;
> +             }
> +     case INVVPID_ALL:
> +             if (ept_vpid.val & VPID_CAP_INVVPID_ALL) {
> +                     invvpid(INVVPID_ALL, vpid, 0);
> +                     break;
> +             }
> +     default:
> +             printf("WARNING: invvpid is not supported\n");
> +     }
> +}
>  
>  static void init_vmcs_ctrl(void)
>  {
> diff --git a/x86/vmx.h b/x86/vmx.h
> index 3571248..b6a4878 100644
> --- a/x86/vmx.h
> +++ b/x86/vmx.h
> @@ -460,6 +460,9 @@ enum Ctrl1 {
>  #define EPT_CAP_INVEPT_SINGLE        (1ull << 25)
>  #define EPT_CAP_INVEPT_ALL   (1ull << 26)
>  #define EPT_CAP_AD_FLAG      (1ull << 21)
> +#define VPID_CAP_INVVPID (1ull << 32)
> +#define VPID_CAP_INVVPID_SINGLE  (1ull << 41)
> +#define VPID_CAP_INVVPID_ALL  (1ull << 42)
>  
>  #define PAGE_SIZE_2M         (512 * PAGE_SIZE)
>  #define PAGE_SIZE_1G         (512 * PAGE_SIZE_2M)
> @@ -485,6 +488,9 @@ enum Ctrl1 {
>  #define INVEPT_SINGLE                1
>  #define INVEPT_GLOBAL                2
>  
> +#define INVVPID_SINGLE      1
> +#define INVVPID_ALL         2
> +
>  #define ACTV_ACTIVE          0
>  #define ACTV_HLT             1
>  
> @@ -544,8 +550,19 @@ static inline void invept(unsigned long type, u64 eptp)
>       asm volatile("invept %0, %1\n" ::"m"(operand),"r"(type));
>  }
>  
> +static inline void invvpid(unsigned long type, u16 vpid, u64 gva)
> +{
> +     struct {
> +             u64 vpid : 16;
> +             u64 rsvd : 48;
> +             u64 gva;
> +     } operand = {vpid, 0, gva};
> +     asm volatile("invvpid %0, %1\n" ::"m"(operand),"r"(type));
> +}
> +
>  void print_vmexit_info();
>  void ept_sync(int type, u64 eptp);
> +void vpid_sync(int type, u16 vpid);
>  void install_ept_entry(unsigned long *pml4, int pte_level,
>               unsigned long guest_addr, unsigned long pte,
>               unsigned long *pt_page);
> diff --git a/x86/vmx_tests.c b/x86/vmx_tests.c
> index 79552fd..451fdd7 100644
> --- a/x86/vmx_tests.c
> +++ b/x86/vmx_tests.c
> @@ -1150,6 +1150,68 @@ static int ept_exit_handler()
>       return VMX_TEST_VMEXIT;
>  }
>  
> +static int vpid_init()
> +{
> +     u32 ctrl_cpu1;
> +
> +     if (!(ctrl_cpu_rev[0].clr & CPU_SECONDARY) ||
> +             !(ctrl_cpu_rev[1].clr & CPU_VPID)) {
> +             printf("\tVPID is not supported");
> +             return VMX_TEST_EXIT;
> +     }
> +
> +     ctrl_cpu1 = vmcs_read(CPU_EXEC_CTRL1);
> +     ctrl_cpu1 |= CPU_VPID;
> +     vmcs_write(CPU_EXEC_CTRL1, ctrl_cpu1);
> +     return VMX_TEST_START;
> +}
> +
> +static void vpid_main()
> +{
> +     vmx_set_test_stage(0);
> +     vmcall();
> +     report("INVVPID SINGLE", vmx_get_test_stage() == 0);
> +     vmx_set_test_stage(1);
> +     vmcall();
> +     report("INVVPID ALL", vmx_get_test_stage() == 1);
> +}
> +
> +static int vpid_exit_handler()
> +{
> +     u64 guest_rip;
> +     ulong reason;
> +     u32 insn_len;
> +     u32 exit_qual;
> +
> +     guest_rip = vmcs_read(GUEST_RIP);
> +     reason = vmcs_read(EXI_REASON) & 0xff;
> +     insn_len = vmcs_read(EXI_INST_LEN);
> +     exit_qual = vmcs_read(EXI_QUALIFICATION);
> +
> +     switch (reason) {
> +     case VMX_VMCALL:
> +             switch(vmx_get_test_stage()) {
> +             case 0:
> +                     vpid_sync(INVVPID_SINGLE, 1);
> +                     break;
> +             case 1:
> +                     vpid_sync(INVVPID_ALL, 1);
> +                     break;
> +             default:
> +                     printf("ERROR: unexpected stage, %d\n",
> +                                     vmx_get_test_stage());
> +                     print_vmexit_info();
> +                     return VMX_TEST_VMEXIT;
> +             }
> +             vmcs_write(GUEST_RIP, guest_rip + insn_len);
> +             return VMX_TEST_RESUME;
> +     default:
> +             printf("Unknown exit reason, %d\n", reason);
> +             print_vmexit_info();
> +     }
> +     return VMX_TEST_VMEXIT;
> +}
> +
>  #define TIMER_VECTOR 222
>  
>  static volatile bool timer_fired;
> @@ -1547,6 +1609,7 @@ struct vmx_test vmx_tests[] = {
>       { "instruction intercept", insn_intercept_init, insn_intercept_main,
>               insn_intercept_exit_handler, NULL, {0} },
>       { "EPT framework", ept_init, ept_main, ept_exit_handler, NULL, {0} },
> +     { "VPID", vpid_init, vpid_main, vpid_exit_handler, NULL, {0} },
>       { "interrupt", interrupt_init, interrupt_main,
>               interrupt_exit_handler, NULL, {0} },
>       { "debug controls", dbgctls_init, dbgctls_main, dbgctls_exit_handler,
> 

Applied, thanks!

Paolo
--
To unsubscribe from this list: send the line "unsubscribe kvm" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to