[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>

authored by Christoph Hellwig and committed by Haavard Skinnemoen 9caebec7 5d1938c8

+27 -34
+1 -6
arch/avr32/kernel/kprobes.c
··· 179 return 1; 180 } 181 182 - static int __kprobes kprobe_fault_handler(struct pt_regs *regs, int trapnr) 183 { 184 struct kprobe *cur = kprobe_running(); 185 ··· 214 break; 215 case DIE_SSTEP: 216 if (post_kprobe_handler(args->regs)) 217 - ret = NOTIFY_STOP; 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:
··· 179 return 1; 180 } 181 182 + int __kprobes kprobe_fault_handler(struct pt_regs *regs, int trapnr) 183 { 184 struct kprobe *cur = kprobe_running(); 185 ··· 214 break; 215 case DIE_SSTEP: 216 if (post_kprobe_handler(args->regs)) 217 ret = NOTIFY_STOP; 218 break; 219 default:
+12 -24
arch/avr32/mm/fault.c
··· 12 #include <linux/mm.h> 13 #include <linux/module.h> 14 #include <linux/pagemap.h> 15 - 16 #include <linux/kdebug.h> 17 #include <asm/mmu_context.h> 18 #include <asm/sysreg.h> 19 #include <asm/tlb.h> 20 #include <asm/uaccess.h> 21 22 #ifdef CONFIG_KPROBES 23 - ATOMIC_NOTIFIER_HEAD(notify_page_fault_chain); 24 - 25 - /* Hook to register for page fault notifications */ 26 - int register_page_fault_notifier(struct notifier_block *nb) 27 { 28 - return atomic_notifier_chain_register(&notify_page_fault_chain, nb); 29 - } 30 31 - int unregister_page_fault_notifier(struct notifier_block *nb) 32 - { 33 - return atomic_notifier_chain_unregister(&notify_page_fault_chain, nb); 34 - } 35 36 - static inline int notify_page_fault(enum die_val val, struct pt_regs *regs, 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 } 45 #else 46 - static inline int notify_page_fault(enum die_val val, struct pt_regs *regs, 47 - int trap, int sig) 48 { 49 - return NOTIFY_DONE; 50 } 51 #endif 52 ··· 65 long signr; 66 int code; 67 68 - if (notify_page_fault(DIE_PAGE_FAULT, regs, 69 - ecr, SIGSEGV) == NOTIFY_STOP) 70 return; 71 72 address = sysreg_read(TLBEAR);
··· 12 #include <linux/mm.h> 13 #include <linux/module.h> 14 #include <linux/pagemap.h> 15 #include <linux/kdebug.h> 16 + #include <linux/kprobes.h> 17 + 18 #include <asm/mmu_context.h> 19 #include <asm/sysreg.h> 20 #include <asm/tlb.h> 21 #include <asm/uaccess.h> 22 23 #ifdef CONFIG_KPROBES 24 + static inline int notify_page_fault(struct pt_regs *regs, int trap) 25 { 26 + int ret = 0; 27 28 + if (!user_mode(regs)) { 29 + if (kprobe_running() && kprobe_fault_handler(regs, trap)) 30 + ret = 1; 31 + } 32 33 + return ret; 34 } 35 #else 36 + static inline int notify_page_fault(struct pt_regs *regs, int trap) 37 { 38 + return 0; 39 } 40 #endif 41 ··· 76 long signr; 77 int code; 78 79 + if (notify_page_fault(regs, ecr)) 80 return; 81 82 address = sysreg_read(TLBEAR);
+13 -4
include/asm-avr32/kdebug.h
··· 5 6 /* Grossly misnamed. */ 7 enum die_val { 8 - DIE_FAULT, 9 DIE_BREAKPOINT, 10 DIE_SSTEP, 11 - DIE_PAGE_FAULT, 12 }; 13 14 - int register_page_fault_notifier(struct notifier_block *nb); 15 - int unregister_page_fault_notifier(struct notifier_block *nb); 16 17 #endif /* __ASM_AVR32_KDEBUG_H */
··· 5 6 /* Grossly misnamed. */ 7 enum die_val { 8 DIE_BREAKPOINT, 9 DIE_SSTEP, 10 }; 11 12 + /* 13 + * These are only here because kprobes.c wants them to implement a 14 + * blatant layering violation. Will hopefully go away soon once all 15 + * architectures are updated. 16 + */ 17 + static inline int register_page_fault_notifier(struct notifier_block *nb) 18 + { 19 + return 0; 20 + } 21 + static inline int unregister_page_fault_notifier(struct notifier_block *nb) 22 + { 23 + return 0; 24 + } 25 26 #endif /* __ASM_AVR32_KDEBUG_H */
+1
include/asm-avr32/kprobes.h
··· 26 kprobe_opcode_t insn[MAX_INSN_SIZE]; 27 }; 28 29 extern int kprobe_exceptions_notify(struct notifier_block *self, 30 unsigned long val, void *data); 31
··· 26 kprobe_opcode_t insn[MAX_INSN_SIZE]; 27 }; 28 29 + extern int kprobe_fault_handler(struct pt_regs *regs, int trapnr); 30 extern int kprobe_exceptions_notify(struct notifier_block *self, 31 unsigned long val, void *data); 32