aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--sys/amd64/amd64/db_interface.c6
-rw-r--r--sys/amd64/amd64/pmap.c285
-rw-r--r--sys/amd64/include/pmap.h2
-rw-r--r--sys/i386/i386/db_interface.c6
-rw-r--r--sys/i386/i386/pmap.c285
-rw-r--r--sys/i386/include/pmap.h2
6 files changed, 224 insertions, 362 deletions
diff --git a/sys/amd64/amd64/db_interface.c b/sys/amd64/amd64/db_interface.c
index e2b936bb1f0d..a26a555af779 100644
--- a/sys/amd64/amd64/db_interface.c
+++ b/sys/amd64/amd64/db_interface.c
@@ -262,7 +262,7 @@ db_write_bytes(vm_offset_t addr, size_t size, char *data)
if (addr > trunc_page((vm_offset_t)btext) - size &&
addr < round_page((vm_offset_t)etext)) {
- ptep0 = pmap_pte(kernel_pmap, addr);
+ ptep0 = pmap_pte_quick(kernel_pmap, addr);
oldmap0 = *ptep0;
*ptep0 |= PG_RW;
@@ -270,14 +270,14 @@ db_write_bytes(vm_offset_t addr, size_t size, char *data)
if ((*ptep0 & PG_PS) == 0) {
addr1 = trunc_page(addr + size - 1);
if (trunc_page(addr) != addr1) {
- ptep1 = pmap_pte(kernel_pmap, addr1);
+ ptep1 = pmap_pte_quick(kernel_pmap, addr1);
oldmap1 = *ptep1;
*ptep1 |= PG_RW;
}
} else {
addr1 = trunc_4mpage(addr + size - 1);
if (trunc_4mpage(addr) != addr1) {
- ptep1 = pmap_pte(kernel_pmap, addr1);
+ ptep1 = pmap_pte_quick(kernel_pmap, addr1);
oldmap1 = *ptep1;
*ptep1 |= PG_RW;
}
diff --git a/sys/amd64/amd64/pmap.c b/sys/amd64/amd64/pmap.c
index daa99c422d3d..6892275ee451 100644
--- a/sys/amd64/amd64/pmap.c
+++ b/sys/amd64/amd64/pmap.c
@@ -41,6 +41,37 @@
* from: @(#)pmap.c 7.7 (Berkeley) 5/12/91
* $FreeBSD$
*/
+/*-
+ * Copyright (c) 2003 Networks Associates Technology, Inc.
+ * All rights reserved.
+ *
+ * This software was developed for the FreeBSD Project by Jake Burkholder,
+ * Safeport Network Services, and Network Associates Laboratories, the
+ * Security Research Division of Network Associates, Inc. under
+ * DARPA/SPAWAR contract N66001-01-C-8035 ("CBOSS"), as part of the DARPA
+ * CHATS research program.
+ *
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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.
+ */
/*
* Manages physical address maps.
@@ -198,7 +229,6 @@ static pt_entry_t *PMAP1 = 0;
static pt_entry_t *PADDR1 = 0;
static PMAP_INLINE void free_pv_entry(pv_entry_t pv);
-static pt_entry_t *get_ptbase(pmap_t pmap);
static pv_entry_t get_pv_entry(void);
static void i386_protection_init(void);
static __inline void pmap_changebit(vm_page_t m, int bit, boolean_t setem);
@@ -215,7 +245,6 @@ static void pmap_insert_entry(pmap_t pmap, vm_offset_t va,
static vm_page_t pmap_allocpte(pmap_t pmap, vm_offset_t va);
static vm_page_t _pmap_allocpte(pmap_t pmap, unsigned ptepindex);
-static pt_entry_t *pmap_pte_quick(pmap_t pmap, vm_offset_t va);
static vm_page_t pmap_page_lookup(vm_object_t object, vm_pindex_t pindex);
static int pmap_unuse_pt(pmap_t, vm_offset_t, vm_page_t);
static vm_offset_t pmap_kmem_choose(vm_offset_t addr);
@@ -227,31 +256,6 @@ CTASSERT(1 << PDESHIFT == sizeof(pd_entry_t));
CTASSERT(1 << PTESHIFT == sizeof(pt_entry_t));
/*
- * Routine: pmap_pte
- * Function:
- * Extract the page table entry associated
- * with the given map/virtual_address pair.
- */
-
-PMAP_INLINE pt_entry_t *
-pmap_pte(pmap, va)
- register pmap_t pmap;
- vm_offset_t va;
-{
- pd_entry_t *pdeaddr;
-
- if (pmap) {
- pdeaddr = pmap_pde(pmap, va);
- if (*pdeaddr & PG_PS)
- return pdeaddr;
- if (*pdeaddr) {
- return get_ptbase(pmap) + i386_btop(va);
- }
- }
- return (0);
-}
-
-/*
* Move the kernel virtual free pointer to the next
* 4MB. This is used to help improve performance
* by using a large (4MB) page for much of the kernel
@@ -336,7 +340,7 @@ pmap_bootstrap(firstaddr, loadaddr)
v = (c)va; va += ((n)*PAGE_SIZE); p = pte; pte += (n);
va = virtual_avail;
- pte = (pt_entry_t *) pmap_pte(kernel_pmap, va);
+ pte = vtopte(va);
/*
* CMAP1/CMAP2 are used for zeroing and copying pages.
@@ -766,72 +770,33 @@ pmap_is_current(pmap_t pmap)
}
/*
- * Are we alternate address space?
- */
-static __inline int
-pmap_is_alternate(pmap_t pmap)
-{
- return ((pmap->pm_pdir[PTDPTDI] & PG_FRAME) ==
- (APTDpde[0] & PG_FRAME));
-}
-
-/*
- * Map in a pmap's pagetables as alternate address space.
- */
-static __inline void
-pmap_set_alternate(pmap_t pmap)
-{
-
- if (!pmap_is_alternate(pmap)) {
- APTDpde[0] = pmap->pm_pdir[PTDPTDI];
- pmap_invalidate_all(kernel_pmap); /* XXX Bandaid */
- }
-}
-
-/*
- * Return an address which is the base of the Virtual mapping of
- * all the PTEs for the given pmap. Note this doesn't say that
- * all the PTEs will be present or that the pages there are valid.
- * The PTEs are made available by the recursive mapping trick.
- * It will map in the alternate PTE space if needed.
- */
-static pt_entry_t *
-get_ptbase(pmap)
- pmap_t pmap;
-{
-
- if (pmap_is_current(pmap))
- return PTmap;
- pmap_set_alternate(pmap);
- return APTmap;
-}
-
-/*
* Super fast pmap_pte routine best used when scanning
* the pv lists. This eliminates many coarse-grained
* invltlb calls. Note that many of the pv list
* scans are across different pmaps. It is very wasteful
* to do an entire invltlb for checking a single mapping.
*/
-
-static pt_entry_t *
+pt_entry_t *
pmap_pte_quick(pmap, va)
register pmap_t pmap;
vm_offset_t va;
{
- pd_entry_t pde, newpf;
- pde = pmap->pm_pdir[va >> PDRSHIFT];
- if (pde != 0) {
- unsigned index = i386_btop(va);
+ pd_entry_t newpf;
+ pd_entry_t *pde;
+
+ pde = pmap_pde(pmap, va);
+ if (*pde & PG_PS)
+ return (pde);
+ if (*pde != 0) {
/* are we current address space or kernel? */
if (pmap_is_current(pmap))
- return PTmap + index;
- newpf = pde & PG_FRAME;
+ return vtopte(va);
+ newpf = *pde & PG_FRAME;
if (((*PMAP1) & PG_FRAME) != newpf) {
*PMAP1 = newpf | PG_RW | PG_V;
pmap_invalidate_page(kernel_pmap, (vm_offset_t)PADDR1);
}
- return PADDR1 + (index & (NPTEPG - 1));
+ return PADDR1 + (i386_btop(va) & (NPTEPG - 1));
}
return (0);
}
@@ -848,20 +813,18 @@ pmap_extract(pmap, va)
vm_offset_t va;
{
vm_paddr_t rtval;
- vm_offset_t pdirindex;
+ pt_entry_t *pte;
+ pd_entry_t pde;
if (pmap == 0)
return 0;
- pdirindex = va >> PDRSHIFT;
- rtval = pmap->pm_pdir[pdirindex];
- if (rtval != 0) {
- pt_entry_t *pte;
- if ((rtval & PG_PS) != 0) {
- rtval &= ~(NBPDR - 1);
- rtval |= va & (NBPDR - 1);
+ pde = pmap->pm_pdir[va >> PDRSHIFT];
+ if (pde != 0) {
+ if ((pde & PG_PS) != 0) {
+ rtval = (pde & ~PDRMASK) | (va & PDRMASK);
return rtval;
}
- pte = get_ptbase(pmap) + i386_btop(va);
+ pte = pmap_pte_quick(pmap, va);
rtval = ((*pte & PG_FRAME) | (va & PAGE_MASK));
return rtval;
}
@@ -1756,24 +1719,12 @@ pmap_remove_pte(pmap_t pmap, pt_entry_t *ptq, vm_offset_t va)
static void
pmap_remove_page(pmap_t pmap, vm_offset_t va)
{
- register pt_entry_t *ptq;
+ pt_entry_t *pte;
- /*
- * if there is no pte for this address, just skip it!!!
- */
- if (*pmap_pde(pmap, va) == 0) {
+ if ((pte = pmap_pte_quick(pmap, va)) == NULL || *pte == 0)
return;
- }
-
- /*
- * get a local va for mappings for this pmap.
- */
- ptq = get_ptbase(pmap) + i386_btop(va);
- if (*ptq) {
- (void) pmap_remove_pte(pmap, ptq, va);
- pmap_invalidate_page(pmap, va);
- }
- return;
+ pmap_remove_pte(pmap, pte, va);
+ pmap_invalidate_page(pmap, va);
}
/*
@@ -1785,10 +1736,9 @@ pmap_remove_page(pmap_t pmap, vm_offset_t va)
void
pmap_remove(pmap_t pmap, vm_offset_t sva, vm_offset_t eva)
{
- register pt_entry_t *ptbase;
vm_offset_t pdnxt;
pd_entry_t ptpaddr;
- vm_offset_t sindex, eindex;
+ pt_entry_t *pte;
int anyvalid;
if (pmap == NULL)
@@ -1810,33 +1760,18 @@ pmap_remove(pmap_t pmap, vm_offset_t sva, vm_offset_t eva)
anyvalid = 0;
- /*
- * Get a local virtual address for the mappings that are being
- * worked with.
- */
- ptbase = get_ptbase(pmap);
-
- sindex = i386_btop(sva);
- eindex = i386_btop(eva);
-
- for (; sindex < eindex; sindex = pdnxt) {
+ for (; sva < eva; sva = pdnxt) {
unsigned pdirindex;
/*
* Calculate index for next page table.
*/
- pdnxt = ((sindex + NPTEPG) & ~(NPTEPG - 1));
+ pdnxt = (sva + NBPDR) & ~PDRMASK;
if (pmap->pm_stats.resident_count == 0)
break;
- pdirindex = sindex / NPDEPG;
+ pdirindex = sva >> PDRSHIFT;
ptpaddr = pmap->pm_pdir[pdirindex];
- if ((ptpaddr & PG_PS) != 0) {
- pmap->pm_pdir[pdirindex] = 0;
- pmap->pm_stats.resident_count -= NBPDR / PAGE_SIZE;
- anyvalid++;
- continue;
- }
/*
* Weed out invalid mappings. Note: we assume that the page
@@ -1846,23 +1781,29 @@ pmap_remove(pmap_t pmap, vm_offset_t sva, vm_offset_t eva)
continue;
/*
+ * Check for large page.
+ */
+ if ((ptpaddr & PG_PS) != 0) {
+ pmap->pm_pdir[pdirindex] = 0;
+ pmap->pm_stats.resident_count -= NBPDR / PAGE_SIZE;
+ anyvalid = 1;
+ continue;
+ }
+
+ /*
* Limit our scan to either the end of the va represented
* by the current page table page, or to the end of the
* range being removed.
*/
- if (pdnxt > eindex) {
- pdnxt = eindex;
- }
+ if (pdnxt > eva)
+ pdnxt = eva;
- for (; sindex != pdnxt; sindex++) {
- vm_offset_t va;
- if (ptbase[sindex] == 0) {
+ for (; sva != pdnxt; sva += PAGE_SIZE) {
+ if ((pte = pmap_pte_quick(pmap, sva)) == NULL ||
+ *pte == 0)
continue;
- }
- va = i386_ptob(sindex);
-
- anyvalid++;
- if (pmap_remove_pte(pmap, ptbase + sindex, va))
+ anyvalid = 1;
+ if (pmap_remove_pte(pmap, pte, sva))
break;
}
}
@@ -1943,10 +1884,8 @@ pmap_remove_all(vm_page_t m)
void
pmap_protect(pmap_t pmap, vm_offset_t sva, vm_offset_t eva, vm_prot_t prot)
{
- register pt_entry_t *ptbase;
vm_offset_t pdnxt;
pd_entry_t ptpaddr;
- vm_offset_t sindex, eindex;
int anychanged;
if (pmap == NULL)
@@ -1962,25 +1901,13 @@ pmap_protect(pmap_t pmap, vm_offset_t sva, vm_offset_t eva, vm_prot_t prot)
anychanged = 0;
- ptbase = get_ptbase(pmap);
-
- sindex = i386_btop(sva);
- eindex = i386_btop(eva);
-
- for (; sindex < eindex; sindex = pdnxt) {
-
+ for (; sva < eva; sva = pdnxt) {
unsigned pdirindex;
- pdnxt = ((sindex + NPTEPG) & ~(NPTEPG - 1));
+ pdnxt = (sva + NBPDR) & ~PDRMASK;
- pdirindex = sindex / NPDEPG;
+ pdirindex = sva >> PDRSHIFT;
ptpaddr = pmap->pm_pdir[pdirindex];
- if ((ptpaddr & PG_PS) != 0) {
- pmap->pm_pdir[pdirindex] &= ~(PG_M|PG_RW);
- pmap->pm_stats.resident_count -= NBPDR / PAGE_SIZE;
- anychanged++;
- continue;
- }
/*
* Weed out invalid mappings. Note: we assume that the page
@@ -1989,17 +1916,27 @@ pmap_protect(pmap_t pmap, vm_offset_t sva, vm_offset_t eva, vm_prot_t prot)
if (ptpaddr == 0)
continue;
- if (pdnxt > eindex) {
- pdnxt = eindex;
+ /*
+ * Check for large page.
+ */
+ if ((ptpaddr & PG_PS) != 0) {
+ pmap->pm_pdir[pdirindex] &= ~(PG_M|PG_RW);
+ pmap->pm_stats.resident_count -= NBPDR / PAGE_SIZE;
+ anychanged = 1;
+ continue;
}
- for (; sindex != pdnxt; sindex++) {
+ if (pdnxt > eva)
+ pdnxt = eva;
+ for (; sva != pdnxt; sva += PAGE_SIZE) {
pt_entry_t pbits;
+ pt_entry_t *pte;
vm_page_t m;
- pbits = ptbase[sindex];
-
+ if ((pte = pmap_pte_quick(pmap, sva)) == NULL)
+ continue;
+ pbits = *pte;
if (pbits & PG_MANAGED) {
m = NULL;
if (pbits & PG_A) {
@@ -2007,20 +1944,19 @@ pmap_protect(pmap_t pmap, vm_offset_t sva, vm_offset_t eva, vm_prot_t prot)
vm_page_flag_set(m, PG_REFERENCED);
pbits &= ~PG_A;
}
- if (pbits & PG_M) {
- if (pmap_track_modified(i386_ptob(sindex))) {
- if (m == NULL)
- m = PHYS_TO_VM_PAGE(pbits);
- vm_page_dirty(m);
- pbits &= ~PG_M;
- }
+ if ((pbits & PG_M) != 0 &&
+ pmap_track_modified(sva)) {
+ if (m == NULL)
+ m = PHYS_TO_VM_PAGE(pbits);
+ vm_page_dirty(m);
+ pbits &= ~PG_M;
}
}
pbits &= ~PG_RW;
- if (pbits != ptbase[sindex]) {
- ptbase[sindex] = pbits;
+ if (pbits != *pte) {
+ *pte = pbits;
anychanged = 1;
}
}
@@ -2081,7 +2017,7 @@ pmap_enter(pmap_t pmap, vm_offset_t va, vm_page_t m, vm_prot_t prot,
}
#endif
- pte = pmap_pte(pmap, va);
+ pte = pmap_pte_quick(pmap, va);
/*
* Page Directory table entry not valid, we need a new PT page
@@ -2576,7 +2512,7 @@ pmap_change_wiring(pmap, va, wired)
if (pmap == NULL)
return;
- pte = pmap_pte(pmap, va);
+ pte = pmap_pte_quick(pmap, va);
if (wired && !pmap_pte_w(pte))
pmap->pm_stats.wired_count++;
@@ -2633,7 +2569,7 @@ pmap_copy(pmap_t dst_pmap, pmap_t src_pmap, vm_offset_t dst_addr, vm_size_t len,
pv_entry_count > pv_entry_high_water)
break;
- pdnxt = ((addr + PAGE_SIZE*NPTEPG) & ~(PAGE_SIZE*NPTEPG - 1));
+ pdnxt = (addr + NBPDR) & ~PDRMASK;
ptepindex = addr >> PDRSHIFT;
srcptepaddr = src_pmap->pm_pdir[ptepindex];
@@ -2643,7 +2579,8 @@ pmap_copy(pmap_t dst_pmap, pmap_t src_pmap, vm_offset_t dst_addr, vm_size_t len,
if (srcptepaddr & PG_PS) {
if (dst_pmap->pm_pdir[ptepindex] == 0) {
dst_pmap->pm_pdir[ptepindex] = srcptepaddr;
- dst_pmap->pm_stats.resident_count += NBPDR / PAGE_SIZE;
+ dst_pmap->pm_stats.resident_count +=
+ NBPDR / PAGE_SIZE;
}
continue;
}
@@ -2656,13 +2593,7 @@ pmap_copy(pmap_t dst_pmap, pmap_t src_pmap, vm_offset_t dst_addr, vm_size_t len,
if (pdnxt > end_addr)
pdnxt = end_addr;
- /*
- * Have to recheck this before every avtopte() call below
- * in case we have blocked and something else used APTDpde.
- */
- pmap_set_alternate(dst_pmap);
src_pte = vtopte(addr);
- dst_pte = avtopte(addr);
while (addr < pdnxt) {
pt_entry_t ptetemp;
ptetemp = *src_pte;
@@ -2676,6 +2607,7 @@ pmap_copy(pmap_t dst_pmap, pmap_t src_pmap, vm_offset_t dst_addr, vm_size_t len,
* block.
*/
dstmpte = pmap_allocpte(dst_pmap, addr);
+ dst_pte = pmap_pte_quick(dst_pmap, addr);
if ((*dst_pte == 0) && (ptetemp = *src_pte)) {
/*
* Clear the modified and
@@ -2697,7 +2629,6 @@ pmap_copy(pmap_t dst_pmap, pmap_t src_pmap, vm_offset_t dst_addr, vm_size_t len,
}
addr += PAGE_SIZE;
src_pte++;
- dst_pte++;
}
}
}
@@ -3288,7 +3219,7 @@ pmap_mincore(pmap, addr)
vm_page_t m;
int val = 0;
- ptep = pmap_pte(pmap, addr);
+ ptep = pmap_pte_quick(pmap, addr);
if (ptep == 0) {
return 0;
}
diff --git a/sys/amd64/include/pmap.h b/sys/amd64/include/pmap.h
index 8688b4627131..ad590ed879b0 100644
--- a/sys/amd64/include/pmap.h
+++ b/sys/amd64/include/pmap.h
@@ -252,7 +252,7 @@ void pmap_kenter(vm_offset_t va, vm_paddr_t pa);
void pmap_kremove(vm_offset_t);
void *pmap_mapdev(vm_paddr_t, vm_size_t);
void pmap_unmapdev(vm_offset_t, vm_size_t);
-pt_entry_t *pmap_pte(pmap_t, vm_offset_t) __pure2;
+pt_entry_t *pmap_pte_quick(pmap_t, vm_offset_t) __pure2;
void pmap_set_opt(void);
void pmap_invalidate_page(pmap_t, vm_offset_t);
void pmap_invalidate_range(pmap_t, vm_offset_t, vm_offset_t);
diff --git a/sys/i386/i386/db_interface.c b/sys/i386/i386/db_interface.c
index e2b936bb1f0d..a26a555af779 100644
--- a/sys/i386/i386/db_interface.c
+++ b/sys/i386/i386/db_interface.c
@@ -262,7 +262,7 @@ db_write_bytes(vm_offset_t addr, size_t size, char *data)
if (addr > trunc_page((vm_offset_t)btext) - size &&
addr < round_page((vm_offset_t)etext)) {
- ptep0 = pmap_pte(kernel_pmap, addr);
+ ptep0 = pmap_pte_quick(kernel_pmap, addr);
oldmap0 = *ptep0;
*ptep0 |= PG_RW;
@@ -270,14 +270,14 @@ db_write_bytes(vm_offset_t addr, size_t size, char *data)
if ((*ptep0 & PG_PS) == 0) {
addr1 = trunc_page(addr + size - 1);
if (trunc_page(addr) != addr1) {
- ptep1 = pmap_pte(kernel_pmap, addr1);
+ ptep1 = pmap_pte_quick(kernel_pmap, addr1);
oldmap1 = *ptep1;
*ptep1 |= PG_RW;
}
} else {
addr1 = trunc_4mpage(addr + size - 1);
if (trunc_4mpage(addr) != addr1) {
- ptep1 = pmap_pte(kernel_pmap, addr1);
+ ptep1 = pmap_pte_quick(kernel_pmap, addr1);
oldmap1 = *ptep1;
*ptep1 |= PG_RW;
}
diff --git a/sys/i386/i386/pmap.c b/sys/i386/i386/pmap.c
index daa99c422d3d..6892275ee451 100644
--- a/sys/i386/i386/pmap.c
+++ b/sys/i386/i386/pmap.c
@@ -41,6 +41,37 @@
* from: @(#)pmap.c 7.7 (Berkeley) 5/12/91
* $FreeBSD$
*/
+/*-
+ * Copyright (c) 2003 Networks Associates Technology, Inc.
+ * All rights reserved.
+ *
+ * This software was developed for the FreeBSD Project by Jake Burkholder,
+ * Safeport Network Services, and Network Associates Laboratories, the
+ * Security Research Division of Network Associates, Inc. under
+ * DARPA/SPAWAR contract N66001-01-C-8035 ("CBOSS"), as part of the DARPA
+ * CHATS research program.
+ *
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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.
+ */
/*
* Manages physical address maps.
@@ -198,7 +229,6 @@ static pt_entry_t *PMAP1 = 0;
static pt_entry_t *PADDR1 = 0;
static PMAP_INLINE void free_pv_entry(pv_entry_t pv);
-static pt_entry_t *get_ptbase(pmap_t pmap);
static pv_entry_t get_pv_entry(void);
static void i386_protection_init(void);
static __inline void pmap_changebit(vm_page_t m, int bit, boolean_t setem);
@@ -215,7 +245,6 @@ static void pmap_insert_entry(pmap_t pmap, vm_offset_t va,
static vm_page_t pmap_allocpte(pmap_t pmap, vm_offset_t va);
static vm_page_t _pmap_allocpte(pmap_t pmap, unsigned ptepindex);
-static pt_entry_t *pmap_pte_quick(pmap_t pmap, vm_offset_t va);
static vm_page_t pmap_page_lookup(vm_object_t object, vm_pindex_t pindex);
static int pmap_unuse_pt(pmap_t, vm_offset_t, vm_page_t);
static vm_offset_t pmap_kmem_choose(vm_offset_t addr);
@@ -227,31 +256,6 @@ CTASSERT(1 << PDESHIFT == sizeof(pd_entry_t));
CTASSERT(1 << PTESHIFT == sizeof(pt_entry_t));
/*
- * Routine: pmap_pte
- * Function:
- * Extract the page table entry associated
- * with the given map/virtual_address pair.
- */
-
-PMAP_INLINE pt_entry_t *
-pmap_pte(pmap, va)
- register pmap_t pmap;
- vm_offset_t va;
-{
- pd_entry_t *pdeaddr;
-
- if (pmap) {
- pdeaddr = pmap_pde(pmap, va);
- if (*pdeaddr & PG_PS)
- return pdeaddr;
- if (*pdeaddr) {
- return get_ptbase(pmap) + i386_btop(va);
- }
- }
- return (0);
-}
-
-/*
* Move the kernel virtual free pointer to the next
* 4MB. This is used to help improve performance
* by using a large (4MB) page for much of the kernel
@@ -336,7 +340,7 @@ pmap_bootstrap(firstaddr, loadaddr)
v = (c)va; va += ((n)*PAGE_SIZE); p = pte; pte += (n);
va = virtual_avail;
- pte = (pt_entry_t *) pmap_pte(kernel_pmap, va);
+ pte = vtopte(va);
/*
* CMAP1/CMAP2 are used for zeroing and copying pages.
@@ -766,72 +770,33 @@ pmap_is_current(pmap_t pmap)
}
/*
- * Are we alternate address space?
- */
-static __inline int
-pmap_is_alternate(pmap_t pmap)
-{
- return ((pmap->pm_pdir[PTDPTDI] & PG_FRAME) ==
- (APTDpde[0] & PG_FRAME));
-}
-
-/*
- * Map in a pmap's pagetables as alternate address space.
- */
-static __inline void
-pmap_set_alternate(pmap_t pmap)
-{
-
- if (!pmap_is_alternate(pmap)) {
- APTDpde[0] = pmap->pm_pdir[PTDPTDI];
- pmap_invalidate_all(kernel_pmap); /* XXX Bandaid */
- }
-}
-
-/*
- * Return an address which is the base of the Virtual mapping of
- * all the PTEs for the given pmap. Note this doesn't say that
- * all the PTEs will be present or that the pages there are valid.
- * The PTEs are made available by the recursive mapping trick.
- * It will map in the alternate PTE space if needed.
- */
-static pt_entry_t *
-get_ptbase(pmap)
- pmap_t pmap;
-{
-
- if (pmap_is_current(pmap))
- return PTmap;
- pmap_set_alternate(pmap);
- return APTmap;
-}
-
-/*
* Super fast pmap_pte routine best used when scanning
* the pv lists. This eliminates many coarse-grained
* invltlb calls. Note that many of the pv list
* scans are across different pmaps. It is very wasteful
* to do an entire invltlb for checking a single mapping.
*/
-
-static pt_entry_t *
+pt_entry_t *
pmap_pte_quick(pmap, va)
register pmap_t pmap;
vm_offset_t va;
{
- pd_entry_t pde, newpf;
- pde = pmap->pm_pdir[va >> PDRSHIFT];
- if (pde != 0) {
- unsigned index = i386_btop(va);
+ pd_entry_t newpf;
+ pd_entry_t *pde;
+
+ pde = pmap_pde(pmap, va);
+ if (*pde & PG_PS)
+ return (pde);
+ if (*pde != 0) {
/* are we current address space or kernel? */
if (pmap_is_current(pmap))
- return PTmap + index;
- newpf = pde & PG_FRAME;
+ return vtopte(va);
+ newpf = *pde & PG_FRAME;
if (((*PMAP1) & PG_FRAME) != newpf) {
*PMAP1 = newpf | PG_RW | PG_V;
pmap_invalidate_page(kernel_pmap, (vm_offset_t)PADDR1);
}
- return PADDR1 + (index & (NPTEPG - 1));
+ return PADDR1 + (i386_btop(va) & (NPTEPG - 1));
}
return (0);
}
@@ -848,20 +813,18 @@ pmap_extract(pmap, va)
vm_offset_t va;
{
vm_paddr_t rtval;
- vm_offset_t pdirindex;
+ pt_entry_t *pte;
+ pd_entry_t pde;
if (pmap == 0)
return 0;
- pdirindex = va >> PDRSHIFT;
- rtval = pmap->pm_pdir[pdirindex];
- if (rtval != 0) {
- pt_entry_t *pte;
- if ((rtval & PG_PS) != 0) {
- rtval &= ~(NBPDR - 1);
- rtval |= va & (NBPDR - 1);
+ pde = pmap->pm_pdir[va >> PDRSHIFT];
+ if (pde != 0) {
+ if ((pde & PG_PS) != 0) {
+ rtval = (pde & ~PDRMASK) | (va & PDRMASK);
return rtval;
}
- pte = get_ptbase(pmap) + i386_btop(va);
+ pte = pmap_pte_quick(pmap, va);
rtval = ((*pte & PG_FRAME) | (va & PAGE_MASK));
return rtval;
}
@@ -1756,24 +1719,12 @@ pmap_remove_pte(pmap_t pmap, pt_entry_t *ptq, vm_offset_t va)
static void
pmap_remove_page(pmap_t pmap, vm_offset_t va)
{
- register pt_entry_t *ptq;
+ pt_entry_t *pte;
- /*
- * if there is no pte for this address, just skip it!!!
- */
- if (*pmap_pde(pmap, va) == 0) {
+ if ((pte = pmap_pte_quick(pmap, va)) == NULL || *pte == 0)
return;
- }
-
- /*
- * get a local va for mappings for this pmap.
- */
- ptq = get_ptbase(pmap) + i386_btop(va);
- if (*ptq) {
- (void) pmap_remove_pte(pmap, ptq, va);
- pmap_invalidate_page(pmap, va);
- }
- return;
+ pmap_remove_pte(pmap, pte, va);
+ pmap_invalidate_page(pmap, va);
}
/*
@@ -1785,10 +1736,9 @@ pmap_remove_page(pmap_t pmap, vm_offset_t va)
void
pmap_remove(pmap_t pmap, vm_offset_t sva, vm_offset_t eva)
{
- register pt_entry_t *ptbase;
vm_offset_t pdnxt;
pd_entry_t ptpaddr;
- vm_offset_t sindex, eindex;
+ pt_entry_t *pte;
int anyvalid;
if (pmap == NULL)
@@ -1810,33 +1760,18 @@ pmap_remove(pmap_t pmap, vm_offset_t sva, vm_offset_t eva)
anyvalid = 0;
- /*
- * Get a local virtual address for the mappings that are being
- * worked with.
- */
- ptbase = get_ptbase(pmap);
-
- sindex = i386_btop(sva);
- eindex = i386_btop(eva);
-
- for (; sindex < eindex; sindex = pdnxt) {
+ for (; sva < eva; sva = pdnxt) {
unsigned pdirindex;
/*
* Calculate index for next page table.
*/
- pdnxt = ((sindex + NPTEPG) & ~(NPTEPG - 1));
+ pdnxt = (sva + NBPDR) & ~PDRMASK;
if (pmap->pm_stats.resident_count == 0)
break;
- pdirindex = sindex / NPDEPG;
+ pdirindex = sva >> PDRSHIFT;
ptpaddr = pmap->pm_pdir[pdirindex];
- if ((ptpaddr & PG_PS) != 0) {
- pmap->pm_pdir[pdirindex] = 0;
- pmap->pm_stats.resident_count -= NBPDR / PAGE_SIZE;
- anyvalid++;
- continue;
- }
/*
* Weed out invalid mappings. Note: we assume that the page
@@ -1846,23 +1781,29 @@ pmap_remove(pmap_t pmap, vm_offset_t sva, vm_offset_t eva)
continue;
/*
+ * Check for large page.
+ */
+ if ((ptpaddr & PG_PS) != 0) {
+ pmap->pm_pdir[pdirindex] = 0;
+ pmap->pm_stats.resident_count -= NBPDR / PAGE_SIZE;
+ anyvalid = 1;
+ continue;
+ }
+
+ /*
* Limit our scan to either the end of the va represented
* by the current page table page, or to the end of the
* range being removed.
*/
- if (pdnxt > eindex) {
- pdnxt = eindex;
- }
+ if (pdnxt > eva)
+ pdnxt = eva;
- for (; sindex != pdnxt; sindex++) {
- vm_offset_t va;
- if (ptbase[sindex] == 0) {
+ for (; sva != pdnxt; sva += PAGE_SIZE) {
+ if ((pte = pmap_pte_quick(pmap, sva)) == NULL ||
+ *pte == 0)
continue;
- }
- va = i386_ptob(sindex);
-
- anyvalid++;
- if (pmap_remove_pte(pmap, ptbase + sindex, va))
+ anyvalid = 1;
+ if (pmap_remove_pte(pmap, pte, sva))
break;
}
}
@@ -1943,10 +1884,8 @@ pmap_remove_all(vm_page_t m)
void
pmap_protect(pmap_t pmap, vm_offset_t sva, vm_offset_t eva, vm_prot_t prot)
{
- register pt_entry_t *ptbase;
vm_offset_t pdnxt;
pd_entry_t ptpaddr;
- vm_offset_t sindex, eindex;
int anychanged;
if (pmap == NULL)
@@ -1962,25 +1901,13 @@ pmap_protect(pmap_t pmap, vm_offset_t sva, vm_offset_t eva, vm_prot_t prot)
anychanged = 0;
- ptbase = get_ptbase(pmap);
-
- sindex = i386_btop(sva);
- eindex = i386_btop(eva);
-
- for (; sindex < eindex; sindex = pdnxt) {
-
+ for (; sva < eva; sva = pdnxt) {
unsigned pdirindex;
- pdnxt = ((sindex + NPTEPG) & ~(NPTEPG - 1));
+ pdnxt = (sva + NBPDR) & ~PDRMASK;
- pdirindex = sindex / NPDEPG;
+ pdirindex = sva >> PDRSHIFT;
ptpaddr = pmap->pm_pdir[pdirindex];
- if ((ptpaddr & PG_PS) != 0) {
- pmap->pm_pdir[pdirindex] &= ~(PG_M|PG_RW);
- pmap->pm_stats.resident_count -= NBPDR / PAGE_SIZE;
- anychanged++;
- continue;
- }
/*
* Weed out invalid mappings. Note: we assume that the page
@@ -1989,17 +1916,27 @@ pmap_protect(pmap_t pmap, vm_offset_t sva, vm_offset_t eva, vm_prot_t prot)
if (ptpaddr == 0)
continue;
- if (pdnxt > eindex) {
- pdnxt = eindex;
+ /*
+ * Check for large page.
+ */
+ if ((ptpaddr & PG_PS) != 0) {
+ pmap->pm_pdir[pdirindex] &= ~(PG_M|PG_RW);
+ pmap->pm_stats.resident_count -= NBPDR / PAGE_SIZE;
+ anychanged = 1;
+ continue;
}
- for (; sindex != pdnxt; sindex++) {
+ if (pdnxt > eva)
+ pdnxt = eva;
+ for (; sva != pdnxt; sva += PAGE_SIZE) {
pt_entry_t pbits;
+ pt_entry_t *pte;
vm_page_t m;
- pbits = ptbase[sindex];
-
+ if ((pte = pmap_pte_quick(pmap, sva)) == NULL)
+ continue;
+ pbits = *pte;
if (pbits & PG_MANAGED) {
m = NULL;
if (pbits & PG_A) {
@@ -2007,20 +1944,19 @@ pmap_protect(pmap_t pmap, vm_offset_t sva, vm_offset_t eva, vm_prot_t prot)
vm_page_flag_set(m, PG_REFERENCED);
pbits &= ~PG_A;
}
- if (pbits & PG_M) {
- if (pmap_track_modified(i386_ptob(sindex))) {
- if (m == NULL)
- m = PHYS_TO_VM_PAGE(pbits);
- vm_page_dirty(m);
- pbits &= ~PG_M;
- }
+ if ((pbits & PG_M) != 0 &&
+ pmap_track_modified(sva)) {
+ if (m == NULL)
+ m = PHYS_TO_VM_PAGE(pbits);
+ vm_page_dirty(m);
+ pbits &= ~PG_M;
}
}
pbits &= ~PG_RW;
- if (pbits != ptbase[sindex]) {
- ptbase[sindex] = pbits;
+ if (pbits != *pte) {
+ *pte = pbits;
anychanged = 1;
}
}
@@ -2081,7 +2017,7 @@ pmap_enter(pmap_t pmap, vm_offset_t va, vm_page_t m, vm_prot_t prot,
}
#endif
- pte = pmap_pte(pmap, va);
+ pte = pmap_pte_quick(pmap, va);
/*
* Page Directory table entry not valid, we need a new PT page
@@ -2576,7 +2512,7 @@ pmap_change_wiring(pmap, va, wired)
if (pmap == NULL)
return;
- pte = pmap_pte(pmap, va);
+ pte = pmap_pte_quick(pmap, va);
if (wired && !pmap_pte_w(pte))
pmap->pm_stats.wired_count++;
@@ -2633,7 +2569,7 @@ pmap_copy(pmap_t dst_pmap, pmap_t src_pmap, vm_offset_t dst_addr, vm_size_t len,
pv_entry_count > pv_entry_high_water)
break;
- pdnxt = ((addr + PAGE_SIZE*NPTEPG) & ~(PAGE_SIZE*NPTEPG - 1));
+ pdnxt = (addr + NBPDR) & ~PDRMASK;
ptepindex = addr >> PDRSHIFT;
srcptepaddr = src_pmap->pm_pdir[ptepindex];
@@ -2643,7 +2579,8 @@ pmap_copy(pmap_t dst_pmap, pmap_t src_pmap, vm_offset_t dst_addr, vm_size_t len,
if (srcptepaddr & PG_PS) {
if (dst_pmap->pm_pdir[ptepindex] == 0) {
dst_pmap->pm_pdir[ptepindex] = srcptepaddr;
- dst_pmap->pm_stats.resident_count += NBPDR / PAGE_SIZE;
+ dst_pmap->pm_stats.resident_count +=
+ NBPDR / PAGE_SIZE;
}
continue;
}
@@ -2656,13 +2593,7 @@ pmap_copy(pmap_t dst_pmap, pmap_t src_pmap, vm_offset_t dst_addr, vm_size_t len,
if (pdnxt > end_addr)
pdnxt = end_addr;
- /*
- * Have to recheck this before every avtopte() call below
- * in case we have blocked and something else used APTDpde.
- */
- pmap_set_alternate(dst_pmap);
src_pte = vtopte(addr);
- dst_pte = avtopte(addr);
while (addr < pdnxt) {
pt_entry_t ptetemp;
ptetemp = *src_pte;
@@ -2676,6 +2607,7 @@ pmap_copy(pmap_t dst_pmap, pmap_t src_pmap, vm_offset_t dst_addr, vm_size_t len,
* block.
*/
dstmpte = pmap_allocpte(dst_pmap, addr);
+ dst_pte = pmap_pte_quick(dst_pmap, addr);
if ((*dst_pte == 0) && (ptetemp = *src_pte)) {
/*
* Clear the modified and
@@ -2697,7 +2629,6 @@ pmap_copy(pmap_t dst_pmap, pmap_t src_pmap, vm_offset_t dst_addr, vm_size_t len,
}
addr += PAGE_SIZE;
src_pte++;
- dst_pte++;
}
}
}
@@ -3288,7 +3219,7 @@ pmap_mincore(pmap, addr)
vm_page_t m;
int val = 0;
- ptep = pmap_pte(pmap, addr);
+ ptep = pmap_pte_quick(pmap, addr);
if (ptep == 0) {
return 0;
}
diff --git a/sys/i386/include/pmap.h b/sys/i386/include/pmap.h
index 8688b4627131..ad590ed879b0 100644
--- a/sys/i386/include/pmap.h
+++ b/sys/i386/include/pmap.h
@@ -252,7 +252,7 @@ void pmap_kenter(vm_offset_t va, vm_paddr_t pa);
void pmap_kremove(vm_offset_t);
void *pmap_mapdev(vm_paddr_t, vm_size_t);
void pmap_unmapdev(vm_offset_t, vm_size_t);
-pt_entry_t *pmap_pte(pmap_t, vm_offset_t) __pure2;
+pt_entry_t *pmap_pte_quick(pmap_t, vm_offset_t) __pure2;
void pmap_set_opt(void);
void pmap_invalidate_page(pmap_t, vm_offset_t);
void pmap_invalidate_range(pmap_t, vm_offset_t, vm_offset_t);