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 <[email protected]>
---
 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


Reply via email to