[POWERPC] kprobes: Eliminate sstep exception if instruction can be emulated

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@in.ibm.com>
Signed-off-by: Paul Mackerras <paulus@samba.org>
This commit is contained in:
Ananth N Mavinakayanahalli 2007-04-18 15:57:51 +10:00 committed by Paul Mackerras
parent 6888199f7f
commit e6349a958b
2 changed files with 40 additions and 1 deletions

View File

@ -59,12 +59,14 @@ int __kprobes arch_prepare_kprobe(struct kprobe *p)
} }
if (!ret) { 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; p->opcode = *p->addr;
flush_icache_range((unsigned long)p->ainsn.insn, flush_icache_range((unsigned long)p->ainsn.insn,
(unsigned long)p->ainsn.insn + sizeof(kprobe_opcode_t)); (unsigned long)p->ainsn.insn + sizeof(kprobe_opcode_t));
} }
p->ainsn.boostable = 0;
return ret; return ret;
} }
@ -232,6 +234,38 @@ static int __kprobes kprobe_handler(struct pt_regs *regs)
return 1; return 1;
ss_probe: 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); prepare_singlestep(p, regs);
kcb->kprobe_status = KPROBE_HIT_SS; kcb->kprobe_status = KPROBE_HIT_SS;
return 1; return 1;

View File

@ -87,6 +87,11 @@ extern void arch_remove_kprobe(struct kprobe *p);
struct arch_specific_insn { struct arch_specific_insn {
/* copy of original instruction */ /* copy of original instruction */
kprobe_opcode_t *insn; 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 { struct prev_kprobe {