aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc/kernel
diff options
context:
space:
mode:
Diffstat (limited to 'arch/powerpc/kernel')
-rw-r--r--arch/powerpc/kernel/machine_kexec_64.c5
-rw-r--r--arch/powerpc/kernel/prom.c89
-rw-r--r--arch/powerpc/kernel/prom_init.c55
-rw-r--r--arch/powerpc/kernel/setup_64.c3
4 files changed, 57 insertions, 95 deletions
diff --git a/arch/powerpc/kernel/machine_kexec_64.c b/arch/powerpc/kernel/machine_kexec_64.c
index ee166c586642..1ccb188ba40d 100644
--- a/arch/powerpc/kernel/machine_kexec_64.c
+++ b/arch/powerpc/kernel/machine_kexec_64.c
@@ -339,3 +339,8 @@ void __init kexec_setup(void)
339{ 339{
340 export_htab_values(); 340 export_htab_values();
341} 341}
342
343int overlaps_crashkernel(unsigned long start, unsigned long size)
344{
345 return (start + size) > crashk_res.start && start <= crashk_res.end;
346}
diff --git a/arch/powerpc/kernel/prom.c b/arch/powerpc/kernel/prom.c
index 4ca608c9cd72..a04f726d3bab 100644
--- a/arch/powerpc/kernel/prom.c
+++ b/arch/powerpc/kernel/prom.c
@@ -50,6 +50,7 @@
50#include <asm/machdep.h> 50#include <asm/machdep.h>
51#include <asm/pSeries_reconfig.h> 51#include <asm/pSeries_reconfig.h>
52#include <asm/pci-bridge.h> 52#include <asm/pci-bridge.h>
53#include <asm/kexec.h>
53 54
54#ifdef DEBUG 55#ifdef DEBUG
55#define DBG(fmt...) printk(KERN_ERR fmt) 56#define DBG(fmt...) printk(KERN_ERR fmt)
@@ -836,6 +837,42 @@ static unsigned long __init unflatten_dt_node(unsigned long mem,
836 return mem; 837 return mem;
837} 838}
838 839
840static int __init early_parse_mem(char *p)
841{
842 if (!p)
843 return 1;
844
845 memory_limit = PAGE_ALIGN(memparse(p, &p));
846 DBG("memory limit = 0x%lx\n", memory_limit);
847
848 return 0;
849}
850early_param("mem", early_parse_mem);
851
852/*
853 * The device tree may be allocated below our memory limit, or inside the
854 * crash kernel region for kdump. If so, move it out now.
855 */
856static void move_device_tree(void)
857{
858 unsigned long start, size;
859 void *p;
860
861 DBG("-> move_device_tree\n");
862
863 start = __pa(initial_boot_params);
864 size = initial_boot_params->totalsize;
865
866 if ((memory_limit && (start + size) > memory_limit) ||
867 overlaps_crashkernel(start, size)) {
868 p = __va(lmb_alloc_base(size, PAGE_SIZE, lmb.rmo_size));
869 memcpy(p, initial_boot_params, size);
870 initial_boot_params = (struct boot_param_header *)p;
871 DBG("Moved device tree to 0x%p\n", p);
872 }
873
874 DBG("<- move_device_tree\n");
875}
839 876
840/** 877/**
841 * unflattens the device-tree passed by the firmware, creating the 878 * unflattens the device-tree passed by the firmware, creating the
@@ -1070,6 +1107,7 @@ static int __init early_init_dt_scan_chosen(unsigned long node,
1070 iommu_force_on = 1; 1107 iommu_force_on = 1;
1071#endif 1108#endif
1072 1109
1110 /* mem=x on the command line is the preferred mechanism */
1073 lprop = of_get_flat_dt_prop(node, "linux,memory-limit", NULL); 1111 lprop = of_get_flat_dt_prop(node, "linux,memory-limit", NULL);
1074 if (lprop) 1112 if (lprop)
1075 memory_limit = *lprop; 1113 memory_limit = *lprop;
@@ -1123,17 +1161,6 @@ static int __init early_init_dt_scan_chosen(unsigned long node,
1123 1161
1124 DBG("Command line is: %s\n", cmd_line); 1162 DBG("Command line is: %s\n", cmd_line);
1125 1163
1126 if (strstr(cmd_line, "mem=")) {
1127 char *p, *q;
1128
1129 for (q = cmd_line; (p = strstr(q, "mem=")) != 0; ) {
1130 q = p + 4;
1131 if (p > cmd_line && p[-1] != ' ')
1132 continue;
1133 memory_limit = memparse(q, &q);
1134 }
1135 }
1136
1137 /* break now */ 1164 /* break now */
1138 return 1; 1165 return 1;
1139} 1166}
@@ -1297,11 +1324,6 @@ void __init early_init_devtree(void *params)
1297 strlcpy(saved_command_line, cmd_line, COMMAND_LINE_SIZE); 1324 strlcpy(saved_command_line, cmd_line, COMMAND_LINE_SIZE);
1298 parse_early_param(); 1325 parse_early_param();
1299 1326
1300 lmb_enforce_memory_limit(memory_limit);
1301 lmb_analyze();
1302
1303 DBG("Phys. mem: %lx\n", lmb_phys_mem_size());
1304
1305 /* Reserve LMB regions used by kernel, initrd, dt, etc... */ 1327 /* Reserve LMB regions used by kernel, initrd, dt, etc... */
1306 lmb_reserve(PHYSICAL_START, __pa(klimit) - PHYSICAL_START); 1328 lmb_reserve(PHYSICAL_START, __pa(klimit) - PHYSICAL_START);
1307#ifdef CONFIG_CRASH_DUMP 1329#ifdef CONFIG_CRASH_DUMP
@@ -1309,6 +1331,15 @@ void __init early_init_devtree(void *params)
1309#endif 1331#endif
1310 early_reserve_mem(); 1332 early_reserve_mem();
1311 1333
1334 lmb_enforce_memory_limit(memory_limit);
1335 lmb_analyze();
1336
1337 DBG("Phys. mem: %lx\n", lmb_phys_mem_size());
1338
1339 /* We may need to relocate the flat tree, do it now.
1340 * FIXME .. and the initrd too? */
1341 move_device_tree();
1342
1312 DBG("Scanning CPUs ...\n"); 1343 DBG("Scanning CPUs ...\n");
1313 1344
1314 /* Retreive CPU related informations from the flat tree 1345 /* Retreive CPU related informations from the flat tree
@@ -2058,29 +2089,3 @@ int prom_update_property(struct device_node *np,
2058 return 0; 2089 return 0;
2059} 2090}
2060 2091
2061#ifdef CONFIG_KEXEC
2062/* We may have allocated the flat device tree inside the crash kernel region
2063 * in prom_init. If so we need to move it out into regular memory. */
2064void kdump_move_device_tree(void)
2065{
2066 unsigned long start, end;
2067 struct boot_param_header *new;
2068
2069 start = __pa((unsigned long)initial_boot_params);
2070 end = start + initial_boot_params->totalsize;
2071
2072 if (end < crashk_res.start || start > crashk_res.end)
2073 return;
2074
2075 new = (struct boot_param_header*)
2076 __va(lmb_alloc(initial_boot_params->totalsize, PAGE_SIZE));
2077
2078 memcpy(new, initial_boot_params, initial_boot_params->totalsize);
2079
2080 initial_boot_params = new;
2081
2082 DBG("Flat device tree blob moved to %p\n", initial_boot_params);
2083
2084 /* XXX should we unreserve the old DT? */
2085}
2086#endif /* CONFIG_KEXEC */
diff --git a/arch/powerpc/kernel/prom_init.c b/arch/powerpc/kernel/prom_init.c
index 078fb5533541..a52377c68fc6 100644
--- a/arch/powerpc/kernel/prom_init.c
+++ b/arch/powerpc/kernel/prom_init.c
@@ -194,8 +194,6 @@ static int __initdata of_platform;
194 194
195static char __initdata prom_cmd_line[COMMAND_LINE_SIZE]; 195static char __initdata prom_cmd_line[COMMAND_LINE_SIZE];
196 196
197static unsigned long __initdata prom_memory_limit;
198
199static unsigned long __initdata alloc_top; 197static unsigned long __initdata alloc_top;
200static unsigned long __initdata alloc_top_high; 198static unsigned long __initdata alloc_top_high;
201static unsigned long __initdata alloc_bottom; 199static unsigned long __initdata alloc_bottom;
@@ -594,16 +592,6 @@ static void __init early_cmdline_parse(void)
594 } 592 }
595#endif 593#endif
596 594
597 opt = strstr(RELOC(prom_cmd_line), RELOC("mem="));
598 if (opt) {
599 opt += 4;
600 RELOC(prom_memory_limit) = prom_memparse(opt, (const char **)&opt);
601#ifdef CONFIG_PPC64
602 /* Align to 16 MB == size of ppc64 large page */
603 RELOC(prom_memory_limit) = ALIGN(RELOC(prom_memory_limit), 0x1000000);
604#endif
605 }
606
607#ifdef CONFIG_KEXEC 595#ifdef CONFIG_KEXEC
608 /* 596 /*
609 * crashkernel=size@addr specifies the location to reserve for 597 * crashkernel=size@addr specifies the location to reserve for
@@ -1115,29 +1103,6 @@ static void __init prom_init_mem(void)
1115 } 1103 }
1116 1104
1117 /* 1105 /*
1118 * If prom_memory_limit is set we reduce the upper limits *except* for
1119 * alloc_top_high. This must be the real top of RAM so we can put
1120 * TCE's up there.
1121 */
1122
1123 RELOC(alloc_top_high) = RELOC(ram_top);
1124
1125 if (RELOC(prom_memory_limit)) {
1126 if (RELOC(prom_memory_limit) <= RELOC(alloc_bottom)) {
1127 prom_printf("Ignoring mem=%x <= alloc_bottom.\n",
1128 RELOC(prom_memory_limit));
1129 RELOC(prom_memory_limit) = 0;
1130 } else if (RELOC(prom_memory_limit) >= RELOC(ram_top)) {
1131 prom_printf("Ignoring mem=%x >= ram_top.\n",
1132 RELOC(prom_memory_limit));
1133 RELOC(prom_memory_limit) = 0;
1134 } else {
1135 RELOC(ram_top) = RELOC(prom_memory_limit);
1136 RELOC(rmo_top) = min(RELOC(rmo_top), RELOC(prom_memory_limit));
1137 }
1138 }
1139
1140 /*
1141 * Setup our top alloc point, that is top of RMO or top of 1106 * Setup our top alloc point, that is top of RMO or top of
1142 * segment 0 when running non-LPAR. 1107 * segment 0 when running non-LPAR.
1143 * Some RS64 machines have buggy firmware where claims up at 1108 * Some RS64 machines have buggy firmware where claims up at
@@ -1149,9 +1114,9 @@ static void __init prom_init_mem(void)
1149 RELOC(rmo_top) = RELOC(ram_top); 1114 RELOC(rmo_top) = RELOC(ram_top);
1150 RELOC(rmo_top) = min(0x30000000ul, RELOC(rmo_top)); 1115 RELOC(rmo_top) = min(0x30000000ul, RELOC(rmo_top));
1151 RELOC(alloc_top) = RELOC(rmo_top); 1116 RELOC(alloc_top) = RELOC(rmo_top);
1117 RELOC(alloc_top_high) = RELOC(ram_top);
1152 1118
1153 prom_printf("memory layout at init:\n"); 1119 prom_printf("memory layout at init:\n");
1154 prom_printf(" memory_limit : %x (16 MB aligned)\n", RELOC(prom_memory_limit));
1155 prom_printf(" alloc_bottom : %x\n", RELOC(alloc_bottom)); 1120 prom_printf(" alloc_bottom : %x\n", RELOC(alloc_bottom));
1156 prom_printf(" alloc_top : %x\n", RELOC(alloc_top)); 1121 prom_printf(" alloc_top : %x\n", RELOC(alloc_top));
1157 prom_printf(" alloc_top_hi : %x\n", RELOC(alloc_top_high)); 1122 prom_printf(" alloc_top_hi : %x\n", RELOC(alloc_top_high));
@@ -1348,16 +1313,10 @@ static void __init prom_initialize_tce_table(void)
1348 1313
1349 reserve_mem(local_alloc_bottom, local_alloc_top - local_alloc_bottom); 1314 reserve_mem(local_alloc_bottom, local_alloc_top - local_alloc_bottom);
1350 1315
1351 if (RELOC(prom_memory_limit)) { 1316 /* These are only really needed if there is a memory limit in
1352 /* 1317 * effect, but we don't know so export them always. */
1353 * We align the start to a 16MB boundary so we can map 1318 RELOC(prom_tce_alloc_start) = local_alloc_bottom;
1354 * the TCE area using large pages if possible. 1319 RELOC(prom_tce_alloc_end) = local_alloc_top;
1355 * The end should be the top of RAM so no need to align it.
1356 */
1357 RELOC(prom_tce_alloc_start) = _ALIGN_DOWN(local_alloc_bottom,
1358 0x1000000);
1359 RELOC(prom_tce_alloc_end) = local_alloc_top;
1360 }
1361 1320
1362 /* Flag the first invalid entry */ 1321 /* Flag the first invalid entry */
1363 prom_debug("ending prom_initialize_tce_table\n"); 1322 prom_debug("ending prom_initialize_tce_table\n");
@@ -2265,10 +2224,6 @@ unsigned long __init prom_init(unsigned long r3, unsigned long r4,
2265 /* 2224 /*
2266 * Fill in some infos for use by the kernel later on 2225 * Fill in some infos for use by the kernel later on
2267 */ 2226 */
2268 if (RELOC(prom_memory_limit))
2269 prom_setprop(_prom->chosen, "/chosen", "linux,memory-limit",
2270 &RELOC(prom_memory_limit),
2271 sizeof(prom_memory_limit));
2272#ifdef CONFIG_PPC64 2227#ifdef CONFIG_PPC64
2273 if (RELOC(ppc64_iommu_off)) 2228 if (RELOC(ppc64_iommu_off))
2274 prom_setprop(_prom->chosen, "/chosen", "linux,iommu-off", 2229 prom_setprop(_prom->chosen, "/chosen", "linux,iommu-off",
diff --git a/arch/powerpc/kernel/setup_64.c b/arch/powerpc/kernel/setup_64.c
index 6224624c3d38..59773d9044ba 100644
--- a/arch/powerpc/kernel/setup_64.c
+++ b/arch/powerpc/kernel/setup_64.c
@@ -347,9 +347,6 @@ void __init setup_system(void)
347{ 347{
348 DBG(" -> setup_system()\n"); 348 DBG(" -> setup_system()\n");
349 349
350#ifdef CONFIG_KEXEC
351 kdump_move_device_tree();
352#endif
353 /* 350 /*
354 * Unflatten the device-tree passed by prom_init or kexec 351 * Unflatten the device-tree passed by prom_init or kexec
355 */ 352 */