#[cfg(gdb)]
use std::sync::{Arc, Mutex};
use rand::RngExt;
use tracing::{Span, instrument};
use super::SandboxConfiguration;
#[cfg(any(crashdump, gdb))]
use super::uninitialized::SandboxRuntimeConfig;
use crate::hypervisor::hyperlight_vm::{HyperlightVm, HyperlightVmError};
use crate::mem::exe::LoadInfo;
use crate::mem::mgr::SandboxMemoryManager;
use crate::mem::ptr::RawPtr;
use crate::mem::shared_mem::GuestSharedMemory;
#[cfg(gdb)]
use crate::sandbox::config::DebugInfo;
#[cfg(feature = "mem_profile")]
use crate::sandbox::trace::MemTraceInfo;
#[cfg(target_os = "linux")]
use crate::signal_handlers::setup_signal_handlers;
use crate::{MultiUseSandbox, Result, UninitializedSandbox};
#[instrument(err(Debug), skip_all, parent = Span::current(), level = "Trace")]
pub(super) fn evolve_impl_multi_use(u_sbox: UninitializedSandbox) -> Result<MultiUseSandbox> {
let (mut hshm, gshm) = u_sbox.mgr.build()?;
#[cfg(feature = "nanvix-unstable")]
{
#[allow(clippy::unwrap_used)]
{
*u_sbox.deferred_hshm.lock().unwrap() = Some(hshm.scratch_mem.clone());
}
}
let page_size = u32::try_from(page_size::get())?;
let mut vm = set_up_hypervisor_partition(
gshm,
&u_sbox.config,
u_sbox.stack_top_gva,
page_size as usize,
#[cfg(any(crashdump, gdb))]
u_sbox.rt_cfg,
u_sbox.load_info,
)?;
let seed = {
let mut rng = rand::rng();
rng.random::<u64>()
};
let peb_addr = {
let peb_u64 = u64::try_from(hshm.layout.peb_address)?;
RawPtr::from(peb_u64)
};
#[cfg(gdb)]
let dbg_mem_access_hdl = Arc::new(Mutex::new(hshm.clone()));
#[cfg(target_os = "linux")]
setup_signal_handlers(&u_sbox.config)?;
let pending = u_sbox.pending_file_mappings;
for mut prepared in pending {
let region = prepared.to_memory_region()?;
unsafe { vm.map_region(®ion) }.map_err(|e| {
crate::HyperlightError::HyperlightVmError(HyperlightVmError::MapRegion(e))
})?;
prepared.mark_consumed();
#[cfg(feature = "nanvix-unstable")]
hshm.write_file_mapping_entry(prepared.guest_base, prepared.size as u64, &prepared.label)?;
hshm.mapped_rgns += 1;
}
vm.initialise(
peb_addr,
seed,
page_size,
&mut hshm,
&u_sbox.host_funcs,
u_sbox.max_guest_log_level,
#[cfg(gdb)]
dbg_mem_access_hdl,
)
.map_err(HyperlightVmError::Initialize)?;
#[cfg(gdb)]
let dbg_mem_wrapper = Arc::new(Mutex::new(hshm.clone()));
Ok(MultiUseSandbox::from_uninit(
u_sbox.host_funcs,
hshm,
vm,
#[cfg(gdb)]
dbg_mem_wrapper,
))
}
pub(crate) fn set_up_hypervisor_partition(
mgr: SandboxMemoryManager<GuestSharedMemory>,
#[cfg_attr(target_os = "windows", allow(unused_variables))] config: &SandboxConfiguration,
stack_top_gva: u64,
page_size: usize,
#[cfg(any(crashdump, gdb))] rt_cfg: SandboxRuntimeConfig,
_load_info: LoadInfo,
) -> Result<HyperlightVm> {
#[cfg(gdb)]
let gdb_conn = if let Some(DebugInfo { port }) = rt_cfg.debug_info {
use crate::hypervisor::gdb::create_gdb_thread;
let gdb_conn = create_gdb_thread(port);
match gdb_conn {
Ok(gdb_conn) => Some(gdb_conn),
Err(e) => {
tracing::error!("Could not create gdb connection: {:#}", e);
None
}
}
} else {
None
};
#[cfg(feature = "mem_profile")]
let trace_info = MemTraceInfo::new(_load_info.info)?;
#[cfg(crashdump)]
let rt_cfg = {
let mut rt_cfg = rt_cfg;
if let crate::sandbox::snapshot::NextAction::Initialise(addr) = mgr.entrypoint {
rt_cfg.entry_point = Some(addr);
}
rt_cfg
};
Ok(HyperlightVm::new(
mgr.shared_mem,
mgr.scratch_mem,
mgr.layout.get_pt_base_gpa(),
mgr.entrypoint,
stack_top_gva,
page_size,
config,
#[cfg(gdb)]
gdb_conn,
#[cfg(crashdump)]
rt_cfg,
#[cfg(feature = "mem_profile")]
trace_info,
)
.map_err(HyperlightVmError::Create)?)
}
#[cfg(test)]
mod tests {
use hyperlight_testing::simple_guest_as_string;
use super::evolve_impl_multi_use;
use crate::UninitializedSandbox;
use crate::sandbox::uninitialized::GuestBinary;
#[test]
fn test_evolve() {
let guest_bin_paths = vec![simple_guest_as_string().unwrap()];
for guest_bin_path in guest_bin_paths {
let u_sbox =
UninitializedSandbox::new(GuestBinary::FilePath(guest_bin_path.clone()), None)
.unwrap();
evolve_impl_multi_use(u_sbox).unwrap();
}
}
}