]> pilppa.org Git - linux-2.6-omap-h63xx.git/blobdiff - arch/blackfin/kernel/traps.c
Blackfin arch: fix bug - sometimes there is no response to the hitting key in uboot...
[linux-2.6-omap-h63xx.git] / arch / blackfin / kernel / traps.c
index 9a9d5083acfdde5e2cae73830c79b9dcdf478030..be5ae7fabc5f02f4c01479dc0271069313cd9972 100644 (file)
@@ -34,6 +34,7 @@
 #include <linux/fs.h>
 #include <asm/traps.h>
 #include <asm/cacheflush.h>
+#include <asm/cplb.h>
 #include <asm/blackfin.h>
 #include <asm/irq_handler.h>
 #include <linux/irq.h>
 #include <asm/dma.h>
 
 #ifdef CONFIG_KGDB
-# include <linux/debugger.h>
 # include <linux/kgdb.h>
 
 # define CHK_DEBUGGER_TRAP() \
        do { \
-               CHK_DEBUGGER(trapnr, sig, info.si_code, fp, ); \
+               kgdb_handle_exception(trapnr, sig, info.si_code, fp); \
        } while (0)
 # define CHK_DEBUGGER_TRAP_MAYBE() \
        do { \
@@ -67,7 +67,15 @@ void __init trap_init(void)
        CSYNC();
 }
 
-unsigned long saved_icplb_fault_addr, saved_dcplb_fault_addr;
+/*
+ * Used to save the RETX, SEQSTAT, I/D CPLB FAULT ADDR
+ * values across the transition from exception to IRQ5.
+ * We put these in L1, so they are going to be in a valid
+ * location during exception context
+ */
+__attribute__((l1_data))
+unsigned long saved_retx, saved_seqstat,
+       saved_icplb_fault_addr, saved_dcplb_fault_addr;
 
 static void decode_address(char *buf, unsigned long address)
 {
@@ -185,9 +193,27 @@ asmlinkage void double_fault_c(struct pt_regs *fp)
        console_verbose();
        oops_in_progress = 1;
        printk(KERN_EMERG "\n" KERN_EMERG "Double Fault\n");
-       dump_bfin_process(fp);
-       dump_bfin_mem(fp);
-       show_regs(fp);
+#ifdef CONFIG_DEBUG_DOUBLEFAULT_PRINT
+       if (((long)fp->seqstat &  SEQSTAT_EXCAUSE) == VEC_UNCOV) {
+               char buf[150];
+               decode_address(buf, saved_retx);
+               printk(KERN_EMERG "While handling exception (EXCAUSE = 0x%x) at %s:\n",
+                       (int)saved_seqstat & SEQSTAT_EXCAUSE, buf);
+               decode_address(buf, saved_dcplb_fault_addr);
+               printk(KERN_NOTICE "   DCPLB_FAULT_ADDR: %s\n", buf);
+               decode_address(buf, saved_icplb_fault_addr);
+               printk(KERN_NOTICE "   ICPLB_FAULT_ADDR: %s\n", buf);
+
+               decode_address(buf, fp->retx);
+               printk(KERN_NOTICE "The instruction at %s caused a double exception\n",
+                       buf);
+       } else
+#endif
+       {
+               dump_bfin_process(fp);
+               dump_bfin_mem(fp);
+               show_regs(fp);
+       }
        panic("Double Fault - unrecoverable event\n");
 
 }
@@ -273,20 +299,30 @@ asmlinkage void trap_c(struct pt_regs *fp)
                info.si_code = SEGV_STACKFLOW;
                sig = SIGSEGV;
                printk(KERN_NOTICE EXC_0x03(KERN_NOTICE));
-               CHK_DEBUGGER_TRAP();
+               CHK_DEBUGGER_TRAP_MAYBE();
+               break;
+       /* 0x04 - User Defined */
+       /* 0x05 - User Defined */
+       /* 0x06 - User Defined */
+       /* 0x07 - User Defined */
+       /* 0x08 - User Defined */
+       /* 0x09 - User Defined */
+       /* 0x0A - User Defined */
+       /* 0x0B - User Defined */
+       /* 0x0C - User Defined */
+       /* 0x0D - User Defined */
+       /* 0x0E - User Defined */
+       /* 0x0F - User Defined */
+       /*
+        * If we got here, it is most likely that someone was trying to use a
+        * custom exception handler, and it is not actually installed properly
+        */
+       case VEC_EXCPT04 ... VEC_EXCPT15:
+               info.si_code = ILL_ILLPARAOP;
+               sig = SIGILL;
+               printk(KERN_NOTICE EXC_0x04(KERN_NOTICE));
+               CHK_DEBUGGER_TRAP_MAYBE();
                break;
-       /* 0x04 - User Defined, Caught by default */
-       /* 0x05 - User Defined, Caught by default */
-       /* 0x06 - User Defined, Caught by default */
-       /* 0x07 - User Defined, Caught by default */
-       /* 0x08 - User Defined, Caught by default */
-       /* 0x09 - User Defined, Caught by default */
-       /* 0x0A - User Defined, Caught by default */
-       /* 0x0B - User Defined, Caught by default */
-       /* 0x0C - User Defined, Caught by default */
-       /* 0x0D - User Defined, Caught by default */
-       /* 0x0E - User Defined, Caught by default */
-       /* 0x0F - User Defined, Caught by default */
        /* 0x10 HW Single step, handled here */
        case VEC_STEP:
                info.si_code = TRAP_STEP;
@@ -302,7 +338,7 @@ asmlinkage void trap_c(struct pt_regs *fp)
                info.si_code = TRAP_TRACEFLOW;
                sig = SIGTRAP;
                printk(KERN_NOTICE EXC_0x11(KERN_NOTICE));
-               CHK_DEBUGGER_TRAP();
+               CHK_DEBUGGER_TRAP_MAYBE();
                break;
        /* 0x12 - Reserved, Caught by default */
        /* 0x13 - Reserved, Caught by default */
@@ -324,35 +360,35 @@ asmlinkage void trap_c(struct pt_regs *fp)
                info.si_code = ILL_ILLOPC;
                sig = SIGILL;
                printk(KERN_NOTICE EXC_0x21(KERN_NOTICE));
-               CHK_DEBUGGER_TRAP();
+               CHK_DEBUGGER_TRAP_MAYBE();
                break;
        /* 0x22 - Illegal Instruction Combination, handled here */
        case VEC_ILGAL_I:
                info.si_code = ILL_ILLPARAOP;
                sig = SIGILL;
                printk(KERN_NOTICE EXC_0x22(KERN_NOTICE));
-               CHK_DEBUGGER_TRAP();
+               CHK_DEBUGGER_TRAP_MAYBE();
                break;
        /* 0x23 - Data CPLB protection violation, handled here */
        case VEC_CPLB_VL:
                info.si_code = ILL_CPLB_VI;
                sig = SIGBUS;
                printk(KERN_NOTICE EXC_0x23(KERN_NOTICE));
-               CHK_DEBUGGER_TRAP();
+               CHK_DEBUGGER_TRAP_MAYBE();
                break;
        /* 0x24 - Data access misaligned, handled here */
        case VEC_MISALI_D:
                info.si_code = BUS_ADRALN;
                sig = SIGBUS;
                printk(KERN_NOTICE EXC_0x24(KERN_NOTICE));
-               CHK_DEBUGGER_TRAP();
+               CHK_DEBUGGER_TRAP_MAYBE();
                break;
        /* 0x25 - Unrecoverable Event, handled here */
        case VEC_UNCOV:
                info.si_code = ILL_ILLEXCPT;
                sig = SIGILL;
                printk(KERN_NOTICE EXC_0x25(KERN_NOTICE));
-               CHK_DEBUGGER_TRAP();
+               CHK_DEBUGGER_TRAP_MAYBE();
                break;
        /* 0x26 - Data CPLB Miss, normal case is handled in _cplb_hdr,
                error case is handled here */
@@ -360,7 +396,6 @@ asmlinkage void trap_c(struct pt_regs *fp)
                info.si_code = BUS_ADRALN;
                sig = SIGBUS;
                printk(KERN_NOTICE EXC_0x26(KERN_NOTICE));
-               CHK_DEBUGGER_TRAP();
                break;
        /* 0x27 - Data CPLB Multiple Hits - Linux Trap Zero, handled here */
        case VEC_CPLB_MHIT:
@@ -372,7 +407,7 @@ asmlinkage void trap_c(struct pt_regs *fp)
                else
 #endif
                        printk(KERN_NOTICE EXC_0x27(KERN_NOTICE));
-               CHK_DEBUGGER_TRAP();
+               CHK_DEBUGGER_TRAP_MAYBE();
                break;
        /* 0x28 - Emulation Watchpoint, handled here */
        case VEC_WATCH:
@@ -391,7 +426,7 @@ asmlinkage void trap_c(struct pt_regs *fp)
                info.si_code = BUS_OPFETCH;
                sig = SIGBUS;
                printk(KERN_NOTICE "BF535: VEC_ISTRU_VL\n");
-               CHK_DEBUGGER_TRAP();
+               CHK_DEBUGGER_TRAP_MAYBE();
                break;
 #else
        /* 0x29 - Reserved, Caught by default */
@@ -401,21 +436,20 @@ asmlinkage void trap_c(struct pt_regs *fp)
                info.si_code = BUS_ADRALN;
                sig = SIGBUS;
                printk(KERN_NOTICE EXC_0x2A(KERN_NOTICE));
-               CHK_DEBUGGER_TRAP();
+               CHK_DEBUGGER_TRAP_MAYBE();
                break;
        /* 0x2B - Instruction CPLB protection violation, handled here */
        case VEC_CPLB_I_VL:
                info.si_code = ILL_CPLB_VI;
                sig = SIGBUS;
                printk(KERN_NOTICE EXC_0x2B(KERN_NOTICE));
-               CHK_DEBUGGER_TRAP();
+               CHK_DEBUGGER_TRAP_MAYBE();
                break;
        /* 0x2C - Instruction CPLB miss, handled in _cplb_hdr */
        case VEC_CPLB_I_M:
                info.si_code = ILL_CPLB_MISS;
                sig = SIGBUS;
                printk(KERN_NOTICE EXC_0x2C(KERN_NOTICE));
-               CHK_DEBUGGER_TRAP();
                break;
        /* 0x2D - Instruction CPLB Multiple Hits, handled here */
        case VEC_CPLB_I_MHIT:
@@ -427,14 +461,14 @@ asmlinkage void trap_c(struct pt_regs *fp)
                else
 #endif
                        printk(KERN_NOTICE EXC_0x2D(KERN_NOTICE));
-               CHK_DEBUGGER_TRAP();
+               CHK_DEBUGGER_TRAP_MAYBE();
                break;
        /* 0x2E - Illegal use of Supervisor Resource, handled here */
        case VEC_ILL_RES:
                info.si_code = ILL_PRVOPC;
                sig = SIGILL;
                printk(KERN_NOTICE EXC_0x2E(KERN_NOTICE));
-               CHK_DEBUGGER_TRAP();
+               CHK_DEBUGGER_TRAP_MAYBE();
                break;
        /* 0x2F - Reserved, Caught by default */
        /* 0x30 - Reserved, Caught by default */
@@ -481,14 +515,19 @@ asmlinkage void trap_c(struct pt_regs *fp)
                        printk(KERN_NOTICE HWC_default(KERN_NOTICE));
                        break;
                }
-               CHK_DEBUGGER_TRAP();
+               CHK_DEBUGGER_TRAP_MAYBE();
                break;
+       /*
+        * We should be handling all known exception types above,
+        * if we get here we hit a reserved one, so panic
+        */
        default:
-               info.si_code = TRAP_ILLTRAP;
-               sig = SIGTRAP;
+               oops_in_progress = 1;
+               info.si_code = ILL_ILLPARAOP;
+               sig = SIGILL;
                printk(KERN_EMERG "Caught Unhandled Exception, code = %08lx\n",
                        (fp->seqstat & SEQSTAT_EXCAUSE));
-               CHK_DEBUGGER_TRAP();
+               CHK_DEBUGGER_TRAP_MAYBE();
                break;
        }