aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/vfio/vfio.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/vfio/vfio.c')
-rw-r--r--drivers/vfio/vfio.c62
1 files changed, 62 insertions, 0 deletions
diff --git a/drivers/vfio/vfio.c b/drivers/vfio/vfio.c
index 842f4507883e..d3cb34224369 100644
--- a/drivers/vfio/vfio.c
+++ b/drivers/vfio/vfio.c
@@ -1353,6 +1353,68 @@ static const struct file_operations vfio_device_fops = {
1353}; 1353};
1354 1354
1355/** 1355/**
1356 * External user API, exported by symbols to be linked dynamically.
1357 *
1358 * The protocol includes:
1359 * 1. do normal VFIO init operation:
1360 * - opening a new container;
1361 * - attaching group(s) to it;
1362 * - setting an IOMMU driver for a container.
1363 * When IOMMU is set for a container, all groups in it are
1364 * considered ready to use by an external user.
1365 *
1366 * 2. User space passes a group fd to an external user.
1367 * The external user calls vfio_group_get_external_user()
1368 * to verify that:
1369 * - the group is initialized;
1370 * - IOMMU is set for it.
1371 * If both checks passed, vfio_group_get_external_user()
1372 * increments the container user counter to prevent
1373 * the VFIO group from disposal before KVM exits.
1374 *
1375 * 3. The external user calls vfio_external_user_iommu_id()
1376 * to know an IOMMU ID.
1377 *
1378 * 4. When the external KVM finishes, it calls
1379 * vfio_group_put_external_user() to release the VFIO group.
1380 * This call decrements the container user counter.
1381 */
1382struct vfio_group *vfio_group_get_external_user(struct file *filep)
1383{
1384 struct vfio_group *group = filep->private_data;
1385
1386 if (filep->f_op != &vfio_group_fops)
1387 return ERR_PTR(-EINVAL);
1388
1389 if (!atomic_inc_not_zero(&group->container_users))
1390 return ERR_PTR(-EINVAL);
1391
1392 if (!group->container->iommu_driver ||
1393 !vfio_group_viable(group)) {
1394 atomic_dec(&group->container_users);
1395 return ERR_PTR(-EINVAL);
1396 }
1397
1398 vfio_group_get(group);
1399
1400 return group;
1401}
1402EXPORT_SYMBOL_GPL(vfio_group_get_external_user);
1403
1404void vfio_group_put_external_user(struct vfio_group *group)
1405{
1406 vfio_group_put(group);
1407 vfio_group_try_dissolve_container(group);
1408}
1409EXPORT_SYMBOL_GPL(vfio_group_put_external_user);
1410
1411int vfio_external_user_iommu_id(struct vfio_group *group)
1412{
1413 return iommu_group_id(group->iommu_group);
1414}
1415EXPORT_SYMBOL_GPL(vfio_external_user_iommu_id);
1416
1417/**
1356 * Module/class support 1418 * Module/class support
1357 */ 1419 */
1358static char *vfio_devnode(struct device *dev, umode_t *mode) 1420static char *vfio_devnode(struct device *dev, umode_t *mode)