Skip to content

Commit

Permalink
[AVR32] optimize pagefault path
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Christoph Hellwig authored and Haavard Skinnemoen committed May 13, 2007
1 parent 5d1938c commit 9caebec
Show file tree
Hide file tree
Showing 4 changed files with 27 additions and 34 deletions.
7 changes: 1 addition & 6 deletions arch/avr32/kernel/kprobes.c
Original file line number Diff line number Diff line change
Expand Up @@ -179,7 +179,7 @@ static int __kprobes post_kprobe_handler(struct pt_regs *regs)
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();

Expand Down Expand Up @@ -216,11 +216,6 @@ int __kprobes kprobe_exceptions_notify(struct notifier_block *self,
if (post_kprobe_handler(args->regs))
ret = NOTIFY_STOP;
break;
case DIE_FAULT:
if (kprobe_running()
&& kprobe_fault_handler(args->regs, args->trapnr))
ret = NOTIFY_STOP;
break;
default:
break;
}
Expand Down
36 changes: 12 additions & 24 deletions arch/avr32/mm/fault.c
Original file line number Diff line number Diff line change
Expand Up @@ -12,41 +12,30 @@
#include <linux/mm.h>
#include <linux/module.h>
#include <linux/pagemap.h>

#include <linux/kdebug.h>
#include <linux/kprobes.h>

#include <asm/mmu_context.h>
#include <asm/sysreg.h>
#include <asm/tlb.h>
#include <asm/uaccess.h>

#ifdef CONFIG_KPROBES
ATOMIC_NOTIFIER_HEAD(notify_page_fault_chain);

/* Hook to register for page fault notifications */
int register_page_fault_notifier(struct notifier_block *nb)
static inline int notify_page_fault(struct pt_regs *regs, int trap)
{
return atomic_notifier_chain_register(&notify_page_fault_chain, nb);
}
int ret = 0;

int unregister_page_fault_notifier(struct notifier_block *nb)
{
return atomic_notifier_chain_unregister(&notify_page_fault_chain, nb);
}
if (!user_mode(regs)) {
if (kprobe_running() && kprobe_fault_handler(regs, trap))
ret = 1;
}

static inline int notify_page_fault(enum die_val val, struct pt_regs *regs,
int trap, int sig)
{
struct die_args args = {
.regs = regs,
.trapnr = trap,
};
return atomic_notifier_call_chain(&notify_page_fault_chain, val, &args);
return ret;
}
#else
static inline int notify_page_fault(enum die_val val, struct pt_regs *regs,
int trap, int sig)
static inline int notify_page_fault(struct pt_regs *regs, int trap)
{
return NOTIFY_DONE;
return 0;
}
#endif

Expand Down Expand Up @@ -76,8 +65,7 @@ asmlinkage void do_page_fault(unsigned long ecr, struct pt_regs *regs)
long signr;
int code;

if (notify_page_fault(DIE_PAGE_FAULT, regs,
ecr, SIGSEGV) == NOTIFY_STOP)
if (notify_page_fault(regs, ecr))
return;

address = sysreg_read(TLBEAR);
Expand Down
17 changes: 13 additions & 4 deletions include/asm-avr32/kdebug.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,22 @@

/* Grossly misnamed. */
enum die_val {
DIE_FAULT,
DIE_BREAKPOINT,
DIE_SSTEP,
DIE_PAGE_FAULT,
};

int register_page_fault_notifier(struct notifier_block *nb);
int unregister_page_fault_notifier(struct notifier_block *nb);
/*
* 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;
}

#endif /* __ASM_AVR32_KDEBUG_H */
1 change: 1 addition & 0 deletions include/asm-avr32/kprobes.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ struct arch_specific_insn {
kprobe_opcode_t insn[MAX_INSN_SIZE];
};

extern int kprobe_fault_handler(struct pt_regs *regs, int trapnr);
extern int kprobe_exceptions_notify(struct notifier_block *self,
unsigned long val, void *data);

Expand Down

0 comments on commit 9caebec

Please sign in to comment.