summaryrefslogtreecommitdiff
path: root/src/backend.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend.rs')
-rw-r--r--src/backend.rs506
1 files changed, 0 insertions, 506 deletions
diff --git a/src/backend.rs b/src/backend.rs
deleted file mode 100644
index 1ae306f..0000000
--- a/src/backend.rs
+++ /dev/null
@@ -1,506 +0,0 @@
-// Copyright (C) 2019-2021 Alibaba Cloud. 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 std::cell::RefCell;
-use std::os::unix::io::RawFd;
-use std::sync::RwLock;
-
-use sys_util::EventFd;
-
-use super::Result;
-
-/// Maximum number of memory regions supported.
-pub const VHOST_MAX_MEMORY_REGIONS: usize = 255;
-
-/// Vring 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>,
-}
-
-impl VringConfigData {
- /// Check whether the log (flag, address) pair is valid.
- pub fn is_log_addr_valid(&self) -> bool {
- if self.flags & 0x1 != 0 && self.log_addr.is_none() {
- return false;
- }
-
- true
- }
-
- /// Get the log address, default to zero if not available.
- pub fn get_log_addr(&self) -> u64 {
- if self.flags & 0x1 != 0 && self.log_addr.is_some() {
- self.log_addr.unwrap()
- } else {
- 0
- }
- }
-}
-
-/// 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 descriptor for mmap.
- pub mmap_handle: RawFd,
-}
-
-/// An interface for setting up vhost-based backend drivers with interior mutability.
-///
-/// 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(&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(&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(&self) -> Result<()>;
-
- /// Used to be sent to request disabling all rings
- /// This is no longer used.
- fn reset_owner(&self) -> Result<()>;
-
- /// Set the guest memory mappings for vhost to use.
- fn set_mem_table(&self, regions: &[VhostUserMemoryRegionInfo]) -> Result<()>;
-
- /// Set base address for page modification logging.
- fn set_log_base(&self, base: u64, fd: Option<RawFd>) -> Result<()>;
-
- /// Specify an eventfd file descriptor to signal on log write.
- fn set_log_fd(&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(&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(&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(&self, queue_index: usize, base: u16) -> Result<()>;
-
- /// Get the available vring base offset.
- fn get_vring_base(&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(&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(&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(&self, queue_index: usize, fd: &EventFd) -> Result<()>;
-}
-
-/// 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 VhostBackendMut: 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<()>;
-}
-
-impl<T: VhostBackendMut> VhostBackend for RwLock<T> {
- fn get_features(&self) -> Result<u64> {
- self.write().unwrap().get_features()
- }
-
- fn set_features(&self, features: u64) -> Result<()> {
- self.write().unwrap().set_features(features)
- }
-
- fn set_owner(&self) -> Result<()> {
- self.write().unwrap().set_owner()
- }
-
- fn reset_owner(&self) -> Result<()> {
- self.write().unwrap().reset_owner()
- }
-
- fn set_mem_table(&self, regions: &[VhostUserMemoryRegionInfo]) -> Result<()> {
- self.write().unwrap().set_mem_table(regions)
- }
-
- fn set_log_base(&self, base: u64, fd: Option<RawFd>) -> Result<()> {
- self.write().unwrap().set_log_base(base, fd)
- }
-
- fn set_log_fd(&self, fd: RawFd) -> Result<()> {
- self.write().unwrap().set_log_fd(fd)
- }
-
- fn set_vring_num(&self, queue_index: usize, num: u16) -> Result<()> {
- self.write().unwrap().set_vring_num(queue_index, num)
- }
-
- fn set_vring_addr(&self, queue_index: usize, config_data: &VringConfigData) -> Result<()> {
- self.write()
- .unwrap()
- .set_vring_addr(queue_index, config_data)
- }
-
- fn set_vring_base(&self, queue_index: usize, base: u16) -> Result<()> {
- self.write().unwrap().set_vring_base(queue_index, base)
- }
-
- fn get_vring_base(&self, queue_index: usize) -> Result<u32> {
- self.write().unwrap().get_vring_base(queue_index)
- }
-
- fn set_vring_call(&self, queue_index: usize, fd: &EventFd) -> Result<()> {
- self.write().unwrap().set_vring_call(queue_index, fd)
- }
-
- fn set_vring_kick(&self, queue_index: usize, fd: &EventFd) -> Result<()> {
- self.write().unwrap().set_vring_kick(queue_index, fd)
- }
-
- fn set_vring_err(&self, queue_index: usize, fd: &EventFd) -> Result<()> {
- self.write().unwrap().set_vring_err(queue_index, fd)
- }
-}
-
-impl<T: VhostBackendMut> VhostBackend for RefCell<T> {
- fn get_features(&self) -> Result<u64> {
- self.borrow_mut().get_features()
- }
-
- fn set_features(&self, features: u64) -> Result<()> {
- self.borrow_mut().set_features(features)
- }
-
- fn set_owner(&self) -> Result<()> {
- self.borrow_mut().set_owner()
- }
-
- fn reset_owner(&self) -> Result<()> {
- self.borrow_mut().reset_owner()
- }
-
- fn set_mem_table(&self, regions: &[VhostUserMemoryRegionInfo]) -> Result<()> {
- self.borrow_mut().set_mem_table(regions)
- }
-
- fn set_log_base(&self, base: u64, fd: Option<RawFd>) -> Result<()> {
- self.borrow_mut().set_log_base(base, fd)
- }
-
- fn set_log_fd(&self, fd: RawFd) -> Result<()> {
- self.borrow_mut().set_log_fd(fd)
- }
-
- fn set_vring_num(&self, queue_index: usize, num: u16) -> Result<()> {
- self.borrow_mut().set_vring_num(queue_index, num)
- }
-
- fn set_vring_addr(&self, queue_index: usize, config_data: &VringConfigData) -> Result<()> {
- self.borrow_mut().set_vring_addr(queue_index, config_data)
- }
-
- fn set_vring_base(&self, queue_index: usize, base: u16) -> Result<()> {
- self.borrow_mut().set_vring_base(queue_index, base)
- }
-
- fn get_vring_base(&self, queue_index: usize) -> Result<u32> {
- self.borrow_mut().get_vring_base(queue_index)
- }
-
- fn set_vring_call(&self, queue_index: usize, fd: &EventFd) -> Result<()> {
- self.borrow_mut().set_vring_call(queue_index, fd)
- }
-
- fn set_vring_kick(&self, queue_index: usize, fd: &EventFd) -> Result<()> {
- self.borrow_mut().set_vring_kick(queue_index, fd)
- }
-
- fn set_vring_err(&self, queue_index: usize, fd: &EventFd) -> Result<()> {
- self.borrow_mut().set_vring_err(queue_index, fd)
- }
-}
-#[cfg(test)]
-mod tests {
- use super::*;
-
- struct MockBackend {}
-
- impl VhostBackendMut for MockBackend {
- fn get_features(&mut self) -> Result<u64> {
- Ok(0x1)
- }
-
- fn set_features(&mut self, features: u64) -> Result<()> {
- assert_eq!(features, 0x1);
- Ok(())
- }
-
- fn set_owner(&mut self) -> Result<()> {
- Ok(())
- }
-
- fn reset_owner(&mut self) -> Result<()> {
- Ok(())
- }
-
- fn set_mem_table(&mut self, _regions: &[VhostUserMemoryRegionInfo]) -> Result<()> {
- Ok(())
- }
-
- fn set_log_base(&mut self, base: u64, fd: Option<RawFd>) -> Result<()> {
- assert_eq!(base, 0x100);
- assert_eq!(fd, Some(100));
- Ok(())
- }
-
- fn set_log_fd(&mut self, fd: RawFd) -> Result<()> {
- assert_eq!(fd, 100);
- Ok(())
- }
-
- fn set_vring_num(&mut self, queue_index: usize, num: u16) -> Result<()> {
- assert_eq!(queue_index, 1);
- assert_eq!(num, 256);
- Ok(())
- }
-
- fn set_vring_addr(
- &mut self,
- queue_index: usize,
- _config_data: &VringConfigData,
- ) -> Result<()> {
- assert_eq!(queue_index, 1);
- Ok(())
- }
-
- fn set_vring_base(&mut self, queue_index: usize, base: u16) -> Result<()> {
- assert_eq!(queue_index, 1);
- assert_eq!(base, 2);
- Ok(())
- }
-
- fn get_vring_base(&mut self, queue_index: usize) -> Result<u32> {
- assert_eq!(queue_index, 1);
- Ok(2)
- }
-
- fn set_vring_call(&mut self, queue_index: usize, _fd: &EventFd) -> Result<()> {
- assert_eq!(queue_index, 1);
- Ok(())
- }
-
- fn set_vring_kick(&mut self, queue_index: usize, _fd: &EventFd) -> Result<()> {
- assert_eq!(queue_index, 1);
- Ok(())
- }
-
- fn set_vring_err(&mut self, queue_index: usize, _fd: &EventFd) -> Result<()> {
- assert_eq!(queue_index, 1);
- Ok(())
- }
- }
-
- #[test]
- fn test_vring_backend_mut() {
- let b = RwLock::new(MockBackend {});
-
- assert_eq!(b.get_features().unwrap(), 0x1);
- b.set_features(0x1).unwrap();
- b.set_owner().unwrap();
- b.reset_owner().unwrap();
- b.set_mem_table(&[]).unwrap();
- b.set_log_base(0x100, Some(100)).unwrap();
- b.set_log_fd(100).unwrap();
- b.set_vring_num(1, 256).unwrap();
-
- let config = VringConfigData {
- queue_max_size: 0x1000,
- queue_size: 0x2000,
- flags: 0x0,
- desc_table_addr: 0x4000,
- used_ring_addr: 0x5000,
- avail_ring_addr: 0x6000,
- log_addr: None,
- };
- b.set_vring_addr(1, &config).unwrap();
-
- b.set_vring_base(1, 2).unwrap();
- assert_eq!(b.get_vring_base(1).unwrap(), 2);
-
- let eventfd = EventFd::new().unwrap();
- b.set_vring_call(1, &eventfd).unwrap();
- b.set_vring_kick(1, &eventfd).unwrap();
- b.set_vring_err(1, &eventfd).unwrap();
- }
-
- #[test]
- fn test_vring_config_data() {
- let mut config = VringConfigData {
- queue_max_size: 0x1000,
- queue_size: 0x2000,
- flags: 0x0,
- desc_table_addr: 0x4000,
- used_ring_addr: 0x5000,
- avail_ring_addr: 0x6000,
- log_addr: None,
- };
-
- assert_eq!(config.is_log_addr_valid(), true);
- assert_eq!(config.get_log_addr(), 0);
-
- config.flags = 0x1;
- assert_eq!(config.is_log_addr_valid(), false);
- assert_eq!(config.get_log_addr(), 0);
-
- config.log_addr = Some(0x7000);
- assert_eq!(config.is_log_addr_valid(), true);
- assert_eq!(config.get_log_addr(), 0x7000);
-
- config.flags = 0x0;
- assert_eq!(config.is_log_addr_valid(), true);
- assert_eq!(config.get_log_addr(), 0);
- }
-}