pmap_update(srcmap->pmap);
uvm_map_extract(srcmap, start, len, dstmap, dstaddrp, flags)	struct vm_map *srcmap, *dstmap;	vaddr_t start, *dstaddrp;	vsize_t len;	int flags;{	vaddr_t dstaddr, end, newend, oldoffset, fudge, orig_fudge,	    oldstart;	struct vm_map_entry *chain, *endchain, *entry, *orig_entry, *newentry,	    *deadentry, *oldentry;	vsize_t elen;	int nchain, error, copy_ok;	UVMHIST_FUNC("uvm_map_extract"); UVMHIST_CALLED(maphist);	UVMHIST_LOG(maphist,"(srcmap=0x%x,start=0x%x, len=0x%x", srcmap, start,	    len,0);	UVMHIST_LOG(maphist," ...,dstmap=0x%x, flags=0x%x)", dstmap,flags,0,0);	/*	 * step 0: sanity check: start must be on a page boundary, length	 * must be page sized.  can't ask for CONTIG/QREF if you asked for	 * REMOVE.	 */	KASSERT((start & PAGE_MASK) == 0 && (len & PAGE_MASK) == 0);	KASSERT((flags & UVM_EXTRACT_REMOVE) == 0 ||		(flags & (UVM_EXTRACT_CONTIG|UVM_EXTRACT_QREF)) == 0);	/*	 * step 1: reserve space in the target map for the extracted area	 */	dstaddr = vm_map_min(dstmap);	if (uvm_map_reserve(dstmap, len, start, 0, &dstaddr) == FALSE)		return(ENOMEM);	*dstaddrp = dstaddr;	/* pass address back to caller */	UVMHIST_LOG(maphist, "  dstaddr=0x%x", dstaddr,0,0,0);	/*	 * step 2: setup for the extraction process loop by init'ing the	 * map entry chain, locking src map, and looking up the first useful	 * entry in the map.	 */	end = start + len;	newend = dstaddr + len;	chain = endchain = NULL;	nchain = 0;	vm_map_lock(srcmap);	if (uvm_map_lookup_entry(srcmap, start, &entry)) {		/* "start" is within an entry */		if (flags & UVM_EXTRACT_QREF) {			/*			 * for quick references we don't clip the entry, so			 * the entry may map space "before" the starting			 * virtual address... this is the "fudge" factor			 * (which can be non-zero only the first time			 * through the "while" loop in step 3).			 */			fudge = start - entry->start;		} else {			/*			 * normal reference: we clip the map to fit (thus			 * fudge is zero)			 */			UVM_MAP_CLIP_START(srcmap, entry, start);			SAVE_HINT(srcmap, srcmap->hint, entry->prev);			fudge = 0;		}	} else {		/* "start" is not within an entry ... skip to next entry */		if (flags & UVM_EXTRACT_CONTIG) {			error = EINVAL;			goto bad;    /* definite hole here ... */		}		entry = entry->next;		fudge = 0;	}	/* save values from srcmap for step 6 */	orig_entry = entry;	orig_fudge = fudge;	/*	 * step 3: now start looping through the map entries, extracting	 * as we go.	 */	while (entry->start < end && entry != &srcmap->header) {		/* if we are not doing a quick reference, clip it */		if ((flags & UVM_EXTRACT_QREF) == 0)			UVM_MAP_CLIP_END(srcmap, entry, end);		/* clear needs_copy (allow chunking) */		if (UVM_ET_ISNEEDSCOPY(entry)) {			if (fudge)				oldstart = entry->start;			else				oldstart = 0;	/* XXX: gcc */			amap_copy(srcmap, entry, M_NOWAIT, TRUE, start, end);			if (UVM_ET_ISNEEDSCOPY(entry)) {  /* failed? */				error = ENOMEM;				goto bad;			}			/* amap_copy could clip (during chunk)!  update fudge */			if (fudge) {				fudge = fudge - (entry->start - oldstart);				orig_fudge = fudge;			}		}		/* calculate the offset of this from "start" */		oldoffset = (entry->start + fudge) - start;		/* allocate a new map entry */		newentry = uvm_mapent_alloc(dstmap);		if (newentry == NULL) {			error = ENOMEM;			goto bad;		}		/* set up new map entry */		newentry->next = NULL;		newentry->prev = endchain;		newentry->start = dstaddr + oldoffset;		newentry->end =		    newentry->start + (entry->end - (entry->start + fudge));		if (newentry->end > newend || newentry->end < newentry->start)			newentry->end = newend;		newentry->object.uvm_obj = entry->object.uvm_obj;		if (newentry->object.uvm_obj) {			if (newentry->object.uvm_obj->pgops->pgo_reference)				newentry->object.uvm_obj->pgops->				    pgo_reference(newentry->object.uvm_obj);				newentry->offset = entry->offset + fudge;		} else {			newentry->offset = 0;		}		newentry->etype = entry->etype;		newentry->protection = (flags & UVM_EXTRACT_FIXPROT) ?			entry->max_protection : entry->protection;		newentry->max_protection = entry->max_protection;		newentry->inheritance = entry->inheritance;		newentry->wired_count = 0;		newentry->aref.ar_amap = entry->aref.ar_amap;		if (newentry->aref.ar_amap) {			newentry->aref.ar_pageoff =			    entry->aref.ar_pageoff + (fudge >> PAGE_SHIFT);			uvm_map_reference_amap(newentry, AMAP_SHARED |			    ((flags & UVM_EXTRACT_QREF) ? AMAP_REFALL : 0));		} else {			newentry->aref.ar_pageoff = 0;		}		newentry->advice = entry->advice;		/* now link it on the chain */		nchain++;		if (endchain == NULL) {			chain = endchain = newentry;		} else {			endchain->next = newentry;			endchain = newentry;		}		/* end of 'while' loop! */		if ((flags & UVM_EXTRACT_CONTIG) && entry->end < end &&		    (entry->next == &srcmap->header ||		    entry->next->start != entry->end)) {			error = EINVAL;			goto bad;		}		entry = entry->next;		fudge = 0;	}	/*	 * step 4: close off chain (in format expected by uvm_map_replace)	 */	if (chain)		chain->prev = endchain;	/*	 * step 5: attempt to lock the dest map so we can pmap_copy.	 * note usage of copy_ok:	 *   1 => dstmap locked, pmap_copy ok, and we "replace" here (step 5)	 *   0 => dstmap unlocked, NO pmap_copy, and we will "replace" in step 7	 */	if (srcmap == dstmap || vm_map_lock_try(dstmap) == TRUE) {		copy_ok = 1;		if (!uvm_map_replace(dstmap, dstaddr, dstaddr+len, chain,		    nchain)) {			if (srcmap != dstmap)				vm_map_unlock(dstmap);			error = EIO;			goto bad;		}	} else {		copy_ok = 0;		/* replace defered until step 7 */	}	/*	 * step 6: traverse the srcmap a second time to do the following:	 *  - if we got a lock on the dstmap do pmap_copy	 *  - if UVM_EXTRACT_REMOVE remove the entries	 * we make use of orig_entry and orig_fudge (saved in step 2)	 */	if (copy_ok || (flags & UVM_EXTRACT_REMOVE)) {		/* purge possible stale hints from srcmap */		if (flags & UVM_EXTRACT_REMOVE) {			SAVE_HINT(srcmap, srcmap->hint, orig_entry->prev);			if (srcmap->first_free->start >= start)				srcmap->first_free = orig_entry->prev;		}		entry = orig_entry;		fudge = orig_fudge;		deadentry = NULL;	/* for UVM_EXTRACT_REMOVE */		while (entry->start < end && entry != &srcmap->header) {			if (copy_ok) {				oldoffset = (entry->start + fudge) - start;				elen = MIN(end, entry->end) -				    (entry->start + fudge);				pmap_copy(dstmap->pmap, srcmap->pmap,				    dstaddr + oldoffset, elen,				    entry->start + fudge);			}			/* we advance "entry" in the following if statement */			if (flags & UVM_EXTRACT_REMOVE) {				pmap_remove(srcmap->pmap, entry->start,						entry->end);        			oldentry = entry;	/* save entry */        			entry = entry->next;	/* advance */				uvm_map_entry_unlink(srcmap, oldentry);							/* add to dead list */				oldentry->next = deadentry;				deadentry = oldentry;      			} else {        			entry = entry->next;		/* advance */			}			/* end of 'while' loop */			fudge = 0;		}		pmap_update(srcmap->pmap);		/*		 * unlock dstmap.  we will dispose of deadentry in		 * step 7 if needed		 */		if (copy_ok && srcmap != dstmap)			vm_map_unlock(dstmap);	} else {		deadentry = NULL;	}	/*	 * step 7: we are done with the source map, unlock.   if copy_ok	 * is 0 then we have not replaced the dummy mapping in dstmap yet	 * and we need to do so now.	 */	vm_map_unlock(srcmap);	if ((flags & UVM_EXTRACT_REMOVE) && deadentry)		uvm_unmap_detach(deadentry, 0);   /* dispose of old entries */	/* now do the replacement if we didn't do it in step 5 */	if (copy_ok == 0) {		vm_map_lock(dstmap);		error = uvm_map_replace(dstmap, dstaddr, dstaddr+len, chain,		    nchain);		vm_map_unlock(dstmap);		if (error == FALSE) {			error = EIO;			goto bad2;		}	}	return(0);	/*	 * bad: failure recovery	 */bad:	vm_map_unlock(srcmap);bad2:			/* src already unlocked */	if (chain)		uvm_unmap_detach(chain,		    (flags & UVM_EXTRACT_QREF) ? AMAP_REFALL : 0);	uvm_unmap(dstmap, dstaddr, dstaddr+len);   /* ??? */	return(error);}