summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Cargo.toml6
-rw-r--r--src/backend.rs135
-rw-r--r--src/lib.rs110
-rw-r--r--src/vsock.rs30
4 files changed, 276 insertions, 5 deletions
diff --git a/Cargo.toml b/Cargo.toml
index 05dd9ea..2eba08a 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -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 }
diff --git a/src/backend.rs b/src/backend.rs
new file mode 100644
index 0000000..e5dc4b7
--- /dev/null
+++ b/src/backend.rs
@@ -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<()>;
+}
diff --git a/src/lib.rs b/src/lib.rs
index 31e1bb2..8e84adf 100644
--- a/src/lib.rs
+++ b/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>;
diff --git a/src/vsock.rs b/src/vsock.rs
new file mode 100644
index 0000000..4fb75f5
--- /dev/null
+++ b/src/vsock.rs
@@ -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<()>;
+}