aboutsummaryrefslogtreecommitdiffstats
path: root/arch/sparc/mm/fault_32.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/sparc/mm/fault_32.c')
-rw-r--r--arch/sparc/mm/fault_32.c106
1 files changed, 60 insertions, 46 deletions
diff --git a/arch/sparc/mm/fault_32.c b/arch/sparc/mm/fault_32.c
index 3fa09ba3845f..bd8601601afa 100644
--- a/arch/sparc/mm/fault_32.c
+++ b/arch/sparc/mm/fault_32.c
@@ -35,6 +35,8 @@
35 35
36extern int prom_node_root; 36extern int prom_node_root;
37 37
38int show_unhandled_signals = 1;
39
38/* At boot time we determine these two values necessary for setting 40/* At boot time we determine these two values necessary for setting
39 * up the segment maps and page table entries (pte's). 41 * up the segment maps and page table entries (pte's).
40 */ 42 */
@@ -149,6 +151,45 @@ asmlinkage int lookup_fault(unsigned long pc, unsigned long ret_pc,
149 return 0; 151 return 0;
150} 152}
151 153
154static inline void
155show_signal_msg(struct pt_regs *regs, int sig, int code,
156 unsigned long address, struct task_struct *tsk)
157{
158 if (!unhandled_signal(tsk, sig))
159 return;
160
161 if (!printk_ratelimit())
162 return;
163
164 printk("%s%s[%d]: segfault at %lx ip %p (rpc %p) sp %p error %x",
165 task_pid_nr(tsk) > 1 ? KERN_INFO : KERN_EMERG,
166 tsk->comm, task_pid_nr(tsk), address,
167 (void *)regs->pc, (void *)regs->u_regs[UREG_I7],
168 (void *)regs->u_regs[UREG_FP], code);
169
170 print_vma_addr(KERN_CONT " in ", regs->pc);
171
172 printk(KERN_CONT "\n");
173}
174
175static void __do_fault_siginfo(int code, int sig, struct pt_regs *regs,
176 unsigned long addr)
177{
178 siginfo_t info;
179
180 info.si_signo = sig;
181 info.si_code = code;
182 info.si_errno = 0;
183 info.si_addr = (void __user *) addr;
184 info.si_trapno = 0;
185
186 if (unlikely(show_unhandled_signals))
187 show_signal_msg(regs, sig, info.si_code,
188 addr, current);
189
190 force_sig_info (sig, &info, current);
191}
192
152extern unsigned long safe_compute_effective_address(struct pt_regs *, 193extern unsigned long safe_compute_effective_address(struct pt_regs *,
153 unsigned int); 194 unsigned int);
154 195
@@ -168,6 +209,14 @@ static unsigned long compute_si_addr(struct pt_regs *regs, int text_fault)
168 return safe_compute_effective_address(regs, insn); 209 return safe_compute_effective_address(regs, insn);
169} 210}
170 211
212static noinline void do_fault_siginfo(int code, int sig, struct pt_regs *regs,
213 int text_fault)
214{
215 unsigned long addr = compute_si_addr(regs, text_fault);
216
217 __do_fault_siginfo(code, sig, regs, addr);
218}
219
171asmlinkage void do_sparc_fault(struct pt_regs *regs, int text_fault, int write, 220asmlinkage void do_sparc_fault(struct pt_regs *regs, int text_fault, int write,
172 unsigned long address) 221 unsigned long address)
173{ 222{
@@ -176,9 +225,8 @@ asmlinkage void do_sparc_fault(struct pt_regs *regs, int text_fault, int write,
176 struct mm_struct *mm = tsk->mm; 225 struct mm_struct *mm = tsk->mm;
177 unsigned int fixup; 226 unsigned int fixup;
178 unsigned long g2; 227 unsigned long g2;
179 siginfo_t info;
180 int from_user = !(regs->psr & PSR_PS); 228 int from_user = !(regs->psr & PSR_PS);
181 int fault; 229 int fault, code;
182 230
183 if(text_fault) 231 if(text_fault)
184 address = regs->pc; 232 address = regs->pc;
@@ -195,7 +243,7 @@ asmlinkage void do_sparc_fault(struct pt_regs *regs, int text_fault, int write,
195 if (!ARCH_SUN4C && address >= TASK_SIZE) 243 if (!ARCH_SUN4C && address >= TASK_SIZE)
196 goto vmalloc_fault; 244 goto vmalloc_fault;
197 245
198 info.si_code = SEGV_MAPERR; 246 code = SEGV_MAPERR;
199 247
200 /* 248 /*
201 * If we're in an interrupt or have no user 249 * If we're in an interrupt or have no user
@@ -229,7 +277,7 @@ asmlinkage void do_sparc_fault(struct pt_regs *regs, int text_fault, int write,
229 * we can handle it.. 277 * we can handle it..
230 */ 278 */
231good_area: 279good_area:
232 info.si_code = SEGV_ACCERR; 280 code = SEGV_ACCERR;
233 if(write) { 281 if(write) {
234 if(!(vma->vm_flags & VM_WRITE)) 282 if(!(vma->vm_flags & VM_WRITE))
235 goto bad_area; 283 goto bad_area;
@@ -273,18 +321,8 @@ bad_area:
273 321
274bad_area_nosemaphore: 322bad_area_nosemaphore:
275 /* User mode accesses just cause a SIGSEGV */ 323 /* User mode accesses just cause a SIGSEGV */
276 if(from_user) { 324 if (from_user) {
277#if 0 325 do_fault_siginfo(code, SIGSEGV, regs, text_fault);
278 printk("Fault whee %s [%d]: segfaults at %08lx pc=%08lx\n",
279 tsk->comm, tsk->pid, address, regs->pc);
280#endif
281 info.si_signo = SIGSEGV;
282 info.si_errno = 0;
283 /* info.si_code set above to make clear whether
284 this was a SEGV_MAPERR or SEGV_ACCERR fault. */
285 info.si_addr = (void __user *)compute_si_addr(regs, text_fault);
286 info.si_trapno = 0;
287 force_sig_info (SIGSEGV, &info, tsk);
288 return; 326 return;
289 } 327 }
290 328
@@ -335,12 +373,7 @@ out_of_memory:
335 373
336do_sigbus: 374do_sigbus:
337 up_read(&mm->mmap_sem); 375 up_read(&mm->mmap_sem);
338 info.si_signo = SIGBUS; 376 do_fault_siginfo(BUS_ADRERR, SIGBUS, regs, text_fault);
339 info.si_errno = 0;
340 info.si_code = BUS_ADRERR;
341 info.si_addr = (void __user *) compute_si_addr(regs, text_fault);
342 info.si_trapno = 0;
343 force_sig_info (SIGBUS, &info, tsk);
344 if (!from_user) 377 if (!from_user)
345 goto no_context; 378 goto no_context;
346 379
@@ -466,14 +499,10 @@ static void force_user_fault(unsigned long address, int write)
466 struct vm_area_struct *vma; 499 struct vm_area_struct *vma;
467 struct task_struct *tsk = current; 500 struct task_struct *tsk = current;
468 struct mm_struct *mm = tsk->mm; 501 struct mm_struct *mm = tsk->mm;
469 siginfo_t info; 502 int code;
470 503
471 info.si_code = SEGV_MAPERR; 504 code = SEGV_MAPERR;
472 505
473#if 0
474 printk("wf<pid=%d,wr=%d,addr=%08lx>\n",
475 tsk->pid, write, address);
476#endif
477 down_read(&mm->mmap_sem); 506 down_read(&mm->mmap_sem);
478 vma = find_vma(mm, address); 507 vma = find_vma(mm, address);
479 if(!vma) 508 if(!vma)
@@ -485,7 +514,7 @@ static void force_user_fault(unsigned long address, int write)
485 if(expand_stack(vma, address)) 514 if(expand_stack(vma, address))
486 goto bad_area; 515 goto bad_area;
487good_area: 516good_area:
488 info.si_code = SEGV_ACCERR; 517 code = SEGV_ACCERR;
489 if(write) { 518 if(write) {
490 if(!(vma->vm_flags & VM_WRITE)) 519 if(!(vma->vm_flags & VM_WRITE))
491 goto bad_area; 520 goto bad_area;
@@ -502,27 +531,12 @@ good_area:
502 return; 531 return;
503bad_area: 532bad_area:
504 up_read(&mm->mmap_sem); 533 up_read(&mm->mmap_sem);
505#if 0 534 __do_fault_siginfo(code, SIGSEGV, tsk->thread.kregs, address);
506 printk("Window whee %s [%d]: segfaults at %08lx\n",
507 tsk->comm, tsk->pid, address);
508#endif
509 info.si_signo = SIGSEGV;
510 info.si_errno = 0;
511 /* info.si_code set above to make clear whether
512 this was a SEGV_MAPERR or SEGV_ACCERR fault. */
513 info.si_addr = (void __user *) address;
514 info.si_trapno = 0;
515 force_sig_info (SIGSEGV, &info, tsk);
516 return; 535 return;
517 536
518do_sigbus: 537do_sigbus:
519 up_read(&mm->mmap_sem); 538 up_read(&mm->mmap_sem);
520 info.si_signo = SIGBUS; 539 __do_fault_siginfo(BUS_ADRERR, SIGBUS, tsk->thread.kregs, address);
521 info.si_errno = 0;
522 info.si_code = BUS_ADRERR;
523 info.si_addr = (void __user *) address;
524 info.si_trapno = 0;
525 force_sig_info (SIGBUS, &info, tsk);
526} 540}
527 541
528void window_overflow_fault(void) 542void window_overflow_fault(void)