qseecom: update on smcinvoke-aware listeners operations
With the introduction of MinkIPC for TA-to-TA communication, if a request for blocking a TA (on a busy listener) is received by qseecom, it may not be originated from the last TA to which a command (or unblock response) was sent to. So, make change to use a session_id instead of app_id to uniquely identify this blocked request and a new cmd ID to support this smcinvoke-aware listener operation. Change-Id: I362e9acfa52c055b5759c210bb881da40f4e0776 Signed-off-by: Zhen Kong <zkong@codeaurora.org>
This commit is contained in:
parent
0ea2b1fc15
commit
7293d203cf
2 changed files with 101 additions and 30 deletions
|
@ -281,6 +281,7 @@ struct qseecom_control {
|
||||||
wait_queue_head_t app_block_wq;
|
wait_queue_head_t app_block_wq;
|
||||||
atomic_t qseecom_state;
|
atomic_t qseecom_state;
|
||||||
int is_apps_region_protected;
|
int is_apps_region_protected;
|
||||||
|
bool smcinvoke_support;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct qseecom_sec_buf_fd_info {
|
struct qseecom_sec_buf_fd_info {
|
||||||
|
@ -578,10 +579,12 @@ static int qseecom_scm_call2(uint32_t svc_id, uint32_t tz_cmd_id,
|
||||||
desc.args[1] = req_64bit->sb_ptr;
|
desc.args[1] = req_64bit->sb_ptr;
|
||||||
desc.args[2] = req_64bit->sb_len;
|
desc.args[2] = req_64bit->sb_len;
|
||||||
}
|
}
|
||||||
|
qseecom.smcinvoke_support = true;
|
||||||
smc_id = TZ_OS_REGISTER_LISTENER_SMCINVOKE_ID;
|
smc_id = TZ_OS_REGISTER_LISTENER_SMCINVOKE_ID;
|
||||||
__qseecom_reentrancy_check_if_no_app_blocked(smc_id);
|
__qseecom_reentrancy_check_if_no_app_blocked(smc_id);
|
||||||
ret = scm_call2(smc_id, &desc);
|
ret = scm_call2(smc_id, &desc);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
|
qseecom.smcinvoke_support = false;
|
||||||
smc_id = TZ_OS_REGISTER_LISTENER_ID;
|
smc_id = TZ_OS_REGISTER_LISTENER_ID;
|
||||||
__qseecom_reentrancy_check_if_no_app_blocked(
|
__qseecom_reentrancy_check_if_no_app_blocked(
|
||||||
smc_id);
|
smc_id);
|
||||||
|
@ -1006,10 +1009,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 =
|
||||||
(struct qseecom_continue_blocked_request_ireq *)
|
(struct qseecom_continue_blocked_request_ireq *)
|
||||||
req_buf;
|
req_buf;
|
||||||
smc_id = TZ_OS_CONTINUE_BLOCKED_REQUEST_ID;
|
if (qseecom.smcinvoke_support)
|
||||||
|
smc_id =
|
||||||
|
TZ_OS_CONTINUE_BLOCKED_REQUEST_SMCINVOKE_ID;
|
||||||
|
else
|
||||||
|
smc_id = TZ_OS_CONTINUE_BLOCKED_REQUEST_ID;
|
||||||
desc.arginfo =
|
desc.arginfo =
|
||||||
TZ_OS_CONTINUE_BLOCKED_REQUEST_ID_PARAM_ID;
|
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);
|
ret = scm_call2(smc_id, &desc);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -1839,7 +1846,7 @@ static int __qseecom_process_incomplete_cmd(struct qseecom_dev_handle *data,
|
||||||
return ret;
|
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_command_scm_resp *resp,
|
||||||
struct qseecom_registered_app_list *ptr_app,
|
struct qseecom_registered_app_list *ptr_app,
|
||||||
struct qseecom_dev_handle *data)
|
struct qseecom_dev_handle *data)
|
||||||
|
@ -1848,9 +1855,8 @@ int __qseecom_process_reentrancy_blocked_on_listener(
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
struct qseecom_continue_blocked_request_ireq ireq;
|
struct qseecom_continue_blocked_request_ireq ireq;
|
||||||
struct qseecom_command_scm_resp continue_resp;
|
struct qseecom_command_scm_resp continue_resp;
|
||||||
sigset_t new_sigset, old_sigset;
|
|
||||||
unsigned long flags;
|
|
||||||
bool found_app = false;
|
bool found_app = false;
|
||||||
|
unsigned long flags;
|
||||||
|
|
||||||
if (!resp || !data) {
|
if (!resp || !data) {
|
||||||
pr_err("invalid resp or data pointer\n");
|
pr_err("invalid resp or data pointer\n");
|
||||||
|
@ -1890,32 +1896,30 @@ int __qseecom_process_reentrancy_blocked_on_listener(
|
||||||
pr_debug("lsntr %d in_use = %d\n",
|
pr_debug("lsntr %d in_use = %d\n",
|
||||||
resp->data, list_ptr->listener_in_use);
|
resp->data, list_ptr->listener_in_use);
|
||||||
ptr_app->blocked_on_listener_id = resp->data;
|
ptr_app->blocked_on_listener_id = resp->data;
|
||||||
|
|
||||||
/* sleep until listener is available */
|
/* sleep until listener is available */
|
||||||
do {
|
qseecom.app_block_ref_cnt++;
|
||||||
qseecom.app_block_ref_cnt++;
|
ptr_app->app_blocked = true;
|
||||||
ptr_app->app_blocked = true;
|
mutex_unlock(&app_access_lock);
|
||||||
sigfillset(&new_sigset);
|
if (wait_event_freezable(
|
||||||
sigprocmask(SIG_SETMASK, &new_sigset, &old_sigset);
|
list_ptr->listener_block_app_wq,
|
||||||
mutex_unlock(&app_access_lock);
|
!list_ptr->listener_in_use)) {
|
||||||
do {
|
pr_err("Interrupted: listener_id %d, app_id %d\n",
|
||||||
if (!wait_event_freezable(
|
resp->data, ptr_app->app_id);
|
||||||
list_ptr->listener_block_app_wq,
|
ret = -ERESTARTSYS;
|
||||||
!list_ptr->listener_in_use)) {
|
goto exit;
|
||||||
break;
|
}
|
||||||
}
|
mutex_lock(&app_access_lock);
|
||||||
} while (1);
|
ptr_app->app_blocked = false;
|
||||||
mutex_lock(&app_access_lock);
|
qseecom.app_block_ref_cnt--;
|
||||||
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;
|
ptr_app->blocked_on_listener_id = 0;
|
||||||
/* notify the blocked app that listener is available */
|
/* notify the blocked app that listener is available */
|
||||||
pr_warn("Lsntr %d is available, unblock app(%d) %s in TZ\n",
|
pr_warn("Lsntr %d is available, unblock app(%d) %s in TZ\n",
|
||||||
resp->data, data->client.app_id,
|
resp->data, data->client.app_id,
|
||||||
data->client.app_name);
|
data->client.app_name);
|
||||||
ireq.qsee_cmd_id = QSEOS_CONTINUE_BLOCKED_REQ_COMMAND;
|
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,
|
ret = qseecom_scm_call(SCM_SVC_TZSCHEDULER, 1,
|
||||||
&ireq, sizeof(ireq),
|
&ireq, sizeof(ireq),
|
||||||
&continue_resp, sizeof(continue_resp));
|
&continue_resp, sizeof(continue_resp));
|
||||||
|
@ -1934,6 +1938,73 @@ exit:
|
||||||
return ret;
|
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(
|
static int __qseecom_reentrancy_process_incomplete_cmd(
|
||||||
struct qseecom_dev_handle *data,
|
struct qseecom_dev_handle *data,
|
||||||
struct qseecom_command_scm_resp *resp)
|
struct qseecom_command_scm_resp *resp)
|
||||||
|
@ -4699,18 +4770,15 @@ int qseecom_process_listener_from_smcinvoke(struct scm_desc *desc)
|
||||||
}
|
}
|
||||||
|
|
||||||
resp.result = desc->ret[0]; /*req_cmd*/
|
resp.result = desc->ret[0]; /*req_cmd*/
|
||||||
resp.resp_type = desc->ret[1]; /*app_id*/
|
resp.resp_type = desc->ret[1]; /*incomplete:unused;blocked:session_id*/
|
||||||
resp.data = desc->ret[2]; /*listener_id*/
|
resp.data = desc->ret[2]; /*listener_id*/
|
||||||
|
|
||||||
dummy_private_data.client.app_id = desc->ret[1];
|
|
||||||
dummy_app_entry.app_id = desc->ret[1];
|
|
||||||
|
|
||||||
mutex_lock(&app_access_lock);
|
mutex_lock(&app_access_lock);
|
||||||
ret = __qseecom_process_reentrancy(&resp, &dummy_app_entry,
|
ret = __qseecom_process_reentrancy(&resp, &dummy_app_entry,
|
||||||
&dummy_private_data);
|
&dummy_private_data);
|
||||||
mutex_unlock(&app_access_lock);
|
mutex_unlock(&app_access_lock);
|
||||||
if (ret)
|
if (ret)
|
||||||
pr_err("Failed to req cmd %d lsnr %d on app %d, ret = %d\n",
|
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[0], (int)desc->ret[2],
|
||||||
(int)desc->ret[1], ret);
|
(int)desc->ret[1], ret);
|
||||||
desc->ret[0] = resp.result;
|
desc->ret[0] = resp.result;
|
||||||
|
|
|
@ -336,7 +336,7 @@ __packed struct qseecom_client_send_fsm_key_req {
|
||||||
|
|
||||||
__packed struct qseecom_continue_blocked_request_ireq {
|
__packed struct qseecom_continue_blocked_request_ireq {
|
||||||
uint32_t qsee_cmd_id;
|
uint32_t qsee_cmd_id;
|
||||||
uint32_t app_id;
|
uint32_t app_or_session_id; /*legacy: app_id; smcinvoke: session_id*/
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -681,6 +681,9 @@ __packed struct qseecom_continue_blocked_request_ireq {
|
||||||
#define TZ_OS_CONTINUE_BLOCKED_REQUEST_ID \
|
#define TZ_OS_CONTINUE_BLOCKED_REQUEST_ID \
|
||||||
TZ_SYSCALL_CREATE_SMC_ID(TZ_OWNER_QSEE_OS, TZ_SVC_LISTENER, 0x04)
|
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 \
|
#define TZ_OS_CONTINUE_BLOCKED_REQUEST_ID_PARAM_ID \
|
||||||
TZ_SYSCALL_CREATE_PARAM_ID_1(TZ_SYSCALL_PARAM_TYPE_VAL)
|
TZ_SYSCALL_CREATE_PARAM_ID_1(TZ_SYSCALL_PARAM_TYPE_VAL)
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue