aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc/kernel/prom.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/powerpc/kernel/prom.c')
-rw-r--r--arch/powerpc/kernel/prom.c145
1 files changed, 107 insertions, 38 deletions
diff --git a/arch/powerpc/kernel/prom.c b/arch/powerpc/kernel/prom.c
index 9a07f97f0712..483455c5bb02 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
@@ -911,7 +948,10 @@ static struct ibm_pa_feature {
911 {CPU_FTR_CTRL, 0, 0, 3, 0}, 948 {CPU_FTR_CTRL, 0, 0, 3, 0},
912 {CPU_FTR_NOEXECUTE, 0, 0, 6, 0}, 949 {CPU_FTR_NOEXECUTE, 0, 0, 6, 0},
913 {CPU_FTR_NODSISRALIGN, 0, 1, 1, 1}, 950 {CPU_FTR_NODSISRALIGN, 0, 1, 1, 1},
951#if 0
952 /* put this back once we know how to test if firmware does 64k IO */
914 {CPU_FTR_CI_LARGE_PAGE, 0, 1, 2, 0}, 953 {CPU_FTR_CI_LARGE_PAGE, 0, 1, 2, 0},
954#endif
915}; 955};
916 956
917static void __init check_cpu_pa_features(unsigned long node) 957static void __init check_cpu_pa_features(unsigned long node)
@@ -1070,6 +1110,7 @@ static int __init early_init_dt_scan_chosen(unsigned long node,
1070 iommu_force_on = 1; 1110 iommu_force_on = 1;
1071#endif 1111#endif
1072 1112
1113 /* mem=x on the command line is the preferred mechanism */
1073 lprop = of_get_flat_dt_prop(node, "linux,memory-limit", NULL); 1114 lprop = of_get_flat_dt_prop(node, "linux,memory-limit", NULL);
1074 if (lprop) 1115 if (lprop)
1075 memory_limit = *lprop; 1116 memory_limit = *lprop;
@@ -1123,17 +1164,6 @@ static int __init early_init_dt_scan_chosen(unsigned long node,
1123 1164
1124 DBG("Command line is: %s\n", cmd_line); 1165 DBG("Command line is: %s\n", cmd_line);
1125 1166
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 */ 1167 /* break now */
1138 return 1; 1168 return 1;
1139} 1169}
@@ -1237,9 +1267,17 @@ static void __init early_reserve_mem(void)
1237{ 1267{
1238 u64 base, size; 1268 u64 base, size;
1239 u64 *reserve_map; 1269 u64 *reserve_map;
1270 unsigned long self_base;
1271 unsigned long self_size;
1240 1272
1241 reserve_map = (u64 *)(((unsigned long)initial_boot_params) + 1273 reserve_map = (u64 *)(((unsigned long)initial_boot_params) +
1242 initial_boot_params->off_mem_rsvmap); 1274 initial_boot_params->off_mem_rsvmap);
1275
1276 /* before we do anything, lets reserve the dt blob */
1277 self_base = __pa((unsigned long)initial_boot_params);
1278 self_size = initial_boot_params->totalsize;
1279 lmb_reserve(self_base, self_size);
1280
1243#ifdef CONFIG_PPC32 1281#ifdef CONFIG_PPC32
1244 /* 1282 /*
1245 * Handle the case where we might be booting from an old kexec 1283 * Handle the case where we might be booting from an old kexec
@@ -1254,6 +1292,9 @@ static void __init early_reserve_mem(void)
1254 size_32 = *(reserve_map_32++); 1292 size_32 = *(reserve_map_32++);
1255 if (size_32 == 0) 1293 if (size_32 == 0)
1256 break; 1294 break;
1295 /* skip if the reservation is for the blob */
1296 if (base_32 == self_base && size_32 == self_size)
1297 continue;
1257 DBG("reserving: %x -> %x\n", base_32, size_32); 1298 DBG("reserving: %x -> %x\n", base_32, size_32);
1258 lmb_reserve(base_32, size_32); 1299 lmb_reserve(base_32, size_32);
1259 } 1300 }
@@ -1265,6 +1306,9 @@ static void __init early_reserve_mem(void)
1265 size = *(reserve_map++); 1306 size = *(reserve_map++);
1266 if (size == 0) 1307 if (size == 0)
1267 break; 1308 break;
1309 /* skip if the reservation is for the blob */
1310 if (base == self_base && size == self_size)
1311 continue;
1268 DBG("reserving: %llx -> %llx\n", base, size); 1312 DBG("reserving: %llx -> %llx\n", base, size);
1269 lmb_reserve(base, size); 1313 lmb_reserve(base, size);
1270 } 1314 }
@@ -1292,18 +1336,26 @@ void __init early_init_devtree(void *params)
1292 lmb_init(); 1336 lmb_init();
1293 of_scan_flat_dt(early_init_dt_scan_root, NULL); 1337 of_scan_flat_dt(early_init_dt_scan_root, NULL);
1294 of_scan_flat_dt(early_init_dt_scan_memory, NULL); 1338 of_scan_flat_dt(early_init_dt_scan_memory, NULL);
1295 lmb_enforce_memory_limit(memory_limit);
1296 lmb_analyze();
1297 1339
1298 DBG("Phys. mem: %lx\n", lmb_phys_mem_size()); 1340 /* Save command line for /proc/cmdline and then parse parameters */
1341 strlcpy(saved_command_line, cmd_line, COMMAND_LINE_SIZE);
1342 parse_early_param();
1299 1343
1300 /* Reserve LMB regions used by kernel, initrd, dt, etc... */ 1344 /* Reserve LMB regions used by kernel, initrd, dt, etc... */
1301 lmb_reserve(PHYSICAL_START, __pa(klimit) - PHYSICAL_START); 1345 lmb_reserve(PHYSICAL_START, __pa(klimit) - PHYSICAL_START);
1302#ifdef CONFIG_CRASH_DUMP 1346 reserve_kdump_trampoline();
1303 lmb_reserve(0, KDUMP_RESERVE_LIMIT); 1347 reserve_crashkernel();
1304#endif
1305 early_reserve_mem(); 1348 early_reserve_mem();
1306 1349
1350 lmb_enforce_memory_limit(memory_limit);
1351 lmb_analyze();
1352
1353 DBG("Phys. mem: %lx\n", lmb_phys_mem_size());
1354
1355 /* We may need to relocate the flat tree, do it now.
1356 * FIXME .. and the initrd too? */
1357 move_device_tree();
1358
1307 DBG("Scanning CPUs ...\n"); 1359 DBG("Scanning CPUs ...\n");
1308 1360
1309 /* Retreive CPU related informations from the flat tree 1361 /* Retreive CPU related informations from the flat tree
@@ -2053,29 +2105,46 @@ int prom_update_property(struct device_node *np,
2053 return 0; 2105 return 0;
2054} 2106}
2055 2107
2056#ifdef CONFIG_KEXEC
2057/* We may have allocated the flat device tree inside the crash kernel region
2058 * in prom_init. If so we need to move it out into regular memory. */
2059void kdump_move_device_tree(void)
2060{
2061 unsigned long start, end;
2062 struct boot_param_header *new;
2063
2064 start = __pa((unsigned long)initial_boot_params);
2065 end = start + initial_boot_params->totalsize;
2066
2067 if (end < crashk_res.start || start > crashk_res.end)
2068 return;
2069 2108
2070 new = (struct boot_param_header*) 2109/* Find the device node for a given logical cpu number, also returns the cpu
2071 __va(lmb_alloc(initial_boot_params->totalsize, PAGE_SIZE)); 2110 * local thread number (index in ibm,interrupt-server#s) if relevant and
2072 2111 * asked for (non NULL)
2073 memcpy(new, initial_boot_params, initial_boot_params->totalsize); 2112 */
2113struct device_node *of_get_cpu_node(int cpu, unsigned int *thread)
2114{
2115 int hardid;
2116 struct device_node *np;
2074 2117
2075 initial_boot_params = new; 2118 hardid = get_hard_smp_processor_id(cpu);
2076 2119
2077 DBG("Flat device tree blob moved to %p\n", initial_boot_params); 2120 for_each_node_by_type(np, "cpu") {
2121 u32 *intserv;
2122 unsigned int plen, t;
2078 2123
2079 /* XXX should we unreserve the old DT? */ 2124 /* Check for ibm,ppc-interrupt-server#s. If it doesn't exist
2125 * fallback to "reg" property and assume no threads
2126 */
2127 intserv = (u32 *)get_property(np, "ibm,ppc-interrupt-server#s",
2128 &plen);
2129 if (intserv == NULL) {
2130 u32 *reg = (u32 *)get_property(np, "reg", NULL);
2131 if (reg == NULL)
2132 continue;
2133 if (*reg == hardid) {
2134 if (thread)
2135 *thread = 0;
2136 return np;
2137 }
2138 } else {
2139 plen /= sizeof(u32);
2140 for (t = 0; t < plen; t++) {
2141 if (hardid == intserv[t]) {
2142 if (thread)
2143 *thread = t;
2144 return np;
2145 }
2146 }
2147 }
2148 }
2149 return NULL;
2080} 2150}
2081#endif /* CONFIG_KEXEC */