All of lore.kernel.org
 help / color / mirror / Atom feed
From: Mark Rutland <mark.rutland@arm.com>
To: Russell King - ARM Linux admin <linux@armlinux.org.uk>
Cc: Giancarlo Ferrari <giancarlo.ferrari89@gmail.com>,
	linux-kernel@vger.kernel.org, penberg@kernel.org,
	geert@linux-m68k.org, linux-arm-kernel@lists.infradead.org,
	akpm@linux-foundation.org, rppt@kernel.org,
	giancarlo.ferrari@nokia.com
Subject: Re: [PATCH] ARM: kexec: Fix panic after TLB are invalidated
Date: Mon, 1 Feb 2021 16:32:40 +0000	[thread overview]
Message-ID: <20210201163240.GE66060@C02TD0UTHF1T.local> (raw)
In-Reply-To: <20210201160838.GH1463@shell.armlinux.org.uk>

On Mon, Feb 01, 2021 at 04:08:38PM +0000, Russell King - ARM Linux admin wrote:
> On Mon, Feb 01, 2021 at 01:57:14PM +0000, Mark Rutland wrote:
> > We could simplify this slightly if we moved the kexec_& variables into a
> > struct (using asm-offset KEXEC_VAR_* offsets and a KEXEC_VAR_SIZE region
> > reserved in the asm), then here we could do something like:
> > 
> > static struct kexec_vars *kexec_buffer_vars(void *buffer)
> > {
> > 	unsigned long code = ((unisigned long)relocate_new_kernel) & ~1;
> > 	unsigned long vars - (unsigned long)relocate_vars;
> > 	unsigned long offset = vars - code;
> > 
> > 	return buffer + offset;
> > }
> > 
> > ... and in machine_kexec() do:
> > 
> > 	struct kexec_vars *kv = kexec_buffer_vars(reboot_code_buffer);
> > 
> > 	kv->start_address = image->start;
> > 	kv->indirection_page = page_list;
> > 	kv->mach_type = machine-arch_type;
> > 	kv->boot_atags = arch.kernel_r2;
> > 
> > ... if that looks any better to you?
> 
> Something like this?

Nice!

That looks about right to me, modulo a bit of cache maintenance noted
below.

> diff --git a/arch/arm/include/asm/kexec-internal.h b/arch/arm/include/asm/kexec-internal.h
> new file mode 100644
> index 000000000000..ecc2322db7aa
> --- /dev/null
> +++ b/arch/arm/include/asm/kexec-internal.h
> @@ -0,0 +1,12 @@
> +/* SPDX-License-Identifier: GPL-2.0 */
> +#ifndef _ARM_KEXEC_INTERNAL_H
> +#define _ARM_KEXEC_INTERNAL_H
> +
> +struct kexec_relocate_data {
> +	unsigned long kexec_start_address;
> +	unsigned long kexec_indirection_page;
> +	unsigned long kexec_mach_type;
> +	unsigned long kexec_r2;
> +};
> +
> +#endif
> diff --git a/arch/arm/kernel/asm-offsets.c b/arch/arm/kernel/asm-offsets.c
> index a1570c8bab25..be8050b0c3df 100644
> --- a/arch/arm/kernel/asm-offsets.c
> +++ b/arch/arm/kernel/asm-offsets.c
> @@ -12,6 +12,7 @@
>  #include <linux/mm.h>
>  #include <linux/dma-mapping.h>
>  #include <asm/cacheflush.h>
> +#include <asm/kexec-internal.h>
>  #include <asm/glue-df.h>
>  #include <asm/glue-pf.h>
>  #include <asm/mach/arch.h>
> @@ -170,5 +171,9 @@ int main(void)
>    DEFINE(MPU_RGN_PRBAR,	offsetof(struct mpu_rgn, prbar));
>    DEFINE(MPU_RGN_PRLAR,	offsetof(struct mpu_rgn, prlar));
>  #endif
> +  DEFINE(KEXEC_START_ADDR,	offsetof(struct kexec_relocate_data, kexec_start_address));
> +  DEFINE(KEXEC_INDIR_PAGE,	offsetof(struct kexec_relocate_data, kexec_indirection_page));
> +  DEFINE(KEXEC_MACH_TYPE,	offsetof(struct kexec_relocate_data, kexec_mach_type));
> +  DEFINE(KEXEC_R2,		offsetof(struct kexec_relocate_data, kexec_r2));
>    return 0; 
>  }
> diff --git a/arch/arm/kernel/machine_kexec.c b/arch/arm/kernel/machine_kexec.c
> index 5d84ad333f05..2b09dad7935e 100644
> --- a/arch/arm/kernel/machine_kexec.c
> +++ b/arch/arm/kernel/machine_kexec.c
> @@ -13,6 +13,7 @@
>  #include <linux/of_fdt.h>
>  #include <asm/mmu_context.h>
>  #include <asm/cacheflush.h>
> +#include <asm/kexec-internal.h>
>  #include <asm/fncpy.h>
>  #include <asm/mach-types.h>
>  #include <asm/smp_plat.h>
> @@ -22,11 +23,6 @@
>  extern void relocate_new_kernel(void);
>  extern const unsigned int relocate_new_kernel_size;
>  
> -extern unsigned long kexec_start_address;
> -extern unsigned long kexec_indirection_page;
> -extern unsigned long kexec_mach_type;
> -extern unsigned long kexec_boot_atags;
> -
>  static atomic_t waiting_for_crash_ipi;
>  
>  /*
> @@ -159,6 +155,7 @@ void (*kexec_reinit)(void);
>  void machine_kexec(struct kimage *image)
>  {
>  	unsigned long page_list, reboot_entry_phys;
> +	struct kexec_relocate_data *data;
>  	void (*reboot_entry)(void);
>  	void *reboot_code_buffer;
>  
> @@ -174,18 +171,17 @@ void machine_kexec(struct kimage *image)
>  
>  	reboot_code_buffer = page_address(image->control_code_page);
>  
> -	/* Prepare parameters for reboot_code_buffer*/
> -	set_kernel_text_rw();
> -	kexec_start_address = image->start;
> -	kexec_indirection_page = page_list;
> -	kexec_mach_type = machine_arch_type;
> -	kexec_boot_atags = image->arch.kernel_r2;
> -
>  	/* copy our kernel relocation code to the control code page */
>  	reboot_entry = fncpy(reboot_code_buffer,
>  			     &relocate_new_kernel,
>  			     relocate_new_kernel_size);
>  
> +	data = reboot_code_buffer + relocate_new_kernel_size;
> +	data->kexec_start_address = image->start;
> +	data->kexec_indirection_page = page_list;
> +	data->kexec_mach_type = machine_arch_type;
> +	data->kexec_r2 = image->arch.kernel_r2;

I reckon here we need:

	__cpuc_flush_dcache_area(reboot_code_buffer,
				 relocate_new_kernel_size + sizeof(*data));

... to make sure both the instructions and data are visible with the MMU
off (since fncpy() only cleans to the PoU, not the PoC).

Otherwise this all looks good to me.

Mark.

> +
>  	/* get the identity mapping physical address for the reboot code */
>  	reboot_entry_phys = virt_to_idmap(reboot_entry);
>  
> diff --git a/arch/arm/kernel/relocate_kernel.S b/arch/arm/kernel/relocate_kernel.S
> index 72a08786e16e..218d524360fc 100644
> --- a/arch/arm/kernel/relocate_kernel.S
> +++ b/arch/arm/kernel/relocate_kernel.S
> @@ -5,14 +5,16 @@
>  
>  #include <linux/linkage.h>
>  #include <asm/assembler.h>
> +#include <asm/asm-offsets.h>
>  #include <asm/kexec.h>
>  
>  	.align	3	/* not needed for this code, but keeps fncpy() happy */
>  
>  ENTRY(relocate_new_kernel)
>  
> -	ldr	r0,kexec_indirection_page
> -	ldr	r1,kexec_start_address
> +	adr	r7, relocate_new_kernel_end
> +	ldr	r0, [r7, #KEXEC_INDIR_PAGE]
> +	ldr	r1, [r7, #KEXEC_START_ADDR]
>  
>  	/*
>  	 * If there is no indirection page (we are doing crashdumps)
> @@ -57,34 +59,16 @@ ENTRY(relocate_new_kernel)
>  
>  2:
>  	/* Jump to relocated kernel */
> -	mov lr,r1
> -	mov r0,#0
> -	ldr r1,kexec_mach_type
> -	ldr r2,kexec_boot_atags
> - ARM(	ret lr	)
> - THUMB(	bx lr		)
> -
> -	.align
> -
> -	.globl kexec_start_address
> -kexec_start_address:
> -	.long	0x0
> -
> -	.globl kexec_indirection_page
> -kexec_indirection_page:
> -	.long	0x0
> -
> -	.globl kexec_mach_type
> -kexec_mach_type:
> -	.long	0x0
> -
> -	/* phy addr of the atags for the new kernel */
> -	.globl kexec_boot_atags
> -kexec_boot_atags:
> -	.long	0x0
> +	mov	lr, r1
> +	mov	r0, #0
> +	ldr	r1, [r7, #KEXEC_MACH_TYPE]
> +	ldr	r2, [r7, #KEXEC_R2]
> + ARM(	ret	lr	)
> + THUMB(	bx	lr	)
>  
>  ENDPROC(relocate_new_kernel)
>  
> +	.align	3
>  relocate_new_kernel_end:
>  
>  	.globl relocate_new_kernel_size
> 
> -- 
> RMK's Patch system: https://www.armlinux.org.uk/developer/patches/
> FTTP is here! 40Mbps down 10Mbps up. Decent connectivity at last!

WARNING: multiple messages have this Message-ID (diff)
From: Mark Rutland <mark.rutland@arm.com>
To: Russell King - ARM Linux admin <linux@armlinux.org.uk>
Cc: linux-kernel@vger.kernel.org, penberg@kernel.org,
	geert@linux-m68k.org, rppt@kernel.org,
	Giancarlo Ferrari <giancarlo.ferrari89@gmail.com>,
	akpm@linux-foundation.org, linux-arm-kernel@lists.infradead.org,
	giancarlo.ferrari@nokia.com
Subject: Re: [PATCH] ARM: kexec: Fix panic after TLB are invalidated
Date: Mon, 1 Feb 2021 16:32:40 +0000	[thread overview]
Message-ID: <20210201163240.GE66060@C02TD0UTHF1T.local> (raw)
In-Reply-To: <20210201160838.GH1463@shell.armlinux.org.uk>

On Mon, Feb 01, 2021 at 04:08:38PM +0000, Russell King - ARM Linux admin wrote:
> On Mon, Feb 01, 2021 at 01:57:14PM +0000, Mark Rutland wrote:
> > We could simplify this slightly if we moved the kexec_& variables into a
> > struct (using asm-offset KEXEC_VAR_* offsets and a KEXEC_VAR_SIZE region
> > reserved in the asm), then here we could do something like:
> > 
> > static struct kexec_vars *kexec_buffer_vars(void *buffer)
> > {
> > 	unsigned long code = ((unisigned long)relocate_new_kernel) & ~1;
> > 	unsigned long vars - (unsigned long)relocate_vars;
> > 	unsigned long offset = vars - code;
> > 
> > 	return buffer + offset;
> > }
> > 
> > ... and in machine_kexec() do:
> > 
> > 	struct kexec_vars *kv = kexec_buffer_vars(reboot_code_buffer);
> > 
> > 	kv->start_address = image->start;
> > 	kv->indirection_page = page_list;
> > 	kv->mach_type = machine-arch_type;
> > 	kv->boot_atags = arch.kernel_r2;
> > 
> > ... if that looks any better to you?
> 
> Something like this?

Nice!

That looks about right to me, modulo a bit of cache maintenance noted
below.

> diff --git a/arch/arm/include/asm/kexec-internal.h b/arch/arm/include/asm/kexec-internal.h
> new file mode 100644
> index 000000000000..ecc2322db7aa
> --- /dev/null
> +++ b/arch/arm/include/asm/kexec-internal.h
> @@ -0,0 +1,12 @@
> +/* SPDX-License-Identifier: GPL-2.0 */
> +#ifndef _ARM_KEXEC_INTERNAL_H
> +#define _ARM_KEXEC_INTERNAL_H
> +
> +struct kexec_relocate_data {
> +	unsigned long kexec_start_address;
> +	unsigned long kexec_indirection_page;
> +	unsigned long kexec_mach_type;
> +	unsigned long kexec_r2;
> +};
> +
> +#endif
> diff --git a/arch/arm/kernel/asm-offsets.c b/arch/arm/kernel/asm-offsets.c
> index a1570c8bab25..be8050b0c3df 100644
> --- a/arch/arm/kernel/asm-offsets.c
> +++ b/arch/arm/kernel/asm-offsets.c
> @@ -12,6 +12,7 @@
>  #include <linux/mm.h>
>  #include <linux/dma-mapping.h>
>  #include <asm/cacheflush.h>
> +#include <asm/kexec-internal.h>
>  #include <asm/glue-df.h>
>  #include <asm/glue-pf.h>
>  #include <asm/mach/arch.h>
> @@ -170,5 +171,9 @@ int main(void)
>    DEFINE(MPU_RGN_PRBAR,	offsetof(struct mpu_rgn, prbar));
>    DEFINE(MPU_RGN_PRLAR,	offsetof(struct mpu_rgn, prlar));
>  #endif
> +  DEFINE(KEXEC_START_ADDR,	offsetof(struct kexec_relocate_data, kexec_start_address));
> +  DEFINE(KEXEC_INDIR_PAGE,	offsetof(struct kexec_relocate_data, kexec_indirection_page));
> +  DEFINE(KEXEC_MACH_TYPE,	offsetof(struct kexec_relocate_data, kexec_mach_type));
> +  DEFINE(KEXEC_R2,		offsetof(struct kexec_relocate_data, kexec_r2));
>    return 0; 
>  }
> diff --git a/arch/arm/kernel/machine_kexec.c b/arch/arm/kernel/machine_kexec.c
> index 5d84ad333f05..2b09dad7935e 100644
> --- a/arch/arm/kernel/machine_kexec.c
> +++ b/arch/arm/kernel/machine_kexec.c
> @@ -13,6 +13,7 @@
>  #include <linux/of_fdt.h>
>  #include <asm/mmu_context.h>
>  #include <asm/cacheflush.h>
> +#include <asm/kexec-internal.h>
>  #include <asm/fncpy.h>
>  #include <asm/mach-types.h>
>  #include <asm/smp_plat.h>
> @@ -22,11 +23,6 @@
>  extern void relocate_new_kernel(void);
>  extern const unsigned int relocate_new_kernel_size;
>  
> -extern unsigned long kexec_start_address;
> -extern unsigned long kexec_indirection_page;
> -extern unsigned long kexec_mach_type;
> -extern unsigned long kexec_boot_atags;
> -
>  static atomic_t waiting_for_crash_ipi;
>  
>  /*
> @@ -159,6 +155,7 @@ void (*kexec_reinit)(void);
>  void machine_kexec(struct kimage *image)
>  {
>  	unsigned long page_list, reboot_entry_phys;
> +	struct kexec_relocate_data *data;
>  	void (*reboot_entry)(void);
>  	void *reboot_code_buffer;
>  
> @@ -174,18 +171,17 @@ void machine_kexec(struct kimage *image)
>  
>  	reboot_code_buffer = page_address(image->control_code_page);
>  
> -	/* Prepare parameters for reboot_code_buffer*/
> -	set_kernel_text_rw();
> -	kexec_start_address = image->start;
> -	kexec_indirection_page = page_list;
> -	kexec_mach_type = machine_arch_type;
> -	kexec_boot_atags = image->arch.kernel_r2;
> -
>  	/* copy our kernel relocation code to the control code page */
>  	reboot_entry = fncpy(reboot_code_buffer,
>  			     &relocate_new_kernel,
>  			     relocate_new_kernel_size);
>  
> +	data = reboot_code_buffer + relocate_new_kernel_size;
> +	data->kexec_start_address = image->start;
> +	data->kexec_indirection_page = page_list;
> +	data->kexec_mach_type = machine_arch_type;
> +	data->kexec_r2 = image->arch.kernel_r2;

I reckon here we need:

	__cpuc_flush_dcache_area(reboot_code_buffer,
				 relocate_new_kernel_size + sizeof(*data));

... to make sure both the instructions and data are visible with the MMU
off (since fncpy() only cleans to the PoU, not the PoC).

Otherwise this all looks good to me.

Mark.

> +
>  	/* get the identity mapping physical address for the reboot code */
>  	reboot_entry_phys = virt_to_idmap(reboot_entry);
>  
> diff --git a/arch/arm/kernel/relocate_kernel.S b/arch/arm/kernel/relocate_kernel.S
> index 72a08786e16e..218d524360fc 100644
> --- a/arch/arm/kernel/relocate_kernel.S
> +++ b/arch/arm/kernel/relocate_kernel.S
> @@ -5,14 +5,16 @@
>  
>  #include <linux/linkage.h>
>  #include <asm/assembler.h>
> +#include <asm/asm-offsets.h>
>  #include <asm/kexec.h>
>  
>  	.align	3	/* not needed for this code, but keeps fncpy() happy */
>  
>  ENTRY(relocate_new_kernel)
>  
> -	ldr	r0,kexec_indirection_page
> -	ldr	r1,kexec_start_address
> +	adr	r7, relocate_new_kernel_end
> +	ldr	r0, [r7, #KEXEC_INDIR_PAGE]
> +	ldr	r1, [r7, #KEXEC_START_ADDR]
>  
>  	/*
>  	 * If there is no indirection page (we are doing crashdumps)
> @@ -57,34 +59,16 @@ ENTRY(relocate_new_kernel)
>  
>  2:
>  	/* Jump to relocated kernel */
> -	mov lr,r1
> -	mov r0,#0
> -	ldr r1,kexec_mach_type
> -	ldr r2,kexec_boot_atags
> - ARM(	ret lr	)
> - THUMB(	bx lr		)
> -
> -	.align
> -
> -	.globl kexec_start_address
> -kexec_start_address:
> -	.long	0x0
> -
> -	.globl kexec_indirection_page
> -kexec_indirection_page:
> -	.long	0x0
> -
> -	.globl kexec_mach_type
> -kexec_mach_type:
> -	.long	0x0
> -
> -	/* phy addr of the atags for the new kernel */
> -	.globl kexec_boot_atags
> -kexec_boot_atags:
> -	.long	0x0
> +	mov	lr, r1
> +	mov	r0, #0
> +	ldr	r1, [r7, #KEXEC_MACH_TYPE]
> +	ldr	r2, [r7, #KEXEC_R2]
> + ARM(	ret	lr	)
> + THUMB(	bx	lr	)
>  
>  ENDPROC(relocate_new_kernel)
>  
> +	.align	3
>  relocate_new_kernel_end:
>  
>  	.globl relocate_new_kernel_size
> 
> -- 
> RMK's Patch system: https://www.armlinux.org.uk/developer/patches/
> FTTP is here! 40Mbps down 10Mbps up. Decent connectivity at last!

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

  reply	other threads:[~2021-02-01 16:34 UTC|newest]

Thread overview: 44+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2021-02-01  0:44 [PATCH] ARM: kexec: Fix panic after TLB are invalidated Giancarlo Ferrari
2021-02-01  0:44 ` Giancarlo Ferrari
2021-02-01 11:34 ` Russell King - ARM Linux admin
2021-02-01 11:34   ` Russell King - ARM Linux admin
2021-02-01 12:47 ` Mark Rutland
2021-02-01 12:47   ` Mark Rutland
2021-02-01 13:03   ` Russell King - ARM Linux admin
2021-02-01 13:03     ` Russell King - ARM Linux admin
2021-02-01 13:57     ` Mark Rutland
2021-02-01 13:57       ` Mark Rutland
2021-02-01 16:08       ` Russell King - ARM Linux admin
2021-02-01 16:08         ` Russell King - ARM Linux admin
2021-02-01 16:32         ` Mark Rutland [this message]
2021-02-01 16:32           ` Mark Rutland
2021-02-01 16:37           ` Russell King - ARM Linux admin
2021-02-01 16:37             ` Russell King - ARM Linux admin
2021-02-01 20:07         ` Giancarlo Ferrari
2021-02-01 20:07           ` Giancarlo Ferrari
2021-02-01 20:16           ` Russell King - ARM Linux admin
2021-02-01 20:16             ` Russell King - ARM Linux admin
2021-02-01 22:18             ` Giancarlo Ferrari
2021-02-01 22:18               ` Giancarlo Ferrari
2021-02-04 23:48               ` Giancarlo Ferrari
2021-02-04 23:48                 ` Giancarlo Ferrari
2021-02-05  0:18                 ` Russell King - ARM Linux admin
2021-02-05  0:18                   ` Russell King - ARM Linux admin
2021-02-05  0:40                   ` Giancarlo Ferrari
2021-02-05  0:40                     ` Giancarlo Ferrari
2021-02-05  0:45                     ` Giancarlo Ferrari
2021-02-05  0:45                       ` Giancarlo Ferrari
2021-02-05  9:44                     ` Russell King - ARM Linux admin
2021-02-05  9:44                       ` Russell King - ARM Linux admin
2021-02-05 14:36                       ` Giancarlo Ferrari
2021-02-05 14:36                         ` Giancarlo Ferrari
2021-02-01 14:39   ` Giancarlo Ferrari
2021-02-01 14:39     ` Giancarlo Ferrari
2021-02-01 15:30     ` Mark Rutland
2021-02-01 15:30       ` Mark Rutland
2021-02-01 19:09       ` Giancarlo Ferrari
2021-02-01 19:09         ` Giancarlo Ferrari
  -- strict thread matches above, loose matches on Subject: below --
2021-01-12 16:49 Giancarlo Ferrari
2021-01-12 16:49 ` Giancarlo Ferrari
2021-02-01 10:10 ` Giancarlo Ferrari
2021-02-01 10:10   ` Giancarlo Ferrari

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20210201163240.GE66060@C02TD0UTHF1T.local \
    --to=mark.rutland@arm.com \
    --cc=akpm@linux-foundation.org \
    --cc=geert@linux-m68k.org \
    --cc=giancarlo.ferrari89@gmail.com \
    --cc=giancarlo.ferrari@nokia.com \
    --cc=linux-arm-kernel@lists.infradead.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux@armlinux.org.uk \
    --cc=penberg@kernel.org \
    --cc=rppt@kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.