11da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
21da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *  Copyright (C) 1991, 1992  Linus Torvalds
3a8c1be9d2e78d8608892c86791837acf12da4bf6Alexander van Heukelum *  Copyright (C) 2000, 2001, 2002 Andi Kleen, SuSE Labs
41da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
51da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *  Pentium III FXSR, SSE support
61da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	Gareth Hughes <gareth@valinux.com>, May 2000
71da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
81da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
91da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
10c1d518c8422ff7d3f377958771b265753028579cAlexander van Heukelum * Handle hardware traps and faults.
111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
12b5964405fbc4fd4c57e0e1f86bc9f1b3dbfa040aIngo Molnar#include <linux/interrupt.h>
13b5964405fbc4fd4c57e0e1f86bc9f1b3dbfa040aIngo Molnar#include <linux/kallsyms.h>
14b5964405fbc4fd4c57e0e1f86bc9f1b3dbfa040aIngo Molnar#include <linux/spinlock.h>
15b5964405fbc4fd4c57e0e1f86bc9f1b3dbfa040aIngo Molnar#include <linux/kprobes.h>
16b5964405fbc4fd4c57e0e1f86bc9f1b3dbfa040aIngo Molnar#include <linux/uaccess.h>
17b5964405fbc4fd4c57e0e1f86bc9f1b3dbfa040aIngo Molnar#include <linux/kdebug.h>
18f503b5ae53cb557ac351a668fcac1baab1cef0dbJason Wessel#include <linux/kgdb.h>
191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/kernel.h>
20b5964405fbc4fd4c57e0e1f86bc9f1b3dbfa040aIngo Molnar#include <linux/module.h>
21b5964405fbc4fd4c57e0e1f86bc9f1b3dbfa040aIngo Molnar#include <linux/ptrace.h>
221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/string.h>
23b5964405fbc4fd4c57e0e1f86bc9f1b3dbfa040aIngo Molnar#include <linux/delay.h>
241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/errno.h>
25b5964405fbc4fd4c57e0e1f86bc9f1b3dbfa040aIngo Molnar#include <linux/kexec.h>
26b5964405fbc4fd4c57e0e1f86bc9f1b3dbfa040aIngo Molnar#include <linux/sched.h>
271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/timer.h>
281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/init.h>
2991768d6c2bad0d2766a166f13f2f57e197de3458Jeremy Fitzhardinge#include <linux/bug.h>
30b5964405fbc4fd4c57e0e1f86bc9f1b3dbfa040aIngo Molnar#include <linux/nmi.h>
31b5964405fbc4fd4c57e0e1f86bc9f1b3dbfa040aIngo Molnar#include <linux/mm.h>
32c1d518c8422ff7d3f377958771b265753028579cAlexander van Heukelum#include <linux/smp.h>
33c1d518c8422ff7d3f377958771b265753028579cAlexander van Heukelum#include <linux/io.h>
341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef CONFIG_EISA
361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/ioport.h>
371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/eisa.h>
381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif
391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef CONFIG_MCA
411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/mca.h>
421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif
431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
44c0d121720220584bba2876b032e58a076b843fa1Dave Jiang#if defined(CONFIG_EDAC)
45c0d121720220584bba2876b032e58a076b843fa1Dave Jiang#include <linux/edac.h>
46c0d121720220584bba2876b032e58a076b843fa1Dave Jiang#endif
47c0d121720220584bba2876b032e58a076b843fa1Dave Jiang
48f85612967c93b67b10dd240e3e8bf8a0eee9def7Vegard Nossum#include <asm/kmemcheck.h>
49b5964405fbc4fd4c57e0e1f86bc9f1b3dbfa040aIngo Molnar#include <asm/stacktrace.h>
501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <asm/processor.h>
511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <asm/debugreg.h>
5260063497a95e716c9a689af3be2687d261f115b4Arun Sharma#include <linux/atomic.h>
53c1d518c8422ff7d3f377958771b265753028579cAlexander van Heukelum#include <asm/traps.h>
541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <asm/desc.h>
551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <asm/i387.h>
561361b83a13d4d92e53fbb6c877528713e118b821Linus Torvalds#include <asm/fpu-internal.h>
579e55e44e39798541ba39d57f4b569deb555ae1ceHidetoshi Seto#include <asm/mce.h>
58c1d518c8422ff7d3f377958771b265753028579cAlexander van Heukelum
591164dd0099c0d79146a55319670f57ab7ad1d352Ingo Molnar#include <asm/mach_traps.h>
60c1d518c8422ff7d3f377958771b265753028579cAlexander van Heukelum
61081f75bbdc86de53537e1b5aca01de72bd2fea6bAlexander van Heukelum#ifdef CONFIG_X86_64
62428cf9025b15573e16e658032f2b963283e34ae0Thomas Gleixner#include <asm/x86_init.h>
63081f75bbdc86de53537e1b5aca01de72bd2fea6bAlexander van Heukelum#include <asm/pgalloc.h>
64081f75bbdc86de53537e1b5aca01de72bd2fea6bAlexander van Heukelum#include <asm/proto.h>
65081f75bbdc86de53537e1b5aca01de72bd2fea6bAlexander van Heukelum#else
66c1d518c8422ff7d3f377958771b265753028579cAlexander van Heukelum#include <asm/processor-flags.h>
678e6dafd6c741cd4679b4de3c5d9698851e4fa59cIngo Molnar#include <asm/setup.h>
681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsasmlinkage int system_call(void);
701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Do we ignore FPU interrupts ? */
72b5964405fbc4fd4c57e0e1f86bc9f1b3dbfa040aIngo Molnarchar ignore_fpu_irq;
731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * The IDT has to be page-aligned to simplify the Pentium
7607e81d61605f885920f31634a65aace52beb97dbTim Abbott * F0 0F bug workaround.
771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
7807e81d61605f885920f31634a65aace52beb97dbTim Abbottgate_desc idt_table[NR_VECTORS] __page_aligned_data = { { { { 0, 0 } } }, };
79081f75bbdc86de53537e1b5aca01de72bd2fea6bAlexander van Heukelum#endif
801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
81b77b881f21b29aa7efa668fde69ee3dc0372ae3fYinghai LuDECLARE_BITMAP(used_vectors, NR_VECTORS);
82b77b881f21b29aa7efa668fde69ee3dc0372ae3fYinghai LuEXPORT_SYMBOL_GPL(used_vectors);
83b77b881f21b29aa7efa668fde69ee3dc0372ae3fYinghai Lu
84762db4347060c5d23e9675846e02f7d95d7f944fAlexander van Heukelumstatic inline void conditional_sti(struct pt_regs *regs)
85762db4347060c5d23e9675846e02f7d95d7f944fAlexander van Heukelum{
86762db4347060c5d23e9675846e02f7d95d7f944fAlexander van Heukelum	if (regs->flags & X86_EFLAGS_IF)
87762db4347060c5d23e9675846e02f7d95d7f944fAlexander van Heukelum		local_irq_enable();
88762db4347060c5d23e9675846e02f7d95d7f944fAlexander van Heukelum}
89762db4347060c5d23e9675846e02f7d95d7f944fAlexander van Heukelum
903d2a71a596bd9c761c8487a2178e95f8a61da083Alexander van Heukelumstatic inline void preempt_conditional_sti(struct pt_regs *regs)
913d2a71a596bd9c761c8487a2178e95f8a61da083Alexander van Heukelum{
923d2a71a596bd9c761c8487a2178e95f8a61da083Alexander van Heukelum	inc_preempt_count();
933d2a71a596bd9c761c8487a2178e95f8a61da083Alexander van Heukelum	if (regs->flags & X86_EFLAGS_IF)
943d2a71a596bd9c761c8487a2178e95f8a61da083Alexander van Heukelum		local_irq_enable();
953d2a71a596bd9c761c8487a2178e95f8a61da083Alexander van Heukelum}
963d2a71a596bd9c761c8487a2178e95f8a61da083Alexander van Heukelum
97be716615fe596ee117292dc615e95f707fb67fd1Thomas Gleixnerstatic inline void conditional_cli(struct pt_regs *regs)
98be716615fe596ee117292dc615e95f707fb67fd1Thomas Gleixner{
99be716615fe596ee117292dc615e95f707fb67fd1Thomas Gleixner	if (regs->flags & X86_EFLAGS_IF)
100be716615fe596ee117292dc615e95f707fb67fd1Thomas Gleixner		local_irq_disable();
101be716615fe596ee117292dc615e95f707fb67fd1Thomas Gleixner}
102be716615fe596ee117292dc615e95f707fb67fd1Thomas Gleixner
1033d2a71a596bd9c761c8487a2178e95f8a61da083Alexander van Heukelumstatic inline void preempt_conditional_cli(struct pt_regs *regs)
1043d2a71a596bd9c761c8487a2178e95f8a61da083Alexander van Heukelum{
1053d2a71a596bd9c761c8487a2178e95f8a61da083Alexander van Heukelum	if (regs->flags & X86_EFLAGS_IF)
1063d2a71a596bd9c761c8487a2178e95f8a61da083Alexander van Heukelum		local_irq_disable();
1073d2a71a596bd9c761c8487a2178e95f8a61da083Alexander van Heukelum	dec_preempt_count();
1083d2a71a596bd9c761c8487a2178e95f8a61da083Alexander van Heukelum}
1093d2a71a596bd9c761c8487a2178e95f8a61da083Alexander van Heukelum
110b5964405fbc4fd4c57e0e1f86bc9f1b3dbfa040aIngo Molnarstatic void __kprobes
1113c1326f8a6d8b9815ca88c95441330f96eef7352Alexander van Heukelumdo_trap(int trapnr, int signr, char *str, struct pt_regs *regs,
112b5964405fbc4fd4c57e0e1f86bc9f1b3dbfa040aIngo Molnar	long error_code, siginfo_t *info)
1131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
1144f339ecb30c759f94a29992d4635d9194132b6cfAlexander Nyberg	struct task_struct *tsk = current;
1154f339ecb30c759f94a29992d4635d9194132b6cfAlexander Nyberg
116081f75bbdc86de53537e1b5aca01de72bd2fea6bAlexander van Heukelum#ifdef CONFIG_X86_32
1176b6891f9c545ccd45d6d8ddfd33ce27c22c271a7gorcunov@gmail.com	if (regs->flags & X86_VM_MASK) {
1183c1326f8a6d8b9815ca88c95441330f96eef7352Alexander van Heukelum		/*
1193c1326f8a6d8b9815ca88c95441330f96eef7352Alexander van Heukelum		 * traps 0, 1, 3, 4, and 5 should be forwarded to vm86.
1203c1326f8a6d8b9815ca88c95441330f96eef7352Alexander van Heukelum		 * On nmi (interrupt 2), do_trap should not be called.
1213c1326f8a6d8b9815ca88c95441330f96eef7352Alexander van Heukelum		 */
122c94082656dac74257f63e91f78d5d458ac781fa5Kees Cook		if (trapnr < X86_TRAP_UD)
1231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			goto vm86_trap;
1241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		goto trap_signal;
1251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
126081f75bbdc86de53537e1b5aca01de72bd2fea6bAlexander van Heukelum#endif
1271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
128717b594a415bfaf2dbd5e8266636488f2564c689Vincent Hanquez	if (!user_mode(regs))
1291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		goto kernel_trap;
1301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
131081f75bbdc86de53537e1b5aca01de72bd2fea6bAlexander van Heukelum#ifdef CONFIG_X86_32
132b5964405fbc4fd4c57e0e1f86bc9f1b3dbfa040aIngo Molnartrap_signal:
133081f75bbdc86de53537e1b5aca01de72bd2fea6bAlexander van Heukelum#endif
134b5964405fbc4fd4c57e0e1f86bc9f1b3dbfa040aIngo Molnar	/*
13551e7dc7011c99e1e5294658c7b551b92ca069985Srikar Dronamraju	 * We want error_code and trap_nr set for userspace faults and
136b5964405fbc4fd4c57e0e1f86bc9f1b3dbfa040aIngo Molnar	 * kernelspace faults which result in die(), but not
137b5964405fbc4fd4c57e0e1f86bc9f1b3dbfa040aIngo Molnar	 * kernelspace faults which are fixed up.  die() gives the
138b5964405fbc4fd4c57e0e1f86bc9f1b3dbfa040aIngo Molnar	 * process no chance to handle the signal and notice the
139b5964405fbc4fd4c57e0e1f86bc9f1b3dbfa040aIngo Molnar	 * kernel fault information, so that won't result in polluting
140b5964405fbc4fd4c57e0e1f86bc9f1b3dbfa040aIngo Molnar	 * the information about previously queued, but not yet
141b5964405fbc4fd4c57e0e1f86bc9f1b3dbfa040aIngo Molnar	 * delivered, faults.  See also do_general_protection below.
142b5964405fbc4fd4c57e0e1f86bc9f1b3dbfa040aIngo Molnar	 */
143b5964405fbc4fd4c57e0e1f86bc9f1b3dbfa040aIngo Molnar	tsk->thread.error_code = error_code;
14451e7dc7011c99e1e5294658c7b551b92ca069985Srikar Dronamraju	tsk->thread.trap_nr = trapnr;
145d18951834216eae82e2f9112416111b4f55f1849Andi Kleen
146081f75bbdc86de53537e1b5aca01de72bd2fea6bAlexander van Heukelum#ifdef CONFIG_X86_64
147081f75bbdc86de53537e1b5aca01de72bd2fea6bAlexander van Heukelum	if (show_unhandled_signals && unhandled_signal(tsk, signr) &&
148081f75bbdc86de53537e1b5aca01de72bd2fea6bAlexander van Heukelum	    printk_ratelimit()) {
149081f75bbdc86de53537e1b5aca01de72bd2fea6bAlexander van Heukelum		printk(KERN_INFO
150081f75bbdc86de53537e1b5aca01de72bd2fea6bAlexander van Heukelum		       "%s[%d] trap %s ip:%lx sp:%lx error:%lx",
151081f75bbdc86de53537e1b5aca01de72bd2fea6bAlexander van Heukelum		       tsk->comm, tsk->pid, str,
152081f75bbdc86de53537e1b5aca01de72bd2fea6bAlexander van Heukelum		       regs->ip, regs->sp, error_code);
153081f75bbdc86de53537e1b5aca01de72bd2fea6bAlexander van Heukelum		print_vma_addr(" in ", regs->ip);
154081f75bbdc86de53537e1b5aca01de72bd2fea6bAlexander van Heukelum		printk("\n");
155081f75bbdc86de53537e1b5aca01de72bd2fea6bAlexander van Heukelum	}
156081f75bbdc86de53537e1b5aca01de72bd2fea6bAlexander van Heukelum#endif
157081f75bbdc86de53537e1b5aca01de72bd2fea6bAlexander van Heukelum
158b5964405fbc4fd4c57e0e1f86bc9f1b3dbfa040aIngo Molnar	if (info)
159b5964405fbc4fd4c57e0e1f86bc9f1b3dbfa040aIngo Molnar		force_sig_info(signr, info, tsk);
160b5964405fbc4fd4c57e0e1f86bc9f1b3dbfa040aIngo Molnar	else
161b5964405fbc4fd4c57e0e1f86bc9f1b3dbfa040aIngo Molnar		force_sig(signr, tsk);
162b5964405fbc4fd4c57e0e1f86bc9f1b3dbfa040aIngo Molnar	return;
1631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
164b5964405fbc4fd4c57e0e1f86bc9f1b3dbfa040aIngo Molnarkernel_trap:
165b5964405fbc4fd4c57e0e1f86bc9f1b3dbfa040aIngo Molnar	if (!fixup_exception(regs)) {
166b5964405fbc4fd4c57e0e1f86bc9f1b3dbfa040aIngo Molnar		tsk->thread.error_code = error_code;
16751e7dc7011c99e1e5294658c7b551b92ca069985Srikar Dronamraju		tsk->thread.trap_nr = trapnr;
168b5964405fbc4fd4c57e0e1f86bc9f1b3dbfa040aIngo Molnar		die(str, regs, error_code);
1691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
170b5964405fbc4fd4c57e0e1f86bc9f1b3dbfa040aIngo Molnar	return;
1711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
172081f75bbdc86de53537e1b5aca01de72bd2fea6bAlexander van Heukelum#ifdef CONFIG_X86_32
173b5964405fbc4fd4c57e0e1f86bc9f1b3dbfa040aIngo Molnarvm86_trap:
174b5964405fbc4fd4c57e0e1f86bc9f1b3dbfa040aIngo Molnar	if (handle_vm86_trap((struct kernel_vm86_regs *) regs,
175b5964405fbc4fd4c57e0e1f86bc9f1b3dbfa040aIngo Molnar						error_code, trapnr))
176b5964405fbc4fd4c57e0e1f86bc9f1b3dbfa040aIngo Molnar		goto trap_signal;
177b5964405fbc4fd4c57e0e1f86bc9f1b3dbfa040aIngo Molnar	return;
178081f75bbdc86de53537e1b5aca01de72bd2fea6bAlexander van Heukelum#endif
1791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
1801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
181b5964405fbc4fd4c57e0e1f86bc9f1b3dbfa040aIngo Molnar#define DO_ERROR(trapnr, signr, str, name)				\
182e407d62088b7f61f38e1086062650c75a4f2757aAlexander van Heukelumdotraplinkage void do_##name(struct pt_regs *regs, long error_code)	\
183b5964405fbc4fd4c57e0e1f86bc9f1b3dbfa040aIngo Molnar{									\
184b5964405fbc4fd4c57e0e1f86bc9f1b3dbfa040aIngo Molnar	if (notify_die(DIE_TRAP, str, regs, error_code, trapnr, signr)	\
185a8c1be9d2e78d8608892c86791837acf12da4bf6Alexander van Heukelum							== NOTIFY_STOP)	\
186b5964405fbc4fd4c57e0e1f86bc9f1b3dbfa040aIngo Molnar		return;							\
18761aef7d24909b95f9eddaa78d78902fbea1d7059Alexander van Heukelum	conditional_sti(regs);						\
1883c1326f8a6d8b9815ca88c95441330f96eef7352Alexander van Heukelum	do_trap(trapnr, signr, str, regs, error_code, NULL);		\
1891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
1901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1913c1326f8a6d8b9815ca88c95441330f96eef7352Alexander van Heukelum#define DO_ERROR_INFO(trapnr, signr, str, name, sicode, siaddr)		\
192e407d62088b7f61f38e1086062650c75a4f2757aAlexander van Heukelumdotraplinkage void do_##name(struct pt_regs *regs, long error_code)	\
193b5964405fbc4fd4c57e0e1f86bc9f1b3dbfa040aIngo Molnar{									\
194b5964405fbc4fd4c57e0e1f86bc9f1b3dbfa040aIngo Molnar	siginfo_t info;							\
195b5964405fbc4fd4c57e0e1f86bc9f1b3dbfa040aIngo Molnar	info.si_signo = signr;						\
196b5964405fbc4fd4c57e0e1f86bc9f1b3dbfa040aIngo Molnar	info.si_errno = 0;						\
197b5964405fbc4fd4c57e0e1f86bc9f1b3dbfa040aIngo Molnar	info.si_code = sicode;						\
198b5964405fbc4fd4c57e0e1f86bc9f1b3dbfa040aIngo Molnar	info.si_addr = (void __user *)siaddr;				\
199b5964405fbc4fd4c57e0e1f86bc9f1b3dbfa040aIngo Molnar	if (notify_die(DIE_TRAP, str, regs, error_code, trapnr, signr)	\
200a8c1be9d2e78d8608892c86791837acf12da4bf6Alexander van Heukelum							== NOTIFY_STOP)	\
201b5964405fbc4fd4c57e0e1f86bc9f1b3dbfa040aIngo Molnar		return;							\
20261aef7d24909b95f9eddaa78d78902fbea1d7059Alexander van Heukelum	conditional_sti(regs);						\
2033c1326f8a6d8b9815ca88c95441330f96eef7352Alexander van Heukelum	do_trap(trapnr, signr, str, regs, error_code, &info);		\
2041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
2051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
206c94082656dac74257f63e91f78d5d458ac781fa5Kees CookDO_ERROR_INFO(X86_TRAP_DE, SIGFPE, "divide error", divide_error, FPE_INTDIV,
207c94082656dac74257f63e91f78d5d458ac781fa5Kees Cook		regs->ip)
208c94082656dac74257f63e91f78d5d458ac781fa5Kees CookDO_ERROR(X86_TRAP_OF, SIGSEGV, "overflow", overflow)
209c94082656dac74257f63e91f78d5d458ac781fa5Kees CookDO_ERROR(X86_TRAP_BR, SIGSEGV, "bounds", bounds)
210c94082656dac74257f63e91f78d5d458ac781fa5Kees CookDO_ERROR_INFO(X86_TRAP_UD, SIGILL, "invalid opcode", invalid_op, ILL_ILLOPN,
211c94082656dac74257f63e91f78d5d458ac781fa5Kees Cook		regs->ip)
212c94082656dac74257f63e91f78d5d458ac781fa5Kees CookDO_ERROR(X86_TRAP_OLD_MF, SIGFPE, "coprocessor segment overrun",
213c94082656dac74257f63e91f78d5d458ac781fa5Kees Cook		coprocessor_segment_overrun)
214c94082656dac74257f63e91f78d5d458ac781fa5Kees CookDO_ERROR(X86_TRAP_TS, SIGSEGV, "invalid TSS", invalid_TSS)
215c94082656dac74257f63e91f78d5d458ac781fa5Kees CookDO_ERROR(X86_TRAP_NP, SIGBUS, "segment not present", segment_not_present)
216081f75bbdc86de53537e1b5aca01de72bd2fea6bAlexander van Heukelum#ifdef CONFIG_X86_32
217c94082656dac74257f63e91f78d5d458ac781fa5Kees CookDO_ERROR(X86_TRAP_SS, SIGBUS, "stack segment", stack_segment)
218081f75bbdc86de53537e1b5aca01de72bd2fea6bAlexander van Heukelum#endif
219c94082656dac74257f63e91f78d5d458ac781fa5Kees CookDO_ERROR_INFO(X86_TRAP_AC, SIGBUS, "alignment check", alignment_check,
220c94082656dac74257f63e91f78d5d458ac781fa5Kees Cook		BUS_ADRALN, 0)
2211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
222081f75bbdc86de53537e1b5aca01de72bd2fea6bAlexander van Heukelum#ifdef CONFIG_X86_64
223081f75bbdc86de53537e1b5aca01de72bd2fea6bAlexander van Heukelum/* Runs on IST stack */
224081f75bbdc86de53537e1b5aca01de72bd2fea6bAlexander van Heukelumdotraplinkage void do_stack_segment(struct pt_regs *regs, long error_code)
225081f75bbdc86de53537e1b5aca01de72bd2fea6bAlexander van Heukelum{
226081f75bbdc86de53537e1b5aca01de72bd2fea6bAlexander van Heukelum	if (notify_die(DIE_TRAP, "stack segment", regs, error_code,
227c94082656dac74257f63e91f78d5d458ac781fa5Kees Cook			X86_TRAP_SS, SIGBUS) == NOTIFY_STOP)
228081f75bbdc86de53537e1b5aca01de72bd2fea6bAlexander van Heukelum		return;
229081f75bbdc86de53537e1b5aca01de72bd2fea6bAlexander van Heukelum	preempt_conditional_sti(regs);
230c94082656dac74257f63e91f78d5d458ac781fa5Kees Cook	do_trap(X86_TRAP_SS, SIGBUS, "stack segment", regs, error_code, NULL);
231081f75bbdc86de53537e1b5aca01de72bd2fea6bAlexander van Heukelum	preempt_conditional_cli(regs);
232081f75bbdc86de53537e1b5aca01de72bd2fea6bAlexander van Heukelum}
233081f75bbdc86de53537e1b5aca01de72bd2fea6bAlexander van Heukelum
234081f75bbdc86de53537e1b5aca01de72bd2fea6bAlexander van Heukelumdotraplinkage void do_double_fault(struct pt_regs *regs, long error_code)
235081f75bbdc86de53537e1b5aca01de72bd2fea6bAlexander van Heukelum{
236081f75bbdc86de53537e1b5aca01de72bd2fea6bAlexander van Heukelum	static const char str[] = "double fault";
237081f75bbdc86de53537e1b5aca01de72bd2fea6bAlexander van Heukelum	struct task_struct *tsk = current;
238081f75bbdc86de53537e1b5aca01de72bd2fea6bAlexander van Heukelum
239081f75bbdc86de53537e1b5aca01de72bd2fea6bAlexander van Heukelum	/* Return not checked because double check cannot be ignored */
240c94082656dac74257f63e91f78d5d458ac781fa5Kees Cook	notify_die(DIE_TRAP, str, regs, error_code, X86_TRAP_DF, SIGSEGV);
241081f75bbdc86de53537e1b5aca01de72bd2fea6bAlexander van Heukelum
242081f75bbdc86de53537e1b5aca01de72bd2fea6bAlexander van Heukelum	tsk->thread.error_code = error_code;
24351e7dc7011c99e1e5294658c7b551b92ca069985Srikar Dronamraju	tsk->thread.trap_nr = X86_TRAP_DF;
244081f75bbdc86de53537e1b5aca01de72bd2fea6bAlexander van Heukelum
245bd8b96dfc216eebc72950a6c40da8d3eca8667dfIngo Molnar	/*
246bd8b96dfc216eebc72950a6c40da8d3eca8667dfIngo Molnar	 * This is always a kernel trap and never fixable (and thus must
247bd8b96dfc216eebc72950a6c40da8d3eca8667dfIngo Molnar	 * never return).
248bd8b96dfc216eebc72950a6c40da8d3eca8667dfIngo Molnar	 */
249081f75bbdc86de53537e1b5aca01de72bd2fea6bAlexander van Heukelum	for (;;)
250081f75bbdc86de53537e1b5aca01de72bd2fea6bAlexander van Heukelum		die(str, regs, error_code);
251081f75bbdc86de53537e1b5aca01de72bd2fea6bAlexander van Heukelum}
252081f75bbdc86de53537e1b5aca01de72bd2fea6bAlexander van Heukelum#endif
253081f75bbdc86de53537e1b5aca01de72bd2fea6bAlexander van Heukelum
254e407d62088b7f61f38e1086062650c75a4f2757aAlexander van Heukelumdotraplinkage void __kprobes
25513485ab55bc77f02024e80bcca0374950b0becb3Alexander van Heukelumdo_general_protection(struct pt_regs *regs, long error_code)
2561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
25713485ab55bc77f02024e80bcca0374950b0becb3Alexander van Heukelum	struct task_struct *tsk;
258b5964405fbc4fd4c57e0e1f86bc9f1b3dbfa040aIngo Molnar
259c6df0d71bec391e78e0a38109d63154acd69a937Alexander van Heukelum	conditional_sti(regs);
260c6df0d71bec391e78e0a38109d63154acd69a937Alexander van Heukelum
261081f75bbdc86de53537e1b5aca01de72bd2fea6bAlexander van Heukelum#ifdef CONFIG_X86_32
2626b6891f9c545ccd45d6d8ddfd33ce27c22c271a7gorcunov@gmail.com	if (regs->flags & X86_VM_MASK)
2631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		goto gp_in_vm86;
264081f75bbdc86de53537e1b5aca01de72bd2fea6bAlexander van Heukelum#endif
2651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
26613485ab55bc77f02024e80bcca0374950b0becb3Alexander van Heukelum	tsk = current;
267717b594a415bfaf2dbd5e8266636488f2564c689Vincent Hanquez	if (!user_mode(regs))
2681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		goto gp_in_kernel;
2691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
27013485ab55bc77f02024e80bcca0374950b0becb3Alexander van Heukelum	tsk->thread.error_code = error_code;
27151e7dc7011c99e1e5294658c7b551b92ca069985Srikar Dronamraju	tsk->thread.trap_nr = X86_TRAP_GP;
272b5964405fbc4fd4c57e0e1f86bc9f1b3dbfa040aIngo Molnar
27313485ab55bc77f02024e80bcca0374950b0becb3Alexander van Heukelum	if (show_unhandled_signals && unhandled_signal(tsk, SIGSEGV) &&
27413485ab55bc77f02024e80bcca0374950b0becb3Alexander van Heukelum			printk_ratelimit()) {
275abd4f7505bafdd6c5319fe3cb5caf9af6104e17aMasoud Asgharifard Sharbiani		printk(KERN_INFO
27613485ab55bc77f02024e80bcca0374950b0becb3Alexander van Heukelum			"%s[%d] general protection ip:%lx sp:%lx error:%lx",
27713485ab55bc77f02024e80bcca0374950b0becb3Alexander van Heukelum			tsk->comm, task_pid_nr(tsk),
27813485ab55bc77f02024e80bcca0374950b0becb3Alexander van Heukelum			regs->ip, regs->sp, error_code);
27903252919b79891063cf99145612360efbdf9500bAndi Kleen		print_vma_addr(" in ", regs->ip);
28003252919b79891063cf99145612360efbdf9500bAndi Kleen		printk("\n");
28103252919b79891063cf99145612360efbdf9500bAndi Kleen	}
282abd4f7505bafdd6c5319fe3cb5caf9af6104e17aMasoud Asgharifard Sharbiani
28313485ab55bc77f02024e80bcca0374950b0becb3Alexander van Heukelum	force_sig(SIGSEGV, tsk);
2841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return;
2851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
286081f75bbdc86de53537e1b5aca01de72bd2fea6bAlexander van Heukelum#ifdef CONFIG_X86_32
2871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsgp_in_vm86:
2881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	local_irq_enable();
2891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	handle_vm86_fault((struct kernel_vm86_regs *) regs, error_code);
2901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return;
291081f75bbdc86de53537e1b5aca01de72bd2fea6bAlexander van Heukelum#endif
2921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsgp_in_kernel:
29413485ab55bc77f02024e80bcca0374950b0becb3Alexander van Heukelum	if (fixup_exception(regs))
29513485ab55bc77f02024e80bcca0374950b0becb3Alexander van Heukelum		return;
29613485ab55bc77f02024e80bcca0374950b0becb3Alexander van Heukelum
29713485ab55bc77f02024e80bcca0374950b0becb3Alexander van Heukelum	tsk->thread.error_code = error_code;
29851e7dc7011c99e1e5294658c7b551b92ca069985Srikar Dronamraju	tsk->thread.trap_nr = X86_TRAP_GP;
299c94082656dac74257f63e91f78d5d458ac781fa5Kees Cook	if (notify_die(DIE_GPF, "general protection fault", regs, error_code,
300c94082656dac74257f63e91f78d5d458ac781fa5Kees Cook			X86_TRAP_GP, SIGSEGV) == NOTIFY_STOP)
30113485ab55bc77f02024e80bcca0374950b0becb3Alexander van Heukelum		return;
30213485ab55bc77f02024e80bcca0374950b0becb3Alexander van Heukelum	die("general protection fault", regs, error_code);
3031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
3041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
305c1d518c8422ff7d3f377958771b265753028579cAlexander van Heukelum/* May run on IST stack. */
306e407d62088b7f61f38e1086062650c75a4f2757aAlexander van Heukelumdotraplinkage void __kprobes do_int3(struct pt_regs *regs, long error_code)
3071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
308f503b5ae53cb557ac351a668fcac1baab1cef0dbJason Wessel#ifdef CONFIG_KGDB_LOW_LEVEL_TRAP
309c94082656dac74257f63e91f78d5d458ac781fa5Kees Cook	if (kgdb_ll_trap(DIE_INT3, "int3", regs, error_code, X86_TRAP_BP,
310c94082656dac74257f63e91f78d5d458ac781fa5Kees Cook				SIGTRAP) == NOTIFY_STOP)
311f503b5ae53cb557ac351a668fcac1baab1cef0dbJason Wessel		return;
312f503b5ae53cb557ac351a668fcac1baab1cef0dbJason Wessel#endif /* CONFIG_KGDB_LOW_LEVEL_TRAP */
313cc3a1bf52a9d2808c7cd6e8f413b02b650b6b84bSrikar Dronamraju
314c94082656dac74257f63e91f78d5d458ac781fa5Kees Cook	if (notify_die(DIE_INT3, "int3", regs, error_code, X86_TRAP_BP,
315c94082656dac74257f63e91f78d5d458ac781fa5Kees Cook			SIGTRAP) == NOTIFY_STOP)
31648c88211a65bc30f030fe228bda30fda870deb90Stas Sergeev		return;
317b5964405fbc4fd4c57e0e1f86bc9f1b3dbfa040aIngo Molnar
31842181186ad4db986fcaa40ca95c6e407e9e79372Steven Rostedt	/*
31942181186ad4db986fcaa40ca95c6e407e9e79372Steven Rostedt	 * Let others (NMI) know that the debug stack is in use
32042181186ad4db986fcaa40ca95c6e407e9e79372Steven Rostedt	 * as we may switch to the interrupt stack.
32142181186ad4db986fcaa40ca95c6e407e9e79372Steven Rostedt	 */
32242181186ad4db986fcaa40ca95c6e407e9e79372Steven Rostedt	debug_stack_usage_inc();
3234915a35e35a037254550a2ba9f367a812bc37d40Alexander van Heukelum	preempt_conditional_sti(regs);
324c94082656dac74257f63e91f78d5d458ac781fa5Kees Cook	do_trap(X86_TRAP_BP, SIGTRAP, "int3", regs, error_code, NULL);
3254915a35e35a037254550a2ba9f367a812bc37d40Alexander van Heukelum	preempt_conditional_cli(regs);
32642181186ad4db986fcaa40ca95c6e407e9e79372Steven Rostedt	debug_stack_usage_dec();
3271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
3281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
329081f75bbdc86de53537e1b5aca01de72bd2fea6bAlexander van Heukelum#ifdef CONFIG_X86_64
330bd8b96dfc216eebc72950a6c40da8d3eca8667dfIngo Molnar/*
331bd8b96dfc216eebc72950a6c40da8d3eca8667dfIngo Molnar * Help handler running on IST stack to switch back to user stack
332bd8b96dfc216eebc72950a6c40da8d3eca8667dfIngo Molnar * for scheduling or signal handling. The actual stack switch is done in
333bd8b96dfc216eebc72950a6c40da8d3eca8667dfIngo Molnar * entry.S
334bd8b96dfc216eebc72950a6c40da8d3eca8667dfIngo Molnar */
335081f75bbdc86de53537e1b5aca01de72bd2fea6bAlexander van Heukelumasmlinkage __kprobes struct pt_regs *sync_regs(struct pt_regs *eregs)
336081f75bbdc86de53537e1b5aca01de72bd2fea6bAlexander van Heukelum{
337081f75bbdc86de53537e1b5aca01de72bd2fea6bAlexander van Heukelum	struct pt_regs *regs = eregs;
338081f75bbdc86de53537e1b5aca01de72bd2fea6bAlexander van Heukelum	/* Did already sync */
339081f75bbdc86de53537e1b5aca01de72bd2fea6bAlexander van Heukelum	if (eregs == (struct pt_regs *)eregs->sp)
340081f75bbdc86de53537e1b5aca01de72bd2fea6bAlexander van Heukelum		;
341081f75bbdc86de53537e1b5aca01de72bd2fea6bAlexander van Heukelum	/* Exception from user space */
342081f75bbdc86de53537e1b5aca01de72bd2fea6bAlexander van Heukelum	else if (user_mode(eregs))
343081f75bbdc86de53537e1b5aca01de72bd2fea6bAlexander van Heukelum		regs = task_pt_regs(current);
344bd8b96dfc216eebc72950a6c40da8d3eca8667dfIngo Molnar	/*
345bd8b96dfc216eebc72950a6c40da8d3eca8667dfIngo Molnar	 * Exception from kernel and interrupts are enabled. Move to
346bd8b96dfc216eebc72950a6c40da8d3eca8667dfIngo Molnar	 * kernel process stack.
347bd8b96dfc216eebc72950a6c40da8d3eca8667dfIngo Molnar	 */
348081f75bbdc86de53537e1b5aca01de72bd2fea6bAlexander van Heukelum	else if (eregs->flags & X86_EFLAGS_IF)
349081f75bbdc86de53537e1b5aca01de72bd2fea6bAlexander van Heukelum		regs = (struct pt_regs *)(eregs->sp -= sizeof(struct pt_regs));
350081f75bbdc86de53537e1b5aca01de72bd2fea6bAlexander van Heukelum	if (eregs != regs)
351081f75bbdc86de53537e1b5aca01de72bd2fea6bAlexander van Heukelum		*regs = *eregs;
352081f75bbdc86de53537e1b5aca01de72bd2fea6bAlexander van Heukelum	return regs;
353081f75bbdc86de53537e1b5aca01de72bd2fea6bAlexander van Heukelum}
354081f75bbdc86de53537e1b5aca01de72bd2fea6bAlexander van Heukelum#endif
355081f75bbdc86de53537e1b5aca01de72bd2fea6bAlexander van Heukelum
3561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
3571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Our handling of the processor debug registers is non-trivial.
3581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * We do not clear them on entry and exit from the kernel. Therefore
3591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * it is possible to get a watchpoint trap here from inside the kernel.
3601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * However, the code in ./ptrace.c has ensured that the user can
3611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * only set watchpoints on userspace addresses. Therefore the in-kernel
3621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * watchpoint trap can only occur in code which is reading/writing
3631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * from user space. Such code must not hold kernel locks (since it
3641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * can equally take a page fault), therefore it is safe to call
3651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * force_sig_info even though that claims and releases locks.
366b5964405fbc4fd4c57e0e1f86bc9f1b3dbfa040aIngo Molnar *
3671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Code in ./signal.c ensures that the debug control register
3681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * is restored before we deliver any signal, and therefore that
3691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * user code runs with the correct debug control register even though
3701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * we clear it here.
3711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
3721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Being careful here means that we don't have to be as careful in a
3731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * lot of more complicated places (task switching can be a bit lazy
3741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * about restoring all the debug state, and ptrace doesn't have to
3751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * find every occurrence of the TF bit that could be saved away even
3761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * by user code)
377c1d518c8422ff7d3f377958771b265753028579cAlexander van Heukelum *
378c1d518c8422ff7d3f377958771b265753028579cAlexander van Heukelum * May run on IST stack.
3791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
380e407d62088b7f61f38e1086062650c75a4f2757aAlexander van Heukelumdotraplinkage void __kprobes do_debug(struct pt_regs *regs, long error_code)
3811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
3821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct task_struct *tsk = current;
383a1e80fafc9f0742a1776a0490258cb64912411b0Frederic Weisbecker	int user_icebp = 0;
38408d68323d1f0c34452e614263b212ca556dae47fK.Prasad	unsigned long dr6;
385da654b74bda14c45a7d98c731bf3c1a43b6b74e2Srinivasa Ds	int si_code;
3861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
38708d68323d1f0c34452e614263b212ca556dae47fK.Prasad	get_debugreg(dr6, 6);
3881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
38940f9249a73f6c251adea492b1c3d19d39e2a9bdaK.Prasad	/* Filter out all the reserved bits which are preset to 1 */
39040f9249a73f6c251adea492b1c3d19d39e2a9bdaK.Prasad	dr6 &= ~DR6_RESERVED;
39140f9249a73f6c251adea492b1c3d19d39e2a9bdaK.Prasad
392a1e80fafc9f0742a1776a0490258cb64912411b0Frederic Weisbecker	/*
393a1e80fafc9f0742a1776a0490258cb64912411b0Frederic Weisbecker	 * If dr6 has no reason to give us about the origin of this trap,
394a1e80fafc9f0742a1776a0490258cb64912411b0Frederic Weisbecker	 * then it's very likely the result of an icebp/int01 trap.
395a1e80fafc9f0742a1776a0490258cb64912411b0Frederic Weisbecker	 * User wants a sigtrap for that.
396a1e80fafc9f0742a1776a0490258cb64912411b0Frederic Weisbecker	 */
397a1e80fafc9f0742a1776a0490258cb64912411b0Frederic Weisbecker	if (!dr6 && user_mode(regs))
398a1e80fafc9f0742a1776a0490258cb64912411b0Frederic Weisbecker		user_icebp = 1;
399a1e80fafc9f0742a1776a0490258cb64912411b0Frederic Weisbecker
400f85612967c93b67b10dd240e3e8bf8a0eee9def7Vegard Nossum	/* Catch kmemcheck conditions first of all! */
401eadb8a091b27a840de7450f84ecff5ef13476424Ingo Molnar	if ((dr6 & DR_STEP) && kmemcheck_trap(regs))
402f85612967c93b67b10dd240e3e8bf8a0eee9def7Vegard Nossum		return;
403f85612967c93b67b10dd240e3e8bf8a0eee9def7Vegard Nossum
40408d68323d1f0c34452e614263b212ca556dae47fK.Prasad	/* DR6 may or may not be cleared by the CPU */
40508d68323d1f0c34452e614263b212ca556dae47fK.Prasad	set_debugreg(0, 6);
40610faa81e102e2b7695f386812055cd2ef9e44b4cRoland McGrath
407ea8e61b7bbc4a2faef77db34eb2db2a2c2372ff6Peter Zijlstra	/*
408ea8e61b7bbc4a2faef77db34eb2db2a2c2372ff6Peter Zijlstra	 * The processor cleared BTF, so don't mark that we need it set.
409ea8e61b7bbc4a2faef77db34eb2db2a2c2372ff6Peter Zijlstra	 */
410ea8e61b7bbc4a2faef77db34eb2db2a2c2372ff6Peter Zijlstra	clear_tsk_thread_flag(tsk, TIF_BLOCKSTEP);
411ea8e61b7bbc4a2faef77db34eb2db2a2c2372ff6Peter Zijlstra
41208d68323d1f0c34452e614263b212ca556dae47fK.Prasad	/* Store the virtualized DR6 value */
41308d68323d1f0c34452e614263b212ca556dae47fK.Prasad	tsk->thread.debugreg6 = dr6;
41408d68323d1f0c34452e614263b212ca556dae47fK.Prasad
41562edab9056a6cf0c9207339c8892c923a5217e45K.Prasad	if (notify_die(DIE_DEBUG, "debug", regs, PTR_ERR(&dr6), error_code,
41662edab9056a6cf0c9207339c8892c923a5217e45K.Prasad							SIGTRAP) == NOTIFY_STOP)
4171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return;
4183d2a71a596bd9c761c8487a2178e95f8a61da083Alexander van Heukelum
41942181186ad4db986fcaa40ca95c6e407e9e79372Steven Rostedt	/*
42042181186ad4db986fcaa40ca95c6e407e9e79372Steven Rostedt	 * Let others (NMI) know that the debug stack is in use
42142181186ad4db986fcaa40ca95c6e407e9e79372Steven Rostedt	 * as we may switch to the interrupt stack.
42242181186ad4db986fcaa40ca95c6e407e9e79372Steven Rostedt	 */
42342181186ad4db986fcaa40ca95c6e407e9e79372Steven Rostedt	debug_stack_usage_inc();
42442181186ad4db986fcaa40ca95c6e407e9e79372Steven Rostedt
4251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* It's safe to allow irq's after DR6 has been saved */
4263d2a71a596bd9c761c8487a2178e95f8a61da083Alexander van Heukelum	preempt_conditional_sti(regs);
4271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
42808d68323d1f0c34452e614263b212ca556dae47fK.Prasad	if (regs->flags & X86_VM_MASK) {
429c94082656dac74257f63e91f78d5d458ac781fa5Kees Cook		handle_vm86_trap((struct kernel_vm86_regs *) regs, error_code,
430c94082656dac74257f63e91f78d5d458ac781fa5Kees Cook					X86_TRAP_DB);
4316554287b1de0448f1e02e200d02b43914e997d15Bart Oldeman		preempt_conditional_cli(regs);
43242181186ad4db986fcaa40ca95c6e407e9e79372Steven Rostedt		debug_stack_usage_dec();
43308d68323d1f0c34452e614263b212ca556dae47fK.Prasad		return;
4341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
4351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/*
43708d68323d1f0c34452e614263b212ca556dae47fK.Prasad	 * Single-stepping through system calls: ignore any exceptions in
43808d68323d1f0c34452e614263b212ca556dae47fK.Prasad	 * kernel space, but re-enable TF when returning to user mode.
43908d68323d1f0c34452e614263b212ca556dae47fK.Prasad	 *
44008d68323d1f0c34452e614263b212ca556dae47fK.Prasad	 * We already checked v86 mode above, so we can check for kernel mode
44108d68323d1f0c34452e614263b212ca556dae47fK.Prasad	 * by just checking the CPL of CS.
4421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 */
44308d68323d1f0c34452e614263b212ca556dae47fK.Prasad	if ((dr6 & DR_STEP) && !user_mode(regs)) {
44408d68323d1f0c34452e614263b212ca556dae47fK.Prasad		tsk->thread.debugreg6 &= ~DR_STEP;
44508d68323d1f0c34452e614263b212ca556dae47fK.Prasad		set_tsk_thread_flag(tsk, TIF_SINGLESTEP);
44608d68323d1f0c34452e614263b212ca556dae47fK.Prasad		regs->flags &= ~X86_EFLAGS_TF;
4471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
44808d68323d1f0c34452e614263b212ca556dae47fK.Prasad	si_code = get_si_code(tsk->thread.debugreg6);
449a1e80fafc9f0742a1776a0490258cb64912411b0Frederic Weisbecker	if (tsk->thread.debugreg6 & (DR_STEP | DR_TRAP_BITS) || user_icebp)
45008d68323d1f0c34452e614263b212ca556dae47fK.Prasad		send_sigtrap(tsk, regs, error_code, si_code);
4513d2a71a596bd9c761c8487a2178e95f8a61da083Alexander van Heukelum	preempt_conditional_cli(regs);
45242181186ad4db986fcaa40ca95c6e407e9e79372Steven Rostedt	debug_stack_usage_dec();
4531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return;
4551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
4561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
4581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Note that we play around with the 'TS' bit in an attempt to get
4591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * the correct behaviour even in the presence of the asynchronous
4601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * IRQ13 behaviour
4611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
4629b6dba9e0798325dab427b9d60c61630ccc39b28Brian Gerstvoid math_error(struct pt_regs *regs, int error_code, int trapnr)
4631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
464e2e75c915de045f0785387dc32f55e92fab0614cBrian Gerst	struct task_struct *task = current;
4651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	siginfo_t info;
4669b6dba9e0798325dab427b9d60c61630ccc39b28Brian Gerst	unsigned short err;
467c94082656dac74257f63e91f78d5d458ac781fa5Kees Cook	char *str = (trapnr == X86_TRAP_MF) ? "fpu exception" :
468c94082656dac74257f63e91f78d5d458ac781fa5Kees Cook						"simd exception";
469e2e75c915de045f0785387dc32f55e92fab0614cBrian Gerst
470e2e75c915de045f0785387dc32f55e92fab0614cBrian Gerst	if (notify_die(DIE_TRAP, str, regs, error_code, trapnr, SIGFPE) == NOTIFY_STOP)
471e2e75c915de045f0785387dc32f55e92fab0614cBrian Gerst		return;
472e2e75c915de045f0785387dc32f55e92fab0614cBrian Gerst	conditional_sti(regs);
473e2e75c915de045f0785387dc32f55e92fab0614cBrian Gerst
474e2e75c915de045f0785387dc32f55e92fab0614cBrian Gerst	if (!user_mode_vm(regs))
475e2e75c915de045f0785387dc32f55e92fab0614cBrian Gerst	{
476e2e75c915de045f0785387dc32f55e92fab0614cBrian Gerst		if (!fixup_exception(regs)) {
477e2e75c915de045f0785387dc32f55e92fab0614cBrian Gerst			task->thread.error_code = error_code;
47851e7dc7011c99e1e5294658c7b551b92ca069985Srikar Dronamraju			task->thread.trap_nr = trapnr;
479e2e75c915de045f0785387dc32f55e92fab0614cBrian Gerst			die(str, regs, error_code);
480e2e75c915de045f0785387dc32f55e92fab0614cBrian Gerst		}
481e2e75c915de045f0785387dc32f55e92fab0614cBrian Gerst		return;
482e2e75c915de045f0785387dc32f55e92fab0614cBrian Gerst	}
4831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/*
4851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * Save the info for the exception handler and clear the error.
4861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 */
4871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	save_init_fpu(task);
48851e7dc7011c99e1e5294658c7b551b92ca069985Srikar Dronamraju	task->thread.trap_nr = trapnr;
4899b6dba9e0798325dab427b9d60c61630ccc39b28Brian Gerst	task->thread.error_code = error_code;
4901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	info.si_signo = SIGFPE;
4911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	info.si_errno = 0;
4929b6dba9e0798325dab427b9d60c61630ccc39b28Brian Gerst	info.si_addr = (void __user *)regs->ip;
493c94082656dac74257f63e91f78d5d458ac781fa5Kees Cook	if (trapnr == X86_TRAP_MF) {
4949b6dba9e0798325dab427b9d60c61630ccc39b28Brian Gerst		unsigned short cwd, swd;
4959b6dba9e0798325dab427b9d60c61630ccc39b28Brian Gerst		/*
4969b6dba9e0798325dab427b9d60c61630ccc39b28Brian Gerst		 * (~cwd & swd) will mask out exceptions that are not set to unmasked
4979b6dba9e0798325dab427b9d60c61630ccc39b28Brian Gerst		 * status.  0x3f is the exception bits in these regs, 0x200 is the
4989b6dba9e0798325dab427b9d60c61630ccc39b28Brian Gerst		 * C1 reg you need in case of a stack fault, 0x040 is the stack
4999b6dba9e0798325dab427b9d60c61630ccc39b28Brian Gerst		 * fault bit.  We should only be taking one exception at a time,
5009b6dba9e0798325dab427b9d60c61630ccc39b28Brian Gerst		 * so if this combination doesn't produce any single exception,
5019b6dba9e0798325dab427b9d60c61630ccc39b28Brian Gerst		 * then we have a bad program that isn't synchronizing its FPU usage
5029b6dba9e0798325dab427b9d60c61630ccc39b28Brian Gerst		 * and it will suffer the consequences since we won't be able to
5039b6dba9e0798325dab427b9d60c61630ccc39b28Brian Gerst		 * fully reproduce the context of the exception
5049b6dba9e0798325dab427b9d60c61630ccc39b28Brian Gerst		 */
5059b6dba9e0798325dab427b9d60c61630ccc39b28Brian Gerst		cwd = get_fpu_cwd(task);
5069b6dba9e0798325dab427b9d60c61630ccc39b28Brian Gerst		swd = get_fpu_swd(task);
507adf77bac052bb5bf0722b2ce2af9fefc5b2d2a71H. Peter Anvin
5089b6dba9e0798325dab427b9d60c61630ccc39b28Brian Gerst		err = swd & ~cwd;
5099b6dba9e0798325dab427b9d60c61630ccc39b28Brian Gerst	} else {
5109b6dba9e0798325dab427b9d60c61630ccc39b28Brian Gerst		/*
5119b6dba9e0798325dab427b9d60c61630ccc39b28Brian Gerst		 * The SIMD FPU exceptions are handled a little differently, as there
5129b6dba9e0798325dab427b9d60c61630ccc39b28Brian Gerst		 * is only a single status/control register.  Thus, to determine which
5139b6dba9e0798325dab427b9d60c61630ccc39b28Brian Gerst		 * unmasked exception was caught we must mask the exception mask bits
5149b6dba9e0798325dab427b9d60c61630ccc39b28Brian Gerst		 * at 0x1f80, and then use these to mask the exception bits at 0x3f.
5159b6dba9e0798325dab427b9d60c61630ccc39b28Brian Gerst		 */
5169b6dba9e0798325dab427b9d60c61630ccc39b28Brian Gerst		unsigned short mxcsr = get_fpu_mxcsr(task);
5179b6dba9e0798325dab427b9d60c61630ccc39b28Brian Gerst		err = ~(mxcsr >> 7) & mxcsr;
5189b6dba9e0798325dab427b9d60c61630ccc39b28Brian Gerst	}
519adf77bac052bb5bf0722b2ce2af9fefc5b2d2a71H. Peter Anvin
520adf77bac052bb5bf0722b2ce2af9fefc5b2d2a71H. Peter Anvin	if (err & 0x001) {	/* Invalid op */
521b5964405fbc4fd4c57e0e1f86bc9f1b3dbfa040aIngo Molnar		/*
522b5964405fbc4fd4c57e0e1f86bc9f1b3dbfa040aIngo Molnar		 * swd & 0x240 == 0x040: Stack Underflow
523b5964405fbc4fd4c57e0e1f86bc9f1b3dbfa040aIngo Molnar		 * swd & 0x240 == 0x240: Stack Overflow
524b5964405fbc4fd4c57e0e1f86bc9f1b3dbfa040aIngo Molnar		 * User must clear the SF bit (0x40) if set
525b5964405fbc4fd4c57e0e1f86bc9f1b3dbfa040aIngo Molnar		 */
526b5964405fbc4fd4c57e0e1f86bc9f1b3dbfa040aIngo Molnar		info.si_code = FPE_FLTINV;
527adf77bac052bb5bf0722b2ce2af9fefc5b2d2a71H. Peter Anvin	} else if (err & 0x004) { /* Divide by Zero */
528b5964405fbc4fd4c57e0e1f86bc9f1b3dbfa040aIngo Molnar		info.si_code = FPE_FLTDIV;
529adf77bac052bb5bf0722b2ce2af9fefc5b2d2a71H. Peter Anvin	} else if (err & 0x008) { /* Overflow */
530b5964405fbc4fd4c57e0e1f86bc9f1b3dbfa040aIngo Molnar		info.si_code = FPE_FLTOVF;
531adf77bac052bb5bf0722b2ce2af9fefc5b2d2a71H. Peter Anvin	} else if (err & 0x012) { /* Denormal, Underflow */
532adf77bac052bb5bf0722b2ce2af9fefc5b2d2a71H. Peter Anvin		info.si_code = FPE_FLTUND;
533adf77bac052bb5bf0722b2ce2af9fefc5b2d2a71H. Peter Anvin	} else if (err & 0x020) { /* Precision */
534b5964405fbc4fd4c57e0e1f86bc9f1b3dbfa040aIngo Molnar		info.si_code = FPE_FLTRES;
535adf77bac052bb5bf0722b2ce2af9fefc5b2d2a71H. Peter Anvin	} else {
536bd8b96dfc216eebc72950a6c40da8d3eca8667dfIngo Molnar		/*
537c94082656dac74257f63e91f78d5d458ac781fa5Kees Cook		 * If we're using IRQ 13, or supposedly even some trap
538c94082656dac74257f63e91f78d5d458ac781fa5Kees Cook		 * X86_TRAP_MF implementations, it's possible
539c94082656dac74257f63e91f78d5d458ac781fa5Kees Cook		 * we get a spurious trap, which is not an error.
540bd8b96dfc216eebc72950a6c40da8d3eca8667dfIngo Molnar		 */
541c94082656dac74257f63e91f78d5d458ac781fa5Kees Cook		return;
5421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
5431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	force_sig_info(SIGFPE, &info, task);
5441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
5451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
546e407d62088b7f61f38e1086062650c75a4f2757aAlexander van Heukelumdotraplinkage void do_coprocessor_error(struct pt_regs *regs, long error_code)
5471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
548081f75bbdc86de53537e1b5aca01de72bd2fea6bAlexander van Heukelum#ifdef CONFIG_X86_32
5491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ignore_fpu_irq = 1;
550081f75bbdc86de53537e1b5aca01de72bd2fea6bAlexander van Heukelum#endif
551081f75bbdc86de53537e1b5aca01de72bd2fea6bAlexander van Heukelum
552c94082656dac74257f63e91f78d5d458ac781fa5Kees Cook	math_error(regs, error_code, X86_TRAP_MF);
5531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
5541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
555e407d62088b7f61f38e1086062650c75a4f2757aAlexander van Heukelumdotraplinkage void
556e407d62088b7f61f38e1086062650c75a4f2757aAlexander van Heukelumdo_simd_coprocessor_error(struct pt_regs *regs, long error_code)
5571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
558c94082656dac74257f63e91f78d5d458ac781fa5Kees Cook	math_error(regs, error_code, X86_TRAP_XF);
5591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
5601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
561e407d62088b7f61f38e1086062650c75a4f2757aAlexander van Heukelumdotraplinkage void
562e407d62088b7f61f38e1086062650c75a4f2757aAlexander van Heukelumdo_spurious_interrupt_bug(struct pt_regs *regs, long error_code)
5631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
564cf81978d5fb32ab75f701690b372e1126b41861fAlexander van Heukelum	conditional_sti(regs);
5651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#if 0
5661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* No need to warn about this any longer. */
567b5964405fbc4fd4c57e0e1f86bc9f1b3dbfa040aIngo Molnar	printk(KERN_INFO "Ignoring P6 Local APIC Spurious Interrupt Bug...\n");
5681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif
5691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
5701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
571081f75bbdc86de53537e1b5aca01de72bd2fea6bAlexander van Heukelumasmlinkage void __attribute__((weak)) smp_thermal_interrupt(void)
5721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
5731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
5744efc0670baf4b14bc95502e54a83ccf639146125Andi Kleen
5757856f6cce4a8cda8c1f94b99605c07d16b8d8decAndi Kleenasmlinkage void __attribute__((weak)) smp_threshold_interrupt(void)
576081f75bbdc86de53537e1b5aca01de72bd2fea6bAlexander van Heukelum{
577081f75bbdc86de53537e1b5aca01de72bd2fea6bAlexander van Heukelum}
578081f75bbdc86de53537e1b5aca01de72bd2fea6bAlexander van Heukelum
5791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
580b5964405fbc4fd4c57e0e1f86bc9f1b3dbfa040aIngo Molnar * 'math_state_restore()' saves the current math information in the
5811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * old math state array, and gets the new ones from the current task
5821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
5831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Careful.. There are problems with IBM-designed IRQ13 behaviour.
5841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Don't touch unless you *really* know how it works.
5851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
586be98c2cdb15ba26148cd2bd58a857d4f7759ed38Linus Torvalds * Must be called with kernel preemption disabled (eg with local
587be98c2cdb15ba26148cd2bd58a857d4f7759ed38Linus Torvalds * local interrupts as in the case of do_device_not_available).
5881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
589be98c2cdb15ba26148cd2bd58a857d4f7759ed38Linus Torvaldsvoid math_state_restore(void)
5901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
591f94edacf998516ac9d849f7bc6949a703977a7f3Linus Torvalds	struct task_struct *tsk = current;
5921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
593aa283f49276e7d840a40fb01eee6de97eaa7e012Suresh Siddha	if (!tsk_used_math(tsk)) {
594aa283f49276e7d840a40fb01eee6de97eaa7e012Suresh Siddha		local_irq_enable();
595aa283f49276e7d840a40fb01eee6de97eaa7e012Suresh Siddha		/*
596aa283f49276e7d840a40fb01eee6de97eaa7e012Suresh Siddha		 * does a slab alloc which can sleep
597aa283f49276e7d840a40fb01eee6de97eaa7e012Suresh Siddha		 */
598aa283f49276e7d840a40fb01eee6de97eaa7e012Suresh Siddha		if (init_fpu(tsk)) {
599aa283f49276e7d840a40fb01eee6de97eaa7e012Suresh Siddha			/*
600aa283f49276e7d840a40fb01eee6de97eaa7e012Suresh Siddha			 * ran out of memory!
601aa283f49276e7d840a40fb01eee6de97eaa7e012Suresh Siddha			 */
602aa283f49276e7d840a40fb01eee6de97eaa7e012Suresh Siddha			do_group_exit(SIGKILL);
603aa283f49276e7d840a40fb01eee6de97eaa7e012Suresh Siddha			return;
604aa283f49276e7d840a40fb01eee6de97eaa7e012Suresh Siddha		}
605aa283f49276e7d840a40fb01eee6de97eaa7e012Suresh Siddha		local_irq_disable();
606aa283f49276e7d840a40fb01eee6de97eaa7e012Suresh Siddha	}
607aa283f49276e7d840a40fb01eee6de97eaa7e012Suresh Siddha
608f94edacf998516ac9d849f7bc6949a703977a7f3Linus Torvalds	__thread_fpu_begin(tsk);
60980ab6f1e8c981b1b6604b2f22e36c917526235cdLinus Torvalds	/*
61080ab6f1e8c981b1b6604b2f22e36c917526235cdLinus Torvalds	 * Paranoid restore. send a SIGSEGV if we fail to restore the state.
61180ab6f1e8c981b1b6604b2f22e36c917526235cdLinus Torvalds	 */
61280ab6f1e8c981b1b6604b2f22e36c917526235cdLinus Torvalds	if (unlikely(restore_fpu_checking(tsk))) {
61380ab6f1e8c981b1b6604b2f22e36c917526235cdLinus Torvalds		__thread_fpu_end(tsk);
61480ab6f1e8c981b1b6604b2f22e36c917526235cdLinus Torvalds		force_sig(SIGSEGV, tsk);
61580ab6f1e8c981b1b6604b2f22e36c917526235cdLinus Torvalds		return;
61680ab6f1e8c981b1b6604b2f22e36c917526235cdLinus Torvalds	}
617b3b0870ef3ffed72b92415423da864f440f57ad6Linus Torvalds
618b3b0870ef3ffed72b92415423da864f440f57ad6Linus Torvalds	tsk->fpu_counter++;
6191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
6205992b6dac0d23a2b51a1ccbaf8f1a2e62097b12bRusty RussellEXPORT_SYMBOL_GPL(math_state_restore);
6211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
622e407d62088b7f61f38e1086062650c75a4f2757aAlexander van Heukelumdotraplinkage void __kprobes
623aa78bcfa01dec3cdbde3cda098ce32abbd9c3bf6Brian Gerstdo_device_not_available(struct pt_regs *regs, long error_code)
6247643e9b936b4af31ba4851eb7d5b3a3bfad52502Alexander van Heukelum{
625a334fe43d85f570ae907acf988a053c5eff78d6eBrian Gerst#ifdef CONFIG_MATH_EMULATION
6267643e9b936b4af31ba4851eb7d5b3a3bfad52502Alexander van Heukelum	if (read_cr0() & X86_CR0_EM) {
627d315760ffa261c15ff92699ac6f514112543d7caTejun Heo		struct math_emu_info info = { };
628d315760ffa261c15ff92699ac6f514112543d7caTejun Heo
6297643e9b936b4af31ba4851eb7d5b3a3bfad52502Alexander van Heukelum		conditional_sti(regs);
630d315760ffa261c15ff92699ac6f514112543d7caTejun Heo
631aa78bcfa01dec3cdbde3cda098ce32abbd9c3bf6Brian Gerst		info.regs = regs;
632d315760ffa261c15ff92699ac6f514112543d7caTejun Heo		math_emulate(&info);
633a334fe43d85f570ae907acf988a053c5eff78d6eBrian Gerst		return;
6347643e9b936b4af31ba4851eb7d5b3a3bfad52502Alexander van Heukelum	}
635a334fe43d85f570ae907acf988a053c5eff78d6eBrian Gerst#endif
636a334fe43d85f570ae907acf988a053c5eff78d6eBrian Gerst	math_state_restore(); /* interrupts still off */
637a334fe43d85f570ae907acf988a053c5eff78d6eBrian Gerst#ifdef CONFIG_X86_32
638a334fe43d85f570ae907acf988a053c5eff78d6eBrian Gerst	conditional_sti(regs);
639081f75bbdc86de53537e1b5aca01de72bd2fea6bAlexander van Heukelum#endif
6407643e9b936b4af31ba4851eb7d5b3a3bfad52502Alexander van Heukelum}
6417643e9b936b4af31ba4851eb7d5b3a3bfad52502Alexander van Heukelum
642081f75bbdc86de53537e1b5aca01de72bd2fea6bAlexander van Heukelum#ifdef CONFIG_X86_32
643e407d62088b7f61f38e1086062650c75a4f2757aAlexander van Heukelumdotraplinkage void do_iret_error(struct pt_regs *regs, long error_code)
644f8e0870f589cfa45575dc7333cdf1b8f769e7900Alexander van Heukelum{
645f8e0870f589cfa45575dc7333cdf1b8f769e7900Alexander van Heukelum	siginfo_t info;
646f8e0870f589cfa45575dc7333cdf1b8f769e7900Alexander van Heukelum	local_irq_enable();
647f8e0870f589cfa45575dc7333cdf1b8f769e7900Alexander van Heukelum
648f8e0870f589cfa45575dc7333cdf1b8f769e7900Alexander van Heukelum	info.si_signo = SIGILL;
649f8e0870f589cfa45575dc7333cdf1b8f769e7900Alexander van Heukelum	info.si_errno = 0;
650f8e0870f589cfa45575dc7333cdf1b8f769e7900Alexander van Heukelum	info.si_code = ILL_BADSTK;
651fc6fcdfbb8f1b2553255170f221cd57a4108591fHannes Eder	info.si_addr = NULL;
652c94082656dac74257f63e91f78d5d458ac781fa5Kees Cook	if (notify_die(DIE_TRAP, "iret exception", regs, error_code,
653c94082656dac74257f63e91f78d5d458ac781fa5Kees Cook			X86_TRAP_IRET, SIGILL) == NOTIFY_STOP)
654f8e0870f589cfa45575dc7333cdf1b8f769e7900Alexander van Heukelum		return;
655c94082656dac74257f63e91f78d5d458ac781fa5Kees Cook	do_trap(X86_TRAP_IRET, SIGILL, "iret exception", regs, error_code,
656c94082656dac74257f63e91f78d5d458ac781fa5Kees Cook		&info);
657f8e0870f589cfa45575dc7333cdf1b8f769e7900Alexander van Heukelum}
658081f75bbdc86de53537e1b5aca01de72bd2fea6bAlexander van Heukelum#endif
659f8e0870f589cfa45575dc7333cdf1b8f769e7900Alexander van Heukelum
66029c843912a0baa7fa63033fe28e1ca7e796686a5Jan Kiszka/* Set of traps needed for early debugging. */
66129c843912a0baa7fa63033fe28e1ca7e796686a5Jan Kiszkavoid __init early_trap_init(void)
66229c843912a0baa7fa63033fe28e1ca7e796686a5Jan Kiszka{
663c94082656dac74257f63e91f78d5d458ac781fa5Kees Cook	set_intr_gate_ist(X86_TRAP_DB, &debug, DEBUG_STACK);
66429c843912a0baa7fa63033fe28e1ca7e796686a5Jan Kiszka	/* int3 can be called from all */
665c94082656dac74257f63e91f78d5d458ac781fa5Kees Cook	set_system_intr_gate_ist(X86_TRAP_BP, &int3, DEBUG_STACK);
666c94082656dac74257f63e91f78d5d458ac781fa5Kees Cook	set_intr_gate(X86_TRAP_PF, &page_fault);
66729c843912a0baa7fa63033fe28e1ca7e796686a5Jan Kiszka	load_idt(&idt_descr);
66829c843912a0baa7fa63033fe28e1ca7e796686a5Jan Kiszka}
66929c843912a0baa7fa63033fe28e1ca7e796686a5Jan Kiszka
6701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsvoid __init trap_init(void)
6711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
672dbeb2be21d678c49a8d8bbf774903df15dd55474Rusty Russell	int i;
673dbeb2be21d678c49a8d8bbf774903df15dd55474Rusty Russell
6741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef CONFIG_EISA
675927222b102186a6cc3e43e25062fcd18c800435eIngo Molnar	void __iomem *p = early_ioremap(0x0FFFD9, 4);
676b5964405fbc4fd4c57e0e1f86bc9f1b3dbfa040aIngo Molnar
677b5964405fbc4fd4c57e0e1f86bc9f1b3dbfa040aIngo Molnar	if (readl(p) == 'E' + ('I'<<8) + ('S'<<16) + ('A'<<24))
6781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		EISA_bus = 1;
679927222b102186a6cc3e43e25062fcd18c800435eIngo Molnar	early_iounmap(p, 4);
6801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif
6811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
682c94082656dac74257f63e91f78d5d458ac781fa5Kees Cook	set_intr_gate(X86_TRAP_DE, &divide_error);
683c94082656dac74257f63e91f78d5d458ac781fa5Kees Cook	set_intr_gate_ist(X86_TRAP_NMI, &nmi, NMI_STACK);
684699d2937d45d9dabc1772d0d07501ccc43885c23Alexander van Heukelum	/* int4 can be called from all */
685c94082656dac74257f63e91f78d5d458ac781fa5Kees Cook	set_system_intr_gate(X86_TRAP_OF, &overflow);
686c94082656dac74257f63e91f78d5d458ac781fa5Kees Cook	set_intr_gate(X86_TRAP_BR, &bounds);
687c94082656dac74257f63e91f78d5d458ac781fa5Kees Cook	set_intr_gate(X86_TRAP_UD, &invalid_op);
688c94082656dac74257f63e91f78d5d458ac781fa5Kees Cook	set_intr_gate(X86_TRAP_NM, &device_not_available);
689081f75bbdc86de53537e1b5aca01de72bd2fea6bAlexander van Heukelum#ifdef CONFIG_X86_32
690c94082656dac74257f63e91f78d5d458ac781fa5Kees Cook	set_task_gate(X86_TRAP_DF, GDT_ENTRY_DOUBLEFAULT_TSS);
691081f75bbdc86de53537e1b5aca01de72bd2fea6bAlexander van Heukelum#else
692c94082656dac74257f63e91f78d5d458ac781fa5Kees Cook	set_intr_gate_ist(X86_TRAP_DF, &double_fault, DOUBLEFAULT_STACK);
693081f75bbdc86de53537e1b5aca01de72bd2fea6bAlexander van Heukelum#endif
694c94082656dac74257f63e91f78d5d458ac781fa5Kees Cook	set_intr_gate(X86_TRAP_OLD_MF, &coprocessor_segment_overrun);
695c94082656dac74257f63e91f78d5d458ac781fa5Kees Cook	set_intr_gate(X86_TRAP_TS, &invalid_TSS);
696c94082656dac74257f63e91f78d5d458ac781fa5Kees Cook	set_intr_gate(X86_TRAP_NP, &segment_not_present);
697c94082656dac74257f63e91f78d5d458ac781fa5Kees Cook	set_intr_gate_ist(X86_TRAP_SS, &stack_segment, STACKFAULT_STACK);
698c94082656dac74257f63e91f78d5d458ac781fa5Kees Cook	set_intr_gate(X86_TRAP_GP, &general_protection);
699c94082656dac74257f63e91f78d5d458ac781fa5Kees Cook	set_intr_gate(X86_TRAP_SPURIOUS, &spurious_interrupt_bug);
700c94082656dac74257f63e91f78d5d458ac781fa5Kees Cook	set_intr_gate(X86_TRAP_MF, &coprocessor_error);
701c94082656dac74257f63e91f78d5d458ac781fa5Kees Cook	set_intr_gate(X86_TRAP_AC, &alignment_check);
7021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef CONFIG_X86_MCE
703c94082656dac74257f63e91f78d5d458ac781fa5Kees Cook	set_intr_gate_ist(X86_TRAP_MC, &machine_check, MCE_STACK);
7041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif
705c94082656dac74257f63e91f78d5d458ac781fa5Kees Cook	set_intr_gate(X86_TRAP_XF, &simd_coprocessor_error);
7061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
707bb3f0b59ad005d2d2ecbbe9bd048eab6d1ecbd31Yinghai Lu	/* Reserve all the builtin and the syscall vector: */
708bb3f0b59ad005d2d2ecbbe9bd048eab6d1ecbd31Yinghai Lu	for (i = 0; i < FIRST_EXTERNAL_VECTOR; i++)
709bb3f0b59ad005d2d2ecbbe9bd048eab6d1ecbd31Yinghai Lu		set_bit(i, used_vectors);
710bb3f0b59ad005d2d2ecbbe9bd048eab6d1ecbd31Yinghai Lu
711081f75bbdc86de53537e1b5aca01de72bd2fea6bAlexander van Heukelum#ifdef CONFIG_IA32_EMULATION
712081f75bbdc86de53537e1b5aca01de72bd2fea6bAlexander van Heukelum	set_system_intr_gate(IA32_SYSCALL_VECTOR, ia32_syscall);
713bb3f0b59ad005d2d2ecbbe9bd048eab6d1ecbd31Yinghai Lu	set_bit(IA32_SYSCALL_VECTOR, used_vectors);
714081f75bbdc86de53537e1b5aca01de72bd2fea6bAlexander van Heukelum#endif
715081f75bbdc86de53537e1b5aca01de72bd2fea6bAlexander van Heukelum
716081f75bbdc86de53537e1b5aca01de72bd2fea6bAlexander van Heukelum#ifdef CONFIG_X86_32
717699d2937d45d9dabc1772d0d07501ccc43885c23Alexander van Heukelum	set_system_trap_gate(SYSCALL_VECTOR, &system_call);
718dbeb2be21d678c49a8d8bbf774903df15dd55474Rusty Russell	set_bit(SYSCALL_VECTOR, used_vectors);
719081f75bbdc86de53537e1b5aca01de72bd2fea6bAlexander van Heukelum#endif
720bb3f0b59ad005d2d2ecbbe9bd048eab6d1ecbd31Yinghai Lu
7211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/*
722b5964405fbc4fd4c57e0e1f86bc9f1b3dbfa040aIngo Molnar	 * Should be a barrier for any external CPU state:
7231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 */
7241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	cpu_init();
7251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
726428cf9025b15573e16e658032f2b963283e34ae0Thomas Gleixner	x86_init.irqs.trap_init();
727228bdaa95fb830e08b6acd1afd4d2c55093cabfaSteven Rostedt
728228bdaa95fb830e08b6acd1afd4d2c55093cabfaSteven Rostedt#ifdef CONFIG_X86_64
729228bdaa95fb830e08b6acd1afd4d2c55093cabfaSteven Rostedt	memcpy(&nmi_idt_table, &idt_table, IDT_ENTRIES * 16);
730c94082656dac74257f63e91f78d5d458ac781fa5Kees Cook	set_nmi_gate(X86_TRAP_DB, &debug);
731c94082656dac74257f63e91f78d5d458ac781fa5Kees Cook	set_nmi_gate(X86_TRAP_BP, &int3);
732228bdaa95fb830e08b6acd1afd4d2c55093cabfaSteven Rostedt#endif
7331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
734