xref: /aosp_15_r20/external/crosvm/devices/src/virtio/queue.rs (revision bb4ee6a4ae7042d18b07a98463b9c8b875e44b39)
1*bb4ee6a4SAndroid Build Coastguard Worker // Copyright 2023 The ChromiumOS Authors
2*bb4ee6a4SAndroid Build Coastguard Worker // Use of this source code is governed by a BSD-style license that can be
3*bb4ee6a4SAndroid Build Coastguard Worker // found in the LICENSE file.
4*bb4ee6a4SAndroid Build Coastguard Worker 
5*bb4ee6a4SAndroid Build Coastguard Worker //! virtqueue interface
6*bb4ee6a4SAndroid Build Coastguard Worker 
7*bb4ee6a4SAndroid Build Coastguard Worker #![deny(missing_docs)]
8*bb4ee6a4SAndroid Build Coastguard Worker 
9*bb4ee6a4SAndroid Build Coastguard Worker use std::ops::Deref;
10*bb4ee6a4SAndroid Build Coastguard Worker use std::ops::DerefMut;
11*bb4ee6a4SAndroid Build Coastguard Worker 
12*bb4ee6a4SAndroid Build Coastguard Worker pub mod packed_descriptor_chain;
13*bb4ee6a4SAndroid Build Coastguard Worker mod packed_queue;
14*bb4ee6a4SAndroid Build Coastguard Worker pub mod split_descriptor_chain;
15*bb4ee6a4SAndroid Build Coastguard Worker mod split_queue;
16*bb4ee6a4SAndroid Build Coastguard Worker 
17*bb4ee6a4SAndroid Build Coastguard Worker use std::num::Wrapping;
18*bb4ee6a4SAndroid Build Coastguard Worker 
19*bb4ee6a4SAndroid Build Coastguard Worker use anyhow::bail;
20*bb4ee6a4SAndroid Build Coastguard Worker use anyhow::Context;
21*bb4ee6a4SAndroid Build Coastguard Worker use anyhow::Result;
22*bb4ee6a4SAndroid Build Coastguard Worker use base::warn;
23*bb4ee6a4SAndroid Build Coastguard Worker use base::Event;
24*bb4ee6a4SAndroid Build Coastguard Worker use cros_async::AsyncError;
25*bb4ee6a4SAndroid Build Coastguard Worker use cros_async::EventAsync;
26*bb4ee6a4SAndroid Build Coastguard Worker use futures::channel::oneshot;
27*bb4ee6a4SAndroid Build Coastguard Worker use futures::select_biased;
28*bb4ee6a4SAndroid Build Coastguard Worker use futures::FutureExt;
29*bb4ee6a4SAndroid Build Coastguard Worker use packed_queue::PackedQueue;
30*bb4ee6a4SAndroid Build Coastguard Worker use serde::Deserialize;
31*bb4ee6a4SAndroid Build Coastguard Worker use serde::Serialize;
32*bb4ee6a4SAndroid Build Coastguard Worker use split_queue::SplitQueue;
33*bb4ee6a4SAndroid Build Coastguard Worker use virtio_sys::virtio_config::VIRTIO_F_RING_PACKED;
34*bb4ee6a4SAndroid Build Coastguard Worker use vm_memory::GuestAddress;
35*bb4ee6a4SAndroid Build Coastguard Worker use vm_memory::GuestMemory;
36*bb4ee6a4SAndroid Build Coastguard Worker 
37*bb4ee6a4SAndroid Build Coastguard Worker use crate::virtio::DescriptorChain;
38*bb4ee6a4SAndroid Build Coastguard Worker use crate::virtio::Interrupt;
39*bb4ee6a4SAndroid Build Coastguard Worker use crate::virtio::VIRTIO_MSI_NO_VECTOR;
40*bb4ee6a4SAndroid Build Coastguard Worker 
41*bb4ee6a4SAndroid Build Coastguard Worker /// A virtio queue's parameters.
42*bb4ee6a4SAndroid Build Coastguard Worker ///
43*bb4ee6a4SAndroid Build Coastguard Worker /// `QueueConfig` can be converted into a running `Queue` by calling [`QueueConfig::activate()`].
44*bb4ee6a4SAndroid Build Coastguard Worker pub struct QueueConfig {
45*bb4ee6a4SAndroid Build Coastguard Worker     /// Whether this queue has already been activated.
46*bb4ee6a4SAndroid Build Coastguard Worker     activated: bool,
47*bb4ee6a4SAndroid Build Coastguard Worker 
48*bb4ee6a4SAndroid Build Coastguard Worker     /// The maximal size in elements offered by the device
49*bb4ee6a4SAndroid Build Coastguard Worker     max_size: u16,
50*bb4ee6a4SAndroid Build Coastguard Worker 
51*bb4ee6a4SAndroid Build Coastguard Worker     /// The queue size in elements the driver selected. This is always guaranteed to be a power of
52*bb4ee6a4SAndroid Build Coastguard Worker     /// two less than or equal to `max_size`, as required for split virtqueues. These invariants
53*bb4ee6a4SAndroid Build Coastguard Worker     /// are enforced by `set_size()`.
54*bb4ee6a4SAndroid Build Coastguard Worker     size: u16,
55*bb4ee6a4SAndroid Build Coastguard Worker 
56*bb4ee6a4SAndroid Build Coastguard Worker     /// Indicates if the queue is finished with configuration
57*bb4ee6a4SAndroid Build Coastguard Worker     ready: bool,
58*bb4ee6a4SAndroid Build Coastguard Worker 
59*bb4ee6a4SAndroid Build Coastguard Worker     /// MSI-X vector for the queue. Don't care for INTx
60*bb4ee6a4SAndroid Build Coastguard Worker     vector: u16,
61*bb4ee6a4SAndroid Build Coastguard Worker 
62*bb4ee6a4SAndroid Build Coastguard Worker     /// Ring features (e.g. `VIRTIO_RING_F_EVENT_IDX`, `VIRTIO_F_RING_PACKED`) offered by the
63*bb4ee6a4SAndroid Build Coastguard Worker     /// device
64*bb4ee6a4SAndroid Build Coastguard Worker     features: u64,
65*bb4ee6a4SAndroid Build Coastguard Worker 
66*bb4ee6a4SAndroid Build Coastguard Worker     // Device feature bits accepted by the driver
67*bb4ee6a4SAndroid Build Coastguard Worker     acked_features: u64,
68*bb4ee6a4SAndroid Build Coastguard Worker 
69*bb4ee6a4SAndroid Build Coastguard Worker     /// Guest physical address of the descriptor table
70*bb4ee6a4SAndroid Build Coastguard Worker     desc_table: GuestAddress,
71*bb4ee6a4SAndroid Build Coastguard Worker 
72*bb4ee6a4SAndroid Build Coastguard Worker     /// Guest physical address of the available ring (driver area)
73*bb4ee6a4SAndroid Build Coastguard Worker     ///
74*bb4ee6a4SAndroid Build Coastguard Worker     /// TODO(b/290657008): update field and accessor names to match the current virtio spec
75*bb4ee6a4SAndroid Build Coastguard Worker     avail_ring: GuestAddress,
76*bb4ee6a4SAndroid Build Coastguard Worker 
77*bb4ee6a4SAndroid Build Coastguard Worker     /// Guest physical address of the used ring (device area)
78*bb4ee6a4SAndroid Build Coastguard Worker     used_ring: GuestAddress,
79*bb4ee6a4SAndroid Build Coastguard Worker 
80*bb4ee6a4SAndroid Build Coastguard Worker     /// Initial available ring index when the queue is activated.
81*bb4ee6a4SAndroid Build Coastguard Worker     next_avail: Wrapping<u16>,
82*bb4ee6a4SAndroid Build Coastguard Worker 
83*bb4ee6a4SAndroid Build Coastguard Worker     /// Initial used ring index when the queue is activated.
84*bb4ee6a4SAndroid Build Coastguard Worker     next_used: Wrapping<u16>,
85*bb4ee6a4SAndroid Build Coastguard Worker }
86*bb4ee6a4SAndroid Build Coastguard Worker 
87*bb4ee6a4SAndroid Build Coastguard Worker #[derive(Serialize, Deserialize)]
88*bb4ee6a4SAndroid Build Coastguard Worker struct QueueConfigSnapshot {
89*bb4ee6a4SAndroid Build Coastguard Worker     activated: bool,
90*bb4ee6a4SAndroid Build Coastguard Worker     max_size: u16,
91*bb4ee6a4SAndroid Build Coastguard Worker     size: u16,
92*bb4ee6a4SAndroid Build Coastguard Worker     ready: bool,
93*bb4ee6a4SAndroid Build Coastguard Worker     vector: u16,
94*bb4ee6a4SAndroid Build Coastguard Worker     features: u64,
95*bb4ee6a4SAndroid Build Coastguard Worker     acked_features: u64,
96*bb4ee6a4SAndroid Build Coastguard Worker     desc_table: GuestAddress,
97*bb4ee6a4SAndroid Build Coastguard Worker     avail_ring: GuestAddress,
98*bb4ee6a4SAndroid Build Coastguard Worker     used_ring: GuestAddress,
99*bb4ee6a4SAndroid Build Coastguard Worker     next_avail: Wrapping<u16>,
100*bb4ee6a4SAndroid Build Coastguard Worker     next_used: Wrapping<u16>,
101*bb4ee6a4SAndroid Build Coastguard Worker }
102*bb4ee6a4SAndroid Build Coastguard Worker 
103*bb4ee6a4SAndroid Build Coastguard Worker impl QueueConfig {
104*bb4ee6a4SAndroid Build Coastguard Worker     /// Constructs a virtio queue configuration with the given `max_size`.
new(max_size: u16, features: u64) -> Self105*bb4ee6a4SAndroid Build Coastguard Worker     pub fn new(max_size: u16, features: u64) -> Self {
106*bb4ee6a4SAndroid Build Coastguard Worker         assert!(max_size > 0);
107*bb4ee6a4SAndroid Build Coastguard Worker         assert!(max_size <= Queue::MAX_SIZE);
108*bb4ee6a4SAndroid Build Coastguard Worker         QueueConfig {
109*bb4ee6a4SAndroid Build Coastguard Worker             activated: false,
110*bb4ee6a4SAndroid Build Coastguard Worker             max_size,
111*bb4ee6a4SAndroid Build Coastguard Worker             size: max_size,
112*bb4ee6a4SAndroid Build Coastguard Worker             ready: false,
113*bb4ee6a4SAndroid Build Coastguard Worker             vector: VIRTIO_MSI_NO_VECTOR,
114*bb4ee6a4SAndroid Build Coastguard Worker             desc_table: GuestAddress(0),
115*bb4ee6a4SAndroid Build Coastguard Worker             avail_ring: GuestAddress(0),
116*bb4ee6a4SAndroid Build Coastguard Worker             used_ring: GuestAddress(0),
117*bb4ee6a4SAndroid Build Coastguard Worker             features,
118*bb4ee6a4SAndroid Build Coastguard Worker             acked_features: 0,
119*bb4ee6a4SAndroid Build Coastguard Worker             next_used: Wrapping(0),
120*bb4ee6a4SAndroid Build Coastguard Worker             next_avail: Wrapping(0),
121*bb4ee6a4SAndroid Build Coastguard Worker         }
122*bb4ee6a4SAndroid Build Coastguard Worker     }
123*bb4ee6a4SAndroid Build Coastguard Worker 
124*bb4ee6a4SAndroid Build Coastguard Worker     /// Returns the maximum size of this queue.
max_size(&self) -> u16125*bb4ee6a4SAndroid Build Coastguard Worker     pub fn max_size(&self) -> u16 {
126*bb4ee6a4SAndroid Build Coastguard Worker         self.max_size
127*bb4ee6a4SAndroid Build Coastguard Worker     }
128*bb4ee6a4SAndroid Build Coastguard Worker 
129*bb4ee6a4SAndroid Build Coastguard Worker     /// Returns the currently configured size of the queue.
size(&self) -> u16130*bb4ee6a4SAndroid Build Coastguard Worker     pub fn size(&self) -> u16 {
131*bb4ee6a4SAndroid Build Coastguard Worker         self.size
132*bb4ee6a4SAndroid Build Coastguard Worker     }
133*bb4ee6a4SAndroid Build Coastguard Worker 
134*bb4ee6a4SAndroid Build Coastguard Worker     /// Sets the queue size.
set_size(&mut self, val: u16)135*bb4ee6a4SAndroid Build Coastguard Worker     pub fn set_size(&mut self, val: u16) {
136*bb4ee6a4SAndroid Build Coastguard Worker         if self.ready {
137*bb4ee6a4SAndroid Build Coastguard Worker             warn!("ignoring write to size on ready queue");
138*bb4ee6a4SAndroid Build Coastguard Worker             return;
139*bb4ee6a4SAndroid Build Coastguard Worker         }
140*bb4ee6a4SAndroid Build Coastguard Worker 
141*bb4ee6a4SAndroid Build Coastguard Worker         if val > self.max_size {
142*bb4ee6a4SAndroid Build Coastguard Worker             warn!(
143*bb4ee6a4SAndroid Build Coastguard Worker                 "requested queue size {} is larger than max_size {}",
144*bb4ee6a4SAndroid Build Coastguard Worker                 val, self.max_size
145*bb4ee6a4SAndroid Build Coastguard Worker             );
146*bb4ee6a4SAndroid Build Coastguard Worker             return;
147*bb4ee6a4SAndroid Build Coastguard Worker         }
148*bb4ee6a4SAndroid Build Coastguard Worker 
149*bb4ee6a4SAndroid Build Coastguard Worker         self.size = val;
150*bb4ee6a4SAndroid Build Coastguard Worker     }
151*bb4ee6a4SAndroid Build Coastguard Worker 
152*bb4ee6a4SAndroid Build Coastguard Worker     /// Returns the currently configured interrupt vector.
vector(&self) -> u16153*bb4ee6a4SAndroid Build Coastguard Worker     pub fn vector(&self) -> u16 {
154*bb4ee6a4SAndroid Build Coastguard Worker         self.vector
155*bb4ee6a4SAndroid Build Coastguard Worker     }
156*bb4ee6a4SAndroid Build Coastguard Worker 
157*bb4ee6a4SAndroid Build Coastguard Worker     /// Sets the interrupt vector for this queue.
set_vector(&mut self, val: u16)158*bb4ee6a4SAndroid Build Coastguard Worker     pub fn set_vector(&mut self, val: u16) {
159*bb4ee6a4SAndroid Build Coastguard Worker         if self.ready {
160*bb4ee6a4SAndroid Build Coastguard Worker             warn!("ignoring write to vector on ready queue");
161*bb4ee6a4SAndroid Build Coastguard Worker             return;
162*bb4ee6a4SAndroid Build Coastguard Worker         }
163*bb4ee6a4SAndroid Build Coastguard Worker 
164*bb4ee6a4SAndroid Build Coastguard Worker         self.vector = val;
165*bb4ee6a4SAndroid Build Coastguard Worker     }
166*bb4ee6a4SAndroid Build Coastguard Worker 
167*bb4ee6a4SAndroid Build Coastguard Worker     /// Getter for descriptor area
desc_table(&self) -> GuestAddress168*bb4ee6a4SAndroid Build Coastguard Worker     pub fn desc_table(&self) -> GuestAddress {
169*bb4ee6a4SAndroid Build Coastguard Worker         self.desc_table
170*bb4ee6a4SAndroid Build Coastguard Worker     }
171*bb4ee6a4SAndroid Build Coastguard Worker 
172*bb4ee6a4SAndroid Build Coastguard Worker     /// Setter for descriptor area
set_desc_table(&mut self, val: GuestAddress)173*bb4ee6a4SAndroid Build Coastguard Worker     pub fn set_desc_table(&mut self, val: GuestAddress) {
174*bb4ee6a4SAndroid Build Coastguard Worker         if self.ready {
175*bb4ee6a4SAndroid Build Coastguard Worker             warn!("ignoring write to desc_table on ready queue");
176*bb4ee6a4SAndroid Build Coastguard Worker             return;
177*bb4ee6a4SAndroid Build Coastguard Worker         }
178*bb4ee6a4SAndroid Build Coastguard Worker 
179*bb4ee6a4SAndroid Build Coastguard Worker         self.desc_table = val;
180*bb4ee6a4SAndroid Build Coastguard Worker     }
181*bb4ee6a4SAndroid Build Coastguard Worker 
182*bb4ee6a4SAndroid Build Coastguard Worker     /// Getter for driver area
avail_ring(&self) -> GuestAddress183*bb4ee6a4SAndroid Build Coastguard Worker     pub fn avail_ring(&self) -> GuestAddress {
184*bb4ee6a4SAndroid Build Coastguard Worker         self.avail_ring
185*bb4ee6a4SAndroid Build Coastguard Worker     }
186*bb4ee6a4SAndroid Build Coastguard Worker 
187*bb4ee6a4SAndroid Build Coastguard Worker     /// Setter for driver area
set_avail_ring(&mut self, val: GuestAddress)188*bb4ee6a4SAndroid Build Coastguard Worker     pub fn set_avail_ring(&mut self, val: GuestAddress) {
189*bb4ee6a4SAndroid Build Coastguard Worker         if self.ready {
190*bb4ee6a4SAndroid Build Coastguard Worker             warn!("ignoring write to avail_ring on ready queue");
191*bb4ee6a4SAndroid Build Coastguard Worker             return;
192*bb4ee6a4SAndroid Build Coastguard Worker         }
193*bb4ee6a4SAndroid Build Coastguard Worker 
194*bb4ee6a4SAndroid Build Coastguard Worker         self.avail_ring = val;
195*bb4ee6a4SAndroid Build Coastguard Worker     }
196*bb4ee6a4SAndroid Build Coastguard Worker 
197*bb4ee6a4SAndroid Build Coastguard Worker     /// Getter for device area
used_ring(&self) -> GuestAddress198*bb4ee6a4SAndroid Build Coastguard Worker     pub fn used_ring(&self) -> GuestAddress {
199*bb4ee6a4SAndroid Build Coastguard Worker         self.used_ring
200*bb4ee6a4SAndroid Build Coastguard Worker     }
201*bb4ee6a4SAndroid Build Coastguard Worker 
202*bb4ee6a4SAndroid Build Coastguard Worker     /// Setter for device area
set_used_ring(&mut self, val: GuestAddress)203*bb4ee6a4SAndroid Build Coastguard Worker     pub fn set_used_ring(&mut self, val: GuestAddress) {
204*bb4ee6a4SAndroid Build Coastguard Worker         if self.ready {
205*bb4ee6a4SAndroid Build Coastguard Worker             warn!("ignoring write to used_ring on ready queue");
206*bb4ee6a4SAndroid Build Coastguard Worker             return;
207*bb4ee6a4SAndroid Build Coastguard Worker         }
208*bb4ee6a4SAndroid Build Coastguard Worker 
209*bb4ee6a4SAndroid Build Coastguard Worker         self.used_ring = val;
210*bb4ee6a4SAndroid Build Coastguard Worker     }
211*bb4ee6a4SAndroid Build Coastguard Worker 
212*bb4ee6a4SAndroid Build Coastguard Worker     /// Getter for next_avail index
next_avail(&self) -> Wrapping<u16>213*bb4ee6a4SAndroid Build Coastguard Worker     pub fn next_avail(&self) -> Wrapping<u16> {
214*bb4ee6a4SAndroid Build Coastguard Worker         self.next_avail
215*bb4ee6a4SAndroid Build Coastguard Worker     }
216*bb4ee6a4SAndroid Build Coastguard Worker 
217*bb4ee6a4SAndroid Build Coastguard Worker     /// Setter for next_avail index
set_next_avail(&mut self, val: Wrapping<u16>)218*bb4ee6a4SAndroid Build Coastguard Worker     pub fn set_next_avail(&mut self, val: Wrapping<u16>) {
219*bb4ee6a4SAndroid Build Coastguard Worker         if self.ready {
220*bb4ee6a4SAndroid Build Coastguard Worker             warn!("ignoring write to next_avail on ready queue");
221*bb4ee6a4SAndroid Build Coastguard Worker             return;
222*bb4ee6a4SAndroid Build Coastguard Worker         }
223*bb4ee6a4SAndroid Build Coastguard Worker 
224*bb4ee6a4SAndroid Build Coastguard Worker         self.next_avail = val;
225*bb4ee6a4SAndroid Build Coastguard Worker     }
226*bb4ee6a4SAndroid Build Coastguard Worker 
227*bb4ee6a4SAndroid Build Coastguard Worker     /// Getter for next_used index
next_used(&self) -> Wrapping<u16>228*bb4ee6a4SAndroid Build Coastguard Worker     pub fn next_used(&self) -> Wrapping<u16> {
229*bb4ee6a4SAndroid Build Coastguard Worker         self.next_used
230*bb4ee6a4SAndroid Build Coastguard Worker     }
231*bb4ee6a4SAndroid Build Coastguard Worker 
232*bb4ee6a4SAndroid Build Coastguard Worker     /// Setter for next_used index
set_next_used(&mut self, val: Wrapping<u16>)233*bb4ee6a4SAndroid Build Coastguard Worker     pub fn set_next_used(&mut self, val: Wrapping<u16>) {
234*bb4ee6a4SAndroid Build Coastguard Worker         if self.ready {
235*bb4ee6a4SAndroid Build Coastguard Worker             warn!("ignoring write to next_used on ready queue");
236*bb4ee6a4SAndroid Build Coastguard Worker             return;
237*bb4ee6a4SAndroid Build Coastguard Worker         }
238*bb4ee6a4SAndroid Build Coastguard Worker 
239*bb4ee6a4SAndroid Build Coastguard Worker         self.next_used = val;
240*bb4ee6a4SAndroid Build Coastguard Worker     }
241*bb4ee6a4SAndroid Build Coastguard Worker 
242*bb4ee6a4SAndroid Build Coastguard Worker     /// Returns the features that have been acknowledged by the driver.
acked_features(&self) -> u64243*bb4ee6a4SAndroid Build Coastguard Worker     pub fn acked_features(&self) -> u64 {
244*bb4ee6a4SAndroid Build Coastguard Worker         self.acked_features
245*bb4ee6a4SAndroid Build Coastguard Worker     }
246*bb4ee6a4SAndroid Build Coastguard Worker 
247*bb4ee6a4SAndroid Build Coastguard Worker     /// Acknowledges that this set of features should be enabled on this queue.
ack_features(&mut self, features: u64)248*bb4ee6a4SAndroid Build Coastguard Worker     pub fn ack_features(&mut self, features: u64) {
249*bb4ee6a4SAndroid Build Coastguard Worker         self.acked_features |= features & self.features;
250*bb4ee6a4SAndroid Build Coastguard Worker     }
251*bb4ee6a4SAndroid Build Coastguard Worker 
252*bb4ee6a4SAndroid Build Coastguard Worker     /// Return whether the driver has enabled this queue.
ready(&self) -> bool253*bb4ee6a4SAndroid Build Coastguard Worker     pub fn ready(&self) -> bool {
254*bb4ee6a4SAndroid Build Coastguard Worker         self.ready
255*bb4ee6a4SAndroid Build Coastguard Worker     }
256*bb4ee6a4SAndroid Build Coastguard Worker 
257*bb4ee6a4SAndroid Build Coastguard Worker     /// Signal that the driver has completed queue configuration.
set_ready(&mut self, enable: bool)258*bb4ee6a4SAndroid Build Coastguard Worker     pub fn set_ready(&mut self, enable: bool) {
259*bb4ee6a4SAndroid Build Coastguard Worker         self.ready = enable;
260*bb4ee6a4SAndroid Build Coastguard Worker     }
261*bb4ee6a4SAndroid Build Coastguard Worker 
262*bb4ee6a4SAndroid Build Coastguard Worker     /// Convert the queue configuration into an active queue.
activate( &mut self, mem: &GuestMemory, event: Event, interrupt: Interrupt, ) -> Result<Queue>263*bb4ee6a4SAndroid Build Coastguard Worker     pub fn activate(
264*bb4ee6a4SAndroid Build Coastguard Worker         &mut self,
265*bb4ee6a4SAndroid Build Coastguard Worker         mem: &GuestMemory,
266*bb4ee6a4SAndroid Build Coastguard Worker         event: Event,
267*bb4ee6a4SAndroid Build Coastguard Worker         interrupt: Interrupt,
268*bb4ee6a4SAndroid Build Coastguard Worker     ) -> Result<Queue> {
269*bb4ee6a4SAndroid Build Coastguard Worker         if !self.ready {
270*bb4ee6a4SAndroid Build Coastguard Worker             bail!("attempted to activate a non-ready queue");
271*bb4ee6a4SAndroid Build Coastguard Worker         }
272*bb4ee6a4SAndroid Build Coastguard Worker 
273*bb4ee6a4SAndroid Build Coastguard Worker         if self.activated {
274*bb4ee6a4SAndroid Build Coastguard Worker             bail!("queue is already activated");
275*bb4ee6a4SAndroid Build Coastguard Worker         }
276*bb4ee6a4SAndroid Build Coastguard Worker         // If VIRTIO_F_RING_PACKED feature bit is set, create a packed queue, otherwise create a
277*bb4ee6a4SAndroid Build Coastguard Worker         // split queue
278*bb4ee6a4SAndroid Build Coastguard Worker         let queue: Queue = if ((self.acked_features >> VIRTIO_F_RING_PACKED) & 1) != 0 {
279*bb4ee6a4SAndroid Build Coastguard Worker             let pq = PackedQueue::new(self, mem, event, interrupt)
280*bb4ee6a4SAndroid Build Coastguard Worker                 .context("Failed to create a packed queue.")?;
281*bb4ee6a4SAndroid Build Coastguard Worker             Queue::PackedVirtQueue(pq)
282*bb4ee6a4SAndroid Build Coastguard Worker         } else {
283*bb4ee6a4SAndroid Build Coastguard Worker             let sq = SplitQueue::new(self, mem, event, interrupt)
284*bb4ee6a4SAndroid Build Coastguard Worker                 .context("Failed to create a split queue.")?;
285*bb4ee6a4SAndroid Build Coastguard Worker             Queue::SplitVirtQueue(sq)
286*bb4ee6a4SAndroid Build Coastguard Worker         };
287*bb4ee6a4SAndroid Build Coastguard Worker 
288*bb4ee6a4SAndroid Build Coastguard Worker         self.activated = true;
289*bb4ee6a4SAndroid Build Coastguard Worker         Ok(queue)
290*bb4ee6a4SAndroid Build Coastguard Worker     }
291*bb4ee6a4SAndroid Build Coastguard Worker 
292*bb4ee6a4SAndroid Build Coastguard Worker     /// Reset queue to a clean state
reset(&mut self)293*bb4ee6a4SAndroid Build Coastguard Worker     pub fn reset(&mut self) {
294*bb4ee6a4SAndroid Build Coastguard Worker         self.activated = false;
295*bb4ee6a4SAndroid Build Coastguard Worker         self.ready = false;
296*bb4ee6a4SAndroid Build Coastguard Worker         self.size = self.max_size;
297*bb4ee6a4SAndroid Build Coastguard Worker         self.vector = VIRTIO_MSI_NO_VECTOR;
298*bb4ee6a4SAndroid Build Coastguard Worker         self.desc_table = GuestAddress(0);
299*bb4ee6a4SAndroid Build Coastguard Worker         self.avail_ring = GuestAddress(0);
300*bb4ee6a4SAndroid Build Coastguard Worker         self.used_ring = GuestAddress(0);
301*bb4ee6a4SAndroid Build Coastguard Worker         self.next_avail = Wrapping(0);
302*bb4ee6a4SAndroid Build Coastguard Worker         self.next_used = Wrapping(0);
303*bb4ee6a4SAndroid Build Coastguard Worker         self.acked_features = 0;
304*bb4ee6a4SAndroid Build Coastguard Worker     }
305*bb4ee6a4SAndroid Build Coastguard Worker 
306*bb4ee6a4SAndroid Build Coastguard Worker     /// Take snapshot of queue configuration
snapshot(&self) -> Result<serde_json::Value>307*bb4ee6a4SAndroid Build Coastguard Worker     pub fn snapshot(&self) -> Result<serde_json::Value> {
308*bb4ee6a4SAndroid Build Coastguard Worker         serde_json::to_value(QueueConfigSnapshot {
309*bb4ee6a4SAndroid Build Coastguard Worker             activated: self.activated,
310*bb4ee6a4SAndroid Build Coastguard Worker             max_size: self.max_size,
311*bb4ee6a4SAndroid Build Coastguard Worker             size: self.size,
312*bb4ee6a4SAndroid Build Coastguard Worker             ready: self.ready,
313*bb4ee6a4SAndroid Build Coastguard Worker             vector: self.vector,
314*bb4ee6a4SAndroid Build Coastguard Worker             features: self.features,
315*bb4ee6a4SAndroid Build Coastguard Worker             acked_features: self.acked_features,
316*bb4ee6a4SAndroid Build Coastguard Worker             desc_table: self.desc_table,
317*bb4ee6a4SAndroid Build Coastguard Worker             avail_ring: self.avail_ring,
318*bb4ee6a4SAndroid Build Coastguard Worker             used_ring: self.used_ring,
319*bb4ee6a4SAndroid Build Coastguard Worker             next_avail: self.next_avail,
320*bb4ee6a4SAndroid Build Coastguard Worker             next_used: self.next_used,
321*bb4ee6a4SAndroid Build Coastguard Worker         })
322*bb4ee6a4SAndroid Build Coastguard Worker         .context("error serializing")
323*bb4ee6a4SAndroid Build Coastguard Worker     }
324*bb4ee6a4SAndroid Build Coastguard Worker 
325*bb4ee6a4SAndroid Build Coastguard Worker     /// Restore queue configuration from snapshot
restore(&mut self, data: serde_json::Value) -> Result<()>326*bb4ee6a4SAndroid Build Coastguard Worker     pub fn restore(&mut self, data: serde_json::Value) -> Result<()> {
327*bb4ee6a4SAndroid Build Coastguard Worker         let snap: QueueConfigSnapshot =
328*bb4ee6a4SAndroid Build Coastguard Worker             serde_json::from_value(data).context("error deserializing")?;
329*bb4ee6a4SAndroid Build Coastguard Worker         self.activated = snap.activated;
330*bb4ee6a4SAndroid Build Coastguard Worker         self.max_size = snap.max_size;
331*bb4ee6a4SAndroid Build Coastguard Worker         self.size = snap.size;
332*bb4ee6a4SAndroid Build Coastguard Worker         self.ready = snap.ready;
333*bb4ee6a4SAndroid Build Coastguard Worker         self.vector = snap.vector;
334*bb4ee6a4SAndroid Build Coastguard Worker         self.features = snap.features;
335*bb4ee6a4SAndroid Build Coastguard Worker         self.acked_features = snap.acked_features;
336*bb4ee6a4SAndroid Build Coastguard Worker         self.desc_table = snap.desc_table;
337*bb4ee6a4SAndroid Build Coastguard Worker         self.avail_ring = snap.avail_ring;
338*bb4ee6a4SAndroid Build Coastguard Worker         self.used_ring = snap.used_ring;
339*bb4ee6a4SAndroid Build Coastguard Worker         self.next_avail = snap.next_avail;
340*bb4ee6a4SAndroid Build Coastguard Worker         self.next_used = snap.next_used;
341*bb4ee6a4SAndroid Build Coastguard Worker         Ok(())
342*bb4ee6a4SAndroid Build Coastguard Worker     }
343*bb4ee6a4SAndroid Build Coastguard Worker }
344*bb4ee6a4SAndroid Build Coastguard Worker 
345*bb4ee6a4SAndroid Build Coastguard Worker /// Usage: define_queue_method!(method_name, return_type[, mut][, arg1: arg1_type, arg2: arg2_type,
346*bb4ee6a4SAndroid Build Coastguard Worker /// ...])
347*bb4ee6a4SAndroid Build Coastguard Worker ///
348*bb4ee6a4SAndroid Build Coastguard Worker /// - `method_name`: The name of the method to be defined (as an identifier).
349*bb4ee6a4SAndroid Build Coastguard Worker /// - `return_type`: The return type of the method.
350*bb4ee6a4SAndroid Build Coastguard Worker /// - `mut` (optional): Include this keyword if the method requires a mutable reference to `self`
351*bb4ee6a4SAndroid Build Coastguard Worker ///   (`&mut self`).
352*bb4ee6a4SAndroid Build Coastguard Worker /// - `arg1: arg1_type, arg2: arg2_type, ...` (optional): Include method parameters as a
353*bb4ee6a4SAndroid Build Coastguard Worker ///   comma-separated list of `name: type` pairs, if the method takes any arguments.
354*bb4ee6a4SAndroid Build Coastguard Worker macro_rules! define_queue_method {
355*bb4ee6a4SAndroid Build Coastguard Worker     (
356*bb4ee6a4SAndroid Build Coastguard Worker         $(#[$doc:meta])*
357*bb4ee6a4SAndroid Build Coastguard Worker         $method:ident, $return_type:ty, $( $var:ident : $vartype:ty ),*
358*bb4ee6a4SAndroid Build Coastguard Worker     ) => {
359*bb4ee6a4SAndroid Build Coastguard Worker         $(#[$doc])*
360*bb4ee6a4SAndroid Build Coastguard Worker         pub fn $method(&self, $($var: $vartype),*) -> $return_type {
361*bb4ee6a4SAndroid Build Coastguard Worker             match self {
362*bb4ee6a4SAndroid Build Coastguard Worker                 Queue::SplitVirtQueue(sq) => sq.$method($($var),*),
363*bb4ee6a4SAndroid Build Coastguard Worker                 Queue::PackedVirtQueue(pq) => pq.$method($($var),*),
364*bb4ee6a4SAndroid Build Coastguard Worker             }
365*bb4ee6a4SAndroid Build Coastguard Worker         }
366*bb4ee6a4SAndroid Build Coastguard Worker     };
367*bb4ee6a4SAndroid Build Coastguard Worker     (
368*bb4ee6a4SAndroid Build Coastguard Worker         $(#[$doc:meta])*
369*bb4ee6a4SAndroid Build Coastguard Worker         $method:ident, $return_type:ty, mut, $( $var:ident : $vartype:ty ),*
370*bb4ee6a4SAndroid Build Coastguard Worker     ) => {
371*bb4ee6a4SAndroid Build Coastguard Worker         $(#[$doc])*
372*bb4ee6a4SAndroid Build Coastguard Worker         pub fn $method(&mut self, $($var: $vartype),*) -> $return_type {
373*bb4ee6a4SAndroid Build Coastguard Worker             match self {
374*bb4ee6a4SAndroid Build Coastguard Worker                 Queue::SplitVirtQueue(sq) => sq.$method($($var),*),
375*bb4ee6a4SAndroid Build Coastguard Worker                 Queue::PackedVirtQueue(pq) => pq.$method($($var),*),
376*bb4ee6a4SAndroid Build Coastguard Worker             }
377*bb4ee6a4SAndroid Build Coastguard Worker         }
378*bb4ee6a4SAndroid Build Coastguard Worker     };
379*bb4ee6a4SAndroid Build Coastguard Worker }
380*bb4ee6a4SAndroid Build Coastguard Worker 
381*bb4ee6a4SAndroid Build Coastguard Worker /// Virtqueue interface representing different types of virtqueues
382*bb4ee6a4SAndroid Build Coastguard Worker /// The struct of each queue type is wrapped in the enum variants
383*bb4ee6a4SAndroid Build Coastguard Worker #[derive(Debug)]
384*bb4ee6a4SAndroid Build Coastguard Worker pub enum Queue {
385*bb4ee6a4SAndroid Build Coastguard Worker     /// Split virtqueue type in virtio v1.2 spec: <https://docs.oasis-open.org/virtio/virtio/v1.2/csd01/virtio-v1.2-csd01.html#x1-350007>
386*bb4ee6a4SAndroid Build Coastguard Worker     SplitVirtQueue(SplitQueue),
387*bb4ee6a4SAndroid Build Coastguard Worker     /// Packed virtqueue type in virtio v1.2 spec: <https://docs.oasis-open.org/virtio/virtio/v1.2/csd01/virtio-v1.2-csd01.html#x1-720008>
388*bb4ee6a4SAndroid Build Coastguard Worker     PackedVirtQueue(PackedQueue),
389*bb4ee6a4SAndroid Build Coastguard Worker }
390*bb4ee6a4SAndroid Build Coastguard Worker 
391*bb4ee6a4SAndroid Build Coastguard Worker impl Queue {
392*bb4ee6a4SAndroid Build Coastguard Worker     /// Largest valid number of entries in a virtqueue.
393*bb4ee6a4SAndroid Build Coastguard Worker     pub const MAX_SIZE: u16 = 32768;
394*bb4ee6a4SAndroid Build Coastguard Worker 
395*bb4ee6a4SAndroid Build Coastguard Worker     /// Asynchronously read the next descriptor chain from the queue.
396*bb4ee6a4SAndroid Build Coastguard Worker     /// Returns a `DescriptorChain` when it is `await`ed.
next_async( &mut self, eventfd: &mut EventAsync, ) -> std::result::Result<DescriptorChain, AsyncError>397*bb4ee6a4SAndroid Build Coastguard Worker     pub async fn next_async(
398*bb4ee6a4SAndroid Build Coastguard Worker         &mut self,
399*bb4ee6a4SAndroid Build Coastguard Worker         eventfd: &mut EventAsync,
400*bb4ee6a4SAndroid Build Coastguard Worker     ) -> std::result::Result<DescriptorChain, AsyncError> {
401*bb4ee6a4SAndroid Build Coastguard Worker         loop {
402*bb4ee6a4SAndroid Build Coastguard Worker             // Check if there are more descriptors available.
403*bb4ee6a4SAndroid Build Coastguard Worker             if let Some(chain) = self.pop() {
404*bb4ee6a4SAndroid Build Coastguard Worker                 return Ok(chain);
405*bb4ee6a4SAndroid Build Coastguard Worker             }
406*bb4ee6a4SAndroid Build Coastguard Worker             eventfd.next_val().await?;
407*bb4ee6a4SAndroid Build Coastguard Worker         }
408*bb4ee6a4SAndroid Build Coastguard Worker     }
409*bb4ee6a4SAndroid Build Coastguard Worker 
410*bb4ee6a4SAndroid Build Coastguard Worker     /// Get the first available descriptor chain without removing it from the queue.
411*bb4ee6a4SAndroid Build Coastguard Worker     /// Call `pop()` on the returned [`PeekedDescriptorChain`] to remove it from the queue.
peek(&mut self) -> Option<PeekedDescriptorChain>412*bb4ee6a4SAndroid Build Coastguard Worker     pub fn peek(&mut self) -> Option<PeekedDescriptorChain> {
413*bb4ee6a4SAndroid Build Coastguard Worker         let desc_chain = match self {
414*bb4ee6a4SAndroid Build Coastguard Worker             Queue::SplitVirtQueue(q) => q.peek(),
415*bb4ee6a4SAndroid Build Coastguard Worker             Queue::PackedVirtQueue(q) => q.peek(),
416*bb4ee6a4SAndroid Build Coastguard Worker         }?;
417*bb4ee6a4SAndroid Build Coastguard Worker 
418*bb4ee6a4SAndroid Build Coastguard Worker         Some(PeekedDescriptorChain::new(self, desc_chain))
419*bb4ee6a4SAndroid Build Coastguard Worker     }
420*bb4ee6a4SAndroid Build Coastguard Worker 
421*bb4ee6a4SAndroid Build Coastguard Worker     /// If a new DescriptorChain is available, returns one and removes it from the queue.
pop(&mut self) -> Option<DescriptorChain>422*bb4ee6a4SAndroid Build Coastguard Worker     pub fn pop(&mut self) -> Option<DescriptorChain> {
423*bb4ee6a4SAndroid Build Coastguard Worker         self.peek().map(PeekedDescriptorChain::pop)
424*bb4ee6a4SAndroid Build Coastguard Worker     }
425*bb4ee6a4SAndroid Build Coastguard Worker 
426*bb4ee6a4SAndroid Build Coastguard Worker     /// Returns `None` if stop_rx receives a value; otherwise returns the result
427*bb4ee6a4SAndroid Build Coastguard Worker     /// of waiting for the next descriptor.
next_async_interruptable( &mut self, queue_event: &mut EventAsync, mut stop_rx: &mut oneshot::Receiver<()>, ) -> std::result::Result<Option<DescriptorChain>, AsyncError>428*bb4ee6a4SAndroid Build Coastguard Worker     pub async fn next_async_interruptable(
429*bb4ee6a4SAndroid Build Coastguard Worker         &mut self,
430*bb4ee6a4SAndroid Build Coastguard Worker         queue_event: &mut EventAsync,
431*bb4ee6a4SAndroid Build Coastguard Worker         mut stop_rx: &mut oneshot::Receiver<()>,
432*bb4ee6a4SAndroid Build Coastguard Worker     ) -> std::result::Result<Option<DescriptorChain>, AsyncError> {
433*bb4ee6a4SAndroid Build Coastguard Worker         select_biased! {
434*bb4ee6a4SAndroid Build Coastguard Worker             avail_desc_res = self.next_async(queue_event).fuse() => {
435*bb4ee6a4SAndroid Build Coastguard Worker                 Ok(Some(avail_desc_res?))
436*bb4ee6a4SAndroid Build Coastguard Worker             }
437*bb4ee6a4SAndroid Build Coastguard Worker             _ = stop_rx => Ok(None),
438*bb4ee6a4SAndroid Build Coastguard Worker         }
439*bb4ee6a4SAndroid Build Coastguard Worker     }
440*bb4ee6a4SAndroid Build Coastguard Worker 
441*bb4ee6a4SAndroid Build Coastguard Worker     /// inject interrupt into guest on this queue
442*bb4ee6a4SAndroid Build Coastguard Worker     /// return true: interrupt is injected into guest for this queue
443*bb4ee6a4SAndroid Build Coastguard Worker     ///        false: interrupt isn't injected
trigger_interrupt(&mut self) -> bool444*bb4ee6a4SAndroid Build Coastguard Worker     pub fn trigger_interrupt(&mut self) -> bool {
445*bb4ee6a4SAndroid Build Coastguard Worker         match self {
446*bb4ee6a4SAndroid Build Coastguard Worker             Queue::SplitVirtQueue(sq) => sq.trigger_interrupt(),
447*bb4ee6a4SAndroid Build Coastguard Worker             Queue::PackedVirtQueue(pq) => pq.trigger_interrupt(),
448*bb4ee6a4SAndroid Build Coastguard Worker         }
449*bb4ee6a4SAndroid Build Coastguard Worker     }
450*bb4ee6a4SAndroid Build Coastguard Worker 
451*bb4ee6a4SAndroid Build Coastguard Worker     /// Restore queue from snapshot
restore( queue_config: &QueueConfig, queue_value: serde_json::Value, mem: &GuestMemory, event: Event, interrupt: Interrupt, ) -> anyhow::Result<Queue>452*bb4ee6a4SAndroid Build Coastguard Worker     pub fn restore(
453*bb4ee6a4SAndroid Build Coastguard Worker         queue_config: &QueueConfig,
454*bb4ee6a4SAndroid Build Coastguard Worker         queue_value: serde_json::Value,
455*bb4ee6a4SAndroid Build Coastguard Worker         mem: &GuestMemory,
456*bb4ee6a4SAndroid Build Coastguard Worker         event: Event,
457*bb4ee6a4SAndroid Build Coastguard Worker         interrupt: Interrupt,
458*bb4ee6a4SAndroid Build Coastguard Worker     ) -> anyhow::Result<Queue> {
459*bb4ee6a4SAndroid Build Coastguard Worker         if queue_config.acked_features & 1 << VIRTIO_F_RING_PACKED != 0 {
460*bb4ee6a4SAndroid Build Coastguard Worker             PackedQueue::restore(queue_value, mem, event, interrupt).map(Queue::PackedVirtQueue)
461*bb4ee6a4SAndroid Build Coastguard Worker         } else {
462*bb4ee6a4SAndroid Build Coastguard Worker             SplitQueue::restore(queue_value, mem, event, interrupt).map(Queue::SplitVirtQueue)
463*bb4ee6a4SAndroid Build Coastguard Worker         }
464*bb4ee6a4SAndroid Build Coastguard Worker     }
465*bb4ee6a4SAndroid Build Coastguard Worker 
466*bb4ee6a4SAndroid Build Coastguard Worker     /// "Reclaim" a queue that was given to a vhost-user backend and is now being taken back using
467*bb4ee6a4SAndroid Build Coastguard Worker     /// VHOST_USER_GET_VRING_BASE.
468*bb4ee6a4SAndroid Build Coastguard Worker     ///
469*bb4ee6a4SAndroid Build Coastguard Worker     /// The `Queue` will have stale fields if the vhost-user backend fulfilled any virtqueue
470*bb4ee6a4SAndroid Build Coastguard Worker     /// requests. This function updates the `Queue` to pick up where the backend left off.
vhost_user_reclaim(&mut self, vring_base: u16)471*bb4ee6a4SAndroid Build Coastguard Worker     pub fn vhost_user_reclaim(&mut self, vring_base: u16) {
472*bb4ee6a4SAndroid Build Coastguard Worker         match self {
473*bb4ee6a4SAndroid Build Coastguard Worker             Queue::SplitVirtQueue(q) => q.vhost_user_reclaim(vring_base),
474*bb4ee6a4SAndroid Build Coastguard Worker             Queue::PackedVirtQueue(q) => q.vhost_user_reclaim(vring_base),
475*bb4ee6a4SAndroid Build Coastguard Worker         }
476*bb4ee6a4SAndroid Build Coastguard Worker     }
477*bb4ee6a4SAndroid Build Coastguard Worker 
478*bb4ee6a4SAndroid Build Coastguard Worker     /// Getter for the next index of the available ring that device will process.
479*bb4ee6a4SAndroid Build Coastguard Worker     ///
480*bb4ee6a4SAndroid Build Coastguard Worker     /// Not to be confused with the available ring's index field, which is the next index for the
481*bb4ee6a4SAndroid Build Coastguard Worker     /// driver to fill.
next_avail_to_process(&self) -> u16482*bb4ee6a4SAndroid Build Coastguard Worker     pub fn next_avail_to_process(&self) -> u16 {
483*bb4ee6a4SAndroid Build Coastguard Worker         match self {
484*bb4ee6a4SAndroid Build Coastguard Worker             Queue::SplitVirtQueue(q) => q.next_avail_to_process(),
485*bb4ee6a4SAndroid Build Coastguard Worker             Queue::PackedVirtQueue(q) => q.next_avail_to_process(),
486*bb4ee6a4SAndroid Build Coastguard Worker         }
487*bb4ee6a4SAndroid Build Coastguard Worker     }
488*bb4ee6a4SAndroid Build Coastguard Worker 
489*bb4ee6a4SAndroid Build Coastguard Worker     define_queue_method!(
490*bb4ee6a4SAndroid Build Coastguard Worker         /// Getter for vector field
491*bb4ee6a4SAndroid Build Coastguard Worker         vector,
492*bb4ee6a4SAndroid Build Coastguard Worker         u16,
493*bb4ee6a4SAndroid Build Coastguard Worker     );
494*bb4ee6a4SAndroid Build Coastguard Worker 
495*bb4ee6a4SAndroid Build Coastguard Worker     define_queue_method!(
496*bb4ee6a4SAndroid Build Coastguard Worker         /// Getter for descriptor area
497*bb4ee6a4SAndroid Build Coastguard Worker         desc_table,
498*bb4ee6a4SAndroid Build Coastguard Worker         GuestAddress,
499*bb4ee6a4SAndroid Build Coastguard Worker     );
500*bb4ee6a4SAndroid Build Coastguard Worker 
501*bb4ee6a4SAndroid Build Coastguard Worker     define_queue_method!(
502*bb4ee6a4SAndroid Build Coastguard Worker         /// Getter for driver area
503*bb4ee6a4SAndroid Build Coastguard Worker         avail_ring,
504*bb4ee6a4SAndroid Build Coastguard Worker         GuestAddress,
505*bb4ee6a4SAndroid Build Coastguard Worker     );
506*bb4ee6a4SAndroid Build Coastguard Worker 
507*bb4ee6a4SAndroid Build Coastguard Worker     define_queue_method!(
508*bb4ee6a4SAndroid Build Coastguard Worker         /// Getter for device area
509*bb4ee6a4SAndroid Build Coastguard Worker         used_ring,
510*bb4ee6a4SAndroid Build Coastguard Worker         GuestAddress,
511*bb4ee6a4SAndroid Build Coastguard Worker     );
512*bb4ee6a4SAndroid Build Coastguard Worker 
513*bb4ee6a4SAndroid Build Coastguard Worker     define_queue_method!(
514*bb4ee6a4SAndroid Build Coastguard Worker         /// Return the actual size of the queue, as the driver may not set up a
515*bb4ee6a4SAndroid Build Coastguard Worker         /// queue as big as the device allows.
516*bb4ee6a4SAndroid Build Coastguard Worker         size,
517*bb4ee6a4SAndroid Build Coastguard Worker         u16,
518*bb4ee6a4SAndroid Build Coastguard Worker     );
519*bb4ee6a4SAndroid Build Coastguard Worker 
520*bb4ee6a4SAndroid Build Coastguard Worker     define_queue_method!(
521*bb4ee6a4SAndroid Build Coastguard Worker         /// Get a reference to the queue's event.
522*bb4ee6a4SAndroid Build Coastguard Worker         event,
523*bb4ee6a4SAndroid Build Coastguard Worker         &Event,
524*bb4ee6a4SAndroid Build Coastguard Worker     );
525*bb4ee6a4SAndroid Build Coastguard Worker 
526*bb4ee6a4SAndroid Build Coastguard Worker     define_queue_method!(
527*bb4ee6a4SAndroid Build Coastguard Worker         /// Get a reference to the queue's interrupt.
528*bb4ee6a4SAndroid Build Coastguard Worker         interrupt,
529*bb4ee6a4SAndroid Build Coastguard Worker         &Interrupt,
530*bb4ee6a4SAndroid Build Coastguard Worker     );
531*bb4ee6a4SAndroid Build Coastguard Worker 
532*bb4ee6a4SAndroid Build Coastguard Worker     define_queue_method!(
533*bb4ee6a4SAndroid Build Coastguard Worker         /// Puts an available descriptor head into the used ring for use by the guest.
534*bb4ee6a4SAndroid Build Coastguard Worker         add_used,
535*bb4ee6a4SAndroid Build Coastguard Worker         (),
536*bb4ee6a4SAndroid Build Coastguard Worker         mut,
537*bb4ee6a4SAndroid Build Coastguard Worker         desc_chain: DescriptorChain,
538*bb4ee6a4SAndroid Build Coastguard Worker         len: u32
539*bb4ee6a4SAndroid Build Coastguard Worker     );
540*bb4ee6a4SAndroid Build Coastguard Worker 
541*bb4ee6a4SAndroid Build Coastguard Worker     define_queue_method!(
542*bb4ee6a4SAndroid Build Coastguard Worker         /// Take snapshot of queue's current status
543*bb4ee6a4SAndroid Build Coastguard Worker         snapshot,
544*bb4ee6a4SAndroid Build Coastguard Worker         Result<serde_json::Value>,
545*bb4ee6a4SAndroid Build Coastguard Worker     );
546*bb4ee6a4SAndroid Build Coastguard Worker }
547*bb4ee6a4SAndroid Build Coastguard Worker 
548*bb4ee6a4SAndroid Build Coastguard Worker /// A `DescriptorChain` that has been peeked from a `Queue` but not popped yet.
549*bb4ee6a4SAndroid Build Coastguard Worker ///
550*bb4ee6a4SAndroid Build Coastguard Worker /// Call [`pop()`](Self::pop) to pop this descriptor chain from the `Queue` and receive the
551*bb4ee6a4SAndroid Build Coastguard Worker /// contained `DescriptorChain` object.
552*bb4ee6a4SAndroid Build Coastguard Worker ///
553*bb4ee6a4SAndroid Build Coastguard Worker /// This object holds a mutable reference to the `Queue` to ensure it is not possible to pop or peek
554*bb4ee6a4SAndroid Build Coastguard Worker /// another descriptor while a peek is already active. Either `pop()` or drop this object before
555*bb4ee6a4SAndroid Build Coastguard Worker /// attempting to manipulate the `Queue` again.
556*bb4ee6a4SAndroid Build Coastguard Worker pub struct PeekedDescriptorChain<'q> {
557*bb4ee6a4SAndroid Build Coastguard Worker     queue: &'q mut Queue,
558*bb4ee6a4SAndroid Build Coastguard Worker     desc_chain: DescriptorChain,
559*bb4ee6a4SAndroid Build Coastguard Worker }
560*bb4ee6a4SAndroid Build Coastguard Worker 
561*bb4ee6a4SAndroid Build Coastguard Worker impl<'q> PeekedDescriptorChain<'q> {
562*bb4ee6a4SAndroid Build Coastguard Worker     /// Create a `PeekedDescriptorChain` that holds a mutable reference to its `Queue`.
563*bb4ee6a4SAndroid Build Coastguard Worker     /// Use [`Queue::peek()`] rather than calling this function.
new(queue: &'q mut Queue, desc_chain: DescriptorChain) -> Self564*bb4ee6a4SAndroid Build Coastguard Worker     fn new(queue: &'q mut Queue, desc_chain: DescriptorChain) -> Self {
565*bb4ee6a4SAndroid Build Coastguard Worker         PeekedDescriptorChain { queue, desc_chain }
566*bb4ee6a4SAndroid Build Coastguard Worker     }
567*bb4ee6a4SAndroid Build Coastguard Worker 
568*bb4ee6a4SAndroid Build Coastguard Worker     /// Pop this descriptor chain from the queue.
pop(self) -> DescriptorChain569*bb4ee6a4SAndroid Build Coastguard Worker     pub fn pop(self) -> DescriptorChain {
570*bb4ee6a4SAndroid Build Coastguard Worker         match self.queue {
571*bb4ee6a4SAndroid Build Coastguard Worker             Queue::SplitVirtQueue(q) => q.pop_peeked(&self.desc_chain),
572*bb4ee6a4SAndroid Build Coastguard Worker             Queue::PackedVirtQueue(q) => q.pop_peeked(&self.desc_chain),
573*bb4ee6a4SAndroid Build Coastguard Worker         }
574*bb4ee6a4SAndroid Build Coastguard Worker         self.desc_chain
575*bb4ee6a4SAndroid Build Coastguard Worker     }
576*bb4ee6a4SAndroid Build Coastguard Worker }
577*bb4ee6a4SAndroid Build Coastguard Worker 
578*bb4ee6a4SAndroid Build Coastguard Worker impl Deref for PeekedDescriptorChain<'_> {
579*bb4ee6a4SAndroid Build Coastguard Worker     type Target = DescriptorChain;
580*bb4ee6a4SAndroid Build Coastguard Worker 
deref(&self) -> &Self::Target581*bb4ee6a4SAndroid Build Coastguard Worker     fn deref(&self) -> &Self::Target {
582*bb4ee6a4SAndroid Build Coastguard Worker         &self.desc_chain
583*bb4ee6a4SAndroid Build Coastguard Worker     }
584*bb4ee6a4SAndroid Build Coastguard Worker }
585*bb4ee6a4SAndroid Build Coastguard Worker 
586*bb4ee6a4SAndroid Build Coastguard Worker impl DerefMut for PeekedDescriptorChain<'_> {
deref_mut(&mut self) -> &mut Self::Target587*bb4ee6a4SAndroid Build Coastguard Worker     fn deref_mut(&mut self) -> &mut Self::Target {
588*bb4ee6a4SAndroid Build Coastguard Worker         &mut self.desc_chain
589*bb4ee6a4SAndroid Build Coastguard Worker     }
590*bb4ee6a4SAndroid Build Coastguard Worker }
591