aboutsummaryrefslogtreecommitdiffstats
path: root/arch/blackfin/kernel/traps.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/blackfin/kernel/traps.c')
-rw-r--r--arch/blackfin/kernel/traps.c212
1 files changed, 155 insertions, 57 deletions
diff --git a/arch/blackfin/kernel/traps.c b/arch/blackfin/kernel/traps.c
index 21a55ef19cbd..66b5f3e3ae2a 100644
--- a/arch/blackfin/kernel/traps.c
+++ b/arch/blackfin/kernel/traps.c
@@ -36,8 +36,10 @@
36#include <asm/cacheflush.h> 36#include <asm/cacheflush.h>
37#include <asm/blackfin.h> 37#include <asm/blackfin.h>
38#include <asm/irq_handler.h> 38#include <asm/irq_handler.h>
39#include <linux/irq.h>
39#include <asm/trace.h> 40#include <asm/trace.h>
40#include <asm/fixed_code.h> 41#include <asm/fixed_code.h>
42#include <asm/dma.h>
41 43
42#ifdef CONFIG_KGDB 44#ifdef CONFIG_KGDB
43# include <linux/debugger.h> 45# include <linux/debugger.h>
@@ -170,7 +172,7 @@ asmlinkage void double_fault_c(struct pt_regs *fp)
170 oops_in_progress = 1; 172 oops_in_progress = 1;
171 printk(KERN_EMERG "\n" KERN_EMERG "Double Fault\n"); 173 printk(KERN_EMERG "\n" KERN_EMERG "Double Fault\n");
172 dump_bfin_process(fp); 174 dump_bfin_process(fp);
173 dump_bfin_mem((void *)fp->retx); 175 dump_bfin_mem(fp);
174 show_regs(fp); 176 show_regs(fp);
175 panic("Double Fault - unrecoverable event\n"); 177 panic("Double Fault - unrecoverable event\n");
176 178
@@ -195,9 +197,13 @@ asmlinkage void trap_c(struct pt_regs *fp)
195 * we will kernel panic, so the system reboots. 197 * we will kernel panic, so the system reboots.
196 * If KGDB is enabled, don't set this for kernel breakpoints 198 * If KGDB is enabled, don't set this for kernel breakpoints
197 */ 199 */
198 if ((bfin_read_IPEND() & 0xFFC0) 200
201 /* TODO: check to see if we are in some sort of deferred HWERR
202 * that we should be able to recover from, not kernel panic
203 */
204 if ((bfin_read_IPEND() & 0xFFC0) && (trapnr != VEC_STEP)
199#ifdef CONFIG_KGDB 205#ifdef CONFIG_KGDB
200 && trapnr != VEC_EXCPT02 206 && (trapnr != VEC_EXCPT02)
201#endif 207#endif
202 ){ 208 ){
203 console_verbose(); 209 console_verbose();
@@ -433,6 +439,36 @@ asmlinkage void trap_c(struct pt_regs *fp)
433 /* 0x3D - Reserved, Caught by default */ 439 /* 0x3D - Reserved, Caught by default */
434 /* 0x3E - Reserved, Caught by default */ 440 /* 0x3E - Reserved, Caught by default */
435 /* 0x3F - Reserved, Caught by default */ 441 /* 0x3F - Reserved, Caught by default */
442 case VEC_HWERR:
443 info.si_code = BUS_ADRALN;
444 sig = SIGBUS;
445 switch (fp->seqstat & SEQSTAT_HWERRCAUSE) {
446 /* System MMR Error */
447 case (SEQSTAT_HWERRCAUSE_SYSTEM_MMR):
448 info.si_code = BUS_ADRALN;
449 sig = SIGBUS;
450 printk(KERN_NOTICE HWC_x2(KERN_NOTICE));
451 break;
452 /* External Memory Addressing Error */
453 case (SEQSTAT_HWERRCAUSE_EXTERN_ADDR):
454 info.si_code = BUS_ADRERR;
455 sig = SIGBUS;
456 printk(KERN_NOTICE HWC_x3(KERN_NOTICE));
457 break;
458 /* Performance Monitor Overflow */
459 case (SEQSTAT_HWERRCAUSE_PERF_FLOW):
460 printk(KERN_NOTICE HWC_x12(KERN_NOTICE));
461 break;
462 /* RAISE 5 instruction */
463 case (SEQSTAT_HWERRCAUSE_RAISE_5):
464 printk(KERN_NOTICE HWC_x18(KERN_NOTICE));
465 break;
466 default: /* Reserved */
467 printk(KERN_NOTICE HWC_default(KERN_NOTICE));
468 break;
469 }
470 CHK_DEBUGGER_TRAP();
471 break;
436 default: 472 default:
437 info.si_code = TRAP_ILLTRAP; 473 info.si_code = TRAP_ILLTRAP;
438 sig = SIGTRAP; 474 sig = SIGTRAP;
@@ -447,7 +483,7 @@ asmlinkage void trap_c(struct pt_regs *fp)
447 if (sig != SIGTRAP) { 483 if (sig != SIGTRAP) {
448 unsigned long stack; 484 unsigned long stack;
449 dump_bfin_process(fp); 485 dump_bfin_process(fp);
450 dump_bfin_mem((void *)fp->retx); 486 dump_bfin_mem(fp);
451 show_regs(fp); 487 show_regs(fp);
452 488
453 /* Print out the trace buffer if it makes sense */ 489 /* Print out the trace buffer if it makes sense */
@@ -461,6 +497,7 @@ asmlinkage void trap_c(struct pt_regs *fp)
461 dump_bfin_trace_buffer(); 497 dump_bfin_trace_buffer();
462 show_stack(current, &stack); 498 show_stack(current, &stack);
463 if (oops_in_progress) { 499 if (oops_in_progress) {
500 print_modules();
464#ifndef CONFIG_ACCESS_CHECK 501#ifndef CONFIG_ACCESS_CHECK
465 printk(KERN_EMERG "Please turn on " 502 printk(KERN_EMERG "Please turn on "
466 "CONFIG_ACCESS_CHECK\n"); 503 "CONFIG_ACCESS_CHECK\n");
@@ -474,13 +511,6 @@ asmlinkage void trap_c(struct pt_regs *fp)
474 info.si_addr = (void *)fp->pc; 511 info.si_addr = (void *)fp->pc;
475 force_sig_info(sig, &info, current); 512 force_sig_info(sig, &info, current);
476 513
477 /* Ensure that bad return addresses don't end up in an infinite
478 * loop, due to speculative loads/reads. This needs to be done after
479 * the signal has been sent.
480 */
481 if (trapnr == VEC_CPLB_I_M && sig != SIGTRAP)
482 fp->pc = SAFE_USER_INSTRUCTION;
483
484 trace_buffer_restore(j); 514 trace_buffer_restore(j);
485 return; 515 return;
486} 516}
@@ -616,8 +646,10 @@ void dump_bfin_process(struct pt_regs *fp)
616 if (oops_in_progress) 646 if (oops_in_progress)
617 printk(KERN_EMERG "Kernel OOPS in progress\n"); 647 printk(KERN_EMERG "Kernel OOPS in progress\n");
618 648
619 if (context & 0x0020) 649 if (context & 0x0020 && (fp->seqstat & SEQSTAT_EXCAUSE) == VEC_HWERR)
620 printk(KERN_NOTICE "Deferred excecption or HW Error context\n"); 650 printk(KERN_NOTICE "HW Error context\n");
651 else if (context & 0x0020)
652 printk(KERN_NOTICE "Defered Exception context\n");
621 else if (context & 0x3FC0) 653 else if (context & 0x3FC0)
622 printk(KERN_NOTICE "Interrupt context\n"); 654 printk(KERN_NOTICE "Interrupt context\n");
623 else if (context & 0x4000) 655 else if (context & 0x4000)
@@ -645,59 +677,124 @@ void dump_bfin_process(struct pt_regs *fp)
645 "No Valid process in current context\n"); 677 "No Valid process in current context\n");
646} 678}
647 679
648void dump_bfin_mem(void *retaddr) 680void dump_bfin_mem(struct pt_regs *fp)
649{ 681{
682 unsigned short *addr, *erraddr, val = 0, err = 0;
683 char sti = 0, buf[6];
650 684
651 if (retaddr >= (void *)FIXED_CODE_START && retaddr < (void *)physical_mem_end 685 if (unlikely((fp->seqstat & SEQSTAT_EXCAUSE) == VEC_HWERR))
652#if L1_CODE_LENGTH != 0 686 erraddr = (void *)fp->pc;
653 /* FIXME: Copy the code out of L1 Instruction SRAM through dma 687 else
654 memcpy. */ 688 erraddr = (void *)fp->retx;
655 && !(retaddr >= (void *)L1_CODE_START 689
656 && retaddr < (void *)(L1_CODE_START + L1_CODE_LENGTH)) 690 printk(KERN_NOTICE "return address: [0x%p]; contents of:", erraddr);
657#endif 691
658 ) { 692 for (addr = (unsigned short *)((unsigned long)erraddr & ~0xF) - 0x10;
659 int i = ((unsigned int)retaddr & 0xFFFFFFF0) - 32; 693 addr < (unsigned short *)((unsigned long)erraddr & ~0xF) + 0x10;
660 unsigned short x = 0; 694 addr++) {
661 printk(KERN_NOTICE "return address: [0x%p]; contents of:", retaddr); 695 if (!((unsigned long)addr & 0xF))
662 for (; i < ((unsigned int)retaddr & 0xFFFFFFF0) + 32; i += 2) { 696 printk("\n" KERN_NOTICE "0x%p: ", addr);
663 if (!(i & 0xF)) 697
664 printk("\n" KERN_NOTICE "0x%08x: ", i); 698 if (get_user(val, addr)) {
665 699 if (addr >= (unsigned short *)L1_CODE_START &&
666 if (get_user(x, (unsigned short *)i)) 700 addr < (unsigned short *)(L1_CODE_START + L1_CODE_LENGTH)) {
667 break; 701 dma_memcpy(&val, addr, sizeof(val));
702 sprintf(buf, "%04x", val);
703 } else if (addr >= (unsigned short *)FIXED_CODE_START &&
704 addr <= (unsigned short *)memory_start) {
705 val = bfin_read16(addr);
706 sprintf(buf, "%04x", val);
707 } else {
708 val = 0;
709 sprintf(buf, "????");
710 }
711 } else
712 sprintf(buf, "%04x", val);
713
714 if (addr == erraddr) {
715 printk("[%s]", buf);
716 err = val;
717 } else
718 printk(" %s ", buf);
719
720 /* Do any previous instructions turn on interrupts? */
721 if (addr <= erraddr && /* in the past */
722 ((val >= 0x0040 && val <= 0x0047) || /* STI instruction */
723 val == 0x017b)) /* [SP++] = RETI */
724 sti = 1;
725 }
726
727 printk("\n");
728
729 /* Hardware error interrupts can be deferred */
730 if (unlikely(sti && (fp->seqstat & SEQSTAT_EXCAUSE) == VEC_HWERR &&
731 oops_in_progress)){
732 printk(KERN_NOTICE "Looks like this was a deferred error - sorry\n");
668#ifndef CONFIG_DEBUG_HWERR 733#ifndef CONFIG_DEBUG_HWERR
669 /* If one of the last few instructions was a STI 734 printk(KERN_NOTICE "The remaining message may be meaningless\n"
670 * it is likely that the error occured awhile ago 735 KERN_NOTICE "You should enable CONFIG_DEBUG_HWERR to get a"
671 * and we just noticed. This only happens in kernel 736 " better idea where it came from\n");
672 * context, which should mean an oops is happening 737#else
673 */ 738 /* If we are handling only one peripheral interrupt
674 if (oops_in_progress && x >= 0x0040 && x <= 0x0047 && i <= 0) 739 * and current mm and pid are valid, and the last error
675 panic("\n\nWARNING : You should reconfigure" 740 * was in that user space process's text area
676 " the kernel to turn on\n" 741 * print it out - because that is where the problem exists
677 " 'Hardware error interrupt" 742 */
678 " debugging'\n" 743 if ((!(((fp)->ipend & ~0x30) & (((fp)->ipend & ~0x30) - 1))) &&
679 " The rest of this error" 744 (current->pid && current->mm)) {
680 " is meanless\n"); 745 /* And the last RETI points to the current userspace context */
681#endif 746 if ((fp + 1)->pc >= current->mm->start_code &&
682 if (i == (unsigned int)retaddr) 747 (fp + 1)->pc <= current->mm->end_code) {
683 printk("[%04x]", x); 748 printk(KERN_NOTICE "It might be better to look around here : \n");
684 else 749 printk(KERN_NOTICE "-------------------------------------------\n");
685 printk(" %04x ", x); 750 show_regs(fp + 1);
751 printk(KERN_NOTICE "-------------------------------------------\n");
752 }
686 } 753 }
687 printk("\n"); 754#endif
688 } else 755 }
689 printk("\n" KERN_NOTICE
690 "Cannot look at the [PC] <%p> for it is"
691 " in unreadable memory - sorry\n", retaddr);
692} 756}
693 757
694void show_regs(struct pt_regs *fp) 758void show_regs(struct pt_regs *fp)
695{ 759{
696 char buf [150]; 760 char buf [150];
761 struct irqaction *action;
762 unsigned int i;
763 unsigned long flags;
697 764
698 printk(KERN_NOTICE "\n" KERN_NOTICE "SEQUENCER STATUS:\n"); 765 printk(KERN_NOTICE "\n" KERN_NOTICE "SEQUENCER STATUS:\t\t%s\n", print_tainted());
699 printk(KERN_NOTICE " SEQSTAT: %08lx IPEND: %04lx SYSCFG: %04lx\n", 766 printk(KERN_NOTICE " SEQSTAT: %08lx IPEND: %04lx SYSCFG: %04lx\n",
700 (long)fp->seqstat, fp->ipend, fp->syscfg); 767 (long)fp->seqstat, fp->ipend, fp->syscfg);
768 printk(KERN_NOTICE " HWERRCAUSE: 0x%lx\n",
769 (fp->seqstat & SEQSTAT_HWERRCAUSE) >> 14);
770 printk(KERN_NOTICE " EXCAUSE : 0x%lx\n",
771 fp->seqstat & SEQSTAT_EXCAUSE);
772 for (i = 6; i <= 15 ; i++) {
773 if (fp->ipend & (1 << i)) {
774 decode_address(buf, bfin_read32(EVT0 + 4*i));
775 printk(KERN_NOTICE " physical IVG%i asserted : %s\n", i, buf);
776 }
777 }
778
779 /* if no interrupts are going off, don't print this out */
780 if (fp->ipend & ~0x3F) {
781 for (i = 0; i < (NR_IRQS - 1); i++) {
782 spin_lock_irqsave(&irq_desc[i].lock, flags);
783 action = irq_desc[i].action;
784 if (!action)
785 goto unlock;
786
787 decode_address(buf, (unsigned int)action->handler);
788 printk(KERN_NOTICE " logical irq %3d mapped : %s", i, buf);
789 for (action = action->next; action; action = action->next) {
790 decode_address(buf, (unsigned int)action->handler);
791 printk(", %s", buf);
792 }
793 printk("\n");
794unlock:
795 spin_unlock_irqrestore(&irq_desc[i].lock, flags);
796 }
797 }
701 798
702 decode_address(buf, fp->rete); 799 decode_address(buf, fp->rete);
703 printk(KERN_NOTICE " RETE: %s\n", buf); 800 printk(KERN_NOTICE " RETE: %s\n", buf);
@@ -708,9 +805,10 @@ void show_regs(struct pt_regs *fp)
708 decode_address(buf, fp->rets); 805 decode_address(buf, fp->rets);
709 printk(KERN_NOTICE " RETS: %s\n", buf); 806 printk(KERN_NOTICE " RETS: %s\n", buf);
710 decode_address(buf, fp->pc); 807 decode_address(buf, fp->pc);
711 printk(KERN_NOTICE " PC: %s\n", buf); 808 printk(KERN_NOTICE " PC : %s\n", buf);
712 809
713 if ((long)fp->seqstat & SEQSTAT_EXCAUSE) { 810 if (((long)fp->seqstat & SEQSTAT_EXCAUSE) &&
811 (((long)fp->seqstat & SEQSTAT_EXCAUSE) != VEC_HWERR)) {
714 decode_address(buf, bfin_read_DCPLB_FAULT_ADDR()); 812 decode_address(buf, bfin_read_DCPLB_FAULT_ADDR());
715 printk(KERN_NOTICE "DCPLB_FAULT_ADDR: %s\n", buf); 813 printk(KERN_NOTICE "DCPLB_FAULT_ADDR: %s\n", buf);
716 decode_address(buf, bfin_read_ICPLB_FAULT_ADDR()); 814 decode_address(buf, bfin_read_ICPLB_FAULT_ADDR());
@@ -824,7 +922,7 @@ void panic_cplb_error(int cplb_panic, struct pt_regs *fp)
824 printk(KERN_EMERG "DCPLB_FAULT_ADDR=%p\n", (void *)bfin_read_DCPLB_FAULT_ADDR()); 922 printk(KERN_EMERG "DCPLB_FAULT_ADDR=%p\n", (void *)bfin_read_DCPLB_FAULT_ADDR());
825 printk(KERN_EMERG "ICPLB_FAULT_ADDR=%p\n", (void *)bfin_read_ICPLB_FAULT_ADDR()); 923 printk(KERN_EMERG "ICPLB_FAULT_ADDR=%p\n", (void *)bfin_read_ICPLB_FAULT_ADDR());
826 dump_bfin_process(fp); 924 dump_bfin_process(fp);
827 dump_bfin_mem((void *)fp->retx); 925 dump_bfin_mem(fp);
828 show_regs(fp); 926 show_regs(fp);
829 dump_stack(); 927 dump_stack();
830 panic("Unrecoverable event\n"); 928 panic("Unrecoverable event\n");