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