From: Alexander Graf <graf@amazon.com>
To: Andrew Morton <akpm@linux-foundation.org>,
Mike Rapoport <rppt@kernel.org>
Cc: David Hildenbrand <david@kernel.org>,
Wei Yang <richard.weiyang@gmail.com>, <linux-mm@kvack.org>,
<linux-kernel@vger.kernel.org>, <nh-open-source@amazon.com>
Subject: [PATCH v2] mm/mm_init: fix out-of-range first_deferred_pfn
Date: Fri, 7 Aug 2026 03:12:43 +0000 [thread overview]
Message-ID: <20260807031243.87904-1-graf@amazon.com> (raw)
With CONFIG_DEFERRED_STRUCT_PAGE_INIT enabled, deferred_grow_zone()
undefers struct page ranges early in boot to satisfy an allocation. With
a large CMA reservation in place, the ranges it finds may not add up to
the allocation it was asked for, and we end up undeferring all available
RAM and still fall short. That is fine in itself: the function accounts
for it and leaves the caller to decide whether it now has enough memory.
The function also remembers where undeferring is to continue next, in
pgdat->first_deferred_pfn, and it walks in PAGES_PER_SECTION (128M)
chunks. If the node's RAM does not end 128M aligned and we undeferred
everything, that "next" points past the end of the node's RAM.
deferred_init_memmap() later picks up from first_deferred_pfn and hits a
BUG_ON(), because it expects a pfn within its node:
kernel BUG at mm/mm_init.c:2131!
CPU: 3 UID: 0 PID: 36 Comm: pgdatinit0 Not tainted 7.2.0-rc6 #1
RIP: 0010:deferred_init_memmap+0x1b8/0x1c0
RAX: 0000000000236000 R13: 0000000000238000
Call Trace:
kthread+0xdf/0x120
ret_from_fork+0x187/0x250
Detect the end of RAM in deferred_grow_zone() instead of assuming that
more deferral is always available. When the walk leaves the zone (which
is where this node's RAM ends), record ULONG_MAX, the value that tells
deferred_init_memmap() the memory map is already initialized.
To reproduce with CONFIG_DEFERRED_STRUCT_PAGE_INIT=y and CONFIG_CMA=y:
qemu-system-x86_64 -enable-kvm -m 8032M -kernel bzImage \
-append "nokaslr cma=4768M@0x100000000"
The above command panics on every boot without this patch and boots
reliably with it applied.
Fixes: 3acb913c9d5b ("mm/mm_init: use deferred_init_memmap_chunk() in deferred_grow_zone()")
Cc: stable@vger.kernel.org
Assisted-by: Kiro:claude-opus-5
Signed-off-by: Alexander Graf <graf@amazon.com>
---
Notes:
Changes since v1: changelog rewritten for readability per review feedback.
No functional change; the diff is byte-identical to v1.
v1: https://lore.kernel.org/linux-mm/20260805224421.15794-1-graf@amazon.com/
Applies unchanged to 6.18.y, 6.19.y, 7.0.y and 7.1.y (checked against
v6.18.39, v6.19.14, v7.0.14 and v7.1.4); the deferred_init_memmap_chunk()
signature change in cbbbf7795fc3 sits outside the hunk context, so stable
needs no separate backport.
mm/mm_init.c | 9 ++++++---
1 file changed, 6 insertions(+), 3 deletions(-)
diff --git a/mm/mm_init.c b/mm/mm_init.c
index 498d62c4ece3..91177be58a00 100644
--- a/mm/mm_init.c
+++ b/mm/mm_init.c
@@ -2214,10 +2214,13 @@ bool __init deferred_grow_zone(struct zone *zone, unsigned int order)
}
/*
- * There were no pages to initialize and free which means the zone's
- * memory map is completely initialized.
+ * The loop only tests spfn before entering an iteration, so on exit it
+ * may point up to a section past the end of the zone. When it does,
+ * the rest of the zone has already been handed to
+ * deferred_init_memmap_chunk() and nothing is left to initialize.
*/
- pgdat->first_deferred_pfn = nr_pages ? spfn : ULONG_MAX;
+ pgdat->first_deferred_pfn =
+ spfn < zone_end_pfn(zone) ? spfn : ULONG_MAX;
pgdat_resize_unlock(pgdat, &flags);
base-commit: 0d839570765118029aa8bf4a95444c6a11aacf85
--
2.47.1
next reply other threads:[~2026-08-07 3:12 UTC|newest]
Thread overview: 2+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-08-07 3:12 Alexander Graf [this message]
2026-08-07 8:52 ` [PATCH v2] mm/mm_init: fix out-of-range first_deferred_pfn Mike Rapoport
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20260807031243.87904-1-graf@amazon.com \
--to=graf@amazon.com \
--cc=akpm@linux-foundation.org \
--cc=david@kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-mm@kvack.org \
--cc=nh-open-source@amazon.com \
--cc=richard.weiyang@gmail.com \
--cc=rppt@kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox