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 | |
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@
-rw-r--r-- | sys/alpha/osf1/imgact_osf1.c | 4 | ||||
-rw-r--r-- | sys/alpha/osf1/osf1_misc.c | 3 | ||||
-rw-r--r-- | sys/compat/linux/linux_misc.c | 6 | ||||
-rw-r--r-- | sys/compat/svr4/imgact_svr4.c | 4 | ||||
-rw-r--r-- | sys/dev/drm/drm_bufs.h | 6 | ||||
-rw-r--r-- | sys/i386/ibcs2/imgact_coff.c | 14 | ||||
-rw-r--r-- | sys/i386/linux/imgact_linux.c | 7 | ||||
-rw-r--r-- | sys/kern/imgact_gzip.c | 6 | ||||
-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 |
12 files changed, 104 insertions, 33 deletions
diff --git a/sys/alpha/osf1/imgact_osf1.c b/sys/alpha/osf1/imgact_osf1.c index 451896f..55498e0 100644 --- a/sys/alpha/osf1/imgact_osf1.c +++ b/sys/alpha/osf1/imgact_osf1.c @@ -189,14 +189,14 @@ exec_osf1_imgact(struct image_params *imgp) /* set up text segment */ if ((error = vm_mmap(&vmspace->vm_map, &taddr, tsize, VM_PROT_READ|VM_PROT_EXECUTE, VM_PROT_ALL, MAP_FIXED|MAP_COPY, - (caddr_t)imgp->vp, ECOFF_TXTOFF(execp)))) { + OBJT_VNODE, imgp->vp, ECOFF_TXTOFF(execp)))) { DPRINTF(("%s(%d): error = %d\n", __FILE__, __LINE__, error)); goto bail; } /* .. data .. */ if ((error = vm_mmap(&vmspace->vm_map, &daddr, dsize, VM_PROT_READ|VM_PROT_EXECUTE|VM_PROT_WRITE, VM_PROT_ALL, - MAP_FIXED|MAP_COPY, (caddr_t)imgp->vp, ECOFF_DATOFF(execp)))) { + MAP_FIXED|MAP_COPY, OBJT_VNODE, imgp->vp, ECOFF_DATOFF(execp)))) { DPRINTF(("%s(%d): error = %d\n", __FILE__, __LINE__, error)); goto bail; } diff --git a/sys/alpha/osf1/osf1_misc.c b/sys/alpha/osf1/osf1_misc.c index 584ed22..dd5ec7a 100644 --- a/sys/alpha/osf1/osf1_misc.c +++ b/sys/alpha/osf1/osf1_misc.c @@ -1458,7 +1458,8 @@ osf1_uswitch(td, uap) if (uap->mask & OSF1_USW_NULLP) { rv = vm_mmap(&(p->p_vmspace->vm_map), &zero, PAGE_SIZE, VM_PROT_READ, VM_PROT_ALL, - MAP_PRIVATE | MAP_FIXED | MAP_ANON, NULL, 0); + MAP_PRIVATE | MAP_FIXED | MAP_ANON, OBJT_DEFAULT, + NULL, 0); if (!rv) return(KERN_SUCCESS); else { diff --git a/sys/compat/linux/linux_misc.c b/sys/compat/linux/linux_misc.c index 7bbeaff..85cd13b 100644 --- a/sys/compat/linux/linux_misc.c +++ b/sys/compat/linux/linux_misc.c @@ -333,7 +333,7 @@ linux_uselib(struct thread *td, struct linux_uselib_args *args) /* Pull in executable header into kernel_map */ error = vm_mmap(kernel_map, (vm_offset_t *)&a_out, PAGE_SIZE, - VM_PROT_READ, VM_PROT_READ, 0, (caddr_t)vp, 0); + VM_PROT_READ, VM_PROT_READ, 0, OBJT_VNODE, vp, 0); /* * Lock no longer needed */ @@ -422,7 +422,7 @@ linux_uselib(struct thread *td, struct linux_uselib_args *args) /* map file into kernel_map */ error = vm_mmap(kernel_map, &buffer, round_page(a_out->a_text + a_out->a_data + file_offset), - VM_PROT_READ, VM_PROT_READ, 0, (caddr_t)vp, + VM_PROT_READ, VM_PROT_READ, 0, OBJT_VNODE, vp, trunc_page(file_offset)); if (error) goto cleanup; @@ -453,7 +453,7 @@ linux_uselib(struct thread *td, struct linux_uselib_args *args) */ error = vm_mmap(&td->td_proc->p_vmspace->vm_map, &vmaddr, a_out->a_text + a_out->a_data, VM_PROT_ALL, VM_PROT_ALL, - MAP_PRIVATE | MAP_FIXED, (caddr_t)vp, file_offset); + MAP_PRIVATE | MAP_FIXED, OBJT_VNODE, vp, file_offset); if (error) goto cleanup; } diff --git a/sys/compat/svr4/imgact_svr4.c b/sys/compat/svr4/imgact_svr4.c index 39eeb99..4c71020 100644 --- a/sys/compat/svr4/imgact_svr4.c +++ b/sys/compat/svr4/imgact_svr4.c @@ -145,7 +145,7 @@ exec_svr4_imgact(imgp) error = vm_mmap(kernel_map, &buffer, round_page(a_out->a_text + a_out->a_data + file_offset), VM_PROT_READ, VM_PROT_READ, 0, - (caddr_t) imgp->vp, trunc_page(file_offset)); + OBJT_VNODE, imgp->vp, trunc_page(file_offset)); if (error) goto fail; @@ -182,7 +182,7 @@ exec_svr4_imgact(imgp) VM_PROT_READ | VM_PROT_EXECUTE, VM_PROT_ALL, MAP_PRIVATE | MAP_FIXED, - (caddr_t)imgp->vp, file_offset); + OBJT_VNODE, imgp->vp, file_offset); if (error) goto fail; diff --git a/sys/dev/drm/drm_bufs.h b/sys/dev/drm/drm_bufs.h index 6f7f205..cb57852 100644 --- a/sys/dev/drm/drm_bufs.h +++ b/sys/dev/drm/drm_bufs.h @@ -923,12 +923,8 @@ int DRM(mapbufs)( DRM_IOCTL_ARGS ) #ifdef __FreeBSD__ vaddr = round_page((vm_offset_t)vms->vm_daddr + MAXDSIZ); -#ifdef this_is_just_plain_bogus retcode = vm_mmap(&vms->vm_map, &vaddr, size, PROT_READ | PROT_WRITE, - VM_PROT_ALL, MAP_SHARED, SLIST_FIRST(&kdev->si_hlist), foff ); -#else - retcode = EOPNOTSUPP; -#endif + VM_PROT_ALL, MAP_SHARED, OBJT_DEVICE, kdev, foff ); #elif defined(__NetBSD__) vaddr = round_page((vaddr_t)vms->vm_daddr + MAXDSIZ); retcode = uvm_mmap(&vms->vm_map, &vaddr, size, diff --git a/sys/i386/ibcs2/imgact_coff.c b/sys/i386/ibcs2/imgact_coff.c index 226d1e9..b6c6cae 100644 --- a/sys/i386/ibcs2/imgact_coff.c +++ b/sys/i386/ibcs2/imgact_coff.c @@ -91,7 +91,7 @@ load_coff_section(struct vmspace *vmspace, struct vnode *vp, vm_offset_t offset, } DPRINTF(("%s(%d): vm_mmap(&vmspace->vm_map, &0x%08lx, 0x%x, 0x%x, " - "VM_PROT_ALL, MAP_PRIVATE | MAP_FIXED, vp, 0x%x)\n", + "VM_PROT_ALL, MAP_PRIVATE | MAP_FIXED, OBJT_VNODE, vp, 0x%x)\n", __FILE__, __LINE__, map_addr, map_len, prot, map_offset)); if ((error = vm_mmap(&vmspace->vm_map, @@ -100,7 +100,8 @@ load_coff_section(struct vmspace *vmspace, struct vnode *vp, vm_offset_t offset, prot, VM_PROT_ALL, MAP_PRIVATE | MAP_FIXED, - (caddr_t) vp, + OBJT_VNODE, + vp, map_offset)) != 0) return error; @@ -136,7 +137,8 @@ load_coff_section(struct vmspace *vmspace, struct vnode *vp, vm_offset_t offset, VM_PROT_READ, VM_PROT_READ, 0, - (caddr_t) vp, + OBJT_VNODE, + vp, trunc_page(offset + filsz))) != 0) return error; @@ -215,7 +217,8 @@ coff_load_file(struct thread *td, char *name) VM_PROT_READ, VM_PROT_READ, 0, - (caddr_t) vp, + OBJT_VNODE, + vp, 0)) != 0) goto unlocked_fail; @@ -372,7 +375,8 @@ exec_coff_imgact(imgp) VM_PROT_READ, VM_PROT_READ, 0, - (caddr_t) imgp->vp, + OBJT_VNODE, + imgp->vp, foff)) != 0) { error = ENOEXEC; goto fail; diff --git a/sys/i386/linux/imgact_linux.c b/sys/i386/linux/imgact_linux.c index 50e40bf..cfc28e9 100644 --- a/sys/i386/linux/imgact_linux.c +++ b/sys/i386/linux/imgact_linux.c @@ -143,8 +143,8 @@ exec_linux_imgact(struct image_params *imgp) error = vm_mmap(kernel_map, &buffer, round_page(a_out->a_text + a_out->a_data + file_offset), - VM_PROT_READ, VM_PROT_READ, 0, - (caddr_t) imgp->vp, trunc_page(file_offset)); + VM_PROT_READ, VM_PROT_READ, 0, OBJT_VNODE, + imgp->vp, trunc_page(file_offset)); if (error) goto fail; @@ -181,7 +181,8 @@ exec_linux_imgact(struct image_params *imgp) VM_PROT_READ | VM_PROT_EXECUTE, VM_PROT_ALL, MAP_PRIVATE | MAP_FIXED, - (caddr_t)imgp->vp, file_offset); + OBJT_VNODE, + imgp->vp, file_offset); if (error) goto fail; diff --git a/sys/kern/imgact_gzip.c b/sys/kern/imgact_gzip.c index d44d49d..0b08204 100644 --- a/sys/kern/imgact_gzip.c +++ b/sys/kern/imgact_gzip.c @@ -238,7 +238,8 @@ do_aout_hdr(struct imgact_gzip * gz) &vmaddr, gz->a_out.a_text + gz->a_out.a_data, VM_PROT_ALL, VM_PROT_ALL, MAP_ANON | MAP_FIXED, - 0, + OBJT_DEFAULT, + NULL, 0); if (error) { @@ -311,7 +312,8 @@ NextByte(void *vp) VM_PROT_READ, /* protection */ VM_PROT_READ, /* max protection */ 0, /* flags */ - (caddr_t) igz->ip->vp, /* vnode */ + OBJT_VNODE, /* handle type */ + igz->ip->vp, /* vnode */ igz->offset); /* offset */ if (error) { igz->where = __LINE__; 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: * |