Skip to content

Commit 54ce69e

Browse files
nicolincjgunthorpe
authored andcommitted
iommufd: Allow hwpt_id to carry viommu_id for IOMMU_HWPT_INVALIDATE
With a vIOMMU object, use space can flush any IOMMU related cache that can be directed via a vIOMMU object. It is similar to the IOMMU_HWPT_INVALIDATE uAPI, but can cover a wider range than IOTLB, e.g. device/desciprtor cache. Allow hwpt_id of the iommu_hwpt_invalidate structure to carry a viommu_id, and reuse the IOMMU_HWPT_INVALIDATE uAPI for vIOMMU invalidations. Drivers can define different structures for vIOMMU invalidations v.s. HWPT ones. Since both the HWPT-based and vIOMMU-based invalidation pathways check own cache invalidation op, remove the WARN_ON_ONCE in the allocator. Update the uAPI, kdoc, and selftest case accordingly. Link: https://patch.msgid.link/r/b411e2245e303b8a964f39f49453a5dff280968f.1730836308.git.nicolinc@nvidia.com Reviewed-by: Jason Gunthorpe <[email protected]> Reviewed-by: Kevin Tian <[email protected]> Signed-off-by: Nicolin Chen <[email protected]> Signed-off-by: Jason Gunthorpe <[email protected]>
1 parent 67db79d commit 54ce69e

File tree

3 files changed

+39
-14
lines changed

3 files changed

+39
-14
lines changed

drivers/iommu/iommufd/hw_pagetable.c

Lines changed: 31 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -251,8 +251,7 @@ iommufd_hwpt_nested_alloc(struct iommufd_ctx *ictx,
251251
}
252252
hwpt->domain->owner = ops;
253253

254-
if (WARN_ON_ONCE(hwpt->domain->type != IOMMU_DOMAIN_NESTED ||
255-
!hwpt->domain->ops->cache_invalidate_user)) {
254+
if (WARN_ON_ONCE(hwpt->domain->type != IOMMU_DOMAIN_NESTED)) {
256255
rc = -EINVAL;
257256
goto out_abort;
258257
}
@@ -483,7 +482,7 @@ int iommufd_hwpt_invalidate(struct iommufd_ucmd *ucmd)
483482
.entry_len = cmd->entry_len,
484483
.entry_num = cmd->entry_num,
485484
};
486-
struct iommufd_hw_pagetable *hwpt;
485+
struct iommufd_object *pt_obj;
487486
u32 done_num = 0;
488487
int rc;
489488

@@ -497,17 +496,40 @@ int iommufd_hwpt_invalidate(struct iommufd_ucmd *ucmd)
497496
goto out;
498497
}
499498

500-
hwpt = iommufd_get_hwpt_nested(ucmd, cmd->hwpt_id);
501-
if (IS_ERR(hwpt)) {
502-
rc = PTR_ERR(hwpt);
499+
pt_obj = iommufd_get_object(ucmd->ictx, cmd->hwpt_id, IOMMUFD_OBJ_ANY);
500+
if (IS_ERR(pt_obj)) {
501+
rc = PTR_ERR(pt_obj);
503502
goto out;
504503
}
504+
if (pt_obj->type == IOMMUFD_OBJ_HWPT_NESTED) {
505+
struct iommufd_hw_pagetable *hwpt =
506+
container_of(pt_obj, struct iommufd_hw_pagetable, obj);
507+
508+
if (!hwpt->domain->ops ||
509+
!hwpt->domain->ops->cache_invalidate_user) {
510+
rc = -EOPNOTSUPP;
511+
goto out_put_pt;
512+
}
513+
rc = hwpt->domain->ops->cache_invalidate_user(hwpt->domain,
514+
&data_array);
515+
} else if (pt_obj->type == IOMMUFD_OBJ_VIOMMU) {
516+
struct iommufd_viommu *viommu =
517+
container_of(pt_obj, struct iommufd_viommu, obj);
518+
519+
if (!viommu->ops || !viommu->ops->cache_invalidate) {
520+
rc = -EOPNOTSUPP;
521+
goto out_put_pt;
522+
}
523+
rc = viommu->ops->cache_invalidate(viommu, &data_array);
524+
} else {
525+
rc = -EINVAL;
526+
goto out_put_pt;
527+
}
505528

506-
rc = hwpt->domain->ops->cache_invalidate_user(hwpt->domain,
507-
&data_array);
508529
done_num = data_array.entry_num;
509530

510-
iommufd_put_object(ucmd->ictx, &hwpt->obj);
531+
out_put_pt:
532+
iommufd_put_object(ucmd->ictx, pt_obj);
511533
out:
512534
cmd->entry_num = done_num;
513535
if (iommufd_ucmd_respond(ucmd, sizeof(*cmd)))

include/uapi/linux/iommufd.h

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -700,7 +700,7 @@ struct iommu_hwpt_vtd_s1_invalidate {
700700
/**
701701
* struct iommu_hwpt_invalidate - ioctl(IOMMU_HWPT_INVALIDATE)
702702
* @size: sizeof(struct iommu_hwpt_invalidate)
703-
* @hwpt_id: ID of a nested HWPT for cache invalidation
703+
* @hwpt_id: ID of a nested HWPT or a vIOMMU, for cache invalidation
704704
* @data_uptr: User pointer to an array of driver-specific cache invalidation
705705
* data.
706706
* @data_type: One of enum iommu_hwpt_invalidate_data_type, defining the data
@@ -711,8 +711,11 @@ struct iommu_hwpt_vtd_s1_invalidate {
711711
* Output the number of requests successfully handled by kernel.
712712
* @__reserved: Must be 0.
713713
*
714-
* Invalidate the iommu cache for user-managed page table. Modifications on a
715-
* user-managed page table should be followed by this operation to sync cache.
714+
* Invalidate iommu cache for user-managed page table or vIOMMU. Modifications
715+
* on a user-managed page table should be followed by this operation, if a HWPT
716+
* is passed in via @hwpt_id. Other caches, such as device cache or descriptor
717+
* cache can be flushed if a vIOMMU is passed in via the @hwpt_id field.
718+
*
716719
* Each ioctl can support one or more cache invalidation requests in the array
717720
* that has a total size of @entry_len * @entry_num.
718721
*

tools/testing/selftests/iommu/iommufd.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -367,9 +367,9 @@ TEST_F(iommufd_ioas, alloc_hwpt_nested)
367367
EXPECT_ERRNO(EBUSY,
368368
_test_ioctl_destroy(self->fd, parent_hwpt_id));
369369

370-
/* hwpt_invalidate only supports a user-managed hwpt (nested) */
370+
/* hwpt_invalidate does not support a parent hwpt */
371371
num_inv = 1;
372-
test_err_hwpt_invalidate(ENOENT, parent_hwpt_id, inv_reqs,
372+
test_err_hwpt_invalidate(EINVAL, parent_hwpt_id, inv_reqs,
373373
IOMMU_HWPT_INVALIDATE_DATA_SELFTEST,
374374
sizeof(*inv_reqs), &num_inv);
375375
assert(!num_inv);

0 commit comments

Comments
 (0)