diff options
Diffstat (limited to 'src/backend.rs')
-rw-r--r-- | src/backend.rs | 506 |
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); - } -} |