diff --git a/sys/vm/vm.h b/sys/vm/vm.h index 3ea45bb..1b0af83 100644 --- a/sys/vm/vm.h +++ b/sys/vm/vm.h @@ -85,6 +85,7 @@ typedef u_char vm_prot_t; /* protection codes */ #define VM_PROT_EXECUTE ((vm_prot_t) 0x04) #define VM_PROT_OVERRIDE_WRITE ((vm_prot_t) 0x08) /* copy-on-write */ #define VM_PROT_NOSYNC ((vm_prot_t) 0x10) +#define VM_PROT_PMAP_CONTEXT ((vm_prot_t) 0x20) /* caller handles mmu */ #define VM_PROT_RW (VM_PROT_READ|VM_PROT_WRITE) #define VM_PROT_ALL (VM_PROT_READ|VM_PROT_WRITE|VM_PROT_EXECUTE) diff --git a/sys/vm/vm_fault.c b/sys/vm/vm_fault.c index 86d0807..56a5895 100644 --- a/sys/vm/vm_fault.c +++ b/sys/vm/vm_fault.c @@ -492,9 +492,16 @@ RetryFault: * page can be safely written. However, it will force a read-only * mapping for a read fault if the memory is managed by a virtual * page table. + * + * We pass VM_PROT_PMAP_CONTEXT to indicate to vm_fault_object() + * that we will handle the pmap op. If we do not pass this flag + * then any COW operation to remove the page from *ALL* pmaps + * (i.e. umtx*() calls do not necessarily modify pages via pmaps + * so if umtx*() COW's it doesn't know which pmap to adjust). */ /* BEFORE */ - result = vm_fault_object(&fs, first_pindex, fault_type); + result = vm_fault_object(&fs, first_pindex, fault_type | + VM_PROT_PMAP_CONTEXT); if (result == KERN_TRY_AGAIN) { vm_object_drop(fs.first_object); @@ -1657,7 +1664,8 @@ skip: * Just remove it from all pmaps. */ vm_page_copy(fs->m, fs->first_m); - vm_page_protect(fs->m, VM_PROT_NONE); + if ((fault_type & VM_PROT_PMAP_CONTEXT) == 0) + vm_page_protect(fs->m, VM_PROT_NONE); vm_page_event(fs->m, VMEVENT_COW); } @@ -1704,6 +1712,9 @@ skip: } } + KASSERT((fs->m == NULL || (fs->m->flags & PG_BUSY)), + ("vm_fault: page %p not busy.1!", fs->m)); + /* * Relock the map if necessary, then check the generation count. * relock_map() will update fs->timestamp to account for the @@ -1729,6 +1740,9 @@ skip: } } + KASSERT((fs->m == NULL || (fs->m->flags & PG_BUSY)), + ("vm_fault: page %p not busy.2!", fs->m)); + /* * If the fault is a write, we know that this page is being * written NOW so dirty it explicitly to save on pmap_is_modified() @@ -1754,6 +1768,9 @@ skip: } } + KASSERT((fs->m == NULL || (fs->m->flags & PG_BUSY)), + ("vm_fault: page %p not busy.3!", fs->m)); + vm_object_pip_wakeup(fs->first_object); vm_object_chain_release_all(fs->first_object, fs->object); if (fs->object != fs->first_object) @@ -1764,8 +1781,8 @@ skip: * fs->object will have another PIP reference if it is not equal * to fs->first_object. */ - KASSERT(fs->m->flags & PG_BUSY, - ("vm_fault: page %p not busy!", fs->m)); + KASSERT((fs->m == NULL || (fs->m->flags & PG_BUSY)), + ("vm_fault: page %p not busy.4!", fs->m)); /* * Sanity check: page must be completely valid or it is not fit to