diff options
Diffstat (limited to 'arch/blackfin/kernel/traps.c')
-rw-r--r-- | arch/blackfin/kernel/traps.c | 103 |
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 | */ |
637 | static bool get_instruction(unsigned short *val, unsigned short *address) | 640 | static 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", |