From 4ba069b802c29eee066385f9826e2d83716626b4 Mon Sep 17 00:00:00 2001 From: Michael Grundy Date: Wed, 20 Sep 2006 15:58:39 +0200 Subject: [S390] add kprobes support. Signed-off-by: Michael Grundy Signed-off-by: David Wilder Signed-off-by: Martin Schwidefsky --- arch/s390/mm/fault.c | 40 +++++++++++++++++++++++++++++++++++++++- 1 file changed, 39 insertions(+), 1 deletion(-) (limited to 'arch/s390/mm/fault.c') diff --git a/arch/s390/mm/fault.c b/arch/s390/mm/fault.c index 7cd82575813..44f0cda7e72 100644 --- a/arch/s390/mm/fault.c +++ b/arch/s390/mm/fault.c @@ -25,10 +25,12 @@ #include #include #include +#include #include #include #include +#include #ifndef CONFIG_64BIT #define __FAIL_ADDR_MASK 0x7ffff000 @@ -48,6 +50,38 @@ extern int sysctl_userprocess_debug; extern void die(const char *,struct pt_regs *,long); +#ifdef CONFIG_KPROBES +ATOMIC_NOTIFIER_HEAD(notify_page_fault_chain); +int register_page_fault_notifier(struct notifier_block *nb) +{ + return atomic_notifier_chain_register(¬ify_page_fault_chain, nb); +} + +int unregister_page_fault_notifier(struct notifier_block *nb) +{ + return atomic_notifier_chain_unregister(¬ify_page_fault_chain, nb); +} + +static inline int notify_page_fault(enum die_val val, const char *str, + struct pt_regs *regs, long err, int trap, int sig) +{ + struct die_args args = { + .regs = regs, + .str = str, + .err = err, + .trapnr = trap, + .signr = sig + }; + return atomic_notifier_call_chain(¬ify_page_fault_chain, val, &args); +} +#else +static inline int notify_page_fault(enum die_val val, const char *str, + struct pt_regs *regs, long err, int trap, int sig) +{ + return NOTIFY_DONE; +} +#endif + extern spinlock_t timerlist_lock; /* @@ -159,7 +193,7 @@ static void do_sigsegv(struct pt_regs *regs, unsigned long error_code, * 11 Page translation -> Not present (nullification) * 3b Region third trans. -> Not present (nullification) */ -static inline void +static inline void __kprobes do_exception(struct pt_regs *regs, unsigned long error_code, int is_protection) { struct task_struct *tsk; @@ -173,6 +207,10 @@ do_exception(struct pt_regs *regs, unsigned long error_code, int is_protection) tsk = current; mm = tsk->mm; + if (notify_page_fault(DIE_PAGE_FAULT, "page fault", regs, error_code, 14, + SIGSEGV) == NOTIFY_STOP) + return; + /* * Check for low-address protection. This needs to be treated * as a special case because the translation exception code -- cgit v1.2.3