vserver 2.0 rc7
[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 #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
224         /*
225          * Make sure that no other task gets in on this processor
226          * while we're claiming the FPU
227          */
228         preempt_disable();
229 #ifndef CONFIG_SMP
230         {
231                 struct task_struct *fpu_owner
232                         = (struct task_struct *)ia64_get_kr(IA64_KR_FPU_OWNER);
233
234                 if (ia64_is_local_fpu_owner(current)) {
235                         preempt_enable_no_resched();
236                         return;
237                 }
238
239                 if (fpu_owner)
240                         ia64_flush_fph(fpu_owner);
241         }
242 #endif /* !CONFIG_SMP */
243         ia64_set_local_fpu_owner(current);
244         if ((current->thread.flags & IA64_THREAD_FPH_VALID) != 0) {
245                 __ia64_load_fpu(current->thread.fph);
246                 psr->mfh = 0;
247         } else {
248                 __ia64_init_fpu();
249                 /*
250                  * Set mfh because the state in thread.fph does not match the state in
251                  * the fph partition.
252                  */
253                 psr->mfh = 1;
254         }
255         preempt_enable_no_resched();
256 }
257
258 static inline int
259 fp_emulate (int fp_fault, void *bundle, long *ipsr, long *fpsr, long *isr, long *pr, long *ifs,
260             struct pt_regs *regs)
261 {
262         fp_state_t fp_state;
263         fpswa_ret_t ret;
264
265         if (!fpswa_interface)
266                 return -1;
267
268         memset(&fp_state, 0, sizeof(fp_state_t));
269
270         /*
271          * compute fp_state.  only FP registers f6 - f11 are used by the
272          * kernel, so set those bits in the mask and set the low volatile
273          * pointer to point to these registers.
274          */
275         fp_state.bitmask_low64 = 0xfc0;  /* bit6..bit11 */
276
277         fp_state.fp_state_low_volatile = (fp_state_low_volatile_t *) &regs->f6;
278         /*
279          * unsigned long (*EFI_FPSWA) (
280          *      unsigned long    trap_type,
281          *      void             *Bundle,
282          *      unsigned long    *pipsr,
283          *      unsigned long    *pfsr,
284          *      unsigned long    *pisr,
285          *      unsigned long    *ppreds,
286          *      unsigned long    *pifs,
287          *      void             *fp_state);
288          */
289         ret = (*fpswa_interface->fpswa)((unsigned long) fp_fault, bundle,
290                                         (unsigned long *) ipsr, (unsigned long *) fpsr,
291                                         (unsigned long *) isr, (unsigned long *) pr,
292                                         (unsigned long *) ifs, &fp_state);
293
294         return ret.status;
295 }
296
297 /*
298  * Handle floating-point assist faults and traps.
299  */
300 static int
301 handle_fpu_swa (int fp_fault, struct pt_regs *regs, unsigned long isr)
302 {
303         long exception, bundle[2];
304         unsigned long fault_ip;
305         struct siginfo siginfo;
306         static int fpu_swa_count = 0;
307         static unsigned long last_time;
308
309         fault_ip = regs->cr_iip;
310         if (!fp_fault && (ia64_psr(regs)->ri == 0))
311                 fault_ip -= 16;
312         if (copy_from_user(bundle, (void __user *) fault_ip, sizeof(bundle)))
313                 return -1;
314
315         if (jiffies - last_time > 5*HZ)
316                 fpu_swa_count = 0;
317         if ((fpu_swa_count < 4) && !(current->thread.flags & IA64_THREAD_FPEMU_NOPRINT)) {
318                 last_time = jiffies;
319                 ++fpu_swa_count;
320                 printk(KERN_WARNING
321                        "%s(%d): floating-point assist fault at ip %016lx, isr %016lx\n",
322                        current->comm, current->pid, regs->cr_iip + ia64_psr(regs)->ri, isr);
323         }
324
325         exception = fp_emulate(fp_fault, bundle, &regs->cr_ipsr, &regs->ar_fpsr, &isr, &regs->pr,
326                                &regs->cr_ifs, regs);
327         if (fp_fault) {
328                 if (exception == 0) {
329                         /* emulation was successful */
330                         ia64_increment_ip(regs);
331                 } else if (exception == -1) {
332                         printk(KERN_ERR "handle_fpu_swa: fp_emulate() returned -1\n");
333                         return -1;
334                 } else {
335                         /* is next instruction a trap? */
336                         if (exception & 2) {
337                                 ia64_increment_ip(regs);
338                         }
339                         siginfo.si_signo = SIGFPE;
340                         siginfo.si_errno = 0;
341                         siginfo.si_code = __SI_FAULT;   /* default code */
342                         siginfo.si_addr = (void __user *) (regs->cr_iip + ia64_psr(regs)->ri);
343                         if (isr & 0x11) {
344                                 siginfo.si_code = FPE_FLTINV;
345                         } else if (isr & 0x22) {
346                                 /* denormal operand gets the same si_code as underflow 
347                                 * see arch/i386/kernel/traps.c:math_error()  */
348                                 siginfo.si_code = FPE_FLTUND;
349                         } else if (isr & 0x44) {
350                                 siginfo.si_code = FPE_FLTDIV;
351                         }
352                         siginfo.si_isr = isr;
353                         siginfo.si_flags = __ISR_VALID;
354                         siginfo.si_imm = 0;
355                         force_sig_info(SIGFPE, &siginfo, current);
356                 }
357         } else {
358                 if (exception == -1) {
359                         printk(KERN_ERR "handle_fpu_swa: fp_emulate() returned -1\n");
360                         return -1;
361                 } else if (exception != 0) {
362                         /* raise exception */
363                         siginfo.si_signo = SIGFPE;
364                         siginfo.si_errno = 0;
365                         siginfo.si_code = __SI_FAULT;   /* default code */
366                         siginfo.si_addr = (void __user *) (regs->cr_iip + ia64_psr(regs)->ri);
367                         if (isr & 0x880) {
368                                 siginfo.si_code = FPE_FLTOVF;
369                         } else if (isr & 0x1100) {
370                                 siginfo.si_code = FPE_FLTUND;
371                         } else if (isr & 0x2200) {
372                                 siginfo.si_code = FPE_FLTRES;
373                         }
374                         siginfo.si_isr = isr;
375                         siginfo.si_flags = __ISR_VALID;
376                         siginfo.si_imm = 0;
377                         force_sig_info(SIGFPE, &siginfo, current);
378                 }
379         }
380         return 0;
381 }
382
383 struct illegal_op_return {
384         unsigned long fkt, arg1, arg2, arg3;
385 };
386
387 struct illegal_op_return
388 ia64_illegal_op_fault (unsigned long ec, long arg1, long arg2, long arg3,
389                        long arg4, long arg5, long arg6, long arg7,
390                        struct pt_regs regs)
391 {
392         struct illegal_op_return rv;
393         struct siginfo si;
394         char buf[128];
395
396 #ifdef CONFIG_IA64_BRL_EMU
397         {
398                 extern struct illegal_op_return ia64_emulate_brl (struct pt_regs *, unsigned long);
399
400                 rv = ia64_emulate_brl(&regs, ec);
401                 if (rv.fkt != (unsigned long) -1)
402                         return rv;
403         }
404 #endif
405
406         sprintf(buf, "IA-64 Illegal operation fault");
407         die_if_kernel(buf, &regs, 0);
408
409         memset(&si, 0, sizeof(si));
410         si.si_signo = SIGILL;
411         si.si_code = ILL_ILLOPC;
412         si.si_addr = (void __user *) (regs.cr_iip + ia64_psr(&regs)->ri);
413         force_sig_info(SIGILL, &si, current);
414         rv.fkt = 0;
415         return rv;
416 }
417
418 void
419 ia64_fault (unsigned long vector, unsigned long isr, unsigned long ifa,
420             unsigned long iim, unsigned long itir, long arg5, long arg6,
421             long arg7, struct pt_regs regs)
422 {
423         unsigned long code, error = isr, iip;
424         struct siginfo siginfo;
425         char buf[128];
426         int result, sig;
427         static const char *reason[] = {
428                 "IA-64 Illegal Operation fault",
429                 "IA-64 Privileged Operation fault",
430                 "IA-64 Privileged Register fault",
431                 "IA-64 Reserved Register/Field fault",
432                 "Disabled Instruction Set Transition fault",
433                 "Unknown fault 5", "Unknown fault 6", "Unknown fault 7", "Illegal Hazard fault",
434                 "Unknown fault 9", "Unknown fault 10", "Unknown fault 11", "Unknown fault 12",
435                 "Unknown fault 13", "Unknown fault 14", "Unknown fault 15"
436         };
437
438         if ((isr & IA64_ISR_NA) && ((isr & IA64_ISR_CODE_MASK) == IA64_ISR_CODE_LFETCH)) {
439                 /*
440                  * This fault was due to lfetch.fault, set "ed" bit in the psr to cancel
441                  * the lfetch.
442                  */
443                 ia64_psr(&regs)->ed = 1;
444                 return;
445         }
446
447         iip = regs.cr_iip + ia64_psr(&regs)->ri;
448
449         switch (vector) {
450               case 24: /* General Exception */
451                 code = (isr >> 4) & 0xf;
452                 sprintf(buf, "General Exception: %s%s", reason[code],
453                         (code == 3) ? ((isr & (1UL << 37))
454                                        ? " (RSE access)" : " (data access)") : "");
455                 if (code == 8) {
456 # ifdef CONFIG_IA64_PRINT_HAZARDS
457                         printk("%s[%d]: possible hazard @ ip=%016lx (pr = %016lx)\n",
458                                current->comm, current->pid,
459                                regs.cr_iip + ia64_psr(&regs)->ri, regs.pr);
460 # endif
461                         return;
462                 }
463                 break;
464
465               case 25: /* Disabled FP-Register */
466                 if (isr & 2) {
467                         disabled_fph_fault(&regs);
468                         return;
469                 }
470                 sprintf(buf, "Disabled FPL fault---not supposed to happen!");
471                 break;
472
473               case 26: /* NaT Consumption */
474                 if (user_mode(&regs)) {
475                         void __user *addr;
476
477                         if (((isr >> 4) & 0xf) == 2) {
478                                 /* NaT page consumption */
479                                 sig = SIGSEGV;
480                                 code = SEGV_ACCERR;
481                                 addr = (void __user *) ifa;
482                         } else {
483                                 /* register NaT consumption */
484                                 sig = SIGILL;
485                                 code = ILL_ILLOPN;
486                                 addr = (void __user *) (regs.cr_iip
487                                                         + ia64_psr(&regs)->ri);
488                         }
489                         siginfo.si_signo = sig;
490                         siginfo.si_code = code;
491                         siginfo.si_errno = 0;
492                         siginfo.si_addr = addr;
493                         siginfo.si_imm = vector;
494                         siginfo.si_flags = __ISR_VALID;
495                         siginfo.si_isr = isr;
496                         force_sig_info(sig, &siginfo, current);
497                         return;
498                 } else if (ia64_done_with_exception(&regs))
499                         return;
500                 sprintf(buf, "NaT consumption");
501                 break;
502
503               case 31: /* Unsupported Data Reference */
504                 if (user_mode(&regs)) {
505                         siginfo.si_signo = SIGILL;
506                         siginfo.si_code = ILL_ILLOPN;
507                         siginfo.si_errno = 0;
508                         siginfo.si_addr = (void __user *) iip;
509                         siginfo.si_imm = vector;
510                         siginfo.si_flags = __ISR_VALID;
511                         siginfo.si_isr = isr;
512                         force_sig_info(SIGILL, &siginfo, current);
513                         return;
514                 }
515                 sprintf(buf, "Unsupported data reference");
516                 break;
517
518               case 29: /* Debug */
519               case 35: /* Taken Branch Trap */
520               case 36: /* Single Step Trap */
521                 if (fsys_mode(current, &regs)) {
522                         extern char __kernel_syscall_via_break[];
523                         /*
524                          * Got a trap in fsys-mode: Taken Branch Trap and Single Step trap
525                          * need special handling; Debug trap is not supposed to happen.
526                          */
527                         if (unlikely(vector == 29)) {
528                                 die("Got debug trap in fsys-mode---not supposed to happen!",
529                                     &regs, 0);
530                                 return;
531                         }
532                         /* re-do the system call via break 0x100000: */
533                         regs.cr_iip = (unsigned long) __kernel_syscall_via_break;
534                         ia64_psr(&regs)->ri = 0;
535                         ia64_psr(&regs)->cpl = 3;
536                         return;
537                 }
538                 switch (vector) {
539                       case 29:
540                         siginfo.si_code = TRAP_HWBKPT;
541 #ifdef CONFIG_ITANIUM
542                         /*
543                          * Erratum 10 (IFA may contain incorrect address) now has
544                          * "NoFix" status.  There are no plans for fixing this.
545                          */
546                         if (ia64_psr(&regs)->is == 0)
547                           ifa = regs.cr_iip;
548 #endif
549                         break;
550                       case 35: siginfo.si_code = TRAP_BRANCH; ifa = 0; break;
551                       case 36: siginfo.si_code = TRAP_TRACE; ifa = 0; break;
552                 }
553                 siginfo.si_signo = SIGTRAP;
554                 siginfo.si_errno = 0;
555                 siginfo.si_addr  = (void __user *) ifa;
556                 siginfo.si_imm   = 0;
557                 siginfo.si_flags = __ISR_VALID;
558                 siginfo.si_isr   = isr;
559                 force_sig_info(SIGTRAP, &siginfo, current);
560                 return;
561
562               case 32: /* fp fault */
563               case 33: /* fp trap */
564                 result = handle_fpu_swa((vector == 32) ? 1 : 0, &regs, isr);
565                 if ((result < 0) || (current->thread.flags & IA64_THREAD_FPEMU_SIGFPE)) {
566                         siginfo.si_signo = SIGFPE;
567                         siginfo.si_errno = 0;
568                         siginfo.si_code = FPE_FLTINV;
569                         siginfo.si_addr = (void __user *) iip;
570                         siginfo.si_flags = __ISR_VALID;
571                         siginfo.si_isr = isr;
572                         siginfo.si_imm = 0;
573                         force_sig_info(SIGFPE, &siginfo, current);
574                 }
575                 return;
576
577               case 34:
578                 if (isr & 0x2) {
579                         /* Lower-Privilege Transfer Trap */
580                         /*
581                          * Just clear PSR.lp and then return immediately: all the
582                          * interesting work (e.g., signal delivery is done in the kernel
583                          * exit path).
584                          */
585                         ia64_psr(&regs)->lp = 0;
586                         return;
587                 } else {
588                         /* Unimplemented Instr. Address Trap */
589                         if (user_mode(&regs)) {
590                                 siginfo.si_signo = SIGILL;
591                                 siginfo.si_code = ILL_BADIADDR;
592                                 siginfo.si_errno = 0;
593                                 siginfo.si_flags = 0;
594                                 siginfo.si_isr = 0;
595                                 siginfo.si_imm = 0;
596                                 siginfo.si_addr = (void __user *) iip;
597                                 force_sig_info(SIGILL, &siginfo, current);
598                                 return;
599                         }
600                         sprintf(buf, "Unimplemented Instruction Address fault");
601                 }
602                 break;
603
604               case 45:
605 #ifdef CONFIG_IA32_SUPPORT
606                 if (ia32_exception(&regs, isr) == 0)
607                         return;
608 #endif
609                 printk(KERN_ERR "Unexpected IA-32 exception (Trap 45)\n");
610                 printk(KERN_ERR "  iip - 0x%lx, ifa - 0x%lx, isr - 0x%lx\n",
611                        iip, ifa, isr);
612                 force_sig(SIGSEGV, current);
613                 break;
614
615               case 46:
616 #ifdef CONFIG_IA32_SUPPORT
617                 if (ia32_intercept(&regs, isr) == 0)
618                         return;
619 #endif
620                 printk(KERN_ERR "Unexpected IA-32 intercept trap (Trap 46)\n");
621                 printk(KERN_ERR "  iip - 0x%lx, ifa - 0x%lx, isr - 0x%lx, iim - 0x%lx\n",
622                        iip, ifa, isr, iim);
623                 force_sig(SIGSEGV, current);
624                 return;
625
626               case 47:
627                 sprintf(buf, "IA-32 Interruption Fault (int 0x%lx)", isr >> 16);
628                 break;
629
630               default:
631                 sprintf(buf, "Fault %lu", vector);
632                 break;
633         }
634         die_if_kernel(buf, &regs, error);
635         force_sig(SIGILL, current);
636 }