summaryrefslogtreecommitdiffstats
path: root/sys/i386
diff options
context:
space:
mode:
authoralc <alc@FreeBSD.org>2005-09-04 19:06:27 +0000
committeralc <alc@FreeBSD.org>2005-09-04 19:06:27 +0000
commit9a159e7bd9578d2bf32cffd83221962b966d1857 (patch)
treeee4bb90320bb3a21efcb8bb76617dedf50046837 /sys/i386
parentea45d0596e491d812d39e558dacfc53c6833b585 (diff)
downloadFreeBSD-src-9a159e7bd9578d2bf32cffd83221962b966d1857.zip
FreeBSD-src-9a159e7bd9578d2bf32cffd83221962b966d1857.tar.gz
Eliminate unnecessary TLB invalidations by pmap_enter(). Specifically,
eliminate TLB invalidations when permissions are relaxed, such as when a read-only mapping is changed to a read/write mapping. Additionally, eliminate TLB invalidations when bits that are ignored by the hardware, such as PG_W ("wired mapping"), are changed. Reviewed by: tegge
Diffstat (limited to 'sys/i386')
-rw-r--r--sys/i386/i386/pmap.c39
1 files changed, 23 insertions, 16 deletions
diff --git a/sys/i386/i386/pmap.c b/sys/i386/i386/pmap.c
index 13d0923..f712f83 100644
--- a/sys/i386/i386/pmap.c
+++ b/sys/i386/i386/pmap.c
@@ -5,6 +5,8 @@
* All rights reserved.
* Copyright (c) 1994 David Greenman
* All rights reserved.
+ * Copyright (c) 2005 Alan L. Cox <alc@cs.rice.edu>
+ * All rights reserved.
*
* This code is derived from software contributed to Berkeley by
* the Systems Programming Group of the University of Utah Computer
@@ -1853,6 +1855,7 @@ pmap_enter(pmap_t pmap, vm_offset_t va, vm_page_t m, vm_prot_t prot,
vm_paddr_t opa;
pt_entry_t origpte, newpte;
vm_page_t mpte, om;
+ boolean_t invlva;
va &= PG_FRAME;
#ifdef PMAP_DIAGNOSTIC
@@ -1926,14 +1929,6 @@ pmap_enter(pmap_t pmap, vm_offset_t va, vm_page_t m, vm_prot_t prot,
else if (!wired && (origpte & PG_W))
pmap->pm_stats.wired_count--;
-#if defined(PMAP_DIAGNOSTIC)
- if (pmap_nw_modified((pt_entry_t) origpte)) {
- printf(
- "pmap_enter: modified page not writable: va: 0x%x, pte: 0x%x\n",
- va, origpte);
- }
-#endif
-
/*
* Remove extra pte reference
*/
@@ -2003,17 +1998,29 @@ validate:
* to update the pte.
*/
if ((origpte & ~(PG_M|PG_A)) != newpte) {
- if (origpte & PG_MANAGED) {
+ if (origpte & PG_V) {
+ invlva = FALSE;
origpte = pte_load_store(pte, newpte | PG_A);
- if ((origpte & PG_M) && pmap_track_modified(va))
- vm_page_dirty(om);
- if (origpte & PG_A)
- vm_page_flag_set(om, PG_REFERENCED);
+ if (origpte & PG_A) {
+ if (origpte & PG_MANAGED)
+ vm_page_flag_set(om, PG_REFERENCED);
+ if (opa != VM_PAGE_TO_PHYS(m))
+ invlva = TRUE;
+ }
+ if (origpte & PG_M) {
+ KASSERT((origpte & PG_RW),
+ ("pmap_enter: modified page not writable:"
+ " va: 0x%x, pte: 0x%x", va, origpte));
+ if ((origpte & PG_MANAGED) &&
+ pmap_track_modified(va))
+ vm_page_dirty(om);
+ if ((prot & VM_PROT_WRITE) == 0)
+ invlva = TRUE;
+ }
+ if (invlva)
+ pmap_invalidate_page(pmap, va);
} else
pte_store(pte, newpte | PG_A);
- if (origpte) {
- pmap_invalidate_page(pmap, va);
- }
}
sched_unpin();
vm_page_unlock_queues();
OpenPOWER on IntegriCloud