aboutsummaryrefslogtreecommitdiffstats
path: root/arch
diff options
context:
space:
mode:
authorChristoph Hellwig <hch@lst.de>2007-05-12 11:56:11 -0400
committerHaavard Skinnemoen <hskinnemoen@atmel.com>2007-05-13 11:07:46 -0400
commit9caebec7b8093574fca5a334a1939530872d75e3 (patch)
tree344415b09f6c08dfc8741420f7410f4e6105b584 /arch
parent5d1938c83ca826891a02badef7c9ea8ed57e01a2 (diff)
[AVR32] optimize pagefault path
Avoid the costly notifier list in the pagefault path and call the kprobes code directly. The same change went into the 2.6.22 cycle for powerpc, 2s390 and sparc64 already. Signed-off-by: Christoph Hellwig <hch@lst.de> Signed-off-by: Haavard Skinnemoen <hskinnemoen@atmel.com>
Diffstat (limited to 'arch')
-rw-r--r--arch/avr32/kernel/kprobes.c7
-rw-r--r--arch/avr32/mm/fault.c36
2 files changed, 13 insertions, 30 deletions
diff --git a/arch/avr32/kernel/kprobes.c b/arch/avr32/kernel/kprobes.c
index 004c94b6fc1d..4942ee662e0b 100644
--- a/arch/avr32/kernel/kprobes.c
+++ b/arch/avr32/kernel/kprobes.c
@@ -179,7 +179,7 @@ static int __kprobes post_kprobe_handler(struct pt_regs *regs)
179 return 1; 179 return 1;
180} 180}
181 181
182static int __kprobes kprobe_fault_handler(struct pt_regs *regs, int trapnr) 182int __kprobes kprobe_fault_handler(struct pt_regs *regs, int trapnr)
183{ 183{
184 struct kprobe *cur = kprobe_running(); 184 struct kprobe *cur = kprobe_running();
185 185
@@ -216,11 +216,6 @@ int __kprobes kprobe_exceptions_notify(struct notifier_block *self,
216 if (post_kprobe_handler(args->regs)) 216 if (post_kprobe_handler(args->regs))
217 ret = NOTIFY_STOP; 217 ret = NOTIFY_STOP;
218 break; 218 break;
219 case DIE_FAULT:
220 if (kprobe_running()
221 && kprobe_fault_handler(args->regs, args->trapnr))
222 ret = NOTIFY_STOP;
223 break;
224 default: 219 default:
225 break; 220 break;
226 } 221 }
diff --git a/arch/avr32/mm/fault.c b/arch/avr32/mm/fault.c
index 88b00b15970f..e011f1ce1875 100644
--- a/arch/avr32/mm/fault.c
+++ b/arch/avr32/mm/fault.c
@@ -12,41 +12,30 @@
12#include <linux/mm.h> 12#include <linux/mm.h>
13#include <linux/module.h> 13#include <linux/module.h>
14#include <linux/pagemap.h> 14#include <linux/pagemap.h>
15
16#include <linux/kdebug.h> 15#include <linux/kdebug.h>
16#include <linux/kprobes.h>
17
17#include <asm/mmu_context.h> 18#include <asm/mmu_context.h>
18#include <asm/sysreg.h> 19#include <asm/sysreg.h>
19#include <asm/tlb.h> 20#include <asm/tlb.h>
20#include <asm/uaccess.h> 21#include <asm/uaccess.h>
21 22
22#ifdef CONFIG_KPROBES 23#ifdef CONFIG_KPROBES
23ATOMIC_NOTIFIER_HEAD(notify_page_fault_chain); 24static inline int notify_page_fault(struct pt_regs *regs, int trap)
24
25/* Hook to register for page fault notifications */
26int register_page_fault_notifier(struct notifier_block *nb)
27{ 25{
28 return atomic_notifier_chain_register(&notify_page_fault_chain, nb); 26 int ret = 0;
29}
30 27
31int unregister_page_fault_notifier(struct notifier_block *nb) 28 if (!user_mode(regs)) {
32{ 29 if (kprobe_running() && kprobe_fault_handler(regs, trap))
33 return atomic_notifier_chain_unregister(&notify_page_fault_chain, nb); 30 ret = 1;
34} 31 }
35 32
36static inline int notify_page_fault(enum die_val val, struct pt_regs *regs, 33 return ret;
37 int trap, int sig)
38{
39 struct die_args args = {
40 .regs = regs,
41 .trapnr = trap,
42 };
43 return atomic_notifier_call_chain(&notify_page_fault_chain, val, &args);
44} 34}
45#else 35#else
46static inline int notify_page_fault(enum die_val val, struct pt_regs *regs, 36static inline int notify_page_fault(struct pt_regs *regs, int trap)
47 int trap, int sig)
48{ 37{
49 return NOTIFY_DONE; 38 return 0;
50} 39}
51#endif 40#endif
52 41
@@ -76,8 +65,7 @@ asmlinkage void do_page_fault(unsigned long ecr, struct pt_regs *regs)
76 long signr; 65 long signr;
77 int code; 66 int code;
78 67
79 if (notify_page_fault(DIE_PAGE_FAULT, regs, 68 if (notify_page_fault(regs, ecr))
80 ecr, SIGSEGV) == NOTIFY_STOP)
81 return; 69 return;
82 70
83 address = sysreg_read(TLBEAR); 71 address = sysreg_read(TLBEAR);