| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273 |
- .. SPDX-License-Identifier: GPL-2.0-only
- .. include:: <isonum.txt>
- =====================
- VFIO Mediated devices
- =====================
- :Copyright: |copy| 2016, NVIDIA CORPORATION. All rights reserved.
- :Author: Neo Jia <cjia@nvidia.com>
- :Author: Kirti Wankhede <kwankhede@nvidia.com>
- Virtual Function I/O (VFIO) Mediated devices[1]
- ===============================================
- The number of use cases for virtualizing DMA devices that do not have built-in
- SR_IOV capability is increasing. Previously, to virtualize such devices,
- developers had to create their own management interfaces and APIs, and then
- integrate them with user space software. To simplify integration with user space
- software, we have identified common requirements and a unified management
- interface for such devices.
- The VFIO driver framework provides unified APIs for direct device access. It is
- an IOMMU/device-agnostic framework for exposing direct device access to user
- space in a secure, IOMMU-protected environment. This framework is used for
- multiple devices, such as GPUs, network adapters, and compute accelerators. With
- direct device access, virtual machines or user space applications have direct
- access to the physical device. This framework is reused for mediated devices.
- The mediated core driver provides a common interface for mediated device
- management that can be used by drivers of different devices. This module
- provides a generic interface to perform these operations:
- * Create and destroy a mediated device
- * Add a mediated device to and remove it from a mediated bus driver
- * Add a mediated device to and remove it from an IOMMU group
- The mediated core driver also provides an interface to register a bus driver.
- For example, the mediated VFIO mdev driver is designed for mediated devices and
- supports VFIO APIs. The mediated bus driver adds a mediated device to and
- removes it from a VFIO group.
- The following high-level block diagram shows the main components and interfaces
- in the VFIO mediated driver framework. The diagram shows NVIDIA, Intel, and IBM
- devices as examples, as these devices are the first devices to use this module::
- +---------------+
- | |
- | +-----------+ | mdev_register_driver() +--------------+
- | | | +<------------------------+ |
- | | mdev | | | |
- | | bus | +------------------------>+ vfio_mdev.ko |<-> VFIO user
- | | driver | | probe()/remove() | | APIs
- | | | | +--------------+
- | +-----------+ |
- | |
- | MDEV CORE |
- | MODULE |
- | mdev.ko |
- | +-----------+ | mdev_register_parent() +--------------+
- | | | +<------------------------+ |
- | | | | | ccw_device.ko|<-> physical
- | | | +------------------------>+ | device
- | | | | callbacks +--------------+
- | | Physical | |
- | | device | | mdev_register_parent() +--------------+
- | | interface | |<------------------------+ |
- | | | | | i915.ko |<-> physical
- | | | +------------------------>+ | device
- | | | | callbacks +--------------+
- | +-----------+ |
- +---------------+
- Registration Interfaces
- =======================
- The mediated core driver provides the following types of registration
- interfaces:
- * Registration interface for a mediated bus driver
- * Physical device driver interface
- Registration Interface for a Mediated Bus Driver
- ------------------------------------------------
- The registration interface for a mediated device driver provides the following
- structure to represent a mediated device's driver::
- /*
- * struct mdev_driver [2] - Mediated device's driver
- * @probe: called when new device created
- * @remove: called when device removed
- * @driver: device driver structure
- */
- struct mdev_driver {
- int (*probe) (struct mdev_device *dev);
- void (*remove) (struct mdev_device *dev);
- unsigned int (*get_available)(struct mdev_type *mtype);
- ssize_t (*show_description)(struct mdev_type *mtype, char *buf);
- struct device_driver driver;
- };
- A mediated bus driver for mdev should use this structure in the function calls
- to register and unregister itself with the core driver:
- * Register::
- int mdev_register_driver(struct mdev_driver *drv);
- * Unregister::
- void mdev_unregister_driver(struct mdev_driver *drv);
- The mediated bus driver's probe function should create a vfio_device on top of
- the mdev_device and connect it to an appropriate implementation of
- vfio_device_ops.
- When a driver wants to add the GUID creation sysfs to an existing device it has
- probe'd to then it should call::
- int mdev_register_parent(struct mdev_parent *parent, struct device *dev,
- struct mdev_driver *mdev_driver);
- This will provide the 'mdev_supported_types/XX/create' files which can then be
- used to trigger the creation of a mdev_device. The created mdev_device will be
- attached to the specified driver.
- When the driver needs to remove itself it calls::
- void mdev_unregister_parent(struct mdev_parent *parent);
- Which will unbind and destroy all the created mdevs and remove the sysfs files.
- Mediated Device Management Interface Through sysfs
- ==================================================
- The management interface through sysfs enables user space software, such as
- libvirt, to query and configure mediated devices in a hardware-agnostic fashion.
- This management interface provides flexibility to the underlying physical
- device's driver to support features such as:
- * Mediated device hot plug
- * Multiple mediated devices in a single virtual machine
- * Multiple mediated devices from different physical devices
- Links in the mdev_bus Class Directory
- -------------------------------------
- The /sys/class/mdev_bus/ directory contains links to devices that are registered
- with the mdev core driver.
- Directories and files under the sysfs for Each Physical Device
- --------------------------------------------------------------
- ::
- |- [parent physical device]
- |--- Vendor-specific-attributes [optional]
- |--- [mdev_supported_types]
- | |--- [<type-id>]
- | | |--- create
- | | |--- name
- | | |--- available_instances
- | | |--- device_api
- | | |--- description
- | | |--- [devices]
- | |--- [<type-id>]
- | | |--- create
- | | |--- name
- | | |--- available_instances
- | | |--- device_api
- | | |--- description
- | | |--- [devices]
- | |--- [<type-id>]
- | |--- create
- | |--- name
- | |--- available_instances
- | |--- device_api
- | |--- description
- | |--- [devices]
- * [mdev_supported_types]
- The list of currently supported mediated device types and their details.
- [<type-id>], device_api, and available_instances are mandatory attributes
- that should be provided by vendor driver.
- * [<type-id>]
- The [<type-id>] name is created by adding the device driver string as a prefix
- to the string provided by the vendor driver. This format of this name is as
- follows::
- sprintf(buf, "%s-%s", dev_driver_string(parent->dev), group->name);
- * device_api
- This attribute shows which device API is being created, for example,
- "vfio-pci" for a PCI device.
- * available_instances
- This attribute shows the number of devices of type <type-id> that can be
- created.
- * [device]
- This directory contains links to the devices of type <type-id> that have been
- created.
- * name
- This attribute shows a human readable name.
- * description
- This attribute can show brief features/description of the type. This is an
- optional attribute.
- Directories and Files Under the sysfs for Each mdev Device
- ----------------------------------------------------------
- ::
- |- [parent phy device]
- |--- [$MDEV_UUID]
- |--- remove
- |--- mdev_type {link to its type}
- |--- vendor-specific-attributes [optional]
- * remove (write only)
- Writing '1' to the 'remove' file destroys the mdev device. The vendor driver can
- fail the remove() callback if that device is active and the vendor driver
- doesn't support hot unplug.
- Example::
- # echo 1 > /sys/bus/mdev/devices/$mdev_UUID/remove
- Mediated device Hot plug
- ------------------------
- Mediated devices can be created and assigned at runtime. The procedure to hot
- plug a mediated device is the same as the procedure to hot plug a PCI device.
- Translation APIs for Mediated Devices
- =====================================
- The following APIs are provided for translating user pfn to host pfn in a VFIO
- driver::
- int vfio_pin_pages(struct vfio_device *device, dma_addr_t iova,
- int npage, int prot, struct page **pages);
- void vfio_unpin_pages(struct vfio_device *device, dma_addr_t iova,
- int npage);
- These functions call back into the back-end IOMMU module by using the pin_pages
- and unpin_pages callbacks of the struct vfio_iommu_driver_ops[4]. Currently
- these callbacks are supported in the TYPE1 IOMMU module. To enable them for
- other IOMMU backend modules, such as PPC64 sPAPR module, they need to provide
- these two callback functions.
- References
- ==========
- 1. See Documentation/driver-api/vfio.rst for more information on VFIO.
- 2. struct mdev_driver in include/linux/mdev.h
- 3. struct mdev_parent_ops in include/linux/mdev.h
- 4. struct vfio_iommu_driver_ops in include/linux/vfio.h
|