diff options
-rw-r--r-- | arch/powerpc/kernel/kprobes.c | 10 | ||||
-rw-r--r-- | arch/powerpc/mm/fault.c | 42 | ||||
-rw-r--r-- | include/asm-powerpc/kdebug.h | 17 | ||||
-rw-r--r-- | include/asm-powerpc/kprobes.h | 1 |
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 | ||
413 | static int __kprobes kprobe_fault_handler(struct pt_regs *regs, int trapnr) | 413 | int __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 | ||
43 | ATOMIC_NOTIFIER_HEAD(notify_page_fault_chain); | ||
44 | 42 | ||
45 | /* Hook to register for page fault notifications */ | 43 | #ifdef CONFIG_KPROBES |
46 | int register_page_fault_notifier(struct notifier_block *nb) | 44 | static inline int notify_page_fault(struct pt_regs *regs) |
47 | { | ||
48 | return atomic_notifier_chain_register(¬ify_page_fault_chain, nb); | ||
49 | } | ||
50 | |||
51 | int unregister_page_fault_notifier(struct notifier_block *nb) | ||
52 | { | 45 | { |
53 | return atomic_notifier_chain_unregister(¬ify_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 | ||
56 | static 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(¬ify_page_fault_chain, val, &args); | ||
67 | } | 57 | } |
68 | #else | 58 | #else |
69 | static inline int notify_page_fault(enum die_val val, const char *str, | 59 | static 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 | ||
19 | extern int register_die_notifier(struct notifier_block *); | 19 | extern int register_die_notifier(struct notifier_block *); |
20 | extern int unregister_die_notifier(struct notifier_block *); | 20 | extern int unregister_die_notifier(struct notifier_block *); |
21 | extern int register_page_fault_notifier(struct notifier_block *); | 21 | |
22 | extern 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 | */ | ||
27 | static inline int register_page_fault_notifier(struct notifier_block *nb) | ||
28 | { | ||
29 | return 0; | ||
30 | } | ||
31 | static inline int unregister_page_fault_notifier(struct notifier_block *nb) | ||
32 | { | ||
33 | return 0; | ||
34 | } | ||
23 | extern struct atomic_notifier_head powerpc_die_chain; | 35 | extern 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 | ||
35 | static inline int notify_die(enum die_val val,char *str,struct pt_regs *regs,long err,int trap, int sig) | 46 | static 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 | ||
117 | extern int kprobe_exceptions_notify(struct notifier_block *self, | 117 | extern int kprobe_exceptions_notify(struct notifier_block *self, |
118 | unsigned long val, void *data); | 118 | unsigned long val, void *data); |
119 | extern 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 */ |