From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-alma10-1.taild15c8.ts.net [100.103.45.18]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id ABE411CAA6C for ; Thu, 6 Aug 2026 05:47:12 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=100.103.45.18 ARC-Seal:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1785995233; cv=none; b=ar+9EamZiirLC5vYbq18I+s5JUHhE0fVWsZ/OJZwsfn3pzX3kiN46PMBFcWM8vAO8M5JMm39HD3Pht0T82TSy4WQgvY/0iOImk40pcXNJpWfdMbJvT0XaoY8SejxsrDg6M6V/XBhBjxN8J1aDd8Ov/hrcIf1XdkEe6DdVXTJ5yo= ARC-Message-Signature:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1785995233; c=relaxed/simple; bh=cQTpy5jfshCgIaP1VTL7BP+Mpa39bv8ya12rVzO6rSE=; h=Date:From:To:Cc:Subject:Message-ID:References:MIME-Version: Content-Type:Content-Disposition:In-Reply-To; b=XrIoV4atFkSnxMPLvmlJajDr4mJODUTU4/hFigaIdAB2rJQxE/xdfjjCszJ0rx/PEFX8zNMzcZqb0N388YzyBryGaz/twnbRG6+aGKJiGy3d6SNaKgf6y+T6Tt31n1X7Au0B+Da2Kkr6wCUxEx6cazt84sUASVsx/uQjc5ojH0Q= ARC-Authentication-Results:i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=ArIOnnkM; arc=none smtp.client-ip=100.103.45.18 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="ArIOnnkM" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 0B2A81F000E9; Thu, 6 Aug 2026 05:47:09 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=kernel.org; s=k20260515; t=1785995232; bh=+dh5HntgmPOrDA8E9mM/SfdAeAFp52+cx/9yS0SyOjk=; h=Date:From:To:Cc:Subject:References:In-Reply-To; b=ArIOnnkMVw7FNhrwjpx28FW6lVCGzzdxx4kLG1BXHeK6y7vcuF+ot3gREJKYOyTWu BmakfSD0x5J39gM1gqS0/o8uCAYzwIc1CD8XG2sEn1a6IvAH09LxQfvOE9gneRgo7o somaGi/84Y5GlVtZQYQ6DlSWUhTc7pk2dM8BC3wd007/BnnDcz01Flgc2PQklBVD0g MymeUHLwFiDRsl2mv8J1E3DBDs8hahhqSEu2bjD/jBhBuEM27JwgbFtNF6lh8UkMi/ kM1n+xiViVSenXNY1BZWJ1gcd3lGx8yBpcdwUl29B6MOSoGfQc2zVjIganSpxQp8HC T3QVaK/dLUvbQ== Date: Thu, 6 Aug 2026 08:47:06 +0300 From: Mike Rapoport To: Alexander Graf Cc: Andrew Morton , David Hildenbrand , Wei Yang , linux-mm@kvack.org, linux-kernel@vger.kernel.org, nh-open-source@amazon.com Subject: Re: [PATCH] mm/mm_init: fix out-of-range first_deferred_pfn Message-ID: References: <20260805224421.15794-1-graf@amazon.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: <20260805224421.15794-1-graf@amazon.com> Hi Alex, On Wed, Aug 05, 2026 at 10:44:21PM +0000, Alexander Graf wrote: > deferred_grow_zone() initializes deferred struct pages a section at a > time until the allocation that called into it can be satisfied, and > records where to resume in pgdat->first_deferred_pfn. Reserve most of > the top zone early (a large CMA reservation is the easy way) and a single > early allocation has to walk the whole zone instead of stopping in its > first free section. If that zone does not end on a section boundary, the > pgdatinit kthread then dies: > > kernel BUG at mm/mm_init.c:2131! > Oops: invalid opcode: 0000 [#1] SMP NOPTI > 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 > > RAX is pgdat_end_pfn(), R13 the pfn that was stored. The loop advances > spfn in whole PAGES_PER_SECTION steps and only tests it before entering > an iteration, so once the walk reaches the end of a zone that ends > mid-section the escaping spfn is SECTION_ALIGN_UP(zone_end_pfn()). > Commit 3acb913c9d5b ("mm/mm_init: use deferred_init_memmap_chunk() in > deferred_grow_zone()") dropped the clamp that used to prevent that: epfn > came from __next_mem_pfn_range_in_zone(), since removed, which capped it > with min(zone_end_pfn(zone), epfn), so spfn could reach zone_end_pfn but > never pass it. The assert is fatal either way, panicking under > panic_on_oops and otherwise leaving page_alloc_init_late() waiting > forever for a completion the dead kthread never reports. > > Store ULONG_MAX once spfn has left the zone. Nothing is left > uninitialized: the loop covers a single gap-free interval, and because it > only enters with spfn < zone_end_pfn() the escaping value is exactly > SECTION_ALIGN_UP(zone_end_pfn()), which is the last_pfn that > deferred_init_memmap() would have used for the same pfn range. A zone > that does end section-aligned now takes this path too and loses its > zero-work padata job along with that node's pr_info() and the WARN_ON() > on the next zone. > > 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 only two paragraphs I understood is this and the BUG splat ;-P Can we please have a lot more of human touch on the changelog? > Top of RAM is then 0x235ffffff, so ZONE_NORMAL ends 96 MiB into its last > section, and less than a section stays free above the reservation once > the early memblock allocations are done. The walk therefore runs off the > end of the zone and stores 0x238000. Sweeping that free remainder from > 96M to 288M in 16M steps, an unpatched kernel dies on 7 of the 13 boots > and a patched one on none. On an 8 GiB cloud instance that reserves most > of its top zone for a memory pool, roughly one boot in three panicked > before reaching userspace. > > 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 > --- > > Notes: > 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. > > First seen on 6.18.y and 6.19-rc distribution kernels. There is no public > report to link, hence no Closes: tag. > > 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 > -- Sincerely yours, Mike.