adsprpc_compat.c 29 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081
  1. // SPDX-License-Identifier: GPL-2.0-only
  2. /*
  3. * Copyright (c) 2014-2021, The Linux Foundation. All rights reserved.
  4. */
  5. #include <linux/compat.h>
  6. #include <linux/fs.h>
  7. #include <linux/uaccess.h>
  8. #include <linux/msm_ion.h>
  9. #include <linux/slab.h>
  10. #include "adsprpc_compat.h"
  11. #include "adsprpc_shared.h"
  12. #define COMPAT_FASTRPC_IOCTL_INVOKE \
  13. _IOWR('R', 1, struct compat_fastrpc_ioctl_invoke)
  14. #define COMPAT_FASTRPC_IOCTL_MMAP \
  15. _IOWR('R', 2, struct compat_fastrpc_ioctl_mmap)
  16. #define COMPAT_FASTRPC_IOCTL_MUNMAP \
  17. _IOWR('R', 3, struct compat_fastrpc_ioctl_munmap)
  18. #define COMPAT_FASTRPC_IOCTL_INVOKE_FD \
  19. _IOWR('R', 4, struct compat_fastrpc_ioctl_invoke_fd)
  20. #define COMPAT_FASTRPC_IOCTL_INIT \
  21. _IOWR('R', 6, struct compat_fastrpc_ioctl_init)
  22. #define COMPAT_FASTRPC_IOCTL_INVOKE_ATTRS \
  23. _IOWR('R', 7, struct compat_fastrpc_ioctl_invoke_attrs)
  24. #define COMPAT_FASTRPC_IOCTL_INIT_ATTRS \
  25. _IOWR('R', 10, struct compat_fastrpc_ioctl_init_attrs)
  26. #define COMPAT_FASTRPC_IOCTL_INVOKE_CRC \
  27. _IOWR('R', 11, struct compat_fastrpc_ioctl_invoke_crc)
  28. #define COMPAT_FASTRPC_IOCTL_CONTROL \
  29. _IOWR('R', 12, struct compat_fastrpc_ioctl_control)
  30. #define COMPAT_FASTRPC_IOCTL_MMAP_64 \
  31. _IOWR('R', 14, struct compat_fastrpc_ioctl_mmap_64)
  32. #define COMPAT_FASTRPC_IOCTL_MUNMAP_64 \
  33. _IOWR('R', 15, struct compat_fastrpc_ioctl_munmap_64)
  34. #define COMPAT_FASTRPC_IOCTL_GET_DSP_INFO \
  35. _IOWR('R', 17, \
  36. struct compat_fastrpc_ioctl_capability)
  37. #define COMPAT_FASTRPC_IOCTL_INVOKE2 \
  38. _IOWR('R', 18, struct compat_fastrpc_ioctl_invoke2)
  39. #define COMPAT_FASTRPC_IOCTL_MEM_MAP \
  40. _IOWR('R', 19, struct compat_fastrpc_ioctl_mem_map)
  41. #define COMPAT_FASTRPC_IOCTL_MEM_UNMAP \
  42. _IOWR('R', 20, struct compat_fastrpc_ioctl_mem_unmap)
  43. #define COMPAT_FASTRPC_IOCTL_INVOKE_PERF \
  44. _IOWR('R', 21, struct compat_fastrpc_ioctl_invoke_perf)
  45. #define COMPAT_FASTRPC_IOCTL_DSPSIGNAL_CREATE \
  46. _IOWR('R', 23, struct fastrpc_ioctl_dspsignal_create)
  47. #define COMPAT_FASTRPC_IOCTL_DSPSIGNAL_DESTROY \
  48. _IOWR('R', 24, struct fastrpc_ioctl_dspsignal_destroy)
  49. #define COMPAT_FASTRPC_IOCTL_DSPSIGNAL_SIGNAL \
  50. _IOWR('R', 25, struct fastrpc_ioctl_dspsignal_signal)
  51. #define COMPAT_FASTRPC_IOCTL_DSPSIGNAL_WAIT \
  52. _IOWR('R', 26, struct fastrpc_ioctl_dspsignal_wait)
  53. #define COMPAT_FASTRPC_IOCTL_DSPSIGNAL_CANCEL_WAIT \
  54. _IOWR('R', 27, struct fastrpc_ioctl_dspsignal_cancel_wait)
  55. struct compat_remote_buf {
  56. compat_uptr_t pv; /* buffer pointer */
  57. compat_size_t len; /* length of buffer */
  58. };
  59. union compat_remote_arg {
  60. struct compat_remote_buf buf;
  61. compat_uint_t h;
  62. };
  63. struct compat_fastrpc_ioctl_invoke {
  64. compat_uint_t handle; /* remote handle */
  65. compat_uint_t sc; /* scalars describing the data */
  66. compat_uptr_t pra; /* remote arguments list */
  67. };
  68. struct compat_fastrpc_ioctl_invoke_fd {
  69. struct compat_fastrpc_ioctl_invoke inv;
  70. compat_uptr_t fds; /* fd list */
  71. };
  72. struct compat_fastrpc_ioctl_invoke_attrs {
  73. struct compat_fastrpc_ioctl_invoke inv;
  74. compat_uptr_t fds; /* fd list */
  75. compat_uptr_t attrs; /* attribute list */
  76. };
  77. struct compat_fastrpc_ioctl_invoke_crc {
  78. struct compat_fastrpc_ioctl_invoke inv;
  79. compat_uptr_t fds; /* fd list */
  80. compat_uptr_t attrs; /* attribute list */
  81. compat_uptr_t crc; /* crc list */
  82. };
  83. struct compat_fastrpc_ioctl_invoke_perf {
  84. struct compat_fastrpc_ioctl_invoke inv;
  85. compat_uptr_t fds;
  86. compat_uptr_t attrs;
  87. compat_uptr_t crc;
  88. compat_uptr_t perf_kernel;
  89. compat_uptr_t perf_dsp;
  90. };
  91. struct compat_fastrpc_ioctl_invoke_async {
  92. struct compat_fastrpc_ioctl_invoke inv;
  93. compat_uptr_t fds; /* fd list */
  94. compat_uptr_t attrs; /* attribute list */
  95. compat_uptr_t crc; /* crc list */
  96. compat_uptr_t perf_kernel; /* Kernel perf data pointer */
  97. compat_uptr_t perf_dsp; /* DSP perf data pointer */
  98. compat_uptr_t job; /* Async job */
  99. };
  100. struct compat_fastrpc_ioctl_invoke_async_no_perf {
  101. struct compat_fastrpc_ioctl_invoke inv;
  102. compat_uptr_t fds; /* fd list */
  103. compat_uptr_t attrs; /* attribute list */
  104. compat_uptr_t crc; /* crc list */
  105. compat_uptr_t job; /* Async job */
  106. };
  107. struct compat_fastrpc_ioctl_invoke2 {
  108. compat_uint_t req; /* type of invocation request */
  109. compat_uptr_t invparam; /* invocation request param */
  110. compat_uint_t size; /* size of invocation param */
  111. compat_int_t err; /* reserved */
  112. };
  113. struct compat_fastrpc_ioctl_async_response {
  114. compat_u64 jobid; /* job id generated by user */
  115. compat_int_t result; /* result from DSP */
  116. compat_uptr_t perf_kernel; /* Kernel perf data pointer */
  117. compat_uptr_t perf_dsp; /* DSP perf data pointer */
  118. compat_uint_t handle;
  119. compat_uint_t sc;
  120. };
  121. struct compat_fastrpc_ioctl_notif_rsp {
  122. compat_int_t domain; /* Domain of User PD */
  123. compat_int_t session; /* Session ID of User PD */
  124. compat_uint_t status; /* Status of the process */
  125. };
  126. struct compat_fastrpc_mem_map {
  127. compat_int_t fd; /* ion fd */
  128. compat_int_t offset; /* buffer offset */
  129. compat_uint_t flags; /* flags to control memory map */
  130. compat_uint_t attrs; /* buffer attributes used for SMMU mapping */
  131. compat_uptr_t vaddrin; /* virtual address */
  132. compat_size_t length; /* buffer length */
  133. compat_u64 vaddrout; /* dsp virtual address */
  134. };
  135. struct compat_fastrpc_ioctl_mem_map {
  136. compat_int_t version;
  137. union {
  138. struct compat_fastrpc_mem_map m;
  139. compat_int_t reserved[MAP_RESERVED_NUM];
  140. };
  141. };
  142. struct compat_fastrpc_mem_unmap {
  143. compat_int_t fd; /* ion fd */
  144. compat_u64 vaddr; /* dsp virtual address */
  145. compat_size_t length; /* buffer length */
  146. };
  147. struct compat_fastrpc_ioctl_mem_unmap {
  148. compat_int_t version;
  149. union {
  150. struct compat_fastrpc_mem_unmap um;
  151. compat_int_t reserved[UNMAP_RESERVED_NUM];
  152. };
  153. };
  154. struct compat_fastrpc_ioctl_mmap {
  155. compat_int_t fd; /* ion fd */
  156. compat_uint_t flags; /* flags for dsp to map with */
  157. compat_uptr_t vaddrin; /* optional virtual address */
  158. compat_size_t size; /* size */
  159. compat_uptr_t vaddrout; /* dsps virtual address */
  160. };
  161. struct compat_fastrpc_ioctl_mmap_64 {
  162. compat_int_t fd; /* ion fd */
  163. compat_uint_t flags; /* flags for dsp to map with */
  164. compat_u64 vaddrin; /* optional virtual address */
  165. compat_size_t size; /* size */
  166. compat_u64 vaddrout; /* dsps virtual address */
  167. };
  168. struct compat_fastrpc_ioctl_munmap {
  169. compat_uptr_t vaddrout; /* address to unmap */
  170. compat_size_t size; /* size */
  171. };
  172. struct compat_fastrpc_ioctl_munmap_64 {
  173. compat_u64 vaddrout; /* address to unmap */
  174. compat_size_t size; /* size */
  175. };
  176. struct compat_fastrpc_ioctl_init {
  177. compat_uint_t flags; /* one of FASTRPC_INIT_* macros */
  178. compat_uptr_t file; /* pointer to elf file */
  179. compat_int_t filelen; /* elf file length */
  180. compat_int_t filefd; /* ION fd for the file */
  181. compat_uptr_t mem; /* mem for the PD */
  182. compat_int_t memlen; /* mem length */
  183. compat_int_t memfd; /* ION fd for the mem */
  184. };
  185. struct compat_fastrpc_ioctl_init_attrs {
  186. struct compat_fastrpc_ioctl_init init;
  187. compat_int_t attrs; /* attributes to init process */
  188. compat_int_t siglen; /* test signature file length */
  189. };
  190. #define FASTRPC_CONTROL_LATENCY (1)
  191. struct compat_fastrpc_ctrl_latency {
  192. compat_uint_t enable; /* latency control enable */
  193. compat_uint_t latency; /* target latency in us */
  194. };
  195. #define FASTRPC_CONTROL_KALLOC (3)
  196. struct compat_fastrpc_ctrl_kalloc {
  197. compat_uint_t kalloc_support; /* Remote memory allocation from kernel */
  198. };
  199. struct compat_fastrpc_ctrl_wakelock {
  200. compat_uint_t enable; /* wakelock control enable */
  201. };
  202. struct compat_fastrpc_ctrl_pm {
  203. compat_uint_t timeout; /* timeout(in ms) for PM to keep system awake */
  204. };
  205. struct compat_fastrpc_ioctl_control {
  206. compat_uint_t req;
  207. union {
  208. struct compat_fastrpc_ctrl_latency lp;
  209. struct compat_fastrpc_ctrl_kalloc kalloc;
  210. struct compat_fastrpc_ctrl_wakelock wp;
  211. struct compat_fastrpc_ctrl_pm pm;
  212. };
  213. };
  214. struct compat_fastrpc_ioctl_capability {
  215. /*
  216. * @param[in]: DSP domain ADSP_DOMAIN_ID,
  217. * SDSP_DOMAIN_ID, or CDSP_DOMAIN_ID
  218. */
  219. compat_uint_t domain;
  220. /*
  221. * @param[in]: One of the DSP attributes
  222. * from enum remote_dsp_attributes
  223. */
  224. compat_uint_t attribute_ID;
  225. /*
  226. * @param[out]: Result of the DSP
  227. * capability query based on attribute_ID
  228. */
  229. compat_uint_t capability;
  230. };
  231. static int compat_get_fastrpc_ioctl_invoke(
  232. struct compat_fastrpc_ioctl_invoke_async __user *inv32,
  233. struct fastrpc_ioctl_invoke_async *inv,
  234. unsigned int cmd, unsigned int sc)
  235. {
  236. compat_uint_t u = 0;
  237. compat_size_t s;
  238. compat_uptr_t p, k;
  239. union compat_remote_arg *pra32;
  240. union remote_arg *pra;
  241. int err = 0, len = 0, j = 0;
  242. len = REMOTE_SCALARS_LENGTH(sc);
  243. pra = (union remote_arg *)(inv + 1);
  244. memcpy(&inv->inv.pra, &pra, sizeof(pra));
  245. memcpy(&inv->inv.sc, &sc, sizeof(sc));
  246. err |= get_user(u, &inv32->inv.handle);
  247. memcpy(&inv->inv.handle, &u, sizeof(u));
  248. err |= get_user(p, &inv32->inv.pra);
  249. if (err)
  250. return err;
  251. pra32 = compat_ptr(p);
  252. pra = (union remote_arg *)(inv + 1);
  253. for (j = 0; j < len; j++) {
  254. err |= get_user(p, &pra32[j].buf.pv);
  255. memcpy((uintptr_t *)&pra[j].buf.pv, &p, sizeof(p));
  256. err |= get_user(s, &pra32[j].buf.len);
  257. memcpy(&pra[j].buf.len, &s, sizeof(s));
  258. }
  259. inv->fds = NULL;
  260. if (cmd != COMPAT_FASTRPC_IOCTL_INVOKE) {
  261. err |= get_user(p, &inv32->fds);
  262. memcpy(&inv->fds, &p, sizeof(p));
  263. }
  264. inv->attrs = NULL;
  265. if ((cmd == COMPAT_FASTRPC_IOCTL_INVOKE_ATTRS) ||
  266. (cmd == COMPAT_FASTRPC_IOCTL_INVOKE_CRC) ||
  267. (cmd == COMPAT_FASTRPC_IOCTL_INVOKE_PERF) ||
  268. (cmd == FASTRPC_INVOKE2_ASYNC)) {
  269. err |= get_user(p, &inv32->attrs);
  270. memcpy(&inv->attrs, &p, sizeof(p));
  271. }
  272. inv->crc = NULL;
  273. if ((cmd == COMPAT_FASTRPC_IOCTL_INVOKE_CRC) ||
  274. (cmd == COMPAT_FASTRPC_IOCTL_INVOKE_PERF)) {
  275. err |= get_user(p, &inv32->crc);
  276. memcpy(&inv->crc, &p, sizeof(p));
  277. }
  278. inv->job = NULL;
  279. if (cmd == FASTRPC_INVOKE2_ASYNC) {
  280. err |= get_user(p, &inv32->job);
  281. memcpy(&inv->job, &p, sizeof(p));
  282. }
  283. inv->perf_kernel = NULL;
  284. inv->perf_dsp = NULL;
  285. if ((cmd == COMPAT_FASTRPC_IOCTL_INVOKE_PERF) || (cmd == FASTRPC_INVOKE2_ASYNC)) {
  286. err |= get_user(k, &inv32->perf_kernel);
  287. err |= get_user(p, &inv32->perf_dsp);
  288. memcpy(&inv->perf_kernel, &k, sizeof(k));
  289. memcpy(&inv->perf_dsp, &p, sizeof(p));
  290. }
  291. return err;
  292. }
  293. static int compat_fastrpc_ioctl_invoke(struct file *filp,
  294. unsigned int cmd, unsigned long arg)
  295. {
  296. struct compat_fastrpc_ioctl_invoke_async __user *inv32;
  297. struct fastrpc_ioctl_invoke_async *inv;
  298. compat_uint_t sc = 0;
  299. int err = 0, len = 0;
  300. struct fastrpc_file *fl = (struct fastrpc_file *)filp->private_data;
  301. inv32 = compat_ptr(arg);
  302. err = get_user(sc, &inv32->inv.sc);
  303. if (err)
  304. return err;
  305. len = REMOTE_SCALARS_LENGTH(sc);
  306. VERIFY(err, NULL != (inv = kmalloc(
  307. sizeof(*inv) + len * sizeof(union remote_arg), GFP_KERNEL)));
  308. if (err)
  309. return -EFAULT;
  310. VERIFY(err, 0 == compat_get_fastrpc_ioctl_invoke(inv32,
  311. inv, cmd, sc));
  312. if (err)
  313. return err;
  314. VERIFY(err, 0 == (err = fastrpc_internal_invoke(fl,
  315. fl->mode, USER_MSG, inv)));
  316. return err;
  317. }
  318. static int compat_get_fastrpc_ioctl_invoke2(
  319. struct compat_fastrpc_ioctl_invoke2 __user *inv32,
  320. struct fastrpc_ioctl_invoke2 **inva,
  321. unsigned int cmd)
  322. {
  323. int err = 0;
  324. compat_uptr_t pparam, p;
  325. compat_uint_t req, size, ref_size = 0;
  326. struct fastrpc_ioctl_invoke2 *inv2_user = NULL;
  327. struct fastrpc_ioctl_invoke_async *asyncinv_user;
  328. err = get_user(req, &inv32->req);
  329. err |= get_user(pparam, &inv32->invparam);
  330. err |= get_user(size, &inv32->size);
  331. if (err)
  332. goto bail;
  333. switch (req) {
  334. case FASTRPC_INVOKE2_ASYNC:
  335. {
  336. struct compat_fastrpc_ioctl_invoke_async __user *lasync32;
  337. struct compat_fastrpc_ioctl_invoke_async_no_perf __user *lasync32_old;
  338. compat_uint_t sc = 0;
  339. int len = 0;
  340. VERIFY(err, size <= sizeof(*lasync32));
  341. if (err) {
  342. err = -EBADE;
  343. goto bail;
  344. }
  345. lasync32 = compat_ptr(pparam);
  346. err = get_user(sc, &lasync32->inv.sc);
  347. if (err)
  348. goto bail;
  349. len = REMOTE_SCALARS_LENGTH(sc);
  350. VERIFY(err, NULL != (inv2_user = kmalloc(
  351. sizeof(*inv2_user) + sizeof(*asyncinv_user) +
  352. len * sizeof(union remote_arg), GFP_KERNEL)));
  353. if (err) {
  354. err = -EFAULT;
  355. goto bail;
  356. }
  357. asyncinv_user =
  358. (struct fastrpc_ioctl_invoke_async *)(inv2_user + 1);
  359. if (size < sizeof(struct compat_fastrpc_ioctl_invoke_async)) {
  360. lasync32_old = compat_ptr(pparam);
  361. VERIFY(err, 0 == compat_get_fastrpc_ioctl_invoke(lasync32,
  362. asyncinv_user, COMPAT_FASTRPC_IOCTL_INVOKE_CRC, sc));
  363. if (err)
  364. goto bail;
  365. asyncinv_user->job = NULL;
  366. err |= get_user(p, &lasync32_old->job);
  367. memcpy(&asyncinv_user->job, &p, sizeof(p));
  368. asyncinv_user->perf_kernel = NULL;
  369. asyncinv_user->perf_dsp = NULL;
  370. } else {
  371. VERIFY(err, 0 == compat_get_fastrpc_ioctl_invoke(lasync32,
  372. asyncinv_user, req, sc));
  373. }
  374. if (err)
  375. goto bail;
  376. memcpy(&inv2_user->req, &req, sizeof(req));
  377. inv2_user->invparam = (uintptr_t)asyncinv_user;
  378. inv2_user->size = sizeof(*asyncinv_user);
  379. if (err)
  380. goto bail;
  381. break;
  382. }
  383. case FASTRPC_INVOKE2_ASYNC_RESPONSE:
  384. ref_size = sizeof(struct compat_fastrpc_ioctl_async_response);
  385. VERIFY(err, size <= ref_size);
  386. if (err) {
  387. err = -EBADE;
  388. goto bail;
  389. }
  390. fallthrough;
  391. case FASTRPC_INVOKE2_KERNEL_OPTIMIZATIONS:
  392. if (!ref_size) {
  393. ref_size = sizeof(uint32_t);
  394. VERIFY(err, size == ref_size);
  395. if (err) {
  396. err = -EBADE;
  397. goto bail;
  398. }
  399. }
  400. fallthrough;
  401. case FASTRPC_INVOKE2_STATUS_NOTIF:
  402. {
  403. if (!ref_size) {
  404. ref_size = sizeof(struct compat_fastrpc_ioctl_notif_rsp);
  405. VERIFY(err, size == ref_size);
  406. if (err) {
  407. err = -EBADE;
  408. goto bail;
  409. }
  410. }
  411. VERIFY(err, NULL != (inv2_user = kmalloc(
  412. sizeof(*inv2_user), GFP_KERNEL)));
  413. if (err) {
  414. err = -EFAULT;
  415. goto bail;
  416. }
  417. memcpy(&inv2_user->req, &req, sizeof(req));
  418. memcpy(&inv2_user->invparam, &pparam, sizeof(pparam));
  419. memcpy(&inv2_user->size, &size, sizeof(size));
  420. if (err)
  421. goto bail;
  422. break;
  423. }
  424. default:
  425. err = -ENOTTY;
  426. break;
  427. }
  428. *inva = inv2_user;
  429. bail:
  430. return err;
  431. }
  432. static int compat_fastrpc_ioctl_invoke2(struct file *filp,
  433. unsigned int cmd, unsigned long arg)
  434. {
  435. struct compat_fastrpc_ioctl_invoke2 __user *inv32;
  436. struct fastrpc_ioctl_invoke2 *inv;
  437. int err = 0;
  438. struct fastrpc_file *fl = (struct fastrpc_file *)filp->private_data;
  439. inv32 = compat_ptr(arg);
  440. VERIFY(err, 0 == compat_get_fastrpc_ioctl_invoke2(inv32,
  441. &inv, cmd));
  442. if (err)
  443. return err;
  444. VERIFY(err, 0 == (err = fastrpc_internal_invoke2(fl, inv)));
  445. return err;
  446. }
  447. static int compat_get_fastrpc_ioctl_mem_map(
  448. struct compat_fastrpc_ioctl_mem_map __user *map32,
  449. struct fastrpc_ioctl_mem_map *map)
  450. {
  451. compat_uint_t u = 0;
  452. compat_int_t i = 0;
  453. compat_size_t s = 0;
  454. compat_uptr_t p = 0;
  455. int err;
  456. err = get_user(i, &map32->version);
  457. if (err || i != 0)
  458. return -EINVAL;
  459. memcpy(&map->version, &i, sizeof(i));
  460. err |= get_user(i, &map32->m.fd);
  461. memcpy(&map->m.fd, &i, sizeof(i));
  462. err |= get_user(i, &map32->m.offset);
  463. memcpy(&map->m.offset, &i, sizeof(i));
  464. err |= get_user(u, &map32->m.flags);
  465. memcpy(&map->m.flags, &u, sizeof(u));
  466. err |= get_user(p, &map32->m.vaddrin);
  467. memcpy(&map->m.vaddrin, &s, sizeof(s));
  468. err |= get_user(s, &map32->m.length);
  469. memcpy(&map->m.length, &s, sizeof(s));
  470. err |= get_user(u, &map32->m.attrs);
  471. memcpy(&map->m.attrs, &u, sizeof(u));
  472. return err;
  473. }
  474. static int compat_put_fastrpc_ioctl_mem_map(
  475. struct compat_fastrpc_ioctl_mem_map __user *map32,
  476. struct fastrpc_ioctl_mem_map *map)
  477. {
  478. compat_u64 p;
  479. int err = 0;
  480. memcpy(&p, &map->m.vaddrout, sizeof(map->m.vaddrout));
  481. err |= put_user(p, &map32->m.vaddrout);
  482. return err;
  483. }
  484. static int compat_get_fastrpc_ioctl_mem_unmap(
  485. struct compat_fastrpc_ioctl_mem_unmap __user *unmap32,
  486. struct fastrpc_ioctl_mem_unmap __user *unmap)
  487. {
  488. compat_int_t i;
  489. compat_size_t s;
  490. compat_u64 p;
  491. int err;
  492. err = get_user(i, &unmap32->version);
  493. if (err || i != 0)
  494. return -EINVAL;
  495. memcpy(&unmap->version, &i, sizeof(i));
  496. err |= get_user(i, &unmap32->um.fd);
  497. memcpy(&unmap->um.fd, &i, sizeof(i));
  498. err |= get_user(p, &unmap32->um.vaddr);
  499. memcpy(&unmap->um.vaddr, &p, sizeof(p));
  500. err |= get_user(s, &unmap32->um.length);
  501. memcpy(&unmap->um.length, &s, sizeof(s));
  502. return err;
  503. }
  504. static int compat_get_fastrpc_ioctl_mmap(
  505. struct compat_fastrpc_ioctl_mmap __user *map32,
  506. struct fastrpc_ioctl_mmap __user *map)
  507. {
  508. compat_uint_t u;
  509. compat_int_t i;
  510. compat_size_t s;
  511. compat_uptr_t p;
  512. int err;
  513. err = get_user(i, &map32->fd);
  514. memcpy(&map->fd, &i, sizeof(i));
  515. err |= get_user(u, &map32->flags);
  516. memcpy(&map->flags, &u, sizeof(u));
  517. err |= get_user(p, &map32->vaddrin);
  518. memcpy((uintptr_t *)&map->vaddrin, &p, sizeof(p));
  519. err |= get_user(s, &map32->size);
  520. memcpy(&map->size, &s, sizeof(s));
  521. return err;
  522. }
  523. static int compat_get_fastrpc_ioctl_mmap_64(
  524. struct compat_fastrpc_ioctl_mmap_64 __user *map32,
  525. struct fastrpc_ioctl_mmap __user *map)
  526. {
  527. compat_uint_t u;
  528. compat_int_t i;
  529. compat_size_t s;
  530. compat_u64 p;
  531. int err;
  532. err = get_user(i, &map32->fd);
  533. memcpy(&map->fd, &i, sizeof(i));
  534. err |= get_user(u, &map32->flags);
  535. memcpy(&map->flags, &u, sizeof(u));
  536. err |= get_user(p, &map32->vaddrin);
  537. memcpy(&map->vaddrin, &p, sizeof(p));
  538. err |= get_user(s, &map32->size);
  539. memcpy(&map->size, &s, sizeof(s));
  540. return err;
  541. }
  542. static int compat_put_fastrpc_ioctl_mmap(
  543. struct compat_fastrpc_ioctl_mmap __user *map32,
  544. struct fastrpc_ioctl_mmap __user *map)
  545. {
  546. compat_uptr_t p;
  547. int err = 0;
  548. memcpy(&p, &map->vaddrout, sizeof(p));
  549. err |= put_user(p, &map32->vaddrout);
  550. return err;
  551. }
  552. static int compat_put_fastrpc_ioctl_mmap_64(
  553. struct compat_fastrpc_ioctl_mmap_64 __user *map32,
  554. struct fastrpc_ioctl_mmap __user *map)
  555. {
  556. compat_u64 p;
  557. int err = 0;
  558. memcpy(&p, &map->vaddrout, sizeof(map->vaddrout));
  559. err |= put_user(p, &map32->vaddrout);
  560. return err;
  561. }
  562. static int compat_get_fastrpc_ioctl_munmap(
  563. struct compat_fastrpc_ioctl_munmap __user *unmap32,
  564. struct fastrpc_ioctl_munmap __user *unmap)
  565. {
  566. compat_uptr_t p;
  567. compat_size_t s;
  568. int err;
  569. err = get_user(p, &unmap32->vaddrout);
  570. memcpy(&unmap->vaddrout, &p, sizeof(p));
  571. err |= get_user(s, &unmap32->size);
  572. memcpy(&unmap->size, &s, sizeof(s));
  573. return err;
  574. }
  575. static int compat_get_fastrpc_ioctl_munmap_64(
  576. struct compat_fastrpc_ioctl_munmap_64 __user *unmap32,
  577. struct fastrpc_ioctl_munmap *unmap)
  578. {
  579. compat_u64 p;
  580. compat_size_t s;
  581. int err;
  582. err = get_user(p, &unmap32->vaddrout);
  583. memcpy(&unmap->vaddrout, &p, sizeof(p));
  584. err |= get_user(s, &unmap32->size);
  585. memcpy(&unmap->size, &s, sizeof(s));
  586. return err;
  587. }
  588. static int compat_get_fastrpc_ioctl_control(
  589. struct compat_fastrpc_ioctl_control __user *ctrl32,
  590. struct fastrpc_ioctl_control *ctrl)
  591. {
  592. compat_uptr_t p;
  593. int err;
  594. err = get_user(p, &ctrl32->req);
  595. memcpy(&ctrl->req, &p, sizeof(p));
  596. if ((p == FASTRPC_CONTROL_LATENCY) || (p == FASTRPC_CONTROL_RPC_POLL)) {
  597. err |= get_user(p, &ctrl32->lp.enable);
  598. memcpy(&ctrl->lp.enable, &p, sizeof(p));
  599. err |= get_user(p, &ctrl32->lp.latency);
  600. memcpy(&ctrl->lp.latency, &p, sizeof(p));
  601. } else if (p == FASTRPC_CONTROL_WAKELOCK) {
  602. err |= get_user(p, &ctrl32->wp.enable);
  603. memcpy(&ctrl->wp.enable, &p, sizeof(p));
  604. } else if (p == FASTRPC_CONTROL_PM) {
  605. err |= get_user(p, &ctrl32->pm.timeout);
  606. memcpy(&ctrl->pm.timeout, &p, sizeof(p));
  607. }
  608. return err;
  609. }
  610. static int compat_get_fastrpc_ioctl_init(
  611. struct compat_fastrpc_ioctl_init_attrs __user *init32,
  612. struct fastrpc_ioctl_init_attrs *init,
  613. unsigned int cmd)
  614. {
  615. compat_uint_t u;
  616. compat_uptr_t p;
  617. compat_int_t i;
  618. int err;
  619. err = get_user(u, &init32->init.flags);
  620. memcpy(&init->init.flags, &u, sizeof(u));
  621. err |= get_user(p, &init32->init.file);
  622. memcpy(&init->init.file, &p, sizeof(p));
  623. err |= get_user(i, &init32->init.filelen);
  624. memcpy(&init->init.filelen, &i, sizeof(i));
  625. err |= get_user(i, &init32->init.filefd);
  626. memcpy(&init->init.filefd, &i, sizeof(i));
  627. err |= get_user(p, &init32->init.mem);
  628. memcpy(&init->init.mem, &p, sizeof(p));
  629. err |= get_user(i, &init32->init.memlen);
  630. memcpy(&init->init.memlen, &i, sizeof(i));
  631. err |= get_user(i, &init32->init.memfd);
  632. memcpy(&init->init.memfd, &i, sizeof(i));
  633. init->attrs = 0;
  634. if (cmd == COMPAT_FASTRPC_IOCTL_INIT_ATTRS) {
  635. err |= get_user(i, &init32->attrs);
  636. memcpy((compat_uptr_t *)&init->attrs, &i, sizeof(i));
  637. }
  638. init->siglen = 0;
  639. if (cmd == COMPAT_FASTRPC_IOCTL_INIT_ATTRS) {
  640. err |= get_user(i, &init32->siglen);
  641. memcpy((compat_uptr_t *)&init->siglen, &i, sizeof(i));
  642. }
  643. return err;
  644. }
  645. static int compat_put_fastrpc_ioctl_get_dsp_info(
  646. struct compat_fastrpc_ioctl_capability __user *info32,
  647. struct fastrpc_ioctl_capability __user *info)
  648. {
  649. compat_uint_t u;
  650. int err = 0;
  651. memcpy(&u, &info->capability, sizeof(u));
  652. err |= put_user(u, &info32->capability);
  653. return err;
  654. }
  655. static int compat_fastrpc_control(struct fastrpc_file *fl,
  656. unsigned long arg)
  657. {
  658. int err = 0;
  659. struct compat_fastrpc_ioctl_control __user *ctrl32;
  660. struct fastrpc_ioctl_control *ctrl;
  661. compat_uptr_t p;
  662. ctrl32 = compat_ptr(arg);
  663. VERIFY(err, NULL != (ctrl = kmalloc(
  664. sizeof(*ctrl), GFP_KERNEL)));
  665. if (err)
  666. return -EFAULT;
  667. VERIFY(err, 0 == compat_get_fastrpc_ioctl_control(ctrl32,
  668. ctrl));
  669. if (err)
  670. return err;
  671. VERIFY(err, 0 == (err = fastrpc_internal_control(fl, ctrl)));
  672. if (err)
  673. return err;
  674. err = get_user(p, &ctrl32->req);
  675. if (err)
  676. return err;
  677. if (p == FASTRPC_CONTROL_KALLOC) {
  678. memcpy(&p, &ctrl->kalloc.kalloc_support, sizeof(ctrl->kalloc.kalloc_support));
  679. err |= put_user(p, &ctrl32->kalloc.kalloc_support);
  680. }
  681. return err;
  682. }
  683. static int compat_fastrpc_get_dsp_info(struct fastrpc_file *fl,
  684. unsigned long arg)
  685. {
  686. struct compat_fastrpc_ioctl_capability __user *info32 = NULL;
  687. struct fastrpc_ioctl_capability *info = NULL;
  688. compat_uint_t u;
  689. int err = 0;
  690. info32 = compat_ptr(arg);
  691. VERIFY(err, NULL != (info = kmalloc(
  692. sizeof(*info), GFP_KERNEL)));
  693. err = get_user(u, &info32->domain);
  694. if (err)
  695. return err;
  696. memcpy(&info->domain, &u, sizeof(info->domain));
  697. err = get_user(u, &info32->attribute_ID);
  698. if (err)
  699. return err;
  700. memcpy(&info->attribute_ID, &u, sizeof(info->attribute_ID));
  701. err = fastrpc_get_info_from_kernel(info, fl);
  702. if (err)
  703. return err;
  704. err = compat_put_fastrpc_ioctl_get_dsp_info(info32, info);
  705. return err;
  706. }
  707. static inline long compat_fastrpc_mmap_device_ioctl(struct fastrpc_file *fl,
  708. unsigned int cmd, unsigned long arg)
  709. {
  710. int err = 0;
  711. switch (cmd) {
  712. case COMPAT_FASTRPC_IOCTL_MEM_MAP:
  713. {
  714. struct compat_fastrpc_ioctl_mem_map __user *map32;
  715. struct fastrpc_ioctl_mem_map *map;
  716. map32 = compat_ptr(arg);
  717. VERIFY(err, NULL != (map = kmalloc(
  718. sizeof(*map), GFP_KERNEL)));
  719. if (err)
  720. return -EFAULT;
  721. err = compat_get_fastrpc_ioctl_mem_map(map32, map);
  722. if (err)
  723. return err;
  724. VERIFY(err, 0 == (err = fastrpc_internal_mem_map(fl,
  725. map)));
  726. if (err)
  727. return err;
  728. VERIFY(err, 0 == compat_put_fastrpc_ioctl_mem_map(map32, map));
  729. return err;
  730. }
  731. case COMPAT_FASTRPC_IOCTL_MEM_UNMAP:
  732. {
  733. struct compat_fastrpc_ioctl_mem_unmap __user *unmap32;
  734. struct fastrpc_ioctl_mem_unmap *unmap;
  735. unmap32 = compat_ptr(arg);
  736. unmap = kmalloc(sizeof(*unmap), GFP_KERNEL);
  737. if (unmap == NULL)
  738. return -EFAULT;
  739. err = compat_get_fastrpc_ioctl_mem_unmap(unmap32, unmap);
  740. if (err)
  741. return err;
  742. VERIFY(err, 0 == (err = fastrpc_internal_mem_unmap(fl,
  743. unmap)));
  744. return err;
  745. }
  746. case COMPAT_FASTRPC_IOCTL_MMAP:
  747. {
  748. struct compat_fastrpc_ioctl_mmap __user *map32;
  749. struct fastrpc_ioctl_mmap *map;
  750. map32 = compat_ptr(arg);
  751. VERIFY(err, NULL != (map = kmalloc(
  752. sizeof(*map), GFP_KERNEL)));
  753. if (err)
  754. return -EFAULT;
  755. VERIFY(err, 0 == compat_get_fastrpc_ioctl_mmap(map32, map));
  756. if (err)
  757. return err;
  758. VERIFY(err, 0 == (err = fastrpc_internal_mmap(fl, map)));
  759. VERIFY(err, 0 == compat_put_fastrpc_ioctl_mmap(map32, map));
  760. return err;
  761. }
  762. case COMPAT_FASTRPC_IOCTL_MMAP_64:
  763. {
  764. struct compat_fastrpc_ioctl_mmap_64 __user *map32;
  765. struct fastrpc_ioctl_mmap *map;
  766. map32 = compat_ptr(arg);
  767. VERIFY(err, NULL != (map = kmalloc(
  768. sizeof(*map), GFP_KERNEL)));
  769. if (err)
  770. return -EFAULT;
  771. VERIFY(err, 0 == compat_get_fastrpc_ioctl_mmap_64(map32, map));
  772. if (err)
  773. return err;
  774. VERIFY(err, 0 == (err = fastrpc_internal_mmap(fl, map)));
  775. VERIFY(err, 0 == compat_put_fastrpc_ioctl_mmap_64(map32, map));
  776. return err;
  777. }
  778. case COMPAT_FASTRPC_IOCTL_MUNMAP:
  779. {
  780. struct compat_fastrpc_ioctl_munmap __user *unmap32;
  781. struct fastrpc_ioctl_munmap *unmap;
  782. unmap32 = compat_ptr(arg);
  783. VERIFY(err, NULL != (unmap = kmalloc(
  784. sizeof(*unmap), GFP_KERNEL)));
  785. if (err)
  786. return -EFAULT;
  787. VERIFY(err, 0 == compat_get_fastrpc_ioctl_munmap(unmap32,
  788. unmap));
  789. if (err)
  790. return err;
  791. VERIFY(err, 0 == (err = fastrpc_internal_munmap(fl,
  792. unmap)));
  793. return err;
  794. }
  795. default:
  796. return -ENOIOCTLCMD;
  797. }
  798. }
  799. static long compat_fastrpc_dspsignal_create(struct fastrpc_file *fl, unsigned long arg)
  800. {
  801. struct fastrpc_ioctl_dspsignal_create __user *uc = compat_ptr(arg);
  802. struct fastrpc_ioctl_dspsignal_create c;
  803. int err = 0;
  804. err = copy_from_user(&c, uc, sizeof(c));
  805. if (err)
  806. return -EFAULT;
  807. return fastrpc_dspsignal_create(fl, &c);
  808. }
  809. static long compat_fastrpc_dspsignal_destroy(struct fastrpc_file *fl, unsigned long arg)
  810. {
  811. struct fastrpc_ioctl_dspsignal_destroy __user *uc = compat_ptr(arg);
  812. struct fastrpc_ioctl_dspsignal_destroy c;
  813. int err = 0;
  814. err = copy_from_user(&c, uc, sizeof(c));
  815. if (err)
  816. return -EFAULT;
  817. return fastrpc_dspsignal_destroy(fl, &c);
  818. }
  819. static long compat_fastrpc_dspsignal_signal(struct fastrpc_file *fl, unsigned long arg)
  820. {
  821. struct fastrpc_ioctl_dspsignal_signal __user *uc = compat_ptr(arg);
  822. struct fastrpc_ioctl_dspsignal_signal c;
  823. int err = 0;
  824. err = copy_from_user(&c, uc, sizeof(c));
  825. if (err)
  826. return -EFAULT;
  827. return fastrpc_dspsignal_signal(fl, &c);
  828. }
  829. static long compat_fastrpc_dspsignal_wait(struct fastrpc_file *fl, unsigned long arg)
  830. {
  831. struct fastrpc_ioctl_dspsignal_wait __user *uc = compat_ptr(arg);
  832. struct fastrpc_ioctl_dspsignal_wait c;
  833. int err = 0;
  834. err = copy_from_user(&c, uc, sizeof(c));
  835. if (err)
  836. return -EFAULT;
  837. return fastrpc_dspsignal_wait(fl, &c);
  838. }
  839. static long compat_fastrpc_dspsignal_cancel_wait(struct fastrpc_file *fl, unsigned long arg)
  840. {
  841. struct fastrpc_ioctl_dspsignal_cancel_wait __user *uc = compat_ptr(arg);
  842. struct fastrpc_ioctl_dspsignal_cancel_wait c;
  843. int err = 0;
  844. err = copy_from_user(&c, uc, sizeof(c));
  845. if (err)
  846. return -EFAULT;
  847. return fastrpc_dspsignal_cancel_wait(fl, &c);
  848. }
  849. long compat_fastrpc_device_ioctl(struct file *filp, unsigned int cmd,
  850. unsigned long arg)
  851. {
  852. int err = 0;
  853. struct fastrpc_file *fl = (struct fastrpc_file *)filp->private_data;
  854. if (!filp->f_op || !filp->f_op->unlocked_ioctl)
  855. return -ENOTTY;
  856. fl->is_compat = true;
  857. switch (cmd) {
  858. case COMPAT_FASTRPC_IOCTL_INVOKE:
  859. case COMPAT_FASTRPC_IOCTL_INVOKE_FD:
  860. case COMPAT_FASTRPC_IOCTL_INVOKE_ATTRS:
  861. case COMPAT_FASTRPC_IOCTL_INVOKE_CRC:
  862. case COMPAT_FASTRPC_IOCTL_INVOKE_PERF:
  863. {
  864. return compat_fastrpc_ioctl_invoke(filp, cmd, arg);
  865. }
  866. case COMPAT_FASTRPC_IOCTL_INVOKE2:
  867. {
  868. return compat_fastrpc_ioctl_invoke2(filp, cmd, arg);
  869. }
  870. case COMPAT_FASTRPC_IOCTL_MUNMAP_64:
  871. {
  872. struct compat_fastrpc_ioctl_munmap_64 __user *unmap32;
  873. struct fastrpc_ioctl_munmap *unmap;
  874. unmap32 = compat_ptr(arg);
  875. VERIFY(err, NULL != (unmap = kmalloc(
  876. sizeof(*unmap), GFP_KERNEL)));
  877. if (err)
  878. return -EFAULT;
  879. VERIFY(err, 0 == compat_get_fastrpc_ioctl_munmap_64(unmap32,
  880. unmap));
  881. if (err)
  882. return err;
  883. VERIFY(err, 0 == (err = fastrpc_internal_munmap(fl,
  884. unmap)));
  885. return err;
  886. }
  887. case COMPAT_FASTRPC_IOCTL_INIT:
  888. fallthrough;
  889. case COMPAT_FASTRPC_IOCTL_INIT_ATTRS:
  890. {
  891. struct compat_fastrpc_ioctl_init_attrs __user *init32;
  892. struct fastrpc_ioctl_init_attrs *init;
  893. init32 = compat_ptr(arg);
  894. VERIFY(err, NULL != (init = kmalloc(
  895. sizeof(*init), GFP_KERNEL)));
  896. if (err)
  897. return -EFAULT;
  898. VERIFY(err, 0 == compat_get_fastrpc_ioctl_init(init32,
  899. init, cmd));
  900. if (err)
  901. return err;
  902. VERIFY(err, 0 == (err = fastrpc_init_process(fl, init)));
  903. return err;
  904. }
  905. case FASTRPC_IOCTL_GETINFO:
  906. {
  907. compat_uptr_t __user *info32;
  908. uint32_t *info;
  909. compat_uint_t u;
  910. info32 = compat_ptr(arg);
  911. VERIFY(err, NULL != (info = kmalloc(
  912. sizeof(*info), GFP_KERNEL)));
  913. if (err)
  914. return -EFAULT;
  915. err = get_user(u, info32);
  916. memcpy(info, &u, sizeof(u));
  917. if (err)
  918. return err;
  919. VERIFY(err, 0 == (err = fastrpc_get_info(fl, info)));
  920. memcpy(&u, info, sizeof(*info));
  921. err |= put_user(u, info32);
  922. return err;
  923. }
  924. case FASTRPC_IOCTL_SETMODE:
  925. return fastrpc_setmode(arg, fl);
  926. case COMPAT_FASTRPC_IOCTL_CONTROL:
  927. {
  928. return compat_fastrpc_control(fl, arg);
  929. }
  930. case COMPAT_FASTRPC_IOCTL_GET_DSP_INFO:
  931. {
  932. return compat_fastrpc_get_dsp_info(fl, arg);
  933. }
  934. case COMPAT_FASTRPC_IOCTL_MEM_MAP:
  935. fallthrough;
  936. case COMPAT_FASTRPC_IOCTL_MEM_UNMAP:
  937. fallthrough;
  938. case COMPAT_FASTRPC_IOCTL_MMAP:
  939. fallthrough;
  940. case COMPAT_FASTRPC_IOCTL_MMAP_64:
  941. fallthrough;
  942. case COMPAT_FASTRPC_IOCTL_MUNMAP:
  943. return compat_fastrpc_mmap_device_ioctl(fl, cmd, arg);
  944. case COMPAT_FASTRPC_IOCTL_DSPSIGNAL_CREATE:
  945. return compat_fastrpc_dspsignal_create(fl, arg);
  946. case COMPAT_FASTRPC_IOCTL_DSPSIGNAL_DESTROY:
  947. return compat_fastrpc_dspsignal_destroy(fl, arg);
  948. case COMPAT_FASTRPC_IOCTL_DSPSIGNAL_SIGNAL:
  949. return compat_fastrpc_dspsignal_signal(fl, arg);
  950. case COMPAT_FASTRPC_IOCTL_DSPSIGNAL_WAIT:
  951. return compat_fastrpc_dspsignal_wait(fl, arg);
  952. case COMPAT_FASTRPC_IOCTL_DSPSIGNAL_CANCEL_WAIT:
  953. return compat_fastrpc_dspsignal_cancel_wait(fl, arg);
  954. default:
  955. return -ENOTTY;
  956. }
  957. }