linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
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 v11 7/9] KVM: X86: Add userspace access interface for CET MSRs
Date: Thu, 23 Apr 2020 11:14:06 -0700	[thread overview]
Message-ID: <20200423181406.GK17824@linux.intel.com> (raw)
In-Reply-To: <20200326081847.5870-8-weijiang.yang@intel.com>

On Thu, Mar 26, 2020 at 04:18:44PM +0800, Yang Weijiang wrote:
> +#define CET_MSR_RSVD_BITS_1  GENMASK(1, 0)
> +#define CET_MSR_RSVD_BITS_2  GENMASK(9, 6)
> +
> +static bool cet_check_msr_write(struct kvm_vcpu *vcpu,

s/cet_check_msr_write/is_cet_msr_valid

Otherwise the polarity of the return value isn't obvious.

> +				struct msr_data *msr,

Unnecessary newline.

> +				u64 mask)

s/mask/rsvd_bits

> +{
> +	u64 data = msr->data;
> +	u32 high_word = data >> 32;
> +
> +	if (data & mask)
> +		return false;
> +
> +	if (!is_64_bit_mode(vcpu) && high_word)
> +		return false;

As I called out before, this is wrong.  AFAIK, the CPU never depends on
WRMSR to prevent loading bits 63:32, software can simply do WRMSR and then
transition back to 32-bit mode.  Yes, the shadow stack itself is 32 bits,
but the internal value is still 64 bits.  This is backed up by the CALL
pseudocode:

  IF ShadowStackEnabled(CPL)
    IF (EFER.LMA and DEST(CodeSegmentSelector).L) = 0
      (* If target is legacy or compatibility mode then the SSP must be in low 4GB *)
      IF (SSP & 0xFFFFFFFF00000000 != 0)
        THEN #GP(0); FI;
  FI;

as well as RDSSP:

  IF CPL = 3
    IF CR4.CET & IA32_U_CET.SH_STK_EN
      IF (operand size is 64 bit)
        THEN
          Dest ← SSP;
        ELSE
          Dest ← SSP[31:0];
      FI;
    FI;
  ELSE

> +
> +	return true;
> +}
> +
> +static bool cet_check_ssp_msr_access(struct kvm_vcpu *vcpu,
> +				     struct msr_data *msr)

Similar to above, the polarity of the return isn't obvious.  Maybe
is_cet_ssp_msr_accessible()?

I'd prefer to pass in @index, passing the full @msr makes it look like
this helper might also check msr->data.

> +{
> +	u32 index = msr->index;
> +
> +	if (!boot_cpu_has(X86_FEATURE_SHSTK))
> +		return false;
> +
> +	if (!msr->host_initiated &&
> +	    !guest_cpuid_has(vcpu, X86_FEATURE_SHSTK))
> +		return false;
> +
> +	if (index == MSR_IA32_INT_SSP_TAB)
> +		return true;
> +
> +	if (index == MSR_IA32_PL3_SSP) {
> +		if (!(supported_xss & XFEATURE_MASK_CET_USER))
> +			return false;
> +	} else if (!(supported_xss & XFEATURE_MASK_CET_KERNEL)) {
> +		return false;
> +	}

	if (index == MSR_IA32_PL3_SSP)
		return supported_xss & XFEATURE_MASK_CET_USER;

	/* MSR_IA32_PL[0-2]_SSP */
	return supported_xss & XFEATURE_MASK_CET_KERNEL;
> +
> +	return true;
> +}
> +
> +static bool cet_check_ctl_msr_access(struct kvm_vcpu *vcpu,

is_cet_ctl_msr_accessible?

> +				     struct msr_data *msr)
> +{
> +	u32 index = msr->index;
> +
> +	if (!boot_cpu_has(X86_FEATURE_SHSTK) &&
> +	    !boot_cpu_has(X86_FEATURE_IBT))
> +		return false;
> +
> +	if (!msr->host_initiated &&
> +	    !guest_cpuid_has(vcpu, X86_FEATURE_SHSTK) &&
> +	    !guest_cpuid_has(vcpu, X86_FEATURE_IBT))
> +		return false;
> +
> +	if (index == MSR_IA32_U_CET) {
> +		if (!(supported_xss & XFEATURE_MASK_CET_USER))
> +			return false;
> +	} else if (!(supported_xss & XFEATURE_MASK_CET_KERNEL)) {
> +		return false;
> +	}

Same as above:

	if (index == MSR_IA32_U_CET)
		return supported_xss & XFEATURE_MASK_CET_USER;

	return supported_xss & XFEATURE_MASK_CET_KERNEL;
> +
> +	return true;
> +}
>  /*
>   * Reads an msr value (of 'msr_index') into 'pdata'.
>   * Returns 0 on success, non-0 otherwise.
> @@ -1941,6 +2026,26 @@ static int vmx_get_msr(struct kvm_vcpu *vcpu, struct msr_data *msr_info)
>  		else
>  			msr_info->data = vmx->pt_desc.guest.addr_a[index / 2];
>  		break;
> +	case MSR_IA32_S_CET:
> +		if (!cet_check_ctl_msr_access(vcpu, msr_info))
> +			return 1;
> +		msr_info->data = vmcs_readl(GUEST_S_CET);
> +		break;
> +	case MSR_IA32_INT_SSP_TAB:
> +		if (!cet_check_ssp_msr_access(vcpu, msr_info))
> +			return 1;
> +		msr_info->data = vmcs_readl(GUEST_INTR_SSP_TABLE);
> +		break;
> +	case MSR_IA32_U_CET:
> +		if (!cet_check_ctl_msr_access(vcpu, msr_info))
> +			return 1;
> +		vmx_get_xsave_msr(msr_info);
> +		break;
> +	case MSR_IA32_PL0_SSP ... MSR_IA32_PL3_SSP:
> +		if (!cet_check_ssp_msr_access(vcpu, msr_info))
> +			return 1;
> +		vmx_get_xsave_msr(msr_info);
> +		break;
>  	case MSR_TSC_AUX:
>  		if (!msr_info->host_initiated &&
>  		    !guest_cpuid_has(vcpu, X86_FEATURE_RDTSCP))
> @@ -2197,6 +2302,34 @@ static int vmx_set_msr(struct kvm_vcpu *vcpu, struct msr_data *msr_info)
>  		else
>  			vmx->pt_desc.guest.addr_a[index / 2] = data;
>  		break;
> +	case MSR_IA32_S_CET:
> +		if (!cet_check_ctl_msr_access(vcpu, msr_info))
> +			return 1;
> +		if (!cet_check_msr_write(vcpu, msr_info, CET_MSR_RSVD_BITS_2))
> +			return 1;
> +		vmcs_writel(GUEST_S_CET, data);
> +		break;
> +	case MSR_IA32_INT_SSP_TAB:
> +		if (!cet_check_ctl_msr_access(vcpu, msr_info))
> +			return 1;
> +		if (!is_64_bit_mode(vcpu))

This is wrong, the SDM explicitly calls out the !64 case:

  IA32_INTERRUPT_SSP_TABLE_ADDR (64 bits; 32 bits on processors that do not
  support Intel 64 architecture).

> +			return 1;
> +		vmcs_writel(GUEST_INTR_SSP_TABLE, data);
> +		break;
> +	case MSR_IA32_U_CET:
> +		if (!cet_check_ctl_msr_access(vcpu, msr_info))
> +			return 1;
> +		if (!cet_check_msr_write(vcpu, msr_info, CET_MSR_RSVD_BITS_2))
> +			return 1;
> +		vmx_set_xsave_msr(msr_info);
> +		break;
> +	case MSR_IA32_PL0_SSP ... MSR_IA32_PL3_SSP:
> +		if (!cet_check_ssp_msr_access(vcpu, msr_info))
> +			return 1;
> +		if (!cet_check_msr_write(vcpu, msr_info, CET_MSR_RSVD_BITS_1))
> +			return 1;
> +		vmx_set_xsave_msr(msr_info);
> +		break;
>  	case MSR_TSC_AUX:
>  		if (!msr_info->host_initiated &&
>  		    !guest_cpuid_has(vcpu, X86_FEATURE_RDTSCP))
> diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
> index 9654d779bdab..9e89ee6a09e1 100644
> --- a/arch/x86/kvm/x86.c
> +++ b/arch/x86/kvm/x86.c
> @@ -1229,6 +1229,10 @@ static const u32 msrs_to_save_all[] = {
>  	MSR_ARCH_PERFMON_EVENTSEL0 + 12, MSR_ARCH_PERFMON_EVENTSEL0 + 13,
>  	MSR_ARCH_PERFMON_EVENTSEL0 + 14, MSR_ARCH_PERFMON_EVENTSEL0 + 15,
>  	MSR_ARCH_PERFMON_EVENTSEL0 + 16, MSR_ARCH_PERFMON_EVENTSEL0 + 17,
> +
> +	MSR_IA32_XSS, MSR_IA32_U_CET, MSR_IA32_S_CET,
> +	MSR_IA32_PL0_SSP, MSR_IA32_PL1_SSP, MSR_IA32_PL2_SSP,
> +	MSR_IA32_PL3_SSP, MSR_IA32_INT_SSP_TAB,
>  };
>  
>  static u32 msrs_to_save[ARRAY_SIZE(msrs_to_save_all)];
> @@ -1504,6 +1508,13 @@ static int __kvm_set_msr(struct kvm_vcpu *vcpu, u32 index, u64 data,
>  		 * invokes 64-bit SYSENTER.
>  		 */
>  		data = get_canonical(data, vcpu_virt_addr_bits(vcpu));
> +		break;
> +	case MSR_IA32_PL0_SSP ... MSR_IA32_PL3_SSP:
> +	case MSR_IA32_U_CET:
> +	case MSR_IA32_S_CET:
> +	case MSR_IA32_INT_SSP_TAB:
> +		if (is_noncanonical_address(data, vcpu))

IMO the canonical check belongs in cet_check_msr_write().  The above checks
are for MSRs that are common to VMX and SVM, i.e. the common check saves
having to duplicate the logic.  If SVM picks up CET support, then they'll
presumably want to share all of the checks, not just the canonical piece.

> +			return 1;
>  	}
>  
>  	msr.data = data;
> -- 
> 2.17.2
> 

  parent reply	other threads:[~2020-04-23 18:14 UTC|newest]

Thread overview: 57+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2020-03-26  8:18 [PATCH v11 0/9] Introduce support for guest CET feature Yang Weijiang
2020-03-26  8:18 ` [PATCH v11 1/9] KVM: VMX: Introduce CET VMX fields and flags Yang Weijiang
2020-04-23 16:07   ` Sean Christopherson
2020-04-24 13:39     ` Yang Weijiang
2020-04-23 16:39   ` Sean Christopherson
2020-04-24 13:44     ` Yang Weijiang
2020-03-26  8:18 ` [PATCH v11 2/9] KVM: VMX: Set guest CET MSRs per KVM and host configuration Yang Weijiang
2020-04-23 16:27   ` Sean Christopherson
2020-04-24 14:07     ` Yang Weijiang
2020-04-24 14:55       ` Sean Christopherson
2020-04-25  9:14         ` Yang Weijiang
2020-04-25 13:26     ` Paolo Bonzini
2020-04-26 15:26       ` Yang Weijiang
2020-03-26  8:18 ` [PATCH v11 3/9] KVM: VMX: Set host/guest CET states for vmexit/vmentry Yang Weijiang
2020-04-01  2:23   ` kbuild test robot
2020-04-23 17:17   ` Sean Christopherson
2020-04-24 14:35     ` Yang Weijiang
2020-04-24 14:49       ` Sean Christopherson
2020-04-25  9:20         ` Yang Weijiang
2020-04-27 17:04           ` Sean Christopherson
2020-04-27 17:56             ` Sean Christopherson
2020-03-26  8:18 ` [PATCH v11 4/9] KVM: VMX: Check CET dependencies on CR settings Yang Weijiang
2020-04-23 17:20   ` Sean Christopherson
2020-04-24 14:36     ` Yang Weijiang
2020-03-26  8:18 ` [PATCH v11 5/9] KVM: X86: Refresh CPUID once guest XSS MSR changes Yang Weijiang
2020-04-01  3:50   ` kbuild test robot
2020-04-23 17:34   ` Sean Christopherson
2020-04-24 14:47     ` Yang Weijiang
2020-04-25 13:19     ` Paolo Bonzini
2020-04-26 15:01       ` Yang Weijiang
2020-03-26  8:18 ` [PATCH v11 6/9] KVM: X86: Load guest fpu state when access MSRs managed by XSAVES Yang Weijiang
2020-03-26  8:18 ` [PATCH v11 7/9] KVM: X86: Add userspace access interface for CET MSRs Yang Weijiang
2020-03-28  7:40   ` kbuild test robot
2020-04-01  4:54   ` kbuild test robot
2020-04-23 18:14   ` Sean Christopherson [this message]
2020-04-24 15:02     ` Yang Weijiang
2020-04-24 15:10       ` Sean Christopherson
2020-04-25  9:28         ` Yang Weijiang
2020-04-25 15:31   ` Paolo Bonzini
2020-04-26 15:23     ` Yang Weijiang
2020-04-27 14:04       ` Paolo Bonzini
2020-04-28 13:41         ` Yang Weijiang
2020-03-26  8:18 ` [PATCH v11 8/9] KVM: VMX: Enable CET support for nested VM Yang Weijiang
2020-04-01  6:11   ` kbuild test robot
2020-04-23 18:29   ` Sean Christopherson
2020-04-24 15:24     ` Yang Weijiang
2020-03-26  8:18 ` [PATCH v11 9/9] KVM: X86: Set CET feature bits for CPUID enumeration Yang Weijiang
2020-03-27  4:41   ` kbuild test robot
2020-04-23 16:56   ` Sean Christopherson
2020-04-24 14:17     ` Yang Weijiang
2020-04-23 16:58   ` Sean Christopherson
2020-04-24 14:23     ` Yang Weijiang
2020-03-26  8:18 ` [kvm-unit-tests PATCH] x86: Add tests for user-mode CET Yang Weijiang
2020-04-23 15:51 ` [PATCH v11 0/9] Introduce support for guest CET feature Sean Christopherson
2020-04-24 13:31   ` Yang Weijiang
2020-04-23 16:03 ` Sean Christopherson
2020-04-24 13:34   ` 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=20200423181406.GK17824@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 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).