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.c89
1 files changed, 47 insertions, 42 deletions
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 */