Skip to content

Commit e89573c

Browse files
jgunthorpewilldeacon
authored andcommitted
iommu/arm-smmu-v3: Report IOMMU_CAP_ENFORCE_CACHE_COHERENCY for CANWBS
HW with CANWBS is always cache coherent and ignores PCI No Snoop requests as well. This meets the requirement for IOMMU_CAP_ENFORCE_CACHE_COHERENCY, so let's return it. Implement the enforce_cache_coherency() op to reject attaching devices that don't have CANWBS. Reviewed-by: Nicolin Chen <nicolinc@nvidia.com> Reviewed-by: Mostafa Saleh <smostafa@google.com> Reviewed-by: Kevin Tian <kevin.tian@intel.com> Reviewed-by: Jerry Snitselaar <jsnitsel@redhat.com> Reviewed-by: Donald Dutile <ddutile@redhat.com> Tested-by: Nicolin Chen <nicolinc@nvidia.com> Signed-off-by: Jason Gunthorpe <jgg@nvidia.com> Link: https://lore.kernel.org/r/4-v4-9e99b76f3518+3a8-smmuv3_nesting_jgg@nvidia.com Signed-off-by: Will Deacon <will@kernel.org>
1 parent 807404d commit e89573c

File tree

2 files changed

+38
-0
lines changed

2 files changed

+38
-0
lines changed

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

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2293,6 +2293,8 @@ static bool arm_smmu_capable(struct device *dev, enum iommu_cap cap)
22932293
case IOMMU_CAP_CACHE_COHERENCY:
22942294
/* Assume that a coherent TCU implies coherent TBUs */
22952295
return master->smmu->features & ARM_SMMU_FEAT_COHERENCY;
2296+
case IOMMU_CAP_ENFORCE_CACHE_COHERENCY:
2297+
return arm_smmu_master_canwbs(master);
22962298
case IOMMU_CAP_NOEXEC:
22972299
case IOMMU_CAP_DEFERRED_FLUSH:
22982300
return true;
@@ -2303,6 +2305,26 @@ static bool arm_smmu_capable(struct device *dev, enum iommu_cap cap)
23032305
}
23042306
}
23052307

2308+
static bool arm_smmu_enforce_cache_coherency(struct iommu_domain *domain)
2309+
{
2310+
struct arm_smmu_domain *smmu_domain = to_smmu_domain(domain);
2311+
struct arm_smmu_master_domain *master_domain;
2312+
unsigned long flags;
2313+
bool ret = true;
2314+
2315+
spin_lock_irqsave(&smmu_domain->devices_lock, flags);
2316+
list_for_each_entry(master_domain, &smmu_domain->devices,
2317+
devices_elm) {
2318+
if (!arm_smmu_master_canwbs(master_domain->master)) {
2319+
ret = false;
2320+
break;
2321+
}
2322+
}
2323+
smmu_domain->enforce_cache_coherency = ret;
2324+
spin_unlock_irqrestore(&smmu_domain->devices_lock, flags);
2325+
return ret;
2326+
}
2327+
23062328
struct arm_smmu_domain *arm_smmu_domain_alloc(void)
23072329
{
23082330
struct arm_smmu_domain *smmu_domain;
@@ -2731,6 +2753,14 @@ static int arm_smmu_attach_prepare(struct arm_smmu_attach_state *state,
27312753
* one of them.
27322754
*/
27332755
spin_lock_irqsave(&smmu_domain->devices_lock, flags);
2756+
if (smmu_domain->enforce_cache_coherency &&
2757+
!arm_smmu_master_canwbs(master)) {
2758+
spin_unlock_irqrestore(&smmu_domain->devices_lock,
2759+
flags);
2760+
kfree(master_domain);
2761+
return -EINVAL;
2762+
}
2763+
27342764
if (state->ats_enabled)
27352765
atomic_inc(&smmu_domain->nr_ats_masters);
27362766
list_add(&master_domain->devices_elm, &smmu_domain->devices);
@@ -3493,6 +3523,7 @@ static struct iommu_ops arm_smmu_ops = {
34933523
.owner = THIS_MODULE,
34943524
.default_domain_ops = &(const struct iommu_domain_ops) {
34953525
.attach_dev = arm_smmu_attach_dev,
3526+
.enforce_cache_coherency = arm_smmu_enforce_cache_coherency,
34963527
.set_dev_pasid = arm_smmu_s1_set_dev_pasid,
34973528
.map_pages = arm_smmu_map_pages,
34983529
.unmap_pages = arm_smmu_unmap_pages,

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

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -811,6 +811,7 @@ struct arm_smmu_domain {
811811
/* List of struct arm_smmu_master_domain */
812812
struct list_head devices;
813813
spinlock_t devices_lock;
814+
bool enforce_cache_coherency : 1;
814815

815816
struct mmu_notifier mmu_notifier;
816817
};
@@ -893,6 +894,12 @@ int arm_smmu_init_one_queue(struct arm_smmu_device *smmu,
893894
int arm_smmu_cmdq_init(struct arm_smmu_device *smmu,
894895
struct arm_smmu_cmdq *cmdq);
895896

897+
static inline bool arm_smmu_master_canwbs(struct arm_smmu_master *master)
898+
{
899+
return dev_iommu_fwspec_get(master->dev)->flags &
900+
IOMMU_FWSPEC_PCI_RC_CANWBS;
901+
}
902+
896903
#ifdef CONFIG_ARM_SMMU_V3_SVA
897904
bool arm_smmu_sva_supported(struct arm_smmu_device *smmu);
898905
bool arm_smmu_master_sva_supported(struct arm_smmu_master *master);

0 commit comments

Comments
 (0)