Add two files under /sys/kernel/debug/crash_memaction/. "regions" lists the physical ranges the bits describe and their offset and length in the bitmap. "bitmap" shows the raw bits as a single blob with all ranges concatenated. The files are root only and behind CONFIG_CRASH_MEMACTION_DEBUGFS.
Signed-off-by: Jan Sebastian Götte <[email protected]> Assisted-by: Claude Opus 5 <[email protected]> --- Documentation/mm/crash_memaction.rst | 9 ++++++ kernel/Kconfig.kexec | 14 +++++++++ kernel/crash_core.c | 59 ++++++++++++++++++++++++++++++++++++ 3 files changed, 82 insertions(+) diff --git a/Documentation/mm/crash_memaction.rst b/Documentation/mm/crash_memaction.rst index 3658bff7693c..eacda046477e 100644 --- a/Documentation/mm/crash_memaction.rst +++ b/Documentation/mm/crash_memaction.rst @@ -57,3 +57,12 @@ Limitations trying to mark smaller objects, use lib/secret_pool or a similar mechanism. * Memory hotplug is not supported at this time. When memory is hotplugged, the newly hotplugged memory will not be included in the bitmap. + +Inspecting the bitmap +===================== + +With ``CONFIG_CRASH_MEMACTION_DEBUGFS`` the bitmap can be read through debugfs:: + + # types 0x3000 page_shift 12 nr_regions 1 + # start_pfn nr_pages offset bytes paddr + 0x0000000000000001 0x0000000000800000 0x0 0x100000 0x0000000040000000 diff --git a/kernel/Kconfig.kexec b/kernel/Kconfig.kexec index 3cdc8d459ac0..b5380e16bfaf 100644 --- a/kernel/Kconfig.kexec +++ b/kernel/Kconfig.kexec @@ -204,4 +204,18 @@ config CRASH_MEMACTION If unsure, say N. +config CRASH_MEMACTION_DEBUGFS + bool "Expose the crash memaction bitmap in debugfs" + depends on CRASH_MEMACTION && DEBUG_FS + help + Allow reading the live crash_memaction bitmap through + /sys/kernel/debug/crash_memaction/. The bitmap is used when + CRASH_MEMACTION is set and when a crash_memaction cmdline param is present + to tell an eventual kdump kernel about the use of certain memory pages. + + Note that this is a debug interface only that gives no guarantees + whatsoever on memory consistency. + + If unsure, say N. + endmenu diff --git a/kernel/crash_core.c b/kernel/crash_core.c index 6bb2f5645ca6..5eb5a5ada8e0 100644 --- a/kernel/crash_core.c +++ b/kernel/crash_core.c @@ -28,9 +28,11 @@ #include <linux/atomic.h> #include <linux/bitmap.h> #include <linux/bitops.h> +#include <linux/debugfs.h> #include <linux/jump_label.h> #include <linux/overflow.h> #include <linux/pfn.h> +#include <linux/seq_file.h> #include <linux/slab.h> #include <linux/string.h> #include <linux/sysfs.h> @@ -66,6 +68,10 @@ static struct crash_memaction_region *crash_memaction_regions __ro_after_init; static unsigned int crash_memaction_nr_regions __ro_after_init; static size_t crash_memaction_note_bytes __ro_after_init; +/* The one allocation all of the bitmaps above were carved out of. */ +static void *crash_ma_bitmap_base __ro_after_init; +static size_t crash_ma_bitmap_size __ro_after_init; + static struct crash_memaction_note *crash_memaction_desc __ro_after_init; static size_t crash_memaction_desc_bytes __ro_after_init; @@ -148,6 +154,8 @@ void __init crash_memaction_init(void) if (!bits) goto nomem; + crash_ma_bitmap_base = bits; + crash_ma_bitmap_size = total_bytes; for (i = 0; i < nr; i++) { regions[i].bits = bits; bits += bitmap_size(regions[i].nr_pages); @@ -341,6 +349,57 @@ void crash_memaction_unmark(void *addr, size_t size) } EXPORT_SYMBOL_GPL(crash_memaction_unmark); +#ifdef CONFIG_CRASH_MEMACTION_DEBUGFS + +static struct debugfs_blob_wrapper crash_ma_bitmap_blob; + +/* @paddr is what the note gives, so a vmcore can be matched to a live one. */ +static int crash_memaction_regions_show(struct seq_file *m, void *v) +{ + unsigned long offset = 0; + unsigned int i; + + seq_printf(m, "# types 0x%x page_shift %u nr_regions %u\n", + crash_memaction_type_mask, PAGE_SHIFT, + crash_memaction_nr_regions); + seq_puts(m, "# start_pfn nr_pages offset bytes paddr\n"); + + for (i = 0; i < crash_memaction_nr_regions; i++) { + struct crash_memaction_region *reg = &crash_memaction_regions[i]; + size_t bytes = bitmap_size(reg->nr_pages); + phys_addr_t paddr = __pa(reg->bits); + + seq_printf(m, "0x%016lx 0x%016lx 0x%016lx 0x%016zx %pa\n", + reg->start_pfn, reg->nr_pages, offset, bytes, &paddr); + offset += bytes; + } + + return 0; +} +DEFINE_SHOW_ATTRIBUTE(crash_memaction_regions); + +static int __init crash_memaction_debugfs_init(void) +{ + struct dentry *dir; + + if (!crash_memaction_nr_regions) + return 0; + + dir = debugfs_create_dir("crash_memaction", NULL); + + debugfs_create_file("regions", 0400, dir, NULL, + &crash_memaction_regions_fops); + + crash_ma_bitmap_blob.data = crash_ma_bitmap_base; + crash_ma_bitmap_blob.size = crash_ma_bitmap_size; + debugfs_create_blob("bitmap", 0400, dir, &crash_ma_bitmap_blob); + + return 0; +} +fs_initcall(crash_memaction_debugfs_init); + +#endif /* CONFIG_CRASH_MEMACTION_DEBUGFS */ + int crash_load_memaction(struct kimage *image) { unsigned long nr_pages, i; -- 2.55.0

