VirtIO library (libvirtio)#

libvirtio provides an abstraction layer for working with VirtIO devices. VirtIO is a standard dedicated to provide a common device API (e.g. network and mass storage adapters) for virtualized execution environment.


General information#

The library offers a set of functionalities for VirtIO device initialization, configuration, data exchange, and cleanup. It supports both legacy and modern VirtIO device models, offering compatibility with various device types including network (virtio-net) and block devices (virtio-blk). The library uses condition variables and mutexes (handle_t) to ensure thread-safe interactions with VirtIO devices and queues.

libvirtio interface#

Device and Queue Management#

  • virtio_initDev - Initializes a VirtIO device.

int virtio_initDev(virtio_dev_t *vdev)
  • virtio_destroyDev - Cleans up resources associated with a VirtIO device.

void virtio_destroyDev(virtio_dev_t *vdev)
  • virtqueue_init - Initializes a VirtIO queue.

int virtqueue_init(virtio_dev_t *vdev, virtqueue_t *vq, unsigned int idx, unsigned int size)
  • virtqueue_destroy - Cleans up resources associated with a VirtIO queue.

void virtqueue_destroy(virtio_dev_t *vdev, virtqueue_t *vq)

Data Exchange#

  • virtqueue_enqueue - Enqueues a request in a VirtIO queue for processing by the device.

int virtqueue_enqueue(virtio_dev_t *vdev, virtqueue_t *vq, virtio_req_t *req)
  • virtqueue_dequeue - Dequeues a processed request from a VirtIO queue.

void *virtqueue_dequeue(virtio_dev_t *vdev, virtqueue_t *vq, unsigned int *len)
  • virtqueue_notify - Notifies the device that there are available requests in the queue.

void virtqueue_notify(virtio_dev_t *vdev, virtqueue_t *vq)
  • virtqueue_enableIRQ - Enable interrupts for a VirtIO queue.

void virtqueue_enableIRQ(virtio_dev_t *vdev, virtqueue_t *vq)
  • virtqueue_disableIRQ - Disable interrupts for a VirtIO queue.

void virtqueue_disableIRQ(virtio_dev_t *vdev, virtqueue_t *vq)

Configuration and Status#

  • virtio_readConfig - Read from the VirtIO device’s configuration space.

uint8_t virtio_readConfig8(virtio_dev_t *vdev, unsigned int reg);

uint16_t virtio_readConfig16(virtio_dev_t *vdev, unsigned int reg);

uint32_t virtio_readConfig32(virtio_dev_t *vdev, unsigned int reg);

uint64_t virtio_readConfig64(virtio_dev_t *vdev, unsigned int reg);
  • virtio_writeConfig -Write to the VirtIO device’s configuration space.

void virtio_writeConfig8(virtio_dev_t *vdev, unsigned int reg, uint8_t val);

void virtio_writeConfig16(virtio_dev_t *vdev, unsigned int reg, uint16_t val);

void virtio_writeConfig32(virtio_dev_t *vdev, unsigned int reg, uint32_t val);

void virtio_writeConfig64(virtio_dev_t *vdev, unsigned int reg, uint64_t val);
  • virtio_readFeatures - Read VirtIO device features.

uint64_t virtio_readFeatures(virtio_dev_t *vdev)
  • virtio_writeFeatures - Write VirtIO device features.

int virtio_writeFeatures(virtio_dev_t *vdev, uint64_t features)
  • virtio_readStatus - Read the VirtIO device status register.

uint8_t virtio_readStatus(virtio_dev_t *vdev)
  • virtio_writeStatus - Write the VirtIO device status register.

void virtio_writeStatus(virtio_dev_t *vdev, uint8_t status)
  • virtio_isr - Reads the interrupt status.

unsigned int virtio_isr(virtio_dev_t *vdev)


  • virtio_reset - Resets a VirtIO device to its initial state.

void virtio_reset(virtio_dev_t *vdev)
  • virtio_find - Detects the next VirtIO device matching a given device descriptor.

int virtio_find(const virtio_devinfo_t *info, virtio_dev_t *vdev, virtio_ctx_t *vctx)
  • virtio_init - Initialize the VirtIO library.

int virtio_init(void)
  • virtio_done - Clean up the VirtIO library.

int virtio_done(void)

Memory Barriers#

  • virtio_mb - Provides a memory barrier to ensure memory operations’ ordering.

void virtio_mb(void)

Data Structures#

  • virtio_devtype_t - Enumerates the types of VirtIO devices, such as PCI and MMIO devices.

typedef enum {
	vdevNONE = 0x00, /* No VirtIO device */
	vdevPCI  = 0x01, /* VirtIO PCI device */
	vdevMMIO = 0x02  /* VirtIO MMIO device */
} virtio_devtype_t;
  • virtio_seg_t - Represents a segment of a data buffer for I/O operations, forming a doubly linked list.

struct _virtio_seg_t {
	void *buff;                /* Buffer exposed to device */
	unsigned int len;          /* Buffer length */
	virtio_seg_t *prev, *next; /* Doubly linked list */
  • virtio_req_t - Encapsulates a request to be processed by a VirtIO device, comprising a list of segments.

typedef struct {
	virtio_seg_t *segs; /* Request segments list */
	unsigned int rsegs; /* Number of device readable segments */
	unsigned int wsegs; /* Number of device writable segments */
} virtio_req_t;
  • virtio_desc_t - Represents a descriptor in the VirtIO queue.

typedef struct {
	uint64_t addr;  /* Buffer physical address */
	uint32_t len;   /* Buffer length */
	uint16_t flags; /* Descriptor flags */
	uint16_t next;  /* Next chained descriptor index (if flags & 0x1) */
} __attribute__((packed)) virtio_desc_t;
  • virtio_avail_t / virtio_used_t - Structures used to manage available and used rings in a VirtIO queue.

typedef struct {
	uint16_t flags;  /* Used buffer notification suppression */
	uint16_t idx;    /* Next available request index */
	uint16_t ring[]; /* Available requests (descriptor chain IDs) */
} __attribute__((packed)) virtio_avail_t;
typedef struct {
	uint16_t flags;            /* Available buffer notification suppression */
	uint16_t idx;              /* Next processed request ring index */
	virtio_used_elem_t ring[]; /* Processed requests */
} __attribute__((packed)) virtio_used_t;
  • virtqueue_t - Represents a VirtIO queue, holding the queue’s descriptors, available and used rings, and synchronization primitives.

typedef struct {
	/* Standard split virtqueue layout */
	volatile virtio_desc_t *desc;   /* Descriptors */
	volatile virtio_avail_t *avail; /* Avail ring */
	volatile uint16_t *uevent;      /* Used event notification suppression */
	volatile virtio_used_t *used;   /* Used ring */
	volatile uint16_t *aevent;      /* Avail event notification suppression */

	/* Custom helper fields */
	void **buffs;       /* Descriptors buffers */
	void *mem;          /* Allocated virtqueue memory */
	unsigned int memsz; /* Allocated virtqueue memory size */
	unsigned int idx;   /* Virtqueue index */
	unsigned int size;  /* Virtqueue size */
	unsigned int noffs; /* Virtqueue notification area offset (modern VirtIO PCI device only) */
	unsigned int nfree; /* Number of free descriptors */
	uint16_t free;      /* Next free descriptor index */
	uint16_t last;      /* Last processed request index */

	/* Synchronization */
	handle_t cond; /* Free descriptors condition variable */
	handle_t lock; /* Virtqueue mutex */
} virtqueue_t;
  • virtio_devinfo_t - Contains basic information about a VirtIO device, including its type, ID, and register addresses.

typedef struct {
	virtio_devtype_t type; /* VirtIO device type */
	unsigned int id;       /* VirtIO device ID */
	unsigned int irq;      /* Interrupt number */
	unsigned int xntf;     /* Notification registers offset multiplier */
	virtio_reg_t base;     /* Base registers */
	virtio_reg_t ntf;      /* Notification register */
	virtio_reg_t isr;      /* Interrupt status register */
	virtio_reg_t cfg;      /* Configuration registers */
} virtio_devinfo_t;
  • virtio_dev_t - Encapsulates a VirtIO device, including its features and device-specific information.

typedef struct {
	virtio_devinfo_t info; /* VirtIO device core data */
	uint64_t features;     /* VirtIO device features */
} virtio_dev_t;
  • virtio_ctx_t - Used for device detection and context management.

typedef struct {
	unsigned char reset;   /* Indicates that context to be reset */
	unsigned char ctx[32]; /* VirtIO device detection context */
} virtio_ctx_t;

Using libvirtio#

To use functions provided by libvirtio please add the library to the LIBS variable in Makefile and include the required header file.

Running tests#

VirtIO library provides the basic set of tests, which is available in phoenix-rtos-tests.

See also#

  1. Phoenix-RTOS core libraries

  2. Phoenix-RTOS Graphics Library

  3. Table of Contents