2 * Architecture-specific trap handling.
4 * Copyright (C) 1998-2003 Hewlett-Packard Co
5 * David Mosberger-Tang <davidm@hpl.hp.com>
7 * 05/12/00 grao <goutham.rao@intel.com> : added isr in siginfo for SIGFPE
10 #include <linux/kernel.h>
11 #include <linux/init.h>
12 #include <linux/sched.h>
13 #include <linux/tty.h>
14 #include <linux/vt_kern.h> /* For unblank_screen() */
15 #include <linux/module.h> /* for EXPORT_SYMBOL */
16 #include <linux/hardirq.h>
17 #include <linux/kprobes.h>
18 #include <linux/delay.h> /* for ssleep() */
19 #include <linux/kdebug.h>
21 #include <asm/fpswa.h>
23 #include <asm/intrinsics.h>
24 #include <asm/processor.h>
25 #include <asm/uaccess.h>
27 fpswa_interface_t *fpswa_interface;
28 EXPORT_SYMBOL(fpswa_interface);
33 if (ia64_boot_param->fpswa)
34 /* FPSWA fixup: make the interface pointer a kernel virtual address: */
35 fpswa_interface = __va(ia64_boot_param->fpswa);
39 die (const char *str, struct pt_regs *regs, long err)
46 .lock = __SPIN_LOCK_UNLOCKED(die.lock),
50 static int die_counter;
53 if (die.lock_owner != cpu) {
55 spin_lock_irq(&die.lock);
57 die.lock_owner_depth = 0;
62 if (++die.lock_owner_depth < 3) {
63 printk("%s[%d]: %s %ld [%d]\n",
64 current->comm, current->pid, str, err, ++die_counter);
65 (void) notify_die(DIE_OOPS, (char *)str, regs, err, 255, SIGSEGV);
68 printk(KERN_ERR "Recursive die() failure, output suppressed\n");
73 spin_unlock_irq(&die.lock);
76 panic("Fatal exception");
82 die_if_kernel (char *str, struct pt_regs *regs, long err)
89 __kprobes ia64_bad_break (unsigned long break_num, struct pt_regs *regs)
94 /* SIGILL, SIGFPE, SIGSEGV, and SIGBUS want these field initialized: */
95 siginfo.si_addr = (void __user *) (regs->cr_iip + ia64_psr(regs)->ri);
96 siginfo.si_imm = break_num;
97 siginfo.si_flags = 0; /* clear __ISR_VALID */
101 case 0: /* unknown error (used by GCC for __builtin_abort()) */
102 if (notify_die(DIE_BREAK, "break 0", regs, break_num, TRAP_BRKPT, SIGTRAP)
105 die_if_kernel("bugcheck!", regs, break_num);
106 sig = SIGILL; code = ILL_ILLOPC;
109 case 1: /* integer divide by zero */
110 sig = SIGFPE; code = FPE_INTDIV;
113 case 2: /* integer overflow */
114 sig = SIGFPE; code = FPE_INTOVF;
117 case 3: /* range check/bounds check */
118 sig = SIGFPE; code = FPE_FLTSUB;
121 case 4: /* null pointer dereference */
122 sig = SIGSEGV; code = SEGV_MAPERR;
125 case 5: /* misaligned data */
126 sig = SIGSEGV; code = BUS_ADRALN;
129 case 6: /* decimal overflow */
130 sig = SIGFPE; code = __FPE_DECOVF;
133 case 7: /* decimal divide by zero */
134 sig = SIGFPE; code = __FPE_DECDIV;
137 case 8: /* packed decimal error */
138 sig = SIGFPE; code = __FPE_DECERR;
141 case 9: /* invalid ASCII digit */
142 sig = SIGFPE; code = __FPE_INVASC;
145 case 10: /* invalid decimal digit */
146 sig = SIGFPE; code = __FPE_INVDEC;
149 case 11: /* paragraph stack overflow */
150 sig = SIGSEGV; code = __SEGV_PSTKOVF;
153 case 0x3f000 ... 0x3ffff: /* bundle-update in progress */
154 sig = SIGILL; code = __ILL_BNDMOD;
158 if (break_num < 0x40000 || break_num > 0x100000)
159 die_if_kernel("Bad break", regs, break_num);
161 if (break_num < 0x80000) {
162 sig = SIGILL; code = __ILL_BREAK;
164 if (notify_die(DIE_BREAK, "bad break", regs, break_num, TRAP_BRKPT, SIGTRAP)
167 sig = SIGTRAP; code = TRAP_BRKPT;
170 siginfo.si_signo = sig;
171 siginfo.si_errno = 0;
172 siginfo.si_code = code;
173 force_sig_info(sig, &siginfo, current);
177 * disabled_fph_fault() is called when a user-level process attempts to access f32..f127
178 * and it doesn't own the fp-high register partition. When this happens, we save the
179 * current fph partition in the task_struct of the fpu-owner (if necessary) and then load
180 * the fp-high partition of the current task (if necessary). Note that the kernel has
181 * access to fph by the time we get here, as the IVT's "Disabled FP-Register" handler takes
182 * care of clearing psr.dfh.
185 disabled_fph_fault (struct pt_regs *regs)
187 struct ia64_psr *psr = ia64_psr(regs);
189 /* first, grant user-level access to fph partition: */
193 * Make sure that no other task gets in on this processor
194 * while we're claiming the FPU
199 struct task_struct *fpu_owner
200 = (struct task_struct *)ia64_get_kr(IA64_KR_FPU_OWNER);
202 if (ia64_is_local_fpu_owner(current)) {
203 preempt_enable_no_resched();
208 ia64_flush_fph(fpu_owner);
210 #endif /* !CONFIG_SMP */
211 ia64_set_local_fpu_owner(current);
212 if ((current->thread.flags & IA64_THREAD_FPH_VALID) != 0) {
213 __ia64_load_fpu(current->thread.fph);
218 * Set mfh because the state in thread.fph does not match the state in
223 preempt_enable_no_resched();
227 fp_emulate (int fp_fault, void *bundle, long *ipsr, long *fpsr, long *isr, long *pr, long *ifs,
228 struct pt_regs *regs)
233 if (!fpswa_interface)
236 memset(&fp_state, 0, sizeof(fp_state_t));
239 * compute fp_state. only FP registers f6 - f11 are used by the
240 * kernel, so set those bits in the mask and set the low volatile
241 * pointer to point to these registers.
243 fp_state.bitmask_low64 = 0xfc0; /* bit6..bit11 */
245 fp_state.fp_state_low_volatile = (fp_state_low_volatile_t *) ®s->f6;
247 * unsigned long (*EFI_FPSWA) (
248 * unsigned long trap_type,
250 * unsigned long *pipsr,
251 * unsigned long *pfsr,
252 * unsigned long *pisr,
253 * unsigned long *ppreds,
254 * unsigned long *pifs,
257 ret = (*fpswa_interface->fpswa)((unsigned long) fp_fault, bundle,
258 (unsigned long *) ipsr, (unsigned long *) fpsr,
259 (unsigned long *) isr, (unsigned long *) pr,
260 (unsigned long *) ifs, &fp_state);
269 static DEFINE_PER_CPU(struct fpu_swa_msg, cpulast);
270 DECLARE_PER_CPU(struct fpu_swa_msg, cpulast);
271 static struct fpu_swa_msg last __cacheline_aligned;
275 * Handle floating-point assist faults and traps.
278 handle_fpu_swa (int fp_fault, struct pt_regs *regs, unsigned long isr)
280 long exception, bundle[2];
281 unsigned long fault_ip;
282 struct siginfo siginfo;
284 fault_ip = regs->cr_iip;
285 if (!fp_fault && (ia64_psr(regs)->ri == 0))
287 if (copy_from_user(bundle, (void __user *) fault_ip, sizeof(bundle)))
290 if (!(current->thread.flags & IA64_THREAD_FPEMU_NOPRINT)) {
291 unsigned long count, current_jiffies = jiffies;
292 struct fpu_swa_msg *cp = &__get_cpu_var(cpulast);
294 if (unlikely(current_jiffies > cp->time))
296 if (unlikely(cp->count < 5)) {
298 cp->time = current_jiffies + 5 * HZ;
300 /* minimize races by grabbing a copy of count BEFORE checking last.time. */
305 * Lower 4 bits are used as a count. Upper bits are a sequence
306 * number that is updated when count is reset. The cmpxchg will
307 * fail is seqno has changed. This minimizes mutiple cpus
308 * resetting the count.
310 if (current_jiffies > last.time)
311 (void) cmpxchg_acq(&last.count, count, 16 + (count & ~15));
313 /* used fetchadd to atomically update the count */
314 if ((last.count & 15) < 5 && (ia64_fetchadd(1, &last.count, acq) & 15) < 5) {
315 last.time = current_jiffies + 5 * HZ;
317 "%s(%d): floating-point assist fault at ip %016lx, isr %016lx\n",
318 current->comm, current->pid, regs->cr_iip + ia64_psr(regs)->ri, isr);
323 exception = fp_emulate(fp_fault, bundle, ®s->cr_ipsr, ®s->ar_fpsr, &isr, ®s->pr,
324 ®s->cr_ifs, regs);
326 if (exception == 0) {
327 /* emulation was successful */
328 ia64_increment_ip(regs);
329 } else if (exception == -1) {
330 printk(KERN_ERR "handle_fpu_swa: fp_emulate() returned -1\n");
333 /* is next instruction a trap? */
335 ia64_increment_ip(regs);
337 siginfo.si_signo = SIGFPE;
338 siginfo.si_errno = 0;
339 siginfo.si_code = __SI_FAULT; /* default code */
340 siginfo.si_addr = (void __user *) (regs->cr_iip + ia64_psr(regs)->ri);
342 siginfo.si_code = FPE_FLTINV;
343 } else if (isr & 0x22) {
344 /* denormal operand gets the same si_code as underflow
345 * see arch/i386/kernel/traps.c:math_error() */
346 siginfo.si_code = FPE_FLTUND;
347 } else if (isr & 0x44) {
348 siginfo.si_code = FPE_FLTDIV;
350 siginfo.si_isr = isr;
351 siginfo.si_flags = __ISR_VALID;
353 force_sig_info(SIGFPE, &siginfo, current);
356 if (exception == -1) {
357 printk(KERN_ERR "handle_fpu_swa: fp_emulate() returned -1\n");
359 } else if (exception != 0) {
360 /* raise exception */
361 siginfo.si_signo = SIGFPE;
362 siginfo.si_errno = 0;
363 siginfo.si_code = __SI_FAULT; /* default code */
364 siginfo.si_addr = (void __user *) (regs->cr_iip + ia64_psr(regs)->ri);
366 siginfo.si_code = FPE_FLTOVF;
367 } else if (isr & 0x1100) {
368 siginfo.si_code = FPE_FLTUND;
369 } else if (isr & 0x2200) {
370 siginfo.si_code = FPE_FLTRES;
372 siginfo.si_isr = isr;
373 siginfo.si_flags = __ISR_VALID;
375 force_sig_info(SIGFPE, &siginfo, current);
381 struct illegal_op_return {
382 unsigned long fkt, arg1, arg2, arg3;
385 struct illegal_op_return
386 ia64_illegal_op_fault (unsigned long ec, long arg1, long arg2, long arg3,
387 long arg4, long arg5, long arg6, long arg7,
390 struct illegal_op_return rv;
394 #ifdef CONFIG_IA64_BRL_EMU
396 extern struct illegal_op_return ia64_emulate_brl (struct pt_regs *, unsigned long);
398 rv = ia64_emulate_brl(®s, ec);
399 if (rv.fkt != (unsigned long) -1)
404 sprintf(buf, "IA-64 Illegal operation fault");
405 die_if_kernel(buf, ®s, 0);
407 memset(&si, 0, sizeof(si));
408 si.si_signo = SIGILL;
409 si.si_code = ILL_ILLOPC;
410 si.si_addr = (void __user *) (regs.cr_iip + ia64_psr(®s)->ri);
411 force_sig_info(SIGILL, &si, current);
417 ia64_fault (unsigned long vector, unsigned long isr, unsigned long ifa,
418 unsigned long iim, unsigned long itir, long arg5, long arg6,
419 long arg7, struct pt_regs regs)
421 unsigned long code, error = isr, iip;
422 struct siginfo siginfo;
425 static const char *reason[] = {
426 "IA-64 Illegal Operation fault",
427 "IA-64 Privileged Operation fault",
428 "IA-64 Privileged Register fault",
429 "IA-64 Reserved Register/Field fault",
430 "Disabled Instruction Set Transition fault",
431 "Unknown fault 5", "Unknown fault 6", "Unknown fault 7", "Illegal Hazard fault",
432 "Unknown fault 9", "Unknown fault 10", "Unknown fault 11", "Unknown fault 12",
433 "Unknown fault 13", "Unknown fault 14", "Unknown fault 15"
436 if ((isr & IA64_ISR_NA) && ((isr & IA64_ISR_CODE_MASK) == IA64_ISR_CODE_LFETCH)) {
438 * This fault was due to lfetch.fault, set "ed" bit in the psr to cancel
441 ia64_psr(®s)->ed = 1;
445 iip = regs.cr_iip + ia64_psr(®s)->ri;
448 case 24: /* General Exception */
449 code = (isr >> 4) & 0xf;
450 sprintf(buf, "General Exception: %s%s", reason[code],
451 (code == 3) ? ((isr & (1UL << 37))
452 ? " (RSE access)" : " (data access)") : "");
454 # ifdef CONFIG_IA64_PRINT_HAZARDS
455 printk("%s[%d]: possible hazard @ ip=%016lx (pr = %016lx)\n",
456 current->comm, current->pid,
457 regs.cr_iip + ia64_psr(®s)->ri, regs.pr);
463 case 25: /* Disabled FP-Register */
465 disabled_fph_fault(®s);
468 sprintf(buf, "Disabled FPL fault---not supposed to happen!");
471 case 26: /* NaT Consumption */
472 if (user_mode(®s)) {
475 if (((isr >> 4) & 0xf) == 2) {
476 /* NaT page consumption */
479 addr = (void __user *) ifa;
481 /* register NaT consumption */
484 addr = (void __user *) (regs.cr_iip
485 + ia64_psr(®s)->ri);
487 siginfo.si_signo = sig;
488 siginfo.si_code = code;
489 siginfo.si_errno = 0;
490 siginfo.si_addr = addr;
491 siginfo.si_imm = vector;
492 siginfo.si_flags = __ISR_VALID;
493 siginfo.si_isr = isr;
494 force_sig_info(sig, &siginfo, current);
496 } else if (ia64_done_with_exception(®s))
498 sprintf(buf, "NaT consumption");
501 case 31: /* Unsupported Data Reference */
502 if (user_mode(®s)) {
503 siginfo.si_signo = SIGILL;
504 siginfo.si_code = ILL_ILLOPN;
505 siginfo.si_errno = 0;
506 siginfo.si_addr = (void __user *) iip;
507 siginfo.si_imm = vector;
508 siginfo.si_flags = __ISR_VALID;
509 siginfo.si_isr = isr;
510 force_sig_info(SIGILL, &siginfo, current);
513 sprintf(buf, "Unsupported data reference");
517 case 35: /* Taken Branch Trap */
518 case 36: /* Single Step Trap */
519 if (fsys_mode(current, ®s)) {
520 extern char __kernel_syscall_via_break[];
522 * Got a trap in fsys-mode: Taken Branch Trap
523 * and Single Step trap need special handling;
524 * Debug trap is ignored (we disable it here
525 * and re-enable it in the lower-privilege trap).
527 if (unlikely(vector == 29)) {
528 set_thread_flag(TIF_DB_DISABLED);
529 ia64_psr(®s)->db = 0;
530 ia64_psr(®s)->lp = 1;
533 /* re-do the system call via break 0x100000: */
534 regs.cr_iip = (unsigned long) __kernel_syscall_via_break;
535 ia64_psr(®s)->ri = 0;
536 ia64_psr(®s)->cpl = 3;
541 siginfo.si_code = TRAP_HWBKPT;
542 #ifdef CONFIG_ITANIUM
544 * Erratum 10 (IFA may contain incorrect address) now has
545 * "NoFix" status. There are no plans for fixing this.
547 if (ia64_psr(®s)->is == 0)
551 case 35: siginfo.si_code = TRAP_BRANCH; ifa = 0; break;
552 case 36: siginfo.si_code = TRAP_TRACE; ifa = 0; break;
554 if (notify_die(DIE_FAULT, "ia64_fault", ®s, vector, siginfo.si_code, SIGTRAP)
557 siginfo.si_signo = SIGTRAP;
558 siginfo.si_errno = 0;
559 siginfo.si_addr = (void __user *) ifa;
561 siginfo.si_flags = __ISR_VALID;
562 siginfo.si_isr = isr;
563 force_sig_info(SIGTRAP, &siginfo, current);
566 case 32: /* fp fault */
567 case 33: /* fp trap */
568 result = handle_fpu_swa((vector == 32) ? 1 : 0, ®s, isr);
569 if ((result < 0) || (current->thread.flags & IA64_THREAD_FPEMU_SIGFPE)) {
570 siginfo.si_signo = SIGFPE;
571 siginfo.si_errno = 0;
572 siginfo.si_code = FPE_FLTINV;
573 siginfo.si_addr = (void __user *) iip;
574 siginfo.si_flags = __ISR_VALID;
575 siginfo.si_isr = isr;
577 force_sig_info(SIGFPE, &siginfo, current);
583 /* Lower-Privilege Transfer Trap */
585 /* If we disabled debug traps during an fsyscall,
586 * re-enable them here.
588 if (test_thread_flag(TIF_DB_DISABLED)) {
589 clear_thread_flag(TIF_DB_DISABLED);
590 ia64_psr(®s)->db = 1;
594 * Just clear PSR.lp and then return immediately:
595 * all the interesting work (e.g., signal delivery)
596 * is done in the kernel exit path.
598 ia64_psr(®s)->lp = 0;
601 /* Unimplemented Instr. Address Trap */
602 if (user_mode(®s)) {
603 siginfo.si_signo = SIGILL;
604 siginfo.si_code = ILL_BADIADDR;
605 siginfo.si_errno = 0;
606 siginfo.si_flags = 0;
609 siginfo.si_addr = (void __user *) iip;
610 force_sig_info(SIGILL, &siginfo, current);
613 sprintf(buf, "Unimplemented Instruction Address fault");
618 #ifdef CONFIG_IA32_SUPPORT
619 if (ia32_exception(®s, isr) == 0)
622 printk(KERN_ERR "Unexpected IA-32 exception (Trap 45)\n");
623 printk(KERN_ERR " iip - 0x%lx, ifa - 0x%lx, isr - 0x%lx\n",
625 force_sig(SIGSEGV, current);
629 #ifdef CONFIG_IA32_SUPPORT
630 if (ia32_intercept(®s, isr) == 0)
633 printk(KERN_ERR "Unexpected IA-32 intercept trap (Trap 46)\n");
634 printk(KERN_ERR " iip - 0x%lx, ifa - 0x%lx, isr - 0x%lx, iim - 0x%lx\n",
636 force_sig(SIGSEGV, current);
640 sprintf(buf, "IA-32 Interruption Fault (int 0x%lx)", isr >> 16);
644 sprintf(buf, "Fault %lu", vector);
647 die_if_kernel(buf, ®s, error);
648 force_sig(SIGILL, current);