Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit e6349a95 authored by Ananth N Mavinakayanahalli's avatar Ananth N Mavinakayanahalli Committed by Paul Mackerras
Browse files

[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: default avatarAnanth N Mavinakayanahalli <ananth@in.ibm.com>
Signed-off-by: default avatarPaul Mackerras <paulus@samba.org>
parent 6888199f
Loading
Loading
Loading
Loading
+35 −1
Original line number Diff line number Diff line
@@ -59,12 +59,14 @@ int __kprobes arch_prepare_kprobe(struct kprobe *p)
	}

	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(struct pt_regs *regs)
		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;
+5 −0
Original line number Diff line number Diff line
@@ -87,6 +87,11 @@ extern void arch_remove_kprobe(struct kprobe *p);
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 {