aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/kernel
diff options
context:
space:
mode:
Diffstat (limited to 'arch/arm/kernel')
-rw-r--r--arch/arm/kernel/Makefile1
-rw-r--r--arch/arm/kernel/crash_dump.c60
-rw-r--r--arch/arm/kernel/machine_kexec.c4
-rw-r--r--arch/arm/kernel/relocate_kernel.S6
-rw-r--r--arch/arm/kernel/setup.c82
5 files changed, 151 insertions, 2 deletions
diff --git a/arch/arm/kernel/Makefile b/arch/arm/kernel/Makefile
index 26d302c28e13..ea023c6aa31e 100644
--- a/arch/arm/kernel/Makefile
+++ b/arch/arm/kernel/Makefile
@@ -39,6 +39,7 @@ obj-$(CONFIG_ARM_THUMBEE) += thumbee.o
39obj-$(CONFIG_KGDB) += kgdb.o 39obj-$(CONFIG_KGDB) += kgdb.o
40obj-$(CONFIG_ARM_UNWIND) += unwind.o 40obj-$(CONFIG_ARM_UNWIND) += unwind.o
41obj-$(CONFIG_HAVE_TCM) += tcm.o 41obj-$(CONFIG_HAVE_TCM) += tcm.o
42obj-$(CONFIG_CRASH_DUMP) += crash_dump.o
42 43
43obj-$(CONFIG_CRUNCH) += crunch.o crunch-bits.o 44obj-$(CONFIG_CRUNCH) += crunch.o crunch-bits.o
44AFLAGS_crunch-bits.o := -Wa,-mcpu=ep9312 45AFLAGS_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 000000000000..cd3b853a8a6d
--- /dev/null
+++ b/arch/arm/kernel/crash_dump.c
@@ -0,0 +1,60 @@
1/*
2 * arch/arm/kernel/crash_dump.c
3 *
4 * Copyright (C) 2010 Nokia Corporation.
5 * Author: Mika Westerberg
6 *
7 * This code is taken from arch/x86/kernel/crash_dump_64.c
8 * Created by: Hariprasad Nellitheertha (hari@in.ibm.com)
9 * Copyright (C) IBM Corporation, 2004. All rights reserved
10 *
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License version 2 as
13 * published by the Free Software Foundation.
14 */
15
16#include <linux/errno.h>
17#include <linux/crash_dump.h>
18#include <linux/uaccess.h>
19#include <linux/io.h>
20
21/* stores the physical address of elf header of crash image */
22unsigned long long elfcorehdr_addr = ELFCORE_ADDR_MAX;
23
24/**
25 * copy_oldmem_page() - copy one page from old kernel memory
26 * @pfn: page frame number to be copied
27 * @buf: buffer where the copied page is placed
28 * @csize: number of bytes to copy
29 * @offset: offset in bytes into the page
30 * @userbuf: if set, @buf is int he user address space
31 *
32 * This function copies one page from old kernel memory into buffer pointed by
33 * @buf. If @buf is in userspace, set @userbuf to %1. Returns number of bytes
34 * copied or negative error in case of failure.
35 */
36ssize_t copy_oldmem_page(unsigned long pfn, char *buf,
37 size_t csize, unsigned long offset,
38 int userbuf)
39{
40 void *vaddr;
41
42 if (!csize)
43 return 0;
44
45 vaddr = ioremap(pfn << PAGE_SHIFT, PAGE_SIZE);
46 if (!vaddr)
47 return -ENOMEM;
48
49 if (userbuf) {
50 if (copy_to_user(buf, vaddr + offset, csize)) {
51 iounmap(vaddr);
52 return -EFAULT;
53 }
54 } else {
55 memcpy(buf, vaddr + offset, csize);
56 }
57
58 iounmap(vaddr);
59 return csize;
60}
diff --git a/arch/arm/kernel/machine_kexec.c b/arch/arm/kernel/machine_kexec.c
index df5958f6864f..1fc74cbd1a19 100644
--- a/arch/arm/kernel/machine_kexec.c
+++ b/arch/arm/kernel/machine_kexec.c
@@ -39,6 +39,10 @@ void machine_kexec_cleanup(struct kimage *image)
39 39
40void machine_crash_shutdown(struct pt_regs *regs) 40void machine_crash_shutdown(struct pt_regs *regs)
41{ 41{
42 local_irq_disable();
43 crash_save_cpu(regs, smp_processor_id());
44
45 printk(KERN_INFO "Loading crashdump kernel...\n");
42} 46}
43 47
44void machine_kexec(struct kimage *image) 48void machine_kexec(struct kimage *image)
diff --git a/arch/arm/kernel/relocate_kernel.S b/arch/arm/kernel/relocate_kernel.S
index 61930eb09029..fd26f8d65151 100644
--- a/arch/arm/kernel/relocate_kernel.S
+++ b/arch/arm/kernel/relocate_kernel.S
@@ -10,6 +10,12 @@ relocate_new_kernel:
10 ldr r0,kexec_indirection_page 10 ldr r0,kexec_indirection_page
11 ldr r1,kexec_start_address 11 ldr r1,kexec_start_address
12 12
13 /*
14 * If there is no indirection page (we are doing crashdumps)
15 * skip any relocation.
16 */
17 cmp r0, #0
18 beq 2f
13 19
140: /* top, read another word for the indirection page */ 200: /* top, read another word for the indirection page */
15 ldr r3, [r0],#4 21 ldr r3, [r0],#4
diff --git a/arch/arm/kernel/setup.c b/arch/arm/kernel/setup.c
index 648c3c1e16c4..776ea1aa974b 100644
--- a/arch/arm/kernel/setup.c
+++ b/arch/arm/kernel/setup.c
@@ -19,12 +19,15 @@
19#include <linux/seq_file.h> 19#include <linux/seq_file.h>
20#include <linux/screen_info.h> 20#include <linux/screen_info.h>
21#include <linux/init.h> 21#include <linux/init.h>
22#include <linux/kexec.h>
23#include <linux/crash_dump.h>
22#include <linux/root_dev.h> 24#include <linux/root_dev.h>
23#include <linux/cpu.h> 25#include <linux/cpu.h>
24#include <linux/interrupt.h> 26#include <linux/interrupt.h>
25#include <linux/smp.h> 27#include <linux/smp.h>
26#include <linux/fs.h> 28#include <linux/fs.h>
27#include <linux/proc_fs.h> 29#include <linux/proc_fs.h>
30#include <linux/memblock.h>
28 31
29#include <asm/unified.h> 32#include <asm/unified.h>
30#include <asm/cpu.h> 33#include <asm/cpu.h>
@@ -419,13 +422,12 @@ static int __init arm_add_memory(unsigned long start, unsigned long size)
419 size -= start & ~PAGE_MASK; 422 size -= start & ~PAGE_MASK;
420 bank->start = PAGE_ALIGN(start); 423 bank->start = PAGE_ALIGN(start);
421 bank->size = size & PAGE_MASK; 424 bank->size = size & PAGE_MASK;
422 bank->node = PHYS_TO_NID(start);
423 425
424 /* 426 /*
425 * Check whether this memory region has non-zero size or 427 * Check whether this memory region has non-zero size or
426 * invalid node number. 428 * invalid node number.
427 */ 429 */
428 if (bank->size == 0 || bank->node >= MAX_NUMNODES) 430 if (bank->size == 0)
429 return -EINVAL; 431 return -EINVAL;
430 432
431 meminfo.nr_banks++; 433 meminfo.nr_banks++;
@@ -680,6 +682,79 @@ static int __init customize_machine(void)
680} 682}
681arch_initcall(customize_machine); 683arch_initcall(customize_machine);
682 684
685#ifdef CONFIG_KEXEC
686static inline unsigned long long get_total_mem(void)
687{
688 unsigned long total;
689
690 total = max_low_pfn - min_low_pfn;
691 return total << PAGE_SHIFT;
692}
693
694/**
695 * reserve_crashkernel() - reserves memory are for crash kernel
696 *
697 * This function reserves memory area given in "crashkernel=" kernel command
698 * line parameter. The memory reserved is used by a dump capture kernel when
699 * primary kernel is crashing.
700 */
701static void __init reserve_crashkernel(void)
702{
703 unsigned long long crash_size, crash_base;
704 unsigned long long total_mem;
705 int ret;
706
707 total_mem = get_total_mem();
708 ret = parse_crashkernel(boot_command_line, total_mem,
709 &crash_size, &crash_base);
710 if (ret)
711 return;
712
713 ret = reserve_bootmem(crash_base, crash_size, BOOTMEM_EXCLUSIVE);
714 if (ret < 0) {
715 printk(KERN_WARNING "crashkernel reservation failed - "
716 "memory is in use (0x%lx)\n", (unsigned long)crash_base);
717 return;
718 }
719
720 printk(KERN_INFO "Reserving %ldMB of memory at %ldMB "
721 "for crashkernel (System RAM: %ldMB)\n",
722 (unsigned long)(crash_size >> 20),
723 (unsigned long)(crash_base >> 20),
724 (unsigned long)(total_mem >> 20));
725
726 crashk_res.start = crash_base;
727 crashk_res.end = crash_base + crash_size - 1;
728 insert_resource(&iomem_resource, &crashk_res);
729}
730#else
731static inline void reserve_crashkernel(void) {}
732#endif /* CONFIG_KEXEC */
733
734/*
735 * Note: elfcorehdr_addr is not just limited to vmcore. It is also used by
736 * is_kdump_kernel() to determine if we are booting after a panic. Hence
737 * ifdef it under CONFIG_CRASH_DUMP and not CONFIG_PROC_VMCORE.
738 */
739
740#ifdef CONFIG_CRASH_DUMP
741/*
742 * elfcorehdr= specifies the location of elf core header stored by the crashed
743 * kernel. This option will be passed by kexec loader to the capture kernel.
744 */
745static int __init setup_elfcorehdr(char *arg)
746{
747 char *end;
748
749 if (!arg)
750 return -EINVAL;
751
752 elfcorehdr_addr = memparse(arg, &end);
753 return end > arg ? 0 : -EINVAL;
754}
755early_param("elfcorehdr", setup_elfcorehdr);
756#endif /* CONFIG_CRASH_DUMP */
757
683void __init setup_arch(char **cmdline_p) 758void __init setup_arch(char **cmdline_p)
684{ 759{
685 struct tag *tags = (struct tag *)&init_tags; 760 struct tag *tags = (struct tag *)&init_tags;
@@ -733,12 +808,15 @@ void __init setup_arch(char **cmdline_p)
733 808
734 parse_early_param(); 809 parse_early_param();
735 810
811 arm_memblock_init(&meminfo, mdesc);
812
736 paging_init(mdesc); 813 paging_init(mdesc);
737 request_standard_resources(&meminfo, mdesc); 814 request_standard_resources(&meminfo, mdesc);
738 815
739#ifdef CONFIG_SMP 816#ifdef CONFIG_SMP
740 smp_init_cpus(); 817 smp_init_cpus();
741#endif 818#endif
819 reserve_crashkernel();
742 820
743 cpu_init(); 821 cpu_init();
744 tcm_init(); 822 tcm_init();