summaryrefslogtreecommitdiffstats
path: root/arch/arm/kernel/setup.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/arm/kernel/setup.c')
-rw-r--r--arch/arm/kernel/setup.c111
1 files changed, 109 insertions, 2 deletions
diff --git a/arch/arm/kernel/setup.c b/arch/arm/kernel/setup.c
index 122d999bdc7..d5231ae7355 100644
--- a/arch/arm/kernel/setup.c
+++ b/arch/arm/kernel/setup.c
@@ -19,12 +19,15 @@
#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>
#include <linux/smp.h>
#include <linux/fs.h>
#include <linux/proc_fs.h>
+#include <linux/memblock.h>
#include <asm/unified.h>
#include <asm/cpu.h>
@@ -44,7 +47,9 @@
#include <asm/traps.h>
#include <asm/unwind.h>
+#if defined(CONFIG_DEPRECATED_PARAM_STRUCT)
#include "compat.h"
+#endif
#include "atags.h"
#include "tcm.h"
@@ -269,6 +274,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;
@@ -311,6 +331,8 @@ static void __init setup_processor(void)
elf_hwcap &= ~HWCAP_THUMB;
#endif
+ feat_v6_fixup();
+
cacheid_init();
cpu_proc_init();
}
@@ -402,13 +424,12 @@ static int __init arm_add_memory(unsigned long start, unsigned long size)
size -= start & ~PAGE_MASK;
bank->start = PAGE_ALIGN(start);
bank->size = size & PAGE_MASK;
- bank->node = PHYS_TO_NID(start);
/*
* Check whether this memory region has non-zero size or
* invalid node number.
*/
- if (bank->size == 0 || bank->node >= MAX_NUMNODES)
+ if (bank->size == 0)
return -EINVAL;
meminfo.nr_banks++;
@@ -663,6 +684,86 @@ 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 */
+
+static void __init squash_mem_tags(struct tag *tag)
+{
+ for (; tag->hdr.size; tag = tag_next(tag))
+ if (tag->hdr.tag == ATAG_MEM)
+ tag->hdr.tag = ATAG_NONE;
+}
+
void __init setup_arch(char **cmdline_p)
{
struct tag *tags = (struct tag *)&init_tags;
@@ -683,12 +784,14 @@ void __init setup_arch(char **cmdline_p)
else if (mdesc->boot_params)
tags = phys_to_virt(mdesc->boot_params);
+#if defined(CONFIG_DEPRECATED_PARAM_STRUCT)
/*
* If we have the old style parameters, convert them to
* a tag list.
*/
if (tags->hdr.tag != ATAG_CORE)
convert_to_tag_list(tags);
+#endif
if (tags->hdr.tag != ATAG_CORE)
tags = (struct tag *)&init_tags;
@@ -716,12 +819,15 @@ void __init setup_arch(char **cmdline_p)
parse_early_param();
+ arm_memblock_init(&meminfo, mdesc);
+
paging_init(mdesc);
request_standard_resources(&meminfo, mdesc);
#ifdef CONFIG_SMP
smp_init_cpus();
#endif
+ reserve_crashkernel();
cpu_init();
tcm_init();
@@ -729,6 +835,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;