diff --git a/sys/arch/mips/mips/compat_16_machdep.c b/sys/arch/mips/mips/compat_16_machdep.c new file mode 100644 index 000000000000..30d82cac7faf --- /dev/null +++ b/sys/arch/mips/mips/compat_16_machdep.c @@ -0,0 +1,277 @@ +/* $NetBSD: compat_16_machdep.c,v 1.1 2003/10/29 23:39:45 christos Exp $ */ + +/*- + * Copyright (c) 1998, 2001 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility, + * NASA Ames Research Center and by Chris Demetriou. + * + * 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 NetBSD + * Foundation, Inc. and its contributors. + * 4. Neither the name of The NetBSD Foundation 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 NETBSD FOUNDATION, INC. 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 FOUNDATION 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. + */ + +/* + * Copyright 1996 The Board of Trustees of The Leland Stanford + * Junior University. All Rights Reserved. + * + * Permission to use, copy, modify, and distribute this + * software and its documentation for any purpose and without + * fee is hereby granted, provided that the above copyright + * notice appear in all copies. Stanford University + * makes no representations about the suitability of this + * software for any purpose. It is provided "as is" without + * express or implied warranty. + */ + +#include /* RCS ID & Copyright macro defns */ + +__KERNEL_RCSID(0, "$NetBSD: compat_16_machdep.c,v 1.1 2003/10/29 23:39:45 christos Exp $"); + +#include "opt_cputype.h" +#include "opt_compat_netbsd.h" +#include "opt_compat_ultrix.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include +#include + +#ifdef DEBUG +int sigdebug = 0; +int sigpid = 0; +#define SDB_FOLLOW 0x01 +#define SDB_KSTACK 0x02 +#define SDB_FPSTATE 0x04 +#endif + +#ifdef COMPAT_16 +/* + * Send a signal to process. + */ +void +sendsig_sigcontext(const ksiginfo_t *ksi, const sigset_t *returnmask) +{ + int sig = ksi->ksi_signo; + struct lwp *l = curlwp; + struct proc *p = l->l_proc; + struct sigacts *ps = p->p_sigacts; + int onstack; + struct sigcontext *scp = getframe(l, sig, &onstack), ksc; + struct frame *f; + sig_t catcher = SIGACTION(p, sig).sa_handler; + + f = (struct frame *)l->l_md.md_regs; + + scp--; + +#ifdef DEBUG + if ((sigdebug & SDB_FOLLOW) || + ((sigdebug & SDB_KSTACK) && p->p_pid == sigpid)) + printf("sendsig(%d): sig %d ssp %p scp %p\n", + p->p_pid, sig, &onstack, scp); +#endif + + /* Build stack frame for signal trampoline. */ + ksc.sc_pc = f->f_regs[PC]; + ksc.mullo = f->f_regs[MULLO]; + ksc.mulhi = f->f_regs[MULHI]; + + /* Save register context. */ + ksc.sc_regs[ZERO] = 0xACEDBADE; /* magic number */ + memcpy(&ksc.sc_regs[1], &f->f_regs[1], + sizeof(ksc.sc_regs) - sizeof(ksc.sc_regs[0])); + + /* Save the FP state, if necessary, then copy it. */ +#ifndef SOFTFLOAT + ksc.sc_fpused = l->l_md.md_flags & MDP_FPUSED; + if (ksc.sc_fpused) { + /* if FPU has current state, save it first */ + if (l == fpcurlwp) + savefpregs(l); + *(struct fpreg *)ksc.sc_fpregs = l->l_addr->u_pcb.pcb_fpregs; + } +#else + *(struct fpreg *)ksc.sc_fpregs = l->l_addr->u_pcb.pcb_fpregs; +#endif + + /* Save signal stack. */ + ksc.sc_onstack = p->p_sigctx.ps_sigstk.ss_flags & SS_ONSTACK; + + /* Save signal mask. */ + ksc.sc_mask = *returnmask; + +#if defined(COMPAT_13) || defined(COMPAT_ULTRIX) + /* + * XXX We always have to save an old style signal mask because + * XXX we might be delivering a signal to a process which will + * XXX escape from the signal in a non-standard way and invoke + * XXX sigreturn() directly. + */ + native_sigset_to_sigset13(returnmask, &ksc.__sc_mask13); +#endif + + if (copyout(&ksc, (caddr_t)scp, sizeof(ksc))) { + /* + * Process has trashed its stack; give it an illegal + * instruction to halt it in its tracks. + */ +#ifdef DEBUG + if ((sigdebug & SDB_FOLLOW) || + ((sigdebug & SDB_KSTACK) && p->p_pid == sigpid)) + printf("sendsig(%d): copyout failed on sig %d\n", + p->p_pid, sig); +#endif + sigexit(l, SIGILL); + /* NOTREACHED */ + } + + /* + * Set up the registers to directly invoke the signal + * handler. The return address will be set up to point + * to the signal trampoline to bounce us back. + */ + f->f_regs[A0] = sig; + f->f_regs[A1] = ksi->ksi_trap; + f->f_regs[A2] = (int)scp; + f->f_regs[A3] = (int)catcher; /* XXX ??? */ + + f->f_regs[PC] = (int)catcher; + f->f_regs[T9] = (int)catcher; + f->f_regs[SP] = (int)scp; + + switch (ps->sa_sigdesc[sig].sd_vers) { +#if 1 /* COMPAT_16 */ + case 0: /* legacy on-stack sigtramp */ + f->f_regs[RA] = (int)p->p_sigctx.ps_sigcode; + break; +#endif /* COMPAT_16 */ + + case 1: + f->f_regs[RA] = (int)ps->sa_sigdesc[sig].sd_tramp; + break; + + default: + /* Don't know what trampoline version; kill it. */ + sigexit(l, SIGILL); + } + + /* Remember that we're now on the signal stack. */ + if (onstack) + p->p_sigctx.ps_sigstk.ss_flags |= SS_ONSTACK; + +#ifdef DEBUG + if ((sigdebug & SDB_FOLLOW) || + ((sigdebug & SDB_KSTACK) && p->p_pid == sigpid)) + printf("sendsig(%d): sig %d returns\n", + p->p_pid, sig); +#endif +} + +/* + * 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 + * psl to gain improper privileges or to cause + * a machine fault. + */ +/* ARGSUSED */ +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 sigcontext *scp, ksc; + struct frame *f; + struct proc *p = l->l_proc; + int error; + + /* + * The trampoline code hands us the context. + * It is unsafe to keep track of it ourselves, in the event that a + * program jumps out of a signal handler. + */ + scp = SCARG(uap, sigcntxp); +#ifdef DEBUG + if (sigdebug & SDB_FOLLOW) + printf("sigreturn: pid %d, scp %p\n", l->l_proc->p_pid, scp); +#endif + if ((error = copyin(scp, &ksc, sizeof(ksc))) != 0) + return (error); + + if ((u_int) ksc.sc_regs[ZERO] != 0xacedbadeU) /* magic number */ + return (EINVAL); + + /* Restore the register context. */ + f = (struct frame *)l->l_md.md_regs; + f->f_regs[PC] = ksc.sc_pc; + f->f_regs[MULLO] = ksc.mullo; + f->f_regs[MULHI] = ksc.mulhi; + memcpy(&f->f_regs[1], &scp->sc_regs[1], + sizeof(scp->sc_regs) - sizeof(scp->sc_regs[0])); +#ifndef SOFTFLOAT + if (scp->sc_fpused) { + /* Disable the FPU to fault in FP registers. */ + f->f_regs[SR] &= ~MIPS_SR_COP_1_BIT; + if (l == fpcurlwp) { + fpcurlwp = (struct lwp *)0; + } + l->l_addr->u_pcb.pcb_fpregs = *(struct fpreg *)scp->sc_fpregs; + } +#else + l->l_addr->u_pcb.pcb_fpregs = *(struct fpreg *)scp->sc_fpregs; +#endif + + /* Restore signal stack. */ + 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); + + return (EJUSTRETURN); +} +#endif diff --git a/sys/arch/mips/mips/linux_trap.c b/sys/arch/mips/mips/linux_trap.c index 9ca50a183409..84952e54fa05 100644 --- a/sys/arch/mips/mips/linux_trap.c +++ b/sys/arch/mips/mips/linux_trap.c @@ -1,4 +1,4 @@ -/* $NetBSD: linux_trap.c,v 1.3 2003/07/15 02:43:38 lukem Exp $ */ +/* $NetBSD: linux_trap.c,v 1.4 2003/10/29 23:39:45 christos Exp $ */ /*- * Copyright (c) 2001 The NetBSD Foundation, Inc. @@ -37,7 +37,7 @@ */ #include -__KERNEL_RCSID(0, "$NetBSD: linux_trap.c,v 1.3 2003/07/15 02:43:38 lukem Exp $"); +__KERNEL_RCSID(0, "$NetBSD: linux_trap.c,v 1.4 2003/10/29 23:39:45 christos Exp $"); #include #include @@ -50,7 +50,14 @@ __KERNEL_RCSID(0, "$NetBSD: linux_trap.c,v 1.3 2003/07/15 02:43:38 lukem Exp $") #include +#ifndef __HAVE_SIGINFO void linux_trapsignal(struct lwp *l, int signo, u_long type) { - trapsignal(l, signo, type); + (*l->l_proc->p_emul->e_trapsignal)(l, signo, type); } +#else +void +linux_trapsignal(struct lwp *l, const ksiginfo_t *ksi) { + (*l->l_proc->p_emul->e_trapsignal)(l, ksi); +} +#endif diff --git a/sys/arch/mips/mips/mips_emul.c b/sys/arch/mips/mips/mips_emul.c index 287d441313f5..c699c00cd132 100644 --- a/sys/arch/mips/mips/mips_emul.c +++ b/sys/arch/mips/mips/mips_emul.c @@ -1,4 +1,4 @@ -/* $NetBSD: mips_emul.c,v 1.7 2003/07/15 02:43:39 lukem Exp $ */ +/* $NetBSD: mips_emul.c,v 1.8 2003/10/29 23:39:45 christos Exp $ */ /* * Copyright (c) 1999 Shuichiro URATA. All rights reserved. @@ -27,7 +27,7 @@ */ #include -__KERNEL_RCSID(0, "$NetBSD: mips_emul.c,v 1.7 2003/07/15 02:43:39 lukem Exp $"); +__KERNEL_RCSID(0, "$NetBSD: mips_emul.c,v 1.8 2003/10/29 23:39:45 christos Exp $"); #include #include @@ -213,6 +213,7 @@ MachEmulateInst(status, cause, opc, frame) struct frame *frame; { u_int32_t inst; + ksiginfo_t ksi; /* * Fetch the instruction. @@ -252,7 +253,18 @@ MachEmulateInst(status, cause, opc, frame) default: frame->f_regs[CAUSE] = cause; frame->f_regs[BADVADDR] = opc; - trapsignal(curlwp, SIGSEGV, opc); + KSI_INIT_TRAP(&ksi); + ksi.ksi_signo = SIGSEGV; + ksi.ksi_trap = cause; /* XXX */ + ksi.ksi_code = SEGV_MAPERR; + ksi.ksi_addr = (void *)opc; +#ifdef __HAVE_SIGINFO + (*curproc->p_emul->e_trapsignal)(curlwp, &ksi); +#else + (*curproc->p_emul->e_trapsignal)(curlwp, ksi.ksi_signo, + ksi.ksi_trap); +#endif + break; } } @@ -260,12 +272,20 @@ static __inline void send_sigsegv(u_int32_t vaddr, u_int32_t exccode, struct frame *frame, u_int32_t cause) { - + ksiginfo_t ksi; cause = (cause & 0xFFFFFF00) | (exccode << MIPS_CR_EXC_CODE_SHIFT); - frame->f_regs[CAUSE] = cause; frame->f_regs[BADVADDR] = vaddr; - trapsignal(curlwp, SIGSEGV, vaddr); + KSI_INIT_TRAP(&ksi); + ksi.ksi_signo = SIGSEGV; + ksi.ksi_trap = cause; + ksi.ksi_code = SEGV_MAPERR; + ksi.ksi_addr = (void *)vaddr; +#ifdef __HAVE_SIGINFO + (*curproc->p_emul->e_trapsignal)(curlwp, &ksi); +#else + (*curproc->p_emul->e_trapsignal)(curlwp, ksi.ksi_signo, ksi.ksi_trap); +#endif } static __inline void @@ -294,9 +314,20 @@ MachEmulateLWC0(u_int32_t inst, struct frame *frame, u_int32_t cause) /* segment and alignment check */ if (vaddr > VM_MAX_ADDRESS || vaddr & 0x3) { + ksiginfo_t ksi; frame->f_regs[CAUSE] = cause; frame->f_regs[BADVADDR] = vaddr; - trapsignal(curlwp, SIGBUS, vaddr); + KSI_INIT_TRAP(&ksi); + ksi.ksi_signo = SIGBUS; + ksi.ksi_trap = cause; + ksi.ksi_code = (vaddr & 3) ? BUS_ADRALN : BUS_ADRERR; + ksi.ksi_addr = (void *)vaddr; +#ifdef __HAVE_SIGINFO + (*curproc->p_emul->e_trapsignal)(curlwp, &ksi); +#else + (*curproc->p_emul->e_trapsignal)(curlwp, ksi.ksi_signo, + ksi.ksi_trap); +#endif return; } @@ -329,9 +360,20 @@ MachEmulateSWC0(u_int32_t inst, struct frame *frame, u_int32_t cause) /* segment and alignment check */ if (vaddr > VM_MAX_ADDRESS || vaddr & 0x3) { + ksiginfo_t ksi; frame->f_regs[CAUSE] = cause; frame->f_regs[BADVADDR] = vaddr; - trapsignal(curlwp, SIGBUS, vaddr); + KSI_INIT_TRAP(&ksi); + ksi.ksi_signo = SIGBUS; + ksi.ksi_trap = cause; + ksi.ksi_code = (vaddr & 3) ? BUS_ADRALN : BUS_ADRERR; + ksi.ksi_addr = (void *)vaddr; +#ifdef __HAVE_SIGINFO + (*curproc->p_emul->e_trapsignal)(curlwp, &ksi); +#else + (*curproc->p_emul->e_trapsignal)(curlwp, ksi.ksi_signo, + ksi.ksi_trap); +#endif return; } @@ -372,6 +414,7 @@ MachEmulateSWC0(u_int32_t inst, struct frame *frame, u_int32_t cause) void MachEmulateSpecial(u_int32_t inst, struct frame *frame, u_int32_t cause) { + ksiginfo_t ksi; switch (((InstFmt)inst).RType.func) { case OP_SYNC: /* nothing */ @@ -379,7 +422,18 @@ MachEmulateSpecial(u_int32_t inst, struct frame *frame, u_int32_t cause) default: frame->f_regs[CAUSE] = cause; frame->f_regs[BADVADDR] = frame->f_regs[PC]; - trapsignal(curlwp, SIGSEGV, frame->f_regs[PC]); + KSI_INIT_TRAP(&ksi); + ksi.ksi_signo = SIGSEGV; + ksi.ksi_trap = cause; + ksi.ksi_code = SEGV_MAPERR; + ksi.ksi_addr = (void *)frame->f_regs[PC]; +#ifdef __HAVE_SIGINFO + (*curproc->p_emul->e_trapsignal)(curlwp, &ksi); +#else + (*curproc->p_emul->e_trapsignal)(curlwp, ksi.ksi_signo, + ksi.ksi_trap); +#endif + break; } update_pc(frame, cause); diff --git a/sys/arch/mips/mips/pmap.c b/sys/arch/mips/mips/pmap.c index 53c477f9d100..1f414ef5e8bd 100644 --- a/sys/arch/mips/mips/pmap.c +++ b/sys/arch/mips/mips/pmap.c @@ -1,4 +1,4 @@ -/* $NetBSD: pmap.c,v 1.151 2003/10/05 16:38:03 tsutsui Exp $ */ +/* $NetBSD: pmap.c,v 1.152 2003/10/29 23:39:45 christos Exp $ */ /*- * Copyright (c) 1998, 2001 The NetBSD Foundation, Inc. @@ -74,7 +74,7 @@ #include -__KERNEL_RCSID(0, "$NetBSD: pmap.c,v 1.151 2003/10/05 16:38:03 tsutsui Exp $"); +__KERNEL_RCSID(0, "$NetBSD: pmap.c,v 1.152 2003/10/29 23:39:45 christos Exp $"); /* * Manages physical address maps. @@ -976,9 +976,11 @@ pmap_procwr(p, va, len) vaddr_t va; size_t len; { +#ifdef MIPS1 pmap_t pmap; pmap = p->p_vmspace->vm_map.pmap; +#endif /* MIPS1 */ if (MIPS_HAS_R4K_MMU) { #ifdef MIPS3_PLUS /* XXX mmu XXX */ diff --git a/sys/arch/mips/mips/sig_machdep.c b/sys/arch/mips/mips/sig_machdep.c index 38245d467bd2..b2922fa21782 100644 --- a/sys/arch/mips/mips/sig_machdep.c +++ b/sys/arch/mips/mips/sig_machdep.c @@ -1,12 +1,11 @@ -/* $NetBSD: sig_machdep.c,v 1.5 2003/09/26 12:02:56 simonb Exp $ */ +/* $NetBSD: sig_machdep.c,v 1.6 2003/10/29 23:39:45 christos Exp $ */ /*- - * Copyright (c) 1998, 2001 The NetBSD Foundation, Inc. + * Copyright (c) 2003 The NetBSD Foundation, Inc. * All rights reserved. * * This code is derived from software contributed to The NetBSD Foundation - * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility, - * NASA Ames Research Center and by Chris Demetriou. + * by Christos Zoulas. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -37,26 +36,12 @@ * POSSIBILITY OF SUCH DAMAGE. */ -/* - * Copyright 1996 The Board of Trustees of The Leland Stanford - * Junior University. All Rights Reserved. - * - * Permission to use, copy, modify, and distribute this - * software and its documentation for any purpose and without - * fee is hereby granted, provided that the above copyright - * notice appear in all copies. Stanford University - * makes no representations about the suitability of this - * software for any purpose. It is provided "as is" without - * express or implied warranty. - */ - #include /* RCS ID & Copyright macro defns */ -__KERNEL_RCSID(0, "$NetBSD: sig_machdep.c,v 1.5 2003/09/26 12:02:56 simonb Exp $"); +__KERNEL_RCSID(0, "$NetBSD: sig_machdep.c,v 1.6 2003/10/29 23:39:45 christos Exp $"); #include "opt_cputype.h" #include "opt_compat_netbsd.h" -#include "opt_compat_ultrix.h" #include #include @@ -71,103 +56,77 @@ __KERNEL_RCSID(0, "$NetBSD: sig_machdep.c,v 1.5 2003/09/26 12:02:56 simonb Exp $ #include +#include #include -#ifdef DEBUG -int sigdebug = 0; -int sigpid = 0; -#define SDB_FOLLOW 0x01 -#define SDB_KSTACK 0x02 -#define SDB_FPSTATE 0x04 -#endif +void * +getframe(struct lwp *l, int sig, int *onstack) +{ + struct proc *p = l->l_proc; + struct sigctx *ctx = &p->p_sigctx; + struct frame *fp = l->l_md.md_regs; + + /* Do we need to jump onto the signal stack? */ + *onstack = (ctx->ps_sigstk.ss_flags & (SS_DISABLE | SS_ONSTACK)) == 0 + && (SIGACTION(p, sig).sa_flags & SA_ONSTACK) != 0; + if (*onstack) + return (char *)ctx->ps_sigstk.ss_sp + ctx->ps_sigstk.ss_size; + else + return (void *)fp->f_regs[SP]; +} + +struct sigframe_siginfo { + ksiginfo_t sf_si; + ucontext_t sf_uc; +}; /* * Send a signal to process. */ -void -sendsig(int sig, const sigset_t *returnmask, u_long code) +static void +sendsig_siginfo(const ksiginfo_t *ksi, const sigset_t *mask) { struct lwp *l = curlwp; struct proc *p = l->l_proc; struct sigacts *ps = p->p_sigacts; - struct sigcontext *scp, ksc; - struct frame *f; int onstack; + int sig = ksi->ksi_signo; + struct sigframe_siginfo *fp = getframe(l, sig, &onstack); + struct frame *tf; + ucontext_t uc; + size_t ucsz; sig_t catcher = SIGACTION(p, sig).sa_handler; - f = (struct frame *)l->l_md.md_regs; + tf = (struct frame *)l->l_md.md_regs; + fp--; - /* Do we need to jump onto the signal stack? */ - onstack = - (p->p_sigctx.ps_sigstk.ss_flags & (SS_DISABLE | SS_ONSTACK)) == 0 && - (SIGACTION(p, sig).sa_flags & SA_ONSTACK) != 0; + /* Build stack frame for signal trampoline. */ + switch (ps->sa_sigdesc[sig].sd_vers) { + case 0: /* handled by sendsig_sigcontext */ + case 1: /* handled by sendsig_sigcontext */ + default: /* unknown version */ + printf("sendsig_siginfo: bad version %d\n", + ps->sa_sigdesc[sig].sd_vers); + sigexit(l, SIGILL); + case 2: + break; + } - /* Allocate space for the signal handler context. */ - if (onstack) - scp = (struct sigcontext *)((caddr_t)p->p_sigctx.ps_sigstk.ss_sp - + p->p_sigctx.ps_sigstk.ss_size); - else - /* cast for _MIPS_BSD_API == _MIPS_BSD_API_LP32_64CLEAN case */ - scp = (struct sigcontext *)(u_int32_t)f->f_regs[SP]; - scp--; + uc.uc_flags = _UC_SIGMASK + | (p->p_sigctx.ps_sigstk.ss_flags & SS_ONSTACK) + ? _UC_SETSTACK : _UC_CLRSTACK; + 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); + ucsz = (char *)&uc.__uc_pad - (char *)&uc; -#ifdef DEBUG - if ((sigdebug & SDB_FOLLOW) || - ((sigdebug & SDB_KSTACK) && p->p_pid == sigpid)) - printf("sendsig(%d): sig %d ssp %p scp %p\n", - p->p_pid, sig, &onstack, scp); -#endif - - /* Build stack frame for signal trampoline. */ - ksc.sc_pc = f->f_regs[PC]; - ksc.mullo = f->f_regs[MULLO]; - ksc.mulhi = f->f_regs[MULHI]; - - /* Save register context. */ - ksc.sc_regs[ZERO] = 0xACEDBADE; /* magic number */ - memcpy(&ksc.sc_regs[1], &f->f_regs[1], - sizeof(ksc.sc_regs) - sizeof(ksc.sc_regs[0])); - - /* Save the FP state, if necessary, then copy it. */ -#ifndef SOFTFLOAT - ksc.sc_fpused = l->l_md.md_flags & MDP_FPUSED; - if (ksc.sc_fpused) { - /* if FPU has current state, save it first */ - if (l == fpcurlwp) - savefpregs(l); - *(struct fpreg *)ksc.sc_fpregs = l->l_addr->u_pcb.pcb_fpregs; - } -#else - *(struct fpreg *)ksc.sc_fpregs = l->l_addr->u_pcb.pcb_fpregs; -#endif - - /* Save signal stack. */ - ksc.sc_onstack = p->p_sigctx.ps_sigstk.ss_flags & SS_ONSTACK; - - /* Save signal mask. */ - ksc.sc_mask = *returnmask; - -#if defined(COMPAT_13) || defined(COMPAT_ULTRIX) - /* - * XXX We always have to save an old style signal mask because - * XXX we might be delivering a signal to a process which will - * XXX escape from the signal in a non-standard way and invoke - * XXX sigreturn() directly. - */ - native_sigset_to_sigset13(returnmask, &ksc.__sc_mask13); -#endif - - if (copyout(&ksc, (caddr_t)scp, sizeof(ksc))) { + if (copyout(&ksi->ksi_info, &fp->sf_si, sizeof(ksi->ksi_info)) != 0 || + copyout(&uc, &fp->sf_uc, ucsz) != 0) { /* * Process has trashed its stack; give it an illegal * instruction to halt it in its tracks. */ -#ifdef DEBUG - if ((sigdebug & SDB_FOLLOW) || - ((sigdebug & SDB_KSTACK) && p->p_pid == sigpid)) - printf("sendsig(%d): copyout failed on sig %d\n", - p->p_pid, sig); -#endif sigexit(l, SIGILL); /* NOTREACHED */ } @@ -177,109 +136,28 @@ sendsig(int sig, const sigset_t *returnmask, u_long code) * handler. The return address will be set up to point * to the signal trampoline to bounce us back. */ - f->f_regs[A0] = sig; - f->f_regs[A1] = code; - f->f_regs[A2] = (int)scp; - f->f_regs[A3] = (int)catcher; /* XXX ??? */ + tf->f_regs[A0] = sig; + tf->f_regs[A1] = (__greg_t)&fp->sf_si; + tf->f_regs[A2] = (__greg_t)&fp->sf_uc; - f->f_regs[PC] = (int)catcher; - f->f_regs[T9] = (int)catcher; - f->f_regs[SP] = (int)scp; - - switch (ps->sa_sigdesc[sig].sd_vers) { -#if 1 /* COMPAT_16 */ - case 0: /* legacy on-stack sigtramp */ - f->f_regs[RA] = (int)p->p_sigctx.ps_sigcode; - break; -#endif /* COMPAT_16 */ - - case 1: - f->f_regs[RA] = (int)ps->sa_sigdesc[sig].sd_tramp; - break; - - default: - /* Don't know what trampoline version; kill it. */ - sigexit(l, SIGILL); - } + tf->f_regs[PC] = (__greg_t)catcher; + tf->f_regs[T9] = (__greg_t)catcher; + tf->f_regs[SP] = (__greg_t)fp; + tf->f_regs[RA] = (__greg_t)ps->sa_sigdesc[sig].sd_tramp; /* Remember that we're now on the signal stack. */ if (onstack) p->p_sigctx.ps_sigstk.ss_flags |= SS_ONSTACK; - -#ifdef DEBUG - if ((sigdebug & SDB_FOLLOW) || - ((sigdebug & SDB_KSTACK) && p->p_pid == sigpid)) - printf("sendsig(%d): sig %d returns\n", - p->p_pid, sig); -#endif } -/* - * 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 - * psl to gain improper privileges or to cause - * a machine fault. - */ -/* ARGSUSED */ -int -sys___sigreturn14(struct lwp *l, void *v, register_t *retval) -{ - struct sys___sigreturn14_args /* { - syscallarg(struct sigcontext *) sigcntxp; - } */ *uap = v; - struct sigcontext *scp, ksc; - struct frame *f; - struct proc *p = l->l_proc; - int error; +void +sendsig(const ksiginfo_t *ksi, const sigset_t *mask) +{ +#ifdef COMPAT_16 + if (curproc->p_sigacts->sa_sigdesc[ksi->ksi_signo].sd_vers < 2) + sendsig_sigcontext(ksi, mask); + else +#endif + sendsig_siginfo(ksi, mask); +} - /* - * The trampoline code hands us the context. - * It is unsafe to keep track of it ourselves, in the event that a - * program jumps out of a signal handler. - */ - scp = SCARG(uap, sigcntxp); -#ifdef DEBUG - if (sigdebug & SDB_FOLLOW) - printf("sigreturn: pid %d, scp %p\n", l->l_proc->p_pid, scp); -#endif - if ((error = copyin(scp, &ksc, sizeof(ksc))) != 0) - return (error); - - if ((u_int) ksc.sc_regs[ZERO] != 0xacedbadeU) /* magic number */ - return (EINVAL); - - /* Restore the register context. */ - f = (struct frame *)l->l_md.md_regs; - f->f_regs[PC] = ksc.sc_pc; - f->f_regs[MULLO] = ksc.mullo; - f->f_regs[MULHI] = ksc.mulhi; - memcpy(&f->f_regs[1], &scp->sc_regs[1], - sizeof(scp->sc_regs) - sizeof(scp->sc_regs[0])); -#ifndef SOFTFLOAT - if (scp->sc_fpused) { - /* Disable the FPU to fault in FP registers. */ - f->f_regs[SR] &= ~MIPS_SR_COP_1_BIT; - if (l == fpcurlwp) { - fpcurlwp = (struct lwp *)0; - } - l->l_addr->u_pcb.pcb_fpregs = *(struct fpreg *)scp->sc_fpregs; - } -#else - l->l_addr->u_pcb.pcb_fpregs = *(struct fpreg *)scp->sc_fpregs; -#endif - - /* Restore signal stack. */ - 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); - - return (EJUSTRETURN); -} diff --git a/sys/arch/mips/mips/sigcode.S b/sys/arch/mips/mips/sigcode.S index 5f018366f05d..2ba25e71b27d 100644 --- a/sys/arch/mips/mips/sigcode.S +++ b/sys/arch/mips/mips/sigcode.S @@ -1,9 +1,11 @@ -/* $NetBSD: sigcode.S,v 1.1 2002/11/09 02:02:33 nisimura Exp $ */ +/* $NetBSD: sigcode.S,v 1.2 2003/10/29 23:39:45 christos Exp $ */ +#include "opt_compat_netbsd.h" #include "opt_compat_ultrix.h" #include "opt_compat_linux.h" #include "opt_compat_irix.h" +#include #include #ifdef COMPAT_ULTRIX #include @@ -20,6 +22,7 @@ .set noreorder +#ifdef COMPAT_16 /* * This code is copied the user's stack for returning from signal handlers * (see sendsig() and sigreturn()). We have to compute the address @@ -29,11 +32,12 @@ */ LEAF_NOPROFILE(sigcode) move a0, sp # address of sigcontext - li v0, SYS___sigreturn14 # sigreturn(scp) + li v0, SYS_compat_16___sigreturn14 # sigreturn(scp) syscall break 0 # just in case sigreturn fails END(sigcode) XLEAF(esigcode) +#endif #ifdef COMPAT_ULTRIX LEAF_NOPROFILE(ultrix_sigcode) diff --git a/sys/arch/mips/mips/trap.c b/sys/arch/mips/mips/trap.c index 341f31f5bb4f..925a436de75c 100644 --- a/sys/arch/mips/mips/trap.c +++ b/sys/arch/mips/mips/trap.c @@ -1,4 +1,4 @@ -/* $NetBSD: trap.c,v 1.183 2003/10/21 15:05:56 tsutsui Exp $ */ +/* $NetBSD: trap.c,v 1.184 2003/10/29 23:39:45 christos Exp $ */ /* * Copyright (c) 1992, 1993 @@ -78,7 +78,7 @@ #include /* RCS ID & Copyright macro defns */ -__KERNEL_RCSID(0, "$NetBSD: trap.c,v 1.183 2003/10/21 15:05:56 tsutsui Exp $"); +__KERNEL_RCSID(0, "$NetBSD: trap.c,v 1.184 2003/10/29 23:39:45 christos Exp $"); #include "opt_cputype.h" /* which mips CPU levels do we support? */ #include "opt_ktrace.h" @@ -212,14 +212,15 @@ trap(status, cause, vaddr, opc, frame) unsigned opc; struct trapframe *frame; { - int type, sig; - int ucode = 0; + int type; struct lwp *l = curlwp; - struct proc *p; + struct proc *p = curproc; vm_prot_t ftype; + ksiginfo_t ksi; + struct frame *fp = (struct frame *)l->l_md.md_regs; extern void fswintrberr(void); + KSI_INIT_TRAP(&ksi); - p = l ? l->l_proc : NULL; uvmexp.traps++; type = TRAPTYPE(cause); if (USERMODE(status)) @@ -246,8 +247,7 @@ trap(status, cause, vaddr, opc, frame) status, cause, opc, vaddr); if (curlwp != NULL) printf("pid=%d cmd=%s usp=0x%x ", - p->p_pid, p->p_comm, - (int)((struct frame *)l->l_md.md_regs)->f_regs[SP]); + p->p_pid, p->p_comm, (int)fp->f_regs[SP]); else printf("curlwp == NULL "); printf("ksp=0x%x\n", (int)&status); @@ -424,11 +424,19 @@ trap(status, cause, vaddr, opc, frame) p->p_pid, p->p_comm, p->p_cred && p->p_ucred ? p->p_ucred->cr_uid : (uid_t) -1); - sig = SIGKILL; + ksi.ksi_signo = SIGKILL; + ksi.ksi_code = 0; } else { - sig = (rv == EACCES) ? SIGBUS : SIGSEGV; + if (rv == EACCES) { + ksi.ksi_signo = SIGBUS; + ksi.ksi_code = BUS_OBJERR; + } else { + ksi.ksi_signo = SIGSEGV; + ksi.ksi_code = SEGV_MAPERR; + } } - ucode = vaddr; + ksi.ksi_trap = type & ~T_USER; + ksi.ksi_addr = (void *)vaddr; break; /* SIGNAL */ } kernelfault: ; @@ -455,8 +463,10 @@ trap(status, cause, vaddr, opc, frame) case T_ADDR_ERR_ST+T_USER: /* misaligned or kseg access */ case T_BUS_ERR_IFETCH+T_USER: /* BERR asserted to cpu */ case T_BUS_ERR_LD_ST+T_USER: /* BERR asserted to cpu */ - sig = SIGSEGV; - ucode = vaddr; + ksi.ksi_trap = type & ~T_USER; + ksi.ksi_signo = SIGSEGV; /* XXX */ + ksi.ksi_addr = (void *)vaddr; + ksi.ksi_code = SEGV_MAPERR; /* XXX */ break; /* SIGNAL */ case T_BREAK: @@ -501,7 +511,10 @@ trap(status, cause, vaddr, opc, frame) instr = fuiword((void *)va); if (l->l_md.md_ss_addr != va || instr != MIPS_BREAK_SSTEP) { - sig = SIGTRAP; + ksi.ksi_trap = type & ~T_USER; + ksi.ksi_signo = SIGTRAP; + ksi.ksi_addr = (void *)va; + ksi.ksi_code = TRAP_TRACE; break; } /* @@ -527,7 +540,10 @@ trap(status, cause, vaddr, opc, frame) printf("Warning: can't restore instruction at 0x%lx: 0x%x\n", l->l_md.md_ss_addr, l->l_md.md_ss_instr); l->l_md.md_ss_addr = 0; - sig = SIGTRAP; + ksi.ksi_trap = type & ~T_USER; + ksi.ksi_signo = SIGTRAP; + ksi.ksi_addr = (void *)va; + ksi.ksi_code = TRAP_BRKPT; break; /* SIGNAL */ } case T_RES_INST+T_USER: @@ -559,12 +575,19 @@ trap(status, cause, vaddr, opc, frame) return; /* GEN */ case T_OVFLOW+T_USER: case T_TRAP+T_USER: - sig = SIGFPE; + ksi.ksi_trap = type & ~T_USER; + ksi.ksi_signo = SIGFPE; + ksi.ksi_addr = (void *)fp->f_regs[PC]; + ksi.ksi_code = FPE_FLTOVF; /* XXX */ break; /* SIGNAL */ } - ((struct frame *)l->l_md.md_regs)->f_regs[CAUSE] = cause; - ((struct frame *)l->l_md.md_regs)->f_regs[BADVADDR] = vaddr; - trapsignal(l, sig, ucode); + fp->f_regs[CAUSE] = cause; + fp->f_regs[BADVADDR] = vaddr; +#ifdef __HAVE_SIGINFO + (*p->p_emul->e_trapsignal)(l, &ksi); +#else + (*p->p_emul->e_trapsignal)(l, ksi.ksi_signo, ksi.ksi_trap); +#endif if ((type & T_USER) == 0) panic("trapsignal"); userret(l);