diff options
author | Anil S Keshavamurthy <anil.s.keshavamurthy@intel.com> | 2006-06-26 03:25:27 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@g5.osdl.org> | 2006-06-26 12:58:22 -0400 |
commit | 4f9e87c0454059e80f3811f95ad9f40ed28c69a2 (patch) | |
tree | cc8290b8fc757b34e01a4e9c25bbe00496400084 /arch/powerpc | |
parent | ae9a5b85655d7133ab8e7c99b742ef20c8dbb7d2 (diff) |
[PATCH] Notify page fault call chain for powerpc
Overloading of page fault notification with the notify_die() has performance
issues(since the only interested components for page fault is kprobes and/or
kdb) and hence this patch introduces the new notifier call chain exclusively
for page fault notifications their by avoiding notifying unnecessary
components in the do_page_fault() code path.
Signed-off-by: Anil S Keshavamurthy <anil.s.keshavamurthy@intel.com>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Diffstat (limited to 'arch/powerpc')
-rw-r--r-- | arch/powerpc/mm/fault.c | 36 |
1 files changed, 35 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 | ||