1 /*
2 * Copyright (c) 2019, The Linux Foundation. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are
6 * met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above
10 * copyright notice, this list of conditions and the following
11 * disclaimer in the documentation and/or other materials provided
12 * with the distribution.
13 * * Neither the name of The Linux Foundation nor the names of its
14 * contributors may be used to endorse or promote products derived
15 * from this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
18 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
19 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
20 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
21 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
24 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
25 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
26 * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
27 * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 */
29
30 //#include "qurt_mutex.h"
31 #include <stdio.h>
32 #include <string.h>
33 #include <errno.h>
34 #include <unistd.h>
35 #include <assert.h>
36 #include <pthread.h>
37 #include <dlfcn.h>
38 #include <stdlib.h>
39 #include <sys/eventfd.h>
40
41 #include "platform_libs.h"
42 #include "HAP_farf.h"
43 #include "verify.h"
44 #include "mod_table.h"
45 #include "remote_priv.h"
46 #include "rpcmem.h"
47 #include "adsp_listener.h"
48 #include "listener_buf.h"
49 #include "shared.h"
50 #include "AEEstd.h"
51 #include "fastrpc_apps_user.h"
52 #include "AEEStdErr.h"
53
54 #define LOGL(format, ...) VERIFY_PRINT_INFO(format, ##__VA_ARGS__)
55 #ifndef MALLOC
56 #define MALLOC malloc
57 #endif
58
59 #ifndef CALLOC
60 #define CALLOC calloc
61 #endif
62
63 #ifndef FREE
64 #define FREE free
65 #endif
66
67 #ifndef REALLOC
68 #define REALLOC realloc
69 #endif
70
71 #ifndef FREEIF
72 #define FREEIF(pv) \
73 do {\
74 if(pv) { \
75 void* tmp = (void*)pv;\
76 pv = 0;\
77 FREE(tmp);\
78 } \
79 } while(0)
80 #endif
81
82 #include <unistd.h>
83 #include <stdio.h>
84 #include <string.h>
85 #include <errno.h>
86 #include <unistd.h>
87 #include <sys/eventfd.h>
88
89 struct listener {
90 pthread_t thread;
91 int eventfd;
92 };
93
94 static struct listener linfo[NUM_DOMAINS_EXTEND] =
95 { [0 ... NUM_DOMAINS_EXTEND - 1] = { .thread = 0, .eventfd = -1 } };
96
97 //TODO: fix this to work over any number of buffers
98 // needs qaic to support extra buffers
99 #define MAX_BUFS 250
100 struct invoke_bufs {
101 adsp_listener_buffer outbufs[MAX_BUFS];
102 adsp_listener_buffer inbufs[MAX_BUFS];
103 int inbufLenReqs[MAX_BUFS];
104 int outbufLenReqs[MAX_BUFS];
105 remote_arg args[2*MAX_BUFS];
106 };
107
108 extern void set_thread_context(int domain);
109
__QAIC_IMPL(apps_remotectl_open)110 __QAIC_IMPL_EXPORT int __QAIC_IMPL(apps_remotectl_open)(const char* name, uint32* handle, char* dlStr, int dlerrorLen, int* dlErr) __QAIC_IMPL_ATTRIBUTE
111 {
112 return mod_table_open(name, handle, dlStr, dlerrorLen, dlErr);
113 }
114
__QAIC_IMPL(apps_remotectl_close)115 __QAIC_IMPL_EXPORT int __QAIC_IMPL(apps_remotectl_close)(uint32 handle, char* errStr, int errStrLen, int* dlErr) __QAIC_IMPL_ATTRIBUTE
116 {
117 return mod_table_close(handle, errStr, errStrLen, dlErr);
118 }
119
120 #define RPC_FREEIF(heapid, buf) \
121 do {\
122 if(heapid == -1) {\
123 FREEIF(buf);\
124 } else {\
125 if(buf) {\
126 rpcmem_free_internal(buf);\
127 buf = 0;\
128 }\
129 }\
130 } while (0)
131
rpcmem_realloc(int heapid,uint32 flags,void * buf,int oldsize,int size)132 static __inline void* rpcmem_realloc(int heapid, uint32 flags, void* buf, int oldsize, int size) {
133 if(heapid == -1) {
134 return REALLOC(buf, size);
135 } else {
136 void* bufnew = rpcmem_alloc_internal(heapid, flags, size);
137 if(buf && bufnew) {
138 memmove(bufnew, buf, oldsize);
139 rpcmem_free_internal(buf);
140 buf = NULL;
141 }
142 return bufnew;
143 }
144 }
145
listener(void * arg)146 static void* listener(void* arg) {
147 struct listener* me = (struct listener*)arg;
148 int numOutBufs = 0;
149 int nErr = AEE_SUCCESS;
150 adsp_listener_invoke_ctx ctx = 0;
151 struct invoke_bufs* bufs = 0;
152 boolean bNeedMore;
153 int result = -1;
154 adsp_listener_remote_handle handle;
155 uint32 sc;
156 int ii, inBufsAllocated = 0;
157 const char* eheap = getenv("ADSP_LISTENER_HEAP_ID");
158 int heapid = eheap == 0 ? 0 : (uint32)atoi(eheap);
159 const char* eflags = getenv("ADSP_LISTENER_HEAP_FLAGS");
160 uint32 flags = eflags == 0 ? RPCMEM_HEAP_DEFAULT : (uint32)atoi(eflags);
161
162 if(eheap || eflags) {
163 FARF(HIGH, "listener using ion heap: %d flags: %x\n", (int)heapid, (int)flags);
164 }
165
166 VERIFYC(NULL != (bufs = rpcmem_realloc(heapid, flags, 0, 0, sizeof(*bufs))), AEE_ENORPCMEMORY);
167 memset(bufs, 0, sizeof(*bufs));
168 set_thread_context((int)(me - &linfo[0]));
169
170 do {
171 invoke:
172 bNeedMore = FALSE;
173 sc = 0xffffffff;
174 if(result != AEE_SUCCESS) {
175 numOutBufs = 0;
176 }
177 nErr = __QAIC_HEADER(adsp_listener_next_invoke)(
178 ctx, result, bufs->outbufs, numOutBufs, &ctx,
179 &handle, &sc, bufs->inbufs, inBufsAllocated,
180 bufs->inbufLenReqs, MAX_BUFS, bufs->outbufLenReqs, MAX_BUFS);
181 if(nErr) {
182 VERIFY_EPRINTF("listener protocol failure %x\n", nErr);
183 VERIFY(AEE_SUCCESS == (nErr = __QAIC_HEADER(adsp_listener_next_invoke)(
184 ctx, nErr, 0, 0, &ctx,
185 &handle, &sc, bufs->inbufs, inBufsAllocated,
186 bufs->inbufLenReqs, MAX_BUFS, bufs->outbufLenReqs, MAX_BUFS)));
187 }
188
189 if(MAX_BUFS < REMOTE_SCALARS_INBUFS(sc) || MAX_BUFS < REMOTE_SCALARS_OUTBUFS(sc)) {
190 result = AEE_EMAXBUFS;
191 goto invoke;
192 }
193 for(ii = 0; ii < (int)REMOTE_SCALARS_INBUFS(sc); ++ii) {
194 if(bufs->inbufs[ii].dataLen < bufs->inbufLenReqs[ii]) {
195 if(0 != bufs->inbufLenReqs[ii]) {
196 bufs->inbufs[ii].data = rpcmem_realloc(heapid, flags, bufs->inbufs[ii].data, bufs->inbufs[ii].dataLen, bufs->inbufLenReqs[ii]);
197 if(0 == bufs->inbufs[ii].data) {
198 bufs->inbufs[ii].dataLen = 0;
199 result = AEE_ENORPCMEMORY;
200 goto invoke;
201 }
202 }
203 bufs->inbufs[ii].dataLen = bufs->inbufLenReqs[ii];
204 inBufsAllocated = STD_MAX(inBufsAllocated, ii + 1);
205 bNeedMore = TRUE;
206 }
207 bufs->args[ii].buf.pv = bufs->inbufs[ii].data;
208 bufs->args[ii].buf.nLen = bufs->inbufLenReqs[ii];
209 }
210 for(ii = 0; ii < (int)REMOTE_SCALARS_OUTBUFS(sc); ++ii) {
211 if(bufs->outbufs[ii].dataLen < bufs->outbufLenReqs[ii]) {
212 if(0 != bufs->outbufLenReqs[ii]) {
213 bufs->outbufs[ii].data = rpcmem_realloc(heapid, flags, bufs->outbufs[ii].data, bufs->outbufs[ii].dataLen, bufs->outbufLenReqs[ii]);
214 if(0 == bufs->outbufs[ii].data) {
215 result = AEE_ENORPCMEMORY;
216 goto invoke;
217 }
218 }
219 bufs->outbufs[ii].dataLen = bufs->outbufLenReqs[ii];
220 }
221 bufs->args[ii + REMOTE_SCALARS_INBUFS(sc)].buf.pv = bufs->outbufs[ii].data;
222 bufs->args[ii + REMOTE_SCALARS_INBUFS(sc)].buf.nLen = bufs->outbufLenReqs[ii];
223 }
224 numOutBufs = REMOTE_SCALARS_OUTBUFS(sc);
225 if(bNeedMore) {
226 assert(inBufsAllocated >= REMOTE_SCALARS_INBUFS(sc));
227 if(0 != (result = __QAIC_HEADER(adsp_listener_invoke_get_in_bufs)(ctx, bufs->inbufs,
228 REMOTE_SCALARS_INBUFS(sc)))) {
229 FARF(HIGH, "adsp_listener_invoke_get_in_bufs failed %x\n", result);
230 goto invoke;
231 }
232 }
233
234 result = mod_table_invoke(handle, sc, bufs->args);
235 } while(1);
236 bail:
237 for(ii = 0; ii < MAX_BUFS && bufs; ++ii) {
238 RPC_FREEIF(heapid, bufs->outbufs[ii].data);
239 RPC_FREEIF(heapid, bufs->inbufs[ii].data);
240 }
241 RPC_FREEIF(heapid, bufs);
242 if(nErr != AEE_SUCCESS) {
243 VERIFY_EPRINTF("Error %x: listener thread exiting\n", nErr);
244 }
245 return (void*)(uintptr_t)nErr;
246 }
247
listener_start_thread(struct listener * me)248 static int listener_start_thread(struct listener* me) {
249 return pthread_create(&me->thread, 0, listener, (void*)me);
250 }
251 #define MIN_BUF_SIZE 0x1000
252 #define ALIGNB(sz) ((sz) == 0 ? MIN_BUF_SIZE : _SBUF_ALIGN((sz), MIN_BUF_SIZE))
253
listener2(void * arg)254 static void* listener2(void* arg) {
255 struct listener* me = (struct listener*)arg;
256 int nErr = AEE_SUCCESS;
257 adsp_listener_invoke_ctx ctx = 0;
258 uint8* outBufs = 0;
259 int outBufsLen = 0, outBufsCapacity = 0;
260 uint8* inBufs = 0;
261 int inBufsLen = 0, inBufsLenReq = 0;
262 int result = -1;
263 adsp_listener_remote_handle handle = -1;
264 uint32 sc = 0;
265 const char* eheap = getenv("ADSP_LISTENER_HEAP_ID");
266 int heapid = eheap == 0 ? -1 : atoi(eheap);
267 const char* eflags = getenv("ADSP_LISTENER_HEAP_FLAGS");
268 uint32 flags = eflags == 0 ? 0 : (uint32)atoi(eflags);
269 const char* emin = getenv("ADSP_LISTENER_MEM_CACHE_SIZE");
270 int cache_size = emin == 0 ? 0 : atoi(emin);
271 remote_arg args[512];
272 struct sbuf buf;
273 eventfd_t event = 0xff;
274
275 memset(args, 0, sizeof(args));
276 set_thread_context((int)(me - &linfo[0]));
277 if(eheap || eflags || emin) {
278 FARF(HIGH, "listener using ion heap: %d flags: %x cache: %lld\n", (int)heapid, (int)flags, cache_size);
279 }
280
281 do {
282 invoke:
283 sc = 0xffffffff;
284 if(result != 0) {
285 outBufsLen = 0;
286 }
287 FARF(HIGH, "responding message for %x %x %x %x", ctx, handle, sc, result);
288 nErr = __QAIC_HEADER(adsp_listener_next2)(
289 ctx, result, outBufs, outBufsLen,
290 &ctx, &handle, &sc, inBufs, inBufsLen, &inBufsLenReq);
291 FARF(HIGH, "got message for %x %x %x %x", ctx, handle, sc, nErr);
292 if(nErr) {
293 VERIFY_EPRINTF("listener protocol failure %x\n", nErr);
294 if (nErr == AEE_EINTERRUPTED) {
295 goto invoke;
296 }
297 VERIFY(0 == (nErr = __QAIC_HEADER(adsp_listener_next2)(
298 ctx, nErr, 0, 0,
299 &ctx, &handle, &sc, inBufs, inBufsLen,
300 &inBufsLenReq)));
301 }
302 if(ALIGNB(inBufsLenReq * 2) < inBufsLen && inBufsLen > cache_size) {
303 void* buf;
304 int size = ALIGNB(inBufsLenReq * 2);
305 if(NULL == (buf = rpcmem_realloc(heapid, flags, inBufs, inBufsLen, size))) {
306 result = AEE_ENORPCMEMORY;
307 FARF(HIGH, "rpcmem_realloc shrink failed");
308 goto invoke;
309 }
310 inBufs = buf;
311 inBufsLen = size;
312 }
313 if(inBufsLenReq > inBufsLen) {
314 void* buf;
315 int req;
316 int oldLen = inBufsLen;
317 int size = _SBUF_ALIGN(inBufsLenReq, MIN_BUF_SIZE);
318 if(AEE_SUCCESS == (buf = rpcmem_realloc(heapid, flags, inBufs, inBufsLen, size))) {
319 result = AEE_ENORPCMEMORY;
320 FARF(ERROR, "rpcmem_realloc failed");
321 goto invoke;
322 }
323 inBufs = buf;
324 inBufsLen = size;
325 if(0 != (result = __QAIC_HEADER(adsp_listener_get_in_bufs2)(ctx, oldLen,
326 inBufs + oldLen,
327 inBufsLen - oldLen, &req))) {
328 FARF(HIGH, "adsp_listener_invoke_get_in_bufs2 failed %x", result);
329 goto invoke;
330 }
331 if(req > inBufsLen) {
332 result = AEE_EBADSIZE;
333 FARF(HIGH, "adsp_listener_invoke_get_in_bufs2 failed %x", result);
334 goto invoke;
335 }
336 }
337 if(REMOTE_SCALARS_INHANDLES(sc) + REMOTE_SCALARS_OUTHANDLES(sc) > 0) {
338 result = AEE_EINVARGS;
339 goto invoke;
340 }
341
342 sbuf_init(&buf, 0, inBufs, inBufsLen);
343 unpack_in_bufs(&buf, args, REMOTE_SCALARS_INBUFS(sc));
344 unpack_out_lens(&buf, args + REMOTE_SCALARS_INBUFS(sc), REMOTE_SCALARS_OUTBUFS(sc));
345
346 sbuf_init(&buf, 0, 0, 0);
347 pack_out_bufs(&buf, args + REMOTE_SCALARS_INBUFS(sc), REMOTE_SCALARS_OUTBUFS(sc));
348 outBufsLen = sbuf_needed(&buf);
349
350 if(ALIGNB(outBufsLen*2) < outBufsCapacity && outBufsCapacity > cache_size) {
351 void* buf;
352 int size = ALIGNB(outBufsLen*2);
353 if(NULL == (buf = rpcmem_realloc(heapid, flags, outBufs, outBufsCapacity, size))) {
354 result = AEE_ENORPCMEMORY;
355 FARF(HIGH, "listener rpcmem_realloc shrink failed");
356 goto invoke;
357 }
358 outBufs = buf;
359 outBufsCapacity = size;
360 }
361 if(outBufsLen > outBufsCapacity) {
362 void* buf;
363 int size = ALIGNB(outBufsLen);
364 if(NULL == (buf = rpcmem_realloc(heapid, flags, outBufs, outBufsCapacity, size))) {
365 result = AEE_ENORPCMEMORY;
366 FARF(ERROR, "listener rpcmem_realloc failed");
367 goto invoke;
368 }
369 outBufs = buf;
370 outBufsLen = size;
371 outBufsCapacity = size;
372 }
373 sbuf_init(&buf, 0, outBufs, outBufsLen);
374 pack_out_bufs(&buf, args + REMOTE_SCALARS_INBUFS(sc), REMOTE_SCALARS_OUTBUFS(sc));
375
376 result = mod_table_invoke(handle, sc, args);
377 } while(1);
378 bail:
379 RPC_FREEIF(heapid, outBufs);
380 RPC_FREEIF(heapid, inBufs);
381 if(nErr != AEE_SUCCESS) {
382 VERIFY_EPRINTF("Error %x: listener thread exited", nErr);
383 }
384 eventfd_write(me->eventfd, event);
385 dlerror();
386 return (void*)(uintptr_t)nErr;
387 }
listener_start_thread2(struct listener * me)388 static int listener_start_thread2(struct listener* me) {
389 return pthread_create(&me->thread, 0, listener2, (void*)me);
390 }
391
392 extern int apps_remotectl_skel_invoke(uint32 _sc, remote_arg* _pra);
393 extern int apps_std_skel_invoke(uint32 _sc, remote_arg* _pra);
394 extern int apps_mem_skel_invoke(uint32 _sc, remote_arg* _pra);
395 extern int adspmsgd_apps_skel_invoke(uint32_t _sc, remote_arg* _pra);
396
397 #include "adsp_listener_stub.c"
398 PL_DEP(mod_table)
399 PL_DEP(apps_std);
400
listener_android_deinit(void)401 void listener_android_deinit(void) {
402 PL_DEINIT(mod_table);
403 PL_DEINIT(apps_std);
404 }
405
listener_android_init(void)406 int listener_android_init(void) {
407 int nErr = 0;
408
409 VERIFY(AEE_SUCCESS == (nErr = PL_INIT(mod_table)));
410 VERIFY(AEE_SUCCESS == (nErr = PL_INIT(apps_std)));
411 VERIFY(AEE_SUCCESS == (nErr = mod_table_register_const_handle(0, "apps_remotectl", apps_remotectl_skel_invoke)));
412 VERIFY(AEE_SUCCESS == (nErr = mod_table_register_static("apps_std", apps_std_skel_invoke)));
413 VERIFY(AEE_SUCCESS == (nErr = mod_table_register_static("apps_mem", apps_mem_skel_invoke)));
414 VERIFY(AEE_SUCCESS == (nErr = mod_table_register_static("adspmsgd_apps", adspmsgd_apps_skel_invoke)));
415 bail:
416 if(nErr != AEE_SUCCESS) {
417 listener_android_deinit();
418 VERIFY_EPRINTF("Error %x: fastrpc listener initialization error", nErr);
419 }
420 return nErr;
421 }
422
listener_android_domain_deinit(int domain)423 void listener_android_domain_deinit(int domain) {
424 struct listener* me = &linfo[domain];
425
426 FARF(HIGH, "fastrpc listener joining to exit");
427 if(me->thread) {
428 pthread_join(me->thread, 0);
429 me->thread = 0;
430 }
431 FARF(HIGH, "fastrpc listener joined");
432 if(me->eventfd != -1) {
433 close(me->eventfd);
434 me->eventfd = -1;
435 }
436 }
437
listener_android_domain_init(int domain)438 int listener_android_domain_init(int domain) {
439 struct listener* me = &linfo[domain];
440 int nErr = 0;
441
442 VERIFYC(-1 != (me->eventfd = eventfd(0, 0)), AEE_EINVALIDFD);
443 nErr = __QAIC_HEADER(adsp_listener_init2)();
444 if(AEE_EUNSUPPORTEDAPI == nErr) {
445 FARF(HIGH, "listener2 initialization error falling back to listener1 %x", nErr);
446 VERIFY(AEE_SUCCESS == (nErr = __QAIC_HEADER(adsp_listener_init)()));
447 VERIFY(AEE_SUCCESS == (nErr = listener_start_thread(me)));
448 } else if(AEE_SUCCESS == nErr) {
449 FARF(HIGH, "listener2 initialized for domain %d", domain);
450 VERIFY(AEE_SUCCESS == (nErr = listener_start_thread2(me)));
451 }
452
453 bail:
454 if(nErr != AEE_SUCCESS) {
455 VERIFY_EPRINTF("Error %x: listener android domain init failed. domain %d\n", nErr, domain);
456 listener_android_domain_deinit(domain);
457 }
458 return nErr;
459 }
460
listener_android_geteventfd(int domain,int * fd)461 int listener_android_geteventfd(int domain, int *fd) {
462 struct listener* me = &linfo[domain];
463 int nErr = 0;
464
465 VERIFYC(-1 != me->eventfd, AEE_EINVALIDFD);
466 *fd = me->eventfd;
467 bail:
468 if (nErr != AEE_SUCCESS) {
469 VERIFY_EPRINTF("Error %x: listener android getevent file descriptor failed for domain %d\n", nErr, domain);
470 }
471 return nErr;
472 }
473
474 PL_DEFINE(listener_android, listener_android_init, listener_android_deinit)
475