@@ -361,15 +361,6 @@ impl HyperlightVm {
361361 host_funcs : & Arc < Mutex < FunctionRegistry > > ,
362362 #[ cfg( gdb) ] dbg_mem_access_fn : Arc < Mutex < SandboxMemoryManager < HostSharedMemory > > > ,
363363 ) -> Result < ( ) > {
364- // ===== KILL() TIMING POINT 1: Between guest function calls =====
365- // Clear any stale cancellation from a previous guest function call or if kill() was called too early.
366- // This ensures that kill() called BETWEEN different guest function calls doesn't affect the next call.
367- //
368- // If kill() was called and ran to completion BEFORE this line executes:
369- // - kill() has NO effect on this guest function call because CANCEL_BIT is cleared here.
370- // - NOTE: stale signals can still be delivered, but they will be ignored.
371- self . interrupt_handle . clear_cancel ( ) ;
372-
373364 // Keeps the trace context and open spans
374365 #[ cfg( feature = "trace_guest" ) ]
375366 let mut tc = crate :: sandbox:: trace:: TraceContext :: new ( ) ;
@@ -378,9 +369,12 @@ impl HyperlightVm {
378369 // ===== KILL() TIMING POINT 2: Before set_tid() =====
379370 // If kill() is called and ran to completion BEFORE this line executes:
380371 // - CANCEL_BIT will be set and we will return an early VmExit::Cancelled()
372+ // without sending any signals/WHV api calls
381373 #[ cfg( any( kvm, mshv3) ) ]
382374 self . interrupt_handle . set_tid ( ) ;
383375 self . interrupt_handle . set_running ( ) ;
376+ // NOTE: `set_running()`` must be called before checking `is_cancelled()`
377+ // otherwise we risk missing a call to `kill()` because the vcpu would not be marked as running yet so signals won't be sent
384378
385379 let exit_reason = if self . interrupt_handle . is_cancelled ( )
386380 || self . interrupt_handle . is_debug_interrupted ( )
@@ -390,13 +384,10 @@ impl HyperlightVm {
390384 #[ cfg( feature = "trace_guest" ) ]
391385 tc. setup_guest_trace ( Span :: current ( ) . context ( ) ) ;
392386
393- // ===== KILL() TIMING POINT 3: Before calling run_vcpu () = ====
387+ // ==== KILL() TIMING POINT 3: Before calling run () ====
394388 // If kill() is called and ran to completion BEFORE this line executes:
395- // - CANCEL_BIT will be set, but it's too late to prevent entering the guest this iteration
396- // - Signals will interrupt the guest (RUNNING_BIT=true), causing VmExit::Cancelled()
397- // - If the guest completes before any signals arrive, kill() may have no effect
398- // - If there are more iterations to do (IO/host func, etc.), the next iteration will be cancelled
399- let exit_reason = self . vm . run_vcpu ( ) ;
389+ // - Will still do a VM entry, but signals will be sent until VM exits
390+ let result = self . vm . run_vcpu ( ) ;
400391
401392 // End current host trace by closing the current span that captures traces
402393 // happening when a guest exits and re-enters.
@@ -405,12 +396,15 @@ impl HyperlightVm {
405396
406397 // Handle the guest trace data if any
407398 #[ cfg( feature = "trace_guest" ) ]
408- if let Err ( e) = self . handle_trace ( & mut tc, mem_mgr) {
409- // If no trace data is available, we just log a message and continue
410- // Is this the right thing to do?
411- log:: debug!( "Error handling guest trace: {:?}" , e) ;
399+ {
400+ let regs = self . vm . regs ( ) ?;
401+ if let Err ( e) = tc. handle_trace ( & regs, mem_mgr) {
402+ // If no trace data is available, we just log a message and continue
403+ // Is this the right thing to do?
404+ log:: debug!( "Error handling guest trace: {:?}" , e) ;
405+ }
412406 }
413- exit_reason
407+ result
414408 } ;
415409
416410 // ===== KILL() TIMING POINT 4: Before clear_running() =====
@@ -511,9 +505,9 @@ impl HyperlightVm {
511505 continue ;
512506 }
513507
508+ // If the vcpu was interrupted by a debugger, we need to handle it
514509 #[ cfg( gdb) ]
515- if debug_interrupted {
516- // If the vcpu was interrupted by a debugger, we need to handle it
510+ {
517511 self . interrupt_handle . clear_debug_interrupt ( ) ;
518512 if let Err ( e) =
519513 self . handle_debug ( dbg_mem_access_fn. clone ( ) , VcpuStopReason :: Interrupt )
@@ -772,16 +766,6 @@ impl HyperlightVm {
772766 Ok ( None )
773767 }
774768 }
775-
776- #[ cfg( feature = "trace_guest" ) ]
777- fn handle_trace (
778- & mut self ,
779- tc : & mut crate :: sandbox:: trace:: TraceContext ,
780- mem_mgr : & mut SandboxMemoryManager < HostSharedMemory > ,
781- ) -> Result < ( ) > {
782- let regs = self . vm . regs ( ) ?;
783- tc. handle_trace ( & regs, mem_mgr)
784- }
785769}
786770
787771impl Drop for HyperlightVm {
@@ -798,7 +782,8 @@ enum MemoryAccess {
798782 StackGuardPageViolation ,
799783}
800784
801- /// Determines if a memory access violation occurred at the given address with the given action type.
785+ /// Determines if a known memory access violation occurred at the given address with the given action type.
786+ /// Returns Some(reason) if violation reason could be determined, or None if violation occurred but in unmapped region.
802787fn get_memory_access_violation < ' a > (
803788 gpa : usize ,
804789 tried : MemoryRegionFlags ,
0 commit comments