From b6e110d2d09fe31f2525fd36067cf629bad5cfde Mon Sep 17 00:00:00 2001 From: Siddharth Gupta Date: Mon, 30 Sep 2019 16:08:05 -0700 Subject: [PATCH] soc: qcom: Migrate SCM calls in qtee_shmbridge Adding APIs to create, delete, and enable shmbridge. Migrating SCM calls in qtee_shmbridge to use the new APIs. Change-Id: I038e7950d11cbf6bb38a8824a576f2d92f879454 Signed-off-by: Siddharth Gupta Signed-off-by: Elliot Berman --- drivers/firmware/qcom_scm-smc.c | 63 ++++++++++++++++++++++ drivers/firmware/qcom_scm.c | 22 ++++++++ drivers/firmware/qcom_scm.h | 8 +++ drivers/firmware/qtee_shmbridge.c | 89 ++++++++++--------------------- include/linux/qcom_scm.h | 10 ++++ 5 files changed, 130 insertions(+), 62 deletions(-) diff --git a/drivers/firmware/qcom_scm-smc.c b/drivers/firmware/qcom_scm-smc.c index 11cebd03c917..a149857b5a5f 100644 --- a/drivers/firmware/qcom_scm-smc.c +++ b/drivers/firmware/qcom_scm-smc.c @@ -1137,6 +1137,69 @@ int __qcom_scm_kgsl_set_smmu_aperture(struct device *dev, return ret; } +/** + * The following shmbridge functions should be called before the SCM driver + * has been initialized. If not, there could be errors that might cause the + * system to crash. + */ +int __qcom_scm_enable_shm_bridge(struct device *dev) +{ + int ret; + struct qcom_scm_desc desc = { + .svc = QCOM_SCM_SVC_MP, + .cmd = QCOM_SCM_MEMP_SHM_BRIDGE_ENABLE, + .owner = ARM_SMCCC_OWNER_SIP + }; + + ret = qcom_scm_call(dev, &desc); + + return ret ? : desc.res[0]; +} + +int __qcom_scm_delete_shm_bridge(struct device *dev, u64 handle) +{ + int ret; + struct qcom_scm_desc desc = { + .svc = QCOM_SCM_SVC_MP, + .cmd = QCOM_SCM_MEMP_SHM_BRIDGE_DELETE, + .owner = ARM_SMCCC_OWNER_SIP + }; + + desc.args[0] = handle; + desc.arginfo = QCOM_SCM_ARGS(1, QCOM_SCM_VAL); + + ret = qcom_scm_call(dev, &desc); + + return ret; +} + +int __qcom_scm_create_shm_bridge(struct device *dev, u64 pfn_and_ns_perm_flags, + u64 ipfn_and_s_perm_flags, u64 size_and_flags, + u64 ns_vmids, u64 *handle) +{ + int ret; + struct qcom_scm_desc desc = { + .svc = QCOM_SCM_SVC_MP, + .cmd = QCOM_SCM_MEMP_SHM_BRDIGE_CREATE, + .owner = ARM_SMCCC_OWNER_SIP + }; + + desc.args[0] = pfn_and_ns_perm_flags; + desc.args[1] = ipfn_and_s_perm_flags; + desc.args[2] = size_and_flags; + desc.args[3] = ns_vmids; + + desc.arginfo = QCOM_SCM_ARGS(4, QCOM_SCM_VAL, QCOM_SCM_VAL, + QCOM_SCM_VAL, QCOM_SCM_VAL); + + ret = qcom_scm_call(dev, &desc); + + if (handle) + *handle = desc.res[1]; + + return ret ? : desc.res[0]; +} + int __qcom_scm_smmu_prepare_atos_id(struct device *dev, u64 dev_id, int cb_num, int operation) { diff --git a/drivers/firmware/qcom_scm.c b/drivers/firmware/qcom_scm.c index b331b5f45426..63268266b1a5 100644 --- a/drivers/firmware/qcom_scm.c +++ b/drivers/firmware/qcom_scm.c @@ -504,6 +504,28 @@ int qcom_scm_kgsl_set_smmu_aperture(unsigned int num_context_bank) } EXPORT_SYMBOL(qcom_scm_kgsl_set_smmu_aperture); +int qcom_scm_enable_shm_bridge(void) +{ + return __qcom_scm_enable_shm_bridge(__scm ? __scm->dev : NULL); +} +EXPORT_SYMBOL(qcom_scm_enable_shm_bridge); + +int qcom_scm_delete_shm_bridge(u64 handle) +{ + return __qcom_scm_delete_shm_bridge(__scm ? __scm->dev : NULL, handle); +} +EXPORT_SYMBOL(qcom_scm_delete_shm_bridge); + +int qcom_scm_create_shm_bridge(u64 pfn_and_ns_perm_flags, + u64 ipfn_and_s_perm_flags, u64 size_and_flags, u64 ns_vmids, + u64 *handle) +{ + return __qcom_scm_create_shm_bridge(__scm ? __scm->dev : NULL, + pfn_and_ns_perm_flags, ipfn_and_s_perm_flags, + size_and_flags, ns_vmids, handle); +} +EXPORT_SYMBOL(qcom_scm_create_shm_bridge); + int qcom_scm_smmu_prepare_atos_id(u64 dev_id, int cb_num, int operation) { return __qcom_scm_smmu_prepare_atos_id(__scm->dev, dev_id, cb_num, diff --git a/drivers/firmware/qcom_scm.h b/drivers/firmware/qcom_scm.h index 67bb055aa3fa..537e8c7d997b 100644 --- a/drivers/firmware/qcom_scm.h +++ b/drivers/firmware/qcom_scm.h @@ -70,6 +70,9 @@ extern void __qcom_scm_mmu_sync(struct device *dev, bool sync); #define QCOM_SCM_MP_IOMMU_SECURE_UNMAP2_FLAT 0x13 #define QCOM_SCM_MP_ASSIGN 0x16 #define QCOM_SCM_MP_CP_SMMU_APERTURE_ID 0x1b +#define QCOM_SCM_MEMP_SHM_BRIDGE_ENABLE 0x1c +#define QCOM_SCM_MEMP_SHM_BRIDGE_DELETE 0x1d +#define QCOM_SCM_MEMP_SHM_BRDIGE_CREATE 0x1e #define QCOM_SCM_MP_SMMU_PREPARE_ATOS_ID 0x21 extern int __qcom_scm_restore_sec_cfg(struct device *dev, u32 device_id, u32 spare); @@ -96,6 +99,11 @@ extern int __qcom_scm_assign_mem(struct device *dev, phys_addr_t dest, size_t dest_sz); extern int __qcom_scm_kgsl_set_smmu_aperture(struct device *dev, unsigned int num_context_bank); +extern int __qcom_scm_enable_shm_bridge(struct device *dev); +extern int __qcom_scm_delete_shm_bridge(struct device *dev, u64 handle); +extern int __qcom_scm_create_shm_bridge(struct device *dev, + u64 pfn_and_ns_perm_flags, u64 ipfn_and_s_perm_flags, + u64 size_and_flags, u64 ns_vmids, u64 *handle); extern int __qcom_scm_smmu_prepare_atos_id(struct device *dev, u64 dev_id, int cb_num, int operation); #define QCOM_SCM_IOMMU_TLBINVAL_FLAG 0x00000001 diff --git a/drivers/firmware/qtee_shmbridge.c b/drivers/firmware/qtee_shmbridge.c index e24df44e694c..a8c4fbf506f9 100644 --- a/drivers/firmware/qtee_shmbridge.c +++ b/drivers/firmware/qtee_shmbridge.c @@ -11,48 +11,13 @@ #include #include #include -#include +#include #include #include #include "qtee_shmbridge_internal.h" #define DEFAULT_BRIDGE_SIZE SZ_4M /*4M*/ -/* - * tz_enable_shm_bridge - * smc_id: 0x02000C1C - */ -#define TZ_SVC_MEMORY_PROTECTION 12 - -#define TZ_SHM_BRIDGE_ENABLE \ - TZ_SYSCALL_CREATE_SMC_ID(TZ_OWNER_SIP, TZ_SVC_MEMORY_PROTECTION, 0x1C) - -#define TZ_SHM_BRIDGE_ENABLE_PARAM_ID \ - TZ_SYSCALL_CREATE_PARAM_ID_0 - -/* - * tz_create_shm_bridge - * smc_id: 0x02000C1E - */ - -#define TZ_SHM_BRIDGE_CREATE \ - TZ_SYSCALL_CREATE_SMC_ID(TZ_OWNER_SIP, TZ_SVC_MEMORY_PROTECTION, 0x1E) - -#define TZ_SHM_BRIDGE_CREATE_PARAM_ID \ - TZ_SYSCALL_CREATE_PARAM_ID_4( \ - TZ_SYSCALL_PARAM_TYPE_VAL, TZ_SYSCALL_PARAM_TYPE_VAL, \ - TZ_SYSCALL_PARAM_TYPE_VAL, TZ_SYSCALL_PARAM_TYPE_VAL) - -/** - * tz_delete_shm_bridge - * smc_id: 0x02000C1D - */ -#define TZ_SHM_BRIDGE_DELETE \ - TZ_SYSCALL_CREATE_SMC_ID(TZ_OWNER_SIP, TZ_SVC_MEMORY_PROTECTION, 0x1D) - -#define TZ_SHM_BRIDGE_DELETE_PARAM_ID \ - TZ_SYSCALL_CREATE_PARAM_ID_1( \ - TZ_SYSCALL_PARAM_TYPE_VAL) #define MAXSHMVMS 4 #define PERM_BITS 3 @@ -118,7 +83,6 @@ static bool qtee_shmbridge_enabled; static int32_t qtee_shmbridge_enable(bool enable) { int32_t ret = 0; - struct scm_desc desc = {0}; qtee_shmbridge_enabled = false; if (!enable) { @@ -126,14 +90,14 @@ static int32_t qtee_shmbridge_enable(bool enable) return ret; } - desc.arginfo = TZ_SHM_BRIDGE_ENABLE_PARAM_ID; - ret = scm_call2(TZ_SHM_BRIDGE_ENABLE, &desc); - if (ret || desc.ret[0]) { - pr_err("Failed to enable shmbridge, rsp = %lld, ret = %d\n", - desc.ret[0], ret); - if (ret == -EIO || desc.ret[0] == SHMBRIDGE_E_NOT_SUPPORTED) + ret = qcom_scm_enable_shm_bridge(); + + if (ret) { + pr_err("Failed to enable shmbridge, ret = %d\n", ret); + + if (ret == -EIO || ret == SHMBRIDGE_E_NOT_SUPPORTED) pr_warn("shmbridge is not supported by this target\n"); - return ret | desc.ret[0]; + return ret; } qtee_shmbridge_enabled = true; pr_warn("shmbridge is enabled\n"); @@ -210,9 +174,11 @@ int32_t qtee_shmbridge_register( { int32_t ret = 0; + uint64_t pfn_and_ns_perm_flags = 0; + uint64_t ipfn_and_s_perm_flags = 0; + uint64_t size_and_flags = 0; uint64_t ns_perms = 0; uint64_t ns_vmids = 0; - struct scm_desc desc = {0}; int i = 0; if (!qtee_shmbridge_enabled) @@ -234,23 +200,23 @@ int32_t qtee_shmbridge_register( ns_vmids = UPDATE_NS_VMIDS(ns_vmids, ns_vmid_list[i]); } - desc.arginfo = TZ_SHM_BRIDGE_CREATE_PARAM_ID; - desc.args[0] = UPDATE_PFN_AND_NS_PERM_FLAGS(paddr, ns_perms); - desc.args[1] = UPDATE_IPFN_AND_S_PERM_FLAGS(paddr, tz_perm); - desc.args[2] = UPDATE_SIZE_AND_FLAGS(size, ns_vmid_num); - desc.args[3] = ns_vmids; + pfn_and_ns_perm_flags = UPDATE_PFN_AND_NS_PERM_FLAGS(paddr, ns_perms); + ipfn_and_s_perm_flags = UPDATE_IPFN_AND_S_PERM_FLAGS(paddr, tz_perm); + size_and_flags = UPDATE_SIZE_AND_FLAGS(size, ns_vmid_num); - pr_debug("%s: arginfo %x, desc.args[0] %llx, args[1] %llx, args[2] %llx, args[3] %llx\n", - __func__, desc.arginfo, desc.args[0], - desc.args[1], desc.args[2], desc.args[3]); - ret = scm_call2(TZ_SHM_BRIDGE_CREATE, &desc); - if (ret || desc.ret[0]) { - pr_err("create shmbridge failed, ret = %d, status = %llx\n", - ret, desc.ret[0]); + pr_debug("%s: desc.args[0] %llx, args[1] %llx, args[2] %llx, args[3] %llx\n", + __func__, pfn_and_ns_perm_flags, ipfn_and_s_perm_flags, + size_and_flags, ns_vmids); + + ret = qcom_scm_create_shm_bridge(pfn_and_ns_perm_flags, + ipfn_and_s_perm_flags, size_and_flags, ns_vmids, + handle); + + if (ret) { + pr_err("create shmbridge failed, ret = %d\n", ret); ret = -EINVAL; goto exit; } - *handle = desc.ret[1]; ret = qtee_shmbridge_list_add_nolock(paddr, *handle); exit: @@ -263,15 +229,14 @@ EXPORT_SYMBOL(qtee_shmbridge_register); int32_t qtee_shmbridge_deregister(uint64_t handle) { int32_t ret = 0; - struct scm_desc desc = {0}; if (!qtee_shmbridge_enabled) return 0; mutex_lock(&bridge_list_head.lock); - desc.arginfo = TZ_SHM_BRIDGE_DELETE_PARAM_ID; - desc.args[0] = handle; - ret = scm_call2(TZ_SHM_BRIDGE_DELETE, &desc); + + ret = qcom_scm_delete_shm_bridge(handle); + if (ret) { pr_err("Failed to del bridge %lld, ret = %d\n", handle, ret); goto exit; diff --git a/include/linux/qcom_scm.h b/include/linux/qcom_scm.h index be1457df54b7..5f9763e84090 100644 --- a/include/linux/qcom_scm.h +++ b/include/linux/qcom_scm.h @@ -75,6 +75,11 @@ extern int qcom_scm_smmu_prepare_atos_id(u64 dev_id, int cb_num, int operation); extern bool qcom_scm_hdcp_available(void); extern int qcom_scm_hdcp_req(struct qcom_scm_hdcp_req *req, u32 req_cnt, u32 *resp); +extern int qcom_scm_enable_shm_bridge(void); +extern int qcom_scm_delete_shm_bridge(u64 handle); +extern int qcom_scm_create_shm_bridge(u64 pfn_and_ns_perm_flags, + u64 ipfn_and_s_perm_flags, u64 size_and_flags, + u64 ns_vmids, u64 *handle); extern int qcom_scm_smmu_change_pgtbl_format(u64 dev_id, int cbndx); extern int qcom_scm_qsmmu500_wait_safe_toggle(bool en); extern int qcom_scm_ice_restore_cfg(void); @@ -139,6 +144,11 @@ static inline int qcom_scm_smmu_prepare_atos_id(u64 dev_id, int cb_num, static inline bool qcom_scm_hdcp_available(void) { return false; } static inline int qcom_scm_hdcp_req(struct qcom_scm_hdcp_req *req, u32 req_cnt, u32 *resp) { return -ENODEV; } +static inline int qcom_scm_enable_shm_bridge(void) { return -ENODEV; } +static inline int qcom_scm_delete_shm_bridge(u64 handle) { return -ENODEV; } +static inline int qcom_scm_create_shm_bridge(u64 pfn_and_ns_perm_flags, + u64 ipfn_and_s_perm_flags, u64 size_and_flags, + u64 ns_vmids, u64 *handle) { return -ENODEV; } static inline int qcom_scm_smmu_change_pgtbl_format(u64 dev_id, int cbndx) { return -ENODEV; } static inline int qcom_scm_qsmmu500_wait_safe_toggle(bool en)