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