lkml.org 
[lkml]   [2019]   [Feb]   [27]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH v3 29/34] arm64: mm: Convert mm/dump.c to use walk_page_range()
    Date
    Now walk_page_range() can walk kernel page tables, we can switch the
    arm64 ptdump code over to using it, simplifying the code.

    Signed-off-by: Steven Price <steven.price@arm.com>
    ---
    arch/arm64/mm/dump.c | 108 +++++++++++++++++++++----------------------
    1 file changed, 53 insertions(+), 55 deletions(-)

    diff --git a/arch/arm64/mm/dump.c b/arch/arm64/mm/dump.c
    index 99bb8facb5cb..ee0bc1441dd0 100644
    --- a/arch/arm64/mm/dump.c
    +++ b/arch/arm64/mm/dump.c
    @@ -286,73 +286,71 @@ static void note_page(struct pg_state *st, unsigned long addr, unsigned level,

    }

    -static void walk_pte(struct pg_state *st, pmd_t *pmdp, unsigned long start,
    - unsigned long end)
    +static int pud_entry(pud_t *pud, unsigned long addr,
    + unsigned long next, struct mm_walk *walk)
    {
    - unsigned long addr = start;
    - pte_t *ptep = pte_offset_kernel(pmdp, start);
    + struct pg_state *st = walk->private;
    + pud_t val = READ_ONCE(*pud);

    - do {
    - note_page(st, addr, 4, READ_ONCE(pte_val(*ptep)));
    - } while (ptep++, addr += PAGE_SIZE, addr != end);
    + if (pud_table(val))
    + return 0;
    +
    + note_page(st, addr, 2, pud_val(val));
    +
    + return 0;
    }

    -static void walk_pmd(struct pg_state *st, pud_t *pudp, unsigned long start,
    - unsigned long end)
    +static int pmd_entry(pmd_t *pmd, unsigned long addr,
    + unsigned long next, struct mm_walk *walk)
    {
    - unsigned long next, addr = start;
    - pmd_t *pmdp = pmd_offset(pudp, start);
    -
    - do {
    - pmd_t pmd = READ_ONCE(*pmdp);
    - next = pmd_addr_end(addr, end);
    -
    - if (pmd_none(pmd) || pmd_sect(pmd)) {
    - note_page(st, addr, 3, pmd_val(pmd));
    - } else {
    - BUG_ON(pmd_bad(pmd));
    - walk_pte(st, pmdp, addr, next);
    - }
    - } while (pmdp++, addr = next, addr != end);
    + struct pg_state *st = walk->private;
    + pmd_t val = READ_ONCE(*pmd);
    +
    + if (pmd_table(val))
    + return 0;
    +
    + note_page(st, addr, 3, pmd_val(val));
    +
    + return 0;
    }

    -static void walk_pud(struct pg_state *st, pgd_t *pgdp, unsigned long start,
    - unsigned long end)
    +static int pte_entry(pte_t *pte, unsigned long addr,
    + unsigned long next, struct mm_walk *walk)
    {
    - unsigned long next, addr = start;
    - pud_t *pudp = pud_offset(pgdp, start);
    -
    - do {
    - pud_t pud = READ_ONCE(*pudp);
    - next = pud_addr_end(addr, end);
    -
    - if (pud_none(pud) || pud_sect(pud)) {
    - note_page(st, addr, 2, pud_val(pud));
    - } else {
    - BUG_ON(pud_bad(pud));
    - walk_pmd(st, pudp, addr, next);
    - }
    - } while (pudp++, addr = next, addr != end);
    + struct pg_state *st = walk->private;
    + pte_t val = READ_ONCE(*pte);
    +
    + note_page(st, addr, 4, pte_val(val));
    +
    + return 0;
    +}
    +
    +static int pte_hole(unsigned long addr, unsigned long next, int depth,
    + struct mm_walk *walk)
    +{
    + struct pg_state *st = walk->private;
    +
    + note_page(st, addr, depth+1, 0);
    +
    + return 0;
    }

    static void walk_pgd(struct pg_state *st, struct mm_struct *mm,
    - unsigned long start)
    + unsigned long start)
    {
    - unsigned long end = (start < TASK_SIZE_64) ? TASK_SIZE_64 : 0;
    - unsigned long next, addr = start;
    - pgd_t *pgdp = pgd_offset(mm, start);
    -
    - do {
    - pgd_t pgd = READ_ONCE(*pgdp);
    - next = pgd_addr_end(addr, end);
    -
    - if (pgd_none(pgd)) {
    - note_page(st, addr, 1, pgd_val(pgd));
    - } else {
    - BUG_ON(pgd_bad(pgd));
    - walk_pud(st, pgdp, addr, next);
    - }
    - } while (pgdp++, addr = next, addr != end);
    + struct mm_walk walk = {
    + .mm = mm,
    + .private = st,
    + .pud_entry = pud_entry,
    + .pmd_entry = pmd_entry,
    + .pte_entry = pte_entry,
    + .pte_hole = pte_hole
    + };
    + down_read(&mm->mmap_sem);
    + walk_page_range(start, start | (((unsigned long)PTRS_PER_PGD <<
    + PGDIR_SHIFT) - 1),
    + &walk);
    + up_read(&mm->mmap_sem);
    }

    void ptdump_walk_pgd(struct seq_file *m, struct ptdump_info *info)
    --
    2.20.1
    \
     
     \ /
      Last update: 2019-02-27 18:09    [W:2.228 / U:0.316 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site