Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

ARM: 8735/1: mm: dump: make page table dumping reusable

This patch refactors the arm page table dumping code,
so multiple tables may be registered with the framework.

This patch refers below commits of arm64.
(4674fdb9f149 ("arm64: mm: dump: make page table dumping reusable"))
(4ddb9bf83349 ("arm64: dump: Make ptdump debugfs a separate option"))

Reviewed-by: Kees Cook <keescook@chromium.org>
Tested-by: Laura Abbott <labbott@redhat.com>
Reviewed-by: Laura Abbott <labbott@redhat.com>
Signed-off-by: Jinbum Park <jinb.park7@gmail.com>
Signed-off-by: Russell King <rmk+kernel@armlinux.org.uk>

authored by

Jinbum Park and committed by
Russell King
4fb69cc4 6fbab054

+106 -41
+5 -1
arch/arm/Kconfig.debug
··· 3 3 4 4 source "lib/Kconfig.debug" 5 5 6 - config ARM_PTDUMP 6 + config ARM_PTDUMP_CORE 7 + def_bool n 8 + 9 + config ARM_PTDUMP_DEBUGFS 7 10 bool "Export kernel pagetable layout to userspace via debugfs" 8 11 depends on DEBUG_KERNEL 9 12 depends on MMU 13 + select ARM_PTDUMP_CORE 10 14 select DEBUG_FS 11 15 ---help--- 12 16 Say Y here if you want to show the kernel pagetable layout in a
+35
arch/arm/include/asm/ptdump.h
··· 1 + /* SPDX-License-Identifier: GPL-2.0 */ 2 + /* Copyright (C) 2014 ARM Ltd. */ 3 + #ifndef __ASM_PTDUMP_H 4 + #define __ASM_PTDUMP_H 5 + 6 + #ifdef CONFIG_ARM_PTDUMP_CORE 7 + 8 + #include <linux/mm_types.h> 9 + #include <linux/seq_file.h> 10 + 11 + struct addr_marker { 12 + unsigned long start_address; 13 + char *name; 14 + }; 15 + 16 + struct ptdump_info { 17 + struct mm_struct *mm; 18 + const struct addr_marker *markers; 19 + unsigned long base_addr; 20 + }; 21 + 22 + void ptdump_walk_pgd(struct seq_file *s, struct ptdump_info *info); 23 + #ifdef CONFIG_ARM_PTDUMP_DEBUGFS 24 + int ptdump_debugfs_register(struct ptdump_info *info, const char *name); 25 + #else 26 + static inline int ptdump_debugfs_register(struct ptdump_info *info, 27 + const char *name) 28 + { 29 + return 0; 30 + } 31 + #endif /* CONFIG_ARM_PTDUMP_DEBUGFS */ 32 + 33 + #endif /* CONFIG_ARM_PTDUMP_CORE */ 34 + 35 + #endif /* __ASM_PTDUMP_H */
+2 -1
arch/arm/mm/Makefile
··· 13 13 obj-$(CONFIG_ARM_MPU) += pmsa-v7.o 14 14 endif 15 15 16 - obj-$(CONFIG_ARM_PTDUMP) += dump.o 16 + obj-$(CONFIG_ARM_PTDUMP_CORE) += dump.o 17 + obj-$(CONFIG_ARM_PTDUMP_DEBUGFS) += ptdump_debugfs.o 17 18 obj-$(CONFIG_MODULES) += proc-syms.o 18 19 obj-$(CONFIG_DEBUG_VIRTUAL) += physaddr.o 19 20
+30 -39
arch/arm/mm/dump.c
··· 21 21 #include <asm/fixmap.h> 22 22 #include <asm/memory.h> 23 23 #include <asm/pgtable.h> 24 - 25 - struct addr_marker { 26 - unsigned long start_address; 27 - const char *name; 28 - }; 24 + #include <asm/ptdump.h> 29 25 30 26 static struct addr_marker address_markers[] = { 31 27 { MODULES_VADDR, "Modules" }, ··· 331 335 } 332 336 } 333 337 334 - static void walk_pgd(struct seq_file *m) 338 + static void walk_pgd(struct pg_state *st, struct mm_struct *mm, 339 + unsigned long start) 335 340 { 336 - pgd_t *pgd = swapper_pg_dir; 337 - struct pg_state st; 338 - unsigned long addr; 341 + pgd_t *pgd = pgd_offset(mm, 0UL); 339 342 unsigned i; 340 - 341 - memset(&st, 0, sizeof(st)); 342 - st.seq = m; 343 - st.marker = address_markers; 343 + unsigned long addr; 344 344 345 345 for (i = 0; i < PTRS_PER_PGD; i++, pgd++) { 346 - addr = i * PGDIR_SIZE; 346 + addr = start + i * PGDIR_SIZE; 347 347 if (!pgd_none(*pgd)) { 348 - walk_pud(&st, pgd, addr); 348 + walk_pud(st, pgd, addr); 349 349 } else { 350 - note_page(&st, addr, 1, pgd_val(*pgd), NULL); 350 + note_page(st, addr, 1, pgd_val(*pgd), NULL); 351 351 } 352 352 } 353 + } 353 354 355 + void ptdump_walk_pgd(struct seq_file *m, struct ptdump_info *info) 356 + { 357 + struct pg_state st = { 358 + .seq = m, 359 + .marker = info->markers, 360 + }; 361 + 362 + walk_pgd(&st, info->mm, info->base_addr); 354 363 note_page(&st, 0, 0, 0, NULL); 355 364 } 356 365 357 - static int ptdump_show(struct seq_file *m, void *v) 366 + static void ptdump_initialize(void) 358 367 { 359 - walk_pgd(m); 360 - return 0; 361 - } 362 - 363 - static int ptdump_open(struct inode *inode, struct file *file) 364 - { 365 - return single_open(file, ptdump_show, NULL); 366 - } 367 - 368 - static const struct file_operations ptdump_fops = { 369 - .open = ptdump_open, 370 - .read = seq_read, 371 - .llseek = seq_lseek, 372 - .release = single_release, 373 - }; 374 - 375 - static int ptdump_init(void) 376 - { 377 - struct dentry *pe; 378 368 unsigned i, j; 379 369 380 370 for (i = 0; i < ARRAY_SIZE(pg_level); i++) ··· 369 387 pg_level[i].mask |= pg_level[i].bits[j].mask; 370 388 371 389 address_markers[2].start_address = VMALLOC_START; 390 + } 372 391 373 - pe = debugfs_create_file("kernel_page_tables", 0400, NULL, NULL, 374 - &ptdump_fops); 375 - return pe ? 0 : -ENOMEM; 392 + static struct ptdump_info kernel_ptdump_info = { 393 + .mm = &init_mm, 394 + .markers = address_markers, 395 + .base_addr = 0, 396 + }; 397 + 398 + static int ptdump_init(void) 399 + { 400 + ptdump_initialize(); 401 + return ptdump_debugfs_register(&kernel_ptdump_info, 402 + "kernel_page_tables"); 376 403 } 377 404 __initcall(ptdump_init);
+34
arch/arm/mm/ptdump_debugfs.c
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + #include <linux/debugfs.h> 3 + #include <linux/seq_file.h> 4 + 5 + #include <asm/ptdump.h> 6 + 7 + static int ptdump_show(struct seq_file *m, void *v) 8 + { 9 + struct ptdump_info *info = m->private; 10 + 11 + ptdump_walk_pgd(m, info); 12 + return 0; 13 + } 14 + 15 + static int ptdump_open(struct inode *inode, struct file *file) 16 + { 17 + return single_open(file, ptdump_show, inode->i_private); 18 + } 19 + 20 + static const struct file_operations ptdump_fops = { 21 + .open = ptdump_open, 22 + .read = seq_read, 23 + .llseek = seq_lseek, 24 + .release = single_release, 25 + }; 26 + 27 + int ptdump_debugfs_register(struct ptdump_info *info, const char *name) 28 + { 29 + struct dentry *pe; 30 + 31 + pe = debugfs_create_file(name, 0400, NULL, info, &ptdump_fops); 32 + return pe ? 0 : -ENOMEM; 33 + 34 + }