diff options
Diffstat (limited to 'arch/mips/kernel/setup.c')
| -rw-r--r-- | arch/mips/kernel/setup.c | 123 | 
1 files changed, 97 insertions, 26 deletions
diff --git a/arch/mips/kernel/setup.c b/arch/mips/kernel/setup.c index 8c41187801c..c7f90519e58 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; @@ -449,7 +471,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 +491,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,34 +502,75 @@ 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) +{ +	int i; + +	setup_elfcorehdr = memparse(p, &p); + +	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 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 + +static void __init arch_mem_addpart(phys_t mem, phys_t end, int type)  { -	phys_t init_mem, init_end, init_size; +	phys_t size; +	int i; +	size = end - mem; +	if (!size) +		return; + +	/* 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; +	} +	add_memory_region(mem, size, type); +} + +static void __init arch_mem_init(char **cmdline_p) +{  	extern void plat_mem_setup(void);  	/* call board setup routine */  	plat_mem_setup(); -	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; -			} -		} -		if (!found) -			add_memory_region(init_mem, init_size, -					  BOOT_MEM_INIT_RAM); -	} +	/* +	 * 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(); @@ -537,6 +600,14 @@ static void __init arch_mem_init(char **cmdline_p)  	}  	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  #ifdef CONFIG_KEXEC  	if (crashk_res.start != crashk_res.end)  		reserve_bootmem(crashk_res.start, @@ -571,7 +642,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) @@ -585,7 +656,7 @@ static void __init request_crashkernel(struct resource *res)  				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)  {  }  |