#[path = "dev/dev.rs"]
pub mod dev;
pub mod pci;
#[path = "queue/queue.rs"]
pub mod queue;
#[cfg(target_os = "linux")]
pub mod vhost;
#[cfg(target_os = "linux")]
#[path = "vu/vu.rs"]
pub mod vu;
#[path = "worker/worker.rs"]
pub mod worker;
use std::fmt::Debug;
use std::os::fd::BorrowedFd;
use std::path::Path;
use snafu::Snafu;
use crate::errors::{DebugTrace, trace_error};
use crate::{bitflags, consts};
#[trace_error]
#[derive(Snafu, DebugTrace)]
#[snafu(module, context(suffix(false)))]
pub enum Error {
#[snafu(display("Hypervisor internal error"), context(false))]
HvError { source: Box<crate::hv::Error> },
#[snafu(display("Failed to access guest memory"), context(false))]
Memory { source: Box<crate::mem::Error> },
#[snafu(display("PCI bus error"), context(false))]
PciBus { source: crate::pci::Error },
#[snafu(display("Cannot access file {path:?}"))]
AccessFile {
path: Box<Path>,
error: std::io::Error,
},
#[snafu(display("Failed to lock file {path:?}"))]
LockFile {
path: Box<Path>,
error: std::fs::TryLockError,
},
#[snafu(display("Error from OS"), context(false))]
System { error: std::io::Error },
#[snafu(display("Failed to create a poll"))]
CreatePoll { error: std::io::Error },
#[snafu(display("Failed to register/deregister an event source"))]
EventSource { error: std::io::Error },
#[snafu(display("Failed to poll events"))]
PollEvents { error: std::io::Error },
#[snafu(display("Failed to create a worker thread"))]
WorkerThread { error: std::io::Error },
#[snafu(display("Invalid descriptor id {id}"))]
InvalidDescriptor { id: u16 },
#[snafu(display("Invalid queue index {index}"))]
InvalidQueueIndex { index: u16 },
#[snafu(display("Invalid msix vector {vector}"))]
InvalidMsixVector { vector: u16 },
#[snafu(display("Invalid virtq buffer"))]
InvalidBuffer,
#[cfg(target_os = "linux")]
#[snafu(display("vhost-user error"), context(false))]
Vu { source: Box<vu::Error> },
#[cfg(target_os = "linux")]
#[snafu(display("vhost error"), context(false))]
Vhost { source: Box<vhost::Error> },
#[snafu(display("fuse error"), context(false))]
Fuse { source: Box<crate::fuse::Error> },
}
type Result<T, E = Error> = std::result::Result<T, E>;
bitflags! {
pub struct VirtioFeature(u128) {
INDIRECT_DESC = 1 << 28;
EVENT_IDX = 1 << 29;
VHOST_PROTOCOL = 1 << 30;
VERSION_1 = 1 << 32;
ACCESS_PLATFORM = 1 << 33;
RING_PACKED = 1 << 34;
}
}
const FEATURE_BUILT_IN: u128 = VirtioFeature::EVENT_IDX.bits()
| VirtioFeature::RING_PACKED.bits()
| VirtioFeature::VERSION_1.bits();
consts! {
pub struct DeviceId(u16) {
NET = 1;
BLOCK = 2;
ENTROPY = 4;
BALLOON = 5;
SOCKET = 19;
IOMMU = 23;
MEM = 24;
FILE_SYSTEM = 26;
PMEM = 27;
}
}
bitflags! {
#[derive(Default)]
pub struct DevStatus(u8) {
ACK = 1 << 0;
DRIVER = 1 << 1;
DRIVER_OK = 1 << 2;
FEATURES_OK = 1 << 3;
NEEDS_RESET = 1 << 6;
FAILED = 1 << 7;
}
}
pub trait IrqSender: Send + Sync + Debug + 'static {
fn queue_irq(&self, idx: u16);
fn config_irq(&self);
fn queue_irqfd<F, T>(&self, idx: u16, f: F) -> Result<T>
where
F: FnOnce(BorrowedFd) -> Result<T>;
fn config_irqfd<F, T>(&self, f: F) -> Result<T>
where
F: FnOnce(BorrowedFd) -> Result<T>;
}
#[cfg(test)]
#[path = "virtio_test.rs"]
mod tests;