From ddf1b76906c31f0b444139c6c13d194fae9fb03a Mon Sep 17 00:00:00 2001 From: Michael Zhao Date: Tue, 21 Jul 2020 17:56:00 +0800 Subject: [PATCH] hypervisor: Refactor create_passthrough_device() for generic type Changed the return type of create_passthrough_device() to generic type hypervisor::Device. Signed-off-by: Michael Zhao --- hypervisor/src/device.rs | 3 ++- hypervisor/src/kvm/mod.rs | 12 +++++++++--- hypervisor/src/vm.rs | 4 ++-- vmm/src/device_manager.rs | 35 +++++++++++++++++++---------------- 4 files changed, 32 insertions(+), 22 deletions(-) diff --git a/hypervisor/src/device.rs b/hypervisor/src/device.rs index cc62d5fb4..db380e39f 100644 --- a/hypervisor/src/device.rs +++ b/hypervisor/src/device.rs @@ -10,6 +10,7 @@ // use crate::DeviceAttr; +use std::os::unix::io::AsRawFd; use thiserror::Error; #[derive(Error, Debug)] @@ -33,7 +34,7 @@ pub type Result = std::result::Result; /// /// This crate provides a hypervisor-agnostic interfaces for device /// -pub trait Device: Send + Sync { +pub trait Device: Send + Sync + AsRawFd { /// Set device attribute. fn set_device_attr(&self, attr: &DeviceAttr) -> Result<()>; } diff --git a/hypervisor/src/kvm/mod.rs b/hypervisor/src/kvm/mod.rs index 5e932b196..507042917 100644 --- a/hypervisor/src/kvm/mod.rs +++ b/hypervisor/src/kvm/mod.rs @@ -9,6 +9,7 @@ // use kvm_ioctls::{NoDatamatch, VcpuFd, VmFd}; +use std::os::unix::io::{AsRawFd, RawFd}; use std::result; use std::sync::Arc; #[cfg(target_arch = "x86_64")] @@ -303,15 +304,14 @@ impl vm::Vm for KvmVm { self.fd.check_extension(c) } /// Create a device that is used for passthrough - fn create_passthrough_device(&self) -> vm::Result { + fn create_passthrough_device(&self) -> vm::Result> { let mut vfio_dev = kvm_create_device { type_: kvm_device_type_KVM_DEV_TYPE_VFIO, fd: 0, flags: 0, }; - self.fd - .create_device(&mut vfio_dev) + self.create_device(&mut vfio_dev) .map_err(|e| vm::HypervisorVmError::CreatePassthroughDevice(e.into())) } } @@ -869,3 +869,9 @@ impl device::Device for KvmDevice { .map_err(|e| device::HypervisorDeviceError::SetDeviceAttribute(e.into())) } } + +impl AsRawFd for KvmDevice { + fn as_raw_fd(&self) -> RawFd { + self.fd.as_raw_fd() + } +} diff --git a/hypervisor/src/vm.rs b/hypervisor/src/vm.rs index a48b2776c..70a8be3cb 100644 --- a/hypervisor/src/vm.rs +++ b/hypervisor/src/vm.rs @@ -14,7 +14,7 @@ use crate::cpu::Vcpu; use crate::device::Device; #[cfg(target_arch = "x86_64")] use crate::ClockData; -use crate::{CreateDevice, DeviceFd, IoEventAddress, IrqRoutingEntry, MemoryRegion}; +use crate::{CreateDevice, IoEventAddress, IrqRoutingEntry, MemoryRegion}; use kvm_ioctls::Cap; use std::sync::Arc; use thiserror::Error; @@ -178,5 +178,5 @@ pub trait Vm: Send + Sync { /// Checks if a particular `Cap` is available. fn check_extension(&self, c: Cap) -> bool; /// Create a device that is used for passthrough - fn create_passthrough_device(&self) -> Result; + fn create_passthrough_device(&self) -> Result>; } diff --git a/vmm/src/device_manager.rs b/vmm/src/device_manager.rs index 334abd8f6..73809e991 100644 --- a/vmm/src/device_manager.rs +++ b/vmm/src/device_manager.rs @@ -57,6 +57,8 @@ use std::fs::{File, OpenOptions}; use std::io::{self, sink, stdout, Seek, SeekFrom}; use std::num::Wrapping; use std::os::unix::fs::OpenOptionsExt; +#[cfg(feature = "pci_support")] +use std::os::unix::io::FromRawFd; use std::path::PathBuf; use std::result; use std::sync::{Arc, Mutex}; @@ -745,7 +747,7 @@ pub struct DeviceManager { // Passthrough device handle #[cfg(feature = "pci_support")] - passthrough_device: Option>, + passthrough_device: Option>, // Paravirtualized IOMMU #[cfg(feature = "pci_support")] @@ -2390,11 +2392,11 @@ impl DeviceManager { &mut self, pci: &mut PciBus, interrupt_manager: &Arc>, - device_fd: &Arc, + device: &Arc, device_cfg: &mut DeviceConfig, ) -> DeviceManagerResult<(u32, String)> { #[cfg(feature = "kvm")] - return self.add_vfio_device(pci, interrupt_manager, device_fd, device_cfg); + return self.add_vfio_device(pci, interrupt_manager, device, device_cfg); #[cfg(not(feature = "kvm"))] Err(DeviceManagerError::NoDevicePassthroughSupport) @@ -2405,7 +2407,7 @@ impl DeviceManager { &mut self, pci: &mut PciBus, interrupt_manager: &Arc>, - device_fd: &Arc, + device: &Arc, device_cfg: &mut DeviceConfig, ) -> DeviceManagerResult<(u32, String)> { // We need to shift the device id since the 3 first bits @@ -2420,7 +2422,10 @@ impl DeviceManager { let memory = self.memory_manager.lock().unwrap().guest_memory(); let vfio_container = Arc::new( - VfioContainer::new(device_fd.clone()).map_err(DeviceManagerError::VfioCreate)?, + VfioContainer::new(Arc::new(unsafe { + DeviceFd::from_raw_fd(device.as_raw_fd()) + })) + .map_err(DeviceManagerError::VfioCreate)?, ); let vfio_device = VfioDevice::new( @@ -2511,17 +2516,16 @@ impl DeviceManager { if let Some(device_list_cfg) = &mut devices { // Create the passthrough device handle - let device_fd = self + let device = self .address_manager .vm .create_passthrough_device() .map_err(|e| DeviceManagerError::CreatePassthroughDevice(e.into()))?; - let device_fd = Arc::new(device_fd); - self.passthrough_device = Some(Arc::clone(&device_fd)); + self.passthrough_device = Some(Arc::clone(&device)); for device_cfg in device_list_cfg.iter_mut() { let (device_id, _) = - self.add_passthrough_device(pci, interrupt_manager, &device_fd, device_cfg)?; + self.add_passthrough_device(pci, interrupt_manager, &device, device_cfg)?; if device_cfg.iommu && self.iommu_device.is_some() { iommu_attached_device_ids.push(device_id); } @@ -2936,26 +2940,25 @@ impl DeviceManager { let interrupt_manager = Arc::clone(&self.msi_interrupt_manager); - let device_fd = if let Some(device_fd) = &self.passthrough_device { - Arc::clone(&device_fd) + let device = if let Some(device) = &self.passthrough_device { + Arc::clone(&device) } else { // If the passthrough device file descriptor has not been created yet, // it is created here and stored in the DeviceManager structure for // future needs. - let device_fd = self + let device = self .address_manager .vm .create_passthrough_device() .map_err(|e| DeviceManagerError::CreatePassthroughDevice(e.into()))?; - let device_fd = Arc::new(device_fd); - self.passthrough_device = Some(Arc::clone(&device_fd)); - device_fd + self.passthrough_device = Some(Arc::clone(&device)); + device }; let (device_id, device_name) = self.add_passthrough_device( &mut pci.lock().unwrap(), &interrupt_manager, - &device_fd, + &device, device_cfg, )?;