| From: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com> |
| Date: Fri, 1 Jun 2018 10:59:20 -0400 |
| Subject: x86/bugs: Add AMD's SPEC_CTRL MSR usage |
| MIME-Version: 1.0 |
| Content-Type: text/plain; charset=UTF-8 |
| Content-Transfer-Encoding: 8bit |
| |
| commit 6ac2f49edb1ef5446089c7c660017732886d62d6 upstream. |
| |
| 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 <konrad.wilk@oracle.com> |
| Signed-off-by: Thomas Gleixner <tglx@linutronix.de> |
| Cc: Tom Lendacky <thomas.lendacky@amd.com> |
| Cc: Janakarajan Natarajan <Janakarajan.Natarajan@amd.com> |
| Cc: kvm@vger.kernel.org |
| Cc: KarimAllah Ahmed <karahmed@amazon.de> |
| Cc: andrew.cooper3@citrix.com |
| Cc: Joerg Roedel <joro@8bytes.org> |
| Cc: Radim Krčmář <rkrcmar@redhat.com> |
| Cc: Andy Lutomirski <luto@kernel.org> |
| Cc: "H. Peter Anvin" <hpa@zytor.com> |
| Cc: Paolo Bonzini <pbonzini@redhat.com> |
| Cc: Borislav Petkov <bp@suse.de> |
| Cc: David Woodhouse <dwmw@amazon.co.uk> |
| Cc: Kees Cook <keescook@chromium.org> |
| Link: https://lkml.kernel.org/r/20180601145921.9500-3-konrad.wilk@oracle.com |
| [bwh: Backported to 3.16: |
| - The feature bit is in feature word 11 |
| - Update feature test in guest_cpuid_has_spec_ctrl() instead of |
| svm_{get,set}_msr() |
| - Adjust filenames, context] |
| Signed-off-by: Ben Hutchings <ben@decadent.org.uk> |
| --- |
| --- a/arch/x86/include/asm/cpufeature.h |
| +++ b/arch/x86/include/asm/cpufeature.h |
| @@ -256,6 +256,7 @@ |
| #define X86_FEATURE_AMD_IBPB (11*32+12) /* "" Indirect Branch Prediction Barrier */ |
| #define X86_FEATURE_AMD_IBRS (11*32+14) /* "" Indirect Branch Restricted Speculation */ |
| #define X86_FEATURE_AMD_STIBP (11*32+15) /* "" Single Thread Indirect Branch Predictors */ |
| +#define X86_FEATURE_AMD_SSBD (11*32+24) /* "" Speculative Store Bypass Disable */ |
| #define X86_FEATURE_VIRT_SSBD (11*32+25) /* Virtualized Speculative Store Bypass Disable */ |
| #define X86_FEATURE_AMD_SSB_NO (11*32+26) /* "" Speculative Store Bypass is fixed in hardware. */ |
| |
| --- a/arch/x86/kernel/cpu/bugs.c |
| +++ b/arch/x86/kernel/cpu/bugs.c |
| @@ -570,18 +570,20 @@ static enum ssb_mitigation __init __ssb_ |
| if (mode == SPEC_STORE_BYPASS_DISABLE) { |
| setup_force_cpu_cap(X86_FEATURE_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 (!static_cpu_has(X86_FEATURE_MSR_SPEC_CTRL)) { |
| + x86_amd_ssb_disable(); |
| + break; |
| + } |
| x86_spec_ctrl_base |= SPEC_CTRL_SSBD; |
| x86_spec_ctrl_mask |= SPEC_CTRL_SSBD; |
| wrmsrl(MSR_IA32_SPEC_CTRL, x86_spec_ctrl_base); |
| break; |
| - case X86_VENDOR_AMD: |
| - x86_amd_ssb_disable(); |
| - break; |
| } |
| } |
| |
| --- a/arch/x86/kernel/cpu/common.c |
| +++ b/arch/x86/kernel/cpu/common.c |
| @@ -716,6 +716,12 @@ static void init_speculation_control(str |
| set_cpu_cap(c, X86_FEATURE_STIBP); |
| set_cpu_cap(c, X86_FEATURE_MSR_SPEC_CTRL); |
| } |
| + |
| + if (cpu_has(c, X86_FEATURE_AMD_SSBD)) { |
| + set_cpu_cap(c, X86_FEATURE_SSBD); |
| + set_cpu_cap(c, X86_FEATURE_MSR_SPEC_CTRL); |
| + clear_cpu_cap(c, X86_FEATURE_VIRT_SSBD); |
| + } |
| } |
| |
| void get_cpu_cap(struct cpuinfo_x86 *c) |
| --- a/arch/x86/kvm/cpuid.c |
| +++ b/arch/x86/kvm/cpuid.c |
| @@ -302,7 +302,8 @@ static inline int __do_cpuid_ent(struct |
| |
| /* cpuid 0x80000008.ebx */ |
| const u32 kvm_cpuid_8000_0008_ebx_x86_features = |
| - F(AMD_IBPB) | F(AMD_IBRS) | F(VIRT_SSBD) | F(AMD_SSB_NO); |
| + F(AMD_IBPB) | F(AMD_IBRS) | F(AMD_SSBD) | F(VIRT_SSBD) | |
| + F(AMD_SSB_NO); |
| |
| /* cpuid 0xC0000001.edx */ |
| const u32 kvm_supported_word5_x86_features = |
| @@ -536,7 +537,12 @@ static inline int __do_cpuid_ent(struct |
| entry->ebx |= F(VIRT_SSBD); |
| entry->ebx &= kvm_cpuid_8000_0008_ebx_x86_features; |
| cpuid_mask(&entry->ebx, 11); |
| - 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 |= F(VIRT_SSBD); |
| break; |
| } |
| --- a/arch/x86/kvm/cpuid.h |
| +++ b/arch/x86/kvm/cpuid.h |
| @@ -120,7 +120,7 @@ static inline bool guest_cpuid_has_spec_ |
| struct kvm_cpuid_entry2 *best; |
| |
| best = kvm_find_cpuid_entry(vcpu, 0x80000008, 0); |
| - if (best && (best->ebx & bit(X86_FEATURE_AMD_IBRS))) |
| + if (best && (best->ebx & (bit(X86_FEATURE_AMD_IBRS | bit(X86_FEATURE_AMD_SSBD))))) |
| return true; |
| best = kvm_find_cpuid_entry(vcpu, 7, 0); |
| return best && (best->edx & (bit(X86_FEATURE_SPEC_CTRL) | bit(X86_FEATURE_SPEC_CTRL_SSBD))); |
| --- a/arch/x86/kvm/svm.c |
| +++ b/arch/x86/kvm/svm.c |
| @@ -3236,7 +3236,7 @@ static int svm_set_msr(struct kvm_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; |