aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDave Hansen <dave.hansen@linux.intel.com>2018-04-20 18:20:21 -0400
committerThomas Gleixner <tglx@linutronix.de>2018-04-25 05:02:50 -0400
commit58e65b51e6f9b9dd94a25ff2b2772222e0358099 (patch)
tree5ca1e02213a03807105bd1e48ad31faba17fab74
parentd2479a30499d93377d3ab10b7822bc5f10ed7f22 (diff)
x86/pti: Fix boot warning from Global-bit setting
commit 231df823c4f04176f607afc4576c989895cff40e The pageattr.c code attempts to process "faults" when it goes looking for PTEs to change and finds non-present entries. It allows these faults in the linear map which is "expected to have holes", but WARN()s about them elsewhere, like when called on the kernel image. However, change_page_attr_clear() is now called on the kernel image in the process of trying to clear the Global bit. This trips the warning in __cpa_process_fault() if a non-present PTE is encountered in the kernel image. The "holes" in the kernel image result from free_init_pages()'s use of set_memory_np(). These holes are totally fine, and result from normal operation, just as they would be in the kernel linear map. Just silence the warning when holes in the kernel image are encountered. Fixes: 39114b7a7 (x86/pti: Never implicitly clear _PAGE_GLOBAL for kernel image) Reported-by: Mariusz Ceier <mceier@gmail.com> Reported-by: Aaro Koskinen <aaro.koskinen@nokia.com> Signed-off-by: Dave Hansen <dave.hansen@linux.intel.com> Signed-off-by: Thomas Gleixner <tglx@linutronix.de> Tested-by: Aaro Koskinen <aaro.koskinen@nokia.com> Acked-by: Ingo Molnar <mingo@kernel.org> Cc: Andrea Arcangeli <aarcange@redhat.com> Cc: Juergen Gross <jgross@suse.com> Cc: Nadav Amit <namit@vmware.com> Cc: Kees Cook <keescook@google.com> Cc: Josh Poimboeuf <jpoimboe@redhat.com> Cc: Peter Zijlstra <peterz@infradead.org> Cc: David Woodhouse <dwmw2@infradead.org> Cc: Hugh Dickins <hughd@google.com> Cc: linux-mm@kvack.org Cc: Linus Torvalds <torvalds@linux-foundation.org> Cc: Andy Lutomirski <luto@kernel.org> Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org> Cc: Borislav Petkov <bp@alien8.de> Cc: Dan Williams <dan.j.williams@intel.com> Cc: Arjan van de Ven <arjan@linux.intel.com> Link: https://lkml.kernel.org/r/20180420222021.1C7D2B3F@viggo.jf.intel.com
-rw-r--r--arch/x86/mm/pageattr.c40
1 files changed, 30 insertions, 10 deletions
diff --git a/arch/x86/mm/pageattr.c b/arch/x86/mm/pageattr.c
index 4fadfd2b7017..3bded76e8d5c 100644
--- a/arch/x86/mm/pageattr.c
+++ b/arch/x86/mm/pageattr.c
@@ -93,6 +93,18 @@ void arch_report_meminfo(struct seq_file *m)
93static inline void split_page_count(int level) { } 93static inline void split_page_count(int level) { }
94#endif 94#endif
95 95
96static inline int
97within(unsigned long addr, unsigned long start, unsigned long end)
98{
99 return addr >= start && addr < end;
100}
101
102static inline int
103within_inclusive(unsigned long addr, unsigned long start, unsigned long end)
104{
105 return addr >= start && addr <= end;
106}
107
96#ifdef CONFIG_X86_64 108#ifdef CONFIG_X86_64
97 109
98static inline unsigned long highmap_start_pfn(void) 110static inline unsigned long highmap_start_pfn(void)
@@ -106,20 +118,25 @@ static inline unsigned long highmap_end_pfn(void)
106 return __pa_symbol(roundup(_brk_end, PMD_SIZE) - 1) >> PAGE_SHIFT; 118 return __pa_symbol(roundup(_brk_end, PMD_SIZE) - 1) >> PAGE_SHIFT;
107} 119}
108 120
109#endif 121static bool __cpa_pfn_in_highmap(unsigned long pfn)
110
111static inline int
112within(unsigned long addr, unsigned long start, unsigned long end)
113{ 122{
114 return addr >= start && addr < end; 123 /*
124 * Kernel text has an alias mapping at a high address, known
125 * here as "highmap".
126 */
127 return within_inclusive(pfn, highmap_start_pfn(), highmap_end_pfn());
115} 128}
116 129
117static inline int 130#else
118within_inclusive(unsigned long addr, unsigned long start, unsigned long end) 131
132static bool __cpa_pfn_in_highmap(unsigned long pfn)
119{ 133{
120 return addr >= start && addr <= end; 134 /* There is no highmap on 32-bit */
135 return false;
121} 136}
122 137
138#endif
139
123/* 140/*
124 * Flushing functions 141 * Flushing functions
125 */ 142 */
@@ -1183,6 +1200,10 @@ static int __cpa_process_fault(struct cpa_data *cpa, unsigned long vaddr,
1183 cpa->numpages = 1; 1200 cpa->numpages = 1;
1184 cpa->pfn = __pa(vaddr) >> PAGE_SHIFT; 1201 cpa->pfn = __pa(vaddr) >> PAGE_SHIFT;
1185 return 0; 1202 return 0;
1203
1204 } else if (__cpa_pfn_in_highmap(cpa->pfn)) {
1205 /* Faults in the highmap are OK, so do not warn: */
1206 return -EFAULT;
1186 } else { 1207 } else {
1187 WARN(1, KERN_WARNING "CPA: called for zero pte. " 1208 WARN(1, KERN_WARNING "CPA: called for zero pte. "
1188 "vaddr = %lx cpa->vaddr = %lx\n", vaddr, 1209 "vaddr = %lx cpa->vaddr = %lx\n", vaddr,
@@ -1335,8 +1356,7 @@ static int cpa_process_alias(struct cpa_data *cpa)
1335 * to touch the high mapped kernel as well: 1356 * to touch the high mapped kernel as well:
1336 */ 1357 */
1337 if (!within(vaddr, (unsigned long)_text, _brk_end) && 1358 if (!within(vaddr, (unsigned long)_text, _brk_end) &&
1338 within_inclusive(cpa->pfn, highmap_start_pfn(), 1359 __cpa_pfn_in_highmap(cpa->pfn)) {
1339 highmap_end_pfn())) {
1340 unsigned long temp_cpa_vaddr = (cpa->pfn << PAGE_SHIFT) + 1360 unsigned long temp_cpa_vaddr = (cpa->pfn << PAGE_SHIFT) +
1341 __START_KERNEL_map - phys_base; 1361 __START_KERNEL_map - phys_base;
1342 alias_cpa = *cpa; 1362 alias_cpa = *cpa;