Skip to content

Commit f36cf38

Browse files
committed
x86/speculation/swapgs: Exclude ATOMs from speculation through SWAPGS
Intel provided the following information: On all current Atom processors, instructions that use a segment register value (e.g. a load or store) will not speculatively execute before the last writer of that segment retires. Thus they will not use a speculatively written segment value. That means on ATOMs there is no speculation through SWAPGS, so the SWAPGS entry paths can be excluded from the extra LFENCE if PTI is disabled. Create a separate bug flag for the through SWAPGS speculation and mark all out-of-order ATOMs and AMD/HYGON CPUs as not affected. The in-order ATOMs are excluded from the whole mitigation mess anyway. Reported-by: Andrew Cooper <[email protected]> Signed-off-by: Thomas Gleixner <[email protected]> Reviewed-by: Tyler Hicks <[email protected]> Reviewed-by: Josh Poimboeuf <[email protected]>
1 parent 64dbc12 commit f36cf38

File tree

3 files changed

+33
-30
lines changed

3 files changed

+33
-30
lines changed

arch/x86/include/asm/cpufeatures.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -396,5 +396,6 @@
396396
#define X86_BUG_L1TF X86_BUG(18) /* CPU is affected by L1 Terminal Fault */
397397
#define X86_BUG_MDS X86_BUG(19) /* CPU is affected by Microarchitectural data sampling */
398398
#define X86_BUG_MSBDS_ONLY X86_BUG(20) /* CPU is only affected by the MSDBS variant of BUG_MDS */
399+
#define X86_BUG_SWAPGS X86_BUG(21) /* CPU is affected by speculation through SWAPGS */
399400

400401
#endif /* _ASM_X86_CPUFEATURES_H */

arch/x86/kernel/cpu/bugs.c

Lines changed: 4 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -284,18 +284,6 @@ static const char * const spectre_v1_strings[] = {
284284
[SPECTRE_V1_MITIGATION_AUTO] = "Mitigation: usercopy/swapgs barriers and __user pointer sanitization",
285285
};
286286

287-
static bool is_swapgs_serializing(void)
288-
{
289-
/*
290-
* Technically, swapgs isn't serializing on AMD (despite it previously
291-
* being documented as such in the APM). But according to AMD, %gs is
292-
* updated non-speculatively, and the issuing of %gs-relative memory
293-
* operands will be blocked until the %gs update completes, which is
294-
* good enough for our purposes.
295-
*/
296-
return boot_cpu_data.x86_vendor == X86_VENDOR_AMD;
297-
}
298-
299287
/*
300288
* Does SMAP provide full mitigation against speculative kernel access to
301289
* userspace?
@@ -346,9 +334,11 @@ static void __init spectre_v1_select_mitigation(void)
346334
* PTI as the CR3 write in the Meltdown mitigation
347335
* is serializing.
348336
*
349-
* If neither is there, mitigate with an LFENCE.
337+
* If neither is there, mitigate with an LFENCE to
338+
* stop speculation through swapgs.
350339
*/
351-
if (!is_swapgs_serializing() && !boot_cpu_has(X86_FEATURE_PTI))
340+
if (boot_cpu_has_bug(X86_BUG_SWAPGS) &&
341+
!boot_cpu_has(X86_FEATURE_PTI))
352342
setup_force_cpu_cap(X86_FEATURE_FENCE_SWAPGS_USER);
353343

354344
/*

arch/x86/kernel/cpu/common.c

Lines changed: 28 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -970,6 +970,7 @@ static void identify_cpu_without_cpuid(struct cpuinfo_x86 *c)
970970
#define NO_L1TF BIT(3)
971971
#define NO_MDS BIT(4)
972972
#define MSBDS_ONLY BIT(5)
973+
#define NO_SWAPGS BIT(6)
973974

974975
#define VULNWL(_vendor, _family, _model, _whitelist) \
975976
{ X86_VENDOR_##_vendor, _family, _model, X86_FEATURE_ANY, _whitelist }
@@ -996,30 +997,38 @@ static const __initconst struct x86_cpu_id cpu_vuln_whitelist[] = {
996997
VULNWL_INTEL(ATOM_BONNELL, NO_SPECULATION),
997998
VULNWL_INTEL(ATOM_BONNELL_MID, NO_SPECULATION),
998999

999-
VULNWL_INTEL(ATOM_SILVERMONT, NO_SSB | NO_L1TF | MSBDS_ONLY),
1000-
VULNWL_INTEL(ATOM_SILVERMONT_X, NO_SSB | NO_L1TF | MSBDS_ONLY),
1001-
VULNWL_INTEL(ATOM_SILVERMONT_MID, NO_SSB | NO_L1TF | MSBDS_ONLY),
1002-
VULNWL_INTEL(ATOM_AIRMONT, NO_SSB | NO_L1TF | MSBDS_ONLY),
1003-
VULNWL_INTEL(XEON_PHI_KNL, NO_SSB | NO_L1TF | MSBDS_ONLY),
1004-
VULNWL_INTEL(XEON_PHI_KNM, NO_SSB | NO_L1TF | MSBDS_ONLY),
1000+
VULNWL_INTEL(ATOM_SILVERMONT, NO_SSB | NO_L1TF | MSBDS_ONLY | NO_SWAPGS),
1001+
VULNWL_INTEL(ATOM_SILVERMONT_X, NO_SSB | NO_L1TF | MSBDS_ONLY | NO_SWAPGS),
1002+
VULNWL_INTEL(ATOM_SILVERMONT_MID, NO_SSB | NO_L1TF | MSBDS_ONLY | NO_SWAPGS),
1003+
VULNWL_INTEL(ATOM_AIRMONT, NO_SSB | NO_L1TF | MSBDS_ONLY | NO_SWAPGS),
1004+
VULNWL_INTEL(XEON_PHI_KNL, NO_SSB | NO_L1TF | MSBDS_ONLY | NO_SWAPGS),
1005+
VULNWL_INTEL(XEON_PHI_KNM, NO_SSB | NO_L1TF | MSBDS_ONLY | NO_SWAPGS),
10051006

10061007
VULNWL_INTEL(CORE_YONAH, NO_SSB),
10071008

1008-
VULNWL_INTEL(ATOM_AIRMONT_MID, NO_L1TF | MSBDS_ONLY),
1009+
VULNWL_INTEL(ATOM_AIRMONT_MID, NO_L1TF | MSBDS_ONLY | NO_SWAPGS),
10091010

1010-
VULNWL_INTEL(ATOM_GOLDMONT, NO_MDS | NO_L1TF),
1011-
VULNWL_INTEL(ATOM_GOLDMONT_X, NO_MDS | NO_L1TF),
1012-
VULNWL_INTEL(ATOM_GOLDMONT_PLUS, NO_MDS | NO_L1TF),
1011+
VULNWL_INTEL(ATOM_GOLDMONT, NO_MDS | NO_L1TF | NO_SWAPGS),
1012+
VULNWL_INTEL(ATOM_GOLDMONT_X, NO_MDS | NO_L1TF | NO_SWAPGS),
1013+
VULNWL_INTEL(ATOM_GOLDMONT_PLUS, NO_MDS | NO_L1TF | NO_SWAPGS),
1014+
1015+
/*
1016+
* Technically, swapgs isn't serializing on AMD (despite it previously
1017+
* being documented as such in the APM). But according to AMD, %gs is
1018+
* updated non-speculatively, and the issuing of %gs-relative memory
1019+
* operands will be blocked until the %gs update completes, which is
1020+
* good enough for our purposes.
1021+
*/
10131022

10141023
/* AMD Family 0xf - 0x12 */
1015-
VULNWL_AMD(0x0f, NO_MELTDOWN | NO_SSB | NO_L1TF | NO_MDS),
1016-
VULNWL_AMD(0x10, NO_MELTDOWN | NO_SSB | NO_L1TF | NO_MDS),
1017-
VULNWL_AMD(0x11, NO_MELTDOWN | NO_SSB | NO_L1TF | NO_MDS),
1018-
VULNWL_AMD(0x12, NO_MELTDOWN | NO_SSB | NO_L1TF | NO_MDS),
1024+
VULNWL_AMD(0x0f, NO_MELTDOWN | NO_SSB | NO_L1TF | NO_MDS | NO_SWAPGS),
1025+
VULNWL_AMD(0x10, NO_MELTDOWN | NO_SSB | NO_L1TF | NO_MDS | NO_SWAPGS),
1026+
VULNWL_AMD(0x11, NO_MELTDOWN | NO_SSB | NO_L1TF | NO_MDS | NO_SWAPGS),
1027+
VULNWL_AMD(0x12, NO_MELTDOWN | NO_SSB | NO_L1TF | NO_MDS | NO_SWAPGS),
10191028

10201029
/* FAMILY_ANY must be last, otherwise 0x0f - 0x12 matches won't work */
1021-
VULNWL_AMD(X86_FAMILY_ANY, NO_MELTDOWN | NO_L1TF | NO_MDS),
1022-
VULNWL_HYGON(X86_FAMILY_ANY, NO_MELTDOWN | NO_L1TF | NO_MDS),
1030+
VULNWL_AMD(X86_FAMILY_ANY, NO_MELTDOWN | NO_L1TF | NO_MDS | NO_SWAPGS),
1031+
VULNWL_HYGON(X86_FAMILY_ANY, NO_MELTDOWN | NO_L1TF | NO_MDS | NO_SWAPGS),
10231032
{}
10241033
};
10251034

@@ -1056,6 +1065,9 @@ static void __init cpu_set_bug_bits(struct cpuinfo_x86 *c)
10561065
setup_force_cpu_bug(X86_BUG_MSBDS_ONLY);
10571066
}
10581067

1068+
if (!cpu_matches(NO_SWAPGS))
1069+
setup_force_cpu_bug(X86_BUG_SWAPGS);
1070+
10591071
if (cpu_matches(NO_MELTDOWN))
10601072
return;
10611073

0 commit comments

Comments
 (0)