12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112 |
- // SPDX-License-Identifier: GPL-2.0-only
- /*
- * Copyright (c) 2014-2021, The Linux Foundation. All rights reserved.
- */
- #include <linux/compat.h>
- #include <linux/fs.h>
- #include <linux/uaccess.h>
- #include <linux/msm_ion.h>
- #include <linux/slab.h>
- #include "adsprpc_compat.h"
- #include "adsprpc_shared.h"
- #define COMPAT_FASTRPC_IOCTL_INVOKE \
- _IOWR('R', 1, struct compat_fastrpc_ioctl_invoke)
- #define COMPAT_FASTRPC_IOCTL_MMAP \
- _IOWR('R', 2, struct compat_fastrpc_ioctl_mmap)
- #define COMPAT_FASTRPC_IOCTL_MUNMAP \
- _IOWR('R', 3, struct compat_fastrpc_ioctl_munmap)
- #define COMPAT_FASTRPC_IOCTL_INVOKE_FD \
- _IOWR('R', 4, struct compat_fastrpc_ioctl_invoke_fd)
- #define COMPAT_FASTRPC_IOCTL_INIT \
- _IOWR('R', 6, struct compat_fastrpc_ioctl_init)
- #define COMPAT_FASTRPC_IOCTL_INVOKE_ATTRS \
- _IOWR('R', 7, struct compat_fastrpc_ioctl_invoke_attrs)
- #define COMPAT_FASTRPC_IOCTL_INIT_ATTRS \
- _IOWR('R', 10, struct compat_fastrpc_ioctl_init_attrs)
- #define COMPAT_FASTRPC_IOCTL_INVOKE_CRC \
- _IOWR('R', 11, struct compat_fastrpc_ioctl_invoke_crc)
- #define COMPAT_FASTRPC_IOCTL_CONTROL \
- _IOWR('R', 12, struct compat_fastrpc_ioctl_control)
- #define COMPAT_FASTRPC_IOCTL_MMAP_64 \
- _IOWR('R', 14, struct compat_fastrpc_ioctl_mmap_64)
- #define COMPAT_FASTRPC_IOCTL_MUNMAP_64 \
- _IOWR('R', 15, struct compat_fastrpc_ioctl_munmap_64)
- #define COMPAT_FASTRPC_IOCTL_GET_DSP_INFO \
- _IOWR('R', 17, \
- 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)
- #define COMPAT_FASTRPC_IOCTL_INVOKE_PERF \
- _IOWR('R', 21, struct compat_fastrpc_ioctl_invoke_perf)
- #define COMPAT_FASTRPC_IOCTL_DSPSIGNAL_CREATE \
- _IOWR('R', 23, struct fastrpc_ioctl_dspsignal_create)
- #define COMPAT_FASTRPC_IOCTL_DSPSIGNAL_DESTROY \
- _IOWR('R', 24, struct fastrpc_ioctl_dspsignal_destroy)
- #define COMPAT_FASTRPC_IOCTL_DSPSIGNAL_SIGNAL \
- _IOWR('R', 25, struct fastrpc_ioctl_dspsignal_signal)
- #define COMPAT_FASTRPC_IOCTL_DSPSIGNAL_WAIT \
- _IOWR('R', 26, struct fastrpc_ioctl_dspsignal_wait)
- #define COMPAT_FASTRPC_IOCTL_DSPSIGNAL_CANCEL_WAIT \
- _IOWR('R', 27, struct fastrpc_ioctl_dspsignal_cancel_wait)
- struct compat_remote_buf {
- compat_uptr_t pv; /* buffer pointer */
- compat_size_t len; /* length of buffer */
- };
- union compat_remote_arg {
- struct compat_remote_buf buf;
- compat_uint_t h;
- };
- struct compat_fastrpc_ioctl_invoke {
- compat_uint_t handle; /* remote handle */
- compat_uint_t sc; /* scalars describing the data */
- compat_uptr_t pra; /* remote arguments list */
- };
- struct compat_fastrpc_ioctl_invoke_fd {
- struct compat_fastrpc_ioctl_invoke inv;
- compat_uptr_t fds; /* fd list */
- };
- struct compat_fastrpc_ioctl_invoke_attrs {
- struct compat_fastrpc_ioctl_invoke inv;
- compat_uptr_t fds; /* fd list */
- compat_uptr_t attrs; /* attribute list */
- };
- struct compat_fastrpc_ioctl_invoke_crc {
- struct compat_fastrpc_ioctl_invoke inv;
- compat_uptr_t fds; /* fd list */
- compat_uptr_t attrs; /* attribute list */
- compat_uptr_t crc; /* crc list */
- };
- struct compat_fastrpc_ioctl_invoke_perf {
- struct compat_fastrpc_ioctl_invoke inv;
- compat_uptr_t fds;
- compat_uptr_t attrs;
- compat_uptr_t crc;
- compat_uptr_t perf_kernel;
- compat_uptr_t perf_dsp;
- };
- struct compat_fastrpc_ioctl_invoke_async {
- struct compat_fastrpc_ioctl_invoke inv;
- compat_uptr_t fds; /* fd list */
- compat_uptr_t attrs; /* attribute list */
- compat_uptr_t crc; /* crc list */
- compat_uptr_t perf_kernel; /* Kernel perf data pointer */
- compat_uptr_t perf_dsp; /* DSP perf data pointer */
- compat_uptr_t job; /* Async job */
- };
- struct compat_fastrpc_ioctl_invoke_async_no_perf {
- struct compat_fastrpc_ioctl_invoke inv;
- compat_uptr_t fds; /* fd list */
- compat_uptr_t attrs; /* attribute list */
- compat_uptr_t crc; /* crc list */
- compat_uptr_t job; /* Async job */
- };
- struct compat_fastrpc_ioctl_invoke2 {
- compat_uint_t req; /* type of invocation request */
- compat_uptr_t invparam; /* invocation request param */
- compat_uint_t size; /* size of invocation param */
- compat_int_t err; /* reserved */
- };
- struct compat_fastrpc_ioctl_async_response {
- compat_u64 jobid; /* job id generated by user */
- compat_int_t result; /* result from DSP */
- compat_uptr_t perf_kernel; /* Kernel perf data pointer */
- compat_uptr_t perf_dsp; /* DSP perf data pointer */
- compat_uint_t handle;
- compat_uint_t sc;
- };
- struct compat_fastrpc_ioctl_notif_rsp {
- compat_int_t domain; /* Domain of User PD */
- compat_int_t session; /* Session ID of User PD */
- compat_uint_t status; /* Status of the process */
- };
- 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 */
- compat_uptr_t vaddrin; /* optional virtual address */
- compat_size_t size; /* size */
- compat_uptr_t vaddrout; /* dsps virtual address */
- };
- struct compat_fastrpc_ioctl_mmap_64 {
- compat_int_t fd; /* ion fd */
- compat_uint_t flags; /* flags for dsp to map with */
- compat_u64 vaddrin; /* optional virtual address */
- compat_size_t size; /* size */
- compat_u64 vaddrout; /* dsps virtual address */
- };
- struct compat_fastrpc_ioctl_munmap {
- compat_uptr_t vaddrout; /* address to unmap */
- compat_size_t size; /* size */
- };
- struct compat_fastrpc_ioctl_munmap_64 {
- compat_u64 vaddrout; /* address to unmap */
- compat_size_t size; /* size */
- };
- struct compat_fastrpc_ioctl_init {
- compat_uint_t flags; /* one of FASTRPC_INIT_* macros */
- compat_uptr_t file; /* pointer to elf file */
- compat_int_t filelen; /* elf file length */
- compat_int_t filefd; /* ION fd for the file */
- compat_uptr_t mem; /* mem for the PD */
- compat_int_t memlen; /* mem length */
- compat_int_t memfd; /* ION fd for the mem */
- };
- struct compat_fastrpc_ioctl_init_attrs {
- struct compat_fastrpc_ioctl_init init;
- compat_int_t attrs; /* attributes to init process */
- compat_int_t siglen; /* test signature file length */
- };
- #define FASTRPC_CONTROL_LATENCY (1)
- struct compat_fastrpc_ctrl_latency {
- compat_uint_t enable; /* latency control enable */
- compat_uint_t latency; /* target latency in us */
- };
- #define FASTRPC_CONTROL_KALLOC (3)
- struct compat_fastrpc_ctrl_kalloc {
- compat_uint_t kalloc_support; /* Remote memory allocation from kernel */
- };
- struct compat_fastrpc_ctrl_wakelock {
- compat_uint_t enable; /* wakelock control enable */
- };
- struct compat_fastrpc_ctrl_pm {
- compat_uint_t timeout; /* timeout(in ms) for PM to keep system awake */
- };
- struct compat_fastrpc_ioctl_control {
- compat_uint_t req;
- union {
- struct compat_fastrpc_ctrl_latency lp;
- struct compat_fastrpc_ctrl_kalloc kalloc;
- struct compat_fastrpc_ctrl_wakelock wp;
- struct compat_fastrpc_ctrl_pm pm;
- };
- };
- struct compat_fastrpc_ioctl_capability {
- /*
- * @param[in]: DSP domain ADSP_DOMAIN_ID,
- * SDSP_DOMAIN_ID, or CDSP_DOMAIN_ID
- */
- compat_uint_t domain;
- /*
- * @param[in]: One of the DSP attributes
- * from enum remote_dsp_attributes
- */
- compat_uint_t attribute_ID;
- /*
- * @param[out]: Result of the DSP
- * capability query based on attribute_ID
- */
- compat_uint_t capability;
- };
- static int compat_get_fastrpc_ioctl_invoke(
- struct compat_fastrpc_ioctl_invoke_async __user *inv32,
- struct fastrpc_ioctl_invoke_async *inv,
- unsigned int cmd, unsigned int sc)
- {
- compat_uint_t u = 0;
- compat_size_t s;
- compat_uptr_t p, k;
- union compat_remote_arg *pra32;
- union remote_arg *pra;
- int err = 0, len = 0, j = 0;
- len = REMOTE_SCALARS_LENGTH(sc);
- pra = (union remote_arg *)(inv + 1);
- memcpy(&inv->inv.pra, &pra, sizeof(pra));
- memcpy(&inv->inv.sc, &sc, sizeof(sc));
- err |= get_user(u, &inv32->inv.handle);
- memcpy(&inv->inv.handle, &u, sizeof(u));
- err |= get_user(p, &inv32->inv.pra);
- if (err)
- return err;
- pra32 = compat_ptr(p);
- for (j = 0; j < len; j++) {
- err |= get_user(p, &pra32[j].buf.pv);
- memcpy((uintptr_t *)&pra[j].buf.pv, &p, sizeof(p));
- err |= get_user(s, &pra32[j].buf.len);
- memcpy(&pra[j].buf.len, &s, sizeof(s));
- }
- if (cmd != COMPAT_FASTRPC_IOCTL_INVOKE) {
- err |= get_user(p, &inv32->fds);
- memcpy(&inv->fds, &p, sizeof(p));
- }
- if ((cmd == COMPAT_FASTRPC_IOCTL_INVOKE_ATTRS) ||
- (cmd == COMPAT_FASTRPC_IOCTL_INVOKE_CRC) ||
- (cmd == COMPAT_FASTRPC_IOCTL_INVOKE_PERF) ||
- (cmd == FASTRPC_INVOKE2_ASYNC)) {
- err |= get_user(p, &inv32->attrs);
- memcpy(&inv->attrs, &p, sizeof(p));
- }
- if ((cmd == COMPAT_FASTRPC_IOCTL_INVOKE_CRC) ||
- (cmd == COMPAT_FASTRPC_IOCTL_INVOKE_PERF)) {
- err |= get_user(p, &inv32->crc);
- memcpy(&inv->crc, &p, sizeof(p));
- }
- if (cmd == FASTRPC_INVOKE2_ASYNC) {
- err |= get_user(p, &inv32->job);
- memcpy(&inv->job, &p, sizeof(p));
- }
- if ((cmd == COMPAT_FASTRPC_IOCTL_INVOKE_PERF) || (cmd == FASTRPC_INVOKE2_ASYNC)) {
- err |= get_user(k, &inv32->perf_kernel);
- err |= get_user(p, &inv32->perf_dsp);
- memcpy(&inv->perf_kernel, &k, sizeof(k));
- memcpy(&inv->perf_dsp, &p, sizeof(p));
- }
- return err;
- }
- static int compat_fastrpc_ioctl_invoke(struct file *filp,
- unsigned int cmd, unsigned long arg)
- {
- struct compat_fastrpc_ioctl_invoke_async __user *inv32;
- struct fastrpc_ioctl_invoke_async *inv = NULL;
- compat_uint_t sc = 0;
- int err = 0, len = 0;
- struct fastrpc_file *fl = (struct fastrpc_file *)filp->private_data;
- inv32 = compat_ptr(arg);
- err = get_user(sc, &inv32->inv.sc);
- if (err)
- return err;
- len = REMOTE_SCALARS_LENGTH(sc);
- VERIFY(err, NULL != (inv = kzalloc(
- sizeof(*inv) + len * sizeof(union remote_arg), GFP_KERNEL)));
- if (err)
- return -EFAULT;
- VERIFY(err, 0 == compat_get_fastrpc_ioctl_invoke(inv32,
- inv, cmd, sc));
- if (err) {
- kfree(inv);
- return err;
- }
- VERIFY(err, 0 == (err = fastrpc_internal_invoke(fl,
- fl->mode, COMPAT_MSG, inv)));
- kfree(inv);
- return err;
- }
- static int compat_get_fastrpc_ioctl_invoke2(
- struct compat_fastrpc_ioctl_invoke2 __user *inv32,
- struct fastrpc_ioctl_invoke2 **inva,
- unsigned int cmd)
- {
- int err = 0;
- compat_uptr_t pparam, p;
- compat_uint_t req, size, ref_size = 0;
- struct fastrpc_ioctl_invoke2 *inv2_user = NULL;
- struct fastrpc_ioctl_invoke_async *asyncinv_user;
- err = get_user(req, &inv32->req);
- err |= get_user(pparam, &inv32->invparam);
- err |= get_user(size, &inv32->size);
- if (err)
- goto bail;
- switch (req) {
- case FASTRPC_INVOKE2_ASYNC:
- {
- struct compat_fastrpc_ioctl_invoke_async __user *lasync32;
- struct compat_fastrpc_ioctl_invoke_async_no_perf __user *lasync32_old;
- compat_uint_t sc = 0;
- int len = 0;
- VERIFY(err, size <= sizeof(*lasync32));
- if (err) {
- err = -EBADE;
- goto bail;
- }
- lasync32 = compat_ptr(pparam);
- err = get_user(sc, &lasync32->inv.sc);
- if (err)
- goto bail;
- len = REMOTE_SCALARS_LENGTH(sc);
- VERIFY(err, NULL != (inv2_user = kzalloc(
- sizeof(*inv2_user) + sizeof(*asyncinv_user) +
- len * sizeof(union remote_arg), GFP_KERNEL)));
- if (err) {
- err = -EFAULT;
- goto bail;
- }
- asyncinv_user =
- (struct fastrpc_ioctl_invoke_async *)(inv2_user + 1);
- if (size < sizeof(struct compat_fastrpc_ioctl_invoke_async)) {
- lasync32_old = compat_ptr(pparam);
- VERIFY(err, 0 == compat_get_fastrpc_ioctl_invoke(lasync32,
- asyncinv_user, COMPAT_FASTRPC_IOCTL_INVOKE_CRC, sc));
- if (err)
- goto bail;
- err |= get_user(p, &lasync32_old->job);
- memcpy(&asyncinv_user->job, &p, sizeof(p));
- } else {
- VERIFY(err, 0 == compat_get_fastrpc_ioctl_invoke(lasync32,
- asyncinv_user, req, sc));
- }
- if (err)
- goto bail;
- memcpy(&inv2_user->req, &req, sizeof(req));
- inv2_user->invparam = (uintptr_t)asyncinv_user;
- inv2_user->size = sizeof(*asyncinv_user);
- break;
- }
- case FASTRPC_INVOKE2_ASYNC_RESPONSE:
- ref_size = sizeof(struct compat_fastrpc_ioctl_async_response);
- VERIFY(err, size <= ref_size);
- if (err) {
- err = -EBADE;
- goto bail;
- }
- fallthrough;
- case FASTRPC_INVOKE2_KERNEL_OPTIMIZATIONS:
- if (!ref_size) {
- ref_size = sizeof(uint32_t);
- VERIFY(err, size == ref_size);
- if (err) {
- err = -EBADE;
- goto bail;
- }
- }
- fallthrough;
- case FASTRPC_INVOKE2_STATUS_NOTIF:
- {
- if (!ref_size) {
- ref_size = sizeof(struct compat_fastrpc_ioctl_notif_rsp);
- VERIFY(err, size == ref_size);
- if (err) {
- err = -EBADE;
- goto bail;
- }
- }
- VERIFY(err, NULL != (inv2_user = kzalloc(
- sizeof(*inv2_user), GFP_KERNEL)));
- if (err) {
- err = -EFAULT;
- goto bail;
- }
- memcpy(&inv2_user->req, &req, sizeof(req));
- memcpy(&inv2_user->invparam, &pparam, sizeof(pparam));
- memcpy(&inv2_user->size, &size, sizeof(size));
- break;
- }
- default:
- err = -ENOTTY;
- break;
- }
- bail:
- *inva = inv2_user;
- return err;
- }
- static int compat_fastrpc_ioctl_invoke2(struct file *filp,
- unsigned int cmd, unsigned long arg)
- {
- struct compat_fastrpc_ioctl_invoke2 __user *inv32;
- struct fastrpc_ioctl_invoke2 *inv = NULL;
- int err = 0;
- struct fastrpc_file *fl = (struct fastrpc_file *)filp->private_data;
- inv32 = compat_ptr(arg);
- VERIFY(err, 0 == compat_get_fastrpc_ioctl_invoke2(inv32,
- &inv, cmd));
- if (err) {
- kfree(inv);
- return err;
- }
- VERIFY(err, 0 == (err = fastrpc_internal_invoke2(fl, inv, true)));
- kfree(inv);
- return err;
- }
- static int compat_get_fastrpc_ioctl_mem_map(
- struct compat_fastrpc_ioctl_mem_map __user *map32,
- struct fastrpc_ioctl_mem_map *map)
- {
- compat_uint_t u = 0;
- compat_int_t i = 0;
- compat_size_t s = 0;
- compat_uptr_t p = 0;
- int err;
- err = get_user(i, &map32->version);
- if (err || i != 0)
- return -EINVAL;
- memcpy(&map->version, &i, sizeof(i));
- err |= get_user(i, &map32->m.fd);
- memcpy(&map->m.fd, &i, sizeof(i));
- err |= get_user(i, &map32->m.offset);
- memcpy(&map->m.offset, &i, sizeof(i));
- err |= get_user(u, &map32->m.flags);
- memcpy(&map->m.flags, &u, sizeof(u));
- err |= get_user(p, &map32->m.vaddrin);
- memcpy(&map->m.vaddrin, &s, sizeof(s));
- err |= get_user(s, &map32->m.length);
- memcpy(&map->m.length, &s, sizeof(s));
- err |= get_user(u, &map32->m.attrs);
- memcpy(&map->m.attrs, &u, sizeof(u));
- return err;
- }
- static int compat_put_fastrpc_ioctl_mem_map(
- struct compat_fastrpc_ioctl_mem_map __user *map32,
- struct fastrpc_ioctl_mem_map *map)
- {
- compat_u64 p;
- int err = 0;
- memcpy(&p, &map->m.vaddrout, sizeof(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;
- memcpy(&unmap->version, &i, sizeof(i));
- err |= get_user(i, &unmap32->um.fd);
- memcpy(&unmap->um.fd, &i, sizeof(i));
- err |= get_user(p, &unmap32->um.vaddr);
- memcpy(&unmap->um.vaddr, &p, sizeof(p));
- err |= get_user(s, &unmap32->um.length);
- memcpy(&unmap->um.length, &s, sizeof(s));
- return err;
- }
- static int compat_get_fastrpc_ioctl_mmap(
- struct compat_fastrpc_ioctl_mmap __user *map32,
- struct fastrpc_ioctl_mmap __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->fd);
- memcpy(&map->fd, &i, sizeof(i));
- err |= get_user(u, &map32->flags);
- memcpy(&map->flags, &u, sizeof(u));
- err |= get_user(p, &map32->vaddrin);
- memcpy((uintptr_t *)&map->vaddrin, &p, sizeof(p));
- err |= get_user(s, &map32->size);
- memcpy(&map->size, &s, sizeof(s));
- return err;
- }
- static int compat_get_fastrpc_ioctl_mmap_64(
- struct compat_fastrpc_ioctl_mmap_64 __user *map32,
- struct fastrpc_ioctl_mmap __user *map)
- {
- compat_uint_t u;
- compat_int_t i;
- compat_size_t s;
- compat_u64 p;
- int err;
- err = get_user(i, &map32->fd);
- memcpy(&map->fd, &i, sizeof(i));
- err |= get_user(u, &map32->flags);
- memcpy(&map->flags, &u, sizeof(u));
- err |= get_user(p, &map32->vaddrin);
- memcpy(&map->vaddrin, &p, sizeof(p));
- err |= get_user(s, &map32->size);
- memcpy(&map->size, &s, sizeof(s));
- return err;
- }
- static int compat_put_fastrpc_ioctl_mmap(
- struct compat_fastrpc_ioctl_mmap __user *map32,
- struct fastrpc_ioctl_mmap __user *map)
- {
- compat_uptr_t p;
- int err = 0;
- memcpy(&p, &map->vaddrout, sizeof(p));
- err |= put_user(p, &map32->vaddrout);
- return err;
- }
- static int compat_put_fastrpc_ioctl_mmap_64(
- struct compat_fastrpc_ioctl_mmap_64 __user *map32,
- struct fastrpc_ioctl_mmap __user *map)
- {
- compat_u64 p;
- int err = 0;
- memcpy(&p, &map->vaddrout, sizeof(map->vaddrout));
- err |= put_user(p, &map32->vaddrout);
- return err;
- }
- static int compat_get_fastrpc_ioctl_munmap(
- struct compat_fastrpc_ioctl_munmap __user *unmap32,
- struct fastrpc_ioctl_munmap __user *unmap)
- {
- compat_uptr_t p;
- compat_size_t s;
- int err;
- err = get_user(p, &unmap32->vaddrout);
- memcpy(&unmap->vaddrout, &p, sizeof(p));
- err |= get_user(s, &unmap32->size);
- memcpy(&unmap->size, &s, sizeof(s));
- return err;
- }
- static int compat_get_fastrpc_ioctl_munmap_64(
- struct compat_fastrpc_ioctl_munmap_64 __user *unmap32,
- struct fastrpc_ioctl_munmap *unmap)
- {
- compat_u64 p;
- compat_size_t s;
- int err;
- err = get_user(p, &unmap32->vaddrout);
- memcpy(&unmap->vaddrout, &p, sizeof(p));
- err |= get_user(s, &unmap32->size);
- memcpy(&unmap->size, &s, sizeof(s));
- return err;
- }
- static int compat_get_fastrpc_ioctl_control(
- struct compat_fastrpc_ioctl_control __user *ctrl32,
- struct fastrpc_ioctl_control *ctrl)
- {
- compat_uptr_t p;
- int err;
- err = get_user(p, &ctrl32->req);
- memcpy(&ctrl->req, &p, sizeof(p));
- if ((p == FASTRPC_CONTROL_LATENCY) || (p == FASTRPC_CONTROL_RPC_POLL)) {
- err |= get_user(p, &ctrl32->lp.enable);
- memcpy(&ctrl->lp.enable, &p, sizeof(p));
- err |= get_user(p, &ctrl32->lp.latency);
- memcpy(&ctrl->lp.latency, &p, sizeof(p));
- } else if (p == FASTRPC_CONTROL_WAKELOCK) {
- err |= get_user(p, &ctrl32->wp.enable);
- memcpy(&ctrl->wp.enable, &p, sizeof(p));
- } else if (p == FASTRPC_CONTROL_PM) {
- err |= get_user(p, &ctrl32->pm.timeout);
- memcpy(&ctrl->pm.timeout, &p, sizeof(p));
- }
- return err;
- }
- static int compat_get_fastrpc_ioctl_init(
- struct compat_fastrpc_ioctl_init_attrs __user *init32,
- struct fastrpc_ioctl_init_attrs *init,
- unsigned int cmd)
- {
- compat_uint_t u;
- compat_uptr_t p;
- compat_int_t i;
- int err;
- err = get_user(u, &init32->init.flags);
- memcpy(&init->init.flags, &u, sizeof(u));
- err |= get_user(p, &init32->init.file);
- memcpy(&init->init.file, &p, sizeof(p));
- err |= get_user(i, &init32->init.filelen);
- memcpy(&init->init.filelen, &i, sizeof(i));
- err |= get_user(i, &init32->init.filefd);
- memcpy(&init->init.filefd, &i, sizeof(i));
- err |= get_user(p, &init32->init.mem);
- memcpy(&init->init.mem, &p, sizeof(p));
- err |= get_user(i, &init32->init.memlen);
- memcpy(&init->init.memlen, &i, sizeof(i));
- err |= get_user(i, &init32->init.memfd);
- memcpy(&init->init.memfd, &i, sizeof(i));
- init->attrs = 0;
- if (cmd == COMPAT_FASTRPC_IOCTL_INIT_ATTRS) {
- err |= get_user(i, &init32->attrs);
- memcpy((compat_uptr_t *)&init->attrs, &i, sizeof(i));
- }
- init->siglen = 0;
- if (cmd == COMPAT_FASTRPC_IOCTL_INIT_ATTRS) {
- err |= get_user(i, &init32->siglen);
- memcpy((compat_uptr_t *)&init->siglen, &i, sizeof(i));
- }
- return err;
- }
- static int compat_put_fastrpc_ioctl_get_dsp_info(
- struct compat_fastrpc_ioctl_capability __user *info32,
- struct fastrpc_ioctl_capability __user *info)
- {
- compat_uint_t u;
- int err = 0;
- memcpy(&u, &info->capability, sizeof(u));
- err |= put_user(u, &info32->capability);
- return err;
- }
- static int compat_fastrpc_control(struct fastrpc_file *fl,
- unsigned long arg)
- {
- int err = 0;
- struct compat_fastrpc_ioctl_control __user *ctrl32;
- struct fastrpc_ioctl_control *ctrl = NULL;
- compat_uptr_t p;
- ctrl32 = compat_ptr(arg);
- VERIFY(err, NULL != (ctrl = kzalloc(
- sizeof(*ctrl), GFP_KERNEL)));
- if (err)
- return -EFAULT;
- VERIFY(err, 0 == compat_get_fastrpc_ioctl_control(ctrl32,
- ctrl));
- if (err)
- goto bail;
- VERIFY(err, 0 == (err = fastrpc_internal_control(fl, ctrl)));
- if (err)
- goto bail;
- err = get_user(p, &ctrl32->req);
- if (err)
- goto bail;
- if (p == FASTRPC_CONTROL_KALLOC) {
- memcpy(&p, &ctrl->kalloc.kalloc_support, sizeof(ctrl->kalloc.kalloc_support));
- err |= put_user(p, &ctrl32->kalloc.kalloc_support);
- }
- bail:
- kfree(ctrl);
- return err;
- }
- static int compat_fastrpc_get_dsp_info(struct fastrpc_file *fl,
- unsigned long arg)
- {
- struct compat_fastrpc_ioctl_capability __user *info32 = NULL;
- struct fastrpc_ioctl_capability *info = NULL;
- compat_uint_t u;
- int err = 0;
- size_t info_size = 0;
- info32 = compat_ptr(arg);
- VERIFY(err, NULL != (info = kzalloc(
- sizeof(*info), GFP_KERNEL)));
- info_size = sizeof(*info);
- if (err) {
- ADSPRPC_ERR("allocation failed for size 0x%zx\n", info_size);
- return err;
- }
- err = get_user(u, &info32->domain);
- if (err)
- goto bail;
- memcpy(&info->domain, &u, sizeof(info->domain));
- err = get_user(u, &info32->attribute_ID);
- if (err)
- goto bail;
- memcpy(&info->attribute_ID, &u, sizeof(info->attribute_ID));
- err = fastrpc_get_info_from_kernel(info, fl);
- if (err)
- goto bail;
- err = compat_put_fastrpc_ioctl_get_dsp_info(info32, info);
- bail:
- kfree(info);
- return err;
- }
- static inline long compat_fastrpc_mmap_device_ioctl(struct fastrpc_file *fl,
- unsigned int cmd, unsigned long arg)
- {
- int err = 0;
- switch (cmd) {
- case COMPAT_FASTRPC_IOCTL_MEM_MAP:
- {
- struct compat_fastrpc_ioctl_mem_map __user *map32;
- struct fastrpc_ioctl_mem_map *map = NULL;
- map32 = compat_ptr(arg);
- VERIFY(err, NULL != (map = kzalloc(
- sizeof(*map), GFP_KERNEL)));
- if (err)
- return -EFAULT;
- err = compat_get_fastrpc_ioctl_mem_map(map32, map);
- if (err) {
- kfree(map);
- return err;
- }
- VERIFY(err, 0 == (err = fastrpc_internal_mem_map(fl,
- map)));
- if (err) {
- kfree(map);
- return err;
- }
- VERIFY(err, 0 == compat_put_fastrpc_ioctl_mem_map(map32, map));
- kfree(map);
- return err;
- }
- case COMPAT_FASTRPC_IOCTL_MEM_UNMAP:
- {
- struct compat_fastrpc_ioctl_mem_unmap __user *unmap32;
- struct fastrpc_ioctl_mem_unmap *unmap = NULL;
- unmap32 = compat_ptr(arg);
- unmap = kzalloc(sizeof(*unmap), GFP_KERNEL);
- if (unmap == NULL)
- return -EFAULT;
- err = compat_get_fastrpc_ioctl_mem_unmap(unmap32, unmap);
- if (err) {
- kfree(unmap);
- return err;
- }
- VERIFY(err, 0 == (err = fastrpc_internal_mem_unmap(fl,
- unmap)));
- kfree(unmap);
- return err;
- }
- case COMPAT_FASTRPC_IOCTL_MMAP:
- {
- struct compat_fastrpc_ioctl_mmap __user *map32;
- struct fastrpc_ioctl_mmap *map = NULL;
- map32 = compat_ptr(arg);
- VERIFY(err, NULL != (map = kzalloc(
- sizeof(*map), GFP_KERNEL)));
- if (err)
- return -EFAULT;
- VERIFY(err, 0 == compat_get_fastrpc_ioctl_mmap(map32, map));
- if (err) {
- kfree(map);
- return err;
- }
- VERIFY(err, 0 == (err = fastrpc_internal_mmap(fl, map)));
- VERIFY(err, 0 == compat_put_fastrpc_ioctl_mmap(map32, map));
- kfree(map);
- return err;
- }
- case COMPAT_FASTRPC_IOCTL_MMAP_64:
- {
- struct compat_fastrpc_ioctl_mmap_64 __user *map32;
- struct fastrpc_ioctl_mmap *map = NULL;
- map32 = compat_ptr(arg);
- VERIFY(err, NULL != (map = kzalloc(
- sizeof(*map), GFP_KERNEL)));
- if (err)
- return -EFAULT;
- VERIFY(err, 0 == compat_get_fastrpc_ioctl_mmap_64(map32, map));
- if (err) {
- kfree(map);
- return err;
- }
- VERIFY(err, 0 == (err = fastrpc_internal_mmap(fl, map)));
- VERIFY(err, 0 == compat_put_fastrpc_ioctl_mmap_64(map32, map));
- kfree(map);
- return err;
- }
- case COMPAT_FASTRPC_IOCTL_MUNMAP:
- {
- struct compat_fastrpc_ioctl_munmap __user *unmap32;
- struct fastrpc_ioctl_munmap *unmap = NULL;
- unmap32 = compat_ptr(arg);
- VERIFY(err, NULL != (unmap = kzalloc(
- sizeof(*unmap), GFP_KERNEL)));
- if (err)
- return -EFAULT;
- VERIFY(err, 0 == compat_get_fastrpc_ioctl_munmap(unmap32,
- unmap));
- if (err) {
- kfree(unmap);
- return err;
- }
- VERIFY(err, 0 == (err = fastrpc_internal_munmap(fl,
- unmap)));
- kfree(unmap);
- return err;
- }
- default:
- return -ENOIOCTLCMD;
- }
- }
- static long compat_fastrpc_dspsignal_create(struct fastrpc_file *fl, unsigned long arg)
- {
- struct fastrpc_ioctl_dspsignal_create __user *uc = compat_ptr(arg);
- struct fastrpc_ioctl_dspsignal_create c;
- int err = 0;
- err = copy_from_user(&c, uc, sizeof(c));
- if (err)
- return -EFAULT;
- return fastrpc_dspsignal_create(fl, &c);
- }
- static long compat_fastrpc_dspsignal_destroy(struct fastrpc_file *fl, unsigned long arg)
- {
- struct fastrpc_ioctl_dspsignal_destroy __user *uc = compat_ptr(arg);
- struct fastrpc_ioctl_dspsignal_destroy c;
- int err = 0;
- err = copy_from_user(&c, uc, sizeof(c));
- if (err)
- return -EFAULT;
- return fastrpc_dspsignal_destroy(fl, &c);
- }
- static long compat_fastrpc_dspsignal_signal(struct fastrpc_file *fl, unsigned long arg)
- {
- struct fastrpc_ioctl_dspsignal_signal __user *uc = compat_ptr(arg);
- struct fastrpc_ioctl_dspsignal_signal c;
- int err = 0;
- err = copy_from_user(&c, uc, sizeof(c));
- if (err)
- return -EFAULT;
- return fastrpc_dspsignal_signal(fl, &c);
- }
- static long compat_fastrpc_dspsignal_wait(struct fastrpc_file *fl, unsigned long arg)
- {
- struct fastrpc_ioctl_dspsignal_wait __user *uc = compat_ptr(arg);
- struct fastrpc_ioctl_dspsignal_wait c;
- int err = 0;
- err = copy_from_user(&c, uc, sizeof(c));
- if (err)
- return -EFAULT;
- return fastrpc_dspsignal_wait(fl, &c);
- }
- static long compat_fastrpc_dspsignal_cancel_wait(struct fastrpc_file *fl, unsigned long arg)
- {
- struct fastrpc_ioctl_dspsignal_cancel_wait __user *uc = compat_ptr(arg);
- struct fastrpc_ioctl_dspsignal_cancel_wait c;
- int err = 0;
- err = copy_from_user(&c, uc, sizeof(c));
- if (err)
- return -EFAULT;
- return fastrpc_dspsignal_cancel_wait(fl, &c);
- }
- long compat_fastrpc_device_ioctl(struct file *filp, unsigned int cmd,
- unsigned long arg)
- {
- int err = 0;
- struct fastrpc_file *fl = (struct fastrpc_file *)filp->private_data;
- 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_INVOKE_PERF:
- {
- 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;
- struct fastrpc_ioctl_munmap *unmap = NULL;
- unmap32 = compat_ptr(arg);
- VERIFY(err, NULL != (unmap = kzalloc(
- sizeof(*unmap), GFP_KERNEL)));
- if (err)
- return -EFAULT;
- VERIFY(err, 0 == compat_get_fastrpc_ioctl_munmap_64(unmap32,
- unmap));
- if (err) {
- kfree(unmap);
- return err;
- }
- VERIFY(err, 0 == (err = fastrpc_internal_munmap(fl,
- unmap)));
- kfree(unmap);
- return err;
- }
- case COMPAT_FASTRPC_IOCTL_INIT:
- fallthrough;
- case COMPAT_FASTRPC_IOCTL_INIT_ATTRS:
- {
- struct compat_fastrpc_ioctl_init_attrs __user *init32;
- struct fastrpc_ioctl_init_attrs *init = NULL;
- init32 = compat_ptr(arg);
- VERIFY(err, NULL != (init = kzalloc(
- sizeof(*init), GFP_KERNEL)));
- if (err)
- return -EFAULT;
- VERIFY(err, 0 == compat_get_fastrpc_ioctl_init(init32,
- init, cmd));
- if (err) {
- kfree(init);
- return err;
- }
- VERIFY(err, 0 == (err = fastrpc_init_process(fl, init)));
- kfree(init);
- return err;
- }
- case FASTRPC_IOCTL_GETINFO:
- {
- compat_uptr_t __user *info32;
- uint32_t *info = NULL;
- compat_uint_t u;
- info32 = compat_ptr(arg);
- VERIFY(err, NULL != (info = kzalloc(
- sizeof(*info), GFP_KERNEL)));
- if (err)
- return -EFAULT;
- err = get_user(u, info32);
- memcpy(info, &u, sizeof(u));
- if (err) {
- kfree(info);
- return err;
- }
- VERIFY(err, 0 == (err = fastrpc_get_info(fl, info)));
- memcpy(&u, info, sizeof(*info));
- err |= put_user(u, info32);
- kfree(info);
- return err;
- }
- case FASTRPC_IOCTL_SETMODE:
- return fastrpc_setmode(arg, fl);
- case COMPAT_FASTRPC_IOCTL_CONTROL:
- {
- return compat_fastrpc_control(fl, arg);
- }
- case COMPAT_FASTRPC_IOCTL_GET_DSP_INFO:
- {
- return compat_fastrpc_get_dsp_info(fl, arg);
- }
- case COMPAT_FASTRPC_IOCTL_MEM_MAP:
- fallthrough;
- case COMPAT_FASTRPC_IOCTL_MEM_UNMAP:
- fallthrough;
- case COMPAT_FASTRPC_IOCTL_MMAP:
- fallthrough;
- case COMPAT_FASTRPC_IOCTL_MMAP_64:
- fallthrough;
- case COMPAT_FASTRPC_IOCTL_MUNMAP:
- return compat_fastrpc_mmap_device_ioctl(fl, cmd, arg);
- case COMPAT_FASTRPC_IOCTL_DSPSIGNAL_CREATE:
- return compat_fastrpc_dspsignal_create(fl, arg);
- case COMPAT_FASTRPC_IOCTL_DSPSIGNAL_DESTROY:
- return compat_fastrpc_dspsignal_destroy(fl, arg);
- case COMPAT_FASTRPC_IOCTL_DSPSIGNAL_SIGNAL:
- return compat_fastrpc_dspsignal_signal(fl, arg);
- case COMPAT_FASTRPC_IOCTL_DSPSIGNAL_WAIT:
- return compat_fastrpc_dspsignal_wait(fl, arg);
- case COMPAT_FASTRPC_IOCTL_DSPSIGNAL_CANCEL_WAIT:
- return compat_fastrpc_dspsignal_cancel_wait(fl, arg);
- default:
- return -ENOTTY;
- }
- }
|