summaryrefslogtreecommitdiff
path: root/sys/vm/vm_mmap.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/vm/vm_mmap.c')
-rw-r--r--sys/vm/vm_mmap.c77
1 files changed, 72 insertions, 5 deletions
diff --git a/sys/vm/vm_mmap.c b/sys/vm/vm_mmap.c
index ca24b98ba8b9..dc653cf2295e 100644
--- a/sys/vm/vm_mmap.c
+++ b/sys/vm/vm_mmap.c
@@ -109,6 +109,8 @@ vmmapentry_rsrc_init(dummy)
static int vm_mmap_vnode(struct thread *, vm_size_t, vm_prot_t, vm_prot_t *,
int *, struct vnode *, vm_ooffset_t, vm_object_t *);
+static int vm_mmap_cdev(struct thread *, vm_size_t, vm_prot_t, vm_prot_t *,
+ int *, struct cdev *, vm_ooffset_t, vm_object_t *);
/*
* MPSAFE
@@ -205,6 +207,7 @@ mmap(td, uap)
vm_size_t size, pageoff;
vm_prot_t prot, maxprot;
void *handle;
+ objtype_t handle_type;
int flags, error;
off_t pos;
struct vmspace *vms = td->td_proc->p_vmspace;
@@ -282,6 +285,7 @@ mmap(td, uap)
* Mapping blank space is trivial.
*/
handle = NULL;
+ handle_type = OBJT_DEFAULT;
maxprot = VM_PROT_ALL;
pos = 0;
} else {
@@ -344,6 +348,7 @@ mmap(td, uap)
maxprot |= VM_PROT_WRITE;
}
handle = (void *)vp;
+ handle_type = OBJT_VNODE;
}
/*
@@ -358,7 +363,7 @@ mmap(td, uap)
}
error = vm_mmap(&vms->vm_map, &addr, size, prot, maxprot,
- flags, handle, pos);
+ flags, handle_type, handle, pos);
if (error == 0)
td->td_retval[0] = (register_t) (addr + pageoff);
done:
@@ -1166,6 +1171,55 @@ done:
}
/*
+ * vm_mmap_cdev()
+ *
+ * MPSAFE
+ *
+ * Helper function for vm_mmap. Perform sanity check specific for mmap
+ * operations on cdevs.
+ */
+int
+vm_mmap_cdev(struct thread *td, vm_size_t objsize,
+ vm_prot_t prot, vm_prot_t *maxprotp, int *flagsp,
+ struct cdev *cdev, vm_ooffset_t foff, vm_object_t *objp)
+{
+ vm_object_t obj;
+ int flags;
+
+ flags = *flagsp;
+
+ /* XXX: lack thredref on device */
+ if (cdev->si_devsw->d_flags & D_MMAP_ANON) {
+ *maxprotp = VM_PROT_ALL;
+ *flagsp |= MAP_ANON;
+ return (0);
+ }
+ /*
+ * cdevs does not provide private mappings of any kind.
+ */
+ if ((*maxprotp & VM_PROT_WRITE) == 0 &&
+ (prot & PROT_WRITE) != 0)
+ return (EACCES);
+ if (flags & (MAP_PRIVATE|MAP_COPY))
+ return (EINVAL);
+ /*
+ * Force device mappings to be shared.
+ */
+ flags |= MAP_SHARED;
+#ifdef MAC_XXX
+ error = mac_check_cdev_mmap(td->td_ucred, cdev, prot);
+ if (error != 0)
+ return (error);
+#endif
+ obj = vm_pager_allocate(OBJT_DEVICE, cdev, objsize, prot, foff);
+ if (obj == NULL)
+ return (EINVAL);
+ *objp = obj;
+ *flagsp = flags;
+ return (0);
+}
+
+/*
* vm_mmap()
*
* MPSAFE
@@ -1176,7 +1230,7 @@ done:
int
vm_mmap(vm_map_t map, vm_offset_t *addr, vm_size_t size, vm_prot_t prot,
vm_prot_t maxprot, int flags,
- void *handle,
+ objtype_t handle_type, void *handle,
vm_ooffset_t foff)
{
boolean_t fitit;
@@ -1222,13 +1276,26 @@ vm_mmap(vm_map_t map, vm_offset_t *addr, vm_size_t size, vm_prot_t prot,
/*
* Lookup/allocate object.
*/
- if (handle != NULL) {
+ switch (handle_type) {
+ case OBJT_DEVICE:
+ error = vm_mmap_cdev(td, size, prot, &maxprot, &flags,
+ handle, foff, &object);
+ break;
+ case OBJT_VNODE:
error = vm_mmap_vnode(td, size, prot, &maxprot, &flags,
handle, foff, &object);
- if (error) {
- return (error);
+ break;
+ case OBJT_DEFAULT:
+ if (handle == NULL) {
+ error = 0;
+ break;
}
+ /* FALLTHROUGH */
+ default:
+ error = EINVAL;
}
+ if (error)
+ return (error);
if (flags & MAP_ANON) {
object = NULL;
docow = 0;