8. VFIO Library

Platform devices in Linux refer to System-on-Chip (SoC) components that aren’t situated on standard buses such as PCI or USB. You can see them in Linux at the path /sys/bus/platform/devices/. To interact with platform devices from user space, the vfio-platform driver provides a framework. This library provides DAO APIs built upon this framework, enabling access to the device resources.

Also this library can be used to access the standard PCIe devices present at /sys/bus/pci/devices/ from the user space.

8.1. Prerequisites for Platform Devices:

To make use of VFIO platform framework, the vfio-platform module must be loaded first:

sudo modprobe vfio-platform

Note

By default vfio-platform assumes that platform device has dedicated reset driver. If such driver is missing or device does not require one, this option can be turned off by setting reset_required=0 module parameter.

Afterwards, the platform device needs to be bound to vfio-platform, following a standard two-step procedure. Initially, the driver_override, located within the platform device directory, must be configured to vfio-platform:

echo vfio-platform | sudo tee /sys/bus/platform/devices/DEV/driver_override

Next DEV device must be bound to vfio-platform driver:

echo DEV | sudo tee /sys/bus/platform/drivers/vfio-platform/bind

8.2. Prerequisites for PCIe Devices:

To make use of VFIO PCIe framework, the vfio-pci module must be loaded first:

sudo modprobe vfio-pci

The PCIe device needs to be bound to vfio-pci, following a standard two-step procedure. Initially, the driver_override, located within the pci device directory, must be configured to vfio-pci:

echo vfio-pci | sudo tee /sys/bus/pci/devices/<BDF>/driver_override

Next BDF of the device must be bound to vfio-pci driver:

echo <BDF> | sudo tee /sys/bus/pci/drivers/vfio-pci/bind

8.3. DAO VFIO device initialization

Invoking the dao_vfio_init() API creates a VFIO container by opening the /dev/vfio/vfio character device and initializes the memory used for storing the details of the devices. This API should be invoked only once to initiate the library.

int dao_vfio_init(void);

After initializing the library, the dao_vfio_device_setup() API can be used to initialize the device. The function takes the memory for storing the device details, specified by the struct dao_vfio_device argument. Upon successful execution, the resources of the devices are mapped, and the device structure is populated.

int dao_vfio_device_setup(const char *dev_name, struct dao_vfio_device *pdev);
struct dao_vfio_mem_resouce {
	uint8_t *addr; /**< Mapped virtual address. */
	uint64_t len;  /**< Length of the resource. */
};

/** DAO VFIO device */
struct dao_vfio_device {
	char name[VFIO_DEV_NAME_MAX_LEN]; /**< Device name */
	int device_fd;                    /**< VFIO device fd */
	int group_fd;                     /**< VFIO group fd */
	unsigned int num_resource;        /**< Number of device resources */
	struct dao_vfio_mem_resouce *mem; /**< Device resources */
	enum dao_vfio_dev_type type;      /**< Device type */
	uint8_t prime;                    /**< Primary device */
	uint8_t mbar;                     /**< Bar index of memory */
	uint8_t rbar;                     /**< Bar index of device registers */
};

8.4. DAO VFIO device cleanup

dao_vfio_device_free() releases the VFIO device and frees the associated memory.

void dao_vfio_device_free(struct dao_vfio_device *pdev);

Upon closing all open devices, the container can be shut down by calling dao_vfio_fini().

void dao_vfio_fini(void);