diff mbox series

[2/2] KVM: x86: Emulate MSR_IA32_ARCH_CAPABILITIES on AMD hosts

Message ID 20190307234302.4092-3-sean.j.christopherson@intel.com (mailing list archive)
State New, archived
Headers show
Series KVM: x86: fix ARCH_CAPBILITIES emulation | expand

Commit Message

Sean Christopherson March 7, 2019, 11:43 p.m. UTC
The CPUID flag ARCH_CAPABILITIES is unconditioinally exposed to host
userspace for all x86 hosts, i.e. KVM advertises ARCH_CAPABILITIES
regardless of hardware support under the pretense that KVM fully
emulates MSR_IA32_ARCH_CAPABILITIES.  Unfortunately, only VMX hosts
handle accesses to MSR_IA32_ARCH_CAPABILITIES (despite KVM_GET_MSRS
also reporting MSR_IA32_ARCH_CAPABILITIES for all hosts).

Move the MSR_IA32_ARCH_CAPABILITIES handling to common x86 code so
that it's emulated on AMD hosts.

Fixes: 1eaafe91a0df4 ("kvm: x86: IA32_ARCH_CAPABILITIES is always supported")
Reported-by: Xiaoyao Li <xiaoyao.li@linux.intel.com>
Cc: Jim Mattson <jmattson@google.com>
Signed-off-by: Sean Christopherson <sean.j.christopherson@intel.com>
---
 arch/x86/include/asm/kvm_host.h |  1 +
 arch/x86/kvm/vmx/vmx.c          | 14 --------------
 arch/x86/kvm/vmx/vmx.h          |  1 -
 arch/x86/kvm/x86.c              | 13 +++++++++++++
 4 files changed, 14 insertions(+), 15 deletions(-)

Comments

Sean Christopherson March 8, 2019, 3:32 p.m. UTC | #1
On Thu, Mar 07, 2019 at 03:43:02PM -0800, Sean Christopherson wrote:
> The CPUID flag ARCH_CAPABILITIES is unconditioinally exposed to host
> userspace for all x86 hosts, i.e. KVM advertises ARCH_CAPABILITIES
> regardless of hardware support under the pretense that KVM fully
> emulates MSR_IA32_ARCH_CAPABILITIES.  Unfortunately, only VMX hosts
> handle accesses to MSR_IA32_ARCH_CAPABILITIES (despite KVM_GET_MSRS
> also reporting MSR_IA32_ARCH_CAPABILITIES for all hosts).
> 
> Move the MSR_IA32_ARCH_CAPABILITIES handling to common x86 code so
> that it's emulated on AMD hosts.
> 
> Fixes: 1eaafe91a0df4 ("kvm: x86: IA32_ARCH_CAPABILITIES is always supported")

And this one should have:

  Cc: stable@vger.kernel.org 

> Reported-by: Xiaoyao Li <xiaoyao.li@linux.intel.com>
> Cc: Jim Mattson <jmattson@google.com>
> Signed-off-by: Sean Christopherson <sean.j.christopherson@intel.com>
> ---
>  arch/x86/include/asm/kvm_host.h |  1 +
>  arch/x86/kvm/vmx/vmx.c          | 14 --------------
>  arch/x86/kvm/vmx/vmx.h          |  1 -
>  arch/x86/kvm/x86.c              | 13 +++++++++++++
>  4 files changed, 14 insertions(+), 15 deletions(-)
> 
> diff --git a/arch/x86/include/asm/kvm_host.h b/arch/x86/include/asm/kvm_host.h
> index 7712b4ed8aa1..3d10ff38cbdb 100644
> --- a/arch/x86/include/asm/kvm_host.h
> +++ b/arch/x86/include/asm/kvm_host.h
> @@ -568,6 +568,7 @@ struct kvm_vcpu_arch {
>  	bool tpr_access_reporting;
>  	u64 ia32_xss;
>  	u64 microcode_version;
> +	u64 arch_capabilities;
>  
>  	/*
>  	 * Paging state of the vcpu
> diff --git a/arch/x86/kvm/vmx/vmx.c b/arch/x86/kvm/vmx/vmx.c
> index 2a86d296c90f..02cf8a551bd1 100644
> --- a/arch/x86/kvm/vmx/vmx.c
> +++ b/arch/x86/kvm/vmx/vmx.c
> @@ -1682,12 +1682,6 @@ static int vmx_get_msr(struct kvm_vcpu *vcpu, struct msr_data *msr_info)
>  
>  		msr_info->data = to_vmx(vcpu)->spec_ctrl;
>  		break;
> -	case MSR_IA32_ARCH_CAPABILITIES:
> -		if (!msr_info->host_initiated &&
> -		    !guest_cpuid_has(vcpu, X86_FEATURE_ARCH_CAPABILITIES))
> -			return 1;
> -		msr_info->data = to_vmx(vcpu)->arch_capabilities;
> -		break;
>  	case MSR_IA32_SYSENTER_CS:
>  		msr_info->data = vmcs_read32(GUEST_SYSENTER_CS);
>  		break;
> @@ -1894,12 +1888,6 @@ static int vmx_set_msr(struct kvm_vcpu *vcpu, struct msr_data *msr_info)
>  		vmx_disable_intercept_for_msr(vmx->vmcs01.msr_bitmap, MSR_IA32_PRED_CMD,
>  					      MSR_TYPE_W);
>  		break;
> -	case MSR_IA32_ARCH_CAPABILITIES:
> -		if (!msr_info->host_initiated ||
> -		    (data & ~kvm_get_arch_capabilities()))
> -			return 1;
> -		vmx->arch_capabilities = data;
> -		break;
>  	case MSR_IA32_CR_PAT:
>  		if (vmcs_config.vmentry_ctrl & VM_ENTRY_LOAD_IA32_PAT) {
>  			if (!kvm_mtrr_valid(vcpu, MSR_IA32_CR_PAT, data))
> @@ -4088,8 +4076,6 @@ static void vmx_vcpu_setup(struct vcpu_vmx *vmx)
>  		++vmx->nmsrs;
>  	}
>  
> -	vmx->arch_capabilities = kvm_get_arch_capabilities();
> -
>  	vm_exit_controls_init(vmx, vmx_vmexit_ctrl());
>  
>  	/* 22.2.1, 20.8.1 */
> diff --git a/arch/x86/kvm/vmx/vmx.h b/arch/x86/kvm/vmx/vmx.h
> index 1554cb45b393..a1e00d0a2482 100644
> --- a/arch/x86/kvm/vmx/vmx.h
> +++ b/arch/x86/kvm/vmx/vmx.h
> @@ -190,7 +190,6 @@ struct vcpu_vmx {
>  	u64		      msr_guest_kernel_gs_base;
>  #endif
>  
> -	u64		      arch_capabilities;
>  	u64		      spec_ctrl;
>  
>  	u32 vm_entry_controls_shadow;
> diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
> index d90f011f3e32..7bfeebc482c4 100644
> --- a/arch/x86/kvm/x86.c
> +++ b/arch/x86/kvm/x86.c
> @@ -2443,6 +2443,12 @@ int kvm_set_msr_common(struct kvm_vcpu *vcpu, struct msr_data *msr_info)
>  		if (msr_info->host_initiated)
>  			vcpu->arch.microcode_version = data;
>  		break;
> +	case MSR_IA32_ARCH_CAPABILITIES:
> +		if (!msr_info->host_initiated ||
> +		    (data & ~kvm_get_arch_capabilities()))
> +			return 1;
> +		vcpu->arch.arch_capabilities = data;
> +		break;
>  	case MSR_EFER:
>  		return set_efer(vcpu, data);
>  	case MSR_K7_HWCR:
> @@ -2747,6 +2753,12 @@ int kvm_get_msr_common(struct kvm_vcpu *vcpu, struct msr_data *msr_info)
>  	case MSR_IA32_UCODE_REV:
>  		msr_info->data = vcpu->arch.microcode_version;
>  		break;
> +	case MSR_IA32_ARCH_CAPABILITIES:
> +		if (!msr_info->host_initiated &&
> +		    !guest_cpuid_has(vcpu, X86_FEATURE_ARCH_CAPABILITIES))
> +			return 1;
> +		msr_info->data = vcpu->arch.arch_capabilities;
> +		break;
>  	case MSR_IA32_TSC:
>  		msr_info->data = kvm_scale_tsc(vcpu, rdtsc()) + vcpu->arch.tsc_offset;
>  		break;
> @@ -8743,6 +8755,7 @@ struct kvm_vcpu *kvm_arch_vcpu_create(struct kvm *kvm,
>  
>  int kvm_arch_vcpu_setup(struct kvm_vcpu *vcpu)
>  {
> +	vcpu->arch.arch_capabilities = kvm_get_arch_capabilities();
>  	vcpu->arch.msr_platform_info = MSR_PLATFORM_INFO_CPUID_FAULT;
>  	kvm_vcpu_mtrr_init(vcpu);
>  	vcpu_load(vcpu);
> -- 
> 2.21.0
>
Jim Mattson March 11, 2019, 9:59 p.m. UTC | #2
On Fri, Mar 8, 2019 at 7:32 AM Sean Christopherson
<sean.j.christopherson@intel.com> wrote:
>
> On Thu, Mar 07, 2019 at 03:43:02PM -0800, Sean Christopherson wrote:
> > The CPUID flag ARCH_CAPABILITIES is unconditioinally exposed to host
> > userspace for all x86 hosts, i.e. KVM advertises ARCH_CAPABILITIES
> > regardless of hardware support under the pretense that KVM fully
> > emulates MSR_IA32_ARCH_CAPABILITIES.  Unfortunately, only VMX hosts
> > handle accesses to MSR_IA32_ARCH_CAPABILITIES (despite KVM_GET_MSRS
> > also reporting MSR_IA32_ARCH_CAPABILITIES for all hosts).
> >
> > Move the MSR_IA32_ARCH_CAPABILITIES handling to common x86 code so
> > that it's emulated on AMD hosts.
> >
> > Fixes: 1eaafe91a0df4 ("kvm: x86: IA32_ARCH_CAPABILITIES is always supported")
>
> And this one should have:
>
>   Cc: stable@vger.kernel.org
>
> > Reported-by: Xiaoyao Li <xiaoyao.li@linux.intel.com>
> > Cc: Jim Mattson <jmattson@google.com>
> > Signed-off-by: Sean Christopherson <sean.j.christopherson@intel.com>
> > ---
> >  arch/x86/include/asm/kvm_host.h |  1 +
> >  arch/x86/kvm/vmx/vmx.c          | 14 --------------
> >  arch/x86/kvm/vmx/vmx.h          |  1 -
> >  arch/x86/kvm/x86.c              | 13 +++++++++++++
> >  4 files changed, 14 insertions(+), 15 deletions(-)
> >
> > diff --git a/arch/x86/include/asm/kvm_host.h b/arch/x86/include/asm/kvm_host.h
> > index 7712b4ed8aa1..3d10ff38cbdb 100644
> > --- a/arch/x86/include/asm/kvm_host.h
> > +++ b/arch/x86/include/asm/kvm_host.h
> > @@ -568,6 +568,7 @@ struct kvm_vcpu_arch {
> >       bool tpr_access_reporting;
> >       u64 ia32_xss;
> >       u64 microcode_version;
> > +     u64 arch_capabilities;
> >
> >       /*
> >        * Paging state of the vcpu
> > diff --git a/arch/x86/kvm/vmx/vmx.c b/arch/x86/kvm/vmx/vmx.c
> > index 2a86d296c90f..02cf8a551bd1 100644
> > --- a/arch/x86/kvm/vmx/vmx.c
> > +++ b/arch/x86/kvm/vmx/vmx.c
> > @@ -1682,12 +1682,6 @@ static int vmx_get_msr(struct kvm_vcpu *vcpu, struct msr_data *msr_info)
> >
> >               msr_info->data = to_vmx(vcpu)->spec_ctrl;
> >               break;
> > -     case MSR_IA32_ARCH_CAPABILITIES:
> > -             if (!msr_info->host_initiated &&
> > -                 !guest_cpuid_has(vcpu, X86_FEATURE_ARCH_CAPABILITIES))
> > -                     return 1;
> > -             msr_info->data = to_vmx(vcpu)->arch_capabilities;
> > -             break;
> >       case MSR_IA32_SYSENTER_CS:
> >               msr_info->data = vmcs_read32(GUEST_SYSENTER_CS);
> >               break;
> > @@ -1894,12 +1888,6 @@ static int vmx_set_msr(struct kvm_vcpu *vcpu, struct msr_data *msr_info)
> >               vmx_disable_intercept_for_msr(vmx->vmcs01.msr_bitmap, MSR_IA32_PRED_CMD,
> >                                             MSR_TYPE_W);
> >               break;
> > -     case MSR_IA32_ARCH_CAPABILITIES:
> > -             if (!msr_info->host_initiated ||
> > -                 (data & ~kvm_get_arch_capabilities()))
> > -                     return 1;
> > -             vmx->arch_capabilities = data;
> > -             break;
> >       case MSR_IA32_CR_PAT:
> >               if (vmcs_config.vmentry_ctrl & VM_ENTRY_LOAD_IA32_PAT) {
> >                       if (!kvm_mtrr_valid(vcpu, MSR_IA32_CR_PAT, data))
> > @@ -4088,8 +4076,6 @@ static void vmx_vcpu_setup(struct vcpu_vmx *vmx)
> >               ++vmx->nmsrs;
> >       }
> >
> > -     vmx->arch_capabilities = kvm_get_arch_capabilities();
> > -
> >       vm_exit_controls_init(vmx, vmx_vmexit_ctrl());
> >
> >       /* 22.2.1, 20.8.1 */
> > diff --git a/arch/x86/kvm/vmx/vmx.h b/arch/x86/kvm/vmx/vmx.h
> > index 1554cb45b393..a1e00d0a2482 100644
> > --- a/arch/x86/kvm/vmx/vmx.h
> > +++ b/arch/x86/kvm/vmx/vmx.h
> > @@ -190,7 +190,6 @@ struct vcpu_vmx {
> >       u64                   msr_guest_kernel_gs_base;
> >  #endif
> >
> > -     u64                   arch_capabilities;
> >       u64                   spec_ctrl;
> >
> >       u32 vm_entry_controls_shadow;
> > diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
> > index d90f011f3e32..7bfeebc482c4 100644
> > --- a/arch/x86/kvm/x86.c
> > +++ b/arch/x86/kvm/x86.c
> > @@ -2443,6 +2443,12 @@ int kvm_set_msr_common(struct kvm_vcpu *vcpu, struct msr_data *msr_info)
> >               if (msr_info->host_initiated)
> >                       vcpu->arch.microcode_version = data;
> >               break;
> > +     case MSR_IA32_ARCH_CAPABILITIES:
> > +             if (!msr_info->host_initiated ||
> > +                 (data & ~kvm_get_arch_capabilities()))
> > +                     return 1;

As I mentioned in the PATCH 1 thread, we'd still like to be able to
set IA32_ARCH_CAPABILITIES.RSBA from userspace, even if it's not
enumerated on the host.

Aside from that, this patch looks good to me. Thanks for the fix. I'll
try to be more cognizant of AMD in the future.
Xiaoyao Li March 12, 2019, 3:08 a.m. UTC | #3
On Mon, 2019-03-11 at 14:59 -0700, Jim Mattson wrote:
> On Fri, Mar 8, 2019 at 7:32 AM Sean Christopherson
> <sean.j.christopherson@intel.com> wrote:
> > 
> > On Thu, Mar 07, 2019 at 03:43:02PM -0800, Sean Christopherson wrote:
> > > The CPUID flag ARCH_CAPABILITIES is unconditioinally exposed to host
> > > userspace for all x86 hosts, i.e. KVM advertises ARCH_CAPABILITIES
> > > regardless of hardware support under the pretense that KVM fully
> > > emulates MSR_IA32_ARCH_CAPABILITIES.  Unfortunately, only VMX hosts
> > > handle accesses to MSR_IA32_ARCH_CAPABILITIES (despite KVM_GET_MSRS
> > > also reporting MSR_IA32_ARCH_CAPABILITIES for all hosts).
> > > 
> > > Move the MSR_IA32_ARCH_CAPABILITIES handling to common x86 code so
> > > that it's emulated on AMD hosts.
> > > 
> > > Fixes: 1eaafe91a0df4 ("kvm: x86: IA32_ARCH_CAPABILITIES is always
> > > supported")
> > 
> > And this one should have:
> > 
> >   Cc: stable@vger.kernel.org
> > 
> > > Reported-by: Xiaoyao Li <xiaoyao.li@linux.intel.com>
> > > Cc: Jim Mattson <jmattson@google.com>
> > > Signed-off-by: Sean Christopherson <sean.j.christopherson@intel.com>
> > > ---
> > >  arch/x86/include/asm/kvm_host.h |  1 +
> > >  arch/x86/kvm/vmx/vmx.c          | 14 --------------
> > >  arch/x86/kvm/vmx/vmx.h          |  1 -
> > >  arch/x86/kvm/x86.c              | 13 +++++++++++++
> > >  4 files changed, 14 insertions(+), 15 deletions(-)
> > > 
> > > diff --git a/arch/x86/include/asm/kvm_host.h
> > > b/arch/x86/include/asm/kvm_host.h
> > > index 7712b4ed8aa1..3d10ff38cbdb 100644
> > > --- a/arch/x86/include/asm/kvm_host.h
> > > +++ b/arch/x86/include/asm/kvm_host.h
> > > @@ -568,6 +568,7 @@ struct kvm_vcpu_arch {
> > >       bool tpr_access_reporting;
> > >       u64 ia32_xss;
> > >       u64 microcode_version;
> > > +     u64 arch_capabilities;
> > > 
> > >       /*
> > >        * Paging state of the vcpu
> > > diff --git a/arch/x86/kvm/vmx/vmx.c b/arch/x86/kvm/vmx/vmx.c
> > > index 2a86d296c90f..02cf8a551bd1 100644
> > > --- a/arch/x86/kvm/vmx/vmx.c
> > > +++ b/arch/x86/kvm/vmx/vmx.c
> > > @@ -1682,12 +1682,6 @@ static int vmx_get_msr(struct kvm_vcpu *vcpu,
> > > struct msr_data *msr_info)
> > > 
> > >               msr_info->data = to_vmx(vcpu)->spec_ctrl;
> > >               break;
> > > -     case MSR_IA32_ARCH_CAPABILITIES:
> > > -             if (!msr_info->host_initiated &&
> > > -                 !guest_cpuid_has(vcpu, X86_FEATURE_ARCH_CAPABILITIES))
> > > -                     return 1;
> > > -             msr_info->data = to_vmx(vcpu)->arch_capabilities;
> > > -             break;
> > >       case MSR_IA32_SYSENTER_CS:
> > >               msr_info->data = vmcs_read32(GUEST_SYSENTER_CS);
> > >               break;
> > > @@ -1894,12 +1888,6 @@ static int vmx_set_msr(struct kvm_vcpu *vcpu,
> > > struct msr_data *msr_info)
> > >               vmx_disable_intercept_for_msr(vmx->vmcs01.msr_bitmap,
> > > MSR_IA32_PRED_CMD,
> > >                                             MSR_TYPE_W);
> > >               break;
> > > -     case MSR_IA32_ARCH_CAPABILITIES:
> > > -             if (!msr_info->host_initiated ||
> > > -                 (data & ~kvm_get_arch_capabilities()))
> > > -                     return 1;
> > > -             vmx->arch_capabilities = data;
> > > -             break;
> > >       case MSR_IA32_CR_PAT:
> > >               if (vmcs_config.vmentry_ctrl & VM_ENTRY_LOAD_IA32_PAT) {
> > >                       if (!kvm_mtrr_valid(vcpu, MSR_IA32_CR_PAT, data))
> > > @@ -4088,8 +4076,6 @@ static void vmx_vcpu_setup(struct vcpu_vmx *vmx)
> > >               ++vmx->nmsrs;
> > >       }
> > > 
> > > -     vmx->arch_capabilities = kvm_get_arch_capabilities();
> > > -
> > >       vm_exit_controls_init(vmx, vmx_vmexit_ctrl());
> > > 
> > >       /* 22.2.1, 20.8.1 */
> > > diff --git a/arch/x86/kvm/vmx/vmx.h b/arch/x86/kvm/vmx/vmx.h
> > > index 1554cb45b393..a1e00d0a2482 100644
> > > --- a/arch/x86/kvm/vmx/vmx.h
> > > +++ b/arch/x86/kvm/vmx/vmx.h
> > > @@ -190,7 +190,6 @@ struct vcpu_vmx {
> > >       u64                   msr_guest_kernel_gs_base;
> > >  #endif
> > > 
> > > -     u64                   arch_capabilities;
> > >       u64                   spec_ctrl;
> > > 
> > >       u32 vm_entry_controls_shadow;
> > > diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
> > > index d90f011f3e32..7bfeebc482c4 100644
> > > --- a/arch/x86/kvm/x86.c
> > > +++ b/arch/x86/kvm/x86.c
> > > @@ -2443,6 +2443,12 @@ int kvm_set_msr_common(struct kvm_vcpu *vcpu,
> > > struct msr_data *msr_info)
> > >               if (msr_info->host_initiated)
> > >                       vcpu->arch.microcode_version = data;
> > >               break;
> > > +     case MSR_IA32_ARCH_CAPABILITIES:
> > > +             if (!msr_info->host_initiated ||
> > > +                 (data & ~kvm_get_arch_capabilities()))
> > > +                     return 1;
> 
> As I mentioned in the PATCH 1 thread, we'd still like to be able to
> set IA32_ARCH_CAPABILITIES.RSBA from userspace, even if it's not
> enumerated on the host.
> 
> Aside from that, this patch looks good to me. Thanks for the fix. I'll
> try to be more cognizant of AMD in the future.

Hi, Jim,

It's clear now. It is your negligence that simply enforce this cpuid for all x86
arch. As a result, here comes some fixes patches, besides this series I have
sent out another (kvm/x86: Move MSR_IA32_ARCH_CAPABILITIES to array
emulated_msrs) https://patchwork.kernel.org/patch/10844303/

Hi, Paolo,

Here is another thing that I need a decision or conclusion from you.
MSR CORE_CPABILITY acts as a feature-enumerating MSR as same as MSR
ARCH_CAPABILITIES. From my fix patch (kvm/x86/vmx: Make the emulation of
MSR_IA32_ARCH_CAPABILITIES only for vmx) 
https://patchwork.kernel.org/patch/10842499/ , you said dropping CPUID flag is
generally not a good idea, because it would change the guest ABI for AMD
processors. I didn't do any test on AMD processor and I cannot tell anything.
Anyway, as Jim's patch has merged into linus' tree for a while, using Sean's
this series to fix it is better.
However, when it comes to MSR CORE_CAPABILITIES, it faces the same situation.
So we should make a conclusion that, when emulating a feature-enumeraing MSR
should we expose it to vendor-specific or just expose to all x86 arch even
though it may be the dead code for other vendor?

Thanks,
-Xiaoyao
Jim Mattson March 12, 2019, 6:45 p.m. UTC | #4
On Mon, Mar 11, 2019 at 8:12 PM Xiaoyao Li <xiaoyao.li@linux.intel.com> wrote:
>
> On Mon, 2019-03-11 at 14:59 -0700, Jim Mattson wrote:
> > On Fri, Mar 8, 2019 at 7:32 AM Sean Christopherson
> > <sean.j.christopherson@intel.com> wrote:
> > >
> > > On Thu, Mar 07, 2019 at 03:43:02PM -0800, Sean Christopherson wrote:
> > > > The CPUID flag ARCH_CAPABILITIES is unconditioinally exposed to host
> > > > userspace for all x86 hosts, i.e. KVM advertises ARCH_CAPABILITIES
> > > > regardless of hardware support under the pretense that KVM fully
> > > > emulates MSR_IA32_ARCH_CAPABILITIES.  Unfortunately, only VMX hosts
> > > > handle accesses to MSR_IA32_ARCH_CAPABILITIES (despite KVM_GET_MSRS
> > > > also reporting MSR_IA32_ARCH_CAPABILITIES for all hosts).
> > > >
> > > > Move the MSR_IA32_ARCH_CAPABILITIES handling to common x86 code so
> > > > that it's emulated on AMD hosts.
> > > >
> > > > Fixes: 1eaafe91a0df4 ("kvm: x86: IA32_ARCH_CAPABILITIES is always
> > > > supported")
> > >
> > > And this one should have:
> > >
> > >   Cc: stable@vger.kernel.org
> > >
> > > > Reported-by: Xiaoyao Li <xiaoyao.li@linux.intel.com>
> > > > Cc: Jim Mattson <jmattson@google.com>
> > > > Signed-off-by: Sean Christopherson <sean.j.christopherson@intel.com>
> > > > ---
> > > >  arch/x86/include/asm/kvm_host.h |  1 +
> > > >  arch/x86/kvm/vmx/vmx.c          | 14 --------------
> > > >  arch/x86/kvm/vmx/vmx.h          |  1 -
> > > >  arch/x86/kvm/x86.c              | 13 +++++++++++++
> > > >  4 files changed, 14 insertions(+), 15 deletions(-)
> > > >
> > > > diff --git a/arch/x86/include/asm/kvm_host.h
> > > > b/arch/x86/include/asm/kvm_host.h
> > > > index 7712b4ed8aa1..3d10ff38cbdb 100644
> > > > --- a/arch/x86/include/asm/kvm_host.h
> > > > +++ b/arch/x86/include/asm/kvm_host.h
> > > > @@ -568,6 +568,7 @@ struct kvm_vcpu_arch {
> > > >       bool tpr_access_reporting;
> > > >       u64 ia32_xss;
> > > >       u64 microcode_version;
> > > > +     u64 arch_capabilities;
> > > >
> > > >       /*
> > > >        * Paging state of the vcpu
> > > > diff --git a/arch/x86/kvm/vmx/vmx.c b/arch/x86/kvm/vmx/vmx.c
> > > > index 2a86d296c90f..02cf8a551bd1 100644
> > > > --- a/arch/x86/kvm/vmx/vmx.c
> > > > +++ b/arch/x86/kvm/vmx/vmx.c
> > > > @@ -1682,12 +1682,6 @@ static int vmx_get_msr(struct kvm_vcpu *vcpu,
> > > > struct msr_data *msr_info)
> > > >
> > > >               msr_info->data = to_vmx(vcpu)->spec_ctrl;
> > > >               break;
> > > > -     case MSR_IA32_ARCH_CAPABILITIES:
> > > > -             if (!msr_info->host_initiated &&
> > > > -                 !guest_cpuid_has(vcpu, X86_FEATURE_ARCH_CAPABILITIES))
> > > > -                     return 1;
> > > > -             msr_info->data = to_vmx(vcpu)->arch_capabilities;
> > > > -             break;
> > > >       case MSR_IA32_SYSENTER_CS:
> > > >               msr_info->data = vmcs_read32(GUEST_SYSENTER_CS);
> > > >               break;
> > > > @@ -1894,12 +1888,6 @@ static int vmx_set_msr(struct kvm_vcpu *vcpu,
> > > > struct msr_data *msr_info)
> > > >               vmx_disable_intercept_for_msr(vmx->vmcs01.msr_bitmap,
> > > > MSR_IA32_PRED_CMD,
> > > >                                             MSR_TYPE_W);
> > > >               break;
> > > > -     case MSR_IA32_ARCH_CAPABILITIES:
> > > > -             if (!msr_info->host_initiated ||
> > > > -                 (data & ~kvm_get_arch_capabilities()))
> > > > -                     return 1;
> > > > -             vmx->arch_capabilities = data;
> > > > -             break;
> > > >       case MSR_IA32_CR_PAT:
> > > >               if (vmcs_config.vmentry_ctrl & VM_ENTRY_LOAD_IA32_PAT) {
> > > >                       if (!kvm_mtrr_valid(vcpu, MSR_IA32_CR_PAT, data))
> > > > @@ -4088,8 +4076,6 @@ static void vmx_vcpu_setup(struct vcpu_vmx *vmx)
> > > >               ++vmx->nmsrs;
> > > >       }
> > > >
> > > > -     vmx->arch_capabilities = kvm_get_arch_capabilities();
> > > > -
> > > >       vm_exit_controls_init(vmx, vmx_vmexit_ctrl());
> > > >
> > > >       /* 22.2.1, 20.8.1 */
> > > > diff --git a/arch/x86/kvm/vmx/vmx.h b/arch/x86/kvm/vmx/vmx.h
> > > > index 1554cb45b393..a1e00d0a2482 100644
> > > > --- a/arch/x86/kvm/vmx/vmx.h
> > > > +++ b/arch/x86/kvm/vmx/vmx.h
> > > > @@ -190,7 +190,6 @@ struct vcpu_vmx {
> > > >       u64                   msr_guest_kernel_gs_base;
> > > >  #endif
> > > >
> > > > -     u64                   arch_capabilities;
> > > >       u64                   spec_ctrl;
> > > >
> > > >       u32 vm_entry_controls_shadow;
> > > > diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
> > > > index d90f011f3e32..7bfeebc482c4 100644
> > > > --- a/arch/x86/kvm/x86.c
> > > > +++ b/arch/x86/kvm/x86.c
> > > > @@ -2443,6 +2443,12 @@ int kvm_set_msr_common(struct kvm_vcpu *vcpu,
> > > > struct msr_data *msr_info)
> > > >               if (msr_info->host_initiated)
> > > >                       vcpu->arch.microcode_version = data;
> > > >               break;
> > > > +     case MSR_IA32_ARCH_CAPABILITIES:
> > > > +             if (!msr_info->host_initiated ||
> > > > +                 (data & ~kvm_get_arch_capabilities()))
> > > > +                     return 1;
> >
> > As I mentioned in the PATCH 1 thread, we'd still like to be able to
> > set IA32_ARCH_CAPABILITIES.RSBA from userspace, even if it's not
> > enumerated on the host.
> >
> > Aside from that, this patch looks good to me. Thanks for the fix. I'll
> > try to be more cognizant of AMD in the future.
>
> Hi, Jim,
>
> It's clear now. It is your negligence that simply enforce this cpuid for all x86
> arch.

Ouch! That's harsh...and a bit supercilious.

It didn't occur to me at the time, but kvm *should* emulate
IA32_ARCH_CAPABILITIES for AMD as well as Intel, to support
cross-vendor migration. If there are any Intel machines in the
migration pool that are vulnerable to exploits of empty RSB
conditions, userspace should be reporting IA32_ARCH_CAPABILITIES.RSBA
regardless of virtual CPU vendor, and to do so,
CPUID.(EAX=07H,ECX=00H):EDX[29] must be enumerated as well.

Again, thanks for fixing this.
Jim Mattson March 12, 2019, 7:02 p.m. UTC | #5
On Tue, Mar 12, 2019 at 11:45 AM Jim Mattson <jmattson@google.com> wrote:
>
> On Mon, Mar 11, 2019 at 8:12 PM Xiaoyao Li <xiaoyao.li@linux.intel.com> wrote:
> >
> > On Mon, 2019-03-11 at 14:59 -0700, Jim Mattson wrote:
> > > On Fri, Mar 8, 2019 at 7:32 AM Sean Christopherson
> > > <sean.j.christopherson@intel.com> wrote:
> > > >
> > > > On Thu, Mar 07, 2019 at 03:43:02PM -0800, Sean Christopherson wrote:
> > > > > The CPUID flag ARCH_CAPABILITIES is unconditioinally exposed to host
> > > > > userspace for all x86 hosts, i.e. KVM advertises ARCH_CAPABILITIES
> > > > > regardless of hardware support under the pretense that KVM fully
> > > > > emulates MSR_IA32_ARCH_CAPABILITIES.  Unfortunately, only VMX hosts
> > > > > handle accesses to MSR_IA32_ARCH_CAPABILITIES (despite KVM_GET_MSRS
> > > > > also reporting MSR_IA32_ARCH_CAPABILITIES for all hosts).
> > > > >
> > > > > Move the MSR_IA32_ARCH_CAPABILITIES handling to common x86 code so
> > > > > that it's emulated on AMD hosts.
> > > > >
> > > > > Fixes: 1eaafe91a0df4 ("kvm: x86: IA32_ARCH_CAPABILITIES is always
> > > > > supported")
> > > >
> > > > And this one should have:
> > > >
> > > >   Cc: stable@vger.kernel.org
> > > >
> > > > > Reported-by: Xiaoyao Li <xiaoyao.li@linux.intel.com>
> > > > > Cc: Jim Mattson <jmattson@google.com>
> > > > > Signed-off-by: Sean Christopherson <sean.j.christopherson@intel.com>
> > > > > ---
> > > > >  arch/x86/include/asm/kvm_host.h |  1 +
> > > > >  arch/x86/kvm/vmx/vmx.c          | 14 --------------
> > > > >  arch/x86/kvm/vmx/vmx.h          |  1 -
> > > > >  arch/x86/kvm/x86.c              | 13 +++++++++++++
> > > > >  4 files changed, 14 insertions(+), 15 deletions(-)
> > > > >
> > > > > diff --git a/arch/x86/include/asm/kvm_host.h
> > > > > b/arch/x86/include/asm/kvm_host.h
> > > > > index 7712b4ed8aa1..3d10ff38cbdb 100644
> > > > > --- a/arch/x86/include/asm/kvm_host.h
> > > > > +++ b/arch/x86/include/asm/kvm_host.h
> > > > > @@ -568,6 +568,7 @@ struct kvm_vcpu_arch {
> > > > >       bool tpr_access_reporting;
> > > > >       u64 ia32_xss;
> > > > >       u64 microcode_version;
> > > > > +     u64 arch_capabilities;
> > > > >
> > > > >       /*
> > > > >        * Paging state of the vcpu
> > > > > diff --git a/arch/x86/kvm/vmx/vmx.c b/arch/x86/kvm/vmx/vmx.c
> > > > > index 2a86d296c90f..02cf8a551bd1 100644
> > > > > --- a/arch/x86/kvm/vmx/vmx.c
> > > > > +++ b/arch/x86/kvm/vmx/vmx.c
> > > > > @@ -1682,12 +1682,6 @@ static int vmx_get_msr(struct kvm_vcpu *vcpu,
> > > > > struct msr_data *msr_info)
> > > > >
> > > > >               msr_info->data = to_vmx(vcpu)->spec_ctrl;
> > > > >               break;
> > > > > -     case MSR_IA32_ARCH_CAPABILITIES:
> > > > > -             if (!msr_info->host_initiated &&
> > > > > -                 !guest_cpuid_has(vcpu, X86_FEATURE_ARCH_CAPABILITIES))
> > > > > -                     return 1;
> > > > > -             msr_info->data = to_vmx(vcpu)->arch_capabilities;
> > > > > -             break;
> > > > >       case MSR_IA32_SYSENTER_CS:
> > > > >               msr_info->data = vmcs_read32(GUEST_SYSENTER_CS);
> > > > >               break;
> > > > > @@ -1894,12 +1888,6 @@ static int vmx_set_msr(struct kvm_vcpu *vcpu,
> > > > > struct msr_data *msr_info)
> > > > >               vmx_disable_intercept_for_msr(vmx->vmcs01.msr_bitmap,
> > > > > MSR_IA32_PRED_CMD,
> > > > >                                             MSR_TYPE_W);
> > > > >               break;
> > > > > -     case MSR_IA32_ARCH_CAPABILITIES:
> > > > > -             if (!msr_info->host_initiated ||
> > > > > -                 (data & ~kvm_get_arch_capabilities()))
> > > > > -                     return 1;
> > > > > -             vmx->arch_capabilities = data;
> > > > > -             break;
> > > > >       case MSR_IA32_CR_PAT:
> > > > >               if (vmcs_config.vmentry_ctrl & VM_ENTRY_LOAD_IA32_PAT) {
> > > > >                       if (!kvm_mtrr_valid(vcpu, MSR_IA32_CR_PAT, data))
> > > > > @@ -4088,8 +4076,6 @@ static void vmx_vcpu_setup(struct vcpu_vmx *vmx)
> > > > >               ++vmx->nmsrs;
> > > > >       }
> > > > >
> > > > > -     vmx->arch_capabilities = kvm_get_arch_capabilities();
> > > > > -
> > > > >       vm_exit_controls_init(vmx, vmx_vmexit_ctrl());
> > > > >
> > > > >       /* 22.2.1, 20.8.1 */
> > > > > diff --git a/arch/x86/kvm/vmx/vmx.h b/arch/x86/kvm/vmx/vmx.h
> > > > > index 1554cb45b393..a1e00d0a2482 100644
> > > > > --- a/arch/x86/kvm/vmx/vmx.h
> > > > > +++ b/arch/x86/kvm/vmx/vmx.h
> > > > > @@ -190,7 +190,6 @@ struct vcpu_vmx {
> > > > >       u64                   msr_guest_kernel_gs_base;
> > > > >  #endif
> > > > >
> > > > > -     u64                   arch_capabilities;
> > > > >       u64                   spec_ctrl;
> > > > >
> > > > >       u32 vm_entry_controls_shadow;
> > > > > diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
> > > > > index d90f011f3e32..7bfeebc482c4 100644
> > > > > --- a/arch/x86/kvm/x86.c
> > > > > +++ b/arch/x86/kvm/x86.c
> > > > > @@ -2443,6 +2443,12 @@ int kvm_set_msr_common(struct kvm_vcpu *vcpu,
> > > > > struct msr_data *msr_info)
> > > > >               if (msr_info->host_initiated)
> > > > >                       vcpu->arch.microcode_version = data;
> > > > >               break;
> > > > > +     case MSR_IA32_ARCH_CAPABILITIES:
> > > > > +             if (!msr_info->host_initiated ||
> > > > > +                 (data & ~kvm_get_arch_capabilities()))
> > > > > +                     return 1;
> > >
> > > As I mentioned in the PATCH 1 thread, we'd still like to be able to
> > > set IA32_ARCH_CAPABILITIES.RSBA from userspace, even if it's not
> > > enumerated on the host.
> > >
> > > Aside from that, this patch looks good to me. Thanks for the fix. I'll
> > > try to be more cognizant of AMD in the future.
> >
> > Hi, Jim,
> >
> > It's clear now. It is your negligence that simply enforce this cpuid for all x86
> > arch.
>
> Ouch! That's harsh...and a bit supercilious.
>
> It didn't occur to me at the time, but kvm *should* emulate
> IA32_ARCH_CAPABILITIES for AMD as well as Intel, to support
> cross-vendor migration. If there are any Intel machines in the
> migration pool that are vulnerable to exploits of empty RSB
> conditions, userspace should be reporting IA32_ARCH_CAPABILITIES.RSBA
> regardless of virtual CPU vendor, and to do so,
> CPUID.(EAX=07H,ECX=00H):EDX[29] must be enumerated as well.
>
> Again, thanks for fixing this.

Note that you should probably also remove the 'case
MSR_IA32_ARCH_CAPABILITIES' from svm_has_emulated_msr().
Xiaoyao Li March 13, 2019, 1:59 a.m. UTC | #6
On Tue, 2019-03-12 at 12:02 -0700, Jim Mattson wrote:
> On Tue, Mar 12, 2019 at 11:45 AM Jim Mattson <jmattson@google.com> wrote:
> > 
> > On Mon, Mar 11, 2019 at 8:12 PM Xiaoyao Li <xiaoyao.li@linux.intel.com>
> > wrote:
> > > 
> > > On Mon, 2019-03-11 at 14:59 -0700, Jim Mattson wrote:
> > > > On Fri, Mar 8, 2019 at 7:32 AM Sean Christopherson
> > > > <sean.j.christopherson@intel.com> wrote:
> > > > > 
> > > > > On Thu, Mar 07, 2019 at 03:43:02PM -0800, Sean Christopherson wrote:
> > > > > > The CPUID flag ARCH_CAPABILITIES is unconditioinally exposed to host
> > > > > > userspace for all x86 hosts, i.e. KVM advertises ARCH_CAPABILITIES
> > > > > > regardless of hardware support under the pretense that KVM fully
> > > > > > emulates MSR_IA32_ARCH_CAPABILITIES.  Unfortunately, only VMX hosts
> > > > > > handle accesses to MSR_IA32_ARCH_CAPABILITIES (despite KVM_GET_MSRS
> > > > > > also reporting MSR_IA32_ARCH_CAPABILITIES for all hosts).
> > > > > > 
> > > > > > Move the MSR_IA32_ARCH_CAPABILITIES handling to common x86 code so
> > > > > > that it's emulated on AMD hosts.
> > > > > > 
> > > > > > Fixes: 1eaafe91a0df4 ("kvm: x86: IA32_ARCH_CAPABILITIES is always
> > > > > > supported")
> > > > > 
> > > > > And this one should have:
> > > > > 
> > > > >   Cc: stable@vger.kernel.org
> > > > > 
> > > > > > Reported-by: Xiaoyao Li <xiaoyao.li@linux.intel.com>
> > > > > > Cc: Jim Mattson <jmattson@google.com>
> > > > > > Signed-off-by: Sean Christopherson <sean.j.christopherson@intel.com>
> > > > > > ---
> > > > > >  arch/x86/include/asm/kvm_host.h |  1 +
> > > > > >  arch/x86/kvm/vmx/vmx.c          | 14 --------------
> > > > > >  arch/x86/kvm/vmx/vmx.h          |  1 -
> > > > > >  arch/x86/kvm/x86.c              | 13 +++++++++++++
> > > > > >  4 files changed, 14 insertions(+), 15 deletions(-)
> > > > > > 
> > > > > > diff --git a/arch/x86/include/asm/kvm_host.h
> > > > > > b/arch/x86/include/asm/kvm_host.h
> > > > > > index 7712b4ed8aa1..3d10ff38cbdb 100644
> > > > > > --- a/arch/x86/include/asm/kvm_host.h
> > > > > > +++ b/arch/x86/include/asm/kvm_host.h
> > > > > > @@ -568,6 +568,7 @@ struct kvm_vcpu_arch {
> > > > > >       bool tpr_access_reporting;
> > > > > >       u64 ia32_xss;
> > > > > >       u64 microcode_version;
> > > > > > +     u64 arch_capabilities;
> > > > > > 
> > > > > >       /*
> > > > > >        * Paging state of the vcpu
> > > > > > diff --git a/arch/x86/kvm/vmx/vmx.c b/arch/x86/kvm/vmx/vmx.c
> > > > > > index 2a86d296c90f..02cf8a551bd1 100644
> > > > > > --- a/arch/x86/kvm/vmx/vmx.c
> > > > > > +++ b/arch/x86/kvm/vmx/vmx.c
> > > > > > @@ -1682,12 +1682,6 @@ static int vmx_get_msr(struct kvm_vcpu *vcpu,
> > > > > > struct msr_data *msr_info)
> > > > > > 
> > > > > >               msr_info->data = to_vmx(vcpu)->spec_ctrl;
> > > > > >               break;
> > > > > > -     case MSR_IA32_ARCH_CAPABILITIES:
> > > > > > -             if (!msr_info->host_initiated &&
> > > > > > -                 !guest_cpuid_has(vcpu,
> > > > > > X86_FEATURE_ARCH_CAPABILITIES))
> > > > > > -                     return 1;
> > > > > > -             msr_info->data = to_vmx(vcpu)->arch_capabilities;
> > > > > > -             break;
> > > > > >       case MSR_IA32_SYSENTER_CS:
> > > > > >               msr_info->data = vmcs_read32(GUEST_SYSENTER_CS);
> > > > > >               break;
> > > > > > @@ -1894,12 +1888,6 @@ static int vmx_set_msr(struct kvm_vcpu *vcpu,
> > > > > > struct msr_data *msr_info)
> > > > > >               vmx_disable_intercept_for_msr(vmx->vmcs01.msr_bitmap,
> > > > > > MSR_IA32_PRED_CMD,
> > > > > >                                             MSR_TYPE_W);
> > > > > >               break;
> > > > > > -     case MSR_IA32_ARCH_CAPABILITIES:
> > > > > > -             if (!msr_info->host_initiated ||
> > > > > > -                 (data & ~kvm_get_arch_capabilities()))
> > > > > > -                     return 1;
> > > > > > -             vmx->arch_capabilities = data;
> > > > > > -             break;
> > > > > >       case MSR_IA32_CR_PAT:
> > > > > >               if (vmcs_config.vmentry_ctrl & VM_ENTRY_LOAD_IA32_PAT)
> > > > > > {
> > > > > >                       if (!kvm_mtrr_valid(vcpu, MSR_IA32_CR_PAT,
> > > > > > data))
> > > > > > @@ -4088,8 +4076,6 @@ static void vmx_vcpu_setup(struct vcpu_vmx
> > > > > > *vmx)
> > > > > >               ++vmx->nmsrs;
> > > > > >       }
> > > > > > 
> > > > > > -     vmx->arch_capabilities = kvm_get_arch_capabilities();
> > > > > > -
> > > > > >       vm_exit_controls_init(vmx, vmx_vmexit_ctrl());
> > > > > > 
> > > > > >       /* 22.2.1, 20.8.1 */
> > > > > > diff --git a/arch/x86/kvm/vmx/vmx.h b/arch/x86/kvm/vmx/vmx.h
> > > > > > index 1554cb45b393..a1e00d0a2482 100644
> > > > > > --- a/arch/x86/kvm/vmx/vmx.h
> > > > > > +++ b/arch/x86/kvm/vmx/vmx.h
> > > > > > @@ -190,7 +190,6 @@ struct vcpu_vmx {
> > > > > >       u64                   msr_guest_kernel_gs_base;
> > > > > >  #endif
> > > > > > 
> > > > > > -     u64                   arch_capabilities;
> > > > > >       u64                   spec_ctrl;
> > > > > > 
> > > > > >       u32 vm_entry_controls_shadow;
> > > > > > diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
> > > > > > index d90f011f3e32..7bfeebc482c4 100644
> > > > > > --- a/arch/x86/kvm/x86.c
> > > > > > +++ b/arch/x86/kvm/x86.c
> > > > > > @@ -2443,6 +2443,12 @@ int kvm_set_msr_common(struct kvm_vcpu *vcpu,
> > > > > > struct msr_data *msr_info)
> > > > > >               if (msr_info->host_initiated)
> > > > > >                       vcpu->arch.microcode_version = data;
> > > > > >               break;
> > > > > > +     case MSR_IA32_ARCH_CAPABILITIES:
> > > > > > +             if (!msr_info->host_initiated ||
> > > > > > +                 (data & ~kvm_get_arch_capabilities()))
> > > > > > +                     return 1;
> > > > 
> > > > As I mentioned in the PATCH 1 thread, we'd still like to be able to
> > > > set IA32_ARCH_CAPABILITIES.RSBA from userspace, even if it's not
> > > > enumerated on the host.
> > > > 
> > > > Aside from that, this patch looks good to me. Thanks for the fix. I'll
> > > > try to be more cognizant of AMD in the future.
> > > 
> > > Hi, Jim,
> > > 
> > > It's clear now. It is your negligence that simply enforce this cpuid for
> > > all x86
> > > arch.
> > 
> > Ouch! That's harsh...and a bit supercilious.
> > 
> > It didn't occur to me at the time, but kvm *should* emulate
> > IA32_ARCH_CAPABILITIES for AMD as well as Intel, to support
> > cross-vendor migration. If there are any Intel machines in the
> > migration pool that are vulnerable to exploits of empty RSB
> > conditions, userspace should be reporting IA32_ARCH_CAPABILITIES.RSBA
> > regardless of virtual CPU vendor, and to do so,
> > CPUID.(EAX=07H,ECX=00H):EDX[29] must be enumerated as well.
> > 
> > Again, thanks for fixing this.
> 
> Note that you should probably also remove the 'case
> MSR_IA32_ARCH_CAPABILITIES' from svm_has_emulated_msr().

Thanks for your reminder. We don't need to remove the 'case
MSR_IA32_ARCH_CAPABILITIES', because there doesn't have and
svm_has_emulated_msr() return true by default.
Xiaoyao Li March 13, 2019, 2:05 a.m. UTC | #7
On Tue, 2019-03-12 at 11:45 -0700, Jim Mattson wrote:
> On Mon, Mar 11, 2019 at 8:12 PM Xiaoyao Li <xiaoyao.li@linux.intel.com> wrote:
> > 
> > On Mon, 2019-03-11 at 14:59 -0700, Jim Mattson wrote:
> > > On Fri, Mar 8, 2019 at 7:32 AM Sean Christopherson
> > > <sean.j.christopherson@intel.com> wrote:
> > > > 
> > > > On Thu, Mar 07, 2019 at 03:43:02PM -0800, Sean Christopherson wrote:
> > > > > The CPUID flag ARCH_CAPABILITIES is unconditioinally exposed to host
> > > > > userspace for all x86 hosts, i.e. KVM advertises ARCH_CAPABILITIES
> > > > > regardless of hardware support under the pretense that KVM fully
> > > > > emulates MSR_IA32_ARCH_CAPABILITIES.  Unfortunately, only VMX hosts
> > > > > handle accesses to MSR_IA32_ARCH_CAPABILITIES (despite KVM_GET_MSRS
> > > > > also reporting MSR_IA32_ARCH_CAPABILITIES for all hosts).
> > > > > 
> > > > > Move the MSR_IA32_ARCH_CAPABILITIES handling to common x86 code so
> > > > > that it's emulated on AMD hosts.
> > > > > 
> > > > > Fixes: 1eaafe91a0df4 ("kvm: x86: IA32_ARCH_CAPABILITIES is always
> > > > > supported")
> > > > 
> > > > And this one should have:
> > > > 
> > > >   Cc: stable@vger.kernel.org
> > > > 
> > > > > Reported-by: Xiaoyao Li <xiaoyao.li@linux.intel.com>
> > > > > Cc: Jim Mattson <jmattson@google.com>
> > > > > Signed-off-by: Sean Christopherson <sean.j.christopherson@intel.com>
> > > > > ---
> > > > >  arch/x86/include/asm/kvm_host.h |  1 +
> > > > >  arch/x86/kvm/vmx/vmx.c          | 14 --------------
> > > > >  arch/x86/kvm/vmx/vmx.h          |  1 -
> > > > >  arch/x86/kvm/x86.c              | 13 +++++++++++++
> > > > >  4 files changed, 14 insertions(+), 15 deletions(-)
> > > > > 
> > > > > diff --git a/arch/x86/include/asm/kvm_host.h
> > > > > b/arch/x86/include/asm/kvm_host.h
> > > > > index 7712b4ed8aa1..3d10ff38cbdb 100644
> > > > > --- a/arch/x86/include/asm/kvm_host.h
> > > > > +++ b/arch/x86/include/asm/kvm_host.h
> > > > > @@ -568,6 +568,7 @@ struct kvm_vcpu_arch {
> > > > >       bool tpr_access_reporting;
> > > > >       u64 ia32_xss;
> > > > >       u64 microcode_version;
> > > > > +     u64 arch_capabilities;
> > > > > 
> > > > >       /*
> > > > >        * Paging state of the vcpu
> > > > > diff --git a/arch/x86/kvm/vmx/vmx.c b/arch/x86/kvm/vmx/vmx.c
> > > > > index 2a86d296c90f..02cf8a551bd1 100644
> > > > > --- a/arch/x86/kvm/vmx/vmx.c
> > > > > +++ b/arch/x86/kvm/vmx/vmx.c
> > > > > @@ -1682,12 +1682,6 @@ static int vmx_get_msr(struct kvm_vcpu *vcpu,
> > > > > struct msr_data *msr_info)
> > > > > 
> > > > >               msr_info->data = to_vmx(vcpu)->spec_ctrl;
> > > > >               break;
> > > > > -     case MSR_IA32_ARCH_CAPABILITIES:
> > > > > -             if (!msr_info->host_initiated &&
> > > > > -                 !guest_cpuid_has(vcpu,
> > > > > X86_FEATURE_ARCH_CAPABILITIES))
> > > > > -                     return 1;
> > > > > -             msr_info->data = to_vmx(vcpu)->arch_capabilities;
> > > > > -             break;
> > > > >       case MSR_IA32_SYSENTER_CS:
> > > > >               msr_info->data = vmcs_read32(GUEST_SYSENTER_CS);
> > > > >               break;
> > > > > @@ -1894,12 +1888,6 @@ static int vmx_set_msr(struct kvm_vcpu *vcpu,
> > > > > struct msr_data *msr_info)
> > > > >               vmx_disable_intercept_for_msr(vmx->vmcs01.msr_bitmap,
> > > > > MSR_IA32_PRED_CMD,
> > > > >                                             MSR_TYPE_W);
> > > > >               break;
> > > > > -     case MSR_IA32_ARCH_CAPABILITIES:
> > > > > -             if (!msr_info->host_initiated ||
> > > > > -                 (data & ~kvm_get_arch_capabilities()))
> > > > > -                     return 1;
> > > > > -             vmx->arch_capabilities = data;
> > > > > -             break;
> > > > >       case MSR_IA32_CR_PAT:
> > > > >               if (vmcs_config.vmentry_ctrl & VM_ENTRY_LOAD_IA32_PAT) {
> > > > >                       if (!kvm_mtrr_valid(vcpu, MSR_IA32_CR_PAT,
> > > > > data))
> > > > > @@ -4088,8 +4076,6 @@ static void vmx_vcpu_setup(struct vcpu_vmx *vmx)
> > > > >               ++vmx->nmsrs;
> > > > >       }
> > > > > 
> > > > > -     vmx->arch_capabilities = kvm_get_arch_capabilities();
> > > > > -
> > > > >       vm_exit_controls_init(vmx, vmx_vmexit_ctrl());
> > > > > 
> > > > >       /* 22.2.1, 20.8.1 */
> > > > > diff --git a/arch/x86/kvm/vmx/vmx.h b/arch/x86/kvm/vmx/vmx.h
> > > > > index 1554cb45b393..a1e00d0a2482 100644
> > > > > --- a/arch/x86/kvm/vmx/vmx.h
> > > > > +++ b/arch/x86/kvm/vmx/vmx.h
> > > > > @@ -190,7 +190,6 @@ struct vcpu_vmx {
> > > > >       u64                   msr_guest_kernel_gs_base;
> > > > >  #endif
> > > > > 
> > > > > -     u64                   arch_capabilities;
> > > > >       u64                   spec_ctrl;
> > > > > 
> > > > >       u32 vm_entry_controls_shadow;
> > > > > diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
> > > > > index d90f011f3e32..7bfeebc482c4 100644
> > > > > --- a/arch/x86/kvm/x86.c
> > > > > +++ b/arch/x86/kvm/x86.c
> > > > > @@ -2443,6 +2443,12 @@ int kvm_set_msr_common(struct kvm_vcpu *vcpu,
> > > > > struct msr_data *msr_info)
> > > > >               if (msr_info->host_initiated)
> > > > >                       vcpu->arch.microcode_version = data;
> > > > >               break;
> > > > > +     case MSR_IA32_ARCH_CAPABILITIES:
> > > > > +             if (!msr_info->host_initiated ||
> > > > > +                 (data & ~kvm_get_arch_capabilities()))
> > > > > +                     return 1;
> > > 
> > > As I mentioned in the PATCH 1 thread, we'd still like to be able to
> > > set IA32_ARCH_CAPABILITIES.RSBA from userspace, even if it's not
> > > enumerated on the host.
> > > 
> > > Aside from that, this patch looks good to me. Thanks for the fix. I'll
> > > try to be more cognizant of AMD in the future.
> > 
> > Hi, Jim,
> > 
> > It's clear now. It is your negligence that simply enforce this cpuid for all
> > x86
> > arch.
> 
> Ouch! That's harsh...and a bit supercilious.

Sorry, no offense. 

> It didn't occur to me at the time, but kvm *should* emulate
> IA32_ARCH_CAPABILITIES for AMD as well as Intel, to support
> cross-vendor migration. If there are any Intel machines in the
> migration pool that are vulnerable to exploits of empty RSB
> conditions, userspace should be reporting IA32_ARCH_CAPABILITIES.RSBA
> regardless of virtual CPU vendor, and to do so,
> CPUID.(EAX=07H,ECX=00H):EDX[29] must be enumerated as well.
> 
> Again, thanks for fixing this.
Jim Mattson March 13, 2019, 3:40 a.m. UTC | #8
On Tue, Mar 12, 2019 at 7:02 PM Xiaoyao Li <xiaoyao.li@linux.intel.com> wrote:
>
> On Tue, 2019-03-12 at 12:02 -0700, Jim Mattson wrote:
> > On Tue, Mar 12, 2019 at 11:45 AM Jim Mattson <jmattson@google.com> wrote:
> > >
> > > On Mon, Mar 11, 2019 at 8:12 PM Xiaoyao Li <xiaoyao.li@linux.intel.com>
> > > wrote:
> > > >
> > > > On Mon, 2019-03-11 at 14:59 -0700, Jim Mattson wrote:
> > > > > On Fri, Mar 8, 2019 at 7:32 AM Sean Christopherson
> > > > > <sean.j.christopherson@intel.com> wrote:
> > > > > >
> > > > > > On Thu, Mar 07, 2019 at 03:43:02PM -0800, Sean Christopherson wrote:
> > > > > > > The CPUID flag ARCH_CAPABILITIES is unconditioinally exposed to host
> > > > > > > userspace for all x86 hosts, i.e. KVM advertises ARCH_CAPABILITIES
> > > > > > > regardless of hardware support under the pretense that KVM fully
> > > > > > > emulates MSR_IA32_ARCH_CAPABILITIES.  Unfortunately, only VMX hosts
> > > > > > > handle accesses to MSR_IA32_ARCH_CAPABILITIES (despite KVM_GET_MSRS
> > > > > > > also reporting MSR_IA32_ARCH_CAPABILITIES for all hosts).
> > > > > > >
> > > > > > > Move the MSR_IA32_ARCH_CAPABILITIES handling to common x86 code so
> > > > > > > that it's emulated on AMD hosts.
> > > > > > >
> > > > > > > Fixes: 1eaafe91a0df4 ("kvm: x86: IA32_ARCH_CAPABILITIES is always
> > > > > > > supported")
> > > > > >
> > > > > > And this one should have:
> > > > > >
> > > > > >   Cc: stable@vger.kernel.org
> > > > > >
> > > > > > > Reported-by: Xiaoyao Li <xiaoyao.li@linux.intel.com>
> > > > > > > Cc: Jim Mattson <jmattson@google.com>
> > > > > > > Signed-off-by: Sean Christopherson <sean.j.christopherson@intel.com>
> > > > > > > ---
> > > > > > >  arch/x86/include/asm/kvm_host.h |  1 +
> > > > > > >  arch/x86/kvm/vmx/vmx.c          | 14 --------------
> > > > > > >  arch/x86/kvm/vmx/vmx.h          |  1 -
> > > > > > >  arch/x86/kvm/x86.c              | 13 +++++++++++++
> > > > > > >  4 files changed, 14 insertions(+), 15 deletions(-)
> > > > > > >
> > > > > > > diff --git a/arch/x86/include/asm/kvm_host.h
> > > > > > > b/arch/x86/include/asm/kvm_host.h
> > > > > > > index 7712b4ed8aa1..3d10ff38cbdb 100644
> > > > > > > --- a/arch/x86/include/asm/kvm_host.h
> > > > > > > +++ b/arch/x86/include/asm/kvm_host.h
> > > > > > > @@ -568,6 +568,7 @@ struct kvm_vcpu_arch {
> > > > > > >       bool tpr_access_reporting;
> > > > > > >       u64 ia32_xss;
> > > > > > >       u64 microcode_version;
> > > > > > > +     u64 arch_capabilities;
> > > > > > >
> > > > > > >       /*
> > > > > > >        * Paging state of the vcpu
> > > > > > > diff --git a/arch/x86/kvm/vmx/vmx.c b/arch/x86/kvm/vmx/vmx.c
> > > > > > > index 2a86d296c90f..02cf8a551bd1 100644
> > > > > > > --- a/arch/x86/kvm/vmx/vmx.c
> > > > > > > +++ b/arch/x86/kvm/vmx/vmx.c
> > > > > > > @@ -1682,12 +1682,6 @@ static int vmx_get_msr(struct kvm_vcpu *vcpu,
> > > > > > > struct msr_data *msr_info)
> > > > > > >
> > > > > > >               msr_info->data = to_vmx(vcpu)->spec_ctrl;
> > > > > > >               break;
> > > > > > > -     case MSR_IA32_ARCH_CAPABILITIES:
> > > > > > > -             if (!msr_info->host_initiated &&
> > > > > > > -                 !guest_cpuid_has(vcpu,
> > > > > > > X86_FEATURE_ARCH_CAPABILITIES))
> > > > > > > -                     return 1;
> > > > > > > -             msr_info->data = to_vmx(vcpu)->arch_capabilities;
> > > > > > > -             break;
> > > > > > >       case MSR_IA32_SYSENTER_CS:
> > > > > > >               msr_info->data = vmcs_read32(GUEST_SYSENTER_CS);
> > > > > > >               break;
> > > > > > > @@ -1894,12 +1888,6 @@ static int vmx_set_msr(struct kvm_vcpu *vcpu,
> > > > > > > struct msr_data *msr_info)
> > > > > > >               vmx_disable_intercept_for_msr(vmx->vmcs01.msr_bitmap,
> > > > > > > MSR_IA32_PRED_CMD,
> > > > > > >                                             MSR_TYPE_W);
> > > > > > >               break;
> > > > > > > -     case MSR_IA32_ARCH_CAPABILITIES:
> > > > > > > -             if (!msr_info->host_initiated ||
> > > > > > > -                 (data & ~kvm_get_arch_capabilities()))
> > > > > > > -                     return 1;
> > > > > > > -             vmx->arch_capabilities = data;
> > > > > > > -             break;
> > > > > > >       case MSR_IA32_CR_PAT:
> > > > > > >               if (vmcs_config.vmentry_ctrl & VM_ENTRY_LOAD_IA32_PAT)
> > > > > > > {
> > > > > > >                       if (!kvm_mtrr_valid(vcpu, MSR_IA32_CR_PAT,
> > > > > > > data))
> > > > > > > @@ -4088,8 +4076,6 @@ static void vmx_vcpu_setup(struct vcpu_vmx
> > > > > > > *vmx)
> > > > > > >               ++vmx->nmsrs;
> > > > > > >       }
> > > > > > >
> > > > > > > -     vmx->arch_capabilities = kvm_get_arch_capabilities();
> > > > > > > -
> > > > > > >       vm_exit_controls_init(vmx, vmx_vmexit_ctrl());
> > > > > > >
> > > > > > >       /* 22.2.1, 20.8.1 */
> > > > > > > diff --git a/arch/x86/kvm/vmx/vmx.h b/arch/x86/kvm/vmx/vmx.h
> > > > > > > index 1554cb45b393..a1e00d0a2482 100644
> > > > > > > --- a/arch/x86/kvm/vmx/vmx.h
> > > > > > > +++ b/arch/x86/kvm/vmx/vmx.h
> > > > > > > @@ -190,7 +190,6 @@ struct vcpu_vmx {
> > > > > > >       u64                   msr_guest_kernel_gs_base;
> > > > > > >  #endif
> > > > > > >
> > > > > > > -     u64                   arch_capabilities;
> > > > > > >       u64                   spec_ctrl;
> > > > > > >
> > > > > > >       u32 vm_entry_controls_shadow;
> > > > > > > diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
> > > > > > > index d90f011f3e32..7bfeebc482c4 100644
> > > > > > > --- a/arch/x86/kvm/x86.c
> > > > > > > +++ b/arch/x86/kvm/x86.c
> > > > > > > @@ -2443,6 +2443,12 @@ int kvm_set_msr_common(struct kvm_vcpu *vcpu,
> > > > > > > struct msr_data *msr_info)
> > > > > > >               if (msr_info->host_initiated)
> > > > > > >                       vcpu->arch.microcode_version = data;
> > > > > > >               break;
> > > > > > > +     case MSR_IA32_ARCH_CAPABILITIES:
> > > > > > > +             if (!msr_info->host_initiated ||
> > > > > > > +                 (data & ~kvm_get_arch_capabilities()))
> > > > > > > +                     return 1;
> > > > >
> > > > > As I mentioned in the PATCH 1 thread, we'd still like to be able to
> > > > > set IA32_ARCH_CAPABILITIES.RSBA from userspace, even if it's not
> > > > > enumerated on the host.
> > > > >
> > > > > Aside from that, this patch looks good to me. Thanks for the fix. I'll
> > > > > try to be more cognizant of AMD in the future.
> > > >
> > > > Hi, Jim,
> > > >
> > > > It's clear now. It is your negligence that simply enforce this cpuid for
> > > > all x86
> > > > arch.
> > >
> > > Ouch! That's harsh...and a bit supercilious.
> > >
> > > It didn't occur to me at the time, but kvm *should* emulate
> > > IA32_ARCH_CAPABILITIES for AMD as well as Intel, to support
> > > cross-vendor migration. If there are any Intel machines in the
> > > migration pool that are vulnerable to exploits of empty RSB
> > > conditions, userspace should be reporting IA32_ARCH_CAPABILITIES.RSBA
> > > regardless of virtual CPU vendor, and to do so,
> > > CPUID.(EAX=07H,ECX=00H):EDX[29] must be enumerated as well.
> > >
> > > Again, thanks for fixing this.
> >
> > Note that you should probably also remove the 'case
> > MSR_IA32_ARCH_CAPABILITIES' from svm_has_emulated_msr().
>
> Thanks for your reminder. We don't need to remove the 'case
> MSR_IA32_ARCH_CAPABILITIES', because there doesn't have and
> svm_has_emulated_msr() return true by default.

Ah. That's because Paolo never applied my changes to fix the AMD
issue. See https://patchwork.kernel.org/patch/10784295/ and
https://patchwork.kernel.org/patch/10784297/. The local branch I was
looking at still has those changes.
Xiaoyao Li March 13, 2019, 4:10 a.m. UTC | #9
On Tue, 2019-03-12 at 20:40 -0700, Jim Mattson wrote:
> On Tue, Mar 12, 2019 at 7:02 PM Xiaoyao Li <xiaoyao.li@linux.intel.com> wrote:
> > 
> > On Tue, 2019-03-12 at 12:02 -0700, Jim Mattson wrote:
> > > On Tue, Mar 12, 2019 at 11:45 AM Jim Mattson <jmattson@google.com> wrote:
> > > > 
> > > > On Mon, Mar 11, 2019 at 8:12 PM Xiaoyao Li <xiaoyao.li@linux.intel.com>
> > > > wrote:
> > > > > 
> > > > > On Mon, 2019-03-11 at 14:59 -0700, Jim Mattson wrote:
> > > > > > On Fri, Mar 8, 2019 at 7:32 AM Sean Christopherson
> > > > > > <sean.j.christopherson@intel.com> wrote:
> > > > > > > 
> > > > > > > On Thu, Mar 07, 2019 at 03:43:02PM -0800, Sean Christopherson
> > > > > > > wrote:
> > > > > > > > The CPUID flag ARCH_CAPABILITIES is unconditioinally exposed to
> > > > > > > > host
> > > > > > > > userspace for all x86 hosts, i.e. KVM advertises
> > > > > > > > ARCH_CAPABILITIES
> > > > > > > > regardless of hardware support under the pretense that KVM fully
> > > > > > > > emulates MSR_IA32_ARCH_CAPABILITIES.  Unfortunately, only VMX
> > > > > > > > hosts
> > > > > > > > handle accesses to MSR_IA32_ARCH_CAPABILITIES (despite
> > > > > > > > KVM_GET_MSRS
> > > > > > > > also reporting MSR_IA32_ARCH_CAPABILITIES for all hosts).
> > > > > > > > 
> > > > > > > > Move the MSR_IA32_ARCH_CAPABILITIES handling to common x86 code
> > > > > > > > so
> > > > > > > > that it's emulated on AMD hosts.
> > > > > > > > 
> > > > > > > > Fixes: 1eaafe91a0df4 ("kvm: x86: IA32_ARCH_CAPABILITIES is
> > > > > > > > always
> > > > > > > > supported")
> > > > > > > 
> > > > > > > And this one should have:
> > > > > > > 
> > > > > > >   Cc: stable@vger.kernel.org
> > > > > > > 
> > > > > > > > Reported-by: Xiaoyao Li <xiaoyao.li@linux.intel.com>
> > > > > > > > Cc: Jim Mattson <jmattson@google.com>
> > > > > > > > Signed-off-by: Sean Christopherson <
> > > > > > > > sean.j.christopherson@intel.com>
> > > > > > > > ---
> > > > > > > >  arch/x86/include/asm/kvm_host.h |  1 +
> > > > > > > >  arch/x86/kvm/vmx/vmx.c          | 14 --------------
> > > > > > > >  arch/x86/kvm/vmx/vmx.h          |  1 -
> > > > > > > >  arch/x86/kvm/x86.c              | 13 +++++++++++++
> > > > > > > >  4 files changed, 14 insertions(+), 15 deletions(-)
> > > > > > > > 
> > > > > > > > diff --git a/arch/x86/include/asm/kvm_host.h
> > > > > > > > b/arch/x86/include/asm/kvm_host.h
> > > > > > > > index 7712b4ed8aa1..3d10ff38cbdb 100644
> > > > > > > > --- a/arch/x86/include/asm/kvm_host.h
> > > > > > > > +++ b/arch/x86/include/asm/kvm_host.h
> > > > > > > > @@ -568,6 +568,7 @@ struct kvm_vcpu_arch {
> > > > > > > >       bool tpr_access_reporting;
> > > > > > > >       u64 ia32_xss;
> > > > > > > >       u64 microcode_version;
> > > > > > > > +     u64 arch_capabilities;
> > > > > > > > 
> > > > > > > >       /*
> > > > > > > >        * Paging state of the vcpu
> > > > > > > > diff --git a/arch/x86/kvm/vmx/vmx.c b/arch/x86/kvm/vmx/vmx.c
> > > > > > > > index 2a86d296c90f..02cf8a551bd1 100644
> > > > > > > > --- a/arch/x86/kvm/vmx/vmx.c
> > > > > > > > +++ b/arch/x86/kvm/vmx/vmx.c
> > > > > > > > @@ -1682,12 +1682,6 @@ static int vmx_get_msr(struct kvm_vcpu
> > > > > > > > *vcpu,
> > > > > > > > struct msr_data *msr_info)
> > > > > > > > 
> > > > > > > >               msr_info->data = to_vmx(vcpu)->spec_ctrl;
> > > > > > > >               break;
> > > > > > > > -     case MSR_IA32_ARCH_CAPABILITIES:
> > > > > > > > -             if (!msr_info->host_initiated &&
> > > > > > > > -                 !guest_cpuid_has(vcpu,
> > > > > > > > X86_FEATURE_ARCH_CAPABILITIES))
> > > > > > > > -                     return 1;
> > > > > > > > -             msr_info->data = to_vmx(vcpu)->arch_capabilities;
> > > > > > > > -             break;
> > > > > > > >       case MSR_IA32_SYSENTER_CS:
> > > > > > > >               msr_info->data = vmcs_read32(GUEST_SYSENTER_CS);
> > > > > > > >               break;
> > > > > > > > @@ -1894,12 +1888,6 @@ static int vmx_set_msr(struct kvm_vcpu
> > > > > > > > *vcpu,
> > > > > > > > struct msr_data *msr_info)
> > > > > > > >               vmx_disable_intercept_for_msr(vmx-
> > > > > > > > >vmcs01.msr_bitmap,
> > > > > > > > MSR_IA32_PRED_CMD,
> > > > > > > >                                             MSR_TYPE_W);
> > > > > > > >               break;
> > > > > > > > -     case MSR_IA32_ARCH_CAPABILITIES:
> > > > > > > > -             if (!msr_info->host_initiated ||
> > > > > > > > -                 (data & ~kvm_get_arch_capabilities()))
> > > > > > > > -                     return 1;
> > > > > > > > -             vmx->arch_capabilities = data;
> > > > > > > > -             break;
> > > > > > > >       case MSR_IA32_CR_PAT:
> > > > > > > >               if (vmcs_config.vmentry_ctrl &
> > > > > > > > VM_ENTRY_LOAD_IA32_PAT)
> > > > > > > > {
> > > > > > > >                       if (!kvm_mtrr_valid(vcpu, MSR_IA32_CR_PAT,
> > > > > > > > data))
> > > > > > > > @@ -4088,8 +4076,6 @@ static void vmx_vcpu_setup(struct vcpu_vmx
> > > > > > > > *vmx)
> > > > > > > >               ++vmx->nmsrs;
> > > > > > > >       }
> > > > > > > > 
> > > > > > > > -     vmx->arch_capabilities = kvm_get_arch_capabilities();
> > > > > > > > -
> > > > > > > >       vm_exit_controls_init(vmx, vmx_vmexit_ctrl());
> > > > > > > > 
> > > > > > > >       /* 22.2.1, 20.8.1 */
> > > > > > > > diff --git a/arch/x86/kvm/vmx/vmx.h b/arch/x86/kvm/vmx/vmx.h
> > > > > > > > index 1554cb45b393..a1e00d0a2482 100644
> > > > > > > > --- a/arch/x86/kvm/vmx/vmx.h
> > > > > > > > +++ b/arch/x86/kvm/vmx/vmx.h
> > > > > > > > @@ -190,7 +190,6 @@ struct vcpu_vmx {
> > > > > > > >       u64                   msr_guest_kernel_gs_base;
> > > > > > > >  #endif
> > > > > > > > 
> > > > > > > > -     u64                   arch_capabilities;
> > > > > > > >       u64                   spec_ctrl;
> > > > > > > > 
> > > > > > > >       u32 vm_entry_controls_shadow;
> > > > > > > > diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
> > > > > > > > index d90f011f3e32..7bfeebc482c4 100644
> > > > > > > > --- a/arch/x86/kvm/x86.c
> > > > > > > > +++ b/arch/x86/kvm/x86.c
> > > > > > > > @@ -2443,6 +2443,12 @@ int kvm_set_msr_common(struct kvm_vcpu
> > > > > > > > *vcpu,
> > > > > > > > struct msr_data *msr_info)
> > > > > > > >               if (msr_info->host_initiated)
> > > > > > > >                       vcpu->arch.microcode_version = data;
> > > > > > > >               break;
> > > > > > > > +     case MSR_IA32_ARCH_CAPABILITIES:
> > > > > > > > +             if (!msr_info->host_initiated ||
> > > > > > > > +                 (data & ~kvm_get_arch_capabilities()))
> > > > > > > > +                     return 1;
> > > > > > 
> > > > > > As I mentioned in the PATCH 1 thread, we'd still like to be able to
> > > > > > set IA32_ARCH_CAPABILITIES.RSBA from userspace, even if it's not
> > > > > > enumerated on the host.
> > > > > > 
> > > > > > Aside from that, this patch looks good to me. Thanks for the fix.
> > > > > > I'll
> > > > > > try to be more cognizant of AMD in the future.
> > > > > 
> > > > > Hi, Jim,
> > > > > 
> > > > > It's clear now. It is your negligence that simply enforce this cpuid
> > > > > for
> > > > > all x86
> > > > > arch.
> > > > 
> > > > Ouch! That's harsh...and a bit supercilious.
> > > > 
> > > > It didn't occur to me at the time, but kvm *should* emulate
> > > > IA32_ARCH_CAPABILITIES for AMD as well as Intel, to support
> > > > cross-vendor migration. If there are any Intel machines in the
> > > > migration pool that are vulnerable to exploits of empty RSB
> > > > conditions, userspace should be reporting IA32_ARCH_CAPABILITIES.RSBA
> > > > regardless of virtual CPU vendor, and to do so,
> > > > CPUID.(EAX=07H,ECX=00H):EDX[29] must be enumerated as well.
> > > > 
> > > > Again, thanks for fixing this.
> > > 
> > > Note that you should probably also remove the 'case
> > > MSR_IA32_ARCH_CAPABILITIES' from svm_has_emulated_msr().
> > 
> > Thanks for your reminder. We don't need to remove the 'case
> > MSR_IA32_ARCH_CAPABILITIES', because there doesn't have and
> > svm_has_emulated_msr() return true by default.
> 
> Ah. That's because Paolo never applied my changes to fix the AMD
> issue. See https://patchwork.kernel.org/patch/10784295/ and
> https://patchwork.kernel.org/patch/10784297/. The local branch I was
> looking at still has those changes.

Yes, I found your fix patches in the maillist just now.
I am so sorry about sending the fix patches without checking you have already
sent out fix serires, and so sorry about the reply yesterday. I might use the
wrong word, anyway, no offense.

And now, as you said, kvm *should* emulate IA32_ARCH_CAPABILITIES for AMD as
well as Intel. Sean's this patch fixes the most part. Also we need your patch 
https://patchwork.kernel.org/patch/10784297/. to move IA32_ARCH_CAPABILITIES
from msrs_to_save[] to emulated_msrs[], while removing the 'case
MSR_IA32_ARCH_CAPABILITIES' part.

That's enough, right?
Jim Mattson March 13, 2019, 4:28 p.m. UTC | #10
On Tue, Mar 12, 2019 at 9:13 PM Xiaoyao Li <xiaoyao.li@linux.intel.com> wrote:

> Yes, I found your fix patches in the maillist just now.
> I am so sorry about sending the fix patches without checking you have already
> sent out fix serires, and so sorry about the reply yesterday. I might use the
> wrong word, anyway, no offense.

No problem. It's a word I imagine you're hearing a lot at Intel these days. :-)

> And now, as you said, kvm *should* emulate IA32_ARCH_CAPABILITIES for AMD as
> well as Intel. Sean's this patch fixes the most part. Also we need your patch
> https://patchwork.kernel.org/patch/10784297/. to move IA32_ARCH_CAPABILITIES
> from msrs_to_save[] to emulated_msrs[], while removing the 'case
> MSR_IA32_ARCH_CAPABILITIES' part.
>
> That's enough, right?

At the risk of beating a dead horse, yes, with the caveat that
userspace should not be restricted from setting bits in the virtual
MSR that aren't set in the physical MSR.
diff mbox series

Patch

diff --git a/arch/x86/include/asm/kvm_host.h b/arch/x86/include/asm/kvm_host.h
index 7712b4ed8aa1..3d10ff38cbdb 100644
--- a/arch/x86/include/asm/kvm_host.h
+++ b/arch/x86/include/asm/kvm_host.h
@@ -568,6 +568,7 @@  struct kvm_vcpu_arch {
 	bool tpr_access_reporting;
 	u64 ia32_xss;
 	u64 microcode_version;
+	u64 arch_capabilities;
 
 	/*
 	 * Paging state of the vcpu
diff --git a/arch/x86/kvm/vmx/vmx.c b/arch/x86/kvm/vmx/vmx.c
index 2a86d296c90f..02cf8a551bd1 100644
--- a/arch/x86/kvm/vmx/vmx.c
+++ b/arch/x86/kvm/vmx/vmx.c
@@ -1682,12 +1682,6 @@  static int vmx_get_msr(struct kvm_vcpu *vcpu, struct msr_data *msr_info)
 
 		msr_info->data = to_vmx(vcpu)->spec_ctrl;
 		break;
-	case MSR_IA32_ARCH_CAPABILITIES:
-		if (!msr_info->host_initiated &&
-		    !guest_cpuid_has(vcpu, X86_FEATURE_ARCH_CAPABILITIES))
-			return 1;
-		msr_info->data = to_vmx(vcpu)->arch_capabilities;
-		break;
 	case MSR_IA32_SYSENTER_CS:
 		msr_info->data = vmcs_read32(GUEST_SYSENTER_CS);
 		break;
@@ -1894,12 +1888,6 @@  static int vmx_set_msr(struct kvm_vcpu *vcpu, struct msr_data *msr_info)
 		vmx_disable_intercept_for_msr(vmx->vmcs01.msr_bitmap, MSR_IA32_PRED_CMD,
 					      MSR_TYPE_W);
 		break;
-	case MSR_IA32_ARCH_CAPABILITIES:
-		if (!msr_info->host_initiated ||
-		    (data & ~kvm_get_arch_capabilities()))
-			return 1;
-		vmx->arch_capabilities = data;
-		break;
 	case MSR_IA32_CR_PAT:
 		if (vmcs_config.vmentry_ctrl & VM_ENTRY_LOAD_IA32_PAT) {
 			if (!kvm_mtrr_valid(vcpu, MSR_IA32_CR_PAT, data))
@@ -4088,8 +4076,6 @@  static void vmx_vcpu_setup(struct vcpu_vmx *vmx)
 		++vmx->nmsrs;
 	}
 
-	vmx->arch_capabilities = kvm_get_arch_capabilities();
-
 	vm_exit_controls_init(vmx, vmx_vmexit_ctrl());
 
 	/* 22.2.1, 20.8.1 */
diff --git a/arch/x86/kvm/vmx/vmx.h b/arch/x86/kvm/vmx/vmx.h
index 1554cb45b393..a1e00d0a2482 100644
--- a/arch/x86/kvm/vmx/vmx.h
+++ b/arch/x86/kvm/vmx/vmx.h
@@ -190,7 +190,6 @@  struct vcpu_vmx {
 	u64		      msr_guest_kernel_gs_base;
 #endif
 
-	u64		      arch_capabilities;
 	u64		      spec_ctrl;
 
 	u32 vm_entry_controls_shadow;
diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
index d90f011f3e32..7bfeebc482c4 100644
--- a/arch/x86/kvm/x86.c
+++ b/arch/x86/kvm/x86.c
@@ -2443,6 +2443,12 @@  int kvm_set_msr_common(struct kvm_vcpu *vcpu, struct msr_data *msr_info)
 		if (msr_info->host_initiated)
 			vcpu->arch.microcode_version = data;
 		break;
+	case MSR_IA32_ARCH_CAPABILITIES:
+		if (!msr_info->host_initiated ||
+		    (data & ~kvm_get_arch_capabilities()))
+			return 1;
+		vcpu->arch.arch_capabilities = data;
+		break;
 	case MSR_EFER:
 		return set_efer(vcpu, data);
 	case MSR_K7_HWCR:
@@ -2747,6 +2753,12 @@  int kvm_get_msr_common(struct kvm_vcpu *vcpu, struct msr_data *msr_info)
 	case MSR_IA32_UCODE_REV:
 		msr_info->data = vcpu->arch.microcode_version;
 		break;
+	case MSR_IA32_ARCH_CAPABILITIES:
+		if (!msr_info->host_initiated &&
+		    !guest_cpuid_has(vcpu, X86_FEATURE_ARCH_CAPABILITIES))
+			return 1;
+		msr_info->data = vcpu->arch.arch_capabilities;
+		break;
 	case MSR_IA32_TSC:
 		msr_info->data = kvm_scale_tsc(vcpu, rdtsc()) + vcpu->arch.tsc_offset;
 		break;
@@ -8743,6 +8755,7 @@  struct kvm_vcpu *kvm_arch_vcpu_create(struct kvm *kvm,
 
 int kvm_arch_vcpu_setup(struct kvm_vcpu *vcpu)
 {
+	vcpu->arch.arch_capabilities = kvm_get_arch_capabilities();
 	vcpu->arch.msr_platform_info = MSR_PLATFORM_INFO_CPUID_FAULT;
 	kvm_vcpu_mtrr_init(vcpu);
 	vcpu_load(vcpu);