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