From mboxrd@z Thu Jan 1 00:00:00 1970 From: Jan Kiszka Subject: Re: [PATCH 1/4] kvm-unit-tests: VMX: Add test cases for PAT and EFER Date: Thu, 15 Aug 2013 09:17:28 +0200 Message-ID: <520C8088.6070607@web.de> References: <1376409368-7016-1-git-send-email-yzt356@gmail.com> <1376409368-7016-2-git-send-email-yzt356@gmail.com> Mime-Version: 1.0 Content-Type: multipart/signed; micalg=pgp-sha1; protocol="application/pgp-signature"; boundary="J3mbPEdbfR6riTHHw0OI71IG6BcgSXIqs" Cc: kvm@vger.kernel.org, gleb@redhat.com, pbonzini@redhat.com To: Arthur Chunqi Li Return-path: Received: from mout.web.de ([212.227.17.11]:52440 "EHLO mout.web.de" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1753242Ab3HOHRf (ORCPT ); Thu, 15 Aug 2013 03:17:35 -0400 Received: from mchn199C.mchp.siemens.de ([95.157.58.223]) by smtp.web.de (mrweb103) with ESMTPSA (Nemesis) id 0MQNma-1VX58K2Obc-00TiBA for ; Thu, 15 Aug 2013 09:17:33 +0200 In-Reply-To: <1376409368-7016-2-git-send-email-yzt356@gmail.com> Sender: kvm-owner@vger.kernel.org List-ID: This is an OpenPGP/MIME signed message (RFC 4880 and 3156) --J3mbPEdbfR6riTHHw0OI71IG6BcgSXIqs Content-Type: text/plain; charset=ISO-8859-15 Content-Transfer-Encoding: quoted-printable 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. >=20 > Signed-off-by: Arthur Chunqi Li > --- > x86/vmx.h | 7 +++ > x86/vmx_tests.c | 185 +++++++++++++++++++++++++++++++++++++++++++++++= ++++++++ > 2 files changed, 192 insertions(+) >=20 > 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 =3D 0x2802ul, > GUEST_DEBUGCTL_HI =3D 0x2803ul, > GUEST_EFER =3D 0x2806ul, > + GUEST_PAT =3D 0x2804ul, > GUEST_PERF_GLOBAL_CTRL =3D 0x2808ul, > GUEST_PDPTE =3D 0x280aul, > =20 > /* 64-Bit Host State */ > + HOST_PAT =3D 0x2c00ul, > HOST_EFER =3D 0x2c02ul, > HOST_PERF_GLOBAL_CTRL =3D 0x2c04ul, > =20 > @@ -330,11 +332,15 @@ enum Ctrl_exi { > EXI_HOST_64 =3D 1UL << 9, > EXI_LOAD_PERF =3D 1UL << 12, > EXI_INTA =3D 1UL << 15, > + EXI_SAVE_PAT =3D 1UL << 18, > + EXI_LOAD_PAT =3D 1UL << 19, > + EXI_SAVE_EFER =3D 1UL << 20, > EXI_LOAD_EFER =3D 1UL << 21, > }; > =20 > enum Ctrl_ent { > ENT_GUEST_64 =3D 1UL << 9, > + ENT_LOAD_PAT =3D 1UL << 14, > ENT_LOAD_EFER =3D 1UL << 15, > }; > =20 > @@ -354,6 +360,7 @@ enum Ctrl0 { > CPU_NMI_WINDOW =3D 1ul << 22, > CPU_IO =3D 1ul << 24, > CPU_IO_BITMAP =3D 1ul << 25, > + CPU_MSR_BITMAP =3D 1ul << 28, > CPU_SECONDARY =3D 1ul << 31, > }; > =20 > 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"); > +} > =20 > void basic_init() > { > @@ -76,6 +87,176 @@ int vmenter_exit_handler() > return VMX_TEST_VMEXIT; > } > =20 > +void msr_bmp_init() > +{ > + void *msr_bitmap; > + u32 ctrl_cpu0; > + > + msr_bitmap =3D alloc_page(); > + memset(msr_bitmap, 0x0, PAGE_SIZE); > + ctrl_cpu0 =3D vmcs_read(CPU_EXEC_CTRL0); > + ctrl_cpu0 |=3D 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 =3D vmcs_read(ENT_CONTROLS); > + ctrl_exi =3D 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 =3D 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 =3D 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 !=3D 0) { > + report("Entry load PAT", 0); > + return; > + } > + } > + wrmsr(MSR_IA32_CR_PAT, 0x6); > + vmcall(); > + guest_ia32_pat =3D rdmsr(MSR_IA32_CR_PAT); > + if (ctrl_enter_rev.clr & ENT_LOAD_PAT) { > + if (guest_ia32_pat !=3D 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 =3D vmcs_read(GUEST_RIP); > + reason =3D vmcs_read(EXI_REASON) & 0xff; > + switch (reason) { > + case VMX_VMCALL: > + guest_pat =3D 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 =3D=3D 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) =3D=3D 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 =3D %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 =3D vmcs_read(ENT_CONTROLS) | ENT_LOAD_EFER; > + ctrl_exi =3D 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 =3D 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 =3D rdmsr(MSR_EFER); > + if (!(ctrl_enter_rev.clr & ENT_LOAD_EFER)) > + printf("\tENT_LOAD_EFER is not supported.\n"); > + else { > + if (guest_ia32_efer !=3D (ia32_efer ^ EFER_NX)) { > + report("Entry load EFER", 0); > + return; > + } > + } > + wrmsr(MSR_EFER, ia32_efer); > + vmcall(); > + guest_ia32_efer =3D rdmsr(MSR_EFER); > + if (ctrl_enter_rev.clr & ENT_LOAD_EFER) { > + if (guest_ia32_efer !=3D 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 =3D vmcs_read(GUEST_RIP); > + reason =3D vmcs_read(EXI_REASON) & 0xff; > + switch (reason) { > + case VMX_VMCALL: > + guest_efer =3D 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 =3D=3D 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) =3D=3D (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 =3D %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[] =3D { > @@ -83,5 +264,9 @@ struct vmx_test vmx_tests[] =3D { > 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} }, > }; >=20 --J3mbPEdbfR6riTHHw0OI71IG6BcgSXIqs Content-Type: application/pgp-signature; name="signature.asc" Content-Description: OpenPGP digital signature Content-Disposition: attachment; filename="signature.asc" -----BEGIN PGP SIGNATURE----- Version: GnuPG v2.0.16 (GNU/Linux) Comment: Using GnuPG with Thunderbird - http://www.enigmail.net/ iEYEARECAAYFAlIMgIsACgkQitSsb3rl5xR8jQCfZxOPbilUPHu33AsP2AfATLDd LCgAn0zGmbABmkMs7DjCaUmtnr9qCVh4 =DkOz -----END PGP SIGNATURE----- --J3mbPEdbfR6riTHHw0OI71IG6BcgSXIqs--