use crate::bits64::rflags::{self, RFlags};
use crate::vmx::{Result, VmFail};
#[inline(always)]
fn vmx_capture_status() -> Result<()> {
let flags = unsafe { 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<()> {
llvm_asm!("vmxon $0" : : "m"(addr));
vmx_capture_status()
}
pub unsafe fn vmxoff() -> Result<()> {
llvm_asm!("vmxoff");
vmx_capture_status()
}
pub unsafe fn vmclear(addr: u64) -> Result<()> {
llvm_asm!("vmclear $0" : : "m"(addr));
vmx_capture_status()
}
pub unsafe fn vmptrld(addr: u64) -> Result<()> {
llvm_asm!("vmptrld $0" : : "m"(addr));
vmx_capture_status()
}
pub unsafe fn vmptrst() -> Result<u64> {
let value: u64 = 0;
llvm_asm!("vmptrst ($0)" : : "r"(&value) : "memory");
vmx_capture_status().and(Ok(value))
}
pub unsafe fn vmread(field: u32) -> Result<u64> {
let field: u64 = field.into();
let value: u64;
llvm_asm!("vmread $1, $0" : "=r"(value) : "r"(field));
vmx_capture_status().and(Ok(value))
}
pub unsafe fn vmwrite(field: u32, value: u64) -> Result<()> {
let field: u64 = field.into();
llvm_asm!("vmwrite $1, $0" : : "r"(field), "r"(value));
vmx_capture_status()
}
#[inline(always)]
pub unsafe fn vmlaunch() -> Result<()> {
llvm_asm!("vmlaunch");
vmx_capture_status()
}
#[inline(always)]
pub unsafe fn vmresume() -> Result<()> {
llvm_asm!("vmresume");
vmx_capture_status()
}