11da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 21da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Architecture-specific trap handling. 31da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 41da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Copyright (C) 1998-2003 Hewlett-Packard Co 51da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * David Mosberger-Tang <davidm@hpl.hp.com> 61da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 71da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 05/12/00 grao <goutham.rao@intel.com> : added isr in siginfo for SIGFPE 81da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 91da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/kernel.h> 111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/init.h> 121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/sched.h> 131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/tty.h> 141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/vt_kern.h> /* For unblank_screen() */ 151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/module.h> /* for EXPORT_SYMBOL */ 161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/hardirq.h> 171f7ad57b75ab0fba27455c7344a6ab7aa6bd90c5Prasanna S Panchamukhi#include <linux/kprobes.h> 18b05de01ae1c76b7d61da21bbcc26345bf7a9052fHorms#include <linux/delay.h> /* for ssleep() */ 191eeb66a1bb973534dc3d064920a5ca683823372eChristoph Hellwig#include <linux/kdebug.h> 201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <asm/fpswa.h> 221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <asm/intrinsics.h> 231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <asm/processor.h> 241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <asm/uaccess.h> 25c140d87995b68b428f70635c2e4071e4e8b3256eDavid Howells#include <asm/setup.h> 261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsfpswa_interface_t *fpswa_interface; 281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsEXPORT_SYMBOL(fpswa_interface); 291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsvoid __init 311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldstrap_init (void) 321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (ia64_boot_param->fpswa) 341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* FPSWA fixup: make the interface pointer a kernel virtual address: */ 351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fpswa_interface = __va(ia64_boot_param->fpswa); 361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 38620de2f5dc697f906408743b1139fe5fb7b0b7f8Jan Beulichint 391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsdie (const char *str, struct pt_regs *regs, long err) 401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds static struct { 421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds spinlock_t lock; 431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u32 lock_owner; 441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int lock_owner_depth; 451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } die = { 468737d59579c5e61ea3d5da4bd63303159fd1cf7eMilind Arun Choudhary .lock = __SPIN_LOCK_UNLOCKED(die.lock), 478737d59579c5e61ea3d5da4bd63303159fd1cf7eMilind Arun Choudhary .lock_owner = -1, 488737d59579c5e61ea3d5da4bd63303159fd1cf7eMilind Arun Choudhary .lock_owner_depth = 0 491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds }; 501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds static int die_counter; 51af25e94d4dcfb9608846242fabdd4e6014e5c9f0<> int cpu = get_cpu(); 521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 53af25e94d4dcfb9608846242fabdd4e6014e5c9f0<> if (die.lock_owner != cpu) { 541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds console_verbose(); 551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds spin_lock_irq(&die.lock); 56af25e94d4dcfb9608846242fabdd4e6014e5c9f0<> die.lock_owner = cpu; 571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds die.lock_owner_depth = 0; 581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds bust_spinlocks(1); 591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 60af25e94d4dcfb9608846242fabdd4e6014e5c9f0<> put_cpu(); 611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (++die.lock_owner_depth < 3) { 631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk("%s[%d]: %s %ld [%d]\n", 6419c5870c0eefd27c6d09d867465e0571262e05d0Alexey Dobriyan current->comm, task_pid_nr(current), str, err, ++die_counter); 65620de2f5dc697f906408743b1139fe5fb7b0b7f8Jan Beulich if (notify_die(DIE_OOPS, str, regs, err, 255, SIGSEGV) 66620de2f5dc697f906408743b1139fe5fb7b0b7f8Jan Beulich != NOTIFY_STOP) 67620de2f5dc697f906408743b1139fe5fb7b0b7f8Jan Beulich show_regs(regs); 68620de2f5dc697f906408743b1139fe5fb7b0b7f8Jan Beulich else 69620de2f5dc697f906408743b1139fe5fb7b0b7f8Jan Beulich regs = NULL; 701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else 711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk(KERN_ERR "Recursive die() failure, output suppressed\n"); 721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds bust_spinlocks(0); 741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds die.lock_owner = -1; 75373d4d099761cb1f637bed488ab3871945882273Rusty Russell add_taint(TAINT_DIE, LOCKDEP_NOW_UNRELIABLE); 761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds spin_unlock_irq(&die.lock); 77b05de01ae1c76b7d61da21bbcc26345bf7a9052fHorms 78620de2f5dc697f906408743b1139fe5fb7b0b7f8Jan Beulich if (!regs) 79620de2f5dc697f906408743b1139fe5fb7b0b7f8Jan Beulich return 1; 80620de2f5dc697f906408743b1139fe5fb7b0b7f8Jan Beulich 81cea6a4ba8acfba6f59cc9ed71e0d05cb770b9d9cHorms if (panic_on_oops) 82012c437d03cb299814e58ac8d574f7510f5989a5Horms panic("Fatal exception"); 83b05de01ae1c76b7d61da21bbcc26345bf7a9052fHorms 841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds do_exit(SIGSEGV); 85620de2f5dc697f906408743b1139fe5fb7b0b7f8Jan Beulich return 0; 861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 88620de2f5dc697f906408743b1139fe5fb7b0b7f8Jan Beulichint 891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsdie_if_kernel (char *str, struct pt_regs *regs, long err) 901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!user_mode(regs)) 92620de2f5dc697f906408743b1139fe5fb7b0b7f8Jan Beulich return die(str, regs, err); 93620de2f5dc697f906408743b1139fe5fb7b0b7f8Jan Beulich return 0; 941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsvoid 971f7ad57b75ab0fba27455c7344a6ab7aa6bd90c5Prasanna S Panchamukhi__kprobes ia64_bad_break (unsigned long break_num, struct pt_regs *regs) 981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds siginfo_t siginfo; 1001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int sig, code; 1011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* SIGILL, SIGFPE, SIGSEGV, and SIGBUS want these field initialized: */ 1031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds siginfo.si_addr = (void __user *) (regs->cr_iip + ia64_psr(regs)->ri); 1041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds siginfo.si_imm = break_num; 1051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds siginfo.si_flags = 0; /* clear __ISR_VALID */ 1061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds siginfo.si_isr = 0; 1071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds switch (break_num) { 1091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case 0: /* unknown error (used by GCC for __builtin_abort()) */ 1107213b2521889eb087eed8abaa48d1a692575da3eAnil S Keshavamurthy if (notify_die(DIE_BREAK, "break 0", regs, break_num, TRAP_BRKPT, SIGTRAP) 1119138d581b0ef855c0314c41c14852a7231b9941cKeith Owens == NOTIFY_STOP) 1127213b2521889eb087eed8abaa48d1a692575da3eAnil S Keshavamurthy return; 113620de2f5dc697f906408743b1139fe5fb7b0b7f8Jan Beulich if (die_if_kernel("bugcheck!", regs, break_num)) 114620de2f5dc697f906408743b1139fe5fb7b0b7f8Jan Beulich return; 1151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sig = SIGILL; code = ILL_ILLOPC; 1161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 1171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case 1: /* integer divide by zero */ 1191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sig = SIGFPE; code = FPE_INTDIV; 1201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 1211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case 2: /* integer overflow */ 1231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sig = SIGFPE; code = FPE_INTOVF; 1241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 1251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case 3: /* range check/bounds check */ 1271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sig = SIGFPE; code = FPE_FLTSUB; 1281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 1291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case 4: /* null pointer dereference */ 1311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sig = SIGSEGV; code = SEGV_MAPERR; 1321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 1331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case 5: /* misaligned data */ 1351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sig = SIGSEGV; code = BUS_ADRALN; 1361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 1371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case 6: /* decimal overflow */ 1391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sig = SIGFPE; code = __FPE_DECOVF; 1401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 1411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case 7: /* decimal divide by zero */ 1431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sig = SIGFPE; code = __FPE_DECDIV; 1441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 1451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case 8: /* packed decimal error */ 1471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sig = SIGFPE; code = __FPE_DECERR; 1481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 1491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case 9: /* invalid ASCII digit */ 1511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sig = SIGFPE; code = __FPE_INVASC; 1521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 1531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case 10: /* invalid decimal digit */ 1551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sig = SIGFPE; code = __FPE_INVDEC; 1561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 1571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case 11: /* paragraph stack overflow */ 1591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sig = SIGSEGV; code = __SEGV_PSTKOVF; 1601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 1611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case 0x3f000 ... 0x3ffff: /* bundle-update in progress */ 1631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sig = SIGILL; code = __ILL_BNDMOD; 1641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 1651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds default: 167620de2f5dc697f906408743b1139fe5fb7b0b7f8Jan Beulich if ((break_num < 0x40000 || break_num > 0x100000) 168620de2f5dc697f906408743b1139fe5fb7b0b7f8Jan Beulich && die_if_kernel("Bad break", regs, break_num)) 169620de2f5dc697f906408743b1139fe5fb7b0b7f8Jan Beulich return; 1701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (break_num < 0x80000) { 1721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sig = SIGILL; code = __ILL_BREAK; 1731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else { 1749138d581b0ef855c0314c41c14852a7231b9941cKeith Owens if (notify_die(DIE_BREAK, "bad break", regs, break_num, TRAP_BRKPT, SIGTRAP) 1759138d581b0ef855c0314c41c14852a7231b9941cKeith Owens == NOTIFY_STOP) 1769138d581b0ef855c0314c41c14852a7231b9941cKeith Owens return; 1771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sig = SIGTRAP; code = TRAP_BRKPT; 1781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds siginfo.si_signo = sig; 1811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds siginfo.si_errno = 0; 1821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds siginfo.si_code = code; 1831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds force_sig_info(sig, &siginfo, current); 1841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 1851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 1871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * disabled_fph_fault() is called when a user-level process attempts to access f32..f127 1881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * and it doesn't own the fp-high register partition. When this happens, we save the 1891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * current fph partition in the task_struct of the fpu-owner (if necessary) and then load 1901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * the fp-high partition of the current task (if necessary). Note that the kernel has 1911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * access to fph by the time we get here, as the IVT's "Disabled FP-Register" handler takes 1921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * care of clearing psr.dfh. 1931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 1941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic inline void 1951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsdisabled_fph_fault (struct pt_regs *regs) 1961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct ia64_psr *psr = ia64_psr(regs); 1981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* first, grant user-level access to fph partition: */ 2001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds psr->dfh = 0; 20105062d96a23ec0959ee5ea969f40813170c73c0ePeter Chubb 20205062d96a23ec0959ee5ea969f40813170c73c0ePeter Chubb /* 20305062d96a23ec0959ee5ea969f40813170c73c0ePeter Chubb * Make sure that no other task gets in on this processor 20405062d96a23ec0959ee5ea969f40813170c73c0ePeter Chubb * while we're claiming the FPU 20505062d96a23ec0959ee5ea969f40813170c73c0ePeter Chubb */ 20605062d96a23ec0959ee5ea969f40813170c73c0ePeter Chubb preempt_disable(); 2071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifndef CONFIG_SMP 2081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { 2091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct task_struct *fpu_owner 2101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds = (struct task_struct *)ia64_get_kr(IA64_KR_FPU_OWNER); 2111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 21205062d96a23ec0959ee5ea969f40813170c73c0ePeter Chubb if (ia64_is_local_fpu_owner(current)) { 21305062d96a23ec0959ee5ea969f40813170c73c0ePeter Chubb preempt_enable_no_resched(); 2141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return; 21505062d96a23ec0959ee5ea969f40813170c73c0ePeter Chubb } 2161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (fpu_owner) 2181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ia64_flush_fph(fpu_owner); 2191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 2201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif /* !CONFIG_SMP */ 2211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ia64_set_local_fpu_owner(current); 2221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if ((current->thread.flags & IA64_THREAD_FPH_VALID) != 0) { 2231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds __ia64_load_fpu(current->thread.fph); 2241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds psr->mfh = 0; 2251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else { 2261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds __ia64_init_fpu(); 2271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 2281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Set mfh because the state in thread.fph does not match the state in 2291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * the fph partition. 2301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 2311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds psr->mfh = 1; 2321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 23305062d96a23ec0959ee5ea969f40813170c73c0ePeter Chubb preempt_enable_no_resched(); 2341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 2351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic inline int 2371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsfp_emulate (int fp_fault, void *bundle, long *ipsr, long *fpsr, long *isr, long *pr, long *ifs, 2381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct pt_regs *regs) 2391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 2401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fp_state_t fp_state; 2411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fpswa_ret_t ret; 2421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!fpswa_interface) 2441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -1; 2451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds memset(&fp_state, 0, sizeof(fp_state_t)); 2471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 2491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * compute fp_state. only FP registers f6 - f11 are used by the 2501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * kernel, so set those bits in the mask and set the low volatile 2511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * pointer to point to these registers. 2521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 2531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fp_state.bitmask_low64 = 0xfc0; /* bit6..bit11 */ 2541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fp_state.fp_state_low_volatile = (fp_state_low_volatile_t *) ®s->f6; 2561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 2571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * unsigned long (*EFI_FPSWA) ( 2581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * unsigned long trap_type, 2591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * void *Bundle, 2601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * unsigned long *pipsr, 2611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * unsigned long *pfsr, 2621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * unsigned long *pisr, 2631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * unsigned long *ppreds, 2641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * unsigned long *pifs, 2651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * void *fp_state); 2661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 2671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ret = (*fpswa_interface->fpswa)((unsigned long) fp_fault, bundle, 2681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds (unsigned long *) ipsr, (unsigned long *) fpsr, 2691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds (unsigned long *) isr, (unsigned long *) pr, 2701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds (unsigned long *) ifs, &fp_state); 2711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return ret.status; 2731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 2741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2751cf24bdbbbd2eb5439796dc399ab1649d150ed1dJack Steinerstruct fpu_swa_msg { 2761cf24bdbbbd2eb5439796dc399ab1649d150ed1dJack Steiner unsigned long count; 2771cf24bdbbbd2eb5439796dc399ab1649d150ed1dJack Steiner unsigned long time; 2781cf24bdbbbd2eb5439796dc399ab1649d150ed1dJack Steiner}; 2791cf24bdbbbd2eb5439796dc399ab1649d150ed1dJack Steinerstatic DEFINE_PER_CPU(struct fpu_swa_msg, cpulast); 2801cf24bdbbbd2eb5439796dc399ab1649d150ed1dJack SteinerDECLARE_PER_CPU(struct fpu_swa_msg, cpulast); 2811cf24bdbbbd2eb5439796dc399ab1649d150ed1dJack Steinerstatic struct fpu_swa_msg last __cacheline_aligned; 2821cf24bdbbbd2eb5439796dc399ab1649d150ed1dJack Steiner 2831cf24bdbbbd2eb5439796dc399ab1649d150ed1dJack Steiner 2841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 2851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Handle floating-point assist faults and traps. 2861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 2871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int 2881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldshandle_fpu_swa (int fp_fault, struct pt_regs *regs, unsigned long isr) 2891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 2901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds long exception, bundle[2]; 2911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned long fault_ip; 2921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct siginfo siginfo; 2931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fault_ip = regs->cr_iip; 2951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!fp_fault && (ia64_psr(regs)->ri == 0)) 2961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fault_ip -= 16; 2971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (copy_from_user(bundle, (void __user *) fault_ip, sizeof(bundle))) 2981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -1; 2991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3001cf24bdbbbd2eb5439796dc399ab1649d150ed1dJack Steiner if (!(current->thread.flags & IA64_THREAD_FPEMU_NOPRINT)) { 3011cf24bdbbbd2eb5439796dc399ab1649d150ed1dJack Steiner unsigned long count, current_jiffies = jiffies; 3026065a244a039a23d933e4b803a4e052da2849208Christoph Lameter struct fpu_swa_msg *cp = this_cpu_ptr(&cpulast); 3031cf24bdbbbd2eb5439796dc399ab1649d150ed1dJack Steiner 3041cf24bdbbbd2eb5439796dc399ab1649d150ed1dJack Steiner if (unlikely(current_jiffies > cp->time)) 3051cf24bdbbbd2eb5439796dc399ab1649d150ed1dJack Steiner cp->count = 0; 3061cf24bdbbbd2eb5439796dc399ab1649d150ed1dJack Steiner if (unlikely(cp->count < 5)) { 3071cf24bdbbbd2eb5439796dc399ab1649d150ed1dJack Steiner cp->count++; 3081cf24bdbbbd2eb5439796dc399ab1649d150ed1dJack Steiner cp->time = current_jiffies + 5 * HZ; 3091cf24bdbbbd2eb5439796dc399ab1649d150ed1dJack Steiner 3101cf24bdbbbd2eb5439796dc399ab1649d150ed1dJack Steiner /* minimize races by grabbing a copy of count BEFORE checking last.time. */ 3111cf24bdbbbd2eb5439796dc399ab1649d150ed1dJack Steiner count = last.count; 3121cf24bdbbbd2eb5439796dc399ab1649d150ed1dJack Steiner barrier(); 3131cf24bdbbbd2eb5439796dc399ab1649d150ed1dJack Steiner 3141cf24bdbbbd2eb5439796dc399ab1649d150ed1dJack Steiner /* 3151cf24bdbbbd2eb5439796dc399ab1649d150ed1dJack Steiner * Lower 4 bits are used as a count. Upper bits are a sequence 3161cf24bdbbbd2eb5439796dc399ab1649d150ed1dJack Steiner * number that is updated when count is reset. The cmpxchg will 3171cf24bdbbbd2eb5439796dc399ab1649d150ed1dJack Steiner * fail is seqno has changed. This minimizes mutiple cpus 31872fdbdce3d52282f8ea95f512e871791256754e6Simon Arlott * resetting the count. 3191cf24bdbbbd2eb5439796dc399ab1649d150ed1dJack Steiner */ 3201cf24bdbbbd2eb5439796dc399ab1649d150ed1dJack Steiner if (current_jiffies > last.time) 3211cf24bdbbbd2eb5439796dc399ab1649d150ed1dJack Steiner (void) cmpxchg_acq(&last.count, count, 16 + (count & ~15)); 3221cf24bdbbbd2eb5439796dc399ab1649d150ed1dJack Steiner 3231cf24bdbbbd2eb5439796dc399ab1649d150ed1dJack Steiner /* used fetchadd to atomically update the count */ 3241cf24bdbbbd2eb5439796dc399ab1649d150ed1dJack Steiner if ((last.count & 15) < 5 && (ia64_fetchadd(1, &last.count, acq) & 15) < 5) { 3251cf24bdbbbd2eb5439796dc399ab1649d150ed1dJack Steiner last.time = current_jiffies + 5 * HZ; 3261cf24bdbbbd2eb5439796dc399ab1649d150ed1dJack Steiner printk(KERN_WARNING 3271cf24bdbbbd2eb5439796dc399ab1649d150ed1dJack Steiner "%s(%d): floating-point assist fault at ip %016lx, isr %016lx\n", 32819c5870c0eefd27c6d09d867465e0571262e05d0Alexey Dobriyan current->comm, task_pid_nr(current), regs->cr_iip + ia64_psr(regs)->ri, isr); 3291cf24bdbbbd2eb5439796dc399ab1649d150ed1dJack Steiner } 3301cf24bdbbbd2eb5439796dc399ab1649d150ed1dJack Steiner } 3311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 3321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds exception = fp_emulate(fp_fault, bundle, ®s->cr_ipsr, ®s->ar_fpsr, &isr, ®s->pr, 3341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ®s->cr_ifs, regs); 3351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (fp_fault) { 3361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (exception == 0) { 3371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* emulation was successful */ 3381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ia64_increment_ip(regs); 3391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else if (exception == -1) { 3401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk(KERN_ERR "handle_fpu_swa: fp_emulate() returned -1\n"); 3411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -1; 3421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else { 3431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* is next instruction a trap? */ 3441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (exception & 2) { 3451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ia64_increment_ip(regs); 3461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 3471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds siginfo.si_signo = SIGFPE; 3481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds siginfo.si_errno = 0; 3491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds siginfo.si_code = __SI_FAULT; /* default code */ 3501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds siginfo.si_addr = (void __user *) (regs->cr_iip + ia64_psr(regs)->ri); 3511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (isr & 0x11) { 3521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds siginfo.si_code = FPE_FLTINV; 3531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else if (isr & 0x22) { 3541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* denormal operand gets the same si_code as underflow 3551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * see arch/i386/kernel/traps.c:math_error() */ 3561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds siginfo.si_code = FPE_FLTUND; 3571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else if (isr & 0x44) { 3581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds siginfo.si_code = FPE_FLTDIV; 3591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 3601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds siginfo.si_isr = isr; 3611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds siginfo.si_flags = __ISR_VALID; 3621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds siginfo.si_imm = 0; 3631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds force_sig_info(SIGFPE, &siginfo, current); 3641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 3651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else { 3661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (exception == -1) { 3671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk(KERN_ERR "handle_fpu_swa: fp_emulate() returned -1\n"); 3681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -1; 3691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else if (exception != 0) { 3701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* raise exception */ 3711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds siginfo.si_signo = SIGFPE; 3721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds siginfo.si_errno = 0; 3731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds siginfo.si_code = __SI_FAULT; /* default code */ 3741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds siginfo.si_addr = (void __user *) (regs->cr_iip + ia64_psr(regs)->ri); 3751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (isr & 0x880) { 3761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds siginfo.si_code = FPE_FLTOVF; 3771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else if (isr & 0x1100) { 3781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds siginfo.si_code = FPE_FLTUND; 3791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else if (isr & 0x2200) { 3801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds siginfo.si_code = FPE_FLTRES; 3811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 3821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds siginfo.si_isr = isr; 3831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds siginfo.si_flags = __ISR_VALID; 3841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds siginfo.si_imm = 0; 3851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds force_sig_info(SIGFPE, &siginfo, current); 3861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 3871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 3881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 3891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 3901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstruct illegal_op_return { 3921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned long fkt, arg1, arg2, arg3; 3931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 3941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstruct illegal_op_return 3961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsia64_illegal_op_fault (unsigned long ec, long arg1, long arg2, long arg3, 3971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds long arg4, long arg5, long arg6, long arg7, 3981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct pt_regs regs) 3991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 4001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct illegal_op_return rv; 4011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct siginfo si; 4021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds char buf[128]; 4031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef CONFIG_IA64_BRL_EMU 4051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { 4061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds extern struct illegal_op_return ia64_emulate_brl (struct pt_regs *, unsigned long); 4071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds rv = ia64_emulate_brl(®s, ec); 4091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (rv.fkt != (unsigned long) -1) 4101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return rv; 4111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 4121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif 4131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sprintf(buf, "IA-64 Illegal operation fault"); 415620de2f5dc697f906408743b1139fe5fb7b0b7f8Jan Beulich rv.fkt = 0; 416620de2f5dc697f906408743b1139fe5fb7b0b7f8Jan Beulich if (die_if_kernel(buf, ®s, 0)) 417620de2f5dc697f906408743b1139fe5fb7b0b7f8Jan Beulich return rv; 4181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds memset(&si, 0, sizeof(si)); 4201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds si.si_signo = SIGILL; 4211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds si.si_code = ILL_ILLOPC; 4221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds si.si_addr = (void __user *) (regs.cr_iip + ia64_psr(®s)->ri); 4231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds force_sig_info(SIGILL, &si, current); 4241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return rv; 4251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 4261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4271f7ad57b75ab0fba27455c7344a6ab7aa6bd90c5Prasanna S Panchamukhivoid __kprobes 4281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsia64_fault (unsigned long vector, unsigned long isr, unsigned long ifa, 4291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned long iim, unsigned long itir, long arg5, long arg6, 4301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds long arg7, struct pt_regs regs) 4311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 4321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned long code, error = isr, iip; 4331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct siginfo siginfo; 4341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds char buf[128]; 4351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int result, sig; 4361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds static const char *reason[] = { 4371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "IA-64 Illegal Operation fault", 4381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "IA-64 Privileged Operation fault", 4391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "IA-64 Privileged Register fault", 4401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "IA-64 Reserved Register/Field fault", 4411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "Disabled Instruction Set Transition fault", 4421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "Unknown fault 5", "Unknown fault 6", "Unknown fault 7", "Illegal Hazard fault", 4431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "Unknown fault 9", "Unknown fault 10", "Unknown fault 11", "Unknown fault 12", 4441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "Unknown fault 13", "Unknown fault 14", "Unknown fault 15" 4451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds }; 4461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if ((isr & IA64_ISR_NA) && ((isr & IA64_ISR_CODE_MASK) == IA64_ISR_CODE_LFETCH)) { 4481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 4491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * This fault was due to lfetch.fault, set "ed" bit in the psr to cancel 4501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * the lfetch. 4511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 4521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ia64_psr(®s)->ed = 1; 4531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return; 4541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 4551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds iip = regs.cr_iip + ia64_psr(®s)->ri; 4571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds switch (vector) { 4591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case 24: /* General Exception */ 4601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds code = (isr >> 4) & 0xf; 4611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sprintf(buf, "General Exception: %s%s", reason[code], 4621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds (code == 3) ? ((isr & (1UL << 37)) 4631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ? " (RSE access)" : " (data access)") : ""); 4641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (code == 8) { 4651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds# ifdef CONFIG_IA64_PRINT_HAZARDS 4661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk("%s[%d]: possible hazard @ ip=%016lx (pr = %016lx)\n", 46719c5870c0eefd27c6d09d867465e0571262e05d0Alexey Dobriyan current->comm, task_pid_nr(current), 4681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds regs.cr_iip + ia64_psr(®s)->ri, regs.pr); 4691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds# endif 4701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return; 4711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 4721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 4731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case 25: /* Disabled FP-Register */ 4751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (isr & 2) { 4761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds disabled_fph_fault(®s); 4771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return; 4781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 4791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sprintf(buf, "Disabled FPL fault---not supposed to happen!"); 4801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 4811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case 26: /* NaT Consumption */ 4831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (user_mode(®s)) { 4841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds void __user *addr; 4851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (((isr >> 4) & 0xf) == 2) { 4871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* NaT page consumption */ 4881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sig = SIGSEGV; 4891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds code = SEGV_ACCERR; 4901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds addr = (void __user *) ifa; 4911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else { 4921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* register NaT consumption */ 4931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sig = SIGILL; 4941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds code = ILL_ILLOPN; 4951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds addr = (void __user *) (regs.cr_iip 4961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds + ia64_psr(®s)->ri); 4971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 4981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds siginfo.si_signo = sig; 4991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds siginfo.si_code = code; 5001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds siginfo.si_errno = 0; 5011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds siginfo.si_addr = addr; 5021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds siginfo.si_imm = vector; 5031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds siginfo.si_flags = __ISR_VALID; 5041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds siginfo.si_isr = isr; 5051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds force_sig_info(sig, &siginfo, current); 5061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return; 5071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else if (ia64_done_with_exception(®s)) 5081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return; 5091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sprintf(buf, "NaT consumption"); 5101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 5111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case 31: /* Unsupported Data Reference */ 5131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (user_mode(®s)) { 5141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds siginfo.si_signo = SIGILL; 5151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds siginfo.si_code = ILL_ILLOPN; 5161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds siginfo.si_errno = 0; 5171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds siginfo.si_addr = (void __user *) iip; 5181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds siginfo.si_imm = vector; 5191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds siginfo.si_flags = __ISR_VALID; 5201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds siginfo.si_isr = isr; 5211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds force_sig_info(SIGILL, &siginfo, current); 5221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return; 5231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 5241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sprintf(buf, "Unsupported data reference"); 5251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 5261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case 29: /* Debug */ 5281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case 35: /* Taken Branch Trap */ 5291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case 36: /* Single Step Trap */ 5301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (fsys_mode(current, ®s)) { 5311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds extern char __kernel_syscall_via_break[]; 5321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 53315029285dc977a392e74eacb7625984b71d4f605Jason Uhlenkott * Got a trap in fsys-mode: Taken Branch Trap 53415029285dc977a392e74eacb7625984b71d4f605Jason Uhlenkott * and Single Step trap need special handling; 53515029285dc977a392e74eacb7625984b71d4f605Jason Uhlenkott * Debug trap is ignored (we disable it here 53615029285dc977a392e74eacb7625984b71d4f605Jason Uhlenkott * and re-enable it in the lower-privilege trap). 5371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 5381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (unlikely(vector == 29)) { 53915029285dc977a392e74eacb7625984b71d4f605Jason Uhlenkott set_thread_flag(TIF_DB_DISABLED); 54015029285dc977a392e74eacb7625984b71d4f605Jason Uhlenkott ia64_psr(®s)->db = 0; 54115029285dc977a392e74eacb7625984b71d4f605Jason Uhlenkott ia64_psr(®s)->lp = 1; 5421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return; 5431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 5441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* re-do the system call via break 0x100000: */ 5451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds regs.cr_iip = (unsigned long) __kernel_syscall_via_break; 5461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ia64_psr(®s)->ri = 0; 5471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ia64_psr(®s)->cpl = 3; 5481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return; 5491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 5501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds switch (vector) { 5511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case 29: 5521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds siginfo.si_code = TRAP_HWBKPT; 5531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef CONFIG_ITANIUM 5541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 5551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Erratum 10 (IFA may contain incorrect address) now has 5561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * "NoFix" status. There are no plans for fixing this. 5571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 5581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (ia64_psr(®s)->is == 0) 5591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ifa = regs.cr_iip; 5601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif 5611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 5621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case 35: siginfo.si_code = TRAP_BRANCH; ifa = 0; break; 5639138d581b0ef855c0314c41c14852a7231b9941cKeith Owens case 36: siginfo.si_code = TRAP_TRACE; ifa = 0; break; 5641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 5659138d581b0ef855c0314c41c14852a7231b9941cKeith Owens if (notify_die(DIE_FAULT, "ia64_fault", ®s, vector, siginfo.si_code, SIGTRAP) 5669138d581b0ef855c0314c41c14852a7231b9941cKeith Owens == NOTIFY_STOP) 5679138d581b0ef855c0314c41c14852a7231b9941cKeith Owens return; 5681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds siginfo.si_signo = SIGTRAP; 5691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds siginfo.si_errno = 0; 5701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds siginfo.si_addr = (void __user *) ifa; 5711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds siginfo.si_imm = 0; 5721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds siginfo.si_flags = __ISR_VALID; 5731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds siginfo.si_isr = isr; 5741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds force_sig_info(SIGTRAP, &siginfo, current); 5751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return; 5761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case 32: /* fp fault */ 5781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case 33: /* fp trap */ 5791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds result = handle_fpu_swa((vector == 32) ? 1 : 0, ®s, isr); 5801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if ((result < 0) || (current->thread.flags & IA64_THREAD_FPEMU_SIGFPE)) { 5811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds siginfo.si_signo = SIGFPE; 5821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds siginfo.si_errno = 0; 5831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds siginfo.si_code = FPE_FLTINV; 5841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds siginfo.si_addr = (void __user *) iip; 5851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds siginfo.si_flags = __ISR_VALID; 5861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds siginfo.si_isr = isr; 5871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds siginfo.si_imm = 0; 5881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds force_sig_info(SIGFPE, &siginfo, current); 5891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 5901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return; 5911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case 34: 5931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (isr & 0x2) { 5941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Lower-Privilege Transfer Trap */ 59515029285dc977a392e74eacb7625984b71d4f605Jason Uhlenkott 59615029285dc977a392e74eacb7625984b71d4f605Jason Uhlenkott /* If we disabled debug traps during an fsyscall, 59715029285dc977a392e74eacb7625984b71d4f605Jason Uhlenkott * re-enable them here. 59815029285dc977a392e74eacb7625984b71d4f605Jason Uhlenkott */ 59915029285dc977a392e74eacb7625984b71d4f605Jason Uhlenkott if (test_thread_flag(TIF_DB_DISABLED)) { 60015029285dc977a392e74eacb7625984b71d4f605Jason Uhlenkott clear_thread_flag(TIF_DB_DISABLED); 60115029285dc977a392e74eacb7625984b71d4f605Jason Uhlenkott ia64_psr(®s)->db = 1; 60215029285dc977a392e74eacb7625984b71d4f605Jason Uhlenkott } 60315029285dc977a392e74eacb7625984b71d4f605Jason Uhlenkott 6041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 60515029285dc977a392e74eacb7625984b71d4f605Jason Uhlenkott * Just clear PSR.lp and then return immediately: 60615029285dc977a392e74eacb7625984b71d4f605Jason Uhlenkott * all the interesting work (e.g., signal delivery) 60715029285dc977a392e74eacb7625984b71d4f605Jason Uhlenkott * is done in the kernel exit path. 6081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 6091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ia64_psr(®s)->lp = 0; 6101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return; 6111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else { 6121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Unimplemented Instr. Address Trap */ 6131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (user_mode(®s)) { 6141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds siginfo.si_signo = SIGILL; 6151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds siginfo.si_code = ILL_BADIADDR; 6161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds siginfo.si_errno = 0; 6171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds siginfo.si_flags = 0; 6181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds siginfo.si_isr = 0; 6191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds siginfo.si_imm = 0; 6201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds siginfo.si_addr = (void __user *) iip; 6211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds force_sig_info(SIGILL, &siginfo, current); 6221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return; 6231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 6241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sprintf(buf, "Unimplemented Instruction Address fault"); 6251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 6261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 6271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case 45: 6291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk(KERN_ERR "Unexpected IA-32 exception (Trap 45)\n"); 6301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk(KERN_ERR " iip - 0x%lx, ifa - 0x%lx, isr - 0x%lx\n", 6311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds iip, ifa, isr); 6321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds force_sig(SIGSEGV, current); 633169ec523c34212f6e382186bce88f17eba4cad49Chen Gang return; 6341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case 46: 6361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk(KERN_ERR "Unexpected IA-32 intercept trap (Trap 46)\n"); 6371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk(KERN_ERR " iip - 0x%lx, ifa - 0x%lx, isr - 0x%lx, iim - 0x%lx\n", 6381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds iip, ifa, isr, iim); 6391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds force_sig(SIGSEGV, current); 6401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return; 6411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case 47: 6431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sprintf(buf, "IA-32 Interruption Fault (int 0x%lx)", isr >> 16); 6441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 6451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds default: 6471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sprintf(buf, "Fault %lu", vector); 6481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 6491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 650620de2f5dc697f906408743b1139fe5fb7b0b7f8Jan Beulich if (!die_if_kernel(buf, ®s, error)) 651620de2f5dc697f906408743b1139fe5fb7b0b7f8Jan Beulich force_sig(SIGILL, current); 6521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 653