1419b0af8Sopenharmony_ci/* 2419b0af8Sopenharmony_ci * Copyright (c) 2012-2022 Huawei Technologies Co., Ltd. 3419b0af8Sopenharmony_ci * Description: dynamic Ion memory allocation and free. 4419b0af8Sopenharmony_ci * 5419b0af8Sopenharmony_ci * This software is licensed under the terms of the GNU General Public 6419b0af8Sopenharmony_ci * License version 2, as published by the Free Software Foundation, and 7419b0af8Sopenharmony_ci * may be copied, distributed, and modified under those terms. 8419b0af8Sopenharmony_ci * 9419b0af8Sopenharmony_ci * This program is distributed in the hope that it will be useful, 10419b0af8Sopenharmony_ci * but WITHOUT ANY WARRANTY; without even the implied warranty of 11419b0af8Sopenharmony_ci * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12419b0af8Sopenharmony_ci * GNU General Public License for more details. 13419b0af8Sopenharmony_ci */ 14419b0af8Sopenharmony_ci 15419b0af8Sopenharmony_ci#include "dynamic_ion_mem.h" 16419b0af8Sopenharmony_ci#include <linux/version.h> 17419b0af8Sopenharmony_ci#if LINUX_VERSION_CODE < KERNEL_VERSION(6, 6, 0) 18419b0af8Sopenharmony_ci#include <stdarg.h> 19419b0af8Sopenharmony_ci#else 20419b0af8Sopenharmony_ci#include <linux/stdarg.h> 21419b0af8Sopenharmony_ci#endif 22419b0af8Sopenharmony_ci#include <linux/workqueue.h> 23419b0af8Sopenharmony_ci#include <linux/kthread.h> 24419b0af8Sopenharmony_ci#include <linux/list.h> 25419b0af8Sopenharmony_ci#include <linux/sched.h> 26419b0af8Sopenharmony_ci#include <linux/delay.h> 27419b0af8Sopenharmony_ci#include <linux/mutex.h> 28419b0af8Sopenharmony_ci#include <linux/timer.h> 29419b0af8Sopenharmony_ci#include <linux/kernel.h> 30419b0af8Sopenharmony_ci#include <linux/uaccess.h> 31419b0af8Sopenharmony_ci#include <linux/debugfs.h> 32419b0af8Sopenharmony_ci#include <linux/module.h> 33419b0af8Sopenharmony_ci#include <linux/version.h> 34419b0af8Sopenharmony_ci#ifndef CONFIG_DMABUF_MM 35419b0af8Sopenharmony_ci#include <linux/ion.h> 36419b0af8Sopenharmony_ci#endif 37419b0af8Sopenharmony_ci#include <linux/mm.h> 38419b0af8Sopenharmony_ci#include <linux/cma.h> 39419b0af8Sopenharmony_ci#include <asm/tlbflush.h> 40419b0af8Sopenharmony_ci#include <asm/cacheflush.h> 41419b0af8Sopenharmony_ci#if ((defined CONFIG_ION_MM) || (defined CONFIG_ION_MM_SECSG)) 42419b0af8Sopenharmony_ci#include <linux/ion/mm_ion.h> 43419b0af8Sopenharmony_ci#endif 44419b0af8Sopenharmony_ci#ifdef CONFIG_DMABUF_MM 45419b0af8Sopenharmony_ci#include <linux/dmabuf/mm_dma_heap.h> 46419b0af8Sopenharmony_ci#endif 47419b0af8Sopenharmony_ci#include "tc_ns_log.h" 48419b0af8Sopenharmony_ci#include "tc_ns_client.h" 49419b0af8Sopenharmony_ci#include "smc_smp.h" 50419b0af8Sopenharmony_ci#include "gp_ops.h" 51419b0af8Sopenharmony_ci#include "teek_client_constants.h" 52419b0af8Sopenharmony_ci#include "mailbox_mempool.h" 53419b0af8Sopenharmony_ci#include "dynamic_ion_uuid.h" 54419b0af8Sopenharmony_ci 55419b0af8Sopenharmony_cistatic DEFINE_MUTEX(dynamic_mem_lock); 56419b0af8Sopenharmony_cistruct dynamic_mem_list { 57419b0af8Sopenharmony_ci struct list_head list; 58419b0af8Sopenharmony_ci}; 59419b0af8Sopenharmony_ci 60419b0af8Sopenharmony_cistatic const struct dynamic_mem_config g_dyn_mem_config[] = { 61419b0af8Sopenharmony_ci #ifdef DEF_ENG 62419b0af8Sopenharmony_ci {TEE_SERVICE_UT, SEC_EID}, 63419b0af8Sopenharmony_ci {TEE_SERVICE_TEST_DYNION, SEC_AI_ION}, 64419b0af8Sopenharmony_ci #endif 65419b0af8Sopenharmony_ci {TEE_SECIDENTIFICATION1, SEC_EID}, 66419b0af8Sopenharmony_ci {TEE_SECIDENTIFICATION3, SEC_EID}, 67419b0af8Sopenharmony_ci {TEE_SERVICE_AI, SEC_AI_ION}, 68419b0af8Sopenharmony_ci {TEE_SERVICE_AI_TINY, SEC_AI_ION}, 69419b0af8Sopenharmony_ci {TEE_SERVICE_VCODEC, SEC_DRM_TEE}, 70419b0af8Sopenharmony_ci}; 71419b0af8Sopenharmony_ci 72419b0af8Sopenharmony_cistatic struct dynamic_mem_list g_dynamic_mem_list; 73419b0af8Sopenharmony_cistatic const uint32_t g_dyn_mem_config_num = ARRAY_SIZE(g_dyn_mem_config); 74419b0af8Sopenharmony_ci 75419b0af8Sopenharmony_cistatic int release_ion_srv(const struct tc_uuid *uuid) 76419b0af8Sopenharmony_ci{ 77419b0af8Sopenharmony_ci struct tc_ns_smc_cmd smc_cmd = {{0}, 0}; 78419b0af8Sopenharmony_ci 79419b0af8Sopenharmony_ci smc_cmd.err_origin = TEEC_ORIGIN_COMMS; 80419b0af8Sopenharmony_ci smc_cmd.cmd_type = CMD_TYPE_GLOBAL; 81419b0af8Sopenharmony_ci smc_cmd.cmd_id = GLOBAL_CMD_ID_RELEASE_ION_SRV; 82419b0af8Sopenharmony_ci if (memcpy_s(&smc_cmd.uuid, sizeof(smc_cmd.uuid), uuid, sizeof(*uuid))) { 83419b0af8Sopenharmony_ci tloge("copy uuid failed\n"); 84419b0af8Sopenharmony_ci return -ENOMEM; 85419b0af8Sopenharmony_ci } 86419b0af8Sopenharmony_ci 87419b0af8Sopenharmony_ci if (tc_ns_smc(&smc_cmd)) { 88419b0af8Sopenharmony_ci tloge("send release ion srv cmd failed\n"); 89419b0af8Sopenharmony_ci return -EPERM; 90419b0af8Sopenharmony_ci } 91419b0af8Sopenharmony_ci return 0; 92419b0af8Sopenharmony_ci} 93419b0af8Sopenharmony_ci 94419b0af8Sopenharmony_ci 95419b0af8Sopenharmony_cistatic int get_ion_sglist(struct dynamic_mem_item *mem_item) 96419b0af8Sopenharmony_ci{ 97419b0af8Sopenharmony_ci struct sglist *tmp_sglist = NULL; 98419b0af8Sopenharmony_ci struct scatterlist *sg = NULL; 99419b0af8Sopenharmony_ci struct page *page = NULL; 100419b0af8Sopenharmony_ci uint32_t sglist_size; 101419b0af8Sopenharmony_ci uint32_t i = 0; 102419b0af8Sopenharmony_ci struct sg_table *ion_sg_table = mem_item->memory.dyn_sg_table; 103419b0af8Sopenharmony_ci 104419b0af8Sopenharmony_ci if (!ion_sg_table) 105419b0af8Sopenharmony_ci return -EINVAL; 106419b0af8Sopenharmony_ci 107419b0af8Sopenharmony_ci if (ion_sg_table->nents <= 0 || ion_sg_table->nents > MAX_ION_NENTS) 108419b0af8Sopenharmony_ci return -EINVAL; 109419b0af8Sopenharmony_ci 110419b0af8Sopenharmony_ci for_each_sg(ion_sg_table->sgl, sg, ion_sg_table->nents, i) { 111419b0af8Sopenharmony_ci if (!sg) { 112419b0af8Sopenharmony_ci tloge("an error sg when get ion sglist\n"); 113419b0af8Sopenharmony_ci return -EINVAL; 114419b0af8Sopenharmony_ci } 115419b0af8Sopenharmony_ci } 116419b0af8Sopenharmony_ci 117419b0af8Sopenharmony_ci sglist_size = sizeof(struct ion_page_info) * ion_sg_table->nents + sizeof(*tmp_sglist); 118419b0af8Sopenharmony_ci tmp_sglist = (struct sglist *)mailbox_alloc(sglist_size, MB_FLAG_ZERO); 119419b0af8Sopenharmony_ci if (!tmp_sglist) { 120419b0af8Sopenharmony_ci tloge("mailbox alloc failed\n"); 121419b0af8Sopenharmony_ci return -ENOMEM; 122419b0af8Sopenharmony_ci } 123419b0af8Sopenharmony_ci 124419b0af8Sopenharmony_ci tmp_sglist->sglist_size = (uint64_t)sglist_size; 125419b0af8Sopenharmony_ci tmp_sglist->ion_size = (uint64_t)mem_item->size; 126419b0af8Sopenharmony_ci tmp_sglist->info_length = (uint64_t)ion_sg_table->nents; 127419b0af8Sopenharmony_ci for_each_sg(ion_sg_table->sgl, sg, ion_sg_table->nents, i) { 128419b0af8Sopenharmony_ci page = sg_page(sg); 129419b0af8Sopenharmony_ci tmp_sglist->page_info[i].phys_addr = page_to_phys(page); 130419b0af8Sopenharmony_ci tmp_sglist->page_info[i].npages = sg->length / PAGE_SIZE; 131419b0af8Sopenharmony_ci } 132419b0af8Sopenharmony_ci mem_item->memory.ion_phys_addr = mailbox_virt_to_phys((uintptr_t)(void *)tmp_sglist); 133419b0af8Sopenharmony_ci mem_item->memory.len = sglist_size; 134419b0af8Sopenharmony_ci return 0; 135419b0af8Sopenharmony_ci} 136419b0af8Sopenharmony_ci 137419b0af8Sopenharmony_cistatic int send_dyn_ion_cmd(struct dynamic_mem_item *mem_item, unsigned int cmd_id, int32_t *ret_origin) 138419b0af8Sopenharmony_ci{ 139419b0af8Sopenharmony_ci struct tc_ns_smc_cmd smc_cmd = {{0}, 0}; 140419b0af8Sopenharmony_ci int ret; 141419b0af8Sopenharmony_ci struct mb_cmd_pack *mb_pack = NULL; 142419b0af8Sopenharmony_ci 143419b0af8Sopenharmony_ci if (!mem_item) { 144419b0af8Sopenharmony_ci tloge("mem_item is null\n"); 145419b0af8Sopenharmony_ci return -EINVAL; 146419b0af8Sopenharmony_ci } 147419b0af8Sopenharmony_ci 148419b0af8Sopenharmony_ci ret = get_ion_sglist(mem_item); 149419b0af8Sopenharmony_ci if (ret != 0) 150419b0af8Sopenharmony_ci return ret; 151419b0af8Sopenharmony_ci 152419b0af8Sopenharmony_ci mb_pack = mailbox_alloc_cmd_pack(); 153419b0af8Sopenharmony_ci if (!mb_pack) { 154419b0af8Sopenharmony_ci mailbox_free(phys_to_virt(mem_item->memory.ion_phys_addr)); 155419b0af8Sopenharmony_ci tloge("alloc cmd pack failed\n"); 156419b0af8Sopenharmony_ci return -ENOMEM; 157419b0af8Sopenharmony_ci } 158419b0af8Sopenharmony_ci smc_cmd.cmd_type = CMD_TYPE_GLOBAL; 159419b0af8Sopenharmony_ci smc_cmd.cmd_id = cmd_id; 160419b0af8Sopenharmony_ci smc_cmd.err_origin = TEEC_ORIGIN_COMMS; 161419b0af8Sopenharmony_ci mb_pack->operation.paramtypes = teec_param_types( 162419b0af8Sopenharmony_ci TEE_PARAM_TYPE_ION_SGLIST_INPUT, 163419b0af8Sopenharmony_ci TEE_PARAM_TYPE_VALUE_INPUT, 164419b0af8Sopenharmony_ci TEE_PARAM_TYPE_VALUE_INPUT, 165419b0af8Sopenharmony_ci TEE_PARAM_TYPE_NONE); 166419b0af8Sopenharmony_ci 167419b0af8Sopenharmony_ci mb_pack->operation.params[0].memref.size = (uint32_t)mem_item->memory.len; 168419b0af8Sopenharmony_ci mb_pack->operation.params[0].memref.buffer = 169419b0af8Sopenharmony_ci (uint32_t)(mem_item->memory.ion_phys_addr & 0xFFFFFFFF); 170419b0af8Sopenharmony_ci mb_pack->operation.buffer_h_addr[0] = 171419b0af8Sopenharmony_ci (uint64_t)(mem_item->memory.ion_phys_addr) >> ADDR_TRANS_NUM; 172419b0af8Sopenharmony_ci mb_pack->operation.params[1].value.a = (uint32_t)mem_item->size; 173419b0af8Sopenharmony_ci mb_pack->operation.params[2].value.a = mem_item->configid; 174419b0af8Sopenharmony_ci smc_cmd.operation_phys = (unsigned int)mailbox_virt_to_phys((uintptr_t)&mb_pack->operation); 175419b0af8Sopenharmony_ci smc_cmd.operation_h_phys = (uint64_t)mailbox_virt_to_phys((uintptr_t)&mb_pack->operation) >> ADDR_TRANS_NUM; 176419b0af8Sopenharmony_ci 177419b0af8Sopenharmony_ci if (tc_ns_smc(&smc_cmd)) { 178419b0af8Sopenharmony_ci if (ret_origin) 179419b0af8Sopenharmony_ci *ret_origin = smc_cmd.err_origin; 180419b0af8Sopenharmony_ci ret = -EPERM; 181419b0af8Sopenharmony_ci tlogd("send loadapp ion failed\n"); 182419b0af8Sopenharmony_ci } 183419b0af8Sopenharmony_ci mailbox_free(phys_to_virt(mem_item->memory.ion_phys_addr)); 184419b0af8Sopenharmony_ci mailbox_free(mb_pack); 185419b0af8Sopenharmony_ci return ret; 186419b0af8Sopenharmony_ci} 187419b0af8Sopenharmony_ci 188419b0af8Sopenharmony_cistatic struct dynamic_mem_item *find_memitem_by_configid_locked(uint32_t configid) 189419b0af8Sopenharmony_ci{ 190419b0af8Sopenharmony_ci struct dynamic_mem_item *item = NULL; 191419b0af8Sopenharmony_ci list_for_each_entry(item, &g_dynamic_mem_list.list, head) { 192419b0af8Sopenharmony_ci if (item->configid == configid) 193419b0af8Sopenharmony_ci return item; 194419b0af8Sopenharmony_ci } 195419b0af8Sopenharmony_ci return NULL; 196419b0af8Sopenharmony_ci} 197419b0af8Sopenharmony_ci 198419b0af8Sopenharmony_cistatic struct dynamic_mem_item *find_memitem_by_uuid_locked(const struct tc_uuid *uuid) 199419b0af8Sopenharmony_ci{ 200419b0af8Sopenharmony_ci struct dynamic_mem_item *item = NULL; 201419b0af8Sopenharmony_ci list_for_each_entry(item, &g_dynamic_mem_list.list, head) { 202419b0af8Sopenharmony_ci if (!memcmp(&item->uuid, uuid, sizeof(*uuid))) 203419b0af8Sopenharmony_ci return item; 204419b0af8Sopenharmony_ci } 205419b0af8Sopenharmony_ci return NULL; 206419b0af8Sopenharmony_ci} 207419b0af8Sopenharmony_ci 208419b0af8Sopenharmony_ci#define BLOCK_64KB_SIZE (64 * 1024) /* 64 */ 209419b0af8Sopenharmony_ci#define BLOCK_64KB_MASK 0xFFFFFFFFFFFF0000 210419b0af8Sopenharmony_ci/* size should be aligned with 64KB */ 211419b0af8Sopenharmony_ci#define BLOCK_64KB_SIZE_MASK (BLOCK_64KB_SIZE -1) 212419b0af8Sopenharmony_cistatic int proc_alloc_dyn_mem(struct dynamic_mem_item *mem_item) 213419b0af8Sopenharmony_ci{ 214419b0af8Sopenharmony_ci struct sg_table *ion_sg_table = NULL; 215419b0af8Sopenharmony_ci 216419b0af8Sopenharmony_ci if (mem_item->size + BLOCK_64KB_SIZE_MASK < mem_item->size) { 217419b0af8Sopenharmony_ci tloge("ion size is error, size = %x\n", mem_item->size); 218419b0af8Sopenharmony_ci return -EINVAL; 219419b0af8Sopenharmony_ci } 220419b0af8Sopenharmony_ci mem_item->memory.len = (mem_item ->size + BLOCK_64KB_SIZE_MASK) & BLOCK_64KB_MASK; 221419b0af8Sopenharmony_ci 222419b0af8Sopenharmony_ci ion_sg_table = mm_secmem_alloc(mem_item->addr_sec_region, 223419b0af8Sopenharmony_ci mem_item->memory.len); 224419b0af8Sopenharmony_ci if (!ion_sg_table) { 225419b0af8Sopenharmony_ci tloge("failed to get ion page, configid = %d\n", 226419b0af8Sopenharmony_ci mem_item->configid); 227419b0af8Sopenharmony_ci return -ENOMEM; 228419b0af8Sopenharmony_ci } 229419b0af8Sopenharmony_ci mem_item->memory.dyn_sg_table = ion_sg_table; 230419b0af8Sopenharmony_ci return 0; 231419b0af8Sopenharmony_ci} 232419b0af8Sopenharmony_ci 233419b0af8Sopenharmony_cistatic void proc_free_dyn_mem(struct dynamic_mem_item *mem_item) 234419b0af8Sopenharmony_ci{ 235419b0af8Sopenharmony_ci if (!mem_item->memory.dyn_sg_table) { 236419b0af8Sopenharmony_ci tloge("ion_phys_addr is NULL\n"); 237419b0af8Sopenharmony_ci return; 238419b0af8Sopenharmony_ci } 239419b0af8Sopenharmony_ci mm_secmem_free(mem_item->ddr_sec_region, 240419b0af8Sopenharmony_ci mem_item->memory.dyn_sg_table); 241419b0af8Sopenharmony_ci mem_item->memory.dyn_sg_table = NULL; 242419b0af8Sopenharmony_ci return; 243419b0af8Sopenharmony_ci} 244419b0af8Sopenharmony_ci 245419b0af8Sopenharmony_ciint init_dynamic_mem(void) 246419b0af8Sopenharmony_ci{ 247419b0af8Sopenharmony_ci INIT_LIST_HEAD(&(g_dynamic_mem_list.list)); 248419b0af8Sopenharmony_ci return 0; 249419b0af8Sopenharmony_ci} 250419b0af8Sopenharmony_ci 251419b0af8Sopenharmony_cistatic int32_t find_ddr_sec_region_by_uuid(const struct tc_uuid *uuid, 252419b0af8Sopenharmony_ci uint32_t *ddr_sec_region) 253419b0af8Sopenharmony_ci{ 254419b0af8Sopenharmony_ci uint32_t i; 255419b0af8Sopenharmony_ci for (i = 0; i < g_dyn_mem_config_num; i++) { 256419b0af8Sopenharmony_ci if (!memcmp(&(g_dyn_mem_config[i].uuid), uuid, 257419b0af8Sopenharmony_ci sizeof(*uuid))) { 258419b0af8Sopenharmony_ci *ddr_sec_region = g_dyn_mem_config[i].ddr_sec_region; 259419b0af8Sopenharmony_ci return 0; 260419b0af8Sopenharmony_ci } 261419b0af8Sopenharmony_ci } 262419b0af8Sopenharmony_ci return -EINVAL; 263419b0af8Sopenharmony_ci} 264419b0af8Sopenharmony_ci 265419b0af8Sopenharmony_cistatic struct dynamic_mem_item *alloc_dyn_mem_item(uint32_t configid, 266419b0af8Sopenharmony_ci uint32_t cafd, const struct tc_uuid *uuid, uint32_t size) 267419b0af8Sopenharmony_ci{ 268419b0af8Sopenharmony_ci uint32_t ddr_sec_region; 269419b0af8Sopenharmony_ci struct dynamic_mem_item *mem_item = NULL; 270419b0af8Sopenharmony_ci int32_t result; 271419b0af8Sopenharmony_ci 272419b0af8Sopenharmony_ci result = find_ddr_sec_region_by_uuid(uuid, &ddr_sec_region); 273419b0af8Sopenharmony_ci if (result != 0) { 274419b0af8Sopenharmony_ci tloge("find ddr sec region failed\n"); 275419b0af8Sopenharmony_ci return NULL; 276419b0af8Sopenharmony_ci } 277419b0af8Sopenharmony_ci 278419b0af8Sopenharmony_ci mem_item = kzalloc(sizeof(*mem_item), GFP_KERNEL); 279419b0af8Sopenharmony_ci if (ZERO_OR_NULL_PTR((unsigned long)(uintptr_t)mem_item)) { 280419b0af8Sopenharmony_ci tloge("alloc mem item failed\n"); 281419b0af8Sopenharmony_ci return NULL; 282419b0af8Sopenharmony_ci } 283419b0af8Sopenharmony_ci 284419b0af8Sopenharmony_ci mem_item->ddr_sec_region = ddr_sec_region; 285419b0af8Sopenharmony_ci mem_item->configid = configid; 286419b0af8Sopenharmony_ci mem_item->size = size; 287419b0af8Sopenharmony_ci mem_item->cafd = cafd; 288419b0af8Sopenharmony_ci result = memcpy_s(&mem_item->uuid, sizeof(mem_item->uuid), uuid, 289419b0af8Sopenharmony_ci sizeof(*uuid)); 290419b0af8Sopenharmony_ci if(result != EOK) { 291419b0af8Sopenharmony_ci tloge("memcpy uuid failed\n"); 292419b0af8Sopenharmony_ci kfree(mem_item); 293419b0af8Sopenharmony_ci return NULL; 294419b0af8Sopenharmony_ci } 295419b0af8Sopenharmony_ci return mem_item; 296419b0af8Sopenharmony_ci} 297419b0af8Sopenharmony_ci 298419b0af8Sopenharmony_ci 299419b0af8Sopenharmony_cistatic int trans_configid2memid(uint32_t configid, uint32_t cafd, 300419b0af8Sopenharmony_ci const struct tc_uuid *uuid, uint32_t size, int32_t *ret_origin) 301419b0af8Sopenharmony_ci{ 302419b0af8Sopenharmony_ci int result; 303419b0af8Sopenharmony_ci 304419b0af8Sopenharmony_ci if (!uuid) 305419b0af8Sopenharmony_ci return -EINVAL; 306419b0af8Sopenharmony_ci mutex_lock(&dynamic_mem_lock); 307419b0af8Sopenharmony_ci do { 308419b0af8Sopenharmony_ci struct dynamic_mem_item *mem_item = 309419b0af8Sopenharmony_ci find_memitem_by_configid_locked(configid); 310419b0af8Sopenharmony_ci if (mem_item) { 311419b0af8Sopenharmony_ci result = -EINVAL; 312419b0af8Sopenharmony_ci break; 313419b0af8Sopenharmony_ci } 314419b0af8Sopenharmony_ci 315419b0af8Sopenharmony_ci mem_item = alloc_dyn_mem_item(configid, cafd, uuid, size); 316419b0af8Sopenharmony_ci if (!mem_item) { 317419b0af8Sopenharmony_ci tloge("alloc dyn mem item failed\n"); 318419b0af8Sopenharmony_ci result = -ENOMEM; 319419b0af8Sopenharmony_ci break; 320419b0af8Sopenharmony_ci } 321419b0af8Sopenharmony_ci 322419b0af8Sopenharmony_ci result = proc_alloc_dyn_mem(mem_item); 323419b0af8Sopenharmony_ci if (result != 0) { 324419b0af8Sopenharmony_ci tloge("alloc dyn mem failed , ret = %d\n", result); 325419b0af8Sopenharmony_ci kfree(mem_item); 326419b0af8Sopenharmony_ci break; 327419b0af8Sopenharmony_ci } 328419b0af8Sopenharmony_ci /* register to tee */ 329419b0af8Sopenharmony_ci result = send_dyn_ion_cmd(mem_item, GLOBAL_CMD_ID_ADD_DYNAMIC_ION, ret_origin); 330419b0af8Sopenharmony_ci if (result != 0) { 331419b0af8Sopenharmony_ci tloge("register to tee failed, result = %d\n", result); 332419b0af8Sopenharmony_ci proc_free_dyn_mem(mem_item); 333419b0af8Sopenharmony_ci kfree(mem_item); 334419b0af8Sopenharmony_ci break; 335419b0af8Sopenharmony_ci } 336419b0af8Sopenharmony_ci list_add_tail(&mem_item->head, &g_dynamic_mem_list.list); 337419b0af8Sopenharmony_ci tloge("log import:alloc ion configid=%d\n", 338419b0af8Sopenharmony_ci mem_item->configid); 339419b0af8Sopenharmony_ci } while (0); 340419b0af8Sopenharmony_ci 341419b0af8Sopenharmony_ci mutex_unlock(&dynamic_mem_lock); 342419b0af8Sopenharmony_ci return result; 343419b0af8Sopenharmony_ci} 344419b0af8Sopenharmony_ci 345419b0af8Sopenharmony_cistatic void release_configid_mem_locked(uint32_t configid) 346419b0af8Sopenharmony_ci{ 347419b0af8Sopenharmony_ci int result; 348419b0af8Sopenharmony_ci /* if config id is memid map, and can reuse */ 349419b0af8Sopenharmony_ci do { 350419b0af8Sopenharmony_ci struct dynamic_mem_item *mem_item = 351419b0af8Sopenharmony_ci find_memitem_by_configid_locked(configid); 352419b0af8Sopenharmony_ci if (!mem_item) { 353419b0af8Sopenharmony_ci tloge("fail to find memitem by configid\n"); 354419b0af8Sopenharmony_ci break; 355419b0af8Sopenharmony_ci } 356419b0af8Sopenharmony_ci 357419b0af8Sopenharmony_ci result = send_dyn_ion_cmd(mem_item, GLOBAL_CMD_ID_DEL_DYNAMIC_ION, NULL); 358419b0af8Sopenharmony_ci if (result != 0) { 359419b0af8Sopenharmony_ci tloge("unregister_from_tee configid=%d, result =%d\n", 360419b0af8Sopenharmony_ci mem_item->configid, result); 361419b0af8Sopenharmony_ci break; 362419b0af8Sopenharmony_ci } 363419b0af8Sopenharmony_ci proc_free_dyn_mem(mem_item); 364419b0af8Sopenharmony_ci list_del(&mem_item->head); 365419b0af8Sopenharmony_ci kfree(mem_item); 366419b0af8Sopenharmony_ci tloge("log import: free ion\n"); 367419b0af8Sopenharmony_ci } while (0); 368419b0af8Sopenharmony_ci 369419b0af8Sopenharmony_ci return; 370419b0af8Sopenharmony_ci} 371419b0af8Sopenharmony_ci 372419b0af8Sopenharmony_ci 373419b0af8Sopenharmony_ciint load_app_use_configid(uint32_t configid, uint32_t cafd, 374419b0af8Sopenharmony_ci const struct tc_uuid *uuid, uint32_t size, int32_t *ret_origin) 375419b0af8Sopenharmony_ci{ 376419b0af8Sopenharmony_ci int result; 377419b0af8Sopenharmony_ci 378419b0af8Sopenharmony_ci if (!uuid) 379419b0af8Sopenharmony_ci return -EINVAL; 380419b0af8Sopenharmony_ci 381419b0af8Sopenharmony_ci result = trans_configid2memid(configid, cafd, uuid, size, ret_origin); 382419b0af8Sopenharmony_ci if (result != 0) { 383419b0af8Sopenharmony_ci tloge("trans_configid2memid failed ret = %d\n", result); 384419b0af8Sopenharmony_ci if (release_ion_srv(uuid) != 0) 385419b0af8Sopenharmony_ci tloge("release ion srv failed\n"); 386419b0af8Sopenharmony_ci } 387419b0af8Sopenharmony_ci return result; 388419b0af8Sopenharmony_ci} 389419b0af8Sopenharmony_ci 390419b0af8Sopenharmony_ci 391419b0af8Sopenharmony_civoid kill_ion_by_uuid(const struct tc_uuid *uuid) 392419b0af8Sopenharmony_ci{ 393419b0af8Sopenharmony_ci if (!uuid) { 394419b0af8Sopenharmony_ci tloge("uuid is null\n"); 395419b0af8Sopenharmony_ci return; 396419b0af8Sopenharmony_ci } 397419b0af8Sopenharmony_ci mutex_lock(&dynamic_mem_lock); 398419b0af8Sopenharmony_ci do { 399419b0af8Sopenharmony_ci struct dynamic_mem_item *mem_item = 400419b0af8Sopenharmony_ci find_memitem_by_uuid_locked(uuid); 401419b0af8Sopenharmony_ci if (!mem_item) 402419b0af8Sopenharmony_ci break; 403419b0af8Sopenharmony_ci tlogd("kill ION by UUID\n"); 404419b0af8Sopenharmony_ci release_configid_mem_locked(mem_item->configid); 405419b0af8Sopenharmony_ci } while (0); 406419b0af8Sopenharmony_ci mutex_unlock(&dynamic_mem_lock); 407419b0af8Sopenharmony_ci} 408419b0af8Sopenharmony_ci 409419b0af8Sopenharmony_civoid kill_ion_by_cafd(unsigned int cafd) 410419b0af8Sopenharmony_ci{ 411419b0af8Sopenharmony_ci struct dynamic_mem_item *item = NULL; 412419b0af8Sopenharmony_ci struct dynamic_mem_item *temp = NULL; 413419b0af8Sopenharmony_ci tlogd("kill_ion_by_cafd:\n"); 414419b0af8Sopenharmony_ci mutex_lock(&dynamic_mem_lock); 415419b0af8Sopenharmony_ci list_for_each_entry_safe(item, temp, &g_dynamic_mem_list.list, head) { 416419b0af8Sopenharmony_ci if (item->cafd == cafd) 417419b0af8Sopenharmony_ci release_configid_mem_locked(item->configid); 418419b0af8Sopenharmony_ci } 419419b0af8Sopenharmony_ci mutex_unlock(&dynamic_mem_lock); 420419b0af8Sopenharmony_ci} 421419b0af8Sopenharmony_ci 422419b0af8Sopenharmony_ciint load_image_for_ion(const struct load_img_params *params, int32_t *ret_origin) 423419b0af8Sopenharmony_ci{ 424419b0af8Sopenharmony_ci int ret = 0; 425419b0af8Sopenharmony_ci 426419b0af8Sopenharmony_ci if (!params) 427419b0af8Sopenharmony_ci return -EFAULT; 428419b0af8Sopenharmony_ci /* check need to add ionmem */ 429419b0af8Sopenharmony_ci uint32_t configid = params->mb_pack->operation.params[1].value.a; 430419b0af8Sopenharmony_ci uint32_t ion_size = params->mb_pack->operation.params[1].value.b; 431419b0af8Sopenharmony_ci int32_t check_result = (configid != 0 && ion_size != 0); 432419b0af8Sopenharmony_ci 433419b0af8Sopenharmony_ci tloge("check load result=%d, cfgid=%d, ion_size=%d, uuid=%x\n", 434419b0af8Sopenharmony_ci check_result, configid, ion_size, params->uuid_return->time_low); 435419b0af8Sopenharmony_ci if (check_result) { 436419b0af8Sopenharmony_ci ret = load_app_use_configid(configid, params->dev_file->dev_file_id, 437419b0af8Sopenharmony_ci params->uuid_return, ion_size, ret_origin); 438419b0af8Sopenharmony_ci if (ret != 0) { 439419b0af8Sopenharmony_ci tloge("load app use configid failed ret=%d\n", ret); 440419b0af8Sopenharmony_ci return -EFAULT; 441419b0af8Sopenharmony_ci } 442419b0af8Sopenharmony_ci } 443419b0af8Sopenharmony_ci return ret; 444419b0af8Sopenharmony_ci} 445419b0af8Sopenharmony_ci 446419b0af8Sopenharmony_cibool is_ion_param(uint32_t param_type) 447419b0af8Sopenharmony_ci{ 448419b0af8Sopenharmony_ci if (param_type == TEEC_ION_INPUT || 449419b0af8Sopenharmony_ci param_type == TEEC_ION_SGLIST_INPUT) 450419b0af8Sopenharmony_ci return true; 451419b0af8Sopenharmony_ci return false; 452419b0af8Sopenharmony_ci} 453419b0af8Sopenharmony_ci 454419b0af8Sopenharmony_cistatic void fill_sg_list(struct sg_table *ion_table, 455419b0af8Sopenharmony_ci uint32_t ion_list_num, struct sglist *tmp_sglist) 456419b0af8Sopenharmony_ci{ 457419b0af8Sopenharmony_ci uint32_t i; 458419b0af8Sopenharmony_ci struct page *page = NULL; 459419b0af8Sopenharmony_ci struct scatterlist *sg = NULL; 460419b0af8Sopenharmony_ci 461419b0af8Sopenharmony_ci for_each_sg(ion_table->sgl, sg, ion_list_num, i) { 462419b0af8Sopenharmony_ci page = sg_page(sg); 463419b0af8Sopenharmony_ci tmp_sglist->page_info[i].phys_addr = page_to_phys(page); 464419b0af8Sopenharmony_ci tmp_sglist->page_info[i].npages = sg->length / PAGE_SIZE; 465419b0af8Sopenharmony_ci } 466419b0af8Sopenharmony_ci} 467419b0af8Sopenharmony_ci 468419b0af8Sopenharmony_cistatic int check_sg_list(const struct sg_table *ion_table, uint32_t ion_list_num) 469419b0af8Sopenharmony_ci{ 470419b0af8Sopenharmony_ci struct scatterlist *sg = NULL; 471419b0af8Sopenharmony_ci uint32_t i; 472419b0af8Sopenharmony_ci for_each_sg(ion_table->sgl, sg, ion_list_num, i) { 473419b0af8Sopenharmony_ci if (!sg) { 474419b0af8Sopenharmony_ci tloge("an error sg when get ion sglist \n"); 475419b0af8Sopenharmony_ci return -EFAULT; 476419b0af8Sopenharmony_ci } 477419b0af8Sopenharmony_ci } 478419b0af8Sopenharmony_ci return 0; 479419b0af8Sopenharmony_ci} 480419b0af8Sopenharmony_ci 481419b0af8Sopenharmony_cistatic int get_ion_sg_list_from_fd(uint32_t ion_shared_fd, 482419b0af8Sopenharmony_ci uint32_t ion_alloc_size, phys_addr_t *sglist_table, 483419b0af8Sopenharmony_ci size_t *ion_sglist_size) 484419b0af8Sopenharmony_ci{ 485419b0af8Sopenharmony_ci struct sg_table *ion_table = NULL; 486419b0af8Sopenharmony_ci struct sglist *tmp_sglist = NULL; 487419b0af8Sopenharmony_ci uint64_t ion_id = 0; 488419b0af8Sopenharmony_ci enum SEC_SVC ion_type = 0; 489419b0af8Sopenharmony_ci uint32_t ion_list_num = 0; 490419b0af8Sopenharmony_ci uint32_t sglist_size; 491419b0af8Sopenharmony_ci#ifdef CONFIG_DMABUF_MM 492419b0af8Sopenharmony_ci if (mm_dma_heap_secmem_get_buffer(ion_shared_fd, &ion_table, &ion_id, &ion_type)) { 493419b0af8Sopenharmony_ci#else 494419b0af8Sopenharmony_ci if (secmem_get_buffer(ion_shared_fd, &ion_table, &ion_id, &ion_type)) { 495419b0af8Sopenharmony_ci#endif 496419b0af8Sopenharmony_ci tloge("get ion table failed. \n"); 497419b0af8Sopenharmony_ci return -EFAULT; 498419b0af8Sopenharmony_ci } 499419b0af8Sopenharmony_ci 500419b0af8Sopenharmony_ci if (ion_type != SEC_DRM_TEE) { 501419b0af8Sopenharmony_ci if (ion_table->nents <= 0 || ion_table->nents > MAX_ION_NENTS) 502419b0af8Sopenharmony_ci return -EFAULT; 503419b0af8Sopenharmony_ci ion_list_num = (uint32_t)(ion_table->nents & INT_MAX); 504419b0af8Sopenharmony_ci if (check_sg_list(ion_table, ion_list_num) != 0) 505419b0af8Sopenharmony_ci return -EFAULT; 506419b0af8Sopenharmony_ci } 507419b0af8Sopenharmony_ci /* ion_list_num is less than 1024, so sglist_size won't flow */ 508419b0af8Sopenharmony_ci sglist_size = sizeof(struct ion_page_info) * ion_list_num + sizeof(*tmp_sglist); 509419b0af8Sopenharmony_ci tmp_sglist = (struct sglist *)mailbox_alloc(sglist_size, MB_FLAG_ZERO); 510419b0af8Sopenharmony_ci if (!tmp_sglist) { 511419b0af8Sopenharmony_ci tloge("sglist mem alloc failed\n"); 512419b0af8Sopenharmony_ci return -ENOMEM; 513419b0af8Sopenharmony_ci } 514419b0af8Sopenharmony_ci tmp_sglist->sglist_size = (uint64_t)sglist_size; 515419b0af8Sopenharmony_ci tmp_sglist->ion_size = (uint64_t)ion_alloc_size; 516419b0af8Sopenharmony_ci tmp_sglist->info_length = (uint64_t)ion_list_num; 517419b0af8Sopenharmony_ci if (ion_type != SEC_DRM_TEE) 518419b0af8Sopenharmony_ci fill_sg_list(ion_table, ion_list_num, tmp_sglist); 519419b0af8Sopenharmony_ci else 520419b0af8Sopenharmony_ci tmp_sglist->ion_id = ion_id; 521419b0af8Sopenharmony_ci 522419b0af8Sopenharmony_ci *sglist_table = mailbox_virt_to_phys((uintptr_t)tmp_sglist); 523419b0af8Sopenharmony_ci *ion_sglist_size = sglist_size; 524419b0af8Sopenharmony_ci return 0; 525419b0af8Sopenharmony_ci} 526419b0af8Sopenharmony_ci 527419b0af8Sopenharmony_ciint alloc_for_ion_sglist(const struct tc_call_params *call_params, 528419b0af8Sopenharmony_ci struct tc_op_params *op_params, uint8_t kernel_params, 529419b0af8Sopenharmony_ci uint32_t param_type, unsigned int index) 530419b0af8Sopenharmony_ci{ 531419b0af8Sopenharmony_ci struct tc_ns_operation *operation = NULL; 532419b0af8Sopenharmony_ci size_t ion_sglist_size = 0; 533419b0af8Sopenharmony_ci phys_addr_t ion_sglist_addr = 0x0; 534419b0af8Sopenharmony_ci union tc_ns_client_param *client_param = NULL; 535419b0af8Sopenharmony_ci unsigned int ion_shared_fd = 0; 536419b0af8Sopenharmony_ci unsigned int ion_alloc_size; 537419b0af8Sopenharmony_ci uint64_t a_addr, b_addr; 538419b0af8Sopenharmony_ci 539419b0af8Sopenharmony_ci /* this never happens */ 540419b0af8Sopenharmony_ci if (index >= TEE_PARAM_NUM || !call_params || !op_params) 541419b0af8Sopenharmony_ci return -EINVAL; 542419b0af8Sopenharmony_ci 543419b0af8Sopenharmony_ci operation = &op_params->mb_pack->operation; 544419b0af8Sopenharmony_ci client_param = &(call_params->context->params[index]); 545419b0af8Sopenharmony_ci a_addr = client_param->value.a_addr | 546419b0af8Sopenharmony_ci ((uint64_t)client_param->value.a_h_addr << ADDR_TRANS_NUM); 547419b0af8Sopenharmony_ci b_addr = client_param->value.b_addr | 548419b0af8Sopenharmony_ci ((uint64_t)client_param->value.b_h_addr << ADDR_TRANS_NUM); 549419b0af8Sopenharmony_ci 550419b0af8Sopenharmony_ci if (read_from_client(&operation->params[index].value.a, 551419b0af8Sopenharmony_ci sizeof(operation->params[index].value.a), 552419b0af8Sopenharmony_ci (void *)(uintptr_t)a_addr, 553419b0af8Sopenharmony_ci sizeof(operation->params[index].value.a), kernel_params)) { 554419b0af8Sopenharmony_ci tloge("valuea copy failed\n"); 555419b0af8Sopenharmony_ci return -EFAULT; 556419b0af8Sopenharmony_ci } 557419b0af8Sopenharmony_ci if (read_from_client(&operation->params[index].value.b, 558419b0af8Sopenharmony_ci sizeof(operation->params[index].value.b), 559419b0af8Sopenharmony_ci (void *)(uintptr_t)b_addr, 560419b0af8Sopenharmony_ci sizeof(operation->params[index].value.b), kernel_params)) { 561419b0af8Sopenharmony_ci tloge("valueb copy failed\n"); 562419b0af8Sopenharmony_ci return -EFAULT; 563419b0af8Sopenharmony_ci } 564419b0af8Sopenharmony_ci ion_shared_fd = operation->params[index].value.a; 565419b0af8Sopenharmony_ci ion_alloc_size = operation->params[index].value.b; 566419b0af8Sopenharmony_ci 567419b0af8Sopenharmony_ci if(get_ion_sg_list_from_fd(ion_shared_fd, ion_alloc_size, 568419b0af8Sopenharmony_ci &ion_sglist_addr, &ion_sglist_size)) { 569419b0af8Sopenharmony_ci tloge("get ion sglist failed, fd=%u\n", ion_shared_fd); 570419b0af8Sopenharmony_ci return -EFAULT; 571419b0af8Sopenharmony_ci } 572419b0af8Sopenharmony_ci op_params->local_tmpbuf[index].temp_buffer = phys_to_virt(ion_sglist_addr); 573419b0af8Sopenharmony_ci op_params->local_tmpbuf[index].size = ion_sglist_size; 574419b0af8Sopenharmony_ci 575419b0af8Sopenharmony_ci operation->params[index].memref.buffer = (unsigned int)ion_sglist_addr; 576419b0af8Sopenharmony_ci operation->buffer_h_addr[index] = 577419b0af8Sopenharmony_ci (uint64_t)ion_sglist_addr >> ADDR_TRANS_NUM; 578419b0af8Sopenharmony_ci operation->params[index].memref.size = (unsigned int)ion_sglist_size; 579419b0af8Sopenharmony_ci op_params->trans_paramtype[index] = param_type; 580419b0af8Sopenharmony_ci 581419b0af8Sopenharmony_ci return 0; 582419b0af8Sopenharmony_ci} 583419b0af8Sopenharmony_ci 584419b0af8Sopenharmony_cistatic int transfer_ion_params(struct tc_ns_operation *operation, 585419b0af8Sopenharmony_ci union tc_ns_client_param *client_param, uint8_t kernel_params, 586419b0af8Sopenharmony_ci unsigned int index) 587419b0af8Sopenharmony_ci{ 588419b0af8Sopenharmony_ci uint64_t a_addr = client_param->value.a_addr | 589419b0af8Sopenharmony_ci ((uint64_t)client_param->value.a_h_addr << ADDR_TRANS_NUM); 590419b0af8Sopenharmony_ci uint64_t b_addr = client_param->value.b_addr | 591419b0af8Sopenharmony_ci ((uint64_t)client_param->value.b_h_addr << ADDR_TRANS_NUM); 592419b0af8Sopenharmony_ci 593419b0af8Sopenharmony_ci if (read_from_client(&operation->params[index].value.a, 594419b0af8Sopenharmony_ci sizeof(operation->params[index].value.a), 595419b0af8Sopenharmony_ci (void *)(uintptr_t)a_addr, 596419b0af8Sopenharmony_ci sizeof(operation->params[index].value.a), kernel_params)) { 597419b0af8Sopenharmony_ci tloge("value.a_addr copy failed\n"); 598419b0af8Sopenharmony_ci return -EFAULT; 599419b0af8Sopenharmony_ci } 600419b0af8Sopenharmony_ci 601419b0af8Sopenharmony_ci if (read_from_client(&operation->params[index].value.b, 602419b0af8Sopenharmony_ci sizeof(operation->params[index].value.b), 603419b0af8Sopenharmony_ci (void *)(uintptr_t)b_addr, 604419b0af8Sopenharmony_ci sizeof(operation->params[index].value.b), kernel_params)) { 605419b0af8Sopenharmony_ci tloge("value.b_addr copy failed\n"); 606419b0af8Sopenharmony_ci return -EFAULT; 607419b0af8Sopenharmony_ci } 608419b0af8Sopenharmony_ci 609419b0af8Sopenharmony_ci return 0; 610419b0af8Sopenharmony_ci} 611419b0af8Sopenharmony_ci 612419b0af8Sopenharmony_ciint alloc_for_ion(const struct tc_call_params *call_params, 613419b0af8Sopenharmony_ci struct tc_op_params *op_params, uint8_t kernel_params, 614419b0af8Sopenharmony_ci uint32_t param_type, unsigned int index) 615419b0af8Sopenharmony_ci{ 616419b0af8Sopenharmony_ci struct tc_ns_operation *operation = NULL; 617419b0af8Sopenharmony_ci size_t drm_ion_size = 0; 618419b0af8Sopenharmony_ci phys_addr_t drm_ion_phys = 0x0; 619419b0af8Sopenharmony_ci struct dma_buf *drm_dma_buf = NULL; 620419b0af8Sopenharmony_ci union tc_ns_client_param *client_param = NULL; 621419b0af8Sopenharmony_ci unsigned int ion_shared_fd = 0; 622419b0af8Sopenharmony_ci int ret = 0; 623419b0af8Sopenharmony_ci 624419b0af8Sopenharmony_ci /* this never happens */ 625419b0af8Sopenharmony_ci if (index >= TEE_PARAM_NUM || !call_params || !op_params) 626419b0af8Sopenharmony_ci return -EINVAL; 627419b0af8Sopenharmony_ci 628419b0af8Sopenharmony_ci operation = &op_params->mb_pack->operation; 629419b0af8Sopenharmony_ci client_param = &(call_params->context->params[index]); 630419b0af8Sopenharmony_ci if (transfer_ion_params(operation, client_param, kernel_params, index)) 631419b0af8Sopenharmony_ci return -EFAULT; 632419b0af8Sopenharmony_ci 633419b0af8Sopenharmony_ci ion_shared_fd = operation->params[index].value.a; 634419b0af8Sopenharmony_ci drm_dma_buf = dma_buf_get(ion_shared_fd); 635419b0af8Sopenharmony_ci if (IS_ERR_OR_NULL(drm_dma_buf)) { 636419b0af8Sopenharmony_ci tloge("drm dma buf is err, ret = %d fd = %u\n", ret, ion_shared_fd); 637419b0af8Sopenharmony_ci return -EFAULT; 638419b0af8Sopenharmony_ci } 639419b0af8Sopenharmony_ci#ifdef CONFIG_DMABUF_MM 640419b0af8Sopenharmony_ci ret = mm_dma_heap_secmem_get_phys(drm_dma_buf, &drm_ion_phys, &drm_ion_size); 641419b0af8Sopenharmony_ci#else 642419b0af8Sopenharmony_ci ret = ion_secmem_get_phys(drm_dma_buf, &drm_ion_phys, &drm_ion_size); 643419b0af8Sopenharmony_ci#endif 644419b0af8Sopenharmony_ci if (ret != 0) { 645419b0af8Sopenharmony_ci tloge("in %s err:ret=%d fd=%u\n", __func__, ret, ion_shared_fd); 646419b0af8Sopenharmony_ci dma_buf_put(drm_dma_buf); 647419b0af8Sopenharmony_ci return -EFAULT; 648419b0af8Sopenharmony_ci } 649419b0af8Sopenharmony_ci 650419b0af8Sopenharmony_ci if (drm_ion_size > operation->params[index].value.b) 651419b0af8Sopenharmony_ci drm_ion_size = operation->params[index].value.b; 652419b0af8Sopenharmony_ci operation->params[index].value.a = (unsigned int)drm_ion_phys; 653419b0af8Sopenharmony_ci operation->params[index].value.b = (unsigned int)drm_ion_size; 654419b0af8Sopenharmony_ci op_params->trans_paramtype[index] = param_type; 655419b0af8Sopenharmony_ci dma_buf_put(drm_dma_buf); 656419b0af8Sopenharmony_ci 657419b0af8Sopenharmony_ci return ret; 658419b0af8Sopenharmony_ci}