From: Sean Christopherson <seanjc@google.com>
To: Jon Kohler <jon@nutanix.com>
Cc: Paolo Bonzini <pbonzini@redhat.com>,
Vitaly Kuznetsov <vkuznets@redhat.com>,
Wanpeng Li <wanpengli@tencent.com>,
Jim Mattson <jmattson@google.com>, Joerg Roedel <joro@8bytes.org>,
Thomas Gleixner <tglx@linutronix.de>,
Ingo Molnar <mingo@redhat.com>, Borislav Petkov <bp@alien8.de>,
Dave Hansen <dave.hansen@linux.intel.com>,
x86@kernel.org, "H. Peter Anvin" <hpa@zytor.com>,
kvm@vger.kernel.org, linux-kernel@vger.kernel.org
Subject: Re: [PATCH] KVM: x86: optimize PKU branching in kvm_load_{guest|host}_xsave_state
Date: Sat, 26 Mar 2022 00:15:07 +0000 [thread overview]
Message-ID: <Yj5bCw0q5n4ZgSuU@google.com> (raw)
In-Reply-To: <20220324004439.6709-1-jon@nutanix.com>
On Wed, Mar 23, 2022, Jon Kohler wrote:
> kvm_load_{guest|host}_xsave_state handles xsave on vm entry and exit,
> part of which is managing memory protection key state. The latest
> arch.pkru is updated with a rdpkru, and if that doesn't match the base
> host_pkru (which about 70% of the time), we issue a __write_pkru.
>
> To improve performance, implement the following optimizations:
> 1. Reorder if conditions prior to wrpkru in both
> kvm_load_{guest|host}_xsave_state.
>
> Flip the ordering of the || condition so that XFEATURE_MASK_PKRU is
> checked first, which when instrumented in our environment appeared
> to be always true and less overall work than kvm_read_cr4_bits.
If it's always true, then it should be checked last, not first. And if
kvm_read_cr4_bits() is more expensive then we should address that issue, not
try to micro-optimize this stuff. X86_CR4_PKE can't be guest-owned, and so
kvm_read_cr4_bits() should be optimized down to:
return vcpu->arch.cr4 & X86_CR4_PKE;
If the compiler isn't smart enough to do that on its own then we should rework
kvm_read_cr4_bits() as that will benefit multiple code paths.
> For kvm_load_guest_xsave_state, hoist arch.pkru != host_pkru ahead
> one position. When instrumented, I saw this be true roughly ~70% of
> the time vs the other conditions which were almost always true.
> With this change, we will avoid 3rd condition check ~30% of the time.
If the guest uses PKRU... If PKRU is used by the host but not the guest, the
early comparison is pure overhead because it will almost always be true (guest
will be zero, host will non-zero),
> 2. Wrap PKU sections with CONFIG_X86_INTEL_MEMORY_PROTECTION_KEYS,
> as if the user compiles out this feature, we should not have
> these branches at all.
Not that it really matters, since static_cpu_has() will patch out all the branches,
and in practice who cares about a JMP or NOP(s)? But...
#ifdeffery is the wrong way to handle this. Replace static_cpu_has() with
cpu_feature_enabled(); that'll boil down to a '0' and omit all the code when
CONFIG_X86_INTEL_MEMORY_PROTECTION_KEYS=n, without the #ifdef ugliness.
> Signed-off-by: Jon Kohler <jon@nutanix.com>
> ---
> arch/x86/kvm/x86.c | 14 +++++++++-----
> 1 file changed, 9 insertions(+), 5 deletions(-)
>
> diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
> index 6db3a506b402..2b00123a5d50 100644
> --- a/arch/x86/kvm/x86.c
> +++ b/arch/x86/kvm/x86.c
> @@ -950,11 +950,13 @@ void kvm_load_guest_xsave_state(struct kvm_vcpu *vcpu)
> wrmsrl(MSR_IA32_XSS, vcpu->arch.ia32_xss);
> }
>
> +#ifdef CONFIG_X86_INTEL_MEMORY_PROTECTION_KEYS
> if (static_cpu_has(X86_FEATURE_PKU) &&
> - (kvm_read_cr4_bits(vcpu, X86_CR4_PKE) ||
> - (vcpu->arch.xcr0 & XFEATURE_MASK_PKRU)) &&
> - vcpu->arch.pkru != vcpu->arch.host_pkru)
> + vcpu->arch.pkru != vcpu->arch.host_pkru &&
> + ((vcpu->arch.xcr0 & XFEATURE_MASK_PKRU) ||
> + kvm_read_cr4_bits(vcpu, X86_CR4_PKE)))
> write_pkru(vcpu->arch.pkru);
> +#endif /* CONFIG_X86_INTEL_MEMORY_PROTECTION_KEYS */
> }
> EXPORT_SYMBOL_GPL(kvm_load_guest_xsave_state);
>
> @@ -963,13 +965,15 @@ void kvm_load_host_xsave_state(struct kvm_vcpu *vcpu)
> if (vcpu->arch.guest_state_protected)
> return;
>
> +#ifdef CONFIG_X86_INTEL_MEMORY_PROTECTION_KEYS
> if (static_cpu_has(X86_FEATURE_PKU) &&
> - (kvm_read_cr4_bits(vcpu, X86_CR4_PKE) ||
> - (vcpu->arch.xcr0 & XFEATURE_MASK_PKRU))) {
> + ((vcpu->arch.xcr0 & XFEATURE_MASK_PKRU) ||
> + kvm_read_cr4_bits(vcpu, X86_CR4_PKE))) {
> vcpu->arch.pkru = rdpkru();
> if (vcpu->arch.pkru != vcpu->arch.host_pkru)
> write_pkru(vcpu->arch.host_pkru);
> }
> +#endif /* CONFIG_X86_INTEL_MEMORY_PROTECTION_KEYS */
>
> if (kvm_read_cr4_bits(vcpu, X86_CR4_OSXSAVE)) {
>
> --
> 2.30.1 (Apple Git-130)
>
next prev parent reply other threads:[~2022-03-26 0:15 UTC|newest]
Thread overview: 7+ messages / expand[flat|nested] mbox.gz Atom feed top
2022-03-24 0:44 [PATCH] KVM: x86: optimize PKU branching in kvm_load_{guest|host}_xsave_state Jon Kohler
2022-03-25 11:01 ` Paolo Bonzini
2022-03-26 0:15 ` Sean Christopherson [this message]
2022-03-26 1:37 ` Jon Kohler
2022-03-27 10:43 ` Paolo Bonzini
2022-03-28 0:53 ` Jon Kohler
2022-03-28 14:51 ` Sean Christopherson
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=Yj5bCw0q5n4ZgSuU@google.com \
--to=seanjc@google.com \
--cc=bp@alien8.de \
--cc=dave.hansen@linux.intel.com \
--cc=hpa@zytor.com \
--cc=jmattson@google.com \
--cc=jon@nutanix.com \
--cc=joro@8bytes.org \
--cc=kvm@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=mingo@redhat.com \
--cc=pbonzini@redhat.com \
--cc=tglx@linutronix.de \
--cc=vkuznets@redhat.com \
--cc=wanpengli@tencent.com \
--cc=x86@kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox