History

sparc: Support show_unhandled_signals.

Just faults right now, will add other traps later.

David S. Miller committed 16 years ago

Commit 4b177641 parent c7ec2b53 files · +92 −50Browse files

Unified · Split

3 files
  1. arch/sparc/mm/fault_32.c +60 −46
  2. arch/sparc/mm/fault_64.c +31 −3
  3. kernel/sysctl.c +1 −1
arch/sparc/mm/fault_32.c+60−46
@@ -35,6 +35,8 @@ · 34 unmodified lines
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 setting40/* 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, · 108 unmodified lines
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) · 13 unmodified lines
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, · 2 unmodified lines
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, · 10 unmodified lines
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 user249 * 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, · 27 unmodified lines
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: · 37 unmodified lines
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 0325 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: · 44 unmodified lines
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) · 119 unmodified lines
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) · 5 unmodified lines
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: · 10 unmodified lines
502 return;531 return;
503bad_area:532bad_area:
504 up_read(&mm->mmap_sem);533 up_read(&mm->mmap_sem);
505#if 0534 __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)
arch/sparc/mm/fault_64.c+31−3
@@ -32,6 +32,8 @@ · 31 unmodified lines
32#include <asm/sections.h>32#include <asm/sections.h>
33#include <asm/mmu_context.h>33#include <asm/mmu_context.h>
34 34
35int show_unhandled_signals = 1;
36
35static inline __kprobes int notify_page_fault(struct pt_regs *regs)37static inline __kprobes int notify_page_fault(struct pt_regs *regs)
36{38{
37 int ret = 0;39 int ret = 0;
@@ -128,22 +130,48 @@ outret: · 90 unmodified lines
128 return insn;130 return insn;
129}131}
130 132
133static inline void
134show_signal_msg(struct pt_regs *regs, int sig, int code,
135 unsigned long address, struct task_struct *tsk)
136{
137 if (!unhandled_signal(tsk, sig))
138 return;
139
140 if (!printk_ratelimit())
141 return;
142
143 printk("%s%s[%d]: segfault at %lx ip %p (rpc %p) sp %p error %x",
144 task_pid_nr(tsk) > 1 ? KERN_INFO : KERN_EMERG,
145 tsk->comm, task_pid_nr(tsk), address,
146 (void *)regs->tpc, (void *)regs->u_regs[UREG_I7],
147 (void *)regs->u_regs[UREG_FP], code);
148
149 print_vma_addr(KERN_CONT " in ", regs->tpc);
150
151 printk(KERN_CONT "\n");
152}
153
131extern unsigned long compute_effective_address(struct pt_regs *, unsigned int, unsigned int);154extern unsigned long compute_effective_address(struct pt_regs *, unsigned int, unsigned int);
132 155
133static void do_fault_siginfo(int code, int sig, struct pt_regs *regs,156static void do_fault_siginfo(int code, int sig, struct pt_regs *regs,
134 unsigned int insn, int fault_code)157 unsigned int insn, int fault_code)
135{158{
159 unsigned long addr;
136 siginfo_t info;160 siginfo_t info;
137 161
138 info.si_code = code;162 info.si_code = code;
139 info.si_signo = sig;163 info.si_signo = sig;
140 info.si_errno = 0;164 info.si_errno = 0;
141 if (fault_code & FAULT_CODE_ITLB)165 if (fault_code & FAULT_CODE_ITLB)
142 info.si_addr = (void __user *) regs->tpc;166 addr = regs->tpc;
143 else167 else
144 info.si_addr = (void __user *)168 addr = compute_effective_address(regs, insn, 0);
145 compute_effective_address(regs, insn, 0);169 info.si_addr = (void __user *) addr;
146 info.si_trapno = 0;170 info.si_trapno = 0;
171
172 if (unlikely(show_unhandled_signals))
173 show_signal_msg(regs, sig, code, addr, current);
174
147 force_sig_info(sig, &info, current);175 force_sig_info(sig, &info, current);
148}176}
149 177
kernel/sysctl.c+1−1
@@ -1441,7 +1441,7 @@ static struct ctl_table fs_table[] = { · 1440 unmodified lines
1441};1441};
1442 1442
1443static struct ctl_table debug_table[] = {1443static struct ctl_table debug_table[] = {
1444#if defined(CONFIG_X86) || defined(CONFIG_PPC)1444#if defined(CONFIG_X86) || defined(CONFIG_PPC) || defined(CONFIG_SPARC)
1445 {1445 {
1446 .procname = "exception-trace",1446 .procname = "exception-trace",
1447 .data = &show_unhandled_signals,1447 .data = &show_unhandled_signals,