Skip to content

Commit db4d30f

Browse files
vintummalaKAGA-KOKO
authored andcommitted
x86/bugs: Add ITLB_MULTIHIT bug infrastructure
Some processors may incur a machine check error possibly resulting in an unrecoverable CPU lockup when an instruction fetch encounters a TLB multi-hit in the instruction TLB. This can occur when the page size is changed along with either the physical address or cache type. The relevant erratum can be found here: https://bugzilla.kernel.org/show_bug.cgi?id=205195 There are other processors affected for which the erratum does not fully disclose the impact. This issue affects both bare-metal x86 page tables and EPT. It can be mitigated by either eliminating the use of large pages or by using careful TLB invalidations when changing the page size in the page tables. Just like Spectre, Meltdown, L1TF and MDS, a new bit has been allocated in MSR_IA32_ARCH_CAPABILITIES (PSCHANGE_MC_NO) and will be set on CPUs which are mitigated against this issue. Signed-off-by: Vineela Tummalapalli <[email protected]> Co-developed-by: Pawan Gupta <[email protected]> Signed-off-by: Pawan Gupta <[email protected]> Signed-off-by: Paolo Bonzini <[email protected]> Signed-off-by: Thomas Gleixner <[email protected]>
1 parent ca8888d commit db4d30f

File tree

7 files changed

+67
-30
lines changed

7 files changed

+67
-30
lines changed

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -487,6 +487,7 @@ What: /sys/devices/system/cpu/vulnerabilities
487487
/sys/devices/system/cpu/vulnerabilities/l1tf
488488
/sys/devices/system/cpu/vulnerabilities/mds
489489
/sys/devices/system/cpu/vulnerabilities/tsx_async_abort
490+
/sys/devices/system/cpu/vulnerabilities/itlb_multihit
490491
Date: January 2018
491492
Contact: Linux kernel mailing list <[email protected]>
492493
Description: Information about CPU vulnerabilities

arch/x86/include/asm/cpufeatures.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -400,5 +400,6 @@
400400
#define X86_BUG_MSBDS_ONLY X86_BUG(20) /* CPU is only affected by the MSDBS variant of BUG_MDS */
401401
#define X86_BUG_SWAPGS X86_BUG(21) /* CPU is affected by speculation through SWAPGS */
402402
#define X86_BUG_TAA X86_BUG(22) /* CPU is affected by TSX Async Abort(TAA) */
403+
#define X86_BUG_ITLB_MULTIHIT X86_BUG(23) /* CPU may incur MCE during certain page attribute changes */
403404

404405
#endif /* _ASM_X86_CPUFEATURES_H */

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

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,13 @@
9393
* Microarchitectural Data
9494
* Sampling (MDS) vulnerabilities.
9595
*/
96+
#define ARCH_CAP_PSCHANGE_MC_NO BIT(6) /*
97+
* The processor is not susceptible to a
98+
* machine check error due to modifying the
99+
* code page size along with either the
100+
* physical address or cache type
101+
* without TLB invalidation.
102+
*/
96103
#define ARCH_CAP_TSX_CTRL_MSR BIT(7) /* MSR for TSX control is available. */
97104
#define ARCH_CAP_TAA_NO BIT(8) /*
98105
* Not susceptible to

arch/x86/kernel/cpu/bugs.c

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1419,6 +1419,11 @@ static ssize_t l1tf_show_state(char *buf)
14191419
}
14201420
#endif
14211421

1422+
static ssize_t itlb_multihit_show_state(char *buf)
1423+
{
1424+
return sprintf(buf, "Processor vulnerable\n");
1425+
}
1426+
14221427
static ssize_t mds_show_state(char *buf)
14231428
{
14241429
if (boot_cpu_has(X86_FEATURE_HYPERVISOR)) {
@@ -1524,6 +1529,9 @@ static ssize_t cpu_show_common(struct device *dev, struct device_attribute *attr
15241529
case X86_BUG_TAA:
15251530
return tsx_async_abort_show_state(buf);
15261531

1532+
case X86_BUG_ITLB_MULTIHIT:
1533+
return itlb_multihit_show_state(buf);
1534+
15271535
default:
15281536
break;
15291537
}
@@ -1565,4 +1573,9 @@ ssize_t cpu_show_tsx_async_abort(struct device *dev, struct device_attribute *at
15651573
{
15661574
return cpu_show_common(dev, attr, buf, X86_BUG_TAA);
15671575
}
1576+
1577+
ssize_t cpu_show_itlb_multihit(struct device *dev, struct device_attribute *attr, char *buf)
1578+
{
1579+
return cpu_show_common(dev, attr, buf, X86_BUG_ITLB_MULTIHIT);
1580+
}
15681581
#endif

arch/x86/kernel/cpu/common.c

Lines changed: 35 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -1016,13 +1016,14 @@ static void identify_cpu_without_cpuid(struct cpuinfo_x86 *c)
10161016
#endif
10171017
}
10181018

1019-
#define NO_SPECULATION BIT(0)
1020-
#define NO_MELTDOWN BIT(1)
1021-
#define NO_SSB BIT(2)
1022-
#define NO_L1TF BIT(3)
1023-
#define NO_MDS BIT(4)
1024-
#define MSBDS_ONLY BIT(5)
1025-
#define NO_SWAPGS BIT(6)
1019+
#define NO_SPECULATION BIT(0)
1020+
#define NO_MELTDOWN BIT(1)
1021+
#define NO_SSB BIT(2)
1022+
#define NO_L1TF BIT(3)
1023+
#define NO_MDS BIT(4)
1024+
#define MSBDS_ONLY BIT(5)
1025+
#define NO_SWAPGS BIT(6)
1026+
#define NO_ITLB_MULTIHIT BIT(7)
10261027

10271028
#define VULNWL(_vendor, _family, _model, _whitelist) \
10281029
{ X86_VENDOR_##_vendor, _family, _model, X86_FEATURE_ANY, _whitelist }
@@ -1043,27 +1044,27 @@ static const __initconst struct x86_cpu_id cpu_vuln_whitelist[] = {
10431044
VULNWL(NSC, 5, X86_MODEL_ANY, NO_SPECULATION),
10441045

10451046
/* Intel Family 6 */
1046-
VULNWL_INTEL(ATOM_SALTWELL, NO_SPECULATION),
1047-
VULNWL_INTEL(ATOM_SALTWELL_TABLET, NO_SPECULATION),
1048-
VULNWL_INTEL(ATOM_SALTWELL_MID, NO_SPECULATION),
1049-
VULNWL_INTEL(ATOM_BONNELL, NO_SPECULATION),
1050-
VULNWL_INTEL(ATOM_BONNELL_MID, NO_SPECULATION),
1051-
1052-
VULNWL_INTEL(ATOM_SILVERMONT, NO_SSB | NO_L1TF | MSBDS_ONLY | NO_SWAPGS),
1053-
VULNWL_INTEL(ATOM_SILVERMONT_D, NO_SSB | NO_L1TF | MSBDS_ONLY | NO_SWAPGS),
1054-
VULNWL_INTEL(ATOM_SILVERMONT_MID, NO_SSB | NO_L1TF | MSBDS_ONLY | NO_SWAPGS),
1055-
VULNWL_INTEL(ATOM_AIRMONT, NO_SSB | NO_L1TF | MSBDS_ONLY | NO_SWAPGS),
1056-
VULNWL_INTEL(XEON_PHI_KNL, NO_SSB | NO_L1TF | MSBDS_ONLY | NO_SWAPGS),
1057-
VULNWL_INTEL(XEON_PHI_KNM, NO_SSB | NO_L1TF | MSBDS_ONLY | NO_SWAPGS),
1047+
VULNWL_INTEL(ATOM_SALTWELL, NO_SPECULATION | NO_ITLB_MULTIHIT),
1048+
VULNWL_INTEL(ATOM_SALTWELL_TABLET, NO_SPECULATION | NO_ITLB_MULTIHIT),
1049+
VULNWL_INTEL(ATOM_SALTWELL_MID, NO_SPECULATION | NO_ITLB_MULTIHIT),
1050+
VULNWL_INTEL(ATOM_BONNELL, NO_SPECULATION | NO_ITLB_MULTIHIT),
1051+
VULNWL_INTEL(ATOM_BONNELL_MID, NO_SPECULATION | NO_ITLB_MULTIHIT),
1052+
1053+
VULNWL_INTEL(ATOM_SILVERMONT, NO_SSB | NO_L1TF | MSBDS_ONLY | NO_SWAPGS | NO_ITLB_MULTIHIT),
1054+
VULNWL_INTEL(ATOM_SILVERMONT_D, NO_SSB | NO_L1TF | MSBDS_ONLY | NO_SWAPGS | NO_ITLB_MULTIHIT),
1055+
VULNWL_INTEL(ATOM_SILVERMONT_MID, NO_SSB | NO_L1TF | MSBDS_ONLY | NO_SWAPGS | NO_ITLB_MULTIHIT),
1056+
VULNWL_INTEL(ATOM_AIRMONT, NO_SSB | NO_L1TF | MSBDS_ONLY | NO_SWAPGS | NO_ITLB_MULTIHIT),
1057+
VULNWL_INTEL(XEON_PHI_KNL, NO_SSB | NO_L1TF | MSBDS_ONLY | NO_SWAPGS | NO_ITLB_MULTIHIT),
1058+
VULNWL_INTEL(XEON_PHI_KNM, NO_SSB | NO_L1TF | MSBDS_ONLY | NO_SWAPGS | NO_ITLB_MULTIHIT),
10581059

10591060
VULNWL_INTEL(CORE_YONAH, NO_SSB),
10601061

1061-
VULNWL_INTEL(ATOM_AIRMONT_MID, NO_L1TF | MSBDS_ONLY | NO_SWAPGS),
1062-
VULNWL_INTEL(ATOM_AIRMONT_NP, NO_L1TF | NO_SWAPGS),
1062+
VULNWL_INTEL(ATOM_AIRMONT_MID, NO_L1TF | MSBDS_ONLY | NO_SWAPGS | NO_ITLB_MULTIHIT),
1063+
VULNWL_INTEL(ATOM_AIRMONT_NP, NO_L1TF | NO_SWAPGS | NO_ITLB_MULTIHIT),
10631064

1064-
VULNWL_INTEL(ATOM_GOLDMONT, NO_MDS | NO_L1TF | NO_SWAPGS),
1065-
VULNWL_INTEL(ATOM_GOLDMONT_D, NO_MDS | NO_L1TF | NO_SWAPGS),
1066-
VULNWL_INTEL(ATOM_GOLDMONT_PLUS, NO_MDS | NO_L1TF | NO_SWAPGS),
1065+
VULNWL_INTEL(ATOM_GOLDMONT, NO_MDS | NO_L1TF | NO_SWAPGS | NO_ITLB_MULTIHIT),
1066+
VULNWL_INTEL(ATOM_GOLDMONT_D, NO_MDS | NO_L1TF | NO_SWAPGS | NO_ITLB_MULTIHIT),
1067+
VULNWL_INTEL(ATOM_GOLDMONT_PLUS, NO_MDS | NO_L1TF | NO_SWAPGS | NO_ITLB_MULTIHIT),
10671068

10681069
/*
10691070
* Technically, swapgs isn't serializing on AMD (despite it previously
@@ -1074,14 +1075,14 @@ static const __initconst struct x86_cpu_id cpu_vuln_whitelist[] = {
10741075
*/
10751076

10761077
/* AMD Family 0xf - 0x12 */
1077-
VULNWL_AMD(0x0f, NO_MELTDOWN | NO_SSB | NO_L1TF | NO_MDS | NO_SWAPGS),
1078-
VULNWL_AMD(0x10, NO_MELTDOWN | NO_SSB | NO_L1TF | NO_MDS | NO_SWAPGS),
1079-
VULNWL_AMD(0x11, NO_MELTDOWN | NO_SSB | NO_L1TF | NO_MDS | NO_SWAPGS),
1080-
VULNWL_AMD(0x12, NO_MELTDOWN | NO_SSB | NO_L1TF | NO_MDS | NO_SWAPGS),
1078+
VULNWL_AMD(0x0f, NO_MELTDOWN | NO_SSB | NO_L1TF | NO_MDS | NO_SWAPGS | NO_ITLB_MULTIHIT),
1079+
VULNWL_AMD(0x10, NO_MELTDOWN | NO_SSB | NO_L1TF | NO_MDS | NO_SWAPGS | NO_ITLB_MULTIHIT),
1080+
VULNWL_AMD(0x11, NO_MELTDOWN | NO_SSB | NO_L1TF | NO_MDS | NO_SWAPGS | NO_ITLB_MULTIHIT),
1081+
VULNWL_AMD(0x12, NO_MELTDOWN | NO_SSB | NO_L1TF | NO_MDS | NO_SWAPGS | NO_ITLB_MULTIHIT),
10811082

10821083
/* FAMILY_ANY must be last, otherwise 0x0f - 0x12 matches won't work */
1083-
VULNWL_AMD(X86_FAMILY_ANY, NO_MELTDOWN | NO_L1TF | NO_MDS | NO_SWAPGS),
1084-
VULNWL_HYGON(X86_FAMILY_ANY, NO_MELTDOWN | NO_L1TF | NO_MDS | NO_SWAPGS),
1084+
VULNWL_AMD(X86_FAMILY_ANY, NO_MELTDOWN | NO_L1TF | NO_MDS | NO_SWAPGS | NO_ITLB_MULTIHIT),
1085+
VULNWL_HYGON(X86_FAMILY_ANY, NO_MELTDOWN | NO_L1TF | NO_MDS | NO_SWAPGS | NO_ITLB_MULTIHIT),
10851086
{}
10861087
};
10871088

@@ -1106,6 +1107,10 @@ static void __init cpu_set_bug_bits(struct cpuinfo_x86 *c)
11061107
{
11071108
u64 ia32_cap = x86_read_arch_cap_msr();
11081109

1110+
/* Set ITLB_MULTIHIT bug if cpu is not in the whitelist and not mitigated */
1111+
if (!cpu_matches(NO_ITLB_MULTIHIT) && !(ia32_cap & ARCH_CAP_PSCHANGE_MC_NO))
1112+
setup_force_cpu_bug(X86_BUG_ITLB_MULTIHIT);
1113+
11091114
if (cpu_matches(NO_SPECULATION))
11101115
return;
11111116

drivers/base/cpu.c

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -561,13 +561,20 @@ ssize_t __weak cpu_show_tsx_async_abort(struct device *dev,
561561
return sprintf(buf, "Not affected\n");
562562
}
563563

564+
ssize_t __weak cpu_show_itlb_multihit(struct device *dev,
565+
struct device_attribute *attr, char *buf)
566+
{
567+
return sprintf(buf, "Not affected\n");
568+
}
569+
564570
static DEVICE_ATTR(meltdown, 0444, cpu_show_meltdown, NULL);
565571
static DEVICE_ATTR(spectre_v1, 0444, cpu_show_spectre_v1, NULL);
566572
static DEVICE_ATTR(spectre_v2, 0444, cpu_show_spectre_v2, NULL);
567573
static DEVICE_ATTR(spec_store_bypass, 0444, cpu_show_spec_store_bypass, NULL);
568574
static DEVICE_ATTR(l1tf, 0444, cpu_show_l1tf, NULL);
569575
static DEVICE_ATTR(mds, 0444, cpu_show_mds, NULL);
570576
static DEVICE_ATTR(tsx_async_abort, 0444, cpu_show_tsx_async_abort, NULL);
577+
static DEVICE_ATTR(itlb_multihit, 0444, cpu_show_itlb_multihit, NULL);
571578

572579
static struct attribute *cpu_root_vulnerabilities_attrs[] = {
573580
&dev_attr_meltdown.attr,
@@ -577,6 +584,7 @@ static struct attribute *cpu_root_vulnerabilities_attrs[] = {
577584
&dev_attr_l1tf.attr,
578585
&dev_attr_mds.attr,
579586
&dev_attr_tsx_async_abort.attr,
587+
&dev_attr_itlb_multihit.attr,
580588
NULL
581589
};
582590

include/linux/cpu.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,8 @@ extern ssize_t cpu_show_mds(struct device *dev,
6262
extern ssize_t cpu_show_tsx_async_abort(struct device *dev,
6363
struct device_attribute *attr,
6464
char *buf);
65+
extern ssize_t cpu_show_itlb_multihit(struct device *dev,
66+
struct device_attribute *attr, char *buf);
6567

6668
extern __printf(4, 5)
6769
struct device *cpu_device_create(struct device *parent, void *drvdata,

0 commit comments

Comments
 (0)