Skip to main content

virtio_resources/
lib.rs

1// Copyright (c) Microsoft Corporation.
2// Licensed under the MIT License.
3
4//! VM resource definitions for virtio devices.
5//!
6//! Device-specific definitions are here to avoid needing to pull in a device
7//! implementation crate just to construct the device's config.
8
9#![expect(missing_docs)]
10#![forbid(unsafe_code)]
11
12use mesh::MeshPayload;
13use vm_resource::Resource;
14use vm_resource::ResourceId;
15use vm_resource::kind::PciDeviceHandleKind;
16use vm_resource::kind::VirtioDeviceHandle;
17
18/// A resource for mapping a virtio device as a PCI device.
19#[derive(MeshPayload)]
20pub struct VirtioPciDeviceHandle(pub Resource<VirtioDeviceHandle>);
21
22impl ResourceId<PciDeviceHandleKind> for VirtioPciDeviceHandle {
23    const ID: &'static str = "virtio";
24}
25
26pub mod p9 {
27    use mesh::MeshPayload;
28    use vm_resource::ResourceId;
29    use vm_resource::kind::VirtioDeviceHandle;
30
31    #[derive(MeshPayload)]
32    pub struct VirtioPlan9Handle {
33        pub tag: String,
34        pub root_path: String,
35        pub debug: bool,
36    }
37
38    impl ResourceId<VirtioDeviceHandle> for VirtioPlan9Handle {
39        const ID: &'static str = "virtio-9p";
40    }
41}
42
43pub mod fs {
44    use mesh::MeshPayload;
45    use vm_resource::ResourceId;
46    use vm_resource::kind::VirtioDeviceHandle;
47
48    #[derive(MeshPayload)]
49    pub struct VirtioFsHandle {
50        pub tag: String,
51        pub fs: VirtioFsBackend,
52    }
53
54    #[derive(MeshPayload)]
55    pub enum VirtioFsBackend {
56        HostFs {
57            root_path: String,
58            mount_options: String,
59        },
60        SectionFs {
61            root_path: String,
62        },
63        /// Expose multiple host folders behind a single device, each as a named
64        /// child of a synthetic root. Lets one virtio-fs device (one tag, one
65        /// PCI/MMIO footprint) serve many shares.
66        Aggregate {
67            children: Vec<VirtioFsAggregateChild>,
68        },
69    }
70
71    /// A single host folder exposed as a named child of a [`VirtioFsBackend::Aggregate`].
72    #[derive(MeshPayload)]
73    pub struct VirtioFsAggregateChild {
74        /// Name of this child's directory under the aggregate's synthetic root;
75        /// the guest bind-mounts `<aggregate-mount>/<name>` onto the user's
76        /// target path.
77        pub name: String,
78        pub root_path: String,
79        pub mount_options: String,
80    }
81
82    impl ResourceId<VirtioDeviceHandle> for VirtioFsHandle {
83        const ID: &'static str = "virtiofs";
84    }
85}
86
87pub mod pmem {
88    use mesh::MeshPayload;
89    use vm_resource::ResourceId;
90    use vm_resource::kind::VirtioDeviceHandle;
91
92    #[derive(MeshPayload)]
93    pub struct VirtioPmemHandle {
94        pub path: String,
95    }
96
97    impl ResourceId<VirtioDeviceHandle> for VirtioPmemHandle {
98        const ID: &'static str = "virtio-pmem";
99    }
100}
101
102pub mod rng {
103    use mesh::MeshPayload;
104    use vm_resource::ResourceId;
105    use vm_resource::kind::VirtioDeviceHandle;
106
107    #[derive(MeshPayload)]
108    pub struct VirtioRngHandle;
109
110    impl ResourceId<VirtioDeviceHandle> for VirtioRngHandle {
111        const ID: &'static str = "virtio-rng";
112    }
113}
114
115pub mod blk {
116    use mesh::MeshPayload;
117    use vm_resource::Resource;
118    use vm_resource::ResourceId;
119    use vm_resource::kind::DiskHandleKind;
120    use vm_resource::kind::VirtioDeviceHandle;
121
122    #[derive(MeshPayload)]
123    pub struct VirtioBlkHandle {
124        pub disk: Resource<DiskHandleKind>,
125        pub read_only: bool,
126    }
127
128    impl ResourceId<VirtioDeviceHandle> for VirtioBlkHandle {
129        const ID: &'static str = "virtio-blk";
130    }
131}
132
133pub mod net {
134    use mesh::MeshPayload;
135    use net_backend_resources::mac_address::MacAddress;
136    use vm_resource::Resource;
137    use vm_resource::ResourceId;
138    use vm_resource::kind::NetEndpointHandleKind;
139    use vm_resource::kind::VirtioDeviceHandle;
140
141    #[derive(MeshPayload)]
142    pub struct VirtioNetHandle {
143        pub max_queues: Option<u16>,
144        pub mac_address: MacAddress,
145        pub endpoint: Resource<NetEndpointHandleKind>,
146    }
147
148    impl ResourceId<VirtioDeviceHandle> for VirtioNetHandle {
149        const ID: &'static str = "virtio-net";
150    }
151}
152
153pub mod console {
154    use mesh::MeshPayload;
155    use vm_resource::Resource;
156    use vm_resource::ResourceId;
157    use vm_resource::kind::SerialBackendHandle;
158    use vm_resource::kind::VirtioDeviceHandle;
159
160    #[derive(MeshPayload)]
161    pub struct VirtioConsoleHandle {
162        pub backend: Resource<SerialBackendHandle>,
163    }
164
165    impl ResourceId<VirtioDeviceHandle> for VirtioConsoleHandle {
166        const ID: &'static str = "virtio-console";
167    }
168}
169
170#[cfg(unix)]
171pub mod vhost_user {
172    use mesh::MeshPayload;
173    use std::os::fd::OwnedFd;
174    use vm_resource::ResourceId;
175    use vm_resource::kind::VirtioDeviceHandle;
176
177    /// Handle for a generic vhost-user device backed by an external process.
178    ///
179    /// The socket must already be connected. The CLI layer connects
180    /// to the backend and passes the connected fd here.
181    ///
182    /// For device types with specific handles (FS, BLK), use those
183    /// instead. This handle is for devices identified only by their
184    /// numeric virtio device ID.
185    #[derive(MeshPayload)]
186    pub struct VhostUserGenericHandle {
187        /// Connected Unix socket fd to the vhost-user backend.
188        pub socket: OwnedFd,
189        /// Virtio device ID (e.g., 2 for block, 1 for net).
190        pub device_id: u16,
191        /// Per-queue sizes. Length determines the queue count.
192        /// Required — must be non-empty.
193        pub queue_sizes: Vec<u16>,
194    }
195
196    impl ResourceId<VirtioDeviceHandle> for VhostUserGenericHandle {
197        const ID: &'static str = "vhost-user-generic";
198    }
199
200    /// Handle for a vhost-user virtio-fs device.
201    ///
202    /// The frontend owns the config space (tag + num_request_queues)
203    /// and does not negotiate `VHOST_USER_PROTOCOL_F_CONFIG` with the
204    /// backend. The tag is specified by the host, matching the
205    /// behavior of cloud-hypervisor.
206    #[derive(MeshPayload)]
207    pub struct VhostUserFsHandle {
208        /// Connected Unix socket fd to the vhost-user backend.
209        pub socket: OwnedFd,
210        /// The mount tag exposed to the guest (max 36 bytes).
211        pub tag: String,
212        /// Number of request queues (default 1 in resolver).
213        pub num_queues: Option<u16>,
214        /// Queue size for all queues (default 1024 in resolver).
215        pub queue_size: Option<u16>,
216    }
217
218    impl ResourceId<VirtioDeviceHandle> for VhostUserFsHandle {
219        const ID: &'static str = "vhost-user-fs";
220    }
221
222    /// Handle for a vhost-user virtio-blk device.
223    #[derive(MeshPayload)]
224    pub struct VhostUserBlkHandle {
225        /// Connected Unix socket fd to the vhost-user backend.
226        pub socket: OwnedFd,
227        /// Number of queues (default 1 in resolver).
228        pub num_queues: Option<u16>,
229        /// Queue size for all queues (default 128 in resolver).
230        pub queue_size: Option<u16>,
231    }
232
233    impl ResourceId<VirtioDeviceHandle> for VhostUserBlkHandle {
234        const ID: &'static str = "vhost-user-blk";
235    }
236}
237
238pub mod vsock {
239    use mesh::MeshPayload;
240    #[cfg(target_os = "linux")]
241    use std::os::fd::OwnedFd;
242    use unix_socket::UnixListener;
243    use vm_resource::ResourceId;
244    use vm_resource::kind::VirtioDeviceHandle;
245
246    #[derive(MeshPayload)]
247    pub struct VirtioVsockHandle {
248        pub guest_cid: u64,
249        pub base_path: String,
250        pub listener: UnixListener,
251    }
252
253    impl ResourceId<VirtioDeviceHandle> for VirtioVsockHandle {
254        const ID: &'static str = "virtio-vsock";
255    }
256
257    /// A virtio-vsock device backed by the Linux kernel's `vhost_vsock`
258    /// implementation.
259    #[cfg(target_os = "linux")]
260    #[derive(MeshPayload)]
261    pub struct VirtioVsockVhostHandle {
262        /// A pre-opened `/dev/vhost-vsock` file descriptor.
263        ///
264        /// The device resolver takes ownership and configures the vhost owner
265        /// and guest CID.
266        pub vhost: OwnedFd,
267        /// The CID used to address the guest from the host's `AF_VSOCK`
268        /// namespace.
269        pub guest_cid: u32,
270    }
271
272    #[cfg(target_os = "linux")]
273    impl ResourceId<VirtioDeviceHandle> for VirtioVsockVhostHandle {
274        const ID: &'static str = "virtio-vsock-vhost";
275    }
276}