summaryrefslogtreecommitdiffstats
path: root/sys/vm
diff options
context:
space:
mode:
authorjhb <jhb@FreeBSD.org>2005-04-01 20:00:11 +0000
committerjhb <jhb@FreeBSD.org>2005-04-01 20:00:11 +0000
commita3c6b782c3ed4abd939e54896eed4b89f4d18d21 (patch)
treec33b91d98e8867bbb1f42b28ab23638d2003f368 /sys/vm
parent9683bbdf3f053a2b65d3ac11aac7a2eec86c559b (diff)
downloadFreeBSD-src-a3c6b782c3ed4abd939e54896eed4b89f4d18d21.zip
FreeBSD-src-a3c6b782c3ed4abd939e54896eed4b89f4d18d21.tar.gz
- Change the vm_mmap() function to accept an objtype_t parameter specifying
the type of object represented by the handle argument. - Allow vm_mmap() to map device memory via cdev objects in addition to vnodes and anonymous memory. Note that mmaping a cdev directly does not currently perform any MAC checks like mapping a vnode does. - Unbreak the DRM getbufs ioctl by having it call vm_mmap() directly on the cdev the ioctl is acting on rather than trying to find a suitable vnode to map from. Reviewed by: alc, arch@
Diffstat (limited to 'sys/vm')
-rw-r--r--sys/vm/vm.h4
-rw-r--r--sys/vm/vm_extern.h2
-rw-r--r--sys/vm/vm_mmap.c77
-rw-r--r--sys/vm/vm_object.h4
4 files changed, 77 insertions, 10 deletions
diff --git a/sys/vm/vm.h b/sys/vm/vm.h
index e61b726..102a934 100644
--- a/sys/vm/vm.h
+++ b/sys/vm/vm.h
@@ -80,6 +80,10 @@ typedef u_char vm_prot_t; /* protection codes */
#define VM_PROT_RW (VM_PROT_READ|VM_PROT_WRITE)
#define VM_PROT_DEFAULT VM_PROT_ALL
+enum obj_type { OBJT_DEFAULT, OBJT_SWAP, OBJT_VNODE, OBJT_DEVICE, OBJT_PHYS,
+ OBJT_DEAD };
+typedef u_char objtype_t;
+
union vm_map_object;
typedef union vm_map_object vm_map_object_t;
diff --git a/sys/vm/vm_extern.h b/sys/vm/vm_extern.h
index 45cc97e..4fc8275 100644
--- a/sys/vm/vm_extern.h
+++ b/sys/vm/vm_extern.h
@@ -72,7 +72,7 @@ void vm_fault_unwire(vm_map_t, vm_offset_t, vm_offset_t, boolean_t);
int vm_fault_wire(vm_map_t, vm_offset_t, vm_offset_t, boolean_t, boolean_t);
void vm_forkproc(struct thread *, struct proc *, struct thread *, int);
void vm_waitproc(struct proc *);
-int vm_mmap(vm_map_t, vm_offset_t *, vm_size_t, vm_prot_t, vm_prot_t, int, void *, vm_ooffset_t);
+int vm_mmap(vm_map_t, vm_offset_t *, vm_size_t, vm_prot_t, vm_prot_t, int, objtype_t, void *, vm_ooffset_t);
void vm_set_page_size(void);
struct vmspace *vmspace_alloc(vm_offset_t, vm_offset_t);
struct vmspace *vmspace_fork(struct vmspace *);
diff --git a/sys/vm/vm_mmap.c b/sys/vm/vm_mmap.c
index ca24b98..dc653cf 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;
diff --git a/sys/vm/vm_object.h b/sys/vm/vm_object.h
index 794c6cf..df3bddd 100644
--- a/sys/vm/vm_object.h
+++ b/sys/vm/vm_object.h
@@ -71,10 +71,6 @@
#include <sys/_lock.h>
#include <sys/_mutex.h>
-enum obj_type { OBJT_DEFAULT, OBJT_SWAP, OBJT_VNODE, OBJT_DEVICE, OBJT_PHYS,
- OBJT_DEAD };
-typedef u_char objtype_t;
-
/*
* Types defined:
*
OpenPOWER on IntegriCloud