From 050d2dca679b66e355cb9b113690cedd19afed47 Mon Sep 17 00:00:00 2001 From: Siddharth Gupta Date: Wed, 11 Sep 2019 18:04:07 -0700 Subject: [PATCH] iommu/arm-smmu: Migrate SCM IO calls in arm-smmu Migrate SCM IO read calls in the smmu driver to use new SCM driver. Add support for io-pgtable-msm-secure map and unmap in SCM driver. Change-Id: If1ce054b9cfcfdcdab3aecc6752fcd4765197a05 Signed-off-by: Siddharth Gupta Signed-off-by: Elliot Berman --- drivers/firmware/qcom_scm-smc.c | 52 +++++++++++++++++++++++++++++++++ drivers/firmware/qcom_scm.c | 17 +++++++++++ drivers/firmware/qcom_scm.h | 11 +++++++ drivers/iommu/arm-smmu.c | 13 +++++---- include/linux/qcom_scm.h | 10 +++++++ 5 files changed, 97 insertions(+), 6 deletions(-) diff --git a/drivers/firmware/qcom_scm-smc.c b/drivers/firmware/qcom_scm-smc.c index cf9d71c29098..55be823ecdfe 100644 --- a/drivers/firmware/qcom_scm-smc.c +++ b/drivers/firmware/qcom_scm-smc.c @@ -952,6 +952,58 @@ int __qcom_scm_iommu_secure_ptbl_init(struct device *dev, u64 addr, u32 size, 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) +{ + int ret; + struct qcom_scm_desc desc = { + .svc = QCOM_SCM_SVC_MP, + .cmd = QCOM_SCM_MP_IOMMU_SECURE_MAP2_FLAT, + .owner = ARM_SMCCC_OWNER_SIP + }; + + desc.args[0] = sg_list_addr; + desc.args[1] = num_sg; + desc.args[2] = sg_block_size; + desc.args[3] = sec_id; + desc.args[4] = cbndx; + desc.args[5] = iova; + desc.args[6] = total_len; + desc.args[7] = 0; + + + desc.arginfo = QCOM_SCM_ARGS(8, QCOM_SCM_RW, QCOM_SCM_VAL, QCOM_SCM_VAL, + QCOM_SCM_VAL, QCOM_SCM_VAL, QCOM_SCM_VAL, QCOM_SCM_VAL, + QCOM_SCM_VAL); + + ret = qcom_scm_call(dev, &desc); + + return ret ? : desc.res[0]; +} + +int __qcom_scm_iommu_secure_unmap(struct device *dev, u64 sec_id, int cbndx, + unsigned long iova, size_t total_len) +{ + int ret; + struct qcom_scm_desc desc = { + .svc = QCOM_SCM_SVC_MP, + .cmd = QCOM_SCM_MP_IOMMU_SECURE_UNMAP2_FLAT, + .owner = ARM_SMCCC_OWNER_SIP + }; + + desc.args[0] = sec_id; + desc.args[1] = cbndx; + desc.args[2] = iova; + desc.args[3] = total_len; + desc.args[4] = QCOM_SCM_IOMMU_TLBINVAL_FLAG; + desc.arginfo = QCOM_SCM_ARGS(5); + + ret = qcom_scm_call(dev, &desc); + + return ret ? : desc.res[0]; +} + 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) diff --git a/drivers/firmware/qcom_scm.c b/drivers/firmware/qcom_scm.c index 5d535efc28ca..c9f2fca19366 100644 --- a/drivers/firmware/qcom_scm.c +++ b/drivers/firmware/qcom_scm.c @@ -358,6 +358,23 @@ int qcom_scm_iommu_secure_ptbl_init(u64 addr, u32 size, u32 spare) } EXPORT_SYMBOL(qcom_scm_iommu_secure_ptbl_init); +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 __qcom_scm_iommu_secure_map(__scm->dev, sg_list_addr, num_sg, + sg_block_size, sec_id, cbndx, iova, total_len); +} +EXPORT_SYMBOL(qcom_scm_iommu_secure_map); + +int qcom_scm_iommu_secure_unmap(u64 sec_id, int cbndx, unsigned long iova, + size_t total_len) +{ + return __qcom_scm_iommu_secure_unmap(__scm->dev, sec_id, cbndx, iova, + total_len); +} +EXPORT_SYMBOL(qcom_scm_iommu_secure_unmap); + /** * 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/drivers/firmware/qcom_scm.h b/drivers/firmware/qcom_scm.h index 2b078fbdbb73..45cd42103f20 100644 --- a/drivers/firmware/qcom_scm.h +++ b/drivers/firmware/qcom_scm.h @@ -55,6 +55,8 @@ 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_IOMMU_SECURE_MAP2_FLAT 0x12 +#define QCOM_SCM_MP_IOMMU_SECURE_UNMAP2_FLAT 0x13 #define QCOM_SCM_MP_ASSIGN 0x16 extern int __qcom_scm_restore_sec_cfg(struct device *dev, u32 device_id, u32 spare); @@ -62,10 +64,19 @@ 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_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); +extern int __qcom_scm_iommu_secure_unmap(struct device *dev, u64 sec_id, + int cbndx, unsigned long iova, + size_t total_len); 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); +#define QCOM_SCM_IOMMU_TLBINVAL_FLAG 0x00000001 + #define QCOM_SCM_SVC_HDCP 0x11 #define QCOM_SCM_HDCP_INVOKE 0x01 diff --git a/drivers/iommu/arm-smmu.c b/drivers/iommu/arm-smmu.c index aafac8dd63e3..6f283eba843a 100644 --- a/drivers/iommu/arm-smmu.c +++ b/drivers/iommu/arm-smmu.c @@ -49,7 +49,7 @@ #include #include -#include +#include #include "arm-smmu.h" #define CREATE_TRACE_POINTS @@ -868,7 +868,7 @@ static int __arm_smmu_tlb_sync(struct arm_smmu_device *smmu, int page, int sync, int status) { unsigned int spin_cnt, delay; - u32 sync_inv_ack, tbu_pwr_status, sync_inv_progress; + u32 sync_inv_ack, tbu_pwr_status = -EINVAL, sync_inv_progress = -EINVAL; u32 reg; arm_smmu_writel(smmu, page, sync, QCOM_DUMMY_VAL); @@ -885,10 +885,11 @@ static int __arm_smmu_tlb_sync(struct arm_smmu_device *smmu, int page, sync_inv_ack = arm_smmu_readl(smmu, ARM_SMMU_IMPL_DEF0, ARM_SMMU_STATS_SYNC_INV_TBU_ACK); - tbu_pwr_status = scm_io_read((unsigned long)(smmu->phys_addr + - ARM_SMMU_TBU_PWR_STATUS)); - sync_inv_progress = scm_io_read((unsigned long)(smmu->phys_addr + - ARM_SMMU_MMU2QSS_AND_SAFE_WAIT_CNTR)); + qcom_scm_io_readl((unsigned long)(smmu->phys_addr + + ARM_SMMU_TBU_PWR_STATUS), &tbu_pwr_status); + qcom_scm_io_readl((unsigned long)(smmu->phys_addr + + ARM_SMMU_MMU2QSS_AND_SAFE_WAIT_CNTR), + &sync_inv_progress); trace_tlbsync_timeout(smmu->dev, 0); dev_err_ratelimited(smmu->dev, "TLB sync timed out -- SMMU may be deadlocked ack 0x%x pwr 0x%x sync and invalidation progress 0x%x\n", diff --git a/include/linux/qcom_scm.h b/include/linux/qcom_scm.h index 6acdf1d9dbfa..efad236365aa 100644 --- a/include/linux/qcom_scm.h +++ b/include/linux/qcom_scm.h @@ -53,6 +53,11 @@ 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_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); +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(phys_addr_t mem_addr, size_t mem_sz, unsigned int *src, const struct qcom_scm_vmperm *newvm, @@ -95,6 +100,11 @@ 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_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; } +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(phys_addr_t mem_addr, size_t mem_sz, unsigned int *src, const struct qcom_scm_vmperm *newvm,