xref: /freebsd/sys/vm/vm_mmap.c (revision 0de89efe5c443f213c7ea28773ef2dc6cf3af2ed)
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.67 1997/08/30 18:50:06 peter Exp $
42  */
43 
44 /*
45  * Mapped file (mmap) interface to VM
46  */
47 
48 #include "opt_rlimit.h"
49 
50 #include <sys/param.h>
51 #include <sys/systm.h>
52 #include <sys/sysproto.h>
53 #include <sys/filedesc.h>
54 #include <sys/proc.h>
55 #include <sys/vnode.h>
56 #include <sys/fcntl.h>
57 #include <sys/file.h>
58 #include <sys/mman.h>
59 #include <sys/conf.h>
60 #include <sys/vmmeter.h>
61 
62 #include <miscfs/specfs/specdev.h>
63 
64 #include <vm/vm.h>
65 #include <vm/vm_param.h>
66 #include <vm/vm_prot.h>
67 #include <vm/vm_inherit.h>
68 #include <sys/lock.h>
69 #include <vm/pmap.h>
70 #include <vm/vm_map.h>
71 #include <vm/vm_object.h>
72 #include <vm/vm_pager.h>
73 #include <vm/vm_pageout.h>
74 #include <vm/vm_extern.h>
75 #include <vm/vm_page.h>
76 
77 #ifndef _SYS_SYSPROTO_H_
78 struct sbrk_args {
79 	int incr;
80 };
81 #endif
82 
83 /* ARGSUSED */
84 int
85 sbrk(p, uap, retval)
86 	struct proc *p;
87 	struct sbrk_args *uap;
88 	int *retval;
89 {
90 
91 	/* Not yet implemented */
92 	return (EOPNOTSUPP);
93 }
94 
95 #ifndef _SYS_SYSPROTO_H_
96 struct sstk_args {
97 	int incr;
98 };
99 #endif
100 
101 /* ARGSUSED */
102 int
103 sstk(p, uap, retval)
104 	struct proc *p;
105 	struct sstk_args *uap;
106 	int *retval;
107 {
108 
109 	/* Not yet implemented */
110 	return (EOPNOTSUPP);
111 }
112 
113 #if defined(COMPAT_43) || defined(COMPAT_SUNOS)
114 #ifndef _SYS_SYSPROTO_H_
115 struct getpagesize_args {
116 	int dummy;
117 };
118 #endif
119 
120 /* ARGSUSED */
121 int
122 ogetpagesize(p, uap, retval)
123 	struct proc *p;
124 	struct getpagesize_args *uap;
125 	int *retval;
126 {
127 
128 	*retval = PAGE_SIZE;
129 	return (0);
130 }
131 #endif				/* COMPAT_43 || COMPAT_SUNOS */
132 
133 
134 /*
135  * Memory Map (mmap) system call.  Note that the file offset
136  * and address are allowed to be NOT page aligned, though if
137  * the MAP_FIXED flag it set, both must have the same remainder
138  * modulo the PAGE_SIZE (POSIX 1003.1b).  If the address is not
139  * page-aligned, the actual mapping starts at trunc_page(addr)
140  * and the return value is adjusted up by the page offset.
141  */
142 #ifndef _SYS_SYSPROTO_H_
143 struct mmap_args {
144 	caddr_t addr;
145 	size_t len;
146 	int prot;
147 	int flags;
148 	int fd;
149 	long pad;
150 	off_t pos;
151 };
152 #endif
153 
154 int
155 mmap(p, uap, retval)
156 	struct proc *p;
157 	register struct mmap_args *uap;
158 	int *retval;
159 {
160 	register struct filedesc *fdp = p->p_fd;
161 	register struct file *fp;
162 	struct vnode *vp;
163 	vm_offset_t addr;
164 	vm_size_t size, pageoff;
165 	vm_prot_t prot, maxprot;
166 	caddr_t handle;
167 	int flags, error;
168 	off_t pos;
169 
170 	addr = (vm_offset_t) uap->addr;
171 	size = uap->len;
172 	prot = uap->prot & VM_PROT_ALL;
173 	flags = uap->flags;
174 	pos = uap->pos;
175 
176 	/* make sure mapping fits into numeric range etc */
177 	if ((pos + size > (vm_offset_t)-PAGE_SIZE) ||
178 	    (ssize_t) uap->len < 0 ||
179 	    ((flags & MAP_ANON) && uap->fd != -1))
180 		return (EINVAL);
181 
182 	/*
183 	 * Align the file position to a page boundary,
184 	 * and save its page offset component.
185 	 */
186 	pageoff = (pos & PAGE_MASK);
187 	pos -= pageoff;
188 
189 	/* Adjust size for rounding (on both ends). */
190 	size += pageoff;			/* low end... */
191 	size = (vm_size_t) round_page(size);	/* hi end */
192 
193 	/*
194 	 * Check for illegal addresses.  Watch out for address wrap... Note
195 	 * that VM_*_ADDRESS are not constants due to casts (argh).
196 	 */
197 	if (flags & MAP_FIXED) {
198 		/*
199 		 * The specified address must have the same remainder
200 		 * as the file offset taken modulo PAGE_SIZE, so it
201 		 * should be aligned after adjustment by pageoff.
202 		 */
203 		addr -= pageoff;
204 		if (addr & PAGE_MASK)
205 			return (EINVAL);
206 		/* Address range must be all in user VM space. */
207 		if (VM_MAXUSER_ADDRESS > 0 && addr + size > VM_MAXUSER_ADDRESS)
208 			return (EINVAL);
209 #ifndef i386
210 		if (VM_MIN_ADDRESS > 0 && addr < VM_MIN_ADDRESS)
211 			return (EINVAL);
212 #endif
213 		if (addr + size < addr)
214 			return (EINVAL);
215 	}
216 	/*
217 	 * XXX for non-fixed mappings where no hint is provided or
218 	 * the hint would fall in the potential heap space,
219 	 * place it after the end of the largest possible heap.
220 	 *
221 	 * There should really be a pmap call to determine a reasonable
222 	 * location.
223 	 */
224 	else if (addr < round_page(p->p_vmspace->vm_daddr + MAXDSIZ))
225 		addr = round_page(p->p_vmspace->vm_daddr + MAXDSIZ);
226 
227 	if (flags & MAP_ANON) {
228 		/*
229 		 * Mapping blank space is trivial.
230 		 */
231 		handle = NULL;
232 		maxprot = VM_PROT_ALL;
233 		pos = 0;
234 	} else {
235 		/*
236 		 * Mapping file, get fp for validation. Obtain vnode and make
237 		 * sure it is of appropriate type.
238 		 */
239 		if (((unsigned) uap->fd) >= fdp->fd_nfiles ||
240 		    (fp = fdp->fd_ofiles[uap->fd]) == NULL)
241 			return (EBADF);
242 		if (fp->f_type != DTYPE_VNODE)
243 			return (EINVAL);
244 		vp = (struct vnode *) fp->f_data;
245 		if (vp->v_type != VREG && vp->v_type != VCHR)
246 			return (EINVAL);
247 		/*
248 		 * XXX hack to handle use of /dev/zero to map anon memory (ala
249 		 * SunOS).
250 		 */
251 		if (vp->v_type == VCHR && iszerodev(vp->v_rdev)) {
252 			handle = NULL;
253 			maxprot = VM_PROT_ALL;
254 			flags |= MAP_ANON;
255 			pos = 0;
256 		} else {
257 			/*
258 			 * Ensure that file and memory protections are
259 			 * compatible.  Note that we only worry about
260 			 * writability if mapping is shared; in this case,
261 			 * current and max prot are dictated by the open file.
262 			 * XXX use the vnode instead?  Problem is: what
263 			 * credentials do we use for determination? What if
264 			 * proc does a setuid?
265 			 */
266 			maxprot = VM_PROT_EXECUTE;	/* ??? */
267 			if (fp->f_flag & FREAD)
268 				maxprot |= VM_PROT_READ;
269 			else if (prot & PROT_READ)
270 				return (EACCES);
271 			if (flags & MAP_SHARED) {
272 				if (fp->f_flag & FWRITE)
273 					maxprot |= VM_PROT_WRITE;
274 				else if (prot & PROT_WRITE)
275 					return (EACCES);
276 			} else
277 				maxprot |= VM_PROT_WRITE;
278 			handle = (caddr_t) vp;
279 		}
280 	}
281 	error = vm_mmap(&p->p_vmspace->vm_map, &addr, size, prot, maxprot,
282 	    flags, handle, pos);
283 	if (error == 0)
284 		*retval = (int) (addr + pageoff);
285 	return (error);
286 }
287 
288 #ifdef COMPAT_43
289 #ifndef _SYS_SYSPROTO_H_
290 struct ommap_args {
291 	caddr_t addr;
292 	int len;
293 	int prot;
294 	int flags;
295 	int fd;
296 	long pos;
297 };
298 #endif
299 int
300 ommap(p, uap, retval)
301 	struct proc *p;
302 	register struct ommap_args *uap;
303 	int *retval;
304 {
305 	struct mmap_args nargs;
306 	static const char cvtbsdprot[8] = {
307 		0,
308 		PROT_EXEC,
309 		PROT_WRITE,
310 		PROT_EXEC | PROT_WRITE,
311 		PROT_READ,
312 		PROT_EXEC | PROT_READ,
313 		PROT_WRITE | PROT_READ,
314 		PROT_EXEC | PROT_WRITE | PROT_READ,
315 	};
316 
317 #define	OMAP_ANON	0x0002
318 #define	OMAP_COPY	0x0020
319 #define	OMAP_SHARED	0x0010
320 #define	OMAP_FIXED	0x0100
321 #define	OMAP_INHERIT	0x0800
322 
323 	nargs.addr = uap->addr;
324 	nargs.len = uap->len;
325 	nargs.prot = cvtbsdprot[uap->prot & 0x7];
326 	nargs.flags = 0;
327 	if (uap->flags & OMAP_ANON)
328 		nargs.flags |= MAP_ANON;
329 	if (uap->flags & OMAP_COPY)
330 		nargs.flags |= MAP_COPY;
331 	if (uap->flags & OMAP_SHARED)
332 		nargs.flags |= MAP_SHARED;
333 	else
334 		nargs.flags |= MAP_PRIVATE;
335 	if (uap->flags & OMAP_FIXED)
336 		nargs.flags |= MAP_FIXED;
337 	if (uap->flags & OMAP_INHERIT)
338 		nargs.flags |= MAP_INHERIT;
339 	nargs.fd = uap->fd;
340 	nargs.pos = uap->pos;
341 	return (mmap(p, &nargs, retval));
342 }
343 #endif				/* COMPAT_43 */
344 
345 
346 #ifndef _SYS_SYSPROTO_H_
347 struct msync_args {
348 	caddr_t addr;
349 	int len;
350 	int flags;
351 };
352 #endif
353 int
354 msync(p, uap, retval)
355 	struct proc *p;
356 	struct msync_args *uap;
357 	int *retval;
358 {
359 	vm_offset_t addr;
360 	vm_size_t size, pageoff;
361 	int flags;
362 	vm_map_t map;
363 	int rv;
364 
365 	addr = (vm_offset_t) uap->addr;
366 	size = uap->len;
367 	flags = uap->flags;
368 
369 	pageoff = (addr & PAGE_MASK);
370 	addr -= pageoff;
371 	size += pageoff;
372 	size = (vm_size_t) round_page(size);
373 	if (addr + size < addr)
374 		return(EINVAL);
375 
376 	if ((flags & (MS_ASYNC|MS_INVALIDATE)) == (MS_ASYNC|MS_INVALIDATE))
377 		return (EINVAL);
378 
379 	map = &p->p_vmspace->vm_map;
380 
381 	/*
382 	 * XXX Gak!  If size is zero we are supposed to sync "all modified
383 	 * pages with the region containing addr".  Unfortunately, we don't
384 	 * really keep track of individual mmaps so we approximate by flushing
385 	 * the range of the map entry containing addr. This can be incorrect
386 	 * if the region splits or is coalesced with a neighbor.
387 	 */
388 	if (size == 0) {
389 		vm_map_entry_t entry;
390 
391 		vm_map_lock_read(map);
392 		rv = vm_map_lookup_entry(map, addr, &entry);
393 		vm_map_unlock_read(map);
394 		if (rv == FALSE)
395 			return (EINVAL);
396 		addr = entry->start;
397 		size = entry->end - entry->start;
398 	}
399 
400 	/*
401 	 * Clean the pages and interpret the return value.
402 	 */
403 	rv = vm_map_clean(map, addr, addr + size, (flags & MS_ASYNC) == 0,
404 	    (flags & MS_INVALIDATE) != 0);
405 
406 	switch (rv) {
407 	case KERN_SUCCESS:
408 		break;
409 	case KERN_INVALID_ADDRESS:
410 		return (EINVAL);	/* Sun returns ENOMEM? */
411 	case KERN_FAILURE:
412 		return (EIO);
413 	default:
414 		return (EINVAL);
415 	}
416 
417 	return (0);
418 }
419 
420 #ifndef _SYS_SYSPROTO_H_
421 struct munmap_args {
422 	caddr_t addr;
423 	size_t len;
424 };
425 #endif
426 int
427 munmap(p, uap, retval)
428 	register struct proc *p;
429 	register struct munmap_args *uap;
430 	int *retval;
431 {
432 	vm_offset_t addr;
433 	vm_size_t size, pageoff;
434 	vm_map_t map;
435 
436 	addr = (vm_offset_t) uap->addr;
437 	size = uap->len;
438 
439 	pageoff = (addr & PAGE_MASK);
440 	addr -= pageoff;
441 	size += pageoff;
442 	size = (vm_size_t) round_page(size);
443 	if (addr + size < addr)
444 		return(EINVAL);
445 
446 	if (size == 0)
447 		return (0);
448 
449 	/*
450 	 * Check for illegal addresses.  Watch out for address wrap... Note
451 	 * that VM_*_ADDRESS are not constants due to casts (argh).
452 	 */
453 	if (VM_MAXUSER_ADDRESS > 0 && addr + size > VM_MAXUSER_ADDRESS)
454 		return (EINVAL);
455 #ifndef i386
456 	if (VM_MIN_ADDRESS > 0 && addr < VM_MIN_ADDRESS)
457 		return (EINVAL);
458 #endif
459 	map = &p->p_vmspace->vm_map;
460 	/*
461 	 * Make sure entire range is allocated.
462 	 */
463 	if (!vm_map_check_protection(map, addr, addr + size, VM_PROT_NONE))
464 		return (EINVAL);
465 	/* returns nothing but KERN_SUCCESS anyway */
466 	(void) vm_map_remove(map, addr, addr + size);
467 	return (0);
468 }
469 
470 void
471 munmapfd(p, fd)
472 	struct proc *p;
473 	int fd;
474 {
475 	/*
476 	 * XXX should unmap any regions mapped to this file
477 	 */
478 	p->p_fd->fd_ofileflags[fd] &= ~UF_MAPPED;
479 }
480 
481 #ifndef _SYS_SYSPROTO_H_
482 struct mprotect_args {
483 	caddr_t addr;
484 	size_t len;
485 	int prot;
486 };
487 #endif
488 int
489 mprotect(p, uap, retval)
490 	struct proc *p;
491 	struct mprotect_args *uap;
492 	int *retval;
493 {
494 	vm_offset_t addr;
495 	vm_size_t size, pageoff;
496 	register vm_prot_t prot;
497 
498 	addr = (vm_offset_t) uap->addr;
499 	size = uap->len;
500 	prot = uap->prot & VM_PROT_ALL;
501 #if defined(VM_PROT_READ_IS_EXEC)
502 	if (prot & VM_PROT_READ)
503 		prot |= VM_PROT_EXECUTE;
504 #endif
505 
506 	pageoff = (addr & PAGE_MASK);
507 	addr -= pageoff;
508 	size += pageoff;
509 	size = (vm_size_t) round_page(size);
510 	if (addr + size < addr)
511 		return(EINVAL);
512 
513 	switch (vm_map_protect(&p->p_vmspace->vm_map, addr, addr + size, prot,
514 		FALSE)) {
515 	case KERN_SUCCESS:
516 		return (0);
517 	case KERN_PROTECTION_FAILURE:
518 		return (EACCES);
519 	}
520 	return (EINVAL);
521 }
522 
523 #ifndef _SYS_SYSPROTO_H_
524 struct minherit_args {
525 	caddr_t addr;
526 	size_t len;
527 	int inherit;
528 };
529 #endif
530 int
531 minherit(p, uap, retval)
532 	struct proc *p;
533 	struct minherit_args *uap;
534 	int *retval;
535 {
536 	vm_offset_t addr;
537 	vm_size_t size, pageoff;
538 	register vm_inherit_t inherit;
539 
540 	addr = (vm_offset_t)uap->addr;
541 	size = uap->len;
542 	inherit = uap->inherit;
543 
544 	pageoff = (addr & PAGE_MASK);
545 	addr -= pageoff;
546 	size += pageoff;
547 	size = (vm_size_t) round_page(size);
548 	if (addr + size < addr)
549 		return(EINVAL);
550 
551 	switch (vm_map_inherit(&p->p_vmspace->vm_map, addr, addr+size,
552 	    inherit)) {
553 	case KERN_SUCCESS:
554 		return (0);
555 	case KERN_PROTECTION_FAILURE:
556 		return (EACCES);
557 	}
558 	return (EINVAL);
559 }
560 
561 #ifndef _SYS_SYSPROTO_H_
562 struct madvise_args {
563 	caddr_t addr;
564 	size_t len;
565 	int behav;
566 };
567 #endif
568 
569 /* ARGSUSED */
570 int
571 madvise(p, uap, retval)
572 	struct proc *p;
573 	struct madvise_args *uap;
574 	int *retval;
575 {
576 	vm_map_t map;
577 	pmap_t pmap;
578 	vm_offset_t start, end;
579 	/*
580 	 * Check for illegal addresses.  Watch out for address wrap... Note
581 	 * that VM_*_ADDRESS are not constants due to casts (argh).
582 	 */
583 	if (VM_MAXUSER_ADDRESS > 0 &&
584 		((vm_offset_t) uap->addr + uap->len) > VM_MAXUSER_ADDRESS)
585 		return (EINVAL);
586 #ifndef i386
587 	if (VM_MIN_ADDRESS > 0 && uap->addr < VM_MIN_ADDRESS)
588 		return (EINVAL);
589 #endif
590 	if (((vm_offset_t) uap->addr + uap->len) < (vm_offset_t) uap->addr)
591 		return (EINVAL);
592 
593 	/*
594 	 * Since this routine is only advisory, we default to conservative
595 	 * behavior.
596 	 */
597 	start = trunc_page((vm_offset_t) uap->addr);
598 	end = round_page((vm_offset_t) uap->addr + uap->len);
599 
600 	map = &p->p_vmspace->vm_map;
601 	pmap = &p->p_vmspace->vm_pmap;
602 
603 	vm_map_madvise(map, pmap, start, end, uap->behav);
604 
605 	return (0);
606 }
607 
608 #ifndef _SYS_SYSPROTO_H_
609 struct mincore_args {
610 	caddr_t addr;
611 	size_t len;
612 	char *vec;
613 };
614 #endif
615 
616 /* ARGSUSED */
617 int
618 mincore(p, uap, retval)
619 	struct proc *p;
620 	struct mincore_args *uap;
621 	int *retval;
622 {
623 	vm_offset_t addr, first_addr;
624 	vm_offset_t end, cend;
625 	pmap_t pmap;
626 	vm_map_t map;
627 	char *vec;
628 	int error;
629 	int vecindex, lastvecindex;
630 	register vm_map_entry_t current;
631 	vm_map_entry_t entry;
632 	int mincoreinfo;
633 
634 	/*
635 	 * Make sure that the addresses presented are valid for user
636 	 * mode.
637 	 */
638 	first_addr = addr = trunc_page((vm_offset_t) uap->addr);
639 	end = addr + (vm_size_t)round_page(uap->len);
640 	if (VM_MAXUSER_ADDRESS > 0 && end > VM_MAXUSER_ADDRESS)
641 		return (EINVAL);
642 	if (end < addr)
643 		return (EINVAL);
644 
645 	/*
646 	 * Address of byte vector
647 	 */
648 	vec = uap->vec;
649 
650 	map = &p->p_vmspace->vm_map;
651 	pmap = &p->p_vmspace->vm_pmap;
652 
653 	vm_map_lock(map);
654 
655 	/*
656 	 * Not needed here
657 	 */
658 #if 0
659 	VM_MAP_RANGE_CHECK(map, addr, end);
660 #endif
661 
662 	if (!vm_map_lookup_entry(map, addr, &entry))
663 		entry = entry->next;
664 
665 	/*
666 	 * Do this on a map entry basis so that if the pages are not
667 	 * in the current processes address space, we can easily look
668 	 * up the pages elsewhere.
669 	 */
670 	lastvecindex = -1;
671 	for(current = entry;
672 		(current != &map->header) && (current->start < end);
673 		current = current->next) {
674 
675 		/*
676 		 * ignore submaps (for now) or null objects
677 		 */
678 		if ((current->eflags & (MAP_ENTRY_IS_A_MAP|MAP_ENTRY_IS_SUB_MAP)) ||
679 			current->object.vm_object == NULL)
680 			continue;
681 
682 		/*
683 		 * limit this scan to the current map entry and the
684 		 * limits for the mincore call
685 		 */
686 		if (addr < current->start)
687 			addr = current->start;
688 		cend = current->end;
689 		if (cend > end)
690 			cend = end;
691 
692 		/*
693 		 * scan this entry one page at a time
694 		 */
695 		while(addr < cend) {
696 			/*
697 			 * Check pmap first, it is likely faster, also
698 			 * it can provide info as to whether we are the
699 			 * one referencing or modifying the page.
700 			 */
701 			mincoreinfo = pmap_mincore(pmap, addr);
702 			if (!mincoreinfo) {
703 				vm_pindex_t pindex;
704 				vm_ooffset_t offset;
705 				vm_page_t m;
706 				/*
707 				 * calculate the page index into the object
708 				 */
709 				offset = current->offset + (addr - current->start);
710 				pindex = OFF_TO_IDX(offset);
711 				m = vm_page_lookup(current->object.vm_object,
712 					pindex);
713 				/*
714 				 * if the page is resident, then gather information about
715 				 * it.
716 				 */
717 				if (m) {
718 					mincoreinfo = MINCORE_INCORE;
719 					if (m->dirty ||
720 						pmap_is_modified(VM_PAGE_TO_PHYS(m)))
721 						mincoreinfo |= MINCORE_MODIFIED_OTHER;
722 					if ((m->flags & PG_REFERENCED) ||
723 						pmap_ts_referenced(VM_PAGE_TO_PHYS(m))) {
724 						m->flags |= PG_REFERENCED;
725 						mincoreinfo |= MINCORE_REFERENCED_OTHER;
726 					}
727 				}
728 			}
729 
730 			/*
731 			 * calculate index into user supplied byte vector
732 			 */
733 			vecindex = OFF_TO_IDX(addr - first_addr);
734 
735 			/*
736 			 * If we have skipped map entries, we need to make sure that
737 			 * the byte vector is zeroed for those skipped entries.
738 			 */
739 			while((lastvecindex + 1) < vecindex) {
740 				error = subyte( vec + lastvecindex, 0);
741 				if (error) {
742 					vm_map_unlock(map);
743 					return (EFAULT);
744 				}
745 				++lastvecindex;
746 			}
747 
748 			/*
749 			 * Pass the page information to the user
750 			 */
751 			error = subyte( vec + vecindex, mincoreinfo);
752 			if (error) {
753 				vm_map_unlock(map);
754 				return (EFAULT);
755 			}
756 			lastvecindex = vecindex;
757 			addr += PAGE_SIZE;
758 		}
759 	}
760 
761 	/*
762 	 * Zero the last entries in the byte vector.
763 	 */
764 	vecindex = OFF_TO_IDX(end - first_addr);
765 	while((lastvecindex + 1) < vecindex) {
766 		error = subyte( vec + lastvecindex, 0);
767 		if (error) {
768 			vm_map_unlock(map);
769 			return (EFAULT);
770 		}
771 		++lastvecindex;
772 	}
773 
774 	vm_map_unlock(map);
775 	return (0);
776 }
777 
778 #ifndef _SYS_SYSPROTO_H_
779 struct mlock_args {
780 	caddr_t addr;
781 	size_t len;
782 };
783 #endif
784 int
785 mlock(p, uap, retval)
786 	struct proc *p;
787 	struct mlock_args *uap;
788 	int *retval;
789 {
790 	vm_offset_t addr;
791 	vm_size_t size, pageoff;
792 	int error;
793 
794 	addr = (vm_offset_t) uap->addr;
795 	size = uap->len;
796 
797 	pageoff = (addr & PAGE_MASK);
798 	addr -= pageoff;
799 	size += pageoff;
800 	size = (vm_size_t) round_page(size);
801 
802 	/* disable wrap around */
803 	if (addr + size < addr)
804 		return (EINVAL);
805 
806 	if (atop(size) + cnt.v_wire_count > vm_page_max_wired)
807 		return (EAGAIN);
808 
809 #ifdef pmap_wired_count
810 	if (size + ptoa(pmap_wired_count(vm_map_pmap(&p->p_vmspace->vm_map))) >
811 	    p->p_rlimit[RLIMIT_MEMLOCK].rlim_cur)
812 		return (ENOMEM);
813 #else
814 	error = suser(p->p_ucred, &p->p_acflag);
815 	if (error)
816 		return (error);
817 #endif
818 
819 	error = vm_map_user_pageable(&p->p_vmspace->vm_map, addr, addr + size, FALSE);
820 	return (error == KERN_SUCCESS ? 0 : ENOMEM);
821 }
822 
823 #ifndef _SYS_SYSPROTO_H_
824 struct mlockall_args {
825 	int	how;
826 };
827 #endif
828 
829 int
830 mlockall(p, uap, retval)
831 	struct proc *p;
832 	struct mlockall_args *uap;
833 	int *retval;
834 {
835 	return 0;
836 }
837 
838 #ifndef _SYS_SYSPROTO_H_
839 struct mlockall_args {
840 	int	how;
841 };
842 #endif
843 
844 int
845 munlockall(p, uap, retval)
846 	struct proc *p;
847 	struct munlockall_args *uap;
848 	int *retval;
849 {
850 	return 0;
851 }
852 
853 #ifndef _SYS_SYSPROTO_H_
854 struct munlock_args {
855 	caddr_t addr;
856 	size_t len;
857 };
858 #endif
859 int
860 munlock(p, uap, retval)
861 	struct proc *p;
862 	struct munlock_args *uap;
863 	int *retval;
864 {
865 	vm_offset_t addr;
866 	vm_size_t size, pageoff;
867 	int error;
868 
869 	addr = (vm_offset_t) uap->addr;
870 	size = uap->len;
871 
872 	pageoff = (addr & PAGE_MASK);
873 	addr -= pageoff;
874 	size += pageoff;
875 	size = (vm_size_t) round_page(size);
876 
877 	/* disable wrap around */
878 	if (addr + size < addr)
879 		return (EINVAL);
880 
881 #ifndef pmap_wired_count
882 	error = suser(p->p_ucred, &p->p_acflag);
883 	if (error)
884 		return (error);
885 #endif
886 
887 	error = vm_map_user_pageable(&p->p_vmspace->vm_map, addr, addr + size, TRUE);
888 	return (error == KERN_SUCCESS ? 0 : ENOMEM);
889 }
890 
891 /*
892  * Internal version of mmap.
893  * Currently used by mmap, exec, and sys5 shared memory.
894  * Handle is either a vnode pointer or NULL for MAP_ANON.
895  */
896 int
897 vm_mmap(vm_map_t map, vm_offset_t *addr, vm_size_t size, vm_prot_t prot,
898 	vm_prot_t maxprot, int flags,
899 	caddr_t handle,		 /* XXX should be vp */
900 	vm_ooffset_t foff)
901 {
902 	boolean_t fitit;
903 	vm_object_t object;
904 	struct vnode *vp = NULL;
905 	objtype_t type;
906 	int rv = KERN_SUCCESS;
907 	vm_ooffset_t objsize;
908 	int docow;
909 	struct proc *p = curproc;
910 
911 	if (size == 0)
912 		return (0);
913 
914 	objsize = size = round_page(size);
915 
916 	/*
917 	 * We currently can only deal with page aligned file offsets.
918 	 * The check is here rather than in the syscall because the
919 	 * kernel calls this function internally for other mmaping
920 	 * operations (such as in exec) and non-aligned offsets will
921 	 * cause pmap inconsistencies...so we want to be sure to
922 	 * disallow this in all cases.
923 	 */
924 	if (foff & PAGE_MASK)
925 		return (EINVAL);
926 
927 	if ((flags & MAP_FIXED) == 0) {
928 		fitit = TRUE;
929 		*addr = round_page(*addr);
930 	} else {
931 		if (*addr != trunc_page(*addr))
932 			return (EINVAL);
933 		fitit = FALSE;
934 		(void) vm_map_remove(map, *addr, *addr + size);
935 	}
936 
937 	/*
938 	 * Lookup/allocate object.
939 	 */
940 	if (flags & MAP_ANON) {
941 		type = OBJT_DEFAULT;
942 		/*
943 		 * Unnamed anonymous regions always start at 0.
944 		 */
945 		if (handle == 0)
946 			foff = 0;
947 	} else {
948 		vp = (struct vnode *) handle;
949 		if (vp->v_type == VCHR) {
950 			type = OBJT_DEVICE;
951 			handle = (caddr_t) vp->v_rdev;
952 		} else {
953 			struct vattr vat;
954 			int error;
955 
956 			error = VOP_GETATTR(vp, &vat, p->p_ucred, p);
957 			if (error)
958 				return (error);
959 			objsize = round_page(vat.va_size);
960 			type = OBJT_VNODE;
961 		}
962 	}
963 
964 	if (handle == NULL) {
965 		object = NULL;
966 	} else {
967 		object = vm_pager_allocate(type,
968 			handle, OFF_TO_IDX(objsize), prot, foff);
969 		if (object == NULL)
970 			return (type == OBJT_DEVICE ? EINVAL : ENOMEM);
971 	}
972 
973 	/*
974 	 * Force device mappings to be shared.
975 	 */
976 	if (type == OBJT_DEVICE) {
977 		flags &= ~(MAP_PRIVATE|MAP_COPY);
978 		flags |= MAP_SHARED;
979 	}
980 
981 	docow = 0;
982 	if ((flags & (MAP_ANON|MAP_SHARED)) == 0) {
983 		docow = MAP_COPY_ON_WRITE | MAP_COPY_NEEDED;
984 	}
985 
986 #if defined(VM_PROT_READ_IS_EXEC)
987 	if (prot & VM_PROT_READ)
988 		prot |= VM_PROT_EXECUTE;
989 
990 	if (maxprot & VM_PROT_READ)
991 		maxprot |= VM_PROT_EXECUTE;
992 #endif
993 
994 	if (fitit) {
995 		*addr = pmap_addr_hint(object, *addr, size);
996 	}
997 
998 	rv = vm_map_find(map, object, foff, addr, size, fitit,
999 			prot, maxprot, docow);
1000 
1001 	if (rv != KERN_SUCCESS) {
1002 		/*
1003 		 * Lose the object reference. Will destroy the
1004 		 * object if it's an unnamed anonymous mapping
1005 		 * or named anonymous without other references.
1006 		 */
1007 		vm_object_deallocate(object);
1008 		goto out;
1009 	}
1010 
1011 	/*
1012 	 * "Pre-fault" resident pages.
1013 	 */
1014 	if ((map->pmap != NULL) && (object != NULL)) {
1015 		pmap_object_init_pt(map->pmap, *addr,
1016 			object, (vm_pindex_t) OFF_TO_IDX(foff), size, 1);
1017 	}
1018 
1019 	/*
1020 	 * Shared memory is also shared with children.
1021 	 */
1022 	if (flags & (MAP_SHARED|MAP_INHERIT)) {
1023 		rv = vm_map_inherit(map, *addr, *addr + size, VM_INHERIT_SHARE);
1024 		if (rv != KERN_SUCCESS) {
1025 			(void) vm_map_remove(map, *addr, *addr + size);
1026 			goto out;
1027 		}
1028 	}
1029 out:
1030 	switch (rv) {
1031 	case KERN_SUCCESS:
1032 		return (0);
1033 	case KERN_INVALID_ADDRESS:
1034 	case KERN_NO_SPACE:
1035 		return (ENOMEM);
1036 	case KERN_PROTECTION_FAILURE:
1037 		return (EACCES);
1038 	default:
1039 		return (EINVAL);
1040 	}
1041 }
1042