diff options
Diffstat (limited to 'arch/x86/kernel/kprobes.c')
| -rw-r--r-- | arch/x86/kernel/kprobes.c | 27 | 
1 files changed, 13 insertions, 14 deletions
diff --git a/arch/x86/kernel/kprobes.c b/arch/x86/kernel/kprobes.c index b43bbaebe2c..1658efdfb4e 100644 --- a/arch/x86/kernel/kprobes.c +++ b/arch/x86/kernel/kprobes.c @@ -534,20 +534,6 @@ static int __kprobes kprobe_handler(struct pt_regs *regs)  	struct kprobe_ctlblk *kcb;  	addr = (kprobe_opcode_t *)(regs->ip - sizeof(kprobe_opcode_t)); -	if (*addr != BREAKPOINT_INSTRUCTION) { -		/* -		 * The breakpoint instruction was removed right -		 * after we hit it.  Another cpu has removed -		 * either a probepoint or a debugger breakpoint -		 * at this address.  In either case, no further -		 * handling of this interrupt is appropriate. -		 * Back up over the (now missing) int3 and run -		 * the original instruction. -		 */ -		regs->ip = (unsigned long)addr; -		return 1; -	} -  	/*  	 * We don't want to be preempted for the entire  	 * duration of kprobe processing. We conditionally @@ -579,6 +565,19 @@ static int __kprobes kprobe_handler(struct pt_regs *regs)  				setup_singlestep(p, regs, kcb, 0);  			return 1;  		} +	} else if (*addr != BREAKPOINT_INSTRUCTION) { +		/* +		 * The breakpoint instruction was removed right +		 * after we hit it.  Another cpu has removed +		 * either a probepoint or a debugger breakpoint +		 * at this address.  In either case, no further +		 * handling of this interrupt is appropriate. +		 * Back up over the (now missing) int3 and run +		 * the original instruction. +		 */ +		regs->ip = (unsigned long)addr; +		preempt_enable_no_resched(); +		return 1;  	} else if (kprobe_running()) {  		p = __get_cpu_var(current_kprobe);  		if (p->break_handler && p->break_handler(p, regs)) {  |