blob: bca3a0f49efa968c7693d0c89d4d2912568a35f9 [file]
// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2021 MediaTek Inc.
*/
#include <trustzone/kree/mem.h>
#include "trustzone/kree/system.h"
#include <tz_cross/ta_mem.h>
#include <linux/mm.h>
#include <linux/slab.h>
#if IS_ENABLED(CONFIG_MTEE_CMA_SECURE_MEMORY)
#include "tz_cma.h"
#endif
/* #define DBG_KREE_MEM */
/* notiec: handle type is the same */
static inline int _allocFunc(uint32_t cmd, KREE_SESSION_HANDLE session,
uint32_t *mem_handle, uint32_t alignment,
uint32_t size, const char *dbg, const char *tag)
{
union MTEEC_PARAM p[4];
int ret;
int handle;
char *tagbuff;
KREE_SHAREDMEM_HANDLE shh;
struct KREE_SHAREDMEM_PARAM param;
if ((session == 0) || (mem_handle == NULL) || (size == 0))
return TZ_RESULT_ERROR_BAD_PARAMETERS;
p[0].value.a = alignment;
p[1].value.a = size;
switch (cmd) {
case TZCMD_MEM_SECUREMEM_ALLOC:
case TZCMD_MEM_SECURECM_ALLOC:
ret = KREE_TeeServiceCall(session, cmd,
TZ_ParamTypes3(TZPT_VALUE_INPUT,
TZPT_VALUE_INPUT,
TZPT_VALUE_OUTPUT),
p);
handle = p[2].value.a;
break;
case TZCMD_MEM_SECUREMEM_ALLOC_WITH_TAG:
case TZCMD_MEM_SECURECM_ALLOC_WITH_TAG:
case TZCMD_MEM_SECUREMEM_ZALLOC_WITH_TAG:
case TZCMD_MEM_SECURECM_ZALLOC_WITH_TAG:
if (tag == NULL)
param.size = 1;
else
param.size = strlen(tag)+1;
tagbuff = kzalloc(param.size, GFP_KERNEL);
if (tagbuff == NULL)
return TZ_RESULT_ERROR_OUT_OF_MEMORY;
param.buffer = tagbuff;
ret = KREE_RegisterSharedmem(session, &shh, &param);
if (ret != TZ_RESULT_SUCCESS) {
kfree(tagbuff);
return ret;
}
if (tag != NULL)
memcpy(tagbuff, tag, param.size);
p[2].memref.handle = shh;
p[2].memref.size = param.size;
p[2].memref.offset = 0;
ret = KREE_TeeServiceCall(session, cmd,
TZ_ParamTypes4(TZPT_VALUE_INPUT,
TZPT_VALUE_INPUT,
TZPT_MEMREF_INPUT,
TZPT_VALUE_OUTPUT),
p);
KREE_UnregisterSharedmem(session, shh);
kfree(tagbuff);
handle = p[3].value.a;
break;
default:
return TZ_RESULT_ERROR_BAD_PARAMETERS;
}
if (ret != TZ_RESULT_SUCCESS) {
pr_warn("[kree] %s Error: %d\n", dbg, ret);
return ret;
}
*mem_handle = (KREE_SECUREMEM_HANDLE) handle;
return TZ_RESULT_SUCCESS;
}
static inline int _handleOpFunc(uint32_t cmd, KREE_SESSION_HANDLE session,
uint32_t mem_handle, const char *dbg)
{
union MTEEC_PARAM p[4];
int ret;
if ((session == 0) || (mem_handle == 0))
return TZ_RESULT_ERROR_BAD_PARAMETERS;
p[0].value.a = (uint32_t) mem_handle;
ret = KREE_TeeServiceCall(session, cmd,
TZ_ParamTypes1(TZPT_VALUE_INPUT), p);
if (ret != TZ_RESULT_SUCCESS) {
pr_warn("[kree] %s Error: %d\n", dbg, ret);
return ret;
}
return TZ_RESULT_SUCCESS;
}
static inline int _handleOpFunc_1(uint32_t cmd,
KREE_SESSION_HANDLE session,
uint32_t mem_handle, uint32_t *count,
const char *dbg)
{
union MTEEC_PARAM p[4];
int ret;
if ((session == 0) || (mem_handle == 0) || (count == NULL))
return TZ_RESULT_ERROR_BAD_PARAMETERS;
p[0].value.a = (uint32_t) mem_handle;
ret = KREE_TeeServiceCall(session, cmd,
TZ_ParamTypes2(TZPT_VALUE_INPUT,
TZPT_VALUE_OUTPUT),
p);
if (ret != TZ_RESULT_SUCCESS) {
pr_warn("[kree] %s Error: %d\n", dbg, ret);
*count = 0;
return ret;
}
*count = p[1].value.a;
return TZ_RESULT_SUCCESS;
}
#if !IS_ENABLED(CONFIG_DEVICE_MODULES_OPTEE)
int kree_register_sharedmem(KREE_SESSION_HANDLE session,
KREE_SHAREDMEM_HANDLE *mem_handle,
void *start, uint32_t size, void *map_p,
const char *tag)
{
union MTEEC_PARAM p[4];
int ret;
struct shm_buffer_s shmbuf;
shmbuf.buffer = (unsigned long)start;
shmbuf.size = size;
p[0].mem.buffer = &shmbuf;
p[0].mem.size = sizeof(struct shm_buffer_s);
p[1].mem.buffer = map_p;
if (map_p != NULL)
p[1].mem.size = ((*(uint64_t *)map_p)+1)*sizeof(uint64_t);
else
p[1].mem.size = 0;
p[2].mem.buffer = (void *)tag;
if (tag != NULL)
p[2].mem.size = strlen(tag)+1;
else
p[2].mem.size = 0;
ret = KREE_TeeServiceCall(session, TZCMD_MEM_SHAREDMEM_REG_WITH_TAG,
TZ_ParamTypes4(TZPT_MEM_INPUT,
TZPT_MEM_INPUT,
TZPT_MEM_INPUT,
TZPT_VALUE_OUTPUT),
p);
if (ret != TZ_RESULT_SUCCESS) {
*mem_handle = 0;
return ret;
}
*mem_handle = p[3].value.a;
return TZ_RESULT_SUCCESS;
}
int kree_unregister_sharedmem(KREE_SESSION_HANDLE session,
KREE_SHAREDMEM_HANDLE mem_handle)
{
union MTEEC_PARAM p[4];
int ret;
p[0].value.a = (uint32_t) mem_handle;
ret = KREE_TeeServiceCall(session, TZCMD_MEM_SHAREDMEM_UNREG,
TZ_ParamTypes1(TZPT_VALUE_INPUT), p);
return ret;
}
/* APIs
*/
static int KREE_RegisterSharedmem_Helper(KREE_SESSION_HANDLE session,
KREE_SHAREDMEM_HANDLE *shm_handle,
struct KREE_SHAREDMEM_PARAM *param,
const char *tag)
{
int ret;
if ((session == 0) || (shm_handle == NULL) ||
(param->buffer == NULL) || (param->size == 0))
return TZ_RESULT_ERROR_BAD_PARAMETERS;
/* only for kmalloc */
if ((param->buffer >= (void *)PAGE_OFFSET) &&
(param->buffer < high_memory)) {
ret = kree_register_sharedmem(session, shm_handle,
param->buffer, param->size,
0, /* set 0 for no remap... */
tag);
if (ret != TZ_RESULT_SUCCESS) {
pr_warn("[kree] KREE_RegisterSharedmem Error: %d\n",
ret);
return ret;
}
} else {
pr_debug("[kree] KREE_RegisterSharedmem Error: support kmalloc only!!!\n");
return TZ_RESULT_ERROR_NOT_IMPLEMENTED;
}
return TZ_RESULT_SUCCESS;
}
int KREE_RegisterSharedmem(KREE_SESSION_HANDLE session,
KREE_SHAREDMEM_HANDLE *shm_handle,
struct KREE_SHAREDMEM_PARAM *param)
{
return KREE_RegisterSharedmem_Helper(session, shm_handle, param, NULL);
}
int KREE_RegisterSharedmemWithTag(KREE_SESSION_HANDLE session,
KREE_SHAREDMEM_HANDLE *shm_handle,
struct KREE_SHAREDMEM_PARAM *param,
const char *tag)
{
return KREE_RegisterSharedmem_Helper(session, shm_handle, param, tag);
}
int KREE_UnregisterSharedmem(KREE_SESSION_HANDLE session,
KREE_SHAREDMEM_HANDLE shm_handle)
{
int ret;
if ((session == 0) || (shm_handle == 0))
return TZ_RESULT_ERROR_BAD_PARAMETERS;
ret = kree_unregister_sharedmem(session, shm_handle);
if (ret != TZ_RESULT_SUCCESS) {
pr_warn("[kree] %s Error: %d\n", __func__, ret);
return ret;
}
return TZ_RESULT_SUCCESS;
}
#endif
int KREE_AllocSecuremem(KREE_SESSION_HANDLE session,
KREE_SECUREMEM_HANDLE *mem_handle,
uint32_t alignment, uint32_t size)
{
int ret;
ret =
_allocFunc(TZCMD_MEM_SECUREMEM_ALLOC, session, mem_handle,
alignment, size, __func__, NULL);
return ret;
}
EXPORT_SYMBOL(KREE_AllocSecuremem);
int KREE_AllocSecurememWithTag(KREE_SESSION_HANDLE session,
KREE_SECUREMEM_HANDLE *mem_handle,
uint32_t alignment, uint32_t size,
const char *tag)
{
int ret;
ret =
_allocFunc(TZCMD_MEM_SECUREMEM_ALLOC_WITH_TAG, session, mem_handle,
alignment, size, __func__, tag);
return ret;
}
EXPORT_SYMBOL(KREE_AllocSecurememWithTag);
int KREE_ZallocSecurememWithTag(KREE_SESSION_HANDLE session,
KREE_SECUREMEM_HANDLE *mem_handle,
uint32_t alignment, uint32_t size,
const char *tag)
{
int ret;
ret =
_allocFunc(TZCMD_MEM_SECUREMEM_ZALLOC_WITH_TAG, session, mem_handle,
alignment, size, __func__, tag);
return ret;
}
EXPORT_SYMBOL(KREE_ZallocSecurememWithTag);
int KREE_ReferenceSecuremem(KREE_SESSION_HANDLE session,
KREE_SECUREMEM_HANDLE mem_handle)
{
int ret;
ret =
_handleOpFunc(TZCMD_MEM_SECUREMEM_REF, session, mem_handle,
__func__);
#ifdef DBG_KREE_MEM
pr_debug("%s: handle=0x%x count=0x%x\n", __func__, mem_handle, count);
#endif
return ret;
}
EXPORT_SYMBOL(KREE_ReferenceSecuremem);
int KREE_UnreferenceSecuremem(KREE_SESSION_HANDLE session,
KREE_SECUREMEM_HANDLE mem_handle)
{
int ret;
uint32_t count = 0;
ret =
_handleOpFunc_1(TZCMD_MEM_SECUREMEM_UNREF, session, mem_handle,
&count, __func__);
#ifdef DBG_KREE_MEM
pr_debug("%s: handle=0x%x count=0x%x\n", __func__, mem_handle, count);
#endif
return ret;
}
EXPORT_SYMBOL(KREE_UnreferenceSecuremem);
int KREE_AllocSecurechunkmem(KREE_SESSION_HANDLE session,
KREE_SECUREMEM_HANDLE *cm_handle,
uint32_t alignment,
uint32_t size)
{
int ret;
ret =
_allocFunc(TZCMD_MEM_SECURECM_ALLOC, session, cm_handle,
alignment, size, __func__, NULL);
return ret;
}
EXPORT_SYMBOL(KREE_AllocSecurechunkmem);
int KREE_AllocSecurechunkmemWithTag(KREE_SESSION_HANDLE session,
KREE_SECUREMEM_HANDLE *cm_handle,
uint32_t alignment,
uint32_t size, const char *tag)
{
int ret;
ret =
_allocFunc(TZCMD_MEM_SECURECM_ALLOC_WITH_TAG, session, cm_handle,
alignment, size, __func__, tag);
#if IS_ENABLED(CONFIG_MTEE_CMA_SECURE_MEMORY)
mtee_cma_preallocate_buffer_check(*cm_handle, size, true);
#endif
return ret;
}
EXPORT_SYMBOL(KREE_AllocSecurechunkmemWithTag);
int KREE_ZallocSecurechunkmemWithTag(KREE_SESSION_HANDLE session,
KREE_SECUREMEM_HANDLE *cm_handle,
uint32_t alignment,
uint32_t size, const char *tag)
{
int ret;
ret =
_allocFunc(TZCMD_MEM_SECURECM_ZALLOC_WITH_TAG, session, cm_handle,
alignment, size, __func__, tag);
#if IS_ENABLED(CONFIG_MTEE_CMA_SECURE_MEMORY)
mtee_cma_preallocate_buffer_check(*cm_handle, size, true);
#endif
return ret;
}
EXPORT_SYMBOL(KREE_ZallocSecurechunkmemWithTag);
int KREE_ReferenceSecurechunkmem(KREE_SESSION_HANDLE session,
KREE_SECURECM_HANDLE cm_handle)
{
int ret;
ret =
_handleOpFunc(TZCMD_MEM_SECURECM_REF, session, cm_handle,
__func__);
#ifdef DBG_KREE_MEM
pr_debug("%s: handle=0x%x\n", __func__, cm_handle);
#endif
return ret;
}
EXPORT_SYMBOL(KREE_ReferenceSecurechunkmem);
int KREE_UnreferenceSecurechunkmem(KREE_SESSION_HANDLE session,
KREE_SECURECM_HANDLE cm_handle)
{
int ret;
uint32_t count = 0;
ret =
_handleOpFunc_1(TZCMD_MEM_SECURECM_UNREF, session, cm_handle,
&count, __func__);
#ifdef DBG_KREE_MEM
pr_debug("%s: handle=0x%x count=0x%x\n", __func__, cm_handle, count);
#endif
#if IS_ENABLED(CONFIG_MTEE_CMA_SECURE_MEMORY)
mtee_cma_preallocate_buffer_check(cm_handle, 0, false);
#endif
return ret;
}
EXPORT_SYMBOL(KREE_UnreferenceSecurechunkmem);
int KREE_ReadSecurechunkmem(KREE_SESSION_HANDLE session, uint32_t offset,
uint32_t size, void *buffer)
{
union MTEEC_PARAM p[4];
int ret;
if ((session == 0) || (size == 0))
return TZ_RESULT_ERROR_BAD_PARAMETERS;
p[0].value.a = offset;
p[1].value.a = size;
p[2].mem.buffer = buffer;
p[2].mem.size = size; /* fix me!!!! */
ret = KREE_TeeServiceCall(session, TZCMD_MEM_SECURECM_READ,
TZ_ParamTypes3(TZPT_VALUE_INPUT,
TZPT_VALUE_INPUT,
TZPT_MEM_OUTPUT),
p);
if (ret != TZ_RESULT_SUCCESS) {
pr_warn("[kree] %s Error: %d\n", __func__, ret);
return ret;
}
return TZ_RESULT_SUCCESS;
}
EXPORT_SYMBOL(KREE_ReadSecurechunkmem);
int KREE_WriteSecurechunkmem(KREE_SESSION_HANDLE session, uint32_t offset,
uint32_t size, void *buffer)
{
union MTEEC_PARAM p[4];
int ret;
if ((session == 0) || (size == 0))
return TZ_RESULT_ERROR_BAD_PARAMETERS;
p[0].value.a = offset;
p[1].value.a = size;
p[2].mem.buffer = buffer;
p[2].mem.size = size; /* fix me!!!! */
ret = KREE_TeeServiceCall(session, TZCMD_MEM_SECURECM_WRITE,
TZ_ParamTypes3(TZPT_VALUE_INPUT,
TZPT_VALUE_INPUT,
TZPT_MEM_INPUT),
p);
if (ret != TZ_RESULT_SUCCESS) {
pr_warn("[kree] %s Error: %d\n", __func__, ret);
return ret;
}
return TZ_RESULT_SUCCESS;
}
EXPORT_SYMBOL(KREE_WriteSecurechunkmem);
int KREE_GetSecurechunkReleaseSize(KREE_SESSION_HANDLE session,
uint32_t *size)
{
union MTEEC_PARAM p[4];
int ret;
ret =
KREE_TeeServiceCall(session, TZCMD_MEM_SECURECM_RSIZE,
TZ_ParamTypes1(TZPT_VALUE_OUTPUT), p);
if (ret != TZ_RESULT_SUCCESS) {
pr_warn("[kree] %s Error: %d\n", __func__, ret);
return ret;
}
*size = p[0].value.a;
return TZ_RESULT_SUCCESS;
}
EXPORT_SYMBOL(KREE_GetSecurechunkReleaseSize);
int KREE_GetTEETotalSize(KREE_SESSION_HANDLE session, uint32_t *size)
{
union MTEEC_PARAM p[4];
int ret;
ret = KREE_TeeServiceCall(session, TZCMD_MEM_TOTAL_SIZE,
TZ_ParamTypes1(TZPT_VALUE_OUTPUT), p);
if (ret != TZ_RESULT_SUCCESS) {
pr_warn("[kree] %s Error: %d\n", __func__, ret);
return ret;
}
*size = p[0].value.a;
return TZ_RESULT_SUCCESS;
}
EXPORT_SYMBOL(KREE_GetTEETotalSize);