|
@@ -27,9 +27,11 @@
|
|
|
#include <asm/pgtable.h>
|
|
|
#include <asm/set_memory.h>
|
|
|
#include <asm/intel-family.h>
|
|
|
+#include <asm/e820/api.h>
|
|
|
|
|
|
static void __init spectre_v2_select_mitigation(void);
|
|
|
static void __init ssb_select_mitigation(void);
|
|
|
+static void __init l1tf_select_mitigation(void);
|
|
|
|
|
|
/*
|
|
|
* Our boot-time value of the SPEC_CTRL MSR. We read it once so that any
|
|
@@ -81,6 +83,8 @@ void __init check_bugs(void)
|
|
|
*/
|
|
|
ssb_select_mitigation();
|
|
|
|
|
|
+ l1tf_select_mitigation();
|
|
|
+
|
|
|
#ifdef CONFIG_X86_32
|
|
|
/*
|
|
|
* Check whether we are able to run this kernel safely on SMP.
|
|
@@ -205,6 +209,32 @@ static void x86_amd_ssb_disable(void)
|
|
|
wrmsrl(MSR_AMD64_LS_CFG, msrval);
|
|
|
}
|
|
|
|
|
|
+static void __init l1tf_select_mitigation(void)
|
|
|
+{
|
|
|
+ u64 half_pa;
|
|
|
+
|
|
|
+ if (!boot_cpu_has_bug(X86_BUG_L1TF))
|
|
|
+ return;
|
|
|
+
|
|
|
+#if CONFIG_PGTABLE_LEVELS == 2
|
|
|
+ pr_warn("Kernel not compiled for PAE. No mitigation for L1TF\n");
|
|
|
+ return;
|
|
|
+#endif
|
|
|
+
|
|
|
+ /*
|
|
|
+ * This is extremely unlikely to happen because almost all
|
|
|
+ * systems have far more MAX_PA/2 than RAM can be fit into
|
|
|
+ * DIMM slots.
|
|
|
+ */
|
|
|
+ half_pa = (u64)l1tf_pfn_limit() << PAGE_SHIFT;
|
|
|
+ if (e820__mapped_any(half_pa, ULLONG_MAX - half_pa, E820_TYPE_RAM)) {
|
|
|
+ pr_warn("System has more than MAX_PA/2 memory. L1TF mitigation not effective.\n");
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ setup_force_cpu_cap(X86_FEATURE_L1TF_PTEINV);
|
|
|
+}
|
|
|
+
|
|
|
#ifdef RETPOLINE
|
|
|
static bool spectre_v2_bad_module;
|
|
|
|
|
@@ -678,6 +708,11 @@ static ssize_t cpu_show_common(struct device *dev, struct device_attribute *attr
|
|
|
case X86_BUG_SPEC_STORE_BYPASS:
|
|
|
return sprintf(buf, "%s\n", ssb_strings[ssb_mode]);
|
|
|
|
|
|
+ case X86_BUG_L1TF:
|
|
|
+ if (boot_cpu_has(X86_FEATURE_L1TF_PTEINV))
|
|
|
+ return sprintf(buf, "Mitigation: Page Table Inversion\n");
|
|
|
+ break;
|
|
|
+
|
|
|
default:
|
|
|
break;
|
|
|
}
|
|
@@ -704,4 +739,9 @@ ssize_t cpu_show_spec_store_bypass(struct device *dev, struct device_attribute *
|
|
|
{
|
|
|
return cpu_show_common(dev, attr, buf, X86_BUG_SPEC_STORE_BYPASS);
|
|
|
}
|
|
|
+
|
|
|
+ssize_t cpu_show_l1tf(struct device *dev, struct device_attribute *attr, char *buf)
|
|
|
+{
|
|
|
+ return cpu_show_common(dev, attr, buf, X86_BUG_L1TF);
|
|
|
+}
|
|
|
#endif
|