]> bbs.cooldavid.org Git - net-next-2.6.git/commitdiff
[S390] fix kprobes single stepping
authorMartin Schwidefsky <schwidefsky@de.ibm.com>
Fri, 29 Oct 2010 14:50:45 +0000 (16:50 +0200)
committerMartin Schwidefsky <sky@mschwide.boeblingen.de.ibm.com>
Fri, 29 Oct 2010 14:50:50 +0000 (16:50 +0200)
Fix kprobes after git commit 1e54622e0403891b10f2105663e0f9dd595a1f17
broke it. The kprobe_handler is now called with interrupts in the state
at the time of the breakpoint. The single step of the replaced instruction
is done with interrupts off which makes it necessary to enable and disable
the interupts in the kprobes code.

Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
arch/s390/kernel/entry.S
arch/s390/kernel/entry64.S
arch/s390/kernel/kprobes.c

index 5efce7202984ad969031922a21a39531014782de..1ecc337fb679045e968ef1915ea009c4777786de 100644 (file)
@@ -557,6 +557,7 @@ pgm_svcper:
 # per was called from kernel, must be kprobes
 #
 kernel_per:
+       REENABLE_IRQS
        mvi     SP_SVCNR(%r15),0xff     # set trap indication to pgm check
        mvi     SP_SVCNR+1(%r15),0xff
        la      %r2,SP_PTREGS(%r15)     # address of register-save area
index a2be23922f4339849b97551e67f1c67fc0cbfbe7..8f3e802174db8382f7adc41bfc2949c4f231236b 100644 (file)
@@ -568,6 +568,7 @@ pgm_svcper:
 # per was called from kernel, must be kprobes
 #
 kernel_per:
+       REENABLE_IRQS
        xc      SP_SVCNR(2,%r15),SP_SVCNR(%r15) # clear svc number
        la      %r2,SP_PTREGS(%r15)     # address of register-save area
        brasl   %r14,do_single_step
index 2a3d2bf6f083070678f4c777b4cea0db00b9ff74..d60fc439851658761cd105d8d403be2e69fee0ad 100644 (file)
@@ -316,6 +316,8 @@ static int __kprobes kprobe_handler(struct pt_regs *regs)
                return 1;
 
 ss_probe:
+       if (regs->psw.mask & (PSW_MASK_PER | PSW_MASK_IO))
+               local_irq_disable();
        prepare_singlestep(p, regs);
        kcb->kprobe_status = KPROBE_HIT_SS;
        return 1;
@@ -463,6 +465,8 @@ static int __kprobes post_kprobe_handler(struct pt_regs *regs)
                goto out;
        }
        reset_current_kprobe();
+       if (regs->psw.mask & (PSW_MASK_PER | PSW_MASK_IO))
+               local_irq_enable();
 out:
        preempt_enable_no_resched();
 
@@ -502,8 +506,11 @@ int __kprobes kprobe_fault_handler(struct pt_regs *regs, int trapnr)
                regs->psw.mask |= kcb->kprobe_saved_imask;
                if (kcb->kprobe_status == KPROBE_REENTER)
                        restore_previous_kprobe(kcb);
-               else
+               else {
                        reset_current_kprobe();
+                       if (regs->psw.mask & (PSW_MASK_PER | PSW_MASK_IO))
+                               local_irq_enable();
+               }
                preempt_enable_no_resched();
                break;
        case KPROBE_HIT_ACTIVE: