Linux-mm Archive on lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v2 0/6] efi: mm/memory-failure: keep hardware-poisoned pages out of the next kexec
@ 2026-08-21 10:06 Breno Leitao
  2026-08-21 10:06 ` [PATCH v2 1/6] efi/libstub: add a helper for the top of usable RAM Breno Leitao
                   ` (6 more replies)
  0 siblings, 7 replies; 16+ messages in thread
From: Breno Leitao @ 2026-08-21 10:06 UTC (permalink / raw)
  To: Ard Biesheuvel, Ilias Apalodimas, Miaohe Lin, Naoya Horiguchi,
	Andrew Morton
  Cc: linux-efi, linux-kernel, linux-mm, rmikey, kas, riel, kexec,
	Breno Leitao, kernel-team

Problem:
========

When a page is hard-offlined due to an uncorrectable memory error (multi
bit ECC), memory_failure() sets PG_hwpoison, unmaps it, removes it from
the buddy allocator. This information is not carried to the next kernel
that is kexeced. The new kernel kexecs and trip over that bad memory
bank _again_.

Why now:
========

Several industry trends make this increasingly important:

    1) DRAM is getting more expensive
    2) soldered / on-package memory (LPDDR, HBM) is becoming more common, so a
       failing part can no longer simply be swapped;
    3) memory is kept in service far longer (at Meta, DRAM lifetime is being
       drastically extended).
    4) It is more and more common to kexec instead of full reboot
    5) Increase of memory per system with CXL

What was done already:
======================

In order make linux deal better with the problem above, I've done
already fixed a bunch of stuff in this area, such as:

1) Panic on unrecoverable errors, instead of "printk and carry over":
https://lore.kernel.org/all/20260630-ecc_panic-v10-0-c6ed5b62eea2@debian.org/

2) Respect poisoned memory at kexec time
https://lore.kernel.org/all/20260812-kexec_posioned-v6-0-e477887086f0@debian.org/

Now, the natural follow up is to carry the poisoned memory information
to the next kexec kernel, avoiding tripping over a known "bad page".

Proposed Solution:
==================

Carry the poisoned frames to the next kernel in a new EFI configuration
table, LINUX_EFI_POISONED_MEMORY.

EFI configuration tables already survive kexec: firmware hands the EFI
system table to every kernel in the chain, so a table installed once is
seen by all successors without a new handover channel.

The table is a bitmap with one bit per 2MB of physical memory, modeled
on LINUX_EFI_UNACCEPTED_MEMORY. The stub sizes it from the EFI memory
map and installs it empty while boot services are up -- a running kernel
cannot install a configuration table, it can only flip bits -- and a
table inherited from an earlier boot is reused as-is. That is one
fixed-size allocation, 64KB per TB of RAM, with no list to grow at
runtime and no chain to trust at parse time.

The allocation is capped at 1MB, which covers 16TB at 2MB per bit. Past
that the stub doubles the unit rather than growing the table, so the
table stays bounded on any machine.

The mechanism is architecture independent, so x86 and arm64 use the same
code.

Each hard offline sets the bit for its unit. Soft-offlined pages are not
recorded: they are still functional, and were offlined predictively.

The next kernel walks the inherited bitmap early in
efi_config_parse_tables(), before memblock and the buddy allocator are
up, and memblock_reserve()s every unit whose bit is set. The bad RAM is
never handed out.

Granularity is the trade-off: one bad 4KB frame costs a whole unit --
2MB, or more on a machine large enough to have coarsened it -- in every
later kernel of the chain. In exchange, a row or column fault -- roughly a
quarter of the DRAM faults reported in [1], and potentially thousands of
4KB pages scattered over gigabytes -- collapses into a bit or two.

A bit is never cleared, which is a known limitation: it stands for a
whole unit, so an unpoison of one frame cannot tell whether the unit as
a whole is good again, and after a kexec there is no PG_hwpoison left to
consult either. Unpoisoning a frame does not hand its unit back to the
next kernel.

Memory hot-added after boot is not covered either: the bitmap spans the
RAM the EFI memory map describes, and a frame outside it is silently not
recorded.

The series is six patches:

    1) add a libstub helper for the top of usable RAM
    2) add the LINUX_EFI_POISONED_MEMORY table
    3) build the table in the stub
    4) install it from both stub entry paths
    5) record poisoned frames into the table from the memory_failure() path
    6) reserve the inherited frames before the allocator comes up

This was initially discussed at
https://lore.kernel.org/all/ajut_LDQGYCShApx@gmail.com/

A special thanks to Kiryl Shutsemau, for feedbacks and suggestions.

[1] https://arxiv.org/abs/2408.15302

To: Ard Biesheuvel <ardb@kernel.org>
To: Ilias Apalodimas <ilias.apalodimas@linaro.org>
To: Miaohe Lin <linmiaohe@huawei.com>
To: Naoya Horiguchi <nao.horiguchi@gmail.com>
To: Andrew Morton <akpm@linux-foundation.org>
Cc: linux-efi@vger.kernel.org
Cc: linux-kernel@vger.kernel.org
Cc: linux-mm@kvack.org
Cc: rmikey@meta.com
Cc: kas@kernel.org
Cc: riel@surriel.com
Cc: kexec@lists.infradead.org

Signed-off-by: Breno Leitao <leitao@debian.org>
---
Changes in v2:
- Replace the growable linked list of 4KB entries with a fixed-size
  bitmap, one bit per 2MB, modeled on the unaccepted-memory table (Kiryl)
- Record hard offlines only, by hooking action_result() instead of
  num_poisoned_pages_inc(), which also fires for soft offline (Kiryl)
- Allocate the table as EFI_ACPI_RECLAIM_MEMORY, so it is not System RAM
  in the next kernel, and reuse an inherited table instead of installing
  a second one
- Validate the geometry of an inherited table before using it
- Cap the table at 1MB, coarsening the unit instead of growing it
- Restrict to 64-bit, as the unaccepted-memory table effectively is
- Never clear a bit: an unpoison no longer un-records the unit
- Split the table definition and the stub installer into separate patches
- Link to v1: https://patch.msgid.link/20260717-hwpoison-kho-v1-0-9c5eda551998@debian.org

---
Breno Leitao (6):
      efi/libstub: add a helper for the top of usable RAM
      efi: add the LINUX_EFI_POISONED_MEMORY configuration table
      efi/libstub: add the poisoned-memory EFI table
      efi/libstub: install the poisoned-memory table from the stub
      efi: record hardware-poisoned frames into the poisoned-memory table
      efi: respect the poisoned pages coming from previous kernel

 drivers/firmware/efi/Kconfig                   |  10 ++
 drivers/firmware/efi/Makefile                  |   1 +
 drivers/firmware/efi/efi.c                     |   8 +
 drivers/firmware/efi/libstub/efi-stub-helper.c |  89 +++++++++++
 drivers/firmware/efi/libstub/efi-stub.c        |   1 +
 drivers/firmware/efi/libstub/efistub.h         |   8 +
 drivers/firmware/efi/libstub/mem.c             |  53 +++++++
 drivers/firmware/efi/libstub/x86-stub.c        |   2 +
 drivers/firmware/efi/poison.c                  | 197 +++++++++++++++++++++++++
 include/linux/efi.h                            |  21 +++
 mm/memory-failure.c                            |   3 +
 11 files changed, 393 insertions(+)
---
base-commit: b8809969e1d7a591e0f49dd464a5d04b3cf02ab1
change-id: 20260622-hwpoison-kho-fc9db2ada8ba

Best regards,
--  
Breno Leitao <leitao@debian.org>



^ permalink raw reply	[flat|nested] 16+ messages in thread

end of thread, other threads:[~2026-08-21 14:53 UTC | newest]

Thread overview: 16+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-08-21 10:06 [PATCH v2 0/6] efi: mm/memory-failure: keep hardware-poisoned pages out of the next kexec Breno Leitao
2026-08-21 10:06 ` [PATCH v2 1/6] efi/libstub: add a helper for the top of usable RAM Breno Leitao
2026-08-21 11:04   ` Kiryl Shutsemau
2026-08-21 10:06 ` [PATCH v2 2/6] efi: add the LINUX_EFI_POISONED_MEMORY configuration table Breno Leitao
2026-08-21 11:51   ` Kiryl Shutsemau
2026-08-21 12:03     ` Pratyush Yadav
2026-08-21 14:11       ` Breno Leitao
2026-08-21 14:04     ` Breno Leitao
2026-08-21 10:06 ` [PATCH v2 3/6] efi/libstub: add the poisoned-memory EFI table Breno Leitao
2026-08-21 10:06 ` [PATCH v2 4/6] efi/libstub: install the poisoned-memory table from the stub Breno Leitao
2026-08-21 10:06 ` [PATCH v2 5/6] efi: record hardware-poisoned frames into the poisoned-memory table Breno Leitao
2026-08-21 10:06 ` [PATCH v2 6/6] efi: respect the poisoned pages coming from previous kernel Breno Leitao
2026-08-21 12:13   ` Kiryl Shutsemau
2026-08-21 14:03     ` Breno Leitao
2026-08-21 14:53       ` Kiryl Shutsemau
2026-08-21 10:29 ` [PATCH v2 0/6] efi: mm/memory-failure: keep hardware-poisoned pages out of the next kexec Kiryl Shutsemau

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox