All of lore.kernel.org
 help / color / mirror / Atom feed
From: David Woodhouse <dwmw@amazon.co.uk>
To: x86@kernel.org, mingo@kernel.org, linux-kernel@vger.kernel.org
Subject: [PATCH v2.1] x86/speculation: Use IBRS if available before calling into firmware
Date: Sun, 11 Feb 2018 15:19:19 +0000	[thread overview]
Message-ID: <1518362359-1005-1-git-send-email-dwmw@amazon.co.uk> (raw)
In-Reply-To: <1518305967-31356-1-git-send-email-dwmw@amazon.co.uk>

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.

Signed-off-by: David Woodhouse <dwmw@amazon.co.uk>
---
Helps to include the right header file.

 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 | 37 +++++++++++++++++++++++++++---------
 arch/x86/kernel/cpu/bugs.c           | 12 +++++++++++-
 drivers/watchdog/hpwdt.c             |  3 +++
 6 files changed, 64 insertions(+), 12 deletions(-)

diff --git a/arch/x86/include/asm/apm.h b/arch/x86/include/asm/apm.h
index 4d4015d..c356098 100644
--- a/arch/x86/include/asm/apm.h
+++ b/arch/x86/include/asm/apm.h
@@ -7,6 +7,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" \
@@ -32,6 +34,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"
@@ -44,6 +47,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,
@@ -56,6 +60,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"
@@ -68,6 +73,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 73b5fff..66c1434 100644
--- a/arch/x86/include/asm/cpufeatures.h
+++ b/arch/x86/include/asm/cpufeatures.h
@@ -211,6 +211,7 @@
 #define X86_FEATURE_RSB_CTXSW		( 7*32+19) /* "" Fill RSB on context switches */
 
 #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 85f6ccb..a399c1e 100644
--- a/arch/x86/include/asm/efi.h
+++ b/arch/x86/include/asm/efi.h
@@ -6,6 +6,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,
@@ -36,8 +37,18 @@
 
 extern asmlinkage unsigned long 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.
@@ -73,6 +84,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();			\
@@ -91,6 +103,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 300cc15..788c4da 100644
--- a/arch/x86/include/asm/nospec-branch.h
+++ b/arch/x86/include/asm/nospec-branch.h
@@ -162,17 +162,36 @@ 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)
+{
+	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);
 }
 
 #endif /* __ASSEMBLY__ */
diff --git a/arch/x86/kernel/cpu/bugs.c b/arch/x86/kernel/cpu/bugs.c
index 61152aa..6f6d763 100644
--- a/arch/x86/kernel/cpu/bugs.c
+++ b/arch/x86/kernel/cpu/bugs.c
@@ -303,6 +303,15 @@ static void __init spectre_v2_select_mitigation(void)
 		setup_force_cpu_cap(X86_FEATURE_USE_IBPB);
 		pr_info("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
@@ -332,8 +341,9 @@ ssize_t cpu_show_spectre_v2(struct device *dev,
 	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
diff --git a/drivers/watchdog/hpwdt.c b/drivers/watchdog/hpwdt.c
index 67fbe35..bab3721 100644
--- a/drivers/watchdog/hpwdt.c
+++ b/drivers/watchdog/hpwdt.c
@@ -38,6 +38,7 @@
 #endif /* CONFIG_HPWDT_NMI_DECODING */
 #include <asm/nmi.h>
 #include <asm/frame.h>
+#include <asm/nospec-branch.h>
 
 #define HPWDT_VERSION			"1.4.0"
 #define SECS_TO_TICKS(secs)		((secs) * 1000 / 128)
@@ -486,11 +487,13 @@ static int hpwdt_pretimeout(unsigned int ulReason, struct pt_regs *regs)
 	if (!hpwdt_nmi_decoding)
 		return NMI_DONE;
 
+	firmware_restrict_branch_speculation_start();
 	spin_lock_irqsave(&rom_lock, rom_pl);
 	if (!die_nmi_called && !is_icru && !is_uefi)
 		asminline_call(&cmn_regs, cru_rom_addr);
 	die_nmi_called = 1;
 	spin_unlock_irqrestore(&rom_lock, rom_pl);
+	firmware_restrict_branch_speculation_end();
 
 	if (allow_kdump)
 		hpwdt_stop();
-- 
2.7.4

  parent reply	other threads:[~2018-02-11 15:19 UTC|newest]

Thread overview: 74+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2018-02-10 23:39 [PATCH v2 0/6] Spectre v2 updates David Woodhouse
2018-02-10 23:39 ` [PATCH v2 1/6] x86/speculation: Update Speculation Control microcode blacklist David Woodhouse
2018-02-11 12:08   ` [tip:x86/pti] " tip-bot for David Woodhouse
2018-02-12  9:50   ` [PATCH v2 1/6] " Darren Kenny
2018-02-12 14:16   ` David Woodhouse
2018-02-12 14:32     ` Thomas Gleixner
2018-02-10 23:39 ` [PATCH v2 2/6] Revert "x86/speculation: Simplify indirect_branch_prediction_barrier()" David Woodhouse
2018-02-11 12:09   ` [tip:x86/pti] " tip-bot for David Woodhouse
2018-02-13  8:58   ` tip-bot for David Woodhouse
2018-02-13  9:41     ` Peter Zijlstra
2018-02-13 11:28       ` Ingo Molnar
2018-02-13 13:28         ` Peter Zijlstra
2018-02-13 13:38           ` Ingo Molnar
2018-02-13 15:26           ` [tip:x86/pti] x86/speculation: Add <asm/msr-index.h> dependency tip-bot for Peter Zijlstra
2018-02-15  0:28           ` tip-bot for Peter Zijlstra
2018-02-10 23:39 ` [PATCH v2 3/6] KVM: x86: Reduce retpoline performance impact in slot_handle_level_range() David Woodhouse
2018-02-11 12:09   ` [tip:x86/pti] KVM/x86: Reduce retpoline performance impact in slot_handle_level_range(), by always inlining iterator helper methods tip-bot for David Woodhouse
2018-02-13  8:58   ` tip-bot for David Woodhouse
2018-02-10 23:39 ` [PATCH v2 4/6] X86/nVMX: Properly set spec_ctrl and pred_cmd before merging MSRs David Woodhouse
2018-02-11 12:10   ` [tip:x86/pti] " tip-bot for KarimAllah Ahmed
2018-02-13  8:59   ` tip-bot for KarimAllah Ahmed
2018-02-10 23:39 ` [PATCH v2 5/6] KVM/nVMX: Set the CPU_BASED_USE_MSR_BITMAPS if we have a valid L02 MSR bitmap David Woodhouse
2018-02-11 10:19   ` Ingo Molnar
     [not found]     ` <1518345844.3677.365.camel@amazon.co.uk>
2018-02-11 10:55       ` Ingo Molnar
2018-02-11 12:10   ` [tip:x86/pti] " tip-bot for KarimAllah Ahmed
2018-02-13  8:59   ` tip-bot for KarimAllah Ahmed
2018-02-10 23:39 ` [PATCH v2 6/6] x86/speculation: Use IBRS if available before calling into firmware David Woodhouse
2018-02-11 11:46   ` Ingo Molnar
2018-02-11 10:41 ` [PATCH v2 0/6] Spectre v2 updates Ingo Molnar
2018-02-11 15:19 ` David Woodhouse [this message]
2018-02-11 18:50   ` [PATCH] x86/speculation: Clean up various Spectre related details Ingo Molnar
2018-02-11 19:25     ` David Woodhouse
2018-02-11 19:43       ` Ingo Molnar
2018-02-12 15:30         ` David Woodhouse
2018-02-13  8:04           ` Ingo Molnar
2018-02-11 19:19   ` [tip:x86/pti] x86/speculation: Use IBRS if available before calling into firmware tip-bot for David Woodhouse
2018-02-12  5:59     ` afzal mohammed
2018-02-12 16:30       ` David Woodhouse
2018-02-12 10:22     ` Ingo Molnar
2018-02-12 11:50       ` Peter Zijlstra
2018-02-12 12:27         ` David Woodhouse
2018-02-12 13:06           ` Peter Zijlstra
2018-02-13  7:58           ` Ingo Molnar
2018-02-12 12:28         ` Peter Zijlstra
2018-02-12 16:13       ` Dave Hansen
2018-02-12 16:58         ` Peter Zijlstra
2018-02-13  7:55           ` Ingo Molnar
2018-02-14  1:49             ` Tim Chen
2018-02-14  8:56               ` Peter Zijlstra
2018-02-14  8:57                 ` Peter Zijlstra
2018-02-14 19:20                 ` Tim Chen
2018-02-14 23:19                   ` Ingo Molnar
2018-02-15  2:01                     ` Tim Chen
2018-02-14  9:31               ` [PATCH] watchdog: hpwdt: Remove spinlock acquire and BIOS calls from NMI context Ingo Molnar
2018-02-14  9:38                 ` Peter Zijlstra
2018-02-14 10:39                   ` Ingo Molnar
2018-02-14  9:44                 ` Borislav Petkov
2018-02-14 18:13                   ` Jerry Hoemann
2018-02-14 23:17                     ` Ingo Molnar
2018-02-15 17:44                       ` Jerry Hoemann
2018-02-15 19:02                         ` Ingo Molnar
2018-02-15 19:48                         ` Peter Zijlstra
2018-02-16 18:44     ` [tip:x86/pti] x86/speculation: Use IBRS if available before calling into firmware Tim Chen
2018-02-16 19:16       ` David Woodhouse
2018-02-16 23:46         ` Tim Chen
2018-02-17 10:26           ` Ingo Molnar
2018-02-19  9:20             ` Peter Zijlstra
2018-02-19  9:29               ` David Woodhouse
2018-02-19  9:39                 ` Ingo Molnar
2018-02-19  9:44                   ` David Woodhouse
2018-02-19 10:08                 ` Peter Zijlstra
2018-02-19  9:36               ` Ingo Molnar
2018-02-12  8:27 ` [PATCH v2 0/6] Spectre v2 updates Paolo Bonzini
2018-02-13  7:59   ` Ingo Molnar

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1518362359-1005-1-git-send-email-dwmw@amazon.co.uk \
    --to=dwmw@amazon.co.uk \
    --cc=linux-kernel@vger.kernel.org \
    --cc=mingo@kernel.org \
    --cc=x86@kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.