diff options
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 1511454c4690..7509aa6474f2 100644 --- a/arch/powerpc/kernel/traps.c +++ b/arch/powerpc/kernel/traps.c | |||
@@ -31,6 +31,7 @@ | |||
31 | #include <linux/prctl.h> | 31 | #include <linux/prctl.h> |
32 | #include <linux/delay.h> | 32 | #include <linux/delay.h> |
33 | #include <linux/kprobes.h> | 33 | #include <linux/kprobes.h> |
34 | #include <linux/kexec.h> | ||
34 | 35 | ||
35 | #include <asm/kdebug.h> | 36 | #include <asm/kdebug.h> |
36 | #include <asm/pgtable.h> | 37 | #include <asm/pgtable.h> |
@@ -95,7 +96,7 @@ static DEFINE_SPINLOCK(die_lock); | |||
95 | 96 | ||
96 | int die(const char *str, struct pt_regs *regs, long err) | 97 | int die(const char *str, struct pt_regs *regs, long err) |
97 | { | 98 | { |
98 | static int die_counter; | 99 | static int die_counter, crash_dump_start = 0; |
99 | int nl = 0; | 100 | int nl = 0; |
100 | 101 | ||
101 | if (debugger(regs)) | 102 | if (debugger(regs)) |
@@ -156,7 +157,21 @@ int die(const char *str, struct pt_regs *regs, long err) | |||
156 | print_modules(); | 157 | print_modules(); |
157 | show_regs(regs); | 158 | show_regs(regs); |
158 | bust_spinlocks(0); | 159 | bust_spinlocks(0); |
160 | |||
161 | if (!crash_dump_start && kexec_should_crash(current)) { | ||
162 | crash_dump_start = 1; | ||
163 | spin_unlock_irq(&die_lock); | ||
164 | crash_kexec(regs); | ||
165 | /* NOTREACHED */ | ||
166 | } | ||
159 | spin_unlock_irq(&die_lock); | 167 | spin_unlock_irq(&die_lock); |
168 | if (crash_dump_start) | ||
169 | /* | ||
170 | * Only for soft-reset: Other CPUs will be responded to an IPI | ||
171 | * sent by first kexec CPU. | ||
172 | */ | ||
173 | for(;;) | ||
174 | ; | ||
160 | 175 | ||
161 | if (in_interrupt()) | 176 | if (in_interrupt()) |
162 | panic("Fatal exception in interrupt"); | 177 | panic("Fatal exception in interrupt"); |
@@ -215,8 +230,10 @@ void _exception(int signr, struct pt_regs *regs, int code, unsigned long addr) | |||
215 | void system_reset_exception(struct pt_regs *regs) | 230 | void system_reset_exception(struct pt_regs *regs) |
216 | { | 231 | { |
217 | /* See if any machine dependent calls */ | 232 | /* See if any machine dependent calls */ |
218 | if (ppc_md.system_reset_exception) | 233 | if (ppc_md.system_reset_exception) { |
219 | ppc_md.system_reset_exception(regs); | 234 | if (ppc_md.system_reset_exception(regs)) |
235 | return; | ||
236 | } | ||
220 | 237 | ||
221 | die("System Reset", regs, SIGABRT); | 238 | die("System Reset", regs, SIGABRT); |
222 | 239 | ||
@@ -886,12 +903,10 @@ void altivec_unavailable_exception(struct pt_regs *regs) | |||
886 | die("Unrecoverable VMX/Altivec Unavailable Exception", regs, SIGABRT); | 903 | die("Unrecoverable VMX/Altivec Unavailable Exception", regs, SIGABRT); |
887 | } | 904 | } |
888 | 905 | ||
889 | #if defined(CONFIG_PPC64) || defined(CONFIG_E500) | ||
890 | void performance_monitor_exception(struct pt_regs *regs) | 906 | void performance_monitor_exception(struct pt_regs *regs) |
891 | { | 907 | { |
892 | perf_irq(regs); | 908 | perf_irq(regs); |
893 | } | 909 | } |
894 | #endif | ||
895 | 910 | ||
896 | #ifdef CONFIG_8xx | 911 | #ifdef CONFIG_8xx |
897 | void SoftwareEmulation(struct pt_regs *regs) | 912 | void SoftwareEmulation(struct pt_regs *regs) |