virtio.rs0.00%
1
// Copyright 2024 Google LLC2
//3
// Licensed under the Apache License, Version 2.0 (the "License");4
// you may not use this file except in compliance with the License.5
// You may obtain a copy of the License at6
//7
// https://www.apache.org/licenses/LICENSE-2.08
//9
// Unless required by applicable law or agreed to in writing, software10
// distributed under the License is distributed on an "AS IS" BASIS,11
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.12
// See the License for the specific language governing permissions and13
// limitations under the License.14
15
#[path = "dev/dev.rs"]16
pub mod dev;17
pub mod pci;18
#[path = "queue/queue.rs"]19
pub mod queue;20
#[cfg(target_os = "linux")]21
pub mod vhost;22
#[cfg(target_os = "linux")]23
#[path = "vu/vu.rs"]24
pub mod vu;25
#[path = "worker/worker.rs"]26
pub mod worker;27
28
use std::fmt::Debug;29
use std::os::fd::BorrowedFd;30
use std::path::Path;31
32
use snafu::Snafu;33
34
use crate::errors::{DebugTrace, trace_error};35
use crate::{bitflags, consts};36
37
#[trace_error]38
#[derive(Snafu, DebugTrace)]39
#[snafu(module, context(suffix(false)))]40
pub enum Error {41
#[snafu(display("Hypervisor internal error"), context(false))]42
HvError { source: Box<crate::hv::Error> },43
#[snafu(display("Failed to access guest memory"), context(false))]44
Memory { source: Box<crate::mem::Error> },45
#[snafu(display("PCI bus error"), context(false))]46
PciBus { source: crate::pci::Error },47
#[snafu(display("Cannot access file {path:?}"))]48
AccessFile {49
path: Box<Path>,50
error: std::io::Error,51
},52
#[snafu(display("Failed to lock file {path:?}"))]53
LockFile {54
path: Box<Path>,55
error: std::fs::TryLockError,56
},57
#[snafu(display("Error from OS"), context(false))]58
System { error: std::io::Error },59
#[snafu(display("Failed to create a poll"))]60
CreatePoll { error: std::io::Error },61
#[snafu(display("Failed to register/deregister an event source"))]62
EventSource { error: std::io::Error },63
#[snafu(display("Failed to poll events"))]64
PollEvents { error: std::io::Error },65
#[snafu(display("Failed to create a worker thread"))]66
WorkerThread { error: std::io::Error },67
#[snafu(display("Invalid descriptor id {id}"))]68
InvalidDescriptor { id: u16 },69
#[snafu(display("Invalid queue index {index}"))]70
InvalidQueueIndex { index: u16 },71
#[snafu(display("Invalid msix vector {vector}"))]72
InvalidMsixVector { vector: u16 },73
#[snafu(display("Invalid virtq buffer"))]74
InvalidBuffer,75
#[cfg(target_os = "linux")]76
#[snafu(display("vhost-user error"), context(false))]77
Vu { source: Box<vu::Error> },78
#[cfg(target_os = "linux")]79
#[snafu(display("vhost error"), context(false))]80
Vhost { source: Box<vhost::Error> },81
#[snafu(display("fuse error"), context(false))]82
Fuse { source: Box<crate::fuse::Error> },83
}84
85
type Result<T, E = Error> = std::result::Result<T, E>;86
87
bitflags! {88
pub struct VirtioFeature(u128) {89
INDIRECT_DESC = 1 << 28;90
EVENT_IDX = 1 << 29;91
VHOST_PROTOCOL = 1 << 30;92
VERSION_1 = 1 << 32;93
ACCESS_PLATFORM = 1 << 33;94
RING_PACKED = 1 << 34;95
}96
}97
98
const FEATURE_BUILT_IN: u128 = VirtioFeature::EVENT_IDX.bits()99
| VirtioFeature::RING_PACKED.bits()100
| VirtioFeature::VERSION_1.bits();101
102
consts! {103
pub struct DeviceId(u16) {104
NET = 1;105
BLOCK = 2;106
ENTROPY = 4;107
BALLOON = 5;108
SOCKET = 19;109
IOMMU = 23;110
MEM = 24;111
FILE_SYSTEM = 26;112
PMEM = 27;113
}114
}115
116
bitflags! {117
#[derive(Default)]118
pub struct DevStatus(u8) {119
ACK = 1 << 0;120
DRIVER = 1 << 1;121
DRIVER_OK = 1 << 2;122
FEATURES_OK = 1 << 3;123
NEEDS_RESET = 1 << 6;124
FAILED = 1 << 7;125
}126
}127
128
pub trait IrqSender: Send + Sync + Debug + 'static {129
fn queue_irq(&self, idx: u16);130
fn config_irq(&self);131
fn queue_irqfd<F, T>(&self, idx: u16, f: F) -> Result<T>132
where133
F: FnOnce(BorrowedFd) -> Result<T>;134
fn config_irqfd<F, T>(&self, f: F) -> Result<T>135
where136
F: FnOnce(BorrowedFd) -> Result<T>;137
}138
139
#[cfg(test)]140
#[path = "virtio_test.rs"]141
mod tests;142