From 7b0010980fa06ebd26ef48917eae7e0ab5a7915a Mon Sep 17 00:00:00 2001 From: Anmolpreet Kaur Date: Wed, 5 Feb 2020 16:10:34 +0530 Subject: [PATCH] qseecom: Change in buffer sharing mechanism in qseecom Copy the entire userspace request buffer to local kernel buffer and use that to send to TZ. Update the response received in the local buffer to the actual userspace buffer after the request is complete. Change-Id: I673d74a32966816c5248778fc967eb91da5b6df5 Signed-off-by: Anmolpreet Kaur --- drivers/misc/qseecom.c | 97 ++++++++++++++++++++++++++++++++---------- 1 file changed, 74 insertions(+), 23 deletions(-) diff --git a/drivers/misc/qseecom.c b/drivers/misc/qseecom.c index 4f737d3b693a..f3aab68cf675 100644 --- a/drivers/misc/qseecom.c +++ b/drivers/misc/qseecom.c @@ -460,6 +460,10 @@ static int __maybe_unused get_qseecom_keymaster_status(char *str) } __setup("androidboot.keymaster=", get_qseecom_keymaster_status); +static int __qseecom_alloc_coherent_buf( + uint32_t size, u8 **vaddr, phys_addr_t *paddr); +static void __qseecom_free_coherent_buf(uint32_t size, + u8 *vaddr, phys_addr_t paddr); #define QSEECOM_SCM_EBUSY_WAIT_MS 30 #define QSEECOM_SCM_EBUSY_MAX_RETRY 67 @@ -3662,7 +3666,8 @@ static int __qseecom_process_reentrancy(struct qseecom_command_scm_resp *resp, } static int __qseecom_send_cmd(struct qseecom_dev_handle *data, - struct qseecom_send_cmd_req *req) + struct qseecom_send_cmd_req *req, + bool is_phys_adr) { int ret = 0; u32 reqd_len_sb_in = 0; @@ -3703,11 +3708,20 @@ static int __qseecom_send_cmd(struct qseecom_dev_handle *data, if (qseecom.qsee_version < QSEE_VERSION_40) { send_data_req.app_id = data->client.app_id; - send_data_req.req_ptr = (uint32_t)(__qseecom_uvirt_to_kphys( - data, (uintptr_t)req->cmd_req_buf)); + + if (!is_phys_adr) { + send_data_req.req_ptr = + (uint32_t)(__qseecom_uvirt_to_kphys + (data, (uintptr_t)req->cmd_req_buf)); + send_data_req.rsp_ptr = + (uint32_t)(__qseecom_uvirt_to_kphys( + data, (uintptr_t)req->resp_buf)); + } else { + send_data_req.req_ptr = (uint32_t)req->cmd_req_buf; + send_data_req.rsp_ptr = (uint32_t)req->resp_buf; + } + send_data_req.req_len = req->cmd_req_len; - send_data_req.rsp_ptr = (uint32_t)(__qseecom_uvirt_to_kphys( - data, (uintptr_t)req->resp_buf)); send_data_req.rsp_len = req->resp_len; send_data_req.sglistinfo_ptr = (uint32_t)data->sglistinfo_shm.paddr; @@ -3717,11 +3731,21 @@ static int __qseecom_send_cmd(struct qseecom_dev_handle *data, cmd_len = sizeof(struct qseecom_client_send_data_ireq); } else { send_data_req_64bit.app_id = data->client.app_id; - send_data_req_64bit.req_ptr = __qseecom_uvirt_to_kphys(data, - (uintptr_t)req->cmd_req_buf); + + if (!is_phys_adr) { + send_data_req_64bit.req_ptr = + __qseecom_uvirt_to_kphys(data, + (uintptr_t)req->cmd_req_buf); + send_data_req_64bit.rsp_ptr = + __qseecom_uvirt_to_kphys(data, + (uintptr_t)req->resp_buf); + } else { + send_data_req_64bit.req_ptr = + (uintptr_t)req->cmd_req_buf; + send_data_req_64bit.rsp_ptr = + (uintptr_t)req->resp_buf; + } send_data_req_64bit.req_len = req->cmd_req_len; - send_data_req_64bit.rsp_ptr = __qseecom_uvirt_to_kphys(data, - (uintptr_t)req->resp_buf); send_data_req_64bit.rsp_len = req->resp_len; /* check if 32bit app's phys_addr region is under 4GB.*/ if ((data->client.app_arch == ELFCLASS32) && @@ -3818,7 +3842,7 @@ static int qseecom_send_cmd(struct qseecom_dev_handle *data, void __user *argp) if (__validate_send_cmd_inputs(data, &req)) return -EINVAL; - ret = __qseecom_send_cmd(data, &req); + ret = __qseecom_send_cmd(data, &req, false); return ret; } @@ -4336,6 +4360,9 @@ static int __qseecom_send_modfd_cmd(struct qseecom_dev_handle *data, int i; struct qseecom_send_modfd_cmd_req req; struct qseecom_send_cmd_req send_cmd_req; + void *origin_req_buf_kvirt, *origin_rsp_buf_kvirt; + phys_addr_t pa; + u8 *va = NULL; ret = copy_from_user(&req, argp, sizeof(req)); if (ret) { @@ -4359,33 +4386,57 @@ static int __qseecom_send_modfd_cmd(struct qseecom_dev_handle *data, return -EINVAL; } } - req.cmd_req_buf = (void *)__qseecom_uvirt_to_kvirt(data, - (uintptr_t)req.cmd_req_buf); - req.resp_buf = (void *)__qseecom_uvirt_to_kvirt(data, - (uintptr_t)req.resp_buf); + + /*Back up original address */ + origin_req_buf_kvirt = (void *)__qseecom_uvirt_to_kvirt(data, + (uintptr_t)req.cmd_req_buf); + origin_rsp_buf_kvirt = (void *)__qseecom_uvirt_to_kvirt(data, + (uintptr_t)req.resp_buf); + + /* Allocate kernel buffer for request and response*/ + ret = __qseecom_alloc_coherent_buf(req.cmd_req_len + req.resp_len, + &va, &pa); + req.cmd_req_buf = va; + send_cmd_req.cmd_req_buf = (void *)pa; + + req.resp_buf = va + req.cmd_req_len; + send_cmd_req.resp_buf = (void *)pa + req.cmd_req_len; + + /* Copy the data to kernel request and response buffers*/ + memcpy(req.cmd_req_buf, origin_req_buf_kvirt, req.cmd_req_len); + memcpy(req.resp_buf, origin_rsp_buf_kvirt, req.resp_len); if (!is_64bit_addr) { ret = __qseecom_update_cmd_buf(&req, false, data); if (ret) - return ret; - ret = __qseecom_send_cmd(data, &send_cmd_req); + goto out; + ret = __qseecom_send_cmd(data, &send_cmd_req, true); if (ret) - return ret; + goto out; ret = __qseecom_update_cmd_buf(&req, true, data); if (ret) - return ret; + goto out; } else { ret = __qseecom_update_cmd_buf_64(&req, false, data); if (ret) - return ret; - ret = __qseecom_send_cmd(data, &send_cmd_req); + goto out; + ret = __qseecom_send_cmd(data, &send_cmd_req, true); if (ret) - return ret; + goto out; ret = __qseecom_update_cmd_buf_64(&req, true, data); if (ret) - return ret; + goto out; } + /*Copy the response back to the userspace buffer*/ + memcpy(origin_rsp_buf_kvirt, req.resp_buf, req.resp_len); + memcpy(origin_req_buf_kvirt, req.cmd_req_buf, req.cmd_req_len); + +out: + if (req.cmd_req_buf) + __qseecom_free_coherent_buf(req.cmd_req_len + req.resp_len, + req.cmd_req_buf, (phys_addr_t)send_cmd_req.cmd_req_buf); + return ret; } @@ -5251,7 +5302,7 @@ int qseecom_send_command(struct qseecom_handle *handle, void *send_buf, if (!strcmp(data->client.app_name, "securemm")) data->use_legacy_cmd = true; - ret = __qseecom_send_cmd(data, &req); + ret = __qseecom_send_cmd(data, &req, false); data->use_legacy_cmd = false; if (qseecom.support_bus_scaling)