[pve-devel] applied [PATCH] backport: KVM: x86: Emulate MSR_IA32_ARCH_CAPABILITIES on AMD hosts
Thomas Lamprecht
t.lamprecht at proxmox.com
Fri Jun 14 12:18:48 CEST 2019
backport this and supporting patches to ensure Ryzen/Epyc CPUs work
with QEMU and it's new MDS mitigation helpers, which also base on
MSRs
Signed-off-by: Thomas Lamprecht <t.lamprecht at proxmox.com>
---
0010 and 0011 where cleanly cherry picked for easier backporting of 0012.
The latter needed a bit of massaging, as upstream splitted up the vmx stuff in
it's own folder between 4.15 and 5.0, so while the hunks itself matched, it was
on the "wrong" file -> fixed that.
Wolfgang L., Dominik C. and Alwin A. reported positive feedback for testing
this, without a (yet) surfaced regression, so applied.
...VM-Take-vcpu-mutex-outside-vcpu_load.patch | 180 ++++++++++++++++++
...dify-MSR_PLATFORM_INFO-on-vCPU-reset.patch | 40 ++++
...MSR_IA32_ARCH_CAPABILITIES-on-AMD-ho.patch | 133 +++++++++++++
3 files changed, 353 insertions(+)
create mode 100644 patches/kernel/0010-KVM-Take-vcpu-mutex-outside-vcpu_load.patch
create mode 100644 patches/kernel/0011-kvm-x86-Don-t-modify-MSR_PLATFORM_INFO-on-vCPU-reset.patch
create mode 100644 patches/kernel/0012-KVM-x86-Emulate-MSR_IA32_ARCH_CAPABILITIES-on-AMD-ho.patch
diff --git a/patches/kernel/0010-KVM-Take-vcpu-mutex-outside-vcpu_load.patch b/patches/kernel/0010-KVM-Take-vcpu-mutex-outside-vcpu_load.patch
new file mode 100644
index 0000000..caf7c56
--- /dev/null
+++ b/patches/kernel/0010-KVM-Take-vcpu-mutex-outside-vcpu_load.patch
@@ -0,0 +1,180 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Christoffer Dall <christoffer.dall at linaro.org>
+Date: Mon, 4 Dec 2017 21:35:23 +0100
+Subject: [PATCH] KVM: Take vcpu->mutex outside vcpu_load
+
+As we're about to call vcpu_load() from architecture-specific
+implementations of the KVM vcpu ioctls, but yet we access data
+structures protected by the vcpu->mutex in the generic code, factor
+this logic out from vcpu_load().
+
+x86 is the only architecture which calls vcpu_load() outside of the main
+vcpu ioctl function, and these calls will no longer take the vcpu mutex
+following this patch. However, with the exception of
+kvm_arch_vcpu_postcreate (see below), the callers are either in the
+creation or destruction path of the VCPU, which means there cannot be
+any concurrent access to the data structure, because the file descriptor
+is not yet accessible, or is already gone.
+
+kvm_arch_vcpu_postcreate makes the newly created vcpu potentially
+accessible by other in-kernel threads through the kvm->vcpus array, and
+we therefore take the vcpu mutex in this case directly.
+
+Signed-off-by: Christoffer Dall <christoffer.dall at linaro.org>
+Reviewed-by: Cornelia Huck <cohuck at redhat.com>
+Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>
+(cherry picked from commit ec7660ccdd2b71d8c7f0243f8590253713e9b75d)
+Signed-off-by: Thomas Lamprecht <t.lamprecht at proxmox.com>
+---
+ arch/x86/kvm/vmx.c | 4 +---
+ arch/x86/kvm/x86.c | 20 +++++++-------------
+ include/linux/kvm_host.h | 2 +-
+ virt/kvm/kvm_main.c | 17 ++++++-----------
+ 4 files changed, 15 insertions(+), 28 deletions(-)
+
+diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c
+index bf348fee4bd5..38e50b40db5a 100644
+--- a/arch/x86/kvm/vmx.c
++++ b/arch/x86/kvm/vmx.c
+@@ -9959,10 +9959,8 @@ static void vmx_switch_vmcs(struct kvm_vcpu *vcpu, struct loaded_vmcs *vmcs)
+ static void vmx_free_vcpu_nested(struct kvm_vcpu *vcpu)
+ {
+ struct vcpu_vmx *vmx = to_vmx(vcpu);
+- int r;
+
+- r = vcpu_load(vcpu);
+- BUG_ON(r);
++ vcpu_load(vcpu);
+ vmx_switch_vmcs(vcpu, &vmx->vmcs01);
+ free_nested(vmx);
+ vcpu_put(vcpu);
+diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
+index ac17f53812af..c578a90f1128 100644
+--- a/arch/x86/kvm/x86.c
++++ b/arch/x86/kvm/x86.c
+@@ -7949,16 +7949,12 @@ struct kvm_vcpu *kvm_arch_vcpu_create(struct kvm *kvm,
+
+ int kvm_arch_vcpu_setup(struct kvm_vcpu *vcpu)
+ {
+- int r;
+-
+ kvm_vcpu_mtrr_init(vcpu);
+- r = vcpu_load(vcpu);
+- if (r)
+- return r;
++ vcpu_load(vcpu);
+ kvm_vcpu_reset(vcpu, false);
+ kvm_mmu_setup(vcpu);
+ vcpu_put(vcpu);
+- return r;
++ return 0;
+ }
+
+ void kvm_arch_vcpu_postcreate(struct kvm_vcpu *vcpu)
+@@ -7968,13 +7964,15 @@ void kvm_arch_vcpu_postcreate(struct kvm_vcpu *vcpu)
+
+ kvm_hv_vcpu_postcreate(vcpu);
+
+- if (vcpu_load(vcpu))
++ if (mutex_lock_killable(&vcpu->mutex))
+ return;
++ vcpu_load(vcpu);
+ msr.data = 0x0;
+ msr.index = MSR_IA32_TSC;
+ msr.host_initiated = true;
+ kvm_write_tsc(vcpu, &msr);
+ vcpu_put(vcpu);
++ mutex_unlock(&vcpu->mutex);
+
+ if (!kvmclock_periodic_sync)
+ return;
+@@ -7985,11 +7983,9 @@ void kvm_arch_vcpu_postcreate(struct kvm_vcpu *vcpu)
+
+ void kvm_arch_vcpu_destroy(struct kvm_vcpu *vcpu)
+ {
+- int r;
+ vcpu->arch.apf.msr_val = 0;
+
+- r = vcpu_load(vcpu);
+- BUG_ON(r);
++ vcpu_load(vcpu);
+ kvm_mmu_unload(vcpu);
+ vcpu_put(vcpu);
+
+@@ -8363,9 +8359,7 @@ int kvm_arch_init_vm(struct kvm *kvm, unsigned long type)
+
+ static void kvm_unload_vcpu_mmu(struct kvm_vcpu *vcpu)
+ {
+- int r;
+- r = vcpu_load(vcpu);
+- BUG_ON(r);
++ vcpu_load(vcpu);
+ kvm_mmu_unload(vcpu);
+ vcpu_put(vcpu);
+ }
+diff --git a/include/linux/kvm_host.h b/include/linux/kvm_host.h
+index c807eab9c1d3..6684da3f197f 100644
+--- a/include/linux/kvm_host.h
++++ b/include/linux/kvm_host.h
+@@ -533,7 +533,7 @@ static inline int kvm_vcpu_get_idx(struct kvm_vcpu *vcpu)
+ int kvm_vcpu_init(struct kvm_vcpu *vcpu, struct kvm *kvm, unsigned id);
+ void kvm_vcpu_uninit(struct kvm_vcpu *vcpu);
+
+-int __must_check vcpu_load(struct kvm_vcpu *vcpu);
++void vcpu_load(struct kvm_vcpu *vcpu);
+ void vcpu_put(struct kvm_vcpu *vcpu);
+
+ #ifdef __KVM_HAVE_IOAPIC
+diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c
+index 238ddbc127e1..0d2eddfdf785 100644
+--- a/virt/kvm/kvm_main.c
++++ b/virt/kvm/kvm_main.c
+@@ -151,17 +151,12 @@ bool kvm_is_reserved_pfn(kvm_pfn_t pfn)
+ /*
+ * Switches to specified vcpu, until a matching vcpu_put()
+ */
+-int vcpu_load(struct kvm_vcpu *vcpu)
++void vcpu_load(struct kvm_vcpu *vcpu)
+ {
+- int cpu;
+-
+- if (mutex_lock_killable(&vcpu->mutex))
+- return -EINTR;
+- cpu = get_cpu();
++ int cpu = get_cpu();
+ preempt_notifier_register(&vcpu->preempt_notifier);
+ kvm_arch_vcpu_load(vcpu, cpu);
+ put_cpu();
+- return 0;
+ }
+ EXPORT_SYMBOL_GPL(vcpu_load);
+
+@@ -171,7 +166,6 @@ void vcpu_put(struct kvm_vcpu *vcpu)
+ kvm_arch_vcpu_put(vcpu);
+ preempt_notifier_unregister(&vcpu->preempt_notifier);
+ preempt_enable();
+- mutex_unlock(&vcpu->mutex);
+ }
+ EXPORT_SYMBOL_GPL(vcpu_put);
+
+@@ -2562,9 +2556,9 @@ static long kvm_vcpu_ioctl(struct file *filp,
+ #endif
+
+
+- r = vcpu_load(vcpu);
+- if (r)
+- return r;
++ if (mutex_lock_killable(&vcpu->mutex))
++ return -EINTR;
++ vcpu_load(vcpu);
+ switch (ioctl) {
+ case KVM_RUN: {
+ struct pid *oldpid;
+@@ -2737,6 +2731,7 @@ static long kvm_vcpu_ioctl(struct file *filp,
+ }
+ out:
+ vcpu_put(vcpu);
++ mutex_unlock(&vcpu->mutex);
+ kfree(fpu);
+ kfree(kvm_sregs);
+ return r;
diff --git a/patches/kernel/0011-kvm-x86-Don-t-modify-MSR_PLATFORM_INFO-on-vCPU-reset.patch b/patches/kernel/0011-kvm-x86-Don-t-modify-MSR_PLATFORM_INFO-on-vCPU-reset.patch
new file mode 100644
index 0000000..d57a726
--- /dev/null
+++ b/patches/kernel/0011-kvm-x86-Don-t-modify-MSR_PLATFORM_INFO-on-vCPU-reset.patch
@@ -0,0 +1,40 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Jim Mattson <jmattson at google.com>
+Date: Tue, 30 Oct 2018 12:20:21 -0700
+Subject: [PATCH] kvm: x86: Don't modify MSR_PLATFORM_INFO on vCPU reset
+
+If userspace has provided a different value for this MSR (e.g with the
+turbo bits set), the userspace-provided value should survive a vCPU
+reset. For backwards compatibility, MSR_PLATFORM_INFO is initialized
+in kvm_arch_vcpu_setup.
+
+Signed-off-by: Jim Mattson <jmattson at google.com>
+Reviewed-by: Drew Schmitt <dasch at google.com>
+Cc: Abhiroop Dabral <adabral at paloaltonetworks.com>
+Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>
+(cherry picked from commit e53d88af63ab4104e1226b8f9959f1e9903da10b)
+Signed-off-by: Thomas Lamprecht <t.lamprecht at proxmox.com>
+---
+ arch/x86/kvm/x86.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
+index c578a90f1128..e1f16d02e44f 100644
+--- a/arch/x86/kvm/x86.c
++++ b/arch/x86/kvm/x86.c
+@@ -7949,6 +7949,7 @@ struct kvm_vcpu *kvm_arch_vcpu_create(struct kvm *kvm,
+
+ int kvm_arch_vcpu_setup(struct kvm_vcpu *vcpu)
+ {
++ vcpu->arch.msr_platform_info = MSR_PLATFORM_INFO_CPUID_FAULT;
+ kvm_vcpu_mtrr_init(vcpu);
+ vcpu_load(vcpu);
+ kvm_vcpu_reset(vcpu, false);
+@@ -8050,7 +8051,6 @@ void kvm_vcpu_reset(struct kvm_vcpu *vcpu, bool init_event)
+ kvm_pmu_reset(vcpu);
+ vcpu->arch.smbase = 0x30000;
+
+- vcpu->arch.msr_platform_info = MSR_PLATFORM_INFO_CPUID_FAULT;
+ vcpu->arch.msr_misc_features_enables = 0;
+
+ vcpu->arch.xcr0 = XFEATURE_MASK_FP;
diff --git a/patches/kernel/0012-KVM-x86-Emulate-MSR_IA32_ARCH_CAPABILITIES-on-AMD-ho.patch b/patches/kernel/0012-KVM-x86-Emulate-MSR_IA32_ARCH_CAPABILITIES-on-AMD-ho.patch
new file mode 100644
index 0000000..a5bdeac
--- /dev/null
+++ b/patches/kernel/0012-KVM-x86-Emulate-MSR_IA32_ARCH_CAPABILITIES-on-AMD-ho.patch
@@ -0,0 +1,133 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Sean Christopherson <sean.j.christopherson at intel.com>
+Date: Thu, 7 Mar 2019 15:43:02 -0800
+Subject: [PATCH] KVM: x86: Emulate MSR_IA32_ARCH_CAPABILITIES on AMD hosts
+
+BugLink: https://bugs.launchpad.net/bugs/1823060
+
+commit 0cf9135b773bf32fba9dd8e6699c1b331ee4b749 upstream.
+
+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")
+Cc: stable at vger.kernel.org
+Reported-by: Xiaoyao Li <xiaoyao.li at linux.intel.com>
+Cc: Jim Mattson <jmattson at google.com>
+Signed-off-by: Sean Christopherson <sean.j.christopherson at intel.com>
+Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh at linuxfoundation.org>
+
+Signed-off-by: Seth Forshee <seth.forshee at canonical.com>
+
+(back ported from commit 0cf9135b773bf32fba9dd8e6699c1b331ee4b749)
+Backported-by: Thomas Lamprecht <t.lamprecht at proxmox.com>
+Signed-off-by: Thomas Lamprecht <t.lamprecht at proxmox.com>
+---
+ arch/x86/include/asm/kvm_host.h | 1 +
+ arch/x86/kvm/vmx.c | 14 --------------
+ arch/x86/kvm/x86.c | 12 ++++++++++++
+ 3 files changed, 13 insertions(+), 14 deletions(-)
+
+diff --git a/arch/x86/include/asm/kvm_host.h b/arch/x86/include/asm/kvm_host.h
+index e76012ca0ddc..fa57f78dff2d 100644
+--- a/arch/x86/include/asm/kvm_host.h
++++ b/arch/x86/include/asm/kvm_host.h
+@@ -508,6 +508,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.c b/arch/x86/kvm/vmx.c
+index 38e50b40db5a..1911ec5e26c1 100644
+--- a/arch/x86/kvm/vmx.c
++++ b/arch/x86/kvm/vmx.c
+@@ -750,7 +750,6 @@ struct vcpu_vmx {
+ u64 msr_guest_kernel_gs_base;
+ #endif
+
+- u64 arch_capabilities;
+ u64 spec_ctrl;
+
+ u32 vm_entry_controls_shadow;
+@@ -3477,12 +3476,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;
+@@ -3644,11 +3637,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)
+- 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))
+@@ -5906,8 +5894,6 @@ static void vmx_vcpu_setup(struct vcpu_vmx *vmx)
+ ++vmx->nmsrs;
+ }
+
+- vmx->arch_capabilities = kvm_get_arch_capabilities();
+-
+ vm_exit_controls_init(vmx, vmcs_config.vmexit_ctrl);
+
+ /* 22.2.1, 20.8.1 */
+diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
+index e1f16d02e44f..bf76e7cd9837 100644
+--- a/arch/x86/kvm/x86.c
++++ b/arch/x86/kvm/x86.c
+@@ -2246,6 +2246,11 @@ 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)
++ return 1;
++ vcpu->arch.arch_capabilities = data;
++ break;
+ case MSR_EFER:
+ return set_efer(vcpu, data);
+ case MSR_K7_HWCR:
+@@ -2541,6 +2546,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;
+@@ -7949,6 +7960,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.20.1
More information about the pve-devel
mailing list