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