BSD 4_4_Lite2 release
[unix-history] / usr / src / sys / hp300 / hp300 / trap.c
index 070326b..f18333b 100644 (file)
@@ -1,45 +1,70 @@
 /*
  * 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.32 91/04/06$
+ * 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.14.1.2 (Berkeley) %G%
+ * from: Utah $Hdr: trap.c 1.37 92/12/20$
+ *
+ *     @(#)trap.c      8.7 (Berkeley) 2/19/95
  */
 
  */
 
-#include "param.h"
-#include "systm.h"
-#include "proc.h"
-#include "seg.h"
-#include "acct.h"
-#include "kernel.h"
-#include "signalvar.h"
-#include "resourcevar.h"
-#include "syslog.h"
-#include "user.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 "../include/psl.h"
-#include "../include/trap.h"
-#include "../include/cpu.h"
-#include "../include/reg.h"
-#include "../include/mtpr.h"
+#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"
-#include "vmmeter.h"
+#include <vm/vm.h>
+#include <vm/pmap.h>
 
 #ifdef HPUXCOMPAT
 
 #ifdef HPUXCOMPAT
-#include "../hpux/hpux.h"
+#include <hp/hpux/hpux.h>
 #endif
 
 struct sysent  sysent[];
 #endif
 
 struct sysent  sysent[];
@@ -70,9 +95,9 @@ 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) */
        FMT0SIZE,       /* type 0 - normal (68020/030/040) */
        FMT1SIZE,       /* type 1 - throwaway (68020/030/040) */
        FMT2SIZE,       /* type 2 - normal 6-word (68020/030/040) */
-       -1,             /* type 3 - FP post-instruction (68040) */
+       FMT3SIZE,       /* type 3 - FP post-instruction (68040) */
        -1, -1, -1,     /* type 4-6 - undefined */
        -1, -1, -1,     /* type 4-6 - undefined */
-       -1,             /* type 7 - access error (68040) */
+       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) */
        58,             /* type 8 - bus fault (68010) */
        FMT9SIZE,       /* type 9 - coprocessor mid-instruction (68020/030) */
        FMTASIZE,       /* type A - short bus fault (68020/030) */
@@ -80,10 +105,105 @@ short     exframesize[] = {
        -1, -1, -1, -1  /* type C-F - undefined */
 };
 
        -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
 
 #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
+       curpriority = p->p_priority;
+}
+
 /*
  * Trap is called from locore to handle most types of processor traps,
  * including events such as simulated software interrupts/AST's.
 /*
  * Trap is called from locore to handle most types of processor traps,
  * including events such as simulated software interrupts/AST's.
@@ -96,24 +216,26 @@ 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 = curproc;
-       struct timeval syst;
-       unsigned ncode;
+       u_int ucode;
+       u_quad_t sticks;
 
        cnt.v_trap++;
 
        cnt.v_trap++;
-       syst = p->p_stime;
+       p = curproc;
+       ucode = 0;
        if (USERMODE(frame.f_sr)) {
                type |= T_USER;
        if (USERMODE(frame.f_sr)) {
                type |= T_USER;
-               p->p_regs = frame.f_regs;
+               sticks = p->p_sticks;
+               p->p_md.md_regs = frame.f_regs;
        }
        switch (type) {
 
        default:
 dopanic:
                printf("trap type %d, code = %x, v = %x\n", type, code, v);
        }
        switch (type) {
 
        default:
 dopanic:
                printf("trap type %d, code = %x, v = %x\n", type, code, v);
-               regdump(frame.f_regs, 128);
+               regdump(&frame, 128);
                type &= ~T_USER;
                if ((unsigned)type < TRAP_TYPES)
                        panic(trap_type[type]);
                type &= ~T_USER;
                if ((unsigned)type < TRAP_TYPES)
                        panic(trap_type[type]);
@@ -136,20 +258,37 @@ copyfault:
 
        case T_BUSERR|T_USER:   /* bus error */
        case T_ADDRERR|T_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.
-        */
+       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_USER;
                printf("pid %d: kernel %s exception\n", p->p_pid,
-                      type==T_COPERR ? "coprocessor" : "format");
+                      (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_sigacts->ps_sigact[SIGILL] = SIG_DFL;
                i = sigmask(SIGILL);
                p->p_sigignore &= ~i;
@@ -181,9 +320,22 @@ copyfault:
                break;
 #endif
 
                break;
 #endif
 
+#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
        case T_ILLINST|T_USER:  /* illegal instruction fault */
 #ifdef HPUXCOMPAT
-               if (p->p_flag & SHPUX) {
+               if (p->p_md.md_flags & MDP_HPUX) {
                        ucode = HPUX_ILL_ILLINST_TRAP;
                        i = SIGILL;
                        break;
                        ucode = HPUX_ILL_ILLINST_TRAP;
                        i = SIGILL;
                        break;
@@ -192,7 +344,7 @@ copyfault:
 #endif
        case T_PRIVINST|T_USER: /* privileged instruction fault */
 #ifdef HPUXCOMPAT
 #endif
        case T_PRIVINST|T_USER: /* privileged instruction fault */
 #ifdef HPUXCOMPAT
-               if (p->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
@@ -202,7 +354,7 @@ copyfault:
 
        case T_ZERODIV|T_USER:  /* Divide by zero */
 #ifdef HPUXCOMPAT
 
        case T_ZERODIV|T_USER:  /* Divide by zero */
 #ifdef HPUXCOMPAT
-               if (p->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
@@ -212,7 +364,7 @@ copyfault:
 
        case T_CHKINST|T_USER:  /* CHK instruction trap */
 #ifdef HPUXCOMPAT
 
        case T_CHKINST|T_USER:  /* CHK instruction trap */
 #ifdef HPUXCOMPAT
-               if (p->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;
@@ -225,7 +377,7 @@ copyfault:
 
        case T_TRAPVINST|T_USER:        /* TRAPV instruction trap */
 #ifdef HPUXCOMPAT
 
        case T_TRAPVINST|T_USER:        /* TRAPV instruction trap */
 #ifdef HPUXCOMPAT
-               if (p->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;
@@ -286,25 +438,29 @@ 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_ASTFLT|T_USER) {
+               if (type != (T_ASTFLT|T_USER)) {
                        cnt.v_trap--;
                        return;
                }
                spl0();
                        cnt.v_trap--;
                        return;
                }
                spl0();
-#ifndef PROFTIMER
-               if ((p->p_flag&SOWEUPC) && p->p_stats->p_prof.pr_scale) {
-                       addupc(frame.f_pc, &p->p_stats->p_prof, 1);
-                       p->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 */
+               /*
+                * If we were doing profiling ticks or other user mode
+                * stuff from interrupt code, Just Say No.
+                */
+               if (p->p_addr->u_pcb.pcb_onfault == fswintr)
+                       goto copyfault;
                /* fall into ... */
 
        case T_MMUFLT|T_USER:   /* page fault */
                /* fall into ... */
 
        case T_MMUFLT|T_USER:   /* page fault */
@@ -316,6 +472,11 @@ copyfault:
                vm_prot_t ftype;
                extern vm_map_t kernel_map;
 
                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);
+#endif
                /*
                 * It is only a kernel address space fault iff:
                 *      1. (type & T_USER) == 0  and
                /*
                 * It is only a kernel address space fault iff:
                 *      1. (type & T_USER) == 0  and
@@ -325,12 +486,11 @@ copyfault:
                 * argument space is lazy-allocated.
                 */
                if (type == T_MMUFLT &&
                 * argument space is lazy-allocated.
                 */
                if (type == T_MMUFLT &&
-                   (!p->p_addr->u_pcb.pcb_onfault ||
-                    (code & (SSW_DF|FC_SUPERD)) == (SSW_DF|FC_SUPERD)))
+                   (!p->p_addr->u_pcb.pcb_onfault || KDFAULT(code)))
                        map = kernel_map;
                else
                        map = &vm->vm_map;
                        map = kernel_map;
                else
                        map = &vm->vm_map;
-               if ((code & (SSW_DF|SSW_RW)) == SSW_DF) /* what about RMW? */
+               if (WRFAULT(code))
                        ftype = VM_PROT_READ | VM_PROT_WRITE;
                else
                        ftype = VM_PROT_READ;
                        ftype = VM_PROT_READ | VM_PROT_WRITE;
                else
                        ftype = VM_PROT_READ;
@@ -340,8 +500,26 @@ copyfault:
                        printf("trap: bad kernel access at %x\n", v);
                        goto dopanic;
                }
                        printf("trap: bad kernel access at %x\n", v);
                        goto dopanic;
                }
+#endif
+#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);
 #endif
                rv = vm_fault(map, va, ftype, FALSE);
+#ifdef DEBUG
+               if (rv && MDB_ISPID(p->p_pid))
+                       printf("vm_fault(%x, %x, %x, 0) -> %x\n",
+                              map, va, ftype, rv);
+#endif
                /*
                 * If this was a stack access we keep track of the maximum
                 * accessed stack size.  Also, if vm_fault gets a protection
                /*
                 * If this was a stack access we keep track of the maximum
                 * accessed stack size.  Also, if vm_fault gets a protection
@@ -360,8 +538,13 @@ copyfault:
                                rv = KERN_INVALID_ADDRESS;
                }
                if (rv == KERN_SUCCESS) {
                                rv = KERN_INVALID_ADDRESS;
                }
                if (rv == KERN_SUCCESS) {
-                       if (type == T_MMUFLT)
+                       if (type == T_MMUFLT) {
+#ifdef HP380
+                               if (mmutype == MMU_68040)
+                                       (void) writeback(&frame, 1);
+#endif
                                return;
                                return;
+                       }
                        goto out;
                }
                if (type == T_MMUFLT) {
                        goto out;
                }
                if (type == T_MMUFLT) {
@@ -382,186 +565,448 @@ copyfault:
        if ((type & T_USER) == 0)
                return;
 out:
        if ((type & T_USER) == 0)
                return;
 out:
-       while (i = CURSIG(p))
-               psig(i);
-       p->p_pri = p->p_usrpri;
-       if (want_resched) {
+       userret(p, &frame, sticks, v, 1);
+}
+
+#ifdef HP380
+#ifdef DEBUG
+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
+       /*
+        * Deal with special cases first.
+        */
+       if ((f->f_ssw & SSW4_TMMASK) == SSW4_TMDCP) {
                /*
                /*
-                * 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 setrq ourselves but before we
-                * swtch()'ed, we might not be on the queue indicated by
-                * our priority.
+                * Dcache push fault.
+                * Line-align the address and write out the push data to
+                * the indicated physical address.
                 */
                 */
-               (void) splclock();
-               setrq(p);
-               p->p_stats->p_ru.ru_nivcsw++;
-               swtch();
-               while (i = CURSIG(p))
-                       psig(i);
+#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
+               /*
+                * 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.
+                */
+#ifdef DEBUG
+               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
+               }
+       } 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;
+               }
+               if (err) {
+                       fa = f->f_wb1a;
+#ifdef DEBUG
+                       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
+               }
        }
        }
-       if (p->p_stats->p_prof.pr_scale) {
-               int ticks;
-               struct timeval *tv = &p->p_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, &p->p_stats->p_prof,
-                           ticks * profscale);
-#else
-                       addupc(frame.f_pc, &p->p_stats->p_prof, ticks);
+       /*
+        * 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
+               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
                }
        }
-       curpri = p->p_pri;
+       if (err == 0 && (f->f_wb3s & SSW4_WBSV)) {
+#ifdef DEBUG
+               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
+               }
+               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
+               }
+       }
+       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
+
 /*
  * Proces a system call.
  */
 syscall(code, frame)
 /*
  * Proces a system call.
  */
 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 = curproc;
+       register struct proc *p;
        int error, opc, numsys;
        int error, opc, numsys;
+       u_int argsize;
        struct args {
                int i[8];
        } args;
        int rval[2];
        struct args {
                int i[8];
        } args;
        int rval[2];
-       struct timeval syst;
-       struct sysent *systab;
+       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 = p->p_stime;
        if (!USERMODE(frame.f_sr))
                panic("syscall");
        if (!USERMODE(frame.f_sr))
                panic("syscall");
-       p->p_regs = frame.f_regs;
+       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
+               callp = sysent, numsys = nsysent;
        params = (caddr_t)frame.f_regs[SP] + sizeof(int);
        params = (caddr_t)frame.f_regs[SP] + sizeof(int);
-       if (code == 0) {                        /* indir */
+       switch (code) {
+
+       case SYS_syscall:
+               /*
+                * Code is first argument, followed by actual args.
+                */
                code = fuword(params);
                params += sizeof(int);
                code = fuword(params);
                params += sizeof(int);
-       }
-       if (code >= numsys)
-               callp = &systab[0];             /* indir (illegal) */
-       else
-               callp = &systab[code];
-       if ((i = callp->sy_narg * sizeof (int)) &&
-           (error = copyin(params, (caddr_t)&args, (u_int)i))) {
+               /*
+                * 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] = 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
                if (KTRPOINT(p, KTR_SYSCALL))
 #ifdef KTRACE
                if (KTRPOINT(p, KTR_SYSCALL))
-                       ktrsyscall(p->p_tracep, code, callp->sy_narg, args.i);
+                       ktrsyscall(p->p_tracep, code, argsize, args.i);
 #endif
 #endif
-               goto done;
+               goto bad;
        }
 #ifdef KTRACE
        if (KTRPOINT(p, KTR_SYSCALL))
        }
 #ifdef KTRACE
        if (KTRPOINT(p, KTR_SYSCALL))
-               ktrsyscall(p->p_tracep, code, callp->sy_narg, args.i);
+               ktrsyscall(p->p_tracep, code, argsize, args.i);
 #endif
        rval[0] = 0;
        rval[1] = frame.f_regs[D1];
 #ifdef HPUXCOMPAT
        /* debug kludge */
        if (callp->sy_call == notimp)
 #endif
        rval[0] = 0;
        rval[1] = frame.f_regs[D1];
 #ifdef HPUXCOMPAT
        /* debug kludge */
        if (callp->sy_call == notimp)
-               error = notimp(p, args.i, rval, code, callp->sy_narg);
+               error = notimp(p, args.i, rval, code, argsize);
        else
 #endif
        else
 #endif
-       error = (*callp->sy_call)(p, &args, rval);
-#ifdef DIAGNOSTIC
-       if (curproc->p_spare[0])
-               panic("syscall: M_NAMEI");
-       if (curproc->p_spare[1])
-               panic("syscall: STARTSAVE");
-       if (curproc->p_spare[2])
-               panic("syscall: LOCK COUNT");
-#endif
-       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] = error;
-                       frame.f_sr |= PSL_C;    /* carry bit */
-               } else {
-                       frame.f_regs[D0] = rval[0];
-                       frame.f_regs[D1] = rval[1];
-                       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 = curproc;
-       while (i = CURSIG(p))
-               psig(i);
-       p->p_pri = p->p_usrpri;
-       if (want_resched) {
+       case 0:
                /*
                /*
-                * 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 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);
-               p->p_stats->p_ru.ru_nivcsw++;
-               swtch();
-               while (i = CURSIG(p))
-                       psig(i);
-       }
-       if (p->p_stats->p_prof.pr_scale) {
-               int ticks;
-               struct timeval *tv = &p->p_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, &p->p_stats->p_prof,
-                           ticks * profscale);
-#else
-                       addupc(frame.f_pc, &p->p_stats->p_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
        if (KTRPOINT(p, KTR_SYSRET))
                ktrsysret(p->p_tracep, code, error, rval[0]);
 #ifdef KTRACE
        if (KTRPOINT(p, KTR_SYSRET))
                ktrsysret(p->p_tracep, code, error, rval[0]);