diff options
Diffstat (limited to 'arch/blackfin/kernel/traps.c')
-rw-r--r-- | arch/blackfin/kernel/traps.c | 198 |
1 files changed, 109 insertions, 89 deletions
diff --git a/arch/blackfin/kernel/traps.c b/arch/blackfin/kernel/traps.c index 5ab87b0b92dd..3909f5b35536 100644 --- a/arch/blackfin/kernel/traps.c +++ b/arch/blackfin/kernel/traps.c | |||
@@ -27,15 +27,15 @@ | |||
27 | * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA | 27 | * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA |
28 | */ | 28 | */ |
29 | 29 | ||
30 | #include <asm/uaccess.h> | 30 | #include <linux/uaccess.h> |
31 | #include <linux/interrupt.h> | ||
32 | #include <linux/module.h> | ||
33 | #include <linux/kallsyms.h> | ||
31 | #include <asm/traps.h> | 34 | #include <asm/traps.h> |
32 | #include <asm/cacheflush.h> | 35 | #include <asm/cacheflush.h> |
33 | #include <asm/blackfin.h> | 36 | #include <asm/blackfin.h> |
34 | #include <asm/uaccess.h> | ||
35 | #include <asm/irq_handler.h> | 37 | #include <asm/irq_handler.h> |
36 | #include <linux/interrupt.h> | 38 | #include <asm/trace.h> |
37 | #include <linux/module.h> | ||
38 | #include <linux/kallsyms.h> | ||
39 | 39 | ||
40 | #ifdef CONFIG_KGDB | 40 | #ifdef CONFIG_KGDB |
41 | # include <linux/debugger.h> | 41 | # include <linux/debugger.h> |
@@ -76,7 +76,7 @@ static int printk_address(unsigned long address) | |||
76 | if (!modname) | 76 | if (!modname) |
77 | modname = delim = ""; | 77 | modname = delim = ""; |
78 | return printk("<0x%p> { %s%s%s%s + 0x%lx }", | 78 | return printk("<0x%p> { %s%s%s%s + 0x%lx }", |
79 | (void*)address, delim, modname, delim, symname, | 79 | (void *)address, delim, modname, delim, symname, |
80 | (unsigned long)offset); | 80 | (unsigned long)offset); |
81 | 81 | ||
82 | } | 82 | } |
@@ -119,7 +119,7 @@ static int printk_address(unsigned long address) | |||
119 | 119 | ||
120 | write_unlock_irq(&tasklist_lock); | 120 | write_unlock_irq(&tasklist_lock); |
121 | return printk("<0x%p> [ %s + 0x%lx ]", | 121 | return printk("<0x%p> [ %s + 0x%lx ]", |
122 | (void*)address, name, offset); | 122 | (void *)address, name, offset); |
123 | } | 123 | } |
124 | 124 | ||
125 | vml = vml->next; | 125 | vml = vml->next; |
@@ -128,19 +128,9 @@ static int printk_address(unsigned long address) | |||
128 | write_unlock_irq(&tasklist_lock); | 128 | write_unlock_irq(&tasklist_lock); |
129 | 129 | ||
130 | /* we were unable to find this address anywhere */ | 130 | /* we were unable to find this address anywhere */ |
131 | return printk("[<0x%p>]", (void*)address); | 131 | return printk("[<0x%p>]", (void *)address); |
132 | } | 132 | } |
133 | 133 | ||
134 | #define trace_buffer_save(x) \ | ||
135 | do { \ | ||
136 | (x) = bfin_read_TBUFCTL(); \ | ||
137 | bfin_write_TBUFCTL((x) & ~TBUFEN); \ | ||
138 | } while (0) | ||
139 | #define trace_buffer_restore(x) \ | ||
140 | do { \ | ||
141 | bfin_write_TBUFCTL((x)); \ | ||
142 | } while (0) | ||
143 | |||
144 | asmlinkage void trap_c(struct pt_regs *fp) | 134 | asmlinkage void trap_c(struct pt_regs *fp) |
145 | { | 135 | { |
146 | int j, sig = 0; | 136 | int j, sig = 0; |
@@ -148,8 +138,15 @@ asmlinkage void trap_c(struct pt_regs *fp) | |||
148 | unsigned long trapnr = fp->seqstat & SEQSTAT_EXCAUSE; | 138 | unsigned long trapnr = fp->seqstat & SEQSTAT_EXCAUSE; |
149 | 139 | ||
150 | #ifdef CONFIG_KGDB | 140 | #ifdef CONFIG_KGDB |
151 | # define CHK_DEBUGGER_TRAP() do { CHK_DEBUGGER(trapnr, sig, info.si_code, fp,); } while (0) | 141 | # define CHK_DEBUGGER_TRAP() \ |
152 | # define CHK_DEBUGGER_TRAP_MAYBE() do { if (kgdb_connected) CHK_DEBUGGER_TRAP(); } while (0) | 142 | do { \ |
143 | CHK_DEBUGGER(trapnr, sig, info.si_code, fp); \ | ||
144 | } while (0) | ||
145 | # define CHK_DEBUGGER_TRAP_MAYBE() \ | ||
146 | do { \ | ||
147 | if (kgdb_connected) \ | ||
148 | CHK_DEBUGGER_TRAP(); \ | ||
149 | } while (0) | ||
153 | #else | 150 | #else |
154 | # define CHK_DEBUGGER_TRAP() do { } while (0) | 151 | # define CHK_DEBUGGER_TRAP() do { } while (0) |
155 | # define CHK_DEBUGGER_TRAP_MAYBE() do { } while (0) | 152 | # define CHK_DEBUGGER_TRAP_MAYBE() do { } while (0) |
@@ -196,15 +193,14 @@ asmlinkage void trap_c(struct pt_regs *fp) | |||
196 | #else | 193 | #else |
197 | /* 0x02 - User Defined, Caught by default */ | 194 | /* 0x02 - User Defined, Caught by default */ |
198 | #endif | 195 | #endif |
199 | /* 0x03 - Atomic test and set */ | 196 | /* 0x03 - User Defined, userspace stack overflow */ |
200 | case VEC_EXCPT03: | 197 | case VEC_EXCPT03: |
201 | info.si_code = SEGV_STACKFLOW; | 198 | info.si_code = SEGV_STACKFLOW; |
202 | sig = SIGSEGV; | 199 | sig = SIGSEGV; |
203 | printk(KERN_EMERG EXC_0x03); | 200 | printk(KERN_EMERG EXC_0x03); |
204 | CHK_DEBUGGER_TRAP(); | 201 | CHK_DEBUGGER_TRAP(); |
205 | break; | 202 | break; |
206 | /* 0x04 - spinlock - handled by _ex_spinlock, | 203 | /* 0x04 - User Defined, Caught by default */ |
207 | getting here is an error */ | ||
208 | /* 0x05 - User Defined, Caught by default */ | 204 | /* 0x05 - User Defined, Caught by default */ |
209 | /* 0x06 - User Defined, Caught by default */ | 205 | /* 0x06 - User Defined, Caught by default */ |
210 | /* 0x07 - User Defined, Caught by default */ | 206 | /* 0x07 - User Defined, Caught by default */ |
@@ -297,7 +293,8 @@ asmlinkage void trap_c(struct pt_regs *fp) | |||
297 | info.si_code = ILL_CPLB_MULHIT; | 293 | info.si_code = ILL_CPLB_MULHIT; |
298 | #ifdef CONFIG_DEBUG_HUNT_FOR_ZERO | 294 | #ifdef CONFIG_DEBUG_HUNT_FOR_ZERO |
299 | sig = SIGSEGV; | 295 | sig = SIGSEGV; |
300 | printk(KERN_EMERG "\n\nNULL pointer access (probably)\n"); | 296 | printk(KERN_EMERG "\n" |
297 | KERN_EMERG "NULL pointer access (probably)\n"); | ||
301 | #else | 298 | #else |
302 | sig = SIGILL; | 299 | sig = SIGILL; |
303 | printk(KERN_EMERG EXC_0x27); | 300 | printk(KERN_EMERG EXC_0x27); |
@@ -418,7 +415,9 @@ asmlinkage void trap_c(struct pt_regs *fp) | |||
418 | if (current->mm) { | 415 | if (current->mm) { |
419 | fp->pc = current->mm->start_code; | 416 | fp->pc = current->mm->start_code; |
420 | } else { | 417 | } else { |
421 | printk(KERN_EMERG "I can't return to memory that doesn't exist - bad things happen\n"); | 418 | printk(KERN_EMERG |
419 | "I can't return to memory that doesn't exist" | ||
420 | " - bad things happen\n"); | ||
422 | panic("Help - I've fallen and can't get up\n"); | 421 | panic("Help - I've fallen and can't get up\n"); |
423 | } | 422 | } |
424 | } | 423 | } |
@@ -522,38 +521,47 @@ EXPORT_SYMBOL(dump_stack); | |||
522 | void dump_bfin_regs(struct pt_regs *fp, void *retaddr) | 521 | void dump_bfin_regs(struct pt_regs *fp, void *retaddr) |
523 | { | 522 | { |
524 | if (current->pid) { | 523 | if (current->pid) { |
525 | printk("\nCURRENT PROCESS:\n\n"); | 524 | printk(KERN_EMERG "\n" KERN_EMERG "CURRENT PROCESS:\n" |
526 | printk("COMM=%s PID=%d\n", current->comm, current->pid); | 525 | KERN_EMERG "\n"); |
526 | printk(KERN_EMERG "COMM=%s PID=%d\n", | ||
527 | current->comm, current->pid); | ||
527 | } else { | 528 | } else { |
528 | printk | 529 | printk |
529 | ("\nNo Valid pid - Either things are really messed up, or you are in the kernel\n"); | 530 | (KERN_EMERG "\n" KERN_EMERG |
531 | "No Valid pid - Either things are really messed up," | ||
532 | " or you are in the kernel\n"); | ||
530 | } | 533 | } |
531 | 534 | ||
532 | if (current->mm) { | 535 | if (current->mm) { |
533 | printk("TEXT = 0x%p-0x%p DATA = 0x%p-0x%p\n" | 536 | printk(KERN_EMERG "TEXT = 0x%p-0x%p DATA = 0x%p-0x%p\n" |
534 | "BSS = 0x%p-0x%p USER-STACK = 0x%p\n\n", | 537 | KERN_EMERG "BSS = 0x%p-0x%p USER-STACK = 0x%p\n" |
535 | (void*)current->mm->start_code, | 538 | KERN_EMERG "\n", |
536 | (void*)current->mm->end_code, | 539 | (void *)current->mm->start_code, |
537 | (void*)current->mm->start_data, | 540 | (void *)current->mm->end_code, |
538 | (void*)current->mm->end_data, | 541 | (void *)current->mm->start_data, |
539 | (void*)current->mm->end_data, | 542 | (void *)current->mm->end_data, |
540 | (void*)current->mm->brk, | 543 | (void *)current->mm->end_data, |
541 | (void*)current->mm->start_stack); | 544 | (void *)current->mm->brk, |
545 | (void *)current->mm->start_stack); | ||
542 | } | 546 | } |
543 | 547 | ||
544 | printk("return address: 0x%p; contents of [PC-16...PC+8]:\n", retaddr); | 548 | printk(KERN_EMERG "return address: [0x%p]; contents of:", retaddr); |
545 | if (retaddr != 0 && retaddr <= (void*)physical_mem_end | 549 | if (retaddr != 0 && retaddr <= (void *)physical_mem_end |
546 | #if L1_CODE_LENGTH != 0 | 550 | #if L1_CODE_LENGTH != 0 |
547 | /* FIXME: Copy the code out of L1 Instruction SRAM through dma | 551 | /* FIXME: Copy the code out of L1 Instruction SRAM through dma |
548 | memcpy. */ | 552 | memcpy. */ |
549 | && !(retaddr >= (void*)L1_CODE_START | 553 | && !(retaddr >= (void *)L1_CODE_START |
550 | && retaddr < (void*)(L1_CODE_START + L1_CODE_LENGTH)) | 554 | && retaddr < (void *)(L1_CODE_START + L1_CODE_LENGTH)) |
551 | #endif | 555 | #endif |
552 | ) { | 556 | ) { |
553 | int i = 0; | 557 | int i = ((unsigned int)retaddr & 0xFFFFFFF0) - 32; |
554 | unsigned short x = 0; | 558 | unsigned short x = 0; |
555 | for (i = -16; i < 8; i++) { | 559 | for (; i < ((unsigned int)retaddr & 0xFFFFFFF0) + 32; i += 2) { |
556 | if (get_user(x, (unsigned short *)retaddr + i)) | 560 | if (!(i & 0xF)) |
561 | printk(KERN_EMERG "\n" KERN_EMERG | ||
562 | "0x%08x: ", i); | ||
563 | |||
564 | if (get_user(x, (unsigned short *)i)) | ||
557 | break; | 565 | break; |
558 | #ifndef CONFIG_DEBUG_HWERR | 566 | #ifndef CONFIG_DEBUG_HWERR |
559 | /* If one of the last few instructions was a STI | 567 | /* If one of the last few instructions was a STI |
@@ -561,53 +569,65 @@ void dump_bfin_regs(struct pt_regs *fp, void *retaddr) | |||
561 | * and we just noticed | 569 | * and we just noticed |
562 | */ | 570 | */ |
563 | if (x >= 0x0040 && x <= 0x0047 && i <= 0) | 571 | if (x >= 0x0040 && x <= 0x0047 && i <= 0) |
564 | panic("\n\nWARNING : You should reconfigure the kernel to turn on\n" | 572 | panic("\n\nWARNING : You should reconfigure" |
565 | " 'Hardware error interrupt debugging'\n" | 573 | " the kernel to turn on\n" |
566 | " The rest of this error is meanless\n"); | 574 | " 'Hardware error interrupt" |
575 | " debugging'\n" | ||
576 | " The rest of this error" | ||
577 | " is meanless\n"); | ||
567 | #endif | 578 | #endif |
568 | 579 | if (i == (unsigned int)retaddr) | |
569 | if (i == -8) | 580 | printk("[%04x]", x); |
570 | printk("\n"); | 581 | else |
571 | if (i == 0) | 582 | printk(" %04x ", x); |
572 | printk("X\n"); | ||
573 | printk("%04x ", x); | ||
574 | } | 583 | } |
584 | printk("\n" KERN_EMERG "\n"); | ||
575 | } else | 585 | } else |
576 | printk("Cannot look at the [PC] for it is in unreadable L1 SRAM - sorry\n"); | 586 | printk(KERN_EMERG |
577 | 587 | "Cannot look at the [PC] for it is" | |
578 | printk("\n\n"); | 588 | "in unreadable L1 SRAM - sorry\n"); |
579 | 589 | ||
580 | printk("RETE: %08lx RETN: %08lx RETX: %08lx RETS: %08lx\n", | 590 | |
581 | fp->rete, fp->retn, fp->retx, fp->rets); | 591 | printk(KERN_EMERG |
582 | printk("IPEND: %04lx SYSCFG: %04lx\n", fp->ipend, fp->syscfg); | 592 | "RETE: %08lx RETN: %08lx RETX: %08lx RETS: %08lx\n", |
583 | printk("SEQSTAT: %08lx SP: %08lx\n", (long)fp->seqstat, (long)fp); | 593 | fp->rete, fp->retn, fp->retx, fp->rets); |
584 | printk("R0: %08lx R1: %08lx R2: %08lx R3: %08lx\n", | 594 | printk(KERN_EMERG "IPEND: %04lx SYSCFG: %04lx\n", |
585 | fp->r0, fp->r1, fp->r2, fp->r3); | 595 | fp->ipend, fp->syscfg); |
586 | printk("R4: %08lx R5: %08lx R6: %08lx R7: %08lx\n", | 596 | printk(KERN_EMERG "SEQSTAT: %08lx SP: %08lx\n", |
587 | fp->r4, fp->r5, fp->r6, fp->r7); | 597 | (long)fp->seqstat, (long)fp); |
588 | printk("P0: %08lx P1: %08lx P2: %08lx P3: %08lx\n", | 598 | printk(KERN_EMERG "R0: %08lx R1: %08lx R2: %08lx R3: %08lx\n", |
589 | fp->p0, fp->p1, fp->p2, fp->p3); | 599 | fp->r0, fp->r1, fp->r2, fp->r3); |
590 | printk("P4: %08lx P5: %08lx FP: %08lx\n", fp->p4, fp->p5, fp->fp); | 600 | printk(KERN_EMERG "R4: %08lx R5: %08lx R6: %08lx R7: %08lx\n", |
591 | printk("A0.w: %08lx A0.x: %08lx A1.w: %08lx A1.x: %08lx\n", | 601 | fp->r4, fp->r5, fp->r6, fp->r7); |
592 | fp->a0w, fp->a0x, fp->a1w, fp->a1x); | 602 | printk(KERN_EMERG "P0: %08lx P1: %08lx P2: %08lx P3: %08lx\n", |
593 | 603 | fp->p0, fp->p1, fp->p2, fp->p3); | |
594 | printk("LB0: %08lx LT0: %08lx LC0: %08lx\n", fp->lb0, fp->lt0, | 604 | printk(KERN_EMERG |
595 | fp->lc0); | 605 | "P4: %08lx P5: %08lx FP: %08lx\n", |
596 | printk("LB1: %08lx LT1: %08lx LC1: %08lx\n", fp->lb1, fp->lt1, | 606 | fp->p4, fp->p5, fp->fp); |
597 | fp->lc1); | 607 | printk(KERN_EMERG |
598 | printk("B0: %08lx L0: %08lx M0: %08lx I0: %08lx\n", fp->b0, fp->l0, | 608 | "A0.w: %08lx A0.x: %08lx A1.w: %08lx A1.x: %08lx\n", |
599 | fp->m0, fp->i0); | 609 | fp->a0w, fp->a0x, fp->a1w, fp->a1x); |
600 | printk("B1: %08lx L1: %08lx M1: %08lx I1: %08lx\n", fp->b1, fp->l1, | 610 | |
601 | fp->m1, fp->i1); | 611 | printk(KERN_EMERG "LB0: %08lx LT0: %08lx LC0: %08lx\n", |
602 | printk("B2: %08lx L2: %08lx M2: %08lx I2: %08lx\n", fp->b2, fp->l2, | 612 | fp->lb0, fp->lt0, fp->lc0); |
603 | fp->m2, fp->i2); | 613 | printk(KERN_EMERG "LB1: %08lx LT1: %08lx LC1: %08lx\n", |
604 | printk("B3: %08lx L3: %08lx M3: %08lx I3: %08lx\n", fp->b3, fp->l3, | 614 | fp->lb1, fp->lt1, fp->lc1); |
605 | fp->m3, fp->i3); | 615 | printk(KERN_EMERG "B0: %08lx L0: %08lx M0: %08lx I0: %08lx\n", |
606 | 616 | fp->b0, fp->l0, fp->m0, fp->i0); | |
607 | printk("\nUSP: %08lx ASTAT: %08lx\n", rdusp(), fp->astat); | 617 | printk(KERN_EMERG "B1: %08lx L1: %08lx M1: %08lx I1: %08lx\n", |
618 | fp->b1, fp->l1, fp->m1, fp->i1); | ||
619 | printk(KERN_EMERG "B2: %08lx L2: %08lx M2: %08lx I2: %08lx\n", | ||
620 | fp->b2, fp->l2, fp->m2, fp->i2); | ||
621 | printk(KERN_EMERG "B3: %08lx L3: %08lx M3: %08lx I3: %08lx\n", | ||
622 | fp->b3, fp->l3, fp->m3, fp->i3); | ||
623 | |||
624 | printk(KERN_EMERG "\n" KERN_EMERG "USP: %08lx ASTAT: %08lx\n", | ||
625 | rdusp(), fp->astat); | ||
608 | if ((long)fp->seqstat & SEQSTAT_EXCAUSE) { | 626 | if ((long)fp->seqstat & SEQSTAT_EXCAUSE) { |
609 | printk(KERN_EMERG "DCPLB_FAULT_ADDR=%p\n", (void*)bfin_read_DCPLB_FAULT_ADDR()); | 627 | printk(KERN_EMERG "DCPLB_FAULT_ADDR=%p\n", |
610 | printk(KERN_EMERG "ICPLB_FAULT_ADDR=%p\n", (void*)bfin_read_ICPLB_FAULT_ADDR()); | 628 | (void *)bfin_read_DCPLB_FAULT_ADDR()); |
629 | printk(KERN_EMERG "ICPLB_FAULT_ADDR=%p\n", | ||
630 | (void *)bfin_read_ICPLB_FAULT_ADDR()); | ||
611 | } | 631 | } |
612 | 632 | ||
613 | printk("\n\n"); | 633 | printk("\n\n"); |
@@ -649,8 +669,8 @@ void panic_cplb_error(int cplb_panic, struct pt_regs *fp) | |||
649 | break; | 669 | break; |
650 | } | 670 | } |
651 | 671 | ||
652 | printk(KERN_EMERG "DCPLB_FAULT_ADDR=%p\n", (void*)bfin_read_DCPLB_FAULT_ADDR()); | 672 | printk(KERN_EMERG "DCPLB_FAULT_ADDR=%p\n", (void *)bfin_read_DCPLB_FAULT_ADDR()); |
653 | printk(KERN_EMERG "ICPLB_FAULT_ADDR=%p\n", (void*)bfin_read_ICPLB_FAULT_ADDR()); | 673 | printk(KERN_EMERG "ICPLB_FAULT_ADDR=%p\n", (void *)bfin_read_ICPLB_FAULT_ADDR()); |
654 | dump_bfin_regs(fp, (void *)fp->retx); | 674 | dump_bfin_regs(fp, (void *)fp->retx); |
655 | dump_stack(); | 675 | dump_stack(); |
656 | panic("Unrecoverable event\n"); | 676 | panic("Unrecoverable event\n"); |