Index: sys/sys/file.h =================================================================== RCS file: /home/chs/netbsd/cvs/src/sys/sys/file.h,v retrieving revision 1.77 diff -u -p -r1.77 file.h --- sys/sys/file.h 5 Sep 2014 09:17:04 -0000 1.77 +++ sys/sys/file.h 19 Nov 2014 15:24:37 -0000 @@ -77,6 +77,7 @@ struct uio; struct iovec; struct stat; struct knote; +struct uvm_object; struct fileops { int (*fo_read) (struct file *, off_t *, struct uio *, @@ -90,17 +91,11 @@ struct fileops { int (*fo_close) (struct file *); int (*fo_kqfilter) (struct file *, struct knote *); void (*fo_restart) (struct file *); - void (*fo_spare1) (void); + int (*fo_mmap) (struct file *, off_t *, size_t, int, int *, + int *, struct uvm_object **, int *); void (*fo_spare2) (void); }; -/* - * Kernel file descriptor. One entry for each open kernel vnode and - * socket. - * - * This structure is exported via the KERN_FILE and KERN_FILE2 sysctl - * calls. Only add members to the end, do not delete them. - */ union file_data { struct vnode *fd_vp; // DTYPE_VNODE struct socket *fd_so; // DTYPE_SOCKET @@ -115,6 +110,13 @@ union file_data { struct ksem *fd_ks; // DTYPE_SEM }; +/* + * Kernel file descriptor. One entry for each open kernel vnode and + * socket. + * + * This structure is exported via the KERN_FILE and KERN_FILE2 sysctl + * calls. Only add members to the end, do not delete them. + */ struct file { off_t f_offset; /* first, is 64-bit */ kauth_cred_t f_cred; /* creds associated with descriptor */ Index: sys/uvm/uvm_extern.h =================================================================== RCS file: /home/chs/netbsd/cvs/src/sys/uvm/uvm_extern.h,v retrieving revision 1.191 diff -u -p -r1.191 uvm_extern.h --- sys/uvm/uvm_extern.h 7 Jul 2014 20:14:43 -0000 1.191 +++ sys/uvm/uvm_extern.h 21 Nov 2014 02:41:16 -0000 @@ -668,9 +668,9 @@ int uvm_pctparam_createsysctlnode(stru const char *, const char *); /* uvm_mmap.c */ -int uvm_mmap(struct vm_map *, vaddr_t *, vsize_t, - vm_prot_t, vm_prot_t, int, - void *, voff_t, vsize_t); +int uvm_mmap_dev(struct proc *, void **, size_t, dev_t, + off_t); +int uvm_mmap_anon(struct proc *, void **, size_t); vaddr_t uvm_default_mapaddr(struct proc *, vaddr_t, vsize_t); /* uvm_mremap.c */ Index: sys/uvm/uvm_mmap.c =================================================================== RCS file: /home/chs/netbsd/cvs/src/sys/uvm/uvm_mmap.c,v retrieving revision 1.149 diff -u -p -r1.149 uvm_mmap.c --- sys/uvm/uvm_mmap.c 5 Sep 2014 09:24:48 -0000 1.149 +++ sys/uvm/uvm_mmap.c 21 Nov 2014 02:48:11 -0000 @@ -78,9 +78,8 @@ __KERNEL_RCSID(0, "$NetBSD: uvm_mmap.c,v #include #include -#ifndef COMPAT_ZERODEV -#define COMPAT_ZERODEV(dev) (0) -#endif +static int uvm_mmap(struct vm_map *, vaddr_t *, vsize_t, vm_prot_t, vm_prot_t, + int, int, struct uvm_object *, voff_t, vsize_t); static int range_test(vaddr_t addr, vsize_t size, bool ismmap) @@ -301,15 +300,13 @@ sys_mmap(struct lwp *l, const struct sys } */ struct proc *p = l->l_proc; vaddr_t addr; - struct vattr va; off_t pos; vsize_t size, pageoff; vm_prot_t prot, maxprot; - int flags, fd; + int flags, fd, advice; vaddr_t defaddr; struct file *fp = NULL; - struct vnode *vp; - void *handle; + struct uvm_object *uobj; int error; #ifdef PAX_ASLR vaddr_t orig_addr; @@ -368,8 +365,10 @@ sys_mmap(struct lwp *l, const struct sys return (EINVAL); error = range_test(addr, size, true); - if (error) + if (error) { return error; + } + } else if (addr == 0 || !(flags & MAP_TRYFIXED)) { /* @@ -393,113 +392,26 @@ sys_mmap(struct lwp *l, const struct sys * check for file mappings (i.e. not anonymous) and verify file. */ + advice = UVM_ADV_NORMAL; if ((flags & MAP_ANON) == 0) { if ((fp = fd_getfile(fd)) == NULL) return (EBADF); - if (fp->f_type != DTYPE_VNODE) { - fd_putfile(fd); - return (ENODEV); /* only mmap vnodes! */ - } - vp = fp->f_vnode; /* convert to vnode */ - if (vp->v_type != VREG && vp->v_type != VCHR && - vp->v_type != VBLK) { - fd_putfile(fd); - return (ENODEV); /* only REG/CHR/BLK support mmap */ - } - if (vp->v_type != VCHR && pos < 0) { - fd_putfile(fd); - return (EINVAL); + + if (fp->f_ops->fo_mmap == NULL) { + error = ENODEV; + goto out; } - if (vp->v_type != VCHR && (off_t)(pos + size) < pos) { - fd_putfile(fd); - return (EOVERFLOW); /* no offset wrapping */ + error = (*fp->f_ops->fo_mmap)(fp, &pos, size, prot, &flags, + &advice, &uobj, &maxprot); + if (error) { + goto out; } - - /* special case: catch SunOS style /dev/zero */ - if (vp->v_type == VCHR - && (vp->v_rdev == zerodev || COMPAT_ZERODEV(vp->v_rdev))) { + if (uobj == NULL) { flags |= MAP_ANON; fd_putfile(fd); fp = NULL; goto is_anon; } - - /* - * Old programs may not select a specific sharing type, so - * default to an appropriate one. - * - * XXX: how does MAP_ANON fit in the picture? - */ - if ((flags & (MAP_SHARED|MAP_PRIVATE)) == 0) { -#if defined(DEBUG) - printf("WARNING: defaulted mmap() share type to " - "%s (pid %d command %s)\n", vp->v_type == VCHR ? - "MAP_SHARED" : "MAP_PRIVATE", p->p_pid, - p->p_comm); -#endif - if (vp->v_type == VCHR) - flags |= MAP_SHARED; /* for a device */ - else - flags |= MAP_PRIVATE; /* for a file */ - } - - /* - * MAP_PRIVATE device mappings don't make sense (and aren't - * supported anyway). However, some programs rely on this, - * so just change it to MAP_SHARED. - */ - if (vp->v_type == VCHR && (flags & MAP_PRIVATE) != 0) { - flags = (flags & ~MAP_PRIVATE) | MAP_SHARED; - } - - /* - * now check protection - */ - - maxprot = VM_PROT_EXECUTE; - - /* check read access */ - if (fp->f_flag & FREAD) - maxprot |= VM_PROT_READ; - else if (prot & PROT_READ) { - fd_putfile(fd); - return (EACCES); - } - - /* check write access, shared case first */ - if (flags & MAP_SHARED) { - /* - * if the file is writable, only add PROT_WRITE to - * maxprot if the file is not immutable, append-only. - * otherwise, if we have asked for PROT_WRITE, return - * EPERM. - */ - if (fp->f_flag & FWRITE) { - vn_lock(vp, LK_SHARED | LK_RETRY); - error = VOP_GETATTR(vp, &va, l->l_cred); - VOP_UNLOCK(vp); - if (error) { - fd_putfile(fd); - return (error); - } - if ((va.va_flags & - (SF_SNAPSHOT|IMMUTABLE|APPEND)) == 0) - maxprot |= VM_PROT_WRITE; - else if (prot & PROT_WRITE) { - fd_putfile(fd); - return (EPERM); - } - } - else if (prot & PROT_WRITE) { - fd_putfile(fd); - return (EACCES); - } - } else { - /* MAP_PRIVATE mappings can always write to */ - maxprot |= VM_PROT_WRITE; - } - handle = vp; - } else { /* MAP_ANON case */ /* * XXX What do we do about (MAP_SHARED|MAP_PRIVATE) == 0? @@ -508,41 +420,11 @@ sys_mmap(struct lwp *l, const struct sys return (EINVAL); is_anon: /* label for SunOS style /dev/zero */ - handle = NULL; + uobj = NULL; maxprot = VM_PROT_ALL; pos = 0; } -#if NVERIEXEC > 0 - if (handle != NULL) { - /* - * Check if the file can be executed indirectly. - * - * XXX: This gives false warnings about "Incorrect access type" - * XXX: if the mapping is not executable. Harmless, but will be - * XXX: fixed as part of other changes. - */ - if (veriexec_verify(l, handle, "(mmap)", VERIEXEC_INDIRECT, - NULL)) { - /* - * Don't allow executable mappings if we can't - * indirectly execute the file. - */ - if (prot & VM_PROT_EXECUTE) { - if (fp != NULL) - fd_putfile(fd); - return (EPERM); - } - - /* - * Strip the executable bit from 'maxprot' to make sure - * it can't be made executable later. - */ - maxprot &= ~VM_PROT_EXECUTE; - } - } -#endif /* NVERIEXEC > 0 */ - #ifdef PAX_MPROTECT pax_mprotect(l, &prot, &maxprot); #endif /* PAX_MPROTECT */ @@ -556,12 +438,12 @@ sys_mmap(struct lwp *l, const struct sys */ error = uvm_mmap(&p->p_vmspace->vm_map, &addr, size, prot, maxprot, - flags, handle, pos, p->p_rlimit[RLIMIT_MEMLOCK].rlim_cur); + flags, advice, uobj, pos, p->p_rlimit[RLIMIT_MEMLOCK].rlim_cur); - if (error == 0) - /* remember to add offset */ - *retval = (register_t)(addr + pageoff); + /* remember to add offset */ + *retval = (register_t)(addr + pageoff); + out: if (fp != NULL) fd_putfile(fd); @@ -1045,21 +927,18 @@ sys_munlockall(struct lwp *l, const void * uvm_mmap: internal version of mmap * * - used by sys_mmap and various framebuffers - * - handle is a vnode pointer or NULL for MAP_ANON + * - uobj is a struct uvm_object pointer or NULL for MAP_ANON * - caller must page-align the file offset */ int uvm_mmap(struct vm_map *map, vaddr_t *addr, vsize_t size, vm_prot_t prot, - vm_prot_t maxprot, int flags, void *handle, voff_t foff, vsize_t locklimit) + vm_prot_t maxprot, int flags, int advice, struct uvm_object *uobj, + voff_t foff, vsize_t locklimit) { - struct uvm_object *uobj; - struct vnode *vp; vaddr_t align = 0; int error; - int advice = UVM_ADV_NORMAL; uvm_flag_t uvmflag = 0; - bool needwritemap; /* * check params @@ -1125,9 +1004,8 @@ uvm_mmap(struct vm_map *map, vaddr_t *ad */ if (flags & MAP_ANON) { - KASSERT(handle == NULL); + KASSERT(uobj == NULL); foff = UVM_UNKNOWN_OFFSET; - uobj = NULL; if ((flags & MAP_SHARED) == 0) /* XXX: defer amap create */ uvmflag |= UVM_FLAG_COPYONW; @@ -1136,75 +1014,10 @@ uvm_mmap(struct vm_map *map, vaddr_t *ad uvmflag |= UVM_FLAG_OVERLAY; } else { - KASSERT(handle != NULL); - vp = (struct vnode *)handle; - - /* - * Don't allow mmap for EXEC if the file system - * is mounted NOEXEC. - */ - if ((prot & PROT_EXEC) != 0 && - (vp->v_mount->mnt_flag & MNT_NOEXEC) != 0) - return (EACCES); - - if (vp->v_type != VCHR) { - error = VOP_MMAP(vp, prot, curlwp->l_cred); - if (error) { - return error; - } - vref(vp); - uobj = &vp->v_uobj; - - /* - * If the vnode is being mapped with PROT_EXEC, - * then mark it as text. - */ - if (prot & PROT_EXEC) { - vn_markexec(vp); - } - } else { - int i = maxprot; - - /* - * XXX Some devices don't like to be mapped with - * XXX PROT_EXEC or PROT_WRITE, but we don't really - * XXX have a better way of handling this, right now - */ - do { - uobj = udv_attach((void *) &vp->v_rdev, - (flags & MAP_SHARED) ? i : - (i & ~VM_PROT_WRITE), foff, size); - i--; - } while ((uobj == NULL) && (i > 0)); - if (uobj == NULL) - return EINVAL; - advice = UVM_ADV_RANDOM; - } + KASSERT(uobj != NULL); if ((flags & MAP_SHARED) == 0) { uvmflag |= UVM_FLAG_COPYONW; } - - /* - * Set vnode flags to indicate the new kinds of mapping. - * We take the vnode lock in exclusive mode here to serialize - * with direct I/O. - * - * Safe to check for these flag values without a lock, as - * long as a reference to the vnode is held. - */ - needwritemap = (vp->v_iflag & VI_WRMAP) == 0 && - (flags & MAP_SHARED) != 0 && - (maxprot & VM_PROT_WRITE) != 0; - if ((vp->v_vflag & VV_MAPPED) == 0 || needwritemap) { - vn_lock(vp, LK_EXCLUSIVE | LK_RETRY); - vp->v_vflag |= VV_MAPPED; - if (needwritemap) { - mutex_enter(vp->v_interlock); - vp->v_iflag |= VI_WRMAP; - mutex_exit(vp->v_interlock); - } - VOP_UNLOCK(vp); - } } uvmflag = UVM_MAPFLAG(prot, maxprot, @@ -1267,3 +1080,48 @@ uvm_default_mapaddr(struct proc *p, vadd else return VM_DEFAULT_ADDRESS_BOTTOMUP(base, sz); } + +int +uvm_mmap_dev(struct proc *p, void **addrp, size_t len, dev_t dev, + off_t off) +{ + struct uvm_object *uobj; + int error, flags, prot; + + flags = MAP_SHARED; + prot = VM_PROT_READ | VM_PROT_WRITE; + if (*addrp) + flags |= MAP_FIXED; + else + *addrp = (void *)p->p_emul->e_vm_default_addr(p, + (vaddr_t)p->p_vmspace->vm_daddr, len); + + uobj = udv_attach(dev, prot, 0, len); + if (uobj == NULL) + return EINVAL; + + error = uvm_mmap(&p->p_vmspace->vm_map, (vaddr_t *)addrp, + (vsize_t)len, prot, prot, flags, UVM_ADV_RANDOM, + uobj, 0, p->p_rlimit[RLIMIT_MEMLOCK].rlim_cur); + return error; +} + +int +uvm_mmap_anon(struct proc *p, void **addrp, size_t len) +{ + int error, flags, prot; + + flags = MAP_PRIVATE | MAP_ANON; + prot = VM_PROT_READ | VM_PROT_WRITE; + if (*addrp) + flags |= MAP_FIXED; + else + *addrp = (void *)p->p_emul->e_vm_default_addr(p, + (vaddr_t)p->p_vmspace->vm_daddr, len); + + error = uvm_mmap(&p->p_vmspace->vm_map, (vaddr_t *)addrp, + (vsize_t)len, prot, prot, flags, UVM_ADV_NORMAL, + NULL, 0, p->p_rlimit[RLIMIT_MEMLOCK].rlim_cur); + return error; + +} Index: sys/uvm/uvm_device.c =================================================================== RCS file: /home/chs/netbsd/cvs/src/sys/uvm/uvm_device.c,v retrieving revision 1.63 diff -u -p -r1.63 uvm_device.c --- sys/uvm/uvm_device.c 27 Jan 2012 19:48:41 -0000 1.63 +++ sys/uvm/uvm_device.c 19 Nov 2014 16:12:20 -0000 @@ -106,11 +106,10 @@ udv_init(void) */ struct uvm_object * -udv_attach(void *arg, vm_prot_t accessprot, +udv_attach(dev_t device, vm_prot_t accessprot, voff_t off, /* used only for access check */ vsize_t size /* used only for access check */) { - dev_t device = *((dev_t *)arg); struct uvm_device *udv, *lcv; const struct cdevsw *cdev; dev_type_mmap((*mapfn)); Index: sys/uvm/uvm_device.h =================================================================== RCS file: /home/chs/netbsd/cvs/src/sys/uvm/uvm_device.h,v retrieving revision 1.12 diff -u -p -r1.12 uvm_device.h --- sys/uvm/uvm_device.h 2 Feb 2011 15:13:34 -0000 1.12 +++ sys/uvm/uvm_device.h 19 Nov 2014 16:12:41 -0000 @@ -62,7 +62,7 @@ struct uvm_device { * prototypes */ -struct uvm_object *udv_attach(void *, vm_prot_t, voff_t, vsize_t); +struct uvm_object *udv_attach(dev_t, vm_prot_t, voff_t, vsize_t); #endif /* _KERNEL */ Index: sys/kern/vfs_vnops.c =================================================================== RCS file: /home/chs/netbsd/cvs/src/sys/kern/vfs_vnops.c,v retrieving revision 1.191 diff -u -p -r1.191 vfs_vnops.c --- sys/kern/vfs_vnops.c 5 Sep 2014 09:20:59 -0000 1.191 +++ sys/kern/vfs_vnops.c 19 Nov 2014 16:30:00 -0000 @@ -89,17 +89,23 @@ __KERNEL_RCSID(0, "$NetBSD: vfs_vnops.c, #include #include #include +#include #include #include #include #include +#include #ifdef UNION #include #endif +#ifndef COMPAT_ZERODEV +#define COMPAT_ZERODEV(dev) (0) +#endif + int (*vn_union_readdir_hook) (struct vnode **, struct file *, struct lwp *); #include @@ -113,6 +119,8 @@ static int vn_poll(file_t *fp, int event static int vn_fcntl(file_t *fp, u_int com, void *data); static int vn_statfile(file_t *fp, struct stat *sb); static int vn_ioctl(file_t *fp, u_long com, void *data); +static int vn_mmap(struct file *, off_t *, size_t, int, int *, int *, + struct uvm_object **, int *); const struct fileops vnops = { .fo_read = vn_read, @@ -124,6 +132,7 @@ const struct fileops vnops = { .fo_close = vn_closefile, .fo_kqfilter = vn_kqfilter, .fo_restart = fnullop_restart, + .fo_mmap = vn_mmap, }; /* @@ -789,6 +798,219 @@ vn_kqfilter(file_t *fp, struct knote *kn return (VOP_KQFILTER(fp->f_vnode, kn)); } +static int +vn_mmap(struct file *fp, off_t *offp, size_t size, int prot, int *flagsp, + int *advicep, struct uvm_object **uobjp, int *maxprotp) +{ + struct uvm_object *uobj; + struct vnode *vp; + struct vattr va; + struct lwp *l; + vm_prot_t maxprot; + off_t off; + int error, flags; + bool needwritemap; + + l = curlwp; + + off = *offp; + flags = *flagsp; + maxprot = VM_PROT_EXECUTE; + + vp = fp->f_vnode; + if (vp->v_type != VREG && vp->v_type != VCHR && + vp->v_type != VBLK) { + /* only REG/CHR/BLK support mmap */ + return ENODEV; + } + if (vp->v_type != VCHR && off < 0) { + return EINVAL; + } + if (vp->v_type != VCHR && (off_t)(off + size) < off) { + /* no offset wrapping */ + return EOVERFLOW; + } + + /* special case: catch SunOS style /dev/zero */ + if (vp->v_type == VCHR && + (vp->v_rdev == zerodev || COMPAT_ZERODEV(vp->v_rdev))) { + *uobjp = NULL; + *maxprotp = VM_PROT_ALL; + return 0; + } + + /* + * Old programs may not select a specific sharing type, so + * default to an appropriate one. + * + * XXX: how does MAP_ANON fit in the picture? + */ + if ((flags & (MAP_SHARED|MAP_PRIVATE)) == 0) { +#if defined(DEBUG) + struct proc *p = l->l_proc; + printf("WARNING: defaulted mmap() share type to " + "%s (pid %d command %s)\n", vp->v_type == VCHR ? + "MAP_SHARED" : "MAP_PRIVATE", p->p_pid, + p->p_comm); +#endif + if (vp->v_type == VCHR) + flags |= MAP_SHARED; /* for a device */ + else + flags |= MAP_PRIVATE; /* for a file */ + } + + /* + * MAP_PRIVATE device mappings don't make sense (and aren't + * supported anyway). However, some programs rely on this, + * so just change it to MAP_SHARED. + */ + if (vp->v_type == VCHR && (flags & MAP_PRIVATE) != 0) { + flags = (flags & ~MAP_PRIVATE) | MAP_SHARED; + } + + /* + * now check protection + */ + + /* check read access */ + if (fp->f_flag & FREAD) + maxprot |= VM_PROT_READ; + else if (prot & PROT_READ) { + return EACCES; + } + + /* check write access, shared case first */ + if (flags & MAP_SHARED) { + /* + * if the file is writable, only add PROT_WRITE to + * maxprot if the file is not immutable, append-only. + * otherwise, if we have asked for PROT_WRITE, return + * EPERM. + */ + if (fp->f_flag & FWRITE) { + vn_lock(vp, LK_SHARED | LK_RETRY); + error = VOP_GETATTR(vp, &va, l->l_cred); + VOP_UNLOCK(vp); + if (error) { + return error; + } + if ((va.va_flags & + (SF_SNAPSHOT|IMMUTABLE|APPEND)) == 0) + maxprot |= VM_PROT_WRITE; + else if (prot & PROT_WRITE) { + return EPERM; + } + } else if (prot & PROT_WRITE) { + return EACCES; + } + } else { + /* MAP_PRIVATE mappings can always write to */ + maxprot |= VM_PROT_WRITE; + } + + /* + * Don't allow mmap for EXEC if the file system + * is mounted NOEXEC. + */ + if ((prot & PROT_EXEC) != 0 && + (vp->v_mount->mnt_flag & MNT_NOEXEC) != 0) { + return EACCES; + } + + if (vp->v_type != VCHR) { + error = VOP_MMAP(vp, prot, curlwp->l_cred); + if (error) { + return error; + } + vref(vp); + uobj = &vp->v_uobj; + + /* + * If the vnode is being mapped with PROT_EXEC, + * then mark it as text. + */ + if (prot & PROT_EXEC) { + vn_markexec(vp); + } + } else { + int i = maxprot; + + /* + * XXX Some devices don't like to be mapped with + * XXX PROT_EXEC or PROT_WRITE, but we don't really + * XXX have a better way of handling this, right now + */ + do { + uobj = udv_attach(vp->v_rdev, + (flags & MAP_SHARED) ? i : + (i & ~VM_PROT_WRITE), off, size); + i--; + } while ((uobj == NULL) && (i > 0)); + if (uobj == NULL) { + return EINVAL; + } + *advicep = UVM_ADV_RANDOM; + } + + /* + * Set vnode flags to indicate the new kinds of mapping. + * We take the vnode lock in exclusive mode here to serialize + * with direct I/O. + * + * Safe to check for these flag values without a lock, as + * long as a reference to the vnode is held. + */ + needwritemap = (vp->v_iflag & VI_WRMAP) == 0 && + (flags & MAP_SHARED) != 0 && + (maxprot & VM_PROT_WRITE) != 0; + if ((vp->v_vflag & VV_MAPPED) == 0 || needwritemap) { + vn_lock(vp, LK_EXCLUSIVE | LK_RETRY); + vp->v_vflag |= VV_MAPPED; + if (needwritemap) { + mutex_enter(vp->v_interlock); + vp->v_iflag |= VI_WRMAP; + mutex_exit(vp->v_interlock); + } + VOP_UNLOCK(vp); + } + +#if NVERIEXEC > 0 + + /* + * Check if the file can be executed indirectly. + * + * XXX: This gives false warnings about "Incorrect access type" + * XXX: if the mapping is not executable. Harmless, but will be + * XXX: fixed as part of other changes. + */ + if (veriexec_verify(l, vp, "(mmap)", VERIEXEC_INDIRECT, + NULL)) { + + /* + * Don't allow executable mappings if we can't + * indirectly execute the file. + */ + if (prot & VM_PROT_EXECUTE) { + return EPERM; + } + + /* + * Strip the executable bit from 'maxprot' to make sure + * it can't be made executable later. + */ + maxprot &= ~VM_PROT_EXECUTE; + } +#endif /* NVERIEXEC > 0 */ + + *uobjp = uobj; + *maxprotp = maxprot; + *flagsp = flags; + + return 0; +} + + + /* * Check that the vnode is still valid, and if so * acquire requested lock. Index: common/lib/libprop/prop_kern.c =================================================================== RCS file: /home/chs/netbsd/cvs/src/common/lib/libprop/prop_kern.c,v retrieving revision 1.17 diff -u -p -r1.17 prop_kern.c --- common/lib/libprop/prop_kern.c 30 Sep 2011 22:08:18 -0000 1.17 +++ common/lib/libprop/prop_kern.c 21 Nov 2014 02:47:43 -0000 @@ -507,9 +507,9 @@ _prop_object_copyout(struct plistref *pr struct lwp *l = curlwp; /* XXX */ struct proc *p = l->l_proc; char *buf; + void *uaddr; size_t len, rlen; int error = 0; - vaddr_t uaddr; switch (prop_object_type(obj)) { case PROP_TYPE_ARRAY: @@ -526,26 +526,12 @@ _prop_object_copyout(struct plistref *pr len = strlen(buf) + 1; rlen = round_page(len); - - /* - * See sys_mmap() in sys/uvm/uvm_mmap.c. - * Let's act as if we were calling mmap(0, ...) - */ - uaddr = p->p_emul->e_vm_default_addr(p, - (vaddr_t)p->p_vmspace->vm_daddr, rlen); - - error = uvm_mmap(&p->p_vmspace->vm_map, - &uaddr, rlen, - VM_PROT_READ|VM_PROT_WRITE, - VM_PROT_READ|VM_PROT_WRITE, - MAP_PRIVATE|MAP_ANON, - NULL, 0, - p->p_rlimit[RLIMIT_MEMLOCK].rlim_cur); - + uaddr = NULL; + error = uvm_mmap_anon(p, &uaddr, rlen); if (error == 0) { - error = copyout(buf, (char *)uaddr, len); + error = copyout(buf, uaddr, len); if (error == 0) { - pref->pref_plist = (char *)uaddr; + pref->pref_plist = uaddr; pref->pref_len = len; } } Index: sys/arch/mac68k/dev/grf_compat.c =================================================================== RCS file: /home/chs/netbsd/cvs/src/sys/arch/mac68k/dev/grf_compat.c,v retrieving revision 1.26 diff -u -p -r1.26 grf_compat.c --- sys/arch/mac68k/dev/grf_compat.c 25 Jul 2014 08:10:33 -0000 1.26 +++ sys/arch/mac68k/dev/grf_compat.c 21 Nov 2014 02:48:52 -0000 @@ -59,6 +59,7 @@ __KERNEL_RCSID(0, "$NetBSD: grf_compat.c #include #include +#include #include dev_type_open(grfopen); @@ -320,24 +321,14 @@ grfmmap(dev_t dev, off_t off, int prot) int grfmap(dev_t dev, struct macfb_softc *sc, void **addrp, struct proc *p) { - struct vnode vn; - u_long len; - int error, flags; + size_t len; + int error; len = m68k_round_page(sc->sc_dc->dc_offset + sc->sc_dc->dc_size); - *addrp = (void *)p->p_emul->e_vm_default_addr(p, - (vaddr_t)p->p_vmspace->vm_daddr, len); - flags = MAP_SHARED | MAP_FIXED; - - vn.v_type = VCHR; /* XXX */ - vn.v_rdev = dev; /* XXX */ - - error = uvm_mmap(&p->p_vmspace->vm_map, (vaddr_t *)addrp, - (vsize_t)len, VM_PROT_ALL, VM_PROT_ALL, - flags, (void *)&vn, 0, p->p_rlimit[RLIMIT_MEMLOCK].rlim_cur); + error = uvm_mmap_dev(p, addrp, len, dev, 0); /* Offset into page: */ - *addrp = (char*)*addrp + sc->sc_dc->dc_offset; + *addrp = (char *)*addrp + sc->sc_dc->dc_offset; return (error); } @@ -345,9 +336,9 @@ grfmap(dev_t dev, struct macfb_softc *sc int grfunmap(dev_t dev, struct macfb_softc *sc, void *addr, struct proc *p) { - vm_size_t size; + size_t size; - addr = (char*)addr - sc->sc_dc->dc_offset; + addr = (char *)addr - sc->sc_dc->dc_offset; if (addr <= 0) return (-1); Index: sys/arch/x68k/dev/grf.c =================================================================== RCS file: /home/chs/netbsd/cvs/src/sys/arch/x68k/dev/grf.c,v retrieving revision 1.44 diff -u -p -r1.44 grf.c --- sys/arch/x68k/dev/grf.c 25 Jul 2014 08:10:35 -0000 1.44 +++ sys/arch/x68k/dev/grf.c 21 Nov 2014 02:46:27 -0000 @@ -66,6 +66,7 @@ __KERNEL_RCSID(0, "$NetBSD: grf.c,v 1.44 #include #include +#include #include #include @@ -266,9 +267,8 @@ int grfmap(dev_t dev, void **addrp, struct proc *p) { struct grf_softc *gp = device_lookup_private(&grf_cd, GRFUNIT(dev)); - int len, error; - struct vnode vn; - int flags; + size_t len; + int error; #ifdef DEBUG if (grfdebug & GDB_MMAP) @@ -276,19 +276,8 @@ grfmap(dev_t dev, void **addrp, struct p #endif len = gp->g_display.gd_regsize + gp->g_display.gd_fbsize; - flags = MAP_SHARED; - if (*addrp) - flags |= MAP_FIXED; - else - *addrp = (void *)p->p_emul->e_vm_default_addr(p, - (vaddr_t)p->p_vmspace->vm_daddr, len); - - vn.v_type = VCHR; /* XXX */ - vn.v_rdev = dev; /* XXX */ - error = uvm_mmap(&p->p_vmspace->vm_map, (vaddr_t *)addrp, - (vsize_t)len, VM_PROT_ALL, VM_PROT_ALL, - flags, (void *)&vn, 0, - p->p_rlimit[RLIMIT_MEMLOCK].rlim_cur); + + error = uvm_mmap_dev(p, addrp, len, dev, 0); if (error == 0) (void) (*gp->g_sw->gd_mode)(gp, GM_MAP, *addrp); Index: sys/external/bsd/drm2/drm/drm_drv.c =================================================================== RCS file: /home/chs/netbsd/cvs/src/sys/external/bsd/drm2/drm/drm_drv.c,v retrieving revision 1.10 diff -u -p -r1.10 drm_drv.c --- sys/external/bsd/drm2/drm/drm_drv.c 4 Nov 2014 11:27:31 -0000 1.10 +++ sys/external/bsd/drm2/drm/drm_drv.c 19 Nov 2014 17:05:26 -0000 @@ -72,11 +72,12 @@ static int drm_poll(struct file *, int); static int drm_kqfilter(struct file *, struct knote *); static int drm_stat(struct file *, struct stat *); static int drm_ioctl(struct file *, unsigned long, void *); +static int drm_fop_mmap(struct file *, off_t *, size_t, int, int *, int *, + struct uvm_object **, int *); static int drm_version_string(char *, size_t *, const char *); static paddr_t drm_mmap(dev_t, off_t, int); static drm_ioctl_t drm_version; -static drm_ioctl_t drm_mmap_ioctl; #define DRM_IOCTL_DEF(IOCTL, FUNC, FLAGS) \ [DRM_IOCTL_NR(IOCTL)] = { \ @@ -215,10 +216,6 @@ static const struct drm_ioctl_desc drm_i DRM_IOCTL_DEF(DRM_IOCTL_MODE_OBJ_GETPROPERTIES, drm_mode_obj_get_properties_ioctl, DRM_CONTROL_ALLOW|DRM_UNLOCKED), DRM_IOCTL_DEF(DRM_IOCTL_MODE_OBJ_SETPROPERTY, drm_mode_obj_set_property_ioctl, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED), DRM_IOCTL_DEF(DRM_IOCTL_MODE_CURSOR2, drm_mode_cursor2_ioctl, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED), - -#ifdef __NetBSD__ - DRM_IOCTL_DEF(DRM_IOCTL_MMAP, drm_mmap_ioctl, DRM_UNLOCKED), -#endif }; const struct cdevsw drm_cdevsw = { @@ -247,6 +244,7 @@ static const struct fileops drm_fileops .fo_close = drm_close, .fo_kqfilter = drm_kqfilter, .fo_restart = fnullop_restart, + .fo_mmap = drm_fop_mmap, }; static int @@ -669,6 +667,22 @@ drm_ioctl(struct file *fp, unsigned long } static int +drm_fop_mmap(struct file *fp, off_t *offp, size_t len, int prot, int *flagsp, + int *advicep, struct uvm_object **uobjp, int *maxprotp) +{ + struct drm_file *const file = fp->f_data; + struct drm_device *const dev = file->minor->dev; + int error; + + KASSERT(fp == file->filp); + error = (*dev->driver->mmap_object)(dev, *offp, len, prot, uobjp, + offp, file->filp); + *maxprotp = prot; + *advicep = UVM_ADV_RANDOM; + return -error; +} + +static int drm_version_string(char *target, size_t *lenp, const char *source) { const size_t len = strlen(source); @@ -722,66 +736,6 @@ drm_mmap(dev_t d, off_t offset, int prot return paddr; } -static int -drm_mmap_ioctl(struct drm_device *dev, void *data, struct drm_file *file) -{ - struct drm_mmap *const args = data; - void *addr = args->dnm_addr; - const size_t size = args->dnm_size; - const int prot = args->dnm_prot; - const int flags = args->dnm_flags; - const off_t offset = args->dnm_offset; - struct uvm_object *uobj; - voff_t uoffset; - const vm_prot_t vm_maxprot = (VM_PROT_READ | VM_PROT_WRITE); - vm_prot_t vm_prot; - int uvmflag; - vaddr_t align, vaddr; - int ret; - - /* XXX Copypasta from drm_gem_mmap. */ - if (drm_device_is_unplugged(dev)) - return -ENODEV; - - if (prot != (prot & (PROT_READ | PROT_WRITE))) - return -EACCES; - if (flags != MAP_SHARED) - return -EINVAL; - if (offset != (offset & ~(PAGE_SIZE-1))) - return -EINVAL; - if (size != (size & ~(PAGE_SIZE-1))) - return -EINVAL; - (void)addr; /* XXX ignore -- no MAP_FIXED for now */ - - ret = (*dev->driver->mmap_object)(dev, offset, size, prot, &uobj, - &uoffset, file->filp); - if (ret) - return ret; - if (uobj == NULL) - return -EINVAL; - - vm_prot = ((ISSET(prot, PROT_READ)? VM_PROT_READ : 0) | - (ISSET(prot, PROT_WRITE)? VM_PROT_WRITE : 0)); - KASSERT(vm_prot == (vm_prot & vm_maxprot)); - uvmflag = UVM_MAPFLAG(vm_prot, vm_maxprot, UVM_INH_COPY, - UVM_ADV_RANDOM, 0); - - align = 0; /* XXX */ - vaddr = (*curproc->p_emul->e_vm_default_addr)(curproc, - (vaddr_t)curproc->p_vmspace->vm_daddr, size); - /* XXX errno NetBSD->Linux */ - ret = -uvm_map(&curproc->p_vmspace->vm_map, &vaddr, size, uobj, - uoffset, align, uvmflag); - if (ret) { - (*uobj->pgops->pgo_detach)(uobj); - return ret; - } - - /* Success! */ - args->dnm_addr = (void *)vaddr; - return 0; -} - static const struct drm_agp_hooks *volatile drm_current_agp_hooks; int Index: sys/external/bsd/drm2/drm/drm_vm.c =================================================================== RCS file: /home/chs/netbsd/cvs/src/sys/external/bsd/drm2/drm/drm_vm.c,v retrieving revision 1.5 diff -u -p -r1.5 drm_vm.c --- sys/external/bsd/drm2/drm/drm_vm.c 26 Jul 2014 21:15:45 -0000 1.5 +++ sys/external/bsd/drm2/drm/drm_vm.c 19 Nov 2014 16:30:51 -0000 @@ -59,7 +59,7 @@ drm_mmap_object(struct drm_device *dev, * access checks; offset does not become a base address for the * subsequent uvm_map, hence we set *uoffsetp to offset, not 0. */ - uobj = udv_attach(&devno, prot, offset, size); + uobj = udv_attach(devno, prot, offset, size); if (uobj == NULL) return -EINVAL; Index: sys/external/bsd/drm2/include/linux/mm.h =================================================================== RCS file: /home/chs/netbsd/cvs/src/sys/external/bsd/drm2/include/linux/mm.h,v retrieving revision 1.3 diff -u -p -r1.3 mm.h --- sys/external/bsd/drm2/include/linux/mm.h 16 Jul 2014 20:59:58 -0000 1.3 +++ sys/external/bsd/drm2/include/linux/mm.h 21 Nov 2014 02:45:41 -0000 @@ -38,8 +38,9 @@ #include #include +#include + #include -#include #include @@ -82,8 +83,8 @@ static inline unsigned long vm_mmap(struct file *file, unsigned long base, unsigned long size, unsigned long prot, unsigned long flags, unsigned long token) { - struct vnode *vnode; - vaddr_t addr; + struct vnode *vp; + void *addr; int error; /* @@ -96,38 +97,19 @@ vm_mmap(struct file *file, unsigned long KASSERT(flags == MAP_SHARED); KASSERT(file->f_type == DTYPE_VNODE); - vnode = file->f_data; + vp = file->f_data; - KASSERT(vnode->v_type == VCHR); + KASSERT(vp->v_type == VCHR); KASSERT((file->f_flag & (FREAD | FWRITE)) == (FREAD | FWRITE)); - { - struct vattr va; - - vn_lock(vnode, (LK_SHARED | LK_RETRY)); - error = VOP_GETATTR(vnode, &va, kauth_cred_get()); - VOP_UNLOCK(vnode); - if (error) - goto out; - /* XXX kassert? */ - if ((va.va_flags & (SF_SNAPSHOT | IMMUTABLE | APPEND)) != 0) { - error = EACCES; - goto out; - } - } - /* XXX pax_mprotect? pax_aslr? */ - addr = (*curproc->p_emul->e_vm_default_addr)(curproc, - (vaddr_t)curproc->p_vmspace->vm_daddr, size); - error = uvm_mmap(&curproc->p_vmspace->vm_map, &addr, size, - (VM_PROT_READ | VM_PROT_WRITE), (VM_PROT_READ | VM_PROT_WRITE), - MAP_SHARED, vnode, base, - curproc->p_rlimit[RLIMIT_MEMLOCK].rlim_cur); + addr = NULL; + error = uvm_mmap_dev(curproc, &addr, size, vp->v_rdev, (off_t)base); if (error) goto out; - KASSERT(addr <= -1024UL); /* XXX Kludgerosity! */ + KASSERT((uintptr_t)addr <= -1024UL); /* XXX Kludgerosity! */ out: /* XXX errno NetBSD->Linux (kludgerific) */ return (error? (-error) : (unsigned long)addr);