diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2008-12-28 16:54:33 -0800 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2008-12-28 16:54:33 -0800 |
commit | 3c92ec8ae91ecf59d88c798301833d7cf83f2179 (patch) | |
tree | 08a38cd3523c42bd49882f17cd501fd879e7ca1c /arch/powerpc/kernel/machine_kexec.c | |
parent | c4c9f0183b7c4e97836e8fecbb67898b06c47e78 (diff) | |
parent | ca9153a3a2a7556d091dfe080e42b0e67881fff6 (diff) | |
download | op-kernel-dev-3c92ec8ae91ecf59d88c798301833d7cf83f2179.zip op-kernel-dev-3c92ec8ae91ecf59d88c798301833d7cf83f2179.tar.gz |
Merge branch 'next' of git://git.kernel.org/pub/scm/linux/kernel/git/paulus/powerpc
* 'next' of git://git.kernel.org/pub/scm/linux/kernel/git/paulus/powerpc: (144 commits)
powerpc/44x: Support 16K/64K base page sizes on 44x
powerpc: Force memory size to be a multiple of PAGE_SIZE
powerpc/32: Wire up the trampoline code for kdump
powerpc/32: Add the ability for a classic ppc kernel to be loaded at 32M
powerpc/32: Allow __ioremap on RAM addresses for kdump kernel
powerpc/32: Setup OF properties for kdump
powerpc/32/kdump: Implement crash_setup_regs() using ppc_save_regs()
powerpc: Prepare xmon_save_regs for use with kdump
powerpc: Remove default kexec/crash_kernel ops assignments
powerpc: Make default kexec/crash_kernel ops implicit
powerpc: Setup OF properties for ppc32 kexec
powerpc/pseries: Fix cpu hotplug
powerpc: Fix KVM build on ppc440
powerpc/cell: add QPACE as a separate Cell platform
powerpc/cell: fix build breakage with CONFIG_SPUFS disabled
powerpc/mpc5200: fix error paths in PSC UART probe function
powerpc/mpc5200: add rts/cts handling in PSC UART driver
powerpc/mpc5200: Make PSC UART driver update serial errors counters
powerpc/mpc5200: Remove obsolete code from mpc5200 MDIO driver
powerpc/mpc5200: Add MDMA/UDMA support to MPC5200 ATA driver
...
Fix trivial conflict in drivers/char/Makefile as per Paul's directions
Diffstat (limited to 'arch/powerpc/kernel/machine_kexec.c')
-rw-r--r-- | arch/powerpc/kernel/machine_kexec.c | 91 |
1 files changed, 79 insertions, 12 deletions
diff --git a/arch/powerpc/kernel/machine_kexec.c b/arch/powerpc/kernel/machine_kexec.c index ac2a21f..b3abebb 100644 --- a/arch/powerpc/kernel/machine_kexec.c +++ b/arch/powerpc/kernel/machine_kexec.c @@ -13,13 +13,17 @@ #include <linux/reboot.h> #include <linux/threads.h> #include <linux/lmb.h> +#include <linux/of.h> #include <asm/machdep.h> #include <asm/prom.h> +#include <asm/sections.h> void machine_crash_shutdown(struct pt_regs *regs) { if (ppc_md.machine_crash_shutdown) ppc_md.machine_crash_shutdown(regs); + else + default_machine_crash_shutdown(regs); } /* @@ -31,11 +35,8 @@ int machine_kexec_prepare(struct kimage *image) { if (ppc_md.machine_kexec_prepare) return ppc_md.machine_kexec_prepare(image); - /* - * Fail if platform doesn't provide its own machine_kexec_prepare - * implementation. - */ - return -ENOSYS; + else + return default_machine_kexec_prepare(image); } void machine_kexec_cleanup(struct kimage *image) @@ -52,13 +53,11 @@ void machine_kexec(struct kimage *image) { if (ppc_md.machine_kexec) ppc_md.machine_kexec(image); - else { - /* - * Fall back to normal restart if platform doesn't provide - * its own kexec function, and user insist to kexec... - */ - machine_restart(NULL); - } + else + default_machine_kexec(image); + + /* Fall back to normal restart if we're still alive. */ + machine_restart(NULL); for(;;); } @@ -118,3 +117,71 @@ int overlaps_crashkernel(unsigned long start, unsigned long size) { return (start + size) > crashk_res.start && start <= crashk_res.end; } + +/* Values we need to export to the second kernel via the device tree. */ +static unsigned long kernel_end; +static unsigned long crashk_size; + +static struct property kernel_end_prop = { + .name = "linux,kernel-end", + .length = sizeof(unsigned long), + .value = &kernel_end, +}; + +static struct property crashk_base_prop = { + .name = "linux,crashkernel-base", + .length = sizeof(unsigned long), + .value = &crashk_res.start, +}; + +static struct property crashk_size_prop = { + .name = "linux,crashkernel-size", + .length = sizeof(unsigned long), + .value = &crashk_size, +}; + +static void __init export_crashk_values(struct device_node *node) +{ + struct property *prop; + + /* There might be existing crash kernel properties, but we can't + * be sure what's in them, so remove them. */ + prop = of_find_property(node, "linux,crashkernel-base", NULL); + if (prop) + prom_remove_property(node, prop); + + prop = of_find_property(node, "linux,crashkernel-size", NULL); + if (prop) + prom_remove_property(node, prop); + + if (crashk_res.start != 0) { + prom_add_property(node, &crashk_base_prop); + crashk_size = crashk_res.end - crashk_res.start + 1; + prom_add_property(node, &crashk_size_prop); + } +} + +static int __init kexec_setup(void) +{ + struct device_node *node; + struct property *prop; + + node = of_find_node_by_path("/chosen"); + if (!node) + return -ENOENT; + + /* remove any stale properties so ours can be found */ + prop = of_find_property(node, kernel_end_prop.name, NULL); + if (prop) + prom_remove_property(node, prop); + + /* information needed by userspace when using default_machine_kexec */ + kernel_end = __pa(_end); + prom_add_property(node, &kernel_end_prop); + + export_crashk_values(node); + + of_node_put(node); + return 0; +} +late_initcall(kexec_setup); |