diff options
author | Linus Torvalds <torvalds@g5.osdl.org> | 2006-01-09 10:03:44 -0800 |
---|---|---|
committer | Linus Torvalds <torvalds@g5.osdl.org> | 2006-01-09 10:03:44 -0800 |
commit | 6150c32589d1976ca8a5c987df951088c05a7542 (patch) | |
tree | 94073696576323ff966e365d8c47b8ecd8372f97 /arch/powerpc/kernel/traps.c | |
parent | 44637a12f80b80157d9c1bc5b7d6ef09c9e05713 (diff) | |
parent | be42d5fa3772241b8ecebd443f1fb36247959c54 (diff) |
Merge git://git.kernel.org/pub/scm/linux/kernel/git/paulus/powerpc-merge
Diffstat (limited to 'arch/powerpc/kernel/traps.c')
-rw-r--r-- | arch/powerpc/kernel/traps.c | 25 |
1 files changed, 20 insertions, 5 deletions
diff --git a/arch/powerpc/kernel/traps.c b/arch/powerpc/kernel/traps.c index 1511454c469..7509aa6474f 100644 --- a/arch/powerpc/kernel/traps.c +++ b/arch/powerpc/kernel/traps.c @@ -31,6 +31,7 @@ #include <linux/prctl.h> #include <linux/delay.h> #include <linux/kprobes.h> +#include <linux/kexec.h> #include <asm/kdebug.h> #include <asm/pgtable.h> @@ -95,7 +96,7 @@ static DEFINE_SPINLOCK(die_lock); int die(const char *str, struct pt_regs *regs, long err) { - static int die_counter; + static int die_counter, crash_dump_start = 0; int nl = 0; if (debugger(regs)) @@ -156,7 +157,21 @@ int die(const char *str, struct pt_regs *regs, long err) print_modules(); show_regs(regs); bust_spinlocks(0); + + if (!crash_dump_start && kexec_should_crash(current)) { + crash_dump_start = 1; + spin_unlock_irq(&die_lock); + crash_kexec(regs); + /* NOTREACHED */ + } spin_unlock_irq(&die_lock); + if (crash_dump_start) + /* + * Only for soft-reset: Other CPUs will be responded to an IPI + * sent by first kexec CPU. + */ + for(;;) + ; if (in_interrupt()) panic("Fatal exception in interrupt"); @@ -215,8 +230,10 @@ void _exception(int signr, struct pt_regs *regs, int code, unsigned long addr) void system_reset_exception(struct pt_regs *regs) { /* See if any machine dependent calls */ - if (ppc_md.system_reset_exception) - ppc_md.system_reset_exception(regs); + if (ppc_md.system_reset_exception) { + if (ppc_md.system_reset_exception(regs)) + return; + } die("System Reset", regs, SIGABRT); @@ -886,12 +903,10 @@ void altivec_unavailable_exception(struct pt_regs *regs) die("Unrecoverable VMX/Altivec Unavailable Exception", regs, SIGABRT); } -#if defined(CONFIG_PPC64) || defined(CONFIG_E500) void performance_monitor_exception(struct pt_regs *regs) { perf_irq(regs); } -#endif #ifdef CONFIG_8xx void SoftwareEmulation(struct pt_regs *regs) |