linux/arch/ia64/ia32/ia32_traps.c
<<
>>
Prefs
   1/*
   2 * IA-32 exception handlers
   3 *
   4 * Copyright (C) 2000 Asit K. Mallick <asit.k.mallick@intel.com>
   5 * Copyright (C) 2001-2002 Hewlett-Packard Co
   6 *      David Mosberger-Tang <davidm@hpl.hp.com>
   7 *
   8 * 06/16/00     A. Mallick      added siginfo for most cases (close to IA32)
   9 * 09/29/00     D. Mosberger    added ia32_intercept()
  10 */
  11
  12#include <linux/kernel.h>
  13#include <linux/sched.h>
  14
  15#include "ia32priv.h"
  16
  17#include <asm/intrinsics.h>
  18#include <asm/ptrace.h>
  19
  20int
  21ia32_intercept (struct pt_regs *regs, unsigned long isr)
  22{
  23        switch ((isr >> 16) & 0xff) {
  24              case 0:   /* Instruction intercept fault */
  25              case 4:   /* Locked Data reference fault */
  26              case 1:   /* Gate intercept trap */
  27                return -1;
  28
  29              case 2:   /* System flag trap */
  30                if (((isr >> 14) & 0x3) >= 2) {
  31                        /* MOV SS, POP SS instructions */
  32                        ia64_psr(regs)->id = 1;
  33                        return 0;
  34                } else
  35                        return -1;
  36        }
  37        return -1;
  38}
  39
  40int
  41ia32_exception (struct pt_regs *regs, unsigned long isr)
  42{
  43        struct siginfo siginfo;
  44
  45        /* initialize these fields to avoid leaking kernel bits to user space: */
  46        siginfo.si_errno = 0;
  47        siginfo.si_flags = 0;
  48        siginfo.si_isr = 0;
  49        siginfo.si_imm = 0;
  50        switch ((isr >> 16) & 0xff) {
  51              case 1:
  52              case 2:
  53                siginfo.si_signo = SIGTRAP;
  54                if (isr == 0)
  55                        siginfo.si_code = TRAP_TRACE;
  56                else if (isr & 0x4)
  57                        siginfo.si_code = TRAP_BRANCH;
  58                else
  59                        siginfo.si_code = TRAP_BRKPT;
  60                break;
  61
  62              case 3:
  63                siginfo.si_signo = SIGTRAP;
  64                siginfo.si_code = TRAP_BRKPT;
  65                break;
  66
  67              case 0:   /* Divide fault */
  68                siginfo.si_signo = SIGFPE;
  69                siginfo.si_code = FPE_INTDIV;
  70                break;
  71
  72              case 4:   /* Overflow */
  73              case 5:   /* Bounds fault */
  74                siginfo.si_signo = SIGFPE;
  75                siginfo.si_code = 0;
  76                break;
  77
  78              case 6:   /* Invalid Op-code */
  79                siginfo.si_signo = SIGILL;
  80                siginfo.si_code = ILL_ILLOPN;
  81                break;
  82
  83              case 7:   /* FP DNA */
  84              case 8:   /* Double Fault */
  85              case 9:   /* Invalid TSS */
  86              case 11:  /* Segment not present */
  87              case 12:  /* Stack fault */
  88              case 13:  /* General Protection Fault */
  89                siginfo.si_signo = SIGSEGV;
  90                siginfo.si_code = 0;
  91                break;
  92
  93              case 16:  /* Pending FP error */
  94                {
  95                        unsigned long fsr, fcr;
  96
  97                        fsr = ia64_getreg(_IA64_REG_AR_FSR);
  98                        fcr = ia64_getreg(_IA64_REG_AR_FCR);
  99
 100                        siginfo.si_signo = SIGFPE;
 101                        /*
 102                         * (~cwd & swd) will mask out exceptions that are not set to unmasked
 103                         * status.  0x3f is the exception bits in these regs, 0x200 is the
 104                         * C1 reg you need in case of a stack fault, 0x040 is the stack
 105                         * fault bit.  We should only be taking one exception at a time,
 106                         * so if this combination doesn't produce any single exception,
 107                         * then we have a bad program that isn't synchronizing its FPU usage
 108                         * and it will suffer the consequences since we won't be able to
 109                         * fully reproduce the context of the exception
 110                         */
 111                        siginfo.si_isr = isr;
 112                        siginfo.si_flags = __ISR_VALID;
 113                        switch(((~fcr) & (fsr & 0x3f)) | (fsr & 0x240)) {
 114                                case 0x000:
 115                                default:
 116                                        siginfo.si_code = 0;
 117                                        break;
 118                                case 0x001: /* Invalid Op */
 119                                case 0x040: /* Stack Fault */
 120                                case 0x240: /* Stack Fault | Direction */
 121                                        siginfo.si_code = FPE_FLTINV;
 122                                        break;
 123                                case 0x002: /* Denormalize */
 124                                case 0x010: /* Underflow */
 125                                        siginfo.si_code = FPE_FLTUND;
 126                                        break;
 127                                case 0x004: /* Zero Divide */
 128                                        siginfo.si_code = FPE_FLTDIV;
 129                                        break;
 130                                case 0x008: /* Overflow */
 131                                        siginfo.si_code = FPE_FLTOVF;
 132                                        break;
 133                                case 0x020: /* Precision */
 134                                        siginfo.si_code = FPE_FLTRES;
 135                                        break;
 136                        }
 137
 138                        break;
 139                }
 140
 141              case 17:  /* Alignment check */
 142                siginfo.si_signo = SIGSEGV;
 143                siginfo.si_code = BUS_ADRALN;
 144                break;
 145
 146              case 19:  /* SSE Numeric error */
 147                siginfo.si_signo = SIGFPE;
 148                siginfo.si_code = 0;
 149                break;
 150
 151              default:
 152                return -1;
 153        }
 154        force_sig_info(siginfo.si_signo, &siginfo, current);
 155        return 0;
 156}
 157