Annotation of src/sys/uvm/uvm_mmap.c, Revision 1.149
1.149 ! matt 1: /* $NetBSD: uvm_mmap.c,v 1.148 2014/01/25 17:30:45 christos Exp $ */
1.1 mrg 2:
3: /*
4: * Copyright (c) 1997 Charles D. Cranor and Washington University.
1.51 chs 5: * Copyright (c) 1991, 1993 The Regents of the University of California.
1.1 mrg 6: * Copyright (c) 1988 University of Utah.
1.51 chs 7: *
1.1 mrg 8: * All rights reserved.
9: *
10: * This code is derived from software contributed to Berkeley by
11: * the Systems Programming Group of the University of Utah Computer
12: * Science Department.
13: *
14: * Redistribution and use in source and binary forms, with or without
15: * modification, are permitted provided that the following conditions
16: * are met:
17: * 1. Redistributions of source code must retain the above copyright
18: * notice, this list of conditions and the following disclaimer.
19: * 2. Redistributions in binary form must reproduce the above copyright
20: * notice, this list of conditions and the following disclaimer in the
21: * documentation and/or other materials provided with the distribution.
1.134 chuck 22: * 3. Neither the name of the University nor the names of its contributors
1.1 mrg 23: * may be used to endorse or promote products derived from this software
24: * without specific prior written permission.
25: *
26: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
27: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
28: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
29: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
30: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
31: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
32: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
33: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
34: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
35: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
36: * SUCH DAMAGE.
37: *
38: * from: Utah $Hdr: vm_mmap.c 1.6 91/10/21$
39: * @(#)vm_mmap.c 8.5 (Berkeley) 5/19/94
1.3 mrg 40: * from: Id: uvm_mmap.c,v 1.1.2.14 1998/01/05 21:04:26 chuck Exp
1.1 mrg 41: */
42:
43: /*
44: * uvm_mmap.c: system call interface into VM system, plus kernel vm_mmap
45: * function.
46: */
1.60 lukem 47:
48: #include <sys/cdefs.h>
1.149 ! matt 49: __KERNEL_RCSID(0, "$NetBSD: uvm_mmap.c,v 1.148 2014/01/25 17:30:45 christos Exp $");
1.80 jdolecek 50:
51: #include "opt_compat_netbsd.h"
1.97 elad 52: #include "opt_pax.h"
1.99 elad 53: #include "veriexec.h"
1.60 lukem 54:
1.1 mrg 55: #include <sys/param.h>
56: #include <sys/systm.h>
57: #include <sys/file.h>
58: #include <sys/filedesc.h>
59: #include <sys/resourcevar.h>
60: #include <sys/mman.h>
61: #include <sys/mount.h>
62: #include <sys/vnode.h>
63: #include <sys/conf.h>
1.9 mrg 64: #include <sys/stat.h>
1.99 elad 65:
66: #if NVERIEXEC > 0
67: #include <sys/verified_exec.h>
68: #endif /* NVERIEXEC > 0 */
1.97 elad 69:
1.137 matt 70: #if defined(PAX_ASLR) || defined(PAX_MPROTECT)
1.97 elad 71: #include <sys/pax.h>
1.137 matt 72: #endif /* PAX_ASLR || PAX_MPROTECT */
1.1 mrg 73:
74: #include <miscfs/specfs/specdev.h>
75:
76: #include <sys/syscallargs.h>
77:
78: #include <uvm/uvm.h>
79: #include <uvm/uvm_device.h>
80:
1.80 jdolecek 81: #ifndef COMPAT_ZERODEV
1.81 dsl 82: #define COMPAT_ZERODEV(dev) (0)
1.80 jdolecek 83: #endif
1.1 mrg 84:
1.115 yamt 85: static int
86: range_test(vaddr_t addr, vsize_t size, bool ismmap)
87: {
88: vaddr_t vm_min_address = VM_MIN_ADDRESS;
89: vaddr_t vm_max_address = VM_MAXUSER_ADDRESS;
90: vaddr_t eaddr = addr + size;
1.145 martin 91: int res = 0;
1.115 yamt 92:
93: if (addr < vm_min_address)
94: return EINVAL;
95: if (eaddr > vm_max_address)
96: return ismmap ? EFBIG : EINVAL;
97: if (addr > eaddr) /* no wrapping! */
98: return ismmap ? EOVERFLOW : EINVAL;
1.145 martin 99:
100: #ifdef MD_MMAP_RANGE_TEST
101: res = MD_MMAP_RANGE_TEST(addr, eaddr);
102: #endif
103:
104: return res;
1.115 yamt 105: }
1.110 christos 106:
1.1 mrg 107: /*
108: * unimplemented VM system calls:
109: */
110:
111: /*
112: * sys_sbrk: sbrk system call.
113: */
114:
115: /* ARGSUSED */
1.6 mrg 116: int
1.119 dsl 117: sys_sbrk(struct lwp *l, const struct sys_sbrk_args *uap, register_t *retval)
1.1 mrg 118: {
1.119 dsl 119: /* {
1.33 kleink 120: syscallarg(intptr_t) incr;
1.119 dsl 121: } */
1.6 mrg 122:
1.17 kleink 123: return (ENOSYS);
1.1 mrg 124: }
125:
126: /*
127: * sys_sstk: sstk system call.
128: */
129:
130: /* ARGSUSED */
1.6 mrg 131: int
1.119 dsl 132: sys_sstk(struct lwp *l, const struct sys_sstk_args *uap, register_t *retval)
1.1 mrg 133: {
1.119 dsl 134: /* {
1.20 mrg 135: syscallarg(int) incr;
1.119 dsl 136: } */
1.6 mrg 137:
1.17 kleink 138: return (ENOSYS);
1.1 mrg 139: }
140:
141: /*
142: * sys_mincore: determine if pages are in core or not.
143: */
144:
145: /* ARGSUSED */
1.6 mrg 146: int
1.129 yamt 147: sys_mincore(struct lwp *l, const struct sys_mincore_args *uap,
148: register_t *retval)
1.1 mrg 149: {
1.119 dsl 150: /* {
1.22 thorpej 151: syscallarg(void *) addr;
1.20 mrg 152: syscallarg(size_t) len;
153: syscallarg(char *) vec;
1.119 dsl 154: } */
1.67 thorpej 155: struct proc *p = l->l_proc;
1.56 chs 156: struct vm_page *pg;
1.22 thorpej 157: char *vec, pgi;
158: struct uvm_object *uobj;
159: struct vm_amap *amap;
160: struct vm_anon *anon;
1.53 chs 161: struct vm_map_entry *entry;
1.22 thorpej 162: vaddr_t start, end, lim;
1.53 chs 163: struct vm_map *map;
1.22 thorpej 164: vsize_t len;
165: int error = 0, npgs;
166:
167: map = &p->p_vmspace->vm_map;
168:
169: start = (vaddr_t)SCARG(uap, addr);
170: len = SCARG(uap, len);
171: vec = SCARG(uap, vec);
172:
173: if (start & PAGE_MASK)
174: return (EINVAL);
175: len = round_page(len);
176: end = start + len;
177: if (end <= start)
178: return (EINVAL);
179:
180: /*
181: * Lock down vec, so our returned status isn't outdated by
182: * storing the status byte for a page.
183: */
1.50 chs 184:
1.62 chs 185: npgs = len >> PAGE_SHIFT;
1.100 chs 186: error = uvm_vslock(p->p_vmspace, vec, npgs, VM_PROT_WRITE);
1.62 chs 187: if (error) {
188: return error;
189: }
1.22 thorpej 190: vm_map_lock_read(map);
191:
1.107 thorpej 192: if (uvm_map_lookup_entry(map, start, &entry) == false) {
1.22 thorpej 193: error = ENOMEM;
194: goto out;
195: }
196:
197: for (/* nothing */;
198: entry != &map->header && entry->start < end;
199: entry = entry->next) {
1.49 chs 200: KASSERT(!UVM_ET_ISSUBMAP(entry));
201: KASSERT(start >= entry->start);
202:
1.22 thorpej 203: /* Make sure there are no holes. */
204: if (entry->end < end &&
205: (entry->next == &map->header ||
206: entry->next->start > entry->end)) {
207: error = ENOMEM;
208: goto out;
209: }
1.6 mrg 210:
1.22 thorpej 211: lim = end < entry->end ? end : entry->end;
212:
213: /*
1.31 thorpej 214: * Special case for objects with no "real" pages. Those
215: * are always considered resident (mapped devices).
1.22 thorpej 216: */
1.50 chs 217:
1.22 thorpej 218: if (UVM_ET_ISOBJ(entry)) {
1.49 chs 219: KASSERT(!UVM_OBJ_IS_KERN_OBJECT(entry->object.uvm_obj));
1.79 yamt 220: if (UVM_OBJ_IS_DEVICE(entry->object.uvm_obj)) {
1.22 thorpej 221: for (/* nothing */; start < lim;
222: start += PAGE_SIZE, vec++)
223: subyte(vec, 1);
224: continue;
225: }
226: }
227:
1.132 uebayasi 228: amap = entry->aref.ar_amap; /* upper layer */
229: uobj = entry->object.uvm_obj; /* lower layer */
1.22 thorpej 230:
231: if (amap != NULL)
232: amap_lock(amap);
233: if (uobj != NULL)
1.136 rmind 234: mutex_enter(uobj->vmobjlock);
1.22 thorpej 235:
236: for (/* nothing */; start < lim; start += PAGE_SIZE, vec++) {
237: pgi = 0;
238: if (amap != NULL) {
1.132 uebayasi 239: /* Check the upper layer first. */
1.22 thorpej 240: anon = amap_lookup(&entry->aref,
241: start - entry->start);
242: /* Don't need to lock anon here. */
1.91 yamt 243: if (anon != NULL && anon->an_page != NULL) {
1.50 chs 244:
1.22 thorpej 245: /*
246: * Anon has the page for this entry
247: * offset.
248: */
1.50 chs 249:
1.22 thorpej 250: pgi = 1;
251: }
252: }
253: if (uobj != NULL && pgi == 0) {
1.132 uebayasi 254: /* Check the lower layer. */
1.56 chs 255: pg = uvm_pagelookup(uobj,
1.22 thorpej 256: entry->offset + (start - entry->start));
1.56 chs 257: if (pg != NULL) {
1.50 chs 258:
1.22 thorpej 259: /*
260: * Object has the page for this entry
261: * offset.
262: */
1.50 chs 263:
1.22 thorpej 264: pgi = 1;
265: }
266: }
267: (void) subyte(vec, pgi);
268: }
269: if (uobj != NULL)
1.136 rmind 270: mutex_exit(uobj->vmobjlock);
1.22 thorpej 271: if (amap != NULL)
272: amap_unlock(amap);
273: }
274:
275: out:
276: vm_map_unlock_read(map);
1.100 chs 277: uvm_vsunlock(p->p_vmspace, SCARG(uap, vec), npgs);
1.22 thorpej 278: return (error);
1.1 mrg 279: }
280:
281: /*
282: * sys_mmap: mmap system call.
283: *
1.64 atatat 284: * => file offset and address may not be page aligned
1.1 mrg 285: * - if MAP_FIXED, offset and address must have remainder mod PAGE_SIZE
286: * - if address isn't page aligned the mapping starts at trunc_page(addr)
287: * and the return value is adjusted up by the page offset.
288: */
289:
1.6 mrg 290: int
1.119 dsl 291: sys_mmap(struct lwp *l, const struct sys_mmap_args *uap, register_t *retval)
1.6 mrg 292: {
1.119 dsl 293: /* {
1.108 christos 294: syscallarg(void *) addr;
1.6 mrg 295: syscallarg(size_t) len;
296: syscallarg(int) prot;
297: syscallarg(int) flags;
298: syscallarg(int) fd;
299: syscallarg(long) pad;
300: syscallarg(off_t) pos;
1.119 dsl 301: } */
1.67 thorpej 302: struct proc *p = l->l_proc;
1.12 eeh 303: vaddr_t addr;
1.9 mrg 304: struct vattr va;
1.6 mrg 305: off_t pos;
1.12 eeh 306: vsize_t size, pageoff;
1.6 mrg 307: vm_prot_t prot, maxprot;
308: int flags, fd;
1.110 christos 309: vaddr_t defaddr;
1.116 ad 310: struct file *fp = NULL;
1.6 mrg 311: struct vnode *vp;
1.50 chs 312: void *handle;
1.6 mrg 313: int error;
1.120 christos 314: #ifdef PAX_ASLR
315: vaddr_t orig_addr;
316: #endif /* PAX_ASLR */
1.6 mrg 317:
318: /*
319: * first, extract syscall args from the uap.
320: */
321:
1.50 chs 322: addr = (vaddr_t)SCARG(uap, addr);
323: size = (vsize_t)SCARG(uap, len);
1.6 mrg 324: prot = SCARG(uap, prot) & VM_PROT_ALL;
325: flags = SCARG(uap, flags);
326: fd = SCARG(uap, fd);
327: pos = SCARG(uap, pos);
328:
1.120 christos 329: #ifdef PAX_ASLR
330: orig_addr = addr;
331: #endif /* PAX_ASLR */
332:
1.6 mrg 333: /*
1.24 thorpej 334: * Fixup the old deprecated MAP_COPY into MAP_PRIVATE, and
335: * validate the flags.
336: */
1.147 christos 337: if (flags & MAP_COPY) {
1.24 thorpej 338: flags = (flags & ~MAP_COPY) | MAP_PRIVATE;
1.147 christos 339: #if defined(COMPAT_10) && defined(__i386__)
340: /*
341: * Ancient kernel on x86 did not obey PROT_EXEC on i386 at least
342: * and ld.so did not turn it on. We take care of this on amd64
343: * in compat32.
344: */
1.148 christos 345: prot |= PROT_EXEC;
1.147 christos 346: #endif
347: }
1.24 thorpej 348: if ((flags & (MAP_SHARED|MAP_PRIVATE)) == (MAP_SHARED|MAP_PRIVATE))
349: return (EINVAL);
350:
351: /*
1.6 mrg 352: * align file position and save offset. adjust size.
353: */
354:
355: pageoff = (pos & PAGE_MASK);
356: pos -= pageoff;
357: size += pageoff; /* add offset */
1.50 chs 358: size = (vsize_t)round_page(size); /* round up */
1.6 mrg 359:
360: /*
1.51 chs 361: * now check (MAP_FIXED) or get (!MAP_FIXED) the "addr"
1.6 mrg 362: */
363: if (flags & MAP_FIXED) {
364:
365: /* ensure address and file offset are aligned properly */
366: addr -= pageoff;
367: if (addr & PAGE_MASK)
368: return (EINVAL);
369:
1.115 yamt 370: error = range_test(addr, size, true);
371: if (error)
372: return error;
1.75 christos 373: } else if (addr == 0 || !(flags & MAP_TRYFIXED)) {
1.6 mrg 374:
375: /*
1.68 atatat 376: * not fixed: make sure we skip over the largest
377: * possible heap for non-topdown mapping arrangements.
378: * we will refine our guess later (e.g. to account for
379: * VAC, etc)
1.6 mrg 380: */
1.46 chs 381:
1.89 fvdl 382: defaddr = p->p_emul->e_vm_default_addr(p,
383: (vaddr_t)p->p_vmspace->vm_daddr, size);
384:
1.68 atatat 385: if (addr == 0 ||
386: !(p->p_vmspace->vm_map.flags & VM_MAP_TOPDOWN))
1.89 fvdl 387: addr = MAX(addr, defaddr);
1.68 atatat 388: else
1.89 fvdl 389: addr = MIN(addr, defaddr);
1.6 mrg 390: }
391:
392: /*
393: * check for file mappings (i.e. not anonymous) and verify file.
394: */
395:
396: if ((flags & MAP_ANON) == 0) {
1.122 ad 397: if ((fp = fd_getfile(fd)) == NULL)
1.54 thorpej 398: return (EBADF);
1.116 ad 399: if (fp->f_type != DTYPE_VNODE) {
1.122 ad 400: fd_putfile(fd);
1.7 kleink 401: return (ENODEV); /* only mmap vnodes! */
1.116 ad 402: }
1.149 ! matt 403: vp = fp->f_vnode; /* convert to vnode */
1.11 thorpej 404: if (vp->v_type != VREG && vp->v_type != VCHR &&
1.116 ad 405: vp->v_type != VBLK) {
1.122 ad 406: fd_putfile(fd);
1.11 thorpej 407: return (ENODEV); /* only REG/CHR/BLK support mmap */
1.116 ad 408: }
409: if (vp->v_type != VCHR && pos < 0) {
1.122 ad 410: fd_putfile(fd);
1.61 chs 411: return (EINVAL);
1.116 ad 412: }
1.138 yamt 413: if (vp->v_type != VCHR && (off_t)(pos + size) < pos) {
1.122 ad 414: fd_putfile(fd);
1.39 kleink 415: return (EOVERFLOW); /* no offset wrapping */
1.116 ad 416: }
1.6 mrg 417:
418: /* special case: catch SunOS style /dev/zero */
1.80 jdolecek 419: if (vp->v_type == VCHR
420: && (vp->v_rdev == zerodev || COMPAT_ZERODEV(vp->v_rdev))) {
1.6 mrg 421: flags |= MAP_ANON;
1.122 ad 422: fd_putfile(fd);
1.116 ad 423: fp = NULL;
1.6 mrg 424: goto is_anon;
425: }
426:
427: /*
428: * Old programs may not select a specific sharing type, so
429: * default to an appropriate one.
430: *
431: * XXX: how does MAP_ANON fit in the picture?
432: */
1.24 thorpej 433: if ((flags & (MAP_SHARED|MAP_PRIVATE)) == 0) {
1.8 tv 434: #if defined(DEBUG)
1.6 mrg 435: printf("WARNING: defaulted mmap() share type to "
1.71 gmcgarry 436: "%s (pid %d command %s)\n", vp->v_type == VCHR ?
1.6 mrg 437: "MAP_SHARED" : "MAP_PRIVATE", p->p_pid,
438: p->p_comm);
1.1 mrg 439: #endif
1.6 mrg 440: if (vp->v_type == VCHR)
441: flags |= MAP_SHARED; /* for a device */
442: else
443: flags |= MAP_PRIVATE; /* for a file */
444: }
445:
1.51 chs 446: /*
1.6 mrg 447: * MAP_PRIVATE device mappings don't make sense (and aren't
448: * supported anyway). However, some programs rely on this,
449: * so just change it to MAP_SHARED.
450: */
451: if (vp->v_type == VCHR && (flags & MAP_PRIVATE) != 0) {
452: flags = (flags & ~MAP_PRIVATE) | MAP_SHARED;
453: }
1.1 mrg 454:
1.6 mrg 455: /*
456: * now check protection
457: */
458:
1.48 thorpej 459: maxprot = VM_PROT_EXECUTE;
1.6 mrg 460:
461: /* check read access */
462: if (fp->f_flag & FREAD)
463: maxprot |= VM_PROT_READ;
1.116 ad 464: else if (prot & PROT_READ) {
1.122 ad 465: fd_putfile(fd);
1.6 mrg 466: return (EACCES);
1.116 ad 467: }
1.6 mrg 468:
1.9 mrg 469: /* check write access, shared case first */
1.6 mrg 470: if (flags & MAP_SHARED) {
1.9 mrg 471: /*
472: * if the file is writable, only add PROT_WRITE to
473: * maxprot if the file is not immutable, append-only.
474: * otherwise, if we have asked for PROT_WRITE, return
475: * EPERM.
476: */
477: if (fp->f_flag & FWRITE) {
1.139 hannken 478: vn_lock(vp, LK_SHARED | LK_RETRY);
479: error = VOP_GETATTR(vp, &va, l->l_cred);
480: VOP_UNLOCK(vp);
481: if (error) {
1.122 ad 482: fd_putfile(fd);
1.9 mrg 483: return (error);
1.116 ad 484: }
1.84 hannken 485: if ((va.va_flags &
486: (SF_SNAPSHOT|IMMUTABLE|APPEND)) == 0)
1.9 mrg 487: maxprot |= VM_PROT_WRITE;
1.116 ad 488: else if (prot & PROT_WRITE) {
1.122 ad 489: fd_putfile(fd);
1.9 mrg 490: return (EPERM);
1.116 ad 491: }
1.9 mrg 492: }
1.116 ad 493: else if (prot & PROT_WRITE) {
1.122 ad 494: fd_putfile(fd);
1.6 mrg 495: return (EACCES);
1.116 ad 496: }
1.6 mrg 497: } else {
498: /* MAP_PRIVATE mappings can always write to */
499: maxprot |= VM_PROT_WRITE;
500: }
1.50 chs 501: handle = vp;
1.1 mrg 502:
1.6 mrg 503: } else { /* MAP_ANON case */
1.24 thorpej 504: /*
505: * XXX What do we do about (MAP_SHARED|MAP_PRIVATE) == 0?
506: */
1.6 mrg 507: if (fd != -1)
508: return (EINVAL);
1.1 mrg 509:
1.24 thorpej 510: is_anon: /* label for SunOS style /dev/zero */
1.6 mrg 511: handle = NULL;
512: maxprot = VM_PROT_ALL;
513: pos = 0;
1.28 cgd 514: }
515:
1.112 elad 516: #if NVERIEXEC > 0
517: if (handle != NULL) {
518: /*
519: * Check if the file can be executed indirectly.
520: *
521: * XXX: This gives false warnings about "Incorrect access type"
522: * XXX: if the mapping is not executable. Harmless, but will be
523: * XXX: fixed as part of other changes.
524: */
525: if (veriexec_verify(l, handle, "(mmap)", VERIEXEC_INDIRECT,
526: NULL)) {
527: /*
528: * Don't allow executable mappings if we can't
529: * indirectly execute the file.
530: */
1.116 ad 531: if (prot & VM_PROT_EXECUTE) {
532: if (fp != NULL)
1.122 ad 533: fd_putfile(fd);
1.112 elad 534: return (EPERM);
1.116 ad 535: }
1.112 elad 536:
537: /*
538: * Strip the executable bit from 'maxprot' to make sure
539: * it can't be made executable later.
540: */
541: maxprot &= ~VM_PROT_EXECUTE;
542: }
543: }
544: #endif /* NVERIEXEC > 0 */
545:
1.97 elad 546: #ifdef PAX_MPROTECT
547: pax_mprotect(l, &prot, &maxprot);
548: #endif /* PAX_MPROTECT */
549:
1.120 christos 550: #ifdef PAX_ASLR
551: pax_aslr(l, &addr, orig_addr, flags);
552: #endif /* PAX_ASLR */
553:
1.6 mrg 554: /*
555: * now let kernel internal function uvm_mmap do the work.
556: */
557:
558: error = uvm_mmap(&p->p_vmspace->vm_map, &addr, size, prot, maxprot,
1.25 thorpej 559: flags, handle, pos, p->p_rlimit[RLIMIT_MEMLOCK].rlim_cur);
1.6 mrg 560:
561: if (error == 0)
562: /* remember to add offset */
563: *retval = (register_t)(addr + pageoff);
1.1 mrg 564:
1.116 ad 565: if (fp != NULL)
1.122 ad 566: fd_putfile(fd);
1.116 ad 567:
1.6 mrg 568: return (error);
1.1 mrg 569: }
570:
571: /*
572: * sys___msync13: the msync system call (a front-end for flush)
573: */
574:
1.6 mrg 575: int
1.129 yamt 576: sys___msync13(struct lwp *l, const struct sys___msync13_args *uap,
577: register_t *retval)
1.6 mrg 578: {
1.119 dsl 579: /* {
1.108 christos 580: syscallarg(void *) addr;
1.6 mrg 581: syscallarg(size_t) len;
582: syscallarg(int) flags;
1.119 dsl 583: } */
1.67 thorpej 584: struct proc *p = l->l_proc;
1.12 eeh 585: vaddr_t addr;
586: vsize_t size, pageoff;
1.53 chs 587: struct vm_map *map;
1.50 chs 588: int error, rv, flags, uvmflags;
1.6 mrg 589:
590: /*
591: * extract syscall args from the uap
592: */
593:
1.12 eeh 594: addr = (vaddr_t)SCARG(uap, addr);
595: size = (vsize_t)SCARG(uap, len);
1.6 mrg 596: flags = SCARG(uap, flags);
597:
598: /* sanity check flags */
599: if ((flags & ~(MS_ASYNC | MS_SYNC | MS_INVALIDATE)) != 0 ||
1.77 chs 600: (flags & (MS_ASYNC | MS_SYNC | MS_INVALIDATE)) == 0 ||
601: (flags & (MS_ASYNC | MS_SYNC)) == (MS_ASYNC | MS_SYNC))
602: return (EINVAL);
1.6 mrg 603: if ((flags & (MS_ASYNC | MS_SYNC)) == 0)
1.77 chs 604: flags |= MS_SYNC;
1.1 mrg 605:
1.6 mrg 606: /*
1.50 chs 607: * align the address to a page boundary and adjust the size accordingly.
1.6 mrg 608: */
609:
610: pageoff = (addr & PAGE_MASK);
611: addr -= pageoff;
612: size += pageoff;
1.50 chs 613: size = (vsize_t)round_page(size);
1.6 mrg 614:
1.115 yamt 615: error = range_test(addr, size, false);
616: if (error)
617: return error;
1.6 mrg 618:
619: /*
620: * get map
621: */
622:
623: map = &p->p_vmspace->vm_map;
624:
625: /*
626: * XXXCDC: do we really need this semantic?
627: *
628: * XXX Gak! If size is zero we are supposed to sync "all modified
629: * pages with the region containing addr". Unfortunately, we
630: * don't really keep track of individual mmaps so we approximate
631: * by flushing the range of the map entry containing addr.
632: * This can be incorrect if the region splits or is coalesced
633: * with a neighbor.
634: */
1.50 chs 635:
1.6 mrg 636: if (size == 0) {
1.53 chs 637: struct vm_map_entry *entry;
1.51 chs 638:
1.6 mrg 639: vm_map_lock_read(map);
640: rv = uvm_map_lookup_entry(map, addr, &entry);
1.107 thorpej 641: if (rv == true) {
1.6 mrg 642: addr = entry->start;
643: size = entry->end - entry->start;
644: }
645: vm_map_unlock_read(map);
1.107 thorpej 646: if (rv == false)
1.6 mrg 647: return (EINVAL);
648: }
649:
650: /*
651: * translate MS_ flags into PGO_ flags
652: */
1.50 chs 653:
1.34 thorpej 654: uvmflags = PGO_CLEANIT;
655: if (flags & MS_INVALIDATE)
656: uvmflags |= PGO_FREE;
1.6 mrg 657: if (flags & MS_SYNC)
658: uvmflags |= PGO_SYNCIO;
659:
1.50 chs 660: error = uvm_map_clean(map, addr, addr+size, uvmflags);
661: return error;
1.1 mrg 662: }
663:
664: /*
665: * sys_munmap: unmap a users memory
666: */
667:
1.6 mrg 668: int
1.119 dsl 669: sys_munmap(struct lwp *l, const struct sys_munmap_args *uap, register_t *retval)
1.6 mrg 670: {
1.119 dsl 671: /* {
1.108 christos 672: syscallarg(void *) addr;
1.6 mrg 673: syscallarg(size_t) len;
1.119 dsl 674: } */
1.67 thorpej 675: struct proc *p = l->l_proc;
1.12 eeh 676: vaddr_t addr;
677: vsize_t size, pageoff;
1.53 chs 678: struct vm_map *map;
1.6 mrg 679: struct vm_map_entry *dead_entries;
1.115 yamt 680: int error;
1.6 mrg 681:
682: /*
1.50 chs 683: * get syscall args.
1.6 mrg 684: */
685:
1.50 chs 686: addr = (vaddr_t)SCARG(uap, addr);
687: size = (vsize_t)SCARG(uap, len);
1.51 chs 688:
1.6 mrg 689: /*
1.50 chs 690: * align the address to a page boundary and adjust the size accordingly.
1.6 mrg 691: */
692:
693: pageoff = (addr & PAGE_MASK);
694: addr -= pageoff;
695: size += pageoff;
1.50 chs 696: size = (vsize_t)round_page(size);
1.6 mrg 697:
698: if (size == 0)
699: return (0);
700:
1.115 yamt 701: error = range_test(addr, size, false);
702: if (error)
703: return error;
1.110 christos 704:
1.6 mrg 705: map = &p->p_vmspace->vm_map;
706:
707: /*
1.51 chs 708: * interesting system call semantic: make sure entire range is
1.6 mrg 709: * allocated before allowing an unmap.
710: */
711:
1.50 chs 712: vm_map_lock(map);
1.66 mycroft 713: #if 0
1.6 mrg 714: if (!uvm_map_checkprot(map, addr, addr + size, VM_PROT_NONE)) {
715: vm_map_unlock(map);
716: return (EINVAL);
717: }
1.66 mycroft 718: #endif
1.144 para 719: uvm_unmap_remove(map, addr, addr + size, &dead_entries, 0);
1.50 chs 720: vm_map_unlock(map);
1.6 mrg 721: if (dead_entries != NULL)
722: uvm_unmap_detach(dead_entries, 0);
723: return (0);
1.1 mrg 724: }
725:
726: /*
727: * sys_mprotect: the mprotect system call
728: */
729:
1.6 mrg 730: int
1.129 yamt 731: sys_mprotect(struct lwp *l, const struct sys_mprotect_args *uap,
732: register_t *retval)
1.6 mrg 733: {
1.119 dsl 734: /* {
1.108 christos 735: syscallarg(void *) addr;
1.76 chs 736: syscallarg(size_t) len;
1.6 mrg 737: syscallarg(int) prot;
1.119 dsl 738: } */
1.67 thorpej 739: struct proc *p = l->l_proc;
1.12 eeh 740: vaddr_t addr;
741: vsize_t size, pageoff;
1.6 mrg 742: vm_prot_t prot;
1.50 chs 743: int error;
1.6 mrg 744:
745: /*
746: * extract syscall args from uap
747: */
748:
1.12 eeh 749: addr = (vaddr_t)SCARG(uap, addr);
750: size = (vsize_t)SCARG(uap, len);
1.6 mrg 751: prot = SCARG(uap, prot) & VM_PROT_ALL;
752:
753: /*
1.50 chs 754: * align the address to a page boundary and adjust the size accordingly.
1.6 mrg 755: */
1.50 chs 756:
1.6 mrg 757: pageoff = (addr & PAGE_MASK);
758: addr -= pageoff;
759: size += pageoff;
1.76 chs 760: size = round_page(size);
1.50 chs 761:
1.115 yamt 762: error = range_test(addr, size, false);
763: if (error)
764: return error;
1.110 christos 765:
1.50 chs 766: error = uvm_map_protect(&p->p_vmspace->vm_map, addr, addr + size, prot,
1.107 thorpej 767: false);
1.50 chs 768: return error;
1.1 mrg 769: }
770:
771: /*
772: * sys_minherit: the minherit system call
773: */
774:
1.6 mrg 775: int
1.129 yamt 776: sys_minherit(struct lwp *l, const struct sys_minherit_args *uap,
777: register_t *retval)
1.6 mrg 778: {
1.119 dsl 779: /* {
1.108 christos 780: syscallarg(void *) addr;
1.6 mrg 781: syscallarg(int) len;
782: syscallarg(int) inherit;
1.119 dsl 783: } */
1.67 thorpej 784: struct proc *p = l->l_proc;
1.12 eeh 785: vaddr_t addr;
786: vsize_t size, pageoff;
1.40 augustss 787: vm_inherit_t inherit;
1.50 chs 788: int error;
1.51 chs 789:
1.12 eeh 790: addr = (vaddr_t)SCARG(uap, addr);
791: size = (vsize_t)SCARG(uap, len);
1.6 mrg 792: inherit = SCARG(uap, inherit);
1.50 chs 793:
1.6 mrg 794: /*
1.50 chs 795: * align the address to a page boundary and adjust the size accordingly.
1.6 mrg 796: */
797:
798: pageoff = (addr & PAGE_MASK);
799: addr -= pageoff;
800: size += pageoff;
1.50 chs 801: size = (vsize_t)round_page(size);
1.6 mrg 802:
1.115 yamt 803: error = range_test(addr, size, false);
804: if (error)
805: return error;
1.110 christos 806:
1.50 chs 807: error = uvm_map_inherit(&p->p_vmspace->vm_map, addr, addr + size,
808: inherit);
809: return error;
1.21 mrg 810: }
811:
812: /*
813: * sys_madvise: give advice about memory usage.
814: */
815:
816: /* ARGSUSED */
817: int
1.129 yamt 818: sys_madvise(struct lwp *l, const struct sys_madvise_args *uap,
819: register_t *retval)
1.21 mrg 820: {
1.119 dsl 821: /* {
1.108 christos 822: syscallarg(void *) addr;
1.21 mrg 823: syscallarg(size_t) len;
824: syscallarg(int) behav;
1.119 dsl 825: } */
1.67 thorpej 826: struct proc *p = l->l_proc;
1.21 mrg 827: vaddr_t addr;
828: vsize_t size, pageoff;
1.50 chs 829: int advice, error;
1.51 chs 830:
1.21 mrg 831: addr = (vaddr_t)SCARG(uap, addr);
832: size = (vsize_t)SCARG(uap, len);
833: advice = SCARG(uap, behav);
834:
835: /*
836: * align the address to a page boundary, and adjust the size accordingly
837: */
1.50 chs 838:
1.21 mrg 839: pageoff = (addr & PAGE_MASK);
840: addr -= pageoff;
841: size += pageoff;
1.50 chs 842: size = (vsize_t)round_page(size);
1.21 mrg 843:
1.115 yamt 844: error = range_test(addr, size, false);
845: if (error)
846: return error;
1.29 thorpej 847:
848: switch (advice) {
849: case MADV_NORMAL:
850: case MADV_RANDOM:
851: case MADV_SEQUENTIAL:
1.50 chs 852: error = uvm_map_advice(&p->p_vmspace->vm_map, addr, addr + size,
1.29 thorpej 853: advice);
854: break;
855:
856: case MADV_WILLNEED:
1.50 chs 857:
1.29 thorpej 858: /*
859: * Activate all these pages, pre-faulting them in if
860: * necessary.
861: */
1.130 yamt 862: error = uvm_map_willneed(&p->p_vmspace->vm_map,
863: addr, addr + size);
864: break;
1.29 thorpej 865:
866: case MADV_DONTNEED:
1.50 chs 867:
1.29 thorpej 868: /*
869: * Deactivate all these pages. We don't need them
870: * any more. We don't, however, toss the data in
871: * the pages.
872: */
1.50 chs 873:
874: error = uvm_map_clean(&p->p_vmspace->vm_map, addr, addr + size,
1.29 thorpej 875: PGO_DEACTIVATE);
876: break;
877:
878: case MADV_FREE:
1.50 chs 879:
1.29 thorpej 880: /*
881: * These pages contain no valid data, and may be
1.45 soren 882: * garbage-collected. Toss all resources, including
1.30 thorpej 883: * any swap space in use.
1.29 thorpej 884: */
1.50 chs 885:
886: error = uvm_map_clean(&p->p_vmspace->vm_map, addr, addr + size,
1.29 thorpej 887: PGO_FREE);
888: break;
889:
890: case MADV_SPACEAVAIL:
1.50 chs 891:
1.29 thorpej 892: /*
893: * XXXMRG What is this? I think it's:
894: *
895: * Ensure that we have allocated backing-store
896: * for these pages.
897: *
898: * This is going to require changes to the page daemon,
899: * as it will free swap space allocated to pages in core.
900: * There's also what to do for device/file/anonymous memory.
901: */
1.50 chs 902:
1.29 thorpej 903: return (EINVAL);
904:
905: default:
1.21 mrg 906: return (EINVAL);
1.29 thorpej 907: }
908:
1.50 chs 909: return error;
1.1 mrg 910: }
911:
912: /*
913: * sys_mlock: memory lock
914: */
915:
1.6 mrg 916: int
1.119 dsl 917: sys_mlock(struct lwp *l, const struct sys_mlock_args *uap, register_t *retval)
1.6 mrg 918: {
1.119 dsl 919: /* {
1.10 kleink 920: syscallarg(const void *) addr;
1.6 mrg 921: syscallarg(size_t) len;
1.119 dsl 922: } */
1.67 thorpej 923: struct proc *p = l->l_proc;
1.12 eeh 924: vaddr_t addr;
925: vsize_t size, pageoff;
1.6 mrg 926: int error;
927:
928: /*
929: * extract syscall args from uap
930: */
1.50 chs 931:
1.12 eeh 932: addr = (vaddr_t)SCARG(uap, addr);
933: size = (vsize_t)SCARG(uap, len);
1.6 mrg 934:
935: /*
936: * align the address to a page boundary and adjust the size accordingly
937: */
1.50 chs 938:
1.6 mrg 939: pageoff = (addr & PAGE_MASK);
940: addr -= pageoff;
941: size += pageoff;
1.50 chs 942: size = (vsize_t)round_page(size);
1.51 chs 943:
1.115 yamt 944: error = range_test(addr, size, false);
945: if (error)
946: return error;
1.1 mrg 947:
1.6 mrg 948: if (atop(size) + uvmexp.wired > uvmexp.wiredmax)
949: return (EAGAIN);
1.1 mrg 950:
1.6 mrg 951: if (size + ptoa(pmap_wired_count(vm_map_pmap(&p->p_vmspace->vm_map))) >
952: p->p_rlimit[RLIMIT_MEMLOCK].rlim_cur)
953: return (EAGAIN);
1.1 mrg 954:
1.107 thorpej 955: error = uvm_map_pageable(&p->p_vmspace->vm_map, addr, addr+size, false,
1.35 thorpej 956: 0);
1.85 briggs 957: if (error == EFAULT)
958: error = ENOMEM;
1.50 chs 959: return error;
1.1 mrg 960: }
961:
962: /*
963: * sys_munlock: unlock wired pages
964: */
965:
1.6 mrg 966: int
1.129 yamt 967: sys_munlock(struct lwp *l, const struct sys_munlock_args *uap,
968: register_t *retval)
1.6 mrg 969: {
1.119 dsl 970: /* {
1.10 kleink 971: syscallarg(const void *) addr;
1.6 mrg 972: syscallarg(size_t) len;
1.119 dsl 973: } */
1.67 thorpej 974: struct proc *p = l->l_proc;
1.12 eeh 975: vaddr_t addr;
976: vsize_t size, pageoff;
1.6 mrg 977: int error;
978:
979: /*
980: * extract syscall args from uap
981: */
982:
1.12 eeh 983: addr = (vaddr_t)SCARG(uap, addr);
984: size = (vsize_t)SCARG(uap, len);
1.6 mrg 985:
986: /*
987: * align the address to a page boundary, and adjust the size accordingly
988: */
1.50 chs 989:
1.6 mrg 990: pageoff = (addr & PAGE_MASK);
991: addr -= pageoff;
992: size += pageoff;
1.50 chs 993: size = (vsize_t)round_page(size);
1.6 mrg 994:
1.115 yamt 995: error = range_test(addr, size, false);
996: if (error)
997: return error;
1.1 mrg 998:
1.107 thorpej 999: error = uvm_map_pageable(&p->p_vmspace->vm_map, addr, addr+size, true,
1.35 thorpej 1000: 0);
1.85 briggs 1001: if (error == EFAULT)
1002: error = ENOMEM;
1.50 chs 1003: return error;
1.22 thorpej 1004: }
1005:
1006: /*
1007: * sys_mlockall: lock all pages mapped into an address space.
1008: */
1009:
1010: int
1.129 yamt 1011: sys_mlockall(struct lwp *l, const struct sys_mlockall_args *uap,
1012: register_t *retval)
1.22 thorpej 1013: {
1.119 dsl 1014: /* {
1.22 thorpej 1015: syscallarg(int) flags;
1.119 dsl 1016: } */
1.67 thorpej 1017: struct proc *p = l->l_proc;
1.22 thorpej 1018: int error, flags;
1019:
1020: flags = SCARG(uap, flags);
1021:
1022: if (flags == 0 ||
1023: (flags & ~(MCL_CURRENT|MCL_FUTURE)) != 0)
1024: return (EINVAL);
1025:
1.25 thorpej 1026: error = uvm_map_pageable_all(&p->p_vmspace->vm_map, flags,
1027: p->p_rlimit[RLIMIT_MEMLOCK].rlim_cur);
1.22 thorpej 1028: return (error);
1029: }
1030:
1031: /*
1032: * sys_munlockall: unlock all pages mapped into an address space.
1033: */
1034:
1035: int
1.119 dsl 1036: sys_munlockall(struct lwp *l, const void *v, register_t *retval)
1.22 thorpej 1037: {
1.67 thorpej 1038: struct proc *p = l->l_proc;
1.22 thorpej 1039:
1040: (void) uvm_map_pageable_all(&p->p_vmspace->vm_map, 0, 0);
1041: return (0);
1.1 mrg 1042: }
1043:
1044: /*
1045: * uvm_mmap: internal version of mmap
1046: *
1.56 chs 1047: * - used by sys_mmap and various framebuffers
1048: * - handle is a vnode pointer or NULL for MAP_ANON
1.1 mrg 1049: * - caller must page-align the file offset
1050: */
1051:
1.6 mrg 1052: int
1.129 yamt 1053: uvm_mmap(struct vm_map *map, vaddr_t *addr, vsize_t size, vm_prot_t prot,
1054: vm_prot_t maxprot, int flags, void *handle, voff_t foff, vsize_t locklimit)
1.6 mrg 1055: {
1056: struct uvm_object *uobj;
1057: struct vnode *vp;
1.70 matt 1058: vaddr_t align = 0;
1.50 chs 1059: int error;
1.6 mrg 1060: int advice = UVM_ADV_NORMAL;
1061: uvm_flag_t uvmflag = 0;
1.106 thorpej 1062: bool needwritemap;
1.6 mrg 1063:
1064: /*
1065: * check params
1066: */
1067:
1068: if (size == 0)
1069: return(0);
1070: if (foff & PAGE_MASK)
1071: return(EINVAL);
1072: if ((prot & maxprot) != prot)
1073: return(EINVAL);
1074:
1075: /*
1076: * for non-fixed mappings, round off the suggested address.
1077: * for fixed mappings, check alignment and zap old mappings.
1078: */
1079:
1080: if ((flags & MAP_FIXED) == 0) {
1.56 chs 1081: *addr = round_page(*addr);
1.6 mrg 1082: } else {
1083: if (*addr & PAGE_MASK)
1084: return(EINVAL);
1085: uvmflag |= UVM_FLAG_FIXED;
1.56 chs 1086: (void) uvm_unmap(map, *addr, *addr + size);
1.6 mrg 1087: }
1088:
1089: /*
1.70 matt 1090: * Try to see if any requested alignment can even be attemped.
1091: * Make sure we can express the alignment (asking for a >= 4GB
1092: * alignment on an ILP32 architecure make no sense) and the
1093: * alignment is at least for a page sized quanitiy. If the
1094: * request was for a fixed mapping, make sure supplied address
1095: * adheres to the request alignment.
1096: */
1097: align = (flags & MAP_ALIGNMENT_MASK) >> MAP_ALIGNMENT_SHIFT;
1098: if (align) {
1099: if (align >= sizeof(vaddr_t) * NBBY)
1100: return(EINVAL);
1101: align = 1L << align;
1102: if (align < PAGE_SIZE)
1103: return(EINVAL);
1.88 chs 1104: if (align >= vm_map_max(map))
1.70 matt 1105: return(ENOMEM);
1106: if (flags & MAP_FIXED) {
1107: if ((*addr & (align-1)) != 0)
1108: return(EINVAL);
1109: align = 0;
1110: }
1111: }
1112:
1113: /*
1.128 mrg 1114: * check resource limits
1115: */
1116:
1117: if (!VM_MAP_IS_KERNEL(map) &&
1118: (((rlim_t)curproc->p_vmspace->vm_map.size + (rlim_t)size) >
1119: curproc->p_rlimit[RLIMIT_AS].rlim_cur))
1120: return ENOMEM;
1121:
1122: /*
1.6 mrg 1123: * handle anon vs. non-anon mappings. for non-anon mappings attach
1124: * to underlying vm object.
1125: */
1126:
1127: if (flags & MAP_ANON) {
1.95 christos 1128: KASSERT(handle == NULL);
1.36 thorpej 1129: foff = UVM_UNKNOWN_OFFSET;
1.6 mrg 1130: uobj = NULL;
1131: if ((flags & MAP_SHARED) == 0)
1132: /* XXX: defer amap create */
1133: uvmflag |= UVM_FLAG_COPYONW;
1134: else
1135: /* shared: create amap now */
1136: uvmflag |= UVM_FLAG_OVERLAY;
1137:
1138: } else {
1.95 christos 1139: KASSERT(handle != NULL);
1.50 chs 1140: vp = (struct vnode *)handle;
1.59 thorpej 1141:
1142: /*
1143: * Don't allow mmap for EXEC if the file system
1144: * is mounted NOEXEC.
1145: */
1146: if ((prot & PROT_EXEC) != 0 &&
1147: (vp->v_mount->mnt_flag & MNT_NOEXEC) != 0)
1148: return (EACCES);
1149:
1.6 mrg 1150: if (vp->v_type != VCHR) {
1.118 pooka 1151: error = VOP_MMAP(vp, prot, curlwp->l_cred);
1.55 chs 1152: if (error) {
1153: return error;
1154: }
1.113 pooka 1155: vref(vp);
1156: uobj = &vp->v_uobj;
1.57 thorpej 1157:
1158: /*
1159: * If the vnode is being mapped with PROT_EXEC,
1160: * then mark it as text.
1161: */
1.117 ad 1162: if (prot & PROT_EXEC) {
1.58 thorpej 1163: vn_markexec(vp);
1.117 ad 1164: }
1.6 mrg 1165: } else {
1.83 darrenr 1166: int i = maxprot;
1167:
1.48 thorpej 1168: /*
1169: * XXX Some devices don't like to be mapped with
1.83 darrenr 1170: * XXX PROT_EXEC or PROT_WRITE, but we don't really
1171: * XXX have a better way of handling this, right now
1.48 thorpej 1172: */
1.83 darrenr 1173: do {
1174: uobj = udv_attach((void *) &vp->v_rdev,
1175: (flags & MAP_SHARED) ? i :
1176: (i & ~VM_PROT_WRITE), foff, size);
1177: i--;
1178: } while ((uobj == NULL) && (i > 0));
1.131 yamt 1179: if (uobj == NULL)
1180: return EINVAL;
1.6 mrg 1181: advice = UVM_ADV_RANDOM;
1182: }
1.92 yamt 1183: if ((flags & MAP_SHARED) == 0) {
1.6 mrg 1184: uvmflag |= UVM_FLAG_COPYONW;
1.100 chs 1185: }
1186:
1187: /*
1188: * Set vnode flags to indicate the new kinds of mapping.
1189: * We take the vnode lock in exclusive mode here to serialize
1190: * with direct I/O.
1.124 ad 1191: *
1192: * Safe to check for these flag values without a lock, as
1193: * long as a reference to the vnode is held.
1.100 chs 1194: */
1.117 ad 1195: needwritemap = (vp->v_iflag & VI_WRMAP) == 0 &&
1.100 chs 1196: (flags & MAP_SHARED) != 0 &&
1197: (maxprot & VM_PROT_WRITE) != 0;
1.124 ad 1198: if ((vp->v_vflag & VV_MAPPED) == 0 || needwritemap) {
1199: vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
1.117 ad 1200: vp->v_vflag |= VV_MAPPED;
1.100 chs 1201: if (needwritemap) {
1.136 rmind 1202: mutex_enter(vp->v_interlock);
1.117 ad 1203: vp->v_iflag |= VI_WRMAP;
1.136 rmind 1204: mutex_exit(vp->v_interlock);
1.100 chs 1205: }
1.133 hannken 1206: VOP_UNLOCK(vp);
1.124 ad 1207: }
1.6 mrg 1208: }
1209:
1.51 chs 1210: uvmflag = UVM_MAPFLAG(prot, maxprot,
1.1 mrg 1211: (flags & MAP_SHARED) ? UVM_INH_SHARE : UVM_INH_COPY,
1212: advice, uvmflag);
1.70 matt 1213: error = uvm_map(map, addr, size, uobj, foff, align, uvmflag);
1.50 chs 1214: if (error) {
1215: if (uobj)
1216: uobj->pgops->pgo_detach(uobj);
1217: return error;
1218: }
1.1 mrg 1219:
1.6 mrg 1220: /*
1.50 chs 1221: * POSIX 1003.1b -- if our address space was configured
1222: * to lock all future mappings, wire the one we just made.
1.78 thorpej 1223: *
1224: * Also handle the MAP_WIRED flag here.
1.6 mrg 1225: */
1226:
1.50 chs 1227: if (prot == VM_PROT_NONE) {
1.6 mrg 1228:
1.25 thorpej 1229: /*
1.50 chs 1230: * No more work to do in this case.
1.25 thorpej 1231: */
1232:
1.50 chs 1233: return (0);
1234: }
1.78 thorpej 1235: if ((flags & MAP_WIRED) != 0 || (map->flags & VM_MAP_WIREFUTURE) != 0) {
1.126 ad 1236: vm_map_lock(map);
1.87 chs 1237: if (atop(size) + uvmexp.wired > uvmexp.wiredmax ||
1238: (locklimit != 0 &&
1239: size + ptoa(pmap_wired_count(vm_map_pmap(map))) >
1240: locklimit)) {
1.50 chs 1241: vm_map_unlock(map);
1242: uvm_unmap(map, *addr, *addr + size);
1243: return ENOMEM;
1.25 thorpej 1244: }
1245:
1.50 chs 1246: /*
1247: * uvm_map_pageable() always returns the map unlocked.
1248: */
1.25 thorpej 1249:
1.50 chs 1250: error = uvm_map_pageable(map, *addr, *addr + size,
1.107 thorpej 1251: false, UVM_LK_ENTER);
1.50 chs 1252: if (error) {
1253: uvm_unmap(map, *addr, *addr + size);
1254: return error;
1255: }
1.25 thorpej 1256: return (0);
1257: }
1.50 chs 1258: return 0;
1.1 mrg 1259: }
1.89 fvdl 1260:
1261: vaddr_t
1.102 yamt 1262: uvm_default_mapaddr(struct proc *p, vaddr_t base, vsize_t sz)
1.89 fvdl 1263: {
1.102 yamt 1264:
1.146 christos 1265: if (p->p_vmspace->vm_map.flags & VM_MAP_TOPDOWN)
1266: return VM_DEFAULT_ADDRESS_TOPDOWN(base, sz);
1267: else
1268: return VM_DEFAULT_ADDRESS_BOTTOMUP(base, sz);
1.89 fvdl 1269: }
CVSweb <webmaster@jp.NetBSD.org>