1#![deny(missing_docs)]
8
9use std::ops::Deref;
10use std::ops::DerefMut;
11
12pub mod packed_descriptor_chain;
13mod packed_queue;
14pub mod split_descriptor_chain;
15mod split_queue;
16
17use std::num::Wrapping;
18
19use anyhow::bail;
20use anyhow::Context;
21use anyhow::Result;
22use base::warn;
23use base::Event;
24use cros_async::AsyncError;
25use cros_async::EventAsync;
26use futures::channel::oneshot;
27use futures::select_biased;
28use futures::FutureExt;
29use packed_queue::PackedQueue;
30use serde::Deserialize;
31use serde::Serialize;
32use snapshot::AnySnapshot;
33use split_queue::SplitQueue;
34use virtio_sys::virtio_config::VIRTIO_F_RING_PACKED;
35use vm_memory::GuestAddress;
36use vm_memory::GuestMemory;
37
38use crate::virtio::DescriptorChain;
39use crate::virtio::Interrupt;
40use crate::virtio::VIRTIO_MSI_NO_VECTOR;
41
42pub struct QueueConfig {
46 activated: bool,
48
49 max_size: u16,
51
52 size: u16,
56
57 ready: bool,
59
60 vector: u16,
62
63 features: u64,
66
67 acked_features: u64,
69
70 desc_table: GuestAddress,
72
73 avail_ring: GuestAddress,
77
78 used_ring: GuestAddress,
80
81 next_avail: Wrapping<u16>,
83
84 next_used: Wrapping<u16>,
86}
87
88#[derive(Serialize, Deserialize)]
89struct QueueConfigSnapshot {
90 activated: bool,
91 max_size: u16,
92 size: u16,
93 ready: bool,
94 vector: u16,
95 features: u64,
96 acked_features: u64,
97 desc_table: GuestAddress,
98 avail_ring: GuestAddress,
99 used_ring: GuestAddress,
100 next_avail: Wrapping<u16>,
101 next_used: Wrapping<u16>,
102}
103
104impl QueueConfig {
105 pub fn new(max_size: u16, features: u64) -> Self {
107 assert!(max_size > 0);
108 assert!(max_size <= Queue::MAX_SIZE);
109 QueueConfig {
110 activated: false,
111 max_size,
112 size: max_size,
113 ready: false,
114 vector: VIRTIO_MSI_NO_VECTOR,
115 desc_table: GuestAddress(0),
116 avail_ring: GuestAddress(0),
117 used_ring: GuestAddress(0),
118 features,
119 acked_features: 0,
120 next_used: Wrapping(0),
121 next_avail: Wrapping(0),
122 }
123 }
124
125 pub fn max_size(&self) -> u16 {
127 self.max_size
128 }
129
130 pub fn size(&self) -> u16 {
132 self.size
133 }
134
135 pub fn set_size(&mut self, val: u16) {
137 if self.ready {
138 warn!("ignoring write to size on ready queue");
139 return;
140 }
141
142 if val > self.max_size {
143 warn!(
144 "requested queue size {} is larger than max_size {}",
145 val, self.max_size
146 );
147 return;
148 }
149
150 self.size = val;
151 }
152
153 pub fn vector(&self) -> u16 {
155 self.vector
156 }
157
158 pub fn set_vector(&mut self, val: u16) {
160 if self.ready {
161 warn!("ignoring write to vector on ready queue");
162 return;
163 }
164
165 self.vector = val;
166 }
167
168 pub fn desc_table(&self) -> GuestAddress {
170 self.desc_table
171 }
172
173 pub fn set_desc_table(&mut self, val: GuestAddress) {
175 if self.ready {
176 warn!("ignoring write to desc_table on ready queue");
177 return;
178 }
179
180 self.desc_table = val;
181 }
182
183 pub fn avail_ring(&self) -> GuestAddress {
185 self.avail_ring
186 }
187
188 pub fn set_avail_ring(&mut self, val: GuestAddress) {
190 if self.ready {
191 warn!("ignoring write to avail_ring on ready queue");
192 return;
193 }
194
195 self.avail_ring = val;
196 }
197
198 pub fn used_ring(&self) -> GuestAddress {
200 self.used_ring
201 }
202
203 pub fn set_used_ring(&mut self, val: GuestAddress) {
205 if self.ready {
206 warn!("ignoring write to used_ring on ready queue");
207 return;
208 }
209
210 self.used_ring = val;
211 }
212
213 pub fn next_avail(&self) -> Wrapping<u16> {
215 self.next_avail
216 }
217
218 pub fn set_next_avail(&mut self, val: Wrapping<u16>) {
220 if self.ready {
221 warn!("ignoring write to next_avail on ready queue");
222 return;
223 }
224
225 self.next_avail = val;
226 }
227
228 pub fn next_used(&self) -> Wrapping<u16> {
230 self.next_used
231 }
232
233 pub fn set_next_used(&mut self, val: Wrapping<u16>) {
235 if self.ready {
236 warn!("ignoring write to next_used on ready queue");
237 return;
238 }
239
240 self.next_used = val;
241 }
242
243 pub fn acked_features(&self) -> u64 {
245 self.acked_features
246 }
247
248 pub fn ack_features(&mut self, features: u64) {
250 self.acked_features |= features & self.features;
251 }
252
253 pub fn ready(&self) -> bool {
255 self.ready
256 }
257
258 pub fn set_ready(&mut self, enable: bool) {
260 self.ready = enable;
261 }
262
263 pub fn activate(
265 &mut self,
266 mem: &GuestMemory,
267 event: Event,
268 interrupt: Interrupt,
269 ) -> Result<Queue> {
270 if !self.ready {
271 bail!("attempted to activate a non-ready queue");
272 }
273
274 if self.activated {
275 bail!("queue is already activated");
276 }
277 let queue: Queue = if ((self.acked_features >> VIRTIO_F_RING_PACKED) & 1) != 0 {
280 let pq = PackedQueue::new(self, mem, event, interrupt)
281 .context("Failed to create a packed queue.")?;
282 Queue::PackedVirtQueue(pq)
283 } else {
284 let sq = SplitQueue::new(self, mem, event, interrupt)
285 .context("Failed to create a split queue.")?;
286 Queue::SplitVirtQueue(sq)
287 };
288
289 self.activated = true;
290 Ok(queue)
291 }
292
293 pub fn reset(&mut self) {
295 self.activated = false;
296 self.ready = false;
297 self.size = self.max_size;
298 self.vector = VIRTIO_MSI_NO_VECTOR;
299 self.desc_table = GuestAddress(0);
300 self.avail_ring = GuestAddress(0);
301 self.used_ring = GuestAddress(0);
302 self.next_avail = Wrapping(0);
303 self.next_used = Wrapping(0);
304 self.acked_features = 0;
305 }
306
307 pub fn snapshot(&self) -> Result<AnySnapshot> {
309 AnySnapshot::to_any(QueueConfigSnapshot {
310 activated: self.activated,
311 max_size: self.max_size,
312 size: self.size,
313 ready: self.ready,
314 vector: self.vector,
315 features: self.features,
316 acked_features: self.acked_features,
317 desc_table: self.desc_table,
318 avail_ring: self.avail_ring,
319 used_ring: self.used_ring,
320 next_avail: self.next_avail,
321 next_used: self.next_used,
322 })
323 .context("error serializing")
324 }
325
326 pub fn restore(&mut self, data: AnySnapshot) -> Result<()> {
328 let snap: QueueConfigSnapshot =
329 AnySnapshot::from_any(data).context("error deserializing")?;
330 self.activated = snap.activated;
331 self.max_size = snap.max_size;
332 self.size = snap.size;
333 self.ready = snap.ready;
334 self.vector = snap.vector;
335 self.features = snap.features;
336 self.acked_features = snap.acked_features;
337 self.desc_table = snap.desc_table;
338 self.avail_ring = snap.avail_ring;
339 self.used_ring = snap.used_ring;
340 self.next_avail = snap.next_avail;
341 self.next_used = snap.next_used;
342 Ok(())
343 }
344}
345
346macro_rules! define_queue_method {
356 (
357 $(#[$doc:meta])*
358 $method:ident, $return_type:ty, $( $var:ident : $vartype:ty ),*
359 ) => {
360 $(#[$doc])*
361 pub fn $method(&self, $($var: $vartype),*) -> $return_type {
362 match self {
363 Queue::SplitVirtQueue(sq) => sq.$method($($var),*),
364 Queue::PackedVirtQueue(pq) => pq.$method($($var),*),
365 }
366 }
367 };
368 (
369 $(#[$doc:meta])*
370 $method:ident, $return_type:ty, mut, $( $var:ident : $vartype:ty ),*
371 ) => {
372 $(#[$doc])*
373 pub fn $method(&mut self, $($var: $vartype),*) -> $return_type {
374 match self {
375 Queue::SplitVirtQueue(sq) => sq.$method($($var),*),
376 Queue::PackedVirtQueue(pq) => pq.$method($($var),*),
377 }
378 }
379 };
380}
381
382#[derive(Debug)]
385pub enum Queue {
386 SplitVirtQueue(SplitQueue),
388 PackedVirtQueue(PackedQueue),
390}
391
392impl Queue {
393 pub const MAX_SIZE: u16 = 32768;
395
396 pub async fn next_async(
399 &mut self,
400 eventfd: &mut EventAsync,
401 ) -> std::result::Result<DescriptorChain, AsyncError> {
402 loop {
403 if let Some(chain) = self.pop() {
405 return Ok(chain);
406 }
407 eventfd.next_val().await?;
408 }
409 }
410
411 pub fn peek(&mut self) -> Option<PeekedDescriptorChain> {
414 let desc_chain = match self {
415 Queue::SplitVirtQueue(q) => q.peek(),
416 Queue::PackedVirtQueue(q) => q.peek(),
417 }?;
418
419 Some(PeekedDescriptorChain::new(self, desc_chain))
420 }
421
422 pub fn pop(&mut self) -> Option<DescriptorChain> {
424 self.peek().map(PeekedDescriptorChain::pop)
425 }
426
427 pub fn try_pop_length(&mut self, request_length: usize) -> Option<Vec<DescriptorChain>> {
430 match self {
431 Queue::SplitVirtQueue(q) => q.try_pop_length(request_length),
432 Queue::PackedVirtQueue(_q) => {
433 unimplemented!()
434 }
435 }
436 }
437
438 pub async fn next_async_interruptable(
441 &mut self,
442 queue_event: &mut EventAsync,
443 mut stop_rx: &mut oneshot::Receiver<()>,
444 ) -> std::result::Result<Option<DescriptorChain>, AsyncError> {
445 select_biased! {
446 avail_desc_res = self.next_async(queue_event).fuse() => {
447 Ok(Some(avail_desc_res?))
448 }
449 _ = stop_rx => Ok(None),
450 }
451 }
452
453 pub fn trigger_interrupt(&mut self) -> bool {
457 match self {
458 Queue::SplitVirtQueue(sq) => sq.trigger_interrupt(),
459 Queue::PackedVirtQueue(pq) => pq.trigger_interrupt(),
460 }
461 }
462
463 pub fn restore(
465 queue_config: &QueueConfig,
466 queue_value: AnySnapshot,
467 mem: &GuestMemory,
468 event: Event,
469 interrupt: Interrupt,
470 ) -> anyhow::Result<Queue> {
471 if queue_config.acked_features & 1 << VIRTIO_F_RING_PACKED != 0 {
472 PackedQueue::restore(queue_value, mem, event, interrupt).map(Queue::PackedVirtQueue)
473 } else {
474 SplitQueue::restore(queue_value, mem, event, interrupt).map(Queue::SplitVirtQueue)
475 }
476 }
477
478 pub fn vhost_user_reclaim(&mut self, vring_base: u16) {
484 match self {
485 Queue::SplitVirtQueue(q) => q.vhost_user_reclaim(vring_base),
486 Queue::PackedVirtQueue(q) => q.vhost_user_reclaim(vring_base),
487 }
488 }
489
490 pub fn next_avail_to_process(&self) -> u16 {
495 match self {
496 Queue::SplitVirtQueue(q) => q.next_avail_to_process(),
497 Queue::PackedVirtQueue(q) => q.next_avail_to_process(),
498 }
499 }
500
501 define_queue_method!(
502 vector,
504 u16,
505 );
506
507 define_queue_method!(
508 desc_table,
510 GuestAddress,
511 );
512
513 define_queue_method!(
514 avail_ring,
516 GuestAddress,
517 );
518
519 define_queue_method!(
520 used_ring,
522 GuestAddress,
523 );
524
525 define_queue_method!(
526 size,
529 u16,
530 );
531
532 define_queue_method!(
533 event,
535 &Event,
536 );
537
538 define_queue_method!(
539 interrupt,
541 &Interrupt,
542 );
543
544 pub fn add_used(&mut self, desc_chain: DescriptorChain) {
547 let len: u32 = desc_chain.writer.bytes_written().try_into().unwrap();
548 self.add_used_with_bytes_written(desc_chain, len);
549 }
550
551 pub fn add_used_with_bytes_written(&mut self, desc_chain: DescriptorChain, len: u32) {
554 let iter = std::iter::once((desc_chain, len));
555 match self {
556 Queue::SplitVirtQueue(q) => q.add_used_with_bytes_written_batch(iter),
557 Queue::PackedVirtQueue(q) => q.add_used_with_bytes_written_batch(iter),
558 }
559 }
560
561 pub fn add_used_batch(&mut self, desc_chains: impl IntoIterator<Item = DescriptorChain>) {
564 let iter = desc_chains.into_iter().map(|desc_chain| {
565 let len: u32 = desc_chain.writer.bytes_written().try_into().unwrap();
566 (desc_chain, len)
567 });
568 match self {
569 Queue::SplitVirtQueue(q) => q.add_used_with_bytes_written_batch(iter),
570 Queue::PackedVirtQueue(q) => q.add_used_with_bytes_written_batch(iter),
571 }
572 }
573
574 define_queue_method!(
575 snapshot,
577 Result<AnySnapshot>,
578 );
579}
580
581pub struct PeekedDescriptorChain<'q> {
590 queue: &'q mut Queue,
591 desc_chain: DescriptorChain,
592}
593
594impl<'q> PeekedDescriptorChain<'q> {
595 fn new(queue: &'q mut Queue, desc_chain: DescriptorChain) -> Self {
598 PeekedDescriptorChain { queue, desc_chain }
599 }
600
601 pub fn pop(self) -> DescriptorChain {
603 match self.queue {
604 Queue::SplitVirtQueue(q) => q.pop_peeked(&self.desc_chain),
605 Queue::PackedVirtQueue(q) => q.pop_peeked(&self.desc_chain),
606 }
607 self.desc_chain
608 }
609}
610
611impl Deref for PeekedDescriptorChain<'_> {
612 type Target = DescriptorChain;
613
614 fn deref(&self) -> &Self::Target {
615 &self.desc_chain
616 }
617}
618
619impl DerefMut for PeekedDescriptorChain<'_> {
620 fn deref_mut(&mut self) -> &mut Self::Target {
621 &mut self.desc_chain
622 }
623}