2019-10-20 13:32:35 +00:00
|
|
|
From: Pawan Gupta <pawan.kumar.gupta@linux.intel.com>
|
2019-10-24 21:48:50 +00:00
|
|
|
Date: Thu, 24 Oct 2019 18:34:26 +0200
|
2019-10-20 13:32:35 +00:00
|
|
|
Subject: x86: Add ITLB_MULTIHIT bug infrastructure
|
|
|
|
|
|
|
|
Some processors may incur a machine check error possibly
|
|
|
|
resulting in an unrecoverable cpu hang 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 [1].
|
|
|
|
|
|
|
|
This issue affects both bare-metal x86 page tables and EPT.
|
|
|
|
|
|
|
|
This 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.
|
|
|
|
|
|
|
|
[1] For example please refer to erratum SKL002 in "6th Generation
|
|
|
|
Intel Processor Family Specification Update"
|
|
|
|
https://www.intel.com/content/www/us/en/products/docs/processors/core/desktop-6th-gen-core-family-spec-update.html
|
|
|
|
https://www.google.com/search?q=site:intel.com+SKL002
|
|
|
|
|
|
|
|
There are a lot of other affected processors outside of Skylake and
|
|
|
|
that the erratum(referred above) does not fully disclose the issue
|
|
|
|
and the impact, both on Skylake and across all the affected CPUs.
|
|
|
|
|
|
|
|
Signed-off-by: Vineela Tummalapalli <vineela.tummalapalli@intel.com>
|
|
|
|
Co-developed-by: Pawan Gupta <pawan.kumar.gupta@linux.intel.com>
|
|
|
|
Signed-off-by: Pawan Gupta <pawan.kumar.gupta@linux.intel.com>
|
|
|
|
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
|
|
|
|
[bwh: Backported to 4.19:
|
|
|
|
- No support for X86_VENDOR_HYGON, ATOM_AIRMONT_NP
|
|
|
|
- Adjust context]
|
|
|
|
Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
|
|
|
|
---
|
|
|
|
.../ABI/testing/sysfs-devices-system-cpu | 1 +
|
|
|
|
arch/x86/include/asm/cpufeatures.h | 1 +
|
|
|
|
arch/x86/include/asm/msr-index.h | 7 ++
|
|
|
|
arch/x86/kernel/cpu/bugs.c | 13 ++++
|
|
|
|
arch/x86/kernel/cpu/common.c | 67 ++++++++++---------
|
|
|
|
drivers/base/cpu.c | 8 +++
|
|
|
|
include/linux/cpu.h | 2 +
|
|
|
|
7 files changed, 68 insertions(+), 31 deletions(-)
|
|
|
|
|
|
|
|
diff --git a/Documentation/ABI/testing/sysfs-devices-system-cpu b/Documentation/ABI/testing/sysfs-devices-system-cpu
|
|
|
|
index 8718d4ad227b..a0edcdc7c0b8 100644
|
|
|
|
--- a/Documentation/ABI/testing/sysfs-devices-system-cpu
|
|
|
|
+++ b/Documentation/ABI/testing/sysfs-devices-system-cpu
|
|
|
|
@@ -478,6 +478,7 @@ What: /sys/devices/system/cpu/vulnerabilities
|
|
|
|
/sys/devices/system/cpu/vulnerabilities/spec_store_bypass
|
|
|
|
/sys/devices/system/cpu/vulnerabilities/l1tf
|
|
|
|
/sys/devices/system/cpu/vulnerabilities/mds
|
|
|
|
+ /sys/devices/system/cpu/vulnerabilities/itlb_multihit
|
|
|
|
Date: January 2018
|
|
|
|
Contact: Linux kernel mailing list <linux-kernel@vger.kernel.org>
|
|
|
|
Description: Information about CPU vulnerabilities
|
|
|
|
diff --git a/arch/x86/include/asm/cpufeatures.h b/arch/x86/include/asm/cpufeatures.h
|
|
|
|
index 759f0a176612..ccad4f183400 100644
|
|
|
|
--- a/arch/x86/include/asm/cpufeatures.h
|
|
|
|
+++ b/arch/x86/include/asm/cpufeatures.h
|
|
|
|
@@ -389,5 +389,6 @@
|
|
|
|
#define X86_BUG_MDS X86_BUG(19) /* CPU is affected by Microarchitectural data sampling */
|
|
|
|
#define X86_BUG_MSBDS_ONLY X86_BUG(20) /* CPU is only affected by the MSDBS variant of BUG_MDS */
|
|
|
|
#define X86_BUG_SWAPGS X86_BUG(21) /* CPU is affected by speculation through SWAPGS */
|
|
|
|
+#define X86_BUG_ITLB_MULTIHIT X86_BUG(22) /* CPU may incur MCE during certain page attribute changes */
|
|
|
|
|
|
|
|
#endif /* _ASM_X86_CPUFEATURES_H */
|
|
|
|
diff --git a/arch/x86/include/asm/msr-index.h b/arch/x86/include/asm/msr-index.h
|
|
|
|
index a1d22e4428f6..f58e6921cbf7 100644
|
|
|
|
--- a/arch/x86/include/asm/msr-index.h
|
|
|
|
+++ b/arch/x86/include/asm/msr-index.h
|
|
|
|
@@ -84,6 +84,13 @@
|
|
|
|
* Microarchitectural Data
|
|
|
|
* Sampling (MDS) vulnerabilities.
|
|
|
|
*/
|
|
|
|
+#define ARCH_CAP_PSCHANGE_MC_NO BIT(6) /*
|
|
|
|
+ * The processor is not susceptible to a
|
|
|
|
+ * machine check error due to modifying the
|
|
|
|
+ * code page size along with either the
|
|
|
|
+ * physical address or cache type
|
|
|
|
+ * without TLB invalidation.
|
|
|
|
+ */
|
|
|
|
|
|
|
|
#define MSR_IA32_FLUSH_CMD 0x0000010b
|
|
|
|
#define L1D_FLUSH BIT(0) /*
|
|
|
|
diff --git a/arch/x86/kernel/cpu/bugs.c b/arch/x86/kernel/cpu/bugs.c
|
|
|
|
index ee7d17611ead..60e47e492c2f 100644
|
|
|
|
--- a/arch/x86/kernel/cpu/bugs.c
|
|
|
|
+++ b/arch/x86/kernel/cpu/bugs.c
|
|
|
|
@@ -1281,6 +1281,11 @@ static ssize_t l1tf_show_state(char *buf)
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
+static ssize_t itlb_multihit_show_state(char *buf)
|
|
|
|
+{
|
|
|
|
+ return sprintf(buf, "Processor vulnerable\n");
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
static ssize_t mds_show_state(char *buf)
|
|
|
|
{
|
|
|
|
if (boot_cpu_has(X86_FEATURE_HYPERVISOR)) {
|
|
|
|
@@ -1366,6 +1371,9 @@ static ssize_t cpu_show_common(struct device *dev, struct device_attribute *attr
|
|
|
|
case X86_BUG_MDS:
|
|
|
|
return mds_show_state(buf);
|
|
|
|
|
|
|
|
+ case X86_BUG_ITLB_MULTIHIT:
|
|
|
|
+ return itlb_multihit_show_state(buf);
|
|
|
|
+
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
@@ -1402,4 +1410,9 @@ ssize_t cpu_show_mds(struct device *dev, struct device_attribute *attr, char *bu
|
|
|
|
{
|
|
|
|
return cpu_show_common(dev, attr, buf, X86_BUG_MDS);
|
|
|
|
}
|
|
|
|
+
|
|
|
|
+ssize_t cpu_show_itlb_multihit(struct device *dev, struct device_attribute *attr, char *buf)
|
|
|
|
+{
|
|
|
|
+ return cpu_show_common(dev, attr, buf, X86_BUG_ITLB_MULTIHIT);
|
|
|
|
+}
|
|
|
|
#endif
|
|
|
|
diff --git a/arch/x86/kernel/cpu/common.c b/arch/x86/kernel/cpu/common.c
|
|
|
|
index b33fdfa0ff49..128808dccd2f 100644
|
|
|
|
--- a/arch/x86/kernel/cpu/common.c
|
|
|
|
+++ b/arch/x86/kernel/cpu/common.c
|
|
|
|
@@ -946,13 +946,14 @@ static void identify_cpu_without_cpuid(struct cpuinfo_x86 *c)
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
-#define NO_SPECULATION BIT(0)
|
|
|
|
-#define NO_MELTDOWN BIT(1)
|
|
|
|
-#define NO_SSB BIT(2)
|
|
|
|
-#define NO_L1TF BIT(3)
|
|
|
|
-#define NO_MDS BIT(4)
|
|
|
|
-#define MSBDS_ONLY BIT(5)
|
|
|
|
-#define NO_SWAPGS BIT(6)
|
|
|
|
+#define NO_SPECULATION BIT(0)
|
|
|
|
+#define NO_MELTDOWN BIT(1)
|
|
|
|
+#define NO_SSB BIT(2)
|
|
|
|
+#define NO_L1TF BIT(3)
|
|
|
|
+#define NO_MDS BIT(4)
|
|
|
|
+#define MSBDS_ONLY BIT(5)
|
|
|
|
+#define NO_SWAPGS BIT(6)
|
|
|
|
+#define NO_ITLB_MULTIHIT BIT(7)
|
|
|
|
|
|
|
|
#define VULNWL(_vendor, _family, _model, _whitelist) \
|
|
|
|
{ X86_VENDOR_##_vendor, _family, _model, X86_FEATURE_ANY, _whitelist }
|
|
|
|
@@ -970,26 +971,26 @@ static const __initconst struct x86_cpu_id cpu_vuln_whitelist[] = {
|
|
|
|
VULNWL(NSC, 5, X86_MODEL_ANY, NO_SPECULATION),
|
|
|
|
|
|
|
|
/* Intel Family 6 */
|
|
|
|
- VULNWL_INTEL(ATOM_SALTWELL, NO_SPECULATION),
|
|
|
|
- VULNWL_INTEL(ATOM_SALTWELL_TABLET, NO_SPECULATION),
|
|
|
|
- VULNWL_INTEL(ATOM_SALTWELL_MID, NO_SPECULATION),
|
|
|
|
- VULNWL_INTEL(ATOM_BONNELL, NO_SPECULATION),
|
|
|
|
- VULNWL_INTEL(ATOM_BONNELL_MID, NO_SPECULATION),
|
|
|
|
-
|
|
|
|
- VULNWL_INTEL(ATOM_SILVERMONT, NO_SSB | NO_L1TF | MSBDS_ONLY | NO_SWAPGS),
|
|
|
|
- VULNWL_INTEL(ATOM_SILVERMONT_X, NO_SSB | NO_L1TF | MSBDS_ONLY | NO_SWAPGS),
|
|
|
|
- VULNWL_INTEL(ATOM_SILVERMONT_MID, NO_SSB | NO_L1TF | MSBDS_ONLY | NO_SWAPGS),
|
|
|
|
- VULNWL_INTEL(ATOM_AIRMONT, NO_SSB | NO_L1TF | MSBDS_ONLY | NO_SWAPGS),
|
|
|
|
- VULNWL_INTEL(XEON_PHI_KNL, NO_SSB | NO_L1TF | MSBDS_ONLY | NO_SWAPGS),
|
|
|
|
- VULNWL_INTEL(XEON_PHI_KNM, NO_SSB | NO_L1TF | MSBDS_ONLY | NO_SWAPGS),
|
|
|
|
+ VULNWL_INTEL(ATOM_SALTWELL, NO_SPECULATION | NO_ITLB_MULTIHIT),
|
|
|
|
+ VULNWL_INTEL(ATOM_SALTWELL_TABLET, NO_SPECULATION | NO_ITLB_MULTIHIT),
|
|
|
|
+ VULNWL_INTEL(ATOM_SALTWELL_MID, NO_SPECULATION | NO_ITLB_MULTIHIT),
|
|
|
|
+ VULNWL_INTEL(ATOM_BONNELL, NO_SPECULATION | NO_ITLB_MULTIHIT),
|
|
|
|
+ VULNWL_INTEL(ATOM_BONNELL_MID, NO_SPECULATION | NO_ITLB_MULTIHIT),
|
|
|
|
+
|
|
|
|
+ VULNWL_INTEL(ATOM_SILVERMONT, NO_SSB | NO_L1TF | MSBDS_ONLY | NO_SWAPGS | NO_ITLB_MULTIHIT),
|
|
|
|
+ VULNWL_INTEL(ATOM_SILVERMONT_X, NO_SSB | NO_L1TF | MSBDS_ONLY | NO_SWAPGS | NO_ITLB_MULTIHIT),
|
|
|
|
+ VULNWL_INTEL(ATOM_SILVERMONT_MID, NO_SSB | NO_L1TF | MSBDS_ONLY | NO_SWAPGS | NO_ITLB_MULTIHIT),
|
|
|
|
+ VULNWL_INTEL(ATOM_AIRMONT, NO_SSB | NO_L1TF | MSBDS_ONLY | NO_SWAPGS | NO_ITLB_MULTIHIT),
|
|
|
|
+ VULNWL_INTEL(XEON_PHI_KNL, NO_SSB | NO_L1TF | MSBDS_ONLY | NO_SWAPGS | NO_ITLB_MULTIHIT),
|
|
|
|
+ VULNWL_INTEL(XEON_PHI_KNM, NO_SSB | NO_L1TF | MSBDS_ONLY | NO_SWAPGS | NO_ITLB_MULTIHIT),
|
|
|
|
|
|
|
|
VULNWL_INTEL(CORE_YONAH, NO_SSB),
|
|
|
|
|
|
|
|
- VULNWL_INTEL(ATOM_AIRMONT_MID, NO_L1TF | MSBDS_ONLY | NO_SWAPGS),
|
|
|
|
+ VULNWL_INTEL(ATOM_AIRMONT_MID, NO_L1TF | MSBDS_ONLY | NO_SWAPGS | NO_ITLB_MULTIHIT),
|
|
|
|
|
|
|
|
- VULNWL_INTEL(ATOM_GOLDMONT, NO_MDS | NO_L1TF | NO_SWAPGS),
|
|
|
|
- VULNWL_INTEL(ATOM_GOLDMONT_X, NO_MDS | NO_L1TF | NO_SWAPGS),
|
|
|
|
- VULNWL_INTEL(ATOM_GOLDMONT_PLUS, NO_MDS | NO_L1TF | NO_SWAPGS),
|
|
|
|
+ VULNWL_INTEL(ATOM_GOLDMONT, NO_MDS | NO_L1TF | NO_SWAPGS | NO_ITLB_MULTIHIT),
|
|
|
|
+ VULNWL_INTEL(ATOM_GOLDMONT_X, NO_MDS | NO_L1TF | NO_SWAPGS | NO_ITLB_MULTIHIT),
|
|
|
|
+ VULNWL_INTEL(ATOM_GOLDMONT_PLUS, NO_MDS | NO_L1TF | NO_SWAPGS | NO_ITLB_MULTIHIT),
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Technically, swapgs isn't serializing on AMD (despite it previously
|
|
|
|
@@ -1000,13 +1001,13 @@ static const __initconst struct x86_cpu_id cpu_vuln_whitelist[] = {
|
|
|
|
*/
|
|
|
|
|
|
|
|
/* AMD Family 0xf - 0x12 */
|
|
|
|
- VULNWL_AMD(0x0f, NO_MELTDOWN | NO_SSB | NO_L1TF | NO_MDS | NO_SWAPGS),
|
|
|
|
- VULNWL_AMD(0x10, NO_MELTDOWN | NO_SSB | NO_L1TF | NO_MDS | NO_SWAPGS),
|
|
|
|
- VULNWL_AMD(0x11, NO_MELTDOWN | NO_SSB | NO_L1TF | NO_MDS | NO_SWAPGS),
|
|
|
|
- VULNWL_AMD(0x12, NO_MELTDOWN | NO_SSB | NO_L1TF | NO_MDS | NO_SWAPGS),
|
|
|
|
+ VULNWL_AMD(0x0f, NO_MELTDOWN | NO_SSB | NO_L1TF | NO_MDS | NO_SWAPGS | NO_ITLB_MULTIHIT),
|
|
|
|
+ VULNWL_AMD(0x10, NO_MELTDOWN | NO_SSB | NO_L1TF | NO_MDS | NO_SWAPGS | NO_ITLB_MULTIHIT),
|
|
|
|
+ VULNWL_AMD(0x11, NO_MELTDOWN | NO_SSB | NO_L1TF | NO_MDS | NO_SWAPGS | NO_ITLB_MULTIHIT),
|
|
|
|
+ VULNWL_AMD(0x12, NO_MELTDOWN | NO_SSB | NO_L1TF | NO_MDS | NO_SWAPGS | NO_ITLB_MULTIHIT),
|
|
|
|
|
|
|
|
/* FAMILY_ANY must be last, otherwise 0x0f - 0x12 matches won't work */
|
|
|
|
- VULNWL_AMD(X86_FAMILY_ANY, NO_MELTDOWN | NO_L1TF | NO_MDS | NO_SWAPGS),
|
|
|
|
+ VULNWL_AMD(X86_FAMILY_ANY, NO_MELTDOWN | NO_L1TF | NO_MDS | NO_SWAPGS | NO_ITLB_MULTIHIT),
|
|
|
|
{}
|
|
|
|
};
|
|
|
|
|
|
|
|
@@ -1021,15 +1022,19 @@ static void __init cpu_set_bug_bits(struct cpuinfo_x86 *c)
|
|
|
|
{
|
|
|
|
u64 ia32_cap = 0;
|
|
|
|
|
|
|
|
+ if (cpu_has(c, X86_FEATURE_ARCH_CAPABILITIES))
|
|
|
|
+ rdmsrl(MSR_IA32_ARCH_CAPABILITIES, ia32_cap);
|
|
|
|
+
|
|
|
|
+ /* Set ITLB_MULTIHIT bug if cpu is not in the whitelist and not mitigated */
|
|
|
|
+ if (!cpu_matches(NO_ITLB_MULTIHIT) && !(ia32_cap & ARCH_CAP_PSCHANGE_MC_NO))
|
|
|
|
+ setup_force_cpu_bug(X86_BUG_ITLB_MULTIHIT);
|
|
|
|
+
|
|
|
|
if (cpu_matches(NO_SPECULATION))
|
|
|
|
return;
|
|
|
|
|
|
|
|
setup_force_cpu_bug(X86_BUG_SPECTRE_V1);
|
|
|
|
setup_force_cpu_bug(X86_BUG_SPECTRE_V2);
|
|
|
|
|
|
|
|
- if (cpu_has(c, X86_FEATURE_ARCH_CAPABILITIES))
|
|
|
|
- rdmsrl(MSR_IA32_ARCH_CAPABILITIES, ia32_cap);
|
|
|
|
-
|
|
|
|
if (!cpu_matches(NO_SSB) && !(ia32_cap & ARCH_CAP_SSB_NO) &&
|
|
|
|
!cpu_has(c, X86_FEATURE_AMD_SSB_NO))
|
|
|
|
setup_force_cpu_bug(X86_BUG_SPEC_STORE_BYPASS);
|
|
|
|
diff --git a/drivers/base/cpu.c b/drivers/base/cpu.c
|
|
|
|
index 2fd6ca1021c2..c21e2aec5cbb 100644
|
|
|
|
--- a/drivers/base/cpu.c
|
|
|
|
+++ b/drivers/base/cpu.c
|
|
|
|
@@ -552,12 +552,19 @@ ssize_t __weak cpu_show_mds(struct device *dev,
|
|
|
|
return sprintf(buf, "Not affected\n");
|
|
|
|
}
|
|
|
|
|
|
|
|
+ssize_t __weak cpu_show_itlb_multihit(struct device *dev,
|
|
|
|
+ struct device_attribute *attr, char *buf)
|
|
|
|
+{
|
|
|
|
+ return sprintf(buf, "Not affected\n");
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
static DEVICE_ATTR(meltdown, 0444, cpu_show_meltdown, NULL);
|
|
|
|
static DEVICE_ATTR(spectre_v1, 0444, cpu_show_spectre_v1, NULL);
|
|
|
|
static DEVICE_ATTR(spectre_v2, 0444, cpu_show_spectre_v2, NULL);
|
|
|
|
static DEVICE_ATTR(spec_store_bypass, 0444, cpu_show_spec_store_bypass, NULL);
|
|
|
|
static DEVICE_ATTR(l1tf, 0444, cpu_show_l1tf, NULL);
|
|
|
|
static DEVICE_ATTR(mds, 0444, cpu_show_mds, NULL);
|
|
|
|
+static DEVICE_ATTR(itlb_multihit, 0444, cpu_show_itlb_multihit, NULL);
|
|
|
|
|
|
|
|
static struct attribute *cpu_root_vulnerabilities_attrs[] = {
|
|
|
|
&dev_attr_meltdown.attr,
|
|
|
|
@@ -566,6 +573,7 @@ static struct attribute *cpu_root_vulnerabilities_attrs[] = {
|
|
|
|
&dev_attr_spec_store_bypass.attr,
|
|
|
|
&dev_attr_l1tf.attr,
|
|
|
|
&dev_attr_mds.attr,
|
|
|
|
+ &dev_attr_itlb_multihit.attr,
|
|
|
|
NULL
|
|
|
|
};
|
|
|
|
|
|
|
|
diff --git a/include/linux/cpu.h b/include/linux/cpu.h
|
|
|
|
index 006f69f9277b..7bb824b0f30e 100644
|
|
|
|
--- a/include/linux/cpu.h
|
|
|
|
+++ b/include/linux/cpu.h
|
|
|
|
@@ -59,6 +59,8 @@ extern ssize_t cpu_show_l1tf(struct device *dev,
|
|
|
|
struct device_attribute *attr, char *buf);
|
|
|
|
extern ssize_t cpu_show_mds(struct device *dev,
|
|
|
|
struct device_attribute *attr, char *buf);
|
|
|
|
+extern ssize_t cpu_show_itlb_multihit(struct device *dev,
|
|
|
|
+ struct device_attribute *attr, char *buf);
|
|
|
|
|
|
|
|
extern __printf(4, 5)
|
|
|
|
struct device *cpu_device_create(struct device *parent, void *drvdata,
|