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 #ifndef VERIFY_PRINT_ERROR
30 #define VERIFY_PRINT_ERROR
31 #endif /* VERIFY_PRINT_ERROR */
32
33 #include <stdio.h>
34 #include <stdlib.h>
35 #include <string.h>
36 #include <pthread.h>
37 #include <sys/mman.h>
38 #include "apps_mem.h"
39 #include "remote64.h"
40 #include "rpcmem.h"
41 #include "verify.h"
42 #include "rpcmem.h"
43 #include "AEEQList.h"
44 #include "AEEstd.h"
45 #include "AEEStdErr.h"
46 #include "fastrpc_apps_user.h"
47 #include "platform_libs.h"
48
49 #define ADSP_MMAP_HEAP_ADDR 4
50 #define ADSP_MMAP_REMOTE_HEAP_ADDR 8
51 #define ADSP_MMAP_ADD_PAGES 0x1000
52
53 static QList memlst;
54 static pthread_mutex_t memmt;
55
56 struct mem_info {
57 QNode qn;
58 uint64 vapps;
59 uint64 vadsp;
60 int32 size;
61 int32 mapped;
62 };
63
64 /*
65 These should be called in some static constructor of the .so that
66 uses rpcmem.
67
68 I moved them into fastrpc_apps_user.c because there is no gurantee in
69 the order of when constructors are called.
70 */
71
apps_mem_init(void)72 static int apps_mem_init(void) {
73 QList_Ctor(&memlst);
74 pthread_mutex_init(&memmt, 0);
75 return AEE_SUCCESS;
76 }
77
apps_mem_deinit(void)78 void apps_mem_deinit(void) {
79 QNode *pn;
80 while ((pn = QList_PopZ(&memlst)) != NULL) {
81 struct mem_info *mfree = STD_RECOVER_REC(struct mem_info, qn, pn);
82
83 if (mfree->vapps) {
84 if(mfree->mapped) {
85 munmap((void*)(uintptr_t)mfree->vapps, mfree->size);
86 } else {
87 rpcmem_free_internal((void *)(uintptr_t)mfree->vapps);
88 }
89 }
90 free(mfree);
91 mfree = NULL;
92 }
93 pthread_mutex_destroy(&memmt);
94 }
95 PL_DEFINE(apps_mem, apps_mem_init, apps_mem_deinit);
96
__QAIC_IMPL(apps_mem_request_map64)97 __QAIC_IMPL_EXPORT int __QAIC_IMPL(apps_mem_request_map64)(int heapid, uint32 lflags, uint32 rflags, uint64 vin, int64 len, uint64* vapps, uint64* vadsp) __QAIC_IMPL_ATTRIBUTE {
98 struct mem_info *minfo = 0;
99 int nErr = 0;
100 void* buf = 0;
101 uint64_t pbuf;
102 int fd = -1;
103
104 (void)vin;
105 VERIFYC(NULL != (minfo = malloc(sizeof(*minfo))), AEE_ENOMEMORY);
106 QNode_CtorZ(&minfo->qn);
107 *vadsp = 0;
108 if (rflags == ADSP_MMAP_HEAP_ADDR || rflags == ADSP_MMAP_REMOTE_HEAP_ADDR) {
109 VERIFY(AEE_SUCCESS == (nErr = remote_mmap64(-1, rflags, 0, len, (uint64_t*)vadsp)));
110 *vapps = 0;
111 minfo->vapps = 0;
112 } else {
113 if ((rflags != ADSP_MMAP_ADD_PAGES) ||
114 ((rflags == ADSP_MMAP_ADD_PAGES) && !is_kernel_alloc_supported(-1, -1))) {
115 VERIFYC(NULL != (buf = rpcmem_alloc_internal(heapid, lflags, len)), AEE_ENORPCMEMORY);
116 fd = rpcmem_to_fd_internal(buf);
117 VERIFYC(fd > 0, AEE_EINVALIDFD);
118 }
119 VERIFY(AEE_SUCCESS == (nErr = remote_mmap64(fd, rflags, (uint64_t)buf, len, (uint64_t*)vadsp)));
120 pbuf = (uint64_t)buf;
121 *vapps = pbuf;
122 minfo->vapps = *vapps;
123 }
124 minfo->vadsp = *vadsp;
125 minfo->size = len;
126 minfo->mapped = 0;
127 pthread_mutex_lock(&memmt);
128 QList_AppendNode(&memlst, &minfo->qn);
129 pthread_mutex_unlock(&memmt);
130 bail:
131 if(nErr) {
132 if(buf) {
133 rpcmem_free_internal(buf);
134 buf = NULL;
135 }
136 if(minfo) {
137 free(minfo);
138 minfo = NULL;
139 }
140 VERIFY_EPRINTF("Error %x: apps_mem_request_mmap64 failed\n", nErr);
141 }
142 return nErr;
143 }
144
__QAIC_IMPL(apps_mem_request_map)145 __QAIC_IMPL_EXPORT int __QAIC_IMPL(apps_mem_request_map)(int heapid, uint32 lflags, uint32 rflags, uint32 vin, int32 len, uint32* vapps, uint32* vadsp) __QAIC_IMPL_ATTRIBUTE {
146 uint64 vin1, vapps1, vadsp1;
147 int64 len1;
148 int nErr = AEE_SUCCESS;
149 vin1 = (uint64)vin;
150 len1 = (int64)len;
151 nErr = apps_mem_request_map64(heapid, lflags, rflags, vin1, len1, &vapps1, &vadsp1);
152 *vapps = (uint32)vapps1;
153 *vadsp = (uint32)vadsp1;
154 if(nErr != AEE_SUCCESS) {
155 VERIFY_EPRINTF("Error %x: apps_mem_request_map failed\n", nErr);
156 }
157 return nErr;
158 }
159
__QAIC_IMPL(apps_mem_request_unmap64)160 __QAIC_IMPL_EXPORT int __QAIC_IMPL(apps_mem_request_unmap64)(uint64 vadsp, int64 len) __QAIC_IMPL_ATTRIBUTE {
161 int nErr = AEE_SUCCESS;
162 struct mem_info *minfo, *mfree = 0;
163 QNode *pn, *pnn;
164 VERIFY(0 == (nErr = remote_munmap64((uint64_t)vadsp, len)));
165 pthread_mutex_lock(&memmt);
166 QLIST_NEXTSAFE_FOR_ALL(&memlst, pn, pnn) {
167 minfo = STD_RECOVER_REC(struct mem_info, qn, pn);
168 if(minfo->vadsp == vadsp) {
169 mfree = minfo;
170 QNode_Dequeue(&minfo->qn);
171 break;
172 }
173 }
174 pthread_mutex_unlock(&memmt);
175 VERIFYC(mfree, AEE_ENOSUCHMAP);
176 if(mfree->mapped) {
177 munmap((void*)(uintptr_t)mfree->vapps, mfree->size);
178 } else {
179 if (mfree->vapps)
180 rpcmem_free_internal((void *)(uintptr_t)mfree->vapps);
181 }
182 free(mfree);
183 mfree = NULL;
184 bail:
185 if(nErr != AEE_SUCCESS) {
186 VERIFY_EPRINTF("Error %x: apps_mem_request_unmap64 failed\n", nErr);
187 }
188 return nErr;
189 }
190
__QAIC_IMPL(apps_mem_request_unmap)191 __QAIC_IMPL_EXPORT int __QAIC_IMPL(apps_mem_request_unmap)(uint32 vadsp, int32 len) __QAIC_IMPL_ATTRIBUTE {
192 uint64 vadsp1 = (uint64)vadsp;
193 int64 len1 = (int64)len;
194 int nErr = apps_mem_request_unmap64(vadsp1, len1);
195 if(nErr != AEE_SUCCESS) {
196 VERIFY_EPRINTF("Error %x: apps_mem_request_unmap failed\n", nErr);
197 }
198 return nErr;
199 }
200
__QAIC_IMPL(apps_mem_share_map)201 __QAIC_IMPL_EXPORT int __QAIC_IMPL(apps_mem_share_map)(int fd, int size, uint64* vapps, uint64* vadsp) __QAIC_IMPL_ATTRIBUTE {
202 struct mem_info *minfo = 0;
203 int nErr = AEE_SUCCESS;
204 void* buf = 0;
205 uint64_t pbuf;
206 VERIFYC(0 != (minfo = malloc(sizeof(*minfo))), AEE_ENOMEMORY);
207 QNode_CtorZ(&minfo->qn);
208 VERIFYC(fd > 0, AEE_EINVALIDFD);
209 *vadsp = 0;
210 VERIFYC(MAP_FAILED != (buf = (void *)mmap(NULL, size,
211 PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0)), AEE_EMMAP);
212 VERIFY(AEE_SUCCESS == (nErr = remote_mmap64(fd, 0, (uint64_t)buf, size, (uint64_t*)vadsp)));
213 pbuf = (uint64_t)buf;
214 *vapps = pbuf;
215 minfo->vapps = *vapps;
216 minfo->vadsp = *vadsp;
217 minfo->size = size;
218 minfo->mapped = 1;
219 pthread_mutex_lock(&memmt);
220 QList_AppendNode(&memlst, &minfo->qn);
221 pthread_mutex_unlock(&memmt);
222 bail:
223 if(nErr) {
224 if(buf) {
225 munmap(buf, size);
226 }
227 if(minfo) {
228 free(minfo);
229 minfo = NULL;
230 }
231 VERIFY_EPRINTF("Error %x: apps_mem_share_map failed\n", nErr);
232 }
233 return nErr;
234 }
235
__QAIC_IMPL(apps_mem_share_unmap)236 __QAIC_IMPL_EXPORT int __QAIC_IMPL(apps_mem_share_unmap)(uint64 vadsp, int size) __QAIC_IMPL_ATTRIBUTE {
237 int64 len1 = (int64)size;
238 int nErr = AEE_SUCCESS;
239 nErr = apps_mem_request_unmap64(vadsp, len1);
240 if(nErr != AEE_SUCCESS) {
241 VERIFY_EPRINTF("Error %x: apps_mem_share_unmap failed\n", nErr);
242 }
243 return nErr;
244 }
245