Skip to content

Commit 051ae5a

Browse files
Steve Sistarejgunthorpe
authored andcommitted
iommufd: Lock all IOAS objects
Define helpers to lock and unlock all IOAS objects. This will allow DMA mappings to be updated atomically during live update. This code is substantially the same as an initial version provided by Jason, plus fixes. Link: https://patch.msgid.link/r/[email protected] Signed-off-by: Steve Sistare <[email protected]> Reviewed-by: Jason Gunthorpe <[email protected]> Reviewed-by: Kevin Tian <[email protected]> Signed-off-by: Jason Gunthorpe <[email protected]>
1 parent 10caa8b commit 051ae5a

File tree

3 files changed

+67
-0
lines changed

3 files changed

+67
-0
lines changed

drivers/iommu/iommufd/ioas.c

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,10 @@ int iommufd_ioas_alloc_ioctl(struct iommufd_ucmd *ucmd)
5252
rc = iommufd_ucmd_respond(ucmd, sizeof(*cmd));
5353
if (rc)
5454
goto out_table;
55+
56+
down_read(&ucmd->ictx->ioas_creation_lock);
5557
iommufd_object_finalize(ucmd->ictx, &ioas->obj);
58+
up_read(&ucmd->ictx->ioas_creation_lock);
5659
return 0;
5760

5861
out_table:
@@ -374,6 +377,68 @@ int iommufd_ioas_unmap(struct iommufd_ucmd *ucmd)
374377
return rc;
375378
}
376379

380+
static void iommufd_release_all_iova_rwsem(struct iommufd_ctx *ictx,
381+
struct xarray *ioas_list)
382+
{
383+
struct iommufd_ioas *ioas;
384+
unsigned long index;
385+
386+
xa_for_each(ioas_list, index, ioas) {
387+
up_write(&ioas->iopt.iova_rwsem);
388+
refcount_dec(&ioas->obj.users);
389+
}
390+
up_write(&ictx->ioas_creation_lock);
391+
xa_destroy(ioas_list);
392+
}
393+
394+
static int iommufd_take_all_iova_rwsem(struct iommufd_ctx *ictx,
395+
struct xarray *ioas_list)
396+
{
397+
struct iommufd_object *obj;
398+
unsigned long index;
399+
int rc;
400+
401+
/*
402+
* This is very ugly, it is done instead of adding a lock around
403+
* pages->source_mm, which is a performance path for mdev, we just
404+
* obtain the write side of all the iova_rwsems which also protects the
405+
* pages->source_*. Due to copies we can't know which IOAS could read
406+
* from the pages, so we just lock everything. This is the only place
407+
* locks are nested and they are uniformly taken in ID order.
408+
*
409+
* ioas_creation_lock prevents new IOAS from being installed in the
410+
* xarray while we do this, and also prevents more than one thread from
411+
* holding nested locks.
412+
*/
413+
down_write(&ictx->ioas_creation_lock);
414+
xa_lock(&ictx->objects);
415+
xa_for_each(&ictx->objects, index, obj) {
416+
struct iommufd_ioas *ioas;
417+
418+
if (!obj || obj->type != IOMMUFD_OBJ_IOAS)
419+
continue;
420+
421+
if (!refcount_inc_not_zero(&obj->users))
422+
continue;
423+
424+
xa_unlock(&ictx->objects);
425+
426+
ioas = container_of(obj, struct iommufd_ioas, obj);
427+
down_write_nest_lock(&ioas->iopt.iova_rwsem,
428+
&ictx->ioas_creation_lock);
429+
430+
rc = xa_err(xa_store(ioas_list, index, ioas, GFP_KERNEL));
431+
if (rc) {
432+
iommufd_release_all_iova_rwsem(ictx, ioas_list);
433+
return rc;
434+
}
435+
436+
xa_lock(&ictx->objects);
437+
}
438+
xa_unlock(&ictx->objects);
439+
return 0;
440+
}
441+
377442
int iommufd_option_rlimit_mode(struct iommu_option *cmd,
378443
struct iommufd_ctx *ictx)
379444
{

drivers/iommu/iommufd/iommufd_private.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ struct iommufd_ctx {
2424
struct xarray objects;
2525
struct xarray groups;
2626
wait_queue_head_t destroy_wait;
27+
struct rw_semaphore ioas_creation_lock;
2728

2829
u8 account_mode;
2930
/* Compatibility with VFIO no iommu */

drivers/iommu/iommufd/main.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -222,6 +222,7 @@ static int iommufd_fops_open(struct inode *inode, struct file *filp)
222222
pr_info_once("IOMMUFD is providing /dev/vfio/vfio, not VFIO.\n");
223223
}
224224

225+
init_rwsem(&ictx->ioas_creation_lock);
225226
xa_init_flags(&ictx->objects, XA_FLAGS_ALLOC1 | XA_FLAGS_ACCOUNT);
226227
xa_init(&ictx->groups);
227228
ictx->file = filp;

0 commit comments

Comments
 (0)