[PATCH v5 03/29] iommu: Apply the new iommufd_object_alloc_ucmd helper

Nicolin Chen
2025-05-18T03:32:41Z

Now the new ucmd-based object allocator eases the finalize/abort routine,
apply this to all existing allocators that aren't protected by any lock.

Upgrade the for-driver vIOMMU alloctor too, and pass down to all existing
viommu_alloc op accordingly.

Note that __iommufd_object_alloc_ucmd() builds in some static tests that
cover both static_asserts in the iommufd_viommu_alloc(). Thus drop them.

Suggested-by: Jason Gunthorpe <jgg@nvidia.com>
Signed-off-by: Nicolin Chen <nicolinc@nvidia.com>
---
drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h | 2 +-
include/linux/iommu.h | 6 +++---
include/linux/iommufd.h | 9 +++------
.../arm/arm-smmu-v3/arm-smmu-v3-iommufd.c | 4 ++--
drivers/iommu/iommufd/eventq.c | 14 ++++---------
drivers/iommu/iommufd/selftest.c | 4 ++--
drivers/iommu/iommufd/viommu.c | 20 ++++---------------
7 files changed, 19 insertions(+), 40 deletions(-)

diff --git a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h
index dd1ad56ce863..4f9aacad0091 100644
--- a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h
+++ b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h
@@ -1061,7 +1061,7 @@ struct arm_vsmmu {
void *arm_smmu_hw_info(struct device *dev, u32 *length, u32 *type);
struct iommufd_viommu *arm_vsmmu_alloc(struct device *dev,
struct iommu_domain *parent,
- struct iommufd_ctx *ictx,
+ struct iommufd_ucmd *ucmd,
unsigned int viommu_type);
int arm_smmu_attach_prepare_vmaster(struct arm_smmu_attach_state *state,
struct arm_smmu_nested_domain *nested_domain);
diff --git a/include/linux/iommu.h b/include/linux/iommu.h
index 3a8d35d41fda..0db39f922775 100644
--- a/include/linux/iommu.h
+++ b/include/linux/iommu.h
@@ -43,7 +43,7 @@ struct iommu_sva;
struct iommu_dma_cookie;
struct iommu_dma_msi_cookie;
struct iommu_fault_param;
-struct iommufd_ctx;
+struct iommufd_ucmd;
struct iommufd_viommu;
struct msi_desc;
struct msi_msg;
@@ -609,7 +609,7 @@ iommu_copy_struct_from_full_user_array(void *kdst, size_t kdst_entry_size,
* include/uapi/linux/iommufd.h
* It is required to call iommufd_viommu_alloc() helper for
* a bundled allocation of the core and the driver structures,
- * using the given @ictx pointer.
+ * using the given @ucmd pointer.
* @pgsize_bitmap: bitmap of all possible supported page sizes
* @owner: Driver module providing these ops
* @identity_domain: An always available, always attachable identity
@@ -662,7 +662,7 @@ struct iommu_ops {

struct iommufd_viommu *(*viommu_alloc)(
struct device *dev, struct iommu_domain *parent_domain,
- struct iommufd_ctx *ictx, unsigned int viommu_type);
+ struct iommufd_ucmd *ucmd, unsigned int viommu_type);

const struct iommu_domain_ops *default_domain_ops;
unsigned long pgsize_bitmap;
diff --git a/include/linux/iommufd.h b/include/linux/iommufd.h
index 47f38034f5e7..d74c97feb9b5 100644
--- a/include/linux/iommufd.h
+++ b/include/linux/iommufd.h
@@ -256,15 +256,12 @@ static inline int iommufd_viommu_report_event(struct iommufd_viommu *viommu,
* Helpers for IOMMU driver to allocate driver structures that will be freed by
* the iommufd core. The free op will be called prior to freeing the memory.
*/
-#define iommufd_viommu_alloc(ictx, drv_struct, member, viommu_ops) \
+#define iommufd_viommu_alloc(ucmd, drv_struct, member, viommu_ops) \
({ \
drv_struct *ret; \
\
- static_assert(__same_type(struct iommufd_viommu, \
- ((drv_struct *)NULL)->member)); \
- static_assert(offsetof(drv_struct, member.obj) == 0); \
- ret = (drv_struct *)_iommufd_object_alloc( \
- ictx, sizeof(drv_struct), IOMMUFD_OBJ_VIOMMU); \
+ ret = (drv_struct *)__iommufd_object_alloc_ucmd( \
+ ucmd, ret, IOMMUFD_OBJ_VIOMMU, member.obj); \
if (!IS_ERR(ret)) \
ret->member.ops = viommu_ops; \
ret; \
diff --git a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-iommufd.c b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-iommufd.c
index e4fd8d522af8..5d50bd8f4c2c 100644
--- a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-iommufd.c
+++ b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-iommufd.c
@@ -384,7 +384,7 @@ static const struct iommufd_viommu_ops arm_vsmmu_ops = {

struct iommufd_viommu *arm_vsmmu_alloc(struct device *dev,
struct iommu_domain *parent,
- struct iommufd_ctx *ictx,
+ struct iommufd_ucmd *ucmd,
unsigned int viommu_type)
{
struct arm_smmu_device *smmu =
@@ -422,7 +422,7 @@ struct iommufd_viommu *arm_vsmmu_alloc(struct device *dev,
!(smmu->features & ARM_SMMU_FEAT_S2FWB))
return ERR_PTR(-EOPNOTSUPP);

- vsmmu = iommufd_viommu_alloc(ictx, struct arm_vsmmu, core,
+ vsmmu = iommufd_viommu_alloc(ucmd, struct arm_vsmmu, core,
&arm_vsmmu_ops);
if (IS_ERR(vsmmu))
return ERR_CAST(vsmmu);
diff --git a/drivers/iommu/iommufd/eventq.c b/drivers/iommu/iommufd/eventq.c
index f39cf0797347..269b667152b7 100644
--- a/drivers/iommu/iommufd/eventq.c
+++ b/drivers/iommu/iommufd/eventq.c
@@ -473,8 +473,8 @@ int iommufd_fault_alloc(struct iommufd_ucmd *ucmd)
if (cmd->flags)
return -EOPNOTSUPP;

- fault = __iommufd_object_alloc(ucmd->ictx, fault, IOMMUFD_OBJ_FAULT,
- common.obj);
+ fault = __iommufd_object_alloc_ucmd(ucmd, fault, IOMMUFD_OBJ_FAULT,
+ common.obj);
if (IS_ERR(fault))
return PTR_ERR(fault);

@@ -483,10 +483,8 @@ int iommufd_fault_alloc(struct iommufd_ucmd *ucmd)

fdno = iommufd_eventq_init(&fault->common, "[iommufd-pgfault]",
ucmd->ictx, &iommufd_fault_fops);
- if (fdno < 0) {
- rc = fdno;
- goto out_abort;
- }
+ if (fdno < 0)
+ return fdno;

cmd->out_fault_id = fault->common.obj.id;
cmd->out_fault_fd = fdno;
@@ -494,7 +492,6 @@ int iommufd_fault_alloc(struct iommufd_ucmd *ucmd)
rc = iommufd_ucmd_respond(ucmd, sizeof(*cmd));
if (rc)
goto out_put_fdno;
- iommufd_object_finalize(ucmd->ictx, &fault->common.obj);

fd_install(fdno, fault->common.filep);

@@ -502,9 +499,6 @@ int iommufd_fault_alloc(struct iommufd_ucmd *ucmd)
out_put_fdno:
put_unused_fd(fdno);
fput(fault->common.filep);
-out_abort:
- iommufd_object_abort_and_destroy(ucmd->ictx, &fault->common.obj);
-
return rc;
}

diff --git a/drivers/iommu/iommufd/selftest.c b/drivers/iommu/iommufd/selftest.c
index 8cd98a72767d..4b021dc50758 100644
--- a/drivers/iommu/iommufd/selftest.c
+++ b/drivers/iommu/iommufd/selftest.c
@@ -735,7 +735,7 @@ static struct iommufd_viommu_ops mock_viommu_ops = {

static struct iommufd_viommu *mock_viommu_alloc(struct device *dev,
struct iommu_domain *domain,
- struct iommufd_ctx *ictx,
+ struct iommufd_ucmd *ucmd,
unsigned int viommu_type)
{
struct mock_iommu_device *mock_iommu =
@@ -745,7 +745,7 @@ static struct iommufd_viommu *mock_viommu_alloc(struct device *dev,
if (viommu_type != IOMMU_VIOMMU_TYPE_SELFTEST)
return ERR_PTR(-EOPNOTSUPP);

- mock_viommu = iommufd_viommu_alloc(ictx, struct mock_viommu, core,
+ mock_viommu = iommufd_viommu_alloc(ucmd, struct mock_viommu, core,
&mock_viommu_ops);
if (IS_ERR(mock_viommu))
return ERR_CAST(mock_viommu);
diff --git a/drivers/iommu/iommufd/viommu.c b/drivers/iommu/iommufd/viommu.c
index 01df2b985f02..6d874d6a4c00 100644
--- a/drivers/iommu/iommufd/viommu.c
+++ b/drivers/iommu/iommufd/viommu.c
@@ -47,8 +47,8 @@ int iommufd_viommu_alloc_ioctl(struct iommufd_ucmd *ucmd)
goto out_put_hwpt;
}

- viommu = ops->viommu_alloc(idev->dev, hwpt_paging->common.domain,
- ucmd->ictx, cmd->type);
+ viommu = ops->viommu_alloc(idev->dev, hwpt_paging->common.domain, ucmd,
+ cmd->type);
if (IS_ERR(viommu)) {
rc = PTR_ERR(viommu);
goto out_put_hwpt;
@@ -70,13 +70,7 @@ int iommufd_viommu_alloc_ioctl(struct iommufd_ucmd *ucmd)

cmd->out_viommu_id = viommu->obj.id;
rc = iommufd_ucmd_respond(ucmd, sizeof(*cmd));
- if (rc)
- goto out_abort;
- iommufd_object_finalize(ucmd->ictx, &viommu->obj);
- goto out_put_hwpt;

-out_abort:
- iommufd_object_abort_and_destroy(ucmd->ictx, &viommu->obj);
out_put_hwpt:
iommufd_put_object(ucmd->ictx, &hwpt_paging->common.obj);
out_put_idev:
@@ -124,7 +118,7 @@ int iommufd_vdevice_alloc_ioctl(struct iommufd_ucmd *ucmd)
goto out_put_idev;
}

- vdev = iommufd_object_alloc(ucmd->ictx, vdev, IOMMUFD_OBJ_VDEVICE);
+ vdev = iommufd_object_alloc_ucmd(ucmd, vdev, IOMMUFD_OBJ_VDEVICE);
if (IS_ERR(vdev)) {
rc = PTR_ERR(vdev);
goto out_put_idev;
@@ -139,18 +133,12 @@ int iommufd_vdevice_alloc_ioctl(struct iommufd_ucmd *ucmd)
curr = xa_cmpxchg(&viommu->vdevs, virt_id, NULL, vdev, GFP_KERNEL);
if (curr) {
rc = xa_err(curr) ?: -EEXIST;
- goto out_abort;
+ goto out_put_idev;
}

cmd->out_vdevice_id = vdev->obj.id;
rc = iommufd_ucmd_respond(ucmd, sizeof(*cmd));
- if (rc)
- goto out_abort;
- iommufd_object_finalize(ucmd->ictx, &vdev->obj);
- goto out_put_idev;

-out_abort:
- iommufd_object_abort_and_destroy(ucmd->ictx, &vdev->obj);
out_put_idev:
iommufd_put_object(ucmd->ictx, &idev->obj);
out_put_viommu:
--
2.43.0