From a1df7a05102b1f5b0e79c51a0504e69b80900a52 Mon Sep 17 00:00:00 2001 From: root Date: Fri, 6 May 2022 16:01:57 +0800 Subject: [PATCH] lilianhui1@huawei.com Signed-off-by: root --- CMakeLists.txt | 2 +- Makefile | 2 +- core/gp_ops.c | 153 ++++++++++++++++++++++++++++++++++++++++ core/gp_ops.h | 7 ++ tc_ns_client.h | 4 ++ teek_client_constants.h | 2 + teek_ns_client.h | 4 ++ 7 files changed, 172 insertions(+), 2 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index cd58879..cf887c0 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -30,7 +30,7 @@ set(KERNEL_DIR ${KPATH}/${KDIR}) set(CMAKE_EXTRA_FLAGS "-fstack-protector-strong -DCONFIG_TEELOG -DCONFIG_TZDRIVER_MODULE -DCONFIG_TEECD_AUTH -DCONFIG_PAGES_MEM=y -DCONFIG_AUTH_ENHANCE -DCONFIG_CLOUDSERVER_TEECD_AUTH") set(CMAKE_EXTRA_FLAGS "${CMAKE_EXTRA_FLAGS} -DCONFIG_CPU_AFF_NR=0 -DCONFIG_BIG_SESSION=1000 -DCONFIG_NOTIFY_PAGE_ORDER=4 -DCONFIG_512K_LOG_PAGES_MEM") set(CMAKE_EXTRA_FLAGS "${CMAKE_EXTRA_FLAGS} -DCONFIG_TEE_LOG_ACHIVE_PATH=\\\\\\\"/var/log/tee/last_teemsg\\\\\\\"") -set(CMAKE_EXTRA_FLAGS "${CMAKE_EXTRA_FLAGS} -DNOT_TRIGGER_AP_RESET -DLAST_TEE_MSG_ROOT_GID") +set(CMAKE_EXTRA_FLAGS "${CMAKE_EXTRA_FLAGS} -DNOT_TRIGGER_AP_RESET -DLAST_TEE_MSG_ROOT_GID -DCONFIG_NOCOPY_SHAREDMEM") set(CMAKE_EXTRA_FLAGS "${CMAKE_EXTRA_FLAGS} -I${PROJECT_SOURCE_DIR}/libboundscheck/include/ -I${PROJECT_SOURCE_DIR} -I${PROJECT_SOURCE_DIR}/auth -I${PROJECT_SOURCE_DIR}/core") set(CMAKE_EXTRA_FLAGS "${CMAKE_EXTRA_FLAGS} -I${PROJECT_SOURCE_DIR}/tlogger -I${PROJECT_SOURCE_DIR}/kthread_affinity") diff --git a/Makefile b/Makefile index 253938d..09f2fea 100644 --- a/Makefile +++ b/Makefile @@ -25,7 +25,7 @@ EXTRA_CFLAGS += -I$(PWD)/libboundscheck/include/ -I$(PWD) -I$(PWD)/auth -I$(PWD) EXTRA_CFLAGS += -I$(PWD)/tlogger -I$(PWD)/kthread_affinity EXTRA_CFLAGS += -DCONFIG_CPU_AFF_NR=0 -DCONFIG_BIG_SESSION=1000 -DCONFIG_NOTIFY_PAGE_ORDER=4 -DCONFIG_512K_LOG_PAGES_MEM EXTRA_CFLAGS += -DCONFIG_TEE_LOG_ACHIVE_PATH=\"/var/log/tee/last_teemsg\" -EXTRA_CFLAGS += -DNOT_TRIGGER_AP_RESET -DLAST_TEE_MSG_ROOT_GID +EXTRA_CFLAGS += -DNOT_TRIGGER_AP_RESET -DLAST_TEE_MSG_ROOT_GID -DCONFIG_NOCOPY_SHAREDMEM all: make -C $(KDIR) M=$(PWD) modules clean: diff --git a/core/gp_ops.c b/core/gp_ops.c index f73aca0..b6eaaef 100644 --- a/core/gp_ops.c +++ b/core/gp_ops.c @@ -30,6 +30,9 @@ #include #include #include +#include +#include +#include #include #include #include "teek_client_constants.h" @@ -531,6 +534,125 @@ static int alloc_for_ref_mem(const struct tc_call_params *call_params, return ret; } +#ifdef CONFIG_NOCOPY_SHAREDMEM +static int fill_shared_mem_info(void *start_vaddr, uint32_t pages_no, + uint32_t offset, uint32_t buffer_size, void *buff) +{ + struct pagelist_info *page_info = NULL; + struct page **pages = NULL; + uint64_t *phys_addr = NULL; + uint32_t page_num; + uint32_t i; + + if (pages_no == 0) + return -EFAULT; + + pages = (struct page **)vmalloc(pages_no * sizeof(uint64_t)); + if (pages == NULL) + return -EFAULT; + + down_read(&(current->mm->mmap_sem)); + page_num = get_user_pages(start_vaddr, pages_no, 0, pages, NULL); + up_read(&(current->mm->mmap_sem)); + if (page_num != pages_no) { + tloge("get page phy addr failed\n"); + if (page_num > 0) + release_pages(pages, page_num); + vfree(pages); + return -EFAULT; + } + + page_info = buff; + page_info->page_num = pages_no; + page_info->page_size = PAGE_SIZE; + page_info->sharedmem_offset = offset; + page_info->sharedmem_size = buffer_size; + + phys_addr = (uint64_t *)buff + (sizeof(*page_info) / sizeof(uint64_t)); + for (i = 0; i < pages_no; i++) { + struct page *page = pages[i]; + if (page == NULL) { + release_pages(pages, page_num); + vfree(pages); + return -EFAULT; + } + phys_addr[i] = (uintptr_t)page_to_phys(page); + } + + vfree(pages); + return 0; +} + +static int check_buffer_for_sharedmem(uint32_t *buffer_size, + const union tc_ns_client_param *client_param, uint8_t kernel_params) +{ + if (read_from_client(buffer_size, sizeof(*buffer_size), + (uint32_t __user *)(uintptr_t)client_param->sharedmem.size_addr, + sizeof(uint32_t), kernel_params)) { + tloge("copy sharedmem.size_addr failed\n"); + return -EFAULT; + } + + if (*buffer_size == 0 || *buffer_size > SZ_256M) { + tloge("invalid buffer size\n"); + return -ENOMEM; + } + + return 0; +} + +static int transfer_shared_mem(const struct tc_call_params *call_params, + struct tc_op_params *op_params, uint8_t kernel_params, + uint32_t param_type, unsigned int index) +{ + void *buff = NULL; + void *start_vaddr = NULL; + union tc_ns_client_param *client_param = NULL; + uint32_t buffer_size; + uint32_t pages_no; + uint32_t offset; + uint32_t buff_len; + + if (index >= TEE_PARAM_NUM) + return -EINVAL; + + client_param = &(call_params->context->params[index]); + if (check_buffer_for_sharedmem(&buffer_size, client_param, kernel_params)) + return -EINVAL; + + buff = (void *)(uint64_t)client_param->sharedmem.buffer; + start_vaddr = (void *)(((uint64_t)buff) & PAGE_MASK); + offset = ((uint32_t)(uintptr_t)buff) & (~PAGE_MASK); + pages_no = PAGE_ALIGN(offset + buffer_size) / PAGE_SIZE; + + buff_len = sizeof(struct pagelist_info) + (sizeof(uint64_t) * pages_no); + buff = mailbox_alloc(buff_len, MB_FLAG_ZERO); + if (buff == NULL) + return -EFAULT; + if(fill_shared_mem_info(start_vaddr, pages_no, offset, buffer_size, buff)) { + mailbox_free(buff); + return -EFAULT; + } + + op_params->local_tmpbuf[index].temp_buffer = buff; + op_params->local_tmpbuf[index].size = buff_len; + + op_params->mb_pack->operation.params[index].sharedmem.buffer = virt_to_phys(buff); + op_params->mb_pack->operation.buffer_h_addr[index] = (uint64_t)virt_to_phys(buff) >> ADDR_TRANS_NUM; + op_params->mb_pack->operation.params[index].sharedmem.size = buff_len; + op_params->trans_paramtype[index] = param_type; + return 0; +} +#else +static int transfer_shared_mem(const struct tc_call_params *call_params, + struct tc_op_params *op_params, uint8_t kernel_params, + uint32_t param_type, unsigned int index) +{ + tloge("invalid shared mem type\n"); + return -1; +} +#endif + static int transfer_client_value(const struct tc_call_params *call_params, struct tc_op_params *op_params, uint8_t kernel_params, uint32_t param_type, unsigned int index) @@ -619,6 +741,9 @@ static int alloc_operation(const struct tc_call_params *call_params, else if (param_type == TEEC_ION_SGLIST_INPUT) ret = alloc_for_ion_sglist(call_params, op_params, kernel_params, param_type, index); + else if (param_type == TEEC_MEMREF_SHARED_INOUT) + ret = transfer_shared_mem(call_params, op_params, + kernel_params, param_type, index); else tlogd("param type = TEEC_NONE\n"); @@ -797,6 +922,26 @@ static int update_client_operation(const struct tc_call_params *call_params, return ret; } + +#ifdef CONFIG_NOCOPY_SHAREDMEM +static void release_page(void *buf) +{ + uint32_t i; + uint64_t *phys_addr = NULL; + struct pagelist_info *page_info = NULL; + struct page *page = NULL; + + page_info = buf; + phys_addr = (uint64_t *)buf + (sizeof(*page_info) / sizeof(uint64_t)); + for (i = 0; i < page_info->page_num; i++) { + page = (uintptr_t)phys_to_page(phys_addr[i]); + if (page == NULL) + continue; + put_page(page); + } +} +#endif + static void free_operation(const struct tc_call_params *call_params, struct tc_op_params *op_params) { @@ -833,6 +978,14 @@ static void free_operation(const struct tc_call_params *call_params, mailbox_free(temp_buf); temp_buf = NULL; } + } else if (param_type == TEEC_MEMREF_SHARED_INOUT) { +#ifdef CONFIG_NOCOPY_SHAREDMEM + temp_buf = local_tmpbuf[index].temp_buffer; + if (temp_buf != NULL) { + release_page(temp_buf); + mailbox_free(temp_buf); + } +#endif } } } diff --git a/core/gp_ops.h b/core/gp_ops.h index 9a19269..c730e7b 100644 --- a/core/gp_ops.h +++ b/core/gp_ops.h @@ -35,6 +35,13 @@ struct tc_op_params { bool op_inited; }; +struct pagelist_info { + uint64_t page_num; + uint64_t page_size; + uint64_t sharedmem_offset; + uint64_t sharedmem_size; +}; + int write_to_client(void __user *dest, size_t dest_size, const void *src, size_t size, uint8_t kernel_api); int read_from_client(void *dest, size_t dest_size, diff --git a/tc_ns_client.h b/tc_ns_client.h index 814a578..ea83e7a 100644 --- a/tc_ns_client.h +++ b/tc_ns_client.h @@ -51,6 +51,10 @@ union tc_ns_client_param { __u64 a_addr; __u64 b_addr; } value; + struct { + __u64 buffer; + __u64 size_addr; + } sharedmem; }; struct tc_ns_client_return { diff --git a/teek_client_constants.h b/teek_client_constants.h index 6e48e22..cecf27c 100644 --- a/teek_client_constants.h +++ b/teek_client_constants.h @@ -131,6 +131,7 @@ enum TEEC_ParamType { TEEC_MEMREF_TEMP_INOUT = 0x07, TEEC_ION_INPUT = 0x08, TEEC_ION_SGLIST_INPUT = 0x09, + TEEC_MEMREF_SHARED_INOUT = 0xa, TEEC_MEMREF_WHOLE = 0xc, TEEC_MEMREF_PARTIAL_INPUT = 0xd, TEEC_MEMREF_PARTIAL_OUTPUT = 0xe, @@ -147,6 +148,7 @@ enum TEE_ParamType { TEE_PARAM_TYPE_MEMREF_INOUT = 0x7, TEE_PARAM_TYPE_ION_INPUT = 0x8, TEE_PARAM_TYPE_ION_SGLIST_INPUT = 0x9, + TEE_PARAM_TYPE_MEMREF_SHARED_INOUT = 0xa, }; enum TEEC_LoginMethod { diff --git a/teek_ns_client.h b/teek_ns_client.h index b9271e8..6cd6a3a 100644 --- a/teek_ns_client.h +++ b/teek_ns_client.h @@ -116,6 +116,10 @@ union tc_ns_parameter { unsigned int a; unsigned int b; } value; + struct { + unsigned int buffer; + unsigned int size; + } sharedmem; }; struct tc_ns_login { -- Gitee