Skip to content

Commit 9029304

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 <kim.phillips@amd.com> Signed-off-by: Kim Phillips <kim.phillips@amd.com> Signed-off-by: Borislav Petkov (AMD) <bp@alien8.de> Reviewed-by: Pawan Gupta <pawan.kumar.gupta@linux.intel.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
1 parent 2b6a5fb commit 9029304

15 files changed

Lines changed: 258 additions & 18 deletions

File tree

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -526,6 +526,7 @@ What: /sys/devices/system/cpu/vulnerabilities
526526
/sys/devices/system/cpu/vulnerabilities/spectre_v1
527527
/sys/devices/system/cpu/vulnerabilities/spectre_v2
528528
/sys/devices/system/cpu/vulnerabilities/srbds
529+
/sys/devices/system/cpu/vulnerabilities/tsa
529530
/sys/devices/system/cpu/vulnerabilities/tsx_async_abort
530531
Date: January 2018
531532
Contact: Linux kernel mailing list <linux-kernel@vger.kernel.org>

Documentation/admin-guide/kernel-parameters.txt

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6645,6 +6645,19 @@
66456645
If not specified, "default" is used. In this case,
66466646
the RNG's choice is left to each individual trust source.
66476647

6648+
tsa= [X86] Control mitigation for Transient Scheduler
6649+
Attacks on AMD CPUs. Search the following in your
6650+
favourite search engine for more details:
6651+
6652+
"Technical guidance for mitigating transient scheduler
6653+
attacks".
6654+
6655+
off - disable the mitigation
6656+
on - enable the mitigation (default)
6657+
user - mitigate only user/kernel transitions
6658+
vm - mitigate only guest/host transitions
6659+
6660+
66486661
tsc= Disable clocksource stability checks for TSC.
66496662
Format: <string>
66506663
[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
@@ -2621,6 +2621,15 @@ config MITIGATION_ITS
26212621
disabled, mitigation cannot be enabled via cmdline.
26222622
See <file:Documentation/admin-guide/hw-vuln/indirect-target-selection.rst>
26232623

2624+
config MITIGATION_TSA
2625+
bool "Mitigate Transient Scheduler Attacks"
2626+
depends on CPU_SUP_AMD
2627+
default y
2628+
help
2629+
Enable mitigation for Transient Scheduler Attacks. TSA is a hardware
2630+
security vulnerability on AMD CPUs which can lead to forwarding of
2631+
invalid info to subsequent instructions and thus can affect their
2632+
timing and thereby cause a leakage.
26242633
endif
26252634

26262635
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
@@ -81,4 +81,16 @@ int intel_microcode_sanity_check(void *mc, bool print_err, int hdr_type);
8181

8282
extern struct cpumask cpus_stop_mask;
8383

84+
union zen_patch_rev {
85+
struct {
86+
__u32 rev : 8,
87+
stepping : 4,
88+
model : 4,
89+
__reserved : 4,
90+
ext_model : 4,
91+
ext_fam : 8;
92+
};
93+
__u32 ucode_rev;
94+
};
95+
8496
#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
@@ -449,6 +449,7 @@
449449
/* AMD-defined Extended Feature 2 EAX, CPUID level 0x80000021 (EAX), word 20 */
450450
#define X86_FEATURE_NO_NESTED_DATA_BP (20*32+ 0) /* "" No Nested Data Breakpoints */
451451
#define X86_FEATURE_LFENCE_RDTSC (20*32+ 2) /* "" LFENCE always serializing / synchronizes RDTSC */
452+
#define X86_FEATURE_VERW_CLEAR (20*32+ 5) /* "" The memory form of VERW mitigates TSA */
452453
#define X86_FEATURE_NULL_SEL_CLR_BASE (20*32+ 6) /* "" Null Selector Clears Base */
453454
#define X86_FEATURE_AUTOIBRS (20*32+ 8) /* "" Automatic IBRS */
454455
#define X86_FEATURE_NO_SMM_CTL_MSR (20*32+ 9) /* "" SMM_CTL MSR is not present */
@@ -470,6 +471,10 @@
470471
#define X86_FEATURE_CLEAR_BHB_LOOP_ON_VMEXIT (21*32+ 4) /* "" Clear branch history at vmexit using SW loop */
471472
#define X86_FEATURE_INDIRECT_THUNK_ITS (21*32 + 5) /* "" Use thunk for indirect branches in lower half of cacheline */
472473

474+
#define X86_FEATURE_TSA_SQ_NO (21*32+11) /* "" AMD CPU not vulnerable to TSA-SQ */
475+
#define X86_FEATURE_TSA_L1_NO (21*32+12) /* "" AMD CPU not vulnerable to TSA-L1 */
476+
#define X86_FEATURE_CLEAR_CPU_BUF_VM (21*32+13) /* "" Clear CPU buffers using VERW before VMRUN */
477+
473478
/*
474479
* BUG word(s)
475480
*/
@@ -521,4 +526,5 @@
521526
#define X86_BUG_IBPB_NO_RET X86_BUG(1*32 + 4) /* "ibpb_no_ret" IBPB omits return target predictions */
522527
#define X86_BUG_ITS X86_BUG(1*32 + 5) /* CPU is affected by Indirect Target Selection */
523528
#define X86_BUG_ITS_NATIVE_ONLY X86_BUG(1*32 + 6) /* CPU is affected by ITS, VMX is not affected */
529+
#define X86_BUG_TSA X86_BUG(1*32+ 9) /* "tsa" CPU is affected by Transient Scheduler Attacks */
524530
#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
@@ -330,19 +330,25 @@
330330
* CFLAGS.ZF.
331331
* Note: Only the memory operand variant of VERW clears the CPU buffers.
332332
*/
333-
.macro CLEAR_CPU_BUFFERS
333+
.macro __CLEAR_CPU_BUFFERS feature
334334
#ifdef CONFIG_X86_64
335-
ALTERNATIVE "", "verw x86_verw_sel(%rip)", X86_FEATURE_CLEAR_CPU_BUF
335+
ALTERNATIVE "", "verw x86_verw_sel(%rip)", \feature
336336
#else
337337
/*
338338
* In 32bit mode, the memory operand must be a %cs reference. The data
339339
* segments may not be usable (vm86 mode), and the stack segment may not
340340
* be flat (ESPFIX32).
341341
*/
342-
ALTERNATIVE "", "verw %cs:x86_verw_sel", X86_FEATURE_CLEAR_CPU_BUF
342+
ALTERNATIVE "", "verw %cs:x86_verw_sel", \feature
343343
#endif
344344
.endm
345345

346+
#define CLEAR_CPU_BUFFERS \
347+
__CLEAR_CPU_BUFFERS X86_FEATURE_CLEAR_CPU_BUF
348+
349+
#define VM_CLEAR_CPU_BUFFERS \
350+
__CLEAR_CPU_BUFFERS X86_FEATURE_CLEAR_CPU_BUF_VM
351+
346352
#ifdef CONFIG_X86_64
347353
.macro CLEAR_BRANCH_HISTORY
348354
ALTERNATIVE "", "call clear_bhb_loop", X86_FEATURE_CLEAR_BHB_LOOP
@@ -627,7 +633,7 @@ static __always_inline void x86_clear_cpu_buffers(void)
627633

628634
/**
629635
* x86_idle_clear_cpu_buffers - Buffer clearing support in idle for the MDS
630-
* vulnerability
636+
* and TSA vulnerabilities.
631637
*
632638
* Clear CPU buffers if the corresponding static key is enabled
633639
*/

arch/x86/kernel/cpu/amd.c

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -539,6 +539,63 @@ static void early_init_amd_mc(struct cpuinfo_x86 *c)
539539
#endif
540540
}
541541

542+
static bool amd_check_tsa_microcode(void)
543+
{
544+
struct cpuinfo_x86 *c = &boot_cpu_data;
545+
union zen_patch_rev p;
546+
u32 min_rev = 0;
547+
548+
p.ext_fam = c->x86 - 0xf;
549+
p.model = c->x86_model;
550+
p.stepping = c->x86_stepping;
551+
552+
if (cpu_has(c, X86_FEATURE_ZEN3) ||
553+
cpu_has(c, X86_FEATURE_ZEN4)) {
554+
switch (p.ucode_rev >> 8) {
555+
case 0xa0011: min_rev = 0x0a0011d7; break;
556+
case 0xa0012: min_rev = 0x0a00123b; break;
557+
case 0xa0082: min_rev = 0x0a00820d; break;
558+
case 0xa1011: min_rev = 0x0a10114c; break;
559+
case 0xa1012: min_rev = 0x0a10124c; break;
560+
case 0xa1081: min_rev = 0x0a108109; break;
561+
case 0xa2010: min_rev = 0x0a20102e; break;
562+
case 0xa2012: min_rev = 0x0a201211; break;
563+
case 0xa4041: min_rev = 0x0a404108; break;
564+
case 0xa5000: min_rev = 0x0a500012; break;
565+
case 0xa6012: min_rev = 0x0a60120a; break;
566+
case 0xa7041: min_rev = 0x0a704108; break;
567+
case 0xa7052: min_rev = 0x0a705208; break;
568+
case 0xa7080: min_rev = 0x0a708008; break;
569+
case 0xa70c0: min_rev = 0x0a70c008; break;
570+
case 0xaa002: min_rev = 0x0aa00216; break;
571+
default:
572+
pr_debug("%s: ucode_rev: 0x%x, current revision: 0x%x\n",
573+
__func__, p.ucode_rev, c->microcode);
574+
return false;
575+
}
576+
}
577+
578+
if (!min_rev)
579+
return false;
580+
581+
return c->microcode >= min_rev;
582+
}
583+
584+
static void tsa_init(struct cpuinfo_x86 *c)
585+
{
586+
if (cpu_has(c, X86_FEATURE_HYPERVISOR))
587+
return;
588+
589+
if (cpu_has(c, X86_FEATURE_ZEN3) ||
590+
cpu_has(c, X86_FEATURE_ZEN4)) {
591+
if (amd_check_tsa_microcode())
592+
setup_force_cpu_cap(X86_FEATURE_VERW_CLEAR);
593+
} else {
594+
setup_force_cpu_cap(X86_FEATURE_TSA_SQ_NO);
595+
setup_force_cpu_cap(X86_FEATURE_TSA_L1_NO);
596+
}
597+
}
598+
542599
static void bsp_init_amd(struct cpuinfo_x86 *c)
543600
{
544601
if (cpu_has(c, X86_FEATURE_CONSTANT_TSC)) {
@@ -645,6 +702,9 @@ static void bsp_init_amd(struct cpuinfo_x86 *c)
645702
break;
646703
}
647704

705+
706+
tsa_init(c);
707+
648708
return;
649709

650710
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
/*
@@ -2093,6 +2095,94 @@ static void update_mds_branch_idle(void)
20932095
#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"
20942096
#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"
20952097

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

2239+
switch (tsa_mitigation) {
2240+
case TSA_MITIGATION_USER_KERNEL:
2241+
case TSA_MITIGATION_VM:
2242+
case TSA_MITIGATION_FULL:
2243+
case TSA_MITIGATION_UCODE_NEEDED:
2244+
/*
2245+
* TSA-SQ can potentially lead to info leakage between
2246+
* SMT threads.
2247+
*/
2248+
if (sched_smt_active())
2249+
static_branch_enable(&cpu_buf_idle_clear);
2250+
else
2251+
static_branch_disable(&cpu_buf_idle_clear);
2252+
break;
2253+
case TSA_MITIGATION_NONE:
2254+
break;
2255+
}
2256+
21492257
mutex_unlock(&spec_ctrl_mutex);
21502258
}
21512259

@@ -3075,6 +3183,11 @@ static ssize_t gds_show_state(char *buf)
30753183
return sysfs_emit(buf, "%s\n", gds_strings[gds_mitigation]);
30763184
}
30773185

3186+
static ssize_t tsa_show_state(char *buf)
3187+
{
3188+
return sysfs_emit(buf, "%s\n", tsa_strings[tsa_mitigation]);
3189+
}
3190+
30783191
static ssize_t cpu_show_common(struct device *dev, struct device_attribute *attr,
30793192
char *buf, unsigned int bug)
30803193
{
@@ -3136,6 +3249,9 @@ static ssize_t cpu_show_common(struct device *dev, struct device_attribute *attr
31363249
case X86_BUG_ITS:
31373250
return its_show_state(buf);
31383251

3252+
case X86_BUG_TSA:
3253+
return tsa_show_state(buf);
3254+
31393255
default:
31403256
break;
31413257
}
@@ -3220,4 +3336,9 @@ ssize_t cpu_show_indirect_target_selection(struct device *dev, struct device_att
32203336
{
32213337
return cpu_show_common(dev, attr, buf, X86_BUG_ITS);
32223338
}
3339+
3340+
ssize_t cpu_show_tsa(struct device *dev, struct device_attribute *attr, char *buf)
3341+
{
3342+
return cpu_show_common(dev, attr, buf, X86_BUG_TSA);
3343+
}
32233344
#endif

0 commit comments

Comments
 (0)