summaryrefslogtreecommitdiffstats
path: root/sys
diff options
context:
space:
mode:
authoralc <alc@FreeBSD.org>2004-06-22 19:35:43 +0000
committeralc <alc@FreeBSD.org>2004-06-22 19:35:43 +0000
commitdd32b92c2514b98b8c9d9af7ac82532d833c6db2 (patch)
tree88224e32119295fa6baac886fcf4eb2b43d69152 /sys
parent5301d01cbad25fe6d254719c611d291061d4c50c (diff)
downloadFreeBSD-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.c32
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);
}
OpenPOWER on IntegriCloud