aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/vfio/vfio.c
diff options
context:
space:
mode:
authorAlexey Kardashevskiy <aik@ozlabs.ru>2013-08-05 12:52:36 -0400
committerAlex Williamson <alex.williamson@redhat.com>2013-08-05 12:52:36 -0400
commit6cdd97821322352b94bb92f271b4466ad38a2468 (patch)
treea79a322ca2ae87302f7ba85c0a286e7ec6b76bb6 /drivers/vfio/vfio.c
parentc095ba7224d8edc71dcef0d655911399a8bd4a3f (diff)
vfio: add external user support
VFIO is designed to be used via ioctls on file descriptors returned by VFIO. However in some situations support for an external user is required. The first user is KVM on PPC64 (SPAPR TCE protocol) which is going to use the existing VFIO groups for exclusive access in real/virtual mode on a host to avoid passing map/unmap requests to the user space which would made things pretty slow. The protocol includes: 1. do normal VFIO init operation: - opening a new container; - attaching group(s) to it; - setting an IOMMU driver for a container. When IOMMU is set for a container, all groups in it are considered ready to use by an external user. 2. User space passes a group fd to an external user. The external user calls vfio_group_get_external_user() to verify that: - the group is initialized; - IOMMU is set for it. If both checks passed, vfio_group_get_external_user() increments the container user counter to prevent the VFIO group from disposal before KVM exits. 3. The external user calls vfio_external_user_iommu_id() to know an IOMMU ID. PPC64 KVM uses it to link logical bus number (LIOBN) with IOMMU ID. 4. When the external KVM finishes, it calls vfio_group_put_external_user() to release the VFIO group. This call decrements the container user counter. Everything gets released. The "vfio: Limit group opens" patch is also required for the consistency. Signed-off-by: Alexey Kardashevskiy <aik@ozlabs.ru> Signed-off-by: Alex Williamson <alex.williamson@redhat.com>
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)