diff options
Diffstat (limited to 'arch/arm/kernel')
-rw-r--r-- | arch/arm/kernel/Makefile | 1 | ||||
-rw-r--r-- | arch/arm/kernel/crash_dump.c | 60 | ||||
-rw-r--r-- | arch/arm/kernel/machine_kexec.c | 4 | ||||
-rw-r--r-- | arch/arm/kernel/relocate_kernel.S | 6 | ||||
-rw-r--r-- | arch/arm/kernel/setup.c | 82 |
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 | |||
39 | obj-$(CONFIG_KGDB) += kgdb.o | 39 | obj-$(CONFIG_KGDB) += kgdb.o |
40 | obj-$(CONFIG_ARM_UNWIND) += unwind.o | 40 | obj-$(CONFIG_ARM_UNWIND) += unwind.o |
41 | obj-$(CONFIG_HAVE_TCM) += tcm.o | 41 | obj-$(CONFIG_HAVE_TCM) += tcm.o |
42 | obj-$(CONFIG_CRASH_DUMP) += crash_dump.o | ||
42 | 43 | ||
43 | obj-$(CONFIG_CRUNCH) += crunch.o crunch-bits.o | 44 | obj-$(CONFIG_CRUNCH) += crunch.o crunch-bits.o |
44 | AFLAGS_crunch-bits.o := -Wa,-mcpu=ep9312 | 45 | 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 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 */ | ||
22 | unsigned 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 | */ | ||
36 | ssize_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 | ||
40 | void machine_crash_shutdown(struct pt_regs *regs) | 40 | void 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 | ||
44 | void machine_kexec(struct kimage *image) | 48 | void 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 | ||
14 | 0: /* top, read another word for the indirection page */ | 20 | 0: /* 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 | } |
681 | arch_initcall(customize_machine); | 683 | arch_initcall(customize_machine); |
682 | 684 | ||
685 | #ifdef CONFIG_KEXEC | ||
686 | static 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 | */ | ||
701 | static 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 | ||
731 | static 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 | */ | ||
745 | static 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 | } | ||
755 | early_param("elfcorehdr", setup_elfcorehdr); | ||
756 | #endif /* CONFIG_CRASH_DUMP */ | ||
757 | |||
683 | void __init setup_arch(char **cmdline_p) | 758 | void __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(); |