Allocate the registry bitmap during boot and sync marked pages to the bitmap.
The registry bitmap is handed over to the kdump kernel through physical addresses and thus needs to be a single, physically contiguous range. A marking lasts past free and until the page frame is handed out again in post_alloc_hook() to account for stale data left in pages that are mid-migration or currently being reclaimed. For the same reason the unmark comes after any init_on_alloc zeroing. A hugetlb folio coming out of the pool never passes through post_alloc_hook(), so it drops the marking of its previous life in dequeue_hugetlb_folio_node_exact() instead. A folio the pool got from the page allocator was already cleared in post_alloc_hook. The hooks sit behind a static key patched out unless the kernel was booted with crash_memaction= to mitigate overhead when not used. Signed-off-by: Jan Sebastian Götte <[email protected]> Assisted-by: Claude Opus 5 <[email protected]> --- mm/hugetlb.c | 4 ++++ mm/mm_init.c | 3 +++ mm/page_alloc.c | 6 ++++++ 3 files changed, 13 insertions(+) diff --git a/mm/hugetlb.c b/mm/hugetlb.c index da980377d353..36f0c0d8f5f1 100644 --- a/mm/hugetlb.c +++ b/mm/hugetlb.c @@ -31,6 +31,7 @@ #include <linux/numa.h> #include <linux/llist.h> #include <linux/cma.h> +#include <linux/crash_memaction.h> #include <linux/migrate.h> #include <linux/nospec.h> #include <linux/delayacct.h> @@ -1281,6 +1282,9 @@ static struct folio *dequeue_hugetlb_folio_node_exact(struct hstate *h, folio_clear_hugetlb_freed(folio); h->free_huge_pages--; h->free_huge_pages_node[nid]--; + + crash_memaction_unmark_pfns(folio_pfn(folio), + folio_nr_pages(folio)); return folio; } diff --git a/mm/mm_init.c b/mm/mm_init.c index 9ce6060de06d..2245972b2685 100644 --- a/mm/mm_init.c +++ b/mm/mm_init.c @@ -27,6 +27,7 @@ #include <linux/stackdepot.h> #include <linux/swap.h> #include <linux/cma.h> +#include <linux/crash_memaction.h> #include <linux/crash_dump.h> #include <linux/execmem.h> #include <linux/sizes.h> @@ -2706,6 +2707,8 @@ void __init mm_core_init(void) */ kho_memory_init(); + crash_memaction_init(); + memblock_free_all(); mem_init(); kmem_cache_init(); diff --git a/mm/page_alloc.c b/mm/page_alloc.c index 759786240af3..ff82f632dc7d 100644 --- a/mm/page_alloc.c +++ b/mm/page_alloc.c @@ -54,6 +54,7 @@ #include <linux/khugepaged.h> #include <linux/delayacct.h> #include <linux/cacheinfo.h> +#include <linux/crash_memaction.h> #include <linux/pgalloc_tag.h> #include <asm/div64.h> #include "internal.h" @@ -1854,6 +1855,11 @@ inline void post_alloc_hook(struct page *page, unsigned int order, set_page_owner(page, order, gfp_flags); page_table_check_alloc(page, order); pgalloc_tag_add(page, current, 1 << order, alloc_flags); + + /* + * Release leftover crash_memaction markings from a previous owner of this page. + */ + crash_memaction_unmark_pfns(page_to_pfn(page), 1UL << order); } static void prep_new_page(struct page *page, unsigned int order, gfp_t gfp_flags, -- 2.55.0

