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