mirror of
https://github.com/cloud-hypervisor/cloud-hypervisor.git
synced 2026-08-05 02:19:16 +00:00
hypervisor, vmm: Introduce VmmOps trait
Run loop in hypervisor needs a callback mechanism to access resources like guest memory, mmio, pio etc. VmmOps trait is introduced here, which is implemented by vmm module. While handling vcpuexits in run loop, this trait allows hypervisor module access to the above mentioned resources via callbacks. Signed-off-by: Praveen Paladugu <prapal@microsoft.com> Signed-off-by: Sebastien Boeuf <sebastien.boeuf@intel.com>
This commit is contained in:
committed by
Rob Bradford
parent
6a9934d933
commit
71c435ce91
@@ -16,9 +16,10 @@ pub use crate::aarch64::{
|
||||
use crate::cpu;
|
||||
use crate::device;
|
||||
use crate::hypervisor;
|
||||
use crate::vm;
|
||||
use crate::vm::{self, VmmOps};
|
||||
#[cfg(target_arch = "aarch64")]
|
||||
use crate::{arm64_core_reg_id, offset__of};
|
||||
use arc_swap::ArcSwapOption;
|
||||
use kvm_ioctls::{NoDatamatch, VcpuFd, VmFd};
|
||||
use serde_derive::{Deserialize, Serialize};
|
||||
use std::os::unix::io::{AsRawFd, RawFd};
|
||||
@@ -91,6 +92,7 @@ pub struct KvmVm {
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
msrs: MsrEntries,
|
||||
state: KvmVmState,
|
||||
vmmops: ArcSwapOption<Box<dyn vm::VmmOps>>,
|
||||
}
|
||||
|
||||
// Returns a `Vec<T>` with a size in bytes at least as large as `size_in_bytes`.
|
||||
@@ -179,6 +181,7 @@ impl vm::Vm for KvmVm {
|
||||
fd: vc,
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
msrs: self.msrs.clone(),
|
||||
vmmops: self.vmmops.clone(),
|
||||
};
|
||||
Ok(Arc::new(vcpu))
|
||||
}
|
||||
@@ -345,6 +348,14 @@ impl vm::Vm for KvmVm {
|
||||
fn set_state(&self, _state: VmState) -> vm::Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
///
|
||||
/// Set the VmmOps interface
|
||||
///
|
||||
fn set_vmmops(&self, vmmops: Box<dyn VmmOps>) -> vm::Result<()> {
|
||||
self.vmmops.store(Some(Arc::new(vmmops)));
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
/// Wrapper over KVM system ioctls.
|
||||
pub struct KvmHypervisor {
|
||||
@@ -422,6 +433,7 @@ impl hypervisor::Hypervisor for KvmHypervisor {
|
||||
fd: vm_fd,
|
||||
msrs,
|
||||
state: VmState {},
|
||||
vmmops: ArcSwapOption::from(None),
|
||||
}))
|
||||
}
|
||||
|
||||
@@ -430,6 +442,7 @@ impl hypervisor::Hypervisor for KvmHypervisor {
|
||||
Ok(Arc::new(KvmVm {
|
||||
fd: vm_fd,
|
||||
state: VmState {},
|
||||
vmmops: ArcSwapOption::from(None),
|
||||
}))
|
||||
}
|
||||
}
|
||||
@@ -490,6 +503,7 @@ pub struct KvmVcpu {
|
||||
fd: VcpuFd,
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
msrs: MsrEntries,
|
||||
vmmops: ArcSwapOption<Box<dyn vm::VmmOps>>,
|
||||
}
|
||||
/// Implementation of Vcpu trait for KVM
|
||||
/// Example:
|
||||
@@ -681,9 +695,27 @@ impl cpu::Vcpu for KvmVcpu {
|
||||
match self.fd.run() {
|
||||
Ok(run) => match run {
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
VcpuExit::IoIn(addr, data) => Ok(cpu::VmExit::IoIn(addr, data)),
|
||||
VcpuExit::IoIn(addr, data) => {
|
||||
if let Some(vmmops) = self.vmmops.load_full() {
|
||||
return vmmops
|
||||
.pio_read(addr.into(), data)
|
||||
.map(|_| cpu::VmExit::Ignore)
|
||||
.map_err(|e| cpu::HypervisorCpuError::RunVcpu(e.into()));
|
||||
}
|
||||
|
||||
Ok(cpu::VmExit::IoIn(addr, data))
|
||||
}
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
VcpuExit::IoOut(addr, data) => Ok(cpu::VmExit::IoOut(addr, data)),
|
||||
VcpuExit::IoOut(addr, data) => {
|
||||
if let Some(vmmops) = self.vmmops.load_full() {
|
||||
return vmmops
|
||||
.pio_write(addr.into(), data)
|
||||
.map(|_| cpu::VmExit::Ignore)
|
||||
.map_err(|e| cpu::HypervisorCpuError::RunVcpu(e.into()));
|
||||
}
|
||||
|
||||
Ok(cpu::VmExit::IoOut(addr, data))
|
||||
}
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
VcpuExit::IoapicEoi(vector) => Ok(cpu::VmExit::IoapicEoi(vector)),
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
@@ -705,8 +737,26 @@ impl cpu::Vcpu for KvmVcpu {
|
||||
}
|
||||
}
|
||||
|
||||
VcpuExit::MmioRead(addr, data) => Ok(cpu::VmExit::MmioRead(addr, data)),
|
||||
VcpuExit::MmioWrite(addr, data) => Ok(cpu::VmExit::MmioWrite(addr, data)),
|
||||
VcpuExit::MmioRead(addr, data) => {
|
||||
if let Some(vmmops) = self.vmmops.load_full() {
|
||||
return vmmops
|
||||
.mmio_read(addr, data)
|
||||
.map(|_| cpu::VmExit::Ignore)
|
||||
.map_err(|e| cpu::HypervisorCpuError::RunVcpu(e.into()));
|
||||
}
|
||||
|
||||
Ok(cpu::VmExit::MmioRead(addr, data))
|
||||
}
|
||||
VcpuExit::MmioWrite(addr, data) => {
|
||||
if let Some(vmmops) = self.vmmops.load_full() {
|
||||
return vmmops
|
||||
.mmio_write(addr, data)
|
||||
.map(|_| cpu::VmExit::Ignore)
|
||||
.map_err(|e| cpu::HypervisorCpuError::RunVcpu(e.into()));
|
||||
}
|
||||
|
||||
Ok(cpu::VmExit::MmioWrite(addr, data))
|
||||
}
|
||||
VcpuExit::Hyperv => Ok(cpu::VmExit::Hyperv),
|
||||
|
||||
r => Err(cpu::HypervisorCpuError::RunVcpu(anyhow!(
|
||||
|
||||
@@ -117,6 +117,36 @@ pub enum HypervisorVmError {
|
||||
///
|
||||
#[error("Failed to create passthrough device: {0}")]
|
||||
CreatePassthroughDevice(#[source] anyhow::Error),
|
||||
///
|
||||
/// Write to Guest memory
|
||||
///
|
||||
#[error("Failed to write to guest memory: {0}")]
|
||||
GuestMemWrite(#[source] anyhow::Error),
|
||||
///
|
||||
/// Read Guest memory
|
||||
///
|
||||
#[error("Failed to read guest memory: {0}")]
|
||||
GuestMemRead(#[source] anyhow::Error),
|
||||
///
|
||||
/// Read from MMIO Bus
|
||||
///
|
||||
#[error("Failed to read from MMIO Bus: {0}")]
|
||||
MmioBusRead(#[source] anyhow::Error),
|
||||
///
|
||||
/// Write to MMIO Bus
|
||||
///
|
||||
#[error("Failed to write to MMIO Bus: {0}")]
|
||||
MmioBusWrite(#[source] anyhow::Error),
|
||||
///
|
||||
/// Read from IO Bus
|
||||
///
|
||||
#[error("Failed to read from IO Bus: {0}")]
|
||||
IoBusRead(#[source] anyhow::Error),
|
||||
///
|
||||
/// Write to IO Bus
|
||||
///
|
||||
#[error("Failed to write to IO Bus: {0}")]
|
||||
IoBusWrite(#[source] anyhow::Error),
|
||||
}
|
||||
///
|
||||
/// Result type for returning from a function
|
||||
@@ -184,4 +214,17 @@ pub trait Vm: Send + Sync {
|
||||
fn state(&self) -> Result<VmState>;
|
||||
/// Set the VM state
|
||||
fn set_state(&self, state: VmState) -> Result<()>;
|
||||
/// Set VmmOps interface
|
||||
fn set_vmmops(&self, vmmops: Box<dyn VmmOps>) -> Result<()>;
|
||||
}
|
||||
|
||||
pub trait VmmOps: Send + Sync {
|
||||
fn guest_mem_write(&self, buf: &[u8], gpa: u64) -> Result<usize>;
|
||||
fn guest_mem_read(&self, buf: &mut [u8], gpa: u64) -> Result<usize>;
|
||||
fn mmio_read(&self, addr: u64, data: &mut [u8]) -> Result<()>;
|
||||
fn mmio_write(&self, addr: u64, data: &[u8]) -> Result<()>;
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
fn pio_read(&self, addr: u64, data: &mut [u8]) -> Result<()>;
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
fn pio_write(&self, addr: u64, data: &[u8]) -> Result<()>;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user