lkml.org 
[lkml]   [2020]   [May]   [19]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH v4 12/45] powerpc/ptdump: Properly handle non standard page size
    Date
    In order to properly display information regardless of the page size,
    it is necessary to take into account real page size.

    Signed-off-by: Christophe Leroy <christophe.leroy@csgroup.eu>
    Fixes: cabe8138b23c ("powerpc: dump as a single line areas mapping a single physical page.")
    Cc: stable@vger.kernel.org
    ---
    v3: Fixed sizes which were shifted one level (went unoticed on PPC32 as PMD and PUD level don't exist)
    ---
    arch/powerpc/mm/ptdump/ptdump.c | 21 ++++++++++++---------
    1 file changed, 12 insertions(+), 9 deletions(-)

    diff --git a/arch/powerpc/mm/ptdump/ptdump.c b/arch/powerpc/mm/ptdump/ptdump.c
    index 1f97668853e3..98d82dcf6f0b 100644
    --- a/arch/powerpc/mm/ptdump/ptdump.c
    +++ b/arch/powerpc/mm/ptdump/ptdump.c
    @@ -60,6 +60,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;
    @@ -168,9 +169,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;
    @@ -195,7 +196,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;
    @@ -207,6 +208,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:
    @@ -218,7 +220,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 */
    @@ -246,6 +248,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 {
    @@ -261,7 +264,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);

    }
    }
    @@ -278,7 +281,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);
    }
    }

    @@ -294,7 +297,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);
    }
    }

    @@ -313,7 +316,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);
    }
    }

    @@ -368,7 +371,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.25.0
    \
     
     \ /
      Last update: 2020-05-19 07:49    [W:3.554 / U:0.012 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site