From: jiangkunkun <jiangkun...@huawei.com>

When altering a translation table descriptor of some specific reasons,
we require break-before-make procedure. But it might cause problems when
the TTD is alive. The I/O streams might not tolerate translation faults.

If the SMMU supports BBML level 1 or BBML level 2, we can change the block
size without using break-before-make.

This adds feature detection for BBML, none functional change.

Co-developed-by: Keqian Zhu <zhukeqi...@huawei.com>
Signed-off-by: Kunkun Jiang <jiangkun...@huawei.com>
---
 drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c | 24 ++++++++++++++++++++-
 drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h |  6 ++++++
 include/linux/io-pgtable.h                  |  1 +
 3 files changed, 30 insertions(+), 1 deletion(-)

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 8cc9d7536b08..9208881a571c 100644
--- a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
+++ b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
@@ -1947,7 +1947,7 @@ static int arm_smmu_domain_finalise_s2(struct 
arm_smmu_domain *smmu_domain,
 static int arm_smmu_domain_finalise(struct iommu_domain *domain,
                                    struct arm_smmu_master *master)
 {
-       int ret;
+       int ret, bbml;
        unsigned long ias, oas;
        enum io_pgtable_fmt fmt;
        struct io_pgtable_cfg pgtbl_cfg;
@@ -1988,12 +1988,20 @@ static int arm_smmu_domain_finalise(struct iommu_domain 
*domain,
                return -EINVAL;
        }
 
+       if (smmu->features & ARM_SMMU_FEAT_BBML2)
+               bbml = 2;
+       else if (smmu->features & ARM_SMMU_FEAT_BBML1)
+               bbml = 1;
+       else
+               bbml = 0;
+
        pgtbl_cfg = (struct io_pgtable_cfg) {
                .pgsize_bitmap  = smmu->pgsize_bitmap,
                .ias            = ias,
                .oas            = oas,
                .httu_hd        = smmu->features & ARM_SMMU_FEAT_HTTU_HD,
                .coherent_walk  = smmu->features & ARM_SMMU_FEAT_COHERENCY,
+               .bbml           = bbml,
                .tlb            = &arm_smmu_flush_ops,
                .iommu_dev      = smmu->dev,
        };
@@ -3328,6 +3336,20 @@ static int arm_smmu_device_hw_probe(struct 
arm_smmu_device *smmu)
 
        /* IDR3 */
        reg = readl_relaxed(smmu->base + ARM_SMMU_IDR3);
+       switch (FIELD_GET(IDR3_BBML, reg)) {
+       case IDR3_BBML0:
+               break;
+       case IDR3_BBML1:
+               smmu->features |= ARM_SMMU_FEAT_BBML1;
+               break;
+       case IDR3_BBML2:
+               smmu->features |= ARM_SMMU_FEAT_BBML2;
+               break;
+       default:
+               dev_err(smmu->dev, "unknown/unsupported BBM behavior level\n");
+               return -ENXIO;
+       }
+
        if (FIELD_GET(IDR3_RIL, reg))
                smmu->features |= ARM_SMMU_FEAT_RANGE_INV;
 
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 e91bea44519e..11e526ab7239 100644
--- a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h
+++ b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h
@@ -55,6 +55,10 @@
 #define IDR1_SIDSIZE                   GENMASK(5, 0)
 
 #define ARM_SMMU_IDR3                  0xc
+#define IDR3_BBML                      GENMASK(12, 11)
+#define IDR3_BBML0                     0
+#define IDR3_BBML1                     1
+#define IDR3_BBML2                     2
 #define IDR3_RIL                       (1 << 10)
 
 #define ARM_SMMU_IDR5                  0x14
@@ -612,6 +616,8 @@ struct arm_smmu_device {
 #define ARM_SMMU_FEAT_SVA              (1 << 17)
 #define ARM_SMMU_FEAT_HTTU_HA          (1 << 18)
 #define ARM_SMMU_FEAT_HTTU_HD          (1 << 19)
+#define ARM_SMMU_FEAT_BBML1            (1 << 20)
+#define ARM_SMMU_FEAT_BBML2            (1 << 21)
        u32                             features;
 
 #define ARM_SMMU_OPT_SKIP_PREFETCH     (1 << 0)
diff --git a/include/linux/io-pgtable.h b/include/linux/io-pgtable.h
index 1a00ea8562c7..26583beeb5d9 100644
--- a/include/linux/io-pgtable.h
+++ b/include/linux/io-pgtable.h
@@ -99,6 +99,7 @@ struct io_pgtable_cfg {
        unsigned int                    oas;
        bool                            httu_hd;
        bool                            coherent_walk;
+       int                             bbml;
        const struct iommu_flush_ops    *tlb;
        struct device                   *iommu_dev;
 
-- 
2.19.1

_______________________________________________
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm

Reply via email to