]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/vm/vm_mmap.c
MFC r313693:
[FreeBSD/FreeBSD.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  * 4. Neither the name of the University nor the names of its contributors
19  *    may be used to endorse or promote products derived from this software
20  *    without specific prior written permission.
21  *
22  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
23  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
26  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32  * SUCH DAMAGE.
33  *
34  * from: Utah $Hdr: vm_mmap.c 1.6 91/10/21$
35  *
36  *      @(#)vm_mmap.c   8.4 (Berkeley) 1/12/94
37  */
38
39 /*
40  * Mapped file (mmap) interface to VM
41  */
42
43 #include <sys/cdefs.h>
44 __FBSDID("$FreeBSD$");
45
46 #include "opt_compat.h"
47 #include "opt_hwpmc_hooks.h"
48 #include "opt_vm.h"
49
50 #include <sys/param.h>
51 #include <sys/systm.h>
52 #include <sys/capsicum.h>
53 #include <sys/kernel.h>
54 #include <sys/lock.h>
55 #include <sys/mutex.h>
56 #include <sys/sysproto.h>
57 #include <sys/filedesc.h>
58 #include <sys/priv.h>
59 #include <sys/proc.h>
60 #include <sys/procctl.h>
61 #include <sys/racct.h>
62 #include <sys/resource.h>
63 #include <sys/resourcevar.h>
64 #include <sys/rwlock.h>
65 #include <sys/sysctl.h>
66 #include <sys/vnode.h>
67 #include <sys/fcntl.h>
68 #include <sys/file.h>
69 #include <sys/mman.h>
70 #include <sys/mount.h>
71 #include <sys/conf.h>
72 #include <sys/stat.h>
73 #include <sys/syscallsubr.h>
74 #include <sys/sysent.h>
75 #include <sys/vmmeter.h>
76
77 #include <security/mac/mac_framework.h>
78
79 #include <vm/vm.h>
80 #include <vm/vm_param.h>
81 #include <vm/pmap.h>
82 #include <vm/vm_map.h>
83 #include <vm/vm_object.h>
84 #include <vm/vm_page.h>
85 #include <vm/vm_pager.h>
86 #include <vm/vm_pageout.h>
87 #include <vm/vm_extern.h>
88 #include <vm/vm_page.h>
89 #include <vm/vnode_pager.h>
90
91 #ifdef HWPMC_HOOKS
92 #include <sys/pmckern.h>
93 #endif
94
95 int old_mlock = 0;
96 SYSCTL_INT(_vm, OID_AUTO, old_mlock, CTLFLAG_RWTUN, &old_mlock, 0,
97     "Do not apply RLIMIT_MEMLOCK on mlockall");
98
99 #ifdef MAP_32BIT
100 #define MAP_32BIT_MAX_ADDR      ((vm_offset_t)1 << 31)
101 #endif
102
103 #ifndef _SYS_SYSPROTO_H_
104 struct sbrk_args {
105         int incr;
106 };
107 #endif
108
109 int
110 sys_sbrk(struct thread *td, struct sbrk_args *uap)
111 {
112         /* Not yet implemented */
113         return (EOPNOTSUPP);
114 }
115
116 #ifndef _SYS_SYSPROTO_H_
117 struct sstk_args {
118         int incr;
119 };
120 #endif
121
122 int
123 sys_sstk(struct thread *td, struct sstk_args *uap)
124 {
125         /* Not yet implemented */
126         return (EOPNOTSUPP);
127 }
128
129 #if defined(COMPAT_43)
130 #ifndef _SYS_SYSPROTO_H_
131 struct getpagesize_args {
132         int dummy;
133 };
134 #endif
135
136 int
137 ogetpagesize(struct thread *td, struct getpagesize_args *uap)
138 {
139
140         td->td_retval[0] = PAGE_SIZE;
141         return (0);
142 }
143 #endif                          /* COMPAT_43 */
144
145
146 /*
147  * Memory Map (mmap) system call.  Note that the file offset
148  * and address are allowed to be NOT page aligned, though if
149  * the MAP_FIXED flag it set, both must have the same remainder
150  * modulo the PAGE_SIZE (POSIX 1003.1b).  If the address is not
151  * page-aligned, the actual mapping starts at trunc_page(addr)
152  * and the return value is adjusted up by the page offset.
153  *
154  * Generally speaking, only character devices which are themselves
155  * memory-based, such as a video framebuffer, can be mmap'd.  Otherwise
156  * there would be no cache coherency between a descriptor and a VM mapping
157  * both to the same character device.
158  */
159 #ifndef _SYS_SYSPROTO_H_
160 struct mmap_args {
161         void *addr;
162         size_t len;
163         int prot;
164         int flags;
165         int fd;
166         long pad;
167         off_t pos;
168 };
169 #endif
170
171 int
172 sys_mmap(td, uap)
173         struct thread *td;
174         struct mmap_args *uap;
175 {
176         struct file *fp;
177         vm_offset_t addr;
178         vm_size_t size, pageoff;
179         vm_prot_t cap_maxprot;
180         int align, error, flags, prot;
181         off_t pos;
182         struct vmspace *vms = td->td_proc->p_vmspace;
183         cap_rights_t rights;
184
185         addr = (vm_offset_t) uap->addr;
186         size = uap->len;
187         prot = uap->prot;
188         flags = uap->flags;
189         pos = uap->pos;
190
191         fp = NULL;
192
193         /*
194          * Ignore old flags that used to be defined but did not do anything.
195          */
196         flags &= ~(MAP_RESERVED0020 | MAP_RESERVED0040);
197         
198         /*
199          * Enforce the constraints.
200          * Mapping of length 0 is only allowed for old binaries.
201          * Anonymous mapping shall specify -1 as filedescriptor and
202          * zero position for new code. Be nice to ancient a.out
203          * binaries and correct pos for anonymous mapping, since old
204          * ld.so sometimes issues anonymous map requests with non-zero
205          * pos.
206          */
207         if (!SV_CURPROC_FLAG(SV_AOUT)) {
208                 if ((uap->len == 0 && curproc->p_osrel >= P_OSREL_MAP_ANON) ||
209                     ((flags & MAP_ANON) != 0 && (uap->fd != -1 || pos != 0)))
210                         return (EINVAL);
211         } else {
212                 if ((flags & MAP_ANON) != 0)
213                         pos = 0;
214         }
215
216         if (flags & MAP_STACK) {
217                 if ((uap->fd != -1) ||
218                     ((prot & (PROT_READ | PROT_WRITE)) != (PROT_READ | PROT_WRITE)))
219                         return (EINVAL);
220                 flags |= MAP_ANON;
221                 pos = 0;
222         }
223         if ((flags & ~(MAP_SHARED | MAP_PRIVATE | MAP_FIXED | MAP_HASSEMAPHORE |
224             MAP_STACK | MAP_NOSYNC | MAP_ANON | MAP_EXCL | MAP_NOCORE |
225             MAP_PREFAULT_READ |
226 #ifdef MAP_32BIT
227             MAP_32BIT |
228 #endif
229             MAP_ALIGNMENT_MASK)) != 0)
230                 return (EINVAL);
231         if ((flags & (MAP_EXCL | MAP_FIXED)) == MAP_EXCL)
232                 return (EINVAL);
233         if ((flags & (MAP_SHARED | MAP_PRIVATE)) == (MAP_SHARED | MAP_PRIVATE))
234                 return (EINVAL);
235         if (prot != PROT_NONE &&
236             (prot & ~(PROT_READ | PROT_WRITE | PROT_EXEC)) != 0)
237                 return (EINVAL);
238
239         /*
240          * Align the file position to a page boundary,
241          * and save its page offset component.
242          */
243         pageoff = (pos & PAGE_MASK);
244         pos -= pageoff;
245
246         /* Adjust size for rounding (on both ends). */
247         size += pageoff;                        /* low end... */
248         size = (vm_size_t) round_page(size);    /* hi end */
249
250         /* Ensure alignment is at least a page and fits in a pointer. */
251         align = flags & MAP_ALIGNMENT_MASK;
252         if (align != 0 && align != MAP_ALIGNED_SUPER &&
253             (align >> MAP_ALIGNMENT_SHIFT >= sizeof(void *) * NBBY ||
254             align >> MAP_ALIGNMENT_SHIFT < PAGE_SHIFT))
255                 return (EINVAL);
256
257         /*
258          * Check for illegal addresses.  Watch out for address wrap... Note
259          * that VM_*_ADDRESS are not constants due to casts (argh).
260          */
261         if (flags & MAP_FIXED) {
262                 /*
263                  * The specified address must have the same remainder
264                  * as the file offset taken modulo PAGE_SIZE, so it
265                  * should be aligned after adjustment by pageoff.
266                  */
267                 addr -= pageoff;
268                 if (addr & PAGE_MASK)
269                         return (EINVAL);
270
271                 /* Address range must be all in user VM space. */
272                 if (addr < vm_map_min(&vms->vm_map) ||
273                     addr + size > vm_map_max(&vms->vm_map))
274                         return (EINVAL);
275                 if (addr + size < addr)
276                         return (EINVAL);
277 #ifdef MAP_32BIT
278                 if (flags & MAP_32BIT && addr + size > MAP_32BIT_MAX_ADDR)
279                         return (EINVAL);
280         } else if (flags & MAP_32BIT) {
281                 /*
282                  * For MAP_32BIT, override the hint if it is too high and
283                  * do not bother moving the mapping past the heap (since
284                  * the heap is usually above 2GB).
285                  */
286                 if (addr + size > MAP_32BIT_MAX_ADDR)
287                         addr = 0;
288 #endif
289         } else {
290                 /*
291                  * XXX for non-fixed mappings where no hint is provided or
292                  * the hint would fall in the potential heap space,
293                  * place it after the end of the largest possible heap.
294                  *
295                  * There should really be a pmap call to determine a reasonable
296                  * location.
297                  */
298                 if (addr == 0 ||
299                     (addr >= round_page((vm_offset_t)vms->vm_taddr) &&
300                     addr < round_page((vm_offset_t)vms->vm_daddr +
301                     lim_max(td, RLIMIT_DATA))))
302                         addr = round_page((vm_offset_t)vms->vm_daddr +
303                             lim_max(td, RLIMIT_DATA));
304         }
305         if (size == 0) {
306                 /*
307                  * Return success without mapping anything for old
308                  * binaries that request a page-aligned mapping of
309                  * length 0.  For modern binaries, this function
310                  * returns an error earlier.
311                  */
312                 error = 0;
313         } else if (flags & MAP_ANON) {
314                 /*
315                  * Mapping blank space is trivial.
316                  *
317                  * This relies on VM_PROT_* matching PROT_*.
318                  */
319                 error = vm_mmap_object(&vms->vm_map, &addr, size, prot,
320                     VM_PROT_ALL, flags, NULL, pos, FALSE, td);
321         } else {
322                 /*
323                  * Mapping file, get fp for validation and don't let the
324                  * descriptor disappear on us if we block. Check capability
325                  * rights, but also return the maximum rights to be combined
326                  * with maxprot later.
327                  */
328                 cap_rights_init(&rights, CAP_MMAP);
329                 if (prot & PROT_READ)
330                         cap_rights_set(&rights, CAP_MMAP_R);
331                 if ((flags & MAP_SHARED) != 0) {
332                         if (prot & PROT_WRITE)
333                                 cap_rights_set(&rights, CAP_MMAP_W);
334                 }
335                 if (prot & PROT_EXEC)
336                         cap_rights_set(&rights, CAP_MMAP_X);
337                 error = fget_mmap(td, uap->fd, &rights, &cap_maxprot, &fp);
338                 if (error != 0)
339                         goto done;
340                 if ((flags & (MAP_SHARED | MAP_PRIVATE)) == 0 &&
341                     td->td_proc->p_osrel >= P_OSREL_MAP_FSTRICT) {
342                         error = EINVAL;
343                         goto done;
344                 }
345
346                 /* This relies on VM_PROT_* matching PROT_*. */
347                 error = fo_mmap(fp, &vms->vm_map, &addr, size, prot,
348                     cap_maxprot, flags, pos, td);
349         }
350
351         if (error == 0)
352                 td->td_retval[0] = (register_t) (addr + pageoff);
353 done:
354         if (fp)
355                 fdrop(fp, td);
356
357         return (error);
358 }
359
360 #if defined(COMPAT_FREEBSD6)
361 int
362 freebsd6_mmap(struct thread *td, struct freebsd6_mmap_args *uap)
363 {
364         struct mmap_args oargs;
365
366         oargs.addr = uap->addr;
367         oargs.len = uap->len;
368         oargs.prot = uap->prot;
369         oargs.flags = uap->flags;
370         oargs.fd = uap->fd;
371         oargs.pos = uap->pos;
372         return (sys_mmap(td, &oargs));
373 }
374 #endif
375
376 #ifdef COMPAT_43
377 #ifndef _SYS_SYSPROTO_H_
378 struct ommap_args {
379         caddr_t addr;
380         int len;
381         int prot;
382         int flags;
383         int fd;
384         long pos;
385 };
386 #endif
387 int
388 ommap(td, uap)
389         struct thread *td;
390         struct ommap_args *uap;
391 {
392         struct mmap_args nargs;
393         static const char cvtbsdprot[8] = {
394                 0,
395                 PROT_EXEC,
396                 PROT_WRITE,
397                 PROT_EXEC | PROT_WRITE,
398                 PROT_READ,
399                 PROT_EXEC | PROT_READ,
400                 PROT_WRITE | PROT_READ,
401                 PROT_EXEC | PROT_WRITE | PROT_READ,
402         };
403
404 #define OMAP_ANON       0x0002
405 #define OMAP_COPY       0x0020
406 #define OMAP_SHARED     0x0010
407 #define OMAP_FIXED      0x0100
408
409         nargs.addr = uap->addr;
410         nargs.len = uap->len;
411         nargs.prot = cvtbsdprot[uap->prot & 0x7];
412 #ifdef COMPAT_FREEBSD32
413 #if defined(__amd64__)
414         if (i386_read_exec && SV_PROC_FLAG(td->td_proc, SV_ILP32) &&
415             nargs.prot != 0)
416                 nargs.prot |= PROT_EXEC;
417 #endif
418 #endif
419         nargs.flags = 0;
420         if (uap->flags & OMAP_ANON)
421                 nargs.flags |= MAP_ANON;
422         if (uap->flags & OMAP_COPY)
423                 nargs.flags |= MAP_COPY;
424         if (uap->flags & OMAP_SHARED)
425                 nargs.flags |= MAP_SHARED;
426         else
427                 nargs.flags |= MAP_PRIVATE;
428         if (uap->flags & OMAP_FIXED)
429                 nargs.flags |= MAP_FIXED;
430         nargs.fd = uap->fd;
431         nargs.pos = uap->pos;
432         return (sys_mmap(td, &nargs));
433 }
434 #endif                          /* COMPAT_43 */
435
436
437 #ifndef _SYS_SYSPROTO_H_
438 struct msync_args {
439         void *addr;
440         size_t len;
441         int flags;
442 };
443 #endif
444 int
445 sys_msync(td, uap)
446         struct thread *td;
447         struct msync_args *uap;
448 {
449         vm_offset_t addr;
450         vm_size_t size, pageoff;
451         int flags;
452         vm_map_t map;
453         int rv;
454
455         addr = (vm_offset_t) uap->addr;
456         size = uap->len;
457         flags = uap->flags;
458
459         pageoff = (addr & PAGE_MASK);
460         addr -= pageoff;
461         size += pageoff;
462         size = (vm_size_t) round_page(size);
463         if (addr + size < addr)
464                 return (EINVAL);
465
466         if ((flags & (MS_ASYNC|MS_INVALIDATE)) == (MS_ASYNC|MS_INVALIDATE))
467                 return (EINVAL);
468
469         map = &td->td_proc->p_vmspace->vm_map;
470
471         /*
472          * Clean the pages and interpret the return value.
473          */
474         rv = vm_map_sync(map, addr, addr + size, (flags & MS_ASYNC) == 0,
475             (flags & MS_INVALIDATE) != 0);
476         switch (rv) {
477         case KERN_SUCCESS:
478                 return (0);
479         case KERN_INVALID_ADDRESS:
480                 return (ENOMEM);
481         case KERN_INVALID_ARGUMENT:
482                 return (EBUSY);
483         case KERN_FAILURE:
484                 return (EIO);
485         default:
486                 return (EINVAL);
487         }
488 }
489
490 #ifndef _SYS_SYSPROTO_H_
491 struct munmap_args {
492         void *addr;
493         size_t len;
494 };
495 #endif
496 int
497 sys_munmap(td, uap)
498         struct thread *td;
499         struct munmap_args *uap;
500 {
501 #ifdef HWPMC_HOOKS
502         struct pmckern_map_out pkm;
503         vm_map_entry_t entry;
504 #endif
505         vm_offset_t addr;
506         vm_size_t size, pageoff;
507         vm_map_t map;
508
509         addr = (vm_offset_t) uap->addr;
510         size = uap->len;
511         if (size == 0)
512                 return (EINVAL);
513
514         pageoff = (addr & PAGE_MASK);
515         addr -= pageoff;
516         size += pageoff;
517         size = (vm_size_t) round_page(size);
518         if (addr + size < addr)
519                 return (EINVAL);
520
521         /*
522          * Check for illegal addresses.  Watch out for address wrap...
523          */
524         map = &td->td_proc->p_vmspace->vm_map;
525         if (addr < vm_map_min(map) || addr + size > vm_map_max(map))
526                 return (EINVAL);
527         vm_map_lock(map);
528 #ifdef HWPMC_HOOKS
529         /*
530          * Inform hwpmc if the address range being unmapped contains
531          * an executable region.
532          */
533         pkm.pm_address = (uintptr_t) NULL;
534         if (vm_map_lookup_entry(map, addr, &entry)) {
535                 for (;
536                      entry != &map->header && entry->start < addr + size;
537                      entry = entry->next) {
538                         if (vm_map_check_protection(map, entry->start,
539                                 entry->end, VM_PROT_EXECUTE) == TRUE) {
540                                 pkm.pm_address = (uintptr_t) addr;
541                                 pkm.pm_size = (size_t) size;
542                                 break;
543                         }
544                 }
545         }
546 #endif
547         vm_map_delete(map, addr, addr + size);
548
549 #ifdef HWPMC_HOOKS
550         /* downgrade the lock to prevent a LOR with the pmc-sx lock */
551         vm_map_lock_downgrade(map);
552         if (pkm.pm_address != (uintptr_t) NULL)
553                 PMC_CALL_HOOK(td, PMC_FN_MUNMAP, (void *) &pkm);
554         vm_map_unlock_read(map);
555 #else
556         vm_map_unlock(map);
557 #endif
558         /* vm_map_delete returns nothing but KERN_SUCCESS anyway */
559         return (0);
560 }
561
562 #ifndef _SYS_SYSPROTO_H_
563 struct mprotect_args {
564         const void *addr;
565         size_t len;
566         int prot;
567 };
568 #endif
569 int
570 sys_mprotect(td, uap)
571         struct thread *td;
572         struct mprotect_args *uap;
573 {
574         vm_offset_t addr;
575         vm_size_t size, pageoff;
576         vm_prot_t prot;
577
578         addr = (vm_offset_t) uap->addr;
579         size = uap->len;
580         prot = uap->prot & VM_PROT_ALL;
581
582         pageoff = (addr & PAGE_MASK);
583         addr -= pageoff;
584         size += pageoff;
585         size = (vm_size_t) round_page(size);
586         if (addr + size < addr)
587                 return (EINVAL);
588
589         switch (vm_map_protect(&td->td_proc->p_vmspace->vm_map, addr,
590             addr + size, prot, FALSE)) {
591         case KERN_SUCCESS:
592                 return (0);
593         case KERN_PROTECTION_FAILURE:
594                 return (EACCES);
595         case KERN_RESOURCE_SHORTAGE:
596                 return (ENOMEM);
597         }
598         return (EINVAL);
599 }
600
601 #ifndef _SYS_SYSPROTO_H_
602 struct minherit_args {
603         void *addr;
604         size_t len;
605         int inherit;
606 };
607 #endif
608 int
609 sys_minherit(struct thread *td, struct minherit_args *uap)
610 {
611         vm_offset_t addr;
612         vm_size_t size, pageoff;
613         vm_inherit_t inherit;
614
615         addr = (vm_offset_t)uap->addr;
616         size = uap->len;
617         inherit = uap->inherit;
618
619         pageoff = (addr & PAGE_MASK);
620         addr -= pageoff;
621         size += pageoff;
622         size = (vm_size_t) round_page(size);
623         if (addr + size < addr)
624                 return (EINVAL);
625
626         switch (vm_map_inherit(&td->td_proc->p_vmspace->vm_map, addr,
627             addr + size, inherit)) {
628         case KERN_SUCCESS:
629                 return (0);
630         case KERN_PROTECTION_FAILURE:
631                 return (EACCES);
632         }
633         return (EINVAL);
634 }
635
636 #ifndef _SYS_SYSPROTO_H_
637 struct madvise_args {
638         void *addr;
639         size_t len;
640         int behav;
641 };
642 #endif
643
644 int
645 sys_madvise(struct thread *td, struct madvise_args *uap)
646 {
647         vm_offset_t start, end;
648         vm_map_t map;
649         int flags;
650
651         /*
652          * Check for our special case, advising the swap pager we are
653          * "immortal."
654          */
655         if (uap->behav == MADV_PROTECT) {
656                 flags = PPROT_SET;
657                 return (kern_procctl(td, P_PID, td->td_proc->p_pid,
658                     PROC_SPROTECT, &flags));
659         }
660
661         /*
662          * Check for illegal behavior
663          */
664         if (uap->behav < 0 || uap->behav > MADV_CORE)
665                 return (EINVAL);
666         /*
667          * Check for illegal addresses.  Watch out for address wrap... Note
668          * that VM_*_ADDRESS are not constants due to casts (argh).
669          */
670         map = &td->td_proc->p_vmspace->vm_map;
671         if ((vm_offset_t)uap->addr < vm_map_min(map) ||
672             (vm_offset_t)uap->addr + uap->len > vm_map_max(map))
673                 return (EINVAL);
674         if (((vm_offset_t) uap->addr + uap->len) < (vm_offset_t) uap->addr)
675                 return (EINVAL);
676
677         /*
678          * Since this routine is only advisory, we default to conservative
679          * behavior.
680          */
681         start = trunc_page((vm_offset_t) uap->addr);
682         end = round_page((vm_offset_t) uap->addr + uap->len);
683
684         if (vm_map_madvise(map, start, end, uap->behav))
685                 return (EINVAL);
686         return (0);
687 }
688
689 #ifndef _SYS_SYSPROTO_H_
690 struct mincore_args {
691         const void *addr;
692         size_t len;
693         char *vec;
694 };
695 #endif
696
697 int
698 sys_mincore(struct thread *td, struct mincore_args *uap)
699 {
700         vm_offset_t addr, first_addr;
701         vm_offset_t end, cend;
702         pmap_t pmap;
703         vm_map_t map;
704         char *vec;
705         int error = 0;
706         int vecindex, lastvecindex;
707         vm_map_entry_t current;
708         vm_map_entry_t entry;
709         vm_object_t object;
710         vm_paddr_t locked_pa;
711         vm_page_t m;
712         vm_pindex_t pindex;
713         int mincoreinfo;
714         unsigned int timestamp;
715         boolean_t locked;
716
717         /*
718          * Make sure that the addresses presented are valid for user
719          * mode.
720          */
721         first_addr = addr = trunc_page((vm_offset_t) uap->addr);
722         end = addr + (vm_size_t)round_page(uap->len);
723         map = &td->td_proc->p_vmspace->vm_map;
724         if (end > vm_map_max(map) || end < addr)
725                 return (ENOMEM);
726
727         /*
728          * Address of byte vector
729          */
730         vec = uap->vec;
731
732         pmap = vmspace_pmap(td->td_proc->p_vmspace);
733
734         vm_map_lock_read(map);
735 RestartScan:
736         timestamp = map->timestamp;
737
738         if (!vm_map_lookup_entry(map, addr, &entry)) {
739                 vm_map_unlock_read(map);
740                 return (ENOMEM);
741         }
742
743         /*
744          * Do this on a map entry basis so that if the pages are not
745          * in the current processes address space, we can easily look
746          * up the pages elsewhere.
747          */
748         lastvecindex = -1;
749         for (current = entry;
750             (current != &map->header) && (current->start < end);
751             current = current->next) {
752
753                 /*
754                  * check for contiguity
755                  */
756                 if (current->end < end &&
757                     (entry->next == &map->header ||
758                      current->next->start > current->end)) {
759                         vm_map_unlock_read(map);
760                         return (ENOMEM);
761                 }
762
763                 /*
764                  * ignore submaps (for now) or null objects
765                  */
766                 if ((current->eflags & MAP_ENTRY_IS_SUB_MAP) ||
767                         current->object.vm_object == NULL)
768                         continue;
769
770                 /*
771                  * limit this scan to the current map entry and the
772                  * limits for the mincore call
773                  */
774                 if (addr < current->start)
775                         addr = current->start;
776                 cend = current->end;
777                 if (cend > end)
778                         cend = end;
779
780                 /*
781                  * scan this entry one page at a time
782                  */
783                 while (addr < cend) {
784                         /*
785                          * Check pmap first, it is likely faster, also
786                          * it can provide info as to whether we are the
787                          * one referencing or modifying the page.
788                          */
789                         object = NULL;
790                         locked_pa = 0;
791                 retry:
792                         m = NULL;
793                         mincoreinfo = pmap_mincore(pmap, addr, &locked_pa);
794                         if (locked_pa != 0) {
795                                 /*
796                                  * The page is mapped by this process but not
797                                  * both accessed and modified.  It is also
798                                  * managed.  Acquire the object lock so that
799                                  * other mappings might be examined.
800                                  */
801                                 m = PHYS_TO_VM_PAGE(locked_pa);
802                                 if (m->object != object) {
803                                         if (object != NULL)
804                                                 VM_OBJECT_WUNLOCK(object);
805                                         object = m->object;
806                                         locked = VM_OBJECT_TRYWLOCK(object);
807                                         vm_page_unlock(m);
808                                         if (!locked) {
809                                                 VM_OBJECT_WLOCK(object);
810                                                 vm_page_lock(m);
811                                                 goto retry;
812                                         }
813                                 } else
814                                         vm_page_unlock(m);
815                                 KASSERT(m->valid == VM_PAGE_BITS_ALL,
816                                     ("mincore: page %p is mapped but invalid",
817                                     m));
818                         } else if (mincoreinfo == 0) {
819                                 /*
820                                  * The page is not mapped by this process.  If
821                                  * the object implements managed pages, then
822                                  * determine if the page is resident so that
823                                  * the mappings might be examined.
824                                  */
825                                 if (current->object.vm_object != object) {
826                                         if (object != NULL)
827                                                 VM_OBJECT_WUNLOCK(object);
828                                         object = current->object.vm_object;
829                                         VM_OBJECT_WLOCK(object);
830                                 }
831                                 if (object->type == OBJT_DEFAULT ||
832                                     object->type == OBJT_SWAP ||
833                                     object->type == OBJT_VNODE) {
834                                         pindex = OFF_TO_IDX(current->offset +
835                                             (addr - current->start));
836                                         m = vm_page_lookup(object, pindex);
837                                         if (m == NULL &&
838                                             vm_page_is_cached(object, pindex))
839                                                 mincoreinfo = MINCORE_INCORE;
840                                         if (m != NULL && m->valid == 0)
841                                                 m = NULL;
842                                         if (m != NULL)
843                                                 mincoreinfo = MINCORE_INCORE;
844                                 }
845                         }
846                         if (m != NULL) {
847                                 /* Examine other mappings to the page. */
848                                 if (m->dirty == 0 && pmap_is_modified(m))
849                                         vm_page_dirty(m);
850                                 if (m->dirty != 0)
851                                         mincoreinfo |= MINCORE_MODIFIED_OTHER;
852                                 /*
853                                  * The first test for PGA_REFERENCED is an
854                                  * optimization.  The second test is
855                                  * required because a concurrent pmap
856                                  * operation could clear the last reference
857                                  * and set PGA_REFERENCED before the call to
858                                  * pmap_is_referenced(). 
859                                  */
860                                 if ((m->aflags & PGA_REFERENCED) != 0 ||
861                                     pmap_is_referenced(m) ||
862                                     (m->aflags & PGA_REFERENCED) != 0)
863                                         mincoreinfo |= MINCORE_REFERENCED_OTHER;
864                         }
865                         if (object != NULL)
866                                 VM_OBJECT_WUNLOCK(object);
867
868                         /*
869                          * subyte may page fault.  In case it needs to modify
870                          * the map, we release the lock.
871                          */
872                         vm_map_unlock_read(map);
873
874                         /*
875                          * calculate index into user supplied byte vector
876                          */
877                         vecindex = OFF_TO_IDX(addr - first_addr);
878
879                         /*
880                          * If we have skipped map entries, we need to make sure that
881                          * the byte vector is zeroed for those skipped entries.
882                          */
883                         while ((lastvecindex + 1) < vecindex) {
884                                 ++lastvecindex;
885                                 error = subyte(vec + lastvecindex, 0);
886                                 if (error) {
887                                         error = EFAULT;
888                                         goto done2;
889                                 }
890                         }
891
892                         /*
893                          * Pass the page information to the user
894                          */
895                         error = subyte(vec + vecindex, mincoreinfo);
896                         if (error) {
897                                 error = EFAULT;
898                                 goto done2;
899                         }
900
901                         /*
902                          * If the map has changed, due to the subyte, the previous
903                          * output may be invalid.
904                          */
905                         vm_map_lock_read(map);
906                         if (timestamp != map->timestamp)
907                                 goto RestartScan;
908
909                         lastvecindex = vecindex;
910                         addr += PAGE_SIZE;
911                 }
912         }
913
914         /*
915          * subyte may page fault.  In case it needs to modify
916          * the map, we release the lock.
917          */
918         vm_map_unlock_read(map);
919
920         /*
921          * Zero the last entries in the byte vector.
922          */
923         vecindex = OFF_TO_IDX(end - first_addr);
924         while ((lastvecindex + 1) < vecindex) {
925                 ++lastvecindex;
926                 error = subyte(vec + lastvecindex, 0);
927                 if (error) {
928                         error = EFAULT;
929                         goto done2;
930                 }
931         }
932
933         /*
934          * If the map has changed, due to the subyte, the previous
935          * output may be invalid.
936          */
937         vm_map_lock_read(map);
938         if (timestamp != map->timestamp)
939                 goto RestartScan;
940         vm_map_unlock_read(map);
941 done2:
942         return (error);
943 }
944
945 #ifndef _SYS_SYSPROTO_H_
946 struct mlock_args {
947         const void *addr;
948         size_t len;
949 };
950 #endif
951 int
952 sys_mlock(struct thread *td, struct mlock_args *uap)
953 {
954
955         return (vm_mlock(td->td_proc, td->td_ucred, uap->addr, uap->len));
956 }
957
958 int
959 vm_mlock(struct proc *proc, struct ucred *cred, const void *addr0, size_t len)
960 {
961         vm_offset_t addr, end, last, start;
962         vm_size_t npages, size;
963         vm_map_t map;
964         unsigned long nsize;
965         int error;
966
967         error = priv_check_cred(cred, PRIV_VM_MLOCK, 0);
968         if (error)
969                 return (error);
970         addr = (vm_offset_t)addr0;
971         size = len;
972         last = addr + size;
973         start = trunc_page(addr);
974         end = round_page(last);
975         if (last < addr || end < addr)
976                 return (EINVAL);
977         npages = atop(end - start);
978         if (npages > vm_page_max_wired)
979                 return (ENOMEM);
980         map = &proc->p_vmspace->vm_map;
981         PROC_LOCK(proc);
982         nsize = ptoa(npages + pmap_wired_count(map->pmap));
983         if (nsize > lim_cur_proc(proc, RLIMIT_MEMLOCK)) {
984                 PROC_UNLOCK(proc);
985                 return (ENOMEM);
986         }
987         PROC_UNLOCK(proc);
988         if (npages + vm_cnt.v_wire_count > vm_page_max_wired)
989                 return (EAGAIN);
990 #ifdef RACCT
991         if (racct_enable) {
992                 PROC_LOCK(proc);
993                 error = racct_set(proc, RACCT_MEMLOCK, nsize);
994                 PROC_UNLOCK(proc);
995                 if (error != 0)
996                         return (ENOMEM);
997         }
998 #endif
999         error = vm_map_wire(map, start, end,
1000             VM_MAP_WIRE_USER | VM_MAP_WIRE_NOHOLES);
1001 #ifdef RACCT
1002         if (racct_enable && error != KERN_SUCCESS) {
1003                 PROC_LOCK(proc);
1004                 racct_set(proc, RACCT_MEMLOCK,
1005                     ptoa(pmap_wired_count(map->pmap)));
1006                 PROC_UNLOCK(proc);
1007         }
1008 #endif
1009         return (error == KERN_SUCCESS ? 0 : ENOMEM);
1010 }
1011
1012 #ifndef _SYS_SYSPROTO_H_
1013 struct mlockall_args {
1014         int     how;
1015 };
1016 #endif
1017
1018 int
1019 sys_mlockall(struct thread *td, struct mlockall_args *uap)
1020 {
1021         vm_map_t map;
1022         int error;
1023
1024         map = &td->td_proc->p_vmspace->vm_map;
1025         error = priv_check(td, PRIV_VM_MLOCK);
1026         if (error)
1027                 return (error);
1028
1029         if ((uap->how == 0) || ((uap->how & ~(MCL_CURRENT|MCL_FUTURE)) != 0))
1030                 return (EINVAL);
1031
1032         /*
1033          * If wiring all pages in the process would cause it to exceed
1034          * a hard resource limit, return ENOMEM.
1035          */
1036         if (!old_mlock && uap->how & MCL_CURRENT) {
1037                 PROC_LOCK(td->td_proc);
1038                 if (map->size > lim_cur(td, RLIMIT_MEMLOCK)) {
1039                         PROC_UNLOCK(td->td_proc);
1040                         return (ENOMEM);
1041                 }
1042                 PROC_UNLOCK(td->td_proc);
1043         }
1044 #ifdef RACCT
1045         if (racct_enable) {
1046                 PROC_LOCK(td->td_proc);
1047                 error = racct_set(td->td_proc, RACCT_MEMLOCK, map->size);
1048                 PROC_UNLOCK(td->td_proc);
1049                 if (error != 0)
1050                         return (ENOMEM);
1051         }
1052 #endif
1053
1054         if (uap->how & MCL_FUTURE) {
1055                 vm_map_lock(map);
1056                 vm_map_modflags(map, MAP_WIREFUTURE, 0);
1057                 vm_map_unlock(map);
1058                 error = 0;
1059         }
1060
1061         if (uap->how & MCL_CURRENT) {
1062                 /*
1063                  * P1003.1-2001 mandates that all currently mapped pages
1064                  * will be memory resident and locked (wired) upon return
1065                  * from mlockall(). vm_map_wire() will wire pages, by
1066                  * calling vm_fault_wire() for each page in the region.
1067                  */
1068                 error = vm_map_wire(map, vm_map_min(map), vm_map_max(map),
1069                     VM_MAP_WIRE_USER|VM_MAP_WIRE_HOLESOK);
1070                 error = (error == KERN_SUCCESS ? 0 : EAGAIN);
1071         }
1072 #ifdef RACCT
1073         if (racct_enable && error != KERN_SUCCESS) {
1074                 PROC_LOCK(td->td_proc);
1075                 racct_set(td->td_proc, RACCT_MEMLOCK,
1076                     ptoa(pmap_wired_count(map->pmap)));
1077                 PROC_UNLOCK(td->td_proc);
1078         }
1079 #endif
1080
1081         return (error);
1082 }
1083
1084 #ifndef _SYS_SYSPROTO_H_
1085 struct munlockall_args {
1086         register_t dummy;
1087 };
1088 #endif
1089
1090 int
1091 sys_munlockall(struct thread *td, struct munlockall_args *uap)
1092 {
1093         vm_map_t map;
1094         int error;
1095
1096         map = &td->td_proc->p_vmspace->vm_map;
1097         error = priv_check(td, PRIV_VM_MUNLOCK);
1098         if (error)
1099                 return (error);
1100
1101         /* Clear the MAP_WIREFUTURE flag from this vm_map. */
1102         vm_map_lock(map);
1103         vm_map_modflags(map, 0, MAP_WIREFUTURE);
1104         vm_map_unlock(map);
1105
1106         /* Forcibly unwire all pages. */
1107         error = vm_map_unwire(map, vm_map_min(map), vm_map_max(map),
1108             VM_MAP_WIRE_USER|VM_MAP_WIRE_HOLESOK);
1109 #ifdef RACCT
1110         if (racct_enable && error == KERN_SUCCESS) {
1111                 PROC_LOCK(td->td_proc);
1112                 racct_set(td->td_proc, RACCT_MEMLOCK, 0);
1113                 PROC_UNLOCK(td->td_proc);
1114         }
1115 #endif
1116
1117         return (error);
1118 }
1119
1120 #ifndef _SYS_SYSPROTO_H_
1121 struct munlock_args {
1122         const void *addr;
1123         size_t len;
1124 };
1125 #endif
1126 int
1127 sys_munlock(td, uap)
1128         struct thread *td;
1129         struct munlock_args *uap;
1130 {
1131         vm_offset_t addr, end, last, start;
1132         vm_size_t size;
1133 #ifdef RACCT
1134         vm_map_t map;
1135 #endif
1136         int error;
1137
1138         error = priv_check(td, PRIV_VM_MUNLOCK);
1139         if (error)
1140                 return (error);
1141         addr = (vm_offset_t)uap->addr;
1142         size = uap->len;
1143         last = addr + size;
1144         start = trunc_page(addr);
1145         end = round_page(last);
1146         if (last < addr || end < addr)
1147                 return (EINVAL);
1148         error = vm_map_unwire(&td->td_proc->p_vmspace->vm_map, start, end,
1149             VM_MAP_WIRE_USER | VM_MAP_WIRE_NOHOLES);
1150 #ifdef RACCT
1151         if (racct_enable && error == KERN_SUCCESS) {
1152                 PROC_LOCK(td->td_proc);
1153                 map = &td->td_proc->p_vmspace->vm_map;
1154                 racct_set(td->td_proc, RACCT_MEMLOCK,
1155                     ptoa(pmap_wired_count(map->pmap)));
1156                 PROC_UNLOCK(td->td_proc);
1157         }
1158 #endif
1159         return (error == KERN_SUCCESS ? 0 : ENOMEM);
1160 }
1161
1162 /*
1163  * vm_mmap_vnode()
1164  *
1165  * Helper function for vm_mmap.  Perform sanity check specific for mmap
1166  * operations on vnodes.
1167  */
1168 int
1169 vm_mmap_vnode(struct thread *td, vm_size_t objsize,
1170     vm_prot_t prot, vm_prot_t *maxprotp, int *flagsp,
1171     struct vnode *vp, vm_ooffset_t *foffp, vm_object_t *objp,
1172     boolean_t *writecounted)
1173 {
1174         struct vattr va;
1175         vm_object_t obj;
1176         vm_offset_t foff;
1177         struct ucred *cred;
1178         int error, flags, locktype;
1179
1180         cred = td->td_ucred;
1181         if ((*maxprotp & VM_PROT_WRITE) && (*flagsp & MAP_SHARED))
1182                 locktype = LK_EXCLUSIVE;
1183         else
1184                 locktype = LK_SHARED;
1185         if ((error = vget(vp, locktype, td)) != 0)
1186                 return (error);
1187         foff = *foffp;
1188         flags = *flagsp;
1189         obj = vp->v_object;
1190         if (vp->v_type == VREG) {
1191                 /*
1192                  * Get the proper underlying object
1193                  */
1194                 if (obj == NULL) {
1195                         error = EINVAL;
1196                         goto done;
1197                 }
1198                 if (obj->type == OBJT_VNODE && obj->handle != vp) {
1199                         vput(vp);
1200                         vp = (struct vnode *)obj->handle;
1201                         /*
1202                          * Bypass filesystems obey the mpsafety of the
1203                          * underlying fs.  Tmpfs never bypasses.
1204                          */
1205                         error = vget(vp, locktype, td);
1206                         if (error != 0)
1207                                 return (error);
1208                 }
1209                 if (locktype == LK_EXCLUSIVE) {
1210                         *writecounted = TRUE;
1211                         vnode_pager_update_writecount(obj, 0, objsize);
1212                 }
1213         } else {
1214                 error = EINVAL;
1215                 goto done;
1216         }
1217         if ((error = VOP_GETATTR(vp, &va, cred)))
1218                 goto done;
1219 #ifdef MAC
1220         /* This relies on VM_PROT_* matching PROT_*. */
1221         error = mac_vnode_check_mmap(cred, vp, (int)prot, flags);
1222         if (error != 0)
1223                 goto done;
1224 #endif
1225         if ((flags & MAP_SHARED) != 0) {
1226                 if ((va.va_flags & (SF_SNAPSHOT|IMMUTABLE|APPEND)) != 0) {
1227                         if (prot & VM_PROT_WRITE) {
1228                                 error = EPERM;
1229                                 goto done;
1230                         }
1231                         *maxprotp &= ~VM_PROT_WRITE;
1232                 }
1233         }
1234         /*
1235          * If it is a regular file without any references
1236          * we do not need to sync it.
1237          * Adjust object size to be the size of actual file.
1238          */
1239         objsize = round_page(va.va_size);
1240         if (va.va_nlink == 0)
1241                 flags |= MAP_NOSYNC;
1242         if (obj->type == OBJT_VNODE) {
1243                 obj = vm_pager_allocate(OBJT_VNODE, vp, objsize, prot, foff,
1244                     cred);
1245                 if (obj == NULL) {
1246                         error = ENOMEM;
1247                         goto done;
1248                 }
1249         } else {
1250                 KASSERT(obj->type == OBJT_DEFAULT || obj->type == OBJT_SWAP,
1251                     ("wrong object type"));
1252                 VM_OBJECT_WLOCK(obj);
1253                 vm_object_reference_locked(obj);
1254 #if VM_NRESERVLEVEL > 0
1255                 vm_object_color(obj, 0);
1256 #endif
1257                 VM_OBJECT_WUNLOCK(obj);
1258         }
1259         *objp = obj;
1260         *flagsp = flags;
1261
1262         vfs_mark_atime(vp, cred);
1263
1264 done:
1265         if (error != 0 && *writecounted) {
1266                 *writecounted = FALSE;
1267                 vnode_pager_update_writecount(obj, objsize, 0);
1268         }
1269         vput(vp);
1270         return (error);
1271 }
1272
1273 /*
1274  * vm_mmap_cdev()
1275  *
1276  * Helper function for vm_mmap.  Perform sanity check specific for mmap
1277  * operations on cdevs.
1278  */
1279 int
1280 vm_mmap_cdev(struct thread *td, vm_size_t objsize, vm_prot_t prot,
1281     vm_prot_t *maxprotp, int *flagsp, struct cdev *cdev, struct cdevsw *dsw,
1282     vm_ooffset_t *foff, vm_object_t *objp)
1283 {
1284         vm_object_t obj;
1285         int error, flags;
1286
1287         flags = *flagsp;
1288
1289         if (dsw->d_flags & D_MMAP_ANON) {
1290                 *objp = NULL;
1291                 *foff = 0;
1292                 *maxprotp = VM_PROT_ALL;
1293                 *flagsp |= MAP_ANON;
1294                 return (0);
1295         }
1296         /*
1297          * cdevs do not provide private mappings of any kind.
1298          */
1299         if ((*maxprotp & VM_PROT_WRITE) == 0 &&
1300             (prot & VM_PROT_WRITE) != 0)
1301                 return (EACCES);
1302         if (flags & (MAP_PRIVATE|MAP_COPY))
1303                 return (EINVAL);
1304         /*
1305          * Force device mappings to be shared.
1306          */
1307         flags |= MAP_SHARED;
1308 #ifdef MAC_XXX
1309         error = mac_cdev_check_mmap(td->td_ucred, cdev, (int)prot);
1310         if (error != 0)
1311                 return (error);
1312 #endif
1313         /*
1314          * First, try d_mmap_single().  If that is not implemented
1315          * (returns ENODEV), fall back to using the device pager.
1316          * Note that d_mmap_single() must return a reference to the
1317          * object (it needs to bump the reference count of the object
1318          * it returns somehow).
1319          *
1320          * XXX assumes VM_PROT_* == PROT_*
1321          */
1322         error = dsw->d_mmap_single(cdev, foff, objsize, objp, (int)prot);
1323         if (error != ENODEV)
1324                 return (error);
1325         obj = vm_pager_allocate(OBJT_DEVICE, cdev, objsize, prot, *foff,
1326             td->td_ucred);
1327         if (obj == NULL)
1328                 return (EINVAL);
1329         *objp = obj;
1330         *flagsp = flags;
1331         return (0);
1332 }
1333
1334 /*
1335  * vm_mmap()
1336  *
1337  * Internal version of mmap used by exec, sys5 shared memory, and
1338  * various device drivers.  Handle is either a vnode pointer, a
1339  * character device, or NULL for MAP_ANON.
1340  */
1341 int
1342 vm_mmap(vm_map_t map, vm_offset_t *addr, vm_size_t size, vm_prot_t prot,
1343         vm_prot_t maxprot, int flags,
1344         objtype_t handle_type, void *handle,
1345         vm_ooffset_t foff)
1346 {
1347         vm_object_t object;
1348         struct thread *td = curthread;
1349         int error;
1350         boolean_t writecounted;
1351
1352         if (size == 0)
1353                 return (EINVAL);
1354
1355         size = round_page(size);
1356         object = NULL;
1357         writecounted = FALSE;
1358
1359         /*
1360          * Lookup/allocate object.
1361          */
1362         switch (handle_type) {
1363         case OBJT_DEVICE: {
1364                 struct cdevsw *dsw;
1365                 struct cdev *cdev;
1366                 int ref;
1367
1368                 cdev = handle;
1369                 dsw = dev_refthread(cdev, &ref);
1370                 if (dsw == NULL)
1371                         return (ENXIO);
1372                 error = vm_mmap_cdev(td, size, prot, &maxprot, &flags, cdev,
1373                     dsw, &foff, &object);
1374                 dev_relthread(cdev, ref);
1375                 break;
1376         }
1377         case OBJT_VNODE:
1378                 error = vm_mmap_vnode(td, size, prot, &maxprot, &flags,
1379                     handle, &foff, &object, &writecounted);
1380                 break;
1381         case OBJT_DEFAULT:
1382                 if (handle == NULL) {
1383                         error = 0;
1384                         break;
1385                 }
1386                 /* FALLTHROUGH */
1387         default:
1388                 error = EINVAL;
1389                 break;
1390         }
1391         if (error)
1392                 return (error);
1393
1394         error = vm_mmap_object(map, addr, size, prot, maxprot, flags, object,
1395             foff, writecounted, td);
1396         if (error != 0 && object != NULL) {
1397                 /*
1398                  * If this mapping was accounted for in the vnode's
1399                  * writecount, then undo that now.
1400                  */
1401                 if (writecounted)
1402                         vnode_pager_release_writecount(object, 0, size);
1403                 vm_object_deallocate(object);
1404         }
1405         return (error);
1406 }
1407
1408 /*
1409  * Internal version of mmap that maps a specific VM object into an
1410  * map.  Called by mmap for MAP_ANON, vm_mmap, shm_mmap, and vn_mmap.
1411  */
1412 int
1413 vm_mmap_object(vm_map_t map, vm_offset_t *addr, vm_size_t size, vm_prot_t prot,
1414     vm_prot_t maxprot, int flags, vm_object_t object, vm_ooffset_t foff,
1415     boolean_t writecounted, struct thread *td)
1416 {
1417         boolean_t fitit;
1418         int docow, error, findspace, rv;
1419
1420         if (map == &td->td_proc->p_vmspace->vm_map) {
1421                 PROC_LOCK(td->td_proc);
1422                 if (map->size + size > lim_cur_proc(td->td_proc, RLIMIT_VMEM)) {
1423                         PROC_UNLOCK(td->td_proc);
1424                         return (ENOMEM);
1425                 }
1426                 if (racct_set(td->td_proc, RACCT_VMEM, map->size + size)) {
1427                         PROC_UNLOCK(td->td_proc);
1428                         return (ENOMEM);
1429                 }
1430                 if (!old_mlock && map->flags & MAP_WIREFUTURE) {
1431                         if (ptoa(pmap_wired_count(map->pmap)) + size >
1432                             lim_cur_proc(td->td_proc, RLIMIT_MEMLOCK)) {
1433                                 racct_set_force(td->td_proc, RACCT_VMEM,
1434                                     map->size);
1435                                 PROC_UNLOCK(td->td_proc);
1436                                 return (ENOMEM);
1437                         }
1438                         error = racct_set(td->td_proc, RACCT_MEMLOCK,
1439                             ptoa(pmap_wired_count(map->pmap)) + size);
1440                         if (error != 0) {
1441                                 racct_set_force(td->td_proc, RACCT_VMEM,
1442                                     map->size);
1443                                 PROC_UNLOCK(td->td_proc);
1444                                 return (error);
1445                         }
1446                 }
1447                 PROC_UNLOCK(td->td_proc);
1448         }
1449
1450         /*
1451          * We currently can only deal with page aligned file offsets.
1452          * The mmap() system call already enforces this by subtracting
1453          * the page offset from the file offset, but checking here
1454          * catches errors in device drivers (e.g. d_single_mmap()
1455          * callbacks) and other internal mapping requests (such as in
1456          * exec).
1457          */
1458         if (foff & PAGE_MASK)
1459                 return (EINVAL);
1460
1461         if ((flags & MAP_FIXED) == 0) {
1462                 fitit = TRUE;
1463                 *addr = round_page(*addr);
1464         } else {
1465                 if (*addr != trunc_page(*addr))
1466                         return (EINVAL);
1467                 fitit = FALSE;
1468         }
1469
1470         if (flags & MAP_ANON) {
1471                 if (object != NULL || foff != 0)
1472                         return (EINVAL);
1473                 docow = 0;
1474         } else if (flags & MAP_PREFAULT_READ)
1475                 docow = MAP_PREFAULT;
1476         else
1477                 docow = MAP_PREFAULT_PARTIAL;
1478
1479         if ((flags & (MAP_ANON|MAP_SHARED)) == 0)
1480                 docow |= MAP_COPY_ON_WRITE;
1481         if (flags & MAP_NOSYNC)
1482                 docow |= MAP_DISABLE_SYNCER;
1483         if (flags & MAP_NOCORE)
1484                 docow |= MAP_DISABLE_COREDUMP;
1485         /* Shared memory is also shared with children. */
1486         if (flags & MAP_SHARED)
1487                 docow |= MAP_INHERIT_SHARE;
1488         if (writecounted)
1489                 docow |= MAP_VN_WRITECOUNT;
1490         if (flags & MAP_STACK) {
1491                 if (object != NULL)
1492                         return (EINVAL);
1493                 docow |= MAP_STACK_GROWS_DOWN;
1494         }
1495         if ((flags & MAP_EXCL) != 0)
1496                 docow |= MAP_CHECK_EXCL;
1497
1498         if (fitit) {
1499                 if ((flags & MAP_ALIGNMENT_MASK) == MAP_ALIGNED_SUPER)
1500                         findspace = VMFS_SUPER_SPACE;
1501                 else if ((flags & MAP_ALIGNMENT_MASK) != 0)
1502                         findspace = VMFS_ALIGNED_SPACE(flags >>
1503                             MAP_ALIGNMENT_SHIFT);
1504                 else
1505                         findspace = VMFS_OPTIMAL_SPACE;
1506                 rv = vm_map_find(map, object, foff, addr, size,
1507 #ifdef MAP_32BIT
1508                     flags & MAP_32BIT ? MAP_32BIT_MAX_ADDR :
1509 #endif
1510                     0, findspace, prot, maxprot, docow);
1511         } else {
1512                 rv = vm_map_fixed(map, object, foff, *addr, size,
1513                     prot, maxprot, docow);
1514         }
1515
1516         if (rv == KERN_SUCCESS) {
1517                 /*
1518                  * If the process has requested that all future mappings
1519                  * be wired, then heed this.
1520                  */
1521                 if (map->flags & MAP_WIREFUTURE) {
1522                         vm_map_wire(map, *addr, *addr + size,
1523                             VM_MAP_WIRE_USER | ((flags & MAP_STACK) ?
1524                             VM_MAP_WIRE_HOLESOK : VM_MAP_WIRE_NOHOLES));
1525                 }
1526         }
1527         return (vm_mmap_to_errno(rv));
1528 }
1529
1530 /*
1531  * Translate a Mach VM return code to zero on success or the appropriate errno
1532  * on failure.
1533  */
1534 int
1535 vm_mmap_to_errno(int rv)
1536 {
1537
1538         switch (rv) {
1539         case KERN_SUCCESS:
1540                 return (0);
1541         case KERN_INVALID_ADDRESS:
1542         case KERN_NO_SPACE:
1543                 return (ENOMEM);
1544         case KERN_PROTECTION_FAILURE:
1545                 return (EACCES);
1546         default:
1547                 return (EINVAL);
1548         }
1549 }