]> git.proxmox.com Git - mirror_ubuntu-artful-kernel.git/commitdiff
KVM: SVM: Implement VIRT_SPEC_CTRL support for SSBD
authorTom Lendacky <thomas.lendacky@amd.com>
Thu, 10 May 2018 20:06:39 +0000 (22:06 +0200)
committerStefan Bader <stefan.bader@canonical.com>
Thu, 24 May 2018 07:59:19 +0000 (09:59 +0200)
Expose the new virtualized architectural mechanism, VIRT_SSBD, for using
speculative store bypass disable (SSBD) under SVM.  This will allow guests
to use SSBD on hardware that uses non-architectural mechanisms for enabling
SSBD.

[ tglx: Folded the migration fixup from Paolo Bonzini ]

Signed-off-by: Tom Lendacky <thomas.lendacky@amd.com>
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
CVE-2018-3639 (x86)

(backported from commit bc226f07dcd3c9ef0b7f6236fe356ea4a9cb4769)
Signed-off-by: Tyler Hicks <tyhicks@canonical.com>
Signed-off-by: Stefan Bader <stefan.bader@canonical.com>
arch/x86/include/asm/kvm_host.h
arch/x86/kernel/cpu/amd.c
arch/x86/kvm/cpuid.c
arch/x86/kvm/cpuid.h
arch/x86/kvm/svm.c
arch/x86/kvm/vmx.c
arch/x86/kvm/x86.c

index 1953c0a5b97209ff5b2e5f373f57145715088b22..ae5552cb7a56d499703b927f02cfa37a23b2a8fe 100644 (file)
@@ -906,7 +906,7 @@ struct kvm_x86_ops {
        int (*hardware_setup)(void);               /* __init */
        void (*hardware_unsetup)(void);            /* __exit */
        bool (*cpu_has_accelerated_tpr)(void);
-       bool (*cpu_has_high_real_mode_segbase)(void);
+       bool (*has_emulated_msr)(int index);
        void (*cpuid_update)(struct kvm_vcpu *vcpu);
 
        int (*vm_init)(struct kvm *kvm);
index 191cfec92ec89fbe4b30677a9c8de9eee62a64e0..9704fbe0b7ad30087c3909dd760387d8b8bd4c94 100644 (file)
@@ -904,7 +904,8 @@ static void init_amd(struct cpuinfo_x86 *c)
                }
        }
 
-       if (cpu_has(c, X86_FEATURE_SPEC_CTRL_SSBD))
+       if (cpu_has(c, X86_FEATURE_SPEC_CTRL_SSBD) ||
+           cpu_has(c, X86_FEATURE_VIRT_SSBD))
                set_cpu_cap(c, X86_FEATURE_SSBD);
 }
 
index 14f5cf5c7bf4ea8f70c52773cad70cfe1586a29c..a6199c9c1b63421d9201a23c8e67360570921902 100644 (file)
@@ -394,7 +394,7 @@ static inline int __do_cpuid_ent(struct kvm_cpuid_entry2 *entry, u32 function,
 
        /* cpuid 0x80000008.0.ebx */
        const u32 kvm_cpuid_80000008_0_ebx_x86_features =
-               F(AMD_IBPB);
+               F(AMD_IBPB) | F(VIRT_SSBD);
 
        /* all calls to cpuid_count() should be made on the same cpu */
        get_cpu();
@@ -631,8 +631,12 @@ static inline int __do_cpuid_ent(struct kvm_cpuid_entry2 *entry, u32 function,
                entry->eax = g_phys_as | (virt_as << 8);
                if (boot_cpu_has(X86_FEATURE_AMD_IBPB))
                        entry->ebx |= F(AMD_IBPB);
+               if (boot_cpu_has(X86_FEATURE_VIRT_SSBD))
+                       entry->ebx |= F(VIRT_SSBD);
                entry->ebx &= kvm_cpuid_80000008_0_ebx_x86_features;
                cpuid_mask(&entry->ebx, CPUID_8000_0008_EBX);
+               if (boot_cpu_has(X86_FEATURE_LS_CFG_SSBD))
+                       entry->ebx |= F(VIRT_SSBD);
                entry->edx = 0;
                break;
        }
index da67283830521dcdee6071c8b3d78225aed7ead0..6e1fa2329bf51a045e8b3413c312c4b662304350 100644 (file)
@@ -180,6 +180,14 @@ static inline bool guest_cpuid_has_nrips(struct kvm_vcpu *vcpu)
 }
 #undef BIT_NRIPS
 
+static inline int guest_cpuid_has_virt_ssbd(struct kvm_vcpu *vcpu)
+{
+       struct kvm_cpuid_entry2 *best;
+
+       best = kvm_find_cpuid_entry(vcpu, 0x80000008, 0);
+       return best && (best->ebx & bit(X86_FEATURE_VIRT_SSBD));
+}
+
 static inline int guest_cpuid_family(struct kvm_vcpu *vcpu)
 {
        struct kvm_cpuid_entry2 *best;
index ce546cb07cebf23b6e0d1e436004170d69aaf570..068084c8e540eafe2839d454149e02dbb1ea0a70 100644 (file)
@@ -3581,6 +3581,13 @@ static int svm_get_msr(struct kvm_vcpu *vcpu, struct msr_data *msr_info)
        case MSR_IA32_UCODE_REV:
                msr_info->data = 0x01000065;
                break;
+       case MSR_AMD64_VIRT_SPEC_CTRL:
+               if (!msr_info->host_initiated &&
+                   !guest_cpuid_has_virt_ssbd(vcpu))
+                       return 1;
+
+               msr_info->data = svm->virt_spec_ctrl;
+               break;
        case MSR_F15H_IC_CFG: {
 
                int family, model;
@@ -3662,6 +3669,16 @@ static int svm_set_msr(struct kvm_vcpu *vcpu, struct msr_data *msr)
        case MSR_IA32_TSC:
                kvm_write_tsc(vcpu, msr);
                break;
+       case MSR_AMD64_VIRT_SPEC_CTRL:
+               if (!msr->host_initiated &&
+                   !guest_cpuid_has_virt_ssbd(vcpu))
+                       return 1;
+
+               if (data & ~SPEC_CTRL_SSBD)
+                       return 1;
+
+               svm->virt_spec_ctrl = data;
+               break;
        case MSR_STAR:
                svm->vmcb->save.star = data;
                break;
@@ -5120,7 +5137,7 @@ static bool svm_cpu_has_accelerated_tpr(void)
        return false;
 }
 
-static bool svm_has_high_real_mode_segbase(void)
+static bool svm_has_emulated_msr(int index)
 {
        return true;
 }
@@ -5429,7 +5446,7 @@ static struct kvm_x86_ops svm_x86_ops __ro_after_init = {
        .hardware_enable = svm_hardware_enable,
        .hardware_disable = svm_hardware_disable,
        .cpu_has_accelerated_tpr = svm_cpu_has_accelerated_tpr,
-       .cpu_has_high_real_mode_segbase = svm_has_high_real_mode_segbase,
+       .has_emulated_msr = svm_has_emulated_msr,
 
        .vcpu_create = svm_create_vcpu,
        .vcpu_free = svm_free_vcpu,
index d50711c947e35f46fec534236ebd19bf2a4602ba..54980817194a99359cb4b1aee855e050ffcdc272 100644 (file)
@@ -8881,9 +8881,21 @@ static void vmx_handle_external_intr(struct kvm_vcpu *vcpu)
 }
 STACK_FRAME_NON_STANDARD(vmx_handle_external_intr);
 
-static bool vmx_has_high_real_mode_segbase(void)
+static bool vmx_has_emulated_msr(int index)
 {
-       return enable_unrestricted_guest || emulate_invalid_guest_state;
+       switch (index) {
+       case MSR_IA32_SMBASE:
+               /*
+                * We cannot do SMM unless we can run the guest in big
+                * real mode.
+                */
+               return enable_unrestricted_guest || emulate_invalid_guest_state;
+       case MSR_AMD64_VIRT_SPEC_CTRL:
+               /* This is AMD only.  */
+               return false;
+       default:
+               return true;
+       }
 }
 
 static bool vmx_mpx_supported(void)
@@ -11749,7 +11761,7 @@ static struct kvm_x86_ops vmx_x86_ops __ro_after_init = {
        .hardware_enable = hardware_enable,
        .hardware_disable = hardware_disable,
        .cpu_has_accelerated_tpr = report_flexpriority,
-       .cpu_has_high_real_mode_segbase = vmx_has_high_real_mode_segbase,
+       .has_emulated_msr = vmx_has_emulated_msr,
 
        .vcpu_create = vmx_create_vcpu,
        .vcpu_free = vmx_free_vcpu,
index a1fc2470f3e1a546557b69a58f2e0c99938d780e..538e6c83e337b73cdbb163f0c5bf357384e2706b 100644 (file)
@@ -1012,6 +1012,7 @@ static u32 emulated_msrs[] = {
        MSR_IA32_SMBASE,
        MSR_PLATFORM_INFO,
        MSR_MISC_FEATURES_ENABLES,
+       MSR_AMD64_VIRT_SPEC_CTRL,
 };
 
 static unsigned num_emulated_msrs;
@@ -2700,7 +2701,7 @@ int kvm_vm_ioctl_check_extension(struct kvm *kvm, long ext)
                 * fringe case that is not enabled except via specific settings
                 * of the module parameters.
                 */
-               r = kvm_x86_ops->cpu_has_high_real_mode_segbase();
+               r = kvm_x86_ops->has_emulated_msr(MSR_IA32_SMBASE);
                break;
        case KVM_CAP_VAPIC:
                r = !kvm_x86_ops->cpu_has_accelerated_tpr();
@@ -4285,14 +4286,8 @@ static void kvm_init_msr_list(void)
        num_msrs_to_save = j;
 
        for (i = j = 0; i < ARRAY_SIZE(emulated_msrs); i++) {
-               switch (emulated_msrs[i]) {
-               case MSR_IA32_SMBASE:
-                       if (!kvm_x86_ops->cpu_has_high_real_mode_segbase())
-                               continue;
-                       break;
-               default:
-                       break;
-               }
+               if (!kvm_x86_ops->has_emulated_msr(emulated_msrs[i]))
+                       continue;
 
                if (j < i)
                        emulated_msrs[j] = emulated_msrs[i];