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