use crate::{ok, sys, AsHandleRef, Handle, HandleBased, HandleRef, Port, Resource, Status, Vmar};
#[derive(Debug, Clone, Copy, Eq, PartialEq, Ord, PartialOrd, Hash)]
#[repr(transparent)]
pub struct GPAddr(pub usize);
#[derive(Debug, Eq, PartialEq, Ord, PartialOrd, Hash)]
#[repr(transparent)]
pub struct Guest(Handle);
impl_handle_based!(Guest);
impl Guest {
pub fn normal(hypervisor: &Resource) -> Result<(Guest, Vmar), Status> {
Self::create(hypervisor, sys::ZX_GUEST_OPT_NORMAL)
}
fn create(
hypervisor: &Resource,
options: sys::zx_guest_option_t,
) -> Result<(Guest, Vmar), Status> {
unsafe {
let mut guest_handle = 0;
let mut vmar_handle = 0;
ok(sys::zx_guest_create(
hypervisor.raw_handle(),
options,
&mut guest_handle,
&mut vmar_handle,
))?;
Ok((
Self::from(Handle::from_raw(guest_handle)),
Vmar::from(Handle::from_raw(vmar_handle)),
))
}
}
pub fn set_trap_bell(
&self,
addr: GPAddr,
size: usize,
port: &Port,
key: u64,
) -> Result<(), Status> {
ok(unsafe {
sys::zx_guest_set_trap(
self.raw_handle(),
sys::ZX_GUEST_TRAP_BELL,
addr.0,
size,
port.raw_handle(),
key,
)
})
}
pub fn set_mem_trap(&self, addr: GPAddr, size: usize, key: u64) -> Result<(), Status> {
ok(unsafe {
sys::zx_guest_set_trap(
self.raw_handle(),
sys::ZX_GUEST_TRAP_MEM,
addr.0,
size,
sys::ZX_HANDLE_INVALID,
key,
)
})
}
pub fn set_io_trap(&self, addr: u16, size: u16, key: u64) -> Result<(), Status> {
ok(unsafe {
sys::zx_guest_set_trap(
self.raw_handle(),
sys::ZX_GUEST_TRAP_IO,
addr.into(),
size.into(),
sys::ZX_HANDLE_INVALID,
key,
)
})
}
}
#[derive(Debug, Clone, Copy)]
pub enum CSDefaultOperandSize {
Bits16 = 2,
Bits32 = 4,
}
#[derive(Debug, Clone, Copy)]
pub enum MemAccessSize {
Bits8 = 1,
Bits16 = 2,
Bits32 = 4,
Bits64 = 8,
}
#[derive(Debug, Clone, Copy)]
pub enum MemData {
Data8(u8),
Data16(u16),
Data32(u32),
Data64(u64),
}
#[derive(Debug, Clone, Copy)]
pub enum PortAccessSize {
Bits8 = 1,
Bits16 = 2,
Bits32 = 4,
}
#[derive(Debug, Clone, Copy)]
pub enum AccessType {
Read,
Write,
}
#[derive(Debug, Clone, Copy)]
pub enum PortData {
Data8(u8),
Data16(u16),
Data32(u32),
}
#[cfg(test)]
mod tests {
use super::*;
use fidl_fuchsia_kernel as fkernel;
use fuchsia_component::client::connect_to_protocol;
use zx::HandleBased;
async fn get_hypervisor() -> Resource {
let resource = connect_to_protocol::<fkernel::HypervisorResourceMarker>()
.unwrap()
.get()
.await
.unwrap();
unsafe { Resource::from(Handle::from_raw(resource.into_raw())) }
}
#[fuchsia::test]
async fn guest_normal_create() {
let hypervisor = get_hypervisor().await;
match Guest::normal(&hypervisor) {
Err(Status::NOT_SUPPORTED) => {
println!("Hypervisor not supported");
return;
}
result => result.unwrap(),
};
}
}