diff options
Diffstat (limited to 'arch/powerpc/kernel/prom.c')
-rw-r--r-- | arch/powerpc/kernel/prom.c | 43 |
1 files changed, 37 insertions, 6 deletions
diff --git a/arch/powerpc/kernel/prom.c b/arch/powerpc/kernel/prom.c index 87d83c56b31e..3a2dc7e6586a 100644 --- a/arch/powerpc/kernel/prom.c +++ b/arch/powerpc/kernel/prom.c | |||
@@ -888,9 +888,10 @@ static u64 __init dt_mem_next_cell(int s, cell_t **cellp) | |||
888 | */ | 888 | */ |
889 | static int __init early_init_dt_scan_drconf_memory(unsigned long node) | 889 | static int __init early_init_dt_scan_drconf_memory(unsigned long node) |
890 | { | 890 | { |
891 | cell_t *dm, *ls; | 891 | cell_t *dm, *ls, *usm; |
892 | unsigned long l, n, flags; | 892 | unsigned long l, n, flags; |
893 | u64 base, size, lmb_size; | 893 | u64 base, size, lmb_size; |
894 | unsigned int is_kexec_kdump = 0, rngs; | ||
894 | 895 | ||
895 | ls = (cell_t *)of_get_flat_dt_prop(node, "ibm,lmb-size", &l); | 896 | ls = (cell_t *)of_get_flat_dt_prop(node, "ibm,lmb-size", &l); |
896 | if (ls == NULL || l < dt_root_size_cells * sizeof(cell_t)) | 897 | if (ls == NULL || l < dt_root_size_cells * sizeof(cell_t)) |
@@ -905,6 +906,12 @@ static int __init early_init_dt_scan_drconf_memory(unsigned long node) | |||
905 | if (l < (n * (dt_root_addr_cells + 4) + 1) * sizeof(cell_t)) | 906 | if (l < (n * (dt_root_addr_cells + 4) + 1) * sizeof(cell_t)) |
906 | return 0; | 907 | return 0; |
907 | 908 | ||
909 | /* check if this is a kexec/kdump kernel. */ | ||
910 | usm = (cell_t *)of_get_flat_dt_prop(node, "linux,drconf-usable-memory", | ||
911 | &l); | ||
912 | if (usm != NULL) | ||
913 | is_kexec_kdump = 1; | ||
914 | |||
908 | for (; n != 0; --n) { | 915 | for (; n != 0; --n) { |
909 | base = dt_mem_next_cell(dt_root_addr_cells, &dm); | 916 | base = dt_mem_next_cell(dt_root_addr_cells, &dm); |
910 | flags = dm[3]; | 917 | flags = dm[3]; |
@@ -915,13 +922,34 @@ static int __init early_init_dt_scan_drconf_memory(unsigned long node) | |||
915 | if ((flags & 0x80) || !(flags & 0x8)) | 922 | if ((flags & 0x80) || !(flags & 0x8)) |
916 | continue; | 923 | continue; |
917 | size = lmb_size; | 924 | size = lmb_size; |
918 | if (iommu_is_off) { | 925 | rngs = 1; |
919 | if (base >= 0x80000000ul) | 926 | if (is_kexec_kdump) { |
927 | /* | ||
928 | * For each lmb in ibm,dynamic-memory, a corresponding | ||
929 | * entry in linux,drconf-usable-memory property contains | ||
930 | * a counter 'p' followed by 'p' (base, size) duple. | ||
931 | * Now read the counter from | ||
932 | * linux,drconf-usable-memory property | ||
933 | */ | ||
934 | rngs = dt_mem_next_cell(dt_root_size_cells, &usm); | ||
935 | if (!rngs) /* there are no (base, size) duple */ | ||
920 | continue; | 936 | continue; |
921 | if ((base + size) > 0x80000000ul) | ||
922 | size = 0x80000000ul - base; | ||
923 | } | 937 | } |
924 | lmb_add(base, size); | 938 | do { |
939 | if (is_kexec_kdump) { | ||
940 | base = dt_mem_next_cell(dt_root_addr_cells, | ||
941 | &usm); | ||
942 | size = dt_mem_next_cell(dt_root_size_cells, | ||
943 | &usm); | ||
944 | } | ||
945 | if (iommu_is_off) { | ||
946 | if (base >= 0x80000000ul) | ||
947 | continue; | ||
948 | if ((base + size) > 0x80000000ul) | ||
949 | size = 0x80000000ul - base; | ||
950 | } | ||
951 | lmb_add(base, size); | ||
952 | } while (--rngs); | ||
925 | } | 953 | } |
926 | lmb_dump_all(); | 954 | lmb_dump_all(); |
927 | return 0; | 955 | return 0; |
@@ -1164,6 +1192,9 @@ void __init early_init_devtree(void *params) | |||
1164 | 1192 | ||
1165 | /* Reserve LMB regions used by kernel, initrd, dt, etc... */ | 1193 | /* Reserve LMB regions used by kernel, initrd, dt, etc... */ |
1166 | lmb_reserve(PHYSICAL_START, __pa(klimit) - PHYSICAL_START); | 1194 | lmb_reserve(PHYSICAL_START, __pa(klimit) - PHYSICAL_START); |
1195 | /* If relocatable, reserve first 32k for interrupt vectors etc. */ | ||
1196 | if (PHYSICAL_START > MEMORY_START) | ||
1197 | lmb_reserve(MEMORY_START, 0x8000); | ||
1167 | reserve_kdump_trampoline(); | 1198 | reserve_kdump_trampoline(); |
1168 | reserve_crashkernel(); | 1199 | reserve_crashkernel(); |
1169 | early_reserve_mem(); | 1200 | early_reserve_mem(); |