160727d8bSWarner Losh /*- 2df8bae1dSRodney W. Grimes * Copyright (c) 1988 University of Utah. 3df8bae1dSRodney W. Grimes * Copyright (c) 1991, 1993 4df8bae1dSRodney W. Grimes * The Regents of the University of California. All rights reserved. 5df8bae1dSRodney W. Grimes * 6df8bae1dSRodney W. Grimes * This code is derived from software contributed to Berkeley by 7df8bae1dSRodney W. Grimes * the Systems Programming Group of the University of Utah Computer 8df8bae1dSRodney W. Grimes * Science Department. 9df8bae1dSRodney W. Grimes * 10df8bae1dSRodney W. Grimes * Redistribution and use in source and binary forms, with or without 11df8bae1dSRodney W. Grimes * modification, are permitted provided that the following conditions 12df8bae1dSRodney W. Grimes * are met: 13df8bae1dSRodney W. Grimes * 1. Redistributions of source code must retain the above copyright 14df8bae1dSRodney W. Grimes * notice, this list of conditions and the following disclaimer. 15df8bae1dSRodney W. Grimes * 2. Redistributions in binary form must reproduce the above copyright 16df8bae1dSRodney W. Grimes * notice, this list of conditions and the following disclaimer in the 17df8bae1dSRodney W. Grimes * documentation and/or other materials provided with the distribution. 18df8bae1dSRodney W. Grimes * 4. Neither the name of the University nor the names of its contributors 19df8bae1dSRodney W. Grimes * may be used to endorse or promote products derived from this software 20df8bae1dSRodney W. Grimes * without specific prior written permission. 21df8bae1dSRodney W. Grimes * 22df8bae1dSRodney W. Grimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 23df8bae1dSRodney W. Grimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 24df8bae1dSRodney W. Grimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 25df8bae1dSRodney W. Grimes * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 26df8bae1dSRodney W. Grimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 27df8bae1dSRodney W. Grimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 28df8bae1dSRodney W. Grimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 29df8bae1dSRodney W. Grimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 30df8bae1dSRodney W. Grimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 31df8bae1dSRodney W. Grimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 32df8bae1dSRodney W. Grimes * SUCH DAMAGE. 33df8bae1dSRodney W. Grimes * 34df8bae1dSRodney W. Grimes * from: Utah $Hdr: vm_mmap.c 1.6 91/10/21$ 35df8bae1dSRodney W. Grimes * 36df8bae1dSRodney W. Grimes * @(#)vm_mmap.c 8.4 (Berkeley) 1/12/94 37df8bae1dSRodney W. Grimes */ 38df8bae1dSRodney W. Grimes 39df8bae1dSRodney W. Grimes /* 40df8bae1dSRodney W. Grimes * Mapped file (mmap) interface to VM 41df8bae1dSRodney W. Grimes */ 42df8bae1dSRodney W. Grimes 43874651b1SDavid E. O'Brien #include <sys/cdefs.h> 44874651b1SDavid E. O'Brien __FBSDID("$FreeBSD$"); 45874651b1SDavid E. O'Brien 465591b823SEivind Eklund #include "opt_compat.h" 4749874f6eSJoseph Koshy #include "opt_hwpmc_hooks.h" 48e9822d92SJoerg Wunsch 49df8bae1dSRodney W. Grimes #include <sys/param.h> 50df8bae1dSRodney W. Grimes #include <sys/systm.h> 51fb919e4dSMark Murray #include <sys/lock.h> 5223955314SAlfred Perlstein #include <sys/mutex.h> 53d2d3e875SBruce Evans #include <sys/sysproto.h> 54df8bae1dSRodney W. Grimes #include <sys/filedesc.h> 55acd3428bSRobert Watson #include <sys/priv.h> 56df8bae1dSRodney W. Grimes #include <sys/proc.h> 57*1ba5ad42SEdward Tomasz Napierala #include <sys/racct.h> 58070f64feSMatthew Dillon #include <sys/resource.h> 59070f64feSMatthew Dillon #include <sys/resourcevar.h> 60df8bae1dSRodney W. Grimes #include <sys/vnode.h> 613ac4d1efSBruce Evans #include <sys/fcntl.h> 62df8bae1dSRodney W. Grimes #include <sys/file.h> 63df8bae1dSRodney W. Grimes #include <sys/mman.h> 64b483c7f6SGuido van Rooij #include <sys/mount.h> 65df8bae1dSRodney W. Grimes #include <sys/conf.h> 664183b6b6SPeter Wemm #include <sys/stat.h> 67497a8238SKonstantin Belousov #include <sys/sysent.h> 68efeaf95aSDavid Greenman #include <sys/vmmeter.h> 69df8bae1dSRodney W. Grimes 70aed55708SRobert Watson #include <security/mac/mac_framework.h> 71aed55708SRobert Watson 72df8bae1dSRodney W. Grimes #include <vm/vm.h> 73efeaf95aSDavid Greenman #include <vm/vm_param.h> 74efeaf95aSDavid Greenman #include <vm/pmap.h> 75efeaf95aSDavid Greenman #include <vm/vm_map.h> 76efeaf95aSDavid Greenman #include <vm/vm_object.h> 771c7c3c6aSMatthew Dillon #include <vm/vm_page.h> 78df8bae1dSRodney W. Grimes #include <vm/vm_pager.h> 79b5e8ce9fSBruce Evans #include <vm/vm_pageout.h> 80efeaf95aSDavid Greenman #include <vm/vm_extern.h> 81867a482dSJohn Dyson #include <vm/vm_page.h> 82df8bae1dSRodney W. Grimes 8349874f6eSJoseph Koshy #ifdef HWPMC_HOOKS 8449874f6eSJoseph Koshy #include <sys/pmckern.h> 8549874f6eSJoseph Koshy #endif 8649874f6eSJoseph Koshy 87d2d3e875SBruce Evans #ifndef _SYS_SYSPROTO_H_ 88df8bae1dSRodney W. Grimes struct sbrk_args { 89df8bae1dSRodney W. Grimes int incr; 90df8bae1dSRodney W. Grimes }; 91d2d3e875SBruce Evans #endif 920d94caffSDavid Greenman 93c8daea13SAlexander Kabaev static int vm_mmap_vnode(struct thread *, vm_size_t, vm_prot_t, vm_prot_t *, 9464345f0bSJohn Baldwin int *, struct vnode *, vm_ooffset_t *, vm_object_t *); 9598df9218SJohn Baldwin static int vm_mmap_cdev(struct thread *, vm_size_t, vm_prot_t, vm_prot_t *, 9664345f0bSJohn Baldwin int *, struct cdev *, vm_ooffset_t *, vm_object_t *); 978e38aeffSJohn Baldwin static int vm_mmap_shm(struct thread *, vm_size_t, vm_prot_t, vm_prot_t *, 988e38aeffSJohn Baldwin int *, struct shmfd *, vm_ooffset_t, vm_object_t *); 99c8daea13SAlexander Kabaev 100d2c60af8SMatthew Dillon /* 101d2c60af8SMatthew Dillon * MPSAFE 102d2c60af8SMatthew Dillon */ 103df8bae1dSRodney W. Grimes /* ARGSUSED */ 104df8bae1dSRodney W. Grimes int 105b40ce416SJulian Elischer sbrk(td, uap) 106b40ce416SJulian Elischer struct thread *td; 107df8bae1dSRodney W. Grimes struct sbrk_args *uap; 108df8bae1dSRodney W. Grimes { 109df8bae1dSRodney W. Grimes /* Not yet implemented */ 110df8bae1dSRodney W. Grimes return (EOPNOTSUPP); 111df8bae1dSRodney W. Grimes } 112df8bae1dSRodney W. Grimes 113d2d3e875SBruce Evans #ifndef _SYS_SYSPROTO_H_ 114df8bae1dSRodney W. Grimes struct sstk_args { 115df8bae1dSRodney W. Grimes int incr; 116df8bae1dSRodney W. Grimes }; 117d2d3e875SBruce Evans #endif 1180d94caffSDavid Greenman 119d2c60af8SMatthew Dillon /* 120d2c60af8SMatthew Dillon * MPSAFE 121d2c60af8SMatthew Dillon */ 122df8bae1dSRodney W. Grimes /* ARGSUSED */ 123df8bae1dSRodney W. Grimes int 124b40ce416SJulian Elischer sstk(td, uap) 125b40ce416SJulian Elischer struct thread *td; 126df8bae1dSRodney W. Grimes struct sstk_args *uap; 127df8bae1dSRodney W. Grimes { 128df8bae1dSRodney W. Grimes /* Not yet implemented */ 129df8bae1dSRodney W. Grimes return (EOPNOTSUPP); 130df8bae1dSRodney W. Grimes } 131df8bae1dSRodney W. Grimes 1321930e303SPoul-Henning Kamp #if defined(COMPAT_43) 133d2d3e875SBruce Evans #ifndef _SYS_SYSPROTO_H_ 134df8bae1dSRodney W. Grimes struct getpagesize_args { 135df8bae1dSRodney W. Grimes int dummy; 136df8bae1dSRodney W. Grimes }; 137d2d3e875SBruce Evans #endif 1380d94caffSDavid Greenman 139df8bae1dSRodney W. Grimes /* ARGSUSED */ 140df8bae1dSRodney W. Grimes int 141b40ce416SJulian Elischer ogetpagesize(td, uap) 142b40ce416SJulian Elischer struct thread *td; 143df8bae1dSRodney W. Grimes struct getpagesize_args *uap; 144df8bae1dSRodney W. Grimes { 1450cddd8f0SMatthew Dillon /* MP SAFE */ 146b40ce416SJulian Elischer td->td_retval[0] = PAGE_SIZE; 147df8bae1dSRodney W. Grimes return (0); 148df8bae1dSRodney W. Grimes } 1491930e303SPoul-Henning Kamp #endif /* COMPAT_43 */ 150df8bae1dSRodney W. Grimes 15154f42e4bSPeter Wemm 15254f42e4bSPeter Wemm /* 15354f42e4bSPeter Wemm * Memory Map (mmap) system call. Note that the file offset 15454f42e4bSPeter Wemm * and address are allowed to be NOT page aligned, though if 15554f42e4bSPeter Wemm * the MAP_FIXED flag it set, both must have the same remainder 15654f42e4bSPeter Wemm * modulo the PAGE_SIZE (POSIX 1003.1b). If the address is not 15754f42e4bSPeter Wemm * page-aligned, the actual mapping starts at trunc_page(addr) 15854f42e4bSPeter Wemm * and the return value is adjusted up by the page offset. 159b4309055SMatthew Dillon * 160b4309055SMatthew Dillon * Generally speaking, only character devices which are themselves 161b4309055SMatthew Dillon * memory-based, such as a video framebuffer, can be mmap'd. Otherwise 162b4309055SMatthew Dillon * there would be no cache coherency between a descriptor and a VM mapping 163b4309055SMatthew Dillon * both to the same character device. 16454f42e4bSPeter Wemm */ 165d2d3e875SBruce Evans #ifndef _SYS_SYSPROTO_H_ 166df8bae1dSRodney W. Grimes struct mmap_args { 167651bb817SAlexander Langer void *addr; 168df8bae1dSRodney W. Grimes size_t len; 169df8bae1dSRodney W. Grimes int prot; 170df8bae1dSRodney W. Grimes int flags; 171df8bae1dSRodney W. Grimes int fd; 172df8bae1dSRodney W. Grimes long pad; 173df8bae1dSRodney W. Grimes off_t pos; 174df8bae1dSRodney W. Grimes }; 175d2d3e875SBruce Evans #endif 176df8bae1dSRodney W. Grimes 177d2c60af8SMatthew Dillon /* 178d2c60af8SMatthew Dillon * MPSAFE 179d2c60af8SMatthew Dillon */ 180df8bae1dSRodney W. Grimes int 181b40ce416SJulian Elischer mmap(td, uap) 182b40ce416SJulian Elischer struct thread *td; 18354d92145SMatthew Dillon struct mmap_args *uap; 184df8bae1dSRodney W. Grimes { 18549874f6eSJoseph Koshy #ifdef HWPMC_HOOKS 18649874f6eSJoseph Koshy struct pmckern_map_in pkm; 18749874f6eSJoseph Koshy #endif 188c8daea13SAlexander Kabaev struct file *fp; 189df8bae1dSRodney W. Grimes struct vnode *vp; 190df8bae1dSRodney W. Grimes vm_offset_t addr; 1919154ee6aSPeter Wemm vm_size_t size, pageoff; 192df8bae1dSRodney W. Grimes vm_prot_t prot, maxprot; 193651bb817SAlexander Langer void *handle; 19498df9218SJohn Baldwin objtype_t handle_type; 195df8bae1dSRodney W. Grimes int flags, error; 19654f42e4bSPeter Wemm off_t pos; 197b40ce416SJulian Elischer struct vmspace *vms = td->td_proc->p_vmspace; 198df8bae1dSRodney W. Grimes 19954f42e4bSPeter Wemm addr = (vm_offset_t) uap->addr; 20054f42e4bSPeter Wemm size = uap->len; 201df8bae1dSRodney W. Grimes prot = uap->prot & VM_PROT_ALL; 202df8bae1dSRodney W. Grimes flags = uap->flags; 20354f42e4bSPeter Wemm pos = uap->pos; 20454f42e4bSPeter Wemm 205426da3bcSAlfred Perlstein fp = NULL; 20627bfa958SSimon L. B. Nielsen 20727bfa958SSimon L. B. Nielsen /* Make sure mapping fits into numeric range, etc. */ 208497a8238SKonstantin Belousov if ((uap->len == 0 && !SV_CURPROC_FLAG(SV_AOUT) && 2097022f954SKonstantin Belousov curproc->p_osrel >= P_OSREL_MAP_ANON) || 2105711bf30SJohn Baldwin ((flags & MAP_ANON) && (uap->fd != -1 || pos != 0))) 211df8bae1dSRodney W. Grimes return (EINVAL); 2129154ee6aSPeter Wemm 2132267af78SJulian Elischer if (flags & MAP_STACK) { 2142267af78SJulian Elischer if ((uap->fd != -1) || 2152267af78SJulian Elischer ((prot & (PROT_READ | PROT_WRITE)) != (PROT_READ | PROT_WRITE))) 2162267af78SJulian Elischer return (EINVAL); 2172267af78SJulian Elischer flags |= MAP_ANON; 2182267af78SJulian Elischer pos = 0; 2192907af2aSJulian Elischer } 2202907af2aSJulian Elischer 2219154ee6aSPeter Wemm /* 22254f42e4bSPeter Wemm * Align the file position to a page boundary, 22354f42e4bSPeter Wemm * and save its page offset component. 2249154ee6aSPeter Wemm */ 22554f42e4bSPeter Wemm pageoff = (pos & PAGE_MASK); 22654f42e4bSPeter Wemm pos -= pageoff; 22754f42e4bSPeter Wemm 22854f42e4bSPeter Wemm /* Adjust size for rounding (on both ends). */ 22954f42e4bSPeter Wemm size += pageoff; /* low end... */ 23054f42e4bSPeter Wemm size = (vm_size_t) round_page(size); /* hi end */ 2319154ee6aSPeter Wemm 232df8bae1dSRodney W. Grimes /* 2330d94caffSDavid Greenman * Check for illegal addresses. Watch out for address wrap... Note 2340d94caffSDavid Greenman * that VM_*_ADDRESS are not constants due to casts (argh). 235df8bae1dSRodney W. Grimes */ 236df8bae1dSRodney W. Grimes if (flags & MAP_FIXED) { 23754f42e4bSPeter Wemm /* 23854f42e4bSPeter Wemm * The specified address must have the same remainder 23954f42e4bSPeter Wemm * as the file offset taken modulo PAGE_SIZE, so it 24054f42e4bSPeter Wemm * should be aligned after adjustment by pageoff. 24154f42e4bSPeter Wemm */ 24254f42e4bSPeter Wemm addr -= pageoff; 24354f42e4bSPeter Wemm if (addr & PAGE_MASK) 24454f42e4bSPeter Wemm return (EINVAL); 24527bfa958SSimon L. B. Nielsen 24654f42e4bSPeter Wemm /* Address range must be all in user VM space. */ 24705ba50f5SJake Burkholder if (addr < vm_map_min(&vms->vm_map) || 24805ba50f5SJake Burkholder addr + size > vm_map_max(&vms->vm_map)) 249df8bae1dSRodney W. Grimes return (EINVAL); 250bbc0ec52SDavid Greenman if (addr + size < addr) 251df8bae1dSRodney W. Grimes return (EINVAL); 25291d5354aSJohn Baldwin } else { 253df8bae1dSRodney W. Grimes /* 25454f42e4bSPeter Wemm * XXX for non-fixed mappings where no hint is provided or 25554f42e4bSPeter Wemm * the hint would fall in the potential heap space, 25654f42e4bSPeter Wemm * place it after the end of the largest possible heap. 257df8bae1dSRodney W. Grimes * 25854f42e4bSPeter Wemm * There should really be a pmap call to determine a reasonable 25954f42e4bSPeter Wemm * location. 260df8bae1dSRodney W. Grimes */ 26191d5354aSJohn Baldwin PROC_LOCK(td->td_proc); 26291d5354aSJohn Baldwin if (addr == 0 || 2631f6889a1SMatthew Dillon (addr >= round_page((vm_offset_t)vms->vm_taddr) && 264c460ac3aSPeter Wemm addr < round_page((vm_offset_t)vms->vm_daddr + 26591d5354aSJohn Baldwin lim_max(td->td_proc, RLIMIT_DATA)))) 266c460ac3aSPeter Wemm addr = round_page((vm_offset_t)vms->vm_daddr + 26791d5354aSJohn Baldwin lim_max(td->td_proc, RLIMIT_DATA)); 26891d5354aSJohn Baldwin PROC_UNLOCK(td->td_proc); 26991d5354aSJohn Baldwin } 270df8bae1dSRodney W. Grimes if (flags & MAP_ANON) { 271df8bae1dSRodney W. Grimes /* 272df8bae1dSRodney W. Grimes * Mapping blank space is trivial. 273df8bae1dSRodney W. Grimes */ 274df8bae1dSRodney W. Grimes handle = NULL; 27598df9218SJohn Baldwin handle_type = OBJT_DEFAULT; 276df8bae1dSRodney W. Grimes maxprot = VM_PROT_ALL; 27730d4dd7eSAlexander Kabaev } else { 278df8bae1dSRodney W. Grimes /* 2798e38aeffSJohn Baldwin * Mapping file, get fp for validation and 2808e38aeffSJohn Baldwin * don't let the descriptor disappear on us if we block. 281df8bae1dSRodney W. Grimes */ 282a4db4953SAlfred Perlstein if ((error = fget(td, uap->fd, &fp)) != 0) 283426da3bcSAlfred Perlstein goto done; 2848e38aeffSJohn Baldwin if (fp->f_type == DTYPE_SHM) { 2858e38aeffSJohn Baldwin handle = fp->f_data; 2868e38aeffSJohn Baldwin handle_type = OBJT_SWAP; 2878e38aeffSJohn Baldwin maxprot = VM_PROT_NONE; 2888e38aeffSJohn Baldwin 2898e38aeffSJohn Baldwin /* FREAD should always be set. */ 2908e38aeffSJohn Baldwin if (fp->f_flag & FREAD) 2918e38aeffSJohn Baldwin maxprot |= VM_PROT_EXECUTE | VM_PROT_READ; 2928e38aeffSJohn Baldwin if (fp->f_flag & FWRITE) 2938e38aeffSJohn Baldwin maxprot |= VM_PROT_WRITE; 2948e38aeffSJohn Baldwin goto map; 2958e38aeffSJohn Baldwin } 296e4ca250dSJohn Baldwin if (fp->f_type != DTYPE_VNODE) { 29789eae00bSTom Rhodes error = ENODEV; 298426da3bcSAlfred Perlstein goto done; 299e4ca250dSJohn Baldwin } 3008e38aeffSJohn Baldwin #if defined(COMPAT_FREEBSD7) || defined(COMPAT_FREEBSD6) || \ 3018e38aeffSJohn Baldwin defined(COMPAT_FREEBSD5) || defined(COMPAT_FREEBSD4) 302279d7226SMatthew Dillon /* 303aa543039SGarrett Wollman * POSIX shared-memory objects are defined to have 304aa543039SGarrett Wollman * kernel persistence, and are not defined to support 305aa543039SGarrett Wollman * read(2)/write(2) -- or even open(2). Thus, we can 306aa543039SGarrett Wollman * use MAP_ASYNC to trade on-disk coherence for speed. 307aa543039SGarrett Wollman * The shm_open(3) library routine turns on the FPOSIXSHM 308aa543039SGarrett Wollman * flag to request this behavior. 309aa543039SGarrett Wollman */ 310aa543039SGarrett Wollman if (fp->f_flag & FPOSIXSHM) 311aa543039SGarrett Wollman flags |= MAP_NOSYNC; 3128e38aeffSJohn Baldwin #endif 3133b6d9652SPoul-Henning Kamp vp = fp->f_vnode; 314c8bdd56bSGuido van Rooij /* 315df8bae1dSRodney W. Grimes * Ensure that file and memory protections are 316df8bae1dSRodney W. Grimes * compatible. Note that we only worry about 317df8bae1dSRodney W. Grimes * writability if mapping is shared; in this case, 318df8bae1dSRodney W. Grimes * current and max prot are dictated by the open file. 319df8bae1dSRodney W. Grimes * XXX use the vnode instead? Problem is: what 3200d94caffSDavid Greenman * credentials do we use for determination? What if 3210d94caffSDavid Greenman * proc does a setuid? 322df8bae1dSRodney W. Grimes */ 3238eec77b0STim J. Robbins if (vp->v_mount != NULL && vp->v_mount->mnt_flag & MNT_NOEXEC) 324b483c7f6SGuido van Rooij maxprot = VM_PROT_NONE; 325b483c7f6SGuido van Rooij else 326b483c7f6SGuido van Rooij maxprot = VM_PROT_EXECUTE; 327279d7226SMatthew Dillon if (fp->f_flag & FREAD) { 328df8bae1dSRodney W. Grimes maxprot |= VM_PROT_READ; 329279d7226SMatthew Dillon } else if (prot & PROT_READ) { 330279d7226SMatthew Dillon error = EACCES; 331279d7226SMatthew Dillon goto done; 332279d7226SMatthew Dillon } 333c8bdd56bSGuido van Rooij /* 334c8bdd56bSGuido van Rooij * If we are sharing potential changes (either via 335c8bdd56bSGuido van Rooij * MAP_SHARED or via the implicit sharing of character 336c8bdd56bSGuido van Rooij * device mappings), and we are trying to get write 337c8bdd56bSGuido van Rooij * permission although we opened it without asking 338c8daea13SAlexander Kabaev * for it, bail out. 339c8bdd56bSGuido van Rooij */ 340ce7a036dSAlexander Kabaev if ((flags & MAP_SHARED) != 0) { 34105feb99fSGuido van Rooij if ((fp->f_flag & FWRITE) != 0) { 342df8bae1dSRodney W. Grimes maxprot |= VM_PROT_WRITE; 343279d7226SMatthew Dillon } else if ((prot & PROT_WRITE) != 0) { 344279d7226SMatthew Dillon error = EACCES; 345279d7226SMatthew Dillon goto done; 346279d7226SMatthew Dillon } 347ce7a036dSAlexander Kabaev } else if (vp->v_type != VCHR || (fp->f_flag & FWRITE) != 0) { 34805feb99fSGuido van Rooij maxprot |= VM_PROT_WRITE; 349279d7226SMatthew Dillon } 350651bb817SAlexander Langer handle = (void *)vp; 35198df9218SJohn Baldwin handle_type = OBJT_VNODE; 35230d4dd7eSAlexander Kabaev } 3538e38aeffSJohn Baldwin map: 35436b90789SKonstantin Belousov td->td_fpop = fp; 3551f6889a1SMatthew Dillon error = vm_mmap(&vms->vm_map, &addr, size, prot, maxprot, 35698df9218SJohn Baldwin flags, handle_type, handle, pos); 35736b90789SKonstantin Belousov td->td_fpop = NULL; 35849874f6eSJoseph Koshy #ifdef HWPMC_HOOKS 35949874f6eSJoseph Koshy /* inform hwpmc(4) if an executable is being mapped */ 36049874f6eSJoseph Koshy if (error == 0 && handle_type == OBJT_VNODE && 36149874f6eSJoseph Koshy (prot & PROT_EXEC)) { 36249874f6eSJoseph Koshy pkm.pm_file = handle; 36349874f6eSJoseph Koshy pkm.pm_address = (uintptr_t) addr; 36449874f6eSJoseph Koshy PMC_CALL_HOOK(td, PMC_FN_MMAP, (void *) &pkm); 36549874f6eSJoseph Koshy } 36649874f6eSJoseph Koshy #endif 367df8bae1dSRodney W. Grimes if (error == 0) 368b40ce416SJulian Elischer td->td_retval[0] = (register_t) (addr + pageoff); 369279d7226SMatthew Dillon done: 370279d7226SMatthew Dillon if (fp) 371b40ce416SJulian Elischer fdrop(fp, td); 372f6b5b182SJeff Roberson 373df8bae1dSRodney W. Grimes return (error); 374df8bae1dSRodney W. Grimes } 375df8bae1dSRodney W. Grimes 376c2815ad5SPeter Wemm int 377c2815ad5SPeter Wemm freebsd6_mmap(struct thread *td, struct freebsd6_mmap_args *uap) 378c2815ad5SPeter Wemm { 379c2815ad5SPeter Wemm struct mmap_args oargs; 380c2815ad5SPeter Wemm 381c2815ad5SPeter Wemm oargs.addr = uap->addr; 382c2815ad5SPeter Wemm oargs.len = uap->len; 383c2815ad5SPeter Wemm oargs.prot = uap->prot; 384c2815ad5SPeter Wemm oargs.flags = uap->flags; 385c2815ad5SPeter Wemm oargs.fd = uap->fd; 386c2815ad5SPeter Wemm oargs.pos = uap->pos; 387c2815ad5SPeter Wemm return (mmap(td, &oargs)); 388c2815ad5SPeter Wemm } 389c2815ad5SPeter Wemm 39005f0fdd2SPoul-Henning Kamp #ifdef COMPAT_43 391d2d3e875SBruce Evans #ifndef _SYS_SYSPROTO_H_ 39205f0fdd2SPoul-Henning Kamp struct ommap_args { 39305f0fdd2SPoul-Henning Kamp caddr_t addr; 39405f0fdd2SPoul-Henning Kamp int len; 39505f0fdd2SPoul-Henning Kamp int prot; 39605f0fdd2SPoul-Henning Kamp int flags; 39705f0fdd2SPoul-Henning Kamp int fd; 39805f0fdd2SPoul-Henning Kamp long pos; 39905f0fdd2SPoul-Henning Kamp }; 400d2d3e875SBruce Evans #endif 40105f0fdd2SPoul-Henning Kamp int 402b40ce416SJulian Elischer ommap(td, uap) 403b40ce416SJulian Elischer struct thread *td; 40454d92145SMatthew Dillon struct ommap_args *uap; 40505f0fdd2SPoul-Henning Kamp { 40605f0fdd2SPoul-Henning Kamp struct mmap_args nargs; 40705f0fdd2SPoul-Henning Kamp static const char cvtbsdprot[8] = { 40805f0fdd2SPoul-Henning Kamp 0, 40905f0fdd2SPoul-Henning Kamp PROT_EXEC, 41005f0fdd2SPoul-Henning Kamp PROT_WRITE, 41105f0fdd2SPoul-Henning Kamp PROT_EXEC | PROT_WRITE, 41205f0fdd2SPoul-Henning Kamp PROT_READ, 41305f0fdd2SPoul-Henning Kamp PROT_EXEC | PROT_READ, 41405f0fdd2SPoul-Henning Kamp PROT_WRITE | PROT_READ, 41505f0fdd2SPoul-Henning Kamp PROT_EXEC | PROT_WRITE | PROT_READ, 41605f0fdd2SPoul-Henning Kamp }; 4170d94caffSDavid Greenman 41805f0fdd2SPoul-Henning Kamp #define OMAP_ANON 0x0002 41905f0fdd2SPoul-Henning Kamp #define OMAP_COPY 0x0020 42005f0fdd2SPoul-Henning Kamp #define OMAP_SHARED 0x0010 42105f0fdd2SPoul-Henning Kamp #define OMAP_FIXED 0x0100 42205f0fdd2SPoul-Henning Kamp 42305f0fdd2SPoul-Henning Kamp nargs.addr = uap->addr; 42405f0fdd2SPoul-Henning Kamp nargs.len = uap->len; 42505f0fdd2SPoul-Henning Kamp nargs.prot = cvtbsdprot[uap->prot & 0x7]; 42605f0fdd2SPoul-Henning Kamp nargs.flags = 0; 42705f0fdd2SPoul-Henning Kamp if (uap->flags & OMAP_ANON) 42805f0fdd2SPoul-Henning Kamp nargs.flags |= MAP_ANON; 42905f0fdd2SPoul-Henning Kamp if (uap->flags & OMAP_COPY) 43005f0fdd2SPoul-Henning Kamp nargs.flags |= MAP_COPY; 43105f0fdd2SPoul-Henning Kamp if (uap->flags & OMAP_SHARED) 43205f0fdd2SPoul-Henning Kamp nargs.flags |= MAP_SHARED; 43305f0fdd2SPoul-Henning Kamp else 43405f0fdd2SPoul-Henning Kamp nargs.flags |= MAP_PRIVATE; 43505f0fdd2SPoul-Henning Kamp if (uap->flags & OMAP_FIXED) 43605f0fdd2SPoul-Henning Kamp nargs.flags |= MAP_FIXED; 43705f0fdd2SPoul-Henning Kamp nargs.fd = uap->fd; 43805f0fdd2SPoul-Henning Kamp nargs.pos = uap->pos; 439b40ce416SJulian Elischer return (mmap(td, &nargs)); 44005f0fdd2SPoul-Henning Kamp } 44105f0fdd2SPoul-Henning Kamp #endif /* COMPAT_43 */ 44205f0fdd2SPoul-Henning Kamp 44305f0fdd2SPoul-Henning Kamp 444d2d3e875SBruce Evans #ifndef _SYS_SYSPROTO_H_ 445df8bae1dSRodney W. Grimes struct msync_args { 446651bb817SAlexander Langer void *addr; 447c899450bSPeter Wemm size_t len; 448e6c6af11SDavid Greenman int flags; 449df8bae1dSRodney W. Grimes }; 450d2d3e875SBruce Evans #endif 451d2c60af8SMatthew Dillon /* 452d2c60af8SMatthew Dillon * MPSAFE 453d2c60af8SMatthew Dillon */ 454df8bae1dSRodney W. Grimes int 455b40ce416SJulian Elischer msync(td, uap) 456b40ce416SJulian Elischer struct thread *td; 457df8bae1dSRodney W. Grimes struct msync_args *uap; 458df8bae1dSRodney W. Grimes { 459df8bae1dSRodney W. Grimes vm_offset_t addr; 460dabee6feSPeter Wemm vm_size_t size, pageoff; 461e6c6af11SDavid Greenman int flags; 462df8bae1dSRodney W. Grimes vm_map_t map; 463df8bae1dSRodney W. Grimes int rv; 464df8bae1dSRodney W. Grimes 465df8bae1dSRodney W. Grimes addr = (vm_offset_t) uap->addr; 4669154ee6aSPeter Wemm size = uap->len; 467e6c6af11SDavid Greenman flags = uap->flags; 468e6c6af11SDavid Greenman 469dabee6feSPeter Wemm pageoff = (addr & PAGE_MASK); 470dabee6feSPeter Wemm addr -= pageoff; 471dabee6feSPeter Wemm size += pageoff; 472dabee6feSPeter Wemm size = (vm_size_t) round_page(size); 4739154ee6aSPeter Wemm if (addr + size < addr) 474dabee6feSPeter Wemm return (EINVAL); 475dabee6feSPeter Wemm 476dabee6feSPeter Wemm if ((flags & (MS_ASYNC|MS_INVALIDATE)) == (MS_ASYNC|MS_INVALIDATE)) 4771e62bc63SDavid Greenman return (EINVAL); 4781e62bc63SDavid Greenman 479b40ce416SJulian Elischer map = &td->td_proc->p_vmspace->vm_map; 4809154ee6aSPeter Wemm 481df8bae1dSRodney W. Grimes /* 482df8bae1dSRodney W. Grimes * Clean the pages and interpret the return value. 483df8bae1dSRodney W. Grimes */ 484950f8459SAlan Cox rv = vm_map_sync(map, addr, addr + size, (flags & MS_ASYNC) == 0, 485e6c6af11SDavid Greenman (flags & MS_INVALIDATE) != 0); 486df8bae1dSRodney W. Grimes switch (rv) { 487df8bae1dSRodney W. Grimes case KERN_SUCCESS: 488d2c60af8SMatthew Dillon return (0); 489df8bae1dSRodney W. Grimes case KERN_INVALID_ADDRESS: 490df8bae1dSRodney W. Grimes return (EINVAL); /* Sun returns ENOMEM? */ 491b7b7cd44SAlan Cox case KERN_INVALID_ARGUMENT: 492b7b7cd44SAlan Cox return (EBUSY); 493df8bae1dSRodney W. Grimes default: 494df8bae1dSRodney W. Grimes return (EINVAL); 495df8bae1dSRodney W. Grimes } 496df8bae1dSRodney W. Grimes } 497df8bae1dSRodney W. Grimes 498d2d3e875SBruce Evans #ifndef _SYS_SYSPROTO_H_ 499df8bae1dSRodney W. Grimes struct munmap_args { 500651bb817SAlexander Langer void *addr; 5019154ee6aSPeter Wemm size_t len; 502df8bae1dSRodney W. Grimes }; 503d2d3e875SBruce Evans #endif 504d2c60af8SMatthew Dillon /* 505d2c60af8SMatthew Dillon * MPSAFE 506d2c60af8SMatthew Dillon */ 507df8bae1dSRodney W. Grimes int 508b40ce416SJulian Elischer munmap(td, uap) 509b40ce416SJulian Elischer struct thread *td; 51054d92145SMatthew Dillon struct munmap_args *uap; 511df8bae1dSRodney W. Grimes { 51249874f6eSJoseph Koshy #ifdef HWPMC_HOOKS 51349874f6eSJoseph Koshy struct pmckern_map_out pkm; 51449874f6eSJoseph Koshy vm_map_entry_t entry; 51549874f6eSJoseph Koshy #endif 516df8bae1dSRodney W. Grimes vm_offset_t addr; 517dabee6feSPeter Wemm vm_size_t size, pageoff; 518df8bae1dSRodney W. Grimes vm_map_t map; 519df8bae1dSRodney W. Grimes 520df8bae1dSRodney W. Grimes addr = (vm_offset_t) uap->addr; 5219154ee6aSPeter Wemm size = uap->len; 522d8834602SAlan Cox if (size == 0) 523d8834602SAlan Cox return (EINVAL); 524dabee6feSPeter Wemm 525dabee6feSPeter Wemm pageoff = (addr & PAGE_MASK); 526dabee6feSPeter Wemm addr -= pageoff; 527dabee6feSPeter Wemm size += pageoff; 528dabee6feSPeter Wemm size = (vm_size_t) round_page(size); 5299154ee6aSPeter Wemm if (addr + size < addr) 530df8bae1dSRodney W. Grimes return (EINVAL); 5319154ee6aSPeter Wemm 532df8bae1dSRodney W. Grimes /* 53305ba50f5SJake Burkholder * Check for illegal addresses. Watch out for address wrap... 534df8bae1dSRodney W. Grimes */ 535b40ce416SJulian Elischer map = &td->td_proc->p_vmspace->vm_map; 53605ba50f5SJake Burkholder if (addr < vm_map_min(map) || addr + size > vm_map_max(map)) 53705ba50f5SJake Burkholder return (EINVAL); 538d8834602SAlan Cox vm_map_lock(map); 53949874f6eSJoseph Koshy #ifdef HWPMC_HOOKS 54049874f6eSJoseph Koshy /* 54149874f6eSJoseph Koshy * Inform hwpmc if the address range being unmapped contains 54249874f6eSJoseph Koshy * an executable region. 54349874f6eSJoseph Koshy */ 5440d419640SRyan Stone pkm.pm_address = (uintptr_t) NULL; 54549874f6eSJoseph Koshy if (vm_map_lookup_entry(map, addr, &entry)) { 54649874f6eSJoseph Koshy for (; 54749874f6eSJoseph Koshy entry != &map->header && entry->start < addr + size; 54849874f6eSJoseph Koshy entry = entry->next) { 54949874f6eSJoseph Koshy if (vm_map_check_protection(map, entry->start, 55049874f6eSJoseph Koshy entry->end, VM_PROT_EXECUTE) == TRUE) { 55149874f6eSJoseph Koshy pkm.pm_address = (uintptr_t) addr; 55249874f6eSJoseph Koshy pkm.pm_size = (size_t) size; 55349874f6eSJoseph Koshy break; 55449874f6eSJoseph Koshy } 55549874f6eSJoseph Koshy } 55649874f6eSJoseph Koshy } 55749874f6eSJoseph Koshy #endif 558655c3490SKonstantin Belousov vm_map_delete(map, addr, addr + size); 5590d419640SRyan Stone 5600d419640SRyan Stone #ifdef HWPMC_HOOKS 5610d419640SRyan Stone /* downgrade the lock to prevent a LOR with the pmc-sx lock */ 5620d419640SRyan Stone vm_map_lock_downgrade(map); 563d473d3a1SRyan Stone if (pkm.pm_address != (uintptr_t) NULL) 5640d419640SRyan Stone PMC_CALL_HOOK(td, PMC_FN_MUNMAP, (void *) &pkm); 5650d419640SRyan Stone vm_map_unlock_read(map); 5660d419640SRyan Stone #else 567d8834602SAlan Cox vm_map_unlock(map); 5680d419640SRyan Stone #endif 5690d419640SRyan Stone /* vm_map_delete returns nothing but KERN_SUCCESS anyway */ 570df8bae1dSRodney W. Grimes return (0); 571df8bae1dSRodney W. Grimes } 572df8bae1dSRodney W. Grimes 573d2d3e875SBruce Evans #ifndef _SYS_SYSPROTO_H_ 574df8bae1dSRodney W. Grimes struct mprotect_args { 575651bb817SAlexander Langer const void *addr; 5769154ee6aSPeter Wemm size_t len; 577df8bae1dSRodney W. Grimes int prot; 578df8bae1dSRodney W. Grimes }; 579d2d3e875SBruce Evans #endif 580d2c60af8SMatthew Dillon /* 581d2c60af8SMatthew Dillon * MPSAFE 582d2c60af8SMatthew Dillon */ 583df8bae1dSRodney W. Grimes int 584b40ce416SJulian Elischer mprotect(td, uap) 585b40ce416SJulian Elischer struct thread *td; 586df8bae1dSRodney W. Grimes struct mprotect_args *uap; 587df8bae1dSRodney W. Grimes { 588df8bae1dSRodney W. Grimes vm_offset_t addr; 589dabee6feSPeter Wemm vm_size_t size, pageoff; 59054d92145SMatthew Dillon vm_prot_t prot; 591df8bae1dSRodney W. Grimes 592df8bae1dSRodney W. Grimes addr = (vm_offset_t) uap->addr; 5939154ee6aSPeter Wemm size = uap->len; 594df8bae1dSRodney W. Grimes prot = uap->prot & VM_PROT_ALL; 595df8bae1dSRodney W. Grimes 596dabee6feSPeter Wemm pageoff = (addr & PAGE_MASK); 597dabee6feSPeter Wemm addr -= pageoff; 598dabee6feSPeter Wemm size += pageoff; 599dabee6feSPeter Wemm size = (vm_size_t) round_page(size); 6009154ee6aSPeter Wemm if (addr + size < addr) 601dabee6feSPeter Wemm return (EINVAL); 602dabee6feSPeter Wemm 60343285049SAlan Cox switch (vm_map_protect(&td->td_proc->p_vmspace->vm_map, addr, 60443285049SAlan Cox addr + size, prot, FALSE)) { 605df8bae1dSRodney W. Grimes case KERN_SUCCESS: 606df8bae1dSRodney W. Grimes return (0); 607df8bae1dSRodney W. Grimes case KERN_PROTECTION_FAILURE: 608df8bae1dSRodney W. Grimes return (EACCES); 6093364c323SKonstantin Belousov case KERN_RESOURCE_SHORTAGE: 6103364c323SKonstantin Belousov return (ENOMEM); 611df8bae1dSRodney W. Grimes } 612df8bae1dSRodney W. Grimes return (EINVAL); 613df8bae1dSRodney W. Grimes } 614df8bae1dSRodney W. Grimes 615d2d3e875SBruce Evans #ifndef _SYS_SYSPROTO_H_ 616dabee6feSPeter Wemm struct minherit_args { 617651bb817SAlexander Langer void *addr; 6189154ee6aSPeter Wemm size_t len; 619dabee6feSPeter Wemm int inherit; 620dabee6feSPeter Wemm }; 621dabee6feSPeter Wemm #endif 622d2c60af8SMatthew Dillon /* 623d2c60af8SMatthew Dillon * MPSAFE 624d2c60af8SMatthew Dillon */ 625dabee6feSPeter Wemm int 626b40ce416SJulian Elischer minherit(td, uap) 627b40ce416SJulian Elischer struct thread *td; 628dabee6feSPeter Wemm struct minherit_args *uap; 629dabee6feSPeter Wemm { 630dabee6feSPeter Wemm vm_offset_t addr; 631dabee6feSPeter Wemm vm_size_t size, pageoff; 63254d92145SMatthew Dillon vm_inherit_t inherit; 633dabee6feSPeter Wemm 634dabee6feSPeter Wemm addr = (vm_offset_t)uap->addr; 6359154ee6aSPeter Wemm size = uap->len; 636dabee6feSPeter Wemm inherit = uap->inherit; 637dabee6feSPeter Wemm 638dabee6feSPeter Wemm pageoff = (addr & PAGE_MASK); 639dabee6feSPeter Wemm addr -= pageoff; 640dabee6feSPeter Wemm size += pageoff; 641dabee6feSPeter Wemm size = (vm_size_t) round_page(size); 6429154ee6aSPeter Wemm if (addr + size < addr) 643dabee6feSPeter Wemm return (EINVAL); 644dabee6feSPeter Wemm 645e0be79afSAlan Cox switch (vm_map_inherit(&td->td_proc->p_vmspace->vm_map, addr, 646e0be79afSAlan Cox addr + size, inherit)) { 647dabee6feSPeter Wemm case KERN_SUCCESS: 648dabee6feSPeter Wemm return (0); 649dabee6feSPeter Wemm case KERN_PROTECTION_FAILURE: 650dabee6feSPeter Wemm return (EACCES); 651dabee6feSPeter Wemm } 652dabee6feSPeter Wemm return (EINVAL); 653dabee6feSPeter Wemm } 654dabee6feSPeter Wemm 655dabee6feSPeter Wemm #ifndef _SYS_SYSPROTO_H_ 656df8bae1dSRodney W. Grimes struct madvise_args { 657651bb817SAlexander Langer void *addr; 6589154ee6aSPeter Wemm size_t len; 659df8bae1dSRodney W. Grimes int behav; 660df8bae1dSRodney W. Grimes }; 661d2d3e875SBruce Evans #endif 6620d94caffSDavid Greenman 663d2c60af8SMatthew Dillon /* 664d2c60af8SMatthew Dillon * MPSAFE 665d2c60af8SMatthew Dillon */ 666df8bae1dSRodney W. Grimes /* ARGSUSED */ 667df8bae1dSRodney W. Grimes int 668b40ce416SJulian Elischer madvise(td, uap) 669b40ce416SJulian Elischer struct thread *td; 670df8bae1dSRodney W. Grimes struct madvise_args *uap; 671df8bae1dSRodney W. Grimes { 672f35329acSJohn Dyson vm_offset_t start, end; 67305ba50f5SJake Burkholder vm_map_t map; 674f4cf2141SWes Peters struct proc *p; 675f4cf2141SWes Peters int error; 676b4309055SMatthew Dillon 677b4309055SMatthew Dillon /* 678f4cf2141SWes Peters * Check for our special case, advising the swap pager we are 679f4cf2141SWes Peters * "immortal." 680f4cf2141SWes Peters */ 681f4cf2141SWes Peters if (uap->behav == MADV_PROTECT) { 682acd3428bSRobert Watson error = priv_check(td, PRIV_VM_MADV_PROTECT); 68369297bf8SJohn Baldwin if (error == 0) { 684f4cf2141SWes Peters p = td->td_proc; 685f4cf2141SWes Peters PROC_LOCK(p); 686f4cf2141SWes Peters p->p_flag |= P_PROTECTED; 687f4cf2141SWes Peters PROC_UNLOCK(p); 68869297bf8SJohn Baldwin } 689f4cf2141SWes Peters return (error); 690f4cf2141SWes Peters } 691f4cf2141SWes Peters /* 692b4309055SMatthew Dillon * Check for illegal behavior 693b4309055SMatthew Dillon */ 6949730a5daSPaul Saab if (uap->behav < 0 || uap->behav > MADV_CORE) 695b4309055SMatthew Dillon return (EINVAL); 696867a482dSJohn Dyson /* 697867a482dSJohn Dyson * Check for illegal addresses. Watch out for address wrap... Note 698867a482dSJohn Dyson * that VM_*_ADDRESS are not constants due to casts (argh). 699867a482dSJohn Dyson */ 70005ba50f5SJake Burkholder map = &td->td_proc->p_vmspace->vm_map; 70105ba50f5SJake Burkholder if ((vm_offset_t)uap->addr < vm_map_min(map) || 70205ba50f5SJake Burkholder (vm_offset_t)uap->addr + uap->len > vm_map_max(map)) 703867a482dSJohn Dyson return (EINVAL); 704867a482dSJohn Dyson if (((vm_offset_t) uap->addr + uap->len) < (vm_offset_t) uap->addr) 705867a482dSJohn Dyson return (EINVAL); 706867a482dSJohn Dyson 707867a482dSJohn Dyson /* 708867a482dSJohn Dyson * Since this routine is only advisory, we default to conservative 709867a482dSJohn Dyson * behavior. 710867a482dSJohn Dyson */ 711cd6eea25SDavid Greenman start = trunc_page((vm_offset_t) uap->addr); 712cd6eea25SDavid Greenman end = round_page((vm_offset_t) uap->addr + uap->len); 713867a482dSJohn Dyson 71405ba50f5SJake Burkholder if (vm_map_madvise(map, start, end, uap->behav)) 715094f6d26SAlan Cox return (EINVAL); 716094f6d26SAlan Cox return (0); 717df8bae1dSRodney W. Grimes } 718df8bae1dSRodney W. Grimes 719d2d3e875SBruce Evans #ifndef _SYS_SYSPROTO_H_ 720df8bae1dSRodney W. Grimes struct mincore_args { 721651bb817SAlexander Langer const void *addr; 7229154ee6aSPeter Wemm size_t len; 723df8bae1dSRodney W. Grimes char *vec; 724df8bae1dSRodney W. Grimes }; 725d2d3e875SBruce Evans #endif 7260d94caffSDavid Greenman 727d2c60af8SMatthew Dillon /* 728d2c60af8SMatthew Dillon * MPSAFE 729d2c60af8SMatthew Dillon */ 730df8bae1dSRodney W. Grimes /* ARGSUSED */ 731df8bae1dSRodney W. Grimes int 732b40ce416SJulian Elischer mincore(td, uap) 733b40ce416SJulian Elischer struct thread *td; 734df8bae1dSRodney W. Grimes struct mincore_args *uap; 735df8bae1dSRodney W. Grimes { 736867a482dSJohn Dyson vm_offset_t addr, first_addr; 737867a482dSJohn Dyson vm_offset_t end, cend; 738867a482dSJohn Dyson pmap_t pmap; 739867a482dSJohn Dyson vm_map_t map; 74002c04a2fSJohn Dyson char *vec; 741d2c60af8SMatthew Dillon int error = 0; 742867a482dSJohn Dyson int vecindex, lastvecindex; 74354d92145SMatthew Dillon vm_map_entry_t current; 744867a482dSJohn Dyson vm_map_entry_t entry; 745567e51e1SAlan Cox vm_object_t object; 746567e51e1SAlan Cox vm_paddr_t locked_pa; 747567e51e1SAlan Cox vm_page_t m; 748567e51e1SAlan Cox vm_pindex_t pindex; 749867a482dSJohn Dyson int mincoreinfo; 750dd2622a8SAlan Cox unsigned int timestamp; 751567e51e1SAlan Cox boolean_t locked; 752df8bae1dSRodney W. Grimes 753867a482dSJohn Dyson /* 754867a482dSJohn Dyson * Make sure that the addresses presented are valid for user 755867a482dSJohn Dyson * mode. 756867a482dSJohn Dyson */ 757867a482dSJohn Dyson first_addr = addr = trunc_page((vm_offset_t) uap->addr); 7589154ee6aSPeter Wemm end = addr + (vm_size_t)round_page(uap->len); 75905ba50f5SJake Burkholder map = &td->td_proc->p_vmspace->vm_map; 76005ba50f5SJake Burkholder if (end > vm_map_max(map) || end < addr) 761455dd7d4SKonstantin Belousov return (ENOMEM); 76202c04a2fSJohn Dyson 763867a482dSJohn Dyson /* 764867a482dSJohn Dyson * Address of byte vector 765867a482dSJohn Dyson */ 76602c04a2fSJohn Dyson vec = uap->vec; 767867a482dSJohn Dyson 768b40ce416SJulian Elischer pmap = vmspace_pmap(td->td_proc->p_vmspace); 769867a482dSJohn Dyson 770eff50fcdSAlan Cox vm_map_lock_read(map); 771dd2622a8SAlan Cox RestartScan: 772dd2622a8SAlan Cox timestamp = map->timestamp; 773867a482dSJohn Dyson 774455dd7d4SKonstantin Belousov if (!vm_map_lookup_entry(map, addr, &entry)) { 775455dd7d4SKonstantin Belousov vm_map_unlock_read(map); 776455dd7d4SKonstantin Belousov return (ENOMEM); 777455dd7d4SKonstantin Belousov } 778867a482dSJohn Dyson 779867a482dSJohn Dyson /* 780867a482dSJohn Dyson * Do this on a map entry basis so that if the pages are not 781867a482dSJohn Dyson * in the current processes address space, we can easily look 782867a482dSJohn Dyson * up the pages elsewhere. 783867a482dSJohn Dyson */ 784867a482dSJohn Dyson lastvecindex = -1; 785867a482dSJohn Dyson for (current = entry; 786867a482dSJohn Dyson (current != &map->header) && (current->start < end); 787867a482dSJohn Dyson current = current->next) { 788867a482dSJohn Dyson 789867a482dSJohn Dyson /* 790455dd7d4SKonstantin Belousov * check for contiguity 791455dd7d4SKonstantin Belousov */ 792455dd7d4SKonstantin Belousov if (current->end < end && 793455dd7d4SKonstantin Belousov (entry->next == &map->header || 794455dd7d4SKonstantin Belousov current->next->start > current->end)) { 795455dd7d4SKonstantin Belousov vm_map_unlock_read(map); 796455dd7d4SKonstantin Belousov return (ENOMEM); 797455dd7d4SKonstantin Belousov } 798455dd7d4SKonstantin Belousov 799455dd7d4SKonstantin Belousov /* 800867a482dSJohn Dyson * ignore submaps (for now) or null objects 801867a482dSJohn Dyson */ 8029fdfe602SMatthew Dillon if ((current->eflags & MAP_ENTRY_IS_SUB_MAP) || 803867a482dSJohn Dyson current->object.vm_object == NULL) 804867a482dSJohn Dyson continue; 805867a482dSJohn Dyson 806867a482dSJohn Dyson /* 807867a482dSJohn Dyson * limit this scan to the current map entry and the 808867a482dSJohn Dyson * limits for the mincore call 809867a482dSJohn Dyson */ 810867a482dSJohn Dyson if (addr < current->start) 811867a482dSJohn Dyson addr = current->start; 812867a482dSJohn Dyson cend = current->end; 813867a482dSJohn Dyson if (cend > end) 814867a482dSJohn Dyson cend = end; 815867a482dSJohn Dyson 816867a482dSJohn Dyson /* 817867a482dSJohn Dyson * scan this entry one page at a time 818867a482dSJohn Dyson */ 819867a482dSJohn Dyson while (addr < cend) { 820867a482dSJohn Dyson /* 821867a482dSJohn Dyson * Check pmap first, it is likely faster, also 822867a482dSJohn Dyson * it can provide info as to whether we are the 823867a482dSJohn Dyson * one referencing or modifying the page. 824867a482dSJohn Dyson */ 825567e51e1SAlan Cox object = NULL; 826567e51e1SAlan Cox locked_pa = 0; 827567e51e1SAlan Cox retry: 828567e51e1SAlan Cox m = NULL; 829567e51e1SAlan Cox mincoreinfo = pmap_mincore(pmap, addr, &locked_pa); 830567e51e1SAlan Cox if (locked_pa != 0) { 831867a482dSJohn Dyson /* 832567e51e1SAlan Cox * The page is mapped by this process but not 833567e51e1SAlan Cox * both accessed and modified. It is also 834567e51e1SAlan Cox * managed. Acquire the object lock so that 835567e51e1SAlan Cox * other mappings might be examined. 836867a482dSJohn Dyson */ 837567e51e1SAlan Cox m = PHYS_TO_VM_PAGE(locked_pa); 838567e51e1SAlan Cox if (m->object != object) { 839567e51e1SAlan Cox if (object != NULL) 840567e51e1SAlan Cox VM_OBJECT_UNLOCK(object); 841567e51e1SAlan Cox object = m->object; 842567e51e1SAlan Cox locked = VM_OBJECT_TRYLOCK(object); 843567e51e1SAlan Cox vm_page_unlock(m); 844567e51e1SAlan Cox if (!locked) { 845567e51e1SAlan Cox VM_OBJECT_LOCK(object); 8462965a453SKip Macy vm_page_lock(m); 847567e51e1SAlan Cox goto retry; 848567e51e1SAlan Cox } 849567e51e1SAlan Cox } else 850567e51e1SAlan Cox vm_page_unlock(m); 851567e51e1SAlan Cox KASSERT(m->valid == VM_PAGE_BITS_ALL, 852567e51e1SAlan Cox ("mincore: page %p is mapped but invalid", 853567e51e1SAlan Cox m)); 854567e51e1SAlan Cox } else if (mincoreinfo == 0) { 855567e51e1SAlan Cox /* 856567e51e1SAlan Cox * The page is not mapped by this process. If 857567e51e1SAlan Cox * the object implements managed pages, then 858567e51e1SAlan Cox * determine if the page is resident so that 859567e51e1SAlan Cox * the mappings might be examined. 860567e51e1SAlan Cox */ 861567e51e1SAlan Cox if (current->object.vm_object != object) { 862567e51e1SAlan Cox if (object != NULL) 863567e51e1SAlan Cox VM_OBJECT_UNLOCK(object); 864567e51e1SAlan Cox object = current->object.vm_object; 865567e51e1SAlan Cox VM_OBJECT_LOCK(object); 866567e51e1SAlan Cox } 867567e51e1SAlan Cox if (object->type == OBJT_DEFAULT || 868567e51e1SAlan Cox object->type == OBJT_SWAP || 869567e51e1SAlan Cox object->type == OBJT_VNODE) { 870567e51e1SAlan Cox pindex = OFF_TO_IDX(current->offset + 871567e51e1SAlan Cox (addr - current->start)); 872567e51e1SAlan Cox m = vm_page_lookup(object, pindex); 873567e51e1SAlan Cox if (m != NULL && m->valid == 0) 874567e51e1SAlan Cox m = NULL; 875567e51e1SAlan Cox if (m != NULL) 876567e51e1SAlan Cox mincoreinfo = MINCORE_INCORE; 877567e51e1SAlan Cox } 878567e51e1SAlan Cox } 879567e51e1SAlan Cox if (m != NULL) { 880567e51e1SAlan Cox /* Examine other mappings to the page. */ 881567e51e1SAlan Cox if (m->dirty == 0 && pmap_is_modified(m)) 882567e51e1SAlan Cox vm_page_dirty(m); 883567e51e1SAlan Cox if (m->dirty != 0) 884867a482dSJohn Dyson mincoreinfo |= MINCORE_MODIFIED_OTHER; 885c46b90e9SAlan Cox /* 886c46b90e9SAlan Cox * The first test for PG_REFERENCED is an 887c46b90e9SAlan Cox * optimization. The second test is 888c46b90e9SAlan Cox * required because a concurrent pmap 889c46b90e9SAlan Cox * operation could clear the last reference 890c46b90e9SAlan Cox * and set PG_REFERENCED before the call to 891c46b90e9SAlan Cox * pmap_is_referenced(). 892c46b90e9SAlan Cox */ 893567e51e1SAlan Cox if ((m->flags & PG_REFERENCED) != 0 || 894c46b90e9SAlan Cox pmap_is_referenced(m) || 895c46b90e9SAlan Cox (m->flags & PG_REFERENCED) != 0) 896867a482dSJohn Dyson mincoreinfo |= MINCORE_REFERENCED_OTHER; 8979b5a5d81SJohn Dyson } 898567e51e1SAlan Cox if (object != NULL) 899567e51e1SAlan Cox VM_OBJECT_UNLOCK(object); 900867a482dSJohn Dyson 901867a482dSJohn Dyson /* 902dd2622a8SAlan Cox * subyte may page fault. In case it needs to modify 903dd2622a8SAlan Cox * the map, we release the lock. 904dd2622a8SAlan Cox */ 905dd2622a8SAlan Cox vm_map_unlock_read(map); 906dd2622a8SAlan Cox 907dd2622a8SAlan Cox /* 908867a482dSJohn Dyson * calculate index into user supplied byte vector 909867a482dSJohn Dyson */ 910867a482dSJohn Dyson vecindex = OFF_TO_IDX(addr - first_addr); 911867a482dSJohn Dyson 912867a482dSJohn Dyson /* 913867a482dSJohn Dyson * If we have skipped map entries, we need to make sure that 914867a482dSJohn Dyson * the byte vector is zeroed for those skipped entries. 915867a482dSJohn Dyson */ 916867a482dSJohn Dyson while ((lastvecindex + 1) < vecindex) { 917867a482dSJohn Dyson error = subyte(vec + lastvecindex, 0); 918867a482dSJohn Dyson if (error) { 919d2c60af8SMatthew Dillon error = EFAULT; 920d2c60af8SMatthew Dillon goto done2; 921867a482dSJohn Dyson } 922867a482dSJohn Dyson ++lastvecindex; 923867a482dSJohn Dyson } 924867a482dSJohn Dyson 925867a482dSJohn Dyson /* 926867a482dSJohn Dyson * Pass the page information to the user 927867a482dSJohn Dyson */ 928867a482dSJohn Dyson error = subyte(vec + vecindex, mincoreinfo); 929867a482dSJohn Dyson if (error) { 930d2c60af8SMatthew Dillon error = EFAULT; 931d2c60af8SMatthew Dillon goto done2; 932867a482dSJohn Dyson } 933dd2622a8SAlan Cox 934dd2622a8SAlan Cox /* 935dd2622a8SAlan Cox * If the map has changed, due to the subyte, the previous 936dd2622a8SAlan Cox * output may be invalid. 937dd2622a8SAlan Cox */ 938dd2622a8SAlan Cox vm_map_lock_read(map); 939dd2622a8SAlan Cox if (timestamp != map->timestamp) 940dd2622a8SAlan Cox goto RestartScan; 941dd2622a8SAlan Cox 942867a482dSJohn Dyson lastvecindex = vecindex; 94302c04a2fSJohn Dyson addr += PAGE_SIZE; 94402c04a2fSJohn Dyson } 945867a482dSJohn Dyson } 946867a482dSJohn Dyson 947867a482dSJohn Dyson /* 948dd2622a8SAlan Cox * subyte may page fault. In case it needs to modify 949dd2622a8SAlan Cox * the map, we release the lock. 950dd2622a8SAlan Cox */ 951dd2622a8SAlan Cox vm_map_unlock_read(map); 952dd2622a8SAlan Cox 953dd2622a8SAlan Cox /* 954867a482dSJohn Dyson * Zero the last entries in the byte vector. 955867a482dSJohn Dyson */ 956867a482dSJohn Dyson vecindex = OFF_TO_IDX(end - first_addr); 957867a482dSJohn Dyson while ((lastvecindex + 1) < vecindex) { 958867a482dSJohn Dyson error = subyte(vec + lastvecindex, 0); 959867a482dSJohn Dyson if (error) { 960d2c60af8SMatthew Dillon error = EFAULT; 961d2c60af8SMatthew Dillon goto done2; 962867a482dSJohn Dyson } 963867a482dSJohn Dyson ++lastvecindex; 964867a482dSJohn Dyson } 965867a482dSJohn Dyson 966dd2622a8SAlan Cox /* 967dd2622a8SAlan Cox * If the map has changed, due to the subyte, the previous 968dd2622a8SAlan Cox * output may be invalid. 969dd2622a8SAlan Cox */ 970dd2622a8SAlan Cox vm_map_lock_read(map); 971dd2622a8SAlan Cox if (timestamp != map->timestamp) 972dd2622a8SAlan Cox goto RestartScan; 973eff50fcdSAlan Cox vm_map_unlock_read(map); 974d2c60af8SMatthew Dillon done2: 975d2c60af8SMatthew Dillon return (error); 976df8bae1dSRodney W. Grimes } 977df8bae1dSRodney W. Grimes 978d2d3e875SBruce Evans #ifndef _SYS_SYSPROTO_H_ 979df8bae1dSRodney W. Grimes struct mlock_args { 980651bb817SAlexander Langer const void *addr; 981df8bae1dSRodney W. Grimes size_t len; 982df8bae1dSRodney W. Grimes }; 983d2d3e875SBruce Evans #endif 984d2c60af8SMatthew Dillon /* 985d2c60af8SMatthew Dillon * MPSAFE 986d2c60af8SMatthew Dillon */ 987df8bae1dSRodney W. Grimes int 988b40ce416SJulian Elischer mlock(td, uap) 989b40ce416SJulian Elischer struct thread *td; 990df8bae1dSRodney W. Grimes struct mlock_args *uap; 991df8bae1dSRodney W. Grimes { 992f0ea4612SDon Lewis struct proc *proc; 993bb734798SDon Lewis vm_offset_t addr, end, last, start; 994bb734798SDon Lewis vm_size_t npages, size; 995*1ba5ad42SEdward Tomasz Napierala unsigned long nsize; 996bb734798SDon Lewis int error; 997df8bae1dSRodney W. Grimes 998acd3428bSRobert Watson error = priv_check(td, PRIV_VM_MLOCK); 99947934cefSDon Lewis if (error) 100047934cefSDon Lewis return (error); 100116929939SDon Lewis addr = (vm_offset_t)uap->addr; 100216929939SDon Lewis size = uap->len; 1003bb734798SDon Lewis last = addr + size; 100416929939SDon Lewis start = trunc_page(addr); 1005bb734798SDon Lewis end = round_page(last); 1006bb734798SDon Lewis if (last < addr || end < addr) 1007df8bae1dSRodney W. Grimes return (EINVAL); 100816929939SDon Lewis npages = atop(end - start); 100916929939SDon Lewis if (npages > vm_page_max_wired) 101016929939SDon Lewis return (ENOMEM); 1011f0ea4612SDon Lewis proc = td->td_proc; 101247934cefSDon Lewis PROC_LOCK(proc); 1013*1ba5ad42SEdward Tomasz Napierala nsize = ptoa(npages + 1014*1ba5ad42SEdward Tomasz Napierala pmap_wired_count(vm_map_pmap(&proc->p_vmspace->vm_map))); 1015*1ba5ad42SEdward Tomasz Napierala if (nsize > lim_cur(proc, RLIMIT_MEMLOCK)) { 101647934cefSDon Lewis PROC_UNLOCK(proc); 10174a40e3d4SJohn Dyson return (ENOMEM); 101891d5354aSJohn Baldwin } 101947934cefSDon Lewis PROC_UNLOCK(proc); 10202feb50bfSAttilio Rao if (npages + cnt.v_wire_count > vm_page_max_wired) 102116929939SDon Lewis return (EAGAIN); 1022*1ba5ad42SEdward Tomasz Napierala PROC_LOCK(proc); 1023*1ba5ad42SEdward Tomasz Napierala error = racct_set(proc, RACCT_MEMLOCK, nsize); 1024*1ba5ad42SEdward Tomasz Napierala PROC_UNLOCK(proc); 1025*1ba5ad42SEdward Tomasz Napierala if (error != 0) 1026*1ba5ad42SEdward Tomasz Napierala return (ENOMEM); 102716929939SDon Lewis error = vm_map_wire(&proc->p_vmspace->vm_map, start, end, 102816929939SDon Lewis VM_MAP_WIRE_USER | VM_MAP_WIRE_NOHOLES); 1029*1ba5ad42SEdward Tomasz Napierala if (error != KERN_SUCCESS) { 1030*1ba5ad42SEdward Tomasz Napierala PROC_LOCK(proc); 1031*1ba5ad42SEdward Tomasz Napierala racct_set(proc, RACCT_MEMLOCK, 1032*1ba5ad42SEdward Tomasz Napierala ptoa(pmap_wired_count(vm_map_pmap(&proc->p_vmspace->vm_map)))); 1033*1ba5ad42SEdward Tomasz Napierala PROC_UNLOCK(proc); 1034*1ba5ad42SEdward Tomasz Napierala } 1035df8bae1dSRodney W. Grimes return (error == KERN_SUCCESS ? 0 : ENOMEM); 1036df8bae1dSRodney W. Grimes } 1037df8bae1dSRodney W. Grimes 1038d2d3e875SBruce Evans #ifndef _SYS_SYSPROTO_H_ 10394a40e3d4SJohn Dyson struct mlockall_args { 10404a40e3d4SJohn Dyson int how; 10414a40e3d4SJohn Dyson }; 10424a40e3d4SJohn Dyson #endif 10434a40e3d4SJohn Dyson 1044d2c60af8SMatthew Dillon /* 1045d2c60af8SMatthew Dillon * MPSAFE 1046d2c60af8SMatthew Dillon */ 10474a40e3d4SJohn Dyson int 1048b40ce416SJulian Elischer mlockall(td, uap) 1049b40ce416SJulian Elischer struct thread *td; 10504a40e3d4SJohn Dyson struct mlockall_args *uap; 10514a40e3d4SJohn Dyson { 1052abd498aaSBruce M Simpson vm_map_t map; 1053abd498aaSBruce M Simpson int error; 1054abd498aaSBruce M Simpson 1055abd498aaSBruce M Simpson map = &td->td_proc->p_vmspace->vm_map; 1056abd498aaSBruce M Simpson error = 0; 1057abd498aaSBruce M Simpson 1058abd498aaSBruce M Simpson if ((uap->how == 0) || ((uap->how & ~(MCL_CURRENT|MCL_FUTURE)) != 0)) 1059abd498aaSBruce M Simpson return (EINVAL); 1060abd498aaSBruce M Simpson 106111f7ddc5SBruce M Simpson #if 0 1062abd498aaSBruce M Simpson /* 1063abd498aaSBruce M Simpson * If wiring all pages in the process would cause it to exceed 1064abd498aaSBruce M Simpson * a hard resource limit, return ENOMEM. 1065abd498aaSBruce M Simpson */ 106691d5354aSJohn Baldwin PROC_LOCK(td->td_proc); 1067fd6f4ffbSEdward Tomasz Napierala if (map->size > lim_cur(td->td_proc, RLIMIT_MEMLOCK)) { 106891d5354aSJohn Baldwin PROC_UNLOCK(td->td_proc); 1069abd498aaSBruce M Simpson return (ENOMEM); 107091d5354aSJohn Baldwin } 107191d5354aSJohn Baldwin PROC_UNLOCK(td->td_proc); 1072abd498aaSBruce M Simpson #else 1073acd3428bSRobert Watson error = priv_check(td, PRIV_VM_MLOCK); 1074abd498aaSBruce M Simpson if (error) 1075abd498aaSBruce M Simpson return (error); 1076abd498aaSBruce M Simpson #endif 1077*1ba5ad42SEdward Tomasz Napierala PROC_LOCK(td->td_proc); 1078*1ba5ad42SEdward Tomasz Napierala error = racct_set(td->td_proc, RACCT_MEMLOCK, map->size); 1079*1ba5ad42SEdward Tomasz Napierala PROC_UNLOCK(td->td_proc); 1080*1ba5ad42SEdward Tomasz Napierala if (error != 0) 1081*1ba5ad42SEdward Tomasz Napierala return (ENOMEM); 1082abd498aaSBruce M Simpson 1083abd498aaSBruce M Simpson if (uap->how & MCL_FUTURE) { 1084abd498aaSBruce M Simpson vm_map_lock(map); 1085abd498aaSBruce M Simpson vm_map_modflags(map, MAP_WIREFUTURE, 0); 1086abd498aaSBruce M Simpson vm_map_unlock(map); 1087abd498aaSBruce M Simpson error = 0; 1088abd498aaSBruce M Simpson } 1089abd498aaSBruce M Simpson 1090abd498aaSBruce M Simpson if (uap->how & MCL_CURRENT) { 1091abd498aaSBruce M Simpson /* 1092abd498aaSBruce M Simpson * P1003.1-2001 mandates that all currently mapped pages 1093abd498aaSBruce M Simpson * will be memory resident and locked (wired) upon return 1094abd498aaSBruce M Simpson * from mlockall(). vm_map_wire() will wire pages, by 1095abd498aaSBruce M Simpson * calling vm_fault_wire() for each page in the region. 1096abd498aaSBruce M Simpson */ 1097abd498aaSBruce M Simpson error = vm_map_wire(map, vm_map_min(map), vm_map_max(map), 1098abd498aaSBruce M Simpson VM_MAP_WIRE_USER|VM_MAP_WIRE_HOLESOK); 1099abd498aaSBruce M Simpson error = (error == KERN_SUCCESS ? 0 : EAGAIN); 1100abd498aaSBruce M Simpson } 1101*1ba5ad42SEdward Tomasz Napierala if (error != KERN_SUCCESS) { 1102*1ba5ad42SEdward Tomasz Napierala PROC_LOCK(td->td_proc); 1103*1ba5ad42SEdward Tomasz Napierala racct_set(td->td_proc, RACCT_MEMLOCK, 1104*1ba5ad42SEdward Tomasz Napierala ptoa(pmap_wired_count(vm_map_pmap(&td->td_proc->p_vmspace->vm_map)))); 1105*1ba5ad42SEdward Tomasz Napierala PROC_UNLOCK(td->td_proc); 1106*1ba5ad42SEdward Tomasz Napierala } 1107abd498aaSBruce M Simpson 1108abd498aaSBruce M Simpson return (error); 11094a40e3d4SJohn Dyson } 11104a40e3d4SJohn Dyson 11114a40e3d4SJohn Dyson #ifndef _SYS_SYSPROTO_H_ 1112fa721254SAlfred Perlstein struct munlockall_args { 1113abd498aaSBruce M Simpson register_t dummy; 11144a40e3d4SJohn Dyson }; 11154a40e3d4SJohn Dyson #endif 11164a40e3d4SJohn Dyson 1117d2c60af8SMatthew Dillon /* 1118d2c60af8SMatthew Dillon * MPSAFE 1119d2c60af8SMatthew Dillon */ 11204a40e3d4SJohn Dyson int 1121b40ce416SJulian Elischer munlockall(td, uap) 1122b40ce416SJulian Elischer struct thread *td; 11234a40e3d4SJohn Dyson struct munlockall_args *uap; 11244a40e3d4SJohn Dyson { 1125abd498aaSBruce M Simpson vm_map_t map; 1126abd498aaSBruce M Simpson int error; 1127abd498aaSBruce M Simpson 1128abd498aaSBruce M Simpson map = &td->td_proc->p_vmspace->vm_map; 1129acd3428bSRobert Watson error = priv_check(td, PRIV_VM_MUNLOCK); 1130abd498aaSBruce M Simpson if (error) 1131abd498aaSBruce M Simpson return (error); 1132abd498aaSBruce M Simpson 1133abd498aaSBruce M Simpson /* Clear the MAP_WIREFUTURE flag from this vm_map. */ 1134abd498aaSBruce M Simpson vm_map_lock(map); 1135abd498aaSBruce M Simpson vm_map_modflags(map, 0, MAP_WIREFUTURE); 1136abd498aaSBruce M Simpson vm_map_unlock(map); 1137abd498aaSBruce M Simpson 1138abd498aaSBruce M Simpson /* Forcibly unwire all pages. */ 1139abd498aaSBruce M Simpson error = vm_map_unwire(map, vm_map_min(map), vm_map_max(map), 1140abd498aaSBruce M Simpson VM_MAP_WIRE_USER|VM_MAP_WIRE_HOLESOK); 1141*1ba5ad42SEdward Tomasz Napierala if (error == KERN_SUCCESS) { 1142*1ba5ad42SEdward Tomasz Napierala PROC_LOCK(td->td_proc); 1143*1ba5ad42SEdward Tomasz Napierala racct_set(td->td_proc, RACCT_MEMLOCK, 0); 1144*1ba5ad42SEdward Tomasz Napierala PROC_UNLOCK(td->td_proc); 1145*1ba5ad42SEdward Tomasz Napierala } 1146abd498aaSBruce M Simpson 1147abd498aaSBruce M Simpson return (error); 11484a40e3d4SJohn Dyson } 11494a40e3d4SJohn Dyson 11504a40e3d4SJohn Dyson #ifndef _SYS_SYSPROTO_H_ 1151df8bae1dSRodney W. Grimes struct munlock_args { 1152651bb817SAlexander Langer const void *addr; 1153df8bae1dSRodney W. Grimes size_t len; 1154df8bae1dSRodney W. Grimes }; 1155d2d3e875SBruce Evans #endif 1156d2c60af8SMatthew Dillon /* 1157d2c60af8SMatthew Dillon * MPSAFE 1158d2c60af8SMatthew Dillon */ 1159df8bae1dSRodney W. Grimes int 1160b40ce416SJulian Elischer munlock(td, uap) 1161b40ce416SJulian Elischer struct thread *td; 1162df8bae1dSRodney W. Grimes struct munlock_args *uap; 1163df8bae1dSRodney W. Grimes { 1164bb734798SDon Lewis vm_offset_t addr, end, last, start; 116516929939SDon Lewis vm_size_t size; 1166df8bae1dSRodney W. Grimes int error; 1167df8bae1dSRodney W. Grimes 1168acd3428bSRobert Watson error = priv_check(td, PRIV_VM_MUNLOCK); 116947934cefSDon Lewis if (error) 117047934cefSDon Lewis return (error); 117116929939SDon Lewis addr = (vm_offset_t)uap->addr; 117216929939SDon Lewis size = uap->len; 1173bb734798SDon Lewis last = addr + size; 117416929939SDon Lewis start = trunc_page(addr); 1175bb734798SDon Lewis end = round_page(last); 1176bb734798SDon Lewis if (last < addr || end < addr) 1177df8bae1dSRodney W. Grimes return (EINVAL); 117816929939SDon Lewis error = vm_map_unwire(&td->td_proc->p_vmspace->vm_map, start, end, 117916929939SDon Lewis VM_MAP_WIRE_USER | VM_MAP_WIRE_NOHOLES); 1180*1ba5ad42SEdward Tomasz Napierala if (error == KERN_SUCCESS) { 1181*1ba5ad42SEdward Tomasz Napierala PROC_LOCK(td->td_proc); 1182*1ba5ad42SEdward Tomasz Napierala racct_sub(td->td_proc, RACCT_MEMLOCK, ptoa(end - start)); 1183*1ba5ad42SEdward Tomasz Napierala PROC_UNLOCK(td->td_proc); 1184*1ba5ad42SEdward Tomasz Napierala } 1185df8bae1dSRodney W. Grimes return (error == KERN_SUCCESS ? 0 : ENOMEM); 1186df8bae1dSRodney W. Grimes } 1187df8bae1dSRodney W. Grimes 1188df8bae1dSRodney W. Grimes /* 1189c8daea13SAlexander Kabaev * vm_mmap_vnode() 1190c8daea13SAlexander Kabaev * 1191c8daea13SAlexander Kabaev * MPSAFE 1192c8daea13SAlexander Kabaev * 1193c8daea13SAlexander Kabaev * Helper function for vm_mmap. Perform sanity check specific for mmap 1194c8daea13SAlexander Kabaev * operations on vnodes. 1195c8daea13SAlexander Kabaev */ 1196c8daea13SAlexander Kabaev int 1197c8daea13SAlexander Kabaev vm_mmap_vnode(struct thread *td, vm_size_t objsize, 1198c8daea13SAlexander Kabaev vm_prot_t prot, vm_prot_t *maxprotp, int *flagsp, 119964345f0bSJohn Baldwin struct vnode *vp, vm_ooffset_t *foffp, vm_object_t *objp) 1200c8daea13SAlexander Kabaev { 1201c8daea13SAlexander Kabaev struct vattr va; 1202c8daea13SAlexander Kabaev vm_object_t obj; 120364345f0bSJohn Baldwin vm_offset_t foff; 1204ae51ff11SJeff Roberson struct mount *mp; 12050359a12eSAttilio Rao struct ucred *cred; 120664345f0bSJohn Baldwin int error, flags; 1207ae51ff11SJeff Roberson int vfslocked; 1208c8daea13SAlexander Kabaev 1209ae51ff11SJeff Roberson mp = vp->v_mount; 12100359a12eSAttilio Rao cred = td->td_ucred; 1211ae51ff11SJeff Roberson vfslocked = VFS_LOCK_GIANT(mp); 1212fa3de770SJohn Baldwin if ((error = vget(vp, LK_SHARED, td)) != 0) { 1213ae51ff11SJeff Roberson VFS_UNLOCK_GIANT(vfslocked); 1214c8daea13SAlexander Kabaev return (error); 1215c8daea13SAlexander Kabaev } 121664345f0bSJohn Baldwin foff = *foffp; 1217c8daea13SAlexander Kabaev flags = *flagsp; 12188516dd18SPoul-Henning Kamp obj = vp->v_object; 1219c8daea13SAlexander Kabaev if (vp->v_type == VREG) { 1220c8daea13SAlexander Kabaev /* 1221c8daea13SAlexander Kabaev * Get the proper underlying object 1222c8daea13SAlexander Kabaev */ 12238516dd18SPoul-Henning Kamp if (obj == NULL) { 1224c8daea13SAlexander Kabaev error = EINVAL; 1225c8daea13SAlexander Kabaev goto done; 1226c8daea13SAlexander Kabaev } 1227c8daea13SAlexander Kabaev if (obj->handle != vp) { 1228c8daea13SAlexander Kabaev vput(vp); 1229c8daea13SAlexander Kabaev vp = (struct vnode*)obj->handle; 1230fa3de770SJohn Baldwin vget(vp, LK_SHARED, td); 1231c8daea13SAlexander Kabaev } 1232c8daea13SAlexander Kabaev } else if (vp->v_type == VCHR) { 123364345f0bSJohn Baldwin error = vm_mmap_cdev(td, objsize, prot, maxprotp, flagsp, 123464345f0bSJohn Baldwin vp->v_rdev, foffp, objp); 123564345f0bSJohn Baldwin if (error == 0) 123664345f0bSJohn Baldwin goto mark_atime; 123791a35e78SKonstantin Belousov goto done; 1238c8daea13SAlexander Kabaev } else { 1239c8daea13SAlexander Kabaev error = EINVAL; 1240c8daea13SAlexander Kabaev goto done; 1241c8daea13SAlexander Kabaev } 12420359a12eSAttilio Rao if ((error = VOP_GETATTR(vp, &va, cred))) 1243c8daea13SAlexander Kabaev goto done; 1244c92163dcSChristian S.J. Peron #ifdef MAC 12450359a12eSAttilio Rao error = mac_vnode_check_mmap(cred, vp, prot, flags); 1246c92163dcSChristian S.J. Peron if (error != 0) 1247c92163dcSChristian S.J. Peron goto done; 1248c92163dcSChristian S.J. Peron #endif 1249c8daea13SAlexander Kabaev if ((flags & MAP_SHARED) != 0) { 1250c8daea13SAlexander Kabaev if ((va.va_flags & (SF_SNAPSHOT|IMMUTABLE|APPEND)) != 0) { 1251c8daea13SAlexander Kabaev if (prot & PROT_WRITE) { 1252c8daea13SAlexander Kabaev error = EPERM; 1253c8daea13SAlexander Kabaev goto done; 1254c8daea13SAlexander Kabaev } 1255c8daea13SAlexander Kabaev *maxprotp &= ~VM_PROT_WRITE; 1256c8daea13SAlexander Kabaev } 1257c8daea13SAlexander Kabaev } 1258c8daea13SAlexander Kabaev /* 1259c8daea13SAlexander Kabaev * If it is a regular file without any references 1260c8daea13SAlexander Kabaev * we do not need to sync it. 1261c8daea13SAlexander Kabaev * Adjust object size to be the size of actual file. 1262c8daea13SAlexander Kabaev */ 1263c8daea13SAlexander Kabaev objsize = round_page(va.va_size); 1264c8daea13SAlexander Kabaev if (va.va_nlink == 0) 1265c8daea13SAlexander Kabaev flags |= MAP_NOSYNC; 12663364c323SKonstantin Belousov obj = vm_pager_allocate(OBJT_VNODE, vp, objsize, prot, foff, td->td_ucred); 1267c8daea13SAlexander Kabaev if (obj == NULL) { 126864345f0bSJohn Baldwin error = ENOMEM; 1269c8daea13SAlexander Kabaev goto done; 1270c8daea13SAlexander Kabaev } 1271c8daea13SAlexander Kabaev *objp = obj; 1272c8daea13SAlexander Kabaev *flagsp = flags; 127364345f0bSJohn Baldwin 127464345f0bSJohn Baldwin mark_atime: 12750359a12eSAttilio Rao vfs_mark_atime(vp, cred); 12761e309003SDiomidis Spinellis 1277c8daea13SAlexander Kabaev done: 1278c8daea13SAlexander Kabaev vput(vp); 1279ae51ff11SJeff Roberson VFS_UNLOCK_GIANT(vfslocked); 1280c8daea13SAlexander Kabaev return (error); 1281c8daea13SAlexander Kabaev } 1282c8daea13SAlexander Kabaev 1283c8daea13SAlexander Kabaev /* 128498df9218SJohn Baldwin * vm_mmap_cdev() 128598df9218SJohn Baldwin * 128698df9218SJohn Baldwin * MPSAFE 128798df9218SJohn Baldwin * 128898df9218SJohn Baldwin * Helper function for vm_mmap. Perform sanity check specific for mmap 128998df9218SJohn Baldwin * operations on cdevs. 129098df9218SJohn Baldwin */ 129198df9218SJohn Baldwin int 129298df9218SJohn Baldwin vm_mmap_cdev(struct thread *td, vm_size_t objsize, 129398df9218SJohn Baldwin vm_prot_t prot, vm_prot_t *maxprotp, int *flagsp, 129464345f0bSJohn Baldwin struct cdev *cdev, vm_ooffset_t *foff, vm_object_t *objp) 129598df9218SJohn Baldwin { 129698df9218SJohn Baldwin vm_object_t obj; 129791a35e78SKonstantin Belousov struct cdevsw *dsw; 12983979450bSKonstantin Belousov int error, flags, ref; 129998df9218SJohn Baldwin 130098df9218SJohn Baldwin flags = *flagsp; 130198df9218SJohn Baldwin 13023979450bSKonstantin Belousov dsw = dev_refthread(cdev, &ref); 130391a35e78SKonstantin Belousov if (dsw == NULL) 130491a35e78SKonstantin Belousov return (ENXIO); 130591a35e78SKonstantin Belousov if (dsw->d_flags & D_MMAP_ANON) { 13063979450bSKonstantin Belousov dev_relthread(cdev, ref); 130798df9218SJohn Baldwin *maxprotp = VM_PROT_ALL; 130898df9218SJohn Baldwin *flagsp |= MAP_ANON; 130998df9218SJohn Baldwin return (0); 131098df9218SJohn Baldwin } 131198df9218SJohn Baldwin /* 131264345f0bSJohn Baldwin * cdevs do not provide private mappings of any kind. 131398df9218SJohn Baldwin */ 131498df9218SJohn Baldwin if ((*maxprotp & VM_PROT_WRITE) == 0 && 131564345f0bSJohn Baldwin (prot & PROT_WRITE) != 0) { 13163979450bSKonstantin Belousov dev_relthread(cdev, ref); 131798df9218SJohn Baldwin return (EACCES); 131864345f0bSJohn Baldwin } 131964345f0bSJohn Baldwin if (flags & (MAP_PRIVATE|MAP_COPY)) { 13203979450bSKonstantin Belousov dev_relthread(cdev, ref); 132198df9218SJohn Baldwin return (EINVAL); 132264345f0bSJohn Baldwin } 132398df9218SJohn Baldwin /* 132498df9218SJohn Baldwin * Force device mappings to be shared. 132598df9218SJohn Baldwin */ 132698df9218SJohn Baldwin flags |= MAP_SHARED; 132798df9218SJohn Baldwin #ifdef MAC_XXX 132864345f0bSJohn Baldwin error = mac_cdev_check_mmap(td->td_ucred, cdev, prot); 132964345f0bSJohn Baldwin if (error != 0) { 13303979450bSKonstantin Belousov dev_relthread(cdev, ref); 133198df9218SJohn Baldwin return (error); 133264345f0bSJohn Baldwin } 133398df9218SJohn Baldwin #endif 133464345f0bSJohn Baldwin /* 133564345f0bSJohn Baldwin * First, try d_mmap_single(). If that is not implemented 133664345f0bSJohn Baldwin * (returns ENODEV), fall back to using the device pager. 133764345f0bSJohn Baldwin * Note that d_mmap_single() must return a reference to the 133864345f0bSJohn Baldwin * object (it needs to bump the reference count of the object 133964345f0bSJohn Baldwin * it returns somehow). 134064345f0bSJohn Baldwin * 134164345f0bSJohn Baldwin * XXX assumes VM_PROT_* == PROT_* 134264345f0bSJohn Baldwin */ 134364345f0bSJohn Baldwin error = dsw->d_mmap_single(cdev, foff, objsize, objp, (int)prot); 13443979450bSKonstantin Belousov dev_relthread(cdev, ref); 134564345f0bSJohn Baldwin if (error != ENODEV) 134664345f0bSJohn Baldwin return (error); 13473364c323SKonstantin Belousov obj = vm_pager_allocate(OBJT_DEVICE, cdev, objsize, prot, *foff, 13483364c323SKonstantin Belousov td->td_ucred); 134998df9218SJohn Baldwin if (obj == NULL) 135098df9218SJohn Baldwin return (EINVAL); 135198df9218SJohn Baldwin *objp = obj; 135298df9218SJohn Baldwin *flagsp = flags; 135398df9218SJohn Baldwin return (0); 135498df9218SJohn Baldwin } 135598df9218SJohn Baldwin 135698df9218SJohn Baldwin /* 13578e38aeffSJohn Baldwin * vm_mmap_shm() 13588e38aeffSJohn Baldwin * 13598e38aeffSJohn Baldwin * MPSAFE 13608e38aeffSJohn Baldwin * 13618e38aeffSJohn Baldwin * Helper function for vm_mmap. Perform sanity check specific for mmap 13628e38aeffSJohn Baldwin * operations on shm file descriptors. 13638e38aeffSJohn Baldwin */ 13648e38aeffSJohn Baldwin int 13658e38aeffSJohn Baldwin vm_mmap_shm(struct thread *td, vm_size_t objsize, 13668e38aeffSJohn Baldwin vm_prot_t prot, vm_prot_t *maxprotp, int *flagsp, 13678e38aeffSJohn Baldwin struct shmfd *shmfd, vm_ooffset_t foff, vm_object_t *objp) 13688e38aeffSJohn Baldwin { 13698e38aeffSJohn Baldwin int error; 13708e38aeffSJohn Baldwin 1371da048309SAlan Cox if ((*flagsp & MAP_SHARED) != 0 && 1372da048309SAlan Cox (*maxprotp & VM_PROT_WRITE) == 0 && 13738e38aeffSJohn Baldwin (prot & PROT_WRITE) != 0) 13748e38aeffSJohn Baldwin return (EACCES); 13758e38aeffSJohn Baldwin #ifdef MAC 13768e38aeffSJohn Baldwin error = mac_posixshm_check_mmap(td->td_ucred, shmfd, prot, *flagsp); 13778e38aeffSJohn Baldwin if (error != 0) 13788e38aeffSJohn Baldwin return (error); 13798e38aeffSJohn Baldwin #endif 13808e38aeffSJohn Baldwin error = shm_mmap(shmfd, objsize, foff, objp); 13818e38aeffSJohn Baldwin if (error) 13828e38aeffSJohn Baldwin return (error); 13838e38aeffSJohn Baldwin return (0); 13848e38aeffSJohn Baldwin } 13858e38aeffSJohn Baldwin 13868e38aeffSJohn Baldwin /* 1387d2c60af8SMatthew Dillon * vm_mmap() 1388d2c60af8SMatthew Dillon * 1389d2c60af8SMatthew Dillon * MPSAFE 1390d2c60af8SMatthew Dillon * 1391d2c60af8SMatthew Dillon * Internal version of mmap. Currently used by mmap, exec, and sys5 1392d2c60af8SMatthew Dillon * shared memory. Handle is either a vnode pointer or NULL for MAP_ANON. 1393df8bae1dSRodney W. Grimes */ 1394df8bae1dSRodney W. Grimes int 1395b9dcd593SBruce Evans vm_mmap(vm_map_t map, vm_offset_t *addr, vm_size_t size, vm_prot_t prot, 1396b9dcd593SBruce Evans vm_prot_t maxprot, int flags, 139798df9218SJohn Baldwin objtype_t handle_type, void *handle, 1398b9dcd593SBruce Evans vm_ooffset_t foff) 1399df8bae1dSRodney W. Grimes { 1400df8bae1dSRodney W. Grimes boolean_t fitit; 14016bda842dSMatt Jacob vm_object_t object = NULL; 1402df8bae1dSRodney W. Grimes int rv = KERN_SUCCESS; 140320eec4bbSAlan Cox int docow, error; 1404b40ce416SJulian Elischer struct thread *td = curthread; 1405df8bae1dSRodney W. Grimes 1406df8bae1dSRodney W. Grimes if (size == 0) 1407df8bae1dSRodney W. Grimes return (0); 1408df8bae1dSRodney W. Grimes 1409749474f2SPeter Wemm size = round_page(size); 1410df8bae1dSRodney W. Grimes 141191d5354aSJohn Baldwin PROC_LOCK(td->td_proc); 1412070f64feSMatthew Dillon if (td->td_proc->p_vmspace->vm_map.size + size > 141391d5354aSJohn Baldwin lim_cur(td->td_proc, RLIMIT_VMEM)) { 141491d5354aSJohn Baldwin PROC_UNLOCK(td->td_proc); 1415070f64feSMatthew Dillon return(ENOMEM); 1416070f64feSMatthew Dillon } 1417*1ba5ad42SEdward Tomasz Napierala if (racct_set(td->td_proc, RACCT_VMEM, 1418*1ba5ad42SEdward Tomasz Napierala td->td_proc->p_vmspace->vm_map.size + size)) { 1419*1ba5ad42SEdward Tomasz Napierala PROC_UNLOCK(td->td_proc); 1420*1ba5ad42SEdward Tomasz Napierala return (ENOMEM); 1421*1ba5ad42SEdward Tomasz Napierala } 142291d5354aSJohn Baldwin PROC_UNLOCK(td->td_proc); 1423070f64feSMatthew Dillon 1424df8bae1dSRodney W. Grimes /* 1425bc9ad247SDavid Greenman * We currently can only deal with page aligned file offsets. 1426bc9ad247SDavid Greenman * The check is here rather than in the syscall because the 1427bc9ad247SDavid Greenman * kernel calls this function internally for other mmaping 1428bc9ad247SDavid Greenman * operations (such as in exec) and non-aligned offsets will 1429bc9ad247SDavid Greenman * cause pmap inconsistencies...so we want to be sure to 1430bc9ad247SDavid Greenman * disallow this in all cases. 1431bc9ad247SDavid Greenman */ 1432bc9ad247SDavid Greenman if (foff & PAGE_MASK) 1433bc9ad247SDavid Greenman return (EINVAL); 1434bc9ad247SDavid Greenman 143506cb7259SDavid Greenman if ((flags & MAP_FIXED) == 0) { 143606cb7259SDavid Greenman fitit = TRUE; 143706cb7259SDavid Greenman *addr = round_page(*addr); 143806cb7259SDavid Greenman } else { 143906cb7259SDavid Greenman if (*addr != trunc_page(*addr)) 144006cb7259SDavid Greenman return (EINVAL); 144106cb7259SDavid Greenman fitit = FALSE; 144206cb7259SDavid Greenman } 1443bc9ad247SDavid Greenman /* 144424a1cce3SDavid Greenman * Lookup/allocate object. 1445df8bae1dSRodney W. Grimes */ 144698df9218SJohn Baldwin switch (handle_type) { 144798df9218SJohn Baldwin case OBJT_DEVICE: 144898df9218SJohn Baldwin error = vm_mmap_cdev(td, size, prot, &maxprot, &flags, 144964345f0bSJohn Baldwin handle, &foff, &object); 145098df9218SJohn Baldwin break; 145198df9218SJohn Baldwin case OBJT_VNODE: 1452c8daea13SAlexander Kabaev error = vm_mmap_vnode(td, size, prot, &maxprot, &flags, 145364345f0bSJohn Baldwin handle, &foff, &object); 145498df9218SJohn Baldwin break; 14558e38aeffSJohn Baldwin case OBJT_SWAP: 14568e38aeffSJohn Baldwin error = vm_mmap_shm(td, size, prot, &maxprot, &flags, 14578e38aeffSJohn Baldwin handle, foff, &object); 14588e38aeffSJohn Baldwin break; 145998df9218SJohn Baldwin case OBJT_DEFAULT: 146098df9218SJohn Baldwin if (handle == NULL) { 146198df9218SJohn Baldwin error = 0; 146298df9218SJohn Baldwin break; 146398df9218SJohn Baldwin } 146498df9218SJohn Baldwin /* FALLTHROUGH */ 146598df9218SJohn Baldwin default: 146698df9218SJohn Baldwin error = EINVAL; 14676bda842dSMatt Jacob break; 146898df9218SJohn Baldwin } 146998df9218SJohn Baldwin if (error) 1470c8daea13SAlexander Kabaev return (error); 14715f55e841SDavid Greenman if (flags & MAP_ANON) { 1472c8daea13SAlexander Kabaev object = NULL; 1473c8daea13SAlexander Kabaev docow = 0; 14745f55e841SDavid Greenman /* 14755f55e841SDavid Greenman * Unnamed anonymous regions always start at 0. 14765f55e841SDavid Greenman */ 147767bf6868SJohn Dyson if (handle == 0) 14785f55e841SDavid Greenman foff = 0; 147974ffb9afSAlan Cox } else if (flags & MAP_PREFAULT_READ) 148074ffb9afSAlan Cox docow = MAP_PREFAULT; 148174ffb9afSAlan Cox else 14824738fa09SAlan Cox docow = MAP_PREFAULT_PARTIAL; 1483df8bae1dSRodney W. Grimes 14844f79d873SMatthew Dillon if ((flags & (MAP_ANON|MAP_SHARED)) == 0) 14854738fa09SAlan Cox docow |= MAP_COPY_ON_WRITE; 14864f79d873SMatthew Dillon if (flags & MAP_NOSYNC) 14874f79d873SMatthew Dillon docow |= MAP_DISABLE_SYNCER; 14889730a5daSPaul Saab if (flags & MAP_NOCORE) 14899730a5daSPaul Saab docow |= MAP_DISABLE_COREDUMP; 14905850152dSJohn Dyson 14912267af78SJulian Elischer if (flags & MAP_STACK) 1492fd75d710SMarcel Moolenaar rv = vm_map_stack(map, *addr, size, prot, maxprot, 1493fd75d710SMarcel Moolenaar docow | MAP_STACK_GROWS_DOWN); 1494d239bd3cSKonstantin Belousov else if (fitit) 1495d0a83a83SAlan Cox rv = vm_map_find(map, object, foff, addr, size, 1496d0a83a83SAlan Cox object != NULL && object->type == OBJT_DEVICE ? 1497d0a83a83SAlan Cox VMFS_ALIGNED_SPACE : VMFS_ANY_SPACE, prot, maxprot, docow); 14982267af78SJulian Elischer else 1499b8ca4ef2SAlan Cox rv = vm_map_fixed(map, object, foff, *addr, size, 1500bd7e5f99SJohn Dyson prot, maxprot, docow); 1501bd7e5f99SJohn Dyson 1502d2c60af8SMatthew Dillon if (rv != KERN_SUCCESS) { 15037fb0c17eSDavid Greenman /* 150424a1cce3SDavid Greenman * Lose the object reference. Will destroy the 150524a1cce3SDavid Greenman * object if it's an unnamed anonymous mapping 150624a1cce3SDavid Greenman * or named anonymous without other references. 15077fb0c17eSDavid Greenman */ 1508df8bae1dSRodney W. Grimes vm_object_deallocate(object); 1509d2c60af8SMatthew Dillon } else if (flags & MAP_SHARED) { 1510df8bae1dSRodney W. Grimes /* 1511df8bae1dSRodney W. Grimes * Shared memory is also shared with children. 1512df8bae1dSRodney W. Grimes */ 1513df8bae1dSRodney W. Grimes rv = vm_map_inherit(map, *addr, *addr + size, VM_INHERIT_SHARE); 1514e4ca250dSJohn Baldwin if (rv != KERN_SUCCESS) 15157fb0c17eSDavid Greenman (void) vm_map_remove(map, *addr, *addr + size); 1516df8bae1dSRodney W. Grimes } 1517abd498aaSBruce M Simpson 1518abd498aaSBruce M Simpson /* 1519abd498aaSBruce M Simpson * If the process has requested that all future mappings 1520abd498aaSBruce M Simpson * be wired, then heed this. 1521abd498aaSBruce M Simpson */ 1522abd498aaSBruce M Simpson if ((rv == KERN_SUCCESS) && (map->flags & MAP_WIREFUTURE)) 1523abd498aaSBruce M Simpson vm_map_wire(map, *addr, *addr + size, 1524abd498aaSBruce M Simpson VM_MAP_WIRE_USER|VM_MAP_WIRE_NOHOLES); 1525abd498aaSBruce M Simpson 1526df8bae1dSRodney W. Grimes switch (rv) { 1527df8bae1dSRodney W. Grimes case KERN_SUCCESS: 1528df8bae1dSRodney W. Grimes return (0); 1529df8bae1dSRodney W. Grimes case KERN_INVALID_ADDRESS: 1530df8bae1dSRodney W. Grimes case KERN_NO_SPACE: 1531df8bae1dSRodney W. Grimes return (ENOMEM); 1532df8bae1dSRodney W. Grimes case KERN_PROTECTION_FAILURE: 1533df8bae1dSRodney W. Grimes return (EACCES); 1534df8bae1dSRodney W. Grimes default: 1535df8bae1dSRodney W. Grimes return (EINVAL); 1536df8bae1dSRodney W. Grimes } 1537df8bae1dSRodney W. Grimes } 1538