use std::os::raw::c_void;
use std::sync::{Arc, Mutex};
use tracing::{instrument, Span};
use crate::hypervisor::handlers::{OutBHandlerCaller, OutBHandlerWrapper};
use crate::mem::custom_drop::CustomPtrDrop;
use crate::mem::mgr::SandboxMemoryManager;
use crate::mem::shared_mem::GuestSharedMemory;
extern "win64" fn call_outb(ptr: *mut Arc<Mutex<dyn OutBHandlerCaller>>, port: u16, data: u64) {
let outb_handlercaller = unsafe { Box::from_raw(ptr) };
let res = outb_handlercaller
.try_lock()
.map_err(|_| crate::new_error!("Error locking"))
.unwrap()
.call(port, data);
assert!(
res.is_ok(),
"ERROR: The guest either panicked or returned an Error. Running inprocess-mode currently does not support error handling. "
);
Box::leak(outb_handlercaller);
}
#[derive(Clone)]
pub(crate) struct LeakedOutBWrapper<'a> {
hdl_ptr: Arc<Mutex<CustomPtrDrop<'a, OutBHandlerWrapper>>>,
}
impl<'a> LeakedOutBWrapper<'a> {
#[instrument(skip_all, parent = Span::current(), level = "Trace")]
pub(crate) fn new(
mgr: &mut SandboxMemoryManager<GuestSharedMemory>,
wrapper: OutBHandlerWrapper,
) -> crate::Result<Self> {
let hdl_box = Box::new(wrapper.clone());
let hdl_ptr = Box::into_raw(hdl_box);
let cd = CustomPtrDrop::new(
hdl_ptr,
Box::new(|ptr| {
let bx = unsafe { Box::from_raw(ptr) };
drop(bx);
}),
);
let res = Self {
hdl_ptr: Arc::new(Mutex::new(cd)),
};
let addr: u64 = res.hdl_wrapper_addr()?;
mgr.set_outb_address_and_context(Self::outb_addr(), addr)?;
Ok(res)
}
#[instrument(err(Debug), skip_all, parent = Span::current(), level = "Trace")]
pub(super) fn hdl_wrapper_addr(&self) -> crate::Result<u64> {
let ptr = self
.hdl_ptr
.try_lock()
.map_err(|_| crate::new_error!("Error locking"))?;
Ok(ptr.as_mut_ptr() as u64)
}
#[instrument(skip_all, parent = Span::current(), level = "Trace")]
pub(super) fn outb_addr() -> u64 {
call_outb as *const c_void as u64
}
}