struct vm_map *map; vaddr_t start, end; struct vm_map_entry **entry_list;
vm_map_t map; vaddr_t start,end; vm_map_entry_t *entry_list;
uvm_unmap_remove(map, start, end, entry_list)	struct vm_map *map;	vaddr_t start, end;	struct vm_map_entry **entry_list;	/* OUT */{	struct vm_map_entry *entry, *first_entry, *next;	vaddr_t len;	UVMHIST_FUNC("uvm_unmap_remove"); UVMHIST_CALLED(maphist);	UVMHIST_LOG(maphist,"(map=0x%x, start=0x%x, end=0x%x)",	    map, start, end, 0);	VM_MAP_RANGE_CHECK(map, start, end);	/*	 * find first entry	 */	if (uvm_map_lookup_entry(map, start, &first_entry) == TRUE) {		/* clip and go... */		entry = first_entry;		UVM_MAP_CLIP_START(map, entry, start);		/* critical!  prevents stale hint */		SAVE_HINT(map, entry, entry->prev);	} else {		entry = first_entry->next;	}	/*	 * Save the free space hint	 */	if (map->first_free->start >= start)		map->first_free = entry->prev;	/*	 * note: we now re-use first_entry for a different task.  we remove	 * a number of map entries from the map and save them in a linked	 * list headed by "first_entry".  once we remove them from the map	 * the caller should unlock the map and drop the references to the	 * backing objects [c.f. uvm_unmap_detach].  the object is to	 * separate unmapping from reference dropping.  why?	 *   [1] the map has to be locked for unmapping	 *   [2] the map need not be locked for reference dropping	 *   [3] dropping references may trigger pager I/O, and if we hit	 *       a pager that does synchronous I/O we may have to wait for it.	 *   [4] we would like all waiting for I/O to occur with maps unlocked	 *       so that we don't block other threads.	 */	first_entry = NULL;	*entry_list = NULL;		/* to be safe */	/*	 * break up the area into map entry sized regions and unmap.  note	 * that all mappings have to be removed before we can even consider	 * dropping references to amaps or VM objects (otherwise we could end	 * up with a mapping to a page on the free list which would be very bad)	 */	while ((entry != &map->header) && (entry->start < end)) {		UVM_MAP_CLIP_END(map, entry, end);		next = entry->next;		len = entry->end - entry->start;		/*		 * unwire before removing addresses from the pmap; otherwise		 * unwiring will put the entries back into the pmap (XXX).		 */		if (VM_MAPENT_ISWIRED(entry))			uvm_map_entry_unwire(map, entry);		/*		 * special case: handle mappings to anonymous kernel objects.		 * we want to free these pages right away...		 */		if (UVM_ET_ISOBJ(entry) &&		    UVM_OBJ_IS_KERN_OBJECT(entry->object.uvm_obj)) {			KASSERT(vm_map_pmap(map) == pmap_kernel());			/*			 * note: kernel object mappings are currently used in			 * two ways:			 *  [1] "normal" mappings of pages in the kernel object			 *  [2] uvm_km_valloc'd allocations in which we			 *      pmap_enter in some non-kernel-object page			 *      (e.g. vmapbuf).			 *			 * for case [1], we need to remove the mapping from			 * the pmap and then remove the page from the kernel			 * object (because, once pages in a kernel object are			 * unmapped they are no longer needed, unlike, say,			 * a vnode where you might want the data to persist			 * until flushed out of a queue).			 *			 * for case [2], we need to remove the mapping from			 * the pmap.  there shouldn't be any pages at the			 * specified offset in the kernel object [but it			 * doesn't hurt to call uvm_km_pgremove just to be			 * safe?]			 *			 * uvm_km_pgremove currently does the following:			 *   for pages in the kernel object in range:			 *     - drops the swap slot			 *     - uvm_pagefree the page			 *			 * note there is version of uvm_km_pgremove() that			 * is used for "intrsafe" objects.			 */			/*			 * remove mappings from pmap and drop the pages			 * from the object.  offsets are always relative			 * to vm_map_min(kernel_map).			 */			if (UVM_OBJ_IS_INTRSAFE_OBJECT(entry->object.uvm_obj)) {				pmap_kremove(entry->start, len);				uvm_km_pgremove_intrsafe(entry->object.uvm_obj,				    entry->start - vm_map_min(kernel_map),				    entry->end - vm_map_min(kernel_map));			} else {				pmap_remove(pmap_kernel(), entry->start,				    entry->start + len);				uvm_km_pgremove(entry->object.uvm_obj,				    entry->start - vm_map_min(kernel_map),				    entry->end - vm_map_min(kernel_map));			}			/*			 * null out kernel_object reference, we've just			 * dropped it			 */			entry->etype &= ~UVM_ET_OBJ;			entry->object.uvm_obj = NULL;	/* to be safe */		} else {			/*		 	 * remove mappings the standard way.		 	 */			pmap_remove(map->pmap, entry->start, entry->end);		}		/*		 * remove entry from map and put it on our list of entries		 * that we've nuked.  then go do next entry.		 */		UVMHIST_LOG(maphist, "  removed map entry 0x%x", entry, 0, 0,0);		/* critical! prevents stale hint */		SAVE_HINT(map, entry, entry->prev);		uvm_map_entry_unlink(map, entry);		map->size -= len;		entry->next = first_entry;		first_entry = entry;		entry = next;		/* next entry, please */	}	pmap_update(vm_map_pmap(map));	/*	 * now we've cleaned up the map and are ready for the caller to drop	 * references to the mapped objects.	 */	*entry_list = first_entry;	UVMHIST_LOG(maphist,"<- done!", 0, 0, 0, 0);}