walk_pagetables() always walk the entire pgdir from address 0
but considers PAGE_OFFSET or KERN_VIRT_START as the starting
address of the walk, resulting in a possible mismatch in the
displayed addresses.

Ex: on PPC32, when KERN_VIRT_START was locally defined as
PAGE_OFFSET, ptdump displayed 0x80000000
instead of 0xc0000000 for the first kernel page,
because 0xc0000000 + 0xc0000000 = 0x80000000

Start the walk at st->start_address instead of starting at 0.

Signed-off-by: Christophe Leroy <christophe.le...@c-s.fr>
---
 arch/powerpc/mm/ptdump/ptdump.c | 8 +++-----
 1 file changed, 3 insertions(+), 5 deletions(-)

diff --git a/arch/powerpc/mm/ptdump/ptdump.c b/arch/powerpc/mm/ptdump/ptdump.c
index 3ad64fc11419..74ff2bff4ea0 100644
--- a/arch/powerpc/mm/ptdump/ptdump.c
+++ b/arch/powerpc/mm/ptdump/ptdump.c
@@ -299,17 +299,15 @@ static void walk_pud(struct pg_state *st, pgd_t *pgd, 
unsigned long start)
 
 static void walk_pagetables(struct pg_state *st)
 {
-       pgd_t *pgd = pgd_offset_k(0UL);
        unsigned int i;
-       unsigned long addr;
-
-       addr = st->start_address;
+       unsigned long addr = st->start_address & PGDIR_MASK;
+       pgd_t *pgd = pgd_offset_k(addr);
 
        /*
         * Traverse the linux pagetable structure and dump pages that are in
         * the hash pagetable.
         */
-       for (i = 0; i < PTRS_PER_PGD; i++, pgd++, addr += PGDIR_SIZE) {
+       for (i = pgd_index(addr); i < PTRS_PER_PGD; i++, pgd++, addr += 
PGDIR_SIZE) {
                if (!pgd_none(*pgd) && !pgd_is_leaf(*pgd))
                        /* pgd exists */
                        walk_pud(st, pgd, addr);
-- 
2.13.3

Reply via email to