@@ -18,30 +18,32 @@ use core::ffi::c_void;
1818use std:: fmt;
1919use std:: fmt:: { Debug , Formatter } ;
2020use std:: string:: String ;
21+ use std:: sync:: atomic:: { AtomicBool , Ordering } ;
22+ use std:: sync:: Arc ;
2123
2224use hyperlight_common:: mem:: PAGE_SIZE_USIZE ;
2325use log:: LevelFilter ;
2426use tracing:: { instrument, Span } ;
2527use windows:: Win32 :: System :: Hypervisor :: {
26- WHvX64RegisterCr0 , WHvX64RegisterCr3 , WHvX64RegisterCr4 , WHvX64RegisterCs , WHvX64RegisterEfer ,
27- WHV_MEMORY_ACCESS_TYPE , WHV_PARTITION_HANDLE , WHV_REGISTER_VALUE , WHV_RUN_VP_EXIT_CONTEXT ,
28- WHV_RUN_VP_EXIT_REASON , WHV_X64_SEGMENT_REGISTER , WHV_X64_SEGMENT_REGISTER_0 ,
28+ WHvCancelRunVirtualProcessor , WHvX64RegisterCr0 , WHvX64RegisterCr3 , WHvX64RegisterCr4 ,
29+ WHvX64RegisterCs , WHvX64RegisterEfer , WHV_MEMORY_ACCESS_TYPE , WHV_PARTITION_HANDLE ,
30+ WHV_REGISTER_VALUE , WHV_RUN_VP_EXIT_CONTEXT , WHV_RUN_VP_EXIT_REASON , WHV_X64_SEGMENT_REGISTER ,
31+ WHV_X64_SEGMENT_REGISTER_0 ,
2932} ;
3033
3134use super :: fpu:: { FP_TAG_WORD_DEFAULT , MXCSR_DEFAULT } ;
3235#[ cfg( gdb) ]
3336use super :: handlers:: DbgMemAccessHandlerWrapper ;
3437use super :: handlers:: { MemAccessHandlerWrapper , OutBHandlerWrapper } ;
3538use super :: surrogate_process:: SurrogateProcess ;
36- use super :: surrogate_process_manager:: * ;
3739use super :: windows_hypervisor_platform:: { VMPartition , VMProcessor } ;
3840use super :: wrappers:: { HandleWrapper , WHvFPURegisters } ;
41+ use super :: { surrogate_process_manager:: * , InterruptHandle } ;
3942use super :: {
4043 HyperlightExit , Hypervisor , VirtualCPU , CR0_AM , CR0_ET , CR0_MP , CR0_NE , CR0_PE , CR0_PG , CR0_WP ,
4144 CR4_OSFXSR , CR4_OSXMMEXCPT , CR4_PAE , EFER_LMA , EFER_LME , EFER_NX , EFER_SCE ,
4245} ;
4346use crate :: hypervisor:: fpu:: FP_CONTROL_WORD_DEFAULT ;
44- use crate :: hypervisor:: hypervisor_handler:: HypervisorHandler ;
4547use crate :: hypervisor:: wrappers:: WHvGeneralRegisters ;
4648use crate :: mem:: memory_region:: { MemoryRegion , MemoryRegionFlags } ;
4749use crate :: mem:: ptr:: { GuestPtr , RawPtr } ;
@@ -56,6 +58,7 @@ pub(crate) struct HypervWindowsDriver {
5658 entrypoint : u64 ,
5759 orig_rsp : GuestPtr ,
5860 mem_regions : Vec < MemoryRegion > ,
61+ interrupt_handle : Arc < WindowsInterruptHandle > ,
5962}
6063/* This does not automatically impl Send/Sync because the host
6164 * address of the shared memory region is a raw pointer, which are
@@ -90,6 +93,7 @@ impl HypervWindowsDriver {
9093
9194 let mut proc = VMProcessor :: new ( partition) ?;
9295 Self :: setup_initial_sregs ( & mut proc, pml4_address) ?;
96+ let partition_handle = proc. get_partition_hdl ( ) ;
9397
9498 // subtract 2 pages for the guard pages, since when we copy memory to and from surrogate process,
9599 // we don't want to copy the guard pages themselves (that would cause access violation)
@@ -102,6 +106,11 @@ impl HypervWindowsDriver {
102106 entrypoint,
103107 orig_rsp : GuestPtr :: try_from ( RawPtr :: from ( rsp) ) ?,
104108 mem_regions,
109+ interrupt_handle : Arc :: new ( WindowsInterruptHandle {
110+ running : AtomicBool :: new ( false ) ,
111+ parition_handle : partition_handle,
112+ dropped : AtomicBool :: new ( false ) ,
113+ } ) ,
105114 } )
106115 }
107116
@@ -151,11 +160,6 @@ impl HypervWindowsDriver {
151160 error. push_str ( & format ! ( "Registers: \n {:#?}" , self . processor. get_regs( ) ?) ) ;
152161 Ok ( error)
153162 }
154-
155- #[ instrument( skip_all, parent = Span :: current( ) , level = "Trace" ) ]
156- pub ( crate ) fn get_partition_hdl ( & self ) -> WHV_PARTITION_HANDLE {
157- self . processor . get_partition_hdl ( )
158- }
159163}
160164
161165impl Debug for HypervWindowsDriver {
@@ -307,7 +311,6 @@ impl Hypervisor for HypervWindowsDriver {
307311 page_size : u32 ,
308312 outb_hdl : OutBHandlerWrapper ,
309313 mem_access_hdl : MemAccessHandlerWrapper ,
310- hv_handler : Option < HypervisorHandler > ,
311314 max_guest_log_level : Option < LevelFilter > ,
312315 #[ cfg( gdb) ] dbg_mem_access_hdl : DbgMemAccessHandlerWrapper ,
313316 ) -> Result < ( ) > {
@@ -333,7 +336,6 @@ impl Hypervisor for HypervWindowsDriver {
333336
334337 VirtualCPU :: run (
335338 self . as_mut_hypervisor ( ) ,
336- hv_handler,
337339 outb_hdl,
338340 mem_access_hdl,
339341 #[ cfg( gdb) ]
@@ -349,7 +351,6 @@ impl Hypervisor for HypervWindowsDriver {
349351 dispatch_func_addr : RawPtr ,
350352 outb_hdl : OutBHandlerWrapper ,
351353 mem_access_hdl : MemAccessHandlerWrapper ,
352- hv_handler : Option < HypervisorHandler > ,
353354 #[ cfg( gdb) ] dbg_mem_access_hdl : DbgMemAccessHandlerWrapper ,
354355 ) -> Result < ( ) > {
355356 // Reset general purpose registers, then set RIP and RSP
@@ -371,7 +372,6 @@ impl Hypervisor for HypervWindowsDriver {
371372
372373 VirtualCPU :: run (
373374 self . as_mut_hypervisor ( ) ,
374- hv_handler,
375375 outb_hdl,
376376 mem_access_hdl,
377377 #[ cfg( gdb) ]
@@ -407,7 +407,11 @@ impl Hypervisor for HypervWindowsDriver {
407407
408408 #[ instrument( err( Debug ) , skip_all, parent = Span :: current( ) , level = "Trace" ) ]
409409 fn run ( & mut self ) -> Result < super :: HyperlightExit > {
410+ self . interrupt_handle . running . store ( true , Ordering :: Relaxed ) ;
410411 let exit_context: WHV_RUN_VP_EXIT_CONTEXT = self . processor . run ( ) ?;
412+ self . interrupt_handle
413+ . running
414+ . store ( false , Ordering :: Relaxed ) ;
411415
412416 let result = match exit_context. ExitReason {
413417 // WHvRunVpExitReasonX64IoPortAccess
@@ -481,8 +485,8 @@ impl Hypervisor for HypervWindowsDriver {
481485 Ok ( result)
482486 }
483487
484- fn get_partition_handle ( & self ) -> WHV_PARTITION_HANDLE {
485- self . processor . get_partition_hdl ( )
488+ fn interrupt_handle ( & self ) -> Arc < dyn InterruptHandle > {
489+ self . interrupt_handle . clone ( )
486490 }
487491
488492 #[ instrument( skip_all, parent = Span :: current( ) , level = "Trace" ) ]
@@ -496,28 +500,26 @@ impl Hypervisor for HypervWindowsDriver {
496500 }
497501}
498502
499- #[ cfg( test) ]
500- pub mod tests {
501- use std:: sync:: { Arc , Mutex } ;
503+ impl Drop for HypervWindowsDriver {
504+ fn drop ( & mut self ) {
505+ self . interrupt_handle . dropped . store ( true , Ordering :: Relaxed ) ;
506+ }
507+ }
502508
503- use serial_test:: serial;
509+ pub struct WindowsInterruptHandle {
510+ // `WHvCancelRunVirtualProcessor()` will return Ok even if the vcpu is not running, which is the reason we need this flag.
511+ running : AtomicBool ,
512+ parition_handle : WHV_PARTITION_HANDLE ,
513+ dropped : AtomicBool ,
514+ }
504515
505- use crate :: hypervisor:: handlers:: { MemAccessHandler , OutBHandler } ;
506- use crate :: hypervisor:: tests:: test_initialise;
507- use crate :: Result ;
516+ impl InterruptHandle for WindowsInterruptHandle {
517+ fn kill ( & self ) -> bool {
518+ self . running . load ( Ordering :: Relaxed )
519+ && unsafe { WHvCancelRunVirtualProcessor ( self . parition_handle , 0 , 0 ) . is_ok ( ) }
520+ }
508521
509- #[ test]
510- #[ serial]
511- fn test_init ( ) {
512- let outb_handler = {
513- let func: Box < dyn FnMut ( u16 , u32 ) -> Result < ( ) > + Send > =
514- Box :: new ( |_, _| -> Result < ( ) > { Ok ( ( ) ) } ) ;
515- Arc :: new ( Mutex :: new ( OutBHandler :: from ( func) ) )
516- } ;
517- let mem_access_handler = {
518- let func: Box < dyn FnMut ( ) -> Result < ( ) > + Send > = Box :: new ( || -> Result < ( ) > { Ok ( ( ) ) } ) ;
519- Arc :: new ( Mutex :: new ( MemAccessHandler :: from ( func) ) )
520- } ;
521- test_initialise ( outb_handler, mem_access_handler) . unwrap ( ) ;
522+ fn dropped ( & self ) -> bool {
523+ self . dropped . load ( Ordering :: Relaxed )
522524 }
523525}
0 commit comments