@@ -21,7 +21,7 @@ use std::sync::LazyLock;
2121#[ cfg( gdb) ]
2222use mshv_bindings:: { DebugRegisters , hv_message_type_HVMSG_X64_EXCEPTION_INTERCEPT} ;
2323use mshv_bindings:: {
24- FloatingPointUnit , SpecialRegisters , StandardRegisters , hv_message_type,
24+ FloatingPointUnit , SpecialRegisters , StandardRegisters , XSave , hv_message_type,
2525 hv_message_type_HVMSG_GPA_INTERCEPT, hv_message_type_HVMSG_UNMAPPED_GPA,
2626 hv_message_type_HVMSG_X64_HALT, hv_message_type_HVMSG_X64_IO_PORT_INTERCEPT,
2727 hv_partition_property_code_HV_PARTITION_PROPERTY_SYNTHETIC_PROC_FEATURES,
@@ -33,6 +33,7 @@ use tracing::{Span, instrument};
3333
3434#[ cfg( gdb) ]
3535use crate :: hypervisor:: gdb:: DebuggableVm ;
36+ use crate :: hypervisor:: regs:: { CommonDebugRegs , FP_CONTROL_WORD_DEFAULT , MXCSR_DEFAULT } ;
3637use crate :: hypervisor:: { HyperlightExit , Hypervisor } ;
3738use crate :: mem:: memory_region:: { MemoryRegion , MemoryRegionFlags } ;
3839use crate :: { Result , new_error} ;
@@ -208,11 +209,60 @@ impl Hypervisor for MshvVm {
208209 Ok ( ( ) )
209210 }
210211
211- #[ cfg( crashdump) ]
212+ fn debug_regs ( & self ) -> Result < CommonDebugRegs > {
213+ let debug_regs = self . vcpu_fd . get_debug_regs ( ) ?;
214+ Ok ( debug_regs. into ( ) )
215+ }
216+
217+ fn set_debug_regs ( & self , drs : & CommonDebugRegs ) -> Result < ( ) > {
218+ let mshv_debug_regs = drs. into ( ) ;
219+ self . vcpu_fd . set_debug_regs ( & mshv_debug_regs) ?;
220+ Ok ( ( ) )
221+ }
222+
212223 fn xsave ( & self ) -> Result < Vec < u8 > > {
213224 let xsave = self . vcpu_fd . get_xsave ( ) ?;
214225 Ok ( xsave. buffer . to_vec ( ) )
215226 }
227+
228+ fn reset_xsave ( & self ) -> Result < ( ) > {
229+ let current_xsave = self . vcpu_fd . get_xsave ( ) ?;
230+ if current_xsave. buffer . len ( ) < 576 {
231+ // Minimum: 512 legacy + 64 header
232+ return Err ( new_error ! (
233+ "Unexpected xsave length {}" ,
234+ current_xsave. buffer. len( )
235+ ) ) ;
236+ }
237+
238+ let mut buf = XSave :: default ( ) ; // default is zeroed 4KB buffer
239+
240+ // Copy XCOMP_BV (offset 520-527) - preserves feature mask + compacted bit
241+ buf. buffer [ 520 ..528 ] . copy_from_slice ( & current_xsave. buffer [ 520 ..528 ] ) ;
242+
243+ // XSAVE area layout from Intel SDM Vol. 1 Section 13.4.1:
244+ // - Bytes 0-1: FCW (x87 FPU Control Word)
245+ // - Bytes 24-27: MXCSR
246+ buf. buffer [ 0 ..2 ] . copy_from_slice ( & FP_CONTROL_WORD_DEFAULT . to_le_bytes ( ) ) ;
247+ buf. buffer [ 24 ..28 ] . copy_from_slice ( & MXCSR_DEFAULT . to_le_bytes ( ) ) ;
248+
249+ self . vcpu_fd . set_xsave ( & buf) ?;
250+ Ok ( ( ) )
251+ }
252+
253+ #[ cfg( test) ]
254+ #[ cfg( feature = "init-paging" ) ]
255+ fn set_xsave ( & self , xsave : & [ u32 ; 1024 ] ) -> Result < ( ) > {
256+ let mut buf = XSave :: default ( ) ;
257+ // Safety: all valid u32 values are 4 valid u8 values
258+ let ( prefix, bytes, suffix) = unsafe { xsave. align_to ( ) } ;
259+ if !prefix. is_empty ( ) || !suffix. is_empty ( ) {
260+ return Err ( new_error ! ( "Invalid xsave buffer alignment" ) ) ;
261+ }
262+ buf. buffer . copy_from_slice ( bytes) ;
263+ self . vcpu_fd . set_xsave ( & buf) ?;
264+ Ok ( ( ) )
265+ }
216266}
217267
218268#[ cfg( gdb) ]
0 commit comments