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