summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authoralc <alc@FreeBSD.org>2010-04-25 20:40:45 +0000
committeralc <alc@FreeBSD.org>2010-04-25 20:40:45 +0000
commit019a1d16bacaa7783b857c309ce61d655e899904 (patch)
treeec9ad7b26fa81cd6cf0b255dbb08eeabdf74fed4
parent8156e27dd79d633bbb41f44cf030e93cdcd15889 (diff)
downloadFreeBSD-src-019a1d16bacaa7783b857c309ce61d655e899904.zip
FreeBSD-src-019a1d16bacaa7783b857c309ce61d655e899904.tar.gz
Clearing a page table entry's accessed bit (PG_A) and setting the
page's PG_REFERENCED flag in pmap_protect() can't really be justified. In contrast to pmap_remove() or pmap_remove_all(), the mapping is not being destroyed, so the notion that the page was accessed is not lost. Moreover, clearing the page table entry's accessed bit and setting the page's PG_REFERENCED flag can throw off the page daemon's activity count calculation. Finally, in my tests, I found that 15% of the atomic memory operations being performed by pmap_protect() were only to clear PG_A, and not change protection. This could, by itself, be fixed, but I don't see the point given the above argument. Remove a comment from pmap_protect_pde() that is no longer meaningful after the above change.
-rw-r--r--sys/amd64/amd64/pmap.c29
-rw-r--r--sys/i386/i386/pmap.c28
2 files changed, 12 insertions, 45 deletions
diff --git a/sys/amd64/amd64/pmap.c b/sys/amd64/amd64/pmap.c
index 9c7d8b0..6cd10b4 100644
--- a/sys/amd64/amd64/pmap.c
+++ b/sys/amd64/amd64/pmap.c
@@ -2833,18 +2833,9 @@ retry:
if (oldpde & PG_MANAGED) {
eva = sva + NBPDR;
for (va = sva, m = PHYS_TO_VM_PAGE(oldpde & PG_PS_FRAME);
- va < eva; va += PAGE_SIZE, m++) {
- /*
- * In contrast to the analogous operation on a 4KB page
- * mapping, the mapping's PG_A flag is not cleared and
- * the page's PG_REFERENCED flag is not set. The
- * reason is that pmap_demote_pde() expects that a 2MB
- * page mapping with a stored page table page has PG_A
- * set.
- */
+ va < eva; va += PAGE_SIZE, m++)
if ((oldpde & (PG_M | PG_RW)) == (PG_M | PG_RW))
vm_page_dirty(m);
- }
}
if ((prot & VM_PROT_WRITE) == 0)
newpde &= ~(PG_RW | PG_M);
@@ -2953,23 +2944,15 @@ retry:
obits = pbits = *pte;
if ((pbits & PG_V) == 0)
continue;
- if (pbits & PG_MANAGED) {
- m = NULL;
- if (pbits & PG_A) {
+
+ if ((prot & VM_PROT_WRITE) == 0) {
+ if ((pbits & (PG_MANAGED | PG_M | PG_RW)) ==
+ (PG_MANAGED | PG_M | PG_RW)) {
m = PHYS_TO_VM_PAGE(pbits & PG_FRAME);
- vm_page_flag_set(m, PG_REFERENCED);
- pbits &= ~PG_A;
- }
- if ((pbits & (PG_M | PG_RW)) == (PG_M | PG_RW)) {
- if (m == NULL)
- m = PHYS_TO_VM_PAGE(pbits &
- PG_FRAME);
vm_page_dirty(m);
}
- }
-
- if ((prot & VM_PROT_WRITE) == 0)
pbits &= ~(PG_RW | PG_M);
+ }
if ((prot & VM_PROT_EXECUTE) == 0)
pbits |= pg_nx;
diff --git a/sys/i386/i386/pmap.c b/sys/i386/i386/pmap.c
index 1ce6454..d8b9686 100644
--- a/sys/i386/i386/pmap.c
+++ b/sys/i386/i386/pmap.c
@@ -2955,18 +2955,9 @@ retry:
if (oldpde & PG_MANAGED) {
eva = sva + NBPDR;
for (va = sva, m = PHYS_TO_VM_PAGE(oldpde & PG_PS_FRAME);
- va < eva; va += PAGE_SIZE, m++) {
- /*
- * In contrast to the analogous operation on a 4KB page
- * mapping, the mapping's PG_A flag is not cleared and
- * the page's PG_REFERENCED flag is not set. The
- * reason is that pmap_demote_pde() expects that a 2/4MB
- * page mapping with a stored page table page has PG_A
- * set.
- */
+ va < eva; va += PAGE_SIZE, m++)
if ((oldpde & (PG_M | PG_RW)) == (PG_M | PG_RW))
vm_page_dirty(m);
- }
}
if ((prot & VM_PROT_WRITE) == 0)
newpde &= ~(PG_RW | PG_M);
@@ -3074,22 +3065,15 @@ retry:
obits = pbits = *pte;
if ((pbits & PG_V) == 0)
continue;
- if (pbits & PG_MANAGED) {
- m = NULL;
- if (pbits & PG_A) {
+
+ if ((prot & VM_PROT_WRITE) == 0) {
+ if ((pbits & (PG_MANAGED | PG_M | PG_RW)) ==
+ (PG_MANAGED | PG_M | PG_RW)) {
m = PHYS_TO_VM_PAGE(pbits & PG_FRAME);
- vm_page_flag_set(m, PG_REFERENCED);
- pbits &= ~PG_A;
- }
- if ((pbits & (PG_M | PG_RW)) == (PG_M | PG_RW)) {
- if (m == NULL)
- m = PHYS_TO_VM_PAGE(pbits & PG_FRAME);
vm_page_dirty(m);
}
- }
-
- if ((prot & VM_PROT_WRITE) == 0)
pbits &= ~(PG_RW | PG_M);
+ }
#ifdef PAE
if ((prot & VM_PROT_EXECUTE) == 0)
pbits |= pg_nx;
OpenPOWER on IntegriCloud