| /* | |
| * Copyright (c) 2019, The Linux Foundation. All rights reserved. | |
| * | |
| * Redistribution and use in source and binary forms, with or without | |
| * modification, are permitted provided that the following conditions are | |
| * met: | |
| * * Redistributions of source code must retain the above copyright | |
| * notice, this list of conditions and the following disclaimer. | |
| * * Redistributions in binary form must reproduce the above | |
| * copyright notice, this list of conditions and the following | |
| * disclaimer in the documentation and/or other materials provided | |
| * with the distribution. | |
| * * Neither the name of The Linux Foundation nor the names of its | |
| * contributors may be used to endorse or promote products derived | |
| * from this software without specific prior written permission. | |
| * | |
| * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED | |
| * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF | |
| * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT | |
| * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS | |
| * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | |
| * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | |
| * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR | |
| * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, | |
| * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE | |
| * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN | |
| * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |
| */ | |
| #ifndef VERIFY_PRINT_ERROR | |
| #define VERIFY_PRINT_ERROR | |
| #endif /* VERIFY_PRINT_ERROR */ | |
| #include <stdio.h> | |
| #include <stdlib.h> | |
| #include <string.h> | |
| #include <pthread.h> | |
| #include <sys/mman.h> | |
| #include "apps_mem.h" | |
| #include "remote64.h" | |
| #include "rpcmem.h" | |
| #include "verify.h" | |
| #include "rpcmem.h" | |
| #include "AEEQList.h" | |
| #include "AEEstd.h" | |
| #include "AEEStdErr.h" | |
| #include "fastrpc_apps_user.h" | |
| #include "platform_libs.h" | |
| #define ADSP_MMAP_HEAP_ADDR 4 | |
| #define ADSP_MMAP_REMOTE_HEAP_ADDR 8 | |
| #define ADSP_MMAP_ADD_PAGES 0x1000 | |
| static QList memlst; | |
| static pthread_mutex_t memmt; | |
| struct mem_info { | |
| QNode qn; | |
| uint64 vapps; | |
| uint64 vadsp; | |
| int32 size; | |
| int32 mapped; | |
| }; | |
| /* | |
| These should be called in some static constructor of the .so that | |
| uses rpcmem. | |
| I moved them into fastrpc_apps_user.c because there is no gurantee in | |
| the order of when constructors are called. | |
| */ | |
| static int apps_mem_init(void) { | |
| QList_Ctor(&memlst); | |
| pthread_mutex_init(&memmt, 0); | |
| return AEE_SUCCESS; | |
| } | |
| void apps_mem_deinit(void) { | |
| QNode *pn; | |
| while ((pn = QList_PopZ(&memlst)) != NULL) { | |
| struct mem_info *mfree = STD_RECOVER_REC(struct mem_info, qn, pn); | |
| if (mfree->vapps) { | |
| if(mfree->mapped) { | |
| munmap((void*)(uintptr_t)mfree->vapps, mfree->size); | |
| } else { | |
| rpcmem_free_internal((void *)(uintptr_t)mfree->vapps); | |
| } | |
| } | |
| free(mfree); | |
| mfree = NULL; | |
| } | |
| pthread_mutex_destroy(&memmt); | |
| } | |
| PL_DEFINE(apps_mem, apps_mem_init, apps_mem_deinit); | |
| __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 { | |
| struct mem_info *minfo = 0; | |
| int nErr = 0; | |
| void* buf = 0; | |
| uint64_t pbuf; | |
| int fd = -1; | |
| (void)vin; | |
| VERIFYC(NULL != (minfo = malloc(sizeof(*minfo))), AEE_ENOMEMORY); | |
| QNode_CtorZ(&minfo->qn); | |
| *vadsp = 0; | |
| if (rflags == ADSP_MMAP_HEAP_ADDR || rflags == ADSP_MMAP_REMOTE_HEAP_ADDR) { | |
| VERIFY(AEE_SUCCESS == (nErr = remote_mmap64(-1, rflags, 0, len, (uint64_t*)vadsp))); | |
| *vapps = 0; | |
| minfo->vapps = 0; | |
| } else { | |
| if ((rflags != ADSP_MMAP_ADD_PAGES) || | |
| ((rflags == ADSP_MMAP_ADD_PAGES) && !is_kernel_alloc_supported(-1, -1))) { | |
| VERIFYC(NULL != (buf = rpcmem_alloc_internal(heapid, lflags, len)), AEE_ENORPCMEMORY); | |
| fd = rpcmem_to_fd_internal(buf); | |
| VERIFYC(fd > 0, AEE_EINVALIDFD); | |
| } | |
| VERIFY(AEE_SUCCESS == (nErr = remote_mmap64(fd, rflags, (uint64_t)buf, len, (uint64_t*)vadsp))); | |
| pbuf = (uint64_t)buf; | |
| *vapps = pbuf; | |
| minfo->vapps = *vapps; | |
| } | |
| minfo->vadsp = *vadsp; | |
| minfo->size = len; | |
| minfo->mapped = 0; | |
| pthread_mutex_lock(&memmt); | |
| QList_AppendNode(&memlst, &minfo->qn); | |
| pthread_mutex_unlock(&memmt); | |
| bail: | |
| if(nErr) { | |
| if(buf) { | |
| rpcmem_free_internal(buf); | |
| buf = NULL; | |
| } | |
| if(minfo) { | |
| free(minfo); | |
| minfo = NULL; | |
| } | |
| VERIFY_EPRINTF("Error %x: apps_mem_request_mmap64 failed\n", nErr); | |
| } | |
| return nErr; | |
| } | |
| __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 { | |
| uint64 vin1, vapps1, vadsp1; | |
| int64 len1; | |
| int nErr = AEE_SUCCESS; | |
| vin1 = (uint64)vin; | |
| len1 = (int64)len; | |
| nErr = apps_mem_request_map64(heapid, lflags, rflags, vin1, len1, &vapps1, &vadsp1); | |
| *vapps = (uint32)vapps1; | |
| *vadsp = (uint32)vadsp1; | |
| if(nErr != AEE_SUCCESS) { | |
| VERIFY_EPRINTF("Error %x: apps_mem_request_map failed\n", nErr); | |
| } | |
| return nErr; | |
| } | |
| __QAIC_IMPL_EXPORT int __QAIC_IMPL(apps_mem_request_unmap64)(uint64 vadsp, int64 len) __QAIC_IMPL_ATTRIBUTE { | |
| int nErr = AEE_SUCCESS; | |
| struct mem_info *minfo, *mfree = 0; | |
| QNode *pn, *pnn; | |
| VERIFY(0 == (nErr = remote_munmap64((uint64_t)vadsp, len))); | |
| pthread_mutex_lock(&memmt); | |
| QLIST_NEXTSAFE_FOR_ALL(&memlst, pn, pnn) { | |
| minfo = STD_RECOVER_REC(struct mem_info, qn, pn); | |
| if(minfo->vadsp == vadsp) { | |
| mfree = minfo; | |
| QNode_Dequeue(&minfo->qn); | |
| break; | |
| } | |
| } | |
| pthread_mutex_unlock(&memmt); | |
| VERIFYC(mfree, AEE_ENOSUCHMAP); | |
| if(mfree->mapped) { | |
| munmap((void*)(uintptr_t)mfree->vapps, mfree->size); | |
| } else { | |
| if (mfree->vapps) | |
| rpcmem_free_internal((void *)(uintptr_t)mfree->vapps); | |
| } | |
| free(mfree); | |
| mfree = NULL; | |
| bail: | |
| if(nErr != AEE_SUCCESS) { | |
| VERIFY_EPRINTF("Error %x: apps_mem_request_unmap64 failed\n", nErr); | |
| } | |
| return nErr; | |
| } | |
| __QAIC_IMPL_EXPORT int __QAIC_IMPL(apps_mem_request_unmap)(uint32 vadsp, int32 len) __QAIC_IMPL_ATTRIBUTE { | |
| uint64 vadsp1 = (uint64)vadsp; | |
| int64 len1 = (int64)len; | |
| int nErr = apps_mem_request_unmap64(vadsp1, len1); | |
| if(nErr != AEE_SUCCESS) { | |
| VERIFY_EPRINTF("Error %x: apps_mem_request_unmap failed\n", nErr); | |
| } | |
| return nErr; | |
| } | |
| __QAIC_IMPL_EXPORT int __QAIC_IMPL(apps_mem_share_map)(int fd, int size, uint64* vapps, uint64* vadsp) __QAIC_IMPL_ATTRIBUTE { | |
| struct mem_info *minfo = 0; | |
| int nErr = AEE_SUCCESS; | |
| void* buf = 0; | |
| uint64_t pbuf; | |
| VERIFYC(0 != (minfo = malloc(sizeof(*minfo))), AEE_ENOMEMORY); | |
| QNode_CtorZ(&minfo->qn); | |
| VERIFYC(fd > 0, AEE_EINVALIDFD); | |
| *vadsp = 0; | |
| VERIFYC(MAP_FAILED != (buf = (void *)mmap(NULL, size, | |
| PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0)), AEE_EMMAP); | |
| VERIFY(AEE_SUCCESS == (nErr = remote_mmap64(fd, 0, (uint64_t)buf, size, (uint64_t*)vadsp))); | |
| pbuf = (uint64_t)buf; | |
| *vapps = pbuf; | |
| minfo->vapps = *vapps; | |
| minfo->vadsp = *vadsp; | |
| minfo->size = size; | |
| minfo->mapped = 1; | |
| pthread_mutex_lock(&memmt); | |
| QList_AppendNode(&memlst, &minfo->qn); | |
| pthread_mutex_unlock(&memmt); | |
| bail: | |
| if(nErr) { | |
| if(buf) { | |
| munmap(buf, size); | |
| } | |
| if(minfo) { | |
| free(minfo); | |
| minfo = NULL; | |
| } | |
| VERIFY_EPRINTF("Error %x: apps_mem_share_map failed\n", nErr); | |
| } | |
| return nErr; | |
| } | |
| __QAIC_IMPL_EXPORT int __QAIC_IMPL(apps_mem_share_unmap)(uint64 vadsp, int size) __QAIC_IMPL_ATTRIBUTE { | |
| int64 len1 = (int64)size; | |
| int nErr = AEE_SUCCESS; | |
| nErr = apps_mem_request_unmap64(vadsp, len1); | |
| if(nErr != AEE_SUCCESS) { | |
| VERIFY_EPRINTF("Error %x: apps_mem_share_unmap failed\n", nErr); | |
| } | |
| return nErr; | |
| } |