On 10/11/2015 13:55, Wanpeng Li wrote: > VPID test case for invvpid single and invvpid all. > > Signed-off-by: Wanpeng Li <wanpeng.li@xxxxxxxxxxx> > --- > 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 majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html