Re: [PATCH 2/3] iommu/arm-smmu-v3: Make BTM optional for SVA
On Fri, Jan 22, 2021 at 02:04:55PM +, Robin Murphy wrote: > > @@ -182,9 +183,13 @@ static void arm_smmu_mm_invalidate_range(struct > > mmu_notifier *mn, > > unsigned long start, unsigned long end) > > { > > struct arm_smmu_mmu_notifier *smmu_mn = mn_to_smmu(mn); > > + struct arm_smmu_domain *smmu_domain = smmu_mn->domain; > > + size_t size = end - start + 1; > > - arm_smmu_atc_inv_domain(smmu_mn->domain, mm->pasid, start, > > - end - start + 1); > > + if (smmu_mn->tlb_inv_command) > > Since we're going to be drilling down to smmu_domain->smmu->features in the > invalidate call anyway, perhaps we could just test for BTM directly here? Yes even with BTM enabled we'll still check features in atc_inv_domain(), so this shortcut isn't useful. Thanks, Jean ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
Re: [PATCH 2/3] iommu/arm-smmu-v3: Make BTM optional for SVA
On 2021-01-22 11:52, Jean-Philippe Brucker wrote: When BTM isn't supported by the SMMU, send invalidations on the command queue. Signed-off-by: Jean-Philippe Brucker --- drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h | 3 +++ drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-sva.c | 14 +++--- drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c | 14 ++ 3 files changed, 28 insertions(+), 3 deletions(-) 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 a6536c2b32d0..652d03ad8ae6 100644 --- a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h +++ b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h @@ -743,6 +743,9 @@ extern struct arm_smmu_ctx_desc quiet_cd; int arm_smmu_write_ctx_desc(struct arm_smmu_domain *smmu_domain, int ssid, struct arm_smmu_ctx_desc *cd); void arm_smmu_tlb_inv_asid(struct arm_smmu_device *smmu, u16 asid); +void arm_smmu_tlb_inv_range_asid(unsigned long iova, size_t size, int asid, +size_t granule, bool leaf, +struct arm_smmu_domain *smmu_domain); bool arm_smmu_free_asid(struct arm_smmu_ctx_desc *cd); int arm_smmu_atc_inv_domain(struct arm_smmu_domain *smmu_domain, int ssid, unsigned long iova, size_t size); 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 642ce2c225b5..ad8cf62a8f83 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 @@ -16,6 +16,7 @@ struct arm_smmu_mmu_notifier { struct mmu_notifier mn; struct arm_smmu_ctx_desc*cd; boolcleared; + booltlb_inv_command; refcount_t refs; struct list_headlist; struct arm_smmu_domain *domain; @@ -182,9 +183,13 @@ static void arm_smmu_mm_invalidate_range(struct mmu_notifier *mn, unsigned long start, unsigned long end) { struct arm_smmu_mmu_notifier *smmu_mn = mn_to_smmu(mn); + struct arm_smmu_domain *smmu_domain = smmu_mn->domain; + size_t size = end - start + 1; - arm_smmu_atc_inv_domain(smmu_mn->domain, mm->pasid, start, - end - start + 1); + if (smmu_mn->tlb_inv_command) Since we're going to be drilling down to smmu_domain->smmu->features in the invalidate call anyway, perhaps we could just test for BTM directly here? Obviously that also proves my previous comment involved a reading comprehension failure and too much haste, so should be discounted. Sorry about that :) Robin. + arm_smmu_tlb_inv_range_asid(start, size, smmu_mn->cd->asid, + PAGE_SIZE, false, smmu_domain); + arm_smmu_atc_inv_domain(smmu_domain, mm->pasid, start, size); } static void arm_smmu_mm_release(struct mmu_notifier *mn, struct mm_struct *mm) @@ -253,6 +258,9 @@ arm_smmu_mmu_notifier_get(struct arm_smmu_domain *smmu_domain, smmu_mn->domain = smmu_domain; smmu_mn->mn.ops = _smmu_mmu_notifier_ops; + if (!(smmu_domain->smmu->features & ARM_SMMU_FEAT_BTM)) + smmu_mn->tlb_inv_command = true; + ret = mmu_notifier_register(_mn->mn, mm); if (ret) { kfree(smmu_mn); @@ -404,7 +412,7 @@ bool arm_smmu_sva_supported(struct arm_smmu_device *smmu) unsigned long reg, fld; unsigned long oas; unsigned long asid_bits; - u32 feat_mask = ARM_SMMU_FEAT_BTM | ARM_SMMU_FEAT_COHERENCY; + u32 feat_mask = ARM_SMMU_FEAT_COHERENCY; if (vabits_actual == 52) feat_mask |= ARM_SMMU_FEAT_VAX; 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 a27b074d5c0c..db545834493b 100644 --- a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c +++ b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c @@ -2018,6 +2018,20 @@ static void arm_smmu_tlb_inv_range_domain(unsigned long iova, size_t size, arm_smmu_atc_inv_domain(smmu_domain, 0, iova, size); } +void arm_smmu_tlb_inv_range_asid(unsigned long iova, size_t size, int asid, +size_t granule, bool leaf, +struct arm_smmu_domain *smmu_domain) +{ + struct arm_smmu_cmdq_ent cmd = { + .opcode = CMDQ_OP_TLBI_NH_VA, + .tlbi = { + .asid = asid, + .leaf = leaf, + }, + }; + arm_smmu_tlb_inv_range(, iova, size, granule, smmu_domain); +} + static void arm_smmu_tlb_inv_page_nosync(struct iommu_iotlb_gather *gather, unsigned long iova, size_t granule, void *cookie)
[PATCH 2/3] iommu/arm-smmu-v3: Make BTM optional for SVA
When BTM isn't supported by the SMMU, send invalidations on the command queue. Signed-off-by: Jean-Philippe Brucker --- drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h | 3 +++ drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-sva.c | 14 +++--- drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c | 14 ++ 3 files changed, 28 insertions(+), 3 deletions(-) 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 a6536c2b32d0..652d03ad8ae6 100644 --- a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h +++ b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h @@ -743,6 +743,9 @@ extern struct arm_smmu_ctx_desc quiet_cd; int arm_smmu_write_ctx_desc(struct arm_smmu_domain *smmu_domain, int ssid, struct arm_smmu_ctx_desc *cd); void arm_smmu_tlb_inv_asid(struct arm_smmu_device *smmu, u16 asid); +void arm_smmu_tlb_inv_range_asid(unsigned long iova, size_t size, int asid, +size_t granule, bool leaf, +struct arm_smmu_domain *smmu_domain); bool arm_smmu_free_asid(struct arm_smmu_ctx_desc *cd); int arm_smmu_atc_inv_domain(struct arm_smmu_domain *smmu_domain, int ssid, unsigned long iova, size_t size); 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 642ce2c225b5..ad8cf62a8f83 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 @@ -16,6 +16,7 @@ struct arm_smmu_mmu_notifier { struct mmu_notifier mn; struct arm_smmu_ctx_desc*cd; boolcleared; + booltlb_inv_command; refcount_t refs; struct list_headlist; struct arm_smmu_domain *domain; @@ -182,9 +183,13 @@ static void arm_smmu_mm_invalidate_range(struct mmu_notifier *mn, unsigned long start, unsigned long end) { struct arm_smmu_mmu_notifier *smmu_mn = mn_to_smmu(mn); + struct arm_smmu_domain *smmu_domain = smmu_mn->domain; + size_t size = end - start + 1; - arm_smmu_atc_inv_domain(smmu_mn->domain, mm->pasid, start, - end - start + 1); + if (smmu_mn->tlb_inv_command) + arm_smmu_tlb_inv_range_asid(start, size, smmu_mn->cd->asid, + PAGE_SIZE, false, smmu_domain); + arm_smmu_atc_inv_domain(smmu_domain, mm->pasid, start, size); } static void arm_smmu_mm_release(struct mmu_notifier *mn, struct mm_struct *mm) @@ -253,6 +258,9 @@ arm_smmu_mmu_notifier_get(struct arm_smmu_domain *smmu_domain, smmu_mn->domain = smmu_domain; smmu_mn->mn.ops = _smmu_mmu_notifier_ops; + if (!(smmu_domain->smmu->features & ARM_SMMU_FEAT_BTM)) + smmu_mn->tlb_inv_command = true; + ret = mmu_notifier_register(_mn->mn, mm); if (ret) { kfree(smmu_mn); @@ -404,7 +412,7 @@ bool arm_smmu_sva_supported(struct arm_smmu_device *smmu) unsigned long reg, fld; unsigned long oas; unsigned long asid_bits; - u32 feat_mask = ARM_SMMU_FEAT_BTM | ARM_SMMU_FEAT_COHERENCY; + u32 feat_mask = ARM_SMMU_FEAT_COHERENCY; if (vabits_actual == 52) feat_mask |= ARM_SMMU_FEAT_VAX; 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 a27b074d5c0c..db545834493b 100644 --- a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c +++ b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c @@ -2018,6 +2018,20 @@ static void arm_smmu_tlb_inv_range_domain(unsigned long iova, size_t size, arm_smmu_atc_inv_domain(smmu_domain, 0, iova, size); } +void arm_smmu_tlb_inv_range_asid(unsigned long iova, size_t size, int asid, +size_t granule, bool leaf, +struct arm_smmu_domain *smmu_domain) +{ + struct arm_smmu_cmdq_ent cmd = { + .opcode = CMDQ_OP_TLBI_NH_VA, + .tlbi = { + .asid = asid, + .leaf = leaf, + }, + }; + arm_smmu_tlb_inv_range(, iova, size, granule, smmu_domain); +} + static void arm_smmu_tlb_inv_page_nosync(struct iommu_iotlb_gather *gather, unsigned long iova, size_t granule, void *cookie) -- 2.30.0 ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu