From 6e9d3eccd67dcc17fb83943ba4eb0c28c072bb1a Mon Sep 17 00:00:00 2001 From: Wei Liu Date: Wed, 30 Jun 2021 19:57:56 +0000 Subject: [PATCH] hypervisor: implement devicefd management for MSHV Signed-off-by: Wei Liu --- hypervisor/src/mshv/mod.rs | 70 +++++++++++++++++++++++++++---- hypervisor/src/mshv/x86_64/mod.rs | 2 - hypervisor/src/vm.rs | 2 - 3 files changed, 63 insertions(+), 11 deletions(-) diff --git a/hypervisor/src/mshv/mod.rs b/hypervisor/src/mshv/mod.rs index b365e4e77..1ce9c4bd5 100644 --- a/hypervisor/src/mshv/mod.rs +++ b/hypervisor/src/mshv/mod.rs @@ -14,7 +14,7 @@ use crate::vec_with_array_field; use crate::vm::{self, VmmOps}; pub use mshv_bindings::*; pub use mshv_ioctls::IoEventAddress; -use mshv_ioctls::{set_registers_64, Mshv, NoDatamatch, VcpuFd, VmFd}; +use mshv_ioctls::{set_registers_64, DeviceFd, Mshv, NoDatamatch, VcpuFd, VmFd}; use serde_derive::{Deserialize, Serialize}; use std::collections::HashMap; use std::sync::{Arc, RwLock}; @@ -31,10 +31,20 @@ pub use x86_64::*; #[cfg(target_arch = "x86_64")] use std::fs::File; -use std::os::unix::io::AsRawFd; +use std::os::unix::io::{AsRawFd, RawFd}; const DIRTY_BITMAP_CLEAR_DIRTY: u64 = 0x4; const DIRTY_BITMAP_SET_DIRTY: u64 = 0x8; + +/// +/// Export generically-named wrappers of mshv-bindings for Unix-based platforms +/// +pub use { + mshv_bindings::mshv_create_device as CreateDevice, + mshv_bindings::mshv_device_attr as DeviceAttr, + mshv_bindings::mshv_msi_routing_entry as IrqRoutingEntry, +}; + pub const PAGE_SHIFT: usize = 12; #[derive(Debug, Default, Copy, Clone, Serialize, Deserialize)] @@ -555,6 +565,36 @@ impl cpu::Vcpu for MshvVcpu { } } +/// Device struct for MSHV +pub struct MshvDevice { + fd: DeviceFd, +} + +impl device::Device for MshvDevice { + /// + /// Set device attribute + /// + fn set_device_attr(&self, attr: &DeviceAttr) -> device::Result<()> { + self.fd + .set_device_attr(attr) + .map_err(|e| device::HypervisorDeviceError::SetDeviceAttribute(e.into())) + } + /// + /// Get device attribute + /// + fn get_device_attr(&self, attr: &mut DeviceAttr) -> device::Result<()> { + self.fd + .get_device_attr(attr) + .map_err(|e| device::HypervisorDeviceError::GetDeviceAttribute(e.into())) + } +} + +impl AsRawFd for MshvDevice { + fn as_raw_fd(&self) -> RawFd { + self.fd.as_raw_fd() + } +} + struct MshvEmulatorContext<'a> { vcpu: &'a MshvVcpu, map: (u64, u64), // Initial GVA to GPA mapping provided by the hypervisor @@ -868,10 +908,28 @@ impl vm::Vm for MshvVm { } } + /// + /// Creates an in-kernel device. + /// + /// See the documentation for `MSHV_CREATE_DEVICE`. + fn create_device(&self, device: &mut CreateDevice) -> vm::Result> { + let fd = self + .fd + .create_device(device) + .map_err(|e| vm::HypervisorVmError::CreateDevice(e.into()))?; + let device = MshvDevice { fd }; + Ok(Arc::new(device)) + } + fn create_passthrough_device(&self) -> vm::Result> { - Err(vm::HypervisorVmError::CreatePassthroughDevice(anyhow!( - "No passthrough support" - ))) + let mut vfio_dev = mshv_create_device { + type_: mshv_device_type_MSHV_DEV_TYPE_VFIO, + fd: 0, + flags: 0, + }; + + self.create_device(&mut vfio_dev) + .map_err(|e| vm::HypervisorVmError::CreatePassthroughDevice(e.into())) } fn set_gsi_routing(&self, entries: &[IrqRoutingEntry]) -> vm::Result<()> { @@ -943,6 +1001,4 @@ impl vm::Vm for MshvVm { } pub use hv_cpuid_entry as CpuIdEntry; -pub type IrqRoutingEntry = mshv_msi_routing_entry; - pub const CPUID_FLAG_VALID_INDEX: u32 = 0; diff --git a/hypervisor/src/mshv/x86_64/mod.rs b/hypervisor/src/mshv/x86_64/mod.rs index 7dfa6f309..c8bef165c 100644 --- a/hypervisor/src/mshv/x86_64/mod.rs +++ b/hypervisor/src/mshv/x86_64/mod.rs @@ -61,8 +61,6 @@ impl fmt::Display for VcpuMshvState { } } -pub struct CreateDevice {} -pub struct DeviceAttr {} pub struct IrqRouting {} pub enum VcpuExit {} pub struct MpState {} diff --git a/hypervisor/src/vm.rs b/hypervisor/src/vm.rs index 112fc0014..7837dd4cd 100644 --- a/hypervisor/src/vm.rs +++ b/hypervisor/src/vm.rs @@ -16,7 +16,6 @@ use crate::device::Device; use crate::x86_64::CpuId; #[cfg(all(feature = "kvm", target_arch = "x86_64"))] use crate::ClockData; -#[cfg(feature = "kvm")] use crate::CreateDevice; #[cfg(feature = "mshv")] use crate::HvState as VmState; @@ -254,7 +253,6 @@ pub trait Vm: Send + Sync { fn create_user_memory_region(&self, user_memory_region: MemoryRegion) -> Result<()>; /// Removes a guest physical memory slot. fn remove_user_memory_region(&self, user_memory_region: MemoryRegion) -> Result<()>; - #[cfg(feature = "kvm")] /// Creates an emulated device in the kernel. fn create_device(&self, device: &mut CreateDevice) -> Result>; /// Returns the preferred CPU target type which can be emulated by KVM on underlying host.