freebsd-skq/sys/alpha/osf1/osf1_signal.c

823 lines
20 KiB
C
Raw Normal View History

/* $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$
*/
#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));
}