diff options
| -rw-r--r-- | arch/powerpc/mm/fault.c | 36 | ||||
| -rw-r--r-- | include/asm-powerpc/kdebug.h | 2 |
2 files changed, 37 insertions, 1 deletions
diff --git a/arch/powerpc/mm/fault.c b/arch/powerpc/mm/fault.c index fdbba4206d59..a0a9e1e0061e 100644 --- a/arch/powerpc/mm/fault.c +++ b/arch/powerpc/mm/fault.c | |||
| @@ -40,6 +40,40 @@ | |||
| 40 | #include <asm/kdebug.h> | 40 | #include <asm/kdebug.h> |
| 41 | #include <asm/siginfo.h> | 41 | #include <asm/siginfo.h> |
| 42 | 42 | ||
| 43 | #ifdef CONFIG_KPROBES | ||
| 44 | ATOMIC_NOTIFIER_HEAD(notify_page_fault_chain); | ||
| 45 | |||
| 46 | /* Hook to register for page fault notifications */ | ||
| 47 | int register_page_fault_notifier(struct notifier_block *nb) | ||
| 48 | { | ||
| 49 | return atomic_notifier_chain_register(¬ify_page_fault_chain, nb); | ||
| 50 | } | ||
| 51 | |||
| 52 | int unregister_page_fault_notifier(struct notifier_block *nb) | ||
| 53 | { | ||
| 54 | return atomic_notifier_chain_unregister(¬ify_page_fault_chain, nb); | ||
| 55 | } | ||
| 56 | |||
| 57 | static inline int notify_page_fault(enum die_val val, const char *str, | ||
| 58 | struct pt_regs *regs, long err, int trap, int sig) | ||
| 59 | { | ||
| 60 | struct die_args args = { | ||
| 61 | .regs = regs, | ||
| 62 | .str = str, | ||
| 63 | .err = err, | ||
| 64 | .trapnr = trap, | ||
| 65 | .signr = sig | ||
| 66 | }; | ||
| 67 | return atomic_notifier_call_chain(¬ify_page_fault_chain, val, &args); | ||
| 68 | } | ||
| 69 | #else | ||
| 70 | static inline int notify_page_fault(enum die_val val, const char *str, | ||
| 71 | struct pt_regs *regs, long err, int trap, int sig) | ||
| 72 | { | ||
| 73 | return NOTIFY_DONE; | ||
| 74 | } | ||
| 75 | #endif | ||
| 76 | |||
| 43 | /* | 77 | /* |
| 44 | * Check whether the instruction at regs->nip is a store using | 78 | * Check whether the instruction at regs->nip is a store using |
| 45 | * an update addressing form which will update r1. | 79 | * an update addressing form which will update r1. |
| @@ -142,7 +176,7 @@ int __kprobes do_page_fault(struct pt_regs *regs, unsigned long address, | |||
| 142 | is_write = error_code & ESR_DST; | 176 | is_write = error_code & ESR_DST; |
| 143 | #endif /* CONFIG_4xx || CONFIG_BOOKE */ | 177 | #endif /* CONFIG_4xx || CONFIG_BOOKE */ |
| 144 | 178 | ||
| 145 | if (notify_die(DIE_PAGE_FAULT, "page_fault", regs, error_code, | 179 | if (notify_page_fault(DIE_PAGE_FAULT, "page_fault", regs, error_code, |
| 146 | 11, SIGSEGV) == NOTIFY_STOP) | 180 | 11, SIGSEGV) == NOTIFY_STOP) |
| 147 | return 0; | 181 | return 0; |
| 148 | 182 | ||
diff --git a/include/asm-powerpc/kdebug.h b/include/asm-powerpc/kdebug.h index c01786ab5fa6..532bfee934f4 100644 --- a/include/asm-powerpc/kdebug.h +++ b/include/asm-powerpc/kdebug.h | |||
| @@ -18,6 +18,8 @@ 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 *); | ||
| 22 | extern int unregister_page_fault_notifier(struct notifier_block *); | ||
| 21 | extern struct atomic_notifier_head powerpc_die_chain; | 23 | extern struct atomic_notifier_head powerpc_die_chain; |
| 22 | 24 | ||
| 23 | /* Grossly misnamed. */ | 25 | /* Grossly misnamed. */ |
