Переглянути джерело

[S390] fix kprobes single stepping

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>
Martin Schwidefsky 14 роки тому
батько
коміт
9ec2708053
3 змінених файлів з 10 додано та 1 видалено
  1. 1 0
      arch/s390/kernel/entry.S
  2. 1 0
      arch/s390/kernel/entry64.S
  3. 8 1
      arch/s390/kernel/kprobes.c

+ 1 - 0
arch/s390/kernel/entry.S

@@ -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

+ 1 - 0
arch/s390/kernel/entry64.S

@@ -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

+ 8 - 1
arch/s390/kernel/kprobes.c

@@ -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: