diff mbox series

[v17,05/15] arm64: kexec: skip relocation code for inplace kexec

Message ID 20210916231325.125533-6-pasha.tatashin@soleen.com (mailing list archive)
State New
Headers show
Series arm64: MMU enabled kexec relocation | expand

Commit Message

Pasha Tatashin Sept. 16, 2021, 11:13 p.m. UTC
In case of kdump or when segments are already in place the relocation
is not needed, therefore the setup of relocation function and call to
it can be skipped.

Signed-off-by: Pasha Tatashin <pasha.tatashin@soleen.com>
Suggested-by: James Morse <james.morse@arm.com>
---
 arch/arm64/kernel/machine_kexec.c   | 34 ++++++++++++++++++-----------
 arch/arm64/kernel/relocate_kernel.S |  3 ---
 2 files changed, 21 insertions(+), 16 deletions(-)

Comments

Will Deacon Sept. 29, 2021, 12:13 p.m. UTC | #1
On Thu, Sep 16, 2021 at 07:13:15PM -0400, Pasha Tatashin wrote:
> In case of kdump or when segments are already in place the relocation
> is not needed, therefore the setup of relocation function and call to
> it can be skipped.
> 
> Signed-off-by: Pasha Tatashin <pasha.tatashin@soleen.com>
> Suggested-by: James Morse <james.morse@arm.com>
> ---
>  arch/arm64/kernel/machine_kexec.c   | 34 ++++++++++++++++++-----------
>  arch/arm64/kernel/relocate_kernel.S |  3 ---
>  2 files changed, 21 insertions(+), 16 deletions(-)

[...]

> @@ -188,19 +190,25 @@ void machine_kexec(struct kimage *kimage)
>  	local_daif_mask();
>  
>  	/*
> -	 * cpu_soft_restart will shutdown the MMU, disable data caches, then
> -	 * transfer control to the kern_reloc which contains a copy of
> -	 * the arm64_relocate_new_kernel routine.  arm64_relocate_new_kernel
> -	 * uses physical addressing to relocate the new image to its final
> -	 * position and transfers control to the image entry point when the
> -	 * relocation is complete.
> +	 * Both restart and cpu_soft_restart will shutdown the MMU, disable data
> +	 * caches. However, restart will start new kernel or purgatory directly,
> +	 * cpu_soft_restart will transfer control to arm64_relocate_new_kernel
>  	 * In kexec case, kimage->start points to purgatory assuming that
>  	 * kernel entry and dtb address are embedded in purgatory by
>  	 * userspace (kexec-tools).
>  	 * In kexec_file case, the kernel starts directly without purgatory.
>  	 */
> -	cpu_soft_restart(kimage->arch.kern_reloc, kimage->head, kimage->start,
> -			 kimage->arch.dtb_mem);
> +	if (kimage->head & IND_DONE) {
> +		typeof(__cpu_soft_restart) *restart;
> +
> +		cpu_install_idmap();
> +		restart = (void *)__pa_symbol(function_nocfi(__cpu_soft_restart));
> +		restart(is_hyp_nvhe(), kimage->start, kimage->arch.dtb_mem,
> +			0, 0);

Why can't you call:

	cpu_soft_restart(kimage->start, kimage->arch.dtb_mem, 0, 0);

here instead of open-coding it?

Will
Pasha Tatashin Sept. 30, 2021, 2:44 a.m. UTC | #2
Hi Will,

> > +             cpu_install_idmap();
> > +             restart = (void *)__pa_symbol(function_nocfi(__cpu_soft_restart));
> > +             restart(is_hyp_nvhe(), kimage->start, kimage->arch.dtb_mem,
> > +                     0, 0);
>
> Why can't you call:
>
>         cpu_soft_restart(kimage->start, kimage->arch.dtb_mem, 0, 0);
>
> here instead of open-coding it?

This is part of a cleanup to remove cpu_soft_restart() wrapper and the
header file that contains it. The wrapper is simple enough and has
only one call site. It makes more sense to do what is needed directly
from machine_kexec().

Pasha
diff mbox series

Patch

diff --git a/arch/arm64/kernel/machine_kexec.c b/arch/arm64/kernel/machine_kexec.c
index b6d5a02cba2e..7f1cb5a2a463 100644
--- a/arch/arm64/kernel/machine_kexec.c
+++ b/arch/arm64/kernel/machine_kexec.c
@@ -144,16 +144,16 @@  int machine_kexec_post_load(struct kimage *kimage)
 {
 	void *reloc_code = page_to_virt(kimage->control_code_page);
 
-	/* If in place flush new kernel image, else flush lists and buffers */
-	if (kimage->head & IND_DONE)
+	/* If in place, relocation is not used, only flush next kernel */
+	if (kimage->head & IND_DONE) {
 		kexec_segment_flush(kimage);
-	else
-		kexec_list_flush(kimage);
+		kexec_image_info(kimage);
+		return 0;
+	}
 
 	memcpy(reloc_code, arm64_relocate_new_kernel,
 	       arm64_relocate_new_kernel_size);
 	kimage->arch.kern_reloc = __pa(reloc_code);
-	kexec_image_info(kimage);
 
 	/* Flush the reloc_code in preparation for its execution. */
 	dcache_clean_inval_poc((unsigned long)reloc_code,
@@ -162,6 +162,8 @@  int machine_kexec_post_load(struct kimage *kimage)
 	icache_inval_pou((uintptr_t)reloc_code,
 			 (uintptr_t)reloc_code +
 			 arm64_relocate_new_kernel_size);
+	kexec_list_flush(kimage);
+	kexec_image_info(kimage);
 
 	return 0;
 }
@@ -188,19 +190,25 @@  void machine_kexec(struct kimage *kimage)
 	local_daif_mask();
 
 	/*
-	 * cpu_soft_restart will shutdown the MMU, disable data caches, then
-	 * transfer control to the kern_reloc which contains a copy of
-	 * the arm64_relocate_new_kernel routine.  arm64_relocate_new_kernel
-	 * uses physical addressing to relocate the new image to its final
-	 * position and transfers control to the image entry point when the
-	 * relocation is complete.
+	 * Both restart and cpu_soft_restart will shutdown the MMU, disable data
+	 * caches. However, restart will start new kernel or purgatory directly,
+	 * cpu_soft_restart will transfer control to arm64_relocate_new_kernel
 	 * In kexec case, kimage->start points to purgatory assuming that
 	 * kernel entry and dtb address are embedded in purgatory by
 	 * userspace (kexec-tools).
 	 * In kexec_file case, the kernel starts directly without purgatory.
 	 */
-	cpu_soft_restart(kimage->arch.kern_reloc, kimage->head, kimage->start,
-			 kimage->arch.dtb_mem);
+	if (kimage->head & IND_DONE) {
+		typeof(__cpu_soft_restart) *restart;
+
+		cpu_install_idmap();
+		restart = (void *)__pa_symbol(function_nocfi(__cpu_soft_restart));
+		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);
+	}
 
 	BUG(); /* Should never get here. */
 }
diff --git a/arch/arm64/kernel/relocate_kernel.S b/arch/arm64/kernel/relocate_kernel.S
index b78ea5de97a4..8058fabe0a76 100644
--- a/arch/arm64/kernel/relocate_kernel.S
+++ b/arch/arm64/kernel/relocate_kernel.S
@@ -32,8 +32,6 @@  SYM_CODE_START(arm64_relocate_new_kernel)
 	mov	x16, x0				/* x16 = kimage_head */
 	mov	x14, xzr			/* x14 = entry ptr */
 	mov	x13, xzr			/* x13 = copy dest */
-	/* Check if the new image needs relocation. */
-	tbnz	x16, IND_DONE_BIT, .Ldone
 	raw_dcache_line_size x15, x1		/* x15 = dcache line size */
 .Lloop:
 	and	x12, x16, PAGE_MASK		/* x12 = addr */
@@ -65,7 +63,6 @@  SYM_CODE_START(arm64_relocate_new_kernel)
 .Lnext:
 	ldr	x16, [x14], #8			/* entry = *ptr++ */
 	tbz	x16, IND_DONE_BIT, .Lloop	/* while (!(entry & DONE)) */
-.Ldone:
 	/* wait for writes from copy_page to finish */
 	dsb	nsh
 	ic	iallu