arm64: kexec: pass kimage as the only argument to relocation function
authorPasha Tatashin <pasha.tatashin@soleen.com>
Thu, 30 Sep 2021 14:31:05 +0000 (14:31 +0000)
committerWill Deacon <will@kernel.org>
Fri, 1 Oct 2021 12:31:00 +0000 (13:31 +0100)
Currently, kexec relocation function (arm64_relocate_new_kernel) accepts
the following arguments:

head: start of array that contains relocation information.
entry: entry point for new kernel or purgatory.
dtb_mem: first and only argument to entry.

The number of arguments cannot be easily expended, because this
function is also called from HVC_SOFT_RESTART, which preserves only
three arguments. And, also arm64_relocate_new_kernel is written in
assembly but called without stack, thus no place to move extra arguments
to free registers.

Soon, we will need to pass more arguments: once we enable MMU we
will need to pass information about page tables.

Pass kimage to arm64_relocate_new_kernel, and teach it to get the
required fields from kimage.

Signed-off-by: Pasha Tatashin <pasha.tatashin@soleen.com>
Acked-by: Catalin Marinas <catalin.marinas@arm.com>
Link: https://lore.kernel.org/r/20210930143113.1502553-8-pasha.tatashin@soleen.com
Signed-off-by: Will Deacon <will@kernel.org>
arch/arm64/kernel/asm-offsets.c
arch/arm64/kernel/machine_kexec.c
arch/arm64/kernel/relocate_kernel.S

index 551427a..1d3319c 100644 (file)
@@ -9,6 +9,7 @@
 
 #include <linux/arm_sdei.h>
 #include <linux/sched.h>
+#include <linux/kexec.h>
 #include <linux/mm.h>
 #include <linux/dma-mapping.h>
 #include <linux/kvm_host.h>
@@ -171,5 +172,11 @@ int main(void)
 #endif
   BLANK();
 #endif
+#ifdef CONFIG_KEXEC_CORE
+  DEFINE(KIMAGE_ARCH_DTB_MEM,          offsetof(struct kimage, arch.dtb_mem));
+  DEFINE(KIMAGE_HEAD,                  offsetof(struct kimage, head));
+  DEFINE(KIMAGE_START,                 offsetof(struct kimage, start));
+  BLANK();
+#endif
   return 0;
 }
index 7f1cb5a..e210b19 100644 (file)
@@ -84,6 +84,9 @@ static void kexec_list_flush(struct kimage *kimage)
 {
        kimage_entry_t *entry;
 
+       dcache_clean_inval_poc((unsigned long)kimage,
+                              (unsigned long)kimage + sizeof(*kimage));
+
        for (entry = &kimage->head; ; entry++) {
                unsigned int flag;
                unsigned long addr;
@@ -206,8 +209,8 @@ void machine_kexec(struct kimage *kimage)
                restart(is_hyp_nvhe(), kimage->start, kimage->arch.dtb_mem,
                        0, 0);
        } else {
-               cpu_soft_restart(kimage->arch.kern_reloc, kimage->head,
-                                kimage->start, kimage->arch.dtb_mem);
+               cpu_soft_restart(kimage->arch.kern_reloc, virt_to_phys(kimage),
+                                0, 0);
        }
 
        BUG(); /* Should never get here. */
index 8c43779..63ea198 100644 (file)
@@ -27,9 +27,7 @@
  */
 SYM_CODE_START(arm64_relocate_new_kernel)
        /* Setup the list loop variables. */
-       mov     x18, x2                         /* x18 = dtb address */
-       mov     x17, x1                         /* x17 = kimage_start */
-       mov     x16, x0                         /* x16 = kimage_head */
+       ldr     x16, [x0, #KIMAGE_HEAD]         /* x16 = kimage_head */
        mov     x14, xzr                        /* x14 = entry ptr */
        mov     x13, xzr                        /* x13 = copy dest */
        raw_dcache_line_size x15, x1            /* x15 = dcache line size */
@@ -63,12 +61,12 @@ SYM_CODE_START(arm64_relocate_new_kernel)
        isb
 
        /* Start new image. */
-       mov     x0, x18
+       ldr     x4, [x0, #KIMAGE_START]         /* relocation start */
+       ldr     x0, [x0, #KIMAGE_ARCH_DTB_MEM]  /* dtb address */
        mov     x1, xzr
        mov     x2, xzr
        mov     x3, xzr
-       br      x17
-
+       br      x4
 SYM_CODE_END(arm64_relocate_new_kernel)
 
 .align 3       /* To keep the 64-bit values below naturally aligned. */