diff options
Diffstat (limited to 'arch/arm/kernel/setup.c')
-rw-r--r-- | arch/arm/kernel/setup.c | 94 |
1 files changed, 94 insertions, 0 deletions
diff --git a/arch/arm/kernel/setup.c b/arch/arm/kernel/setup.c index 31b2643bb0c6..776ea1aa974b 100644 --- a/arch/arm/kernel/setup.c +++ b/arch/arm/kernel/setup.c @@ -19,6 +19,8 @@ #include <linux/seq_file.h> #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> @@ -270,6 +272,21 @@ static void __init cacheid_init(void) extern struct proc_info_list *lookup_processor_type(unsigned int); extern struct machine_desc *lookup_machine_type(unsigned int); +static void __init feat_v6_fixup(void) +{ + int id = read_cpuid_id(); + + if ((id & 0xff0f0000) != 0x41070000) + return; + + /* + * HWCAP_TLS is available only on 1136 r1p0 and later, + * see also kuser_get_tls_init. + */ + if ((((id >> 4) & 0xfff) == 0xb36) && (((id >> 20) & 3) == 0)) + elf_hwcap &= ~HWCAP_TLS; +} + static void __init setup_processor(void) { struct proc_info_list *list; @@ -312,6 +329,8 @@ static void __init setup_processor(void) elf_hwcap &= ~HWCAP_THUMB; #endif + feat_v6_fixup(); + cacheid_init(); cpu_proc_init(); } @@ -663,6 +682,79 @@ 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 at %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 */ + +/* + * 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; @@ -724,6 +816,7 @@ void __init setup_arch(char **cmdline_p) #ifdef CONFIG_SMP smp_init_cpus(); #endif + reserve_crashkernel(); cpu_init(); tcm_init(); @@ -731,6 +824,7 @@ void __init setup_arch(char **cmdline_p) /* * Set up various architecture-specific pointers */ + arch_nr_irqs = mdesc->nr_irqs; init_arch_irq = mdesc->init_irq; system_timer = mdesc->timer; init_machine = mdesc->init_machine; |