/** * 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 FASTRPC_INTERNAL_H #define FASTRPC_INTERNAL_H #include #include "remote64.h" #include "verify.h" #include "AEEstd.h" #define FASTRPC_IOCTL_ALLOC_DMA_BUFF _IOWR('R', 1, struct fastrpc_alloc_dma_buf) #define FASTRPC_IOCTL_FREE_DMA_BUFF _IOWR('R', 2, uint32_t) #define FASTRPC_IOCTL_INVOKE _IOWR('R', 3, struct fastrpc_invoke) #define FASTRPC_IOCTL_INIT_ATTACH _IO('R', 4) #define FASTRPC_IOCTL_INIT_CREATE _IOWR('R', 5, struct fastrpc_init_create) #define FASTRPC_IOCTL_MMAP _IOWR('R', 6, struct fastrpc_ioctl_mmap) #define FASTRPC_IOCTL_MUNMAP _IOWR('R', 7, struct fastrpc_ioctl_munmap) #define DEVICE_NAME "adsprpc-smd" #if !(defined __qdsp6__) && !(defined __hexagon__) static __inline uint32 Q6_R_cl0_R(uint32 num) { int ii; for(ii = 31; ii >= 0; --ii) { if(num & (1 << ii)) { return 31 - ii; } } return 0; } #else #include "hexagon_protos.h" #include #endif #define FASTRPC_INFO_SMMU (1 << 0) /* struct fastrpc_invoke_args { __u64 ptr; __u64 length; __s32 fd; __u32 attrs; __u32 crc; }; */ struct fastrpc_invoke_args { __u64 ptr; __u64 length; __s32 fd; __u32 reserved; }; struct fastrpc_invoke { __u32 handle; __u32 sc; __u64 args; }; #define FASTRPC_ATTR_NOVA (1) #define FASTRPC_ATTR_NOMAP (16) #define GUEST_OS 0 #define USER_PD -1 #define STATIC_USER_PD 1 #define ATTACH_SENSORS_PD 2 #define GUEST_OS_SHARED 3 struct fastrpc_init_create { __u32 filelen; /* elf file length */ __s32 filefd; /* fd for the file */ __u32 attrs; __u32 siglen; __u64 file; /* pointer to elf file */ }; #define FASTRPC_ATTR_DEBUG_PROCESS (1) struct fastrpc_alloc_dma_buf { __s32 fd; /* fd */ __u32 flags; /* flags to map with */ __u64 size; /* size */ }; struct fastrpc_ioctl_mmap { __s32 fd; /* fd */ __u32 flags; /* flags for dsp to map with */ __u64 vaddrin; /* optional virtual address */ __u64 size; /* size */ __u64 vaddrout; /* dsps virtual address */ }; struct fastrpc_ioctl_munmap { __u64 vaddrout; /* address to unmap */ __u64 size; /* size */ }; #define FASTRPC_CONTROL_LATENCY (1) struct fastrpc_ctrl_latency { uint32_t enable; //!latency control enable uint32_t level; //!level of control }; #define FASTRPC_CONTROL_SMMU (2) struct fastrpc_ctrl_smmu { uint32_t sharedcb; }; #define FASTRPC_CONTROL_KALLOC (3) struct fastrpc_ctrl_kalloc { uint32_t kalloc_support; }; struct fastrpc_ioctl_control { uint32_t req; union { struct fastrpc_ctrl_latency lp; struct fastrpc_ctrl_smmu smmu; struct fastrpc_ctrl_kalloc kalloc; }; }; #define FASTRPC_SMD_GUID "fastrpcsmd-apps-dsp" struct smq_null_invoke32 { uint32_t ctx; //! invoke caller context remote_handle handle; //! handle to invoke uint32_t sc; //! scalars structure describing the rest of the data }; struct smq_null_invoke { uint64_t ctx; //! invoke caller context remote_handle handle; //! handle to invoke uint32_t sc; //! scalars structure describing the rest of the data }; typedef uint32_t smq_invoke_buf_phy_addr; struct smq_phy_page { uint64_t addr; //! physical address int64_t size; //! size }; struct smq_phy_page32 { uint32_t addr; //! physical address uint32_t size; //! size }; struct smq_invoke_buf { int num; int pgidx; }; struct smq_invoke32 { struct smq_null_invoke32 header; struct smq_phy_page32 page; //! remote arg and list of pages address }; struct smq_invoke { struct smq_null_invoke header; struct smq_phy_page page; //! remote arg and list of pages address }; struct smq_msg32 { uint32_t pid; uint32_t tid; struct smq_invoke32 invoke; }; struct smq_msg { uint32_t pid; uint32_t tid; struct smq_invoke invoke; }; struct smq_msg_u { union { struct smq_msg32 msg32; struct smq_msg msg64; } msg; int size; }; struct smq_invoke_rsp32 { uint32_t ctx; //! invoke caller context int nRetVal; //! invoke return value }; struct smq_invoke_rsp { uint64_t ctx; //! invoke caller context int nRetVal; //! invoke return value }; struct smq_invoke_rsp_u { union { struct smq_invoke_rsp32 rsp32; struct smq_invoke_rsp rsp64; } rsp; int size; }; static __inline void to_smq_msg(uint32 mode, struct smq_msg_u* msg, struct smq_msg* msg64) { if(0 == mode) { msg64->pid = msg->msg.msg32.pid; msg64->tid = msg->msg.msg32.tid; msg64->invoke.header.ctx = msg->msg.msg32.invoke.header.ctx; msg64->invoke.header.handle = msg->msg.msg32.invoke.header.handle; msg64->invoke.header.sc = msg->msg.msg32.invoke.header.sc; msg64->invoke.page.addr = msg->msg.msg32.invoke.page.addr; msg64->invoke.page.size = msg->msg.msg32.invoke.page.size; } else { std_memmove(msg64, &msg->msg.msg64, sizeof(*msg64)); } } static __inline void to_smq_invoke_rsp(uint32 mode, uint64 ctx, int nRetVal, struct smq_invoke_rsp_u* rsp) { if (0 == mode) { rsp->rsp.rsp32.ctx = (uint32)ctx; rsp->rsp.rsp32.nRetVal = nRetVal; rsp->size = sizeof(rsp->rsp.rsp32); } else { rsp->rsp.rsp64.ctx = ctx; rsp->rsp.rsp64.nRetVal = nRetVal; rsp->size = sizeof(rsp->rsp.rsp64); } } static __inline struct smq_invoke_buf* to_smq_invoke_buf_start(uint32 mode, void* virt, uint32 sc) { struct smq_invoke_buf* buf; int len = REMOTE_SCALARS_LENGTH(sc); if(0 == mode) { remote_arg* pra = (remote_arg*)virt; buf = (struct smq_invoke_buf*)(&pra[len]); } else { remote_arg64* pra = (remote_arg64*)virt; buf = (struct smq_invoke_buf*)(&pra[len]); } return buf; } static __inline struct smq_invoke_buf* smq_invoke_buf_start(remote_arg64 *pra, uint32 sc) { int len = REMOTE_SCALARS_LENGTH(sc); return (struct smq_invoke_buf*)(&pra[len]); } static __inline struct smq_phy_page* smq_phy_page_start(uint32 sc, struct smq_invoke_buf* buf) { int nTotal = REMOTE_SCALARS_INBUFS(sc) + REMOTE_SCALARS_OUTBUFS(sc); return (struct smq_phy_page*)(&buf[nTotal]); } //! size of the out of band data static __inline int smq_data_size(uint32 sc, int nPages) { struct smq_invoke_buf* buf = smq_invoke_buf_start(0, sc); struct smq_phy_page* page = smq_phy_page_start(sc, buf); return (int)(uintptr_t)(&(page[nPages])); } static __inline void to_smq_data(uint32 mode, uint32 sc, int nPages, void* pv, remote_arg64* rpra) { if(0 == mode) { struct smq_phy_page* page; struct smq_phy_page32* page32; remote_arg *pra = (remote_arg*)pv; int ii, len; len = REMOTE_SCALARS_LENGTH(sc); for(ii = 0; ii < len; ++ii) { rpra[ii].buf.pv = (uint64)(uintptr_t)pra[ii].buf.pv; rpra[ii].buf.nLen = pra[ii].buf.nLen; } len = REMOTE_SCALARS_INBUFS(sc) + REMOTE_SCALARS_OUTBUFS(sc); std_memmove(&rpra[ii], &pra[ii], len * sizeof(struct smq_invoke_buf)); page = (struct smq_phy_page*)((struct smq_invoke_buf*)&rpra[ii] + len); page32 = (struct smq_phy_page32*)((struct smq_invoke_buf*)&pra[ii] + len); for(ii = 0; ii < nPages; ++ii) { page[ii].addr = page32[ii].addr; page[ii].size = page32[ii].size; } } else { std_memmove(rpra, pv, smq_data_size(sc, nPages)); } } #endif // FASTRPC_INTERNAL_H