All of lore.kernel.org
 help / color / mirror / Atom feed
* [RFC 0/2] Selective MMU identity mapping for kexec
@ 2010-11-01 18:32 Per Fransson
  2010-11-01 18:32 ` [RFC 1/2] " Per Fransson
  2010-11-01 18:32 ` [RFC 2/2] " Per Fransson
  0 siblings, 2 replies; 6+ messages in thread
From: Per Fransson @ 2010-11-01 18:32 UTC (permalink / raw)
  To: linux-arm-kernel

Hi,

I would appreciate your input on some kexec related changes.

When restarting using the kernel kexec functionality the MMU needs to be turned off.
Any code which does this needs to use identity mapped addresses to get
reliable results. In the ARM kexec case this identity mapping is done:

- using the page table of the current task

- for all addresses normally used by user space, i.e. 0x00000000-PAGE_OFFSET

If kexec is used at a kernel crash to collect a core dump this means that we lose important information.

This is what these patches do:

* Actually turn off the MMU, which has been omitted by mistake, see this post:

    http://lists.infradead.org/pipermail/linux-arm-kernel/2010-July/019631.html

* Set up a more selective identity mapping

* Restore the old mapping once the MMU is off


The patch was generated from a linux-next 20101028 with these additional related patches which are in the pipeline:

http://dev.omapzoom.org/?p=santosh/kernel-omap4-base.git;a=commit;h=ae360a78f41164e7f9c4cf846696b5b6d8dae5c8
http://dev.omapzoom.org/?p=santosh/kernel-omap4-base.git;a=commit;h=2fd8658931193599c867fd6974fa184ec34af16c
http://dev.omapzoom.org/?p=santosh/kernel-omap4-base.git;a=commit;h=ae6948048c417d429b8a0f85fad13e483f7cc1a3


Regards,
Per


Per Fransson (2):
  Turn off MMU in cpu_v7_reset
  Selective MMU identity mapping for kexec

 arch/arm/kernel/machine_kexec.c   |   27 +++++++++++++++++++++-
 arch/arm/kernel/relocate_kernel.S |   23 +++++++++++++++++++
 arch/arm/mm/mmu.c                 |   44 +++++++++++++++++++++++++++++++++++++
 arch/arm/mm/proc-v7.S             |    4 +++
 4 files changed, 97 insertions(+), 1 deletions(-)

-- 
1.7.2.2

^ permalink raw reply	[flat|nested] 6+ messages in thread

* [RFC 1/2] Selective MMU identity mapping for kexec
  2010-11-01 18:32 [RFC 0/2] Selective MMU identity mapping for kexec Per Fransson
@ 2010-11-01 18:32 ` Per Fransson
  2010-11-01 18:32 ` [RFC 2/2] " Per Fransson
  1 sibling, 0 replies; 6+ messages in thread
From: Per Fransson @ 2010-11-01 18:32 UTC (permalink / raw)
  To: linux-arm-kernel

Signed-off-by: Per Fransson <per.xx.fransson@stericsson.com>
---
 arch/arm/mm/proc-v7.S |    3 +++
 1 files changed, 3 insertions(+), 0 deletions(-)

diff --git a/arch/arm/mm/proc-v7.S b/arch/arm/mm/proc-v7.S
index 2b5b20b..b249143 100644
--- a/arch/arm/mm/proc-v7.S
+++ b/arch/arm/mm/proc-v7.S
@@ -61,6 +61,9 @@ ENDPROC(cpu_v7_proc_fin)
  */
 	.align	5
 ENTRY(cpu_v7_reset)
+	mrc	p15, 0, ip, c1, c0, 0		@ ctrl register
+	bic	ip, ip, #0x0001			@ ...............m
+	mcr	p15, 0, ip, c1, c0, 0		@ ctrl register
 	mov	pc, r0
 ENDPROC(cpu_v7_reset)
 
-- 
1.7.2.2

^ permalink raw reply related	[flat|nested] 6+ messages in thread

* [RFC 2/2] Selective MMU identity mapping for kexec
  2010-11-01 18:32 [RFC 0/2] Selective MMU identity mapping for kexec Per Fransson
  2010-11-01 18:32 ` [RFC 1/2] " Per Fransson
@ 2010-11-01 18:32 ` Per Fransson
  2010-12-15 17:39   ` Will Deacon
  1 sibling, 1 reply; 6+ messages in thread
From: Per Fransson @ 2010-11-01 18:32 UTC (permalink / raw)
  To: linux-arm-kernel

Signed-off-by: Per Fransson <per.xx.fransson@stericsson.com>
---
 arch/arm/kernel/machine_kexec.c   |   27 +++++++++++++++++++++-
 arch/arm/kernel/relocate_kernel.S |   23 +++++++++++++++++++
 arch/arm/mm/mmu.c                 |   44 +++++++++++++++++++++++++++++++++++++
 arch/arm/mm/proc-v7.S             |    1 +
 4 files changed, 94 insertions(+), 1 deletions(-)

diff --git a/arch/arm/kernel/machine_kexec.c b/arch/arm/kernel/machine_kexec.c
index 3a8fd51..d5bb12f 100644
--- a/arch/arm/kernel/machine_kexec.c
+++ b/arch/arm/kernel/machine_kexec.c
@@ -17,12 +17,20 @@ extern const unsigned char relocate_new_kernel[];
 extern const unsigned int relocate_new_kernel_size;
 
 extern void setup_mm_for_reboot(char mode);
+extern void identity_map(unsigned long, pgd_t*, pgd_t**);
 
 extern unsigned long kexec_start_address;
 extern unsigned long kexec_indirection_page;
 extern unsigned long kexec_mach_type;
 extern unsigned long kexec_boot_atags;
 
+typedef struct {
+	pgd_t *ptr;
+	pgd_t store;
+} kexec_mmu_ent_t;
+
+extern kexec_mmu_ent_t kexec_mmu_ents[4];
+
 /*
  * Provide a dummy crash_notes definition while crash dump arrives to arm.
  * This prevents breakage of crash_notes attribute in kernel/ksysfs.c.
@@ -51,6 +59,7 @@ void machine_kexec(struct kimage *image)
 	unsigned long reboot_code_buffer_phys;
 	void *reboot_code_buffer;
 
+	unsigned long cpu_reset_phys;
 
 	page_list = image->head & PAGE_MASK;
 
@@ -65,18 +74,34 @@ void machine_kexec(struct kimage *image)
 	kexec_mach_type = machine_arch_type;
 	kexec_boot_atags = image->start - KEXEC_ARM_ZIMAGE_OFFSET + KEXEC_ARM_ATAGS_OFFSET;
 
+	/* Identity map the code which turns off the mmu (cpu_reset) and
+	   the code which will be executed immediately afterwards
+	   (relocate_new_kernel).
+	   Store the old entries so they can be restored. */
+	/* cpu_reset cannot be used directly when MULTI_CPU is true, see
+	   cpu-multi32.h, instead processor.reset will have to be used */
+	cpu_reset_phys = virt_to_phys(cpu_reset);
+	identity_map(cpu_reset_phys, &kexec_mmu_ents[0].store,
+		     &kexec_mmu_ents[0].ptr);
+	identity_map(((char *)cpu_reset_phys)+PGDIR_SIZE,
+		     &kexec_mmu_ents[1].store, &kexec_mmu_ents[1].ptr);
+	identity_map(reboot_code_buffer_phys,
+		     &kexec_mmu_ents[2].store, &kexec_mmu_ents[2].ptr);
+	identity_map(((char *)reboot_code_buffer_phys)+PGDIR_SIZE,
+		     &kexec_mmu_ents[3].store, &kexec_mmu_ents[3].ptr);
+
 	/* copy our kernel relocation code to the control code page */
 	memcpy(reboot_code_buffer,
 	       relocate_new_kernel, relocate_new_kernel_size);
 
 
+
 	flush_icache_range((unsigned long) reboot_code_buffer,
 			   (unsigned long) reboot_code_buffer + KEXEC_CONTROL_PAGE_SIZE);
 	printk(KERN_INFO "Bye!\n");
 
 	local_irq_disable();
 	local_fiq_disable();
-	setup_mm_for_reboot(0); /* mode is not used, so just pass 0*/
 	flush_cache_all();
 	outer_flush_all();
 	outer_disable();
diff --git a/arch/arm/kernel/relocate_kernel.S b/arch/arm/kernel/relocate_kernel.S
index fd26f8d..36b1268 100644
--- a/arch/arm/kernel/relocate_kernel.S
+++ b/arch/arm/kernel/relocate_kernel.S
@@ -7,6 +7,23 @@
 	.globl relocate_new_kernel
 relocate_new_kernel:
 
+	/* We get here when the MMU is in a transitional state.
+	   Wait for the virtual address mapping to wear off before
+	   overwriting the identity mappings (set up for the sake
+	   of MMU disabling) with the previous mappings. */
+	ldr	r0, =100
+0:	subs	r0, r0, #1
+	beq	0b
+
+	adr	r0, kexec_mmu_ents
+	.rept 4
+	ldr	r1, [r0], #4
+	ldr	r2, [r0], #4
+	str	r2, [r1], #4
+	ldr	r2, [r0], #4
+	str	r2, [r1], #4
+	.endr
+
 	ldr	r0,kexec_indirection_page
 	ldr	r1,kexec_start_address
 
@@ -67,6 +84,12 @@ kexec_start_address:
 kexec_indirection_page:
 	.long	0x0
 
+
+	.globl kexec_mmu_ents
+kexec_mmu_ents:
+	.space 4*12, 0
+
+
 	.globl kexec_mach_type
 kexec_mach_type:
 	.long	0x0
diff --git a/arch/arm/mm/mmu.c b/arch/arm/mm/mmu.c
index de3afc7..64f3f05 100644
--- a/arch/arm/mm/mmu.c
+++ b/arch/arm/mm/mmu.c
@@ -1080,3 +1080,47 @@ void setup_mm_for_reboot(char mode)
 
 	local_flush_tlb_all();
 }
+
+
+/*
+ * In order to soft-boot, we need to insert a 1:1 mapping in place of
+ * the user-mode pages.  This will then ensure that we have predictable
+ * results when turning the mmu off
+ */
+void identity_map(unsigned long phys_addr, pmd_t *pmd_store, pmd_t **pmd_ptr)
+{
+	unsigned long base_pmdval;
+	pgd_t *pgd;
+	pmd_t *pmd;
+	int i;
+	unsigned long pmdval;
+
+	/*
+	 * We need to access to user-mode page tables here. For kernel threads
+	 * we don't have any user-mode mappings so we use the context that we
+	 * "borrowed".
+	 */
+	pgd = current->active_mm->pgd;
+
+	base_pmdval = PMD_SECT_AP_WRITE | PMD_SECT_AP_READ | PMD_TYPE_SECT;
+	if (cpu_architecture() <= CPU_ARCH_ARMv5TEJ && !cpu_is_xscale())
+		base_pmdval |= PMD_BIT4;
+
+	/* Where to modify */
+	pmd = pgd + (phys_addr >> PGDIR_SHIFT);
+
+	/* Save old value */
+	pmd_store[0] = pmd[0];
+	pmd_store[1] = pmd[1];
+
+	*pmd_ptr = virt_to_phys(pmd);
+
+	/* Set new value */
+	pmdval = ((phys_addr >> PGDIR_SHIFT) << PGDIR_SHIFT) | base_pmdval;
+	pmd[0] = __pmd(pmdval);
+	pmd[1] = __pmd(pmdval + (1 << (PGDIR_SHIFT - 1)));
+
+	flush_pmd_entry(pmd);
+	local_flush_tlb_all();
+}
+
diff --git a/arch/arm/mm/proc-v7.S b/arch/arm/mm/proc-v7.S
index b249143..37ee55b 100644
--- a/arch/arm/mm/proc-v7.S
+++ b/arch/arm/mm/proc-v7.S
@@ -61,6 +61,7 @@ ENDPROC(cpu_v7_proc_fin)
  */
 	.align	5
 ENTRY(cpu_v7_reset)
+	sub	pc, pc, #PAGE_OFFSET+4		@ go to physical addresses
 	mrc	p15, 0, ip, c1, c0, 0		@ ctrl register
 	bic	ip, ip, #0x0001			@ ...............m
 	mcr	p15, 0, ip, c1, c0, 0		@ ctrl register
-- 
1.7.2.2

^ permalink raw reply related	[flat|nested] 6+ messages in thread

* [RFC 2/2] Selective MMU identity mapping for kexec
  2010-11-01 18:32 ` [RFC 2/2] " Per Fransson
@ 2010-12-15 17:39   ` Will Deacon
  2010-12-15 23:35     ` Russell King - ARM Linux
  0 siblings, 1 reply; 6+ messages in thread
From: Will Deacon @ 2010-12-15 17:39 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Per,

It's nice to see somebody looking at this!

On Mon, 2010-11-01 at 19:32 +0100, Per Fransson wrote:
> Signed-off-by: Per Fransson <per.xx.fransson@stericsson.com>
> ---
>  arch/arm/kernel/machine_kexec.c   |   27 +++++++++++++++++++++-
>  arch/arm/kernel/relocate_kernel.S |   23 +++++++++++++++++++
>  arch/arm/mm/mmu.c                 |   44 +++++++++++++++++++++++++++++++++++++
>  arch/arm/mm/proc-v7.S             |    1 +
>  4 files changed, 94 insertions(+), 1 deletions(-)

Some parts of this patchset will be useful for implementing CPU hotplug
on the ARM RealView boards. The idea is to throw cores back to the
bootloader when they are offlined, so we need to be able to disable the
MMU safely before we jump.

> diff --git a/arch/arm/kernel/machine_kexec.c b/arch/arm/kernel/machine_kexec.c
> index 3a8fd51..d5bb12f 100644
> --- a/arch/arm/kernel/machine_kexec.c
> +++ b/arch/arm/kernel/machine_kexec.c
> @@ -17,12 +17,20 @@ extern const unsigned char relocate_new_kernel[];
>  extern const unsigned int relocate_new_kernel_size;
>  
>  extern void setup_mm_for_reboot(char mode);
> +extern void identity_map(unsigned long, pgd_t*, pgd_t**);

[...]

> +	cpu_reset_phys = virt_to_phys(cpu_reset);
> +	identity_map(cpu_reset_phys, &kexec_mmu_ents[0].store,
> +		     &kexec_mmu_ents[0].ptr);
> +	identity_map(((char *)cpu_reset_phys)+PGDIR_SIZE,
> +		     &kexec_mmu_ents[1].store, &kexec_mmu_ents[1].ptr);

I think this could become common code as calling cpu_reset will require
the identity map to be in place now that you have added MMU disable code
there.

> diff --git a/arch/arm/mm/proc-v7.S b/arch/arm/mm/proc-v7.S
> index b249143..37ee55b 100644
> --- a/arch/arm/mm/proc-v7.S
> +++ b/arch/arm/mm/proc-v7.S
> @@ -61,6 +61,7 @@ ENDPROC(cpu_v7_proc_fin)
>   */
>  	.align	5
>  ENTRY(cpu_v7_reset)
> +	sub	pc, pc, #PAGE_OFFSET+4		@ go to physical addresses
>  	mrc	p15, 0, ip, c1, c0, 0		@ ctrl register
>  	bic	ip, ip, #0x0001			@ ...............m
>  	mcr	p15, 0, ip, c1, c0, 0		@ ctrl register

I'm not too keen on modifying the PC directly here. It also won't
compile for Thumb2. How about invoking the function using the 1:1
mapping instead? I think casting its physical address to a function
pointer will cause the compiler to generate any trampolines that are
needed.

Cheers,

Will

^ permalink raw reply	[flat|nested] 6+ messages in thread

* [RFC 2/2] Selective MMU identity mapping for kexec
  2010-12-15 17:39   ` Will Deacon
@ 2010-12-15 23:35     ` Russell King - ARM Linux
  0 siblings, 0 replies; 6+ messages in thread
From: Russell King - ARM Linux @ 2010-12-15 23:35 UTC (permalink / raw)
  To: linux-arm-kernel

On Wed, Dec 15, 2010 at 05:39:22PM +0000, Will Deacon wrote:
> Hi Per,
> 
> It's nice to see somebody looking at this!
> 
> On Mon, 2010-11-01 at 19:32 +0100, Per Fransson wrote:
> > Signed-off-by: Per Fransson <per.xx.fransson@stericsson.com>
> > ---
> >  arch/arm/kernel/machine_kexec.c   |   27 +++++++++++++++++++++-
> >  arch/arm/kernel/relocate_kernel.S |   23 +++++++++++++++++++
> >  arch/arm/mm/mmu.c                 |   44 +++++++++++++++++++++++++++++++++++++
> >  arch/arm/mm/proc-v7.S             |    1 +
> >  4 files changed, 94 insertions(+), 1 deletions(-)
> 
> Some parts of this patchset will be useful for implementing CPU hotplug
> on the ARM RealView boards. The idea is to throw cores back to the
> bootloader when they are offlined, so we need to be able to disable the
> MMU safely before we jump.

Beware - you can't replace random pre-existing table entries on a running
SMP system without creating hazards.

> > +	cpu_reset_phys = virt_to_phys(cpu_reset);
> > +	identity_map(cpu_reset_phys, &kexec_mmu_ents[0].store,
> > +		     &kexec_mmu_ents[0].ptr);
> > +	identity_map(((char *)cpu_reset_phys)+PGDIR_SIZE,
> > +		     &kexec_mmu_ents[1].store, &kexec_mmu_ents[1].ptr);
> 
> I think this could become common code as calling cpu_reset will require
> the identity map to be in place now that you have added MMU disable code
> there.

We have an identity mapping function set in the kernel (which has been
recently moved into its own file in my devel branch.)  It would need to
be extended to return the old pmd and pmd pointer to undo.

^ permalink raw reply	[flat|nested] 6+ messages in thread

* [RFC 0/2] Selective MMU identity mapping for kexec
@ 2010-11-08  8:42 Per Fransson
  0 siblings, 0 replies; 6+ messages in thread
From: Per Fransson @ 2010-11-08  8:42 UTC (permalink / raw)
  To: kexec; +Cc: Per Fransson

Hi,

I would appreciate your input on some kexec related changes.

When restarting using the kernel kexec functionality the MMU needs to be turned off.
Any code which does this needs to use identity mapped addresses to get
reliable results. In the ARM kexec case this identity mapping is done:

- using the page table of the current task

- for all addresses normally used by user space, i.e. 0x00000000-PAGE_OFFSET

If kexec is used at a kernel crash to collect a core dump this means that we lose important information.

This is what these patches do:

* Actually turn off the MMU, which has been omitted by mistake, see this post:

    http://lists.infradead.org/pipermail/linux-arm-kernel/2010-July/019631.html

* Set up a more selective identity mapping

* Restore the old mapping once the MMU is off


The patch was generated from a linux-next 20101028 with these additional related patches which are in the pipeline:

http://dev.omapzoom.org/?p=santosh/kernel-omap4-base.git;a=commit;h=ae360a78f41164e7f9c4cf846696b5b6d8dae5c8
http://dev.omapzoom.org/?p=santosh/kernel-omap4-base.git;a=commit;h=2fd8658931193599c867fd6974fa184ec34af16c
http://dev.omapzoom.org/?p=santosh/kernel-omap4-base.git;a=commit;h=ae6948048c417d429b8a0f85fad13e483f7cc1a3


Regards,
Per


Per Fransson (2):
  Turn off MMU in cpu_v7_reset
  Selective MMU identity mapping for kexec

 arch/arm/kernel/machine_kexec.c   |   27 +++++++++++++++++++++-
 arch/arm/kernel/relocate_kernel.S |   23 +++++++++++++++++++
 arch/arm/mm/mmu.c                 |   44 +++++++++++++++++++++++++++++++++++++
 arch/arm/mm/proc-v7.S             |    4 +++
 4 files changed, 97 insertions(+), 1 deletions(-)

-- 
1.7.2.2


_______________________________________________
kexec mailing list
kexec@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/kexec

^ permalink raw reply	[flat|nested] 6+ messages in thread

end of thread, other threads:[~2010-12-15 23:35 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2010-11-01 18:32 [RFC 0/2] Selective MMU identity mapping for kexec Per Fransson
2010-11-01 18:32 ` [RFC 1/2] " Per Fransson
2010-11-01 18:32 ` [RFC 2/2] " Per Fransson
2010-12-15 17:39   ` Will Deacon
2010-12-15 23:35     ` Russell King - ARM Linux
2010-11-08  8:42 [RFC 0/2] " Per Fransson

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.