* [PATCH v2] liveupdate: kho: calculate per-node bootmem sizes before allocating any
@ 2026-10-29 10:34 George Guo
0 siblings, 0 replies; only message in thread
From: George Guo @ 2026-10-29 10:34 UTC (permalink / raw)
To: rppt, pasha.tatashin, pratyush
Cc: graf, changyuanl, akpm, chenhuacai, sourabhjain, liukexin,
guodongtai, kexec, linux-mm, loongarch, linux-kernel
From: George Guo <guodongtai@kylinos.cn>
kho_reserve_bootmem() calculated the per-node bootmem sizes inside the
allocation loop, after the lowmem and global areas had been allocated.
Without CONFIG_NUMA, memblock_get_region_node() returns 0 for every
region, and memblock_reserved_kern_size() attributes a region to a node
by memblock_get_region_node(). Since allocations are marked
MEMBLOCK_RSRV_KERN, the newly allocated lowmem and global areas enter
node 0's baseline and are scaled again by bootmem_size_node().
In the original 1 GiB QEMU reproducer, the default 200% scale made
node 0 request 672 MiB: twice the sum of the 98.45 MiB baseline and
224 MiB lowmem area, rounded up to 32 MiB alignment. The reservation
failed and KHO disabled itself.
With CONFIG_NUMA=y, node-specific accounting excludes the NUMA_NO_NODE
reservations.
The lowmem and global sizes are already calculated by
bootmem_size_update() before any allocation. Calculate the per-node
sizes into the kho_bootmem descriptors before reserving any bootmem
area as well, and allocate the per-node areas from the stored sizes.
Use separate read and write indices to preserve the saved sizes when
zero-sized per-node areas are skipped.
Fixes: 3dc92c311498 ("kexec: add Kexec HandOver (KHO) generation helpers")
Reported-by: Kexin Liu <liukexin@kylinos.cn>
Co-developed-by: Kexin Liu <liukexin@kylinos.cn>
Signed-off-by: Kexin Liu <liukexin@kylinos.cn>
Signed-off-by: George Guo <guodongtai@kylinos.cn>
---
Changes in v2:
- Calculate every size before any allocation (Mike). The lowmem and
global sizes are already calculated by bootmem_size_update(), so only
the per-node sizes move out of the allocation loop.
- Rebase onto liveupdate-7.4: follow the "scratch" to "bootmem" rename,
and keep the zero-size node skip added by "kho: do not reserve empty
per-node bootmem areas" by reading the saved sizes with a separate
index.
- Explain why only CONFIG_NUMA=n kernels are affected (Pratyush, Sourabh).
- The global size over-allocation on NUMA systems, which I planned to
look at as a follow-up, is handled by Sourabh's "kho: fix global
scratch size calculation" [1]. Mike asked there for a broader rework
of the sizing; this patch only fixes the CONFIG_NUMA=n double
counting.
- No Assisted-by tag, although I said on v1 that I would add one: the
Assisted-by references have since been removed from the documentation
in mainline.
Tested with the KHO vmtest on a 1 GiB LoongArch QEMU guest, with the
LoongArch KHO series on top: it passes with both CONFIG_NUMA=n and
CONFIG_NUMA=y. Without this patch, KHO disables itself in the
CONFIG_NUMA=n run.
v1: https://lore.kernel.org/all/20260904025101.9959-1-dongtai.guo@linux.dev/
[1] https://lore.kernel.org/all/20260922131217.698809-1-sourabhjain@linux.ibm.com/
kernel/liveupdate/kexec_handover.c | 17 +++++++++++++++--
1 file changed, 15 insertions(+), 2 deletions(-)
diff --git a/kernel/liveupdate/kexec_handover.c b/kernel/liveupdate/kexec_handover.c
index 6f1f55fe3181..9a53d7750367 100644
--- a/kernel/liveupdate/kexec_handover.c
+++ b/kernel/liveupdate/kexec_handover.c
@@ -831,7 +831,7 @@ bool kho_bootmem_overlap(phys_addr_t phys, size_t size)
*/
static void __init kho_reserve_bootmem(void)
{
- int nid, i = 0, max_nr_bootmem;
+ int nid, i, j, max_nr_bootmem;
phys_addr_t addr, size;
if (!kho_enable)
@@ -848,6 +848,15 @@ static void __init kho_reserve_bootmem(void)
goto err_disable_kho;
}
+ /*
+ * Save the per-node sizes before allocating bootmem areas. Without
+ * CONFIG_NUMA, new lowmem and global allocations would otherwise be
+ * counted as node 0 kernel reservations and scaled again.
+ */
+ j = 2;
+ for_each_node_state(nid, N_MEMORY)
+ kho_bootmem[j++].size = bootmem_size_node(nid);
+
/*
* reserve bootmem area in low memory for lowmem allocations in the
* next kernel
@@ -860,6 +869,7 @@ static void __init kho_reserve_bootmem(void)
goto err_free_bootmem_desc;
}
+ i = 0;
kho_bootmem[i].addr = addr;
kho_bootmem[i].size = size;
i++;
@@ -879,9 +889,12 @@ static void __init kho_reserve_bootmem(void)
/*
* Loop over nodes that have both memory and are online. Skip
* memoryless nodes, as we can not allocate bootmem areas there.
+ * Skipping zero-sized areas leaves i behind j, so writes to
+ * kho_bootmem[i] cannot overwrite unread sizes.
*/
+ j = i;
for_each_node_state(nid, N_MEMORY) {
- size = bootmem_size_node(nid);
+ size = kho_bootmem[j++].size;
if (!size)
continue;
base-commit: 9a6a70aefe77f6fb9ff2b3037dcf87f6dff65c8c
--
2.53.0
^ permalink raw reply [flat|nested] only message in thread
only message in thread, other threads:[~2026-10-29 10:34 UTC | newest]
Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-10-29 10:34 [PATCH v2] liveupdate: kho: calculate per-node bootmem sizes before allocating any George Guo
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®