Skip to content

Commit 7074d7b

Browse files
committed
iommufd: Add IOMMU_HWPT_ALLOC
This allows userspace to manually create HWPTs on IOAS's and then use those HWPTs as inputs to iommufd_device_attach/replace(). Following series will extend this to allow creating iommu_domains with driver specific parameters. Link: https://lore.kernel.org/r/17-v8-6659224517ea+532-iommufd_alloc_jgg@nvidia.com Reviewed-by: Lu Baolu <baolu.lu@linux.intel.com> Reviewed-by: Kevin Tian <kevin.tian@intel.com> Tested-by: Nicolin Chen <nicolinc@nvidia.com> Signed-off-by: Jason Gunthorpe <jgg@nvidia.com>
1 parent fa1ffdb commit 7074d7b

File tree

4 files changed

+84
-0
lines changed

4 files changed

+84
-0
lines changed

drivers/iommu/iommufd/hw_pagetable.c

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
* Copyright (c) 2021-2022, NVIDIA CORPORATION & AFFILIATES
44
*/
55
#include <linux/iommu.h>
6+
#include <uapi/linux/iommufd.h>
67

78
#include "iommufd_private.h"
89

@@ -131,3 +132,48 @@ iommufd_hw_pagetable_alloc(struct iommufd_ctx *ictx, struct iommufd_ioas *ioas,
131132
iommufd_object_abort_and_destroy(ictx, &hwpt->obj);
132133
return ERR_PTR(rc);
133134
}
135+
136+
int iommufd_hwpt_alloc(struct iommufd_ucmd *ucmd)
137+
{
138+
struct iommu_hwpt_alloc *cmd = ucmd->cmd;
139+
struct iommufd_hw_pagetable *hwpt;
140+
struct iommufd_device *idev;
141+
struct iommufd_ioas *ioas;
142+
int rc;
143+
144+
if (cmd->flags || cmd->__reserved)
145+
return -EOPNOTSUPP;
146+
147+
idev = iommufd_get_device(ucmd, cmd->dev_id);
148+
if (IS_ERR(idev))
149+
return PTR_ERR(idev);
150+
151+
ioas = iommufd_get_ioas(ucmd->ictx, cmd->pt_id);
152+
if (IS_ERR(ioas)) {
153+
rc = PTR_ERR(ioas);
154+
goto out_put_idev;
155+
}
156+
157+
mutex_lock(&ioas->mutex);
158+
hwpt = iommufd_hw_pagetable_alloc(ucmd->ictx, ioas, idev, false);
159+
if (IS_ERR(hwpt)) {
160+
rc = PTR_ERR(hwpt);
161+
goto out_unlock;
162+
}
163+
164+
cmd->out_hwpt_id = hwpt->obj.id;
165+
rc = iommufd_ucmd_respond(ucmd, sizeof(*cmd));
166+
if (rc)
167+
goto out_hwpt;
168+
iommufd_object_finalize(ucmd->ictx, &hwpt->obj);
169+
goto out_unlock;
170+
171+
out_hwpt:
172+
iommufd_object_abort_and_destroy(ucmd->ictx, &hwpt->obj);
173+
out_unlock:
174+
mutex_unlock(&ioas->mutex);
175+
iommufd_put_object(&ioas->obj);
176+
out_put_idev:
177+
iommufd_put_object(&idev->obj);
178+
return rc;
179+
}

drivers/iommu/iommufd/iommufd_private.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -262,6 +262,7 @@ struct iommufd_hw_pagetable *
262262
iommufd_hw_pagetable_detach(struct iommufd_device *idev);
263263
void iommufd_hw_pagetable_destroy(struct iommufd_object *obj);
264264
void iommufd_hw_pagetable_abort(struct iommufd_object *obj);
265+
int iommufd_hwpt_alloc(struct iommufd_ucmd *ucmd);
265266

266267
static inline void iommufd_hw_pagetable_put(struct iommufd_ctx *ictx,
267268
struct iommufd_hw_pagetable *hwpt)
@@ -298,6 +299,14 @@ struct iommufd_device {
298299
bool enforce_cache_coherency;
299300
};
300301

302+
static inline struct iommufd_device *
303+
iommufd_get_device(struct iommufd_ucmd *ucmd, u32 id)
304+
{
305+
return container_of(iommufd_get_object(ucmd->ictx, id,
306+
IOMMUFD_OBJ_DEVICE),
307+
struct iommufd_device, obj);
308+
}
309+
301310
void iommufd_device_destroy(struct iommufd_object *obj);
302311

303312
struct iommufd_access {

drivers/iommu/iommufd/main.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -265,6 +265,7 @@ static int iommufd_option(struct iommufd_ucmd *ucmd)
265265

266266
union ucmd_buffer {
267267
struct iommu_destroy destroy;
268+
struct iommu_hwpt_alloc hwpt;
268269
struct iommu_ioas_alloc alloc;
269270
struct iommu_ioas_allow_iovas allow_iovas;
270271
struct iommu_ioas_copy ioas_copy;
@@ -296,6 +297,8 @@ struct iommufd_ioctl_op {
296297
}
297298
static const struct iommufd_ioctl_op iommufd_ioctl_ops[] = {
298299
IOCTL_OP(IOMMU_DESTROY, iommufd_destroy, struct iommu_destroy, id),
300+
IOCTL_OP(IOMMU_HWPT_ALLOC, iommufd_hwpt_alloc, struct iommu_hwpt_alloc,
301+
__reserved),
299302
IOCTL_OP(IOMMU_IOAS_ALLOC, iommufd_ioas_alloc_ioctl,
300303
struct iommu_ioas_alloc, out_ioas_id),
301304
IOCTL_OP(IOMMU_IOAS_ALLOW_IOVAS, iommufd_ioas_allow_iovas,

include/uapi/linux/iommufd.h

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ enum {
4545
IOMMUFD_CMD_IOAS_UNMAP,
4646
IOMMUFD_CMD_OPTION,
4747
IOMMUFD_CMD_VFIO_IOAS,
48+
IOMMUFD_CMD_HWPT_ALLOC,
4849
};
4950

5051
/**
@@ -344,4 +345,29 @@ struct iommu_vfio_ioas {
344345
__u16 __reserved;
345346
};
346347
#define IOMMU_VFIO_IOAS _IO(IOMMUFD_TYPE, IOMMUFD_CMD_VFIO_IOAS)
348+
349+
/**
350+
* struct iommu_hwpt_alloc - ioctl(IOMMU_HWPT_ALLOC)
351+
* @size: sizeof(struct iommu_hwpt_alloc)
352+
* @flags: Must be 0
353+
* @dev_id: The device to allocate this HWPT for
354+
* @pt_id: The IOAS to connect this HWPT to
355+
* @out_hwpt_id: The ID of the new HWPT
356+
* @__reserved: Must be 0
357+
*
358+
* Explicitly allocate a hardware page table object. This is the same object
359+
* type that is returned by iommufd_device_attach() and represents the
360+
* underlying iommu driver's iommu_domain kernel object.
361+
*
362+
* A HWPT will be created with the IOVA mappings from the given IOAS.
363+
*/
364+
struct iommu_hwpt_alloc {
365+
__u32 size;
366+
__u32 flags;
367+
__u32 dev_id;
368+
__u32 pt_id;
369+
__u32 out_hwpt_id;
370+
__u32 __reserved;
371+
};
372+
#define IOMMU_HWPT_ALLOC _IO(IOMMUFD_TYPE, IOMMUFD_CMD_HWPT_ALLOC)
347373
#endif

0 commit comments

Comments
 (0)