BSD 4_4_Lite2 release
[unix-history] / usr / src / sys / hp300 / hp300 / trap.c
index d600a4e..f18333b 100644 (file)
@@ -1,46 +1,72 @@
 /*
  * Copyright (c) 1988 University of Utah.
 /*
  * Copyright (c) 1988 University of Utah.
- * Copyright (c) 1982, 1986, 1990 The Regents of the University of California.
- * All rights reserved.
+ * Copyright (c) 1982, 1986, 1990, 1993
+ *     The Regents of the University of California.  All rights reserved.
  *
  * This code is derived from software contributed to Berkeley by
  * the Systems Programming Group of the University of Utah Computer
  * Science Department.
  *
  *
  * This code is derived from software contributed to Berkeley by
  * the Systems Programming Group of the University of Utah Computer
  * Science Department.
  *
- * %sccs.include.redist.c%
+ * 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.
  *
  *
- * from: Utah $Hdr: trap.c 1.28 89/09/25$
+ * 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.
  *
  *
- *     @(#)trap.c      7.4 (Berkeley) %G%
+ * from: Utah $Hdr: trap.c 1.37 92/12/20$
+ *
+ *     @(#)trap.c      8.7 (Berkeley) 2/19/95
  */
 
  */
 
-#include "cpu.h"
-#include "psl.h"
-#include "reg.h"
-#include "pte.h"
-#include "mtpr.h"
-
-#include "param.h"
-#include "systm.h"
-#include "user.h"
-#include "proc.h"
-#include "seg.h"
-#include "trap.h"
-#include "acct.h"
-#include "kernel.h"
-#include "vm.h"
-#include "cmap.h"
-#include "syslog.h"
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/proc.h>
+#include <sys/acct.h>
+#include <sys/kernel.h>
+#include <sys/signalvar.h>
+#include <sys/resourcevar.h>
+#include <sys/syscall.h>
+#include <sys/syslog.h>
+#include <sys/user.h>
 #ifdef KTRACE
 #ifdef KTRACE
-#include "ktrace.h"
+#include <sys/ktrace.h>
 #endif
 
 #endif
 
+#include <machine/psl.h>
+#include <machine/trap.h>
+#include <machine/cpu.h>
+#include <machine/reg.h>
+#include <machine/mtpr.h>
+
+#include <vm/vm.h>
+#include <vm/pmap.h>
+
 #ifdef HPUXCOMPAT
 #ifdef HPUXCOMPAT
-#include "../hpux/hpux.h"
+#include <hp/hpux/hpux.h>
 #endif
 
 #endif
 
-#define        USER    040             /* user-mode flag added to type */
-
 struct sysent  sysent[];
 int    nsysent;
 
 struct sysent  sysent[];
 int    nsysent;
 
@@ -62,12 +88,126 @@ char       *trap_type[] = {
 };
 #define        TRAP_TYPES      (sizeof trap_type / sizeof trap_type[0])
 
 };
 #define        TRAP_TYPES      (sizeof trap_type / sizeof trap_type[0])
 
+/*
+ * Size of various exception stack frames (minus the standard 8 bytes)
+ */
+short  exframesize[] = {
+       FMT0SIZE,       /* type 0 - normal (68020/030/040) */
+       FMT1SIZE,       /* type 1 - throwaway (68020/030/040) */
+       FMT2SIZE,       /* type 2 - normal 6-word (68020/030/040) */
+       FMT3SIZE,       /* type 3 - FP post-instruction (68040) */
+       -1, -1, -1,     /* type 4-6 - undefined */
+       FMT7SIZE,       /* type 7 - access error (68040) */
+       58,             /* type 8 - bus fault (68010) */
+       FMT9SIZE,       /* type 9 - coprocessor mid-instruction (68020/030) */
+       FMTASIZE,       /* type A - short bus fault (68020/030) */
+       FMTBSIZE,       /* type B - long bus fault (68020/030) */
+       -1, -1, -1, -1  /* type C-F - undefined */
+};
+
+#ifdef HP380
+#define KDFAULT(c)     (mmutype == MMU_68040 ? \
+                           ((c) & SSW4_TMMASK) == SSW4_TMKD : \
+                           ((c) & (SSW_DF|FC_SUPERD)) == (SSW_DF|FC_SUPERD))
+#define WRFAULT(c)     (mmutype == MMU_68040 ? \
+                           ((c) & SSW4_RW) == 0 : \
+                           ((c) & (SSW_DF|SSW_RW)) == SSW_DF)
+#else
+#define KDFAULT(c)     (((c) & (SSW_DF|SSW_FCMASK)) == (SSW_DF|FC_SUPERD))
+#define WRFAULT(c)     (((c) & (SSW_DF|SSW_RW)) == SSW_DF)
+#endif
+
 #ifdef DEBUG
 int mmudebug = 0;
 #ifdef DEBUG
 int mmudebug = 0;
+int mmupid = -1;
+#define MDB_FOLLOW     1
+#define MDB_WBFOLLOW   2
+#define MDB_WBFAILED   4
+#define MDB_ISPID(p)   (p) == mmupid
+#endif
+
+/*
+ * trap and syscall both need the following work done before returning
+ * to user mode.
+ */
+static inline void
+userret(p, fp, oticks, faultaddr, fromtrap)
+       register struct proc *p;
+       register struct frame *fp;
+       u_quad_t oticks;
+       u_int faultaddr;
+       int fromtrap;
+{
+       int sig, s;
+#ifdef HP380
+       int beenhere = 0;
+
+again:
+#endif
+       /* take pending signals */
+       while ((sig = CURSIG(p)) != 0)
+               postsig(sig);
+       p->p_priority = p->p_usrpri;
+       if (want_resched) {
+               /*
+                * Since we are curproc, clock will normally just change
+                * our priority without moving us from one queue to another
+                * (since the running process is not on a queue.)
+                * If that happened after we put ourselves on the run queue
+                * but before we mi_switch()'ed, we might not be on the queue
+                * indicated by our priority.
+                */
+               s = splstatclock();
+               setrunqueue(p);
+               p->p_stats->p_ru.ru_nivcsw++;
+               mi_switch();
+               splx(s);
+               while ((sig = CURSIG(p)) != 0)
+                       postsig(sig);
+       }
+
+       /*
+        * If profiling, charge system time to the trapped pc.
+        */
+       if (p->p_flag & P_PROFIL) {
+               extern int psratio;
+
+               addupc_task(p, fp->f_pc,
+                           (int)(p->p_sticks - oticks) * psratio);
+       }
+#ifdef HP380
+       /*
+        * Deal with user mode writebacks (from trap, or from sigreturn).
+        * If any writeback fails, go back and attempt signal delivery.
+        * unless we have already been here and attempted the writeback
+        * (e.g. bad address with user ignoring SIGSEGV).  In that case
+        * we just return to the user without sucessfully completing
+        * the writebacks.  Maybe we should just drop the sucker?
+        */
+       if (mmutype == MMU_68040 && fp->f_format == FMT7) {
+               if (beenhere) {
+#ifdef DEBUG
+                       if (mmudebug & MDB_WBFAILED)
+                               printf(fromtrap ?
+               "pid %d(%s): writeback aborted, pc=%x, fa=%x\n" :
+               "pid %d(%s): writeback aborted in sigreturn, pc=%x\n",
+                                   p->p_pid, p->p_comm, fp->f_pc, faultaddr);
+#endif
+               } else if (sig = writeback(fp, fromtrap)) {
+                       beenhere = 1;
+                       oticks = p->p_sticks;
+                       trapsignal(p, sig, faultaddr);
+                       goto again;
+               }
+       }
 #endif
 #endif
+       curpriority = p->p_priority;
+}
 
 /*
 
 /*
- * Called from the trap handler when a processor trap occurs.
+ * Trap is called from locore to handle most types of processor traps,
+ * including events such as simulated software interrupts/AST's.
+ * System calls are broken out for efficiency.
  */
 /*ARGSUSED*/
 trap(type, code, v, frame)
  */
 /*ARGSUSED*/
 trap(type, code, v, frame)
@@ -76,35 +216,33 @@ trap(type, code, v, frame)
        register unsigned v;
        struct frame frame;
 {
        register unsigned v;
        struct frame frame;
 {
+       extern char fswintr[];
+       register struct proc *p;
        register int i;
        register int i;
-       unsigned ucode = 0;
-       register struct proc *p = u.u_procp;
-       struct timeval syst;
-       unsigned ncode;
+       u_int ucode;
+       u_quad_t sticks;
 
        cnt.v_trap++;
 
        cnt.v_trap++;
-       syst = u.u_ru.ru_stime;
+       p = curproc;
+       ucode = 0;
        if (USERMODE(frame.f_sr)) {
        if (USERMODE(frame.f_sr)) {
-               type |= USER;
-               u.u_ar0 = frame.f_regs;
+               type |= T_USER;
+               sticks = p->p_sticks;
+               p->p_md.md_regs = frame.f_regs;
        }
        switch (type) {
 
        default:
 dopanic:
        }
        switch (type) {
 
        default:
 dopanic:
-#ifdef KGDB
-               if (!panicstr && kgdb_trap(type, code, v, &frame))
-                       return;
-#endif
                printf("trap type %d, code = %x, v = %x\n", type, code, v);
                printf("trap type %d, code = %x, v = %x\n", type, code, v);
-               regdump(frame.f_regs, 128);
-               type &= ~USER;
+               regdump(&frame, 128);
+               type &= ~T_USER;
                if ((unsigned)type < TRAP_TYPES)
                        panic(trap_type[type]);
                panic("trap");
 
        case T_BUSERR:          /* kernel bus error */
                if ((unsigned)type < TRAP_TYPES)
                        panic(trap_type[type]);
                panic("trap");
 
        case T_BUSERR:          /* kernel bus error */
-               if (!u.u_pcb.pcb_onfault)
+               if (!p->p_addr->u_pcb.pcb_onfault)
                        goto dopanic;
                /*
                 * If we have arranged to catch this fault in any of the
                        goto dopanic;
                /*
                 * If we have arranged to catch this fault in any of the
@@ -113,27 +251,45 @@ dopanic:
                 * that it may need to clean up stack frame.
                 */
 copyfault:
                 * that it may need to clean up stack frame.
                 */
 copyfault:
-               frame.f_pc = (int) u.u_pcb.pcb_onfault;
-               frame.f_stackadj = -1;
+               frame.f_stackadj = exframesize[frame.f_format];
+               frame.f_format = frame.f_vector = 0;
+               frame.f_pc = (int) p->p_addr->u_pcb.pcb_onfault;
                return;
 
                return;
 
-       case T_BUSERR+USER:     /* bus error */
-       case T_ADDRERR+USER:    /* address error */
+       case T_BUSERR|T_USER:   /* bus error */
+       case T_ADDRERR|T_USER:  /* address error */
+               ucode = v;
                i = SIGBUS;
                break;
 
                i = SIGBUS;
                break;
 
+#ifdef HP380
+       case T_ADDRERR:
+               /*
+                * Yow!  Looks like we get a kernel exception if the PC
+                * in the RTE frame is odd on a 68040 (not on a 68030).
+                * It comes through as a user exception for access faults
+                * (T_MMUFLT).
+                */
+               if (*(short *)frame.f_pc != 0x4e73)
+                       goto dopanic;
+               /* fall through */
+#endif
+
 #ifdef FPCOPROC
        case T_COPERR:          /* kernel coprocessor violation */
 #endif
 #ifdef FPCOPROC
        case T_COPERR:          /* kernel coprocessor violation */
 #endif
-       case T_FMTERR:          /* kernel format error */
-       /*
-        * The user has most likely trashed the RTE or FP state info
-        * in the stack frame of a signal handler.
-        */
-               type |= USER;
-               printf("pid %d: kernel %s exception\n", u.u_procp->p_pid,
-                      type==T_COPERR ? "coprocessor" : "format");
-               u.u_signal[SIGILL] = SIG_DFL;
+       case T_FMTERR|T_USER:   /* do all RTE errors come in as T_USER? */
+       case T_FMTERR:          /* ...just in case... */
+               /*
+                * The user has most likely trashed the RTE or FP state info
+                * in the stack frame of a signal handler.
+                */
+               type |= T_USER;
+               printf("pid %d: kernel %s exception\n", p->p_pid,
+                      (type==T_COPERR|T_USER) ? "coprocessor" :
+                      (type==T_ADDRERR|T_USER) ? "RTE address" :
+                      "RTE format");
+               p->p_sigacts->ps_sigact[SIGILL] = SIG_DFL;
                i = sigmask(SIGILL);
                p->p_sigignore &= ~i;
                p->p_sigcatch &= ~i;
                i = sigmask(SIGILL);
                p->p_sigignore &= ~i;
                p->p_sigcatch &= ~i;
@@ -143,13 +299,13 @@ copyfault:
                break;
 
 #ifdef FPCOPROC
                break;
 
 #ifdef FPCOPROC
-       case T_COPERR+USER:     /* user coprocessor violation */
+       case T_COPERR|T_USER:   /* user coprocessor violation */
        /* What is a proper response here? */
                ucode = 0;
                i = SIGFPE;
                break;
 
        /* What is a proper response here? */
                ucode = 0;
                i = SIGFPE;
                break;
 
-       case T_FPERR+USER:              /* 68881 exceptions */
+       case T_FPERR|T_USER:    /* 68881 exceptions */
        /*
         * We pass along the 68881 status register which locore stashed
         * in code for us.  Note that there is a possibility that the
        /*
         * We pass along the 68881 status register which locore stashed
         * in code for us.  Note that there is a possibility that the
@@ -164,18 +320,31 @@ copyfault:
                break;
 #endif
 
                break;
 #endif
 
-       case T_ILLINST+USER:    /* illegal instruction fault */
+#ifdef HP380
+       case T_FPEMULI|T_USER:  /* unimplemented FP instuction */
+       case T_FPEMULD|T_USER:  /* unimplemented FP data type */
+               /* XXX need to FSAVE */
+               printf("pid %d(%s): unimplemented FP %s at %x (EA %x)\n",
+                      p->p_pid, p->p_comm,
+                      frame.f_format == 2 ? "instruction" : "data type",
+                      frame.f_pc, frame.f_fmt2.f_iaddr);
+               /* XXX need to FRESTORE */
+               i = SIGFPE;
+               break;
+#endif
+
+       case T_ILLINST|T_USER:  /* illegal instruction fault */
 #ifdef HPUXCOMPAT
 #ifdef HPUXCOMPAT
-               if (u.u_procp->p_flag & SHPUX) {
+               if (p->p_md.md_flags & MDP_HPUX) {
                        ucode = HPUX_ILL_ILLINST_TRAP;
                        i = SIGILL;
                        break;
                }
                /* fall through */
 #endif
                        ucode = HPUX_ILL_ILLINST_TRAP;
                        i = SIGILL;
                        break;
                }
                /* fall through */
 #endif
-       case T_PRIVINST+USER:   /* privileged instruction fault */
+       case T_PRIVINST|T_USER: /* privileged instruction fault */
 #ifdef HPUXCOMPAT
 #ifdef HPUXCOMPAT
-               if (u.u_procp->p_flag & SHPUX)
+               if (p->p_md.md_flags & MDP_HPUX)
                        ucode = HPUX_ILL_PRIV_TRAP;
                else
 #endif
                        ucode = HPUX_ILL_PRIV_TRAP;
                else
 #endif
@@ -183,9 +352,9 @@ copyfault:
                i = SIGILL;
                break;
 
                i = SIGILL;
                break;
 
-       case T_ZERODIV+USER:    /* Divide by zero */
+       case T_ZERODIV|T_USER:  /* Divide by zero */
 #ifdef HPUXCOMPAT
 #ifdef HPUXCOMPAT
-               if (u.u_procp->p_flag & SHPUX)
+               if (p->p_md.md_flags & MDP_HPUX)
                        ucode = HPUX_FPE_INTDIV_TRAP;
                else
 #endif
                        ucode = HPUX_FPE_INTDIV_TRAP;
                else
 #endif
@@ -193,9 +362,9 @@ copyfault:
                i = SIGFPE;
                break;
 
                i = SIGFPE;
                break;
 
-       case T_CHKINST+USER:    /* CHK instruction trap */
+       case T_CHKINST|T_USER:  /* CHK instruction trap */
 #ifdef HPUXCOMPAT
 #ifdef HPUXCOMPAT
-               if (u.u_procp->p_flag & SHPUX) {
+               if (p->p_md.md_flags & MDP_HPUX) {
                        /* handled differently under hp-ux */
                        i = SIGILL;
                        ucode = HPUX_ILL_CHK_TRAP;
                        /* handled differently under hp-ux */
                        i = SIGILL;
                        ucode = HPUX_ILL_CHK_TRAP;
@@ -206,9 +375,9 @@ copyfault:
                i = SIGFPE;
                break;
 
                i = SIGFPE;
                break;
 
-       case T_TRAPVINST+USER:  /* TRAPV instruction trap */
+       case T_TRAPVINST|T_USER:        /* TRAPV instruction trap */
 #ifdef HPUXCOMPAT
 #ifdef HPUXCOMPAT
-               if (u.u_procp->p_flag & SHPUX) {
+               if (p->p_md.md_flags & MDP_HPUX) {
                        /* handled differently under hp-ux */
                        i = SIGILL;
                        ucode = HPUX_ILL_TRAPV_TRAP;
                        /* handled differently under hp-ux */
                        i = SIGILL;
                        ucode = HPUX_ILL_TRAPV_TRAP;
@@ -225,44 +394,29 @@ copyfault:
         *      HP-UX uses trap #1 for breakpoints,
         *      HPBSD uses trap #2,
         *      SUN 3.x uses trap #15,
         *      HP-UX uses trap #1 for breakpoints,
         *      HPBSD uses trap #2,
         *      SUN 3.x uses trap #15,
-        *      KGDB uses trap #15 (for kernel breakpoints).
+        *      KGDB uses trap #15 (for kernel breakpoints; handled elsewhere).
         *
         * HPBSD and HP-UX traps both get mapped by locore.s into T_TRACE.
         * SUN 3.x traps get passed through as T_TRAP15 and are not really
         *
         * HPBSD and HP-UX traps both get mapped by locore.s into T_TRACE.
         * SUN 3.x traps get passed through as T_TRAP15 and are not really
-        * supported yet.  KGDB traps are also passed through as T_TRAP15
-        * and are not used yet.
+        * supported yet.
         */
        case T_TRACE:           /* kernel trace trap */
         */
        case T_TRACE:           /* kernel trace trap */
-       case T_TRAP15:          /* SUN (or KGDB) kernel trace trap */
-#ifdef KGDB
-               if (kgdb_trap(type, code, v, &frame))
-                       return;
-#endif
+       case T_TRAP15:          /* SUN trace trap */
                frame.f_sr &= ~PSL_T;
                i = SIGTRAP;
                break;
 
                frame.f_sr &= ~PSL_T;
                i = SIGTRAP;
                break;
 
-       case T_TRACE+USER:      /* user trace trap */
-       case T_TRAP15+USER:     /* SUN user trace trap */
-#ifdef SUNCOMPAT
-               /*
-                * Trap #2 is used to signal a cache flush.
-                * Should we also flush data cache?
-                */
-               if (type == T_TRACE+USER && (p->p_flag & SSUN)) {
-                       ICIA();
-                       goto out;
-               }
-#endif
+       case T_TRACE|T_USER:    /* user trace trap */
+       case T_TRAP15|T_USER:   /* SUN user trace trap */
                frame.f_sr &= ~PSL_T;
                i = SIGTRAP;
                break;
 
                frame.f_sr &= ~PSL_T;
                i = SIGTRAP;
                break;
 
-       case T_AST:             /* system async trap, cannot happen */
+       case T_ASTFLT:          /* system async trap, cannot happen */
                goto dopanic;
 
                goto dopanic;
 
-       case T_AST+USER:        /* user async trap */
-               astoff();
+       case T_ASTFLT|T_USER:   /* user async trap */
+               astpending = 0;
                /*
                 * We check for software interrupts first.  This is because
                 * they are at a higher level than ASTs, and on a VAX would
                /*
                 * We check for software interrupts first.  This is because
                 * they are at a higher level than ASTs, and on a VAX would
@@ -275,7 +429,7 @@ copyfault:
                /* fall into... */
 
        case T_SSIR:            /* software interrupt */
                /* fall into... */
 
        case T_SSIR:            /* software interrupt */
-       case T_SSIR+USER:
+       case T_SSIR|T_USER:
                if (ssir & SIR_NET) {
                        siroff(SIR_NET);
                        cnt.v_soft++;
                if (ssir & SIR_NET) {
                        siroff(SIR_NET);
                        cnt.v_soft++;
@@ -284,390 +438,577 @@ copyfault:
                if (ssir & SIR_CLOCK) {
                        siroff(SIR_CLOCK);
                        cnt.v_soft++;
                if (ssir & SIR_CLOCK) {
                        siroff(SIR_CLOCK);
                        cnt.v_soft++;
-                       softclock((caddr_t)frame.f_pc, (int)frame.f_sr);
+                       softclock();
                }
                /*
                 * If this was not an AST trap, we are all done.
                 */
                }
                /*
                 * If this was not an AST trap, we are all done.
                 */
-               if (type != T_AST+USER) {
+               if (type != (T_ASTFLT|T_USER)) {
                        cnt.v_trap--;
                        return;
                }
                spl0();
                        cnt.v_trap--;
                        return;
                }
                spl0();
-#ifndef PROFTIMER
-               if ((u.u_procp->p_flag&SOWEUPC) && u.u_prof.pr_scale) {
-                       addupc(frame.f_pc, &u.u_prof, 1);
-                       u.u_procp->p_flag &= ~SOWEUPC;
+               if (p->p_flag & P_OWEUPC) {
+                       p->p_flag &= ~P_OWEUPC;
+                       ADDUPROF(p);
                }
                }
-#endif
                goto out;
 
        case T_MMUFLT:          /* kernel mode page fault */
                /*
                goto out;
 
        case T_MMUFLT:          /* kernel mode page fault */
                /*
-                * Could be caused by a page fault in one of the copy to/from
-                * user space routines.  If so, we will have a catch address.
+                * If we were doing profiling ticks or other user mode
+                * stuff from interrupt code, Just Say No.
                 */
                 */
-               if (!u.u_pcb.pcb_onfault)
-                       goto dopanic;
+               if (p->p_addr->u_pcb.pcb_onfault == fswintr)
+                       goto copyfault;
                /* fall into ... */
 
                /* fall into ... */
 
-       case T_MMUFLT+USER:     /* page fault */
-/*
-               printf("trap: T_MMUFLT pid %d, code %x, v %x, pc %x, ps %x\n",
+       case T_MMUFLT|T_USER:   /* page fault */
+           {
+               register vm_offset_t va;
+               register struct vmspace *vm = p->p_vmspace;
+               register vm_map_t map;
+               int rv;
+               vm_prot_t ftype;
+               extern vm_map_t kernel_map;
+
+#ifdef DEBUG
+               if ((mmudebug & MDB_WBFOLLOW) || MDB_ISPID(p->p_pid))
+               printf("trap: T_MMUFLT pid=%d, code=%x, v=%x, pc=%x, sr=%x\n",
                       p->p_pid, code, v, frame.f_pc, frame.f_sr);
                       p->p_pid, code, v, frame.f_pc, frame.f_sr);
-*/
-               if (v >= USRSTACK) {
-                       if (type == T_MMUFLT)
-                               goto copyfault;
-                       i = SIGSEGV;
-                       break;
-               }
-               ncode = code >> 16;
-#if defined(HP330) || defined(HP360) || defined(HP370)
+#endif
                /*
                /*
-                * Crudely map PMMU faults into HP MMU faults.
+                * It is only a kernel address space fault iff:
+                *      1. (type & T_USER) == 0  and
+                *      2. pcb_onfault not set or
+                *      3. pcb_onfault set but supervisor space data fault
+                * The last can occur during an exec() copyin where the
+                * argument space is lazy-allocated.
                 */
                 */
-               if (mmutype != MMU_HP) {
-                       int ocode = ncode;
-                       ncode = 0;
-                       if (ocode & PMMU_WP)
-                               ncode |= MMU_WPF;
-                       else if (ocode & PMMU_INV) {
-                               if ((ocode & PMMU_LVLMASK) == 2)
-                                       ncode |= MMU_PF;
-                               else 
-                                       ncode |= MMU_PTF;
-                       }
-                       /*
-                        * RMW cycle, must load ATC by hand
-                        */
-                       else if ((code & (SSW_DF|SSW_RM)) == (SSW_DF|SSW_RM)) {
+               if (type == T_MMUFLT &&
+                   (!p->p_addr->u_pcb.pcb_onfault || KDFAULT(code)))
+                       map = kernel_map;
+               else
+                       map = &vm->vm_map;
+               if (WRFAULT(code))
+                       ftype = VM_PROT_READ | VM_PROT_WRITE;
+               else
+                       ftype = VM_PROT_READ;
+               va = trunc_page((vm_offset_t)v);
 #ifdef DEBUG
 #ifdef DEBUG
-                               log(LOG_WARNING,
-                                   "RMW fault at %x: MMUSR %x SSW %x\n",
-                                   v, ocode, code & 0xFFFF);
+               if (map == kernel_map && va == 0) {
+                       printf("trap: bad kernel access at %x\n", v);
+                       goto dopanic;
+               }
 #endif
 #endif
-                               ploadw((caddr_t)v);
-                               return;
-                       }
-                       /*
-                        * Fault with no fault bits, should indicate bad
-                        * hardware but we see this on 340s using starbase
-                        * sometimes (faults accessing catseye registers)
-                        */
-                       else {
-                               log(LOG_WARNING,
-                                   "Bad PMMU fault at %x: MMUSR %x SSW %x\n",
-                                   v, ocode, code & 0xFFFF);
-                               return;
+#ifdef HPUXCOMPAT
+               if (ISHPMMADDR(va)) {
+                       vm_offset_t bva;
+
+                       rv = pmap_mapmulti(map->pmap, va);
+                       if (rv != KERN_SUCCESS) {
+                               bva = HPMMBASEADDR(va);
+                               rv = vm_fault(map, bva, ftype, FALSE);
+                               if (rv == KERN_SUCCESS)
+                                       (void) pmap_mapmulti(map->pmap, va);
                        }
                        }
+               } else
+#endif
+               rv = vm_fault(map, va, ftype, FALSE);
 #ifdef DEBUG
 #ifdef DEBUG
-                       if (mmudebug && mmudebug == p->p_pid)
-                               printf("MMU %d: v%x, os%x, ns%x\n",
-                                      p->p_pid, v, ocode, ncode);
+               if (rv && MDB_ISPID(p->p_pid))
+                       printf("vm_fault(%x, %x, %x, 0) -> %x\n",
+                              map, va, ftype, rv);
 #endif
 #endif
+               /*
+                * If this was a stack access we keep track of the maximum
+                * accessed stack size.  Also, if vm_fault gets a protection
+                * failure it is due to accessing the stack region outside
+                * the current limit and we need to reflect that as an access
+                * error.
+                */
+               if ((caddr_t)va >= vm->vm_maxsaddr && map != kernel_map) {
+                       if (rv == KERN_SUCCESS) {
+                               unsigned nss;
+
+                               nss = clrnd(btoc(USRSTACK-(unsigned)va));
+                               if (nss > vm->vm_ssize)
+                                       vm->vm_ssize = nss;
+                       } else if (rv == KERN_PROTECTION_FAILURE)
+                               rv = KERN_INVALID_ADDRESS;
                }
                }
+               if (rv == KERN_SUCCESS) {
+                       if (type == T_MMUFLT) {
+#ifdef HP380
+                               if (mmutype == MMU_68040)
+                                       (void) writeback(&frame, 1);
 #endif
 #endif
-#ifdef DEBUG
-               if ((ncode & (MMU_PTF|MMU_PF|MMU_WPF|MMU_FPE)) == 0) {
-                       printf("T_MMUFLT with no fault bits\n");
+                               return;
+                       }
+                       goto out;
+               }
+               if (type == T_MMUFLT) {
+                       if (p->p_addr->u_pcb.pcb_onfault)
+                               goto copyfault;
+                       printf("vm_fault(%x, %x, %x, 0) -> %x\n",
+                              map, va, ftype, rv);
+                       printf("  type %x, code [mmu,,ssw]: %x\n",
+                              type, code);
                        goto dopanic;
                }
                        goto dopanic;
                }
-#endif
-               if (ncode & MMU_PTF) {
+               ucode = v;
+               i = (rv == KERN_PROTECTION_FAILURE) ? SIGBUS : SIGSEGV;
+               break;
+           }
+       }
+       trapsignal(p, i, ucode);
+       if ((type & T_USER) == 0)
+               return;
+out:
+       userret(p, &frame, sticks, v, 1);
+}
+
+#ifdef HP380
 #ifdef DEBUG
 #ifdef DEBUG
-                       /*
-                        * NOTE: we use a u_int instead of an ste since the
-                        * current compiler generates bogus code for some
-                        * bitfield operations (i.e. attempts to access last
-                        * word of a page as a longword causing fault).
-                        */
-                       extern struct ste *vtoste();
-                       u_int *ste = (u_int *)vtoste(p, v);
-
-                       if (*ste & SG_V) {
-                               if (ncode & MMU_WPF) {
-                                       printf("PTF|WPF...\n");
-                                       if (type == T_MMUFLT)
-                                               goto copyfault;
-                                       i = SIGBUS;
-                                       break;
-                               }
-                               printf("MMU_PTF with sg_v, ste@%x = %x\n",
-                                      ste, *ste);
-                               goto dopanic;
-                       }
-#endif
-#ifdef HPUXCOMPAT
-                       if (ISHPMMADDR(v)) {
-                               extern struct ste *vtoste();
-                               u_int *bste, *nste;
-
-                               bste = (u_int *)vtoste(p, HPMMBASEADDR(v));
-                               nste = (u_int *)vtoste(p, v);
-                               if ((*bste & SG_V) && *nste == SG_NV) {
-                                       *nste = *bste;
-                                       TBIAU();
-                                       return;
-                               }
-                       }
+struct writebackstats {
+       int calls;
+       int cpushes;
+       int move16s;
+       int wb1s, wb2s, wb3s;
+       int wbsize[4];
+} wbstats;
+
+char *f7sz[] = { "longword", "byte", "word", "line" };
+char *f7tt[] = { "normal", "MOVE16", "AFC", "ACK" };
+char *f7tm[] = { "d-push", "u-data", "u-code", "M-data",
+                "M-code", "k-data", "k-code", "RES" };
+char wberrstr[] =
+    "WARNING: pid %d(%s) writeback [%s] failed, pc=%x fa=%x wba=%x wbd=%x\n";
+#endif
+
+writeback(fp, docachepush)
+       struct frame *fp;
+       int docachepush;
+{
+       register struct fmt7 *f = &fp->f_fmt7;
+       register struct proc *p = curproc;
+       int err = 0;
+       u_int fa;
+       caddr_t oonfault = p->p_addr->u_pcb.pcb_onfault;
+
+#ifdef DEBUG
+       if ((mmudebug & MDB_WBFOLLOW) || MDB_ISPID(p->p_pid)) {
+               printf(" pid=%d, fa=%x,", p->p_pid, f->f_fa);
+               dumpssw(f->f_ssw);
+       }
+       wbstats.calls++;
 #endif
 #endif
-               growit:
-                       if (type == T_MMUFLT)
-                               goto copyfault;
-                       if (grow((unsigned)frame.f_regs[SP]) || grow(v))
-                               goto out;
-                       i = SIGSEGV;
-                       break;
-               }
-#ifdef HPUXCOMPAT
-               if (ISHPMMADDR(v)) {
-                       TBIS(v);
-                       v = HPMMBASEADDR(v);
+       /*
+        * Deal with special cases first.
+        */
+       if ((f->f_ssw & SSW4_TMMASK) == SSW4_TMDCP) {
+               /*
+                * Dcache push fault.
+                * Line-align the address and write out the push data to
+                * the indicated physical address.
+                */
+#ifdef DEBUG
+               if ((mmudebug & MDB_WBFOLLOW) || MDB_ISPID(p->p_pid)) {
+                       printf(" pushing %s to PA %x, data %x",
+                              f7sz[(f->f_ssw & SSW4_SZMASK) >> 5],
+                              f->f_fa, f->f_pd0);
+                       if ((f->f_ssw & SSW4_SZMASK) == SSW4_SZLN)
+                               printf("/%x/%x/%x",
+                                      f->f_pd1, f->f_pd2, f->f_pd3);
+                       printf("\n");
                }
                }
+               if (f->f_wb1s & SSW4_WBSV)
+                       panic("writeback: cache push with WB1S valid");
+               wbstats.cpushes++;
 #endif
                /*
 #endif
                /*
-                * NOTE: WPF without PG_V is possible
-                * (e.g. attempt to write shared text which is paged out)
+                * XXX there are security problems if we attempt to do a
+                * cache push after a signal handler has been called.
+                */
+               if (docachepush) {
+                       pmap_enter(kernel_pmap, (vm_offset_t)vmmap,
+                                  trunc_page(f->f_fa), VM_PROT_WRITE, TRUE);
+                       fa = (u_int)&vmmap[(f->f_fa & PGOFSET) & ~0xF];
+                       bcopy((caddr_t)&f->f_pd0, (caddr_t)fa, 16);
+                       DCFL(pmap_extract(kernel_pmap, (vm_offset_t)fa));
+                       pmap_remove(kernel_pmap, (vm_offset_t)vmmap,
+                                   (vm_offset_t)&vmmap[NBPG]);
+               } else
+                       printf("WARNING: pid %d(%s) uid %d: CPUSH not done\n",
+                              p->p_pid, p->p_comm, p->p_ucred->cr_uid);
+       } else if ((f->f_ssw & (SSW4_RW|SSW4_TTMASK)) == SSW4_TTM16) {
+               /*
+                * MOVE16 fault.
+                * Line-align the address and write out the push data to
+                * the indicated virtual address.
                 */
                 */
-               if (ncode & MMU_WPF) {
 #ifdef DEBUG
 #ifdef DEBUG
-                       extern struct ste *vtoste();
-                       u_int *ste = (u_int *)vtoste(p, v);
-
-                       if (!(*ste & SG_V)) {
-                               printf("MMU_WPF without sg_v, ste@%x = %x\n",
-                                      ste, *ste);
-                               goto dopanic;
-                       }
+               if ((mmudebug & MDB_WBFOLLOW) || MDB_ISPID(p->p_pid))
+                       printf(" MOVE16 to VA %x(%x), data %x/%x/%x/%x\n",
+                              f->f_fa, f->f_fa & ~0xF, f->f_pd0, f->f_pd1,
+                              f->f_pd2, f->f_pd3);
+               if (f->f_wb1s & SSW4_WBSV)
+                       panic("writeback: MOVE16 with WB1S valid");
+               wbstats.move16s++;
+#endif
+               if (KDFAULT(f->f_wb1s))
+                       bcopy((caddr_t)&f->f_pd0, (caddr_t)(f->f_fa & ~0xF), 16);
+               else
+                       err = suline((caddr_t)(f->f_fa & ~0xF), (caddr_t)&f->f_pd0);
+               if (err) {
+                       fa = f->f_fa & ~0xF;
+#ifdef DEBUG
+                       if (mmudebug & MDB_WBFAILED)
+                               printf(wberrstr, p->p_pid, p->p_comm,
+                                      "MOVE16", fp->f_pc, f->f_fa,
+                                      f->f_fa & ~0xF, f->f_pd0);
 #endif
 #endif
-                       if (type == T_MMUFLT)
-                               goto copyfault;
-                       i = SIGBUS;
+               }
+       } else if (f->f_wb1s & SSW4_WBSV) {
+               /*
+                * Writeback #1.
+                * Position the "memory-aligned" data and write it out.
+                */
+               register u_int wb1d = f->f_wb1d;
+               register int off;
+
+#ifdef DEBUG
+               if ((mmudebug & MDB_WBFOLLOW) || MDB_ISPID(p->p_pid))
+                       dumpwb(1, f->f_wb1s, f->f_wb1a, f->f_wb1d);
+               wbstats.wb1s++;
+               wbstats.wbsize[(f->f_wb2s&SSW4_SZMASK)>>5]++;
+#endif
+               off = (f->f_wb1a & 3) * 8;
+               switch (f->f_wb1s & SSW4_SZMASK) {
+               case SSW4_SZLW:
+                       if (off)
+                               wb1d = (wb1d >> (32 - off)) | (wb1d << off);
+                       if (KDFAULT(f->f_wb1s))
+                               *(long *)f->f_wb1a = wb1d;
+                       else
+                               err = suword((caddr_t)f->f_wb1a, wb1d);
+                       break;
+               case SSW4_SZB:
+                       off = 24 - off;
+                       if (off)
+                               wb1d >>= off;
+                       if (KDFAULT(f->f_wb1s))
+                               *(char *)f->f_wb1a = wb1d;
+                       else
+                               err = subyte((caddr_t)f->f_wb1a, wb1d);
+                       break;
+               case SSW4_SZW:
+                       off = (off + 16) % 32;
+                       if (off)
+                               wb1d = (wb1d >> (32 - off)) | (wb1d << off);
+                       if (KDFAULT(f->f_wb1s))
+                               *(short *)f->f_wb1a = wb1d;
+                       else
+                               err = susword((caddr_t)f->f_wb1a, wb1d);
                        break;
                }
                        break;
                }
-               if (ncode & MMU_PF) {
-                       register u_int vp;
+               if (err) {
+                       fa = f->f_wb1a;
 #ifdef DEBUG
 #ifdef DEBUG
-                       extern struct ste *vtoste();
-                       u_int *ste = (u_int *)vtoste(p, v);
-                       struct pte *pte;
-
-                       if (!(*ste & SG_V)) {
-                               printf("MMU_PF without sg_v, ste@%x = %x\n",
-                                      ste, *ste);
-                               goto dopanic;
-                       }
+                       if (mmudebug & MDB_WBFAILED)
+                               printf(wberrstr, p->p_pid, p->p_comm,
+                                      "#1", fp->f_pc, f->f_fa,
+                                      f->f_wb1a, f->f_wb1d);
 #endif
 #endif
-                       vp = btop(v);
-                       if (vp >= dptov(p, p->p_dsize) &&
-                           vp < sptov(p, p->p_ssize-1))
-                               goto growit;
+               }
+       }
+       /*
+        * Deal with the "normal" writebacks.
+        *
+        * XXX writeback2 is known to reflect a LINE size writeback after
+        * a MOVE16 was already dealt with above.  Ignore it.
+        */
+       if (err == 0 && (f->f_wb2s & SSW4_WBSV) &&
+           (f->f_wb2s & SSW4_SZMASK) != SSW4_SZLN) {
 #ifdef DEBUG
 #ifdef DEBUG
-                       pte = vtopte(p, vp);
-                       if (*(u_int *)pte & PG_V) {
-                               printf("MMU_PF with pg_v, pte = %x\n",
-                                      *(u_int *)pte);
-                               goto dopanic;
+               if ((mmudebug & MDB_WBFOLLOW) || MDB_ISPID(p->p_pid))
+                       dumpwb(2, f->f_wb2s, f->f_wb2a, f->f_wb2d);
+               wbstats.wb2s++;
+               wbstats.wbsize[(f->f_wb2s&SSW4_SZMASK)>>5]++;
+#endif
+               switch (f->f_wb2s & SSW4_SZMASK) {
+               case SSW4_SZLW:
+                       if (KDFAULT(f->f_wb2s))
+                               *(long *)f->f_wb2a = f->f_wb2d;
+                       else
+                               err = suword((caddr_t)f->f_wb2a, f->f_wb2d);
+                       break;
+               case SSW4_SZB:
+                       if (KDFAULT(f->f_wb2s))
+                               *(char *)f->f_wb2a = f->f_wb2d;
+                       else
+                               err = subyte((caddr_t)f->f_wb2a, f->f_wb2d);
+                       break;
+               case SSW4_SZW:
+                       if (KDFAULT(f->f_wb2s))
+                               *(short *)f->f_wb2a = f->f_wb2d;
+                       else
+                               err = susword((caddr_t)f->f_wb2a, f->f_wb2d);
+                       break;
+               }
+               if (err) {
+                       fa = f->f_wb2a;
+#ifdef DEBUG
+                       if (mmudebug & MDB_WBFAILED) {
+                               printf(wberrstr, p->p_pid, p->p_comm,
+                                      "#2", fp->f_pc, f->f_fa,
+                                      f->f_wb2a, f->f_wb2d);
+                               dumpssw(f->f_ssw);
+                               dumpwb(2, f->f_wb2s, f->f_wb2a, f->f_wb2d);
                        }
 #endif
                        }
 #endif
-                       i = u.u_error;
-                       pagein(v, 0);
-                       u.u_error = i;
-                       if (type == T_MMUFLT)
-                               return;
-                       goto out;
                }
                }
+       }
+       if (err == 0 && (f->f_wb3s & SSW4_WBSV)) {
 #ifdef DEBUG
 #ifdef DEBUG
-               printf("T_MMUFLT: unrecognized scenerio\n");
-               goto dopanic;
+               if ((mmudebug & MDB_WBFOLLOW) || MDB_ISPID(p->p_pid))
+                       dumpwb(3, f->f_wb3s, f->f_wb3a, f->f_wb3d);
+               wbstats.wb3s++;
+               wbstats.wbsize[(f->f_wb3s&SSW4_SZMASK)>>5]++;
+#endif
+               switch (f->f_wb3s & SSW4_SZMASK) {
+               case SSW4_SZLW:
+                       if (KDFAULT(f->f_wb3s))
+                               *(long *)f->f_wb3a = f->f_wb3d;
+                       else
+                               err = suword((caddr_t)f->f_wb3a, f->f_wb3d);
+                       break;
+               case SSW4_SZB:
+                       if (KDFAULT(f->f_wb3s))
+                               *(char *)f->f_wb3a = f->f_wb3d;
+                       else
+                               err = subyte((caddr_t)f->f_wb3a, f->f_wb3d);
+                       break;
+               case SSW4_SZW:
+                       if (KDFAULT(f->f_wb3s))
+                               *(short *)f->f_wb3a = f->f_wb3d;
+                       else
+                               err = susword((caddr_t)f->f_wb3a, f->f_wb3d);
+                       break;
+#ifdef DEBUG
+               case SSW4_SZLN:
+                       panic("writeback: wb3s indicates LINE write");
 #endif
 #endif
-       }
-       trapsignal(i, ucode);
-       if ((type & USER) == 0)
-               return;
-out:
-       p = u.u_procp;
-       if (i = CURSIG(p))
-               psig(i);
-       p->p_pri = p->p_usrpri;
-       if (runrun) {
-               /*
-                * Since we are u.u_procp, clock will normally just change
-                * our priority without moving us from one queue to another
-                * (since the running process is not on a queue.)
-                * If that happened after we setrq ourselves but before we
-                * swtch()'ed, we might not be on the queue indicated by
-                * our priority.
-                */
-               (void) splclock();
-               setrq(p);
-               u.u_ru.ru_nivcsw++;
-               swtch();
-               if (i = CURSIG(p))
-                       psig(i);
-       }
-       if (u.u_prof.pr_scale) {
-               int ticks;
-               struct timeval *tv = &u.u_ru.ru_stime;
-
-               ticks = ((tv->tv_sec - syst.tv_sec) * 1000 +
-                       (tv->tv_usec - syst.tv_usec) / 1000) / (tick / 1000);
-               if (ticks) {
-#ifdef PROFTIMER
-                       extern int profscale;
-                       addupc(frame.f_pc, &u.u_prof, ticks * profscale);
-#else
-                       addupc(frame.f_pc, &u.u_prof, ticks);
+               }
+               if (err) {
+                       fa = f->f_wb3a;
+#ifdef DEBUG
+                       if (mmudebug & MDB_WBFAILED)
+                               printf(wberrstr, p->p_pid, p->p_comm,
+                                      "#3", fp->f_pc, f->f_fa,
+                                      f->f_wb3a, f->f_wb3d);
 #endif
                }
        }
 #endif
                }
        }
-       curpri = p->p_pri;
+       p->p_addr->u_pcb.pcb_onfault = oonfault;
+       /*
+        * Determine the cause of the failure if any translating to
+        * a signal.  If the corresponding VA is valid and RO it is
+        * a protection fault (SIGBUS) otherwise consider it an
+        * illegal reference (SIGSEGV).
+        */
+       if (err) {
+               if (vm_map_check_protection(&p->p_vmspace->vm_map,      
+                                           trunc_page(fa), round_page(fa),
+                                           VM_PROT_READ) &&
+                   !vm_map_check_protection(&p->p_vmspace->vm_map,
+                                            trunc_page(fa), round_page(fa),
+                                            VM_PROT_WRITE))
+                       err = SIGBUS;
+               else
+                       err = SIGSEGV;
+       }
+       return(err);
+}
+
+#ifdef DEBUG
+dumpssw(ssw)
+       register u_short ssw;
+{
+       printf(" SSW: %x: ", ssw);
+       if (ssw & SSW4_CP)
+               printf("CP,");
+       if (ssw & SSW4_CU)
+               printf("CU,");
+       if (ssw & SSW4_CT)
+               printf("CT,");
+       if (ssw & SSW4_CM)
+               printf("CM,");
+       if (ssw & SSW4_MA)
+               printf("MA,");
+       if (ssw & SSW4_ATC)
+               printf("ATC,");
+       if (ssw & SSW4_LK)
+               printf("LK,");
+       if (ssw & SSW4_RW)
+               printf("RW,");
+       printf(" SZ=%s, TT=%s, TM=%s\n",
+              f7sz[(ssw & SSW4_SZMASK) >> 5],
+              f7tt[(ssw & SSW4_TTMASK) >> 3],
+              f7tm[ssw & SSW4_TMMASK]);
 }
 
 }
 
+dumpwb(num, s, a, d)
+       int num;
+       u_short s;
+       u_int a, d;
+{
+       register struct proc *p = curproc;
+       vm_offset_t pa;
+
+       printf(" writeback #%d: VA %x, data %x, SZ=%s, TT=%s, TM=%s\n",
+              num, a, d, f7sz[(s & SSW4_SZMASK) >> 5],
+              f7tt[(s & SSW4_TTMASK) >> 3], f7tm[s & SSW4_TMMASK]);
+       printf("               PA ");
+       pa = pmap_extract(&p->p_vmspace->vm_pmap, (vm_offset_t)a);
+       if (pa == 0)
+               printf("<invalid address>");
+       else
+               printf("%x, current value %x", pa, fuword((caddr_t)a));
+       printf("\n");
+}
+#endif
+#endif
+
 /*
 /*
- * Called from the trap handler when a system call occurs
+ * Proces a system call.
  */
  */
-/*ARGSUSED*/
 syscall(code, frame)
 syscall(code, frame)
-       volatile int code;
+       u_int code;
        struct frame frame;
 {
        register caddr_t params;
        struct frame frame;
 {
        register caddr_t params;
-       register int i;
        register struct sysent *callp;
        register struct sysent *callp;
-       register struct proc *p = u.u_procp;
+       register struct proc *p;
        int error, opc, numsys;
        int error, opc, numsys;
-       struct timeval syst;
-       struct sysent *systab;
+       u_int argsize;
+       struct args {
+               int i[8];
+       } args;
+       int rval[2];
+       u_quad_t sticks;
 #ifdef HPUXCOMPAT
        extern struct sysent hpuxsysent[];
        extern int hpuxnsysent, notimp();
 #endif
 
        cnt.v_syscall++;
 #ifdef HPUXCOMPAT
        extern struct sysent hpuxsysent[];
        extern int hpuxnsysent, notimp();
 #endif
 
        cnt.v_syscall++;
-       syst = u.u_ru.ru_stime;
        if (!USERMODE(frame.f_sr))
                panic("syscall");
        if (!USERMODE(frame.f_sr))
                panic("syscall");
-       u.u_ar0 = frame.f_regs;
-       u.u_error = 0;
+       p = curproc;
+       sticks = p->p_sticks;
+       p->p_md.md_regs = frame.f_regs;
        opc = frame.f_pc - 2;
        opc = frame.f_pc - 2;
-       systab = sysent;
-       numsys = nsysent;
 #ifdef HPUXCOMPAT
 #ifdef HPUXCOMPAT
-       if (p->p_flag & SHPUX) {
-               systab = hpuxsysent;
-               numsys = hpuxnsysent;
-       }
+       if (p->p_md.md_flags & MDP_HPUX)
+               callp = hpuxsysent, numsys = hpuxnsysent;
+       else
 #endif
 #endif
-       params = (caddr_t)frame.f_regs[SP] + NBPW;
-       if (code == 0) {                        /* indir */
+               callp = sysent, numsys = nsysent;
+       params = (caddr_t)frame.f_regs[SP] + sizeof(int);
+       switch (code) {
+
+       case SYS_syscall:
+               /*
+                * Code is first argument, followed by actual args.
+                */
                code = fuword(params);
                code = fuword(params);
-               params += NBPW;
-       }
-       if (code >= numsys)
-               callp = &systab[0];             /* indir (illegal) */
-       else
-               callp = &systab[code];
-       if ((i = callp->sy_narg * sizeof (int)) &&
-           (error = copyin(params, (caddr_t)u.u_arg, (u_int)i))) {
+               params += sizeof(int);
+               /*
+                * XXX sigreturn requires special stack manipulation
+                * that is only done if entered via the sigreturn
+                * trap.  Cannot allow it here so make sure we fail.
+                */
+               if (code == SYS_sigreturn)
+                       code = numsys;
+               break;
+
+       case SYS___syscall:
+               /*
+                * Like syscall, but code is a quad, so as to maintain
+                * quad alignment for the rest of the arguments.
+                */
 #ifdef HPUXCOMPAT
 #ifdef HPUXCOMPAT
-               if (p->p_flag & SHPUX)
-                       error = bsdtohpuxerrno(error);
+               if (p->p_md.md_flags & MDP_HPUX)
+                       break;
 #endif
 #endif
-               frame.f_regs[D0] = (u_char) error;
-               frame.f_sr |= PSL_C;    /* carry bit */
+               code = fuword(params + _QUAD_LOWWORD * sizeof(int));
+               params += sizeof(quad_t);
+               break;
+
+       default:
+               /* nothing to do by default */
+               break;
+       }
+       if (code < numsys)
+               callp += code;
+       else
+               callp += SYS_syscall;   /* => nosys */
+       argsize = callp->sy_argsize;
+       if (argsize && (error = copyin(params, (caddr_t)&args, argsize))) {
 #ifdef KTRACE
 #ifdef KTRACE
-                if (KTRPOINT(p, KTR_SYSCALL))
-                        ktrsyscall(p->p_tracep, code, callp->sy_narg);
+               if (KTRPOINT(p, KTR_SYSCALL))
+                       ktrsyscall(p->p_tracep, code, argsize, args.i);
 #endif
 #endif
-               goto done;
+               goto bad;
        }
 #ifdef KTRACE
        }
 #ifdef KTRACE
-        if (KTRPOINT(p, KTR_SYSCALL))
-                ktrsyscall(p->p_tracep, code, callp->sy_narg);
+       if (KTRPOINT(p, KTR_SYSCALL))
+               ktrsyscall(p->p_tracep, code, argsize, args.i);
 #endif
 #endif
-       u.u_r.r_val1 = 0;
-       u.u_r.r_val2 = frame.f_regs[D0];
+       rval[0] = 0;
+       rval[1] = frame.f_regs[D1];
 #ifdef HPUXCOMPAT
        /* debug kludge */
        if (callp->sy_call == notimp)
 #ifdef HPUXCOMPAT
        /* debug kludge */
        if (callp->sy_call == notimp)
-               error = notimp(code, callp->sy_narg);
+               error = notimp(p, args.i, rval, code, argsize);
        else
 #endif
        else
 #endif
-       error = (*callp->sy_call)(u.u_procp, u.u_ap, &u.u_r.r_val1);
-       error = u.u_error;              /* XXX */
-       if (error == ERESTART)
-               frame.f_pc = opc;
-       else if (error != EJUSTRETURN) {
-               if (error) {
-#ifdef HPUXCOMPAT
-                       if (p->p_flag & SHPUX)
-                               error = bsdtohpuxerrno(error);
-#endif
-                       frame.f_regs[D0] = (u_char) error;
-                       frame.f_sr |= PSL_C;    /* carry bit */
-               } else {
-                       frame.f_regs[D0] = u.u_r.r_val1;
-                       frame.f_regs[D1] = u.u_r.r_val2;
-                       frame.f_sr &= ~PSL_C;
-               }
-       }
-       /* else if (error == EJUSTRETURN) */
-               /* nothing to do */
+               error = (*callp->sy_call)(p, &args, rval);
+       switch (error) {
 
 
-done:
-       /*
-        * Reinitialize proc pointer `p' as it may be different
-        * if this is a child returning from fork syscall.
-        */
-       p = u.u_procp;
-       /*
-        * XXX the check for sigreturn ensures that we don't
-        * attempt to set up a call to a signal handler (sendsig) before
-        * we have cleaned up the stack from the last call (sigreturn).
-        * Allowing this seems to lock up the machine in certain scenarios.
-        * What should really be done is to clean up the signal handling
-        * so that this is not a problem.
-        */
-#include "syscall.h"
-       if (code != SYS_sigreturn && (i = CURSIG(p)))
-               psig(i);
-       p->p_pri = p->p_usrpri;
-       if (runrun) {
+       case 0:
                /*
                /*
-                * Since we are u.u_procp, clock will normally just change
-                * our priority without moving us from one queue to another
-                * (since the running process is not on a queue.)
-                * If that happened after we setrq ourselves but before we
-                * swtch()'ed, we might not be on the queue indicated by
-                * our priority.
+                * Reinitialize proc pointer `p' as it may be different
+                * if this is a child returning from fork syscall.
                 */
                 */
-               (void) splclock();
-               setrq(p);
-               u.u_ru.ru_nivcsw++;
-               swtch();
-               if (i = CURSIG(p))
-                       psig(i);
-       }
-       if (u.u_prof.pr_scale) {
-               int ticks;
-               struct timeval *tv = &u.u_ru.ru_stime;
-
-               ticks = ((tv->tv_sec - syst.tv_sec) * 1000 +
-                       (tv->tv_usec - syst.tv_usec) / 1000) / (tick / 1000);
-               if (ticks) {
-#ifdef PROFTIMER
-                       extern int profscale;
-                       addupc(frame.f_pc, &u.u_prof, ticks * profscale);
-#else
-                       addupc(frame.f_pc, &u.u_prof, ticks);
+               p = curproc;
+               frame.f_regs[D0] = rval[0];
+               frame.f_regs[D1] = rval[1];
+               frame.f_sr &= ~PSL_C;
+               break;
+
+       case ERESTART:
+               frame.f_pc = opc;
+               break;
+
+       case EJUSTRETURN:
+               break;          /* nothing to do */
+
+       default:
+       bad:
+#ifdef HPUXCOMPAT
+               if (p->p_md.md_flags & MDP_HPUX)
+                       error = bsdtohpuxerrno(error);
 #endif
 #endif
-               }
+               frame.f_regs[D0] = error;
+               frame.f_sr |= PSL_C;
+               break;
        }
        }
-       curpri = p->p_pri;
+
+       userret(p, &frame, sticks, (u_int)0, 0);
 #ifdef KTRACE
 #ifdef KTRACE
-        if (KTRPOINT(p, KTR_SYSRET))
-                ktrsysret(p->p_tracep, code);
+       if (KTRPOINT(p, KTR_SYSRET))
+               ktrsysret(p->p_tracep, code, error, rval[0]);
 #endif
 }
 #endif
 }