New: WARNING at mm/memblock.c:904 __free_reserved_area(): "Cannot free reserved memory because of deferred initialization of the memory map" during housekeeping_init() at boot
Subsystems (2)
Andrew Morton
maintainer(switched to email. Please respond via emailed reply-to-all, not via the bugzilla web interface).
Quoted 21 lines · On Tue, 28 Jul 2026 15:52:54 +0000 [email protected] wrote:
https://bugzilla.kernel.org/show_bug.cgi?id=221804
Bug ID: 221804
Summary: WARNING atmm/memblock.c:904__free_reserved_area():
"Cannot free reserved memory because of deferred initialization of the memory map" duringhousekeeping_init()at boot
Product: Memory Management
Version: 2.5
Hardware: All
OS: Linux
Status: NEW
Severity: normal
Priority: P3
Component: Other
Assignee: [email protected]
Reporter: [email protected]
Regression: NoHello Kernel Team,
Quoted 7 lines
I notice this today:
...
[ 0.075447] Dynamic Preempt: lazy [ 0.075489] ------------[ cut here ]------------ [ 0.075490] Cannot free reserved memory because of deferred initializationof the memory map
Thanks. I asked Gemini "what happened here" and the response was illuminating.
The bottom lines:
The Core Issue: Initialization Order Conflict
The kernel hit an order-of-operations conflict between memory setup and kernel parameter parsing:
CONFIG_DEFERRED_STRUCT_PAGE_INIT=y delays initializing struct page tracking structures for large pools of RAM until secondary CPUs come online (to speed up boot times on large systems).
housekeeping_init() runs very early during start_kernel(). It parses CPU isolation/housekeeping flags (isolcpus=, nohz_full=, rcu_nocbs=) and allocates temporary cpumask buffers in memblock. Once parsed, it tries to free those temporary buffers back to the memory pool using memblock_phys_free().
The Collision: memblock_phys_free() calls __free_reserved_area(), which requires valid struct page mappings. Because page initialization was deferred, __free_reserved_area() detects that the target memory's struct page maps aren't ready yet (at time 0.075s, whereas deferred init only finished around 0.325s).
As a safeguard, __free_reserved_area() issues a WARN() and refuses to free the pages.
Fix/Workaround:
Fix the nohz_full syntax on the command line (e.g., nohz_full=8-55,64-111).
To eliminate the warning entirely until fixed upstream, boot with deferred_init=off as a kernel parameter or disable CONFIG_DEFERRED_STRUCT_PAGE_INIT in the kernel build. Upstream, housekeeping_init() should either avoid early memblock freeing or use allocations that don't depend on fully initialized page maps.
I don't think this is very high priority.
Quoted 56 lines · Andrew Morton
(switched to email. Please respond via emailed reply-to-all, not via the bugzilla web interface).
Quoted 21 lines · On Tue, 28 Jul 2026 15:52:54 +0000 [email protected] wrote:
https://bugzilla.kernel.org/show_bug.cgi?id=221804
Bug ID: 221804
Summary: WARNING atmm/memblock.c:904__free_reserved_area():
"Cannot free reserved memory because of deferred initialization of the memory map" duringhousekeeping_init()at boot
Product: Memory Management
Version: 2.5
Hardware: All
OS: Linux
Status: NEW
Severity: normal
Priority: P3
Component: Other
Assignee: [email protected]
Reporter: [email protected]
Regression: NoHello Kernel Team,
Quoted 7 lines
I notice this today:
...
[ 0.075447] Dynamic Preempt: lazy [ 0.075489] ------------[ cut here ]------------ [ 0.075490] Cannot free reserved memory because of deferred initializationof the memory map
Thanks. I asked Gemini "what happened here" and the response was illuminating.
The bottom lines:
The Core Issue: Initialization Order Conflict
The kernel hit an order-of-operations conflict between memory setup and kernel parameter parsing:
CONFIG_DEFERRED_STRUCT_PAGE_INIT=ydelays initializing struct page tracking structures for large pools of RAM until secondary CPUs come online (to speed up boot times on large systems).
housekeeping_init()runs very early duringstart_kernel(). It parses CPU isolation/housekeeping flags (isolcpus=, nohz_full=, rcu_nocbs=) and allocates temporary cpumask buffers in memblock. Once parsed, it tries to free those temporary buffers back to the memory pool usingmemblock_phys_free().
Quoted 5 lines
The Collision:
memblock_phys_free()calls__free_reserved_area(), which requires valid struct page mappings. Because page initialization was deferred,__free_reserved_area()detects that the target memory's struct page maps aren't ready yet (at time 0.075s, whereas deferred init only finished around 0.325s).
Just to add a bit of a human touch:
housekeeping_setup() allocates the masks from memblock when it parses the command line before mm_core_init().
housekeeping_init() reallocates them with kmalloc() to allow consistent kfree() afterwards and frees the memblock allocations.
And since housekeeping_init() happens after page allocator + slab init and before deferred_memmap_init() we can't reliably memblock_free() the memblock allocations.
Quoted 7 lines
As a safeguard,
__free_reserved_area()issues aWARN()and refuses to free the pages.Fix/Workaround:
Fix the
nohz_fullsyntax on the command line (e.g., nohz_full=8-55,64-111).
I don't see how that will help.
Quoted 2 lines
To eliminate the warning entirely until fixed upstream, boot with deferred_init=off as a kernel parameter
Which does not exist :)
Quoted 1 line
or disable
CONFIG_DEFERRED_STRUCT_PAGE_INITin the kernel build.
This would work, but would cost in boot time on a machine with 128 GiB of RAM.
Quoted 2 lines
Upstream,
housekeeping_init()should either avoid early memblock freeing
Presuming that houskeeping wants to keep the reallocation with kmalloc(), it should defer freeing to, say, some_initcall(housekeeping_late_init).
And housekeeping_setup() might want to memblock_alloc() enough memory for all the possible hk_type's once and than free that memory in an initcall.
Quoted 2 lines
or use allocations that don't depend on fully initialized page maps.
It's really not an option :)
Quoted 1 line
I don't think this is very high priority.
Signature · 2 lines
Sincerely yours, Mike.
PATCH 1/1 sched/isolation: Defer freeing of the bootmem housekeeping cpumasks
In reply to Andrew Mortonhousekeeping_setup() allocates the housekeeping cpumasks from memblock while parsing the command line, long before the page allocator exists. housekeeping_init() then reallocates them with kmalloc(), so that a later runtime update can free the old mask with kfree(), and releases the memblock allocations with memblock_free().
That release is not safe where it currently sits. housekeeping_init() is called from start_kernel() after mm_core_init(), so slab_is_available() is already true and memblock_phys_free() takes the __free_reserved_area() path. But it is still called long before page_alloc_init_late(), so with CONFIG_DEFERRED_STRUCT_PAGE_INIT=y the deferred part of the memory map is not initialized yet, and __free_reserved_area() refuses to touch it:
Cannot free reserved memory because of deferred initialization of the memory map
WARNING: mm/memblock.c:904 at __free_reserved_area+0xde/0xf0, CPU#0: swapper/0/0 Call Trace: memblock_phys_free+0xe4/0x120 housekeeping_init+0x149/0x170 start_kernel+0x5b6/0x800 x86_64_start_reservations+0x24/0x30 x86_64_start_kernel+0xd7/0xe0 common_startup_64+0x13e/0x151
The warning fires once per housekeeping type in use -- four splats on a 112-CPU two-socket machine booted with both isolcpus= and nohz_full= -- and taints the kernel with G W. No memory is actually lost either way:
a cpumask is much smaller than a page, so __free_reserved_area() has no whole page to hand back to the buddy allocator in the first place.
Record the bootmem masks instead and release them from a core_initcall, which runs after page_alloc_init_late() has initialized the deferred memory map. early_initcall() would still be too early: kernel_init_freeable() runs do_pre_smp_initcalls() before page_alloc_init_late().
Masks that housekeeping_init() did not manage to replace, because kmalloc() failed, are never recorded and therefore stay live, preserving the existing error behaviour.
---
Reproduced on a Dell PowerEdge R750 (2x Xeon Gold 6330, 112 CPUs, 2 NUMA nodes, 128 GiB) running v7.2-rc5 with PREEMPT_RT and CONFIG_DEFERRED_STRUCT_PAGE_INIT=y, booted with:
rcu_nocbs=8-55,64-111 nohz_full=managed_irq,nohz,domain,8-55,64-111 isolcpus=managed_irq,nohz,domain,8-55,64-111 kthread_cpus=0-3,56-59 irqaffinity=4-7,60-63 rcutree.kthread_prio=21
Four splats at boot without this patch, none with it. Also build-tested on x86_64 defconfig plus CONFIG_NO_HZ_FULL and CONFIG_DEFERRED_STRUCT_PAGE_INIT.
The bad memblock_free() has been there since 27c3a5967f05 in v7.0, but it only became visible in v7.1, when 59bd1d914bb5 ("memblock: warn when freeing reserved memory before memory map is initialized") added the WARN. Since nothing is actually leaked and the effect is a warning plus a G W taint, I did not Cc stable -- say the word if you would rather have it there.
I also considered Mike's second suggestion, of having housekeeping_setup() make a single memblock allocation covering all HK_TYPE_MAX masks and freeing that one region later. It touches more code for no additional benefit here, so I went with the simpler variant.
kernel/sched/isolation.c | 24 +++++++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-)
kernel/sched/isolation.c +23 -1
@@ -28,6 +28,17 @@ struct housekeeping {static struct housekeeping housekeeping; +/* +* Bootmem cpumasks that housekeeping_init() has replaced with kmalloc()ed +* copies. They can't be released right there: housekeeping_init() runs once +* the page allocator and slab are up, but before page_alloc_init_late() has +* initialized the deferred part of the memory map, and memblock_free() then +* reaches __free_reserved_area(), which refuses to touch a memory map that +* isn't fully initialized yet. Record them instead and release them from a +* core_initcall, which runs after page_alloc_init_late(). +*/ +static struct cpumask *housekeeping_bootmem_masks[HK_TYPE_MAX ]__initdata ; +bool housekeeping_enabled (enum hk_type type) {return !!(READ_ONCE (housekeeping.flags) &BIT (type));
@@ -189,10 +200,21 @@ void __init housekeeping_init(void)WARN_ON_ONCE (cpumask_empty (omask));cpumask_copy (nmask, omask);RCU_INIT_POINTER (housekeeping.cpumasks[type], nmask); -memblock_free (omask,cpumask_size ()); + housekeeping_bootmem_masks[type] = omask; } } +static int __init housekeeping_free_bootmem_masks (void ) +{ +enum hk_type type; + +for (type =0 ; type <HK_TYPE_MAX ; type++) +memblock_free (housekeeping_bootmem_masks[type],cpumask_size ()); + +return 0 ; +} +core_initcall (housekeeping_free_bootmem_masks); +static void __init housekeeping_setup_type (enum hk_type type,cpumask_var_t housekeeping_staging) {
base-commit: 2d2338c93da79b3bfe4b6099a931d9468d539952
Signature · 1 line
2.55.0
Re: [PATCH] sched/isolation: Defer freeing of the bootmem housekeeping cpumasks
Quoted 22 lines · Ionut Nechita
housekeeping_setup()allocates the housekeeping cpumasks from memblock while parsing the command line, long before the page allocator exists.housekeeping_init()then reallocates them withkmalloc(), so that a later runtime update can free the old mask withkfree(), and releases the memblock allocations withmemblock_free().That release is not safe where it currently sits.
housekeeping_init()is called fromstart_kernel()aftermm_core_init(), soslab_is_available()is already true andmemblock_phys_free()takes the__free_reserved_area()path. But it is still called long beforepage_alloc_init_late(), so withCONFIG_DEFERRED_STRUCT_PAGE_INIT=ythe deferred part of the memory map is not initialized yet, and__free_reserved_area()refuses to touch it:Record the bootmem masks instead and release them from a
core_initcall, which runs afterpage_alloc_init_late()has initialized the deferred memory map.early_initcall()would still be too early:kernel_init_freeable()runsdo_pre_smp_initcalls()beforepage_alloc_init_late().Masks that
housekeeping_init()did not manage to replace, becausekmalloc()failed, are never recorded and therefore stay live, preserving the existing error behaviour.
Quoted 5 lines
Fixes 27c3a5967f05 ("sched/isolation: Convert housekeeping cpumasks to rcu pointers")Suggested-by Mike Rapoport (Microsoft) <[email protected]>Signed-off-by Ionut Nechita <[email protected]>
Some nits below.
Quoted 9 lines
--- kernel/sched/isolation.c | 24 +++++++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-)kernel/sched/isolation.c +0
-0
kernel/sched/isolation.c struct housekeeping { · line 32
Quoted 5 lines
kernel/sched/isolation.c +2
-0@@ -28,6 +28,17 @@ struct housekeeping {static struct housekeeping housekeeping; +/* +* Bootmem cpumasks that housekeeping_init() has replaced with kmalloc()ed
Nit: s/has replaced/replaces
kernel/sched/isolation.c struct housekeeping { · line 38
Quoted 6 lines
kernel/sched/isolation.c +6
-0+* copies. They can't be released right there: housekeeping_init() runs once +* the page allocator and slab are up, but before page_alloc_init_late() has +* initialized the deferred part of the memory map, and memblock_free() then +* reaches __free_reserved_area(), which refuses to touch a memory map that +* isn't fully initialized yet. Record them instead and release them from a +* core_initcall, which runs after page_alloc_init_late().
And I'd split it into 3 paragraphs :)
- the first sentence
- description why that memory can't be released in housekeeping_init()
- Record them ...
Quoted 34 lines
kernel/sched/isolation.c +15
-1+*/ +static struct cpumask *housekeeping_bootmem_masks[HK_TYPE_MAX ]__initdata ; +bool housekeeping_enabled (enum hk_type type) {return !!(READ_ONCE (housekeeping.flags) &BIT (type));@@ -189,10 +200,21 @@ void __init housekeeping_init(void)WARN_ON_ONCE (cpumask_empty (omask));cpumask_copy (nmask, omask);RCU_INIT_POINTER (housekeeping.cpumasks[type], nmask); -memblock_free (omask,cpumask_size ()); + housekeeping_bootmem_masks[type] = omask; } } +static int __init housekeeping_free_bootmem_masks (void ) +{ +enum hk_type type; + +for (type =0 ; type <HK_TYPE_MAX ; type++) +memblock_free (housekeeping_bootmem_masks[type],cpumask_size ()); + +return 0 ; +} +core_initcall (housekeeping_free_bootmem_masks); +static void __init housekeeping_setup_type (enum hk_type type,cpumask_var_t housekeeping_staging) {base-commit:
2d2338c93da79b3bfe4b6099a931d9468d539952Signature · 1 line
2.55.0
Signature · 2 lines
Sincerely yours, Mike.
Re: [PATCH] sched/isolation: Defer freeing of the bootmem housekeeping cpumasks
Quoted 3 lines · Mike Rapoport
Some nits below.
Thanks for the Ack and for the comment nits, and sorry for the noise -- this patch is not needed.
The same problem was already fixed by:
2b58c749b8c5 ("sched/isolation: Defer freeing of cpumask memblock memory
to initcall")
from Waiman Long, written on 2026-07-01, applied by Peter to sched/urgent and merged in v7.3-rc1. It records the stale bootmem masks on an __initdata llist and releases them from a pure_initcall, which is initcall level 0 and therefore runs from do_initcalls() inside do_basic_setup(), after page_alloc_init_late(). I only noticed it now, while preparing the v2 -- I should have re-checked mainline before posting.
So please drop this one, there will be no v2.
I will close bug 221804 as RESOLVED/CODE_FIX pointing at 2b58c749b8c5.
Ionut