All of lore.kernel.org
 help / color / mirror / Atom feed
* [RFC 00/10] Initial implementation of kdump for ARM
@ 2010-03-29  9:26 Mika Westerberg
  2010-03-29  9:26 ` [RFC 01/10] arm: kdump: reserve memory for crashkernel Mika Westerberg
  0 siblings, 1 reply; 22+ messages in thread
From: Mika Westerberg @ 2010-03-29  9:26 UTC (permalink / raw)
  To: linux-arm-kernel

Hello,

This series implements initial support for crashdumps on ARM. Mostly this stuff
is adapted from other architectures (namely x86). I've been testing this on my
N900 which is OMAP3430 based. I've used LKDTM module to crash the kernel in
different places.

This works as follows (see also Documentation/kdump/kdump.txt):

	1. Memory is reserved for the dump capture kernel by using kernel command
	   line option: crashkernel=size at start
	2. Userspace tool prepares vmcore header based on /proc/iomem and passes
	   this and the dump capture kernel using kexec system call. We also
	   reserve primary kernel memory by passing mem=size$start options to
	   the dump capture kernel.
	3. When crash happens, primary kernel saves current machine state and
	   passes control to the dump capture kernel
	4. Dump capture kernel makes /proc/vmcore available to userspace which
	   can use it as it likes (for example copying it to some media etc.).

I also have rough modifications for kexec-tools which makes it possible to load
the dump capture kernel and related information. I've planned to clean those and
send them to kexec mailing list after this kernel part is finished. I also have
some gdb macros adapted from Documentation/kdump/gdbmacros.txt that work on ARM
kernel crashdumps, in case someone is interested.

When ARM switches to use LMB, some of the patches that reserve bootmem need
to be reworked.

Note that these probably don't work with SMP systems (I don't have such hardware
available).

I would really appreciate any comments and suggestions.

Thanks,
MW

Mika Westerberg (10):
  arm: kdump: reserve memory for crashkernel
  arm: kdump: implement crash_setup_regs()
  arm: kdump: implement machine_crash_shutdown()
  arm: kdump: skip indirection page when crashing
  arm: kdump: make kexec work in interrupt context
  arm: kdump: implement copy_oldmem_page()
  arm: allow passing an ELF64 header to elf_check_arch()
  arm: kdump: add support for elfcorehdr= parameter
  arm: implement reserve memory early parameter
  arm: kdump: add CONFIG_CRASH_DUMP Kconfig option

 arch/arm/Kconfig                  |   11 ++++
 arch/arm/Makefile                 |   10 ++++
 arch/arm/include/asm/elf.h        |    4 +-
 arch/arm/include/asm/kexec.h      |   35 ++++++++++++-
 arch/arm/include/asm/setup.h      |    4 ++
 arch/arm/kernel/Makefile          |    1 +
 arch/arm/kernel/crash_dump.c      |   82 +++++++++++++++++++++++++++++++
 arch/arm/kernel/elf.c             |    6 ++-
 arch/arm/kernel/machine_kexec.c   |    4 ++
 arch/arm/kernel/relocate_kernel.S |    6 ++
 arch/arm/kernel/setup.c           |   98 ++++++++++++++++++++++++++++++++++--
 arch/arm/mm/init.c                |   25 +++++++++-
 arch/arm/mm/mmu.c                 |   10 ++--
 13 files changed, 277 insertions(+), 19 deletions(-)
 create mode 100644 arch/arm/kernel/crash_dump.c

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

* [RFC 01/10] arm: kdump: reserve memory for crashkernel
  2010-03-29  9:26 [RFC 00/10] Initial implementation of kdump for ARM Mika Westerberg
@ 2010-03-29  9:26 ` Mika Westerberg
  2010-03-29  9:26   ` [RFC 02/10] arm: kdump: implement crash_setup_regs() Mika Westerberg
  0 siblings, 1 reply; 22+ messages in thread
From: Mika Westerberg @ 2010-03-29  9:26 UTC (permalink / raw)
  To: linux-arm-kernel

Implemented ARM support for command line option "crashkernel=size at start" which
allows user to reserve some memory for a dump capture kernel.

Signed-off-by: Mika Westerberg <ext-mika.1.westerberg@nokia.com>
---
 arch/arm/kernel/setup.c |   51 +++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 51 insertions(+), 0 deletions(-)

diff --git a/arch/arm/kernel/setup.c b/arch/arm/kernel/setup.c
index c91c77b..076454f 100644
--- a/arch/arm/kernel/setup.c
+++ b/arch/arm/kernel/setup.c
@@ -19,6 +19,7 @@
 #include <linux/seq_file.h>
 #include <linux/screen_info.h>
 #include <linux/init.h>
+#include <linux/kexec.h>
 #include <linux/root_dev.h>
 #include <linux/cpu.h>
 #include <linux/interrupt.h>
@@ -661,6 +662,55 @@ static int __init customize_machine(void)
 }
 arch_initcall(customize_machine);
 
+#ifdef CONFIG_KEXEC
+static inline unsigned long long get_total_mem(void)
+{
+	unsigned long total;
+
+	total = max_low_pfn - min_low_pfn;
+	return total << PAGE_SHIFT;
+}
+
+/**
+ * reserve_crashkernel() - reserves memory are for crash kernel
+ *
+ * This function reserves memory area given in "crashkernel=" kernel command
+ * line parameter. The memory reserved is used by a dump capture kernel when
+ * primary kernel is crashing.
+ */
+static void __init reserve_crashkernel(void)
+{
+	unsigned long long crash_size, crash_base;
+	unsigned long long total_mem;
+	int ret;
+
+	total_mem = get_total_mem();
+	ret = parse_crashkernel(boot_command_line, total_mem,
+				&crash_size, &crash_base);
+	if (ret)
+		return;
+
+	ret = reserve_bootmem(crash_base, crash_size, BOOTMEM_EXCLUSIVE);
+	if (ret < 0) {
+		printk(KERN_WARNING "crashkernel reservation failed - "
+		       "memory is in use (0x%lx)\n", (unsigned long)crash_base);
+		return;
+	}
+
+	printk(KERN_INFO "Reserving %ldMB of memory@%ldMB "
+	       "for crashkernel (System RAM: %ldMB)\n",
+	       (unsigned long)(crash_size >> 20),
+	       (unsigned long)(crash_base >> 20),
+	       (unsigned long)(total_mem >> 20));
+
+	crashk_res.start = crash_base;
+	crashk_res.end = crash_base + crash_size - 1;
+	insert_resource(&iomem_resource, &crashk_res);
+}
+#else
+static inline void reserve_crashkernel(void) {}
+#endif /* CONFIG_KEXEC */
+
 void __init setup_arch(char **cmdline_p)
 {
 	struct tag *tags = (struct tag *)&init_tags;
@@ -720,6 +770,7 @@ void __init setup_arch(char **cmdline_p)
 #ifdef CONFIG_SMP
 	smp_init_cpus();
 #endif
+	reserve_crashkernel();
 
 	cpu_init();
 	tcm_init();
-- 
1.5.6.5

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

* [RFC 02/10] arm: kdump: implement crash_setup_regs()
  2010-03-29  9:26 ` [RFC 01/10] arm: kdump: reserve memory for crashkernel Mika Westerberg
@ 2010-03-29  9:26   ` Mika Westerberg
  2010-03-29  9:26     ` [RFC 03/10] arm: kdump: implement machine_crash_shutdown() Mika Westerberg
  2010-04-12 20:01     ` [RFC 02/10] arm: kdump: implement crash_setup_regs() Russell King - ARM Linux
  0 siblings, 2 replies; 22+ messages in thread
From: Mika Westerberg @ 2010-03-29  9:26 UTC (permalink / raw)
  To: linux-arm-kernel

Implement machine specific function crash_setup_regs() which is responsible for
storing machine state when crash occured.

Signed-off-by: Mika Westerberg <ext-mika.1.westerberg@nokia.com>
---
 arch/arm/include/asm/kexec.h |   35 ++++++++++++++++++++++++++++++++---
 1 files changed, 32 insertions(+), 3 deletions(-)

diff --git a/arch/arm/include/asm/kexec.h b/arch/arm/include/asm/kexec.h
index df15a0d..4a4b66f 100644
--- a/arch/arm/include/asm/kexec.h
+++ b/arch/arm/include/asm/kexec.h
@@ -19,10 +19,39 @@
 
 #ifndef __ASSEMBLY__
 
-struct kimage;
-/* Provide a dummy definition to avoid build failures. */
+/*
+ * crash_setup_regs() - save registers for the panic kernel
+ * @newregs: registers are saved here
+ * @oldregs: registers to be saved (may be %NULL)
+ *
+ * Function copies machine registers from @oldregs to @newregs. If @oldregs is
+ * %NULL then current registers are stored there.
+ */
 static inline void crash_setup_regs(struct pt_regs *newregs,
-                                        struct pt_regs *oldregs) { }
+				    struct pt_regs *oldregs)
+{
+	if (oldregs) {
+		memcpy(newregs, oldregs, sizeof(*newregs));
+	} else {
+		__asm__ __volatile__("mov %0, r0" : "=r"(newregs->ARM_r0));
+		__asm__ __volatile__("mov %0, r1" : "=r"(newregs->ARM_r1));
+		__asm__ __volatile__("mov %0, r2" : "=r"(newregs->ARM_r2));
+		__asm__ __volatile__("mov %0, r3" : "=r"(newregs->ARM_r3));
+		__asm__ __volatile__("mov %0, r4" : "=r"(newregs->ARM_r4));
+		__asm__ __volatile__("mov %0, r5" : "=r"(newregs->ARM_r5));
+		__asm__ __volatile__("mov %0, r6" : "=r"(newregs->ARM_r6));
+		__asm__ __volatile__("mov %0, r7" : "=r"(newregs->ARM_r7));
+		__asm__ __volatile__("mov %0, r8" : "=r"(newregs->ARM_r8));
+		__asm__ __volatile__("mov %0, r9" : "=r"(newregs->ARM_r9));
+		__asm__ __volatile__("mov %0, r10" : "=r"(newregs->ARM_r10));
+		__asm__ __volatile__("mov %0, r11" : "=r"(newregs->ARM_fp));
+		__asm__ __volatile__("mov %0, r12" : "=r"(newregs->ARM_ip));
+		__asm__ __volatile__("mov %0, r13" : "=r"(newregs->ARM_sp));
+		__asm__ __volatile__("mov %0, r14" : "=r"(newregs->ARM_lr));
+		__asm__ __volatile__("mov %0, r15" : "=r"(newregs->ARM_pc));
+		__asm__ __volatile__("mrs %0, cpsr" : "=r"(newregs->ARM_cpsr));
+	}
+}
 
 #endif /* __ASSEMBLY__ */
 
-- 
1.5.6.5

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

* [RFC 03/10] arm: kdump: implement machine_crash_shutdown()
  2010-03-29  9:26   ` [RFC 02/10] arm: kdump: implement crash_setup_regs() Mika Westerberg
@ 2010-03-29  9:26     ` Mika Westerberg
  2010-03-29  9:26       ` [RFC 04/10] arm: kdump: skip indirection page when crashing Mika Westerberg
  2010-04-12 20:01     ` [RFC 02/10] arm: kdump: implement crash_setup_regs() Russell King - ARM Linux
  1 sibling, 1 reply; 22+ messages in thread
From: Mika Westerberg @ 2010-03-29  9:26 UTC (permalink / raw)
  To: linux-arm-kernel

Implement function machine_crash_shutdown() which disables IRQs and saves
machine state to ELF notes structure.

Signed-off-by: Mika Westerberg <ext-mika.1.westerberg@nokia.com>
---
 arch/arm/kernel/machine_kexec.c |    4 ++++
 1 files changed, 4 insertions(+), 0 deletions(-)

diff --git a/arch/arm/kernel/machine_kexec.c b/arch/arm/kernel/machine_kexec.c
index 598ca61..81e9898 100644
--- a/arch/arm/kernel/machine_kexec.c
+++ b/arch/arm/kernel/machine_kexec.c
@@ -43,6 +43,10 @@ void machine_shutdown(void)
 
 void machine_crash_shutdown(struct pt_regs *regs)
 {
+	local_irq_disable();
+	crash_save_cpu(regs, smp_processor_id());
+
+	printk(KERN_INFO "Loading crashdump kernel...\n");
 }
 
 void machine_kexec(struct kimage *image)
-- 
1.5.6.5

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

* [RFC 04/10] arm: kdump: skip indirection page when crashing
  2010-03-29  9:26     ` [RFC 03/10] arm: kdump: implement machine_crash_shutdown() Mika Westerberg
@ 2010-03-29  9:26       ` Mika Westerberg
  2010-03-29  9:26         ` [RFC 05/10] arm: kdump: make kexec work in interrupt context Mika Westerberg
  0 siblings, 1 reply; 22+ messages in thread
From: Mika Westerberg @ 2010-03-29  9:26 UTC (permalink / raw)
  To: linux-arm-kernel

When we are crashing there is no indirection page in place. Only control page is
present.

Signed-off-by: Mika Westerberg <ext-mika.1.westerberg@nokia.com>
---
 arch/arm/kernel/relocate_kernel.S |    6 ++++++
 1 files changed, 6 insertions(+), 0 deletions(-)

diff --git a/arch/arm/kernel/relocate_kernel.S b/arch/arm/kernel/relocate_kernel.S
index 61930eb..fd26f8d 100644
--- a/arch/arm/kernel/relocate_kernel.S
+++ b/arch/arm/kernel/relocate_kernel.S
@@ -10,6 +10,12 @@ relocate_new_kernel:
 	ldr	r0,kexec_indirection_page
 	ldr	r1,kexec_start_address
 
+	/*
+	 * If there is no indirection page (we are doing crashdumps)
+	 * skip any relocation.
+	 */
+	cmp	r0, #0
+	beq	2f
 
 0:	/* top, read another word for the indirection page */
 	ldr	r3, [r0],#4
-- 
1.5.6.5

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

* [RFC 05/10] arm: kdump: make kexec work in interrupt context
  2010-03-29  9:26       ` [RFC 04/10] arm: kdump: skip indirection page when crashing Mika Westerberg
@ 2010-03-29  9:26         ` Mika Westerberg
  2010-03-29  9:26           ` [RFC 06/10] arm: kdump: implement copy_oldmem_page() Mika Westerberg
  2010-04-12 20:03           ` [RFC 05/10] arm: kdump: make kexec work in interrupt context Russell King - ARM Linux
  0 siblings, 2 replies; 22+ messages in thread
From: Mika Westerberg @ 2010-03-29  9:26 UTC (permalink / raw)
  To: linux-arm-kernel

When crash happens in interrupt context there is no userspace context. We always
use current->active_mm in those cases.

Signed-off-by: Mika Westerberg <ext-mika.1.westerberg@nokia.com>
---
 arch/arm/mm/mmu.c |   10 ++++++----
 1 files changed, 6 insertions(+), 4 deletions(-)

diff --git a/arch/arm/mm/mmu.c b/arch/arm/mm/mmu.c
index 9d4da6a..7bf192e 100644
--- a/arch/arm/mm/mmu.c
+++ b/arch/arm/mm/mmu.c
@@ -1050,10 +1050,12 @@ void setup_mm_for_reboot(char mode)
 	pgd_t *pgd;
 	int i;
 
-	if (current->mm && current->mm->pgd)
-		pgd = current->mm->pgd;
-	else
-		pgd = init_mm.pgd;
+	/*
+	 * 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())
-- 
1.5.6.5

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

* [RFC 06/10] arm: kdump: implement copy_oldmem_page()
  2010-03-29  9:26         ` [RFC 05/10] arm: kdump: make kexec work in interrupt context Mika Westerberg
@ 2010-03-29  9:26           ` Mika Westerberg
  2010-03-29  9:26             ` [RFC 07/10] arm: allow passing an ELF64 header to elf_check_arch() Mika Westerberg
  2010-04-12 20:03           ` [RFC 05/10] arm: kdump: make kexec work in interrupt context Russell King - ARM Linux
  1 sibling, 1 reply; 22+ messages in thread
From: Mika Westerberg @ 2010-03-29  9:26 UTC (permalink / raw)
  To: linux-arm-kernel

This function is used by vmcore code to read a page from the old kernel memory.

Signed-off-by: Mika Westerberg <ext-mika.1.westerberg@nokia.com>
---
 arch/arm/kernel/Makefile     |    1 +
 arch/arm/kernel/crash_dump.c |   82 ++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 83 insertions(+), 0 deletions(-)
 create mode 100644 arch/arm/kernel/crash_dump.c

diff --git a/arch/arm/kernel/Makefile b/arch/arm/kernel/Makefile
index 26d302c..ea023c6 100644
--- a/arch/arm/kernel/Makefile
+++ b/arch/arm/kernel/Makefile
@@ -39,6 +39,7 @@ obj-$(CONFIG_ARM_THUMBEE)	+= thumbee.o
 obj-$(CONFIG_KGDB)		+= kgdb.o
 obj-$(CONFIG_ARM_UNWIND)	+= unwind.o
 obj-$(CONFIG_HAVE_TCM)		+= tcm.o
+obj-$(CONFIG_CRASH_DUMP)	+= crash_dump.o
 
 obj-$(CONFIG_CRUNCH)		+= crunch.o crunch-bits.o
 AFLAGS_crunch-bits.o		:= -Wa,-mcpu=ep9312
diff --git a/arch/arm/kernel/crash_dump.c b/arch/arm/kernel/crash_dump.c
new file mode 100644
index 0000000..84382d3
--- /dev/null
+++ b/arch/arm/kernel/crash_dump.c
@@ -0,0 +1,82 @@
+/*
+ * arch/arm/kernel/crash_dump.c
+ *
+ * Copyright (C) 2010 Nokia Corporation.
+ *
+ * This code is heavily based on x86 version found in
+ * arch/x86/kernel/crash_dump_32.c.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * Author: Mika Westerberg
+ */
+#include <linux/errno.h>
+#include <linux/crash_dump.h>
+#include <linux/uaccess.h>
+#include <linux/highmem.h>
+#include <linux/io.h>
+
+/* buffer used when copying an old page to userspace */
+static void *kdump_buf_page;
+
+/* stores the physical address of elf header of crash image */
+unsigned long long elfcorehdr_addr = ELFCORE_ADDR_MAX;
+
+/**
+ * copy_oldmem_page() - copy one page from old kernel memory
+ * @pfn: page frame number to be copied
+ * @buf: buffer where the copied page is placed
+ * @csize: number of bytes to copy
+ * @offset: offset in bytes into the page
+ * @userbuf: if set, @buf is int he user address space
+ *
+ * This function copies one page from old kernel memory into buffer pointed by
+ * @buf. If @buf is in userspace, set @userbuf to %1. Returns number of bytes
+ * copied or negative error in case of failure.
+ */
+ssize_t copy_oldmem_page(unsigned long pfn, char *buf,
+			 size_t csize, unsigned long offset,
+			 int userbuf)
+{
+	void *vaddr;
+
+	if (!csize)
+		return 0;
+
+	vaddr = kmap_atomic_pfn(pfn, KM_PTE0);
+
+	if (userbuf) {
+		if (!kdump_buf_page) {
+			printk(KERN_WARNING "Kdump: kdump buffer page not "
+				"allocated\n");
+			kunmap_atomic(vaddr, KM_PTE0);
+			return -EFAULT;
+		}
+
+		copy_page(kdump_buf_page, vaddr);
+		kunmap_atomic(vaddr, KM_PTE0);
+
+		if (copy_to_user(buf, vaddr + offset, csize))
+			return -EFAULT;
+	} else {
+		memcpy(buf, vaddr + offset, csize);
+		kunmap_atomic(vaddr, KM_PTE0);
+	}
+
+	return csize;
+}
+
+static int __init kdump_buf_page_init(void)
+{
+	kdump_buf_page = kmalloc(PAGE_SIZE, GFP_KERNEL);
+	if (!kdump_buf_page) {
+		printk(KERN_WARNING "Kdump: failed to allocate kdump buffer "
+			"page\n");
+		return -ENOMEM;
+	}
+
+	return 0;
+}
+arch_initcall(kdump_buf_page_init);
-- 
1.5.6.5

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

* [RFC 07/10] arm: allow passing an ELF64 header to elf_check_arch()
  2010-03-29  9:26           ` [RFC 06/10] arm: kdump: implement copy_oldmem_page() Mika Westerberg
@ 2010-03-29  9:26             ` Mika Westerberg
  2010-03-29  9:26               ` [RFC 08/10] arm: kdump: add support for elfcorehdr= parameter Mika Westerberg
                                 ` (2 more replies)
  0 siblings, 3 replies; 22+ messages in thread
From: Mika Westerberg @ 2010-03-29  9:26 UTC (permalink / raw)
  To: linux-arm-kernel

This is needed to shut following compiler warning when CONFIG_PROC_VMCORE is
enabled:

fs/proc/vmcore.c: In function 'parse_crash_elf64_headers':
fs/proc/vmcore.c:500: warning: passing argument 1 of 'elf_check_arch' from
incompatible pointer type

ELF32 and ELF64 headers have common fields of same size (namely e_ident and
e_machine) which are checked in arm_elf_check_arch().

Signed-off-by: Mika Westerberg <ext-mika.1.westerberg@nokia.com>
---
 arch/arm/include/asm/elf.h |    4 ++--
 arch/arm/kernel/elf.c      |    6 ++++--
 2 files changed, 6 insertions(+), 4 deletions(-)

diff --git a/arch/arm/include/asm/elf.h b/arch/arm/include/asm/elf.h
index bff0564..aa71815 100644
--- a/arch/arm/include/asm/elf.h
+++ b/arch/arm/include/asm/elf.h
@@ -92,8 +92,8 @@ struct elf32_hdr;
 /*
  * This is used to ensure we don't load something for the wrong architecture.
  */
-extern int elf_check_arch(const struct elf32_hdr *);
-#define elf_check_arch elf_check_arch
+extern int arm_elf_check_arch(const struct elf32_hdr *);
+#define elf_check_arch(x) arm_elf_check_arch((const struct elf32_hdr *)(x))
 
 extern int arm_elf_read_implies_exec(const struct elf32_hdr *, int);
 #define elf_read_implies_exec(ex,stk) arm_elf_read_implies_exec(&(ex), stk)
diff --git a/arch/arm/kernel/elf.c b/arch/arm/kernel/elf.c
index d4a0da1..14e501b 100644
--- a/arch/arm/kernel/elf.c
+++ b/arch/arm/kernel/elf.c
@@ -4,11 +4,13 @@
 #include <linux/binfmts.h>
 #include <linux/elf.h>
 
-int elf_check_arch(const struct elf32_hdr *x)
+int arm_elf_check_arch(const struct elf32_hdr *x)
 {
 	unsigned int eflags;
 
 	/* Make sure it's an ARM executable */
+	if (x->e_ident[EI_CLASS] != ELF_CLASS)
+		return 0;
 	if (x->e_machine != EM_ARM)
 		return 0;
 
@@ -35,7 +37,7 @@ int elf_check_arch(const struct elf32_hdr *x)
 	}
 	return 1;
 }
-EXPORT_SYMBOL(elf_check_arch);
+EXPORT_SYMBOL(arm_elf_check_arch);
 
 void elf_set_personality(const struct elf32_hdr *x)
 {
-- 
1.5.6.5

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

* [RFC 08/10] arm: kdump: add support for elfcorehdr= parameter
  2010-03-29  9:26             ` [RFC 07/10] arm: allow passing an ELF64 header to elf_check_arch() Mika Westerberg
@ 2010-03-29  9:26               ` Mika Westerberg
  2010-03-29  9:26                 ` [RFC 09/10] arm: implement reserve memory early parameter Mika Westerberg
  2010-03-29 21:12               ` [RFC 07/10] arm: allow passing an ELF64 header to elf_check_arch() Russell King - ARM Linux
  2010-03-29 23:41               ` Jamie Lokier
  2 siblings, 1 reply; 22+ messages in thread
From: Mika Westerberg @ 2010-03-29  9:26 UTC (permalink / raw)
  To: linux-arm-kernel

This parameter is used by primary kernel to pass address of vmcore header to the
dump capture kernel.

Signed-off-by: Mika Westerberg <ext-mika.1.westerberg@nokia.com>
---
 arch/arm/kernel/setup.c |   25 +++++++++++++++++++++++++
 1 files changed, 25 insertions(+), 0 deletions(-)

diff --git a/arch/arm/kernel/setup.c b/arch/arm/kernel/setup.c
index 076454f..25a1664 100644
--- a/arch/arm/kernel/setup.c
+++ b/arch/arm/kernel/setup.c
@@ -20,6 +20,7 @@
 #include <linux/screen_info.h>
 #include <linux/init.h>
 #include <linux/kexec.h>
+#include <linux/crash_dump.h>
 #include <linux/root_dev.h>
 #include <linux/cpu.h>
 #include <linux/interrupt.h>
@@ -711,6 +712,30 @@ static void __init reserve_crashkernel(void)
 static inline void reserve_crashkernel(void) {}
 #endif /* CONFIG_KEXEC */
 
+/*
+ * Note: elfcorehdr_addr is not just limited to vmcore. It is also used by
+ * is_kdump_kernel() to determine if we are booting after a panic. Hence
+ * ifdef it under CONFIG_CRASH_DUMP and not CONFIG_PROC_VMCORE.
+ */
+
+#ifdef CONFIG_CRASH_DUMP
+/*
+ * elfcorehdr= specifies the location of elf core header stored by the crashed
+ * kernel. This option will be passed by kexec loader to the capture kernel.
+ */
+static int __init setup_elfcorehdr(char *arg)
+{
+	char *end;
+
+	if (!arg)
+		return -EINVAL;
+
+	elfcorehdr_addr = memparse(arg, &end);
+	return end > arg ? 0 : -EINVAL;
+}
+early_param("elfcorehdr", setup_elfcorehdr);
+#endif /* CONFIG_CRASH_DUMP */
+
 void __init setup_arch(char **cmdline_p)
 {
 	struct tag *tags = (struct tag *)&init_tags;
-- 
1.5.6.5

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

* [RFC 09/10] arm: implement reserve memory early parameter
  2010-03-29  9:26               ` [RFC 08/10] arm: kdump: add support for elfcorehdr= parameter Mika Westerberg
@ 2010-03-29  9:26                 ` Mika Westerberg
  2010-03-29  9:26                   ` [RFC 10/10] arm: kdump: add CONFIG_CRASH_DUMP Kconfig option Mika Westerberg
  2010-04-12 21:05                   ` [RFC 09/10] arm: implement reserve memory early parameter Russell King - ARM Linux
  0 siblings, 2 replies; 22+ messages in thread
From: Mika Westerberg @ 2010-03-29  9:26 UTC (permalink / raw)
  To: linux-arm-kernel

Implemented mem=size$start early parameter which makes it possible to reserve
some memory from the kernel. This can be used for dump capture kernels to
preserve any memory used by the primary kernel.

Signed-off-by: Mika Westerberg <ext-mika.1.westerberg@nokia.com>
---
 arch/arm/include/asm/setup.h |    4 ++++
 arch/arm/kernel/setup.c      |   22 ++++++++++++++++------
 arch/arm/mm/init.c           |   25 +++++++++++++++++++++++--
 3 files changed, 43 insertions(+), 8 deletions(-)

diff --git a/arch/arm/include/asm/setup.h b/arch/arm/include/asm/setup.h
index f392fb4..9910300 100644
--- a/arch/arm/include/asm/setup.h
+++ b/arch/arm/include/asm/setup.h
@@ -203,6 +203,10 @@ struct membank {
 	unsigned long size;
 	unsigned short node;
 	unsigned short highmem;
+
+#define MEMBANK_FREE		0
+#define MEMBANK_RESERVED	1
+	unsigned int flags;
 };
 
 struct meminfo {
diff --git a/arch/arm/kernel/setup.c b/arch/arm/kernel/setup.c
index 25a1664..08de8b7 100644
--- a/arch/arm/kernel/setup.c
+++ b/arch/arm/kernel/setup.c
@@ -387,7 +387,8 @@ static struct machine_desc * __init setup_machine(unsigned int nr)
 	return list;
 }
 
-static int __init arm_add_memory(unsigned long start, unsigned long size)
+static int __init arm_add_memory(unsigned long start, unsigned long size,
+				 unsigned long flags)
 {
 	struct membank *bank = &meminfo.bank[meminfo.nr_banks];
 
@@ -405,6 +406,7 @@ static int __init arm_add_memory(unsigned long start, unsigned long size)
 	bank->start = PAGE_ALIGN(start);
 	bank->size  = size & PAGE_MASK;
 	bank->node  = PHYS_TO_NID(start);
+	bank->flags = flags;
 
 	/*
 	 * Check whether this memory region has non-zero size or
@@ -418,13 +420,17 @@ static int __init arm_add_memory(unsigned long start, unsigned long size)
 }
 
 /*
- * Pick out the memory size.  We look for mem=size at start,
+ * Pick out the memory size.  We look for mem=size at start or mem=size$start,
  * where start and size are "size[KkMm]"
+ *
+ * If '$' is used as a separator, it is interpreted as reserve this memory. This
+ * can be usefull for example when we are running dump capture kernel and want
+ * to reserve any memory used by the primary kernel.
  */
 static int __init early_mem(char *p)
 {
 	static int usermem __initdata = 0;
-	unsigned long size, start;
+	unsigned long size, start, flags = 0;
 	char *endp;
 
 	/*
@@ -439,10 +445,14 @@ static int __init early_mem(char *p)
 
 	start = PHYS_OFFSET;
 	size  = memparse(p, &endp);
-	if (*endp == '@')
+	if (*endp == '@') {
+		start = memparse(endp + 1, NULL);
+	} else if (*endp == '$') {
 		start = memparse(endp + 1, NULL);
+		flags = MEMBANK_RESERVED;
+	}
 
-	arm_add_memory(start, size);
+	arm_add_memory(start, size, flags);
 
 	return 0;
 }
@@ -536,7 +546,7 @@ __tagtable(ATAG_CORE, parse_tag_core);
 
 static int __init parse_tag_mem32(const struct tag *tag)
 {
-	return arm_add_memory(tag->u.mem.start, tag->u.mem.size);
+	return arm_add_memory(tag->u.mem.start, tag->u.mem.size, 0);
 }
 
 __tagtable(ATAG_MEM, parse_tag_mem32);
diff --git a/arch/arm/mm/init.c b/arch/arm/mm/init.c
index 7829cb5..41fdcd0 100644
--- a/arch/arm/mm/init.c
+++ b/arch/arm/mm/init.c
@@ -274,8 +274,29 @@ static void __init bootmem_init_node(int node, struct meminfo *mi,
 
 	for_each_nodebank(i, mi, node) {
 		struct membank *bank = &mi->bank[i];
-		if (!bank->highmem)
-			free_bootmem_node(pgdat, bank_phys_start(bank), bank_phys_size(bank));
+		unsigned long start, size;
+
+		if (bank->highmem)
+			continue;
+
+		start = bank_phys_start(bank);
+		size = bank_phys_size(bank);
+
+		free_bootmem_node(pgdat, start, size);
+
+		if (bank->flags & MEMBANK_RESERVED) {
+			int err;
+
+			err = reserve_bootmem_node(pgdat, start, size,
+						   BOOTMEM_EXCLUSIVE);
+			if (err)
+				continue;
+
+			printk(KERN_INFO
+				"reserved memory: "
+				"[0x%08lx - 0x%08lx] (%4ld MB)\n",
+				start, start + size - 1, size >> 20);
+		}
 	}
 
 	/*
-- 
1.5.6.5

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

* [RFC 10/10] arm: kdump: add CONFIG_CRASH_DUMP Kconfig option
  2010-03-29  9:26                 ` [RFC 09/10] arm: implement reserve memory early parameter Mika Westerberg
@ 2010-03-29  9:26                   ` Mika Westerberg
  2010-04-12 21:05                   ` [RFC 09/10] arm: implement reserve memory early parameter Russell King - ARM Linux
  1 sibling, 0 replies; 22+ messages in thread
From: Mika Westerberg @ 2010-03-29  9:26 UTC (permalink / raw)
  To: linux-arm-kernel

Add CONFIG_CRASH_DUMP configuration option which is used by dump capture
kernels. This option also forces one to link kernel in different address (by
default it is 0x02008000).

Signed-off-by: Mika Westerberg <ext-mika.1.westerberg@nokia.com>
---
 arch/arm/Kconfig  |   11 +++++++++++
 arch/arm/Makefile |   10 ++++++++++
 2 files changed, 21 insertions(+), 0 deletions(-)

diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index c5408bf..4940cff 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -1466,6 +1466,17 @@ config ATAGS_PROC
 	  Should the atags used to boot the kernel be exported in an "atags"
 	  file in procfs. Useful with kexec.
 
+config CRASH_DUMP
+	bool "Build kdump crash kernel (EXPERIMENTAL)"
+	depends on EXPERIMENTAL
+	help
+	  Build a kernel suitable for use as kdump capture kernel. This should
+	  be set only on dump capture kernels. Note that dump capture kernel
+	  must be loaded into different address than the primary kernel. See
+	  file arch/arm/Makefile how to change this.
+
+	  For more details see Documentation/kdump/kdump.txt
+
 endmenu
 
 menu "CPU Power Management"
diff --git a/arch/arm/Makefile b/arch/arm/Makefile
index ed820e7..848dee9 100644
--- a/arch/arm/Makefile
+++ b/arch/arm/Makefile
@@ -109,6 +109,16 @@ CHECKFLAGS	+= -D__arm__
 #Default value
 head-y		:= arch/arm/kernel/head$(MMUEXT).o arch/arm/kernel/init_task.o
 textofs-y	:= 0x00008000
+
+#
+# Dump capture kernels are linked by default to address 0x02008000 to prevent
+# them from stepping over the primary kernel memory. Adjust this if you need to
+# link it into a different address.
+#
+# Remember also check your $(MACHINE)/Makefile.boot to correspond this.
+#
+textofs-$(CONFIG_CRASH_DUMP) := 0x02008000
+
 textofs-$(CONFIG_ARCH_CLPS711X) := 0x00028000
 # SA1111 DMA bug: we don't want the kernel to live in precious DMA-able memory
 ifeq ($(CONFIG_ARCH_SA1100),y)
-- 
1.5.6.5

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

* [RFC 07/10] arm: allow passing an ELF64 header to elf_check_arch()
  2010-03-29  9:26             ` [RFC 07/10] arm: allow passing an ELF64 header to elf_check_arch() Mika Westerberg
  2010-03-29  9:26               ` [RFC 08/10] arm: kdump: add support for elfcorehdr= parameter Mika Westerberg
@ 2010-03-29 21:12               ` Russell King - ARM Linux
  2010-03-30  7:11                 ` Mika Westerberg
  2010-03-29 23:41               ` Jamie Lokier
  2 siblings, 1 reply; 22+ messages in thread
From: Russell King - ARM Linux @ 2010-03-29 21:12 UTC (permalink / raw)
  To: linux-arm-kernel

On Mon, Mar 29, 2010 at 12:26:33PM +0300, Mika Westerberg wrote:
> This is needed to shut following compiler warning when CONFIG_PROC_VMCORE is
> enabled:
> 
> fs/proc/vmcore.c: In function 'parse_crash_elf64_headers':
> fs/proc/vmcore.c:500: warning: passing argument 1 of 'elf_check_arch' from
> incompatible pointer type
> 
> ELF32 and ELF64 headers have common fields of same size (namely e_ident and
> e_machine) which are checked in arm_elf_check_arch().

A smaller patch:

-#define elf_check_arch elf_check_arch
+#define elf_check_arch(x) elf_check_arch((const struct elf32_hdr *)(x))

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

* [RFC 07/10] arm: allow passing an ELF64 header to elf_check_arch()
  2010-03-29  9:26             ` [RFC 07/10] arm: allow passing an ELF64 header to elf_check_arch() Mika Westerberg
  2010-03-29  9:26               ` [RFC 08/10] arm: kdump: add support for elfcorehdr= parameter Mika Westerberg
  2010-03-29 21:12               ` [RFC 07/10] arm: allow passing an ELF64 header to elf_check_arch() Russell King - ARM Linux
@ 2010-03-29 23:41               ` Jamie Lokier
  2010-03-30  7:26                 ` Mika Westerberg
  2 siblings, 1 reply; 22+ messages in thread
From: Jamie Lokier @ 2010-03-29 23:41 UTC (permalink / raw)
  To: linux-arm-kernel

Mika Westerberg wrote:
> This is needed to shut following compiler warning when CONFIG_PROC_VMCORE is
> enabled:
> 
> fs/proc/vmcore.c: In function 'parse_crash_elf64_headers':
> fs/proc/vmcore.c:500: warning: passing argument 1 of 'elf_check_arch' from
> incompatible pointer type
> 
> ELF32 and ELF64 headers have common fields of same size (namely e_ident and
> e_machine) which are checked in arm_elf_check_arch().

Wouldn't it be better to just disable the elf64 code entirely on
32-bit archs, saving about half of the code size in vmcore.c which
looks like it will never be called?

-- Jamie

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

* [RFC 07/10] arm: allow passing an ELF64 header to elf_check_arch()
  2010-03-29 21:12               ` [RFC 07/10] arm: allow passing an ELF64 header to elf_check_arch() Russell King - ARM Linux
@ 2010-03-30  7:11                 ` Mika Westerberg
  0 siblings, 0 replies; 22+ messages in thread
From: Mika Westerberg @ 2010-03-30  7:11 UTC (permalink / raw)
  To: linux-arm-kernel

On Mon, Mar 29, 2010 at 11:12:08PM +0200, ext Russell King - ARM Linux wrote:
> On Mon, Mar 29, 2010 at 12:26:33PM +0300, Mika Westerberg wrote:
> > This is needed to shut following compiler warning when CONFIG_PROC_VMCORE is
> > enabled:
> > 
> > fs/proc/vmcore.c: In function 'parse_crash_elf64_headers':
> > fs/proc/vmcore.c:500: warning: passing argument 1 of 'elf_check_arch' from
> > incompatible pointer type
> > 
> > ELF32 and ELF64 headers have common fields of same size (namely e_ident and
> > e_machine) which are checked in arm_elf_check_arch().
> 
> A smaller patch:
> 
> -#define elf_check_arch elf_check_arch
> +#define elf_check_arch(x) elf_check_arch((const struct elf32_hdr *)(x))

With this I get:

arch/arm/kernel/elf.c:7: error: expected declaration specifiers or '...' before
'(' token
arch/arm/kernel/elf.c: In function 'elf_check_arch':
arch/arm/kernel/elf.c:8: error: number of arguments doesn't match prototype
/home/westeri/devel/maemo/linux/linux-2.6/arch/arm/include/asm/elf.h:95: error:
prototype declaration
arch/arm/kernel/elf.c:12: error: 'x' undeclared (first use in this function)
arch/arm/kernel/elf.c:12: error: (Each undeclared identifier is reported only
once
arch/arm/kernel/elf.c:12: error: for each function it appears in.)
make[1]: *** [arch/arm/kernel/elf.o] Error 1
make: *** [arch/arm/kernel] Error 2

That's why I changed name of the function to arm_elf_check_arch().

Thanks,
MW

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

* [RFC 07/10] arm: allow passing an ELF64 header to elf_check_arch()
  2010-03-29 23:41               ` Jamie Lokier
@ 2010-03-30  7:26                 ` Mika Westerberg
  2010-03-30 11:41                   ` Jamie Lokier
  0 siblings, 1 reply; 22+ messages in thread
From: Mika Westerberg @ 2010-03-30  7:26 UTC (permalink / raw)
  To: linux-arm-kernel

On Tue, Mar 30, 2010 at 01:41:24AM +0200, ext Jamie Lokier wrote:
> Mika Westerberg wrote:
> > This is needed to shut following compiler warning when CONFIG_PROC_VMCORE is
> > enabled:
> > 
> > fs/proc/vmcore.c: In function 'parse_crash_elf64_headers':
> > fs/proc/vmcore.c:500: warning: passing argument 1 of 'elf_check_arch' from
> > incompatible pointer type
> > 
> > ELF32 and ELF64 headers have common fields of same size (namely e_ident and
> > e_machine) which are checked in arm_elf_check_arch().
> 
> Wouldn't it be better to just disable the elf64 code entirely on
> 32-bit archs, saving about half of the code size in vmcore.c which
> looks like it will never be called?

I took this approach from the other architectures that implement kdump.

At least on those archs that support both 32 and 64-bit both versions should be
supported. But I can add the required #ifdefs to vmcore code if preferred.

Thanks,
MW

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

* [RFC 07/10] arm: allow passing an ELF64 header to elf_check_arch()
  2010-03-30  7:26                 ` Mika Westerberg
@ 2010-03-30 11:41                   ` Jamie Lokier
  0 siblings, 0 replies; 22+ messages in thread
From: Jamie Lokier @ 2010-03-30 11:41 UTC (permalink / raw)
  To: linux-arm-kernel

Mika Westerberg wrote:
> On Tue, Mar 30, 2010 at 01:41:24AM +0200, ext Jamie Lokier wrote:
> > Wouldn't it be better to just disable the elf64 code entirely on
> > 32-bit archs, saving about half of the code size in vmcore.c which
> > looks like it will never be called?
> 
> I took this approach from the other architectures that implement kdump.
> 
> At least on those archs that support both 32 and 64-bit both versions should be
> supported. But I can add the required #ifdefs to vmcore code if preferred.

Ok, copying the other archs makes sense.  Someone can trim vmcore.c in
a separate patch later and tidy up the archs while they're at it.
(I've put it on my todo list but I rarely actually do the things on it...)

-- Jamie

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

* [RFC 02/10] arm: kdump: implement crash_setup_regs()
  2010-03-29  9:26   ` [RFC 02/10] arm: kdump: implement crash_setup_regs() Mika Westerberg
  2010-03-29  9:26     ` [RFC 03/10] arm: kdump: implement machine_crash_shutdown() Mika Westerberg
@ 2010-04-12 20:01     ` Russell King - ARM Linux
  2010-04-13  5:53       ` Mika Westerberg
  1 sibling, 1 reply; 22+ messages in thread
From: Russell King - ARM Linux @ 2010-04-12 20:01 UTC (permalink / raw)
  To: linux-arm-kernel

On Mon, Mar 29, 2010 at 12:26:28PM +0300, Mika Westerberg wrote:
> Implement machine specific function crash_setup_regs() which is responsible for
> storing machine state when crash occured.

Slightly concerned about this...

> +	} else {
> +		__asm__ __volatile__("mov %0, r0" : "=r"(newregs->ARM_r0));
> +		__asm__ __volatile__("mov %0, r1" : "=r"(newregs->ARM_r1));
> +		__asm__ __volatile__("mov %0, r2" : "=r"(newregs->ARM_r2));
> +		__asm__ __volatile__("mov %0, r3" : "=r"(newregs->ARM_r3));
> +		__asm__ __volatile__("mov %0, r4" : "=r"(newregs->ARM_r4));
> +		__asm__ __volatile__("mov %0, r5" : "=r"(newregs->ARM_r5));
> +		__asm__ __volatile__("mov %0, r6" : "=r"(newregs->ARM_r6));
> +		__asm__ __volatile__("mov %0, r7" : "=r"(newregs->ARM_r7));
> +		__asm__ __volatile__("mov %0, r8" : "=r"(newregs->ARM_r8));
> +		__asm__ __volatile__("mov %0, r9" : "=r"(newregs->ARM_r9));
> +		__asm__ __volatile__("mov %0, r10" : "=r"(newregs->ARM_r10));
> +		__asm__ __volatile__("mov %0, r11" : "=r"(newregs->ARM_fp));
> +		__asm__ __volatile__("mov %0, r12" : "=r"(newregs->ARM_ip));
> +		__asm__ __volatile__("mov %0, r13" : "=r"(newregs->ARM_sp));
> +		__asm__ __volatile__("mov %0, r14" : "=r"(newregs->ARM_lr));
> +		__asm__ __volatile__("mov %0, r15" : "=r"(newregs->ARM_pc));
> + 		__asm__ __volatile__("mrs %0, cpsr" : "=r"(newregs->ARM_cpsr));

How is whatever follows on supposed to work back from this state?  It's
entirely possible that the compiler will generate a load of asm between
each __asm__ statement corrupting the registers - and you can't save
all this state without having one register storing the 'newregs'
pointer.

It'd probably be better to do something like:

	__asm__ __volatile__("stmia %0, {r0 - r15}" : : "r" (&newregs->ARM_r0));
	__asm__ __volatile__("mrs %0, cpsr" : "=r" (newregs->ARM_cpsr));

instead, which should mean only one register is (potentially) corrupted.
However, I still think you're going to have problems knowing what's in
each register.

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

* [RFC 05/10] arm: kdump: make kexec work in interrupt context
  2010-03-29  9:26         ` [RFC 05/10] arm: kdump: make kexec work in interrupt context Mika Westerberg
  2010-03-29  9:26           ` [RFC 06/10] arm: kdump: implement copy_oldmem_page() Mika Westerberg
@ 2010-04-12 20:03           ` Russell King - ARM Linux
  1 sibling, 0 replies; 22+ messages in thread
From: Russell King - ARM Linux @ 2010-04-12 20:03 UTC (permalink / raw)
  To: linux-arm-kernel

On Mon, Mar 29, 2010 at 12:26:31PM +0300, Mika Westerberg wrote:
> When crash happens in interrupt context there is no userspace context. We always
> use current->active_mm in those cases.

Ok.  This should probably be a standalone bug fix.  Please send it
to the patch system, thanks.

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

* [RFC 09/10] arm: implement reserve memory early parameter
  2010-03-29  9:26                 ` [RFC 09/10] arm: implement reserve memory early parameter Mika Westerberg
  2010-03-29  9:26                   ` [RFC 10/10] arm: kdump: add CONFIG_CRASH_DUMP Kconfig option Mika Westerberg
@ 2010-04-12 21:05                   ` Russell King - ARM Linux
  2010-04-13  6:37                     ` Mika Westerberg
  2010-04-15 12:40                     ` Mika Westerberg
  1 sibling, 2 replies; 22+ messages in thread
From: Russell King - ARM Linux @ 2010-04-12 21:05 UTC (permalink / raw)
  To: linux-arm-kernel

On Mon, Mar 29, 2010 at 12:26:35PM +0300, Mika Westerberg wrote:
> Implemented mem=size$start early parameter which makes it possible to reserve
> some memory from the kernel. This can be used for dump capture kernels to
> preserve any memory used by the primary kernel.

Please note that if we move ARM over to LMB, these patches will have to
be redone.

However, I'm not sure why this is required - it appears that x86 doesn't
require this kind of feature.  Can you explain in more detail how this
new parameter format would be used?

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

* [RFC 02/10] arm: kdump: implement crash_setup_regs()
  2010-04-12 20:01     ` [RFC 02/10] arm: kdump: implement crash_setup_regs() Russell King - ARM Linux
@ 2010-04-13  5:53       ` Mika Westerberg
  0 siblings, 0 replies; 22+ messages in thread
From: Mika Westerberg @ 2010-04-13  5:53 UTC (permalink / raw)
  To: linux-arm-kernel

On Mon, Apr 12, 2010 at 10:01:44PM +0200, ext Russell King - ARM Linux wrote:
> On Mon, Mar 29, 2010 at 12:26:28PM +0300, Mika Westerberg wrote:
> > Implement machine specific function crash_setup_regs() which is responsible for
> > storing machine state when crash occured.
> 
> Slightly concerned about this...
> 
> > +	} else {
> > +		__asm__ __volatile__("mov %0, r0" : "=r"(newregs->ARM_r0));
> > +		__asm__ __volatile__("mov %0, r1" : "=r"(newregs->ARM_r1));
> > +		__asm__ __volatile__("mov %0, r2" : "=r"(newregs->ARM_r2));
> > +		__asm__ __volatile__("mov %0, r3" : "=r"(newregs->ARM_r3));
> > +		__asm__ __volatile__("mov %0, r4" : "=r"(newregs->ARM_r4));
> > +		__asm__ __volatile__("mov %0, r5" : "=r"(newregs->ARM_r5));
> > +		__asm__ __volatile__("mov %0, r6" : "=r"(newregs->ARM_r6));
> > +		__asm__ __volatile__("mov %0, r7" : "=r"(newregs->ARM_r7));
> > +		__asm__ __volatile__("mov %0, r8" : "=r"(newregs->ARM_r8));
> > +		__asm__ __volatile__("mov %0, r9" : "=r"(newregs->ARM_r9));
> > +		__asm__ __volatile__("mov %0, r10" : "=r"(newregs->ARM_r10));
> > +		__asm__ __volatile__("mov %0, r11" : "=r"(newregs->ARM_fp));
> > +		__asm__ __volatile__("mov %0, r12" : "=r"(newregs->ARM_ip));
> > +		__asm__ __volatile__("mov %0, r13" : "=r"(newregs->ARM_sp));
> > +		__asm__ __volatile__("mov %0, r14" : "=r"(newregs->ARM_lr));
> > +		__asm__ __volatile__("mov %0, r15" : "=r"(newregs->ARM_pc));
> > + 		__asm__ __volatile__("mrs %0, cpsr" : "=r"(newregs->ARM_cpsr));
> 
> How is whatever follows on supposed to work back from this state?  It's
> entirely possible that the compiler will generate a load of asm between
> each __asm__ statement corrupting the registers - and you can't save
> all this state without having one register storing the 'newregs'
> pointer.

Yeah. I'll have to admit that this is copied from other archs. For example in
x86 they do similar. Anyway I think that it is not necessary to get these
exactly correct because what we are really interested are the frames before, e.g
where the crash happened.

> It'd probably be better to do something like:
> 
> 	__asm__ __volatile__("stmia %0, {r0 - r15}" : : "r" (&newregs->ARM_r0));
> 	__asm__ __volatile__("mrs %0, cpsr" : "=r" (newregs->ARM_cpsr));
> 
> instead, which should mean only one register is (potentially) corrupted.
> However, I still think you're going to have problems knowing what's in
> each register.

Thanks. I think we can live with one register corrupted (unless someone has
better aproach for this). I'll use this in the next revision of the patches.

Regards,
MW

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

* [RFC 09/10] arm: implement reserve memory early parameter
  2010-04-12 21:05                   ` [RFC 09/10] arm: implement reserve memory early parameter Russell King - ARM Linux
@ 2010-04-13  6:37                     ` Mika Westerberg
  2010-04-15 12:40                     ` Mika Westerberg
  1 sibling, 0 replies; 22+ messages in thread
From: Mika Westerberg @ 2010-04-13  6:37 UTC (permalink / raw)
  To: linux-arm-kernel

On Mon, Apr 12, 2010 at 11:05:21PM +0200, ext Russell King - ARM Linux wrote:
> On Mon, Mar 29, 2010 at 12:26:35PM +0300, Mika Westerberg wrote:
> > Implemented mem=size$start early parameter which makes it possible to reserve
> > some memory from the kernel. This can be used for dump capture kernels to
> > preserve any memory used by the primary kernel.
> 
> Please note that if we move ARM over to LMB, these patches will have to
> be redone.

Yes.

> However, I'm not sure why this is required - it appears that x86 doesn't
> require this kind of feature.  Can you explain in more detail how this
> new parameter format would be used?

Well the idea is to preserve memory used by the primary kernel so that the dump
capture kernel is not allowed to use it.

When dump capture kernel is loaded with kexec (a userspace program) it goes
through system RAM found in /proc/iomem and marks all segments that are not
reserved for crash kernel as being reserved. This marking is done by
constructing kernel command line containing something like:

	mem=32M at 2112M mem=64M$2048M mem=160M$2144M mem=256M$2304M

Here the last 3 parameters are those that tell the dump capture kernel what
memory belongs to the primary kernel.

I actually tried to use only mem=32 at 2112M parameter but somehow the dump capture
kernel fails to boot. I couldn't find any reason for that, but it might be that
there is something I missed.

I get following when I start the kernel with only mem=32 at 2112M (the kernel is
linked to 0xc4000000):

<6>PID hash table entries: 128 (order: -3, 512 bytes)
<6>Dentry cache hash table entries: 4096 (order: 2, 16384 bytes)
<6>Inode-cache hash table entries: 2048 (order: 1, 8192 bytes)
<6>allocated 163840 bytes of page_cgroup
<6>please try 'cgroup_disable=memory' option if you don't want memory cgroups
<1>BUG: Bad page state in process swapper  pfn:84000
<1>Unhandled fault: alignment exception (0x001) at 0xfffffffb
<0>Internal error: : 1 [#1] PREEMPT
<0>last sysfs file: 
<d>Modules linked in:
CPU: 0    Not tainted  (2.6.32.10-10448-g59e4695-dirty #12)
PC is at bad_page+0xe8/0x13c
LR is at 0x0
pc : [<c409fb9c>]    lr : [<00000000>]    psr: 00000193
sp : c44b7ed0  ip : c44b7e30  fp : c44b7ef4
r10: 00000000  r9 : 00080000  r8 : 7ffffbff
r7 : 00084000  r6 : 00080000  r5 : c45bd000  r4 : ffffffbf
r3 : fffffff7  r2 : 7fbffbff  r1 : c45bd000  r0 : c44544ee
Flags: nzcv  IRQs off  FIQs on  Mode SVC_32  ISA ARM  Segment kernel
Control: 10c5387f  Table: 84004019  DAC: 00000017
<0>Process swapper (pid: 0, stack limit = 0xc44b62e8)
<0>Stack: (0xc44b7ed0 to 0xc44b8000)
<0>7ec0:                                     c44cb004 0000087f c44b7f0c c44b7ee8
<0>7ee0: c45bd000 7ffffbff c44b7f1c c44b7ef8 c40a0a18 c409fac0 00000000 00000001
<0>7f00: 00080000 00084000 c402c0cc 00000001 c44b7f2c c44b7f20 c40a0c24 c40a09b4
<0>7f20: c44b7f44 c44b7f30 c40a0c60 c40a0c1c 00000007 00000001 c44b7f54 c44b7f48
<0>7f40: c4029134 c40a0c34 c44b7f9c c44b7f58 c4016c9c c40290c0 c44b7fa4 00002000
<0>7f60: 00000000 00000001 00086000 00080000 413fc082 00000000 c451f830 c402ae14
<0>7f80: c44ba62c 840291ec 413fc082 0000001f c44b7fac c44b7fa0 c4016dc4 c4016b78
<0>7fa0: c44b7fcc c44b7fb0 c400c43c c4016dbc c402ae18 c44fa140 c402ae18 c44fa140
<0>7fc0: c44b7ff4 c44b7fd0 c40089ec c400c35c c4008674 00000000 00000000 c402ae18
<0>7fe0: 10c53c7d c44fa4b0 00000000 c44b7ff8 84008034 c40088d4 00000000 00000000
Backtrace: 
[<c409fab4>] (bad_page+0x0/0x13c) from [<c40a0a18>] (free_hot_cold_page+0x70/0x22c)
 r5:7ffffbff r4:c45bd000
[<c40a09a8>] (free_hot_cold_page+0x0/0x22c) from [<c40a0c24>] (free_hot_page+0x14/0x18)
[<c40a0c10>] (free_hot_page+0x0/0x18) from [<c40a0c60>] (__free_pages+0x38/0x44)
[<c40a0c28>] (__free_pages+0x0/0x44) from [<c4029134>] (__free_pages_bootmem+0x80/0x84)
 r5:00000001 r4:00000007
[<c40290b4>] (__free_pages_bootmem+0x0/0x84) from [<c4016c9c>] (free_all_bootmem_core+0x130/0x224)
[<c4016b6c>] (free_all_bootmem_core+0x0/0x224) from [<c4016dc4>] (free_all_bootmem_node+0x14/0x18)
[<c4016db0>] (free_all_bootmem_node+0x0/0x18) from [<c400c43c>] (mem_init+0xec/0x208)
[<c400c350>] (mem_init+0x0/0x208) from [<c40089ec>] (start_kernel+0x124/0x2cc)
 r5:c44fa140 r4:c402ae18
[<c40088c8>] (start_kernel+0x0/0x2cc) from [<84008034>] (0x84008034)

Thanks,
MW

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

* [RFC 09/10] arm: implement reserve memory early parameter
  2010-04-12 21:05                   ` [RFC 09/10] arm: implement reserve memory early parameter Russell King - ARM Linux
  2010-04-13  6:37                     ` Mika Westerberg
@ 2010-04-15 12:40                     ` Mika Westerberg
  1 sibling, 0 replies; 22+ messages in thread
From: Mika Westerberg @ 2010-04-15 12:40 UTC (permalink / raw)
  To: linux-arm-kernel

On Mon, Apr 12, 2010 at 11:05:21PM +0200, ext Russell King - ARM Linux wrote:
> On Mon, Mar 29, 2010 at 12:26:35PM +0300, Mika Westerberg wrote:
> > Implemented mem=size$start early parameter which makes it possible to reserve
> > some memory from the kernel. This can be used for dump capture kernels to
> > preserve any memory used by the primary kernel.
> 
> Please note that if we move ARM over to LMB, these patches will have to
> be redone.
> 
> However, I'm not sure why this is required - it appears that x86 doesn't
> require this kind of feature.  Can you explain in more detail how this
> new parameter format would be used?

Hi,

I investigated this further and it seems that this is, like you commented, not
required. It should be enough to pass correct mem=size at start parameter to the
dump capture kernel.

I have following changes to get kernel linked into different address (in this
case 0xc2008000):
	arch/arm/Makefile: 			textofs-y := 0x02008000
	arch/arm/mach-omap2/Makefile.boot:	zreladdr-y := 0x82008000

Physical memory in this platform starts at 0x80000000.

When I start the kernel with 'mem=32M at 0x82000000' boot fails in very early stage:

[    0.000000] BUG: Bad page state in process swapper  pfn:82000
[    0.000000] page:c2ac2000 count:0 mapcount:0 mapping:(null) index:0xffffffff
[    0.000000] page flags: 0x92092(error|dirty|slab|writeback|swapcache|buddy)

Is mem= parameter supposed to work so that I can pass also start address? Now it
seems to still use hard-coded PHYS_OFFSET etc. Or maybe I'm doing something
wrong here.

I managed to get this working with following patch but it is probably not
correct. Any ideas how to get it working properly?

Thanks,
MW

diff --git a/arch/arm/include/asm/memory.h b/arch/arm/include/asm/memory.h
index 4312ee5..7036a2f 100644
--- a/arch/arm/include/asm/memory.h
+++ b/arch/arm/include/asm/memory.h
@@ -171,7 +171,8 @@
  * direct-mapped view.  We assume this is the first page
  * of RAM in the mem_map as well.
  */
-#define PHYS_PFN_OFFSET	(PHYS_OFFSET >> PAGE_SHIFT)
+extern unsigned long phys_pfn_offset;
+#define PHYS_PFN_OFFSET	phys_pfn_offset
 
 /*
  * These are *only* valid on the kernel direct mapped RAM memory.
diff --git a/arch/arm/kernel/setup.c b/arch/arm/kernel/setup.c
index 25a1664..e61e57d 100644
--- a/arch/arm/kernel/setup.c
+++ b/arch/arm/kernel/setup.c
@@ -90,6 +90,8 @@ EXPORT_SYMBOL(system_serial_high);
 unsigned int elf_hwcap;
 EXPORT_SYMBOL(elf_hwcap);
 
+unsigned long phys_pfn_offset = PHYS_OFFSET >> PAGE_SHIFT;
+EXPORT_SYMBOL(phys_pfn_offset);
 
 #ifdef MULTI_CPU
 struct processor processor;
@@ -439,8 +441,10 @@ static int __init early_mem(char *p)
 
 	start = PHYS_OFFSET;
 	size  = memparse(p, &endp);
-	if (*endp == '@')
+	if (*endp == '@') {
 		start = memparse(endp + 1, NULL);
+		phys_pfn_offset = start >> PAGE_SHIFT;
+	}
 
 	arm_add_memory(start, size);
 

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

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

Thread overview: 22+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2010-03-29  9:26 [RFC 00/10] Initial implementation of kdump for ARM Mika Westerberg
2010-03-29  9:26 ` [RFC 01/10] arm: kdump: reserve memory for crashkernel Mika Westerberg
2010-03-29  9:26   ` [RFC 02/10] arm: kdump: implement crash_setup_regs() Mika Westerberg
2010-03-29  9:26     ` [RFC 03/10] arm: kdump: implement machine_crash_shutdown() Mika Westerberg
2010-03-29  9:26       ` [RFC 04/10] arm: kdump: skip indirection page when crashing Mika Westerberg
2010-03-29  9:26         ` [RFC 05/10] arm: kdump: make kexec work in interrupt context Mika Westerberg
2010-03-29  9:26           ` [RFC 06/10] arm: kdump: implement copy_oldmem_page() Mika Westerberg
2010-03-29  9:26             ` [RFC 07/10] arm: allow passing an ELF64 header to elf_check_arch() Mika Westerberg
2010-03-29  9:26               ` [RFC 08/10] arm: kdump: add support for elfcorehdr= parameter Mika Westerberg
2010-03-29  9:26                 ` [RFC 09/10] arm: implement reserve memory early parameter Mika Westerberg
2010-03-29  9:26                   ` [RFC 10/10] arm: kdump: add CONFIG_CRASH_DUMP Kconfig option Mika Westerberg
2010-04-12 21:05                   ` [RFC 09/10] arm: implement reserve memory early parameter Russell King - ARM Linux
2010-04-13  6:37                     ` Mika Westerberg
2010-04-15 12:40                     ` Mika Westerberg
2010-03-29 21:12               ` [RFC 07/10] arm: allow passing an ELF64 header to elf_check_arch() Russell King - ARM Linux
2010-03-30  7:11                 ` Mika Westerberg
2010-03-29 23:41               ` Jamie Lokier
2010-03-30  7:26                 ` Mika Westerberg
2010-03-30 11:41                   ` Jamie Lokier
2010-04-12 20:03           ` [RFC 05/10] arm: kdump: make kexec work in interrupt context Russell King - ARM Linux
2010-04-12 20:01     ` [RFC 02/10] arm: kdump: implement crash_setup_regs() Russell King - ARM Linux
2010-04-13  5:53       ` Mika Westerberg

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.