Skip to content

Commit 17dbca1

Browse files
Andi KleenKAGA-KOKO
authored andcommitted
x86/speculation/l1tf: Add sysfs reporting for l1tf
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>
1 parent 10a7041 commit 17dbca1

File tree

6 files changed

+77
-0
lines changed

6 files changed

+77
-0
lines changed

arch/x86/include/asm/cpufeatures.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -219,6 +219,7 @@
219219
#define X86_FEATURE_IBPB ( 7*32+26) /* Indirect Branch Prediction Barrier */
220220
#define X86_FEATURE_STIBP ( 7*32+27) /* Single Thread Indirect Branch Predictors */
221221
#define X86_FEATURE_ZEN ( 7*32+28) /* "" CPU is AMD family 0x17 (Zen) */
222+
#define X86_FEATURE_L1TF_PTEINV ( 7*32+29) /* "" L1TF workaround PTE inversion */
222223

223224
/* Virtualization flags: Linux defined, word 8 */
224225
#define X86_FEATURE_TPR_SHADOW ( 8*32+ 0) /* Intel TPR Shadow */
@@ -373,5 +374,6 @@
373374
#define X86_BUG_SPECTRE_V1 X86_BUG(15) /* CPU is affected by Spectre variant 1 attack with conditional branches */
374375
#define X86_BUG_SPECTRE_V2 X86_BUG(16) /* CPU is affected by Spectre variant 2 attack with indirect branches */
375376
#define X86_BUG_SPEC_STORE_BYPASS X86_BUG(17) /* CPU is affected by speculative store bypass attack */
377+
#define X86_BUG_L1TF X86_BUG(18) /* CPU is affected by L1 Terminal Fault */
376378

377379
#endif /* _ASM_X86_CPUFEATURES_H */

arch/x86/include/asm/processor.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -181,6 +181,11 @@ extern const struct seq_operations cpuinfo_op;
181181

182182
extern void cpu_detect(struct cpuinfo_x86 *c);
183183

184+
static inline unsigned long l1tf_pfn_limit(void)
185+
{
186+
return BIT(boot_cpu_data.x86_phys_bits - 1 - PAGE_SHIFT) - 1;
187+
}
188+
184189
extern void early_cpu_init(void);
185190
extern void identify_boot_cpu(void);
186191
extern void identify_secondary_cpu(struct cpuinfo_x86 *);

arch/x86/kernel/cpu/bugs.c

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,9 +27,11 @@
2727
#include <asm/pgtable.h>
2828
#include <asm/set_memory.h>
2929
#include <asm/intel-family.h>
30+
#include <asm/e820/api.h>
3031

3132
static void __init spectre_v2_select_mitigation(void);
3233
static void __init ssb_select_mitigation(void);
34+
static void __init l1tf_select_mitigation(void);
3335

3436
/*
3537
* 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)
8183
*/
8284
ssb_select_mitigation();
8385

86+
l1tf_select_mitigation();
87+
8488
#ifdef CONFIG_X86_32
8589
/*
8690
* Check whether we are able to run this kernel safely on SMP.
@@ -205,6 +209,32 @@ static void x86_amd_ssb_disable(void)
205209
wrmsrl(MSR_AMD64_LS_CFG, msrval);
206210
}
207211

212+
static void __init l1tf_select_mitigation(void)
213+
{
214+
u64 half_pa;
215+
216+
if (!boot_cpu_has_bug(X86_BUG_L1TF))
217+
return;
218+
219+
#if CONFIG_PGTABLE_LEVELS == 2
220+
pr_warn("Kernel not compiled for PAE. No mitigation for L1TF\n");
221+
return;
222+
#endif
223+
224+
/*
225+
* This is extremely unlikely to happen because almost all
226+
* systems have far more MAX_PA/2 than RAM can be fit into
227+
* DIMM slots.
228+
*/
229+
half_pa = (u64)l1tf_pfn_limit() << PAGE_SHIFT;
230+
if (e820__mapped_any(half_pa, ULLONG_MAX - half_pa, E820_TYPE_RAM)) {
231+
pr_warn("System has more than MAX_PA/2 memory. L1TF mitigation not effective.\n");
232+
return;
233+
}
234+
235+
setup_force_cpu_cap(X86_FEATURE_L1TF_PTEINV);
236+
}
237+
208238
#ifdef RETPOLINE
209239
static bool spectre_v2_bad_module;
210240

@@ -678,6 +708,11 @@ static ssize_t cpu_show_common(struct device *dev, struct device_attribute *attr
678708
case X86_BUG_SPEC_STORE_BYPASS:
679709
return sprintf(buf, "%s\n", ssb_strings[ssb_mode]);
680710

711+
case X86_BUG_L1TF:
712+
if (boot_cpu_has(X86_FEATURE_L1TF_PTEINV))
713+
return sprintf(buf, "Mitigation: Page Table Inversion\n");
714+
break;
715+
681716
default:
682717
break;
683718
}
@@ -704,4 +739,9 @@ ssize_t cpu_show_spec_store_bypass(struct device *dev, struct device_attribute *
704739
{
705740
return cpu_show_common(dev, attr, buf, X86_BUG_SPEC_STORE_BYPASS);
706741
}
742+
743+
ssize_t cpu_show_l1tf(struct device *dev, struct device_attribute *attr, char *buf)
744+
{
745+
return cpu_show_common(dev, attr, buf, X86_BUG_L1TF);
746+
}
707747
#endif

arch/x86/kernel/cpu/common.c

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -984,6 +984,21 @@ static const __initconst struct x86_cpu_id cpu_no_spec_store_bypass[] = {
984984
{}
985985
};
986986

987+
static const __initconst struct x86_cpu_id cpu_no_l1tf[] = {
988+
/* in addition to cpu_no_speculation */
989+
{ X86_VENDOR_INTEL, 6, INTEL_FAM6_ATOM_SILVERMONT1 },
990+
{ X86_VENDOR_INTEL, 6, INTEL_FAM6_ATOM_SILVERMONT2 },
991+
{ X86_VENDOR_INTEL, 6, INTEL_FAM6_ATOM_AIRMONT },
992+
{ X86_VENDOR_INTEL, 6, INTEL_FAM6_ATOM_MERRIFIELD },
993+
{ X86_VENDOR_INTEL, 6, INTEL_FAM6_ATOM_MOOREFIELD },
994+
{ X86_VENDOR_INTEL, 6, INTEL_FAM6_ATOM_GOLDMONT },
995+
{ X86_VENDOR_INTEL, 6, INTEL_FAM6_ATOM_DENVERTON },
996+
{ X86_VENDOR_INTEL, 6, INTEL_FAM6_ATOM_GEMINI_LAKE },
997+
{ X86_VENDOR_INTEL, 6, INTEL_FAM6_XEON_PHI_KNL },
998+
{ X86_VENDOR_INTEL, 6, INTEL_FAM6_XEON_PHI_KNM },
999+
{}
1000+
};
1001+
9871002
static void __init cpu_set_bug_bits(struct cpuinfo_x86 *c)
9881003
{
9891004
u64 ia32_cap = 0;
@@ -1010,6 +1025,11 @@ static void __init cpu_set_bug_bits(struct cpuinfo_x86 *c)
10101025
return;
10111026

10121027
setup_force_cpu_bug(X86_BUG_CPU_MELTDOWN);
1028+
1029+
if (x86_match_cpu(cpu_no_l1tf))
1030+
return;
1031+
1032+
setup_force_cpu_bug(X86_BUG_L1TF);
10131033
}
10141034

10151035
/*

drivers/base/cpu.c

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -540,16 +540,24 @@ ssize_t __weak cpu_show_spec_store_bypass(struct device *dev,
540540
return sprintf(buf, "Not affected\n");
541541
}
542542

543+
ssize_t __weak cpu_show_l1tf(struct device *dev,
544+
struct device_attribute *attr, char *buf)
545+
{
546+
return sprintf(buf, "Not affected\n");
547+
}
548+
543549
static DEVICE_ATTR(meltdown, 0444, cpu_show_meltdown, NULL);
544550
static DEVICE_ATTR(spectre_v1, 0444, cpu_show_spectre_v1, NULL);
545551
static DEVICE_ATTR(spectre_v2, 0444, cpu_show_spectre_v2, NULL);
546552
static DEVICE_ATTR(spec_store_bypass, 0444, cpu_show_spec_store_bypass, NULL);
553+
static DEVICE_ATTR(l1tf, 0444, cpu_show_l1tf, NULL);
547554

548555
static struct attribute *cpu_root_vulnerabilities_attrs[] = {
549556
&dev_attr_meltdown.attr,
550557
&dev_attr_spectre_v1.attr,
551558
&dev_attr_spectre_v2.attr,
552559
&dev_attr_spec_store_bypass.attr,
560+
&dev_attr_l1tf.attr,
553561
NULL
554562
};
555563

include/linux/cpu.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,8 @@ extern ssize_t cpu_show_spectre_v2(struct device *dev,
5555
struct device_attribute *attr, char *buf);
5656
extern ssize_t cpu_show_spec_store_bypass(struct device *dev,
5757
struct device_attribute *attr, char *buf);
58+
extern ssize_t cpu_show_l1tf(struct device *dev,
59+
struct device_attribute *attr, char *buf);
5860

5961
extern __printf(4, 5)
6062
struct device *cpu_device_create(struct device *parent, void *drvdata,

0 commit comments

Comments
 (0)