diff options
Diffstat (limited to 'arch/blackfin/kernel/traps.c')
-rw-r--r-- | arch/blackfin/kernel/traps.c | 94 |
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 | ||
70 | void *saved_icplb_fault_addr, *saved_dcplb_fault_addr; | ||
71 | |||
70 | int kstack_depth_to_print = 48; | 72 | int kstack_depth_to_print = 48; |
71 | 73 | ||
72 | static void decode_address(char *buf, unsigned long address) | 74 | static 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); |