diff options
Diffstat (limited to 'arch/blackfin/kernel/traps.c')
-rw-r--r-- | arch/blackfin/kernel/traps.c | 32 |
1 files changed, 26 insertions, 6 deletions
diff --git a/arch/blackfin/kernel/traps.c b/arch/blackfin/kernel/traps.c index d3cbcd6bd985..ba70c4bc2699 100644 --- a/arch/blackfin/kernel/traps.c +++ b/arch/blackfin/kernel/traps.c | |||
@@ -138,6 +138,12 @@ static void decode_address(char *buf, unsigned long address) | |||
138 | if (!mm) | 138 | if (!mm) |
139 | continue; | 139 | continue; |
140 | 140 | ||
141 | if (!down_read_trylock(&mm->mmap_sem)) { | ||
142 | if (!in_atomic) | ||
143 | mmput(mm); | ||
144 | continue; | ||
145 | } | ||
146 | |||
141 | 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)) { |
142 | struct vm_area_struct *vma; | 148 | struct vm_area_struct *vma; |
143 | 149 | ||
@@ -177,6 +183,7 @@ static void decode_address(char *buf, unsigned long address) | |||
177 | sprintf(buf, "[ %s vma:0x%lx-0x%lx]", | 183 | sprintf(buf, "[ %s vma:0x%lx-0x%lx]", |
178 | name, vma->vm_start, vma->vm_end); | 184 | name, vma->vm_start, vma->vm_end); |
179 | 185 | ||
186 | up_read(&mm->mmap_sem); | ||
180 | if (!in_atomic) | 187 | if (!in_atomic) |
181 | mmput(mm); | 188 | mmput(mm); |
182 | 189 | ||
@@ -186,11 +193,16 @@ static void decode_address(char *buf, unsigned long address) | |||
186 | goto done; | 193 | goto done; |
187 | } | 194 | } |
188 | } | 195 | } |
196 | |||
197 | up_read(&mm->mmap_sem); | ||
189 | if (!in_atomic) | 198 | if (!in_atomic) |
190 | mmput(mm); | 199 | mmput(mm); |
191 | } | 200 | } |
192 | 201 | ||
193 | /* 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 | */ | ||
194 | sprintf(buf, "/* kernel dynamic memory */"); | 206 | sprintf(buf, "/* kernel dynamic memory */"); |
195 | 207 | ||
196 | done: | 208 | done: |
@@ -248,9 +260,7 @@ asmlinkage notrace void trap_c(struct pt_regs *fp) | |||
248 | #ifdef CONFIG_DEBUG_BFIN_HWTRACE_ON | 260 | #ifdef CONFIG_DEBUG_BFIN_HWTRACE_ON |
249 | int j; | 261 | int j; |
250 | #endif | 262 | #endif |
251 | #ifdef CONFIG_DEBUG_HUNT_FOR_ZERO | ||
252 | unsigned int cpu = raw_smp_processor_id(); | 263 | unsigned int cpu = raw_smp_processor_id(); |
253 | #endif | ||
254 | const char *strerror = NULL; | 264 | const char *strerror = NULL; |
255 | int sig = 0; | 265 | int sig = 0; |
256 | siginfo_t info; | 266 | siginfo_t info; |
@@ -639,7 +649,17 @@ asmlinkage notrace void trap_c(struct pt_regs *fp) | |||
639 | { | 649 | { |
640 | info.si_signo = sig; | 650 | info.si_signo = sig; |
641 | info.si_errno = 0; | 651 | info.si_errno = 0; |
642 | 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 | } | ||
643 | force_sig_info(sig, &info, current); | 663 | force_sig_info(sig, &info, current); |
644 | } | 664 | } |
645 | 665 | ||
@@ -712,7 +732,7 @@ static void decode_instruction(unsigned short *address) | |||
712 | verbose_printk("RTE"); | 732 | verbose_printk("RTE"); |
713 | else if (opcode == 0x0025) | 733 | else if (opcode == 0x0025) |
714 | verbose_printk("EMUEXCPT"); | 734 | verbose_printk("EMUEXCPT"); |
715 | else if (opcode == 0x0040 && opcode <= 0x0047) | 735 | else if (opcode >= 0x0040 && opcode <= 0x0047) |
716 | verbose_printk("STI R%i", opcode & 7); | 736 | verbose_printk("STI R%i", opcode & 7); |
717 | else if (opcode >= 0x0050 && opcode <= 0x0057) | 737 | else if (opcode >= 0x0050 && opcode <= 0x0057) |
718 | verbose_printk("JUMP (P%i)", opcode & 7); | 738 | verbose_printk("JUMP (P%i)", opcode & 7); |
@@ -1096,7 +1116,7 @@ void dump_bfin_mem(struct pt_regs *fp) | |||
1096 | /* And the last RETI points to the current userspace context */ | 1116 | /* And the last RETI points to the current userspace context */ |
1097 | if ((fp + 1)->pc >= current->mm->start_code && | 1117 | if ((fp + 1)->pc >= current->mm->start_code && |
1098 | (fp + 1)->pc <= current->mm->end_code) { | 1118 | (fp + 1)->pc <= current->mm->end_code) { |
1099 | 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"); |
1100 | verbose_printk(KERN_NOTICE "-------------------------------------------\n"); | 1120 | verbose_printk(KERN_NOTICE "-------------------------------------------\n"); |
1101 | show_regs(fp + 1); | 1121 | show_regs(fp + 1); |
1102 | verbose_printk(KERN_NOTICE "-------------------------------------------\n"); | 1122 | verbose_printk(KERN_NOTICE "-------------------------------------------\n"); |