Source-Changes-HG archive

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

[src/trunk]: src/sys/arch/sparc64 use sunos32_machdep.c on 64 bit kernels.



details:   https://anonhg.NetBSD.org/src/rev/55b791a97a39
branches:  trunk
changeset: 503401:55b791a97a39
user:      mrg <mrg%NetBSD.org@localhost>
date:      Mon Feb 05 12:47:47 2001 +0000

description:
use sunos32_machdep.c on 64 bit kernels.

diffstat:

 sys/arch/sparc64/conf/files.sparc64        |    5 +-
 sys/arch/sparc64/sparc64/sunos32_machdep.c |  287 +++++++++++++++++++++++++++++
 2 files changed, 290 insertions(+), 2 deletions(-)

diffs (truncated from 311 to 300 lines):

diff -r dfd48b6333ef -r 55b791a97a39 sys/arch/sparc64/conf/files.sparc64
--- a/sys/arch/sparc64/conf/files.sparc64       Mon Feb 05 12:46:19 2001 +0000
+++ b/sys/arch/sparc64/conf/files.sparc64       Mon Feb 05 12:47:47 2001 +0000
@@ -1,4 +1,4 @@
-#      $NetBSD: files.sparc64,v 1.43 2001/02/02 07:32:45 mrg Exp $
+#      $NetBSD: files.sparc64,v 1.44 2001/02/05 12:47:47 mrg Exp $
 
 # @(#)files.sparc64    8.1 (Berkeley) 7/19/93
 # sparc64-specific configuration info
@@ -249,8 +249,9 @@
 # SunOS Binary Compatibility (COMPAT_SUNOS), 32-bit & 64-bit kernel
 # (64-bit also depends on COMPAT_NETBSD32)
 include "compat/sunos/files.sunos"
+file   arch/sparc64/sparc64/sunos_machdep.c    compat_sunos & !compat_netbsd32
 include "compat/sunos32/files.sunos32"
-file   arch/sparc64/sparc64/sunos_machdep.c    compat_sunos
+file   arch/sparc64/sparc64/sunos32_machdep.c  compat_sunos & compat_netbsd32
 
 # Miscellaneous
 file   netns/ns_cksum.c                ns
diff -r dfd48b6333ef -r 55b791a97a39 sys/arch/sparc64/sparc64/sunos32_machdep.c
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/sys/arch/sparc64/sparc64/sunos32_machdep.c        Mon Feb 05 12:47:47 2001 +0000
@@ -0,0 +1,287 @@
+/*     $NetBSD: sunos32_machdep.c,v 1.1 2001/02/05 12:47:47 mrg Exp $  */
+/* from: NetBSD: sunos_machdep.c,v 1.14 2001/01/29 01:37:56 mrg Exp    */
+
+/*
+ * Copyright (c) 1995, 2001 Matthew R. Green
+ * All rights reserved.
+ *
+ * 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. The name of the author may not be used to endorse or promote products
+ *    derived from this software without 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.
+ */
+
+#include "opt_ddb.h"
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/proc.h>
+#include <sys/namei.h>
+#include <sys/user.h>
+#include <sys/filedesc.h>
+#include <sys/ioctl.h>
+#include <sys/mount.h>
+#include <sys/kernel.h>
+#include <sys/signal.h>
+#include <sys/signalvar.h>
+#include <sys/malloc.h>
+
+#include <sys/syscallargs.h>
+#include <compat/sunos/sunos.h>
+#include <compat/sunos/sunos_syscallargs.h>
+#include <compat/netbsd32/netbsd32.h>
+#include <compat/sunos32/sunos32.h>
+#include <compat/sunos32/sunos32_syscallargs.h>
+
+#include <machine/frame.h>
+#include <machine/cpu.h>
+
+#ifdef DEBUG
+#include <sparc64/sparc64/sigdebug.h>
+#endif
+
+struct sunos32_sigcontext {
+       u_int32_t       sc_onstack;             /* sigstack state to restore */
+       u_int32_t       sc_mask;                /* signal mask to restore (old style) */
+       /* begin machine dependent portion */
+       u_int32_t       sc_sp;                  /* %sp to restore */
+       u_int32_t       sc_pc;                  /* pc to restore */
+       u_int32_t       sc_npc;                 /* npc to restore */
+       u_int32_t       sc_psr;                 /* pstate to restore */
+       u_int32_t       sc_g1;                  /* %g1 to restore */
+       u_int32_t       sc_o0;                  /* %o0 to restore */
+};
+
+struct sunos32_sigframe {
+       u_int32_t       sf_signo;               /* signal number */
+       u_int32_t       sf_code;                /* code */
+       u_int32_t       sf_scp;                 /* SunOS user addr of sigcontext */
+       u_int32_t       sf_addr;                /* SunOS compat, always 0 for now */
+       struct  sunos32_sigcontext sf_sc;       /* actual sigcontext */
+};
+
+void
+sunos32_sendsig(catcher, sig, mask, code)
+       sig_t catcher;
+       int sig;
+       sigset_t *mask;
+       u_long code;
+{
+       struct proc *p = curproc;       /* XXX */
+       struct sunos32_sigframe *fp;
+       struct trapframe64 *tf;
+       struct rwindow32 *oldsp, *newsp;
+       struct sunos32_sigframe sf;
+       struct sunos32_sigcontext *scp;
+       u_int32_t addr, oldsp32;
+       int onstack; 
+
+       tf = p->p_md.md_tf;
+       /* Need to attempt to zero extend this 32-bit pointer */
+       oldsp = (struct rwindow32 *)(u_long)(u_int)tf->tf_out[6];
+       oldsp32 = (u_int32_t)(u_long)oldsp;
+
+       /*
+        * Compute new user stack addresses, subtract off
+        * one signal frame, and align.
+        */
+       onstack =
+           (p->p_sigctx.ps_sigstk.ss_flags & (SS_DISABLE | SS_ONSTACK)) == 0 &&
+           (SIGACTION(p, sig).sa_flags & SA_ONSTACK) != 0;
+
+       if (onstack)
+               fp = (struct sunos32_sigframe *)
+                    ((caddr_t)p->p_sigctx.ps_sigstk.ss_sp + p->p_sigctx.ps_sigstk.ss_size);
+       else
+               fp = (struct sunos32_sigframe *)oldsp;
+
+       fp = (struct sunos32_sigframe *)((u_long)(fp - 1) & ~7);
+
+#ifdef DEBUG
+       sigpid = p->p_pid;
+       if (((sigdebug & SDB_KSTACK) && p->p_pid == sigpid) || 1) {
+               printf("sunos32_sendsig: %s[%d] sig %d newusp %p scp %p oldsp %p\n",
+                   p->p_comm, p->p_pid, sig, fp, &fp->sf_sc, oldsp);
+#ifdef DDB
+               if (sigdebug & SDB_DDB) Debugger();
+#endif
+       }
+#endif
+       /*
+        * Now set up the signal frame.  We build it in kernel space
+        * and then copy it out.  We probably ought to just build it
+        * directly in user space....
+        */
+       sf.sf_signo = sig;
+       sf.sf_code = (u_int32_t)code;
+       scp = &fp->sf_sc;
+       if ((u_long)scp >= 0x100000000)
+               printf("sunos32_sendsig: sf_scp overflow %p > 0x100000000\n", scp);
+       sf.sf_scp = (u_int32_t)(u_long)scp;
+       sf.sf_addr = 0;                 /* XXX */
+
+       /*
+        * Build the signal context to be used by sigreturn.
+        */
+       sf.sf_sc.sc_onstack = p->p_sigctx.ps_sigstk.ss_flags & SS_ONSTACK;
+       native_sigset_to_sigset13(mask, &sf.sf_sc.sc_mask);
+       sf.sf_sc.sc_sp = (u_int)(u_long)oldsp;
+       sf.sf_sc.sc_pc = tf->tf_pc;
+       sf.sf_sc.sc_npc = tf->tf_npc;
+       sf.sf_sc.sc_psr = TSTATECCR_TO_PSR(tf->tf_tstate); /* XXX */
+       sf.sf_sc.sc_g1 = tf->tf_global[1];
+       sf.sf_sc.sc_o0 = tf->tf_out[0];
+
+       /*
+        * Put the stack in a consistent state before we whack away
+        * at it.  Note that write_user_windows may just dump the
+        * registers into the pcb; we need them in the process's memory.
+        * We also need to make sure that when we start the signal handler,
+        * its %i6 (%fp), which is loaded from the newly allocated stack area,
+        * joins seamlessly with the frame it was in when the signal occurred,
+        * so that the debugger and _longjmp code can back up through it.
+        */
+       newsp = (struct rwindow32 *)((long)fp - sizeof(struct rwindow32));
+       write_user_windows();
+#ifdef DEBUG
+       if ((sigdebug & SDB_KSTACK) || 1)
+           printf("sunos32_sendsig: saving sf to %p, setting stack pointer %p to %p\n",
+                  fp, &(((struct rwindow32 *)newsp)->rw_in[6]), oldsp);
+#endif
+       if (rwindow_save(p) || copyout((caddr_t)&sf, (caddr_t)fp, sizeof sf) || 
+           copyout((caddr_t)&oldsp32, &(((struct rwindow32 *)newsp)->rw_in[6]), sizeof oldsp32)) {
+               /*
+                * Process has trashed its stack; give it an illegal
+                * instruction to halt it in its tracks.
+                */
+#ifdef DEBUG
+               if ((sigdebug & SDB_KSTACK) && p->p_pid == sigpid)
+                       printf("sunos32_sendsig: window save or copyout error\n");
+               printf("sunos32_sendsig: stack was trashed trying to send sig %d, sending SIGILL\n", sig);
+#ifdef DDB
+               if (sigdebug & SDB_DDB) Debugger();
+#endif
+#endif
+               sigexit(p, SIGILL);
+               /* NOTREACHED */
+       }
+
+#ifdef DEBUG
+       if ((sigdebug & SDB_FOLLOW) || 1) {
+               printf("sunos32_sendsig: %s[%d] sig %d scp %p\n",
+                      p->p_comm, p->p_pid, sig, &fp->sf_sc);
+       }
+#endif
+       /*
+        * Arrange to continue execution at the code copied out in exec().
+        * It needs the function to call in %g1, and a new stack pointer.
+        */
+       addr = (u_int32_t)(u_long)catcher;      /* user does his own trampolining */
+       tf->tf_pc = addr;
+       tf->tf_npc = addr + 4;
+       tf->tf_out[6] = (u_int64_t)(u_int)(u_long)newsp;
+#ifdef DEBUG
+       if (((sigdebug & SDB_KSTACK) && p->p_pid == sigpid) || 1) {
+               printf("sunos32_sendsig: about to return to catcher %p thru %p\n", 
+                      catcher, (void *)(u_long)addr);
+#ifdef DDB
+               if (sigdebug & SDB_DDB) Debugger();
+#endif
+       }
+#endif
+}
+
+int
+sunos32_sys_sigreturn(p, v, retval)
+        register struct proc *p;
+       void *v;
+       register_t *retval;
+{
+       struct sunos32_sys_sigreturn_args /* 
+               syscallarg(netbsd32_sigcontextp_t) sigcntxp;
+       } */ *uap = v;
+       struct sunos32_sigcontext sc, *scp;
+       sigset_t mask;
+       struct trapframe64 *tf;
+
+       /* First ensure consistent stack state (see sendsig). */
+       write_user_windows();
+       if (rwindow_save(p))
+               sigexit(p, SIGILL);
+#ifdef DEBUG
+       if (sigdebug & SDB_FOLLOW) {
+               printf("sunos32_sigreturn: %s[%d], sigcntxp %p\n",
+                   p->p_comm, p->p_pid, (void *)(u_long)SCARG(uap, sigcntxp));
+#ifdef DDB
+               if (sigdebug & SDB_DDB) Debugger();
+#endif
+       }
+#endif
+
+       scp = (struct sunos32_sigcontext *)(u_long)SCARG(uap, sigcntxp);
+       if ((vaddr_t)scp & 3 || (copyin((caddr_t)scp, &sc, sizeof sc) != 0))
+               return (EFAULT);
+       scp = &sc;
+
+       tf = p->p_md.md_tf;
+       /*
+        * Only the icc bits in the psr are used, so it need not be
+        * verified.  pc and npc must be multiples of 4.  This is all
+        * that is required; if it holds, just do it.
+        */
+       if (((scp->sc_pc | scp->sc_npc) & 3) != 0 || scp->sc_pc == 0 || scp->sc_npc == 0)
+       {
+#ifdef DEBUG
+               printf("sunos32_sigreturn: pc %x or npc %x invalid\n", scp->sc_pc, scp->sc_npc);
+#ifdef DDB
+               Debugger();
+#endif
+#endif
+               return (EINVAL);
+       }
+       /* take only psr ICC field */
+       tf->tf_tstate = (int64_t)(tf->tf_tstate & ~TSTATE_CCR) | PSRCC_TO_TSTATE(scp->sc_psr);
+       tf->tf_pc = scp->sc_pc;
+       tf->tf_npc = scp->sc_npc;
+       tf->tf_global[1] = scp->sc_g1;
+       tf->tf_out[0] = scp->sc_o0;
+       tf->tf_out[6] = scp->sc_sp;
+#ifdef DEBUG
+       if (sigdebug & SDB_FOLLOW) {
+               printf("sunos32_sigreturn: return trapframe pc=%p sp=%p tstate=%llx\n",
+                      (void *)(u_long)tf->tf_pc, (void *)(u_long)tf->tf_out[6], (unsigned long long)tf->tf_tstate);
+#ifdef DDB
+               if (sigdebug & SDB_DDB) Debugger();
+#endif
+       }
+#endif
+



Home | Main Index | Thread Index | Old Index