summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPasha Tatashin <pasha.tatashin@soleen.com>2021-09-30 16:31:07 +0200
committerWill Deacon <will@kernel.org>2021-10-01 14:31:00 +0200
commitba959fe96a1bbb98765762da20ecb3a6eb9c9d39 (patch)
treec43ad3d51524e52e34d11398c0f0881e424ea055
parentarm64: kexec: configure EL2 vectors for kexec (diff)
downloadlinux-ba959fe96a1bbb98765762da20ecb3a6eb9c9d39.tar.xz
linux-ba959fe96a1bbb98765762da20ecb3a6eb9c9d39.zip
arm64: kexec: relocate in EL1 mode
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 entering the new world. Suggested-by: James Morse <james.morse@arm.com> 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-10-pasha.tatashin@soleen.com Signed-off-by: Will Deacon <will@kernel.org>
-rw-r--r--arch/arm64/kernel/cpu-reset.h3
-rw-r--r--arch/arm64/kernel/machine_kexec.c4
-rw-r--r--arch/arm64/kernel/relocate_kernel.S13
3 files changed, 14 insertions, 6 deletions
diff --git a/arch/arm64/kernel/cpu-reset.h b/arch/arm64/kernel/cpu-reset.h
index 81b3d0fe7a63..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_nvhe();
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 59a4b4172b68..cf5d6f22a041 100644
--- a/arch/arm64/kernel/machine_kexec.c
+++ b/arch/arm64/kernel/machine_kexec.c
@@ -240,8 +240,8 @@ void machine_kexec(struct kimage *kimage)
} else {
if (is_hyp_nvhe())
__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 63ea19868f63..b4fb97312a80 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. */