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/config.h>
11 #include <linux/kernel.h>
12 #include <linux/init.h>
13 #include <linux/sched.h>
14 #include <linux/tty.h>
15 #include <linux/vt_kern.h> /* For unblank_screen() */
16 #include <linux/module.h> /* for EXPORT_SYMBOL */
18 #include <asm/fpswa.h>
19 #include <asm/hardirq.h>
21 #include <asm/intrinsics.h>
22 #include <asm/processor.h>
23 #include <asm/uaccess.h>
25 extern spinlock_t timerlist_lock;
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 * Unlock any spinlocks which will prevent us from getting the message out (timerlist_lock
40 * is acquired through the console unblank code)
43 bust_spinlocks (int yes)
45 int loglevel_save = console_loglevel;
57 * OK, the message is on the console. Now we call printk() without
58 * oops_in_progress set so that printk will give klogd a poke. Hold onto
61 console_loglevel = 15; /* NMI oopser may have shut the console up */
63 console_loglevel = loglevel_save;
67 die (const char *str, struct pt_regs *regs, long err)
74 .lock = SPIN_LOCK_UNLOCKED,
78 static int die_counter;
80 if (die.lock_owner != smp_processor_id()) {
82 spin_lock_irq(&die.lock);
83 die.lock_owner = smp_processor_id();
84 die.lock_owner_depth = 0;
88 if (++die.lock_owner_depth < 3) {
89 printk("%s[%d]: %s %ld [%d]\n",
90 current->comm, current->pid, str, err, ++die_counter);
93 printk(KERN_ERR "Recursive die() failure, output suppressed\n");
100 panic("Fatal exception");
104 spin_unlock_irq(&die.lock);
109 die_if_kernel (char *str, struct pt_regs *regs, long err)
111 if (!user_mode(regs))
116 ia64_bad_break (unsigned long break_num, struct pt_regs *regs)
121 /* SIGILL, SIGFPE, SIGSEGV, and SIGBUS want these field initialized: */
122 siginfo.si_addr = (void *) (regs->cr_iip + ia64_psr(regs)->ri);
123 siginfo.si_imm = break_num;
124 siginfo.si_flags = 0; /* clear __ISR_VALID */
128 case 0: /* unknown error (used by GCC for __builtin_abort()) */
129 die_if_kernel("bugcheck!", regs, break_num);
130 sig = SIGILL; code = ILL_ILLOPC;
133 case 1: /* integer divide by zero */
134 sig = SIGFPE; code = FPE_INTDIV;
137 case 2: /* integer overflow */
138 sig = SIGFPE; code = FPE_INTOVF;
141 case 3: /* range check/bounds check */
142 sig = SIGFPE; code = FPE_FLTSUB;
145 case 4: /* null pointer dereference */
146 sig = SIGSEGV; code = SEGV_MAPERR;
149 case 5: /* misaligned data */
150 sig = SIGSEGV; code = BUS_ADRALN;
153 case 6: /* decimal overflow */
154 sig = SIGFPE; code = __FPE_DECOVF;
157 case 7: /* decimal divide by zero */
158 sig = SIGFPE; code = __FPE_DECDIV;
161 case 8: /* packed decimal error */
162 sig = SIGFPE; code = __FPE_DECERR;
165 case 9: /* invalid ASCII digit */
166 sig = SIGFPE; code = __FPE_INVASC;
169 case 10: /* invalid decimal digit */
170 sig = SIGFPE; code = __FPE_INVDEC;
173 case 11: /* paragraph stack overflow */
174 sig = SIGSEGV; code = __SEGV_PSTKOVF;
177 case 0x3f000 ... 0x3ffff: /* bundle-update in progress */
178 sig = SIGILL; code = __ILL_BNDMOD;
182 if (break_num < 0x40000 || break_num > 0x100000)
183 die_if_kernel("Bad break", regs, break_num);
185 if (break_num < 0x80000) {
186 sig = SIGILL; code = __ILL_BREAK;
188 sig = SIGTRAP; code = TRAP_BRKPT;
191 siginfo.si_signo = sig;
192 siginfo.si_errno = 0;
193 siginfo.si_code = code;
194 force_sig_info(sig, &siginfo, current);
198 * disabled_fph_fault() is called when a user-level process attempts to access f32..f127
199 * and it doesn't own the fp-high register partition. When this happens, we save the
200 * current fph partition in the task_struct of the fpu-owner (if necessary) and then load
201 * the fp-high partition of the current task (if necessary). Note that the kernel has
202 * access to fph by the time we get here, as the IVT's "Disabled FP-Register" handler takes
203 * care of clearing psr.dfh.
206 disabled_fph_fault (struct pt_regs *regs)
208 struct ia64_psr *psr = ia64_psr(regs);
210 /* first, grant user-level access to fph partition: */
214 struct task_struct *fpu_owner
215 = (struct task_struct *)ia64_get_kr(IA64_KR_FPU_OWNER);
217 if (ia64_is_local_fpu_owner(current))
221 ia64_flush_fph(fpu_owner);
223 #endif /* !CONFIG_SMP */
224 ia64_set_local_fpu_owner(current);
225 if ((current->thread.flags & IA64_THREAD_FPH_VALID) != 0) {
226 __ia64_load_fpu(current->thread.fph);
231 * Set mfh because the state in thread.fph does not match the state in
239 fp_emulate (int fp_fault, void *bundle, long *ipsr, long *fpsr, long *isr, long *pr, long *ifs,
240 struct pt_regs *regs)
245 if (!fpswa_interface)
248 memset(&fp_state, 0, sizeof(fp_state_t));
251 * compute fp_state. only FP registers f6 - f11 are used by the
252 * kernel, so set those bits in the mask and set the low volatile
253 * pointer to point to these registers.
255 fp_state.bitmask_low64 = 0xfc0; /* bit6..bit11 */
257 fp_state.fp_state_low_volatile = (fp_state_low_volatile_t *) ®s->f6;
259 * unsigned long (*EFI_FPSWA) (
260 * unsigned long trap_type,
262 * unsigned long *pipsr,
263 * unsigned long *pfsr,
264 * unsigned long *pisr,
265 * unsigned long *ppreds,
266 * unsigned long *pifs,
269 ret = (*fpswa_interface->fpswa)((unsigned long) fp_fault, bundle,
270 (unsigned long *) ipsr, (unsigned long *) fpsr,
271 (unsigned long *) isr, (unsigned long *) pr,
272 (unsigned long *) ifs, &fp_state);
278 * Handle floating-point assist faults and traps.
281 handle_fpu_swa (int fp_fault, struct pt_regs *regs, unsigned long isr)
283 long exception, bundle[2];
284 unsigned long fault_ip;
285 struct siginfo siginfo;
286 static int fpu_swa_count = 0;
287 static unsigned long last_time;
289 fault_ip = regs->cr_iip;
290 if (!fp_fault && (ia64_psr(regs)->ri == 0))
292 if (copy_from_user(bundle, (void *) fault_ip, sizeof(bundle)))
295 if (jiffies - last_time > 5*HZ)
297 if ((fpu_swa_count < 4) && !(current->thread.flags & IA64_THREAD_FPEMU_NOPRINT)) {
301 "%s(%d): floating-point assist fault at ip %016lx, isr %016lx\n",
302 current->comm, current->pid, regs->cr_iip + ia64_psr(regs)->ri, isr);
305 exception = fp_emulate(fp_fault, bundle, ®s->cr_ipsr, ®s->ar_fpsr, &isr, ®s->pr,
306 ®s->cr_ifs, regs);
308 if (exception == 0) {
309 /* emulation was successful */
310 ia64_increment_ip(regs);
311 } else if (exception == -1) {
312 printk(KERN_ERR "handle_fpu_swa: fp_emulate() returned -1\n");
315 /* is next instruction a trap? */
317 ia64_increment_ip(regs);
319 siginfo.si_signo = SIGFPE;
320 siginfo.si_errno = 0;
321 siginfo.si_code = __SI_FAULT; /* default code */
322 siginfo.si_addr = (void *) (regs->cr_iip + ia64_psr(regs)->ri);
324 siginfo.si_code = FPE_FLTINV;
325 } else if (isr & 0x22) {
326 /* denormal operand gets the same si_code as underflow
327 * see arch/i386/kernel/traps.c:math_error() */
328 siginfo.si_code = FPE_FLTUND;
329 } else if (isr & 0x44) {
330 siginfo.si_code = FPE_FLTDIV;
332 siginfo.si_isr = isr;
333 siginfo.si_flags = __ISR_VALID;
335 force_sig_info(SIGFPE, &siginfo, current);
338 if (exception == -1) {
339 printk(KERN_ERR "handle_fpu_swa: fp_emulate() returned -1\n");
341 } else if (exception != 0) {
342 /* raise exception */
343 siginfo.si_signo = SIGFPE;
344 siginfo.si_errno = 0;
345 siginfo.si_code = __SI_FAULT; /* default code */
346 siginfo.si_addr = (void *) (regs->cr_iip + ia64_psr(regs)->ri);
348 siginfo.si_code = FPE_FLTOVF;
349 } else if (isr & 0x1100) {
350 siginfo.si_code = FPE_FLTUND;
351 } else if (isr & 0x2200) {
352 siginfo.si_code = FPE_FLTRES;
354 siginfo.si_isr = isr;
355 siginfo.si_flags = __ISR_VALID;
357 force_sig_info(SIGFPE, &siginfo, current);
363 struct illegal_op_return {
364 unsigned long fkt, arg1, arg2, arg3;
367 struct illegal_op_return
368 ia64_illegal_op_fault (unsigned long ec, unsigned long arg1, unsigned long arg2,
369 unsigned long arg3, unsigned long arg4, unsigned long arg5,
370 unsigned long arg6, unsigned long arg7, unsigned long stack)
372 struct pt_regs *regs = (struct pt_regs *) &stack;
373 struct illegal_op_return rv;
377 #ifdef CONFIG_IA64_BRL_EMU
379 extern struct illegal_op_return ia64_emulate_brl (struct pt_regs *, unsigned long);
381 rv = ia64_emulate_brl(regs, ec);
382 if (rv.fkt != (unsigned long) -1)
387 sprintf(buf, "IA-64 Illegal operation fault");
388 die_if_kernel(buf, regs, 0);
390 memset(&si, 0, sizeof(si));
391 si.si_signo = SIGILL;
392 si.si_code = ILL_ILLOPC;
393 si.si_addr = (void *) (regs->cr_iip + ia64_psr(regs)->ri);
394 force_sig_info(SIGILL, &si, current);
400 ia64_fault (unsigned long vector, unsigned long isr, unsigned long ifa,
401 unsigned long iim, unsigned long itir, unsigned long arg5,
402 unsigned long arg6, unsigned long arg7, unsigned long stack)
404 struct pt_regs *regs = (struct pt_regs *) &stack;
405 unsigned long code, error = isr;
406 struct siginfo siginfo;
409 static const char *reason[] = {
410 "IA-64 Illegal Operation fault",
411 "IA-64 Privileged Operation fault",
412 "IA-64 Privileged Register fault",
413 "IA-64 Reserved Register/Field fault",
414 "Disabled Instruction Set Transition fault",
415 "Unknown fault 5", "Unknown fault 6", "Unknown fault 7", "Illegal Hazard fault",
416 "Unknown fault 9", "Unknown fault 10", "Unknown fault 11", "Unknown fault 12",
417 "Unknown fault 13", "Unknown fault 14", "Unknown fault 15"
420 if ((isr & IA64_ISR_NA) && ((isr & IA64_ISR_CODE_MASK) == IA64_ISR_CODE_LFETCH)) {
422 * This fault was due to lfetch.fault, set "ed" bit in the psr to cancel
425 ia64_psr(regs)->ed = 1;
430 case 24: /* General Exception */
431 code = (isr >> 4) & 0xf;
432 sprintf(buf, "General Exception: %s%s", reason[code],
433 (code == 3) ? ((isr & (1UL << 37))
434 ? " (RSE access)" : " (data access)") : "");
436 # ifdef CONFIG_IA64_PRINT_HAZARDS
437 printk("%s[%d]: possible hazard @ ip=%016lx (pr = %016lx)\n",
438 current->comm, current->pid, regs->cr_iip + ia64_psr(regs)->ri,
445 case 25: /* Disabled FP-Register */
447 disabled_fph_fault(regs);
450 sprintf(buf, "Disabled FPL fault---not supposed to happen!");
453 case 26: /* NaT Consumption */
454 if (user_mode(regs)) {
457 if (((isr >> 4) & 0xf) == 2) {
458 /* NaT page consumption */
463 /* register NaT consumption */
466 addr = (void *) (regs->cr_iip + ia64_psr(regs)->ri);
468 siginfo.si_signo = sig;
469 siginfo.si_code = code;
470 siginfo.si_errno = 0;
471 siginfo.si_addr = addr;
472 siginfo.si_imm = vector;
473 siginfo.si_flags = __ISR_VALID;
474 siginfo.si_isr = isr;
475 force_sig_info(sig, &siginfo, current);
477 } else if (ia64_done_with_exception(regs))
479 sprintf(buf, "NaT consumption");
482 case 31: /* Unsupported Data Reference */
483 if (user_mode(regs)) {
484 siginfo.si_signo = SIGILL;
485 siginfo.si_code = ILL_ILLOPN;
486 siginfo.si_errno = 0;
487 siginfo.si_addr = (void *) (regs->cr_iip + ia64_psr(regs)->ri);
488 siginfo.si_imm = vector;
489 siginfo.si_flags = __ISR_VALID;
490 siginfo.si_isr = isr;
491 force_sig_info(SIGILL, &siginfo, current);
494 sprintf(buf, "Unsupported data reference");
498 case 35: /* Taken Branch Trap */
499 case 36: /* Single Step Trap */
500 if (fsys_mode(current, regs)) {
501 extern char __kernel_syscall_via_break[];
503 * Got a trap in fsys-mode: Taken Branch Trap and Single Step trap
504 * need special handling; Debug trap is not supposed to happen.
506 if (unlikely(vector == 29)) {
507 die("Got debug trap in fsys-mode---not supposed to happen!",
511 /* re-do the system call via break 0x100000: */
512 regs->cr_iip = (unsigned long) __kernel_syscall_via_break;
513 ia64_psr(regs)->ri = 0;
514 ia64_psr(regs)->cpl = 3;
519 siginfo.si_code = TRAP_HWBKPT;
520 #ifdef CONFIG_ITANIUM
522 * Erratum 10 (IFA may contain incorrect address) now has
523 * "NoFix" status. There are no plans for fixing this.
525 if (ia64_psr(regs)->is == 0)
529 case 35: siginfo.si_code = TRAP_BRANCH; ifa = 0; break;
530 case 36: siginfo.si_code = TRAP_TRACE; ifa = 0; break;
532 siginfo.si_signo = SIGTRAP;
533 siginfo.si_errno = 0;
534 siginfo.si_addr = (void *) ifa;
536 siginfo.si_flags = __ISR_VALID;
537 siginfo.si_isr = isr;
538 force_sig_info(SIGTRAP, &siginfo, current);
541 case 32: /* fp fault */
542 case 33: /* fp trap */
543 result = handle_fpu_swa((vector == 32) ? 1 : 0, regs, isr);
544 if ((result < 0) || (current->thread.flags & IA64_THREAD_FPEMU_SIGFPE)) {
545 siginfo.si_signo = SIGFPE;
546 siginfo.si_errno = 0;
547 siginfo.si_code = FPE_FLTINV;
548 siginfo.si_addr = (void *) (regs->cr_iip + ia64_psr(regs)->ri);
549 siginfo.si_flags = __ISR_VALID;
550 siginfo.si_isr = isr;
552 force_sig_info(SIGFPE, &siginfo, current);
558 /* Lower-Privilege Transfer Trap */
560 * Just clear PSR.lp and then return immediately: all the
561 * interesting work (e.g., signal delivery is done in the kernel
564 ia64_psr(regs)->lp = 0;
567 /* Unimplemented Instr. Address Trap */
568 if (user_mode(regs)) {
569 siginfo.si_signo = SIGILL;
570 siginfo.si_code = ILL_BADIADDR;
571 siginfo.si_errno = 0;
572 siginfo.si_flags = 0;
575 siginfo.si_addr = (void *) (regs->cr_iip + ia64_psr(regs)->ri);
576 force_sig_info(SIGILL, &siginfo, current);
579 sprintf(buf, "Unimplemented Instruction Address fault");
584 #ifdef CONFIG_IA32_SUPPORT
585 if (ia32_exception(regs, isr) == 0)
588 printk(KERN_ERR "Unexpected IA-32 exception (Trap 45)\n");
589 printk(KERN_ERR " iip - 0x%lx, ifa - 0x%lx, isr - 0x%lx\n",
590 regs->cr_iip, ifa, isr);
591 force_sig(SIGSEGV, current);
595 #ifdef CONFIG_IA32_SUPPORT
596 if (ia32_intercept(regs, isr) == 0)
599 printk(KERN_ERR "Unexpected IA-32 intercept trap (Trap 46)\n");
600 printk(KERN_ERR " iip - 0x%lx, ifa - 0x%lx, isr - 0x%lx, iim - 0x%lx\n",
601 regs->cr_iip, ifa, isr, iim);
602 force_sig(SIGSEGV, current);
606 sprintf(buf, "IA-32 Interruption Fault (int 0x%lx)", isr >> 16);
610 sprintf(buf, "Fault %lu", vector);
613 die_if_kernel(buf, regs, error);
614 force_sig(SIGILL, current);