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


Reply via email to