* [kvm-unit-tests PATCH] x86: access: Shadow CR0, CR4 and EFER to avoid unnecessary VM-Exits
@ 2020-03-10 3:54 Sean Christopherson
2020-03-31 15:15 ` Paolo Bonzini
0 siblings, 1 reply; 2+ messages in thread
From: Sean Christopherson @ 2020-03-10 3:54 UTC (permalink / raw)
To: Paolo Bonzini; +Cc: kvm
Track the last known CR0, CR4, and EFER values in the access test to
avoid taking a VM-Exit on every. single. test. The EFER VM-Exits in
particular absolutely tank performance when running the test in L1.
Opportunistically tweak the 5-level test to print that it's starting
before configuring 5-level page tables, e.g. in case enabling 5-level
paging runs into issues.
No functional change intended.
Signed-off-by: Sean Christopherson <sean.j.christopherson@intel.com>
---
x86/access.c | 45 +++++++++++++++++++++++++++------------------
1 file changed, 27 insertions(+), 18 deletions(-)
diff --git a/x86/access.c b/x86/access.c
index 7303fc3..86d8a72 100644
--- a/x86/access.c
+++ b/x86/access.c
@@ -169,29 +169,33 @@ typedef struct {
static void ac_test_show(ac_test_t *at);
+static unsigned long shadow_cr0;
+static unsigned long shadow_cr4;
+static unsigned long long shadow_efer;
+
static void set_cr0_wp(int wp)
{
- unsigned long cr0 = read_cr0();
- unsigned long old_cr0 = cr0;
+ unsigned long cr0 = shadow_cr0;
cr0 &= ~CR0_WP_MASK;
if (wp)
cr0 |= CR0_WP_MASK;
- if (old_cr0 != cr0)
+ if (cr0 != shadow_cr0) {
write_cr0(cr0);
+ shadow_cr0 = cr0;
+ }
}
static unsigned set_cr4_smep(int smep)
{
- unsigned long cr4 = read_cr4();
- unsigned long old_cr4 = cr4;
+ unsigned long cr4 = shadow_cr4;
extern u64 ptl2[];
unsigned r;
cr4 &= ~CR4_SMEP_MASK;
if (smep)
cr4 |= CR4_SMEP_MASK;
- if (old_cr4 == cr4)
+ if (cr4 == shadow_cr4)
return 0;
if (smep)
@@ -199,37 +203,39 @@ static unsigned set_cr4_smep(int smep)
r = write_cr4_checking(cr4);
if (r || !smep)
ptl2[2] |= PT_USER_MASK;
+ if (!r)
+ shadow_cr4 = cr4;
return r;
}
static void set_cr4_pke(int pke)
{
- unsigned long cr4 = read_cr4();
- unsigned long old_cr4 = cr4;
+ unsigned long cr4 = shadow_cr4;
cr4 &= ~X86_CR4_PKE;
if (pke)
cr4 |= X86_CR4_PKE;
- if (old_cr4 == cr4)
+ if (cr4 == shadow_cr4)
return;
/* Check that protection keys do not affect accesses when CR4.PKE=0. */
- if ((read_cr4() & X86_CR4_PKE) && !pke) {
+ if ((shadow_cr4 & X86_CR4_PKE) && !pke)
write_pkru(0xfffffffc);
- }
write_cr4(cr4);
+ shadow_cr4 = cr4;
}
static void set_efer_nx(int nx)
{
- unsigned long long efer = rdmsr(MSR_EFER);
- unsigned long long old_efer = efer;
+ unsigned long long efer = shadow_efer;
efer &= ~EFER_NX_MASK;
if (nx)
efer |= EFER_NX_MASK;
- if (old_efer != efer)
+ if (efer != shadow_efer) {
wrmsr(MSR_EFER, efer);
+ shadow_efer = efer;
+ }
}
static void ac_env_int(ac_pool_t *pool)
@@ -245,7 +251,7 @@ static void ac_env_int(ac_pool_t *pool)
static void ac_test_init(ac_test_t *at, void *virt)
{
- wrmsr(MSR_EFER, rdmsr(MSR_EFER) | EFER_NX_MASK);
+ set_efer_nx(1);
set_cr0_wp(1);
at->flags = 0;
at->virt = virt;
@@ -935,14 +941,17 @@ static int ac_test_run(void)
printf("run\n");
tests = successes = 0;
+ shadow_cr0 = read_cr0();
+ shadow_cr4 = read_cr4();
+ shadow_efer = rdmsr(MSR_EFER);
+
if (this_cpu_has(X86_FEATURE_PKU)) {
set_cr4_pke(1);
set_cr4_pke(0);
/* Now PKRU = 0xFFFFFFFF. */
} else {
- unsigned long cr4 = read_cr4();
tests++;
- if (write_cr4_checking(cr4 | X86_CR4_PKE) == GP_VECTOR) {
+ if (write_cr4_checking(shadow_cr4 | X86_CR4_PKE) == GP_VECTOR) {
successes++;
invalid_mask |= AC_PKU_AD_MASK;
invalid_mask |= AC_PKU_WD_MASK;
@@ -996,8 +1005,8 @@ int main(void)
if (this_cpu_has(X86_FEATURE_LA57)) {
page_table_levels = 5;
- setup_5level_page_table();
printf("starting 5-level paging test.\n\n");
+ setup_5level_page_table();
r = ac_test_run();
}
--
2.24.1
^ permalink raw reply related [flat|nested] 2+ messages in thread
* Re: [kvm-unit-tests PATCH] x86: access: Shadow CR0, CR4 and EFER to avoid unnecessary VM-Exits
2020-03-10 3:54 [kvm-unit-tests PATCH] x86: access: Shadow CR0, CR4 and EFER to avoid unnecessary VM-Exits Sean Christopherson
@ 2020-03-31 15:15 ` Paolo Bonzini
0 siblings, 0 replies; 2+ messages in thread
From: Paolo Bonzini @ 2020-03-31 15:15 UTC (permalink / raw)
To: Sean Christopherson; +Cc: kvm
On 10/03/20 04:54, Sean Christopherson wrote:
> Track the last known CR0, CR4, and EFER values in the access test to
> avoid taking a VM-Exit on every. single. test. The EFER VM-Exits in
> particular absolutely tank performance when running the test in L1.
>
> Opportunistically tweak the 5-level test to print that it's starting
> before configuring 5-level page tables, e.g. in case enabling 5-level
> paging runs into issues.
>
> No functional change intended.
>
> Signed-off-by: Sean Christopherson <sean.j.christopherson@intel.com>
> ---
> x86/access.c | 45 +++++++++++++++++++++++++++------------------
> 1 file changed, 27 insertions(+), 18 deletions(-)
>
> diff --git a/x86/access.c b/x86/access.c
> index 7303fc3..86d8a72 100644
> --- a/x86/access.c
> +++ b/x86/access.c
> @@ -169,29 +169,33 @@ typedef struct {
>
> static void ac_test_show(ac_test_t *at);
>
> +static unsigned long shadow_cr0;
> +static unsigned long shadow_cr4;
> +static unsigned long long shadow_efer;
> +
> static void set_cr0_wp(int wp)
> {
> - unsigned long cr0 = read_cr0();
> - unsigned long old_cr0 = cr0;
> + unsigned long cr0 = shadow_cr0;
>
> cr0 &= ~CR0_WP_MASK;
> if (wp)
> cr0 |= CR0_WP_MASK;
> - if (old_cr0 != cr0)
> + if (cr0 != shadow_cr0) {
> write_cr0(cr0);
> + shadow_cr0 = cr0;
> + }
> }
>
> static unsigned set_cr4_smep(int smep)
> {
> - unsigned long cr4 = read_cr4();
> - unsigned long old_cr4 = cr4;
> + unsigned long cr4 = shadow_cr4;
> extern u64 ptl2[];
> unsigned r;
>
> cr4 &= ~CR4_SMEP_MASK;
> if (smep)
> cr4 |= CR4_SMEP_MASK;
> - if (old_cr4 == cr4)
> + if (cr4 == shadow_cr4)
> return 0;
>
> if (smep)
> @@ -199,37 +203,39 @@ static unsigned set_cr4_smep(int smep)
> r = write_cr4_checking(cr4);
> if (r || !smep)
> ptl2[2] |= PT_USER_MASK;
> + if (!r)
> + shadow_cr4 = cr4;
> return r;
> }
>
> static void set_cr4_pke(int pke)
> {
> - unsigned long cr4 = read_cr4();
> - unsigned long old_cr4 = cr4;
> + unsigned long cr4 = shadow_cr4;
>
> cr4 &= ~X86_CR4_PKE;
> if (pke)
> cr4 |= X86_CR4_PKE;
> - if (old_cr4 == cr4)
> + if (cr4 == shadow_cr4)
> return;
>
> /* Check that protection keys do not affect accesses when CR4.PKE=0. */
> - if ((read_cr4() & X86_CR4_PKE) && !pke) {
> + if ((shadow_cr4 & X86_CR4_PKE) && !pke)
> write_pkru(0xfffffffc);
> - }
> write_cr4(cr4);
> + shadow_cr4 = cr4;
> }
>
> static void set_efer_nx(int nx)
> {
> - unsigned long long efer = rdmsr(MSR_EFER);
> - unsigned long long old_efer = efer;
> + unsigned long long efer = shadow_efer;
>
> efer &= ~EFER_NX_MASK;
> if (nx)
> efer |= EFER_NX_MASK;
> - if (old_efer != efer)
> + if (efer != shadow_efer) {
> wrmsr(MSR_EFER, efer);
> + shadow_efer = efer;
> + }
> }
>
> static void ac_env_int(ac_pool_t *pool)
> @@ -245,7 +251,7 @@ static void ac_env_int(ac_pool_t *pool)
>
> static void ac_test_init(ac_test_t *at, void *virt)
> {
> - wrmsr(MSR_EFER, rdmsr(MSR_EFER) | EFER_NX_MASK);
> + set_efer_nx(1);
> set_cr0_wp(1);
> at->flags = 0;
> at->virt = virt;
> @@ -935,14 +941,17 @@ static int ac_test_run(void)
> printf("run\n");
> tests = successes = 0;
>
> + shadow_cr0 = read_cr0();
> + shadow_cr4 = read_cr4();
> + shadow_efer = rdmsr(MSR_EFER);
> +
> if (this_cpu_has(X86_FEATURE_PKU)) {
> set_cr4_pke(1);
> set_cr4_pke(0);
> /* Now PKRU = 0xFFFFFFFF. */
> } else {
> - unsigned long cr4 = read_cr4();
> tests++;
> - if (write_cr4_checking(cr4 | X86_CR4_PKE) == GP_VECTOR) {
> + if (write_cr4_checking(shadow_cr4 | X86_CR4_PKE) == GP_VECTOR) {
> successes++;
> invalid_mask |= AC_PKU_AD_MASK;
> invalid_mask |= AC_PKU_WD_MASK;
> @@ -996,8 +1005,8 @@ int main(void)
>
> if (this_cpu_has(X86_FEATURE_LA57)) {
> page_table_levels = 5;
> - setup_5level_page_table();
> printf("starting 5-level paging test.\n\n");
> + setup_5level_page_table();
> r = ac_test_run();
> }
>
>
Applied all three patches, thanks.
Paolo
^ permalink raw reply [flat|nested] 2+ messages in thread
end of thread, other threads:[~2020-03-31 15:15 UTC | newest]
Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-03-10 3:54 [kvm-unit-tests PATCH] x86: access: Shadow CR0, CR4 and EFER to avoid unnecessary VM-Exits Sean Christopherson
2020-03-31 15:15 ` Paolo Bonzini
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).