From: Usama Arif <usama.arif@linux.dev>
To: Breno Leitao <leitao@debian.org>
Cc: Usama Arif <usama.arif@linux.dev>,
Ilias Apalodimas <ilias.apalodimas@linaro.org>,
Miaohe Lin <linmiaohe@huawei.com>,
Naoya Horiguchi <nao.horiguchi@gmail.com>,
Andrew Morton <akpm@linux-foundation.org>,
kas@kernel.org, kexec@lists.infradead.org,
David Hildenbrand <david@kernel.org>,
Lorenzo Stoakes <ljs@kernel.org>,
"Liam R. Howlett" <liam@infradead.org>,
Vlastimil Babka <vbabka@kernel.org>,
Mike Rapoport <rppt@kernel.org>,
Suren Baghdasaryan <surenb@google.com>,
Michal Hocko <mhocko@suse.com>, 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>,
Brendan Jackman <brendan.jackman@linux.dev>,
Johannes Weiner <hannes@cmpxchg.org>, Zi Yan <ziy@nvidia.com>,
Oscar Salvador <osalvador@suse.de>,
Greg Kroah-Hartman <gregkh@linuxfoundation.org>,
"Rafael J. Wysocki" <rafael@kernel.org>,
Danilo Krummrich <dakr@kernel.org>,
hannes@cmpxchg.or, shakeel.butt@linux.dev,
linux-efi@vger.kernel.org, linux-kernel@vger.kernel.org,
linux-mm@kvack.org, rmikey@meta.com, riel@surriel.com,
harry@kernel.org, linux-cxl@vger.kernel.org,
driver-core@lists.linux.dev, kernel-team@meta.com
Subject: Re: [PATCH v5 3/9] mm/memory-failure: libstub: install the poisoned-memory EFI table
Date: Wed, 16 Sep 2026 08:39:53 -0700 [thread overview]
Message-ID: <20260916153954.1054456-1-usama.arif@linux.dev> (raw)
In-Reply-To: <20260915-hwpoison-kho-v5-3-3bc7a57bd503@debian.org>
On Tue, 15 Sep 2026 05:53:37 -0700 Breno Leitao <leitao@debian.org> wrote:
> A EFI config table can only be installed while boot services are still
> up, so the stub has to create it; the running kernel can only flip bits
> in a table that already exists.
>
> Size the bitmap from the span the UEFI memory map describes, which
> efi_get_ram_range() walks since the stub has no max_pfn. Bit 0 covers
> the bottom of that span, recorded in phys_base, so a machine whose RAM
> starts high does not pay for the hole below it. Memory the firmware
> hot-adds later sits outside the span and is not carried across a kexec.
>
> One table has to serve every architecture, and what they agree on is the
> attribute: setup_e820() takes a descriptor as RAM only if it is writeback
> cacheable, and so does is_usable_memory() on arm64.
>
> The bitmap spans from the lowest to the highest descriptor that is
> write-back cacheable or unaccepted memory, as discussed with Kiryl. That
> leaves out the MMIO apertures, which sit high enough to stretch it far
> past the RAM it needs to describe.
>
> At one bit per 2M that is 64K per TiB, and 256M at the 4PB x86
> architectural maximum. The 2M granule is called "unit" here, and the
> table carries it so the granule can change later without breaking the
> kernels already reading it.
>
> Allocate it as EFI_ACPI_RECLAIM_MEMORY so the next kernel does not take
> it for free RAM, and install it empty.
>
> A table installed by an earlier boot rides the system table across kexec
> and is reused as-is.
>
> Signed-off-by: Breno Leitao <leitao@debian.org>
> ---
> drivers/firmware/efi/libstub/efi-stub-helper.c | 103 +++++++++++++++++++++++++
> drivers/firmware/efi/libstub/efi-stub.c | 1 +
> drivers/firmware/efi/libstub/efistub.h | 6 ++
> drivers/firmware/efi/libstub/x86-stub.c | 2 +
> 4 files changed, 112 insertions(+)
>
> diff --git a/drivers/firmware/efi/libstub/efi-stub-helper.c b/drivers/firmware/efi/libstub/efi-stub-helper.c
> index 48f93f7758e9e9..9c66e06c972c5a 100644
> --- a/drivers/firmware/efi/libstub/efi-stub-helper.c
> +++ b/drivers/firmware/efi/libstub/efi-stub-helper.c
> @@ -774,3 +774,106 @@ void efi_remap_image(unsigned long image_base, unsigned alloc_size,
> efi_warn("Failed to remap data region non-executable\n");
> }
> }
> +
> +#ifdef CONFIG_EFI_POISONED_MEMORY
> +/*
> + * Find the base and top of the memory, so, we can create the bitmap for
> + * the full range.
> + */
> +static efi_status_t efi_get_ram_range(u64 *base, u64 *top)
> +{
> + struct efi_boot_memmap *map __free(efi_pool) = NULL;
> + u64 ram_base = ULLONG_MAX, ram_top = 0;
> + efi_status_t status;
> + int i, nr_desc;
> +
> + status = efi_get_memory_map(&map, false);
> + if (status != EFI_SUCCESS)
> + return status;
> +
> + nr_desc = map->map_size / map->desc_size;
> + for (i = 0; i < nr_desc; i++) {
> + efi_memory_desc_t *d;
> +
> + d = efi_memdesc_ptr((unsigned long)map->map, map->desc_size, i);
> + if (!(d->attribute & EFI_MEMORY_WB) &&
> + d->type != EFI_UNACCEPTED_MEMORY)
> + continue;
> + ram_base = min(ram_base, d->phys_addr);
Can this use the architecture's full RAM predicate? On x86,
setup_e820() maps EFI_LOADER_CODE, EFI_LOADER_DATA, both boot-services
types, and EFI_CONVENTIONAL_MEMORY as E820_TYPE_RAM without requiring
EFI_MEMORY_WB.
If a non-WB descriptor is at either end of RAM, this code omits it
from the bitmap span. efi_hwpoison_record_pfn() then rejects a
poisoned PFN there, so the next kernel can allocate the bad frame.
One possible way to preserve the x86 behavior before applying the WB rule is:
if (IS_ENABLED(CONFIG_X86) &&
(d->type == EFI_LOADER_CODE ||
d->type == EFI_LOADER_DATA ||
d->type == EFI_BOOT_SERVICES_CODE ||
d->type == EFI_BOOT_SERVICES_DATA ||
d->type == EFI_CONVENTIONAL_MEMORY))
goto include;
if (!(d->attribute & EFI_MEMORY_WB) &&
d->type != EFI_UNACCEPTED_MEMORY)
continue;
include:
ram_base = min(ram_base, d->phys_addr);
> + ram_top = max(ram_top,
> + d->phys_addr + d->num_pages * EFI_PAGE_SIZE);
> + }
> + if (!ram_top || ram_base == ULLONG_MAX)
> + return EFI_NOT_FOUND;
> +
> + *base = round_down(ram_base, EFI_POISON_UNIT_SIZE);
> + *top = round_up(ram_top, EFI_POISON_UNIT_SIZE);
> +
> + return EFI_SUCCESS;
> +}
> +
> +/* The size of the bitmap */
> +static u64 efi_poison_bitmap_size(u64 span)
> +{
> + u64 bytes = DIV_ROUND_UP(DIV_ROUND_UP(span, EFI_POISON_UNIT_SIZE),
> + BITS_PER_BYTE);
> +
> + return round_up(bytes, sizeof(unsigned long));
> +}
> +
> +static struct linux_efi_poisoned_memory *efi_poison_alloc(u64 phys_base,
> + u64 bitmap_size)
> +{
> + struct linux_efi_poisoned_memory *pm;
> + efi_status_t status;
> +
> + status = efi_bs_call(allocate_pool, EFI_ACPI_RECLAIM_MEMORY,
> + sizeof(*pm) + bitmap_size, (void **)&pm);
> + if (status != EFI_SUCCESS)
> + return NULL;
> +
> + pm->version = 1;
> + pm->unit_size = EFI_POISON_UNIT_SIZE;
> + pm->phys_base = phys_base;
> + pm->size = bitmap_size;
> + memset(pm->bitmap, 0, bitmap_size);
> +
> + return pm;
> +}
> +
> +/* This needs to be done while boot service is still active */
> +void install_poisoned_memory_table(void)
> +{
> + efi_guid_t poisoned_memory_table_guid = LINUX_EFI_POISONED_MEMORY_TABLE_GUID;
> + struct linux_efi_poisoned_memory *pm;
> + u64 ram_base, ram_top, bitmap_size;
> + efi_status_t status;
> +
> + /* A table installed by an earlier boot rides the system table across kexec. */
> + pm = get_efi_config_table(poisoned_memory_table_guid);
> + if (pm) {
> + if (pm->version != 1)
> + efi_err("Unknown version of poisoned-memory table\n");
> + return;
> + }
> +
> + if (efi_get_ram_range(&ram_base, &ram_top) != EFI_SUCCESS) {
> + efi_err("Failed to size the poisoned-memory table!\n");
> + return;
> + }
> +
> + bitmap_size = efi_poison_bitmap_size(ram_top - ram_base);
> + pm = efi_poison_alloc(ram_base, bitmap_size);
> + if (!pm) {
> + efi_err("Failed to allocate poisoned-memory table!\n");
> + return;
> + }
> +
> + status = efi_bs_call(install_configuration_table,
> + &poisoned_memory_table_guid, pm);
> + if (status != EFI_SUCCESS) {
> + efi_bs_call(free_pool, pm);
> + efi_err("Failed to install poisoned-memory config table!\n");
> + }
> +}
> +#endif
> diff --git a/drivers/firmware/efi/libstub/efi-stub.c b/drivers/firmware/efi/libstub/efi-stub.c
> index 235c9738da2d63..22a315e2814a1a 100644
> --- a/drivers/firmware/efi/libstub/efi-stub.c
> +++ b/drivers/firmware/efi/libstub/efi-stub.c
> @@ -179,6 +179,7 @@ efi_status_t efi_stub_common(efi_handle_t handle,
> EFI_RT_SUPPORTED_SET_VIRTUAL_ADDRESS_MAP);
>
> install_memreserve_table();
> + install_poisoned_memory_table();
>
> status = efi_boot_kernel(handle, image, image_addr, cmdline_ptr);
>
> diff --git a/drivers/firmware/efi/libstub/efistub.h b/drivers/firmware/efi/libstub/efistub.h
> index fd91fc15ec810b..44436869c4efe1 100644
> --- a/drivers/firmware/efi/libstub/efistub.h
> +++ b/drivers/firmware/efi/libstub/efistub.h
> @@ -1169,6 +1169,12 @@ efi_enable_reset_attack_mitigation(void) { }
>
> void efi_retrieve_eventlog(void);
>
> +#ifdef CONFIG_EFI_POISONED_MEMORY
> +void install_poisoned_memory_table(void);
> +#else
> +static inline void install_poisoned_memory_table(void) { }
> +#endif
> +
> struct sysfb_display_info *alloc_primary_display(void);
> struct sysfb_display_info *__alloc_primary_display(void);
> void free_primary_display(struct sysfb_display_info *dpy);
> diff --git a/drivers/firmware/efi/libstub/x86-stub.c b/drivers/firmware/efi/libstub/x86-stub.c
> index 0bae0f06b6763a..3136132b9628ab 100644
> --- a/drivers/firmware/efi/libstub/x86-stub.c
> +++ b/drivers/firmware/efi/libstub/x86-stub.c
> @@ -1024,6 +1024,8 @@ void __noreturn efi_stub_entry(efi_handle_t handle,
>
> setup_unaccepted_memory();
>
> + install_poisoned_memory_table();
> +
> status = exit_boot(boot_params, handle);
> if (status != EFI_SUCCESS) {
> efi_err("exit_boot() failed!\n");
>
> --
> 2.53.0-Meta
>
>
next prev parent reply other threads:[~2026-09-16 15:40 UTC|newest]
Thread overview: 27+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-09-15 12:53 [PATCH v5 0/9] mm/memory-failure: keep hardware-poisoned pages out of the next kexec Breno Leitao
2026-09-15 12:53 ` [PATCH v5 1/9] mm/page_alloc: factor out the accept-and-free tail of __free_pages_core() Breno Leitao
2026-09-15 12:57 ` sashiko-bot
2026-09-15 12:53 ` [PATCH v5 2/9] mm/memory-failure: efi: add the LINUX_EFI_POISONED_MEMORY configuration table Breno Leitao
2026-09-15 13:05 ` sashiko-bot
2026-09-15 12:53 ` [PATCH v5 3/9] mm/memory-failure: libstub: install the poisoned-memory EFI table Breno Leitao
2026-09-15 13:15 ` sashiko-bot
2026-09-15 14:00 ` Breno Leitao
2026-09-16 15:39 ` Usama Arif [this message]
2026-09-15 12:53 ` [PATCH v5 4/9] mm/memory-failure: efi: adopt the inherited poisoned-memory table Breno Leitao
2026-09-15 13:24 ` sashiko-bot
2026-09-15 12:53 ` [PATCH v5 5/9] mm/memory-failure: efi: record hardware-poisoned frames into the " Breno Leitao
2026-09-15 13:36 ` sashiko-bot
2026-09-15 14:33 ` Breno Leitao
2026-09-15 12:53 ` [PATCH v5 6/9] mm/memory-failure: efi: answer whether a range is poisoned Breno Leitao
2026-09-15 13:45 ` sashiko-bot
2026-09-16 6:44 ` David Hildenbrand (Arm)
2026-09-15 12:53 ` [PATCH v5 7/9] drivers/base/memory: count inherited poisoned frames into the block Breno Leitao
2026-09-15 13:59 ` sashiko-bot
2026-09-16 6:48 ` David Hildenbrand (Arm)
2026-09-16 9:35 ` Breno Leitao
2026-09-16 14:51 ` David Hildenbrand (Arm)
2026-09-15 12:53 ` [PATCH v5 8/9] mm/memory-failure: add hwpoison_boot_page() to flag an inherited frame Breno Leitao
2026-09-15 14:11 ` sashiko-bot
2026-09-15 12:53 ` [PATCH v5 9/9] mm/memory-failure: keep inherited poisoned frames out of the buddy allocator Breno Leitao
2026-09-15 14:25 ` sashiko-bot
2026-09-16 8:32 ` Vlastimil Babka (SUSE)
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=20260916153954.1054456-1-usama.arif@linux.dev \
--to=usama.arif@linux.dev \
--cc=akpm@linux-foundation.org \
--cc=bp@alien8.de \
--cc=brendan.jackman@linux.dev \
--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.or \
--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-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=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=rppt@kernel.org \
--cc=shakeel.butt@linux.dev \
--cc=surenb@google.com \
--cc=tglx@kernel.org \
--cc=vbabka@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
all inboxes | Powered by JetHome®