aboutsummaryrefslogtreecommitdiffstats
path: root/arch
diff options
context:
space:
mode:
authorDavid Daney <ddaney@caviumnetworks.com>2011-11-22 09:38:03 -0500
committerRalf Baechle <ralf@linux-mips.org>2011-12-07 17:03:45 -0500
commit43064c0c8ee2ada8edd421520c633584d648e100 (patch)
tree3621ac70a6d96a872942c205f03f9fda18826588 /arch
parentb1c10bea620f79109b5cc9935267bea4f6f29ac6 (diff)
MIPS: Handle initmem in systems with kernel not in add_memory_region() mem
This patch addresses a couple of related problems: 1) The kernel may reside in physical memory outside of the ranges set by plat_mem_setup(). If this is the case, init mem cannot be reused as it resides outside of the range of pages that the kernel memory allocators control. 2) initrd images might be loaded in physical memory outside of the ranges set by plat_mem_setup(). The memory likewise cannot be reused. The patch doesn't handle this specific case, but the infrastructure is useful for future patches that do. The crux of the problem is that there are memory regions that need be memory_present(), but that cannot be free_bootmem() at the time of arch_mem_init(). We create a new type of memory (BOOT_MEM_INIT_RAM) for use with add_memory_region(). Then arch_mem_init() adds the init mem with this type if the init mem is not already covered by existing ranges. When memory is being freed into the bootmem allocator, we skip the BOOT_MEM_INIT_RAM ranges so they are not clobbered, but we do signal them as memory_present(). This way when they are later freed, the necessary memory manager structures have initialized and the Sparse allocater is prevented from crashing. The Octeon specific code that handled this case is removed, because the new general purpose code handles the case. Signed-off-by: David Daney <ddaney@caviumnetworks.com> To: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/1988/ Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
Diffstat (limited to 'arch')
-rw-r--r--arch/mips/cavium-octeon/setup.c8
-rw-r--r--arch/mips/include/asm/bootinfo.h1
-rw-r--r--arch/mips/kernel/setup.c43
-rw-r--r--arch/mips/mm/init.c9
4 files changed, 47 insertions, 14 deletions
diff --git a/arch/mips/cavium-octeon/setup.c b/arch/mips/cavium-octeon/setup.c
index 2d9028f1474c..b394552e5ca0 100644
--- a/arch/mips/cavium-octeon/setup.c
+++ b/arch/mips/cavium-octeon/setup.c
@@ -642,14 +642,6 @@ void __init plat_mem_setup(void)
642 642
643 total = 0; 643 total = 0;
644 644
645 /* First add the init memory we will be returning. */
646 memory = __pa_symbol(&__init_begin) & PAGE_MASK;
647 mem_alloc_size = (__pa_symbol(&__init_end) & PAGE_MASK) - memory;
648 if (mem_alloc_size > 0) {
649 add_memory_region(memory, mem_alloc_size, BOOT_MEM_RAM);
650 total += mem_alloc_size;
651 }
652
653 /* 645 /*
654 * The Mips memory init uses the first memory location for 646 * The Mips memory init uses the first memory location for
655 * some memory vectors. When SPARSEMEM is in use, it doesn't 647 * some memory vectors. When SPARSEMEM is in use, it doesn't
diff --git a/arch/mips/include/asm/bootinfo.h b/arch/mips/include/asm/bootinfo.h
index 35cd1bab69c3..7a51d879e6ca 100644
--- a/arch/mips/include/asm/bootinfo.h
+++ b/arch/mips/include/asm/bootinfo.h
@@ -86,6 +86,7 @@ extern unsigned long mips_machtype;
86#define BOOT_MEM_RAM 1 86#define BOOT_MEM_RAM 1
87#define BOOT_MEM_ROM_DATA 2 87#define BOOT_MEM_ROM_DATA 2
88#define BOOT_MEM_RESERVED 3 88#define BOOT_MEM_RESERVED 3
89#define BOOT_MEM_INIT_RAM 4
89 90
90/* 91/*
91 * A memory map that's built upon what was determined 92 * A memory map that's built upon what was determined
diff --git a/arch/mips/kernel/setup.c b/arch/mips/kernel/setup.c
index 84af26ab2212..e86c2cf554aa 100644
--- a/arch/mips/kernel/setup.c
+++ b/arch/mips/kernel/setup.c
@@ -121,6 +121,9 @@ static void __init print_memory_map(void)
121 case BOOT_MEM_RAM: 121 case BOOT_MEM_RAM:
122 printk(KERN_CONT "(usable)\n"); 122 printk(KERN_CONT "(usable)\n");
123 break; 123 break;
124 case BOOT_MEM_INIT_RAM:
125 printk(KERN_CONT "(usable after init)\n");
126 break;
124 case BOOT_MEM_ROM_DATA: 127 case BOOT_MEM_ROM_DATA:
125 printk(KERN_CONT "(ROM data)\n"); 128 printk(KERN_CONT "(ROM data)\n");
126 break; 129 break;
@@ -361,15 +364,24 @@ static void __init bootmem_init(void)
361 for (i = 0; i < boot_mem_map.nr_map; i++) { 364 for (i = 0; i < boot_mem_map.nr_map; i++) {
362 unsigned long start, end, size; 365 unsigned long start, end, size;
363 366
367 start = PFN_UP(boot_mem_map.map[i].addr);
368 end = PFN_DOWN(boot_mem_map.map[i].addr
369 + boot_mem_map.map[i].size);
370
364 /* 371 /*
365 * Reserve usable memory. 372 * Reserve usable memory.
366 */ 373 */
367 if (boot_mem_map.map[i].type != BOOT_MEM_RAM) 374 switch (boot_mem_map.map[i].type) {
375 case BOOT_MEM_RAM:
376 break;
377 case BOOT_MEM_INIT_RAM:
378 memory_present(0, start, end);
368 continue; 379 continue;
380 default:
381 /* Not usable memory */
382 continue;
383 }
369 384
370 start = PFN_UP(boot_mem_map.map[i].addr);
371 end = PFN_DOWN(boot_mem_map.map[i].addr
372 + boot_mem_map.map[i].size);
373 /* 385 /*
374 * We are rounding up the start address of usable memory 386 * We are rounding up the start address of usable memory
375 * and at the end of the usable range downwards. 387 * and at the end of the usable range downwards.
@@ -455,11 +467,33 @@ early_param("mem", early_parse_mem);
455 467
456static void __init arch_mem_init(char **cmdline_p) 468static void __init arch_mem_init(char **cmdline_p)
457{ 469{
470 phys_t init_mem, init_end, init_size;
471
458 extern void plat_mem_setup(void); 472 extern void plat_mem_setup(void);
459 473
460 /* call board setup routine */ 474 /* call board setup routine */
461 plat_mem_setup(); 475 plat_mem_setup();
462 476
477 init_mem = PFN_UP(__pa_symbol(&__init_begin)) << PAGE_SHIFT;
478 init_end = PFN_DOWN(__pa_symbol(&__init_end)) << PAGE_SHIFT;
479 init_size = init_end - init_mem;
480 if (init_size) {
481 /* Make sure it is in the boot_mem_map */
482 int i, found;
483 found = 0;
484 for (i = 0; i < boot_mem_map.nr_map; i++) {
485 if (init_mem >= boot_mem_map.map[i].addr &&
486 init_mem < (boot_mem_map.map[i].addr +
487 boot_mem_map.map[i].size)) {
488 found = 1;
489 break;
490 }
491 }
492 if (!found)
493 add_memory_region(init_mem, init_size,
494 BOOT_MEM_INIT_RAM);
495 }
496
463 pr_info("Determined physical RAM map:\n"); 497 pr_info("Determined physical RAM map:\n");
464 print_memory_map(); 498 print_memory_map();
465 499
@@ -523,6 +557,7 @@ static void __init resource_init(void)
523 res = alloc_bootmem(sizeof(struct resource)); 557 res = alloc_bootmem(sizeof(struct resource));
524 switch (boot_mem_map.map[i].type) { 558 switch (boot_mem_map.map[i].type) {
525 case BOOT_MEM_RAM: 559 case BOOT_MEM_RAM:
560 case BOOT_MEM_INIT_RAM:
526 case BOOT_MEM_ROM_DATA: 561 case BOOT_MEM_ROM_DATA:
527 res->name = "System RAM"; 562 res->name = "System RAM";
528 break; 563 break;
diff --git a/arch/mips/mm/init.c b/arch/mips/mm/init.c
index b7ebc4fa89bc..3b3ffd439cd7 100644
--- a/arch/mips/mm/init.c
+++ b/arch/mips/mm/init.c
@@ -304,9 +304,14 @@ int page_is_ram(unsigned long pagenr)
304 for (i = 0; i < boot_mem_map.nr_map; i++) { 304 for (i = 0; i < boot_mem_map.nr_map; i++) {
305 unsigned long addr, end; 305 unsigned long addr, end;
306 306
307 if (boot_mem_map.map[i].type != BOOT_MEM_RAM) 307 switch (boot_mem_map.map[i].type) {
308 case BOOT_MEM_RAM:
309 case BOOT_MEM_INIT_RAM:
310 break;
311 default:
308 /* not usable memory */ 312 /* not usable memory */
309 continue; 313 continue;
314 }
310 315
311 addr = PFN_UP(boot_mem_map.map[i].addr); 316 addr = PFN_UP(boot_mem_map.map[i].addr);
312 end = PFN_DOWN(boot_mem_map.map[i].addr + 317 end = PFN_DOWN(boot_mem_map.map[i].addr +
@@ -379,7 +384,7 @@ void __init mem_init(void)
379 384
380 reservedpages = ram = 0; 385 reservedpages = ram = 0;
381 for (tmp = 0; tmp < max_low_pfn; tmp++) 386 for (tmp = 0; tmp < max_low_pfn; tmp++)
382 if (page_is_ram(tmp)) { 387 if (page_is_ram(tmp) && pfn_valid(tmp)) {
383 ram++; 388 ram++;
384 if (PageReserved(pfn_to_page(tmp))) 389 if (PageReserved(pfn_to_page(tmp)))
385 reservedpages++; 390 reservedpages++;