[PATCH] kprobes: eliminate sstep exception if instruction can be emulated

Ananth N Mavinakayanahalli ananth at in.ibm.com
Wed Apr 18 15:57:51 EST 2007


For cases when probes are placed on instructions that can be emulated,
don't take the single-step exception.

Signed-off-by: Ananth N Mavinakayanahalli <ananth at in.ibm.com>
---
 arch/powerpc/kernel/kprobes.c |   36 +++++++++++++++++++++++++++++++++++-
 include/asm-powerpc/kprobes.h |    5 +++++
 2 files changed, 40 insertions(+), 1 deletion(-)

Index: linux-2.6.21-rc7/arch/powerpc/kernel/kprobes.c
===================================================================
--- linux-2.6.21-rc7.orig/arch/powerpc/kernel/kprobes.c
+++ linux-2.6.21-rc7/arch/powerpc/kernel/kprobes.c
@@ -59,12 +59,14 @@ int __kprobes arch_prepare_kprobe(struct
 	}
 
 	if (!ret) {
-		memcpy(p->ainsn.insn, p->addr, MAX_INSN_SIZE * sizeof(kprobe_opcode_t));
+		memcpy(p->ainsn.insn, p->addr,
+				MAX_INSN_SIZE * sizeof(kprobe_opcode_t));
 		p->opcode = *p->addr;
 		flush_icache_range((unsigned long)p->ainsn.insn,
 			(unsigned long)p->ainsn.insn + sizeof(kprobe_opcode_t));
 	}
 
+	p->ainsn.boostable = 0;
 	return ret;
 }
 
@@ -232,6 +234,38 @@ static int __kprobes kprobe_handler(stru
 		return 1;
 
 ss_probe:
+	if (p->ainsn.boostable >= 0) {
+		unsigned int insn = *p->ainsn.insn;
+
+		/* regs->nip is also adjusted if emulate_step returns 1 */
+		ret = emulate_step(regs, insn);
+		if (ret > 0) {
+			/*
+			 * Once this instruction has been boosted
+			 * successfully, set the boostable flag
+			 */
+			if (unlikely(p->ainsn.boostable == 0))
+				p->ainsn.boostable = 1;
+
+			if (p->post_handler)
+				p->post_handler(p, regs, 0);
+
+			kcb->kprobe_status = KPROBE_HIT_SSDONE;
+			reset_current_kprobe();
+			preempt_enable_no_resched();
+			return 1;
+		} else if (ret < 0) {
+			/*
+			 * We don't allow kprobes on mtmsr(d)/rfi(d), etc.
+			 * So, we should never get here... but, its still
+			 * good to catch them, just in case...
+			 */
+			printk("Can't step on instruction %x\n", insn);
+			BUG();
+		} else if (ret == 0)
+			/* This instruction can't be boosted */
+			p->ainsn.boostable = -1;
+	}
 	prepare_singlestep(p, regs);
 	kcb->kprobe_status = KPROBE_HIT_SS;
 	return 1;
Index: linux-2.6.21-rc7/include/asm-powerpc/kprobes.h
===================================================================
--- linux-2.6.21-rc7.orig/include/asm-powerpc/kprobes.h
+++ linux-2.6.21-rc7/include/asm-powerpc/kprobes.h
@@ -87,6 +87,11 @@ extern void arch_remove_kprobe(struct kp
 struct arch_specific_insn {
 	/* copy of original instruction */
 	kprobe_opcode_t *insn;
+	/*
+	 * Set in kprobes code, initially to 0. If the instruction can be
+	 * eumulated, this is set to 1, if not, to -1.
+	 */
+	int boostable;
 };
 
 struct prev_kprobe {



More information about the Linuxppc-dev mailing list