[RFC PATCH 2/2] memblock: don't allocate reserve_mem regions from KHO bootmem
Jose A. Perez de Azpillaga
azpijr at gmail.com
Wed Oct 21 14:10:46 PDT 2026
On a KHO boot, a reserve_mem region that can't be revived is allocated
from KHO_NOPRSRV memory, which includes the bootmem the next kernel
boots out of. With CONFIG_KEXEC_HANDOVER_DEBUG, preserving the region
then fails:
WARNING: kernel/liveupdate/kexec_handover.c:1245 at kho_preserve_pages+0x168/0x180
failed to prepare memblock FDT for KHO: -22
Without it, the next kernel puts its memmap on top of the region and
the ramoops records in it are lost.
Use the search that keeps HugeTLB pages out of bootmem, and keep the
mirrored memory fallback of memblock_phys_alloc().
Fixes: f99230780211 ("memblock: add KHO support for reserve_mem")
Signed-off-by: Jose A. Perez de Azpillaga <azpijr at gmail.com>
---
mm/memblock.c | 30 ++++++++++++++++++++++++++++--
1 file changed, 28 insertions(+), 2 deletions(-)
diff --git a/mm/memblock.c b/mm/memblock.c
index f43659688681..0fa9d6529285 100644
--- a/mm/memblock.c
+++ b/mm/memblock.c
@@ -2761,6 +2761,33 @@ static bool __init reserve_mem_kho_revive(const char *name, phys_addr_t size,
}
#endif /* CONFIG_KEXEC_HANDOVER */
+/*
+ * The region gets preserved with KHO, so it can't be in KHO bootmem. On a KHO
+ * boot only KHO_NOPRSRV memory is used at this point, and that is more than
+ * just bootmem.
+ */
+static phys_addr_t __init reserve_mem_alloc(phys_addr_t size, phys_addr_t align)
+{
+ enum memblock_flags flags = choose_memblock_flags();
+ phys_addr_t start;
+
+ start = memblock_find_outside_kho_bootmem(size, align, NUMA_NO_NODE,
+ flags);
+ if (!start && (flags & MEMBLOCK_MIRROR)) {
+ pr_warn("Could not allocate %pap bytes of mirrored memory\n",
+ &size);
+ start = memblock_find_outside_kho_bootmem(size, align,
+ NUMA_NO_NODE,
+ flags & ~MEMBLOCK_MIRROR);
+ }
+
+ if (!start || memblock_reserve_kern(start, size))
+ return 0;
+
+ memblock_prep_allocation(start, size, true);
+ return start;
+}
+
/*
* Parse reserve_mem=nn:align:name
*/
@@ -2829,8 +2856,7 @@ static int __init reserve_mem(char *p)
if (reserve_mem_kho_revive(name, size, align))
return 1;
- /* TODO: Allocation must be outside of KHO_NOPRSRV region */
- start = memblock_phys_alloc(size, align);
+ start = reserve_mem_alloc(size, align);
if (!start) {
pr_err("reserve_mem: memblock allocation failed\n");
return -ENOMEM;
--
2.55.0
More information about the kexec
mailing list