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