BSD 4_3_Net_2 release
[unix-history] / usr / src / sys / i386 / i386 / locore.s
index db30bb8..30258d6 100644 (file)
@@ -5,22 +5,49 @@
  * This code is derived from software contributed to Berkeley by
  * William Jolitz.
  *
  * This code is derived from software contributed to Berkeley by
  * William Jolitz.
  *
- * %sccs.include.386.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.
  *
  *
- *     @(#)locore.s    5.9 (Berkeley) %G%
+ * 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.3 (Berkeley) 5/13/91
  */
 
  */
 
+
 /*
  * locore.s:   4BSD machine support for the Intel 386
  *             Preliminary version
  *             Written by William F. Jolitz, 386BSD Project
  */
 
 /*
  * locore.s:   4BSD machine support for the Intel 386
  *             Preliminary version
  *             Written by William F. Jolitz, 386BSD Project
  */
 
+#include "assym.s"
 #include "machine/psl.h"
 #include "machine/pte.h"
 
 #include "errno.h"
 #include "machine/psl.h"
 #include "machine/pte.h"
 
 #include "errno.h"
-#include "cmap.h"
 
 #include "machine/trap.h"
 
 
 #include "machine/trap.h"
 
        .set    IDXSHIFT,10
        .set    SYSTEM,0xFE000000       # virtual address of system start
        /*note: gas copys sign bit (e.g. arithmetic >>), can't do SYSTEM>>22! */
        .set    IDXSHIFT,10
        .set    SYSTEM,0xFE000000       # virtual address of system start
        /*note: gas copys sign bit (e.g. arithmetic >>), can't do SYSTEM>>22! */
-       .set    SYSPDROFF,0x3F8         # Page dir
-
-       .set    IOPHYSmem,0xa0000
+       .set    SYSPDROFF,0x3F8         # Page dir index of System Base
 
 /* IBM "compatible" nop - sensitive macro on "fast" 386 machines */
 
 /* IBM "compatible" nop - sensitive macro on "fast" 386 machines */
-#define        NOP     jmp 7f ; nop ; 7: jmp 7f ; nop ; 7:
+#define        NOP     ;
+
+/*
+ * PTmap is recursive pagemap at top of virtual address space.
+ * Within PTmap, the page directory can be found (third indirection).
+ */
+       .set    PDRPDROFF,0x3F7         # Page dir index of Page dir
+       .globl  _PTmap, _PTD, _PTDpde
+       .set    _PTmap,0xFDC00000
+       .set    _PTD,0xFDFF7000
+       .set    _PTDpde,0xFDFF7000+4*PDRPDROFF
 
 /*
 
 /*
- * User structure is UPAGES at top of user space.
+ * APTmap, APTD is the alternate recursive pagemap.
+ * It's used when modifying another process's page tables.
  */
  */
-       .set    _u,0xFDFFE000
-       .globl  _u
-       .set    UPDROFF,0x3F7
-       .set    UPTEOFF,0x3FE
+       .set    APDRPDROFF,0x3FE                # Page dir index of Page dir
+       .globl  _APTmap, _APTD, _APTDpde
+       .set    _APTmap,0xFF800000
+       .set    _APTD,0xFFBFE000
+       .set    _APTDpde,0xFDFF7000+4*APDRPDROFF
+
+/*
+ * Access to each processes kernel stack is via a region of
+ * per-process address space (at the beginning), immediatly above
+ * the user process stack.
+ */
+       .set    _kstack, USRSTACK
+       .globl  _kstack
+       .set    PPDROFF,0x3F6
+       .set    PPTEOFF,0x400-UPAGES    # 0x3FE
 
 #define        ENTRY(name) \
        .globl _/**/name; _/**/name:
 #define        ALTENTRY(name) \
        .globl _/**/name; _/**/name:
 
 
 #define        ENTRY(name) \
        .globl _/**/name; _/**/name:
 #define        ALTENTRY(name) \
        .globl _/**/name; _/**/name:
 
-/*
- * System page table
- * Mbmap and Usrptmap are enlarged by CLSIZE entries
- * as they are managed by resource maps starting with index 1 or CLSIZE.
- */ 
-#define        SYSMAP(mname, vname, npte)              \
-_/**/mname:    .globl  _/**/mname;             \
-       .space  (npte)*4;                       \
-       .set    _/**/vname,ptes*NBPG+SYSTEM;    \
-       .globl  _/**/vname;                     \
-       .set    ptes,ptes + npte
-#define        ZSYSMAP(mname, vname, npte)             \
-_/**/mname:    .globl  _/**/mname;             \
-       .set    _/**/vname,ptes*NBPG+SYSTEM;    \
-       .globl  _/**/vname;
-
-       .data
-       # assumed to start at data mod 4096
-       .set    ptes,0
-       SYSMAP(Sysmap,Sysbase,SYSPTSIZE)
-       SYSMAP(Forkmap,forkutl,UPAGES)
-       SYSMAP(Xswapmap,xswaputl,UPAGES)
-       SYSMAP(Xswap2map,xswap2utl,UPAGES)
-       SYSMAP(Swapmap,swaputl,UPAGES)
-       SYSMAP(Pushmap,pushutl,UPAGES)
-       SYSMAP(Vfmap,vfutl,UPAGES)
-       SYSMAP(CMAP1,CADDR1,1)
-       SYSMAP(CMAP2,CADDR2,1)
-       SYSMAP(mmap,vmmap,1)
-       SYSMAP(alignmap,alignutl,1)     /* XXX */
-       SYSMAP(msgbufmap,msgbuf,MSGBUFPTECNT)
-       /* SYSMAP(EMCmap,EMCbase,1) */
-       SYSMAP(Npxmap,npxutl,UPAGES)
-       SYSMAP(Swtchmap,Swtchbase,UPAGES)
-       .set mbxxx,(NMBCLUSTERS*MCLBYTES)
-       .set mbyyy,(mbxxx>>PGSHIFT)
-       .set mbpgs,(mbyyy+CLSIZE)
-       SYSMAP(Mbmap,mbutl,mbpgs)
-       /*
-        * XXX: NEED way to compute kmem size from maxusers,
-        * device complement
-        */
-       SYSMAP(kmempt,kmembase,300*CLSIZE)
-#ifdef GPROF
-       SYSMAP(profmap,profbase,600*CLSIZE)
-#endif
-       .set    atmemsz,0x100000-0xa0000
-       .set    atpgs,(atmemsz>>PGSHIFT)
-       SYSMAP(ATDevmem,atdevbase,atpgs)
-       SYSMAP(Usriomap,usrio,USRIOSIZE+CLSIZE) /* for PHYSIO */
-       ZSYSMAP(ekmempt,kmemlimit,0)
-       SYSMAP(Usrptmap,usrpt,USRPTSIZE+CLSIZE)
-
-eSysmap:
-       # .set  _Syssize,(eSysmap-_Sysmap)/4
-       .set    _Syssize,ptes
-       .globl  _Syssize
-
-       /* align on next page boundary */
-       # . = . + NBPG - 1 & -NBPG      /* align to page boundry-does not work*/
-       # .space (PGSIZE - ((eSysmap-_Sysmap) % PGSIZE)) % PGSIZE
-       .set sz,(4*ptes)%NBPG
-       # .set rptes,(ptes)%1024
-       # .set rptes,1024-rptes
-       # .set ptes,ptes+rptes
-       .set Npdes,8
-       # .space (NBPG - sz)
-
 /*
  * Initialization
  */
        .data
 /*
  * Initialization
  */
        .data
-       .globl  _cpu, _cold, _boothowto, _bootdev, _cyloffset, _Maxmem
+       .globl  _cpu,_cold,_boothowto,_bootdev,_cyloffset,_atdevbase,_atdevphys
 _cpu:  .long   0               # are we 386, 386sx, or 486
 _cold: .long   1               # cold till we are not
 _cpu:  .long   0               # are we 386, 386sx, or 486
 _cold: .long   1               # cold till we are not
+_atdevbase:    .long   0       # location of start of iomem in virtual
+_atdevphys:    .long   0       # location of device mapping ptes (phys)
+
+       .globl  _IdlePTD, _KPTphys
+_IdlePTD:      .long   0
+_KPTphys:      .long   0
+
+       .space 512
+tmpstk:
        .text
        .globl  start
        .text
        .globl  start
-start:                         # This is assumed to be location zero!
-       movw    $0x1234,%ax
+start: movw    $0x1234,%ax
        movw    %ax,0x472       # warm boot
        jmp     1f
        .space  0x500           # skip over warm boot shit
 
        movw    %ax,0x472       # warm boot
        jmp     1f
        .space  0x500           # skip over warm boot shit
 
-       /* enable a20! yecchh!! */
+       /* enable a20! yecchh!! - move this to bootstrap? */
 1:     inb     $0x64,%al
        andb    $2,%al
        jnz     1b
 1:     inb     $0x64,%al
        andb    $2,%al
        jnz     1b
@@ -151,9 +138,13 @@ start:                             # This is assumed to be location zero!
        NOP
        outb    %al,$0x60
 
        NOP
        outb    %al,$0x60
 
-       /* pass parameters on stack (howto, bootdev, unit, cyloffset) */
+       /*
+        * pass parameters on stack (howto, bootdev, unit, cyloffset)
+        * note: 0(%esp) is return address of boot
+        * ( if we want to hold onto /boot, it's physical %esp up to _end)
+        */
 
 
      movl    4(%esp),%eax
1:    movl    4(%esp),%eax
        movl    %eax,_boothowto-SYSTEM
        movl    8(%esp),%eax
        movl    %eax,_bootdev-SYSTEM
        movl    %eax,_boothowto-SYSTEM
        movl    8(%esp),%eax
        movl    %eax,_bootdev-SYSTEM
@@ -167,6 +158,7 @@ start:                              # This is assumed to be location zero!
        movl    $ 0xA0,%ecx             # look every 4K up to 640K
 1:     movl    0(%eax),%ebx            # save location to check
        movl    $0xa55a5aa5,0(%eax)     # write test pattern
        movl    $ 0xA0,%ecx             # look every 4K up to 640K
 1:     movl    0(%eax),%ebx            # save location to check
        movl    $0xa55a5aa5,0(%eax)     # write test pattern
+       /* flush stupid cache here! (with bcopy (0,0,512*1024) ) */
        cmpl    $0xa55a5aa5,0(%eax)     # does not check yet for rollover
        jne     2f
        movl    %ebx,0(%eax)            # restore memory
        cmpl    $0xa55a5aa5,0(%eax)     # does not check yet for rollover
        jne     2f
        movl    %ebx,0(%eax)            # restore memory
@@ -188,27 +180,36 @@ start:                            # This is assumed to be location zero!
 2:     shrl    $12,%eax
        movl    %eax,_Maxmem-SYSTEM
 
 2:     shrl    $12,%eax
        movl    %eax,_Maxmem-SYSTEM
 
-/* clear memory. */
-       movl    $_edata-SYSTEM,%edi
+/* find end of kernel image */
        movl    $_end-SYSTEM,%ecx
        addl    $ NBPG-1,%ecx
        andl    $~(NBPG-1),%ecx
        movl    %ecx,%esi
        movl    $_end-SYSTEM,%ecx
        addl    $ NBPG-1,%ecx
        andl    $~(NBPG-1),%ecx
        movl    %ecx,%esi
+
+/* clear bss and memory for bootstrap pagetables. */
+       movl    $_edata-SYSTEM,%edi
        subl    %edi,%ecx
        subl    %edi,%ecx
-       addl    $(UPAGES*NBPG)+NBPG+NBPG+NBPG,%ecx
-       #       txt+data+proc zero pt+u.
+       addl    $(UPAGES+5)*NBPG,%ecx
+/*
+ * Virtual address space of kernel:
+ *
+ *     text | data | bss | page dir | proc0 kernel stack | usr stk map | Sysmap
+ *                          0               1       2       3             4
+ */
        xorl    %eax,%eax       # pattern
        cld
        rep
        stosb
 
        xorl    %eax,%eax       # pattern
        cld
        rep
        stosb
 
-/* should do all of memory, but some systems don't probe correctly (yet)*/
-       movl    $0x100000,%edi
-       movl    $0x200000,%ecx
-       xorl    %eax,%eax       # pattern
-       cld
-       rep
-       stosb
+       movl    %esi,_IdlePTD-SYSTEM /*physical address of Idle Address space */
+       movl    $ tmpstk-SYSTEM,%esp    # bootstrap stack end location
+
+#define        fillkpt         \
+1:     movl    %eax,0(%ebx)    ; \
+       addl    $ NBPG,%eax     ; /* increment physical address */ \
+       addl    $4,%ebx         ; /* next pte */ \
+       loop    1b              ;
+
 /*
  * Map Kernel
  * N.B. don't bother with making kernel text RO, as 386
 /*
  * Map Kernel
  * N.B. don't bother with making kernel text RO, as 386
@@ -218,87 +219,56 @@ start:                            # This is assumed to be location zero!
  */
        movl    %esi,%ecx               # this much memory,
        shrl    $ PGSHIFT,%ecx          # for this many pte s
  */
        movl    %esi,%ecx               # this much memory,
        shrl    $ PGSHIFT,%ecx          # for this many pte s
+       addl    $ UPAGES+4,%ecx         # including our early context
        movl    $ PG_V,%eax             #  having these bits set,
        movl    $ PG_V,%eax             #  having these bits set,
-       movl    $_Sysmap-SYSTEM,%ebx    #   in the kernel page table,
-                                       #    fill in kernel page table.
-1:     movl    %eax,0(%ebx)
-       addl    $ NBPG,%eax                     # increment physical address
-       addl    $4,%ebx                         # next pte
-       loop    1b
-
-/* temporary double map  virt == real */
-
-       movl    $1024,%ecx              # for this many pte s,
-       movl    $ PG_V,%eax             #  having these bits set,
-       movl    $_Sysmap+4096-SYSTEM,%ebx       #   in the temporary page table,
-                                       #    fill in kernel page table.
-1:     movl    %eax,0(%ebx)
-       addl    $ NBPG,%eax                     # increment physical address
-       addl    $4,%ebx                         # next pte
-       loop    1b
+       lea     (4*NBPG)(%esi),%ebx     #   physical address of KPT in proc 0,
+       movl    %ebx,_KPTphys-SYSTEM    #    in the kernel page table,
+       fillkpt
 
 /* map I/O memory map */
 
 
 /* map I/O memory map */
 
-       movl    $atpgs,%ecx             # for this many pte s,
-       movl    $(IOPHYSmem|PG_V),%eax  #  having these bits set, (perhaps URW?)
-       movl    $_ATDevmem-SYSTEM,%ebx  #   in the temporary page table,
-                                       #    fill in kernel page table.
-1:     movl    %eax,0(%ebx)
-       addl    $ NBPG,%eax                     # increment physical address
-       addl    $4,%ebx                         # next pte
-       loop    1b
+       movl    $0x100-0xa0,%ecx        # for this many pte s,
+       movl    $(0xa0000|PG_V),%eax    #  having these bits set, (perhaps URW?)
+       movl    %ebx,_atdevphys-SYSTEM  #   remember phys addr of ptes
+       fillkpt
 
 
-/* map proc 0's page table (P1 region) */
-
-       movl    $_Usrptmap-SYSTEM,%ebx  # get pt map address
-       lea     (0*NBPG)(%esi),%eax     # physical address of pt in proc 0
-       orl     $ PG_V,%eax             #  having these bits set,
-       movl    %eax,0(%ebx)
-
- /* map proc 0's _u */
+ /* map proc 0's kernel stack into user page table page */
 
        movl    $ UPAGES,%ecx           # for this many pte s,
 
        movl    $ UPAGES,%ecx           # for this many pte s,
-       lea     (2*NBPG)(%esi),%eax     # physical address of _u in proc 0
+       lea     (1*NBPG)(%esi),%eax     # physical address in proc 0
+       lea     (SYSTEM)(%eax),%edx
+       movl    %edx,_proc0paddr-SYSTEM  # remember VA for 0th process init
        orl     $ PG_V|PG_URKW,%eax     #  having these bits set,
        orl     $ PG_V|PG_URKW,%eax     #  having these bits set,
-       lea     (0*NBPG)(%esi),%ebx     # physical address of stack pt in proc 0
-       addl    $(UPTEOFF*4),%ebx
-                                       #    fill in proc 0 stack page table.
-1:     movl    %eax,0(%ebx)
-       addl    $ NBPG,%eax                     # increment physical address
-       addl    $4,%ebx                         # next pte
-       loop    1b
-
- /* locate proc 0's page directory*/
-       lea     (1*NBPG)(%esi),%eax     # physical address of ptd in proc 0
-       movl    %eax,%edi               # remember ptd physical address
+       lea     (3*NBPG)(%esi),%ebx     # physical address of stack pt in proc 0
+       addl    $(PPTEOFF*4),%ebx
+       fillkpt
 
 /*
  * Construct a page table directory
  * (of page directory elements - pde's)
  */
 
 /*
  * Construct a page table directory
  * (of page directory elements - pde's)
  */
-                                       /* kernel pde's */
-       movl    $_Sysmap-SYSTEM,%eax    # physical address of kernel page table
+       /* install a pde for temporary double map of bottom of VA */
+       lea     (4*NBPG)(%esi),%eax     # physical address of kernel page table
        orl     $ PG_V,%eax             # pde entry is valid
        orl     $ PG_V,%eax             # pde entry is valid
-       movl    $ Npdes,%ecx            # for this many pde s,
-       movl    %edi,%ebx               # phys address of ptd in proc 0
-       addl    $(SYSPDROFF*4), %ebx    # offset of pde for kernel
-1:     movl    %eax,0(%ebx)
-       addl    $ NBPG,%eax                     # increment physical address
-       addl    $4,%ebx                         # next pde
-       loop    1b
-                                       # install a pde for temporary double map
-       movl    $_Sysmap+4096-SYSTEM,%eax       # physical address of temp page table
+       movl    %eax,(%esi)             # which is where temp maps!
+
+       /* kernel pde's */
+       movl    $ 3,%ecx                # for this many pde s,
+       lea     (SYSPDROFF*4)(%esi), %ebx       # offset of pde for kernel
+       fillkpt
+
+       /* install a pde recursively mapping page directory as a page table! */
+       movl    %esi,%eax               # phys address of ptd in proc 0
        orl     $ PG_V,%eax             # pde entry is valid
        orl     $ PG_V,%eax             # pde entry is valid
-       movl    %edi,%ebx               # phys address of ptd in proc 0
-       movl    %eax,0(%ebx)                    # which is where temp maps!
-                                       # install a pde to map _u for proc 0
-       lea     (0*NBPG)(%esi),%eax     # physical address of pt in proc 0
+       movl    %eax, PDRPDROFF*4(%esi) # which is where PTmap maps!
+
+       /* install a pde to map kernel stack for proc 0 */
+       lea     (3*NBPG)(%esi),%eax     # physical address of pt in proc 0
        orl     $ PG_V,%eax             # pde entry is valid
        orl     $ PG_V,%eax             # pde entry is valid
-       movl    %edi,%ebx               # phys address of ptd in proc 0
-       addl    $(UPDROFF*4), %ebx      # offset of pde for kernel
-       movl    %eax,0(%ebx)            # which is where _u maps!
+       movl    %eax,PPDROFF*4(%esi)    # which is where kernel stack maps!
 
 
-       movl    %edi,%eax               # phys address of ptd in proc 0
+       /* load base of page directory, and enable mapping */
+       movl    %esi,%eax               # phys address of ptd in proc 0
        orl     $ I386_CR3PAT,%eax
        movl    %eax,%cr3               # load ptd addr into mmu
        movl    %cr0,%eax               # get control word
        orl     $ I386_CR3PAT,%eax
        movl    %eax,%cr3               # load ptd addr into mmu
        movl    %cr0,%eax               # get control word
@@ -306,72 +276,66 @@ start:                            # This is assumed to be location zero!
        movl    %eax,%cr0               # NOW!
 
        pushl   $begin                          # jump to high mem!
        movl    %eax,%cr0               # NOW!
 
        pushl   $begin                          # jump to high mem!
-       ret             # jmp $begin does not work
-begin:
-       movl    $_Sysbase,%eax          # kernel stack just below system
-       movl    %eax,%esp
+       ret
+
+begin: /* now running relocated at SYSTEM where the system is linked to run */
+
+       .globl _Crtat
+       movl    _Crtat,%eax
+       subl    $0xfe0a0000,%eax
+       movl    _atdevphys,%edx # get pte PA
+       subl    _KPTphys,%edx   # remove base of ptes, now have phys offset
+       shll    $ PGSHIFT-2,%edx  # corresponding to virt offset
+       addl    $ SYSTEM,%edx   # add virtual base
+       movl    %edx, _atdevbase
+       addl    %eax,%edx
+       movl    %edx,_Crtat
+
+       /* set up bootstrap stack */
+       movl    $ _kstack+UPAGES*NBPG-4*12,%esp # bootstrap stack end location
        xorl    %eax,%eax               # mark end of frames
        movl    %eax,%ebp
        xorl    %eax,%eax               # mark end of frames
        movl    %eax,%ebp
-       
-       movl    _Crtat,%eax             # initialize Crt video ram address
-       subl    $ IOPHYSmem,%eax
-       addl    $_atdevbase,%eax
-       movl    %eax,_Crtat
+       movl    _proc0paddr, %eax
+       movl    %esi, PCB_CR3(%eax)
 
 
+       lea     7*NBPG(%esi),%esi       # skip past stack.
+       pushl   %esi
+       
        call    _init386                # wire 386 chip for unix operation
        call    _init386                # wire 386 chip for unix operation
-
-/* initialize (slightly) the pcb */
-       movl    $_u,%eax                # proc0 u-area
-       movl    $_usrpt,%ecx
-       movl    %ecx,PCB_P0BR(%eax)     # p0br: SVA of text/data user PT
-       xorl    %ecx,%ecx
-       movl    %ecx,PCB_P0LR(%eax)     # p0lr: 0 (doesn t really exist)
-       movl    %ecx,PCB_FLAGS(%eax)    # no fp yet.
-       movl    $_usrpt+NBPG,%ecx       # addr of end of PT
-       subl    $ P1PAGES*4,%ecx                # backwards size of P1 region
-       movl    %ecx,PCB_P1BR(%eax)     # p1br: P1PAGES from end of PT
-       movl    $ P1PAGES-UPAGES,PCB_P1LR(%eax) # p1lr: vax style
-       movl    $ CLSIZE,PCB_SZPT(%eax) # page table size
-       movl    %edi,PCB_CR3(%eax)
-       pushl   %edi    # cr3
-       movl    %esi,%eax
-       addl    $(UPAGES*NBPG)+NBPG+NBPG+NBPG,%eax
-       shrl    $ PGSHIFT,%eax
-       pushl   %eax    # firstaddr
-
-       pushl   $20             # install signal trampoline code
-       pushl   $_u+PCB_SIGC
-       pushl   $sigcode
-       call    _bcopy
-       addl    $12,%esp
-
+       
+       movl    $0,_PTD
        call    _main
        call    _main
+       popl    %esi
 
        .globl  __ucodesel,__udatasel
        movzwl  __ucodesel,%eax
        movzwl  __udatasel,%ecx
        # build outer stack frame
        pushl   %ecx            # user ss
 
        .globl  __ucodesel,__udatasel
        movzwl  __ucodesel,%eax
        movzwl  __udatasel,%ecx
        # build outer stack frame
        pushl   %ecx            # user ss
-       pushl   $_u     # user esp
-       pushl   %eax    # user cs
-       pushl   $0      # user ip
+       pushl   $ USRSTACK      # user esp
+       pushl   %eax            # user cs
+       pushl   $0              # user ip
        movw    %cx,%ds
        movw    %cx,%es
        movw    %cx,%ds
        movw    %cx,%es
-       movw    %ax,%fs         # double map cs to fs
-       movw    %cx,%gs         # and ds to gs
+       # movw  %ax,%fs         # double map cs to fs
+       # movw  %cx,%gs         # and ds to gs
        lret    # goto user!
 
        lret    # goto user!
 
+       pushl   $lretmsg1       /* "should never get here!" */
+       call    _panic
+lretmsg1:
+       .asciz  "lret: toinit\n"
+
        .globl  __exit
 __exit:
        call _reset_cpu
        /* NOTREACHED */
 
        .globl  __exit
 __exit:
        call _reset_cpu
        /* NOTREACHED */
 
-       .set    exec,11
+       .set    exec,59
        .set    exit,1
        .globl  _icode
        .set    exit,1
        .globl  _icode
-       .globl  _initflags
        .globl  _szicode
        .globl  _szicode
-/* gas fucks up offset -- */
+
 #define        LCALL(x,y)      .byte 0x9a ; .long y; .word x
 /*
  * Icode is copied out to process 1 to exec /etc/init.
 #define        LCALL(x,y)      .byte 0x9a ; .long y; .word x
 /*
  * Icode is copied out to process 1 to exec /etc/init.
@@ -397,16 +361,20 @@ _icode:
        pushl   %eax    # dummy out rta
        LCALL(0x7,0x0)
 
        pushl   %eax    # dummy out rta
        LCALL(0x7,0x0)
 
-init:  .asciz  "/sbin/init"
+init:
+       .asciz  "/sbin/init"
        .align  2
        .align  2
-_initflags:
-       .long   0
-argv:  .long   init-_icode
-       .long   _initflags-_icode
+argv:
+       .long   init+6-_icode           # argv[0] = "init" ("/sbin/init" + 6)
+       .long   eicode-_icode           # argv[1] follows icode after copyout
        .long   0
        .long   0
+eicode:
+
 _szicode:
        .long   _szicode-_icode
 _szicode:
        .long   _szicode-_icode
-sigcode:
+
+       .globl  _sigcode,_szsigcode
+_sigcode:
        movl    12(%esp),%eax   # unsure if call will dec stack 1st
        call    %eax
        xorl    %eax,%eax       # smaller movl $103,%eax
        movl    12(%esp),%eax   # unsure if call will dec stack 1st
        call    %eax
        xorl    %eax,%eax       # smaller movl $103,%eax
@@ -414,6 +382,8 @@ sigcode:
        LCALL(0x7,0)            # enter kernel with args on stack
        hlt                     # never gets here
 
        LCALL(0x7,0)            # enter kernel with args on stack
        hlt                     # never gets here
 
+_szsigcode:
+       .long   _szsigcode-_sigcode
 
        .globl ___udivsi3
 ___udivsi3:
 
        .globl ___udivsi3
 ___udivsi3:
@@ -432,19 +402,27 @@ ___divsi3:
 
        .globl  _inb
 _inb:  movl    4(%esp),%edx
 
        .globl  _inb
 _inb:  movl    4(%esp),%edx
-       inb     $0x84,%al       # Compaq SystemPro 
+       # inb   $0x84,%al       # Compaq SystemPro 
        subl    %eax,%eax       # clr eax
        NOP
        inb     %dx,%al
        NOP
        ret
 
        subl    %eax,%eax       # clr eax
        NOP
        inb     %dx,%al
        NOP
        ret
 
+
+       .globl  _rtcin
+_rtcin:        movl    4(%esp),%eax
+       outb    %al,$0x70
+       subl    %eax,%eax       # clr eax
+       inb     $0x71,%al       # Compaq SystemPro 
+       ret
+
        .globl  _outb
 _outb: movl    4(%esp),%edx
        movl    8(%esp),%eax
        NOP
        outb    %al,%dx
        .globl  _outb
 _outb: movl    4(%esp),%edx
        movl    8(%esp),%eax
        NOP
        outb    %al,%dx
-       inb     $0x84,%al
+       # inb   $0x84,%al
        NOP
        ret
 
        NOP
        ret
 
@@ -481,7 +459,6 @@ _fillw:
        movl    8(%esp),%eax
        movl    12(%esp),%edi
        movl    16(%esp),%ecx
        movl    8(%esp),%eax
        movl    12(%esp),%edi
        movl    16(%esp),%ecx
-       # xorl  %eax,%eax
        cld
        rep
        stosw
        cld
        rep
        stosw
@@ -513,9 +490,33 @@ _bcopy:
        xorl    %eax,%eax
        ret
 
        xorl    %eax,%eax
        ret
 
+       #
+       # ovbcopy (src,dst,cnt)
+       # NOTE: does not (yet) work doing words at a time
+       #
+
+       .globl  _ovbcopy
+_ovbcopy:
+       pushl   %esi
+       pushl   %edi
+       movl    12(%esp),%esi
+       movl    16(%esp),%edi
+       movl    20(%esp),%ecx
+       addl    %ecx,%esi       /* copy from end to beginning */
+       addl    %ecx,%edi
+       decl    %esi
+       decl    %edi
+       std                     /* decrementing as we go */
+       rep
+       movsb
+       xorl    %eax,%eax
+       cld
+       ret
+
        .globl  _copyout
 _copyout:
        .globl  _copyout
 _copyout:
-       movl    $cpyflt,_nofault        # in case we page/protection violate
+       movl    _curpcb,%eax
+       movl    $cpyflt,PCB_ONFAULT(%eax) # in case we page/protection violate
        pushl   %esi
        pushl   %edi
        movl    12(%esp),%esi
        pushl   %esi
        pushl   %edi
        movl    12(%esp),%esi
@@ -532,12 +533,14 @@ _copyout:
        popl    %edi
        popl    %esi
        xorl    %eax,%eax
        popl    %edi
        popl    %esi
        xorl    %eax,%eax
-       movl    %eax,_nofault
+       movl    _curpcb,%edx
+       movl    %eax,PCB_ONFAULT(%edx)
        ret
 
        .globl  _copyin
 _copyin:
        ret
 
        .globl  _copyin
 _copyin:
-       movl    $cpyflt,_nofault        # in case we page/protection violate
+       movl    _curpcb,%eax
+       movl    $cpyflt,PCB_ONFAULT(%eax) # in case we page/protection violate
        pushl   %esi
        pushl   %edi
        movl    12(%esp),%esi
        pushl   %esi
        pushl   %edi
        movl    12(%esp),%esi
@@ -554,13 +557,14 @@ _copyin:
        popl    %edi
        popl    %esi
        xorl    %eax,%eax
        popl    %edi
        popl    %esi
        xorl    %eax,%eax
-       movl    %eax,_nofault
+       movl    _curpcb,%edx
+       movl    %eax,PCB_ONFAULT(%edx)
        ret
 
 cpyflt: popl   %edi
        popl    %esi
        ret
 
 cpyflt: popl   %edi
        popl    %esi
-       xorl    %eax,%eax
-       movl    %eax,_nofault
+       movl    _curpcb,%edx
+       movl    $0,PCB_ONFAULT(%edx)
        movl    $ EFAULT,%eax
        ret
 
        movl    $ EFAULT,%eax
        ret
 
@@ -663,10 +667,21 @@ _ltr:
        .globl  _load_cr3
 _load_cr3:
 _lcr3:
        .globl  _load_cr3
 _load_cr3:
 _lcr3:
+       inb     $0x84,%al       # check wristwatch
        movl    4(%esp),%eax
        orl     $ I386_CR3PAT,%eax
        movl    %eax,%cr3
        movl    4(%esp),%eax
        orl     $ I386_CR3PAT,%eax
        movl    %eax,%cr3
+       inb     $0x84,%al       # check wristwatch
+       ret
+
+       # tlbflush()
+       .globl  _tlbflush
+_tlbflush:
+       inb     $0x84,%al       # check wristwatch
        movl    %cr3,%eax
        movl    %cr3,%eax
+       orl     $ I386_CR3PAT,%eax
+       movl    %eax,%cr3
+       inb     $0x84,%al       # check wristwatch
        ret
 
        # lcr0(cr0)
        ret
 
        # lcr0(cr0)
@@ -724,72 +739,75 @@ _ssdtosd:
  */
 ALTENTRY(fuiword)
 ENTRY(fuword)
  */
 ALTENTRY(fuiword)
 ENTRY(fuword)
-       movl    $fusufault,_nofault     # in case we page/protection violate
+       movl    _curpcb,%ecx
+       movl    $fusufault,PCB_ONFAULT(%ecx)
        movl    4(%esp),%edx
        movl    4(%esp),%edx
-       .byte   0x65            # use gs
+       # .byte 0x65            # use gs
        movl    0(%edx),%eax
        movl    0(%edx),%eax
-       xorl    %edx,%edx
-       movl    %edx,_nofault
+       movl    $0,PCB_ONFAULT(%ecx)
        ret
        
 ENTRY(fusword)
        ret
        
 ENTRY(fusword)
-       movl    $fusufault,_nofault     # in case we page/protection violate
+       movl    _curpcb,%ecx
+       movl    $fusufault,PCB_ONFAULT(%ecx) #in case we page/protection violate
        movl    4(%esp),%edx
        movl    4(%esp),%edx
-       .byte   0x65            # use gs
+       # .byte 0x65            # use gs
        movzwl  0(%edx),%eax
        movzwl  0(%edx),%eax
-       xorl    %edx,%edx
-       movl    %edx,_nofault
+       movl    $0,PCB_ONFAULT(%ecx)
        ret
        
 ALTENTRY(fuibyte)
 ENTRY(fubyte)
        ret
        
 ALTENTRY(fuibyte)
 ENTRY(fubyte)
-       movl    $fusufault,_nofault     # in case we page/protection violate
+       movl    _curpcb,%ecx
+       movl    $fusufault,PCB_ONFAULT(%ecx) #in case we page/protection violate
        movl    4(%esp),%edx
        movl    4(%esp),%edx
-       .byte   0x65            # use gs
+       # .byte 0x65            # use gs
        movzbl  0(%edx),%eax
        movzbl  0(%edx),%eax
-       xorl    %edx,%edx
-       movl    %edx,_nofault
+       movl    $0,PCB_ONFAULT(%ecx)
        ret
        
 fusufault:
        ret
        
 fusufault:
+       movl    _curpcb,%ecx
        xorl    %eax,%eax
        xorl    %eax,%eax
-       movl    %eax,_nofault
+       movl    %eax,PCB_ONFAULT(%ecx) #in case we page/protection violate
        decl    %eax
        ret
 
 ALTENTRY(suiword)
 ENTRY(suword)
        decl    %eax
        ret
 
 ALTENTRY(suiword)
 ENTRY(suword)
-       movl    $fusufault,_nofault     # in case we page/protection violate
+       movl    _curpcb,%ecx
+       movl    $fusufault,PCB_ONFAULT(%ecx) #in case we page/protection violate
        movl    4(%esp),%edx
        movl    8(%esp),%eax
        movl    4(%esp),%edx
        movl    8(%esp),%eax
-       .byte   0x65            # use gs
+       # .byte 0x65            # use gs
        movl    %eax,0(%edx)
        xorl    %eax,%eax
        movl    %eax,0(%edx)
        xorl    %eax,%eax
-       movl    %eax,_nofault
+       movl    %eax,PCB_ONFAULT(%ecx) #in case we page/protection violate
        ret
        
 ENTRY(susword)
        ret
        
 ENTRY(susword)
-       movl    $fusufault,_nofault     # in case we page/protection violate
+       movl    _curpcb,%ecx
+       movl    $fusufault,PCB_ONFAULT(%ecx) #in case we page/protection violate
        movl    4(%esp),%edx
        movl    8(%esp),%eax
        movl    4(%esp),%edx
        movl    8(%esp),%eax
-       .byte   0x65            # use gs
+       # .byte 0x65            # use gs
        movw    %ax,0(%edx)
        xorl    %eax,%eax
        movw    %ax,0(%edx)
        xorl    %eax,%eax
-       movl    %eax,_nofault
+       movl    %eax,PCB_ONFAULT(%ecx) #in case we page/protection violate
        ret
 
 ALTENTRY(suibyte)
 ENTRY(subyte)
        ret
 
 ALTENTRY(suibyte)
 ENTRY(subyte)
-       movl    $fusufault,_nofault     # in case we page/protection violate
+       movl    _curpcb,%ecx
+       movl    $fusufault,PCB_ONFAULT(%ecx) #in case we page/protection violate
        movl    4(%esp),%edx
        movl    8(%esp),%eax
        movl    4(%esp),%edx
        movl    8(%esp),%eax
-       .byte   0x65            # use gs
+       # .byte 0x65            # use gs
        movb    %eax,0(%edx)
        xorl    %eax,%eax
        movb    %eax,0(%edx)
        xorl    %eax,%eax
-       movl    %eax,_nofault
+       movl    %eax,PCB_ONFAULT(%ecx) #in case we page/protection violate
        ret
 
        ret
 
-       ALTENTRY(savectx)
        ENTRY(setjmp)
        movl    4(%esp),%eax
        movl    %ebx, 0(%eax)           # save ebx
        ENTRY(setjmp)
        movl    4(%esp),%eax
        movl    %ebx, 0(%eax)           # save ebx
@@ -802,6 +820,7 @@ ENTRY(subyte)
        xorl    %eax,%eax               # return (0);
        ret
 
        xorl    %eax,%eax               # return (0);
        ret
 
+#ifdef notdef
        ENTRY(longjmp)
        movl    4(%esp),%eax
        movl     0(%eax),%ebx           # restore ebx
        ENTRY(longjmp)
        movl    4(%esp),%eax
        movl     0(%eax),%ebx           # restore ebx
@@ -814,6 +833,7 @@ ENTRY(subyte)
        xorl    %eax,%eax               # return (1);
        incl    %eax
        ret
        xorl    %eax,%eax               # return (1);
        incl    %eax
        ret
+#endif
 /*
  * The following primitives manipulate the run queues.
  * _whichqs tells which of the 32 queues _qs
 /*
  * The following primitives manipulate the run queues.
  * _whichqs tells which of the 32 queues _qs
@@ -912,54 +932,14 @@ badsw:
  * Swtch()
  */
 ENTRY(swtch)
  * Swtch()
  */
 ENTRY(swtch)
-       movw    _cpl, %ax
-       movw    %ax, _u+PCB_IML
-       movl    $1,%eax
-       movl    %eax,_noproc
-       incl    _cnt+V_SWTCH
-sw1:
-       cli
-       bsfl    _whichqs,%eax   # find a full q
-       jz      idle            # if none, idle
-swfnd:
-       btrl    %eax,_whichqs   # clear q full status
-       jnb     sw1             # if it was clear, look for another
-       pushl   %eax            # save which one we are using
-       shll    $3,%eax
-       addl    $_qs,%eax       # select q
-       pushl   %eax
-
-       cmpl    P_LINK(%eax),%eax       # linked to self? (e.g. not on list)
-       je      badsw           # not possible
-       movl    P_LINK(%eax),%ecx       # unlink from front of process q
-       movl    P_LINK(%ecx),%edx
-       movl    %edx,P_LINK(%eax)
-       movl    P_RLINK(%ecx),%eax
-       movl    %eax,P_RLINK(%edx)
 
 
-       popl    %eax
-       popl    %edx
-       cmpl    P_LINK(%ecx),%eax       # q empty
-       je      sw2
-       btsl    %edx,_whichqs           # nope, indicate full
-sw2:
-       movl    $0,%eax
-       movl    %eax,_noproc
-       movl    %eax,_runrun
-       cmpl    $0,P_WCHAN(%ecx)
-       jne     badsw
-       cmpb    $ SRUN,P_STAT(%ecx)
-       jne     badsw
-       movl    %eax,P_RLINK(%ecx)
+       incl    _cnt+V_SWTCH
 
 
-       movl    P_ADDR(%ecx),%edx
-       movl    (%edx),%eax
-       movl    %eax,_Swtchmap
-       movl    _Swtchbase+PCB_CR3,%edx
+       /* switch to new process. first, save context as needed */
 
 
-/* switch to new process. first, save context as needed */
+       movl    _curproc,%ecx
+       movl    P_ADDR(%ecx),%ecx
 
 
-       movl    $_u,%ecx
 
        movl    (%esp),%eax             # Hardware registers
        movl    %eax, PCB_EIP(%ecx)
 
        movl    (%esp),%eax             # Hardware registers
        movl    %eax, PCB_EIP(%ecx)
@@ -990,69 +970,125 @@ sw2:
        movl    _CMAP2,%eax             # save temporary map PTE
        movl    %eax,PCB_CMAP2(%ecx)    # in our context
 
        movl    _CMAP2,%eax             # save temporary map PTE
        movl    %eax,PCB_CMAP2(%ecx)    # in our context
 
-       orl     $ I386_CR3PAT,%edx
-       movl    %edx,%cr3       # context switch address space
+       movw    _cpl, %ax
+       movw    %ax, PCB_IML(%ecx)      # save ipl
 
 
-       movl    $_u,%ecx
+       /* save is done, now choose a new process or idle */
+sw1:
+       cli                             # XXX?
+       movl    _whichqs,%edi
+2:
+       bsfl    %edi,%eax               # find a full q
+       jz      idle                    # if none, idle
+       # XX update whichqs?
+swfnd:
+       btrl    %eax,%edi               # clear q full status
+       jnb     2b              # if it was clear, look for another
+       movl    %eax,%ebx               # save which one we are using
 
 
-/* restore context */
-       movl    PCB_EBX(%ecx), %ebx
-       movl    PCB_ESP(%ecx), %esp
-       movl    PCB_EBP(%ecx), %ebp
-       movl    PCB_ESI(%ecx), %esi
-       movl    PCB_EDI(%ecx), %edi
-       movl    PCB_EIP(%ecx), %eax
+       shll    $3,%eax
+       addl    $_qs,%eax               # select q
+       movl    %eax,%esi
+
+#ifdef DIAGNOSTIC
+       cmpl    P_LINK(%eax),%eax # linked to self? (e.g. not on list)
+       je      badsw                   # not possible
+#endif
+
+       movl    P_LINK(%eax),%ecx       # unlink from front of process q
+       movl    P_LINK(%ecx),%edx
+       movl    %edx,P_LINK(%eax)
+       movl    P_RLINK(%ecx),%eax
+       movl    %eax,P_RLINK(%edx)
+
+       cmpl    P_LINK(%ecx),%esi       # q empty
+       je      3f
+       btsl    %ebx,%edi               # nope, set to indicate full
+3:
+       movl    %edi,_whichqs           # update q status
+
+       movl    $0,%eax
+       movl    %ecx,_curproc
+       movl    %eax,_want_resched
+
+#ifdef DIAGNOSTIC
+       cmpl    %eax,P_WCHAN(%ecx)
+       jne     badsw
+       cmpb    $ SRUN,P_STAT(%ecx)
+       jne     badsw
+#endif
+
+       movl    %eax,P_RLINK(%ecx) /* isolate process to run */
+       movl    P_ADDR(%ecx),%edx
+       movl    %edx,_curpcb
+       movl    PCB_CR3(%edx),%ebx
+
+       /* switch address space */
+       movl    %esp,%ecx
+       movl    $tmpstk,%esp
+       orl     $ I386_CR3PAT,%ebx
+       inb     $0x84,%al       # flush write buffers
+       movl    %ebx,%cr3       # context switch address space
+       movl    (%ecx),%eax     # touch stack, fault if not there
+       movl    %eax,(%ecx)
+       movl    %ecx,%esp
+
+       /* restore context */
+       movl    PCB_EBX(%edx), %ebx
+       movl    PCB_ESP(%edx), %esp
+       movl    PCB_EBP(%edx), %ebp
+       movl    PCB_ESI(%edx), %esi
+       movl    PCB_EDI(%edx), %edi
+       movl    PCB_EIP(%edx), %eax
        movl    %eax, (%esp)
 
 #ifdef NPX
        movl    %eax, (%esp)
 
 #ifdef NPX
-       movb    PCB_FLAGS(%ecx),%al
+       movb    PCB_FLAGS(%edx),%al
        /* if fp could be used, a dna trap will do a restore */
        testb   $ FP_WASUSED,%al
        je      1f
        /* if fp could be used, a dna trap will do a restore */
        testb   $ FP_WASUSED,%al
        je      1f
-       orb     $ FP_NEEDSRESTORE,%al
-       movb    %al, PCB_FLAGS(%ecx)
+       orb     $ FP_NEEDSRESTORE,PCB_FLAGS(%ecx)
 1:
 #endif
 
 1:
 #endif
 
-       movl    PCB_CMAP2(%ecx),%eax    # get temporary map
+       movl    PCB_CMAP2(%edx),%eax    # get temporary map
        movl    %eax,_CMAP2             # reload temporary map PTE
        movl    %eax,_CMAP2             # reload temporary map PTE
-       cmpl    $0,PCB_SSWAP(%ecx)      # do an alternate return?
-       jne     res3                    # yes, go reload regs
-
-       call _spl0
-       movl    $0,%eax
-       ret
 
 
-res3:
-       xorl    %eax,%eax               # inline restore context
-       xchgl   PCB_SSWAP(%ecx),%eax    # addr of saved context, clear it
-
-       movl     0(%eax),%ebx           # restore ebx
-       movl     4(%eax),%esp           # restore esp
-       movl     8(%eax),%ebp           # restore ebp
-       movl    12(%eax),%esi           # restore esi
-       movl    16(%eax),%edi           # restore edi
-       movl    20(%eax),%edx           # get rta
-       movl    %edx,(%esp)             # put in return frame
-
-       pushl   _u+PCB_IML
+       pushl   PCB_IML(%edx)
        call    _splx
        popl    %eax
 
        call    _splx
        popl    %eax
 
-       xorl    %eax,%eax               # return (1);
-       incl    %eax
+       movl    %edx,%eax               # return (1);
        ret
 
 /*
        ret
 
 /*
- * Resume(p_addr)
- * current just used to fillout u. tss so fork can fake a return to swtch
+ * struct proc *swtch_to_inactive(p) ; struct proc *p;
+ *
+ * At exit of a process, move off the address space of the
+ * process and onto a "safe" one. Then, on a temporary stack
+ * return and run code that disposes of the old state.
+ * Since this code requires a parameter from the "old" stack,
+ * pass it back as a return value.
+ */
+ENTRY(swtch_to_inactive)
+       popl    %edx                    # old pc
+       popl    %eax                    # arg, our return value
+       movl    _IdlePTD,%ecx
+       movl    %ecx,%cr3               # good bye address space
+ #write buffer?
+       movl    $tmpstk-4,%esp          # temporary stack, compensated for call
+       jmp     %edx                    # return, execute remainder of cleanup
+
+/*
+ * savectx(pcb, altreturn)
+ * Update pcb, saving current processor state and arranging
+ * for alternate return ala longjmp in swtch if altreturn is true.
  */
  */
-ENTRY(resume)
-       # movl  4(%esp),%ecx
-       movl    $_u,%ecx
+ENTRY(savectx)
+       movl    4(%esp), %ecx
        movw    _cpl, %ax
        movw    %ax,  PCB_IML(%ecx)
        movw    _cpl, %ax
        movw    %ax,  PCB_IML(%ecx)
-       movl    (%esp),%eax     
+       movl    (%esp), %eax    
        movl    %eax, PCB_EIP(%ecx)
        movl    %ebx, PCB_EBX(%ecx)
        movl    %esp, PCB_ESP(%ecx)
        movl    %eax, PCB_EIP(%ecx)
        movl    %ebx, PCB_EBX(%ecx)
        movl    %esp, PCB_ESP(%ecx)
@@ -1061,40 +1097,97 @@ ENTRY(resume)
        movl    %edi, PCB_EDI(%ecx)
 #ifdef NPX
        /* have we ever used fp, and need to save? */
        movl    %edi, PCB_EDI(%ecx)
 #ifdef NPX
        /* have we ever used fp, and need to save? */
-       testb   $ FP_WASUSED,PCB_FLAGS(%ecx)
+       testb   $ FP_WASUSED, PCB_FLAGS(%ecx)
        je      1f
        je      1f
-       movl    %cr0,%eax
-       andb    $0xfb,%al
-       movl    %eax,%cr0
+       movl    %cr0, %edx
+       andb    $0xfb, %dl
+       movl    %edx, %cr0
        fnsave  PCB_SAVEFPU(%ecx)
        fnsave  PCB_SAVEFPU(%ecx)
-       orb     $4,%eax
-       movl    %eax,%cr0
+       orb     $4, %edx
+       movl    %edx, %cr0
 1:
 #endif
 1:
 #endif
-       movl    $0,%eax
+       movl    _CMAP2, %edx            # save temporary map PTE
+       movl    %edx, PCB_CMAP2(%ecx)   # in our context
+
+       cmpl    $0, 8(%esp)
+       je      1f
+       movl    %esp, %edx              # relocate current sp relative to pcb
+       subl    $_kstack, %edx          #   (sp is relative to kstack):
+       addl    %edx, %ecx              #   pcb += sp - kstack;
+       movl    %eax, (%ecx)            # write return pc at (relocated) sp@
+       # this mess deals with replicating register state gcc hides
+       movl    12(%esp),%eax
+       movl    %eax,12(%ecx)
+       movl    16(%esp),%eax
+       movl    %eax,16(%ecx)
+       movl    20(%esp),%eax
+       movl    %eax,20(%ecx)
+       movl    24(%esp),%eax
+       movl    %eax,24(%ecx)
+1:
+       xorl    %eax, %eax              # return 0
+       ret
+
+/*
+ * update profiling information for the user
+ * addupc(pc, up, ticks) struct uprof *up;
+ */
+
+ENTRY(addupc)
+       movl    4(%esp),%eax            /* pc */
+       movl    8(%esp),%ecx            /* up */
+
+       /* does sampled pc fall within bottom of profiling window? */
+       subl    PR_OFF(%ecx),%eax       /* pc -= up->pr_off; */
+       jl      1f                      /* if (pc < 0) return; */
+
+       /* construct scaled index */
+       shrl    $1,%eax                 /* reduce pc to a short index */
+       mull    PR_SCALE(%ecx)          /* pc*up->pr_scale */
+       shrdl   $15,%edx,%eax           /* praddr >> 15 */
+       cmpl    $0,%edx                 /* if overflow, ignore */
+       jne     1f
+       andb    $0xfe,%al               /* praddr &= ~1 */
+
+       /* within profiling buffer? if so, compute address */
+       cmpl    %eax,PR_SIZE(%ecx)      /* if (praddr > up->pr_size) return; */
+       jg      1f
+       addl    PR_BASE(%ecx),%eax      /* praddr += up->pr_base; */
+
+       /* tally ticks to selected counter */
+       movl    _curpcb,%ecx
+       movl    $proffault,PCB_ONFAULT(%ecx) #in case we page/protection violate
+       movl    12(%esp),%edx           /* ticks */
+       addw    %dx,(%eax)
+       movl    $0,PCB_ONFAULT(%ecx)
+1:     ret
+
+proffault:
+       /* disable profiling if we get a fault */
+       movl    $0,PR_SCALE(%ecx) /*    up->pr_scale = 0; */
+       movl    _curpcb,%ecx
+       movl    $0,PCB_ONFAULT(%ecx)
        ret
 
 .data
        ret
 
 .data
-       .globl  _cyloffset
+       .globl  _cyloffset, _curpcb
 _cyloffset:    .long   0
 _cyloffset:    .long   0
-       .globl  _nofault
-_nofault:      .long   0
+       .globl  _proc0paddr
+_proc0paddr:   .long   0
+LF:    .asciz "swtch %x"
+
 .text
  # To be done:
 .text
  # To be done:
-       .globl _addupc
        .globl _astoff
        .globl _astoff
-       .globl _doadump
-_addupc:               # sorry, no profiling
-       .byte 0xcc
 _astoff:
        ret
 _astoff:
        ret
-_doadump:
-       call _reset_cpu
 
 #define        IDTVEC(name)    .align 4; .globl _X/**/name; _X/**/name:
 
 #define        IDTVEC(name)    .align 4; .globl _X/**/name; _X/**/name:
-/*#define      PANIC(msg)      xorl %eax,%eax; movl %eax,_waittime; pushl 1f; \
-                       call _panic; 1: .asciz msg*/
-#define        PRINTF(n,msg)   pushal ; pushl 1f; call _printf; MSG(msg) ; popl %eax ; popal
+#define        PANIC(msg)      xorl %eax,%eax; movl %eax,_waittime; pushl 1f; \
+                       call _panic; 1: .asciz msg
+#define        PRINTF(n,msg)   pushal ; pushl 1f; call _printf; MSG(msg) ; \
+                        popl %eax ; popal
 #define        MSG(msg)        .data; 1: .asciz msg; .text
 
        .text
 #define        MSG(msg)        .data; 1: .asciz msg; .text
 
        .text
@@ -1102,16 +1195,21 @@ _doadump:
 /*
  * Trap and fault vector routines
  */ 
 /*
  * Trap and fault vector routines
  */ 
-#define        TRAP(a) pushl $ a; jmp alltraps
+#define        TRAP(a)         pushl $a ; jmp alltraps
+#ifdef KGDB
+#define        BPTTRAP(a)      pushl $a ; jmp bpttraps
+#else
+#define        BPTTRAP(a)      TRAP(a)
+#endif
 
 IDTVEC(div)
        pushl $0; TRAP(T_DIVIDE)
 IDTVEC(dbg)
 
 IDTVEC(div)
        pushl $0; TRAP(T_DIVIDE)
 IDTVEC(dbg)
-       pushl $0; TRAP(T_TRCTRAP)
+       pushl $0; BPTTRAP(T_TRCTRAP)
 IDTVEC(nmi)
        pushl $0; TRAP(T_NMI)
 IDTVEC(bpt)
 IDTVEC(nmi)
        pushl $0; TRAP(T_NMI)
 IDTVEC(bpt)
-       pushl $0; TRAP(T_BPTFLT)
+       pushl $0; BPTTRAP(T_BPTFLT)
 IDTVEC(ofl)
        pushl $0; TRAP(T_OFLOW)
 IDTVEC(bnd)
 IDTVEC(ofl)
        pushl $0; TRAP(T_OFLOW)
 IDTVEC(bnd)
@@ -1179,6 +1277,7 @@ alltraps:
        movw    $0x10,%ax
        movw    %ax,%ds
        movw    %ax,%es
        movw    $0x10,%ax
        movw    %ax,%ds
        movw    %ax,%es
+calltrap:
        incl    _cnt+V_TRAP
        call    _trap
        pop %es
        incl    _cnt+V_TRAP
        call    _trap
        pop %es
@@ -1188,6 +1287,25 @@ alltraps:
        addl    $8,%esp                 # pop type, code
        iret
 
        addl    $8,%esp                 # pop type, code
        iret
 
+#ifdef KGDB
+/*
+ * This code checks for a kgdb trap, then falls through
+ * to the regular trap code.
+ */
+bpttraps:
+       pushal
+       push    %es
+       push    %ds
+       movw    $0x10,%ax
+       movw    %ax,%ds
+       movw    %ax,%es
+       movzwl  52(%esp),%eax
+       test    $3,%eax 
+       jne     calltrap
+       call    _kgdb_trap_glue         
+       jmp     calltrap
+#endif
+
 /*
  * Call gate entry for syscall
  */
 /*
  * Call gate entry for syscall
  */
@@ -1220,3 +1338,6 @@ ENTRY(ntohs)
        movzwl  4(%esp),%eax
        xchgb   %al,%ah
        ret
        movzwl  4(%esp),%eax
        xchgb   %al,%ah
        ret
+
+#include "vector.s"
+#include "i386/isa/icu.s"