public inbox for linux-arm-kernel@lists.infradead.org
 help / color / mirror / Atom feed
* [RFC 0/2] Selective identity mapping for kexec
@ 2010-11-01 16:36 Per Fransson
  2010-11-01 16:36 ` [RFC 2/2] Selective MMU " Per Fransson
  2010-11-02 12:59 ` [RFC 0/2] Selective " Simon Horman
  0 siblings, 2 replies; 4+ messages in thread
From: Per Fransson @ 2010-11-01 16:36 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] 4+ messages in thread

* [RFC 2/2] Selective MMU identity mapping for kexec
  2010-11-01 16:36 [RFC 0/2] Selective identity mapping for kexec Per Fransson
@ 2010-11-01 16:36 ` Per Fransson
  2010-11-02 12:59 ` [RFC 0/2] Selective " Simon Horman
  1 sibling, 0 replies; 4+ messages in thread
From: Per Fransson @ 2010-11-01 16:36 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] 4+ messages in thread

* [RFC 0/2] Selective identity mapping for kexec
  2010-11-01 16:36 [RFC 0/2] Selective identity mapping for kexec Per Fransson
  2010-11-01 16:36 ` [RFC 2/2] Selective MMU " Per Fransson
@ 2010-11-02 12:59 ` Simon Horman
  2010-11-02 13:05   ` Simon Horman
  1 sibling, 1 reply; 4+ messages in thread
From: Simon Horman @ 2010-11-02 12:59 UTC (permalink / raw)
  To: linux-arm-kernel

On Mon, Nov 01, 2010 at 05:36:52PM +0100, Per Fransson wrote:
> Hi,
> 
> I would appreciate your input on some kexec related changes.

Hi,

It would be useful to CC kexec at lists.infradead.org on kexec patches.
Also, I seem to be missing patch 1/2. Did it have a different CC list?

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

* [RFC 0/2] Selective identity mapping for kexec
  2010-11-02 12:59 ` [RFC 0/2] Selective " Simon Horman
@ 2010-11-02 13:05   ` Simon Horman
  0 siblings, 0 replies; 4+ messages in thread
From: Simon Horman @ 2010-11-02 13:05 UTC (permalink / raw)
  To: linux-arm-kernel

On Tue, Nov 02, 2010 at 09:59:10PM +0900, Simon Horman wrote:
> On Mon, Nov 01, 2010 at 05:36:52PM +0100, Per Fransson wrote:
> > Hi,
> > 
> > I would appreciate your input on some kexec related changes.
> 
> Hi,
> 
> It would be useful to CC kexec at lists.infradead.org on kexec patches.
> Also, I seem to be missing patch 1/2. Did it have a different CC list?

Scratch the second comment, I see 1/2 in your second posting of the patches.

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

end of thread, other threads:[~2010-11-02 13:05 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2010-11-01 16:36 [RFC 0/2] Selective identity mapping for kexec Per Fransson
2010-11-01 16:36 ` [RFC 2/2] Selective MMU " Per Fransson
2010-11-02 12:59 ` [RFC 0/2] Selective " Simon Horman
2010-11-02 13:05   ` Simon Horman

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox