aboutsummaryrefslogtreecommitdiffstats
path: root/arch/sparc64/kernel/kprobes.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/sparc64/kernel/kprobes.c')
-rw-r--r--arch/sparc64/kernel/kprobes.c16
1 files changed, 14 insertions, 2 deletions
diff --git a/arch/sparc64/kernel/kprobes.c b/arch/sparc64/kernel/kprobes.c
index 491bf28a4370d..7066d7ba667a5 100644
--- a/arch/sparc64/kernel/kprobes.c
+++ b/arch/sparc64/kernel/kprobes.c
@@ -68,8 +68,14 @@ static inline void prepare_singlestep(struct kprobe *p, struct pt_regs *regs)
current_kprobe_orig_tstate_pil = (regs->tstate & TSTATE_PIL);
regs->tstate |= TSTATE_PIL;
- regs->tpc = (unsigned long) &p->ainsn.insn[0];
- regs->tnpc = (unsigned long) &p->ainsn.insn[1];
+ /*single step inline, if it a breakpoint instruction*/
+ if (p->opcode == BREAKPOINT_INSTRUCTION) {
+ regs->tpc = (unsigned long) p->addr;
+ regs->tnpc = current_kprobe_orig_tnpc;
+ } else {
+ regs->tpc = (unsigned long) &p->ainsn.insn[0];
+ regs->tnpc = (unsigned long) &p->ainsn.insn[1];
+ }
}
static inline void disarm_kprobe(struct kprobe *p, struct pt_regs *regs)
@@ -97,6 +103,12 @@ static int kprobe_handler(struct pt_regs *regs)
*/
p = get_kprobe(addr);
if (p) {
+ if (kprobe_status == KPROBE_HIT_SS) {
+ regs->tstate = ((regs->tstate & ~TSTATE_PIL) |
+ current_kprobe_orig_tstate_pil);
+ unlock_kprobes();
+ goto no_kprobe;
+ }
disarm_kprobe(p, regs);
ret = 1;
} else {