Skip to contentSkip to conversation

Linux Patch #3

PATCH In review [email protected] 2 participants 2 messages Apr 27, 2018 – Apr 28, 2018

Subsystems (2)
lore
Share & tools
lore
#0 lore raw

PATCH v6 3/10 Linux Patch #3

The 336996-Speculative-Execution-Side-Channel-Mitigations.pdf refers to all the other bits as reserved. The Intel SDM glossary defines reserved as implementation specific - aka unknown.

As such at bootup we should take it into account and apply proper masking for the bits we use.

A copy of this document is available at
https://bugzilla.kernel.org/show_bug.cgi?id=199511

---
v2: New patch
v3: Expose only one global variable
v4: Don't expose global variable.
Provide x86_set_spec_ctrl and x86_get_spec_ctrl Only filter IBRS on x86_set_spec_ctrl
v5: Add bugzilla URL
Added Reviewed-by
Removed spec_ctrl_save_msr s/x86_get_spec_ctrl/x86_get_default_spec_ctrl/ Add __read_mostly on the variable
Add comment for what it is.
v6: Made x86_spec_ctrl_base static
Added Reviewed-by

---
 arch/x86/include/asm/nospec-branch.h | 25 +++++++++++++++++++++----
 arch/x86/kernel/cpu/bugs.c           | 28 ++++++++++++++++++++++++++++
 2 files changed, 49 insertions(+), 4 deletions(-)
arch/x86/include/asm/nospec-branch.h +21 -4
index f928ad9b143f..984f4a36960f 100644
@@ -217,6 +217,17 @@ enum spectre_v2_mitigation {
 	SPECTRE_V2_IBRS,
 };
 
+/*
+ * The Intel specification for the SPEC_CTRL MSR requires that we
+ * preserve any already set reserved bits at boot time (e.g. for
+ * future additions that this kernel is not currently aware of).
+ * We then set any additional mitigation bits that we want
+ * ourselves and always use this as the base for SPEC_CTRL.
+ * We also use this when handling guest entry/exit as below.
+ */
+extern void x86_set_spec_ctrl(u64);
+extern u64 x86_get_default_spec_ctrl(void);
+
 extern char __indirect_thunk_start[];
 extern char __indirect_thunk_end[];
 
@@ -248,12 +259,14 @@ static inline void vmexit_fill_RSB(void)
 				 "movl $0, %%edx\n\t"		\
 				 "wrmsr",			\
 				 _feature)			\
-		     : : [msr] "i" (_msr), [val] "i" (_val)	\
+		     : : [msr] "i" (_msr), [val] "m" (_val)	\
 		     : "eax", "ecx", "edx", "memory")
 
 static inline void indirect_branch_prediction_barrier(void)
 {
-	alternative_msr_write(MSR_IA32_PRED_CMD, PRED_CMD_IBPB,
+	u64 val = PRED_CMD_IBPB;
+
+	alternative_msr_write(MSR_IA32_PRED_CMD, val,
 			      X86_FEATURE_USE_IBPB);
 }
 
@@ -265,14 +278,18 @@ static inline void indirect_branch_prediction_barrier(void)
  */
 #define firmware_restrict_branch_speculation_start()			\
 do {									\
+	u64 val = x86_get_default_spec_ctrl() | SPEC_CTRL_IBRS;		\
+									\
 	preempt_disable();						\
-	alternative_msr_write(MSR_IA32_SPEC_CTRL, SPEC_CTRL_IBRS,	\
+	alternative_msr_write(MSR_IA32_SPEC_CTRL, val,			\
 			      X86_FEATURE_USE_IBRS_FW);			\
 } while (0)
 
 #define firmware_restrict_branch_speculation_end()			\
 do {									\
-	alternative_msr_write(MSR_IA32_SPEC_CTRL, 0,			\
+	u64 val = x86_get_default_spec_ctrl();				\
+									\
+	alternative_msr_write(MSR_IA32_SPEC_CTRL, val,			\
 			      X86_FEATURE_USE_IBRS_FW);			\
 	preempt_enable();						\
 } while (0)
arch/x86/kernel/cpu/bugs.c +28 -0
index ad613f73d071..048719d5c9b8 100644
@@ -28,10 +28,23 @@
 
 static void __init spectre_v2_select_mitigation(void);
 
+/*
+ * Our boot-time value of SPEC_CTRL MSR. We read it once so that any
+ * writes to SPEC_CTRL contain whatever reserved bits have been set.
+ */
+static u64 __read_mostly x86_spec_ctrl_base;
+
 void __init check_bugs(void)
 {
 	identify_boot_cpu();
 
+	/*
+	 * Read the SPEC_CTRL MSR to account for reserved bits which may have
+	 * unknown values.
+	 */
+	if (boot_cpu_has(X86_FEATURE_IBRS))
+		rdmsrl(MSR_IA32_SPEC_CTRL, x86_spec_ctrl_base);
+
 	if (!IS_ENABLED(CONFIG_SMP)) {
 		pr_info("CPU: ");
 		print_cpu_info(&boot_cpu_data);
@@ -95,6 +108,21 @@ static const char *spectre_v2_strings[] = {
 
 static enum spectre_v2_mitigation spectre_v2_enabled = SPECTRE_V2_NONE;
 
+void x86_set_spec_ctrl(u64 val)
+{
+	if (val & ~(SPEC_CTRL_IBRS))
+		WARN_ONCE(1, "SPEC_CTRL MSR value 0x%16llx is unknown.\n", val);
+	else
+		wrmsrl(MSR_IA32_SPEC_CTRL, x86_spec_ctrl_base | val);
+}
+EXPORT_SYMBOL_GPL(x86_set_spec_ctrl);
+
+u64 x86_get_default_spec_ctrl(void)
+{
+	return x86_spec_ctrl_base;
+}
+EXPORT_SYMBOL_GPL(x86_get_default_spec_ctrl);
+
 #ifdef RETPOLINE
 static bool spectre_v2_bad_module;
 
Signature · 1 line
2.14.3
#1 lore raw

arch/x86/kernel/cpu/bugs.c line 35

Quoted 5 lines · speck for konrad.wilk_at_oracle.com
arch/x86/kernel/cpu/bugs.c +5 -0
+/*
+ * Our boot-time value of SPEC_CTRL MSR. We read it once so that any
+ * writes to SPEC_CTRL contain whatever reserved bits have been set.
+ */
+static u64 __read_mostly x86_spec_ctrl_base;

This wants to be __ro_after_init. Nothing can change it during runtime.