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