From e81049289e4c73e53c0ce876f46744ebd7edadef Mon Sep 17 00:00:00 2001 From: quebs2 Date: Fri, 12 Mar 2021 15:39:55 +0800 Subject: [PATCH] Fix instability issue during tbase load in Kernel 5.4 Tbase load was failing intermittently during fc_init() operation in __smc() with error: Trustonic TEE: ERROR -14 __smc: fc_init failed (4dee8000) The root cause has two components 1- qcom_scm_call() needs to be done atomically. Task reschedule was causing a failure. Thus changed to the atomic call qcom_scm_call_atomic(). 2- Qcom scm_call requires cache maintenance. API attests that any buffers that are expected to be accessed by the secure world must be flushed before invoking qcom_scm_call and invalidated in the cache immediately after qcom_scm_call returns. Cache invalidation was missing, hence add it. Change-Id: I83139fc5110eb3af536a30800c994c8e451df1fa Signed-off-by: quebs2 Reviewed-on: https://gerrit.mot.com/1899491 SME-Granted: SME Approvals Granted SLTApproved: Slta Waiver Tested-by: Jira Key Reviewed-by: Zhenxin Xi Submit-Approved: Jira Key --- drivers/firmware/qcom_scm-smc.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/drivers/firmware/qcom_scm-smc.c b/drivers/firmware/qcom_scm-smc.c index b14b6a626a3b..11257612c487 100644 --- a/drivers/firmware/qcom_scm-smc.c +++ b/drivers/firmware/qcom_scm-smc.c @@ -2394,7 +2394,8 @@ int __qcom_scm_invoke_smc(struct device *dev, phys_addr_t in_buf, int __trustonic_smc_fastcall(void *fc_generic, size_t size) { - int ret; + int ret = 0; + struct qcom_scm_desc desc = { .svc = SCM_SVC_MOBICORE, .cmd = SCM_CMD_MOBICORE, @@ -2402,7 +2403,7 @@ int __trustonic_smc_fastcall(void *fc_generic, size_t size) }; void *scm_buf_va = NULL; - phys_addr_t scm_buf_pa; + phys_addr_t scm_buf_pa = 0; struct qtee_shm scm_shm = {0}; if (qtee_shmbridge_is_enabled()) { @@ -2439,9 +2440,9 @@ int __trustonic_smc_fastcall(void *fc_generic, size_t size) desc.args[3] = (u32)size; desc.arginfo = QCOM_SCM_ARGS(4, QCOM_SCM_RW, QCOM_SCM_VAL, QCOM_SCM_RW, QCOM_SCM_VAL); - ret = qcom_scm_call(NULL, &desc); - - qtee_shmbridge_flush_shm_buf(&scm_shm); + ret = qcom_scm_call_atomic(NULL, &desc); + qtee_shmbridge_inv_shm_buf(&scm_shm); + memset(fc_generic, 0x00, size); memcpy(fc_generic, scm_buf_va, size); if (qtee_shmbridge_is_enabled()) {