mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
* [RFC PATCH 0/2] memblock: keep reserve_mem regions out of KHO bootmem
@ 2026-10-21 21:10 Jose A. Perez de Azpillaga
  2026-10-21 21:10 ` [RFC PATCH 1/2] memblock: factor out the KHO bootmem check from memblock_alloc_hugetlb() Jose A. Perez de Azpillaga
  2026-10-21 21:10 ` [RFC PATCH 2/2] memblock: don't allocate reserve_mem regions from KHO bootmem Jose A. Perez de Azpillaga
  0 siblings, 2 replies; 3+ messages in thread
From: Jose A. Perez de Azpillaga @ 2026-10-21 21:10 UTC (permalink / raw)
  To: Mike Rapoport, Andrew Morton, Kees Cook, Alexander Graf, Changyuan Lyu
  Cc: Tony Luck, Guilherme G. Piccoli, linux-mm, linux-kernel,
	Pratyush Yadav, Pasha Tatashin, kexec,
	Jose A. Perez de Azpillaga

On a KHO boot, a reserve_mem= region that can't be revived (new name,
size or alignment) can be allocated from KHO bootmem, which the next
kernel boots out of. With CONFIG_KEXEC_HANDOVER_DEBUG preserving it
fails; without it, the next kernel's memmap ends up on top of it.

Patch 1 factors the bootmem check out of memblock_alloc_hugetlb(), and
patch 2 uses it for reserve_mem. That also drops the TODO in
reserve_mem(), which asks for the allocation to be outside KHO_NOPRSRV,
though it's bootmem it has to stay out of.

Questions:

- If kho_discover_noprsrv() fails, only bootmem is NOPRSRV, and
  reserve_mem() now fails with -ENOMEM instead of using it. Is that the
  right thing to do?

- Should reserve_mem skip mirrored memory like HugeTLB does, rather
  than keep the fallback?

No Cc: stable, since patch 2 relies on 14773e2aa4c5 ("kho: extend
scratch") for room outside bootmem.

Based on next-20261021, as it needs the KHO bootmem rename from
liveupdate-7.4 and touches code changed in memblock for-next.

Tested on x86_64 in QEMU.

Jose A. Perez de Azpillaga (2):
  memblock: factor out the KHO bootmem check from
    memblock_alloc_hugetlb()
  memblock: don't allocate reserve_mem regions from KHO bootmem

 mm/memblock.c | 100 ++++++++++++++++++++++++++++++++------------------
 1 file changed, 64 insertions(+), 36 deletions(-)


base-commit: 9a482184d910775cf648863148944945b74e2815
--
2.55.0


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

* [RFC PATCH 1/2] memblock: factor out the KHO bootmem check from memblock_alloc_hugetlb()
  2026-10-21 21:10 [RFC PATCH 0/2] memblock: keep reserve_mem regions out of KHO bootmem Jose A. Perez de Azpillaga
@ 2026-10-21 21:10 ` Jose A. Perez de Azpillaga
  2026-10-21 21:10 ` [RFC PATCH 2/2] memblock: don't allocate reserve_mem regions from KHO bootmem Jose A. Perez de Azpillaga
  1 sibling, 0 replies; 3+ messages in thread
From: Jose A. Perez de Azpillaga @ 2026-10-21 21:10 UTC (permalink / raw)
  To: Mike Rapoport, Andrew Morton, Kees Cook, Alexander Graf, Changyuan Lyu
  Cc: Tony Luck, Guilherme G. Piccoli, linux-mm, linux-kernel,
	Pratyush Yadav, Pasha Tatashin, kexec,
	Jose A. Perez de Azpillaga

reserve_mem regions are preserved with KHO too, and need the same search
that keeps HugeTLB pages out of KHO bootmem. Move it into a helper.

No functional change intended.

Signed-off-by: Jose A. Perez de Azpillaga <azpijr@gmail.com>
---
 mm/memblock.c | 70 ++++++++++++++++++++++++++-------------------------
 1 file changed, 36 insertions(+), 34 deletions(-)

diff --git a/mm/memblock.c b/mm/memblock.c
index a450092a80fb..f43659688681 100644
--- a/mm/memblock.c
+++ b/mm/memblock.c
@@ -1744,6 +1744,31 @@ void * __init memblock_alloc_try_nid_raw(
 	return memblock_alloc_internal(size, align, min_addr, max_addr, nid);
 }
 
+/*
+ * Memory that can be preserved with KHO can't be in KHO bootmem, since the
+ * next kernel boots out of it. Bootmem areas are normally not very large, so
+ * this shouldn't take too many retries.
+ */
+static phys_addr_t __init memblock_find_outside_kho_bootmem(phys_addr_t size,
+					phys_addr_t align, int nid,
+					enum memblock_flags flags)
+{
+	phys_addr_t addr, start = 0, end = MEMBLOCK_ALLOC_ACCESSIBLE;
+
+	while ((addr = memblock_find_in_range_node(size, align, start, end,
+						   nid, flags))) {
+		if (!kho_bootmem_overlap(addr, size))
+			break;
+
+		if (memblock_bottom_up())
+			start = addr + size;
+		else
+			end = addr;
+	}
+
+	return addr;
+}
+
 /**
  * memblock_alloc_hugetlb - allocate boot memory for HugeTLB pages
  * @size:      size of the memory to be allocated in bytes
@@ -1761,52 +1786,29 @@ void * __init memblock_alloc_try_nid_raw(
 void * __init memblock_alloc_hugetlb(phys_addr_t size, int nid, bool exact_nid)
 {
 	enum memblock_flags flags = choose_memblock_flags();
-	phys_addr_t addr, start = 0, end = MEMBLOCK_ALLOC_ACCESSIBLE;
+	phys_addr_t addr;
 
 	memblock_dbg("%s: %llu bytes, nid=%d, exact_nid=%d %pS\n", __func__,
 		     (u64)size, nid, exact_nid, (void *)_RET_IP_);
 
 	/* Don't waste mirrored memory on HugeTLB pages. */
 	flags &= ~MEMBLOCK_MIRROR;
-retry:
-	/* HugeTLB pages are always aligned by their size. */
-	addr = memblock_find_in_range_node(size, size, start, end, nid, flags);
-	if (addr)
-		goto found;
+
+	/*
+	 * HugeTLB pages are always aligned by their size, and can be preserved
+	 * with KHO.
+	 */
+	addr = memblock_find_outside_kho_bootmem(size, size, nid, flags);
 
 	/* Try all nodes if allowed. */
-	if (numa_valid_node(nid) && !exact_nid) {
+	if (!addr && numa_valid_node(nid) && !exact_nid) {
 		nid = NUMA_NO_NODE;
-		/*
-		 * If a previous candidate overlapped with KHO bootmem, it would
-		 * update start or end. Now that the search is opening to all
-		 * nodes, reset them.
-		 */
-		start = 0;
-		end = MEMBLOCK_ALLOC_ACCESSIBLE;
-
-		goto retry;
+		addr = memblock_find_outside_kho_bootmem(size, size, nid, flags);
 	}
 
 	/* Found nothing... :-( */
-	return NULL;
-
-found:
-	/*
-	 * HugeTLB pages can be preserved with KHO and no preserved memory can
-	 * be in bootmem. So retry if found address overlaps with bootmem.
-	 *
-	 * Bootmem areas are normally not very large, so this shouldn't take too
-	 * many retries.
-	 */
-	if (kho_bootmem_overlap(addr, size)) {
-		if (memblock_bottom_up())
-			start = addr + size;
-		else
-			end = addr;
-
-		goto retry;
-	}
+	if (!addr)
+		return NULL;
 
 	if (__memblock_reserve(addr, size, nid, MEMBLOCK_RSRV_KERN | MEMBLOCK_RSRV_HUGETLB))
 		return NULL;
-- 
2.55.0


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

* [RFC PATCH 2/2] memblock: don't allocate reserve_mem regions from KHO bootmem
  2026-10-21 21:10 [RFC PATCH 0/2] memblock: keep reserve_mem regions out of KHO bootmem Jose A. Perez de Azpillaga
  2026-10-21 21:10 ` [RFC PATCH 1/2] memblock: factor out the KHO bootmem check from memblock_alloc_hugetlb() Jose A. Perez de Azpillaga
@ 2026-10-21 21:10 ` Jose A. Perez de Azpillaga
  1 sibling, 0 replies; 3+ messages in thread
From: Jose A. Perez de Azpillaga @ 2026-10-21 21:10 UTC (permalink / raw)
  To: Mike Rapoport, Andrew Morton, Kees Cook, Alexander Graf, Changyuan Lyu
  Cc: Tony Luck, Guilherme G. Piccoli, linux-mm, linux-kernel,
	Pratyush Yadav, Pasha Tatashin, kexec,
	Jose A. Perez de Azpillaga

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@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


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

end of thread, other threads:[~2026-10-21 21:11 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-10-21 21:10 [RFC PATCH 0/2] memblock: keep reserve_mem regions out of KHO bootmem Jose A. Perez de Azpillaga
2026-10-21 21:10 ` [RFC PATCH 1/2] memblock: factor out the KHO bootmem check from memblock_alloc_hugetlb() Jose A. Perez de Azpillaga
2026-10-21 21:10 ` [RFC PATCH 2/2] memblock: don't allocate reserve_mem regions from KHO bootmem Jose A. Perez de Azpillaga

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®