aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc
diff options
context:
space:
mode:
authorChristoph Hellwig <hch@infradead.org>2007-04-30 06:56:46 -0400
committerPaul Mackerras <paulus@samba.org>2007-05-02 06:57:39 -0400
commit9f90b997de4efd5404a8c52f89c400f0f4e2d216 (patch)
tree7dd6adc27b196e672fedd464a42700e336cd210a /arch/powerpc
parenteb609e52d188775da738a1ffd1e982e6212c77d7 (diff)
[POWERPC] Minor fault path optimization
Call the kprobes pagefault handler directly instead of going through the complex notifier chain. Signed-off-by: Christoph Hellwig <hch@lst.de> Signed-off-by: Paul Mackerras <paulus@samba.org>
Diffstat (limited to 'arch/powerpc')
-rw-r--r--arch/powerpc/kernel/kprobes.c10
-rw-r--r--arch/powerpc/mm/fault.c42
2 files changed, 16 insertions, 36 deletions
diff --git a/arch/powerpc/kernel/kprobes.c b/arch/powerpc/kernel/kprobes.c
index ef647e7a9dc3..c27f41870c8f 100644
--- a/arch/powerpc/kernel/kprobes.c
+++ b/arch/powerpc/kernel/kprobes.c
@@ -410,7 +410,7 @@ out:
410 return 1; 410 return 1;
411} 411}
412 412
413static int __kprobes kprobe_fault_handler(struct pt_regs *regs, int trapnr) 413int __kprobes kprobe_fault_handler(struct pt_regs *regs, int trapnr)
414{ 414{
415 struct kprobe *cur = kprobe_running(); 415 struct kprobe *cur = kprobe_running();
416 struct kprobe_ctlblk *kcb = get_kprobe_ctlblk(); 416 struct kprobe_ctlblk *kcb = get_kprobe_ctlblk();
@@ -495,14 +495,6 @@ int __kprobes kprobe_exceptions_notify(struct notifier_block *self,
495 if (post_kprobe_handler(args->regs)) 495 if (post_kprobe_handler(args->regs))
496 ret = NOTIFY_STOP; 496 ret = NOTIFY_STOP;
497 break; 497 break;
498 case DIE_PAGE_FAULT:
499 /* kprobe_running() needs smp_processor_id() */
500 preempt_disable();
501 if (kprobe_running() &&
502 kprobe_fault_handler(args->regs, args->trapnr))
503 ret = NOTIFY_STOP;
504 preempt_enable();
505 break;
506 default: 498 default:
507 break; 499 break;
508 } 500 }
diff --git a/arch/powerpc/mm/fault.c b/arch/powerpc/mm/fault.c
index 03aeb3a46077..a0f88026e464 100644
--- a/arch/powerpc/mm/fault.c
+++ b/arch/powerpc/mm/fault.c
@@ -39,37 +39,26 @@
39#include <asm/kdebug.h> 39#include <asm/kdebug.h>
40#include <asm/siginfo.h> 40#include <asm/siginfo.h>
41 41
42#ifdef CONFIG_KPROBES
43ATOMIC_NOTIFIER_HEAD(notify_page_fault_chain);
44 42
45/* Hook to register for page fault notifications */ 43#ifdef CONFIG_KPROBES
46int register_page_fault_notifier(struct notifier_block *nb) 44static inline int notify_page_fault(struct pt_regs *regs)
47{
48 return atomic_notifier_chain_register(&notify_page_fault_chain, nb);
49}
50
51int unregister_page_fault_notifier(struct notifier_block *nb)
52{ 45{
53 return atomic_notifier_chain_unregister(&notify_page_fault_chain, nb); 46 int ret = 0;
54} 47
48 /* kprobe_running() needs smp_processor_id() */
49 if (!user_mode(regs)) {
50 preempt_disable();
51 if (kprobe_running() && kprobe_fault_handler(regs, 11))
52 ret = 1;
53 preempt_enable();
54 }
55 55
56static inline int notify_page_fault(enum die_val val, const char *str, 56 return ret;
57 struct pt_regs *regs, long err, int trap, int sig)
58{
59 struct die_args args = {
60 .regs = regs,
61 .str = str,
62 .err = err,
63 .trapnr = trap,
64 .signr = sig
65 };
66 return atomic_notifier_call_chain(&notify_page_fault_chain, val, &args);
67} 57}
68#else 58#else
69static inline int notify_page_fault(enum die_val val, const char *str, 59static inline int notify_page_fault(struct pt_regs *regs)
70 struct pt_regs *regs, long err, int trap, int sig)
71{ 60{
72 return NOTIFY_DONE; 61 return 0;
73} 62}
74#endif 63#endif
75 64
@@ -175,8 +164,7 @@ int __kprobes do_page_fault(struct pt_regs *regs, unsigned long address,
175 is_write = error_code & ESR_DST; 164 is_write = error_code & ESR_DST;
176#endif /* CONFIG_4xx || CONFIG_BOOKE */ 165#endif /* CONFIG_4xx || CONFIG_BOOKE */
177 166
178 if (notify_page_fault(DIE_PAGE_FAULT, "page_fault", regs, error_code, 167 if (notify_page_fault(regs))
179 11, SIGSEGV) == NOTIFY_STOP)
180 return 0; 168 return 0;
181 169
182 if (trap == 0x300) { 170 if (trap == 0x300) {