mirror of
https://github.com/cloud-hypervisor/cloud-hypervisor.git
synced 2026-08-05 02:19:16 +00:00
Bump to the released versions that are compatible wherever possible but for the vhost and vfio crates they are git hashes as no releases with compatible versions have yet been made. Signed-off-by: Rob Bradford <rbradford@meta.com>
176 lines
5.6 KiB
Rust
176 lines
5.6 KiB
Rust
// Copyright 2018 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
|
//
|
|
// Portions Copyright 2017 The Chromium OS Authors. All rights reserved.
|
|
// Use of this source code is governed by a BSD-style license that can be
|
|
// found in the LICENSE-BSD-3-Clause file.
|
|
//
|
|
// Copyright © 2019 Intel Corporation
|
|
//
|
|
// SPDX-License-Identifier: Apache-2.0 AND BSD-3-Clause
|
|
|
|
//! Implements virtio devices, queues, and transport mechanisms.
|
|
|
|
use std::io;
|
|
|
|
use serde::{Deserialize, Serialize};
|
|
use thiserror::Error;
|
|
|
|
#[macro_use]
|
|
mod device;
|
|
pub mod balloon;
|
|
pub mod block;
|
|
mod console;
|
|
pub mod epoll_helper;
|
|
mod iommu;
|
|
pub mod mem;
|
|
pub mod net;
|
|
mod pmem;
|
|
mod rng;
|
|
pub mod seccomp_filters;
|
|
mod thread_helper;
|
|
pub mod transport;
|
|
pub mod vdpa;
|
|
pub mod vhost_user;
|
|
pub mod vsock;
|
|
pub mod watchdog;
|
|
|
|
use vm_memory::bitmap::AtomicBitmap;
|
|
use vm_memory::{GuestAddress, GuestMemory};
|
|
use vm_virtio::VirtioDeviceType;
|
|
|
|
pub use self::balloon::Balloon;
|
|
pub use self::block::{Block, BlockState};
|
|
pub use self::console::{Console, ConsoleResizer, Endpoint};
|
|
pub use self::device::{
|
|
ActivationContext, DmaRemapping, VirtioCommon, VirtioDevice, VirtioInterrupt,
|
|
VirtioInterruptType, VirtioSharedMemoryList,
|
|
};
|
|
pub use self::epoll_helper::{
|
|
EPOLL_HELPER_EVENT_LAST, EpollHelper, EpollHelperError, EpollHelperHandler,
|
|
};
|
|
pub use self::iommu::{AccessPlatformMapping, Iommu, IommuMapping};
|
|
pub use self::mem::{BlocksState, Mem, VIRTIO_MEM_ALIGN_SIZE, VirtioMemMappingSource};
|
|
pub use self::net::{Net, NetCtrlEpollHandler};
|
|
pub use self::pmem::Pmem;
|
|
pub use self::rng::Rng;
|
|
pub use self::vdpa::{Vdpa, VdpaDmaMapping};
|
|
pub use self::vsock::Vsock;
|
|
pub use self::watchdog::Watchdog;
|
|
|
|
type GuestMemoryMmap = vm_memory::GuestMemoryMmap<AtomicBitmap>;
|
|
type GuestRegionMmap = vm_memory::GuestRegionMmap<AtomicBitmap>;
|
|
type MmapRegion = vm_memory::MmapRegion<AtomicBitmap>;
|
|
|
|
const DEVICE_INIT: u32 = 0x00;
|
|
const DEVICE_ACKNOWLEDGE: u32 = 0x01;
|
|
const DEVICE_DRIVER: u32 = 0x02;
|
|
const DEVICE_DRIVER_OK: u32 = 0x04;
|
|
const DEVICE_FEATURES_OK: u32 = 0x08;
|
|
const DEVICE_NEEDS_RESET: u32 = 0x40;
|
|
const DEVICE_FAILED: u32 = 0x80;
|
|
|
|
const VIRTIO_F_RING_INDIRECT_DESC: u32 = 28;
|
|
const VIRTIO_F_RING_EVENT_IDX: u32 = 29;
|
|
const VIRTIO_F_VERSION_1: u32 = 32;
|
|
const VIRTIO_F_ACCESS_PLATFORM: u32 = 33;
|
|
const VIRTIO_F_IN_ORDER: u32 = 35;
|
|
const VIRTIO_F_ORDER_PLATFORM: u32 = 36;
|
|
#[allow(dead_code)]
|
|
const VIRTIO_F_SR_IOV: u32 = 37;
|
|
const VIRTIO_F_NOTIFICATION_DATA: u32 = 38;
|
|
|
|
#[derive(Error, Debug)]
|
|
pub enum ActivateError {
|
|
#[error("Failed to activate virtio device")]
|
|
BadActivate,
|
|
#[error("Failed to clone exit event fd")]
|
|
CloneExitEventFd(#[source] std::io::Error),
|
|
#[error("Failed to spawn thread")]
|
|
ThreadSpawn(#[source] std::io::Error),
|
|
#[error("Failed to setup vhost-user-fs daemon")]
|
|
VhostUserFsSetup(#[source] vhost_user::Error),
|
|
#[error("Failed to setup vhost-user daemon")]
|
|
VhostUserSetup(#[source] vhost_user::Error),
|
|
#[error("Failed to create seccomp filter")]
|
|
CreateSeccompFilter(#[source] seccompiler::Error),
|
|
#[error("Failed to create rate limiter")]
|
|
CreateRateLimiter(#[source] std::io::Error),
|
|
#[error("Failed to activate the vDPA device")]
|
|
ActivateVdpa(#[source] vdpa::Error),
|
|
}
|
|
|
|
pub type ActivateResult = std::result::Result<(), ActivateError>;
|
|
|
|
pub type DeviceEventT = u16;
|
|
|
|
#[derive(Error, Debug)]
|
|
pub enum Error {
|
|
#[error("Failed to single used queue")]
|
|
FailedSignalingUsedQueue(#[source] io::Error),
|
|
#[error("I/O Error")]
|
|
IoError(#[source] io::Error),
|
|
#[error("Failed to update memory vhost-user")]
|
|
VhostUserUpdateMemory(#[source] vhost_user::Error),
|
|
#[error("Failed to add memory region vhost-user")]
|
|
VhostUserAddMemoryRegion(#[source] vhost_user::Error),
|
|
#[error("Failed to set shared memory region")]
|
|
SetShmRegionsNotSupported,
|
|
#[error("Failed to process net queue")]
|
|
NetQueuePair(#[source] ::net_util::NetQueuePairError),
|
|
#[error("Failed to ")]
|
|
QueueAddUsed(#[source] virtio_queue::Error),
|
|
#[error("Failed to ")]
|
|
QueueIterator(#[source] virtio_queue::Error),
|
|
}
|
|
|
|
#[derive(Clone, Copy, Debug, Default, Deserialize, Serialize, PartialEq, Eq)]
|
|
pub struct TokenBucketConfig {
|
|
pub size: u64,
|
|
pub one_time_burst: Option<u64>,
|
|
pub refill_time: u64,
|
|
}
|
|
|
|
#[derive(Clone, Copy, Debug, Default, Deserialize, Serialize, PartialEq, Eq)]
|
|
#[serde(deny_unknown_fields)]
|
|
pub struct RateLimiterConfig {
|
|
pub bandwidth: Option<TokenBucketConfig>,
|
|
pub ops: Option<TokenBucketConfig>,
|
|
}
|
|
|
|
impl TryInto<rate_limiter::RateLimiter> for RateLimiterConfig {
|
|
type Error = io::Error;
|
|
|
|
fn try_into(self) -> std::result::Result<rate_limiter::RateLimiter, Self::Error> {
|
|
let bw = self.bandwidth.unwrap_or_default();
|
|
let ops = self.ops.unwrap_or_default();
|
|
rate_limiter::RateLimiter::new(
|
|
bw.size,
|
|
bw.one_time_burst.unwrap_or(0),
|
|
bw.refill_time,
|
|
ops.size,
|
|
ops.one_time_burst.unwrap_or(0),
|
|
ops.refill_time,
|
|
)
|
|
}
|
|
}
|
|
|
|
/// Return the host virtual address corresponding to the given guest address range
|
|
///
|
|
/// Convert an absolute address into an address space (GuestMemory)
|
|
/// to a host pointer and verify that the provided size define a valid
|
|
/// range within a single memory region.
|
|
/// Return None if it is out of bounds or if addr+size overlaps a single region.
|
|
pub fn get_host_address_range<M: GuestMemory + ?Sized>(
|
|
mem: &M,
|
|
addr: GuestAddress,
|
|
size: usize,
|
|
) -> Option<*mut u8> {
|
|
if mem.check_range(addr, size) {
|
|
let slice = mem.get_slice(addr, size).unwrap();
|
|
assert!(slice.len() >= size);
|
|
Some(slice.ptr_guard_mut().as_ptr())
|
|
} else {
|
|
None
|
|
}
|
|
}
|