mod error;
mod linux;
mod types;
pub use error::*;
pub use types::*;
use crate::device::Device;
use linux::*;
use std::os::fd::{AsRawFd, RawFd};
use vsock::VMADDR_CID_HOST;
type Result<T> = std::result::Result<T, LaunchError>;
#[derive(Default)]
pub struct Launcher {
vm_fd: RawFd,
slot_uid: u64,
cpu_ids: Vec<u32>,
}
impl Launcher {
pub fn new(dev: &Device) -> Result<Self> {
let mut slot_uid: u64 = 0;
let vm_fd = unsafe { ne_create_vm(dev.as_raw_fd(), &mut slot_uid) }?;
if vm_fd < 0 || slot_uid == 0 {
return Err(LaunchError::ioctl_err_from_errno());
}
Ok(Self {
vm_fd,
slot_uid,
cpu_ids: Vec::new(),
})
}
pub fn vm_fd(&self) -> RawFd {
self.vm_fd
}
pub fn slot_uid(&self) -> u64 {
self.slot_uid
}
pub fn set_memory(&mut self, mem: MemoryInfo) -> Result<()> {
let mut load_info = ImageLoadInfo::from(&mem.image_type);
unsafe { ne_get_image_load_info(self.vm_fd.as_raw_fd(), &mut load_info) }?;
let mut regions = UserMemoryRegions::new(mem.size_mib).map_err(LaunchError::MemInit)?;
regions
.image_fill(load_info.memory_offset as usize, mem.image_type)
.map_err(LaunchError::MemInit)?;
for r in regions.inner_ref() {
unsafe { ne_set_user_memory_region(self.vm_fd, r) }?;
}
Ok(())
}
pub fn add_vcpu(&mut self, id: Option<u32>) -> Result<()> {
let mut id = id.unwrap_or(0);
unsafe { ne_add_vcpu(self.vm_fd, &mut id) }?;
self.cpu_ids.push(id);
Ok(())
}
pub fn start(&self, flags: StartFlags, cid: Option<u32>) -> Result<u64> {
let cid = match cid {
Some(cid) => {
if cid <= VMADDR_CID_HOST || cid == u32::MAX {
return Err(LaunchError::CidInvalid);
}
cid
}
None => 0,
};
let mut start_info = StartInfo::new(flags, cid.into());
unsafe { ne_start_enclave(self.vm_fd, &mut start_info) }?;
Ok(start_info.cid)
}
}