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