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 */
12c767a54ba0657e52e6edaa97cbe0b0a8bf1c1655Joe Perches
13c767a54ba0657e52e6edaa97cbe0b0a8bf1c1655Joe Perches#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
14c767a54ba0657e52e6edaa97cbe0b0a8bf1c1655Joe Perches
1556dd9470d7c8734f055da2a6bac553caf4a468ebFrederic Weisbecker#include <linux/context_tracking.h>
16b5964405fbc4fd4c57e0e1f86bc9f1b3dbfa040aIngo Molnar#include <linux/interrupt.h>
17b5964405fbc4fd4c57e0e1f86bc9f1b3dbfa040aIngo Molnar#include <linux/kallsyms.h>
18b5964405fbc4fd4c57e0e1f86bc9f1b3dbfa040aIngo Molnar#include <linux/spinlock.h>
19b5964405fbc4fd4c57e0e1f86bc9f1b3dbfa040aIngo Molnar#include <linux/kprobes.h>
20b5964405fbc4fd4c57e0e1f86bc9f1b3dbfa040aIngo Molnar#include <linux/uaccess.h>
21b5964405fbc4fd4c57e0e1f86bc9f1b3dbfa040aIngo Molnar#include <linux/kdebug.h>
22f503b5ae53cb557ac351a668fcac1baab1cef0dbJason Wessel#include <linux/kgdb.h>
231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/kernel.h>
24b5964405fbc4fd4c57e0e1f86bc9f1b3dbfa040aIngo Molnar#include <linux/module.h>
25b5964405fbc4fd4c57e0e1f86bc9f1b3dbfa040aIngo Molnar#include <linux/ptrace.h>
26b02ef20a9fba08948e643d3eec0efadf1da01a44Oleg Nesterov#include <linux/uprobes.h>
271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/string.h>
28b5964405fbc4fd4c57e0e1f86bc9f1b3dbfa040aIngo Molnar#include <linux/delay.h>
291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/errno.h>
30b5964405fbc4fd4c57e0e1f86bc9f1b3dbfa040aIngo Molnar#include <linux/kexec.h>
31b5964405fbc4fd4c57e0e1f86bc9f1b3dbfa040aIngo Molnar#include <linux/sched.h>
321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/timer.h>
331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/init.h>
3491768d6c2bad0d2766a166f13f2f57e197de3458Jeremy Fitzhardinge#include <linux/bug.h>
35b5964405fbc4fd4c57e0e1f86bc9f1b3dbfa040aIngo Molnar#include <linux/nmi.h>
36b5964405fbc4fd4c57e0e1f86bc9f1b3dbfa040aIngo Molnar#include <linux/mm.h>
37c1d518c8422ff7d3f377958771b265753028579cAlexander van Heukelum#include <linux/smp.h>
38c1d518c8422ff7d3f377958771b265753028579cAlexander van Heukelum#include <linux/io.h>
391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef CONFIG_EISA
411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/ioport.h>
421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/eisa.h>
431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif
441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
45c0d121720220584bba2876b032e58a076b843fa1Dave Jiang#if defined(CONFIG_EDAC)
46c0d121720220584bba2876b032e58a076b843fa1Dave Jiang#include <linux/edac.h>
47c0d121720220584bba2876b032e58a076b843fa1Dave Jiang#endif
48c0d121720220584bba2876b032e58a076b843fa1Dave Jiang
49f85612967c93b67b10dd240e3e8bf8a0eee9def7Vegard Nossum#include <asm/kmemcheck.h>
50b5964405fbc4fd4c57e0e1f86bc9f1b3dbfa040aIngo Molnar#include <asm/stacktrace.h>
511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <asm/processor.h>
521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <asm/debugreg.h>
5360063497a95e716c9a689af3be2687d261f115b4Arun Sharma#include <linux/atomic.h>
5408d636b6d4fb80647fe8869ea1cd97b2c26a4751Steven Rostedt#include <asm/ftrace.h>
55c1d518c8422ff7d3f377958771b265753028579cAlexander van Heukelum#include <asm/traps.h>
561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <asm/desc.h>
571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <asm/i387.h>
581361b83a13d4d92e53fbb6c877528713e118b821Linus Torvalds#include <asm/fpu-internal.h>
599e55e44e39798541ba39d57f4b569deb555ae1ceHidetoshi Seto#include <asm/mce.h>
604eefbe792baedb474e256d35370849992fcf1c79Kees Cook#include <asm/fixmap.h>
611164dd0099c0d79146a55319670f57ab7ad1d352Ingo Molnar#include <asm/mach_traps.h>
6217f41571bb2c4a398785452ac2718a6c5d77180eJiri Kosina#include <asm/alternative.h>
63c1d518c8422ff7d3f377958771b265753028579cAlexander van Heukelum
64081f75bbdc86de53537e1b5aca01de72bd2fea6bAlexander van Heukelum#ifdef CONFIG_X86_64
65428cf9025b15573e16e658032f2b963283e34ae0Thomas Gleixner#include <asm/x86_init.h>
66081f75bbdc86de53537e1b5aca01de72bd2fea6bAlexander van Heukelum#include <asm/pgalloc.h>
67081f75bbdc86de53537e1b5aca01de72bd2fea6bAlexander van Heukelum#include <asm/proto.h>
684df05f361937ee86e5a8c9ead8aeb6a19ea9b7d7Kees Cook
694df05f361937ee86e5a8c9ead8aeb6a19ea9b7d7Kees Cook/* No need to be aligned, but done to keep all IDTs defined the same way. */
704df05f361937ee86e5a8c9ead8aeb6a19ea9b7d7Kees Cookgate_desc debug_idt_table[NR_VECTORS] __page_aligned_bss;
71081f75bbdc86de53537e1b5aca01de72bd2fea6bAlexander van Heukelum#else
72c1d518c8422ff7d3f377958771b265753028579cAlexander van Heukelum#include <asm/processor-flags.h>
738e6dafd6c741cd4679b4de3c5d9698851e4fa59cIngo Molnar#include <asm/setup.h>
741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsasmlinkage int system_call(void);
76081f75bbdc86de53537e1b5aca01de72bd2fea6bAlexander van Heukelum#endif
771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
784df05f361937ee86e5a8c9ead8aeb6a19ea9b7d7Kees Cook/* Must be page-aligned because the real IDT is used in a fixmap. */
794df05f361937ee86e5a8c9ead8aeb6a19ea9b7d7Kees Cookgate_desc idt_table[NR_VECTORS] __page_aligned_bss;
804df05f361937ee86e5a8c9ead8aeb6a19ea9b7d7Kees Cook
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{
92bdb43806589096ac4272fe1307e789846ac08d7cPeter Zijlstra	preempt_count_inc();
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();
107bdb43806589096ac4272fe1307e789846ac08d7cPeter Zijlstra	preempt_count_dec();
1083d2a71a596bd9c761c8487a2178e95f8a61da083Alexander van Heukelum}
1093d2a71a596bd9c761c8487a2178e95f8a61da083Alexander van Heukelum
1109326638cbee2d36b051ed2a69f3e4e107e5f86bdMasami Hiramatsustatic nokprobe_inline int
111c416ddf5b909736f5b57d348f5de159693e699adFrederic Weisbeckerdo_trap_no_signal(struct task_struct *tsk, int trapnr, char *str,
112c416ddf5b909736f5b57d348f5de159693e699adFrederic Weisbecker		  struct pt_regs *regs,	long error_code)
1131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
114081f75bbdc86de53537e1b5aca01de72bd2fea6bAlexander van Heukelum#ifdef CONFIG_X86_32
1156b6891f9c545ccd45d6d8ddfd33ce27c22c271a7gorcunov@gmail.com	if (regs->flags & X86_VM_MASK) {
1163c1326f8a6d8b9815ca88c95441330f96eef7352Alexander van Heukelum		/*
117c416ddf5b909736f5b57d348f5de159693e699adFrederic Weisbecker		 * Traps 0, 1, 3, 4, and 5 should be forwarded to vm86.
1183c1326f8a6d8b9815ca88c95441330f96eef7352Alexander van Heukelum		 * On nmi (interrupt 2), do_trap should not be called.
1193c1326f8a6d8b9815ca88c95441330f96eef7352Alexander van Heukelum		 */
120c416ddf5b909736f5b57d348f5de159693e699adFrederic Weisbecker		if (trapnr < X86_TRAP_UD) {
121c416ddf5b909736f5b57d348f5de159693e699adFrederic Weisbecker			if (!handle_vm86_trap((struct kernel_vm86_regs *) regs,
122c416ddf5b909736f5b57d348f5de159693e699adFrederic Weisbecker						error_code, trapnr))
123c416ddf5b909736f5b57d348f5de159693e699adFrederic Weisbecker				return 0;
124c416ddf5b909736f5b57d348f5de159693e699adFrederic Weisbecker		}
125c416ddf5b909736f5b57d348f5de159693e699adFrederic Weisbecker		return -1;
1261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
127081f75bbdc86de53537e1b5aca01de72bd2fea6bAlexander van Heukelum#endif
128c416ddf5b909736f5b57d348f5de159693e699adFrederic Weisbecker	if (!user_mode(regs)) {
129c416ddf5b909736f5b57d348f5de159693e699adFrederic Weisbecker		if (!fixup_exception(regs)) {
130c416ddf5b909736f5b57d348f5de159693e699adFrederic Weisbecker			tsk->thread.error_code = error_code;
131c416ddf5b909736f5b57d348f5de159693e699adFrederic Weisbecker			tsk->thread.trap_nr = trapnr;
132c416ddf5b909736f5b57d348f5de159693e699adFrederic Weisbecker			die(str, regs, error_code);
133c416ddf5b909736f5b57d348f5de159693e699adFrederic Weisbecker		}
134c416ddf5b909736f5b57d348f5de159693e699adFrederic Weisbecker		return 0;
135c416ddf5b909736f5b57d348f5de159693e699adFrederic Weisbecker	}
1361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
137c416ddf5b909736f5b57d348f5de159693e699adFrederic Weisbecker	return -1;
138c416ddf5b909736f5b57d348f5de159693e699adFrederic Weisbecker}
1391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1401c326c4dfe182a1c4c1e39f2c00f04c380d11692Oleg Nesterovstatic siginfo_t *fill_trap_info(struct pt_regs *regs, int signr, int trapnr,
1411c326c4dfe182a1c4c1e39f2c00f04c380d11692Oleg Nesterov				siginfo_t *info)
142958d3d729802f7d741cbe8400e69b89baae580eeOleg Nesterov{
143958d3d729802f7d741cbe8400e69b89baae580eeOleg Nesterov	unsigned long siaddr;
144958d3d729802f7d741cbe8400e69b89baae580eeOleg Nesterov	int sicode;
145958d3d729802f7d741cbe8400e69b89baae580eeOleg Nesterov
146958d3d729802f7d741cbe8400e69b89baae580eeOleg Nesterov	switch (trapnr) {
1471c326c4dfe182a1c4c1e39f2c00f04c380d11692Oleg Nesterov	default:
1481c326c4dfe182a1c4c1e39f2c00f04c380d11692Oleg Nesterov		return SEND_SIG_PRIV;
1491c326c4dfe182a1c4c1e39f2c00f04c380d11692Oleg Nesterov
150958d3d729802f7d741cbe8400e69b89baae580eeOleg Nesterov	case X86_TRAP_DE:
151958d3d729802f7d741cbe8400e69b89baae580eeOleg Nesterov		sicode = FPE_INTDIV;
152b02ef20a9fba08948e643d3eec0efadf1da01a44Oleg Nesterov		siaddr = uprobe_get_trap_addr(regs);
153958d3d729802f7d741cbe8400e69b89baae580eeOleg Nesterov		break;
154958d3d729802f7d741cbe8400e69b89baae580eeOleg Nesterov	case X86_TRAP_UD:
155958d3d729802f7d741cbe8400e69b89baae580eeOleg Nesterov		sicode = ILL_ILLOPN;
156b02ef20a9fba08948e643d3eec0efadf1da01a44Oleg Nesterov		siaddr = uprobe_get_trap_addr(regs);
157958d3d729802f7d741cbe8400e69b89baae580eeOleg Nesterov		break;
158958d3d729802f7d741cbe8400e69b89baae580eeOleg Nesterov	case X86_TRAP_AC:
159958d3d729802f7d741cbe8400e69b89baae580eeOleg Nesterov		sicode = BUS_ADRALN;
160958d3d729802f7d741cbe8400e69b89baae580eeOleg Nesterov		siaddr = 0;
161958d3d729802f7d741cbe8400e69b89baae580eeOleg Nesterov		break;
162958d3d729802f7d741cbe8400e69b89baae580eeOleg Nesterov	}
163958d3d729802f7d741cbe8400e69b89baae580eeOleg Nesterov
164958d3d729802f7d741cbe8400e69b89baae580eeOleg Nesterov	info->si_signo = signr;
165958d3d729802f7d741cbe8400e69b89baae580eeOleg Nesterov	info->si_errno = 0;
166958d3d729802f7d741cbe8400e69b89baae580eeOleg Nesterov	info->si_code = sicode;
167958d3d729802f7d741cbe8400e69b89baae580eeOleg Nesterov	info->si_addr = (void __user *)siaddr;
1681c326c4dfe182a1c4c1e39f2c00f04c380d11692Oleg Nesterov	return info;
169958d3d729802f7d741cbe8400e69b89baae580eeOleg Nesterov}
170958d3d729802f7d741cbe8400e69b89baae580eeOleg Nesterov
1719326638cbee2d36b051ed2a69f3e4e107e5f86bdMasami Hiramatsustatic void
172c416ddf5b909736f5b57d348f5de159693e699adFrederic Weisbeckerdo_trap(int trapnr, int signr, char *str, struct pt_regs *regs,
173c416ddf5b909736f5b57d348f5de159693e699adFrederic Weisbecker	long error_code, siginfo_t *info)
174c416ddf5b909736f5b57d348f5de159693e699adFrederic Weisbecker{
175c416ddf5b909736f5b57d348f5de159693e699adFrederic Weisbecker	struct task_struct *tsk = current;
176c416ddf5b909736f5b57d348f5de159693e699adFrederic Weisbecker
177c416ddf5b909736f5b57d348f5de159693e699adFrederic Weisbecker
178c416ddf5b909736f5b57d348f5de159693e699adFrederic Weisbecker	if (!do_trap_no_signal(tsk, trapnr, str, regs, error_code))
179c416ddf5b909736f5b57d348f5de159693e699adFrederic Weisbecker		return;
180b5964405fbc4fd4c57e0e1f86bc9f1b3dbfa040aIngo Molnar	/*
18151e7dc7011c99e1e5294658c7b551b92ca069985Srikar Dronamraju	 * We want error_code and trap_nr set for userspace faults and
182b5964405fbc4fd4c57e0e1f86bc9f1b3dbfa040aIngo Molnar	 * kernelspace faults which result in die(), but not
183b5964405fbc4fd4c57e0e1f86bc9f1b3dbfa040aIngo Molnar	 * kernelspace faults which are fixed up.  die() gives the
184b5964405fbc4fd4c57e0e1f86bc9f1b3dbfa040aIngo Molnar	 * process no chance to handle the signal and notice the
185b5964405fbc4fd4c57e0e1f86bc9f1b3dbfa040aIngo Molnar	 * kernel fault information, so that won't result in polluting
186b5964405fbc4fd4c57e0e1f86bc9f1b3dbfa040aIngo Molnar	 * the information about previously queued, but not yet
187b5964405fbc4fd4c57e0e1f86bc9f1b3dbfa040aIngo Molnar	 * delivered, faults.  See also do_general_protection below.
188b5964405fbc4fd4c57e0e1f86bc9f1b3dbfa040aIngo Molnar	 */
189b5964405fbc4fd4c57e0e1f86bc9f1b3dbfa040aIngo Molnar	tsk->thread.error_code = error_code;
19051e7dc7011c99e1e5294658c7b551b92ca069985Srikar Dronamraju	tsk->thread.trap_nr = trapnr;
191d18951834216eae82e2f9112416111b4f55f1849Andi Kleen
192081f75bbdc86de53537e1b5aca01de72bd2fea6bAlexander van Heukelum#ifdef CONFIG_X86_64
193081f75bbdc86de53537e1b5aca01de72bd2fea6bAlexander van Heukelum	if (show_unhandled_signals && unhandled_signal(tsk, signr) &&
194081f75bbdc86de53537e1b5aca01de72bd2fea6bAlexander van Heukelum	    printk_ratelimit()) {
195c767a54ba0657e52e6edaa97cbe0b0a8bf1c1655Joe Perches		pr_info("%s[%d] trap %s ip:%lx sp:%lx error:%lx",
196c767a54ba0657e52e6edaa97cbe0b0a8bf1c1655Joe Perches			tsk->comm, tsk->pid, str,
197c767a54ba0657e52e6edaa97cbe0b0a8bf1c1655Joe Perches			regs->ip, regs->sp, error_code);
198081f75bbdc86de53537e1b5aca01de72bd2fea6bAlexander van Heukelum		print_vma_addr(" in ", regs->ip);
199c767a54ba0657e52e6edaa97cbe0b0a8bf1c1655Joe Perches		pr_cont("\n");
200081f75bbdc86de53537e1b5aca01de72bd2fea6bAlexander van Heukelum	}
201081f75bbdc86de53537e1b5aca01de72bd2fea6bAlexander van Heukelum#endif
202081f75bbdc86de53537e1b5aca01de72bd2fea6bAlexander van Heukelum
20338cad57be9800e46c52a3612fb9d963eee4fd9c3Oleg Nesterov	force_sig_info(signr, info ?: SEND_SIG_PRIV, tsk);
2041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
2059326638cbee2d36b051ed2a69f3e4e107e5f86bdMasami HiramatsuNOKPROBE_SYMBOL(do_trap);
2061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
207dff0796e53c29147c9bd1f5567a261dcf0e528bcOleg Nesterovstatic void do_error_trap(struct pt_regs *regs, long error_code, char *str,
2081c326c4dfe182a1c4c1e39f2c00f04c380d11692Oleg Nesterov			  unsigned long trapnr, int signr)
209dff0796e53c29147c9bd1f5567a261dcf0e528bcOleg Nesterov{
210dff0796e53c29147c9bd1f5567a261dcf0e528bcOleg Nesterov	enum ctx_state prev_state = exception_enter();
2111c326c4dfe182a1c4c1e39f2c00f04c380d11692Oleg Nesterov	siginfo_t info;
212dff0796e53c29147c9bd1f5567a261dcf0e528bcOleg Nesterov
213dff0796e53c29147c9bd1f5567a261dcf0e528bcOleg Nesterov	if (notify_die(DIE_TRAP, str, regs, error_code, trapnr, signr) !=
214dff0796e53c29147c9bd1f5567a261dcf0e528bcOleg Nesterov			NOTIFY_STOP) {
215dff0796e53c29147c9bd1f5567a261dcf0e528bcOleg Nesterov		conditional_sti(regs);
2161c326c4dfe182a1c4c1e39f2c00f04c380d11692Oleg Nesterov		do_trap(trapnr, signr, str, regs, error_code,
2171c326c4dfe182a1c4c1e39f2c00f04c380d11692Oleg Nesterov			fill_trap_info(regs, signr, trapnr, &info));
218dff0796e53c29147c9bd1f5567a261dcf0e528bcOleg Nesterov	}
219dff0796e53c29147c9bd1f5567a261dcf0e528bcOleg Nesterov
220dff0796e53c29147c9bd1f5567a261dcf0e528bcOleg Nesterov	exception_exit(prev_state);
221dff0796e53c29147c9bd1f5567a261dcf0e528bcOleg Nesterov}
222dff0796e53c29147c9bd1f5567a261dcf0e528bcOleg Nesterov
223b5964405fbc4fd4c57e0e1f86bc9f1b3dbfa040aIngo Molnar#define DO_ERROR(trapnr, signr, str, name)				\
224e407d62088b7f61f38e1086062650c75a4f2757aAlexander van Heukelumdotraplinkage void do_##name(struct pt_regs *regs, long error_code)	\
225b5964405fbc4fd4c57e0e1f86bc9f1b3dbfa040aIngo Molnar{									\
2261c326c4dfe182a1c4c1e39f2c00f04c380d11692Oleg Nesterov	do_error_trap(regs, error_code, str, trapnr, signr);		\
2271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
2281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2290eb14833d5b1ea1accfeffb71be5de5929f85da9Oleg NesterovDO_ERROR(X86_TRAP_DE,     SIGFPE,  "divide error",		divide_error)
2300eb14833d5b1ea1accfeffb71be5de5929f85da9Oleg NesterovDO_ERROR(X86_TRAP_OF,     SIGSEGV, "overflow",			overflow)
2310eb14833d5b1ea1accfeffb71be5de5929f85da9Oleg NesterovDO_ERROR(X86_TRAP_BR,     SIGSEGV, "bounds",			bounds)
2320eb14833d5b1ea1accfeffb71be5de5929f85da9Oleg NesterovDO_ERROR(X86_TRAP_UD,     SIGILL,  "invalid opcode",		invalid_op)
2330eb14833d5b1ea1accfeffb71be5de5929f85da9Oleg NesterovDO_ERROR(X86_TRAP_OLD_MF, SIGFPE,  "coprocessor segment overrun",coprocessor_segment_overrun)
2340eb14833d5b1ea1accfeffb71be5de5929f85da9Oleg NesterovDO_ERROR(X86_TRAP_TS,     SIGSEGV, "invalid TSS",		invalid_TSS)
2350eb14833d5b1ea1accfeffb71be5de5929f85da9Oleg NesterovDO_ERROR(X86_TRAP_NP,     SIGBUS,  "segment not present",	segment_not_present)
2360eb14833d5b1ea1accfeffb71be5de5929f85da9Oleg NesterovDO_ERROR(X86_TRAP_SS,     SIGBUS,  "stack segment",		stack_segment)
2370eb14833d5b1ea1accfeffb71be5de5929f85da9Oleg NesterovDO_ERROR(X86_TRAP_AC,     SIGBUS,  "alignment check",		alignment_check)
2381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
239081f75bbdc86de53537e1b5aca01de72bd2fea6bAlexander van Heukelum#ifdef CONFIG_X86_64
240081f75bbdc86de53537e1b5aca01de72bd2fea6bAlexander van Heukelum/* Runs on IST stack */
241081f75bbdc86de53537e1b5aca01de72bd2fea6bAlexander van Heukelumdotraplinkage void do_double_fault(struct pt_regs *regs, long error_code)
242081f75bbdc86de53537e1b5aca01de72bd2fea6bAlexander van Heukelum{
243081f75bbdc86de53537e1b5aca01de72bd2fea6bAlexander van Heukelum	static const char str[] = "double fault";
244081f75bbdc86de53537e1b5aca01de72bd2fea6bAlexander van Heukelum	struct task_struct *tsk = current;
245081f75bbdc86de53537e1b5aca01de72bd2fea6bAlexander van Heukelum
246af726f21ed8af2cdaa4e93098dc211521218ae65Andy Lutomirski#ifdef CONFIG_X86_ESPFIX64
247af726f21ed8af2cdaa4e93098dc211521218ae65Andy Lutomirski	extern unsigned char native_irq_return_iret[];
248af726f21ed8af2cdaa4e93098dc211521218ae65Andy Lutomirski
249af726f21ed8af2cdaa4e93098dc211521218ae65Andy Lutomirski	/*
250af726f21ed8af2cdaa4e93098dc211521218ae65Andy Lutomirski	 * If IRET takes a non-IST fault on the espfix64 stack, then we
251af726f21ed8af2cdaa4e93098dc211521218ae65Andy Lutomirski	 * end up promoting it to a doublefault.  In that case, modify
252af726f21ed8af2cdaa4e93098dc211521218ae65Andy Lutomirski	 * the stack to make it look like we just entered the #GP
253af726f21ed8af2cdaa4e93098dc211521218ae65Andy Lutomirski	 * handler from user space, similar to bad_iret.
254af726f21ed8af2cdaa4e93098dc211521218ae65Andy Lutomirski	 */
255af726f21ed8af2cdaa4e93098dc211521218ae65Andy Lutomirski	if (((long)regs->sp >> PGDIR_SHIFT) == ESPFIX_PGD_ENTRY &&
256af726f21ed8af2cdaa4e93098dc211521218ae65Andy Lutomirski		regs->cs == __KERNEL_CS &&
257af726f21ed8af2cdaa4e93098dc211521218ae65Andy Lutomirski		regs->ip == (unsigned long)native_irq_return_iret)
258af726f21ed8af2cdaa4e93098dc211521218ae65Andy Lutomirski	{
259af726f21ed8af2cdaa4e93098dc211521218ae65Andy Lutomirski		struct pt_regs *normal_regs = task_pt_regs(current);
260af726f21ed8af2cdaa4e93098dc211521218ae65Andy Lutomirski
261af726f21ed8af2cdaa4e93098dc211521218ae65Andy Lutomirski		/* Fake a #GP(0) from userspace. */
262af726f21ed8af2cdaa4e93098dc211521218ae65Andy Lutomirski		memmove(&normal_regs->ip, (void *)regs->sp, 5*8);
263af726f21ed8af2cdaa4e93098dc211521218ae65Andy Lutomirski		normal_regs->orig_ax = 0;  /* Missing (lost) #GP error code */
264af726f21ed8af2cdaa4e93098dc211521218ae65Andy Lutomirski		regs->ip = (unsigned long)general_protection;
265af726f21ed8af2cdaa4e93098dc211521218ae65Andy Lutomirski		regs->sp = (unsigned long)&normal_regs->orig_ax;
266af726f21ed8af2cdaa4e93098dc211521218ae65Andy Lutomirski		return;
267af726f21ed8af2cdaa4e93098dc211521218ae65Andy Lutomirski	}
268af726f21ed8af2cdaa4e93098dc211521218ae65Andy Lutomirski#endif
269af726f21ed8af2cdaa4e93098dc211521218ae65Andy Lutomirski
2706c1e0256fad84a843d915414e4b5973b7443d48dFrederic Weisbecker	exception_enter();
271081f75bbdc86de53537e1b5aca01de72bd2fea6bAlexander van Heukelum	/* Return not checked because double check cannot be ignored */
272c94082656dac74257f63e91f78d5d458ac781fa5Kees Cook	notify_die(DIE_TRAP, str, regs, error_code, X86_TRAP_DF, SIGSEGV);
273081f75bbdc86de53537e1b5aca01de72bd2fea6bAlexander van Heukelum
274081f75bbdc86de53537e1b5aca01de72bd2fea6bAlexander van Heukelum	tsk->thread.error_code = error_code;
27551e7dc7011c99e1e5294658c7b551b92ca069985Srikar Dronamraju	tsk->thread.trap_nr = X86_TRAP_DF;
276081f75bbdc86de53537e1b5aca01de72bd2fea6bAlexander van Heukelum
2774d067d8e056d76a3327f0517c7722db55e7888fcBorislav Petkov#ifdef CONFIG_DOUBLEFAULT
2784d067d8e056d76a3327f0517c7722db55e7888fcBorislav Petkov	df_debug(regs, error_code);
2794d067d8e056d76a3327f0517c7722db55e7888fcBorislav Petkov#endif
280bd8b96dfc216eebc72950a6c40da8d3eca8667dfIngo Molnar	/*
281bd8b96dfc216eebc72950a6c40da8d3eca8667dfIngo Molnar	 * This is always a kernel trap and never fixable (and thus must
282bd8b96dfc216eebc72950a6c40da8d3eca8667dfIngo Molnar	 * never return).
283bd8b96dfc216eebc72950a6c40da8d3eca8667dfIngo Molnar	 */
284081f75bbdc86de53537e1b5aca01de72bd2fea6bAlexander van Heukelum	for (;;)
285081f75bbdc86de53537e1b5aca01de72bd2fea6bAlexander van Heukelum		die(str, regs, error_code);
286081f75bbdc86de53537e1b5aca01de72bd2fea6bAlexander van Heukelum}
287081f75bbdc86de53537e1b5aca01de72bd2fea6bAlexander van Heukelum#endif
288081f75bbdc86de53537e1b5aca01de72bd2fea6bAlexander van Heukelum
2899326638cbee2d36b051ed2a69f3e4e107e5f86bdMasami Hiramatsudotraplinkage void
29013485ab55bc77f02024e80bcca0374950b0becb3Alexander van Heukelumdo_general_protection(struct pt_regs *regs, long error_code)
2911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
29213485ab55bc77f02024e80bcca0374950b0becb3Alexander van Heukelum	struct task_struct *tsk;
2936c1e0256fad84a843d915414e4b5973b7443d48dFrederic Weisbecker	enum ctx_state prev_state;
294b5964405fbc4fd4c57e0e1f86bc9f1b3dbfa040aIngo Molnar
2956c1e0256fad84a843d915414e4b5973b7443d48dFrederic Weisbecker	prev_state = exception_enter();
296c6df0d71bec391e78e0a38109d63154acd69a937Alexander van Heukelum	conditional_sti(regs);
297c6df0d71bec391e78e0a38109d63154acd69a937Alexander van Heukelum
298081f75bbdc86de53537e1b5aca01de72bd2fea6bAlexander van Heukelum#ifdef CONFIG_X86_32
299ef3f628872c838933a279d0d7e63e707783c9710Frederic Weisbecker	if (regs->flags & X86_VM_MASK) {
300ef3f628872c838933a279d0d7e63e707783c9710Frederic Weisbecker		local_irq_enable();
301ef3f628872c838933a279d0d7e63e707783c9710Frederic Weisbecker		handle_vm86_fault((struct kernel_vm86_regs *) regs, error_code);
3026ba3c97a38803883c2eee489505796cb0a727122Frederic Weisbecker		goto exit;
303ef3f628872c838933a279d0d7e63e707783c9710Frederic Weisbecker	}
304081f75bbdc86de53537e1b5aca01de72bd2fea6bAlexander van Heukelum#endif
3051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
30613485ab55bc77f02024e80bcca0374950b0becb3Alexander van Heukelum	tsk = current;
307ef3f628872c838933a279d0d7e63e707783c9710Frederic Weisbecker	if (!user_mode(regs)) {
308ef3f628872c838933a279d0d7e63e707783c9710Frederic Weisbecker		if (fixup_exception(regs))
3096ba3c97a38803883c2eee489505796cb0a727122Frederic Weisbecker			goto exit;
310ef3f628872c838933a279d0d7e63e707783c9710Frederic Weisbecker
311ef3f628872c838933a279d0d7e63e707783c9710Frederic Weisbecker		tsk->thread.error_code = error_code;
312ef3f628872c838933a279d0d7e63e707783c9710Frederic Weisbecker		tsk->thread.trap_nr = X86_TRAP_GP;
3136ba3c97a38803883c2eee489505796cb0a727122Frederic Weisbecker		if (notify_die(DIE_GPF, "general protection fault", regs, error_code,
3146ba3c97a38803883c2eee489505796cb0a727122Frederic Weisbecker			       X86_TRAP_GP, SIGSEGV) != NOTIFY_STOP)
315ef3f628872c838933a279d0d7e63e707783c9710Frederic Weisbecker			die("general protection fault", regs, error_code);
3166ba3c97a38803883c2eee489505796cb0a727122Frederic Weisbecker		goto exit;
317ef3f628872c838933a279d0d7e63e707783c9710Frederic Weisbecker	}
3181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
31913485ab55bc77f02024e80bcca0374950b0becb3Alexander van Heukelum	tsk->thread.error_code = error_code;
32051e7dc7011c99e1e5294658c7b551b92ca069985Srikar Dronamraju	tsk->thread.trap_nr = X86_TRAP_GP;
321b5964405fbc4fd4c57e0e1f86bc9f1b3dbfa040aIngo Molnar
32213485ab55bc77f02024e80bcca0374950b0becb3Alexander van Heukelum	if (show_unhandled_signals && unhandled_signal(tsk, SIGSEGV) &&
32313485ab55bc77f02024e80bcca0374950b0becb3Alexander van Heukelum			printk_ratelimit()) {
324c767a54ba0657e52e6edaa97cbe0b0a8bf1c1655Joe Perches		pr_info("%s[%d] general protection ip:%lx sp:%lx error:%lx",
32513485ab55bc77f02024e80bcca0374950b0becb3Alexander van Heukelum			tsk->comm, task_pid_nr(tsk),
32613485ab55bc77f02024e80bcca0374950b0becb3Alexander van Heukelum			regs->ip, regs->sp, error_code);
32703252919b79891063cf99145612360efbdf9500bAndi Kleen		print_vma_addr(" in ", regs->ip);
328c767a54ba0657e52e6edaa97cbe0b0a8bf1c1655Joe Perches		pr_cont("\n");
32903252919b79891063cf99145612360efbdf9500bAndi Kleen	}
330abd4f7505bafdd6c5319fe3cb5caf9af6104e17aMasoud Asgharifard Sharbiani
33138cad57be9800e46c52a3612fb9d963eee4fd9c3Oleg Nesterov	force_sig_info(SIGSEGV, SEND_SIG_PRIV, tsk);
3326ba3c97a38803883c2eee489505796cb0a727122Frederic Weisbeckerexit:
3336c1e0256fad84a843d915414e4b5973b7443d48dFrederic Weisbecker	exception_exit(prev_state);
3341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
3359326638cbee2d36b051ed2a69f3e4e107e5f86bdMasami HiramatsuNOKPROBE_SYMBOL(do_general_protection);
3361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
337c1d518c8422ff7d3f377958771b265753028579cAlexander van Heukelum/* May run on IST stack. */
3389326638cbee2d36b051ed2a69f3e4e107e5f86bdMasami Hiramatsudotraplinkage void notrace do_int3(struct pt_regs *regs, long error_code)
3391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
3406c1e0256fad84a843d915414e4b5973b7443d48dFrederic Weisbecker	enum ctx_state prev_state;
3416c1e0256fad84a843d915414e4b5973b7443d48dFrederic Weisbecker
34208d636b6d4fb80647fe8869ea1cd97b2c26a4751Steven Rostedt#ifdef CONFIG_DYNAMIC_FTRACE
343a192cd0413b71c2a3e4e48dd365af704be72b748Steven Rostedt	/*
344a192cd0413b71c2a3e4e48dd365af704be72b748Steven Rostedt	 * ftrace must be first, everything else may cause a recursive crash.
345a192cd0413b71c2a3e4e48dd365af704be72b748Steven Rostedt	 * See note by declaration of modifying_ftrace_code in ftrace.c
346a192cd0413b71c2a3e4e48dd365af704be72b748Steven Rostedt	 */
347a192cd0413b71c2a3e4e48dd365af704be72b748Steven Rostedt	if (unlikely(atomic_read(&modifying_ftrace_code)) &&
348a192cd0413b71c2a3e4e48dd365af704be72b748Steven Rostedt	    ftrace_int3_handler(regs))
34908d636b6d4fb80647fe8869ea1cd97b2c26a4751Steven Rostedt		return;
35008d636b6d4fb80647fe8869ea1cd97b2c26a4751Steven Rostedt#endif
35117f41571bb2c4a398785452ac2718a6c5d77180eJiri Kosina	if (poke_int3_handler(regs))
35217f41571bb2c4a398785452ac2718a6c5d77180eJiri Kosina		return;
35317f41571bb2c4a398785452ac2718a6c5d77180eJiri Kosina
3544cdf77a828b056258f48a9f6078bd2f77d9704bbMasami Hiramatsu	prev_state = exception_enter();
355f503b5ae53cb557ac351a668fcac1baab1cef0dbJason Wessel#ifdef CONFIG_KGDB_LOW_LEVEL_TRAP
356c94082656dac74257f63e91f78d5d458ac781fa5Kees Cook	if (kgdb_ll_trap(DIE_INT3, "int3", regs, error_code, X86_TRAP_BP,
357c94082656dac74257f63e91f78d5d458ac781fa5Kees Cook				SIGTRAP) == NOTIFY_STOP)
3586ba3c97a38803883c2eee489505796cb0a727122Frederic Weisbecker		goto exit;
359f503b5ae53cb557ac351a668fcac1baab1cef0dbJason Wessel#endif /* CONFIG_KGDB_LOW_LEVEL_TRAP */
360cc3a1bf52a9d2808c7cd6e8f413b02b650b6b84bSrikar Dronamraju
3616f6343f53d133bae516caf3d254bce37d8774625Masami Hiramatsu#ifdef CONFIG_KPROBES
3626f6343f53d133bae516caf3d254bce37d8774625Masami Hiramatsu	if (kprobe_int3_handler(regs))
3634cdf77a828b056258f48a9f6078bd2f77d9704bbMasami Hiramatsu		goto exit;
3646f6343f53d133bae516caf3d254bce37d8774625Masami Hiramatsu#endif
3656f6343f53d133bae516caf3d254bce37d8774625Masami Hiramatsu
366c94082656dac74257f63e91f78d5d458ac781fa5Kees Cook	if (notify_die(DIE_INT3, "int3", regs, error_code, X86_TRAP_BP,
367c94082656dac74257f63e91f78d5d458ac781fa5Kees Cook			SIGTRAP) == NOTIFY_STOP)
3686ba3c97a38803883c2eee489505796cb0a727122Frederic Weisbecker		goto exit;
369b5964405fbc4fd4c57e0e1f86bc9f1b3dbfa040aIngo Molnar
37042181186ad4db986fcaa40ca95c6e407e9e79372Steven Rostedt	/*
37142181186ad4db986fcaa40ca95c6e407e9e79372Steven Rostedt	 * Let others (NMI) know that the debug stack is in use
37242181186ad4db986fcaa40ca95c6e407e9e79372Steven Rostedt	 * as we may switch to the interrupt stack.
37342181186ad4db986fcaa40ca95c6e407e9e79372Steven Rostedt	 */
37442181186ad4db986fcaa40ca95c6e407e9e79372Steven Rostedt	debug_stack_usage_inc();
3754915a35e35a037254550a2ba9f367a812bc37d40Alexander van Heukelum	preempt_conditional_sti(regs);
376c94082656dac74257f63e91f78d5d458ac781fa5Kees Cook	do_trap(X86_TRAP_BP, SIGTRAP, "int3", regs, error_code, NULL);
3774915a35e35a037254550a2ba9f367a812bc37d40Alexander van Heukelum	preempt_conditional_cli(regs);
37842181186ad4db986fcaa40ca95c6e407e9e79372Steven Rostedt	debug_stack_usage_dec();
3796ba3c97a38803883c2eee489505796cb0a727122Frederic Weisbeckerexit:
3806c1e0256fad84a843d915414e4b5973b7443d48dFrederic Weisbecker	exception_exit(prev_state);
3811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
3829326638cbee2d36b051ed2a69f3e4e107e5f86bdMasami HiramatsuNOKPROBE_SYMBOL(do_int3);
3831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
384081f75bbdc86de53537e1b5aca01de72bd2fea6bAlexander van Heukelum#ifdef CONFIG_X86_64
385bd8b96dfc216eebc72950a6c40da8d3eca8667dfIngo Molnar/*
386bd8b96dfc216eebc72950a6c40da8d3eca8667dfIngo Molnar * Help handler running on IST stack to switch back to user stack
387bd8b96dfc216eebc72950a6c40da8d3eca8667dfIngo Molnar * for scheduling or signal handling. The actual stack switch is done in
388bd8b96dfc216eebc72950a6c40da8d3eca8667dfIngo Molnar * entry.S
389bd8b96dfc216eebc72950a6c40da8d3eca8667dfIngo Molnar */
390ec00010972a0971b2c1da4fbe4e5c7d8ed1ecb05Ingo Molnarasmlinkage __visible struct pt_regs *sync_regs(struct pt_regs *eregs)
391081f75bbdc86de53537e1b5aca01de72bd2fea6bAlexander van Heukelum{
392081f75bbdc86de53537e1b5aca01de72bd2fea6bAlexander van Heukelum	struct pt_regs *regs = eregs;
393081f75bbdc86de53537e1b5aca01de72bd2fea6bAlexander van Heukelum	/* Did already sync */
394081f75bbdc86de53537e1b5aca01de72bd2fea6bAlexander van Heukelum	if (eregs == (struct pt_regs *)eregs->sp)
395081f75bbdc86de53537e1b5aca01de72bd2fea6bAlexander van Heukelum		;
396081f75bbdc86de53537e1b5aca01de72bd2fea6bAlexander van Heukelum	/* Exception from user space */
397081f75bbdc86de53537e1b5aca01de72bd2fea6bAlexander van Heukelum	else if (user_mode(eregs))
398081f75bbdc86de53537e1b5aca01de72bd2fea6bAlexander van Heukelum		regs = task_pt_regs(current);
399bd8b96dfc216eebc72950a6c40da8d3eca8667dfIngo Molnar	/*
400bd8b96dfc216eebc72950a6c40da8d3eca8667dfIngo Molnar	 * Exception from kernel and interrupts are enabled. Move to
401bd8b96dfc216eebc72950a6c40da8d3eca8667dfIngo Molnar	 * kernel process stack.
402bd8b96dfc216eebc72950a6c40da8d3eca8667dfIngo Molnar	 */
403081f75bbdc86de53537e1b5aca01de72bd2fea6bAlexander van Heukelum	else if (eregs->flags & X86_EFLAGS_IF)
404081f75bbdc86de53537e1b5aca01de72bd2fea6bAlexander van Heukelum		regs = (struct pt_regs *)(eregs->sp -= sizeof(struct pt_regs));
405081f75bbdc86de53537e1b5aca01de72bd2fea6bAlexander van Heukelum	if (eregs != regs)
406081f75bbdc86de53537e1b5aca01de72bd2fea6bAlexander van Heukelum		*regs = *eregs;
407081f75bbdc86de53537e1b5aca01de72bd2fea6bAlexander van Heukelum	return regs;
408081f75bbdc86de53537e1b5aca01de72bd2fea6bAlexander van Heukelum}
4099326638cbee2d36b051ed2a69f3e4e107e5f86bdMasami HiramatsuNOKPROBE_SYMBOL(sync_regs);
410b645af2d5905c4e32399005b867987919cbfc3aeAndy Lutomirski
411b645af2d5905c4e32399005b867987919cbfc3aeAndy Lutomirskistruct bad_iret_stack {
412b645af2d5905c4e32399005b867987919cbfc3aeAndy Lutomirski	void *error_entry_ret;
413b645af2d5905c4e32399005b867987919cbfc3aeAndy Lutomirski	struct pt_regs regs;
414b645af2d5905c4e32399005b867987919cbfc3aeAndy Lutomirski};
415b645af2d5905c4e32399005b867987919cbfc3aeAndy Lutomirski
416b645af2d5905c4e32399005b867987919cbfc3aeAndy Lutomirskiasmlinkage __visible
417b645af2d5905c4e32399005b867987919cbfc3aeAndy Lutomirskistruct bad_iret_stack *fixup_bad_iret(struct bad_iret_stack *s)
418b645af2d5905c4e32399005b867987919cbfc3aeAndy Lutomirski{
419b645af2d5905c4e32399005b867987919cbfc3aeAndy Lutomirski	/*
420b645af2d5905c4e32399005b867987919cbfc3aeAndy Lutomirski	 * This is called from entry_64.S early in handling a fault
421b645af2d5905c4e32399005b867987919cbfc3aeAndy Lutomirski	 * caused by a bad iret to user mode.  To handle the fault
422b645af2d5905c4e32399005b867987919cbfc3aeAndy Lutomirski	 * correctly, we want move our stack frame to task_pt_regs
423b645af2d5905c4e32399005b867987919cbfc3aeAndy Lutomirski	 * and we want to pretend that the exception came from the
424b645af2d5905c4e32399005b867987919cbfc3aeAndy Lutomirski	 * iret target.
425b645af2d5905c4e32399005b867987919cbfc3aeAndy Lutomirski	 */
426b645af2d5905c4e32399005b867987919cbfc3aeAndy Lutomirski	struct bad_iret_stack *new_stack =
427b645af2d5905c4e32399005b867987919cbfc3aeAndy Lutomirski		container_of(task_pt_regs(current),
428b645af2d5905c4e32399005b867987919cbfc3aeAndy Lutomirski			     struct bad_iret_stack, regs);
429b645af2d5905c4e32399005b867987919cbfc3aeAndy Lutomirski
430b645af2d5905c4e32399005b867987919cbfc3aeAndy Lutomirski	/* Copy the IRET target to the new stack. */
431b645af2d5905c4e32399005b867987919cbfc3aeAndy Lutomirski	memmove(&new_stack->regs.ip, (void *)s->regs.sp, 5*8);
432b645af2d5905c4e32399005b867987919cbfc3aeAndy Lutomirski
433b645af2d5905c4e32399005b867987919cbfc3aeAndy Lutomirski	/* Copy the remainder of the stack from the current stack. */
434b645af2d5905c4e32399005b867987919cbfc3aeAndy Lutomirski	memmove(new_stack, s, offsetof(struct bad_iret_stack, regs.ip));
435b645af2d5905c4e32399005b867987919cbfc3aeAndy Lutomirski
436b645af2d5905c4e32399005b867987919cbfc3aeAndy Lutomirski	BUG_ON(!user_mode_vm(&new_stack->regs));
437b645af2d5905c4e32399005b867987919cbfc3aeAndy Lutomirski	return new_stack;
438b645af2d5905c4e32399005b867987919cbfc3aeAndy Lutomirski}
439081f75bbdc86de53537e1b5aca01de72bd2fea6bAlexander van Heukelum#endif
440081f75bbdc86de53537e1b5aca01de72bd2fea6bAlexander van Heukelum
4411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
4421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Our handling of the processor debug registers is non-trivial.
4431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * We do not clear them on entry and exit from the kernel. Therefore
4441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * it is possible to get a watchpoint trap here from inside the kernel.
4451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * However, the code in ./ptrace.c has ensured that the user can
4461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * only set watchpoints on userspace addresses. Therefore the in-kernel
4471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * watchpoint trap can only occur in code which is reading/writing
4481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * from user space. Such code must not hold kernel locks (since it
4491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * can equally take a page fault), therefore it is safe to call
4501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * force_sig_info even though that claims and releases locks.
451b5964405fbc4fd4c57e0e1f86bc9f1b3dbfa040aIngo Molnar *
4521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Code in ./signal.c ensures that the debug control register
4531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * is restored before we deliver any signal, and therefore that
4541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * user code runs with the correct debug control register even though
4551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * we clear it here.
4561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
4571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Being careful here means that we don't have to be as careful in a
4581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * lot of more complicated places (task switching can be a bit lazy
4591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * about restoring all the debug state, and ptrace doesn't have to
4601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * find every occurrence of the TF bit that could be saved away even
4611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * by user code)
462c1d518c8422ff7d3f377958771b265753028579cAlexander van Heukelum *
463c1d518c8422ff7d3f377958771b265753028579cAlexander van Heukelum * May run on IST stack.
4641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
4659326638cbee2d36b051ed2a69f3e4e107e5f86bdMasami Hiramatsudotraplinkage void do_debug(struct pt_regs *regs, long error_code)
4661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
4671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct task_struct *tsk = current;
4686c1e0256fad84a843d915414e4b5973b7443d48dFrederic Weisbecker	enum ctx_state prev_state;
469a1e80fafc9f0742a1776a0490258cb64912411b0Frederic Weisbecker	int user_icebp = 0;
47008d68323d1f0c34452e614263b212ca556dae47fK.Prasad	unsigned long dr6;
471da654b74bda14c45a7d98c731bf3c1a43b6b74e2Srinivasa Ds	int si_code;
4721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4734cdf77a828b056258f48a9f6078bd2f77d9704bbMasami Hiramatsu	prev_state = exception_enter();
4744cdf77a828b056258f48a9f6078bd2f77d9704bbMasami Hiramatsu
47508d68323d1f0c34452e614263b212ca556dae47fK.Prasad	get_debugreg(dr6, 6);
4761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
47740f9249a73f6c251adea492b1c3d19d39e2a9bdaK.Prasad	/* Filter out all the reserved bits which are preset to 1 */
47840f9249a73f6c251adea492b1c3d19d39e2a9bdaK.Prasad	dr6 &= ~DR6_RESERVED;
47940f9249a73f6c251adea492b1c3d19d39e2a9bdaK.Prasad
480a1e80fafc9f0742a1776a0490258cb64912411b0Frederic Weisbecker	/*
481a1e80fafc9f0742a1776a0490258cb64912411b0Frederic Weisbecker	 * If dr6 has no reason to give us about the origin of this trap,
482a1e80fafc9f0742a1776a0490258cb64912411b0Frederic Weisbecker	 * then it's very likely the result of an icebp/int01 trap.
483a1e80fafc9f0742a1776a0490258cb64912411b0Frederic Weisbecker	 * User wants a sigtrap for that.
484a1e80fafc9f0742a1776a0490258cb64912411b0Frederic Weisbecker	 */
485a1e80fafc9f0742a1776a0490258cb64912411b0Frederic Weisbecker	if (!dr6 && user_mode(regs))
486a1e80fafc9f0742a1776a0490258cb64912411b0Frederic Weisbecker		user_icebp = 1;
487a1e80fafc9f0742a1776a0490258cb64912411b0Frederic Weisbecker
488f85612967c93b67b10dd240e3e8bf8a0eee9def7Vegard Nossum	/* Catch kmemcheck conditions first of all! */
489eadb8a091b27a840de7450f84ecff5ef13476424Ingo Molnar	if ((dr6 & DR_STEP) && kmemcheck_trap(regs))
4906ba3c97a38803883c2eee489505796cb0a727122Frederic Weisbecker		goto exit;
491f85612967c93b67b10dd240e3e8bf8a0eee9def7Vegard Nossum
49208d68323d1f0c34452e614263b212ca556dae47fK.Prasad	/* DR6 may or may not be cleared by the CPU */
49308d68323d1f0c34452e614263b212ca556dae47fK.Prasad	set_debugreg(0, 6);
49410faa81e102e2b7695f386812055cd2ef9e44b4cRoland McGrath
495ea8e61b7bbc4a2faef77db34eb2db2a2c2372ff6Peter Zijlstra	/*
496ea8e61b7bbc4a2faef77db34eb2db2a2c2372ff6Peter Zijlstra	 * The processor cleared BTF, so don't mark that we need it set.
497ea8e61b7bbc4a2faef77db34eb2db2a2c2372ff6Peter Zijlstra	 */
498ea8e61b7bbc4a2faef77db34eb2db2a2c2372ff6Peter Zijlstra	clear_tsk_thread_flag(tsk, TIF_BLOCKSTEP);
499ea8e61b7bbc4a2faef77db34eb2db2a2c2372ff6Peter Zijlstra
50008d68323d1f0c34452e614263b212ca556dae47fK.Prasad	/* Store the virtualized DR6 value */
50108d68323d1f0c34452e614263b212ca556dae47fK.Prasad	tsk->thread.debugreg6 = dr6;
50208d68323d1f0c34452e614263b212ca556dae47fK.Prasad
5036f6343f53d133bae516caf3d254bce37d8774625Masami Hiramatsu#ifdef CONFIG_KPROBES
5046f6343f53d133bae516caf3d254bce37d8774625Masami Hiramatsu	if (kprobe_debug_handler(regs))
5056f6343f53d133bae516caf3d254bce37d8774625Masami Hiramatsu		goto exit;
5066f6343f53d133bae516caf3d254bce37d8774625Masami Hiramatsu#endif
5076f6343f53d133bae516caf3d254bce37d8774625Masami Hiramatsu
5085a802e15308f152247433d87050d1bfbf9613483Rusty Russell	if (notify_die(DIE_DEBUG, "debug", regs, (long)&dr6, error_code,
50962edab9056a6cf0c9207339c8892c923a5217e45K.Prasad							SIGTRAP) == NOTIFY_STOP)
5106ba3c97a38803883c2eee489505796cb0a727122Frederic Weisbecker		goto exit;
5113d2a71a596bd9c761c8487a2178e95f8a61da083Alexander van Heukelum
51242181186ad4db986fcaa40ca95c6e407e9e79372Steven Rostedt	/*
51342181186ad4db986fcaa40ca95c6e407e9e79372Steven Rostedt	 * Let others (NMI) know that the debug stack is in use
51442181186ad4db986fcaa40ca95c6e407e9e79372Steven Rostedt	 * as we may switch to the interrupt stack.
51542181186ad4db986fcaa40ca95c6e407e9e79372Steven Rostedt	 */
51642181186ad4db986fcaa40ca95c6e407e9e79372Steven Rostedt	debug_stack_usage_inc();
51742181186ad4db986fcaa40ca95c6e407e9e79372Steven Rostedt
5181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* It's safe to allow irq's after DR6 has been saved */
5193d2a71a596bd9c761c8487a2178e95f8a61da083Alexander van Heukelum	preempt_conditional_sti(regs);
5201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
52108d68323d1f0c34452e614263b212ca556dae47fK.Prasad	if (regs->flags & X86_VM_MASK) {
522c94082656dac74257f63e91f78d5d458ac781fa5Kees Cook		handle_vm86_trap((struct kernel_vm86_regs *) regs, error_code,
523c94082656dac74257f63e91f78d5d458ac781fa5Kees Cook					X86_TRAP_DB);
5246554287b1de0448f1e02e200d02b43914e997d15Bart Oldeman		preempt_conditional_cli(regs);
52542181186ad4db986fcaa40ca95c6e407e9e79372Steven Rostedt		debug_stack_usage_dec();
5266ba3c97a38803883c2eee489505796cb0a727122Frederic Weisbecker		goto exit;
5271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
5281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/*
53008d68323d1f0c34452e614263b212ca556dae47fK.Prasad	 * Single-stepping through system calls: ignore any exceptions in
53108d68323d1f0c34452e614263b212ca556dae47fK.Prasad	 * kernel space, but re-enable TF when returning to user mode.
53208d68323d1f0c34452e614263b212ca556dae47fK.Prasad	 *
53308d68323d1f0c34452e614263b212ca556dae47fK.Prasad	 * We already checked v86 mode above, so we can check for kernel mode
53408d68323d1f0c34452e614263b212ca556dae47fK.Prasad	 * by just checking the CPL of CS.
5351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 */
53608d68323d1f0c34452e614263b212ca556dae47fK.Prasad	if ((dr6 & DR_STEP) && !user_mode(regs)) {
53708d68323d1f0c34452e614263b212ca556dae47fK.Prasad		tsk->thread.debugreg6 &= ~DR_STEP;
53808d68323d1f0c34452e614263b212ca556dae47fK.Prasad		set_tsk_thread_flag(tsk, TIF_SINGLESTEP);
53908d68323d1f0c34452e614263b212ca556dae47fK.Prasad		regs->flags &= ~X86_EFLAGS_TF;
5401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
54108d68323d1f0c34452e614263b212ca556dae47fK.Prasad	si_code = get_si_code(tsk->thread.debugreg6);
542a1e80fafc9f0742a1776a0490258cb64912411b0Frederic Weisbecker	if (tsk->thread.debugreg6 & (DR_STEP | DR_TRAP_BITS) || user_icebp)
54308d68323d1f0c34452e614263b212ca556dae47fK.Prasad		send_sigtrap(tsk, regs, error_code, si_code);
5443d2a71a596bd9c761c8487a2178e95f8a61da083Alexander van Heukelum	preempt_conditional_cli(regs);
54542181186ad4db986fcaa40ca95c6e407e9e79372Steven Rostedt	debug_stack_usage_dec();
5461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5476ba3c97a38803883c2eee489505796cb0a727122Frederic Weisbeckerexit:
5486c1e0256fad84a843d915414e4b5973b7443d48dFrederic Weisbecker	exception_exit(prev_state);
5491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
5509326638cbee2d36b051ed2a69f3e4e107e5f86bdMasami HiramatsuNOKPROBE_SYMBOL(do_debug);
5511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
5531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Note that we play around with the 'TS' bit in an attempt to get
5541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * the correct behaviour even in the presence of the asynchronous
5551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * IRQ13 behaviour
5561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
5575e1b05beeca8139204324581a5b1ffb53d057f96Oleg Nesterovstatic void math_error(struct pt_regs *regs, int error_code, int trapnr)
5581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
559e2e75c915de045f0785387dc32f55e92fab0614cBrian Gerst	struct task_struct *task = current;
5601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	siginfo_t info;
5619b6dba9e0798325dab427b9d60c61630ccc39b28Brian Gerst	unsigned short err;
562c94082656dac74257f63e91f78d5d458ac781fa5Kees Cook	char *str = (trapnr == X86_TRAP_MF) ? "fpu exception" :
563c94082656dac74257f63e91f78d5d458ac781fa5Kees Cook						"simd exception";
564e2e75c915de045f0785387dc32f55e92fab0614cBrian Gerst
565e2e75c915de045f0785387dc32f55e92fab0614cBrian Gerst	if (notify_die(DIE_TRAP, str, regs, error_code, trapnr, SIGFPE) == NOTIFY_STOP)
566e2e75c915de045f0785387dc32f55e92fab0614cBrian Gerst		return;
567e2e75c915de045f0785387dc32f55e92fab0614cBrian Gerst	conditional_sti(regs);
568e2e75c915de045f0785387dc32f55e92fab0614cBrian Gerst
569e2e75c915de045f0785387dc32f55e92fab0614cBrian Gerst	if (!user_mode_vm(regs))
570e2e75c915de045f0785387dc32f55e92fab0614cBrian Gerst	{
571e2e75c915de045f0785387dc32f55e92fab0614cBrian Gerst		if (!fixup_exception(regs)) {
572e2e75c915de045f0785387dc32f55e92fab0614cBrian Gerst			task->thread.error_code = error_code;
57351e7dc7011c99e1e5294658c7b551b92ca069985Srikar Dronamraju			task->thread.trap_nr = trapnr;
574e2e75c915de045f0785387dc32f55e92fab0614cBrian Gerst			die(str, regs, error_code);
575e2e75c915de045f0785387dc32f55e92fab0614cBrian Gerst		}
576e2e75c915de045f0785387dc32f55e92fab0614cBrian Gerst		return;
577e2e75c915de045f0785387dc32f55e92fab0614cBrian Gerst	}
5781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/*
5801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * Save the info for the exception handler and clear the error.
5811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 */
5821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	save_init_fpu(task);
58351e7dc7011c99e1e5294658c7b551b92ca069985Srikar Dronamraju	task->thread.trap_nr = trapnr;
5849b6dba9e0798325dab427b9d60c61630ccc39b28Brian Gerst	task->thread.error_code = error_code;
5851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	info.si_signo = SIGFPE;
5861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	info.si_errno = 0;
587b02ef20a9fba08948e643d3eec0efadf1da01a44Oleg Nesterov	info.si_addr = (void __user *)uprobe_get_trap_addr(regs);
588c94082656dac74257f63e91f78d5d458ac781fa5Kees Cook	if (trapnr == X86_TRAP_MF) {
5899b6dba9e0798325dab427b9d60c61630ccc39b28Brian Gerst		unsigned short cwd, swd;
5909b6dba9e0798325dab427b9d60c61630ccc39b28Brian Gerst		/*
5919b6dba9e0798325dab427b9d60c61630ccc39b28Brian Gerst		 * (~cwd & swd) will mask out exceptions that are not set to unmasked
5929b6dba9e0798325dab427b9d60c61630ccc39b28Brian Gerst		 * status.  0x3f is the exception bits in these regs, 0x200 is the
5939b6dba9e0798325dab427b9d60c61630ccc39b28Brian Gerst		 * C1 reg you need in case of a stack fault, 0x040 is the stack
5949b6dba9e0798325dab427b9d60c61630ccc39b28Brian Gerst		 * fault bit.  We should only be taking one exception at a time,
5959b6dba9e0798325dab427b9d60c61630ccc39b28Brian Gerst		 * so if this combination doesn't produce any single exception,
5969b6dba9e0798325dab427b9d60c61630ccc39b28Brian Gerst		 * then we have a bad program that isn't synchronizing its FPU usage
5979b6dba9e0798325dab427b9d60c61630ccc39b28Brian Gerst		 * and it will suffer the consequences since we won't be able to
5989b6dba9e0798325dab427b9d60c61630ccc39b28Brian Gerst		 * fully reproduce the context of the exception
5999b6dba9e0798325dab427b9d60c61630ccc39b28Brian Gerst		 */
6009b6dba9e0798325dab427b9d60c61630ccc39b28Brian Gerst		cwd = get_fpu_cwd(task);
6019b6dba9e0798325dab427b9d60c61630ccc39b28Brian Gerst		swd = get_fpu_swd(task);
602adf77bac052bb5bf0722b2ce2af9fefc5b2d2a71H. Peter Anvin
6039b6dba9e0798325dab427b9d60c61630ccc39b28Brian Gerst		err = swd & ~cwd;
6049b6dba9e0798325dab427b9d60c61630ccc39b28Brian Gerst	} else {
6059b6dba9e0798325dab427b9d60c61630ccc39b28Brian Gerst		/*
6069b6dba9e0798325dab427b9d60c61630ccc39b28Brian Gerst		 * The SIMD FPU exceptions are handled a little differently, as there
6079b6dba9e0798325dab427b9d60c61630ccc39b28Brian Gerst		 * is only a single status/control register.  Thus, to determine which
6089b6dba9e0798325dab427b9d60c61630ccc39b28Brian Gerst		 * unmasked exception was caught we must mask the exception mask bits
6099b6dba9e0798325dab427b9d60c61630ccc39b28Brian Gerst		 * at 0x1f80, and then use these to mask the exception bits at 0x3f.
6109b6dba9e0798325dab427b9d60c61630ccc39b28Brian Gerst		 */
6119b6dba9e0798325dab427b9d60c61630ccc39b28Brian Gerst		unsigned short mxcsr = get_fpu_mxcsr(task);
6129b6dba9e0798325dab427b9d60c61630ccc39b28Brian Gerst		err = ~(mxcsr >> 7) & mxcsr;
6139b6dba9e0798325dab427b9d60c61630ccc39b28Brian Gerst	}
614adf77bac052bb5bf0722b2ce2af9fefc5b2d2a71H. Peter Anvin
615adf77bac052bb5bf0722b2ce2af9fefc5b2d2a71H. Peter Anvin	if (err & 0x001) {	/* Invalid op */
616b5964405fbc4fd4c57e0e1f86bc9f1b3dbfa040aIngo Molnar		/*
617b5964405fbc4fd4c57e0e1f86bc9f1b3dbfa040aIngo Molnar		 * swd & 0x240 == 0x040: Stack Underflow
618b5964405fbc4fd4c57e0e1f86bc9f1b3dbfa040aIngo Molnar		 * swd & 0x240 == 0x240: Stack Overflow
619b5964405fbc4fd4c57e0e1f86bc9f1b3dbfa040aIngo Molnar		 * User must clear the SF bit (0x40) if set
620b5964405fbc4fd4c57e0e1f86bc9f1b3dbfa040aIngo Molnar		 */
621b5964405fbc4fd4c57e0e1f86bc9f1b3dbfa040aIngo Molnar		info.si_code = FPE_FLTINV;
622adf77bac052bb5bf0722b2ce2af9fefc5b2d2a71H. Peter Anvin	} else if (err & 0x004) { /* Divide by Zero */
623b5964405fbc4fd4c57e0e1f86bc9f1b3dbfa040aIngo Molnar		info.si_code = FPE_FLTDIV;
624adf77bac052bb5bf0722b2ce2af9fefc5b2d2a71H. Peter Anvin	} else if (err & 0x008) { /* Overflow */
625b5964405fbc4fd4c57e0e1f86bc9f1b3dbfa040aIngo Molnar		info.si_code = FPE_FLTOVF;
626adf77bac052bb5bf0722b2ce2af9fefc5b2d2a71H. Peter Anvin	} else if (err & 0x012) { /* Denormal, Underflow */
627adf77bac052bb5bf0722b2ce2af9fefc5b2d2a71H. Peter Anvin		info.si_code = FPE_FLTUND;
628adf77bac052bb5bf0722b2ce2af9fefc5b2d2a71H. Peter Anvin	} else if (err & 0x020) { /* Precision */
629b5964405fbc4fd4c57e0e1f86bc9f1b3dbfa040aIngo Molnar		info.si_code = FPE_FLTRES;
630adf77bac052bb5bf0722b2ce2af9fefc5b2d2a71H. Peter Anvin	} else {
631bd8b96dfc216eebc72950a6c40da8d3eca8667dfIngo Molnar		/*
632c94082656dac74257f63e91f78d5d458ac781fa5Kees Cook		 * If we're using IRQ 13, or supposedly even some trap
633c94082656dac74257f63e91f78d5d458ac781fa5Kees Cook		 * X86_TRAP_MF implementations, it's possible
634c94082656dac74257f63e91f78d5d458ac781fa5Kees Cook		 * we get a spurious trap, which is not an error.
635bd8b96dfc216eebc72950a6c40da8d3eca8667dfIngo Molnar		 */
636c94082656dac74257f63e91f78d5d458ac781fa5Kees Cook		return;
6371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
6381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	force_sig_info(SIGFPE, &info, task);
6391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
6401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
641e407d62088b7f61f38e1086062650c75a4f2757aAlexander van Heukelumdotraplinkage void do_coprocessor_error(struct pt_regs *regs, long error_code)
6421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
6436c1e0256fad84a843d915414e4b5973b7443d48dFrederic Weisbecker	enum ctx_state prev_state;
6446c1e0256fad84a843d915414e4b5973b7443d48dFrederic Weisbecker
6456c1e0256fad84a843d915414e4b5973b7443d48dFrederic Weisbecker	prev_state = exception_enter();
646c94082656dac74257f63e91f78d5d458ac781fa5Kees Cook	math_error(regs, error_code, X86_TRAP_MF);
6476c1e0256fad84a843d915414e4b5973b7443d48dFrederic Weisbecker	exception_exit(prev_state);
6481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
6491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
650e407d62088b7f61f38e1086062650c75a4f2757aAlexander van Heukelumdotraplinkage void
651e407d62088b7f61f38e1086062650c75a4f2757aAlexander van Heukelumdo_simd_coprocessor_error(struct pt_regs *regs, long error_code)
6521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
6536c1e0256fad84a843d915414e4b5973b7443d48dFrederic Weisbecker	enum ctx_state prev_state;
6546c1e0256fad84a843d915414e4b5973b7443d48dFrederic Weisbecker
6556c1e0256fad84a843d915414e4b5973b7443d48dFrederic Weisbecker	prev_state = exception_enter();
656c94082656dac74257f63e91f78d5d458ac781fa5Kees Cook	math_error(regs, error_code, X86_TRAP_XF);
6576c1e0256fad84a843d915414e4b5973b7443d48dFrederic Weisbecker	exception_exit(prev_state);
6581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
6591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
660e407d62088b7f61f38e1086062650c75a4f2757aAlexander van Heukelumdotraplinkage void
661e407d62088b7f61f38e1086062650c75a4f2757aAlexander van Heukelumdo_spurious_interrupt_bug(struct pt_regs *regs, long error_code)
6621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
663cf81978d5fb32ab75f701690b372e1126b41861fAlexander van Heukelum	conditional_sti(regs);
6641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#if 0
6651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* No need to warn about this any longer. */
666c767a54ba0657e52e6edaa97cbe0b0a8bf1c1655Joe Perches	pr_info("Ignoring P6 Local APIC Spurious Interrupt Bug...\n");
6671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif
6681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
6691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6702605fc216fa492f9e7c488bdc7f687cd6dcc703bAndi Kleenasmlinkage __visible void __attribute__((weak)) smp_thermal_interrupt(void)
6711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
6721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
6734efc0670baf4b14bc95502e54a83ccf639146125Andi Kleen
6742605fc216fa492f9e7c488bdc7f687cd6dcc703bAndi Kleenasmlinkage __visible void __attribute__((weak)) smp_threshold_interrupt(void)
675081f75bbdc86de53537e1b5aca01de72bd2fea6bAlexander van Heukelum{
676081f75bbdc86de53537e1b5aca01de72bd2fea6bAlexander van Heukelum}
677081f75bbdc86de53537e1b5aca01de72bd2fea6bAlexander van Heukelum
6781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
679b5964405fbc4fd4c57e0e1f86bc9f1b3dbfa040aIngo Molnar * 'math_state_restore()' saves the current math information in the
6801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * old math state array, and gets the new ones from the current task
6811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
6821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Careful.. There are problems with IBM-designed IRQ13 behaviour.
6831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Don't touch unless you *really* know how it works.
6841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
685be98c2cdb15ba26148cd2bd58a857d4f7759ed38Linus Torvalds * Must be called with kernel preemption disabled (eg with local
686be98c2cdb15ba26148cd2bd58a857d4f7759ed38Linus Torvalds * local interrupts as in the case of do_device_not_available).
6871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
688be98c2cdb15ba26148cd2bd58a857d4f7759ed38Linus Torvaldsvoid math_state_restore(void)
6891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
690f94edacf998516ac9d849f7bc6949a703977a7f3Linus Torvalds	struct task_struct *tsk = current;
6911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
692aa283f49276e7d840a40fb01eee6de97eaa7e012Suresh Siddha	if (!tsk_used_math(tsk)) {
693aa283f49276e7d840a40fb01eee6de97eaa7e012Suresh Siddha		local_irq_enable();
694aa283f49276e7d840a40fb01eee6de97eaa7e012Suresh Siddha		/*
695aa283f49276e7d840a40fb01eee6de97eaa7e012Suresh Siddha		 * does a slab alloc which can sleep
696aa283f49276e7d840a40fb01eee6de97eaa7e012Suresh Siddha		 */
697aa283f49276e7d840a40fb01eee6de97eaa7e012Suresh Siddha		if (init_fpu(tsk)) {
698aa283f49276e7d840a40fb01eee6de97eaa7e012Suresh Siddha			/*
699aa283f49276e7d840a40fb01eee6de97eaa7e012Suresh Siddha			 * ran out of memory!
700aa283f49276e7d840a40fb01eee6de97eaa7e012Suresh Siddha			 */
701aa283f49276e7d840a40fb01eee6de97eaa7e012Suresh Siddha			do_group_exit(SIGKILL);
702aa283f49276e7d840a40fb01eee6de97eaa7e012Suresh Siddha			return;
703aa283f49276e7d840a40fb01eee6de97eaa7e012Suresh Siddha		}
704aa283f49276e7d840a40fb01eee6de97eaa7e012Suresh Siddha		local_irq_disable();
705aa283f49276e7d840a40fb01eee6de97eaa7e012Suresh Siddha	}
706aa283f49276e7d840a40fb01eee6de97eaa7e012Suresh Siddha
707f94edacf998516ac9d849f7bc6949a703977a7f3Linus Torvalds	__thread_fpu_begin(tsk);
708304bceda6a18ae0b0240b8aac9a6bdf8ce2d2469Suresh Siddha
70980ab6f1e8c981b1b6604b2f22e36c917526235cdLinus Torvalds	/*
71080ab6f1e8c981b1b6604b2f22e36c917526235cdLinus Torvalds	 * Paranoid restore. send a SIGSEGV if we fail to restore the state.
71180ab6f1e8c981b1b6604b2f22e36c917526235cdLinus Torvalds	 */
71280ab6f1e8c981b1b6604b2f22e36c917526235cdLinus Torvalds	if (unlikely(restore_fpu_checking(tsk))) {
713304bceda6a18ae0b0240b8aac9a6bdf8ce2d2469Suresh Siddha		drop_init_fpu(tsk);
71438cad57be9800e46c52a3612fb9d963eee4fd9c3Oleg Nesterov		force_sig_info(SIGSEGV, SEND_SIG_PRIV, tsk);
71580ab6f1e8c981b1b6604b2f22e36c917526235cdLinus Torvalds		return;
71680ab6f1e8c981b1b6604b2f22e36c917526235cdLinus Torvalds	}
717b3b0870ef3ffed72b92415423da864f440f57ad6Linus Torvalds
718c375f15a434db1867cb004bafba92aba739e4e39Vineet Gupta	tsk->thread.fpu_counter++;
7191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
7205992b6dac0d23a2b51a1ccbaf8f1a2e62097b12bRusty RussellEXPORT_SYMBOL_GPL(math_state_restore);
7211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7229326638cbee2d36b051ed2a69f3e4e107e5f86bdMasami Hiramatsudotraplinkage void
723aa78bcfa01dec3cdbde3cda098ce32abbd9c3bf6Brian Gerstdo_device_not_available(struct pt_regs *regs, long error_code)
7247643e9b936b4af31ba4851eb7d5b3a3bfad52502Alexander van Heukelum{
7256c1e0256fad84a843d915414e4b5973b7443d48dFrederic Weisbecker	enum ctx_state prev_state;
7266c1e0256fad84a843d915414e4b5973b7443d48dFrederic Weisbecker
7276c1e0256fad84a843d915414e4b5973b7443d48dFrederic Weisbecker	prev_state = exception_enter();
7285d2bd7009f306c82afddd1ca4d9763ad8473c216Suresh Siddha	BUG_ON(use_eager_fpu());
729304bceda6a18ae0b0240b8aac9a6bdf8ce2d2469Suresh Siddha
730a334fe43d85f570ae907acf988a053c5eff78d6eBrian Gerst#ifdef CONFIG_MATH_EMULATION
7317643e9b936b4af31ba4851eb7d5b3a3bfad52502Alexander van Heukelum	if (read_cr0() & X86_CR0_EM) {
732d315760ffa261c15ff92699ac6f514112543d7caTejun Heo		struct math_emu_info info = { };
733d315760ffa261c15ff92699ac6f514112543d7caTejun Heo
7347643e9b936b4af31ba4851eb7d5b3a3bfad52502Alexander van Heukelum		conditional_sti(regs);
735d315760ffa261c15ff92699ac6f514112543d7caTejun Heo
736aa78bcfa01dec3cdbde3cda098ce32abbd9c3bf6Brian Gerst		info.regs = regs;
737d315760ffa261c15ff92699ac6f514112543d7caTejun Heo		math_emulate(&info);
7386c1e0256fad84a843d915414e4b5973b7443d48dFrederic Weisbecker		exception_exit(prev_state);
739a334fe43d85f570ae907acf988a053c5eff78d6eBrian Gerst		return;
7407643e9b936b4af31ba4851eb7d5b3a3bfad52502Alexander van Heukelum	}
741a334fe43d85f570ae907acf988a053c5eff78d6eBrian Gerst#endif
742a334fe43d85f570ae907acf988a053c5eff78d6eBrian Gerst	math_state_restore(); /* interrupts still off */
743a334fe43d85f570ae907acf988a053c5eff78d6eBrian Gerst#ifdef CONFIG_X86_32
744a334fe43d85f570ae907acf988a053c5eff78d6eBrian Gerst	conditional_sti(regs);
745081f75bbdc86de53537e1b5aca01de72bd2fea6bAlexander van Heukelum#endif
7466c1e0256fad84a843d915414e4b5973b7443d48dFrederic Weisbecker	exception_exit(prev_state);
7477643e9b936b4af31ba4851eb7d5b3a3bfad52502Alexander van Heukelum}
7489326638cbee2d36b051ed2a69f3e4e107e5f86bdMasami HiramatsuNOKPROBE_SYMBOL(do_device_not_available);
7497643e9b936b4af31ba4851eb7d5b3a3bfad52502Alexander van Heukelum
750081f75bbdc86de53537e1b5aca01de72bd2fea6bAlexander van Heukelum#ifdef CONFIG_X86_32
751e407d62088b7f61f38e1086062650c75a4f2757aAlexander van Heukelumdotraplinkage void do_iret_error(struct pt_regs *regs, long error_code)
752f8e0870f589cfa45575dc7333cdf1b8f769e7900Alexander van Heukelum{
753f8e0870f589cfa45575dc7333cdf1b8f769e7900Alexander van Heukelum	siginfo_t info;
7546c1e0256fad84a843d915414e4b5973b7443d48dFrederic Weisbecker	enum ctx_state prev_state;
7556ba3c97a38803883c2eee489505796cb0a727122Frederic Weisbecker
7566c1e0256fad84a843d915414e4b5973b7443d48dFrederic Weisbecker	prev_state = exception_enter();
757f8e0870f589cfa45575dc7333cdf1b8f769e7900Alexander van Heukelum	local_irq_enable();
758f8e0870f589cfa45575dc7333cdf1b8f769e7900Alexander van Heukelum
759f8e0870f589cfa45575dc7333cdf1b8f769e7900Alexander van Heukelum	info.si_signo = SIGILL;
760f8e0870f589cfa45575dc7333cdf1b8f769e7900Alexander van Heukelum	info.si_errno = 0;
761f8e0870f589cfa45575dc7333cdf1b8f769e7900Alexander van Heukelum	info.si_code = ILL_BADSTK;
762fc6fcdfbb8f1b2553255170f221cd57a4108591fHannes Eder	info.si_addr = NULL;
763c94082656dac74257f63e91f78d5d458ac781fa5Kees Cook	if (notify_die(DIE_TRAP, "iret exception", regs, error_code,
7646ba3c97a38803883c2eee489505796cb0a727122Frederic Weisbecker			X86_TRAP_IRET, SIGILL) != NOTIFY_STOP) {
7656ba3c97a38803883c2eee489505796cb0a727122Frederic Weisbecker		do_trap(X86_TRAP_IRET, SIGILL, "iret exception", regs, error_code,
7666ba3c97a38803883c2eee489505796cb0a727122Frederic Weisbecker			&info);
7676ba3c97a38803883c2eee489505796cb0a727122Frederic Weisbecker	}
7686c1e0256fad84a843d915414e4b5973b7443d48dFrederic Weisbecker	exception_exit(prev_state);
769f8e0870f589cfa45575dc7333cdf1b8f769e7900Alexander van Heukelum}
770081f75bbdc86de53537e1b5aca01de72bd2fea6bAlexander van Heukelum#endif
771f8e0870f589cfa45575dc7333cdf1b8f769e7900Alexander van Heukelum
77229c843912a0baa7fa63033fe28e1ca7e796686a5Jan Kiszka/* Set of traps needed for early debugging. */
77329c843912a0baa7fa63033fe28e1ca7e796686a5Jan Kiszkavoid __init early_trap_init(void)
77429c843912a0baa7fa63033fe28e1ca7e796686a5Jan Kiszka{
775c94082656dac74257f63e91f78d5d458ac781fa5Kees Cook	set_intr_gate_ist(X86_TRAP_DB, &debug, DEBUG_STACK);
77629c843912a0baa7fa63033fe28e1ca7e796686a5Jan Kiszka	/* int3 can be called from all */
777c94082656dac74257f63e91f78d5d458ac781fa5Kees Cook	set_system_intr_gate_ist(X86_TRAP_BP, &int3, DEBUG_STACK);
7788170e6bed465b4b0c7687f93e9948aca4358a33bH. Peter Anvin#ifdef CONFIG_X86_32
77925c74b10bacead867478480170083f69cfc0db48Seiji Aguchi	set_intr_gate(X86_TRAP_PF, page_fault);
7808170e6bed465b4b0c7687f93e9948aca4358a33bH. Peter Anvin#endif
78129c843912a0baa7fa63033fe28e1ca7e796686a5Jan Kiszka	load_idt(&idt_descr);
78229c843912a0baa7fa63033fe28e1ca7e796686a5Jan Kiszka}
78329c843912a0baa7fa63033fe28e1ca7e796686a5Jan Kiszka
7848170e6bed465b4b0c7687f93e9948aca4358a33bH. Peter Anvinvoid __init early_trap_pf_init(void)
7858170e6bed465b4b0c7687f93e9948aca4358a33bH. Peter Anvin{
7868170e6bed465b4b0c7687f93e9948aca4358a33bH. Peter Anvin#ifdef CONFIG_X86_64
78725c74b10bacead867478480170083f69cfc0db48Seiji Aguchi	set_intr_gate(X86_TRAP_PF, page_fault);
7888170e6bed465b4b0c7687f93e9948aca4358a33bH. Peter Anvin#endif
7898170e6bed465b4b0c7687f93e9948aca4358a33bH. Peter Anvin}
7908170e6bed465b4b0c7687f93e9948aca4358a33bH. Peter Anvin
7911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsvoid __init trap_init(void)
7921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
793dbeb2be21d678c49a8d8bbf774903df15dd55474Rusty Russell	int i;
794dbeb2be21d678c49a8d8bbf774903df15dd55474Rusty Russell
7951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef CONFIG_EISA
796927222b102186a6cc3e43e25062fcd18c800435eIngo Molnar	void __iomem *p = early_ioremap(0x0FFFD9, 4);
797b5964405fbc4fd4c57e0e1f86bc9f1b3dbfa040aIngo Molnar
798b5964405fbc4fd4c57e0e1f86bc9f1b3dbfa040aIngo Molnar	if (readl(p) == 'E' + ('I'<<8) + ('S'<<16) + ('A'<<24))
7991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		EISA_bus = 1;
800927222b102186a6cc3e43e25062fcd18c800435eIngo Molnar	early_iounmap(p, 4);
8011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif
8021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
80325c74b10bacead867478480170083f69cfc0db48Seiji Aguchi	set_intr_gate(X86_TRAP_DE, divide_error);
804c94082656dac74257f63e91f78d5d458ac781fa5Kees Cook	set_intr_gate_ist(X86_TRAP_NMI, &nmi, NMI_STACK);
805699d2937d45d9dabc1772d0d07501ccc43885c23Alexander van Heukelum	/* int4 can be called from all */
806c94082656dac74257f63e91f78d5d458ac781fa5Kees Cook	set_system_intr_gate(X86_TRAP_OF, &overflow);
80725c74b10bacead867478480170083f69cfc0db48Seiji Aguchi	set_intr_gate(X86_TRAP_BR, bounds);
80825c74b10bacead867478480170083f69cfc0db48Seiji Aguchi	set_intr_gate(X86_TRAP_UD, invalid_op);
80925c74b10bacead867478480170083f69cfc0db48Seiji Aguchi	set_intr_gate(X86_TRAP_NM, device_not_available);
810081f75bbdc86de53537e1b5aca01de72bd2fea6bAlexander van Heukelum#ifdef CONFIG_X86_32
811c94082656dac74257f63e91f78d5d458ac781fa5Kees Cook	set_task_gate(X86_TRAP_DF, GDT_ENTRY_DOUBLEFAULT_TSS);
812081f75bbdc86de53537e1b5aca01de72bd2fea6bAlexander van Heukelum#else
813c94082656dac74257f63e91f78d5d458ac781fa5Kees Cook	set_intr_gate_ist(X86_TRAP_DF, &double_fault, DOUBLEFAULT_STACK);
814081f75bbdc86de53537e1b5aca01de72bd2fea6bAlexander van Heukelum#endif
81525c74b10bacead867478480170083f69cfc0db48Seiji Aguchi	set_intr_gate(X86_TRAP_OLD_MF, coprocessor_segment_overrun);
81625c74b10bacead867478480170083f69cfc0db48Seiji Aguchi	set_intr_gate(X86_TRAP_TS, invalid_TSS);
81725c74b10bacead867478480170083f69cfc0db48Seiji Aguchi	set_intr_gate(X86_TRAP_NP, segment_not_present);
8186f442be2fb22be02cafa606f1769fa1e6f894441Andy Lutomirski	set_intr_gate(X86_TRAP_SS, stack_segment);
81925c74b10bacead867478480170083f69cfc0db48Seiji Aguchi	set_intr_gate(X86_TRAP_GP, general_protection);
82025c74b10bacead867478480170083f69cfc0db48Seiji Aguchi	set_intr_gate(X86_TRAP_SPURIOUS, spurious_interrupt_bug);
82125c74b10bacead867478480170083f69cfc0db48Seiji Aguchi	set_intr_gate(X86_TRAP_MF, coprocessor_error);
82225c74b10bacead867478480170083f69cfc0db48Seiji Aguchi	set_intr_gate(X86_TRAP_AC, alignment_check);
8231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef CONFIG_X86_MCE
824c94082656dac74257f63e91f78d5d458ac781fa5Kees Cook	set_intr_gate_ist(X86_TRAP_MC, &machine_check, MCE_STACK);
8251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif
82625c74b10bacead867478480170083f69cfc0db48Seiji Aguchi	set_intr_gate(X86_TRAP_XF, simd_coprocessor_error);
8271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
828bb3f0b59ad005d2d2ecbbe9bd048eab6d1ecbd31Yinghai Lu	/* Reserve all the builtin and the syscall vector: */
829bb3f0b59ad005d2d2ecbbe9bd048eab6d1ecbd31Yinghai Lu	for (i = 0; i < FIRST_EXTERNAL_VECTOR; i++)
830bb3f0b59ad005d2d2ecbbe9bd048eab6d1ecbd31Yinghai Lu		set_bit(i, used_vectors);
831bb3f0b59ad005d2d2ecbbe9bd048eab6d1ecbd31Yinghai Lu
832081f75bbdc86de53537e1b5aca01de72bd2fea6bAlexander van Heukelum#ifdef CONFIG_IA32_EMULATION
833081f75bbdc86de53537e1b5aca01de72bd2fea6bAlexander van Heukelum	set_system_intr_gate(IA32_SYSCALL_VECTOR, ia32_syscall);
834bb3f0b59ad005d2d2ecbbe9bd048eab6d1ecbd31Yinghai Lu	set_bit(IA32_SYSCALL_VECTOR, used_vectors);
835081f75bbdc86de53537e1b5aca01de72bd2fea6bAlexander van Heukelum#endif
836081f75bbdc86de53537e1b5aca01de72bd2fea6bAlexander van Heukelum
837081f75bbdc86de53537e1b5aca01de72bd2fea6bAlexander van Heukelum#ifdef CONFIG_X86_32
838699d2937d45d9dabc1772d0d07501ccc43885c23Alexander van Heukelum	set_system_trap_gate(SYSCALL_VECTOR, &system_call);
839dbeb2be21d678c49a8d8bbf774903df15dd55474Rusty Russell	set_bit(SYSCALL_VECTOR, used_vectors);
840081f75bbdc86de53537e1b5aca01de72bd2fea6bAlexander van Heukelum#endif
841bb3f0b59ad005d2d2ecbbe9bd048eab6d1ecbd31Yinghai Lu
8421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/*
8434eefbe792baedb474e256d35370849992fcf1c79Kees Cook	 * Set the IDT descriptor to a fixed read-only location, so that the
8444eefbe792baedb474e256d35370849992fcf1c79Kees Cook	 * "sidt" instruction will not leak the location of the kernel, and
8454eefbe792baedb474e256d35370849992fcf1c79Kees Cook	 * to defend the IDT against arbitrary memory write vulnerabilities.
8464eefbe792baedb474e256d35370849992fcf1c79Kees Cook	 * It will be reloaded in cpu_init() */
8474eefbe792baedb474e256d35370849992fcf1c79Kees Cook	__set_fixmap(FIX_RO_IDT, __pa_symbol(idt_table), PAGE_KERNEL_RO);
8484eefbe792baedb474e256d35370849992fcf1c79Kees Cook	idt_descr.address = fix_to_virt(FIX_RO_IDT);
8494eefbe792baedb474e256d35370849992fcf1c79Kees Cook
8504eefbe792baedb474e256d35370849992fcf1c79Kees Cook	/*
851b5964405fbc4fd4c57e0e1f86bc9f1b3dbfa040aIngo Molnar	 * Should be a barrier for any external CPU state:
8521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 */
8531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	cpu_init();
8541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
855428cf9025b15573e16e658032f2b963283e34ae0Thomas Gleixner	x86_init.irqs.trap_init();
856228bdaa95fb830e08b6acd1afd4d2c55093cabfaSteven Rostedt
857228bdaa95fb830e08b6acd1afd4d2c55093cabfaSteven Rostedt#ifdef CONFIG_X86_64
858629f4f9d59a27d8e58aa612e886e6a9a63ea7aebSeiji Aguchi	memcpy(&debug_idt_table, &idt_table, IDT_ENTRIES * 16);
859c94082656dac74257f63e91f78d5d458ac781fa5Kees Cook	set_nmi_gate(X86_TRAP_DB, &debug);
860c94082656dac74257f63e91f78d5d458ac781fa5Kees Cook	set_nmi_gate(X86_TRAP_BP, &int3);
861228bdaa95fb830e08b6acd1afd4d2c55093cabfaSteven Rostedt#endif
8621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
863