ascend inclusion category: feature bugzilla: https://gitee.com/openeuler/kernel/issues/I931MI CVE: NA
-----------------------------------------------------------------
The svsp requires the pasid of svsp_mm has the value of pasid of the normal mm with the highest bit set. In this commit we introduce IOMMU_SVA_FEAT_SVSP feature to allow user pass the pasid of normal mm and set pasid of svsp_mm by the given rules.
Signed-off-by: Yuan Can yuancan@huawei.com --- .../iommu/arm/arm-smmu-v3/arm-smmu-v3-sva.c | 33 +++++++++++++++++++ drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c | 14 ++++++++ drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h | 8 +++++ include/linux/iommu.h | 3 ++ 4 files changed, 58 insertions(+)
diff --git a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-sva.c b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-sva.c index 5bb805ca3e5d..3f643a4e4cc0 100644 --- a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-sva.c +++ b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-sva.c @@ -597,3 +597,36 @@ struct iommu_domain *arm_smmu_sva_domain_alloc(void)
return domain; } + +#ifdef CONFIG_ASCEND_SVSP +bool arm_smmu_master_svsp_supported(struct arm_smmu_master *master) +{ + /* svsp depends on sva */ + if (!arm_smmu_master_sva_supported(master)) + return false; + + return true; +} + +int arm_smmu_master_enable_svsp(struct arm_smmu_master *master) +{ + if (arm_smmu_master_sva_enabled(master)) { + master->svsp_enabled = true; + return 0; + } + + return -EINVAL; +} + +int arm_smmu_master_disable_svsp(struct arm_smmu_master *master) +{ + master->svsp_enabled = false; + return 0; +} + +unsigned int svm_svsp_extract_ssid_bits(struct arm_smmu_master *master) +{ + return master->ssid_bits; +} +EXPORT_SYMBOL(svm_svsp_extract_ssid_bits); +#endif diff --git a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c index 09dc2d690de1..77ef1e2efb27 100644 --- a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c +++ b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c @@ -3269,6 +3269,14 @@ static int arm_smmu_dev_enable_feature(struct device *dev, if (arm_smmu_master_sva_enabled(master)) return -EBUSY; return arm_smmu_master_enable_sva(master); +#ifdef CONFIG_ASCEND_SVSP + case IOMMU_DEV_FEAT_SVSP: + if (!arm_smmu_master_svsp_supported(master)) + return -EINVAL; + if (master->svsp_enabled) + return -EBUSY; + return arm_smmu_master_enable_svsp(master); +#endif default: return -EINVAL; } @@ -3294,6 +3302,12 @@ static int arm_smmu_dev_disable_feature(struct device *dev, if (!arm_smmu_master_sva_enabled(master)) return -EINVAL; return arm_smmu_master_disable_sva(master); +#ifdef CONFIG_ASCEND_SVSP + case IOMMU_DEV_FEAT_SVSP: + if (!master->svsp_enabled) + return -EINVAL; + return arm_smmu_master_disable_svsp(master); +#endif default: return -EINVAL; } diff --git a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h index f04d10223f6e..13b09da7c902 100644 --- a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h +++ b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h @@ -767,6 +767,9 @@ struct arm_smmu_master { bool stall_enabled; bool sva_enabled; bool iopf_enabled; +#ifdef CONFIG_ASCEND_SVSP + bool svsp_enabled; +#endif struct list_head bonds; unsigned int ssid_bits; }; @@ -831,6 +834,11 @@ void arm_smmu_sva_notifier_synchronize(void); struct iommu_domain *arm_smmu_sva_domain_alloc(void); void arm_smmu_sva_remove_dev_pasid(struct iommu_domain *domain, struct device *dev, ioasid_t id); +#ifdef CONFIG_ASCEND_SVSP +bool arm_smmu_master_svsp_supported(struct arm_smmu_master *master); +int arm_smmu_master_enable_svsp(struct arm_smmu_master *master); +int arm_smmu_master_disable_svsp(struct arm_smmu_master *master); +#endif #else /* CONFIG_ARM_SMMU_V3_SVA */ static inline bool arm_smmu_sva_supported(struct arm_smmu_device *smmu) { diff --git a/include/linux/iommu.h b/include/linux/iommu.h index a9f9b8bb7540..a1be18a687b6 100644 --- a/include/linux/iommu.h +++ b/include/linux/iommu.h @@ -200,6 +200,9 @@ struct iommu_iort_rmr_data { enum iommu_dev_features { IOMMU_DEV_FEAT_SVA, IOMMU_DEV_FEAT_IOPF, +#ifdef CONFIG_ASCEND_SVSP + IOMMU_DEV_FEAT_SVSP, +#endif };
#define IOMMU_NO_PASID (0U) /* Reserved for DMA w/o PASID */