diff options
author | alc <alc@FreeBSD.org> | 2004-06-22 19:35:43 +0000 |
---|---|---|
committer | alc <alc@FreeBSD.org> | 2004-06-22 19:35:43 +0000 |
commit | dd32b92c2514b98b8c9d9af7ac82532d833c6db2 (patch) | |
tree | 88224e32119295fa6baac886fcf4eb2b43d69152 /sys | |
parent | 5301d01cbad25fe6d254719c611d291061d4c50c (diff) | |
download | FreeBSD-src-dd32b92c2514b98b8c9d9af7ac82532d833c6db2.zip FreeBSD-src-dd32b92c2514b98b8c9d9af7ac82532d833c6db2.tar.gz |
Implement the protection check required by the pmap_extract_and_hold()
specification. This enables the elimination of Giant from that function.
Reviewed by: tegge@
Diffstat (limited to 'sys')
-rw-r--r-- | sys/i386/i386/pmap.c | 32 |
1 files changed, 24 insertions, 8 deletions
diff --git a/sys/i386/i386/pmap.c b/sys/i386/i386/pmap.c index 97cd380..756f5dd6 100644 --- a/sys/i386/i386/pmap.c +++ b/sys/i386/i386/pmap.c @@ -860,18 +860,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; + 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); + pde = *pmap_pde(pmap, va); + if (pde != 0) { + 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_quick(pmap, va); + if (pte != 0 && + ((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); } |