From: Mike Rapoport <rppt@kernel.org>
To: Breno Leitao <leitao@debian.org>
Cc: Ard Biesheuvel <ardb@kernel.org>,
Ilias Apalodimas <ilias.apalodimas@linaro.org>,
Thomas Gleixner <tglx@kernel.org>, Ingo Molnar <mingo@redhat.com>,
Borislav Petkov <bp@alien8.de>,
Dave Hansen <dave.hansen@linux.intel.com>,
x86@kernel.org, "H. Peter Anvin" <hpa@zytor.com>,
Andrew Morton <akpm@linux-foundation.org>,
David Hildenbrand <david@kernel.org>,
Lorenzo Stoakes <ljs@kernel.org>,
"Liam R. Howlett" <liam@infradead.org>,
Vlastimil Babka <vbabka@kernel.org>,
Suren Baghdasaryan <surenb@google.com>,
Michal Hocko <mhocko@suse.com>, Miaohe Lin <linmiaohe@huawei.com>,
Naoya Horiguchi <nao.horiguchi@gmail.com>,
Oscar Salvador <osalvador@suse.de>,
Greg Kroah-Hartman <gregkh@linuxfoundation.org>,
"Rafael J. Wysocki" <rafael@kernel.org>,
Danilo Krummrich <dakr@kernel.org>,
Catalin Marinas <catalin.marinas@arm.com>,
Will Deacon <will@kernel.org>,
Mark Rutland <mark.rutland@arm.com>,
kas@kernel.org, kexec@lists.infradead.org,
Brendan Jackman <brendan.jackman@linux.dev>,
Johannes Weiner <hannes@cmpxchg.org>, Zi Yan <ziy@nvidia.com>,
shakeel.butt@linux.dev, linux-efi@vger.kernel.org,
linux-kernel@vger.kernel.org, linux-mm@kvack.org,
linux-cxl@vger.kernel.org, driver-core@lists.linux.dev,
linux-arm-kernel@lists.infradead.org, rmikey@meta.com,
riel@surriel.com, harry@kernel.org, kernel-team@meta.com
Subject: Re: [PATCH v6 4/7] mm/memblock: add a reserved-region flag for poisoned frames
Date: Thu, 22 Oct 2026 19:33:30 +0300 [thread overview]
Message-ID: <ato62palTbNjLwN7@kernel.org> (raw)
In-Reply-To: <20261016-hwpoison-kho-v6-4-f304255147da@debian.org>
Hi Breno,
On Fri, Oct 16, 2026 at 05:15:44AM -0700, Breno Leitao wrote:
> memblock allocates from and frees to buddy whatever is not reserved, and
> knows nothing about frames an earlier kernel found hardware-poisoned.
> Such a frame can back the memmap, a page table or a percpu area before
> any hwpoison code runs, and otherwise reaches the buddy allocator like
> any other free frame.
>
> Add MEMBLOCK_RSRV_HWPOISON for a reserved range holding those frames.
How much this would fragment memblock.reserved?
memblock is not very scalable, to say the least, and each new flag
increases the size of memblock arrays which obviously hurts performance.
Do you have some statistics how many regions would be created for the
poisoned ranges?
> memblock neither allocates from a flagged range nor frees it to buddy.
> memmap_init_reserved_pages() initializes its struct pages like any other
> reserved range, including above first_deferred_pfn, but flags the RAM
> frames PG_hwpoison instead of PG_reserved. That is the state of a frame
> poisoned by this kernel. Holes in the range stay reserved.
>
> PG_reserved is left clear on purpose. page_is_unmovable() treats a
> reserved page as unmovable but skips a counted PG_hwpoison one, so a
> memory block holding an inherited frame can still be offlined.
>
> memblock_reserve_hwpoison() is the entry point. It is best effort. Until
> the reserved array can be resized it keeps spare slots for the
> reservations that must not fail. It flags only what no earlier
> reservation covers, a kexec segment for one: that was placed around the
> bad frames, and memblock_add_range() would warn about the overlap. A page
> shared with such a reservation stays with it, so no page is flagged
> twice.
>
> It returns 0 only when every free part of the range is reserved. If any
> part cannot be reserved it returns an error, even when another part was.
>
> Name the flag in the debugfs flag table. MEMBLOCK_RSRV_HUGETLB gets a
> name too: it has none, and would be left as a NULL slot below the new
> flag, which memblock_debug_show() passes on to seq_puts().
>
> Signed-off-by: Breno Leitao <leitao@debian.org>
> ---
> include/linux/memblock.h | 10 ++++++
> mm/memblock.c | 80 +++++++++++++++++++++++++++++++++++++++++++++++-
> 2 files changed, 89 insertions(+), 1 deletion(-)
>
> diff --git a/include/linux/memblock.h b/include/linux/memblock.h
> index aa845f488327f2..86755be249666d 100644
> --- a/include/linux/memblock.h
> +++ b/include/linux/memblock.h
> @@ -52,6 +52,8 @@ extern unsigned long long max_possible_pfn;
> * kernel that we know is good to use. It is the only memory that
> * allocations may happen from in this phase.
> * @MEMBLOCK_RSRV_HUGETLB: memory is reserved for hugetlb pages
> + * @MEMBLOCK_RSRV_HWPOISON: reserved memory region holding frames an earlier
> + * kernel found to be hardware-poisoned.
> */
> enum memblock_flags {
> MEMBLOCK_NONE = 0x0, /* No special request */
> @@ -63,6 +65,7 @@ enum memblock_flags {
> MEMBLOCK_RSRV_KERN = 0x20, /* memory reserved for kernel use */
> MEMBLOCK_KHO_SCRATCH = 0x40, /* scratch memory for kexec handover */
> MEMBLOCK_RSRV_HUGETLB = 0x80, /* memory reserved for hugetlb pages */
> + MEMBLOCK_RSRV_HWPOISON = 0x100, /* poisoned by an earlier kernel */
> };
>
> /**
> @@ -142,6 +145,8 @@ static __always_inline int memblock_reserve_kern(phys_addr_t base, phys_addr_t s
> return __memblock_reserve(base, size, NUMA_NO_NODE, MEMBLOCK_RSRV_KERN);
> }
>
> +int memblock_reserve_hwpoison(phys_addr_t base, phys_addr_t size);
> +
> #ifdef CONFIG_HAVE_MEMBLOCK_PHYS_MAP
> int memblock_physmem_add(phys_addr_t base, phys_addr_t size);
> #endif
> @@ -295,6 +300,11 @@ static inline bool memblock_is_reserved_noinit(struct memblock_region *m)
> return m->flags & MEMBLOCK_RSRV_NOINIT;
> }
>
> +static inline bool memblock_is_reserved_hwpoison(struct memblock_region *m)
> +{
> + return m->flags & MEMBLOCK_RSRV_HWPOISON;
> +}
> +
> static inline bool memblock_is_driver_managed(struct memblock_region *m)
> {
> return m->flags & MEMBLOCK_DRIVER_MANAGED;
> diff --git a/mm/memblock.c b/mm/memblock.c
> index 31961ed628b0ad..d20d99972a4db0 100644
> --- a/mm/memblock.c
> +++ b/mm/memblock.c
> @@ -36,6 +36,9 @@
> # define INIT_MEMBLOCK_RESERVED_REGIONS INIT_MEMBLOCK_REGIONS
> #endif
>
> +/* Reserved slots memblock_reserve_hwpoison() leaves free until a resize. */
> +#define MEMBLOCK_HWPOISON_SPARE 32
> +
> #ifndef INIT_MEMBLOCK_MEMORY_REGIONS
> #define INIT_MEMBLOCK_MEMORY_REGIONS INIT_MEMBLOCK_REGIONS
> #endif
> @@ -1015,6 +1018,55 @@ int __init_memblock __memblock_reserve(phys_addr_t base, phys_addr_t size,
> return memblock_add_range(&memblock.reserved, base, size, nid, flags);
> }
>
> +int __init memblock_reserve_hwpoison(phys_addr_t base, phys_addr_t size)
> +{
> + phys_addr_t end = base + size;
> + bool reserved = false;
> + int err = 0;
> +
> + while (base < end) {
> + phys_addr_t next = end;
> + struct memblock_region *r;
> + bool covered = false;
> +
> + for_each_reserved_mem_region(r) {
> + if (r->base + r->size <= base)
> + continue;
> + if (r->base >= end)
> + break;
> + if (PAGE_ALIGN_DOWN(r->base) <= base) {
> + base = min(end, PAGE_ALIGN(r->base + r->size));
> + covered = true;
> + } else {
> + next = PAGE_ALIGN_DOWN(r->base);
> + }
> + break;
> + }
> + if (covered)
> + continue;
> +
> + if (!memblock_can_resize &&
> + memblock.reserved.cnt + MEMBLOCK_HWPOISON_SPARE >=
> + memblock.reserved.max) {
> + err = -ENOSPC;
> + break;
> + }
> +
> + err = __memblock_reserve(base, next - base, NUMA_NO_NODE,
> + MEMBLOCK_RSRV_HWPOISON);
> + if (err)
> + break;
> +
> + reserved = true;
> + base = next;
> + }
> +
> + if (err)
> + return err;
> +
> + return reserved ? 0 : -EBUSY;
> +}
> +
> #ifdef CONFIG_HAVE_MEMBLOCK_PHYS_MAP
> int __init_memblock memblock_physmem_add(phys_addr_t base, phys_addr_t size)
> {
> @@ -2394,6 +2446,27 @@ static void __init memmap_init_reserved_range(phys_addr_t start,
> }
> }
>
> +/*
> + * Frames an earlier kernel found poisoned end up as a frame poisoned by this
> + * kernel would: PG_hwpoison, not PG_reserved. Holes in the range stay reserved.
> + */
> +static void __init memmap_init_hwpoison_range(phys_addr_t start,
> + phys_addr_t end, int nid)
> +{
> + unsigned long pfn;
> +
> + for_each_valid_pfn(pfn, PFN_DOWN(start), PFN_UP(end)) {
> + struct page *page = pfn_to_page(pfn);
> +
> + init_deferred_page(pfn, nid);
> +
> + if (memblock_is_map_memory(PFN_PHYS(pfn)))
> + hwpoison_boot_page(page);
> + else
> + __SetPageReserved(page);
> + }
> +}
> +
> static void __init memmap_init_reserved_pages(void)
> {
> struct memblock_region *region;
> @@ -2438,7 +2511,10 @@ static void __init memmap_init_reserved_pages(void)
> if (!numa_valid_node(nid))
> nid = early_pfn_to_nid(PFN_DOWN(start));
>
> - memmap_init_reserved_range(start, end, nid);
> + if (memblock_is_reserved_hwpoison(region))
> + memmap_init_hwpoison_range(start, end, nid);
> + else
> + memmap_init_reserved_range(start, end, nid);
> }
> }
> }
> @@ -2874,6 +2950,8 @@ static const char * const flagname[] = {
> [ilog2(MEMBLOCK_RSRV_NOINIT)] = "RSV_NIT",
> [ilog2(MEMBLOCK_RSRV_KERN)] = "RSV_KERN",
> [ilog2(MEMBLOCK_KHO_SCRATCH)] = "KHO_SCRATCH",
> + [ilog2(MEMBLOCK_RSRV_HUGETLB)] = "RSV_HUGETLB",
> + [ilog2(MEMBLOCK_RSRV_HWPOISON)] = "RSV_HWPOISON",
> };
>
> static int memblock_debug_show(struct seq_file *m, void *private)
>
> --
> 2.53.0-Meta
>
--
Sincerely yours,
Mike.
next prev parent reply other threads:[~2026-10-22 16:33 UTC|newest]
Thread overview: 16+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-10-16 12:15 [PATCH v6 0/7] mm/memory-failure: keep hardware-poisoned pages out of the next kexec Breno Leitao
2026-10-16 12:15 ` [PATCH v6 1/7] mm/memory-failure: efi: add the LINUX_EFI_POISONED_MEMORY configuration table Breno Leitao
2026-10-16 12:22 ` sashiko-bot
2026-10-16 12:15 ` [PATCH v6 2/7] mm/memory-failure: libstub: install the poisoned-memory EFI table Breno Leitao
2026-10-16 12:24 ` sashiko-bot
2026-10-16 12:15 ` [PATCH v6 3/7] mm/memory-failure: add hwpoison_boot_page() to flag an inherited frame Breno Leitao
2026-10-16 12:29 ` sashiko-bot
2026-10-16 12:15 ` [PATCH v6 4/7] mm/memblock: add a reserved-region flag for poisoned frames Breno Leitao
2026-10-16 12:26 ` sashiko-bot
2026-10-22 16:33 ` Mike Rapoport [this message]
2026-10-16 12:15 ` [PATCH v6 5/7] drivers/base/memory: count the poison a block already holds when creating it Breno Leitao
2026-10-16 12:30 ` sashiko-bot
2026-10-16 12:15 ` [PATCH v6 6/7] mm/memory-failure: efi: reserve the inherited poisoned-memory units Breno Leitao
2026-10-16 12:24 ` sashiko-bot
2026-10-16 12:15 ` [PATCH v6 7/7] mm/memory-failure: efi: record hardware-poisoned frames into the poisoned-memory table Breno Leitao
2026-10-16 12:28 ` sashiko-bot
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=ato62palTbNjLwN7@kernel.org \
--to=rppt@kernel.org \
--cc=akpm@linux-foundation.org \
--cc=ardb@kernel.org \
--cc=bp@alien8.de \
--cc=brendan.jackman@linux.dev \
--cc=catalin.marinas@arm.com \
--cc=dakr@kernel.org \
--cc=dave.hansen@linux.intel.com \
--cc=david@kernel.org \
--cc=driver-core@lists.linux.dev \
--cc=gregkh@linuxfoundation.org \
--cc=hannes@cmpxchg.org \
--cc=harry@kernel.org \
--cc=hpa@zytor.com \
--cc=ilias.apalodimas@linaro.org \
--cc=kas@kernel.org \
--cc=kernel-team@meta.com \
--cc=kexec@lists.infradead.org \
--cc=leitao@debian.org \
--cc=liam@infradead.org \
--cc=linmiaohe@huawei.com \
--cc=linux-arm-kernel@lists.infradead.org \
--cc=linux-cxl@vger.kernel.org \
--cc=linux-efi@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-mm@kvack.org \
--cc=ljs@kernel.org \
--cc=mark.rutland@arm.com \
--cc=mhocko@suse.com \
--cc=mingo@redhat.com \
--cc=nao.horiguchi@gmail.com \
--cc=osalvador@suse.de \
--cc=rafael@kernel.org \
--cc=riel@surriel.com \
--cc=rmikey@meta.com \
--cc=shakeel.butt@linux.dev \
--cc=surenb@google.com \
--cc=tglx@kernel.org \
--cc=vbabka@kernel.org \
--cc=will@kernel.org \
--cc=x86@kernel.org \
--cc=ziy@nvidia.com \
/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