iommu: Add domain_alloc_identity()
authorJason Gunthorpe <jgg@nvidia.com>
Tue, 8 Apr 2025 16:35:48 +0000 (13:35 -0300)
committerJoerg Roedel <jroedel@suse.de>
Mon, 28 Apr 2025 11:14:57 +0000 (13:14 +0200)
virtio-iommu has a mode where the IDENTITY domain is actually a paging
domain with an identity mapping covering some of the system address
space manually created.

To support this add a new domain_alloc_identity() op that accepts
the struct device so that virtio can allocate and fully finalize a
paging domain to return.

Signed-off-by: Jason Gunthorpe <jgg@nvidia.com>
Reviewed-by: Kevin Tian <kevin.tian@intel.com>
Link: https://lore.kernel.org/r/2-v4-ff5fb6b03bd1+288-iommu_virtio_domains_jgg@nvidia.com
Signed-off-by: Joerg Roedel <jroedel@suse.de>
drivers/iommu/iommu.c
include/linux/iommu.h

index df283bd..2b7c048 100644 (file)
@@ -1631,15 +1631,19 @@ static struct iommu_domain *__iommu_alloc_identity_domain(struct device *dev)
        if (ops->identity_domain)
                return ops->identity_domain;
 
-       /* Older drivers create the identity domain via ops->domain_alloc() */
-       if (!ops->domain_alloc)
+       if (ops->domain_alloc_identity) {
+               domain = ops->domain_alloc_identity(dev);
+               if (IS_ERR(domain))
+                       return domain;
+       } else if (ops->domain_alloc) {
+               domain = ops->domain_alloc(IOMMU_DOMAIN_IDENTITY);
+               if (!domain)
+                       return ERR_PTR(-ENOMEM);
+               if (IS_ERR(domain))
+                       return domain;
+       } else {
                return ERR_PTR(-EOPNOTSUPP);
-
-       domain = ops->domain_alloc(IOMMU_DOMAIN_IDENTITY);
-       if (IS_ERR(domain))
-               return domain;
-       if (!domain)
-               return ERR_PTR(-ENOMEM);
+       }
 
        iommu_domain_init(domain, IOMMU_DOMAIN_IDENTITY, ops);
        return domain;
index 8d9119b..7b636b9 100644 (file)
@@ -567,6 +567,9 @@ iommu_copy_struct_from_full_user_array(void *kdst, size_t kdst_entry_size,
  * @domain_alloc: allocate and return an iommu domain if success. Otherwise
  *                NULL is returned. The domain is not fully initialized until
  *                the caller iommu_domain_alloc() returns.
+ * @domain_alloc_identity: allocate an IDENTITY domain. Drivers should prefer to
+ *                         use identity_domain instead. This should only be used
+ *                         if dynamic logic is necessary.
  * @domain_alloc_paging_flags: Allocate an iommu domain corresponding to the
  *                     input parameters as defined in
  *                     include/uapi/linux/iommufd.h. The @user_data can be
@@ -625,6 +628,7 @@ struct iommu_ops {
 
        /* Domain allocation and freeing by the iommu driver */
        struct iommu_domain *(*domain_alloc)(unsigned iommu_domain_type);
+       struct iommu_domain *(*domain_alloc_identity)(struct device *dev);
        struct iommu_domain *(*domain_alloc_paging_flags)(
                struct device *dev, u32 flags,
                const struct iommu_user_data *user_data);