struct vm_map *map;
vm_map_t map;
uvm_mmap(map, addr, size, prot, maxprot, flags, handle, foff, locklimit)	struct vm_map *map;	vaddr_t *addr;	vsize_t size;	vm_prot_t prot, maxprot;	int flags;	void *handle;	voff_t foff;	vsize_t locklimit;{	struct uvm_object *uobj;	struct vnode *vp;	int error;	int advice = UVM_ADV_NORMAL;	uvm_flag_t uvmflag = 0;	/*	 * check params	 */	if (size == 0)		return(0);	if (foff & PAGE_MASK)		return(EINVAL);	if ((prot & maxprot) != prot)		return(EINVAL);	/*	 * for non-fixed mappings, round off the suggested address.	 * for fixed mappings, check alignment and zap old mappings.	 */	if ((flags & MAP_FIXED) == 0) {		*addr = round_page(*addr);	/* round */	} else {		if (*addr & PAGE_MASK)			return(EINVAL);		uvmflag |= UVM_FLAG_FIXED;		(void) uvm_unmap(map, *addr, *addr + size);	/* zap! */	}	/*	 * handle anon vs. non-anon mappings.   for non-anon mappings attach	 * to underlying vm object.	 */	if (flags & MAP_ANON) {		foff = UVM_UNKNOWN_OFFSET;		uobj = NULL;		if ((flags & MAP_SHARED) == 0)			/* XXX: defer amap create */			uvmflag |= UVM_FLAG_COPYONW;		else			/* shared: create amap now */			uvmflag |= UVM_FLAG_OVERLAY;	} else {		vp = (struct vnode *)handle;		if (vp->v_type != VCHR) {			error = VOP_MMAP(vp, 0, curproc->p_ucred, curproc);			if (error) {				return error;			}			uobj = uvn_attach((void *)vp, (flags & MAP_SHARED) ?			   maxprot : (maxprot & ~VM_PROT_WRITE));			/* XXX for now, attach doesn't gain a ref */			VREF(vp);		} else {			uobj = udv_attach((void *) &vp->v_rdev,			    (flags & MAP_SHARED) ? maxprot :			    (maxprot & ~VM_PROT_WRITE), foff, size);			/*			 * XXX Some devices don't like to be mapped with			 * XXX PROT_EXEC, but we don't really have a			 * XXX better way of handling this, right now			 */			if (uobj == NULL && (prot & PROT_EXEC) == 0) {				maxprot &= ~VM_PROT_EXECUTE;				uobj = udv_attach((void *)&vp->v_rdev,				    (flags & MAP_SHARED) ? maxprot :				    (maxprot & ~VM_PROT_WRITE), foff, size);			}			advice = UVM_ADV_RANDOM;		}		if (uobj == NULL)			return((vp->v_type == VREG) ? ENOMEM : EINVAL);		if ((flags & MAP_SHARED) == 0)			uvmflag |= UVM_FLAG_COPYONW;	}	uvmflag = UVM_MAPFLAG(prot, maxprot,			(flags & MAP_SHARED) ? UVM_INH_SHARE : UVM_INH_COPY,			advice, uvmflag);	error = uvm_map(map, addr, size, uobj, foff, 0, uvmflag);	if (error) {		if (uobj)			uobj->pgops->pgo_detach(uobj);		return error;	}	/*	 * POSIX 1003.1b -- if our address space was configured	 * to lock all future mappings, wire the one we just made.	 */	if (prot == VM_PROT_NONE) {		/*		 * No more work to do in this case.		 */		return (0);	}	vm_map_lock(map);	if (map->flags & VM_MAP_WIREFUTURE) {		if ((atop(size) + uvmexp.wired) > uvmexp.wiredmax#ifdef pmap_wired_count		    || (locklimit != 0 && (size +		    ptoa(pmap_wired_count(vm_map_pmap(map)))) >			locklimit)#endif		) {			vm_map_unlock(map);			uvm_unmap(map, *addr, *addr + size);			return ENOMEM;		}		/*		 * uvm_map_pageable() always returns the map unlocked.		 */		error = uvm_map_pageable(map, *addr, *addr + size,					 FALSE, UVM_LK_ENTER);		if (error) {			uvm_unmap(map, *addr, *addr + size);			return error;		}		return (0);	}	vm_map_unlock(map);	return 0;}