Loading drivers/soc/qcom/scm_qcpe.c +313 −95 Original line number Diff line number Diff line Loading @@ -10,6 +10,8 @@ * GNU General Public License for more details. */ #define pr_fmt(fmt) "QSEECOM: %s:%d : " fmt, __func__, __LINE__ #include <linux/slab.h> #include <linux/io.h> #include <linux/module.h> Loading @@ -18,7 +20,6 @@ #include <linux/err.h> #include <linux/init.h> #include <linux/delay.h> #include <linux/of.h> #include <asm/cacheflush.h> #include <asm/compiler.h> Loading @@ -30,6 +31,12 @@ #include <linux/habmm.h> #ifdef CONFIG_GHS_VMM #include <../../staging/android/ion/ion_hvenv_driver.h> #include <linux/msm_ion.h> #include <soc/qcom/qseecomi.h> #endif #define SCM_ENOMEM (-5) #define SCM_EOPNOTSUPP (-4) #define SCM_EINVAL_ADDR (-3) Loading Loading @@ -69,6 +76,7 @@ DEFINE_MUTEX(scm_lmh_lock); result = x + y; \ result; \ }) /** * struct scm_command - one SCM command buffer * @len: total available memory for command and response Loading Loading @@ -113,6 +121,19 @@ struct scm_response { u32 is_complete; }; struct scm_extra_arg { union { u32 args32[N_EXT_SCM_ARGS]; u64 args64[N_EXT_SCM_ARGS]; }; }; struct smc_params_s { uint64_t fn_id; uint64_t arginfo; uint64_t args[MAX_SCM_ARGS]; } __packed; #ifdef CONFIG_ARM64 #define R0_STR "x0" Loading Loading @@ -141,6 +162,16 @@ struct scm_response { #endif static enum scm_interface_version { SCM_UNKNOWN, SCM_LEGACY, SCM_ARMV8_32, SCM_ARMV8_64, } scm_version = SCM_UNKNOWN; /* This will be set to specify SMC32 or SMC64 */ static u32 scm_version_mask; /** * scm_command_to_response() - Get a pointer to a scm_response * @cmd: command Loading Loading @@ -195,76 +226,280 @@ static int scm_remap_error(int err) return -EINVAL; } #define MAX_SCM_ARGS 10 #ifdef CONFIG_GHS_VMM enum SCM_QCPE_IONIZE { /* args[0] - physical addr, args[1] - length */ IONIZE_IDX_0, struct qcpe_msg_s { uint64_t fn_id; uint64_t arginfo; uint64_t args[MAX_SCM_ARGS]; /* args[1] - physical addr, args[2] - length */ IONIZE_IDX_1, /* args[0] - physical addr, args[1] - length */ /* args[2] - physical addr, args[3] - length */ IONIZE_IDX_0_2, /* args[2] - physical addr, args[3] - length */ IONIZE_IDX_2, /* args[5] - physical addr, args[6] - length */ IONIZE_IDX_5 }; static struct ion_client *ion_clnt; static int scm_ion_alloc(size_t len, void **vaddr, ion_phys_addr_t *paddr, struct ion_handle **ihandle) { struct ion_handle *ihndl = NULL; void *mvaddr; ion_phys_addr_t mpaddr; int ret = 0; if (!ion_clnt) { ion_clnt = hvenv_ion_client_create("qseecom-kernel"); if (IS_ERR_OR_NULL(ion_clnt)) { pr_err("Ion client cannot be created\n"); return SCM_ENOMEM; } } ihndl = ion_alloc(ion_clnt, len, SZ_4K, ION_HEAP(ION_QSECOM_HEAP_ID), 0); if (IS_ERR_OR_NULL(ihandle)) { pr_err("ION alloc failed\n"); return SCM_ENOMEM; } mvaddr = ion_map_kernel(ion_clnt, ihndl); if (IS_ERR_OR_NULL(mvaddr)) { pr_err("ION memory mapping for image loading failed\n"); ret = SCM_ENOMEM; goto free_ion; } ret = ion_phys(ion_clnt, ihndl, &mpaddr, &len); if (ret) { pr_err("physical memory retrieval failure\n"); ret = SCM_ENOMEM; goto unmap_ion; } *vaddr = mvaddr; *paddr = mpaddr; *ihandle = ihndl; return ret; unmap_ion: ion_unmap_kernel(ion_clnt, ihndl); free_ion: ion_free(ion_clnt, ihndl); return ret; } static int scm_ionize(enum SCM_QCPE_IONIZE idx, u64 *args, struct ion_handle **ihandle) { ion_phys_addr_t ion_paddr; void *krn_vaddr; void *ion_vaddr; size_t len, len1; struct ion_handle *ihndl = NULL; int ret = 0; switch (idx) { case IONIZE_IDX_0: len = (size_t)args[1]; ret = scm_ion_alloc(len, &ion_vaddr, &ion_paddr, &ihndl); if (ret) break; krn_vaddr = phys_to_virt(args[0]); memcpy(ion_vaddr, krn_vaddr, len); args[0] = ion_paddr; break; case IONIZE_IDX_1: len = (size_t)args[2]; ret = scm_ion_alloc(len, &ion_vaddr, &ion_paddr, &ihndl); if (ret) break; krn_vaddr = phys_to_virt(args[1]); memcpy(ion_vaddr, krn_vaddr, len); args[1] = ion_paddr; break; case IONIZE_IDX_0_2: len = (size_t)args[1] + (size_t)args[3]; ret = scm_ion_alloc(len, &ion_vaddr, &ion_paddr, &ihndl); if (ret) break; krn_vaddr = phys_to_virt(args[0]); len = (size_t)args[1]; memcpy(ion_vaddr, krn_vaddr, len); args[0] = ion_paddr; krn_vaddr = phys_to_virt(args[2]); len1 = (size_t)args[3]; memcpy((uint8_t *)ion_vaddr + len, krn_vaddr, len1); args[2] = ion_paddr; break; case IONIZE_IDX_2: len = (size_t)args[3]; ret = scm_ion_alloc(len, &ion_vaddr, &ion_paddr, &ihndl); if (ret) break; krn_vaddr = phys_to_virt(args[2]); memcpy(ion_vaddr, krn_vaddr, len); args[2] = ion_paddr; break; case IONIZE_IDX_5: len = (size_t)args[6]; ret = scm_ion_alloc(len, &ion_vaddr, &ion_paddr, &ihndl); if (ret) break; krn_vaddr = phys_to_virt(args[5]); memcpy(ion_vaddr, krn_vaddr, len); args[5] = ion_paddr; break; default: break; } *ihandle = ihndl; return ret; } static int ionize_buffers(u32 fn_id, struct smc_params_s *desc, struct ion_handle **ihandle) { struct ion_handle *ihndl = NULL; int ret = 0; switch (fn_id) { case TZ_OS_APP_LOOKUP_ID: case TZ_OS_KS_GEN_KEY_ID: case TZ_OS_KS_DEL_KEY_ID: case TZ_OS_KS_SET_PIPE_KEY_ID: case TZ_OS_KS_UPDATE_KEY_ID: ret = scm_ionize(IONIZE_IDX_0, desc->args, &ihndl); break; case TZ_ES_SAVE_PARTITION_HASH_ID: ret = scm_ionize(IONIZE_IDX_1, desc->args, &ihndl); break; case TZ_OS_LISTENER_RESPONSE_HANDLER_WITH_WHITELIST_ID: ret = scm_ionize(IONIZE_IDX_2, desc->args, &ihndl); break; case TZ_APP_QSAPP_SEND_DATA_WITH_WHITELIST_ID: case TZ_APP_GPAPP_OPEN_SESSION_WITH_WHITELIST_ID: case TZ_APP_GPAPP_INVOKE_COMMAND_WITH_WHITELIST_ID: ret = scm_ionize(IONIZE_IDX_5, desc->args, &ihndl); break; default: break; } *ihandle = ihndl; return ret; } static void free_ion_buffers(struct ion_handle *ihandle) { ion_free(ion_clnt, ihandle); } #endif static int scm_call_qcpe(u32 fn_id, struct scm_desc *desc) { static bool opened; static u32 handle; u32 ret; u32 size_bytes; struct qcpe_msg_s msg; int i; uint64_t arglen = desc->arginfo & 0xf; struct smc_params_s smc_params = {0,}; int ret; #ifdef CONFIG_GHS_VMM struct ion_handle *ihandle = NULL; #endif pr_info("scm_call_qcpe: IN: 0x%x, 0x%x, 0x%llx, 0x%llx, 0x%llx, 0x%llx, 0x%llx, 0x%llx, 0x%llx", pr_info("\nscm_call_qcpe: IN: 0x%x, 0x%x, 0x%llx, 0x%llx, 0x%llx, 0x%llx, 0x%llx\n", fn_id, desc->arginfo, desc->args[0], desc->args[1], desc->args[2], desc->args[3], desc->args[4], desc->args[5], desc->args[6]); desc->args[2], desc->args[3], desc->x5); if (!opened) { ret = habmm_socket_open(&handle, MM_QCPE_VM1, 0, 0); if (ret) { pr_err("scm_call_qcpe: habmm_socket_open failed with ret = %d", pr_err( "scm_call_qcpe: habmm_socket_open failed with ret = %d", ret); return ret; } opened = true; } msg.fn_id = fn_id | 0x40000000; /* SMC64_MASK */ msg.arginfo = desc->arginfo; msg.args[0] = desc->args[0]; msg.args[1] = desc->args[1]; msg.args[2] = desc->args[2]; msg.args[3] = desc->x5; msg.args[4] = 0; smc_params.fn_id = fn_id | scm_version_mask; smc_params.arginfo = desc->arginfo; smc_params.args[0] = desc->args[0]; smc_params.args[1] = desc->args[1]; smc_params.args[2] = desc->args[2]; ret = habmm_socket_send(handle, &msg, sizeof(msg), 0); if (ret) { pr_err("scm_call_qcpe: habmm_socket_send failed with ret = %d", ret); return ret; } #ifdef CONFIG_GHS_VMM if (arglen <= N_REGISTER_ARGS) { smc_params.args[FIRST_EXT_ARG_IDX] = desc->x5; } else { struct scm_extra_arg *argbuf = (struct scm_extra_arg *)desc->extra_arg_buf; int j = 0; size_bytes = sizeof(msg); memset(&msg, 0x0, sizeof(msg)); if (scm_version == SCM_ARMV8_64) for (i = FIRST_EXT_ARG_IDX; i < MAX_SCM_ARGS; i++) smc_params.args[i] = argbuf->args64[j++]; else for (i = FIRST_EXT_ARG_IDX; i < MAX_SCM_ARGS; i++) smc_params.args[i] = argbuf->args32[j++]; } ret = habmm_socket_recv(handle, &msg, &size_bytes, 0, 0); if (ret) { pr_err("scm_call_qcpe: habmm_socket_recv failed with ret = %d", ret); ret = ionize_buffers(fn_id & (~SMC64_MASK), &smc_params, &ihandle); if (ret) return ret; } #else smc_params.args[3] = desc->x5; smc_params.args[4] = 0; #endif if (size_bytes != sizeof(msg)) { pr_err("scm_call_qcpe: expected size: %lu, actual=%u\n", sizeof(msg), size_bytes); return SCM_ERROR; } ret = habmm_socket_send(handle, &smc_params, sizeof(smc_params), 0); if (ret) goto err_ret; desc->ret[0] = msg.args[1]; desc->ret[1] = msg.args[2]; desc->ret[2] = msg.args[3]; size_bytes = sizeof(smc_params); memset(&smc_params, 0x0, sizeof(smc_params)); pr_info("scm_call_qcpe: OUT: 0x%llx, 0x%llx, 0x%llx, 0x%llx", msg.args[0], msg.args[1], msg.args[2], msg.args[3]); ret = habmm_socket_recv(handle, &smc_params, &size_bytes, 0, 0); if (ret) goto err_ret; if (size_bytes != sizeof(smc_params)) { pr_err("scm_call_qcpe: expected size: %lu, actual=%u\n", sizeof(smc_params), size_bytes); ret = SCM_ERROR; goto err_ret; } return msg.args[0]; desc->ret[0] = smc_params.args[1]; desc->ret[1] = smc_params.args[2]; desc->ret[2] = smc_params.args[3]; ret = smc_params.args[0]; pr_info("\nscm_call_qcpe: OUT: 0x%llx, 0x%llx, 0x%llx, 0x%llx", smc_params.args[0], desc->ret[0], desc->ret[1], desc->ret[2]); err_ret: #ifdef CONFIG_GHS_VMM if (ihandle) free_ion_buffers(ihandle); #endif return ret; } static u32 smc(u32 cmd_addr) Loading Loading @@ -452,23 +687,6 @@ int scm_call_noalloc(u32 svc_id, u32 cmd_id, const void *cmd_buf, } struct scm_extra_arg { union { u32 args32[N_EXT_SCM_ARGS]; u64 args64[N_EXT_SCM_ARGS]; }; }; static enum scm_interface_version { SCM_UNKNOWN, SCM_LEGACY, SCM_ARMV8_32, SCM_ARMV8_64, } scm_version = SCM_UNKNOWN; /* This will be set to specify SMC32 or SMC64 */ static u32 scm_version_mask; bool is_scm_armv8(void) { int ret; Loading Loading
drivers/soc/qcom/scm_qcpe.c +313 −95 Original line number Diff line number Diff line Loading @@ -10,6 +10,8 @@ * GNU General Public License for more details. */ #define pr_fmt(fmt) "QSEECOM: %s:%d : " fmt, __func__, __LINE__ #include <linux/slab.h> #include <linux/io.h> #include <linux/module.h> Loading @@ -18,7 +20,6 @@ #include <linux/err.h> #include <linux/init.h> #include <linux/delay.h> #include <linux/of.h> #include <asm/cacheflush.h> #include <asm/compiler.h> Loading @@ -30,6 +31,12 @@ #include <linux/habmm.h> #ifdef CONFIG_GHS_VMM #include <../../staging/android/ion/ion_hvenv_driver.h> #include <linux/msm_ion.h> #include <soc/qcom/qseecomi.h> #endif #define SCM_ENOMEM (-5) #define SCM_EOPNOTSUPP (-4) #define SCM_EINVAL_ADDR (-3) Loading Loading @@ -69,6 +76,7 @@ DEFINE_MUTEX(scm_lmh_lock); result = x + y; \ result; \ }) /** * struct scm_command - one SCM command buffer * @len: total available memory for command and response Loading Loading @@ -113,6 +121,19 @@ struct scm_response { u32 is_complete; }; struct scm_extra_arg { union { u32 args32[N_EXT_SCM_ARGS]; u64 args64[N_EXT_SCM_ARGS]; }; }; struct smc_params_s { uint64_t fn_id; uint64_t arginfo; uint64_t args[MAX_SCM_ARGS]; } __packed; #ifdef CONFIG_ARM64 #define R0_STR "x0" Loading Loading @@ -141,6 +162,16 @@ struct scm_response { #endif static enum scm_interface_version { SCM_UNKNOWN, SCM_LEGACY, SCM_ARMV8_32, SCM_ARMV8_64, } scm_version = SCM_UNKNOWN; /* This will be set to specify SMC32 or SMC64 */ static u32 scm_version_mask; /** * scm_command_to_response() - Get a pointer to a scm_response * @cmd: command Loading Loading @@ -195,76 +226,280 @@ static int scm_remap_error(int err) return -EINVAL; } #define MAX_SCM_ARGS 10 #ifdef CONFIG_GHS_VMM enum SCM_QCPE_IONIZE { /* args[0] - physical addr, args[1] - length */ IONIZE_IDX_0, struct qcpe_msg_s { uint64_t fn_id; uint64_t arginfo; uint64_t args[MAX_SCM_ARGS]; /* args[1] - physical addr, args[2] - length */ IONIZE_IDX_1, /* args[0] - physical addr, args[1] - length */ /* args[2] - physical addr, args[3] - length */ IONIZE_IDX_0_2, /* args[2] - physical addr, args[3] - length */ IONIZE_IDX_2, /* args[5] - physical addr, args[6] - length */ IONIZE_IDX_5 }; static struct ion_client *ion_clnt; static int scm_ion_alloc(size_t len, void **vaddr, ion_phys_addr_t *paddr, struct ion_handle **ihandle) { struct ion_handle *ihndl = NULL; void *mvaddr; ion_phys_addr_t mpaddr; int ret = 0; if (!ion_clnt) { ion_clnt = hvenv_ion_client_create("qseecom-kernel"); if (IS_ERR_OR_NULL(ion_clnt)) { pr_err("Ion client cannot be created\n"); return SCM_ENOMEM; } } ihndl = ion_alloc(ion_clnt, len, SZ_4K, ION_HEAP(ION_QSECOM_HEAP_ID), 0); if (IS_ERR_OR_NULL(ihandle)) { pr_err("ION alloc failed\n"); return SCM_ENOMEM; } mvaddr = ion_map_kernel(ion_clnt, ihndl); if (IS_ERR_OR_NULL(mvaddr)) { pr_err("ION memory mapping for image loading failed\n"); ret = SCM_ENOMEM; goto free_ion; } ret = ion_phys(ion_clnt, ihndl, &mpaddr, &len); if (ret) { pr_err("physical memory retrieval failure\n"); ret = SCM_ENOMEM; goto unmap_ion; } *vaddr = mvaddr; *paddr = mpaddr; *ihandle = ihndl; return ret; unmap_ion: ion_unmap_kernel(ion_clnt, ihndl); free_ion: ion_free(ion_clnt, ihndl); return ret; } static int scm_ionize(enum SCM_QCPE_IONIZE idx, u64 *args, struct ion_handle **ihandle) { ion_phys_addr_t ion_paddr; void *krn_vaddr; void *ion_vaddr; size_t len, len1; struct ion_handle *ihndl = NULL; int ret = 0; switch (idx) { case IONIZE_IDX_0: len = (size_t)args[1]; ret = scm_ion_alloc(len, &ion_vaddr, &ion_paddr, &ihndl); if (ret) break; krn_vaddr = phys_to_virt(args[0]); memcpy(ion_vaddr, krn_vaddr, len); args[0] = ion_paddr; break; case IONIZE_IDX_1: len = (size_t)args[2]; ret = scm_ion_alloc(len, &ion_vaddr, &ion_paddr, &ihndl); if (ret) break; krn_vaddr = phys_to_virt(args[1]); memcpy(ion_vaddr, krn_vaddr, len); args[1] = ion_paddr; break; case IONIZE_IDX_0_2: len = (size_t)args[1] + (size_t)args[3]; ret = scm_ion_alloc(len, &ion_vaddr, &ion_paddr, &ihndl); if (ret) break; krn_vaddr = phys_to_virt(args[0]); len = (size_t)args[1]; memcpy(ion_vaddr, krn_vaddr, len); args[0] = ion_paddr; krn_vaddr = phys_to_virt(args[2]); len1 = (size_t)args[3]; memcpy((uint8_t *)ion_vaddr + len, krn_vaddr, len1); args[2] = ion_paddr; break; case IONIZE_IDX_2: len = (size_t)args[3]; ret = scm_ion_alloc(len, &ion_vaddr, &ion_paddr, &ihndl); if (ret) break; krn_vaddr = phys_to_virt(args[2]); memcpy(ion_vaddr, krn_vaddr, len); args[2] = ion_paddr; break; case IONIZE_IDX_5: len = (size_t)args[6]; ret = scm_ion_alloc(len, &ion_vaddr, &ion_paddr, &ihndl); if (ret) break; krn_vaddr = phys_to_virt(args[5]); memcpy(ion_vaddr, krn_vaddr, len); args[5] = ion_paddr; break; default: break; } *ihandle = ihndl; return ret; } static int ionize_buffers(u32 fn_id, struct smc_params_s *desc, struct ion_handle **ihandle) { struct ion_handle *ihndl = NULL; int ret = 0; switch (fn_id) { case TZ_OS_APP_LOOKUP_ID: case TZ_OS_KS_GEN_KEY_ID: case TZ_OS_KS_DEL_KEY_ID: case TZ_OS_KS_SET_PIPE_KEY_ID: case TZ_OS_KS_UPDATE_KEY_ID: ret = scm_ionize(IONIZE_IDX_0, desc->args, &ihndl); break; case TZ_ES_SAVE_PARTITION_HASH_ID: ret = scm_ionize(IONIZE_IDX_1, desc->args, &ihndl); break; case TZ_OS_LISTENER_RESPONSE_HANDLER_WITH_WHITELIST_ID: ret = scm_ionize(IONIZE_IDX_2, desc->args, &ihndl); break; case TZ_APP_QSAPP_SEND_DATA_WITH_WHITELIST_ID: case TZ_APP_GPAPP_OPEN_SESSION_WITH_WHITELIST_ID: case TZ_APP_GPAPP_INVOKE_COMMAND_WITH_WHITELIST_ID: ret = scm_ionize(IONIZE_IDX_5, desc->args, &ihndl); break; default: break; } *ihandle = ihndl; return ret; } static void free_ion_buffers(struct ion_handle *ihandle) { ion_free(ion_clnt, ihandle); } #endif static int scm_call_qcpe(u32 fn_id, struct scm_desc *desc) { static bool opened; static u32 handle; u32 ret; u32 size_bytes; struct qcpe_msg_s msg; int i; uint64_t arglen = desc->arginfo & 0xf; struct smc_params_s smc_params = {0,}; int ret; #ifdef CONFIG_GHS_VMM struct ion_handle *ihandle = NULL; #endif pr_info("scm_call_qcpe: IN: 0x%x, 0x%x, 0x%llx, 0x%llx, 0x%llx, 0x%llx, 0x%llx, 0x%llx, 0x%llx", pr_info("\nscm_call_qcpe: IN: 0x%x, 0x%x, 0x%llx, 0x%llx, 0x%llx, 0x%llx, 0x%llx\n", fn_id, desc->arginfo, desc->args[0], desc->args[1], desc->args[2], desc->args[3], desc->args[4], desc->args[5], desc->args[6]); desc->args[2], desc->args[3], desc->x5); if (!opened) { ret = habmm_socket_open(&handle, MM_QCPE_VM1, 0, 0); if (ret) { pr_err("scm_call_qcpe: habmm_socket_open failed with ret = %d", pr_err( "scm_call_qcpe: habmm_socket_open failed with ret = %d", ret); return ret; } opened = true; } msg.fn_id = fn_id | 0x40000000; /* SMC64_MASK */ msg.arginfo = desc->arginfo; msg.args[0] = desc->args[0]; msg.args[1] = desc->args[1]; msg.args[2] = desc->args[2]; msg.args[3] = desc->x5; msg.args[4] = 0; smc_params.fn_id = fn_id | scm_version_mask; smc_params.arginfo = desc->arginfo; smc_params.args[0] = desc->args[0]; smc_params.args[1] = desc->args[1]; smc_params.args[2] = desc->args[2]; ret = habmm_socket_send(handle, &msg, sizeof(msg), 0); if (ret) { pr_err("scm_call_qcpe: habmm_socket_send failed with ret = %d", ret); return ret; } #ifdef CONFIG_GHS_VMM if (arglen <= N_REGISTER_ARGS) { smc_params.args[FIRST_EXT_ARG_IDX] = desc->x5; } else { struct scm_extra_arg *argbuf = (struct scm_extra_arg *)desc->extra_arg_buf; int j = 0; size_bytes = sizeof(msg); memset(&msg, 0x0, sizeof(msg)); if (scm_version == SCM_ARMV8_64) for (i = FIRST_EXT_ARG_IDX; i < MAX_SCM_ARGS; i++) smc_params.args[i] = argbuf->args64[j++]; else for (i = FIRST_EXT_ARG_IDX; i < MAX_SCM_ARGS; i++) smc_params.args[i] = argbuf->args32[j++]; } ret = habmm_socket_recv(handle, &msg, &size_bytes, 0, 0); if (ret) { pr_err("scm_call_qcpe: habmm_socket_recv failed with ret = %d", ret); ret = ionize_buffers(fn_id & (~SMC64_MASK), &smc_params, &ihandle); if (ret) return ret; } #else smc_params.args[3] = desc->x5; smc_params.args[4] = 0; #endif if (size_bytes != sizeof(msg)) { pr_err("scm_call_qcpe: expected size: %lu, actual=%u\n", sizeof(msg), size_bytes); return SCM_ERROR; } ret = habmm_socket_send(handle, &smc_params, sizeof(smc_params), 0); if (ret) goto err_ret; desc->ret[0] = msg.args[1]; desc->ret[1] = msg.args[2]; desc->ret[2] = msg.args[3]; size_bytes = sizeof(smc_params); memset(&smc_params, 0x0, sizeof(smc_params)); pr_info("scm_call_qcpe: OUT: 0x%llx, 0x%llx, 0x%llx, 0x%llx", msg.args[0], msg.args[1], msg.args[2], msg.args[3]); ret = habmm_socket_recv(handle, &smc_params, &size_bytes, 0, 0); if (ret) goto err_ret; if (size_bytes != sizeof(smc_params)) { pr_err("scm_call_qcpe: expected size: %lu, actual=%u\n", sizeof(smc_params), size_bytes); ret = SCM_ERROR; goto err_ret; } return msg.args[0]; desc->ret[0] = smc_params.args[1]; desc->ret[1] = smc_params.args[2]; desc->ret[2] = smc_params.args[3]; ret = smc_params.args[0]; pr_info("\nscm_call_qcpe: OUT: 0x%llx, 0x%llx, 0x%llx, 0x%llx", smc_params.args[0], desc->ret[0], desc->ret[1], desc->ret[2]); err_ret: #ifdef CONFIG_GHS_VMM if (ihandle) free_ion_buffers(ihandle); #endif return ret; } static u32 smc(u32 cmd_addr) Loading Loading @@ -452,23 +687,6 @@ int scm_call_noalloc(u32 svc_id, u32 cmd_id, const void *cmd_buf, } struct scm_extra_arg { union { u32 args32[N_EXT_SCM_ARGS]; u64 args64[N_EXT_SCM_ARGS]; }; }; static enum scm_interface_version { SCM_UNKNOWN, SCM_LEGACY, SCM_ARMV8_32, SCM_ARMV8_64, } scm_version = SCM_UNKNOWN; /* This will be set to specify SMC32 or SMC64 */ static u32 scm_version_mask; bool is_scm_armv8(void) { int ret; Loading