Skip to main content

virtio_queue/
queue.rs

1// Copyright 2022 Amazon.com, Inc. or its affiliates. All Rights Reserved.
2// Copyright (C) 2020-2021 Alibaba Cloud. All rights reserved.
3// Copyright © 2019 Intel Corporation.
4// Portions Copyright 2017 The Chromium OS Authors. All rights reserved.
5// Use of this source code is governed by a BSD-style license that can be
6// found in the LICENSE-BSD-3-Clause file.
7//
8// SPDX-License-Identifier: Apache-2.0 AND BSD-3-Clause
9
10use std::mem::size_of;
11use std::num::Wrapping;
12use std::ops::Deref;
13use std::sync::atomic::{fence, Ordering};
14
15use vm_memory::{Address, Bytes, GuestAddress, GuestMemory, Permissions};
16
17use crate::defs::{
18    DEFAULT_AVAIL_RING_ADDR, DEFAULT_DESC_TABLE_ADDR, DEFAULT_USED_RING_ADDR,
19    VIRTQ_AVAIL_ELEMENT_SIZE, VIRTQ_AVAIL_RING_HEADER_SIZE, VIRTQ_AVAIL_RING_META_SIZE,
20    VIRTQ_USED_ELEMENT_SIZE, VIRTQ_USED_RING_HEADER_SIZE, VIRTQ_USED_RING_META_SIZE,
21};
22use crate::desc::{split::VirtqUsedElem, RawDescriptor};
23use crate::{error, DescriptorChain, Error, QueueGuard, QueueOwnedT, QueueState, QueueT};
24use virtio_bindings::bindings::virtio_ring::VRING_USED_F_NO_NOTIFY;
25
26#[cfg(kani)]
27mod verification;
28
29/// The maximum queue size as defined in the Virtio Spec.
30pub const MAX_QUEUE_SIZE: u16 = 32768;
31
32/// Struct to maintain information and manipulate a virtio queue.
33///
34/// # Example
35///
36/// ```rust
37/// use virtio_queue::{Queue, QueueOwnedT, QueueT};
38/// use vm_memory::{Bytes, GuestAddress, GuestAddressSpace, GuestMemoryMmap};
39///
40/// let m = GuestMemoryMmap::<()>::from_ranges(&[(GuestAddress(0), 0x10000)]).unwrap();
41/// let mut queue = Queue::new(1024).unwrap();
42///
43/// // First, the driver sets up the queue; this set up is done via writes on the bus (PCI, MMIO).
44/// queue.set_size(8);
45/// queue.set_desc_table_address(Some(0x1000), None);
46/// queue.set_avail_ring_address(Some(0x2000), None);
47/// queue.set_used_ring_address(Some(0x3000), None);
48/// queue.set_event_idx(true);
49/// queue.set_ready(true);
50/// // The user should check if the queue is valid before starting to use it.
51/// assert!(queue.is_valid(&m));
52///
53/// // Here the driver would add entries in the available ring and then update the `idx` field of
54/// // the available ring (address = 0x2000 + 2).
55/// m.write_obj(3, GuestAddress(0x2002));
56///
57/// loop {
58///     queue.disable_notification(&m).unwrap();
59///
60///     // Consume entries from the available ring.
61///     while let Some(chain) = queue.iter(&m).unwrap().next() {
62///         // Process the descriptor chain, and then add an entry in the used ring and optionally
63///         // notify the driver.
64///         queue.add_used(&m, chain.head_index(), 0x100).unwrap();
65///
66///         if queue.needs_notification(&m).unwrap() {
67///             // Here we would notify the driver it has new entries in the used ring to consume.
68///         }
69///     }
70///     if !queue.enable_notification(&m).unwrap() {
71///         break;
72///     }
73/// }
74///
75/// // We can reset the queue at some point.
76/// queue.reset();
77/// // The queue should not be ready after reset.
78/// assert!(!queue.ready());
79/// ```
80#[derive(Debug, Default, PartialEq, Eq)]
81pub struct Queue {
82    /// The maximum size in elements offered by the device.
83    max_size: u16,
84
85    /// Tail position of the available ring.
86    next_avail: Wrapping<u16>,
87
88    /// Head position of the used ring.
89    next_used: Wrapping<u16>,
90
91    /// VIRTIO_F_RING_EVENT_IDX negotiated.
92    event_idx_enabled: bool,
93
94    /// The number of descriptor chains placed in the used ring via `add_used`
95    /// since the last time `needs_notification` was called on the associated queue.
96    num_added: Wrapping<u16>,
97
98    /// The queue size in elements the driver selected.
99    size: u16,
100
101    /// Indicates if the queue is finished with configuration.
102    ready: bool,
103
104    /// Guest physical address of the descriptor table.
105    desc_table: GuestAddress,
106
107    /// Guest physical address of the available ring.
108    avail_ring: GuestAddress,
109
110    /// Guest physical address of the used ring.
111    used_ring: GuestAddress,
112}
113
114impl Queue {
115    /// Equivalent of [`QueueT::set_size`] returning an error in case of invalid size.
116    ///
117    /// This should not be directly used, as the preferred method is part of the [`QueueT`]
118    /// interface. This is a convenience function for implementing save/restore capabilities.
119    pub fn try_set_size(&mut self, size: u16) -> Result<(), Error> {
120        if size > self.max_size() || size == 0 || (size & (size - 1)) != 0 {
121            return Err(Error::InvalidSize);
122        }
123        self.size = size;
124        Ok(())
125    }
126
127    /// Tries to set the descriptor table address. In case of an invalid value, the address is
128    /// not updated.
129    ///
130    /// This should not be directly used, as the preferred method is
131    /// [`QueueT::set_desc_table_address`]. This is a convenience function for implementing
132    /// save/restore capabilities.
133    pub fn try_set_desc_table_address(&mut self, desc_table: GuestAddress) -> Result<(), Error> {
134        if desc_table.mask(0xf) != 0 {
135            return Err(Error::InvalidDescTableAlign);
136        }
137        self.desc_table = desc_table;
138
139        Ok(())
140    }
141
142    /// Tries to update the available ring address. In case of an invalid value, the address is
143    /// not updated.
144    ///
145    /// This should not be directly used, as the preferred method is
146    /// [`QueueT::set_avail_ring_address`]. This is a convenience function for implementing
147    /// save/restore capabilities.
148    pub fn try_set_avail_ring_address(&mut self, avail_ring: GuestAddress) -> Result<(), Error> {
149        if avail_ring.mask(0x1) != 0 {
150            return Err(Error::InvalidAvailRingAlign);
151        }
152        self.avail_ring = avail_ring;
153        Ok(())
154    }
155
156    /// Tries to update the used ring address. In cae of an invalid value, the address is not
157    /// updated.
158    ///
159    /// This should not be directly used, as the preferred method is
160    /// [`QueueT::set_used_ring_address`]. This is a convenience function for implementing
161    /// save/restore capabilities.
162    pub fn try_set_used_ring_address(&mut self, used_ring: GuestAddress) -> Result<(), Error> {
163        if used_ring.mask(0x3) != 0 {
164            return Err(Error::InvalidUsedRingAlign);
165        }
166        self.used_ring = used_ring;
167        Ok(())
168    }
169
170    /// Returns the state of the `Queue`.
171    ///
172    /// This is useful for implementing save/restore capabilities.
173    /// The state does not have support for serialization, but this can be
174    /// added by VMMs locally through the use of a
175    /// [remote type](https://serde.rs/remote-derive.html).
176    ///
177    /// Alternatively, a version aware and serializable/deserializable QueueState
178    /// is available in the `virtio-queue-ser` crate.
179    pub fn state(&self) -> QueueState {
180        QueueState {
181            max_size: self.max_size,
182            next_avail: self.next_avail(),
183            next_used: self.next_used(),
184            event_idx_enabled: self.event_idx_enabled,
185            size: self.size,
186            ready: self.ready,
187            desc_table: self.desc_table(),
188            avail_ring: self.avail_ring(),
189            used_ring: self.used_ring(),
190        }
191    }
192
193    // Helper method that writes `val` to the `avail_event` field of the used ring, using
194    // the provided ordering.
195    fn set_avail_event<M: GuestMemory>(
196        &self,
197        mem: &M,
198        val: u16,
199        order: Ordering,
200    ) -> Result<(), Error> {
201        // This can not overflow an u64 since it is working with relatively small numbers compared
202        // to u64::MAX.
203        let avail_event_offset =
204            VIRTQ_USED_RING_HEADER_SIZE + VIRTQ_USED_ELEMENT_SIZE * u64::from(self.size);
205        let addr = self
206            .used_ring
207            .checked_add(avail_event_offset)
208            .ok_or(Error::AddressOverflow)?;
209
210        mem.store(u16::to_le(val), addr, order)
211            .map_err(Error::GuestMemory)
212    }
213
214    // Set the value of the `flags` field of the used ring, applying the specified ordering.
215    fn set_used_flags<M: GuestMemory>(
216        &mut self,
217        mem: &M,
218        val: u16,
219        order: Ordering,
220    ) -> Result<(), Error> {
221        mem.store(u16::to_le(val), self.used_ring, order)
222            .map_err(Error::GuestMemory)
223    }
224
225    // Write the appropriate values to enable or disable notifications from the driver.
226    //
227    // Every access in this method uses `Relaxed` ordering because a fence is added by the caller
228    // when appropriate.
229    fn set_notification<M: GuestMemory>(&mut self, mem: &M, enable: bool) -> Result<(), Error> {
230        if enable {
231            if self.event_idx_enabled {
232                // We call `set_avail_event` using the `next_avail` value, instead of reading
233                // and using the current `avail_idx` to avoid missing notifications. More
234                // details in `enable_notification`.
235                self.set_avail_event(mem, self.next_avail.0, Ordering::Relaxed)
236            } else {
237                self.set_used_flags(mem, 0, Ordering::Relaxed)
238            }
239        } else if !self.event_idx_enabled {
240            self.set_used_flags(mem, VRING_USED_F_NO_NOTIFY as u16, Ordering::Relaxed)
241        } else {
242            // Notifications are effectively disabled by default after triggering once when
243            // `VIRTIO_F_EVENT_IDX` is negotiated, so we don't do anything in that case.
244            Ok(())
245        }
246    }
247
248    // Return the value present in the used_event field of the avail ring.
249    //
250    // If the VIRTIO_F_EVENT_IDX feature bit is not negotiated, the flags field in the available
251    // ring offers a crude mechanism for the driver to inform the device that it doesn’t want
252    // interrupts when buffers are used. Otherwise virtq_avail.used_event is a more performant
253    // alternative where the driver specifies how far the device can progress before interrupting.
254    //
255    // Neither of these interrupt suppression methods are reliable, as they are not synchronized
256    // with the device, but they serve as useful optimizations. So we only ensure access to the
257    // virtq_avail.used_event is atomic, but do not need to synchronize with other memory accesses.
258    fn used_event<M: GuestMemory>(&self, mem: &M, order: Ordering) -> Result<Wrapping<u16>, Error> {
259        // This can not overflow an u64 since it is working with relatively small numbers compared
260        // to u64::MAX.
261        let used_event_offset =
262            VIRTQ_AVAIL_RING_HEADER_SIZE + u64::from(self.size) * VIRTQ_AVAIL_ELEMENT_SIZE;
263        let used_event_addr = self
264            .avail_ring
265            .checked_add(used_event_offset)
266            .ok_or(Error::AddressOverflow)?;
267
268        mem.load(used_event_addr, order)
269            .map(u16::from_le)
270            .map(Wrapping)
271            .map_err(Error::GuestMemory)
272    }
273}
274
275impl<'a> QueueGuard<'a> for Queue {
276    type G = &'a mut Self;
277}
278
279impl QueueT for Queue {
280    fn new(max_size: u16) -> Result<Self, Error> {
281        // We need to check that the max size is a power of 2 because we're setting this as the
282        // queue size, and the valid queue sizes are a power of 2 as per the specification.
283        if max_size == 0 || max_size > MAX_QUEUE_SIZE || (max_size & (max_size - 1)) != 0 {
284            return Err(Error::InvalidMaxSize);
285        }
286        Ok(Queue {
287            max_size,
288            size: max_size,
289            ready: false,
290            desc_table: GuestAddress(DEFAULT_DESC_TABLE_ADDR),
291            avail_ring: GuestAddress(DEFAULT_AVAIL_RING_ADDR),
292            used_ring: GuestAddress(DEFAULT_USED_RING_ADDR),
293            next_avail: Wrapping(0),
294            next_used: Wrapping(0),
295            event_idx_enabled: false,
296            num_added: Wrapping(0),
297        })
298    }
299
300    fn is_valid<M: GuestMemory>(&self, mem: &M) -> bool {
301        let queue_size = self.size as u64;
302        let desc_table = self.desc_table;
303        // The multiplication can not overflow an u64 since we are multiplying an u16 with a
304        // small number.
305        let desc_table_size = size_of::<RawDescriptor>() as u64 * queue_size;
306        let avail_ring = self.avail_ring;
307        // The operations below can not overflow an u64 since they're working with relatively small
308        // numbers compared to u64::MAX.
309        let avail_ring_size = VIRTQ_AVAIL_RING_META_SIZE + VIRTQ_AVAIL_ELEMENT_SIZE * queue_size;
310        let used_ring = self.used_ring;
311        let used_ring_size = VIRTQ_USED_RING_META_SIZE + VIRTQ_USED_ELEMENT_SIZE * queue_size;
312
313        if !self.ready {
314            error!("attempt to use virtio queue that is not marked ready");
315            false
316        } else if !mem.check_range(desc_table, desc_table_size as usize, Permissions::Read) {
317            error!(
318                "virtio queue descriptor table is not accessible: start:0x{:08x} size:0x{:08x}",
319                desc_table.raw_value(),
320                desc_table_size
321            );
322            false
323        } else if !mem.check_range(avail_ring, avail_ring_size as usize, Permissions::Read) {
324            error!(
325                "virtio queue available ring is not accessible: start:0x{:08x} size:0x{:08x}",
326                avail_ring.raw_value(),
327                avail_ring_size
328            );
329            false
330        } else if !mem.check_range(used_ring, used_ring_size as usize, Permissions::Write) {
331            error!(
332                "virtio queue used ring is not accessible: start:0x{:08x} size:0x{:08x}",
333                used_ring.raw_value(),
334                used_ring_size
335            );
336            false
337        } else {
338            true
339        }
340    }
341
342    fn reset(&mut self) {
343        self.ready = false;
344        self.size = self.max_size;
345        self.desc_table = GuestAddress(DEFAULT_DESC_TABLE_ADDR);
346        self.avail_ring = GuestAddress(DEFAULT_AVAIL_RING_ADDR);
347        self.used_ring = GuestAddress(DEFAULT_USED_RING_ADDR);
348        self.next_avail = Wrapping(0);
349        self.next_used = Wrapping(0);
350        self.num_added = Wrapping(0);
351        self.event_idx_enabled = false;
352    }
353
354    fn lock(&mut self) -> <Self as QueueGuard<'_>>::G {
355        self
356    }
357
358    fn max_size(&self) -> u16 {
359        self.max_size
360    }
361
362    fn size(&self) -> u16 {
363        self.size
364    }
365
366    fn set_size(&mut self, size: u16) {
367        if self.try_set_size(size).is_err() {
368            error!("virtio queue with invalid size: {}", size);
369        }
370    }
371
372    fn ready(&self) -> bool {
373        self.ready
374    }
375
376    fn set_ready(&mut self, ready: bool) {
377        self.ready = ready;
378    }
379
380    fn set_desc_table_address(&mut self, low: Option<u32>, high: Option<u32>) {
381        let low = low.unwrap_or(self.desc_table.0 as u32) as u64;
382        let high = high.unwrap_or((self.desc_table.0 >> 32) as u32) as u64;
383
384        let desc_table = GuestAddress((high << 32) | low);
385        if self.try_set_desc_table_address(desc_table).is_err() {
386            error!("virtio queue descriptor table breaks alignment constraints");
387        }
388    }
389
390    fn set_avail_ring_address(&mut self, low: Option<u32>, high: Option<u32>) {
391        let low = low.unwrap_or(self.avail_ring.0 as u32) as u64;
392        let high = high.unwrap_or((self.avail_ring.0 >> 32) as u32) as u64;
393
394        let avail_ring = GuestAddress((high << 32) | low);
395        if self.try_set_avail_ring_address(avail_ring).is_err() {
396            error!("virtio queue available ring breaks alignment constraints");
397        }
398    }
399
400    fn set_used_ring_address(&mut self, low: Option<u32>, high: Option<u32>) {
401        let low = low.unwrap_or(self.used_ring.0 as u32) as u64;
402        let high = high.unwrap_or((self.used_ring.0 >> 32) as u32) as u64;
403
404        let used_ring = GuestAddress((high << 32) | low);
405        if self.try_set_used_ring_address(used_ring).is_err() {
406            error!("virtio queue used ring breaks alignment constraints");
407        }
408    }
409
410    fn set_event_idx(&mut self, enabled: bool) {
411        self.event_idx_enabled = enabled;
412    }
413
414    fn avail_idx<M>(&self, mem: &M, order: Ordering) -> Result<Wrapping<u16>, Error>
415    where
416        M: GuestMemory + ?Sized,
417    {
418        let addr = self
419            .avail_ring
420            .checked_add(2)
421            .ok_or(Error::AddressOverflow)?;
422
423        mem.load(addr, order)
424            .map(u16::from_le)
425            .map(Wrapping)
426            .map_err(Error::GuestMemory)
427    }
428
429    fn used_idx<M: GuestMemory>(&self, mem: &M, order: Ordering) -> Result<Wrapping<u16>, Error> {
430        let addr = self
431            .used_ring
432            .checked_add(2)
433            .ok_or(Error::AddressOverflow)?;
434
435        mem.load(addr, order)
436            .map(u16::from_le)
437            .map(Wrapping)
438            .map_err(Error::GuestMemory)
439    }
440
441    fn add_used<M: GuestMemory>(
442        &mut self,
443        mem: &M,
444        head_index: u16,
445        len: u32,
446    ) -> Result<(), Error> {
447        if head_index >= self.size {
448            error!(
449                "attempted to add out of bounds descriptor to used ring: {}",
450                head_index
451            );
452            return Err(Error::InvalidDescriptorIndex);
453        }
454
455        let next_used_index = u64::from(self.next_used.0 % self.size);
456        // This can not overflow an u64 since it is working with relatively small numbers compared
457        // to u64::MAX.
458        let offset = VIRTQ_USED_RING_HEADER_SIZE + next_used_index * VIRTQ_USED_ELEMENT_SIZE;
459        let addr = self
460            .used_ring
461            .checked_add(offset)
462            .ok_or(Error::AddressOverflow)?;
463        mem.write_obj(VirtqUsedElem::new(head_index.into(), len), addr)
464            .map_err(Error::GuestMemory)?;
465
466        self.next_used += Wrapping(1);
467        self.num_added += Wrapping(1);
468
469        mem.store(
470            u16::to_le(self.next_used.0),
471            self.used_ring
472                .checked_add(2)
473                .ok_or(Error::AddressOverflow)?,
474            Ordering::Release,
475        )
476        .map_err(Error::GuestMemory)
477    }
478
479    fn enable_notification<M: GuestMemory>(&mut self, mem: &M) -> Result<bool, Error> {
480        self.set_notification(mem, true)?;
481        // Ensures the following read is not reordered before any previous write operation.
482        fence(Ordering::SeqCst);
483
484        // We double check here to avoid the situation where the available ring has been updated
485        // just before we re-enabled notifications, and it's possible to miss one. We compare the
486        // current `avail_idx` value to `self.next_avail` because it's where we stopped processing
487        // entries. There are situations where we intentionally avoid processing everything in the
488        // available ring (which will cause this method to return `true`), but in that case we'll
489        // probably not re-enable notifications as we already know there are pending entries.
490        self.avail_idx(mem, Ordering::Relaxed)
491            .map(|idx| idx != self.next_avail)
492    }
493
494    fn disable_notification<M: GuestMemory>(&mut self, mem: &M) -> Result<(), Error> {
495        self.set_notification(mem, false)
496    }
497
498    fn needs_notification<M: GuestMemory>(&mut self, mem: &M) -> Result<bool, Error> {
499        let used_idx = self.next_used;
500
501        // Complete all the writes in add_used() before reading the event.
502        fence(Ordering::SeqCst);
503
504        // The VRING_AVAIL_F_NO_INTERRUPT flag isn't supported yet.
505
506        // When the `EVENT_IDX` feature is negotiated, the driver writes into `used_event`
507        // a value that's used by the device to determine whether a notification must
508        // be submitted after adding a descriptor chain to the used ring. According to the
509        // standard, the notification must be sent when `next_used == used_event + 1`, but
510        // various device model implementations rely on an inequality instead, most likely
511        // to also support use cases where a bunch of descriptor chains are added to the used
512        // ring first, and only afterwards the `needs_notification` logic is called. For example,
513        // the approach based on `num_added` below is taken from the Linux Kernel implementation
514        // (i.e. https://elixir.bootlin.com/linux/v5.15.35/source/drivers/virtio/virtio_ring.c#L661)
515
516        // The `old` variable below is used to determine the value of `next_used` from when
517        // `needs_notification` was called last (each `needs_notification` call resets `num_added`
518        // to zero, while each `add_used` called increments it by one). Then, the logic below
519        // uses wrapped arithmetic to see whether `used_event` can be found between `old` and
520        // `next_used` in the circular sequence space of the used ring.
521        if self.event_idx_enabled {
522            let used_event = self.used_event(mem, Ordering::Relaxed)?;
523            let old = used_idx - self.num_added;
524            self.num_added = Wrapping(0);
525
526            return Ok(used_idx - used_event - Wrapping(1) < used_idx - old);
527        }
528
529        Ok(true)
530    }
531
532    fn next_avail(&self) -> u16 {
533        self.next_avail.0
534    }
535
536    fn set_next_avail(&mut self, next_avail: u16) {
537        self.next_avail = Wrapping(next_avail);
538    }
539
540    fn next_used(&self) -> u16 {
541        self.next_used.0
542    }
543
544    fn set_next_used(&mut self, next_used: u16) {
545        self.next_used = Wrapping(next_used);
546    }
547
548    fn desc_table(&self) -> u64 {
549        self.desc_table.0
550    }
551
552    fn avail_ring(&self) -> u64 {
553        self.avail_ring.0
554    }
555
556    fn used_ring(&self) -> u64 {
557        self.used_ring.0
558    }
559
560    fn event_idx_enabled(&self) -> bool {
561        self.event_idx_enabled
562    }
563
564    fn pop_descriptor_chain<M>(&mut self, mem: M) -> Option<DescriptorChain<M>>
565    where
566        M: Clone + Deref,
567        M::Target: GuestMemory,
568    {
569        // Default, iter-based impl. Will be subsequently improved.
570        match self.iter(mem) {
571            Ok(mut iter) => iter.next(),
572            Err(e) => {
573                error!("Iterator error {}", e);
574                None
575            }
576        }
577    }
578}
579
580impl QueueOwnedT for Queue {
581    fn iter<M>(&mut self, mem: M) -> Result<AvailIter<'_, M>, Error>
582    where
583        M: Deref,
584        M::Target: GuestMemory,
585    {
586        // We're checking here that a reset did not happen without re-initializing the queue.
587        // TODO: In the future we might want to also check that the other parameters in the
588        // queue are valid.
589        if !self.ready || self.avail_ring == GuestAddress(0) {
590            return Err(Error::QueueNotReady);
591        }
592
593        self.avail_idx(mem.deref(), Ordering::Acquire)
594            .map(move |idx| AvailIter::new(mem, idx, self))?
595    }
596
597    fn go_to_previous_position(&mut self) {
598        self.next_avail -= Wrapping(1);
599    }
600}
601
602/// Consuming iterator over all available descriptor chain heads in the queue.
603///
604/// # Example
605///
606/// ```rust
607/// # use virtio_bindings::bindings::virtio_ring::{VRING_DESC_F_NEXT, VRING_DESC_F_WRITE};
608/// # use virtio_queue::mock::MockSplitQueue;
609/// use virtio_queue::{desc::{split::Descriptor as SplitDescriptor, RawDescriptor}, Queue, QueueOwnedT};
610/// use vm_memory::{GuestAddress, GuestMemoryMmap};
611///
612/// # fn populate_queue(m: &GuestMemoryMmap) -> Queue {
613/// #    let vq = MockSplitQueue::new(m, 16);
614/// #    let mut q: Queue = vq.create_queue().unwrap();
615/// #
616/// #    // The chains are (0, 1), (2, 3, 4) and (5, 6).
617/// #    let mut descs = Vec::new();
618/// #    for i in 0..7 {
619/// #        let flags = match i {
620/// #            1 | 6 => 0,
621/// #            2 | 5 => VRING_DESC_F_NEXT | VRING_DESC_F_WRITE,
622/// #            4 => VRING_DESC_F_WRITE,
623/// #            _ => VRING_DESC_F_NEXT,
624/// #        };
625/// #
626/// #        descs.push(RawDescriptor::from(SplitDescriptor::new((0x1000 * (i + 1)) as u64, 0x1000, flags as u16, i + 1)));
627/// #    }
628/// #
629/// #    vq.add_desc_chains(&descs, 0).unwrap();
630/// #    q
631/// # }
632/// let m = &GuestMemoryMmap::<()>::from_ranges(&[(GuestAddress(0), 0x10000)]).unwrap();
633/// // Populate the queue with descriptor chains and update the available ring accordingly.
634/// let mut queue = populate_queue(m);
635/// let mut i = queue.iter(m).unwrap();
636///
637/// {
638///     let mut c = i.next().unwrap();
639///     let _first_head_index = c.head_index();
640///     // We should have two descriptors in the first chain.
641///     let _desc1 = c.next().unwrap();
642///     let _desc2 = c.next().unwrap();
643/// }
644///
645/// {
646///     let c = i.next().unwrap();
647///     let _second_head_index = c.head_index();
648///
649///     let mut iter = c.writable();
650///     // We should have two writable descriptors in the second chain.
651///     let _desc1 = iter.next().unwrap();
652///     let _desc2 = iter.next().unwrap();
653/// }
654///
655/// {
656///     let c = i.next().unwrap();
657///     let _third_head_index = c.head_index();
658///
659///     let mut iter = c.readable();
660///     // We should have one readable descriptor in the third chain.
661///     let _desc1 = iter.next().unwrap();
662/// }
663/// // Let's go back one position in the available ring.
664/// i.go_to_previous_position();
665/// // We should be able to access again the third descriptor chain.
666/// let c = i.next().unwrap();
667/// let _third_head_index = c.head_index();
668/// ```
669#[derive(Debug)]
670pub struct AvailIter<'b, M> {
671    mem: M,
672    desc_table: GuestAddress,
673    avail_ring: GuestAddress,
674    queue_size: u16,
675    last_index: Wrapping<u16>,
676    next_avail: &'b mut Wrapping<u16>,
677}
678
679impl<'b, M> AvailIter<'b, M>
680where
681    M: Deref,
682    M::Target: GuestMemory,
683{
684    /// Create a new instance of `AvailInter`.
685    ///
686    /// # Arguments
687    ///
688    /// * `mem` - the `GuestMemory` object that can be used to access the queue buffers.
689    /// * `idx` - the index of the available ring entry where the driver would put the next available descriptor chain.
690    /// * `queue` - the `Queue` object from which the needed data to create the `AvailIter` can be retrieved.
691    pub(crate) fn new(mem: M, idx: Wrapping<u16>, queue: &'b mut Queue) -> Result<Self, Error> {
692        // The number of descriptor chain heads to process should always
693        // be smaller or equal to the queue size, as the driver should
694        // never ask the VMM to process a available ring entry more than
695        // once. Checking and reporting such incorrect driver behavior
696        // can prevent potential hanging and Denial-of-Service from
697        // happening on the VMM side.
698        if (idx - queue.next_avail).0 > queue.size {
699            return Err(Error::InvalidAvailRingIndex);
700        }
701
702        Ok(AvailIter {
703            mem,
704            desc_table: queue.desc_table,
705            avail_ring: queue.avail_ring,
706            queue_size: queue.size,
707            last_index: idx,
708            next_avail: &mut queue.next_avail,
709        })
710    }
711
712    /// Goes back one position in the available descriptor chain offered by the driver.
713    ///
714    /// Rust does not support bidirectional iterators. This is the only way to revert the effect
715    /// of an iterator increment on the queue.
716    ///
717    /// Note: this method assumes there's only one thread manipulating the queue, so it should only
718    /// be invoked in single-threaded context.
719    pub fn go_to_previous_position(&mut self) {
720        *self.next_avail -= Wrapping(1);
721    }
722}
723
724impl<M> Iterator for AvailIter<'_, M>
725where
726    M: Clone + Deref,
727    M::Target: GuestMemory,
728{
729    type Item = DescriptorChain<M>;
730
731    fn next(&mut self) -> Option<Self::Item> {
732        if *self.next_avail == self.last_index {
733            return None;
734        }
735
736        // These two operations can not overflow an u64 since they're working with relatively small
737        // numbers compared to u64::MAX.
738        let elem_off =
739            u64::from(self.next_avail.0.checked_rem(self.queue_size)?) * VIRTQ_AVAIL_ELEMENT_SIZE;
740        let offset = VIRTQ_AVAIL_RING_HEADER_SIZE + elem_off;
741
742        let addr = self.avail_ring.checked_add(offset)?;
743        let head_index: u16 = self
744            .mem
745            .load(addr, Ordering::Acquire)
746            .map(u16::from_le)
747            .map_err(|_| error!("Failed to read from memory {:x}", addr.raw_value()))
748            .ok()?;
749
750        *self.next_avail += Wrapping(1);
751
752        Some(DescriptorChain::new(
753            self.mem.clone(),
754            self.desc_table,
755            self.queue_size,
756            head_index,
757        ))
758    }
759}
760
761#[cfg(any(test, feature = "test-utils"))]
762// It is convenient for tests to implement `PartialEq`, but it is not a
763// proper implementation as `GuestMemory` errors cannot implement `PartialEq`.
764impl PartialEq for Error {
765    fn eq(&self, other: &Self) -> bool {
766        format!("{}", &self) == format!("{other}")
767    }
768}
769
770#[cfg(test)]
771mod tests {
772    use super::*;
773    use crate::defs::{DEFAULT_AVAIL_RING_ADDR, DEFAULT_DESC_TABLE_ADDR, DEFAULT_USED_RING_ADDR};
774    use crate::desc::{split::Descriptor as SplitDescriptor, RawDescriptor};
775    use crate::mock::MockSplitQueue;
776    use virtio_bindings::bindings::virtio_ring::{
777        VRING_DESC_F_NEXT, VRING_DESC_F_WRITE, VRING_USED_F_NO_NOTIFY,
778    };
779
780    use vm_memory::{Address, Bytes, GuestAddress, GuestMemoryMmap};
781
782    #[test]
783    fn test_queue_is_valid() {
784        let m = &GuestMemoryMmap::<()>::from_ranges(&[(GuestAddress(0), 0x10000)]).unwrap();
785        let vq = MockSplitQueue::new(m, 16);
786        let mut q: Queue = vq.create_queue().unwrap();
787
788        // q is currently valid
789        assert!(q.is_valid(m));
790
791        // shouldn't be valid when not marked as ready
792        q.set_ready(false);
793        assert!(!q.ready());
794        assert!(!q.is_valid(m));
795        q.set_ready(true);
796
797        // shouldn't be allowed to set a size > max_size
798        q.set_size(q.max_size() << 1);
799        assert_eq!(q.size, q.max_size());
800
801        // or set the size to 0
802        q.set_size(0);
803        assert_eq!(q.size, q.max_size());
804
805        // or set a size which is not a power of 2
806        q.set_size(11);
807        assert_eq!(q.size, q.max_size());
808
809        // but should be allowed to set a size if 0 < size <= max_size and size is a power of two
810        q.set_size(4);
811        assert_eq!(q.size, 4);
812        q.size = q.max_size();
813
814        // shouldn't be allowed to set an address that breaks the alignment constraint
815        q.set_desc_table_address(Some(0xf), None);
816        assert_eq!(q.desc_table.0, vq.desc_table_addr().0);
817        // should be allowed to set an aligned out of bounds address
818        q.set_desc_table_address(Some(0xffff_fff0), None);
819        assert_eq!(q.desc_table.0, 0xffff_fff0);
820        // but shouldn't be valid
821        assert!(!q.is_valid(m));
822        // but should be allowed to set a valid description table address
823        q.set_desc_table_address(Some(0x10), None);
824        assert_eq!(q.desc_table.0, 0x10);
825        assert!(q.is_valid(m));
826        let addr = vq.desc_table_addr().0;
827        q.set_desc_table_address(Some(addr as u32), Some((addr >> 32) as u32));
828
829        // shouldn't be allowed to set an address that breaks the alignment constraint
830        q.set_avail_ring_address(Some(0x1), None);
831        assert_eq!(q.avail_ring.0, vq.avail_addr().0);
832        // should be allowed to set an aligned out of bounds address
833        q.set_avail_ring_address(Some(0xffff_fffe), None);
834        assert_eq!(q.avail_ring.0, 0xffff_fffe);
835        // but shouldn't be valid
836        assert!(!q.is_valid(m));
837        // but should be allowed to set a valid available ring address
838        q.set_avail_ring_address(Some(0x2), None);
839        assert_eq!(q.avail_ring.0, 0x2);
840        assert!(q.is_valid(m));
841        let addr = vq.avail_addr().0;
842        q.set_avail_ring_address(Some(addr as u32), Some((addr >> 32) as u32));
843
844        // shouldn't be allowed to set an address that breaks the alignment constraint
845        q.set_used_ring_address(Some(0x3), None);
846        assert_eq!(q.used_ring.0, vq.used_addr().0);
847        // should be allowed to set an aligned out of bounds address
848        q.set_used_ring_address(Some(0xffff_fffc), None);
849        assert_eq!(q.used_ring.0, 0xffff_fffc);
850        // but shouldn't be valid
851        assert!(!q.is_valid(m));
852        // but should be allowed to set a valid used ring address
853        q.set_used_ring_address(Some(0x4), None);
854        assert_eq!(q.used_ring.0, 0x4);
855        let addr = vq.used_addr().0;
856        q.set_used_ring_address(Some(addr as u32), Some((addr >> 32) as u32));
857        assert!(q.is_valid(m));
858    }
859
860    #[test]
861    fn test_add_used() {
862        let mem = &GuestMemoryMmap::<()>::from_ranges(&[(GuestAddress(0), 0x10000)]).unwrap();
863        let vq = MockSplitQueue::new(mem, 16);
864        let mut q: Queue = vq.create_queue().unwrap();
865
866        assert_eq!(q.used_idx(mem, Ordering::Acquire).unwrap(), Wrapping(0));
867        assert_eq!(u16::from_le(vq.used().idx().load()), 0);
868
869        // index too large
870        assert!(q.add_used(mem, 16, 0x1000).is_err());
871        assert_eq!(u16::from_le(vq.used().idx().load()), 0);
872
873        // should be ok
874        q.add_used(mem, 1, 0x1000).unwrap();
875        assert_eq!(q.next_used, Wrapping(1));
876        assert_eq!(q.used_idx(mem, Ordering::Acquire).unwrap(), Wrapping(1));
877        assert_eq!(u16::from_le(vq.used().idx().load()), 1);
878
879        let x = vq.used().ring().ref_at(0).unwrap().load();
880        assert_eq!(x.id(), 1);
881        assert_eq!(x.len(), 0x1000);
882    }
883
884    #[test]
885    fn test_reset_queue() {
886        let m = &GuestMemoryMmap::<()>::from_ranges(&[(GuestAddress(0), 0x10000)]).unwrap();
887        let vq = MockSplitQueue::new(m, 16);
888        let mut q: Queue = vq.create_queue().unwrap();
889
890        q.set_size(8);
891        // The address set by `MockSplitQueue` for the descriptor table is DEFAULT_DESC_TABLE_ADDR,
892        // so let's change it for testing the reset.
893        q.set_desc_table_address(Some(0x5000), None);
894        // Same for `event_idx_enabled`, `next_avail` `next_used` and `signalled_used`.
895        q.set_event_idx(true);
896        q.set_next_avail(2);
897        q.set_next_used(4);
898        q.num_added = Wrapping(15);
899        assert_eq!(q.size, 8);
900        // `create_queue` also marks the queue as ready.
901        assert!(q.ready);
902        assert_ne!(q.desc_table, GuestAddress(DEFAULT_DESC_TABLE_ADDR));
903        assert_ne!(q.avail_ring, GuestAddress(DEFAULT_AVAIL_RING_ADDR));
904        assert_ne!(q.used_ring, GuestAddress(DEFAULT_USED_RING_ADDR));
905        assert_ne!(q.next_avail, Wrapping(0));
906        assert_ne!(q.next_used, Wrapping(0));
907        assert_ne!(q.num_added, Wrapping(0));
908        assert!(q.event_idx_enabled);
909
910        q.reset();
911        assert_eq!(q.size, 16);
912        assert!(!q.ready);
913        assert_eq!(q.desc_table, GuestAddress(DEFAULT_DESC_TABLE_ADDR));
914        assert_eq!(q.avail_ring, GuestAddress(DEFAULT_AVAIL_RING_ADDR));
915        assert_eq!(q.used_ring, GuestAddress(DEFAULT_USED_RING_ADDR));
916        assert_eq!(q.next_avail, Wrapping(0));
917        assert_eq!(q.next_used, Wrapping(0));
918        assert_eq!(q.num_added, Wrapping(0));
919        assert!(!q.event_idx_enabled);
920    }
921
922    #[test]
923    fn test_needs_notification() {
924        let mem = &GuestMemoryMmap::<()>::from_ranges(&[(GuestAddress(0), 0x10000)]).unwrap();
925        let qsize = 16;
926        let vq = MockSplitQueue::new(mem, qsize);
927        let mut q: Queue = vq.create_queue().unwrap();
928        let avail_addr = vq.avail_addr();
929
930        // It should always return true when EVENT_IDX isn't enabled.
931        for i in 0..qsize {
932            q.next_used = Wrapping(i);
933            assert!(q.needs_notification(mem).unwrap());
934        }
935
936        mem.write_obj::<u16>(
937            u16::to_le(4),
938            avail_addr.unchecked_add(4 + qsize as u64 * 2),
939        )
940        .unwrap();
941        q.set_event_idx(true);
942
943        // Incrementing up to this value causes an `u16` to wrap back to 0.
944        let wrap = u32::from(u16::MAX) + 1;
945
946        for i in 0..wrap + 12 {
947            q.next_used = Wrapping(i as u16);
948            // Let's test wrapping around the maximum index value as well.
949            // `num_added` needs to be at least `1` to represent the fact that new descriptor
950            // chains have be added to the used ring since the last time `needs_notification`
951            // returned.
952            q.num_added = Wrapping(1);
953            let expected = i == 5 || i == (5 + wrap);
954            assert_eq!((q.needs_notification(mem).unwrap(), i), (expected, i));
955        }
956
957        mem.write_obj::<u16>(
958            u16::to_le(8),
959            avail_addr.unchecked_add(4 + qsize as u64 * 2),
960        )
961        .unwrap();
962
963        // Returns `false` because the current `used_event` value is behind both `next_used` and
964        // the value of `next_used` at the time when `needs_notification` last returned (which is
965        // computed based on `num_added` as described in the comments for `needs_notification`.
966        assert!(!q.needs_notification(mem).unwrap());
967
968        mem.write_obj::<u16>(
969            u16::to_le(15),
970            avail_addr.unchecked_add(4 + qsize as u64 * 2),
971        )
972        .unwrap();
973
974        q.num_added = Wrapping(1);
975        assert!(!q.needs_notification(mem).unwrap());
976
977        q.next_used = Wrapping(15);
978        q.num_added = Wrapping(1);
979        assert!(!q.needs_notification(mem).unwrap());
980
981        q.next_used = Wrapping(16);
982        q.num_added = Wrapping(1);
983        assert!(q.needs_notification(mem).unwrap());
984
985        // Calling `needs_notification` again immediately returns `false`.
986        assert!(!q.needs_notification(mem).unwrap());
987
988        mem.write_obj::<u16>(
989            u16::to_le(u16::MAX - 3),
990            avail_addr.unchecked_add(4 + qsize as u64 * 2),
991        )
992        .unwrap();
993        q.next_used = Wrapping(u16::MAX - 2);
994        q.num_added = Wrapping(1);
995        // Returns `true` because, when looking at circular sequence of indices of the used ring,
996        // the value we wrote in the `used_event` appears between the "old" value of `next_used`
997        // (i.e. `next_used` - `num_added`) and the current `next_used`, thus suggesting that we
998        // need to notify the driver.
999        assert!(q.needs_notification(mem).unwrap());
1000    }
1001
1002    #[test]
1003    fn test_enable_disable_notification() {
1004        let mem = &GuestMemoryMmap::<()>::from_ranges(&[(GuestAddress(0), 0x10000)]).unwrap();
1005        let vq = MockSplitQueue::new(mem, 16);
1006
1007        let mut q: Queue = vq.create_queue().unwrap();
1008        let used_addr = vq.used_addr();
1009
1010        assert!(!q.event_idx_enabled);
1011
1012        q.enable_notification(mem).unwrap();
1013        let v = mem.read_obj::<u16>(used_addr).map(u16::from_le).unwrap();
1014        assert_eq!(v, 0);
1015
1016        q.disable_notification(mem).unwrap();
1017        let v = mem.read_obj::<u16>(used_addr).map(u16::from_le).unwrap();
1018        assert_eq!(v, VRING_USED_F_NO_NOTIFY as u16);
1019
1020        q.enable_notification(mem).unwrap();
1021        let v = mem.read_obj::<u16>(used_addr).map(u16::from_le).unwrap();
1022        assert_eq!(v, 0);
1023
1024        q.set_event_idx(true);
1025        let avail_addr = vq.avail_addr();
1026        mem.write_obj::<u16>(u16::to_le(2), avail_addr.unchecked_add(2))
1027            .unwrap();
1028
1029        assert!(q.enable_notification(mem).unwrap());
1030        q.next_avail = Wrapping(2);
1031        assert!(!q.enable_notification(mem).unwrap());
1032
1033        mem.write_obj::<u16>(u16::to_le(8), avail_addr.unchecked_add(2))
1034            .unwrap();
1035
1036        assert!(q.enable_notification(mem).unwrap());
1037        q.next_avail = Wrapping(8);
1038        assert!(!q.enable_notification(mem).unwrap());
1039    }
1040
1041    #[test]
1042    fn test_consume_chains_with_notif() {
1043        let mem = &GuestMemoryMmap::<()>::from_ranges(&[(GuestAddress(0), 0x10000)]).unwrap();
1044        let vq = MockSplitQueue::new(mem, 16);
1045
1046        let mut q: Queue = vq.create_queue().unwrap();
1047
1048        // q is currently valid.
1049        assert!(q.is_valid(mem));
1050
1051        // The chains are (0, 1), (2, 3, 4), (5, 6), (7, 8), (9, 10, 11, 12).
1052        let mut descs = Vec::new();
1053        for i in 0..13 {
1054            let flags = match i {
1055                1 | 4 | 6 | 8 | 12 => 0,
1056                _ => VRING_DESC_F_NEXT,
1057            };
1058
1059            descs.push(RawDescriptor::from(SplitDescriptor::new(
1060                (0x1000 * (i + 1)) as u64,
1061                0x1000,
1062                flags as u16,
1063                i + 1,
1064            )));
1065        }
1066
1067        vq.add_desc_chains(&descs, 0).unwrap();
1068        // Update the index of the chain that can be consumed to not be the last one.
1069        // This enables us to consume chains in multiple iterations as opposed to consuming
1070        // all the driver written chains at once.
1071        vq.avail().idx().store(u16::to_le(2));
1072        // No descriptor chains are consumed at this point.
1073        assert_eq!(q.next_avail(), 0);
1074
1075        let mut i = 0;
1076
1077        loop {
1078            i += 1;
1079            q.disable_notification(mem).unwrap();
1080
1081            while let Some(chain) = q.iter(mem).unwrap().next() {
1082                // Process the descriptor chain, and then add entries to the
1083                // used ring.
1084                let head_index = chain.head_index();
1085                let mut desc_len = 0;
1086                chain.for_each(|d| {
1087                    if d.flags() as u32 & VRING_DESC_F_WRITE == VRING_DESC_F_WRITE {
1088                        desc_len += d.len();
1089                    }
1090                });
1091                q.add_used(mem, head_index, desc_len).unwrap();
1092            }
1093            if !q.enable_notification(mem).unwrap() {
1094                break;
1095            }
1096        }
1097        // The chains should be consumed in a single loop iteration because there's nothing updating
1098        // the `idx` field of the available ring in the meantime.
1099        assert_eq!(i, 1);
1100        // The next chain that can be consumed should have index 2.
1101        assert_eq!(q.next_avail(), 2);
1102        assert_eq!(q.next_used(), 2);
1103        // Let the device know it can consume one more chain.
1104        vq.avail().idx().store(u16::to_le(3));
1105        i = 0;
1106
1107        loop {
1108            i += 1;
1109            q.disable_notification(mem).unwrap();
1110
1111            while let Some(chain) = q.iter(mem).unwrap().next() {
1112                // Process the descriptor chain, and then add entries to the
1113                // used ring.
1114                let head_index = chain.head_index();
1115                let mut desc_len = 0;
1116                chain.for_each(|d| {
1117                    if d.flags() as u32 & VRING_DESC_F_WRITE == VRING_DESC_F_WRITE {
1118                        desc_len += d.len();
1119                    }
1120                });
1121                q.add_used(mem, head_index, desc_len).unwrap();
1122            }
1123
1124            // For the simplicity of the test we are updating here the `idx` value of the available
1125            // ring. Ideally this should be done on a separate thread.
1126            // Because of this update, the loop should be iterated again to consume the new
1127            // available descriptor chains.
1128            vq.avail().idx().store(u16::to_le(4));
1129            if !q.enable_notification(mem).unwrap() {
1130                break;
1131            }
1132        }
1133        assert_eq!(i, 2);
1134        // The next chain that can be consumed should have index 4.
1135        assert_eq!(q.next_avail(), 4);
1136        assert_eq!(q.next_used(), 4);
1137
1138        // Set an `idx` that is bigger than the number of entries added in the ring.
1139        // This is an allowed scenario, but the indexes of the chain will have unexpected values.
1140        vq.avail().idx().store(u16::to_le(7));
1141        loop {
1142            q.disable_notification(mem).unwrap();
1143
1144            while let Some(chain) = q.iter(mem).unwrap().next() {
1145                // Process the descriptor chain, and then add entries to the
1146                // used ring.
1147                let head_index = chain.head_index();
1148                let mut desc_len = 0;
1149                chain.for_each(|d| {
1150                    if d.flags() as u32 & VRING_DESC_F_WRITE == VRING_DESC_F_WRITE {
1151                        desc_len += d.len();
1152                    }
1153                });
1154                q.add_used(mem, head_index, desc_len).unwrap();
1155            }
1156            if !q.enable_notification(mem).unwrap() {
1157                break;
1158            }
1159        }
1160        assert_eq!(q.next_avail(), 7);
1161        assert_eq!(q.next_used(), 7);
1162    }
1163
1164    #[test]
1165    fn test_invalid_avail_idx() {
1166        // This is a negative test for the following MUST from the spec: `A driver MUST NOT
1167        // decrement the available idx on a virtqueue (ie. there is no way to “unexpose” buffers).`.
1168        // We validate that for this misconfiguration, the device does not panic.
1169        let mem = &GuestMemoryMmap::<()>::from_ranges(&[(GuestAddress(0), 0x10000)]).unwrap();
1170        let vq = MockSplitQueue::new(mem, 16);
1171
1172        let mut q: Queue = vq.create_queue().unwrap();
1173
1174        // q is currently valid.
1175        assert!(q.is_valid(mem));
1176
1177        // The chains are (0, 1), (2, 3, 4), (5, 6).
1178        let mut descs = Vec::new();
1179        for i in 0..7 {
1180            let flags = match i {
1181                1 | 4 | 6 => 0,
1182                _ => VRING_DESC_F_NEXT,
1183            };
1184
1185            descs.push(RawDescriptor::from(SplitDescriptor::new(
1186                (0x1000 * (i + 1)) as u64,
1187                0x1000,
1188                flags as u16,
1189                i + 1,
1190            )));
1191        }
1192
1193        vq.add_desc_chains(&descs, 0).unwrap();
1194        // Let the device know it can consume chains with the index < 2.
1195        vq.avail().idx().store(u16::to_le(3));
1196        // No descriptor chains are consumed at this point.
1197        assert_eq!(q.next_avail(), 0);
1198        assert_eq!(q.next_used(), 0);
1199
1200        loop {
1201            q.disable_notification(mem).unwrap();
1202
1203            while let Some(chain) = q.iter(mem).unwrap().next() {
1204                // Process the descriptor chain, and then add entries to the
1205                // used ring.
1206                let head_index = chain.head_index();
1207                let mut desc_len = 0;
1208                chain.for_each(|d| {
1209                    if d.flags() as u32 & VRING_DESC_F_WRITE == VRING_DESC_F_WRITE {
1210                        desc_len += d.len();
1211                    }
1212                });
1213                q.add_used(mem, head_index, desc_len).unwrap();
1214            }
1215            if !q.enable_notification(mem).unwrap() {
1216                break;
1217            }
1218        }
1219        // The next chain that can be consumed should have index 3.
1220        assert_eq!(q.next_avail(), 3);
1221        assert_eq!(q.avail_idx(mem, Ordering::Acquire).unwrap(), Wrapping(3));
1222        assert_eq!(q.next_used(), 3);
1223        assert_eq!(q.used_idx(mem, Ordering::Acquire).unwrap(), Wrapping(3));
1224        assert!(q.lock().ready());
1225
1226        // Decrement `idx` which should be forbidden. We don't enforce this thing, but we should
1227        // test that we don't panic in case the driver decrements it.
1228        vq.avail().idx().store(u16::to_le(1));
1229        // Invalid available ring index
1230        assert!(q.iter(mem).is_err());
1231    }
1232
1233    #[test]
1234    fn test_iterator_and_avail_idx() {
1235        // This test ensures constructing a descriptor chain iterator succeeds
1236        // with valid available ring indexes while produces an error with invalid
1237        // indexes.
1238        let queue_size = 2;
1239        let mem = &GuestMemoryMmap::<()>::from_ranges(&[(GuestAddress(0), 0x10000)]).unwrap();
1240        let vq = MockSplitQueue::new(mem, queue_size);
1241
1242        let mut q: Queue = vq.create_queue().unwrap();
1243
1244        // q is currently valid.
1245        assert!(q.is_valid(mem));
1246
1247        // Create descriptors to fill up the queue
1248        let mut descs = Vec::new();
1249        for i in 0..queue_size {
1250            descs.push(RawDescriptor::from(SplitDescriptor::new(
1251                (0x1000 * (i + 1)) as u64,
1252                0x1000,
1253                0_u16,
1254                i + 1,
1255            )));
1256        }
1257        vq.add_desc_chains(&descs, 0).unwrap();
1258
1259        // Set the 'next_available' index to 'u16:MAX' to test the wrapping scenarios
1260        q.set_next_avail(u16::MAX);
1261
1262        // When the number of chains exposed by the driver is equal to or less than the queue
1263        // size, the available ring index is valid and constructs an iterator successfully.
1264        let avail_idx = Wrapping(q.next_avail()) + Wrapping(queue_size);
1265        vq.avail().idx().store(u16::to_le(avail_idx.0));
1266        assert!(q.iter(mem).is_ok());
1267        let avail_idx = Wrapping(q.next_avail()) + Wrapping(queue_size - 1);
1268        vq.avail().idx().store(u16::to_le(avail_idx.0));
1269        assert!(q.iter(mem).is_ok());
1270
1271        // When the number of chains exposed by the driver is larger than the queue size, the
1272        // available ring index is invalid and produces an error from constructing an iterator.
1273        let avail_idx = Wrapping(q.next_avail()) + Wrapping(queue_size + 1);
1274        vq.avail().idx().store(u16::to_le(avail_idx.0));
1275        assert!(q.iter(mem).is_err());
1276    }
1277
1278    #[test]
1279    fn test_descriptor_and_iterator() {
1280        let m = &GuestMemoryMmap::<()>::from_ranges(&[(GuestAddress(0), 0x10000)]).unwrap();
1281        let vq = MockSplitQueue::new(m, 16);
1282
1283        let mut q: Queue = vq.create_queue().unwrap();
1284
1285        // q is currently valid
1286        assert!(q.is_valid(m));
1287
1288        // the chains are (0, 1), (2, 3, 4) and (5, 6)
1289        let mut descs = Vec::new();
1290        for j in 0..7 {
1291            let flags = match j {
1292                1 | 6 => 0,
1293                2 | 5 => VRING_DESC_F_NEXT | VRING_DESC_F_WRITE,
1294                4 => VRING_DESC_F_WRITE,
1295                _ => VRING_DESC_F_NEXT,
1296            };
1297
1298            descs.push(RawDescriptor::from(SplitDescriptor::new(
1299                (0x1000 * (j + 1)) as u64,
1300                0x1000,
1301                flags as u16,
1302                j + 1,
1303            )));
1304        }
1305
1306        vq.add_desc_chains(&descs, 0).unwrap();
1307
1308        let mut i = q.iter(m).unwrap();
1309
1310        {
1311            let c = i.next().unwrap();
1312            assert_eq!(c.head_index(), 0);
1313
1314            let mut iter = c;
1315            assert!(iter.next().is_some());
1316            assert!(iter.next().is_some());
1317            assert!(iter.next().is_none());
1318            assert!(iter.next().is_none());
1319        }
1320
1321        {
1322            let c = i.next().unwrap();
1323            assert_eq!(c.head_index(), 2);
1324
1325            let mut iter = c.writable();
1326            assert!(iter.next().is_some());
1327            assert!(iter.next().is_some());
1328            assert!(iter.next().is_none());
1329            assert!(iter.next().is_none());
1330        }
1331
1332        {
1333            let c = i.next().unwrap();
1334            assert_eq!(c.head_index(), 5);
1335
1336            let mut iter = c.readable();
1337            assert!(iter.next().is_some());
1338            assert!(iter.next().is_none());
1339            assert!(iter.next().is_none());
1340        }
1341    }
1342
1343    #[test]
1344    fn test_iterator() {
1345        let m = &GuestMemoryMmap::<()>::from_ranges(&[(GuestAddress(0), 0x10000)]).unwrap();
1346        let vq = MockSplitQueue::new(m, 16);
1347
1348        let mut q: Queue = vq.create_queue().unwrap();
1349
1350        q.size = q.max_size;
1351        q.desc_table = vq.desc_table_addr();
1352        q.avail_ring = vq.avail_addr();
1353        q.used_ring = vq.used_addr();
1354        assert!(q.is_valid(m));
1355
1356        {
1357            // an invalid queue should return an iterator with no next
1358            q.ready = false;
1359            assert!(q.iter(m).is_err());
1360        }
1361
1362        q.ready = true;
1363
1364        // now let's create two simple descriptor chains
1365        // the chains are (0, 1) and (2, 3, 4)
1366        {
1367            let mut descs = Vec::new();
1368            for j in 0..5u16 {
1369                let flags = match j {
1370                    1 | 4 => 0,
1371                    _ => VRING_DESC_F_NEXT,
1372                };
1373
1374                descs.push(RawDescriptor::from(SplitDescriptor::new(
1375                    (0x1000 * (j + 1)) as u64,
1376                    0x1000,
1377                    flags as u16,
1378                    j + 1,
1379                )));
1380            }
1381            vq.add_desc_chains(&descs, 0).unwrap();
1382
1383            let mut i = q.iter(m).unwrap();
1384
1385            {
1386                let mut c = i.next().unwrap();
1387                assert_eq!(c.head_index(), 0);
1388
1389                c.next().unwrap();
1390                assert!(c.next().is_some());
1391                assert!(c.next().is_none());
1392                assert_eq!(c.head_index(), 0);
1393            }
1394
1395            {
1396                let mut c = i.next().unwrap();
1397                assert_eq!(c.head_index(), 2);
1398
1399                c.next().unwrap();
1400                c.next().unwrap();
1401                c.next().unwrap();
1402                assert!(c.next().is_none());
1403                assert_eq!(c.head_index(), 2);
1404            }
1405
1406            // also test go_to_previous_position() works as expected
1407            {
1408                assert!(i.next().is_none());
1409                i.go_to_previous_position();
1410                let mut c = q.iter(m).unwrap().next().unwrap();
1411                c.next().unwrap();
1412                c.next().unwrap();
1413                c.next().unwrap();
1414                assert!(c.next().is_none());
1415            }
1416        }
1417
1418        // Test that iterating some broken descriptor chain does not exceed
1419        // 2^32 bytes in total (VIRTIO spec version 1.2, 2.7.5.2:
1420        // Drivers MUST NOT add a descriptor chain longer than 2^32 bytes in
1421        // total)
1422        {
1423            let descs = vec![
1424                RawDescriptor::from(SplitDescriptor::new(
1425                    0x1000,
1426                    0xffff_ffff,
1427                    VRING_DESC_F_NEXT as u16,
1428                    1,
1429                )),
1430                RawDescriptor::from(SplitDescriptor::new(0x1000, 0x1234_5678, 0, 2)),
1431            ];
1432            vq.add_desc_chains(&descs, 0).unwrap();
1433            let mut yielded_bytes_by_iteration = 0_u32;
1434            for d in q.iter(m).unwrap().next().unwrap() {
1435                yielded_bytes_by_iteration = yielded_bytes_by_iteration
1436                    .checked_add(d.len())
1437                    .expect("iterator should not yield more than 2^32 bytes");
1438            }
1439        }
1440
1441        // Same as above, but test with a descriptor which is self-referential
1442        {
1443            let descs = vec![RawDescriptor::from(SplitDescriptor::new(
1444                0x1000,
1445                0xffff_ffff,
1446                VRING_DESC_F_NEXT as u16,
1447                0,
1448            ))];
1449            vq.add_desc_chains(&descs, 0).unwrap();
1450            let mut yielded_bytes_by_iteration = 0_u32;
1451            for d in q.iter(m).unwrap().next().unwrap() {
1452                yielded_bytes_by_iteration = yielded_bytes_by_iteration
1453                    .checked_add(d.len())
1454                    .expect("iterator should not yield more than 2^32 bytes");
1455            }
1456        }
1457    }
1458
1459    #[test]
1460    fn test_regression_iterator_division() {
1461        // This is a regression test that tests that the iterator does not try to divide
1462        // by 0 when the queue size is 0
1463        let m = &GuestMemoryMmap::<()>::from_ranges(&[(GuestAddress(0), 0x10000)]).unwrap();
1464        let vq = MockSplitQueue::new(m, 1);
1465        // This input was generated by the fuzzer, both for the QueueS and the Descriptor
1466        let descriptors: Vec<RawDescriptor> = vec![RawDescriptor::from(SplitDescriptor::new(
1467            14178673876262995140,
1468            3301229764,
1469            50372,
1470            50372,
1471        ))];
1472        vq.build_desc_chain(&descriptors).unwrap();
1473
1474        let mut q = Queue {
1475            max_size: 38,
1476            next_avail: Wrapping(0),
1477            next_used: Wrapping(0),
1478            event_idx_enabled: false,
1479            num_added: Wrapping(0),
1480            size: 0,
1481            ready: false,
1482            desc_table: GuestAddress(12837708984796196),
1483            avail_ring: GuestAddress(0),
1484            used_ring: GuestAddress(9943947977301164032),
1485        };
1486
1487        assert!(q.pop_descriptor_chain(m).is_none());
1488    }
1489
1490    #[test]
1491    fn test_setters_error_cases() {
1492        assert_eq!(Queue::new(15).unwrap_err(), Error::InvalidMaxSize);
1493        let mut q = Queue::new(16).unwrap();
1494
1495        let expected_val = q.desc_table.0;
1496        assert_eq!(
1497            q.try_set_desc_table_address(GuestAddress(0xf)).unwrap_err(),
1498            Error::InvalidDescTableAlign
1499        );
1500        assert_eq!(q.desc_table(), expected_val);
1501
1502        let expected_val = q.avail_ring.0;
1503        assert_eq!(
1504            q.try_set_avail_ring_address(GuestAddress(0x1)).unwrap_err(),
1505            Error::InvalidAvailRingAlign
1506        );
1507        assert_eq!(q.avail_ring(), expected_val);
1508
1509        let expected_val = q.used_ring.0;
1510        assert_eq!(
1511            q.try_set_used_ring_address(GuestAddress(0x3)).unwrap_err(),
1512            Error::InvalidUsedRingAlign
1513        );
1514        assert_eq!(q.used_ring(), expected_val);
1515
1516        let expected_val = q.size;
1517        assert_eq!(q.try_set_size(15).unwrap_err(), Error::InvalidSize);
1518        assert_eq!(q.size(), expected_val)
1519    }
1520
1521    #[test]
1522    // This is a regression test for a fuzzing finding. If the driver requests a reset of the
1523    // device, but then does not re-initializes the queue then a subsequent call to process
1524    // a request should yield no descriptors to process. Before this fix we were processing
1525    // descriptors that were added to the queue before, and we were ending up processing 255
1526    // descriptors per chain.
1527    fn test_regression_timeout_after_reset() {
1528        // The input below was generated by libfuzzer and adapted for this test.
1529        let m = &GuestMemoryMmap::<()>::from_ranges(&[(GuestAddress(0x0), 0x10000)]).unwrap();
1530        let vq = MockSplitQueue::new(m, 1024);
1531
1532        // This input below was generated by the fuzzer.
1533        let descriptors: Vec<RawDescriptor> = vec![
1534            RawDescriptor::from(SplitDescriptor::new(21508325467, 0, 1, 4)),
1535            RawDescriptor::from(SplitDescriptor::new(2097152, 4096, 3, 0)),
1536            RawDescriptor::from(SplitDescriptor::new(
1537                18374686479672737792,
1538                4294967295,
1539                65535,
1540                29,
1541            )),
1542            RawDescriptor::from(SplitDescriptor::new(76842670169653248, 1114115, 0, 0)),
1543            RawDescriptor::from(SplitDescriptor::new(16, 983040, 126, 3)),
1544            RawDescriptor::from(SplitDescriptor::new(897648164864, 0, 0, 0)),
1545            RawDescriptor::from(SplitDescriptor::new(111669149722, 0, 0, 0)),
1546        ];
1547        vq.build_multiple_desc_chains(&descriptors).unwrap();
1548
1549        let mut q: Queue = vq.create_queue().unwrap();
1550
1551        // Setting the queue to ready should not allow consuming descriptors after reset.
1552        q.reset();
1553        q.set_ready(true);
1554        let mut counter = 0;
1555        while let Some(mut desc_chain) = q.pop_descriptor_chain(m) {
1556            // this empty loop is here to check that there are no side effects
1557            // in terms of memory & execution time.
1558            while desc_chain.next().is_some() {
1559                counter += 1;
1560            }
1561        }
1562        assert_eq!(counter, 0);
1563
1564        // Setting the avail_addr to valid should not allow consuming descriptors after reset.
1565        q.reset();
1566        q.set_avail_ring_address(Some(0x1000), None);
1567        assert_eq!(q.avail_ring, GuestAddress(0x1000));
1568        counter = 0;
1569        while let Some(mut desc_chain) = q.pop_descriptor_chain(m) {
1570            // this empty loop is here to check that there are no side effects
1571            // in terms of memory & execution time.
1572            while desc_chain.next().is_some() {
1573                counter += 1;
1574            }
1575        }
1576        assert_eq!(counter, 0);
1577    }
1578}