Add traits to support vhost backend devices
These interfaces are derived from the firecracker and crosvm projects. They may be extended when enable support of vhost-user protocol. Signed-off-by: Liu Jiang <gerry@linux.alibaba.com>
This commit is contained in:
parent
5d61e36bda
commit
bcbbaaabb3
4 changed files with 276 additions and 5 deletions
|
|
@ -5,4 +5,10 @@ authors = ["Liu Jiang <gerry@linux.alibaba.com>"]
|
|||
repository = "https://github.com/rust-vmm/vhost"
|
||||
license = "Apache-2.0 or BSD-3-Clause"
|
||||
|
||||
[features]
|
||||
default = []
|
||||
vhost-vsock = []
|
||||
|
||||
[dependencies]
|
||||
vmm-sys-util = ">=0.3.1"
|
||||
vm-memory = { version = "0.2.0", optional = true }
|
||||
|
|
|
|||
135
src/backend.rs
Normal file
135
src/backend.rs
Normal file
|
|
@ -0,0 +1,135 @@
|
|||
// Copyright (C) 2019 Alibaba Cloud Computing. All rights reserved.
|
||||
// SPDX-License-Identifier: Apache-2.0 or BSD-3-Clause
|
||||
//
|
||||
// Portions 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-Google file.
|
||||
|
||||
//! Common traits and structs for vhost-kern and vhost-user backend drivers.
|
||||
|
||||
use super::Result;
|
||||
use std::os::unix::io::RawFd;
|
||||
use vmm_sys_util::eventfd::EventFd;
|
||||
|
||||
/// Maximum number of memory regions supported.
|
||||
pub const VHOST_MAX_MEMORY_REGIONS: usize = 255;
|
||||
|
||||
/// Vring/virtque configuration data.
|
||||
pub struct VringConfigData {
|
||||
/// Maximum queue size supported by the driver.
|
||||
pub queue_max_size: u16,
|
||||
/// Actual queue size negotiated by the driver.
|
||||
pub queue_size: u16,
|
||||
/// Bitmask of vring flags.
|
||||
pub flags: u32,
|
||||
/// Descriptor table address.
|
||||
pub desc_table_addr: u64,
|
||||
/// Used ring buffer address.
|
||||
pub used_ring_addr: u64,
|
||||
/// Available ring buffer address.
|
||||
pub avail_ring_addr: u64,
|
||||
/// Optional address for logging.
|
||||
pub log_addr: Option<u64>,
|
||||
}
|
||||
|
||||
/// Memory region configuration data.
|
||||
#[derive(Default, Clone, Copy)]
|
||||
pub struct VhostUserMemoryRegionInfo {
|
||||
/// Guest physical address of the memory region.
|
||||
pub guest_phys_addr: u64,
|
||||
/// Size of the memory region.
|
||||
pub memory_size: u64,
|
||||
/// Virtual address in the current process.
|
||||
pub userspace_addr: u64,
|
||||
/// Optional offset where region starts in the mapped memory.
|
||||
pub mmap_offset: u64,
|
||||
/// Optional file diescriptor for mmap
|
||||
pub mmap_handle: RawFd,
|
||||
}
|
||||
|
||||
/// An interface for setting up vhost-based backend drivers.
|
||||
///
|
||||
/// Vhost devices are subset of virtio devices, which improve virtio device's performance by
|
||||
/// delegating data plane operations to dedicated IO service processes. Vhost devices use the
|
||||
/// same virtqueue layout as virtio devices to allow vhost devices to be mapped directly to
|
||||
/// virtio devices.
|
||||
/// The purpose of vhost is to implement a subset of a virtio device's functionality outside the
|
||||
/// VMM process. Typically fast paths for IO operations are delegated to the dedicated IO service
|
||||
/// processes, and slow path for device configuration are still handled by the VMM process. It may
|
||||
/// also be used to control access permissions of virtio backend devices.
|
||||
pub trait VhostBackend: std::marker::Sized {
|
||||
/// Get a bitmask of supported virtio/vhost features.
|
||||
fn get_features(&mut self) -> Result<u64>;
|
||||
|
||||
/// Inform the vhost subsystem which features to enable.
|
||||
/// This should be a subset of supported features from get_features().
|
||||
///
|
||||
/// # Arguments
|
||||
/// * `features` - Bitmask of features to set.
|
||||
fn set_features(&mut self, features: u64) -> Result<()>;
|
||||
|
||||
/// Set the current process as the owner of the vhost backend.
|
||||
/// This must be run before any other vhost commands.
|
||||
fn set_owner(&mut self) -> Result<()>;
|
||||
|
||||
/// Used to be sent to request disabling all rings
|
||||
/// This is no longer used.
|
||||
fn reset_owner(&mut self) -> Result<()>;
|
||||
|
||||
/// Set the guest memory mappings for vhost to use.
|
||||
fn set_mem_table(&mut self, regions: &[VhostUserMemoryRegionInfo]) -> Result<()>;
|
||||
|
||||
/// Set base address for page modification logging.
|
||||
fn set_log_base(&mut self, base: u64, fd: Option<RawFd>) -> Result<()>;
|
||||
|
||||
/// Specify an eventfd file descriptor to signal on log write.
|
||||
fn set_log_fd(&mut self, fd: RawFd) -> Result<()>;
|
||||
|
||||
/// Set the number of descriptors in the vring.
|
||||
///
|
||||
/// # Arguments
|
||||
/// * `queue_index` - Index of the queue to set descriptor count for.
|
||||
/// * `num` - Number of descriptors in the queue.
|
||||
fn set_vring_num(&mut self, queue_index: usize, num: u16) -> Result<()>;
|
||||
|
||||
/// Set the addresses for a given vring.
|
||||
///
|
||||
/// # Arguments
|
||||
/// * `queue_index` - Index of the queue to set addresses for.
|
||||
/// * `config_data` - Configuration data for a vring.
|
||||
fn set_vring_addr(&mut self, queue_index: usize, config_data: &VringConfigData) -> Result<()>;
|
||||
|
||||
/// Set the first index to look for available descriptors.
|
||||
///
|
||||
/// # Arguments
|
||||
/// * `queue_index` - Index of the queue to modify.
|
||||
/// * `num` - Index where available descriptors start.
|
||||
fn set_vring_base(&mut self, queue_index: usize, base: u16) -> Result<()>;
|
||||
|
||||
/// Get the available vring base offset.
|
||||
fn get_vring_base(&mut self, queue_index: usize) -> Result<u32>;
|
||||
|
||||
/// Set the eventfd to trigger when buffers have been used by the host.
|
||||
///
|
||||
/// # Arguments
|
||||
/// * `queue_index` - Index of the queue to modify.
|
||||
/// * `fd` - EventFd to trigger.
|
||||
fn set_vring_call(&mut self, queue_index: usize, fd: &EventFd) -> Result<()>;
|
||||
|
||||
/// Set the eventfd that will be signaled by the guest when buffers are
|
||||
/// available for the host to process.
|
||||
///
|
||||
/// # Arguments
|
||||
/// * `queue_index` - Index of the queue to modify.
|
||||
/// * `fd` - EventFd that will be signaled from guest.
|
||||
fn set_vring_kick(&mut self, queue_index: usize, fd: &EventFd) -> Result<()>;
|
||||
|
||||
/// Set the eventfd that will be signaled by the guest when error happens.
|
||||
///
|
||||
/// # Arguments
|
||||
/// * `queue_index` - Index of the queue to modify.
|
||||
/// * `fd` - EventFd that will be signaled from guest.
|
||||
fn set_vring_err(&mut self, queue_index: usize, fd: &EventFd) -> Result<()>;
|
||||
}
|
||||
110
src/lib.rs
110
src/lib.rs
|
|
@ -1,7 +1,107 @@
|
|||
#[cfg(test)]
|
||||
mod tests {
|
||||
#[test]
|
||||
fn it_works() {
|
||||
assert_eq!(2 + 2, 4);
|
||||
// Copyright (C) 2019 Alibaba Cloud Computing. All rights reserved.
|
||||
// SPDX-License-Identifier: Apache-2.0 or BSD-3-Clause
|
||||
|
||||
//! Virtio Vhost Backend Drivers
|
||||
//!
|
||||
//! Virtio devices use virtqueues to transport data efficiently. The first generation of virtqueue
|
||||
//! is a set of three different single-producer, single-consumer ring structures designed to store
|
||||
//! generic scatter-gather I/O. The virtio specification 1.1 introduces an alternative compact
|
||||
//! virtqueue layout named "Packed Virtqueue", which is more friendly to memory cache system and
|
||||
//! hardware implemented virtio devices. The packed virtqueue uses read-write memory, that means
|
||||
//! the memory will be both read and written by both host and guest. The new Packed Virtqueue is
|
||||
//! preferred for performance.
|
||||
//!
|
||||
//! Vhost is a mechanism to improve performance of Virtio devices by delegate data plane operations
|
||||
//! to dedicated IO service processes. Only the configuration, I/O submission notification, and I/O
|
||||
//! completion interruption are piped through the hypervisor.
|
||||
//! It uses the same virtqueue layout as Virtio to allow Vhost devices to be mapped directly to
|
||||
//! Virtio devices. This allows a Vhost device to be accessed directly by a guest OS inside a
|
||||
//! hypervisor process with an existing Virtio (PCI) driver.
|
||||
//!
|
||||
//! The initial vhost implementation is a part of the Linux kernel and uses ioctl interface to
|
||||
//! communicate with userspace applications. Dedicated kernel worker threads are created to handle
|
||||
//! IO requests from the guest.
|
||||
//!
|
||||
//! Later Vhost-user protocol is introduced to complement the ioctl interface used to control the
|
||||
//! vhost implementation in the Linux kernel. It implements the control plane needed to establish
|
||||
//! virtqueues sharing with a user space process on the same host. It uses communication over a
|
||||
//! Unix domain socket to share file descriptors in the ancillary data of the message.
|
||||
//! The protocol defines 2 sides of the communication, master and slave. Master is the application
|
||||
//! that shares its virtqueues. Slave is the consumer of the virtqueues. Master and slave can be
|
||||
//! either a client (i.e. connecting) or server (listening) in the socket communication.
|
||||
|
||||
#![deny(missing_docs)]
|
||||
|
||||
#[cfg(feature = "vhost-kern")]
|
||||
extern crate vm_memory;
|
||||
extern crate vmm_sys_util;
|
||||
|
||||
mod backend;
|
||||
pub use backend::*;
|
||||
|
||||
#[cfg(feature = "vhost-vsock")]
|
||||
pub mod vsock;
|
||||
|
||||
/// Error codes for vhost operations
|
||||
#[derive(Debug)]
|
||||
pub enum Error {
|
||||
/// Invalid operations.
|
||||
InvalidOperation,
|
||||
/// Invalid guest memory.
|
||||
InvalidGuestMemory,
|
||||
/// Invalid guest memory region.
|
||||
InvalidGuestMemoryRegion,
|
||||
/// Invalid queue.
|
||||
InvalidQueue,
|
||||
/// Invalid descriptor table address.
|
||||
DescriptorTableAddress,
|
||||
/// Invalid used address.
|
||||
UsedAddress,
|
||||
/// Invalid available address.
|
||||
AvailAddress,
|
||||
/// Invalid log address.
|
||||
LogAddress,
|
||||
#[cfg(feature = "vhost-kern")]
|
||||
/// Error opening the vhost backend driver.
|
||||
VhostOpen(std::io::Error),
|
||||
#[cfg(feature = "vhost-kern")]
|
||||
/// Error while running ioctl.
|
||||
IoctlError(std::io::Error),
|
||||
/// Error from IO subsystem.
|
||||
IOError(std::io::Error),
|
||||
#[cfg(any(feature = "vhost-user-master", feature = "vhost-user-slave"))]
|
||||
/// Error from the vhost-user subsystem.
|
||||
VhostUserProtocol(crate::vhost_user::Error),
|
||||
}
|
||||
|
||||
impl std::fmt::Display for Error {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
|
||||
match self {
|
||||
Error::InvalidOperation => write!(f, "invalid vhost operations"),
|
||||
Error::InvalidGuestMemory => write!(f, "invalid guest memory object"),
|
||||
Error::InvalidGuestMemoryRegion => write!(f, "invalid guest memory region"),
|
||||
Error::InvalidQueue => write!(f, "invalid virtque"),
|
||||
Error::DescriptorTableAddress => write!(f, "invalid virtque descriptor talbe address"),
|
||||
Error::UsedAddress => write!(f, "invalid virtque used talbe address"),
|
||||
Error::AvailAddress => write!(f, "invalid virtque available talbe address"),
|
||||
Error::LogAddress => write!(f, "invalid virtque log address"),
|
||||
Error::IOError(e) => write!(f, "IO error: {}", e),
|
||||
#[cfg(feature = "vhost-kern")]
|
||||
Error::VhostOpen(e) => write!(f, "failure in opening vhost file: {}", e),
|
||||
#[cfg(feature = "vhost-kern")]
|
||||
Error::IoctlError(e) => write!(f, "failure in vhost ioctl: {}", e),
|
||||
#[cfg(any(feature = "vhost-user-master", feature = "vhost-user-slave"))]
|
||||
Error::VhostUserProtocol(e) => write!(f, "vhost-user error: {}", e),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(any(feature = "vhost-user-master", feature = "vhost-user-slave"))]
|
||||
impl std::convert::From<crate::vhost_user::Error> for Error {
|
||||
fn from(err: crate::vhost_user::Error) -> Self {
|
||||
Error::VhostUserProtocol(err)
|
||||
}
|
||||
}
|
||||
|
||||
/// Result of vhost operations
|
||||
pub type Result<T> = std::result::Result<T, Error>;
|
||||
|
|
|
|||
30
src/vsock.rs
Normal file
30
src/vsock.rs
Normal file
|
|
@ -0,0 +1,30 @@
|
|||
// Copyright (C) 2019 Alibaba Cloud Computing. All rights reserved.
|
||||
// SPDX-License-Identifier: Apache-2.0 or BSD-3-Clause
|
||||
//
|
||||
// Portions 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-Google file.
|
||||
|
||||
//! Trait to control vhost-vsock backend drivers.
|
||||
|
||||
use crate::backend::VhostBackend;
|
||||
use crate::Result;
|
||||
|
||||
/// Trait to control vhost-vsock backend drivers.
|
||||
pub trait VhostVsock: VhostBackend {
|
||||
/// Set the CID for the guest.
|
||||
/// This number is used for routing all data destined for running in the guest.
|
||||
/// Each guest on a hypervisor must have an unique CID.
|
||||
///
|
||||
/// # Arguments
|
||||
/// * `cid` - CID to assign to the guest
|
||||
fn set_guest_cid(&mut self, cid: u64) -> Result<()>;
|
||||
|
||||
/// Tell the VHOST driver to start performing data transfer.
|
||||
fn start(&mut self) -> Result<()>;
|
||||
|
||||
/// Tell the VHOST driver to stop performing data transfer.
|
||||
fn stop(&mut self) -> Result<()>;
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue