virtio_driver/transports/mod.rs
1// SPDX-License-Identifier: (MIT OR Apache-2.0)
2
3use std::io::Error;
4use std::os::unix::io::RawFd;
5use std::sync::Arc;
6
7#[cfg(feature = "pci")]
8mod pci;
9#[cfg(feature = "vhost-user")]
10mod vhost_user;
11#[cfg(feature = "vhost-vdpa")]
12mod vhost_vdpa;
13
14#[cfg(feature = "pci")]
15pub use pci::Pci;
16#[cfg(feature = "vhost-user")]
17pub use vhost_user::VhostUser;
18#[cfg(feature = "vhost-vdpa")]
19pub use vhost_vdpa::VhostVdpa;
20
21use crate::util::bytevalued::ByteValued;
22use crate::util::eventfd::EventFd;
23use crate::util::iova::Iova;
24use crate::virtqueue::{Virtqueue, VirtqueueLayout};
25
26/// Something that can translate process addresses into IOVAs.
27pub trait IovaTranslator: Send + Sync {
28 /// Determines the base IOVA corresponding to the given process address range.
29 ///
30 /// If the transport requires memory to be mapped prior to use but the address doesn't belong to
31 /// a mapped memory region, an `Err` will be returned.
32 ///
33 /// The `addr..addr + len` range must not cross memory region boundaries, otherwise `Err` is
34 /// returned.
35 fn translate_addr(&self, addr: usize, len: usize) -> Result<Iova, Error>;
36}
37
38/// An interface to the virtio transport/bus of a device
39///
40/// Type parameters:
41/// - `C` represents the device configuration space, as returned by [`VirtioTransport::get_config`];
42/// - `R` has the same meaning as in [`Virtqueue`], and is used to store device-specific per-request
43/// data.
44pub trait VirtioTransport<C: ByteValued, R: Copy>: Send + Sync {
45 /// Returns the maximum number of queues supported by the device if the transport is able to
46 /// get this information.
47 fn max_queues(&self) -> Option<usize>;
48
49 /// Returns the maximum number of memory regions supported by the transport.
50 fn max_mem_regions(&self) -> u64;
51
52 /// Returns the alignment requirement in bytes of the memory region
53 fn mem_region_alignment(&self) -> usize;
54
55 /// Allocates or maps the memory to store the virtqueues in.
56 ///
57 /// This memory must be accessible by the device and is also used for additional per-request
58 /// metadata (such as request headers) that is created internally by the driver and must be
59 /// visible for the device.
60 fn alloc_queue_mem(&mut self, layout: &VirtqueueLayout) -> Result<&mut [u8], Error>;
61
62 /// Maps a memory region with the transport.
63 ///
64 /// Returns the IOVA corresponding to the start of the memory region.
65 ///
66 /// Requests to the device may only refer to memory that is in a mapped memory region.
67 fn map_mem_region(
68 &mut self,
69 addr: usize,
70 len: usize,
71 fd: RawFd,
72 fd_offset: i64,
73 ) -> Result<Iova, Error>;
74
75 /// Unmaps a memory region from the transport.
76 ///
77 /// Note that mapped regions are implicitly unmapped when the transport is dropped.
78 fn unmap_mem_region(&mut self, addr: usize, len: usize) -> Result<(), Error>;
79
80 /// Returns a value that can translate process addresses into IOVAs.
81 fn iova_translator(&self) -> Box<dyn IovaTranslator>;
82
83 /// Initialises and enables the passed queues on the transport level.
84 fn setup_queues(&mut self, queues: &[Virtqueue<R>]) -> Result<(), Error>;
85
86 /// Returns the negotiated virtio feature flags.
87 fn get_features(&self) -> u64;
88
89 /// Queries the device configuration.
90 fn get_config(&self) -> Result<C, Error>;
91
92 /// Returns a [`QueueNotifier`] that can be used to notify the device of new requests in the
93 /// queue.
94 fn get_submission_notifier(&self, queue_idx: usize) -> Box<dyn QueueNotifier>;
95
96 /// Returns an [`EventFd`] that can be read to be notified of request completions in the queue.
97 fn get_completion_fd(&self, queue_idx: usize) -> Arc<EventFd>;
98}
99
100/// A trait for types that can be used to submit available buffer notifications to a queue.
101pub trait QueueNotifier: Send + Sync {
102 /// Trigger an available buffer notification.
103 fn notify(&self) -> Result<(), Error>;
104}