From: Konrad Rzeszutek Wilk Date: Fri, 1 Jun 2018 14:59:20 +0000 (-0400) Subject: x86/bugs: Add AMD's SPEC_CTRL MSR usage X-Git-Tag: v4.1.12-124.31.3~284 X-Git-Url: https://www.infradead.org/git/?a=commitdiff_plain;h=6ed384dcb12d6b7f2b8a448810e56206b9db4fb7;p=users%2Fjedix%2Flinux-maple.git x86/bugs: Add AMD's SPEC_CTRL MSR usage The AMD document outlining the SSBD handling 124441_AMD64_SpeculativeStoreBypassDisable_Whitepaper_final.pdf mentions that if CPUID 8000_0008.EBX[24] is set we should be using the SPEC_CTRL MSR (0x48) over the VIRT SPEC_CTRL MSR (0xC001_011f) for speculative store bypass disable. This in effect means we should clear the X86_FEATURE_VIRT_SSBD flag so that we would prefer the SPEC_CTRL MSR. See the document titled: 124441_AMD64_SpeculativeStoreBypassDisable_Whitepaper_final.pdf A copy of this document is available at https://bugzilla.kernel.org/show_bug.cgi?id=199889 Signed-off-by: Konrad Rzeszutek Wilk Signed-off-by: Thomas Gleixner Cc: Tom Lendacky Cc: Janakarajan Natarajan Cc: kvm@vger.kernel.org Cc: KarimAllah Ahmed Cc: andrew.cooper3@citrix.com Cc: Joerg Roedel Cc: Radim Krčmář Cc: Andy Lutomirski Cc: "H. Peter Anvin" Cc: Paolo Bonzini Cc: Borislav Petkov Cc: David Woodhouse Cc: Kees Cook Link: https://lkml.kernel.org/r/20180601145921.9500-3-konrad.wilk@oracle.com (cherry picked from commit 6ac2f49edb1ef5446089c7c660017732886d62d6) Orabug: 28870524 CVE: CVE-2018-3639 Signed-off-by: Mihai Carabas Reviewed-by: Boris Ostrovsky Reviewed-by: Darren Kenny Signed-off-by: Brian Maly Conflicts: arch/x86/include/asm/cpufeatures.h arch/x86/kernel/cpu/bugs.c arch/x86/kernel/cpu/common.c arch/x86/kvm/cpuid.c arch/x86/kvm/svm.c The conflicts were due to different filenames (cpufeature.h, bugs_64.c) and different context. Signed-off-by: Brian Maly --- diff --git a/arch/x86/include/asm/cpufeature.h b/arch/x86/include/asm/cpufeature.h index edf15b54395c4..c39093d904a0b 100644 --- a/arch/x86/include/asm/cpufeature.h +++ b/arch/x86/include/asm/cpufeature.h @@ -73,6 +73,7 @@ */ #define X86_FEATURE_L1TF_PTEINV ( 2*32+0) /* "" L1TF workaround PTE inversion */ #define X86_FEATURE_FLUSH_L1D ( 2*32+1) /* Flush L1D cache */ +#define X86_FEATURE_AMD_SSBD ( 2*32+2) /* "" Speculative Store Bypass Disable */ /* Other features, Linux-defined mapping, word 3 */ /* This range is used for feature bits which conflict or are synthesized */ diff --git a/arch/x86/kernel/cpu/bugs_64.c b/arch/x86/kernel/cpu/bugs_64.c index d046b49feccb3..4518c670e8e21 100644 --- a/arch/x86/kernel/cpu/bugs_64.c +++ b/arch/x86/kernel/cpu/bugs_64.c @@ -1030,11 +1030,18 @@ static void __init ssb_init(void) if (ssb_mode == SPEC_STORE_BYPASS_DISABLE) { /* - * Intel uses the SPEC CTRL MSR Bit(2) for this, while AMD uses - * a completely different MSR and bit dependent on family. + * Intel uses the SPEC CTRL MSR Bit(2) for this, while AMD may + * use a completely different MSR and bit dependent on family. */ switch (boot_cpu_data.x86_vendor) { case X86_VENDOR_INTEL: + case X86_VENDOR_AMD: + if (ssb_mode == SPEC_STORE_BYPASS_DISABLE && + !static_cpu_has(X86_FEATURE_IBRS)) { + x86_amd_ssbd_enable(); + break; + } + x86_spec_ctrl_base |= SPEC_CTRL_SSBD; x86_spec_ctrl_mask |= SPEC_CTRL_SSBD; x86_spec_ctrl_priv |= SPEC_CTRL_SSBD; @@ -1043,10 +1050,6 @@ static void __init ssb_init(void) update_cpu_spec_ctrl_all(); break; - case X86_VENDOR_AMD: - if (ssb_mode == SPEC_STORE_BYPASS_DISABLE) - x86_amd_ssbd_enable(); - break; } } if (boot_cpu_has_bug(X86_BUG_SPEC_STORE_BYPASS)) diff --git a/arch/x86/kernel/cpu/common.c b/arch/x86/kernel/cpu/common.c index 43819120a021a..1f2b47ceede62 100644 --- a/arch/x86/kernel/cpu/common.c +++ b/arch/x86/kernel/cpu/common.c @@ -760,6 +760,8 @@ void get_cpu_cap(struct cpuinfo_x86 *c, enum get_cpu_cap_behavior behavior) set_cpu_cap(c, X86_FEATURE_IBRS); if (ebx & BIT(15)) set_cpu_cap(c, X86_FEATURE_STIBP); + if (ebx & BIT(24)) + set_cpu_cap(c, X86_FEATURE_AMD_SSBD); if (ebx & BIT(25)) set_cpu_cap(c, X86_FEATURE_VIRT_SSBD); } diff --git a/arch/x86/kvm/cpuid.c b/arch/x86/kvm/cpuid.c index 894acfa0a7f0a..1e5793aab0f27 100644 --- a/arch/x86/kvm/cpuid.c +++ b/arch/x86/kvm/cpuid.c @@ -56,7 +56,6 @@ u64 kvm_supported_xcr0(void) return xcr0; } - int kvm_update_cpuid(struct kvm_vcpu *vcpu) { struct kvm_cpuid_entry2 *best; @@ -358,7 +357,7 @@ static inline int __do_cpuid_ent(struct kvm_cpuid_entry2 *entry, u32 function, /* cpuid 0x80000008.ebx */ const u32 kvm_cpuid_80000008_ebx_x86_features = - KF(IBPB) | KF(IBRS) | KF(VIRT_SSBD); + KF(IBPB) | KF(IBRS) | KF(AMD_SSBD) | KF(VIRT_SSBD); /* all calls to cpuid_count() should be made on the same cpu */ get_cpu(); @@ -597,7 +596,12 @@ static inline int __do_cpuid_ent(struct kvm_cpuid_entry2 *entry, u32 function, if ( !boot_cpu_has(X86_FEATURE_IBPB) ) entry->ebx &= ~(1u << KVM_CPUID_BIT_IBPB); - if (boot_cpu_has(X86_FEATURE_LS_CFG_SSBD)) + /* + * The preference is to use SPEC CTRL MSR instead of the + * VIRT_SPEC MSR. + */ + if (boot_cpu_has(X86_FEATURE_LS_CFG_SSBD) && + !boot_cpu_has(X86_FEATURE_AMD_SSBD)) entry->ebx |= KF(VIRT_SSBD); break; } diff --git a/arch/x86/kvm/cpuid.h b/arch/x86/kvm/cpuid.h index 24a166ad0a983..61ccddc01f209 100644 --- a/arch/x86/kvm/cpuid.h +++ b/arch/x86/kvm/cpuid.h @@ -131,6 +131,7 @@ static inline bool guest_cpuid_has_mpx(struct kvm_vcpu *vcpu) /* These are scattered features in cpufeatures.h. */ #define KVM_CPUID_BIT_IBPB 12 +#define KVM_CPUID_BIT_AMD_SSBD 24 #define KVM_CPUID_BIT_VIRT_SSBD 25 #define KVM_CPUID_BIT_IBRS 26 #define KVM_CPUID_BIT_STIBP 27 @@ -160,4 +161,12 @@ static inline bool guest_cpuid_has_ssbd(struct kvm_vcpu *vcpu) best = kvm_find_cpuid_entry(vcpu, 7, 0); return best && (best->edx & KF(SSBD)); } + +static inline bool guest_cpuid_has_amd_ssbd(struct kvm_vcpu *vcpu) +{ + struct kvm_cpuid_entry2 *best; + + best = kvm_find_cpuid_entry(vcpu, 7, 0); + return best && (best->edx & KF(AMD_SSBD)); +} #endif diff --git a/arch/x86/kvm/svm.c b/arch/x86/kvm/svm.c index b6bf48bd74c91..2694d18319a7c 100644 --- a/arch/x86/kvm/svm.c +++ b/arch/x86/kvm/svm.c @@ -3178,7 +3178,7 @@ static int svm_get_msr(struct kvm_vcpu *vcpu, struct msr_data *msr_info) case MSR_IA32_SPEC_CTRL: if (!msr_info->host_initiated && !guest_cpuid_has_ibrs(vcpu) && - !guest_cpuid_has_ssbd(vcpu)) + !guest_cpuid_has_amd_ssbd(vcpu)) return 1; msr_info->data = svm->spec_ctrl; @@ -3308,11 +3308,11 @@ static int svm_set_msr(struct kvm_vcpu *vcpu, struct msr_data *msr) case MSR_IA32_SPEC_CTRL: if (!msr->host_initiated && !guest_cpuid_has_ibrs(vcpu) && - !guest_cpuid_has_ssbd(vcpu)) + !guest_cpuid_has_amd_ssbd(vcpu)) return 1; /* The STIBP bit doesn't fault even if it's not advertised */ - if (data & ~(SPEC_CTRL_IBRS | SPEC_CTRL_STIBP)) + if (data & ~(SPEC_CTRL_IBRS | SPEC_CTRL_STIBP | SPEC_CTRL_SSBD)) return 1; svm->spec_ctrl = data;