* [PATCH 0/2] mm/ptdump: Drop assumption that pxd_val() is u64 @ 2025-03-17 6:18 Anshuman Khandual 2025-03-17 6:18 ` [PATCH 1/2] mm/ptdump: Split note_page() into level specific callbacks Anshuman Khandual 2025-03-17 6:18 ` [PATCH 2/2] arm64/ptdump: Replace u64 with pteval_t Anshuman Khandual 0 siblings, 2 replies; 8+ messages in thread From: Anshuman Khandual @ 2025-03-17 6:18 UTC (permalink / raw) To: linux-mm Cc: Anshuman Khandual, Catalin Marinas, Will Deacon, Steven Price, Ryan Roberts, Madhavan Srinivasan, Nicholas Piggin, Paul Walmsley, Palmer Dabbelt, Gerald Schaefer, Heiko Carstens, Peter Zijlstra, Thomas Gleixner, Ingo Molnar, Andrew Morton, linux-arm-kernel, linux-kernel, linuxppc-dev, linux-riscv, linux-s390 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. This series splits note_page() into individual page table level specific callbacks which accepts corresponding pxd_t page table entry as an argument instead and later all subscribing platforms could derive pxd_val() from the entries as required and proceed as before. Page table entry's value, mask and protection are represented with pteval_t not u64 that has been assumed while dumping the page table entries on arm64 platform. Replace such u64 instances with pteval_t instead as expected. This series has been tested on arm64 platform but it does build on other relevant platforms (v6.14-rc7). Changes in V1: - Added note_page_flush() callback and implemented the same on all subscribing platforms - Moved note_page() argument change from u64 to pteval_t on arm64 platform from second patch to the first patch instead Changes in RFC: https://lore.kernel.org/all/20250310095902.390664-1-anshuman.khandual@arm.com/ Cc: Catalin Marinas <catalin.marinas@arm.com> Cc: Will Deacon <will@kernel.org> Cc: Steven Price <steven.price@arm.com> Cc: Ryan Roberts <ryan.roberts@arm.com> 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: Andrew Morton <akpm@linux-foundation.org> Cc: linux-arm-kernel@lists.infradead.org Cc: linux-kernel@vger.kernel.org Cc: linuxppc-dev@lists.ozlabs.org Cc: linux-riscv@lists.infradead.org Cc: linux-s390@vger.kernel.org Cc: linux-mm@kvack.org Anshuman Khandual (2): mm/ptdump: Split note_page() into level specific callbacks arm64/ptdump: Replace u64 with pteval_t arch/arm64/include/asm/ptdump.h | 24 ++++++++++++---- arch/arm64/mm/ptdump.c | 50 ++++++++++++++++++++++++++++++--- 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, 272 insertions(+), 30 deletions(-) -- 2.25.1 ^ permalink raw reply [flat|nested] 8+ messages in thread
* [PATCH 1/2] mm/ptdump: Split note_page() into level specific callbacks 2025-03-17 6:18 [PATCH 0/2] mm/ptdump: Drop assumption that pxd_val() is u64 Anshuman Khandual @ 2025-03-17 6:18 ` Anshuman Khandual 2025-03-21 3:37 ` Anshuman Khandual 2025-03-31 8:59 ` Alexander Gordeev 2025-03-17 6:18 ` [PATCH 2/2] arm64/ptdump: Replace u64 with pteval_t Anshuman Khandual 1 sibling, 2 replies; 8+ messages in thread From: Anshuman Khandual @ 2025-03-17 6:18 UTC (permalink / raw) To: linux-mm Cc: Anshuman Khandual, Catalin Marinas, Will Deacon, Steven Price, Ryan Roberts, Madhavan Srinivasan, Nicholas Piggin, Paul Walmsley, Palmer Dabbelt, Gerald Schaefer, Heiko Carstens, Peter Zijlstra, Thomas Gleixner, Ingo Molnar, Andrew Morton, linux-arm-kernel, linux-kernel, linuxppc-dev, linux-riscv, linux-s390 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. 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: Andrew Morton <akpm@linux-foundation.org> Cc: linux-arm-kernel@lists.infradead.org Cc: linux-kernel@vger.kernel.org Cc: linuxppc-dev@lists.ozlabs.org Cc: linux-riscv@lists.infradead.org Cc: linux-s390@vger.kernel.org Cc: linux-mm@kvack.org Signed-off-by: Anshuman Khandual <anshuman.khandual@arm.com> --- 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(-) diff --git a/arch/arm64/include/asm/ptdump.h b/arch/arm64/include/asm/ptdump.h index 6cf4aae05219..e5da9ce8a515 100644 --- a/arch/arm64/include/asm/ptdump.h +++ b/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_register(struct ptdump_info *info, #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_CORE */ #endif /* __ASM_PTDUMP_H */ diff --git a/arch/arm64/mm/ptdump.c b/arch/arm64/mm/ptdump.c index 688fbe0271ca..fd1610b4fd15 100644 --- a/arch/arm64/mm/ptdump.c +++ b/arch/arm64/mm/ptdump.c @@ -189,7 +189,7 @@ static void note_prot_wx(struct ptdump_pg_state *st, unsigned long addr) } 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_st, unsigned long addr, int level, } +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, struct ptdump_info *info) .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} diff --git a/arch/powerpc/mm/ptdump/ptdump.c b/arch/powerpc/mm/ptdump/ptdump.c index 9dc239967b77..b2358d794855 100644 --- a/arch/powerpc/mm/ptdump/ptdump.c +++ b/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 *m, void *v) .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, } }; diff --git a/arch/riscv/mm/ptdump.c b/arch/riscv/mm/ptdump.c index 9d5f657a251b..32922550a50a 100644 --- a/arch/riscv/mm/ptdump.c +++ b/arch/riscv/mm/ptdump.c @@ -318,6 +318,38 @@ static void note_page(struct ptdump_state *pt_st, unsigned long addr, } } +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 *s, struct ptd_mm_info *pinfo) .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} diff --git a/arch/s390/mm/dump_pagetables.c b/arch/s390/mm/dump_pagetables.c index fa54f3bc0c8d..e7cc52542f71 100644 --- a/arch/s390/mm/dump_pagetables.c +++ b/arch/s390/mm/dump_pagetables.c @@ -145,11 +145,48 @@ static void note_page(struct ptdump_state *pt_st, unsigned long addr, int level, } } +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}, @@ -188,7 +225,12 @@ static int ptdump_show(struct seq_file *m, void *v) { 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}, diff --git a/arch/x86/mm/dump_pagetables.c b/arch/x86/mm/dump_pagetables.c index 89079ea73e65..2e1c2d006ace 100644 --- a/arch/x86/mm/dump_pagetables.c +++ b/arch/x86/mm/dump_pagetables.c @@ -362,6 +362,38 @@ static void note_page(struct ptdump_state *pt_st, unsigned long addr, int level, } } +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 seq_file *m, 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 }, diff --git a/include/linux/ptdump.h b/include/linux/ptdump.h index 8dbd51ea8626..1c1eb1fae199 100644 --- a/include/linux/ptdump.h +++ b/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; }; diff --git a/mm/ptdump.c b/mm/ptdump.c index 106e1d66e9f9..706cfc19439b 100644 --- a/mm/ptdump.c +++ b/mm/ptdump.c @@ -18,7 +18,7 @@ static inline int note_kasan_page_table(struct mm_walk *walk, { 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, unsigned long addr, 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, unsigned long addr, 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, unsigned long addr, 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, unsigned long addr, 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, unsigned long addr, 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 addr, unsigned long next, 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 *st, struct mm_struct *mm, pgd_t *pgd) 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) -- 2.25.1 ^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH 1/2] mm/ptdump: Split note_page() into level specific callbacks 2025-03-17 6:18 ` [PATCH 1/2] mm/ptdump: Split note_page() into level specific callbacks Anshuman Khandual @ 2025-03-21 3:37 ` Anshuman Khandual 2025-03-31 8:59 ` Alexander Gordeev 1 sibling, 0 replies; 8+ messages in thread From: Anshuman Khandual @ 2025-03-21 3:37 UTC (permalink / raw) To: linux-mm Cc: Catalin Marinas, Will Deacon, Steven Price, Ryan Roberts, Madhavan Srinivasan, Nicholas Piggin, Paul Walmsley, Palmer Dabbelt, Gerald Schaefer, Heiko Carstens, Peter Zijlstra, Thomas Gleixner, Ingo Molnar, Andrew Morton, linux-arm-kernel, linux-kernel, linuxppc-dev, linux-riscv, linux-s390 On 3/17/25 11:48, Anshuman Khandual wrote: > 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. Does this look good OR is there any concern OR an alternate approach ? > > 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: Andrew Morton <akpm@linux-foundation.org> > Cc: linux-arm-kernel@lists.infradead.org > Cc: linux-kernel@vger.kernel.org > Cc: linuxppc-dev@lists.ozlabs.org > Cc: linux-riscv@lists.infradead.org > Cc: linux-s390@vger.kernel.org > Cc: linux-mm@kvack.org > Signed-off-by: Anshuman Khandual <anshuman.khandual@arm.com> > --- > 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(-) > > diff --git a/arch/arm64/include/asm/ptdump.h b/arch/arm64/include/asm/ptdump.h > index 6cf4aae05219..e5da9ce8a515 100644 > --- a/arch/arm64/include/asm/ptdump.h > +++ b/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_register(struct ptdump_info *info, > #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_CORE */ > > #endif /* __ASM_PTDUMP_H */ > diff --git a/arch/arm64/mm/ptdump.c b/arch/arm64/mm/ptdump.c > index 688fbe0271ca..fd1610b4fd15 100644 > --- a/arch/arm64/mm/ptdump.c > +++ b/arch/arm64/mm/ptdump.c > @@ -189,7 +189,7 @@ static void note_prot_wx(struct ptdump_pg_state *st, unsigned long addr) > } > > 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_st, unsigned long addr, int level, > > } > > +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, struct ptdump_info *info) > .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} > diff --git a/arch/powerpc/mm/ptdump/ptdump.c b/arch/powerpc/mm/ptdump/ptdump.c > index 9dc239967b77..b2358d794855 100644 > --- a/arch/powerpc/mm/ptdump/ptdump.c > +++ b/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 *m, void *v) > .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, > } > }; > diff --git a/arch/riscv/mm/ptdump.c b/arch/riscv/mm/ptdump.c > index 9d5f657a251b..32922550a50a 100644 > --- a/arch/riscv/mm/ptdump.c > +++ b/arch/riscv/mm/ptdump.c > @@ -318,6 +318,38 @@ static void note_page(struct ptdump_state *pt_st, unsigned long addr, > } > } > > +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 *s, struct ptd_mm_info *pinfo) > .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} > diff --git a/arch/s390/mm/dump_pagetables.c b/arch/s390/mm/dump_pagetables.c > index fa54f3bc0c8d..e7cc52542f71 100644 > --- a/arch/s390/mm/dump_pagetables.c > +++ b/arch/s390/mm/dump_pagetables.c > @@ -145,11 +145,48 @@ static void note_page(struct ptdump_state *pt_st, unsigned long addr, int level, > } > } > > +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}, > @@ -188,7 +225,12 @@ static int ptdump_show(struct seq_file *m, void *v) > { > 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}, > diff --git a/arch/x86/mm/dump_pagetables.c b/arch/x86/mm/dump_pagetables.c > index 89079ea73e65..2e1c2d006ace 100644 > --- a/arch/x86/mm/dump_pagetables.c > +++ b/arch/x86/mm/dump_pagetables.c > @@ -362,6 +362,38 @@ static void note_page(struct ptdump_state *pt_st, unsigned long addr, int level, > } > } > > +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 seq_file *m, > > 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 > }, > diff --git a/include/linux/ptdump.h b/include/linux/ptdump.h > index 8dbd51ea8626..1c1eb1fae199 100644 > --- a/include/linux/ptdump.h > +++ b/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; > }; > diff --git a/mm/ptdump.c b/mm/ptdump.c > index 106e1d66e9f9..706cfc19439b 100644 > --- a/mm/ptdump.c > +++ b/mm/ptdump.c > @@ -18,7 +18,7 @@ static inline int note_kasan_page_table(struct mm_walk *walk, > { > 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, unsigned long addr, > 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, unsigned long addr, > 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, unsigned long addr, > 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, unsigned long addr, > 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, unsigned long addr, > 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 addr, unsigned long next, > 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 *st, struct mm_struct *mm, pgd_t *pgd) > 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) ^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH 1/2] mm/ptdump: Split note_page() into level specific callbacks 2025-03-17 6:18 ` [PATCH 1/2] mm/ptdump: Split note_page() into level specific callbacks Anshuman Khandual 2025-03-21 3:37 ` Anshuman Khandual @ 2025-03-31 8:59 ` Alexander Gordeev 2025-04-01 2:51 ` Anshuman Khandual 1 sibling, 1 reply; 8+ messages in thread From: Alexander Gordeev @ 2025-03-31 8:59 UTC (permalink / raw) To: Anshuman Khandual Cc: linux-mm, Catalin Marinas, Will Deacon, Steven Price, Ryan Roberts, Madhavan Srinivasan, Nicholas Piggin, Paul Walmsley, Palmer Dabbelt, Gerald Schaefer, Heiko Carstens, Peter Zijlstra, Thomas Gleixner, Ingo Molnar, Andrew Morton, linux-arm-kernel, linux-kernel, linuxppc-dev, linux-riscv, linux-s390 On Mon, Mar 17, 2025 at 11:48:17AM +0530, Anshuman Khandual wrote: Hi Anshuman, ... > --- a/include/linux/ptdump.h > +++ b/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); Should you treat effective_prot() similarly? > const struct ptdump_range *range; > }; ^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH 1/2] mm/ptdump: Split note_page() into level specific callbacks 2025-03-31 8:59 ` Alexander Gordeev @ 2025-04-01 2:51 ` Anshuman Khandual 0 siblings, 0 replies; 8+ messages in thread From: Anshuman Khandual @ 2025-04-01 2:51 UTC (permalink / raw) To: Alexander Gordeev Cc: linux-mm, Catalin Marinas, Will Deacon, Steven Price, Ryan Roberts, Madhavan Srinivasan, Nicholas Piggin, Paul Walmsley, Palmer Dabbelt, Gerald Schaefer, Heiko Carstens, Peter Zijlstra, Thomas Gleixner, Ingo Molnar, Andrew Morton, linux-arm-kernel, linux-kernel, linuxppc-dev, linux-riscv, linux-s390 On 3/31/25 14:29, Alexander Gordeev wrote: > On Mon, Mar 17, 2025 at 11:48:17AM +0530, Anshuman Khandual wrote: > > Hi Anshuman, > > ... >> --- a/include/linux/ptdump.h >> +++ b/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); > > Should you treat effective_prot() similarly? Agreed. effective_prot() also uses pxd_val() derived data type in generic MM and might cause the same problem later going ahead. Will split the helper into level specific callbacks as well. > >> const struct ptdump_range *range; >> }; ^ permalink raw reply [flat|nested] 8+ messages in thread
* [PATCH 2/2] arm64/ptdump: Replace u64 with pteval_t 2025-03-17 6:18 [PATCH 0/2] mm/ptdump: Drop assumption that pxd_val() is u64 Anshuman Khandual 2025-03-17 6:18 ` [PATCH 1/2] mm/ptdump: Split note_page() into level specific callbacks Anshuman Khandual @ 2025-03-17 6:18 ` Anshuman Khandual 2025-03-17 9:28 ` Ryan Roberts 1 sibling, 1 reply; 8+ messages in thread From: Anshuman Khandual @ 2025-03-17 6:18 UTC (permalink / raw) To: linux-mm Cc: Anshuman Khandual, Catalin Marinas, Will Deacon, Steven Price, Ryan Roberts, Madhavan Srinivasan, Nicholas Piggin, Paul Walmsley, Palmer Dabbelt, Gerald Schaefer, Heiko Carstens, Peter Zijlstra, Thomas Gleixner, Ingo Molnar, Andrew Morton, linux-arm-kernel, linux-kernel, linuxppc-dev, linux-riscv, linux-s390, Marc Zyngier Page table entry's value, mask and protection are represented with pteval_t data type format not u64 that has been assumed while dumping the page table entries. Replace all such u64 instances with pteval_t instead as required. Cc: Catalin Marinas <catalin.marinas@arm.com> Cc: Will Deacon <will@kernel.org> Cc: Marc Zyngier <maz@kernel.org> Cc: linux-arm-kernel@lists.infradead.org Cc: linux-kernel@vger.kernel.org Signed-off-by: Anshuman Khandual <anshuman.khandual@arm.com> --- arch/arm64/include/asm/ptdump.h | 8 ++++---- arch/arm64/mm/ptdump.c | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/arch/arm64/include/asm/ptdump.h b/arch/arm64/include/asm/ptdump.h index e5da9ce8a515..476a870489b9 100644 --- a/arch/arm64/include/asm/ptdump.h +++ b/arch/arm64/include/asm/ptdump.h @@ -24,8 +24,8 @@ struct ptdump_info { }; struct ptdump_prot_bits { - u64 mask; - u64 val; + pteval_t mask; + pteval_t val; const char *set; const char *clear; }; @@ -34,7 +34,7 @@ struct ptdump_pg_level { const struct ptdump_prot_bits *bits; char name[4]; int num; - u64 mask; + pteval_t mask; }; /* @@ -51,7 +51,7 @@ struct ptdump_pg_state { const struct mm_struct *mm; unsigned long start_address; int level; - u64 current_prot; + pteval_t current_prot; bool check_wx; unsigned long wx_pages; unsigned long uxn_pages; diff --git a/arch/arm64/mm/ptdump.c b/arch/arm64/mm/ptdump.c index fd1610b4fd15..a5651be95868 100644 --- a/arch/arm64/mm/ptdump.c +++ b/arch/arm64/mm/ptdump.c @@ -194,7 +194,7 @@ void note_page(struct ptdump_state *pt_st, unsigned long addr, int level, struct ptdump_pg_state *st = container_of(pt_st, struct ptdump_pg_state, ptdump); struct ptdump_pg_level *pg_level = st->pg_level; static const char units[] = "KMGTPE"; - u64 prot = 0; + pteval_t prot = 0; /* check if the current level has been folded dynamically */ if (st->mm && ((level == 1 && mm_p4d_folded(st->mm)) || -- 2.25.1 ^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH 2/2] arm64/ptdump: Replace u64 with pteval_t 2025-03-17 6:18 ` [PATCH 2/2] arm64/ptdump: Replace u64 with pteval_t Anshuman Khandual @ 2025-03-17 9:28 ` Ryan Roberts 2025-03-18 4:37 ` Anshuman Khandual 0 siblings, 1 reply; 8+ messages in thread From: Ryan Roberts @ 2025-03-17 9:28 UTC (permalink / raw) To: Anshuman Khandual, linux-mm Cc: Catalin Marinas, Will Deacon, Steven Price, Madhavan Srinivasan, Nicholas Piggin, Paul Walmsley, Palmer Dabbelt, Gerald Schaefer, Heiko Carstens, Peter Zijlstra, Thomas Gleixner, Ingo Molnar, Andrew Morton, linux-arm-kernel, linux-kernel, linuxppc-dev, linux-riscv, linux-s390, Marc Zyngier On 17/03/2025 06:18, Anshuman Khandual wrote: > Page table entry's value, mask and protection are represented with pteval_t > data type format not u64 that has been assumed while dumping the page table > entries. Replace all such u64 instances with pteval_t instead as required. > > Cc: Catalin Marinas <catalin.marinas@arm.com> > Cc: Will Deacon <will@kernel.org> > Cc: Marc Zyngier <maz@kernel.org> > Cc: linux-arm-kernel@lists.infradead.org > Cc: linux-kernel@vger.kernel.org > Signed-off-by: Anshuman Khandual <anshuman.khandual@arm.com> > --- > arch/arm64/include/asm/ptdump.h | 8 ++++---- > arch/arm64/mm/ptdump.c | 2 +- > 2 files changed, 5 insertions(+), 5 deletions(-) > > diff --git a/arch/arm64/include/asm/ptdump.h b/arch/arm64/include/asm/ptdump.h > index e5da9ce8a515..476a870489b9 100644 > --- a/arch/arm64/include/asm/ptdump.h > +++ b/arch/arm64/include/asm/ptdump.h > @@ -24,8 +24,8 @@ struct ptdump_info { > }; > > struct ptdump_prot_bits { > - u64 mask; > - u64 val; > + pteval_t mask; > + pteval_t val; Given Ard's suggestion of using "ptdesc" as a generic term for PTDESC_SHIFT (or PTDESC_ORDER, or whatever we ended up calling it), I wonder if it would be cleaner to do the same with the types? We could have a ptdesc_t, which is typedef'ed as u64 (or u128), then pteval_t, pmdval_t, ..., could all be typedef'ed as ptdesc_t. Then for code that just wants a generic pgtable descriptor value, we can use that type to indicate that it can be at any level. Thanks, Ryan > const char *set; > const char *clear; > }; > @@ -34,7 +34,7 @@ struct ptdump_pg_level { > const struct ptdump_prot_bits *bits; > char name[4]; > int num; > - u64 mask; > + pteval_t mask; > }; > > /* > @@ -51,7 +51,7 @@ struct ptdump_pg_state { > const struct mm_struct *mm; > unsigned long start_address; > int level; > - u64 current_prot; > + pteval_t current_prot; > bool check_wx; > unsigned long wx_pages; > unsigned long uxn_pages; > diff --git a/arch/arm64/mm/ptdump.c b/arch/arm64/mm/ptdump.c > index fd1610b4fd15..a5651be95868 100644 > --- a/arch/arm64/mm/ptdump.c > +++ b/arch/arm64/mm/ptdump.c > @@ -194,7 +194,7 @@ void note_page(struct ptdump_state *pt_st, unsigned long addr, int level, > struct ptdump_pg_state *st = container_of(pt_st, struct ptdump_pg_state, ptdump); > struct ptdump_pg_level *pg_level = st->pg_level; > static const char units[] = "KMGTPE"; > - u64 prot = 0; > + pteval_t prot = 0; > > /* check if the current level has been folded dynamically */ > if (st->mm && ((level == 1 && mm_p4d_folded(st->mm)) || ^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH 2/2] arm64/ptdump: Replace u64 with pteval_t 2025-03-17 9:28 ` Ryan Roberts @ 2025-03-18 4:37 ` Anshuman Khandual 0 siblings, 0 replies; 8+ messages in thread From: Anshuman Khandual @ 2025-03-18 4:37 UTC (permalink / raw) To: Ryan Roberts, linux-mm Cc: Catalin Marinas, Will Deacon, Steven Price, Madhavan Srinivasan, Nicholas Piggin, Paul Walmsley, Palmer Dabbelt, Gerald Schaefer, Heiko Carstens, Peter Zijlstra, Thomas Gleixner, Ingo Molnar, Andrew Morton, linux-arm-kernel, linux-kernel, linuxppc-dev, linux-riscv, linux-s390, Marc Zyngier On 3/17/25 14:58, Ryan Roberts wrote: > On 17/03/2025 06:18, Anshuman Khandual wrote: >> Page table entry's value, mask and protection are represented with pteval_t >> data type format not u64 that has been assumed while dumping the page table >> entries. Replace all such u64 instances with pteval_t instead as required. >> >> Cc: Catalin Marinas <catalin.marinas@arm.com> >> Cc: Will Deacon <will@kernel.org> >> Cc: Marc Zyngier <maz@kernel.org> >> Cc: linux-arm-kernel@lists.infradead.org >> Cc: linux-kernel@vger.kernel.org >> Signed-off-by: Anshuman Khandual <anshuman.khandual@arm.com> >> --- >> arch/arm64/include/asm/ptdump.h | 8 ++++---- >> arch/arm64/mm/ptdump.c | 2 +- >> 2 files changed, 5 insertions(+), 5 deletions(-) >> >> diff --git a/arch/arm64/include/asm/ptdump.h b/arch/arm64/include/asm/ptdump.h >> index e5da9ce8a515..476a870489b9 100644 >> --- a/arch/arm64/include/asm/ptdump.h >> +++ b/arch/arm64/include/asm/ptdump.h >> @@ -24,8 +24,8 @@ struct ptdump_info { >> }; >> >> struct ptdump_prot_bits { >> - u64 mask; >> - u64 val; >> + pteval_t mask; >> + pteval_t val; > > Given Ard's suggestion of using "ptdesc" as a generic term for PTDESC_SHIFT (or > PTDESC_ORDER, or whatever we ended up calling it), I wonder if it would be > cleaner to do the same with the types? We could have a ptdesc_t, which is > typedef'ed as u64 (or u128), then pteval_t, pmdval_t, ..., could all be > typedef'ed as ptdesc_t. Then for code that just wants a generic pgtable > descriptor value, we can use that type to indicate that it can be at any level. Something like the following ? Will cross check again if this might have missed something which could be converted as ptdesc_t as well. diff --git a/arch/arm64/include/asm/pgtable-types.h b/arch/arm64/include/asm/pgtable-types.h index 6d6d4065b0cb..686541e986e3 100644 --- a/arch/arm64/include/asm/pgtable-types.h +++ b/arch/arm64/include/asm/pgtable-types.h @@ -11,11 +11,13 @@ #include <asm/types.h> -typedef u64 pteval_t; -typedef u64 pmdval_t; -typedef u64 pudval_t; -typedef u64 p4dval_t; -typedef u64 pgdval_t; +typedef u64 ptdesc_t; + +typedef ptdesc_t pteval_t; +typedef ptdesc_t pmdval_t; +typedef ptdesc_t pudval_t; +typedef ptdesc_t p4dval_t; +typedef ptdesc_t pgdval_t; /* * These are used to make use of C type-checking.. @@ -46,7 +48,7 @@ typedef struct { pgdval_t pgd; } pgd_t; #define pgd_val(x) ((x).pgd) #define __pgd(x) ((pgd_t) { (x) } ) -typedef struct { pteval_t pgprot; } pgprot_t; +typedef struct { ptdesc_t pgprot; } pgprot_t; #define pgprot_val(x) ((x).pgprot) #define __pgprot(x) ((pgprot_t) { (x) } ) diff --git a/arch/arm64/include/asm/ptdump.h b/arch/arm64/include/asm/ptdump.h index e5da9ce8a515..9548813bc877 100644 --- a/arch/arm64/include/asm/ptdump.h +++ b/arch/arm64/include/asm/ptdump.h @@ -24,8 +24,8 @@ struct ptdump_info { }; struct ptdump_prot_bits { - u64 mask; - u64 val; + ptdesc_t mask; + ptdesc_t val; const char *set; const char *clear; }; @@ -34,7 +34,7 @@ struct ptdump_pg_level { const struct ptdump_prot_bits *bits; char name[4]; int num; - u64 mask; + ptdesc_t mask; }; /* @@ -51,7 +51,7 @@ struct ptdump_pg_state { const struct mm_struct *mm; unsigned long start_address; int level; - u64 current_prot; + ptdesc_t current_prot; bool check_wx; unsigned long wx_pages; unsigned long uxn_pages; diff --git a/arch/arm64/kernel/efi.c b/arch/arm64/kernel/efi.c index 1d25d8899dbf..42e281c07c2f 100644 --- a/arch/arm64/kernel/efi.c +++ b/arch/arm64/kernel/efi.c @@ -29,7 +29,7 @@ static bool region_is_misaligned(const efi_memory_desc_t *md) * executable, everything else can be mapped with the XN bits * set. Also take the new (optional) RO/XP bits into account. */ -static __init pteval_t create_mapping_protection(efi_memory_desc_t *md) +static __init ptdesc_t create_mapping_protection(efi_memory_desc_t *md) { u64 attr = md->attribute; u32 type = md->type; @@ -83,7 +83,7 @@ static __init pteval_t create_mapping_protection(efi_memory_desc_t *md) int __init efi_create_mapping(struct mm_struct *mm, efi_memory_desc_t *md) { - pteval_t prot_val = create_mapping_protection(md); + ptdesc_t prot_val = create_mapping_protection(md); bool page_mappings_only = (md->type == EFI_RUNTIME_SERVICES_CODE || md->type == EFI_RUNTIME_SERVICES_DATA); diff --git a/arch/arm64/kernel/pi/map_kernel.c b/arch/arm64/kernel/pi/map_kernel.c index e57b043f324b..a00f57c73d81 100644 --- a/arch/arm64/kernel/pi/map_kernel.c +++ b/arch/arm64/kernel/pi/map_kernel.c @@ -159,7 +159,7 @@ static void noinline __section(".idmap.text") set_ttbr0_for_lpa2(u64 ttbr) static void __init remap_idmap_for_lpa2(void) { /* clear the bits that change meaning once LPA2 is turned on */ - pteval_t mask = PTE_SHARED; + ptdesc_t mask = PTE_SHARED; /* * We have to clear bits [9:8] in all block or page descriptors in the diff --git a/arch/arm64/kernel/pi/map_range.c b/arch/arm64/kernel/pi/map_range.c index 2b69e3beeef8..30c6bc50844f 100644 --- a/arch/arm64/kernel/pi/map_range.c +++ b/arch/arm64/kernel/pi/map_range.c @@ -30,7 +30,7 @@ void __init map_range(u64 *pte, u64 start, u64 end, u64 pa, pgprot_t prot, int level, pte_t *tbl, bool may_use_cont, u64 va_offset) { u64 cmask = (level == 3) ? CONT_PTE_SIZE - 1 : U64_MAX; - pteval_t protval = pgprot_val(prot) & ~PTE_TYPE_MASK; + ptdesc_t protval = pgprot_val(prot) & ~PTE_TYPE_MASK; int lshift = (3 - level) * (PAGE_SHIFT - 3); u64 lmask = (PAGE_SIZE << lshift) - 1; @@ -87,7 +87,7 @@ void __init map_range(u64 *pte, u64 start, u64 end, u64 pa, pgprot_t prot, } } -asmlinkage u64 __init create_init_idmap(pgd_t *pg_dir, pteval_t clrmask) +asmlinkage u64 __init create_init_idmap(pgd_t *pg_dir, ptdesc_t clrmask) { u64 ptep = (u64)pg_dir + PAGE_SIZE; pgprot_t text_prot = PAGE_KERNEL_ROX; diff --git a/arch/arm64/kernel/pi/pi.h b/arch/arm64/kernel/pi/pi.h index c91e5e965cd3..91dcb5b6bbd1 100644 --- a/arch/arm64/kernel/pi/pi.h +++ b/arch/arm64/kernel/pi/pi.h @@ -33,4 +33,4 @@ void map_range(u64 *pgd, u64 start, u64 end, u64 pa, pgprot_t prot, asmlinkage void early_map_kernel(u64 boot_status, void *fdt); -asmlinkage u64 create_init_idmap(pgd_t *pgd, pteval_t clrmask); +asmlinkage u64 create_init_idmap(pgd_t *pgd, ptdesc_t clrmask); diff --git a/arch/arm64/mm/mmap.c b/arch/arm64/mm/mmap.c index 07aeab8a7606..c86c348857c4 100644 --- a/arch/arm64/mm/mmap.c +++ b/arch/arm64/mm/mmap.c @@ -83,7 +83,7 @@ arch_initcall(adjust_protection_map); pgprot_t vm_get_page_prot(unsigned long vm_flags) { - pteval_t prot; + ptdesc_t prot; /* Short circuit GCS to avoid bloating the table. */ if (system_supports_gcs() && (vm_flags & VM_SHADOW_STACK)) { diff --git a/arch/arm64/mm/ptdump.c b/arch/arm64/mm/ptdump.c index fd1610b4fd15..280e850f1688 100644 --- a/arch/arm64/mm/ptdump.c +++ b/arch/arm64/mm/ptdump.c @@ -194,7 +194,7 @@ void note_page(struct ptdump_state *pt_st, unsigned long addr, int level, struct ptdump_pg_state *st = container_of(pt_st, struct ptdump_pg_state, ptdump); struct ptdump_pg_level *pg_level = st->pg_level; static const char units[] = "KMGTPE"; - u64 prot = 0; + ptdesc_t prot = 0; /* check if the current level has been folded dynamically */ if (st->mm && ((level == 1 && mm_p4d_folded(st->mm)) || -- 2.25.1 > > Thanks, > Ryan > >> const char *set; >> const char *clear; >> }; >> @@ -34,7 +34,7 @@ struct ptdump_pg_level { >> const struct ptdump_prot_bits *bits; >> char name[4]; >> int num; >> - u64 mask; >> + pteval_t mask; >> }; >> >> /* >> @@ -51,7 +51,7 @@ struct ptdump_pg_state { >> const struct mm_struct *mm; >> unsigned long start_address; >> int level; >> - u64 current_prot; >> + pteval_t current_prot; >> bool check_wx; >> unsigned long wx_pages; >> unsigned long uxn_pages; >> diff --git a/arch/arm64/mm/ptdump.c b/arch/arm64/mm/ptdump.c >> index fd1610b4fd15..a5651be95868 100644 >> --- a/arch/arm64/mm/ptdump.c >> +++ b/arch/arm64/mm/ptdump.c >> @@ -194,7 +194,7 @@ void note_page(struct ptdump_state *pt_st, unsigned long addr, int level, >> struct ptdump_pg_state *st = container_of(pt_st, struct ptdump_pg_state, ptdump); >> struct ptdump_pg_level *pg_level = st->pg_level; >> static const char units[] = "KMGTPE"; >> - u64 prot = 0; >> + pteval_t prot = 0; >> >> /* check if the current level has been folded dynamically */ >> if (st->mm && ((level == 1 && mm_p4d_folded(st->mm)) || > ^ permalink raw reply [flat|nested] 8+ messages in thread
end of thread, other threads:[~2025-04-01 2:51 UTC | newest] Thread overview: 8+ messages (download: mbox.gz / follow: Atom feed) -- links below jump to the message on this page -- 2025-03-17 6:18 [PATCH 0/2] mm/ptdump: Drop assumption that pxd_val() is u64 Anshuman Khandual 2025-03-17 6:18 ` [PATCH 1/2] mm/ptdump: Split note_page() into level specific callbacks Anshuman Khandual 2025-03-21 3:37 ` Anshuman Khandual 2025-03-31 8:59 ` Alexander Gordeev 2025-04-01 2:51 ` Anshuman Khandual 2025-03-17 6:18 ` [PATCH 2/2] arm64/ptdump: Replace u64 with pteval_t Anshuman Khandual 2025-03-17 9:28 ` Ryan Roberts 2025-03-18 4:37 ` Anshuman Khandual
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox