Skip to content

Commit d8010d4

Browse files
committed
x86/bugs: Add a Transient Scheduler Attacks mitigation
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]>
1 parent f9af88a commit d8010d4

File tree

13 files changed

+232
-7
lines changed

13 files changed

+232
-7
lines changed

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -584,6 +584,7 @@ What: /sys/devices/system/cpu/vulnerabilities
584584
/sys/devices/system/cpu/vulnerabilities/spectre_v1
585585
/sys/devices/system/cpu/vulnerabilities/spectre_v2
586586
/sys/devices/system/cpu/vulnerabilities/srbds
587+
/sys/devices/system/cpu/vulnerabilities/tsa
587588
/sys/devices/system/cpu/vulnerabilities/tsx_async_abort
588589
Date: January 2018
589590
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
@@ -7488,6 +7488,19 @@
74887488
having this key zero'ed is acceptable. E.g. in testing
74897489
scenarios.
74907490

7491+
tsa= [X86] Control mitigation for Transient Scheduler
7492+
Attacks on AMD CPUs. Search the following in your
7493+
favourite search engine for more details:
7494+
7495+
"Technical guidance for mitigating transient scheduler
7496+
attacks".
7497+
7498+
off - disable the mitigation
7499+
on - enable the mitigation (default)
7500+
user - mitigate only user/kernel transitions
7501+
vm - mitigate only guest/host transitions
7502+
7503+
74917504
tsc= Disable clocksource stability checks for TSC.
74927505
Format: <string>
74937506
[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
@@ -2695,6 +2695,15 @@ config MITIGATION_ITS
26952695
disabled, mitigation cannot be enabled via cmdline.
26962696
See <file:Documentation/admin-guide/hw-vuln/indirect-target-selection.rst>
26972697

2698+
config MITIGATION_TSA
2699+
bool "Mitigate Transient Scheduler Attacks"
2700+
depends on CPU_SUP_AMD
2701+
default y
2702+
help
2703+
Enable mitigation for Transient Scheduler Attacks. TSA is a hardware
2704+
security vulnerability on AMD CPUs which can lead to forwarding of
2705+
invalid info to subsequent instructions and thus can affect their
2706+
timing and thereby cause a leakage.
26982707
endif
26992708

27002709
config ARCH_HAS_ADD_PAGES

arch/x86/include/asm/cpufeatures.h

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -456,6 +456,7 @@
456456
#define X86_FEATURE_NO_NESTED_DATA_BP (20*32+ 0) /* No Nested Data Breakpoints */
457457
#define X86_FEATURE_WRMSR_XX_BASE_NS (20*32+ 1) /* WRMSR to {FS,GS,KERNEL_GS}_BASE is non-serializing */
458458
#define X86_FEATURE_LFENCE_RDTSC (20*32+ 2) /* LFENCE always serializing / synchronizes RDTSC */
459+
#define X86_FEATURE_VERW_CLEAR (20*32+ 5) /* The memory form of VERW mitigates TSA */
459460
#define X86_FEATURE_NULL_SEL_CLR_BASE (20*32+ 6) /* Null Selector Clears Base */
460461
#define X86_FEATURE_AUTOIBRS (20*32+ 8) /* Automatic IBRS */
461462
#define X86_FEATURE_NO_SMM_CTL_MSR (20*32+ 9) /* SMM_CTL MSR is not present */
@@ -487,6 +488,9 @@
487488
#define X86_FEATURE_PREFER_YMM (21*32+ 8) /* Avoid ZMM registers due to downclocking */
488489
#define X86_FEATURE_APX (21*32+ 9) /* Advanced Performance Extensions */
489490
#define X86_FEATURE_INDIRECT_THUNK_ITS (21*32+10) /* Use thunk for indirect branches in lower half of cacheline */
491+
#define X86_FEATURE_TSA_SQ_NO (21*32+11) /* AMD CPU not vulnerable to TSA-SQ */
492+
#define X86_FEATURE_TSA_L1_NO (21*32+12) /* AMD CPU not vulnerable to TSA-L1 */
493+
#define X86_FEATURE_CLEAR_CPU_BUF_VM (21*32+13) /* Clear CPU buffers using VERW before VMRUN */
490494

491495
/*
492496
* BUG word(s)
@@ -542,5 +546,5 @@
542546
#define X86_BUG_OLD_MICROCODE X86_BUG( 1*32+ 6) /* "old_microcode" CPU has old microcode, it is surely vulnerable to something */
543547
#define X86_BUG_ITS X86_BUG( 1*32+ 7) /* "its" CPU is affected by Indirect Target Selection */
544548
#define X86_BUG_ITS_NATIVE_ONLY X86_BUG( 1*32+ 8) /* "its_native_only" CPU is affected by ITS, VMX is not affected */
545-
549+
#define X86_BUG_TSA X86_BUG( 1*32+ 9) /* "tsa" CPU is affected by Transient Scheduler Attacks */
546550
#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(u32 eax, u32 ecx)
8080
*/
8181
static __always_inline void __mwaitx(u32 eax, u32 ebx, u32 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
@@ -308,19 +308,25 @@
308308
* CFLAGS.ZF.
309309
* Note: Only the memory operand variant of VERW clears the CPU buffers.
310310
*/
311-
.macro CLEAR_CPU_BUFFERS
311+
.macro __CLEAR_CPU_BUFFERS feature
312312
#ifdef CONFIG_X86_64
313-
ALTERNATIVE "", "verw x86_verw_sel(%rip)", X86_FEATURE_CLEAR_CPU_BUF
313+
ALTERNATIVE "", "verw x86_verw_sel(%rip)", \feature
314314
#else
315315
/*
316316
* In 32bit mode, the memory operand must be a %cs reference. The data
317317
* segments may not be usable (vm86 mode), and the stack segment may not
318318
* be flat (ESPFIX32).
319319
*/
320-
ALTERNATIVE "", "verw %cs:x86_verw_sel", X86_FEATURE_CLEAR_CPU_BUF
320+
ALTERNATIVE "", "verw %cs:x86_verw_sel", \feature
321321
#endif
322322
.endm
323323

324+
#define CLEAR_CPU_BUFFERS \
325+
__CLEAR_CPU_BUFFERS X86_FEATURE_CLEAR_CPU_BUF
326+
327+
#define VM_CLEAR_CPU_BUFFERS \
328+
__CLEAR_CPU_BUFFERS X86_FEATURE_CLEAR_CPU_BUF_VM
329+
324330
#ifdef CONFIG_X86_64
325331
.macro CLEAR_BRANCH_HISTORY
326332
ALTERNATIVE "", "call clear_bhb_loop", X86_FEATURE_CLEAR_BHB_LOOP
@@ -602,7 +608,7 @@ static __always_inline void x86_clear_cpu_buffers(void)
602608

603609
/**
604610
* x86_idle_clear_cpu_buffers - Buffer clearing support in idle for the MDS
605-
* vulnerability
611+
* and TSA vulnerabilities.
606612
*
607613
* Clear CPU buffers if the corresponding static key is enabled
608614
*/

arch/x86/kernel/cpu/amd.c

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -377,6 +377,47 @@ static void bsp_determine_snp(struct cpuinfo_x86 *c)
377377
#endif
378378
}
379379

380+
#define ZEN_MODEL_STEP_UCODE(fam, model, step, ucode) \
381+
X86_MATCH_VFM_STEPS(VFM_MAKE(X86_VENDOR_AMD, fam, model), \
382+
step, step, ucode)
383+
384+
static const struct x86_cpu_id amd_tsa_microcode[] = {
385+
ZEN_MODEL_STEP_UCODE(0x19, 0x01, 0x1, 0x0a0011d7),
386+
ZEN_MODEL_STEP_UCODE(0x19, 0x01, 0x2, 0x0a00123b),
387+
ZEN_MODEL_STEP_UCODE(0x19, 0x08, 0x2, 0x0a00820d),
388+
ZEN_MODEL_STEP_UCODE(0x19, 0x11, 0x1, 0x0a10114c),
389+
ZEN_MODEL_STEP_UCODE(0x19, 0x11, 0x2, 0x0a10124c),
390+
ZEN_MODEL_STEP_UCODE(0x19, 0x18, 0x1, 0x0a108109),
391+
ZEN_MODEL_STEP_UCODE(0x19, 0x21, 0x0, 0x0a20102e),
392+
ZEN_MODEL_STEP_UCODE(0x19, 0x21, 0x2, 0x0a201211),
393+
ZEN_MODEL_STEP_UCODE(0x19, 0x44, 0x1, 0x0a404108),
394+
ZEN_MODEL_STEP_UCODE(0x19, 0x50, 0x0, 0x0a500012),
395+
ZEN_MODEL_STEP_UCODE(0x19, 0x61, 0x2, 0x0a60120a),
396+
ZEN_MODEL_STEP_UCODE(0x19, 0x74, 0x1, 0x0a704108),
397+
ZEN_MODEL_STEP_UCODE(0x19, 0x75, 0x2, 0x0a705208),
398+
ZEN_MODEL_STEP_UCODE(0x19, 0x78, 0x0, 0x0a708008),
399+
ZEN_MODEL_STEP_UCODE(0x19, 0x7c, 0x0, 0x0a70c008),
400+
ZEN_MODEL_STEP_UCODE(0x19, 0xa0, 0x2, 0x0aa00216),
401+
{},
402+
};
403+
404+
static void tsa_init(struct cpuinfo_x86 *c)
405+
{
406+
if (cpu_has(c, X86_FEATURE_HYPERVISOR))
407+
return;
408+
409+
if (cpu_has(c, X86_FEATURE_ZEN3) ||
410+
cpu_has(c, X86_FEATURE_ZEN4)) {
411+
if (x86_match_min_microcode_rev(amd_tsa_microcode))
412+
setup_force_cpu_cap(X86_FEATURE_VERW_CLEAR);
413+
else
414+
pr_debug("%s: current revision: 0x%x\n", __func__, c->microcode);
415+
} else {
416+
setup_force_cpu_cap(X86_FEATURE_TSA_SQ_NO);
417+
setup_force_cpu_cap(X86_FEATURE_TSA_L1_NO);
418+
}
419+
}
420+
380421
static void bsp_init_amd(struct cpuinfo_x86 *c)
381422
{
382423
if (cpu_has(c, X86_FEATURE_CONSTANT_TSC)) {
@@ -489,6 +530,9 @@ static void bsp_init_amd(struct cpuinfo_x86 *c)
489530
}
490531

491532
bsp_determine_snp(c);
533+
534+
tsa_init(c);
535+
492536
return;
493537

494538
warn:

arch/x86/kernel/cpu/bugs.c

Lines changed: 124 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,8 @@ static void __init bhi_apply_mitigation(void);
9494
static void __init its_select_mitigation(void);
9595
static void __init its_update_mitigation(void);
9696
static void __init its_apply_mitigation(void);
97+
static void __init tsa_select_mitigation(void);
98+
static void __init tsa_apply_mitigation(void);
9799

98100
/* The base value of the SPEC_CTRL MSR without task-specific bits set */
99101
u64 x86_spec_ctrl_base;
@@ -225,6 +227,7 @@ void __init cpu_select_mitigations(void)
225227
gds_select_mitigation();
226228
its_select_mitigation();
227229
bhi_select_mitigation();
230+
tsa_select_mitigation();
228231

229232
/*
230233
* After mitigations are selected, some may need to update their
@@ -272,6 +275,7 @@ void __init cpu_select_mitigations(void)
272275
gds_apply_mitigation();
273276
its_apply_mitigation();
274277
bhi_apply_mitigation();
278+
tsa_apply_mitigation();
275279
}
276280

277281
/*
@@ -1487,6 +1491,94 @@ static void __init its_apply_mitigation(void)
14871491
set_return_thunk(its_return_thunk);
14881492
}
14891493

1494+
#undef pr_fmt
1495+
#define pr_fmt(fmt) "Transient Scheduler Attacks: " fmt
1496+
1497+
enum tsa_mitigations {
1498+
TSA_MITIGATION_NONE,
1499+
TSA_MITIGATION_AUTO,
1500+
TSA_MITIGATION_UCODE_NEEDED,
1501+
TSA_MITIGATION_USER_KERNEL,
1502+
TSA_MITIGATION_VM,
1503+
TSA_MITIGATION_FULL,
1504+
};
1505+
1506+
static const char * const tsa_strings[] = {
1507+
[TSA_MITIGATION_NONE] = "Vulnerable",
1508+
[TSA_MITIGATION_UCODE_NEEDED] = "Vulnerable: No microcode",
1509+
[TSA_MITIGATION_USER_KERNEL] = "Mitigation: Clear CPU buffers: user/kernel boundary",
1510+
[TSA_MITIGATION_VM] = "Mitigation: Clear CPU buffers: VM",
1511+
[TSA_MITIGATION_FULL] = "Mitigation: Clear CPU buffers",
1512+
};
1513+
1514+
static enum tsa_mitigations tsa_mitigation __ro_after_init =
1515+
IS_ENABLED(CONFIG_MITIGATION_TSA) ? TSA_MITIGATION_AUTO : TSA_MITIGATION_NONE;
1516+
1517+
static int __init tsa_parse_cmdline(char *str)
1518+
{
1519+
if (!str)
1520+
return -EINVAL;
1521+
1522+
if (!strcmp(str, "off"))
1523+
tsa_mitigation = TSA_MITIGATION_NONE;
1524+
else if (!strcmp(str, "on"))
1525+
tsa_mitigation = TSA_MITIGATION_FULL;
1526+
else if (!strcmp(str, "user"))
1527+
tsa_mitigation = TSA_MITIGATION_USER_KERNEL;
1528+
else if (!strcmp(str, "vm"))
1529+
tsa_mitigation = TSA_MITIGATION_VM;
1530+
else
1531+
pr_err("Ignoring unknown tsa=%s option.\n", str);
1532+
1533+
return 0;
1534+
}
1535+
early_param("tsa", tsa_parse_cmdline);
1536+
1537+
static void __init tsa_select_mitigation(void)
1538+
{
1539+
if (cpu_mitigations_off() || !boot_cpu_has_bug(X86_BUG_TSA)) {
1540+
tsa_mitigation = TSA_MITIGATION_NONE;
1541+
return;
1542+
}
1543+
1544+
if (tsa_mitigation == TSA_MITIGATION_NONE)
1545+
return;
1546+
1547+
if (!boot_cpu_has(X86_FEATURE_VERW_CLEAR)) {
1548+
tsa_mitigation = TSA_MITIGATION_UCODE_NEEDED;
1549+
goto out;
1550+
}
1551+
1552+
if (tsa_mitigation == TSA_MITIGATION_AUTO)
1553+
tsa_mitigation = TSA_MITIGATION_FULL;
1554+
1555+
/*
1556+
* No need to set verw_clear_cpu_buf_mitigation_selected - it
1557+
* doesn't fit all cases here and it is not needed because this
1558+
* is the only VERW-based mitigation on AMD.
1559+
*/
1560+
out:
1561+
pr_info("%s\n", tsa_strings[tsa_mitigation]);
1562+
}
1563+
1564+
static void __init tsa_apply_mitigation(void)
1565+
{
1566+
switch (tsa_mitigation) {
1567+
case TSA_MITIGATION_USER_KERNEL:
1568+
setup_force_cpu_cap(X86_FEATURE_CLEAR_CPU_BUF);
1569+
break;
1570+
case TSA_MITIGATION_VM:
1571+
setup_force_cpu_cap(X86_FEATURE_CLEAR_CPU_BUF_VM);
1572+
break;
1573+
case TSA_MITIGATION_FULL:
1574+
setup_force_cpu_cap(X86_FEATURE_CLEAR_CPU_BUF);
1575+
setup_force_cpu_cap(X86_FEATURE_CLEAR_CPU_BUF_VM);
1576+
break;
1577+
default:
1578+
break;
1579+
}
1580+
}
1581+
14901582
#undef pr_fmt
14911583
#define pr_fmt(fmt) "Spectre V2 : " fmt
14921584

@@ -2316,6 +2408,25 @@ void cpu_bugs_smt_update(void)
23162408
break;
23172409
}
23182410

2411+
switch (tsa_mitigation) {
2412+
case TSA_MITIGATION_USER_KERNEL:
2413+
case TSA_MITIGATION_VM:
2414+
case TSA_MITIGATION_AUTO:
2415+
case TSA_MITIGATION_FULL:
2416+
/*
2417+
* TSA-SQ can potentially lead to info leakage between
2418+
* SMT threads.
2419+
*/
2420+
if (sched_smt_active())
2421+
static_branch_enable(&cpu_buf_idle_clear);
2422+
else
2423+
static_branch_disable(&cpu_buf_idle_clear);
2424+
break;
2425+
case TSA_MITIGATION_NONE:
2426+
case TSA_MITIGATION_UCODE_NEEDED:
2427+
break;
2428+
}
2429+
23192430
mutex_unlock(&spec_ctrl_mutex);
23202431
}
23212432

@@ -3265,6 +3376,11 @@ static ssize_t gds_show_state(char *buf)
32653376
return sysfs_emit(buf, "%s\n", gds_strings[gds_mitigation]);
32663377
}
32673378

3379+
static ssize_t tsa_show_state(char *buf)
3380+
{
3381+
return sysfs_emit(buf, "%s\n", tsa_strings[tsa_mitigation]);
3382+
}
3383+
32683384
static ssize_t cpu_show_common(struct device *dev, struct device_attribute *attr,
32693385
char *buf, unsigned int bug)
32703386
{
@@ -3328,6 +3444,9 @@ static ssize_t cpu_show_common(struct device *dev, struct device_attribute *attr
33283444
case X86_BUG_ITS:
33293445
return its_show_state(buf);
33303446

3447+
case X86_BUG_TSA:
3448+
return tsa_show_state(buf);
3449+
33313450
default:
33323451
break;
33333452
}
@@ -3414,6 +3533,11 @@ ssize_t cpu_show_indirect_target_selection(struct device *dev, struct device_att
34143533
{
34153534
return cpu_show_common(dev, attr, buf, X86_BUG_ITS);
34163535
}
3536+
3537+
ssize_t cpu_show_tsa(struct device *dev, struct device_attribute *attr, char *buf)
3538+
{
3539+
return cpu_show_common(dev, attr, buf, X86_BUG_TSA);
3540+
}
34173541
#endif
34183542

34193543
void __warn_thunk(void)

arch/x86/kernel/cpu/common.c

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1233,6 +1233,8 @@ static const __initconst struct x86_cpu_id cpu_vuln_whitelist[] = {
12331233
#define ITS BIT(8)
12341234
/* CPU is affected by Indirect Target Selection, but guest-host isolation is not affected */
12351235
#define ITS_NATIVE_ONLY BIT(9)
1236+
/* CPU is affected by Transient Scheduler Attacks */
1237+
#define TSA BIT(10)
12361238

12371239
static const struct x86_cpu_id cpu_vuln_blacklist[] __initconst = {
12381240
VULNBL_INTEL_STEPS(INTEL_IVYBRIDGE, X86_STEP_MAX, SRBDS),
@@ -1280,7 +1282,7 @@ static const struct x86_cpu_id cpu_vuln_blacklist[] __initconst = {
12801282
VULNBL_AMD(0x16, RETBLEED),
12811283
VULNBL_AMD(0x17, RETBLEED | SMT_RSB | SRSO),
12821284
VULNBL_HYGON(0x18, RETBLEED | SMT_RSB | SRSO),
1283-
VULNBL_AMD(0x19, SRSO),
1285+
VULNBL_AMD(0x19, SRSO | TSA),
12841286
VULNBL_AMD(0x1a, SRSO),
12851287
{}
12861288
};
@@ -1530,6 +1532,16 @@ static void __init cpu_set_bug_bits(struct cpuinfo_x86 *c)
15301532
setup_force_cpu_bug(X86_BUG_ITS_NATIVE_ONLY);
15311533
}
15321534

1535+
if (c->x86_vendor == X86_VENDOR_AMD) {
1536+
if (!cpu_has(c, X86_FEATURE_TSA_SQ_NO) ||
1537+
!cpu_has(c, X86_FEATURE_TSA_L1_NO)) {
1538+
if (cpu_matches(cpu_vuln_blacklist, TSA) ||
1539+
/* Enable bug on Zen guests to allow for live migration. */
1540+
(cpu_has(c, X86_FEATURE_HYPERVISOR) && cpu_has(c, X86_FEATURE_ZEN)))
1541+
setup_force_cpu_bug(X86_BUG_TSA);
1542+
}
1543+
}
1544+
15331545
if (cpu_matches(cpu_vuln_whitelist, NO_MELTDOWN))
15341546
return;
15351547

arch/x86/kernel/cpu/scattered.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,8 @@ static const struct cpuid_bit cpuid_bits[] = {
5050
{ X86_FEATURE_MBA, CPUID_EBX, 6, 0x80000008, 0 },
5151
{ X86_FEATURE_SMBA, CPUID_EBX, 2, 0x80000020, 0 },
5252
{ X86_FEATURE_BMEC, CPUID_EBX, 3, 0x80000020, 0 },
53+
{ X86_FEATURE_TSA_SQ_NO, CPUID_ECX, 1, 0x80000021, 0 },
54+
{ X86_FEATURE_TSA_L1_NO, CPUID_ECX, 2, 0x80000021, 0 },
5355
{ X86_FEATURE_AMD_WORKLOAD_CLASS, CPUID_EAX, 22, 0x80000021, 0 },
5456
{ X86_FEATURE_PERFMON_V2, CPUID_EAX, 0, 0x80000022, 0 },
5557
{ X86_FEATURE_AMD_LBR_V2, CPUID_EAX, 1, 0x80000022, 0 },

0 commit comments

Comments
 (0)