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 *) &regs->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, &regs->cr_ipsr, &regs->ar_fpsr, &isr, &regs->pr,
3341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			       &regs->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(&regs, 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, &regs, 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(&regs)->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(&regs)->ed = 1;
4531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return;
4541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
4551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	iip = regs.cr_iip + ia64_psr(&regs)->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(&regs)->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(&regs);
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(&regs)) {
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(&regs)->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(&regs))
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(&regs)) {
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, &regs)) {
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(&regs)->db = 0;
54115029285dc977a392e74eacb7625984b71d4f605Jason Uhlenkott				ia64_psr(&regs)->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(&regs)->ri = 0;
5471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			ia64_psr(&regs)->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(&regs)->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", &regs, 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, &regs, 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(&regs)->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(&regs)->lp = 0;
6101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			return;
6111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		} else {
6121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			/* Unimplemented Instr. Address Trap */
6131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if (user_mode(&regs)) {
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, &regs, error))
651620de2f5dc697f906408743b1139fe5fb7b0b7f8Jan Beulich		force_sig(SIGILL, current);
6521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
653