From: Sean Christopherson <sean.j.christopherson@intel.com>
To: Yang Weijiang <weijiang.yang@intel.com>
Cc: kvm@vger.kernel.org, linux-kernel@vger.kernel.org,
pbonzini@redhat.com, jmattson@google.com,
yu.c.zhang@linux.intel.com
Subject: Re: [PATCH v9 4/7] KVM: VMX: Load CET states on vmentry/vmexit
Date: Tue, 3 Mar 2020 14:06:18 -0800 [thread overview]
Message-ID: <20200303220618.GB1439@linux.intel.com> (raw)
In-Reply-To: <20191227021133.11993-5-weijiang.yang@intel.com>
On Fri, Dec 27, 2019 at 10:11:30AM +0800, Yang Weijiang wrote:
> "Load {guest,host} CET state" bit controls whether guest/host
> CET states will be loaded at VM entry/exit. Before doing that,
> KVM needs to check if CET can be enabled both on host and guest.
>
> Note:
> 1)The processor does not allow CR4.CET to be set if CR0.WP = 0,
> similarly, it does not allow CR0.WP to be cleared while CR4.CET = 1.
> In either case, KVM would inject #GP to guest.
>
> 2)SHSTK and IBT features share one control MSR:
> MSR_IA32_{U,S}_CET, which means it's difficult to hide
> one feature from another in the case of SHSTK != IBT,
> after discussed in community, it's agreed to allow Guest
> control two features independently as it won't introduce
> security hole.
>
> Co-developed-by: Zhang Yi Z <yi.z.zhang@linux.intel.com>
> Signed-off-by: Zhang Yi Z <yi.z.zhang@linux.intel.com>
> Signed-off-by: Yang Weijiang <weijiang.yang@intel.com>
> ---
> arch/x86/kvm/vmx/capabilities.h | 10 ++++++
> arch/x86/kvm/vmx/vmx.c | 56 +++++++++++++++++++++++++++++++--
> arch/x86/kvm/x86.c | 3 ++
> 3 files changed, 67 insertions(+), 2 deletions(-)
>
> diff --git a/arch/x86/kvm/vmx/capabilities.h b/arch/x86/kvm/vmx/capabilities.h
> index 7aa69716d516..4a67d35a42a2 100644
> --- a/arch/x86/kvm/vmx/capabilities.h
> +++ b/arch/x86/kvm/vmx/capabilities.h
> @@ -106,6 +106,16 @@ static inline bool vmx_mpx_supported(void)
> (vmcs_config.vmentry_ctrl & VM_ENTRY_LOAD_BNDCFGS);
> }
>
> +static inline bool cpu_has_load_guest_cet_states_ctrl(void)
> +{
> + return ((vmcs_config.vmentry_ctrl) & VM_ENTRY_LOAD_GUEST_CET_STATE);
> +}
> +
> +static inline bool cpu_has_load_host_cet_states_ctrl(void)
> +{
> + return ((vmcs_config.vmexit_ctrl) & VM_EXIT_LOAD_HOST_CET_STATE);
No need for parantheses around vmcs_config.vmexit_ctrl.
> +}
> +
> static inline bool cpu_has_vmx_tpr_shadow(void)
> {
> return vmcs_config.cpu_based_exec_ctrl & CPU_BASED_TPR_SHADOW;
> diff --git a/arch/x86/kvm/vmx/vmx.c b/arch/x86/kvm/vmx/vmx.c
> index 61fc846c7ef3..95063cc7da89 100644
> --- a/arch/x86/kvm/vmx/vmx.c
> +++ b/arch/x86/kvm/vmx/vmx.c
> @@ -44,6 +44,7 @@
> #include <asm/spec-ctrl.h>
> #include <asm/virtext.h>
> #include <asm/vmx.h>
> +#include <asm/cet.h>
>
> #include "capabilities.h"
> #include "cpuid.h"
> @@ -2445,7 +2446,8 @@ static __init int setup_vmcs_config(struct vmcs_config *vmcs_conf,
> VM_EXIT_LOAD_IA32_EFER |
> VM_EXIT_CLEAR_BNDCFGS |
> VM_EXIT_PT_CONCEAL_PIP |
> - VM_EXIT_CLEAR_IA32_RTIT_CTL;
> + VM_EXIT_CLEAR_IA32_RTIT_CTL |
> + VM_EXIT_LOAD_HOST_CET_STATE;
> if (adjust_vmx_controls(min, opt, MSR_IA32_VMX_EXIT_CTLS,
> &_vmexit_control) < 0)
> return -EIO;
> @@ -2469,7 +2471,8 @@ static __init int setup_vmcs_config(struct vmcs_config *vmcs_conf,
> VM_ENTRY_LOAD_IA32_EFER |
> VM_ENTRY_LOAD_BNDCFGS |
> VM_ENTRY_PT_CONCEAL_PIP |
> - VM_ENTRY_LOAD_IA32_RTIT_CTL;
> + VM_ENTRY_LOAD_IA32_RTIT_CTL |
> + VM_ENTRY_LOAD_GUEST_CET_STATE;
> if (adjust_vmx_controls(min, opt, MSR_IA32_VMX_ENTRY_CTLS,
> &_vmentry_control) < 0)
> return -EIO;
> @@ -3027,6 +3030,25 @@ void vmx_set_cr3(struct kvm_vcpu *vcpu, unsigned long cr3)
> vmcs_writel(GUEST_CR3, guest_cr3);
> }
>
> +bool is_cet_bit_allowed(struct kvm_vcpu *vcpu)
This should be static. I'd also include cr4 in the name, e.g.
static bool is_cr4_set_allowed(...)
> +{
> + u64 kvm_xss = kvm_supported_xss();
> + unsigned long cr0;
> + bool cet_allowed;
> +
> + cr0 = kvm_read_cr0(vcpu);
> +
> + /* Right now, only user-mode CET is supported.*/
> + cet_allowed = (kvm_xss & XFEATURE_MASK_CET_USER) &&
> + (guest_cpuid_has(vcpu, X86_FEATURE_SHSTK) ||
> + guest_cpuid_has(vcpu, X86_FEATURE_IBT));
Probably makes sense to add a "is_cet_supported()" helper. That'd reduce
the amount of copy+paste and would probably add clarity to most flows.
> +
> + if ((cr0 & X86_CR0_WP) && cet_allowed)
> + return true;
> +
> + return false;
return (cr0 & X86_CR0_WP) && cet_allowed;
Even better, especially if you add is_cet_supported(), to avoid VMREAD of
CR0 when CET isn't supported.
return is_cet_supported() && (kvm_read_cr0(vcpu) & X86_CR0_WP);
At that point, you can probably even forgo the helper, e.g.
if ((cr4 & X86_CR4_CET) &&
(!is_cet_supported() || !(kvm_read_cr0(vcpu) & X86_CR0_WP)))
return 1;
> +}
> +
> int vmx_set_cr4(struct kvm_vcpu *vcpu, unsigned long cr4)
> {
> struct vcpu_vmx *vmx = to_vmx(vcpu);
> @@ -3067,6 +3089,9 @@ int vmx_set_cr4(struct kvm_vcpu *vcpu, unsigned long cr4)
> return 1;
> }
>
> + if ((cr4 & X86_CR4_CET) && !is_cet_bit_allowed(vcpu))
> + return 1;
> +
> if (vmx->nested.vmxon && !nested_cr4_valid(vcpu, cr4))
> return 1;
>
> @@ -3930,6 +3955,12 @@ void vmx_set_constant_host_state(struct vcpu_vmx *vmx)
>
> if (cpu_has_load_ia32_efer())
> vmcs_write64(HOST_IA32_EFER, host_efer);
> +
> + if (cpu_has_load_host_cet_states_ctrl()) {
> + vmcs_writel(HOST_S_CET, 0);
> + vmcs_writel(HOST_INTR_SSP_TABLE, 0);
> + vmcs_writel(HOST_SSP, 0);
> + }
> }
>
> void set_cr4_guest_host_mask(struct vcpu_vmx *vmx)
> @@ -6499,7 +6530,9 @@ bool __vmx_vcpu_run(struct vcpu_vmx *vmx, unsigned long *regs, bool launched);
> static void vmx_vcpu_run(struct kvm_vcpu *vcpu)
> {
> struct vcpu_vmx *vmx = to_vmx(vcpu);
> + u64 kvm_xss = kvm_supported_xss();
> unsigned long cr3, cr4;
> + bool cet_allowed;
>
> /* Record the guest's net vcpu time for enforced NMI injections. */
> if (unlikely(!enable_vnmi &&
> @@ -6530,6 +6563,25 @@ static void vmx_vcpu_run(struct kvm_vcpu *vcpu)
> vmx->loaded_vmcs->host_state.cr3 = cr3;
> }
>
> + /* Right now, only user-mode CET is supported.*/
> + cet_allowed = (kvm_xss & XFEATURE_MASK_CET_USER) &&
> + (guest_cpuid_has(vcpu, X86_FEATURE_SHSTK) ||
> + guest_cpuid_has(vcpu, X86_FEATURE_IBT));
> +
> + if (cpu_has_load_guest_cet_states_ctrl() && cet_allowed)
> + vmcs_set_bits(VM_ENTRY_CONTROLS,
> + VM_ENTRY_LOAD_GUEST_CET_STATE);
> + else
> + vmcs_clear_bits(VM_ENTRY_CONTROLS,
> + VM_ENTRY_LOAD_GUEST_CET_STATE);
> +
> + if (cpu_has_load_host_cet_states_ctrl() && cet_allowed)
> + vmcs_set_bits(VM_EXIT_CONTROLS,
> + VM_EXIT_LOAD_HOST_CET_STATE);
> + else
> + vmcs_clear_bits(VM_EXIT_CONTROLS,
> + VM_EXIT_LOAD_HOST_CET_STATE);
Why are you clearing VMCS bits in vmx_vcpu_run()? Unless I'm missing
something, these can go in vmx_cpuid_update().
> +
> cr4 = cr4_read_shadow();
> if (unlikely(cr4 != vmx->loaded_vmcs->host_state.cr4)) {
> vmcs_writel(HOST_CR4, cr4);
> diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
> index a9b1140d0508..b27d97eaec24 100644
> --- a/arch/x86/kvm/x86.c
> +++ b/arch/x86/kvm/x86.c
> @@ -788,6 +788,9 @@ int kvm_set_cr0(struct kvm_vcpu *vcpu, unsigned long cr0)
> if (!(cr0 & X86_CR0_PG) && kvm_read_cr4_bits(vcpu, X86_CR4_PCIDE))
> return 1;
>
> + if (!(cr0 & X86_CR0_WP) && kvm_read_cr4_bits(vcpu, X86_CR4_CET))
> + return 1;
> +
> kvm_x86_ops->set_cr0(vcpu, cr0);
>
> if ((cr0 ^ old_cr0) & X86_CR0_PG) {
> --
> 2.17.2
>
next prev parent reply other threads:[~2020-03-03 22:06 UTC|newest]
Thread overview: 20+ messages / expand[flat|nested] mbox.gz Atom feed top
2019-12-27 2:11 [PATCH v9 0/7] Introduce support for guest CET feature Yang Weijiang
2019-12-27 2:11 ` [PATCH v9 1/7] KVM: CPUID: Fix IA32_XSS support in CPUID(0xd,i) enumeration Yang Weijiang
2020-03-05 14:51 ` Paolo Bonzini
2020-03-06 0:38 ` Yang Weijiang
2019-12-27 2:11 ` [PATCH v9 2/7] KVM: VMX: Define CET VMCS fields and #CP flag Yang Weijiang
2020-03-03 21:42 ` Sean Christopherson
2020-03-04 8:44 ` Yang Weijiang
2019-12-27 2:11 ` [PATCH v9 3/7] KVM: VMX: Pass through CET related MSRs Yang Weijiang
2020-03-03 21:51 ` Sean Christopherson
2020-03-04 8:46 ` Yang Weijiang
2019-12-27 2:11 ` [PATCH v9 4/7] KVM: VMX: Load CET states on vmentry/vmexit Yang Weijiang
2020-03-03 22:06 ` Sean Christopherson [this message]
2020-03-04 8:55 ` Yang Weijiang
2019-12-27 2:11 ` [PATCH v9 5/7] KVM: X86: Enable CET bits update in IA32_XSS Yang Weijiang
2019-12-27 2:11 ` [PATCH v9 6/7] KVM: X86: Load guest fpu state when accessing MSRs managed by XSAVES Yang Weijiang
2019-12-27 2:11 ` [PATCH v9 7/7] KVM: X86: Add user-space access interface for CET MSRs Yang Weijiang
2020-03-03 22:28 ` Sean Christopherson
2020-03-04 15:18 ` Yang Weijiang
2020-03-04 15:45 ` Sean Christopherson
2020-03-05 12:31 ` Yang Weijiang
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=20200303220618.GB1439@linux.intel.com \
--to=sean.j.christopherson@intel.com \
--cc=jmattson@google.com \
--cc=kvm@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=pbonzini@redhat.com \
--cc=weijiang.yang@intel.com \
--cc=yu.c.zhang@linux.intel.com \
/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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.