mshv: Use in-kernel ioeventfd mechanism

Signed-off-by: Vineeth Pillai <viremana@linux.microsoft.com>
This commit is contained in:
Vineeth Pillai 2020-12-10 11:54:15 -05:00 committed by Rob Bradford
parent 5209bd6120
commit 7659055eec
2 changed files with 22 additions and 39 deletions

View File

@ -14,7 +14,8 @@ use crate::cpu::Vcpu;
use crate::hypervisor; use crate::hypervisor;
use crate::vm::{self, VmmOps}; use crate::vm::{self, VmmOps};
pub use mshv_bindings::*; pub use mshv_bindings::*;
use mshv_ioctls::{set_registers_64, InterruptRequest, Mshv, VcpuFd, VmFd}; pub use mshv_ioctls::IoEventAddress;
use mshv_ioctls::{set_registers_64, InterruptRequest, Mshv, NoDatamatch, VcpuFd, VmFd};
use serde_derive::{Deserialize, Serialize}; use serde_derive::{Deserialize, Serialize};
use std::sync::Arc; use std::sync::Arc;
use vm::DataMatch; use vm::DataMatch;
@ -28,7 +29,6 @@ pub use x86_64::VcpuMshvState as CpuState;
#[cfg(target_arch = "x86_64")] #[cfg(target_arch = "x86_64")]
pub use x86_64::*; pub use x86_64::*;
// Wei: for emulating ioeventfd
use std::collections::HashMap; use std::collections::HashMap;
use std::os::unix::io::AsRawFd; use std::os::unix::io::AsRawFd;
use std::sync::RwLock; use std::sync::RwLock;
@ -101,13 +101,11 @@ impl hypervisor::Hypervisor for MshvHypervisor {
} }
let vm_fd = Arc::new(fd); let vm_fd = Arc::new(fd);
let ioeventfds = Arc::new(RwLock::new(HashMap::new()));
let gsi_routes = Arc::new(RwLock::new(HashMap::new())); let gsi_routes = Arc::new(RwLock::new(HashMap::new()));
Ok(Arc::new(MshvVm { Ok(Arc::new(MshvVm {
fd: vm_fd, fd: vm_fd,
msrs, msrs,
ioeventfds,
gsi_routes, gsi_routes,
hv_state: hv_state_init(), hv_state: hv_state_init(),
vmmops: None, vmmops: None,
@ -170,7 +168,6 @@ pub struct MshvVcpu {
vp_index: u8, vp_index: u8,
cpuid: CpuId, cpuid: CpuId,
msrs: MsrEntries, msrs: MsrEntries,
ioeventfds: Arc<RwLock<HashMap<IoEventAddress, (Option<DataMatch>, EventFd)>>>,
gsi_routes: Arc<RwLock<HashMap<u32, MshvIrqRoutingEntry>>>, gsi_routes: Arc<RwLock<HashMap<u32, MshvIrqRoutingEntry>>>,
hv_state: Arc<RwLock<HvState>>, // Mshv State hv_state: Arc<RwLock<HvState>>, // Mshv State
vmmops: Option<Arc<Box<dyn vm::VmmOps>>>, vmmops: Option<Arc<Box<dyn vm::VmmOps>>>,
@ -573,19 +570,6 @@ impl<'a> PlatformEmulator for MshvEmulatorContext<'a> {
gpa gpa
); );
if let Some((datamatch, efd)) = self
.vcpu
.ioeventfds
.read()
.unwrap()
.get(&IoEventAddress::Mmio(gpa))
{
debug!("ioevent {:x} {:x?} {}", gpa, datamatch, efd.as_raw_fd());
/* TODO: use datamatch to provide the correct semantics */
efd.write(1).unwrap();
}
if let Some(vmmops) = &self.vcpu.vmmops { if let Some(vmmops) = &self.vcpu.vmmops {
vmmops vmmops
.mmio_write(gpa, data) .mmio_write(gpa, data)
@ -654,8 +638,6 @@ impl<'a> PlatformEmulator for MshvEmulatorContext<'a> {
pub struct MshvVm { pub struct MshvVm {
fd: Arc<VmFd>, fd: Arc<VmFd>,
msrs: MsrEntries, msrs: MsrEntries,
// Emulate ioeventfd
ioeventfds: Arc<RwLock<HashMap<IoEventAddress, (Option<DataMatch>, EventFd)>>>,
// GSI routing information // GSI routing information
gsi_routes: Arc<RwLock<HashMap<u32, MshvIrqRoutingEntry>>>, gsi_routes: Arc<RwLock<HashMap<u32, MshvIrqRoutingEntry>>>,
// Hypervisor State // Hypervisor State
@ -743,7 +725,6 @@ impl vm::Vm for MshvVm {
vp_index: id, vp_index: id,
cpuid: CpuId::new(1), cpuid: CpuId::new(1),
msrs: self.msrs.clone(), msrs: self.msrs.clone(),
ioeventfds: self.ioeventfds.clone(),
gsi_routes: self.gsi_routes.clone(), gsi_routes: self.gsi_routes.clone(),
hv_state: self.hv_state.clone(), hv_state: self.hv_state.clone(),
vmmops, vmmops,
@ -760,26 +741,36 @@ impl vm::Vm for MshvVm {
addr: &IoEventAddress, addr: &IoEventAddress,
datamatch: Option<DataMatch>, datamatch: Option<DataMatch>,
) -> vm::Result<()> { ) -> vm::Result<()> {
let dup_fd = fd.try_clone().unwrap();
debug!( debug!(
"register_ioevent fd {} addr {:x?} datamatch {:?}", "register_ioevent fd {} addr {:x?} datamatch {:?}",
fd.as_raw_fd(), fd.as_raw_fd(),
addr, addr,
datamatch datamatch
); );
if let Some(dm) = datamatch {
self.ioeventfds match dm {
.write() vm::DataMatch::DataMatch32(mshv_dm32) => self
.unwrap() .fd
.insert(*addr, (datamatch, dup_fd)); .register_ioevent(fd, addr, mshv_dm32)
Ok(()) .map_err(|e| vm::HypervisorVmError::RegisterIoEvent(e.into())),
vm::DataMatch::DataMatch64(mshv_dm64) => self
.fd
.register_ioevent(fd, addr, mshv_dm64)
.map_err(|e| vm::HypervisorVmError::RegisterIoEvent(e.into())),
}
} else {
self.fd
.register_ioevent(fd, addr, NoDatamatch)
.map_err(|e| vm::HypervisorVmError::RegisterIoEvent(e.into()))
}
} }
/// Unregister an event from a certain address it has been previously registered to. /// Unregister an event from a certain address it has been previously registered to.
fn unregister_ioevent(&self, fd: &EventFd, addr: &IoEventAddress) -> vm::Result<()> { fn unregister_ioevent(&self, fd: &EventFd, addr: &IoEventAddress) -> vm::Result<()> {
debug!("unregister_ioevent fd {} addr {:x?}", fd.as_raw_fd(), addr); debug!("unregister_ioevent fd {} addr {:x?}", fd.as_raw_fd(), addr);
self.ioeventfds.write().unwrap().remove(addr).unwrap();
Ok(()) self.fd
.unregister_ioevent(fd, addr, NoDatamatch)
.map_err(|e| vm::HypervisorVmError::UnregisterIoEvent(e.into()))
} }
/// Creates/modifies a guest physical memory slot. /// Creates/modifies a guest physical memory slot.

View File

@ -42,14 +42,6 @@ pub struct IrqRouting {}
pub enum VcpuExit {} pub enum VcpuExit {}
pub struct MpState {} pub struct MpState {}
#[derive(Eq, PartialEq, Hash, Clone, Debug, Copy)]
pub enum IoEventAddress {
/// Representation of an programmable I/O address.
Pio(u64),
/// Representation of an memory mapped I/O address.
Mmio(u64),
}
impl SegmentRegisterOps for SegmentRegister { impl SegmentRegisterOps for SegmentRegister {
fn segment_type(&self) -> u8 { fn segment_type(&self) -> u8 {
self.type_ self.type_