Re: [PATCH 2/3] iommu/arm-smmu-v3: Make BTM optional for SVA

2021-01-22 Thread Jean-Philippe Brucker
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

2021-01-22 Thread Robin Murphy

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

2021-01-22 Thread Jean-Philippe Brucker
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