@@ -68,6 +68,7 @@ use crate::metrics::{METRIC_ERRONEOUS_VCPU_KICKS, METRIC_GUEST_CANCELLATION};
6868use crate :: sandbox:: SandboxConfiguration ;
6969use crate :: sandbox:: host_funcs:: FunctionRegistry ;
7070use crate :: sandbox:: outb:: { HandleOutbError , handle_outb} ;
71+ use crate :: sandbox:: snapshot:: NextAction ;
7172#[ cfg( feature = "mem_profile" ) ]
7273use crate :: sandbox:: trace:: MemTraceInfo ;
7374#[ cfg( crashdump) ]
@@ -85,7 +86,7 @@ pub(crate) struct HyperlightVm {
8586 #[ cfg( not( gdb) ) ]
8687 vm : Box < dyn VirtualMachine > ,
8788 page_size : usize ,
88- entrypoint : Option < u64 > , // only present if this vm has not yet been initialised
89+ entrypoint : NextAction , // only present if this vm has not yet been initialised
8990 rsp_gva : u64 ,
9091 interrupt_handle : Arc < dyn InterruptHandleImpl > ,
9192
@@ -120,6 +121,8 @@ pub enum DispatchGuestCallError {
120121 Run ( #[ from] RunVmError ) ,
121122 #[ error( "Failed to setup registers: {0}" ) ]
122123 SetupRegs ( RegisterError ) ,
124+ #[ error( "VM was uninitialized" ) ]
125+ Uninitialized ,
123126}
124127
125128impl DispatchGuestCallError {
@@ -129,7 +132,7 @@ impl DispatchGuestCallError {
129132 // These errors poison the sandbox because they can leave it in an inconsistent state
130133 // by returning before the guest can unwind properly
131134 DispatchGuestCallError :: Run ( _) => true ,
132- DispatchGuestCallError :: SetupRegs ( _) => false ,
135+ DispatchGuestCallError :: SetupRegs ( _) | DispatchGuestCallError :: Uninitialized => false ,
133136 }
134137 }
135138
@@ -338,7 +341,7 @@ impl HyperlightVm {
338341 snapshot_mem : GuestSharedMemory ,
339342 scratch_mem : GuestSharedMemory ,
340343 _pml4_addr : u64 ,
341- entrypoint : Option < u64 > ,
344+ entrypoint : NextAction ,
342345 rsp_gva : u64 ,
343346 #[ cfg_attr( target_os = "windows" , allow( unused_variables) ) ] config : & SandboxConfiguration ,
344347 #[ cfg( gdb) ] gdb_conn : Option < DebugCommChannel < DebugResponse , DebugMsg > > ,
@@ -438,9 +441,9 @@ impl HyperlightVm {
438441 ret. send_dbg_msg ( DebugResponse :: InterruptHandle ( ret. interrupt_handle . clone ( ) ) ) ?;
439442 // Add breakpoint to the entry point address, if we are going to initialise
440443 ret. vm . set_debug ( true ) . map_err ( VmError :: Debug ) ?;
441- if let Some ( entrypoint ) = entrypoint {
444+ if let NextAction :: Initialise ( initialise ) = entrypoint {
442445 ret. vm
443- . add_hw_breakpoint ( entrypoint )
446+ . add_hw_breakpoint ( initialise )
444447 . map_err ( CreateHyperlightVmError :: AddHwBreakpoint ) ?;
445448 }
446449 }
@@ -462,7 +465,7 @@ impl HyperlightVm {
462465 guest_max_log_level : Option < LevelFilter > ,
463466 #[ cfg( gdb) ] dbg_mem_access_fn : Arc < Mutex < SandboxMemoryManager < HostSharedMemory > > > ,
464467 ) -> std:: result:: Result < ( ) , InitializeError > {
465- let Some ( entrypoint ) = self . entrypoint else {
468+ let NextAction :: Initialise ( initialise ) = self . entrypoint else {
466469 return Ok ( ( ) ) ;
467470 } ;
468471
@@ -474,7 +477,7 @@ impl HyperlightVm {
474477 } ;
475478
476479 let regs = CommonRegisters {
477- rip : entrypoint ,
480+ rip : initialise ,
478481 // We usually keep the top of the stack 16-byte
479482 // aligned. However, the ABI requirement is that the stack
480483 // be aligned _before a call instruction_, which means
@@ -508,6 +511,7 @@ impl HyperlightVm {
508511 return Err ( InitializeError :: InvalidStackPointer ( regs. rsp ) ) ;
509512 }
510513 self . rsp_gva = regs. rsp ;
514+ self . entrypoint = NextAction :: Call ( regs. rax ) ;
511515
512516 Ok ( ( ) )
513517 }
@@ -631,6 +635,16 @@ impl HyperlightVm {
631635 self . rsp_gva = gva;
632636 }
633637
638+ /// Get the current entrypoint action
639+ pub ( crate ) fn get_entrypoint ( & self ) -> NextAction {
640+ self . entrypoint
641+ }
642+
643+ /// Set the current entrypoint action
644+ pub ( crate ) fn set_entrypoint ( & mut self , entrypoint : NextAction ) {
645+ self . entrypoint = entrypoint
646+ }
647+
634648 /// Dispatch a call from the host to the guest using the given pointer
635649 /// to the dispatch function _in the guest's address space_.
636650 ///
@@ -641,14 +655,16 @@ impl HyperlightVm {
641655 #[ instrument( err( Debug ) , skip_all, parent = Span :: current( ) , level = "Trace" ) ]
642656 pub ( crate ) fn dispatch_call_from_host (
643657 & mut self ,
644- dispatch_func_addr : RawPtr ,
645658 mem_mgr : & mut SandboxMemoryManager < HostSharedMemory > ,
646659 host_funcs : & Arc < Mutex < FunctionRegistry > > ,
647660 #[ cfg( gdb) ] dbg_mem_access_fn : Arc < Mutex < SandboxMemoryManager < HostSharedMemory > > > ,
648661 ) -> std:: result:: Result < ( ) , DispatchGuestCallError > {
662+ let NextAction :: Call ( dispatch_func_addr) = self . entrypoint else {
663+ return Err ( DispatchGuestCallError :: Uninitialized ) ;
664+ } ;
649665 // set RIP and RSP, reset others
650666 let regs = CommonRegisters {
651- rip : dispatch_func_addr. into ( ) ,
667+ rip : dispatch_func_addr,
652668 // We usually keep the top of the stack 16-byte
653669 // aligned. However, the ABI requirement is that the stack
654670 // be aligned _before a call instruction_, which means
@@ -755,13 +771,13 @@ impl HyperlightVm {
755771 match exit_reason {
756772 #[ cfg( gdb) ]
757773 Ok ( VmExit :: Debug { dr6, exception } ) => {
774+ let initialise = match self . entrypoint {
775+ NextAction :: Initialise ( initialise) => initialise,
776+ _ => 0 ,
777+ } ;
758778 // Handle debug event (breakpoints)
759- let stop_reason = arch:: vcpu_stop_reason (
760- self . vm . as_mut ( ) ,
761- dr6,
762- self . entrypoint . unwrap_or ( 0 ) ,
763- exception,
764- ) ?;
779+ let stop_reason =
780+ arch:: vcpu_stop_reason ( self . vm . as_mut ( ) , dr6, initialise, exception) ?;
765781 if let Err ( e) = self . handle_debug ( dbg_mem_access_fn. clone ( ) , stop_reason) {
766782 break Err ( e. into ( ) ) ;
767783 }
@@ -1133,14 +1149,19 @@ impl HyperlightVm {
11331149 . and_then ( |name| name. to_os_string ( ) . into_string ( ) . ok ( ) )
11341150 } ) ;
11351151
1152+ let initialise = match self . entrypoint {
1153+ NextAction :: Initialise ( initialise) => initialise,
1154+ _ => 0 ,
1155+ } ;
1156+
11361157 // Include dynamically mapped regions
11371158 // TODO: include the snapshot and scratch regions
11381159 let regions: Vec < MemoryRegion > = self . get_mapped_regions ( ) . cloned ( ) . collect ( ) ;
11391160 Ok ( Some ( crashdump:: CrashDumpContext :: new (
11401161 regions,
11411162 regs,
11421163 xsave. to_vec ( ) ,
1143- self . entrypoint . unwrap_or ( 0 ) ,
1164+ initialise ,
11441165 self . rt_cfg . binary_path . clone ( ) ,
11451166 filename,
11461167 ) ) )
0 commit comments