diff options
author | jhb <jhb@FreeBSD.org> | 2005-04-01 20:00:11 +0000 |
---|---|---|
committer | jhb <jhb@FreeBSD.org> | 2005-04-01 20:00:11 +0000 |
commit | a3c6b782c3ed4abd939e54896eed4b89f4d18d21 (patch) | |
tree | c33b91d98e8867bbb1f42b28ab23638d2003f368 /sys/vm | |
parent | 9683bbdf3f053a2b65d3ac11aac7a2eec86c559b (diff) | |
download | FreeBSD-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.h | 4 | ||||
-rw-r--r-- | sys/vm/vm_extern.h | 2 | ||||
-rw-r--r-- | sys/vm/vm_mmap.c | 77 | ||||
-rw-r--r-- | sys/vm/vm_object.h | 4 |
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: * |