BSD 4_3_Net_2 release
[unix-history] / usr / src / sys / i386 / i386 / pmap.c
index 117ff80..66ecd85 100644 (file)
@@ -1,16 +1,43 @@
 /* 
 /* 
- * Copyright (c) 1987 Carnegie-Mellon University
  * Copyright (c) 1991 Regents of the University of California.
  * All rights reserved.
  *
  * This code is derived from software contributed to Berkeley by
  * Copyright (c) 1991 Regents of the University of California.
  * All rights reserved.
  *
  * This code is derived from software contributed to Berkeley by
- * The Mach Operating System project at Carnegie-Mellon University.
+ * the Systems Programming Group of the University of Utah Computer
+ * Science Department and William Jolitz of UUNET Technologies Inc.
  *
  *
- * The CMU software License Agreement specifies the terms and conditions
- * for use and redistribution.
+ * 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.
  *
  *
- * This version by William Jolitz for UUNET Technologies, Inc.
+ * 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.
  *
  *
+ *     @(#)pmap.c      7.7 (Berkeley)  5/12/91
+ */
+
+/*
  * Derived from hp300 version by Mike Hibler, this version by William
  * Jolitz uses a recursive map [a pde points to the page directory] to
  * map the page tables using the pagetables themselves. This is done to
  * Derived from hp300 version by Mike Hibler, this version by William
  * Jolitz uses a recursive map [a pde points to the page directory] to
  * map the page tables using the pagetables themselves. This is done to
@@ -18,7 +45,6 @@
  * space, and to reduce the cost of memory to each process.
  *
  *     Derived from: hp300/@(#)pmap.c  7.1 (Berkeley) 12/5/90
  * space, and to reduce the cost of memory to each process.
  *
  *     Derived from: hp300/@(#)pmap.c  7.1 (Berkeley) 12/5/90
- *     @(#)pmap.c      7.3     %G%
  */
 
 /*
  */
 
 /*
  */
 
 #include "param.h"
  */
 
 #include "param.h"
-#include "../vm/vm_param.h"
-#include "user.h"
 #include "proc.h"
 #include "proc.h"
-#include "lock.h"
 #include "malloc.h"
 #include "malloc.h"
+#include "user.h"
 
 
-#include "../vm/pmap.h"
-#include "../vm/vm_map.h"
-#include "../vm/vm_kern.h"
-#include "../vm/vm_prot.h"
-#include "../vm/vm_page.h"
-#include "../vm/vm_pageout.h"
+#include "vm/vm.h"
+#include "vm/vm_kern.h"
+#include "vm/vm_page.h"
+/*#include "vm/vm_pageout.h"*/
 
 
-#include "machine/isa.h"
+/*#include "machine/isa.h"*/
 
 /*
  * Allocate various and sundry SYSMAPs used in the days of old VM
 
 /*
  * Allocate various and sundry SYSMAPs used in the days of old VM
@@ -188,7 +210,7 @@ struct msgbuf       *msgbufp;
 struct pte *pmap_pte();
 
 extern vm_offset_t     atdevbase;
 struct pte *pmap_pte();
 
 extern vm_offset_t     atdevbase;
-int
+void
 pmap_bootstrap(firstaddr, loadaddr)
        vm_offset_t firstaddr;
        vm_offset_t loadaddr;
 pmap_bootstrap(firstaddr, loadaddr)
        vm_offset_t firstaddr;
        vm_offset_t loadaddr;
@@ -200,6 +222,7 @@ pmap_bootstrap(firstaddr, loadaddr)
        extern vm_offset_t maxmem, physmem;
 extern int IdlePTD;
 
        extern vm_offset_t maxmem, physmem;
 extern int IdlePTD;
 
+firstaddr = 0x100000;  /*XXX basemem completely fucked (again) */
        avail_start = firstaddr;
        avail_end = maxmem << PG_SHIFT;
 
        avail_start = firstaddr;
        avail_end = maxmem << PG_SHIFT;
 
@@ -209,9 +232,6 @@ extern int IdlePTD;
        mem_size = physmem << PG_SHIFT;
        virtual_avail = atdevbase + 0x100000 - 0xa0000 + 10*NBPG;
        virtual_end = VM_MAX_KERNEL_ADDRESS;
        mem_size = physmem << PG_SHIFT;
        virtual_avail = atdevbase + 0x100000 - 0xa0000 + 10*NBPG;
        virtual_end = VM_MAX_KERNEL_ADDRESS;
-printf("avail [%x %x] virtual [%x %x]\n",
-       avail_start, avail_end, virtual_avail, virtual_end);
-printf("cr3 %x", rcr3());
        i386pagesperpage = PAGE_SIZE / I386_PAGE_SIZE;
 
        /*
        i386pagesperpage = PAGE_SIZE / I386_PAGE_SIZE;
 
        /*
@@ -270,7 +290,6 @@ printf("cr3 %x", rcr3());
        /**(int *)PTD = 0;
        load_cr3(rcr3());*/
 
        /**(int *)PTD = 0;
        load_cr3(rcr3());*/
 
-       return (firstaddr);
 }
 
 /*
 }
 
 /*
@@ -296,7 +315,7 @@ pmap_init(phys_start, phys_end)
         * unavailable regions which we have mapped in locore.
         */
        addr = atdevbase;
         * unavailable regions which we have mapped in locore.
         */
        addr = atdevbase;
-       (void) vm_map_find(kernel_map, VM_OBJECT_NULL, (vm_offset_t) 0,
+       (void) vm_map_find(kernel_map, NULL, (vm_offset_t) 0,
                           &addr, (0x100000-0xa0000), FALSE);
 
        addr = (vm_offset_t) 0xfe000000+KPTphys/* *NBPG */;
                           &addr, (0x100000-0xa0000), FALSE);
 
        addr = (vm_offset_t) 0xfe000000+KPTphys/* *NBPG */;
@@ -370,6 +389,7 @@ pmap_map(virt, start, end, prot)
  * [ just allocate a ptd and mark it uninitialize -- should we track
  *   with a table which process has which ptd? -wfj ]
  */
  * [ just allocate a ptd and mark it uninitialize -- should we track
  *   with a table which process has which ptd? -wfj ]
  */
+
 pmap_t
 pmap_create(size)
        vm_size_t       size;
 pmap_t
 pmap_create(size)
        vm_size_t       size;
@@ -378,35 +398,55 @@ pmap_create(size)
 
 #ifdef DEBUG
        if (pmapdebug & (PDB_FOLLOW|PDB_CREATE))
 
 #ifdef DEBUG
        if (pmapdebug & (PDB_FOLLOW|PDB_CREATE))
-               pg("pmap_create(%x)", size);
+               printf("pmap_create(%x)\n", size);
 #endif
        /*
         * Software use map does not need a pmap
         */
        if (size)
 #endif
        /*
         * Software use map does not need a pmap
         */
        if (size)
-               return(PMAP_NULL);
+               return(NULL);
 
 
+       /* XXX: is it ok to wait here? */
        pmap = (pmap_t) malloc(sizeof *pmap, M_VMPMAP, M_WAITOK);
        pmap = (pmap_t) malloc(sizeof *pmap, M_VMPMAP, M_WAITOK);
-       if (pmap == PMAP_NULL)
+#ifdef notifwewait
+       if (pmap == NULL)
                panic("pmap_create: cannot allocate a pmap");
                panic("pmap_create: cannot allocate a pmap");
+#endif
+       bzero(pmap, sizeof(*pmap));
+       pmap_pinit(pmap);
+       return (pmap);
+}
+
+/*
+ * Initialize a preallocated and zeroed pmap structure,
+ * such as one in a vmspace structure.
+ */
+void
+pmap_pinit(pmap)
+       register struct pmap *pmap;
+{
+
+#ifdef DEBUG
+       if (pmapdebug & (PDB_FOLLOW|PDB_CREATE))
+               pg("pmap_pinit(%x)\n", pmap);
+#endif
 
        /*
         * No need to allocate page table space yet but we do need a
         * valid page directory table.
         */
        pmap->pm_pdir = (pd_entry_t *) kmem_alloc(kernel_map, NBPG);
 
        /*
         * No need to allocate page table space yet but we do need a
         * valid page directory table.
         */
        pmap->pm_pdir = (pd_entry_t *) kmem_alloc(kernel_map, NBPG);
+
+       /* wire in kernel global address entries */
        bcopy(PTD+KPTDI_FIRST, pmap->pm_pdir+KPTDI_FIRST,
                (KPTDI_LAST-KPTDI_FIRST+1)*4);
        bcopy(PTD+KPTDI_FIRST, pmap->pm_pdir+KPTDI_FIRST,
                (KPTDI_LAST-KPTDI_FIRST+1)*4);
+
+       /* install self-referential address mapping entry */
        *(int *)(pmap->pm_pdir+PTDPTDI) =
                (int)pmap_extract(kernel_pmap, pmap->pm_pdir) | PG_V | PG_URKW;
 
        *(int *)(pmap->pm_pdir+PTDPTDI) =
                (int)pmap_extract(kernel_pmap, pmap->pm_pdir) | PG_V | PG_URKW;
 
-       pmap->pm_dref = 0;
        pmap->pm_count = 1;
        simple_lock_init(&pmap->pm_lock);
        pmap->pm_count = 1;
        simple_lock_init(&pmap->pm_lock);
-       pmap->pm_stats.resident_count = 0;
-       pmap->pm_stats.wired_count = 0;
-       pmap->pm_ptpages = 0;
-       return(pmap);
 }
 
 /*
 }
 
 /*
@@ -422,19 +462,41 @@ pmap_destroy(pmap)
 
 #ifdef DEBUG
        if (pmapdebug & PDB_FOLLOW)
 
 #ifdef DEBUG
        if (pmapdebug & PDB_FOLLOW)
-               printf("pmap_destroy(%x)", pmap);
+               printf("pmap_destroy(%x)\n", pmap);
 #endif
 #endif
-       if (pmap == PMAP_NULL)
+       if (pmap == NULL)
                return;
 
        simple_lock(&pmap->pm_lock);
                return;
 
        simple_lock(&pmap->pm_lock);
-       /*count = --pmap->pm_count;*/
+       count = --pmap->pm_count;
        simple_unlock(&pmap->pm_lock);
        simple_unlock(&pmap->pm_lock);
-       /*if (count)
-               return;*/
+       if (count == 0) {
+               pmap_release(pmap);
+               free((caddr_t)pmap, M_VMPMAP);
+       }
+}
 
 
+/*
+ * Release any resources held by the given physical map.
+ * Called when a pmap initialized by pmap_pinit is being released.
+ * Should only be called if the map contains no valid mappings.
+ */
+void
+pmap_release(pmap)
+       register struct pmap *pmap;
+{
+
+#ifdef DEBUG
+       if (pmapdebug & PDB_FOLLOW)
+               pg("pmap_release(%x)\n", pmap);
+#endif
+#ifdef notdef /* DIAGNOSTIC */
+       /* count would be 0 from pmap_destroy... */
+       simple_lock(&pmap->pm_lock);
+       if (pmap->pm_count != 1)
+               panic("pmap_release count");
+#endif
        kmem_free(kernel_map, (vm_offset_t)pmap->pm_pdir, NBPG);
        kmem_free(kernel_map, (vm_offset_t)pmap->pm_pdir, NBPG);
-       free((caddr_t)pmap, M_VMPMAP);
 }
 
 /*
 }
 
 /*
@@ -448,7 +510,7 @@ pmap_reference(pmap)
        if (pmapdebug & PDB_FOLLOW)
                printf("pmap_reference(%x)", pmap);
 #endif
        if (pmapdebug & PDB_FOLLOW)
                printf("pmap_reference(%x)", pmap);
 #endif
-       if (pmap != PMAP_NULL) {
+       if (pmap != NULL) {
                simple_lock(&pmap->pm_lock);
                pmap->pm_count++;
                simple_unlock(&pmap->pm_lock);
                simple_lock(&pmap->pm_lock);
                pmap->pm_count++;
                simple_unlock(&pmap->pm_lock);
@@ -463,7 +525,7 @@ pmap_reference(pmap)
  */
 void
 pmap_remove(pmap, sva, eva)
  */
 void
 pmap_remove(pmap, sva, eva)
-       register pmap_t pmap;
+       register struct pmap *pmap;
        vm_offset_t sva, eva;
 {
        register vm_offset_t pa, va;
        vm_offset_t sva, eva;
 {
        register vm_offset_t pa, va;
@@ -481,7 +543,7 @@ pmap_remove(pmap, sva, eva)
                pg("pmap_remove(%x, %x, %x)", pmap, sva, eva);
 #endif
 
                pg("pmap_remove(%x, %x, %x)", pmap, sva, eva);
 #endif
 
-       if (pmap == PMAP_NULL)
+       if (pmap == NULL)
                return;
 
 #ifdef DEBUG
                return;
 
 #ifdef DEBUG
@@ -529,9 +591,13 @@ pmap_remove(pmap, sva, eva)
                        *(int *)pte++ = 0;
                        /*TBIS(va + ix * I386_PAGE_SIZE);*/
                } while (++ix != i386pagesperpage);
                        *(int *)pte++ = 0;
                        /*TBIS(va + ix * I386_PAGE_SIZE);*/
                } while (++ix != i386pagesperpage);
-               if (pmap == u.u_procp->p_map->pmap)
-                       pmap_activate(pmap, (struct pcb *)u.u_procp->p_addr);
-               load_cr3(u.u_pcb.pcb_ptd);
+               if (pmap == &curproc->p_vmspace->vm_pmap)
+                       pmap_activate(pmap, (struct pcb *)curproc->p_addr);
+               /* are we current address space or kernel? */
+               /*if (pmap->pm_pdir[PTDPTDI].pd_pfnum == PTDpde.pd_pfnum
+                       || pmap == kernel_pmap)
+               load_cr3(curpcb->pcb_ptd);*/
+               tlbflush();
 
 #ifdef needednotdone
 reduce wiring count on page table pages as references drop
 
 #ifdef needednotdone
 reduce wiring count on page table pages as references drop
@@ -557,7 +623,7 @@ reduce wiring count on page table pages as references drop
                                *pv = *npv;
                                free((caddr_t)npv, M_VMPVENT);
                        } else
                                *pv = *npv;
                                free((caddr_t)npv, M_VMPVENT);
                        } else
-                               pv->pv_pmap = PMAP_NULL;
+                               pv->pv_pmap = NULL;
 #ifdef DEBUG
                        remove_stats.pvfirst++;
 #endif
 #ifdef DEBUG
                        remove_stats.pvfirst++;
 #endif
@@ -571,7 +637,7 @@ reduce wiring count on page table pages as references drop
                                pv = npv;
                        }
 #ifdef DEBUG
                                pv = npv;
                        }
 #ifdef DEBUG
-                       if (npv == PV_ENTRY_NULL)
+                       if (npv == NULL)
                                panic("pmap_remove: PA not in pv_tab");
 #endif
                        pv->pv_next = npv->pv_next;
                                panic("pmap_remove: PA not in pv_tab");
 #endif
                        pv->pv_next = npv->pv_next;
@@ -623,7 +689,7 @@ pmap_remove_all(pa)
        /*
         * Do it the easy way for now
         */
        /*
         * Do it the easy way for now
         */
-       while (pv->pv_pmap != PMAP_NULL) {
+       while (pv->pv_pmap != NULL) {
 #ifdef DEBUG
                if (!pmap_pde_v(pmap_pde(pv->pv_pmap, pv->pv_va)) ||
                    pmap_pte_pa(pmap_pte(pv->pv_pmap, pv->pv_va)) != pa)
 #ifdef DEBUG
                if (!pmap_pde_v(pmap_pde(pv->pv_pmap, pv->pv_va)) ||
                    pmap_pte_pa(pmap_pte(pv->pv_pmap, pv->pv_va)) != pa)
@@ -671,7 +737,7 @@ pmap_protect(pmap, sva, eva, prot)
        if (pmapdebug & (PDB_FOLLOW|PDB_PROTECT))
                printf("pmap_protect(%x, %x, %x, %x)", pmap, sva, eva, prot);
 #endif
        if (pmapdebug & (PDB_FOLLOW|PDB_PROTECT))
                printf("pmap_protect(%x, %x, %x, %x)", pmap, sva, eva, prot);
 #endif
-       if (pmap == PMAP_NULL)
+       if (pmap == NULL)
                return;
 
        if ((prot & VM_PROT_READ) == VM_PROT_NONE) {
                return;
 
        if ((prot & VM_PROT_READ) == VM_PROT_NONE) {
@@ -717,8 +783,8 @@ pmap_protect(pmap, sva, eva, prot)
                        /*TBIS(va + ix * I386_PAGE_SIZE);*/
                } while (++ix != i386pagesperpage);
        }
                        /*TBIS(va + ix * I386_PAGE_SIZE);*/
                } while (++ix != i386pagesperpage);
        }
-       if (pmap == u.u_procp->p_map->pmap)
-               pmap_activate(pmap, (struct pcb *)u.u_procp->p_addr);
+       if (pmap == &curproc->p_vmspace->vm_pmap)
+               pmap_activate(pmap, (struct pcb *)curproc->p_addr);
 }
 
 /*
 }
 
 /*
@@ -752,7 +818,7 @@ pmap_enter(pmap, va, pa, prot, wired)
                printf("pmap_enter(%x, %x, %x, %x, %x)",
                       pmap, va, pa, prot, wired);
 #endif
                printf("pmap_enter(%x, %x, %x, %x, %x)",
                       pmap, va, pa, prot, wired);
 #endif
-       if (pmap == PMAP_NULL)
+       if (pmap == NULL)
                return;
 
        if(va > VM_MAX_KERNEL_ADDRESS)panic("pmap_enter: toobig");
                return;
 
        if(va > VM_MAX_KERNEL_ADDRESS)panic("pmap_enter: toobig");
@@ -845,13 +911,13 @@ pmap_enter(pmap, va, pa, prot, wired)
                /*
                 * No entries yet, use header as the first entry
                 */
                /*
                 * No entries yet, use header as the first entry
                 */
-               if (pv->pv_pmap == PMAP_NULL) {
+               if (pv->pv_pmap == NULL) {
 #ifdef DEBUG
                        enter_stats.firstpv++;
 #endif
                        pv->pv_va = va;
                        pv->pv_pmap = pmap;
 #ifdef DEBUG
                        enter_stats.firstpv++;
 #endif
                        pv->pv_va = va;
                        pv->pv_pmap = pmap;
-                       pv->pv_next = PV_ENTRY_NULL;
+                       pv->pv_next = NULL;
                        pv->pv_flags = 0;
                }
                /*
                        pv->pv_flags = 0;
                }
                /*
@@ -926,7 +992,31 @@ validate:
 cache, tlb flushes
 #endif
 /*pads(pmap);*/
 cache, tlb flushes
 #endif
 /*pads(pmap);*/
-       load_cr3(u.u_pcb.pcb_ptd);
+       /*load_cr3(((struct pcb *)curproc->p_addr)->pcb_ptd);*/
+       tlbflush();
+}
+
+/*
+ *      pmap_page_protect:
+ *
+ *      Lower the permission for all mappings to a given page.
+ */
+void
+pmap_page_protect(phys, prot)
+        vm_offset_t     phys;
+        vm_prot_t       prot;
+{
+        switch (prot) {
+        case VM_PROT_READ:
+        case VM_PROT_READ|VM_PROT_EXECUTE:
+                pmap_copy_on_write(phys);
+                break;
+        case VM_PROT_ALL:
+                break;
+        default:
+                pmap_remove_all(phys);
+                break;
+        }
 }
 
 /*
 }
 
 /*
@@ -949,7 +1039,7 @@ pmap_change_wiring(pmap, va, wired)
        if (pmapdebug & PDB_FOLLOW)
                printf("pmap_change_wiring(%x, %x, %x)", pmap, va, wired);
 #endif
        if (pmapdebug & PDB_FOLLOW)
                printf("pmap_change_wiring(%x, %x, %x)", pmap, va, wired);
 #endif
-       if (pmap == PMAP_NULL)
+       if (pmap == NULL)
                return;
 
        pte = pmap_pte(pmap, va);
                return;
 
        pte = pmap_pte(pmap, va);
@@ -1018,7 +1108,7 @@ struct pte *pmap_pte(pmap, va)
                        if (pmap->pm_pdir[PTDPTDI].pd_pfnum
                                != APTDpde.pd_pfnum) {
                                APTDpde = pmap->pm_pdir[PTDPTDI];
                        if (pmap->pm_pdir[PTDPTDI].pd_pfnum
                                != APTDpde.pd_pfnum) {
                                APTDpde = pmap->pm_pdir[PTDPTDI];
-                               load_cr3(u.u_pcb.pcb_ptd);
+                               tlbflush();
                        }
                        return((struct pte *) avtopte(va));
                }
                        }
                        return((struct pte *) avtopte(va));
                }
@@ -1092,7 +1182,7 @@ void pmap_update()
        if (pmapdebug & PDB_FOLLOW)
                printf("pmap_update()");
 #endif
        if (pmapdebug & PDB_FOLLOW)
                printf("pmap_update()");
 #endif
-       load_cr3(u.u_pcb.pcb_ptd);
+       tlbflush();
 }
 
 /*
 }
 
 /*
@@ -1120,14 +1210,14 @@ pmap_collect(pmap)
 #ifdef DEBUG
        int *pde;
        int opmapdebug;
 #ifdef DEBUG
        int *pde;
        int opmapdebug;
-#endif
        printf("pmap_collect(%x) ", pmap);
        printf("pmap_collect(%x) ", pmap);
+#endif
        if (pmap != kernel_pmap)
                return;
 
 }
 
        if (pmap != kernel_pmap)
                return;
 
 }
 
-/* [ macro again?, should I force u. into user map here? -wfj ] */
+/* [ macro again?, should I force kstack into user map here? -wfj ] */
 void
 pmap_activate(pmap, pcbp)
        register pmap_t pmap;
 void
 pmap_activate(pmap, pcbp)
        register pmap_t pmap;
@@ -1411,7 +1501,7 @@ pmap_testbit(pa, bit)
         * Not found, check current mappings returning
         * immediately if found.
         */
         * Not found, check current mappings returning
         * immediately if found.
         */
-       if (pv->pv_pmap != PMAP_NULL) {
+       if (pv->pv_pmap != NULL) {
                for (; pv; pv = pv->pv_next) {
                        pte = (int *) pmap_pte(pv->pv_pmap, pv->pv_va);
                        ix = 0;
                for (; pv; pv = pv->pv_next) {
                        pte = (int *) pmap_pte(pv->pv_pmap, pv->pv_va);
                        ix = 0;
@@ -1458,7 +1548,7 @@ pmap_changebit(pa, bit, setem)
         * Loop over all current mappings setting/clearing as appropos
         * If setting RO do we need to clear the VAC?
         */
         * Loop over all current mappings setting/clearing as appropos
         * If setting RO do we need to clear the VAC?
         */
-       if (pv->pv_pmap != PMAP_NULL) {
+       if (pv->pv_pmap != NULL) {
 #ifdef DEBUG
                int toflush = 0;
 #endif
 #ifdef DEBUG
                int toflush = 0;
 #endif
@@ -1467,6 +1557,17 @@ pmap_changebit(pa, bit, setem)
                        toflush |= (pv->pv_pmap == kernel_pmap) ? 2 : 1;
 #endif
                        va = pv->pv_va;
                        toflush |= (pv->pv_pmap == kernel_pmap) ? 2 : 1;
 #endif
                        va = pv->pv_va;
+
+                        /*
+                         * XXX don't write protect pager mappings
+                         */
+                        if (bit == PG_RO) {
+                                extern vm_offset_t pager_sva, pager_eva;
+
+                                if (va >= pager_sva && va < pager_eva)
+                                        continue;
+                        }
+
                        pte = (int *) pmap_pte(pv->pv_pmap, va);
                        ix = 0;
                        do {
                        pte = (int *) pmap_pte(pv->pv_pmap, va);
                        ix = 0;
                        do {
@@ -1482,8 +1583,8 @@ pmap_changebit(pa, bit, setem)
                                pte++;
                        } while (++ix != i386pagesperpage);
 
                                pte++;
                        } while (++ix != i386pagesperpage);
 
-                       if (pv->pv_pmap == u.u_procp->p_map->pmap)
-                               pmap_activate(pv->pv_pmap, (struct pcb *)u.u_procp->p_addr);
+                       if (pv->pv_pmap == &curproc->p_vmspace->vm_pmap)
+                               pmap_activate(pv->pv_pmap, (struct pcb *)curproc->p_addr);
                }
 #ifdef somethinglikethis
                if (setem && bit == PG_RO && (pmapvacflush & PVF_PROTECT)) {
                }
 #ifdef somethinglikethis
                if (setem && bit == PG_RO && (pmapvacflush & PVF_PROTECT)) {