[PATCH] kho: try to allocate contiguous memory for kexec segments

Michal Clapinski mclapinski at google.com
Mon Jun 1 12:30:14 PDT 2026


This allows us to skip relocations (and maybe checksum calculation
in the future).

kho_scratch is marked as MIGRATE_CMA but isn't actually given to the
CMA, so it should only contain movable allocations, therefore this
should always succeed.

Signed-off-by: Michal Clapinski <mclapinski at google.com>
---
 kernel/kexec_core.c                |  6 +++++-
 kernel/liveupdate/kexec_handover.c | 21 +++++++++++++++++----
 2 files changed, 22 insertions(+), 5 deletions(-)

diff --git a/kernel/kexec_core.c b/kernel/kexec_core.c
index dc770b9a6d05..cba3ce985aa9 100644
--- a/kernel/kexec_core.c
+++ b/kernel/kexec_core.c
@@ -43,6 +43,7 @@
 #include <linux/kmsg_dump.h>
 #include <linux/dma-map-ops.h>
 #include <linux/sysfs.h>
+#include <linux/kexec_handover.h>
 
 #include <asm/page.h>
 #include <asm/sections.h>
@@ -566,7 +567,10 @@ static void kimage_free_cma(struct kimage *image)
 			continue;
 
 		arch_kexec_pre_free_pages(page_address(cma), nr_pages);
-		dma_release_from_contiguous(NULL, cma, nr_pages);
+		if (kho_is_enabled())
+			free_contig_range(page_to_pfn(cma), nr_pages);
+		else
+			dma_release_from_contiguous(NULL, cma, nr_pages);
 		image->segment_cma[i] = NULL;
 	}
 
diff --git a/kernel/liveupdate/kexec_handover.c b/kernel/liveupdate/kexec_handover.c
index 4834a809985a..289fd5948fd2 100644
--- a/kernel/liveupdate/kexec_handover.c
+++ b/kernel/liveupdate/kexec_handover.c
@@ -1770,15 +1770,28 @@ static int kho_walk_scratch(struct kexec_buf *kbuf,
 	return ret;
 }
 
+static void kho_try_alloc_contig(struct kexec_buf *kbuf)
+{
+	unsigned long start_pfn = PFN_DOWN(kbuf->mem);
+	unsigned long nr_pages = kbuf->memsz >> PAGE_SHIFT;
+
+	if (alloc_contig_range(start_pfn, start_pfn + nr_pages,
+			       ACR_FLAGS_CMA, GFP_KERNEL))
+		return;
+
+	kbuf->cma = pfn_to_page(start_pfn);
+	arch_kexec_post_alloc_pages(page_address(kbuf->cma), nr_pages, 0);
+}
+
 int kho_locate_mem_hole(struct kexec_buf *kbuf,
 			int (*func)(struct resource *, void *))
 {
-	int ret;
-
 	if (!kho_enable || kbuf->image->type == KEXEC_TYPE_CRASH)
 		return 1;
 
-	ret = kho_walk_scratch(kbuf, func);
+	if (!kho_walk_scratch(kbuf, func))
+		return -EADDRNOTAVAIL;
 
-	return ret == 1 ? 0 : -EADDRNOTAVAIL;
+	kho_try_alloc_contig(kbuf);
+	return 0;
 }
-- 
2.54.0.929.g9b7fa37559-goog




More information about the kexec mailing list