Add SA_SIGINFO support for VAX.

This commit is contained in:
matt 2003-09-29 21:04:53 +00:00
parent 5c09d20130
commit 050d126a03
9 changed files with 522 additions and 317 deletions

View File

@ -1,4 +1,4 @@
# $NetBSD: files.vax,v 1.99 2003/07/27 01:19:34 thorpej Exp $
# $NetBSD: files.vax,v 1.100 2003/09/29 21:04:53 matt Exp $
#
# new style config file for vax architecture
#
@ -332,6 +332,7 @@ file arch/vax/vax/bus_dma.c
file arch/vax/vax/bus_mem.c
file arch/vax/vax/procfs_machdep.c procfs
file arch/vax/vax/sgmap.c
file arch/vax/vax/sig_machdep.c
file arch/vax/vax/vm_machdep.c
file arch/vax/vax/findcpu.c
file arch/vax/vax/autoconf.c

View File

@ -1,4 +1,4 @@
/* $NetBSD: ibcs2_machdep.h,v 1.6 2003/09/26 12:02:57 simonb Exp $ */
/* $NetBSD: ibcs2_machdep.h,v 1.7 2003/09/29 21:04:53 matt Exp $ */
/*-
* Copyright (c) 1997 The NetBSD Foundation, Inc.
@ -47,9 +47,9 @@
struct exec_package;
struct exec_vmcmd;
void ibcs2_setregs __P((struct lwp *, struct exec_package *, u_long));
void ibcs2_sendsig __P((int, const sigset_t *, u_long));
int ibcs2_sys_sysmachine __P((struct proc *, void *, register_t *));
void ibcs2_setregs (struct lwp *, struct exec_package *, u_long);
void ibcs2_sendsig (const ksiginfo_t *, const sigset_t *);
int ibcs2_sys_sysmachine (struct proc *, void *, register_t *);
#endif /* _KERNEL */

View File

@ -1,4 +1,4 @@
/* $NetBSD: signal.h,v 1.10 2003/08/07 16:30:12 agc Exp $ */
/* $NetBSD: signal.h,v 1.11 2003/09/29 21:04:53 matt Exp $ */
/*
* Copyright (c) 1982, 1986, 1989, 1991 Regents of the University of California.
@ -40,6 +40,8 @@
typedef int sig_atomic_t;
#define __HAVE_SIGINFO
#if defined(_NETBSD_SOURCE)
/*
* Information pushed on stack when a signal is delivered.
@ -71,29 +73,16 @@ struct sigcontext {
sigset_t sc_mask; /* signal mask to restore (new style) */
};
/*
* The following macros are used to convert from a ucontext to sigcontext,
* and vice-versa. This is for building a sigcontext to deliver to old-style
* signal handlers, and converting back (in the event the handler modifies
* the context).
*/
#define _MCONTEXT_TO_SIGCONTEXT(uc, sc) \
do { \
(sc)->sc_sp = (uc)->uc_mcontext.__gregs[_REG_SP]; \
(sc)->sc_fp = (uc)->uc_mcontext.__gregs[_REG_FP]; \
(sc)->sc_ap = (uc)->uc_mcontext.__gregs[_REG_AP]; \
(sc)->sc_pc = (uc)->uc_mcontext.__gregs[_REG_PC]; \
(sc)->sc_ps = (uc)->uc_mcontext.__gregs[_REG_PSL]; \
} while (/*CONSTCOND*/0)
#ifdef _KERNEL
void sendsig_context(int, const sigset_t *, u_long);
#define _SIGCONTEXT_TO_MCONTEXT(sc, uc) \
do { \
(uc)->uc_mcontext.__gregs[_REG_SP] = (sc)->sc_sp; \
(uc)->uc_mcontext.__gregs[_REG_FP] = (sc)->sc_fp; \
(uc)->uc_mcontext.__gregs[_REG_AP] = (sc)->sc_ap; \
(uc)->uc_mcontext.__gregs[_REG_PC] = (sc)->sc_pc; \
(uc)->uc_mcontext.__gregs[_REG_PSL] = (sc)->sc_ps; \
} while (/*CONSTCOND*/0)
#ifdef COMPAT_16
#define SIGTRAMP_VALID(vers) ((vers) <= 3 && (vers) != 1)
#else
#define SIGTRAMP_VALID(vers) ((vers) == 3)
#endif
#endif /* _KERNEL */
#endif /* _NETBSD_SOURCE */
#endif /* !_VAX_SIGNAL_H_ */

View File

@ -1,4 +1,4 @@
# $NetBSD: genassym.cf,v 1.26 2003/01/19 22:29:23 ragge Exp $
# $NetBSD: genassym.cf,v 1.27 2003/09/29 21:04:53 matt Exp $
#
# Copyright (c) 1997 Ludd, University of Lule}, Sweden.
# All rights reserved.
@ -40,11 +40,12 @@ include <sys/device.h>
include <uvm/uvm.h>
include <machine/cpu.h>
include <machine/mtpr.h>
include <machine/pcb.h>
include <machine/sid.h>
include <machine/signal.h>
include <machine/trap.h>
include <machine/cpu.h>
include <machine/uvax.h>
define L_PRIORITY offsetof(struct lwp, l_priority)
@ -125,7 +126,7 @@ define EFAULT EFAULT
define EV_COUNT offsetof(struct evcnt, ev_count)
define SYS___sigreturn14 SYS___sigreturn14
define SYS_compat_16___sigreturn14 SYS_compat_16___sigreturn14
define SYS_exit SYS_exit
define VAX_TYP_UV2 VAX_TYP_UV2

View File

@ -1,4 +1,4 @@
/* $NetBSD: ibcs2_machdep.c,v 1.6 2003/09/26 12:02:57 simonb Exp $ */
/* $NetBSD: ibcs2_machdep.c,v 1.7 2003/09/29 21:04:53 matt Exp $ */
/*-
* Copyright (c) 1997 The NetBSD Foundation, Inc.
@ -37,7 +37,7 @@
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: ibcs2_machdep.c,v 1.6 2003/09/26 12:02:57 simonb Exp $");
__KERNEL_RCSID(0, "$NetBSD: ibcs2_machdep.c,v 1.7 2003/09/29 21:04:53 matt Exp $");
#include <sys/param.h>
#include <sys/systm.h>
@ -57,10 +57,7 @@ __KERNEL_RCSID(0, "$NetBSD: ibcs2_machdep.c,v 1.6 2003/09/26 12:02:57 simonb Exp
#include <compat/ibcs2/ibcs2_signal.h>
void
ibcs2_setregs(l, epp, stack)
struct lwp *l;
struct exec_package *epp;
u_long stack;
ibcs2_setregs(struct lwp *l, struct exec_package *epp, u_long stack)
{
/* Don't need to anything special */
setregs(l, epp, stack);
@ -77,19 +74,19 @@ ibcs2_setregs(l, epp, stack)
* specified pc, psl.
*/
void
ibcs2_sendsig(sig, mask, code)
int sig;
const sigset_t *mask;
u_long code;
ibcs2_sendsig(const ksiginfo_t *ksi, const sigset_t *mask)
{
sendsig(native_to_ibcs2_signo[sig], mask, code);
ksiginfo_t nksi;
if (ksi->ksi_signo != native_to_ibcs2_signo[ksi->ksi_signo]) {
nksi = *ksi;
nksi.ksi_signo = native_to_ibcs2_signo[ksi->ksi_signo];
ksi = &nksi;
}
sendsig(ksi, mask);
}
int
ibcs2_sys_sysmachine(p, v, retval)
struct proc *p;
void *v;
register_t *retval;
ibcs2_sys_sysmachine(struct proc *l, void *v, register_t *retval)
{
return EINVAL;
}

View File

@ -1,4 +1,4 @@
/* $NetBSD: machdep.c,v 1.139 2003/09/26 12:02:57 simonb Exp $ */
/* $NetBSD: machdep.c,v 1.140 2003/09/29 21:04:53 matt Exp $ */
/*
* Copyright (c) 1982, 1986, 1990 The Regents of the University of California.
@ -83,7 +83,7 @@
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: machdep.c,v 1.139 2003/09/26 12:02:57 simonb Exp $");
__KERNEL_RCSID(0, "$NetBSD: machdep.c,v 1.140 2003/09/29 21:04:53 matt Exp $");
#include "opt_ddb.h"
#include "opt_compat_netbsd.h"
@ -412,268 +412,6 @@ consinit()
#endif
}
#if defined(COMPAT_13) || defined(COMPAT_ULTRIX)
int
compat_13_sys_sigreturn(l, v, retval)
struct lwp *l;
void *v;
register_t *retval;
{
struct compat_13_sys_sigreturn_args /* {
syscallarg(struct sigcontext13 *) sigcntxp;
} */ *uap = v;
struct proc *p = l->l_proc;
struct trapframe *scf;
struct sigcontext13 *ucntx;
struct sigcontext13 ksc;
sigset_t mask;
scf = l->l_addr->u_pcb.framep;
ucntx = SCARG(uap, sigcntxp);
if (copyin((caddr_t)ucntx, (caddr_t)&ksc, sizeof(struct sigcontext)))
return EINVAL;
/* Compatibility mode? */
if ((ksc.sc_ps & (PSL_IPL | PSL_IS)) ||
((ksc.sc_ps & (PSL_U | PSL_PREVU)) != (PSL_U | PSL_PREVU)) ||
(ksc.sc_ps & PSL_CM)) {
return (EINVAL);
}
if (ksc.sc_onstack & SS_ONSTACK)
p->p_sigctx.ps_sigstk.ss_flags |= SS_ONSTACK;
else
p->p_sigctx.ps_sigstk.ss_flags &= ~SS_ONSTACK;
native_sigset13_to_sigset(&ksc.sc_mask, &mask);
(void) sigprocmask1(p, SIG_SETMASK, &mask, 0);
scf->fp = ksc.sc_fp;
scf->ap = ksc.sc_ap;
scf->pc = ksc.sc_pc;
scf->sp = ksc.sc_sp;
scf->psl = ksc.sc_ps;
return (EJUSTRETURN);
}
#endif
int
sys___sigreturn14(l, v, retval)
struct lwp *l;
void *v;
register_t *retval;
{
struct sys___sigreturn14_args /* {
syscallarg(struct sigcontext *) sigcntxp;
} */ *uap = v;
struct proc *p = l->l_proc;
struct trapframe *scf;
struct sigcontext *ucntx;
struct sigcontext ksc;
scf = l->l_addr->u_pcb.framep;
ucntx = SCARG(uap, sigcntxp);
if (copyin((caddr_t)ucntx, (caddr_t)&ksc, sizeof(struct sigcontext)))
return EINVAL;
/* Compatibility mode? */
if ((ksc.sc_ps & (PSL_IPL | PSL_IS)) ||
((ksc.sc_ps & (PSL_U | PSL_PREVU)) != (PSL_U | PSL_PREVU)) ||
(ksc.sc_ps & PSL_CM)) {
return (EINVAL);
}
if (ksc.sc_onstack & SS_ONSTACK)
p->p_sigctx.ps_sigstk.ss_flags |= SS_ONSTACK;
else
p->p_sigctx.ps_sigstk.ss_flags &= ~SS_ONSTACK;
/* Restore signal mask. */
(void) sigprocmask1(p, SIG_SETMASK, &ksc.sc_mask, 0);
scf->fp = ksc.sc_fp;
scf->ap = ksc.sc_ap;
scf->pc = ksc.sc_pc;
scf->sp = ksc.sc_sp;
scf->psl = ksc.sc_ps;
return (EJUSTRETURN);
}
#if defined(COMPAT_16) || defined(COMPAT_ULTRIX) || defined(COMPAT_IBCS2)
struct otrampframe {
unsigned sig; /* Signal number */
unsigned code; /* Info code */
unsigned scp; /* Pointer to struct sigcontext */
unsigned r0, r1, r2, r3, r4, r5; /* Registers saved when
* interrupt */
unsigned pc; /* Address of signal handler */
unsigned arg; /* Pointer to first (and only) sigreturn
* argument */
};
static void
oldsendsig(int sig, const sigset_t *mask, u_long code)
{
struct lwp *l = curlwp;
struct proc *p = l->l_proc;
struct sigacts *ps = p->p_sigacts;
struct trapframe *syscf;
struct sigcontext *sigctx, gsigctx;
struct otrampframe *trampf, gtrampf;
unsigned cursp;
int onstack;
sig_t catcher = SIGACTION(p, sig).sa_handler;
syscf = l->l_addr->u_pcb.framep;
onstack =
(p->p_sigctx.ps_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)
cursp = ((int)p->p_sigctx.ps_sigstk.ss_sp + p->p_sigctx.ps_sigstk.ss_size);
else
cursp = syscf->sp;
/* Set up positions for structs on stack */
sigctx = (struct sigcontext *) (cursp - sizeof(struct sigcontext));
trampf = (struct otrampframe *) ((unsigned)sigctx -
sizeof(struct otrampframe));
/* Place for pointer to arg list in sigreturn */
cursp = (unsigned)sigctx - 8;
gtrampf.arg = (int) sigctx;
gtrampf.pc = (unsigned) catcher;
/* r0..r5 are saved by the popr in the sigcode snippet */
gtrampf.scp = (int) sigctx;
gtrampf.code = code;
gtrampf.sig = sig;
gsigctx.sc_pc = syscf->pc;
gsigctx.sc_ps = syscf->psl;
gsigctx.sc_ap = syscf->ap;
gsigctx.sc_fp = syscf->fp;
gsigctx.sc_sp = syscf->sp;
gsigctx.sc_onstack = p->p_sigctx.ps_sigstk.ss_flags & SS_ONSTACK;
gsigctx.sc_mask = *mask;
#if defined(COMPAT_13) || defined(COMPAT_ULTRIX)
native_sigset_to_sigset13(mask, &gsigctx.__sc_mask13);
#endif
if (copyout(&gtrampf, trampf, sizeof(gtrampf)) ||
copyout(&gsigctx, sigctx, sizeof(gsigctx)))
sigexit(l, SIGILL);
/*
* Note the trampoline version numbers are coordinated with
* machine-dependent code in libc.
*/
switch (ps->sa_sigdesc[sig].sd_vers) {
case 0:
syscf->pc = (int)p->p_sigctx.ps_sigcode;
break;
case 1:
syscf->pc = (int)ps->sa_sigdesc[sig].sd_tramp;
break;
default:
/* ``cannot happen'' */
sigexit(l, SIGILL);
}
syscf->psl = PSL_U | PSL_PREVU;
syscf->ap = cursp;
syscf->sp = cursp;
if (onstack)
p->p_sigctx.ps_sigstk.ss_flags |= SS_ONSTACK;
}
#endif
struct trampoline {
unsigned int narg; /* Argument count (== 3) */
unsigned int sig; /* Signal number */
unsigned int code; /* Info code */
unsigned int scp; /* Pointer to struct sigcontext */
};
/*
* Brief description of how sendsig() works:
* A struct sigcontext is allocated on the user stack. The relevant
* registers are saved in it. Below it is a struct trampframe constructed, it
* is actually an argument list for callg. The user
* stack pointer is put below all structs.
*
* The registers will contain when the signal handler is called:
* pc, psl - Obvious
* sp - An address below all structs
* fp - The address of the signal handler
* ap - The address to the callg frame
*
* The trampoline code will save r0-r5 before doing anything else.
*/
void
sendsig(int sig, const sigset_t *mask, u_long code)
{
struct lwp *l = curlwp;
struct proc *p = curproc;
struct sigacts *ps = p->p_sigacts;
struct trampoline tramp;
struct sigcontext sigctx;
struct trapframe *tf = l->l_addr->u_pcb.framep;
sig_t catcher = SIGACTION(p, sig).sa_handler;
int onstack =
(p->p_sigctx.ps_sigstk.ss_flags & (SS_DISABLE | SS_ONSTACK)) == 0 &&
(SIGACTION(p, sig).sa_flags & SA_ONSTACK) != 0;
int cursp = onstack == 0 ? tf->sp :
((int)p->p_sigctx.ps_sigstk.ss_sp + p->p_sigctx.ps_sigstk.ss_size);
#if defined(COMPAT_16) || defined(COMPAT_ULTRIX) || defined(COMPAT_IBCS2)
if (ps->sa_sigdesc[sig].sd_vers < 2)
return oldsendsig(sig, mask, code);
#endif
/*
* The sigcontext struct will be passed back to sigreturn().
*/
sigctx.sc_pc = tf->pc;
sigctx.sc_ps = tf->psl;
sigctx.sc_ap = tf->ap;
sigctx.sc_fp = tf->fp;
sigctx.sc_sp = tf->sp;
sigctx.sc_onstack = p->p_sigctx.ps_sigstk.ss_flags & SS_ONSTACK;
sigctx.sc_mask = *mask;
/*
* Arguments given to the signal handler.
*/
tramp.narg = 3;
tramp.sig = sig;
tramp.code = code;
tramp.scp = cursp - sizeof(struct sigcontext);
if (copyout(&sigctx, (char *)tramp.scp, sizeof(struct sigcontext)) ||
copyout(&tramp, (char *)tramp.scp - sizeof(tramp), sizeof(tramp)))
sigexit(l, SIGILL);
switch (ps->sa_sigdesc[sig].sd_vers) {
case 2:
tf->pc = (int)ps->sa_sigdesc[sig].sd_tramp;
break;
default:
/* Don't know what trampoline version; kill it. */
sigexit(l, SIGILL);
}
tf->psl = PSL_U | PSL_PREVU;
tf->ap = tramp.scp - sizeof(tramp);
tf->fp = (int)catcher;
tf->sp = tf->ap;
if (onstack)
p->p_sigctx.ps_sigstk.ss_flags |= SS_ONSTACK;
}
int waittime = -1;
static volatile int showto; /* Must be volatile to survive MM on -> MM off */

View File

@ -0,0 +1,459 @@
/* $NetBSD: sig_machdep.c,v 1.1 2003/09/29 21:04:53 matt Exp $ */
/*
* Copyright (c) 1982, 1986, 1990 The Regents of the University of California.
* All rights reserved.
*
* Changed for the VAX port (and for readability) /IC
*
* This code is derived from software contributed to Berkeley by the Systems
* Programming Group of the University of Utah Computer Science Department.
*
* 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.
* 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. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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.
*
* from: Utah Hdr: machdep.c 1.63 91/04/24
*
* @(#)machdep.c 7.16 (Berkeley) 6/3/91
*/
/*
* Copyright (c) 2002, Hugh Graham.
* Copyright (c) 1994, 1998 Ludd, University of Lule}, Sweden.
* Copyright (c) 1993 Adam Glass
* Copyright (c) 1988 University of Utah.
*
* Changed for the VAX port (and for readability) /IC
*
* This code is derived from software contributed to Berkeley by the Systems
* Programming Group of the University of Utah Computer Science Department.
*
* 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.
* 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. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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.
*
* from: Utah Hdr: machdep.c 1.63 91/04/24
*
* @(#)machdep.c 7.16 (Berkeley) 6/3/91
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: sig_machdep.c,v 1.1 2003/09/29 21:04:53 matt Exp $");
#include "opt_ddb.h"
#include "opt_compat_netbsd.h"
#include "opt_compat_ultrix.h"
#include "opt_multiprocessor.h"
#include "opt_lockdebug.h"
#include "opt_compat_ibcs2.h"
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/extent.h>
#include <sys/proc.h>
#include <sys/user.h>
#include <sys/time.h>
#include <sys/signal.h>
#include <sys/kernel.h>
#include <sys/msgbuf.h>
#include <sys/buf.h>
#include <sys/mbuf.h>
#include <sys/reboot.h>
#include <sys/conf.h>
#include <sys/device.h>
#include <sys/exec.h>
#include <sys/mount.h>
#include <sys/sa.h>
#include <sys/syscallargs.h>
#include <sys/ptrace.h>
#include <sys/savar.h>
#include <sys/ksyms.h>
#include <dev/cons.h>
#include <uvm/uvm_extern.h>
#include <sys/sysctl.h>
#include <machine/sid.h>
#include <machine/pte.h>
#include <machine/mtpr.h>
#include <machine/cpu.h>
#include <machine/macros.h>
#include <machine/nexus.h>
#include <machine/trap.h>
#include <machine/reg.h>
#include <machine/db_machdep.h>
#include <machine/scb.h>
#include <vax/vax/gencons.h>
#ifdef DDB
#include <ddb/db_sym.h>
#include <ddb/db_extern.h>
#endif
typedef vaddr_t (*sig_setupstack_t)(const ksiginfo_t *, const sigset_t *,
int, struct lwp *, struct trapframe *, vaddr_t, int, vaddr_t);
#if defined(COMPAT_13) || defined(COMAT_ULTRIX) || defined(COMPAT_IBCS2)
static vaddr_t setupstack_oldsigcontext(const ksiginfo_t *, const sigset_t *,
int, struct lwp *, struct trapframe *, vaddr_t, int, vaddr_t);
#endif
#if defined(COMPAT_16) || defined(COMAT_ULTRIX)
static vaddr_t setupstack_sigcontext2(const ksiginfo_t *, const sigset_t *,
int, struct lwp *, struct trapframe *, vaddr_t, int, vaddr_t);
#endif
static vaddr_t setupstack_siginfo3(const ksiginfo_t *, const sigset_t *,
int, struct lwp *, struct trapframe *, vaddr_t, int, vaddr_t);
const static sig_setupstack_t sig_setupstacks[] = {
#if defined(COMPAT_13) || defined(COMAT_ULTRIX) || defined(COMPAT_IBCS2)
setupstack_oldsigcontext, /* 0 */
setupstack_oldsigcontext, /* 1 */
#else
0, /* 0 */
0, /* 1 */
#endif
#if defined(COMPAT_16) || defined(COMPAT_ULTRIX)
setupstack_sigcontext2, /* 2 */
#else
0, /* 2 */
#endif
setupstack_siginfo3, /* 3 */
};
#if defined(COMPAT_13) || defined(COMAT_ULTRIX) || defined(COMPAT_IBCS2)
int
compat_13_sys_sigreturn(struct lwp *l, void *v, register_t *retval)
{
struct compat_13_sys_sigreturn_args /* {
syscallarg(struct sigcontext13 *) sigcntxp;
} */ *uap = v;
struct proc *p = l->l_proc;
struct trapframe *scf;
struct sigcontext13 *ucntx;
struct sigcontext13 ksc;
sigset_t mask;
scf = l->l_addr->u_pcb.framep;
ucntx = SCARG(uap, sigcntxp);
if (copyin((caddr_t)ucntx, (caddr_t)&ksc, sizeof(struct sigcontext)))
return EINVAL;
/* Compatibility mode? */
if ((ksc.sc_ps & (PSL_IPL | PSL_IS)) ||
((ksc.sc_ps & (PSL_U | PSL_PREVU)) != (PSL_U | PSL_PREVU)) ||
(ksc.sc_ps & PSL_CM)) {
return (EINVAL);
}
if (ksc.sc_onstack & SS_ONSTACK)
p->p_sigctx.ps_sigstk.ss_flags |= SS_ONSTACK;
else
p->p_sigctx.ps_sigstk.ss_flags &= ~SS_ONSTACK;
native_sigset13_to_sigset(&ksc.sc_mask, &mask);
(void) sigprocmask1(p, SIG_SETMASK, &mask, 0);
scf->fp = ksc.sc_fp;
scf->ap = ksc.sc_ap;
scf->pc = ksc.sc_pc;
scf->sp = ksc.sc_sp;
scf->psl = ksc.sc_ps;
return (EJUSTRETURN);
}
#endif
#ifdef COMPAT_16
int
compat_16_sys___sigreturn14(struct lwp *l, void *v, register_t *retval)
{
struct compat_16_sys___sigreturn14_args /* {
syscallarg(struct sigcontext *) sigcntxp;
} */ *uap = v;
struct proc *p = l->l_proc;
struct trapframe *scf;
struct sigcontext *ucntx;
struct sigcontext ksc;
scf = l->l_addr->u_pcb.framep;
ucntx = SCARG(uap, sigcntxp);
if (copyin((caddr_t)ucntx, (caddr_t)&ksc, sizeof(struct sigcontext)))
return EINVAL;
/* Compatibility mode? */
if ((ksc.sc_ps & (PSL_IPL | PSL_IS)) ||
((ksc.sc_ps & (PSL_U | PSL_PREVU)) != (PSL_U | PSL_PREVU)) ||
(ksc.sc_ps & PSL_CM)) {
return (EINVAL);
}
if (ksc.sc_onstack & SS_ONSTACK)
p->p_sigctx.ps_sigstk.ss_flags |= SS_ONSTACK;
else
p->p_sigctx.ps_sigstk.ss_flags &= ~SS_ONSTACK;
/* Restore signal mask. */
(void) sigprocmask1(p, SIG_SETMASK, &ksc.sc_mask, 0);
scf->fp = ksc.sc_fp;
scf->ap = ksc.sc_ap;
scf->pc = ksc.sc_pc;
scf->sp = ksc.sc_sp;
scf->psl = ksc.sc_ps;
return (EJUSTRETURN);
}
struct otrampframe {
unsigned sig; /* Signal number */
unsigned code; /* Info code */
vaddr_t scp; /* Pointer to struct sigcontext */
unsigned r0, r1, r2, r3, r4, r5; /* Registers saved when interrupt */
register_t pc; /* Address of signal handler */
vaddr_t arg; /* Pointer to first (and only) sigreturn argument */
};
static vaddr_t
setupstack_oldsigcontext(const ksiginfo_t *ksi, const sigset_t *mask, int vers,
struct lwp *l, struct trapframe *tf, vaddr_t sp, int onstack,
vaddr_t handler)
{
struct sigcontext sigctx;
struct otrampframe tramp;
sigctx.sc_pc = tf->pc;
sigctx.sc_ps = tf->psl;
sigctx.sc_ap = tf->ap;
sigctx.sc_fp = tf->fp;
sigctx.sc_sp = tf->sp;
sigctx.sc_onstack = onstack ? SS_ONSTACK : 0;
sigctx.sc_mask = *mask;
sp -= sizeof(struct sigcontext);
#if defined(COMPAT_13) || defined(COMPAT_ULTRIX)
native_sigset_to_sigset13(mask, &sigctx.__sc_mask13);
#endif
tramp.sig = ksi->ksi_signo;
tramp.code = ksi->ksi_trap;
/* Set up positions for structs on stack */
tramp.scp = sp;
/* r0..r5 are saved by the popr in the sigcode snippet but we need
to zero them anyway. */
tramp.r0 = tramp.r1 = tramp.r2 = tramp.r3 = tramp.r4 = tramp.r5 = 0;
tramp.pc = (register_t)handler;
tramp.arg = sp;
/* Point stack pointer at pc in trampoline. */
sp =- 8;
if (copyout(&tramp, (caddr_t)tramp.scp - sizeof(tramp), sizeof(tramp)) != 0 ||
copyout(&sigctx, (caddr_t)tramp.scp, sizeof(sigctx)) != 0)
return 0;
return sp;
}
#endif /* COMPAT_16 */
/*
* Brief description of how sendsig() works:
* A struct sigcontext is allocated on the user stack. The relevant
* registers are saved in it. Below it is a struct trampframe constructed, it
* is actually an argument list for callg. The user
* stack pointer is put below all structs.
*
* The registers will contain when the signal handler is called:
* pc, psl - Obvious
* sp - An address below all structs
* fp - The address of the signal handler
* ap - The address to the callg frame
*
* The trampoline code will save r0-r5 before doing anything else.
*/
struct trampoline2 {
unsigned int narg; /* Argument count (== 3) */
unsigned int sig; /* Signal number */
unsigned int code; /* Info code */
vaddr_t scp; /* Pointer to struct sigcontext */
};
static vaddr_t
setupstack_sigcontext2(const ksiginfo_t *ksi, const sigset_t *mask, int vers,
struct lwp *l, struct trapframe *tf, vaddr_t sp, int onstack,
vaddr_t handler)
{
struct trampoline2 tramp;
struct sigcontext sigctx;
/* The sigcontext struct will be passed back to sigreturn(). */
sigctx.sc_pc = tf->pc;
sigctx.sc_ps = tf->psl;
sigctx.sc_ap = tf->ap;
sigctx.sc_fp = tf->fp;
sigctx.sc_sp = tf->sp;
sigctx.sc_onstack = onstack ? SS_ONSTACK : 0;
sigctx.sc_mask = *mask;
sp -= sizeof(struct sigcontext);
/* Arguments given to the signal handler. */
tramp.narg = 3;
tramp.sig = ksi->ksi_signo;
tramp.code = ksi->ksi_trap;
tramp.scp = sp;
sp -= sizeof(tramp);
/* Store the handler in the trapframe. */
tf->fp = handler;
/* Copy out the sigcontext and trampoline. */
if (copyout(&sigctx, (char *)tramp.scp, sizeof(sigctx)) != 0 ||
copyout(&tramp, (char *)sp, sizeof(tramp)) != 0)
return 0;
/* return updated stack pointer */
return sp;
}
/*
* Brief description of how sendsig() works:
* A struct sigcontext is allocated on the user stack. The relevant
* registers are saved in it. Below it is a struct trampframe constructed, it
* is actually an argument list for callg. The user
* stack pointer is put below all structs.
*
* The registers will contain when the signal handler is called:
* pc, psl - Obvious
* sp - An address below all structs
* fp - The address of the signal handler
* ap - The address to the callg frame
*
* The trampoline code will save r0-r5 before doing anything else.
*/
struct trampoline3 {
unsigned int narg; /* Argument count (== 3) */
int sig; /* Signal number */
vaddr_t sip; /* Pointer to siginfo_t */
vaddr_t ucp; /* Pointer to ucontext_t */
};
static vaddr_t
setupstack_siginfo3(const ksiginfo_t *ksi, const sigset_t *mask, int vers,
struct lwp *l, struct trapframe *tf, vaddr_t sp, int onstack,
vaddr_t handler)
{
struct trampoline3 tramp;
ucontext_t uc;
/*
* Arguments given to the signal handler.
*/
tramp.narg = 3;
tramp.sig = ksi->ksi_signo;
sp -= sizeof(uc); tramp.ucp = sp;
sp -= sizeof(siginfo_t); tramp.sip = sp;
sp -= sizeof(tramp);
/* Save register context. */
uc.uc_flags = _UC_SIGMASK;
uc.uc_sigmask = *mask;
uc.uc_link = NULL;
memset(&uc.uc_stack, 0, sizeof(uc.uc_stack));
cpu_getmcontext(l, &uc.uc_mcontext, &uc.uc_flags);
tf->fp = handler;
/* Copy the context to the stack. */
if (copyout(&uc, (char *)tramp.ucp, sizeof(uc)) != 0 ||
copyout(ksi, (char *)tramp.sip, sizeof(*ksi)) != 0 ||
copyout(&tramp, (char *)sp, sizeof(tramp)) != 0)
sigexit(l, SIGILL);
return sp;
};
void
sendsig(const ksiginfo_t *ksi, const sigset_t *mask)
{
struct lwp *l = curlwp;
struct proc *p = l->l_proc;
struct trapframe *tf = l->l_addr->u_pcb.framep;
struct sigaltstack *ss = &p->p_sigctx.ps_sigstk;
const struct sigact_sigdesc *sd =
&p->p_sigacts->sa_sigdesc[ksi->ksi_signo];
vaddr_t sp;
int onstack;
sig_setupstack_t setup;
/* Figure what stack we are running on. */
onstack = (ss->ss_flags & (SS_DISABLE | SS_ONSTACK)) == 0 &&
(sd->sd_sigact.sa_flags & SA_ONSTACK) != 0;
sp = onstack ? ((vaddr_t)ss->ss_sp + ss->ss_size) : tf->sp;
if (sd->sd_vers > 3 || (setup = sig_setupstacks[sd->sd_vers]) == NULL)
goto nosupport;
sp = (*setup)(ksi, mask, sd->sd_vers, l, tf, sp, onstack,
(vaddr_t)sd->sd_sigact.sa_handler);
if (sp == 0)
goto nosupport;
if (sd->sd_vers == 0)
tf->pc = (register_t)p->p_sigctx.ps_sigcode;
else
tf->pc = (register_t)sd->sd_tramp;
tf->psl = PSL_U | PSL_PREVU;
tf->sp = sp;
tf->ap = sp;
if (onstack)
ss->ss_flags |= SS_ONSTACK;
return;
nosupport:
/* Don't know what trampoline version; kill it. */
printf("sendsig(sig %d): bad version %d\n",
ksi->ksi_signo, sd->sd_vers);
sigexit(l, SIGILL);
}

View File

@ -1,4 +1,4 @@
/* $NetBSD: subr.S,v 1.7 2003/01/20 04:45:57 matt Exp $ */
/* $NetBSD: subr.S,v 1.8 2003/09/29 21:04:53 matt Exp $ */
/*
* Copyright (c) 1994 Ludd, University of Lule}, Sweden.
@ -169,7 +169,7 @@ _C_LABEL(sigcode):
movl 0x24(%sp),%r0
calls $3,(%r0)
popr $0x3f
chmk $SYS___sigreturn14
chmk $SYS_compat_16___sigreturn14
chmk $SYS_exit
halt
@ -191,7 +191,7 @@ _C_LABEL(ibcs2_sigcode):
movl 0x24(%sp),%r0
calls $3,(%r0)
popr $0x3f
chmk $SYS___sigreturn14
chmk $SYS_compat_16___sigreturn14
chmk $SYS_exit
halt
_C_LABEL(ibcs2_esigcode):

View File

@ -1,4 +1,4 @@
/* $NetBSD: trap.c,v 1.82 2003/09/18 22:38:36 cl Exp $ */
/* $NetBSD: trap.c,v 1.83 2003/09/29 21:04:53 matt Exp $ */
/*
* Copyright (c) 1994 Ludd, University of Lule}, Sweden.
@ -33,7 +33,7 @@
/* All bugs are subject to removal without further notice */
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: trap.c,v 1.82 2003/09/18 22:38:36 cl Exp $");
__KERNEL_RCSID(0, "$NetBSD: trap.c,v 1.83 2003/09/29 21:04:53 matt Exp $");
#include "opt_ddb.h"
#include "opt_ktrace.h"
@ -163,7 +163,7 @@ userret(struct lwp *l, struct trapframe *frame, u_quad_t oticks)
void
trap(struct trapframe *frame)
{
u_int sig = 0, type = frame->trap, trapsig = 1;
u_int sig = 0, type = frame->trap, trapsig = 1, code = 0;
u_int rv, addr, umode;
struct lwp *l = curlwp;
struct proc *p = l->l_proc;
@ -223,6 +223,7 @@ fram:
case T_ACCFLT|T_USER:
if (frame->code < 0) { /* Check for kernel space */
sig = SIGSEGV;
code = SEGV_ACCERR;
break;
}
@ -293,6 +294,7 @@ if(faultdebug)printf("trap accflt type %lx, code %lx, pc %lx, psl %lx\n",
panic("Segv in kernel mode: pc %x addr %x",
(u_int)frame->pc, (u_int)frame->code);
}
code = SEGV_ACCERR;
if (rv == ENOMEM) {
printf("UVM: pid %d (%s), uid %d killed: "
"out of swap\n",
@ -302,6 +304,8 @@ if(faultdebug)printf("trap accflt type %lx, code %lx, pc %lx, psl %lx\n",
sig = SIGKILL;
} else {
sig = SIGSEGV;
if (rv != EACCES)
code = SEGV_MAPERR;
}
} else {
trapsig = 0;
@ -316,15 +320,26 @@ if(faultdebug)printf("trap accflt type %lx, code %lx, pc %lx, psl %lx\n",
break;
case T_BPTFLT|T_USER:
sig = SIGTRAP;
code = TRAP_BRKPT;
break;
case T_TRCTRAP|T_USER:
sig = SIGTRAP;
code = TRAP_TRACE;
frame->psl &= ~PSL_T;
break;
case T_PRIVINFLT|T_USER:
sig = SIGILL;
code = ILL_PRVOPC;
break;
case T_RESADFLT|T_USER:
sig = SIGILL;
code = ILL_ILLADR;
break;
case T_RESOPFLT|T_USER:
sig = SIGILL;
code = ILL_ILLOPC;
break;
case T_XFCFLT|T_USER:
@ -350,12 +365,17 @@ if(faultdebug)printf("trap accflt type %lx, code %lx, pc %lx, psl %lx\n",
#endif
}
if (trapsig) {
ksiginfo_t ksi;
if ((sig == SIGSEGV || sig == SIGILL) && cpu_printfataltraps)
printf("pid %d.%d (%s): sig %d: type %lx, code %lx, pc %lx, psl %lx\n",
p->p_pid, l->l_lid, p->p_comm, sig, frame->trap,
frame->code, frame->pc, frame->psl);
KERNEL_PROC_LOCK(l);
trapsignal(l, sig, frame->code);
memset(&ksi, 0, sizeof(ksi));
ksi.ksi_signo = sig;
ksi.ksi_trap = frame->code;
ksi.ksi_code = code;
trapsignal(l, &ksi);
KERNEL_PROC_UNLOCK(l);
}