arcbox_virtio/lib.rs
1//! # arcbox-virtio
2//!
3//! `VirtIO` device implementations for `ArcBox`.
4//!
5//! This crate provides `VirtIO` device emulation including:
6//!
7//! - [`blk`]: Block device (virtio-blk)
8//! - [`net`]: Network device (virtio-net)
9//! - [`console`]: Console device (virtio-console)
10//! - [`fs`]: Filesystem device (virtio-fs)
11//! - [`vsock`]: Socket device (virtio-vsock)
12//!
13//! ## `VirtIO` Queue
14//!
15//! All devices use the standard `VirtIO` queue (virtqueue) mechanism for
16//! communication with the guest. The [`queue`] module provides the core
17//! queue implementation.
18//!
19//! ## Architecture
20//!
21//! ```text
22//! ┌─────────────────────────────────────────┐
23//! │ arcbox-virtio │
24//! │ ┌─────┐ ┌─────┐ ┌─────┐ ┌─────┐ ┌────┐│
25//! │ │ blk │ │ net │ │cons │ │ fs │ │vsock││
26//! │ └──┬──┘ └──┬──┘ └──┬──┘ └──┬──┘ └──┬─┘│
27//! │ └───────┴───────┴───────┴───────┘ │
28//! │ │ │
29//! │ VirtQueue │
30//! └─────────────────────────────────────────┘
31//! ```
32
33#![allow(clippy::ptr_as_ptr)]
34#![allow(clippy::borrow_as_ptr)]
35#![allow(clippy::unnecessary_cast)]
36#![allow(clippy::cognitive_complexity)]
37#![allow(clippy::map_unwrap_or)]
38#![allow(clippy::useless_vec)]
39#![allow(clippy::unnecessary_wraps)]
40#![allow(clippy::redundant_clone)]
41#![allow(clippy::unnecessary_map_or)]
42#![allow(clippy::missing_fields_in_debug)]
43#![allow(clippy::needless_lifetimes)]
44#![allow(clippy::needless_collect)]
45#![allow(mismatched_lifetime_syntaxes)]
46
47pub mod blk;
48pub mod console;
49pub mod error;
50pub mod fs;
51pub mod net;
52pub mod queue;
53pub mod vsock;
54
55pub use error::{Result, VirtioError};
56pub use queue::{AvailRing, Descriptor, UsedRing, VirtQueue};
57
58/// `VirtIO` device type IDs.
59#[derive(Debug, Clone, Copy, PartialEq, Eq)]
60#[repr(u32)]
61pub enum VirtioDeviceId {
62 /// Network device.
63 Net = 1,
64 /// Block device.
65 Block = 2,
66 /// Console device.
67 Console = 3,
68 /// Entropy source.
69 Rng = 4,
70 /// Balloon device.
71 Balloon = 5,
72 /// SCSI host.
73 Scsi = 8,
74 /// Filesystem device.
75 Fs = 26,
76 /// Socket device.
77 Vsock = 19,
78}
79
80/// `VirtIO` device status flags.
81#[derive(Debug, Clone, Copy)]
82pub struct DeviceStatus(u8);
83
84impl DeviceStatus {
85 /// Device acknowledged.
86 pub const ACKNOWLEDGE: u8 = 1;
87 /// Driver loaded.
88 pub const DRIVER: u8 = 2;
89 /// Driver is ready.
90 pub const DRIVER_OK: u8 = 4;
91 /// Feature negotiation complete.
92 pub const FEATURES_OK: u8 = 8;
93 /// Device needs reset.
94 pub const DEVICE_NEEDS_RESET: u8 = 64;
95 /// Driver failed.
96 pub const FAILED: u8 = 128;
97
98 /// Creates a new device status.
99 #[must_use]
100 pub const fn new(status: u8) -> Self {
101 Self(status)
102 }
103
104 /// Returns the raw status value.
105 #[must_use]
106 pub const fn raw(&self) -> u8 {
107 self.0
108 }
109
110 /// Checks if a flag is set.
111 #[must_use]
112 pub const fn has(&self, flag: u8) -> bool {
113 self.0 & flag != 0
114 }
115
116 /// Sets a flag.
117 pub const fn set(&mut self, flag: u8) {
118 self.0 |= flag;
119 }
120
121 /// Clears a flag.
122 pub const fn clear(&mut self, flag: u8) {
123 self.0 &= !flag;
124 }
125}
126
127/// Trait for `VirtIO` devices.
128pub trait VirtioDevice: Send + Sync {
129 /// Returns the device type ID.
130 fn device_id(&self) -> VirtioDeviceId;
131
132 /// Returns the device features.
133 fn features(&self) -> u64;
134
135 /// Acknowledges features from the driver.
136 fn ack_features(&mut self, features: u64);
137
138 /// Reads from the device configuration space.
139 fn read_config(&self, offset: u64, data: &mut [u8]);
140
141 /// Writes to the device configuration space.
142 fn write_config(&mut self, offset: u64, data: &[u8]);
143
144 /// Activates the device.
145 fn activate(&mut self) -> Result<()>;
146
147 /// Resets the device.
148 fn reset(&mut self);
149}