Borislav Petkov 09deb3
From: Peter Zijlstra <peterz@infradead.org>
Borislav Petkov 09deb3
Date: Tue, 14 Jun 2022 23:15:52 +0200
Borislav Petkov 09deb3
Subject: x86/bugs: Keep a per-CPU IA32_SPEC_CTRL value
Borislav Petkov 09deb3
Git-commit: caa0ff24d5d0e02abce5e65c3d2b7f20a6617be5
Borislav Petkov 43fbd8
Patch-mainline: v5.19-rc4
Borislav Petkov 09deb3
References: bsc#1199657 CVE-2022-29900 CVE-2022-29901
Borislav Petkov 09deb3
Borislav Petkov 09deb3
Due to TIF_SSBD and TIF_SPEC_IB the actual IA32_SPEC_CTRL value can
Borislav Petkov 09deb3
differ from x86_spec_ctrl_base. As such, keep a per-CPU value
Borislav Petkov 09deb3
reflecting the current task's MSR content.
Borislav Petkov 09deb3
Borislav Petkov 09deb3
  [jpoimboe: rename]
Borislav Petkov 09deb3
Borislav Petkov 09deb3
Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Borislav Petkov 09deb3
Signed-off-by: Borislav Petkov <bp@suse.de>
Borislav Petkov 09deb3
Reviewed-by: Josh Poimboeuf <jpoimboe@kernel.org>
Borislav Petkov 09deb3
Signed-off-by: Borislav Petkov <bp@suse.de>
Borislav Petkov 09deb3
---
Borislav Petkov 09deb3
 arch/x86/include/asm/nospec-branch.h |    1 +
Borislav Petkov 09deb3
 arch/x86/kernel/cpu/bugs.c           |   28 +++++++++++++++++++++++-----
Borislav Petkov 09deb3
 arch/x86/kernel/process.c            |    2 +-
Borislav Petkov 09deb3
 3 files changed, 25 insertions(+), 6 deletions(-)
Borislav Petkov 09deb3
Borislav Petkov 09deb3
--- a/arch/x86/include/asm/nospec-branch.h
Borislav Petkov 09deb3
+++ b/arch/x86/include/asm/nospec-branch.h
Borislav Petkov 09deb3
@@ -253,6 +253,7 @@ static inline void indirect_branch_predi
Borislav Petkov 09deb3
 
Borislav Petkov 09deb3
 /* The Intel SPEC CTRL MSR base value cache */
Borislav Petkov 09deb3
 extern u64 x86_spec_ctrl_base;
Borislav Petkov 09deb3
+extern void write_spec_ctrl_current(u64 val);
Borislav Petkov 09deb3
 
Borislav Petkov 09deb3
 /*
Borislav Petkov 09deb3
  * With retpoline, we must use IBRS to restrict branch prediction
Borislav Petkov 09deb3
--- a/arch/x86/kernel/cpu/bugs.c
Borislav Petkov 09deb3
+++ b/arch/x86/kernel/cpu/bugs.c
Borislav Petkov 09deb3
@@ -48,12 +48,30 @@ static void __init taa_select_mitigation
Borislav Petkov 09deb3
 static void __init mmio_select_mitigation(void);
Borislav Petkov 09deb3
 static void __init srbds_select_mitigation(void);
Borislav Petkov 09deb3
 
Borislav Petkov 09deb3
-/* The base value of the SPEC_CTRL MSR that always has to be preserved. */
Borislav Petkov 09deb3
+/* The base value of the SPEC_CTRL MSR without task-specific bits set */
Borislav Petkov 09deb3
 u64 x86_spec_ctrl_base;
Borislav Petkov 09deb3
 EXPORT_SYMBOL_GPL(x86_spec_ctrl_base);
Borislav Petkov 09deb3
+
Borislav Petkov 09deb3
+/* The current value of the SPEC_CTRL MSR with task-specific bits set */
Borislav Petkov 09deb3
+DEFINE_PER_CPU(u64, x86_spec_ctrl_current);
Borislav Petkov 09deb3
+EXPORT_SYMBOL_GPL(x86_spec_ctrl_current);
Borislav Petkov 09deb3
+
Borislav Petkov 09deb3
 static DEFINE_MUTEX(spec_ctrl_mutex);
Borislav Petkov 09deb3
 
Borislav Petkov 09deb3
 /*
Borislav Petkov 09deb3
+ * Keep track of the SPEC_CTRL MSR value for the current task, which may differ
Borislav Petkov 09deb3
+ * from x86_spec_ctrl_base due to STIBP/SSB in __speculation_ctrl_update().
Borislav Petkov 09deb3
+ */
Borislav Petkov 09deb3
+void write_spec_ctrl_current(u64 val)
Borislav Petkov 09deb3
+{
Borislav Petkov 09deb3
+	if (this_cpu_read(x86_spec_ctrl_current) == val)
Borislav Petkov 09deb3
+		return;
Borislav Petkov 09deb3
+
Borislav Petkov 09deb3
+	this_cpu_write(x86_spec_ctrl_current, val);
Borislav Petkov 09deb3
+	wrmsrl(MSR_IA32_SPEC_CTRL, val);
Borislav Petkov 09deb3
+}
Borislav Petkov 09deb3
+
Borislav Petkov 09deb3
+/*
Borislav Petkov 09deb3
  * The vendor and possibly platform specific bits which can be modified in
Borislav Petkov 09deb3
  * x86_spec_ctrl_base.
Borislav Petkov 09deb3
  */
Borislav Petkov 09deb3
@@ -1235,7 +1253,7 @@ static void __init spectre_v2_select_mit
Borislav Petkov 09deb3
 	if (spectre_v2_in_eibrs_mode(mode)) {
Borislav Petkov 09deb3
 		/* Force it so VMEXIT will restore correctly */
Borislav Petkov 09deb3
 		x86_spec_ctrl_base |= SPEC_CTRL_IBRS;
Borislav Petkov 09deb3
-		wrmsrl(MSR_IA32_SPEC_CTRL, x86_spec_ctrl_base);
Borislav Petkov 09deb3
+		write_spec_ctrl_current(x86_spec_ctrl_base);
Borislav Petkov 09deb3
 	}
Borislav Petkov 09deb3
 
Borislav Petkov 09deb3
 	switch (mode) {
Borislav Petkov 09deb3
@@ -1290,7 +1308,7 @@ static void __init spectre_v2_select_mit
Borislav Petkov 09deb3
 
Borislav Petkov 09deb3
 static void update_stibp_msr(void * __unused)
Borislav Petkov 09deb3
 {
Borislav Petkov 09deb3
-	wrmsrl(MSR_IA32_SPEC_CTRL, x86_spec_ctrl_base);
Borislav Petkov 09deb3
+	write_spec_ctrl_current(x86_spec_ctrl_base);
Borislav Petkov 09deb3
 }
Borislav Petkov 09deb3
 
Borislav Petkov 09deb3
 /* Update x86_spec_ctrl_base in case SMT state changed. */
Borislav Petkov 09deb3
@@ -1522,7 +1540,7 @@ static enum ssb_mitigation __init __ssb_
Borislav Petkov 09deb3
 			x86_amd_ssb_disable();
Borislav Petkov 09deb3
 		} else {
Borislav Petkov 09deb3
 			x86_spec_ctrl_base |= SPEC_CTRL_SSBD;
Borislav Petkov 09deb3
-			wrmsrl(MSR_IA32_SPEC_CTRL, x86_spec_ctrl_base);
Borislav Petkov 09deb3
+			write_spec_ctrl_current(x86_spec_ctrl_base);
Borislav Petkov 09deb3
 		}
Borislav Petkov 09deb3
 	}
Borislav Petkov 09deb3
 
Borislav Petkov 09deb3
@@ -1740,7 +1758,7 @@ int arch_prctl_spec_ctrl_get(struct task
Borislav Petkov 09deb3
 void x86_spec_ctrl_setup_ap(void)
Borislav Petkov 09deb3
 {
Borislav Petkov 09deb3
 	if (boot_cpu_has(X86_FEATURE_MSR_SPEC_CTRL))
Borislav Petkov 09deb3
-		wrmsrl(MSR_IA32_SPEC_CTRL, x86_spec_ctrl_base);
Borislav Petkov 09deb3
+		write_spec_ctrl_current(x86_spec_ctrl_base);
Borislav Petkov 09deb3
 
Borislav Petkov 09deb3
 	if (ssb_mode == SPEC_STORE_BYPASS_DISABLE)
Borislav Petkov 09deb3
 		x86_amd_ssb_disable();
Borislav Petkov 09deb3
--- a/arch/x86/kernel/process.c
Borislav Petkov 09deb3
+++ b/arch/x86/kernel/process.c
Borislav Petkov 09deb3
@@ -599,7 +599,7 @@ static __always_inline void __speculatio
Borislav Petkov 09deb3
 	}
Borislav Petkov 09deb3
 
Borislav Petkov 09deb3
 	if (updmsr)
Borislav Petkov 09deb3
-		wrmsrl(MSR_IA32_SPEC_CTRL, msr);
Borislav Petkov 09deb3
+		write_spec_ctrl_current(msr);
Borislav Petkov 09deb3
 }
Borislav Petkov 09deb3
 
Borislav Petkov 09deb3
 static unsigned long speculation_ctrl_update_tif(struct task_struct *tsk)