Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

arm64: kexec: pass kimage as the only argument to relocation function

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>

authored by

Pasha Tatashin and committed by
Will Deacon
878fdbd7 3036ec59

+16 -8
+7
arch/arm64/kernel/asm-offsets.c
··· 9 9 10 10 #include <linux/arm_sdei.h> 11 11 #include <linux/sched.h> 12 + #include <linux/kexec.h> 12 13 #include <linux/mm.h> 13 14 #include <linux/dma-mapping.h> 14 15 #include <linux/kvm_host.h> ··· 170 169 #ifdef CONFIG_ARM64_PTR_AUTH_KERNEL 171 170 DEFINE(PTRAUTH_KERNEL_KEY_APIA, offsetof(struct ptrauth_keys_kernel, apia)); 172 171 #endif 172 + BLANK(); 173 + #endif 174 + #ifdef CONFIG_KEXEC_CORE 175 + DEFINE(KIMAGE_ARCH_DTB_MEM, offsetof(struct kimage, arch.dtb_mem)); 176 + DEFINE(KIMAGE_HEAD, offsetof(struct kimage, head)); 177 + DEFINE(KIMAGE_START, offsetof(struct kimage, start)); 173 178 BLANK(); 174 179 #endif 175 180 return 0;
+5 -2
arch/arm64/kernel/machine_kexec.c
··· 84 84 { 85 85 kimage_entry_t *entry; 86 86 87 + dcache_clean_inval_poc((unsigned long)kimage, 88 + (unsigned long)kimage + sizeof(*kimage)); 89 + 87 90 for (entry = &kimage->head; ; entry++) { 88 91 unsigned int flag; 89 92 unsigned long addr; ··· 209 206 restart(is_hyp_nvhe(), kimage->start, kimage->arch.dtb_mem, 210 207 0, 0); 211 208 } else { 212 - cpu_soft_restart(kimage->arch.kern_reloc, kimage->head, 213 - kimage->start, kimage->arch.dtb_mem); 209 + cpu_soft_restart(kimage->arch.kern_reloc, virt_to_phys(kimage), 210 + 0, 0); 214 211 } 215 212 216 213 BUG(); /* Should never get here. */
+4 -6
arch/arm64/kernel/relocate_kernel.S
··· 27 27 */ 28 28 SYM_CODE_START(arm64_relocate_new_kernel) 29 29 /* Setup the list loop variables. */ 30 - mov x18, x2 /* x18 = dtb address */ 31 - mov x17, x1 /* x17 = kimage_start */ 32 - mov x16, x0 /* x16 = kimage_head */ 30 + ldr x16, [x0, #KIMAGE_HEAD] /* x16 = kimage_head */ 33 31 mov x14, xzr /* x14 = entry ptr */ 34 32 mov x13, xzr /* x13 = copy dest */ 35 33 raw_dcache_line_size x15, x1 /* x15 = dcache line size */ ··· 61 63 isb 62 64 63 65 /* Start new image. */ 64 - mov x0, x18 66 + ldr x4, [x0, #KIMAGE_START] /* relocation start */ 67 + ldr x0, [x0, #KIMAGE_ARCH_DTB_MEM] /* dtb address */ 65 68 mov x1, xzr 66 69 mov x2, xzr 67 70 mov x3, xzr 68 - br x17 69 - 71 + br x4 70 72 SYM_CODE_END(arm64_relocate_new_kernel) 71 73 72 74 .align 3 /* To keep the 64-bit values below naturally aligned. */