[PATCH v2 4/4] iommu/arm-smmu-v3: Enable HTTU for stage1 with io-pgtable mapping
Ryan Roberts
ryan.roberts at arm.com
Tue Apr 23 09:45:16 PDT 2024
On 22/02/2024 09:49, Shameer Kolothum wrote:
> From: Kunkun Jiang <jiangkunkun at huawei.com>
>
> If io-pgtable quirk flag indicates support for hardware update of
> dirty state, enable HA/HD bits in the SMMU CD and also set the DBM
> bit in the page descriptor.
>
> And now report the dirty page tracking capability of SMMUv3.
>
> Co-developed-by: Keqian Zhu <zhukeqian1 at huawei.com>
> Signed-off-by: Keqian Zhu <zhukeqian1 at huawei.com>
> Signed-off-by: Kunkun Jiang <jiangkunkun at huawei.com>
> Signed-off-by: Joao Martins <joao.m.martins at oracle.com>
> Signed-off-by: Shameer Kolothum <shameerali.kolothum.thodi at huawei.com>
Section 3.13 of the spec states: "Where translation tables are shared between
CDs that contain the same ASID (within a translation regime), the CD HA and HD
fields must be identical."
I don't think the way that smmu domains work, its possible to end up with a
single pgtable shared between multiple CDs? So the driver should be able to
guarantee this constraint is met?
Assuming yes:
Reviewed-by: Ryan Roberts <ryan.roberts at arm.com>
> ---
> drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c | 15 +++++++++++++++
> drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h | 3 +++
> drivers/iommu/io-pgtable-arm.c | 5 ++++-
> 3 files changed, 22 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 058bbb0dbe2e..4423cc7e48cf 100644
> --- a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
> +++ b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
> @@ -1271,6 +1271,12 @@ void arm_smmu_make_s1_cd(struct arm_smmu_cd *target,
> CTXDESC_CD_0_ASET |
> FIELD_PREP(CTXDESC_CD_0_ASID, smmu_domain->asid)
> );
> +
> + /* To enable dirty flag update, set both Access flag and dirty state update */
> + if (pgtbl_cfg->quirks & IO_PGTABLE_QUIRK_ARM_HD)
> + target->data[0] |= cpu_to_le64(CTXDESC_CD_0_TCR_HA |
> + CTXDESC_CD_0_TCR_HD);
> +
> target->data[1] = cpu_to_le64(pgtbl_cfg->arm_lpae_s1_cfg.ttbr &
> CTXDESC_CD_1_TTB0_MASK);
> target->data[3] = cpu_to_le64(pgtbl_cfg->arm_lpae_s1_cfg.mair);
> @@ -2307,6 +2313,13 @@ static const struct iommu_flush_ops arm_smmu_flush_ops = {
> .tlb_add_page = arm_smmu_tlb_inv_page_nosync,
> };
>
> +static bool arm_smmu_dbm_capable(struct arm_smmu_device *smmu)
> +{
> + u32 features = (ARM_SMMU_FEAT_HD | ARM_SMMU_FEAT_COHERENCY);
> +
> + return (smmu->features & features) == features;
> +}
> +
> /* IOMMU API */
> static bool arm_smmu_capable(struct device *dev, enum iommu_cap cap)
> {
> @@ -2319,6 +2332,8 @@ static bool arm_smmu_capable(struct device *dev, enum iommu_cap cap)
> case IOMMU_CAP_NOEXEC:
> case IOMMU_CAP_DEFERRED_FLUSH:
> return true;
> + case IOMMU_CAP_DIRTY_TRACKING:
> + return arm_smmu_dbm_capable(master->smmu);
> default:
> return false;
> }
> 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 5e51a6c1d55f..a9cd805e5a1b 100644
> --- a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h
> +++ b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h
> @@ -313,6 +313,9 @@ struct arm_smmu_cd {
> #define CTXDESC_CD_0_TCR_IPS GENMASK_ULL(34, 32)
> #define CTXDESC_CD_0_TCR_TBI0 (1ULL << 38)
>
> +#define CTXDESC_CD_0_TCR_HA (1UL << 43)
> +#define CTXDESC_CD_0_TCR_HD (1UL << 42)
> +
> #define CTXDESC_CD_0_AA64 (1UL << 41)
> #define CTXDESC_CD_0_S (1UL << 44)
> #define CTXDESC_CD_0_R (1UL << 45)
> diff --git a/drivers/iommu/io-pgtable-arm.c b/drivers/iommu/io-pgtable-arm.c
> index 1ce7b7a3c1e8..56e88e555fc7 100644
> --- a/drivers/iommu/io-pgtable-arm.c
> +++ b/drivers/iommu/io-pgtable-arm.c
> @@ -429,6 +429,8 @@ static arm_lpae_iopte arm_lpae_prot_to_pte(struct arm_lpae_io_pgtable *data,
> pte = ARM_LPAE_PTE_nG;
> if (!(prot & IOMMU_WRITE) && (prot & IOMMU_READ))
> pte |= ARM_LPAE_PTE_AP_RDONLY;
> + else if (data->iop.cfg.quirks & IO_PGTABLE_QUIRK_ARM_HD)
> + pte |= ARM_LPAE_PTE_AP_WRITABLE;
> if (!(prot & IOMMU_PRIV))
> pte |= ARM_LPAE_PTE_AP_UNPRIV;
> } else {
> @@ -948,7 +950,8 @@ arm_64_lpae_alloc_pgtable_s1(struct io_pgtable_cfg *cfg, void *cookie)
>
> if (cfg->quirks & ~(IO_PGTABLE_QUIRK_ARM_NS |
> IO_PGTABLE_QUIRK_ARM_TTBR1 |
> - IO_PGTABLE_QUIRK_ARM_OUTER_WBWA))
> + IO_PGTABLE_QUIRK_ARM_OUTER_WBWA |
> + IO_PGTABLE_QUIRK_ARM_HD))
> return NULL;
>
> data = arm_lpae_alloc_pgtable(cfg);
More information about the linux-arm-kernel
mailing list