diff options
Diffstat (limited to 'arch/x86/kernel/traps.c')
| -rw-r--r-- | arch/x86/kernel/traps.c | 18 | 
1 files changed, 17 insertions, 1 deletions
diff --git a/arch/x86/kernel/traps.c b/arch/x86/kernel/traps.c index 142d70c74b0..60788dee0f8 100644 --- a/arch/x86/kernel/traps.c +++ b/arch/x86/kernel/traps.c @@ -392,7 +392,13 @@ static notrace __kprobes void default_do_nmi(struct pt_regs *regs)  		if (notify_die(DIE_NMI_IPI, "nmi_ipi", regs, reason, 2, SIGINT)  								== NOTIFY_STOP)  			return; +  #ifdef CONFIG_X86_LOCAL_APIC +		if (notify_die(DIE_NMI, "nmi", regs, reason, 2, SIGINT) +							== NOTIFY_STOP) +			return; + +#ifndef CONFIG_LOCKUP_DETECTOR  		/*  		 * Ok, so this is none of the documented NMI sources,  		 * so it must be the NMI watchdog. @@ -400,6 +406,7 @@ static notrace __kprobes void default_do_nmi(struct pt_regs *regs)  		if (nmi_watchdog_tick(regs, reason))  			return;  		if (!do_nmi_callback(regs, cpu)) +#endif /* !CONFIG_LOCKUP_DETECTOR */  			unknown_nmi_error(reason, regs);  #else  		unknown_nmi_error(reason, regs); @@ -526,6 +533,7 @@ asmlinkage __kprobes struct pt_regs *sync_regs(struct pt_regs *eregs)  dotraplinkage void __kprobes do_debug(struct pt_regs *regs, long error_code)  {  	struct task_struct *tsk = current; +	int user_icebp = 0;  	unsigned long dr6;  	int si_code; @@ -534,6 +542,14 @@ dotraplinkage void __kprobes do_debug(struct pt_regs *regs, long error_code)  	/* Filter out all the reserved bits which are preset to 1 */  	dr6 &= ~DR6_RESERVED; +	/* +	 * If dr6 has no reason to give us about the origin of this trap, +	 * then it's very likely the result of an icebp/int01 trap. +	 * User wants a sigtrap for that. +	 */ +	if (!dr6 && user_mode(regs)) +		user_icebp = 1; +  	/* Catch kmemcheck conditions first of all! */  	if ((dr6 & DR_STEP) && kmemcheck_trap(regs))  		return; @@ -575,7 +591,7 @@ dotraplinkage void __kprobes do_debug(struct pt_regs *regs, long error_code)  		regs->flags &= ~X86_EFLAGS_TF;  	}  	si_code = get_si_code(tsk->thread.debugreg6); -	if (tsk->thread.debugreg6 & (DR_STEP | DR_TRAP_BITS)) +	if (tsk->thread.debugreg6 & (DR_STEP | DR_TRAP_BITS) || user_icebp)  		send_sigtrap(tsk, regs, error_code, si_code);  	preempt_conditional_cli(regs);  | 
