Re: [kvm-unit-tests PATCH] vpid test case

From: Paolo Bonzini
Date: Wed Nov 11 2015 - 08:11:15 EST




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 linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/