diff options
Diffstat (limited to 'src/apps_mem_imp.c')
-rw-r--r-- | src/apps_mem_imp.c | 244 |
1 files changed, 244 insertions, 0 deletions
diff --git a/src/apps_mem_imp.c b/src/apps_mem_imp.c new file mode 100644 index 0000000..d6f2ccb --- /dev/null +++ b/src/apps_mem_imp.c @@ -0,0 +1,244 @@ +/* + * 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; +} |