Re: [PATCH RFC 13/19] iommu/arm-smmu-v3: Add feature detection for BBML

Robin Murphy
2022-04-29T11:11:54Z

On 2022-04-28 22:09, Joao Martins wrote:
> From: Kunkun Jiang <jiangkunkun@huawei.com>
>
> This detects BBML feature and if SMMU supports it, transfer BBMLx
> quirk to io-pgtable.
>
> BBML1 requires still marking PTE nT prior to performing a
> translation table update, while BBML2 requires neither break-before-make
> nor PTE nT bit being set. For dirty tracking it needs to clear
> the dirty bit so checking BBML2 tells us the prerequisite. See SMMUv3.2
> manual, section "3.21.1.3 When SMMU_IDR3.BBML == 2 (Level 2)" and
> "3.21.1.2 When SMMU_IDR3.BBML == 1 (Level 1)"

You can drop this, and the dependencies on BBML elsewhere, until you get
round to the future large-page-splitting work, since that's the only
thing this represents. Not much point having the feature flags without
an actual implementation, or any users.

Robin.

> Co-developed-by: Keqian Zhu <zhukeqian1@huawei.com>
> Signed-off-by: Keqian Zhu <zhukeqian1@huawei.com>
> Signed-off-by: Kunkun Jiang <jiangkunkun@huawei.com>
> [joaomart: massage commit message with the need to have BBML quirk
> and add the Quirk io-pgtable flags]
> Signed-off-by: Joao Martins <joao.m.martins@oracle.com>
> ---
> drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c | 19 +++++++++++++++++++
> drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h | 6 ++++++
> include/linux/io-pgtable.h | 3 +++
> 3 files changed, 28 insertions(+)
>
> 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 14609ece4e33..4dba53bde2e3 100644
> --- a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
> +++ b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
> @@ -2203,6 +2203,11 @@ static int arm_smmu_domain_finalise(struct iommu_domain *domain,
> .iommu_dev = smmu->dev,
> };
>
> + if (smmu->features & ARM_SMMU_FEAT_BBML1)
> + pgtbl_cfg.quirks |= IO_PGTABLE_QUIRK_ARM_BBML1;
> + else if (smmu->features & ARM_SMMU_FEAT_BBML2)
> + pgtbl_cfg.quirks |= IO_PGTABLE_QUIRK_ARM_BBML2;
> +
> pgtbl_ops = alloc_io_pgtable_ops(fmt, &pgtbl_cfg, smmu_domain);
> if (!pgtbl_ops)
> return -ENOMEM;
> @@ -3591,6 +3596,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 1487a80fdf1b..e15750be1d95 100644
> --- a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h
> +++ b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h
> @@ -54,6 +54,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
> @@ -644,6 +648,8 @@ struct arm_smmu_device {
> #define ARM_SMMU_FEAT_E2H (1 << 18)
> #define ARM_SMMU_FEAT_HA (1 << 19)
> #define ARM_SMMU_FEAT_HD (1 << 20)
> +#define ARM_SMMU_FEAT_BBML1 (1 << 21)
> +#define ARM_SMMU_FEAT_BBML2 (1 << 22)
> 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 c2ebfe037f5d..d7626ca67dbf 100644
> --- a/include/linux/io-pgtable.h
> +++ b/include/linux/io-pgtable.h
> @@ -85,6 +85,9 @@ struct io_pgtable_cfg {
> #define IO_PGTABLE_QUIRK_ARM_MTK_EXT BIT(3)
> #define IO_PGTABLE_QUIRK_ARM_TTBR1 BIT(5)
> #define IO_PGTABLE_QUIRK_ARM_OUTER_WBWA BIT(6)
> + #define IO_PGTABLE_QUIRK_ARM_BBML1 BIT(7)
> + #define IO_PGTABLE_QUIRK_ARM_BBML2 BIT(8)
> +
> unsigned long quirks;
> unsigned long pgsize_bitmap;
> unsigned int ias;