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

[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
Loading
Loading
Loading
Loading
+1 −9
Original line number Diff line number Diff line
@@ -410,7 +410,7 @@ out:
	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_ctlblk *kcb = get_kprobe_ctlblk();
@@ -495,14 +495,6 @@ int __kprobes kprobe_exceptions_notify(struct notifier_block *self,
		if (post_kprobe_handler(args->regs))
			ret = NOTIFY_STOP;
		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:
		break;
	}
+15 −27
Original line number Diff line number Diff line
@@ -39,37 +39,26 @@
#include <asm/kdebug.h>
#include <asm/siginfo.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)
{
	return atomic_notifier_chain_register(&notify_page_fault_chain, nb);
}

int unregister_page_fault_notifier(struct notifier_block *nb)
#ifdef CONFIG_KPROBES
static inline int notify_page_fault(struct pt_regs *regs)
{
	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,
			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);
	return ret;
}
#else
static inline int notify_page_fault(enum die_val val, const char *str,
			struct pt_regs *regs, long err, int trap, int sig)
static inline int notify_page_fault(struct pt_regs *regs)
{
	return NOTIFY_DONE;
	return 0;
}
#endif

@@ -175,8 +164,7 @@ int __kprobes do_page_fault(struct pt_regs *regs, unsigned long address,
	is_write = error_code & ESR_DST;
#endif /* CONFIG_4xx || CONFIG_BOOKE */

	if (notify_page_fault(DIE_PAGE_FAULT, "page_fault", regs, error_code,
				11, SIGSEGV) == NOTIFY_STOP)
	if (notify_page_fault(regs))
		return 0;

	if (trap == 0x300) {
+14 −3
Original line number Diff line number Diff line
@@ -18,8 +18,20 @@ struct die_args {

extern int register_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;

/* Grossly misnamed. */
@@ -29,7 +41,6 @@ enum die_val {
	DIE_DABR_MATCH,
	DIE_BPT,
	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)
+1 −0
Original line number Diff line number Diff line
@@ -116,5 +116,6 @@ struct kprobe_ctlblk {

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