pub struct UserQueue {
    size: Wrapping<u16>,
    mem: QueueMemory,
    mem_layout: MemLayout,
    avail_idx: Wrapping<u16>,
    used_count: Wrapping<u16>,
    free_count: Wrapping<u16>,
    device_writable: bool,
}
Expand description

Represents a virtqueue that is allocated in the guest userspace and manipulated from a VFIO driver.

This struct is similar to devices::virtio::Queue which is designed for the virtio devices, but this struct is defined for the virtio drivers.

Memory Layout

mem is the memory allocated in the guest userspace for the virtqueue, which is mapped into the vvu device via VFIO. The GuestAddresses of mem are the IOVAs that should be used when communicating with the vvu device. All accesses to the shared memory from the device backend must be done through the GuestMemory read/write functions.

The layout mem is defined in the following table and stored in mem_layout.

| | Alignment | Size | |—————————————————————–| | Descriptor Table | 16 | 16 ∗ (Queue Size) | | Available Ring | 2 | 6 + 2 ∗ (Queue Size) | | Used Ring | 4 | 6 + 8 ∗ (Queue Size) | | Buffers | (Buffer Size) | (Buffer Size) * (Queue Size) |

TODO(b/207364742): Once we support VIRTIO_F_EVENT_IDX, the additional 2 bytes for the used_event field will be added. TODO(b/215153367): Use crate::virtio::Queue as an underlying data structure so that we can use descriptor_utils::{Reader, Writer} instead of having our own read/write methods. One of the biggest blockers is that virtio::Queue is designed for device-side’s virtqueue, where readable/writable areas are inverted from our use case.

Fields§

§size: Wrapping<u16>

The queue size.

§mem: QueueMemory

The underlying memory.

§mem_layout: MemLayout

Virtqueue layout on mem.

§avail_idx: Wrapping<u16>§used_count: Wrapping<u16>§free_count: Wrapping<u16>§device_writable: bool

Whether buffers are device-writable or readable. If true, every descriptor has the VIRTQ_DESC_F_WRITE flag. TODO(b/215153358, b/215153367): Since VIRTQ_DESC_F_WRITE is a per-descriptor flag, this design is specific to the current vvu specification draft, where a device-writable queue and a device-readable queue are separated. Ideally, we should update the vvu spec to use both device-{readable, writable} buffers in one virtqueue. Also, it’s better to use crate::virtio::DescriptorChain for descirptors as a part of b/215153367.

Implementations§

Creats a UserQueue instance.

Allocates memory region and returns addresses on the regions for (desc_table, avail_ring, used_ring, `buffer``).

Initialize the descriptor table.

Returns the IOVA of the buffer for the given index.

source

fn write_desc_entry(&self, index: Wrapping<u16>, desc: Desc) -> Result<()>

Writes the given descriptor table entry.

Puts an index into the avail ring for use by the host.

Reads the Used ring’s index.

Reads the Used ring’s element for the given index.

Reads data in the virtqueue. Returns Ok(None) if no data are available.

TODO: Use descriptor_utils::Reader.

Writes data into virtqueue’s buffer and returns its address.

TODO: Use descriptor_utils::Writer.

Acknowledges buffers that the device used.

Writes the given data to the virtqueue.

Auto Trait Implementations§

Blanket Implementations§

Gets the TypeId of self. Read more
Immutably borrows from an owned value. Read more
Mutably borrows from an owned value. Read more
Convert Box<dyn Trait> (where Trait: Downcast) to Box<dyn Any>. Box<dyn Any> can then be further downcast into Box<ConcreteType> where ConcreteType implements Trait.
Convert Rc<Trait> (where Trait: Downcast) to Rc<Any>. Rc<Any> can then be further downcast into Rc<ConcreteType> where ConcreteType implements Trait.
Convert &Trait (where Trait: Downcast) to &Any. This is needed since Rust cannot generate &Any’s vtable from &Trait’s.
Convert &mut Trait (where Trait: Downcast) to &Any. This is needed since Rust cannot generate &mut Any’s vtable from &mut Trait’s.
Convert Arc<Trait> (where Trait: Downcast) to Arc<Any>. Arc<Any> can then be further downcast into Arc<ConcreteType> where ConcreteType implements Trait.

Returns the argument unchanged.

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

The type returned in the event of a conversion error.
Performs the conversion.
The type returned in the event of a conversion error.
Performs the conversion.