Trait Virtqueue

Source
pub trait Virtqueue {
    // Required methods
    fn negotiate_queue_size(&self, device_max_elements: usize) -> usize;
    fn initialize(&self, queue_number: u32, queue_elements: usize);
    fn physical_addresses(&self) -> VirtqueueAddresses;
    fn used_interrupt(&self);
}
Expand description

A VirtIO Virtqueue.

Virtqueues are VirtIO’s mechanism to exchange data between a host and a guest. Each queue instance provides a bidirectional communication channel to send data from the guest (VirtIO driver) to the host (VirtIO device) and back. Typically, a given Virtqueue is only used for communication in a single direction. A VirtIO device can support multiple Virtqueues.

Fundamentally, every Virtqueue refers to three distinct regions in memory:

  • the descriptor area: this memory region contains an array of so-called Virtqueue descriptors. Each descriptor is a data structure containing metadata concerning a buffer shared by the guest (VirtIO driver) into the Virtqueue, such as its guest-physical address in memory and length. Multiple shared buffers in distinct memory locations can be chained into a single buffer.

  • the available ring: this available ring is a data structure maintained by the guest (VirtIO driver). It contains a ring-buffer which is used for the guest to share descriptors (as maintained in the descriptor area) with the host (VirtIO device).

  • the used ring: buffers shared with the host (VirtIO device) will eventually be returned to the guest (VirtIO driver) by the device placing them into the used ring. The host will further issue an interrupt, which shall be routed to the Virtqueue by means of the Virtqueue::used_interrupt method.

Required Methods§

Source

fn negotiate_queue_size(&self, device_max_elements: usize) -> usize

Negotiate the number of used descriptors in the Virtqueue.

The method is presented with the maximum number of queue elements the intended device can support. The method must return a value smaller or equal than device_max_elements. The device’s addresses as returned by Virtqueue::physical_addresses after Virtqueue initialization must have a memory layout adhering to the Virtual I/O Device (VIRTIO) Specification, Version 1.1, for at least the returned number of queue elements.

This method may be called any number of times before initialization of the Virtqueue. Only its latest returned value is valid and must be passed to Virtqueue::initialize.

Source

fn initialize(&self, queue_number: u32, queue_elements: usize)

Initialize the Virtqueue.

This method must bring the Virtqueue into a state where it can be exposed to a VirtIO transport based on the return value of Virtqueue::physical_addresses. A Virtqueue must refuse operations which require it to be initialized until this method has been called.

The passed queue_number must identify the queue to the device. After returning from Virtqueue::initialize, calls into the Virtqueue (except for Virtqueue::physical_addresses) may attempt to communicate with the VirtIO device referencing this passed queue_number. In practice, this means that the VirtIO device should be made aware of this Virtqueue promptly after calling this method, at least before invoking Virtqueue::used_interrupt.

The provided queue_elements is the latest negotiated queue size, as returned by Virtqueue::negotiate_queue_size.

Source

fn physical_addresses(&self) -> VirtqueueAddresses

The physical addresses of the Virtqueue descriptors, available and used ring.

The returned addresses and their memory contents must adhere to the Virtual I/O Device (VIRTIO) Specification, Version 1.1

This method must not be called before the Virtqueue has been initialized.

Source

fn used_interrupt(&self)

Interrupt indicating that a VirtIO device may have placed a buffer into this Virtqueue’s used ring.

A Virtqueue must be tolerant of spurious calls to this method.

Implementors§

Source§

impl<const MAX_QUEUE_SIZE: usize> Virtqueue for SplitVirtqueue<'_, '_, MAX_QUEUE_SIZE>