From: Xingang Wang wangxingang5@huawei.com
ascend inclusion category: feature bugzilla: https://gitee.com/openeuler/kernel/issues/I49RB2 CVE: NA
-------------------------------------------------
Add interface to get mpam configuration of CD/STE context, use s1mpam to indicate whether partid and pmg from CD or STE.
Signed-off-by: Xingang Wang wangxingang5@huawei.com Reviewed-by: Yingtai Xie xieyingtai@huawei.com Reviewed-by: Zhen Lei thunder.leizhen@huawei.com Signed-off-by: Yang Yingliang yangyingliang@huawei.com --- drivers/iommu/arm-smmu-v3-context.c | 17 +++++++ drivers/iommu/arm-smmu-v3.c | 71 +++++++++++++++++++++++++++++ include/linux/ascend_smmu.h | 3 ++ 3 files changed, 91 insertions(+)
diff --git a/drivers/iommu/arm-smmu-v3-context.c b/drivers/iommu/arm-smmu-v3-context.c index b30a93e076608..d87d6f72e8642 100644 --- a/drivers/iommu/arm-smmu-v3-context.c +++ b/drivers/iommu/arm-smmu-v3-context.c @@ -588,6 +588,23 @@ int arm_smmu_set_cd_mpam(struct iommu_pasid_table_ops *ops, return 0; }
+int arm_smmu_get_cd_mpam(struct iommu_pasid_table_ops *ops, + int ssid, int *partid, int *pmg) +{ + struct arm_smmu_cd_tables *tbl = pasid_ops_to_tables(ops); + u64 val; + __le64 *cdptr = arm_smmu_get_cd_ptr(tbl, ssid); + + if (!cdptr) + return -ENOMEM; + + val = le64_to_cpu(cdptr[5]); + *partid = FIELD_GET(CTXDESC_CD_5_PARTID_MASK, val); + *pmg = FIELD_GET(CTXDESC_CD_5_PMG_MASK, val); + + return 0; +} + static void arm_smmu_clear_cd(struct iommu_pasid_table_ops *ops, int pasid, struct iommu_pasid_entry *entry) { diff --git a/drivers/iommu/arm-smmu-v3.c b/drivers/iommu/arm-smmu-v3.c index 6634d596f7efc..2cce9bccab5dc 100644 --- a/drivers/iommu/arm-smmu-v3.c +++ b/drivers/iommu/arm-smmu-v3.c @@ -4197,9 +4197,38 @@ static int arm_smmu_set_ste_mpam(struct arm_smmu_device *smmu, return 0; }
+static int arm_smmu_get_ste_mpam(struct arm_smmu_device *smmu, + int sid, int *partid, int *pmg, int *s1mpam) +{ + u64 val; + __le64 *ste; + + if (!arm_smmu_sid_in_range(smmu, sid)) + return -ERANGE; + + /* get ste ptr */ + ste = arm_smmu_get_step_for_sid(smmu, sid); + + val = le64_to_cpu(ste[1]); + *s1mpam = FIELD_GET(STRTAB_STE_1_S1MPAM, val); + if (*s1mpam) + return 0; + + val = le64_to_cpu(ste[4]); + *partid = FIELD_GET(STRTAB_STE_4_PARTID_MASK, val); + + val = le64_to_cpu(ste[5]); + *pmg = FIELD_GET(STRTAB_STE_5_PMG_MASK, val); + + return 0; +} + int arm_smmu_set_cd_mpam(struct iommu_pasid_table_ops *ops, int ssid, int partid, int pmg);
+int arm_smmu_get_cd_mpam(struct iommu_pasid_table_ops *ops, + int ssid, int *partid, int *pmg); + static int arm_smmu_set_mpam(struct arm_smmu_device *smmu, int sid, int ssid, int partid, int pmg, int s1mpam) { @@ -4278,6 +4307,48 @@ int arm_smmu_set_dev_mpam(struct device *dev, int ssid, int partid, int pmg, } EXPORT_SYMBOL(arm_smmu_set_dev_mpam);
+static int arm_smmu_get_mpam(struct arm_smmu_device *smmu, + int sid, int ssid, int *partid, int *pmg, int *s1mpam) +{ + struct arm_smmu_master_data *master = arm_smmu_find_master(smmu, sid); + struct arm_smmu_s1_cfg *cfg = master ? master->ste.s1_cfg : NULL; + int ret; + + if (!(smmu->features & ARM_SMMU_FEAT_MPAM)) + return -ENODEV; + + ret = arm_smmu_get_ste_mpam(smmu, sid, partid, pmg, s1mpam); + if (ret) + return ret; + + /* return STE mpam configuration when s1mpam == 0 */ + if (!(*s1mpam)) + return 0; + + if (WARN_ON(!cfg)) + return -EINVAL; + + if (WARN_ON(ssid >= (1 << master->ssid_bits))) + return -E2BIG; + + return arm_smmu_get_cd_mpam(cfg->ops, ssid, partid, pmg); +} + +/** + * arm_smmu_get_dev_mpam() - get mpam configuration + * @dev: the device + */ +int arm_smmu_get_dev_mpam(struct device *dev, int ssid, int *partid, int *pmg, + int *s1mpam) +{ + struct arm_smmu_master_data *master = dev->iommu_fwspec->iommu_priv; + struct arm_smmu_device *smmu = master->domain->smmu; + int sid = master->streams->id; + + return arm_smmu_get_mpam(smmu, sid, ssid, partid, pmg, s1mpam); +} +EXPORT_SYMBOL(arm_smmu_get_dev_mpam); + static int arm_smmu_device_probe(struct platform_device *pdev) { int irq, ret; diff --git a/include/linux/ascend_smmu.h b/include/linux/ascend_smmu.h index bd0edd25057e1..a9f449a135781 100644 --- a/include/linux/ascend_smmu.h +++ b/include/linux/ascend_smmu.h @@ -6,4 +6,7 @@ extern int arm_smmu_set_dev_mpam(struct device *dev, int ssid, int partid, int pmg, int s1mpam);
+extern int arm_smmu_get_dev_mpam(struct device *dev, int ssid, int *partid, + int *pmg, int *s1mpam); + #endif /* __LINUX_ASCEND_SMMU_H */