Skip to content

Commit 13a7501

Browse files
nicolincjgunthorpe
authored andcommitted
iommufd: Allow pt_id to carry viommu_id for IOMMU_HWPT_ALLOC
Now a vIOMMU holds a shareable nesting parent HWPT. So, it can act like that nesting parent HWPT to allocate a nested HWPT. Support that in the IOMMU_HWPT_ALLOC ioctl handler, and update its kdoc. Also, add an iommufd_viommu_alloc_hwpt_nested helper to allocate a nested HWPT for a vIOMMU object. Since a vIOMMU object holds the parent hwpt's refcount already, increase the refcount of the vIOMMU only. Link: https://patch.msgid.link/r/a0f24f32bfada8b448d17587adcaedeeb50a67ed.1730836219.git.nicolinc@nvidia.com Reviewed-by: Kevin Tian <[email protected]> Signed-off-by: Nicolin Chen <[email protected]> Signed-off-by: Jason Gunthorpe <[email protected]>
1 parent 69d2689 commit 13a7501

File tree

3 files changed

+81
-7
lines changed

3 files changed

+81
-7
lines changed

drivers/iommu/iommufd/hw_pagetable.c

Lines changed: 72 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,10 @@ void iommufd_hwpt_nested_destroy(struct iommufd_object *obj)
5757
container_of(obj, struct iommufd_hwpt_nested, common.obj);
5858

5959
__iommufd_hwpt_destroy(&hwpt_nested->common);
60-
refcount_dec(&hwpt_nested->parent->common.obj.users);
60+
if (hwpt_nested->viommu)
61+
refcount_dec(&hwpt_nested->viommu->obj.users);
62+
else
63+
refcount_dec(&hwpt_nested->parent->common.obj.users);
6164
}
6265

6366
void iommufd_hwpt_nested_abort(struct iommufd_object *obj)
@@ -260,6 +263,58 @@ iommufd_hwpt_nested_alloc(struct iommufd_ctx *ictx,
260263
return ERR_PTR(rc);
261264
}
262265

266+
/**
267+
* iommufd_viommu_alloc_hwpt_nested() - Get a hwpt_nested for a vIOMMU
268+
* @viommu: vIOMMU ojbect to associate the hwpt_nested/domain with
269+
* @flags: Flags from userspace
270+
* @user_data: user_data pointer. Must be valid
271+
*
272+
* Allocate a new IOMMU_DOMAIN_NESTED for a vIOMMU and return it as a NESTED
273+
* hw_pagetable.
274+
*/
275+
static struct iommufd_hwpt_nested *
276+
iommufd_viommu_alloc_hwpt_nested(struct iommufd_viommu *viommu, u32 flags,
277+
const struct iommu_user_data *user_data)
278+
{
279+
struct iommufd_hwpt_nested *hwpt_nested;
280+
struct iommufd_hw_pagetable *hwpt;
281+
int rc;
282+
283+
if (!user_data->len)
284+
return ERR_PTR(-EOPNOTSUPP);
285+
if (!viommu->ops || !viommu->ops->alloc_domain_nested)
286+
return ERR_PTR(-EOPNOTSUPP);
287+
288+
hwpt_nested = __iommufd_object_alloc(
289+
viommu->ictx, hwpt_nested, IOMMUFD_OBJ_HWPT_NESTED, common.obj);
290+
if (IS_ERR(hwpt_nested))
291+
return ERR_CAST(hwpt_nested);
292+
hwpt = &hwpt_nested->common;
293+
294+
hwpt_nested->viommu = viommu;
295+
refcount_inc(&viommu->obj.users);
296+
hwpt_nested->parent = viommu->hwpt;
297+
298+
hwpt->domain =
299+
viommu->ops->alloc_domain_nested(viommu, flags, user_data);
300+
if (IS_ERR(hwpt->domain)) {
301+
rc = PTR_ERR(hwpt->domain);
302+
hwpt->domain = NULL;
303+
goto out_abort;
304+
}
305+
hwpt->domain->owner = viommu->iommu_dev->ops;
306+
307+
if (WARN_ON_ONCE(hwpt->domain->type != IOMMU_DOMAIN_NESTED)) {
308+
rc = -EINVAL;
309+
goto out_abort;
310+
}
311+
return hwpt_nested;
312+
313+
out_abort:
314+
iommufd_object_abort_and_destroy(viommu->ictx, &hwpt->obj);
315+
return ERR_PTR(rc);
316+
}
317+
263318
int iommufd_hwpt_alloc(struct iommufd_ucmd *ucmd)
264319
{
265320
struct iommu_hwpt_alloc *cmd = ucmd->cmd;
@@ -316,6 +371,22 @@ int iommufd_hwpt_alloc(struct iommufd_ucmd *ucmd)
316371
goto out_unlock;
317372
}
318373
hwpt = &hwpt_nested->common;
374+
} else if (pt_obj->type == IOMMUFD_OBJ_VIOMMU) {
375+
struct iommufd_hwpt_nested *hwpt_nested;
376+
struct iommufd_viommu *viommu;
377+
378+
viommu = container_of(pt_obj, struct iommufd_viommu, obj);
379+
if (viommu->iommu_dev != __iommu_get_iommu_dev(idev->dev)) {
380+
rc = -EINVAL;
381+
goto out_unlock;
382+
}
383+
hwpt_nested = iommufd_viommu_alloc_hwpt_nested(
384+
viommu, cmd->flags, &user_data);
385+
if (IS_ERR(hwpt_nested)) {
386+
rc = PTR_ERR(hwpt_nested);
387+
goto out_unlock;
388+
}
389+
hwpt = &hwpt_nested->common;
319390
} else {
320391
rc = -EINVAL;
321392
goto out_put_pt;

drivers/iommu/iommufd/iommufd_private.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -290,6 +290,7 @@ struct iommufd_hwpt_paging {
290290
struct iommufd_hwpt_nested {
291291
struct iommufd_hw_pagetable common;
292292
struct iommufd_hwpt_paging *parent;
293+
struct iommufd_viommu *viommu;
293294
};
294295

295296
static inline bool hwpt_is_paging(struct iommufd_hw_pagetable *hwpt)

include/uapi/linux/iommufd.h

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -435,7 +435,7 @@ enum iommu_hwpt_data_type {
435435
* @size: sizeof(struct iommu_hwpt_alloc)
436436
* @flags: Combination of enum iommufd_hwpt_alloc_flags
437437
* @dev_id: The device to allocate this HWPT for
438-
* @pt_id: The IOAS or HWPT to connect this HWPT to
438+
* @pt_id: The IOAS or HWPT or vIOMMU to connect this HWPT to
439439
* @out_hwpt_id: The ID of the new HWPT
440440
* @__reserved: Must be 0
441441
* @data_type: One of enum iommu_hwpt_data_type
@@ -454,11 +454,13 @@ enum iommu_hwpt_data_type {
454454
* IOMMU_HWPT_DATA_NONE. The HWPT can be allocated as a parent HWPT for a
455455
* nesting configuration by passing IOMMU_HWPT_ALLOC_NEST_PARENT via @flags.
456456
*
457-
* A user-managed nested HWPT will be created from a given parent HWPT via
458-
* @pt_id, in which the parent HWPT must be allocated previously via the
459-
* same ioctl from a given IOAS (@pt_id). In this case, the @data_type
460-
* must be set to a pre-defined type corresponding to an I/O page table
461-
* type supported by the underlying IOMMU hardware.
457+
* A user-managed nested HWPT will be created from a given vIOMMU (wrapping a
458+
* parent HWPT) or a parent HWPT via @pt_id, in which the parent HWPT must be
459+
* allocated previously via the same ioctl from a given IOAS (@pt_id). In this
460+
* case, the @data_type must be set to a pre-defined type corresponding to an
461+
* I/O page table type supported by the underlying IOMMU hardware. The device
462+
* via @dev_id and the vIOMMU via @pt_id must be associated to the same IOMMU
463+
* instance.
462464
*
463465
* If the @data_type is set to IOMMU_HWPT_DATA_NONE, @data_len and
464466
* @data_uptr should be zero. Otherwise, both @data_len and @data_uptr

0 commit comments

Comments
 (0)