Example #1
0
int
netbsd32_cpu_setmcontext(
	struct lwp *l,
	/* XXX const netbsd32_*/mcontext_t *mcp,
	unsigned int flags)
{
#ifdef NOT_YET
/* XXX */
	greg32_t *gr = mcp->__gregs;
	struct trapframe64 *tf = l->l_md.md_tf;

	/* First ensure consistent stack state (see sendsig). */
	write_user_windows();
	if (rwindow_save(p)) {
		mutex_enter(l->l_proc->p_lock);
		sigexit(p, SIGILL);
	}

	if ((flags & _UC_CPU) != 0) {
		/*
	 	 * Only the icc bits in the psr are used, so it need not be
	 	 * verified.  pc and npc must be multiples of 4.  This is all
	 	 * that is required; if it holds, just do it.
		 */
		if (((gr[_REG_PC] | gr[_REG_nPC]) & 3) != 0 ||
		    gr[_REG_PC] == 0 || gr[_REG_nPC] == 0)
			return (EINVAL);

		/* Restore general register context. */
		/* take only tstate CCR (and ASI) fields */
		tf->tf_tstate = (tf->tf_tstate & ~TSTATE_CCR) |
		    PSRCC_TO_TSTATE(gr[_REG_PSR]);
		tf->tf_pc        = (uint64_t)gr[_REG_PC];
		tf->tf_npc       = (uint64_t)gr[_REG_nPC];
		tf->tf_y         = (uint64_t)gr[_REG_Y];
		tf->tf_global[1] = (uint64_t)gr[_REG_G1];
		tf->tf_global[2] = (uint64_t)gr[_REG_G2];
		tf->tf_global[3] = (uint64_t)gr[_REG_G3];
		tf->tf_global[4] = (uint64_t)gr[_REG_G4];
		tf->tf_global[5] = (uint64_t)gr[_REG_G5];
		tf->tf_global[6] = (uint64_t)gr[_REG_G6];
		tf->tf_global[7] = (uint64_t)gr[_REG_G7];
		tf->tf_out[0]    = (uint64_t)gr[_REG_O0];
		tf->tf_out[1]    = (uint64_t)gr[_REG_O1];
		tf->tf_out[2]    = (uint64_t)gr[_REG_O2];
		tf->tf_out[3]    = (uint64_t)gr[_REG_O3];
		tf->tf_out[4]    = (uint64_t)gr[_REG_O4];
		tf->tf_out[5]    = (uint64_t)gr[_REG_O5];
		tf->tf_out[6]    = (uint64_t)gr[_REG_O6];
		tf->tf_out[7]    = (uint64_t)gr[_REG_O7];
		/* %asi restored above; %fprs not yet supported. */

		/* XXX mcp->__gwins */
	}

	/* Restore FP register context, if any. */
	if ((flags & _UC_FPU) != 0 && mcp->__fpregs.__fpu_en != 0) {
		struct fpstate *fsp;
		const netbsd32_fpregset_t *fpr = &mcp->__fpregs;
		int reload = 0;

		/*
		 * If we're the current FPU owner, simply reload it from
		 * the supplied context.  Otherwise, store it into the
		 * process' FPU save area (which is used to restore from
		 * by lazy FPU context switching); allocate it if necessary.
		 */
		/*
		 * XXX Should we really activate the supplied FPU context
		 * XXX immediately or just fault it in later?
		 */
		if ((fsp = l->l_md.md_fpstate) == NULL) {
			fsp = pool_cache_get(fpstate_cache, PR_WAITOK);
			l->l_md.md_fpstate = fsp;
		} else {
			/* Drop the live context on the floor. */
			fpusave_lwp(l, false);
			reload = 1;
		}
		/* Note: sizeof fpr->__fpu_fr <= sizeof fsp->fs_regs. */
		memcpy(fsp->fs_regs, fpr->__fpu_fr, sizeof (fpr->__fpu_fr));
		fsp->fs_fsr = fpr->__fpu_fsr;	/* don't care about fcc1-3 */
		fsp->fs_qsize = 0;

#if 0
		/* Need more info! */
		mcp->__fpregs.__fpu_q = NULL;	/* `Need more info.' */
		mcp->__fpregs.__fpu_qcnt = 0 /*fs.fs_qsize*/; /* See above */
#endif

		/* Reload context again, if necessary. */
		if (reload)
			loadfpstate(fsp);
	}

	/* XXX mcp->__xrs */
	/* XXX mcp->__asrs */
#endif
	return (0);
}
Example #2
0
/* ARGSUSED */
int
compat_16_netbsd32___sigreturn14(struct lwp *l, const struct compat_16_netbsd32___sigreturn14_args *uap, register_t *retval)
{
	/* {
		syscallarg(struct sigcontext *) sigcntxp;
	} */
	struct netbsd32_sigcontext sc, *scp;
	struct trapframe64 *tf;
	struct proc *p = l->l_proc;

	/* First ensure consistent stack state (see sendsig). */
	write_user_windows();
	if (rwindow_save(l)) {
#ifdef DEBUG
		printf("netbsd32_sigreturn14: rwindow_save(%p) failed, sending SIGILL\n", p);
		Debugger();
#endif
		mutex_enter(p->p_lock);
		sigexit(l, SIGILL);
	}
#ifdef DEBUG
	if (sigdebug & SDB_FOLLOW) {
		printf("netbsd32_sigreturn14: %s[%d], sigcntxp %p\n",
		    p->p_comm, p->p_pid, SCARG(uap, sigcntxp));
		if (sigdebug & SDB_DDB) Debugger();
	}
#endif
	scp = (struct netbsd32_sigcontext *)(u_long)SCARG(uap, sigcntxp);
 	if ((vaddr_t)scp & 3 || (copyin((void *)scp, &sc, sizeof sc) != 0))
	{
#ifdef DEBUG
		printf("netbsd32_sigreturn14: copyin failed: scp=%p\n", scp);
		Debugger();
#endif
		return (EINVAL);
	}
	scp = &sc;

	tf = l->l_md.md_tf;
	/*
	 * Only the icc bits in the psr are used, so it need not be
	 * verified.  pc and npc must be multiples of 4.  This is all
	 * that is required; if it holds, just do it.
	 */
	if (((sc.sc_pc | sc.sc_npc) & 3) != 0 || (sc.sc_pc == 0) || (sc.sc_npc == 0))
#ifdef DEBUG
	{
		printf("netbsd32_sigreturn14: pc %p or npc %p invalid\n", sc.sc_pc, sc.sc_npc);
		Debugger();
		return (EINVAL);
	}
#else
		return (EINVAL);
#endif
	/* take only psr ICC field */
	tf->tf_tstate = (int64_t)(tf->tf_tstate & ~TSTATE_CCR) | PSRCC_TO_TSTATE(sc.sc_psr);
	tf->tf_pc = (int64_t)sc.sc_pc;
	tf->tf_npc = (int64_t)sc.sc_npc;
	tf->tf_global[1] = (int64_t)sc.sc_g1;
	tf->tf_out[0] = (int64_t)sc.sc_o0;
	tf->tf_out[6] = (int64_t)sc.sc_sp;
#ifdef DEBUG
	if (sigdebug & SDB_FOLLOW) {
		printf("netbsd32_sigreturn14: return trapframe pc=%p sp=%p tstate=%llx\n",
		       (vaddr_t)tf->tf_pc, (vaddr_t)tf->tf_out[6], tf->tf_tstate);
		if (sigdebug & SDB_DDB) Debugger();
	}
#endif

	/* Restore signal stack. */
	mutex_enter(p->p_lock);
	if (sc.sc_onstack & SS_ONSTACK)
		l->l_sigstk.ss_flags |= SS_ONSTACK;
	else
		l->l_sigstk.ss_flags &= ~SS_ONSTACK;
	/* Restore signal mask. */
	(void) sigprocmask1(l, SIG_SETMASK, &sc.sc_mask, 0);
	mutex_exit(p->p_lock);

	return (EJUSTRETURN);
}
Example #3
0
void
netbsd32_cpu_getmcontext(
	struct lwp *l,
	/* netbsd32_mcontext_t XXX */mcontext_t  *mcp,
	unsigned int *flags)
{
#if 0
/* XXX */
	greg32_t *gr = mcp->__gregs;
	const struct trapframe64 *tf = l->l_md.md_tf;

	/* First ensure consistent stack state (see sendsig). */ /* XXX? */
	write_user_windows();
	if (rwindow_save(l)) {
		mutex_enter(l->l_proc->p_lock);
		sigexit(l, SIGILL);
	}

	/* For now: Erase any random indicators for optional state. */
	(void)memset(mcp, 0, sizeof (*mcp));

	/* Save general register context. */
	gr[_REG_PSR] = TSTATECCR_TO_PSR(tf->tf_tstate);
	gr[_REG_PC]  = tf->tf_pc;
	gr[_REG_nPC] = tf->tf_npc;
	gr[_REG_Y]   = tf->tf_y;
	gr[_REG_G1]  = tf->tf_global[1];
	gr[_REG_G2]  = tf->tf_global[2];
	gr[_REG_G3]  = tf->tf_global[3];
	gr[_REG_G4]  = tf->tf_global[4];
	gr[_REG_G5]  = tf->tf_global[5];
	gr[_REG_G6]  = tf->tf_global[6];
	gr[_REG_G7]  = tf->tf_global[7];
	gr[_REG_O0]  = tf->tf_out[0];
	gr[_REG_O1]  = tf->tf_out[1];
	gr[_REG_O2]  = tf->tf_out[2];
	gr[_REG_O3]  = tf->tf_out[3];
	gr[_REG_O4]  = tf->tf_out[4];
	gr[_REG_O5]  = tf->tf_out[5];
	gr[_REG_O6]  = tf->tf_out[6];
	gr[_REG_O7]  = tf->tf_out[7];
	*flags |= (_UC_CPU|_UC_TLSBASE);

	mcp->__gwins = 0;


	/* Save FP register context, if any. */
	if (l->l_md.md_fpstate != NULL) {
		struct fpstate *fsp;
		netbsd32_fpregset_t *fpr = &mcp->__fpregs;

		/*
		 * If our FP context is currently held in the FPU, take a
		 * private snapshot - lazy FPU context switching can deal
		 * with it later when it becomes necessary.
		 * Otherwise, get it from the process's save area.
		 */
		fpusave_lwp(l, true);
		fsp = l->l_md.md_fpstate;
		memcpy(&fpr->__fpu_fr, fsp->fs_regs, sizeof (fpr->__fpu_fr));
		mcp->__fpregs.__fpu_q = NULL;	/* `Need more info.' */
		mcp->__fpregs.__fpu_fsr = fs.fs_fsr;
		mcp->__fpregs.__fpu_qcnt = 0 /*fs.fs_qsize*/; /* See above */
		mcp->__fpregs.__fpu_q_entrysize =
		    sizeof (struct netbsd32_fq);
		mcp->__fpregs.__fpu_en = 1;
		*flags |= _UC_FPU;
	} else {
		mcp->__fpregs.__fpu_en = 0;
	}

	mcp->__xrs.__xrs_id = 0;	/* Solaris extension? */
#endif
}
Example #4
0
int
cpu_setmcontext32(struct lwp *l, const mcontext32_t *mcp, unsigned int flags)
{
	struct trapframe *tf = l->l_md.md_tf;
	const __greg32_t *gr = mcp->__gregs;
	struct proc *p = l->l_proc;
	int error;

	/* First ensure consistent stack state (see sendsig). */
	write_user_windows();
	if (rwindow_save(l)) {
		mutex_enter(p->p_lock);
		sigexit(l, SIGILL);
	}

	/* Restore register context, if any. */
	if ((flags & _UC_CPU) != 0) {
		error = cpu_mcontext32_validate(l, mcp);
		if (error)
			return error;

		/* Restore general register context. */
		/* take only tstate CCR (and ASI) fields */
		tf->tf_tstate = (tf->tf_tstate & ~TSTATE_CCR) |
		    PSRCC_TO_TSTATE(gr[_REG32_PSR]);
		tf->tf_pc        = (uint64_t)gr[_REG32_PC];
		tf->tf_npc       = (uint64_t)gr[_REG32_nPC];
		tf->tf_y         = (uint64_t)gr[_REG32_Y];
		tf->tf_global[1] = (uint64_t)gr[_REG32_G1];
		tf->tf_global[2] = (uint64_t)gr[_REG32_G2];
		tf->tf_global[3] = (uint64_t)gr[_REG32_G3];
		tf->tf_global[4] = (uint64_t)gr[_REG32_G4];
		tf->tf_global[5] = (uint64_t)gr[_REG32_G5];
		tf->tf_global[6] = (uint64_t)gr[_REG32_G6];
		/* done in lwp_setprivate */
		/* tf->tf_global[7] = (uint64_t)gr[_REG32_G7]; */
		tf->tf_out[0]    = (uint64_t)gr[_REG32_O0];
		tf->tf_out[1]    = (uint64_t)gr[_REG32_O1];
		tf->tf_out[2]    = (uint64_t)gr[_REG32_O2];
		tf->tf_out[3]    = (uint64_t)gr[_REG32_O3];
		tf->tf_out[4]    = (uint64_t)gr[_REG32_O4];
		tf->tf_out[5]    = (uint64_t)gr[_REG32_O5];
		tf->tf_out[6]    = (uint64_t)gr[_REG32_O6];
		tf->tf_out[7]    = (uint64_t)gr[_REG32_O7];
		/* %asi restored above; %fprs not yet supported. */

		if (flags & _UC_TLSBASE)
			lwp_setprivate(l, (void *)(uintptr_t)gr[_REG32_G7]);

		/* XXX mcp->__gwins */
	}

	/* Restore floating point register context, if any. */
	if ((flags & _UC_FPU) != 0) {
#ifdef notyet
		struct fpstate64 *fsp;
		const __fpregset_t *fpr = &mcp->__fpregs;

		/*
		 * If we're the current FPU owner, simply reload it from
		 * the supplied context.  Otherwise, store it into the
		 * process' FPU save area (which is used to restore from
		 * by lazy FPU context switching); allocate it if necessary.
		 */
		if ((fsp = l->l_md.md_fpstate) == NULL) {
			fsp = pool_cache_get(fpstate_cache, PR_WAITOK);
			l->l_md.md_fpstate = fsp;
		} else {
			/* Drop the live context on the floor. */
			fpusave_lwp(l, false);
		}
		/* Note: sizeof fpr->__fpu_fr <= sizeof fsp->fs_regs. */
		memcpy(fsp->fs_regs, &fpr->__fpu_fr, sizeof (fpr->__fpu_fr));
		fsp->fs_fsr = mcp->__fpregs.__fpu_fsr;
		fsp->fs_qsize = 0;

#if 0
		/* Need more info! */
		mcp->__fpregs.__fpu_q = NULL;	/* `Need more info.' */
		mcp->__fpregs.__fpu_qcnt = 0 /*fs.fs_qsize*/; /* See above */
#endif
#endif
	}
#ifdef _UC_SETSTACK
	mutex_enter(p->p_lock);
	if (flags & _UC_SETSTACK)
		l->l_sigstk.ss_flags |= SS_ONSTACK;
	if (flags & _UC_CLRSTACK)
		l->l_sigstk.ss_flags &= ~SS_ONSTACK;
	mutex_exit(p->p_lock);
#endif
	return (0);
}
Example #5
0
static void
netbsd32_sendsig_sigcontext(const ksiginfo_t *ksi, const sigset_t *mask)
{
	int sig = ksi->ksi_signo;
	struct lwp *l = curlwp;
	struct proc *p = l->l_proc;
	struct sparc32_sigframe *fp;
	struct trapframe64 *tf;
	int addr, onstack, error;
	struct rwindow32 *oldsp, *newsp;
	register32_t sp;
	sig_t catcher = SIGACTION(p, sig).sa_handler;
	struct sparc32_sigframe sf;
	extern char netbsd32_sigcode[], netbsd32_esigcode[];
#define	szsigcode	(netbsd32_esigcode - netbsd32_sigcode)

	tf = l->l_md.md_tf;
	/* Need to attempt to zero extend this 32-bit pointer */
	oldsp = (struct rwindow32 *)(u_long)(u_int)tf->tf_out[6];
	/* Do we need to jump onto the signal stack? */
	onstack =
	    (l->l_sigstk.ss_flags & (SS_DISABLE | SS_ONSTACK)) == 0 &&
	    (SIGACTION(p, sig).sa_flags & SA_ONSTACK) != 0;
	if (onstack) {
		fp = (struct sparc32_sigframe *)((char *)l->l_sigstk.ss_sp +
					l->l_sigstk.ss_size);
		l->l_sigstk.ss_flags |= SS_ONSTACK;
	} else
		fp = (struct sparc32_sigframe *)oldsp;
	fp = (struct sparc32_sigframe *)((u_long)(fp - 1) & ~7);

#ifdef DEBUG
	sigpid = p->p_pid;
	if ((sigdebug & SDB_KSTACK) && p->p_pid == sigpid) {
		printf("sendsig: %s[%d] sig %d newusp %p scp %p oldsp %p\n",
		    p->p_comm, p->p_pid, sig, fp, &fp->sf_sc, oldsp);
		if (sigdebug & SDB_DDB) Debugger();
	}
#endif
	/*
	 * Now set up the signal frame.  We build it in kernel space
	 * and then copy it out.  We probably ought to just build it
	 * directly in user space....
	 */
	sf.sf_signo = sig;
	sf.sf_code = (u_int)ksi->ksi_trap;
#if defined(COMPAT_SUNOS) || defined(MODULAR)
	sf.sf_scp = (u_long)&fp->sf_sc;
#endif
	sf.sf_addr = 0;			/* XXX */

	/*
	 * Build the signal context to be used by sigreturn.
	 */
	sf.sf_sc.sc_onstack = onstack;
	sf.sf_sc.sc_mask = *mask;
	sf.sf_sc.sc_sp = (u_long)oldsp;
	sf.sf_sc.sc_pc = tf->tf_pc;
	sf.sf_sc.sc_npc = tf->tf_npc;
	sf.sf_sc.sc_psr = TSTATECCR_TO_PSR(tf->tf_tstate); /* XXX */
	sf.sf_sc.sc_g1 = tf->tf_global[1];
	sf.sf_sc.sc_o0 = tf->tf_out[0];

	/*
	 * Put the stack in a consistent state before we whack away
	 * at it.  Note that write_user_windows may just dump the
	 * registers into the pcb; we need them in the process's memory.
	 * We also need to make sure that when we start the signal handler,
	 * its %i6 (%fp), which is loaded from the newly allocated stack area,
	 * joins seamlessly with the frame it was in when the signal occurred,
	 * so that the debugger and _longjmp code can back up through it.
	 */
	sendsig_reset(l, sig);
	mutex_exit(p->p_lock);
	newsp = (struct rwindow32 *)((long)fp - sizeof(struct rwindow32));
	write_user_windows();
#ifdef DEBUG
	if ((sigdebug & SDB_KSTACK))
	    printf("sendsig: saving sf to %p, setting stack pointer %p to %p\n",
		   fp, &(((struct rwindow32 *)newsp)->rw_in[6]), oldsp);
#endif
	sp = NETBSD32PTR32I(oldsp);
	error = (rwindow_save(l) || 
	    copyout(&sf, fp, sizeof sf) || 
	    copyout(&sp, &(((struct rwindow32 *)newsp)->rw_in[6]),
	        sizeof(sp)));
	mutex_enter(p->p_lock);
	if (error) {
		/*
		 * Process has trashed its stack; give it an illegal
		 * instruction to halt it in its tracks.
		 */
#ifdef DEBUG
		mutex_exit(p->p_lock);
		if ((sigdebug & SDB_KSTACK) && p->p_pid == sigpid)
			printf("sendsig: window save or copyout error\n");
		printf("sendsig: stack was trashed trying to send sig %d, sending SIGILL\n", sig);
		if (sigdebug & SDB_DDB) Debugger();
		mutex_enter(p->p_lock);
#endif
		sigexit(l, SIGILL);
		/* NOTREACHED */
	}

#ifdef DEBUG
	if (sigdebug & SDB_FOLLOW) {
		printf("sendsig: %s[%d] sig %d scp %p\n",
		       p->p_comm, p->p_pid, sig, &fp->sf_sc);
	}
#endif
	/*
	 * Arrange to continue execution at the code copied out in exec().
	 * It needs the function to call in %g1, and a new stack pointer.
	 */
	addr = p->p_psstrp - szsigcode;
	tf->tf_global[1] = (long)catcher;
	tf->tf_pc = addr;
	tf->tf_npc = addr + 4;
	tf->tf_out[6] = (uint64_t)(u_int)(u_long)newsp;

	/* Remember that we're now on the signal stack. */
	if (onstack)
		l->l_sigstk.ss_flags |= SS_ONSTACK;

#ifdef DEBUG
	if ((sigdebug & SDB_KSTACK) && p->p_pid == sigpid) {
		mutex_exit(p->p_lock);
		printf("sendsig: about to return to catcher %p thru %p\n", 
		       catcher, addr);
		if (sigdebug & SDB_DDB) Debugger();
		mutex_enter(p->p_lock);
	}
#endif
}
Example #6
0
void sunos_sendsig(const ksiginfo_t *ksi, const sigset_t *mask)
{
	struct lwp *l = curlwp;
	struct proc *p = l->l_proc;
	struct sunos_sigframe *fp;
	struct trapframe *tf;
	int addr, onstack, oldsp, newsp, error;
	int sig = ksi->ksi_signo;
	u_long code = ksi->ksi_code;
	sig_t catcher = SIGACTION(p, sig).sa_handler;
	struct sunos_sigframe sf;

	tf = l->l_md.md_tf;
	oldsp = tf->tf_out[6];

	/*
	 * Compute new user stack addresses, subtract off
	 * one signal frame, and align.
	 */
	onstack =
	    (l->l_sigstk.ss_flags & (SS_DISABLE | SS_ONSTACK)) == 0 &&
	    (SIGACTION(p, sig).sa_flags & SA_ONSTACK) != 0;

	if (onstack)
		fp = (struct sunos_sigframe *)
		     ((char *)l->l_sigstk.ss_sp + l->l_sigstk.ss_size);
	else
		fp = (struct sunos_sigframe *)oldsp;

	fp = (struct sunos_sigframe *)((int)(fp - 1) & ~7);

#ifdef DEBUG
	if ((sunos_sigdebug & SDB_KSTACK) && p->p_pid == sunos_sigpid)
		printf("sendsig: %s[%d] sig %d newusp %p scp %p\n",
		    p->p_comm, p->p_pid, sig, fp, &fp->sf_sc);
#endif
	/*
	 * Now set up the signal frame.  We build it in kernel space
	 * and then copy it out.  We probably ought to just build it
	 * directly in user space....
	 */
	sf.sf_signo = sig;
	sf.sf_code = code;
	sf.sf_scp = &fp->sf_sc;
	sf.sf_addr = 0;			/* XXX */

	/*
	 * Build the signal context to be used by sigreturn.
	 */
	sf.sf_sc.sc_onstack = l->l_sigstk.ss_flags & SS_ONSTACK;
	native_sigset_to_sigset13(mask, &sf.sf_sc.sc_mask);
	sf.sf_sc.sc_sp = oldsp;
	sf.sf_sc.sc_pc = tf->tf_pc;
	sf.sf_sc.sc_npc = tf->tf_npc;
	sf.sf_sc.sc_psr = tf->tf_psr;
	sf.sf_sc.sc_g1 = tf->tf_global[1];
	sf.sf_sc.sc_o0 = tf->tf_out[0];

	/*
	 * Put the stack in a consistent state before we whack away
	 * at it.  Note that write_user_windows may just dump the
	 * registers into the pcb; we need them in the process's memory.
	 * We also need to make sure that when we start the signal handler,
	 * its %i6 (%fp), which is loaded from the newly allocated stack area,
	 * joins seamlessly with the frame it was in when the signal occurred,
	 * so that the debugger and _longjmp code can back up through it.
	 */
	sendsig_reset(l, sig);
	mutex_exit(p->p_lock);
	newsp = (int)fp - sizeof(struct rwindow);
	write_user_windows();
	error = (rwindow_save(l) || copyout((void *)&sf, (void *)fp, sizeof sf) ||
	    suword(&((struct rwindow *)newsp)->rw_in[6], oldsp));
	mutex_enter(p->p_lock);

	if (error) {
		/*
		 * Process has trashed its stack; give it an illegal
		 * instruction to halt it in its tracks.
		 */
#ifdef DEBUG
		if ((sunos_sigdebug & SDB_KSTACK) && p->p_pid == sunos_sigpid)
			printf("sendsig: window save or copyout error\n");
#endif
		sigexit(l, SIGILL);
		/* NOTREACHED */
	}
#ifdef DEBUG
	if (sunos_sigdebug & SDB_FOLLOW)
		printf("sendsig: %s[%d] sig %d scp %p\n",
		       p->p_comm, p->p_pid, sig, &fp->sf_sc);
#endif
	/*
	 * Arrange to continue execution at the code copied out in exec().
	 * It needs the function to call in %g1, and a new stack pointer.
	 */
	addr = (int)catcher;	/* user does his own trampolining */
	tf->tf_pc = addr;
	tf->tf_npc = addr + 4;
	tf->tf_out[6] = newsp;

	/* Remember that we're now on the signal stack. */
	if (onstack)
		l->l_sigstk.ss_flags |= SS_ONSTACK;

#ifdef DEBUG
	if ((sunos_sigdebug & SDB_KSTACK) && p->p_pid == sunos_sigpid)
		printf("sendsig: about to return to catcher\n");
#endif
}
/*
 * Send an interrupt to process.
 *
 * Stack is set up to allow sigcode stored
 * in u. to call routine. After the handler is
 * done svr4 will call setcontext for us
 * with the user context we just set up, and we
 * will return to the user pc, psl.
 */
void
svr4_32_sendsig(const ksiginfo_t *ksi, const sigset_t *mask)
{
	int sig = ksi->ksi_signo;
	register struct lwp *l = curlwp;
	struct proc *p = l->l_proc;
	register struct trapframe64 *tf;
	struct svr4_32_sigframe *fp, frame;
	int onstack, error;
	vaddr_t oldsp, newsp, addr;
	sig_t catcher = SIGACTION(p, sig).sa_handler;
	sigset_t tmask;

	tf = (struct trapframe64 *)l->l_md.md_tf;
	oldsp = tf->tf_out[6];

	/* Do we need to jump onto the signal stack? */
	onstack =
	    (l->l_sigstk.ss_flags & (SS_DISABLE | SS_ONSTACK)) == 0 &&
	    (SIGACTION(p, sig).sa_flags & SA_ONSTACK) != 0;

	/*
	 * Allocate space for the signal handler context.
	 */
	if (onstack)
		fp = (struct svr4_32_sigframe *)((char *)l->l_sigstk.ss_sp +
						l->l_sigstk.ss_size);
	else
		fp = (struct svr4_32_sigframe *)oldsp;
	fp = (struct svr4_32_sigframe *) ((long) (fp - 1) & ~7);

#ifdef DEBUG
	sigpid = p->p_pid;
	if ((sigdebug & SDB_KSTACK) && p->p_pid == sigpid) {
		printf("svr4_32_sendsig: %s[%d] sig %d newusp %p scp %p oldsp %p\n",
		    p->p_comm, p->p_pid, sig, fp, &fp->sf_uc, (void *)(u_long)oldsp);
#ifdef DDB
		if (sigdebug & SDB_DDB) Debugger();
#endif
	}
#endif
	/*
	 * Build the argument list for the signal handler.
	 */
	svr4_32_getsiginfo(&frame.sf_si, sig, ksi->ksi_trap,
	    (void *)(u_long)tf->tf_pc);

	/* Build stack frame for signal trampoline. */
	frame.sf_signum = frame.sf_si.si_signo;
	NETBSD32PTR32(frame.sf_sip, &fp->sf_si);
	NETBSD32PTR32(frame.sf_ucp, &fp->sf_uc);
	frame.sf_handler = catcher;

	DPRINTF(("svr4_32_sendsig signum=%d si = %p uc = %p handler = %p\n",
	         frame.sf_signum, frame.sf_sip,
		 frame.sf_ucp, frame.sf_handler));
	/*
	 * Modify the signal context to be used by sigreturn.
	 */
	tmask = *mask;
	sendsig_reset(l, sig);
	frame.sf_uc.uc_mcontext.greg[SVR4_SPARC_SP] = oldsp;
	newsp = (u_long)fp - sizeof(struct rwindow32);
	mutex_exit(p->p_lock);
	svr4_32_getcontext(l, &frame.sf_uc, &tmask);
	write_user_windows();

#ifdef DEBUG
	if ((sigdebug & SDB_KSTACK))
	    printf("svr4_32_sendsig: saving sf to %p, setting stack pointer %p to %p\n",
		   fp, &(((struct rwindow32 *)newsp)->rw_in[6]), (void *)(u_long)oldsp);
#endif
	error = (rwindow_save(l) || copyout(&frame, fp, sizeof(frame)) != 0 ||
	    copyout(&oldsp, &((struct rwindow32 *)newsp)->rw_in[6], sizeof(oldsp)));
	mutex_enter(p->p_lock);

	if (error) {
		/*
		 * Process has trashed its stack; give it an illegal
		 * instruction to halt it in its tracks.
		 */
#ifdef DEBUG
		mutex_exit(p->p_lock);
		if ((sigdebug & SDB_KSTACK) && p->p_pid == sigpid)
			printf("svr4_32_sendsig: window save or copyout error\n");
		printf("svr4_32_sendsig: stack was trashed trying to send sig %d, sending SIGILL\n", sig);
#ifdef DDB
		Debugger();
#endif
		mutex_enter(p->p_lock);
#endif
		sigexit(l, SIGILL);
		/* NOTREACHED */
	}

#ifdef DEBUG
	if (sigdebug & SDB_FOLLOW) {
		printf("svr4_32_sendsig: %s[%d] sig %d scp %p\n",
		       p->p_comm, p->p_pid, sig, &fp->sf_uc);
	}
#endif
	/*
	 * Build context to run handler in.
	 */
	addr = (vaddr_t)p->p_sigctx.ps_sigcode;
	tf->tf_pc = addr;
	tf->tf_npc = addr + 4;
	tf->tf_global[1] = (vaddr_t)catcher;
	tf->tf_out[6] = newsp;

	/* Remember that we're now on the signal stack. */
	if (onstack)
		l->l_sigstk.ss_flags |= SS_ONSTACK;
#ifdef DEBUG
	if ((sigdebug & SDB_KSTACK) && p->p_pid == sigpid) {
		mutex_exit(p->p_lock);
		printf("svr4_32_sendsig: about to return to catcher %p thru %p\n", 
		       catcher, (void *)(u_long)addr);
#ifdef DDB
		if (sigdebug & SDB_DDB) Debugger();
#endif
		mutex_enter(p->p_lock);
	}
#endif
}
/*
 * Set to mcontext specified.
 * Return to previous pc and psl as specified by
 * context left by sendsig. Check carefully to
 * make sure that the user has not modified the
 * psl to gain improper privileges or to cause
 * a machine fault.
 * This is almost like sigreturn() and it shows.
 */
int
svr4_32_setmcontext(struct lwp *l, struct svr4_32_mcontext *mc,
	netbsd32_u_long flags)
{
	register struct trapframe64 *tf;
	svr4_32_greg_t *r = mc->greg;
#ifdef FPU_CONTEXT
	svr4_32_fregset_t *f = &mc->freg;
	struct fpstate64 *fps = p->p_md.md_fpstate;
#endif

#ifdef DEBUG_SVR4
	svr4_32_printmcontext("setmcontext", uc);
#endif

	write_user_windows();
	if (rwindow_save(l)) {
#ifdef DEBUG
		printf("svr4_32_setcontext: rwindow_save(%p) failed, sending SIGILL\n", l);
#ifdef DDB
		Debugger();
#endif
#endif
		mutex_enter(l->l_proc->p_lock);
		sigexit(l, SIGILL);
	}

#ifdef DEBUG
	if (sigdebug & SDB_FOLLOW)
		printf("svr4_32_setmcontext: %s[%d], svr4_32_mcontext %p\n",
		    l->l_proc->p_comm, l->l_proc->p_pid, mc);
#endif

	if (flags & SVR4_UC_CPU) {
		/* Restore register context. */
		tf = (struct trapframe64 *)l->l_md.md_tf;

		/*
		 * Only the icc bits in the psr are used, so it need not be
		 * verified.  pc and npc must be multiples of 4.  This is all
		 * that is required; if it holds, just do it.
		 */
		if (((r[SVR4_SPARC_PC] | r[SVR4_SPARC_nPC]) & 3) != 0) {
			printf("pc or npc are not multiples of 4!\n");
			return EINVAL;
		}

		/* take only psr ICC field */
		tf->tf_tstate = (tf->tf_tstate & ~TSTATE_CCR) |
		    PSRCC_TO_TSTATE(r[SVR4_SPARC_PSR]);
		tf->tf_pc = r[SVR4_SPARC_PC];
		tf->tf_npc = r[SVR4_SPARC_nPC];
		tf->tf_y = r[SVR4_SPARC_Y];

		/* Restore everything */
		tf->tf_global[1] = r[SVR4_SPARC_G1];
		tf->tf_global[2] = r[SVR4_SPARC_G2];
		tf->tf_global[3] = r[SVR4_SPARC_G3];
		tf->tf_global[4] = r[SVR4_SPARC_G4];
		tf->tf_global[5] = r[SVR4_SPARC_G5];
		tf->tf_global[6] = r[SVR4_SPARC_G6];
		tf->tf_global[7] = r[SVR4_SPARC_G7];

		tf->tf_out[0] = r[SVR4_SPARC_O0];
		tf->tf_out[1] = r[SVR4_SPARC_O1];
		tf->tf_out[2] = r[SVR4_SPARC_O2];
		tf->tf_out[3] = r[SVR4_SPARC_O3];
		tf->tf_out[4] = r[SVR4_SPARC_O4];
		tf->tf_out[5] = r[SVR4_SPARC_O5];
		tf->tf_out[6] = r[SVR4_SPARC_O6];
		tf->tf_out[7] = r[SVR4_SPARC_O7];
	}


#ifdef FPU_CONTEXT
	if (flags & SVR4_UC_FPU) {
		/*
		 * Set the floating point registers
		 */
		int error;
		size_t sz = f->fp_nqel * f->fp_nqsize;
		if (sz > sizeof(fps->fs_queue)) {
#ifdef DIAGNOSTIC
			printf("setmcontext: fp_queue too large\n");
#endif
			return EINVAL;
		}
		/* Note: touches only pre-v9 floating point registers. */
		memcpy(fps->fs_regs, f->fpu_regs, sizeof(f->fpu_regs));
		fps->fs_qsize = f->fp_nqel;
		fps->fs_fsr = f->fp_fsr;
		if (f->fp_q != 0) {
			if ((error = copyin((void *)(u_long)f->fp_q,
			                    fps->fs_queue,
					    f->fp_nqel * f->fp_nqsize)) != 0) {
#ifdef DIAGNOSTIC
				printf("setmcontext: fp_queue copy failed\n");
#endif
				return error;
			}
		}
	}
#endif

	return 0;
}
void *
svr4_32_getmcontext(struct lwp *l, struct svr4_32_mcontext *mc,
	netbsd32_u_long *flags)
{
	struct trapframe64 *tf = (struct trapframe64 *)l->l_md.md_tf;
	svr4_32_greg_t *r = mc->greg;
#ifdef FPU_CONTEXT
	svr4_32_fregset_t *f = &mc->freg;
	struct fpstate *fps = l->l_md.md_fpstate;
#endif

	write_user_windows();
	if (rwindow_save(l)) {
#ifdef DEBUG
		printf("svr4_32_getcontext: rwindow_save(%p) failed, sending SIGILL\n", l);
#ifdef DDB
		Debugger();
#endif
#endif
		mutex_enter(l->l_proc->p_lock);
		sigexit(l, SIGILL);
	}

	/*
	 * Get the general purpose registers
	 */
	r[SVR4_SPARC_PSR] = TSTATECCR_TO_PSR(tf->tf_tstate);
	r[SVR4_SPARC_PC] = tf->tf_pc;
	r[SVR4_SPARC_nPC] = tf->tf_npc;
	r[SVR4_SPARC_Y] = tf->tf_y;
	r[SVR4_SPARC_G1] = tf->tf_global[1];
	r[SVR4_SPARC_G2] = tf->tf_global[2];
	r[SVR4_SPARC_G3] = tf->tf_global[3];
	r[SVR4_SPARC_G4] = tf->tf_global[4];
	r[SVR4_SPARC_G5] = tf->tf_global[5];
	r[SVR4_SPARC_G6] = tf->tf_global[6];
	r[SVR4_SPARC_G7] = tf->tf_global[7];
	r[SVR4_SPARC_O0] = tf->tf_out[0];
	r[SVR4_SPARC_O1] = tf->tf_out[1];
	r[SVR4_SPARC_O2] = tf->tf_out[2];
	r[SVR4_SPARC_O3] = tf->tf_out[3];
	r[SVR4_SPARC_O4] = tf->tf_out[4];
	r[SVR4_SPARC_O5] = tf->tf_out[5];
	r[SVR4_SPARC_O6] = tf->tf_out[6];
	r[SVR4_SPARC_O7] = tf->tf_out[7];

	*flags |= SVR4_UC_CPU;

#ifdef FPU_CONTEXT
	/*
	 * Get the floating point registers
	 */
	/* Note: copies only pre-v9 floating point registers. */
	memcpy(f->fpu_regs, fps->fs_regs, sizeof(f->fpu_regs));
	f->fp_nqsize = sizeof(struct fp_qentry);
	f->fp_nqel = fps->fs_qsize;
	f->fp_fsr = fps->fs_fsr;
	if (f->fp_q != NULL) {
		size_t sz = f->fp_nqel * f->fp_nqsize;
		if (sz > sizeof(fps->fs_queue)) {
#ifdef DIAGNOSTIC
			printf("getcontext: fp_queue too large\n");
#endif
			return;
		}
		if (copyout(fps->fs_queue, (void *)(u_long)f->fp_q, sz) != 0) {
#ifdef DIAGNOSTIC
			printf("getcontext: copy of fp_queue failed %d\n",
			    error);
#endif
			return;
		}
	}
	f->fp_busy = 0;	/* XXX: How do we determine that? */
	*flags |= SVR4_UC_FPU;
#endif


#ifdef DEBUG_SVR4
	svr4_32_printmcontext("getmcontext", mc);
#endif
	return (void *)(u_long)tf->tf_out[6];
}
void
sunos32_sendsig(const ksiginfo_t *ksi, const sigset_t *mask)
{
	int sig = ksi->ksi_signo;
	struct lwp *l = curlwp;	/* XXX */
	struct proc *p = l->l_proc;
	struct sunos32_sigframe *fp;
	struct trapframe64 *tf;
	struct rwindow32 *oldsp, *newsp;
	struct sunos32_sigframe sf;
	struct sunos32_sigcontext *scp;
	uint32_t addr, oldsp32;
	int onstack, error; 
	sig_t catcher = SIGACTION(p, sig).sa_handler;

	tf = l->l_md.md_tf;
	/* Need to attempt to zero extend this 32-bit pointer */
	oldsp = (struct rwindow32 *)(u_long)(u_int)tf->tf_out[6];
	oldsp32 = (uint32_t)(u_long)oldsp;

	/*
	 * Compute new user stack addresses, subtract off
	 * one signal frame, and align.
	 */
	onstack =
	    (l->l_sigstk.ss_flags & (SS_DISABLE | SS_ONSTACK)) == 0 &&
	    (SIGACTION(p, sig).sa_flags & SA_ONSTACK) != 0;

	if (onstack)
		fp = (struct sunos32_sigframe *)
		     ((char *)l->l_sigstk.ss_sp + l->l_sigstk.ss_size);
	else
		fp = (struct sunos32_sigframe *)oldsp;

	fp = (struct sunos32_sigframe *)((u_long)(fp - 1) & ~7);

#ifdef DEBUG
	sigpid = p->p_pid;
	if ((sigdebug & SDB_KSTACK) && p->p_pid == sigpid) {
		mutex_exit(p->p_lock);
		printf("sunos32_sendsig: %s[%d] sig %d newusp %p scp %p oldsp %p\n",
		    p->p_comm, p->p_pid, sig, fp, &fp->sf_sc, oldsp);
#ifdef DDB
		if (sigdebug & SDB_DDB) Debugger();
#endif
		mutex_enter(p->p_lock);
	}
#endif
	/*
	 * Now set up the signal frame.  We build it in kernel space
	 * and then copy it out.  We probably ought to just build it
	 * directly in user space....
	 */
	sf.sf_signo = sig;
	sf.sf_code = (uint32_t)ksi->ksi_trap;
	scp = &fp->sf_sc;
	if ((u_long)scp >= 0x100000000)
		printf("sunos32_sendsig: sf_scp overflow %p > 0x100000000\n", scp);
	sf.sf_scp = (uint32_t)(u_long)scp;
	sf.sf_addr = 0;			/* XXX */

	/*
	 * Build the signal context to be used by sigreturn.
	 */
	sf.sf_sc.sc_onstack = l->l_sigstk.ss_flags & SS_ONSTACK;
	native_sigset_to_sigset13(mask, &sf.sf_sc.sc_mask);
	sf.sf_sc.sc_sp = (u_int)(u_long)oldsp;
	sf.sf_sc.sc_pc = tf->tf_pc;
	sf.sf_sc.sc_npc = tf->tf_npc;
	sf.sf_sc.sc_psr = TSTATECCR_TO_PSR(tf->tf_tstate); /* XXX */
	sf.sf_sc.sc_g1 = tf->tf_global[1];
	sf.sf_sc.sc_o0 = tf->tf_out[0];

	/*
	 * Put the stack in a consistent state before we whack away
	 * at it.  Note that write_user_windows may just dump the
	 * registers into the pcb; we need them in the process's memory.
	 * We also need to make sure that when we start the signal handler,
	 * its %i6 (%fp), which is loaded from the newly allocated stack area,
	 * joins seamlessly with the frame it was in when the signal occurred,
	 * so that the debugger and _longjmp code can back up through it.
	 */
	sendsig_reset(l, sig);
	mutex_exit(p->p_lock);
	newsp = (struct rwindow32 *)((long)fp - sizeof(struct rwindow32));
	write_user_windows();
#ifdef DEBUG
	if ((sigdebug & SDB_KSTACK))
	    printf("sunos32_sendsig: saving sf to %p, setting stack pointer %p to %p\n",
		   fp, &(((struct rwindow32 *)newsp)->rw_in[6]), oldsp);
#endif
	error = (rwindow_save(l) || copyout((void *)&sf, (void *)fp, sizeof sf) || 
	    copyout((void *)&oldsp32, &(((struct rwindow32 *)newsp)->rw_in[6]), sizeof oldsp32));
	mutex_enter(p->p_lock);
	if (error) {
		/*
		 * Process has trashed its stack; give it an illegal
		 * instruction to halt it in its tracks.
		 */
#ifdef DEBUG
		mutex_exit(p->p_lock);
		if ((sigdebug & SDB_KSTACK) && p->p_pid == sigpid)
			printf("sunos32_sendsig: window save or copyout error\n");
		printf("sunos32_sendsig: stack was trashed trying to send sig %d, sending SIGILL\n", sig);
#ifdef DDB
		if (sigdebug & SDB_DDB) Debugger();
#endif
		mutex_enter(p->p_lock);
#endif
		sigexit(l, SIGILL);
		/* NOTREACHED */
	}

#ifdef DEBUG
	if ((sigdebug & SDB_FOLLOW)) {
		printf("sunos32_sendsig: %s[%d] sig %d scp %p\n",
		       p->p_comm, p->p_pid, sig, &fp->sf_sc);
	}
#endif
	/*
	 * Arrange to continue execution at the code copied out in exec().
	 * It needs the function to call in %g1, and a new stack pointer.
	 */
	addr = (uint32_t)(u_long)catcher;	/* user does his own trampolining */
	tf->tf_pc = addr;
	tf->tf_npc = addr + 4;
	tf->tf_out[6] = (uint64_t)(u_int)(u_long)newsp;
#ifdef DEBUG
	if ((sigdebug & SDB_KSTACK) && p->p_pid == sigpid) {
		mutex_exit(p->p_lock);
		printf("sunos32_sendsig: about to return to catcher %p thru %p\n", 
		       catcher, (void *)(u_long)addr);
#ifdef DDB
		if (sigdebug & SDB_DDB) Debugger();
#endif
		mutex_enter(p->p_lock);
	}
#endif
}