Skip to main content

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}