@@ -40,9 +40,9 @@ use crate::hypervisor::gdb::{
4040} ;
4141#[ cfg( gdb) ]
4242use crate :: hypervisor:: gdb:: { DebugError , DebugMemoryAccessError } ;
43- use crate :: hypervisor :: regs :: {
44- CommonDebugRegs , CommonFpu , CommonRegisters , CommonSpecialRegisters ,
45- } ;
43+ # [ cfg ( not ( target_os = "windows" ) ) ]
44+ use crate :: hypervisor :: regs :: CommonDebugRegs ;
45+ use crate :: hypervisor :: regs :: { CommonFpu , CommonRegisters , CommonSpecialRegisters } ;
4646#[ cfg( not( gdb) ) ]
4747use crate :: hypervisor:: virtual_machine:: VirtualMachine ;
4848#[ cfg( kvm) ]
@@ -335,23 +335,37 @@ impl HyperlightVm {
335335 }
336336
337337 /// Resets the following vCPU state:
338- /// - General purpose registers
339- /// - Debug registers
340- /// - XSAVE (includes FPU/SSE state with proper FCW and MXCSR defaults)
341- /// - Special registers (restored from snapshot, with CR3 updated to new page table location)
338+ /// - On Windows: calls WHvResetPartition (resets all per-VP state including
339+ /// GP registers, debug registers, XSAVE, MSRs, APIC, etc.)
340+ /// - On Linux: explicitly resets GP registers, debug registers, and XSAVE
341+ ///
342+ /// This does NOT restore special registers (except on windows). Call `restore_sregs` separately
343+ /// after memory mappings are established.
342344 // TODO: check if other state needs to be reset
343- pub ( crate ) fn reset_vcpu (
345+ pub ( crate ) fn reset_vm_state ( & mut self ) -> std:: result:: Result < ( ) , RegisterError > {
346+ #[ cfg( target_os = "windows" ) ]
347+ self . vm . reset_partition ( ) ?;
348+
349+ #[ cfg( not( target_os = "windows" ) ) ]
350+ {
351+ self . vm . set_regs ( & CommonRegisters {
352+ rflags : 1 << 1 , // Reserved bit always set
353+ ..Default :: default ( )
354+ } ) ?;
355+ self . vm . set_debug_regs ( & CommonDebugRegs :: default ( ) ) ?;
356+ self . vm . reset_xsave ( ) ?;
357+ }
358+
359+ Ok ( ( ) )
360+ }
361+
362+ /// Restores special registers from snapshot with CR3 updated to the
363+ /// new page table location.
364+ pub ( crate ) fn restore_sregs (
344365 & mut self ,
345366 cr3 : u64 ,
346367 sregs : & CommonSpecialRegisters ,
347368 ) -> std:: result:: Result < ( ) , RegisterError > {
348- self . vm . set_regs ( & CommonRegisters {
349- rflags : 1 << 1 , // Reserved bit always set
350- ..Default :: default ( )
351- } ) ?;
352- self . vm . set_debug_regs ( & CommonDebugRegs :: default ( ) ) ?;
353- self . vm . reset_xsave ( ) ?;
354-
355369 #[ cfg( not( feature = "nanvix-unstable" ) ) ]
356370 {
357371 // Restore the full special registers from snapshot, but update CR3
@@ -885,7 +899,9 @@ mod tests {
885899 use super :: * ;
886900 #[ cfg( kvm) ]
887901 use crate :: hypervisor:: regs:: FP_CONTROL_WORD_DEFAULT ;
888- use crate :: hypervisor:: regs:: { CommonSegmentRegister , CommonTableRegister , MXCSR_DEFAULT } ;
902+ use crate :: hypervisor:: regs:: {
903+ CommonDebugRegs , CommonSegmentRegister , CommonTableRegister , MXCSR_DEFAULT ,
904+ } ;
889905 use crate :: hypervisor:: virtual_machine:: VirtualMachine ;
890906 use crate :: mem:: layout:: SandboxMemoryLayout ;
891907 use crate :: mem:: memory_region:: { GuestMemoryRegion , MemoryRegionFlags } ;
@@ -1629,7 +1645,8 @@ mod tests {
16291645 assert_eq ! ( got_sregs, expected_sregs) ;
16301646
16311647 // Reset the vCPU
1632- hyperlight_vm. reset_vcpu ( 0 , & default_sregs ( ) ) . unwrap ( ) ;
1648+ hyperlight_vm. reset_vm_state ( ) . unwrap ( ) ;
1649+ hyperlight_vm. restore_sregs ( 0 , & default_sregs ( ) ) . unwrap ( ) ;
16331650
16341651 // Verify registers are reset to defaults
16351652 assert_regs_reset ( hyperlight_vm. vm . as_ref ( ) ) ;
@@ -1758,7 +1775,8 @@ mod tests {
17581775 assert_eq ! ( regs, expected_dirty) ;
17591776
17601777 // Reset vcpu
1761- hyperlight_vm. reset_vcpu ( 0 , & default_sregs ( ) ) . unwrap ( ) ;
1778+ hyperlight_vm. reset_vm_state ( ) . unwrap ( ) ;
1779+ hyperlight_vm. restore_sregs ( 0 , & default_sregs ( ) ) . unwrap ( ) ;
17621780
17631781 // Check registers are reset to defaults
17641782 assert_regs_reset ( hyperlight_vm. vm . as_ref ( ) ) ;
@@ -1882,7 +1900,8 @@ mod tests {
18821900 }
18831901
18841902 // Reset vcpu
1885- hyperlight_vm. reset_vcpu ( 0 , & default_sregs ( ) ) . unwrap ( ) ;
1903+ hyperlight_vm. reset_vm_state ( ) . unwrap ( ) ;
1904+ hyperlight_vm. restore_sregs ( 0 , & default_sregs ( ) ) . unwrap ( ) ;
18861905
18871906 // Check FPU is reset to defaults
18881907 assert_fpu_reset ( hyperlight_vm. vm . as_ref ( ) ) ;
@@ -1933,7 +1952,8 @@ mod tests {
19331952 assert_eq ! ( debug_regs, expected_dirty) ;
19341953
19351954 // Reset vcpu
1936- hyperlight_vm. reset_vcpu ( 0 , & default_sregs ( ) ) . unwrap ( ) ;
1955+ hyperlight_vm. reset_vm_state ( ) . unwrap ( ) ;
1956+ hyperlight_vm. restore_sregs ( 0 , & default_sregs ( ) ) . unwrap ( ) ;
19371957
19381958 // Check debug registers are reset to default values
19391959 assert_debug_regs_reset ( hyperlight_vm. vm . as_ref ( ) ) ;
@@ -1982,9 +2002,10 @@ mod tests {
19822002 assert_eq ! ( sregs, expected_dirty) ;
19832003
19842004 // Reset vcpu
1985- hyperlight_vm. reset_vcpu ( 0 , & default_sregs ( ) ) . unwrap ( ) ;
2005+ hyperlight_vm. reset_vm_state ( ) . unwrap ( ) ;
2006+ hyperlight_vm. restore_sregs ( 0 , & default_sregs ( ) ) . unwrap ( ) ;
19862007
1987- // Check registers are reset to defaults (CR3 is 0 as passed to reset_vcpu)
2008+ // Check registers are reset to defaults
19882009 let sregs = hyperlight_vm. vm . sregs ( ) . unwrap ( ) ;
19892010 let mut expected_reset = CommonSpecialRegisters :: standard_64bit_defaults ( 0 ) ;
19902011 normalize_sregs_for_run_tests ( & mut expected_reset, & sregs) ;
@@ -2020,7 +2041,11 @@ mod tests {
20202041 let root_pt_addr = ctx. ctx . vm . get_root_pt ( ) . unwrap ( ) ;
20212042 let segment_state = ctx. ctx . vm . get_snapshot_sregs ( ) . unwrap ( ) ;
20222043
2023- ctx. ctx . vm . reset_vcpu ( root_pt_addr, & segment_state) . unwrap ( ) ;
2044+ ctx. ctx . vm . reset_vm_state ( ) . unwrap ( ) ;
2045+ ctx. ctx
2046+ . vm
2047+ . restore_sregs ( root_pt_addr, & segment_state)
2048+ . unwrap ( ) ;
20242049
20252050 // Re-run from entrypoint (flag=1 means guest skips dirty phase, just does FXSAVE)
20262051 // Use stack_top - 8 to match initialise()'s behavior (simulates call pushing return addr)
0 commit comments