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