]> www.infradead.org Git - users/jedix/linux-maple.git/commitdiff
x86/speculation/l1tf: Add sysfs reporting for l1tf
authorAndi Klein <ak@linux.intel.com>
Wed, 13 Jun 2018 22:48:26 +0000 (15:48 -0700)
committerKonrad Rzeszutek Wilk <konrad.wilk@oracle.com>
Fri, 10 Aug 2018 22:56:32 +0000 (18:56 -0400)
L1TF core kernel workarounds are cheap and normally always enabled, However
they still should be reported in sysfs if the system is vulnerable or
mitigated. Add the necessary CPU feature/bug bits.

- Extend the existing checks for Meltdowns to determine if the system is
  vulnerable. All CPUs which are not vulnerable to Meltdown are also not
  vulnerable to L1TF

- Check for 32bit non PAE and emit a warning as there is no practical way
  for mitigation due to the limited physical address bits

- If the system has more than MAX_PA/2 physical memory the invert page
  workarounds don't protect the system against the L1TF attack anymore,
  because an inverted physical address will also point to valid
  memory. Print a warning in this case and report that the system is
  vulnerable.

Add a function which returns the PFN limit for the L1TF mitigation, which
will be used in follow up patches for sanity and range checks.

[ tglx: Renamed the CPU feature bit to L1TF_PTEINV ]

Signed-off-by: Andi Kleen <ak@linux.intel.com>
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Reviewed-by: Josh Poimboeuf <jpoimboe@redhat.com>
Acked-by: Dave Hansen <dave.hansen@intel.com>
Orabug: 28220674
CVE: CVE-2018-3620

(cherry picked from commit 17dbca119312b4e8173d4e25ff64262119fcef38)

Signed-off-by: Mihai Carabas <mihai.carabas@oracle.com>
Reviewed-by: Darren Kenny <darren.kenny@oracle.com>
Reviewed-by: Boris Ostrovsky <boris.ostrovsky@oracle.com>
Conflicts for UEK5:
arch/x86/include/asm/cpufeatures.h
arch/x86/kernel/cpu/bugs.c
[
cpufeatures.h: we do not have that entry free. use another
bugs.c: we have in place the ibrs logic, compared to upstream
]

Conflicts for UEK4:
arch/x86/include/asm/cpufeatures.h
arch/x86/kernel/cpu/bugs.c
arch/x86/kernel/cpu/common.c
cpufeatures.h: different file name and also moved the feature to word 2. We also removed word 2 as we won't use Transmeta on UEK4
bugs.c: different file name (bugs_64.c)
common.c: contextual (cpu_set_bug_bits didn't have __init)

arch/x86/include/asm/cpufeature.h
arch/x86/include/asm/processor.h
arch/x86/kernel/cpu/bugs_64.c
arch/x86/kernel/cpu/common.c
drivers/base/cpu.c
include/linux/cpu.h

index b69aec41b145a533a089348953b75df8ea68e78a..684f044c90b9f5b95c808e3de3f38dc04e681ecc 100644 (file)
 #define X86_FEATURE_3DNOWEXT   ( 1*32+30) /* AMD 3DNow! extensions */
 #define X86_FEATURE_3DNOW      ( 1*32+31) /* 3DNow! */
 
-/* Transmeta-defined CPU features, CPUID level 0x80860001, word 2 */
-#define X86_FEATURE_RECOVERY   ( 2*32+ 0) /* CPU in recovery mode */
-#define X86_FEATURE_LONGRUN    ( 2*32+ 1) /* Longrun power control */
-#define X86_FEATURE_LRTI       ( 2*32+ 3) /* LongRun table interface */
+/*
+ * Auxiliary flags completing word 6: Linux defined - For features scattered
+ * in various CPUID levels like 0x6, 0xA etc, word 2
+ */
+#define X86_FEATURE_L1TF_PTEINV                ( 2*32+0) /* "" L1TF workaround PTE inversion */
 
 /* Other features, Linux-defined mapping, word 3 */
 /* This range is used for feature bits which conflict or are synthesized */
 #define X86_BUG_SPECTRE_V1     X86_BUG(15) /* conditional branches */
 #define X86_BUG_SPECTRE_V2     X86_BUG(16) /* indirect branches */
 #define X86_BUG_SPEC_STORE_BYPASS      X86_BUG(17) /* CPU is affected by speculative store bypass attack */
+#define X86_BUG_L1TF                   X86_BUG(18) /* CPU is affected by L1 Terminal Fault */
 
 #if defined(__KERNEL__) && !defined(__ASSEMBLY__)
 
index 70fe9446390a5299284e0fc955c9f86358887b7c..5537d70cfdc6fa47402cd0c45eda9c0724cb64e5 100644 (file)
@@ -175,6 +175,11 @@ extern const struct seq_operations cpuinfo_op;
 extern void cpu_detect(struct cpuinfo_x86 *c);
 extern void fpu_detect(struct cpuinfo_x86 *c);
 
+static inline unsigned long l1tf_pfn_limit(void)
+{
+       return BIT(boot_cpu_data.x86_phys_bits - 1 - PAGE_SHIFT) - 1;
+}
+
 extern void early_cpu_init(void);
 extern void identify_boot_cpu(void);
 extern void identify_secondary_cpu(struct cpuinfo_x86 *);
index d83265ce5788d7cda0c964d4c1aef4dec8d6b110..55c99f1652e414d5d3b393280e546c12573bd38d 100644 (file)
@@ -21,6 +21,7 @@
 #include <asm/spec-ctrl.h>
 #include <asm/cmdline.h>
 #include <asm/intel-family.h>
+#include <asm/e820.h>
 
 /*
  * use_ibrs flags:
@@ -115,6 +116,7 @@ __setup("spectre_v2_heuristics=", spectre_v2_heuristics_setup);
 static void __init spectre_v2_select_mitigation(void);
 static void __init ssb_select_mitigation(void);
 static bool ssbd_ibrs_selected(void);
+static void __init l1tf_select_mitigation(void);
 
 /*
  * Our boot-time value of the SPEC_CTRL MSR. We read it once so that any
@@ -180,6 +182,8 @@ void __init check_bugs(void)
         */
        ssb_select_mitigation();
 
+       l1tf_select_mitigation();
+
        alternative_instructions();
 
        /*
@@ -350,6 +354,31 @@ static void x86_amd_ssbd_enable(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_any_mapped(half_pa, ULLONG_MAX - half_pa, E820_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);
+}
 
 /*
  * Disable retpoline and attempt to fall back to another Spectre v2 mitigation.
@@ -976,6 +1005,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;
        }
@@ -1006,4 +1040,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
index da39d7aeb51c66793a29c9e12e0d3fd055e12f3c..521c48e00c60f4c9401aa1cb4d9844101b05971d 100644 (file)
@@ -846,6 +846,21 @@ static const struct x86_cpu_id cpu_no_spec_store_bypass[] = {
        {}
 };
 
+static const __initconst struct x86_cpu_id cpu_no_l1tf[] = {
+       /* in addition to cpu_no_speculation */
+       { X86_VENDOR_INTEL,     6,      INTEL_FAM6_ATOM_SILVERMONT1     },
+       { X86_VENDOR_INTEL,     6,      INTEL_FAM6_ATOM_SILVERMONT2     },
+       { X86_VENDOR_INTEL,     6,      INTEL_FAM6_ATOM_AIRMONT         },
+       { X86_VENDOR_INTEL,     6,      INTEL_FAM6_ATOM_MERRIFIELD      },
+       { X86_VENDOR_INTEL,     6,      INTEL_FAM6_ATOM_MOOREFIELD      },
+       { X86_VENDOR_INTEL,     6,      INTEL_FAM6_ATOM_GOLDMONT        },
+       { X86_VENDOR_INTEL,     6,      INTEL_FAM6_ATOM_DENVERTON       },
+       { X86_VENDOR_INTEL,     6,      INTEL_FAM6_ATOM_GEMINI_LAKE     },
+       { X86_VENDOR_INTEL,     6,      INTEL_FAM6_XEON_PHI_KNL         },
+       { X86_VENDOR_INTEL,     6,      INTEL_FAM6_XEON_PHI_KNM         },
+       {}
+};
+
 static void cpu_set_bug_bits(struct cpuinfo_x86 *c)
 {
        u64 ia32_cap = 0;
@@ -874,6 +889,11 @@ static void cpu_set_bug_bits(struct cpuinfo_x86 *c)
                return;
 
        setup_force_cpu_bug(X86_BUG_CPU_MELTDOWN);
+
+       if (x86_match_cpu(cpu_no_l1tf))
+               return;
+
+       setup_force_cpu_bug(X86_BUG_L1TF);
 }
 
 /*
index fce3facc213104c54fbd7c598306aa3b9d07aa0e..e495e904c0261ac6d341019cb07f63afc2f37d37 100644 (file)
@@ -495,16 +495,24 @@ ssize_t __weak cpu_show_spec_store_bypass(struct device *dev,
        return sprintf(buf, "Not affected\n");
 }
 
+ssize_t __weak cpu_show_l1tf(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 struct attribute *cpu_root_vulnerabilities_attrs[] = {
        &dev_attr_meltdown.attr,
        &dev_attr_spectre_v1.attr,
        &dev_attr_spectre_v2.attr,
        &dev_attr_spec_store_bypass.attr,
+       &dev_attr_l1tf.attr,
        NULL
 };
 
index af76d70ebf454fc2388812d246290768e1d4f67b..39761736c177b068e1cfa42ae13018f832a8313d 100644 (file)
@@ -48,6 +48,8 @@ extern ssize_t cpu_show_spectre_v2(struct device *dev,
                                   struct device_attribute *attr, char *buf);
 extern ssize_t cpu_show_spec_store_bypass(struct device *dev,
                                          struct device_attribute *attr, char *buf);
+extern ssize_t cpu_show_l1tf(struct device *dev,
+                            struct device_attribute *attr, char *buf);
 
 extern struct device *cpu_device_create(struct device *parent, void *drvdata,
                                        const struct attribute_group **groups,