Re: [PATCH v9 13/18] arm64: kexec: add expandable argument to relocation function
From: James Morse <james.morse@arm.com>
Date: 2020-05-07 16:22:23
Also in:
kexec, linux-mm, lkml
Hi Pavel, On 26/03/2020 03:24, Pavel Tatashin wrote:
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.
Another benefit of allowing this function to accept more arguments, is that kernel can actually accept up to 4 arguments (x0-x3), however currently only one is used, but if in the future we will need for more (for example, pass information about when previous kernel exited to have a precise measurement in time spent in purgatory), we won't be easilty do that if arm64_relocate_new_kernel can't accept more arguments.
This is a niche debug hack. We really don't want an ABI with purgatory. I think the register values it gets were added early for compatibility with kexec_file_load().
So, add a new struct: kern_reloc_arg, and place it in kexec safe page (i.e memory that is not overwritten during relocation). Thus, make arm64_relocate_new_kernel to only take one argument, that contains all the needed information.
Do we really not have enough registers? The PCS[0] gives you 8 arguments. In this patch you use 6. If this is really about the hyp-stub abi, please state that.
quoted hunk ↗ jump to hunk
diff --git a/arch/arm64/kernel/machine_kexec.c b/arch/arm64/kernel/machine_kexec.c index cee3be586384..b1122eea627e 100644 --- a/arch/arm64/kernel/machine_kexec.c +++ b/arch/arm64/kernel/machine_kexec.c@@ -59,13 +60,35 @@ void machine_kexec_cleanup(struct kimage *kimage)
int machine_kexec_post_load(struct kimage *kimage)
{
void *reloc_code = page_to_virt(kimage->control_code_page);
+ struct kern_reloc_arg *kern_reloc_arg = kexec_page_alloc(kimage);
+
+ if (!kern_reloc_arg)
+ return -ENOMEM;
memcpy(reloc_code, arm64_relocate_new_kernel,
arm64_relocate_new_kernel_size);
kimage->arch.kern_reloc = __pa(reloc_code);
+ kimage->arch.kern_reloc_arg = __pa(kern_reloc_arg);
+ kern_reloc_arg->head = kimage->head;
+ kern_reloc_arg->entry_addr = kimage->start;
+ kern_reloc_arg->kern_arg0 = kimage->arch.dtb_mem;These kern_reloc_arg values are written via the cacheable linear map. They are read in arm64_relocate_new_kernel() where the MMU is disabled an all memory access are non-cacheable. To ensure you read the values you wrote, you must clean kern_reloc_arg to the PoC.
kexec_image_info(kimage); return 0;Thanks,
James [0] https://developer.arm.com/docs/ihi0055/d/procedure-call-standard-for-the-arm-64-bit-architecture _______________________________________________ linux-arm-kernel mailing list linux-arm-kernel@lists.infradead.org http://lists.infradead.org/mailman/listinfo/linux-arm-kernel