aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid S. Miller <davem@sunset.davemloft.net>2007-05-08 21:25:14 -0400
committerDavid S. Miller <davem@sunset.davemloft.net>2007-05-08 21:25:14 -0400
commit127cda1e8cc282de1ca7a9dcc3866841977b9fcc (patch)
tree800169fa92dc96160044d914ca1ca9fea60339ea
parent6c1142602c9c8faedbc1321892a169652a173fc7 (diff)
[SPARC64]: Optimize fault kprobe handling just like powerpc.
And eliminate DIE_GPF while we're at it. Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--arch/sparc64/kernel/kprobes.c11
-rw-r--r--arch/sparc64/mm/fault.c45
-rw-r--r--include/asm-sparc64/kdebug.h16
-rw-r--r--include/asm-sparc64/kprobes.h1
4 files changed, 29 insertions, 44 deletions
diff --git a/arch/sparc64/kernel/kprobes.c b/arch/sparc64/kernel/kprobes.c
index a44fe47a3c2b..c93a15b785fa 100644
--- a/arch/sparc64/kernel/kprobes.c
+++ b/arch/sparc64/kernel/kprobes.c
@@ -313,7 +313,7 @@ out:
313 return 1; 313 return 1;
314} 314}
315 315
316static int __kprobes kprobe_fault_handler(struct pt_regs *regs, int trapnr) 316int __kprobes kprobe_fault_handler(struct pt_regs *regs, int trapnr)
317{ 317{
318 struct kprobe *cur = kprobe_running(); 318 struct kprobe *cur = kprobe_running();
319 struct kprobe_ctlblk *kcb = get_kprobe_ctlblk(); 319 struct kprobe_ctlblk *kcb = get_kprobe_ctlblk();
@@ -403,15 +403,6 @@ int __kprobes kprobe_exceptions_notify(struct notifier_block *self,
403 if (post_kprobe_handler(args->regs)) 403 if (post_kprobe_handler(args->regs))
404 ret = NOTIFY_STOP; 404 ret = NOTIFY_STOP;
405 break; 405 break;
406 case DIE_GPF:
407 case DIE_PAGE_FAULT:
408 /* kprobe_running() needs smp_processor_id() */
409 preempt_disable();
410 if (kprobe_running() &&
411 kprobe_fault_handler(args->regs, args->trapnr))
412 ret = NOTIFY_STOP;
413 preempt_enable();
414 break;
415 default: 406 default:
416 break; 407 break;
417 } 408 }
diff --git a/arch/sparc64/mm/fault.c b/arch/sparc64/mm/fault.c
index c32e309f7788..b582024d2199 100644
--- a/arch/sparc64/mm/fault.c
+++ b/arch/sparc64/mm/fault.c
@@ -32,36 +32,23 @@
32#include <asm/mmu_context.h> 32#include <asm/mmu_context.h>
33 33
34#ifdef CONFIG_KPROBES 34#ifdef CONFIG_KPROBES
35ATOMIC_NOTIFIER_HEAD(notify_page_fault_chain); 35static inline int notify_page_fault(struct pt_regs *regs)
36
37/* Hook to register for page fault notifications */
38int register_page_fault_notifier(struct notifier_block *nb)
39{ 36{
40 return atomic_notifier_chain_register(&notify_page_fault_chain, nb); 37 int ret = 0;
41} 38
42 39 /* kprobe_running() needs smp_processor_id() */
43int unregister_page_fault_notifier(struct notifier_block *nb) 40 if (!user_mode(regs)) {
44{ 41 preempt_disable();
45 return atomic_notifier_chain_unregister(&notify_page_fault_chain, nb); 42 if (kprobe_running() && kprobe_fault_handler(regs, 0))
46} 43 ret = 1;
47 44 preempt_enable();
48static inline int notify_page_fault(enum die_val val, const char *str, 45 }
49 struct pt_regs *regs, long err, int trap, int sig) 46 return ret;
50{
51 struct die_args args = {
52 .regs = regs,
53 .str = str,
54 .err = err,
55 .trapnr = trap,
56 .signr = sig
57 };
58 return atomic_notifier_call_chain(&notify_page_fault_chain, val, &args);
59} 47}
60#else 48#else
61static inline int notify_page_fault(enum die_val val, const char *str, 49static inline int notify_page_fault(struct pt_regs *regs)
62 struct pt_regs *regs, long err, int trap, int sig)
63{ 50{
64 return NOTIFY_DONE; 51 return 0;
65} 52}
66#endif 53#endif
67 54
@@ -120,9 +107,6 @@ static void __kprobes unhandled_fault(unsigned long address,
120 printk(KERN_ALERT "tsk->{mm,active_mm}->pgd = %016lx\n", 107 printk(KERN_ALERT "tsk->{mm,active_mm}->pgd = %016lx\n",
121 (tsk->mm ? (unsigned long) tsk->mm->pgd : 108 (tsk->mm ? (unsigned long) tsk->mm->pgd :
122 (unsigned long) tsk->active_mm->pgd)); 109 (unsigned long) tsk->active_mm->pgd));
123 if (notify_die(DIE_GPF, "general protection fault", regs,
124 0, 0, SIGSEGV) == NOTIFY_STOP)
125 return;
126 die_if_kernel("Oops", regs); 110 die_if_kernel("Oops", regs);
127} 111}
128 112
@@ -299,8 +283,7 @@ asmlinkage void __kprobes do_sparc64_fault(struct pt_regs *regs)
299 283
300 fault_code = get_thread_fault_code(); 284 fault_code = get_thread_fault_code();
301 285
302 if (notify_page_fault(DIE_PAGE_FAULT, "page_fault", regs, 286 if (notify_page_fault(regs))
303 fault_code, 0, SIGSEGV) == NOTIFY_STOP)
304 return; 287 return;
305 288
306 si_code = SEGV_MAPERR; 289 si_code = SEGV_MAPERR;
diff --git a/include/asm-sparc64/kdebug.h b/include/asm-sparc64/kdebug.h
index f8032e73f384..627e3396a5f0 100644
--- a/include/asm-sparc64/kdebug.h
+++ b/include/asm-sparc64/kdebug.h
@@ -7,8 +7,19 @@
7 7
8struct pt_regs; 8struct pt_regs;
9 9
10extern int register_page_fault_notifier(struct notifier_block *); 10/*
11extern int unregister_page_fault_notifier(struct notifier_block *); 11 * These are only here because kprobes.c wants them to implement a
12 * blatant layering violation. Will hopefully go away soon once all
13 * architectures are updated.
14 */
15static inline int register_page_fault_notifier(struct notifier_block *nb)
16{
17 return 0;
18}
19static inline int unregister_page_fault_notifier(struct notifier_block *nb)
20{
21 return 0;
22}
12 23
13extern void bad_trap(struct pt_regs *, long); 24extern void bad_trap(struct pt_regs *, long);
14 25
@@ -20,7 +31,6 @@ enum die_val {
20 DIE_DIE, 31 DIE_DIE,
21 DIE_TRAP, 32 DIE_TRAP,
22 DIE_TRAP_TL1, 33 DIE_TRAP_TL1,
23 DIE_GPF,
24 DIE_CALL, 34 DIE_CALL,
25 DIE_PAGE_FAULT, 35 DIE_PAGE_FAULT,
26}; 36};
diff --git a/include/asm-sparc64/kprobes.h b/include/asm-sparc64/kprobes.h
index becc38fa06c5..a331b7b0dff2 100644
--- a/include/asm-sparc64/kprobes.h
+++ b/include/asm-sparc64/kprobes.h
@@ -43,4 +43,5 @@ struct kprobe_ctlblk {
43 43
44extern int kprobe_exceptions_notify(struct notifier_block *self, 44extern int kprobe_exceptions_notify(struct notifier_block *self,
45 unsigned long val, void *data); 45 unsigned long val, void *data);
46extern int kprobe_fault_handler(struct pt_regs *regs, int trapnr);
46#endif /* _SPARC64_KPROBES_H */ 47#endif /* _SPARC64_KPROBES_H */