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