use crate::bits64::rflags::{self, RFlags};
use crate::vmx::{Result, VmFail};
use core::arch::asm;
#[inline(always)]
fn vmx_capture_status() -> Result<()> {
let flags = rflags::read();
if flags.contains(RFlags::FLAGS_ZF) {
Err(VmFail::VmFailValid)
} else if flags.contains(RFlags::FLAGS_CF) {
Err(VmFail::VmFailInvalid)
} else {
Ok(())
}
}
pub unsafe fn vmxon(addr: u64) -> Result<()> {
asm!("vmxon ({0})", in(reg) &addr, options(att_syntax));
vmx_capture_status()
}
pub unsafe fn vmxoff() -> Result<()> {
asm!("vmxoff");
vmx_capture_status()
}
pub unsafe fn vmclear(addr: u64) -> Result<()> {
asm!("vmclear ({0})", in(reg) &addr, options(att_syntax));
vmx_capture_status()
}
pub unsafe fn vmptrld(addr: u64) -> Result<()> {
asm!("vmptrld ({0})", in(reg) &addr, options(att_syntax));
vmx_capture_status()
}
pub unsafe fn vmptrst() -> Result<u64> {
let value: u64 = 0;
asm!("vmptrst ({0})", in(reg) &value, options(att_syntax));
vmx_capture_status().and(Ok(value))
}
pub unsafe fn vmread(field: u32) -> Result<u64> {
let field: u64 = field.into();
let value: u64;
asm!("vmread {0}, {1}", in(reg) field, out(reg) value, options(att_syntax));
vmx_capture_status().and(Ok(value))
}
pub unsafe fn vmwrite(field: u32, value: u64) -> Result<()> {
let field: u64 = field.into();
asm!("vmwrite {1}, {0}", in(reg) field, in(reg) value, options(att_syntax));
vmx_capture_status()
}
#[inline(always)]
pub unsafe fn vmlaunch() -> Result<()> {
asm!("vmlaunch");
vmx_capture_status()
}
#[inline(always)]
pub unsafe fn vmresume() -> Result<()> {
asm!("vmresume");
vmx_capture_status()
}