aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86/boot
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2016-07-25 18:34:18 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2016-07-25 18:34:18 -0400
commit0f657262d5f99ad86b9a63fb5dcd29036c2ed916 (patch)
tree54b83052c019bc1dff662cb1b38cbff59d901535 /arch/x86/boot
parent425dbc6db34dbd679cab1a17135c5910b271a03d (diff)
parent55920d31f1e3fea06702c74271dd56c4fc9b70ca (diff)
Merge branch 'x86-mm-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip
Pull x86 mm updates from Ingo Molnar: "Various x86 low level modifications: - preparatory work to support virtually mapped kernel stacks (Andy Lutomirski) - support for 64-bit __get_user() on 32-bit kernels (Benjamin LaHaise) - (involved) workaround for Knights Landing CPU erratum (Dave Hansen) - MPX enhancements (Dave Hansen) - mremap() extension to allow remapping of the special VDSO vma, for purposes of user level context save/restore (Dmitry Safonov) - hweight and entry code cleanups (Borislav Petkov) - bitops code generation optimizations and cleanups with modern GCC (H. Peter Anvin) - syscall entry code optimizations (Paolo Bonzini)" * 'x86-mm-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip: (43 commits) x86/mm/cpa: Add missing comment in populate_pdg() x86/mm/cpa: Fix populate_pgd(): Stop trying to deallocate failed PUDs x86/syscalls: Add compat_sys_preadv64v2/compat_sys_pwritev64v2 x86/smp: Remove unnecessary initialization of thread_info::cpu x86/smp: Remove stack_smp_processor_id() x86/uaccess: Move thread_info::addr_limit to thread_struct x86/dumpstack: Rename thread_struct::sig_on_uaccess_error to sig_on_uaccess_err x86/uaccess: Move thread_info::uaccess_err and thread_info::sig_on_uaccess_err to thread_struct x86/dumpstack: When OOPSing, rewind the stack before do_exit() x86/mm/64: In vmalloc_fault(), use CR3 instead of current->active_mm x86/dumpstack/64: Handle faults when printing the "Stack: " part of an OOPS x86/dumpstack: Try harder to get a call trace on stack overflow x86/mm: Remove kernel_unmap_pages_in_pgd() and efi_cleanup_page_tables() x86/mm/cpa: In populate_pgd(), don't set the PGD entry until it's populated x86/mm/hotplug: Don't remove PGD entries in remove_pagetable() x86/mm: Use pte_none() to test for empty PTE x86/mm: Disallow running with 32-bit PTEs to work around erratum x86/mm: Ignore A/D bits in pte/pmd/pud_none() x86/mm: Move swap offset/type up in PTE to work around erratum x86/entry: Inline enter_from_user_mode() ...
Diffstat (limited to 'arch/x86/boot')
-rw-r--r--arch/x86/boot/bitops.h8
-rw-r--r--arch/x86/boot/boot.h18
-rw-r--r--arch/x86/boot/cpu.c2
-rw-r--r--arch/x86/boot/cpucheck.c33
-rw-r--r--arch/x86/boot/cpuflags.c1
-rw-r--r--arch/x86/boot/cpuflags.h1
-rw-r--r--arch/x86/boot/string.c2
7 files changed, 53 insertions, 12 deletions
diff --git a/arch/x86/boot/bitops.h b/arch/x86/boot/bitops.h
index 878e4b9940d9..0d41d68131cc 100644
--- a/arch/x86/boot/bitops.h
+++ b/arch/x86/boot/bitops.h
@@ -16,14 +16,16 @@
16#define BOOT_BITOPS_H 16#define BOOT_BITOPS_H
17#define _LINUX_BITOPS_H /* Inhibit inclusion of <linux/bitops.h> */ 17#define _LINUX_BITOPS_H /* Inhibit inclusion of <linux/bitops.h> */
18 18
19static inline int constant_test_bit(int nr, const void *addr) 19#include <linux/types.h>
20
21static inline bool constant_test_bit(int nr, const void *addr)
20{ 22{
21 const u32 *p = (const u32 *)addr; 23 const u32 *p = (const u32 *)addr;
22 return ((1UL << (nr & 31)) & (p[nr >> 5])) != 0; 24 return ((1UL << (nr & 31)) & (p[nr >> 5])) != 0;
23} 25}
24static inline int variable_test_bit(int nr, const void *addr) 26static inline bool variable_test_bit(int nr, const void *addr)
25{ 27{
26 u8 v; 28 bool v;
27 const u32 *p = (const u32 *)addr; 29 const u32 *p = (const u32 *)addr;
28 30
29 asm("btl %2,%1; setc %0" : "=qm" (v) : "m" (*p), "Ir" (nr)); 31 asm("btl %2,%1; setc %0" : "=qm" (v) : "m" (*p), "Ir" (nr));
diff --git a/arch/x86/boot/boot.h b/arch/x86/boot/boot.h
index 9011a88353de..e5612f3e3b57 100644
--- a/arch/x86/boot/boot.h
+++ b/arch/x86/boot/boot.h
@@ -24,6 +24,7 @@
24#include <linux/types.h> 24#include <linux/types.h>
25#include <linux/edd.h> 25#include <linux/edd.h>
26#include <asm/setup.h> 26#include <asm/setup.h>
27#include <asm/asm.h>
27#include "bitops.h" 28#include "bitops.h"
28#include "ctype.h" 29#include "ctype.h"
29#include "cpuflags.h" 30#include "cpuflags.h"
@@ -176,18 +177,18 @@ static inline void wrgs32(u32 v, addr_t addr)
176} 177}
177 178
178/* Note: these only return true/false, not a signed return value! */ 179/* Note: these only return true/false, not a signed return value! */
179static inline int memcmp_fs(const void *s1, addr_t s2, size_t len) 180static inline bool memcmp_fs(const void *s1, addr_t s2, size_t len)
180{ 181{
181 u8 diff; 182 bool diff;
182 asm volatile("fs; repe; cmpsb; setnz %0" 183 asm volatile("fs; repe; cmpsb" CC_SET(nz)
183 : "=qm" (diff), "+D" (s1), "+S" (s2), "+c" (len)); 184 : CC_OUT(nz) (diff), "+D" (s1), "+S" (s2), "+c" (len));
184 return diff; 185 return diff;
185} 186}
186static inline int memcmp_gs(const void *s1, addr_t s2, size_t len) 187static inline bool memcmp_gs(const void *s1, addr_t s2, size_t len)
187{ 188{
188 u8 diff; 189 bool diff;
189 asm volatile("gs; repe; cmpsb; setnz %0" 190 asm volatile("gs; repe; cmpsb" CC_SET(nz)
190 : "=qm" (diff), "+D" (s1), "+S" (s2), "+c" (len)); 191 : CC_OUT(nz) (diff), "+D" (s1), "+S" (s2), "+c" (len));
191 return diff; 192 return diff;
192} 193}
193 194
@@ -294,6 +295,7 @@ static inline int cmdline_find_option_bool(const char *option)
294 295
295/* cpu.c, cpucheck.c */ 296/* cpu.c, cpucheck.c */
296int check_cpu(int *cpu_level_ptr, int *req_level_ptr, u32 **err_flags_ptr); 297int check_cpu(int *cpu_level_ptr, int *req_level_ptr, u32 **err_flags_ptr);
298int check_knl_erratum(void);
297int validate_cpu(void); 299int validate_cpu(void);
298 300
299/* early_serial_console.c */ 301/* early_serial_console.c */
diff --git a/arch/x86/boot/cpu.c b/arch/x86/boot/cpu.c
index 29207f69ae8c..26240dde081e 100644
--- a/arch/x86/boot/cpu.c
+++ b/arch/x86/boot/cpu.c
@@ -93,6 +93,8 @@ int validate_cpu(void)
93 show_cap_strs(err_flags); 93 show_cap_strs(err_flags);
94 putchar('\n'); 94 putchar('\n');
95 return -1; 95 return -1;
96 } else if (check_knl_erratum()) {
97 return -1;
96 } else { 98 } else {
97 return 0; 99 return 0;
98 } 100 }
diff --git a/arch/x86/boot/cpucheck.c b/arch/x86/boot/cpucheck.c
index 1fd7d575092e..4ad7d70e8739 100644
--- a/arch/x86/boot/cpucheck.c
+++ b/arch/x86/boot/cpucheck.c
@@ -24,6 +24,7 @@
24# include "boot.h" 24# include "boot.h"
25#endif 25#endif
26#include <linux/types.h> 26#include <linux/types.h>
27#include <asm/intel-family.h>
27#include <asm/processor-flags.h> 28#include <asm/processor-flags.h>
28#include <asm/required-features.h> 29#include <asm/required-features.h>
29#include <asm/msr-index.h> 30#include <asm/msr-index.h>
@@ -175,6 +176,8 @@ int check_cpu(int *cpu_level_ptr, int *req_level_ptr, u32 **err_flags_ptr)
175 puts("WARNING: PAE disabled. Use parameter 'forcepae' to enable at your own risk!\n"); 176 puts("WARNING: PAE disabled. Use parameter 'forcepae' to enable at your own risk!\n");
176 } 177 }
177 } 178 }
179 if (!err)
180 err = check_knl_erratum();
178 181
179 if (err_flags_ptr) 182 if (err_flags_ptr)
180 *err_flags_ptr = err ? err_flags : NULL; 183 *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)
185 188
186 return (cpu.level < req_level || err) ? -1 : 0; 189 return (cpu.level < req_level || err) ? -1 : 0;
187} 190}
191
192int check_knl_erratum(void)
193{
194 /*
195 * First check for the affected model/family:
196 */
197 if (!is_intel() ||
198 cpu.family != 6 ||
199 cpu.model != INTEL_FAM6_XEON_PHI_KNL)
200 return 0;
201
202 /*
203 * This erratum affects the Accessed/Dirty bits, and can
204 * cause stray bits to be set in !Present PTEs. We have
205 * enough bits in our 64-bit PTEs (which we have on real
206 * 64-bit mode or PAE) to avoid using these troublesome
207 * bits. But, we do not have enough space in our 32-bit
208 * PTEs. So, refuse to run on 32-bit non-PAE kernels.
209 */
210 if (IS_ENABLED(CONFIG_X86_64) || IS_ENABLED(CONFIG_X86_PAE))
211 return 0;
212
213 puts("This 32-bit kernel can not run on this Xeon Phi x200\n"
214 "processor due to a processor erratum. Use a 64-bit\n"
215 "kernel, or enable PAE in this 32-bit kernel.\n\n");
216
217 return -1;
218}
219
220
diff --git a/arch/x86/boot/cpuflags.c b/arch/x86/boot/cpuflags.c
index 431fa5f84537..6687ab953257 100644
--- a/arch/x86/boot/cpuflags.c
+++ b/arch/x86/boot/cpuflags.c
@@ -102,6 +102,7 @@ void get_cpuflags(void)
102 cpuid(0x1, &tfms, &ignored, &cpu.flags[4], 102 cpuid(0x1, &tfms, &ignored, &cpu.flags[4],
103 &cpu.flags[0]); 103 &cpu.flags[0]);
104 cpu.level = (tfms >> 8) & 15; 104 cpu.level = (tfms >> 8) & 15;
105 cpu.family = cpu.level;
105 cpu.model = (tfms >> 4) & 15; 106 cpu.model = (tfms >> 4) & 15;
106 if (cpu.level >= 6) 107 if (cpu.level >= 6)
107 cpu.model += ((tfms >> 16) & 0xf) << 4; 108 cpu.model += ((tfms >> 16) & 0xf) << 4;
diff --git a/arch/x86/boot/cpuflags.h b/arch/x86/boot/cpuflags.h
index 4cb404fd45ce..15ad56a3f905 100644
--- a/arch/x86/boot/cpuflags.h
+++ b/arch/x86/boot/cpuflags.h
@@ -6,6 +6,7 @@
6 6
7struct cpu_features { 7struct cpu_features {
8 int level; /* Family, or 64 for x86-64 */ 8 int level; /* Family, or 64 for x86-64 */
9 int family; /* Family, always */
9 int model; 10 int model;
10 u32 flags[NCAPINTS]; 11 u32 flags[NCAPINTS];
11}; 12};
diff --git a/arch/x86/boot/string.c b/arch/x86/boot/string.c
index 318b8465d302..cc3bd583dce1 100644
--- a/arch/x86/boot/string.c
+++ b/arch/x86/boot/string.c
@@ -17,7 +17,7 @@
17 17
18int memcmp(const void *s1, const void *s2, size_t len) 18int memcmp(const void *s1, const void *s2, size_t len)
19{ 19{
20 u8 diff; 20 bool diff;
21 asm("repe; cmpsb; setnz %0" 21 asm("repe; cmpsb; setnz %0"
22 : "=qm" (diff), "+D" (s1), "+S" (s2), "+c" (len)); 22 : "=qm" (diff), "+D" (s1), "+S" (s2), "+c" (len));
23 return diff; 23 return diff;