|
|
1.1 root 1: /*
2: * Copyright (c) 1988 University of Utah.
3: * Copyright (c) 1991 The Regents of the University of California.
4: * All rights reserved.
5: *
6: * This code is derived from software contributed to Berkeley by
7: * the Systems Programming Group of the University of Utah Computer
8: * Science Department.
9: *
10: * Redistribution and use in source and binary forms, with or without
11: * modification, are permitted provided that the following conditions
12: * are met:
13: * 1. Redistributions of source code must retain the above copyright
14: * notice, this list of conditions and the following disclaimer.
15: * 2. Redistributions in binary form must reproduce the above copyright
16: * notice, this list of conditions and the following disclaimer in the
17: * documentation and/or other materials provided with the distribution.
18: * 3. All advertising materials mentioning features or use of this software
19: * must display the following acknowledgement:
20: * This product includes software developed by the University of
21: * California, Berkeley and its contributors.
22: * 4. Neither the name of the University nor the names of its contributors
23: * may be used to endorse or promote products derived from this software
24: * without specific prior written permission.
25: *
26: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
27: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
28: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
29: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
30: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
31: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
32: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
33: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
34: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
35: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
36: * SUCH DAMAGE.
37: *
38: * from: Utah $Hdr: vm_mmap.c 1.3 90/01/21$
39: *
1.1.1.4 ! root 40: * from: @(#)vm_mmap.c 7.5 (Berkeley) 6/28/91
! 41: * vm_mmap.c,v 1.10 1993/07/17 15:24:54 mycroft Exp
1.1 root 42: */
43:
44: /*
45: * Mapped file (mmap) interface to VM
46: */
47:
48: #include "param.h"
49: #include "systm.h"
50: #include "filedesc.h"
51: #include "proc.h"
52: #include "vnode.h"
53: #include "specdev.h"
54: #include "file.h"
55: #include "mman.h"
56: #include "conf.h"
57:
58: #include "vm.h"
59: #include "vm_pager.h"
60: #include "vm_prot.h"
61: #include "vm_statistics.h"
62:
63: #ifdef DEBUG
64: int mmapdebug = 0;
65: #define MDB_FOLLOW 0x01
66: #define MDB_SYNC 0x02
67: #define MDB_MAPIT 0x04
68: #endif
69:
70: /* ARGSUSED */
71: getpagesize(p, uap, retval)
72: struct proc *p;
73: void *uap;
74: int *retval;
75: {
76:
77: *retval = NBPG * CLSIZE;
78: return (0);
79: }
80:
1.1.1.4 ! root 81: struct sbrk_args {
! 82: int incr;
! 83: };
! 84:
1.1 root 85: /* ARGSUSED */
86: sbrk(p, uap, retval)
87: struct proc *p;
1.1.1.4 ! root 88: struct sbrk_args *uap;
1.1 root 89: int *retval;
90: {
91:
92: /* Not yet implemented */
93: return (EOPNOTSUPP);
94: }
95:
1.1.1.4 ! root 96: struct sstk_args {
! 97: int incr;
! 98: };
! 99:
1.1 root 100: /* ARGSUSED */
101: sstk(p, uap, retval)
102: struct proc *p;
1.1.1.4 ! root 103: struct sstk_args *uap;
1.1 root 104: int *retval;
105: {
106:
107: /* Not yet implemented */
108: return (EOPNOTSUPP);
109: }
110:
1.1.1.4 ! root 111: struct smmap_args {
! 112: caddr_t addr;
! 113: int len;
! 114: int prot;
! 115: int flags;
! 116: int fd;
! 117: off_t pos;
! 118: };
! 119:
1.1 root 120: smmap(p, uap, retval)
121: struct proc *p;
1.1.1.4 ! root 122: register struct smmap_args *uap;
1.1 root 123: int *retval;
124: {
125: register struct filedesc *fdp = p->p_fd;
126: register struct file *fp;
127: struct vnode *vp;
128: vm_offset_t addr;
129: vm_size_t size;
130: vm_prot_t prot;
1.1.1.3 root 131: vm_prot_t maxprot;
1.1 root 132: caddr_t handle;
133: int mtype, error;
1.1.1.3 root 134: int flags = uap->flags;
1.1 root 135:
136: #ifdef DEBUG
137: if (mmapdebug & MDB_FOLLOW)
138: printf("mmap(%d): addr %x len %x pro %x flg %x fd %d pos %x\n",
139: p->p_pid, uap->addr, uap->len, uap->prot,
1.1.1.4 ! root 140: flags, uap->fd, uap->pos);
1.1 root 141: #endif
142: /*
143: * Make sure one of the sharing types is specified
144: */
1.1.1.3 root 145: mtype = flags & MAP_TYPE;
1.1 root 146: switch (mtype) {
147: case MAP_FILE:
148: case MAP_ANON:
149: break;
150: default:
151: return(EINVAL);
152: }
153: /*
154: * Address (if FIXED) must be page aligned.
155: * Size is implicitly rounded to a page boundary.
156: */
157: addr = (vm_offset_t) uap->addr;
1.1.1.3 root 158: if ((flags & MAP_FIXED) && (addr & page_mask) || uap->len < 0)
1.1 root 159: return(EINVAL);
160: size = (vm_size_t) round_page(uap->len);
1.1.1.3 root 161: if ((flags & MAP_FIXED) && (addr + size > VM_MAXUSER_ADDRESS))
162: return EINVAL;
1.1 root 163: /*
164: * XXX if no hint provided for a non-fixed mapping place it after
165: * the end of the largest possible heap.
166: *
167: * There should really be a pmap call to determine a reasonable
168: * location.
169: */
1.1.1.3 root 170: if (addr == 0 && (flags & MAP_FIXED) == 0)
1.1 root 171: addr = round_page(p->p_vmspace->vm_daddr + MAXDSIZ);
172: /*
173: * Mapping file or named anonymous, get fp for validation
174: */
175: if (mtype == MAP_FILE || uap->fd != -1) {
176: if (((unsigned)uap->fd) >= fdp->fd_nfiles ||
177: (fp = fdp->fd_ofiles[uap->fd]) == NULL)
178: return(EBADF);
179: }
180: /*
181: * If we are mapping a file we need to check various
182: * file/vnode related things.
183: */
184: if (mtype == MAP_FILE) {
185: /*
186: * Obtain vnode and make sure it is of appropriate type
187: */
188: if (fp->f_type != DTYPE_VNODE)
189: return(EINVAL);
190: vp = (struct vnode *)fp->f_data;
191: if (vp->v_type != VREG && vp->v_type != VCHR)
192: return(EINVAL);
193: /*
194: * Ensure that file protection and desired protection
195: * are compatible. Note that we only worry about writability
1.1.1.4 ! root 196: * if mapping is shared. XXX (cgd) -- coalese access checks
! 197: * and permissions setting.
1.1 root 198: */
199: if ((uap->prot & PROT_READ) && (fp->f_flag & FREAD) == 0 ||
1.1.1.3 root 200: ((flags & MAP_SHARED) &&
1.1 root 201: (uap->prot & PROT_WRITE) && (fp->f_flag & FWRITE) == 0))
202: return(EACCES);
203: handle = (caddr_t)vp;
1.1.1.3 root 204: /*
1.1.1.4 ! root 205: * Map maximum protections to MACH style
1.1.1.3 root 206: */
1.1.1.4 ! root 207: maxprot = VM_PROT_EXECUTE; /* ??? */
1.1.1.3 root 208: if (fp->f_flag & FREAD)
209: maxprot |= VM_PROT_READ;
1.1.1.4 ! root 210: if(uap->flags & MAP_SHARED) {
! 211: if (fp->f_flag & FWRITE)
! 212: maxprot |= VM_PROT_WRITE;
! 213: } else
1.1.1.3 root 214: maxprot |= VM_PROT_WRITE;
215: } else if (uap->fd != -1) {
216: maxprot = VM_PROT_ALL;
1.1 root 217: handle = (caddr_t)fp;
1.1.1.3 root 218: } else {
219: maxprot = VM_PROT_ALL;
1.1 root 220: handle = NULL;
1.1.1.3 root 221: }
1.1 root 222: /*
1.1.1.4 ! root 223: * Map current protections to MACH style
1.1 root 224: */
225: prot = VM_PROT_NONE;
226: if (uap->prot & PROT_READ)
227: prot |= VM_PROT_READ;
228: if (uap->prot & PROT_WRITE)
229: prot |= VM_PROT_WRITE;
230: if (uap->prot & PROT_EXEC)
231: prot |= VM_PROT_EXECUTE;
232:
1.1.1.3 root 233: error = vm_mmap(&p->p_vmspace->vm_map, &addr, size, prot, maxprot,
234: flags, handle, (vm_offset_t)uap->pos);
1.1 root 235: if (error == 0)
236: *retval = (int) addr;
237: return(error);
238: }
239:
1.1.1.4 ! root 240: struct msync_args {
! 241: caddr_t addr;
! 242: int len;
! 243: };
! 244:
1.1 root 245: msync(p, uap, retval)
246: struct proc *p;
1.1.1.4 ! root 247: struct msync_args *uap;
1.1 root 248: int *retval;
249: {
250: vm_offset_t addr, objoff, oaddr;
251: vm_size_t size, osize;
252: vm_prot_t prot, mprot;
253: vm_inherit_t inherit;
254: vm_object_t object;
255: boolean_t shared;
256: int rv;
257:
258: #ifdef DEBUG
259: if (mmapdebug & (MDB_FOLLOW|MDB_SYNC))
260: printf("msync(%d): addr %x len %x\n",
261: p->p_pid, uap->addr, uap->len);
262: #endif
263: if (((int)uap->addr & page_mask) || uap->len < 0)
264: return(EINVAL);
265: addr = oaddr = (vm_offset_t)uap->addr;
266: osize = (vm_size_t)uap->len;
267: /*
268: * Region must be entirely contained in a single entry
269: */
270: if (!vm_map_is_allocated(&p->p_vmspace->vm_map, addr, addr+osize,
271: TRUE))
272: return(EINVAL);
273: /*
274: * Determine the object associated with that entry
275: * (object is returned locked on KERN_SUCCESS)
276: */
277: rv = vm_region(&p->p_vmspace->vm_map, &addr, &size, &prot, &mprot,
278: &inherit, &shared, &object, &objoff);
279: if (rv != KERN_SUCCESS)
280: return(EINVAL);
281: #ifdef DEBUG
282: if (mmapdebug & MDB_SYNC)
283: printf("msync: region: object %x addr %x size %d objoff %d\n",
284: object, addr, size, objoff);
285: #endif
286: /*
287: * Do not msync non-vnoded backed objects.
288: */
289: if (object->internal || object->pager == NULL ||
290: object->pager->pg_type != PG_VNODE) {
291: vm_object_unlock(object);
292: return(EINVAL);
293: }
294: objoff += oaddr - addr;
295: if (osize == 0)
296: osize = size;
297: #ifdef DEBUG
298: if (mmapdebug & MDB_SYNC)
299: printf("msync: cleaning/flushing object range [%x-%x)\n",
300: objoff, objoff+osize);
301: #endif
302: if (prot & VM_PROT_WRITE)
303: vm_object_page_clean(object, objoff, objoff+osize);
304: /*
305: * (XXX)
306: * Bummer, gotta flush all cached pages to ensure
307: * consistency with the file system cache.
308: */
309: vm_object_page_remove(object, objoff, objoff+osize);
310: vm_object_unlock(object);
311: return(0);
312: }
313:
1.1.1.4 ! root 314: struct munmap_args {
! 315: caddr_t addr;
! 316: int len;
! 317: };
! 318:
1.1 root 319: munmap(p, uap, retval)
320: register struct proc *p;
1.1.1.4 ! root 321: register struct munmap_args *uap;
1.1 root 322: int *retval;
323: {
324: vm_offset_t addr;
325: vm_size_t size;
326:
327: #ifdef DEBUG
328: if (mmapdebug & MDB_FOLLOW)
329: printf("munmap(%d): addr %x len %x\n",
330: p->p_pid, uap->addr, uap->len);
331: #endif
332:
333: addr = (vm_offset_t) uap->addr;
334: if ((addr & page_mask) || uap->len < 0)
335: return(EINVAL);
336: size = (vm_size_t) round_page(uap->len);
337: if (size == 0)
338: return(0);
1.1.1.3 root 339: if (addr + size >= VM_MAXUSER_ADDRESS)
340: return EINVAL;
1.1 root 341: if (!vm_map_is_allocated(&p->p_vmspace->vm_map, addr, addr+size,
342: FALSE))
343: return(EINVAL);
344: /* returns nothing but KERN_SUCCESS anyway */
345: (void) vm_map_remove(&p->p_vmspace->vm_map, addr, addr+size);
346: return(0);
347: }
348:
1.1.1.2 root 349: munmapfd(p, fd)
350: register struct proc *p;
1.1 root 351: {
352: #ifdef DEBUG
353: if (mmapdebug & MDB_FOLLOW)
1.1.1.2 root 354: printf("munmapfd(%d): fd %d\n", p->p_pid, fd);
1.1 root 355: #endif
356:
357: /*
358: * XXX -- should vm_deallocate any regions mapped to this file
359: */
1.1.1.2 root 360: p->p_fd->fd_ofileflags[fd] &= ~UF_MAPPED;
1.1 root 361: }
362:
1.1.1.4 ! root 363: struct mprotect_args {
! 364: caddr_t addr;
! 365: int len;
! 366: int prot;
! 367: };
! 368:
1.1 root 369: mprotect(p, uap, retval)
370: struct proc *p;
1.1.1.4 ! root 371: struct mprotect_args *uap;
1.1 root 372: int *retval;
373: {
374: vm_offset_t addr;
375: vm_size_t size;
376: register vm_prot_t prot;
377:
378: #ifdef DEBUG
379: if (mmapdebug & MDB_FOLLOW)
380: printf("mprotect(%d): addr %x len %x prot %d\n",
381: p->p_pid, uap->addr, uap->len, uap->prot);
382: #endif
383:
384: addr = (vm_offset_t) uap->addr;
385: if ((addr & page_mask) || uap->len < 0)
386: return(EINVAL);
387: size = (vm_size_t) uap->len;
388: /*
389: * Map protections
390: */
391: prot = VM_PROT_NONE;
392: if (uap->prot & PROT_READ)
393: prot |= VM_PROT_READ;
394: if (uap->prot & PROT_WRITE)
395: prot |= VM_PROT_WRITE;
396: if (uap->prot & PROT_EXEC)
397: prot |= VM_PROT_EXECUTE;
398:
399: switch (vm_map_protect(&p->p_vmspace->vm_map, addr, addr+size, prot,
400: FALSE)) {
401: case KERN_SUCCESS:
402: return (0);
403: case KERN_PROTECTION_FAILURE:
404: return (EACCES);
405: }
406: return (EINVAL);
407: }
408:
1.1.1.4 ! root 409: struct madvise_args {
! 410: caddr_t addr;
! 411: int len;
! 412: int behav;
! 413: };
! 414:
1.1 root 415: /* ARGSUSED */
416: madvise(p, uap, retval)
417: struct proc *p;
1.1.1.4 ! root 418: struct madvise_args *uap;
1.1 root 419: int *retval;
420: {
421:
422: /* Not yet implemented */
423: return (EOPNOTSUPP);
424: }
425:
1.1.1.4 ! root 426: struct mincore_args {
! 427: caddr_t addr;
! 428: int len;
! 429: char *vec;
! 430: };
! 431:
1.1 root 432: /* ARGSUSED */
433: mincore(p, uap, retval)
434: struct proc *p;
1.1.1.4 ! root 435: struct mincore_args *uap;
1.1 root 436: int *retval;
437: {
438:
439: /* Not yet implemented */
440: return (EOPNOTSUPP);
441: }
442:
443: /*
444: * Internal version of mmap.
445: * Currently used by mmap, exec, and sys5 shared memory.
446: * Handle is:
447: * MAP_FILE: a vnode pointer
448: * MAP_ANON: NULL or a file pointer
449: */
1.1.1.3 root 450: vm_mmap(map, addr, size, prot, maxprot, flags, handle, foff)
1.1 root 451: register vm_map_t map;
452: register vm_offset_t *addr;
453: register vm_size_t size;
454: vm_prot_t prot;
1.1.1.3 root 455: vm_prot_t maxprot;
1.1 root 456: register int flags;
457: caddr_t handle; /* XXX should be vp */
458: vm_offset_t foff;
459: {
460: register vm_pager_t pager;
461: boolean_t fitit;
462: vm_object_t object;
463: struct vnode *vp;
464: int type;
465: int rv = KERN_SUCCESS;
466:
467: if (size == 0)
468: return (0);
469:
470: if ((flags & MAP_FIXED) == 0) {
471: fitit = TRUE;
472: *addr = round_page(*addr);
473: } else {
474: fitit = FALSE;
475: (void) vm_deallocate(map, *addr, size);
476: }
477:
478: /*
479: * Lookup/allocate pager. All except an unnamed anonymous lookup
480: * gain a reference to ensure continued existance of the object.
481: * (XXX the exception is to appease the pageout daemon)
482: */
483: if ((flags & MAP_TYPE) == MAP_ANON)
484: type = PG_DFLT;
485: else {
486: vp = (struct vnode *)handle;
487: if (vp->v_type == VCHR) {
488: type = PG_DEVICE;
489: handle = (caddr_t)vp->v_rdev;
490: } else
491: type = PG_VNODE;
492: }
493: pager = vm_pager_allocate(type, handle, size, prot);
494: if (pager == NULL)
495: return (type == PG_DEVICE ? EINVAL : ENOMEM);
496: /*
497: * Find object and release extra reference gained by lookup
498: */
499: object = vm_object_lookup(pager);
500: vm_object_deallocate(object);
501:
502: /*
503: * Anonymous memory.
504: */
505: if ((flags & MAP_TYPE) == MAP_ANON) {
506: rv = vm_allocate_with_pager(map, addr, size, fitit,
507: pager, (vm_offset_t)foff, TRUE);
508: if (rv != KERN_SUCCESS) {
509: if (handle == NULL)
510: vm_pager_deallocate(pager);
511: else
512: vm_object_deallocate(object);
513: goto out;
514: }
515: /*
1.1.1.3 root 516: * The object of unnamed anonymous regions was just created
517: * find it for pager_cache.
518: */
519: if (handle == NULL)
520: object = vm_object_lookup(pager);
521:
522: /*
1.1 root 523: * Don't cache anonymous objects.
524: * Loses the reference gained by vm_pager_allocate.
525: */
526: (void) pager_cache(object, FALSE);
527: #ifdef DEBUG
528: if (mmapdebug & MDB_MAPIT)
529: printf("vm_mmap(%d): ANON *addr %x size %x pager %x\n",
530: curproc->p_pid, *addr, size, pager);
531: #endif
532: }
533: /*
534: * Must be type MAP_FILE.
535: * Distinguish between character special and regular files.
536: */
537: else if (vp->v_type == VCHR) {
538: rv = vm_allocate_with_pager(map, addr, size, fitit,
539: pager, (vm_offset_t)foff, FALSE);
540: /*
541: * Uncache the object and lose the reference gained
542: * by vm_pager_allocate(). If the call to
543: * vm_allocate_with_pager() was sucessful, then we
544: * gained an additional reference ensuring the object
545: * will continue to exist. If the call failed then
546: * the deallocate call below will terminate the
547: * object which is fine.
548: */
549: (void) pager_cache(object, FALSE);
550: if (rv != KERN_SUCCESS)
551: goto out;
552: }
553: /*
554: * A regular file
555: */
556: else {
557: #ifdef DEBUG
558: if (object == NULL)
559: printf("vm_mmap: no object: vp %x, pager %x\n",
560: vp, pager);
561: #endif
562: /*
563: * Map it directly.
564: * Allows modifications to go out to the vnode.
565: */
566: if (flags & MAP_SHARED) {
567: rv = vm_allocate_with_pager(map, addr, size,
568: fitit, pager,
569: (vm_offset_t)foff, FALSE);
570: if (rv != KERN_SUCCESS) {
571: vm_object_deallocate(object);
572: goto out;
573: }
574: /*
575: * Don't cache the object. This is the easiest way
576: * of ensuring that data gets back to the filesystem
577: * because vnode_pager_deallocate() will fsync the
578: * vnode. pager_cache() will lose the extra ref.
579: */
580: if (prot & VM_PROT_WRITE)
581: pager_cache(object, FALSE);
582: else
583: vm_object_deallocate(object);
584: }
585: /*
586: * Copy-on-write of file. Two flavors.
587: * MAP_COPY is true COW, you essentially get a snapshot of
588: * the region at the time of mapping. MAP_PRIVATE means only
589: * that your changes are not reflected back to the object.
590: * Changes made by others will be seen.
591: */
592: else {
593: vm_map_t tmap;
594: vm_offset_t off;
595:
596: /* locate and allocate the target address space */
597: rv = vm_map_find(map, NULL, (vm_offset_t)0,
598: addr, size, fitit);
599: if (rv != KERN_SUCCESS) {
600: vm_object_deallocate(object);
601: goto out;
602: }
603: tmap = vm_map_create(pmap_create(size), VM_MIN_ADDRESS,
604: VM_MIN_ADDRESS+size, TRUE);
605: off = VM_MIN_ADDRESS;
606: rv = vm_allocate_with_pager(tmap, &off, size,
607: TRUE, pager,
608: (vm_offset_t)foff, FALSE);
609: if (rv != KERN_SUCCESS) {
610: vm_object_deallocate(object);
611: vm_map_deallocate(tmap);
612: goto out;
613: }
614: /*
615: * (XXX)
616: * MAP_PRIVATE implies that we see changes made by
617: * others. To ensure that we need to guarentee that
618: * no copy object is created (otherwise original
619: * pages would be pushed to the copy object and we
620: * would never see changes made by others). We
621: * totally sleeze it right now by marking the object
622: * internal temporarily.
623: */
624: if ((flags & MAP_COPY) == 0)
625: object->internal = TRUE;
626: rv = vm_map_copy(map, tmap, *addr, size, off,
627: FALSE, FALSE);
628: object->internal = FALSE;
629: /*
630: * (XXX)
631: * My oh my, this only gets worse...
632: * Force creation of a shadow object so that
633: * vm_map_fork will do the right thing.
634: */
635: if ((flags & MAP_COPY) == 0) {
636: vm_map_t tmap;
637: vm_map_entry_t tentry;
638: vm_object_t tobject;
639: vm_offset_t toffset;
640: vm_prot_t tprot;
641: boolean_t twired, tsu;
642:
643: tmap = map;
644: vm_map_lookup(&tmap, *addr, VM_PROT_WRITE,
645: &tentry, &tobject, &toffset,
646: &tprot, &twired, &tsu);
647: vm_map_lookup_done(tmap, tentry);
648: }
649: /*
650: * (XXX)
651: * Map copy code cannot detect sharing unless a
652: * sharing map is involved. So we cheat and write
653: * protect everything ourselves.
654: */
655: vm_object_pmap_copy(object, (vm_offset_t)foff,
656: (vm_offset_t)foff+size);
657: vm_object_deallocate(object);
658: vm_map_deallocate(tmap);
659: if (rv != KERN_SUCCESS)
660: goto out;
661: }
662: #ifdef DEBUG
663: if (mmapdebug & MDB_MAPIT)
664: printf("vm_mmap(%d): FILE *addr %x size %x pager %x\n",
665: curproc->p_pid, *addr, size, pager);
666: #endif
667: }
668: /*
669: * Correct protection (default is VM_PROT_ALL).
670: * Note that we set the maximum protection. This may not be
1.1.1.4 ! root 671: * entirely correct. The maximum protection is be based on
! 672: * the object permissions where it makes sense (e.g. a vnode).
1.1 root 673: */
674: rv = vm_map_protect(map, *addr, *addr+size, prot, FALSE);
675: if (rv != KERN_SUCCESS) {
676: (void) vm_deallocate(map, *addr, size);
677: goto out;
678: }
1.1.1.3 root 679: /*
680: * We only need to set max_protection in case it's
681: * unequal to its default, which is VM_PROT_DEFAULT.
682: */
683: if(maxprot != VM_PROT_DEFAULT) {
684: rv = vm_map_protect(map, *addr, *addr+size, maxprot, TRUE);
685: if (rv != KERN_SUCCESS) {
686: (void) vm_deallocate(map, *addr, size);
687: goto out;
688: }
1.1 root 689: }
690: /*
691: * Shared memory is also shared with children.
692: */
693: if (flags & MAP_SHARED) {
694: rv = vm_inherit(map, *addr, size, VM_INHERIT_SHARE);
695: if (rv != KERN_SUCCESS) {
696: (void) vm_deallocate(map, *addr, size);
697: goto out;
698: }
699: }
700: out:
701: #ifdef DEBUG
702: if (mmapdebug & MDB_MAPIT)
703: printf("vm_mmap: rv %d\n", rv);
704: #endif
705: switch (rv) {
706: case KERN_SUCCESS:
707: return (0);
708: case KERN_INVALID_ADDRESS:
709: case KERN_NO_SPACE:
710: return (ENOMEM);
711: case KERN_PROTECTION_FAILURE:
712: return (EACCES);
713: default:
714: return (EINVAL);
715: }
716: }
717:
718: /*
719: * Internal bastardized version of MACHs vm_region system call.
720: * Given address and size it returns map attributes as well
721: * as the (locked) object mapped at that location.
722: */
723: vm_region(map, addr, size, prot, max_prot, inheritance, shared, object, objoff)
724: vm_map_t map;
725: vm_offset_t *addr; /* IN/OUT */
726: vm_size_t *size; /* OUT */
727: vm_prot_t *prot; /* OUT */
728: vm_prot_t *max_prot; /* OUT */
729: vm_inherit_t *inheritance; /* OUT */
730: boolean_t *shared; /* OUT */
731: vm_object_t *object; /* OUT */
732: vm_offset_t *objoff; /* OUT */
733: {
734: vm_map_entry_t tmp_entry;
735: register
736: vm_map_entry_t entry;
737: register
738: vm_offset_t tmp_offset;
739: vm_offset_t start;
740:
741: if (map == NULL)
742: return(KERN_INVALID_ARGUMENT);
743:
744: start = *addr;
745:
746: vm_map_lock_read(map);
747: if (!vm_map_lookup_entry(map, start, &tmp_entry)) {
748: if ((entry = tmp_entry->next) == &map->header) {
749: vm_map_unlock_read(map);
750: return(KERN_NO_SPACE);
751: }
752: start = entry->start;
753: *addr = start;
754: } else
755: entry = tmp_entry;
756:
757: *prot = entry->protection;
758: *max_prot = entry->max_protection;
759: *inheritance = entry->inheritance;
760:
761: tmp_offset = entry->offset + (start - entry->start);
762: *size = (entry->end - start);
763:
764: if (entry->is_a_map) {
765: register vm_map_t share_map;
766: vm_size_t share_size;
767:
768: share_map = entry->object.share_map;
769:
770: vm_map_lock_read(share_map);
771: (void) vm_map_lookup_entry(share_map, tmp_offset, &tmp_entry);
772:
773: if ((share_size = (tmp_entry->end - tmp_offset)) < *size)
774: *size = share_size;
775:
776: vm_object_lock(tmp_entry->object);
777: *object = tmp_entry->object.vm_object;
778: *objoff = tmp_entry->offset + (tmp_offset - tmp_entry->start);
779:
780: *shared = (share_map->ref_count != 1);
781: vm_map_unlock_read(share_map);
782: } else {
783: vm_object_lock(entry->object);
784: *object = entry->object.vm_object;
785: *objoff = tmp_offset;
786:
787: *shared = FALSE;
788: }
789:
790: vm_map_unlock_read(map);
791:
792: return(KERN_SUCCESS);
793: }
794:
795: /*
796: * Yet another bastard routine.
797: */
798: vm_allocate_with_pager(map, addr, size, fitit, pager, poffset, internal)
799: register vm_map_t map;
800: register vm_offset_t *addr;
801: register vm_size_t size;
802: boolean_t fitit;
803: vm_pager_t pager;
804: vm_offset_t poffset;
805: boolean_t internal;
806: {
807: register vm_object_t object;
808: register int result;
809:
810: if (map == NULL)
811: return(KERN_INVALID_ARGUMENT);
812:
813: *addr = trunc_page(*addr);
814: size = round_page(size);
815:
816: /*
817: * Lookup the pager/paging-space in the object cache.
818: * If it's not there, then create a new object and cache
819: * it.
820: */
821: object = vm_object_lookup(pager);
822: vm_stat.lookups++;
823: if (object == NULL) {
824: object = vm_object_allocate(size);
825: vm_object_enter(object, pager);
826: } else
827: vm_stat.hits++;
828: object->internal = internal;
829:
830: result = vm_map_find(map, object, poffset, addr, size, fitit);
831: if (result != KERN_SUCCESS)
832: vm_object_deallocate(object);
833: else if (pager != NULL)
834: vm_object_setpager(object, pager, (vm_offset_t) 0, TRUE);
835: return(result);
836: }
837:
838: /*
839: * XXX: this routine belongs in vm_map.c.
840: *
841: * Returns TRUE if the range [start - end) is allocated in either
842: * a single entry (single_entry == TRUE) or multiple contiguous
843: * entries (single_entry == FALSE).
844: *
845: * start and end should be page aligned.
846: */
847: boolean_t
848: vm_map_is_allocated(map, start, end, single_entry)
849: vm_map_t map;
850: vm_offset_t start, end;
851: boolean_t single_entry;
852: {
853: vm_map_entry_t mapent;
854: register vm_offset_t nend;
855:
856: vm_map_lock_read(map);
857:
858: /*
859: * Start address not in any entry
860: */
861: if (!vm_map_lookup_entry(map, start, &mapent)) {
862: vm_map_unlock_read(map);
863: return (FALSE);
864: }
865: /*
866: * Find the maximum stretch of contiguously allocated space
867: */
868: nend = mapent->end;
869: if (!single_entry) {
870: mapent = mapent->next;
871: while (mapent != &map->header && mapent->start == nend) {
872: nend = mapent->end;
873: mapent = mapent->next;
874: }
875: }
876:
877: vm_map_unlock_read(map);
878: return (end <= nend);
879: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.