Skip to content

Commit 6e7a2ff

Browse files
committed
Merge tag 'iommu-fixes-v6.9-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/joro/iommu
Pull iommu fixes from Joerg Roedel: "ARM SMMU fixes: - Fix swabbing of the STE fields in the unlikely event of running on a big-endian machine - Fix setting of STE.SHCFG on hardware that doesn't implement support for attribute overrides IOMMU core: - PASID validation fix in device attach path" * tag 'iommu-fixes-v6.9-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/joro/iommu: iommu: Validate the PASID in iommu_attach_device_pasid() iommu/arm-smmu-v3: Fix access for STE.SHCFG iommu/arm-smmu-v3: Add cpu_to_le64() around STRTAB_STE_0_V
2 parents d8e8fbe + c404f55 commit 6e7a2ff

File tree

3 files changed

+37
-14
lines changed

3 files changed

+37
-14
lines changed

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

Lines changed: 25 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1139,7 +1139,8 @@ static void arm_smmu_write_ste(struct arm_smmu_master *master, u32 sid,
11391139
* requires a breaking update, zero the V bit, write all qwords
11401140
* but 0, then set qword 0
11411141
*/
1142-
unused_update.data[0] = entry->data[0] & (~STRTAB_STE_0_V);
1142+
unused_update.data[0] = entry->data[0] &
1143+
cpu_to_le64(~STRTAB_STE_0_V);
11431144
entry_set(smmu, sid, entry, &unused_update, 0, 1);
11441145
entry_set(smmu, sid, entry, target, 1, num_entry_qwords - 1);
11451146
entry_set(smmu, sid, entry, target, 0, 1);
@@ -1453,14 +1454,17 @@ static void arm_smmu_make_abort_ste(struct arm_smmu_ste *target)
14531454
FIELD_PREP(STRTAB_STE_0_CFG, STRTAB_STE_0_CFG_ABORT));
14541455
}
14551456

1456-
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)
14571459
{
14581460
memset(target, 0, sizeof(*target));
14591461
target->data[0] = cpu_to_le64(
14601462
STRTAB_STE_0_V |
14611463
FIELD_PREP(STRTAB_STE_0_CFG, STRTAB_STE_0_CFG_BYPASS));
1462-
target->data[1] = cpu_to_le64(
1463-
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));
14641468
}
14651469

14661470
static void arm_smmu_make_cdtable_ste(struct arm_smmu_ste *target,
@@ -1523,6 +1527,7 @@ static void arm_smmu_make_s2_domain_ste(struct arm_smmu_ste *target,
15231527
typeof(&pgtbl_cfg->arm_lpae_s2_cfg.vtcr) vtcr =
15241528
&pgtbl_cfg->arm_lpae_s2_cfg.vtcr;
15251529
u64 vtcr_val;
1530+
struct arm_smmu_device *smmu = master->smmu;
15261531

15271532
memset(target, 0, sizeof(*target));
15281533
target->data[0] = cpu_to_le64(
@@ -1531,9 +1536,11 @@ static void arm_smmu_make_s2_domain_ste(struct arm_smmu_ste *target,
15311536

15321537
target->data[1] = cpu_to_le64(
15331538
FIELD_PREP(STRTAB_STE_1_EATS,
1534-
master->ats_enabled ? STRTAB_STE_1_EATS_TRANS : 0) |
1535-
FIELD_PREP(STRTAB_STE_1_SHCFG,
1536-
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));
15371544

15381545
vtcr_val = FIELD_PREP(STRTAB_STE_2_VTCR_S2T0SZ, vtcr->tsz) |
15391546
FIELD_PREP(STRTAB_STE_2_VTCR_S2SL0, vtcr->sl) |
@@ -1560,7 +1567,8 @@ static void arm_smmu_make_s2_domain_ste(struct arm_smmu_ste *target,
15601567
* This can safely directly manipulate the STE memory without a sync sequence
15611568
* because the STE table has not been installed in the SMMU yet.
15621569
*/
1563-
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,
15641572
unsigned int nent)
15651573
{
15661574
unsigned int i;
@@ -1569,7 +1577,7 @@ static void arm_smmu_init_initial_stes(struct arm_smmu_ste *strtab,
15691577
if (disable_bypass)
15701578
arm_smmu_make_abort_ste(strtab);
15711579
else
1572-
arm_smmu_make_bypass_ste(strtab);
1580+
arm_smmu_make_bypass_ste(smmu, strtab);
15731581
strtab++;
15741582
}
15751583
}
@@ -1597,7 +1605,7 @@ static int arm_smmu_init_l2_strtab(struct arm_smmu_device *smmu, u32 sid)
15971605
return -ENOMEM;
15981606
}
15991607

1600-
arm_smmu_init_initial_stes(desc->l2ptr, 1 << STRTAB_SPLIT);
1608+
arm_smmu_init_initial_stes(smmu, desc->l2ptr, 1 << STRTAB_SPLIT);
16011609
arm_smmu_write_strtab_l1_desc(strtab, desc);
16021610
return 0;
16031611
}
@@ -2637,8 +2645,9 @@ static int arm_smmu_attach_dev_identity(struct iommu_domain *domain,
26372645
struct device *dev)
26382646
{
26392647
struct arm_smmu_ste ste;
2648+
struct arm_smmu_master *master = dev_iommu_priv_get(dev);
26402649

2641-
arm_smmu_make_bypass_ste(&ste);
2650+
arm_smmu_make_bypass_ste(master->smmu, &ste);
26422651
return arm_smmu_attach_dev_ste(dev, &ste);
26432652
}
26442653

@@ -3264,7 +3273,7 @@ static int arm_smmu_init_strtab_linear(struct arm_smmu_device *smmu)
32643273
reg |= FIELD_PREP(STRTAB_BASE_CFG_LOG2SIZE, smmu->sid_bits);
32653274
cfg->strtab_base_cfg = reg;
32663275

3267-
arm_smmu_init_initial_stes(strtab, cfg->num_l1_ents);
3276+
arm_smmu_init_initial_stes(smmu, strtab, cfg->num_l1_ents);
32683277
return 0;
32693278
}
32703279

@@ -3777,6 +3786,9 @@ static int arm_smmu_device_hw_probe(struct arm_smmu_device *smmu)
37773786
return -ENXIO;
37783787
}
37793788

3789+
if (reg & IDR1_ATTR_TYPES_OVR)
3790+
smmu->features |= ARM_SMMU_FEAT_ATTR_TYPES_OVR;
3791+
37803792
/* Queue sizes, capped to ensure natural alignment */
37813793
smmu->cmdq.q.llq.max_n_shift = min_t(u32, CMDQ_MAX_SZ_SHIFT,
37823794
FIELD_GET(IDR1_CMDQS, reg));
@@ -3992,7 +4004,7 @@ static void arm_smmu_rmr_install_bypass_ste(struct arm_smmu_device *smmu)
39924004
* STE table is not programmed to HW, see
39934005
* arm_smmu_initial_bypass_stes()
39944006
*/
3995-
arm_smmu_make_bypass_ste(
4007+
arm_smmu_make_bypass_ste(smmu,
39964008
arm_smmu_get_step_for_sid(smmu, rmr->sids[i]));
39974009
}
39984010
}

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)

drivers/iommu/iommu.c

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3354,6 +3354,7 @@ int iommu_attach_device_pasid(struct iommu_domain *domain,
33543354
{
33553355
/* Caller must be a probed driver on dev */
33563356
struct iommu_group *group = dev->iommu_group;
3357+
struct group_device *device;
33573358
void *curr;
33583359
int ret;
33593360

@@ -3363,10 +3364,18 @@ int iommu_attach_device_pasid(struct iommu_domain *domain,
33633364
if (!group)
33643365
return -ENODEV;
33653366

3366-
if (!dev_has_iommu(dev) || dev_iommu_ops(dev) != domain->owner)
3367+
if (!dev_has_iommu(dev) || dev_iommu_ops(dev) != domain->owner ||
3368+
pasid == IOMMU_NO_PASID)
33673369
return -EINVAL;
33683370

33693371
mutex_lock(&group->mutex);
3372+
for_each_group_device(group, device) {
3373+
if (pasid >= device->dev->iommu->max_pasids) {
3374+
ret = -EINVAL;
3375+
goto out_unlock;
3376+
}
3377+
}
3378+
33703379
curr = xa_cmpxchg(&group->pasid_array, pasid, NULL, domain, GFP_KERNEL);
33713380
if (curr) {
33723381
ret = xa_err(curr) ? : -EBUSY;

0 commit comments

Comments
 (0)