@@ -91,6 +91,11 @@ pub(crate) struct HyperlightVm {
9191 trace_info : MemTraceInfo ,
9292 #[ cfg( crashdump) ]
9393 rt_cfg : SandboxRuntimeConfig ,
94+ // Windows does not support just "zeroing" out the xsave area - we need to preserve the XCOMP_BV.
95+ // Since it varies by hardware, we can't just hardcode a value, so we save it here.
96+ // Also note that windows uses compacted format for xsave.
97+ #[ cfg( target_os = "windows" ) ]
98+ xcomp_bv : u64 ,
9499}
95100
96101impl HyperlightVm {
@@ -144,6 +149,8 @@ impl HyperlightVm {
144149 #[ cfg( not( feature = "init-paging" ) ) ]
145150 vm. set_sregs ( & CommonSpecialRegisters :: standard_real_mode_defaults ( ) ) ?;
146151
152+ vm. set_fpu ( & CommonFpu :: default ( ) ) ?;
153+
147154 #[ cfg( gdb) ]
148155 let gdb_conn = if let Some ( gdb_conn) = gdb_conn {
149156 // Add breakpoint to the entry point address
@@ -186,6 +193,17 @@ impl HyperlightVm {
186193 dropped : AtomicBool :: new ( false ) ,
187194 } ) ;
188195
196+ // get xsave header for debugging
197+ #[ cfg( target_os = "windows" ) ]
198+ let xsave = vm. xsave ( ) ?;
199+
200+ #[ cfg( target_os = "windows" ) ]
201+ let xcomp_bv = if xsave. len ( ) >= 528 {
202+ u64:: from_le_bytes ( xsave[ 520 ..528 ] . try_into ( ) . unwrap ( ) )
203+ } else {
204+ return Err ( new_error ! ( "XSAVE buffer too small to contain XCOMP_BV" ) ) ;
205+ } ;
206+
189207 #[ allow( unused_mut) ] // needs to be mutable when gdb is enabled
190208 let mut ret = Self {
191209 vm,
@@ -209,6 +227,8 @@ impl HyperlightVm {
209227 trace_info,
210228 #[ cfg( crashdump) ]
211229 rt_cfg,
230+ #[ cfg( target_os = "windows" ) ]
231+ xcomp_bv,
212232 } ;
213233
214234 // Send the interrupt handle to the GDB thread if debugging is enabled
@@ -580,6 +600,9 @@ impl HyperlightVm {
580600
581601 pub ( crate ) fn reset_vcpu ( & self ) -> Result < ( ) > {
582602 self . vm . set_regs ( & CommonRegisters :: default ( ) ) ?;
603+ self . vm . set_fpu ( & CommonFpu :: default ( ) ) ?;
604+ self . vm . set_debug_regs ( & CommonDebugRegs :: default ( ) ) ?;
605+
583606 #[ cfg( feature = "init-paging" ) ]
584607 self . vm
585608 . set_sregs ( & CommonSpecialRegisters :: standard_64bit_defaults (
@@ -588,9 +611,25 @@ impl HyperlightVm {
588611 #[ cfg( not( feature = "init-paging" ) ) ]
589612 self . vm
590613 . set_sregs ( & CommonSpecialRegisters :: standard_real_mode_defaults ( ) ) ?;
591- self . vm . set_fpu ( & CommonFpu :: default ( ) ) ?;
614+
615+ // Windows does not support just "zeroing" out the xsave area - we need to preserve the XCOMP_BV.
616+ #[ cfg( target_os = "windows" ) ]
617+ {
618+ // The XSAVE header starts at offset 512.
619+ // Bytes 7:0 of the header is XSTATE_BV.
620+ // Bytes 15:8 of the header is XCOMP_BV.
621+ // So XCOMP_BV starts at offset 512 + 8 = 520.
622+ // We are using a u32 array, so the index is 520 / 4 = 130.
623+ const XCOMP_BV_OFFSET_U32 : usize = 520 / std:: mem:: size_of :: < u32 > ( ) ;
624+
625+ let mut xsave = [ 0u32 ; 1024 ] ;
626+ xsave[ XCOMP_BV_OFFSET_U32 ] = self . xcomp_bv as u32 ;
627+ xsave[ XCOMP_BV_OFFSET_U32 + 1 ] = ( self . xcomp_bv >> 32 ) as u32 ;
628+ self . vm . set_xsave ( & xsave) ?;
629+ }
630+ #[ cfg( not( target_os = "windows" ) ) ]
592631 self . vm . set_xsave ( & [ 0 ; 1024 ] ) ?;
593- self . vm . set_debug_regs ( & CommonDebugRegs :: default ( ) ) ? ;
632+
594633 // MSRs don't need to be reset as they cannot be modified by guest (unless unsafely-allowed)
595634 Ok ( ( ) )
596635 }
0 commit comments