Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/sys Add signal delivery for the PowerPC. Everything is imple...



details:   https://anonhg.NetBSD.org/src/rev/d59859e5c1e0
branches:  trunk
changeset: 539829:d59859e5c1e0
user:      manu <manu%NetBSD.org@localhost>
date:      Tue Nov 26 23:54:09 2002 +0000

description:
Add signal delivery for the PowerPC. Everything is implemented except siginfo.
The stack layout is observed from stack dumps on Darwin, so it should be
very accurate.

diffstat:

 sys/arch/powerpc/include/darwin_machdep.h |   99 ++++++++++++++++
 sys/arch/powerpc/powerpc/darwin_machdep.c |  177 ++++++++++++++++++++++++++++-
 sys/compat/darwin/darwin_exec.c           |    7 +-
 sys/compat/darwin/darwin_signal.h         |   39 +++++-
 4 files changed, 304 insertions(+), 18 deletions(-)

diffs (truncated from 411 to 300 lines):

diff -r f39620c7f00b -r d59859e5c1e0 sys/arch/powerpc/include/darwin_machdep.h
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/sys/arch/powerpc/include/darwin_machdep.h Tue Nov 26 23:54:09 2002 +0000
@@ -0,0 +1,99 @@
+/*     $NetBSD: darwin_machdep.h,v 1.1 2002/11/26 23:54:09 manu Exp $ */
+
+/*-
+ * Copyright (c) 2002 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Emmanuel Dreyfus
+ *
+ * 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.
+ */
+
+#ifndef        _DARWIN_MACHDEP_H_
+#define        _DARWIN_MACHDEP_H_
+
+struct darwin_ppc_exception_state {
+       unsigned long dar;
+       unsigned long dsisr;
+       unsigned long exception;
+       unsigned long pad[5];
+};
+
+struct darwin_ppc_thread_state {
+       unsigned int srr0;
+       unsigned int srr1;
+       unsigned int gpreg[32];
+       unsigned int cr;
+       unsigned int xer;
+       unsigned int lr;
+       unsigned int ctr;
+       unsigned int mq;
+       unsigned int vrsave;
+};
+
+struct darwin_ppc_float_state {
+       double  fpregs[32];
+       unsigned int fpscr_pad;
+       unsigned int fpscr;
+};
+
+struct darwin_ppc_vector_state {
+       unsigned long vr[32][4];
+       unsigned long vscr[4];
+       unsigned int pad1[4];
+       unsigned int vrvalid;
+       unsigned int pad2[7];
+};
+
+struct darwin_mcontext {
+       struct darwin_ppc_exception_state es;   
+       struct darwin_ppc_thread_state ss;
+       struct darwin_ppc_float_state fs;
+       struct darwin_ppc_vector_state vs;                      
+};
+
+struct darwin_sigframe {
+       int nocopy1[30];
+       /* struct darwin_mcontext without the vs field */
+       struct darwin__mcontext {
+               struct darwin_ppc_exception_state es;
+               struct darwin_ppc_thread_state ss;
+               struct darwin_ppc_float_state fs;
+       } dmc;
+       int nocopy2[144];
+       /* struct darwin_ucontext with some padding */
+       struct darwin__ucontext {
+               darwin_siginfo_t si;
+               struct darwin_ucontext uctx;
+       } duc;
+       int nocopy3[56];
+};
+
+#endif /* !_DARWIN_MACHDEP_H_ */
diff -r f39620c7f00b -r d59859e5c1e0 sys/arch/powerpc/powerpc/darwin_machdep.c
--- a/sys/arch/powerpc/powerpc/darwin_machdep.c Tue Nov 26 23:48:44 2002 +0000
+++ b/sys/arch/powerpc/powerpc/darwin_machdep.c Tue Nov 26 23:54:09 2002 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: darwin_machdep.c,v 1.1 2002/11/25 22:25:12 manu Exp $ */
+/*     $NetBSD: darwin_machdep.c,v 1.2 2002/11/26 23:54:10 manu Exp $ */
 
 /*-
  * Copyright (c) 2002 The NetBSD Foundation, Inc.
@@ -37,7 +37,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: darwin_machdep.c,v 1.1 2002/11/25 22:25:12 manu Exp $");
+__KERNEL_RCSID(0, "$NetBSD: darwin_machdep.c,v 1.2 2002/11/26 23:54:10 manu Exp $");
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -50,28 +50,191 @@
 #include <compat/darwin/darwin_signal.h>
 #include <compat/darwin/darwin_syscallargs.h>
 
+#include <arch/powerpc/include/psl.h>
+#include <arch/powerpc/include/darwin_machdep.h>
+
+/*
+ * Send a signal to a Darwin process.
+ */
 void
 darwin_sendsig(sig, mask, code)
        int sig;
-       sigset_t *mask; 
+       sigset_t *mask;
        u_long code;
 {
-       printf("darwin_sendsig: sig = %d\n", sig);
+       struct proc *p = curproc;
+       struct sigacts *ps = p->p_sigacts;
+       struct trapframe *tf;
+       struct darwin_sigframe *sfp, sf;
+       int onstack;
+       size_t stack_size;
+       sig_t catcher = SIGACTION(p, sig).sa_handler;
+       int error;
+
+       tf = trapframe(p);
+
+       /* Use an alternate signal stack? */
+       onstack =
+           (p->p_sigctx.ps_sigstk.ss_flags & (SS_DISABLE | SS_ONSTACK)) == 0 &&
+           (SIGACTION(p, sig).sa_flags & SA_ONSTACK) != 0;
+
+       /* Set the new stack pointer sfp */
+       if (onstack) {
+               sfp = (struct darwin_sigframe *)
+                   ((caddr_t)p->p_sigctx.ps_sigstk.ss_sp +
+                   p->p_sigctx.ps_sigstk.ss_size);
+               stack_size = p->p_sigctx.ps_sigstk.ss_size;
+       } else {
+               sfp = (struct darwin_sigframe *)tf->fixreg[1];
+               stack_size = 0;
+       }
+       /* 16 bytes alignement */
+       sfp = (struct darwin_sigframe *)((u_long)(sfp - 1) & ~0xfUL);
+
+       /* Prepare the signal frame */
+       bzero(&sf, sizeof(sf));
+       sf.dmc.es.dar = tf->dar;
+       sf.dmc.es.dsisr = tf->dsisr;
+       sf.dmc.es.exception = tf->exc;
+
+       sf.dmc.ss.srr0 = tf->srr0;
+       sf.dmc.ss.srr1 = tf->srr1;
+       memcpy(&sf.dmc.ss.gpreg[0], &tf->fixreg[0], sizeof(sf.dmc.ss.gpreg));
+       sf.dmc.ss.cr = tf->cr;
+       sf.dmc.ss.xer = tf->xer;
+       sf.dmc.ss.lr = tf->lr;
+       sf.dmc.ss.ctr = tf->ctr;
+       sf.dmc.ss.mq = 0; /* XXX */
+       sf.dmc.ss.vrsave = tf->vrsave;
+
+       /* XXX What should we do with th FP regs? */
+
+       /* 
+        * Darwin only supports 32 signals. 
+        * Unsupported signals are mapped to 0 
+        */
+       if (sig >= 32) {
+               DPRINTF(("unsupported signal for darwin: %d\n", sig));
+               sig = 0;
+       }
+
+       sf.duc.si.si_signo = sig;
+       sf.duc.uctx.uc_onstack = onstack;
+       native_sigset_to_sigset13(mask, &sf.duc.uctx.uc_sigmask);
+       sf.duc.uctx.uc_stack.ss_sp = (char *)sfp;
+       sf.duc.uctx.uc_stack.ss_size = stack_size;
+       if (onstack)
+               sf.duc.uctx.uc_stack.ss_flags |= SS_ONSTACK;
+       sf.duc.uctx.uc_link = NULL;
+       sf.duc.uctx.uc_mcsize = sizeof(sf.dmc);
+       sf.duc.uctx.uc_mcontext = (struct darwin_mcontext *)&sfp->dmc;
+
+       /* Copyout mcontext */
+       if ((error = copyout(&sf.dmc, &sfp->dmc, sizeof(sf.dmc))) != 0) {
+               sigexit(p, SIGILL);
+               /* NOTREACHED */
+       }
+
+       /* Copyout ucontext */
+       if ((error = copyout(&sf.duc, &sfp->duc, sizeof(sf.duc))) != 0) {
+               sigexit(p, SIGILL);
+               /* NOTREACHED */
+       }
+
+       /* Darwin only supports libc based trampoline */
+       if (ps->sa_sigdesc[sig].sd_vers != 1) {
+               sigexit(p, SIGILL);
+               /* NOTREACHED */
+       }
+
+       /* Prepare registers */
+       tf->fixreg[1] = (u_long)sfp;
+       tf->fixreg[3] = (u_long)catcher;
+       tf->fixreg[4] = 1; /* 1 => without siginfo, 2 => with siginfo */
+       tf->fixreg[5] = (u_long)code;
+       tf->fixreg[6] = (u_long)&sfp->duc.si;
+       tf->fixreg[7] = (u_long)&sfp->duc.uctx;
+       tf->lr = (u_long)tf->srr0;
+       tf->srr0 = (u_long)ps->sa_sigdesc[sig].sd_tramp;
+       tf->srr1 = (PSL_EE | PSL_ME | PSL_IR | PSL_DR | PSL_PR);
+
+       /* Remember that we're now on the signal stack. */
+       if (onstack)
+               p->p_sigctx.ps_sigstk.ss_flags |= SS_ONSTACK;
+
        return;
 }
 
+/*
+ * The signal trampoline calls this system call 
+ * to get the process state restored like it was
+ * before the signal delivery.
+ */
 int
 darwin_sys_sigreturn(p, v, retval)
        struct proc *p;
        void *v;
        register_t *retval;
 {
-
        struct darwin_sys_sigreturn_args /* {
                syscallarg(struct darwin_ucontext *) uctx;
        } */ *uap = v;
+       struct darwin_ucontext uctx;
+       struct darwin_mcontext mctx;
+       struct trapframe *tf;
+       sigset_t mask;
+       size_t mcsize;
+       int error;
 
-       printf("darwin_sys_sigreturn: uctx = %p\n", SCARG(uap, uctx));
+       /*
+        * The trampoline hands us the context.
+        * It is unsafe to keep track of it ourselves, in the event that a
+        * program jumps out of a signal hander.
+        */
+       if ((error = copyin(SCARG(uap, uctx), &uctx, sizeof(uctx))) != 0)
+               return (error);
+
+       /* Check mcontext size, as it is handed by used code */
+       mcsize = uctx.uc_mcsize;
+       if (mcsize > sizeof(mctx))
+               mcsize = sizeof(mctx);
+
+       if ((error = copyin(uctx.uc_mcontext, &mctx, mcsize)) != 0)
+               return (error);
 
-       return 0;
+       /* Check for security abuse */
+       tf = trapframe(p);
+       mctx.ss.srr1 &= ~(PSL_POW | PSL_ILE | PSL_IP | PSL_LE | PSL_RI);
+       mctx.ss.srr1 |= (PSL_PR | PSL_ME | PSL_IR | PSL_DR | PSL_EE); 
+       if ((mctx.ss.srr1 & PSL_USERSTATIC) != (tf->srr1 & PSL_USERSTATIC)) {
+               DPRINTF(("uctx.ss.srr1 = 0x%08x, rf->srr1 = 0x%08x\n",
+                   mctx.ss.srr1, tf->srr1));
+               return (EINVAL);
+       }
+
+       /* Restore the context */
+       tf->dar = mctx.es.dar;
+       tf->dsisr = mctx.es.dsisr;
+       tf->exc = mctx.es.exception;
+
+       tf->srr0 = mctx.ss.srr0;
+       tf->srr1 = mctx.ss.srr1;
+       memcpy(&tf->fixreg[0], &mctx.ss.gpreg[0], sizeof(mctx.ss.gpreg));



Home | Main Index | Thread Index | Old Index