@@ -22,7 +22,34 @@ use hyperlight_common::outb::OutBAction;
2222/// Halt the execution of the guest and returns control to the host.
2323#[ inline( never) ]
2424pub fn halt ( ) {
25- unsafe { asm ! ( "hlt" , options( nostack) ) }
25+ #[ cfg( feature = "trace_guest" ) ]
26+ {
27+ // End any ongoing trace before halting
28+ hyperlight_guest_tracing:: end_trace ( ) ;
29+ // If tracing is enabled, we need to pass the trace batch info
30+ // along with the halt instruction so the host can retrieve it
31+ if let Some ( tbi) = hyperlight_guest_tracing:: guest_trace_info ( ) {
32+ unsafe {
33+ asm ! ( "hlt" ,
34+ in( "r8" ) OutBAction :: TraceBatch as u64 ,
35+ in( "r9" ) tbi. guest_start_tsc,
36+ in( "r10" ) tbi. spans_ptr,
37+ in( "r11" ) tbi. events_ptr,
38+ options( nostack)
39+ )
40+ } ;
41+ hyperlight_guest_tracing:: clean_trace_state ( ) ;
42+ } else {
43+ // If tracing is not enabled, we can directly halt
44+ unsafe { asm ! ( "hlt" , options( nostack) ) } ;
45+ }
46+ }
47+
48+ #[ cfg( not( feature = "trace_guest" ) ) ]
49+ {
50+ // If tracing is not enabled, we can directly halt
51+ unsafe { asm ! ( "hlt" , options( nostack) ) } ;
52+ }
2653}
2754
2855/// Exits the VM with an Abort OUT action and code 0.
@@ -33,6 +60,9 @@ pub extern "C" fn abort() -> ! {
3360
3461/// Exits the VM with an Abort OUT action and a specific code.
3562pub fn abort_with_code ( code : & [ u8 ] ) -> ! {
63+ // End any ongoing trace before aborting
64+ #[ cfg( feature = "trace_guest" ) ]
65+ hyperlight_guest_tracing:: end_trace ( ) ;
3666 outb ( OutBAction :: Abort as u16 , code) ;
3767 outb ( OutBAction :: Abort as u16 , & [ 0xFF ] ) ; // send abort terminator (if not included in code)
3868 unreachable ! ( )
@@ -43,6 +73,9 @@ pub fn abort_with_code(code: &[u8]) -> ! {
4373/// # Safety
4474/// This function is unsafe because it dereferences a raw pointer.
4575pub unsafe fn abort_with_code_and_message ( code : & [ u8 ] , message_ptr : * const c_char ) -> ! {
76+ // End any ongoing trace before aborting
77+ #[ cfg( feature = "trace_guest" ) ]
78+ hyperlight_guest_tracing:: end_trace ( ) ;
4679 unsafe {
4780 // Step 1: Send abort code (typically 1 byte, but `code` allows flexibility)
4881 outb ( OutBAction :: Abort as u16 , code) ;
@@ -89,6 +122,31 @@ pub(crate) fn outb(port: u16, data: &[u8]) {
89122
90123/// OUT function for sending a 32-bit value to the host.
91124pub ( crate ) unsafe fn out32 ( port : u16 , val : u32 ) {
125+ #[ cfg( feature = "trace_guest" ) ]
126+ {
127+ if let Some ( tbi) = hyperlight_guest_tracing:: guest_trace_info ( ) {
128+ // If tracing is enabled, send the trace batch info along with the OUT action
129+ unsafe {
130+ asm ! ( "out dx, eax" ,
131+ in( "dx" ) port,
132+ in( "eax" ) val,
133+ in( "r8" ) OutBAction :: TraceBatch as u64 ,
134+ in( "r9" ) tbi. guest_start_tsc,
135+ in( "r10" ) tbi. spans_ptr,
136+ in( "r11" ) tbi. events_ptr,
137+ options( preserves_flags, nomem, nostack)
138+ )
139+ } ;
140+
141+ hyperlight_guest_tracing:: clean_trace_state ( ) ;
142+ } else {
143+ // If tracing is not enabled, just send the value
144+ unsafe {
145+ asm ! ( "out dx, eax" , in( "dx" ) port, in( "eax" ) val, options( preserves_flags, nomem, nostack) )
146+ } ;
147+ }
148+ }
149+ #[ cfg( not( feature = "trace_guest" ) ) ]
92150 unsafe {
93151 asm ! ( "out dx, eax" , in( "dx" ) port, in( "eax" ) val, options( preserves_flags, nomem, nostack) ) ;
94152 }
0 commit comments