virtio/queues/mod.rs
1// Licensed under the Apache License, Version 2.0 or the MIT License.
2// SPDX-License-Identifier: Apache-2.0 OR MIT
3// Copyright Tock Contributors 2022.
4
5//! VirtIO Virtqueues.
6//!
7//! This module and its submodules provide abstractions for and
8//! implementations of VirtIO Virtqueues. For more information, see
9//! the documentation of the [`Virtqueue`] trait.
10
11pub mod split_queue;
12
13/// A set of addresses representing a Virtqueue in memory.
14pub struct VirtqueueAddresses {
15 pub descriptor_area: u64,
16 pub driver_area: u64,
17 pub device_area: u64,
18}
19
20/// A VirtIO Virtqueue.
21///
22/// Virtqueues are VirtIO's mechanism to exchange data between a host and a
23/// guest. Each queue instance provides a bidirectional communication channel to
24/// send data from the guest (VirtIO driver) to the host (VirtIO device) and
25/// back. Typically, a given Virtqueue is only used for communication in a
26/// single direction. A VirtIO device can support multiple Virtqueues.
27///
28/// Fundamentally, every Virtqueue refers to three distinct regions in memory:
29///
30/// - the **descriptor area**: this memory region contains an array of so-called
31/// Virtqueue descriptors. Each descriptor is a data structure containing
32/// metadata concerning a buffer shared by the guest (VirtIO driver) into the
33/// Virtqueue, such as its guest-physical address in memory and
34/// length. Multiple shared buffers in distinct memory locations can be
35/// chained into a single buffer.
36///
37/// - the **available ring**: this available ring is a data structure maintained
38/// by the guest (VirtIO driver). It contains a ring-buffer which is used for
39/// the guest to share descriptors (as maintained in the _descriptor area_)
40/// with the host (VirtIO device).
41///
42/// - the **used ring**: buffers shared with the host (VirtIO device) will
43/// eventually be returned to the guest (VirtIO driver) by the device placing
44/// them into the used ring. The host will further issue an interrupt, which
45/// shall be routed to the Virtqueue by means of the
46/// [`Virtqueue::used_interrupt`] method.
47pub trait Virtqueue {
48 /// Negotiate the number of used descriptors in the Virtqueue.
49 ///
50 /// The method is presented with the maximum number of queue elements the
51 /// intended device can support. The method must return a value smaller or
52 /// equal than `device_max_elements`. The device's addresses as returned by
53 /// [`Virtqueue::physical_addresses`] after Virtqueue initialization must
54 /// have a memory layout adhering to the [Virtual I/O Device (VIRTIO)
55 /// Specification, Version
56 /// 1.1](https://docs.oasis-open.org/virtio/virtio/v1.1/csprd01/virtio-v1.1-csprd01.html),
57 /// for at least the returned number of queue elements.
58 ///
59 /// This method may be called any number of times before initialization of
60 /// the [`Virtqueue`]. Only its latest returned value is valid and must be
61 /// passed to [`Virtqueue::initialize`].
62 fn negotiate_queue_size(&self, device_max_elements: usize) -> usize;
63
64 /// Initialize the Virtqueue.
65 ///
66 /// This method must bring the Virtqueue into a state where it can be
67 /// exposed to a VirtIO transport based on the return value of
68 /// [`Virtqueue::physical_addresses`]. A Virtqueue must refuse operations
69 /// which require it to be initialized until this method has been called.
70 ///
71 /// The passed `queue_number` must identify the queue to the device. After
72 /// returning from [`Virtqueue::initialize`], calls into the Virtqueue
73 /// (except for [`Virtqueue::physical_addresses`]) may attempt to
74 /// communicate with the VirtIO device referencing this passed
75 /// `queue_number`. In practice, this means that the VirtIO device should be
76 /// made aware of this [`Virtqueue`] promptly after calling this method, at
77 /// least before invoking [`Virtqueue::used_interrupt`].
78 ///
79 /// The provided `queue_elements` is the latest negotiated queue size, as
80 /// returned by [`Virtqueue::negotiate_queue_size`].
81 fn initialize(&self, queue_number: u32, queue_elements: usize);
82
83 /// The physical addresses of the Virtqueue descriptors, available and used ring.
84 ///
85 /// The returned addresses and their memory contents must adhere to the
86 /// [Virtual I/O Device (VIRTIO) Specification, Version
87 /// 1.1](https://docs.oasis-open.org/virtio/virtio/v1.1/csprd01/virtio-v1.1-csprd01.html)
88 ///
89 /// This method must not be called before the Virtqueue has been
90 /// initialized.
91 fn physical_addresses(&self) -> VirtqueueAddresses;
92
93 /// Interrupt indicating that a VirtIO device may have placed a buffer into
94 /// this Virtqueue's used ring.
95 ///
96 /// A [`Virtqueue`] must be tolerant of spurious calls to this method.
97 fn used_interrupt(&self);
98}