ptdump can now note non-leaf descriptor entries, a useful addition for debugging table descriptor permissions when working on related code Signed-off-by: Maxwell Bland <mbland@xxxxxxxxxxxx> --- arch/arm64/mm/ptdump.c | 6 ++++-- arch/powerpc/mm/ptdump/ptdump.c | 2 ++ arch/riscv/mm/ptdump.c | 6 ++++-- arch/s390/mm/dump_pagetables.c | 6 ++++-- arch/x86/mm/dump_pagetables.c | 3 ++- include/linux/ptdump.h | 1 + mm/ptdump.c | 13 +++++++++++++ 7 files changed, 30 insertions(+), 7 deletions(-) diff --git a/arch/arm64/mm/ptdump.c b/arch/arm64/mm/ptdump.c index 796231a4fd63..1a6f4a3513e5 100644 --- a/arch/arm64/mm/ptdump.c +++ b/arch/arm64/mm/ptdump.c @@ -299,7 +299,8 @@ void ptdump_walk(struct seq_file *s, struct ptdump_info *info) .range = (struct ptdump_range[]){ {info->base_addr, end}, {0, 0} - } + }, + .note_non_leaf = false } }; @@ -335,7 +336,8 @@ bool ptdump_check_wx(void) .range = (struct ptdump_range[]) { {_PAGE_OFFSET(vabits_actual), ~0UL}, {0, 0} - } + }, + .note_non_leaf = false } }; diff --git a/arch/powerpc/mm/ptdump/ptdump.c b/arch/powerpc/mm/ptdump/ptdump.c index 9dc239967b77..89e673f5fd3d 100644 --- a/arch/powerpc/mm/ptdump/ptdump.c +++ b/arch/powerpc/mm/ptdump/ptdump.c @@ -307,6 +307,7 @@ static int ptdump_show(struct seq_file *m, void *v) .ptdump = { .note_page = note_page, .range = ptdump_range, + .note_non_leaf = false } }; @@ -340,6 +341,7 @@ bool ptdump_check_wx(void) .ptdump = { .note_page = note_page, .range = ptdump_range, + .note_non_leaf = false } }; diff --git a/arch/riscv/mm/ptdump.c b/arch/riscv/mm/ptdump.c index 1289cc6d3700..b355633afcaf 100644 --- a/arch/riscv/mm/ptdump.c +++ b/arch/riscv/mm/ptdump.c @@ -328,7 +328,8 @@ static void ptdump_walk(struct seq_file *s, struct ptd_mm_info *pinfo) .range = (struct ptdump_range[]) { {pinfo->base_addr, pinfo->end}, {0, 0} - } + }, + .note_non_leaf = false } }; @@ -350,7 +351,8 @@ bool ptdump_check_wx(void) .range = (struct ptdump_range[]) { {KERN_VIRT_START, ULONG_MAX}, {0, 0} - } + }, + .note_non_leaf = false } }; diff --git a/arch/s390/mm/dump_pagetables.c b/arch/s390/mm/dump_pagetables.c index ffd07ed7b4af..6468cfd53e2a 100644 --- a/arch/s390/mm/dump_pagetables.c +++ b/arch/s390/mm/dump_pagetables.c @@ -200,7 +200,8 @@ bool ptdump_check_wx(void) .range = (struct ptdump_range[]) { {.start = 0, .end = max_addr}, {.start = 0, .end = 0}, - } + }, + .note_non_leaf = false }, .seq = NULL, .level = -1, @@ -239,7 +240,8 @@ static int ptdump_show(struct seq_file *m, void *v) .range = (struct ptdump_range[]) { {.start = 0, .end = max_addr}, {.start = 0, .end = 0}, - } + }, + .note_non_leaf = false }, .seq = m, .level = -1, diff --git a/arch/x86/mm/dump_pagetables.c b/arch/x86/mm/dump_pagetables.c index 89079ea73e65..43f00dfb955f 100644 --- a/arch/x86/mm/dump_pagetables.c +++ b/arch/x86/mm/dump_pagetables.c @@ -380,7 +380,8 @@ bool ptdump_walk_pgd_level_core(struct seq_file *m, .ptdump = { .note_page = note_page, .effective_prot = effective_prot, - .range = ptdump_ranges + .range = ptdump_ranges, + .note_non_leaf = false }, .level = -1, .to_dmesg = dmesg, diff --git a/include/linux/ptdump.h b/include/linux/ptdump.h index 8dbd51ea8626..b3e793a5c77f 100644 --- a/include/linux/ptdump.h +++ b/include/linux/ptdump.h @@ -16,6 +16,7 @@ struct ptdump_state { int level, u64 val); void (*effective_prot)(struct ptdump_state *st, int level, u64 val); const struct ptdump_range *range; + bool note_non_leaf; }; bool ptdump_walk_pgd_level_core(struct seq_file *m, diff --git a/mm/ptdump.c b/mm/ptdump.c index 106e1d66e9f9..97da7a765b22 100644 --- a/mm/ptdump.c +++ b/mm/ptdump.c @@ -41,6 +41,9 @@ static int ptdump_pgd_entry(pgd_t *pgd, unsigned long addr, if (st->effective_prot) st->effective_prot(st, 0, pgd_val(val)); + if (st->note_non_leaf && !pgd_leaf(val)) + st->note_page(st, addr, 0, pgd_val(val)); + if (pgd_leaf(val)) { st->note_page(st, addr, 0, pgd_val(val)); walk->action = ACTION_CONTINUE; @@ -64,6 +67,9 @@ static int ptdump_p4d_entry(p4d_t *p4d, unsigned long addr, if (st->effective_prot) st->effective_prot(st, 1, p4d_val(val)); + if (st->note_non_leaf && !p4d_leaf(val)) + st->note_page(st, addr, 1, p4d_val(val)); + if (p4d_leaf(val)) { st->note_page(st, addr, 1, p4d_val(val)); walk->action = ACTION_CONTINUE; @@ -87,6 +93,9 @@ static int ptdump_pud_entry(pud_t *pud, unsigned long addr, if (st->effective_prot) st->effective_prot(st, 2, pud_val(val)); + if (st->note_non_leaf && !pud_leaf(val)) + st->note_page(st, addr, 2, pud_val(val)); + if (pud_leaf(val)) { st->note_page(st, addr, 2, pud_val(val)); walk->action = ACTION_CONTINUE; @@ -108,6 +117,10 @@ static int ptdump_pmd_entry(pmd_t *pmd, unsigned long addr, if (st->effective_prot) st->effective_prot(st, 3, pmd_val(val)); + + if (st->note_non_leaf && !pmd_leaf(val)) + st->note_page(st, addr, 3, pmd_val(val)); + if (pmd_leaf(val)) { st->note_page(st, addr, 3, pmd_val(val)); walk->action = ACTION_CONTINUE; -- 2.39.2