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::vm::{self, VmmOps};
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 std::sync::Arc;
use vm::DataMatch;
@ -28,7 +29,6 @@ pub use x86_64::VcpuMshvState as CpuState;
#[cfg(target_arch = "x86_64")]
pub use x86_64::*;
// Wei: for emulating ioeventfd
use std::collections::HashMap;
use std::os::unix::io::AsRawFd;
use std::sync::RwLock;
@ -101,13 +101,11 @@ impl hypervisor::Hypervisor for MshvHypervisor {
}
let vm_fd = Arc::new(fd);
let ioeventfds = Arc::new(RwLock::new(HashMap::new()));
let gsi_routes = Arc::new(RwLock::new(HashMap::new()));
Ok(Arc::new(MshvVm {
fd: vm_fd,
msrs,
ioeventfds,
gsi_routes,
hv_state: hv_state_init(),
vmmops: None,
@ -170,7 +168,6 @@ pub struct MshvVcpu {
vp_index: u8,
cpuid: CpuId,
msrs: MsrEntries,
ioeventfds: Arc<RwLock<HashMap<IoEventAddress, (Option<DataMatch>, EventFd)>>>,
gsi_routes: Arc<RwLock<HashMap<u32, MshvIrqRoutingEntry>>>,
hv_state: Arc<RwLock<HvState>>, // Mshv State
vmmops: Option<Arc<Box<dyn vm::VmmOps>>>,
@ -573,19 +570,6 @@ impl<'a> PlatformEmulator for MshvEmulatorContext<'a> {
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 {
vmmops
.mmio_write(gpa, data)
@ -654,8 +638,6 @@ impl<'a> PlatformEmulator for MshvEmulatorContext<'a> {
pub struct MshvVm {
fd: Arc<VmFd>,
msrs: MsrEntries,
// Emulate ioeventfd
ioeventfds: Arc<RwLock<HashMap<IoEventAddress, (Option<DataMatch>, EventFd)>>>,
// GSI routing information
gsi_routes: Arc<RwLock<HashMap<u32, MshvIrqRoutingEntry>>>,
// Hypervisor State
@ -743,7 +725,6 @@ impl vm::Vm for MshvVm {
vp_index: id,
cpuid: CpuId::new(1),
msrs: self.msrs.clone(),
ioeventfds: self.ioeventfds.clone(),
gsi_routes: self.gsi_routes.clone(),
hv_state: self.hv_state.clone(),
vmmops,
@ -760,26 +741,36 @@ impl vm::Vm for MshvVm {
addr: &IoEventAddress,
datamatch: Option<DataMatch>,
) -> vm::Result<()> {
let dup_fd = fd.try_clone().unwrap();
debug!(
"register_ioevent fd {} addr {:x?} datamatch {:?}",
fd.as_raw_fd(),
addr,
datamatch
);
self.ioeventfds
.write()
.unwrap()
.insert(*addr, (datamatch, dup_fd));
Ok(())
if let Some(dm) = datamatch {
match dm {
vm::DataMatch::DataMatch32(mshv_dm32) => self
.fd
.register_ioevent(fd, addr, mshv_dm32)
.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.
fn unregister_ioevent(&self, fd: &EventFd, addr: &IoEventAddress) -> vm::Result<()> {
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.

View File

@ -42,14 +42,6 @@ pub struct IrqRouting {}
pub enum VcpuExit {}
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 {
fn segment_type(&self) -> u8 {
self.type_