Skip to content

Commit 7a0395f

Browse files
bp3tk0vgregkh
authored andcommitted
x86/bugs: Add a Transient Scheduler Attacks mitigation
Commit d8010d4 upstream. Add the required features detection glue to bugs.c et all in order to support the TSA mitigation. Co-developed-by: Kim Phillips <[email protected]> Signed-off-by: Kim Phillips <[email protected]> Signed-off-by: Borislav Petkov (AMD) <[email protected]> Reviewed-by: Pawan Gupta <[email protected]> Signed-off-by: Greg Kroah-Hartman <[email protected]>
1 parent 0720e43 commit 7a0395f

File tree

15 files changed

+258
-18
lines changed

15 files changed

+258
-18
lines changed

Documentation/ABI/testing/sysfs-devices-system-cpu

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -523,6 +523,7 @@ What: /sys/devices/system/cpu/vulnerabilities
523523
/sys/devices/system/cpu/vulnerabilities/spectre_v1
524524
/sys/devices/system/cpu/vulnerabilities/spectre_v2
525525
/sys/devices/system/cpu/vulnerabilities/srbds
526+
/sys/devices/system/cpu/vulnerabilities/tsa
526527
/sys/devices/system/cpu/vulnerabilities/tsx_async_abort
527528
Date: January 2018
528529
Contact: Linux kernel mailing list <[email protected]>

Documentation/admin-guide/kernel-parameters.txt

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6993,6 +6993,19 @@
69936993
having this key zero'ed is acceptable. E.g. in testing
69946994
scenarios.
69956995

6996+
tsa= [X86] Control mitigation for Transient Scheduler
6997+
Attacks on AMD CPUs. Search the following in your
6998+
favourite search engine for more details:
6999+
7000+
"Technical guidance for mitigating transient scheduler
7001+
attacks".
7002+
7003+
off - disable the mitigation
7004+
on - enable the mitigation (default)
7005+
user - mitigate only user/kernel transitions
7006+
vm - mitigate only guest/host transitions
7007+
7008+
69967009
tsc= Disable clocksource stability checks for TSC.
69977010
Format: <string>
69987011
[x86] reliable: mark tsc clocksource as reliable, this

arch/x86/Kconfig

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2760,6 +2760,15 @@ config MITIGATION_ITS
27602760
disabled, mitigation cannot be enabled via cmdline.
27612761
See <file:Documentation/admin-guide/hw-vuln/indirect-target-selection.rst>
27622762

2763+
config MITIGATION_TSA
2764+
bool "Mitigate Transient Scheduler Attacks"
2765+
depends on CPU_SUP_AMD
2766+
default y
2767+
help
2768+
Enable mitigation for Transient Scheduler Attacks. TSA is a hardware
2769+
security vulnerability on AMD CPUs which can lead to forwarding of
2770+
invalid info to subsequent instructions and thus can affect their
2771+
timing and thereby cause a leakage.
27632772
endif
27642773

27652774
config ARCH_HAS_ADD_PAGES

arch/x86/include/asm/cpu.h

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,4 +69,16 @@ int intel_microcode_sanity_check(void *mc, bool print_err, int hdr_type);
6969

7070
extern struct cpumask cpus_stop_mask;
7171

72+
union zen_patch_rev {
73+
struct {
74+
__u32 rev : 8,
75+
stepping : 4,
76+
model : 4,
77+
__reserved : 4,
78+
ext_model : 4,
79+
ext_fam : 8;
80+
};
81+
__u32 ucode_rev;
82+
};
83+
7284
#endif /* _ASM_X86_CPU_H */

arch/x86/include/asm/cpufeatures.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -455,6 +455,7 @@
455455
#define X86_FEATURE_NO_NESTED_DATA_BP (20*32+ 0) /* No Nested Data Breakpoints */
456456
#define X86_FEATURE_WRMSR_XX_BASE_NS (20*32+ 1) /* WRMSR to {FS,GS,KERNEL_GS}_BASE is non-serializing */
457457
#define X86_FEATURE_LFENCE_RDTSC (20*32+ 2) /* LFENCE always serializing / synchronizes RDTSC */
458+
#define X86_FEATURE_VERW_CLEAR (20*32+ 5) /* The memory form of VERW mitigates TSA */
458459
#define X86_FEATURE_NULL_SEL_CLR_BASE (20*32+ 6) /* Null Selector Clears Base */
459460
#define X86_FEATURE_AUTOIBRS (20*32+ 8) /* Automatic IBRS */
460461
#define X86_FEATURE_NO_SMM_CTL_MSR (20*32+ 9) /* SMM_CTL MSR is not present */
@@ -477,6 +478,10 @@
477478
#define X86_FEATURE_FAST_CPPC (21*32 + 5) /* AMD Fast CPPC */
478479
#define X86_FEATURE_INDIRECT_THUNK_ITS (21*32 + 6) /* Use thunk for indirect branches in lower half of cacheline */
479480

481+
#define X86_FEATURE_TSA_SQ_NO (21*32+11) /* AMD CPU not vulnerable to TSA-SQ */
482+
#define X86_FEATURE_TSA_L1_NO (21*32+12) /* AMD CPU not vulnerable to TSA-L1 */
483+
#define X86_FEATURE_CLEAR_CPU_BUF_VM (21*32+13) /* Clear CPU buffers using VERW before VMRUN */
484+
480485
/*
481486
* BUG word(s)
482487
*/
@@ -529,4 +534,5 @@
529534
#define X86_BUG_IBPB_NO_RET X86_BUG(1*32 + 4) /* "ibpb_no_ret" IBPB omits return target predictions */
530535
#define X86_BUG_ITS X86_BUG(1*32 + 5) /* "its" CPU is affected by Indirect Target Selection */
531536
#define X86_BUG_ITS_NATIVE_ONLY X86_BUG(1*32 + 6) /* "its_native_only" CPU is affected by ITS, VMX is not affected */
537+
#define X86_BUG_TSA X86_BUG( 1*32+ 9) /* "tsa" CPU is affected by Transient Scheduler Attacks */
532538
#endif /* _ASM_X86_CPUFEATURES_H */

arch/x86/include/asm/mwait.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,7 @@ static __always_inline void __mwait(unsigned long eax, unsigned long ecx)
8080
static __always_inline void __mwaitx(unsigned long eax, unsigned long ebx,
8181
unsigned long ecx)
8282
{
83-
/* No MDS buffer clear as this is AMD/HYGON only */
83+
/* No need for TSA buffer clearing on AMD */
8484

8585
/* "mwaitx %eax, %ebx, %ecx;" */
8686
asm volatile(".byte 0x0f, 0x01, 0xfb;"

arch/x86/include/asm/nospec-branch.h

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -321,19 +321,25 @@
321321
* CFLAGS.ZF.
322322
* Note: Only the memory operand variant of VERW clears the CPU buffers.
323323
*/
324-
.macro CLEAR_CPU_BUFFERS
324+
.macro __CLEAR_CPU_BUFFERS feature
325325
#ifdef CONFIG_X86_64
326-
ALTERNATIVE "", "verw x86_verw_sel(%rip)", X86_FEATURE_CLEAR_CPU_BUF
326+
ALTERNATIVE "", "verw x86_verw_sel(%rip)", \feature
327327
#else
328328
/*
329329
* In 32bit mode, the memory operand must be a %cs reference. The data
330330
* segments may not be usable (vm86 mode), and the stack segment may not
331331
* be flat (ESPFIX32).
332332
*/
333-
ALTERNATIVE "", "verw %cs:x86_verw_sel", X86_FEATURE_CLEAR_CPU_BUF
333+
ALTERNATIVE "", "verw %cs:x86_verw_sel", \feature
334334
#endif
335335
.endm
336336

337+
#define CLEAR_CPU_BUFFERS \
338+
__CLEAR_CPU_BUFFERS X86_FEATURE_CLEAR_CPU_BUF
339+
340+
#define VM_CLEAR_CPU_BUFFERS \
341+
__CLEAR_CPU_BUFFERS X86_FEATURE_CLEAR_CPU_BUF_VM
342+
337343
#ifdef CONFIG_X86_64
338344
.macro CLEAR_BRANCH_HISTORY
339345
ALTERNATIVE "", "call clear_bhb_loop", X86_FEATURE_CLEAR_BHB_LOOP
@@ -617,7 +623,7 @@ static __always_inline void x86_clear_cpu_buffers(void)
617623

618624
/**
619625
* x86_idle_clear_cpu_buffers - Buffer clearing support in idle for the MDS
620-
* vulnerability
626+
* and TSA vulnerabilities.
621627
*
622628
* Clear CPU buffers if the corresponding static key is enabled
623629
*/

arch/x86/kernel/cpu/amd.c

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -368,6 +368,63 @@ static void bsp_determine_snp(struct cpuinfo_x86 *c)
368368
#endif
369369
}
370370

371+
static bool amd_check_tsa_microcode(void)
372+
{
373+
struct cpuinfo_x86 *c = &boot_cpu_data;
374+
union zen_patch_rev p;
375+
u32 min_rev = 0;
376+
377+
p.ext_fam = c->x86 - 0xf;
378+
p.model = c->x86_model;
379+
p.stepping = c->x86_stepping;
380+
381+
if (cpu_has(c, X86_FEATURE_ZEN3) ||
382+
cpu_has(c, X86_FEATURE_ZEN4)) {
383+
switch (p.ucode_rev >> 8) {
384+
case 0xa0011: min_rev = 0x0a0011d7; break;
385+
case 0xa0012: min_rev = 0x0a00123b; break;
386+
case 0xa0082: min_rev = 0x0a00820d; break;
387+
case 0xa1011: min_rev = 0x0a10114c; break;
388+
case 0xa1012: min_rev = 0x0a10124c; break;
389+
case 0xa1081: min_rev = 0x0a108109; break;
390+
case 0xa2010: min_rev = 0x0a20102e; break;
391+
case 0xa2012: min_rev = 0x0a201211; break;
392+
case 0xa4041: min_rev = 0x0a404108; break;
393+
case 0xa5000: min_rev = 0x0a500012; break;
394+
case 0xa6012: min_rev = 0x0a60120a; break;
395+
case 0xa7041: min_rev = 0x0a704108; break;
396+
case 0xa7052: min_rev = 0x0a705208; break;
397+
case 0xa7080: min_rev = 0x0a708008; break;
398+
case 0xa70c0: min_rev = 0x0a70c008; break;
399+
case 0xaa002: min_rev = 0x0aa00216; break;
400+
default:
401+
pr_debug("%s: ucode_rev: 0x%x, current revision: 0x%x\n",
402+
__func__, p.ucode_rev, c->microcode);
403+
return false;
404+
}
405+
}
406+
407+
if (!min_rev)
408+
return false;
409+
410+
return c->microcode >= min_rev;
411+
}
412+
413+
static void tsa_init(struct cpuinfo_x86 *c)
414+
{
415+
if (cpu_has(c, X86_FEATURE_HYPERVISOR))
416+
return;
417+
418+
if (cpu_has(c, X86_FEATURE_ZEN3) ||
419+
cpu_has(c, X86_FEATURE_ZEN4)) {
420+
if (amd_check_tsa_microcode())
421+
setup_force_cpu_cap(X86_FEATURE_VERW_CLEAR);
422+
} else {
423+
setup_force_cpu_cap(X86_FEATURE_TSA_SQ_NO);
424+
setup_force_cpu_cap(X86_FEATURE_TSA_L1_NO);
425+
}
426+
}
427+
371428
static void bsp_init_amd(struct cpuinfo_x86 *c)
372429
{
373430
if (cpu_has(c, X86_FEATURE_CONSTANT_TSC)) {
@@ -475,6 +532,9 @@ static void bsp_init_amd(struct cpuinfo_x86 *c)
475532
}
476533

477534
bsp_determine_snp(c);
535+
536+
tsa_init(c);
537+
478538
return;
479539

480540
warn:

arch/x86/kernel/cpu/bugs.c

Lines changed: 121 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ static void __init l1d_flush_select_mitigation(void);
5050
static void __init srso_select_mitigation(void);
5151
static void __init gds_select_mitigation(void);
5252
static void __init its_select_mitigation(void);
53+
static void __init tsa_select_mitigation(void);
5354

5455
/* The base value of the SPEC_CTRL MSR without task-specific bits set */
5556
u64 x86_spec_ctrl_base;
@@ -185,6 +186,7 @@ void __init cpu_select_mitigations(void)
185186
srso_select_mitigation();
186187
gds_select_mitigation();
187188
its_select_mitigation();
189+
tsa_select_mitigation();
188190
}
189191

190192
/*
@@ -2103,6 +2105,94 @@ static void update_mds_branch_idle(void)
21032105
#define TAA_MSG_SMT "TAA CPU bug present and SMT on, data leak possible. See https://www.kernel.org/doc/html/latest/admin-guide/hw-vuln/tsx_async_abort.html for more details.\n"
21042106
#define MMIO_MSG_SMT "MMIO Stale Data CPU bug present and SMT on, data leak possible. See https://www.kernel.org/doc/html/latest/admin-guide/hw-vuln/processor_mmio_stale_data.html for more details.\n"
21052107

2108+
#undef pr_fmt
2109+
#define pr_fmt(fmt) "Transient Scheduler Attacks: " fmt
2110+
2111+
enum tsa_mitigations {
2112+
TSA_MITIGATION_NONE,
2113+
TSA_MITIGATION_UCODE_NEEDED,
2114+
TSA_MITIGATION_USER_KERNEL,
2115+
TSA_MITIGATION_VM,
2116+
TSA_MITIGATION_FULL,
2117+
};
2118+
2119+
static const char * const tsa_strings[] = {
2120+
[TSA_MITIGATION_NONE] = "Vulnerable",
2121+
[TSA_MITIGATION_UCODE_NEEDED] = "Vulnerable: Clear CPU buffers attempted, no microcode",
2122+
[TSA_MITIGATION_USER_KERNEL] = "Mitigation: Clear CPU buffers: user/kernel boundary",
2123+
[TSA_MITIGATION_VM] = "Mitigation: Clear CPU buffers: VM",
2124+
[TSA_MITIGATION_FULL] = "Mitigation: Clear CPU buffers",
2125+
};
2126+
2127+
static enum tsa_mitigations tsa_mitigation __ro_after_init =
2128+
IS_ENABLED(CONFIG_MITIGATION_TSA) ? TSA_MITIGATION_FULL : TSA_MITIGATION_NONE;
2129+
2130+
static int __init tsa_parse_cmdline(char *str)
2131+
{
2132+
if (!str)
2133+
return -EINVAL;
2134+
2135+
if (!strcmp(str, "off"))
2136+
tsa_mitigation = TSA_MITIGATION_NONE;
2137+
else if (!strcmp(str, "on"))
2138+
tsa_mitigation = TSA_MITIGATION_FULL;
2139+
else if (!strcmp(str, "user"))
2140+
tsa_mitigation = TSA_MITIGATION_USER_KERNEL;
2141+
else if (!strcmp(str, "vm"))
2142+
tsa_mitigation = TSA_MITIGATION_VM;
2143+
else
2144+
pr_err("Ignoring unknown tsa=%s option.\n", str);
2145+
2146+
return 0;
2147+
}
2148+
early_param("tsa", tsa_parse_cmdline);
2149+
2150+
static void __init tsa_select_mitigation(void)
2151+
{
2152+
if (tsa_mitigation == TSA_MITIGATION_NONE)
2153+
return;
2154+
2155+
if (cpu_mitigations_off() || !boot_cpu_has_bug(X86_BUG_TSA)) {
2156+
tsa_mitigation = TSA_MITIGATION_NONE;
2157+
return;
2158+
}
2159+
2160+
if (!boot_cpu_has(X86_FEATURE_VERW_CLEAR))
2161+
tsa_mitigation = TSA_MITIGATION_UCODE_NEEDED;
2162+
2163+
switch (tsa_mitigation) {
2164+
case TSA_MITIGATION_USER_KERNEL:
2165+
setup_force_cpu_cap(X86_FEATURE_CLEAR_CPU_BUF);
2166+
break;
2167+
2168+
case TSA_MITIGATION_VM:
2169+
setup_force_cpu_cap(X86_FEATURE_CLEAR_CPU_BUF_VM);
2170+
break;
2171+
2172+
case TSA_MITIGATION_UCODE_NEEDED:
2173+
if (!boot_cpu_has(X86_FEATURE_HYPERVISOR))
2174+
goto out;
2175+
2176+
pr_notice("Forcing mitigation on in a VM\n");
2177+
2178+
/*
2179+
* On the off-chance that microcode has been updated
2180+
* on the host, enable the mitigation in the guest just
2181+
* in case.
2182+
*/
2183+
fallthrough;
2184+
case TSA_MITIGATION_FULL:
2185+
setup_force_cpu_cap(X86_FEATURE_CLEAR_CPU_BUF);
2186+
setup_force_cpu_cap(X86_FEATURE_CLEAR_CPU_BUF_VM);
2187+
break;
2188+
default:
2189+
break;
2190+
}
2191+
2192+
out:
2193+
pr_info("%s\n", tsa_strings[tsa_mitigation]);
2194+
}
2195+
21062196
void cpu_bugs_smt_update(void)
21072197
{
21082198
mutex_lock(&spec_ctrl_mutex);
@@ -2156,6 +2246,24 @@ void cpu_bugs_smt_update(void)
21562246
break;
21572247
}
21582248

2249+
switch (tsa_mitigation) {
2250+
case TSA_MITIGATION_USER_KERNEL:
2251+
case TSA_MITIGATION_VM:
2252+
case TSA_MITIGATION_FULL:
2253+
case TSA_MITIGATION_UCODE_NEEDED:
2254+
/*
2255+
* TSA-SQ can potentially lead to info leakage between
2256+
* SMT threads.
2257+
*/
2258+
if (sched_smt_active())
2259+
static_branch_enable(&cpu_buf_idle_clear);
2260+
else
2261+
static_branch_disable(&cpu_buf_idle_clear);
2262+
break;
2263+
case TSA_MITIGATION_NONE:
2264+
break;
2265+
}
2266+
21592267
mutex_unlock(&spec_ctrl_mutex);
21602268
}
21612269

@@ -3084,6 +3192,11 @@ static ssize_t gds_show_state(char *buf)
30843192
return sysfs_emit(buf, "%s\n", gds_strings[gds_mitigation]);
30853193
}
30863194

3195+
static ssize_t tsa_show_state(char *buf)
3196+
{
3197+
return sysfs_emit(buf, "%s\n", tsa_strings[tsa_mitigation]);
3198+
}
3199+
30873200
static ssize_t cpu_show_common(struct device *dev, struct device_attribute *attr,
30883201
char *buf, unsigned int bug)
30893202
{
@@ -3145,6 +3258,9 @@ static ssize_t cpu_show_common(struct device *dev, struct device_attribute *attr
31453258
case X86_BUG_ITS:
31463259
return its_show_state(buf);
31473260

3261+
case X86_BUG_TSA:
3262+
return tsa_show_state(buf);
3263+
31483264
default:
31493265
break;
31503266
}
@@ -3229,6 +3345,11 @@ ssize_t cpu_show_indirect_target_selection(struct device *dev, struct device_att
32293345
{
32303346
return cpu_show_common(dev, attr, buf, X86_BUG_ITS);
32313347
}
3348+
3349+
ssize_t cpu_show_tsa(struct device *dev, struct device_attribute *attr, char *buf)
3350+
{
3351+
return cpu_show_common(dev, attr, buf, X86_BUG_TSA);
3352+
}
32323353
#endif
32333354

32343355
void __warn_thunk(void)

0 commit comments

Comments
 (0)