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");
72 spin_unlock_irq(&die
.lock
);
75 panic("Fatal exception");
81 die_if_kernel (char *str
, struct pt_regs
*regs
, long err
)
88 __kprobes
ia64_bad_break (unsigned long break_num
, struct pt_regs
*regs
)
93 /* SIGILL, SIGFPE, SIGSEGV, and SIGBUS want these field initialized: */
94 siginfo
.si_addr
= (void __user
*) (regs
->cr_iip
+ ia64_psr(regs
)->ri
);
95 siginfo
.si_imm
= break_num
;
96 siginfo
.si_flags
= 0; /* clear __ISR_VALID */
100 case 0: /* unknown error (used by GCC for __builtin_abort()) */
101 if (notify_die(DIE_BREAK
, "break 0", regs
, break_num
, TRAP_BRKPT
, SIGTRAP
)
104 die_if_kernel("bugcheck!", regs
, break_num
);
105 sig
= SIGILL
; code
= ILL_ILLOPC
;
108 case 1: /* integer divide by zero */
109 sig
= SIGFPE
; code
= FPE_INTDIV
;
112 case 2: /* integer overflow */
113 sig
= SIGFPE
; code
= FPE_INTOVF
;
116 case 3: /* range check/bounds check */
117 sig
= SIGFPE
; code
= FPE_FLTSUB
;
120 case 4: /* null pointer dereference */
121 sig
= SIGSEGV
; code
= SEGV_MAPERR
;
124 case 5: /* misaligned data */
125 sig
= SIGSEGV
; code
= BUS_ADRALN
;
128 case 6: /* decimal overflow */
129 sig
= SIGFPE
; code
= __FPE_DECOVF
;
132 case 7: /* decimal divide by zero */
133 sig
= SIGFPE
; code
= __FPE_DECDIV
;
136 case 8: /* packed decimal error */
137 sig
= SIGFPE
; code
= __FPE_DECERR
;
140 case 9: /* invalid ASCII digit */
141 sig
= SIGFPE
; code
= __FPE_INVASC
;
144 case 10: /* invalid decimal digit */
145 sig
= SIGFPE
; code
= __FPE_INVDEC
;
148 case 11: /* paragraph stack overflow */
149 sig
= SIGSEGV
; code
= __SEGV_PSTKOVF
;
152 case 0x3f000 ... 0x3ffff: /* bundle-update in progress */
153 sig
= SIGILL
; code
= __ILL_BNDMOD
;
157 if (break_num
< 0x40000 || break_num
> 0x100000)
158 die_if_kernel("Bad break", regs
, break_num
);
160 if (break_num
< 0x80000) {
161 sig
= SIGILL
; code
= __ILL_BREAK
;
163 if (notify_die(DIE_BREAK
, "bad break", regs
, break_num
, TRAP_BRKPT
, SIGTRAP
)
166 sig
= SIGTRAP
; code
= TRAP_BRKPT
;
169 siginfo
.si_signo
= sig
;
170 siginfo
.si_errno
= 0;
171 siginfo
.si_code
= code
;
172 force_sig_info(sig
, &siginfo
, current
);
176 * disabled_fph_fault() is called when a user-level process attempts to access f32..f127
177 * and it doesn't own the fp-high register partition. When this happens, we save the
178 * current fph partition in the task_struct of the fpu-owner (if necessary) and then load
179 * the fp-high partition of the current task (if necessary). Note that the kernel has
180 * access to fph by the time we get here, as the IVT's "Disabled FP-Register" handler takes
181 * care of clearing psr.dfh.
184 disabled_fph_fault (struct pt_regs
*regs
)
186 struct ia64_psr
*psr
= ia64_psr(regs
);
188 /* first, grant user-level access to fph partition: */
192 * Make sure that no other task gets in on this processor
193 * while we're claiming the FPU
198 struct task_struct
*fpu_owner
199 = (struct task_struct
*)ia64_get_kr(IA64_KR_FPU_OWNER
);
201 if (ia64_is_local_fpu_owner(current
)) {
202 preempt_enable_no_resched();
207 ia64_flush_fph(fpu_owner
);
209 #endif /* !CONFIG_SMP */
210 ia64_set_local_fpu_owner(current
);
211 if ((current
->thread
.flags
& IA64_THREAD_FPH_VALID
) != 0) {
212 __ia64_load_fpu(current
->thread
.fph
);
217 * Set mfh because the state in thread.fph does not match the state in
222 preempt_enable_no_resched();
226 fp_emulate (int fp_fault
, void *bundle
, long *ipsr
, long *fpsr
, long *isr
, long *pr
, long *ifs
,
227 struct pt_regs
*regs
)
232 if (!fpswa_interface
)
235 memset(&fp_state
, 0, sizeof(fp_state_t
));
238 * compute fp_state. only FP registers f6 - f11 are used by the
239 * kernel, so set those bits in the mask and set the low volatile
240 * pointer to point to these registers.
242 fp_state
.bitmask_low64
= 0xfc0; /* bit6..bit11 */
244 fp_state
.fp_state_low_volatile
= (fp_state_low_volatile_t
*) ®s
->f6
;
246 * unsigned long (*EFI_FPSWA) (
247 * unsigned long trap_type,
249 * unsigned long *pipsr,
250 * unsigned long *pfsr,
251 * unsigned long *pisr,
252 * unsigned long *ppreds,
253 * unsigned long *pifs,
256 ret
= (*fpswa_interface
->fpswa
)((unsigned long) fp_fault
, bundle
,
257 (unsigned long *) ipsr
, (unsigned long *) fpsr
,
258 (unsigned long *) isr
, (unsigned long *) pr
,
259 (unsigned long *) ifs
, &fp_state
);
268 static DEFINE_PER_CPU(struct fpu_swa_msg
, cpulast
);
269 DECLARE_PER_CPU(struct fpu_swa_msg
, cpulast
);
270 static struct fpu_swa_msg last __cacheline_aligned
;
274 * Handle floating-point assist faults and traps.
277 handle_fpu_swa (int fp_fault
, struct pt_regs
*regs
, unsigned long isr
)
279 long exception
, bundle
[2];
280 unsigned long fault_ip
;
281 struct siginfo siginfo
;
283 fault_ip
= regs
->cr_iip
;
284 if (!fp_fault
&& (ia64_psr(regs
)->ri
== 0))
286 if (copy_from_user(bundle
, (void __user
*) fault_ip
, sizeof(bundle
)))
289 if (!(current
->thread
.flags
& IA64_THREAD_FPEMU_NOPRINT
)) {
290 unsigned long count
, current_jiffies
= jiffies
;
291 struct fpu_swa_msg
*cp
= &__get_cpu_var(cpulast
);
293 if (unlikely(current_jiffies
> cp
->time
))
295 if (unlikely(cp
->count
< 5)) {
297 cp
->time
= current_jiffies
+ 5 * HZ
;
299 /* minimize races by grabbing a copy of count BEFORE checking last.time. */
304 * Lower 4 bits are used as a count. Upper bits are a sequence
305 * number that is updated when count is reset. The cmpxchg will
306 * fail is seqno has changed. This minimizes mutiple cpus
307 * resetting the count.
309 if (current_jiffies
> last
.time
)
310 (void) cmpxchg_acq(&last
.count
, count
, 16 + (count
& ~15));
312 /* used fetchadd to atomically update the count */
313 if ((last
.count
& 15) < 5 && (ia64_fetchadd(1, &last
.count
, acq
) & 15) < 5) {
314 last
.time
= current_jiffies
+ 5 * HZ
;
316 "%s(%d): floating-point assist fault at ip %016lx, isr %016lx\n",
317 current
->comm
, current
->pid
, regs
->cr_iip
+ ia64_psr(regs
)->ri
, isr
);
322 exception
= fp_emulate(fp_fault
, bundle
, ®s
->cr_ipsr
, ®s
->ar_fpsr
, &isr
, ®s
->pr
,
323 ®s
->cr_ifs
, regs
);
325 if (exception
== 0) {
326 /* emulation was successful */
327 ia64_increment_ip(regs
);
328 } else if (exception
== -1) {
329 printk(KERN_ERR
"handle_fpu_swa: fp_emulate() returned -1\n");
332 /* is next instruction a trap? */
334 ia64_increment_ip(regs
);
336 siginfo
.si_signo
= SIGFPE
;
337 siginfo
.si_errno
= 0;
338 siginfo
.si_code
= __SI_FAULT
; /* default code */
339 siginfo
.si_addr
= (void __user
*) (regs
->cr_iip
+ ia64_psr(regs
)->ri
);
341 siginfo
.si_code
= FPE_FLTINV
;
342 } else if (isr
& 0x22) {
343 /* denormal operand gets the same si_code as underflow
344 * see arch/i386/kernel/traps.c:math_error() */
345 siginfo
.si_code
= FPE_FLTUND
;
346 } else if (isr
& 0x44) {
347 siginfo
.si_code
= FPE_FLTDIV
;
349 siginfo
.si_isr
= isr
;
350 siginfo
.si_flags
= __ISR_VALID
;
352 force_sig_info(SIGFPE
, &siginfo
, current
);
355 if (exception
== -1) {
356 printk(KERN_ERR
"handle_fpu_swa: fp_emulate() returned -1\n");
358 } else if (exception
!= 0) {
359 /* raise exception */
360 siginfo
.si_signo
= SIGFPE
;
361 siginfo
.si_errno
= 0;
362 siginfo
.si_code
= __SI_FAULT
; /* default code */
363 siginfo
.si_addr
= (void __user
*) (regs
->cr_iip
+ ia64_psr(regs
)->ri
);
365 siginfo
.si_code
= FPE_FLTOVF
;
366 } else if (isr
& 0x1100) {
367 siginfo
.si_code
= FPE_FLTUND
;
368 } else if (isr
& 0x2200) {
369 siginfo
.si_code
= FPE_FLTRES
;
371 siginfo
.si_isr
= isr
;
372 siginfo
.si_flags
= __ISR_VALID
;
374 force_sig_info(SIGFPE
, &siginfo
, current
);
380 struct illegal_op_return
{
381 unsigned long fkt
, arg1
, arg2
, arg3
;
384 struct illegal_op_return
385 ia64_illegal_op_fault (unsigned long ec
, long arg1
, long arg2
, long arg3
,
386 long arg4
, long arg5
, long arg6
, long arg7
,
389 struct illegal_op_return rv
;
393 #ifdef CONFIG_IA64_BRL_EMU
395 extern struct illegal_op_return
ia64_emulate_brl (struct pt_regs
*, unsigned long);
397 rv
= ia64_emulate_brl(®s
, ec
);
398 if (rv
.fkt
!= (unsigned long) -1)
403 sprintf(buf
, "IA-64 Illegal operation fault");
404 die_if_kernel(buf
, ®s
, 0);
406 memset(&si
, 0, sizeof(si
));
407 si
.si_signo
= SIGILL
;
408 si
.si_code
= ILL_ILLOPC
;
409 si
.si_addr
= (void __user
*) (regs
.cr_iip
+ ia64_psr(®s
)->ri
);
410 force_sig_info(SIGILL
, &si
, current
);
416 ia64_fault (unsigned long vector
, unsigned long isr
, unsigned long ifa
,
417 unsigned long iim
, unsigned long itir
, long arg5
, long arg6
,
418 long arg7
, struct pt_regs regs
)
420 unsigned long code
, error
= isr
, iip
;
421 struct siginfo siginfo
;
424 static const char *reason
[] = {
425 "IA-64 Illegal Operation fault",
426 "IA-64 Privileged Operation fault",
427 "IA-64 Privileged Register fault",
428 "IA-64 Reserved Register/Field fault",
429 "Disabled Instruction Set Transition fault",
430 "Unknown fault 5", "Unknown fault 6", "Unknown fault 7", "Illegal Hazard fault",
431 "Unknown fault 9", "Unknown fault 10", "Unknown fault 11", "Unknown fault 12",
432 "Unknown fault 13", "Unknown fault 14", "Unknown fault 15"
435 if ((isr
& IA64_ISR_NA
) && ((isr
& IA64_ISR_CODE_MASK
) == IA64_ISR_CODE_LFETCH
)) {
437 * This fault was due to lfetch.fault, set "ed" bit in the psr to cancel
440 ia64_psr(®s
)->ed
= 1;
444 iip
= regs
.cr_iip
+ ia64_psr(®s
)->ri
;
447 case 24: /* General Exception */
448 code
= (isr
>> 4) & 0xf;
449 sprintf(buf
, "General Exception: %s%s", reason
[code
],
450 (code
== 3) ? ((isr
& (1UL << 37))
451 ? " (RSE access)" : " (data access)") : "");
453 # ifdef CONFIG_IA64_PRINT_HAZARDS
454 printk("%s[%d]: possible hazard @ ip=%016lx (pr = %016lx)\n",
455 current
->comm
, current
->pid
,
456 regs
.cr_iip
+ ia64_psr(®s
)->ri
, regs
.pr
);
462 case 25: /* Disabled FP-Register */
464 disabled_fph_fault(®s
);
467 sprintf(buf
, "Disabled FPL fault---not supposed to happen!");
470 case 26: /* NaT Consumption */
471 if (user_mode(®s
)) {
474 if (((isr
>> 4) & 0xf) == 2) {
475 /* NaT page consumption */
478 addr
= (void __user
*) ifa
;
480 /* register NaT consumption */
483 addr
= (void __user
*) (regs
.cr_iip
484 + ia64_psr(®s
)->ri
);
486 siginfo
.si_signo
= sig
;
487 siginfo
.si_code
= code
;
488 siginfo
.si_errno
= 0;
489 siginfo
.si_addr
= addr
;
490 siginfo
.si_imm
= vector
;
491 siginfo
.si_flags
= __ISR_VALID
;
492 siginfo
.si_isr
= isr
;
493 force_sig_info(sig
, &siginfo
, current
);
495 } else if (ia64_done_with_exception(®s
))
497 sprintf(buf
, "NaT consumption");
500 case 31: /* Unsupported Data Reference */
501 if (user_mode(®s
)) {
502 siginfo
.si_signo
= SIGILL
;
503 siginfo
.si_code
= ILL_ILLOPN
;
504 siginfo
.si_errno
= 0;
505 siginfo
.si_addr
= (void __user
*) iip
;
506 siginfo
.si_imm
= vector
;
507 siginfo
.si_flags
= __ISR_VALID
;
508 siginfo
.si_isr
= isr
;
509 force_sig_info(SIGILL
, &siginfo
, current
);
512 sprintf(buf
, "Unsupported data reference");
516 case 35: /* Taken Branch Trap */
517 case 36: /* Single Step Trap */
518 if (fsys_mode(current
, ®s
)) {
519 extern char __kernel_syscall_via_break
[];
521 * Got a trap in fsys-mode: Taken Branch Trap
522 * and Single Step trap need special handling;
523 * Debug trap is ignored (we disable it here
524 * and re-enable it in the lower-privilege trap).
526 if (unlikely(vector
== 29)) {
527 set_thread_flag(TIF_DB_DISABLED
);
528 ia64_psr(®s
)->db
= 0;
529 ia64_psr(®s
)->lp
= 1;
532 /* re-do the system call via break 0x100000: */
533 regs
.cr_iip
= (unsigned long) __kernel_syscall_via_break
;
534 ia64_psr(®s
)->ri
= 0;
535 ia64_psr(®s
)->cpl
= 3;
540 siginfo
.si_code
= TRAP_HWBKPT
;
541 #ifdef CONFIG_ITANIUM
543 * Erratum 10 (IFA may contain incorrect address) now has
544 * "NoFix" status. There are no plans for fixing this.
546 if (ia64_psr(®s
)->is
== 0)
550 case 35: siginfo
.si_code
= TRAP_BRANCH
; ifa
= 0; break;
551 case 36: siginfo
.si_code
= TRAP_TRACE
; ifa
= 0; break;
553 if (notify_die(DIE_FAULT
, "ia64_fault", ®s
, vector
, siginfo
.si_code
, SIGTRAP
)
556 siginfo
.si_signo
= SIGTRAP
;
557 siginfo
.si_errno
= 0;
558 siginfo
.si_addr
= (void __user
*) ifa
;
560 siginfo
.si_flags
= __ISR_VALID
;
561 siginfo
.si_isr
= isr
;
562 force_sig_info(SIGTRAP
, &siginfo
, current
);
565 case 32: /* fp fault */
566 case 33: /* fp trap */
567 result
= handle_fpu_swa((vector
== 32) ? 1 : 0, ®s
, isr
);
568 if ((result
< 0) || (current
->thread
.flags
& IA64_THREAD_FPEMU_SIGFPE
)) {
569 siginfo
.si_signo
= SIGFPE
;
570 siginfo
.si_errno
= 0;
571 siginfo
.si_code
= FPE_FLTINV
;
572 siginfo
.si_addr
= (void __user
*) iip
;
573 siginfo
.si_flags
= __ISR_VALID
;
574 siginfo
.si_isr
= isr
;
576 force_sig_info(SIGFPE
, &siginfo
, current
);
582 /* Lower-Privilege Transfer Trap */
584 /* If we disabled debug traps during an fsyscall,
585 * re-enable them here.
587 if (test_thread_flag(TIF_DB_DISABLED
)) {
588 clear_thread_flag(TIF_DB_DISABLED
);
589 ia64_psr(®s
)->db
= 1;
593 * Just clear PSR.lp and then return immediately:
594 * all the interesting work (e.g., signal delivery)
595 * is done in the kernel exit path.
597 ia64_psr(®s
)->lp
= 0;
600 /* Unimplemented Instr. Address Trap */
601 if (user_mode(®s
)) {
602 siginfo
.si_signo
= SIGILL
;
603 siginfo
.si_code
= ILL_BADIADDR
;
604 siginfo
.si_errno
= 0;
605 siginfo
.si_flags
= 0;
608 siginfo
.si_addr
= (void __user
*) iip
;
609 force_sig_info(SIGILL
, &siginfo
, current
);
612 sprintf(buf
, "Unimplemented Instruction Address fault");
617 #ifdef CONFIG_IA32_SUPPORT
618 if (ia32_exception(®s
, isr
) == 0)
621 printk(KERN_ERR
"Unexpected IA-32 exception (Trap 45)\n");
622 printk(KERN_ERR
" iip - 0x%lx, ifa - 0x%lx, isr - 0x%lx\n",
624 force_sig(SIGSEGV
, current
);
628 #ifdef CONFIG_IA32_SUPPORT
629 if (ia32_intercept(®s
, isr
) == 0)
632 printk(KERN_ERR
"Unexpected IA-32 intercept trap (Trap 46)\n");
633 printk(KERN_ERR
" iip - 0x%lx, ifa - 0x%lx, isr - 0x%lx, iim - 0x%lx\n",
635 force_sig(SIGSEGV
, current
);
639 sprintf(buf
, "IA-32 Interruption Fault (int 0x%lx)", isr
>> 16);
643 sprintf(buf
, "Fault %lu", vector
);
646 die_if_kernel(buf
, ®s
, error
);
647 force_sig(SIGILL
, current
);