aboutsummaryrefslogtreecommitdiffstats
path: root/common/recipes-kernel/linux/linux-yocto-4.9.21/0010-x86-speculation-Use-IBRS-if-available-before-calling.patch
diff options
context:
space:
mode:
Diffstat (limited to 'common/recipes-kernel/linux/linux-yocto-4.9.21/0010-x86-speculation-Use-IBRS-if-available-before-calling.patch')
-rw-r--r--common/recipes-kernel/linux/linux-yocto-4.9.21/0010-x86-speculation-Use-IBRS-if-available-before-calling.patch232
1 files changed, 232 insertions, 0 deletions
diff --git a/common/recipes-kernel/linux/linux-yocto-4.9.21/0010-x86-speculation-Use-IBRS-if-available-before-calling.patch b/common/recipes-kernel/linux/linux-yocto-4.9.21/0010-x86-speculation-Use-IBRS-if-available-before-calling.patch
new file mode 100644
index 00000000..d5bd585e
--- /dev/null
+++ b/common/recipes-kernel/linux/linux-yocto-4.9.21/0010-x86-speculation-Use-IBRS-if-available-before-calling.patch
@@ -0,0 +1,232 @@
+From d65c0b72013dac24f4e2d0b031ed8bc6b71bfcca Mon Sep 17 00:00:00 2001
+From: David Woodhouse <dwmw@amazon.co.uk>
+Date: Mon, 19 Feb 2018 10:50:54 +0000
+Subject: [PATCH 10/14] x86/speculation: Use IBRS if available before calling
+ into firmware
+
+commit dd84441a797150dcc49298ec95c459a8891d8bb1 upstream.
+
+Retpoline means the kernel is safe because it has no indirect branches.
+But firmware isn't, so use IBRS for firmware calls if it's available.
+
+Block preemption while IBRS is set, although in practice the call sites
+already had to be doing that.
+
+Ignore hpwdt.c for now. It's taking spinlocks and calling into firmware
+code, from an NMI handler. I don't want to touch that with a bargepole.
+
+Signed-off-by: David Woodhouse <dwmw@amazon.co.uk>
+Reviewed-by: Thomas Gleixner <tglx@linutronix.de>
+Cc: Linus Torvalds <torvalds@linux-foundation.org>
+Cc: Peter Zijlstra <peterz@infradead.org>
+Cc: arjan.van.de.ven@intel.com
+Cc: bp@alien8.de
+Cc: dave.hansen@intel.com
+Cc: jmattson@google.com
+Cc: karahmed@amazon.de
+Cc: kvm@vger.kernel.org
+Cc: pbonzini@redhat.com
+Cc: rkrcmar@redhat.com
+Link: http://lkml.kernel.org/r/1519037457-7643-2-git-send-email-dwmw@amazon.co.uk
+Signed-off-by: Ingo Molnar <mingo@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ arch/x86/include/asm/apm.h | 6 ++++++
+ arch/x86/include/asm/cpufeatures.h | 1 +
+ arch/x86/include/asm/efi.h | 17 ++++++++++++++--
+ arch/x86/include/asm/nospec-branch.h | 39 +++++++++++++++++++++++++++---------
+ arch/x86/kernel/cpu/bugs.c | 12 ++++++++++-
+ 5 files changed, 63 insertions(+), 12 deletions(-)
+
+diff --git a/arch/x86/include/asm/apm.h b/arch/x86/include/asm/apm.h
+index 93eebc63..46e40ae 100644
+--- a/arch/x86/include/asm/apm.h
++++ b/arch/x86/include/asm/apm.h
+@@ -6,6 +6,8 @@
+ #ifndef _ASM_X86_MACH_DEFAULT_APM_H
+ #define _ASM_X86_MACH_DEFAULT_APM_H
+
++#include <asm/nospec-branch.h>
++
+ #ifdef APM_ZERO_SEGS
+ # define APM_DO_ZERO_SEGS \
+ "pushl %%ds\n\t" \
+@@ -31,6 +33,7 @@ static inline void apm_bios_call_asm(u32 func, u32 ebx_in, u32 ecx_in,
+ * N.B. We do NOT need a cld after the BIOS call
+ * because we always save and restore the flags.
+ */
++ firmware_restrict_branch_speculation_start();
+ __asm__ __volatile__(APM_DO_ZERO_SEGS
+ "pushl %%edi\n\t"
+ "pushl %%ebp\n\t"
+@@ -43,6 +46,7 @@ static inline void apm_bios_call_asm(u32 func, u32 ebx_in, u32 ecx_in,
+ "=S" (*esi)
+ : "a" (func), "b" (ebx_in), "c" (ecx_in)
+ : "memory", "cc");
++ firmware_restrict_branch_speculation_end();
+ }
+
+ static inline bool apm_bios_call_simple_asm(u32 func, u32 ebx_in,
+@@ -55,6 +59,7 @@ static inline bool apm_bios_call_simple_asm(u32 func, u32 ebx_in,
+ * N.B. We do NOT need a cld after the BIOS call
+ * because we always save and restore the flags.
+ */
++ firmware_restrict_branch_speculation_start();
+ __asm__ __volatile__(APM_DO_ZERO_SEGS
+ "pushl %%edi\n\t"
+ "pushl %%ebp\n\t"
+@@ -67,6 +72,7 @@ static inline bool apm_bios_call_simple_asm(u32 func, u32 ebx_in,
+ "=S" (si)
+ : "a" (func), "b" (ebx_in), "c" (ecx_in)
+ : "memory", "cc");
++ firmware_restrict_branch_speculation_end();
+ return error;
+ }
+
+diff --git a/arch/x86/include/asm/cpufeatures.h b/arch/x86/include/asm/cpufeatures.h
+index 8eb23f5..ed7a1d2 100644
+--- a/arch/x86/include/asm/cpufeatures.h
++++ b/arch/x86/include/asm/cpufeatures.h
+@@ -203,6 +203,7 @@
+ #define X86_FEATURE_KAISER ( 7*32+31) /* CONFIG_PAGE_TABLE_ISOLATION w/o nokaiser */
+
+ #define X86_FEATURE_USE_IBPB ( 7*32+21) /* "" Indirect Branch Prediction Barrier enabled */
++#define X86_FEATURE_USE_IBRS_FW ( 7*32+22) /* "" Use IBRS during runtime firmware calls */
+
+ /* Virtualization flags: Linux defined, word 8 */
+ #define X86_FEATURE_TPR_SHADOW ( 8*32+ 0) /* Intel TPR Shadow */
+diff --git a/arch/x86/include/asm/efi.h b/arch/x86/include/asm/efi.h
+index 389d700..9df22bb 100644
+--- a/arch/x86/include/asm/efi.h
++++ b/arch/x86/include/asm/efi.h
+@@ -5,6 +5,7 @@
+ #include <asm/pgtable.h>
+ #include <asm/processor-flags.h>
+ #include <asm/tlb.h>
++#include <asm/nospec-branch.h>
+
+ /*
+ * We map the EFI regions needed for runtime services non-contiguously,
+@@ -35,8 +36,18 @@
+
+ extern unsigned long asmlinkage efi_call_phys(void *, ...);
+
+-#define arch_efi_call_virt_setup() kernel_fpu_begin()
+-#define arch_efi_call_virt_teardown() kernel_fpu_end()
++#define arch_efi_call_virt_setup() \
++({ \
++ kernel_fpu_begin(); \
++ firmware_restrict_branch_speculation_start(); \
++})
++
++#define arch_efi_call_virt_teardown() \
++({ \
++ firmware_restrict_branch_speculation_end(); \
++ kernel_fpu_end(); \
++})
++
+
+ /*
+ * Wrap all the virtual calls in a way that forces the parameters on the stack.
+@@ -72,6 +83,7 @@ struct efi_scratch {
+ efi_sync_low_kernel_mappings(); \
+ preempt_disable(); \
+ __kernel_fpu_begin(); \
++ firmware_restrict_branch_speculation_start(); \
+ \
+ if (efi_scratch.use_pgd) { \
+ efi_scratch.prev_cr3 = read_cr3(); \
+@@ -90,6 +102,7 @@ struct efi_scratch {
+ __flush_tlb_all(); \
+ } \
+ \
++ firmware_restrict_branch_speculation_end(); \
+ __kernel_fpu_end(); \
+ preempt_enable(); \
+ })
+diff --git a/arch/x86/include/asm/nospec-branch.h b/arch/x86/include/asm/nospec-branch.h
+index dace2de..031840a 100644
+--- a/arch/x86/include/asm/nospec-branch.h
++++ b/arch/x86/include/asm/nospec-branch.h
+@@ -219,17 +219,38 @@ static inline void vmexit_fill_RSB(void)
+ #endif
+ }
+
++#define alternative_msr_write(_msr, _val, _feature) \
++ asm volatile(ALTERNATIVE("", \
++ "movl %[msr], %%ecx\n\t" \
++ "movl %[val], %%eax\n\t" \
++ "movl $0, %%edx\n\t" \
++ "wrmsr", \
++ _feature) \
++ : : [msr] "i" (_msr), [val] "i" (_val) \
++ : "eax", "ecx", "edx", "memory")
++
+ static inline void indirect_branch_prediction_barrier(void)
+ {
+- asm volatile(ALTERNATIVE("",
+- "movl %[msr], %%ecx\n\t"
+- "movl %[val], %%eax\n\t"
+- "movl $0, %%edx\n\t"
+- "wrmsr",
+- X86_FEATURE_USE_IBPB)
+- : : [msr] "i" (MSR_IA32_PRED_CMD),
+- [val] "i" (PRED_CMD_IBPB)
+- : "eax", "ecx", "edx", "memory");
++ alternative_msr_write(MSR_IA32_PRED_CMD, PRED_CMD_IBPB,
++ X86_FEATURE_USE_IBPB);
++}
++
++/*
++ * With retpoline, we must use IBRS to restrict branch prediction
++ * before calling into firmware.
++ */
++static inline void firmware_restrict_branch_speculation_start(void)
++{
++ preempt_disable();
++ alternative_msr_write(MSR_IA32_SPEC_CTRL, SPEC_CTRL_IBRS,
++ X86_FEATURE_USE_IBRS_FW);
++}
++
++static inline void firmware_restrict_branch_speculation_end(void)
++{
++ alternative_msr_write(MSR_IA32_SPEC_CTRL, 0,
++ X86_FEATURE_USE_IBRS_FW);
++ preempt_enable();
+ }
+
+ #endif /* __ASSEMBLY__ */
+diff --git a/arch/x86/kernel/cpu/bugs.c b/arch/x86/kernel/cpu/bugs.c
+index baddc9e..b8b0b6e 100644
+--- a/arch/x86/kernel/cpu/bugs.c
++++ b/arch/x86/kernel/cpu/bugs.c
+@@ -299,6 +299,15 @@ static void __init spectre_v2_select_mitigation(void)
+ setup_force_cpu_cap(X86_FEATURE_USE_IBPB);
+ pr_info("Spectre v2 mitigation: Enabling Indirect Branch Prediction Barrier\n");
+ }
++
++ /*
++ * Retpoline means the kernel is safe because it has no indirect
++ * branches. But firmware isn't, so use IBRS to protect that.
++ */
++ if (boot_cpu_has(X86_FEATURE_IBRS)) {
++ setup_force_cpu_cap(X86_FEATURE_USE_IBRS_FW);
++ pr_info("Enabling Restricted Speculation for firmware calls\n");
++ }
+ }
+
+ #undef pr_fmt
+@@ -325,8 +334,9 @@ ssize_t cpu_show_spectre_v2(struct device *dev, struct device_attribute *attr, c
+ if (!boot_cpu_has_bug(X86_BUG_SPECTRE_V2))
+ return sprintf(buf, "Not affected\n");
+
+- return sprintf(buf, "%s%s%s\n", spectre_v2_strings[spectre_v2_enabled],
++ return sprintf(buf, "%s%s%s%s\n", spectre_v2_strings[spectre_v2_enabled],
+ boot_cpu_has(X86_FEATURE_USE_IBPB) ? ", IBPB" : "",
++ boot_cpu_has(X86_FEATURE_USE_IBRS_FW) ? ", IBRS_FW" : "",
+ spectre_v2_module_string());
+ }
+ #endif
+--
+2.7.4
+