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
3535
3636 extern int prom_node_root;
3737
38+int show_unhandled_signals = 1;
39+
3840 /* At boot time we determine these two values necessary for setting
3941 * up the segment maps and page table entries (pte's).
4042 */
@@ -149,6 +151,45 @@ asmlinkage int lookup_fault(unsigned long pc, unsigned long ret_pc, · 108 unmodified lines
149151 return 0;
150152 }
151153
154+static inline void
155+show_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+
175+static 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+
152193 extern unsigned long safe_compute_effective_address(struct pt_regs *,
153194 unsigned int);
154195
@@ -168,6 +209,14 @@ static unsigned long compute_si_addr(struct pt_regs *regs, int text_fault) · 13 unmodified lines
168209 return safe_compute_effective_address(regs, insn);
169210 }
170211
212+static 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+
171220 asmlinkage void do_sparc_fault(struct pt_regs *regs, int text_fault, int write,
172221 unsigned long address)
173222 {
@@ -176,9 +225,8 @@ asmlinkage void do_sparc_fault(struct pt_regs *regs, int text_fault, int write, · 2 unmodified lines
176225 struct mm_struct *mm = tsk->mm;
177226 unsigned int fixup;
178227 unsigned long g2;
179− siginfo_t info;
180228 int from_user = !(regs->psr & PSR_PS);
181− int fault;
229+ int fault, code;
182230
183231 if(text_fault)
184232 address = regs->pc;
@@ -195,7 +243,7 @@ asmlinkage void do_sparc_fault(struct pt_regs *regs, int text_fault, int write, · 10 unmodified lines
195243 if (!ARCH_SUN4C && address >= TASK_SIZE)
196244 goto vmalloc_fault;
197245
198− info.si_code = SEGV_MAPERR;
246+ code = SEGV_MAPERR;
199247
200248 /*
201249 * 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
229277 * we can handle it..
230278 */
231279 good_area:
232− info.si_code = SEGV_ACCERR;
280+ code = SEGV_ACCERR;
233281 if(write) {
234282 if(!(vma->vm_flags & VM_WRITE))
235283 goto bad_area;
@@ -273,18 +321,8 @@ bad_area: · 37 unmodified lines
273321
274322 bad_area_nosemaphore:
275323 /* User mode accesses just cause a SIGSEGV */
276− if(from_user) {
277−#if 0
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);
324+ if (from_user) {
325+ do_fault_siginfo(code, SIGSEGV, regs, text_fault);
288326 return;
289327 }
290328
@@ -335,12 +373,7 @@ out_of_memory: · 44 unmodified lines
335373
336374 do_sigbus:
337375 up_read(&mm->mmap_sem);
338− info.si_signo = SIGBUS;
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);
376+ do_fault_siginfo(BUS_ADRERR, SIGBUS, regs, text_fault);
344377 if (!from_user)
345378 goto no_context;
346379
@@ -466,14 +499,10 @@ static void force_user_fault(unsigned long address, int write) · 119 unmodified lines
466499 struct vm_area_struct *vma;
467500 struct task_struct *tsk = current;
468501 struct mm_struct *mm = tsk->mm;
469− siginfo_t info;
502+ int code;
470503
471− info.si_code = SEGV_MAPERR;
504+ code = SEGV_MAPERR;
472505
473−#if 0
474− printk("wf<pid=%d,wr=%d,addr=%08lx>\n",
475− tsk->pid, write, address);
476−#endif
477506 down_read(&mm->mmap_sem);
478507 vma = find_vma(mm, address);
479508 if(!vma)
@@ -485,7 +514,7 @@ static void force_user_fault(unsigned long address, int write) · 5 unmodified lines
485514 if(expand_stack(vma, address))
486515 goto bad_area;
487516 good_area:
488− info.si_code = SEGV_ACCERR;
517+ code = SEGV_ACCERR;
489518 if(write) {
490519 if(!(vma->vm_flags & VM_WRITE))
491520 goto bad_area;
@@ -502,27 +531,12 @@ good_area: · 10 unmodified lines
502531 return;
503532 bad_area:
504533 up_read(&mm->mmap_sem);
505−#if 0
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);
534+ __do_fault_siginfo(code, SIGSEGV, tsk->thread.kregs, address);
516535 return;
517536
518537 do_sigbus:
519538 up_read(&mm->mmap_sem);
520− info.si_signo = SIGBUS;
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);
539+ __do_fault_siginfo(BUS_ADRERR, SIGBUS, tsk->thread.kregs, address);
526540 }
527541
528542 void window_overflow_fault(void)
arch/sparc/mm/fault_64.c+31−3
@@ -32,6 +32,8 @@ · 31 unmodified lines
3232 #include <asm/sections.h>
3333 #include <asm/mmu_context.h>
3434
35+int show_unhandled_signals = 1;
36+
3537 static inline __kprobes int notify_page_fault(struct pt_regs *regs)
3638 {
3739 int ret = 0;
@@ -128,22 +130,48 @@ outret: · 90 unmodified lines
128130 return insn;
129131 }
130132
133+static inline void
134+show_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+
131154 extern unsigned long compute_effective_address(struct pt_regs *, unsigned int, unsigned int);
132155
133156 static void do_fault_siginfo(int code, int sig, struct pt_regs *regs,
134157 unsigned int insn, int fault_code)
135158 {
159+ unsigned long addr;
136160 siginfo_t info;
137161
138162 info.si_code = code;
139163 info.si_signo = sig;
140164 info.si_errno = 0;
141165 if (fault_code & FAULT_CODE_ITLB)
142− info.si_addr = (void __user *) regs->tpc;
166+ addr = regs->tpc;
143167 else
144− info.si_addr = (void __user *)
145− compute_effective_address(regs, insn, 0);
168+ addr = compute_effective_address(regs, insn, 0);
169+ info.si_addr = (void __user *) addr;
146170 info.si_trapno = 0;
171+
172+ if (unlikely(show_unhandled_signals))
173+ show_signal_msg(regs, sig, code, addr, current);
174+
147175 force_sig_info(sig, &info, current);
148176 }
149177
kernel/sysctl.c+1−1
@@ -1441,7 +1441,7 @@ static struct ctl_table fs_table[] = { · 1440 unmodified lines
14411441 };
14421442
14431443 static struct ctl_table debug_table[] = {
1444−#if defined(CONFIG_X86) || defined(CONFIG_PPC)
1444+#if defined(CONFIG_X86) || defined(CONFIG_PPC) || defined(CONFIG_SPARC)
14451445 {
14461446 .procname = "exception-trace",
14471447 .data = &show_unhandled_signals,