Skip to main content

vmbus_ring/
lib.rs

1// Copyright (c) Microsoft Corporation.
2// Licensed under the MIT License.
3
4//! This module implements the low-level interface to the VmBus ring buffer. The
5//! ring buffer resides in guest memory and is mapped into the host, allowing
6//! efficient transfer of variable-sized packets.
7//!
8//! Ring buffer packets have headers called descriptors, which can specify a
9//! transaction ID and metadata referring to memory outside the ring buffer.
10//! Each packet is a multiple of 8 bytes.
11//!
12//! In practice, ring buffers always come in pairs so that packets can be both
13//! sent and received. However, this module's interfaces operate on them singly.
14
15#![expect(missing_docs)]
16#![forbid(unsafe_code)]
17
18pub mod gparange;
19
20pub use pipe_protocol::*;
21pub use protocol::PAGE_SIZE;
22pub use protocol::TransferPageRange;
23
24use crate::gparange::GpaRange;
25use guestmem::AccessError;
26use guestmem::MemoryRead;
27use guestmem::MemoryWrite;
28use guestmem::ranges::PagedRange;
29use inspect::Inspect;
30use protocol::*;
31use safeatomic::AtomicSliceOps;
32use std::fmt::Debug;
33use std::sync::Arc;
34use std::sync::atomic::AtomicU8;
35use std::sync::atomic::AtomicU32;
36use std::sync::atomic::AtomicU64;
37use std::sync::atomic::Ordering;
38use thiserror::Error;
39use zerocopy::FromZeros;
40use zerocopy::IntoBytes;
41
42mod pipe_protocol {
43    use zerocopy::FromBytes;
44    use zerocopy::Immutable;
45    use zerocopy::IntoBytes;
46    use zerocopy::KnownLayout;
47
48    /// Pipe channel packets are prefixed with this header to allow for
49    /// non-8-multiple lengths.
50    #[repr(C)]
51    #[derive(Debug, Copy, Clone, IntoBytes, Immutable, KnownLayout, FromBytes)]
52    pub struct PipeHeader {
53        pub packet_type: u32,
54        pub len: u32,
55    }
56
57    /// Regular data packet.
58    pub const PIPE_PACKET_TYPE_DATA: u32 = 1;
59    /// Data packet that has been partially consumed, in which case the `len`
60    /// field's high word is the number of bytes already read. The opposite
61    /// endpoint will never write this type.
62    pub const PIPE_PACKET_TYPE_PARTIAL: u32 = 2;
63    /// Setup a GPA direct buffer for RDMA.
64    pub const PIPE_PACKET_TYPE_SETUP_GPA_DIRECT: u32 = 3;
65    /// Tear down a GPA direct buffer.
66    pub const PIPE_PACKET_TYPE_TEARDOWN_GPA_DIRECT: u32 = 4;
67
68    /// The maximum size of a pipe packet's payload.
69    pub const MAXIMUM_PIPE_PACKET_SIZE: usize = 16384;
70}
71
72mod protocol {
73    use crate::CONTROL_WORD_COUNT;
74    use inspect::Inspect;
75    use safeatomic::AtomicSliceOps;
76    use std::fmt::Debug;
77    use std::sync::atomic::AtomicU32;
78    use std::sync::atomic::Ordering;
79    use zerocopy::FromBytes;
80    use zerocopy::Immutable;
81    use zerocopy::IntoBytes;
82    use zerocopy::KnownLayout;
83
84    /// VmBus ring buffers are sized in multiples 4KB pages, with a 4KB control page.
85    pub const PAGE_SIZE: usize = 4096;
86
87    /// The descriptor header on every packet.
88    #[repr(C)]
89    #[derive(Copy, Clone, Debug, IntoBytes, Immutable, KnownLayout, FromBytes)]
90    pub struct PacketDescriptor {
91        pub packet_type: u16,
92        pub data_offset8: u16,
93        pub length8: u16,
94        pub flags: u16,
95        pub transaction_id: u64,
96    }
97
98    /// A control page accessor.
99    pub struct Control<'a>(pub &'a [AtomicU32; CONTROL_WORD_COUNT]);
100
101    impl<'a> Control<'a> {
102        pub fn from_page(page: &'a guestmem::Page) -> Option<Self> {
103            let slice = page.as_atomic_slice()?[..CONTROL_WORD_COUNT]
104                .try_into()
105                .unwrap();
106            Some(Self(slice))
107        }
108
109        pub fn inp(&self) -> &AtomicU32 {
110            &self.0[0]
111        }
112        pub fn outp(&self) -> &AtomicU32 {
113            &self.0[1]
114        }
115        pub fn interrupt_mask(&self) -> &AtomicU32 {
116            &self.0[2]
117        }
118        pub fn pending_send_size(&self) -> &AtomicU32 {
119            &self.0[3]
120        }
121        pub fn feature_bits(&self) -> &AtomicU32 {
122            &self.0[16]
123        }
124    }
125
126    impl Inspect for Control<'_> {
127        fn inspect(&self, req: inspect::Request<'_>) {
128            req.respond()
129                .hex("in", self.inp().load(Ordering::Relaxed))
130                .hex("out", self.outp().load(Ordering::Relaxed))
131                .hex(
132                    "interrupt_mask",
133                    self.interrupt_mask().load(Ordering::Relaxed),
134                )
135                .hex(
136                    "pending_send_size",
137                    self.pending_send_size().load(Ordering::Relaxed),
138                )
139                .hex("feature_bits", self.feature_bits().load(Ordering::Relaxed));
140        }
141    }
142
143    impl Debug for Control<'_> {
144        fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
145            f.debug_struct("Control")
146                .field("inp", self.inp())
147                .field("outp", self.outp())
148                .field("interrupt_mask", self.interrupt_mask())
149                .field("pending_send_size", self.pending_send_size())
150                .field("feature_bits", self.feature_bits())
151                .finish()
152        }
153    }
154
155    /// If set, the endpoint supports sending signals when the number of free
156    /// bytes in the ring reaches or exceeds `pending_send_size`.
157    pub const FEATURE_SUPPORTS_PENDING_SEND_SIZE: u32 = 1;
158
159    /// A transfer range specifying a length and offset within a transfer page
160    /// set. Only used by NetVSP.
161    #[repr(C)]
162    #[derive(Debug, Copy, Clone, IntoBytes, Immutable, KnownLayout, FromBytes)]
163    pub struct TransferPageRange {
164        pub byte_count: u32,
165        pub byte_offset: u32,
166    }
167
168    /// The extended portion of the packet descriptor that describes a transfer
169    /// page packet.
170    #[repr(C)]
171    #[derive(Copy, Clone, Debug, IntoBytes, Immutable, KnownLayout, FromBytes)]
172    pub struct TransferPageHeader {
173        pub transfer_page_set_id: u16,
174        pub reserved: u16, // may have garbage non-zero values
175        pub range_count: u32,
176    }
177
178    /// The extended portion of the packet descriptor describing a GPA direct packet.
179    #[repr(C)]
180    #[derive(Copy, Clone, Debug, IntoBytes, Immutable, KnownLayout, FromBytes)]
181    pub struct GpaDirectHeader {
182        pub reserved: u32, // may have garbage non-zero values
183        pub range_count: u32,
184    }
185
186    pub const PACKET_FLAG_COMPLETION_REQUESTED: u16 = 1;
187
188    /// The packet footer.
189    #[repr(C)]
190    #[derive(Copy, Clone, Debug, IntoBytes, Immutable, KnownLayout, FromBytes)]
191    pub struct Footer {
192        pub reserved: u32,
193        /// The ring offset of the packet.
194        pub offset: u32,
195    }
196}
197
198#[derive(Copy, Clone, Debug, Error)]
199pub enum Error {
200    #[error("invalid ring buffer pointer")]
201    InvalidRingPointer,
202    #[error("invalid message length")]
203    InvalidMessageLength,
204    #[error("invalid data available")]
205    InvalidDataAvailable,
206    #[error("ring buffer too large")]
207    RingTooLarge,
208    #[error("invalid ring memory")]
209    InvalidRingMemory,
210    #[error("invalid descriptor offset or length")]
211    InvalidDescriptorLengths,
212    #[error("unknown packet descriptor flags")]
213    InvalidDescriptorFlags,
214    #[error("unknown packet descriptor type")]
215    InvalidDescriptorType,
216    #[error("invalid range count for gpa direct packet")]
217    InvalidDescriptorGpaDirectRangeCount,
218    #[error("the interrupt mask bit was supposed to be clear but it is set")]
219    InterruptsExternallyMasked,
220}
221
222#[derive(Copy, Clone, Debug, Error)]
223pub enum ReadError {
224    #[error("ring buffer empty")]
225    Empty,
226    #[error(transparent)]
227    Corrupt(#[from] Error),
228}
229
230#[derive(Copy, Clone, Debug, Error)]
231pub enum WriteError {
232    #[error("ring buffer full")]
233    Full(usize),
234    #[error(transparent)]
235    Corrupt(#[from] Error),
236}
237
238/// A range within a ring buffer.
239#[derive(Copy, Clone, Debug)]
240pub struct RingRange {
241    off: u32,
242    size: u32,
243}
244
245impl RingRange {
246    /// The empty range.
247    pub fn empty() -> Self {
248        RingRange { off: 0, size: 0 }
249    }
250
251    /// Retrieves a `MemoryWrite` that allows for writing to the range.
252    pub fn writer<'a, T: Ring>(&self, ring: &'a T) -> RingRangeWriter<'a, T::Memory> {
253        RingRangeWriter {
254            start: self.off,
255            end: self.off + self.size,
256            mem: ring.mem(),
257        }
258    }
259
260    /// Writes the full range using aligned writes of `u64` values.
261    ///
262    /// # Panics
263    /// Panics if the ring range is not exactly the size of `data`.
264    pub fn write_aligned_full<T: Ring>(&self, ring: &T, data: &[u64]) {
265        assert_eq!(self.size as usize, data.len() * 8);
266        ring.mem().write_aligned(self.off as usize, data.as_bytes());
267    }
268
269    /// Retrieves a `MemoryRead` that allows for writing to the range.
270    pub fn reader<'a, T: Ring>(&self, ring: &'a T) -> RingRangeReader<'a, T::Memory> {
271        RingRangeReader {
272            start: self.off,
273            end: self.off + self.size,
274            mem: ring.mem(),
275        }
276    }
277
278    /// Returns the length of the range.
279    pub fn len(&self) -> usize {
280        self.size as usize
281    }
282
283    /// Checks if this range is empty.
284    pub fn is_empty(&self) -> bool {
285        self.size == 0
286    }
287}
288
289/// A type implementing `MemoryRead` accessing a `RingRange`.
290pub struct RingRangeReader<'a, T> {
291    start: u32,
292    end: u32,
293    mem: &'a T,
294}
295
296impl<T: RingMem> MemoryRead for RingRangeReader<'_, T> {
297    fn read(&mut self, data: &mut [u8]) -> Result<&mut Self, AccessError> {
298        if self.len() < data.len() {
299            return Err(AccessError::OutOfRange(self.len(), data.len()));
300        }
301        self.mem.read_at(self.start as usize, data);
302        self.start += data.len() as u32;
303        Ok(self)
304    }
305
306    fn skip(&mut self, len: usize) -> Result<&mut Self, AccessError> {
307        if self.len() < len {
308            return Err(AccessError::OutOfRange(self.len(), len));
309        }
310        self.start += len as u32;
311        Ok(self)
312    }
313
314    fn len(&self) -> usize {
315        (self.end - self.start) as usize
316    }
317}
318
319/// A type implementing `MemoryWrite` accessing a `RingRange`.
320pub struct RingRangeWriter<'a, T> {
321    start: u32,
322    end: u32,
323    mem: &'a T,
324}
325
326impl<T: RingMem> MemoryWrite for RingRangeWriter<'_, T> {
327    fn write(&mut self, data: &[u8]) -> Result<(), AccessError> {
328        if self.len() < data.len() {
329            return Err(AccessError::OutOfRange(self.len(), data.len()));
330        }
331        self.mem.write_at(self.start as usize, data);
332        self.start += data.len() as u32;
333        Ok(())
334    }
335
336    fn fill(&mut self, _val: u8, _len: usize) -> Result<(), AccessError> {
337        unimplemented!()
338    }
339
340    fn len(&self) -> usize {
341        (self.end - self.start) as usize
342    }
343}
344
345/// The alternate types of incoming packets. For packets with external data,
346/// includes a `RingRange` whose data is the variable portion of the packet
347/// descriptor.
348#[derive(Debug, Copy, Clone)]
349pub enum IncomingPacketType {
350    InBand,
351    Completion,
352    GpaDirect(u32, RingRange),
353    TransferPages(u16, u32, RingRange),
354}
355
356/// An incoming packet.
357#[derive(Debug)]
358pub struct IncomingPacket {
359    pub transaction_id: Option<u64>,
360    pub typ: IncomingPacketType,
361    pub payload: RingRange,
362}
363
364const PACKET_TYPE_IN_BAND: u16 = 6;
365const PACKET_TYPE_TRANSFER_PAGES: u16 = 0x7;
366const PACKET_TYPE_GPA_DIRECT: u16 = 0x9;
367const PACKET_TYPE_COMPLETION: u16 = 0xb;
368
369fn parse_packet<M: RingMem>(
370    ring: &M,
371    ring_off: u32,
372    avail: u32,
373) -> Result<(u32, IncomingPacket), ReadError> {
374    const DESCRIPTOR_SIZE8: u16 = size_of::<PacketDescriptor>() as u16 / 8;
375
376    let mut desc = PacketDescriptor::new_zeroed();
377    ring.read_aligned(ring_off as usize, desc.as_mut_bytes());
378    let len = desc.length8 as u32 * 8;
379    if desc.length8 < desc.data_offset8 || desc.data_offset8 < DESCRIPTOR_SIZE8 || avail < len {
380        return Err(ReadError::Corrupt(Error::InvalidDescriptorLengths));
381    }
382
383    if (desc.flags & !PACKET_FLAG_COMPLETION_REQUESTED) != 0 {
384        return Err(ReadError::Corrupt(Error::InvalidDescriptorFlags));
385    }
386    let transaction_id = if desc.flags & PACKET_FLAG_COMPLETION_REQUESTED != 0
387        || desc.packet_type == PACKET_TYPE_COMPLETION
388    {
389        Some(desc.transaction_id)
390    } else {
391        None
392    };
393    let typ = match desc.packet_type {
394        PACKET_TYPE_IN_BAND => IncomingPacketType::InBand,
395        PACKET_TYPE_COMPLETION => IncomingPacketType::Completion,
396        PACKET_TYPE_TRANSFER_PAGES => {
397            const TRANSFER_PAGE_HEADER_SIZE8: u16 =
398                DESCRIPTOR_SIZE8 + size_of::<TransferPageHeader>() as u16 / 8;
399
400            if desc.data_offset8 < TRANSFER_PAGE_HEADER_SIZE8 {
401                return Err(ReadError::Corrupt(Error::InvalidDescriptorLengths));
402            }
403
404            let mut tph = TransferPageHeader::new_zeroed();
405            ring.read_aligned(
406                ring_off as usize + size_of::<PacketDescriptor>(),
407                tph.as_mut_bytes(),
408            );
409            IncomingPacketType::TransferPages(
410                tph.transfer_page_set_id,
411                tph.range_count,
412                RingRange {
413                    off: ring_off + TRANSFER_PAGE_HEADER_SIZE8 as u32 * 8,
414                    size: (desc.data_offset8 - TRANSFER_PAGE_HEADER_SIZE8) as u32 * 8,
415                },
416            )
417        }
418        PACKET_TYPE_GPA_DIRECT => {
419            const GPA_DIRECT_HEADER_SIZE8: u16 =
420                DESCRIPTOR_SIZE8 + size_of::<GpaDirectHeader>() as u16 / 8;
421
422            if desc.data_offset8 < GPA_DIRECT_HEADER_SIZE8 {
423                return Err(ReadError::Corrupt(Error::InvalidDescriptorLengths));
424            }
425
426            let mut gph = GpaDirectHeader::new_zeroed();
427            ring.read_aligned(
428                ring_off as usize + size_of::<PacketDescriptor>(),
429                gph.as_mut_bytes(),
430            );
431            if gph.range_count == 0 {
432                return Err(ReadError::Corrupt(
433                    Error::InvalidDescriptorGpaDirectRangeCount,
434                ));
435            }
436            IncomingPacketType::GpaDirect(
437                gph.range_count,
438                RingRange {
439                    off: ring_off + GPA_DIRECT_HEADER_SIZE8 as u32 * 8,
440                    size: (desc.data_offset8 - GPA_DIRECT_HEADER_SIZE8) as u32 * 8,
441                },
442            )
443        }
444        _ => return Err(ReadError::Corrupt(Error::InvalidDescriptorType)),
445    };
446    let payload = RingRange {
447        off: ring_off + desc.data_offset8 as u32 * 8,
448        size: (desc.length8 - desc.data_offset8) as u32 * 8,
449    };
450    Ok((
451        len,
452        IncomingPacket {
453            transaction_id,
454            typ,
455            payload,
456        },
457    ))
458}
459
460/// The size of the control region in 32-bit words.
461pub const CONTROL_WORD_COUNT: usize = 32;
462
463/// A trait for memory backing a ring buffer.
464pub trait RingMem: Send {
465    /// Returns the control page.
466    fn control(&self) -> &[AtomicU32; CONTROL_WORD_COUNT];
467
468    /// Reads from the data portion of the ring, wrapping (once) at the end of
469    /// the ring. Precondition: `addr + data.len() <= self.len() * 2`.
470    fn read_at(&self, addr: usize, data: &mut [u8]);
471
472    /// Reads from the data portion of the ring, as in [`RingMem::read_at`]. `addr` and
473    /// `data.len()` must be multiples of 8.
474    ///
475    /// `read_at` may be faster for large or variable-sized reads.
476    fn read_aligned(&self, addr: usize, data: &mut [u8]) {
477        debug_assert!(addr.is_multiple_of(8));
478        debug_assert!(data.len().is_multiple_of(8));
479        self.read_at(addr, data)
480    }
481
482    /// Writes to the data portion of the ring, wrapping (once) at the end of
483    /// the ring. Precondition: `addr + data.len() <= self.len() * 2`.
484    fn write_at(&self, addr: usize, data: &[u8]);
485
486    /// Writes to the data portion of the ring, as in [`RingMem::write_at`]. `addr` and
487    /// `data.len()` must be multiples of 8.
488    ///
489    /// `write_at` may be faster for large or variable-sized writes.
490    fn write_aligned(&self, addr: usize, data: &[u8]) {
491        debug_assert!(addr.is_multiple_of(8));
492        debug_assert!(data.len().is_multiple_of(8));
493        self.write_at(addr, data)
494    }
495
496    /// Returns the length of the ring in bytes.
497    fn len(&self) -> usize;
498}
499
500/// Implementation of `RingMem` for references. Useful for tests.
501impl<T: RingMem + Sync> RingMem for &'_ T {
502    fn control(&self) -> &[AtomicU32; CONTROL_WORD_COUNT] {
503        (*self).control()
504    }
505    fn read_at(&self, addr: usize, data: &mut [u8]) {
506        (*self).read_at(addr, data)
507    }
508    fn write_at(&self, addr: usize, data: &[u8]) {
509        (*self).write_at(addr, data)
510    }
511    fn len(&self) -> usize {
512        (*self).len()
513    }
514
515    fn read_aligned(&self, addr: usize, data: &mut [u8]) {
516        (*self).read_aligned(addr, data)
517    }
518
519    fn write_aligned(&self, addr: usize, data: &[u8]) {
520        (*self).write_aligned(addr, data)
521    }
522}
523
524#[derive(Debug)]
525pub struct SingleMappedRingMem<T>(pub T);
526
527impl<T: AsRef<[AtomicU8]>> SingleMappedRingMem<T> {
528    fn control_range(&self) -> &[AtomicU8; PAGE_SIZE] {
529        self.0.as_ref()[..PAGE_SIZE].try_into().unwrap()
530    }
531
532    fn data(&self) -> &[AtomicU8] {
533        &self.0.as_ref()[PAGE_SIZE..]
534    }
535}
536
537impl<T: AsRef<[AtomicU8]> + Send> RingMem for SingleMappedRingMem<T> {
538    fn read_at(&self, mut addr: usize, data: &mut [u8]) {
539        if addr >= self.len() {
540            addr -= self.len();
541        }
542        let this_data = self.data();
543        if addr + data.len() <= self.len() {
544            this_data[addr..addr + data.len()].atomic_read(data);
545        } else {
546            let data_len = data.len();
547            let (first, last) = data.split_at_mut(self.len() - addr);
548            this_data[addr..].atomic_read(first);
549            this_data[..data_len - (self.len() - addr)].atomic_read(last);
550        }
551    }
552
553    fn write_at(&self, mut addr: usize, data: &[u8]) {
554        if addr > self.len() {
555            addr -= self.len();
556        }
557        let this_data = self.data();
558        if addr + data.len() <= self.len() {
559            this_data[addr..addr + data.len()].atomic_write(data);
560        } else {
561            let (first, last) = data.split_at(self.len() - addr);
562            this_data[addr..].atomic_write(first);
563            this_data[..data.len() - (self.len() - addr)].atomic_write(last);
564        }
565    }
566
567    fn control(&self) -> &[AtomicU32; CONTROL_WORD_COUNT] {
568        self.control_range().as_atomic_slice().unwrap()[..CONTROL_WORD_COUNT]
569            .try_into()
570            .unwrap()
571    }
572
573    fn len(&self) -> usize {
574        self.data().len()
575    }
576}
577
578/// An implementation of `RingMem` over a flat allocation. Useful for tests.
579#[derive(Clone)]
580pub struct FlatRingMem {
581    inner: Arc<FlatRingInner>,
582}
583
584struct FlatRingInner {
585    control: [AtomicU32; CONTROL_WORD_COUNT],
586    data: Vec<AtomicU8>,
587}
588
589impl FlatRingMem {
590    /// Allocates a new memory.
591    pub fn new(len: usize) -> Self {
592        let mut data = Vec::new();
593        data.resize_with(len, Default::default);
594        Self {
595            inner: Arc::new(FlatRingInner {
596                control: [0; CONTROL_WORD_COUNT].map(Into::into),
597                data,
598            }),
599        }
600    }
601}
602
603impl Debug for FlatRingMem {
604    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
605        f.debug_struct("FlatRingMem").finish()
606    }
607}
608
609impl RingMem for FlatRingMem {
610    fn read_at(&self, mut addr: usize, data: &mut [u8]) {
611        if addr > self.len() {
612            addr -= self.len();
613        }
614        if addr + data.len() <= self.len() {
615            self.inner.data[addr..addr + data.len()].atomic_read(data);
616        } else {
617            let data_len = data.len();
618            let (first, last) = data.split_at_mut(self.len() - addr);
619            self.inner.data[addr..].atomic_read(first);
620            self.inner.data[..data_len - (self.len() - addr)].atomic_read(last);
621        }
622    }
623
624    fn write_at(&self, mut addr: usize, data: &[u8]) {
625        if addr > self.len() {
626            addr -= self.len();
627        }
628        if addr + data.len() <= self.len() {
629            self.inner.data[addr..addr + data.len()].atomic_write(data);
630        } else {
631            let (first, last) = data.split_at(self.len() - addr);
632            self.inner.data[addr..].atomic_write(first);
633            self.inner.data[..data.len() - (self.len() - addr)].atomic_write(last);
634        }
635    }
636
637    fn control(&self) -> &[AtomicU32; CONTROL_WORD_COUNT] {
638        &self.inner.control
639    }
640
641    fn len(&self) -> usize {
642        self.inner.data.len()
643    }
644}
645
646/// A trait for ring buffer memory divided into discontiguous pages.
647pub trait PagedMemory: Send {
648    /// Returns the control page.
649    fn control(&self) -> &[AtomicU8; PAGE_SIZE];
650    /// Returns the number of data pages.
651    fn data_page_count(&self) -> usize;
652    /// Returns a data page.
653    ///
654    /// For performance reasons, `page` may be in `0..data_page_count*2`,
655    /// representing the ring logically mapped twice consecutively. The
656    /// implementation should return the same page for `n` and `n +
657    /// data_page_count`.
658    fn data(&self, page: usize) -> &[AtomicU8; PAGE_SIZE];
659}
660
661/// An implementation of [`RingMem`] on top of discontiguous pages.
662#[derive(Debug, Clone)]
663pub struct PagedRingMem<T>(T);
664
665impl<T: PagedMemory> PagedRingMem<T> {
666    /// Returns a new ring memory wrapping a type implementing [`PagedMemory`].
667    pub fn new(inner: T) -> Self {
668        Self(inner)
669    }
670}
671
672impl<T: PagedMemory> RingMem for PagedRingMem<T> {
673    fn len(&self) -> usize {
674        self.0.data_page_count() * PAGE_SIZE
675    }
676
677    fn read_at(&self, mut addr: usize, mut data: &mut [u8]) {
678        while !data.is_empty() {
679            let page = addr / PAGE_SIZE;
680            let offset = addr % PAGE_SIZE;
681            let offset_end = PAGE_SIZE.min(offset + data.len());
682            let len = offset_end - offset;
683            let (this, next) = data.split_at_mut(len);
684            self.0.data(page)[offset..offset_end].atomic_read(this);
685            addr += len;
686            data = next;
687        }
688    }
689
690    fn write_at(&self, mut addr: usize, mut data: &[u8]) {
691        while !data.is_empty() {
692            let page = addr / PAGE_SIZE;
693            let offset = addr % PAGE_SIZE;
694            let offset_end = PAGE_SIZE.min(offset + data.len());
695            let len = offset_end - offset;
696            let (this, next) = data.split_at(len);
697            self.0.data(page)[offset..offset_end].atomic_write(this);
698            addr += len;
699            data = next;
700        }
701    }
702
703    #[inline]
704    fn read_aligned(&self, addr: usize, data: &mut [u8]) {
705        debug_assert!(addr.is_multiple_of(8));
706        debug_assert!(data.len().is_multiple_of(8));
707        for (i, b) in data.chunks_exact_mut(8).enumerate() {
708            let addr = (addr & !7) + i * 8;
709            let page = addr / PAGE_SIZE;
710            let offset = addr % PAGE_SIZE;
711            b.copy_from_slice(
712                &self.0.data(page)[offset..offset + 8]
713                    .as_atomic::<AtomicU64>()
714                    .unwrap()
715                    .load(Ordering::Relaxed)
716                    .to_ne_bytes(),
717            );
718        }
719    }
720
721    #[inline]
722    fn write_aligned(&self, addr: usize, data: &[u8]) {
723        debug_assert!(addr.is_multiple_of(8));
724        debug_assert!(data.len().is_multiple_of(8));
725        for (i, b) in data.chunks_exact(8).enumerate() {
726            let addr = (addr & !7) + i * 8;
727            let page = addr / PAGE_SIZE;
728            let offset = addr % PAGE_SIZE;
729            self.0.data(page)[offset..offset + 8]
730                .as_atomic::<AtomicU64>()
731                .unwrap()
732                .store(u64::from_ne_bytes(b.try_into().unwrap()), Ordering::Relaxed);
733        }
734    }
735
736    #[inline]
737    fn control(&self) -> &[AtomicU32; CONTROL_WORD_COUNT] {
738        self.0.control().as_atomic_slice().unwrap()[..CONTROL_WORD_COUNT]
739            .try_into()
740            .unwrap()
741    }
742}
743
744/// Information about an outgoing packet.
745#[derive(Debug)]
746pub struct OutgoingPacket<'a> {
747    pub transaction_id: u64,
748    pub size: usize,
749    pub typ: OutgoingPacketType<'a>,
750}
751
752/// The outgoing packet type variants.
753#[derive(Debug, Copy, Clone)]
754pub enum OutgoingPacketType<'a> {
755    /// A non-transactional data packet.
756    InBandNoCompletion,
757    /// A transactional data packet.
758    InBandWithCompletion,
759    /// A completion packet.
760    Completion,
761    /// A GPA direct packet, which can reference memory outside the ring by address.
762    ///
763    /// Not supported on the host side of the ring.
764    GpaDirect(&'a [PagedRange<'a>]),
765    /// A transfer page packet, which can reference memory outside the ring by a
766    /// buffer ID and a set of offsets into some pre-established buffer
767    /// (typically a GPADL).
768    ///
769    /// Used by networking. Should not be used in new devices--just embed the
770    /// buffer offsets in the device-specific packet payload.
771    TransferPages(u16, &'a [TransferPageRange]),
772}
773
774/// Namespace type with methods to compute packet sizes, for use with
775/// `set_pending_send_size`.
776pub struct PacketSize(());
777
778impl PacketSize {
779    /// Computes the size of an in-band packet.
780    pub const fn in_band(payload_len: usize) -> usize {
781        size_of::<PacketDescriptor>() + ((payload_len + 7) & !7) + size_of::<Footer>()
782    }
783
784    /// Computes the size of a completion packet.
785    pub const fn completion(payload_len: usize) -> usize {
786        Self::in_band(payload_len)
787    }
788
789    // Computes the size of a gpa direct packet.
790    // pub fn gpa_direct()
791
792    /// Computes the size of a transfer page packet.
793    pub const fn transfer_pages(count: usize, payload_len: usize) -> usize {
794        Self::in_band(payload_len)
795            + size_of::<TransferPageHeader>()
796            + count * size_of::<TransferPageRange>()
797    }
798}
799
800/// A trait shared by the incoming and outgoing ring buffers. Used primarily
801/// with `RingRange::reader` and `RingRange::writer`.
802pub trait Ring {
803    /// The underlying memory type.
804    type Memory: RingMem;
805
806    /// The backing memory of the ring buffer.
807    fn mem(&self) -> &Self::Memory;
808}
809
810/// The interface to the receiving endpoint of a ring buffer.
811#[derive(Debug)]
812pub struct IncomingRing<M: RingMem> {
813    inner: InnerRing<M>,
814}
815
816impl<M: RingMem> Inspect for IncomingRing<M> {
817    fn inspect(&self, req: inspect::Request<'_>) {
818        self.inner.inspect(req);
819    }
820}
821
822/// The current incoming ring state.
823#[derive(Debug, Clone, Inspect)]
824pub struct IncomingOffset {
825    #[inspect(hex)]
826    cached_in: u32,
827    #[inspect(hex)]
828    committed_out: u32,
829    #[inspect(hex)]
830    next_out: u32,
831}
832
833impl IncomingOffset {
834    /// Reverts the removal of packets that have not yet been committed.
835    pub fn revert(&mut self) {
836        self.next_out = self.committed_out;
837    }
838}
839
840impl<M: RingMem> Ring for IncomingRing<M> {
841    type Memory = M;
842    fn mem(&self) -> &Self::Memory {
843        &self.inner.mem
844    }
845}
846
847impl<M: RingMem> IncomingRing<M> {
848    /// Returns a new incoming ring. Fails if the ring memory is not sized or
849    /// aligned correctly or if the ring control data is corrupt.
850    pub fn new(mem: M) -> Result<Self, Error> {
851        let inner = InnerRing::new(mem)?;
852        // Start with interrupts masked.
853        let control = inner.control();
854        control.interrupt_mask().store(1, Ordering::Relaxed);
855        Ok(Self { inner })
856    }
857
858    /// Indicates whether pending send size notification is supported on
859    /// the vmbus ring.
860    pub fn supports_pending_send_size(&self) -> bool {
861        let feature_bits = self.inner.control().feature_bits().load(Ordering::Relaxed);
862        (feature_bits & FEATURE_SUPPORTS_PENDING_SEND_SIZE) != 0
863    }
864
865    /// Enables or disables the interrupt mask, declaring to the opposite
866    /// endpoint that interrupts should not or should be sent for a ring
867    /// empty-to-non-empty transition.
868    pub fn set_interrupt_mask(&self, state: bool) {
869        self.inner
870            .control()
871            .interrupt_mask()
872            .store(state as u32, Ordering::SeqCst);
873    }
874
875    /// Verifies that interrupts are currently unmasked.
876    ///
877    /// This can be used to check that ring state is consistent.
878    pub fn verify_interrupts_unmasked(&self) -> Result<(), Error> {
879        if self
880            .inner
881            .control()
882            .interrupt_mask()
883            .load(Ordering::Relaxed)
884            == 0
885        {
886            Ok(())
887        } else {
888            Err(Error::InterruptsExternallyMasked)
889        }
890    }
891
892    /// Returns the current incoming offset, for passing to `read` and
893    /// `commit_read`.
894    pub fn incoming(&self) -> Result<IncomingOffset, Error> {
895        let control = self.inner.control();
896        let next_out = self
897            .inner
898            .validate(control.outp().load(Ordering::Relaxed))?;
899        let cached_in = self.inner.validate(control.inp().load(Ordering::Relaxed))?;
900        Ok(IncomingOffset {
901            next_out,
902            cached_in,
903            committed_out: next_out,
904        })
905    }
906
907    /// Returns true if there are any packets to read.
908    pub fn can_read(&self, incoming: &mut IncomingOffset) -> Result<bool, Error> {
909        let can_read = if incoming.next_out != incoming.cached_in {
910            true
911        } else {
912            let inp = self
913                .inner
914                .validate(self.inner.control().inp().load(Ordering::Acquire))?;
915            // Cache the new offset to ensure a stable result.
916            incoming.cached_in = inp;
917            incoming.next_out != inp
918        };
919        Ok(can_read)
920    }
921
922    /// Commits a series of packet reads, returning whether the opposite
923    /// endpoint should be signaled.
924    pub fn commit_read(&self, ptrs: &mut IncomingOffset) -> bool {
925        if ptrs.committed_out == ptrs.next_out {
926            return false;
927        }
928        let control = self.inner.control();
929        control.outp().store(ptrs.next_out, Ordering::SeqCst);
930        let pending_send_size = control.pending_send_size().load(Ordering::SeqCst);
931        // Some implementations set the pending send size to the size of the
932        // ring minus 1. The intent is that a signal arrive when the ring is
933        // completely empty, but this is invalid since the maximum writable ring
934        // size in the size of the ring minus 8. Mask off the low bits to work
935        // around this.
936        let pending_send_size = pending_send_size & !7;
937        let signal = if pending_send_size != 0 {
938            if let Ok(inp) = self.inner.validate(control.inp().load(Ordering::SeqCst)) {
939                let old_free = self.inner.free(inp, ptrs.committed_out);
940                let new_free = self.inner.free(inp, ptrs.next_out);
941                old_free < pending_send_size && new_free >= pending_send_size
942            } else {
943                false
944            }
945        } else {
946            false
947        };
948        ptrs.committed_out = ptrs.next_out;
949        signal
950    }
951
952    /// Parses the next packet descriptor, returning the parsed information and
953    /// a range that can be used to read the packet. The caller should commit
954    /// the read with `commit_read` to free up space in the ring.
955    pub fn read(&self, ptrs: &mut IncomingOffset) -> Result<IncomingPacket, ReadError> {
956        let outp = ptrs.next_out;
957        let mut inp = ptrs.cached_in;
958        if inp == outp {
959            inp = self
960                .inner
961                .validate(self.inner.control().inp().load(Ordering::Acquire))?;
962            if inp == outp {
963                return Err(ReadError::Empty);
964            }
965            ptrs.cached_in = inp;
966        }
967        let avail = self.inner.available(inp, outp);
968        if avail < 16 {
969            return Err(ReadError::Corrupt(Error::InvalidDataAvailable));
970        }
971        let (len, packet) = parse_packet(&self.inner.mem, outp, avail)?;
972        ptrs.next_out = self
973            .inner
974            .add_pointer(outp, len + size_of::<Footer>() as u32);
975
976        Ok(packet)
977    }
978}
979
980/// The sending side of a ring buffer.
981#[derive(Debug)]
982pub struct OutgoingRing<M: RingMem> {
983    inner: InnerRing<M>,
984}
985
986impl<M: RingMem> Inspect for OutgoingRing<M> {
987    fn inspect(&self, req: inspect::Request<'_>) {
988        self.inner.inspect(req);
989    }
990}
991
992/// An outgoing ring offset, used to determine the position to write packets to.
993#[derive(Debug, Clone, Inspect)]
994pub struct OutgoingOffset {
995    #[inspect(hex)]
996    cached_out: u32,
997    #[inspect(hex)]
998    committed_in: u32,
999    #[inspect(hex)]
1000    next_in: u32,
1001}
1002
1003impl OutgoingOffset {
1004    /// Reverts the insertion of packets that have not yet been committed.
1005    pub fn revert(&mut self) {
1006        self.next_in = self.committed_in;
1007    }
1008}
1009
1010impl<M: RingMem> Ring for OutgoingRing<M> {
1011    type Memory = M;
1012    fn mem(&self) -> &Self::Memory {
1013        &self.inner.mem
1014    }
1015}
1016
1017impl<M: RingMem> OutgoingRing<M> {
1018    /// Returns a new outgoing ring over `mem`.
1019    pub fn new(mem: M) -> Result<Self, Error> {
1020        let inner = InnerRing::new(mem)?;
1021        // Report to the opposite endpoint that we will send interrupts for a
1022        // ring full to ring non-full transition. Feature bits are set by the
1023        // sending side.
1024        let control = inner.control();
1025        control
1026            .feature_bits()
1027            .store(FEATURE_SUPPORTS_PENDING_SEND_SIZE, Ordering::Relaxed);
1028        // Start with no interrupt requested.
1029        control.pending_send_size().store(0, Ordering::Relaxed);
1030        Ok(Self { inner })
1031    }
1032
1033    /// Returns the current outgoing offset, for passing to `write` and
1034    /// ultimately `commit_write`.
1035    pub fn outgoing(&self) -> Result<OutgoingOffset, Error> {
1036        let control = self.inner.control();
1037        let next_in = self.inner.validate(control.inp().load(Ordering::Relaxed))?;
1038        let cached_out = self
1039            .inner
1040            .validate(control.outp().load(Ordering::Relaxed))?;
1041        Ok(OutgoingOffset {
1042            cached_out,
1043            committed_in: next_in,
1044            next_in,
1045        })
1046    }
1047
1048    /// Sets the pending send size: the number of bytes that should be free in
1049    /// the ring before the opposite endpoint sends a ring-non-full signal.
1050    ///
1051    /// Fails if the packet size is larger than the ring's maximum packet size.
1052    pub fn set_pending_send_size(&self, len: usize) -> Result<(), Error> {
1053        if len > self.maximum_packet_size() {
1054            return Err(Error::InvalidMessageLength);
1055        }
1056        self.inner
1057            .control()
1058            .pending_send_size()
1059            .store((len as u32 + 7) & !7, Ordering::SeqCst);
1060
1061        Ok(())
1062    }
1063
1064    /// Returns the maximum packet size that can fit in the ring.
1065    pub fn maximum_packet_size(&self) -> usize {
1066        self.inner.len() as usize - 8
1067    }
1068
1069    /// Returns whether a packet can fit in the ring starting at the specified
1070    /// offset.
1071    pub fn can_write(&self, ptrs: &mut OutgoingOffset, len: usize) -> Result<bool, Error> {
1072        let can_write = if self.inner.free(ptrs.next_in, ptrs.cached_out) as usize >= len {
1073            true
1074        } else {
1075            let outp = self
1076                .inner
1077                .validate(self.inner.control().outp().load(Ordering::Relaxed))?;
1078
1079            // Cache the new offset to ensure a stable result.
1080            ptrs.cached_out = outp;
1081            self.inner.free(ptrs.next_in, outp) as usize >= len
1082        };
1083        Ok(can_write)
1084    }
1085
1086    /// Commits a series of writes that ended at the specified offset, returning
1087    /// whether the opposite endpoint should be signaled.
1088    pub fn commit_write(&self, ptrs: &mut OutgoingOffset) -> bool {
1089        if ptrs.committed_in == ptrs.next_in {
1090            return false;
1091        }
1092        let inp = ptrs.next_in;
1093
1094        // Update the ring offset and check if the opposite endpoint needs to be
1095        // signaled. This is the case only if interrupts are unmasked and the
1096        // ring was previously empty before this write.
1097        let control = self.inner.control();
1098        control.inp().store(inp, Ordering::SeqCst);
1099        let needs_interrupt = control.interrupt_mask().load(Ordering::SeqCst) == 0
1100            && control.outp().load(Ordering::SeqCst) == ptrs.committed_in;
1101
1102        ptrs.committed_in = inp;
1103        needs_interrupt
1104    }
1105
1106    /// Writes the header of the next packet and returns the ring range for the
1107    /// payload. The caller should write the payload, then commit the write (or
1108    /// multiple writes) with `commit_write`.
1109    ///
1110    /// Returns `Err(RingFull(len))` if the ring is full, where `len` is the
1111    /// number of bytes needed to write the requested packet.
1112    pub fn write(
1113        &self,
1114        ptrs: &mut OutgoingOffset,
1115        packet: &OutgoingPacket<'_>,
1116    ) -> Result<RingRange, WriteError> {
1117        const DESCRIPTOR_SIZE: usize = size_of::<PacketDescriptor>();
1118        let (packet_type, header_size, flags) = match packet.typ {
1119            OutgoingPacketType::InBandNoCompletion => (PACKET_TYPE_IN_BAND, DESCRIPTOR_SIZE, 0),
1120            OutgoingPacketType::InBandWithCompletion => (
1121                PACKET_TYPE_IN_BAND,
1122                DESCRIPTOR_SIZE,
1123                PACKET_FLAG_COMPLETION_REQUESTED,
1124            ),
1125            OutgoingPacketType::Completion => (PACKET_TYPE_COMPLETION, DESCRIPTOR_SIZE, 0),
1126            OutgoingPacketType::GpaDirect(ranges) => (
1127                PACKET_TYPE_GPA_DIRECT,
1128                DESCRIPTOR_SIZE
1129                    + size_of::<GpaDirectHeader>()
1130                    + ranges.iter().fold(0, |a, range| {
1131                        a + size_of::<GpaRange>() + size_of_val(range.gpns())
1132                    }),
1133                PACKET_FLAG_COMPLETION_REQUESTED,
1134            ),
1135            OutgoingPacketType::TransferPages(_, ranges) => (
1136                PACKET_TYPE_TRANSFER_PAGES,
1137                DESCRIPTOR_SIZE + size_of::<TransferPageHeader>() + size_of_val(ranges),
1138                PACKET_FLAG_COMPLETION_REQUESTED,
1139            ),
1140        };
1141        let msg_len = (packet.size + header_size).div_ceil(8) * 8;
1142        let total_msg_len = (msg_len + size_of::<Footer>()) as u32;
1143        if total_msg_len >= self.inner.len() - 8 {
1144            return Err(WriteError::Corrupt(Error::InvalidMessageLength));
1145        }
1146        let inp = ptrs.next_in;
1147        let mut outp = ptrs.cached_out;
1148        if self.inner.free(inp, outp) < total_msg_len {
1149            outp = self
1150                .inner
1151                .validate(self.inner.control().outp().load(Ordering::Relaxed))?;
1152            if self.inner.free(inp, outp) < total_msg_len {
1153                return Err(WriteError::Full(total_msg_len as usize));
1154            }
1155            ptrs.cached_out = outp;
1156        }
1157        let desc = PacketDescriptor {
1158            packet_type,
1159            data_offset8: header_size as u16 / 8,
1160            length8: (msg_len / 8) as u16,
1161            flags,
1162            transaction_id: packet.transaction_id,
1163        };
1164
1165        let footer = Footer {
1166            reserved: 0,
1167            offset: inp,
1168        };
1169
1170        let off = inp as usize;
1171        self.inner.mem.write_aligned(off, desc.as_bytes());
1172        match packet.typ {
1173            OutgoingPacketType::GpaDirect(ranges) => {
1174                let mut writer = RingRange {
1175                    off: (off + DESCRIPTOR_SIZE) as u32,
1176                    size: header_size as u32,
1177                }
1178                .writer(self);
1179                let gpa_header = GpaDirectHeader {
1180                    reserved: 0,
1181                    range_count: ranges.len() as u32,
1182                };
1183                writer
1184                    .write(gpa_header.as_bytes())
1185                    .map_err(|_| WriteError::Corrupt(Error::InvalidMessageLength))?;
1186
1187                for range in ranges {
1188                    let gpa_rng = GpaRange {
1189                        len: range.len() as u32,
1190                        offset: range.offset() as u32,
1191                    };
1192                    writer
1193                        .write(gpa_rng.as_bytes())
1194                        .map_err(|_| WriteError::Corrupt(Error::InvalidMessageLength))?;
1195                    writer
1196                        .write(range.gpns().as_bytes())
1197                        .map_err(|_| WriteError::Corrupt(Error::InvalidMessageLength))?;
1198                }
1199            }
1200            OutgoingPacketType::TransferPages(tp_id, ranges) => {
1201                let tp_header = TransferPageHeader {
1202                    transfer_page_set_id: tp_id,
1203                    reserved: 0,
1204                    range_count: ranges.len() as u32,
1205                };
1206                self.inner
1207                    .mem
1208                    .write_aligned(off + DESCRIPTOR_SIZE, tp_header.as_bytes());
1209                for (i, range) in ranges.iter().enumerate() {
1210                    self.inner.mem.write_aligned(
1211                        off + DESCRIPTOR_SIZE + size_of_val(&tp_header) + i * 8,
1212                        range.as_bytes(),
1213                    );
1214                }
1215            }
1216            _ => (),
1217        }
1218
1219        self.inner
1220            .mem
1221            .write_aligned(off + msg_len, footer.as_bytes());
1222        ptrs.next_in = self.inner.add_pointer(inp, total_msg_len);
1223        Ok(RingRange {
1224            off: inp + header_size as u32,
1225            size: packet.size as u32,
1226        })
1227    }
1228}
1229
1230struct InnerRing<M: RingMem> {
1231    mem: M,
1232    size: u32,
1233}
1234
1235impl<M: RingMem> Inspect for InnerRing<M> {
1236    fn inspect(&self, req: inspect::Request<'_>) {
1237        req.respond()
1238            .hex("ring_size", self.size)
1239            .field("control", self.control());
1240    }
1241}
1242
1243/// Inspects ring buffer state without creating an IncomingRing or OutgoingRing
1244/// structure.
1245///
1246/// # Panics
1247///
1248/// Panics if control_page is not aligned.
1249pub fn inspect_ring(control_page: &guestmem::Page, response: &mut inspect::Response<'_>) {
1250    let control = Control::from_page(control_page).expect("control page is not aligned");
1251    response.field("control", control);
1252}
1253
1254/// Returns whether a ring buffer is in a state where the receiving end might
1255/// need a signal.
1256pub fn reader_needs_signal(control_page: &guestmem::Page) -> bool {
1257    Control::from_page(control_page).is_some_and(|control| {
1258        control.interrupt_mask().load(Ordering::Relaxed) == 0
1259            && (control.inp().load(Ordering::Relaxed) != control.outp().load(Ordering::Relaxed))
1260    })
1261}
1262
1263/// Returns whether a ring buffer is in a state where the sending end might need
1264/// a signal.
1265pub fn writer_needs_signal(control_page: &guestmem::Page, ring_size: u32) -> bool {
1266    Control::from_page(control_page).is_some_and(|control| {
1267        let pending_size = control.pending_send_size().load(Ordering::Relaxed);
1268        pending_size != 0
1269            && ring_free(
1270                ring_size,
1271                control.inp().load(Ordering::Relaxed),
1272                control.outp().load(Ordering::Relaxed),
1273            ) >= pending_size
1274    })
1275}
1276
1277impl<M: RingMem> Debug for InnerRing<M> {
1278    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1279        f.debug_struct("InnerRing")
1280            .field("control", &self.control())
1281            .field("size", &self.size)
1282            .finish()
1283    }
1284}
1285
1286impl<M: RingMem> InnerRing<M> {
1287    pub fn new(mem: M) -> Result<Self, Error> {
1288        let ring_size = u32::try_from(mem.len()).map_err(|_| Error::InvalidRingMemory)?;
1289        if ring_size % 4096 != 0 {
1290            return Err(Error::InvalidRingMemory);
1291        }
1292        let ring = InnerRing {
1293            mem,
1294            size: ring_size,
1295        };
1296        Ok(ring)
1297    }
1298
1299    fn control(&self) -> Control<'_> {
1300        Control(self.mem.control())
1301    }
1302
1303    fn len(&self) -> u32 {
1304        self.size
1305    }
1306
1307    fn validate(&self, p: u32) -> Result<u32, Error> {
1308        if p >= self.size || !p.is_multiple_of(8) {
1309            Err(Error::InvalidRingPointer)
1310        } else {
1311            Ok(p)
1312        }
1313    }
1314
1315    fn add_pointer(&self, p: u32, off: u32) -> u32 {
1316        let np = p + off;
1317        if np >= self.size {
1318            assert!(np < self.size * 2);
1319            np - self.size
1320        } else {
1321            np
1322        }
1323    }
1324
1325    fn available(&self, inp: u32, outp: u32) -> u32 {
1326        if inp > outp {
1327            // |____outp....inp_____|
1328            inp - outp
1329        } else {
1330            // |....inp____outp.....|
1331            self.size + inp - outp
1332        }
1333    }
1334
1335    fn free(&self, inp: u32, outp: u32) -> u32 {
1336        ring_free(self.size, inp, outp)
1337    }
1338}
1339
1340fn ring_free(size: u32, inp: u32, outp: u32) -> u32 {
1341    // It's not possible to fully fill the ring since that state would be
1342    // indistinguishable from the empty ring. So subtract 8 bytes from the
1343    // result.
1344    if outp > inp {
1345        // |....inp____outp.....|
1346        outp - inp - 8
1347    } else {
1348        // |____outp....inp_____|
1349        size - (inp - outp) - 8
1350    }
1351}
1352
1353#[cfg(test)]
1354mod tests {
1355    use super::*;
1356
1357    fn write_simple<T: RingMem>(out_ring: &mut OutgoingRing<T>, buf: &[u8]) -> Option<bool> {
1358        let mut outgoing = out_ring.outgoing().unwrap();
1359        match out_ring.write(
1360            &mut outgoing,
1361            &OutgoingPacket {
1362                typ: OutgoingPacketType::InBandNoCompletion,
1363                size: buf.len(),
1364                transaction_id: 0,
1365            },
1366        ) {
1367            Ok(range) => {
1368                range.writer(out_ring).write(buf).unwrap();
1369                Some(out_ring.commit_write(&mut outgoing))
1370            }
1371            Err(WriteError::Full(_)) => None,
1372            Err(err) => panic!("{}", err),
1373        }
1374    }
1375
1376    fn read_simple<T: RingMem>(in_ring: &mut IncomingRing<T>) -> (Vec<u8>, bool) {
1377        let mut incoming = in_ring.incoming().unwrap();
1378        let msg = in_ring
1379            .read(&mut incoming)
1380            .unwrap()
1381            .payload
1382            .reader(in_ring)
1383            .read_all()
1384            .unwrap();
1385        let signal = in_ring.commit_read(&mut incoming);
1386        (msg, signal)
1387    }
1388
1389    #[test]
1390    fn test_ring() {
1391        let rmem = FlatRingMem::new(16384);
1392        let mut in_ring = IncomingRing::new(&rmem).unwrap();
1393        in_ring.set_interrupt_mask(false);
1394        let mut out_ring = OutgoingRing::new(&rmem).unwrap();
1395
1396        let p = &[1, 2, 3, 4, 5, 6, 7, 8];
1397        assert!(write_simple(&mut out_ring, p).unwrap());
1398
1399        let (msg, signal) = read_simple(&mut in_ring);
1400        assert!(!signal);
1401
1402        assert_eq!(p, &msg[..]);
1403    }
1404
1405    #[test]
1406    fn test_interrupt_mask() {
1407        let rmem = FlatRingMem::new(16384);
1408        let mut in_ring = IncomingRing::new(&rmem).unwrap();
1409        let mut out_ring = OutgoingRing::new(&rmem).unwrap();
1410
1411        // Interrupts are masked, so no signal is expected.
1412        assert!(!write_simple(&mut out_ring, &[1, 2, 3]).unwrap());
1413        assert!(!read_simple(&mut in_ring).1);
1414
1415        // Unmask interrupts, then try again, expecting a signal this time.
1416        in_ring.set_interrupt_mask(false);
1417        assert!(write_simple(&mut out_ring, &[1, 2, 3]).unwrap());
1418        assert!(!read_simple(&mut in_ring).1);
1419    }
1420
1421    #[test]
1422    fn test_pending_send_size() {
1423        let rmem = FlatRingMem::new(16384);
1424        let mut in_ring = IncomingRing::new(&rmem).unwrap();
1425        let mut out_ring = OutgoingRing::new(&rmem).unwrap();
1426
1427        // Fill the ring up with some packets.
1428        write_simple(&mut out_ring, &[1; 4000]).unwrap();
1429        write_simple(&mut out_ring, &[2; 4000]).unwrap();
1430        write_simple(&mut out_ring, &[3; 4000]).unwrap();
1431        write_simple(&mut out_ring, &[4; 4000]).unwrap();
1432        assert!(write_simple(&mut out_ring, &[5; 4000]).is_none());
1433
1434        // No pending send size yet.
1435        assert!(!read_simple(&mut in_ring).1);
1436
1437        // Fill the ring back up.
1438        write_simple(&mut out_ring, &[5; 4000]).unwrap();
1439        assert!(write_simple(&mut out_ring, &[6; 4000]).is_none());
1440
1441        // Set a pending send size for two packets worth of space (packet size +
1442        // 16 bytes for the descriptor and 8 bytes for the footer).
1443        out_ring.set_pending_send_size(4024 * 2).unwrap();
1444
1445        // There should be a signal after two packets, then no more signals.
1446        assert!(!read_simple(&mut in_ring).1);
1447        assert!(read_simple(&mut in_ring).1);
1448        assert!(!read_simple(&mut in_ring).1);
1449    }
1450
1451    #[test]
1452    fn test_malformed_gpa_direct_packet() {
1453        let rmem = FlatRingMem::new(16384);
1454
1455        let desc = PacketDescriptor {
1456            packet_type: PACKET_TYPE_GPA_DIRECT,
1457            data_offset8: 2,
1458            length8: 3,
1459            flags: 0,
1460            transaction_id: 0,
1461        };
1462
1463        rmem.write_aligned(0, desc.as_bytes());
1464        let header = GpaDirectHeader {
1465            reserved: 0,
1466            range_count: 1,
1467        };
1468        rmem.write_aligned(size_of::<PacketDescriptor>(), header.as_bytes());
1469        let err = parse_packet(&rmem, 0, 16384).unwrap_err();
1470        assert!(matches!(
1471            err,
1472            ReadError::Corrupt(Error::InvalidDescriptorLengths)
1473        ));
1474    }
1475
1476    #[test]
1477    fn test_malformed_transfer_page_packet() {
1478        let rmem = FlatRingMem::new(16384);
1479
1480        let desc = PacketDescriptor {
1481            packet_type: PACKET_TYPE_TRANSFER_PAGES,
1482            data_offset8: 2,
1483            length8: 3,
1484            flags: 0,
1485            transaction_id: 0,
1486        };
1487
1488        rmem.write_aligned(0, desc.as_bytes());
1489        let header = TransferPageHeader {
1490            range_count: 1,
1491            transfer_page_set_id: 1,
1492            reserved: 0,
1493        };
1494        rmem.write_aligned(size_of::<PacketDescriptor>(), header.as_bytes());
1495        let err = parse_packet(&rmem, 0, 16384).unwrap_err();
1496        assert!(matches!(
1497            err,
1498            ReadError::Corrupt(Error::InvalidDescriptorLengths)
1499        ));
1500    }
1501}