|
|
1.1 root 1: /*
2: * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
3: *
4: * @APPLE_LICENSE_HEADER_START@
5: *
6: * The contents of this file constitute Original Code as defined in and
7: * are subject to the Apple Public Source License Version 1.1 (the
8: * "License"). You may not use this file except in compliance with the
9: * License. Please obtain a copy of the License at
10: * http://www.apple.com/publicsource and read it before using this file.
11: *
12: * This Original Code and all software distributed under the License are
13: * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
14: * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
15: * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
16: * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
17: * License for the specific language governing rights and limitations
18: * under the License.
19: *
20: * @APPLE_LICENSE_HEADER_END@
21: */
22: /*
23: * Copyright (c) 1988 University of Utah.
24: * Copyright (c) 1991, 1993
25: * The Regents of the University of California. All rights reserved.
26: *
27: * This code is derived from software contributed to Berkeley by
28: * the Systems Programming Group of the University of Utah Computer
29: * Science Department.
30: *
31: * Redistribution and use in source and binary forms, with or without
32: * modification, are permitted provided that the following conditions
33: * are met:
34: * 1. Redistributions of source code must retain the above copyright
35: * notice, this list of conditions and the following disclaimer.
36: * 2. Redistributions in binary form must reproduce the above copyright
37: * notice, this list of conditions and the following disclaimer in the
38: * documentation and/or other materials provided with the distribution.
39: * 3. All advertising materials mentioning features or use of this software
40: * must display the following acknowledgement:
41: * This product includes software developed by the University of
42: * California, Berkeley and its contributors.
43: * 4. Neither the name of the University nor the names of its contributors
44: * may be used to endorse or promote products derived from this software
45: * without specific prior written permission.
46: *
47: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
48: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
49: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
50: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
51: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
52: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
53: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
54: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
55: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
56: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
57: * SUCH DAMAGE.
58: *
59: * from: Utah $Hdr: vm_mmap.c 1.6 91/10/21$
60: *
61: * @(#)vm_mmap.c 8.10 (Berkeley) 2/19/95
62: */
63:
64: /*
65: * Mapped file (mmap) interface to VM
66: */
67:
68: #include <sys/param.h>
69: #include <sys/systm.h>
70: #include <sys/filedesc.h>
71: #include <sys/proc.h>
72: #include <sys/resourcevar.h>
73: #include <sys/buf.h>
74: #include <sys/vnode.h>
75: #include <sys/acct.h>
76: #include <sys/wait.h>
77: #include <sys/file.h>
78: #include <sys/vadvise.h>
79: #include <sys/trace.h>
80: #include <sys/mman.h>
81: #include <sys/conf.h>
82: #include <sys/stat.h>
83:
84: #include <mach/mach_types.h>
85:
86: #include <kern/cpu_number.h>
87:
88: #include <vm/vm_map.h>
89: #include <vm/vm_kern.h>
90: #include <vm/vm_pager.h>
91: #include <vm/vnode_pager.h>
92: #include <kern/mapfs.h>
93:
94: #include <mach/vm_sync.h>
95: #include <mach/vm_behavior.h>
96: #include <mach/vm_inherit.h>
97: #include <mach/vm_statistics.h>
98:
99: struct sbrk_args {
100: int incr;
101: };
102:
103: /* ARGSUSED */
104: int
105: sbrk(p, uap, retval)
106: struct proc *p;
107: struct sbrk_args *uap;
108: register_t *retval;
109: {
110: /* Not yet implemented */
111: return (EOPNOTSUPP);
112: }
113:
114: struct sstk_args {
115: int incr;
116: } *uap;
117:
118: /* ARGSUSED */
119: int
120: sstk(p, uap, retval)
121: struct proc *p;
122: struct sstk_args *uap;
123: register_t *retval;
124: {
125: /* Not yet implemented */
126: return (EOPNOTSUPP);
127: }
128:
129: #if COMPAT_43
130: /* ARGSUSED */
131: int
132: ogetpagesize(p, uap, retval)
133: struct proc *p;
134: void *uap;
135: register_t *retval;
136: {
137:
138: *retval = PAGE_SIZE;
139: return (0);
140: }
141: #endif /* COMPAT_43 */
142:
143: struct osmmap_args {
144: caddr_t addr;
145: int len;
146: int prot;
147: int share;
148: int fd;
149: long pos;
150: };
151:
152: osmmap(curp, uap, retval)
153: struct proc *curp;
154: register struct osmmap_args *uap;
155: register_t *retval;
156: {
157: struct mmap_args {
158: caddr_t addr;
159: size_t len;
160: int prot;
161: int flags;
162: int fd;
163: #ifdef DOUBLE_ALIGN_PARAMS
164: long pad;
165: #endif
166: off_t pos;
167: } newargs;
168:
169: if ((uap->share == MAP_SHARED )|| (uap->share == MAP_PRIVATE )) {
170: newargs.addr = uap->addr;
171: newargs.len = (size_t)uap->len;
172: newargs.prot = uap->prot;
173: newargs.flags = uap->share;
174: newargs.fd = uap->fd;
175: newargs.pos = (off_t)uap->pos;
176: return(mmap(curp,&newargs, retval));
177: } else
178: return(EINVAL);
179: }
180:
181: struct mmap_args {
182: caddr_t addr;
183: size_t len;
184: int prot;
185: int flags;
186: int fd;
187: #ifdef DOUBLE_ALIGN_PARAMS
188: long pad;
189: #endif
190: off_t pos;
191: };
192: int
193: mmap(p, uap, retval)
194: struct proc *p;
195: struct mmap_args *uap;
196: register_t *retval;
197: {
198: /*
199: * Map in special device (must be SHARED) or file
200: */
201: struct file *fp;
202: register struct vnode *vp;
203: int flags;
204: int prot;
205: int err=0;
206: vm_map_t user_map;
207: kern_return_t result;
208: vm_offset_t user_addr;
209: vm_size_t user_size, pageoff;
210: vm_offset_t file_pos;
211: boolean_t find_space, docow;
212: vm_prot_t maxprot;
213: void *handle;
214: vm_pager_t pager;
215: struct vm_info *vmp;
216: int mapanon=0;
217:
218: user_addr = (vm_offset_t)uap->addr;
219: user_size = (vm_size_t) uap->len;
220: prot = (uap->prot & VM_PROT_ALL);
221: flags = uap->flags;
222:
223: /*
224: * The vm code does not have prototypes & compiler doesn't do the'
225: * the right thing when you cast 64bit value and pass it in function
226: * call. So here it is.
227: */
228: file_pos = (vm_offset_t)uap->pos;
229:
230:
231: /* make sure mapping fits into numeric range etc */
232: if ((file_pos + user_size > (vm_offset_t)-PAGE_SIZE) ||
233: ((ssize_t) uap->len < 0 )||
234: ((flags & MAP_ANON) && uap->fd != -1))
235: return (EINVAL);
236:
237: /*
238: * Align the file position to a page boundary,
239: * and save its page offset component.
240: */
241: pageoff = (file_pos & PAGE_MASK);
242: file_pos -= pageoff;
243:
244:
245: /* Adjust size for rounding (on both ends). */
246: user_size += pageoff; /* low end... */
247: user_size = (vm_size_t) round_page(user_size); /* hi end */
248:
249:
250: /*
251: * Check for illegal addresses. Watch out for address wrap... Note
252: * that VM_*_ADDRESS are not constants due to casts (argh).
253: */
254: if (flags & MAP_FIXED) {
255: /*
256: * The specified address must have the same remainder
257: * as the file offset taken modulo PAGE_SIZE, so it
258: * should be aligned after adjustment by pageoff.
259: */
260: user_addr -= pageoff;
261: if (user_addr & PAGE_MASK)
262: return (EINVAL);
263: /* Address range must be all in user VM space. */
264: if (VM_MAX_ADDRESS > 0 && (user_addr + user_size > VM_MAX_ADDRESS))
265: return (EINVAL);
266: if (VM_MIN_ADDRESS > 0 && user_addr < VM_MIN_ADDRESS)
267: return (EINVAL);
268: if (user_addr + user_size < user_addr)
269: return (EINVAL);
270: }
271: #ifdef notyet
272: /* DO not have apis to get this info, need to wait till then*/
273: /*
274: * XXX for non-fixed mappings where no hint is provided or
275: * the hint would fall in the potential heap space,
276: * place it after the end of the largest possible heap.
277: *
278: * There should really be a pmap call to determine a reasonable
279: * location.
280: */
281: else if (addr < round_page(p->p_vmspace->vm_daddr + MAXDSIZ))
282: addr = round_page(p->p_vmspace->vm_daddr + MAXDSIZ);
283:
284: #endif
285:
286:
287: if (flags & MAP_ANON) {
288: /*
289: * Mapping blank space is trivial.
290: */
291: handle = NULL;
292: maxprot = VM_PROT_ALL;
293: file_pos = 0;
294: mapanon = 1;
295: } else {
296: /*
297: * Mapping file, get fp for validation. Obtain vnode and make
298: * sure it is of appropriate type.
299: */
300: err = fdgetf(p, uap->fd, &fp);
301: if (err)
302: return(err);
303: if(fp->f_type == DTYPE_PSXSHM) {
304: uap->addr = user_addr;
305: uap->len = user_size;
306: uap->prot = prot;
307: uap->flags = flags;
308: uap->pos = file_pos;
309: return(pshm_mmap(p, uap, retval, fp , pageoff));
310: }
311:
312: if (fp->f_type != DTYPE_VNODE)
313: return(EINVAL);
314: vp = (struct vnode *)fp->f_data;
315:
316: if (vp->v_type != VREG && vp->v_type != VCHR)
317: return (EINVAL);
318: /*
319: * XXX hack to handle use of /dev/zero to map anon memory (ala
320: * SunOS).
321: */
322: if (vp->v_type == VCHR || vp->v_type == VSTR) {
323: return(EOPNOTSUPP);
324: } else {
325: /*
326: * Ensure that file and memory protections are
327: * compatible. Note that we only worry about
328: * writability if mapping is shared; in this case,
329: * current and max prot are dictated by the open file.
330: * XXX use the vnode instead? Problem is: what
331: * credentials do we use for determination? What if
332: * proc does a setuid?
333: */
334: maxprot = VM_PROT_EXECUTE; /* ??? */
335: if (fp->f_flag & FREAD)
336: maxprot |= VM_PROT_READ;
337: else if (prot & PROT_READ)
338: return (EACCES);
339: /*
340: * If we are sharing potential changes (either via
341: * MAP_SHARED or via the implicit sharing of character
342: * device mappings), and we are trying to get write
343: * permission although we opened it without asking
344: * for it, bail out.
345: */
346:
347: if ((flags & MAP_SHARED) != 0) {
348: if ((fp->f_flag & FWRITE) != 0) {
349: struct vattr va;
350: if ((err =
351: VOP_GETATTR(vp, &va,
352: p->p_ucred, p)))
353: return (err);
354: if ((va.va_flags &
355: (IMMUTABLE|APPEND)) == 0)
356: maxprot |= VM_PROT_WRITE;
357: else if (prot & PROT_WRITE)
358: return (EPERM);
359: } else if ((prot & PROT_WRITE) != 0)
360: return (EACCES);
361: } else
362: maxprot |= VM_PROT_WRITE;
363:
364: handle = (void *)vp;
365: }
366: }
367:
368: if (user_size == 0)
369: return(0);
370:
371: /*
372: * We bend a little - round the start and end addresses
373: * to the nearest page boundary.
374: */
375: user_size = round_page(user_size);
376:
377: if (file_pos & PAGE_MASK)
378: return (EINVAL);
379:
380: user_map = current_map();
381:
382: if ((flags & MAP_FIXED) == 0) {
383: find_space = TRUE;
384: user_addr = round_page(user_addr);
385: } else {
386: if (user_addr != trunc_page(user_addr))
387: return (EINVAL);
388: find_space = FALSE;
389: (void) vm_deallocate(user_map, user_addr, user_size);
390: }
391:
392:
393: /*
394: * Lookup/allocate object.
395: */
396: if (flags & MAP_ANON) {
397: /*
398: * Unnamed anonymous regions always start at 0.
399: */
400: if (handle == 0)
401: file_pos = 0;
402: }
403:
404: if (handle == NULL) {
405: pager = NULL;
406: #ifdef notyet
407: /* Hmm .. */
408: #if defined(VM_PROT_READ_IS_EXEC)
409: if (prot & VM_PROT_READ)
410: prot |= VM_PROT_EXECUTE;
411:
412: if (maxprot & VM_PROT_READ)
413: maxprot |= VM_PROT_EXECUTE;
414: #endif
415: #endif
416: result = vm_allocate(user_map, &user_addr, user_size, find_space);
417: if (result != KERN_SUCCESS)
418: goto out;
419:
420: } else {
421: if (!vp->v_vm_info) {
422: vm_info_init(vp);
423: }
424: pager = vnode_pager_setup(vp,
425: vp->v_vm_info->pager, FALSE, FALSE);
426:
427: if (pager == NULL)
428: return (ENOMEM);
429: /*
430: * Set credentials:
431: * FIXME: if we're writing the file we need a way to
432: * ensure that someone doesn't replace our R/W creds
433: * with ones that only work for read.
434: */
435: vmp = vp->v_vm_info;
436: if (vmp->cred == NULL) {
437: crhold(p->p_ucred);
438: vmp->cred = p->p_ucred;
439: }
440: docow = FALSE;
441: if ((flags & (MAP_ANON|MAP_SHARED)) == 0) {
442: docow = TRUE;
443: }
444:
445: #ifdef notyet
446: /* Hmm .. */
447: #if defined(VM_PROT_READ_IS_EXEC)
448: if (prot & VM_PROT_READ)
449: prot |= VM_PROT_EXECUTE;
450:
451: if (maxprot & VM_PROT_READ)
452: maxprot |= VM_PROT_EXECUTE;
453: #endif
454: #endif /* notyet */
455:
456: result = vm_map(user_map, &user_addr, user_size,
457: 0, find_space, pager, file_pos, docow,
458: prot, maxprot,
459: VM_INHERIT_DEFAULT);
460:
461: if (result != KERN_SUCCESS)
462: goto out;
463:
464: }
465:
466: if (flags & (MAP_SHARED|MAP_INHERIT)) {
467: result = vm_inherit(user_map, user_addr, user_size,
468: VM_INHERIT_SHARE);
469: if (result != KERN_SUCCESS) {
470: (void) vm_deallocate(user_map, user_addr, user_size);
471: goto out;
472: }
473: }
474:
475: out:
476: switch (result) {
477: case KERN_SUCCESS:
478: if(!mapanon) {
479: *fdflags(p, uap->fd) |= UF_MAPPED;
480: if (ISMAPPABLEFILE(vp))
481: vp->v_vm_info->mapped = 1;
482: }
483: *retval = (register_t)(user_addr + pageoff);
484: return (0);
485: case KERN_INVALID_ADDRESS:
486: case KERN_NO_SPACE:
487: return (ENOMEM);
488: case KERN_PROTECTION_FAILURE:
489: return (EACCES);
490: default:
491: return (EINVAL);
492: }
493: /*NOTREACHED*/
494: }
495:
496: struct msync_args {
497: caddr_t addr;
498: int len;
499: int flags;
500: };
501: int
502: msync(p, uap, retval)
503: struct proc *p;
504: struct msync_args *uap;
505: register_t *retval;
506: {
507: vm_offset_t addr;
508: vm_size_t size, pageoff;
509: int flags;
510: vm_map_t user_map;
511: int rv;
512: vm_sync_t sync_flags=0;
513:
514: addr = (vm_offset_t) uap->addr;
515: pageoff = (addr & PAGE_MASK);
516: addr -= pageoff;
517: size = uap->len;
518: size = (vm_size_t) round_page(size);
519: flags = uap->flags;
520:
521: if (addr + size < addr)
522: return(EINVAL);
523:
524: user_map = current_map();
525:
526: if ((flags & (MS_ASYNC|MS_INVALIDATE)) == (MS_ASYNC|MS_INVALIDATE))
527: return (EINVAL);
528:
529: #ifdef notyet
530: /* XXX Gak! If size is zero we are supposed to sync "all modified
531: * pages with the region containing addr". Unfortunately, we don't
532: * really keep track of individual mmaps so we approximate by flushing
533: * the range of the map entry containing addr. This can be incorrect
534: * if the region splits or is coalesced with a neighbor.
535: */
536: if (size == 0) {
537: vm_map_entry_t entry;
538:
539: vm_map_lock_read(map);
540: rv = vm_map_lookup_entry(map, addr, &entry);
541: vm_map_unlock_read(map);
542: if (rv == FALSE)
543: return (EINVAL);
544: addr = entry->start;
545: size = entry->end - entry->start;
546: }
547: #endif /* notyet */
548:
549: if (flags & MS_ASYNC)
550: sync_flags |= VM_SYNC_ASYNCHRONOUS;
551: else
552: sync_flags |= VM_SYNC_SYNCHRONOUS;
553:
554: if (flags & MS_INVALIDATE)
555: sync_flags |= VM_SYNC_INVALIDATE;
556:
557: rv = vm_msync(user_map, addr, size, sync_flags);
558:
559: switch (rv) {
560: case KERN_SUCCESS:
561: break;
562: case KERN_INVALID_ADDRESS:
563: return (EINVAL); /* Sun returns ENOMEM? */
564: case KERN_FAILURE:
565: return (EIO);
566: default:
567: return (EINVAL);
568: }
569:
570: return (0);
571:
572: }
573:
574:
575: mremap()
576: {
577: /* Not yet implemented */
578: return (EOPNOTSUPP);
579: }
580:
581: struct munmap_args {
582: caddr_t addr;
583: int len;
584: };
585: munmap(p, uap, retval)
586: struct proc *p;
587: struct munmap_args *uap;
588: register_t *retval;
589:
590: {
591: vm_offset_t user_addr;
592: vm_size_t user_size, pageoff;
593: kern_return_t result;
594:
595: user_addr = (vm_offset_t) uap->addr;
596: user_size = (vm_size_t) uap->len;
597:
598: pageoff = (user_addr & PAGE_MASK);
599:
600: user_addr -= pageoff;
601: user_size += pageoff;
602: user_size = round_page(user_size);
603: if (user_addr + user_size < user_addr)
604: return(EINVAL);
605:
606: if (user_size == 0)
607: return (0);
608:
609: /* Address range must be all in user VM space. */
610: if (VM_MAX_ADDRESS > 0 && (user_addr + user_size > VM_MAX_ADDRESS))
611: return (EINVAL);
612: if (VM_MIN_ADDRESS > 0 && user_addr < VM_MIN_ADDRESS)
613: return (EINVAL);
614:
615:
616: result = vm_deallocate(current_map(), user_addr, user_size);
617: if (result != KERN_SUCCESS) {
618: return(EINVAL);
619: }
620: return(0);
621: }
622:
623: void
624: munmapfd(p, fd)
625: struct proc *p;
626: int fd;
627: {
628: /*
629: * XXX should vm_deallocate any regions mapped to this file
630: */
631: *fdflags(p, fd) &= ~UF_MAPPED;
632: }
633:
634: struct mprotect_args {
635: caddr_t addr;
636: int len;
637: int prot;
638: };
639: int
640: mprotect(p, uap, retval)
641: struct proc *p;
642: struct mprotect_args *uap;
643: register_t *retval;
644: {
645: register vm_prot_t prot;
646: vm_offset_t user_addr;
647: vm_size_t user_size, pageoff;
648: kern_return_t result;
649: vm_map_t user_map;
650:
651: user_addr = (vm_offset_t) uap->addr;
652: user_size = (vm_size_t) uap->len;
653: prot = (vm_prot_t)(uap->prot & VM_PROT_ALL);
654:
655: #ifdef notyet
656: /* Hmm .. */
657: #if defined(VM_PROT_READ_IS_EXEC)
658: if (prot & VM_PROT_READ)
659: prot |= VM_PROT_EXECUTE;
660: #endif
661: #endif /* notyet */
662:
663: pageoff = (user_addr & PAGE_MASK);
664: user_addr -= pageoff;
665: user_size += pageoff;
666: user_size = round_page(user_size);
667: if (user_addr + user_size < user_addr)
668: return(EINVAL);
669:
670: user_map = current_map();
671:
672: result = vm_map_protect(user_map, user_addr, user_addr+user_size, prot,
673: FALSE);
674: switch (result) {
675: case KERN_SUCCESS:
676: return (0);
677: case KERN_PROTECTION_FAILURE:
678: return (EACCES);
679: }
680: return (EINVAL);
681: }
682:
683:
684: struct minherit_args {
685: void *addr;
686: size_t len;
687: int inherit;
688: };
689:
690: int
691: minherit(p, uap, retval)
692: struct proc *p;
693: struct minherit_args *uap;
694: register_t *retval;
695: {
696: vm_offset_t addr;
697: vm_size_t size, pageoff;
698: register vm_inherit_t inherit;
699: vm_map_t user_map;
700: kern_return_t result;
701:
702: addr = (vm_offset_t)uap->addr;
703: size = uap->len;
704: inherit = uap->inherit;
705:
706: pageoff = (addr & PAGE_MASK);
707: addr -= pageoff;
708: size += pageoff;
709: size = (vm_size_t) round_page(size);
710: if (addr + size < addr)
711: return(EINVAL);
712:
713: user_map = current_map();
714: result = vm_inherit(user_map, addr, size,
715: inherit);
716: switch (result) {
717: case KERN_SUCCESS:
718: return (0);
719: case KERN_PROTECTION_FAILURE:
720: return (EACCES);
721: }
722: return (EINVAL);
723: }
724:
725: struct madvise_args {
726: caddr_t addr;
727: int len;
728: int behav;
729: };
730: /* ARGSUSED */
731: int
732: madvise(p, uap, retval)
733: struct proc *p;
734: struct madvise_args *uap;
735: register_t *retval;
736: {
737: vm_map_t user_map;
738: vm_offset_t start, end;
739: vm_behavior_t new_behavior;
740: kern_return_t result;
741:
742: /*
743: * Check for illegal addresses. Watch out for address wrap... Note
744: * that VM_*_ADDRESS are not constants due to casts (argh).
745: */
746: if (VM_MAX_ADDRESS > 0 &&
747: ((vm_offset_t) uap->addr + uap->len) > VM_MAX_ADDRESS)
748: return (EINVAL);
749: if (VM_MIN_ADDRESS > 0 && uap->addr < VM_MIN_ADDRESS)
750: return (EINVAL);
751:
752: if (((vm_offset_t) uap->addr + uap->len) < (vm_offset_t) uap->addr)
753: return (EINVAL);
754:
755: /*
756: * Since this routine is only advisory, we default to conservative
757: * behavior.
758: */
759: start = trunc_page((vm_offset_t) uap->addr);
760: end = round_page((vm_offset_t) uap->addr + uap->len);
761:
762: user_map = current_map();
763:
764: switch (uap->behav) {
765: case MADV_RANDOM:
766: new_behavior = VM_BEHAVIOR_RANDOM;
767: case MADV_SEQUENTIAL:
768: new_behavior = VM_BEHAVIOR_SEQUENTIAL;
769: case MADV_NORMAL:
770: default:
771: new_behavior = VM_BEHAVIOR_DEFAULT;
772: }
773:
774: result = vm_behavior_set(user_map, start, end, uap->behav);
775: switch (result) {
776: case KERN_SUCCESS:
777: return (0);
778: case KERN_INVALID_ADDRESS:
779: return (EINVAL);
780: }
781:
782: return (EINVAL);
783: }
784:
785: struct mincore_args {
786: const void *addr;
787: size_t len;
788: char *vec;
789: };
790: /* ARGSUSED */
791: int
792: mincore(p, uap, retval)
793: struct proc *p;
794: struct mincore_args *uap;
795: register_t *retval;
796: {
797: vm_offset_t addr, first_addr;
798: vm_offset_t end;
799: vm_map_t map;
800: char *vec;
801: int error;
802: int vecindex, lastvecindex;
803: int mincoreinfo=0;
804: int pqueryinfo;
805: kern_return_t ret;
806: int numref;
807:
808: map = current_map();
809:
810: /*
811: * Make sure that the addresses presented are valid for user
812: * mode.
813: */
814: first_addr = addr = trunc_page((vm_offset_t) uap->addr);
815: end = addr + (vm_size_t)round_page(uap->len);
816:
817: if (VM_MAX_ADDRESS > 0 && end > VM_MAX_ADDRESS)
818: return (EINVAL);
819: if (end < addr)
820: return (EINVAL);
821:
822: /*
823: * Address of byte vector
824: */
825: vec = uap->vec;
826:
827: map = current_map();
828:
829: /*
830: * Do this on a map entry basis so that if the pages are not
831: * in the current processes address space, we can easily look
832: * up the pages elsewhere.
833: */
834: lastvecindex = -1;
835: for(addr; addr < end; addr += PAGE_SIZE) {
836: pqueryinfo = 0;
837: ret = vm_map_page_query(map, addr, &pqueryinfo, &numref);
838: if (ret != KERN_SUCCESS)
839: pqueryinfo = 0;
840: mincoreinfo = 0;
841: if (pqueryinfo & VM_PAGE_QUERY_PAGE_PRESENT)
842: mincoreinfo |= MINCORE_INCORE;
843: if (pqueryinfo & VM_PAGE_QUERY_PAGE_REF)
844: mincoreinfo |= MINCORE_REFERENCED;
845: if (pqueryinfo & VM_PAGE_QUERY_PAGE_DIRTY)
846: mincoreinfo |= MINCORE_MODIFIED;
847:
848:
849: /*
850: * calculate index into user supplied byte vector
851: */
852: vecindex = (addr - first_addr)>> PAGE_SHIFT;
853:
854: /*
855: * If we have skipped map entries, we need to make sure that
856: * the byte vector is zeroed for those skipped entries.
857: */
858: while((lastvecindex + 1) < vecindex) {
859: error = subyte( vec + lastvecindex, 0);
860: if (error) {
861: return (EFAULT);
862: }
863: ++lastvecindex;
864: }
865:
866: /*
867: * Pass the page information to the user
868: */
869: error = subyte( vec + vecindex, mincoreinfo);
870: if (error) {
871: return (EFAULT);
872: }
873: lastvecindex = vecindex;
874: }
875:
876:
877: /*
878: * Zero the last entries in the byte vector.
879: */
880: vecindex = (end - first_addr) >> PAGE_SHIFT;
881: while((lastvecindex + 1) < vecindex) {
882: error = subyte( vec + lastvecindex, 0);
883: if (error) {
884: return (EFAULT);
885: }
886: ++lastvecindex;
887: }
888:
889: return (0);
890: }
891:
892: struct mlock_args {
893: caddr_t addr;
894: size_t len;
895: };
896:
897: #define BSD_DUMMY_HOST 1
898:
899: int
900: mlock(p, uap, retval)
901: struct proc *p;
902: struct mlock_args *uap;
903: register_t *retval;
904: {
905: vm_map_t user_map;
906: vm_offset_t addr;
907: vm_size_t size, pageoff;
908: int error;
909: kern_return_t result;
910:
911: addr = (vm_offset_t) uap->addr;
912: size = uap->len;
913:
914: pageoff = (addr & PAGE_MASK);
915: addr -= pageoff;
916: size += pageoff;
917: size = (vm_size_t) round_page(size);
918:
919: /* disable wrap around */
920: if (addr + size < addr)
921: return (EINVAL);
922: #ifdef notyet
923: /* Hmm.. What am I going to do with this? */
924: if (atop(size) + cnt.v_wire_count > vm_page_max_wired)
925: return (EAGAIN);
926: #ifdef pmap_wired_count
927: if (size + ptoa(pmap_wired_count(vm_map_pmap(&p->p_vmspace->vm_map))) >
928: p->p_rlimit[RLIMIT_MEMLOCK].rlim_cur)
929: return (ENOMEM);
930: #else
931: error = suser(p->p_ucred, &p->p_acflag);
932: if (error)
933: return (error);
934: #endif
935: #endif /* notyet */
936:
937: user_map = current_map();
938:
939: /* vm_wire */
940: result = vm_wire(BSD_DUMMY_HOST, user_map, addr, size, VM_PROT_ALL);
941: return (result == KERN_SUCCESS ? 0 : ENOMEM);
942: }
943:
944: struct munlock_args {
945: caddr_t addr;
946: size_t len;
947: };
948: int
949: munlock(p, uap, retval)
950: struct proc *p;
951: struct munlock_args *uap;
952: register_t *retval;
953: {
954: vm_offset_t addr;
955: vm_size_t size, pageoff;
956: int error;
957: vm_map_t user_map;
958: kern_return_t result;
959:
960: addr = (vm_offset_t) uap->addr;
961: size = uap->len;
962:
963: pageoff = (addr & PAGE_MASK);
964: addr -= pageoff;
965: size += pageoff;
966: size = (vm_size_t) round_page(size);
967:
968: /* disable wrap around */
969: if (addr + size < addr)
970: return (EINVAL);
971:
972: #ifdef notyet
973: /* Hmm.. What am I going to do with this? */
974: #ifndef pmap_wired_count
975: error = suser(p->p_ucred, &p->p_acflag);
976: if (error)
977: return (error);
978: #endif
979: #endif /* notyet */
980:
981: user_map = current_map();
982:
983: /* vm_wire */
984: result = vm_wire(BSD_DUMMY_HOST, user_map, addr, size, VM_PROT_NONE);
985: return (result == KERN_SUCCESS ? 0 : ENOMEM);
986: }
987:
988:
989: struct mlockall_args {
990: int how;
991: };
992:
993: int
994: mlockall(p, uap)
995: struct proc *p;
996: struct mlockall_args *uap;
997: {
998: return 0;
999: }
1000:
1001: struct munlockall_args {
1002: int how;
1003: };
1004:
1005: int
1006: munlockall(p, uap)
1007: struct proc *p;
1008: struct munlockall_args *uap;
1009: {
1010: return 0;
1011: }
1012:
1013:
1014: /* BEGIN DEFUNCT */
1015: struct obreak_args {
1016: char *nsiz;
1017: };
1018: obreak(p, uap, retval)
1019: struct proc *p;
1020: struct obreak_args *uap;
1021: register_t *retval;
1022: {
1023: /* Not implemented, obsolete */
1024: return (ENOMEM);
1025: }
1026:
1027: int both;
1028:
1029: ovadvise()
1030: {
1031:
1032: #ifdef lint
1033: both = 0;
1034: #endif
1035: }
1036: /* END DEFUNCT */
1037: #if 1
1038: int print_map_addr=0;
1039: #endif /* 1 */
1040:
1041: kern_return_t map_fd(
1042: int fd,
1043: vm_offset_t offset,
1044: vm_offset_t *va,
1045: boolean_t findspace,
1046: vm_size_t size)
1047: {
1048: kern_return_t ret;
1049: boolean_t funnel_state;
1050:
1051: funnel_state = thread_set_funneled(TRUE);
1052:
1053: ret = map_fd_funneled( fd, offset, va, findspace, size);
1054:
1055: (void) thread_set_funneled(funnel_state);
1056:
1057: return ret;
1058: }
1059:
1060: kern_return_t map_fd_funneled(
1061: int fd,
1062: vm_offset_t offset,
1063: vm_offset_t *va,
1064: boolean_t findspace,
1065: vm_size_t size)
1066: {
1067: kern_return_t result;
1068: struct file *fp;
1069: struct vnode *vp;
1070: void * pager;
1071: vm_offset_t map_addr=0;
1072: vm_size_t map_size;
1073: vm_map_copy_t tmp;
1074: int err=0;
1075: vm_map_t my_map;
1076: struct proc *p =(struct proc *)(get_bsdtask_info(current_task()));
1077: #if 0
1078: extern int print_map_addr;
1079: #endif /* 0 */
1080:
1081: /*
1082: * Find the inode; verify that it's a regular file.
1083: */
1084:
1085: err = fdgetf(p, fd, &fp);
1086: if (err)
1087: return(err);
1088:
1089: if (fp->f_type != DTYPE_VNODE)
1090: return(KERN_INVALID_ARGUMENT);
1091: vp = (struct vnode *)fp->f_data;
1092:
1093: if (vp->v_type != VREG)
1094: return (KERN_INVALID_ARGUMENT);
1095:
1096: map_size = round_page(size);
1097:
1098: /*
1099: * Allow user to map in a zero length file.
1100: */
1101: if (size == 0)
1102: return (KERN_SUCCESS);
1103: /*
1104: * Map in the file.
1105: */
1106: if (!vp->v_vm_info) {
1107: vm_info_init(vp);
1108: }
1109:
1110: pager = (void *) vnode_pager_setup(vp, vp->v_vm_info->pager, FALSE, TRUE);
1111: if (pager == NULL)
1112: return (KERN_FAILURE);
1113:
1114:
1115: my_map = current_map();
1116:
1117: result = vm_map(
1118: my_map,
1119: &map_addr, map_size, (vm_offset_t)0, TRUE,
1120: pager, offset, TRUE,
1121: VM_PROT_DEFAULT, VM_PROT_ALL,
1122: VM_INHERIT_DEFAULT);
1123: if (result != KERN_SUCCESS)
1124: return (result);
1125:
1126:
1127: if (!findspace) {
1128: vm_offset_t dst_addr;
1129: vm_map_copy_t tmp;
1130:
1131: if (copyin(va, &dst_addr, sizeof (dst_addr)) ||
1132: trunc_page(dst_addr) != dst_addr) {
1133: (void) vm_map_remove(
1134: my_map,
1135: map_addr, map_addr + map_size,
1136: VM_MAP_NO_FLAGS);
1137: return (KERN_INVALID_ADDRESS);
1138: }
1139:
1140: result = vm_map_copyin(
1141: my_map,
1142: map_addr, map_size, TRUE,
1143: &tmp);
1144: if (result != KERN_SUCCESS) {
1145:
1146: (void) vm_map_remove(
1147: my_map,
1148: map_addr, map_addr + map_size,
1149: VM_MAP_NO_FLAGS);
1150: return (result);
1151: }
1152:
1153: result = vm_map_copy_overwrite(
1154: my_map,
1155: dst_addr, tmp, FALSE);
1156: if (result != KERN_SUCCESS) {
1157: vm_map_copy_discard(tmp);
1158: return (result);
1159: }
1160: }
1161: else {
1162: if (copyout(&map_addr, va, sizeof (map_addr))) {
1163: (void) vm_map_remove(
1164: my_map,
1165: map_addr, map_addr + map_size,
1166: VM_MAP_NO_FLAGS);
1167: return (KERN_INVALID_ADDRESS);
1168: }
1169: }
1170: if (ISMAPPABLEFILE(vp))
1171: vp->v_vm_info->mapped = 1;
1172:
1173: /*
1174: * Set credentials.
1175: */
1176: if (vp->v_vm_info->cred == NULL) {
1177: crhold(current_proc()->p_ucred);
1178: vp->v_vm_info->cred = current_proc()->p_ucred;
1179: }
1180:
1181: return (KERN_SUCCESS);
1182: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.