in kernel/traps.c [1000:1123]
asmlinkage void trap_c(struct frame *fp)
{
int sig, si_code;
void __user *addr;
int vector = (fp->ptregs.vector >> 2) & 0xff;
if (fp->ptregs.sr & PS_S) {
if (vector == VEC_TRACE) {
/* traced a trapping instruction on a 68020/30,
* real exception will be executed afterwards.
*/
return;
}
#ifdef CONFIG_MMU
if (fixup_exception(&fp->ptregs))
return;
#endif
bad_super_trap(fp);
return;
}
/* send the appropriate signal to the user program */
switch (vector) {
case VEC_ADDRERR:
si_code = BUS_ADRALN;
sig = SIGBUS;
break;
case VEC_ILLEGAL:
case VEC_LINE10:
case VEC_LINE11:
si_code = ILL_ILLOPC;
sig = SIGILL;
break;
case VEC_PRIV:
si_code = ILL_PRVOPC;
sig = SIGILL;
break;
case VEC_COPROC:
si_code = ILL_COPROC;
sig = SIGILL;
break;
case VEC_TRAP1:
case VEC_TRAP2:
case VEC_TRAP3:
case VEC_TRAP4:
case VEC_TRAP5:
case VEC_TRAP6:
case VEC_TRAP7:
case VEC_TRAP8:
case VEC_TRAP9:
case VEC_TRAP10:
case VEC_TRAP11:
case VEC_TRAP12:
case VEC_TRAP13:
case VEC_TRAP14:
si_code = ILL_ILLTRP;
sig = SIGILL;
break;
case VEC_FPBRUC:
case VEC_FPOE:
case VEC_FPNAN:
si_code = FPE_FLTINV;
sig = SIGFPE;
break;
case VEC_FPIR:
si_code = FPE_FLTRES;
sig = SIGFPE;
break;
case VEC_FPDIVZ:
si_code = FPE_FLTDIV;
sig = SIGFPE;
break;
case VEC_FPUNDER:
si_code = FPE_FLTUND;
sig = SIGFPE;
break;
case VEC_FPOVER:
si_code = FPE_FLTOVF;
sig = SIGFPE;
break;
case VEC_ZERODIV:
si_code = FPE_INTDIV;
sig = SIGFPE;
break;
case VEC_CHK:
case VEC_TRAP:
si_code = FPE_INTOVF;
sig = SIGFPE;
break;
case VEC_TRACE: /* ptrace single step */
si_code = TRAP_TRACE;
sig = SIGTRAP;
break;
case VEC_TRAP15: /* breakpoint */
si_code = TRAP_BRKPT;
sig = SIGTRAP;
break;
default:
si_code = ILL_ILLOPC;
sig = SIGILL;
break;
}
switch (fp->ptregs.format) {
default:
addr = (void __user *) fp->ptregs.pc;
break;
case 2:
addr = (void __user *) fp->un.fmt2.iaddr;
break;
case 7:
addr = (void __user *) fp->un.fmt7.effaddr;
break;
case 9:
addr = (void __user *) fp->un.fmt9.iaddr;
break;
case 10:
addr = (void __user *) fp->un.fmta.daddr;
break;
case 11:
addr = (void __user*) fp->un.fmtb.daddr;
break;
}
force_sig_fault(sig, si_code, addr);
}