Skip to content

Commit ec9098d

Browse files
misalehwilldeacon
authored andcommitted
iommu/arm-smmu-v3: Fix access for STE.SHCFG
STE attributes(NSCFG, PRIVCFG, INSTCFG) use value 0 for "Use Icomming", for some reason SHCFG doesn't follow that, and it is defined as "0b01". Currently the driver sets SHCFG to Use Incoming for stage-2 and bypass domains. However according to the User Manual (ARM IHI 0070 F.b): When SMMU_IDR1.ATTR_TYPES_OVR == 0, this field is RES0 and the incoming Shareability attribute is used. This patch adds a condition for writing SHCFG to Use incoming to be compliant with the architecture, and defines ATTR_TYPE_OVR as a new feature discovered from IDR1. This also required to propagate the SMMU through some functions args. There is no need to add similar condition for the newly introduced function arm_smmu_get_ste_used() as the values of the STE are the same before and after any transition, so this will not trigger any change. (we already do the same for the VMID). Although this is a misconfiguration from the driver, this has been there for a long time, so probably no HW running Linux is affected by it. Reported-by: Will Deacon <will@kernel.org> Closes: https://lore.kernel.org/all/20240215134952.GA690@willie-the-truck/ Signed-off-by: Mostafa Saleh <smostafa@google.com> Reviewed-by: Jason Gunthorpe <jgg@nvidia.com> Link: https://lore.kernel.org/r/20240323134658.464743-1-smostafa@google.com Signed-off-by: Will Deacon <will@kernel.org>
1 parent 0493e73 commit ec9098d

File tree

2 files changed

+25
-12
lines changed

2 files changed

+25
-12
lines changed

drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c

Lines changed: 23 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1454,14 +1454,17 @@ static void arm_smmu_make_abort_ste(struct arm_smmu_ste *target)
14541454
FIELD_PREP(STRTAB_STE_0_CFG, STRTAB_STE_0_CFG_ABORT));
14551455
}
14561456

1457-
static void arm_smmu_make_bypass_ste(struct arm_smmu_ste *target)
1457+
static void arm_smmu_make_bypass_ste(struct arm_smmu_device *smmu,
1458+
struct arm_smmu_ste *target)
14581459
{
14591460
memset(target, 0, sizeof(*target));
14601461
target->data[0] = cpu_to_le64(
14611462
STRTAB_STE_0_V |
14621463
FIELD_PREP(STRTAB_STE_0_CFG, STRTAB_STE_0_CFG_BYPASS));
1463-
target->data[1] = cpu_to_le64(
1464-
FIELD_PREP(STRTAB_STE_1_SHCFG, STRTAB_STE_1_SHCFG_INCOMING));
1464+
1465+
if (smmu->features & ARM_SMMU_FEAT_ATTR_TYPES_OVR)
1466+
target->data[1] = cpu_to_le64(FIELD_PREP(STRTAB_STE_1_SHCFG,
1467+
STRTAB_STE_1_SHCFG_INCOMING));
14651468
}
14661469

14671470
static void arm_smmu_make_cdtable_ste(struct arm_smmu_ste *target,
@@ -1524,6 +1527,7 @@ static void arm_smmu_make_s2_domain_ste(struct arm_smmu_ste *target,
15241527
typeof(&pgtbl_cfg->arm_lpae_s2_cfg.vtcr) vtcr =
15251528
&pgtbl_cfg->arm_lpae_s2_cfg.vtcr;
15261529
u64 vtcr_val;
1530+
struct arm_smmu_device *smmu = master->smmu;
15271531

15281532
memset(target, 0, sizeof(*target));
15291533
target->data[0] = cpu_to_le64(
@@ -1532,9 +1536,11 @@ static void arm_smmu_make_s2_domain_ste(struct arm_smmu_ste *target,
15321536

15331537
target->data[1] = cpu_to_le64(
15341538
FIELD_PREP(STRTAB_STE_1_EATS,
1535-
master->ats_enabled ? STRTAB_STE_1_EATS_TRANS : 0) |
1536-
FIELD_PREP(STRTAB_STE_1_SHCFG,
1537-
STRTAB_STE_1_SHCFG_INCOMING));
1539+
master->ats_enabled ? STRTAB_STE_1_EATS_TRANS : 0));
1540+
1541+
if (smmu->features & ARM_SMMU_FEAT_ATTR_TYPES_OVR)
1542+
target->data[1] |= cpu_to_le64(FIELD_PREP(STRTAB_STE_1_SHCFG,
1543+
STRTAB_STE_1_SHCFG_INCOMING));
15381544

15391545
vtcr_val = FIELD_PREP(STRTAB_STE_2_VTCR_S2T0SZ, vtcr->tsz) |
15401546
FIELD_PREP(STRTAB_STE_2_VTCR_S2SL0, vtcr->sl) |
@@ -1561,7 +1567,8 @@ static void arm_smmu_make_s2_domain_ste(struct arm_smmu_ste *target,
15611567
* This can safely directly manipulate the STE memory without a sync sequence
15621568
* because the STE table has not been installed in the SMMU yet.
15631569
*/
1564-
static void arm_smmu_init_initial_stes(struct arm_smmu_ste *strtab,
1570+
static void arm_smmu_init_initial_stes(struct arm_smmu_device *smmu,
1571+
struct arm_smmu_ste *strtab,
15651572
unsigned int nent)
15661573
{
15671574
unsigned int i;
@@ -1570,7 +1577,7 @@ static void arm_smmu_init_initial_stes(struct arm_smmu_ste *strtab,
15701577
if (disable_bypass)
15711578
arm_smmu_make_abort_ste(strtab);
15721579
else
1573-
arm_smmu_make_bypass_ste(strtab);
1580+
arm_smmu_make_bypass_ste(smmu, strtab);
15741581
strtab++;
15751582
}
15761583
}
@@ -1598,7 +1605,7 @@ static int arm_smmu_init_l2_strtab(struct arm_smmu_device *smmu, u32 sid)
15981605
return -ENOMEM;
15991606
}
16001607

1601-
arm_smmu_init_initial_stes(desc->l2ptr, 1 << STRTAB_SPLIT);
1608+
arm_smmu_init_initial_stes(smmu, desc->l2ptr, 1 << STRTAB_SPLIT);
16021609
arm_smmu_write_strtab_l1_desc(strtab, desc);
16031610
return 0;
16041611
}
@@ -2638,8 +2645,9 @@ static int arm_smmu_attach_dev_identity(struct iommu_domain *domain,
26382645
struct device *dev)
26392646
{
26402647
struct arm_smmu_ste ste;
2648+
struct arm_smmu_master *master = dev_iommu_priv_get(dev);
26412649

2642-
arm_smmu_make_bypass_ste(&ste);
2650+
arm_smmu_make_bypass_ste(master->smmu, &ste);
26432651
return arm_smmu_attach_dev_ste(dev, &ste);
26442652
}
26452653

@@ -3265,7 +3273,7 @@ static int arm_smmu_init_strtab_linear(struct arm_smmu_device *smmu)
32653273
reg |= FIELD_PREP(STRTAB_BASE_CFG_LOG2SIZE, smmu->sid_bits);
32663274
cfg->strtab_base_cfg = reg;
32673275

3268-
arm_smmu_init_initial_stes(strtab, cfg->num_l1_ents);
3276+
arm_smmu_init_initial_stes(smmu, strtab, cfg->num_l1_ents);
32693277
return 0;
32703278
}
32713279

@@ -3778,6 +3786,9 @@ static int arm_smmu_device_hw_probe(struct arm_smmu_device *smmu)
37783786
return -ENXIO;
37793787
}
37803788

3789+
if (reg & IDR1_ATTR_TYPES_OVR)
3790+
smmu->features |= ARM_SMMU_FEAT_ATTR_TYPES_OVR;
3791+
37813792
/* Queue sizes, capped to ensure natural alignment */
37823793
smmu->cmdq.q.llq.max_n_shift = min_t(u32, CMDQ_MAX_SZ_SHIFT,
37833794
FIELD_GET(IDR1_CMDQS, reg));
@@ -3993,7 +4004,7 @@ static void arm_smmu_rmr_install_bypass_ste(struct arm_smmu_device *smmu)
39934004
* STE table is not programmed to HW, see
39944005
* arm_smmu_initial_bypass_stes()
39954006
*/
3996-
arm_smmu_make_bypass_ste(
4007+
arm_smmu_make_bypass_ste(smmu,
39974008
arm_smmu_get_step_for_sid(smmu, rmr->sids[i]));
39984009
}
39994010
}

drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@
4444
#define IDR1_TABLES_PRESET (1 << 30)
4545
#define IDR1_QUEUES_PRESET (1 << 29)
4646
#define IDR1_REL (1 << 28)
47+
#define IDR1_ATTR_TYPES_OVR (1 << 27)
4748
#define IDR1_CMDQS GENMASK(25, 21)
4849
#define IDR1_EVTQS GENMASK(20, 16)
4950
#define IDR1_PRIQS GENMASK(15, 11)
@@ -647,6 +648,7 @@ struct arm_smmu_device {
647648
#define ARM_SMMU_FEAT_SVA (1 << 17)
648649
#define ARM_SMMU_FEAT_E2H (1 << 18)
649650
#define ARM_SMMU_FEAT_NESTING (1 << 19)
651+
#define ARM_SMMU_FEAT_ATTR_TYPES_OVR (1 << 20)
650652
u32 features;
651653

652654
#define ARM_SMMU_OPT_SKIP_PREFETCH (1 << 0)

0 commit comments

Comments
 (0)