hypervisor: implement devicefd management for MSHV

Signed-off-by: Wei Liu <liuwe@microsoft.com>
This commit is contained in:
Wei Liu 2021-06-30 19:57:56 +00:00 committed by LIU Wei
parent 10b954e954
commit 6e9d3eccd6
3 changed files with 63 additions and 11 deletions

View File

@ -14,7 +14,7 @@ use crate::vec_with_array_field;
use crate::vm::{self, VmmOps}; use crate::vm::{self, VmmOps};
pub use mshv_bindings::*; pub use mshv_bindings::*;
pub use mshv_ioctls::IoEventAddress; 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 serde_derive::{Deserialize, Serialize};
use std::collections::HashMap; use std::collections::HashMap;
use std::sync::{Arc, RwLock}; use std::sync::{Arc, RwLock};
@ -31,10 +31,20 @@ pub use x86_64::*;
#[cfg(target_arch = "x86_64")] #[cfg(target_arch = "x86_64")]
use std::fs::File; 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_CLEAR_DIRTY: u64 = 0x4;
const DIRTY_BITMAP_SET_DIRTY: u64 = 0x8; 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; pub const PAGE_SHIFT: usize = 12;
#[derive(Debug, Default, Copy, Clone, Serialize, Deserialize)] #[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> { struct MshvEmulatorContext<'a> {
vcpu: &'a MshvVcpu, vcpu: &'a MshvVcpu,
map: (u64, u64), // Initial GVA to GPA mapping provided by the hypervisor 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<Arc<dyn device::Device>> {
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<Arc<dyn device::Device>> { fn create_passthrough_device(&self) -> vm::Result<Arc<dyn device::Device>> {
Err(vm::HypervisorVmError::CreatePassthroughDevice(anyhow!( let mut vfio_dev = mshv_create_device {
"No passthrough support" 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<()> { 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 use hv_cpuid_entry as CpuIdEntry;
pub type IrqRoutingEntry = mshv_msi_routing_entry;
pub const CPUID_FLAG_VALID_INDEX: u32 = 0; pub const CPUID_FLAG_VALID_INDEX: u32 = 0;

View File

@ -61,8 +61,6 @@ impl fmt::Display for VcpuMshvState {
} }
} }
pub struct CreateDevice {}
pub struct DeviceAttr {}
pub struct IrqRouting {} pub struct IrqRouting {}
pub enum VcpuExit {} pub enum VcpuExit {}
pub struct MpState {} pub struct MpState {}

View File

@ -16,7 +16,6 @@ use crate::device::Device;
use crate::x86_64::CpuId; use crate::x86_64::CpuId;
#[cfg(all(feature = "kvm", target_arch = "x86_64"))] #[cfg(all(feature = "kvm", target_arch = "x86_64"))]
use crate::ClockData; use crate::ClockData;
#[cfg(feature = "kvm")]
use crate::CreateDevice; use crate::CreateDevice;
#[cfg(feature = "mshv")] #[cfg(feature = "mshv")]
use crate::HvState as VmState; 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<()>; fn create_user_memory_region(&self, user_memory_region: MemoryRegion) -> Result<()>;
/// Removes a guest physical memory slot. /// Removes a guest physical memory slot.
fn remove_user_memory_region(&self, user_memory_region: MemoryRegion) -> Result<()>; fn remove_user_memory_region(&self, user_memory_region: MemoryRegion) -> Result<()>;
#[cfg(feature = "kvm")]
/// Creates an emulated device in the kernel. /// Creates an emulated device in the kernel.
fn create_device(&self, device: &mut CreateDevice) -> Result<Arc<dyn Device>>; fn create_device(&self, device: &mut CreateDevice) -> Result<Arc<dyn Device>>;
/// Returns the preferred CPU target type which can be emulated by KVM on underlying host. /// Returns the preferred CPU target type which can be emulated by KVM on underlying host.