1360 lines
34 KiB
C
1360 lines
34 KiB
C
// SPDX-License-Identifier: GPL-2.0
|
|
/*
|
|
* Copyright (C) 2020 MediaTek Inc.
|
|
*/
|
|
|
|
#include <linux/slab.h>
|
|
#include "cmdq_sec.h"
|
|
#include "cmdq_virtual.h"
|
|
#include "cmdq_device.h"
|
|
|
|
/* secure path header */
|
|
#include "cmdqsectl_api.h"
|
|
#if defined(CMDQ_SECURE_PATH_SUPPORT)
|
|
#include "tz_cross/ta_mem.h"
|
|
#endif
|
|
|
|
|
|
static atomic_t gDebugSecSwCopy = ATOMIC_INIT(0);
|
|
static atomic_t gDebugSecCmdId = ATOMIC_INIT(0);
|
|
|
|
#if defined(CMDQ_SECURE_PATH_SUPPORT)
|
|
static KREE_SESSION_HANDLE cmdq_session;
|
|
static KREE_SESSION_HANDLE cmdq_mem_session;
|
|
#endif
|
|
|
|
/* lock to protect atomic secure task execution */
|
|
static DEFINE_MUTEX(gCmdqSecExecLock);
|
|
/* lock to protext atomic access gCmdqSecContextList */
|
|
static DEFINE_MUTEX(gCmdqSecContextLock);
|
|
#if defined(CMDQ_SECURE_PATH_SUPPORT)
|
|
/* secure context list. note each porcess has its own sec context */
|
|
static struct list_head gCmdqSecContextList;
|
|
/* secure context to cmdqSecTL */
|
|
static struct cmdqSecContextStruct *gCmdqSecContextHandle;
|
|
static KREE_SHAREDMEM_HANDLE gCmdq_share_cookie_handle;
|
|
static uint32_t gSubmitTaskCount;
|
|
#endif
|
|
static uint32_t gSecPrintCount;
|
|
|
|
/*
|
|
** for CMDQ_LOG_LEVEL
|
|
** set log level to 0 to enable all logs
|
|
** set log level to 3 to close all logs
|
|
*/
|
|
enum LOG_LEVEL {
|
|
LOG_LEVEL_MSG = 0,
|
|
LOG_LEVEL_LOG = 1,
|
|
LOG_LEVEL_ERR = 2,
|
|
LOG_LEVEL_MAX,
|
|
};
|
|
|
|
/* Set 1 to open once for each process context, because of below reasons:
|
|
* 1. kmalloc size > 4KB, need pre-allocation to avoid memory
|
|
* fragmentation and causes kmalloc fail.
|
|
* 2. we entry secure world for config and trigger GCE, and wait in normal world
|
|
*/
|
|
#define CMDQ_OPEN_SESSION_ONCE (1)
|
|
|
|
/* function declaretion */
|
|
|
|
|
|
/* #if defined(CMDQ_SECURE_PATH_SUPPORT) */
|
|
/***********add from k2 START ***********/
|
|
void cmdq_sec_lock_secure_path(void)
|
|
{
|
|
#if defined(CMDQ_SECURE_PATH_SUPPORT)
|
|
mutex_lock(&gCmdqSecExecLock);
|
|
smp_mb(); /*memory barrier */
|
|
#else
|
|
CMDQ_ERR("SVP feature is not on\n");
|
|
#endif
|
|
}
|
|
|
|
void cmdq_sec_unlock_secure_path(void)
|
|
{
|
|
#if defined(CMDQ_SECURE_PATH_SUPPORT)
|
|
mutex_unlock(&gCmdqSecExecLock);
|
|
#else
|
|
CMDQ_ERR("SVP feature is not on\n");
|
|
#endif
|
|
}
|
|
|
|
int32_t cmdq_sec_create_shared_memory(
|
|
struct cmdqSecSharedMemoryStruct **pHandle, const uint32_t size)
|
|
{
|
|
#if defined(CMDQ_SECURE_PATH_SUPPORT)
|
|
struct cmdqSecSharedMemoryStruct *handle = NULL;
|
|
|
|
handle = kzalloc(sizeof(uint8_t *) *
|
|
sizeof(struct cmdqSecSharedMemoryStruct), GFP_KERNEL);
|
|
if (handle == NULL)
|
|
return -ENOMEM;
|
|
|
|
|
|
CMDQ_LOG("%s\n", __func__);
|
|
|
|
handle->pVABase = kcalloc(size, sizeof(uint8_t), GFP_KERNEL);
|
|
handle->size = size;
|
|
*pHandle = handle;
|
|
#else
|
|
CMDQ_ERR("SVP feature is not on\n");
|
|
#endif
|
|
return 0;
|
|
}
|
|
|
|
int32_t cmdq_sec_destroy_shared_memory(
|
|
struct cmdqSecSharedMemoryStruct *handle)
|
|
{
|
|
#if defined(CMDQ_SECURE_PATH_SUPPORT)
|
|
if (handle && handle->pVABase)
|
|
kfree(handle->pVABase);
|
|
|
|
|
|
|
|
kfree(handle);
|
|
|
|
#else
|
|
CMDQ_ERR("SVP feature is not on\n");
|
|
#endif
|
|
return 0;
|
|
}
|
|
|
|
/***********add from k2 END ***********/
|
|
|
|
|
|
|
|
/* the API for other code to acquire cmdq_mem session handle */
|
|
/* a NULL handle is returned when it fails */
|
|
|
|
|
|
#if defined(CMDQ_SECURE_PATH_SUPPORT)
|
|
KREE_SESSION_HANDLE cmdq_session_handle(void)
|
|
{
|
|
CMDQ_MSG("%s() acquire TEE session\n", __func__);
|
|
if (cmdq_session == 0) {
|
|
TZ_RESULT ret;
|
|
|
|
CMDQ_MSG("%s() create session\n", __func__);
|
|
CMDQ_LOG("TZ_TA_CMDQ_UUID:%s\n", TZ_TA_CMDQ_UUID);
|
|
ret = KREE_CreateSession(TZ_TA_CMDQ_UUID, &cmdq_session);
|
|
if (ret != TZ_RESULT_SUCCESS) {
|
|
CMDQ_ERR("%s() failed to create session, ret=%d\n",
|
|
__func__, ret);
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
CMDQ_MSG("%s() session=%x\n", __func__, (unsigned int)cmdq_session);
|
|
return cmdq_session;
|
|
}
|
|
#endif
|
|
|
|
#if defined(CMDQ_SECURE_PATH_SUPPORT)
|
|
KREE_SESSION_HANDLE cmdq_mem_session_handle(void)
|
|
{
|
|
CMDQ_MSG("%s() acquires TEE memory session\n", __func__);
|
|
if (cmdq_mem_session == 0) {
|
|
TZ_RESULT ret;
|
|
|
|
CMDQ_MSG("%s() create memory session\n", __func__);
|
|
|
|
ret = KREE_CreateSession(TZ_TA_MEM_UUID, &cmdq_mem_session);
|
|
if (ret != TZ_RESULT_SUCCESS) {
|
|
CMDQ_ERR("%s() failed to create session: ret=%d\n",
|
|
__func__, ret);
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
CMDQ_MSG("%s() session=%x\n", __func__, (unsigned int)cmdq_mem_session);
|
|
return cmdq_mem_session;
|
|
}
|
|
#endif
|
|
|
|
#if defined(CMDQ_SECURE_PATH_SUPPORT)
|
|
static int32_t cmdq_sec_setup_context_session(
|
|
struct cmdqSecContextStruct *handle)
|
|
{
|
|
/* init handle:iwcMessage sessionHandle memSessionHandle */
|
|
|
|
#if CMDQ_OPEN_SESSION_ONCE
|
|
if (handle->iwcMessage == NULL) {
|
|
#endif
|
|
/* alloc message bufer */
|
|
handle->iwcMessage = kmalloc(sizeof(struct iwcCmdqMessage_t),
|
|
GFP_KERNEL);
|
|
if (handle->iwcMessage == NULL) {
|
|
CMDQ_ERR("handle->iwcMessage kmalloc failed!\n");
|
|
return -ENOMEM;
|
|
}
|
|
#if CMDQ_OPEN_SESSION_ONCE
|
|
}
|
|
#endif
|
|
CMDQ_MSG("handle->iwcMessage 0x%p\n", handle->iwcMessage);
|
|
|
|
/* init session handle */
|
|
handle->sessionHandle = cmdq_session_handle();
|
|
if (handle->sessionHandle == 0)
|
|
return -1;
|
|
|
|
/* init memory session handle */
|
|
handle->memSessionHandle = cmdq_mem_session_handle();
|
|
if (handle->memSessionHandle == 0) {
|
|
CMDQ_ERR("create cmdq_mem_session_handle error\n");
|
|
return -2;
|
|
}
|
|
|
|
CMDQ_MSG("handle->sessionHandle 0x%x\n", handle->sessionHandle);
|
|
CMDQ_MSG("handle->memSessionHandle 0x%x\n", handle->memSessionHandle);
|
|
return 0;
|
|
}
|
|
#endif
|
|
|
|
#if defined(CMDQ_SECURE_PATH_SUPPORT)
|
|
static void cmdq_sec_deinit_session_unlocked(
|
|
struct cmdqSecContextStruct *handle)
|
|
{
|
|
CMDQ_MSG("[SEC]-->SESSION_DEINIT\n");
|
|
do {
|
|
if (handle->iwcMessage != NULL) {
|
|
kfree(handle->iwcMessage);
|
|
handle->iwcMessage = NULL;
|
|
}
|
|
|
|
} while (0);
|
|
|
|
CMDQ_MSG("[SEC]<--SESSION_DEINIT\n");
|
|
}
|
|
#endif
|
|
|
|
#if defined(CMDQ_SECURE_PATH_SUPPORT)
|
|
static int32_t cmdq_sec_fill_iwc_command_basic_unlocked(
|
|
struct iwcCmdqMessage_t *_pIwc,
|
|
uint32_t iwcCommand,
|
|
struct TaskStruct *_pTask, int32_t thread)
|
|
{
|
|
struct iwcCmdqMessage_t *pIwc;
|
|
|
|
pIwc = (struct iwcCmdqMessage_t *) _pIwc;
|
|
|
|
/* specify command id only, don't care other other */
|
|
memset(pIwc, 0x0, sizeof(struct iwcCmdqMessage_t));
|
|
pIwc->cmd = iwcCommand;
|
|
|
|
/* medatada: debug config */
|
|
/*pIwc->debug.logLevel = (cmdq_core_should_print_msg()) ? (1) : (0); */
|
|
pIwc->debug.logLevel =
|
|
cmdq_sec_get_sec_print_count() ?
|
|
LOG_LEVEL_MSG : cmdq_sec_get_log_level();
|
|
pIwc->debug.enableProfile = cmdq_core_profile_enabled();
|
|
return 0;
|
|
}
|
|
#endif
|
|
|
|
#if defined(CMDQ_SECURE_PATH_SUPPORT)
|
|
static int32_t cmdq_sec_fill_iwc_cancel_msg_unlocked(
|
|
struct iwcCmdqMessage_t *_pIwc,
|
|
uint32_t iwcCommand,
|
|
struct TaskStruct *_pTask, int32_t thread)
|
|
{
|
|
const struct TaskStruct *pTask = (struct TaskStruct *)_pTask;
|
|
struct iwcCmdqMessage_t *pIwc = (struct iwcCmdqMessage_t *) _pIwc;
|
|
|
|
if ((pIwc == NULL) || (pTask == NULL)) {
|
|
CMDQ_ERR("%s invalid param\n", __func__);
|
|
return -1;
|
|
}
|
|
|
|
memset(pIwc, 0x0, sizeof(struct iwcCmdqMessage_t));
|
|
pIwc->cmd = iwcCommand;
|
|
pIwc->cancelTask.waitCookie = pTask->secData.waitCookie;
|
|
pIwc->cancelTask.thread = thread;
|
|
/* medatada: debug config */
|
|
/* pIwc->debug.logLevel = (cmdq_core_should_print_msg()) ? (1) : (0);*/
|
|
pIwc->debug.logLevel =
|
|
cmdq_sec_get_sec_print_count() ?
|
|
LOG_LEVEL_MSG : cmdq_sec_get_log_level();
|
|
pIwc->debug.enableProfile = cmdq_core_profile_enabled();
|
|
CMDQ_LOG("CANCEL_TASK:%p, thread:%d, cookie:%d, resetExecCnt:%d\n",
|
|
pTask, thread, pTask->secData.waitCookie,
|
|
pTask->secData.resetExecCnt);
|
|
return 0;
|
|
}
|
|
#endif
|
|
|
|
#if defined(CMDQ_SECURE_PATH_SUPPORT)
|
|
static int32_t cmdq_sec_fill_iwc_command_msg_unlocked(
|
|
struct iwcCmdqMessage_t *pIwc,
|
|
uint32_t iwcCommand,
|
|
struct TaskStruct *pTask, int32_t thread)
|
|
{
|
|
int32_t status = 0;
|
|
/* TEE will insert some instr,DAPC and M4U configuration */
|
|
const uint32_t reservedCommandSize = 4 * CMDQ_INST_SIZE;
|
|
struct CmdBufferStruct *cmd_buffer = NULL;
|
|
uint32_t buffer_index = 0;
|
|
|
|
CMDQ_MSG("enter fill_iwc_command_msg_unlock\n");
|
|
|
|
if ((pIwc == NULL) || (pTask == NULL)) {
|
|
CMDQ_ERR("%s invalid param", __func__);
|
|
return -EFAULT;
|
|
}
|
|
|
|
/* check command size first */
|
|
if (pTask &&
|
|
(CMDQ_TZ_CMD_BLOCK_SIZE <
|
|
(pTask->commandSize + reservedCommandSize))) {
|
|
CMDQ_ERR("[SEC]SESSION_MSG: pTask %p commandSize %d > %d\n",
|
|
pTask, pTask->commandSize, CMDQ_TZ_CMD_BLOCK_SIZE);
|
|
return -EFAULT;
|
|
}
|
|
|
|
CMDQ_MSG("[SEC]-->SESSION_MSG: cmdId[%d]\n", iwcCommand);
|
|
|
|
/* fill message buffer for inter world communication */
|
|
memset(pIwc, 0x0, sizeof(struct iwcCmdqMessage_t));
|
|
pIwc->cmd = iwcCommand;
|
|
/* metadata */
|
|
pIwc->command.metadata.enginesNeedDAPC = pTask->secData.enginesNeedDAPC;
|
|
pIwc->command.metadata.enginesNeedPortSecurity =
|
|
pTask->secData.enginesNeedPortSecurity;
|
|
pIwc->command.metadata.secMode = pTask->secData.secMode;
|
|
|
|
|
|
if (pTask != NULL && thread != CMDQ_INVALID_THREAD) {
|
|
/* basic data */
|
|
pIwc->command.scenario = pTask->scenario;
|
|
pIwc->command.thread = thread;
|
|
pIwc->command.priority = pTask->priority;
|
|
pIwc->command.engineFlag = pTask->engineFlag;
|
|
pIwc->command.hNormalTask = (0LL | (unsigned long) (pTask));
|
|
pIwc->command.commandSize = pTask->bufferSize;
|
|
|
|
buffer_index = 0;
|
|
list_for_each_entry(cmd_buffer,
|
|
&pTask->cmd_buffer_list, listEntry) {
|
|
uint32_t copy_size = list_is_last(
|
|
&cmd_buffer->listEntry,
|
|
&pTask->cmd_buffer_list) ?
|
|
CMDQ_CMD_BUFFER_SIZE -
|
|
pTask->buf_available_size :
|
|
CMDQ_CMD_BUFFER_SIZE;
|
|
uint32_t *start_va = (pIwc->command.pVABase +
|
|
buffer_index *
|
|
CMDQ_CMD_BUFFER_SIZE / CMDQ_INST_SIZE * 2);
|
|
uint32_t *end_va = start_va +
|
|
copy_size / sizeof(uint32_t);
|
|
|
|
memcpy(start_va, (cmd_buffer->pVABase), (copy_size));
|
|
|
|
/* we must reset the jump inst */
|
|
/* since now buffer is continues */
|
|
if (((end_va[-1] >> 24) & 0xff) == CMDQ_CODE_JUMP &&
|
|
(end_va[-1] & 0x1) == 1) {
|
|
end_va[-1] = CMDQ_CODE_JUMP << 24;
|
|
end_va[-2] = 0x8;
|
|
}
|
|
|
|
buffer_index++;
|
|
}
|
|
|
|
/* cookie */
|
|
pIwc->command.waitCookie = pTask->secData.waitCookie;
|
|
pIwc->command.resetExecCnt = pTask->secData.resetExecCnt;
|
|
|
|
CMDQ_MSG
|
|
("[SEC]SESSION_MSG: task 0x%p, thread: %d, size: %d\n",
|
|
pTask, thread, pTask->commandSize);
|
|
CMDQ_MSG
|
|
("bufferSize: %d, scenario:%d\n",
|
|
pTask->bufferSize, pTask->scenario);
|
|
CMDQ_MSG("flag:0x%08llx ,hNormalTask:0x%llx\n",
|
|
pTask->engineFlag, pIwc->command.hNormalTask);
|
|
|
|
CMDQ_VERBOSE("[SEC]SESSION_MSG: addrList[%d][0x%llx]\n",
|
|
pTask->secData.addrMetadataCount,
|
|
pTask->secData.addrMetadatas);
|
|
if (pTask->secData.addrMetadataCount > 0) {
|
|
pIwc->command.metadata.addrListLength =
|
|
pTask->secData.addrMetadataCount;
|
|
memcpy((pIwc->command.metadata.addrList),
|
|
CMDQ_U32_PTR(pTask->secData.addrMetadatas),
|
|
(pTask->secData.addrMetadataCount) *
|
|
sizeof(struct iwcCmdqAddrMetadata_t));
|
|
}
|
|
|
|
pIwc->debug.logLevel =
|
|
cmdq_sec_get_sec_print_count() ? LOG_LEVEL_MSG :
|
|
cmdq_sec_get_log_level();
|
|
pIwc->debug.enableProfile = cmdq_core_profile_enabled();
|
|
} else {
|
|
/* relase resource, or debug function will go here */
|
|
CMDQ_VERBOSE("[SEC]-->SESSION_MSG: no task, cmdId[%d]\n",
|
|
iwcCommand);
|
|
pIwc->command.commandSize = 0;
|
|
pIwc->command.metadata.addrListLength = 0;
|
|
}
|
|
|
|
CMDQ_MSG("[SEC]<--SESSION_MSG[%d]\n", status);
|
|
CMDQ_MSG("leaving fill_iwc_command_msg_unlock\n");
|
|
return status;
|
|
}
|
|
#endif
|
|
|
|
void dump_message(const struct iwcCmdqMessage_t *message)
|
|
{
|
|
#ifdef DEBUG_SVP_INFO
|
|
CMDQ_LOG("dump iwcCmdqMessage info\n");
|
|
CMDQ_LOG("cmdID:%d,thread:%d,scenario:%d,priority:%d\n",
|
|
message->cmd,
|
|
message->command.thread,
|
|
message->command.scenario,
|
|
message->command.priority);
|
|
CMDQ_LOG("commandSize:%d,engineFlag:0x%llx\n",
|
|
message->command.commandSize,
|
|
message->command.engineFlag);
|
|
CMDQ_LOG("pVABase:0x%p\n", message->command.pVABase);
|
|
CMDQ_LOG("addrlistLen:%d,needDAPC:0x%llx,needPortSecurity:0x%llx\n",
|
|
message->command.metadata.addrListLength,
|
|
message->command.metadata.enginesNeedDAPC,
|
|
message->command.metadata.enginesNeedPortSecurity);
|
|
#else
|
|
CMDQ_ERR("please open DEBUG_SVP_INFO macro first\n");
|
|
#endif
|
|
}
|
|
|
|
#if defined(CMDQ_SECURE_PATH_SUPPORT)
|
|
static int32_t cmdq_sec_execute_session_unlocked(
|
|
struct cmdqSecContextStruct *handle)
|
|
{
|
|
TZ_RESULT tzRes;
|
|
|
|
CMDQ_PROF_START("CMDQ_SEC_EXE");
|
|
|
|
do {
|
|
/* Register share memory */
|
|
union MTEEC_PARAM cmdq_param[4];
|
|
unsigned int paramTypes;
|
|
KREE_SHAREDMEM_HANDLE cmdq_share_handle = 0;
|
|
struct KREE_SHAREDMEM_PARAM cmdq_shared_param;
|
|
/* allocate path init for shared cookie */
|
|
if (CMD_CMDQ_TL_INIT_SHARED_MEMORY ==
|
|
((struct iwcCmdqMessage_t *) (handle->iwcMessage))->cmd) {
|
|
cmdq_shared_param.buffer =
|
|
cmdq_core_get_cmdqcontext()
|
|
->hSecSharedMem->pVABase;
|
|
cmdq_shared_param.size = cmdq_core_get_cmdqcontext()
|
|
->hSecSharedMem->size;
|
|
CMDQ_MSG("cmdq_shared_param.buffer %p\n",
|
|
cmdq_shared_param.buffer);
|
|
CMDQ_MSG("handle->memSessionHandle:%d\n",
|
|
(uint32_t) handle->memSessionHandle);
|
|
tzRes =
|
|
KREE_RegisterSharedmem(handle->memSessionHandle,
|
|
&cmdq_share_handle,
|
|
&cmdq_shared_param);
|
|
/* save for unregister */
|
|
gCmdq_share_cookie_handle = cmdq_share_handle;
|
|
if (tzRes != TZ_RESULT_SUCCESS) {
|
|
CMDQ_ERR
|
|
("register shareMem err:%d,session:%x\n",
|
|
tzRes,
|
|
(unsigned int)(handle->memSessionHandle));
|
|
return tzRes;
|
|
}
|
|
/* KREE_Tee service call */
|
|
cmdq_param[0].memref.handle =
|
|
(uint32_t) cmdq_share_handle;
|
|
cmdq_param[0].memref.offset = 0;
|
|
cmdq_param[0].memref.size = cmdq_shared_param.size;
|
|
paramTypes = TZ_ParamTypes1(TZPT_MEMREF_INOUT);
|
|
tzRes =
|
|
KREE_TeeServiceCall(handle->sessionHandle,
|
|
CMD_CMDQ_TL_INIT_SHARED_MEMORY,
|
|
paramTypes,
|
|
cmdq_param);
|
|
if (tzRes != TZ_RESULT_SUCCESS) {
|
|
CMDQ_ERR("INIT_SHARED_MEMORY fail, ret=0x%x\n",
|
|
tzRes);
|
|
return tzRes;
|
|
}
|
|
CMDQ_MSG("KREE_TeeServiceCall tzRes =0x%x\n", tzRes);
|
|
break;
|
|
}
|
|
cmdq_shared_param.buffer = handle->iwcMessage;
|
|
cmdq_shared_param.size = (sizeof(struct iwcCmdqMessage_t));
|
|
CMDQ_MSG("cmdq_shared_param.buffer %p\n",
|
|
cmdq_shared_param.buffer);
|
|
/* dump_message((iwcCmdqMessage_t *) handle->iwcMessage); */
|
|
|
|
|
|
tzRes =
|
|
KREE_RegisterSharedmem(handle->memSessionHandle,
|
|
&cmdq_share_handle,
|
|
&cmdq_shared_param);
|
|
if (tzRes != TZ_RESULT_SUCCESS) {
|
|
CMDQ_ERR
|
|
("register shareMem err:%d,mem_session:%x\n",
|
|
tzRes,
|
|
(unsigned int)(handle->memSessionHandle));
|
|
break;
|
|
}
|
|
|
|
/* KREE_Tee service call */
|
|
cmdq_param[0].memref.handle = (uint32_t) cmdq_share_handle;
|
|
cmdq_param[0].memref.offset = 0;
|
|
cmdq_param[0].memref.size = cmdq_shared_param.size;
|
|
paramTypes = TZ_ParamTypes1(TZPT_MEMREF_INPUT);
|
|
|
|
CMDQ_MSG("commandID:%d\n", ((struct iwcCmdqMessage_t *)
|
|
(handle->iwcMessage))->cmd);
|
|
CMDQ_MSG("handle->sessionHandle:%x\n", handle->sessionHandle);
|
|
CMDQ_MSG("start to enter Secure World\n");
|
|
|
|
if (CMD_CMDQ_TL_SUBMIT_TASK ==
|
|
((struct iwcCmdqMessage_t *) (handle->iwcMessage))->cmd)
|
|
gSubmitTaskCount++;
|
|
tzRes =
|
|
KREE_TeeServiceCall(handle->sessionHandle,
|
|
((struct iwcCmdqMessage_t *)
|
|
(handle->iwcMessage))->cmd,
|
|
paramTypes, cmdq_param);
|
|
if (tzRes != TZ_RESULT_SUCCESS) {
|
|
CMDQ_ERR("leave secure world fail, ret=0x%x\n",
|
|
tzRes);
|
|
break;
|
|
}
|
|
CMDQ_MSG("leave secure world KREE_TeeServiceCall tzRes =0x%x\n",
|
|
tzRes);
|
|
|
|
|
|
/* Unregister share memory */
|
|
tzRes = KREE_UnregisterSharedmem(handle->memSessionHandle,
|
|
cmdq_share_handle);
|
|
if (tzRes != TZ_RESULT_SUCCESS) {
|
|
CMDQ_ERR("KREE_UnregisterSharedmem fail, ret=0x%x\n",
|
|
tzRes);
|
|
break;
|
|
}
|
|
|
|
/* wait respond */
|
|
|
|
/* config with timeout */
|
|
|
|
|
|
} while (0);
|
|
|
|
CMDQ_PROF_END("CMDQ_SEC_EXE");
|
|
|
|
/* return tee service call result */
|
|
return tzRes;
|
|
}
|
|
#endif
|
|
|
|
CmdqSecFillIwcCB cmdq_sec_get_iwc_msg_fill_cb_by_iwc_command(
|
|
uint32_t iwcCommand)
|
|
{
|
|
#if defined(CMDQ_SECURE_PATH_SUPPORT)
|
|
CmdqSecFillIwcCB cb = NULL;
|
|
|
|
switch (iwcCommand) {
|
|
case CMD_CMDQ_TL_CANCEL_TASK:
|
|
cb = cmdq_sec_fill_iwc_cancel_msg_unlocked;
|
|
break;
|
|
case CMD_CMDQ_TL_SUBMIT_TASK:
|
|
cb = cmdq_sec_fill_iwc_command_msg_unlocked;
|
|
break;
|
|
case CMD_CMDQ_TL_TEST_HELLO_TL:
|
|
case CMD_CMDQ_TL_TEST_DUMMY:
|
|
default:
|
|
cb = cmdq_sec_fill_iwc_command_basic_unlocked;
|
|
break;
|
|
};
|
|
return cb;
|
|
#else
|
|
CMDQ_ERR("SVP feature is not on\n");
|
|
return (CmdqSecFillIwcCB)NULL;
|
|
#endif
|
|
}
|
|
|
|
int32_t cmdq_sec_send_context_session_message(
|
|
struct cmdqSecContextStruct *handle,
|
|
uint32_t iwcCommand,
|
|
struct TaskStruct *pTask,
|
|
int32_t thread,
|
|
CmdqSecFillIwcCB iwcFillCB, void *data)
|
|
{
|
|
#if defined(CMDQ_SECURE_PATH_SUPPORT)
|
|
int32_t status = 0;
|
|
int32_t iwcRsp = 0;
|
|
const CmdqSecFillIwcCB icwcFillCB = (iwcFillCB == NULL) ?
|
|
cmdq_sec_get_iwc_msg_fill_cb_by_iwc_command(iwcCommand) :
|
|
(iwcFillCB);
|
|
CMDQ_MSG("enter %s()", __func__);
|
|
|
|
do {
|
|
|
|
/* fill message bufer */
|
|
/*debug level */
|
|
((struct iwcCmdqMessage_t *)
|
|
(handle->iwcMessage))->debug.logLevel =
|
|
cmdq_sec_get_sec_print_count() ?
|
|
LOG_LEVEL_MSG :
|
|
cmdq_sec_get_log_level();
|
|
status =
|
|
icwcFillCB((struct iwcCmdqMessage_t *)(handle->iwcMessage),
|
|
iwcCommand, pTask,
|
|
thread);
|
|
if (status < 0)
|
|
break;
|
|
|
|
/* send message */
|
|
status = cmdq_sec_execute_session_unlocked(handle);
|
|
if (status != TZ_RESULT_SUCCESS) {
|
|
CMDQ_ERR("execute_session_unlocked status:%d\n",
|
|
status);
|
|
break;
|
|
}
|
|
/* get secure task execution result */
|
|
/*
|
|
* iwcRsp = ((iwcCmdqMessage_t*)(handle->iwcMessage))->rsp;
|
|
* status = iwcRsp; //(0 == iwcRsp)? (0):(-EFAULT);
|
|
*/
|
|
|
|
/* and then, update task state */
|
|
/* log print */
|
|
if (status > 0) {
|
|
CMDQ_ERR("SEC_SEND:status[%d],cmdId[%d],iwcRsp[%d]\n",
|
|
status,
|
|
iwcCommand, iwcRsp);
|
|
} else {
|
|
CMDQ_MSG("SEC_SEND:status[%d],cmdId[%d],iwcRsp[%d]\n",
|
|
status,
|
|
iwcCommand, iwcRsp);
|
|
}
|
|
} while (0);
|
|
|
|
return status;
|
|
#else
|
|
CMDQ_ERR("SVP feature is not on\n");
|
|
return 0;
|
|
#endif
|
|
}
|
|
|
|
|
|
#if !(CMDQ_OPEN_SESSION_ONCE)
|
|
static int32_t cmdq_sec_teardown_context_session(
|
|
struct cmdqSecContextStruct *handle)
|
|
{
|
|
#if defined(CMDQ_SECURE_PATH_SUPPORT)
|
|
int32_t status = 0;
|
|
|
|
if (handle) {
|
|
CMDQ_MSG("SEC_TEARDOWN:iwcMessage:0x%p\n", handle->iwcMessage);
|
|
cmdq_sec_deinit_session_unlocked(handle);
|
|
} else {
|
|
CMDQ_ERR("SEC_TEARDOWN: null secCtxHandle\n");
|
|
status = -1;
|
|
}
|
|
return status;
|
|
#else
|
|
CMDQ_ERR("SVP feature is not on\n");
|
|
return 0;
|
|
#endif
|
|
}
|
|
#endif
|
|
|
|
int32_t cmdq_sec_submit_to_secure_world_async_unlocked(
|
|
uint32_t iwcCommand,
|
|
struct TaskStruct *pTask,
|
|
int32_t thread,
|
|
CmdqSecFillIwcCB iwcFillCB, void *data, bool throwAEE)
|
|
{
|
|
#if defined(CMDQ_SECURE_PATH_SUPPORT)
|
|
|
|
const int32_t tgid = current->tgid;
|
|
const int32_t pid = current->pid;
|
|
|
|
struct cmdqSecContextStruct *handle = NULL;
|
|
int32_t status = 0;
|
|
int32_t duration = 0;
|
|
|
|
CMDQ_TIME tEntrySec;
|
|
CMDQ_TIME tExitSec;
|
|
|
|
|
|
CMDQ_MSG("[SEC]-->SEC_SUBMIT: tgid[%d:%d]\n", tgid, pid);
|
|
do {
|
|
/* find handle first */
|
|
|
|
if (gCmdqSecContextHandle == NULL)
|
|
gCmdqSecContextHandle =
|
|
cmdq_sec_context_handle_create(current->tgid);
|
|
|
|
handle = gCmdqSecContextHandle;
|
|
|
|
/* find handle first */
|
|
/* handle = cmdq_sec_find_context_handle_unlocked(tgid); */
|
|
/* handle = cmdq_sec_acquire_context_handle(tgid); */
|
|
if (handle == NULL) {
|
|
CMDQ_ERR("SEC_SUBMIT: tgid %d err[NULL secCtxHandle]\n",
|
|
tgid);
|
|
status = -(CMDQ_ERR_NULL_SEC_CTX_HANDLE);
|
|
break;
|
|
}
|
|
/* alloc iwc buffer */
|
|
if (cmdq_sec_setup_context_session(handle) < 0) {
|
|
status = -(CMDQ_ERR_SEC_CTX_SETUP);
|
|
break;
|
|
}
|
|
CMDQ_MSG("leaving cmdq_sec_setup_context_session()\n");
|
|
/* */
|
|
/* record profile data */
|
|
/* tbase timer/time support is not enough currently, */
|
|
/* so we treats entry/exit timing to secure world as */
|
|
/*the trigger/gotIRQ_&_wakeup timing */
|
|
/* */
|
|
/* if (CMD_CMDQ_TL_INIT_SHARED_MEMORY == iwcCommand)
|
|
* gCmdqContext.hSecSharedMem->handle = handle;
|
|
*/
|
|
|
|
tEntrySec = sched_clock();
|
|
status =
|
|
cmdq_sec_send_context_session_message(handle,
|
|
iwcCommand, pTask, thread,
|
|
iwcFillCB, data);
|
|
tExitSec = sched_clock();
|
|
CMDQ_GET_TIME_IN_US_PART(tEntrySec, tExitSec, duration);
|
|
if (pTask) {
|
|
pTask->trigger = tEntrySec;
|
|
pTask->gotIRQ = tExitSec;
|
|
pTask->wakedUp = tExitSec;
|
|
}
|
|
#if !(CMDQ_OPEN_SESSION_ONCE)
|
|
/* teardown context session in Deinit */
|
|
cmdq_sec_teardown_context_session(handle);
|
|
#endif
|
|
|
|
/* Note we entry secure for config only */
|
|
/* and wait result in normal world. */
|
|
/* No need reset module HW for config failed case */
|
|
|
|
|
|
} while (0);
|
|
|
|
if (-ETIMEDOUT == status) {
|
|
/* t-base strange issue, mc_wait_notification false */
|
|
/* timeout when secure world has done */
|
|
/* because retry may failed, give up retry method */
|
|
CMDQ_ERR("CMDQ [SEC]<--SEC_SUBMIT: err[%d][timeout]\n",
|
|
status);
|
|
CMDQ_ERR("pTask[0x%p], THR[%d], tgid[%d:%d]\n",
|
|
pTask, thread, tgid, pid);
|
|
CMDQ_ERR("config_duration_ms[%d], cmdId[%d]\n",
|
|
duration, iwcCommand);
|
|
|
|
} else if (status < 0) {
|
|
if (throwAEE) {
|
|
char buffer[200] = {0};
|
|
int n = 0;
|
|
|
|
n += snprintf(buffer, sizeof(buffer) - n,
|
|
"[SEC]<--SEC_SUBMIT: err[%d], pTask[0x%p], ",
|
|
status, pTask);
|
|
n += snprintf(buffer + n, sizeof(buffer) - n,
|
|
"THR[%d],tgid[%d:%d],dur_ms[%d],cmdId[%d]\n",
|
|
thread,
|
|
tgid,
|
|
pid, duration, iwcCommand);
|
|
|
|
/* throw AEE */
|
|
CMDQ_AEE("CMDQ", "%s", buffer);
|
|
}
|
|
} else {
|
|
CMDQ_MSG
|
|
("[SEC]<--SEC_SUBMIT: err[%d], pTask[0x%p], THR[%d]\n",
|
|
status, pTask, thread);
|
|
CMDQ_MSG
|
|
("tgid[%d:%d], config_duration_ms[%d], cmdId[%d]\n",
|
|
tgid, pid, duration, iwcCommand);
|
|
}
|
|
return status;
|
|
#else
|
|
CMDQ_ERR("SVP feature is not supported\n");
|
|
return 0;
|
|
#endif
|
|
}
|
|
|
|
|
|
|
|
int32_t cmdq_sec_exec_task_async_unlocked(
|
|
struct TaskStruct *pTask, int32_t thread)
|
|
{
|
|
#ifdef CMDQ_SECURE_PATH_SUPPORT
|
|
int32_t status = 0;
|
|
|
|
status =
|
|
cmdq_sec_submit_to_secure_world_async_unlocked(
|
|
CMD_CMDQ_TL_SUBMIT_TASK, pTask, thread,
|
|
NULL, NULL, true);
|
|
|
|
if (status < 0)
|
|
CMDQ_ERR("%s[%d]\n", __func__, status);
|
|
|
|
|
|
return status;
|
|
|
|
|
|
#else
|
|
CMDQ_ERR("SVP feature is not on\n");
|
|
return -EFAULT;
|
|
#endif
|
|
}
|
|
|
|
int32_t cmdq_sec_cancel_error_task_unlocked(
|
|
struct TaskStruct *pTask, int32_t thread,
|
|
struct cmdqSecCancelTaskResultStruct *pResult)
|
|
{
|
|
#ifdef CMDQ_SECURE_PATH_SUPPORT
|
|
int32_t status = 0;
|
|
|
|
if ((pTask == NULL) ||
|
|
(cmdq_get_func()->isSecureThread(thread) == false)
|
|
|| (pResult == NULL)) {
|
|
CMDQ_ERR("%s invalid param, pTask:%p, thread:%d, pResult:%p\n",
|
|
__func__, pTask, thread, pResult);
|
|
return -EFAULT;
|
|
}
|
|
status = cmdq_sec_submit_to_secure_world_async_unlocked(
|
|
CMD_CMDQ_TL_CANCEL_TASK,
|
|
pTask, thread, NULL,
|
|
(void *)pResult, true);
|
|
|
|
if (status <= 0)
|
|
CMDQ_ERR("gSubmitTaskCount:%u\n", gSubmitTaskCount);
|
|
|
|
return status;
|
|
#else
|
|
CMDQ_ERR("secure path not support\n");
|
|
return -EFAULT;
|
|
#endif
|
|
}
|
|
|
|
#if defined(CMDQ_SECURE_PATH_SUPPORT)
|
|
static atomic_t gCmdqSecPathResource = ATOMIC_INIT(0);
|
|
#endif
|
|
|
|
int32_t cmdq_sec_allocate_path_resource_unlocked(bool throwAEE)
|
|
{
|
|
#ifdef CMDQ_SECURE_PATH_SUPPORT
|
|
int32_t status = 0;
|
|
|
|
CMDQ_MSG("%s throwAEE: %s", __func__, throwAEE ? "true" : "false");
|
|
|
|
if (atomic_cmpxchg(&gCmdqSecPathResource, 0, 1) != 0) {
|
|
/* has allocated successfully */
|
|
CMDQ_MSG("allocate path resource already\n");
|
|
return status;
|
|
}
|
|
CMDQ_MSG("begine to allocate path resource\n");
|
|
status =
|
|
cmdq_sec_submit_to_secure_world_async_unlocked(
|
|
CMD_CMDQ_TL_PATH_RES_ALLOCATE, NULL, -1,
|
|
NULL, NULL, throwAEE);
|
|
if (status < 0) {
|
|
CMDQ_ERR("%s[%d] reset context\n", __func__, status);
|
|
|
|
/* in fail case, we want function alloc again */
|
|
atomic_set(&gCmdqSecPathResource, 0);
|
|
}
|
|
|
|
return status;
|
|
#else
|
|
CMDQ_ERR("secure path not support\n");
|
|
return -EFAULT;
|
|
#endif
|
|
}
|
|
|
|
int32_t cmdq_sec_init_share_memory(void)
|
|
{
|
|
#ifdef CMDQ_SECURE_PATH_SUPPORT
|
|
int32_t status = 0;
|
|
|
|
CMDQ_MSG("starting test init share memory\n");
|
|
status =
|
|
cmdq_sec_submit_to_secure_world_async_unlocked(
|
|
CMD_CMDQ_TL_INIT_SHARED_MEMORY, NULL, -1,
|
|
NULL, NULL, true);
|
|
if (status < 0)
|
|
CMDQ_ERR("%s[%d]\n", __func__, status);
|
|
|
|
CMDQ_MSG("test init share memory end\n");
|
|
return status;
|
|
#else
|
|
CMDQ_ERR("secure path not support\n");
|
|
return -EFAULT;
|
|
#endif
|
|
}
|
|
|
|
|
|
/* ---------------------------------------------------------- */
|
|
|
|
struct cmdqSecContextStruct *cmdq_sec_find_context_handle_unlocked(
|
|
uint32_t tgid)
|
|
{
|
|
#ifdef CMDQ_SECURE_PATH_SUPPORT
|
|
struct cmdqSecContextStruct *handle = NULL;
|
|
|
|
do {
|
|
struct cmdqSecContextStruct *secContextEntry = NULL;
|
|
struct list_head *pos = NULL;
|
|
|
|
list_for_each(pos, &gCmdqSecContextList) {
|
|
secContextEntry = list_entry(pos,
|
|
struct cmdqSecContextStruct, listEntry);
|
|
if (secContextEntry && tgid == secContextEntry->tgid) {
|
|
handle = secContextEntry;
|
|
break;
|
|
}
|
|
}
|
|
} while (0);
|
|
|
|
CMDQ_MSG("SecCtxHandle_SEARCH: Handle[0x%p], tgid[%d]\n", handle, tgid);
|
|
return handle;
|
|
#else
|
|
CMDQ_ERR("secure path not support\n");
|
|
return (struct cmdqSecContextStruct *)NULL;
|
|
#endif
|
|
}
|
|
|
|
|
|
int32_t cmdq_sec_release_context_handle_unlocked(
|
|
struct cmdqSecContextStruct *handle)
|
|
{
|
|
#ifdef CMDQ_SECURE_PATH_SUPPORT
|
|
int32_t status = 0;
|
|
|
|
do {
|
|
handle->referCount--;
|
|
if (handle->referCount > 0)
|
|
break;
|
|
|
|
/* 1. clean up secure path in secure world */
|
|
/* 2. delete secContext from list */
|
|
list_del(&(handle->listEntry));
|
|
/* 3. release secure path resource in normal world */
|
|
kfree(handle);
|
|
|
|
} while (0);
|
|
return status;
|
|
#else
|
|
CMDQ_ERR("secure path not support\n");
|
|
return 0;
|
|
#endif
|
|
}
|
|
|
|
int32_t cmdq_sec_release_context_handle(uint32_t tgid)
|
|
{
|
|
#ifdef CMDQ_SECURE_PATH_SUPPORT
|
|
int32_t status = 0;
|
|
struct cmdqSecContextStruct *handle = NULL;
|
|
|
|
mutex_lock(&gCmdqSecContextLock);
|
|
smp_mb(); /*memory barrier */
|
|
|
|
handle = cmdq_sec_find_context_handle_unlocked(tgid);
|
|
if (handle) {
|
|
CMDQ_MSG("SecCtxHandle_RELEASE: +tgid[%d], handle[0x%p]\n",
|
|
tgid, handle);
|
|
status = cmdq_sec_release_context_handle_unlocked(handle);
|
|
CMDQ_MSG("SecCtxHandle_RELEASE: -tgid[%d], status[%d]\n",
|
|
tgid, status);
|
|
} else {
|
|
status = -1;
|
|
CMDQ_ERR("SecCtxHandle_RELEASE: err[not exist], tgid[%d]\n",
|
|
tgid);
|
|
}
|
|
|
|
mutex_unlock(&gCmdqSecContextLock);
|
|
return status;
|
|
#else
|
|
CMDQ_ERR("secure path not support\n");
|
|
return 0;
|
|
#endif
|
|
}
|
|
|
|
struct cmdqSecContextStruct *cmdq_sec_context_handle_create(
|
|
uint32_t tgid)
|
|
{
|
|
#ifdef CMDQ_SECURE_PATH_SUPPORT
|
|
struct cmdqSecContextStruct *handle = NULL;
|
|
|
|
handle = kmalloc(sizeof(uint8_t *) *
|
|
sizeof(struct cmdqSecContextStruct), GFP_ATOMIC);
|
|
if (handle) {
|
|
handle->iwcMessage = NULL;
|
|
handle->tgid = tgid;
|
|
handle->referCount = 0;
|
|
} else {
|
|
CMDQ_ERR("SecCtxHandle_CREATE: err[LOW_MEM], tgid[%d]\n", tgid);
|
|
}
|
|
|
|
CMDQ_MSG("SecCtxHandle_CREATE: create new, Handle[0x%p], tgid[%d]\n",
|
|
handle, tgid);
|
|
return handle;
|
|
#else
|
|
CMDQ_ERR("secure path not support\n");
|
|
return (struct cmdqSecContextStruct *)NULL;
|
|
#endif
|
|
}
|
|
|
|
struct cmdqSecContextStruct *cmdq_sec_acquire_context_handle(
|
|
uint32_t tgid)
|
|
{
|
|
#ifdef CMDQ_SECURE_PATH_SUPPORT
|
|
struct cmdqSecContextStruct *handle = NULL;
|
|
|
|
mutex_lock(&gCmdqSecContextLock);
|
|
smp_mb(); /*memory barrier */
|
|
do {
|
|
/* find sec context of a process */
|
|
handle = cmdq_sec_find_context_handle_unlocked(tgid);
|
|
/* if it dose not exist, create new one */
|
|
if (handle == NULL) {
|
|
handle = cmdq_sec_context_handle_create(tgid);
|
|
if (handle)
|
|
list_add_tail(&(handle->listEntry),
|
|
&gCmdqSecContextList);
|
|
}
|
|
} while (0);
|
|
|
|
/* increase caller referCount */
|
|
if (handle)
|
|
handle->referCount++;
|
|
|
|
if (handle) {
|
|
CMDQ_MSG("[CMDQ]Handle[0x%p], tgid[%d], refCount[%d]\n",
|
|
handle, tgid,
|
|
handle->referCount);
|
|
}
|
|
mutex_unlock(&gCmdqSecContextLock);
|
|
|
|
return handle;
|
|
#else
|
|
CMDQ_ERR("secure path not support\n");
|
|
return (struct cmdqSecContextStruct *)NULL;
|
|
#endif
|
|
}
|
|
|
|
void cmdq_sec_dump_context_list(void)
|
|
{
|
|
#ifdef CMDQ_SECURE_PATH_SUPPORT
|
|
struct cmdqSecContextStruct *secContextEntry = NULL;
|
|
struct list_head *pos = NULL;
|
|
|
|
CMDQ_ERR("=============== [CMDQ] sec context ===============\n");
|
|
|
|
list_for_each(pos, &gCmdqSecContextList) {
|
|
secContextEntry = list_entry(pos,
|
|
struct cmdqSecContextStruct, listEntry);
|
|
CMDQ_ERR("handle[0x%p],gid_%d[ref:%d],state[%d],iwc[0x%p]\n",
|
|
secContextEntry,
|
|
secContextEntry->tgid,
|
|
secContextEntry->referCount,
|
|
secContextEntry->state, secContextEntry->iwcMessage);
|
|
}
|
|
#else
|
|
CMDQ_ERR("secure path not support\n");
|
|
#endif
|
|
}
|
|
|
|
void cmdqSecDeInitialize(void)
|
|
{
|
|
#if defined(CMDQ_SECURE_PATH_SUPPORT)
|
|
/* .TEE. close SVP CMDQ TEE serivice session */
|
|
/* the sessions are created and accessed */
|
|
/* using [cmdq_session_handle()] / */
|
|
/* [cmdq_mem_session_handle()] API, and closed here. */
|
|
|
|
struct cmdqSecContextStruct *secContextEntry = NULL;
|
|
struct list_head *pos = NULL;
|
|
TZ_RESULT ret;
|
|
|
|
ret = KREE_UnregisterSharedmem(gCmdqSecContextHandle->memSessionHandle,
|
|
gCmdq_share_cookie_handle);
|
|
if (ret != TZ_RESULT_SUCCESS) {
|
|
CMDQ_ERR("deinit unregister share memory failed ret=%d\n", ret);
|
|
return;
|
|
}
|
|
|
|
ret = KREE_CloseSession(cmdq_session);
|
|
if (ret != TZ_RESULT_SUCCESS) {
|
|
CMDQ_ERR("DDP close ddp_session fail ret=%d\n", ret);
|
|
return;
|
|
}
|
|
|
|
ret = KREE_CloseSession(cmdq_mem_session);
|
|
if (ret != TZ_RESULT_SUCCESS) {
|
|
CMDQ_ERR("DDP close ddp_mem_session fail ret=%d\n", ret);
|
|
return;
|
|
}
|
|
|
|
/* release shared memory */
|
|
cmdq_sec_destroy_shared_memory(
|
|
cmdq_core_get_cmdqcontext()->hSecSharedMem);
|
|
|
|
#if CMDQ_OPEN_SESSION_ONCE
|
|
cmdq_sec_deinit_session_unlocked(gCmdqSecContextHandle);
|
|
#endif
|
|
if (gCmdqSecContextHandle != NULL) {
|
|
kfree(gCmdqSecContextHandle);
|
|
gCmdqSecContextHandle = NULL;
|
|
}
|
|
|
|
/*release cmdqSecContextHandle */
|
|
mutex_lock(&gCmdqSecContextLock);
|
|
smp_mb(); /*memory barrier */
|
|
|
|
list_for_each(pos, &gCmdqSecContextList) {
|
|
secContextEntry = list_entry(pos,
|
|
struct cmdqSecContextStruct, listEntry);
|
|
if (secContextEntry != NULL) {
|
|
secContextEntry->referCount = 0;
|
|
cmdq_sec_release_context_handle_unlocked(
|
|
secContextEntry);
|
|
}
|
|
}
|
|
|
|
mutex_unlock(&gCmdqSecContextLock);
|
|
#else
|
|
CMDQ_ERR("secure path not support\n");
|
|
#endif
|
|
}
|
|
|
|
int32_t cmdqSecRegisterSecureBuffer(
|
|
struct transmitBufferStruct *pSecureData)
|
|
{
|
|
#ifdef CMDQ_SECURE_PATH_SUPPORT
|
|
int32_t status = 0;
|
|
struct KREE_SHAREDMEM_PARAM cmdq_shared_param;
|
|
TZ_RESULT tzRes = TZ_RESULT_SUCCESS;
|
|
|
|
do {
|
|
if (pSecureData == NULL) {
|
|
status = -1;
|
|
break;
|
|
}
|
|
|
|
cmdq_shared_param.buffer = pSecureData->pBuffer;
|
|
cmdq_shared_param.size = pSecureData->size;
|
|
|
|
if (pSecureData->memSessionHandle == 0) {
|
|
pSecureData->memSessionHandle =
|
|
cmdq_mem_session_handle();
|
|
if (pSecureData->memSessionHandle == 0) {
|
|
status = -2;
|
|
break;
|
|
}
|
|
}
|
|
|
|
|
|
tzRes = KREE_RegisterSharedmem(pSecureData->memSessionHandle,
|
|
&(pSecureData->shareMemHandle),
|
|
&cmdq_shared_param);
|
|
|
|
|
|
if (tzRes != TZ_RESULT_SUCCESS) {
|
|
status = -3;
|
|
break;
|
|
}
|
|
} while (0);
|
|
|
|
if (status != 0)
|
|
CMDQ_ERR("%s failed, status[%d]\n", __func__, status);
|
|
|
|
|
|
return status;
|
|
#else
|
|
CMDQ_ERR("secure path not support\n");
|
|
return 0;
|
|
#endif
|
|
}
|
|
|
|
int32_t cmdqSecServiceCall(struct transmitBufferStruct *pSecureData,
|
|
int32_t cmd)
|
|
{
|
|
#ifdef CMDQ_SECURE_PATH_SUPPORT
|
|
union MTEEC_PARAM cmdq_param[4];
|
|
unsigned int paramTypes = TZ_ParamTypes1(TZPT_MEMREF_INPUT);
|
|
TZ_RESULT tzRes = TZ_RESULT_SUCCESS;
|
|
|
|
if (pSecureData->cmdqHandle == 0) {
|
|
pSecureData->cmdqHandle = cmdq_session_handle();
|
|
if (pSecureData->cmdqHandle == 0) {
|
|
CMDQ_ERR("get cmdq handle failed\n");
|
|
return -1;
|
|
}
|
|
}
|
|
|
|
|
|
cmdq_param[0].memref.handle =
|
|
(uint32_t) pSecureData->shareMemHandle;
|
|
cmdq_param[0].memref.offset = 0;
|
|
cmdq_param[0].memref.size = pSecureData->size;
|
|
|
|
tzRes = KREE_TeeServiceCall(pSecureData->cmdqHandle,
|
|
cmd, paramTypes, cmdq_param);
|
|
if (tzRes != TZ_RESULT_SUCCESS) {
|
|
CMDQ_ERR("leave secure world %s fail, ret=0x%x\n",
|
|
__func__, tzRes);
|
|
return -2;
|
|
}
|
|
return 0;
|
|
#else
|
|
CMDQ_ERR("secure path not support\n");
|
|
return 0;
|
|
#endif
|
|
}
|
|
|
|
int32_t cmdqSecUnRegisterSecureBuffer(
|
|
struct transmitBufferStruct *pSecureData)
|
|
{
|
|
#ifdef CMDQ_SECURE_PATH_SUPPORT
|
|
TZ_RESULT ret = TZ_RESULT_SUCCESS;
|
|
|
|
ret = KREE_UnregisterSharedmem(pSecureData->memSessionHandle,
|
|
pSecureData->shareMemHandle);
|
|
|
|
if (ret != TZ_RESULT_SUCCESS) {
|
|
CMDQ_ERR("deinit unregister share memory failed ret=%d\n", ret);
|
|
return -1;
|
|
}
|
|
return 0;
|
|
#else
|
|
CMDQ_ERR("secure path not support\n");
|
|
return 0;
|
|
#endif
|
|
}
|
|
|
|
void cmdq_sec_register_secure_irq(void)
|
|
{
|
|
/*
|
|
** pass SECURE IRQ ID to trustzone
|
|
** 1 prepare buffer to transfer to secure world
|
|
** 2 register secure buffer
|
|
** 3 service call
|
|
** 4 unregister secure buffer
|
|
*/
|
|
|
|
/* 1 prepare buffer to transfer to secure world */
|
|
uint32_t secureIrqID = cmdq_dev_get_irq_secure_id();
|
|
struct transmitBufferStruct secureData;
|
|
|
|
memset(&secureData, 0, sizeof(secureData));
|
|
secureData.pBuffer = &secureIrqID;
|
|
secureData.size = sizeof(secureIrqID);
|
|
|
|
/* 2 register secure buffer */
|
|
if (cmdqSecRegisterSecureBuffer(&secureData) != 0)
|
|
return;
|
|
CMDQ_LOG("register secure irq normal\n");
|
|
|
|
/* 3 service call */
|
|
cmdqSecServiceCall(&secureData, CMD_CMDQ_TL_REGISTER_SECURE_IRQ);
|
|
|
|
/* 4 unregister secure buffer */
|
|
cmdqSecUnRegisterSecureBuffer(&secureData);
|
|
|
|
|
|
}
|
|
|
|
void cmdqSecInitialize(void)
|
|
{
|
|
#ifdef CMDQ_SECURE_PATH_SUPPORT
|
|
INIT_LIST_HEAD(&gCmdqSecContextList);
|
|
/* cmdq_sec_allocate_path_resource_unlocked(); */
|
|
|
|
#endif
|
|
}
|
|
|
|
int cmdq_sec_init_secure_path(void *data)
|
|
{
|
|
#ifdef CMDQ_SECURE_PATH_SUPPORT
|
|
int status = 0;
|
|
|
|
CMDQ_LOG("begin to init secure path\n");
|
|
/* allocate shared memory */
|
|
cmdq_core_get_cmdqcontext()->hSecSharedMem = NULL;
|
|
status = cmdq_sec_create_shared_memory(
|
|
&(cmdq_core_get_cmdqcontext()->hSecSharedMem), PAGE_SIZE);
|
|
/* init share memory */
|
|
cmdq_sec_lock_secure_path();
|
|
status &= cmdq_sec_init_share_memory();
|
|
cmdq_sec_unlock_secure_path();
|
|
CMDQ_LOG("init secure path done\n");
|
|
return status;
|
|
#else
|
|
CMDQ_ERR("secure path not support\n");
|
|
return 0;
|
|
#endif
|
|
}
|
|
|
|
void cmdqSecEnableProfile(const bool enable)
|
|
{
|
|
CMDQ_LOG("%s undefined!\n", __func__);
|
|
}
|
|
|
|
/* ------------------------------------------------------------------ */
|
|
/* debug */
|
|
/* */
|
|
void cmdq_sec_set_commandId(uint32_t cmdId)
|
|
{
|
|
atomic_set(&gDebugSecCmdId, cmdId);
|
|
}
|
|
|
|
const uint32_t cmdq_sec_get_commandId(void)
|
|
{
|
|
return (uint32_t) (atomic_read(&gDebugSecCmdId));
|
|
}
|
|
|
|
void cmdq_debug_set_sw_copy(int32_t value)
|
|
{
|
|
atomic_set(&gDebugSecSwCopy, value);
|
|
}
|
|
|
|
int32_t cmdq_debug_get_sw_copy(void)
|
|
{
|
|
return atomic_read(&gDebugSecSwCopy);
|
|
}
|
|
|
|
void cmdq_sec_set_sec_print_count(uint32_t count, bool bPrint)
|
|
{
|
|
gSecPrintCount = count;
|
|
if (bPrint)
|
|
CMDQ_LOG("set sec count to %d\n", count);
|
|
}
|
|
|
|
uint32_t cmdq_sec_get_sec_print_count(void)
|
|
{
|
|
return gSecPrintCount;
|
|
}
|
|
|
|
int32_t cmdq_sec_get_log_level(void)
|
|
{
|
|
int32_t loglevel = cmdq_core_get_log_level();
|
|
|
|
if (loglevel == CMDQ_LOG_LEVEL_NORMAL)
|
|
return LOG_LEVEL_LOG;
|
|
else if (cmdq_core_should_print_msg())
|
|
return LOG_LEVEL_MSG;
|
|
else if (cmdq_core_should_full_error())
|
|
return LOG_LEVEL_LOG;
|
|
else if (loglevel & (1<<3))
|
|
return LOG_LEVEL_MSG;
|
|
|
|
return LOG_LEVEL_LOG;
|
|
}
|
|
|