]> git.saurik.com Git - apple/xnu.git/blobdiff - bsd/kern/kern_mman.c
xnu-517.3.7.tar.gz
[apple/xnu.git] / bsd / kern / kern_mman.c
index 3fd5b0650c524912f8401f9ef3f45baed68e5389..0c02c2f7e29c31361c4e384770dbbb215231f421 100644 (file)
@@ -1,21 +1,24 @@
 /*
- * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
+ * Copyright (c) 2000-2002 Apple Computer, Inc. All rights reserved.
  *
  * @APPLE_LICENSE_HEADER_START@
  * 
- * The contents of this file constitute Original Code as defined in and
- * are subject to the Apple Public Source License Version 1.1 (the
- * "License").  You may not use this file except in compliance with the
- * License.  Please obtain a copy of the License at
- * http://www.apple.com/publicsource and read it before using this file.
+ * Copyright (c) 1999-2003 Apple Computer, Inc.  All Rights Reserved.
  * 
- * This Original Code and all software distributed under the License are
- * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * This file contains Original Code and/or Modifications of Original Code
+ * as defined in and that are subject to the Apple Public Source License
+ * Version 2.0 (the 'License'). You may not use this file except in
+ * compliance with the License. Please obtain a copy of the License at
+ * http://www.opensource.apple.com/apsl/ and read it before using this
+ * file.
+ * 
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
- * License for the specific language governing rights and limitations
- * under the License.
+ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+ * Please see the License for the specific language governing rights and
+ * limitations under the License.
  * 
  * @APPLE_LICENSE_HEADER_END@
  */
@@ -148,6 +151,7 @@ struct osmmap_args {
                long    pos;
 };
 
+int
 osmmap(curp, uap, retval)
        struct proc *curp;
        register struct osmmap_args *uap;
@@ -243,7 +247,7 @@ mmap(p, uap, retval)
 
        /* Adjust size for rounding (on both ends). */
        user_size += pageoff;                   /* low end... */
-       user_size = (vm_size_t) round_page(user_size);  /* hi end */
+       user_size = (vm_size_t) round_page_32(user_size);       /* hi end */
 
 
        /*
@@ -277,8 +281,8 @@ mmap(p, uap, retval)
         * There should really be a pmap call to determine a reasonable
         * location.
         */
-       else if (addr < round_page(p->p_vmspace->vm_daddr + MAXDSIZ))
-               addr = round_page(p->p_vmspace->vm_daddr + MAXDSIZ);
+       else if (addr < round_page_32(p->p_vmspace->vm_daddr + MAXDSIZ))
+               addr = round_page_32(p->p_vmspace->vm_daddr + MAXDSIZ);
 
 #endif
 
@@ -300,7 +304,7 @@ mmap(p, uap, retval)
                if (err)
                        return(err);
                if(fp->f_type == DTYPE_PSXSHM) {
-                       uap->addr = user_addr;
+                       uap->addr = (caddr_t)user_addr;
                        uap->len = user_size;
                        uap->prot = prot;
                        uap->flags = flags;
@@ -319,7 +323,7 @@ mmap(p, uap, retval)
                 * SunOS).
                 */
                if (vp->v_type == VCHR || vp->v_type == VSTR) {
-                       return(EOPNOTSUPP);
+                       return(ENODEV);
                } else {
                        /*
                         * Ensure that file and memory protections are
@@ -371,7 +375,7 @@ mmap(p, uap, retval)
         *      We bend a little - round the start and end addresses
         *      to the nearest page boundary.
         */
-       user_size = round_page(user_size);
+       user_size = round_page_32(user_size);
 
        if (file_pos & PAGE_MASK_64)
                return (EINVAL);
@@ -380,9 +384,9 @@ mmap(p, uap, retval)
 
        if ((flags & MAP_FIXED) == 0) {
                find_space = TRUE;
-               user_addr = round_page(user_addr); 
+               user_addr = round_page_32(user_addr); 
        } else {
-               if (user_addr != trunc_page(user_addr))
+               if (user_addr != trunc_page_32(user_addr))
                        return (EINVAL);
                find_space = FALSE;
                (void) vm_deallocate(user_map, user_addr, user_size);
@@ -416,9 +420,16 @@ mmap(p, uap, retval)
                if (result != KERN_SUCCESS) 
                                goto out;
                
+               result = vm_protect(user_map, user_addr, user_size, TRUE, maxprot);
+               if (result != KERN_SUCCESS) 
+                               goto out;
+               result = vm_protect(user_map, user_addr, user_size, FALSE, prot);
+               if (result != KERN_SUCCESS) 
+                               goto out;
+
        } else {
                UBCINFOCHECK("mmap", vp);
-               pager = ubc_getpager(vp);
+               pager = (vm_pager_t)ubc_getpager(vp);
                
                if (pager == NULL)
                        return (ENOMEM);
@@ -458,7 +469,7 @@ mmap(p, uap, retval)
                ubc_map(vp);
        }
 
-       if (flags & (MAP_SHARED|MAP_INHERIT)) {
+       if (flags & MAP_SHARED) {
                result = vm_inherit(user_map, user_addr, user_size,
                                VM_INHERIT_SHARE);
                if (result != KERN_SUCCESS) {
@@ -507,7 +518,7 @@ msync(p, uap, retval)
        pageoff = (addr & PAGE_MASK);
        addr -= pageoff;
        size = uap->len;
-       size = (vm_size_t) round_page(size);
+       size = (vm_size_t) round_page_32(size);
        flags = uap->flags;
 
        if (addr + size < addr)
@@ -515,6 +526,9 @@ msync(p, uap, retval)
 
        user_map = current_map();
 
+       if ((flags & (MS_ASYNC|MS_SYNC)) == (MS_ASYNC|MS_SYNC))
+               return (EINVAL);
+
        if ((flags & (MS_ASYNC|MS_INVALIDATE)) == (MS_ASYNC|MS_INVALIDATE))
                return (EINVAL);
 
@@ -526,7 +540,7 @@ msync(p, uap, retval)
                 * inaccurate results, lets just return error as invalid size
                 * specified
                 */
-               return(EINVAL);
+               return (EINVAL); /* XXX breaks posix apps */
        }
 
        if (flags & MS_KILLPAGES)
@@ -556,10 +570,10 @@ msync(p, uap, retval)
        }
 
        return (0);
-
 }
 
 
+int
 mremap()
 {
        /* Not yet implemented */
@@ -570,6 +584,7 @@ struct munmap_args {
                caddr_t addr;
                int     len;
 };
+int
 munmap(p, uap, retval)
        struct proc *p;
        struct munmap_args *uap;
@@ -587,7 +602,7 @@ munmap(p, uap, retval)
 
        user_addr -= pageoff;
        user_size += pageoff;
-       user_size = round_page(user_size);
+       user_size = round_page_32(user_size);
        if (user_addr + user_size < user_addr)
                return(EINVAL);
 
@@ -651,7 +666,7 @@ mprotect(p, uap, retval)
        pageoff = (user_addr & PAGE_MASK);
        user_addr -= pageoff;
        user_size += pageoff;
-       user_size = round_page(user_size);
+       user_size = round_page_32(user_size);
        if (user_addr + user_size < user_addr)
                return(EINVAL);
 
@@ -694,7 +709,7 @@ minherit(p, uap, retval)
        pageoff = (addr & PAGE_MASK);
        addr -= pageoff;
        size += pageoff;
-       size = (vm_size_t) round_page(size);
+       size = (vm_size_t) round_page_32(size);
        if (addr + size < addr)
                return(EINVAL);
 
@@ -733,33 +748,43 @@ madvise(p, uap, retval)
         */
        if (VM_MAX_ADDRESS > 0 &&
                ((vm_offset_t) uap->addr + uap->len) > VM_MAX_ADDRESS)
-               return (EINVAL);
+               return (ENOMEM);
        if (VM_MIN_ADDRESS > 0 && uap->addr < VM_MIN_ADDRESS)
-               return (EINVAL);
+               return (ENOMEM);
 
        if (((vm_offset_t) uap->addr + uap->len) < (vm_offset_t) uap->addr)
-               return (EINVAL);
+               return (ENOMEM);
 
        /*
         * Since this routine is only advisory, we default to conservative
         * behavior.
         */
-       start = trunc_page((vm_offset_t) uap->addr);
-       end = round_page((vm_offset_t) uap->addr + uap->len);
+       start = trunc_page_32((vm_offset_t) uap->addr);
+       end = round_page_32((vm_offset_t) uap->addr + uap->len);
        
        user_map = current_map();
 
        switch (uap->behav) {
                case MADV_RANDOM:
                        new_behavior = VM_BEHAVIOR_RANDOM;
+                       break;
                case MADV_SEQUENTIAL: 
                        new_behavior = VM_BEHAVIOR_SEQUENTIAL;
+                       break;
                case MADV_NORMAL:
-               default:
                        new_behavior = VM_BEHAVIOR_DEFAULT;
+                       break;
+               case MADV_WILLNEED:
+                       new_behavior = VM_BEHAVIOR_WILLNEED;
+                       break;
+               case MADV_DONTNEED:
+                       new_behavior = VM_BEHAVIOR_DONTNEED;
+                       break;
+               default:
+                       return(EINVAL);
        }
 
-       result = vm_behavior_set(user_map, start, end, uap->behav);
+       result = vm_behavior_set(user_map, start, end, new_behavior);
        switch (result) {
                case KERN_SUCCESS:
                        return (0);
@@ -799,8 +824,8 @@ mincore(p, uap, retval)
         * Make sure that the addresses presented are valid for user
         * mode.
         */
-       first_addr = addr = trunc_page((vm_offset_t) uap->addr);
-       end = addr + (vm_size_t)round_page(uap->len);
+       first_addr = addr = trunc_page_32((vm_offset_t) uap->addr);
+       end = addr + (vm_size_t)round_page_32(uap->len);
 
        if (VM_MAX_ADDRESS > 0 && end > VM_MAX_ADDRESS)
                return (EINVAL);
@@ -900,7 +925,7 @@ mlock(p, uap, retval)
        pageoff = (addr & PAGE_MASK);
        addr -= pageoff;
        size += pageoff;
-       size = (vm_size_t) round_page(size);
+       size = (vm_size_t) round_page_32(size);
 
        /* disable wrap around */
        if (addr + size < addr)
@@ -923,7 +948,7 @@ mlock(p, uap, retval)
        user_map = current_map();
 
        /* vm_wire */
-       result = vm_wire(host_priv_self(), user_map, addr, size, VM_PROT_ALL);
+       result = vm_map_wire(user_map, addr, (vm_offset_t)(addr+size), VM_PROT_NONE, TRUE);
        return (result == KERN_SUCCESS ? 0 : ENOMEM);
 }
 
@@ -949,7 +974,7 @@ munlock(p, uap, retval)
        pageoff = (addr & PAGE_MASK);
        addr -= pageoff;
        size += pageoff;
-       size = (vm_size_t) round_page(size);
+       size = (vm_size_t) round_page_32(size);
 
        /* disable wrap around */
        if (addr + size < addr)
@@ -1001,6 +1026,7 @@ munlockall(p, uap)
 struct obreak_args {
        char *nsiz;
 };
+int
 obreak(p, uap, retval)
        struct proc *p;
        struct obreak_args *uap;
@@ -1012,6 +1038,7 @@ obreak(p, uap, retval)
 
 int    both;
 
+int
 ovadvise()
 {
 
@@ -1020,12 +1047,11 @@ ovadvise()
 #endif
 }
 /* END DEFUNCT */
-#if 1
-int print_map_addr=0;
-#endif /* 1 */
 
 /* CDY need to fix interface to allow user to map above 32 bits */
-kern_return_t map_fd(
+/* USV: No! need to obsolete map_fd()! mmap() already supports 64 bits */
+kern_return_t
+map_fd(
        int             fd,
        vm_offset_t     offset,
        vm_offset_t     *va,
@@ -1045,7 +1071,8 @@ kern_return_t map_fd(
        return ret;
 }
 
-kern_return_t map_fd_funneled(
+kern_return_t
+map_fd_funneled(
        int                     fd,
        vm_object_offset_t      offset,
        vm_offset_t             *va,
@@ -1061,10 +1088,7 @@ kern_return_t map_fd_funneled(
        vm_map_copy_t   tmp;
        int             err=0;
        vm_map_t        my_map;
-       struct proc     *p =(struct proc *)(get_bsdtask_info(current_task()));
-#if 0
-       extern int print_map_addr;
-#endif /* 0 */
+       struct proc     *p =(struct proc *)current_proc();
 
        /*
         *      Find the inode; verify that it's a regular file.
@@ -1076,16 +1100,20 @@ kern_return_t map_fd_funneled(
        
        if (fp->f_type != DTYPE_VNODE)
                return(KERN_INVALID_ARGUMENT);
+
+       if (!(fp->f_flag & FREAD))
+               return (KERN_PROTECTION_FAILURE);
+
        vp = (struct vnode *)fp->f_data;
 
        if (vp->v_type != VREG)
                return (KERN_INVALID_ARGUMENT);
 
        if (offset & PAGE_MASK_64) {
-               printf("map_fd: file offset not page aligned(%d : %s\)n",p->p_pid, p->p_comm);
+               printf("map_fd: file offset not page aligned(%d : %s)\n",p->p_pid, p->p_comm);
                return (KERN_INVALID_ARGUMENT);
        }
-       map_size = round_page(size);
+       map_size = round_page_32(size);
 
        /*
         * Allow user to map in a zero length file.
@@ -1118,7 +1146,7 @@ kern_return_t map_fd_funneled(
                vm_map_copy_t   tmp;
 
                if (copyin(va, &dst_addr, sizeof (dst_addr))    ||
-                                       trunc_page(dst_addr) != dst_addr) {
+                                       trunc_page_32(dst_addr) != dst_addr) {
                        (void) vm_map_remove(
                                        my_map,
                                        map_addr, map_addr + map_size,