Linux-2.6.12-rc2
[cascardo/linux.git] / arch / ia64 / kernel / traps.c
1 /*
2  * Architecture-specific trap handling.
3  *
4  * Copyright (C) 1998-2003 Hewlett-Packard Co
5  *      David Mosberger-Tang <davidm@hpl.hp.com>
6  *
7  * 05/12/00 grao <goutham.rao@intel.com> : added isr in siginfo for SIGFPE
8  */
9
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 */
17 #include <linux/hardirq.h>
18
19 #include <asm/fpswa.h>
20 #include <asm/ia32.h>
21 #include <asm/intrinsics.h>
22 #include <asm/processor.h>
23 #include <asm/uaccess.h>
24
25 extern spinlock_t timerlist_lock;
26
27 fpswa_interface_t *fpswa_interface;
28 EXPORT_SYMBOL(fpswa_interface);
29
30 void __init
31 trap_init (void)
32 {
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);
36 }
37
38 /*
39  * Unlock any spinlocks which will prevent us from getting the message out (timerlist_lock
40  * is acquired through the console unblank code)
41  */
42 void
43 bust_spinlocks (int yes)
44 {
45         int loglevel_save = console_loglevel;
46
47         if (yes) {
48                 oops_in_progress = 1;
49                 return;
50         }
51
52 #ifdef CONFIG_VT
53         unblank_screen();
54 #endif
55         oops_in_progress = 0;
56         /*
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
59          * your hats...
60          */
61         console_loglevel = 15;          /* NMI oopser may have shut the console up */
62         printk(" ");
63         console_loglevel = loglevel_save;
64 }
65
66 void
67 die (const char *str, struct pt_regs *regs, long err)
68 {
69         static struct {
70                 spinlock_t lock;
71                 u32 lock_owner;
72                 int lock_owner_depth;
73         } die = {
74                 .lock =                 SPIN_LOCK_UNLOCKED,
75                 .lock_owner =           -1,
76                 .lock_owner_depth =     0
77         };
78         static int die_counter;
79
80         if (die.lock_owner != smp_processor_id()) {
81                 console_verbose();
82                 spin_lock_irq(&die.lock);
83                 die.lock_owner = smp_processor_id();
84                 die.lock_owner_depth = 0;
85                 bust_spinlocks(1);
86         }
87
88         if (++die.lock_owner_depth < 3) {
89                 printk("%s[%d]: %s %ld [%d]\n",
90                         current->comm, current->pid, str, err, ++die_counter);
91                 show_regs(regs);
92         } else
93                 printk(KERN_ERR "Recursive die() failure, output suppressed\n");
94
95         bust_spinlocks(0);
96         die.lock_owner = -1;
97         spin_unlock_irq(&die.lock);
98         do_exit(SIGSEGV);
99 }
100
101 void
102 die_if_kernel (char *str, struct pt_regs *regs, long err)
103 {
104         if (!user_mode(regs))
105                 die(str, regs, err);
106 }
107
108 void
109 ia64_bad_break (unsigned long break_num, struct pt_regs *regs)
110 {
111         siginfo_t siginfo;
112         int sig, code;
113
114         /* SIGILL, SIGFPE, SIGSEGV, and SIGBUS want these field initialized: */
115         siginfo.si_addr = (void __user *) (regs->cr_iip + ia64_psr(regs)->ri);
116         siginfo.si_imm = break_num;
117         siginfo.si_flags = 0;           /* clear __ISR_VALID */
118         siginfo.si_isr = 0;
119
120         switch (break_num) {
121               case 0: /* unknown error (used by GCC for __builtin_abort()) */
122                 die_if_kernel("bugcheck!", regs, break_num);
123                 sig = SIGILL; code = ILL_ILLOPC;
124                 break;
125
126               case 1: /* integer divide by zero */
127                 sig = SIGFPE; code = FPE_INTDIV;
128                 break;
129
130               case 2: /* integer overflow */
131                 sig = SIGFPE; code = FPE_INTOVF;
132                 break;
133
134               case 3: /* range check/bounds check */
135                 sig = SIGFPE; code = FPE_FLTSUB;
136                 break;
137
138               case 4: /* null pointer dereference */
139                 sig = SIGSEGV; code = SEGV_MAPERR;
140                 break;
141
142               case 5: /* misaligned data */
143                 sig = SIGSEGV; code = BUS_ADRALN;
144                 break;
145
146               case 6: /* decimal overflow */
147                 sig = SIGFPE; code = __FPE_DECOVF;
148                 break;
149
150               case 7: /* decimal divide by zero */
151                 sig = SIGFPE; code = __FPE_DECDIV;
152                 break;
153
154               case 8: /* packed decimal error */
155                 sig = SIGFPE; code = __FPE_DECERR;
156                 break;
157
158               case 9: /* invalid ASCII digit */
159                 sig = SIGFPE; code = __FPE_INVASC;
160                 break;
161
162               case 10: /* invalid decimal digit */
163                 sig = SIGFPE; code = __FPE_INVDEC;
164                 break;
165
166               case 11: /* paragraph stack overflow */
167                 sig = SIGSEGV; code = __SEGV_PSTKOVF;
168                 break;
169
170               case 0x3f000 ... 0x3ffff: /* bundle-update in progress */
171                 sig = SIGILL; code = __ILL_BNDMOD;
172                 break;
173
174               default:
175                 if (break_num < 0x40000 || break_num > 0x100000)
176                         die_if_kernel("Bad break", regs, break_num);
177
178                 if (break_num < 0x80000) {
179                         sig = SIGILL; code = __ILL_BREAK;
180                 } else {
181                         sig = SIGTRAP; code = TRAP_BRKPT;
182                 }
183         }
184         siginfo.si_signo = sig;
185         siginfo.si_errno = 0;
186         siginfo.si_code = code;
187         force_sig_info(sig, &siginfo, current);
188 }
189
190 /*
191  * disabled_fph_fault() is called when a user-level process attempts to access f32..f127
192  * and it doesn't own the fp-high register partition.  When this happens, we save the
193  * current fph partition in the task_struct of the fpu-owner (if necessary) and then load
194  * the fp-high partition of the current task (if necessary).  Note that the kernel has
195  * access to fph by the time we get here, as the IVT's "Disabled FP-Register" handler takes
196  * care of clearing psr.dfh.
197  */
198 static inline void
199 disabled_fph_fault (struct pt_regs *regs)
200 {
201         struct ia64_psr *psr = ia64_psr(regs);
202
203         /* first, grant user-level access to fph partition: */
204         psr->dfh = 0;
205 #ifndef CONFIG_SMP
206         {
207                 struct task_struct *fpu_owner
208                         = (struct task_struct *)ia64_get_kr(IA64_KR_FPU_OWNER);
209
210                 if (ia64_is_local_fpu_owner(current))
211                         return;
212
213                 if (fpu_owner)
214                         ia64_flush_fph(fpu_owner);
215         }
216 #endif /* !CONFIG_SMP */
217         ia64_set_local_fpu_owner(current);
218         if ((current->thread.flags & IA64_THREAD_FPH_VALID) != 0) {
219                 __ia64_load_fpu(current->thread.fph);
220                 psr->mfh = 0;
221         } else {
222                 __ia64_init_fpu();
223                 /*
224                  * Set mfh because the state in thread.fph does not match the state in
225                  * the fph partition.
226                  */
227                 psr->mfh = 1;
228         }
229 }
230
231 static inline int
232 fp_emulate (int fp_fault, void *bundle, long *ipsr, long *fpsr, long *isr, long *pr, long *ifs,
233             struct pt_regs *regs)
234 {
235         fp_state_t fp_state;
236         fpswa_ret_t ret;
237
238         if (!fpswa_interface)
239                 return -1;
240
241         memset(&fp_state, 0, sizeof(fp_state_t));
242
243         /*
244          * compute fp_state.  only FP registers f6 - f11 are used by the
245          * kernel, so set those bits in the mask and set the low volatile
246          * pointer to point to these registers.
247          */
248         fp_state.bitmask_low64 = 0xfc0;  /* bit6..bit11 */
249
250         fp_state.fp_state_low_volatile = (fp_state_low_volatile_t *) &regs->f6;
251         /*
252          * unsigned long (*EFI_FPSWA) (
253          *      unsigned long    trap_type,
254          *      void             *Bundle,
255          *      unsigned long    *pipsr,
256          *      unsigned long    *pfsr,
257          *      unsigned long    *pisr,
258          *      unsigned long    *ppreds,
259          *      unsigned long    *pifs,
260          *      void             *fp_state);
261          */
262         ret = (*fpswa_interface->fpswa)((unsigned long) fp_fault, bundle,
263                                         (unsigned long *) ipsr, (unsigned long *) fpsr,
264                                         (unsigned long *) isr, (unsigned long *) pr,
265                                         (unsigned long *) ifs, &fp_state);
266
267         return ret.status;
268 }
269
270 /*
271  * Handle floating-point assist faults and traps.
272  */
273 static int
274 handle_fpu_swa (int fp_fault, struct pt_regs *regs, unsigned long isr)
275 {
276         long exception, bundle[2];
277         unsigned long fault_ip;
278         struct siginfo siginfo;
279         static int fpu_swa_count = 0;
280         static unsigned long last_time;
281
282         fault_ip = regs->cr_iip;
283         if (!fp_fault && (ia64_psr(regs)->ri == 0))
284                 fault_ip -= 16;
285         if (copy_from_user(bundle, (void __user *) fault_ip, sizeof(bundle)))
286                 return -1;
287
288         if (jiffies - last_time > 5*HZ)
289                 fpu_swa_count = 0;
290         if ((fpu_swa_count < 4) && !(current->thread.flags & IA64_THREAD_FPEMU_NOPRINT)) {
291                 last_time = jiffies;
292                 ++fpu_swa_count;
293                 printk(KERN_WARNING
294                        "%s(%d): floating-point assist fault at ip %016lx, isr %016lx\n",
295                        current->comm, current->pid, regs->cr_iip + ia64_psr(regs)->ri, isr);
296         }
297
298         exception = fp_emulate(fp_fault, bundle, &regs->cr_ipsr, &regs->ar_fpsr, &isr, &regs->pr,
299                                &regs->cr_ifs, regs);
300         if (fp_fault) {
301                 if (exception == 0) {
302                         /* emulation was successful */
303                         ia64_increment_ip(regs);
304                 } else if (exception == -1) {
305                         printk(KERN_ERR "handle_fpu_swa: fp_emulate() returned -1\n");
306                         return -1;
307                 } else {
308                         /* is next instruction a trap? */
309                         if (exception & 2) {
310                                 ia64_increment_ip(regs);
311                         }
312                         siginfo.si_signo = SIGFPE;
313                         siginfo.si_errno = 0;
314                         siginfo.si_code = __SI_FAULT;   /* default code */
315                         siginfo.si_addr = (void __user *) (regs->cr_iip + ia64_psr(regs)->ri);
316                         if (isr & 0x11) {
317                                 siginfo.si_code = FPE_FLTINV;
318                         } else if (isr & 0x22) {
319                                 /* denormal operand gets the same si_code as underflow 
320                                 * see arch/i386/kernel/traps.c:math_error()  */
321                                 siginfo.si_code = FPE_FLTUND;
322                         } else if (isr & 0x44) {
323                                 siginfo.si_code = FPE_FLTDIV;
324                         }
325                         siginfo.si_isr = isr;
326                         siginfo.si_flags = __ISR_VALID;
327                         siginfo.si_imm = 0;
328                         force_sig_info(SIGFPE, &siginfo, current);
329                 }
330         } else {
331                 if (exception == -1) {
332                         printk(KERN_ERR "handle_fpu_swa: fp_emulate() returned -1\n");
333                         return -1;
334                 } else if (exception != 0) {
335                         /* raise exception */
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);
340                         if (isr & 0x880) {
341                                 siginfo.si_code = FPE_FLTOVF;
342                         } else if (isr & 0x1100) {
343                                 siginfo.si_code = FPE_FLTUND;
344                         } else if (isr & 0x2200) {
345                                 siginfo.si_code = FPE_FLTRES;
346                         }
347                         siginfo.si_isr = isr;
348                         siginfo.si_flags = __ISR_VALID;
349                         siginfo.si_imm = 0;
350                         force_sig_info(SIGFPE, &siginfo, current);
351                 }
352         }
353         return 0;
354 }
355
356 struct illegal_op_return {
357         unsigned long fkt, arg1, arg2, arg3;
358 };
359
360 struct illegal_op_return
361 ia64_illegal_op_fault (unsigned long ec, long arg1, long arg2, long arg3,
362                        long arg4, long arg5, long arg6, long arg7,
363                        struct pt_regs regs)
364 {
365         struct illegal_op_return rv;
366         struct siginfo si;
367         char buf[128];
368
369 #ifdef CONFIG_IA64_BRL_EMU
370         {
371                 extern struct illegal_op_return ia64_emulate_brl (struct pt_regs *, unsigned long);
372
373                 rv = ia64_emulate_brl(&regs, ec);
374                 if (rv.fkt != (unsigned long) -1)
375                         return rv;
376         }
377 #endif
378
379         sprintf(buf, "IA-64 Illegal operation fault");
380         die_if_kernel(buf, &regs, 0);
381
382         memset(&si, 0, sizeof(si));
383         si.si_signo = SIGILL;
384         si.si_code = ILL_ILLOPC;
385         si.si_addr = (void __user *) (regs.cr_iip + ia64_psr(&regs)->ri);
386         force_sig_info(SIGILL, &si, current);
387         rv.fkt = 0;
388         return rv;
389 }
390
391 void
392 ia64_fault (unsigned long vector, unsigned long isr, unsigned long ifa,
393             unsigned long iim, unsigned long itir, long arg5, long arg6,
394             long arg7, struct pt_regs regs)
395 {
396         unsigned long code, error = isr, iip;
397         struct siginfo siginfo;
398         char buf[128];
399         int result, sig;
400         static const char *reason[] = {
401                 "IA-64 Illegal Operation fault",
402                 "IA-64 Privileged Operation fault",
403                 "IA-64 Privileged Register fault",
404                 "IA-64 Reserved Register/Field fault",
405                 "Disabled Instruction Set Transition fault",
406                 "Unknown fault 5", "Unknown fault 6", "Unknown fault 7", "Illegal Hazard fault",
407                 "Unknown fault 9", "Unknown fault 10", "Unknown fault 11", "Unknown fault 12",
408                 "Unknown fault 13", "Unknown fault 14", "Unknown fault 15"
409         };
410
411         if ((isr & IA64_ISR_NA) && ((isr & IA64_ISR_CODE_MASK) == IA64_ISR_CODE_LFETCH)) {
412                 /*
413                  * This fault was due to lfetch.fault, set "ed" bit in the psr to cancel
414                  * the lfetch.
415                  */
416                 ia64_psr(&regs)->ed = 1;
417                 return;
418         }
419
420         iip = regs.cr_iip + ia64_psr(&regs)->ri;
421
422         switch (vector) {
423               case 24: /* General Exception */
424                 code = (isr >> 4) & 0xf;
425                 sprintf(buf, "General Exception: %s%s", reason[code],
426                         (code == 3) ? ((isr & (1UL << 37))
427                                        ? " (RSE access)" : " (data access)") : "");
428                 if (code == 8) {
429 # ifdef CONFIG_IA64_PRINT_HAZARDS
430                         printk("%s[%d]: possible hazard @ ip=%016lx (pr = %016lx)\n",
431                                current->comm, current->pid,
432                                regs.cr_iip + ia64_psr(&regs)->ri, regs.pr);
433 # endif
434                         return;
435                 }
436                 break;
437
438               case 25: /* Disabled FP-Register */
439                 if (isr & 2) {
440                         disabled_fph_fault(&regs);
441                         return;
442                 }
443                 sprintf(buf, "Disabled FPL fault---not supposed to happen!");
444                 break;
445
446               case 26: /* NaT Consumption */
447                 if (user_mode(&regs)) {
448                         void __user *addr;
449
450                         if (((isr >> 4) & 0xf) == 2) {
451                                 /* NaT page consumption */
452                                 sig = SIGSEGV;
453                                 code = SEGV_ACCERR;
454                                 addr = (void __user *) ifa;
455                         } else {
456                                 /* register NaT consumption */
457                                 sig = SIGILL;
458                                 code = ILL_ILLOPN;
459                                 addr = (void __user *) (regs.cr_iip
460                                                         + ia64_psr(&regs)->ri);
461                         }
462                         siginfo.si_signo = sig;
463                         siginfo.si_code = code;
464                         siginfo.si_errno = 0;
465                         siginfo.si_addr = addr;
466                         siginfo.si_imm = vector;
467                         siginfo.si_flags = __ISR_VALID;
468                         siginfo.si_isr = isr;
469                         force_sig_info(sig, &siginfo, current);
470                         return;
471                 } else if (ia64_done_with_exception(&regs))
472                         return;
473                 sprintf(buf, "NaT consumption");
474                 break;
475
476               case 31: /* Unsupported Data Reference */
477                 if (user_mode(&regs)) {
478                         siginfo.si_signo = SIGILL;
479                         siginfo.si_code = ILL_ILLOPN;
480                         siginfo.si_errno = 0;
481                         siginfo.si_addr = (void __user *) iip;
482                         siginfo.si_imm = vector;
483                         siginfo.si_flags = __ISR_VALID;
484                         siginfo.si_isr = isr;
485                         force_sig_info(SIGILL, &siginfo, current);
486                         return;
487                 }
488                 sprintf(buf, "Unsupported data reference");
489                 break;
490
491               case 29: /* Debug */
492               case 35: /* Taken Branch Trap */
493               case 36: /* Single Step Trap */
494                 if (fsys_mode(current, &regs)) {
495                         extern char __kernel_syscall_via_break[];
496                         /*
497                          * Got a trap in fsys-mode: Taken Branch Trap and Single Step trap
498                          * need special handling; Debug trap is not supposed to happen.
499                          */
500                         if (unlikely(vector == 29)) {
501                                 die("Got debug trap in fsys-mode---not supposed to happen!",
502                                     &regs, 0);
503                                 return;
504                         }
505                         /* re-do the system call via break 0x100000: */
506                         regs.cr_iip = (unsigned long) __kernel_syscall_via_break;
507                         ia64_psr(&regs)->ri = 0;
508                         ia64_psr(&regs)->cpl = 3;
509                         return;
510                 }
511                 switch (vector) {
512                       case 29:
513                         siginfo.si_code = TRAP_HWBKPT;
514 #ifdef CONFIG_ITANIUM
515                         /*
516                          * Erratum 10 (IFA may contain incorrect address) now has
517                          * "NoFix" status.  There are no plans for fixing this.
518                          */
519                         if (ia64_psr(&regs)->is == 0)
520                           ifa = regs.cr_iip;
521 #endif
522                         break;
523                       case 35: siginfo.si_code = TRAP_BRANCH; ifa = 0; break;
524                       case 36: siginfo.si_code = TRAP_TRACE; ifa = 0; break;
525                 }
526                 siginfo.si_signo = SIGTRAP;
527                 siginfo.si_errno = 0;
528                 siginfo.si_addr  = (void __user *) ifa;
529                 siginfo.si_imm   = 0;
530                 siginfo.si_flags = __ISR_VALID;
531                 siginfo.si_isr   = isr;
532                 force_sig_info(SIGTRAP, &siginfo, current);
533                 return;
534
535               case 32: /* fp fault */
536               case 33: /* fp trap */
537                 result = handle_fpu_swa((vector == 32) ? 1 : 0, &regs, isr);
538                 if ((result < 0) || (current->thread.flags & IA64_THREAD_FPEMU_SIGFPE)) {
539                         siginfo.si_signo = SIGFPE;
540                         siginfo.si_errno = 0;
541                         siginfo.si_code = FPE_FLTINV;
542                         siginfo.si_addr = (void __user *) iip;
543                         siginfo.si_flags = __ISR_VALID;
544                         siginfo.si_isr = isr;
545                         siginfo.si_imm = 0;
546                         force_sig_info(SIGFPE, &siginfo, current);
547                 }
548                 return;
549
550               case 34:
551                 if (isr & 0x2) {
552                         /* Lower-Privilege Transfer Trap */
553                         /*
554                          * Just clear PSR.lp and then return immediately: all the
555                          * interesting work (e.g., signal delivery is done in the kernel
556                          * exit path).
557                          */
558                         ia64_psr(&regs)->lp = 0;
559                         return;
560                 } else {
561                         /* Unimplemented Instr. Address Trap */
562                         if (user_mode(&regs)) {
563                                 siginfo.si_signo = SIGILL;
564                                 siginfo.si_code = ILL_BADIADDR;
565                                 siginfo.si_errno = 0;
566                                 siginfo.si_flags = 0;
567                                 siginfo.si_isr = 0;
568                                 siginfo.si_imm = 0;
569                                 siginfo.si_addr = (void __user *) iip;
570                                 force_sig_info(SIGILL, &siginfo, current);
571                                 return;
572                         }
573                         sprintf(buf, "Unimplemented Instruction Address fault");
574                 }
575                 break;
576
577               case 45:
578 #ifdef CONFIG_IA32_SUPPORT
579                 if (ia32_exception(&regs, isr) == 0)
580                         return;
581 #endif
582                 printk(KERN_ERR "Unexpected IA-32 exception (Trap 45)\n");
583                 printk(KERN_ERR "  iip - 0x%lx, ifa - 0x%lx, isr - 0x%lx\n",
584                        iip, ifa, isr);
585                 force_sig(SIGSEGV, current);
586                 break;
587
588               case 46:
589 #ifdef CONFIG_IA32_SUPPORT
590                 if (ia32_intercept(&regs, isr) == 0)
591                         return;
592 #endif
593                 printk(KERN_ERR "Unexpected IA-32 intercept trap (Trap 46)\n");
594                 printk(KERN_ERR "  iip - 0x%lx, ifa - 0x%lx, isr - 0x%lx, iim - 0x%lx\n",
595                        iip, ifa, isr, iim);
596                 force_sig(SIGSEGV, current);
597                 return;
598
599               case 47:
600                 sprintf(buf, "IA-32 Interruption Fault (int 0x%lx)", isr >> 16);
601                 break;
602
603               default:
604                 sprintf(buf, "Fault %lu", vector);
605                 break;
606         }
607         die_if_kernel(buf, &regs, error);
608         force_sig(SIGILL, current);
609 }