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