adsprpc_compat.c 29 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085
  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, COMPAT_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, true)));
  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. size_t info_size = 0;
  691. info32 = compat_ptr(arg);
  692. VERIFY(err, NULL != (info = kmalloc(
  693. sizeof(*info), GFP_KERNEL)));
  694. info_size = sizeof(*info);
  695. if (err) {
  696. ADSPRPC_ERR("allocation failed for size 0x%zx\n", info_size);
  697. return err;
  698. }
  699. err = get_user(u, &info32->domain);
  700. if (err)
  701. return err;
  702. memcpy(&info->domain, &u, sizeof(info->domain));
  703. err = get_user(u, &info32->attribute_ID);
  704. if (err)
  705. return err;
  706. memcpy(&info->attribute_ID, &u, sizeof(info->attribute_ID));
  707. err = fastrpc_get_info_from_kernel(info, fl);
  708. if (err)
  709. return err;
  710. err = compat_put_fastrpc_ioctl_get_dsp_info(info32, info);
  711. return err;
  712. }
  713. static inline long compat_fastrpc_mmap_device_ioctl(struct fastrpc_file *fl,
  714. unsigned int cmd, unsigned long arg)
  715. {
  716. int err = 0;
  717. switch (cmd) {
  718. case COMPAT_FASTRPC_IOCTL_MEM_MAP:
  719. {
  720. struct compat_fastrpc_ioctl_mem_map __user *map32;
  721. struct fastrpc_ioctl_mem_map *map;
  722. map32 = compat_ptr(arg);
  723. VERIFY(err, NULL != (map = kmalloc(
  724. sizeof(*map), GFP_KERNEL)));
  725. if (err)
  726. return -EFAULT;
  727. err = compat_get_fastrpc_ioctl_mem_map(map32, map);
  728. if (err)
  729. return err;
  730. VERIFY(err, 0 == (err = fastrpc_internal_mem_map(fl,
  731. map)));
  732. if (err)
  733. return err;
  734. VERIFY(err, 0 == compat_put_fastrpc_ioctl_mem_map(map32, map));
  735. return err;
  736. }
  737. case COMPAT_FASTRPC_IOCTL_MEM_UNMAP:
  738. {
  739. struct compat_fastrpc_ioctl_mem_unmap __user *unmap32;
  740. struct fastrpc_ioctl_mem_unmap *unmap;
  741. unmap32 = compat_ptr(arg);
  742. unmap = kmalloc(sizeof(*unmap), GFP_KERNEL);
  743. if (unmap == NULL)
  744. return -EFAULT;
  745. err = compat_get_fastrpc_ioctl_mem_unmap(unmap32, unmap);
  746. if (err)
  747. return err;
  748. VERIFY(err, 0 == (err = fastrpc_internal_mem_unmap(fl,
  749. unmap)));
  750. return err;
  751. }
  752. case COMPAT_FASTRPC_IOCTL_MMAP:
  753. {
  754. struct compat_fastrpc_ioctl_mmap __user *map32;
  755. struct fastrpc_ioctl_mmap *map;
  756. map32 = compat_ptr(arg);
  757. VERIFY(err, NULL != (map = kmalloc(
  758. sizeof(*map), GFP_KERNEL)));
  759. if (err)
  760. return -EFAULT;
  761. VERIFY(err, 0 == compat_get_fastrpc_ioctl_mmap(map32, map));
  762. if (err)
  763. return err;
  764. VERIFY(err, 0 == (err = fastrpc_internal_mmap(fl, map)));
  765. VERIFY(err, 0 == compat_put_fastrpc_ioctl_mmap(map32, map));
  766. return err;
  767. }
  768. case COMPAT_FASTRPC_IOCTL_MMAP_64:
  769. {
  770. struct compat_fastrpc_ioctl_mmap_64 __user *map32;
  771. struct fastrpc_ioctl_mmap *map;
  772. map32 = compat_ptr(arg);
  773. VERIFY(err, NULL != (map = kmalloc(
  774. sizeof(*map), GFP_KERNEL)));
  775. if (err)
  776. return -EFAULT;
  777. VERIFY(err, 0 == compat_get_fastrpc_ioctl_mmap_64(map32, map));
  778. if (err)
  779. return err;
  780. VERIFY(err, 0 == (err = fastrpc_internal_mmap(fl, map)));
  781. VERIFY(err, 0 == compat_put_fastrpc_ioctl_mmap_64(map32, map));
  782. return err;
  783. }
  784. case COMPAT_FASTRPC_IOCTL_MUNMAP:
  785. {
  786. struct compat_fastrpc_ioctl_munmap __user *unmap32;
  787. struct fastrpc_ioctl_munmap *unmap;
  788. unmap32 = compat_ptr(arg);
  789. VERIFY(err, NULL != (unmap = kmalloc(
  790. sizeof(*unmap), GFP_KERNEL)));
  791. if (err)
  792. return -EFAULT;
  793. VERIFY(err, 0 == compat_get_fastrpc_ioctl_munmap(unmap32,
  794. unmap));
  795. if (err)
  796. return err;
  797. VERIFY(err, 0 == (err = fastrpc_internal_munmap(fl,
  798. unmap)));
  799. return err;
  800. }
  801. default:
  802. return -ENOIOCTLCMD;
  803. }
  804. }
  805. static long compat_fastrpc_dspsignal_create(struct fastrpc_file *fl, unsigned long arg)
  806. {
  807. struct fastrpc_ioctl_dspsignal_create __user *uc = compat_ptr(arg);
  808. struct fastrpc_ioctl_dspsignal_create c;
  809. int err = 0;
  810. err = copy_from_user(&c, uc, sizeof(c));
  811. if (err)
  812. return -EFAULT;
  813. return fastrpc_dspsignal_create(fl, &c);
  814. }
  815. static long compat_fastrpc_dspsignal_destroy(struct fastrpc_file *fl, unsigned long arg)
  816. {
  817. struct fastrpc_ioctl_dspsignal_destroy __user *uc = compat_ptr(arg);
  818. struct fastrpc_ioctl_dspsignal_destroy c;
  819. int err = 0;
  820. err = copy_from_user(&c, uc, sizeof(c));
  821. if (err)
  822. return -EFAULT;
  823. return fastrpc_dspsignal_destroy(fl, &c);
  824. }
  825. static long compat_fastrpc_dspsignal_signal(struct fastrpc_file *fl, unsigned long arg)
  826. {
  827. struct fastrpc_ioctl_dspsignal_signal __user *uc = compat_ptr(arg);
  828. struct fastrpc_ioctl_dspsignal_signal c;
  829. int err = 0;
  830. err = copy_from_user(&c, uc, sizeof(c));
  831. if (err)
  832. return -EFAULT;
  833. return fastrpc_dspsignal_signal(fl, &c);
  834. }
  835. static long compat_fastrpc_dspsignal_wait(struct fastrpc_file *fl, unsigned long arg)
  836. {
  837. struct fastrpc_ioctl_dspsignal_wait __user *uc = compat_ptr(arg);
  838. struct fastrpc_ioctl_dspsignal_wait c;
  839. int err = 0;
  840. err = copy_from_user(&c, uc, sizeof(c));
  841. if (err)
  842. return -EFAULT;
  843. return fastrpc_dspsignal_wait(fl, &c);
  844. }
  845. static long compat_fastrpc_dspsignal_cancel_wait(struct fastrpc_file *fl, unsigned long arg)
  846. {
  847. struct fastrpc_ioctl_dspsignal_cancel_wait __user *uc = compat_ptr(arg);
  848. struct fastrpc_ioctl_dspsignal_cancel_wait c;
  849. int err = 0;
  850. err = copy_from_user(&c, uc, sizeof(c));
  851. if (err)
  852. return -EFAULT;
  853. return fastrpc_dspsignal_cancel_wait(fl, &c);
  854. }
  855. long compat_fastrpc_device_ioctl(struct file *filp, unsigned int cmd,
  856. unsigned long arg)
  857. {
  858. int err = 0;
  859. struct fastrpc_file *fl = (struct fastrpc_file *)filp->private_data;
  860. if (!filp->f_op || !filp->f_op->unlocked_ioctl)
  861. return -ENOTTY;
  862. switch (cmd) {
  863. case COMPAT_FASTRPC_IOCTL_INVOKE:
  864. case COMPAT_FASTRPC_IOCTL_INVOKE_FD:
  865. case COMPAT_FASTRPC_IOCTL_INVOKE_ATTRS:
  866. case COMPAT_FASTRPC_IOCTL_INVOKE_CRC:
  867. case COMPAT_FASTRPC_IOCTL_INVOKE_PERF:
  868. {
  869. return compat_fastrpc_ioctl_invoke(filp, cmd, arg);
  870. }
  871. case COMPAT_FASTRPC_IOCTL_INVOKE2:
  872. {
  873. return compat_fastrpc_ioctl_invoke2(filp, cmd, arg);
  874. }
  875. case COMPAT_FASTRPC_IOCTL_MUNMAP_64:
  876. {
  877. struct compat_fastrpc_ioctl_munmap_64 __user *unmap32;
  878. struct fastrpc_ioctl_munmap *unmap;
  879. unmap32 = compat_ptr(arg);
  880. VERIFY(err, NULL != (unmap = kmalloc(
  881. sizeof(*unmap), GFP_KERNEL)));
  882. if (err)
  883. return -EFAULT;
  884. VERIFY(err, 0 == compat_get_fastrpc_ioctl_munmap_64(unmap32,
  885. unmap));
  886. if (err)
  887. return err;
  888. VERIFY(err, 0 == (err = fastrpc_internal_munmap(fl,
  889. unmap)));
  890. return err;
  891. }
  892. case COMPAT_FASTRPC_IOCTL_INIT:
  893. fallthrough;
  894. case COMPAT_FASTRPC_IOCTL_INIT_ATTRS:
  895. {
  896. struct compat_fastrpc_ioctl_init_attrs __user *init32;
  897. struct fastrpc_ioctl_init_attrs *init;
  898. init32 = compat_ptr(arg);
  899. VERIFY(err, NULL != (init = kmalloc(
  900. sizeof(*init), GFP_KERNEL)));
  901. if (err)
  902. return -EFAULT;
  903. VERIFY(err, 0 == compat_get_fastrpc_ioctl_init(init32,
  904. init, cmd));
  905. if (err)
  906. return err;
  907. VERIFY(err, 0 == (err = fastrpc_init_process(fl, init)));
  908. return err;
  909. }
  910. case FASTRPC_IOCTL_GETINFO:
  911. {
  912. compat_uptr_t __user *info32;
  913. uint32_t *info;
  914. compat_uint_t u;
  915. info32 = compat_ptr(arg);
  916. VERIFY(err, NULL != (info = kmalloc(
  917. sizeof(*info), GFP_KERNEL)));
  918. if (err)
  919. return -EFAULT;
  920. err = get_user(u, info32);
  921. memcpy(info, &u, sizeof(u));
  922. if (err)
  923. return err;
  924. VERIFY(err, 0 == (err = fastrpc_get_info(fl, info)));
  925. memcpy(&u, info, sizeof(*info));
  926. err |= put_user(u, info32);
  927. return err;
  928. }
  929. case FASTRPC_IOCTL_SETMODE:
  930. return fastrpc_setmode(arg, fl);
  931. case COMPAT_FASTRPC_IOCTL_CONTROL:
  932. {
  933. return compat_fastrpc_control(fl, arg);
  934. }
  935. case COMPAT_FASTRPC_IOCTL_GET_DSP_INFO:
  936. {
  937. return compat_fastrpc_get_dsp_info(fl, arg);
  938. }
  939. case COMPAT_FASTRPC_IOCTL_MEM_MAP:
  940. fallthrough;
  941. case COMPAT_FASTRPC_IOCTL_MEM_UNMAP:
  942. fallthrough;
  943. case COMPAT_FASTRPC_IOCTL_MMAP:
  944. fallthrough;
  945. case COMPAT_FASTRPC_IOCTL_MMAP_64:
  946. fallthrough;
  947. case COMPAT_FASTRPC_IOCTL_MUNMAP:
  948. return compat_fastrpc_mmap_device_ioctl(fl, cmd, arg);
  949. case COMPAT_FASTRPC_IOCTL_DSPSIGNAL_CREATE:
  950. return compat_fastrpc_dspsignal_create(fl, arg);
  951. case COMPAT_FASTRPC_IOCTL_DSPSIGNAL_DESTROY:
  952. return compat_fastrpc_dspsignal_destroy(fl, arg);
  953. case COMPAT_FASTRPC_IOCTL_DSPSIGNAL_SIGNAL:
  954. return compat_fastrpc_dspsignal_signal(fl, arg);
  955. case COMPAT_FASTRPC_IOCTL_DSPSIGNAL_WAIT:
  956. return compat_fastrpc_dspsignal_wait(fl, arg);
  957. case COMPAT_FASTRPC_IOCTL_DSPSIGNAL_CANCEL_WAIT:
  958. return compat_fastrpc_dspsignal_cancel_wait(fl, arg);
  959. default:
  960. return -ENOTTY;
  961. }
  962. }