use crate::{call, sys, Error, Vcpu};
mod regs;
pub use regs::*;
#[repr(u32)]
#[derive(Debug, Copy, Clone, Eq, PartialEq)]
pub enum InterruptType {
IRQ = sys::hv_interrupt_type_t_HV_INTERRUPT_TYPE_IRQ,
FIQ = sys::hv_interrupt_type_t_HV_INTERRUPT_TYPE_FIQ,
}
#[repr(u32)]
#[derive(Debug, Copy, Clone, Eq, PartialEq)]
pub enum ExitReason {
Canceled = sys::hv_exit_reason_t_HV_EXIT_REASON_CANCELED,
Exception = sys::hv_exit_reason_t_HV_EXIT_REASON_EXCEPTION,
VTimerActivated = sys::hv_exit_reason_t_HV_EXIT_REASON_VTIMER_ACTIVATED,
Unknown = sys::hv_exit_reason_t_HV_EXIT_REASON_UNKNOWN,
}
impl Default for ExitReason {
fn default() -> Self {
ExitReason::Unknown
}
}
impl From<sys::hv_exit_reason_t> for ExitReason {
fn from(value: sys::hv_exit_reason_t) -> Self {
match value {
sys::hv_exit_reason_t_HV_EXIT_REASON_CANCELED => ExitReason::Canceled,
sys::hv_exit_reason_t_HV_EXIT_REASON_EXCEPTION => ExitReason::Exception,
sys::hv_exit_reason_t_HV_EXIT_REASON_VTIMER_ACTIVATED => ExitReason::VTimerActivated,
sys::hv_exit_reason_t_HV_EXIT_REASON_UNKNOWN => ExitReason::Unknown,
_ => ExitReason::Unknown,
}
}
}
pub type VcpuExit = sys::hv_vcpu_exit_t;
pub trait VcpuExt {
fn get_reg(&self, reg: regs::Reg) -> Result<u64, Error>;
fn set_reg(&self, reg: regs::Reg, value: u64) -> Result<(), Error>;
fn get_simd_fp_reg(&self, reg: regs::SimdFpReg) -> Result<regs::SimdFpUchar16, Error>;
fn set_simd_fp_reg(
&self,
reg: regs::SimdFpReg,
value: regs::SimdFpUchar16,
) -> Result<(), Error>;
fn get_sys_reg(&self, reg: regs::SysReg) -> Result<u64, Error>;
fn set_sys_reg(&self, reg: regs::SysReg, value: u64) -> Result<(), Error>;
fn pending_interrupt(&self, ty: InterruptType) -> Result<bool, Error>;
fn set_pending_interrupt(&self, ty: InterruptType, pending: bool) -> Result<(), Error>;
fn trap_debug_exceptions(&self) -> Result<bool, Error>;
fn set_trap_debug_exceptions(&self, enable: bool) -> Result<(), Error>;
fn trap_debug_reg_accesses(&self) -> Result<bool, Error>;
fn set_trap_debug_reg_accesses(&self, enable: bool) -> Result<(), Error>;
fn vtimer_mask(&self) -> Result<bool, Error>;
fn set_vtimer_mask(&self, vtimer_is_masked: bool) -> Result<(), Error>;
fn vtimer_offset(&self) -> Result<u64, Error>;
fn set_vtimer_offset(&self, vtimer_offset: u64) -> Result<(), Error>;
fn exit_info(&self) -> VcpuExit;
}
impl VcpuExt for Vcpu {
fn get_reg(&self, reg: regs::Reg) -> Result<u64, Error> {
let mut out = 0_u64;
call!(sys::hv_vcpu_get_reg(self.id, reg as _, &mut out))?;
Ok(out)
}
fn set_reg(&self, reg: regs::Reg, value: u64) -> Result<(), Error> {
call!(sys::hv_vcpu_set_reg(self.id, reg as _, value))
}
fn get_simd_fp_reg(&self, reg: regs::SimdFpReg) -> Result<regs::SimdFpUchar16, Error> {
let mut out = 0_u128;
call!(sys::hv_vcpu_get_simd_fp_reg(self.id, reg as _, &mut out))?;
Ok(out)
}
fn set_simd_fp_reg(
&self,
reg: regs::SimdFpReg,
value: regs::SimdFpUchar16,
) -> Result<(), Error> {
call!(sys::hv_vcpu_set_simd_fp_reg(self.id, reg as _, value))?;
Ok(())
}
fn get_sys_reg(&self, reg: regs::SysReg) -> Result<u64, Error> {
let mut out = 0_u64;
call!(sys::hv_vcpu_get_sys_reg(self.id, reg as _, &mut out))?;
Ok(out)
}
fn set_sys_reg(&self, reg: regs::SysReg, value: u64) -> Result<(), Error> {
call!(sys::hv_vcpu_set_sys_reg(self.id, reg as _, value))
}
fn pending_interrupt(&self, ty: InterruptType) -> Result<bool, Error> {
let mut out = false;
call!(sys::hv_vcpu_get_pending_interrupt(
self.id, ty as u32, &mut out
))?;
Ok(out)
}
fn set_pending_interrupt(&self, ty: InterruptType, mut pending: bool) -> Result<(), Error> {
call!(sys::hv_vcpu_get_pending_interrupt(
self.id,
ty as u32,
&mut pending
))
}
fn trap_debug_exceptions(&self) -> Result<bool, Error> {
let mut out = false;
call!(sys::hv_vcpu_get_trap_debug_exceptions(self.id, &mut out))?;
Ok(out)
}
fn set_trap_debug_exceptions(&self, enable: bool) -> Result<(), Error> {
call!(sys::hv_vcpu_set_trap_debug_exceptions(self.id, enable))
}
fn trap_debug_reg_accesses(&self) -> Result<bool, Error> {
let mut out = false;
call!(sys::hv_vcpu_get_trap_debug_reg_accesses(self.id, &mut out))?;
Ok(out)
}
fn set_trap_debug_reg_accesses(&self, enable: bool) -> Result<(), Error> {
call!(sys::hv_vcpu_set_trap_debug_reg_accesses(self.id, enable))
}
fn vtimer_mask(&self) -> Result<bool, Error> {
let mut out = false;
call!(sys::hv_vcpu_get_vtimer_mask(self.id, &mut out))?;
Ok(out)
}
fn set_vtimer_mask(&self, vtimer_is_masked: bool) -> Result<(), Error> {
call!(sys::hv_vcpu_set_vtimer_mask(self.id, vtimer_is_masked))
}
fn vtimer_offset(&self) -> Result<u64, Error> {
let mut out = 0_u64;
call!(sys::hv_vcpu_get_vtimer_offset(self.id, &mut out))?;
Ok(out)
}
fn set_vtimer_offset(&self, vtimer_offset: u64) -> Result<(), Error> {
call!(sys::hv_vcpu_set_vtimer_offset(self.id, vtimer_offset))
}
fn exit_info(&self) -> VcpuExit {
if self.exit.is_null() {
VcpuExit::default()
} else {
unsafe { *self.exit }
}
}
}