On 2022-01-06 02:20, Lu Baolu wrote:
Expose an interface to replace the domain of an iommu group for frameworks
like vfio which claims the ownership of the whole iommu group.
But if the underlying point is the new expectation that
iommu_{attach,detach}_device() operate on the device's whole group where
relevant, why should we invent some special mechanism for VFIO to be
needlessly inconsistent?
I said before that it's trivial for VFIO to resolve a suitable device if
it needs to; by now I've actually written the patch ;)
https://gitlab.arm.com/linux-arm/linux-rm/-/commit/9f37d8c17c9b606abc96e1f1001c0b97c8b93ed5
Robin.
Signed-off-by: Lu Baolu <baolu.lu@xxxxxxxxxxxxxxx>
---
include/linux/iommu.h | 10 ++++++++++
drivers/iommu/iommu.c | 37 +++++++++++++++++++++++++++++++++++++
2 files changed, 47 insertions(+)
diff --git a/include/linux/iommu.h b/include/linux/iommu.h
index 408a6d2b3034..66ebce3d1e11 100644
--- a/include/linux/iommu.h
+++ b/include/linux/iommu.h
@@ -677,6 +677,9 @@ void iommu_device_unuse_dma_api(struct device *dev);
int iommu_group_set_dma_owner(struct iommu_group *group, void *owner);
void iommu_group_release_dma_owner(struct iommu_group *group);
bool iommu_group_dma_owner_claimed(struct iommu_group *group);
+int iommu_group_replace_domain(struct iommu_group *group,
+ struct iommu_domain *old,
+ struct iommu_domain *new);
#else /* CONFIG_IOMMU_API */
@@ -1090,6 +1093,13 @@ static inline bool iommu_group_dma_owner_claimed(struct iommu_group *group)
{
return false;
}
+
+static inline int
+iommu_group_replace_domain(struct iommu_group *group, struct iommu_domain *old,
+ struct iommu_domain *new)
+{
+ return -ENODEV;
+}
#endif /* CONFIG_IOMMU_API */
/**
diff --git a/drivers/iommu/iommu.c b/drivers/iommu/iommu.c
index 72a95dea688e..ab8ab95969f5 100644
--- a/drivers/iommu/iommu.c
+++ b/drivers/iommu/iommu.c
@@ -3431,3 +3431,40 @@ bool iommu_group_dma_owner_claimed(struct iommu_group *group)
return user;
}
EXPORT_SYMBOL_GPL(iommu_group_dma_owner_claimed);
+
+/**
+ * iommu_group_replace_domain() - Replace group's domain
+ * @group: The group.
+ * @old: The previous attached domain. NULL for none.
+ * @new: The new domain about to be attached.
+ *
+ * This is to support backward compatibility for vfio which manages the dma
+ * ownership in iommu_group level.
+ */
+int iommu_group_replace_domain(struct iommu_group *group,
+ struct iommu_domain *old,
+ struct iommu_domain *new)
+{
+ int ret = 0;
+
+ mutex_lock(&group->mutex);
+ if (!group->owner || group->domain != old) {
+ ret = -EPERM;
+ goto unlock_out;
+ }
+
+ if (old)
+ __iommu_detach_group(old, group);
+
+ if (new) {
+ ret = __iommu_attach_group(new, group);
+ if (ret && old)
+ __iommu_attach_group(old, group);
+ }
+
+unlock_out:
+ mutex_unlock(&group->mutex);
+
+ return ret;
+}
+EXPORT_SYMBOL_GPL(iommu_group_replace_domain);