1#![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 #[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 pub const PIPE_PACKET_TYPE_DATA: u32 = 1;
63 pub const PIPE_PACKET_TYPE_PARTIAL: u32 = 2;
67 pub const PIPE_PACKET_TYPE_SETUP_GPA_DIRECT: u32 = 3;
69 pub const PIPE_PACKET_TYPE_TEARDOWN_GPA_DIRECT: u32 = 4;
71
72 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 pub const PAGE_SIZE: usize = 4096;
90
91 #[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 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 pub const FEATURE_SUPPORTS_PENDING_SEND_SIZE: u32 = 1;
162
163 #[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 #[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, pub range_count: u32,
180 }
181
182 #[repr(C)]
184 #[derive(Copy, Clone, Debug, IntoBytes, Immutable, KnownLayout, FromBytes)]
185 pub struct GpaDirectHeader {
186 pub reserved: u32, pub range_count: u32,
188 }
189
190 pub const PACKET_FLAG_COMPLETION_REQUESTED: u16 = 1;
191
192 #[repr(C)]
194 #[derive(Copy, Clone, Debug, IntoBytes, Immutable, KnownLayout, FromBytes)]
195 pub struct Footer {
196 pub reserved: u32,
197 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#[derive(Copy, Clone, Debug)]
244pub struct RingRange {
245 off: u32,
246 size: u32,
247}
248
249impl RingRange {
250 pub fn empty() -> Self {
252 RingRange { off: 0, size: 0 }
253 }
254
255 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 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 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 pub fn len(&self) -> usize {
284 self.size as usize
285 }
286
287 pub fn is_empty(&self) -> bool {
289 self.size == 0
290 }
291}
292
293pub 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
323pub 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#[derive(Debug, Copy, Clone)]
353pub enum IncomingPacketType {
354 InBand,
355 Completion,
356 GpaDirect(u32, RingRange),
357 TransferPages(u16, u32, RingRange),
358}
359
360#[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
464pub const CONTROL_WORD_COUNT: usize = 32;
466
467pub trait RingMem: Send {
469 fn control(&self) -> &[AtomicU32; CONTROL_WORD_COUNT];
471
472 fn read_at(&self, addr: usize, data: &mut [u8]);
475
476 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 fn write_at(&self, addr: usize, data: &[u8]);
489
490 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 fn len(&self) -> usize;
502}
503
504impl<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#[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 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
650pub trait PagedMemory: Send {
652 fn control(&self) -> &[AtomicU8; PAGE_SIZE];
654 fn data_page_count(&self) -> usize;
656 fn data(&self, page: usize) -> &[AtomicU8; PAGE_SIZE];
663}
664
665#[derive(Debug, Clone)]
667pub struct PagedRingMem<T>(T);
668
669impl<T: PagedMemory> PagedRingMem<T> {
670 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#[derive(Debug)]
750pub struct OutgoingPacket<'a> {
751 pub transaction_id: u64,
752 pub size: usize,
753 pub typ: OutgoingPacketType<'a>,
754}
755
756#[derive(Debug, Copy, Clone)]
758pub enum OutgoingPacketType<'a> {
759 InBandNoCompletion,
761 InBandWithCompletion,
763 Completion,
765 GpaDirect(&'a [PagedRange<'a>]),
769 TransferPages(u16, &'a [TransferPageRange]),
776}
777
778pub struct PacketSize(());
781
782impl PacketSize {
783 pub const fn in_band(payload_len: usize) -> usize {
785 size_of::<PacketDescriptor>() + ((payload_len + 7) & !7) + size_of::<Footer>()
786 }
787
788 pub const fn completion(payload_len: usize) -> usize {
790 Self::in_band(payload_len)
791 }
792
793 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
804pub trait Ring {
807 type Memory: RingMem;
809
810 fn mem(&self) -> &Self::Memory;
812}
813
814#[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#[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 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 pub fn new(mem: M) -> Result<Self, Error> {
855 let inner = InnerRing::new(mem)?;
856 let control = inner.control();
858 control.interrupt_mask().store(1, Ordering::Relaxed);
859 Ok(Self { inner })
860 }
861
862 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 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 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 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 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 incoming.cached_in = inp;
921 incoming.next_out != inp
922 };
923 Ok(can_read)
924 }
925
926 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 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 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#[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#[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 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 pub fn new(mem: M) -> Result<Self, Error> {
1024 let inner = InnerRing::new(mem)?;
1025 let control = inner.control();
1029 control
1030 .feature_bits()
1031 .store(FEATURE_SUPPORTS_PENDING_SEND_SIZE, Ordering::Relaxed);
1032 control.pending_send_size().store(0, Ordering::Relaxed);
1034 Ok(Self { inner })
1035 }
1036
1037 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 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 pub fn maximum_packet_size(&self) -> usize {
1070 self.inner.len() as usize - 8
1071 }
1072
1073 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 ptrs.cached_out = outp;
1085 self.inner.free(ptrs.next_in, outp) as usize >= len
1086 };
1087 Ok(can_write)
1088 }
1089
1090 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 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 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
1247pub 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
1258pub 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
1267pub 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 inp - outp
1333 } else {
1334 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 if outp > inp {
1349 outp - inp - 8
1351 } else {
1352 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 assert!(!write_simple(&mut out_ring, &[1, 2, 3]).unwrap());
1417 assert!(!read_simple(&mut in_ring).1);
1418
1419 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 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 assert!(!read_simple(&mut in_ring).1);
1440
1441 write_simple(&mut out_ring, &[5; 4000]).unwrap();
1443 assert!(write_simple(&mut out_ring, &[6; 4000]).is_none());
1444
1445 out_ring.set_pending_send_size(4024 * 2).unwrap();
1448
1449 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}