[PATCH] kprobes: eliminate sstep exception if instruction can be emulated
From: Ananth N Mavinakayanahalli <hidden>
Date: 2007-04-18 05:54:14
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 <redacted> --- 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 {