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