patch-2_6_7-vs1_9_1_12
[linux-2.6.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
18 #include <asm/fpswa.h>
19 #include <asm/hardirq.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 *) (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 *) 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 *) (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 *) (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, unsigned long arg1, unsigned long arg2,
362                        unsigned long arg3, unsigned long arg4, unsigned long arg5,
363                        unsigned long arg6, unsigned long arg7, unsigned long stack)
364 {
365         struct pt_regs *regs = (struct pt_regs *) &stack;
366         struct illegal_op_return rv;
367         struct siginfo si;
368         char buf[128];
369
370 #ifdef CONFIG_IA64_BRL_EMU
371         {
372                 extern struct illegal_op_return ia64_emulate_brl (struct pt_regs *, unsigned long);
373
374                 rv = ia64_emulate_brl(regs, ec);
375                 if (rv.fkt != (unsigned long) -1)
376                         return rv;
377         }
378 #endif
379
380         sprintf(buf, "IA-64 Illegal operation fault");
381         die_if_kernel(buf, regs, 0);
382
383         memset(&si, 0, sizeof(si));
384         si.si_signo = SIGILL;
385         si.si_code = ILL_ILLOPC;
386         si.si_addr = (void *) (regs->cr_iip + ia64_psr(regs)->ri);
387         force_sig_info(SIGILL, &si, current);
388         rv.fkt = 0;
389         return rv;
390 }
391
392 void
393 ia64_fault (unsigned long vector, unsigned long isr, unsigned long ifa,
394             unsigned long iim, unsigned long itir, unsigned long arg5,
395             unsigned long arg6, unsigned long arg7, unsigned long stack)
396 {
397         struct pt_regs *regs = (struct pt_regs *) &stack;
398         unsigned long code, error = isr;
399         struct siginfo siginfo;
400         char buf[128];
401         int result, sig;
402         static const char *reason[] = {
403                 "IA-64 Illegal Operation fault",
404                 "IA-64 Privileged Operation fault",
405                 "IA-64 Privileged Register fault",
406                 "IA-64 Reserved Register/Field fault",
407                 "Disabled Instruction Set Transition fault",
408                 "Unknown fault 5", "Unknown fault 6", "Unknown fault 7", "Illegal Hazard fault",
409                 "Unknown fault 9", "Unknown fault 10", "Unknown fault 11", "Unknown fault 12",
410                 "Unknown fault 13", "Unknown fault 14", "Unknown fault 15"
411         };
412
413         if ((isr & IA64_ISR_NA) && ((isr & IA64_ISR_CODE_MASK) == IA64_ISR_CODE_LFETCH)) {
414                 /*
415                  * This fault was due to lfetch.fault, set "ed" bit in the psr to cancel
416                  * the lfetch.
417                  */
418                 ia64_psr(regs)->ed = 1;
419                 return;
420         }
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, regs->cr_iip + ia64_psr(regs)->ri,
432                                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 *addr;
449
450                         if (((isr >> 4) & 0xf) == 2) {
451                                 /* NaT page consumption */
452                                 sig = SIGSEGV;
453                                 code = SEGV_ACCERR;
454                                 addr = (void *) ifa;
455                         } else {
456                                 /* register NaT consumption */
457                                 sig = SIGILL;
458                                 code = ILL_ILLOPN;
459                                 addr = (void *) (regs->cr_iip + ia64_psr(regs)->ri);
460                         }
461                         siginfo.si_signo = sig;
462                         siginfo.si_code = code;
463                         siginfo.si_errno = 0;
464                         siginfo.si_addr = addr;
465                         siginfo.si_imm = vector;
466                         siginfo.si_flags = __ISR_VALID;
467                         siginfo.si_isr = isr;
468                         force_sig_info(sig, &siginfo, current);
469                         return;
470                 } else if (ia64_done_with_exception(regs))
471                         return;
472                 sprintf(buf, "NaT consumption");
473                 break;
474
475               case 31: /* Unsupported Data Reference */
476                 if (user_mode(regs)) {
477                         siginfo.si_signo = SIGILL;
478                         siginfo.si_code = ILL_ILLOPN;
479                         siginfo.si_errno = 0;
480                         siginfo.si_addr = (void *) (regs->cr_iip + ia64_psr(regs)->ri);
481                         siginfo.si_imm = vector;
482                         siginfo.si_flags = __ISR_VALID;
483                         siginfo.si_isr = isr;
484                         force_sig_info(SIGILL, &siginfo, current);
485                         return;
486                 }
487                 sprintf(buf, "Unsupported data reference");
488                 break;
489
490               case 29: /* Debug */
491               case 35: /* Taken Branch Trap */
492               case 36: /* Single Step Trap */
493                 if (fsys_mode(current, regs)) {
494                         extern char __kernel_syscall_via_break[];
495                         /*
496                          * Got a trap in fsys-mode: Taken Branch Trap and Single Step trap
497                          * need special handling; Debug trap is not supposed to happen.
498                          */
499                         if (unlikely(vector == 29)) {
500                                 die("Got debug trap in fsys-mode---not supposed to happen!",
501                                     regs, 0);
502                                 return;
503                         }
504                         /* re-do the system call via break 0x100000: */
505                         regs->cr_iip = (unsigned long) __kernel_syscall_via_break;
506                         ia64_psr(regs)->ri = 0;
507                         ia64_psr(regs)->cpl = 3;
508                         return;
509                 }
510                 switch (vector) {
511                       case 29:
512                         siginfo.si_code = TRAP_HWBKPT;
513 #ifdef CONFIG_ITANIUM
514                         /*
515                          * Erratum 10 (IFA may contain incorrect address) now has
516                          * "NoFix" status.  There are no plans for fixing this.
517                          */
518                         if (ia64_psr(regs)->is == 0)
519                           ifa = regs->cr_iip;
520 #endif
521                         break;
522                       case 35: siginfo.si_code = TRAP_BRANCH; ifa = 0; break;
523                       case 36: siginfo.si_code = TRAP_TRACE; ifa = 0; break;
524                 }
525                 siginfo.si_signo = SIGTRAP;
526                 siginfo.si_errno = 0;
527                 siginfo.si_addr  = (void *) ifa;
528                 siginfo.si_imm   = 0;
529                 siginfo.si_flags = __ISR_VALID;
530                 siginfo.si_isr   = isr;
531                 force_sig_info(SIGTRAP, &siginfo, current);
532                 return;
533
534               case 32: /* fp fault */
535               case 33: /* fp trap */
536                 result = handle_fpu_swa((vector == 32) ? 1 : 0, regs, isr);
537                 if ((result < 0) || (current->thread.flags & IA64_THREAD_FPEMU_SIGFPE)) {
538                         siginfo.si_signo = SIGFPE;
539                         siginfo.si_errno = 0;
540                         siginfo.si_code = FPE_FLTINV;
541                         siginfo.si_addr = (void *) (regs->cr_iip + ia64_psr(regs)->ri);
542                         siginfo.si_flags = __ISR_VALID;
543                         siginfo.si_isr = isr;
544                         siginfo.si_imm = 0;
545                         force_sig_info(SIGFPE, &siginfo, current);
546                 }
547                 return;
548
549               case 34:
550                 if (isr & 0x2) {
551                         /* Lower-Privilege Transfer Trap */
552                         /*
553                          * Just clear PSR.lp and then return immediately: all the
554                          * interesting work (e.g., signal delivery is done in the kernel
555                          * exit path).
556                          */
557                         ia64_psr(regs)->lp = 0;
558                         return;
559                 } else {
560                         /* Unimplemented Instr. Address Trap */
561                         if (user_mode(regs)) {
562                                 siginfo.si_signo = SIGILL;
563                                 siginfo.si_code = ILL_BADIADDR;
564                                 siginfo.si_errno = 0;
565                                 siginfo.si_flags = 0;
566                                 siginfo.si_isr = 0;
567                                 siginfo.si_imm = 0;
568                                 siginfo.si_addr = (void *) (regs->cr_iip + ia64_psr(regs)->ri);
569                                 force_sig_info(SIGILL, &siginfo, current);
570                                 return;
571                         }
572                         sprintf(buf, "Unimplemented Instruction Address fault");
573                 }
574                 break;
575
576               case 45:
577 #ifdef CONFIG_IA32_SUPPORT
578                 if (ia32_exception(regs, isr) == 0)
579                         return;
580 #endif
581                 printk(KERN_ERR "Unexpected IA-32 exception (Trap 45)\n");
582                 printk(KERN_ERR "  iip - 0x%lx, ifa - 0x%lx, isr - 0x%lx\n",
583                        regs->cr_iip, ifa, isr);
584                 force_sig(SIGSEGV, current);
585                 break;
586
587               case 46:
588 #ifdef CONFIG_IA32_SUPPORT
589                 if (ia32_intercept(regs, isr) == 0)
590                         return;
591 #endif
592                 printk(KERN_ERR "Unexpected IA-32 intercept trap (Trap 46)\n");
593                 printk(KERN_ERR "  iip - 0x%lx, ifa - 0x%lx, isr - 0x%lx, iim - 0x%lx\n",
594                        regs->cr_iip, ifa, isr, iim);
595                 force_sig(SIGSEGV, current);
596                 return;
597
598               case 47:
599                 sprintf(buf, "IA-32 Interruption Fault (int 0x%lx)", isr >> 16);
600                 break;
601
602               default:
603                 sprintf(buf, "Fault %lu", vector);
604                 break;
605         }
606         die_if_kernel(buf, regs, error);
607         force_sig(SIGILL, current);
608 }