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}