Ejemplo n.º 1
0
void signal_frame(uint8_t *trapframe, uint32_t d0, uint32_t d1, uint32_t a0,
	uint32_t a1)
{
	extern void *udata_shadow;
	uint8_t *usp = get_usp();
	udata_ptr = udata_shadow;
	uint16_t ccr = *(uint16_t *)trapframe;
	uint32_t addr = *(uint32_t *)(trapframe + 2);
	int err = 0;

	/* Build the user stack frame */

	/* FIXME: eventually we should put the trap frame details and trap
	   info into the frame */
	usp -= 4;
	err |= uputl(addr, usp);
	usp -= 4;
	err |= uputw(ccr, usp);
	usp -= 2;
	err |=uputl(a1, usp);
	usp -= 4;
	err |= uputl(a0, usp);
	usp -= 4;
	err |= uputl(d1, usp);
	usp -= 4;
	err |= uputl(d0, usp);
	usp -= 4;
	err |= uputl(udata.u_codebase + 4, usp);
	set_usp(usp);

	if (err) {
		kprintf("%d: stack fault\n", udata.u_ptab->p_pid);
		doexit(dump_core(SIGKILL));
	}
	/* Now patch up the kernel frame */
	*(uint16_t *)trapframe = 0;
	*(uint32_t *)(trapframe + 2) = (uint32_t)udata.u_sigvec[udata.u_cursig];
	udata.u_sigvec[udata.u_cursig] = SIG_DFL;
	udata.u_cursig = 0;
}
Ejemplo n.º 2
0
int exception(struct trapdata *framedata)
{
	ptptr proc;
	unsigned int frame, fsize;
	uint8_t trap = framedata->trap;
	unsigned int sig = 0;
	uint16_t m;
	uint16_t *sp = (uint16_t *)framedata;
	uint16_t *usp = get_usp();
	uint16_t *unwind, *context;
	uint8_t err = 0;
	int i;

	/* We translate debug to SIGIOT and A and F line to SIGILL
	   We will need to fix up 68000 v 68010 move to/from SR */
	static const uint8_t trap_to_sig[] = {
		0, 0, SIGSEGV, SIGBUS, SIGILL, SIGFPE,
		SIGABRT/*CHK*/, SIGTRAP/*TRAPV */,
		SIGILL, SIGIOT, SIGILL, SIGFPE };

	proc = udata.u_ptab;

	if (sysinfo.cpu[0] == 10) {
		/* Long or short frame: the CPU tells us the frame format */
		if (framedata->exception[3] & 0x8000) {
			fsize = 29;
			frame = FRAME_C;
		} else  {
			fsize = 4;
			frame = FRAME_D;
		}
	} else {
		frame = FRAME_B;
		fsize = 3;
	}
	if (trap == 0) {
		sig = udata.u_cursig;
		udata.u_cursig = 0;
	} else if (trap < 12) {
		if (trap < 4) {
			/* On a 68010 this frame is 29 words and the event is
			   restartable (although not always usefully). We need to
			   decide whether to set the restart flag case by case */
			if (sysinfo.cpu[0] == 0) {
				frame = FRAME_A;
				fsize = 7;
			}
		}
		sig = trap_to_sig[trap];
	} else if (trap >= 32 && trap < 48)
		sig = SIGTRAP;
	/* This processing only applies to synchronous hardware exceptions */
	if (trap) {
		/* Went boom in kernel space or without a user recovery */
		if (kernel_flag || sig == 0) {
			explode(framedata, frame);
			panic("trap");
		}

		/* Cheating here .. all our exceptions are low 16 signal */
		m = 1 << sig;
		/*
		 *	The caller is ignoring our signal. In some cases this is fine
		 *	but in others it's less clear (eg division by zero) and we
		 *	may need to take different action.
		 */
		if (proc->p_sig[0].s_ignored & m)
			return 0;
		/* Weird case - we took a sync signal and the caller wants us to
		   report it later. */
		if (proc->p_sig[0].s_held & m) {
			/* TODO: if it's not meaningfully restartable we should
			   probably treat this as a kill */
			ssig(proc, sig);
			return 0;
		}
		recalc_cursig();	/* Put any async signal back */
	}
	if (udata.u_sigvec[sig] == SIG_DFL) {
		/* Default action for our signal ? */
		doexit(dump_core(sig));
		/* This will never return. We will go schedule new work */
		panic("exret");
	}
	/* build signal frame

		Our unwinder code does
		move.l 8(sp),sp
		movem.l a0-a1/d0-d1,(sp)+
		move.w (sp)+,ccr
		rts */


	/* Now update the user stack */
	/* - Push the recovery PC */
	/* - Patch the kernel exception frame */
	if (sysinfo.cpu[0]) {
		/* FIXME */
		err |= pushw(&usp, sp[34]);
		err |= pushw(&usp, sp[33]);
		*(uint32_t *)(&sp[33]) = (uint32_t)udata.u_sigvec[sig];
	} else {
		err |= pushw(&usp, sp[31 + fsize]);
		err |= pushw(&usp, sp[30 + fsize]);
		*(uint32_t *)(&sp[30 + fsize]) = (uint32_t)udata.u_sigvec[sig];
	}

	/* FIXME: when we do ptrace we will need to support adding the T
	   flag back here as the exception cleared it */
	err |= pushw(&usp,  framedata->sr);
	/* Push A1 A0 D1 D0 to match MOVEM.L */
	err |= pushl(&usp, framedata->a[1]);
	err |= pushl(&usp, framedata->a[0]);
	err |= pushl(&usp, framedata->d[1]);
	err |= pushl(&usp, framedata->d[0]);

	/* Remember the target for undoing the frame */
	unwind = usp;

	/* Copy in the signal context itself. 30 words of registers, 2 of
	   trap code and then the hardware exception */
	for (i = 0; i < 30 + 2 + fsize; i++)
		err |= pushw(&usp, *sp++);
	context = usp;
	err |= pushl(&usp, (uint32_t)unwind);
	/* Signal context is a secret extra non portable argument */
	err |= pushl(&usp, (uint32_t)context);
	/* We end it with the call frame as seen from the signal handler, a
	   single argument and a return address */
	err |= pushl(&usp, sig);
	err |= pushl(&usp, udata.u_codebase + 0x04);

	set_usp(usp);

	if (err) {
		doexit(dump_core(SIGSTKFLT));
		panic("exret2");
	}
	/* Once built clear the restart state */
	udata.u_sigvec[sig] = SIG_DFL;
	/* Return, RTE and end up on the signal frame */
	return 1;
}