summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMichael Ellerman <michael@ellerman.id.au>2006-02-03 19:05:47 +1100
committerPaul Mackerras <paulus@samba.org>2006-02-07 21:32:44 +1100
commitb68239ee746760bd99a68692f4c97a28f08a5d01 (patch)
tree716746e0faca1db7691f53c8d85ae72bddc5d001
parentb4fd884a037c791a39f2f03da719e251af176a97 (diff)
downloadlinux-b68239ee746760bd99a68692f4c97a28f08a5d01.tar.gz
linux-b68239ee746760bd99a68692f4c97a28f08a5d01.tar.bz2
linux-b68239ee746760bd99a68692f4c97a28f08a5d01.zip
[PATCH] powerpc: Don't overwrite flat device tree with kdump kernel
It's possible for prom_init to allocate the flat device tree inside the kdump crash kernel region. If this happens, when we load the kdump kernel we overwrite the flattened device tree, which is bad. We could make prom_init try and avoid allocating inside the crash kernel region, but then we run into issues if the crash kernel region uses all the space inside the RMO. The easiest solution is to move the flat device tree once we're running in the kernel. Signed-off-by: Michael Ellerman <michael@ellerman.id.au> Signed-off-by: Paul Mackerras <paulus@samba.org>
-rw-r--r--arch/powerpc/kernel/prom.c27
-rw-r--r--arch/powerpc/kernel/setup_64.c3
-rw-r--r--include/asm-powerpc/prom.h2
3 files changed, 32 insertions, 0 deletions
diff --git a/arch/powerpc/kernel/prom.c b/arch/powerpc/kernel/prom.c
index 535a33e4aa37..2b062853bcc7 100644
--- a/arch/powerpc/kernel/prom.c
+++ b/arch/powerpc/kernel/prom.c
@@ -1922,3 +1922,30 @@ int prom_update_property(struct device_node *np,
return 0;
}
+
+#ifdef CONFIG_KEXEC
+/* We may have allocated the flat device tree inside the crash kernel region
+ * in prom_init. If so we need to move it out into regular memory. */
+void kdump_move_device_tree(void)
+{
+ unsigned long start, end;
+ struct boot_param_header *new;
+
+ start = __pa((unsigned long)initial_boot_params);
+ end = start + initial_boot_params->totalsize;
+
+ if (end < crashk_res.start || start > crashk_res.end)
+ return;
+
+ new = (struct boot_param_header*)
+ __va(lmb_alloc(initial_boot_params->totalsize, PAGE_SIZE));
+
+ memcpy(new, initial_boot_params, initial_boot_params->totalsize);
+
+ initial_boot_params = new;
+
+ DBG("Flat device tree blob moved to %p\n", initial_boot_params);
+
+ /* XXX should we unreserve the old DT? */
+}
+#endif /* CONFIG_KEXEC */
diff --git a/arch/powerpc/kernel/setup_64.c b/arch/powerpc/kernel/setup_64.c
index e29b275e09e0..a717dff695ef 100644
--- a/arch/powerpc/kernel/setup_64.c
+++ b/arch/powerpc/kernel/setup_64.c
@@ -398,6 +398,9 @@ void __init setup_system(void)
{
DBG(" -> setup_system()\n");
+#ifdef CONFIG_KEXEC
+ kdump_move_device_tree();
+#endif
/*
* Unflatten the device-tree passed by prom_init or kexec
*/
diff --git a/include/asm-powerpc/prom.h b/include/asm-powerpc/prom.h
index 5b2bd4eefb01..cbd297f44cce 100644
--- a/include/asm-powerpc/prom.h
+++ b/include/asm-powerpc/prom.h
@@ -222,5 +222,7 @@ extern int of_address_to_resource(struct device_node *dev, int index,
extern int of_pci_address_to_resource(struct device_node *dev, int bar,
struct resource *r);
+extern void kdump_move_device_tree(void);
+
#endif /* __KERNEL__ */
#endif /* _POWERPC_PROM_H */