aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/powerpc/kernel/kprobes.c10
-rw-r--r--arch/powerpc/mm/fault.c42
-rw-r--r--include/asm-powerpc/kdebug.h17
-rw-r--r--include/asm-powerpc/kprobes.h1
4 files changed, 31 insertions, 39 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) {
diff --git a/include/asm-powerpc/kdebug.h b/include/asm-powerpc/kdebug.h
index 532bfee934f4..df996b933def 100644
--- a/include/asm-powerpc/kdebug.h
+++ b/include/asm-powerpc/kdebug.h
@@ -18,8 +18,20 @@ struct die_args {
18 18
19extern int register_die_notifier(struct notifier_block *); 19extern int register_die_notifier(struct notifier_block *);
20extern int unregister_die_notifier(struct notifier_block *); 20extern int unregister_die_notifier(struct notifier_block *);
21extern int register_page_fault_notifier(struct notifier_block *); 21
22extern int unregister_page_fault_notifier(struct notifier_block *); 22/*
23 * These are only here because kprobes.c wants them to implement a
24 * blatant layering violation. Will hopefully go away soon once all
25 * architectures are updated.
26 */
27static inline int register_page_fault_notifier(struct notifier_block *nb)
28{
29 return 0;
30}
31static inline int unregister_page_fault_notifier(struct notifier_block *nb)
32{
33 return 0;
34}
23extern struct atomic_notifier_head powerpc_die_chain; 35extern struct atomic_notifier_head powerpc_die_chain;
24 36
25/* Grossly misnamed. */ 37/* Grossly misnamed. */
@@ -29,7 +41,6 @@ enum die_val {
29 DIE_DABR_MATCH, 41 DIE_DABR_MATCH,
30 DIE_BPT, 42 DIE_BPT,
31 DIE_SSTEP, 43 DIE_SSTEP,
32 DIE_PAGE_FAULT,
33}; 44};
34 45
35static inline int notify_die(enum die_val val,char *str,struct pt_regs *regs,long err,int trap, int sig) 46static inline int notify_die(enum die_val val,char *str,struct pt_regs *regs,long err,int trap, int sig)
diff --git a/include/asm-powerpc/kprobes.h b/include/asm-powerpc/kprobes.h
index fc713e595982..b0e40ff32ee0 100644
--- a/include/asm-powerpc/kprobes.h
+++ b/include/asm-powerpc/kprobes.h
@@ -116,5 +116,6 @@ struct kprobe_ctlblk {
116 116
117extern int kprobe_exceptions_notify(struct notifier_block *self, 117extern int kprobe_exceptions_notify(struct notifier_block *self,
118 unsigned long val, void *data); 118 unsigned long val, void *data);
119extern int kprobe_fault_handler(struct pt_regs *regs, int trapnr);
119#endif /* __KERNEL__ */ 120#endif /* __KERNEL__ */
120#endif /* _ASM_POWERPC_KPROBES_H */ 121#endif /* _ASM_POWERPC_KPROBES_H */