Logo Search packages:      
Sourcecode: linux version File versions

ia32_traps.c

/*
 * IA-32 exception handlers
 *
 * Copyright (C) 2000 Asit K. Mallick <asit.k.mallick@intel.com>
 * Copyright (C) 2001-2002 Hewlett-Packard Co
 *    David Mosberger-Tang <davidm@hpl.hp.com>
 *
 * 06/16/00 A. Mallick  added siginfo for most cases (close to IA32)
 * 09/29/00 D. Mosberger      added ia32_intercept()
 */

#include <linux/kernel.h>
#include <linux/sched.h>

#include "ia32priv.h"

#include <asm/intrinsics.h>
#include <asm/ptrace.h>

int
ia32_intercept (struct pt_regs *regs, unsigned long isr)
{
      switch ((isr >> 16) & 0xff) {
            case 0:     /* Instruction intercept fault */
            case 4:     /* Locked Data reference fault */
            case 1:     /* Gate intercept trap */
            return -1;

            case 2:     /* System flag trap */
            if (((isr >> 14) & 0x3) >= 2) {
                  /* MOV SS, POP SS instructions */
                  ia64_psr(regs)->id = 1;
                  return 0;
            } else
                  return -1;
      }
      return -1;
}

int
ia32_exception (struct pt_regs *regs, unsigned long isr)
{
      struct siginfo siginfo;

      /* initialize these fields to avoid leaking kernel bits to user space: */
      siginfo.si_errno = 0;
      siginfo.si_flags = 0;
      siginfo.si_isr = 0;
      siginfo.si_imm = 0;
      switch ((isr >> 16) & 0xff) {
            case 1:
            case 2:
            siginfo.si_signo = SIGTRAP;
            if (isr == 0)
                  siginfo.si_code = TRAP_TRACE;
            else if (isr & 0x4)
                  siginfo.si_code = TRAP_BRANCH;
            else
                  siginfo.si_code = TRAP_BRKPT;
            break;

            case 3:
            siginfo.si_signo = SIGTRAP;
            siginfo.si_code = TRAP_BRKPT;
            break;

            case 0:     /* Divide fault */
            siginfo.si_signo = SIGFPE;
            siginfo.si_code = FPE_INTDIV;
            break;

            case 4:     /* Overflow */
            case 5:     /* Bounds fault */
            siginfo.si_signo = SIGFPE;
            siginfo.si_code = 0;
            break;

            case 6:     /* Invalid Op-code */
            siginfo.si_signo = SIGILL;
            siginfo.si_code = ILL_ILLOPN;
            break;

            case 7:     /* FP DNA */
            case 8:     /* Double Fault */
            case 9:     /* Invalid TSS */
            case 11:    /* Segment not present */
            case 12:    /* Stack fault */
            case 13:    /* General Protection Fault */
            siginfo.si_signo = SIGSEGV;
            siginfo.si_code = 0;
            break;

            case 16:    /* Pending FP error */
            {
                  unsigned long fsr, fcr;

                  fsr = ia64_getreg(_IA64_REG_AR_FSR);
                  fcr = ia64_getreg(_IA64_REG_AR_FCR);

                  siginfo.si_signo = SIGFPE;
                  /*
                   * (~cwd & swd) will mask out exceptions that are not set to unmasked
                   * status.  0x3f is the exception bits in these regs, 0x200 is the
                   * C1 reg you need in case of a stack fault, 0x040 is the stack
                   * fault bit.  We should only be taking one exception at a time,
                   * so if this combination doesn't produce any single exception,
                   * then we have a bad program that isn't synchronizing its FPU usage
                   * and it will suffer the consequences since we won't be able to
                   * fully reproduce the context of the exception
                   */
                  siginfo.si_isr = isr;
                  siginfo.si_flags = __ISR_VALID;
                  switch(((~fcr) & (fsr & 0x3f)) | (fsr & 0x240)) {
                        case 0x000:
                        default:
                              siginfo.si_code = 0;
                              break;
                        case 0x001: /* Invalid Op */
                        case 0x040: /* Stack Fault */
                        case 0x240: /* Stack Fault | Direction */
                              siginfo.si_code = FPE_FLTINV;
                              break;
                        case 0x002: /* Denormalize */
                        case 0x010: /* Underflow */
                              siginfo.si_code = FPE_FLTUND;
                              break;
                        case 0x004: /* Zero Divide */
                              siginfo.si_code = FPE_FLTDIV;
                              break;
                        case 0x008: /* Overflow */
                              siginfo.si_code = FPE_FLTOVF;
                              break;
                        case 0x020: /* Precision */
                              siginfo.si_code = FPE_FLTRES;
                              break;
                  }

                  break;
            }

            case 17:    /* Alignment check */
            siginfo.si_signo = SIGSEGV;
            siginfo.si_code = BUS_ADRALN;
            break;

            case 19:    /* SSE Numeric error */
            siginfo.si_signo = SIGFPE;
            siginfo.si_code = 0;
            break;

            default:
            return -1;
      }
      force_sig_info(siginfo.si_signo, &siginfo, current);
      return 0;
}

Generated by  Doxygen 1.6.0   Back to index