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