• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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