[PATCH] iommu/arm-smmu-v3: Add HAFT support for SVA
From: Robin Murphy <robin.murphy@arm.com>
Date: 2026-07-01 17:45:48
Also in:
linux-iommu, stable
Subsystem:
arm smmu drivers, arm smmu sva support, iommu subsystem, the rest · Maintainers:
Will Deacon, Joerg Roedel, Linus Torvalds
Since table access flags cannot be software-managed, if process
pagetables are using HAFT then SVA must require the SMMU to support and
enable it too, otherwise page aging is liable to get out of whack.
Cc: <redacted>
Fixes: 62df5870ebf7 ("arm64: Enable ARCH_HAS_NONLEAF_PMD_YOUNG")
Signed-off-by: Robin Murphy <robin.murphy@arm.com>
---
drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-sva.c | 5 +++++
drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c | 6 ++++++
drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h | 3 +++
3 files changed, 14 insertions(+)
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 1ed8a6f29dc4..ef11e9493f93 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@@ -102,6 +102,8 @@ void arm_smmu_make_sva_cd(struct arm_smmu_cd *target, target->data[0] |= cpu_to_le64(CTXDESC_CD_0_TCR_HA); if (master->smmu->features & ARM_SMMU_FEAT_HD) target->data[0] |= cpu_to_le64(CTXDESC_CD_0_TCR_HD); + if (master->smmu->features & ARM_SMMU_FEAT_HAFT && system_supports_haft()) + target->data[1] |= cpu_to_le64(CTXDESC_CD_1_HAFT); } else { target->data[0] |= cpu_to_le64(CTXDESC_CD_0_TCR_EPD0);
@@ -211,6 +213,9 @@ bool arm_smmu_sva_supported(struct arm_smmu_device *smmu) if (system_supports_bbml2_noabort()) feat_mask |= ARM_SMMU_FEAT_BBML2; + if (system_supports_haft()) + feat_mask |= ARM_SMMU_FEAT_HAFT; + if ((smmu->features & feat_mask) != feat_mask) return false;
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 a10affb483a4..7637e9128533 100644
--- a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
+++ b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c@@ -4925,6 +4925,9 @@ static void arm_smmu_get_httu(struct arm_smmu_device *smmu, u32 reg) u32 hw_features = 0; switch (FIELD_GET(IDR0_HTTU, reg)) { + case IDR0_HTTU_ACCESS_DIRTY_HAFT: + hw_features |= ARM_SMMU_FEAT_HAFT; + fallthrough; case IDR0_HTTU_ACCESS_DIRTY: hw_features |= ARM_SMMU_FEAT_HD; fallthrough;
@@ -5256,6 +5259,9 @@ static int arm_smmu_device_acpi_probe(struct platform_device *pdev, smmu->features |= ARM_SMMU_FEAT_COHERENCY; switch (FIELD_GET(ACPI_IORT_SMMU_V3_HTTU_OVERRIDE, iort_smmu->flags)) { + case IDR0_HTTU_ACCESS_DIRTY_HAFT: + smmu->features |= ARM_SMMU_FEAT_HAFT; + fallthrough; case IDR0_HTTU_ACCESS_DIRTY: smmu->features |= ARM_SMMU_FEAT_HD; fallthrough;
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 c909c9a88538..61a7df5afb99 100644
--- a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h
+++ b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h@@ -40,6 +40,7 @@ struct arm_vsmmu; #define IDR0_HTTU GENMASK(7, 6) #define IDR0_HTTU_ACCESS 1 #define IDR0_HTTU_ACCESS_DIRTY 2 +#define IDR0_HTTU_ACCESS_DIRTY_HAFT 3 #define IDR0_COHACC (1 << 4) #define IDR0_TTF GENMASK(3, 2) #define IDR0_TTF_AARCH64 2
@@ -369,6 +370,7 @@ static inline unsigned int arm_smmu_cdtab_l2_idx(unsigned int ssid) #define CTXDESC_CD_0_ASET (1UL << 47) #define CTXDESC_CD_0_ASID GENMASK_ULL(63, 48) +#define CTXDESC_CD_1_HAFT (1UL << 3) #define CTXDESC_CD_1_TTB0_MASK GENMASK_ULL(51, 4) /*
@@ -921,6 +923,7 @@ struct arm_smmu_device { #define ARM_SMMU_FEAT_HD (1 << 22) #define ARM_SMMU_FEAT_S2FWB (1 << 23) #define ARM_SMMU_FEAT_BBML2 (1 << 24) +#define ARM_SMMU_FEAT_HAFT (1 << 25) u32 features; #define ARM_SMMU_OPT_SKIP_PREFETCH (1 << 0)
--
2.54.0.dirty