Merge branch 'drm-forlinus' of git://git.kernel.org/pub/scm/linux/kernel/git/airlied...
[pandora-kernel.git] / arch / powerpc / kernel / traps.c
index 07e5ee4..7509aa6 100644 (file)
@@ -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>
@@ -39,7 +40,6 @@
 #include <asm/io.h>
 #include <asm/machdep.h>
 #include <asm/rtas.h>
-#include <asm/xmon.h>
 #include <asm/pmc.h>
 #ifdef CONFIG_PPC32
 #include <asm/reg.h>
@@ -50,7 +50,6 @@
 #ifdef CONFIG_PPC64
 #include <asm/firmware.h>
 #include <asm/processor.h>
-#include <asm/systemcfg.h>
 #endif
 
 #ifdef CONFIG_PPC64    /* XXX */
@@ -97,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))
@@ -130,7 +129,7 @@ int die(const char *str, struct pt_regs *regs, long err)
        nl = 1;
 #endif
 #ifdef CONFIG_PPC64
-       switch (systemcfg->platform) {
+       switch (_machine) {
        case PLATFORM_PSERIES:
                printk("PSERIES ");
                nl = 1;
@@ -158,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");
@@ -217,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);
 
@@ -748,22 +763,12 @@ static int check_bug_trap(struct pt_regs *regs)
                return 0;
        if (bug->line & BUG_WARNING_TRAP) {
                /* this is a WARN_ON rather than BUG/BUG_ON */
-#ifdef CONFIG_XMON
-               xmon_printf(KERN_ERR "Badness in %s at %s:%ld\n",
-                      bug->function, bug->file,
-                      bug->line & ~BUG_WARNING_TRAP);
-#endif /* CONFIG_XMON */               
                printk(KERN_ERR "Badness in %s at %s:%ld\n",
                       bug->function, bug->file,
                       bug->line & ~BUG_WARNING_TRAP);
                dump_stack();
                return 1;
        }
-#ifdef CONFIG_XMON
-       xmon_printf(KERN_CRIT "kernel BUG in %s at %s:%ld!\n",
-              bug->function, bug->file, bug->line);
-       xmon(regs);
-#endif /* CONFIG_XMON */
        printk(KERN_CRIT "kernel BUG in %s at %s:%ld!\n",
               bug->function, bug->file, bug->line);
 
@@ -898,16 +903,10 @@ void altivec_unavailable_exception(struct pt_regs *regs)
        die("Unrecoverable VMX/Altivec Unavailable Exception", regs, SIGABRT);
 }
 
-#ifdef CONFIG_PPC64
-extern perf_irq_t perf_irq;
-#endif
-
-#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)