Commit 9f90b997 authored by Christoph Hellwig's avatar Christoph Hellwig Committed by Paul Mackerras

[POWERPC] Minor fault path optimization

Call the kprobes pagefault handler directly instead of going through
the complex notifier chain.
Signed-off-by: default avatarChristoph Hellwig <hch@lst.de>
Signed-off-by: default avatarPaul Mackerras <paulus@samba.org>
parent eb609e52
...@@ -410,7 +410,7 @@ static int __kprobes post_kprobe_handler(struct pt_regs *regs) ...@@ -410,7 +410,7 @@ static int __kprobes post_kprobe_handler(struct pt_regs *regs)
return 1; return 1;
} }
static int __kprobes kprobe_fault_handler(struct pt_regs *regs, int trapnr) int __kprobes kprobe_fault_handler(struct pt_regs *regs, int trapnr)
{ {
struct kprobe *cur = kprobe_running(); struct kprobe *cur = kprobe_running();
struct kprobe_ctlblk *kcb = get_kprobe_ctlblk(); struct kprobe_ctlblk *kcb = get_kprobe_ctlblk();
...@@ -495,14 +495,6 @@ int __kprobes kprobe_exceptions_notify(struct notifier_block *self, ...@@ -495,14 +495,6 @@ int __kprobes kprobe_exceptions_notify(struct notifier_block *self,
if (post_kprobe_handler(args->regs)) if (post_kprobe_handler(args->regs))
ret = NOTIFY_STOP; ret = NOTIFY_STOP;
break; break;
case DIE_PAGE_FAULT:
/* kprobe_running() needs smp_processor_id() */
preempt_disable();
if (kprobe_running() &&
kprobe_fault_handler(args->regs, args->trapnr))
ret = NOTIFY_STOP;
preempt_enable();
break;
default: default:
break; break;
} }
......
...@@ -39,37 +39,26 @@ ...@@ -39,37 +39,26 @@
#include <asm/kdebug.h> #include <asm/kdebug.h>
#include <asm/siginfo.h> #include <asm/siginfo.h>
#ifdef CONFIG_KPROBES
ATOMIC_NOTIFIER_HEAD(notify_page_fault_chain);
/* Hook to register for page fault notifications */ #ifdef CONFIG_KPROBES
int register_page_fault_notifier(struct notifier_block *nb) static inline int notify_page_fault(struct pt_regs *regs)
{
return atomic_notifier_chain_register(&notify_page_fault_chain, nb);
}
int unregister_page_fault_notifier(struct notifier_block *nb)
{ {
return atomic_notifier_chain_unregister(&notify_page_fault_chain, nb); int ret = 0;
}
/* kprobe_running() needs smp_processor_id() */
if (!user_mode(regs)) {
preempt_disable();
if (kprobe_running() && kprobe_fault_handler(regs, 11))
ret = 1;
preempt_enable();
}
static inline int notify_page_fault(enum die_val val, const char *str, return ret;
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(&notify_page_fault_chain, val, &args);
} }
#else #else
static inline int notify_page_fault(enum die_val val, const char *str, static inline int notify_page_fault(struct pt_regs *regs)
struct pt_regs *regs, long err, int trap, int sig)
{ {
return NOTIFY_DONE; return 0;
} }
#endif #endif
...@@ -175,8 +164,7 @@ int __kprobes do_page_fault(struct pt_regs *regs, unsigned long address, ...@@ -175,8 +164,7 @@ int __kprobes do_page_fault(struct pt_regs *regs, unsigned long address,
is_write = error_code & ESR_DST; is_write = error_code & ESR_DST;
#endif /* CONFIG_4xx || CONFIG_BOOKE */ #endif /* CONFIG_4xx || CONFIG_BOOKE */
if (notify_page_fault(DIE_PAGE_FAULT, "page_fault", regs, error_code, if (notify_page_fault(regs))
11, SIGSEGV) == NOTIFY_STOP)
return 0; return 0;
if (trap == 0x300) { if (trap == 0x300) {
......
...@@ -18,8 +18,20 @@ struct die_args { ...@@ -18,8 +18,20 @@ struct die_args {
extern int register_die_notifier(struct notifier_block *); extern int register_die_notifier(struct notifier_block *);
extern int unregister_die_notifier(struct notifier_block *); extern int unregister_die_notifier(struct notifier_block *);
extern int register_page_fault_notifier(struct notifier_block *);
extern int unregister_page_fault_notifier(struct notifier_block *); /*
* These are only here because kprobes.c wants them to implement a
* blatant layering violation. Will hopefully go away soon once all
* architectures are updated.
*/
static inline int register_page_fault_notifier(struct notifier_block *nb)
{
return 0;
}
static inline int unregister_page_fault_notifier(struct notifier_block *nb)
{
return 0;
}
extern struct atomic_notifier_head powerpc_die_chain; extern struct atomic_notifier_head powerpc_die_chain;
/* Grossly misnamed. */ /* Grossly misnamed. */
...@@ -29,7 +41,6 @@ enum die_val { ...@@ -29,7 +41,6 @@ enum die_val {
DIE_DABR_MATCH, DIE_DABR_MATCH,
DIE_BPT, DIE_BPT,
DIE_SSTEP, DIE_SSTEP,
DIE_PAGE_FAULT,
}; };
static inline int notify_die(enum die_val val,char *str,struct pt_regs *regs,long err,int trap, int sig) static inline int notify_die(enum die_val val,char *str,struct pt_regs *regs,long err,int trap, int sig)
......
...@@ -116,5 +116,6 @@ struct kprobe_ctlblk { ...@@ -116,5 +116,6 @@ struct kprobe_ctlblk {
extern int kprobe_exceptions_notify(struct notifier_block *self, extern int kprobe_exceptions_notify(struct notifier_block *self,
unsigned long val, void *data); unsigned long val, void *data);
extern int kprobe_fault_handler(struct pt_regs *regs, int trapnr);
#endif /* __KERNEL__ */ #endif /* __KERNEL__ */
#endif /* _ASM_POWERPC_KPROBES_H */ #endif /* _ASM_POWERPC_KPROBES_H */
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment