blob: 0f07483eaf1deceb2b3a3f9cd0339f68098c8312 [file] [log] [blame]
Sathish Ambley69e1ab02016-10-18 10:28:15 -07001/*
Sathish Ambleya21b5b52017-01-11 16:11:01 -08002 * Copyright (c) 2014-2017, The Linux Foundation. All rights reserved.
Sathish Ambley69e1ab02016-10-18 10:28:15 -07003 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 and
6 * only version 2 as published by the Free Software Foundation.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 */
Sathish Ambley69e1ab02016-10-18 10:28:15 -070014#include <linux/compat.h>
15#include <linux/fs.h>
16#include <linux/uaccess.h>
17#include <linux/msm_ion.h>
18
19#include "adsprpc_compat.h"
20#include "adsprpc_shared.h"
21
22#define COMPAT_FASTRPC_IOCTL_INVOKE \
23 _IOWR('R', 1, struct compat_fastrpc_ioctl_invoke)
24#define COMPAT_FASTRPC_IOCTL_MMAP \
25 _IOWR('R', 2, struct compat_fastrpc_ioctl_mmap)
26#define COMPAT_FASTRPC_IOCTL_MUNMAP \
27 _IOWR('R', 3, struct compat_fastrpc_ioctl_munmap)
28#define COMPAT_FASTRPC_IOCTL_INVOKE_FD \
29 _IOWR('R', 4, struct compat_fastrpc_ioctl_invoke_fd)
30#define COMPAT_FASTRPC_IOCTL_INIT \
31 _IOWR('R', 6, struct compat_fastrpc_ioctl_init)
32#define COMPAT_FASTRPC_IOCTL_INVOKE_ATTRS \
33 _IOWR('R', 7, struct compat_fastrpc_ioctl_invoke_attrs)
Sathish Ambleya21b5b52017-01-11 16:11:01 -080034#define COMPAT_FASTRPC_IOCTL_GETPERF \
35 _IOWR('R', 9, struct compat_fastrpc_ioctl_perf)
Sathish Ambleyd6300c32017-01-18 09:50:43 -080036#define COMPAT_FASTRPC_IOCTL_INIT_ATTRS \
37 _IOWR('R', 10, struct compat_fastrpc_ioctl_init_attrs)
Sathish Ambleybae51902017-07-03 15:00:49 -070038#define COMPAT_FASTRPC_IOCTL_INVOKE_CRC \
39 _IOWR('R', 11, struct compat_fastrpc_ioctl_invoke_crc)
Tharun Kumar Merugu5f6ca61c2017-08-11 11:43:11 +053040#define COMPAT_FASTRPC_IOCTL_CONTROL \
41 _IOWR('R', 12, struct compat_fastrpc_ioctl_control)
Sathish Ambley69e1ab02016-10-18 10:28:15 -070042
43struct compat_remote_buf {
44 compat_uptr_t pv; /* buffer pointer */
Tharun Kumar Merugufb51f942017-12-07 10:32:15 +053045 compat_size_t len; /* length of buffer */
Sathish Ambley69e1ab02016-10-18 10:28:15 -070046};
47
48union compat_remote_arg {
49 struct compat_remote_buf buf;
50 compat_uint_t h;
51};
52
53struct compat_fastrpc_ioctl_invoke {
54 compat_uint_t handle; /* remote handle */
55 compat_uint_t sc; /* scalars describing the data */
56 compat_uptr_t pra; /* remote arguments list */
57};
58
59struct compat_fastrpc_ioctl_invoke_fd {
60 struct compat_fastrpc_ioctl_invoke inv;
61 compat_uptr_t fds; /* fd list */
62};
63
64struct compat_fastrpc_ioctl_invoke_attrs {
65 struct compat_fastrpc_ioctl_invoke inv;
66 compat_uptr_t fds; /* fd list */
67 compat_uptr_t attrs; /* attribute list */
68};
69
Sathish Ambleybae51902017-07-03 15:00:49 -070070struct compat_fastrpc_ioctl_invoke_crc {
71 struct compat_fastrpc_ioctl_invoke inv;
72 compat_uptr_t fds; /* fd list */
73 compat_uptr_t attrs; /* attribute list */
74 compat_uptr_t crc; /* crc list */
75};
76
Sathish Ambley69e1ab02016-10-18 10:28:15 -070077struct compat_fastrpc_ioctl_mmap {
78 compat_int_t fd; /* ion fd */
79 compat_uint_t flags; /* flags for dsp to map with */
80 compat_uptr_t vaddrin; /* optional virtual address */
Tharun Kumar Merugufb51f942017-12-07 10:32:15 +053081 compat_size_t size; /* size */
Sathish Ambley69e1ab02016-10-18 10:28:15 -070082 compat_uptr_t vaddrout; /* dsps virtual address */
83};
84
85struct compat_fastrpc_ioctl_munmap {
86 compat_uptr_t vaddrout; /* address to unmap */
Tharun Kumar Merugufb51f942017-12-07 10:32:15 +053087 compat_size_t size; /* size */
Sathish Ambley69e1ab02016-10-18 10:28:15 -070088};
89
90struct compat_fastrpc_ioctl_init {
91 compat_uint_t flags; /* one of FASTRPC_INIT_* macros */
92 compat_uptr_t file; /* pointer to elf file */
93 compat_int_t filelen; /* elf file length */
94 compat_int_t filefd; /* ION fd for the file */
95 compat_uptr_t mem; /* mem for the PD */
96 compat_int_t memlen; /* mem length */
97 compat_int_t memfd; /* ION fd for the mem */
98};
99
Sathish Ambleyd6300c32017-01-18 09:50:43 -0800100struct compat_fastrpc_ioctl_init_attrs {
101 struct compat_fastrpc_ioctl_init init;
102 compat_int_t attrs; /* attributes to init process */
103 compat_int_t siglen; /* test signature file length */
104};
105
Sathish Ambleya21b5b52017-01-11 16:11:01 -0800106struct compat_fastrpc_ioctl_perf { /* kernel performance data */
107 compat_uptr_t data;
108 compat_int_t numkeys;
109 compat_uptr_t keys;
110};
111
Tharun Kumar Merugu5f6ca61c2017-08-11 11:43:11 +0530112#define FASTRPC_CONTROL_LATENCY (1)
113struct compat_fastrpc_ctrl_latency {
114 compat_uint_t enable; /* latency control enable */
115 compat_uint_t level; /* level of control */
116};
117
118struct compat_fastrpc_ioctl_control {
119 compat_uint_t req;
120 union {
121 struct compat_fastrpc_ctrl_latency lp;
122 };
123};
124
Sathish Ambley69e1ab02016-10-18 10:28:15 -0700125static int compat_get_fastrpc_ioctl_invoke(
Sathish Ambleybae51902017-07-03 15:00:49 -0700126 struct compat_fastrpc_ioctl_invoke_crc __user *inv32,
127 struct fastrpc_ioctl_invoke_crc __user **inva,
Sathish Ambley69e1ab02016-10-18 10:28:15 -0700128 unsigned int cmd)
129{
130 compat_uint_t u, sc;
Tharun Kumar Merugufb51f942017-12-07 10:32:15 +0530131 compat_size_t s;
Sathish Ambley69e1ab02016-10-18 10:28:15 -0700132 compat_uptr_t p;
Sathish Ambleybae51902017-07-03 15:00:49 -0700133 struct fastrpc_ioctl_invoke_crc *inv;
Sathish Ambley69e1ab02016-10-18 10:28:15 -0700134 union compat_remote_arg *pra32;
135 union remote_arg *pra;
Sathish Ambley58dc64d2016-11-29 17:11:53 -0800136 int err, len, j;
Sathish Ambley69e1ab02016-10-18 10:28:15 -0700137
138 err = get_user(sc, &inv32->inv.sc);
139 if (err)
140 return err;
141
142 len = REMOTE_SCALARS_LENGTH(sc);
143 VERIFY(err, NULL != (inv = compat_alloc_user_space(
144 sizeof(*inv) + len * sizeof(*pra))));
145 if (err)
146 return -EFAULT;
147
148 pra = (union remote_arg *)(inv + 1);
149 err = put_user(pra, &inv->inv.pra);
150 err |= put_user(sc, &inv->inv.sc);
151 err |= get_user(u, &inv32->inv.handle);
152 err |= put_user(u, &inv->inv.handle);
153 err |= get_user(p, &inv32->inv.pra);
154 if (err)
155 return err;
156
157 pra32 = compat_ptr(p);
158 pra = (union remote_arg *)(inv + 1);
Sathish Ambley58dc64d2016-11-29 17:11:53 -0800159 for (j = 0; j < len; j++) {
Sathish Ambley69e1ab02016-10-18 10:28:15 -0700160 err |= get_user(p, &pra32[j].buf.pv);
161 err |= put_user(p, (uintptr_t *)&pra[j].buf.pv);
162 err |= get_user(s, &pra32[j].buf.len);
163 err |= put_user(s, &pra[j].buf.len);
164 }
Sathish Ambley69e1ab02016-10-18 10:28:15 -0700165
166 err |= put_user(NULL, &inv->fds);
167 if (cmd != COMPAT_FASTRPC_IOCTL_INVOKE) {
168 err |= get_user(p, &inv32->fds);
169 err |= put_user(p, (compat_uptr_t *)&inv->fds);
170 }
171 err |= put_user(NULL, &inv->attrs);
Sathish Ambleybae51902017-07-03 15:00:49 -0700172 if ((cmd == COMPAT_FASTRPC_IOCTL_INVOKE_ATTRS) ||
173 (cmd == COMPAT_FASTRPC_IOCTL_INVOKE_CRC)) {
Sathish Ambley69e1ab02016-10-18 10:28:15 -0700174 err |= get_user(p, &inv32->attrs);
175 err |= put_user(p, (compat_uptr_t *)&inv->attrs);
176 }
Sathish Ambleybae51902017-07-03 15:00:49 -0700177 err |= put_user(NULL, (compat_uptr_t __user **)&inv->crc);
178 if (cmd == COMPAT_FASTRPC_IOCTL_INVOKE_CRC) {
179 err |= get_user(p, &inv32->crc);
180 err |= put_user(p, (compat_uptr_t __user *)&inv->crc);
181 }
Sathish Ambley69e1ab02016-10-18 10:28:15 -0700182
183 *inva = inv;
184 return err;
185}
186
Sathish Ambley69e1ab02016-10-18 10:28:15 -0700187static int compat_get_fastrpc_ioctl_mmap(
188 struct compat_fastrpc_ioctl_mmap __user *map32,
189 struct fastrpc_ioctl_mmap __user *map)
190{
191 compat_uint_t u;
192 compat_int_t i;
Tharun Kumar Merugufb51f942017-12-07 10:32:15 +0530193 compat_size_t s;
Sathish Ambley69e1ab02016-10-18 10:28:15 -0700194 compat_uptr_t p;
195 int err;
196
197 err = get_user(i, &map32->fd);
198 err |= put_user(i, &map->fd);
199 err |= get_user(u, &map32->flags);
200 err |= put_user(u, &map->flags);
201 err |= get_user(p, &map32->vaddrin);
202 err |= put_user(p, (uintptr_t *)&map->vaddrin);
203 err |= get_user(s, &map32->size);
204 err |= put_user(s, &map->size);
205
206 return err;
207}
208
209static int compat_put_fastrpc_ioctl_mmap(
210 struct compat_fastrpc_ioctl_mmap __user *map32,
211 struct fastrpc_ioctl_mmap __user *map)
212{
213 compat_uptr_t p;
214 int err;
215
216 err = get_user(p, &map->vaddrout);
217 err |= put_user(p, &map32->vaddrout);
218
219 return err;
220}
221
222static int compat_get_fastrpc_ioctl_munmap(
223 struct compat_fastrpc_ioctl_munmap __user *unmap32,
224 struct fastrpc_ioctl_munmap __user *unmap)
225{
226 compat_uptr_t p;
Tharun Kumar Merugufb51f942017-12-07 10:32:15 +0530227 compat_size_t s;
Sathish Ambley69e1ab02016-10-18 10:28:15 -0700228 int err;
229
230 err = get_user(p, &unmap32->vaddrout);
231 err |= put_user(p, &unmap->vaddrout);
232 err |= get_user(s, &unmap32->size);
233 err |= put_user(s, &unmap->size);
234
235 return err;
236}
237
Sathish Ambleya21b5b52017-01-11 16:11:01 -0800238static int compat_get_fastrpc_ioctl_perf(
239 struct compat_fastrpc_ioctl_perf __user *perf32,
240 struct fastrpc_ioctl_perf __user *perf)
241{
242 compat_uptr_t p;
243 int err;
244
245 err = get_user(p, &perf32->data);
246 err |= put_user(p, &perf->data);
247 err |= get_user(p, &perf32->keys);
248 err |= put_user(p, &perf->keys);
249
250 return err;
251}
252
Tharun Kumar Merugu5f6ca61c2017-08-11 11:43:11 +0530253static int compat_get_fastrpc_ioctl_control(
254 struct compat_fastrpc_ioctl_control __user *ctrl32,
255 struct fastrpc_ioctl_control __user *ctrl)
256{
257 compat_uptr_t p;
258 int err;
259
260 err = get_user(p, &ctrl32->req);
261 err |= put_user(p, &ctrl->req);
262 if (p == FASTRPC_CONTROL_LATENCY) {
263 err |= get_user(p, &ctrl32->lp.enable);
264 err |= put_user(p, &ctrl->lp.enable);
265 err |= get_user(p, &ctrl32->lp.level);
266 err |= put_user(p, &ctrl->lp.level);
267 }
268
269 return err;
270}
271
Sathish Ambley69e1ab02016-10-18 10:28:15 -0700272static int compat_get_fastrpc_ioctl_init(
Sathish Ambleyd6300c32017-01-18 09:50:43 -0800273 struct compat_fastrpc_ioctl_init_attrs __user *init32,
274 struct fastrpc_ioctl_init_attrs __user *init,
275 unsigned int cmd)
Sathish Ambley69e1ab02016-10-18 10:28:15 -0700276{
277 compat_uint_t u;
278 compat_uptr_t p;
279 compat_int_t i;
280 int err;
281
Sathish Ambleyd6300c32017-01-18 09:50:43 -0800282 err = get_user(u, &init32->init.flags);
283 err |= put_user(u, &init->init.flags);
284 err |= get_user(p, &init32->init.file);
285 err |= put_user(p, &init->init.file);
286 err |= get_user(i, &init32->init.filelen);
287 err |= put_user(i, &init->init.filelen);
288 err |= get_user(i, &init32->init.filefd);
289 err |= put_user(i, &init->init.filefd);
290 err |= get_user(p, &init32->init.mem);
291 err |= put_user(p, &init->init.mem);
292 err |= get_user(i, &init32->init.memlen);
293 err |= put_user(i, &init->init.memlen);
294 err |= get_user(i, &init32->init.memfd);
295 err |= put_user(i, &init->init.memfd);
296
297 err |= put_user(0, &init->attrs);
298 if (cmd == COMPAT_FASTRPC_IOCTL_INIT_ATTRS) {
299 err |= get_user(i, &init32->attrs);
300 err |= put_user(i, (compat_uptr_t *)&init->attrs);
301 }
302
303 err |= put_user(0, &init->siglen);
304 if (cmd == COMPAT_FASTRPC_IOCTL_INIT_ATTRS) {
305 err |= get_user(i, &init32->siglen);
306 err |= put_user(i, (compat_uptr_t *)&init->siglen);
307 }
Sathish Ambley69e1ab02016-10-18 10:28:15 -0700308
309 return err;
310}
311
312long compat_fastrpc_device_ioctl(struct file *filp, unsigned int cmd,
313 unsigned long arg)
314{
315 int err = 0;
316
317 if (!filp->f_op || !filp->f_op->unlocked_ioctl)
318 return -ENOTTY;
319
320 switch (cmd) {
321 case COMPAT_FASTRPC_IOCTL_INVOKE:
322 case COMPAT_FASTRPC_IOCTL_INVOKE_FD:
323 case COMPAT_FASTRPC_IOCTL_INVOKE_ATTRS:
Sathish Ambleybae51902017-07-03 15:00:49 -0700324 case COMPAT_FASTRPC_IOCTL_INVOKE_CRC:
Sathish Ambley69e1ab02016-10-18 10:28:15 -0700325 {
Sathish Ambleybae51902017-07-03 15:00:49 -0700326 struct compat_fastrpc_ioctl_invoke_crc __user *inv32;
327 struct fastrpc_ioctl_invoke_crc __user *inv;
Sathish Ambley69e1ab02016-10-18 10:28:15 -0700328
329 inv32 = compat_ptr(arg);
330 VERIFY(err, 0 == compat_get_fastrpc_ioctl_invoke(inv32,
331 &inv, cmd));
332 if (err)
333 return err;
Sathish Ambley58dc64d2016-11-29 17:11:53 -0800334 return filp->f_op->unlocked_ioctl(filp,
Sathish Ambleybae51902017-07-03 15:00:49 -0700335 FASTRPC_IOCTL_INVOKE_CRC, (unsigned long)inv);
Sathish Ambley69e1ab02016-10-18 10:28:15 -0700336 }
337 case COMPAT_FASTRPC_IOCTL_MMAP:
338 {
339 struct compat_fastrpc_ioctl_mmap __user *map32;
340 struct fastrpc_ioctl_mmap __user *map;
341 long ret;
342
343 map32 = compat_ptr(arg);
344 VERIFY(err, NULL != (map = compat_alloc_user_space(
345 sizeof(*map))));
346 if (err)
347 return -EFAULT;
348 VERIFY(err, 0 == compat_get_fastrpc_ioctl_mmap(map32, map));
349 if (err)
350 return err;
351 ret = filp->f_op->unlocked_ioctl(filp, FASTRPC_IOCTL_MMAP,
352 (unsigned long)map);
353 if (ret)
354 return ret;
355 VERIFY(err, 0 == compat_put_fastrpc_ioctl_mmap(map32, map));
356 return err;
357 }
358 case COMPAT_FASTRPC_IOCTL_MUNMAP:
359 {
360 struct compat_fastrpc_ioctl_munmap __user *unmap32;
361 struct fastrpc_ioctl_munmap __user *unmap;
362
363 unmap32 = compat_ptr(arg);
364 VERIFY(err, NULL != (unmap = compat_alloc_user_space(
365 sizeof(*unmap))));
366 if (err)
367 return -EFAULT;
368 VERIFY(err, 0 == compat_get_fastrpc_ioctl_munmap(unmap32,
369 unmap));
370 if (err)
371 return err;
372 return filp->f_op->unlocked_ioctl(filp, FASTRPC_IOCTL_MUNMAP,
373 (unsigned long)unmap);
374 }
375 case COMPAT_FASTRPC_IOCTL_INIT:
Sathish Ambleyd6300c32017-01-18 09:50:43 -0800376 /* fall through */
377 case COMPAT_FASTRPC_IOCTL_INIT_ATTRS:
Sathish Ambley69e1ab02016-10-18 10:28:15 -0700378 {
Sathish Ambleyd6300c32017-01-18 09:50:43 -0800379 struct compat_fastrpc_ioctl_init_attrs __user *init32;
380 struct fastrpc_ioctl_init_attrs __user *init;
Sathish Ambley69e1ab02016-10-18 10:28:15 -0700381
382 init32 = compat_ptr(arg);
383 VERIFY(err, NULL != (init = compat_alloc_user_space(
384 sizeof(*init))));
385 if (err)
386 return -EFAULT;
387 VERIFY(err, 0 == compat_get_fastrpc_ioctl_init(init32,
Sathish Ambleyd6300c32017-01-18 09:50:43 -0800388 init, cmd));
Sathish Ambley69e1ab02016-10-18 10:28:15 -0700389 if (err)
390 return err;
Sathish Ambleyd6300c32017-01-18 09:50:43 -0800391 return filp->f_op->unlocked_ioctl(filp,
392 FASTRPC_IOCTL_INIT_ATTRS, (unsigned long)init);
Sathish Ambley69e1ab02016-10-18 10:28:15 -0700393 }
394 case FASTRPC_IOCTL_GETINFO:
395 {
396 compat_uptr_t __user *info32;
397 uint32_t __user *info;
398 compat_uint_t u;
399 long ret;
400
401 info32 = compat_ptr(arg);
402 VERIFY(err, NULL != (info = compat_alloc_user_space(
403 sizeof(*info))));
404 if (err)
405 return -EFAULT;
Sathish Ambley36849af2017-02-02 09:35:55 -0800406 err = get_user(u, info32);
407 err |= put_user(u, info);
408 if (err)
409 return err;
Sathish Ambley69e1ab02016-10-18 10:28:15 -0700410 ret = filp->f_op->unlocked_ioctl(filp, FASTRPC_IOCTL_GETINFO,
411 (unsigned long)info);
412 if (ret)
413 return ret;
414 err = get_user(u, info);
415 err |= put_user(u, info32);
416 return err;
417 }
418 case FASTRPC_IOCTL_SETMODE:
419 return filp->f_op->unlocked_ioctl(filp, cmd,
420 (unsigned long)compat_ptr(arg));
Tharun Kumar Merugu5f6ca61c2017-08-11 11:43:11 +0530421 case COMPAT_FASTRPC_IOCTL_CONTROL:
422 {
423 struct compat_fastrpc_ioctl_control __user *ctrl32;
424 struct fastrpc_ioctl_control __user *ctrl;
425
426 ctrl32 = compat_ptr(arg);
427 VERIFY(err, NULL != (ctrl = compat_alloc_user_space(
428 sizeof(*ctrl))));
429 if (err)
430 return -EFAULT;
431 VERIFY(err, 0 == compat_get_fastrpc_ioctl_control(ctrl32,
432 ctrl));
433 if (err)
434 return err;
435 err = filp->f_op->unlocked_ioctl(filp, FASTRPC_IOCTL_CONTROL,
436 (unsigned long)ctrl);
437 return err;
438 }
Sathish Ambleya21b5b52017-01-11 16:11:01 -0800439 case COMPAT_FASTRPC_IOCTL_GETPERF:
440 {
441 struct compat_fastrpc_ioctl_perf __user *perf32;
442 struct fastrpc_ioctl_perf *perf;
443 compat_uint_t u;
444 long ret;
445
446 perf32 = compat_ptr(arg);
447 VERIFY(err, NULL != (perf = compat_alloc_user_space(
448 sizeof(*perf))));
449 if (err)
450 return -EFAULT;
451 VERIFY(err, 0 == compat_get_fastrpc_ioctl_perf(perf32,
452 perf));
453 if (err)
454 return err;
455 ret = filp->f_op->unlocked_ioctl(filp, FASTRPC_IOCTL_GETPERF,
456 (unsigned long)perf);
457 if (ret)
458 return ret;
459 err = get_user(u, &perf->numkeys);
460 err |= put_user(u, &perf32->numkeys);
461 return err;
462 }
Sathish Ambley69e1ab02016-10-18 10:28:15 -0700463 default:
464 return -ENOIOCTLCMD;
465 }
466}