aboutsummaryrefslogtreecommitdiffstats
path: root/arch/blackfin/kernel/traps.c
diff options
context:
space:
mode:
authorRobin Getz <robin.getz@analog.com>2008-01-27 02:38:56 -0500
committerBryan Wu <bryan.wu@analog.com>2008-01-27 02:38:56 -0500
commit13fe24f37df20e580a5a364e67ec8cf3219d8f8c (patch)
treec790da8a840c6fdc3e6f5eacccadede92e329d7c /arch/blackfin/kernel/traps.c
parentf53e86760e10abbe7ee98a5b3cb270fa6426fcdb (diff)
[Blackfin] arch: fix bug - trap_tests fails to recover on some tests.
http://blackfin.uclinux.org/gf/project/uclinux-dist/tracker/?action=TrackerItemEdit&tracker_item_id=3719 When the CPLBs get a miss, we do: - find a victim in the HW table - remove the victim - find the replacement in the software table - put it into the HW table. If we can't find a replacement in the software table, we accidently leave a duplicate in the HW table. This patch ensures that duplicate is marked as not valid. What we should do is find the replacement in the software table, before we find a victim in the HW table - but its too late in the release cycle to do that much restructuring of this code. Rather that duplicate code, connect Hardware Errors (irq5) into trap_c, so user space processes get killed properly. The rest of irq_panic() can be moved into traps.c (later) There is still a small corner case that causes problems when a pheriperal interrupt goes off a single cycle before a user space hardware error. This causes a kernel panic, rather than the user space process being killed. But, this checkin makes things work in 99.9% of the cases, and is a vast improvement from what is there today (which fails 100% of the time). Signed-off-by: Robin Getz <robin.getz@analog.com> Signed-off-by: Bryan Wu <bryan.wu@analog.com>
Diffstat (limited to 'arch/blackfin/kernel/traps.c')
-rw-r--r--arch/blackfin/kernel/traps.c54
1 files changed, 46 insertions, 8 deletions
diff --git a/arch/blackfin/kernel/traps.c b/arch/blackfin/kernel/traps.c
index 21a55ef19cbd..4be5ff0be60f 100644
--- a/arch/blackfin/kernel/traps.c
+++ b/arch/blackfin/kernel/traps.c
@@ -433,6 +433,36 @@ asmlinkage void trap_c(struct pt_regs *fp)
433 /* 0x3D - Reserved, Caught by default */ 433 /* 0x3D - Reserved, Caught by default */
434 /* 0x3E - Reserved, Caught by default */ 434 /* 0x3E - Reserved, Caught by default */
435 /* 0x3F - Reserved, Caught by default */ 435 /* 0x3F - Reserved, Caught by default */
436 case VEC_HWERR:
437 info.si_code = BUS_ADRALN;
438 sig = SIGBUS;
439 switch (fp->seqstat & SEQSTAT_HWERRCAUSE) {
440 /* System MMR Error */
441 case (SEQSTAT_HWERRCAUSE_SYSTEM_MMR):
442 info.si_code = BUS_ADRALN;
443 sig = SIGBUS;
444 printk(KERN_NOTICE HWC_x2(KERN_NOTICE));
445 break;
446 /* External Memory Addressing Error */
447 case (SEQSTAT_HWERRCAUSE_EXTERN_ADDR):
448 info.si_code = BUS_ADRERR;
449 sig = SIGBUS;
450 printk(KERN_NOTICE HWC_x3(KERN_NOTICE));
451 break;
452 /* Performance Monitor Overflow */
453 case (SEQSTAT_HWERRCAUSE_PERF_FLOW):
454 printk(KERN_NOTICE HWC_x12(KERN_NOTICE));
455 break;
456 /* RAISE 5 instruction */
457 case (SEQSTAT_HWERRCAUSE_RAISE_5):
458 printk(KERN_NOTICE HWC_x18(KERN_NOTICE));
459 break;
460 default: /* Reserved */
461 printk(KERN_NOTICE HWC_default(KERN_NOTICE));
462 break;
463 }
464 CHK_DEBUGGER_TRAP();
465 break;
436 default: 466 default:
437 info.si_code = TRAP_ILLTRAP; 467 info.si_code = TRAP_ILLTRAP;
438 sig = SIGTRAP; 468 sig = SIGTRAP;
@@ -447,7 +477,11 @@ asmlinkage void trap_c(struct pt_regs *fp)
447 if (sig != SIGTRAP) { 477 if (sig != SIGTRAP) {
448 unsigned long stack; 478 unsigned long stack;
449 dump_bfin_process(fp); 479 dump_bfin_process(fp);
450 dump_bfin_mem((void *)fp->retx); 480 /* Is it an interrupt, or an exception? */
481 if (trapnr == VEC_HWERR)
482 dump_bfin_mem((void *)fp->pc);
483 else
484 dump_bfin_mem((void *)fp->retx);
451 show_regs(fp); 485 show_regs(fp);
452 486
453 /* Print out the trace buffer if it makes sense */ 487 /* Print out the trace buffer if it makes sense */
@@ -672,12 +706,11 @@ void dump_bfin_mem(void *retaddr)
672 * context, which should mean an oops is happening 706 * context, which should mean an oops is happening
673 */ 707 */
674 if (oops_in_progress && x >= 0x0040 && x <= 0x0047 && i <= 0) 708 if (oops_in_progress && x >= 0x0040 && x <= 0x0047 && i <= 0)
675 panic("\n\nWARNING : You should reconfigure" 709 printk(KERN_EMERG "\n"
710 KERN_EMERG "WARNING : You should reconfigure"
676 " the kernel to turn on\n" 711 " the kernel to turn on\n"
677 " 'Hardware error interrupt" 712 KERN_EMERG " 'Hardware error interrupt debugging'\n"
678 " debugging'\n" 713 KERN_EMERG " The rest of this error is meanless\n");
679 " The rest of this error"
680 " is meanless\n");
681#endif 714#endif
682 if (i == (unsigned int)retaddr) 715 if (i == (unsigned int)retaddr)
683 printk("[%04x]", x); 716 printk("[%04x]", x);
@@ -698,6 +731,10 @@ void show_regs(struct pt_regs *fp)
698 printk(KERN_NOTICE "\n" KERN_NOTICE "SEQUENCER STATUS:\n"); 731 printk(KERN_NOTICE "\n" KERN_NOTICE "SEQUENCER STATUS:\n");
699 printk(KERN_NOTICE " SEQSTAT: %08lx IPEND: %04lx SYSCFG: %04lx\n", 732 printk(KERN_NOTICE " SEQSTAT: %08lx IPEND: %04lx SYSCFG: %04lx\n",
700 (long)fp->seqstat, fp->ipend, fp->syscfg); 733 (long)fp->seqstat, fp->ipend, fp->syscfg);
734 printk(KERN_NOTICE " HWERRCAUSE: 0x%lx\n",
735 (fp->seqstat & SEQSTAT_HWERRCAUSE) >> 14);
736 printk(KERN_NOTICE " EXCAUSE : 0x%lx\n",
737 fp->seqstat & SEQSTAT_EXCAUSE);
701 738
702 decode_address(buf, fp->rete); 739 decode_address(buf, fp->rete);
703 printk(KERN_NOTICE " RETE: %s\n", buf); 740 printk(KERN_NOTICE " RETE: %s\n", buf);
@@ -708,9 +745,10 @@ void show_regs(struct pt_regs *fp)
708 decode_address(buf, fp->rets); 745 decode_address(buf, fp->rets);
709 printk(KERN_NOTICE " RETS: %s\n", buf); 746 printk(KERN_NOTICE " RETS: %s\n", buf);
710 decode_address(buf, fp->pc); 747 decode_address(buf, fp->pc);
711 printk(KERN_NOTICE " PC: %s\n", buf); 748 printk(KERN_NOTICE " PC : %s\n", buf);
712 749
713 if ((long)fp->seqstat & SEQSTAT_EXCAUSE) { 750 if (((long)fp->seqstat & SEQSTAT_EXCAUSE) &&
751 (((long)fp->seqstat & SEQSTAT_EXCAUSE) != VEC_HWERR)) {
714 decode_address(buf, bfin_read_DCPLB_FAULT_ADDR()); 752 decode_address(buf, bfin_read_DCPLB_FAULT_ADDR());
715 printk(KERN_NOTICE "DCPLB_FAULT_ADDR: %s\n", buf); 753 printk(KERN_NOTICE "DCPLB_FAULT_ADDR: %s\n", buf);
716 decode_address(buf, bfin_read_ICPLB_FAULT_ADDR()); 754 decode_address(buf, bfin_read_ICPLB_FAULT_ADDR());