Message ID | 42cd20f9e8dac363bcbc703fd7e861435a1cd782.1536336906.git.joseph.salisbury@canonical.com |
---|---|
State | New |
Headers | show |
Series | Fixes for LP:1788563 | expand |
On 09/10/2018 11:02 AM, Joseph Salisbury wrote: > From: Andi Kleen <ak@linux.intel.com> > > BugLink: https://bugs.launchpad.net/bugs/1789834 > > On Nehalem and newer core CPUs the CPU cache internally uses 44 bits > physical address space. The L1TF workaround is limited by this internal > cache address width, and needs to have one bit free there for the > mitigation to work. > > Older client systems report only 36bit physical address space so the range > check decides that L1TF is not mitigated for a 36bit phys/32GB system with > some memory holes. > > But since these actually have the larger internal cache width this warning > is bogus because it would only really be needed if the system had more than > 43bits of memory. > > Add a new internal x86_cache_bits field. Normally it is the same as the > physical bits field reported by CPUID, but for Nehalem and newerforce it to > be at least 44bits. > > Change the L1TF memory size warning to use the new cache_bits field to > avoid bogus warnings and remove the bogus comment about memory size. > > Fixes: 17dbca119312 ("x86/speculation/l1tf: Add sysfs reporting for l1tf") > Reported-by: George Anchev <studio@anchev.net> > Reported-by: Christopher Snowhill <kode54@gmail.com> > Signed-off-by: Andi Kleen <ak@linux.intel.com> > Signed-off-by: Thomas Gleixner <tglx@linutronix.de> > Cc: x86@kernel.org > Cc: linux-kernel@vger.kernel.org > Cc: Michael Hocko <mhocko@suse.com> > Cc: vbabka@suse.cz > Cc: stable@vger.kernel.org > Link: https://lkml.kernel.org/r/20180824170351.34874-1-andi@firstfloor.org > > (backported from commit cc51e5428ea54f575d49cfcede1d4cb3a72b4ec4) > Signed-off-by: Joseph Salisbury <joseph.salisbury@canonical.com> > --- > arch/x86/include/asm/processor.h | 4 +++- > arch/x86/kernel/cpu/bugs.c | 46 +++++++++++++++++++++++++++++++++++----- > 2 files changed, 44 insertions(+), 6 deletions(-) > > diff --git a/arch/x86/include/asm/processor.h b/arch/x86/include/asm/processor.h > index 8c770dd..49feba0 100644 > --- a/arch/x86/include/asm/processor.h > +++ b/arch/x86/include/asm/processor.h > @@ -132,6 +132,8 @@ struct cpuinfo_x86 { > /* Index into per_cpu list: */ > u16 cpu_index; > u32 microcode; > + /* Address space bits used by the cache internally */ > + u8 x86_cache_bits; > unsigned initialized : 1; > } __randomize_layout; > > @@ -183,7 +185,7 @@ extern void cpu_detect(struct cpuinfo_x86 *c); > > static inline unsigned long long l1tf_pfn_limit(void) > { > - return BIT_ULL(boot_cpu_data.x86_phys_bits - 1 - PAGE_SHIFT); > + return BIT_ULL(boot_cpu_data.x86_cache_bits - 1 - PAGE_SHIFT); > } > > extern void early_cpu_init(void); > diff --git a/arch/x86/kernel/cpu/bugs.c b/arch/x86/kernel/cpu/bugs.c > index edfc64a..df9e418 100644 > --- a/arch/x86/kernel/cpu/bugs.c > +++ b/arch/x86/kernel/cpu/bugs.c > @@ -653,6 +653,45 @@ enum vmx_l1d_flush_state l1tf_vmx_mitigation = VMENTER_L1D_FLUSH_AUTO; > EXPORT_SYMBOL_GPL(l1tf_vmx_mitigation); > #endif > > +/* > + * These CPUs all support 44bits physical address space internally in the > + * cache but CPUID can report a smaller number of physical address bits. > + * > + * The L1TF mitigation uses the top most address bit for the inversion of > + * non present PTEs. When the installed memory reaches into the top most > + * address bit due to memory holes, which has been observed on machines > + * which report 36bits physical address bits and have 32G RAM installed, > + * then the mitigation range check in l1tf_select_mitigation() triggers. > + * This is a false positive because the mitigation is still possible due to > + * the fact that the cache uses 44bit internally. Use the cache bits > + * instead of the reported physical bits and adjust them on the affected > + * machines to 44bit if the reported bits are less than 44. > + */ > +static void override_cache_bits(struct cpuinfo_x86 *c) > +{ > + if (c->x86 != 6) > + return; > + > + switch (c->x86_model) { > + case INTEL_FAM6_NEHALEM: > + case INTEL_FAM6_WESTMERE: > + case INTEL_FAM6_SANDYBRIDGE: > + case INTEL_FAM6_IVYBRIDGE: > + case INTEL_FAM6_HASWELL_CORE: > + case INTEL_FAM6_HASWELL_ULT: > + case INTEL_FAM6_HASWELL_GT3E: > + case INTEL_FAM6_BROADWELL_CORE: > + case INTEL_FAM6_BROADWELL_GT3E: > + case INTEL_FAM6_SKYLAKE_MOBILE: > + case INTEL_FAM6_SKYLAKE_DESKTOP: > + case INTEL_FAM6_KABYLAKE_MOBILE: > + case INTEL_FAM6_KABYLAKE_DESKTOP: > + if (c->x86_cache_bits < 44) > + c->x86_cache_bits = 44; This backport is incorrect because it drops the assignment of c->x86_cache_bits in get_cpu_address_sizes(). Without that assignment, c->x86_cache_bits is left uninitialized in all cases except when the CPU family is 6 and the model matches one of the ones listed above. Tyler > + break; > + } > +} > + > static void __init l1tf_select_mitigation(void) > { > u64 half_pa; > @@ -660,6 +699,8 @@ static void __init l1tf_select_mitigation(void) > if (!boot_cpu_has_bug(X86_BUG_L1TF)) > return; > > + override_cache_bits(&boot_cpu_data); > + > switch (l1tf_mitigation) { > case L1TF_MITIGATION_OFF: > case L1TF_MITIGATION_FLUSH_NOWARN: > @@ -679,11 +720,6 @@ static void __init l1tf_select_mitigation(void) > 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"); >
diff --git a/arch/x86/include/asm/processor.h b/arch/x86/include/asm/processor.h index 8c770dd..49feba0 100644 --- a/arch/x86/include/asm/processor.h +++ b/arch/x86/include/asm/processor.h @@ -132,6 +132,8 @@ struct cpuinfo_x86 { /* Index into per_cpu list: */ u16 cpu_index; u32 microcode; + /* Address space bits used by the cache internally */ + u8 x86_cache_bits; unsigned initialized : 1; } __randomize_layout; @@ -183,7 +185,7 @@ extern void cpu_detect(struct cpuinfo_x86 *c); static inline unsigned long long l1tf_pfn_limit(void) { - return BIT_ULL(boot_cpu_data.x86_phys_bits - 1 - PAGE_SHIFT); + return BIT_ULL(boot_cpu_data.x86_cache_bits - 1 - PAGE_SHIFT); } extern void early_cpu_init(void); diff --git a/arch/x86/kernel/cpu/bugs.c b/arch/x86/kernel/cpu/bugs.c index edfc64a..df9e418 100644 --- a/arch/x86/kernel/cpu/bugs.c +++ b/arch/x86/kernel/cpu/bugs.c @@ -653,6 +653,45 @@ enum vmx_l1d_flush_state l1tf_vmx_mitigation = VMENTER_L1D_FLUSH_AUTO; EXPORT_SYMBOL_GPL(l1tf_vmx_mitigation); #endif +/* + * These CPUs all support 44bits physical address space internally in the + * cache but CPUID can report a smaller number of physical address bits. + * + * The L1TF mitigation uses the top most address bit for the inversion of + * non present PTEs. When the installed memory reaches into the top most + * address bit due to memory holes, which has been observed on machines + * which report 36bits physical address bits and have 32G RAM installed, + * then the mitigation range check in l1tf_select_mitigation() triggers. + * This is a false positive because the mitigation is still possible due to + * the fact that the cache uses 44bit internally. Use the cache bits + * instead of the reported physical bits and adjust them on the affected + * machines to 44bit if the reported bits are less than 44. + */ +static void override_cache_bits(struct cpuinfo_x86 *c) +{ + if (c->x86 != 6) + return; + + switch (c->x86_model) { + case INTEL_FAM6_NEHALEM: + case INTEL_FAM6_WESTMERE: + case INTEL_FAM6_SANDYBRIDGE: + case INTEL_FAM6_IVYBRIDGE: + case INTEL_FAM6_HASWELL_CORE: + case INTEL_FAM6_HASWELL_ULT: + case INTEL_FAM6_HASWELL_GT3E: + case INTEL_FAM6_BROADWELL_CORE: + case INTEL_FAM6_BROADWELL_GT3E: + case INTEL_FAM6_SKYLAKE_MOBILE: + case INTEL_FAM6_SKYLAKE_DESKTOP: + case INTEL_FAM6_KABYLAKE_MOBILE: + case INTEL_FAM6_KABYLAKE_DESKTOP: + if (c->x86_cache_bits < 44) + c->x86_cache_bits = 44; + break; + } +} + static void __init l1tf_select_mitigation(void) { u64 half_pa; @@ -660,6 +699,8 @@ static void __init l1tf_select_mitigation(void) if (!boot_cpu_has_bug(X86_BUG_L1TF)) return; + override_cache_bits(&boot_cpu_data); + switch (l1tf_mitigation) { case L1TF_MITIGATION_OFF: case L1TF_MITIGATION_FLUSH_NOWARN: @@ -679,11 +720,6 @@ static void __init l1tf_select_mitigation(void) 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");