From 5694ac2b1eba70a800d97b519711390235dc10f5 Mon Sep 17 00:00:00 2001 From: Sebastien Boeuf Date: Wed, 30 Oct 2019 11:03:02 -0700 Subject: [PATCH] vm-virtio: Create new VirtioTransport trait to abstract ioeventfds In order to group together some functions that can be shared across virtio transport layers, this commit introduces a new trait called VirtioTransport. The first function of this trait being ioeventfds() as it is needed from both virtio-mmio and virtio-pci devices, represented by MmioDevice and VirtioPciDevice structures respectively. Signed-off-by: Sebastien Boeuf --- vm-virtio/src/transport/mmio.rs | 13 +++++++++- vm-virtio/src/transport/mod.rs | 5 ++++ vm-virtio/src/transport/pci_device.rs | 34 ++++++++++++++------------- vmm/src/device_manager.rs | 15 ++++++------ 4 files changed, 42 insertions(+), 25 deletions(-) diff --git a/vm-virtio/src/transport/mmio.rs b/vm-virtio/src/transport/mmio.rs index c5ced43a0..391add025 100644 --- a/vm-virtio/src/transport/mmio.rs +++ b/vm-virtio/src/transport/mmio.rs @@ -8,6 +8,7 @@ use std::sync::{Arc, RwLock}; use byteorder::{ByteOrder, LittleEndian}; use libc::EFD_NONBLOCK; +use crate::transport::{VirtioTransport, NOTIFY_REG_OFFSET}; use crate::{ Queue, VirtioDevice, VirtioInterrupt, VirtioInterruptType, DEVICE_ACKNOWLEDGE, DEVICE_DRIVER, DEVICE_DRIVER_OK, DEVICE_FAILED, DEVICE_FEATURES_OK, DEVICE_INIT, @@ -86,7 +87,7 @@ impl MmioDevice { /// Gets the list of queue events that must be triggered whenever the VM writes to /// `virtio::NOTIFY_REG_OFFSET` past the MMIO base. Each event must be triggered when the /// value being written equals the index of the event in this list. - pub fn queue_evts(&self) -> &[EventFd] { + fn queue_evts(&self) -> &[EventFd] { self.queue_evts.as_slice() } @@ -140,6 +141,16 @@ impl MmioDevice { } } +impl VirtioTransport for MmioDevice { + fn ioeventfds(&self, base_addr: u64) -> Vec<(&EventFd, u64)> { + let notify_base = base_addr + u64::from(NOTIFY_REG_OFFSET); + self.queue_evts() + .iter() + .map(|event| (event, notify_base)) + .collect() + } +} + impl BusDevice for MmioDevice { fn read(&mut self, _base: u64, offset: u64, data: &mut [u8]) { match offset { diff --git a/vm-virtio/src/transport/mod.rs b/vm-virtio/src/transport/mod.rs index 016aa9f8d..83ccb7a3b 100644 --- a/vm-virtio/src/transport/mod.rs +++ b/vm-virtio/src/transport/mod.rs @@ -2,6 +2,7 @@ // // SPDX-License-Identifier: Apache-2.0 +use vmm_sys_util::eventfd::EventFd; #[cfg(feature = "pci_support")] mod pci_common_config; #[cfg(feature = "pci_support")] @@ -17,3 +18,7 @@ mod mmio; pub use mmio::MmioDevice; #[cfg(feature = "mmio_support")] pub const NOTIFY_REG_OFFSET: u32 = 0x50; + +pub trait VirtioTransport { + fn ioeventfds(&self, base_addr: u64) -> Vec<(&EventFd, u64)>; +} diff --git a/vm-virtio/src/transport/pci_device.rs b/vm-virtio/src/transport/pci_device.rs index 5f817d9a9..1ab64f540 100755 --- a/vm-virtio/src/transport/pci_device.rs +++ b/vm-virtio/src/transport/pci_device.rs @@ -30,6 +30,7 @@ use vm_memory::{Address, ByteValued, GuestAddress, GuestMemoryMmap, GuestUsize, use vmm_sys_util::{errno::Result, eventfd::EventFd}; use super::VirtioPciCommonConfig; +use crate::transport::VirtioTransport; use crate::{ Queue, VirtioDevice, VirtioDeviceType, VirtioInterrupt, VirtioInterruptType, VirtioIommuRemapping, DEVICE_ACKNOWLEDGE, DEVICE_DRIVER, DEVICE_DRIVER_OK, DEVICE_FAILED, @@ -338,7 +339,7 @@ impl VirtioPciDevice { /// Gets the list of queue events that must be triggered whenever the VM writes to /// `virtio::NOTIFY_REG_OFFSET` past the MMIO base. Each event must be triggered when the /// value being written equals the index of the event in this list. - pub fn queue_evts(&self) -> &[EventFd] { + fn queue_evts(&self) -> &[EventFd] { self.queue_evts.as_slice() } @@ -366,21 +367,6 @@ impl VirtioPciDevice { self.configuration.get_bar_addr(self.settings_bar as usize) } - pub fn ioeventfds(&self, bar_addr: u64) -> Vec<(&EventFd, u64, u64)> { - let notify_base = bar_addr + NOTIFICATION_BAR_OFFSET; - self.queue_evts() - .iter() - .enumerate() - .map(|(i, event)| { - ( - event, - notify_base + i as u64 * u64::from(NOTIFY_OFF_MULTIPLIER), - i as u64, - ) - }) - .collect() - } - fn add_pci_capabilities( &mut self, settings_bar: u8, @@ -452,6 +438,22 @@ impl VirtioPciDevice { } } +impl VirtioTransport for VirtioPciDevice { + fn ioeventfds(&self, base_addr: u64) -> Vec<(&EventFd, u64)> { + let notify_base = base_addr + NOTIFICATION_BAR_OFFSET; + self.queue_evts() + .iter() + .enumerate() + .map(|(i, event)| { + ( + event, + notify_base + i as u64 * u64::from(NOTIFY_OFF_MULTIPLIER), + ) + }) + .collect() + } +} + impl PciDevice for VirtioPciDevice { fn assign_pin_irq( &mut self, diff --git a/vmm/src/device_manager.rs b/vmm/src/device_manager.rs index 5b181b0dc..3b261ae74 100644 --- a/vmm/src/device_manager.rs +++ b/vmm/src/device_manager.rs @@ -44,6 +44,7 @@ use vm_memory::GuestAddress; use vm_memory::{Address, GuestMemoryMmap, GuestUsize}; #[cfg(feature = "pci_support")] use vm_virtio::transport::VirtioPciDevice; +use vm_virtio::transport::VirtioTransport; use vm_virtio::vhost_user::VhostUserConfig; #[cfg(feature = "pci_support")] use vm_virtio::{DmaRemapping, IommuMapping, VirtioIommuRemapping}; @@ -360,11 +361,11 @@ impl DeviceRelocation for AddressManager { if let Some(virtio_pci_dev) = any_dev.downcast_ref::() { let bar_addr = virtio_pci_dev.config_bar_addr(); if bar_addr == new_base { - for (event, addr, _) in virtio_pci_dev.ioeventfds(old_base) { + for (event, addr) in virtio_pci_dev.ioeventfds(old_base) { let io_addr = IoEventAddress::Mmio(addr); self.vm_fd.unregister_ioevent(event, &io_addr)?; } - for (event, addr, _) in virtio_pci_dev.ioeventfds(new_base) { + for (event, addr) in virtio_pci_dev.ioeventfds(new_base) { let io_addr = IoEventAddress::Mmio(addr); self.vm_fd.register_ioevent(event, &io_addr, NoDatamatch)?; } @@ -1207,7 +1208,7 @@ impl DeviceManager { .map_err(DeviceManagerError::AllocateBars)?; let bar_addr = virtio_pci_device.config_bar_addr(); - for (event, addr, _) in virtio_pci_device.ioeventfds(bar_addr) { + for (event, addr) in virtio_pci_device.ioeventfds(bar_addr) { let io_addr = IoEventAddress::Mmio(addr); vm_fd .register_ioevent(event, &io_addr, NoDatamatch) @@ -1316,12 +1317,10 @@ impl DeviceManager { let mut mmio_device = vm_virtio::transport::MmioDevice::new(memory.clone(), virtio_device) .map_err(DeviceManagerError::VirtioDevice)?; - for (i, queue_evt) in mmio_device.queue_evts().iter().enumerate() { - let io_addr = IoEventAddress::Mmio( - mmio_base.0 + u64::from(vm_virtio::transport::NOTIFY_REG_OFFSET), - ); + for (i, (event, addr)) in mmio_device.ioeventfds(mmio_base.0).iter().enumerate() { + let io_addr = IoEventAddress::Mmio(*addr); vm_fd - .register_ioevent(queue_evt, &io_addr, i as u32) + .register_ioevent(event, &io_addr, i as u32) .map_err(DeviceManagerError::RegisterIoevent)?; }