From 7acb5c64370ae44209b0ec2651067784120302ff Mon Sep 17 00:00:00 2001 From: Muminul Islam Date: Fri, 4 Dec 2020 15:08:27 -0800 Subject: [PATCH] hypervisor, mshv: Define MshvEmulatorContext This patch adds the definition and implementation MshvEmulatorContext which is platform emulation for Hyper-V. Co-Developed-by: Samuel Ortiz Signed-off-by: Samuel Ortiz Co-Developed-by: Wei Liu Signed-off-by: Wei Liu Signed-off-by: Muminul Islam --- hypervisor/src/mshv/mod.rs | 111 +++++++++++++++++++++++++++++++++++++ 1 file changed, 111 insertions(+) diff --git a/hypervisor/src/mshv/mod.rs b/hypervisor/src/mshv/mod.rs index 196e76095..152ac911a 100644 --- a/hypervisor/src/mshv/mod.rs +++ b/hypervisor/src/mshv/mod.rs @@ -573,6 +573,117 @@ impl cpu::Vcpu for MshvVcpu { } } +struct MshvEmulatorContext<'a> { + vcpu: &'a MshvVcpu, + tlb: SoftTLB, +} + +/// Platform emulation for Hyper-V +impl<'a> PlatformEmulator for MshvEmulatorContext<'a> { + type CpuState = EmulatorCpuState; + + fn read_memory(&self, gva: u64, data: &mut [u8]) -> Result<(), PlatformError> { + let gpa = self.tlb.translate(gva)?; + debug!( + "mshv emulator: memory read {} bytes from [{:#x} -> {:#x}]", + data.len(), + gva, + gpa + ); + + if let Some(vmmops) = &self.vcpu.vmmops { + vmmops + .mmio_read(gpa, data) + .map_err(|e| PlatformError::MemoryReadFailure(e.into()))?; + } + + Ok(()) + } + + fn write_memory(&mut self, gva: u64, data: &[u8]) -> Result<(), PlatformError> { + let gpa = self.tlb.translate(gva)?; + debug!( + "mshv emulator: memory write {} bytes at [{:#x} -> {:#x}]", + data.len(), + gva, + 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) + .map_err(|e| PlatformError::MemoryWriteFailure(e.into()))?; + } + + Ok(()) + } + + fn cpu_state(&self, cpu_id: usize) -> Result { + if cpu_id != self.vcpu.vp_index as usize { + return Err(PlatformError::GetCpuStateFailure(anyhow!( + "CPU id mismatch {:?} {:?}", + cpu_id, + self.vcpu.vp_index + ))); + } + + let regs = self + .vcpu + .get_regs() + .map_err(|e| PlatformError::GetCpuStateFailure(e.into()))?; + let sregs = self + .vcpu + .get_sregs() + .map_err(|e| PlatformError::GetCpuStateFailure(e.into()))?; + + debug!("mshv emulator: Getting new CPU state"); + debug!("mshv emulator: {:#x?}", regs); + + Ok(EmulatorCpuState { regs, sregs }) + } + + fn set_cpu_state(&self, cpu_id: usize, state: Self::CpuState) -> Result<(), PlatformError> { + if cpu_id != self.vcpu.vp_index as usize { + return Err(PlatformError::SetCpuStateFailure(anyhow!( + "CPU id mismatch {:?} {:?}", + cpu_id, + self.vcpu.vp_index + ))); + } + + debug!("mshv emulator: Setting new CPU state"); + debug!("mshv emulator: {:#x?}", state.regs); + + self.vcpu + .set_regs(&state.regs) + .map_err(|e| PlatformError::SetCpuStateFailure(e.into()))?; + self.vcpu + .set_sregs(&state.sregs) + .map_err(|e| PlatformError::SetCpuStateFailure(e.into())) + } + + fn gva_to_gpa(&self, gva: u64) -> Result { + self.tlb.translate(gva) + } + + fn fetch(&self, ip: u64, instruction_bytes: &mut [u8]) -> Result<(), PlatformError> { + Err(PlatformError::MemoryReadFailure(anyhow!("unimplemented"))) + } +} + #[allow(clippy::type_complexity)] /// Wrapper over Mshv VM ioctls. pub struct MshvVm {