Loading drivers/misc/qseecom.c +130 −24 Original line number Diff line number Diff line Loading @@ -278,6 +278,7 @@ struct qseecom_control { wait_queue_head_t app_block_wq; atomic_t qseecom_state; int is_apps_region_protected; bool smcinvoke_support; }; struct qseecom_sec_buf_fd_info { Loading Loading @@ -575,10 +576,12 @@ static int qseecom_scm_call2(uint32_t svc_id, uint32_t tz_cmd_id, desc.args[1] = req_64bit->sb_ptr; desc.args[2] = req_64bit->sb_len; } qseecom.smcinvoke_support = true; smc_id = TZ_OS_REGISTER_LISTENER_SMCINVOKE_ID; __qseecom_reentrancy_check_if_no_app_blocked(smc_id); ret = scm_call2(smc_id, &desc); if (ret) { qseecom.smcinvoke_support = false; smc_id = TZ_OS_REGISTER_LISTENER_ID; __qseecom_reentrancy_check_if_no_app_blocked( smc_id); Loading Loading @@ -1003,10 +1006,14 @@ static int qseecom_scm_call2(uint32_t svc_id, uint32_t tz_cmd_id, struct qseecom_continue_blocked_request_ireq *req = (struct qseecom_continue_blocked_request_ireq *) req_buf; if (qseecom.smcinvoke_support) smc_id = TZ_OS_CONTINUE_BLOCKED_REQUEST_SMCINVOKE_ID; else smc_id = TZ_OS_CONTINUE_BLOCKED_REQUEST_ID; desc.arginfo = TZ_OS_CONTINUE_BLOCKED_REQUEST_ID_PARAM_ID; desc.args[0] = req->app_id; desc.args[0] = req->app_or_session_id; ret = scm_call2(smc_id, &desc); break; } Loading Loading @@ -1836,7 +1843,7 @@ static int __qseecom_process_incomplete_cmd(struct qseecom_dev_handle *data, return ret; } int __qseecom_process_reentrancy_blocked_on_listener( static int __qseecom_process_blocked_on_listener_legacy( struct qseecom_command_scm_resp *resp, struct qseecom_registered_app_list *ptr_app, struct qseecom_dev_handle *data) Loading @@ -1845,9 +1852,8 @@ int __qseecom_process_reentrancy_blocked_on_listener( int ret = 0; struct qseecom_continue_blocked_request_ireq ireq; struct qseecom_command_scm_resp continue_resp; sigset_t new_sigset, old_sigset; unsigned long flags; bool found_app = false; unsigned long flags; if (!resp || !data) { pr_err("invalid resp or data pointer\n"); Loading Loading @@ -1887,32 +1893,30 @@ int __qseecom_process_reentrancy_blocked_on_listener( pr_debug("lsntr %d in_use = %d\n", resp->data, list_ptr->listener_in_use); ptr_app->blocked_on_listener_id = resp->data; /* sleep until listener is available */ do { qseecom.app_block_ref_cnt++; ptr_app->app_blocked = true; sigfillset(&new_sigset); sigprocmask(SIG_SETMASK, &new_sigset, &old_sigset); mutex_unlock(&app_access_lock); do { if (!wait_event_freezable( if (wait_event_freezable( list_ptr->listener_block_app_wq, !list_ptr->listener_in_use)) { break; pr_err("Interrupted: listener_id %d, app_id %d\n", resp->data, ptr_app->app_id); ret = -ERESTARTSYS; goto exit; } } while (1); mutex_lock(&app_access_lock); sigprocmask(SIG_SETMASK, &old_sigset, NULL); ptr_app->app_blocked = false; qseecom.app_block_ref_cnt--; } while (list_ptr->listener_in_use == true); ptr_app->blocked_on_listener_id = 0; /* notify the blocked app that listener is available */ pr_warn("Lsntr %d is available, unblock app(%d) %s in TZ\n", resp->data, data->client.app_id, data->client.app_name); ireq.qsee_cmd_id = QSEOS_CONTINUE_BLOCKED_REQ_COMMAND; ireq.app_id = data->client.app_id; ireq.app_or_session_id = data->client.app_id; ret = qseecom_scm_call(SCM_SVC_TZSCHEDULER, 1, &ireq, sizeof(ireq), &continue_resp, sizeof(continue_resp)); Loading @@ -1931,6 +1935,73 @@ exit: return ret; } static int __qseecom_process_blocked_on_listener_smcinvoke( struct qseecom_command_scm_resp *resp) { struct qseecom_registered_listener_list *list_ptr; int ret = 0; struct qseecom_continue_blocked_request_ireq ireq; struct qseecom_command_scm_resp continue_resp; unsigned int session_id; if (!resp) { pr_err("invalid resp pointer\n"); ret = -EINVAL; goto exit; } session_id = resp->resp_type; list_ptr = __qseecom_find_svc(resp->data); if (!list_ptr) { pr_err("Invalid listener ID\n"); ret = -ENODATA; goto exit; } pr_debug("lsntr %d in_use = %d\n", resp->data, list_ptr->listener_in_use); /* sleep until listener is available */ qseecom.app_block_ref_cnt++; mutex_unlock(&app_access_lock); if (wait_event_freezable( list_ptr->listener_block_app_wq, !list_ptr->listener_in_use)) { pr_err("Interrupted: listener_id %d, session_id %d\n", resp->data, session_id); ret = -ERESTARTSYS; goto exit; } mutex_lock(&app_access_lock); qseecom.app_block_ref_cnt--; /* notify TZ that listener is available */ pr_warn("Lsntr %d is available, unblock session(%d) in TZ\n", resp->data, session_id); ireq.qsee_cmd_id = QSEOS_CONTINUE_BLOCKED_REQ_COMMAND; ireq.app_or_session_id = session_id; ret = qseecom_scm_call(SCM_SVC_TZSCHEDULER, 1, &ireq, sizeof(ireq), &continue_resp, sizeof(continue_resp)); if (ret) { pr_err("scm_call for continue blocked req for session %d failed, ret %d\n", session_id, ret); goto exit; } resp->result = QSEOS_RESULT_INCOMPLETE; exit: return ret; } static int __qseecom_process_reentrancy_blocked_on_listener( struct qseecom_command_scm_resp *resp, struct qseecom_registered_app_list *ptr_app, struct qseecom_dev_handle *data) { if (!qseecom.smcinvoke_support) return __qseecom_process_blocked_on_listener_legacy( resp, ptr_app, data); else return __qseecom_process_blocked_on_listener_smcinvoke( resp); } static int __qseecom_reentrancy_process_incomplete_cmd( struct qseecom_dev_handle *data, struct qseecom_command_scm_resp *resp) Loading Loading @@ -4684,6 +4755,41 @@ int qseecom_set_bandwidth(struct qseecom_handle *handle, bool high) } EXPORT_SYMBOL(qseecom_set_bandwidth); int qseecom_process_listener_from_smcinvoke(struct scm_desc *desc) { struct qseecom_registered_app_list dummy_app_entry = { {0} }; struct qseecom_dev_handle dummy_private_data = {0}; struct qseecom_command_scm_resp resp; int ret = 0; if (!desc) { pr_err("desc is NULL\n"); return -EINVAL; } resp.result = desc->ret[0]; /*req_cmd*/ resp.resp_type = desc->ret[1]; /*incomplete:unused;blocked:session_id*/ resp.data = desc->ret[2]; /*listener_id*/ mutex_lock(&app_access_lock); if (qseecom.qsee_reentrancy_support) ret = __qseecom_process_reentrancy(&resp, &dummy_app_entry, &dummy_private_data); else ret = __qseecom_process_incomplete_cmd(&dummy_private_data, &resp); mutex_unlock(&app_access_lock); if (ret) pr_err("Failed on cmd %d for lsnr %d session %d, ret = %d\n", (int)desc->ret[0], (int)desc->ret[2], (int)desc->ret[1], ret); desc->ret[0] = resp.result; desc->ret[1] = resp.resp_type; desc->ret[2] = resp.data; return ret; } EXPORT_SYMBOL(qseecom_process_listener_from_smcinvoke); static int qseecom_send_resp(void) { qseecom.send_resp_flag = 1; Loading drivers/misc/qseecom_kernel.h +2 −0 Original line number Diff line number Diff line Loading @@ -14,6 +14,7 @@ #define __QSEECOM_KERNEL_H_ #include <linux/types.h> #include <soc/qcom/scm.h> #define QSEECOM_ALIGN_SIZE 0x40 #define QSEECOM_ALIGN_MASK (QSEECOM_ALIGN_SIZE - 1) Loading @@ -38,5 +39,6 @@ int qseecom_shutdown_app(struct qseecom_handle **handle); int qseecom_send_command(struct qseecom_handle *handle, void *send_buf, uint32_t sbuf_len, void *resp_buf, uint32_t rbuf_len); int qseecom_set_bandwidth(struct qseecom_handle *handle, bool high); int qseecom_process_listener_from_smcinvoke(struct scm_desc *desc); #endif /* __QSEECOM_KERNEL_H_ */ include/soc/qcom/qseecomi.h +4 −1 Original line number Diff line number Diff line Loading @@ -336,7 +336,7 @@ __packed struct qseecom_client_send_fsm_key_req { __packed struct qseecom_continue_blocked_request_ireq { uint32_t qsee_cmd_id; uint32_t app_id; uint32_t app_or_session_id; /*legacy: app_id; smcinvoke: session_id*/ }; Loading Loading @@ -681,6 +681,9 @@ __packed struct qseecom_continue_blocked_request_ireq { #define TZ_OS_CONTINUE_BLOCKED_REQUEST_ID \ TZ_SYSCALL_CREATE_SMC_ID(TZ_OWNER_QSEE_OS, TZ_SVC_LISTENER, 0x04) #define TZ_OS_CONTINUE_BLOCKED_REQUEST_SMCINVOKE_ID \ TZ_SYSCALL_CREATE_SMC_ID(TZ_OWNER_QSEE_OS, TZ_SVC_LISTENER, 0x07) #define TZ_OS_CONTINUE_BLOCKED_REQUEST_ID_PARAM_ID \ TZ_SYSCALL_CREATE_PARAM_ID_1(TZ_SYSCALL_PARAM_TYPE_VAL) Loading Loading
drivers/misc/qseecom.c +130 −24 Original line number Diff line number Diff line Loading @@ -278,6 +278,7 @@ struct qseecom_control { wait_queue_head_t app_block_wq; atomic_t qseecom_state; int is_apps_region_protected; bool smcinvoke_support; }; struct qseecom_sec_buf_fd_info { Loading Loading @@ -575,10 +576,12 @@ static int qseecom_scm_call2(uint32_t svc_id, uint32_t tz_cmd_id, desc.args[1] = req_64bit->sb_ptr; desc.args[2] = req_64bit->sb_len; } qseecom.smcinvoke_support = true; smc_id = TZ_OS_REGISTER_LISTENER_SMCINVOKE_ID; __qseecom_reentrancy_check_if_no_app_blocked(smc_id); ret = scm_call2(smc_id, &desc); if (ret) { qseecom.smcinvoke_support = false; smc_id = TZ_OS_REGISTER_LISTENER_ID; __qseecom_reentrancy_check_if_no_app_blocked( smc_id); Loading Loading @@ -1003,10 +1006,14 @@ static int qseecom_scm_call2(uint32_t svc_id, uint32_t tz_cmd_id, struct qseecom_continue_blocked_request_ireq *req = (struct qseecom_continue_blocked_request_ireq *) req_buf; if (qseecom.smcinvoke_support) smc_id = TZ_OS_CONTINUE_BLOCKED_REQUEST_SMCINVOKE_ID; else smc_id = TZ_OS_CONTINUE_BLOCKED_REQUEST_ID; desc.arginfo = TZ_OS_CONTINUE_BLOCKED_REQUEST_ID_PARAM_ID; desc.args[0] = req->app_id; desc.args[0] = req->app_or_session_id; ret = scm_call2(smc_id, &desc); break; } Loading Loading @@ -1836,7 +1843,7 @@ static int __qseecom_process_incomplete_cmd(struct qseecom_dev_handle *data, return ret; } int __qseecom_process_reentrancy_blocked_on_listener( static int __qseecom_process_blocked_on_listener_legacy( struct qseecom_command_scm_resp *resp, struct qseecom_registered_app_list *ptr_app, struct qseecom_dev_handle *data) Loading @@ -1845,9 +1852,8 @@ int __qseecom_process_reentrancy_blocked_on_listener( int ret = 0; struct qseecom_continue_blocked_request_ireq ireq; struct qseecom_command_scm_resp continue_resp; sigset_t new_sigset, old_sigset; unsigned long flags; bool found_app = false; unsigned long flags; if (!resp || !data) { pr_err("invalid resp or data pointer\n"); Loading Loading @@ -1887,32 +1893,30 @@ int __qseecom_process_reentrancy_blocked_on_listener( pr_debug("lsntr %d in_use = %d\n", resp->data, list_ptr->listener_in_use); ptr_app->blocked_on_listener_id = resp->data; /* sleep until listener is available */ do { qseecom.app_block_ref_cnt++; ptr_app->app_blocked = true; sigfillset(&new_sigset); sigprocmask(SIG_SETMASK, &new_sigset, &old_sigset); mutex_unlock(&app_access_lock); do { if (!wait_event_freezable( if (wait_event_freezable( list_ptr->listener_block_app_wq, !list_ptr->listener_in_use)) { break; pr_err("Interrupted: listener_id %d, app_id %d\n", resp->data, ptr_app->app_id); ret = -ERESTARTSYS; goto exit; } } while (1); mutex_lock(&app_access_lock); sigprocmask(SIG_SETMASK, &old_sigset, NULL); ptr_app->app_blocked = false; qseecom.app_block_ref_cnt--; } while (list_ptr->listener_in_use == true); ptr_app->blocked_on_listener_id = 0; /* notify the blocked app that listener is available */ pr_warn("Lsntr %d is available, unblock app(%d) %s in TZ\n", resp->data, data->client.app_id, data->client.app_name); ireq.qsee_cmd_id = QSEOS_CONTINUE_BLOCKED_REQ_COMMAND; ireq.app_id = data->client.app_id; ireq.app_or_session_id = data->client.app_id; ret = qseecom_scm_call(SCM_SVC_TZSCHEDULER, 1, &ireq, sizeof(ireq), &continue_resp, sizeof(continue_resp)); Loading @@ -1931,6 +1935,73 @@ exit: return ret; } static int __qseecom_process_blocked_on_listener_smcinvoke( struct qseecom_command_scm_resp *resp) { struct qseecom_registered_listener_list *list_ptr; int ret = 0; struct qseecom_continue_blocked_request_ireq ireq; struct qseecom_command_scm_resp continue_resp; unsigned int session_id; if (!resp) { pr_err("invalid resp pointer\n"); ret = -EINVAL; goto exit; } session_id = resp->resp_type; list_ptr = __qseecom_find_svc(resp->data); if (!list_ptr) { pr_err("Invalid listener ID\n"); ret = -ENODATA; goto exit; } pr_debug("lsntr %d in_use = %d\n", resp->data, list_ptr->listener_in_use); /* sleep until listener is available */ qseecom.app_block_ref_cnt++; mutex_unlock(&app_access_lock); if (wait_event_freezable( list_ptr->listener_block_app_wq, !list_ptr->listener_in_use)) { pr_err("Interrupted: listener_id %d, session_id %d\n", resp->data, session_id); ret = -ERESTARTSYS; goto exit; } mutex_lock(&app_access_lock); qseecom.app_block_ref_cnt--; /* notify TZ that listener is available */ pr_warn("Lsntr %d is available, unblock session(%d) in TZ\n", resp->data, session_id); ireq.qsee_cmd_id = QSEOS_CONTINUE_BLOCKED_REQ_COMMAND; ireq.app_or_session_id = session_id; ret = qseecom_scm_call(SCM_SVC_TZSCHEDULER, 1, &ireq, sizeof(ireq), &continue_resp, sizeof(continue_resp)); if (ret) { pr_err("scm_call for continue blocked req for session %d failed, ret %d\n", session_id, ret); goto exit; } resp->result = QSEOS_RESULT_INCOMPLETE; exit: return ret; } static int __qseecom_process_reentrancy_blocked_on_listener( struct qseecom_command_scm_resp *resp, struct qseecom_registered_app_list *ptr_app, struct qseecom_dev_handle *data) { if (!qseecom.smcinvoke_support) return __qseecom_process_blocked_on_listener_legacy( resp, ptr_app, data); else return __qseecom_process_blocked_on_listener_smcinvoke( resp); } static int __qseecom_reentrancy_process_incomplete_cmd( struct qseecom_dev_handle *data, struct qseecom_command_scm_resp *resp) Loading Loading @@ -4684,6 +4755,41 @@ int qseecom_set_bandwidth(struct qseecom_handle *handle, bool high) } EXPORT_SYMBOL(qseecom_set_bandwidth); int qseecom_process_listener_from_smcinvoke(struct scm_desc *desc) { struct qseecom_registered_app_list dummy_app_entry = { {0} }; struct qseecom_dev_handle dummy_private_data = {0}; struct qseecom_command_scm_resp resp; int ret = 0; if (!desc) { pr_err("desc is NULL\n"); return -EINVAL; } resp.result = desc->ret[0]; /*req_cmd*/ resp.resp_type = desc->ret[1]; /*incomplete:unused;blocked:session_id*/ resp.data = desc->ret[2]; /*listener_id*/ mutex_lock(&app_access_lock); if (qseecom.qsee_reentrancy_support) ret = __qseecom_process_reentrancy(&resp, &dummy_app_entry, &dummy_private_data); else ret = __qseecom_process_incomplete_cmd(&dummy_private_data, &resp); mutex_unlock(&app_access_lock); if (ret) pr_err("Failed on cmd %d for lsnr %d session %d, ret = %d\n", (int)desc->ret[0], (int)desc->ret[2], (int)desc->ret[1], ret); desc->ret[0] = resp.result; desc->ret[1] = resp.resp_type; desc->ret[2] = resp.data; return ret; } EXPORT_SYMBOL(qseecom_process_listener_from_smcinvoke); static int qseecom_send_resp(void) { qseecom.send_resp_flag = 1; Loading
drivers/misc/qseecom_kernel.h +2 −0 Original line number Diff line number Diff line Loading @@ -14,6 +14,7 @@ #define __QSEECOM_KERNEL_H_ #include <linux/types.h> #include <soc/qcom/scm.h> #define QSEECOM_ALIGN_SIZE 0x40 #define QSEECOM_ALIGN_MASK (QSEECOM_ALIGN_SIZE - 1) Loading @@ -38,5 +39,6 @@ int qseecom_shutdown_app(struct qseecom_handle **handle); int qseecom_send_command(struct qseecom_handle *handle, void *send_buf, uint32_t sbuf_len, void *resp_buf, uint32_t rbuf_len); int qseecom_set_bandwidth(struct qseecom_handle *handle, bool high); int qseecom_process_listener_from_smcinvoke(struct scm_desc *desc); #endif /* __QSEECOM_KERNEL_H_ */
include/soc/qcom/qseecomi.h +4 −1 Original line number Diff line number Diff line Loading @@ -336,7 +336,7 @@ __packed struct qseecom_client_send_fsm_key_req { __packed struct qseecom_continue_blocked_request_ireq { uint32_t qsee_cmd_id; uint32_t app_id; uint32_t app_or_session_id; /*legacy: app_id; smcinvoke: session_id*/ }; Loading Loading @@ -681,6 +681,9 @@ __packed struct qseecom_continue_blocked_request_ireq { #define TZ_OS_CONTINUE_BLOCKED_REQUEST_ID \ TZ_SYSCALL_CREATE_SMC_ID(TZ_OWNER_QSEE_OS, TZ_SVC_LISTENER, 0x04) #define TZ_OS_CONTINUE_BLOCKED_REQUEST_SMCINVOKE_ID \ TZ_SYSCALL_CREATE_SMC_ID(TZ_OWNER_QSEE_OS, TZ_SVC_LISTENER, 0x07) #define TZ_OS_CONTINUE_BLOCKED_REQUEST_ID_PARAM_ID \ TZ_SYSCALL_CREATE_PARAM_ID_1(TZ_SYSCALL_PARAM_TYPE_VAL) Loading