[PATCH 2/2] iommu/arm-smmu-v3: Override for Inst/Data attribute
From: Peter Griffin
Date: Fri Jul 24 2026 - 08:41:13 EST
Add an option to override the instruction/data attribute
of incoming traffic to Data by setting the INSTCFG override
in all Stream Table Entries.
The option can be provided in the device tree entry for the SMMU
by adding the "arm,instdata-override" property.
Changes by Peter Griffin:
- Make it apply on vanilla upstream arm-smmu-v3
Signed-off-by: Pranjal Shrivastava <praan@xxxxxxxxxx>
Signed-off-by: Peter Griffin <peter.griffin@xxxxxxxxxx>
---
drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c | 26 ++++++++++++++++++++++----
drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h | 7 +++++++
2 files changed, 29 insertions(+), 4 deletions(-)
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 57b750ebcd3d..2b39cb5aa49d 100644
--- a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
+++ b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
@@ -82,6 +82,7 @@ DEFINE_MUTEX(arm_smmu_asid_lock);
static struct arm_smmu_option_prop arm_smmu_options[] = {
{ ARM_SMMU_OPT_SKIP_PREFETCH, "hisilicon,broken-prefetch-cmd" },
{ ARM_SMMU_OPT_PAGE0_REGS_ONLY, "cavium,cn9900-broken-page1-regspace"},
+ { ARM_SMMU_OPT_OVR_INSTCFG_DATA, "arm,instdata-override"},
{ 0, NULL},
};
@@ -1206,7 +1207,8 @@ void arm_smmu_get_ste_used(const __le64 *ent, __le64 *used_bits)
cpu_to_le64(STRTAB_STE_1_S1DSS | STRTAB_STE_1_S1CIR |
STRTAB_STE_1_S1COR | STRTAB_STE_1_S1CSH |
STRTAB_STE_1_S1STALLD | STRTAB_STE_1_STRW |
- STRTAB_STE_1_EATS | STRTAB_STE_1_MEV);
+ STRTAB_STE_1_EATS | STRTAB_STE_1_MEV |
+ STRTAB_STE_1_INSTCFG);
used_bits[2] |= cpu_to_le64(STRTAB_STE_2_S2VMID);
/*
@@ -1222,7 +1224,8 @@ void arm_smmu_get_ste_used(const __le64 *ent, __le64 *used_bits)
if (cfg & BIT(1)) {
used_bits[1] |=
cpu_to_le64(STRTAB_STE_1_S2FWB | STRTAB_STE_1_EATS |
- STRTAB_STE_1_SHCFG | STRTAB_STE_1_MEV);
+ STRTAB_STE_1_SHCFG | STRTAB_STE_1_MEV |
+ STRTAB_STE_1_INSTCFG);
used_bits[2] |=
cpu_to_le64(STRTAB_STE_2_S2VMID | STRTAB_STE_2_VTCR |
STRTAB_STE_2_S2AA64 | STRTAB_STE_2_S2ENDI |
@@ -1835,7 +1838,11 @@ void arm_smmu_make_cdtable_ste(struct arm_smmu_ste *target,
STRTAB_STE_1_S1STALLD :
0) |
FIELD_PREP(STRTAB_STE_1_EATS,
- ats_enabled ? STRTAB_STE_1_EATS_TRANS : 0));
+ ats_enabled ? STRTAB_STE_1_EATS_TRANS : 0)) |
+ FIELD_PREP(STRTAB_STE_1_INSTCFG,
+ smmu->options & ARM_SMMU_OPT_OVR_INSTCFG_DATA ?
+ STRTAB_STE_1_INSTCFG_DATA :
+ STRTAB_STE_1_INSTCFG_INCOMING);
if ((smmu->features & ARM_SMMU_FEAT_ATTR_TYPES_OVR) &&
s1dss == STRTAB_STE_1_S1DSS_BYPASS)
@@ -1887,7 +1894,11 @@ void arm_smmu_make_s2_domain_ste(struct arm_smmu_ste *target,
target->data[1] = cpu_to_le64(
FIELD_PREP(STRTAB_STE_1_EATS,
- ats_enabled ? STRTAB_STE_1_EATS_TRANS : 0));
+ ats_enabled ? STRTAB_STE_1_EATS_TRANS : 0) |
+ FIELD_PREP(STRTAB_STE_1_INSTCFG,
+ smmu->options & ARM_SMMU_OPT_OVR_INSTCFG_DATA ?
+ STRTAB_STE_1_INSTCFG_DATA :
+ STRTAB_STE_1_INSTCFG_INCOMING));
if (pgtbl_cfg->quirks & IO_PGTABLE_QUIRK_ARM_S2FWB)
target->data[1] |= cpu_to_le64(STRTAB_STE_1_S2FWB);
@@ -5087,6 +5098,13 @@ static int arm_smmu_device_hw_probe(struct arm_smmu_device *smmu)
if (smmu->sid_bits <= STRTAB_SPLIT)
smmu->features &= ~ARM_SMMU_FEAT_2_LVL_STRTAB;
+ if (reg & IDR1_ATTR_PERMS_OVR) {
+ smmu->features |= ARM_SMMU_FEAT_PERMS_OVR;
+ } else if (smmu->options & ARM_SMMU_OPT_OVR_INSTCFG_DATA) {
+ dev_err(smmu->dev, "Inst/Data attribute override not supported\n");
+ return -ENXIO;
+ }
+
/* IDR3 */
reg = readl_relaxed(smmu->base + ARM_SMMU_IDR3);
if (FIELD_GET(IDR3_RIL, reg))
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..e5f5c0bc6b8a 100644
--- a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h
+++ b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h
@@ -51,6 +51,7 @@ struct arm_vsmmu;
#define IDR1_QUEUES_PRESET (1 << 29)
#define IDR1_REL (1 << 28)
#define IDR1_ATTR_TYPES_OVR (1 << 27)
+#define IDR1_ATTR_PERMS_OVR (1 << 26)
#define IDR1_CMDQS GENMASK(25, 21)
#define IDR1_EVTQS GENMASK(20, 16)
#define IDR1_PRIQS GENMASK(15, 11)
@@ -283,6 +284,10 @@ static inline u32 arm_smmu_strtab_l2_idx(u32 sid)
#define STRTAB_STE_1_SHCFG GENMASK_ULL(45, 44)
#define STRTAB_STE_1_SHCFG_INCOMING 1UL
+#define STRTAB_STE_1_INSTCFG GENMASK_ULL(51, 50)
+#define STRTAB_STE_1_INSTCFG_INCOMING 0UL
+#define STRTAB_STE_1_INSTCFG_DATA 2UL
+
#define STRTAB_STE_2_S2VMID GENMASK_ULL(15, 0)
#define STRTAB_STE_2_VTCR GENMASK_ULL(50, 32)
#define STRTAB_STE_2_VTCR_S2T0SZ GENMASK_ULL(5, 0)
@@ -921,6 +926,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_PERMS_OVR (1 << 25)
u32 features;
#define ARM_SMMU_OPT_SKIP_PREFETCH (1 << 0)
@@ -928,6 +934,7 @@ struct arm_smmu_device {
#define ARM_SMMU_OPT_MSIPOLL (1 << 2)
#define ARM_SMMU_OPT_CMDQ_FORCE_SYNC (1 << 3)
#define ARM_SMMU_OPT_TEGRA241_CMDQV (1 << 4)
+#define ARM_SMMU_OPT_OVR_INSTCFG_DATA (1 << 5)
u32 options;
struct arm_smmu_cmdq cmdq;
--
2.55.0.229.g6434b31f56-goog