diff options
Diffstat (limited to 'arch/x86/kernel/traps.c')
| -rw-r--r-- | arch/x86/kernel/traps.c | 134 | 
1 files changed, 70 insertions, 64 deletions
diff --git a/arch/x86/kernel/traps.c b/arch/x86/kernel/traps.c index ec61d4c1b93..ff9281f1602 100644 --- a/arch/x86/kernel/traps.c +++ b/arch/x86/kernel/traps.c @@ -50,7 +50,6 @@  #include <asm/processor.h>  #include <asm/debugreg.h>  #include <linux/atomic.h> -#include <asm/system.h>  #include <asm/traps.h>  #include <asm/desc.h>  #include <asm/i387.h> @@ -120,7 +119,7 @@ do_trap(int trapnr, int signr, char *str, struct pt_regs *regs,  		 * traps 0, 1, 3, 4, and 5 should be forwarded to vm86.  		 * On nmi (interrupt 2), do_trap should not be called.  		 */ -		if (trapnr < 6) +		if (trapnr < X86_TRAP_UD)  			goto vm86_trap;  		goto trap_signal;  	} @@ -133,7 +132,7 @@ do_trap(int trapnr, int signr, char *str, struct pt_regs *regs,  trap_signal:  #endif  	/* -	 * We want error_code and trap_no set for userspace faults and +	 * We want error_code and trap_nr set for userspace faults and  	 * kernelspace faults which result in die(), but not  	 * kernelspace faults which are fixed up.  die() gives the  	 * process no chance to handle the signal and notice the @@ -142,7 +141,7 @@ trap_signal:  	 * delivered, faults.  See also do_general_protection below.  	 */  	tsk->thread.error_code = error_code; -	tsk->thread.trap_no = trapnr; +	tsk->thread.trap_nr = trapnr;  #ifdef CONFIG_X86_64  	if (show_unhandled_signals && unhandled_signal(tsk, signr) && @@ -165,7 +164,7 @@ trap_signal:  kernel_trap:  	if (!fixup_exception(regs)) {  		tsk->thread.error_code = error_code; -		tsk->thread.trap_no = trapnr; +		tsk->thread.trap_nr = trapnr;  		die(str, regs, error_code);  	}  	return; @@ -204,27 +203,31 @@ dotraplinkage void do_##name(struct pt_regs *regs, long error_code)	\  	do_trap(trapnr, signr, str, regs, error_code, &info);		\  } -DO_ERROR_INFO(0, SIGFPE, "divide error", divide_error, FPE_INTDIV, regs->ip) -DO_ERROR(4, SIGSEGV, "overflow", overflow) -DO_ERROR(5, SIGSEGV, "bounds", bounds) -DO_ERROR_INFO(6, SIGILL, "invalid opcode", invalid_op, ILL_ILLOPN, regs->ip) -DO_ERROR(9, SIGFPE, "coprocessor segment overrun", coprocessor_segment_overrun) -DO_ERROR(10, SIGSEGV, "invalid TSS", invalid_TSS) -DO_ERROR(11, SIGBUS, "segment not present", segment_not_present) +DO_ERROR_INFO(X86_TRAP_DE, SIGFPE, "divide error", divide_error, FPE_INTDIV, +		regs->ip) +DO_ERROR(X86_TRAP_OF, SIGSEGV, "overflow", overflow) +DO_ERROR(X86_TRAP_BR, SIGSEGV, "bounds", bounds) +DO_ERROR_INFO(X86_TRAP_UD, SIGILL, "invalid opcode", invalid_op, ILL_ILLOPN, +		regs->ip) +DO_ERROR(X86_TRAP_OLD_MF, SIGFPE, "coprocessor segment overrun", +		coprocessor_segment_overrun) +DO_ERROR(X86_TRAP_TS, SIGSEGV, "invalid TSS", invalid_TSS) +DO_ERROR(X86_TRAP_NP, SIGBUS, "segment not present", segment_not_present)  #ifdef CONFIG_X86_32 -DO_ERROR(12, SIGBUS, "stack segment", stack_segment) +DO_ERROR(X86_TRAP_SS, SIGBUS, "stack segment", stack_segment)  #endif -DO_ERROR_INFO(17, SIGBUS, "alignment check", alignment_check, BUS_ADRALN, 0) +DO_ERROR_INFO(X86_TRAP_AC, SIGBUS, "alignment check", alignment_check, +		BUS_ADRALN, 0)  #ifdef CONFIG_X86_64  /* Runs on IST stack */  dotraplinkage void do_stack_segment(struct pt_regs *regs, long error_code)  {  	if (notify_die(DIE_TRAP, "stack segment", regs, error_code, -			12, SIGBUS) == NOTIFY_STOP) +			X86_TRAP_SS, SIGBUS) == NOTIFY_STOP)  		return;  	preempt_conditional_sti(regs); -	do_trap(12, SIGBUS, "stack segment", regs, error_code, NULL); +	do_trap(X86_TRAP_SS, SIGBUS, "stack segment", regs, error_code, NULL);  	preempt_conditional_cli(regs);  } @@ -234,10 +237,10 @@ dotraplinkage void do_double_fault(struct pt_regs *regs, long error_code)  	struct task_struct *tsk = current;  	/* Return not checked because double check cannot be ignored */ -	notify_die(DIE_TRAP, str, regs, error_code, 8, SIGSEGV); +	notify_die(DIE_TRAP, str, regs, error_code, X86_TRAP_DF, SIGSEGV);  	tsk->thread.error_code = error_code; -	tsk->thread.trap_no = 8; +	tsk->thread.trap_nr = X86_TRAP_DF;  	/*  	 * This is always a kernel trap and never fixable (and thus must @@ -265,7 +268,7 @@ do_general_protection(struct pt_regs *regs, long error_code)  		goto gp_in_kernel;  	tsk->thread.error_code = error_code; -	tsk->thread.trap_no = 13; +	tsk->thread.trap_nr = X86_TRAP_GP;  	if (show_unhandled_signals && unhandled_signal(tsk, SIGSEGV) &&  			printk_ratelimit()) { @@ -292,9 +295,9 @@ gp_in_kernel:  		return;  	tsk->thread.error_code = error_code; -	tsk->thread.trap_no = 13; -	if (notify_die(DIE_GPF, "general protection fault", regs, -				error_code, 13, SIGSEGV) == NOTIFY_STOP) +	tsk->thread.trap_nr = X86_TRAP_GP; +	if (notify_die(DIE_GPF, "general protection fault", regs, error_code, +			X86_TRAP_GP, SIGSEGV) == NOTIFY_STOP)  		return;  	die("general protection fault", regs, error_code);  } @@ -303,13 +306,13 @@ gp_in_kernel:  dotraplinkage void __kprobes do_int3(struct pt_regs *regs, long error_code)  {  #ifdef CONFIG_KGDB_LOW_LEVEL_TRAP -	if (kgdb_ll_trap(DIE_INT3, "int3", regs, error_code, 3, SIGTRAP) -			== NOTIFY_STOP) +	if (kgdb_ll_trap(DIE_INT3, "int3", regs, error_code, X86_TRAP_BP, +				SIGTRAP) == NOTIFY_STOP)  		return;  #endif /* CONFIG_KGDB_LOW_LEVEL_TRAP */ -	if (notify_die(DIE_INT3, "int3", regs, error_code, 3, SIGTRAP) -			== NOTIFY_STOP) +	if (notify_die(DIE_INT3, "int3", regs, error_code, X86_TRAP_BP, +			SIGTRAP) == NOTIFY_STOP)  		return;  	/* @@ -318,7 +321,7 @@ dotraplinkage void __kprobes do_int3(struct pt_regs *regs, long error_code)  	 */  	debug_stack_usage_inc();  	preempt_conditional_sti(regs); -	do_trap(3, SIGTRAP, "int3", regs, error_code, NULL); +	do_trap(X86_TRAP_BP, SIGTRAP, "int3", regs, error_code, NULL);  	preempt_conditional_cli(regs);  	debug_stack_usage_dec();  } @@ -423,8 +426,8 @@ dotraplinkage void __kprobes do_debug(struct pt_regs *regs, long error_code)  	preempt_conditional_sti(regs);  	if (regs->flags & X86_VM_MASK) { -		handle_vm86_trap((struct kernel_vm86_regs *) regs, -				error_code, 1); +		handle_vm86_trap((struct kernel_vm86_regs *) regs, error_code, +					X86_TRAP_DB);  		preempt_conditional_cli(regs);  		debug_stack_usage_dec();  		return; @@ -461,7 +464,8 @@ void math_error(struct pt_regs *regs, int error_code, int trapnr)  	struct task_struct *task = current;  	siginfo_t info;  	unsigned short err; -	char *str = (trapnr == 16) ? "fpu exception" : "simd exception"; +	char *str = (trapnr == X86_TRAP_MF) ? "fpu exception" : +						"simd exception";  	if (notify_die(DIE_TRAP, str, regs, error_code, trapnr, SIGFPE) == NOTIFY_STOP)  		return; @@ -471,7 +475,7 @@ void math_error(struct pt_regs *regs, int error_code, int trapnr)  	{  		if (!fixup_exception(regs)) {  			task->thread.error_code = error_code; -			task->thread.trap_no = trapnr; +			task->thread.trap_nr = trapnr;  			die(str, regs, error_code);  		}  		return; @@ -481,12 +485,12 @@ void math_error(struct pt_regs *regs, int error_code, int trapnr)  	 * Save the info for the exception handler and clear the error.  	 */  	save_init_fpu(task); -	task->thread.trap_no = trapnr; +	task->thread.trap_nr = trapnr;  	task->thread.error_code = error_code;  	info.si_signo = SIGFPE;  	info.si_errno = 0;  	info.si_addr = (void __user *)regs->ip; -	if (trapnr == 16) { +	if (trapnr == X86_TRAP_MF) {  		unsigned short cwd, swd;  		/*  		 * (~cwd & swd) will mask out exceptions that are not set to unmasked @@ -530,10 +534,11 @@ void math_error(struct pt_regs *regs, int error_code, int trapnr)  		info.si_code = FPE_FLTRES;  	} else {  		/* -		 * If we're using IRQ 13, or supposedly even some trap 16 -		 * implementations, it's possible we get a spurious trap... +		 * If we're using IRQ 13, or supposedly even some trap +		 * X86_TRAP_MF implementations, it's possible +		 * we get a spurious trap, which is not an error.  		 */ -		return;		/* Spurious trap, no error */ +		return;  	}  	force_sig_info(SIGFPE, &info, task);  } @@ -544,13 +549,13 @@ dotraplinkage void do_coprocessor_error(struct pt_regs *regs, long error_code)  	ignore_fpu_irq = 1;  #endif -	math_error(regs, error_code, 16); +	math_error(regs, error_code, X86_TRAP_MF);  }  dotraplinkage void  do_simd_coprocessor_error(struct pt_regs *regs, long error_code)  { -	math_error(regs, error_code, 19); +	math_error(regs, error_code, X86_TRAP_XF);  }  dotraplinkage void @@ -644,20 +649,21 @@ dotraplinkage void do_iret_error(struct pt_regs *regs, long error_code)  	info.si_errno = 0;  	info.si_code = ILL_BADSTK;  	info.si_addr = NULL; -	if (notify_die(DIE_TRAP, "iret exception", -			regs, error_code, 32, SIGILL) == NOTIFY_STOP) +	if (notify_die(DIE_TRAP, "iret exception", regs, error_code, +			X86_TRAP_IRET, SIGILL) == NOTIFY_STOP)  		return; -	do_trap(32, SIGILL, "iret exception", regs, error_code, &info); +	do_trap(X86_TRAP_IRET, SIGILL, "iret exception", regs, error_code, +		&info);  }  #endif  /* Set of traps needed for early debugging. */  void __init early_trap_init(void)  { -	set_intr_gate_ist(1, &debug, DEBUG_STACK); +	set_intr_gate_ist(X86_TRAP_DB, &debug, DEBUG_STACK);  	/* int3 can be called from all */ -	set_system_intr_gate_ist(3, &int3, DEBUG_STACK); -	set_intr_gate(14, &page_fault); +	set_system_intr_gate_ist(X86_TRAP_BP, &int3, DEBUG_STACK); +	set_intr_gate(X86_TRAP_PF, &page_fault);  	load_idt(&idt_descr);  } @@ -673,30 +679,30 @@ void __init trap_init(void)  	early_iounmap(p, 4);  #endif -	set_intr_gate(0, ÷_error); -	set_intr_gate_ist(2, &nmi, NMI_STACK); +	set_intr_gate(X86_TRAP_DE, ÷_error); +	set_intr_gate_ist(X86_TRAP_NMI, &nmi, NMI_STACK);  	/* int4 can be called from all */ -	set_system_intr_gate(4, &overflow); -	set_intr_gate(5, &bounds); -	set_intr_gate(6, &invalid_op); -	set_intr_gate(7, &device_not_available); +	set_system_intr_gate(X86_TRAP_OF, &overflow); +	set_intr_gate(X86_TRAP_BR, &bounds); +	set_intr_gate(X86_TRAP_UD, &invalid_op); +	set_intr_gate(X86_TRAP_NM, &device_not_available);  #ifdef CONFIG_X86_32 -	set_task_gate(8, GDT_ENTRY_DOUBLEFAULT_TSS); +	set_task_gate(X86_TRAP_DF, GDT_ENTRY_DOUBLEFAULT_TSS);  #else -	set_intr_gate_ist(8, &double_fault, DOUBLEFAULT_STACK); +	set_intr_gate_ist(X86_TRAP_DF, &double_fault, DOUBLEFAULT_STACK);  #endif -	set_intr_gate(9, &coprocessor_segment_overrun); -	set_intr_gate(10, &invalid_TSS); -	set_intr_gate(11, &segment_not_present); -	set_intr_gate_ist(12, &stack_segment, STACKFAULT_STACK); -	set_intr_gate(13, &general_protection); -	set_intr_gate(15, &spurious_interrupt_bug); -	set_intr_gate(16, &coprocessor_error); -	set_intr_gate(17, &alignment_check); +	set_intr_gate(X86_TRAP_OLD_MF, &coprocessor_segment_overrun); +	set_intr_gate(X86_TRAP_TS, &invalid_TSS); +	set_intr_gate(X86_TRAP_NP, &segment_not_present); +	set_intr_gate_ist(X86_TRAP_SS, &stack_segment, STACKFAULT_STACK); +	set_intr_gate(X86_TRAP_GP, &general_protection); +	set_intr_gate(X86_TRAP_SPURIOUS, &spurious_interrupt_bug); +	set_intr_gate(X86_TRAP_MF, &coprocessor_error); +	set_intr_gate(X86_TRAP_AC, &alignment_check);  #ifdef CONFIG_X86_MCE -	set_intr_gate_ist(18, &machine_check, MCE_STACK); +	set_intr_gate_ist(X86_TRAP_MC, &machine_check, MCE_STACK);  #endif -	set_intr_gate(19, &simd_coprocessor_error); +	set_intr_gate(X86_TRAP_XF, &simd_coprocessor_error);  	/* Reserve all the builtin and the syscall vector: */  	for (i = 0; i < FIRST_EXTERNAL_VECTOR; i++) @@ -721,7 +727,7 @@ void __init trap_init(void)  #ifdef CONFIG_X86_64  	memcpy(&nmi_idt_table, &idt_table, IDT_ENTRIES * 16); -	set_nmi_gate(1, &debug); -	set_nmi_gate(3, &int3); +	set_nmi_gate(X86_TRAP_DB, &debug); +	set_nmi_gate(X86_TRAP_BP, &int3);  #endif  }  |