13 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
22 #include <linux/kernel.h>
23 #include <linux/module.h>
24 #include <linux/ptrace.h>
25 #include <linux/string.h>
27 #include <linux/errno.h>
28 #include <linux/kexec.h>
29 #include <linux/sched.h>
43 #if defined(CONFIG_EDAC)
48 #include <asm/stacktrace.h>
49 #include <asm/processor.h>
52 #include <asm/ftrace.h>
53 #include <asm/traps.h>
64 #include <asm/pgalloc.h>
68 #include <asm/setup.h>
85 static inline void conditional_sti(
struct pt_regs *
regs)
91 static inline void preempt_conditional_sti(
struct pt_regs *regs)
98 static inline void conditional_cli(
struct pt_regs *regs)
104 static inline void preempt_conditional_cli(
struct pt_regs *regs)
116 if (regs->
flags & X86_VM_MASK) {
132 tsk->
thread.trap_nr = trapnr;
133 die(str, regs, error_code);
148 if (!do_trap_no_signal(tsk, trapnr, str, regs, error_code))
160 tsk->
thread.trap_nr = trapnr;
164 printk_ratelimit()) {
165 pr_info(
"%s[%d] trap %s ip:%lx sp:%lx error:%lx",
167 regs->ip, regs->
sp, error_code);
179 #define DO_ERROR(trapnr, signr, str, name) \
180 dotraplinkage void do_##name(struct pt_regs *regs, long error_code) \
182 exception_enter(regs); \
183 if (notify_die(DIE_TRAP, str, regs, error_code, \
184 trapnr, signr) == NOTIFY_STOP) { \
185 exception_exit(regs); \
188 conditional_sti(regs); \
189 do_trap(trapnr, signr, str, regs, error_code, NULL); \
190 exception_exit(regs); \
193 #define DO_ERROR_INFO(trapnr, signr, str, name, sicode, siaddr) \
194 dotraplinkage void do_##name(struct pt_regs *regs, long error_code) \
197 info.si_signo = signr; \
199 info.si_code = sicode; \
200 info.si_addr = (void __user *)siaddr; \
201 exception_enter(regs); \
202 if (notify_die(DIE_TRAP, str, regs, error_code, \
203 trapnr, signr) == NOTIFY_STOP) { \
204 exception_exit(regs); \
207 conditional_sti(regs); \
208 do_trap(trapnr, signr, str, regs, error_code, &info); \
209 exception_exit(regs); \
232 exception_enter(regs);
235 preempt_conditional_sti(regs);
237 preempt_conditional_cli(regs);
239 exception_exit(regs);
244 static const char str[] =
"double fault";
247 exception_enter(regs);
259 die(str, regs, error_code);
268 exception_enter(regs);
269 conditional_sti(regs);
272 if (regs->
flags & X86_VM_MASK) {
288 die(
"general protection fault", regs, error_code);
296 printk_ratelimit()) {
297 pr_info(
"%s[%d] general protection ip:%lx sp:%lx error:%lx",
298 tsk->
comm, task_pid_nr(tsk),
299 regs->ip, regs->
sp, error_code);
306 exception_exit(regs);
312 #ifdef CONFIG_DYNAMIC_FTRACE
318 ftrace_int3_handler(regs))
321 exception_enter(regs);
322 #ifdef CONFIG_KGDB_LOW_LEVEL_TRAP
336 debug_stack_usage_inc();
337 preempt_conditional_sti(regs);
339 preempt_conditional_cli(regs);
340 debug_stack_usage_dec();
342 exception_exit(regs);
355 if (eregs == (
struct pt_regs *)eregs->
sp)
403 exception_enter(regs);
405 get_debugreg(dr6, 6);
431 tsk->
thread.debugreg6 = dr6;
441 debug_stack_usage_inc();
444 preempt_conditional_sti(regs);
446 if (regs->
flags & X86_VM_MASK) {
449 preempt_conditional_cli(regs);
450 debug_stack_usage_dec();
461 if ((dr6 & DR_STEP) && !
user_mode(regs)) {
462 tsk->
thread.debugreg6 &= ~DR_STEP;
466 si_code = get_si_code(tsk->
thread.debugreg6);
469 preempt_conditional_cli(regs);
470 debug_stack_usage_dec();
473 exception_exit(regs);
486 char *str = (trapnr ==
X86_TRAP_MF) ?
"fpu exception" :
491 conditional_sti(regs);
493 if (!user_mode_vm(regs))
497 task->
thread.trap_nr = trapnr;
498 die(str, regs, error_code);
507 task->
thread.trap_nr = trapnr;
511 info.si_addr = (
void __user *)regs->ip;
524 cwd = get_fpu_cwd(task);
525 swd = get_fpu_swd(task);
535 unsigned short mxcsr = get_fpu_mxcsr(task);
536 err = ~(mxcsr >> 7) & mxcsr;
546 }
else if (err & 0x004) {
548 }
else if (err & 0x008) {
550 }
else if (err & 0x012) {
552 }
else if (err & 0x020) {
570 exception_enter(regs);
572 exception_exit(regs);
578 exception_enter(regs);
580 exception_exit(regs);
586 conditional_sti(regs);
589 pr_info(
"Ignoring P6 Local APIC Spurious Interrupt Bug...\n");
630 __thread_fpu_begin(tsk);
635 if (
unlikely(restore_fpu_checking(tsk))) {
648 exception_enter(regs);
651 #ifdef CONFIG_MATH_EMULATION
655 conditional_sti(regs);
659 exception_exit(regs);
665 conditional_sti(regs);
667 exception_exit(regs);
675 exception_enter(regs);
687 exception_exit(regs);
708 if (
readl(p) ==
'E' + (
'I'<<8) + (
'S'<<16) + (
'A'<<24))
716 set_system_intr_gate(X86_TRAP_OF, &overflow);
717 set_intr_gate(X86_TRAP_BR, &bounds);
718 set_intr_gate(X86_TRAP_UD, &invalid_op);
721 set_task_gate(
X86_TRAP_DF, GDT_ENTRY_DOUBLEFAULT_TSS);
733 #ifdef CONFIG_X86_MCE
742 #ifdef CONFIG_IA32_EMULATION