xref: /freebsd/sys/vm/vm_mmap.c (revision ef5d438ed4bc17ad7ece3e40fe4d1f9baf3aadf7)
1 /*
2  * Copyright (c) 1988 University of Utah.
3  * Copyright (c) 1991, 1993
4  *	The Regents of the University of California.  All rights reserved.
5  *
6  * This code is derived from software contributed to Berkeley by
7  * the Systems Programming Group of the University of Utah Computer
8  * Science Department.
9  *
10  * Redistribution and use in source and binary forms, with or without
11  * modification, are permitted provided that the following conditions
12  * are met:
13  * 1. Redistributions of source code must retain the above copyright
14  *    notice, this list of conditions and the following disclaimer.
15  * 2. Redistributions in binary form must reproduce the above copyright
16  *    notice, this list of conditions and the following disclaimer in the
17  *    documentation and/or other materials provided with the distribution.
18  * 3. All advertising materials mentioning features or use of this software
19  *    must display the following acknowledgement:
20  *	This product includes software developed by the University of
21  *	California, Berkeley and its contributors.
22  * 4. Neither the name of the University nor the names of its contributors
23  *    may be used to endorse or promote products derived from this software
24  *    without specific prior written permission.
25  *
26  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
27  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
28  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
29  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
30  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
31  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
32  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
33  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
34  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
35  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
36  * SUCH DAMAGE.
37  *
38  * from: Utah $Hdr: vm_mmap.c 1.6 91/10/21$
39  *
40  *	@(#)vm_mmap.c	8.4 (Berkeley) 1/12/94
41  * $Id: vm_mmap.c,v 1.35 1996/01/19 03:59:59 dyson Exp $
42  */
43 
44 /*
45  * Mapped file (mmap) interface to VM
46  */
47 
48 #include <sys/param.h>
49 #include <sys/systm.h>
50 #include <sys/sysproto.h>
51 #include <sys/filedesc.h>
52 #include <sys/resourcevar.h>
53 #include <sys/proc.h>
54 #include <sys/vnode.h>
55 #include <sys/file.h>
56 #include <sys/mman.h>
57 #include <sys/conf.h>
58 #include <sys/vmmeter.h>
59 
60 #include <miscfs/specfs/specdev.h>
61 
62 #include <vm/vm.h>
63 #include <vm/vm_param.h>
64 #include <vm/vm_prot.h>
65 #include <vm/vm_inherit.h>
66 #include <vm/lock.h>
67 #include <vm/pmap.h>
68 #include <vm/vm_map.h>
69 #include <vm/vm_object.h>
70 #include <vm/vm_pager.h>
71 #include <vm/vm_pageout.h>
72 #include <vm/vm_extern.h>
73 #include <vm/vm_kern.h>
74 
75 #ifndef _SYS_SYSPROTO_H_
76 struct sbrk_args {
77 	int incr;
78 };
79 #endif
80 
81 /* ARGSUSED */
82 int
83 sbrk(p, uap, retval)
84 	struct proc *p;
85 	struct sbrk_args *uap;
86 	int *retval;
87 {
88 
89 	/* Not yet implemented */
90 	return (EOPNOTSUPP);
91 }
92 
93 #ifndef _SYS_SYSPROTO_H_
94 struct sstk_args {
95 	int incr;
96 };
97 #endif
98 
99 /* ARGSUSED */
100 int
101 sstk(p, uap, retval)
102 	struct proc *p;
103 	struct sstk_args *uap;
104 	int *retval;
105 {
106 
107 	/* Not yet implemented */
108 	return (EOPNOTSUPP);
109 }
110 
111 #if defined(COMPAT_43) || defined(COMPAT_SUNOS)
112 #ifndef _SYS_SYSPROTO_H_
113 struct getpagesize_args {
114 	int dummy;
115 };
116 #endif
117 
118 /* ARGSUSED */
119 int
120 ogetpagesize(p, uap, retval)
121 	struct proc *p;
122 	struct getpagesize_args *uap;
123 	int *retval;
124 {
125 
126 	*retval = PAGE_SIZE;
127 	return (0);
128 }
129 #endif				/* COMPAT_43 || COMPAT_SUNOS */
130 
131 #ifndef _SYS_SYSPROTO_H_
132 struct mmap_args {
133 	caddr_t addr;
134 	size_t len;
135 	int prot;
136 	int flags;
137 	int fd;
138 	long pad;
139 	off_t pos;
140 };
141 #endif
142 
143 int
144 mmap(p, uap, retval)
145 	struct proc *p;
146 	register struct mmap_args *uap;
147 	int *retval;
148 {
149 	register struct filedesc *fdp = p->p_fd;
150 	register struct file *fp;
151 	struct vnode *vp;
152 	vm_offset_t addr;
153 	vm_size_t size;
154 	vm_prot_t prot, maxprot;
155 	caddr_t handle;
156 	int flags, error;
157 
158 	prot = uap->prot & VM_PROT_ALL;
159 	flags = uap->flags;
160 	/*
161 	 * Address (if FIXED) must be page aligned. Size is implicitly rounded
162 	 * to a page boundary.
163 	 */
164 	addr = (vm_offset_t) uap->addr;
165 	if (((flags & MAP_FIXED) && (addr & PAGE_MASK)) ||
166 	    (ssize_t) uap->len < 0 || ((flags & MAP_ANON) && uap->fd != -1))
167 		return (EINVAL);
168 	size = (vm_size_t) round_page(uap->len);
169 	/*
170 	 * Check for illegal addresses.  Watch out for address wrap... Note
171 	 * that VM_*_ADDRESS are not constants due to casts (argh).
172 	 */
173 	if (flags & MAP_FIXED) {
174 		if (VM_MAXUSER_ADDRESS > 0 && addr + size > VM_MAXUSER_ADDRESS)
175 			return (EINVAL);
176 #ifndef i386
177 		if (VM_MIN_ADDRESS > 0 && addr < VM_MIN_ADDRESS)
178 			return (EINVAL);
179 #endif
180 		if (addr + size < addr)
181 			return (EINVAL);
182 	}
183 	/*
184 	 * XXX if no hint provided for a non-fixed mapping place it after the
185 	 * end of the largest possible heap.
186 	 *
187 	 * There should really be a pmap call to determine a reasonable location.
188 	 */
189 	if (addr == 0 && (flags & MAP_FIXED) == 0)
190 		addr = round_page(p->p_vmspace->vm_daddr + MAXDSIZ);
191 	if (flags & MAP_ANON) {
192 		/*
193 		 * Mapping blank space is trivial.
194 		 */
195 		handle = NULL;
196 		maxprot = VM_PROT_ALL;
197 	} else {
198 		/*
199 		 * Mapping file, get fp for validation. Obtain vnode and make
200 		 * sure it is of appropriate type.
201 		 */
202 		if (((unsigned) uap->fd) >= fdp->fd_nfiles ||
203 		    (fp = fdp->fd_ofiles[uap->fd]) == NULL)
204 			return (EBADF);
205 		if (fp->f_type != DTYPE_VNODE)
206 			return (EINVAL);
207 		vp = (struct vnode *) fp->f_data;
208 		if (vp->v_type != VREG && vp->v_type != VCHR)
209 			return (EINVAL);
210 		/*
211 		 * XXX hack to handle use of /dev/zero to map anon memory (ala
212 		 * SunOS).
213 		 */
214 		if (vp->v_type == VCHR && iszerodev(vp->v_rdev)) {
215 			handle = NULL;
216 			maxprot = VM_PROT_ALL;
217 			flags |= MAP_ANON;
218 		} else {
219 			/*
220 			 * Ensure that file and memory protections are
221 			 * compatible.  Note that we only worry about
222 			 * writability if mapping is shared; in this case,
223 			 * current and max prot are dictated by the open file.
224 			 * XXX use the vnode instead?  Problem is: what
225 			 * credentials do we use for determination? What if
226 			 * proc does a setuid?
227 			 */
228 			maxprot = VM_PROT_EXECUTE;	/* ??? */
229 			if (fp->f_flag & FREAD)
230 				maxprot |= VM_PROT_READ;
231 			else if (prot & PROT_READ)
232 				return (EACCES);
233 			if (flags & MAP_SHARED) {
234 				if (fp->f_flag & FWRITE)
235 					maxprot |= VM_PROT_WRITE;
236 				else if (prot & PROT_WRITE)
237 					return (EACCES);
238 			} else
239 				maxprot |= VM_PROT_WRITE;
240 			handle = (caddr_t) vp;
241 		}
242 	}
243 	error = vm_mmap(&p->p_vmspace->vm_map, &addr, size, prot, maxprot,
244 	    flags, handle, uap->pos);
245 	if (error == 0)
246 		*retval = (int) addr;
247 	return (error);
248 }
249 
250 #ifdef COMPAT_43
251 #ifndef _SYS_SYSPROTO_H_
252 struct ommap_args {
253 	caddr_t addr;
254 	int len;
255 	int prot;
256 	int flags;
257 	int fd;
258 	long pos;
259 };
260 #endif
261 int
262 ommap(p, uap, retval)
263 	struct proc *p;
264 	register struct ommap_args *uap;
265 	int *retval;
266 {
267 	struct mmap_args nargs;
268 	static const char cvtbsdprot[8] = {
269 		0,
270 		PROT_EXEC,
271 		PROT_WRITE,
272 		PROT_EXEC | PROT_WRITE,
273 		PROT_READ,
274 		PROT_EXEC | PROT_READ,
275 		PROT_WRITE | PROT_READ,
276 		PROT_EXEC | PROT_WRITE | PROT_READ,
277 	};
278 
279 #define	OMAP_ANON	0x0002
280 #define	OMAP_COPY	0x0020
281 #define	OMAP_SHARED	0x0010
282 #define	OMAP_FIXED	0x0100
283 #define	OMAP_INHERIT	0x0800
284 
285 	nargs.addr = uap->addr;
286 	nargs.len = uap->len;
287 	nargs.prot = cvtbsdprot[uap->prot & 0x7];
288 	nargs.flags = 0;
289 	if (uap->flags & OMAP_ANON)
290 		nargs.flags |= MAP_ANON;
291 	if (uap->flags & OMAP_COPY)
292 		nargs.flags |= MAP_COPY;
293 	if (uap->flags & OMAP_SHARED)
294 		nargs.flags |= MAP_SHARED;
295 	else
296 		nargs.flags |= MAP_PRIVATE;
297 	if (uap->flags & OMAP_FIXED)
298 		nargs.flags |= MAP_FIXED;
299 	if (uap->flags & OMAP_INHERIT)
300 		nargs.flags |= MAP_INHERIT;
301 	nargs.fd = uap->fd;
302 	nargs.pos = uap->pos;
303 	return (mmap(p, &nargs, retval));
304 }
305 #endif				/* COMPAT_43 */
306 
307 
308 #ifndef _SYS_SYSPROTO_H_
309 struct msync_args {
310 	caddr_t addr;
311 	int len;
312 	int flags;
313 };
314 #endif
315 int
316 msync(p, uap, retval)
317 	struct proc *p;
318 	struct msync_args *uap;
319 	int *retval;
320 {
321 	vm_offset_t addr;
322 	vm_size_t size, pageoff;
323 	int flags;
324 	vm_map_t map;
325 	int rv;
326 
327 	map = &p->p_vmspace->vm_map;
328 	addr = (vm_offset_t) uap->addr;
329 	size = round_page((vm_size_t) uap->len);
330 	flags = uap->flags;
331 
332 	/*
333 	 * Align the address to a page boundary,
334 	 * and adjust the size accordingly.
335 	 */
336 	pageoff = (addr & PAGE_MASK);
337 	addr -= pageoff;
338 	size += pageoff;
339 	size = (vm_size_t) round_page(size);
340 	if ((int)size < 0)
341 		return(EINVAL);
342 
343 	if ((flags & (MS_ASYNC|MS_INVALIDATE)) == (MS_ASYNC|MS_INVALIDATE))
344 		return (EINVAL);
345 
346 	/*
347 	 * XXX Gak!  If size is zero we are supposed to sync "all modified
348 	 * pages with the region containing addr".  Unfortunately, we don't
349 	 * really keep track of individual mmaps so we approximate by flushing
350 	 * the range of the map entry containing addr. This can be incorrect
351 	 * if the region splits or is coalesced with a neighbor.
352 	 */
353 	if (size == 0) {
354 		vm_map_entry_t entry;
355 
356 		vm_map_lock_read(map);
357 		rv = vm_map_lookup_entry(map, addr, &entry);
358 		vm_map_unlock_read(map);
359 		if (rv == FALSE)
360 			return (EINVAL);
361 		addr = entry->start;
362 		size = entry->end - entry->start;
363 	}
364 
365 	/*
366 	 * Clean the pages and interpret the return value.
367 	 */
368 	rv = vm_map_clean(map, addr, addr + size, (flags & MS_ASYNC) == 0,
369 	    (flags & MS_INVALIDATE) != 0);
370 
371 	switch (rv) {
372 	case KERN_SUCCESS:
373 		break;
374 	case KERN_INVALID_ADDRESS:
375 		return (EINVAL);	/* Sun returns ENOMEM? */
376 	case KERN_FAILURE:
377 		return (EIO);
378 	default:
379 		return (EINVAL);
380 	}
381 
382 	return (0);
383 }
384 
385 #ifndef _SYS_SYSPROTO_H_
386 struct munmap_args {
387 	caddr_t addr;
388 	int len;
389 };
390 #endif
391 int
392 munmap(p, uap, retval)
393 	register struct proc *p;
394 	register struct munmap_args *uap;
395 	int *retval;
396 {
397 	vm_offset_t addr;
398 	vm_size_t size, pageoff;
399 	vm_map_t map;
400 
401 	addr = (vm_offset_t) uap->addr;
402 	size = (vm_size_t) uap->len;
403 
404 	/*
405 	 * Align the address to a page boundary,
406 	 * and adjust the size accordingly.
407 	 */
408 	pageoff = (addr & PAGE_MASK);
409 	addr -= pageoff;
410 	size += pageoff;
411 	size = (vm_size_t) round_page(size);
412 	if ((int)size < 0)
413 		return(EINVAL);
414 	if (size == 0)
415 		return (0);
416 
417 	/*
418 	 * Check for illegal addresses.  Watch out for address wrap... Note
419 	 * that VM_*_ADDRESS are not constants due to casts (argh).
420 	 */
421 	if (VM_MAXUSER_ADDRESS > 0 && addr + size > VM_MAXUSER_ADDRESS)
422 		return (EINVAL);
423 #ifndef i386
424 	if (VM_MIN_ADDRESS > 0 && addr < VM_MIN_ADDRESS)
425 		return (EINVAL);
426 #endif
427 	if (addr + size < addr)
428 		return (EINVAL);
429 	map = &p->p_vmspace->vm_map;
430 	/*
431 	 * Make sure entire range is allocated.
432 	 */
433 	if (!vm_map_check_protection(map, addr, addr + size, VM_PROT_NONE))
434 		return (EINVAL);
435 	/* returns nothing but KERN_SUCCESS anyway */
436 	(void) vm_map_remove(map, addr, addr + size);
437 	return (0);
438 }
439 
440 void
441 munmapfd(p, fd)
442 	struct proc *p;
443 	int fd;
444 {
445 	/*
446 	 * XXX should unmap any regions mapped to this file
447 	 */
448 	p->p_fd->fd_ofileflags[fd] &= ~UF_MAPPED;
449 }
450 
451 #ifndef _SYS_SYSPROTO_H_
452 struct mprotect_args {
453 	caddr_t addr;
454 	int len;
455 	int prot;
456 };
457 #endif
458 int
459 mprotect(p, uap, retval)
460 	struct proc *p;
461 	struct mprotect_args *uap;
462 	int *retval;
463 {
464 	vm_offset_t addr;
465 	vm_size_t size, pageoff;
466 	register vm_prot_t prot;
467 
468 	addr = (vm_offset_t) uap->addr;
469 	size = (vm_size_t) uap->len;
470 	prot = uap->prot & VM_PROT_ALL;
471 
472 	/*
473 	 * Align the address to a page boundary,
474 	 * and adjust the size accordingly.
475 	 */
476 	pageoff = (addr & PAGE_MASK);
477 	addr -= pageoff;
478 	size += pageoff;
479 	size = (vm_size_t) round_page(size);
480 	if ((int)size < 0)
481 		return(EINVAL);
482 
483 	switch (vm_map_protect(&p->p_vmspace->vm_map, addr, addr + size, prot,
484 		FALSE)) {
485 	case KERN_SUCCESS:
486 		return (0);
487 	case KERN_PROTECTION_FAILURE:
488 		return (EACCES);
489 	}
490 	return (EINVAL);
491 }
492 
493 #ifndef _SYS_SYSPROTO_H_
494 struct minherit_args {
495 	caddr_t addr;
496 	int len;
497 	int inherit;
498 };
499 #endif
500 int
501 minherit(p, uap, retval)
502 	struct proc *p;
503 	struct minherit_args *uap;
504 	int *retval;
505 {
506 	vm_offset_t addr;
507 	vm_size_t size, pageoff;
508 	register vm_inherit_t inherit;
509 
510 	addr = (vm_offset_t)uap->addr;
511 	size = (vm_size_t)uap->len;
512 	inherit = uap->inherit;
513 
514 	/*
515 	 * Align the address to a page boundary,
516 	 * and adjust the size accordingly.
517 	 */
518 	pageoff = (addr & PAGE_MASK);
519 	addr -= pageoff;
520 	size += pageoff;
521 	size = (vm_size_t) round_page(size);
522 	if ((int)size < 0)
523 		return(EINVAL);
524 
525 	switch (vm_map_inherit(&p->p_vmspace->vm_map, addr, addr+size,
526 	    inherit)) {
527 	case KERN_SUCCESS:
528 		return (0);
529 	case KERN_PROTECTION_FAILURE:
530 		return (EACCES);
531 	}
532 	return (EINVAL);
533 }
534 
535 #ifndef _SYS_SYSPROTO_H_
536 struct madvise_args {
537 	caddr_t addr;
538 	int len;
539 	int behav;
540 };
541 #endif
542 
543 /* ARGSUSED */
544 int
545 madvise(p, uap, retval)
546 	struct proc *p;
547 	struct madvise_args *uap;
548 	int *retval;
549 {
550 
551 	/* Not yet implemented */
552 	return (EOPNOTSUPP);
553 }
554 
555 #ifndef _SYS_SYSPROTO_H_
556 struct mincore_args {
557 	caddr_t addr;
558 	int len;
559 	char *vec;
560 };
561 #endif
562 
563 /* ARGSUSED */
564 int
565 mincore(p, uap, retval)
566 	struct proc *p;
567 	struct mincore_args *uap;
568 	int *retval;
569 {
570 	vm_offset_t addr;
571 	vm_offset_t end;
572 	char *vec;
573 
574 	addr = trunc_page((vm_offset_t) uap->addr);
575 	end = addr + round_page((vm_size_t) uap->len);
576 	if (VM_MAXUSER_ADDRESS > 0 && end > VM_MAXUSER_ADDRESS)
577 		return (EINVAL);
578 	if (end < addr)
579 		return (EINVAL);
580 
581 	vec = uap->vec;
582 	while(addr < end) {
583 		int error;
584 		if (pmap_extract(&p->p_vmspace->vm_pmap, addr)) {
585 			error = subyte( vec, 1);
586 		} else {
587 			error = subyte( vec, 0);
588 		}
589 		if (error)
590 			return EFAULT;
591 		vec++;
592 		addr += PAGE_SIZE;
593 	}
594 	return (0);
595 }
596 
597 #ifndef _SYS_SYSPROTO_H_
598 struct mlock_args {
599 	caddr_t addr;
600 	size_t len;
601 };
602 #endif
603 int
604 mlock(p, uap, retval)
605 	struct proc *p;
606 	struct mlock_args *uap;
607 	int *retval;
608 {
609 	vm_offset_t addr;
610 	vm_size_t size, pageoff;
611 	int error;
612 
613 	addr = (vm_offset_t) uap->addr;
614 	size = (vm_size_t) uap->len;
615 	/*
616 	 * Align the address to a page boundary,
617 	 * and adjust the size accordingly.
618 	 */
619 	pageoff = (addr & PAGE_MASK);
620 	addr -= pageoff;
621 	size += pageoff;
622 	size = (vm_size_t) round_page(size);
623 
624 	/* disable wrap around */
625 	if (addr + (int)size < addr)
626 		return (EINVAL);
627 
628 	if (atop(size) + cnt.v_wire_count > vm_page_max_wired)
629 		return (EAGAIN);
630 #ifdef pmap_wired_count
631 	if (size + ptoa(pmap_wired_count(vm_map_pmap(&p->p_vmspace->vm_map))) >
632 	    p->p_rlimit[RLIMIT_MEMLOCK].rlim_cur)
633 		return (EAGAIN);
634 #else
635 	error = suser(p->p_ucred, &p->p_acflag);
636 	if (error)
637 		return (error);
638 #endif
639 
640 	error = vm_map_pageable(&p->p_vmspace->vm_map, addr, addr + size, FALSE);
641 	return (error == KERN_SUCCESS ? 0 : ENOMEM);
642 }
643 
644 #ifndef _SYS_SYSPROTO_H_
645 struct munlock_args {
646 	caddr_t addr;
647 	size_t len;
648 };
649 #endif
650 int
651 munlock(p, uap, retval)
652 	struct proc *p;
653 	struct munlock_args *uap;
654 	int *retval;
655 {
656 	vm_offset_t addr;
657 	vm_size_t size, pageoff;
658 	int error;
659 
660 	addr = (vm_offset_t) uap->addr;
661 	size = (vm_size_t) uap->len;
662 	/*
663 	 * Align the address to a page boundary,
664 	 * and adjust the size accordingly.
665 	 */
666 	pageoff = (addr & PAGE_MASK);
667 	addr -= pageoff;
668 	size += pageoff;
669 	size = (vm_size_t) round_page(size);
670 
671 	/* disable wrap around */
672 	if (addr + (int)size < addr)
673 		return (EINVAL);
674 
675 #ifndef pmap_wired_count
676 	error = suser(p->p_ucred, &p->p_acflag);
677 	if (error)
678 		return (error);
679 #endif
680 
681 	error = vm_map_pageable(&p->p_vmspace->vm_map, addr, addr + size, TRUE);
682 	return (error == KERN_SUCCESS ? 0 : ENOMEM);
683 }
684 
685 /*
686  * Internal version of mmap.
687  * Currently used by mmap, exec, and sys5 shared memory.
688  * Handle is either a vnode pointer or NULL for MAP_ANON.
689  */
690 int
691 vm_mmap(map, addr, size, prot, maxprot, flags, handle, foff)
692 	register vm_map_t map;
693 	register vm_offset_t *addr;
694 	register vm_size_t size;
695 	vm_prot_t prot, maxprot;
696 	register int flags;
697 	caddr_t handle;		/* XXX should be vp */
698 	vm_ooffset_t foff;
699 {
700 	boolean_t fitit;
701 	vm_object_t object, object2;
702 	struct vnode *vp = NULL;
703 	objtype_t type;
704 	int rv = KERN_SUCCESS;
705 	vm_ooffset_t objsize;
706 	int docow;
707 	struct proc *p = curproc;
708 
709 	if (size == 0)
710 		return (0);
711 
712 	objsize = size = round_page(size);
713 
714 	/*
715 	 * We currently can only deal with page aligned file offsets.
716 	 * The check is here rather than in the syscall because the
717 	 * kernel calls this function internally for other mmaping
718 	 * operations (such as in exec) and non-aligned offsets will
719 	 * cause pmap inconsistencies...so we want to be sure to
720 	 * disallow this in all cases.
721 	 */
722 	if (foff & PAGE_MASK)
723 		return (EINVAL);
724 
725 	if ((flags & MAP_FIXED) == 0) {
726 		fitit = TRUE;
727 		*addr = round_page(*addr);
728 	} else {
729 		if (*addr != trunc_page(*addr))
730 			return (EINVAL);
731 		fitit = FALSE;
732 		(void) vm_map_remove(map, *addr, *addr + size);
733 	}
734 
735 	/*
736 	 * Lookup/allocate object.
737 	 */
738 	if (flags & MAP_ANON) {
739 		type = OBJT_SWAP;
740 		/*
741 		 * Unnamed anonymous regions always start at 0.
742 		 */
743 		if (handle == 0)
744 			foff = 0;
745 	} else {
746 		vp = (struct vnode *) handle;
747 		if (vp->v_type == VCHR) {
748 			type = OBJT_DEVICE;
749 			handle = (caddr_t) vp->v_rdev;
750 		} else {
751 			struct vattr vat;
752 			int error;
753 
754 			error = VOP_GETATTR(vp, &vat, p->p_ucred, p);
755 			if (error)
756 				return (error);
757 			objsize = round_page(vat.va_size);
758 			type = OBJT_VNODE;
759 		}
760 	}
761 	object = vm_pager_allocate(type, handle, OFF_TO_IDX(objsize), prot, foff);
762 	if (object == NULL)
763 		return (type == OBJT_DEVICE ? EINVAL : ENOMEM);
764 
765 	object2 = NULL;
766 	docow = 0;
767 	if ((flags & (MAP_ANON|MAP_SHARED)) == 0 && (type != OBJT_DEVICE)) {
768 		docow = MAP_COPY_ON_WRITE;
769 		if (objsize < size) {
770 			object2 = vm_object_allocate( OBJT_DEFAULT,
771 				OFF_TO_IDX(size - (foff & ~(PAGE_SIZE - 1))));
772 			object2->backing_object = object;
773 			object2->backing_object_offset = foff;
774 			TAILQ_INSERT_TAIL(&object->shadow_head,
775 				object2, shadow_list);
776 		} else {
777 			docow |= MAP_COPY_NEEDED;
778 		}
779 	}
780 	if (object2)
781 		rv = vm_map_find(map, object2, 0, addr, size, fitit,
782 			prot, maxprot, docow);
783 	else
784 		rv = vm_map_find(map, object, foff, addr, size, fitit,
785 			prot, maxprot, docow);
786 
787 
788 	if (rv != KERN_SUCCESS) {
789 		/*
790 		 * Lose the object reference. Will destroy the
791 		 * object if it's an unnamed anonymous mapping
792 		 * or named anonymous without other references.
793 		 */
794 		if (object2)
795 			vm_object_deallocate(object2);
796 		else
797 			vm_object_deallocate(object);
798 		goto out;
799 	}
800 
801 	/*
802 	 * "Pre-fault" resident pages.
803 	 */
804 	if ((map != kernel_map) &&
805 		(type == OBJT_VNODE) && (map->pmap != NULL)) {
806 		pmap_object_init_pt(map->pmap, *addr,
807 			object, (vm_pindex_t) OFF_TO_IDX(foff), size);
808 	}
809 
810 	/*
811 	 * Shared memory is also shared with children.
812 	 */
813 	if (flags & MAP_SHARED) {
814 		rv = vm_map_inherit(map, *addr, *addr + size, VM_INHERIT_SHARE);
815 		if (rv != KERN_SUCCESS) {
816 			(void) vm_map_remove(map, *addr, *addr + size);
817 			goto out;
818 		}
819 	}
820 out:
821 	switch (rv) {
822 	case KERN_SUCCESS:
823 		return (0);
824 	case KERN_INVALID_ADDRESS:
825 	case KERN_NO_SPACE:
826 		return (ENOMEM);
827 	case KERN_PROTECTION_FAILURE:
828 		return (EACCES);
829 	default:
830 		return (EINVAL);
831 	}
832 }
833