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.c83
1 files changed, 71 insertions, 12 deletions
diff --git a/arch/blackfin/kernel/traps.c b/arch/blackfin/kernel/traps.c
index 6b7325d634af..ba70c4bc2699 100644
--- a/arch/blackfin/kernel/traps.c
+++ b/arch/blackfin/kernel/traps.c
@@ -119,6 +119,15 @@ static void decode_address(char *buf, unsigned long address)
119 return; 119 return;
120 } 120 }
121 121
122 /*
123 * Don't walk any of the vmas if we are oopsing, it has been known
124 * to cause problems - corrupt vmas (kernel crashes) cause double faults
125 */
126 if (oops_in_progress) {
127 strcat(buf, "/* kernel dynamic memory (maybe user-space) */");
128 return;
129 }
130
122 /* looks like we're off in user-land, so let's walk all the 131 /* looks like we're off in user-land, so let's walk all the
123 * mappings of all our processes and see if we can't be a whee 132 * mappings of all our processes and see if we can't be a whee
124 * bit more specific 133 * bit more specific
@@ -129,6 +138,12 @@ static void decode_address(char *buf, unsigned long address)
129 if (!mm) 138 if (!mm)
130 continue; 139 continue;
131 140
141 if (!down_read_trylock(&mm->mmap_sem)) {
142 if (!in_atomic)
143 mmput(mm);
144 continue;
145 }
146
132 for (n = rb_first(&mm->mm_rb); n; n = rb_next(n)) { 147 for (n = rb_first(&mm->mm_rb); n; n = rb_next(n)) {
133 struct vm_area_struct *vma; 148 struct vm_area_struct *vma;
134 149
@@ -168,6 +183,7 @@ static void decode_address(char *buf, unsigned long address)
168 sprintf(buf, "[ %s vma:0x%lx-0x%lx]", 183 sprintf(buf, "[ %s vma:0x%lx-0x%lx]",
169 name, vma->vm_start, vma->vm_end); 184 name, vma->vm_start, vma->vm_end);
170 185
186 up_read(&mm->mmap_sem);
171 if (!in_atomic) 187 if (!in_atomic)
172 mmput(mm); 188 mmput(mm);
173 189
@@ -177,11 +193,16 @@ static void decode_address(char *buf, unsigned long address)
177 goto done; 193 goto done;
178 } 194 }
179 } 195 }
196
197 up_read(&mm->mmap_sem);
180 if (!in_atomic) 198 if (!in_atomic)
181 mmput(mm); 199 mmput(mm);
182 } 200 }
183 201
184 /* we were unable to find this address anywhere */ 202 /*
203 * we were unable to find this address anywhere,
204 * or some MMs were skipped because they were in use.
205 */
185 sprintf(buf, "/* kernel dynamic memory */"); 206 sprintf(buf, "/* kernel dynamic memory */");
186 207
187done: 208done:
@@ -239,9 +260,7 @@ asmlinkage notrace void trap_c(struct pt_regs *fp)
239#ifdef CONFIG_DEBUG_BFIN_HWTRACE_ON 260#ifdef CONFIG_DEBUG_BFIN_HWTRACE_ON
240 int j; 261 int j;
241#endif 262#endif
242#ifdef CONFIG_DEBUG_HUNT_FOR_ZERO
243 unsigned int cpu = raw_smp_processor_id(); 263 unsigned int cpu = raw_smp_processor_id();
244#endif
245 const char *strerror = NULL; 264 const char *strerror = NULL;
246 int sig = 0; 265 int sig = 0;
247 siginfo_t info; 266 siginfo_t info;
@@ -515,6 +534,36 @@ asmlinkage notrace void trap_c(struct pt_regs *fp)
515 break; 534 break;
516 /* External Memory Addressing Error */ 535 /* External Memory Addressing Error */
517 case (SEQSTAT_HWERRCAUSE_EXTERN_ADDR): 536 case (SEQSTAT_HWERRCAUSE_EXTERN_ADDR):
537 if (ANOMALY_05000310) {
538 static unsigned long anomaly_rets;
539
540 if ((fp->pc >= (L1_CODE_START + L1_CODE_LENGTH - 512)) &&
541 (fp->pc < (L1_CODE_START + L1_CODE_LENGTH))) {
542 /*
543 * A false hardware error will happen while fetching at
544 * the L1 instruction SRAM boundary. Ignore it.
545 */
546 anomaly_rets = fp->rets;
547 goto traps_done;
548 } else if (fp->rets == anomaly_rets) {
549 /*
550 * While boundary code returns to a function, at the ret
551 * point, a new false hardware error might occur too based
552 * on tests. Ignore it too.
553 */
554 goto traps_done;
555 } else if ((fp->rets >= (L1_CODE_START + L1_CODE_LENGTH - 512)) &&
556 (fp->rets < (L1_CODE_START + L1_CODE_LENGTH))) {
557 /*
558 * If boundary code calls a function, at the entry point,
559 * a new false hardware error maybe happen based on tests.
560 * Ignore it too.
561 */
562 goto traps_done;
563 } else
564 anomaly_rets = 0;
565 }
566
518 info.si_code = BUS_ADRERR; 567 info.si_code = BUS_ADRERR;
519 sig = SIGBUS; 568 sig = SIGBUS;
520 strerror = KERN_NOTICE HWC_x3(KERN_NOTICE); 569 strerror = KERN_NOTICE HWC_x3(KERN_NOTICE);
@@ -600,7 +649,17 @@ asmlinkage notrace void trap_c(struct pt_regs *fp)
600 { 649 {
601 info.si_signo = sig; 650 info.si_signo = sig;
602 info.si_errno = 0; 651 info.si_errno = 0;
603 info.si_addr = (void __user *)fp->pc; 652 switch (trapnr) {
653 case VEC_CPLB_VL:
654 case VEC_MISALI_D:
655 case VEC_CPLB_M:
656 case VEC_CPLB_MHIT:
657 info.si_addr = (void __user *)cpu_pda[cpu].dcplb_fault_addr;
658 break;
659 default:
660 info.si_addr = (void __user *)fp->pc;
661 break;
662 }
604 force_sig_info(sig, &info, current); 663 force_sig_info(sig, &info, current);
605 } 664 }
606 665
@@ -619,7 +678,7 @@ asmlinkage notrace void trap_c(struct pt_regs *fp)
619 678
620/* 679/*
621 * Similar to get_user, do some address checking, then dereference 680 * Similar to get_user, do some address checking, then dereference
622 * Return true on sucess, false on bad address 681 * Return true on success, false on bad address
623 */ 682 */
624static bool get_instruction(unsigned short *val, unsigned short *address) 683static bool get_instruction(unsigned short *val, unsigned short *address)
625{ 684{
@@ -673,7 +732,7 @@ static void decode_instruction(unsigned short *address)
673 verbose_printk("RTE"); 732 verbose_printk("RTE");
674 else if (opcode == 0x0025) 733 else if (opcode == 0x0025)
675 verbose_printk("EMUEXCPT"); 734 verbose_printk("EMUEXCPT");
676 else if (opcode == 0x0040 && opcode <= 0x0047) 735 else if (opcode >= 0x0040 && opcode <= 0x0047)
677 verbose_printk("STI R%i", opcode & 7); 736 verbose_printk("STI R%i", opcode & 7);
678 else if (opcode >= 0x0050 && opcode <= 0x0057) 737 else if (opcode >= 0x0050 && opcode <= 0x0057)
679 verbose_printk("JUMP (P%i)", opcode & 7); 738 verbose_printk("JUMP (P%i)", opcode & 7);
@@ -976,12 +1035,12 @@ void dump_bfin_process(struct pt_regs *fp)
976 !((unsigned long)current & 0x3) && current->pid) { 1035 !((unsigned long)current & 0x3) && current->pid) {
977 verbose_printk(KERN_NOTICE "CURRENT PROCESS:\n"); 1036 verbose_printk(KERN_NOTICE "CURRENT PROCESS:\n");
978 if (current->comm >= (char *)FIXED_CODE_START) 1037 if (current->comm >= (char *)FIXED_CODE_START)
979 verbose_printk(KERN_NOTICE "COMM=%s PID=%d\n", 1038 verbose_printk(KERN_NOTICE "COMM=%s PID=%d",
980 current->comm, current->pid); 1039 current->comm, current->pid);
981 else 1040 else
982 verbose_printk(KERN_NOTICE "COMM= invalid\n"); 1041 verbose_printk(KERN_NOTICE "COMM= invalid");
983 1042
984 printk(KERN_NOTICE "CPU = %d\n", current_thread_info()->cpu); 1043 printk(KERN_CONT " CPU=%d\n", current_thread_info()->cpu);
985 if (!((unsigned long)current->mm & 0x3) && (unsigned long)current->mm >= FIXED_CODE_START) 1044 if (!((unsigned long)current->mm & 0x3) && (unsigned long)current->mm >= FIXED_CODE_START)
986 verbose_printk(KERN_NOTICE 1045 verbose_printk(KERN_NOTICE
987 "TEXT = 0x%p-0x%p DATA = 0x%p-0x%p\n" 1046 "TEXT = 0x%p-0x%p DATA = 0x%p-0x%p\n"
@@ -1057,7 +1116,7 @@ void dump_bfin_mem(struct pt_regs *fp)
1057 /* And the last RETI points to the current userspace context */ 1116 /* And the last RETI points to the current userspace context */
1058 if ((fp + 1)->pc >= current->mm->start_code && 1117 if ((fp + 1)->pc >= current->mm->start_code &&
1059 (fp + 1)->pc <= current->mm->end_code) { 1118 (fp + 1)->pc <= current->mm->end_code) {
1060 verbose_printk(KERN_NOTICE "It might be better to look around here : \n"); 1119 verbose_printk(KERN_NOTICE "It might be better to look around here :\n");
1061 verbose_printk(KERN_NOTICE "-------------------------------------------\n"); 1120 verbose_printk(KERN_NOTICE "-------------------------------------------\n");
1062 show_regs(fp + 1); 1121 show_regs(fp + 1);
1063 verbose_printk(KERN_NOTICE "-------------------------------------------\n"); 1122 verbose_printk(KERN_NOTICE "-------------------------------------------\n");
@@ -1140,7 +1199,7 @@ void show_regs(struct pt_regs *fp)
1140 if (fp->ipend & ~0x3F) { 1199 if (fp->ipend & ~0x3F) {
1141 for (i = 0; i < (NR_IRQS - 1); i++) { 1200 for (i = 0; i < (NR_IRQS - 1); i++) {
1142 if (!in_atomic) 1201 if (!in_atomic)
1143 spin_lock_irqsave(&irq_desc[i].lock, flags); 1202 raw_spin_lock_irqsave(&irq_desc[i].lock, flags);
1144 1203
1145 action = irq_desc[i].action; 1204 action = irq_desc[i].action;
1146 if (!action) 1205 if (!action)
@@ -1155,7 +1214,7 @@ void show_regs(struct pt_regs *fp)
1155 verbose_printk("\n"); 1214 verbose_printk("\n");
1156unlock: 1215unlock:
1157 if (!in_atomic) 1216 if (!in_atomic)
1158 spin_unlock_irqrestore(&irq_desc[i].lock, flags); 1217 raw_spin_unlock_irqrestore(&irq_desc[i].lock, flags);
1159 } 1218 }
1160 } 1219 }
1161 1220