aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBoris Ostrovsky <boris.ostrovsky@oracle.com>2015-11-05 13:56:35 -0500
committerThomas Gleixner <tglx@linutronix.de>2015-11-07 04:39:39 -0500
commitf4e342c87776884f0309942a3880ca7e835239f9 (patch)
tree9406165675c8569eb732aa4f9446c9e94a1e8c8a
parent3849e91f571dcb48cf2c8143480c59137d44d6bc (diff)
x86/mm: Skip the hypervisor range when walking PGD
The range between 0xffff800000000000 and 0xffff87ffffffffff is reserved for hypervisor and therefore we should not try to follow PGD's indexes corresponding to those addresses. While this has always been a problem, with the new W+X warning mechanism ptdump_walk_pgd_level_core() can now be called during boot, causing a PV Xen guest to crash. [ tglx: Replaced the macro with a readable inline ] Fixes: e1a58320a38d "x86/mm: Warn on W^X mappings" Reported-by: Sander Eikelenboom <linux@eikelenboom.it> Signed-off-by: Boris Ostrovsky <boris.ostrovsky@oracle.com> Cc: xen-devel@lists.xen.org Link: http://lkml.kernel.org/r/1446749795-27764-1-git-send-email-boris.ostrovsky@oracle.com Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
-rw-r--r--arch/x86/mm/dump_pagetables.c17
1 files changed, 16 insertions, 1 deletions
diff --git a/arch/x86/mm/dump_pagetables.c b/arch/x86/mm/dump_pagetables.c
index 1bf417e9cc13..a035c2aa7801 100644
--- a/arch/x86/mm/dump_pagetables.c
+++ b/arch/x86/mm/dump_pagetables.c
@@ -358,6 +358,21 @@ static void walk_pud_level(struct seq_file *m, struct pg_state *st, pgd_t addr,
358#define pgd_none(a) pud_none(__pud(pgd_val(a))) 358#define pgd_none(a) pud_none(__pud(pgd_val(a)))
359#endif 359#endif
360 360
361#ifdef CONFIG_X86_64
362static inline bool is_hypervisor_range(int idx)
363{
364 /*
365 * ffff800000000000 - ffff87ffffffffff is reserved for
366 * the hypervisor.
367 */
368 return paravirt_enabled() &&
369 (idx >= pgd_index(__PAGE_OFFSET) - 16) &&
370 (idx < pgd_index(__PAGE_OFFSET));
371}
372#else
373static inline bool is_hypervisor_range(int idx) { return false; }
374#endif
375
361static void ptdump_walk_pgd_level_core(struct seq_file *m, pgd_t *pgd, 376static void ptdump_walk_pgd_level_core(struct seq_file *m, pgd_t *pgd,
362 bool checkwx) 377 bool checkwx)
363{ 378{
@@ -381,7 +396,7 @@ static void ptdump_walk_pgd_level_core(struct seq_file *m, pgd_t *pgd,
381 396
382 for (i = 0; i < PTRS_PER_PGD; i++) { 397 for (i = 0; i < PTRS_PER_PGD; i++) {
383 st.current_address = normalize_addr(i * PGD_LEVEL_MULT); 398 st.current_address = normalize_addr(i * PGD_LEVEL_MULT);
384 if (!pgd_none(*start)) { 399 if (!pgd_none(*start) && !is_hypervisor_range(i)) {
385 if (pgd_large(*start) || !pgd_present(*start)) { 400 if (pgd_large(*start) || !pgd_present(*start)) {
386 prot = pgd_flags(*start); 401 prot = pgd_flags(*start);
387 note_page(m, &st, __pgprot(prot), 1); 402 note_page(m, &st, __pgprot(prot), 1);