| From 50cce7284c64901e34ad982f6422aae1ebd55ec7 Mon Sep 17 00:00:00 2001 |
| From: Christophe Leroy <christophe.leroy@csgroup.eu> |
| Date: Tue, 19 May 2020 05:48:54 +0000 |
| Subject: [PATCH] powerpc/ptdump: Properly handle non standard page size |
| |
| commit b00ff6d8c1c3898b0f768cbb38ef722d25bd2f39 upstream. |
| |
| In order to properly display information regardless of the page size, |
| it is necessary to take into account real page size. |
| |
| Fixes: cabe8138b23c ("powerpc: dump as a single line areas mapping a single physical page.") |
| Cc: stable@vger.kernel.org |
| Signed-off-by: Christophe Leroy <christophe.leroy@csgroup.eu> |
| Signed-off-by: Michael Ellerman <mpe@ellerman.id.au> |
| Link: https://lore.kernel.org/r/a53b2a0ffd042a8d85464bf90d55bc5b970e00a1.1589866984.git.christophe.leroy@csgroup.eu |
| Signed-off-by: Paul Gortmaker <paul.gortmaker@windriver.com> |
| |
| diff --git a/arch/powerpc/mm/ptdump/ptdump.c b/arch/powerpc/mm/ptdump/ptdump.c |
| index 49cee97c0207..485363358395 100644 |
| --- a/arch/powerpc/mm/ptdump/ptdump.c |
| +++ b/arch/powerpc/mm/ptdump/ptdump.c |
| @@ -62,6 +62,7 @@ struct pg_state { |
| unsigned long start_address; |
| unsigned long start_pa; |
| unsigned long last_pa; |
| + unsigned long page_size; |
| unsigned int level; |
| u64 current_flags; |
| bool check_wx; |
| @@ -163,9 +164,9 @@ static void dump_addr(struct pg_state *st, unsigned long addr) |
| #endif |
| |
| pt_dump_seq_printf(st->seq, REG "-" REG " ", st->start_address, addr - 1); |
| - if (st->start_pa == st->last_pa && st->start_address + PAGE_SIZE != addr) { |
| + if (st->start_pa == st->last_pa && st->start_address + st->page_size != addr) { |
| pt_dump_seq_printf(st->seq, "[" REG "]", st->start_pa); |
| - delta = PAGE_SIZE >> 10; |
| + delta = st->page_size >> 10; |
| } else { |
| pt_dump_seq_printf(st->seq, " " REG " ", st->start_pa); |
| delta = (addr - st->start_address) >> 10; |
| @@ -196,7 +197,7 @@ static void note_prot_wx(struct pg_state *st, unsigned long addr) |
| } |
| |
| static void note_page(struct pg_state *st, unsigned long addr, |
| - unsigned int level, u64 val) |
| + unsigned int level, u64 val, unsigned long page_size) |
| { |
| u64 flag = val & pg_level[level].mask; |
| u64 pa = val & PTE_RPN_MASK; |
| @@ -208,6 +209,7 @@ static void note_page(struct pg_state *st, unsigned long addr, |
| st->start_address = addr; |
| st->start_pa = pa; |
| st->last_pa = pa; |
| + st->page_size = page_size; |
| pt_dump_seq_printf(st->seq, "---[ %s ]---\n", st->marker->name); |
| /* |
| * Dump the section of virtual memory when: |
| @@ -219,7 +221,7 @@ static void note_page(struct pg_state *st, unsigned long addr, |
| */ |
| } else if (flag != st->current_flags || level != st->level || |
| addr >= st->marker[1].start_address || |
| - (pa != st->last_pa + PAGE_SIZE && |
| + (pa != st->last_pa + st->page_size && |
| (pa != st->start_pa || st->start_pa != st->last_pa))) { |
| |
| /* Check the PTE flags */ |
| @@ -247,6 +249,7 @@ static void note_page(struct pg_state *st, unsigned long addr, |
| st->start_address = addr; |
| st->start_pa = pa; |
| st->last_pa = pa; |
| + st->page_size = page_size; |
| st->current_flags = flag; |
| st->level = level; |
| } else { |
| @@ -262,7 +265,7 @@ static void walk_pte(struct pg_state *st, pmd_t *pmd, unsigned long start) |
| |
| for (i = 0; i < PTRS_PER_PTE; i++, pte++) { |
| addr = start + i * PAGE_SIZE; |
| - note_page(st, addr, 4, pte_val(*pte)); |
| + note_page(st, addr, 4, pte_val(*pte), PAGE_SIZE); |
| |
| } |
| } |
| @@ -279,7 +282,7 @@ static void walk_pmd(struct pg_state *st, pud_t *pud, unsigned long start) |
| /* pmd exists */ |
| walk_pte(st, pmd, addr); |
| else |
| - note_page(st, addr, 3, pmd_val(*pmd)); |
| + note_page(st, addr, 3, pmd_val(*pmd), PMD_SIZE); |
| } |
| } |
| |
| @@ -295,7 +298,7 @@ static void walk_pud(struct pg_state *st, pgd_t *pgd, unsigned long start) |
| /* pud exists */ |
| walk_pmd(st, pud, addr); |
| else |
| - note_page(st, addr, 2, pud_val(*pud)); |
| + note_page(st, addr, 2, pud_val(*pud), PUD_SIZE); |
| } |
| } |
| |
| @@ -316,7 +319,7 @@ static void walk_pagetables(struct pg_state *st) |
| /* pgd exists */ |
| walk_pud(st, pgd, addr); |
| else |
| - note_page(st, addr, 1, pgd_val(*pgd)); |
| + note_page(st, addr, 1, pgd_val(*pgd), PGDIR_SIZE); |
| } |
| } |
| |
| @@ -375,7 +378,7 @@ static int ptdump_show(struct seq_file *m, void *v) |
| |
| /* Traverse kernel page tables */ |
| walk_pagetables(&st); |
| - note_page(&st, 0, 0, 0); |
| + note_page(&st, 0, 0, 0, 0); |
| return 0; |
| } |
| |
| -- |
| 2.27.0 |
| |