From df1491d15575b0af72fbf9929b4ba744830c7c67 Mon Sep 17 00:00:00 2001 From: Siddharth Gupta Date: Thu, 10 Oct 2019 13:26:24 -0700 Subject: [PATCH 01/28] msm: kgsl: Migrate SCM calls in kgsl iommu Adding APIs to check if KGSL SMMU is available, and programming the SMMU Aperture size. Migrating SCM calls in the KGSL IOMMU driver. Change-Id: I77178f3e300112fa47a8ca6861acb08d547c9875 Signed-off-by: Siddharth Gupta Signed-off-by: Elliot Berman --- drivers/firmware/qcom_scm-smc.c | 49 +++++++++++++++++++++++++++++++++ drivers/firmware/qcom_scm.c | 27 ++++++++++++++++++ drivers/firmware/qcom_scm.h | 9 ++++++ include/linux/qcom_scm.h | 13 +++++++++ 4 files changed, 98 insertions(+) diff --git a/drivers/firmware/qcom_scm-smc.c b/drivers/firmware/qcom_scm-smc.c index b4b64b925409..3ada61be5311 100644 --- a/drivers/firmware/qcom_scm-smc.c +++ b/drivers/firmware/qcom_scm-smc.c @@ -1008,6 +1008,33 @@ int __qcom_scm_mem_protect_region_id(struct device *dev, phys_addr_t paddr, return ret; } +int __qcom_scm_mem_protect_lock_id2_flat(struct device *dev, + phys_addr_t list_addr, size_t list_size, + size_t chunk_size, size_t memory_usage, + int lock) +{ + int ret; + struct qcom_scm_desc desc = { + .svc = QCOM_SCM_SVC_MP, + .cmd = QCOM_SCM_MP_MEM_PROTECT_LOCK_ID2_FLAT, + .owner = ARM_SMCCC_OWNER_SIP + }; + + desc.args[0] = list_addr; + desc.args[1] = list_size; + desc.args[2] = chunk_size; + desc.args[3] = memory_usage; + desc.args[4] = lock; + desc.args[5] = 0; + + desc.arginfo = QCOM_SCM_ARGS(6, QCOM_SCM_RW, QCOM_SCM_VAL, QCOM_SCM_VAL, + QCOM_SCM_VAL, QCOM_SCM_VAL, QCOM_SCM_VAL); + + ret = qcom_scm_call(dev, &desc); + + return ret; +} + int __qcom_scm_iommu_secure_map(struct device *dev, phys_addr_t sg_list_addr, size_t num_sg, size_t sg_block_size, u64 sec_id, int cbndx, unsigned long iova, size_t total_len) @@ -1088,6 +1115,28 @@ int __qcom_scm_assign_mem(struct device *dev, phys_addr_t mem_region, return ret ? : desc.res[0]; } +int __qcom_scm_kgsl_set_smmu_aperture(struct device *dev, + unsigned int num_context_bank) +{ + int ret; + struct qcom_scm_desc desc = { + .svc = QCOM_SCM_SVC_MP, + .cmd = QCOM_SCM_MP_CP_SMMU_APERTURE_ID, + .owner = ARM_SMCCC_OWNER_SIP + }; + + desc.args[0] = 0xffff0000 | ((QCOM_SCM_CP_APERTURE_REG & 0xff) << 8) | + (num_context_bank & 0xff); + desc.args[1] = 0xffffffff; + desc.args[2] = 0xffffffff; + desc.args[3] = 0xffffffff; + desc.arginfo = QCOM_SCM_ARGS(4); + + ret = qcom_scm_call(dev, &desc); + + return ret; +} + int __qcom_scm_hdcp_req(struct device *dev, struct qcom_scm_hdcp_req *req, u32 req_cnt, u32 *resp) { diff --git a/drivers/firmware/qcom_scm.c b/drivers/firmware/qcom_scm.c index 1eab6f19fc6d..58a5d435fada 100644 --- a/drivers/firmware/qcom_scm.c +++ b/drivers/firmware/qcom_scm.c @@ -378,6 +378,15 @@ int qcom_scm_mem_protect_region_id(phys_addr_t paddr, size_t size) } EXPORT_SYMBOL(qcom_scm_mem_protect_region_id); +int qcom_scm_mem_protect_lock_id2_flat(phys_addr_t list_addr, + size_t list_size, size_t chunk_size, + size_t memory_usage, int lock) +{ + return __qcom_scm_mem_protect_lock_id2_flat(__scm->dev, list_addr, + list_size, chunk_size, memory_usage, lock); +} +EXPORT_SYMBOL(qcom_scm_mem_protect_lock_id2_flat); + int qcom_scm_iommu_secure_map(phys_addr_t sg_list_addr, size_t num_sg, size_t sg_block_size, u64 sec_id, int cbndx, unsigned long iova, size_t total_len) @@ -477,6 +486,24 @@ int qcom_scm_assign_mem(phys_addr_t mem_addr, size_t mem_sz, } EXPORT_SYMBOL(qcom_scm_assign_mem); +bool qcom_scm_kgsl_set_smmu_aperture_available(void) +{ + int ret; + + ret = __qcom_scm_is_call_available(__scm->dev, QCOM_SCM_SVC_MP, + QCOM_SCM_MP_CP_SMMU_APERTURE_ID); + + return ret > 0; +} +EXPORT_SYMBOL(qcom_scm_kgsl_set_smmu_aperture_available); + +int qcom_scm_kgsl_set_smmu_aperture(unsigned int num_context_bank) +{ + return __qcom_scm_kgsl_set_smmu_aperture(__scm->dev, + num_context_bank); +} +EXPORT_SYMBOL(qcom_scm_kgsl_set_smmu_aperture); + /** * qcom_scm_hdcp_available() - Check if secure environment supports HDCP. * diff --git a/drivers/firmware/qcom_scm.h b/drivers/firmware/qcom_scm.h index 47c8b8f8174b..46e5bd640bb7 100644 --- a/drivers/firmware/qcom_scm.h +++ b/drivers/firmware/qcom_scm.h @@ -65,9 +65,11 @@ extern void __qcom_scm_mmu_sync(struct device *dev, bool sync); #define QCOM_SCM_MP_IOMMU_SECURE_PTBL_SIZE 0x03 #define QCOM_SCM_MP_IOMMU_SECURE_PTBL_INIT 0x04 #define QCOM_SCM_MP_MEM_PROTECT_REGION_ID 0x10 +#define QCOM_SCM_MP_MEM_PROTECT_LOCK_ID2_FLAT 0x11 #define QCOM_SCM_MP_IOMMU_SECURE_MAP2_FLAT 0x12 #define QCOM_SCM_MP_IOMMU_SECURE_UNMAP2_FLAT 0x13 #define QCOM_SCM_MP_ASSIGN 0x16 +#define QCOM_SCM_MP_CP_SMMU_APERTURE_ID 0x1b extern int __qcom_scm_restore_sec_cfg(struct device *dev, u32 device_id, u32 spare); extern int __qcom_scm_iommu_secure_ptbl_size(struct device *dev, u32 spare, @@ -76,6 +78,10 @@ extern int __qcom_scm_iommu_secure_ptbl_init(struct device *dev, u64 addr, u32 size, u32 spare); extern int __qcom_scm_mem_protect_region_id(struct device *dev, phys_addr_t paddr, size_t size); +extern int __qcom_scm_mem_protect_lock_id2_flat(struct device *dev, + phys_addr_t list_addr, size_t list_size, + size_t chunk_size, size_t memory_usage, + int lock); extern int __qcom_scm_iommu_secure_map(struct device *dev, phys_addr_t sg_list_addr, size_t num_sg, size_t sg_block_size, u64 sec_id, int cbndx, @@ -87,7 +93,10 @@ extern int __qcom_scm_assign_mem(struct device *dev, phys_addr_t mem_region, size_t mem_sz, phys_addr_t src, size_t src_sz, phys_addr_t dest, size_t dest_sz); +extern int __qcom_scm_kgsl_set_smmu_aperture(struct device *dev, + unsigned int num_context_bank); #define QCOM_SCM_IOMMU_TLBINVAL_FLAG 0x00000001 +#define QCOM_SCM_CP_APERTURE_REG 0x0 #define QCOM_SCM_SVC_HDCP 0x11 #define QCOM_SCM_HDCP_INVOKE 0x01 diff --git a/include/linux/qcom_scm.h b/include/linux/qcom_scm.h index ea3ca01baad6..a3aead9fedf9 100644 --- a/include/linux/qcom_scm.h +++ b/include/linux/qcom_scm.h @@ -56,6 +56,9 @@ extern int qcom_scm_restore_sec_cfg(u32 device_id, u32 spare); extern int qcom_scm_iommu_secure_ptbl_size(u32 spare, size_t *size); extern int qcom_scm_iommu_secure_ptbl_init(u64 addr, u32 size, u32 spare); extern int qcom_scm_mem_protect_region_id(phys_addr_t paddr, size_t size); +extern int qcom_scm_mem_protect_lock_id2_flat(phys_addr_t list_addr, + size_t list_size, size_t chunk_size, + size_t memory_usage, int lock); extern int qcom_scm_iommu_secure_map(phys_addr_t sg_list_addr, size_t num_sg, size_t sg_block_size, u64 sec_id, int cbndx, unsigned long iova, size_t total_len); @@ -65,6 +68,9 @@ extern int qcom_scm_assign_mem(phys_addr_t mem_addr, size_t mem_sz, unsigned int *src, const struct qcom_scm_vmperm *newvm, unsigned int dest_cnt); +extern bool qcom_scm_kgsl_set_smmu_aperture_available(void); +extern int qcom_scm_kgsl_set_smmu_aperture( + unsigned int num_context_bank); extern bool qcom_scm_hdcp_available(void); extern int qcom_scm_hdcp_req(struct qcom_scm_hdcp_req *req, u32 req_cnt, u32 *resp); @@ -110,6 +116,9 @@ static inline int qcom_scm_iommu_secure_ptbl_init(u64 addr, u32 size, u32 spare) { return -ENODEV; } static inline int qcom_scm_mem_protect_region_id(phys_addr_t paddr, size_t size) { return -ENODEV; } +static inline int qcom_scm_mem_protect_lock_id2_flat(phys_addr_t list_addr, + size_t list_size, size_t chunk_size, size_t memory_usage, + int lock) { return -ENODEV; } static inline int qcom_scm_iommu_secure_map(phys_addr_t sg_list_addr, size_t num_sg, size_t sg_block_size, u64 sec_id, int cbndx, unsigned long iova, size_t total_len) { return -ENODEV; } @@ -119,6 +128,10 @@ static inline int qcom_scm_assign_mem(phys_addr_t mem_addr, size_t mem_sz, unsigned int *src, const struct qcom_scm_vmperm *newvm, unsigned int dest_cnt) { return -ENODEV; } +static inline bool qcom_scm_kgsl_set_smmu_aperture_available(void) + { return false; } +static inline int qcom_scm_kgsl_set_smmu_aperture( + unsigned int num_context_bank) { return -ENODEV; } 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; } From 49ec350a86101181beb31be39b10cb7fcbcce02a Mon Sep 17 00:00:00 2001 From: Siddharth Gupta Date: Mon, 30 Sep 2019 15:50:28 -0700 Subject: [PATCH 02/28] soc: qcom: Migrate SCM calls in msm_tz_smmu Adding APIs to change smmu pagetable format, and to prepare atos id. Migrating SCM calls in msm_tz_smmu to use the new APIs. Change-Id: I3aed64cd524e94cfa6d6ea168031eda62fd14fb0 Signed-off-by: Siddharth Gupta Signed-off-by: Elliot Berman --- drivers/firmware/qcom_scm-smc.c | 44 +++++++++++++++++++++++++++++++++ drivers/firmware/qcom_scm.c | 13 ++++++++++ drivers/firmware/qcom_scm.h | 6 +++++ include/linux/qcom_scm.h | 6 +++++ 4 files changed, 69 insertions(+) diff --git a/drivers/firmware/qcom_scm-smc.c b/drivers/firmware/qcom_scm-smc.c index 3ada61be5311..11cebd03c917 100644 --- a/drivers/firmware/qcom_scm-smc.c +++ b/drivers/firmware/qcom_scm-smc.c @@ -1137,6 +1137,28 @@ int __qcom_scm_kgsl_set_smmu_aperture(struct device *dev, return ret; } +int __qcom_scm_smmu_prepare_atos_id(struct device *dev, u64 dev_id, int cb_num, + int operation) +{ + int ret; + struct qcom_scm_desc desc = { + .svc = QCOM_SCM_SVC_MP, + .cmd = QCOM_SCM_MP_SMMU_PREPARE_ATOS_ID, + .owner = ARM_SMCCC_OWNER_SIP + }; + + desc.args[0] = dev_id; + desc.args[1] = cb_num; + desc.args[2] = operation; + + desc.arginfo = QCOM_SCM_ARGS(3, QCOM_SCM_VAL, QCOM_SCM_VAL, + QCOM_SCM_VAL); + + ret = qcom_scm_call(dev, &desc); + + return ret; +} + int __qcom_scm_hdcp_req(struct device *dev, struct qcom_scm_hdcp_req *req, u32 req_cnt, u32 *resp) { @@ -1168,6 +1190,28 @@ int __qcom_scm_hdcp_req(struct device *dev, struct qcom_scm_hdcp_req *req, return ret; } +int __qcom_scm_smmu_change_pgtbl_format(struct device *dev, u64 dev_id, + int cbndx) +{ + int ret; + struct qcom_scm_desc desc = { + .svc = QCOM_SCM_SVC_SMMU_PROGRAM, + .cmd = QCOM_SCM_SMMU_CHANGE_PGTBL_FORMAT, + .owner = ARM_SMCCC_OWNER_SIP + }; + + desc.args[0] = dev_id; + desc.args[1] = cbndx; + desc.args[2] = 1; /* Enable */ + + desc.arginfo = QCOM_SCM_ARGS(3, QCOM_SCM_VAL, QCOM_SCM_VAL, + QCOM_SCM_VAL); + + ret = qcom_scm_call(dev, &desc); + + return ret; +} + int __qcom_scm_qsmmu500_wait_safe_toggle(struct device *dev, bool en) { struct qcom_scm_desc desc = { diff --git a/drivers/firmware/qcom_scm.c b/drivers/firmware/qcom_scm.c index 58a5d435fada..b331b5f45426 100644 --- a/drivers/firmware/qcom_scm.c +++ b/drivers/firmware/qcom_scm.c @@ -504,6 +504,13 @@ int qcom_scm_kgsl_set_smmu_aperture(unsigned int num_context_bank) } EXPORT_SYMBOL(qcom_scm_kgsl_set_smmu_aperture); +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, + operation); +} +EXPORT_SYMBOL(qcom_scm_smmu_prepare_atos_id); + /** * qcom_scm_hdcp_available() - Check if secure environment supports HDCP. * @@ -546,6 +553,12 @@ int qcom_scm_hdcp_req(struct qcom_scm_hdcp_req *req, u32 req_cnt, u32 *resp) } EXPORT_SYMBOL(qcom_scm_hdcp_req); +int qcom_scm_smmu_change_pgtbl_format(u64 dev_id, int cbndx) +{ + return __qcom_scm_smmu_change_pgtbl_format(__scm->dev, dev_id, cbndx); +} +EXPORT_SYMBOL(qcom_scm_smmu_change_pgtbl_format); + int qcom_scm_qsmmu500_wait_safe_toggle(bool en) { return __qcom_scm_qsmmu500_wait_safe_toggle(__scm->dev, en); diff --git a/drivers/firmware/qcom_scm.h b/drivers/firmware/qcom_scm.h index 46e5bd640bb7..67bb055aa3fa 100644 --- a/drivers/firmware/qcom_scm.h +++ b/drivers/firmware/qcom_scm.h @@ -70,6 +70,7 @@ 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_MP_SMMU_PREPARE_ATOS_ID 0x21 extern int __qcom_scm_restore_sec_cfg(struct device *dev, u32 device_id, u32 spare); extern int __qcom_scm_iommu_secure_ptbl_size(struct device *dev, u32 spare, @@ -95,6 +96,8 @@ 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_smmu_prepare_atos_id(struct device *dev, u64 dev_id, + int cb_num, int operation); #define QCOM_SCM_IOMMU_TLBINVAL_FLAG 0x00000001 #define QCOM_SCM_CP_APERTURE_REG 0x0 @@ -104,7 +107,10 @@ extern int __qcom_scm_hdcp_req(struct device *dev, struct qcom_scm_hdcp_req *req, u32 req_cnt, u32 *resp); #define QCOM_SCM_SVC_SMMU_PROGRAM 0x15 +#define QCOM_SCM_SMMU_CHANGE_PGTBL_FORMAT 0x01 #define QCOM_SCM_SMMU_CONFIG_ERRATA1 0x3 +extern int __qcom_scm_smmu_change_pgtbl_format(struct device *dev, u64 dev_id, + int cbndx); extern int __qcom_scm_qsmmu500_wait_safe_toggle(struct device *dev, bool enable); #define QCOM_SCM_SMMU_CONFIG_ERRATA1_CLIENT_ALL 0x2 diff --git a/include/linux/qcom_scm.h b/include/linux/qcom_scm.h index a3aead9fedf9..be1457df54b7 100644 --- a/include/linux/qcom_scm.h +++ b/include/linux/qcom_scm.h @@ -71,9 +71,11 @@ extern int qcom_scm_assign_mem(phys_addr_t mem_addr, size_t mem_sz, extern bool qcom_scm_kgsl_set_smmu_aperture_available(void); extern int qcom_scm_kgsl_set_smmu_aperture( unsigned int num_context_bank); +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_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); extern bool qcom_scm_is_available(void); @@ -132,9 +134,13 @@ static inline bool qcom_scm_kgsl_set_smmu_aperture_available(void) { return false; } static inline int qcom_scm_kgsl_set_smmu_aperture( unsigned int num_context_bank) { return -ENODEV; } +static inline int qcom_scm_smmu_prepare_atos_id(u64 dev_id, int cb_num, + int operation) { return -ENODEV; } 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_smmu_change_pgtbl_format(u64 dev_id, int cbndx) + { return -ENODEV; } static inline int qcom_scm_qsmmu500_wait_safe_toggle(bool en) { return -ENODEV; } static inline int qcom_scm_ice_restore_cfg(void) { return -ENODEV; } From b6e110d2d09fe31f2525fd36067cf629bad5cfde Mon Sep 17 00:00:00 2001 From: Siddharth Gupta Date: Mon, 30 Sep 2019 16:08:05 -0700 Subject: [PATCH 03/28] 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) From d321e284cb41b9e43b96abe6b2f20cd960e7302d Mon Sep 17 00:00:00 2001 From: Elliot Berman Date: Tue, 24 Sep 2019 15:17:45 -0700 Subject: [PATCH 04/28] coresight: tpdm: Migrate SCM calls Use upstream qcom_scm driver for SCM call to hw-enable check. Change-Id: I1278bf2af22540d6b9e7c6c42e60c969124ad133 Signed-off-by: Elliot Berman --- drivers/hwtracing/coresight/coresight-tpdm.c | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/drivers/hwtracing/coresight/coresight-tpdm.c b/drivers/hwtracing/coresight/coresight-tpdm.c index e844c3895dd3..356da12ddf43 100644 --- a/drivers/hwtracing/coresight/coresight-tpdm.c +++ b/drivers/hwtracing/coresight/coresight-tpdm.c @@ -14,7 +14,7 @@ #include #include #include -#include +#include #include "coresight-priv.h" @@ -4103,8 +4103,7 @@ static int tpdm_probe(struct amba_device *adev, const struct amba_id *id) struct coresight_desc desc = { 0 }; static int traceid = TPDM_TRACE_ID_START; uint32_t version; - struct scm_desc des = {0}; - u32 scm_ret = 0; + u32 dump_state = 0; desc.name = coresight_alloc_device_name(&tpdm_devs, dev); if (!desc.name) @@ -4115,10 +4114,8 @@ static int tpdm_probe(struct amba_device *adev, const struct amba_id *id) adev->dev.platform_data = pdata; if (of_property_read_bool(adev->dev.of_node, "qcom,hw-enable-check")) { - ret = scm_call2(SCM_SIP_FNID(SCM_SVC_UTIL, - HW_ENABLE_CHECK_VALUE), &des); - scm_ret = des.ret[0]; - if (scm_ret == 0) + ret = qcom_scm_get_sec_dump_state(&dump_state); + if (ret || !dump_state) return -ENXIO; } From 5317ce310c18ebee8889ed61adc90e6b5bee3ec1 Mon Sep 17 00:00:00 2001 From: Elliot Berman Date: Tue, 24 Sep 2019 17:58:00 -0700 Subject: [PATCH 05/28] msm: kgsl: Migrate SCM calls in GPU bus governor Migrate MSM Adreno Governor TZ interface to upstream SCM driver. Change-Id: I1c4347d33b6be835f04422918c29e9c627e02874 Signed-off-by: Elliot Berman Signed-off-by: Siddharth Gupta --- drivers/firmware/qcom_scm-smc.c | 138 ++++++++++++++++++++++++++++++++ drivers/firmware/qcom_scm.c | 70 ++++++++++++++++ drivers/firmware/qcom_scm.h | 27 +++++++ include/linux/qcom_scm.h | 24 ++++++ 4 files changed, 259 insertions(+) diff --git a/drivers/firmware/qcom_scm-smc.c b/drivers/firmware/qcom_scm-smc.c index a149857b5a5f..a3eece5c663e 100644 --- a/drivers/firmware/qcom_scm-smc.c +++ b/drivers/firmware/qcom_scm-smc.c @@ -858,6 +858,19 @@ int __qcom_scm_io_writel(struct device *dev, phys_addr_t addr, unsigned int val) return qcom_scm_call_atomic(dev, &desc); } +int __qcom_scm_io_reset(struct device *dev) +{ + struct qcom_scm_desc desc = { + .svc = QCOM_SCM_SVC_IO, + .cmd = QCOM_SCM_IO_RESET, + .owner = ARM_SMCCC_OWNER_SIP + }; + + desc.arginfo = QCOM_SCM_ARGS(2); + + return qcom_scm_call_atomic(dev, &desc); +} + int __qcom_scm_is_call_available(struct device *dev, u32 svc_id, u32 cmd_id) { int ret; @@ -1222,6 +1235,131 @@ int __qcom_scm_smmu_prepare_atos_id(struct device *dev, u64 dev_id, int cb_num, return ret; } +bool __qcom_scm_dcvs_core_available(struct device *dev) +{ + return __qcom_scm_is_call_available(dev, QCOM_SCM_SVC_DCVS, + QCOM_SCM_DCVS_INIT) && + __qcom_scm_is_call_available(dev, QCOM_SCM_SVC_DCVS, + QCOM_SCM_DCVS_UPDATE) && + __qcom_scm_is_call_available(dev, QCOM_SCM_SVC_DCVS, + QCOM_SCM_DCVS_RESET); +} + +bool __qcom_scm_dcvs_ca_available(struct device *dev) +{ + return __qcom_scm_is_call_available(dev, QCOM_SCM_SVC_DCVS, + QCOM_SCM_DCVS_INIT_CA_V2) && + __qcom_scm_is_call_available(dev, QCOM_SCM_SVC_DCVS, + QCOM_SCM_DCVS_UPDATE_CA_V2); +} + +int __qcom_scm_dcvs_reset(struct device *dev) +{ + struct qcom_scm_desc desc = { + .svc = QCOM_SCM_SVC_DCVS, + .cmd = QCOM_SCM_DCVS_RESET, + .owner = ARM_SMCCC_OWNER_SIP + }; + + return qcom_scm_call(dev, &desc); +} + +int __qcom_scm_dcvs_init_v2(struct device *dev, phys_addr_t addr, size_t size, + int *version) +{ + int ret; + struct qcom_scm_desc desc = { + .svc = QCOM_SCM_SVC_DCVS, + .cmd = QCOM_SCM_DCVS_INIT_V2, + .owner = ARM_SMCCC_OWNER_SIP + }; + + desc.args[0] = addr; + desc.args[1] = size; + desc.arginfo = QCOM_SCM_ARGS(2, QCOM_SCM_RW, QCOM_SCM_VAL); + + ret = qcom_scm_call(dev, &desc); + + if (ret >= 0) + *version = desc.res[0]; + return ret; +} + +int __qcom_scm_dcvs_init_ca_v2(struct device *dev, phys_addr_t addr, + size_t size) +{ + struct qcom_scm_desc desc = { + .svc = QCOM_SCM_SVC_DCVS, + .cmd = QCOM_SCM_DCVS_INIT_CA_V2, + .owner = ARM_SMCCC_OWNER_SIP + }; + + desc.args[0] = addr; + desc.args[1] = size; + desc.arginfo = QCOM_SCM_ARGS(2, QCOM_SCM_RW, QCOM_SCM_VAL); + + return qcom_scm_call(dev, &desc); +} + +int __qcom_scm_dcvs_update(struct device *dev, int level, s64 total_time, + s64 busy_time) +{ + int ret; + struct qcom_scm_desc desc = { + .svc = QCOM_SCM_SVC_DCVS, + .cmd = QCOM_SCM_DCVS_UPDATE, + .owner = ARM_SMCCC_OWNER_SIP + }; + + desc.args[0] = level; + desc.args[1] = total_time; + desc.args[2] = busy_time; + desc.arginfo = QCOM_SCM_ARGS(3); + + ret = qcom_scm_call_atomic(dev, &desc); + + return ret ? : desc.res[0]; +} + +int __qcom_scm_dcvs_update_v2(struct device *dev, int level, s64 total_time, + s64 busy_time) +{ + int ret; + struct qcom_scm_desc desc = { + .svc = QCOM_SCM_SVC_DCVS, + .cmd = QCOM_SCM_DCVS_UPDATE_V2, + .owner = ARM_SMCCC_OWNER_SIP + }; + + desc.args[0] = level; + desc.args[1] = total_time; + desc.args[2] = busy_time; + desc.arginfo = QCOM_SCM_ARGS(3); + + ret = qcom_scm_call(dev, &desc); + return ret ? : desc.res[0]; +} + +int __qcom_scm_dcvs_update_ca_v2(struct device *dev, int level, s64 total_time, + s64 busy_time, int context_count) +{ + int ret; + struct qcom_scm_desc desc = { + .svc = QCOM_SCM_SVC_DCVS, + .cmd = QCOM_SCM_DCVS_UPDATE_CA_V2, + .owner = ARM_SMCCC_OWNER_SIP + }; + + desc.args[0] = level; + desc.args[1] = total_time; + desc.args[2] = busy_time; + desc.args[3] = context_count; + desc.arginfo = QCOM_SCM_ARGS(4); + + ret = qcom_scm_call(dev, &desc); + return ret ? : desc.res[0]; +} + int __qcom_scm_hdcp_req(struct device *dev, struct qcom_scm_hdcp_req *req, u32 req_cnt, u32 *resp) { diff --git a/drivers/firmware/qcom_scm.c b/drivers/firmware/qcom_scm.c index 63268266b1a5..fb7add7aff2a 100644 --- a/drivers/firmware/qcom_scm.c +++ b/drivers/firmware/qcom_scm.c @@ -341,6 +341,15 @@ int qcom_scm_io_writel(phys_addr_t addr, unsigned int val) } EXPORT_SYMBOL(qcom_scm_io_writel); +/** + * qcom_scm_io_reset() + */ +int qcom_scm_io_reset(void) +{ + return __qcom_scm_io_reset(__scm ? __scm->dev : NULL); +} +EXPORT_SYMBOL(qcom_scm_io_reset); + int qcom_scm_get_jtag_etm_feat_id(u64 *version) { return __qcom_scm_get_feat_version(__scm ? __scm->dev : NULL, @@ -533,6 +542,67 @@ int qcom_scm_smmu_prepare_atos_id(u64 dev_id, int cb_num, int operation) } EXPORT_SYMBOL(qcom_scm_smmu_prepare_atos_id); +/** + * qcom_scm_dcvs_core_available() - check if core DCVS operations are available + */ +bool qcom_scm_dcvs_core_available(void) +{ + return __qcom_scm_dcvs_core_available(__scm ? __scm->dev : NULL); +} +EXPORT_SYMBOL(qcom_scm_dcvs_core_available); + +/** + * qcom_scm_dcvs_ca_available() - check if context aware DCVS operations are + * available + */ +bool qcom_scm_dcvs_ca_available(void) +{ + return __qcom_scm_dcvs_ca_available(__scm ? __scm->dev : NULL); +} +EXPORT_SYMBOL(qcom_scm_dcvs_ca_available); + +/** + * qcom_scm_dcvs_reset() + */ +int qcom_scm_dcvs_reset(void) +{ + return __qcom_scm_dcvs_reset(__scm ? __scm->dev : NULL); +} +EXPORT_SYMBOL(qcom_scm_dcvs_reset); + +int qcom_scm_dcvs_init_v2(phys_addr_t addr, size_t size, int *version) +{ + return __qcom_scm_dcvs_init_v2(__scm->dev, addr, size, version); +} +EXPORT_SYMBOL(qcom_scm_dcvs_init_v2); + +int qcom_scm_dcvs_init_ca_v2(phys_addr_t addr, size_t size) +{ + return __qcom_scm_dcvs_init_ca_v2(__scm->dev, addr, size); +} +EXPORT_SYMBOL(qcom_scm_dcvs_init_ca_v2); + +int qcom_scm_dcvs_update(int level, s64 total_time, s64 busy_time) +{ + return __qcom_scm_dcvs_update(__scm->dev, level, total_time, busy_time); +} +EXPORT_SYMBOL(qcom_scm_dcvs_update); + +int qcom_scm_dcvs_update_v2(int level, s64 total_time, s64 busy_time) +{ + return __qcom_scm_dcvs_update_v2(__scm->dev, level, total_time, + busy_time); +} +EXPORT_SYMBOL(qcom_scm_dcvs_update_v2); + +int qcom_scm_dcvs_update_ca_v2(int level, s64 total_time, s64 busy_time, + int context_count) +{ + return __qcom_scm_dcvs_update_ca_v2(__scm->dev, level, total_time, + busy_time, context_count); +} +EXPORT_SYMBOL(qcom_scm_dcvs_update_ca_v2); + /** * qcom_scm_hdcp_available() - Check if secure environment supports HDCP. * diff --git a/drivers/firmware/qcom_scm.h b/drivers/firmware/qcom_scm.h index 537e8c7d997b..6686d489a72e 100644 --- a/drivers/firmware/qcom_scm.h +++ b/drivers/firmware/qcom_scm.h @@ -44,8 +44,10 @@ extern int __qcom_scm_get_sec_dump_state(struct device *dev, u32 *dump_state); #define QCOM_SCM_SVC_IO 0x05 #define QCOM_SCM_IO_READ 0x01 #define QCOM_SCM_IO_WRITE 0x02 +#define QCOM_SCM_IO_RESET 0x03 extern int __qcom_scm_io_readl(struct device *dev, phys_addr_t addr, unsigned int *val); extern int __qcom_scm_io_writel(struct device *dev, phys_addr_t addr, unsigned int val); +extern int __qcom_scm_io_reset(struct device *dev); #define QCOM_SCM_SVC_INFO 0x06 #define QCOM_SCM_INFO_IS_CALL_AVAIL 0x01 @@ -109,6 +111,31 @@ extern int __qcom_scm_smmu_prepare_atos_id(struct device *dev, u64 dev_id, #define QCOM_SCM_IOMMU_TLBINVAL_FLAG 0x00000001 #define QCOM_SCM_CP_APERTURE_REG 0x0 +#define QCOM_SCM_SVC_DCVS 0x0D +#define QCOM_SCM_DCVS_RESET 0x07 +#define QCOM_SCM_DCVS_UPDATE 0x08 +#define QCOM_SCM_DCVS_INIT 0x09 +#define QCOM_SCM_DCVS_UPDATE_V2 0x0a +#define QCOM_SCM_DCVS_INIT_V2 0x0b +#define QCOM_SCM_DCVS_INIT_CA_V2 0x0c +#define QCOM_SCM_DCVS_UPDATE_CA_V2 0x0d +extern bool __qcom_scm_dcvs_core_available(struct device *dev); +extern bool __qcom_scm_dcvs_ca_available(struct device *dev); +extern int __qcom_scm_dcvs_reset(struct device *dev); +extern int __qcom_scm_dcvs_init_v2(struct device *dev, phys_addr_t addr, + size_t size, int *version); +extern int __qcom_scm_dcvs_init_ca_v2(struct device *dev, phys_addr_t addr, + size_t size); +extern int __qcom_scm_dcvs_update(struct device *dev, int level, + s64 total_time, s64 busy_time); + +extern int __qcom_scm_dcvs_update_v2(struct device *dev, int level, + s64 total_time, s64 busy_time); + +extern int __qcom_scm_dcvs_update_ca_v2(struct device *dev, int level, + s64 total_time, s64 busy_time, + int context_count); + #define QCOM_SCM_SVC_HDCP 0x11 #define QCOM_SCM_HDCP_INVOKE 0x01 extern int __qcom_scm_hdcp_req(struct device *dev, diff --git a/include/linux/qcom_scm.h b/include/linux/qcom_scm.h index 5f9763e84090..7fc1df0b320a 100644 --- a/include/linux/qcom_scm.h +++ b/include/linux/qcom_scm.h @@ -50,6 +50,7 @@ extern int qcom_scm_pas_shutdown(u32 peripheral); extern int qcom_scm_get_sec_dump_state(u32 *dump_state); extern int qcom_scm_io_readl(phys_addr_t addr, unsigned int *val); extern int qcom_scm_io_writel(phys_addr_t addr, unsigned int val); +extern int qcom_scm_io_reset(void); extern int qcom_scm_get_jtag_etm_feat_id(u64 *version); extern void qcom_scm_mmu_sync(bool sync); extern int qcom_scm_restore_sec_cfg(u32 device_id, u32 spare); @@ -72,6 +73,15 @@ extern bool qcom_scm_kgsl_set_smmu_aperture_available(void); extern int qcom_scm_kgsl_set_smmu_aperture( unsigned int num_context_bank); extern int qcom_scm_smmu_prepare_atos_id(u64 dev_id, int cb_num, int operation); +extern bool qcom_scm_dcvs_core_available(void); +extern bool qcom_scm_dcvs_ca_available(void); +extern int qcom_scm_dcvs_reset(void); +extern int qcom_scm_dcvs_init_v2(phys_addr_t addr, size_t size, int *version); +extern int qcom_scm_dcvs_init_ca_v2(phys_addr_t addr, size_t size); +extern int qcom_scm_dcvs_update(int level, s64 total_time, s64 busy_time); +extern int qcom_scm_dcvs_update_v2(int level, s64 total_time, s64 busy_time); +extern int qcom_scm_dcvs_update_ca_v2(int level, s64 total_time, s64 busy_time, + int context_count); extern bool qcom_scm_hdcp_available(void); extern int qcom_scm_hdcp_req(struct qcom_scm_hdcp_req *req, u32 req_cnt, u32 *resp); @@ -112,6 +122,8 @@ static inline int qcom_scm_io_readl(phys_addr_t addr, unsigned int *val) { return -ENODEV; } static inline int qcom_scm_io_writel(phys_addr_t addr, unsigned int val) { return -ENODEV; } +static inline int qcom_scm_io_reset(void) + { return -ENODEV; } static inline int qcom_scm_get_jtag_etm_feat_id(u64 *version) { return -ENODEV; } static inline void qcom_scm_mmu_sync(bool sync) {} @@ -141,6 +153,18 @@ static inline int qcom_scm_kgsl_set_smmu_aperture( unsigned int num_context_bank) { return -ENODEV; } static inline int qcom_scm_smmu_prepare_atos_id(u64 dev_id, int cb_num, int operation) { return -ENODEV; } +static inline bool qcom_scm_dcvs_core_available(void) { return false; } +static inline bool qcom_scm_dcvs_ca_available(void) { return false; } +static inline int qcom_scm_dcvs_init_v2(phys_addr_t addr, size_t size, + int *version) { return -ENODEV; } +static inline int qcom_scm_dcvs_init_ca_v2(phys_addr_t addr, size_t size) + { return -ENODEV; } +static inline int qcom_scm_dcvs_update(int level, s64 total_time, s64 busy_time) + { return -ENODEV; } +static inline int qcom_scm_dcvs_update_v2(int level, s64 total_time, + s64 busy_time) { return -ENODEV; } +static inline int qcom_scm_dcvs_update_ca_v2(int level, s64 total_time, + s64 busy_time, int context_count) { return -ENODEV; } 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; } From 348d7803bb44b891a9e91947cc1410dda020e202 Mon Sep 17 00:00:00 2001 From: Elliot Berman Date: Tue, 29 Oct 2019 10:43:37 -0700 Subject: [PATCH 06/28] firmware: qcom_scm: Add calls for pfk_ice Add variant of qcom_scm_call which disables EBUSY retry mechanism. Add SCM calls for pfk_ice to initialize keys. Change-Id: Ib785cd0bf4df5b81d73bad96c2a6f56ae961b55d Signed-off-by: Elliot Berman --- drivers/firmware/qcom_scm-smc.c | 73 ++++++++++++++++++++++++++++++++- drivers/firmware/qcom_scm.c | 15 +++++++ drivers/firmware/qcom_scm.h | 11 +++++ include/linux/qcom_scm.h | 10 +++++ 4 files changed, 107 insertions(+), 2 deletions(-) diff --git a/drivers/firmware/qcom_scm-smc.c b/drivers/firmware/qcom_scm-smc.c index a3eece5c663e..abd5ce130d61 100644 --- a/drivers/firmware/qcom_scm-smc.c +++ b/drivers/firmware/qcom_scm-smc.c @@ -21,6 +21,9 @@ #define MAX_QCOM_SCM_ARGS 10 #define MAX_QCOM_SCM_RETS 3 +#define QCOM_SCM_ATOMIC BIT(0) +#define QCOM_SCM_NORETRY BIT(1) + enum qcom_scm_arg_types { QCOM_SCM_VAL, QCOM_SCM_RO, @@ -181,11 +184,12 @@ static void __qcom_scm_call_do_quirk(const struct arm_smccc_args *smc, } static int qcom_scm_call_smccc(struct device *dev, - struct qcom_scm_desc *desc, bool atomic) + struct qcom_scm_desc *desc, const u32 options) { int arglen = desc->arginfo & 0xf; int i, ret; size_t alloc_len; + const bool atomic = options & QCOM_SCM_ATOMIC; gfp_t flag = atomic ? GFP_ATOMIC : GFP_NOIO; u32 smccc_call_type = atomic ? ARM_SMCCC_FAST_CALL : ARM_SMCCC_STD_CALL; u32 qcom_smccc_convention = @@ -262,7 +266,8 @@ static int qcom_scm_call_smccc(struct device *dev, mutex_unlock(&qcom_scm_lock); if (res.a0 == QCOM_SCM_V2_EBUSY) { - if (retry_count++ > QCOM_SCM_EBUSY_MAX_RETRY) + if (retry_count++ > QCOM_SCM_EBUSY_MAX_RETRY || + (options & QCOM_SCM_NORETRY)) break; msleep(QCOM_SCM_EBUSY_WAIT_MS); } @@ -543,6 +548,31 @@ static int qcom_scm_call_atomic(struct device *dev, struct qcom_scm_desc *desc) } } +/** + * qcom_scm_call_noretry() - Invoke a syscall in the secure world + * @dev: device + * @svc_id: service identifier + * @cmd_id: command identifier + * @desc: Descriptor structure containing arguments and return values + * + * Sends a command to the SCM and waits for the command to finish processing. + * This should *only* be called in pre-emptible context. + */ +static int qcom_scm_call_noretry(struct device *dev, struct qcom_scm_desc *desc) +{ + might_sleep(); + switch (__get_convention()) { + case SMC_CONVENTION_ARM_32: + case SMC_CONVENTION_ARM_64: + return qcom_scm_call_smccc(dev, desc, QCOM_SCM_NORETRY); + case SMC_CONVENTION_LEGACY: + return qcom_scm_call_legacy(dev, desc); + default: + pr_err("Unknown current SCM calling convention.\n"); + return -EINVAL; + } +} + /** * qcom_scm_set_cold_boot_addr() - Set the cold boot address for cpus * @entry: Entry point function for the cpus @@ -1360,6 +1390,45 @@ int __qcom_scm_dcvs_update_ca_v2(struct device *dev, int level, s64 total_time, return ret ? : desc.res[0]; } +int __qcom_scm_config_set_ice_key(struct device *dev, uint32_t index, + phys_addr_t paddr, size_t size, + uint32_t cipher, unsigned int data_unit, + unsigned int food) +{ + struct qcom_scm_desc desc = { + .svc = QCOM_SCM_SVC_ES, + .cmd = QCOM_SCM_ES_CONFIG_SET_ICE_KEY, + .owner = ARM_SMCCC_OWNER_SIP + }; + + desc.args[0] = index; + desc.args[1] = paddr; + desc.args[2] = size; + desc.args[3] = cipher; + desc.args[4] = data_unit; + desc.args[5] = food; + desc.arginfo = QCOM_SCM_ARGS(6, QCOM_SCM_VAL, QCOM_SCM_RW, QCOM_SCM_VAL, + QCOM_SCM_VAL, QCOM_SCM_VAL, QCOM_SCM_VAL); + + return qcom_scm_call_noretry(dev, &desc); +} + +int __qcom_scm_clear_ice_key(struct device *dev, uint32_t index, + unsigned int food) +{ + struct qcom_scm_desc desc = { + .svc = QCOM_SCM_SVC_ES, + .cmd = QCOM_SCM_ES_CLEAR_ICE_KEY, + .owner = ARM_SMCCC_OWNER_SIP + }; + + desc.args[0] = index; + desc.args[1] = food; + desc.arginfo = QCOM_SCM_ARGS(2); + + return qcom_scm_call_noretry(dev, &desc); +} + int __qcom_scm_hdcp_req(struct device *dev, struct qcom_scm_hdcp_req *req, u32 req_cnt, u32 *resp) { diff --git a/drivers/firmware/qcom_scm.c b/drivers/firmware/qcom_scm.c index fb7add7aff2a..f3b178e5f1a9 100644 --- a/drivers/firmware/qcom_scm.c +++ b/drivers/firmware/qcom_scm.c @@ -603,6 +603,21 @@ int qcom_scm_dcvs_update_ca_v2(int level, s64 total_time, s64 busy_time, } EXPORT_SYMBOL(qcom_scm_dcvs_update_ca_v2); +int qcom_scm_config_set_ice_key(uint32_t index, phys_addr_t paddr, size_t size, + uint32_t cipher, unsigned int data_unit, + unsigned int food) +{ + return __qcom_scm_config_set_ice_key(__scm->dev, index, paddr, size, + cipher, data_unit, food); +} +EXPORT_SYMBOL(qcom_scm_config_set_ice_key); + +int qcom_scm_clear_ice_key(uint32_t index, unsigned int food) +{ + return __qcom_scm_clear_ice_key(__scm->dev, index, food); +} +EXPORT_SYMBOL(qcom_scm_clear_ice_key); + /** * qcom_scm_hdcp_available() - Check if secure environment supports HDCP. * diff --git a/drivers/firmware/qcom_scm.h b/drivers/firmware/qcom_scm.h index 6686d489a72e..162759c34f3c 100644 --- a/drivers/firmware/qcom_scm.h +++ b/drivers/firmware/qcom_scm.h @@ -136,6 +136,17 @@ extern int __qcom_scm_dcvs_update_ca_v2(struct device *dev, int level, s64 total_time, s64 busy_time, int context_count); +#define QCOM_SCM_SVC_ES 0x10 +#define QCOM_SCM_ES_CONFIG_SET_ICE_KEY 0x05 +#define QCOM_SCM_ES_CLEAR_ICE_KEY 0x06 +extern int __qcom_scm_config_set_ice_key(struct device *dev, uint32_t index, + phys_addr_t paddr, size_t size, + uint32_t cipher, + unsigned int data_unit, + unsigned int food); +extern int __qcom_scm_clear_ice_key(struct device *dev, uint32_t index, + unsigned int food); + #define QCOM_SCM_SVC_HDCP 0x11 #define QCOM_SCM_HDCP_INVOKE 0x01 extern int __qcom_scm_hdcp_req(struct device *dev, diff --git a/include/linux/qcom_scm.h b/include/linux/qcom_scm.h index 7fc1df0b320a..3d093dc8cc2d 100644 --- a/include/linux/qcom_scm.h +++ b/include/linux/qcom_scm.h @@ -82,6 +82,11 @@ extern int qcom_scm_dcvs_update(int level, s64 total_time, s64 busy_time); extern int qcom_scm_dcvs_update_v2(int level, s64 total_time, s64 busy_time); extern int qcom_scm_dcvs_update_ca_v2(int level, s64 total_time, s64 busy_time, int context_count); +extern int qcom_scm_config_set_ice_key(uint32_t index, phys_addr_t paddr, + size_t size, uint32_t cipher, + unsigned int data_unit, + unsigned int food); +extern int qcom_scm_clear_ice_key(uint32_t index, unsigned int food); extern bool qcom_scm_hdcp_available(void); extern int qcom_scm_hdcp_req(struct qcom_scm_hdcp_req *req, u32 req_cnt, u32 *resp); @@ -165,6 +170,11 @@ static inline int qcom_scm_dcvs_update_v2(int level, s64 total_time, s64 busy_time) { return -ENODEV; } static inline int qcom_scm_dcvs_update_ca_v2(int level, s64 total_time, s64 busy_time, int context_count) { return -ENODEV; } +static inline int qcom_scm_config_set_ice_key(uint32_t index, phys_addr_t paddr, + size_t size, uint32_t cipher, unsigned int data_unit, + unsigned int food) { return -ENODEV; } +static inline int qcom_scm_clear_ice_key(uint32_t index, unsigned int food) + { return -ENODEV; } 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; } From 7729d81d86a8f9bb362c9b302a8eecdadb5ee29b Mon Sep 17 00:00:00 2001 From: Elliot Berman Date: Tue, 20 Aug 2019 10:12:56 -0700 Subject: [PATCH 07/28] soc: qcom: Migrate SCM calls in PIL Migrate away from downstream scm_call2 API to upstream QCOM SCM API. Change-Id: I8eb5d138ad039e279dc21345e3175f69cafaec24 Signed-off-by: Elliot Berman --- drivers/soc/qcom/subsys-pil-tz.c | 79 ++++---------------------------- 1 file changed, 8 insertions(+), 71 deletions(-) diff --git a/drivers/soc/qcom/subsys-pil-tz.c b/drivers/soc/qcom/subsys-pil-tz.c index cbd3d3d57b16..fda0cba15c5a 100644 --- a/drivers/soc/qcom/subsys-pil-tz.c +++ b/drivers/soc/qcom/subsys-pil-tz.c @@ -18,10 +18,10 @@ #include #include #include +#include #include #include -#include #include #include @@ -111,13 +111,6 @@ struct pil_tz_data { u32 bits_arr[2]; }; -enum scm_cmd { - PAS_INIT_IMAGE_CMD = 1, - PAS_MEM_SETUP_CMD, - PAS_AUTH_AND_RESET_CMD = 5, - PAS_SHUTDOWN_CMD, -}; - enum pas_id { PAS_MODEM, PAS_Q6, @@ -557,10 +550,7 @@ static int pil_init_image_trusted(struct pil_desc *pil, { struct pil_tz_data *d = desc_to_data(pil); u32 scm_ret = 0; - void *mdata_buf; - dma_addr_t mdata_phys; int ret; - struct scm_desc desc = {0}; if (d->subsys_desc.no_auth) return 0; @@ -569,28 +559,9 @@ static int pil_init_image_trusted(struct pil_desc *pil, if (ret) return ret; - dma_set_mask(pil->dev, DMA_BIT_MASK(sizeof(dma_addr_t) * 8)); - mdata_buf = dma_alloc_coherent(pil->dev, size, &mdata_phys, GFP_KERNEL); - if (!mdata_buf) { - pr_err("scm-pas: Allocation for metadata failed.\n"); - scm_pas_disable_bw(); - return -ENOMEM; - } - - memcpy(mdata_buf, metadata, size); - - desc.args[0] = d->pas_id; - desc.args[1] = mdata_phys; - desc.arginfo = SCM_ARGS(2, SCM_VAL, SCM_RW); - ret = scm_call2(SCM_SIP_FNID(SCM_SVC_PIL, PAS_INIT_IMAGE_CMD), - &desc); - scm_ret = desc.ret[0]; - - dma_free_coherent(pil->dev, size, mdata_buf, mdata_phys); + scm_ret = qcom_scm_pas_init_image(d->pas_id, metadata, size); scm_pas_disable_bw(); - if (ret) - return ret; return scm_ret; } @@ -599,22 +570,12 @@ static int pil_mem_setup_trusted(struct pil_desc *pil, phys_addr_t addr, { struct pil_tz_data *d = desc_to_data(pil); u32 scm_ret = 0; - int ret; - struct scm_desc desc = {0}; if (d->subsys_desc.no_auth) return 0; - desc.args[0] = d->pas_id; - desc.args[1] = addr; - desc.args[2] = size; - desc.arginfo = SCM_ARGS(3); - ret = scm_call2(SCM_SIP_FNID(SCM_SVC_PIL, PAS_MEM_SETUP_CMD), - &desc); - scm_ret = desc.ret[0]; + scm_ret = qcom_scm_pas_mem_setup(d->pas_id, addr, size); - if (ret) - return ret; return scm_ret; } @@ -622,15 +583,11 @@ static int pil_auth_and_reset(struct pil_desc *pil) { struct pil_tz_data *d = desc_to_data(pil); int rc; - u32 proc, scm_ret = 0; - struct scm_desc desc = {0}; + u32 scm_ret = 0; if (d->subsys_desc.no_auth) return 0; - desc.args[0] = proc = d->pas_id; - desc.arginfo = SCM_ARGS(1); - rc = scm_pas_enable_bw(); if (rc) return rc; @@ -643,9 +600,7 @@ static int pil_auth_and_reset(struct pil_desc *pil) if (rc) goto err_clks; - rc = scm_call2(SCM_SIP_FNID(SCM_SVC_PIL, - PAS_AUTH_AND_RESET_CMD), &desc); - scm_ret = desc.ret[0]; + scm_ret = qcom_scm_pas_auth_and_reset(d->pas_id); scm_pas_disable_bw(); if (rc) @@ -663,16 +618,12 @@ err_clks: static int pil_shutdown_trusted(struct pil_desc *pil) { struct pil_tz_data *d = desc_to_data(pil); - u32 proc, scm_ret = 0; + u32 scm_ret = 0; int rc; - struct scm_desc desc = {0}; if (d->subsys_desc.no_auth) return 0; - desc.args[0] = proc = d->pas_id; - desc.arginfo = SCM_ARGS(1); - rc = do_bus_scaling_request(pil, 1); if (rc) return rc; @@ -687,9 +638,7 @@ static int pil_shutdown_trusted(struct pil_desc *pil) if (rc) goto err_clks; - rc = scm_call2(SCM_SIP_FNID(SCM_SVC_PIL, PAS_SHUTDOWN_CMD), - &desc); - scm_ret = desc.ret[0]; + scm_ret = qcom_scm_pas_shutdown(d->pas_id); disable_unprepare_clocks(d->proxy_clks, d->proxy_clk_count); disable_regulators(d, d->proxy_regs, d->proxy_reg_count, false); @@ -715,23 +664,11 @@ err_regulators: static int pil_deinit_image_trusted(struct pil_desc *pil) { struct pil_tz_data *d = desc_to_data(pil); - u32 proc, scm_ret = 0; - int rc; - struct scm_desc desc = {0}; if (d->subsys_desc.no_auth) return 0; - desc.args[0] = proc = d->pas_id; - desc.arginfo = SCM_ARGS(1); - - rc = scm_call2(SCM_SIP_FNID(SCM_SVC_PIL, PAS_SHUTDOWN_CMD), - &desc); - scm_ret = desc.ret[0]; - - if (rc) - return rc; - return scm_ret; + return qcom_scm_pas_shutdown(d->pas_id); } static struct pil_reset_ops pil_ops_trusted = { From 9f0809bb26b1b6b4eee890235689b54b67cf11a7 Mon Sep 17 00:00:00 2001 From: Elliot Berman Date: Fri, 11 Oct 2019 12:09:49 -0700 Subject: [PATCH 08/28] firmware: qcom: Migrate SCM calls in tz_log Migrate SCM call to register qsee log buffer to new SCM driver. Change-Id: Ic9c700f5324f1a5d5a9ce28ab95cc55fed9c692e Signed-off-by: Elliot Berman --- drivers/firmware/qcom_scm-smc.c | 20 ++++++++++++++++++++ drivers/firmware/qcom_scm.c | 13 +++++++++++++ drivers/firmware/qcom_scm.h | 6 ++++++ include/linux/qcom_scm.h | 6 ++++++ 4 files changed, 45 insertions(+) diff --git a/drivers/firmware/qcom_scm-smc.c b/drivers/firmware/qcom_scm-smc.c index abd5ce130d61..416389de8294 100644 --- a/drivers/firmware/qcom_scm-smc.c +++ b/drivers/firmware/qcom_scm-smc.c @@ -1510,6 +1510,26 @@ int __qcom_scm_ice_restore_cfg(struct device *dev) return qcom_scm_call(dev, &desc); } +int __qcom_scm_register_qsee_log_buf(struct device *dev, phys_addr_t buf, + size_t len) +{ + int ret; + struct qcom_scm_desc desc = { + .svc = QCOM_SCM_SVC_QSEELOG, + .cmd = QCOM_SCM_QSEELOG_REGISTER, + .owner = ARM_SMCCC_OWNER_TRUSTED_OS + }; + + + desc.args[0] = buf; + desc.args[1] = len; + desc.arginfo = QCOM_SCM_ARGS(2, QCOM_SCM_RW); + + ret = qcom_scm_call(dev, &desc); + + return ret ? : desc.res[0]; +} + void __qcom_scm_init(void) { __query_convention(); diff --git a/drivers/firmware/qcom_scm.c b/drivers/firmware/qcom_scm.c index f3b178e5f1a9..e199b75e550c 100644 --- a/drivers/firmware/qcom_scm.c +++ b/drivers/firmware/qcom_scm.c @@ -678,6 +678,19 @@ int qcom_scm_ice_restore_cfg(void) } EXPORT_SYMBOL(qcom_scm_ice_restore_cfg); +int qcom_scm_get_tz_log_feat_id(u64 *version) +{ + return __qcom_scm_get_feat_version(__scm->dev, QCOM_SCM_FEAT_LOG_ID, + version); +} +EXPORT_SYMBOL(qcom_scm_get_tz_log_feat_id); + +int qcom_scm_register_qsee_log_buf(phys_addr_t buf, size_t len) +{ + return __qcom_scm_register_qsee_log_buf(__scm->dev, buf, len); +} +EXPORT_SYMBOL(qcom_scm_register_qsee_log_buf); + /** * qcom_scm_is_available() - Checks if SCM is available */ diff --git a/drivers/firmware/qcom_scm.h b/drivers/firmware/qcom_scm.h index 162759c34f3c..aba137729ebc 100644 --- a/drivers/firmware/qcom_scm.h +++ b/drivers/firmware/qcom_scm.h @@ -162,6 +162,12 @@ extern int __qcom_scm_qsmmu500_wait_safe_toggle(struct device *dev, #define QCOM_SCM_SMMU_CONFIG_ERRATA1_CLIENT_ALL 0x2 // TOS Services and Function IDs +#define QCOM_SCM_SVC_QSEELOG 0x01 +#define QCOM_SCM_QSEELOG_REGISTER 0x06 +extern int __qcom_scm_register_qsee_log_buf(struct device *dev, phys_addr_t buf, + size_t len); +#define QCOM_SCM_FEAT_LOG_ID 0x0a + #define QCOM_SCM_SVC_KEYSTORE 0x05 #define QCOM_SCM_ICE_RESTORE_KEY_ID 0x06 extern int __qcom_scm_ice_restore_cfg(struct device *dev); diff --git a/include/linux/qcom_scm.h b/include/linux/qcom_scm.h index 3d093dc8cc2d..8ca5fe630ef0 100644 --- a/include/linux/qcom_scm.h +++ b/include/linux/qcom_scm.h @@ -98,6 +98,8 @@ extern int qcom_scm_create_shm_bridge(u64 pfn_and_ns_perm_flags, 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); +extern int qcom_scm_get_tz_log_feat_id(u64 *version); +extern int qcom_scm_register_qsee_log_buf(phys_addr_t buf, size_t len); extern bool qcom_scm_is_available(void); #else @@ -188,6 +190,10 @@ static inline int qcom_scm_smmu_change_pgtbl_format(u64 dev_id, int cbndx) static inline int qcom_scm_qsmmu500_wait_safe_toggle(bool en) { return -ENODEV; } static inline int qcom_scm_ice_restore_cfg(void) { return -ENODEV; } +static inline int qcom_scm_get_tz_log_feat_id(u64 *version) + { return -ENODEV; } +static inline int qcom_scm_register_qsee_log_buf(phys_addr_t buf, size_t len) + { return -ENODEV; } static inline bool qcom_scm_is_available(void) { return false; } #endif #endif From 3e2067094185c789ccab7ccbc61e498ef4b535ac Mon Sep 17 00:00:00 2001 From: Elliot Berman Date: Fri, 11 Oct 2019 18:46:36 -0700 Subject: [PATCH 09/28] soc: qcom: Migrate SCM calls in remoteqdss Migrate scm_call2 usage to new SCM driver in remoteqdss. Change-Id: Idd25aab0c5fb7cc55ee81c8f685981b8362a7b45 Signed-off-by: Elliot Berman --- drivers/firmware/qcom_scm-smc.c | 22 ++++++++++++++++++++++ drivers/firmware/qcom_scm.c | 6 ++++++ drivers/firmware/qcom_scm.h | 5 +++++ include/linux/qcom_scm.h | 3 +++ 4 files changed, 36 insertions(+) diff --git a/drivers/firmware/qcom_scm-smc.c b/drivers/firmware/qcom_scm-smc.c index 416389de8294..953890dca1a5 100644 --- a/drivers/firmware/qcom_scm-smc.c +++ b/drivers/firmware/qcom_scm-smc.c @@ -1497,6 +1497,28 @@ int __qcom_scm_qsmmu500_wait_safe_toggle(struct device *dev, bool en) return qcom_scm_call_atomic(dev, &desc); } +int __qcom_scm_qdss_invoke(struct device *dev, phys_addr_t addr, size_t size, + u64 *out) +{ + int ret; + struct qcom_scm_desc desc = { + .svc = QCOM_SCM_SVC_QDSS, + .cmd = QCOM_SCM_QDSS_INVOKE, + .owner = ARM_SMCCC_OWNER_SIP + }; + + desc.args[0] = addr; + desc.args[1] = size; + desc.arginfo = QCOM_SCM_ARGS(2, QCOM_SCM_RO, QCOM_SCM_VAL); + + ret = qcom_scm_call(dev, &desc); + + if (out) + *out = desc.res[1]; + + return ret ? : desc.res[0]; +} + int __qcom_scm_ice_restore_cfg(struct device *dev) { struct qcom_scm_desc desc = { diff --git a/drivers/firmware/qcom_scm.c b/drivers/firmware/qcom_scm.c index e199b75e550c..eb5a89263f7a 100644 --- a/drivers/firmware/qcom_scm.c +++ b/drivers/firmware/qcom_scm.c @@ -672,6 +672,12 @@ int qcom_scm_qsmmu500_wait_safe_toggle(bool en) } EXPORT_SYMBOL(qcom_scm_qsmmu500_wait_safe_toggle); +int qcom_scm_qdss_invoke(phys_addr_t paddr, size_t size, u64 *out) +{ + return __qcom_scm_qdss_invoke(__scm->dev, paddr, size, out); +} +EXPORT_SYMBOL(qcom_scm_qdss_invoke); + int qcom_scm_ice_restore_cfg(void) { return __qcom_scm_ice_restore_cfg(__scm->dev); diff --git a/drivers/firmware/qcom_scm.h b/drivers/firmware/qcom_scm.h index aba137729ebc..692973ec678e 100644 --- a/drivers/firmware/qcom_scm.h +++ b/drivers/firmware/qcom_scm.h @@ -161,6 +161,11 @@ extern int __qcom_scm_qsmmu500_wait_safe_toggle(struct device *dev, bool enable); #define QCOM_SCM_SMMU_CONFIG_ERRATA1_CLIENT_ALL 0x2 +#define QCOM_SCM_SVC_QDSS 0x16 +#define QCOM_SCM_QDSS_INVOKE 0x01 +extern int __qcom_scm_qdss_invoke(struct device *dev, phys_addr_t addr, + size_t size, u64 *out); + // TOS Services and Function IDs #define QCOM_SCM_SVC_QSEELOG 0x01 #define QCOM_SCM_QSEELOG_REGISTER 0x06 diff --git a/include/linux/qcom_scm.h b/include/linux/qcom_scm.h index 8ca5fe630ef0..38e1d3643bd6 100644 --- a/include/linux/qcom_scm.h +++ b/include/linux/qcom_scm.h @@ -97,6 +97,7 @@ extern int qcom_scm_create_shm_bridge(u64 pfn_and_ns_perm_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_qdss_invoke(phys_addr_t addr, size_t size, u64 *out); extern int qcom_scm_ice_restore_cfg(void); extern int qcom_scm_get_tz_log_feat_id(u64 *version); extern int qcom_scm_register_qsee_log_buf(phys_addr_t buf, size_t len); @@ -189,6 +190,8 @@ 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) { return -ENODEV; } +static inline int qcom_scm_qdss_invoke(phys_addr_t data, size_t size, u64 *out) + { return -EINVAL; } static inline int qcom_scm_ice_restore_cfg(void) { return -ENODEV; } static inline int qcom_scm_get_tz_log_feat_id(u64 *version) { return -ENODEV; } From 0d8b2730932ae6eb92d7170b4a811620175d2b21 Mon Sep 17 00:00:00 2001 From: Elliot Berman Date: Mon, 14 Oct 2019 10:01:59 -0700 Subject: [PATCH 10/28] firmware: qcom_scm: Add calls for camera - Add SCM API to notify secure world that a LUT should be secure. - Add SCM API to notify secure world that camera should be secure. Change-Id: I31b0ce2c58182f809d0875c64116436a30ce8f62 Signed-off-by: Elliot Berman --- drivers/firmware/qcom_scm-smc.c | 34 ++++++++++++++++++++++++++++++++- drivers/firmware/qcom_scm.c | 13 +++++++++++++ drivers/firmware/qcom_scm.h | 9 ++++++++- include/linux/qcom_scm.h | 6 ++++++ 4 files changed, 60 insertions(+), 2 deletions(-) diff --git a/drivers/firmware/qcom_scm-smc.c b/drivers/firmware/qcom_scm-smc.c index 953890dca1a5..5dc3b7319b19 100644 --- a/drivers/firmware/qcom_scm-smc.c +++ b/drivers/firmware/qcom_scm-smc.c @@ -1486,7 +1486,7 @@ int __qcom_scm_qsmmu500_wait_safe_toggle(struct device *dev, bool en) { struct qcom_scm_desc desc = { .svc = QCOM_SCM_SVC_SMMU_PROGRAM, - .cmd = QCOM_SCM_SMMU_CONFIG_ERRATA1, + .cmd = QCOM_SCM_SMMU_SECURE_LUT, .owner = ARM_SMCCC_OWNER_SIP, }; @@ -1497,6 +1497,22 @@ int __qcom_scm_qsmmu500_wait_safe_toggle(struct device *dev, bool en) return qcom_scm_call_atomic(dev, &desc); } +int __qcom_scm_smmu_notify_secure_lut(struct device *dev, u64 dev_id, + bool secure) +{ + struct qcom_scm_desc desc = { + .svc = QCOM_SCM_SVC_SMMU_PROGRAM, + .cmd = QCOM_SCM_SMMU_SECURE_LUT, + .owner = ARM_SMCCC_OWNER_SIP + }; + + desc.args[0] = dev_id; + desc.args[1] = secure; + desc.arginfo = QCOM_SCM_ARGS(2); + + return qcom_scm_call(dev, &desc); +} + int __qcom_scm_qdss_invoke(struct device *dev, phys_addr_t addr, size_t size, u64 *out) { @@ -1519,6 +1535,22 @@ int __qcom_scm_qdss_invoke(struct device *dev, phys_addr_t addr, size_t size, return ret ? : desc.res[0]; } +int __qcom_scm_camera_protect_phy_lanes(struct device *dev, bool protect, + u64 regmask) +{ + struct qcom_scm_desc desc = { + .svc = QCOM_SCM_SVC_CAMERA, + .cmd = QCOM_SCM_CAMERA_PROTECT_PHY_LANES, + .owner = ARM_SMCCC_OWNER_SIP + }; + + desc.args[0] = protect; + desc.args[1] = regmask; + desc.arginfo = QCOM_SCM_ARGS(2); + + return qcom_scm_call(dev, &desc); +} + int __qcom_scm_ice_restore_cfg(struct device *dev) { struct qcom_scm_desc desc = { diff --git a/drivers/firmware/qcom_scm.c b/drivers/firmware/qcom_scm.c index eb5a89263f7a..c53835171f2c 100644 --- a/drivers/firmware/qcom_scm.c +++ b/drivers/firmware/qcom_scm.c @@ -672,12 +672,25 @@ int qcom_scm_qsmmu500_wait_safe_toggle(bool en) } EXPORT_SYMBOL(qcom_scm_qsmmu500_wait_safe_toggle); +int qcom_scm_smmu_notify_secure_lut(u64 dev_id, bool secure) +{ + return __qcom_scm_smmu_notify_secure_lut(__scm->dev, dev_id, secure); +} +EXPORT_SYMBOL(qcom_scm_smmu_notify_secure_lut); + int qcom_scm_qdss_invoke(phys_addr_t paddr, size_t size, u64 *out) { return __qcom_scm_qdss_invoke(__scm->dev, paddr, size, out); } EXPORT_SYMBOL(qcom_scm_qdss_invoke); +int qcom_scm_camera_protect_phy_lanes(bool protect, u64 regmask) +{ + return __qcom_scm_camera_protect_phy_lanes(__scm->dev, protect, + regmask); +} +EXPORT_SYMBOL(qcom_scm_camera_protect_phy_lanes); + int qcom_scm_ice_restore_cfg(void) { return __qcom_scm_ice_restore_cfg(__scm->dev); diff --git a/drivers/firmware/qcom_scm.h b/drivers/firmware/qcom_scm.h index 692973ec678e..4e925c19ee5a 100644 --- a/drivers/firmware/qcom_scm.h +++ b/drivers/firmware/qcom_scm.h @@ -154,11 +154,13 @@ extern int __qcom_scm_hdcp_req(struct device *dev, #define QCOM_SCM_SVC_SMMU_PROGRAM 0x15 #define QCOM_SCM_SMMU_CHANGE_PGTBL_FORMAT 0x01 -#define QCOM_SCM_SMMU_CONFIG_ERRATA1 0x3 +#define QCOM_SCM_SMMU_SECURE_LUT 0x03 extern int __qcom_scm_smmu_change_pgtbl_format(struct device *dev, u64 dev_id, int cbndx); extern int __qcom_scm_qsmmu500_wait_safe_toggle(struct device *dev, bool enable); +extern int __qcom_scm_smmu_notify_secure_lut(struct device *dev, u64 dev_id, + bool secure); #define QCOM_SCM_SMMU_CONFIG_ERRATA1_CLIENT_ALL 0x2 #define QCOM_SCM_SVC_QDSS 0x16 @@ -166,6 +168,11 @@ extern int __qcom_scm_qsmmu500_wait_safe_toggle(struct device *dev, extern int __qcom_scm_qdss_invoke(struct device *dev, phys_addr_t addr, size_t size, u64 *out); +#define QCOM_SCM_SVC_CAMERA 0x18 +#define QCOM_SCM_CAMERA_PROTECT_PHY_LANES 0x07 +extern int __qcom_scm_camera_protect_phy_lanes(struct device *dev, + bool protect, u64 regmask); + // TOS Services and Function IDs #define QCOM_SCM_SVC_QSEELOG 0x01 #define QCOM_SCM_QSEELOG_REGISTER 0x06 diff --git a/include/linux/qcom_scm.h b/include/linux/qcom_scm.h index 38e1d3643bd6..ef19c6793b3e 100644 --- a/include/linux/qcom_scm.h +++ b/include/linux/qcom_scm.h @@ -97,7 +97,9 @@ extern int qcom_scm_create_shm_bridge(u64 pfn_and_ns_perm_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_smmu_notify_secure_lut(u64 dev_id, bool secure); extern int qcom_scm_qdss_invoke(phys_addr_t addr, size_t size, u64 *out); +extern int qcom_scm_camera_protect_phy_lanes(bool protect, u64 regmask); extern int qcom_scm_ice_restore_cfg(void); extern int qcom_scm_get_tz_log_feat_id(u64 *version); extern int qcom_scm_register_qsee_log_buf(phys_addr_t buf, size_t len); @@ -190,8 +192,12 @@ 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) { return -ENODEV; } +static inline int qcom_scm_smmu_notify_secure_lut(u64 dev_id, bool secure) + { return -EINVAL; } static inline int qcom_scm_qdss_invoke(phys_addr_t data, size_t size, u64 *out) { return -EINVAL; } +static inline int qcom_scm_camera_protect_phy_lanes(bool protect, u64 regmask) + { return -EINVAL; } static inline int qcom_scm_ice_restore_cfg(void) { return -ENODEV; } static inline int qcom_scm_get_tz_log_feat_id(u64 *version) { return -ENODEV; } From 6009e24b133f348ec93056f87305398bfe6ee4eb Mon Sep 17 00:00:00 2001 From: Elliot Berman Date: Mon, 14 Oct 2019 11:20:51 -0700 Subject: [PATCH 11/28] input: touchscreen: synaptics_dsx: Migrate SCM calls Migrate secure world calls to qcom_scm driver in synaptics_dsx_core.c. Change-Id: Ie339dcad416658a0f1227b9a9ee995799695dc94 Signed-off-by: Elliot Berman --- drivers/firmware/qcom_scm-smc.c | 22 ++++++++++++++++++++++ drivers/firmware/qcom_scm.c | 7 +++++++ drivers/firmware/qcom_scm.h | 5 +++++ include/linux/qcom_scm.h | 3 +++ 4 files changed, 37 insertions(+) diff --git a/drivers/firmware/qcom_scm-smc.c b/drivers/firmware/qcom_scm-smc.c index 5dc3b7319b19..33e6a46aec7b 100644 --- a/drivers/firmware/qcom_scm-smc.c +++ b/drivers/firmware/qcom_scm-smc.c @@ -853,6 +853,28 @@ int __qcom_scm_get_sec_dump_state(struct device *dev, u32 *dump_state) return ret; } +int __qcom_scm_tz_blsp_modify_owner(struct device *dev, int food, u64 subsystem, + int *out) +{ + int ret; + struct qcom_scm_desc desc = { + .svc = QCOM_SCM_SVC_TZ, + .cmd = QOCM_SCM_TZ_BLSP_MODIFY_OWNER, + .owner = ARM_SMCCC_OWNER_SIP + }; + + desc.args[0] = subsystem; + desc.args[1] = food; + desc.arginfo = QCOM_SCM_ARGS(2); + + ret = qcom_scm_call(dev, &desc); + + if (out) + *out = desc.res[0]; + + return ret; +} + int __qcom_scm_io_readl(struct device *dev, phys_addr_t addr, unsigned int *val) { diff --git a/drivers/firmware/qcom_scm.c b/drivers/firmware/qcom_scm.c index c53835171f2c..7c6b949fa110 100644 --- a/drivers/firmware/qcom_scm.c +++ b/drivers/firmware/qcom_scm.c @@ -329,6 +329,13 @@ int qcom_scm_get_sec_dump_state(u32 *dump_state) } EXPORT_SYMBOL(qcom_scm_get_sec_dump_state); +int qcom_scm_tz_blsp_modify_owner(int food, u64 subsystem, int *out) +{ + return __qcom_scm_tz_blsp_modify_owner(__scm->dev, subsystem, food, + out); +} +EXPORT_SYMBOL(qcom_scm_tz_blsp_modify_owner); + int qcom_scm_io_readl(phys_addr_t addr, unsigned int *val) { return __qcom_scm_io_readl(__scm->dev, addr, val); diff --git a/drivers/firmware/qcom_scm.h b/drivers/firmware/qcom_scm.h index 4e925c19ee5a..6a0cd805ed62 100644 --- a/drivers/firmware/qcom_scm.h +++ b/drivers/firmware/qcom_scm.h @@ -41,6 +41,11 @@ extern int __qcom_scm_pas_mss_reset(struct device *dev, bool reset); #define QCOM_SCM_UTIL_GET_SEC_DUMP_STATE 0x10 extern int __qcom_scm_get_sec_dump_state(struct device *dev, u32 *dump_state); +#define QCOM_SCM_SVC_TZ 0x04 +#define QOCM_SCM_TZ_BLSP_MODIFY_OWNER 0x03 +extern int __qcom_scm_tz_blsp_modify_owner(struct device *dev, int food, + u64 subsystem, int *out); + #define QCOM_SCM_SVC_IO 0x05 #define QCOM_SCM_IO_READ 0x01 #define QCOM_SCM_IO_WRITE 0x02 diff --git a/include/linux/qcom_scm.h b/include/linux/qcom_scm.h index ef19c6793b3e..3086587fa367 100644 --- a/include/linux/qcom_scm.h +++ b/include/linux/qcom_scm.h @@ -48,6 +48,7 @@ extern int qcom_scm_pas_mem_setup(u32 peripheral, phys_addr_t addr, extern int qcom_scm_pas_auth_and_reset(u32 peripheral); extern int qcom_scm_pas_shutdown(u32 peripheral); extern int qcom_scm_get_sec_dump_state(u32 *dump_state); +extern int qcom_scm_tz_blsp_modify_owner(int food, u64 subsystem, int *out); extern int qcom_scm_io_readl(phys_addr_t addr, unsigned int *val); extern int qcom_scm_io_writel(phys_addr_t addr, unsigned int val); extern int qcom_scm_io_reset(void); @@ -128,6 +129,8 @@ static inline int qcom_scm_pas_auth_and_reset(u32 peripheral) static inline int qcom_scm_pas_shutdown(u32 peripheral) { return -ENODEV; } static inline int qcom_scm_get_sec_dump_state(u32 *dump_state) {return -ENODEV; } +static inline int qcom_scm_tz_blsp_modify_owner(int food, u64 subsystem, + int *out) { return -ENODEV; } static inline int qcom_scm_io_readl(phys_addr_t addr, unsigned int *val) { return -ENODEV; } static inline int qcom_scm_io_writel(phys_addr_t addr, unsigned int val) From d98f9f01bfa7483a52d89663dc4fbe703a583378 Mon Sep 17 00:00:00 2001 From: Elliot Berman Date: Mon, 14 Oct 2019 14:04:19 -0700 Subject: [PATCH 12/28] firmware: qcom_scm: Add support for protecting videos Add secure world call to protect memory for video. Change-Id: I27a82d31054b8a2459738d3c7a2785abd357504f Signed-off-by: Elliot Berman --- drivers/firmware/qcom_scm-smc.c | 19 +++++++++++++++++++ drivers/firmware/qcom_scm.c | 8 ++++++++ drivers/firmware/qcom_scm.h | 4 ++++ include/linux/qcom_scm.h | 5 +++++ 4 files changed, 36 insertions(+) diff --git a/drivers/firmware/qcom_scm-smc.c b/drivers/firmware/qcom_scm-smc.c index 33e6a46aec7b..c05f7c1bb183 100644 --- a/drivers/firmware/qcom_scm-smc.c +++ b/drivers/firmware/qcom_scm-smc.c @@ -1054,6 +1054,25 @@ int __qcom_scm_iommu_secure_ptbl_init(struct device *dev, u64 addr, u32 size, return ret; } +int __qcom_scm_mem_protect_video(struct device *dev, + u32 cp_start, u32 cp_size, + u32 cp_nonpixel_start, u32 cp_nonpixel_size) +{ + struct qcom_scm_desc desc = { + .svc = QCOM_SCM_SVC_MP, + .cmd = QCOM_SCM_MP_MEM_PROTECT_VIDEO, + .owner = ARM_SMCCC_OWNER_SIP + }; + + desc.args[0] = cp_start; + desc.args[1] = cp_size; + desc.args[2] = cp_nonpixel_start; + desc.args[3] = cp_nonpixel_size; + desc.arginfo = QCOM_SCM_ARGS(4); + + return qcom_scm_call(dev, &desc); +} + int __qcom_scm_mem_protect_region_id(struct device *dev, phys_addr_t paddr, size_t size) { diff --git a/drivers/firmware/qcom_scm.c b/drivers/firmware/qcom_scm.c index 7c6b949fa110..5f4a42a4109b 100644 --- a/drivers/firmware/qcom_scm.c +++ b/drivers/firmware/qcom_scm.c @@ -388,6 +388,14 @@ int qcom_scm_iommu_secure_ptbl_init(u64 addr, u32 size, u32 spare) } EXPORT_SYMBOL(qcom_scm_iommu_secure_ptbl_init); +int qcom_scm_mem_protect_video(u32 cp_start, u32 cp_size, + u32 cp_nonpixel_start, u32 cp_nonpixel_size) +{ + return __qcom_scm_mem_protect_video(__scm->dev, cp_start, cp_size, + cp_nonpixel_start, cp_nonpixel_size); +} +EXPORT_SYMBOL(qcom_scm_mem_protect_video); + int qcom_scm_mem_protect_region_id(phys_addr_t paddr, size_t size) { return __qcom_scm_mem_protect_region_id(__scm->dev, paddr, size); diff --git a/drivers/firmware/qcom_scm.h b/drivers/firmware/qcom_scm.h index 6a0cd805ed62..5cfbe46b1971 100644 --- a/drivers/firmware/qcom_scm.h +++ b/drivers/firmware/qcom_scm.h @@ -71,6 +71,7 @@ extern void __qcom_scm_mmu_sync(struct device *dev, bool sync); #define QCOM_SCM_MP_RESTORE_SEC_CFG 0x02 #define QCOM_SCM_MP_IOMMU_SECURE_PTBL_SIZE 0x03 #define QCOM_SCM_MP_IOMMU_SECURE_PTBL_INIT 0x04 +#define QCOM_SCM_MP_MEM_PROTECT_VIDEO 0x08 #define QCOM_SCM_MP_MEM_PROTECT_REGION_ID 0x10 #define QCOM_SCM_MP_MEM_PROTECT_LOCK_ID2_FLAT 0x11 #define QCOM_SCM_MP_IOMMU_SECURE_MAP2_FLAT 0x12 @@ -87,6 +88,9 @@ extern int __qcom_scm_iommu_secure_ptbl_size(struct device *dev, u32 spare, size_t *size); extern int __qcom_scm_iommu_secure_ptbl_init(struct device *dev, u64 addr, u32 size, u32 spare); +extern int __qcom_scm_mem_protect_video(struct device *dev, + u32 cp_start, u32 cp_size, + u32 cp_nonpixel_start, u32 cp_nonpixel_size); extern int __qcom_scm_mem_protect_region_id(struct device *dev, phys_addr_t paddr, size_t size); extern int __qcom_scm_mem_protect_lock_id2_flat(struct device *dev, diff --git a/include/linux/qcom_scm.h b/include/linux/qcom_scm.h index 3086587fa367..aeec3199d410 100644 --- a/include/linux/qcom_scm.h +++ b/include/linux/qcom_scm.h @@ -57,6 +57,8 @@ extern void qcom_scm_mmu_sync(bool sync); extern int qcom_scm_restore_sec_cfg(u32 device_id, u32 spare); extern int qcom_scm_iommu_secure_ptbl_size(u32 spare, size_t *size); extern int qcom_scm_iommu_secure_ptbl_init(u64 addr, u32 size, u32 spare); +extern int qcom_scm_mem_protect_video(u32 cp_start, u32 cp_size, + u32 cp_nonpixel_start, u32 cp_nonpixel_size); extern int qcom_scm_mem_protect_region_id(phys_addr_t paddr, size_t size); extern int qcom_scm_mem_protect_lock_id2_flat(phys_addr_t list_addr, size_t list_size, size_t chunk_size, @@ -146,6 +148,9 @@ static inline int qcom_scm_iommu_secure_ptbl_size(u32 spare, size_t *size) { return -ENODEV; } static inline int qcom_scm_iommu_secure_ptbl_init(u64 addr, u32 size, u32 spare) { return -ENODEV; } +static inline int qcom_scm_mem_protect_video(u32 cp_start, u32 cp_size, + u32 cp_nonpixel_start, u32 cp_nonpixel_size) + { return -ENODEV; } static inline int qcom_scm_mem_protect_region_id(phys_addr_t paddr, size_t size) { return -ENODEV; } static inline int qcom_scm_mem_protect_lock_id2_flat(phys_addr_t list_addr, From d917dea1c2ee6e65a71ada985c3479f8c85fda98 Mon Sep 17 00:00:00 2001 From: Elliot Berman Date: Tue, 24 Sep 2019 15:53:03 -0700 Subject: [PATCH 13/28] msm: cvp: Migrate SCM calls Migrate setting CVP state to use upstream qcom_scm driver. Change-Id: Iac27ae205beae63cc8fb682c81065d706fcf9563 Signed-off-by: Elliot Berman --- drivers/media/platform/msm/cvp/cvp_hfi.c | 67 +++--------------------- 1 file changed, 8 insertions(+), 59 deletions(-) diff --git a/drivers/media/platform/msm/cvp/cvp_hfi.c b/drivers/media/platform/msm/cvp/cvp_hfi.c index 2dd7bd920541..cd563b0f6822 100644 --- a/drivers/media/platform/msm/cvp/cvp_hfi.c +++ b/drivers/media/platform/msm/cvp/cvp_hfi.c @@ -19,7 +19,7 @@ #include #include #include -#include +#include #include #include #include @@ -1184,28 +1184,20 @@ err_create_pkt: static int __tzbsp_set_cvp_state(enum tzbsp_subsys_state state) { - int tzbsp_rsp = 0; int rc = 0; - struct scm_desc desc = {0}; - desc.args[0] = state; - desc.args[1] = TZBSP_CVP_PAS_ID; - desc.arginfo = SCM_ARGS(2); + rc = qcom_scm_set_remote_state(state, TZBSP_CVP_PAS_ID); - rc = scm_call2(SCM_SIP_FNID(SCM_SVC_BOOT, - TZBSP_PIL_SET_STATE), &desc); - tzbsp_rsp = desc.ret[0]; - - if (rc) { - dprintk(CVP_ERR, "Failed scm_call %d\n", rc); + if (rc < 0) { + dprintk(CVP_ERR, "Failed qcom_scm_set_remote_state %d\n", rc); return rc; } - dprintk(CVP_DBG, "Set state %d, resp %d\n", state, tzbsp_rsp); - if (tzbsp_rsp) { + dprintk(CVP_DBG, "Set state %d, resp %d\n", state, rc); + if (rc) { dprintk(CVP_ERR, "Failed to set cvp core state to suspend: %d\n", - tzbsp_rsp); + rc); return -EINVAL; } @@ -3744,50 +3736,7 @@ static void __deinit_resources(struct iris_hfi_device *device) static int __protect_cp_mem(struct iris_hfi_device *device) { - struct cvp_tzbsp_memprot memprot; - unsigned int resp = 0; - int rc = 0; - struct context_bank_info *cb; - struct scm_desc desc = {0}; - - if (!device) - return -EINVAL; - - memprot.cp_start = 0x0; - memprot.cp_size = 0x0; - memprot.cp_nonpixel_start = 0x0; - memprot.cp_nonpixel_size = 0x0; - - list_for_each_entry(cb, &device->res->context_banks, list) { - if (!strcmp(cb->name, "cvp_hlos")) { - desc.args[1] = memprot.cp_size = - cb->addr_range.start; - dprintk(CVP_DBG, "%s memprot.cp_size: %#x\n", - __func__, memprot.cp_size); - } - - if (!strcmp(cb->name, "cvp_sec_nonpixel")) { - desc.args[2] = memprot.cp_nonpixel_start = - cb->addr_range.start; - desc.args[3] = memprot.cp_nonpixel_size = - cb->addr_range.size; - dprintk(CVP_DBG, - "%s memprot.cp_nonpixel_start: %#x size: %#x\n", - __func__, memprot.cp_nonpixel_start, - memprot.cp_nonpixel_size); - } - } - - desc.arginfo = SCM_ARGS(4); - rc = 0; - resp = desc.ret[0]; - - if (rc) { - dprintk(CVP_ERR, "Failed to protect memory(%d) response: %d\n", - rc, resp); - } - - return rc; + return device ? 0 : -EINVAL; } static int __disable_regulator(struct regulator_info *rinfo, From fb0a041246be511178d124267614b8d679a20874 Mon Sep 17 00:00:00 2001 From: Siddharth Gupta Date: Mon, 14 Oct 2019 15:38:35 -0700 Subject: [PATCH 14/28] thermal: qcom: Migrate SCM calls in lmh_dbg Migrate SCM calls present in lmh_dbg to use upstream driver conventions. Change-Id: I424e5a70fbc5886d7685740e64f8ec7d78edadf1 Signed-off-by: Siddharth Gupta Signed-off-by: Elliot Berman --- drivers/firmware/qcom_scm-smc.c | 88 +++++++++++++++++++++++++++++++++ drivers/firmware/qcom_scm.c | 57 +++++++++++++++++++++ drivers/firmware/qcom_scm.h | 15 ++++++ include/linux/qcom_scm.h | 27 ++++++++++ 4 files changed, 187 insertions(+) diff --git a/drivers/firmware/qcom_scm-smc.c b/drivers/firmware/qcom_scm-smc.c index c05f7c1bb183..555c22b76eee 100644 --- a/drivers/firmware/qcom_scm-smc.c +++ b/drivers/firmware/qcom_scm-smc.c @@ -1501,6 +1501,94 @@ int __qcom_scm_hdcp_req(struct device *dev, struct qcom_scm_hdcp_req *req, return ret; } +int __qcom_scm_lmh_read_buf_size(struct device *dev, int *size) +{ + int ret; + struct qcom_scm_desc desc = { + .svc = QCOM_SCM_SVC_LMH, + .cmd = QCOM_SCM_LMH_DEBUG_READ_BUF_SIZE, + .owner = ARM_SMCCC_OWNER_SIP + }; + + desc.arginfo = QCOM_SCM_ARGS(0); + + ret = qcom_scm_call(dev, &desc); + + if (size) + *size = desc.res[0]; + + return ret; +} + +int __qcom_scm_lmh_debug_read(struct device *dev, phys_addr_t payload, + uint32_t size) +{ + int ret; + struct qcom_scm_desc desc = { + .svc = QCOM_SCM_SVC_LMH, + .cmd = QCOM_SCM_LMH_DEBUG_READ, + .owner = ARM_SMCCC_OWNER_SIP + }; + + desc.args[0] = payload; + desc.args[1] = size; + desc.arginfo = QCOM_SCM_ARGS(2, QCOM_SCM_RW, QCOM_SCM_VAL); + + ret = qcom_scm_call(dev, &desc); + + return ret ? : desc.res[0]; +} + +int __qcom_scm_lmh_debug_config_write(struct device *dev, u64 cmd_id, + phys_addr_t payload, int payload_size, uint32_t *buf, + int buf_size) +{ + struct qcom_scm_desc desc = { + .svc = QCOM_SCM_SVC_LMH, + .cmd = cmd_id, + .owner = ARM_SMCCC_OWNER_SIP + }; + + if (buf_size < 3) + return -EINVAL; + + desc.args[0] = payload; + desc.args[1] = payload_size; + desc.args[2] = buf[0]; + desc.args[3] = buf[1]; + desc.args[4] = buf[2]; + desc.arginfo = QCOM_SCM_ARGS(5, QCOM_SCM_RO, QCOM_SCM_VAL, QCOM_SCM_VAL, + QCOM_SCM_VAL, QCOM_SCM_VAL); + + return qcom_scm_call(dev, &desc); +} + +int __qcom_scm_lmh_get_type(struct device *dev, phys_addr_t payload, + u64 payload_size, u64 debug_type, uint32_t get_from, + uint32_t *size) +{ + int ret; + struct qcom_scm_desc desc = { + .svc = QCOM_SCM_SVC_LMH, + .cmd = QCOM_SCM_LMH_DEBUG_GET_TYPE, + .owner = ARM_SMCCC_OWNER_SIP + }; + + desc.args[0] = payload; + desc.args[1] = payload_size; + desc.args[2] = debug_type; + desc.args[3] = get_from; + desc.arginfo = QCOM_SCM_ARGS(4, QCOM_SCM_RW, QCOM_SCM_VAL, QCOM_SCM_VAL, + QCOM_SCM_VAL); + + ret = qcom_scm_call(dev, &desc); + + if (size) + *size = desc.res[0]; + + return ret; +} + int __qcom_scm_smmu_change_pgtbl_format(struct device *dev, u64 dev_id, int cbndx) { diff --git a/drivers/firmware/qcom_scm.c b/drivers/firmware/qcom_scm.c index 5f4a42a4109b..40c31a147f95 100644 --- a/drivers/firmware/qcom_scm.c +++ b/drivers/firmware/qcom_scm.c @@ -675,6 +675,63 @@ int qcom_scm_hdcp_req(struct qcom_scm_hdcp_req *req, u32 req_cnt, u32 *resp) } EXPORT_SYMBOL(qcom_scm_hdcp_req); +bool qcom_scm_is_lmh_debug_set_available(void) +{ + return __qcom_scm_is_call_available(__scm->dev, QCOM_SCM_SVC_LMH, + QCOM_SCM_LMH_DEBUG_SET); +} +EXPORT_SYMBOL(qcom_scm_is_lmh_debug_set_available); + +bool qcom_scm_is_lmh_debug_read_buf_size_available(void) +{ + return __qcom_scm_is_call_available(__scm->dev, QCOM_SCM_SVC_LMH, + QCOM_SCM_LMH_DEBUG_READ_BUF_SIZE); +} +EXPORT_SYMBOL(qcom_scm_is_lmh_debug_read_buf_size_available); + +bool qcom_scm_is_lmh_debug_read_buf_available(void) +{ + return __qcom_scm_is_call_available(__scm->dev, QCOM_SCM_SVC_LMH, + QCOM_SCM_LMH_DEBUG_READ); +} +EXPORT_SYMBOL(qcom_scm_is_lmh_debug_read_buf_available); + +bool qcom_scm_is_lmh_debug_get_type_available(void) +{ + return __qcom_scm_is_call_available(__scm->dev, QCOM_SCM_SVC_LMH, + QCOM_SCM_LMH_DEBUG_GET_TYPE); +} +EXPORT_SYMBOL(qcom_scm_is_lmh_debug_get_type_available); + +int qcom_scm_lmh_read_buf_size(int *size) +{ + return __qcom_scm_lmh_read_buf_size(__scm->dev, size); +} +EXPORT_SYMBOL(qcom_scm_lmh_read_buf_size); + +int qcom_scm_lmh_debug_read(phys_addr_t payload, uint32_t size) +{ + return __qcom_scm_lmh_debug_read(__scm->dev, payload, size); +} +EXPORT_SYMBOL(qcom_scm_lmh_debug_read); + +int qcom_scm_lmh_debug_set_config_write(phys_addr_t payload, int payload_size, + uint32_t *buf, int buf_size) +{ + return __qcom_scm_lmh_debug_config_write(__scm->dev, + QCOM_SCM_LMH_DEBUG_SET, payload, payload_size, buf, + buf_size); +} +EXPORT_SYMBOL(qcom_scm_lmh_debug_set_config_write); + +int qcom_scm_lmh_get_type(phys_addr_t payload, u64 payload_size, + u64 debug_type, uint32_t get_from, uint32_t *size) +{ + return __qcom_scm_lmh_get_type(__scm->dev, payload, payload_size, + debug_type, get_from, size); +} +EXPORT_SYMBOL(qcom_scm_lmh_get_type); + int qcom_scm_smmu_change_pgtbl_format(u64 dev_id, int cbndx) { return __qcom_scm_smmu_change_pgtbl_format(__scm->dev, dev_id, cbndx); diff --git a/drivers/firmware/qcom_scm.h b/drivers/firmware/qcom_scm.h index 5cfbe46b1971..0e213fa24123 100644 --- a/drivers/firmware/qcom_scm.h +++ b/drivers/firmware/qcom_scm.h @@ -161,6 +161,21 @@ extern int __qcom_scm_clear_ice_key(struct device *dev, uint32_t index, extern int __qcom_scm_hdcp_req(struct device *dev, struct qcom_scm_hdcp_req *req, u32 req_cnt, u32 *resp); +#define QCOM_SCM_SVC_LMH 0x13 +#define QCOM_SCM_LMH_DEBUG_SET 0x08 +#define QCOM_SCM_LMH_DEBUG_READ_BUF_SIZE 0x09 +#define QCOM_SCM_LMH_DEBUG_READ 0x0A +#define QCOM_SCM_LMH_DEBUG_GET_TYPE 0x0B +extern int __qcom_scm_lmh_read_buf_size(struct device *dev, int *size); +extern int __qcom_scm_lmh_debug_read(struct device *dev, phys_addr_t payload, + uint32_t size); +extern int __qcom_scm_lmh_debug_config_write(struct device *dev, u64 cmd_id, + phys_addr_t payload, int payload_size, uint32_t *buf, + int buf_size); +extern int __qcom_scm_lmh_get_type(struct device *dev, phys_addr_t payload, + u64 payload_size, u64 debug_type, uint32_t get_from, + uint32_t *size); + #define QCOM_SCM_SVC_SMMU_PROGRAM 0x15 #define QCOM_SCM_SMMU_CHANGE_PGTBL_FORMAT 0x01 #define QCOM_SCM_SMMU_SECURE_LUT 0x03 diff --git a/include/linux/qcom_scm.h b/include/linux/qcom_scm.h index aeec3199d410..ffbe5e8f55d3 100644 --- a/include/linux/qcom_scm.h +++ b/include/linux/qcom_scm.h @@ -98,6 +98,16 @@ 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 bool qcom_scm_is_lmh_debug_set_available(void); +extern bool qcom_scm_is_lmh_debug_read_buf_size_available(void); +extern bool qcom_scm_is_lmh_debug_read_buf_available(void); +extern bool qcom_scm_is_lmh_debug_get_type_available(void); +extern int qcom_scm_lmh_read_buf_size(int *size); +extern int qcom_scm_lmh_debug_read(phys_addr_t payload, uint32_t size); +extern int qcom_scm_lmh_debug_set_config_write(phys_addr_t payload, + int payload_size, uint32_t *buf, int buf_size); +extern int qcom_scm_lmh_get_type(phys_addr_t payload, u64 payload_size, + u64 debug_type, uint32_t get_from, uint32_t *size); 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_smmu_notify_secure_lut(u64 dev_id, bool secure); @@ -196,6 +206,23 @@ 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 bool qcom_scm_is_lmh_debug_set_available(void) + { return -EINVAL; } +static inline bool qcom_scm_is_lmh_debug_read_buf_size_available(void) + { return -EINVAL; } +static inline bool qcom_scm_is_lmh_debug_read_buf_available(void) + { return -EINVAL; } +static inline bool qcom_scm_is_lmh_debug_get_type_available(void) + { return -EINVAL; } +static inline int qcom_scm_lmh_read_buf_size(int *size) { return -ENODEV; } +static inline int qcom_scm_lmh_debug_read(phys_addr_t payload, uint32_t size) + { return -ENODEV; } +static inline int qcom_scm_lmh_debug_set_config_write(phys_addr_t payload, + int payload_size, uint32_t *buf, int buf_size) + { return -ENODEV; } +static inline int qcom_scm_lmh_get_type(phys_addr_t payload, u64 payload_size, + u64 debug_type, uint32_t get_from, uint32_t *size) + { 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) From 89d665314e64fae4d735d7e355cddfd51c9f826b Mon Sep 17 00:00:00 2001 From: Siddharth Gupta Date: Thu, 17 Oct 2019 15:45:25 -0700 Subject: [PATCH 15/28] thermal: qcom: Migrate SCM calls in msm_lmh_dcvs Migrate SCM calls present in lmh_dbg to use the upstream driver. Change-Id: I6daa774f5dc3af630676c9f3f70f0a5d09a8e7b6 Signed-off-by: Siddharth Gupta Signed-off-by: Elliot Berman --- drivers/firmware/qcom_scm-smc.c | 21 +++++++++++++++++++++ drivers/firmware/qcom_scm.c | 8 ++++++++ drivers/firmware/qcom_scm.h | 4 ++++ include/linux/qcom_scm.h | 5 +++++ 4 files changed, 38 insertions(+) diff --git a/drivers/firmware/qcom_scm-smc.c b/drivers/firmware/qcom_scm-smc.c index 555c22b76eee..d3f96bc65b90 100644 --- a/drivers/firmware/qcom_scm-smc.c +++ b/drivers/firmware/qcom_scm-smc.c @@ -1520,6 +1520,27 @@ int __qcom_scm_lmh_read_buf_size(struct device *dev, int *size) return ret; } +int __qcom_scm_lmh_limit_dcvsh(struct device *dev, phys_addr_t payload, + uint32_t payload_size, u64 limit_node, uint32_t node_id, + u64 version) +{ + struct qcom_scm_desc desc = { + .svc = QCOM_SCM_SVC_LMH, + .cmd = QCOM_SCM_LMH_LIMIT_DCVSH, + .owner = ARM_SMCCC_OWNER_SIP + }; + + desc.args[0] = payload; + desc.args[1] = payload_size; + desc.args[2] = limit_node; + desc.args[3] = node_id; + desc.args[4] = version; + desc.arginfo = QCOM_SCM_ARGS(5, QCOM_SCM_RO, QCOM_SCM_VAL, QCOM_SCM_VAL, + QCOM_SCM_VAL, QCOM_SCM_VAL); + + return qcom_scm_call(dev, &desc); +} + int __qcom_scm_lmh_debug_read(struct device *dev, phys_addr_t payload, uint32_t size) { diff --git a/drivers/firmware/qcom_scm.c b/drivers/firmware/qcom_scm.c index 40c31a147f95..abef50024c7f 100644 --- a/drivers/firmware/qcom_scm.c +++ b/drivers/firmware/qcom_scm.c @@ -709,6 +709,14 @@ int qcom_scm_lmh_read_buf_size(int *size) } EXPORT_SYMBOL(qcom_scm_lmh_read_buf_size); +int qcom_scm_lmh_limit_dcvsh(phys_addr_t payload, uint32_t payload_size, + u64 limit_node, uint32_t node_id, u64 version) +{ + return __qcom_scm_lmh_limit_dcvsh(__scm->dev, payload, payload_size, + limit_node, node_id, version); +} +EXPORT_SYMBOL(qcom_scm_lmh_limit_dcvsh); + int qcom_scm_lmh_debug_read(phys_addr_t payload, uint32_t size) { return __qcom_scm_lmh_debug_read(__scm->dev, payload, size); diff --git a/drivers/firmware/qcom_scm.h b/drivers/firmware/qcom_scm.h index 0e213fa24123..c9eece2edc32 100644 --- a/drivers/firmware/qcom_scm.h +++ b/drivers/firmware/qcom_scm.h @@ -164,9 +164,13 @@ extern int __qcom_scm_hdcp_req(struct device *dev, #define QCOM_SCM_SVC_LMH 0x13 #define QCOM_SCM_LMH_DEBUG_SET 0x08 #define QCOM_SCM_LMH_DEBUG_READ_BUF_SIZE 0x09 +#define QCOM_SCM_LMH_LIMIT_DCVSH 0x10 #define QCOM_SCM_LMH_DEBUG_READ 0x0A #define QCOM_SCM_LMH_DEBUG_GET_TYPE 0x0B extern int __qcom_scm_lmh_read_buf_size(struct device *dev, int *size); +extern int __qcom_scm_lmh_limit_dcvsh(struct device *dev, phys_addr_t payload, + uint32_t payload_size, u64 limit_node, uint32_t node_id, + u64 version); extern int __qcom_scm_lmh_debug_read(struct device *dev, phys_addr_t payload, uint32_t size); extern int __qcom_scm_lmh_debug_config_write(struct device *dev, u64 cmd_id, diff --git a/include/linux/qcom_scm.h b/include/linux/qcom_scm.h index ffbe5e8f55d3..242172432db0 100644 --- a/include/linux/qcom_scm.h +++ b/include/linux/qcom_scm.h @@ -103,6 +103,8 @@ extern bool qcom_scm_is_lmh_debug_read_buf_size_available(void); extern bool qcom_scm_is_lmh_debug_read_buf_available(void); extern bool qcom_scm_is_lmh_debug_get_type_available(void); extern int qcom_scm_lmh_read_buf_size(int *size); +extern int qcom_scm_lmh_limit_dcvsh(phys_addr_t payload, uint32_t payload_size, + u64 limit_node, uint32_t node_id, u64 version); extern int qcom_scm_lmh_debug_read(phys_addr_t payload, uint32_t size); extern int qcom_scm_lmh_debug_set_config_write(phys_addr_t payload, int payload_size, uint32_t *buf, int buf_size); @@ -215,6 +217,9 @@ static inline bool qcom_scm_is_lmh_debug_read_buf_available(void) static inline bool qcom_scm_is_lmh_debug_get_type_available(void) { return -EINVAL; } static inline int qcom_scm_lmh_read_buf_size(int *size) { return -ENODEV; } +static inline int qcom_scm_lmh_limit_dcvsh(phys_addr_t payload, + uint32_t payload_size, u64 limit_node, uint32_t node_id, + u64 version) { return -ENODEV; } static inline int qcom_scm_lmh_debug_read(phys_addr_t payload, uint32_t size) { return -ENODEV; } static inline int qcom_scm_lmh_debug_set_config_write(phys_addr_t payload, From e7e95d870636e237ea08dfa3ec08e3906f139e0d Mon Sep 17 00:00:00 2001 From: Siddharth Gupta Date: Thu, 17 Oct 2019 15:46:36 -0700 Subject: [PATCH 16/28] firmware: qcom_scm: Add a scm calls for displace memory protect Add a scm calls for displace memory protect. Change-Id: I8a23b13f1917adcad5f627f0f55fc7702bd01cd7 Signed-off-by: Siddharth Gupta Signed-off-by: Elliot Berman --- drivers/firmware/qcom_scm-smc.c | 20 ++++++++++++++++++++ drivers/firmware/qcom_scm.c | 12 ++++++++++++ drivers/firmware/qcom_scm.h | 3 +++ include/linux/qcom_scm.h | 5 +++++ 4 files changed, 40 insertions(+) diff --git a/drivers/firmware/qcom_scm-smc.c b/drivers/firmware/qcom_scm-smc.c index d3f96bc65b90..093500f3f89a 100644 --- a/drivers/firmware/qcom_scm-smc.c +++ b/drivers/firmware/qcom_scm-smc.c @@ -1199,6 +1199,26 @@ int __qcom_scm_assign_mem(struct device *dev, phys_addr_t mem_region, return ret ? : desc.res[0]; } +int __qcom_scm_mem_protect_sd_ctrl(struct device *dev, u32 devid, + phys_addr_t mem_addr, u64 mem_size, u32 vmid) +{ + int ret; + struct qcom_scm_desc desc = { + .svc = QCOM_SCM_SVC_MP, + .cmd = QCOM_SCM_MP_CMD_SD_CTRL, + .owner = ARM_SMCCC_OWNER_SIP + }; + + desc.args[0] = devid; + desc.args[1] = mem_addr; + desc.args[2] = mem_size; + desc.args[3] = vmid; + desc.arginfo = QCOM_SCM_ARGS(4); + ret = qcom_scm_call(dev, &desc); + + return ret ? : desc.res[0]; +} + int __qcom_scm_kgsl_set_smmu_aperture(struct device *dev, unsigned int num_context_bank) { diff --git a/drivers/firmware/qcom_scm.c b/drivers/firmware/qcom_scm.c index abef50024c7f..949f283a22dd 100644 --- a/drivers/firmware/qcom_scm.c +++ b/drivers/firmware/qcom_scm.c @@ -510,6 +510,18 @@ int qcom_scm_assign_mem(phys_addr_t mem_addr, size_t mem_sz, } EXPORT_SYMBOL(qcom_scm_assign_mem); +/** + * qcom_scm_mem_protect_sd_ctrl() - SDE memory protect. + * + */ +int qcom_scm_mem_protect_sd_ctrl(u32 devid, phys_addr_t mem_addr, u64 mem_size, + u32 vmid) +{ + return __qcom_scm_mem_protect_sd_ctrl(__scm->dev, devid, mem_addr, + mem_size, vmid); +} +EXPORT_SYMBOL(qcom_scm_mem_protect_sd_ctrl); + bool qcom_scm_kgsl_set_smmu_aperture_available(void) { int ret; diff --git a/drivers/firmware/qcom_scm.h b/drivers/firmware/qcom_scm.h index c9eece2edc32..fb8fb0a6a883 100644 --- a/drivers/firmware/qcom_scm.h +++ b/drivers/firmware/qcom_scm.h @@ -77,6 +77,7 @@ extern void __qcom_scm_mmu_sync(struct device *dev, bool sync); #define QCOM_SCM_MP_IOMMU_SECURE_MAP2_FLAT 0x12 #define QCOM_SCM_MP_IOMMU_SECURE_UNMAP2_FLAT 0x13 #define QCOM_SCM_MP_ASSIGN 0x16 +#define QCOM_SCM_MP_CMD_SD_CTRL 0x18 #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 @@ -108,6 +109,8 @@ extern int __qcom_scm_assign_mem(struct device *dev, phys_addr_t mem_region, size_t mem_sz, phys_addr_t src, size_t src_sz, phys_addr_t dest, size_t dest_sz); +extern int __qcom_scm_mem_protect_sd_ctrl(struct device *dev, u32 devid, + phys_addr_t mem_addr, u64 mem_size, u32 vmid); 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); diff --git a/include/linux/qcom_scm.h b/include/linux/qcom_scm.h index 242172432db0..aafe1064d8ee 100644 --- a/include/linux/qcom_scm.h +++ b/include/linux/qcom_scm.h @@ -72,6 +72,8 @@ extern int qcom_scm_assign_mem(phys_addr_t mem_addr, size_t mem_sz, unsigned int *src, const struct qcom_scm_vmperm *newvm, unsigned int dest_cnt); +extern int qcom_scm_mem_protect_sd_ctrl(u32 devid, phys_addr_t mem_addr, + u64 mem_size, u32 vmid); extern bool qcom_scm_kgsl_set_smmu_aperture_available(void); extern int qcom_scm_kgsl_set_smmu_aperture( unsigned int num_context_bank); @@ -177,6 +179,9 @@ static inline int qcom_scm_assign_mem(phys_addr_t mem_addr, size_t mem_sz, unsigned int *src, const struct qcom_scm_vmperm *newvm, unsigned int dest_cnt) { return -ENODEV; } +static inline int qcom_scm_mem_protect_sd_ctrl(u32 devid, phys_addr_t mem_addr, + u64 mem_size, u32 vmid) + { return -ENODEV; } static inline bool qcom_scm_kgsl_set_smmu_aperture_available(void) { return false; } static inline int qcom_scm_kgsl_set_smmu_aperture( From d416ab102832781e500ffbf99e84a8219973fe48 Mon Sep 17 00:00:00 2001 From: Siddharth Gupta Date: Thu, 17 Oct 2019 15:49:00 -0700 Subject: [PATCH 17/28] firmware: qcom_scm: Add memory protection API for MDF Add memory protection API for MultiDSP framework as scm_call2 is depreciated on latest kernel. Change-Id: I935f29bf958e57498fd115022d9f6352adbab861 Signed-off-by: Siddharth Gupta Signed-off-by: Elliot Berman --- drivers/firmware/qcom_scm-smc.c | 20 ++++++++++++++++++++ drivers/firmware/qcom_scm.c | 12 ++++++++++++ drivers/firmware/qcom_scm.h | 3 +++ include/linux/qcom_scm.h | 5 +++++ 4 files changed, 40 insertions(+) diff --git a/drivers/firmware/qcom_scm-smc.c b/drivers/firmware/qcom_scm-smc.c index 093500f3f89a..70f3b6f5330f 100644 --- a/drivers/firmware/qcom_scm-smc.c +++ b/drivers/firmware/qcom_scm-smc.c @@ -1326,6 +1326,26 @@ int __qcom_scm_smmu_prepare_atos_id(struct device *dev, u64 dev_id, int cb_num, return ret; } +int __qcom_mdf_assign_memory_to_subsys(struct device *dev, u64 start_addr, + u64 end_addr, phys_addr_t paddr, u64 size) +{ + int ret; + struct qcom_scm_desc desc = { + .svc = QCOM_SCM_SVC_MP, + .cmd = QCOM_SCM_MP_MPU_LOCK_NS_REGION, + .owner = ARM_SMCCC_OWNER_SIP + }; + + desc.args[0] = start_addr; + desc.args[1] = end_addr; + desc.args[2] = paddr; + desc.args[3] = size; + desc.arginfo = QCOM_SCM_ARGS(4); + ret = qcom_scm_call(dev, &desc); + + return ret ? : desc.res[0]; +} + bool __qcom_scm_dcvs_core_available(struct device *dev) { return __qcom_scm_is_call_available(dev, QCOM_SCM_SVC_DCVS, diff --git a/drivers/firmware/qcom_scm.c b/drivers/firmware/qcom_scm.c index 949f283a22dd..477e99c53adf 100644 --- a/drivers/firmware/qcom_scm.c +++ b/drivers/firmware/qcom_scm.c @@ -569,6 +569,18 @@ int qcom_scm_smmu_prepare_atos_id(u64 dev_id, int cb_num, int operation) } EXPORT_SYMBOL(qcom_scm_smmu_prepare_atos_id); +/** + * qcom_mdf_assign_memory_to_subsys - SDE memory protect. + * + */ +int qcom_mdf_assign_memory_to_subsys(u64 start_addr, u64 end_addr, + phys_addr_t paddr, u64 size) +{ + return __qcom_mdf_assign_memory_to_subsys(__scm->dev, + start_addr, end_addr, paddr, size); +} +EXPORT_SYMBOL(qcom_mdf_assign_memory_to_subsys); + /** * qcom_scm_dcvs_core_available() - check if core DCVS operations are available */ diff --git a/drivers/firmware/qcom_scm.h b/drivers/firmware/qcom_scm.h index fb8fb0a6a883..b7c315352b88 100644 --- a/drivers/firmware/qcom_scm.h +++ b/drivers/firmware/qcom_scm.h @@ -83,6 +83,7 @@ extern void __qcom_scm_mmu_sync(struct device *dev, bool sync); #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 +#define QCOM_SCM_MP_MPU_LOCK_NS_REGION 0x25 extern int __qcom_scm_restore_sec_cfg(struct device *dev, u32 device_id, u32 spare); extern int __qcom_scm_iommu_secure_ptbl_size(struct device *dev, u32 spare, @@ -120,6 +121,8 @@ extern int __qcom_scm_create_shm_bridge(struct device *dev, 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); +extern int __qcom_mdf_assign_memory_to_subsys(struct device *dev, + u64 start_addr, u64 end_addr, phys_addr_t paddr, u64 size); #define QCOM_SCM_IOMMU_TLBINVAL_FLAG 0x00000001 #define QCOM_SCM_CP_APERTURE_REG 0x0 diff --git a/include/linux/qcom_scm.h b/include/linux/qcom_scm.h index aafe1064d8ee..8581a1056c4e 100644 --- a/include/linux/qcom_scm.h +++ b/include/linux/qcom_scm.h @@ -78,6 +78,8 @@ extern bool qcom_scm_kgsl_set_smmu_aperture_available(void); extern int qcom_scm_kgsl_set_smmu_aperture( unsigned int num_context_bank); extern int qcom_scm_smmu_prepare_atos_id(u64 dev_id, int cb_num, int operation); +extern int qcom_mdf_assign_memory_to_subsys(u64 start_addr, + u64 end_addr, phys_addr_t paddr, u64 size); extern bool qcom_scm_dcvs_core_available(void); extern bool qcom_scm_dcvs_ca_available(void); extern int qcom_scm_dcvs_reset(void); @@ -188,6 +190,9 @@ static inline int qcom_scm_kgsl_set_smmu_aperture( unsigned int num_context_bank) { return -ENODEV; } static inline int qcom_scm_smmu_prepare_atos_id(u64 dev_id, int cb_num, int operation) { return -ENODEV; } +static inline int qcom_mdf_assign_memory_to_subsys(struct device *dev, + u64 start_addr, u64 end_addr, phys_addr_t paddr, u64 size) + { return -ENODEV; } static inline bool qcom_scm_dcvs_core_available(void) { return false; } static inline bool qcom_scm_dcvs_ca_available(void) { return false; } static inline int qcom_scm_dcvs_init_v2(phys_addr_t addr, size_t size, From f278fbe3a92ab574fb685d34f5e345802c65f963 Mon Sep 17 00:00:00 2001 From: Siddharth Gupta Date: Thu, 17 Oct 2019 10:57:25 -0700 Subject: [PATCH 18/28] soc: qcom: Migrating to upstream SCM driver in smcinvoke Migrate the downstream SCM driver calls to the upstream driver calls. Change-Id: Idb94438e439a3bd17a95dd846e6d3bd683bab69e Signed-off-by: Siddharth Gupta Signed-off-by: Elliot Berman --- drivers/firmware/qcom_scm-smc.c | 58 +++++++++++++++++++++++++++++++++ drivers/firmware/qcom_scm.c | 17 ++++++++++ drivers/firmware/qcom_scm.h | 10 ++++++ include/linux/qcom_scm.h | 12 +++++++ 4 files changed, 97 insertions(+) diff --git a/drivers/firmware/qcom_scm-smc.c b/drivers/firmware/qcom_scm-smc.c index 70f3b6f5330f..e0d4cc8f6fcc 100644 --- a/drivers/firmware/qcom_scm-smc.c +++ b/drivers/firmware/qcom_scm-smc.c @@ -1774,6 +1774,64 @@ int __qcom_scm_register_qsee_log_buf(struct device *dev, phys_addr_t buf, return ret ? : desc.res[0]; } +int __qcom_scm_invoke_smc(struct device *dev, phys_addr_t in_buf, + size_t in_buf_size, phys_addr_t out_buf, size_t out_buf_size, + int32_t *result, u64 *response_type, unsigned int *data) +{ + int ret; + struct qcom_scm_desc desc = { + .svc = QCOM_SCM_SVC_SMCINVOKE, + .cmd = QCOM_SCM_SMCINVOKE_INVOKE, + .owner = ARM_SMCCC_OWNER_TRUSTED_OS + }; + + desc.args[0] = in_buf; + desc.args[1] = in_buf_size; + desc.args[2] = out_buf; + desc.args[3] = out_buf_size; + desc.arginfo = QCOM_SCM_ARGS(4, QCOM_SCM_RW, QCOM_SCM_VAL, QCOM_SCM_RW, + QCOM_SCM_VAL); + + ret = qcom_scm_call(dev, &desc); + + if (result) + *result = desc.res[1]; + + if (response_type) + *response_type = desc.res[0]; + + return ret; +} + +int __qcom_scm_invoke_callback_response(struct device *dev, phys_addr_t out_buf, + size_t out_buf_size, int32_t *result, u64 *response_type, + unsigned int *data) +{ + int ret; + struct qcom_scm_desc desc = { + .svc = QCOM_SCM_SVC_SMCINVOKE, + .cmd = QCOM_SCM_SMCINVOKE_CB_RSP, + .owner = ARM_SMCCC_OWNER_TRUSTED_OS + }; + + desc.args[0] = out_buf; + desc.args[1] = out_buf_size; + desc.arginfo = QCOM_SCM_ARGS(2, QCOM_SCM_RW, QCOM_SCM_VAL); + + ret = qcom_scm_call(dev, &desc); + + if (result) + *result = desc.res[1]; + + if (response_type) + *response_type = desc.res[0]; + + if (data) + *data = desc.res[2]; + + return ret; +} + void __qcom_scm_init(void) { __query_convention(); diff --git a/drivers/firmware/qcom_scm.c b/drivers/firmware/qcom_scm.c index 477e99c53adf..056d8e298e16 100644 --- a/drivers/firmware/qcom_scm.c +++ b/drivers/firmware/qcom_scm.c @@ -814,6 +814,23 @@ int qcom_scm_register_qsee_log_buf(phys_addr_t buf, size_t len) } EXPORT_SYMBOL(qcom_scm_register_qsee_log_buf); +int qcom_scm_invoke_smc(phys_addr_t in_buf, size_t in_buf_size, + phys_addr_t out_buf, size_t out_buf_size, int32_t *result, + u64 *response_type, unsigned int *data) +{ + return __qcom_scm_invoke_smc(__scm->dev, in_buf, in_buf_size, out_buf, + out_buf_size, result, response_type, data); +} +EXPORT_SYMBOL(qcom_scm_invoke_smc); + +int qcom_scm_invoke_callback_response(phys_addr_t out_buf, + size_t out_buf_size, int32_t *result, u64 *response_type, + unsigned int *data) +{ + return __qcom_scm_invoke_callback_response(__scm->dev, out_buf, + out_buf_size, result, response_type, data); +} + /** * qcom_scm_is_available() - Checks if SCM is available */ diff --git a/drivers/firmware/qcom_scm.h b/drivers/firmware/qcom_scm.h index b7c315352b88..3608bb27f84b 100644 --- a/drivers/firmware/qcom_scm.h +++ b/drivers/firmware/qcom_scm.h @@ -218,6 +218,16 @@ extern int __qcom_scm_register_qsee_log_buf(struct device *dev, phys_addr_t buf, #define QCOM_SCM_ICE_RESTORE_KEY_ID 0x06 extern int __qcom_scm_ice_restore_cfg(struct device *dev); +#define QCOM_SCM_SVC_SMCINVOKE 0x06 +#define QCOM_SCM_SMCINVOKE_INVOKE 0x00 +#define QCOM_SCM_SMCINVOKE_CB_RSP 0x01 +extern int __qcom_scm_invoke_smc(struct device *dev, phys_addr_t in_buf, + size_t in_buf_size, phys_addr_t out_buf, size_t out_buf_size, + int32_t *result, u64 *response_type, unsigned int *data); +extern int __qcom_scm_invoke_callback_response(struct device *dev, + phys_addr_t out_buf, size_t out_buf_size, int32_t *result, + u64 *response_type, unsigned int *data); + extern void __qcom_scm_init(void); /* common error codes */ diff --git a/include/linux/qcom_scm.h b/include/linux/qcom_scm.h index 8581a1056c4e..65df08faee23 100644 --- a/include/linux/qcom_scm.h +++ b/include/linux/qcom_scm.h @@ -122,6 +122,12 @@ extern int qcom_scm_camera_protect_phy_lanes(bool protect, u64 regmask); extern int qcom_scm_ice_restore_cfg(void); extern int qcom_scm_get_tz_log_feat_id(u64 *version); extern int qcom_scm_register_qsee_log_buf(phys_addr_t buf, size_t len); +extern int qcom_scm_invoke_smc(phys_addr_t in_buf, size_t in_buf_size, + phys_addr_t out_buf, size_t out_buf_size, int32_t *result, + u64 *response_type, unsigned int *data); +extern int qcom_scm_invoke_callback_response(phys_addr_t out_buf, + size_t out_buf_size, int32_t *result, u64 *response_type, + unsigned int *data); extern bool qcom_scm_is_available(void); #else @@ -253,6 +259,12 @@ static inline int qcom_scm_get_tz_log_feat_id(u64 *version) { return -ENODEV; } static inline int qcom_scm_register_qsee_log_buf(phys_addr_t buf, size_t len) { return -ENODEV; } +static inline int qcom_scm_invoke_smc(phys_addr_t in_buf, size_t in_buf_size, + phys_addr_t out_buf, size_t out_buf_size, int32_t *result, + u64 *request_type, unsigned int *data) { return -ENODEV; } +static inline int qcom_scm_invoke_callback_response(phys_addr_t out_buf, + size_t out_buf_size, int32_t *result, u64 *request_type, + unsigned int *data) { return -ENODEV; } static inline bool qcom_scm_is_available(void) { return false; } #endif #endif From 6c33f33594d9cf8d83d351aeea7ee28f5cbe0ae5 Mon Sep 17 00:00:00 2001 From: Elliot Berman Date: Thu, 17 Oct 2019 16:49:06 -0700 Subject: [PATCH 19/28] soc: qcom: Prune unused SCM calls Prune unused SCM calls for upstream SCM driver migration. Change-Id: Ic29d3085d2df6c5d9a276aaa22e0710951313615 Signed-off-by: Elliot Berman --- drivers/soc/qcom/dcc_v2.c | 1 - drivers/soc/qcom/memory_dump_v2.c | 27 +-------------------------- 2 files changed, 1 insertion(+), 27 deletions(-) diff --git a/drivers/soc/qcom/dcc_v2.c b/drivers/soc/qcom/dcc_v2.c index 795e1cfc2e5d..ccaaea742a48 100644 --- a/drivers/soc/qcom/dcc_v2.c +++ b/drivers/soc/qcom/dcc_v2.c @@ -15,7 +15,6 @@ #include #include #include -#include #include #define TIMEOUT_US (100) diff --git a/drivers/soc/qcom/memory_dump_v2.c b/drivers/soc/qcom/memory_dump_v2.c index 49f93c9b604c..2eff0ac56faa 100644 --- a/drivers/soc/qcom/memory_dump_v2.c +++ b/drivers/soc/qcom/memory_dump_v2.c @@ -12,15 +12,13 @@ #include #include #include -#include +#include #include #include #include #define MSM_DUMP_TABLE_VERSION MSM_DUMP_MAKE_VERSION(2, 0) -#define SCM_CMD_DEBUG_LAR_UNLOCK 0x4 - struct msm_dump_table { uint32_t version; uint32_t num_entries; @@ -227,29 +225,6 @@ err0: } early_initcall(init_memory_dump); -#ifdef CONFIG_MSM_DEBUG_LAR_UNLOCK -static int __init init_debug_lar_unlock(void) -{ - int ret; - uint32_t argument = 0; - struct scm_desc desc = {0}; - - if (!is_scm_armv8()) - ret = scm_call(SCM_SVC_TZ, SCM_CMD_DEBUG_LAR_UNLOCK, &argument, - sizeof(argument), NULL, 0); - else - ret = scm_call2(SCM_SIP_FNID(SCM_SVC_TZ, - SCM_CMD_DEBUG_LAR_UNLOCK), &desc); - if (ret) - pr_err("Core Debug Lock unlock failed, ret: %d\n", ret); - else - pr_info("Core Debug Lock unlocked\n"); - - return ret; -} -early_initcall(init_debug_lar_unlock); -#endif - static int mem_dump_probe(struct platform_device *pdev) { struct device_node *child_node; From ec51a0f5ea90ce107eeddbb1223f0a9ecf023538 Mon Sep 17 00:00:00 2001 From: Siddharth Gupta Date: Wed, 11 Sep 2019 16:52:53 -0700 Subject: [PATCH 20/28] firmware: qcom_scm: Permit early SCM calls before driver probe In some cases we need to make early SCM calls, i.e., when the driver has not been probed. Adding NULL dereference checks to handle such cases. Change-Id: I4e6e6821795ed5833e59350865a17530494c52f9 Signed-off-by: Siddharth Gupta Signed-off-by: Elliot Berman --- drivers/firmware/qcom_scm.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/firmware/qcom_scm.c b/drivers/firmware/qcom_scm.c index 056d8e298e16..fc2081c2c94d 100644 --- a/drivers/firmware/qcom_scm.c +++ b/drivers/firmware/qcom_scm.c @@ -338,13 +338,13 @@ EXPORT_SYMBOL(qcom_scm_tz_blsp_modify_owner); int qcom_scm_io_readl(phys_addr_t addr, unsigned int *val) { - return __qcom_scm_io_readl(__scm->dev, addr, val); + return __qcom_scm_io_readl(__scm ? __scm->dev : NULL, addr, val); } EXPORT_SYMBOL(qcom_scm_io_readl); int qcom_scm_io_writel(phys_addr_t addr, unsigned int val) { - return __qcom_scm_io_writel(__scm->dev, addr, val); + return __qcom_scm_io_writel(__scm ? __scm->dev : NULL, addr, val); } EXPORT_SYMBOL(qcom_scm_io_writel); From f8bf2650d230109be8e37f2e4d0d279f14ffe35b Mon Sep 17 00:00:00 2001 From: "Isaac J. Manjarres" Date: Mon, 21 Oct 2019 15:24:58 -0700 Subject: [PATCH 21/28] firmware: qcom_scm: Add support to assign multiple memory regions The secure world allows for changing the ownership of multiple (not necessarily physically contiguous) memory regions in one secure call. Thus, expose an interface for clients to assign more than one memory region per secure call. Change-Id: Ic444627daee9d735b8b039ae3965e861cdcd110a Signed-off-by: Isaac J. Manjarres Signed-off-by: Elliot Berman --- drivers/firmware/qcom_scm.c | 46 ++++++++++++++++++++++++++---------- include/linux/qcom_scm.h | 47 +++++++++++++++++++++++++++++++++++++ 2 files changed, 80 insertions(+), 13 deletions(-) diff --git a/drivers/firmware/qcom_scm.c b/drivers/firmware/qcom_scm.c index fc2081c2c94d..8a1451a93ea1 100644 --- a/drivers/firmware/qcom_scm.c +++ b/drivers/firmware/qcom_scm.c @@ -37,19 +37,6 @@ struct qcom_scm { u64 dload_mode_addr; }; -struct qcom_scm_current_perm_info { - __le32 vmid; - __le32 perm; - __le64 ctx; - __le32 ctx_size; - __le32 unused; -}; - -struct qcom_scm_mem_map_info { - __le64 mem_addr; - __le64 mem_size; -}; - static struct qcom_scm *__scm; static int qcom_scm_clk_enable(void) @@ -428,6 +415,39 @@ int qcom_scm_iommu_secure_unmap(u64 sec_id, int cbndx, unsigned long iova, } EXPORT_SYMBOL(qcom_scm_iommu_secure_unmap); +/** + * qcom_scm_assign_mem_regions() - Make a secure call to reassign memory + * ownership of several memory regions + * @mem_regions: A buffer describing the set of memory regions that need to + * be reassigned + * @mem_regions_sz: The size of the buffer describing the set of memory + * regions that need to be reassigned (in bytes) + * @srcvms: A buffer populated with he vmid(s) for the current set of + * owners + * @src_sz: The size of the src_vms buffer (in bytes) + * @newvms: A buffer populated with the new owners and corresponding + * permission flags. + * @newvms_sz: The size of the new_vms buffer (in bytes) + * + * NOTE: It is up to the caller to ensure that the buffers that will be accessed + * by the secure world are cache aligned, and have been flushed prior to + * invoking this call. + * + * Return negative errno on failure, 0 on success. + */ +int qcom_scm_assign_mem_regions(struct qcom_scm_mem_map_info *mem_regions, + size_t mem_regions_sz, u32 *srcvms, + size_t src_sz, + struct qcom_scm_current_perm_info *newvms, + size_t newvms_sz) +{ + return __qcom_scm_assign_mem(__scm ? __scm->dev : NULL, + virt_to_phys(mem_regions), mem_regions_sz, + virt_to_phys(srcvms), src_sz, + virt_to_phys(newvms), newvms_sz); +} +EXPORT_SYMBOL(qcom_scm_assign_mem_regions); + /** * qcom_scm_assign_mem() - Make a secure call to reassign memory ownership * @mem_addr: mem region whose ownership need to be reassigned diff --git a/include/linux/qcom_scm.h b/include/linux/qcom_scm.h index 65df08faee23..5eb2c7be417f 100644 --- a/include/linux/qcom_scm.h +++ b/include/linux/qcom_scm.h @@ -24,6 +24,19 @@ struct qcom_scm_vmperm { int perm; }; +struct qcom_scm_current_perm_info { + __le32 vmid; + __le32 perm; + __le64 ctx; + __le32 ctx_size; + __le32 unused; +}; + +struct qcom_scm_mem_map_info { + __le64 mem_addr; + __le64 mem_size; +}; + #define QCOM_SCM_VMID_HLOS 0x3 #define QCOM_SCM_VMID_MSS_MSA 0xF #define QCOM_SCM_VMID_WLAN 0x18 @@ -34,6 +47,30 @@ struct qcom_scm_vmperm { #define QCOM_SCM_PERM_RW (QCOM_SCM_PERM_READ | QCOM_SCM_PERM_WRITE) #define QCOM_SCM_PERM_RWX (QCOM_SCM_PERM_RW | QCOM_SCM_PERM_EXEC) +static inline void qcom_scm_populate_vmperm_info( + struct qcom_scm_current_perm_info *destvm, int vmid, int perm) +{ + if (!destvm) + return; + + destvm->vmid = cpu_to_le32(vmid); + destvm->perm = cpu_to_le32(perm); + destvm->ctx = 0; + destvm->ctx_size = 0; +} + +static inline void qcom_scm_populate_mem_map_info( + struct qcom_scm_mem_map_info *mem_to_map, + phys_addr_t mem_addr, size_t mem_size) +{ + if (!mem_to_map) + return; + + mem_to_map->mem_addr = cpu_to_le64(mem_addr); + mem_to_map->mem_size = cpu_to_le64(mem_size); +} + + #if IS_ENABLED(CONFIG_QCOM_SCM) extern int qcom_scm_set_cold_boot_addr(void *entry, const cpumask_t *cpus); extern int qcom_scm_set_warm_boot_addr(void *entry, const cpumask_t *cpus); @@ -68,6 +105,11 @@ extern int qcom_scm_iommu_secure_map(phys_addr_t sg_list_addr, size_t num_sg, unsigned long iova, size_t total_len); extern int qcom_scm_iommu_secure_unmap(u64 sec_id, int cbndx, unsigned long iova, size_t total_len); +extern int +qcom_scm_assign_mem_regions(struct qcom_scm_mem_map_info *mem_regions, + size_t mem_regions_sz, u32 *srcvms, size_t src_sz, + struct qcom_scm_current_perm_info *newvms, + size_t newvms_sz); extern int qcom_scm_assign_mem(phys_addr_t mem_addr, size_t mem_sz, unsigned int *src, const struct qcom_scm_vmperm *newvm, @@ -183,6 +225,11 @@ static inline int qcom_scm_iommu_secure_map(phys_addr_t sg_list_addr, unsigned long iova, size_t total_len) { return -ENODEV; } static inline int qcom_scm_iommu_secure_unmap(u64 sec_id, int cbndx, unsigned long iova, size_t total_len) { return -ENODEV; } +static inline int +qcom_scm_assign_mem_regions(struct qcom_scm_mem_map_info *mem_regions, + size_t mem_regions_sz, u32 *srcvms, size_t src_sz, + struct qcom_scm_current_perm_info *newvms, + size_t newvms_sz) { return -ENODEV; } static inline int qcom_scm_assign_mem(phys_addr_t mem_addr, size_t mem_sz, unsigned int *src, const struct qcom_scm_vmperm *newvm, From ff2fa44e3b318a2a0d86e0261964f5786ad9caba Mon Sep 17 00:00:00 2001 From: "Isaac J. Manjarres" Date: Mon, 21 Oct 2019 15:34:27 -0700 Subject: [PATCH 22/28] soc: qcom: secure_buffer: Migrate to qcom_scm usage Use qcom_scm_assign_mem_regions() when switching ownership of several memory regions. Change-Id: If6337af580e9e0cf4b484f81bd2870a02292cdba Signed-off-by: Isaac J. Manjarres Signed-off-by: Elliot Berman --- drivers/soc/qcom/secure_buffer.c | 80 ++++++++++++-------------- drivers/soc/qcom/trace_secure_buffer.h | 8 +-- include/soc/qcom/secure_buffer.h | 12 ---- 3 files changed, 41 insertions(+), 59 deletions(-) diff --git a/drivers/soc/qcom/secure_buffer.c b/drivers/soc/qcom/secure_buffer.c index c5145410b959..ff6932efa770 100644 --- a/drivers/soc/qcom/secure_buffer.c +++ b/drivers/soc/qcom/secure_buffer.c @@ -13,23 +13,22 @@ #include #include #include -#include +#include #include #define CREATE_TRACE_POINTS #include "trace_secure_buffer.h" -#define MEM_PROT_ASSIGN_ID 0x16 #define BATCH_MAX_SIZE SZ_2M #define BATCH_MAX_SECTIONS 32 static struct device *qcom_secure_buffer_dev; -static struct dest_vm_and_perm_info * +static struct qcom_scm_current_perm_info * populate_dest_info(int *dest_vmids, int nelements, int *dest_perms, size_t *size_in_bytes) { - struct dest_vm_and_perm_info *dest_info; + struct qcom_scm_current_perm_info *dest_info; int i; size_t size; @@ -42,18 +41,15 @@ populate_dest_info(int *dest_vmids, int nelements, int *dest_perms, if (!dest_info) return NULL; - for (i = 0; i < nelements; i++) { - dest_info[i].vm = dest_vmids[i]; - dest_info[i].perm = dest_perms[i]; - dest_info[i].ctx = 0x0; - dest_info[i].ctx_size = 0; - } + for (i = 0; i < nelements; i++) + qcom_scm_populate_vmperm_info(&dest_info[i], dest_vmids[i], + dest_perms[i]); *size_in_bytes = size; return dest_info; } -static unsigned int get_batches_from_sgl(struct mem_prot_info *sg_table_copy, +static unsigned int get_batches_from_sgl(struct qcom_scm_mem_map_info *sgt_copy, struct scatterlist *sgl, struct scatterlist **next_sgl) { @@ -63,9 +59,10 @@ static unsigned int get_batches_from_sgl(struct mem_prot_info *sg_table_copy, /* Ensure no zero size batches */ do { - sg_table_copy[i].addr = page_to_phys(sg_page(curr_sgl)); - sg_table_copy[i].size = curr_sgl->length; - batch_size += sg_table_copy[i].size; + qcom_scm_populate_mem_map_info(&sgt_copy[i], + page_to_phys(sg_page(curr_sgl)), + curr_sgl->length); + batch_size += curr_sgl->length; curr_sgl = sg_next(curr_sgl); i++; } while (curr_sgl && i < BATCH_MAX_SECTIONS && @@ -75,9 +72,11 @@ static unsigned int get_batches_from_sgl(struct mem_prot_info *sg_table_copy, return i; } -static int batched_hyp_assign(struct sg_table *table, struct scm_desc *desc) +static int batched_hyp_assign(struct sg_table *table, u32 *source_vmids, + size_t source_size, + struct qcom_scm_current_perm_info *destvms, + size_t destvms_size) { - unsigned int entries_size; unsigned int batch_start = 0; unsigned int batches_processed; unsigned int i = 0; @@ -87,40 +86,44 @@ static int batched_hyp_assign(struct sg_table *table, struct scm_desc *desc) int ret = 0; ktime_t batch_assign_start_ts; ktime_t first_assign_ts; - struct mem_prot_info *sg_table_copy = kcalloc(BATCH_MAX_SECTIONS, - sizeof(*sg_table_copy), - GFP_KERNEL); + struct qcom_scm_mem_map_info *mem_regions_buf = + kcalloc(BATCH_MAX_SECTIONS, sizeof(*mem_regions_buf), + GFP_KERNEL); dma_addr_t entries_dma_addr; + size_t mem_regions_buf_size; - if (!sg_table_copy) + if (!mem_regions_buf) return -ENOMEM; first_assign_ts = ktime_get(); while (batch_start < table->nents) { - batches_processed = get_batches_from_sgl(sg_table_copy, + batches_processed = get_batches_from_sgl(mem_regions_buf, curr_sgl, &next_sgl); curr_sgl = next_sgl; - entries_size = batches_processed * sizeof(*sg_table_copy); + mem_regions_buf_size = batches_processed * + sizeof(*mem_regions_buf); entries_dma_addr = dma_map_single(qcom_secure_buffer_dev, - sg_table_copy, entries_size, + mem_regions_buf, + mem_regions_buf_size, DMA_TO_DEVICE); if (dma_mapping_error(qcom_secure_buffer_dev, entries_dma_addr)) { ret = -EADDRNOTAVAIL; break; } - desc->args[0] = entries_dma_addr; - desc->args[1] = entries_size; - trace_hyp_assign_batch_start(sg_table_copy, batches_processed); + trace_hyp_assign_batch_start(mem_regions_buf, + batches_processed); batch_assign_start_ts = ktime_get(); - ret = scm_call2(SCM_SIP_FNID(SCM_SVC_MP, - MEM_PROT_ASSIGN_ID), desc); + ret = qcom_scm_assign_mem_regions(mem_regions_buf, + mem_regions_buf_size, + source_vmids, source_size, + destvms, destvms_size); trace_hyp_assign_batch_end(ret, ktime_us_delta(ktime_get(), batch_assign_start_ts)); dma_unmap_single(qcom_secure_buffer_dev, entries_dma_addr, - entries_size, DMA_TO_DEVICE); + mem_regions_buf_size, DMA_TO_DEVICE); i++; if (ret) { @@ -138,7 +141,7 @@ static int batched_hyp_assign(struct sg_table *table, struct scm_desc *desc) } total_delta = ktime_us_delta(ktime_get(), first_assign_ts); trace_hyp_assign_end(total_delta, div64_u64(total_delta, i)); - kfree(sg_table_copy); + kfree(mem_regions_buf); return ret; } @@ -152,10 +155,9 @@ int hyp_assign_table(struct sg_table *table, int dest_nelems) { int ret = 0; - struct scm_desc desc = {0}; u32 *source_vm_copy; size_t source_vm_copy_size; - struct dest_vm_and_perm_info *dest_vm_copy; + struct qcom_scm_current_perm_info *dest_vm_copy; size_t dest_vm_copy_size; dma_addr_t source_dma_addr, dest_dma_addr; @@ -197,20 +199,12 @@ int hyp_assign_table(struct sg_table *table, goto out_free_dest; } - - desc.args[2] = source_dma_addr; - desc.args[3] = source_vm_copy_size; - desc.args[4] = dest_dma_addr; - desc.args[5] = dest_vm_copy_size; - desc.args[6] = 0; - - desc.arginfo = SCM_ARGS(7, SCM_RO, SCM_VAL, SCM_RO, SCM_VAL, SCM_RO, - SCM_VAL, SCM_VAL); - trace_hyp_assign_info(source_vm_list, source_nelems, dest_vmids, dest_perms, dest_nelems); - ret = batched_hyp_assign(table, &desc); + + ret = batched_hyp_assign(table, source_vm_copy, source_vm_copy_size, + dest_vm_copy, dest_vm_copy_size); dma_unmap_single(qcom_secure_buffer_dev, dest_dma_addr, dest_vm_copy_size, DMA_TO_DEVICE); diff --git a/drivers/soc/qcom/trace_secure_buffer.h b/drivers/soc/qcom/trace_secure_buffer.h index f0655c8fa270..2fef8079fd56 100644 --- a/drivers/soc/qcom/trace_secure_buffer.h +++ b/drivers/soc/qcom/trace_secure_buffer.h @@ -52,7 +52,7 @@ TRACE_EVENT(hyp_assign_info, TRACE_EVENT(hyp_assign_batch_start, - TP_PROTO(struct mem_prot_info *info, int info_nelems), + TP_PROTO(struct qcom_scm_mem_map_info *info, int info_nelems), TP_ARGS(info, info_nelems), @@ -72,9 +72,9 @@ TRACE_EVENT(hyp_assign_batch_start, __entry->batch_size = 0; for (i = 0; i < info_nelems; i++) { - addr_arr_ptr[i] = info[i].addr; - sizes_arr_ptr[i] = info[i].size; - __entry->batch_size += info[i].size; + addr_arr_ptr[i] = info[i].mem_addr; + sizes_arr_ptr[i] = info[i].mem_size; + __entry->batch_size += info[i].mem_size; } ), diff --git a/include/soc/qcom/secure_buffer.h b/include/soc/qcom/secure_buffer.h index 0e43db3c96ac..584a0b8814d8 100644 --- a/include/soc/qcom/secure_buffer.h +++ b/include/soc/qcom/secure_buffer.h @@ -41,18 +41,6 @@ enum vmid { #define PERM_WRITE 0x2 #define PERM_EXEC 0x1 -struct dest_vm_and_perm_info { - u32 vm; - u32 perm; - u64 ctx; - u32 ctx_size; -}; - -struct mem_prot_info { - phys_addr_t addr; - u64 size; -}; - #if IS_ENABLED(CONFIG_QCOM_SECURE_BUFFER) int hyp_assign_table(struct sg_table *table, u32 *source_vm_list, int source_nelems, From d0a14e5c2c7b2a86f5c3b151add7931acf3f50b3 Mon Sep 17 00:00:00 2001 From: Siddharth Gupta Date: Fri, 11 Oct 2019 23:15:28 -0700 Subject: [PATCH 23/28] soc: qcom: Migrate SCM calls in secure_buffer Migrate SCM calls to use the upstream SCM driver. Change-Id: I09d5a64f18de4c691c20d3bb94371cdf6385b1d5 Signed-off-by: Siddharth Gupta Signed-off-by: Elliot Berman --- drivers/firmware/qcom_scm.c | 7 +++++++ drivers/firmware/qcom_scm.h | 1 + drivers/soc/qcom/Kconfig | 2 +- include/linux/qcom_scm.h | 3 +++ 4 files changed, 12 insertions(+), 1 deletion(-) diff --git a/drivers/firmware/qcom_scm.c b/drivers/firmware/qcom_scm.c index 8a1451a93ea1..4fce62a76d0f 100644 --- a/drivers/firmware/qcom_scm.c +++ b/drivers/firmware/qcom_scm.c @@ -601,6 +601,13 @@ int qcom_mdf_assign_memory_to_subsys(u64 start_addr, u64 end_addr, } EXPORT_SYMBOL(qcom_mdf_assign_memory_to_subsys); +int qcom_scm_get_feat_version_cp(u64 *version) +{ + return __qcom_scm_get_feat_version(__scm->dev, QCOM_SCM_MP_CP_FEAT_ID, + version); +} +EXPORT_SYMBOL(qcom_scm_get_feat_version_cp); + /** * qcom_scm_dcvs_core_available() - check if core DCVS operations are available */ diff --git a/drivers/firmware/qcom_scm.h b/drivers/firmware/qcom_scm.h index 3608bb27f84b..ddf022702836 100644 --- a/drivers/firmware/qcom_scm.h +++ b/drivers/firmware/qcom_scm.h @@ -62,6 +62,7 @@ extern int __qcom_scm_is_call_available(struct device *dev, u32 svc_id, extern int __qcom_scm_get_feat_version(struct device *dev, u64 feat_id, u64 *version); #define QCOM_SCM_TZ_DBG_ETM_FEAT_ID 0x08 +#define QCOM_SCM_MP_CP_FEAT_ID 0x0c #define QCOM_SCM_SVC_PWR 0x09 #define QCOM_SCM_PWR_MMU_SYNC 0x08 diff --git a/drivers/soc/qcom/Kconfig b/drivers/soc/qcom/Kconfig index 288f8d33d01d..73a33eafceb6 100644 --- a/drivers/soc/qcom/Kconfig +++ b/drivers/soc/qcom/Kconfig @@ -380,7 +380,7 @@ config QCOM_SECURE_CHAN_MANAGER config QCOM_SECURE_BUFFER tristate "Helper functions for secure buffers through TZ" - depends on QCOM_SECURE_CHAN_MANAGER + depends on QCOM_SCM help Enable for targets that need to call into TZ to secure memory buffers. This ensures that only the correct clients can diff --git a/include/linux/qcom_scm.h b/include/linux/qcom_scm.h index 5eb2c7be417f..5be160ea3a8e 100644 --- a/include/linux/qcom_scm.h +++ b/include/linux/qcom_scm.h @@ -116,6 +116,7 @@ extern int qcom_scm_assign_mem(phys_addr_t mem_addr, size_t mem_sz, unsigned int dest_cnt); extern int qcom_scm_mem_protect_sd_ctrl(u32 devid, phys_addr_t mem_addr, u64 mem_size, u32 vmid); +extern int qcom_scm_get_feat_version_cp(u64 *version); extern bool qcom_scm_kgsl_set_smmu_aperture_available(void); extern int qcom_scm_kgsl_set_smmu_aperture( unsigned int num_context_bank); @@ -246,6 +247,8 @@ static inline int qcom_scm_smmu_prepare_atos_id(u64 dev_id, int cb_num, static inline int qcom_mdf_assign_memory_to_subsys(struct device *dev, u64 start_addr, u64 end_addr, phys_addr_t paddr, u64 size) { return -ENODEV; } +static inline int qcom_scm_get_feat_version_cp(u64 *version) + { return -ENODEV; } static inline bool qcom_scm_dcvs_core_available(void) { return false; } static inline bool qcom_scm_dcvs_ca_available(void) { return false; } static inline int qcom_scm_dcvs_init_v2(phys_addr_t addr, size_t size, From 0213ebc079113202e2bf7748617653e65e7702a4 Mon Sep 17 00:00:00 2001 From: Siddharth Gupta Date: Fri, 18 Oct 2019 14:45:50 -0700 Subject: [PATCH 24/28] firmware: qcom_smc: Add compatibility layer for qseecom Adding a compatibility layer so that only header changes are required for qseecom. This change will exist only for Lahaina bring up. Change-Id: I5b69dd02491416e4b593c42c85a2ffcf97280020 Signed-off-by: Siddharth Gupta Signed-off-by: Elliot Berman --- drivers/firmware/Makefile | 2 +- drivers/firmware/qcom_scm-smc.c | 22 ++++++++ drivers/firmware/qcom_smc.c | 19 +++++++ include/soc/qcom/qseecom_scm.h | 99 +++++++++++++++++++++++++++++++++ 4 files changed, 141 insertions(+), 1 deletion(-) create mode 100644 drivers/firmware/qcom_smc.c create mode 100644 include/soc/qcom/qseecom_scm.h diff --git a/drivers/firmware/Makefile b/drivers/firmware/Makefile index 16a080bdec9b..f678b8055598 100644 --- a/drivers/firmware/Makefile +++ b/drivers/firmware/Makefile @@ -18,7 +18,7 @@ obj-$(CONFIG_FIRMWARE_MEMMAP) += memmap.o obj-$(CONFIG_RASPBERRYPI_FIRMWARE) += raspberrypi.o obj-$(CONFIG_FW_CFG_SYSFS) += qemu_fw_cfg.o obj-$(CONFIG_QCOM_SCM) += _qcom_scm.o -_qcom_scm-y += qcom_scm.o qcom_scm-smc.o +_qcom_scm-y += qcom_scm.o qcom_scm-smc.o qcom_smc.o _qcom_scm-$(CONFIG_QTEE_SHM_BRIDGE) += qtee_shmbridge.o obj-$(CONFIG_TI_SCI_PROTOCOL) += ti_sci.o obj-$(CONFIG_TRUSTED_FOUNDATIONS) += trusted_foundations.o diff --git a/drivers/firmware/qcom_scm-smc.c b/drivers/firmware/qcom_scm-smc.c index e0d4cc8f6fcc..01e12e7bdbe1 100644 --- a/drivers/firmware/qcom_scm-smc.c +++ b/drivers/firmware/qcom_scm-smc.c @@ -15,6 +15,7 @@ #include #include +#include #include "qcom_scm.h" @@ -1832,6 +1833,27 @@ int __qcom_scm_invoke_callback_response(struct device *dev, phys_addr_t out_buf, return ret; } +int __qcom_scm_qseecom_do(u32 cmd_id, struct scm_desc *desc, bool retry) +{ + int _ret; + struct qcom_scm_desc _desc; + + memcpy(&_desc.args, desc->args, sizeof(_desc.args)); + _desc.owner = (cmd_id & 0x3f000000) >> 24; + _desc.svc = (cmd_id & 0xff00) >> 8; + _desc.cmd = (cmd_id & 0xff); + _desc.arginfo = desc->arginfo; + + if (retry) + _ret = qcom_scm_call(NULL, &_desc); + else + _ret = qcom_scm_call_noretry(NULL, &_desc); + + memcpy(desc->ret, &_desc.res, sizeof(_desc.res)); + + return _ret; +} + void __qcom_scm_init(void) { __query_convention(); diff --git a/drivers/firmware/qcom_smc.c b/drivers/firmware/qcom_smc.c new file mode 100644 index 000000000000..cf39ee557a2f --- /dev/null +++ b/drivers/firmware/qcom_smc.c @@ -0,0 +1,19 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2019 The Linux Foundation. All rights reserved. + */ +#include +#include +#include + +int qcom_scm_qseecom_call(u32 cmd_id, struct scm_desc *desc) +{ + return __qcom_scm_qseecom_do(cmd_id, desc, true); +} +EXPORT_SYMBOL(qcom_scm_qseecom_call); + +int qcom_scm_qseecom_call_noretry(u32 cmd_id, struct scm_desc *desc) +{ + return __qcom_scm_qseecom_do(cmd_id, desc, false); +} +EXPORT_SYMBOL(qcom_scm_qseecom_call_noretry); diff --git a/include/soc/qcom/qseecom_scm.h b/include/soc/qcom/qseecom_scm.h new file mode 100644 index 000000000000..557e7f4bc625 --- /dev/null +++ b/include/soc/qcom/qseecom_scm.h @@ -0,0 +1,99 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2010-2019, The Linux Foundation. All rights reserved. + */ + +#ifndef __MACH_SCM_H +#define __MACH_SCM_H + +#define SCM_SVC_BOOT 0x1 +#define SCM_SVC_PIL 0x2 +#define SCM_SVC_UTIL 0x3 +#define SCM_SVC_TZ 0x4 +#define SCM_SVC_IO 0x5 +#define SCM_SVC_INFO 0x6 +#define SCM_SVC_SSD 0x7 +#define SCM_SVC_FUSE 0x8 +#define SCM_SVC_PWR 0x9 +#define SCM_SVC_MP 0xC +#define SCM_SVC_DCVS 0xD +#define SCM_SVC_ES 0x10 +#define SCM_SVC_HDCP 0x11 +#define SCM_SVC_MDTP 0x12 +#define SCM_SVC_LMH 0x13 +#define SCM_SVC_SMMU_PROGRAM 0x15 +#define SCM_SVC_QDSS 0x16 +#define SCM_SVC_RTIC 0x19 +#define SCM_SVC_TZSCHEDULER 0xFC + +#define SCM_FUSE_READ 0x7 +#define SCM_CMD_HDCP 0x01 + +/* SCM Features */ +#define SCM_SVC_SEC_CAMERA 0xD + +#define DEFINE_SCM_BUFFER(__n) \ +static char __n[PAGE_SIZE] __aligned(PAGE_SIZE) + +#define SCM_BUFFER_SIZE(__buf) sizeof(__buf) + +#define SCM_BUFFER_PHYS(__buf) virt_to_phys(__buf) + +#define SCM_SIP_FNID(s, c) (((((s) & 0xFF) << 8) | ((c) & 0xFF)) | 0x02000000) +#define SCM_QSEEOS_FNID(s, c) (((((s) & 0xFF) << 8) | ((c) & 0xFF)) | \ + 0x32000000) +#define SCM_SVC_ID(s) (((s) & 0xFF00) >> 8) + +#define MAX_SCM_ARGS 10 +#define MAX_SCM_RETS 3 + +enum scm_arg_types { + SCM_VAL, + SCM_RO, + SCM_RW, + SCM_BUFVAL, +}; + +#define SCM_ARGS_IMPL(num, a, b, c, d, e, f, g, h, i, j, ...) (\ + (((a) & 0xff) << 4) | \ + (((b) & 0xff) << 6) | \ + (((c) & 0xff) << 8) | \ + (((d) & 0xff) << 10) | \ + (((e) & 0xff) << 12) | \ + (((f) & 0xff) << 14) | \ + (((g) & 0xff) << 16) | \ + (((h) & 0xff) << 18) | \ + (((i) & 0xff) << 20) | \ + (((j) & 0xff) << 22) | \ + (num & 0xffff)) + +#define SCM_ARGS(...) SCM_ARGS_IMPL(__VA_ARGS__, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0) + +struct scm_desc { + u32 arginfo; + u64 args[MAX_SCM_ARGS]; + u64 ret[MAX_SCM_RETS]; +}; + +extern int __qcom_scm_qseecom_do(u32 cmd_id, struct scm_desc *desc, bool retry); + +#if IS_ENABLED(CONFIG_QCOM_SCM) + +int qcom_scm_qseecom_call(u32 cmd_id, struct scm_desc *desc); +int qcom_scm_qseecom_call_noretry(u32 cmd_id, struct scm_desc *desc); + +#else + +static inline int qcom_scm_qseecom_call(u32 cmd_id, struct scm_desc *desc) +{ + return -ENODEV; +} + +static inline int qcom_scm_qseecom_call_noretry(u32 cmd_id, + struct scm_desc *desc) +{ + return -ENODEV; +} + +#endif +#endif From 3364df41fa5eb086b8219755409ef1f3fc2e002f Mon Sep 17 00:00:00 2001 From: Siddharth Gupta Date: Mon, 4 Nov 2019 17:58:35 -0800 Subject: [PATCH 25/28] firmware: qcom_scm: Add calls for csptest Add SCM calls to check for whether mode switch and secure watchdog trigger calls are available. Add SCM call for cpu errata. Change-Id: Ibe2ccf4d44ce89c342ed3c65bbe6f075f9be8c40 Signed-off-by: Siddharth Gupta Signed-off-by: Elliot Berman --- drivers/firmware/qcom_scm-smc.c | 13 +++++++++++++ drivers/firmware/qcom_scm.c | 19 +++++++++++++++++++ drivers/firmware/qcom_scm.h | 4 ++++ include/linux/qcom_scm.h | 9 +++++++++ 4 files changed, 45 insertions(+) diff --git a/drivers/firmware/qcom_scm-smc.c b/drivers/firmware/qcom_scm-smc.c index 01e12e7bdbe1..6064dbed3357 100644 --- a/drivers/firmware/qcom_scm-smc.c +++ b/drivers/firmware/qcom_scm-smc.c @@ -729,6 +729,19 @@ int __qcom_scm_set_dload_mode(struct device *dev, bool enable) return qcom_scm_call_atomic(dev, &desc); } +int __qcom_scm_config_cpu_errata(struct device *dev) +{ + struct qcom_scm_desc desc = { + .svc = QCOM_SCM_SVC_BOOT, + .cmd = QCOM_SCM_BOOT_CONFIG_CPU_ERRATA, + .owner = ARM_SMCCC_OWNER_SIP, + }; + + desc.arginfo = 0xffffffff; + + return qcom_scm_call(dev, &desc); +} + bool __qcom_scm_pas_supported(struct device *dev, u32 peripheral) { int ret; diff --git a/drivers/firmware/qcom_scm.c b/drivers/firmware/qcom_scm.c index 4fce62a76d0f..38e26c37d915 100644 --- a/drivers/firmware/qcom_scm.c +++ b/drivers/firmware/qcom_scm.c @@ -153,6 +153,12 @@ static void qcom_scm_set_download_mode(bool enable) dev_err(__scm->dev, "failed to set download mode: %d\n", ret); } +int qcom_scm_config_cpu_errata(void) +{ + return __qcom_scm_config_cpu_errata(__scm->dev); +} +EXPORT_SYMBOL(qcom_scm_config_cpu_errata); + /** * qcom_scm_pas_supported() - Check if the peripheral authentication service is * available for the given peripherial @@ -344,6 +350,19 @@ int qcom_scm_io_reset(void) } EXPORT_SYMBOL(qcom_scm_io_reset); +bool qcom_scm_is_secure_wdog_trigger_available(void) +{ + return __qcom_scm_is_call_available(__scm->dev, QCOM_SCM_SVC_BOOT, + QCOM_SCM_BOOT_SEC_WDOG_TRIGGER); +} + +bool qcom_scm_is_mode_switch_available(void) +{ + return __qcom_scm_is_call_available(__scm->dev, QCOM_SCM_SVC_BOOT, + QCOM_SCM_BOOT_SWITCH_MODE); +} +EXPORT_SYMBOL(qcom_scm_is_mode_switch_available); + int qcom_scm_get_jtag_etm_feat_id(u64 *version) { return __qcom_scm_get_feat_version(__scm ? __scm->dev : NULL, diff --git a/drivers/firmware/qcom_scm.h b/drivers/firmware/qcom_scm.h index ddf022702836..6096d5a70176 100644 --- a/drivers/firmware/qcom_scm.h +++ b/drivers/firmware/qcom_scm.h @@ -9,8 +9,11 @@ #define QCOM_SCM_BOOT_SET_ADDR 0x01 #define QCOM_SCM_BOOT_TERMINATE_PC 0x02 #define QCOM_SCM_BOOT_SEC_WDOG_DIS 0x07 +#define QCOM_SCM_BOOT_SEC_WDOG_TRIGGER 0x08 #define QCOM_SCM_BOOT_SET_REMOTE_STATE 0x0a +#define QCOM_SCM_BOOT_SWITCH_MODE 0x0f #define QCOM_SCM_BOOT_SET_DLOAD_MODE 0x10 +#define QCOM_SCM_BOOT_CONFIG_CPU_ERRATA 0x12 extern int __qcom_scm_set_cold_boot_addr(struct device *dev, void *entry, const cpumask_t *cpus); extern int __qcom_scm_set_warm_boot_addr(struct device *dev, void *entry, @@ -19,6 +22,7 @@ extern void __qcom_scm_cpu_power_down(struct device *dev, u32 flags); extern int __qcom_scm_sec_wdog_deactivate(struct device *dev); extern int __qcom_scm_set_remote_state(struct device *dev, u32 state, u32 id); extern int __qcom_scm_set_dload_mode(struct device *dev, bool enable); +extern int __qcom_scm_config_cpu_errata(struct device *dev); #define QCOM_SCM_FLUSH_FLAG_MASK 0x3 #define QCOM_SCM_SVC_PIL 0x02 diff --git a/include/linux/qcom_scm.h b/include/linux/qcom_scm.h index 5be160ea3a8e..889a7a15826e 100644 --- a/include/linux/qcom_scm.h +++ b/include/linux/qcom_scm.h @@ -77,6 +77,7 @@ extern int qcom_scm_set_warm_boot_addr(void *entry, const cpumask_t *cpus); extern void qcom_scm_cpu_power_down(u32 flags); extern int qcom_scm_sec_wdog_deactivate(void); extern int qcom_scm_set_remote_state(u32 state, u32 id); +extern int qcom_scm_config_cpu_errata(void); extern bool qcom_scm_pas_supported(u32 peripheral); extern int qcom_scm_pas_init_image(u32 peripheral, const void *metadata, size_t size); @@ -89,6 +90,8 @@ extern int qcom_scm_tz_blsp_modify_owner(int food, u64 subsystem, int *out); extern int qcom_scm_io_readl(phys_addr_t addr, unsigned int *val); extern int qcom_scm_io_writel(phys_addr_t addr, unsigned int val); extern int qcom_scm_io_reset(void); +extern bool qcom_scm_is_secure_wdog_trigger_available(void); +extern bool qcom_scm_is_mode_switch_available(void); extern int qcom_scm_get_jtag_etm_feat_id(u64 *version); extern void qcom_scm_mmu_sync(bool sync); extern int qcom_scm_restore_sec_cfg(u32 device_id, u32 spare); @@ -186,6 +189,8 @@ static inline void qcom_scm_cpu_power_down(u32 flags) {} static inline int qcom_scm_sec_wdog_deactivate(void) { return -ENODEV; } static inline u32 qcom_scm_set_remote_state(u32 state, u32 id) { return -ENODEV; } +static inline int qcom_scm_config_cpu_errata(void) + { return -ENODEV; } static inline bool qcom_scm_pas_supported(u32 peripheral) { return false; } static inline int qcom_scm_pas_init_image(u32 peripheral, const void *metadata, size_t size) { return -ENODEV; } @@ -204,6 +209,10 @@ static inline int qcom_scm_io_writel(phys_addr_t addr, unsigned int val) { return -ENODEV; } static inline int qcom_scm_io_reset(void) { return -ENODEV; } +static inline bool qcom_scm_is_secure_wdog_trigger_available(void) + { return -ENODEV; } +static inline bool qcom_scm_is_mode_switch_available(void) + { return -ENODEV; } static inline int qcom_scm_get_jtag_etm_feat_id(u64 *version) { return -ENODEV; } static inline void qcom_scm_mmu_sync(bool sync) {} From 23a99bc7bce2ac0d59aa41e1a24fabdb0307441c Mon Sep 17 00:00:00 2001 From: Siddharth Gupta Date: Wed, 6 Nov 2019 16:57:48 -0800 Subject: [PATCH 26/28] firmware: qcom_scm: Add calls for seccam Add calls to the SCM driver for seccam driver. Change-Id: I0468057945ab8c84ea6c608fdb194093422a2c3e Signed-off-by: Siddharth Gupta Signed-off-by: Elliot Berman --- drivers/firmware/qcom_scm-smc.c | 16 ++++++++++++++++ drivers/firmware/qcom_scm.c | 6 ++++++ drivers/firmware/qcom_scm.h | 3 +++ include/linux/qcom_scm.h | 3 +++ 4 files changed, 28 insertions(+) diff --git a/drivers/firmware/qcom_scm-smc.c b/drivers/firmware/qcom_scm-smc.c index 6064dbed3357..d7e55267bf1e 100644 --- a/drivers/firmware/qcom_scm-smc.c +++ b/drivers/firmware/qcom_scm-smc.c @@ -1739,6 +1739,22 @@ int __qcom_scm_qdss_invoke(struct device *dev, phys_addr_t addr, size_t size, return ret ? : desc.res[0]; } +int __qcom_scm_camera_protect_all(struct device *dev, uint32_t protect, + uint32_t param) +{ + struct qcom_scm_desc desc = { + .svc = QCOM_SCM_SVC_CAMERA, + .cmd = QCOM_SCM_CAMERA_PROTECT_ALL, + .owner = ARM_SMCCC_OWNER_SIP + }; + + desc.args[0] = protect; + desc.args[1] = param; + desc.arginfo = QCOM_SCM_ARGS(2, QCOM_SCM_VAL, QCOM_SCM_VAL); + + return qcom_scm_call(dev, &desc); +} + int __qcom_scm_camera_protect_phy_lanes(struct device *dev, bool protect, u64 regmask) { diff --git a/drivers/firmware/qcom_scm.c b/drivers/firmware/qcom_scm.c index 38e26c37d915..ff74247fd546 100644 --- a/drivers/firmware/qcom_scm.c +++ b/drivers/firmware/qcom_scm.c @@ -834,6 +834,12 @@ int qcom_scm_qdss_invoke(phys_addr_t paddr, size_t size, u64 *out) } EXPORT_SYMBOL(qcom_scm_qdss_invoke); +int qcom_scm_camera_protect_all(uint32_t protect, uint32_t param) +{ + return __qcom_scm_camera_protect_all(__scm->dev, protect, param); +} +EXPORT_SYMBOL(qcom_scm_camera_protect_all); + int qcom_scm_camera_protect_phy_lanes(bool protect, u64 regmask) { return __qcom_scm_camera_protect_phy_lanes(__scm->dev, protect, diff --git a/drivers/firmware/qcom_scm.h b/drivers/firmware/qcom_scm.h index 6096d5a70176..da0e50ca4d91 100644 --- a/drivers/firmware/qcom_scm.h +++ b/drivers/firmware/qcom_scm.h @@ -208,7 +208,10 @@ extern int __qcom_scm_qdss_invoke(struct device *dev, phys_addr_t addr, size_t size, u64 *out); #define QCOM_SCM_SVC_CAMERA 0x18 +#define QCOM_SCM_CAMERA_PROTECT_ALL 0x06 #define QCOM_SCM_CAMERA_PROTECT_PHY_LANES 0x07 +extern int __qcom_scm_camera_protect_all(struct device *dev, uint32_t protect, + uint32_t param); extern int __qcom_scm_camera_protect_phy_lanes(struct device *dev, bool protect, u64 regmask); diff --git a/include/linux/qcom_scm.h b/include/linux/qcom_scm.h index 889a7a15826e..5e4daba01b9e 100644 --- a/include/linux/qcom_scm.h +++ b/include/linux/qcom_scm.h @@ -164,6 +164,7 @@ 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_smmu_notify_secure_lut(u64 dev_id, bool secure); extern int qcom_scm_qdss_invoke(phys_addr_t addr, size_t size, u64 *out); +extern int qcom_scm_camera_protect_all(uint32_t protect, uint32_t param); extern int qcom_scm_camera_protect_phy_lanes(bool protect, u64 regmask); extern int qcom_scm_ice_restore_cfg(void); extern int qcom_scm_get_tz_log_feat_id(u64 *version); @@ -311,6 +312,8 @@ static inline int qcom_scm_smmu_notify_secure_lut(u64 dev_id, bool secure) { return -EINVAL; } static inline int qcom_scm_qdss_invoke(phys_addr_t data, size_t size, u64 *out) { return -EINVAL; } +static inline int qcom_scm_camera_protect_all(uint32_t protect, uint32_t param) + { return -ENODEV; } static inline int qcom_scm_camera_protect_phy_lanes(bool protect, u64 regmask) { return -EINVAL; } static inline int qcom_scm_ice_restore_cfg(void) { return -ENODEV; } From 871f20c5e18e4c1bea67050b34d5653dc2eda653 Mon Sep 17 00:00:00 2001 From: Elliot Berman Date: Tue, 19 Nov 2019 15:35:53 -0800 Subject: [PATCH 27/28] firmware: qcom_scm: Add calls for watchdog tests Add call to trigger secure watchdog and spin CPU. Change-Id: I792c366528f46c87c68e73a49e276b1cd9462eaf Signed-off-by: Elliot Berman --- drivers/firmware/qcom_scm-smc.c | 28 ++++++++++++++++++++++++++++ drivers/firmware/qcom_scm.c | 12 ++++++++++++ drivers/firmware/qcom_scm.h | 3 +++ include/linux/qcom_scm.h | 4 ++++ 4 files changed, 47 insertions(+) diff --git a/drivers/firmware/qcom_scm-smc.c b/drivers/firmware/qcom_scm-smc.c index d7e55267bf1e..77f4cb28a97f 100644 --- a/drivers/firmware/qcom_scm-smc.c +++ b/drivers/firmware/qcom_scm-smc.c @@ -696,6 +696,20 @@ int __qcom_scm_sec_wdog_deactivate(struct device *dev) return qcom_scm_call(dev, &desc); } +int __qcom_scm_sec_wdog_trigger(struct device *dev) +{ + struct qcom_scm_desc desc = { + .svc = QCOM_SCM_SVC_BOOT, + .cmd = QCOM_SCM_BOOT_SEC_WDOG_TRIGGER, + .owner = ARM_SMCCC_OWNER_SIP, + }; + int ret; + + ret = qcom_scm_call(dev, &desc); + + return ret ? : desc.res[0]; +} + int __qcom_scm_set_remote_state(struct device *dev, u32 state, u32 id) { struct qcom_scm_desc desc = { @@ -714,6 +728,20 @@ int __qcom_scm_set_remote_state(struct device *dev, u32 state, u32 id) return ret ? : desc.res[0]; } +int __qcom_scm_spin_cpu(struct device *dev) +{ + struct qcom_scm_desc desc = { + .svc = QCOM_SCM_SVC_BOOT, + .cmd = QCOM_SCM_BOOT_SPIN_CPU, + .owner = ARM_SMCCC_OWNER_SIP + }; + + desc.args[0] = 0; + desc.arginfo = QCOM_SCM_ARGS(1); + + return qcom_scm_call(dev, &desc); +} + int __qcom_scm_set_dload_mode(struct device *dev, bool enable) { struct qcom_scm_desc desc = { diff --git a/drivers/firmware/qcom_scm.c b/drivers/firmware/qcom_scm.c index ff74247fd546..3691cbba9f3c 100644 --- a/drivers/firmware/qcom_scm.c +++ b/drivers/firmware/qcom_scm.c @@ -124,12 +124,24 @@ int qcom_scm_sec_wdog_deactivate(void) } EXPORT_SYMBOL(qcom_scm_sec_wdog_deactivate); +int qcom_scm_sec_wdog_trigger(void) +{ + return __qcom_scm_sec_wdog_trigger(__scm->dev); +} +EXPORT_SYMBOL(qcom_scm_sec_wdog_trigger); + int qcom_scm_set_remote_state(u32 state, u32 id) { return __qcom_scm_set_remote_state(__scm->dev, state, id); } EXPORT_SYMBOL(qcom_scm_set_remote_state); +int qcom_scm_spin_cpu(void) +{ + return __qcom_scm_spin_cpu(__scm->dev); +} +EXPORT_SYMBOL(qcom_scm_spin_cpu); + static void qcom_scm_set_download_mode(bool enable) { bool avail; diff --git a/drivers/firmware/qcom_scm.h b/drivers/firmware/qcom_scm.h index da0e50ca4d91..87c5520f6f06 100644 --- a/drivers/firmware/qcom_scm.h +++ b/drivers/firmware/qcom_scm.h @@ -11,6 +11,7 @@ #define QCOM_SCM_BOOT_SEC_WDOG_DIS 0x07 #define QCOM_SCM_BOOT_SEC_WDOG_TRIGGER 0x08 #define QCOM_SCM_BOOT_SET_REMOTE_STATE 0x0a +#define QCOM_SCM_BOOT_SPIN_CPU 0x0d #define QCOM_SCM_BOOT_SWITCH_MODE 0x0f #define QCOM_SCM_BOOT_SET_DLOAD_MODE 0x10 #define QCOM_SCM_BOOT_CONFIG_CPU_ERRATA 0x12 @@ -20,7 +21,9 @@ extern int __qcom_scm_set_warm_boot_addr(struct device *dev, void *entry, const cpumask_t *cpus); extern void __qcom_scm_cpu_power_down(struct device *dev, u32 flags); extern int __qcom_scm_sec_wdog_deactivate(struct device *dev); +extern int __qcom_scm_sec_wdog_trigger(struct device *dev); extern int __qcom_scm_set_remote_state(struct device *dev, u32 state, u32 id); +extern int __qcom_scm_spin_cpu(struct device *dev); extern int __qcom_scm_set_dload_mode(struct device *dev, bool enable); extern int __qcom_scm_config_cpu_errata(struct device *dev); #define QCOM_SCM_FLUSH_FLAG_MASK 0x3 diff --git a/include/linux/qcom_scm.h b/include/linux/qcom_scm.h index 5e4daba01b9e..f12ef1372167 100644 --- a/include/linux/qcom_scm.h +++ b/include/linux/qcom_scm.h @@ -76,7 +76,9 @@ extern int qcom_scm_set_cold_boot_addr(void *entry, const cpumask_t *cpus); extern int qcom_scm_set_warm_boot_addr(void *entry, const cpumask_t *cpus); extern void qcom_scm_cpu_power_down(u32 flags); extern int qcom_scm_sec_wdog_deactivate(void); +extern int qcom_scm_sec_wdog_trigger(void); extern int qcom_scm_set_remote_state(u32 state, u32 id); +extern int qcom_scm_spin_cpu(void); extern int qcom_scm_config_cpu_errata(void); extern bool qcom_scm_pas_supported(u32 peripheral); extern int qcom_scm_pas_init_image(u32 peripheral, const void *metadata, @@ -188,8 +190,10 @@ int qcom_scm_set_warm_boot_addr(void *entry, const cpumask_t *cpus) { return -ENODEV; } static inline void qcom_scm_cpu_power_down(u32 flags) {} static inline int qcom_scm_sec_wdog_deactivate(void) { return -ENODEV; } +static inline int qcom_scm_sec_wdog_trigger(void) { return -ENODEV; } static inline u32 qcom_scm_set_remote_state(u32 state, u32 id) { return -ENODEV; } +static inline int qcom_scm_spin_cpu(void) { return -ENODEV; } static inline int qcom_scm_config_cpu_errata(void) { return -ENODEV; } static inline bool qcom_scm_pas_supported(u32 peripheral) { return false; } From 1699be26f319ca2c3595e2b3beeb55d8b2a32bd9 Mon Sep 17 00:00:00 2001 From: Elliot Berman Date: Tue, 19 Nov 2019 10:58:46 -0800 Subject: [PATCH 28/28] defconfig: Enable qcom_scm as a module Enable qcom_scm as a module in lahaina GKI. Change-Id: I92cc0a27d48fc5e0de06361f798a68cd570a87e5 Signed-off-by: Elliot Berman --- arch/arm64/configs/vendor/lahaina_GKI.config | 3 +++ arch/arm64/configs/vendor/lahaina_QGKI.config | 3 --- drivers/firmware/Kconfig | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/arch/arm64/configs/vendor/lahaina_GKI.config b/arch/arm64/configs/vendor/lahaina_GKI.config index 98021bb9fb20..62dbf7892303 100644 --- a/arch/arm64/configs/vendor/lahaina_GKI.config +++ b/arch/arm64/configs/vendor/lahaina_GKI.config @@ -19,6 +19,9 @@ CONFIG_MSM_CORE_HANG_DETECT=m CONFIG_QCOM_LLCC=m CONFIG_QCOM_LAHAINA_LLCC=m CONFIG_QCOM_IPCC=m +CONFIG_QCOM_SCM=m +CONFIG_QTEE_SHM_BRIDGE=y +# CONFIG_QCOM_SCM_DOWNLOAD_MODE_DEFAULT is not set CONFIG_BUILD_ARM64_UNCOMPRESSED_KERNEL=y CONFIG_HWSPINLOCK_QCOM=m CONFIG_QCOM_SMEM=m diff --git a/arch/arm64/configs/vendor/lahaina_QGKI.config b/arch/arm64/configs/vendor/lahaina_QGKI.config index 59511471a539..f0320692beb0 100644 --- a/arch/arm64/configs/vendor/lahaina_QGKI.config +++ b/arch/arm64/configs/vendor/lahaina_QGKI.config @@ -27,6 +27,3 @@ CONFIG_MSM_GLOBAL_SYNX=y CONFIG_MSM_CVP=y CONFIG_ION_POOL_AUTO_REFILL=y CONFIG_MSM_BT_POWER=m -CONFIG_QCOM_SCM=y -# CONFIG_QCOM_SCM_DOWNLOAD_MODE_DEFAULT is not set -CONFIG_QTEE_SHM_BRIDGE=y diff --git a/drivers/firmware/Kconfig b/drivers/firmware/Kconfig index a37ed1a677de..b3da58e1c44e 100644 --- a/drivers/firmware/Kconfig +++ b/drivers/firmware/Kconfig @@ -235,7 +235,7 @@ config INTEL_STRATIX10_RSU Say Y here if you want Intel RSU support. config QCOM_SCM - bool "Qualcomm Technologies, Inc. SCM Interface" + tristate "Qualcomm Technologies, Inc. SCM Interface" depends on ARM || ARM64 select RESET_CONTROLLER help