This commit was generated by cvs2svn to track changes on a CVS vendor
[unix-history] / sys / vm / vm_mmap.c
index 4eeac45..8a8e1ae 100644 (file)
@@ -37,7 +37,7 @@
  *
  *     from: Utah $Hdr: vm_mmap.c 1.3 90/01/21$
  *     from: @(#)vm_mmap.c     7.5 (Berkeley) 6/28/91
  *
  *     from: Utah $Hdr: vm_mmap.c 1.3 90/01/21$
  *     from: @(#)vm_mmap.c     7.5 (Berkeley) 6/28/91
- *     $Id: vm_mmap.c,v 1.12 1993/11/29 14:30:24 davidg Exp $
+ *     $Id: vm_mmap.c,v 1.20 1994/01/14 16:27:22 davidg Exp $
  */
 
 /*
  */
 
 /*
 #include "vm_pager.h"
 #include "vm_prot.h"
 #include "vm_statistics.h"
 #include "vm_pager.h"
 #include "vm_prot.h"
 #include "vm_statistics.h"
+#include "vm_user.h"
+
+static boolean_t vm_map_is_allocated(vm_map_t, vm_offset_t, vm_offset_t,
+                                    boolean_t);
 
 #ifdef DEBUG
 int mmapdebug = 0;
 
 #ifdef DEBUG
 int mmapdebug = 0;
@@ -142,6 +146,7 @@ smmap(p, uap, retval)
                       p->p_pid, uap->addr, uap->len, uap->prot,
                       uap->flags, uap->fd, uap->pos);
 #endif
                       p->p_pid, uap->addr, uap->len, uap->prot,
                       uap->flags, uap->fd, uap->pos);
 #endif
+
        /*
         * Make sure one of the sharing types is specified
         */
        /*
         * Make sure one of the sharing types is specified
         */
@@ -153,18 +158,16 @@ smmap(p, uap, retval)
        default:
                return(EINVAL);
        }
        default:
                return(EINVAL);
        }
+
        /*
         * Address (if FIXED) must be page aligned.
         * Size is implicitly rounded to a page boundary.
         */
        addr = (vm_offset_t) uap->addr;
        /*
         * Address (if FIXED) must be page aligned.
         * Size is implicitly rounded to a page boundary.
         */
        addr = (vm_offset_t) uap->addr;
-       if ((flags & MAP_FIXED) && (addr & page_mask) || uap->len < 0)
+       if ((flags & MAP_FIXED) && (addr & PAGE_MASK) || uap->len < 0)
                return(EINVAL);
        size = (vm_size_t) round_page(uap->len);
                return(EINVAL);
        size = (vm_size_t) round_page(uap->len);
-       if (addr + size >= VM_MAXUSER_ADDRESS)
-               return(EINVAL);
-       if ((size != 0) && (addr >= addr + size))
-               return(EINVAL);
+
        /*
         * XXX if no hint provided for a non-fixed mapping place it after
         * the end of the largest possible heap.
        /*
         * XXX if no hint provided for a non-fixed mapping place it after
         * the end of the largest possible heap.
@@ -174,6 +177,15 @@ smmap(p, uap, retval)
         */
        if (addr == 0 && (flags & MAP_FIXED) == 0)
                addr = round_page(p->p_vmspace->vm_daddr + MAXDSIZ);
         */
        if (addr == 0 && (flags & MAP_FIXED) == 0)
                addr = round_page(p->p_vmspace->vm_daddr + MAXDSIZ);
+
+       /*
+        * Check address range for validity
+        */
+       if (addr + size >= VM_MAXUSER_ADDRESS)
+               return(EINVAL);
+       if (addr > addr + size)
+               return(EINVAL);
+
        /*
         * Mapping file or named anonymous, get fp for validation
         */
        /*
         * Mapping file or named anonymous, get fp for validation
         */
@@ -182,6 +194,23 @@ smmap(p, uap, retval)
                    (fp = fdp->fd_ofiles[uap->fd]) == NULL)
                        return(EBADF);
        }
                    (fp = fdp->fd_ofiles[uap->fd]) == NULL)
                        return(EBADF);
        }
+
+       /*
+        * Set initial maximum protection
+        */
+       maxprot = VM_PROT_ALL;
+
+       /*
+        * Map protections to MACH style
+        */
+       prot = VM_PROT_NONE;
+       if (uap->prot & PROT_READ)
+               prot |= VM_PROT_READ;
+       if (uap->prot & PROT_WRITE)
+               prot |= VM_PROT_WRITE;
+       if (uap->prot & PROT_EXEC)
+               prot |= VM_PROT_EXECUTE;
+
        /*
         * If we are mapping a file we need to check various
         * file/vnode related things.
        /*
         * If we are mapping a file we need to check various
         * file/vnode related things.
@@ -195,45 +224,36 @@ smmap(p, uap, retval)
                vp = (struct vnode *)fp->f_data;
                if (vp->v_type != VREG && vp->v_type != VCHR)
                        return(EINVAL);
                vp = (struct vnode *)fp->f_data;
                if (vp->v_type != VREG && vp->v_type != VCHR)
                        return(EINVAL);
+
                /*
                /*
-                * Ensure that file protection and desired protection
-                * are compatible.  Note that we only worry about writability
-                * if mapping is shared.
-                */
-               if ((uap->prot & PROT_READ) && (fp->f_flag & FREAD) == 0 ||
-                   ((flags & MAP_SHARED) &&
-                    (uap->prot & PROT_WRITE) && (fp->f_flag & FWRITE) == 0))
-                       return(EACCES);
-               handle = (caddr_t)vp;
-               /*
-                * PATCH GVR 25-03-93
-                * Map protections to MACH style
+                * Set maxprot according to file protection.
+                * If the file is the backing store, enable maxprot write
+                *      if the file protection allows. If the file isn't
+                *      the backing store, enable writes.
                 */
                 */
-               if(uap->flags & MAP_SHARED) {
-                       maxprot = VM_PROT_EXECUTE;
-                       if (fp->f_flag & FREAD)
-                               maxprot |= VM_PROT_READ;
+               maxprot = VM_PROT_NONE;
+               if (fp->f_flag & FREAD)
+                       maxprot |= VM_PROT_READ|VM_PROT_EXECUTE;
+               if (uap->flags & MAP_SHARED) {
                        if (fp->f_flag & FWRITE)
                                maxprot |= VM_PROT_WRITE;
                        if (fp->f_flag & FWRITE)
                                maxprot |= VM_PROT_WRITE;
-               } else
-                       maxprot = VM_PROT_ALL;
+               } else {
+                       maxprot |= VM_PROT_WRITE;
+               }
+
+               /*
+                * Ensure that calculated maximum protection and desired
+                * protection are compatible.
+                */
+               if ((maxprot & prot) != prot)
+                       return(EACCES);
+
+               handle = (caddr_t)vp;
        } else if (uap->fd != -1) {
        } else if (uap->fd != -1) {
-               maxprot = VM_PROT_ALL;
                handle = (caddr_t)fp;
        } else {
                handle = (caddr_t)fp;
        } else {
-               maxprot = VM_PROT_ALL;
                handle = NULL;
        }
                handle = NULL;
        }
-       /*
-        * Map protections to MACH style
-        */
-       prot = VM_PROT_NONE;
-       if (uap->prot & PROT_READ)
-               prot |= VM_PROT_READ;
-       if (uap->prot & PROT_WRITE)
-               prot |= VM_PROT_WRITE;
-       if (uap->prot & PROT_EXEC)
-               prot |= VM_PROT_EXECUTE;
 
        error = vm_mmap(&p->p_vmspace->vm_map, &addr, size, prot, maxprot,
                        flags, handle, (vm_offset_t)uap->pos);
 
        error = vm_mmap(&p->p_vmspace->vm_map, &addr, size, prot, maxprot,
                        flags, handle, (vm_offset_t)uap->pos);
@@ -266,7 +286,7 @@ msync(p, uap, retval)
                printf("msync(%d): addr %x len %x\n",
                       p->p_pid, uap->addr, uap->len);
 #endif
                printf("msync(%d): addr %x len %x\n",
                       p->p_pid, uap->addr, uap->len);
 #endif
-       if (((int)uap->addr & page_mask) || uap->len < 0)
+       if (((int)uap->addr & PAGE_MASK) || uap->len < 0)
                return(EINVAL);
        addr = oaddr = (vm_offset_t)uap->addr;
        osize = (vm_size_t)uap->len;
                return(EINVAL);
        addr = oaddr = (vm_offset_t)uap->addr;
        osize = (vm_size_t)uap->len;
@@ -338,7 +358,7 @@ munmap(p, uap, retval)
 #endif
 
        addr = (vm_offset_t) uap->addr;
 #endif
 
        addr = (vm_offset_t) uap->addr;
-       if ((addr & page_mask) || uap->len < 0)
+       if ((addr & PAGE_MASK) || uap->len < 0)
                return(EINVAL);
        size = (vm_size_t) round_page(uap->len);
        if (size == 0)
                return(EINVAL);
        size = (vm_size_t) round_page(uap->len);
        if (size == 0)
@@ -395,7 +415,7 @@ mprotect(p, uap, retval)
 #endif
 
        addr = (vm_offset_t) uap->addr;
 #endif
 
        addr = (vm_offset_t) uap->addr;
-       if ((addr & page_mask) || uap->len < 0)
+       if ((addr & PAGE_MASK) || uap->len < 0)
                return(EINVAL);
        size = (vm_size_t) uap->len;
        /*
                return(EINVAL);
        size = (vm_size_t) uap->len;
        /*
@@ -501,11 +521,8 @@ vm_mmap(map, addr, size, prot, maxprot, flags, handle, foff)
        else {
                vp = (struct vnode *)handle;
                if (vp->v_type == VCHR) {
        else {
                vp = (struct vnode *)handle;
                if (vp->v_type == VCHR) {
-                       unsigned long kludge;
-
                        type = PG_DEVICE;
                        type = PG_DEVICE;
-                       kludge = (u_long)vp->v_rdev;
-                       handle = kludge;
+                       handle = (caddr_t)(u_long)vp->v_rdev;
                } else
                        type = PG_VNODE;
        }
                } else
                        type = PG_VNODE;
        }
@@ -531,13 +548,6 @@ vm_mmap(map, addr, size, prot, maxprot, flags, handle, foff)
                                vm_object_deallocate(object);
                        goto out;
                }
                                vm_object_deallocate(object);
                        goto out;
                }
-               /*
-                * The object of unnamed anonymous regions was just created
-                * find it for pager_cache.
-                */
-               if (handle == NULL)
-                       object = vm_object_lookup(pager);
-
                /*
                 * Don't cache anonymous objects.
                 * Loses the reference gained by vm_pager_allocate.
                /*
                 * Don't cache anonymous objects.
                 * Loses the reference gained by vm_pager_allocate.
@@ -695,17 +705,25 @@ vm_mmap(map, addr, size, prot, maxprot, flags, handle, foff)
         * Changed again: indeed set maximum protection based on
         * object permissions.
         */
         * Changed again: indeed set maximum protection based on
         * object permissions.
         */
-               rv = vm_map_protect(map, *addr, *addr+size, prot, FALSE);
+       /*
+        * We only need to set max_protection in case it's
+        * unequal to its default, which is VM_PROT_DEFAULT.
+        */
+       if (maxprot != VM_PROT_DEFAULT) {
+               rv = vm_map_protect(map, *addr, *addr+size, maxprot, TRUE);
                if (rv != KERN_SUCCESS) {
                        (void) vm_deallocate(map, *addr, size);
                        goto out;
                }
                if (rv != KERN_SUCCESS) {
                        (void) vm_deallocate(map, *addr, size);
                        goto out;
                }
+       }
        /*
        /*
-        * We only need to set max_protection in case it's
-        * unequal to its default, which is VM_PROT_DEFAULT.
+        * We only need to set the protection if it is unequal
+        * to the maximum (if it is equal to maxprot, and isn't
+        * the default, then it would have been set above when
+        * maximum prot was set.
         */
         */
-       if(maxprot != VM_PROT_DEFAULT) {
-               rv = vm_map_protect(map, *addr, *addr+size, maxprot, TRUE);
+       if (prot != maxprot) {
+               rv = vm_map_protect(map, *addr, *addr+size, prot, FALSE);
                if (rv != KERN_SUCCESS) {
                        (void) vm_deallocate(map, *addr, size);
                        goto out;
                if (rv != KERN_SUCCESS) {
                        (void) vm_deallocate(map, *addr, size);
                        goto out;
@@ -848,7 +866,8 @@ vm_allocate_with_pager(map, addr, size, fitit, pager, poffset, internal)
        vm_stat.lookups++;
        if (object == NULL) {
                object = vm_object_allocate(size);
        vm_stat.lookups++;
        if (object == NULL) {
                object = vm_object_allocate(size);
-               vm_object_enter(object, pager);
+               if (!internal)
+                       vm_object_enter(object, pager);
        } else
                vm_stat.hits++;
        object->internal = internal;
        } else
                vm_stat.hits++;
        object->internal = internal;
@@ -870,7 +889,7 @@ vm_allocate_with_pager(map, addr, size, fitit, pager, poffset, internal)
  *
  * start and end should be page aligned.
  */
  *
  * start and end should be page aligned.
  */
-boolean_t
+static boolean_t
 vm_map_is_allocated(map, start, end, single_entry)
        vm_map_t map;
        vm_offset_t start, end;
 vm_map_is_allocated(map, start, end, single_entry)
        vm_map_t map;
        vm_offset_t start, end;