1#![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 #[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 pub const PIPE_PACKET_TYPE_DATA: u32 = 1;
59 pub const PIPE_PACKET_TYPE_PARTIAL: u32 = 2;
63 pub const PIPE_PACKET_TYPE_SETUP_GPA_DIRECT: u32 = 3;
65 pub const PIPE_PACKET_TYPE_TEARDOWN_GPA_DIRECT: u32 = 4;
67
68 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 pub const PAGE_SIZE: usize = 4096;
86
87 #[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 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 pub const FEATURE_SUPPORTS_PENDING_SEND_SIZE: u32 = 1;
158
159 #[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 #[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, pub range_count: u32,
176 }
177
178 #[repr(C)]
180 #[derive(Copy, Clone, Debug, IntoBytes, Immutable, KnownLayout, FromBytes)]
181 pub struct GpaDirectHeader {
182 pub reserved: u32, pub range_count: u32,
184 }
185
186 pub const PACKET_FLAG_COMPLETION_REQUESTED: u16 = 1;
187
188 #[repr(C)]
190 #[derive(Copy, Clone, Debug, IntoBytes, Immutable, KnownLayout, FromBytes)]
191 pub struct Footer {
192 pub reserved: u32,
193 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#[derive(Copy, Clone, Debug)]
240pub struct RingRange {
241 off: u32,
242 size: u32,
243}
244
245impl RingRange {
246 pub fn empty() -> Self {
248 RingRange { off: 0, size: 0 }
249 }
250
251 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 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 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 pub fn len(&self) -> usize {
280 self.size as usize
281 }
282
283 pub fn is_empty(&self) -> bool {
285 self.size == 0
286 }
287}
288
289pub 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
319pub 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#[derive(Debug, Copy, Clone)]
349pub enum IncomingPacketType {
350 InBand,
351 Completion,
352 GpaDirect(u32, RingRange),
353 TransferPages(u16, u32, RingRange),
354}
355
356#[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
460pub const CONTROL_WORD_COUNT: usize = 32;
462
463pub trait RingMem: Send {
465 fn control(&self) -> &[AtomicU32; CONTROL_WORD_COUNT];
467
468 fn read_at(&self, addr: usize, data: &mut [u8]);
471
472 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 fn write_at(&self, addr: usize, data: &[u8]);
485
486 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 fn len(&self) -> usize;
498}
499
500impl<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#[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 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
646pub trait PagedMemory: Send {
648 fn control(&self) -> &[AtomicU8; PAGE_SIZE];
650 fn data_page_count(&self) -> usize;
652 fn data(&self, page: usize) -> &[AtomicU8; PAGE_SIZE];
659}
660
661#[derive(Debug, Clone)]
663pub struct PagedRingMem<T>(T);
664
665impl<T: PagedMemory> PagedRingMem<T> {
666 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#[derive(Debug)]
746pub struct OutgoingPacket<'a> {
747 pub transaction_id: u64,
748 pub size: usize,
749 pub typ: OutgoingPacketType<'a>,
750}
751
752#[derive(Debug, Copy, Clone)]
754pub enum OutgoingPacketType<'a> {
755 InBandNoCompletion,
757 InBandWithCompletion,
759 Completion,
761 GpaDirect(&'a [PagedRange<'a>]),
765 TransferPages(u16, &'a [TransferPageRange]),
772}
773
774pub struct PacketSize(());
777
778impl PacketSize {
779 pub const fn in_band(payload_len: usize) -> usize {
781 size_of::<PacketDescriptor>() + ((payload_len + 7) & !7) + size_of::<Footer>()
782 }
783
784 pub const fn completion(payload_len: usize) -> usize {
786 Self::in_band(payload_len)
787 }
788
789 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
800pub trait Ring {
803 type Memory: RingMem;
805
806 fn mem(&self) -> &Self::Memory;
808}
809
810#[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#[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 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 pub fn new(mem: M) -> Result<Self, Error> {
851 let inner = InnerRing::new(mem)?;
852 let control = inner.control();
854 control.interrupt_mask().store(1, Ordering::Relaxed);
855 Ok(Self { inner })
856 }
857
858 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 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 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 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 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 incoming.cached_in = inp;
917 incoming.next_out != inp
918 };
919 Ok(can_read)
920 }
921
922 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 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 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#[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#[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 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 pub fn new(mem: M) -> Result<Self, Error> {
1020 let inner = InnerRing::new(mem)?;
1021 let control = inner.control();
1025 control
1026 .feature_bits()
1027 .store(FEATURE_SUPPORTS_PENDING_SEND_SIZE, Ordering::Relaxed);
1028 control.pending_send_size().store(0, Ordering::Relaxed);
1030 Ok(Self { inner })
1031 }
1032
1033 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 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 pub fn maximum_packet_size(&self) -> usize {
1066 self.inner.len() as usize - 8
1067 }
1068
1069 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 ptrs.cached_out = outp;
1081 self.inner.free(ptrs.next_in, outp) as usize >= len
1082 };
1083 Ok(can_write)
1084 }
1085
1086 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 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 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
1243pub 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
1254pub 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
1263pub 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 inp - outp
1329 } else {
1330 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 if outp > inp {
1345 outp - inp - 8
1347 } else {
1348 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 assert!(!write_simple(&mut out_ring, &[1, 2, 3]).unwrap());
1413 assert!(!read_simple(&mut in_ring).1);
1414
1415 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 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 assert!(!read_simple(&mut in_ring).1);
1436
1437 write_simple(&mut out_ring, &[5; 4000]).unwrap();
1439 assert!(write_simple(&mut out_ring, &[6; 4000]).is_none());
1440
1441 out_ring.set_pending_send_size(4024 * 2).unwrap();
1444
1445 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}