summaryrefslogtreecommitdiffstats
path: root/sys/amd64
diff options
context:
space:
mode:
authoralc <alc@FreeBSD.org>2004-06-23 04:37:14 +0000
committeralc <alc@FreeBSD.org>2004-06-23 04:37:14 +0000
commita7339dd630908d8b36aa1327f9cfe91bbb08e166 (patch)
tree3742d51cf242ef418dfad9c40e00446a2d7bb21a /sys/amd64
parent02f435b86f33f736587cc5061f5997c04ac4e923 (diff)
downloadFreeBSD-src-a7339dd630908d8b36aa1327f9cfe91bbb08e166.zip
FreeBSD-src-a7339dd630908d8b36aa1327f9cfe91bbb08e166.tar.gz
Implement the protection check required by the pmap_extract_and_hold()
specification. This enables the elimination of Giant from that function.
Diffstat (limited to 'sys/amd64')
-rw-r--r--sys/amd64/amd64/pmap.c32
1 files changed, 24 insertions, 8 deletions
diff --git a/sys/amd64/amd64/pmap.c b/sys/amd64/amd64/pmap.c
index 81b2669..4ab9630 100644
--- a/sys/amd64/amd64/pmap.c
+++ b/sys/amd64/amd64/pmap.c
@@ -801,18 +801,34 @@ pmap_extract(pmap, va)
vm_page_t
pmap_extract_and_hold(pmap_t pmap, vm_offset_t va, vm_prot_t prot)
{
- vm_paddr_t pa;
+ pd_entry_t pde, *pdep;
+ pt_entry_t pte;
vm_page_t m;
m = NULL;
- mtx_lock(&Giant);
- if ((pa = pmap_extract(pmap, va)) != 0) {
- m = PHYS_TO_VM_PAGE(pa);
- vm_page_lock_queues();
- vm_page_hold(m);
- vm_page_unlock_queues();
+ if (pmap == NULL)
+ return (m);
+ vm_page_lock_queues();
+ PMAP_LOCK(pmap);
+ pdep = pmap_pde(pmap, va);
+ if (pdep != NULL && (pde = *pdep)) {
+ if (pde & PG_PS) {
+ if ((pde & PG_RW) || (prot & VM_PROT_WRITE) == 0) {
+ m = PHYS_TO_VM_PAGE((pde & ~PDRMASK) |
+ (va & PDRMASK));
+ vm_page_hold(m);
+ }
+ } else {
+ pte = *pmap_pte(pmap, va);
+ if ((pte & PG_V) &&
+ ((pte & PG_RW) || (prot & VM_PROT_WRITE) == 0)) {
+ m = PHYS_TO_VM_PAGE(pte & PG_FRAME);
+ vm_page_hold(m);
+ }
+ }
}
- mtx_unlock(&Giant);
+ vm_page_unlock_queues();
+ PMAP_UNLOCK(pmap);
return (m);
}
OpenPOWER on IntegriCloud