asmlinkage void trap_c()

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);
}