From: Benjamin Herrenschmidt <benh@kernel.crashing.org>
To: linux-mm@kvack.org
Cc: Mike Rapoport <rppt@kernel.org>
Subject: [PATCH] mm: Fix memblock_free_late() when using deferred struct page
Date: Tue, 03 Feb 2026 19:02:08 +1100 [thread overview]
Message-ID: <ec2aaef14783869b3be6e3c253b2dcbf67dbc12a.camel@kernel.crashing.org> (raw)
Currently, when using deferred struct page init, we may end up not
freeing the pages depending on where they are. Typically this happens
when efi_free_boot_services() tries to free UEFI Boot Services pages.
We can hit the !early_page_initialised() test in memblock_free_pages()
since the deferred initializer hasn't even started yet. As a result we
drop the pages on the floor.
Now, memblock_free_late() should only ever be called for pages that
are reserved, and thus for which the struct page has already been
initialized by memmap_init_reserved_pages().
So it should be safe to just free them normally and ignore the deferred
initializer, which will skip over them as it skips over anything still
in the memblock reserved list.
This recovers something like 130MB of RAM on EC2 t3a.nano instances who
only have 512MB to begin with (as to why UEFI uses that much, that's a
question for another day).
Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
---
mm/internal.h | 2 +-
mm/memblock.c | 6 ++++--
mm/mm_init.c | 4 ++--
3 files changed, 7 insertions(+), 5 deletions(-)
diff --git a/mm/internal.h b/mm/internal.h
index 9e0577413087c..fe6da7c30caf0 100644
--- a/mm/internal.h
+++ b/mm/internal.h
@@ -660,7 +660,7 @@ extern int __isolate_free_page(struct page *page,
unsigned int order);
extern void __putback_isolated_page(struct page *page, unsigned int
order,
int mt);
extern void memblock_free_pages(struct page *page, unsigned long pfn,
- unsigned int order);
+ unsigned int order, bool reserved);
extern void __free_pages_core(struct page *page, unsigned int order,
enum meminit_context context);
diff --git a/mm/memblock.c b/mm/memblock.c
index 3d7b0114442c4..b836b638615d0 100644
--- a/mm/memblock.c
+++ b/mm/memblock.c
@@ -1718,8 +1718,10 @@ void __init memblock_free_late(phys_addr_t base,
phys_addr_t size)
cursor = PFN_UP(base);
end = PFN_DOWN(base + size);
+ /* Only free pages that were reserved */
+ VM_WARN_ON(!memblock_is_region_reserved(base, size));
for (; cursor < end; cursor++) {
- memblock_free_pages(pfn_to_page(cursor), cursor, 0);
+ memblock_free_pages(pfn_to_page(cursor), cursor, 0,
true);
totalram_pages_inc();
}
}
@@ -2141,7 +2143,7 @@ static void __init __free_pages_memory(unsigned
long start, unsigned long end)
while (start + (1UL << order) > end)
order--;
- memblock_free_pages(pfn_to_page(start), start, order);
+ memblock_free_pages(pfn_to_page(start), start, order,
false);
start += (1UL << order);
}
diff --git a/mm/mm_init.c b/mm/mm_init.c
index 624c1f90ce050..34dc39a21b4bb 100644
--- a/mm/mm_init.c
+++ b/mm/mm_init.c
@@ -2440,9 +2440,9 @@ void *__init alloc_large_system_hash(const char
*tablename,
}
void __init memblock_free_pages(struct page *page, unsigned long pfn,
- unsigned int
order)
+ unsigned int order, bool reserved)
{
- if (IS_ENABLED(CONFIG_DEFERRED_STRUCT_PAGE_INIT)) {
+ if (IS_ENABLED(CONFIG_DEFERRED_STRUCT_PAGE_INIT) && !reserved)
{
int nid = early_pfn_to_nid(pfn);
if (!early_page_initialised(pfn, nid))
--
2.43.0
next reply other threads:[~2026-02-03 8:02 UTC|newest]
Thread overview: 33+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-02-03 8:02 Benjamin Herrenschmidt [this message]
2026-02-03 18:40 ` Mike Rapoport
2026-02-03 19:53 ` Benjamin Herrenschmidt
2026-02-04 7:39 ` Mike Rapoport
2026-02-04 9:02 ` Benjamin Herrenschmidt
2026-02-06 10:33 ` Mike Rapoport
2026-02-10 1:04 ` Benjamin Herrenschmidt
2026-02-10 2:10 ` Benjamin Herrenschmidt
2026-02-10 6:17 ` Benjamin Herrenschmidt
2026-02-10 8:34 ` Benjamin Herrenschmidt
2026-02-10 14:32 ` Mike Rapoport
2026-02-10 23:23 ` Benjamin Herrenschmidt
2026-02-11 5:20 ` Mike Rapoport
2026-02-16 5:34 ` Benjamin Herrenschmidt
2026-02-16 6:51 ` Benjamin Herrenschmidt
2026-02-16 4:53 ` Benjamin Herrenschmidt
2026-02-16 15:28 ` Mike Rapoport
2026-02-16 10:36 ` Alexander Potapenko
2026-02-17 8:28 ` [PATCH v2] " Benjamin Herrenschmidt
2026-02-17 12:32 ` Mike Rapoport
2026-02-17 22:00 ` Benjamin Herrenschmidt
2026-02-17 21:47 ` Benjamin Herrenschmidt
2026-02-18 0:15 ` Benjamin Herrenschmidt
2026-02-18 8:05 ` Mike Rapoport
2026-02-19 2:48 ` Benjamin Herrenschmidt
2026-02-19 10:16 ` Mike Rapoport
2026-02-19 22:46 ` Benjamin Herrenschmidt
2026-02-20 4:57 ` Benjamin Herrenschmidt
2026-02-20 9:09 ` Mike Rapoport
2026-02-20 9:00 ` Mike Rapoport
2026-02-20 5:12 ` Benjamin Herrenschmidt
2026-02-20 5:15 ` Benjamin Herrenschmidt
2026-02-20 5:47 ` Benjamin Herrenschmidt
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=ec2aaef14783869b3be6e3c253b2dcbf67dbc12a.camel@kernel.crashing.org \
--to=benh@kernel.crashing.org \
--cc=linux-mm@kvack.org \
--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