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.c94
1 files changed, 58 insertions, 36 deletions
diff --git a/arch/blackfin/kernel/traps.c b/arch/blackfin/kernel/traps.c
index 56a67ab698c7..5b847070dae5 100644
--- a/arch/blackfin/kernel/traps.c
+++ b/arch/blackfin/kernel/traps.c
@@ -67,6 +67,8 @@ void __init trap_init(void)
67 CSYNC(); 67 CSYNC();
68} 68}
69 69
70void *saved_icplb_fault_addr, *saved_dcplb_fault_addr;
71
70int kstack_depth_to_print = 48; 72int kstack_depth_to_print = 48;
71 73
72static void decode_address(char *buf, unsigned long address) 74static void decode_address(char *buf, unsigned long address)
@@ -75,7 +77,7 @@ static void decode_address(char *buf, unsigned long address)
75 struct task_struct *p; 77 struct task_struct *p;
76 struct mm_struct *mm; 78 struct mm_struct *mm;
77 unsigned long flags, offset; 79 unsigned long flags, offset;
78 unsigned int in_exception = bfin_read_IPEND() & 0x10; 80 unsigned char in_atomic = (bfin_read_IPEND() & 0x10) || in_atomic();
79 81
80#ifdef CONFIG_KALLSYMS 82#ifdef CONFIG_KALLSYMS
81 unsigned long symsize; 83 unsigned long symsize;
@@ -117,7 +119,7 @@ static void decode_address(char *buf, unsigned long address)
117 */ 119 */
118 write_lock_irqsave(&tasklist_lock, flags); 120 write_lock_irqsave(&tasklist_lock, flags);
119 for_each_process(p) { 121 for_each_process(p) {
120 mm = (in_exception ? p->mm : get_task_mm(p)); 122 mm = (in_atomic ? p->mm : get_task_mm(p));
121 if (!mm) 123 if (!mm)
122 continue; 124 continue;
123 125
@@ -137,23 +139,36 @@ static void decode_address(char *buf, unsigned long address)
137 /* FLAT does not have its text aligned to the start of 139 /* FLAT does not have its text aligned to the start of
138 * the map while FDPIC ELF does ... 140 * the map while FDPIC ELF does ...
139 */ 141 */
140 if (current->mm && 142
141 (address > current->mm->start_code) && 143 /* before we can check flat/fdpic, we need to
142 (address < current->mm->end_code)) 144 * make sure current is valid
143 offset = address - current->mm->start_code; 145 */
144 else 146 if ((unsigned long)current >= FIXED_CODE_START &&
145 offset = (address - vma->vm_start) + (vma->vm_pgoff << PAGE_SHIFT); 147 !((unsigned long)current & 0x3)) {
146 148 if (current->mm &&
147 sprintf(buf, "<0x%p> [ %s + 0x%lx ]", 149 (address > current->mm->start_code) &&
148 (void *)address, name, offset); 150 (address < current->mm->end_code))
149 if (!in_exception) 151 offset = address - current->mm->start_code;
152 else
153 offset = (address - vma->vm_start) +
154 (vma->vm_pgoff << PAGE_SHIFT);
155
156 sprintf(buf, "<0x%p> [ %s + 0x%lx ]",
157 (void *)address, name, offset);
158 } else
159 sprintf(buf, "<0x%p> [ %s vma:0x%lx-0x%lx]",
160 (void *)address, name,
161 vma->vm_start, vma->vm_end);
162
163 if (!in_atomic)
150 mmput(mm); 164 mmput(mm);
165
151 goto done; 166 goto done;
152 } 167 }
153 168
154 vml = vml->next; 169 vml = vml->next;
155 } 170 }
156 if (!in_exception) 171 if (!in_atomic)
157 mmput(mm); 172 mmput(mm);
158 } 173 }
159 174
@@ -506,7 +521,7 @@ asmlinkage void trap_c(struct pt_regs *fp)
506 521
507 info.si_signo = sig; 522 info.si_signo = sig;
508 info.si_errno = 0; 523 info.si_errno = 0;
509 info.si_addr = (void *)fp->pc; 524 info.si_addr = (void __user *)fp->pc;
510 force_sig_info(sig, &info, current); 525 force_sig_info(sig, &info, current);
511 526
512 trace_buffer_restore(j); 527 trace_buffer_restore(j);
@@ -655,21 +670,31 @@ void dump_bfin_process(struct pt_regs *fp)
655 else if (context & 0x8000) 670 else if (context & 0x8000)
656 printk(KERN_NOTICE "Kernel process context\n"); 671 printk(KERN_NOTICE "Kernel process context\n");
657 672
658 if (current->pid && current->mm) { 673 /* Because we are crashing, and pointers could be bad, we check things
674 * pretty closely before we use them
675 */
676 if ((unsigned long)current >= FIXED_CODE_START &&
677 !((unsigned long)current & 0x3) && current->pid) {
659 printk(KERN_NOTICE "CURRENT PROCESS:\n"); 678 printk(KERN_NOTICE "CURRENT PROCESS:\n");
660 printk(KERN_NOTICE "COMM=%s PID=%d\n", 679 if (current->comm >= (char *)FIXED_CODE_START)
661 current->comm, current->pid); 680 printk(KERN_NOTICE "COMM=%s PID=%d\n",
662 681 current->comm, current->pid);
663 printk(KERN_NOTICE "TEXT = 0x%p-0x%p DATA = 0x%p-0x%p\n" 682 else
664 KERN_NOTICE "BSS = 0x%p-0x%p USER-STACK = 0x%p\n" 683 printk(KERN_NOTICE "COMM= invalid\n");
665 KERN_NOTICE "\n", 684
666 (void *)current->mm->start_code, 685 if (!((unsigned long)current->mm & 0x3) && (unsigned long)current->mm >= FIXED_CODE_START)
667 (void *)current->mm->end_code, 686 printk(KERN_NOTICE "TEXT = 0x%p-0x%p DATA = 0x%p-0x%p\n"
668 (void *)current->mm->start_data, 687 KERN_NOTICE " BSS = 0x%p-0x%p USER-STACK = 0x%p\n"
669 (void *)current->mm->end_data, 688 KERN_NOTICE "\n",
670 (void *)current->mm->end_data, 689 (void *)current->mm->start_code,
671 (void *)current->mm->brk, 690 (void *)current->mm->end_code,
672 (void *)current->mm->start_stack); 691 (void *)current->mm->start_data,
692 (void *)current->mm->end_data,
693 (void *)current->mm->end_data,
694 (void *)current->mm->brk,
695 (void *)current->mm->start_stack);
696 else
697 printk(KERN_NOTICE "invalid mm\n");
673 } else 698 } else
674 printk(KERN_NOTICE "\n" KERN_NOTICE 699 printk(KERN_NOTICE "\n" KERN_NOTICE
675 "No Valid process in current context\n"); 700 "No Valid process in current context\n");
@@ -680,10 +705,7 @@ void dump_bfin_mem(struct pt_regs *fp)
680 unsigned short *addr, *erraddr, val = 0, err = 0; 705 unsigned short *addr, *erraddr, val = 0, err = 0;
681 char sti = 0, buf[6]; 706 char sti = 0, buf[6];
682 707
683 if (unlikely((fp->seqstat & SEQSTAT_EXCAUSE) == VEC_HWERR)) 708 erraddr = (void *)fp->pc;
684 erraddr = (void *)fp->pc;
685 else
686 erraddr = (void *)fp->retx;
687 709
688 printk(KERN_NOTICE "return address: [0x%p]; contents of:", erraddr); 710 printk(KERN_NOTICE "return address: [0x%p]; contents of:", erraddr);
689 711
@@ -807,9 +829,9 @@ unlock:
807 829
808 if (((long)fp->seqstat & SEQSTAT_EXCAUSE) && 830 if (((long)fp->seqstat & SEQSTAT_EXCAUSE) &&
809 (((long)fp->seqstat & SEQSTAT_EXCAUSE) != VEC_HWERR)) { 831 (((long)fp->seqstat & SEQSTAT_EXCAUSE) != VEC_HWERR)) {
810 decode_address(buf, bfin_read_DCPLB_FAULT_ADDR()); 832 decode_address(buf, saved_dcplb_fault_addr);
811 printk(KERN_NOTICE "DCPLB_FAULT_ADDR: %s\n", buf); 833 printk(KERN_NOTICE "DCPLB_FAULT_ADDR: %s\n", buf);
812 decode_address(buf, bfin_read_ICPLB_FAULT_ADDR()); 834 decode_address(buf, saved_icplb_fault_addr);
813 printk(KERN_NOTICE "ICPLB_FAULT_ADDR: %s\n", buf); 835 printk(KERN_NOTICE "ICPLB_FAULT_ADDR: %s\n", buf);
814 } 836 }
815 837
@@ -917,8 +939,8 @@ void panic_cplb_error(int cplb_panic, struct pt_regs *fp)
917 939
918 oops_in_progress = 1; 940 oops_in_progress = 1;
919 941
920 printk(KERN_EMERG "DCPLB_FAULT_ADDR=%p\n", (void *)bfin_read_DCPLB_FAULT_ADDR()); 942 printk(KERN_EMERG "DCPLB_FAULT_ADDR=%p\n", saved_dcplb_fault_addr);
921 printk(KERN_EMERG "ICPLB_FAULT_ADDR=%p\n", (void *)bfin_read_ICPLB_FAULT_ADDR()); 943 printk(KERN_EMERG "ICPLB_FAULT_ADDR=%p\n", saved_icplb_fault_addr);
922 dump_bfin_process(fp); 944 dump_bfin_process(fp);
923 dump_bfin_mem(fp); 945 dump_bfin_mem(fp);
924 show_regs(fp); 946 show_regs(fp);