BSD 4_4_Lite1 release
[unix-history] / usr / src / sys / hp300 / hp300 / locore.s
index e7db8d1..00b7f6c 100644 (file)
@@ -1,22 +1,74 @@
 /*
  * Copyright (c) 1988 University of Utah.
 /*
  * Copyright (c) 1988 University of Utah.
- * Copyright (c) 1980, 1990 The Regents of the University of California.
- * All rights reserved.
+ * Copyright (c) 1980, 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: locore.s 1.2 90/07/14$
+ * 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.
  *
  *
- *     @(#)locore.s    7.5 (Berkeley) %G%
+ * from: Utah $Hdr: locore.s 1.66 92/12/22$
+ *
+ *     @(#)locore.s    8.5 (Berkeley) 11/14/93
+ */
+
+/*
+ * STACKCHECK enables two types of kernel stack checking:
+ *     1. stack "overflow".  On every clock interrupt we ensure that
+ *        the current kernel stack has not grown into the user struct
+ *        page, i.e. size exceeded UPAGES-1 pages.
+ *     2. stack "underflow".  Before every rte to user mode we ensure
+ *        that we will be exactly at the base of the stack after the
+ *        exception frame has been popped.
+ * Both checks are performed at splclock since they operate on the
+ * global temporary stack.
  */
  */
+/* #define     STACKCHECK */
+
+#include "assym.s"
+#include <hp300/hp300/vectors.s>
 
 #define MMUADDR(ar)    movl    _MMUbase,ar
 #define CLKADDR(ar)    movl    _CLKbase,ar
 
 
 #define MMUADDR(ar)    movl    _MMUbase,ar
 #define CLKADDR(ar)    movl    _CLKbase,ar
 
+/*
+ * Temporary stack for a variety of purposes.
+ * Try and make this the first thing is the data segment so it
+ * is page aligned.  Note that if we overflow here, we run into
+ * our text segment.
+ */
+       .data
+       .space  NBPG
+tmpstk:
+
        .text
 /*
  * This is where we wind up if the kernel jumps to location 0.
        .text
 /*
  * This is where we wind up if the kernel jumps to location 0.
@@ -49,34 +101,73 @@ _doadump:
        .globl  _trap, _nofault, _longjmp
 _buserr:
        tstl    _nofault                | device probe?
        .globl  _trap, _nofault, _longjmp
 _buserr:
        tstl    _nofault                | device probe?
-       jeq     _addrerr                | no, handle as usual
+       jeq     Lberr                   | no, handle as usual
        movl    _nofault,sp@-           | yes,
        jbsr    _longjmp                |  longjmp(nofault)
        movl    _nofault,sp@-           | yes,
        jbsr    _longjmp                |  longjmp(nofault)
+Lberr:
+#if defined(HP380)
+       cmpl    #-2,_mmutype            | 68040?
+       jne     _addrerr                | no, skip
+       clrl    sp@-                    | stack adjust count
+       moveml  #0xFFFF,sp@-            | save user registers
+       movl    usp,a0                  | save the user SP
+       movl    a0,sp@(FR_SP)           |   in the savearea
+       lea     sp@(FR_HW),a1           | grab base of HW berr frame
+       moveq   #0,d0
+       movw    a1@(12),d0              | grab SSW
+       movl    a1@(20),d1              | and fault VA
+       btst    #11,d0                  | check for mis-aligned access
+       jeq     Lberr2                  | no, skip
+       addl    #3,d1                   | yes, get into next page
+       andl    #PG_FRAME,d1            | and truncate
+Lberr2:
+       movl    d1,sp@-                 | push fault VA
+       movl    d0,sp@-                 | and padded SSW
+       btst    #10,d0                  | ATC bit set?
+       jeq     Lisberr                 | no, must be a real bus error
+       movc    dfc,d1                  | yes, get MMU fault
+       movc    d0,dfc                  | store faulting function code
+       movl    sp@(4),a0               | get faulting address
+       .word   0xf568                  | ptestr a0@
+       movc    d1,dfc
+       .long   0x4e7a0805              | movc mmusr,d0
+       movw    d0,sp@                  | save (ONLY LOW 16 BITS!)
+       jra     Lismerr
+#endif
 _addrerr:
 _addrerr:
-       clrw    sp@-                    | pad SR to longword
+       clrl    sp@-                    | stack adjust count
        moveml  #0xFFFF,sp@-            | save user registers
        movl    usp,a0                  | save the user SP
        moveml  #0xFFFF,sp@-            | save user registers
        movl    usp,a0                  | save the user SP
-       movl    a0,sp@(60)              |   in the savearea
-       lea     sp@(64),a1              | grab base of HW berr frame
-       movw    a1@(12),d0              | grab SSW for fault processing
+       movl    a0,sp@(FR_SP)           |   in the savearea
+       lea     sp@(FR_HW),a1           | grab base of HW berr frame
+#if defined(HP380)
+       cmpl    #-2,_mmutype            | 68040?
+       jne     Lbenot040               | no, skip
+       movl    a1@(8),sp@-             | yes, push fault address
+       clrl    sp@-                    | no SSW for address fault
+       jra     Lisaerr                 | go deal with it
+Lbenot040:
+#endif
+       moveq   #0,d0
+       movw    a1@(10),d0              | grab SSW for fault processing
        btst    #12,d0                  | RB set?
        jeq     LbeX0                   | no, test RC
        bset    #14,d0                  | yes, must set FB
        btst    #12,d0                  | RB set?
        jeq     LbeX0                   | no, test RC
        bset    #14,d0                  | yes, must set FB
-       movw    d0,a1@(12)              | for hardware too
+       movw    d0,a1@(10)              | for hardware too
 LbeX0:
        btst    #13,d0                  | RC set?
        jeq     LbeX1                   | no, skip
        bset    #15,d0                  | yes, must set FC
 LbeX0:
        btst    #13,d0                  | RC set?
        jeq     LbeX1                   | no, skip
        bset    #15,d0                  | yes, must set FC
-       movw    d0,a1@(12)              | for hardware too
+       movw    d0,a1@(10)              | for hardware too
 LbeX1:
        btst    #8,d0                   | data fault?
        jeq     Lbe0                    | no, check for hard cases
 LbeX1:
        btst    #8,d0                   | data fault?
        jeq     Lbe0                    | no, check for hard cases
-       movl    a1@(18),d1              | fault address is as given in frame
+       movl    a1@(16),d1              | fault address is as given in frame
        jra     Lbe10                   | thats it
 Lbe0:
        jra     Lbe10                   | thats it
 Lbe0:
-       btst    #4,a1@(8)               | long (type B) stack frame?
+       btst    #4,a1@(6)               | long (type B) stack frame?
        jne     Lbe4                    | yes, go handle
        jne     Lbe4                    | yes, go handle
-       movl    a1@(4),d1               | no, can use save PC
+       movl    a1@(2),d1               | no, can use save PC
        btst    #14,d0                  | FB set?
        jeq     Lbe3                    | no, try FC
        addql   #4,d1                   | yes, adjust address
        btst    #14,d0                  | FB set?
        jeq     Lbe3                    | no, try FC
        addql   #4,d1                   | yes, adjust address
@@ -87,15 +178,14 @@ Lbe3:
        addql   #2,d1                   | yes, adjust address
        jra     Lbe10                   | done
 Lbe4:
        addql   #2,d1                   | yes, adjust address
        jra     Lbe10                   | done
 Lbe4:
-       movl    a1@(38),d1              | long format, use stage B address
+       movl    a1@(36),d1              | long format, use stage B address
        btst    #15,d0                  | FC set?
        jeq     Lbe10                   | no, all done
        subql   #2,d1                   | yes, adjust address
 Lbe10:
        movl    d1,sp@-                 | push fault VA
        btst    #15,d0                  | FC set?
        jeq     Lbe10                   | no, all done
        subql   #2,d1                   | yes, adjust address
 Lbe10:
        movl    d1,sp@-                 | push fault VA
-       movw    d0,sp@-                 | and SSW
-       clrw    sp@-                    |   padded to longword
-       movw    a1@(8),d0               | get frame format/vector offset
+       movl    d0,sp@-                 | and padded SSW
+       movw    a1@(6),d0               | get frame format/vector offset
        andw    #0x0FFF,d0              | clear out frame format
        cmpw    #12,d0                  | address error vector?
        jeq     Lisaerr                 | yes, go to it
        andw    #0x0FFF,d0              | clear out frame format
        cmpw    #12,d0                  | address error vector?
        jeq     Lisaerr                 | yes, go to it
@@ -121,95 +211,86 @@ Lbehpmmu:
 #endif
 Lismerr:
        movl    #T_MMUFLT,sp@-          | show that we are an MMU fault
 #endif
 Lismerr:
        movl    #T_MMUFLT,sp@-          | show that we are an MMU fault
-       jra     Lbexit                  | and deal with it
+       jra     Ltrapnstkadj            | and deal with it
 Lisaerr:
        movl    #T_ADDRERR,sp@-         | mark address error
 Lisaerr:
        movl    #T_ADDRERR,sp@-         | mark address error
-       jra     Lbexit                  | and deal with it
+       jra     Ltrapnstkadj            | and deal with it
 Lisberr:
        movl    #T_BUSERR,sp@-          | mark bus error
 Lisberr:
        movl    #T_BUSERR,sp@-          | mark bus error
-Lbexit:
+Ltrapnstkadj:
        jbsr    _trap                   | handle the error
        lea     sp@(12),sp              | pop value args
        jbsr    _trap                   | handle the error
        lea     sp@(12),sp              | pop value args
-       movl    sp@(60),a0              | restore user SP
+       movl    sp@(FR_SP),a0           | restore user SP
        movl    a0,usp                  |   from save area
        movl    a0,usp                  |   from save area
-       moveml  sp@+,#0x7FFF            | restore most user regs
-       addql   #4,sp                   | toss SSP
-       tstw    sp@+                    | do we need to clean up stack?
-       jeq     rei                     | no, just continue
-       btst    #7,sp@(6)               | type 9/10/11 frame?
-       jeq     rei                     | no, nothing to do
-       btst    #5,sp@(6)               | type 9?
-       jne     Lbex1                   | no, skip
-       movw    sp@,sp@(12)             | yes, push down SR
-       movl    sp@(2),sp@(14)          | and PC
-       clrw    sp@(18)                 | and mark as type 0 frame
-       lea     sp@(12),sp              | clean the excess
+       movw    sp@(FR_ADJ),d0          | need to adjust stack?
+       jne     Lstkadj                 | yes, go to it
+       moveml  sp@+,#0x7FFF            | no, restore most user regs
+       addql   #8,sp                   | toss SSP and stkadj
        jra     rei                     | all done
        jra     rei                     | all done
-Lbex1:
-       btst    #4,sp@(6)               | type 10?
-       jne     Lbex2                   | no, skip
-       movw    sp@,sp@(24)             | yes, push down SR
-       movl    sp@(2),sp@(26)          | and PC
-       clrw    sp@(30)                 | and mark as type 0 frame
-       lea     sp@(24),sp              | clean the excess
-       jra     rei                     | all done
-Lbex2:
-       movw    sp@,sp@(84)             | type 11, push down SR
-       movl    sp@(2),sp@(86)          | and PC
-       clrw    sp@(90)                 | and mark as type 0 frame
-       lea     sp@(84),sp              | clean the excess
+Lstkadj:
+       lea     sp@(FR_HW),a1           | pointer to HW frame
+       addql   #8,a1                   | source pointer
+       movl    a1,a0                   | source
+       addw    d0,a0                   |  + hole size = dest pointer
+       movl    a1@-,a0@-               | copy
+       movl    a1@-,a0@-               |  8 bytes
+       movl    a0,sp@(FR_SP)           | new SSP
+       moveml  sp@+,#0x7FFF            | restore user registers
+       movl    sp@,sp                  | and our SP
        jra     rei                     | all done
 
        jra     rei                     | all done
 
-_illinst:
-       clrw    sp@-
-       moveml  #0xFFFF,sp@-
-       moveq   #T_ILLINST,d0
-       jra     _fault
-
-_zerodiv:
-       clrw    sp@-
-       moveml  #0xFFFF,sp@-
-       moveq   #T_ZERODIV,d0
-       jra     _fault
-
-_chkinst:
-       clrw    sp@-
-       moveml  #0xFFFF,sp@-
-       moveq   #T_CHKINST,d0
-       jra     _fault
-
-_trapvinst:
-       clrw    sp@-
-       moveml  #0xFFFF,sp@-
-       moveq   #T_TRAPVINST,d0
-       jra     _fault
-
-_privinst:
-       clrw    sp@-
-       moveml  #0xFFFF,sp@-
-       moveq   #T_PRIVINST,d0
-       jra     _fault
-
-_coperr:
-       clrw    sp@-
-       moveml  #0xFFFF,sp@-
-       moveq   #T_COPERR,d0
-       jra     _fault
+/*
+ * FP exceptions.
+ */
+_fpfline:
+#if defined(HP380)
+       cmpw    #0x202c,sp@(6)          | format type 2?
+       jne     _illinst                | no, not an FP emulation
+#ifdef HPFPLIB
+       .globl fpsp_unimp
+       jmp     fpsp_unimp              | yes, go handle it
+#else
+       clrl    sp@-                    | stack adjust count
+       moveml  #0xFFFF,sp@-            | save registers
+       moveq   #T_FPEMULI,d0           | denote as FP emulation trap
+       jra     fault                   | do it
+#endif
+#else
+       jra     _illinst
+#endif
 
 
-_fmterr:
-       clrw    sp@-
-       moveml  #0xFFFF,sp@-
-       moveq   #T_FMTERR,d0
-       jra     _fault
+_fpunsupp:
+#if defined(HP380)
+       cmpl    #-2,_mmutype            | 68040?
+       jne     _illinst                | no, treat as illinst
+#ifdef HPFPLIB
+       .globl  fpsp_unsupp
+       jmp     fpsp_unsupp             | yes, go handle it
+#else
+       clrl    sp@-                    | stack adjust count
+       moveml  #0xFFFF,sp@-            | save registers
+       moveq   #T_FPEMULD,d0           | denote as FP emulation trap
+       jra     fault                   | do it
+#endif
+#else
+       jra     _illinst
+#endif
 
 
-_fptrap:
+/*
+ * Handles all other FP coprocessor exceptions.
+ * Note that since some FP exceptions generate mid-instruction frames
+ * and may cause signal delivery, we need to test for stack adjustment
+ * after the trap call.
+ */
+_fpfault:
 #ifdef FPCOPROC
 #ifdef FPCOPROC
-       clrw    sp@-            | pad SR to longword
+       clrl    sp@-            | stack adjust count
        moveml  #0xFFFF,sp@-    | save user registers
        movl    usp,a0          | and save
        moveml  #0xFFFF,sp@-    | save user registers
        movl    usp,a0          | and save
-       movl    a0,sp@(60)      |   the user stack pointer
+       movl    a0,sp@(FR_SP)   |   the user stack pointer
        clrl    sp@-            | no VA arg
        clrl    sp@-            | no VA arg
-       lea     _u+PCB_FPCTX,a0 | address of FP savearea
+       movl    _curpcb,a0      | current pcb
+       lea     a0@(PCB_FPCTX),a0 | address of FP savearea
        fsave   a0@             | save state
        tstb    a0@             | null state frame?
        jeq     Lfptnull        | yes, safe
        fsave   a0@             | save state
        tstb    a0@             | null state frame?
        jeq     Lfptnull        | yes, safe
@@ -220,57 +301,140 @@ Lfptnull:
        fmovem  fpsr,sp@-       | push fpsr as code argument
        frestore a0@            | restore state
        movl    #T_FPERR,sp@-   | push type arg
        fmovem  fpsr,sp@-       | push fpsr as code argument
        frestore a0@            | restore state
        movl    #T_FPERR,sp@-   | push type arg
-       jbsr    _trap           | call trap
-       lea     sp@(12),sp      | pop value args
-       movl    sp@(60),a0      | restore
-       movl    a0,usp          |   user SP
-       moveml  sp@+,#0x7FFF    | and remaining user registers
-       addql   #6,sp           | pop SSP and align word
-       jra     rei             | all done
+       jra     Ltrapnstkadj    | call trap and deal with stack cleanup
 #else
        jra     _badtrap        | treat as an unexpected trap
 #endif
 
 #else
        jra     _badtrap        | treat as an unexpected trap
 #endif
 
+#ifdef HPFPLIB
+/*
+ * We wind up here from the 040 FP emulation library after
+ * the exception has been processed.
+ */
        .globl  _fault
 _fault:
        .globl  _fault
 _fault:
+       subql   #4,sp           | space for rts addr
+       movl    d0,sp@-         | scratch register
+       movw    sp@(14),d0      | get vector offset
+       andl    #0xFFF,d0       | mask out frame type and clear high word
+       cmpl    #0x100,d0       | HP-UX style reschedule trap?
+       jne     Lfault1         | no, skip
+       movl    sp@+,d0         | restore scratch register
+       addql   #4,sp           | pop space
+       jra     Lrei1           | go do AST
+Lfault1:
+       cmpl    #0xC0,d0        | FP exception?
+       jlt     Lfault2         | no, skip
+       movl    sp@+,d0         | yes, backoff
+       addql   #4,sp           |  and prepare for normal trap frame
+       jra     _fpfault        | go to it
+Lfault2:
+       addl    #Lvectab,d0     | convert to vector table offset
+       exg     d0,a0
+       movl    a0@,sp@(4)      | get exception vector and save for rts
+       exg     d0,a0
+       movl    sp@+,d0         |   scratch registers
+       rts                     | return to handler from vectab
+#endif
+
+/*
+ * Coprocessor and format errors can generate mid-instruction stack
+ * frames and cause signal delivery hence we need to check for potential
+ * stack adjustment.
+ */
+_coperr:
+       clrl    sp@-            | stack adjust count
+       moveml  #0xFFFF,sp@-
        movl    usp,a0          | get and save
        movl    usp,a0          | get and save
-       movl    a0,sp@(60)      |   the user stack pointer
+       movl    a0,sp@(FR_SP)   |   the user stack pointer
        clrl    sp@-            | no VA arg
        clrl    sp@-            | or code arg
        clrl    sp@-            | no VA arg
        clrl    sp@-            | or code arg
-       movl    d0,sp@-         | push trap type
-       jbsr    _trap           | handle trap
-       lea     sp@(12),sp      | pop value args
-       movl    sp@(60),a0      | restore
-       movl    a0,usp          |   user SP
-       moveml  sp@+,#0x7FFF    | restore most user regs
-       addql   #6,sp           | pop SP and pad word
-       jra     rei             | all done
+       movl    #T_COPERR,sp@-  | push trap type
+       jra     Ltrapnstkadj    | call trap and deal with stack adjustments
+
+_fmterr:
+       clrl    sp@-            | stack adjust count
+       moveml  #0xFFFF,sp@-
+       movl    usp,a0          | get and save
+       movl    a0,sp@(FR_SP)   |   the user stack pointer
+       clrl    sp@-            | no VA arg
+       clrl    sp@-            | or code arg
+       movl    #T_FMTERR,sp@-  | push trap type
+       jra     Ltrapnstkadj    | call trap and deal with stack adjustments
+
+/*
+ * Other exceptions only cause four and six word stack frame and require
+ * no post-trap stack adjustment.
+ */
+_illinst:
+       clrl    sp@-
+       moveml  #0xFFFF,sp@-
+       moveq   #T_ILLINST,d0
+       jra     fault
+
+_zerodiv:
+       clrl    sp@-
+       moveml  #0xFFFF,sp@-
+       moveq   #T_ZERODIV,d0
+       jra     fault
+
+_chkinst:
+       clrl    sp@-
+       moveml  #0xFFFF,sp@-
+       moveq   #T_CHKINST,d0
+       jra     fault
+
+_trapvinst:
+       clrl    sp@-
+       moveml  #0xFFFF,sp@-
+       moveq   #T_TRAPVINST,d0
+       jra     fault
+
+_privinst:
+       clrl    sp@-
+       moveml  #0xFFFF,sp@-
+       moveq   #T_PRIVINST,d0
+       jra     fault
+
+       .globl  fault
+fault:
+       movl    usp,a0                  | get and save
+       movl    a0,sp@(FR_SP)           |   the user stack pointer
+       clrl    sp@-                    | no VA arg
+       clrl    sp@-                    | or code arg
+       movl    d0,sp@-                 | push trap type
+       jbsr    _trap                   | handle trap
+       lea     sp@(12),sp              | pop value args
+       movl    sp@(FR_SP),a0           | restore
+       movl    a0,usp                  |   user SP
+       moveml  sp@+,#0x7FFF            | restore most user regs
+       addql   #8,sp                   | pop SP and stack adjust
+       jra     rei                     | all done
 
        .globl  _straytrap
 _badtrap:
 
        .globl  _straytrap
 _badtrap:
+       moveml  #0xC0C0,sp@-            | save scratch regs
+       movw    sp@(22),sp@-            | push exception vector info
        clrw    sp@-
        clrw    sp@-
-       moveml  #0xC0C0,sp@-
-       movw    sp@(24),sp@-
-       clrw    sp@-
-       jbsr    _straytrap
-       addql   #4,sp
-       moveml  sp@+,#0x0303
-       addql   #2,sp
-       jra     rei
+       movl    sp@(22),sp@-            | and PC
+       jbsr    _straytrap              | report
+       addql   #8,sp                   | pop args
+       moveml  sp@+,#0x0303            | restore regs
+       jra     rei                     | all done
 
        .globl  _syscall
 _trap0:
 
        .globl  _syscall
 _trap0:
-       clrw    sp@-                    | pad SR to longword
+       clrl    sp@-                    | stack adjust count
        moveml  #0xFFFF,sp@-            | save user registers
        movl    usp,a0                  | save the user SP
        moveml  #0xFFFF,sp@-            | save user registers
        movl    usp,a0                  | save the user SP
-       movl    a0,sp@(60)              |   in the savearea
+       movl    a0,sp@(FR_SP)           |   in the savearea
        movl    d0,sp@-                 | push syscall number
        jbsr    _syscall                | handle it
        addql   #4,sp                   | pop syscall arg
        movl    d0,sp@-                 | push syscall number
        jbsr    _syscall                | handle it
        addql   #4,sp                   | pop syscall arg
-       movl    sp@(60),a0              | grab and restore
+       movl    sp@(FR_SP),a0           | grab and restore
        movl    a0,usp                  |   user SP
        moveml  sp@+,#0x7FFF            | restore most registers
        movl    a0,usp                  |   user SP
        moveml  sp@+,#0x7FFF            | restore most registers
-       addql   #6,sp                   | pop SSP and align word
+       addql   #8,sp                   | pop SP and stack adjust
        jra     rei                     | all done
 
 /*
        jra     rei                     | all done
 
 /*
@@ -281,15 +445,29 @@ _trap0:
  * to make adjustments so that trap 2 is used for sigreturn.
  */
 _trap1:
  * to make adjustments so that trap 2 is used for sigreturn.
  */
 _trap1:
-       btst    #PCB_TRCB,_u+PCB_FLAGS+1| being traced by an HPUX process?
+       btst    #MDP_TRCB,mdpflag       | being traced by an HPUX process?
        jeq     sigreturn               | no, trap1 is sigreturn
        jra     _trace                  | yes, trap1 is breakpoint
 
 _trap2:
        jeq     sigreturn               | no, trap1 is sigreturn
        jra     _trace                  | yes, trap1 is breakpoint
 
 _trap2:
-       btst    #PCB_TRCB,_u+PCB_FLAGS+1| being traced by an HPUX process?
+       btst    #MDP_TRCB,mdpflag       | being traced by an HPUX process?
        jeq     _trace                  | no, trap2 is breakpoint
        jra     sigreturn               | yes, trap2 is sigreturn
 
        jeq     _trace                  | no, trap2 is breakpoint
        jra     sigreturn               | yes, trap2 is sigreturn
 
+/*
+ * Trap 12 is the entry point for the cachectl "syscall" (both HPUX & BSD)
+ *     cachectl(command, addr, length)
+ * command in d0, addr in a1, length in d1
+ */
+       .globl  _cachectl
+_trap12:
+       movl    d1,sp@-                 | push length
+       movl    a1,sp@-                 | push addr
+       movl    d0,sp@-                 | push command
+       jbsr    _cachectl               | do it
+       lea     sp@(12),sp              | pop args
+       jra     rei                     | all done
+
 /*
  * Trap 15 is used for:
  *     - KGDB traps
 /*
  * Trap 15 is used for:
  *     - KGDB traps
@@ -297,20 +475,39 @@ _trap2:
  * We just pass it on and let trap() sort it all out
  */
 _trap15:
  * We just pass it on and let trap() sort it all out
  */
 _trap15:
-       clrw    sp@-
+       clrl    sp@-
        moveml  #0xFFFF,sp@-
        moveml  #0xFFFF,sp@-
+#ifdef KGDB
+       moveq   #T_TRAP15,d0
+       movw    sp@(FR_HW),d1           | get PSW
+       andw    #PSL_S,d1               | from user mode?
+       jeq     fault                   | yes, just a regular fault
+       movl    d0,sp@-
+       .globl  _kgdb_trap_glue
+       jbsr    _kgdb_trap_glue         | returns if no debugger
+       addl    #4,sp
+#endif
        moveq   #T_TRAP15,d0
        moveq   #T_TRAP15,d0
-       jra     _fault
+       jra     fault
 
 /*
  * Hit a breakpoint (trap 1 or 2) instruction.
  * Push the code and treat as a normal fault.
  */
 _trace:
 
 /*
  * Hit a breakpoint (trap 1 or 2) instruction.
  * Push the code and treat as a normal fault.
  */
 _trace:
-       clrw    sp@-
+       clrl    sp@-
        moveml  #0xFFFF,sp@-
        moveml  #0xFFFF,sp@-
+#ifdef KGDB
        moveq   #T_TRACE,d0
        moveq   #T_TRACE,d0
-       jra     _fault
+       movw    sp@(FR_HW),d1           | get SSW
+       andw    #PSL_S,d1               | from user mode?
+       jeq     fault                   | no, regular fault
+       movl    d0,sp@-
+       jbsr    _kgdb_trap_glue         | returns if no debugger
+       addl    #4,sp
+#endif
+       moveq   #T_TRACE,d0
+       jra     fault
 
 /*
  * The sigreturn() syscall comes here.  It requires special handling
 
 /*
  * The sigreturn() syscall comes here.  It requires special handling
@@ -321,37 +518,20 @@ sigreturn:
        lea     sp@(-84),sp             | leave enough space for largest frame
        movl    sp@(84),sp@             | move up current 8 byte frame
        movl    sp@(88),sp@(4)
        lea     sp@(-84),sp             | leave enough space for largest frame
        movl    sp@(84),sp@             | move up current 8 byte frame
        movl    sp@(88),sp@(4)
-       movw    #0xFFFF,sp@-            | default: must clean stack
+       movl    #84,sp@-                | default: adjust by 84 bytes
        moveml  #0xFFFF,sp@-            | save user registers
        movl    usp,a0                  | save the user SP
        moveml  #0xFFFF,sp@-            | save user registers
        movl    usp,a0                  | save the user SP
-       movl    a0,sp@(60)              |   in the savearea
+       movl    a0,sp@(FR_SP)           |   in the savearea
        movl    #SYS_sigreturn,sp@-     | push syscall number
        jbsr    _syscall                | handle it
        addql   #4,sp                   | pop syscall#
        movl    #SYS_sigreturn,sp@-     | push syscall number
        jbsr    _syscall                | handle it
        addql   #4,sp                   | pop syscall#
-       movl    sp@(60),a0              | grab and restore
+       movl    sp@(FR_SP),a0           | grab and restore
        movl    a0,usp                  |   user SP
        movl    a0,usp                  |   user SP
-       lea     sp@(64),a1              | pointer to HW frame
-       tstw    a1@+                    | do we need to clean up stack?
+       lea     sp@(FR_HW),a1           | pointer to HW frame
+       movw    sp@(FR_ADJ),d0          | do we need to adjust the stack?
        jeq     Lsigr1                  | no, just continue
        jeq     Lsigr1                  | no, just continue
-       movb    a1@(6),d0               | grab format byte
-       lsrb    #4,d0                   | get rid of excess
-       cmpb    #10,d0                  | type 10 frame?
-       jne     Lsigr2                  | no, continue
-       movw    #32,d1                  | yes, frame size is 32 bytes
-       jra     Lsigrcp                 | go to it
-Lsigr2:
-       cmpb    #9,d0                   | type 9?
-       jne     Lsigr3                  | no, continue
-       movw    #20,d1                  | yes, frame size is 20 bytes
-       jra     Lsigrcp                 | go to it
-Lsigr3:
-       cmpb    #2,d0                   | type 2?
-       jne     Lsigr4                  | no, continue
-       movw    #12,d1                  | yes, frame size is 12 bytes
-       jra     Lsigrcp                 | go to it
-Lsigr4:
-       movw    #8,d1                   | must be type 0/1, size is 8 bytes
-Lsigrcp:
+       moveq   #92,d1                  | total size
+       subw    d0,d1                   |  - hole size = frame size
        lea     a1@(92),a0              | destination
        addw    d1,a1                   | source
        lsrw    #1,d1                   | convert to word count
        lea     a1@(92),a0              | destination
        addw    d1,a1                   | source
        lsrw    #1,d1                   | convert to word count
@@ -361,7 +541,7 @@ Lsigrlp:
        dbf     d1,Lsigrlp              | continue
        movl    a0,a1                   | new HW frame base
 Lsigr1:
        dbf     d1,Lsigrlp              | continue
        movl    a0,a1                   | new HW frame base
 Lsigr1:
-       movl    a1,sp@(60)              | new SP value
+       movl    a1,sp@(FR_SP)           | new SP value
        moveml  sp@+,#0x7FFF            | restore user registers
        movl    sp@,sp                  | and our SP
        jra     rei                     | all done
        moveml  sp@+,#0x7FFF            | restore user registers
        movl    sp@,sp                  | and our SP
        jra     rei                     | all done
@@ -374,13 +554,14 @@ Lsigr1:
  *     Level 0:        Spurious: ignored.
  *     Level 1:        HIL
  *     Level 2:
  *     Level 0:        Spurious: ignored.
  *     Level 1:        HIL
  *     Level 2:
- *     Level 3:        Internal HP-IB
+ *     Level 3:        Internal HP-IB, DCM
  *     Level 4:        "Fast" HP-IBs, SCSI
  *     Level 4:        "Fast" HP-IBs, SCSI
- *     Level 5:        DMA, Ethernet, Built-in RS232
+ *     Level 5:        DMA, Ethernet, Built-in RS232 (DCA)
  *     Level 6:        Clock
  *     Level 7:        Non-maskable: parity errors, RESET key
  */
  *     Level 6:        Clock
  *     Level 7:        Non-maskable: parity errors, RESET key
  */
-       .globl  _hilint, _intrhand, _hardclock, _nmihand
+       .globl  _hilint, _intrhand, _hardclock, _nmihand, _dmaintr
+       .globl  _dcafastservice
 
 _spurintr:
        addql   #1,_intrcnt+0
 
 _spurintr:
        addql   #1,_intrcnt+0
@@ -388,36 +569,47 @@ _spurintr:
        jra     rei
 
 _lev1intr:
        jra     rei
 
 _lev1intr:
-       addql   #1,_intrcnt+4
-       clrw    sp@-
        moveml  #0xC0C0,sp@-
        jbsr    _hilint
        moveml  sp@+,#0x0303
        moveml  #0xC0C0,sp@-
        jbsr    _hilint
        moveml  sp@+,#0x0303
-       addql   #2,sp
+       addql   #1,_intrcnt+4
        addql   #1,_cnt+V_INTR
        jra     rei
 
        addql   #1,_cnt+V_INTR
        jra     rei
 
-/* check for DMA first to reduce overhead */
+/*
+ * Check for unbuffered serial port (DCA) interrupts first in an attempt
+ * to minimize received character lossage.  Then we check for DMA activity
+ * to reduce overhead there.
+ */
 _lev5intr:
 _lev5intr:
-       clrw    sp@-
        moveml  #0xC0C0,sp@-
        moveml  #0xC0C0,sp@-
-       jbsr    _dmaintr
-       tstl    d0
-       jeq     Lnotdma
-       addql   #1,_intrcnt+24
+       tstl    _dcafastservice         | unbuffered port active?
+       jeq     Ltrydma                 | no, check DMA
+       clrl    sp@-                    | yes, check DCA port 0
+       jbsr    _dcaintr                |    first to avoid overflow
+       addql   #4,sp
+       tstl    d0                      | did it belong to DCA?
+       jeq     Ltrydma                 | no, go try DMA
+       moveml  sp@+,#0x0303
+       addql   #1,_intrcnt+20
+       addql   #1,_cnt+V_INTR
+       jra     rei
+Ltrydma:
+       jbsr    _dmaintr                | check DMA channels
+       tstl    d0                      | was it ours?
+       jeq     Lnotdma                 | no, go poll other devices
        moveml  sp@+,#0x0303
        moveml  sp@+,#0x0303
-       addql   #2,sp
+       addql   #1,_intrcnt+24
        addql   #1,_cnt+V_INTR
        jra     rei
 
 _lev2intr:
 _lev3intr:
 _lev4intr:
        addql   #1,_cnt+V_INTR
        jra     rei
 
 _lev2intr:
 _lev3intr:
 _lev4intr:
-       clrw    sp@-
        moveml  #0xC0C0,sp@-
 Lnotdma:
        lea     _intrcnt,a0
        moveml  #0xC0C0,sp@-
 Lnotdma:
        lea     _intrcnt,a0
-       movw    sp@(24),d0              | use vector offset
+       movw    sp@(22),d0              | use vector offset
        andw    #0xfff,d0               |   sans frame type
        addql   #1,a0@(-0x60,d0:w)      |     to increment apropos counter
        movw    sr,sp@-                 | push current SR value
        andw    #0xfff,d0               |   sans frame type
        addql   #1,a0@(-0x60,d0:w)      |     to increment apropos counter
        movw    sr,sp@-                 | push current SR value
@@ -425,117 +617,99 @@ Lnotdma:
        jbsr    _intrhand               | handle interrupt
        addql   #4,sp                   | pop SR
        moveml  sp@+,#0x0303
        jbsr    _intrhand               | handle interrupt
        addql   #4,sp                   | pop SR
        moveml  sp@+,#0x0303
-       addql   #2,sp
        addql   #1,_cnt+V_INTR
        jra     rei
 
 _lev6intr:
        addql   #1,_cnt+V_INTR
        jra     rei
 
 _lev6intr:
-       clrw    sp@-
-       moveml  #0xC0C0,sp@-
-#ifdef DEBUG
-       .globl  _panicstr, _regdump, _panic
-       tstl    timebomb                | set to go off?
-       jeq     Lnobomb                 | no, skip it
-       subql   #1,timebomb             | decrement
-       jne     Lnobomb                 | not ready to go off
-       moveml  sp@+,#0x0303            | temporarily restore regs
-       jra     Luseours                | go die
-Lnobomb:
-       cmpl    #_u+NBPG,sp             | our we still in stack pages?
+#ifdef STACKCHECK
+       .globl  _panicstr,_badkstack
+       cmpl    #_kstack+NBPG,sp        | are we still in stack page?
        jcc     Lstackok                | yes, continue normally
        jcc     Lstackok                | yes, continue normally
+       tstl    _curproc                | if !curproc could have switch_exited,
+       jeq     Lstackok                |     might be on tmpstk
        tstl    _panicstr               | have we paniced?
        jne     Lstackok                | yes, do not re-panic
        tstl    _panicstr               | have we paniced?
        jne     Lstackok                | yes, do not re-panic
-       lea     tmpstk,sp               | no, switch to tmpstk
-Luseours:
-       moveml  #0xFFFF,sp@-            | push all registers
-       movl    sp,a0                   | remember this spot
-       movl    #256,sp@-               | longword count
-       movl    a0,sp@-                 | and reg pointer
-       jbsr    _regdump                | dump core
-       addql   #8,sp                   | pop params
-       movl    #Lstkrip,sp@-           | push panic message
-       jbsr    _panic                  | ES and D
-Lstkrip:
-       .asciz  "k-stack overflow"
-       .even
+       movl    sp@(4),tmpstk-4         | no, copy common
+       movl    sp@,tmpstk-8            |  frame info
+       movl    sp,tmpstk-16            | no, save original SP
+       lea     tmpstk-16,sp            | switch to tmpstk
+       moveml  #0xFFFE,sp@-            | push remaining registers
+       movl    #1,sp@-                 | is an overflow
+       jbsr    _badkstack              | badkstack(1, frame)
+       addql   #4,sp
+       moveml  sp@+,#0x7FFF            | restore most registers
+       movl    sp@,sp                  | and SP
 Lstackok:
 #endif
 Lstackok:
 #endif
+       moveml  #0xC0C0,sp@-            | save scratch registers
        CLKADDR(a0)
        movb    a0@(CLKSR),d0           | read clock status
        CLKADDR(a0)
        movb    a0@(CLKSR),d0           | read clock status
-#ifdef PROFTIMER
-       .globl  _profon
-       tstb    _profon                 | profile clock on?
-       jeq     Ltimer1                 | no, then must be timer1 interrupt
+Lclkagain:
+       btst    #0,d0                   | clear timer1 int immediately to
+       jeq     Lnotim1                 |  minimize chance of losing another
+       movpw   a0@(CLKMSB1),d1         |  due to statintr processing delay
+Lnotim1:
        btst    #2,d0                   | timer3 interrupt?
        btst    #2,d0                   | timer3 interrupt?
-       jeq     Ltimer1                 | no, must be timer1
-       movb    a0@(CLKMSB3),d1         | clear timer3 interrupt
-       lea     sp@(16),a1              | get pointer to PS
-#ifdef GPROF
-       .globl  _profclock
-       movl    d0,sp@-                 | save status so jsr will not clobber
-       movl    a1@,sp@-                | push padded PS
-       movl    a1@(4),sp@-             | push PC
-       jbsr    _profclock              | profclock(pc, ps)
-       addql   #8,sp                   | pop params
-#else
-       btst    #5,a1@(2)               | saved PS in user mode?
-       jne     Lttimer1                | no, go check timer1
-       tstl    _u+U_PROFSCALE          | process being profiled?
-       jeq     Lttimer1                | no, go check timer1
-       movl    d0,sp@-                 | save status so jsr will not clobber
-       movl    #1,sp@-
-       movl    #_u+U_PROF,sp@-
-       movl    a1@(4),sp@-
-       jbsr    _addupc                 | addupc(pc, &u.u_prof, 1)
-       lea     sp@(12),sp              | pop params
-#endif
-       addql   #1,_intrcnt+32          | add another profile clock interrupt
-       movl    sp@+,d0                 | get saved clock status
+       jeq     Lnotim3                 | no, skip statclock
+       movpw   a0@(CLKMSB3),d1         | clear timer3 interrupt
+       addql   #1,_intrcnt+32          | count clock interrupts
+       lea     sp@(16),a1              | a1 = &clockframe
+       movl    d0,sp@-                 | save status
+       movl    a1,sp@-
+       jbsr    _statintr               | statintr(&frame)
+       addql   #4,sp
+       movl    sp@+,d0                 | restore pre-statintr status
        CLKADDR(a0)
        CLKADDR(a0)
-Lttimer1:
+Lnotim3:
        btst    #0,d0                   | timer1 interrupt?
        btst    #0,d0                   | timer1 interrupt?
-       jeq     Ltimend                 | no, check state of kernel profiling
-Ltimer1:
-#endif
-       movb    a0@(CLKMSB1),d1         | clear timer1 interrupt
-       lea     sp@(16),a1              | get pointer to PS
-       movl    a1@,sp@-                | push padded PS
-       movl    a1@(4),sp@-             | push PC
-       jbsr    _hardclock              | call generic clock int routine
-       addql   #8,sp                   | pop params
-       addql   #1,_intrcnt+28          | add another system clock interrupt
-#ifdef PROFTIMER
-Ltimend:
-#ifdef GPROF
-       .globl  _profiling, _startprofclock
-       tstl    _profiling              | kernel profiling desired?
-       jne     Ltimdone                | no, all done
-       bset    #7,_profon              | mark continuous timing
-       jne     Ltimdone                | was already enabled, all done
-       jbsr    _startprofclock         | else turn it on
-Ltimdone:
-#endif
+       jeq     Lrecheck                | no, skip hardclock
+       addql   #1,_intrcnt+28          | count hardclock interrupts
+       lea     sp@(16),a1              | a1 = &clockframe
+       movl    a1,sp@-
+#ifdef USELEDS
+       .globl  _ledaddr, _inledcontrol, _ledcontrol, _hz
+       tstl    _ledaddr                | using LEDs?
+       jeq     Lnoled0                 | no, skip this code
+       movl    heartbeat,d0            | get tick count
+       addql   #1,d0                   |  increment
+       movl    _hz,d1
+       lsrl    #1,d1                   | throb twice a second
+       cmpl    d0,d1                   | are we there yet?
+       jne     Lnoled1                 | no, nothing to do
+       tstl    _inledcontrol           | already updating LEDs?
+       jne     Lnoled2                 | yes, skip it
+       movl    #LED_PULSE,sp@-
+       movl    #LED_DISK+LED_LANRCV+LED_LANXMT,sp@-
+       clrl    sp@-
+       jbsr    _ledcontrol             | toggle pulse, turn all others off
+       lea     sp@(12),sp
+Lnoled2:
+       movql   #0,d0
+Lnoled1:
+       movl    d0,heartbeat
+Lnoled0:
 #endif
 #endif
-       moveml  sp@+,#0x0303            | restore scratch regs
-       addql   #2,sp                   | pop pad word
+       jbsr    _hardclock              | hardclock(&frame)
+       addql   #4,sp
+       CLKADDR(a0)
+Lrecheck:
        addql   #1,_cnt+V_INTR          | chalk up another interrupt
        addql   #1,_cnt+V_INTR          | chalk up another interrupt
+       movb    a0@(CLKSR),d0           | see if anything happened
+       jmi     Lclkagain               |  while we were in hardclock/statintr
+       moveml  sp@+,#0x0303            | restore scratch registers
        jra     rei                     | all done
 
 _lev7intr:
        jra     rei                     | all done
 
 _lev7intr:
-#ifdef PROFTIMER
        addql   #1,_intrcnt+36
        addql   #1,_intrcnt+36
-#else
-       addql   #1,_intrcnt+32
-#endif
-       clrw    sp@-                    | pad SR to longword
+       clrl    sp@-
        moveml  #0xFFFF,sp@-            | save registers
        movl    usp,a0                  | and save
        moveml  #0xFFFF,sp@-            | save registers
        movl    usp,a0                  | and save
-       movl    a0,sp@(60)              |   the user stack pointer
+       movl    a0,sp@(FR_SP)           |   the user stack pointer
        jbsr    _nmihand                | call handler
        jbsr    _nmihand                | call handler
-       movl    sp@(60),a0              | restore
+       movl    sp@(FR_SP),a0           | restore
        movl    a0,usp                  |   user SP
        moveml  sp@+,#0x7FFF            | and remaining registers
        movl    a0,usp                  |   user SP
        moveml  sp@+,#0x7FFF            | and remaining registers
-       addql   #6,sp                   | pop SSP and align word
+       addql   #8,sp                   | pop SP and stack adjust
        jra     rei                     | all done
 
 /*
        jra     rei                     | all done
 
 /*
@@ -545,61 +719,60 @@ _lev7intr:
  * (profiling, scheduling) and software interrupts (network, softclock).
  * We check for ASTs first, just like the VAX.  To avoid excess overhead
  * the T_ASTFLT handling code will also check for software interrupts so we
  * (profiling, scheduling) and software interrupts (network, softclock).
  * We check for ASTs first, just like the VAX.  To avoid excess overhead
  * the T_ASTFLT handling code will also check for software interrupts so we
- * do not have to do it here.
+ * do not have to do it here.  After identifing that we need an AST we
+ * drop the IPL to allow device interrupts.
  *
  * This code is complicated by the fact that sendsig may have been called
  *
  * This code is complicated by the fact that sendsig may have been called
- * necessitating a stack cleanup.  A cleanup should only be needed at this
- * point for coprocessor mid-instruction frames (type 9), but we also test
- * for bus error frames (type 10 and 11).
+ * necessitating a stack cleanup.
  */
        .comm   _ssir,1
  */
        .comm   _ssir,1
+       .globl  _astpending
 rei:
 rei:
-#ifdef DEBUG
+#ifdef STACKCHECK
        tstl    _panicstr               | have we paniced?
        tstl    _panicstr               | have we paniced?
-       jne     Ldorte                  | yes, do not make matters worse
+       jne     Ldorte1                 | yes, do not make matters worse
 #endif
 #endif
-       btst    #PCB_ASTB,_u+PCB_FLAGS+1| AST pending?
+       tstl    _astpending             | AST pending?
        jeq     Lchksir                 | no, go check for SIR
        jeq     Lchksir                 | no, go check for SIR
+Lrei1:
        btst    #5,sp@                  | yes, are we returning to user mode?
        jne     Lchksir                 | no, go check for SIR
        btst    #5,sp@                  | yes, are we returning to user mode?
        jne     Lchksir                 | no, go check for SIR
-       clrw    sp@-                    | pad SR to longword
+       movw    #PSL_LOWIPL,sr          | lower SPL
+       clrl    sp@-                    | stack adjust
        moveml  #0xFFFF,sp@-            | save all registers
        movl    usp,a1                  | including
        moveml  #0xFFFF,sp@-            | save all registers
        movl    usp,a1                  | including
-       movl    a1,sp@(60)              |    the users SP
+       movl    a1,sp@(FR_SP)           |    the users SP
        clrl    sp@-                    | VA == none
        clrl    sp@-                    | code == none
        movl    #T_ASTFLT,sp@-          | type == async system trap
        jbsr    _trap                   | go handle it
        lea     sp@(12),sp              | pop value args
        clrl    sp@-                    | VA == none
        clrl    sp@-                    | code == none
        movl    #T_ASTFLT,sp@-          | type == async system trap
        jbsr    _trap                   | go handle it
        lea     sp@(12),sp              | pop value args
-       movl    sp@(60),a0              | restore
-       movl    a0,usp                  |   user SP
-       moveml  sp@+,#0x7FFF            | and all remaining registers
-       addql   #4,sp                   | toss SSP
-       tstw    sp@+                    | do we need to clean up stack?
-       jeq     Ldorte                  | no, just continue
-       btst    #7,sp@(6)               | type 9/10/11 frame?
-       jeq     Ldorte                  | no, nothing to do
-       btst    #5,sp@(6)               | type 9?
-       jne     Last1                   | no, skip
-       movw    sp@,sp@(12)             | yes, push down SR
-       movl    sp@(2),sp@(14)          | and PC
-       clrw    sp@(18)                 | and mark as type 0 frame
-       lea     sp@(12),sp              | clean the excess
-       jra     Ldorte                  | all done
-Last1:
-       btst    #4,sp@(6)               | type 10?
-       jne     Last2                   | no, skip
-       movw    sp@,sp@(24)             | yes, push down SR
-       movl    sp@(2),sp@(26)          | and PC
-       clrw    sp@(30)                 | and mark as type 0 frame
-       lea     sp@(24),sp              | clean the excess
-       jra     Ldorte                  | all done
-Last2:
-       movw    sp@,sp@(84)             | type 11, push down SR
-       movl    sp@(2),sp@(86)          | and PC
-       clrw    sp@(90)                 | and mark as type 0 frame
-       lea     sp@(84),sp              | clean the excess
-       jra     Ldorte                  | all done
+       movl    sp@(FR_SP),a0           | restore user SP
+       movl    a0,usp                  |   from save area
+       movw    sp@(FR_ADJ),d0          | need to adjust stack?
+       jne     Laststkadj              | yes, go to it
+       moveml  sp@+,#0x7FFF            | no, restore most user regs
+       addql   #8,sp                   | toss SP and stack adjust
+#ifdef STACKCHECK
+       jra     Ldorte
+#else
+       rte                             | and do real RTE
+#endif
+Laststkadj:
+       lea     sp@(FR_HW),a1           | pointer to HW frame
+       addql   #8,a1                   | source pointer
+       movl    a1,a0                   | source
+       addw    d0,a0                   |  + hole size = dest pointer
+       movl    a1@-,a0@-               | copy
+       movl    a1@-,a0@-               |  8 bytes
+       movl    a0,sp@(FR_SP)           | new SSP
+       moveml  sp@+,#0x7FFF            | restore user registers
+       movl    sp@,sp                  | and our SP
+#ifdef STACKCHECK
+       jra     Ldorte
+#else
+       rte                             | and do real RTE
+#endif
 Lchksir:
        tstb    _ssir                   | SIR pending?
        jeq     Ldorte                  | no, all done
 Lchksir:
        tstb    _ssir                   | SIR pending?
        jeq     Ldorte                  | no, all done
@@ -612,34 +785,76 @@ Lgotsir:
        movw    #SPL1,sr                | prevent others from servicing int
        tstb    _ssir                   | too late?
        jeq     Ldorte                  | yes, oh well...
        movw    #SPL1,sr                | prevent others from servicing int
        tstb    _ssir                   | too late?
        jeq     Ldorte                  | yes, oh well...
-       clrw    sp@-                    | pad SR to longword
+       clrl    sp@-                    | stack adjust
        moveml  #0xFFFF,sp@-            | save all registers
        movl    usp,a1                  | including
        moveml  #0xFFFF,sp@-            | save all registers
        movl    usp,a1                  | including
-       movl    a1,sp@(60)              |    the users SP
+       movl    a1,sp@(FR_SP)           |    the users SP
        clrl    sp@-                    | VA == none
        clrl    sp@-                    | code == none
        movl    #T_SSIR,sp@-            | type == software interrupt
        jbsr    _trap                   | go handle it
        lea     sp@(12),sp              | pop value args
        clrl    sp@-                    | VA == none
        clrl    sp@-                    | code == none
        movl    #T_SSIR,sp@-            | type == software interrupt
        jbsr    _trap                   | go handle it
        lea     sp@(12),sp              | pop value args
-       movl    sp@(60),a0              | restore
+       movl    sp@(FR_SP),a0           | restore
        movl    a0,usp                  |   user SP
        moveml  sp@+,#0x7FFF            | and all remaining registers
        movl    a0,usp                  |   user SP
        moveml  sp@+,#0x7FFF            | and all remaining registers
-       addql   #6,sp                   | pop SSP and align word
+       addql   #8,sp                   | pop SP and stack adjust
+#ifdef STACKCHECK
+       jra     Ldorte
+#else
        rte
        rte
+#endif
 Lnosir:
        movl    sp@+,d0                 | restore scratch register
 Ldorte:
 Lnosir:
        movl    sp@+,d0                 | restore scratch register
 Ldorte:
+#ifdef STACKCHECK
+       movw    #SPL6,sr                | avoid trouble
+       btst    #5,sp@                  | are we returning to user mode?
+       jne     Ldorte1                 | no, skip it
+       movl    a6,tmpstk-20
+       movl    d0,tmpstk-76
+       moveq   #0,d0
+       movb    sp@(6),d0               | get format/vector
+       lsrl    #3,d0                   | convert to index
+       lea     _exframesize,a6         |  into exframesize
+       addl    d0,a6                   |  to get pointer to correct entry
+       movw    a6@,d0                  | get size for this frame
+       addql   #8,d0                   | adjust for unaccounted for bytes
+       lea     _kstackatbase,a6        | desired stack base
+       subl    d0,a6                   |   - frame size == our stack
+       cmpl    a6,sp                   | are we where we think?
+       jeq     Ldorte2                 | yes, skip it
+       lea     tmpstk,a6               | will be using tmpstk
+       movl    sp@(4),a6@-             | copy common
+       movl    sp@,a6@-                |   frame info
+       clrl    a6@-
+       movl    sp,a6@-                 | save sp
+       subql   #4,a6                   | skip over already saved a6
+       moveml  #0x7FFC,a6@-            | push remaining regs (d0/a6/a7 done)
+       lea     a6@(-4),sp              | switch to tmpstk (skip saved d0)
+       clrl    sp@-                    | is an underflow
+       jbsr    _badkstack              | badkstack(0, frame)
+       addql   #4,sp
+       moveml  sp@+,#0x7FFF            | restore most registers
+       movl    sp@,sp                  | and SP
+       rte
+Ldorte2:
+       movl    tmpstk-76,d0
+       movl    tmpstk-20,a6
+Ldorte1:
+#endif
        rte                             | real return
 
 /*
        rte                             | real return
 
 /*
- * Kernel access to the current processes user struct is via a fixed
+ * Kernel access to the current processes kernel stack is via a fixed
  * virtual address.  It is at the same address as in the users VA space.
  * virtual address.  It is at the same address as in the users VA space.
- * Umap contains the KVA of the first of UPAGES PTEs mapping VA _u.
+ * Umap contains the KVA of the first of UPAGES PTEs mapping VA _kstack.
  */
        .data
  */
        .data
-       .set    _u,USRSTACK
+       .set    _kstack,USRSTACK
+       .set    _kstackatbase,USRSTACK+UPAGES*NBPG-4
+       .globl  _kstackatbase
 _Umap: .long   0
 _Umap: .long   0
-       .globl  _u, _Umap
+       .globl  _kstack, _Umap
 
 #define        RELOC(var, ar)  \
        lea     var,ar; \
 
 #define        RELOC(var, ar)  \
        lea     var,ar; \
@@ -669,12 +884,12 @@ start:
        movc    d0,cacr                 | clear and disable on-chip cache(s)
 
 /* determine our CPU/MMU combo - check for all regardless of kernel config */
        movc    d0,cacr                 | clear and disable on-chip cache(s)
 
 /* determine our CPU/MMU combo - check for all regardless of kernel config */
-       movl    #IOBASE+MMUBASE,a1
+       movl    #INTIOBASE+MMUBASE,a1
        movl    #0x200,d0               | data freeze bit
        movc    d0,cacr                 |   only exists on 68030
        movc    cacr,d0                 | read it back
        tstl    d0                      | zero?
        movl    #0x200,d0               | data freeze bit
        movc    d0,cacr                 |   only exists on 68030
        movc    cacr,d0                 | read it back
        tstl    d0                      | zero?
-       jeq     Lis68020                | yes, we have 68020
+       jeq     Lnot68030               | yes, we have 68020/68040
        RELOC(_mmutype, a0)             | no, we have 68030
        movl    #-1,a0@                 | set to reflect 68030 PMMU
        RELOC(_machineid, a0)
        RELOC(_mmutype, a0)             | no, we have 68030
        movl    #-1,a0@                 | set to reflect 68030 PMMU
        RELOC(_machineid, a0)
@@ -702,6 +917,32 @@ Lhaspac:
        RELOC(_ectype, a0)
        movl    #-1,a0@                 | also has a physical address cache
        jra     Lstart1
        RELOC(_ectype, a0)
        movl    #-1,a0@                 | also has a physical address cache
        jra     Lstart1
+Lnot68030:
+       bset    #31,d0                  | data cache enable bit
+       movc    d0,cacr                 |   only exists on 68040
+       movc    cacr,d0                 | read it back
+       tstl    d0                      | zero?
+       beq     Lis68020                | yes, we have 68020
+       moveq   #0,d0                   | now turn it back off
+       movec   d0,cacr                 |   before we access any data
+       RELOC(_mmutype, a0)
+       movl    #-2,a0@                 | with a 68040 MMU
+       RELOC(_ectype, a0)
+       movl    #0,a0@                  | and no cache (for now XXX)
+#ifdef HPFPLIB
+       RELOC(_processor, a0)
+       movl    #3,a0@                  | HP-UX style processor id
+#endif
+       RELOC(_machineid, a0)
+       movl    a1@(MMUCMD),d0          | read MMU register
+       lsrl    #8,d0                   | get apparent ID
+       cmpb    #6,d0                   | id == 6?
+       jeq     Lis33mhz                | yes, we have a 433s
+       movl    #7,a0@                  | no, we have a 380/425t
+       jra     Lstart1
+Lis33mhz:
+       movl    #8,a0@                  | 433s (XXX 425s returns same ID, ugh!)
+       jra     Lstart1
 Lis68020:
        movl    #1,a1@(MMUCMD)          | a 68020, write HP MMU location
        movl    a1@(MMUCMD),d0          | read it back
 Lis68020:
        movl    #1,a1@(MMUCMD)          | a 68020, write HP MMU location
        movl    a1@(MMUCMD),d0          | read it back
@@ -728,216 +969,29 @@ Lstart1:
        moveq   #FC_USERD,d0            | user space
        movc    d0,sfc                  |   as source
        movc    d0,dfc                  |   and destination of transfers
        moveq   #FC_USERD,d0            | user space
        movc    d0,sfc                  |   as source
        movc    d0,dfc                  |   and destination of transfers
-
-/*
- * Allocate kernel segment/page table resources.
- *     a5 contains the PA of lowest RAM page
- *     a4 contains the PA of first available page at any time
- *     d5 contains the VA of first available page at any time
- *        (since we assume a zero load point, it is also the size of
- *        allocated space at any time)
- * We assume (i.e. do not check) that the initial page table size
- * (Sysptsize) is big enough to map everything we allocate here.
- *
- * We allocate the DIO map here since the 320/350 MMU registers are
- * mapped in this range and it would be nice to be able to access them
- * after the MMU is turned on.
- */
-       .globl  _Sysseg, _Sysmap, _Sysptmap, _Sysptsize
+/* initialize memory sizes (for pmap_bootstrap) */
+       movl    #MAXADDR,d1             | last page
+       moveq   #PGSHIFT,d2
+       lsrl    d2,d1                   | convert to page (click) number
+       RELOC(_maxmem, a0)
+       movl    d1,a0@                  | save as maxmem
+       movl    a5,d0                   | lowram value from ROM via boot
+       lsrl    d2,d0                   | convert to page number
+       subl    d0,d1                   | compute amount of RAM present
+       RELOC(_physmem, a0)
+       movl    d1,a0@                  | and physmem
+/* configure kernel and proc0 VA space so we can get going */
+       .globl  _Sysseg, _pmap_bootstrap, _avail_start
        movl    #_end,d5                | end of static kernel text/data
        addl    #NBPG-1,d5
        andl    #PG_FRAME,d5            | round to a page
        movl    d5,a4
        movl    #_end,d5                | end of static kernel text/data
        addl    #NBPG-1,d5
        andl    #PG_FRAME,d5            | round to a page
        movl    d5,a4
-       addl    a5,a4
-/* allocate kernel segment table */
-       RELOC(_Sysseg, a0)
-       movl    d5,a0@                  | remember VA for pmap module
-       movl    a4,sp@-                 | remember PA for loading MMU
-       addl    #NBPG,a4
-       addl    #NBPG,d5
-/* allocate initial page table pages (including IO map) */
-       RELOC(_Sysptsize, a0)
-       movl    a0@,d0                  | initial system PT size (pages)
-       addl    #(IOMAPSIZE+NPTEPG-1)/NPTEPG,d0 | add pages for IO map
-       movl    #PGSHIFT,d1
-       lsll    d1,d0                   | convert to bytes
-       movl    a4,sp@-                 | remember PA for ST load
-       addl    d0,a4
-       addl    d0,d5
-/* allocate kernel page table map */
-       RELOC(_Sysptmap, a0)
-       movl    d5,a0@                  | remember VA for pmap module
-       movl    a4,sp@-                 | remember PA for PT map load
-       addl    #NBPG,a4
-       addl    #NBPG,d5
-/* compute KVA of Sysptmap; mapped after page table pages */
-       movl    d0,d2                   | remember PT size (bytes)
-       moveq   #SG_ISHIFT-PGSHIFT,d1
-       lsll    d1,d0                   | page table size serves as seg index
-       RELOC(_Sysmap, a0)
-       movl    d0,a0@                  | remember VA for pmap module
-/* initialize ST and PT map: PT pages + PT map */
-       movl    sp@+,a1                 | PT map PA
-       movl    sp@+,d4                 | start of PT pages
-       movl    sp@+,a0                 | ST phys addr
-       lea     a0@(NBPG-4),a2          | (almost) end of ST
-       movl    d4,d3
-       orl     #SG_RW+SG_V,d4          | create proto STE for ST
-       orl     #PG_RW+PG_CI+PG_V,d3    | create proto PTE for PT map
-List1:
-       movl    d4,a0@+
-       movl    d3,a1@+
-       addl    #NBPG,d4
-       addl    #NBPG,d3
-       cmpl    a4,d4                   | sleezy, but works ok
-       jcs     List1
-/* initialize ST and PT map: invalidate up to last entry */
-List2:
-       movl    #SG_NV,a0@+
-       movl    #PG_NV,a1@+
-       cmpl    a2,a0
-       jcs     List2
-/*
- * Portions of the last segment of KVA space (0xFFF00000 - 0xFFFFFFFF)
- * are mapped for a couple of purposes. 0xFFF00000 for UPAGES is used
- * for mapping the current process u-area (u + kernel stack).  The
- * very last page (0xFFFFF000) is mapped to the last physical page of
- * RAM to give us a region in which PA == VA.  We use this page for
- * enabling/disabling mapping.
- */
-       movl    a4,d1                   | grab next available for PT page
-       andl    #SG_FRAME,d1            | mask to frame number
-       orl     #SG_RW+SG_V,d1          | RW and valid
-       movl    d1,a0@+                 | store in last ST entry
-       movl    a0,a2                   | remember addr for PT load
-       andl    #PG_FRAME,d1
-       orl     #PG_RW+PG_V,d1          | convert to PTE
-       movl    d1,a1@+                 | store in PT map
-       movl    a4,a0                   | physical beginning of PT page
-       lea     a0@(NBPG-4),a1          | (almost) end of page
-Lispt7:
-       movl    #PG_NV,a0@+             | invalidate
-       cmpl    a1,a0
-       jcs     Lispt7
-       movl    #MAXADDR,d1             | get last phys page addr
-       andl    #PG_FRAME,d1
-       orl     #PG_RW+PG_V,d1
-       movl    d1,a0@+                 | map to last virt page
-       addl    #NBPG,a4
-       addl    #NBPG,d5
-/* record KVA at which to access current u-area PTEs */
-       RELOC(_Sysmap, a0)
-       movl    a0@,d0                  | get system PT address
-       addl    #NPTEPG*NBPG,d0         | end of system PT
-       subl    #HIGHPAGES*4,d0         | back up to first PTE for u-area
-       RELOC(_Umap, a0)
-       movl    d0,a0@                  | remember location
-/* initialize page table pages */
-       movl    a2,a0                   | end of ST is start of PT
-       addl    d2,a2                   | add size to get end of PT
-/* text pages are read-only */
-       clrl    d0                      | assume load at VA 0
-       movl    a5,d1                   | get load PA
-       andl    #PG_FRAME,d1            | convert to a page frame
-#ifdef KGDB
-       orl     #PG_RW+PG_V,d1          | XXX: RW for now
-#else
-       orl     #PG_RO+PG_V,d1          | create proto PTE
-#endif
-       movl    #_etext,a1              | go til end of text
-Lipt1:
-       movl    d1,a0@+                 | load PTE
-       addl    #NBPG,d1                | increment page frame number
-       addl    #NBPG,d0                | and address counter
-       cmpl    a1,d0                   | done yet?
-       jcs     Lipt1                   | no, keep going
-/* data, bss and dynamic tables are read/write */
-       andl    #PG_FRAME,d1            | mask out old prot bits
-       orl     #PG_RW+PG_V,d1          | mark as valid and RW
-       movl    d5,a1                   | go til end of data allocated so far
-       addl    #(UPAGES+1)*NBPG,a1     | and proc0 PT/u-area (to be allocated)
-Lipt2:
-       movl    d1,a0@+                 | load PTE
-       addl    #NBPG,d1                | increment page frame number
-       addl    #NBPG,d0                | and address counter
-       cmpl    a1,d0                   | done yet?
-       jcs     Lipt2                   | no, keep going
-/* invalidate remainder of kernel PT */
-       movl    a2,a1                   | end of PT
-Lipt3:
-       movl    #PG_NV,a0@+             | invalidate PTE
-       cmpl    a1,a0                   | done yet?
-       jcs     Lipt3                   | no, keep going
-/* go back and validate IO PTEs at end of allocated PT space */
-       movl    a2,a0                   | end of allocated PT space
-       subl    #IOMAPSIZE*4,a0         | back up IOMAPSIZE PTEs
-       movl    #IOBASE,d1              | physical IO base
-       orl     #PG_RW+PG_CI+PG_V,d1    | create proto PTE
-Lipt4:
-       movl    d1,a0@+                 | load PTE
-       addl    #NBPG,d1                | increment page frame number
-       cmpl    a2,a0                   | done yet?
-       jcs     Lipt4                   | no, keep going
-/* record base KVA of IO space which is just before Sysmap */
-       RELOC(_Sysmap, a0)
-       movl    a0@,d0                  | Sysmap VA
-       subl    #IOMAPSIZE*NBPG,d0      | Back up size of IO space
-       RELOC(_DIObase, a0)
-       movl    d0,a0@
-/* also record base of clock and MMU registers for fast access */
-       addl    #CLKBASE,d0
-       RELOC(_CLKbase, a0)
-       movl    d0,a0@
-       subl    #CLKBASE,d0
-       addl    #MMUBASE,d0
-       RELOC(_MMUbase, a0)
-       movl    d0,a0@
-
-/*
- * Setup page table for process 0.
- *
- * We set up page table access for the kernel via Usrptmap (usrpt)
- * and access to the u-area itself via Umap (u).  First available
- * page (VA: d5, PA: a4) is used for proc0 page table.  Next UPAGES
- * pages following are for u-area.
- */
-       movl    a4,d0
-       movl    d0,d1
-       andl    #PG_FRAME,d1            | mask to page frame number
-       orl     #PG_RW+PG_V,d1          | RW and valid
-       movl    d1,d4                   | remember for later Usrptmap load
-       movl    d0,a0                   | base of proc0 PT
-       addl    #NBPG,d0                | plus one page yields base of u-area
-       movl    d0,a2                   |   and end of PT
-       addl    #NBPG,d5                | keep VA in sync
-/* invalidate entire page table */
-Liudot1:
-       movl    #PG_NV,a0@+             | invalidate PTE
-       cmpl    a2,a0                   | done yet?
-       jcs     Liudot1                 | no, keep going
-/* now go back and validate u-area PTEs in PT and in Umap */
-       lea     a0@(-HIGHPAGES*4),a0    | base of PTEs for u-area (p_addr)
-       lea     a0@(UPAGES*4),a1        | end of PTEs for u-area
-       lea     a4@(-HIGHPAGES*4),a3    | u-area PTE base in Umap PT
-       movl    d0,d1                   | get base of u-area
-       andl    #PG_FRAME,d1            | mask to page frame number
-       orl     #PG_RW+PG_V,d1          | add valid and writable
-Liudot2:
-       movl    d1,a0@+                 | validate p_addr PTE
-       movl    d1,a3@+                 | validate u PTE
-       addl    #NBPG,d1                | to next page
-       cmpl    a1,a0                   | done yet?
-       jcs     Liudot2                 | no, keep going
-/* clear process 0 u-area */
-       addl    #NBPG*UPAGES,d0         | end of u-area
-Lclru1:
-       clrl    a2@+                    | clear
-       cmpl    d0,a2                   | done yet?
-       jcs     Lclru1                  | no, keep going
-       movl    a2,a4                   | save phys addr of first avail page
-       RELOC(_proc0paddr, a0)
-       movl    d5,a0@                  | save KVA of proc0 u-area
-       addl    #UPAGES*NBPG,d5         | and virtual addr as well
+       addl    a5,a4                   | convert to PA
+       pea     a5@                     | firstpa
+       pea     a4@                     | nextpa
+       RELOC(_pmap_bootstrap,a0)
+       jbsr    a0@                     | pmap_bootstrap(firstpa, nextpa)
+       addql   #8,sp
 
 /*
  * Prepare to enable MMU.
 
 /*
  * Prepare to enable MMU.
@@ -950,22 +1004,26 @@ Lclru1:
  * Is this all really necessary, or am I paranoid??
  */
        RELOC(_Sysseg, a0)              | system segment table addr
  * Is this all really necessary, or am I paranoid??
  */
        RELOC(_Sysseg, a0)              | system segment table addr
-       movl    a0@,a1                  | read value (a KVA)
-       addl    a5,a1                   | convert to PA
+       movl    a0@,d1                  | read value (a KVA)
+       addl    a5,d1                   | convert to PA
        RELOC(_mmutype, a0)
        tstl    a0@                     | HP MMU?
        jeq     Lhpmmu2                 | yes, skip
        RELOC(_mmutype, a0)
        tstl    a0@                     | HP MMU?
        jeq     Lhpmmu2                 | yes, skip
+       cmpl    #-2,a0@                 | 68040?
+       jne     Lmotommu1               | no, skip
+       .long   0x4e7b1807              | movc d1,srp
+       jra     Lstploaddone
+Lmotommu1:
        RELOC(_protorp, a0)
        movl    #0x80000202,a0@         | nolimit + share global + 4 byte PTEs
        RELOC(_protorp, a0)
        movl    #0x80000202,a0@         | nolimit + share global + 4 byte PTEs
-       movl    a1,a0@(4)               | + segtable address
+       movl    d1,a0@(4)               | + segtable address
        pmove   a0@,srp                 | load the supervisor root pointer
        movl    #0x80000002,a0@         | reinit upper half for CRP loads
        jra     Lstploaddone            | done
 Lhpmmu2:
        pmove   a0@,srp                 | load the supervisor root pointer
        movl    #0x80000002,a0@         | reinit upper half for CRP loads
        jra     Lstploaddone            | done
 Lhpmmu2:
-       movl    a1,d1
        moveq   #PGSHIFT,d2
        lsrl    d2,d1                   | convert to page frame
        moveq   #PGSHIFT,d2
        lsrl    d2,d1                   | convert to page frame
-       movl    d1,IOBASE+MMUBASE+MMUSSTP | load in sysseg table register
+       movl    d1,INTIOBASE+MMUBASE+MMUSSTP | load in sysseg table register
 Lstploaddone:
        lea     MAXADDR,a2              | PA of last RAM page
        RELOC(Lhighcode, a1)            | addr of high code
 Lstploaddone:
        lea     MAXADDR,a2              | PA of last RAM page
        RELOC(Lhighcode, a1)            | addr of high code
@@ -980,13 +1038,32 @@ Lhighcode:
        RELOC(_mmutype, a0)
        tstl    a0@                     | HP MMU?
        jeq     Lhpmmu3                 | yes, skip
        RELOC(_mmutype, a0)
        tstl    a0@                     | HP MMU?
        jeq     Lhpmmu3                 | yes, skip
-       movl    #MMU_IEN+MMU_FPE,IOBASE+MMUBASE+MMUCMD | enable 68881 and i-cache
-       movl    #0x82c0aa00,a2@                 | value to load TC with
-       pmove   a2@,tc                          | load it
+       cmpl    #-2,a0@                 | 68040?
+       jne     Lmotommu2               | no, skip
+       movw    #0,INTIOBASE+MMUBASE+MMUCMD+2
+       movw    #MMU_IEN+MMU_CEN+MMU_FPE,INTIOBASE+MMUBASE+MMUCMD+2
+                                       | enable FPU and caches
+       moveq   #0,d0                   | ensure TT regs are disabled
+       .long   0x4e7b0004              | movc d0,itt0
+       .long   0x4e7b0005              | movc d0,itt1
+       .long   0x4e7b0006              | movc d0,dtt0
+       .long   0x4e7b0007              | movc d0,dtt1
+       .word   0xf4d8                  | cinva bc
+       .word   0xf518                  | pflusha
+       movl    #0x8000,d0
+       .long   0x4e7b0003              | movc d0,tc
+       movl    #0x80008000,d0
+       movc    d0,cacr                 | turn on both caches
+       jmp     Lenab1
+Lmotommu2:
+       movl    #MMU_IEN+MMU_FPE,INTIOBASE+MMUBASE+MMUCMD
+                                       | enable 68881 and i-cache
+       movl    #0x82c0aa00,a2@         | value to load TC with
+       pmove   a2@,tc                  | load it
        jmp     Lenab1
 Lhpmmu3:
        jmp     Lenab1
 Lhpmmu3:
-       movl    #0,IOBASE+MMUBASE+MMUCMD        | clear external cache
-       movl    #MMU_ENAB,IOBASE+MMUBASE+MMUCMD | turn on MMU
+       movl    #0,INTIOBASE+MMUBASE+MMUCMD     | clear external cache
+       movl    #MMU_ENAB,INTIOBASE+MMUBASE+MMUCMD | turn on MMU
        jmp     Lenab1                          | jmp to mapped code
 Lehighcode:
 
        jmp     Lenab1                          | jmp to mapped code
 Lehighcode:
 
@@ -996,52 +1073,29 @@ Lehighcode:
 Lenab1:
 /* check for internal HP-IB in SYSFLAG */
        btst    #5,0xfffffed2           | internal HP-IB?
 Lenab1:
 /* check for internal HP-IB in SYSFLAG */
        btst    #5,0xfffffed2           | internal HP-IB?
-       jeq     Linitmem                | yes, have HP-IB just continue
-       clrl    _internalhpib           | no, clear flag
-/* init mem sizes */
-Linitmem:
-       movl    #MAXADDR,d1             | last page
-       moveq   #PGSHIFT,d2
-       lsrl    d2,d1                   | convert to page (click) number
-       movl    d1,_maxmem              | save as maxmem
-       movl    _lowram,d0              | lowram value from ROM via boot
-       lsrl    d2,d0                   | convert to page number
-       subl    d0,d1                   | compute amount of RAM present
-       movl    d1,_physmem             | and physmem
-/*
- * pmap_bootstrap is supposed to be called with mapping off early on
- * to set up the kernel VA space.  However, this only works easily if
- * you have a kernel PA == VA mapping.  Since we do not, we just set
- * up and enable mapping here and then call the bootstrap routine to
- * get the pmap module in sync with reality.
- */
-       .globl  _avail_start
+       jeq     Lfinish                 | yes, have HP-IB just continue
+       clrl    _internalhpib           | no, clear associated address
+Lfinish:
+/* select the software page size now */
        lea     tmpstk,sp               | temporary stack
        lea     tmpstk,sp               | temporary stack
-       movl    a5,sp@-                 | phys load address (assumes VA 0)
-       movl    a4,sp@-                 | first available PA
-       jbsr    _pmap_bootstrap         | sync up pmap module
-       addql   #8,sp
-|      movl    _avail_start,a4         | pmap_bootstrap may need RAM
-/* initialize (slightly) the pcb */
-       lea     _u,a1                   | proc0 u-area
-       lea     a1@(UPAGES*NBPG-4),sp   | set kernel stack to end of u-area
+       jbsr    _vm_set_page_size       | select software page size
+/* set kernel stack, user SP, and initial pcb */
+       lea     _kstack,a1              | proc0 kernel stack
+       lea     a1@(UPAGES*NBPG-4),sp   | set kernel stack to end of area
        movl    #USRSTACK-4,a2
        movl    a2,usp                  | init user SP
        movl    #USRSTACK-4,a2
        movl    a2,usp                  | init user SP
-       clrw    a1@(PCB_FLAGS)          | clear flags
+       movl    _proc0paddr,a1          | get proc0 pcb addr
+       movl    a1,_curpcb              | proc0 is running
 #ifdef FPCOPROC
        clrl    a1@(PCB_FPCTX)          | ensure null FP context
        movl    a1,sp@-
        jbsr    _m68881_restore         | restore it (does not kill a1)
        addql   #4,sp
 #endif
 #ifdef FPCOPROC
        clrl    a1@(PCB_FPCTX)          | ensure null FP context
        movl    a1,sp@-
        jbsr    _m68881_restore         | restore it (does not kill a1)
        addql   #4,sp
 #endif
-       addl    #PCB_SIGC,a1            | address of proc0 sig trampoline code
-       movl    #Lsigcode,a2            | address of sig trampoline proto
-Lsigc:
-       movw    a2@+,a1@+               | copy
-       cmpl    #Lesigcode,a2           | done yet?
-       jcs     Lsigc                   | no, keep going
 /* flush TLB and turn on caches */
        jbsr    _TBIA                   | invalidate TLB
 /* flush TLB and turn on caches */
        jbsr    _TBIA                   | invalidate TLB
+       cmpl    #-2,_mmutype            | 68040?
+       jeq     Lnocache0               | yes, cache already on
        movl    #CACHE_ON,d0
        movc    d0,cacr                 | clear cache(s)
        tstl    _ectype
        movl    #CACHE_ON,d0
        movc    d0,cacr                 | clear cache(s)
        tstl    _ectype
@@ -1050,22 +1104,39 @@ Lsigc:
        orl     #MMU_CEN,a0@(MMUCMD)    | turn on external cache
 Lnocache0:
 /* final setup for C code */
        orl     #MMU_CEN,a0@(MMUCMD)    | turn on external cache
 Lnocache0:
 /* final setup for C code */
+       jbsr    _isrinit                | be ready for stray ints
        movw    #PSL_LOWIPL,sr          | lower SPL
        movl    d7,_boothowto           | save reboot flags
        movl    d6,_bootdev             |   and boot device
        movw    #PSL_LOWIPL,sr          | lower SPL
        movl    d7,_boothowto           | save reboot flags
        movl    d6,_bootdev             |   and boot device
-       movl    a4,d1                   | addr of first available RAM
-       moveq   #PGSHIFT,d2
-       lsrl    d2,d1                   | convert to click
-       movl    d1,sp@-                 | param to main
-       jbsr    _main                   | main(firstaddr)
-       addql   #4,sp
-/* proc[1] == init now running here;
- * create a null exception frame and return to user mode in icode
+/*
+ * Create a fake exception frame that returns to user mode,
+ * make space for the rest of a fake saved register set, and
+ * pass the first available RAM and a pointer to the register
+ * set to "main()".  "main()" will call "icode()", which fakes
+ * an "execve()" system call, which is why we need to do that
+ * ("main()" sets "u.u_ar0" to point to the register set).
+ * When "main()" returns, we're running in process 1 and have
+ * successfully faked the "execve()".  We load up the registers from
+ * that set; the "rte" loads the PC and PSR, which jumps to "init".
  */
  */
-       clrw    sp@-                    | vector offset/frame type
-       clrl    sp@-                    | return to icode location 0
-       movw    #PSL_USER,sp@-          | in user mode
-       rte
+       clrw    sp@-                    | vector offset/frame type
+       clrl    sp@-                    | PC - filled in by "execve"
+       movw    #PSL_USER,sp@-          | in user mode
+       clrw    sp@-                    | pad SR to longword
+       lea     sp@(-64),sp             | construct space for D0-D7/A0-A7
+       pea     sp@                     | addr of space for D0
+       jbsr    _main                   | main(firstaddr, r0)
+       addql   #4,sp                   | pop args
+       cmpl    #-2,_mmutype            | 68040?
+       jne     Lnoflush                | no, skip
+       .word   0xf478                  | cpusha dc
+       .word   0xf498                  | cinva ic
+Lnoflush:
+       movl    sp@(60),a0              | grab and load
+       movl    a0,usp                  |   user SP
+       moveml  sp@+,#0x7FFF            | load most registers (all but SSP)
+       addql   #6,sp                   | pop SSP and align word
+       rte
 
 /*
  * Signal "trampoline" code (18 bytes).  Invoked from RTE setup by sendsig().
 
 /*
  * Signal "trampoline" code (18 bytes).  Invoked from RTE setup by sendsig().
@@ -1081,100 +1152,77 @@ Lnocache0:
  *                     .
  *     scp+0-> beginning of signal context frame
  */
  *                     .
  *     scp+0-> beginning of signal context frame
  */
-Lsigcode:
+       .globl  _sigcode, _esigcode, _sigcodetrap
+       .data
+_sigcode:
        movl    sp@(12),a0              | signal handler addr   (4 bytes)
        jsr     a0@                     | call signal handler   (2 bytes)
        addql   #4,sp                   | pop signo             (2 bytes)
        movl    sp@(12),a0              | signal handler addr   (4 bytes)
        jsr     a0@                     | call signal handler   (2 bytes)
        addql   #4,sp                   | pop signo             (2 bytes)
+_sigcodetrap:
        trap    #1                      | special syscall entry (2 bytes)
        movl    d0,sp@(4)               | save errno            (4 bytes)
        moveq   #1,d0                   | syscall == exit       (2 bytes)
        trap    #0                      | exit(errno)           (2 bytes)
        trap    #1                      | special syscall entry (2 bytes)
        movl    d0,sp@(4)               | save errno            (4 bytes)
        moveq   #1,d0                   | syscall == exit       (2 bytes)
        trap    #0                      | exit(errno)           (2 bytes)
-Lesigcode:
-
-/*
- * Icode is copied out to process 1 to exec init.
- * If the exec fails, process 1 exits.
- */
-       .globl  _icode,_initflags,_szicode
-_icode:
-       pea     pc@(argv-.-2)
-       pea     pc@(init-.-2)
-       clrl    sp@-
-       moveq   #SYS_execv,d0
-       trap    #0
-       moveq   #SYS_exit,d0
-       trap    #0
-init:
-       .asciz  "/sbin/init"
-       .even
-_initflags:
-       .long   0
-argv:
-       .long   init+6-_icode
-       .long   _initflags-_icode
-       .long   0
-_szicode:
-       .long   _szicode-_icode
+       .align  2
+_esigcode:
 
 /*
  * Primitives
  */ 
 
 
 /*
  * Primitives
  */ 
 
+#ifdef __STDC__
+#define EXPORT(name)           .globl _ ## name; _ ## name:
+#else
+#define EXPORT(name)           .globl _/**/name; _/**/name:
+#endif
 #ifdef GPROF
 #ifdef GPROF
-#ifdef __GNUC__
-#define        ENTRY(name) \
-       .globl _/**/name; _/**/name: link a6,#0; jbsr mcount; unlk a6
-#define ALTENTRY(name, rname) \
-       ENTRY(name); jra rname+12
+#if __GNUC__ >= 2
+#define        ENTRY(name)             EXPORT(name) link a6,\#0; jbsr mcount; unlk a6
 #else
 #else
-#define        ENTRY(name) \
-       .globl _/**/name; _/**/name: jbsr mcount
-#define ALTENTRY(name, rname) \
-       ENTRY(name); jra rname+6
+#define        ENTRY(name)             EXPORT(name) link a6,#0; jbsr mcount; unlk a6
 #endif
 #endif
+#define ALTENTRY(name, rname)  ENTRY(name); jra rname+12
 #else
 #else
-#define        ENTRY(name) \
-       .globl _/**/name; _/**/name:
-#define ALTENTRY(name, rname) \
-       .globl _/**/name; _/**/name:
+#define        ENTRY(name)             EXPORT(name)
+#define ALTENTRY(name, rname)  ENTRY(name)
 #endif
 
 /*
 #endif
 
 /*
- * update profiling information for the user
- * addupc(pc, &u.u_prof, ticks)
+ * For gcc2
  */
  */
-ENTRY(addupc)
-       movl    a2,sp@-                 | scratch register
-       movl    sp@(12),a2              | get &u.u_prof
-       movl    sp@(8),d0               | get user pc
-       subl    a2@(8),d0               | pc -= pr->pr_off
-       jlt     Lauexit                 | less than 0, skip it
-       movl    a2@(12),d1              | get pr->pr_scale
-       lsrl    #1,d0                   | pc /= 2
-       lsrl    #1,d1                   | scale /= 2
-       mulul   d1,d0                   | pc /= scale
-       moveq   #14,d1
-       lsrl    d1,d0                   | pc >>= 14
-       bclr    #0,d0                   | pc &= ~1
-       cmpl    a2@(4),d0               | too big for buffer?
-       jge     Lauexit                 | yes, screw it
-       addl    a2@,d0                  | no, add base
-       movl    d0,sp@-                 | push address
-       jbsr    _fusword                | grab old value
-       movl    sp@+,a0                 | grab address back
-       cmpl    #-1,d0                  | access ok
-       jeq     Lauerror                | no, skip out
-       addw    sp@(18),d0              | add tick to current value
-       movl    d0,sp@-                 | push value
-       movl    a0,sp@-                 | push address
-       jbsr    _susword                | write back new value
-       addql   #8,sp                   | pop params
-       tstl    d0                      | fault?
-       jeq     Lauexit                 | no, all done
-Lauerror:
-       clrl    a2@(12)                 | clear scale (turn off prof)
-Lauexit:
-       movl    sp@+,a2                 | restore scratch reg
+ENTRY(__main)
+       rts
+
+/*
+ * copypage(fromaddr, toaddr)
+ *
+ * Optimized version of bcopy for a single page-aligned NBPG byte copy.
+ */
+ENTRY(copypage)
+       movl    sp@(4),a0               | source address
+       movl    sp@(8),a1               | destination address
+       movl    #NBPG/32,d0             | number of 32 byte chunks
+#if defined(HP380)
+       cmpl    #-2,_mmutype            | 68040?
+       jne     Lmlloop                 | no, use movl
+Lm16loop:
+       .long   0xf6209000              | move16 a0@+,a1@+
+       .long   0xf6209000              | move16 a0@+,a1@+
+       subql   #1,d0
+       jne     Lm16loop
+       rts
+#endif
+Lmlloop:
+       movl    a0@+,a1@+
+       movl    a0@+,a1@+
+       movl    a0@+,a1@+
+       movl    a0@+,a1@+
+       movl    a0@+,a1@+
+       movl    a0@+,a1@+
+       movl    a0@+,a1@+
+       movl    a0@+,a1@+
+       subql   #1,d0
+       jne     Lmlloop
        rts
 
 /*
        rts
 
 /*
@@ -1182,19 +1230,22 @@ Lauexit:
  *
  * Copy a null terminated string from the user address space into
  * the kernel address space.
  *
  * Copy a null terminated string from the user address space into
  * the kernel address space.
- * NOTE: maxlength must be < 64K
+ *
+ * NOTE: maxlength must be < 64K (due to use of DBcc)
  */
 ENTRY(copyinstr)
  */
 ENTRY(copyinstr)
+       movl    _curpcb,a0              | current pcb
+       movl    #Lcisflt1,a0@(PCB_ONFAULT) | set up to catch faults
        movl    sp@(4),a0               | a0 = fromaddr
        movl    sp@(8),a1               | a1 = toaddr
        moveq   #0,d0
        movw    sp@(14),d0              | d0 = maxlength
        jlt     Lcisflt1                | negative count, error
        jeq     Lcisdone                | zero count, all done
        movl    sp@(4),a0               | a0 = fromaddr
        movl    sp@(8),a1               | a1 = toaddr
        moveq   #0,d0
        movw    sp@(14),d0              | d0 = maxlength
        jlt     Lcisflt1                | negative count, error
        jeq     Lcisdone                | zero count, all done
-       movl    #Lcisflt1,_u+PCB_ONFAULT | set up to catch faults
        subql   #1,d0                   | set up for dbeq
 Lcisloop:
        movsb   a0@+,d1                 | grab a byte
        subql   #1,d0                   | set up for dbeq
 Lcisloop:
        movsb   a0@+,d1                 | grab a byte
+       nop
        movb    d1,a1@+                 | copy it
        dbeq    d0,Lcisloop             | if !null and more, continue
        jne     Lcisflt2                | ran out of room, error
        movb    d1,a1@+                 | copy it
        dbeq    d0,Lcisloop             | if !null and more, continue
        jne     Lcisflt2                | ran out of room, error
@@ -1206,7 +1257,8 @@ Lcisdone:
        movl    sp@(16),a1              | return location
        movl    a0,a1@                  | stash it
 Lcisret:
        movl    sp@(16),a1              | return location
        movl    a0,a1@                  | stash it
 Lcisret:
-       clrl    _u+PCB_ONFAULT          | clear fault addr
+       movl    _curpcb,a0              | current pcb
+       clrl    a0@(PCB_ONFAULT)        | clear fault addr
        rts
 Lcisflt1:
        moveq   #EFAULT,d0              | copy fault
        rts
 Lcisflt1:
        moveq   #EFAULT,d0              | copy fault
@@ -1220,20 +1272,23 @@ Lcisflt2:
  *
  * Copy a null terminated string from the kernel
  * address space to the user address space.
  *
  * Copy a null terminated string from the kernel
  * address space to the user address space.
- * NOTE: maxlength must be < 64K
+ *
+ * NOTE: maxlength must be < 64K (due to use of DBcc)
  */
 ENTRY(copyoutstr)
  */
 ENTRY(copyoutstr)
+       movl    _curpcb,a0              | current pcb
+       movl    #Lcosflt1,a0@(PCB_ONFAULT) | set up to catch faults
        movl    sp@(4),a0               | a0 = fromaddr
        movl    sp@(8),a1               | a1 = toaddr
        moveq   #0,d0
        movw    sp@(14),d0              | d0 = maxlength
        jlt     Lcosflt1                | negative count, error
        jeq     Lcosdone                | zero count, all done
        movl    sp@(4),a0               | a0 = fromaddr
        movl    sp@(8),a1               | a1 = toaddr
        moveq   #0,d0
        movw    sp@(14),d0              | d0 = maxlength
        jlt     Lcosflt1                | negative count, error
        jeq     Lcosdone                | zero count, all done
-       movl    #Lcosflt1,_u+PCB_ONFAULT| set up to catch faults
        subql   #1,d0                   | set up for dbeq
 Lcosloop:
        movb    a0@+,d1                 | grab a byte
        movsb   d1,a1@+                 | copy it
        subql   #1,d0                   | set up for dbeq
 Lcosloop:
        movb    a0@+,d1                 | grab a byte
        movsb   d1,a1@+                 | copy it
+       nop
        dbeq    d0,Lcosloop             | if !null and more, continue
        jne     Lcosflt2                | ran out of room, error
        moveq   #0,d0                   | got a null, all done
        dbeq    d0,Lcosloop             | if !null and more, continue
        jne     Lcosflt2                | ran out of room, error
        moveq   #0,d0                   | got a null, all done
@@ -1244,7 +1299,8 @@ Lcosdone:
        movl    sp@(16),a1              | return location
        movl    a0,a1@                  | stash it
 Lcosret:
        movl    sp@(16),a1              | return location
        movl    a0,a1@                  | stash it
 Lcosret:
-       clrl    _u+PCB_ONFAULT          | clear fault addr
+       movl    _curpcb,a0              | current pcb
+       clrl    a0@(PCB_ONFAULT)        | clear fault addr
        rts
 Lcosflt1:
        moveq   #EFAULT,d0              | copy fault
        rts
 Lcosflt1:
        moveq   #EFAULT,d0              | copy fault
@@ -1258,7 +1314,8 @@ Lcosflt2:
  *
  * Copy a null terminated string from one point to another in
  * the kernel address space.
  *
  * Copy a null terminated string from one point to another in
  * the kernel address space.
- * NOTE: maxlength must be < 64K
+ *
+ * NOTE: maxlength must be < 64K (due to use of DBcc)
  */
 ENTRY(copystr)
        movl    sp@(4),a0               | a0 = fromaddr
  */
 ENTRY(copystr)
        movl    sp@(4),a0               | a0 = fromaddr
@@ -1267,7 +1324,6 @@ ENTRY(copystr)
        movw    sp@(14),d0              | d0 = maxlength
        jlt     Lcsflt1                 | negative count, error
        jeq     Lcsdone                 | zero count, all done
        movw    sp@(14),d0              | d0 = maxlength
        jlt     Lcsflt1                 | negative count, error
        jeq     Lcsdone                 | zero count, all done
-       movl    #Lcsflt1,_u+PCB_ONFAULT | set up to catch faults
        subql   #1,d0                   | set up for dbeq
 Lcsloop:
        movb    a0@+,a1@+               | copy a byte
        subql   #1,d0                   | set up for dbeq
 Lcsloop:
        movb    a0@+,a1@+               | copy a byte
@@ -1281,7 +1337,6 @@ Lcsdone:
        movl    sp@(16),a1              | return location
        movl    a0,a1@                  | stash it
 Lcsret:
        movl    sp@(16),a1              | return location
        movl    a0,a1@                  | stash it
 Lcsret:
-       clrl    _u+PCB_ONFAULT          | clear fault addr
        rts
 Lcsflt1:
        moveq   #EFAULT,d0              | copy fault
        rts
 Lcsflt1:
        moveq   #EFAULT,d0              | copy fault
@@ -1291,111 +1346,126 @@ Lcsflt2:
        jra     Lcsdone 
 
 /* 
        jra     Lcsdone 
 
 /* 
- * Copyin(from, to, len)
+ * Copyin(from_user, to_kernel, len)
+ * Copyout(from_kernel, to_user, len)
+ *
+ * Copy specified amount of data between kernel and user space.
  *
  *
- * Copy specified amount of data from user space into the kernel.
- * NOTE: len must be < 64K
+ * XXX both use the DBcc instruction which has 16-bit limitation so only
+ * 64k units can be copied, where "unit" is either a byte or a longword
+ * depending on alignment.  To be safe, assume it can copy at most
+ * 64k bytes.  Don't make MAXBSIZE or MAXPHYS larger than 64k without
+ * fixing this code!
  */
 ENTRY(copyin)
  */
 ENTRY(copyin)
+       movl    sp@(12),d0              | get size
+#ifdef MAPPEDCOPY
+       .globl  _mappedcopysize,_mappedcopyin
+       cmpl    _mappedcopysize,d0      | size >= mappedcopysize
+       jcc     _mappedcopyin           | yes, go do it the new way
+#endif
        movl    d2,sp@-                 | scratch register
        movl    d2,sp@-                 | scratch register
-       movl    #Lciflt,_u+PCB_ONFAULT  | catch faults
-       movl    sp@(16),d2              | check count
+       movl    _curpcb,a0              | current pcb
+       movl    #Lciflt,a0@(PCB_ONFAULT) | set up to catch faults
+       tstl    d0                      | check count
        jlt     Lciflt                  | negative, error
        jeq     Lcidone                 | zero, done
        movl    sp@(8),a0               | src address
        movl    sp@(12),a1              | dest address
        jlt     Lciflt                  | negative, error
        jeq     Lcidone                 | zero, done
        movl    sp@(8),a0               | src address
        movl    sp@(12),a1              | dest address
-       movl    a0,d0
-       btst    #0,d0                   | src address odd?
+       movl    a0,d2
+       btst    #0,d2                   | src address odd?
        jeq     Lcieven                 | no, go check dest
        movsb   a0@+,d1                 | yes, get a byte
        jeq     Lcieven                 | no, go check dest
        movsb   a0@+,d1                 | yes, get a byte
+       nop
        movb    d1,a1@+                 | put a byte
        movb    d1,a1@+                 | put a byte
-       subql   #1,d2                   | adjust count
+       subql   #1,d0                   | adjust count
        jeq     Lcidone                 | exit if done
 Lcieven:
        jeq     Lcidone                 | exit if done
 Lcieven:
-       movl    a1,d0
-       btst    #0,d0                   | dest address odd?
-       jne     Lcibyte                 | yes, must copy by bytes
-       movl    d2,d0                   | no, get count
-       lsrl    #2,d0                   | convert to longwords
-       jeq     Lcibyte                 | no longwords, copy bytes
-       subql   #1,d0                   | set up for dbf
+       movl    a1,d2
+       btst    #0,d2                   | dest address odd?
+       jne     Lcibloop                | yes, must copy by bytes
+       movl    d0,d2                   | no, get count
+       lsrl    #2,d2                   | convert to longwords
+       jeq     Lcibloop                | no longwords, copy bytes
 Lcilloop:
        movsl   a0@+,d1                 | get a long
 Lcilloop:
        movsl   a0@+,d1                 | get a long
+       nop
        movl    d1,a1@+                 | put a long
        movl    d1,a1@+                 | put a long
-       dbf     d0,Lcilloop             | til done
-       andl    #3,d2                   | what remains
+       subql   #1,d2
+       jne     Lcilloop                | til done
+       andl    #3,d0                   | what remains
        jeq     Lcidone                 | all done
        jeq     Lcidone                 | all done
-Lcibyte:
-       subql   #1,d2                   | set up for dbf
 Lcibloop:
        movsb   a0@+,d1                 | get a byte
 Lcibloop:
        movsb   a0@+,d1                 | get a byte
+       nop
        movb    d1,a1@+                 | put a byte
        movb    d1,a1@+                 | put a byte
-       dbf     d2,Lcibloop             | til done
+       subql   #1,d0
+       jne     Lcibloop                | til done
 Lcidone:
 Lcidone:
-       moveq   #0,d0                   | success
-Lciexit:
-       clrl    _u+PCB_ONFAULT          | reset fault catcher
+       movl    _curpcb,a0              | current pcb
+       clrl    a0@(PCB_ONFAULT)        | clear fault catcher
        movl    sp@+,d2                 | restore scratch reg
        rts
 Lciflt:
        moveq   #EFAULT,d0              | got a fault
        movl    sp@+,d2                 | restore scratch reg
        rts
 Lciflt:
        moveq   #EFAULT,d0              | got a fault
-       jra     Lciexit
+       jra     Lcidone
 
 
-/* 
- * Copyout(from, to, len)
- *
- * Copy specified amount of data from kernel to the user space
- * NOTE: len must be < 64K
- */
 ENTRY(copyout)
 ENTRY(copyout)
+       movl    sp@(12),d0              | get size
+#ifdef MAPPEDCOPY
+       .globl  _mappedcopysize,_mappedcopyout
+       cmpl    _mappedcopysize,d0      | size >= mappedcopysize
+       jcc     _mappedcopyout          | yes, go do it the new way
+#endif
        movl    d2,sp@-                 | scratch register
        movl    d2,sp@-                 | scratch register
-       movl    #Lcoflt,_u+PCB_ONFAULT  | catch faults
-       movl    sp@(16),d2              | check count
+       movl    _curpcb,a0              | current pcb
+       movl    #Lcoflt,a0@(PCB_ONFAULT) | catch faults
+       tstl    d0                      | check count
        jlt     Lcoflt                  | negative, error
        jeq     Lcodone                 | zero, done
        movl    sp@(8),a0               | src address
        movl    sp@(12),a1              | dest address
        jlt     Lcoflt                  | negative, error
        jeq     Lcodone                 | zero, done
        movl    sp@(8),a0               | src address
        movl    sp@(12),a1              | dest address
-       movl    a0,d0
-       btst    #0,d0                   | src address odd?
+       movl    a0,d2
+       btst    #0,d2                   | src address odd?
        jeq     Lcoeven                 | no, go check dest
        movb    a0@+,d1                 | yes, get a byte
        movsb   d1,a1@+                 | put a byte
        jeq     Lcoeven                 | no, go check dest
        movb    a0@+,d1                 | yes, get a byte
        movsb   d1,a1@+                 | put a byte
-       subql   #1,d2                   | adjust count
+       nop
+       subql   #1,d0                   | adjust count
        jeq     Lcodone                 | exit if done
 Lcoeven:
        jeq     Lcodone                 | exit if done
 Lcoeven:
-       movl    a1,d0
-       btst    #0,d0                   | dest address odd?
-       jne     Lcobyte                 | yes, must copy by bytes
-       movl    d2,d0                   | no, get count
-       lsrl    #2,d0                   | convert to longwords
-       jeq     Lcobyte                 | no longwords, copy bytes
-       subql   #1,d0                   | set up for dbf
+       movl    a1,d2
+       btst    #0,d2                   | dest address odd?
+       jne     Lcobloop                | yes, must copy by bytes
+       movl    d0,d2                   | no, get count
+       lsrl    #2,d2                   | convert to longwords
+       jeq     Lcobloop                | no longwords, copy bytes
 Lcolloop:
        movl    a0@+,d1                 | get a long
        movsl   d1,a1@+                 | put a long
 Lcolloop:
        movl    a0@+,d1                 | get a long
        movsl   d1,a1@+                 | put a long
-       dbf     d0,Lcolloop             | til done
-       andl    #3,d2                   | what remains
+       nop
+       subql   #1,d2
+       jne     Lcolloop                | til done
+       andl    #3,d0                   | what remains
        jeq     Lcodone                 | all done
        jeq     Lcodone                 | all done
-Lcobyte:
-       subql   #1,d2                   | set up for dbf
 Lcobloop:
        movb    a0@+,d1                 | get a byte
        movsb   d1,a1@+                 | put a byte
 Lcobloop:
        movb    a0@+,d1                 | get a byte
        movsb   d1,a1@+                 | put a byte
-       dbf     d2,Lcobloop             | til done
+       nop
+       subql   #1,d0
+       jne     Lcobloop                | til done
 Lcodone:
 Lcodone:
-       moveq   #0,d0                   | success
-Lcoexit:
-       clrl    _u+PCB_ONFAULT          | reset fault catcher
+       movl    _curpcb,a0              | current pcb
+       clrl    a0@(PCB_ONFAULT)        | clear fault catcher
        movl    sp@+,d2                 | restore scratch reg
        rts
 Lcoflt:
        moveq   #EFAULT,d0              | got a fault
        movl    sp@+,d2                 | restore scratch reg
        rts
 Lcoflt:
        moveq   #EFAULT,d0              | got a fault
-       jra     Lcoexit
+       jra     Lcodone
 
 /*
  * non-local gotos
  */
 
 /*
  * non-local gotos
  */
-ALTENTRY(savectx, _setjmp)
 ENTRY(setjmp)
        movl    sp@(4),a0       | savearea pointer
        moveml  #0xFCFC,a0@     | save d2-d7/a2-a7
 ENTRY(setjmp)
        movl    sp@(4),a0       | savearea pointer
        moveml  #0xFCFC,a0@     | save d2-d7/a2-a7
@@ -1403,15 +1473,6 @@ ENTRY(setjmp)
        moveq   #0,d0           | return 0
        rts
 
        moveq   #0,d0           | return 0
        rts
 
-ENTRY(qsetjmp)
-       movl    sp@(4),a0       | savearea pointer
-       lea     a0@(40),a0      | skip regs we do not save
-       movl    a6,a0@+         | save FP
-       movl    sp,a0@+         | save SP
-       movl    sp@,a0@         | and return address
-       moveq   #0,d0           | return 0
-       rts
-
 ENTRY(longjmp)
        movl    sp@(4),a0
        moveml  a0@+,#0xFCFC
 ENTRY(longjmp)
        movl    sp@(4),a0
        moveml  a0@+,#0xFCFC
@@ -1420,49 +1481,47 @@ ENTRY(longjmp)
        rts
 
 /*
        rts
 
 /*
- * The following primitives manipulate the run queues.
- * _whichqs tells which of the 32 queues _qs
- * have processes in them.  Setrq puts processes into queues, Remrq
- * removes them from queues.  The running process is on no queue,
- * other processes are on a queue related to p->p_pri, divided by 4
- * actually to shrink the 0-127 range of priorities into the 32 available
+ * The following primitives manipulate the run queues.  _whichqs tells which
+ * of the 32 queues _qs have processes in them.  Setrunqueue puts processes
+ * into queues, Remrq removes them from queues.  The running process is on
+ * no queue, other processes are on a queue related to p->p_priority, divided
+ * by 4 actually to shrink the 0-127 range of priorities into the 32 available
  * queues.
  */
 
        .globl  _whichqs,_qs,_cnt,_panic
  * queues.
  */
 
        .globl  _whichqs,_qs,_cnt,_panic
-       .comm   _noproc,4
-       .comm   _runrun,4
+       .globl  _curproc,_want_resched
 
 /*
 
 /*
- * Setrq(p)
+ * Setrunqueue(p)
  *
  * Call should be made at spl6(), and p->p_stat should be SRUN
  */
  *
  * Call should be made at spl6(), and p->p_stat should be SRUN
  */
-ENTRY(setrq)
+ENTRY(setrunqueue)
        movl    sp@(4),a0
        movl    sp@(4),a0
-       tstl    a0@(P_RLINK)
+       tstl    a0@(P_BACK)
        jeq     Lset1
        movl    #Lset2,sp@-
        jbsr    _panic
 Lset1:
        clrl    d0
        jeq     Lset1
        movl    #Lset2,sp@-
        jbsr    _panic
 Lset1:
        clrl    d0
-       movb    a0@(P_PRI),d0
+       movb    a0@(P_PRIORITY),d0
        lsrb    #2,d0
        movl    _whichqs,d1
        bset    d0,d1
        movl    d1,_whichqs
        lslb    #3,d0
        addl    #_qs,d0
        lsrb    #2,d0
        movl    _whichqs,d1
        bset    d0,d1
        movl    d1,_whichqs
        lslb    #3,d0
        addl    #_qs,d0
-       movl    d0,a0@(P_LINK)
+       movl    d0,a0@(P_FORW)
        movl    d0,a1
        movl    d0,a1
-       movl    a1@(P_RLINK),a0@(P_RLINK)
-       movl    a0,a1@(P_RLINK)
-       movl    a0@(P_RLINK),a1
-       movl    a0,a1@(P_LINK)
+       movl    a1@(P_BACK),a0@(P_BACK)
+       movl    a0,a1@(P_BACK)
+       movl    a0@(P_BACK),a1
+       movl    a0,a1@(P_FORW)
        rts
 
 Lset2:
        rts
 
 Lset2:
-       .asciz  "setrq"
+       .asciz  "setrunqueue"
        .even
 
 /*
        .even
 
 /*
@@ -1473,7 +1532,7 @@ Lset2:
 ENTRY(remrq)
        movl    sp@(4),a0
        clrl    d0
 ENTRY(remrq)
        movl    sp@(4),a0
        clrl    d0
-       movb    a0@(P_PRI),d0
+       movb    a0@(P_PRIORITY),d0
        lsrb    #2,d0
        movl    _whichqs,d1
        bclr    d0,d1
        lsrb    #2,d0
        movl    _whichqs,d1
        bclr    d0,d1
@@ -1482,52 +1541,65 @@ ENTRY(remrq)
        jbsr    _panic
 Lrem1:
        movl    d1,_whichqs
        jbsr    _panic
 Lrem1:
        movl    d1,_whichqs
-       movl    a0@(P_LINK),a1
-       movl    a0@(P_RLINK),a1@(P_RLINK)
-       movl    a0@(P_RLINK),a1
-       movl    a0@(P_LINK),a1@(P_LINK)
+       movl    a0@(P_FORW),a1
+       movl    a0@(P_BACK),a1@(P_BACK)
+       movl    a0@(P_BACK),a1
+       movl    a0@(P_FORW),a1@(P_FORW)
        movl    #_qs,a1
        movl    d0,d1
        lslb    #3,d1
        addl    d1,a1
        movl    #_qs,a1
        movl    d0,d1
        lslb    #3,d1
        addl    d1,a1
-       cmpl    a1@(P_LINK),a1
+       cmpl    a1@(P_FORW),a1
        jeq     Lrem2
        movl    _whichqs,d1
        bset    d0,d1
        movl    d1,_whichqs
 Lrem2:
        jeq     Lrem2
        movl    _whichqs,d1
        bset    d0,d1
        movl    d1,_whichqs
 Lrem2:
-       clrl    a0@(P_RLINK)
+       clrl    a0@(P_BACK)
        rts
 
 Lrem3:
        .asciz  "remrq"
 Lsw0:
        rts
 
 Lrem3:
        .asciz  "remrq"
 Lsw0:
-       .asciz  "swtch"
+       .asciz  "switch"
        .even
 
        .even
 
-/*
- * Masterpaddr is the p->p_addr of the running process on the master
- * processor.  When a multiprocessor system, the slave processors will have
- * an array of slavepaddrs (on an HP it only exists for the benefit of adb).
- */
-       .globl  _masterpaddr
+       .globl  _curpcb
+       .globl  _masterpaddr    | XXX compatibility (debuggers)
        .data
        .data
-_masterpaddr:
+_masterpaddr:                  | XXX compatibility (debuggers)
+_curpcb:
        .long   0
        .long   0
+mdpflag:
+       .byte   0               | copy of proc md_flags low byte
+       .align  2
+       .comm   nullpcb,SIZEOF_PCB
        .text
 
 /*
        .text
 
 /*
- * When no processes are on the runq, Swtch branches to idle
+ * At exit of a process, do a switch for the last time.
+ * The mapping of the pcb at p->p_addr has already been deleted,
+ * and the memory for the pcb+stack has been freed.
+ * The ipl is high enough to prevent the memory from being reallocated.
+ */
+ENTRY(switch_exit)
+       movl    #nullpcb,_curpcb        | save state into garbage pcb
+       lea     tmpstk,sp               | goto a tmp stack
+       jra     _cpu_switch
+
+/*
+ * When no processes are on the runq, Swtch branches to Idle
  * to wait for something to come ready.
  */
  * to wait for something to come ready.
  */
-       .globl  Idle
-Idle:
+       .globl  idle
 idle:
 idle:
-       movw    #PSL_LOWIPL,sr
-       tstl    _whichqs
-       jne     Lsw1
        stop    #PSL_LOWIPL
        stop    #PSL_LOWIPL
-       jra     idle
+Idle:
+       movw    #PSL_HIGHIPL,sr
+       tstl    _whichqs
+       jeq     idle
+       movw    #PSL_LOWIPL,sr
+       jra     Lsw1
 
 Lbadsw:
        movl    #Lsw0,sp@-
 
 Lbadsw:
        movl    #Lsw0,sp@-
@@ -1535,138 +1607,158 @@ Lbadsw:
        /*NOTREACHED*/
 
 /*
        /*NOTREACHED*/
 
 /*
- * Swtch()
+ * cpu_switch()
+ *
+ * NOTE: On the mc68851 (318/319/330) we attempt to avoid flushing the
+ * entire ATC.  The effort involved in selective flushing may not be
+ * worth it, maybe we should just flush the whole thing?
+ *
+ * NOTE 2: With the new VM layout we now no longer know if an inactive
+ * user's PTEs have been changed (formerly denoted by the SPTECHG p_flag
+ * bit).  For now, we just always flush the full ATC.
  */
  */
-ENTRY(swtch)
-       movw    sr,_u+PCB_PS
-       movl    #1,_noproc
+ENTRY(cpu_switch)
+       movl    _curpcb,a0              | current pcb
+       movw    sr,a0@(PCB_PS)          | save sr before changing ipl
+#ifdef notyet
+       movl    _curproc,sp@-           | remember last proc running
+#endif
+       clrl    _curproc
        addql   #1,_cnt+V_SWTCH
        addql   #1,_cnt+V_SWTCH
+
 Lsw1:
 Lsw1:
+       /*
+        * Find the highest-priority queue that isn't empty,
+        * then take the first proc from that queue.
+        */
        clrl    d0
        clrl    d0
-       movl    _whichqs,d1
+       lea     _whichqs,a0
+       movl    a0@,d1
 Lswchk:
        btst    d0,d1
        jne     Lswfnd
        addqb   #1,d0
        cmpb    #32,d0
        jne     Lswchk
 Lswchk:
        btst    d0,d1
        jne     Lswfnd
        addqb   #1,d0
        cmpb    #32,d0
        jne     Lswchk
-       jra     idle
+       jra     Idle
 Lswfnd:
 Lswfnd:
-       movw    #PSL_HIGHIPL,sr
-       movl    _whichqs,d1
+       movw    #PSL_HIGHIPL,sr         | lock out interrupts
+       movl    a0@,d1                  | and check again...
        bclr    d0,d1
        bclr    d0,d1
-       jeq     Lsw1
-       movl    d1,_whichqs
+       jeq     Lsw1                    | proc moved, rescan
+       movl    d1,a0@                  | update whichqs
+       moveq   #1,d1                   | double check for higher priority
+       lsll    d0,d1                   | process (which may have snuck in
+       subql   #1,d1                   | while we were finding this one)
+       andl    a0@,d1
+       jeq     Lswok                   | no one got in, continue
+       movl    a0@,d1
+       bset    d0,d1                   | otherwise put this one back
+       movl    d1,a0@
+       jra     Lsw1                    | and rescan
+Lswok:
        movl    d0,d1
        movl    d0,d1
-       lslb    #3,d1
-       addl    #_qs,d1
+       lslb    #3,d1                   | convert queue number to index
+       addl    #_qs,d1                 | locate queue (q)
        movl    d1,a1
        movl    d1,a1
-       cmpl    a1@(P_LINK),a1
-       jeq     Lbadsw
-       movl    a1@(P_LINK),a0
-       movl    a0@(P_LINK),a1@(P_LINK)
-       movl    a0@(P_LINK),a1
-       movl    a0@(P_RLINK),a1@(P_RLINK)
-       cmpl    a0@(P_LINK),d1
-       jeq     Lsw2
+       cmpl    a1@(P_FORW),a1          | anyone on queue?
+       jeq     Lbadsw                  | no, panic
+       movl    a1@(P_FORW),a0          | p = q->p_forw
+       movl    a0@(P_FORW),a1@(P_FORW) | q->p_forw = p->p_forw
+       movl    a0@(P_FORW),a1          | q = p->p_forw
+       movl    a0@(P_BACK),a1@(P_BACK) | q->p_back = p->p_back
+       cmpl    a0@(P_FORW),d1          | anyone left on queue?
+       jeq     Lsw2                    | no, skip
        movl    _whichqs,d1
        movl    _whichqs,d1
-       bset    d0,d1
+       bset    d0,d1                   | yes, reset bit
        movl    d1,_whichqs
 Lsw2:
        movl    d1,_whichqs
 Lsw2:
-       clrl    _noproc
-       clrl    _runrun
+       movl    a0,_curproc
+       clrl    _want_resched
+#ifdef notyet
+       movl    sp@+,a1
+       cmpl    a0,a1                   | switching to same proc?
+       jeq     Lswdone                 | yes, skip save and restore
+#endif
+       /*
+        * Save state of previous process in its pcb.
+        */
+       movl    _curpcb,a1
+       moveml  #0xFCFC,a1@(PCB_REGS)   | save non-scratch registers
+       movl    usp,a2                  | grab USP (a2 has been saved)
+       movl    a2,a1@(PCB_USP)         | and save it
+#ifdef FPCOPROC
+       lea     a1@(PCB_FPCTX),a2       | pointer to FP save area
+       fsave   a2@                     | save FP state
+       tstb    a2@                     | null state frame?
+       jeq     Lswnofpsave             | yes, all done
+       fmovem  fp0-fp7,a2@(216)        | save FP general registers
+       fmovem  fpcr/fpsr/fpi,a2@(312)  | save FP control registers
+Lswnofpsave:
+#endif
+
+#ifdef DIAGNOSTIC
        tstl    a0@(P_WCHAN)
        jne     Lbadsw
        cmpb    #SRUN,a0@(P_STAT)
        jne     Lbadsw
        tstl    a0@(P_WCHAN)
        jne     Lbadsw
        cmpb    #SRUN,a0@(P_STAT)
        jne     Lbadsw
-       clrl    a0@(P_RLINK)
-       movl    a0@(P_ADDR),d0
-       movl    d0,_masterpaddr
-       movl    a0@(P_MAP),a1           | map = p->p_map
-       tstl    a1                      | map == VM_MAP_NULL?
-       jeq     Lswnochg                | yes, skip
-       movl    a1@(PMAP),a1            | pmap = map->pmap
-       tstl    a1                      | pmap == PMAP_NULL?
-       jeq     Lswnochg                | yes, skip
-       tstl    a1@(PM_STCHG)           | pmap->st_changed?
+#endif
+       clrl    a0@(P_BACK)             | clear back link
+       movb    a0@(P_MDFLAG+3),mdpflag | low byte of p_md.md_flags
+       movl    a0@(P_ADDR),a1          | get p_addr
+       movl    a1,_curpcb
+
+       /* see if pmap_activate needs to be called; should remove this */
+       movl    a0@(P_VMSPACE),a0       | vmspace = p->p_vmspace
+#ifdef DIAGNOSTIC
+       tstl    a0                      | map == VM_MAP_NULL?
+       jeq     Lbadsw                  | panic
+#endif
+       lea     a0@(VM_PMAP),a0         | pmap = &vmspace.vm_pmap
+       tstl    a0@(PM_STCHG)           | pmap->st_changed?
        jeq     Lswnochg                | no, skip
        jeq     Lswnochg                | no, skip
-       movl    d0,sp@-                 | push pcb (at p_addr)
-       pea     a1@                     | push pmap
+       pea     a1@                     | push pcb (at p_addr)
+       pea     a0@                     | push pmap
        jbsr    _pmap_activate          | pmap_activate(pmap, pcb)
        addql   #8,sp
        jbsr    _pmap_activate          | pmap_activate(pmap, pcb)
        addql   #8,sp
-       movl    _masterpaddr,d0         | restore p_addr for resume below
+       movl    _curpcb,a1              | restore p_addr
 Lswnochg:
 Lswnochg:
-       jra     Lres0
 
 
-/*
- * Resume(p_addr)
- *
- * NOTE: on the PMMU we attempt to avoid flushing the entire TAC.
- * The effort involved in selective flushing may not be worth it,
- * maybe we should just flush the whole thing?
- */
-ENTRY(resume)
-       movw    sr,_u+PCB_PS
-       movl    sp@(4),d0
-Lres0:
-       lea     _u,a1                   | &u
-       movl    usp,a0                  | grab USP
-       movl    a0,a1@(PCB_USP)         | and save it
-       moveml  #0xFCFC,a1@(PCB_REGS)   | save non-scratch registers
-#ifdef FPCOPROC
-       lea     a1@(PCB_FPCTX),a0       | pointer to FP save area
-       fsave   a0@                     | save FP state
-       tstb    a0@                     | null state frame?
-       jeq     Lresnofpsave            | yes, all done
-       fmovem  fp0-fp7,a0@(216)        | save FP general registers
-       fmovem  fpcr/fpsr/fpi,a0@(312)  | save FP control registers
-Lresnofpsave:
-#endif
-#ifdef PROFTIMER
-       movw    #SPL6,sr                | protect against clock interrupts
-       bclr    #0,_profon              | clear user profiling bit, was set?
-       jeq     Lskipoff                | no, clock off or doing kernel only
-#ifdef GPROF
-       tstb    _profon                 | kernel profiling also enabled?
-       jlt     Lskipoff                | yes, nothing more to do
-#endif
-       CLKADDR(a0)
-       movb    #0,a0@(CLKCR2)          | no, just user, select CR3
-       movb    #0,a0@(CLKCR3)          | and turn it off
-Lskipoff:
-#endif
-       movl    _CMAP2,a1@(PCB_CMAP2)   | save temporary map PTE
        movl    #PGSHIFT,d1
        movl    #PGSHIFT,d1
+       movl    a1,d0
        lsrl    d1,d0                   | convert p_addr to page number
        lsrl    d1,d0                   | convert p_addr to page number
-       lsll    #2,d0                   | and now to Systab offset
-       addl    _Sysmap,d0              | add Systab base to get PTE addr
+       lsll    #2,d0                   | and now to Sysmap offset
+       addl    _Sysmap,d0              | add Sysmap base to get PTE addr
+#ifdef notdef
        movw    #PSL_HIGHIPL,sr         | go crit while changing PTEs
        movw    #PSL_HIGHIPL,sr         | go crit while changing PTEs
+#endif
        lea     tmpstk,sp               | now goto a tmp stack for NMI
        movl    d0,a0                   | address of new context
        lea     tmpstk,sp               | now goto a tmp stack for NMI
        movl    d0,a0                   | address of new context
-       movl    _Umap,a1                | address of PTEs for u
-       moveq   #UPAGES-1,d0            | sizeof u
+       movl    _Umap,a2                | address of PTEs for kstack
+       moveq   #UPAGES-1,d0            | sizeof kstack
 Lres1:
        movl    a0@+,d1                 | get PTE
        andl    #~PG_PROT,d1            | mask out old protection
        orl     #PG_RW+PG_V,d1          | ensure valid and writable
 Lres1:
        movl    a0@+,d1                 | get PTE
        andl    #~PG_PROT,d1            | mask out old protection
        orl     #PG_RW+PG_V,d1          | ensure valid and writable
-       movl    d1,a1@+                 | load it up
+       movl    d1,a2@+                 | load it up
        dbf     d0,Lres1                | til done
        dbf     d0,Lres1                | til done
-       lea     _u,a1                   | reload &u
+#if defined(HP380)
+       cmpl    #-2,_mmutype            | 68040?
+       jne     Lres1a                  | no, skip
+       .word   0xf518                  | yes, pflusha
+       movl    a1@(PCB_USTP),d0        | get USTP
+       moveq   #PGSHIFT,d1
+       lsll    d1,d0                   | convert to addr
+       .long   0x4e7b0806              | movc d0,urp
+       jra     Lcxswdone
+Lres1a:
+#endif
        movl    #CACHE_CLR,d0
        movc    d0,cacr                 | invalidate cache(s)
 #if defined(HP330) || defined(HP360) || defined(HP370)
        tstl    _mmutype                | HP MMU?
        jeq     Lhpmmu4                 | yes, skip
        movl    #CACHE_CLR,d0
        movc    d0,cacr                 | invalidate cache(s)
 #if defined(HP330) || defined(HP360) || defined(HP370)
        tstl    _mmutype                | HP MMU?
        jeq     Lhpmmu4                 | yes, skip
-       jmi     Lnot68851a              | must flush all on 68030 MMU
-#ifdef DEBUG
-       tstl    fulltflush              | 68851, conservative?
-       jne     Lnot68851a              | yes, go flush all
-#endif
-       pflushs #4,#4                   | flush only supervisor side
-       jra     Lres2
-Lnot68851a:
        pflusha                         | flush entire TLB
        pflusha                         | flush entire TLB
-Lres2:
        movl    a1@(PCB_USTP),d0        | get USTP
        moveq   #PGSHIFT,d1
        lsll    d1,d0                   | convert to addr
        movl    a1@(PCB_USTP),d0        | get USTP
        moveq   #PGSHIFT,d1
        lsll    d1,d0                   | convert to addr
@@ -1687,224 +1779,218 @@ Lnocache1:
        movl    a1@(PCB_USTP),a0@(MMUUSTP) | context switch
 #endif
 Lcxswdone:
        movl    a1@(PCB_USTP),a0@(MMUUSTP) | context switch
 #endif
 Lcxswdone:
-       movl    a1@(U_PROCP),a0         | u.u_procp
-       bclr    #SPTECHGB-24,a0@(P_FLAG)| clear SPTECHG bit
-#if defined(HP330)
-       jeq     Lnot68851b              | if set need to flush user TLB
-       tstl    _mmutype                | 68851 PMMU?
-       jle     Lnot68851b              | no, skip
-       pflushs #0,#4                   | user PT changed, flush user TLB
-Lnot68851b:
-#endif
-       movl    a1@(PCB_CMAP2),_CMAP2   | reload tmp map
        moveml  a1@(PCB_REGS),#0xFCFC   | and registers
        movl    a1@(PCB_USP),a0
        movl    a0,usp                  | and USP
        moveml  a1@(PCB_REGS),#0xFCFC   | and registers
        movl    a1@(PCB_USP),a0
        movl    a0,usp                  | and USP
-#ifdef PROFTIMER
-       tstl    a1@(U_PROFSCALE)        | process being profiled?
-       jeq     Lskipon                 | no, do nothing
-       orb     #1,_profon              | turn on user profiling bit
-#ifdef GPROF
-       jlt     Lskipon                 | already profiling kernel, all done
-#endif
-       CLKADDR(a0)
-       movl    _profint,d1             | profiling interval
-       subql   #1,d1                   |   adjusted
-       movepw  d1,a0@(CLKMSB3)         | set interval
-       movb    #0,a0@(CLKCR2)          | select CR3
-       movb    #64,a0@(CLKCR3)         | turn it on
-Lskipon:
-#endif
 #ifdef FPCOPROC
        lea     a1@(PCB_FPCTX),a0       | pointer to FP save area
        tstb    a0@                     | null state frame?
        jeq     Lresfprest              | yes, easy
 #ifdef FPCOPROC
        lea     a1@(PCB_FPCTX),a0       | pointer to FP save area
        tstb    a0@                     | null state frame?
        jeq     Lresfprest              | yes, easy
+#if defined(HP380)
+       cmpl    #-2,_mmutype            | 68040?
+       jne     Lresnot040              | no, skip
+       clrl    sp@-                    | yes...
+       frestore sp@+                   | ...magic!
+Lresnot040:
+#endif
        fmovem  a0@(312),fpcr/fpsr/fpi  | restore FP control registers
        fmovem  a0@(216),fp0-fp7        | restore FP general registers
 Lresfprest:
        frestore a0@                    | restore state
 #endif
        fmovem  a0@(312),fpcr/fpsr/fpi  | restore FP control registers
        fmovem  a0@(216),fp0-fp7        | restore FP general registers
 Lresfprest:
        frestore a0@                    | restore state
 #endif
-       tstl    a1@(PCB_SSWAP)          | do an alternate return?
-       jne     Lres3                   | yes, go reload regs
        movw    a1@(PCB_PS),sr          | no, restore PS
        movw    a1@(PCB_PS),sr          | no, restore PS
-       rts
-Lres3:
-       movl    a1@(PCB_SSWAP),a0       | addr of saved context
-       clrl    a1@(PCB_SSWAP)          | clear flag
-       moveml  a0@+,#0x7CFC            | restore registers
-       movl    a0@+,a1                 | and SP
-       cmpl    sp,a1                   | paranoia...
-       jge     Lres4                   | ...must be popping, yes?
-       lea     tmpstk,sp               | no! set up a legit stack
-       movl    #Lres5,sp@-             | push a panic message
-       jbsr    _panic                  | and panic
-       /* NOTREACHED */
-Lres4:
-       movl    a1,sp                   | restore SP
-       movl    a0@,sp@                 | and PC
-       moveq   #1,d0                   | arrange for non-zero return
-       movw    #PSL_LOWIPL,sr          | lower SPL
+       moveq   #1,d0                   | return 1 (for alternate returns)
        rts
 
        rts
 
-Lres5:
-       .asciz  "ldctx"
-       .even
+/*
+ * savectx(pcb, altreturn)
+ * Update pcb, saving current processor state and arranging
+ * for alternate return ala longjmp in switch if altreturn is true.
+ */
+ENTRY(savectx)
+       movl    sp@(4),a1
+       movw    sr,a1@(PCB_PS)
+       movl    usp,a0                  | grab USP
+       movl    a0,a1@(PCB_USP)         | and save it
+       moveml  #0xFCFC,a1@(PCB_REGS)   | save non-scratch registers
+#ifdef FPCOPROC
+       lea     a1@(PCB_FPCTX),a0       | pointer to FP save area
+       fsave   a0@                     | save FP state
+       tstb    a0@                     | null state frame?
+       jeq     Lsvnofpsave             | yes, all done
+       fmovem  fp0-fp7,a0@(216)        | save FP general registers
+       fmovem  fpcr/fpsr/fpi,a0@(312)  | save FP control registers
+Lsvnofpsave:
+#endif
+       tstl    sp@(8)                  | altreturn?
+       jeq     Lsavedone
+       movl    sp,d0                   | relocate current sp relative to a1
+       subl    #_kstack,d0             |   (sp is relative to kstack):
+       addl    d0,a1                   |   a1 += sp - kstack;
+       movl    sp@,a1@                 | write return pc at (relocated) sp@
+Lsavedone:
+       moveq   #0,d0                   | return 0
+       rts
 
 /*
  * {fu,su},{byte,sword,word}
  */
 ALTENTRY(fuiword, _fuword)
 ENTRY(fuword)
 
 /*
  * {fu,su},{byte,sword,word}
  */
 ALTENTRY(fuiword, _fuword)
 ENTRY(fuword)
-       movl    sp@(4),d0               | address to read
-       btst    #0,d0                   | is it odd?
-       jne     Lfserr                  | yes, a fault
-       movl    #Lfserr,_u+PCB_ONFAULT  | where to return to on a fault
-       movl    d0,a0
+       movl    sp@(4),a0               | address to read
+       movl    _curpcb,a1              | current pcb
+       movl    #Lfserr,a1@(PCB_ONFAULT) | where to return to on a fault
        movsl   a0@,d0                  | do read from user space
        movsl   a0@,d0                  | do read from user space
+       nop
        jra     Lfsdone
 
 ENTRY(fusword)
        jra     Lfsdone
 
 ENTRY(fusword)
-       movl    sp@(4),d0
-       btst    #0,d0                   | is address odd?
-       jne     Lfserr                  | yes, a fault
-       movl    #Lfserr,_u+PCB_ONFAULT  | where to return to on a fault
-       movl    d0,a0                   | address to read
+       movl    sp@(4),a0
+       movl    _curpcb,a1              | current pcb
+       movl    #Lfserr,a1@(PCB_ONFAULT) | where to return to on a fault
        moveq   #0,d0
        movsw   a0@,d0                  | do read from user space
        moveq   #0,d0
        movsw   a0@,d0                  | do read from user space
+       nop
+       jra     Lfsdone
+
+/* Just like fusword, but tells trap code not to page in. */
+ENTRY(fuswintr)
+       movl    sp@(4),a0
+       movl    _curpcb,a1
+       movl    #_fswintr,a1@(PCB_ONFAULT)
+       moveq   #0,d0
+       movsw   a0@,d0
+       nop
        jra     Lfsdone
 
 ALTENTRY(fuibyte, _fubyte)
 ENTRY(fubyte)
        jra     Lfsdone
 
 ALTENTRY(fuibyte, _fubyte)
 ENTRY(fubyte)
-       movl    #Lfserr,_u+PCB_ONFAULT  | where to return to on a fault
        movl    sp@(4),a0               | address to read
        movl    sp@(4),a0               | address to read
+       movl    _curpcb,a1              | current pcb
+       movl    #Lfserr,a1@(PCB_ONFAULT) | where to return to on a fault
        moveq   #0,d0
        movsb   a0@,d0                  | do read from user space
        moveq   #0,d0
        movsb   a0@,d0                  | do read from user space
+       nop
        jra     Lfsdone
 
 Lfserr:
        moveq   #-1,d0                  | error indicator
 Lfsdone:
        jra     Lfsdone
 
 Lfserr:
        moveq   #-1,d0                  | error indicator
 Lfsdone:
-       clrl    _u+PCB_ONFAULT          | clear fault address
+       clrl    a1@(PCB_ONFAULT)        | clear fault address
        rts
 
        rts
 
-ALTENTRY(suiword, _suword)
+/* Just like Lfserr, but the address is different (& exported). */
+       .globl  _fswintr
+_fswintr:
+       moveq   #-1,d0
+       jra     Lfsdone
+
+
+/*
+ * Write a longword in user instruction space.
+ * Largely the same as suword but with a final i-cache purge on those
+ * machines with split caches.
+ */
+ENTRY(suiword)
+       movl    sp@(4),a0               | address to write
+       movl    sp@(8),d0               | value to put there
+       movl    _curpcb,a1              | current pcb
+       movl    #Lfserr,a1@(PCB_ONFAULT) | where to return to on a fault
+       movsl   d0,a0@                  | do write to user space
+       nop
+       moveq   #0,d0                   | indicate no fault
+#if defined(HP380)
+       cmpl    #-2,_mmutype            | 68040?
+       jne     Lsuicpurge              | no, skip
+       .word   0xf498                  | cinva ic (XXX overkill)
+       jra     Lfsdone
+Lsuicpurge:
+#endif
+       movl    #IC_CLEAR,d1
+       movc    d1,cacr                 | invalidate i-cache
+       jra     Lfsdone
+
 ENTRY(suword)
 ENTRY(suword)
-       movl    sp@(4),d0               | address to write
-       btst    #0,d0                   | is it odd?
-       jne     Lfserr                  | yes, a fault
-       movl    #Lfserr,_u+PCB_ONFAULT  | where to return to on a fault
-       movl    d0,a0                   | address to write
+       movl    sp@(4),a0               | address to write
        movl    sp@(8),d0               | value to put there
        movl    sp@(8),d0               | value to put there
+       movl    _curpcb,a1              | current pcb
+       movl    #Lfserr,a1@(PCB_ONFAULT) | where to return to on a fault
        movsl   d0,a0@                  | do write to user space
        movsl   d0,a0@                  | do write to user space
+       nop
        moveq   #0,d0                   | indicate no fault
        jra     Lfsdone
 
 ENTRY(susword)
        moveq   #0,d0                   | indicate no fault
        jra     Lfsdone
 
 ENTRY(susword)
-       movl    sp@(4),d0               | address to write
-       btst    #0,d0                   | is it odd?
-       jne     Lfserr                  | yes, a fault
-       movl    #Lfserr,_u+PCB_ONFAULT  | where to return to on a fault
-       movl    d0,a0                   | address to write
+       movl    sp@(4),a0               | address to write
        movw    sp@(10),d0              | value to put there
        movw    sp@(10),d0              | value to put there
+       movl    _curpcb,a1              | current pcb
+       movl    #Lfserr,a1@(PCB_ONFAULT) | where to return to on a fault
        movsw   d0,a0@                  | do write to user space
        movsw   d0,a0@                  | do write to user space
+       nop
        moveq   #0,d0                   | indicate no fault
        jra     Lfsdone
 
        moveq   #0,d0                   | indicate no fault
        jra     Lfsdone
 
+ENTRY(suswintr)
+       movl    sp@(4),a0
+       movw    sp@(10),d0
+       movl    _curpcb,a1
+       movl    #_fswintr,a1@(PCB_ONFAULT)
+       movsw   d0,a0@
+       nop
+       moveq   #0,d0
+       jra     Lfsdone
+
 ALTENTRY(suibyte, _subyte)
 ENTRY(subyte)
 ALTENTRY(suibyte, _subyte)
 ENTRY(subyte)
-       movl    #Lfserr,_u+PCB_ONFAULT  | where to return to on a fault
        movl    sp@(4),a0               | address to write
        movb    sp@(11),d0              | value to put there
        movl    sp@(4),a0               | address to write
        movb    sp@(11),d0              | value to put there
+       movl    _curpcb,a1              | current pcb
+       movl    #Lfserr,a1@(PCB_ONFAULT) | where to return to on a fault
        movsb   d0,a0@                  | do write to user space
        movsb   d0,a0@                  | do write to user space
+       nop
        moveq   #0,d0                   | indicate no fault
        jra     Lfsdone
 
        moveq   #0,d0                   | indicate no fault
        jra     Lfsdone
 
-/*
- * Copy 1 relocation unit (NBPG bytes)
- * from user virtual address to physical address
- */
-ENTRY(copyseg)
-       movl    sp@(8),d0                       | destination page number
-       moveq   #PGSHIFT,d1
-       lsll    d1,d0                           | convert to address
-       orl     #PG_CI+PG_RW+PG_V,d0            | make sure valid and writable
-       movl    _CMAP2,a0
-       movl    _CADDR2,sp@-                    | destination kernel VA
-       movl    d0,a0@                          | load in page table
-       jbsr    _TBIS                           | invalidate any old mapping
-       addql   #4,sp
-       movl    _CADDR2,a1                      | destination addr
-       movl    sp@(4),a0                       | source addr
-       movl    #NBPG/4-1,d0                    | count
-       movl    #Lcpydone,_u+PCB_ONFAULT        | where to go on a fault
-Lcpyloop:
-       movsl   a0@+,d1                         | read longword
-       movl    d1,a1@+                         | write longword
-       dbf     d0,Lcpyloop                     | continue until done
-Lcpydone:
-       clrl    _u+PCB_ONFAULT                  | clear error catch
-       rts
-
-/*
- * Copy 1 relocation unit (NBPG bytes)
- * from physical address to physical address
- */
-ENTRY(physcopyseg)
-       movl    sp@(4),d0                       | source page number
-       moveq   #PGSHIFT,d1
-       lsll    d1,d0                           | convert to address
-       orl     #PG_CI+PG_RW+PG_V,d0            | make sure valid and writable
-       movl    _CMAP1,a0
-       movl    d0,a0@                          | load in page table
-       movl    _CADDR1,sp@-                    | destination kernel VA
-       jbsr    _TBIS                           | invalidate any old mapping
-       addql   #4,sp
-
-       movl    sp@(8),d0                       | destination page number
-       moveq   #PGSHIFT,d1
-       lsll    d1,d0                           | convert to address
-       orl     #PG_CI+PG_RW+PG_V,d0            | make sure valid and writable
-       movl    _CMAP2,a0
-       movl    d0,a0@                          | load in page table
-       movl    _CADDR2,sp@-                    | destination kernel VA
-       jbsr    _TBIS                           | invalidate any old mapping
-       addql   #4,sp
-
-       movl    _CADDR1,a0                      | source addr
-       movl    _CADDR2,a1                      | destination addr
-       movl    #NBPG/4-1,d0                    | count
-Lpcpy:
-       movl    a0@+,a1@+                       | copy longword
-       dbf     d0,Lpcpy                        | continue until done
-       rts
-
-/*
- * zero out physical memory
- * specified in relocation units (NBPG bytes)
- */
-ENTRY(clearseg)
-       movl    sp@(4),d0                       | destination page number
-       moveq   #PGSHIFT,d1
-       lsll    d1,d0                           | convert to address
-       orl     #PG_CI+PG_RW+PG_V,d0            | make sure valid and writable
-       movl    _CMAP1,a0
-       movl    _CADDR1,sp@-                    | destination kernel VA
-       movl    d0,a0@                          | load in page map
-       jbsr    _TBIS                           | invalidate any old mapping
-       addql   #4,sp
-       movl    _CADDR1,a1                      | destination addr
-       movl    #NBPG/4-1,d0                    | count
-/* simple clear loop is fastest on 68020 */
-Lclrloop:
-       clrl    a1@+                            | clear a longword
-       dbf     d0,Lclrloop                     | continue til done
+#if defined(HP380)
+ENTRY(suline)
+       movl    sp@(4),a0               | address to write
+       movl    _curpcb,a1              | current pcb
+       movl    #Lslerr,a1@(PCB_ONFAULT) | where to return to on a fault
+       movl    sp@(8),a1               | address of line
+       movl    a1@+,d0                 | get lword
+       movsl   d0,a0@+                 | put lword
+       nop                             | sync
+       movl    a1@+,d0                 | get lword
+       movsl   d0,a0@+                 | put lword
+       nop                             | sync
+       movl    a1@+,d0                 | get lword
+       movsl   d0,a0@+                 | put lword
+       nop                             | sync
+       movl    a1@+,d0                 | get lword
+       movsl   d0,a0@+                 | put lword
+       nop                             | sync
+       moveq   #0,d0                   | indicate no fault
+       jra     Lsldone
+Lslerr:
+       moveq   #-1,d0
+Lsldone:
+       movl    _curpcb,a1              | current pcb
+       clrl    a1@(PCB_ONFAULT)        | clear fault address
        rts
        rts
+#endif
 
 /*
  * Invalidate entire TLB.
  */
 ENTRY(TBIA)
 __TBIA:
 
 /*
  * Invalidate entire TLB.
  */
 ENTRY(TBIA)
 __TBIA:
+#if defined(HP380)
+       cmpl    #-2,_mmutype            | 68040?
+       jne     Lmotommu3               | no, skip
+       .word   0xf518                  | yes, pflusha
+       rts
+Lmotommu3:
+#endif
 #if defined(HP330) || defined(HP360) || defined(HP370)
        tstl    _mmutype                | HP MMU?
        jeq     Lhpmmu6                 | yes, skip
 #if defined(HP330) || defined(HP360) || defined(HP370)
        tstl    _mmutype                | HP MMU?
        jeq     Lhpmmu6                 | yes, skip
@@ -1937,6 +2023,21 @@ ENTRY(TBIS)
        tstl    fulltflush              | being conservative?
        jne     __TBIA                  | yes, flush entire TLB
 #endif
        tstl    fulltflush              | being conservative?
        jne     __TBIA                  | yes, flush entire TLB
 #endif
+#if defined(HP380)
+       cmpl    #-2,_mmutype            | 68040?
+       jne     Lmotommu4               | no, skip
+       movl    sp@(4),a0
+       movc    dfc,d1
+       moveq   #1,d0                   | user space
+       movc    d0,dfc
+       .word   0xf508                  | pflush a0@
+       moveq   #5,d0                   | super space
+       movc    d0,dfc
+       .word   0xf508                  | pflush a0@
+       movc    d1,dfc
+       rts
+Lmotommu4:
+#endif
 #if defined(HP330) || defined(HP360) || defined(HP370)
        tstl    _mmutype                | HP MMU?
        jeq     Lhpmmu5                 | yes, skip
 #if defined(HP330) || defined(HP360) || defined(HP370)
        tstl    _mmutype                | HP MMU?
        jeq     Lhpmmu5                 | yes, skip
@@ -1977,6 +2078,13 @@ ENTRY(TBIAS)
        tstl    fulltflush              | being conservative?
        jne     __TBIA                  | yes, flush everything
 #endif
        tstl    fulltflush              | being conservative?
        jne     __TBIA                  | yes, flush everything
 #endif
+#if defined(HP380)
+       cmpl    #-2,_mmutype            | 68040?
+       jne     Lmotommu5               | no, skip
+       .word   0xf518                  | yes, pflusha (for now) XXX
+       rts
+Lmotommu5:
+#endif
 #if defined(HP330) || defined(HP360) || defined(HP370)
        tstl    _mmutype                | HP MMU?
        jeq     Lhpmmu7                 | yes, skip
 #if defined(HP330) || defined(HP360) || defined(HP370)
        tstl    _mmutype                | HP MMU?
        jeq     Lhpmmu7                 | yes, skip
@@ -2011,6 +2119,13 @@ ENTRY(TBIAU)
        tstl    fulltflush              | being conservative?
        jne     __TBIA                  | yes, flush everything
 #endif
        tstl    fulltflush              | being conservative?
        jne     __TBIA                  | yes, flush everything
 #endif
+#if defined(HP380)
+       cmpl    #-2,_mmutype            | 68040?
+       jne     Lmotommu6               | no, skip
+       .word   0xf518                  | yes, pflusha (for now) XXX
+       rts
+Lmotommu6:
+#endif
 #if defined(HP330) || defined(HP360) || defined(HP370)
        tstl    _mmutype                | HP MMU?
        jeq     Lhpmmu8                 | yes, skip
 #if defined(HP330) || defined(HP360) || defined(HP370)
        tstl    _mmutype                | HP MMU?
        jeq     Lhpmmu8                 | yes, skip
@@ -2041,6 +2156,14 @@ Lhpmmu8:
  * Invalidate instruction cache
  */
 ENTRY(ICIA)
  * Invalidate instruction cache
  */
 ENTRY(ICIA)
+#if defined(HP380)
+ENTRY(ICPA)
+       cmpl    #-2,_mmutype            | 68040
+       jne     Lmotommu7               | no, skip
+       .word   0xf498                  | cinva ic
+       rts
+Lmotommu7:
+#endif
        movl    #IC_CLEAR,d0
        movc    d0,cacr                 | invalidate i-cache
        rts
        movl    #IC_CLEAR,d0
        movc    d0,cacr                 | invalidate i-cache
        rts
@@ -2055,6 +2178,13 @@ ENTRY(ICIA)
  */
 ENTRY(DCIA)
 __DCIA:
  */
 ENTRY(DCIA)
 __DCIA:
+#if defined(HP380)
+       cmpl    #-2,_mmutype            | 68040
+       jne     Lmotommu8               | no, skip
+       /* XXX implement */
+       rts
+Lmotommu8:
+#endif
 #if defined(HP320) || defined(HP350)
        tstl    _ectype                 | got external VAC?
        jle     Lnocache2               | no, all done
 #if defined(HP320) || defined(HP350)
        tstl    _ectype                 | got external VAC?
        jle     Lnocache2               | no, all done
@@ -2067,6 +2197,13 @@ Lnocache2:
 
 ENTRY(DCIS)
 __DCIS:
 
 ENTRY(DCIS)
 __DCIS:
+#if defined(HP380)
+       cmpl    #-2,_mmutype            | 68040
+       jne     Lmotommu9               | no, skip
+       /* XXX implement */
+       rts
+Lmotommu9:
+#endif
 #if defined(HP320) || defined(HP350)
        tstl    _ectype                 | got external VAC?
        jle     Lnocache3               | no, all done
 #if defined(HP320) || defined(HP350)
        tstl    _ectype                 | got external VAC?
        jle     Lnocache3               | no, all done
@@ -2079,6 +2216,13 @@ Lnocache3:
 
 ENTRY(DCIU)
 __DCIU:
 
 ENTRY(DCIU)
 __DCIU:
+#if defined(HP380)
+       cmpl    #-2,_mmutype            | 68040
+       jne     LmotommuA               | no, skip
+       /* XXX implement */
+       rts
+LmotommuA:
+#endif
 #if defined(HP320) || defined(HP350)
        tstl    _ectype                 | got external VAC?
        jle     Lnocache4               | no, all done
 #if defined(HP320) || defined(HP350)
        tstl    _ectype                 | got external VAC?
        jle     Lnocache4               | no, all done
@@ -2089,7 +2233,45 @@ Lnocache4:
 #endif
        rts
 
 #endif
        rts
 
+#if defined(HP380)
+ENTRY(ICPL)
+       movl    sp@(4),a0               | address
+       .word   0xf488                  | cinvl ic,a0@
+       rts
+ENTRY(ICPP)
+       movl    sp@(4),a0               | address
+       .word   0xf490                  | cinvp ic,a0@
+       rts
+ENTRY(DCPL)
+       movl    sp@(4),a0               | address
+       .word   0xf448                  | cinvl dc,a0@
+       rts
+ENTRY(DCPP)
+       movl    sp@(4),a0               | address
+       .word   0xf450                  | cinvp dc,a0@
+       rts
+ENTRY(DCPA)
+       .word   0xf458                  | cinva dc
+       rts
+ENTRY(DCFL)
+       movl    sp@(4),a0               | address
+       .word   0xf468                  | cpushl dc,a0@
+       rts
+ENTRY(DCFP)
+       movl    sp@(4),a0               | address
+       .word   0xf470                  | cpushp dc,a0@
+       rts
+#endif
+
 ENTRY(PCIA)
 ENTRY(PCIA)
+#if defined(HP380)
+ENTRY(DCFA)
+       cmpl    #-2,_mmutype            | 68040
+       jne     LmotommuB               | no, skip
+       .word   0xf478                  | cpusha dc
+       rts
+LmotommuB:
+#endif
 #if defined(HP360) || defined(HP370)
        movl    #DC_CLEAR,d0
        movc    d0,cacr                 | invalidate on-chip d-cache
 #if defined(HP360) || defined(HP370)
        movl    #DC_CLEAR,d0
        movc    d0,cacr                 | invalidate on-chip d-cache
@@ -2118,6 +2300,18 @@ ENTRY(ecacheoff)
 Lnocache8:
        rts
 
 Lnocache8:
        rts
 
+/*
+ * Get callers current SP value.
+ * Note that simply taking the address of a local variable in a C function
+ * doesn't work because callee saved registers may be outside the stack frame
+ * defined by A6 (e.g. GCC generated code).
+ */
+       .globl  _getsp
+_getsp:
+       movl    sp,d0                   | get current SP
+       addql   #4,d0                   | compensate for return address
+       rts
+
        .globl  _getsfc, _getdfc
 _getsfc:
        movc    sfc,d0
        .globl  _getsfc, _getdfc
 _getsfc:
        movc    sfc,d0
@@ -2130,12 +2324,19 @@ _getdfc:
  * Load a new user segment table pointer.
  */
 ENTRY(loadustp)
  * Load a new user segment table pointer.
  */
 ENTRY(loadustp)
-#if defined(HP330) || defined(HP360) || defined(HP370)
+#if defined(HP330) || defined(HP360) || defined(HP370) || defined(HP380)
        tstl    _mmutype                | HP MMU?
        jeq     Lhpmmu9                 | yes, skip
        movl    sp@(4),d0               | new USTP
        moveq   #PGSHIFT,d1
        lsll    d1,d0                   | convert to addr
        tstl    _mmutype                | HP MMU?
        jeq     Lhpmmu9                 | yes, skip
        movl    sp@(4),d0               | new USTP
        moveq   #PGSHIFT,d1
        lsll    d1,d0                   | convert to addr
+#if defined(HP380)
+       cmpl    #-2,_mmutype            | 68040?
+       jne     LmotommuC               | no, skip
+       .long   0x4e7b0806              | movc d0,urp
+       rts
+LmotommuC:
+#endif
        lea     _protorp,a0             | CRP prototype
        movl    d0,a0@(4)               | stash USTP
        pmove   a0@,crp                 | load root pointer
        lea     _protorp,a0             | CRP prototype
        movl    d0,a0@(4)               | stash USTP
        pmove   a0@,crp                 | load root pointer
@@ -2150,24 +2351,6 @@ Lhpmmu9:
 #endif
        rts
 
 #endif
        rts
 
-/*
- * Flush any hardware context associated with given USTP.
- * Only does something for HP330 where we must flush RPT
- * and ATC entries in PMMU.
- */
-ENTRY(flushustp)
-#if defined(HP330)
-       tstl    _mmutype                | 68851 PMMU?
-       jle     Lnot68851               | no, nothing to do
-       movl    sp@(4),d0               | get USTP to flush
-       moveq   #PGSHIFT,d1
-       lsll    d1,d0                   | convert to address
-       movl    d0,_protorp+4           | stash USTP
-       pflushr _protorp                | flush RPT/TLB entries
-Lnot68851:
-#endif
-       rts
-
 ENTRY(ploadw)
 #if defined(HP330) || defined(HP360) || defined(HP370)
        movl    sp@(4),a0               | address to load
 ENTRY(ploadw)
 #if defined(HP330) || defined(HP360) || defined(HP370)
        movl    sp@(4),a0               | address to load
@@ -2176,26 +2359,15 @@ ENTRY(ploadw)
        rts
 
 /*
        rts
 
 /*
- * Set processor priority level calls.  Most could (should) be replaced
- * by inline asm expansions.  However, SPL0 and SPLX require special
- * handling.  If we are returning to the base processor priority (SPL0)
- * we need to check for our emulated software interrupts.
+ * Set processor priority level calls.  Most are implemented with
+ * inline asm expansions.  However, spl0 requires special handling
+ * as we need to check for our emulated software interrupts.
  */
 
 ENTRY(spl0)
        moveq   #0,d0
        movw    sr,d0                   | get old SR for return
        movw    #PSL_LOWIPL,sr          | restore new SR
  */
 
 ENTRY(spl0)
        moveq   #0,d0
        movw    sr,d0                   | get old SR for return
        movw    #PSL_LOWIPL,sr          | restore new SR
-       jra     Lsplsir
-
-ENTRY(splx)
-       moveq   #0,d0
-       movw    sr,d0                   | get current SR for return
-       movw    sp@(6),d1               | get new value
-       movw    d1,sr                   | restore new SR
-       andw    #PSL_IPL7,d1            | mask all but PSL_IPL
-       jne     Lspldone                | non-zero, all done
-Lsplsir:
        tstb    _ssir                   | software interrupt pending?
        jeq     Lspldone                | no, all done
        subql   #4,sp                   | make room for RTE frame
        tstb    _ssir                   | software interrupt pending?
        jeq     Lspldone                | no, all done
        subql   #4,sp                   | make room for RTE frame
@@ -2206,75 +2378,6 @@ Lsplsir:
 Lspldone:
        rts
 
 Lspldone:
        rts
 
-ALTENTRY(splsoftclock, _spl1)
-ALTENTRY(splnet, _spl1)
-ENTRY(spl1)
-       moveq   #0,d0
-       movw    sr,d0
-       movw    #SPL1,sr
-       rts
-
-ENTRY(spl2)
-       moveq   #0,d0
-       movw    sr,d0
-       movw    #SPL2,sr
-       rts
-
-ENTRY(spl3)
-       moveq   #0,d0
-       movw    sr,d0
-       movw    #SPL3,sr
-       rts
-
-ENTRY(spl4)
-       moveq   #0,d0
-       movw    sr,d0
-       movw    #SPL4,sr
-       rts
-
-ALTENTRY(splimp, _spl5)
-ALTENTRY(splbio, _spl5)
-ALTENTRY(spltty, _spl5)
-ENTRY(spl5)
-       moveq   #0,d0
-       movw    sr,d0
-       movw    #SPL5,sr
-       rts
-
-ALTENTRY(splclock, _spl6)
-ENTRY(spl6)
-       moveq   #0,d0
-       movw    sr,d0
-       movw    #SPL6,sr
-       rts
-
-ALTENTRY(splhigh, _spl7)
-ENTRY(spl7)
-       moveq   #0,d0
-       movw    sr,d0
-       movw    #PSL_HIGHIPL,sr
-       rts
-
-#ifdef GPROF
-/*
- * Special versions of splhigh and splx called by mcount().
- * Note that __splx does not check for software interrupts.
- */
-       .globl  __splhigh, __splx
-__splhigh:
-       moveq   #0,d0
-       movw    sr,d0
-       movw    #PSL_HIGHIPL,sr
-       rts
-
-__splx:
-       moveq   #0,d0
-       movw    sr,d0                   | get current SR for return
-       movw    sp@(6),d1               | get new value
-       movw    d1,sr                   | restore new SR
-       rts
-#endif
-
 ENTRY(_insque)
        movw    sr,d0
        movw    #PSL_HIGHIPL,sr         | atomic
 ENTRY(_insque)
        movw    sr,d0
        movw    #PSL_HIGHIPL,sr         | atomic
@@ -2534,6 +2637,10 @@ Lm68881rdone:
  */
        .globl  _doboot
 _doboot:
  */
        .globl  _doboot
 _doboot:
+#if defined(HP380)
+       cmpl    #-2,_mmutype            | 68040?
+       jeq     Lnocache5               | yes, skip
+#endif
        movl    #CACHE_OFF,d0
        movc    d0,cacr                 | disable on-chip cache(s)
 #if defined(HP320) || defined(HP350) || defined(HP370)
        movl    #CACHE_OFF,d0
        movc    d0,cacr                 | disable on-chip cache(s)
 #if defined(HP320) || defined(HP350) || defined(HP370)
@@ -2541,8 +2648,8 @@ _doboot:
        jeq     Lnocache5
        MMUADDR(a0)
        andl    #~MMU_CEN,a0@(MMUCMD)   | disable external cache
        jeq     Lnocache5
        MMUADDR(a0)
        andl    #~MMU_CEN,a0@(MMUCMD)   | disable external cache
-Lnocache5:
 #endif
 #endif
+Lnocache5:
        lea     MAXADDR,a0              | last page of physical memory
        movl    _boothowto,a0@+         | store howto
        movl    _bootdev,a0@+           | and devtype
        lea     MAXADDR,a0              | last page of physical memory
        movl    _boothowto,a0@+         | store howto
        movl    _bootdev,a0@+           | and devtype
@@ -2552,10 +2659,26 @@ Lbootcopy:
        movw    a1@+,a0@+               | copy a word
        cmpl    a3,a1                   | done yet?
        jcs     Lbootcopy               | no, keep going
        movw    a1@+,a0@+               | copy a word
        cmpl    a3,a1                   | done yet?
        jcs     Lbootcopy               | no, keep going
+#if defined(HP380)
+       cmpl    #-2,_mmutype            | 68040?
+       jne     LmotommuE               | no, skip
+       .word   0xf4f8                  | cpusha bc
+LmotommuE:
+#endif
        jmp     MAXADDR+8               | jump to last page
 
 Lbootcode:
        lea     MAXADDR+0x800,sp        | physical SP in case of NMI
        jmp     MAXADDR+8               | jump to last page
 
 Lbootcode:
        lea     MAXADDR+0x800,sp        | physical SP in case of NMI
+#if defined(HP380)
+       cmpl    #-2,_mmutype            | 68040?
+       jne     LmotommuF               | no, skip
+       movl    #0,d0
+       movc    d0,cacr                 | caches off
+       .long   0x4e7b0003              | movc d0,tc
+       movl    d2,MAXADDR+NBPG-4       | restore old high page contents
+       jmp     0x1A4                   | goto REQ_REBOOT
+LmotommuF:
+#endif
 #if defined(HP330) || defined(HP360) || defined(HP370)
        tstl    _mmutype                | HP MMU?
        jeq     LhpmmuB                 | yes, skip
 #if defined(HP330) || defined(HP360) || defined(HP370)
        tstl    _mmutype                | HP MMU?
        jeq     LhpmmuB                 | yes, skip
@@ -2573,8 +2696,6 @@ LhpmmuB:
 Lebootcode:
 
        .data
 Lebootcode:
 
        .data
-       .space  NBPG
-tmpstk:
        .globl  _machineid
 _machineid:
        .long   0               | default to 320
        .globl  _machineid
 _machineid:
        .long   0               | default to 320
@@ -2592,24 +2713,54 @@ _internalhpib:
        .globl  _cold
 _cold:
        .long   1               | cold start flag
        .globl  _cold
 _cold:
        .long   1               | cold start flag
-       .globl  _DIObase, _CLKbase, _MMUbase, _proc0paddr
+       .globl  _want_resched
+_want_resched:
+       .long   0
+       .globl  _intiobase, _intiolimit, _extiobase, _CLKbase, _MMUbase
+       .globl  _proc0paddr
 _proc0paddr:
        .long   0               | KVA of proc0 u-area
 _proc0paddr:
        .long   0               | KVA of proc0 u-area
-_DIObase:
-       .long   0               | KVA of base of IO space
+_intiobase:
+       .long   0               | KVA of base of internal IO space
+_intiolimit:
+       .long   0               | KVA of end of internal IO space
+_extiobase:
+       .long   0               | KVA of base of external IO space
 _CLKbase:
        .long   0               | KVA of base of clock registers
 _MMUbase:
        .long   0               | KVA of base of HP MMU registers
 _CLKbase:
        .long   0               | KVA of base of clock registers
 _MMUbase:
        .long   0               | KVA of base of HP MMU registers
+#ifdef USELEDS
+heartbeat:
+       .long   0               | clock ticks since last pulse of heartbeat
+#endif
 #ifdef DEBUG
        .globl  fulltflush, fullcflush
 fulltflush:
        .long   0
 fullcflush:
        .long   0
 #ifdef DEBUG
        .globl  fulltflush, fullcflush
 fulltflush:
        .long   0
 fullcflush:
        .long   0
-       .globl  timebomb
-timebomb:
+#endif
+#ifdef HPFPLIB
+/*
+ * Undefined symbols from hpux_float.o:
+ *
+ * kdb_printf: A kernel debugger print routine, we just use printf instead.
+ * processor:  HP-UX equiv. of machineid, set to 3 if it is a 68040.
+ * u:          Ye ole u-area.  The code wants to grab the first longword
+ *             indirect off of that and clear the 0x40000 bit there.
+ *             Oddly enough this was incorrect even in HP-UX!
+ * runrun:     Old name for want_resched.
+ */
+       .globl  _kdb_printf,_processor,_u,_runrun
+_kdb_printf:
+       .long   _printf
+_processor:
+       .long   0
+_u:
+       .long   .+4
        .long   0
        .long   0
+       .set    _runrun,_want_resched
 #endif
 /* interrupt counters */
        .globl  _intrcnt,_eintrcnt,_intrnames,_eintrnames
 #endif
 /* interrupt counters */
        .globl  _intrcnt,_eintrcnt,_intrnames,_eintrnames
@@ -2622,16 +2773,10 @@ _intrnames:
        .asciz  "lev5"
        .asciz  "dma"
        .asciz  "clock"
        .asciz  "lev5"
        .asciz  "dma"
        .asciz  "clock"
-#ifdef PROFTIMER
-       .asciz  "pclock"
-#endif
+       .asciz  "statclock"
        .asciz  "nmi"
 _eintrnames:
        .even
 _intrcnt:
        .asciz  "nmi"
 _eintrnames:
        .even
 _intrcnt:
-#ifdef PROFTIMER
        .long   0,0,0,0,0,0,0,0,0,0
        .long   0,0,0,0,0,0,0,0,0,0
-#else
-       .long   0,0,0,0,0,0,0,0,0
-#endif
 _eintrcnt:
 _eintrcnt: