1use 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
29pub const MAX_QUEUE_SIZE: u16 = 32768;
31
32#[derive(Debug, Default, PartialEq, Eq)]
81pub struct Queue {
82 max_size: u16,
84
85 next_avail: Wrapping<u16>,
87
88 next_used: Wrapping<u16>,
90
91 event_idx_enabled: bool,
93
94 num_added: Wrapping<u16>,
97
98 size: u16,
100
101 ready: bool,
103
104 desc_table: GuestAddress,
106
107 avail_ring: GuestAddress,
109
110 used_ring: GuestAddress,
112}
113
114impl Queue {
115 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 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 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 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 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 fn set_avail_event<M: GuestMemory>(
196 &self,
197 mem: &M,
198 val: u16,
199 order: Ordering,
200 ) -> Result<(), Error> {
201 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 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 fn set_notification<M: GuestMemory>(&mut self, mem: &M, enable: bool) -> Result<(), Error> {
230 if enable {
231 if self.event_idx_enabled {
232 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 Ok(())
245 }
246 }
247
248 fn used_event<M: GuestMemory>(&self, mem: &M, order: Ordering) -> Result<Wrapping<u16>, Error> {
259 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 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 let desc_table_size = size_of::<RawDescriptor>() as u64 * queue_size;
306 let avail_ring = self.avail_ring;
307 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 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 fence(Ordering::SeqCst);
483
484 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 fence(Ordering::SeqCst);
503
504 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 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 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#[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 pub(crate) fn new(mem: M, idx: Wrapping<u16>, queue: &'b mut Queue) -> Result<Self, Error> {
692 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 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 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"))]
762impl 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 assert!(q.is_valid(m));
790
791 q.set_ready(false);
793 assert!(!q.ready());
794 assert!(!q.is_valid(m));
795 q.set_ready(true);
796
797 q.set_size(q.max_size() << 1);
799 assert_eq!(q.size, q.max_size());
800
801 q.set_size(0);
803 assert_eq!(q.size, q.max_size());
804
805 q.set_size(11);
807 assert_eq!(q.size, q.max_size());
808
809 q.set_size(4);
811 assert_eq!(q.size, 4);
812 q.size = q.max_size();
813
814 q.set_desc_table_address(Some(0xf), None);
816 assert_eq!(q.desc_table.0, vq.desc_table_addr().0);
817 q.set_desc_table_address(Some(0xffff_fff0), None);
819 assert_eq!(q.desc_table.0, 0xffff_fff0);
820 assert!(!q.is_valid(m));
822 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 q.set_avail_ring_address(Some(0x1), None);
831 assert_eq!(q.avail_ring.0, vq.avail_addr().0);
832 q.set_avail_ring_address(Some(0xffff_fffe), None);
834 assert_eq!(q.avail_ring.0, 0xffff_fffe);
835 assert!(!q.is_valid(m));
837 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 q.set_used_ring_address(Some(0x3), None);
846 assert_eq!(q.used_ring.0, vq.used_addr().0);
847 q.set_used_ring_address(Some(0xffff_fffc), None);
849 assert_eq!(q.used_ring.0, 0xffff_fffc);
850 assert!(!q.is_valid(m));
852 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 assert!(q.add_used(mem, 16, 0x1000).is_err());
871 assert_eq!(u16::from_le(vq.used().idx().load()), 0);
872
873 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 q.set_desc_table_address(Some(0x5000), None);
894 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 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 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 let wrap = u32::from(u16::MAX) + 1;
945
946 for i in 0..wrap + 12 {
947 q.next_used = Wrapping(i as u16);
948 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 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 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 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 assert!(q.is_valid(mem));
1050
1051 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 vq.avail().idx().store(u16::to_le(2));
1072 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 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 assert_eq!(i, 1);
1100 assert_eq!(q.next_avail(), 2);
1102 assert_eq!(q.next_used(), 2);
1103 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 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 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 assert_eq!(q.next_avail(), 4);
1136 assert_eq!(q.next_used(), 4);
1137
1138 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 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 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 assert!(q.is_valid(mem));
1176
1177 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 vq.avail().idx().store(u16::to_le(3));
1196 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 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 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 vq.avail().idx().store(u16::to_le(1));
1229 assert!(q.iter(mem).is_err());
1231 }
1232
1233 #[test]
1234 fn test_iterator_and_avail_idx() {
1235 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 assert!(q.is_valid(mem));
1246
1247 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 q.set_next_avail(u16::MAX);
1261
1262 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 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 assert!(q.is_valid(m));
1287
1288 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 q.ready = false;
1359 assert!(q.iter(m).is_err());
1360 }
1361
1362 q.ready = true;
1363
1364 {
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 {
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 {
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 {
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 let m = &GuestMemoryMmap::<()>::from_ranges(&[(GuestAddress(0), 0x10000)]).unwrap();
1464 let vq = MockSplitQueue::new(m, 1);
1465 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 fn test_regression_timeout_after_reset() {
1528 let m = &GuestMemoryMmap::<()>::from_ranges(&[(GuestAddress(0x0), 0x10000)]).unwrap();
1530 let vq = MockSplitQueue::new(m, 1024);
1531
1532 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 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 while desc_chain.next().is_some() {
1559 counter += 1;
1560 }
1561 }
1562 assert_eq!(counter, 0);
1563
1564 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 while desc_chain.next().is_some() {
1573 counter += 1;
1574 }
1575 }
1576 assert_eq!(counter, 0);
1577 }
1578}