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.c103
1 files changed, 40 insertions, 63 deletions
diff --git a/arch/blackfin/kernel/traps.c b/arch/blackfin/kernel/traps.c
index d279552fe9b0..bf2b2d1f8ae5 100644
--- a/arch/blackfin/kernel/traps.c
+++ b/arch/blackfin/kernel/traps.c
@@ -37,6 +37,7 @@
37#include <asm/traps.h> 37#include <asm/traps.h>
38#include <asm/cacheflush.h> 38#include <asm/cacheflush.h>
39#include <asm/cplb.h> 39#include <asm/cplb.h>
40#include <asm/dma.h>
40#include <asm/blackfin.h> 41#include <asm/blackfin.h>
41#include <asm/irq_handler.h> 42#include <asm/irq_handler.h>
42#include <linux/irq.h> 43#include <linux/irq.h>
@@ -211,7 +212,7 @@ asmlinkage void double_fault_c(struct pt_regs *fp)
211 console_verbose(); 212 console_verbose();
212 oops_in_progress = 1; 213 oops_in_progress = 1;
213#ifdef CONFIG_DEBUG_VERBOSE 214#ifdef CONFIG_DEBUG_VERBOSE
214 printk(KERN_EMERG "\n" KERN_EMERG "Double Fault\n"); 215 printk(KERN_EMERG "Double Fault\n");
215#ifdef CONFIG_DEBUG_DOUBLEFAULT_PRINT 216#ifdef CONFIG_DEBUG_DOUBLEFAULT_PRINT
216 if (((long)fp->seqstat & SEQSTAT_EXCAUSE) == VEC_UNCOV) { 217 if (((long)fp->seqstat & SEQSTAT_EXCAUSE) == VEC_UNCOV) {
217 unsigned int cpu = smp_processor_id(); 218 unsigned int cpu = smp_processor_id();
@@ -569,11 +570,12 @@ asmlinkage void trap_c(struct pt_regs *fp)
569 if (kernel_mode_regs(fp) || (current && !current->mm)) { 570 if (kernel_mode_regs(fp) || (current && !current->mm)) {
570 console_verbose(); 571 console_verbose();
571 oops_in_progress = 1; 572 oops_in_progress = 1;
572 if (strerror)
573 verbose_printk(strerror);
574 } 573 }
575 574
576 if (sig != SIGTRAP) { 575 if (sig != SIGTRAP) {
576 if (strerror)
577 verbose_printk(strerror);
578
577 dump_bfin_process(fp); 579 dump_bfin_process(fp);
578 dump_bfin_mem(fp); 580 dump_bfin_mem(fp);
579 show_regs(fp); 581 show_regs(fp);
@@ -582,15 +584,14 @@ asmlinkage void trap_c(struct pt_regs *fp)
582#ifndef CONFIG_DEBUG_BFIN_NO_KERN_HWTRACE 584#ifndef CONFIG_DEBUG_BFIN_NO_KERN_HWTRACE
583 if (trapnr == VEC_CPLB_I_M || trapnr == VEC_CPLB_M) 585 if (trapnr == VEC_CPLB_I_M || trapnr == VEC_CPLB_M)
584 verbose_printk(KERN_NOTICE "No trace since you do not have " 586 verbose_printk(KERN_NOTICE "No trace since you do not have "
585 "CONFIG_DEBUG_BFIN_NO_KERN_HWTRACE enabled\n" 587 "CONFIG_DEBUG_BFIN_NO_KERN_HWTRACE enabled\n\n");
586 KERN_NOTICE "\n");
587 else 588 else
588#endif 589#endif
589 dump_bfin_trace_buffer(); 590 dump_bfin_trace_buffer();
590 591
591 if (oops_in_progress) { 592 if (oops_in_progress) {
592 /* Dump the current kernel stack */ 593 /* Dump the current kernel stack */
593 verbose_printk(KERN_NOTICE "\n" KERN_NOTICE "Kernel Stack\n"); 594 verbose_printk(KERN_NOTICE "Kernel Stack\n");
594 show_stack(current, NULL); 595 show_stack(current, NULL);
595 print_modules(); 596 print_modules();
596#ifndef CONFIG_ACCESS_CHECK 597#ifndef CONFIG_ACCESS_CHECK
@@ -619,7 +620,9 @@ asmlinkage void trap_c(struct pt_regs *fp)
619 force_sig_info(sig, &info, current); 620 force_sig_info(sig, &info, current);
620 } 621 }
621 622
622 if (ANOMALY_05000461 && trapnr == VEC_HWERR && !access_ok(VERIFY_READ, fp->pc, 8)) 623 if ((ANOMALY_05000461 && trapnr == VEC_HWERR && !access_ok(VERIFY_READ, fp->pc, 8)) ||
624 (ANOMALY_05000281 && trapnr == VEC_HWERR) ||
625 (ANOMALY_05000189 && (trapnr == VEC_CPLB_I_VL || trapnr == VEC_CPLB_VL)))
623 fp->pc = SAFE_USER_INSTRUCTION; 626 fp->pc = SAFE_USER_INSTRUCTION;
624 627
625 traps_done: 628 traps_done:
@@ -636,57 +639,30 @@ asmlinkage void trap_c(struct pt_regs *fp)
636 */ 639 */
637static bool get_instruction(unsigned short *val, unsigned short *address) 640static bool get_instruction(unsigned short *val, unsigned short *address)
638{ 641{
639 642 unsigned long addr = (unsigned long)address;
640 unsigned long addr;
641
642 addr = (unsigned long)address;
643 643
644 /* Check for odd addresses */ 644 /* Check for odd addresses */
645 if (addr & 0x1) 645 if (addr & 0x1)
646 return false; 646 return false;
647 647
648 /* Check that things do not wrap around */ 648 /* MMR region will never have instructions */
649 if (addr > (addr + 2)) 649 if (addr >= SYSMMR_BASE)
650 return false; 650 return false;
651 651
652 /* 652 switch (bfin_mem_access_type(addr, 2)) {
653 * Since we are in exception context, we need to do a little address checking 653 case BFIN_MEM_ACCESS_CORE:
654 * We need to make sure we are only accessing valid memory, and 654 case BFIN_MEM_ACCESS_CORE_ONLY:
655 * we don't read something in the async space that can hang forever 655 *val = *address;
656 */ 656 return true;
657 if ((addr >= FIXED_CODE_START && (addr + 2) <= physical_mem_end) || 657 case BFIN_MEM_ACCESS_DMA:
658#if L2_LENGTH != 0 658 dma_memcpy(val, address, 2);
659 (addr >= L2_START && (addr + 2) <= (L2_START + L2_LENGTH)) || 659 return true;
660#endif 660 case BFIN_MEM_ACCESS_ITEST:
661 (addr >= BOOT_ROM_START && (addr + 2) <= (BOOT_ROM_START + BOOT_ROM_LENGTH)) || 661 isram_memcpy(val, address, 2);
662#if L1_DATA_A_LENGTH != 0 662 return true;
663 (addr >= L1_DATA_A_START && (addr + 2) <= (L1_DATA_A_START + L1_DATA_A_LENGTH)) || 663 default: /* invalid access */
664#endif 664 return false;
665#if L1_DATA_B_LENGTH != 0
666 (addr >= L1_DATA_B_START && (addr + 2) <= (L1_DATA_B_START + L1_DATA_B_LENGTH)) ||
667#endif
668 (addr >= L1_SCRATCH_START && (addr + 2) <= (L1_SCRATCH_START + L1_SCRATCH_LENGTH)) ||
669 (!(bfin_read_EBIU_AMBCTL0() & B0RDYEN) &&
670 addr >= ASYNC_BANK0_BASE && (addr + 2) <= (ASYNC_BANK0_BASE + ASYNC_BANK0_SIZE)) ||
671 (!(bfin_read_EBIU_AMBCTL0() & B1RDYEN) &&
672 addr >= ASYNC_BANK1_BASE && (addr + 2) <= (ASYNC_BANK1_BASE + ASYNC_BANK1_SIZE)) ||
673 (!(bfin_read_EBIU_AMBCTL1() & B2RDYEN) &&
674 addr >= ASYNC_BANK2_BASE && (addr + 2) <= (ASYNC_BANK2_BASE + ASYNC_BANK1_SIZE)) ||
675 (!(bfin_read_EBIU_AMBCTL1() & B3RDYEN) &&
676 addr >= ASYNC_BANK3_BASE && (addr + 2) <= (ASYNC_BANK3_BASE + ASYNC_BANK1_SIZE))) {
677 *val = *address;
678 return true;
679 }
680
681#if L1_CODE_LENGTH != 0
682 if (addr >= L1_CODE_START && (addr + 2) <= (L1_CODE_START + L1_CODE_LENGTH)) {
683 isram_memcpy(val, address, 2);
684 return true;
685 } 665 }
686#endif
687
688
689 return false;
690} 666}
691 667
692/* 668/*
@@ -932,7 +908,7 @@ void show_stack(struct task_struct *task, unsigned long *stack)
932 908
933 ret_addr = 0; 909 ret_addr = 0;
934 if (!j && i % 8 == 0) 910 if (!j && i % 8 == 0)
935 printk("\n" KERN_NOTICE "%p:",addr); 911 printk(KERN_NOTICE "%p:",addr);
936 912
937 /* if it is an odd address, or zero, just skip it */ 913 /* if it is an odd address, or zero, just skip it */
938 if (*addr & 0x1 || !*addr) 914 if (*addr & 0x1 || !*addr)
@@ -1022,9 +998,9 @@ void dump_bfin_process(struct pt_regs *fp)
1022 998
1023 printk(KERN_NOTICE "CPU = %d\n", current_thread_info()->cpu); 999 printk(KERN_NOTICE "CPU = %d\n", current_thread_info()->cpu);
1024 if (!((unsigned long)current->mm & 0x3) && (unsigned long)current->mm >= FIXED_CODE_START) 1000 if (!((unsigned long)current->mm & 0x3) && (unsigned long)current->mm >= FIXED_CODE_START)
1025 verbose_printk(KERN_NOTICE "TEXT = 0x%p-0x%p DATA = 0x%p-0x%p\n" 1001 verbose_printk(KERN_NOTICE
1026 KERN_NOTICE " BSS = 0x%p-0x%p USER-STACK = 0x%p\n" 1002 "TEXT = 0x%p-0x%p DATA = 0x%p-0x%p\n"
1027 KERN_NOTICE "\n", 1003 " BSS = 0x%p-0x%p USER-STACK = 0x%p\n\n",
1028 (void *)current->mm->start_code, 1004 (void *)current->mm->start_code,
1029 (void *)current->mm->end_code, 1005 (void *)current->mm->end_code,
1030 (void *)current->mm->start_data, 1006 (void *)current->mm->start_data,
@@ -1035,8 +1011,8 @@ void dump_bfin_process(struct pt_regs *fp)
1035 else 1011 else
1036 verbose_printk(KERN_NOTICE "invalid mm\n"); 1012 verbose_printk(KERN_NOTICE "invalid mm\n");
1037 } else 1013 } else
1038 verbose_printk(KERN_NOTICE "\n" KERN_NOTICE 1014 verbose_printk(KERN_NOTICE
1039 "No Valid process in current context\n"); 1015 "No Valid process in current context\n");
1040#endif 1016#endif
1041} 1017}
1042 1018
@@ -1054,7 +1030,7 @@ void dump_bfin_mem(struct pt_regs *fp)
1054 addr < (unsigned short *)((unsigned long)erraddr & ~0xF) + 0x10; 1030 addr < (unsigned short *)((unsigned long)erraddr & ~0xF) + 0x10;
1055 addr++) { 1031 addr++) {
1056 if (!((unsigned long)addr & 0xF)) 1032 if (!((unsigned long)addr & 0xF))
1057 verbose_printk("\n" KERN_NOTICE "0x%p: ", addr); 1033 verbose_printk(KERN_NOTICE "0x%p: ", addr);
1058 1034
1059 if (!get_instruction(&val, addr)) { 1035 if (!get_instruction(&val, addr)) {
1060 val = 0; 1036 val = 0;
@@ -1082,9 +1058,9 @@ void dump_bfin_mem(struct pt_regs *fp)
1082 oops_in_progress)){ 1058 oops_in_progress)){
1083 verbose_printk(KERN_NOTICE "Looks like this was a deferred error - sorry\n"); 1059 verbose_printk(KERN_NOTICE "Looks like this was a deferred error - sorry\n");
1084#ifndef CONFIG_DEBUG_HWERR 1060#ifndef CONFIG_DEBUG_HWERR
1085 verbose_printk(KERN_NOTICE "The remaining message may be meaningless\n" 1061 verbose_printk(KERN_NOTICE
1086 KERN_NOTICE "You should enable CONFIG_DEBUG_HWERR to get a" 1062"The remaining message may be meaningless\n"
1087 " better idea where it came from\n"); 1063"You should enable CONFIG_DEBUG_HWERR to get a better idea where it came from\n");
1088#else 1064#else
1089 /* If we are handling only one peripheral interrupt 1065 /* If we are handling only one peripheral interrupt
1090 * and current mm and pid are valid, and the last error 1066 * and current mm and pid are valid, and the last error
@@ -1140,9 +1116,10 @@ void show_regs(struct pt_regs *fp)
1140 1116
1141 verbose_printk(KERN_NOTICE "%s", linux_banner); 1117 verbose_printk(KERN_NOTICE "%s", linux_banner);
1142 1118
1143 verbose_printk(KERN_NOTICE "\n" KERN_NOTICE "SEQUENCER STATUS:\t\t%s\n", print_tainted()); 1119 verbose_printk(KERN_NOTICE "\nSEQUENCER STATUS:\t\t%s\n",
1120 print_tainted());
1144 verbose_printk(KERN_NOTICE " SEQSTAT: %08lx IPEND: %04lx SYSCFG: %04lx\n", 1121 verbose_printk(KERN_NOTICE " SEQSTAT: %08lx IPEND: %04lx SYSCFG: %04lx\n",
1145 (long)fp->seqstat, fp->ipend, fp->syscfg); 1122 (long)fp->seqstat, fp->ipend, fp->syscfg);
1146 if ((fp->seqstat & SEQSTAT_EXCAUSE) == VEC_HWERR) { 1123 if ((fp->seqstat & SEQSTAT_EXCAUSE) == VEC_HWERR) {
1147 verbose_printk(KERN_NOTICE " HWERRCAUSE: 0x%lx\n", 1124 verbose_printk(KERN_NOTICE " HWERRCAUSE: 0x%lx\n",
1148 (fp->seqstat & SEQSTAT_HWERRCAUSE) >> 14); 1125 (fp->seqstat & SEQSTAT_HWERRCAUSE) >> 14);
@@ -1210,7 +1187,7 @@ unlock:
1210 verbose_printk(KERN_NOTICE "ICPLB_FAULT_ADDR: %s\n", buf); 1187 verbose_printk(KERN_NOTICE "ICPLB_FAULT_ADDR: %s\n", buf);
1211 } 1188 }
1212 1189
1213 verbose_printk(KERN_NOTICE "\n" KERN_NOTICE "PROCESSOR STATE:\n"); 1190 verbose_printk(KERN_NOTICE "PROCESSOR STATE:\n");
1214 verbose_printk(KERN_NOTICE " R0 : %08lx R1 : %08lx R2 : %08lx R3 : %08lx\n", 1191 verbose_printk(KERN_NOTICE " R0 : %08lx R1 : %08lx R2 : %08lx R3 : %08lx\n",
1215 fp->r0, fp->r1, fp->r2, fp->r3); 1192 fp->r0, fp->r1, fp->r2, fp->r3);
1216 verbose_printk(KERN_NOTICE " R4 : %08lx R5 : %08lx R6 : %08lx R7 : %08lx\n", 1193 verbose_printk(KERN_NOTICE " R4 : %08lx R5 : %08lx R6 : %08lx R7 : %08lx\n",