| From: Anshuman Khandual <anshuman.khandual@arm.com> |
| Subject: mm/ptdump: split note_page() into level specific callbacks |
| Date: Mon, 7 Apr 2025 11:01:11 +0530 |
| |
| Patch series "mm/ptdump: Drop assumption that pxd_val() is u64", v2. |
| |
| Last argument passed down in note_page() is u64 assuming pxd_val() |
| returned value (all page table levels) is 64 bit - which might not be the |
| case going ahead when D128 page tables is enabled on arm64 platform. |
| Besides pxd_val() is very platform specific and its type should not be |
| assumed in generic MM. A similar problem exists for effective_prot(), |
| although it is restricted to x86 platform. |
| |
| This series splits note_page() and effective_prot() into individual page |
| table level specific callbacks which accepts corresponding pxd_t page |
| table entry as an argument instead and later on all subscribing platforms |
| could derive pxd_val() from the table entries as required and proceed as |
| before. |
| |
| Define ptdesc_t type which describes the basic page table descriptor |
| layout on arm64 platform. Subsequently all level specific pxxval_t |
| descriptors are derived from ptdesc_t thus establishing a common original |
| format, which can also be appropriate for page table entries, masks and |
| protection values etc which are used at all page table levels. |
| |
| |
| This patch (of 3): |
| |
| Last argument passed down in note_page() is u64 assuming pxd_val() |
| returned value (all page table levels) is 64 bit - which might not be the |
| case going ahead when D128 page tables is enabled on arm64 platform. |
| Besides pxd_val() is very platform specific and its type should not be |
| assumed in generic MM. |
| |
| Split note_page() into individual page table level specific callbacks |
| which accepts corresponding pxd_t argument instead and then subscribing |
| platforms just derive pxd_val() from the entries as required and proceed |
| as earlier. |
| |
| Also add a note_page_flush() callback for flushing the last page table |
| page that was being handled earlier via level = -1. |
| |
| Link: https://lkml.kernel.org/r/20250407053113.746295-1-anshuman.khandual@arm.com |
| Link: https://lkml.kernel.org/r/20250407053113.746295-2-anshuman.khandual@arm.com |
| Signed-off-by: Anshuman Khandual <anshuman.khandual@arm.com> |
| Cc: Catalin Marinas <catalin.marinas@arm.com> |
| Cc: Will Deacon <will@kernel.org> |
| Cc: Madhavan Srinivasan <maddy@linux.ibm.com> |
| Cc: Nicholas Piggin <npiggin@gmail.com> |
| Cc: Paul Walmsley <paul.walmsley@sifive.com> |
| Cc: Palmer Dabbelt <palmer@dabbelt.com> |
| Cc: Gerald Schaefer <gerald.schaefer@linux.ibm.com> |
| Cc: Heiko Carstens <hca@linux.ibm.com> |
| Cc: Peter Zijlstra <peterz@infradead.org> |
| Cc: Thomas Gleixner <tglx@linutronix.de> |
| Cc: Ingo Molnar <mingo@redhat.com> |
| Cc: Ard Biesheuvel <ardb@kernel.org> |
| Cc: Dave Hansen <dave.hansen@linux.intel.com> |
| Cc: Mark Rutland <mark.rutland@arm.com> |
| Cc: Ryan Roberts <ryan.roberts@arm.com> |
| Signed-off-by: Andrew Morton <akpm@linux-foundation.org> |
| --- |
| |
| arch/arm64/include/asm/ptdump.h | 16 ++++++++-- |
| arch/arm64/mm/ptdump.c | 48 ++++++++++++++++++++++++++++-- |
| arch/powerpc/mm/ptdump/ptdump.c | 46 +++++++++++++++++++++++++++- |
| arch/riscv/mm/ptdump.c | 46 +++++++++++++++++++++++++++- |
| arch/s390/mm/dump_pagetables.c | 46 +++++++++++++++++++++++++++- |
| arch/x86/mm/dump_pagetables.c | 39 +++++++++++++++++++++++- |
| include/linux/ptdump.h | 9 +++-- |
| mm/ptdump.c | 42 ++++++++++++++++++++------ |
| 8 files changed, 267 insertions(+), 25 deletions(-) |
| |
| --- a/arch/arm64/include/asm/ptdump.h~mm-ptdump-split-note_page-into-level-specific-callbacks |
| +++ a/arch/arm64/include/asm/ptdump.h |
| @@ -59,7 +59,13 @@ struct ptdump_pg_state { |
| |
| void ptdump_walk(struct seq_file *s, struct ptdump_info *info); |
| void note_page(struct ptdump_state *pt_st, unsigned long addr, int level, |
| - u64 val); |
| + pteval_t val); |
| +void note_page_pte(struct ptdump_state *st, unsigned long addr, pte_t pte); |
| +void note_page_pmd(struct ptdump_state *st, unsigned long addr, pmd_t pmd); |
| +void note_page_pud(struct ptdump_state *st, unsigned long addr, pud_t pud); |
| +void note_page_p4d(struct ptdump_state *st, unsigned long addr, p4d_t p4d); |
| +void note_page_pgd(struct ptdump_state *st, unsigned long addr, pgd_t pgd); |
| +void note_page_flush(struct ptdump_state *st); |
| #ifdef CONFIG_PTDUMP_DEBUGFS |
| #define EFI_RUNTIME_MAP_END DEFAULT_MAP_WINDOW_64 |
| void __init ptdump_debugfs_register(struct ptdump_info *info, const char *name); |
| @@ -69,7 +75,13 @@ static inline void ptdump_debugfs_regist |
| #endif /* CONFIG_PTDUMP_DEBUGFS */ |
| #else |
| static inline void note_page(struct ptdump_state *pt_st, unsigned long addr, |
| - int level, u64 val) { } |
| + int level, pteval_t val) { } |
| +static inline void note_page_pte(struct ptdump_state *st, unsigned long addr, pte_t pte) { } |
| +static inline void note_page_pmd(struct ptdump_state *st, unsigned long addr, pmd_t pmd) { } |
| +static inline void note_page_pud(struct ptdump_state *st, unsigned long addr, pud_t pud) { } |
| +static inline void note_page_p4d(struct ptdump_state *st, unsigned long addr, p4d_t p4d) { } |
| +static inline void note_page_pgd(struct ptdump_state *st, unsigned long addr, pgd_t pgd) { } |
| +static inline void note_page_flush(struct ptdump_state *st) { } |
| #endif /* CONFIG_PTDUMP */ |
| |
| #endif /* __ASM_PTDUMP_H */ |
| --- a/arch/arm64/mm/ptdump.c~mm-ptdump-split-note_page-into-level-specific-callbacks |
| +++ a/arch/arm64/mm/ptdump.c |
| @@ -189,7 +189,7 @@ static void note_prot_wx(struct ptdump_p |
| } |
| |
| void note_page(struct ptdump_state *pt_st, unsigned long addr, int level, |
| - u64 val) |
| + pteval_t val) |
| { |
| struct ptdump_pg_state *st = container_of(pt_st, struct ptdump_pg_state, ptdump); |
| struct ptdump_pg_level *pg_level = st->pg_level; |
| @@ -251,6 +251,38 @@ void note_page(struct ptdump_state *pt_s |
| |
| } |
| |
| +void note_page_pte(struct ptdump_state *pt_st, unsigned long addr, pte_t pte) |
| +{ |
| + note_page(pt_st, addr, 4, pte_val(pte)); |
| +} |
| + |
| +void note_page_pmd(struct ptdump_state *pt_st, unsigned long addr, pmd_t pmd) |
| +{ |
| + note_page(pt_st, addr, 3, pmd_val(pmd)); |
| +} |
| + |
| +void note_page_pud(struct ptdump_state *pt_st, unsigned long addr, pud_t pud) |
| +{ |
| + note_page(pt_st, addr, 2, pud_val(pud)); |
| +} |
| + |
| +void note_page_p4d(struct ptdump_state *pt_st, unsigned long addr, p4d_t p4d) |
| +{ |
| + note_page(pt_st, addr, 1, p4d_val(p4d)); |
| +} |
| + |
| +void note_page_pgd(struct ptdump_state *pt_st, unsigned long addr, pgd_t pgd) |
| +{ |
| + note_page(pt_st, addr, 0, pgd_val(pgd)); |
| +} |
| + |
| +void note_page_flush(struct ptdump_state *pt_st) |
| +{ |
| + pte_t pte_zero = {0}; |
| + |
| + note_page(pt_st, 0, -1, pte_val(pte_zero)); |
| +} |
| + |
| void ptdump_walk(struct seq_file *s, struct ptdump_info *info) |
| { |
| unsigned long end = ~0UL; |
| @@ -266,7 +298,12 @@ void ptdump_walk(struct seq_file *s, str |
| .pg_level = &kernel_pg_levels[0], |
| .level = -1, |
| .ptdump = { |
| - .note_page = note_page, |
| + .note_page_pte = note_page_pte, |
| + .note_page_pmd = note_page_pmd, |
| + .note_page_pud = note_page_pud, |
| + .note_page_p4d = note_page_p4d, |
| + .note_page_pgd = note_page_pgd, |
| + .note_page_flush = note_page_flush, |
| .range = (struct ptdump_range[]){ |
| {info->base_addr, end}, |
| {0, 0} |
| @@ -303,7 +340,12 @@ bool ptdump_check_wx(void) |
| .level = -1, |
| .check_wx = true, |
| .ptdump = { |
| - .note_page = note_page, |
| + .note_page_pte = note_page_pte, |
| + .note_page_pmd = note_page_pmd, |
| + .note_page_pud = note_page_pud, |
| + .note_page_p4d = note_page_p4d, |
| + .note_page_pgd = note_page_pgd, |
| + .note_page_flush = note_page_flush, |
| .range = (struct ptdump_range[]) { |
| {_PAGE_OFFSET(vabits_actual), ~0UL}, |
| {0, 0} |
| --- a/arch/powerpc/mm/ptdump/ptdump.c~mm-ptdump-split-note_page-into-level-specific-callbacks |
| +++ a/arch/powerpc/mm/ptdump/ptdump.c |
| @@ -298,6 +298,38 @@ static void populate_markers(void) |
| #endif |
| } |
| |
| +static void note_page_pte(struct ptdump_state *pt_st, unsigned long addr, pte_t pte) |
| +{ |
| + note_page(pt_st, addr, 4, pte_val(pte)); |
| +} |
| + |
| +static void note_page_pmd(struct ptdump_state *pt_st, unsigned long addr, pmd_t pmd) |
| +{ |
| + note_page(pt_st, addr, 3, pmd_val(pmd)); |
| +} |
| + |
| +static void note_page_pud(struct ptdump_state *pt_st, unsigned long addr, pud_t pud) |
| +{ |
| + note_page(pt_st, addr, 2, pud_val(pud)); |
| +} |
| + |
| +static void note_page_p4d(struct ptdump_state *pt_st, unsigned long addr, p4d_t p4d) |
| +{ |
| + note_page(pt_st, addr, 1, p4d_val(p4d)); |
| +} |
| + |
| +static void note_page_pgd(struct ptdump_state *pt_st, unsigned long addr, pgd_t pgd) |
| +{ |
| + note_page(pt_st, addr, 0, pgd_val(pgd)); |
| +} |
| + |
| +static void note_page_flush(struct ptdump_state *pt_st) |
| +{ |
| + pte_t pte_zero = {0}; |
| + |
| + note_page(pt_st, 0, -1, pte_val(pte_zero)); |
| +} |
| + |
| static int ptdump_show(struct seq_file *m, void *v) |
| { |
| struct pg_state st = { |
| @@ -305,7 +337,12 @@ static int ptdump_show(struct seq_file * |
| .marker = address_markers, |
| .level = -1, |
| .ptdump = { |
| - .note_page = note_page, |
| + .note_page_pte = note_page_pte, |
| + .note_page_pmd = note_page_pmd, |
| + .note_page_pud = note_page_pud, |
| + .note_page_p4d = note_page_p4d, |
| + .note_page_pgd = note_page_pgd, |
| + .note_page_flush = note_page_flush, |
| .range = ptdump_range, |
| } |
| }; |
| @@ -338,7 +375,12 @@ bool ptdump_check_wx(void) |
| .level = -1, |
| .check_wx = true, |
| .ptdump = { |
| - .note_page = note_page, |
| + .note_page_pte = note_page_pte, |
| + .note_page_pmd = note_page_pmd, |
| + .note_page_pud = note_page_pud, |
| + .note_page_p4d = note_page_p4d, |
| + .note_page_pgd = note_page_pgd, |
| + .note_page_flush = note_page_flush, |
| .range = ptdump_range, |
| } |
| }; |
| --- a/arch/riscv/mm/ptdump.c~mm-ptdump-split-note_page-into-level-specific-callbacks |
| +++ a/arch/riscv/mm/ptdump.c |
| @@ -318,6 +318,38 @@ static void note_page(struct ptdump_stat |
| } |
| } |
| |
| +static void note_page_pte(struct ptdump_state *pt_st, unsigned long addr, pte_t pte) |
| +{ |
| + note_page(pt_st, addr, 4, pte_val(pte)); |
| +} |
| + |
| +static void note_page_pmd(struct ptdump_state *pt_st, unsigned long addr, pmd_t pmd) |
| +{ |
| + note_page(pt_st, addr, 3, pmd_val(pmd)); |
| +} |
| + |
| +static void note_page_pud(struct ptdump_state *pt_st, unsigned long addr, pud_t pud) |
| +{ |
| + note_page(pt_st, addr, 2, pud_val(pud)); |
| +} |
| + |
| +static void note_page_p4d(struct ptdump_state *pt_st, unsigned long addr, p4d_t p4d) |
| +{ |
| + note_page(pt_st, addr, 1, p4d_val(p4d)); |
| +} |
| + |
| +static void note_page_pgd(struct ptdump_state *pt_st, unsigned long addr, pgd_t pgd) |
| +{ |
| + note_page(pt_st, addr, 0, pgd_val(pgd)); |
| +} |
| + |
| +static void note_page_flush(struct ptdump_state *pt_st) |
| +{ |
| + pte_t pte_zero = {0}; |
| + |
| + note_page(pt_st, 0, -1, pte_val(pte_zero)); |
| +} |
| + |
| static void ptdump_walk(struct seq_file *s, struct ptd_mm_info *pinfo) |
| { |
| struct pg_state st = { |
| @@ -325,7 +357,12 @@ static void ptdump_walk(struct seq_file |
| .marker = pinfo->markers, |
| .level = -1, |
| .ptdump = { |
| - .note_page = note_page, |
| + .note_page_pte = note_page_pte, |
| + .note_page_pmd = note_page_pmd, |
| + .note_page_pud = note_page_pud, |
| + .note_page_p4d = note_page_p4d, |
| + .note_page_pgd = note_page_pgd, |
| + .note_page_flush = note_page_flush, |
| .range = (struct ptdump_range[]) { |
| {pinfo->base_addr, pinfo->end}, |
| {0, 0} |
| @@ -347,7 +384,12 @@ bool ptdump_check_wx(void) |
| .level = -1, |
| .check_wx = true, |
| .ptdump = { |
| - .note_page = note_page, |
| + .note_page_pte = note_page_pte, |
| + .note_page_pmd = note_page_pmd, |
| + .note_page_pud = note_page_pud, |
| + .note_page_p4d = note_page_p4d, |
| + .note_page_pgd = note_page_pgd, |
| + .note_page_flush = note_page_flush, |
| .range = (struct ptdump_range[]) { |
| {KERN_VIRT_START, ULONG_MAX}, |
| {0, 0} |
| --- a/arch/s390/mm/dump_pagetables.c~mm-ptdump-split-note_page-into-level-specific-callbacks |
| +++ a/arch/s390/mm/dump_pagetables.c |
| @@ -147,11 +147,48 @@ static void note_page(struct ptdump_stat |
| } |
| } |
| |
| +static void note_page_pte(struct ptdump_state *pt_st, unsigned long addr, pte_t pte) |
| +{ |
| + note_page(pt_st, addr, 4, pte_val(pte)); |
| +} |
| + |
| +static void note_page_pmd(struct ptdump_state *pt_st, unsigned long addr, pmd_t pmd) |
| +{ |
| + note_page(pt_st, addr, 3, pmd_val(pmd)); |
| +} |
| + |
| +static void note_page_pud(struct ptdump_state *pt_st, unsigned long addr, pud_t pud) |
| +{ |
| + note_page(pt_st, addr, 2, pud_val(pud)); |
| +} |
| + |
| +static void note_page_p4d(struct ptdump_state *pt_st, unsigned long addr, p4d_t p4d) |
| +{ |
| + note_page(pt_st, addr, 1, p4d_val(p4d)); |
| +} |
| + |
| +static void note_page_pgd(struct ptdump_state *pt_st, unsigned long addr, pgd_t pgd) |
| +{ |
| + note_page(pt_st, addr, 0, pgd_val(pgd)); |
| +} |
| + |
| +static void note_page_flush(struct ptdump_state *pt_st) |
| +{ |
| + pte_t pte_zero = {0}; |
| + |
| + note_page(pt_st, 0, -1, pte_val(pte_zero)); |
| +} |
| + |
| bool ptdump_check_wx(void) |
| { |
| struct pg_state st = { |
| .ptdump = { |
| - .note_page = note_page, |
| + .note_page_pte = note_page_pte, |
| + .note_page_pmd = note_page_pmd, |
| + .note_page_pud = note_page_pud, |
| + .note_page_p4d = note_page_p4d, |
| + .note_page_pgd = note_page_pgd, |
| + .note_page_flush = note_page_flush, |
| .range = (struct ptdump_range[]) { |
| {.start = 0, .end = max_addr}, |
| {.start = 0, .end = 0}, |
| @@ -190,7 +227,12 @@ static int ptdump_show(struct seq_file * |
| { |
| struct pg_state st = { |
| .ptdump = { |
| - .note_page = note_page, |
| + .note_page_pte = note_page_pte, |
| + .note_page_pmd = note_page_pmd, |
| + .note_page_pud = note_page_pud, |
| + .note_page_p4d = note_page_p4d, |
| + .note_page_pgd = note_page_pgd, |
| + .note_page_flush = note_page_flush, |
| .range = (struct ptdump_range[]) { |
| {.start = 0, .end = max_addr}, |
| {.start = 0, .end = 0}, |
| --- a/arch/x86/mm/dump_pagetables.c~mm-ptdump-split-note_page-into-level-specific-callbacks |
| +++ a/arch/x86/mm/dump_pagetables.c |
| @@ -362,6 +362,38 @@ static void note_page(struct ptdump_stat |
| } |
| } |
| |
| +static void note_page_pte(struct ptdump_state *pt_st, unsigned long addr, pte_t pte) |
| +{ |
| + note_page(pt_st, addr, 4, pte_val(pte)); |
| +} |
| + |
| +static void note_page_pmd(struct ptdump_state *pt_st, unsigned long addr, pmd_t pmd) |
| +{ |
| + note_page(pt_st, addr, 3, pmd_val(pmd)); |
| +} |
| + |
| +static void note_page_pud(struct ptdump_state *pt_st, unsigned long addr, pud_t pud) |
| +{ |
| + note_page(pt_st, addr, 2, pud_val(pud)); |
| +} |
| + |
| +static void note_page_p4d(struct ptdump_state *pt_st, unsigned long addr, p4d_t p4d) |
| +{ |
| + note_page(pt_st, addr, 1, p4d_val(p4d)); |
| +} |
| + |
| +static void note_page_pgd(struct ptdump_state *pt_st, unsigned long addr, pgd_t pgd) |
| +{ |
| + note_page(pt_st, addr, 0, pgd_val(pgd)); |
| +} |
| + |
| +static void note_page_flush(struct ptdump_state *pt_st) |
| +{ |
| + pte_t pte_zero = {0}; |
| + |
| + note_page(pt_st, 0, -1, pte_val(pte_zero)); |
| +} |
| + |
| bool ptdump_walk_pgd_level_core(struct seq_file *m, |
| struct mm_struct *mm, pgd_t *pgd, |
| bool checkwx, bool dmesg) |
| @@ -378,7 +410,12 @@ bool ptdump_walk_pgd_level_core(struct s |
| |
| struct pg_state st = { |
| .ptdump = { |
| - .note_page = note_page, |
| + .note_page_pte = note_page_pte, |
| + .note_page_pmd = note_page_pmd, |
| + .note_page_pud = note_page_pud, |
| + .note_page_p4d = note_page_p4d, |
| + .note_page_pgd = note_page_pgd, |
| + .note_page_flush = note_page_flush, |
| .effective_prot = effective_prot, |
| .range = ptdump_ranges |
| }, |
| --- a/include/linux/ptdump.h~mm-ptdump-split-note_page-into-level-specific-callbacks |
| +++ a/include/linux/ptdump.h |
| @@ -11,9 +11,12 @@ struct ptdump_range { |
| }; |
| |
| struct ptdump_state { |
| - /* level is 0:PGD to 4:PTE, or -1 if unknown */ |
| - void (*note_page)(struct ptdump_state *st, unsigned long addr, |
| - int level, u64 val); |
| + void (*note_page_pte)(struct ptdump_state *st, unsigned long addr, pte_t pte); |
| + void (*note_page_pmd)(struct ptdump_state *st, unsigned long addr, pmd_t pmd); |
| + void (*note_page_pud)(struct ptdump_state *st, unsigned long addr, pud_t pud); |
| + void (*note_page_p4d)(struct ptdump_state *st, unsigned long addr, p4d_t p4d); |
| + void (*note_page_pgd)(struct ptdump_state *st, unsigned long addr, pgd_t pgd); |
| + void (*note_page_flush)(struct ptdump_state *st); |
| void (*effective_prot)(struct ptdump_state *st, int level, u64 val); |
| const struct ptdump_range *range; |
| }; |
| --- a/mm/ptdump.c~mm-ptdump-split-note_page-into-level-specific-callbacks |
| +++ a/mm/ptdump.c |
| @@ -18,7 +18,7 @@ static inline int note_kasan_page_table( |
| { |
| struct ptdump_state *st = walk->private; |
| |
| - st->note_page(st, addr, 4, pte_val(kasan_early_shadow_pte[0])); |
| + st->note_page_pte(st, addr, kasan_early_shadow_pte[0]); |
| |
| walk->action = ACTION_CONTINUE; |
| |
| @@ -42,7 +42,7 @@ static int ptdump_pgd_entry(pgd_t *pgd, |
| st->effective_prot(st, 0, pgd_val(val)); |
| |
| if (pgd_leaf(val)) { |
| - st->note_page(st, addr, 0, pgd_val(val)); |
| + st->note_page_pgd(st, addr, val); |
| walk->action = ACTION_CONTINUE; |
| } |
| |
| @@ -65,7 +65,7 @@ static int ptdump_p4d_entry(p4d_t *p4d, |
| st->effective_prot(st, 1, p4d_val(val)); |
| |
| if (p4d_leaf(val)) { |
| - st->note_page(st, addr, 1, p4d_val(val)); |
| + st->note_page_p4d(st, addr, val); |
| walk->action = ACTION_CONTINUE; |
| } |
| |
| @@ -88,7 +88,7 @@ static int ptdump_pud_entry(pud_t *pud, |
| st->effective_prot(st, 2, pud_val(val)); |
| |
| if (pud_leaf(val)) { |
| - st->note_page(st, addr, 2, pud_val(val)); |
| + st->note_page_pud(st, addr, val); |
| walk->action = ACTION_CONTINUE; |
| } |
| |
| @@ -109,7 +109,7 @@ static int ptdump_pmd_entry(pmd_t *pmd, |
| if (st->effective_prot) |
| st->effective_prot(st, 3, pmd_val(val)); |
| if (pmd_leaf(val)) { |
| - st->note_page(st, addr, 3, pmd_val(val)); |
| + st->note_page_pmd(st, addr, val); |
| walk->action = ACTION_CONTINUE; |
| } |
| |
| @@ -125,7 +125,7 @@ static int ptdump_pte_entry(pte_t *pte, |
| if (st->effective_prot) |
| st->effective_prot(st, 4, pte_val(val)); |
| |
| - st->note_page(st, addr, 4, pte_val(val)); |
| + st->note_page_pte(st, addr, val); |
| |
| return 0; |
| } |
| @@ -134,9 +134,31 @@ static int ptdump_hole(unsigned long add |
| int depth, struct mm_walk *walk) |
| { |
| struct ptdump_state *st = walk->private; |
| - |
| - st->note_page(st, addr, depth, 0); |
| - |
| + pte_t pte_zero = {0}; |
| + pmd_t pmd_zero = {0}; |
| + pud_t pud_zero = {0}; |
| + p4d_t p4d_zero = {0}; |
| + pgd_t pgd_zero = {0}; |
| + |
| + switch (depth) { |
| + case 4: |
| + st->note_page_pte(st, addr, pte_zero); |
| + break; |
| + case 3: |
| + st->note_page_pmd(st, addr, pmd_zero); |
| + break; |
| + case 2: |
| + st->note_page_pud(st, addr, pud_zero); |
| + break; |
| + case 1: |
| + st->note_page_p4d(st, addr, p4d_zero); |
| + break; |
| + case 0: |
| + st->note_page_pgd(st, addr, pgd_zero); |
| + break; |
| + default: |
| + break; |
| + } |
| return 0; |
| } |
| |
| @@ -162,7 +184,7 @@ void ptdump_walk_pgd(struct ptdump_state |
| mmap_write_unlock(mm); |
| |
| /* Flush out the last page */ |
| - st->note_page(st, 0, -1, 0); |
| + st->note_page_flush(st); |
| } |
| |
| static int check_wx_show(struct seq_file *m, void *v) |
| _ |