Loading drivers/char/adsprpc.c +345 −77 Original line number Diff line number Diff line Loading @@ -863,16 +863,22 @@ static int fastrpc_alloc_cma_memory(dma_addr_t *region_phys, void **vaddr, return 0; } static int fastrpc_mmap_remove(struct fastrpc_file *fl, uintptr_t va, static int fastrpc_mmap_remove(struct fastrpc_file *fl, int fd, uintptr_t va, size_t len, struct fastrpc_mmap **ppmap) { struct fastrpc_mmap *match = NULL, *map; struct hlist_node *n; struct fastrpc_apps *me = &gfa; /* * Search for a mapping by matching fd, remote address and length. * For backward compatibility, search for a mapping by matching is * limited to remote address and length when passed fd < 0. */ spin_lock(&me->hlock); hlist_for_each_entry_safe(map, n, &me->maps, hn) { if (map->raddr == va && if ((fd < 0 || map->fd == fd) && map->raddr == va && map->raddr + map->len == va + len && map->refs == 1) { match = map; Loading @@ -886,7 +892,7 @@ static int fastrpc_mmap_remove(struct fastrpc_file *fl, uintptr_t va, return 0; } hlist_for_each_entry_safe(map, n, &fl->maps, hn) { if (map->raddr == va && if ((fd < 0 || map->fd == fd) && map->raddr == va && map->raddr + map->len == va + len && map->refs == 1) { match = map; Loading @@ -898,7 +904,7 @@ static int fastrpc_mmap_remove(struct fastrpc_file *fl, uintptr_t va, *ppmap = match; return 0; } return -ENOTTY; return -ETOOMANYREFS; } static void fastrpc_mmap_free(struct fastrpc_mmap *map, uint32_t flags) Loading Loading @@ -3353,6 +3359,106 @@ static int fastrpc_release_current_dsp_process(struct fastrpc_file *fl) return err; } static int fastrpc_mem_map_to_dsp(struct fastrpc_file *fl, int fd, int offset, uint32_t flags, uintptr_t va, uint64_t phys, size_t size, uintptr_t *raddr) { struct fastrpc_ioctl_invoke_async ioctl; struct smq_phy_page page; remote_arg_t ra[4]; int err = 0; struct { int pid; int fd; int offset; uint32_t flags; uint64_t vaddrin; int num; int data_len; } inargs; struct { uint64_t vaddrout; } routargs; inargs.pid = fl->tgid; inargs.fd = fd; inargs.offset = offset; inargs.vaddrin = (uintptr_t)va; inargs.flags = flags; inargs.num = sizeof(page); inargs.data_len = 0; ra[0].buf.pv = (void *)&inargs; ra[0].buf.len = sizeof(inargs); page.addr = phys; page.size = size; ra[1].buf.pv = (void *)&page; ra[1].buf.len = sizeof(page); ra[2].buf.pv = (void *)&page; ra[2].buf.len = 0; ra[3].buf.pv = (void *)&routargs; ra[3].buf.len = sizeof(routargs); ioctl.inv.handle = FASTRPC_STATIC_HANDLE_PROCESS_GROUP; ioctl.inv.sc = REMOTE_SCALARS_MAKE(10, 3, 1); ioctl.inv.pra = ra; ioctl.fds = NULL; ioctl.attrs = NULL; ioctl.crc = NULL; ioctl.job = NULL; VERIFY(err, 0 == (err = fastrpc_internal_invoke(fl, FASTRPC_MODE_PARALLEL, 1, &ioctl))); if (err) goto bail; if (raddr) *raddr = (uintptr_t)routargs.vaddrout; bail: if (err) { pr_err("adsprpc: %s failed. err 0x%x fd %d len 0x%x\n", __func__, err, fd, size); } return err; } static int fastrpc_mem_unmap_to_dsp(struct fastrpc_file *fl, int fd, uint32_t flags, uintptr_t va, uint64_t phys, size_t size) { struct fastrpc_ioctl_invoke_async ioctl; remote_arg_t ra[1]; int err = 0; struct { int pid; int fd; uint64_t vaddrin; uint64_t len; } inargs; inargs.pid = fl->tgid; inargs.fd = fd; inargs.vaddrin = (uint64_t)va; inargs.len = (uint64_t)size; ra[0].buf.pv = (void *)&inargs; ra[0].buf.len = sizeof(inargs); ioctl.inv.handle = FASTRPC_STATIC_HANDLE_PROCESS_GROUP; ioctl.inv.sc = REMOTE_SCALARS_MAKE(11, 1, 0); ioctl.inv.pra = ra; ioctl.fds = NULL; ioctl.attrs = NULL; ioctl.crc = NULL; ioctl.job = NULL; VERIFY(err, 0 == (err = fastrpc_internal_invoke(fl, FASTRPC_MODE_PARALLEL, 1, &ioctl))); if (err) goto bail; bail: if (err) { pr_err("adsprpc: %s failed. err 0x%x fd %d len 0x%x\n", __func__, err, fd, size); } return err; } static int fastrpc_unmap_on_dsp(struct fastrpc_file *fl, uintptr_t raddr, uint64_t phys, size_t size, uint32_t flags) { Loading Loading @@ -3686,7 +3792,7 @@ static int fastrpc_internal_munmap(struct fastrpc_file *fl, } mutex_lock(&fl->map_mutex); VERIFY(err, !fastrpc_mmap_remove(fl, ud->vaddrout, ud->size, &map)); VERIFY(err, !fastrpc_mmap_remove(fl, -1, ud->vaddrout, ud->size, &map)); mutex_unlock(&fl->map_mutex); if (err) goto bail; Loading Loading @@ -3739,6 +3845,106 @@ static int fastrpc_internal_munmap_fd(struct fastrpc_file *fl, return err; } static int fastrpc_internal_mem_map(struct fastrpc_file *fl, struct fastrpc_ioctl_mem_map *ud) { int err = 0; struct fastrpc_mmap *map = NULL; VERIFY(err, fl->dsp_proc_init == 1); if (err) { pr_err("adsprpc: ERROR: %s: user application %s trying to map without initialization\n", __func__, current->comm); err = EBADR; goto bail; } /* create SMMU mapping */ mutex_lock(&fl->map_mutex); VERIFY(err, !fastrpc_mmap_create(fl, ud->m.fd, ud->m.attrs, ud->m.vaddrin, ud->m.length, ud->m.flags, &map)); mutex_unlock(&fl->map_mutex); if (err) goto bail; if (map->raddr) { err = -EEXIST; goto bail; } /* create DSP mapping */ VERIFY(err, !(err = fastrpc_mem_map_to_dsp(fl, ud->m.fd, ud->m.offset, ud->m.flags, map->va, map->phys, ud->m.length, &map->raddr))); if (err) goto bail; ud->m.vaddrout = map->raddr; bail: if (err) { pr_err("adsprpc: %s failed to map fd %d flags %d err %d\n", __func__, ud->m.fd, ud->m.flags, err); if (map) { mutex_lock(&fl->map_mutex); fastrpc_mmap_free(map, 0); mutex_unlock(&fl->map_mutex); } } return err; } static int fastrpc_internal_mem_unmap(struct fastrpc_file *fl, struct fastrpc_ioctl_mem_unmap *ud) { int err = 0; struct fastrpc_mmap *map = NULL; VERIFY(err, fl->dsp_proc_init == 1); if (err) { pr_err("adsprpc: ERROR: %s: user application %s trying to map without initialization\n", __func__, current->comm); err = EBADR; goto bail; } mutex_lock(&fl->map_mutex); VERIFY(err, !fastrpc_mmap_remove(fl, ud->um.fd, (uintptr_t)ud->um.vaddr, ud->um.length, &map)); mutex_unlock(&fl->map_mutex); if (err) goto bail; VERIFY(err, map->flags == FASTRPC_MAP_FD || map->flags == FASTRPC_MAP_FD_DELAYED || map->flags == FASTRPC_MAP_STATIC); if (err) { err = -EBADMSG; goto bail; } /* remove mapping on DSP */ VERIFY(err, !(err = fastrpc_mem_unmap_to_dsp(fl, map->fd, map->flags, map->raddr, map->phys, map->size))); if (err) goto bail; /* remove SMMU mapping */ mutex_lock(&fl->map_mutex); fastrpc_mmap_free(map, 0); mutex_unlock(&fl->map_mutex); map = NULL; bail: if (err) { pr_err("adsprpc: %s failed to unmap fd %d addr 0x%llx length 0x%x err 0x%x\n", __func__, ud->um.fd, ud->um.vaddr, ud->um.length, err); /* Add back to map list in case of error to unmap on DSP */ if (map) { mutex_lock(&fl->map_mutex); fastrpc_mmap_add(map); mutex_unlock(&fl->map_mutex); } } return err; } static int fastrpc_internal_mmap(struct fastrpc_file *fl, struct fastrpc_ioctl_mmap *ud) Loading Loading @@ -4735,11 +4941,10 @@ static int fastrpc_get_dsp_info( return err; } static long fastrpc_device_ioctl(struct file *file, unsigned int ioctl_num, unsigned long ioctl_param) { union { union fastrpc_ioctl_param { struct fastrpc_ioctl_invoke_async inv; struct fastrpc_ioctl_mem_map mem_map; struct fastrpc_ioctl_mem_unmap mem_unmap; struct fastrpc_ioctl_mmap mmap; struct fastrpc_ioctl_mmap_64 mmap64; struct fastrpc_ioctl_munmap munmap; Loading @@ -4750,11 +4955,116 @@ static long fastrpc_device_ioctl(struct file *file, unsigned int ioctl_num, struct fastrpc_ioctl_control cp; struct fastrpc_ioctl_capability cap; struct fastrpc_ioctl_invoke2 inv2; } p; }; static inline int fastrpc_mmap_device_ioctl(struct fastrpc_file *fl, unsigned int ioctl_num, union fastrpc_ioctl_param *p, void *param) { union { struct fastrpc_ioctl_mmap mmap; struct fastrpc_ioctl_munmap munmap; } i; int err = 0; switch (ioctl_num) { case FASTRPC_IOCTL_MEM_MAP: K_COPY_FROM_USER(err, 0, &p->mem_map, param, sizeof(p->mem_map)); if (err) goto bail; VERIFY(err, 0 == (err = fastrpc_internal_mem_map(fl, &p->mem_map))); if (err) goto bail; K_COPY_TO_USER(err, 0, param, &p->mem_map, sizeof(p->mem_map)); if (err) goto bail; break; case FASTRPC_IOCTL_MEM_UNMAP: K_COPY_FROM_USER(err, 0, &p->mem_unmap, param, sizeof(p->mem_unmap)); if (err) goto bail; VERIFY(err, 0 == (err = fastrpc_internal_mem_unmap(fl, &p->mem_unmap))); if (err) goto bail; K_COPY_TO_USER(err, 0, param, &p->mem_unmap, sizeof(p->mem_unmap)); if (err) goto bail; break; case FASTRPC_IOCTL_MMAP: K_COPY_FROM_USER(err, 0, &p->mmap, param, sizeof(p->mmap)); if (err) goto bail; VERIFY(err, 0 == (err = fastrpc_internal_mmap(fl, &p->mmap))); if (err) goto bail; K_COPY_TO_USER(err, 0, param, &p->mmap, sizeof(p->mmap)); if (err) goto bail; break; case FASTRPC_IOCTL_MUNMAP: K_COPY_FROM_USER(err, 0, &p->munmap, param, sizeof(p->munmap)); if (err) goto bail; VERIFY(err, 0 == (err = fastrpc_internal_munmap(fl, &p->munmap))); if (err) goto bail; break; case FASTRPC_IOCTL_MMAP_64: K_COPY_FROM_USER(err, 0, &p->mmap64, param, sizeof(p->mmap64)); if (err) goto bail; get_fastrpc_ioctl_mmap_64(&p->mmap64, &i.mmap); VERIFY(err, 0 == (err = fastrpc_internal_mmap(fl, &i.mmap))); if (err) goto bail; put_fastrpc_ioctl_mmap_64(&p->mmap64, &i.mmap); K_COPY_TO_USER(err, 0, param, &p->mmap64, sizeof(p->mmap64)); if (err) goto bail; break; case FASTRPC_IOCTL_MUNMAP_64: K_COPY_FROM_USER(err, 0, &p->munmap64, param, sizeof(p->munmap64)); if (err) goto bail; get_fastrpc_ioctl_munmap_64(&p->munmap64, &i.munmap); VERIFY(err, 0 == (err = fastrpc_internal_munmap(fl, &i.munmap))); if (err) goto bail; break; case FASTRPC_IOCTL_MUNMAP_FD: K_COPY_FROM_USER(err, 0, &p->munmap_fd, param, sizeof(p->munmap_fd)); if (err) goto bail; VERIFY(err, 0 == (err = fastrpc_internal_munmap_fd(fl, &p->munmap_fd))); if (err) goto bail; break; default: err = -ENOTTY; pr_info("bad ioctl: %d\n", ioctl_num); break; } bail: return err; } static long fastrpc_device_ioctl(struct file *file, unsigned int ioctl_num, unsigned long ioctl_param) { union fastrpc_ioctl_param p; void *param = (char *)ioctl_param; struct fastrpc_file *fl = (struct fastrpc_file *)file->private_data; int size = 0, err = 0; Loading Loading @@ -4811,63 +5121,6 @@ static long fastrpc_device_ioctl(struct file *file, unsigned int ioctl_num, if (err) goto bail; break; case FASTRPC_IOCTL_MMAP: K_COPY_FROM_USER(err, 0, &p.mmap, param, sizeof(p.mmap)); if (err) goto bail; VERIFY(err, 0 == (err = fastrpc_internal_mmap(fl, &p.mmap))); if (err) goto bail; K_COPY_TO_USER(err, 0, param, &p.mmap, sizeof(p.mmap)); if (err) goto bail; break; case FASTRPC_IOCTL_MUNMAP: K_COPY_FROM_USER(err, 0, &p.munmap, param, sizeof(p.munmap)); if (err) goto bail; VERIFY(err, 0 == (err = fastrpc_internal_munmap(fl, &p.munmap))); if (err) goto bail; break; case FASTRPC_IOCTL_MMAP_64: K_COPY_FROM_USER(err, 0, &p.mmap64, param, sizeof(p.mmap64)); if (err) goto bail; get_fastrpc_ioctl_mmap_64(&p.mmap64, &i.mmap); VERIFY(err, 0 == (err = fastrpc_internal_mmap(fl, &i.mmap))); if (err) goto bail; put_fastrpc_ioctl_mmap_64(&p.mmap64, &i.mmap); K_COPY_TO_USER(err, 0, param, &p.mmap64, sizeof(p.mmap64)); if (err) goto bail; break; case FASTRPC_IOCTL_MUNMAP_64: K_COPY_FROM_USER(err, 0, &p.munmap64, param, sizeof(p.munmap64)); if (err) goto bail; get_fastrpc_ioctl_munmap_64(&p.munmap64, &i.munmap); VERIFY(err, 0 == (err = fastrpc_internal_munmap(fl, &i.munmap))); if (err) goto bail; break; case FASTRPC_IOCTL_MUNMAP_FD: K_COPY_FROM_USER(err, 0, &p.munmap_fd, param, sizeof(p.munmap_fd)); if (err) goto bail; VERIFY(err, 0 == (err = fastrpc_internal_munmap_fd(fl, &p.munmap_fd))); if (err) goto bail; break; case FASTRPC_IOCTL_SETMODE: err = fastrpc_setmode(ioctl_param, fl); break; Loading Loading @@ -4906,6 +5159,21 @@ static long fastrpc_device_ioctl(struct file *file, unsigned int ioctl_num, case FASTRPC_IOCTL_GET_DSP_INFO: err = fastrpc_get_dsp_info(&p.cap, param, fl); break; case FASTRPC_IOCTL_MEM_MAP: /* fall through */ case FASTRPC_IOCTL_MEM_UNMAP: /* fall through */ case FASTRPC_IOCTL_MMAP: /* fall through */ case FASTRPC_IOCTL_MUNMAP: /* fall through */ case FASTRPC_IOCTL_MMAP_64: /* fall through */ case FASTRPC_IOCTL_MUNMAP_64: /* fall through */ case FASTRPC_IOCTL_MUNMAP_FD: err = fastrpc_mmap_device_ioctl(fl, ioctl_num, &p, param); break; default: err = -ENOTTY; pr_info("bad ioctl: %d\n", ioctl_num); Loading drivers/char/adsprpc_compat.c +180 −12 Original line number Diff line number Diff line Loading @@ -39,6 +39,10 @@ struct compat_fastrpc_ioctl_capability) #define COMPAT_FASTRPC_IOCTL_INVOKE2 \ _IOWR('R', 18, struct compat_fastrpc_ioctl_invoke2) #define COMPAT_FASTRPC_IOCTL_MEM_MAP \ _IOWR('R', 19, struct compat_fastrpc_ioctl_mem_map) #define COMPAT_FASTRPC_IOCTL_MEM_UNMAP \ _IOWR('R', 20, struct compat_fastrpc_ioctl_mem_unmap) struct compat_remote_buf { compat_uptr_t pv; /* buffer pointer */ Loading Loading @@ -89,6 +93,38 @@ struct compat_fastrpc_ioctl_invoke2 { compat_int_t err; /* reserved */ }; struct compat_fastrpc_mem_map { compat_int_t fd; /* ion fd */ compat_int_t offset; /* buffer offset */ compat_uint_t flags; /* flags to control memory map */ compat_uint_t attrs; /* buffer attributes used for SMMU mapping */ compat_uptr_t vaddrin; /* virtual address */ compat_size_t length; /* buffer length */ compat_u64 vaddrout; /* dsp virtual address */ }; struct compat_fastrpc_ioctl_mem_map { compat_int_t version; union { struct compat_fastrpc_mem_map m; compat_int_t reserved[MAP_RESERVED_NUM]; }; }; struct compat_fastrpc_mem_unmap { compat_int_t fd; /* ion fd */ compat_u64 vaddr; /* dsp virtual address */ compat_size_t length; /* buffer length */ }; struct compat_fastrpc_ioctl_mem_unmap { compat_int_t version; union { struct compat_fastrpc_mem_unmap um; compat_int_t reserved[UNMAP_RESERVED_NUM]; }; }; struct compat_fastrpc_ioctl_mmap { compat_int_t fd; /* ion fd */ compat_uint_t flags; /* flags for dsp to map with */ Loading Loading @@ -372,6 +408,74 @@ static int compat_fastrpc_ioctl_invoke2(struct file *filp, FASTRPC_IOCTL_INVOKE2, (unsigned long)inv); } static int compat_get_fastrpc_ioctl_mem_map( struct compat_fastrpc_ioctl_mem_map __user *map32, struct fastrpc_ioctl_mem_map __user *map) { compat_uint_t u; compat_int_t i; compat_size_t s; compat_uptr_t p; int err; err = get_user(i, &map32->version); if (err || i != 0) return -EINVAL; err = put_user(i, &map->version); err |= get_user(i, &map32->m.fd); err |= put_user(i, &map->m.fd); err |= get_user(i, &map32->m.offset); err |= put_user(i, &map->m.offset); err |= get_user(u, &map32->m.flags); err |= put_user(u, &map->m.flags); err |= get_user(p, &map32->m.vaddrin); err |= put_user(p, &map->m.vaddrin); err |= get_user(s, &map32->m.length); err |= put_user(s, &map->m.length); err |= get_user(u, &map32->m.attrs); err |= put_user(u, &map->m.attrs); return err; } static int compat_put_fastrpc_ioctl_mem_map( struct compat_fastrpc_ioctl_mem_map __user *map32, struct fastrpc_ioctl_mem_map __user *map) { compat_u64 p; int err; err = get_user(p, &map->m.vaddrout); err |= put_user(p, &map32->m.vaddrout); return err; } static int compat_get_fastrpc_ioctl_mem_unmap( struct compat_fastrpc_ioctl_mem_unmap __user *unmap32, struct fastrpc_ioctl_mem_unmap __user *unmap) { compat_int_t i; compat_size_t s; compat_u64 p; int err; err = get_user(i, &unmap32->version); if (err || i != 0) return -EINVAL; err = put_user(i, &unmap->version); err |= get_user(i, &unmap32->um.fd); err |= put_user(i, &unmap->um.fd); err |= get_user(p, &unmap32->um.vaddr); err |= put_user(p, &unmap->um.vaddr); err |= get_user(s, &unmap32->um.length); err |= put_user(s, &unmap->um.length); return err; } static int compat_get_fastrpc_ioctl_mmap( struct compat_fastrpc_ioctl_mmap __user *map32, struct fastrpc_ioctl_mmap __user *map) Loading Loading @@ -661,25 +765,54 @@ static int compat_fastrpc_get_dsp_info(struct file *filp, return err; } long compat_fastrpc_device_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) static inline long compat_fastrpc_mmap_device_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) { int err = 0; if (!filp->f_op || !filp->f_op->unlocked_ioctl) return -ENOTTY; switch (cmd) { case COMPAT_FASTRPC_IOCTL_INVOKE: case COMPAT_FASTRPC_IOCTL_INVOKE_FD: case COMPAT_FASTRPC_IOCTL_INVOKE_ATTRS: case COMPAT_FASTRPC_IOCTL_INVOKE_CRC: case COMPAT_FASTRPC_IOCTL_MEM_MAP: { return compat_fastrpc_ioctl_invoke(filp, cmd, arg); struct compat_fastrpc_ioctl_mem_map __user *map32; struct fastrpc_ioctl_mem_map __user *map; long ret; map32 = compat_ptr(arg); map = compat_alloc_user_space(sizeof(*map)); if (map == NULL) return -EFAULT; err = compat_get_fastrpc_ioctl_mem_map(map32, map); if (err) return err; ret = filp->f_op->unlocked_ioctl(filp, FASTRPC_IOCTL_MEM_MAP, (unsigned long)map); if (ret) return ret; VERIFY(err, 0 == compat_put_fastrpc_ioctl_mem_map(map32, map)); return err; } case COMPAT_FASTRPC_IOCTL_INVOKE2: case COMPAT_FASTRPC_IOCTL_MEM_UNMAP: { return compat_fastrpc_ioctl_invoke2(filp, cmd, arg); struct compat_fastrpc_ioctl_mem_unmap __user *unmap32; struct fastrpc_ioctl_mem_unmap __user *unmap; long ret; unmap32 = compat_ptr(arg); unmap = compat_alloc_user_space(sizeof(*unmap)); if (unmap == NULL) return -EFAULT; err = compat_get_fastrpc_ioctl_mem_unmap(unmap32, unmap); if (err) return err; ret = filp->f_op->unlocked_ioctl(filp, FASTRPC_IOCTL_MEM_UNMAP, (unsigned long)unmap); if (ret) return ret; return err; } case COMPAT_FASTRPC_IOCTL_MMAP: { Loading Loading @@ -740,6 +873,31 @@ long compat_fastrpc_device_ioctl(struct file *filp, unsigned int cmd, return filp->f_op->unlocked_ioctl(filp, FASTRPC_IOCTL_MUNMAP, (unsigned long)unmap); } default: return -ENOIOCTLCMD; } } long compat_fastrpc_device_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) { int err = 0; if (!filp->f_op || !filp->f_op->unlocked_ioctl) return -ENOTTY; switch (cmd) { case COMPAT_FASTRPC_IOCTL_INVOKE: case COMPAT_FASTRPC_IOCTL_INVOKE_FD: case COMPAT_FASTRPC_IOCTL_INVOKE_ATTRS: case COMPAT_FASTRPC_IOCTL_INVOKE_CRC: { return compat_fastrpc_ioctl_invoke(filp, cmd, arg); } case COMPAT_FASTRPC_IOCTL_INVOKE2: { return compat_fastrpc_ioctl_invoke2(filp, cmd, arg); } case COMPAT_FASTRPC_IOCTL_MUNMAP_64: { struct compat_fastrpc_ioctl_munmap_64 __user *unmap32; Loading Loading @@ -814,6 +972,16 @@ long compat_fastrpc_device_ioctl(struct file *filp, unsigned int cmd, { return compat_fastrpc_get_dsp_info(filp, arg); } case COMPAT_FASTRPC_IOCTL_MEM_MAP: /* fall through */ case COMPAT_FASTRPC_IOCTL_MEM_UNMAP: /* fall through */ case COMPAT_FASTRPC_IOCTL_MMAP: /* fall through */ case COMPAT_FASTRPC_IOCTL_MMAP_64: /* fall through */ case COMPAT_FASTRPC_IOCTL_MUNMAP: return compat_fastrpc_mmap_device_ioctl(filp, cmd, arg); default: return -ENOIOCTLCMD; } Loading drivers/char/adsprpc_shared.h +73 −1 Original line number Diff line number Diff line Loading @@ -26,7 +26,8 @@ #define FASTRPC_IOCTL_GET_DSP_INFO \ _IOWR('R', 17, struct fastrpc_ioctl_capability) #define FASTRPC_IOCTL_INVOKE2 _IOWR('R', 18, struct fastrpc_ioctl_invoke2) #define FASTRPC_IOCTL_MEM_MAP _IOWR('R', 19, struct fastrpc_ioctl_mem_map) #define FASTRPC_IOCTL_MEM_UNMAP _IOWR('R', 20, struct fastrpc_ioctl_mem_unmap) #define FASTRPC_GLINK_GUID "fastrpcglink-apps-dsp" #define FASTRPC_SMD_GUID "fastrpcsmd-apps-dsp" Loading Loading @@ -271,6 +272,77 @@ struct fastrpc_ioctl_munmap_fd { ssize_t len; /* length */ }; /** * Control flags for mapping memory on DSP user process */ enum fastrpc_map_flags { /** * Map memory pages with RW- permission and CACHE WRITEBACK. * The driver is responsible for cache maintenance when passed * the buffer to FastRPC calls. Same virtual address will be * assigned for subsequent FastRPC calls. */ FASTRPC_MAP_STATIC = 0, /* Reserved */ FASTRPC_MAP_RESERVED, /** * Map memory pages with RW- permission and CACHE WRITEBACK. * Mapping tagged with a file descriptor. User is responsible for * CPU and DSP cache maintenance for the buffer. Get virtual address * of buffer on DSP using HAP_mmap_get() and HAP_mmap_put() APIs. */ FASTRPC_MAP_FD = 2, /** * Mapping delayed until user call HAP_mmap() and HAP_munmap() * functions on DSP. It is useful to map a buffer with cache modes * other than default modes. User is responsible for CPU and DSP * cache maintenance for the buffer. */ FASTRPC_MAP_FD_DELAYED, FASTRPC_MAP_MAX, }; struct fastrpc_mem_map { int fd; /* ion fd */ int offset; /* buffer offset */ uint32_t flags; /* flags defined in enum fastrpc_map_flags */ int attrs; /* buffer attributes used for SMMU mapping */ uintptr_t vaddrin; /* buffer virtual address */ size_t length; /* buffer length */ uint64_t vaddrout; /* [out] remote virtual address */ }; /* Map and unmap IOCTL methods reserved memory size for future extensions */ #define MAP_RESERVED_NUM (14) #define UNMAP_RESERVED_NUM (10) /* map memory to DSP device */ struct fastrpc_ioctl_mem_map { int version; /* Initial version 0 */ union { struct fastrpc_mem_map m; int reserved[MAP_RESERVED_NUM]; }; }; struct fastrpc_mem_unmap { int fd; /* ion fd */ uint64_t vaddr; /* remote process (dsp) virtual address */ size_t length; /* buffer size */ }; /* unmap memory to DSP device */ struct fastrpc_ioctl_mem_unmap { int version; /* Initial version 0 */ union { struct fastrpc_mem_unmap um; int reserved[UNMAP_RESERVED_NUM]; }; }; struct fastrpc_ioctl_perf { /* kernel performance data */ uintptr_t data; uint32_t numkeys; Loading Loading
drivers/char/adsprpc.c +345 −77 Original line number Diff line number Diff line Loading @@ -863,16 +863,22 @@ static int fastrpc_alloc_cma_memory(dma_addr_t *region_phys, void **vaddr, return 0; } static int fastrpc_mmap_remove(struct fastrpc_file *fl, uintptr_t va, static int fastrpc_mmap_remove(struct fastrpc_file *fl, int fd, uintptr_t va, size_t len, struct fastrpc_mmap **ppmap) { struct fastrpc_mmap *match = NULL, *map; struct hlist_node *n; struct fastrpc_apps *me = &gfa; /* * Search for a mapping by matching fd, remote address and length. * For backward compatibility, search for a mapping by matching is * limited to remote address and length when passed fd < 0. */ spin_lock(&me->hlock); hlist_for_each_entry_safe(map, n, &me->maps, hn) { if (map->raddr == va && if ((fd < 0 || map->fd == fd) && map->raddr == va && map->raddr + map->len == va + len && map->refs == 1) { match = map; Loading @@ -886,7 +892,7 @@ static int fastrpc_mmap_remove(struct fastrpc_file *fl, uintptr_t va, return 0; } hlist_for_each_entry_safe(map, n, &fl->maps, hn) { if (map->raddr == va && if ((fd < 0 || map->fd == fd) && map->raddr == va && map->raddr + map->len == va + len && map->refs == 1) { match = map; Loading @@ -898,7 +904,7 @@ static int fastrpc_mmap_remove(struct fastrpc_file *fl, uintptr_t va, *ppmap = match; return 0; } return -ENOTTY; return -ETOOMANYREFS; } static void fastrpc_mmap_free(struct fastrpc_mmap *map, uint32_t flags) Loading Loading @@ -3353,6 +3359,106 @@ static int fastrpc_release_current_dsp_process(struct fastrpc_file *fl) return err; } static int fastrpc_mem_map_to_dsp(struct fastrpc_file *fl, int fd, int offset, uint32_t flags, uintptr_t va, uint64_t phys, size_t size, uintptr_t *raddr) { struct fastrpc_ioctl_invoke_async ioctl; struct smq_phy_page page; remote_arg_t ra[4]; int err = 0; struct { int pid; int fd; int offset; uint32_t flags; uint64_t vaddrin; int num; int data_len; } inargs; struct { uint64_t vaddrout; } routargs; inargs.pid = fl->tgid; inargs.fd = fd; inargs.offset = offset; inargs.vaddrin = (uintptr_t)va; inargs.flags = flags; inargs.num = sizeof(page); inargs.data_len = 0; ra[0].buf.pv = (void *)&inargs; ra[0].buf.len = sizeof(inargs); page.addr = phys; page.size = size; ra[1].buf.pv = (void *)&page; ra[1].buf.len = sizeof(page); ra[2].buf.pv = (void *)&page; ra[2].buf.len = 0; ra[3].buf.pv = (void *)&routargs; ra[3].buf.len = sizeof(routargs); ioctl.inv.handle = FASTRPC_STATIC_HANDLE_PROCESS_GROUP; ioctl.inv.sc = REMOTE_SCALARS_MAKE(10, 3, 1); ioctl.inv.pra = ra; ioctl.fds = NULL; ioctl.attrs = NULL; ioctl.crc = NULL; ioctl.job = NULL; VERIFY(err, 0 == (err = fastrpc_internal_invoke(fl, FASTRPC_MODE_PARALLEL, 1, &ioctl))); if (err) goto bail; if (raddr) *raddr = (uintptr_t)routargs.vaddrout; bail: if (err) { pr_err("adsprpc: %s failed. err 0x%x fd %d len 0x%x\n", __func__, err, fd, size); } return err; } static int fastrpc_mem_unmap_to_dsp(struct fastrpc_file *fl, int fd, uint32_t flags, uintptr_t va, uint64_t phys, size_t size) { struct fastrpc_ioctl_invoke_async ioctl; remote_arg_t ra[1]; int err = 0; struct { int pid; int fd; uint64_t vaddrin; uint64_t len; } inargs; inargs.pid = fl->tgid; inargs.fd = fd; inargs.vaddrin = (uint64_t)va; inargs.len = (uint64_t)size; ra[0].buf.pv = (void *)&inargs; ra[0].buf.len = sizeof(inargs); ioctl.inv.handle = FASTRPC_STATIC_HANDLE_PROCESS_GROUP; ioctl.inv.sc = REMOTE_SCALARS_MAKE(11, 1, 0); ioctl.inv.pra = ra; ioctl.fds = NULL; ioctl.attrs = NULL; ioctl.crc = NULL; ioctl.job = NULL; VERIFY(err, 0 == (err = fastrpc_internal_invoke(fl, FASTRPC_MODE_PARALLEL, 1, &ioctl))); if (err) goto bail; bail: if (err) { pr_err("adsprpc: %s failed. err 0x%x fd %d len 0x%x\n", __func__, err, fd, size); } return err; } static int fastrpc_unmap_on_dsp(struct fastrpc_file *fl, uintptr_t raddr, uint64_t phys, size_t size, uint32_t flags) { Loading Loading @@ -3686,7 +3792,7 @@ static int fastrpc_internal_munmap(struct fastrpc_file *fl, } mutex_lock(&fl->map_mutex); VERIFY(err, !fastrpc_mmap_remove(fl, ud->vaddrout, ud->size, &map)); VERIFY(err, !fastrpc_mmap_remove(fl, -1, ud->vaddrout, ud->size, &map)); mutex_unlock(&fl->map_mutex); if (err) goto bail; Loading Loading @@ -3739,6 +3845,106 @@ static int fastrpc_internal_munmap_fd(struct fastrpc_file *fl, return err; } static int fastrpc_internal_mem_map(struct fastrpc_file *fl, struct fastrpc_ioctl_mem_map *ud) { int err = 0; struct fastrpc_mmap *map = NULL; VERIFY(err, fl->dsp_proc_init == 1); if (err) { pr_err("adsprpc: ERROR: %s: user application %s trying to map without initialization\n", __func__, current->comm); err = EBADR; goto bail; } /* create SMMU mapping */ mutex_lock(&fl->map_mutex); VERIFY(err, !fastrpc_mmap_create(fl, ud->m.fd, ud->m.attrs, ud->m.vaddrin, ud->m.length, ud->m.flags, &map)); mutex_unlock(&fl->map_mutex); if (err) goto bail; if (map->raddr) { err = -EEXIST; goto bail; } /* create DSP mapping */ VERIFY(err, !(err = fastrpc_mem_map_to_dsp(fl, ud->m.fd, ud->m.offset, ud->m.flags, map->va, map->phys, ud->m.length, &map->raddr))); if (err) goto bail; ud->m.vaddrout = map->raddr; bail: if (err) { pr_err("adsprpc: %s failed to map fd %d flags %d err %d\n", __func__, ud->m.fd, ud->m.flags, err); if (map) { mutex_lock(&fl->map_mutex); fastrpc_mmap_free(map, 0); mutex_unlock(&fl->map_mutex); } } return err; } static int fastrpc_internal_mem_unmap(struct fastrpc_file *fl, struct fastrpc_ioctl_mem_unmap *ud) { int err = 0; struct fastrpc_mmap *map = NULL; VERIFY(err, fl->dsp_proc_init == 1); if (err) { pr_err("adsprpc: ERROR: %s: user application %s trying to map without initialization\n", __func__, current->comm); err = EBADR; goto bail; } mutex_lock(&fl->map_mutex); VERIFY(err, !fastrpc_mmap_remove(fl, ud->um.fd, (uintptr_t)ud->um.vaddr, ud->um.length, &map)); mutex_unlock(&fl->map_mutex); if (err) goto bail; VERIFY(err, map->flags == FASTRPC_MAP_FD || map->flags == FASTRPC_MAP_FD_DELAYED || map->flags == FASTRPC_MAP_STATIC); if (err) { err = -EBADMSG; goto bail; } /* remove mapping on DSP */ VERIFY(err, !(err = fastrpc_mem_unmap_to_dsp(fl, map->fd, map->flags, map->raddr, map->phys, map->size))); if (err) goto bail; /* remove SMMU mapping */ mutex_lock(&fl->map_mutex); fastrpc_mmap_free(map, 0); mutex_unlock(&fl->map_mutex); map = NULL; bail: if (err) { pr_err("adsprpc: %s failed to unmap fd %d addr 0x%llx length 0x%x err 0x%x\n", __func__, ud->um.fd, ud->um.vaddr, ud->um.length, err); /* Add back to map list in case of error to unmap on DSP */ if (map) { mutex_lock(&fl->map_mutex); fastrpc_mmap_add(map); mutex_unlock(&fl->map_mutex); } } return err; } static int fastrpc_internal_mmap(struct fastrpc_file *fl, struct fastrpc_ioctl_mmap *ud) Loading Loading @@ -4735,11 +4941,10 @@ static int fastrpc_get_dsp_info( return err; } static long fastrpc_device_ioctl(struct file *file, unsigned int ioctl_num, unsigned long ioctl_param) { union { union fastrpc_ioctl_param { struct fastrpc_ioctl_invoke_async inv; struct fastrpc_ioctl_mem_map mem_map; struct fastrpc_ioctl_mem_unmap mem_unmap; struct fastrpc_ioctl_mmap mmap; struct fastrpc_ioctl_mmap_64 mmap64; struct fastrpc_ioctl_munmap munmap; Loading @@ -4750,11 +4955,116 @@ static long fastrpc_device_ioctl(struct file *file, unsigned int ioctl_num, struct fastrpc_ioctl_control cp; struct fastrpc_ioctl_capability cap; struct fastrpc_ioctl_invoke2 inv2; } p; }; static inline int fastrpc_mmap_device_ioctl(struct fastrpc_file *fl, unsigned int ioctl_num, union fastrpc_ioctl_param *p, void *param) { union { struct fastrpc_ioctl_mmap mmap; struct fastrpc_ioctl_munmap munmap; } i; int err = 0; switch (ioctl_num) { case FASTRPC_IOCTL_MEM_MAP: K_COPY_FROM_USER(err, 0, &p->mem_map, param, sizeof(p->mem_map)); if (err) goto bail; VERIFY(err, 0 == (err = fastrpc_internal_mem_map(fl, &p->mem_map))); if (err) goto bail; K_COPY_TO_USER(err, 0, param, &p->mem_map, sizeof(p->mem_map)); if (err) goto bail; break; case FASTRPC_IOCTL_MEM_UNMAP: K_COPY_FROM_USER(err, 0, &p->mem_unmap, param, sizeof(p->mem_unmap)); if (err) goto bail; VERIFY(err, 0 == (err = fastrpc_internal_mem_unmap(fl, &p->mem_unmap))); if (err) goto bail; K_COPY_TO_USER(err, 0, param, &p->mem_unmap, sizeof(p->mem_unmap)); if (err) goto bail; break; case FASTRPC_IOCTL_MMAP: K_COPY_FROM_USER(err, 0, &p->mmap, param, sizeof(p->mmap)); if (err) goto bail; VERIFY(err, 0 == (err = fastrpc_internal_mmap(fl, &p->mmap))); if (err) goto bail; K_COPY_TO_USER(err, 0, param, &p->mmap, sizeof(p->mmap)); if (err) goto bail; break; case FASTRPC_IOCTL_MUNMAP: K_COPY_FROM_USER(err, 0, &p->munmap, param, sizeof(p->munmap)); if (err) goto bail; VERIFY(err, 0 == (err = fastrpc_internal_munmap(fl, &p->munmap))); if (err) goto bail; break; case FASTRPC_IOCTL_MMAP_64: K_COPY_FROM_USER(err, 0, &p->mmap64, param, sizeof(p->mmap64)); if (err) goto bail; get_fastrpc_ioctl_mmap_64(&p->mmap64, &i.mmap); VERIFY(err, 0 == (err = fastrpc_internal_mmap(fl, &i.mmap))); if (err) goto bail; put_fastrpc_ioctl_mmap_64(&p->mmap64, &i.mmap); K_COPY_TO_USER(err, 0, param, &p->mmap64, sizeof(p->mmap64)); if (err) goto bail; break; case FASTRPC_IOCTL_MUNMAP_64: K_COPY_FROM_USER(err, 0, &p->munmap64, param, sizeof(p->munmap64)); if (err) goto bail; get_fastrpc_ioctl_munmap_64(&p->munmap64, &i.munmap); VERIFY(err, 0 == (err = fastrpc_internal_munmap(fl, &i.munmap))); if (err) goto bail; break; case FASTRPC_IOCTL_MUNMAP_FD: K_COPY_FROM_USER(err, 0, &p->munmap_fd, param, sizeof(p->munmap_fd)); if (err) goto bail; VERIFY(err, 0 == (err = fastrpc_internal_munmap_fd(fl, &p->munmap_fd))); if (err) goto bail; break; default: err = -ENOTTY; pr_info("bad ioctl: %d\n", ioctl_num); break; } bail: return err; } static long fastrpc_device_ioctl(struct file *file, unsigned int ioctl_num, unsigned long ioctl_param) { union fastrpc_ioctl_param p; void *param = (char *)ioctl_param; struct fastrpc_file *fl = (struct fastrpc_file *)file->private_data; int size = 0, err = 0; Loading Loading @@ -4811,63 +5121,6 @@ static long fastrpc_device_ioctl(struct file *file, unsigned int ioctl_num, if (err) goto bail; break; case FASTRPC_IOCTL_MMAP: K_COPY_FROM_USER(err, 0, &p.mmap, param, sizeof(p.mmap)); if (err) goto bail; VERIFY(err, 0 == (err = fastrpc_internal_mmap(fl, &p.mmap))); if (err) goto bail; K_COPY_TO_USER(err, 0, param, &p.mmap, sizeof(p.mmap)); if (err) goto bail; break; case FASTRPC_IOCTL_MUNMAP: K_COPY_FROM_USER(err, 0, &p.munmap, param, sizeof(p.munmap)); if (err) goto bail; VERIFY(err, 0 == (err = fastrpc_internal_munmap(fl, &p.munmap))); if (err) goto bail; break; case FASTRPC_IOCTL_MMAP_64: K_COPY_FROM_USER(err, 0, &p.mmap64, param, sizeof(p.mmap64)); if (err) goto bail; get_fastrpc_ioctl_mmap_64(&p.mmap64, &i.mmap); VERIFY(err, 0 == (err = fastrpc_internal_mmap(fl, &i.mmap))); if (err) goto bail; put_fastrpc_ioctl_mmap_64(&p.mmap64, &i.mmap); K_COPY_TO_USER(err, 0, param, &p.mmap64, sizeof(p.mmap64)); if (err) goto bail; break; case FASTRPC_IOCTL_MUNMAP_64: K_COPY_FROM_USER(err, 0, &p.munmap64, param, sizeof(p.munmap64)); if (err) goto bail; get_fastrpc_ioctl_munmap_64(&p.munmap64, &i.munmap); VERIFY(err, 0 == (err = fastrpc_internal_munmap(fl, &i.munmap))); if (err) goto bail; break; case FASTRPC_IOCTL_MUNMAP_FD: K_COPY_FROM_USER(err, 0, &p.munmap_fd, param, sizeof(p.munmap_fd)); if (err) goto bail; VERIFY(err, 0 == (err = fastrpc_internal_munmap_fd(fl, &p.munmap_fd))); if (err) goto bail; break; case FASTRPC_IOCTL_SETMODE: err = fastrpc_setmode(ioctl_param, fl); break; Loading Loading @@ -4906,6 +5159,21 @@ static long fastrpc_device_ioctl(struct file *file, unsigned int ioctl_num, case FASTRPC_IOCTL_GET_DSP_INFO: err = fastrpc_get_dsp_info(&p.cap, param, fl); break; case FASTRPC_IOCTL_MEM_MAP: /* fall through */ case FASTRPC_IOCTL_MEM_UNMAP: /* fall through */ case FASTRPC_IOCTL_MMAP: /* fall through */ case FASTRPC_IOCTL_MUNMAP: /* fall through */ case FASTRPC_IOCTL_MMAP_64: /* fall through */ case FASTRPC_IOCTL_MUNMAP_64: /* fall through */ case FASTRPC_IOCTL_MUNMAP_FD: err = fastrpc_mmap_device_ioctl(fl, ioctl_num, &p, param); break; default: err = -ENOTTY; pr_info("bad ioctl: %d\n", ioctl_num); Loading
drivers/char/adsprpc_compat.c +180 −12 Original line number Diff line number Diff line Loading @@ -39,6 +39,10 @@ struct compat_fastrpc_ioctl_capability) #define COMPAT_FASTRPC_IOCTL_INVOKE2 \ _IOWR('R', 18, struct compat_fastrpc_ioctl_invoke2) #define COMPAT_FASTRPC_IOCTL_MEM_MAP \ _IOWR('R', 19, struct compat_fastrpc_ioctl_mem_map) #define COMPAT_FASTRPC_IOCTL_MEM_UNMAP \ _IOWR('R', 20, struct compat_fastrpc_ioctl_mem_unmap) struct compat_remote_buf { compat_uptr_t pv; /* buffer pointer */ Loading Loading @@ -89,6 +93,38 @@ struct compat_fastrpc_ioctl_invoke2 { compat_int_t err; /* reserved */ }; struct compat_fastrpc_mem_map { compat_int_t fd; /* ion fd */ compat_int_t offset; /* buffer offset */ compat_uint_t flags; /* flags to control memory map */ compat_uint_t attrs; /* buffer attributes used for SMMU mapping */ compat_uptr_t vaddrin; /* virtual address */ compat_size_t length; /* buffer length */ compat_u64 vaddrout; /* dsp virtual address */ }; struct compat_fastrpc_ioctl_mem_map { compat_int_t version; union { struct compat_fastrpc_mem_map m; compat_int_t reserved[MAP_RESERVED_NUM]; }; }; struct compat_fastrpc_mem_unmap { compat_int_t fd; /* ion fd */ compat_u64 vaddr; /* dsp virtual address */ compat_size_t length; /* buffer length */ }; struct compat_fastrpc_ioctl_mem_unmap { compat_int_t version; union { struct compat_fastrpc_mem_unmap um; compat_int_t reserved[UNMAP_RESERVED_NUM]; }; }; struct compat_fastrpc_ioctl_mmap { compat_int_t fd; /* ion fd */ compat_uint_t flags; /* flags for dsp to map with */ Loading Loading @@ -372,6 +408,74 @@ static int compat_fastrpc_ioctl_invoke2(struct file *filp, FASTRPC_IOCTL_INVOKE2, (unsigned long)inv); } static int compat_get_fastrpc_ioctl_mem_map( struct compat_fastrpc_ioctl_mem_map __user *map32, struct fastrpc_ioctl_mem_map __user *map) { compat_uint_t u; compat_int_t i; compat_size_t s; compat_uptr_t p; int err; err = get_user(i, &map32->version); if (err || i != 0) return -EINVAL; err = put_user(i, &map->version); err |= get_user(i, &map32->m.fd); err |= put_user(i, &map->m.fd); err |= get_user(i, &map32->m.offset); err |= put_user(i, &map->m.offset); err |= get_user(u, &map32->m.flags); err |= put_user(u, &map->m.flags); err |= get_user(p, &map32->m.vaddrin); err |= put_user(p, &map->m.vaddrin); err |= get_user(s, &map32->m.length); err |= put_user(s, &map->m.length); err |= get_user(u, &map32->m.attrs); err |= put_user(u, &map->m.attrs); return err; } static int compat_put_fastrpc_ioctl_mem_map( struct compat_fastrpc_ioctl_mem_map __user *map32, struct fastrpc_ioctl_mem_map __user *map) { compat_u64 p; int err; err = get_user(p, &map->m.vaddrout); err |= put_user(p, &map32->m.vaddrout); return err; } static int compat_get_fastrpc_ioctl_mem_unmap( struct compat_fastrpc_ioctl_mem_unmap __user *unmap32, struct fastrpc_ioctl_mem_unmap __user *unmap) { compat_int_t i; compat_size_t s; compat_u64 p; int err; err = get_user(i, &unmap32->version); if (err || i != 0) return -EINVAL; err = put_user(i, &unmap->version); err |= get_user(i, &unmap32->um.fd); err |= put_user(i, &unmap->um.fd); err |= get_user(p, &unmap32->um.vaddr); err |= put_user(p, &unmap->um.vaddr); err |= get_user(s, &unmap32->um.length); err |= put_user(s, &unmap->um.length); return err; } static int compat_get_fastrpc_ioctl_mmap( struct compat_fastrpc_ioctl_mmap __user *map32, struct fastrpc_ioctl_mmap __user *map) Loading Loading @@ -661,25 +765,54 @@ static int compat_fastrpc_get_dsp_info(struct file *filp, return err; } long compat_fastrpc_device_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) static inline long compat_fastrpc_mmap_device_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) { int err = 0; if (!filp->f_op || !filp->f_op->unlocked_ioctl) return -ENOTTY; switch (cmd) { case COMPAT_FASTRPC_IOCTL_INVOKE: case COMPAT_FASTRPC_IOCTL_INVOKE_FD: case COMPAT_FASTRPC_IOCTL_INVOKE_ATTRS: case COMPAT_FASTRPC_IOCTL_INVOKE_CRC: case COMPAT_FASTRPC_IOCTL_MEM_MAP: { return compat_fastrpc_ioctl_invoke(filp, cmd, arg); struct compat_fastrpc_ioctl_mem_map __user *map32; struct fastrpc_ioctl_mem_map __user *map; long ret; map32 = compat_ptr(arg); map = compat_alloc_user_space(sizeof(*map)); if (map == NULL) return -EFAULT; err = compat_get_fastrpc_ioctl_mem_map(map32, map); if (err) return err; ret = filp->f_op->unlocked_ioctl(filp, FASTRPC_IOCTL_MEM_MAP, (unsigned long)map); if (ret) return ret; VERIFY(err, 0 == compat_put_fastrpc_ioctl_mem_map(map32, map)); return err; } case COMPAT_FASTRPC_IOCTL_INVOKE2: case COMPAT_FASTRPC_IOCTL_MEM_UNMAP: { return compat_fastrpc_ioctl_invoke2(filp, cmd, arg); struct compat_fastrpc_ioctl_mem_unmap __user *unmap32; struct fastrpc_ioctl_mem_unmap __user *unmap; long ret; unmap32 = compat_ptr(arg); unmap = compat_alloc_user_space(sizeof(*unmap)); if (unmap == NULL) return -EFAULT; err = compat_get_fastrpc_ioctl_mem_unmap(unmap32, unmap); if (err) return err; ret = filp->f_op->unlocked_ioctl(filp, FASTRPC_IOCTL_MEM_UNMAP, (unsigned long)unmap); if (ret) return ret; return err; } case COMPAT_FASTRPC_IOCTL_MMAP: { Loading Loading @@ -740,6 +873,31 @@ long compat_fastrpc_device_ioctl(struct file *filp, unsigned int cmd, return filp->f_op->unlocked_ioctl(filp, FASTRPC_IOCTL_MUNMAP, (unsigned long)unmap); } default: return -ENOIOCTLCMD; } } long compat_fastrpc_device_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) { int err = 0; if (!filp->f_op || !filp->f_op->unlocked_ioctl) return -ENOTTY; switch (cmd) { case COMPAT_FASTRPC_IOCTL_INVOKE: case COMPAT_FASTRPC_IOCTL_INVOKE_FD: case COMPAT_FASTRPC_IOCTL_INVOKE_ATTRS: case COMPAT_FASTRPC_IOCTL_INVOKE_CRC: { return compat_fastrpc_ioctl_invoke(filp, cmd, arg); } case COMPAT_FASTRPC_IOCTL_INVOKE2: { return compat_fastrpc_ioctl_invoke2(filp, cmd, arg); } case COMPAT_FASTRPC_IOCTL_MUNMAP_64: { struct compat_fastrpc_ioctl_munmap_64 __user *unmap32; Loading Loading @@ -814,6 +972,16 @@ long compat_fastrpc_device_ioctl(struct file *filp, unsigned int cmd, { return compat_fastrpc_get_dsp_info(filp, arg); } case COMPAT_FASTRPC_IOCTL_MEM_MAP: /* fall through */ case COMPAT_FASTRPC_IOCTL_MEM_UNMAP: /* fall through */ case COMPAT_FASTRPC_IOCTL_MMAP: /* fall through */ case COMPAT_FASTRPC_IOCTL_MMAP_64: /* fall through */ case COMPAT_FASTRPC_IOCTL_MUNMAP: return compat_fastrpc_mmap_device_ioctl(filp, cmd, arg); default: return -ENOIOCTLCMD; } Loading
drivers/char/adsprpc_shared.h +73 −1 Original line number Diff line number Diff line Loading @@ -26,7 +26,8 @@ #define FASTRPC_IOCTL_GET_DSP_INFO \ _IOWR('R', 17, struct fastrpc_ioctl_capability) #define FASTRPC_IOCTL_INVOKE2 _IOWR('R', 18, struct fastrpc_ioctl_invoke2) #define FASTRPC_IOCTL_MEM_MAP _IOWR('R', 19, struct fastrpc_ioctl_mem_map) #define FASTRPC_IOCTL_MEM_UNMAP _IOWR('R', 20, struct fastrpc_ioctl_mem_unmap) #define FASTRPC_GLINK_GUID "fastrpcglink-apps-dsp" #define FASTRPC_SMD_GUID "fastrpcsmd-apps-dsp" Loading Loading @@ -271,6 +272,77 @@ struct fastrpc_ioctl_munmap_fd { ssize_t len; /* length */ }; /** * Control flags for mapping memory on DSP user process */ enum fastrpc_map_flags { /** * Map memory pages with RW- permission and CACHE WRITEBACK. * The driver is responsible for cache maintenance when passed * the buffer to FastRPC calls. Same virtual address will be * assigned for subsequent FastRPC calls. */ FASTRPC_MAP_STATIC = 0, /* Reserved */ FASTRPC_MAP_RESERVED, /** * Map memory pages with RW- permission and CACHE WRITEBACK. * Mapping tagged with a file descriptor. User is responsible for * CPU and DSP cache maintenance for the buffer. Get virtual address * of buffer on DSP using HAP_mmap_get() and HAP_mmap_put() APIs. */ FASTRPC_MAP_FD = 2, /** * Mapping delayed until user call HAP_mmap() and HAP_munmap() * functions on DSP. It is useful to map a buffer with cache modes * other than default modes. User is responsible for CPU and DSP * cache maintenance for the buffer. */ FASTRPC_MAP_FD_DELAYED, FASTRPC_MAP_MAX, }; struct fastrpc_mem_map { int fd; /* ion fd */ int offset; /* buffer offset */ uint32_t flags; /* flags defined in enum fastrpc_map_flags */ int attrs; /* buffer attributes used for SMMU mapping */ uintptr_t vaddrin; /* buffer virtual address */ size_t length; /* buffer length */ uint64_t vaddrout; /* [out] remote virtual address */ }; /* Map and unmap IOCTL methods reserved memory size for future extensions */ #define MAP_RESERVED_NUM (14) #define UNMAP_RESERVED_NUM (10) /* map memory to DSP device */ struct fastrpc_ioctl_mem_map { int version; /* Initial version 0 */ union { struct fastrpc_mem_map m; int reserved[MAP_RESERVED_NUM]; }; }; struct fastrpc_mem_unmap { int fd; /* ion fd */ uint64_t vaddr; /* remote process (dsp) virtual address */ size_t length; /* buffer size */ }; /* unmap memory to DSP device */ struct fastrpc_ioctl_mem_unmap { int version; /* Initial version 0 */ union { struct fastrpc_mem_unmap um; int reserved[UNMAP_RESERVED_NUM]; }; }; struct fastrpc_ioctl_perf { /* kernel performance data */ uintptr_t data; uint32_t numkeys; Loading