use std::time::Duration;
use crate::{
Architecture, Gfn, MemoryAccess, MemoryAccessOptions, VcpuId, View, VmiError, VmiEvent,
VmiEventResponse, VmiInfo, VmiMappedPage,
};
pub trait VmiDriver: 'static {
type Architecture: Architecture;
fn info(&self) -> Result<VmiInfo, VmiError>;
}
pub trait VmiRead: VmiDriver {
fn read_page(&self, gfn: Gfn) -> Result<VmiMappedPage, VmiError>;
}
pub trait VmiWrite: VmiDriver {
fn write_page(&self, gfn: Gfn, offset: u64, content: &[u8]) -> Result<VmiMappedPage, VmiError>;
}
pub trait VmiQueryProtection: VmiDriver {
fn memory_access(&self, gfn: Gfn, view: View) -> Result<MemoryAccess, VmiError>;
}
pub trait VmiSetProtection: VmiDriver {
fn set_memory_access(&self, gfn: Gfn, view: View, access: MemoryAccess)
-> Result<(), VmiError>;
fn set_memory_access_with_options(
&self,
gfn: Gfn,
view: View,
access: MemoryAccess,
options: MemoryAccessOptions,
) -> Result<(), VmiError>;
}
pub trait VmiQueryRegisters: VmiDriver {
fn registers(
&self,
vcpu: VcpuId,
) -> Result<<Self::Architecture as Architecture>::Registers, VmiError>;
}
pub trait VmiSetRegisters: VmiDriver {
fn set_registers(
&self,
vcpu: VcpuId,
registers: <Self::Architecture as Architecture>::Registers,
) -> Result<(), VmiError>;
}
pub trait VmiEventControl: VmiDriver {
fn monitor_enable(
&self,
option: <Self::Architecture as Architecture>::EventMonitor,
) -> Result<(), VmiError>;
fn monitor_disable(
&self,
option: <Self::Architecture as Architecture>::EventMonitor,
) -> Result<(), VmiError>;
fn events_pending(&self) -> usize;
fn event_processing_overhead(&self) -> Duration;
fn wait_for_event(
&self,
timeout: Duration,
handler: impl FnMut(&VmiEvent<Self::Architecture>) -> VmiEventResponse<Self::Architecture>,
) -> Result<(), VmiError>;
}
pub trait VmiViewControl: VmiDriver {
fn default_view(&self) -> View;
fn create_view(&self, default_access: MemoryAccess) -> Result<View, VmiError>;
fn destroy_view(&self, view: View) -> Result<(), VmiError>;
fn switch_to_view(&self, view: View) -> Result<(), VmiError>;
fn change_view_gfn(&self, view: View, old_gfn: Gfn, new_gfn: Gfn) -> Result<(), VmiError>;
fn reset_view_gfn(&self, view: View, gfn: Gfn) -> Result<(), VmiError>;
}
pub trait VmiVmControl: VmiDriver {
fn pause(&self) -> Result<(), VmiError>;
fn resume(&self) -> Result<(), VmiError>;
fn allocate_gfn(&self) -> Result<Gfn, VmiError>;
fn allocate_gfn_at(&self, gfn: Gfn) -> Result<(), VmiError>;
fn free_gfn(&self, gfn: Gfn) -> Result<(), VmiError>;
fn inject_interrupt(
&self,
vcpu: VcpuId,
interrupt: <Self::Architecture as Architecture>::Interrupt,
) -> Result<(), VmiError>;
fn reset_state(&self) -> Result<(), VmiError>;
}
pub trait VmiMemory: VmiRead + VmiWrite {}
impl<T> VmiMemory for T where T: VmiRead + VmiWrite {}
pub trait VmiProtection: VmiQueryProtection + VmiSetProtection {}
impl<T> VmiProtection for T where T: VmiQueryProtection + VmiSetProtection {}
pub trait VmiRegisters: VmiQueryRegisters + VmiSetRegisters {}
impl<T> VmiRegisters for T where T: VmiQueryRegisters + VmiSetRegisters {}
pub trait VmiReadAccess: VmiRead + VmiQueryProtection + VmiQueryRegisters {}
impl<T> VmiReadAccess for T where T: VmiRead + VmiQueryProtection + VmiQueryRegisters {}
pub trait VmiWriteAccess: VmiWrite + VmiSetProtection + VmiSetRegisters {}
impl<T> VmiWriteAccess for T where T: VmiWrite + VmiSetProtection + VmiSetRegisters {}
pub trait VmiFullDriver:
VmiReadAccess + VmiWriteAccess + VmiEventControl + VmiViewControl + VmiVmControl
{
}
impl<T> VmiFullDriver for T where
T: VmiReadAccess + VmiWriteAccess + VmiEventControl + VmiViewControl + VmiVmControl
{
}