aboutsummaryrefslogtreecommitdiff
path: root/arch/mips/kernel/setup.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/mips/kernel/setup.c')
-rw-r--r--arch/mips/kernel/setup.c223
1 files changed, 150 insertions, 73 deletions
diff --git a/arch/mips/kernel/setup.c b/arch/mips/kernel/setup.c
index 8c41187801c..a842154d57d 100644
--- a/arch/mips/kernel/setup.c
+++ b/arch/mips/kernel/setup.c
@@ -8,7 +8,7 @@
* Copyright (C) 1994, 95, 96, 97, 98, 99, 2000, 01, 02, 03 Ralf Baechle
* Copyright (C) 1996 Stoned Elipot
* Copyright (C) 1999 Silicon Graphics, Inc.
- * Copyright (C) 2000, 2001, 2002, 2007 Maciej W. Rozycki
+ * Copyright (C) 2000, 2001, 2002, 2007 Maciej W. Rozycki
*/
#include <linux/init.h>
#include <linux/ioport.h>
@@ -23,6 +23,7 @@
#include <linux/pfn.h>
#include <linux/debugfs.h>
#include <linux/kexec.h>
+#include <linux/sizes.h>
#include <asm/addrspace.h>
#include <asm/bootinfo.h>
@@ -77,6 +78,8 @@ EXPORT_SYMBOL(mips_io_port_base);
static struct resource code_resource = { .name = "Kernel code", };
static struct resource data_resource = { .name = "Kernel data", };
+static void *detect_magic __initdata = detect_memory_region;
+
void __init add_memory_region(phys_t start, phys_t size, long type)
{
int x = boot_mem_map.nr_map;
@@ -122,6 +125,25 @@ void __init add_memory_region(phys_t start, phys_t size, long type)
boot_mem_map.nr_map++;
}
+void __init detect_memory_region(phys_t start, phys_t sz_min, phys_t sz_max)
+{
+ void *dm = &detect_magic;
+ phys_t size;
+
+ for (size = sz_min; size < sz_max; size <<= 1) {
+ if (!memcmp(dm, dm + size, sizeof(detect_magic)))
+ break;
+ }
+
+ pr_debug("Memory: %lluMB of RAM detected at 0x%llx (min: %lluMB, max: %lluMB)\n",
+ ((unsigned long long) size) / SZ_1M,
+ (unsigned long long) start,
+ ((unsigned long long) sz_min) / SZ_1M,
+ ((unsigned long long) sz_max) / SZ_1M);
+
+ add_memory_region(start, size, BOOT_MEM_RAM);
+}
+
static void __init print_memory_map(void)
{
int i;
@@ -278,12 +300,13 @@ static void __init bootmem_init(void)
int i;
/*
- * Init any data related to initrd. It's a nop if INITRD is
- * not selected. Once that done we can determine the low bound
- * of usable memory.
+ * Sanity check any INITRD first. We don't take it into account
+ * for bootmem setup initially, rely on the end-of-kernel-code
+ * as our memory range starting point. Once bootmem is inited we
+ * will reserve the area used for the initrd.
*/
- reserved_end = max(init_initrd(),
- (unsigned long) PFN_UP(__pa_symbol(&_end)));
+ init_initrd();
+ reserved_end = (unsigned long) PFN_UP(__pa_symbol(&_end));
/*
* max_low_pfn is not a number of pages. The number of pages
@@ -340,6 +363,14 @@ static void __init bootmem_init(void)
max_low_pfn = PFN_DOWN(HIGHMEM_START);
}
+#ifdef CONFIG_BLK_DEV_INITRD
+ /*
+ * mapstart should be after initrd_end
+ */
+ if (initrd_end)
+ mapstart = max(mapstart, (unsigned long)PFN_UP(__pa(initrd_end)));
+#endif
+
/*
* Initialize the boot-time allocator with low memory only.
*/
@@ -449,7 +480,7 @@ static void __init bootmem_init(void)
* At this stage the bootmem allocator is ready to use.
*
* NOTE: historically plat_mem_setup did the entire platform initialization.
- * This was rather impractical because it meant plat_mem_setup had to
+ * This was rather impractical because it meant plat_mem_setup had to
* get away without any kind of memory allocator. To keep old code from
* breaking plat_setup was just renamed to plat_setup and a second platform
* initialization hook for anything else was introduced.
@@ -469,7 +500,7 @@ static int __init early_parse_mem(char *p)
if (usermem == 0) {
boot_mem_map.nr_map = 0;
usermem = 1;
- }
+ }
start = 0;
size = memparse(p, &p);
if (*p == '@')
@@ -480,73 +511,54 @@ static int __init early_parse_mem(char *p)
}
early_param("mem", early_parse_mem);
-static void __init arch_mem_init(char **cmdline_p)
+#ifdef CONFIG_PROC_VMCORE
+unsigned long setup_elfcorehdr, setup_elfcorehdr_size;
+static int __init early_parse_elfcorehdr(char *p)
{
- phys_t init_mem, init_end, init_size;
-
- extern void plat_mem_setup(void);
+ int i;
- /* call board setup routine */
- plat_mem_setup();
+ setup_elfcorehdr = memparse(p, &p);
- init_mem = PFN_UP(__pa_symbol(&__init_begin)) << PAGE_SHIFT;
- init_end = PFN_DOWN(__pa_symbol(&__init_end)) << PAGE_SHIFT;
- init_size = init_end - init_mem;
- if (init_size) {
- /* Make sure it is in the boot_mem_map */
- int i, found;
- found = 0;
- for (i = 0; i < boot_mem_map.nr_map; i++) {
- if (init_mem >= boot_mem_map.map[i].addr &&
- init_mem < (boot_mem_map.map[i].addr +
- boot_mem_map.map[i].size)) {
- found = 1;
- break;
- }
+ for (i = 0; i < boot_mem_map.nr_map; i++) {
+ unsigned long start = boot_mem_map.map[i].addr;
+ unsigned long end = (boot_mem_map.map[i].addr +
+ boot_mem_map.map[i].size);
+ if (setup_elfcorehdr >= start && setup_elfcorehdr < end) {
+ /*
+ * Reserve from the elf core header to the end of
+ * the memory segment, that should all be kdump
+ * reserved memory.
+ */
+ setup_elfcorehdr_size = end - setup_elfcorehdr;
+ break;
}
- if (!found)
- add_memory_region(init_mem, init_size,
- BOOT_MEM_INIT_RAM);
}
-
- pr_info("Determined physical RAM map:\n");
- print_memory_map();
-
-#ifdef CONFIG_CMDLINE_BOOL
-#ifdef CONFIG_CMDLINE_OVERRIDE
- strlcpy(boot_command_line, builtin_cmdline, COMMAND_LINE_SIZE);
-#else
- if (builtin_cmdline[0]) {
- strlcat(arcs_cmdline, " ", COMMAND_LINE_SIZE);
- strlcat(arcs_cmdline, builtin_cmdline, COMMAND_LINE_SIZE);
- }
- strlcpy(boot_command_line, arcs_cmdline, COMMAND_LINE_SIZE);
-#endif
-#else
- strlcpy(boot_command_line, arcs_cmdline, COMMAND_LINE_SIZE);
+ /*
+ * If we don't find it in the memory map, then we shouldn't
+ * have to worry about it, as the new kernel won't use it.
+ */
+ return 0;
+}
+early_param("elfcorehdr", early_parse_elfcorehdr);
#endif
- strlcpy(command_line, boot_command_line, COMMAND_LINE_SIZE);
- *cmdline_p = command_line;
+static void __init arch_mem_addpart(phys_t mem, phys_t end, int type)
+{
+ phys_t size;
+ int i;
- parse_early_param();
+ size = end - mem;
+ if (!size)
+ return;
- if (usermem) {
- pr_info("User-defined physical RAM map:\n");
- print_memory_map();
+ /* Make sure it is in the boot_mem_map */
+ for (i = 0; i < boot_mem_map.nr_map; i++) {
+ if (mem >= boot_mem_map.map[i].addr &&
+ mem < (boot_mem_map.map[i].addr +
+ boot_mem_map.map[i].size))
+ return;
}
-
- bootmem_init();
-#ifdef CONFIG_KEXEC
- if (crashk_res.start != crashk_res.end)
- reserve_bootmem(crashk_res.start,
- crashk_res.end - crashk_res.start + 1,
- BOOTMEM_DEFAULT);
-#endif
- device_tree_init();
- sparse_init();
- plat_swiotlb_setup();
- paging_init();
+ add_memory_region(mem, size, type);
}
#ifdef CONFIG_KEXEC
@@ -571,7 +583,7 @@ static void __init mips_parse_crashkernel(void)
return;
crashk_res.start = crash_base;
- crashk_res.end = crash_base + crash_size - 1;
+ crashk_res.end = crash_base + crash_size - 1;
}
static void __init request_crashkernel(struct resource *res)
@@ -582,10 +594,10 @@ static void __init request_crashkernel(struct resource *res)
if (!ret)
pr_info("Reserving %ldMB of memory at %ldMB for crashkernel\n",
(unsigned long)((crashk_res.end -
- crashk_res.start + 1) >> 20),
+ crashk_res.start + 1) >> 20),
(unsigned long)(crashk_res.start >> 20));
}
-#else /* !defined(CONFIG_KEXEC) */
+#else /* !defined(CONFIG_KEXEC) */
static void __init mips_parse_crashkernel(void)
{
}
@@ -595,6 +607,76 @@ static void __init request_crashkernel(struct resource *res)
}
#endif /* !defined(CONFIG_KEXEC) */
+static void __init arch_mem_init(char **cmdline_p)
+{
+ extern void plat_mem_setup(void);
+
+ /* call board setup routine */
+ plat_mem_setup();
+
+ /*
+ * Make sure all kernel memory is in the maps. The "UP" and
+ * "DOWN" are opposite for initdata since if it crosses over
+ * into another memory section you don't want that to be
+ * freed when the initdata is freed.
+ */
+ arch_mem_addpart(PFN_DOWN(__pa_symbol(&_text)) << PAGE_SHIFT,
+ PFN_UP(__pa_symbol(&_edata)) << PAGE_SHIFT,
+ BOOT_MEM_RAM);
+ arch_mem_addpart(PFN_UP(__pa_symbol(&__init_begin)) << PAGE_SHIFT,
+ PFN_DOWN(__pa_symbol(&__init_end)) << PAGE_SHIFT,
+ BOOT_MEM_INIT_RAM);
+
+ pr_info("Determined physical RAM map:\n");
+ print_memory_map();
+
+#ifdef CONFIG_CMDLINE_BOOL
+#ifdef CONFIG_CMDLINE_OVERRIDE
+ strlcpy(boot_command_line, builtin_cmdline, COMMAND_LINE_SIZE);
+#else
+ if (builtin_cmdline[0]) {
+ strlcat(arcs_cmdline, " ", COMMAND_LINE_SIZE);
+ strlcat(arcs_cmdline, builtin_cmdline, COMMAND_LINE_SIZE);
+ }
+ strlcpy(boot_command_line, arcs_cmdline, COMMAND_LINE_SIZE);
+#endif
+#else
+ strlcpy(boot_command_line, arcs_cmdline, COMMAND_LINE_SIZE);
+#endif
+ strlcpy(command_line, boot_command_line, COMMAND_LINE_SIZE);
+
+ *cmdline_p = command_line;
+
+ parse_early_param();
+
+ if (usermem) {
+ pr_info("User-defined physical RAM map:\n");
+ print_memory_map();
+ }
+
+ bootmem_init();
+#ifdef CONFIG_PROC_VMCORE
+ if (setup_elfcorehdr && setup_elfcorehdr_size) {
+ printk(KERN_INFO "kdump reserved memory at %lx-%lx\n",
+ setup_elfcorehdr, setup_elfcorehdr_size);
+ reserve_bootmem(setup_elfcorehdr, setup_elfcorehdr_size,
+ BOOTMEM_DEFAULT);
+ }
+#endif
+
+ mips_parse_crashkernel();
+#ifdef CONFIG_KEXEC
+ if (crashk_res.start != crashk_res.end)
+ reserve_bootmem(crashk_res.start,
+ crashk_res.end - crashk_res.start + 1,
+ BOOTMEM_DEFAULT);
+#endif
+ device_tree_init();
+ sparse_init();
+ plat_swiotlb_setup();
+ paging_init();
+}
+
static void __init resource_init(void)
{
int i;
@@ -607,11 +689,6 @@ static void __init resource_init(void)
data_resource.start = __pa_symbol(&_etext);
data_resource.end = __pa_symbol(&_edata) - 1;
- /*
- * Request address space for all standard RAM.
- */
- mips_parse_crashkernel();
-
for (i = 0; i < boot_mem_map.nr_map; i++) {
struct resource *res;
unsigned long start, end;