/*	$NetBSD: osf1_signal.c,v 1.4 1998/05/20 16:35:01 chs Exp $
 */

/*
 * Copyright (c) 1998-1999 Andrew Gallatin
 * 
 * Taken from NetBSD's sys/compat/osf1/osf1_signal.c, which at the
 * time *had no copyright*!
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer
 *    in this position and unchanged.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 * 3. The name of the author may not be used to endorse or promote products
 *    derived from this software withough specific prior written permission
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 * $FreeBSD: src/sys/alpha/osf1/osf1_signal.c,v 1.1 1999/12/14 22:35:33 gallatin Exp $
 */

#include <sys/param.h>
#include <sys/systm.h>
#include <sys/sysproto.h>
#include <sys/signalvar.h>
#include <sys/kernel.h>
#include <sys/proc.h>
#include <sys/lock.h>
#include <sys/malloc.h>
#include <sys/reboot.h>
#include <sys/buf.h>
#include <sys/mbuf.h>
#include <sys/vmmeter.h>
#include <sys/msgbuf.h>
#include <sys/exec.h>
#include <sys/sysctl.h>
#include <sys/uio.h>
#include <net/netisr.h>
#include <vm/vm.h>
#include <vm/vm_kern.h>
#include <vm/vm_page.h>
#include <vm/vm_map.h>
#include <vm/vm_extern.h>
#include <vm/vm_object.h>
#include <vm/vm_pager.h>
#include <sys/user.h>
#include <sys/ptrace.h>
#include <machine/clock.h>
#include <machine/md_var.h>
#include <machine/reg.h>
#include <machine/pal.h>
#include <machine/cpuconf.h>
#include <machine/bootinfo.h>
#include <machine/rpb.h>
#include <machine/prom.h>
#include <machine/chipset.h>
#include <machine/vmparam.h>
#include <machine/elf.h>
#include <ddb/ddb.h>
#include <alpha/alpha/db_instruction.h>
#include <sys/vnode.h>
#include <miscfs/procfs/procfs.h>

#include <alpha/osf1/osf1_signal.h>
#include <alpha/osf1/osf1_proto.h>
#include <alpha/osf1/osf1_syscall.h>
#include <alpha/osf1/osf1_util.h>
#include <alpha/osf1/osf1.h>
#include <sys/sysproto.h>

#define	DPRINTF uprintf
int osf1_sigdbg = 0;

static void bsd_to_osf1_sigaction __P((const struct sigaction *bsa,
					struct osf1_sigaction *osa));
static void osf1_to_bsd_sigaction __P((const struct osf1_sigaction *osa,
					struct sigaction *bsa));

#define	sigemptyset(s)		SIGEMPTYSET(*(s))
#define	sigismember(s, n)	SIGISMEMBER(*(s), n)
#define	sigaddset(s, n)		SIGADDSET(*(s), n)

#define	osf1_sigmask(n)		(1 << ((n) - 1))
#define	osf1_sigemptyset(s)	memset((s), 0, sizeof(*(s)))
#define	osf1_sigfillset(s)	memset((s), 0xffffffff, sizeof(*(s)))
#define	osf1_sigismember(s, n)	(*(s) & sigmask(n))
#define	osf1_sigaddset(s, n)	(*(s) |= sigmask(n))

int bsd_to_osf1_sig[OSF1_SIGTBLSZ] = {
	OSF1_SIGHUP,	/* 1 */
	OSF1_SIGINT,	/* 2 */
	OSF1_SIGQUIT,	/* 3 */
	OSF1_SIGILL,	/* 4 */
	OSF1_SIGTRAP,	/* 5 */
	OSF1_SIGABRT,	/* 6 */
	OSF1_SIGEMT,	/* 7 */
	OSF1_SIGFPE,	/* 8 */
	OSF1_SIGKILL,	/* 9 */
	OSF1_SIGBUS,	/* 10 */
	OSF1_SIGSEGV,	/* 11 */
	OSF1_SIGSYS,	/* 12 */
	OSF1_SIGPIPE,	/* 13 */
	OSF1_SIGALRM,	/* 14 */
	OSF1_SIGTERM,	/* 15 */
	OSF1_SIGURG,	/* 16 */
	OSF1_SIGSTOP,	/* 17 */
	OSF1_SIGTSTP,	/* 18 */
	OSF1_SIGCONT,	/* 19 */
	OSF1_SIGCHLD,	/* 20 */
	OSF1_SIGTTIN,	/* 21 */
	OSF1_SIGTTOU,	/* 22 */
	OSF1_SIGIO,	/* 23 */
	OSF1_SIGXCPU,	/* 24 */
	OSF1_SIGXFSZ,	/* 25 */
	OSF1_SIGVTALRM,	/* 26 */
	OSF1_SIGPROF,	/* 27 */
	OSF1_SIGWINCH,	/* 28 */
	OSF1_SIGINFO,	/* 29 */
	OSF1_SIGUSR1,	/* 30 */
	OSF1_SIGUSR2,	/* 31 */
	0		/* 32 */
};

int osf1_to_bsd_sig[OSF1_SIGTBLSZ] = {
	SIGHUP,		/* 1 */
	SIGINT,		/* 2 */
	SIGQUIT,	/* 3 */
	SIGILL,		/* 4 */
	SIGTRAP,	/* 5 */
	SIGABRT,	/* 6 */
	SIGEMT,		/* 7 */
	SIGFPE,		/* 8 */
	SIGKILL,	/* 9 */
	SIGBUS,		/* 10 */
	SIGSEGV,	/* 11 */
	SIGSYS,		/* 12 */
	SIGPIPE,	/* 13 */
	SIGALRM,	/* 14 */
	SIGTERM,	/* 15 */
	SIGURG,		/* 16 */
	SIGSTOP,	/* 17 */
	SIGTSTP,	/* 18 */
	SIGCONT,	/* 19 */
	SIGCHLD,	/* 20 */
	SIGTTIN,	/* 21 */
	SIGTTOU,	/* 22 */
	SIGIO,		/* 23 */
	SIGXCPU,	/* 24 */
	SIGXFSZ,	/* 25 */
	SIGVTALRM,	/* 26 */
	SIGPROF,	/* 27 */
	SIGWINCH,	/* 28 */
	SIGINFO,	/* 29 */
	SIGUSR1,	/* 30 */
	SIGUSR2,	/* 31 */
	0		/* 32 */
};


void
osf1_to_bsd_sigset(oss, bss)
	const osf1_sigset_t *oss;
	sigset_t *bss;
{
	int i, newsig;

	SIGEMPTYSET(*bss);
	for (i = 1; i <= OSF1_SIGTBLSZ; i++) {
		if (osf1_sigismember(oss, i)) {
			newsig = osf1_to_bsd_sig[_SIG_IDX(i)];
			if (newsig)
				SIGADDSET(*bss, newsig);
		}
	}
}

void
bsd_to_osf1_sigset(bss, oss)
	const sigset_t *bss;
	osf1_sigset_t *oss;
{
	int i, newsig;

	osf1_sigemptyset(oss);
	for (i = 1; i <= OSF1_SIGTBLSZ; i++) {
		if (SIGISMEMBER(*bss, i)) {
			newsig = bsd_to_osf1_sig[_SIG_IDX(i)];
			if (newsig)
				osf1_sigaddset(oss, newsig);
		}
	}

}

/*
 * XXX: Only a subset of the flags is currently implemented.
 */
void
osf1_to_bsd_sigaction(osa, bsa)
	const struct osf1_sigaction *osa;
	struct sigaction *bsa;
{

	bsa->sa_handler = osa->osa_handler;
	if (osf1_sigdbg)
		uprintf("%s(%d): handler @0x%lx \n", __FILE__, __LINE__,
			(unsigned long)osa->osa_handler);
	osf1_to_bsd_sigset(&osa->osa_mask, &bsa->sa_mask);
	bsa->sa_flags = 0;
	if ((osa->osa_flags & OSF1_SA_ONSTACK) != 0)
		bsa->sa_flags |= SA_ONSTACK;
	if ((osa->osa_flags & OSF1_SA_RESTART) != 0)
		bsa->sa_flags |= SA_RESTART;
	if ((osa->osa_flags & OSF1_SA_RESETHAND) != 0)
		bsa->sa_flags |= SA_RESETHAND;
	if ((osa->osa_flags & OSF1_SA_NOCLDSTOP) != 0)
		bsa->sa_flags |= SA_NOCLDSTOP;
	if ((osa->osa_flags & OSF1_SA_NODEFER) != 0)
		bsa->sa_flags |= SA_NODEFER;
}

void
bsd_to_osf1_sigaction(bsa, osa)
	const struct sigaction *bsa;
	struct osf1_sigaction *osa;
{

	osa->osa_handler = bsa->sa_handler;
	bsd_to_osf1_sigset(&bsa->sa_mask, &osa->osa_mask);
	osa->osa_flags = 0;
	if ((bsa->sa_flags & SA_ONSTACK) != 0)
		osa->osa_flags |= SA_ONSTACK;
	if ((bsa->sa_flags & SA_RESTART) != 0)
		osa->osa_flags |= SA_RESTART;
	if ((bsa->sa_flags & SA_NOCLDSTOP) != 0)
		osa->osa_flags |= SA_NOCLDSTOP;
	if ((bsa->sa_flags & SA_NODEFER) != 0)
		osa->osa_flags |= SA_NODEFER;
	if ((bsa->sa_flags & SA_RESETHAND) != 0)
		osa->osa_flags |= SA_RESETHAND;
}

void
osf1_to_bsd_sigaltstack(oss, bss)
	const struct osf1_sigaltstack *oss;
	struct sigaltstack *bss;
{

	bss->ss_sp = oss->ss_sp;
	bss->ss_size = oss->ss_size;
	bss->ss_flags = 0;

	if ((oss->ss_flags & OSF1_SS_DISABLE) != 0)
		bss->ss_flags |= SS_DISABLE;
	if ((oss->ss_flags & OSF1_SS_ONSTACK) != 0)
		bss->ss_flags |= SS_ONSTACK;
}

void
bsd_to_osf1_sigaltstack(bss, oss)
	const struct sigaltstack *bss;
	struct osf1_sigaltstack *oss;
{

	oss->ss_sp = bss->ss_sp;
	oss->ss_size = bss->ss_size;
	oss->ss_flags = 0;

	if ((bss->ss_flags & SS_DISABLE) != 0)
		oss->ss_flags |= OSF1_SS_DISABLE;
	if ((bss->ss_flags & SS_ONSTACK) != 0)
		oss->ss_flags |= OSF1_SS_ONSTACK;
}

int
osf1_sigaction(p, uap)
	struct proc *p;
	struct osf1_sigaction_args *uap;
{
	int error;
	caddr_t sg;
	struct osf1_sigaction *nosa, *oosa, tmposa;
	struct sigaction *nbsa, *obsa, tmpbsa;
	struct sigaction_args sa;

	sg = stackgap_init();
	nosa = SCARG(uap, nsa);
	oosa = SCARG(uap, osa);
	if (osf1_sigdbg && uap->sigtramp)
		uprintf("osf1_sigaction: trampoline handler at %p\n",
		    uap->sigtramp);
		p->p_md.osf_sigtramp = uap->sigtramp;
	if (oosa != NULL)
		obsa = stackgap_alloc(&sg, sizeof(struct sigaction));
	else
		obsa = NULL;
	if (nosa != NULL) {
		nbsa = stackgap_alloc(&sg, sizeof(struct sigaction));
		if ((error = copyin(nosa, &tmposa, sizeof(tmposa))) != 0)
			return error;
		osf1_to_bsd_sigaction(&tmposa, &tmpbsa);
		if ((error = copyout(&tmpbsa, nbsa, sizeof(tmpbsa))) != 0)
			return error;
	} else
		nbsa = NULL;

	SCARG(&sa, sig) = OSF1_OSF12BSD_SIG(SCARG(uap, signum));
	SCARG(&sa, act) = nbsa;
	SCARG(&sa, oact) = obsa;

	if ((error = sigaction(p, &sa)) != 0)
		return error;

	if (oosa != NULL) {
		if ((error = copyin(obsa, &tmpbsa, sizeof(tmpbsa))) != 0)
			return error;
		bsd_to_osf1_sigaction(&tmpbsa, &tmposa);
		if ((error = copyout(&tmposa, oosa, sizeof(tmposa))) != 0)
			return error;
	}

	return 0;
}

int
osf1_sigaltstack(p, uap)
	register struct proc *p;
	struct osf1_sigaltstack_args *uap;
{
	int error;
	caddr_t sg;
	struct osf1_sigaltstack *noss, *ooss, tmposs;
	struct sigaltstack *nbss, *obss, tmpbss;
	struct sigaltstack_args sa;

	sg = stackgap_init();
	noss = SCARG(uap, nss);
	ooss = SCARG(uap, oss);

	if (ooss != NULL)
		obss = stackgap_alloc(&sg, sizeof(struct sigaltstack));
	else
		obss = NULL;

	if (noss != NULL) {
		nbss = stackgap_alloc(&sg, sizeof(struct sigaltstack));
		if ((error = copyin(noss, &tmposs, sizeof(tmposs))) != 0)
			return error;
		osf1_to_bsd_sigaltstack(&tmposs, &tmpbss);
		if ((error = copyout(&tmpbss, nbss, sizeof(tmpbss))) != 0)
			return error;
	} else
		nbss = NULL;

	SCARG(&sa, ss) = nbss;
	SCARG(&sa, oss) = obss;

	if ((error = sigaltstack(p, &sa)) != 0)
		return error;

	if (obss != NULL) {
		if ((error = copyin(obss, &tmpbss, sizeof(tmpbss))) != 0)
			return error;
		bsd_to_osf1_sigaltstack(&tmpbss, &tmposs);
		if ((error = copyout(&tmposs, ooss, sizeof(tmposs))) != 0)
			return error;
	}

	return 0;
}

int
osf1_signal(p, uap)
	register struct proc *p;
	struct osf1_signal_args *uap;
{
	int error, signum;
	caddr_t sg;

	sg = stackgap_init();

	signum = OSF1_OSF12BSD_SIG(OSF1_SIGNO(SCARG(uap, signum)));
	if (signum <= 0 || signum > OSF1_NSIG) {
		if (OSF1_SIGCALL(SCARG(uap, signum)) == OSF1_SIGNAL_MASK ||
		    OSF1_SIGCALL(SCARG(uap, signum)) == OSF1_SIGDEFER_MASK)
			p->p_retval[0] = -1;
		return EINVAL;
	}

	switch (OSF1_SIGCALL(SCARG(uap, signum))) {
	case OSF1_SIGDEFER_MASK:
		/*
		 * sigset is identical to signal() except
		 * that SIG_HOLD is allowed as
		 * an action.
		 */
		if ((u_long)SCARG(uap, handler) ==  OSF1_SIG_HOLD) {
			sigset_t mask;
			sigset_t *bmask;
			struct sigprocmask_args sa;

			bmask = stackgap_alloc(&sg, sizeof(sigset_t));
			SIGEMPTYSET(mask);
			SIGADDSET(mask, signum);
			SCARG(&sa, how) = SIG_BLOCK;
			SCARG(&sa, set) = bmask;
			SCARG(&sa, oset) = NULL;
			if ((error = copyout(&mask, bmask, sizeof(mask))) != 0)
				return (error);
			return sigprocmask(p, &sa);
		}
		/* FALLTHROUGH */

	case OSF1_SIGNAL_MASK:
		{
			struct sigaction_args sa_args;
			struct sigaction *nbsa, *obsa, sa;

			nbsa = stackgap_alloc(&sg, sizeof(struct sigaction));
			obsa = stackgap_alloc(&sg, sizeof(struct sigaction));
			SCARG(&sa_args, sig) = signum;
			SCARG(&sa_args, act) = nbsa;
			SCARG(&sa_args, oact) = obsa;

			sa.sa_handler = SCARG(uap, handler);
			SIGEMPTYSET(sa.sa_mask);
			sa.sa_flags = 0;
#if 0
			if (signum != SIGALRM)
				sa.sa_flags = SA_RESTART;
#endif
			if ((error = copyout(&sa, nbsa, sizeof(sa))) != 0)
				return error;
			if ((error = sigaction(p, &sa_args)) != 0) {
				DPRINTF("signal: sigaction failed: %d\n",
					 error);
				p->p_retval[0] = -1;
				return error;
			}
			if ((error = copyin(obsa, &sa, sizeof(sa))) != 0)
				return error;
			p->p_retval[0] = (long)sa.sa_handler;
			return 0;
		}

	case OSF1_SIGHOLD_MASK:
		{
			struct sigprocmask_args sa;
			sigset_t set;
			sigset_t *bset;

			bset = stackgap_alloc(&sg, sizeof(sigset_t));
			SIGEMPTYSET(set);
			SIGADDSET(set, signum);
			SCARG(&sa, how) = SIG_BLOCK;
			SCARG(&sa, set) = bset;
			SCARG(&sa, oset) = NULL;
			if ((error = copyout(&set, bset, sizeof(set))) != 0)
				return (error);
			return sigprocmask(p, &sa);
		}

	case OSF1_SIGRELSE_MASK:
		{
			struct sigprocmask_args sa;
			sigset_t set;
			sigset_t *bset;

			bset = stackgap_alloc(&sg, sizeof(sigset_t));
			SIGEMPTYSET(set);
			SIGADDSET(set, signum);
			SCARG(&sa, how) = SIG_UNBLOCK;
			SCARG(&sa, set) = bset;
			SCARG(&sa, oset) = NULL;
			if ((error = copyout(&set, bset, sizeof(set))) != 0)
				return (error);
			return sigprocmask(p, &sa);

		}

	case OSF1_SIGIGNORE_MASK:
		{
			struct sigaction_args sa_args;
			struct sigaction *bsa, sa;

			bsa = stackgap_alloc(&sg, sizeof(struct sigaction));
			SCARG(&sa_args, sig) = signum;
			SCARG(&sa_args, act) = bsa;
			SCARG(&sa_args, oact) = NULL;

			sa.sa_handler = SIG_IGN;
			SIGEMPTYSET(sa.sa_mask);
			sa.sa_flags = 0;
			if ((error = copyout(&sa, bsa, sizeof(sa))) != 0)
				return error;
			if ((error = sigaction(p, &sa_args)) != 0) {
				DPRINTF(("sigignore: sigaction failed\n"));
				return error;
			}
			return 0;
		}

	case OSF1_SIGPAUSE_MASK:
		{
			struct sigsuspend_args sa;
			sigset_t set;
			sigset_t *bmask;

			bmask = stackgap_alloc(&sg, sizeof(sigset_t));
			set = p->p_sigmask;
			SIGDELSET(set, signum);
			SCARG(&sa, sigmask) = bmask;
			if ((error = copyout(&set, bmask, sizeof(set))) != 0)
				return (error);
			return sigsuspend(p, &sa);
		}

	default:
		return ENOSYS;
	}
}

int
osf1_sigprocmask(p, uap)
	register struct proc *p;
	struct osf1_sigprocmask_args /* {
		syscallarg(int) how;
		syscallarg(osf1_sigset_t *) set;
	} */ *uap;
{
	int error;
	osf1_sigset_t oss;
	sigset_t bss;

	error = 0;
		/* Fix the return value first if needed */
	bsd_to_osf1_sigset(&p->p_sigmask, &oss);
	p->p_retval[0] = oss;

	osf1_to_bsd_sigset(&uap->mask, &bss);

	(void) splhigh();

	switch (SCARG(uap, how)) {
	case OSF1_SIG_BLOCK:
		SIGSETOR(p->p_sigmask, bss);
		SIG_CANTMASK(p->p_sigmask);
		break;

	case OSF1_SIG_UNBLOCK:
		SIGSETNAND(p->p_sigmask, bss);
		break;

	case OSF1_SIG_SETMASK:
		p->p_sigmask = bss;
		SIG_CANTMASK(p->p_sigmask);
		break;

	default:
		error = EINVAL;
		break;
	}

	(void) spl0();

	return error;
}

int
osf1_sigpending(p, uap)
	register struct proc *p;
	struct osf1_sigpending_args /* {
		syscallarg(osf1_sigset_t *) mask;
	} */ *uap;
{
	osf1_sigset_t oss;
	sigset_t bss;

	bss = p->p_siglist;
	SIGSETAND(bss, p->p_sigmask);
	bsd_to_osf1_sigset(&bss, &oss);

	return copyout(&oss, SCARG(uap, mask), sizeof(oss));
}

int
osf1_sigsuspend(p, uap)
	register struct proc *p;
	struct osf1_sigsuspend_args /* {
		syscallarg(osf1_sigset_t *) ss;
	} */ *uap;
{
	int error;
	caddr_t sg;
	osf1_sigset_t oss;
	sigset_t bss;
	sigset_t *bmask;
	struct sigsuspend_args sa;

	sg = stackgap_init();

	bmask = stackgap_alloc(&sg, sizeof(sigset_t));
	oss = SCARG(uap, ss);
	osf1_to_bsd_sigset(&oss, &bss);
	SCARG(&sa, sigmask) = bmask;
	if ((error = copyout(&bss, bmask, sizeof(bss))) != 0){
		return (error);
	}
	return sigsuspend(p, &sa);
}

int
osf1_kill(p, uap)
	register struct proc *p;
	struct osf1_kill_args /* {
		syscallarg(int) pid;
		syscallarg(int) signum;
	} */ *uap;
{
	struct kill_args ka;

	SCARG(&ka, pid) = SCARG(uap, pid);
	SCARG(&ka, signum) = OSF1_OSF12BSD_SIG(SCARG(uap, signum));
	return kill(p, &ka);
}


/*
 * Send an interrupt to process.
 *
 * Stack is set up to allow sigcode stored at top to call routine,
 * followed by kcall to sigreturn routine below.  After sigreturn resets
 * the signal mask, the stack, and the frame pointer, it returns to the
 * user specified pc, psl.
 */

void
osf1_sendsig(sig_t catcher, int sig, sigset_t *mask, u_long code)
{
	int fsize, oonstack, rndfsize;
	struct proc *p;
	osiginfo_t *sip, ksi;
	struct trapframe *frame;
	struct sigacts *psp;

	p = curproc;
	psp = p->p_sigacts;

	frame = p->p_md.md_tf;
	oonstack = p->p_sigstk.ss_flags & SS_ONSTACK;
	fsize = sizeof ksi;
	rndfsize = ((fsize + 15) / 16) * 16;

	/*
	 * Allocate and validate space for the signal handler context.
	 * Note that if the stack is in P0 space, the call to grow() is a nop,
	 * and the useracc() check will fail if the process has not already
	 * allocated the space with a `brk'.
	 */
	if ((p->p_flag & P_ALTSTACK) && !oonstack &&
	    SIGISMEMBER(psp->ps_sigonstack, sig)) {
		sip = (osiginfo_t *)((caddr_t)p->p_sigstk.ss_sp +
		    p->p_sigstk.ss_size - rndfsize);
		p->p_sigstk.ss_flags |= SS_ONSTACK;
	} else
		sip = (osiginfo_t *)(alpha_pal_rdusp() - rndfsize);

	(void)grow_stack(p, (u_long)sip);
	if (useracc((caddr_t)sip, fsize, VM_PROT_WRITE) == 0) {
		/*
		 * Process has trashed its stack; give it an illegal
		 * instruction to halt it in its tracks.
		 */
		SIGACTION(p, SIGILL) = SIG_DFL;
		SIGDELSET(p->p_sigignore, SIGILL);
		SIGDELSET(p->p_sigcatch, SIGILL);
		SIGDELSET(p->p_sigmask, SIGILL);
		psignal(p, SIGILL);
		return;
	}

	/*
	 * Build the signal context to be used by sigreturn.
	 */
	ksi.si_sc.sc_onstack = oonstack;
	SIG2OSIG(*mask, ksi.si_sc.sc_mask);
	ksi.si_sc.sc_pc = frame->tf_regs[FRAME_PC];
	ksi.si_sc.sc_ps = frame->tf_regs[FRAME_PS];

	/* copy the registers. */
	fill_regs(p, (struct reg *)ksi.si_sc.sc_regs);
	ksi.si_sc.sc_regs[R_ZERO] = 0xACEDBADE;		/* magic number */
	ksi.si_sc.sc_regs[R_SP] = alpha_pal_rdusp();

	/* save the floating-point state, if necessary, then copy it. */
	alpha_fpstate_save(p, 1);		/* XXX maybe write=0 */
	ksi.si_sc.sc_ownedfp = p->p_md.md_flags & MDP_FPUSED;
	bcopy(&p->p_addr->u_pcb.pcb_fp, (struct fpreg *)ksi.si_sc.sc_fpregs,
	    sizeof(struct fpreg));
	ksi.si_sc.sc_fp_control = p->p_addr->u_pcb.pcb_fp_control;
	bzero(ksi.si_sc.sc_reserved, sizeof ksi.si_sc.sc_reserved); /* XXX */
	ksi.si_sc.sc_xxx1[0] = 0;				/* XXX */
	ksi.si_sc.sc_xxx1[1] = 0;				/* XXX */
	ksi.si_sc.sc_traparg_a0 = frame->tf_regs[FRAME_TRAPARG_A0];
	ksi.si_sc.sc_traparg_a1 = frame->tf_regs[FRAME_TRAPARG_A1];
	ksi.si_sc.sc_traparg_a2 = frame->tf_regs[FRAME_TRAPARG_A2];
	ksi.si_sc.sc_xxx2[0] = 0;				/* XXX */
	ksi.si_sc.sc_xxx2[1] = 0;				/* XXX */
	ksi.si_sc.sc_xxx2[2] = 0;				/* XXX */
	/* Fill in POSIX parts */
	ksi.si_signo = sig;
	ksi.si_code = code;
	ksi.si_value.sigval_ptr = NULL;				/* XXX */

	/*
	 * copy the frame out to userland.
	 */
	(void) copyout((caddr_t)&ksi, (caddr_t)sip, fsize);

	/*
	 * Set up the registers to return to sigcode.
	 */
	if (osf1_sigdbg)
		uprintf("attempting to call osf1 sigtramp\n");
	frame->tf_regs[FRAME_PC] = (u_int64_t)p->p_md.osf_sigtramp;
	frame->tf_regs[FRAME_A0] = sig;
	frame->tf_regs[FRAME_A1] = code;
	frame->tf_regs[FRAME_A2] = (u_int64_t)sip;
	frame->tf_regs[FRAME_A3]  = (u_int64_t)catcher;		/* a3 is pv */
	alpha_pal_wrusp((unsigned long)sip);
}


/*
 * System call to cleanup state after a signal has been taken.  Reset signal
 * mask and stack state from context left by sendsig (above).  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 state to gain
 * improper privileges.
 */
int
osf1_sigreturn(struct proc *p,
	struct osf1_sigreturn_args /* {
		struct osigcontext *sigcntxp;
	} */ *uap)
{
	struct osigcontext ksc, *scp;

	scp = uap->sigcntxp;
	if (useracc((caddr_t)scp, sizeof (*scp), VM_PROT_READ) == 0 ) {
		uprintf("uac fails\n");
		uprintf("scp: %p\n", scp);
	}
	/*
	 * Test and fetch the context structure.
	 * We grab it all at once for speed.
	 */
	if (useracc((caddr_t)scp, sizeof (*scp), VM_PROT_READ) == 0 ||
	    copyin((caddr_t)scp, (caddr_t)&ksc, sizeof ksc))
		return (EFAULT);

	/*
	 * Restore the user-supplied information.
	 */
	if (ksc.sc_onstack)
		p->p_sigstk.ss_flags |= SS_ONSTACK;
	else
		p->p_sigstk.ss_flags &= ~SS_ONSTACK;

	/*
	 * longjmp is still implemented by calling osigreturn. The new
	 * sigmask is stored in sc_reserved, sc_mask is only used for
	 * backward compatibility.
	 */
	SIGSETOLD(p->p_sigmask, ksc.sc_mask);
	SIG_CANTMASK(p->p_sigmask);

	set_regs(p, (struct reg *)ksc.sc_regs);
	p->p_md.md_tf->tf_regs[FRAME_PC] = ksc.sc_pc;
	p->p_md.md_tf->tf_regs[FRAME_PS] =
	    (ksc.sc_ps | ALPHA_PSL_USERSET) & ~ALPHA_PSL_USERCLR;

	alpha_pal_wrusp(ksc.sc_regs[R_SP]);

	/* XXX ksc.sc_ownedfp ? */
	alpha_fpstate_drop(p);
	bcopy((struct fpreg *)ksc.sc_fpregs, &p->p_addr->u_pcb.pcb_fp,
	    sizeof(struct fpreg));
	p->p_addr->u_pcb.pcb_fp_control = ksc.sc_fp_control;
	return (EJUSTRETURN);
}

extern int
osigstack(struct proc *p, struct osf1_osigstack_args *uap);

int
osf1_osigstack(p, uap)
	register struct proc *p;
	struct osf1_osigstack_args /* {
					struct sigstack *nss;
					struct sigstack *oss;
	} */ *uap;
{

/*	uprintf("osf1_osigstack: oss = %p, nss = %p",uap->oss, uap->nss);
	uprintf(" stack ptr = %p\n",p->p_sigacts->ps_sigstk.ss_sp);*/
	return(osigstack(p, uap));
}
