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 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.

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} },
>  };
> 


Attachment: signature.asc
Description: OpenPGP digital signature


[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