mirror of
https://github.com/torvalds/linux.git
synced 2024-11-24 05:02:12 +00:00
x86/mm: Disallow running with 32-bit PTEs to work around erratum
The Intel(R) Xeon Phi(TM) Processor x200 Family (codename: Knights Landing) has an erratum where a processor thread setting the Accessed or Dirty bits may not do so atomically against its checks for the Present bit. This may cause a thread (which is about to page fault) to set A and/or D, even though the Present bit had already been atomically cleared. These bits are truly "stray". In the case of the Dirty bit, the thread associated with the stray set was *not* allowed to write to the page. This means that we do not have to launder the bit(s); we can simply ignore them. If the PTE is used for storing a swap index or a NUMA migration index, the A bit could be misinterpreted as part of the swap type. The stray bits being set cause a software-cleared PTE to be interpreted as a swap entry. In some cases (like when the swap index ends up being for a non-existent swapfile), the kernel detects the stray value and WARN()s about it, but there is no guarantee that the kernel can always detect it. When we have 64-bit PTEs (64-bit mode or 32-bit PAE), we were able to move the swap PTE format around to avoid these troublesome bits. But, 32-bit non-PAE is tight on bits. So, disallow it from running on this hardware. I can't imagine anyone wanting to run 32-bit non-highmem kernels on this hardware, but disallowing them from running entirely is surely the safe thing to do. Signed-off-by: Dave Hansen <dave.hansen@linux.intel.com> Cc: Andrew Morton <akpm@linux-foundation.org> Cc: Andy Lutomirski <luto@kernel.org> Cc: Borislav Petkov <bp@alien8.de> Cc: Brian Gerst <brgerst@gmail.com> Cc: Dave Hansen <dave@sr71.net> Cc: Denys Vlasenko <dvlasenk@redhat.com> Cc: H. Peter Anvin <hpa@zytor.com> Cc: Josh Poimboeuf <jpoimboe@redhat.com> Cc: Linus Torvalds <torvalds@linux-foundation.org> Cc: Luis R. Rodriguez <mcgrof@suse.com> Cc: Peter Zijlstra <peterz@infradead.org> Cc: Thomas Gleixner <tglx@linutronix.de> Cc: Toshi Kani <toshi.kani@hp.com> Cc: dave.hansen@intel.com Cc: linux-mm@kvack.org Cc: mhocko@suse.com Link: http://lkml.kernel.org/r/20160708001914.D0B50110@viggo.jf.intel.com Signed-off-by: Ingo Molnar <mingo@kernel.org>
This commit is contained in:
parent
97e3c602cc
commit
e4a84be6f0
@ -294,6 +294,7 @@ static inline int cmdline_find_option_bool(const char *option)
|
||||
|
||||
/* cpu.c, cpucheck.c */
|
||||
int check_cpu(int *cpu_level_ptr, int *req_level_ptr, u32 **err_flags_ptr);
|
||||
int check_knl_erratum(void);
|
||||
int validate_cpu(void);
|
||||
|
||||
/* early_serial_console.c */
|
||||
|
@ -93,6 +93,8 @@ int validate_cpu(void)
|
||||
show_cap_strs(err_flags);
|
||||
putchar('\n');
|
||||
return -1;
|
||||
} else if (check_knl_erratum()) {
|
||||
return -1;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
|
@ -24,6 +24,7 @@
|
||||
# include "boot.h"
|
||||
#endif
|
||||
#include <linux/types.h>
|
||||
#include <asm/intel-family.h>
|
||||
#include <asm/processor-flags.h>
|
||||
#include <asm/required-features.h>
|
||||
#include <asm/msr-index.h>
|
||||
@ -175,6 +176,8 @@ int check_cpu(int *cpu_level_ptr, int *req_level_ptr, u32 **err_flags_ptr)
|
||||
puts("WARNING: PAE disabled. Use parameter 'forcepae' to enable at your own risk!\n");
|
||||
}
|
||||
}
|
||||
if (!err)
|
||||
err = check_knl_erratum();
|
||||
|
||||
if (err_flags_ptr)
|
||||
*err_flags_ptr = err ? err_flags : NULL;
|
||||
@ -185,3 +188,33 @@ int check_cpu(int *cpu_level_ptr, int *req_level_ptr, u32 **err_flags_ptr)
|
||||
|
||||
return (cpu.level < req_level || err) ? -1 : 0;
|
||||
}
|
||||
|
||||
int check_knl_erratum(void)
|
||||
{
|
||||
/*
|
||||
* First check for the affected model/family:
|
||||
*/
|
||||
if (!is_intel() ||
|
||||
cpu.family != 6 ||
|
||||
cpu.model != INTEL_FAM6_XEON_PHI_KNL)
|
||||
return 0;
|
||||
|
||||
/*
|
||||
* This erratum affects the Accessed/Dirty bits, and can
|
||||
* cause stray bits to be set in !Present PTEs. We have
|
||||
* enough bits in our 64-bit PTEs (which we have on real
|
||||
* 64-bit mode or PAE) to avoid using these troublesome
|
||||
* bits. But, we do not have enough space in our 32-bit
|
||||
* PTEs. So, refuse to run on 32-bit non-PAE kernels.
|
||||
*/
|
||||
if (IS_ENABLED(CONFIG_X86_64) || IS_ENABLED(CONFIG_X86_PAE))
|
||||
return 0;
|
||||
|
||||
puts("This 32-bit kernel can not run on this Xeon Phi x200\n"
|
||||
"processor due to a processor erratum. Use a 64-bit\n"
|
||||
"kernel, or enable PAE in this 32-bit kernel.\n\n");
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
|
@ -102,6 +102,7 @@ void get_cpuflags(void)
|
||||
cpuid(0x1, &tfms, &ignored, &cpu.flags[4],
|
||||
&cpu.flags[0]);
|
||||
cpu.level = (tfms >> 8) & 15;
|
||||
cpu.family = cpu.level;
|
||||
cpu.model = (tfms >> 4) & 15;
|
||||
if (cpu.level >= 6)
|
||||
cpu.model += ((tfms >> 16) & 0xf) << 4;
|
||||
|
@ -6,6 +6,7 @@
|
||||
|
||||
struct cpu_features {
|
||||
int level; /* Family, or 64 for x86-64 */
|
||||
int family; /* Family, always */
|
||||
int model;
|
||||
u32 flags[NCAPINTS];
|
||||
};
|
||||
|
Loading…
Reference in New Issue
Block a user