diff --git a/src/hyperlight_host/src/hypervisor/handlers.rs b/src/hyperlight_host/src/hypervisor/handlers.rs index 9dbb948af..95f225c40 100644 --- a/src/hyperlight_host/src/hypervisor/handlers.rs +++ b/src/hyperlight_host/src/hypervisor/handlers.rs @@ -18,49 +18,10 @@ use std::sync::{Arc, Mutex}; use tracing::{instrument, Span}; +/// Re-export OutBHandler from the outb module where it naturally belongs +pub(crate) use crate::sandbox::outb::OutBHandler; use crate::{new_error, Result}; -/// The trait representing custom logic to handle the case when -/// a Hypervisor's virtual CPU (vCPU) informs Hyperlight the guest -/// has initiated an outb operation. -pub trait OutBHandlerCaller: Sync + Send { - /// Function that gets called when an outb operation has occurred. - fn call(&mut self, port: u16, payload: u32) -> Result<()>; -} - -/// A convenient type representing a common way `OutBHandler` implementations -/// are passed as parameters to functions -/// -/// Note: This needs to be wrapped in a Mutex to be able to grab a mutable -/// reference to the underlying data (i.e., handle_outb in `Sandbox` takes -/// a &mut self). -pub type OutBHandlerWrapper = Arc>; - -pub(crate) type OutBHandlerFunction = Box Result<()> + Send>; - -/// A `OutBHandler` implementation using a `OutBHandlerFunction` -/// -/// Note: This handler must live no longer than the `Sandbox` to which it belongs -pub(crate) struct OutBHandler(Arc>); - -impl From for OutBHandler { - #[instrument(skip_all, parent = Span::current(), level= "Trace")] - fn from(func: OutBHandlerFunction) -> Self { - Self(Arc::new(Mutex::new(func))) - } -} - -impl OutBHandlerCaller for OutBHandler { - #[instrument(err(Debug), skip_all, parent = Span::current(), level= "Trace")] - fn call(&mut self, port: u16, payload: u32) -> Result<()> { - let mut func = self - .0 - .try_lock() - .map_err(|e| new_error!("Error locking at {}:{}: {}", file!(), line!(), e))?; - func(port, payload) - } -} - /// The trait representing custom logic to handle the case when /// a Hypervisor's virtual CPU (vCPU) informs Hyperlight a memory access /// outside the designated address space has occurred. diff --git a/src/hyperlight_host/src/hypervisor/hyperv_linux.rs b/src/hyperlight_host/src/hypervisor/hyperv_linux.rs index 85dc514b5..dc71aff64 100644 --- a/src/hyperlight_host/src/hypervisor/hyperv_linux.rs +++ b/src/hyperlight_host/src/hypervisor/hyperv_linux.rs @@ -25,6 +25,7 @@ extern crate mshv_bindings3 as mshv_bindings; extern crate mshv_ioctls3 as mshv_ioctls; use std::fmt::{Debug, Formatter}; +use std::sync::{Arc, Mutex}; use log::{error, LevelFilter}; #[cfg(mshv2)] @@ -54,7 +55,7 @@ use super::fpu::{FP_CONTROL_WORD_DEFAULT, FP_TAG_WORD_DEFAULT, MXCSR_DEFAULT}; use super::gdb::{DebugCommChannel, DebugMsg, DebugResponse, GuestDebug, MshvDebug}; #[cfg(gdb)] use super::handlers::DbgMemAccessHandlerWrapper; -use super::handlers::{MemAccessHandlerWrapper, OutBHandlerWrapper}; +use super::handlers::{MemAccessHandlerWrapper, OutBHandler}; use super::{ Hypervisor, VirtualCPU, CR0_AM, CR0_ET, CR0_MP, CR0_NE, CR0_PE, CR0_PG, CR0_WP, CR4_OSFXSR, CR4_OSXMMEXCPT, CR4_PAE, EFER_LMA, EFER_LME, EFER_NX, EFER_SCE, @@ -459,7 +460,7 @@ impl Hypervisor for HypervLinuxDriver { peb_addr: RawPtr, seed: u64, page_size: u32, - outb_hdl: OutBHandlerWrapper, + outb_hdl: Arc>, mem_access_hdl: MemAccessHandlerWrapper, hv_handler: Option, max_guest_log_level: Option, @@ -501,7 +502,7 @@ impl Hypervisor for HypervLinuxDriver { fn dispatch_call_from_host( &mut self, dispatch_func_addr: RawPtr, - outb_handle_fn: OutBHandlerWrapper, + outb_handle_fn: Arc>, mem_access_fn: MemAccessHandlerWrapper, hv_handler: Option, #[cfg(gdb)] dbg_mem_access_fn: DbgMemAccessHandlerWrapper, @@ -544,7 +545,7 @@ impl Hypervisor for HypervLinuxDriver { data: Vec, rip: u64, instruction_length: u64, - outb_handle_fn: OutBHandlerWrapper, + outb_handle_fn: Arc>, ) -> Result<()> { let mut padded = [0u8; 4]; let copy_len = data.len().min(4); diff --git a/src/hyperlight_host/src/hypervisor/hyperv_windows.rs b/src/hyperlight_host/src/hypervisor/hyperv_windows.rs index abc2b77cf..8a28a3f17 100644 --- a/src/hyperlight_host/src/hypervisor/hyperv_windows.rs +++ b/src/hyperlight_host/src/hypervisor/hyperv_windows.rs @@ -18,6 +18,7 @@ use core::ffi::c_void; use std::fmt; use std::fmt::{Debug, Formatter}; use std::string::String; +use std::sync::{Arc, Mutex}; use hyperlight_common::mem::PAGE_SIZE_USIZE; use log::LevelFilter; @@ -31,7 +32,7 @@ use windows::Win32::System::Hypervisor::{ use super::fpu::{FP_TAG_WORD_DEFAULT, MXCSR_DEFAULT}; #[cfg(gdb)] use super::handlers::DbgMemAccessHandlerWrapper; -use super::handlers::{MemAccessHandlerWrapper, OutBHandlerWrapper}; +use super::handlers::{MemAccessHandlerWrapper, OutBHandler}; use super::surrogate_process::SurrogateProcess; use super::surrogate_process_manager::*; use super::windows_hypervisor_platform::{VMPartition, VMProcessor}; @@ -305,7 +306,7 @@ impl Hypervisor for HypervWindowsDriver { peb_address: RawPtr, seed: u64, page_size: u32, - outb_hdl: OutBHandlerWrapper, + outb_hdl: Arc>, mem_access_hdl: MemAccessHandlerWrapper, hv_handler: Option, max_guest_log_level: Option, @@ -347,7 +348,7 @@ impl Hypervisor for HypervWindowsDriver { fn dispatch_call_from_host( &mut self, dispatch_func_addr: RawPtr, - outb_hdl: OutBHandlerWrapper, + outb_hdl: Arc>, mem_access_hdl: MemAccessHandlerWrapper, hv_handler: Option, #[cfg(gdb)] dbg_mem_access_hdl: DbgMemAccessHandlerWrapper, @@ -388,7 +389,7 @@ impl Hypervisor for HypervWindowsDriver { data: Vec, rip: u64, instruction_length: u64, - outb_handle_fn: OutBHandlerWrapper, + outb_handle_fn: Arc>, ) -> Result<()> { let mut padded = [0u8; 4]; let copy_len = data.len().min(4); @@ -500,20 +501,24 @@ impl Hypervisor for HypervWindowsDriver { pub mod tests { use std::sync::{Arc, Mutex}; + use hyperlight_testing::dummy_guest_as_string; use serial_test::serial; use crate::hypervisor::handlers::{MemAccessHandler, OutBHandler}; use crate::hypervisor::tests::test_initialise; + use crate::sandbox::uninitialized::{GuestBinary, UninitializedSandbox}; use crate::Result; #[test] #[serial] fn test_init() { - let outb_handler = { - let func: Box Result<()> + Send> = - Box::new(|_, _| -> Result<()> { Ok(()) }); - Arc::new(Mutex::new(OutBHandler::from(func))) - }; + let filename = dummy_guest_as_string().expect("Guest Binary Missing"); + let sandbox = UninitializedSandbox::new(GuestBinary::FilePath(filename), None).unwrap(); + let (hshm, gshm) = sandbox.mgr.build(); + drop(gshm); + let host_funcs = sandbox.host_funcs.clone(); + + let outb_handler = { crate::sandbox::outb::outb_handler_wrapper(hshm.clone(), host_funcs) }; let mem_access_handler = { let func: Box Result<()> + Send> = Box::new(|| -> Result<()> { Ok(()) }); Arc::new(Mutex::new(MemAccessHandler::from(func))) diff --git a/src/hyperlight_host/src/hypervisor/hypervisor_handler.rs b/src/hyperlight_host/src/hypervisor/hypervisor_handler.rs index 8e351708c..7f318e46d 100644 --- a/src/hyperlight_host/src/hypervisor/hypervisor_handler.rs +++ b/src/hyperlight_host/src/hypervisor/hypervisor_handler.rs @@ -39,7 +39,7 @@ use windows::Win32::System::Hypervisor::{WHvCancelRunVirtualProcessor, WHV_PARTI use super::gdb::create_gdb_thread; #[cfg(gdb)] use crate::hypervisor::handlers::DbgMemAccessHandlerWrapper; -use crate::hypervisor::handlers::{MemAccessHandlerWrapper, OutBHandlerWrapper}; +use crate::hypervisor::handlers::{MemAccessHandlerWrapper, OutBHandler}; #[cfg(target_os = "windows")] use crate::hypervisor::wrappers::HandleWrapper; use crate::hypervisor::Hypervisor; @@ -184,7 +184,7 @@ pub(crate) struct HvHandlerConfig { pub(crate) dispatch_function_addr: Arc>>, pub(crate) max_init_time: Duration, pub(crate) max_exec_time: Duration, - pub(crate) outb_handler: OutBHandlerWrapper, + pub(crate) outb_handler: Arc>, pub(crate) mem_access_handler: MemAccessHandlerWrapper, pub(crate) max_wait_for_cancellation: Duration, pub(crate) max_guest_log_level: Option, diff --git a/src/hyperlight_host/src/hypervisor/kvm.rs b/src/hyperlight_host/src/hypervisor/kvm.rs index 3dd1cb1fc..504ecb21e 100644 --- a/src/hyperlight_host/src/hypervisor/kvm.rs +++ b/src/hyperlight_host/src/hypervisor/kvm.rs @@ -16,7 +16,6 @@ limitations under the License. use std::convert::TryFrom; use std::fmt::Debug; -#[cfg(gdb)] use std::sync::{Arc, Mutex}; use kvm_bindings::{kvm_fpu, kvm_regs, kvm_userspace_memory_region, KVM_MEM_READONLY}; @@ -30,7 +29,7 @@ use super::fpu::{FP_CONTROL_WORD_DEFAULT, FP_TAG_WORD_DEFAULT, MXCSR_DEFAULT}; use super::gdb::{DebugCommChannel, DebugMsg, DebugResponse, GuestDebug, KvmDebug, VcpuStopReason}; #[cfg(gdb)] use super::handlers::DbgMemAccessHandlerWrapper; -use super::handlers::{MemAccessHandlerWrapper, OutBHandlerWrapper}; +use super::handlers::{MemAccessHandlerWrapper, OutBHandler}; use super::{ HyperlightExit, Hypervisor, VirtualCPU, CR0_AM, CR0_ET, CR0_MP, CR0_NE, CR0_PE, CR0_PG, CR0_WP, CR4_OSFXSR, CR4_OSXMMEXCPT, CR4_PAE, EFER_LMA, EFER_LME, EFER_NX, EFER_SCE, @@ -404,7 +403,7 @@ impl Hypervisor for KVMDriver { peb_addr: RawPtr, seed: u64, page_size: u32, - outb_hdl: OutBHandlerWrapper, + outb_hdl: Arc>, mem_access_hdl: MemAccessHandlerWrapper, hv_handler: Option, max_guest_log_level: Option, @@ -445,7 +444,7 @@ impl Hypervisor for KVMDriver { fn dispatch_call_from_host( &mut self, dispatch_func_addr: RawPtr, - outb_handle_fn: OutBHandlerWrapper, + outb_handle_fn: Arc>, mem_access_fn: MemAccessHandlerWrapper, hv_handler: Option, #[cfg(gdb)] dbg_mem_access_fn: DbgMemAccessHandlerWrapper, @@ -487,7 +486,7 @@ impl Hypervisor for KVMDriver { data: Vec, _rip: u64, _instruction_length: u64, - outb_handle_fn: OutBHandlerWrapper, + outb_handle_fn: Arc>, ) -> Result<()> { // KVM does not need RIP or instruction length, as it automatically sets the RIP @@ -638,10 +637,13 @@ impl Hypervisor for KVMDriver { mod tests { use std::sync::{Arc, Mutex}; + use hyperlight_testing::dummy_guest_as_string; + #[cfg(gdb)] use crate::hypervisor::handlers::DbgMemAccessHandlerCaller; use crate::hypervisor::handlers::{MemAccessHandler, OutBHandler}; use crate::hypervisor::tests::test_initialise; + use crate::sandbox::uninitialized::{GuestBinary, UninitializedSandbox}; use crate::Result; #[cfg(gdb)] @@ -668,11 +670,14 @@ mod tests { return; } - let outb_handler: Arc> = { - let func: Box Result<()> + Send> = - Box::new(|_, _| -> Result<()> { Ok(()) }); - Arc::new(Mutex::new(OutBHandler::from(func))) - }; + let filename = dummy_guest_as_string().expect("Guest Binary Missing"); + let sandbox = UninitializedSandbox::new(GuestBinary::FilePath(filename), None).unwrap(); + let (hshm, gshm) = sandbox.mgr.build(); + drop(gshm); + let host_funcs = sandbox.host_funcs.clone(); + + let outb_handler: Arc> = + { crate::sandbox::outb::outb_handler_wrapper(hshm.clone(), host_funcs) }; let mem_access_handler = { let func: Box Result<()> + Send> = Box::new(|| -> Result<()> { Ok(()) }); Arc::new(Mutex::new(MemAccessHandler::from(func))) diff --git a/src/hyperlight_host/src/hypervisor/mod.rs b/src/hyperlight_host/src/hypervisor/mod.rs index 62cebe829..e37969ef9 100644 --- a/src/hyperlight_host/src/hypervisor/mod.rs +++ b/src/hyperlight_host/src/hypervisor/mod.rs @@ -67,9 +67,7 @@ use gdb::VcpuStopReason; #[cfg(gdb)] use self::handlers::{DbgMemAccessHandlerCaller, DbgMemAccessHandlerWrapper}; -use self::handlers::{ - MemAccessHandlerCaller, MemAccessHandlerWrapper, OutBHandlerCaller, OutBHandlerWrapper, -}; +use self::handlers::{MemAccessHandlerCaller, MemAccessHandlerWrapper, OutBHandler}; use crate::hypervisor::hypervisor_handler::HypervisorHandler; use crate::mem::ptr::RawPtr; @@ -124,7 +122,7 @@ pub(crate) trait Hypervisor: Debug + Sync + Send { peb_addr: RawPtr, seed: u64, page_size: u32, - outb_handle_fn: OutBHandlerWrapper, + outb_handle_fn: Arc>, mem_access_fn: MemAccessHandlerWrapper, hv_handler: Option, guest_max_log_level: Option, @@ -141,7 +139,7 @@ pub(crate) trait Hypervisor: Debug + Sync + Send { fn dispatch_call_from_host( &mut self, dispatch_func_addr: RawPtr, - outb_handle_fn: OutBHandlerWrapper, + outb_handle_fn: Arc>, mem_access_fn: MemAccessHandlerWrapper, hv_handler: Option, #[cfg(gdb)] dbg_mem_access_fn: DbgMemAccessHandlerWrapper, @@ -154,7 +152,7 @@ pub(crate) trait Hypervisor: Debug + Sync + Send { data: Vec, rip: u64, instruction_length: u64, - outb_handle_fn: OutBHandlerWrapper, + outb_handle_fn: Arc>, ) -> Result<()>; /// Run the vCPU @@ -254,7 +252,7 @@ impl VirtualCPU { pub fn run( hv: &mut dyn Hypervisor, hv_handler: Option, - outb_handle_fn: Arc>, + outb_handle_fn: Arc>, mem_access_fn: Arc>, #[cfg(gdb)] dbg_mem_access_fn: Arc>, ) -> Result<()> { @@ -341,7 +339,7 @@ pub(crate) mod tests { #[cfg(gdb)] use super::handlers::DbgMemAccessHandlerWrapper; - use super::handlers::{MemAccessHandlerWrapper, OutBHandlerWrapper}; + use super::handlers::{MemAccessHandlerWrapper, OutBHandler}; use crate::hypervisor::hypervisor_handler::{ HvHandlerConfig, HypervisorHandler, HypervisorHandlerAction, }; @@ -351,7 +349,7 @@ pub(crate) mod tests { use crate::{new_error, Result}; pub(crate) fn test_initialise( - outb_hdl: OutBHandlerWrapper, + outb_hdl: Arc>, mem_access_hdl: MemAccessHandlerWrapper, #[cfg(gdb)] dbg_mem_access_fn: DbgMemAccessHandlerWrapper, ) -> Result<()> { diff --git a/src/hyperlight_host/src/sandbox/outb.rs b/src/hyperlight_host/src/sandbox/outb.rs index 4dc91207f..5620e6f06 100644 --- a/src/hyperlight_host/src/sandbox/outb.rs +++ b/src/hyperlight_host/src/sandbox/outb.rs @@ -26,11 +26,43 @@ use tracing_log::format_trace; use super::host_funcs::FunctionRegistry; use super::mem_mgr::MemMgrWrapper; -use crate::hypervisor::handlers::{OutBHandler, OutBHandlerFunction, OutBHandlerWrapper}; use crate::mem::mgr::SandboxMemoryManager; use crate::mem::shared_mem::HostSharedMemory; use crate::{new_error, HyperlightError, Result}; +/// A `OutBHandler` implementation that contains the required data directly +/// +/// Note: This handler must live no longer than the `Sandbox` to which it belongs +pub(crate) struct OutBHandler { + mem_mgr_wrapper: MemMgrWrapper, + host_funcs_wrapper: Arc>, +} + +impl OutBHandler { + /// Create a new OutBHandler with the required dependencies + #[instrument(skip_all, parent = Span::current(), level= "Trace")] + pub fn new( + mem_mgr_wrapper: MemMgrWrapper, + host_funcs_wrapper: Arc>, + ) -> Self { + Self { + mem_mgr_wrapper, + host_funcs_wrapper, + } + } + + /// Function that gets called when an outb operation has occurred. + #[instrument(err(Debug), skip_all, parent = Span::current(), level= "Trace")] + pub fn call(&mut self, port: u16, payload: u32) -> Result<()> { + handle_outb_impl( + &mut self.mem_mgr_wrapper, + self.host_funcs_wrapper.clone(), + port, + payload, + ) + } +} + #[instrument(err(Debug), skip_all, parent = Span::current(), level="Trace")] pub(super) fn outb_log(mgr: &mut SandboxMemoryManager) -> Result<()> { // This code will create either a logging record or a tracing record for the GuestLogData depending on if the host has set up a tracing subscriber. @@ -146,7 +178,7 @@ fn outb_abort(mem_mgr: &mut MemMgrWrapper, data: u32) -> Resul /// Handles OutB operations from the guest. #[instrument(err(Debug), skip_all, parent = Span::current(), level= "Trace")] -fn handle_outb_impl( +pub(crate) fn handle_outb_impl( mem_mgr: &mut MemMgrWrapper, host_funcs: Arc>, port: u16, @@ -184,23 +216,15 @@ fn handle_outb_impl( } /// Given a `MemMgrWrapper` and ` HostFuncsWrapper` -- both passed by _value_ -/// -- return an `OutBHandlerWrapper` wrapping the core OUTB handler logic. +/// -- return an `Arc>` wrapping the core OUTB handler logic. /// /// TODO: pass at least the `host_funcs_wrapper` param by reference. #[instrument(skip_all, parent = Span::current(), level= "Trace")] pub(crate) fn outb_handler_wrapper( - mut mem_mgr_wrapper: MemMgrWrapper, + mem_mgr_wrapper: MemMgrWrapper, host_funcs_wrapper: Arc>, -) -> OutBHandlerWrapper { - let outb_func: OutBHandlerFunction = Box::new(move |port, payload| { - handle_outb_impl( - &mut mem_mgr_wrapper, - host_funcs_wrapper.clone(), - port, - payload, - ) - }); - let outb_hdl = OutBHandler::from(outb_func); +) -> Arc> { + let outb_hdl = OutBHandler::new(mem_mgr_wrapper, host_funcs_wrapper); Arc::new(Mutex::new(outb_hdl)) }