Skip to content

Commit 6f73401

Browse files
LuBaolujoergroedel
authored andcommitted
iommu: Allow attaching static domains in iommu_attach_device_pasid()
The idxd driver attaches the default domain to a PASID of the device to perform kernel DMA using that PASID. The domain is attached to the device's PASID through iommu_attach_device_pasid(), which checks if the domain->owner matches the iommu_ops retrieved from the device. If they do not match, it returns a failure. if (ops != domain->owner || pasid == IOMMU_NO_PASID) return -EINVAL; The static identity domain implemented by the intel iommu driver doesn't specify the domain owner. Therefore, kernel DMA with PASID doesn't work for the idxd driver if the device translation mode is set to passthrough. Generally the owner field of static domains are not set because they are already part of iommu ops. Add a helper domain_iommu_ops_compatible() that checks if a domain is compatible with the device's iommu ops. This helper explicitly allows the static blocked and identity domains associated with the device's iommu_ops to be considered compatible. Fixes: 2031c46 ("iommu/vt-d: Add support for static identity domain") Closes: https://bugzilla.kernel.org/show_bug.cgi?id=220031 Cc: stable@vger.kernel.org Suggested-by: Jason Gunthorpe <jgg@nvidia.com> Link: https://lore.kernel.org/linux-iommu/20250422191554.GC1213339@ziepe.ca/ Signed-off-by: Lu Baolu <baolu.lu@linux.intel.com> Reviewed-by: Dave Jiang <dave.jiang@intel.com> Reviewed-by: Robin Murphy <robin.murphy@arm.com> Reviewed-by: Jason Gunthorpe <jgg@nvidia.com> Reviewed-by: Vasant Hegde <vasant.hegde@amd.com> Reviewed-by: Kevin Tian <kevin.tian@intel.com> Link: https://lore.kernel.org/r/20250424034123.2311362-1-baolu.lu@linux.intel.com Signed-off-by: Joerg Roedel <jroedel@suse.de>
1 parent fa26198 commit 6f73401

File tree

1 file changed

+18
-3
lines changed

1 file changed

+18
-3
lines changed

drivers/iommu/iommu.c

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2206,6 +2206,19 @@ static void *iommu_make_pasid_array_entry(struct iommu_domain *domain,
22062206
return xa_tag_pointer(domain, IOMMU_PASID_ARRAY_DOMAIN);
22072207
}
22082208

2209+
static bool domain_iommu_ops_compatible(const struct iommu_ops *ops,
2210+
struct iommu_domain *domain)
2211+
{
2212+
if (domain->owner == ops)
2213+
return true;
2214+
2215+
/* For static domains, owner isn't set. */
2216+
if (domain == ops->blocked_domain || domain == ops->identity_domain)
2217+
return true;
2218+
2219+
return false;
2220+
}
2221+
22092222
static int __iommu_attach_group(struct iommu_domain *domain,
22102223
struct iommu_group *group)
22112224
{
@@ -2216,7 +2229,8 @@ static int __iommu_attach_group(struct iommu_domain *domain,
22162229
return -EBUSY;
22172230

22182231
dev = iommu_group_first_dev(group);
2219-
if (!dev_has_iommu(dev) || dev_iommu_ops(dev) != domain->owner)
2232+
if (!dev_has_iommu(dev) ||
2233+
!domain_iommu_ops_compatible(dev_iommu_ops(dev), domain))
22202234
return -EINVAL;
22212235

22222236
return __iommu_group_set_domain(group, domain);
@@ -3405,7 +3419,8 @@ int iommu_attach_device_pasid(struct iommu_domain *domain,
34053419
!ops->blocked_domain->ops->set_dev_pasid)
34063420
return -EOPNOTSUPP;
34073421

3408-
if (ops != domain->owner || pasid == IOMMU_NO_PASID)
3422+
if (!domain_iommu_ops_compatible(ops, domain) ||
3423+
pasid == IOMMU_NO_PASID)
34093424
return -EINVAL;
34103425

34113426
mutex_lock(&group->mutex);
@@ -3481,7 +3496,7 @@ int iommu_replace_device_pasid(struct iommu_domain *domain,
34813496
if (!domain->ops->set_dev_pasid)
34823497
return -EOPNOTSUPP;
34833498

3484-
if (dev_iommu_ops(dev) != domain->owner ||
3499+
if (!domain_iommu_ops_compatible(dev_iommu_ops(dev), domain) ||
34853500
pasid == IOMMU_NO_PASID || !handle)
34863501
return -EINVAL;
34873502

0 commit comments

Comments
 (0)