Skip to content

Commit 9fdf791

Browse files
committed
Merge branch 'vfio_mdev_ops' into iommufd.git for-next
Yi Liu says =================== The .bind_iommufd op of vfio emulated devices are either empty or does nothing. This is different with the vfio physical devices, to add vfio device cdev, need to make them act the same. This series first makes the .bind_iommufd op of vfio emulated devices to create iommufd_access, this introduces a new iommufd API. Then let the driver that does not provide .bind_iommufd op to use the vfio emulated iommufd op set. This makes all vfio device drivers have consistent iommufd operations, which is good for adding new device uAPIs in the device cdev =================== * branch 'vfio_mdev_ops': vfio: Check the presence for iommufd callbacks in __vfio_register_dev() vfio/mdev: Uses the vfio emulated iommufd ops set in the mdev sample drivers vfio-iommufd: Make vfio_iommufd_emulated_bind() return iommufd_access ID vfio-iommufd: No need to record iommufd_ctx in vfio_device iommufd: Create access in vfio_iommufd_emulated_bind() iommu/iommufd: Pass iommufd_ctx pointer in iommufd_get_ioas() Signed-off-by: Jason Gunthorpe <jgg@nvidia.com>
2 parents fd8c1a4 + 7d12578 commit 9fdf791

12 files changed

Lines changed: 84 additions & 61 deletions

File tree

drivers/iommu/iommufd/device.c

Lines changed: 33 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -395,17 +395,20 @@ void iommufd_access_destroy_object(struct iommufd_object *obj)
395395
struct iommufd_access *access =
396396
container_of(obj, struct iommufd_access, obj);
397397

398-
iopt_remove_access(&access->ioas->iopt, access);
398+
if (access->ioas) {
399+
iopt_remove_access(&access->ioas->iopt, access);
400+
refcount_dec(&access->ioas->obj.users);
401+
access->ioas = NULL;
402+
}
399403
iommufd_ctx_put(access->ictx);
400-
refcount_dec(&access->ioas->obj.users);
401404
}
402405

403406
/**
404407
* iommufd_access_create - Create an iommufd_access
405408
* @ictx: iommufd file descriptor
406-
* @ioas_id: ID for a IOMMUFD_OBJ_IOAS
407409
* @ops: Driver's ops to associate with the access
408410
* @data: Opaque data to pass into ops functions
411+
* @id: Output ID number to return to userspace for this access
409412
*
410413
* An iommufd_access allows a driver to read/write to the IOAS without using
411414
* DMA. The underlying CPU memory can be accessed using the
@@ -414,12 +417,10 @@ void iommufd_access_destroy_object(struct iommufd_object *obj)
414417
* The provided ops are required to use iommufd_access_pin_pages().
415418
*/
416419
struct iommufd_access *
417-
iommufd_access_create(struct iommufd_ctx *ictx, u32 ioas_id,
418-
const struct iommufd_access_ops *ops, void *data)
420+
iommufd_access_create(struct iommufd_ctx *ictx,
421+
const struct iommufd_access_ops *ops, void *data, u32 *id)
419422
{
420423
struct iommufd_access *access;
421-
struct iommufd_object *obj;
422-
int rc;
423424

424425
/*
425426
* There is no uAPI for the access object, but to keep things symmetric
@@ -432,33 +433,18 @@ iommufd_access_create(struct iommufd_ctx *ictx, u32 ioas_id,
432433
access->data = data;
433434
access->ops = ops;
434435

435-
obj = iommufd_get_object(ictx, ioas_id, IOMMUFD_OBJ_IOAS);
436-
if (IS_ERR(obj)) {
437-
rc = PTR_ERR(obj);
438-
goto out_abort;
439-
}
440-
access->ioas = container_of(obj, struct iommufd_ioas, obj);
441-
iommufd_ref_to_users(obj);
442-
443436
if (ops->needs_pin_pages)
444437
access->iova_alignment = PAGE_SIZE;
445438
else
446439
access->iova_alignment = 1;
447-
rc = iopt_add_access(&access->ioas->iopt, access);
448-
if (rc)
449-
goto out_put_ioas;
450440

451441
/* The calling driver is a user until iommufd_access_destroy() */
452442
refcount_inc(&access->obj.users);
453443
access->ictx = ictx;
454444
iommufd_ctx_get(ictx);
455445
iommufd_object_finalize(ictx, &access->obj);
446+
*id = access->obj.id;
456447
return access;
457-
out_put_ioas:
458-
refcount_dec(&access->ioas->obj.users);
459-
out_abort:
460-
iommufd_object_abort(ictx, &access->obj);
461-
return ERR_PTR(rc);
462448
}
463449
EXPORT_SYMBOL_NS_GPL(iommufd_access_create, IOMMUFD);
464450

@@ -477,6 +463,30 @@ void iommufd_access_destroy(struct iommufd_access *access)
477463
}
478464
EXPORT_SYMBOL_NS_GPL(iommufd_access_destroy, IOMMUFD);
479465

466+
int iommufd_access_attach(struct iommufd_access *access, u32 ioas_id)
467+
{
468+
struct iommufd_ioas *new_ioas;
469+
int rc = 0;
470+
471+
if (access->ioas)
472+
return -EINVAL;
473+
474+
new_ioas = iommufd_get_ioas(access->ictx, ioas_id);
475+
if (IS_ERR(new_ioas))
476+
return PTR_ERR(new_ioas);
477+
478+
rc = iopt_add_access(&new_ioas->iopt, access);
479+
if (rc) {
480+
iommufd_put_object(&new_ioas->obj);
481+
return rc;
482+
}
483+
iommufd_ref_to_users(&new_ioas->obj);
484+
485+
access->ioas = new_ioas;
486+
return 0;
487+
}
488+
EXPORT_SYMBOL_NS_GPL(iommufd_access_attach, IOMMUFD);
489+
480490
/**
481491
* iommufd_access_notify_unmap - Notify users of an iopt to stop using it
482492
* @iopt: iopt to work on

drivers/iommu/iommufd/ioas.c

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@ int iommufd_ioas_iova_ranges(struct iommufd_ucmd *ucmd)
7171
if (cmd->__reserved)
7272
return -EOPNOTSUPP;
7373

74-
ioas = iommufd_get_ioas(ucmd, cmd->ioas_id);
74+
ioas = iommufd_get_ioas(ucmd->ictx, cmd->ioas_id);
7575
if (IS_ERR(ioas))
7676
return PTR_ERR(ioas);
7777

@@ -151,7 +151,7 @@ int iommufd_ioas_allow_iovas(struct iommufd_ucmd *ucmd)
151151
if (cmd->__reserved)
152152
return -EOPNOTSUPP;
153153

154-
ioas = iommufd_get_ioas(ucmd, cmd->ioas_id);
154+
ioas = iommufd_get_ioas(ucmd->ictx, cmd->ioas_id);
155155
if (IS_ERR(ioas))
156156
return PTR_ERR(ioas);
157157
iopt = &ioas->iopt;
@@ -213,7 +213,7 @@ int iommufd_ioas_map(struct iommufd_ucmd *ucmd)
213213
if (cmd->iova >= ULONG_MAX || cmd->length >= ULONG_MAX)
214214
return -EOVERFLOW;
215215

216-
ioas = iommufd_get_ioas(ucmd, cmd->ioas_id);
216+
ioas = iommufd_get_ioas(ucmd->ictx, cmd->ioas_id);
217217
if (IS_ERR(ioas))
218218
return PTR_ERR(ioas);
219219

@@ -253,7 +253,7 @@ int iommufd_ioas_copy(struct iommufd_ucmd *ucmd)
253253
cmd->dst_iova >= ULONG_MAX)
254254
return -EOVERFLOW;
255255

256-
src_ioas = iommufd_get_ioas(ucmd, cmd->src_ioas_id);
256+
src_ioas = iommufd_get_ioas(ucmd->ictx, cmd->src_ioas_id);
257257
if (IS_ERR(src_ioas))
258258
return PTR_ERR(src_ioas);
259259
rc = iopt_get_pages(&src_ioas->iopt, cmd->src_iova, cmd->length,
@@ -262,7 +262,7 @@ int iommufd_ioas_copy(struct iommufd_ucmd *ucmd)
262262
if (rc)
263263
return rc;
264264

265-
dst_ioas = iommufd_get_ioas(ucmd, cmd->dst_ioas_id);
265+
dst_ioas = iommufd_get_ioas(ucmd->ictx, cmd->dst_ioas_id);
266266
if (IS_ERR(dst_ioas)) {
267267
rc = PTR_ERR(dst_ioas);
268268
goto out_pages;
@@ -292,7 +292,7 @@ int iommufd_ioas_unmap(struct iommufd_ucmd *ucmd)
292292
unsigned long unmapped = 0;
293293
int rc;
294294

295-
ioas = iommufd_get_ioas(ucmd, cmd->ioas_id);
295+
ioas = iommufd_get_ioas(ucmd->ictx, cmd->ioas_id);
296296
if (IS_ERR(ioas))
297297
return PTR_ERR(ioas);
298298

@@ -381,7 +381,7 @@ int iommufd_ioas_option(struct iommufd_ucmd *ucmd)
381381
if (cmd->__reserved)
382382
return -EOPNOTSUPP;
383383

384-
ioas = iommufd_get_ioas(ucmd, cmd->object_id);
384+
ioas = iommufd_get_ioas(ucmd->ictx, cmd->object_id);
385385
if (IS_ERR(ioas))
386386
return PTR_ERR(ioas);
387387

drivers/iommu/iommufd/iommufd_private.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -212,10 +212,10 @@ struct iommufd_ioas {
212212
struct list_head hwpt_list;
213213
};
214214

215-
static inline struct iommufd_ioas *iommufd_get_ioas(struct iommufd_ucmd *ucmd,
215+
static inline struct iommufd_ioas *iommufd_get_ioas(struct iommufd_ctx *ictx,
216216
u32 id)
217217
{
218-
return container_of(iommufd_get_object(ucmd->ictx, id,
218+
return container_of(iommufd_get_object(ictx, id,
219219
IOMMUFD_OBJ_IOAS),
220220
struct iommufd_ioas, obj);
221221
}

drivers/iommu/iommufd/selftest.c

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,7 @@ void iommufd_test_syz_conv_iova_id(struct iommufd_ucmd *ucmd,
7575
return;
7676
*flags &= ~(u32)MOCK_FLAGS_ACCESS_SYZ;
7777

78-
ioas = iommufd_get_ioas(ucmd, ioas_id);
78+
ioas = iommufd_get_ioas(ucmd->ictx, ioas_id);
7979
if (IS_ERR(ioas))
8080
return;
8181
*iova = iommufd_test_syz_conv_iova(&ioas->iopt, iova);
@@ -463,7 +463,7 @@ static int iommufd_test_add_reserved(struct iommufd_ucmd *ucmd,
463463
struct iommufd_ioas *ioas;
464464
int rc;
465465

466-
ioas = iommufd_get_ioas(ucmd, mockpt_id);
466+
ioas = iommufd_get_ioas(ucmd->ictx, mockpt_id);
467467
if (IS_ERR(ioas))
468468
return PTR_ERR(ioas);
469469
down_write(&ioas->iopt.iova_rwsem);
@@ -700,6 +700,7 @@ static int iommufd_test_create_access(struct iommufd_ucmd *ucmd,
700700
struct iommu_test_cmd *cmd = ucmd->cmd;
701701
struct selftest_access *staccess;
702702
struct iommufd_access *access;
703+
u32 id;
703704
int fdno;
704705
int rc;
705706

@@ -717,15 +718,18 @@ static int iommufd_test_create_access(struct iommufd_ucmd *ucmd,
717718
}
718719

719720
access = iommufd_access_create(
720-
ucmd->ictx, ioas_id,
721+
ucmd->ictx,
721722
(flags & MOCK_FLAGS_ACCESS_CREATE_NEEDS_PIN_PAGES) ?
722723
&selftest_access_ops_pin :
723724
&selftest_access_ops,
724-
staccess);
725+
staccess, &id);
725726
if (IS_ERR(access)) {
726727
rc = PTR_ERR(access);
727728
goto out_put_fdno;
728729
}
730+
rc = iommufd_access_attach(access, ioas_id);
731+
if (rc)
732+
goto out_destroy;
729733
cmd->create_access.out_access_fd = fdno;
730734
rc = iommufd_ucmd_respond(ucmd, sizeof(*cmd));
731735
if (rc)

drivers/iommu/iommufd/vfio_compat.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -137,7 +137,7 @@ int iommufd_vfio_ioas(struct iommufd_ucmd *ucmd)
137137
return iommufd_ucmd_respond(ucmd, sizeof(*cmd));
138138

139139
case IOMMU_VFIO_IOAS_SET:
140-
ioas = iommufd_get_ioas(ucmd, cmd->ioas_id);
140+
ioas = iommufd_get_ioas(ucmd->ictx, cmd->ioas_id);
141141
if (IS_ERR(ioas))
142142
return PTR_ERR(ioas);
143143
xa_lock(&ucmd->ictx->objects);

drivers/vfio/iommufd.c

Lines changed: 18 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -32,13 +32,6 @@ int vfio_iommufd_bind(struct vfio_device *vdev, struct iommufd_ctx *ictx)
3232
return 0;
3333
}
3434

35-
/*
36-
* If the driver doesn't provide this op then it means the device does
37-
* not do DMA at all. So nothing to do.
38-
*/
39-
if (!vdev->ops->bind_iommufd)
40-
return 0;
41-
4235
ret = vdev->ops->bind_iommufd(vdev, ictx, &device_id);
4336
if (ret)
4437
return ret;
@@ -119,15 +112,17 @@ EXPORT_SYMBOL_GPL(vfio_iommufd_physical_attach_ioas);
119112
/*
120113
* The emulated standard ops mean that vfio_device is going to use the
121114
* "mdev path" and will call vfio_pin_pages()/vfio_dma_rw(). Drivers using this
122-
* ops set should call vfio_register_emulated_iommu_dev().
115+
* ops set should call vfio_register_emulated_iommu_dev(). Drivers that do
116+
* not call vfio_pin_pages()/vfio_dma_rw() have no need to provide dma_unmap.
123117
*/
124118

125119
static void vfio_emulated_unmap(void *data, unsigned long iova,
126120
unsigned long length)
127121
{
128122
struct vfio_device *vdev = data;
129123

130-
vdev->ops->dma_unmap(vdev, iova, length);
124+
if (vdev->ops->dma_unmap)
125+
vdev->ops->dma_unmap(vdev, iova, length);
131126
}
132127

133128
static const struct iommufd_access_ops vfio_user_ops = {
@@ -138,10 +133,14 @@ static const struct iommufd_access_ops vfio_user_ops = {
138133
int vfio_iommufd_emulated_bind(struct vfio_device *vdev,
139134
struct iommufd_ctx *ictx, u32 *out_device_id)
140135
{
136+
struct iommufd_access *user;
137+
141138
lockdep_assert_held(&vdev->dev_set->lock);
142139

143-
vdev->iommufd_ictx = ictx;
144-
iommufd_ctx_get(ictx);
140+
user = iommufd_access_create(ictx, &vfio_user_ops, vdev, out_device_id);
141+
if (IS_ERR(user))
142+
return PTR_ERR(user);
143+
vdev->iommufd_access = user;
145144
return 0;
146145
}
147146
EXPORT_SYMBOL_GPL(vfio_iommufd_emulated_bind);
@@ -152,24 +151,24 @@ void vfio_iommufd_emulated_unbind(struct vfio_device *vdev)
152151

153152
if (vdev->iommufd_access) {
154153
iommufd_access_destroy(vdev->iommufd_access);
154+
vdev->iommufd_attached = false;
155155
vdev->iommufd_access = NULL;
156156
}
157-
iommufd_ctx_put(vdev->iommufd_ictx);
158-
vdev->iommufd_ictx = NULL;
159157
}
160158
EXPORT_SYMBOL_GPL(vfio_iommufd_emulated_unbind);
161159

162160
int vfio_iommufd_emulated_attach_ioas(struct vfio_device *vdev, u32 *pt_id)
163161
{
164-
struct iommufd_access *user;
162+
int rc;
165163

166164
lockdep_assert_held(&vdev->dev_set->lock);
167165

168-
user = iommufd_access_create(vdev->iommufd_ictx, *pt_id, &vfio_user_ops,
169-
vdev);
170-
if (IS_ERR(user))
171-
return PTR_ERR(user);
172-
vdev->iommufd_access = user;
166+
if (vdev->iommufd_attached)
167+
return -EBUSY;
168+
rc = iommufd_access_attach(vdev->iommufd_access, *pt_id);
169+
if (rc)
170+
return rc;
171+
vdev->iommufd_attached = true;
173172
return 0;
174173
}
175174
EXPORT_SYMBOL_GPL(vfio_iommufd_emulated_attach_ioas);

drivers/vfio/vfio_main.c

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -255,8 +255,9 @@ static int __vfio_register_dev(struct vfio_device *device,
255255
{
256256
int ret;
257257

258-
if (WARN_ON(device->ops->bind_iommufd &&
259-
(!device->ops->unbind_iommufd ||
258+
if (WARN_ON(IS_ENABLED(CONFIG_IOMMUFD) &&
259+
(!device->ops->bind_iommufd ||
260+
!device->ops->unbind_iommufd ||
260261
!device->ops->attach_ioas)))
261262
return -EINVAL;
262263

include/linux/iommufd.h

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -40,9 +40,10 @@ enum {
4040
};
4141

4242
struct iommufd_access *
43-
iommufd_access_create(struct iommufd_ctx *ictx, u32 ioas_id,
44-
const struct iommufd_access_ops *ops, void *data);
43+
iommufd_access_create(struct iommufd_ctx *ictx,
44+
const struct iommufd_access_ops *ops, void *data, u32 *id);
4545
void iommufd_access_destroy(struct iommufd_access *access);
46+
int iommufd_access_attach(struct iommufd_access *access, u32 ioas_id);
4647

4748
void iommufd_ctx_get(struct iommufd_ctx *ictx);
4849

include/linux/vfio.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,6 @@ struct vfio_device {
6060
void (*put_kvm)(struct kvm *kvm);
6161
#if IS_ENABLED(CONFIG_IOMMUFD)
6262
struct iommufd_device *iommufd_device;
63-
struct iommufd_ctx *iommufd_ictx;
6463
bool iommufd_attached;
6564
#endif
6665
};

samples/vfio-mdev/mbochs.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1374,6 +1374,9 @@ static const struct vfio_device_ops mbochs_dev_ops = {
13741374
.write = mbochs_write,
13751375
.ioctl = mbochs_ioctl,
13761376
.mmap = mbochs_mmap,
1377+
.bind_iommufd = vfio_iommufd_emulated_bind,
1378+
.unbind_iommufd = vfio_iommufd_emulated_unbind,
1379+
.attach_ioas = vfio_iommufd_emulated_attach_ioas,
13771380
};
13781381

13791382
static struct mdev_driver mbochs_driver = {

0 commit comments

Comments
 (0)