diff options
author | Benjamin Herrenschmidt <benh@kernel.crashing.org> | 2013-07-01 18:13:52 -0400 |
---|---|---|
committer | Benjamin Herrenschmidt <benh@kernel.crashing.org> | 2013-07-01 18:20:49 -0400 |
commit | c039e3a8ddd52139d0f81711ecd757772f868b22 (patch) | |
tree | 4ea9107e32db9a648aa0c3b1750672355ad7eb87 /arch | |
parent | e2a800beaca1f580945773e57d1a0e7cd37b1056 (diff) |
powerpc: Handle both new style and old style reserve maps
When Jeremy introduced the new device-tree based reserve map, he made
the code in early_reserve_mem_dt() bail out if it found one, thus not
reserving the initrd nor processing the old style map.
I hit problems with variants of kexec that didn't put the initrd in
the new style map either. While these could/will be fixed, I believe
we should be safe here and rather reserve more than not enough.
We could have a firmware passing stuff via the new style map, and
in the middle, a kexec that knows nothing about it and adding other
things to the old style map.
I don't see a big issue with processing both and reserving everything
that needs to be. memblock_reserve() supports overlaps fine these days.
Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Diffstat (limited to 'arch')
-rw-r--r-- | arch/powerpc/kernel/prom.c | 31 |
1 files changed, 17 insertions, 14 deletions
diff --git a/arch/powerpc/kernel/prom.c b/arch/powerpc/kernel/prom.c index 9c753bc9885d..eb23ac92abb9 100644 --- a/arch/powerpc/kernel/prom.c +++ b/arch/powerpc/kernel/prom.c | |||
@@ -559,7 +559,7 @@ void __init early_init_dt_setup_initrd_arch(unsigned long start, | |||
559 | } | 559 | } |
560 | #endif | 560 | #endif |
561 | 561 | ||
562 | static bool __init early_reserve_mem_dt(void) | 562 | static void __init early_reserve_mem_dt(void) |
563 | { | 563 | { |
564 | unsigned long i, len, dt_root; | 564 | unsigned long i, len, dt_root; |
565 | const __be32 *prop; | 565 | const __be32 *prop; |
@@ -569,7 +569,9 @@ static bool __init early_reserve_mem_dt(void) | |||
569 | prop = of_get_flat_dt_prop(dt_root, "reserved-ranges", &len); | 569 | prop = of_get_flat_dt_prop(dt_root, "reserved-ranges", &len); |
570 | 570 | ||
571 | if (!prop) | 571 | if (!prop) |
572 | return false; | 572 | return; |
573 | |||
574 | DBG("Found new-style reserved-ranges\n"); | ||
573 | 575 | ||
574 | /* Each reserved range is an (address,size) pair, 2 cells each, | 576 | /* Each reserved range is an (address,size) pair, 2 cells each, |
575 | * totalling 4 cells per range. */ | 577 | * totalling 4 cells per range. */ |
@@ -579,11 +581,11 @@ static bool __init early_reserve_mem_dt(void) | |||
579 | base = of_read_number(prop + (i * 4) + 0, 2); | 581 | base = of_read_number(prop + (i * 4) + 0, 2); |
580 | size = of_read_number(prop + (i * 4) + 2, 2); | 582 | size = of_read_number(prop + (i * 4) + 2, 2); |
581 | 583 | ||
582 | if (size) | 584 | if (size) { |
585 | DBG("reserving: %llx -> %llx\n", base, size); | ||
583 | memblock_reserve(base, size); | 586 | memblock_reserve(base, size); |
587 | } | ||
584 | } | 588 | } |
585 | |||
586 | return true; | ||
587 | } | 589 | } |
588 | 590 | ||
589 | static void __init early_reserve_mem(void) | 591 | static void __init early_reserve_mem(void) |
@@ -601,20 +603,16 @@ static void __init early_reserve_mem(void) | |||
601 | self_size = initial_boot_params->totalsize; | 603 | self_size = initial_boot_params->totalsize; |
602 | memblock_reserve(self_base, self_size); | 604 | memblock_reserve(self_base, self_size); |
603 | 605 | ||
604 | /* | 606 | /* Look for the new "reserved-regions" property in the DT */ |
605 | * Try looking for reserved-regions property in the DT first; if | 607 | early_reserve_mem_dt(); |
606 | * it's present, it'll contain all of the necessary reservation | ||
607 | * info | ||
608 | */ | ||
609 | if (early_reserve_mem_dt()) | ||
610 | return; | ||
611 | 608 | ||
612 | #ifdef CONFIG_BLK_DEV_INITRD | 609 | #ifdef CONFIG_BLK_DEV_INITRD |
613 | /* then reserve the initrd, if any */ | 610 | /* Then reserve the initrd, if any */ |
614 | if (initrd_start && (initrd_end > initrd_start)) | 611 | if (initrd_start && (initrd_end > initrd_start)) { |
615 | memblock_reserve(_ALIGN_DOWN(__pa(initrd_start), PAGE_SIZE), | 612 | memblock_reserve(_ALIGN_DOWN(__pa(initrd_start), PAGE_SIZE), |
616 | _ALIGN_UP(initrd_end, PAGE_SIZE) - | 613 | _ALIGN_UP(initrd_end, PAGE_SIZE) - |
617 | _ALIGN_DOWN(initrd_start, PAGE_SIZE)); | 614 | _ALIGN_DOWN(initrd_start, PAGE_SIZE)); |
615 | } | ||
618 | #endif /* CONFIG_BLK_DEV_INITRD */ | 616 | #endif /* CONFIG_BLK_DEV_INITRD */ |
619 | 617 | ||
620 | #ifdef CONFIG_PPC32 | 618 | #ifdef CONFIG_PPC32 |
@@ -626,6 +624,8 @@ static void __init early_reserve_mem(void) | |||
626 | u32 base_32, size_32; | 624 | u32 base_32, size_32; |
627 | u32 *reserve_map_32 = (u32 *)reserve_map; | 625 | u32 *reserve_map_32 = (u32 *)reserve_map; |
628 | 626 | ||
627 | DBG("Found old 32-bit reserve map\n"); | ||
628 | |||
629 | while (1) { | 629 | while (1) { |
630 | base_32 = *(reserve_map_32++); | 630 | base_32 = *(reserve_map_32++); |
631 | size_32 = *(reserve_map_32++); | 631 | size_32 = *(reserve_map_32++); |
@@ -640,6 +640,9 @@ static void __init early_reserve_mem(void) | |||
640 | return; | 640 | return; |
641 | } | 641 | } |
642 | #endif | 642 | #endif |
643 | DBG("Processing reserve map\n"); | ||
644 | |||
645 | /* Handle the reserve map in the fdt blob if it exists */ | ||
643 | while (1) { | 646 | while (1) { |
644 | base = *(reserve_map++); | 647 | base = *(reserve_map++); |
645 | size = *(reserve_map++); | 648 | size = *(reserve_map++); |