Since we are going to keep MMU enabled during relocation, we need to
keep EL1 mode throughout the relocation.

Keep EL1 enabled, and switch EL2 only before enterying the new world.

Suggested-by: James Morse <[email protected]>
Signed-off-by: Pavel Tatashin <[email protected]>
---
 arch/arm64/kernel/cpu-reset.h       |  3 +--
 arch/arm64/kernel/machine_kexec.c   |  4 ++--
 arch/arm64/kernel/relocate_kernel.S | 13 +++++++++++--
 3 files changed, 14 insertions(+), 6 deletions(-)

diff --git a/arch/arm64/kernel/cpu-reset.h b/arch/arm64/kernel/cpu-reset.h
index 48d0ed48c147..296abbac7192 100644
--- a/arch/arm64/kernel/cpu-reset.h
+++ b/arch/arm64/kernel/cpu-reset.h
@@ -20,11 +20,10 @@ static inline void __noreturn __nocfi 
cpu_soft_restart(unsigned long entry,
 {
        typeof(__cpu_soft_restart) *restart;
 
-       unsigned long el2_switch = is_hyp_callable();
        restart = (void *)__pa_symbol(function_nocfi(__cpu_soft_restart));
 
        cpu_install_idmap();
-       restart(el2_switch, entry, arg0, arg1, arg2);
+       restart(0, entry, arg0, arg1, arg2);
        unreachable();
 }
 
diff --git a/arch/arm64/kernel/machine_kexec.c 
b/arch/arm64/kernel/machine_kexec.c
index 9f74791cb1d0..c9993f029262 100644
--- a/arch/arm64/kernel/machine_kexec.c
+++ b/arch/arm64/kernel/machine_kexec.c
@@ -231,8 +231,8 @@ void machine_kexec(struct kimage *kimage)
        } else {
                if (is_hyp_callable())
                        __hyp_set_vectors(kimage->arch.el2_vectors);
-               cpu_soft_restart(kimage->arch.kern_reloc, virt_to_phys(kimage),
-                                0, 0);
+               cpu_soft_restart(kimage->arch.kern_reloc,
+                                virt_to_phys(kimage), 0, 0);
        }
 
        BUG(); /* Should never get here. */
diff --git a/arch/arm64/kernel/relocate_kernel.S 
b/arch/arm64/kernel/relocate_kernel.S
index 36b4496524c3..df023b82544b 100644
--- a/arch/arm64/kernel/relocate_kernel.S
+++ b/arch/arm64/kernel/relocate_kernel.S
@@ -13,6 +13,7 @@
 #include <asm/kexec.h>
 #include <asm/page.h>
 #include <asm/sysreg.h>
+#include <asm/virt.h>
 
 /*
  * arm64_relocate_new_kernel - Put a 2nd stage image in place and boot it.
@@ -61,12 +62,20 @@ SYM_CODE_START(arm64_relocate_new_kernel)
        isb
 
        /* Start new image. */
+       ldr     x1, [x0, #KIMAGE_ARCH_EL2_VECTORS]      /* relocation start */
+       cbz     x1, .Lel1
+       ldr     x1, [x0, #KIMAGE_START]         /* relocation start */
+       ldr     x2, [x0, #KIMAGE_ARCH_DTB_MEM]  /* dtb address */
+       mov     x3, xzr
+       mov     x4, xzr
+       mov     x0, #HVC_SOFT_RESTART
+       hvc     #0                              /* Jumps from el2 */
+.Lel1:
        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      x4
+       br      x4                              /* Jumps from el1 */
 SYM_CODE_END(arm64_relocate_new_kernel)
 
 .align 3       /* To keep the 64-bit values below naturally aligned. */
-- 
2.25.1


_______________________________________________
kexec mailing list
[email protected]
http://lists.infradead.org/mailman/listinfo/kexec

Reply via email to