Skip to content

Commit 885f82b

Browse files
committed
x86/process: Allow runtime control of Speculative Store Bypass
The Speculative Store Bypass vulnerability can be mitigated with the Reduced Data Speculation (RDS) feature. To allow finer grained control of this eventually expensive mitigation a per task mitigation control is required. Add a new TIF_RDS flag and put it into the group of TIF flags which are evaluated for mismatch in switch_to(). If these bits differ in the previous and the next task, then the slow path function __switch_to_xtra() is invoked. Implement the TIF_RDS dependent mitigation control in the slow path. If the prctl for controlling Speculative Store Bypass is disabled or no task uses the prctl then there is no overhead in the switch_to() fast path. Update the KVM related speculation control functions to take TID_RDS into account as well. Based on a patch from Tim Chen. Completely rewritten. Signed-off-by: Thomas Gleixner <[email protected]> Reviewed-by: Ingo Molnar <[email protected]> Reviewed-by: Konrad Rzeszutek Wilk <[email protected]>
1 parent b617cfc commit 885f82b

File tree

5 files changed

+65
-7
lines changed

5 files changed

+65
-7
lines changed

arch/x86/include/asm/msr-index.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,8 @@
4242
#define MSR_IA32_SPEC_CTRL 0x00000048 /* Speculation Control */
4343
#define SPEC_CTRL_IBRS (1 << 0) /* Indirect Branch Restricted Speculation */
4444
#define SPEC_CTRL_STIBP (1 << 1) /* Single Thread Indirect Branch Predictors */
45-
#define SPEC_CTRL_RDS (1 << 2) /* Reduced Data Speculation */
45+
#define SPEC_CTRL_RDS_SHIFT 2 /* Reduced Data Speculation bit */
46+
#define SPEC_CTRL_RDS (1 << SPEC_CTRL_RDS_SHIFT) /* Reduced Data Speculation */
4647

4748
#define MSR_IA32_PRED_CMD 0x00000049 /* Prediction Command */
4849
#define PRED_CMD_IBPB (1 << 0) /* Indirect Branch Prediction Barrier */

arch/x86/include/asm/spec-ctrl.h

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
#ifndef _ASM_X86_SPECCTRL_H_
33
#define _ASM_X86_SPECCTRL_H_
44

5+
#include <linux/thread_info.h>
56
#include <asm/nospec-branch.h>
67

78
/*
@@ -18,4 +19,20 @@ extern void x86_spec_ctrl_restore_host(u64);
1819
extern u64 x86_amd_ls_cfg_base;
1920
extern u64 x86_amd_ls_cfg_rds_mask;
2021

22+
/* The Intel SPEC CTRL MSR base value cache */
23+
extern u64 x86_spec_ctrl_base;
24+
25+
static inline u64 rds_tif_to_spec_ctrl(u64 tifn)
26+
{
27+
BUILD_BUG_ON(TIF_RDS < SPEC_CTRL_RDS_SHIFT);
28+
return (tifn & _TIF_RDS) >> (TIF_RDS - SPEC_CTRL_RDS_SHIFT);
29+
}
30+
31+
static inline u64 rds_tif_to_amd_ls_cfg(u64 tifn)
32+
{
33+
return (tifn & _TIF_RDS) ? x86_amd_ls_cfg_rds_mask : 0ULL;
34+
}
35+
36+
extern void speculative_store_bypass_update(void);
37+
2138
#endif

arch/x86/include/asm/thread_info.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,7 @@ struct thread_info {
7979
#define TIF_SIGPENDING 2 /* signal pending */
8080
#define TIF_NEED_RESCHED 3 /* rescheduling necessary */
8181
#define TIF_SINGLESTEP 4 /* reenable singlestep on user return*/
82+
#define TIF_RDS 5 /* Reduced data speculation */
8283
#define TIF_SYSCALL_EMU 6 /* syscall emulation active */
8384
#define TIF_SYSCALL_AUDIT 7 /* syscall auditing active */
8485
#define TIF_SECCOMP 8 /* secure computing */
@@ -105,6 +106,7 @@ struct thread_info {
105106
#define _TIF_SIGPENDING (1 << TIF_SIGPENDING)
106107
#define _TIF_NEED_RESCHED (1 << TIF_NEED_RESCHED)
107108
#define _TIF_SINGLESTEP (1 << TIF_SINGLESTEP)
109+
#define _TIF_RDS (1 << TIF_RDS)
108110
#define _TIF_SYSCALL_EMU (1 << TIF_SYSCALL_EMU)
109111
#define _TIF_SYSCALL_AUDIT (1 << TIF_SYSCALL_AUDIT)
110112
#define _TIF_SECCOMP (1 << TIF_SECCOMP)
@@ -144,7 +146,7 @@ struct thread_info {
144146

145147
/* flags to check in __switch_to() */
146148
#define _TIF_WORK_CTXSW \
147-
(_TIF_IO_BITMAP|_TIF_NOCPUID|_TIF_NOTSC|_TIF_BLOCKSTEP)
149+
(_TIF_IO_BITMAP|_TIF_NOCPUID|_TIF_NOTSC|_TIF_BLOCKSTEP|_TIF_RDS)
148150

149151
#define _TIF_WORK_CTXSW_PREV (_TIF_WORK_CTXSW|_TIF_USER_RETURN_NOTIFY)
150152
#define _TIF_WORK_CTXSW_NEXT (_TIF_WORK_CTXSW)

arch/x86/kernel/cpu/bugs.c

Lines changed: 21 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ static void __init ssb_select_mitigation(void);
3333
* Our boot-time value of the SPEC_CTRL MSR. We read it once so that any
3434
* writes to SPEC_CTRL contain whatever reserved bits have been set.
3535
*/
36-
static u64 __ro_after_init x86_spec_ctrl_base;
36+
u64 __ro_after_init x86_spec_ctrl_base;
3737

3838
/*
3939
* The vendor and possibly platform specific bits which can be modified in
@@ -140,25 +140,41 @@ EXPORT_SYMBOL_GPL(x86_spec_ctrl_set);
140140

141141
u64 x86_spec_ctrl_get_default(void)
142142
{
143-
return x86_spec_ctrl_base;
143+
u64 msrval = x86_spec_ctrl_base;
144+
145+
if (boot_cpu_data.x86_vendor == X86_VENDOR_INTEL)
146+
msrval |= rds_tif_to_spec_ctrl(current_thread_info()->flags);
147+
return msrval;
144148
}
145149
EXPORT_SYMBOL_GPL(x86_spec_ctrl_get_default);
146150

147151
void x86_spec_ctrl_set_guest(u64 guest_spec_ctrl)
148152
{
153+
u64 host = x86_spec_ctrl_base;
154+
149155
if (!boot_cpu_has(X86_FEATURE_IBRS))
150156
return;
151-
if (x86_spec_ctrl_base != guest_spec_ctrl)
157+
158+
if (boot_cpu_data.x86_vendor == X86_VENDOR_INTEL)
159+
host |= rds_tif_to_spec_ctrl(current_thread_info()->flags);
160+
161+
if (host != guest_spec_ctrl)
152162
wrmsrl(MSR_IA32_SPEC_CTRL, guest_spec_ctrl);
153163
}
154164
EXPORT_SYMBOL_GPL(x86_spec_ctrl_set_guest);
155165

156166
void x86_spec_ctrl_restore_host(u64 guest_spec_ctrl)
157167
{
168+
u64 host = x86_spec_ctrl_base;
169+
158170
if (!boot_cpu_has(X86_FEATURE_IBRS))
159171
return;
160-
if (x86_spec_ctrl_base != guest_spec_ctrl)
161-
wrmsrl(MSR_IA32_SPEC_CTRL, x86_spec_ctrl_base);
172+
173+
if (boot_cpu_data.x86_vendor == X86_VENDOR_INTEL)
174+
host |= rds_tif_to_spec_ctrl(current_thread_info()->flags);
175+
176+
if (host != guest_spec_ctrl)
177+
wrmsrl(MSR_IA32_SPEC_CTRL, host);
162178
}
163179
EXPORT_SYMBOL_GPL(x86_spec_ctrl_restore_host);
164180

arch/x86/kernel/process.c

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@
3838
#include <asm/switch_to.h>
3939
#include <asm/desc.h>
4040
#include <asm/prctl.h>
41+
#include <asm/spec-ctrl.h>
4142

4243
/*
4344
* per-CPU TSS segments. Threads are completely 'soft' on Linux,
@@ -278,6 +279,24 @@ static inline void switch_to_bitmap(struct tss_struct *tss,
278279
}
279280
}
280281

282+
static __always_inline void __speculative_store_bypass_update(unsigned long tifn)
283+
{
284+
u64 msr;
285+
286+
if (static_cpu_has(X86_FEATURE_AMD_RDS)) {
287+
msr = x86_amd_ls_cfg_base | rds_tif_to_amd_ls_cfg(tifn);
288+
wrmsrl(MSR_AMD64_LS_CFG, msr);
289+
} else {
290+
msr = x86_spec_ctrl_base | rds_tif_to_spec_ctrl(tifn);
291+
wrmsrl(MSR_IA32_SPEC_CTRL, msr);
292+
}
293+
}
294+
295+
void speculative_store_bypass_update(void)
296+
{
297+
__speculative_store_bypass_update(current_thread_info()->flags);
298+
}
299+
281300
void __switch_to_xtra(struct task_struct *prev_p, struct task_struct *next_p,
282301
struct tss_struct *tss)
283302
{
@@ -309,6 +328,9 @@ void __switch_to_xtra(struct task_struct *prev_p, struct task_struct *next_p,
309328

310329
if ((tifp ^ tifn) & _TIF_NOCPUID)
311330
set_cpuid_faulting(!!(tifn & _TIF_NOCPUID));
331+
332+
if ((tifp ^ tifn) & _TIF_RDS)
333+
__speculative_store_bypass_update(tifn);
312334
}
313335

314336
/*

0 commit comments

Comments
 (0)