@@ -18,30 +18,32 @@ use core::ffi::c_void;
18
18
use std:: fmt;
19
19
use std:: fmt:: { Debug , Formatter } ;
20
20
use std:: string:: String ;
21
+ use std:: sync:: atomic:: { AtomicBool , Ordering } ;
22
+ use std:: sync:: Arc ;
21
23
22
24
use hyperlight_common:: mem:: PAGE_SIZE_USIZE ;
23
25
use log:: LevelFilter ;
24
26
use tracing:: { instrument, Span } ;
25
27
use 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 ,
29
32
} ;
30
33
31
34
use super :: fpu:: { FP_TAG_WORD_DEFAULT , MXCSR_DEFAULT } ;
32
35
#[ cfg( gdb) ]
33
36
use super :: handlers:: DbgMemAccessHandlerWrapper ;
34
37
use super :: handlers:: { MemAccessHandlerWrapper , OutBHandlerWrapper } ;
35
38
use super :: surrogate_process:: SurrogateProcess ;
36
- use super :: surrogate_process_manager:: * ;
37
39
use super :: windows_hypervisor_platform:: { VMPartition , VMProcessor } ;
38
40
use super :: wrappers:: { HandleWrapper , WHvFPURegisters } ;
41
+ use super :: { surrogate_process_manager:: * , InterruptHandle } ;
39
42
use super :: {
40
43
HyperlightExit , Hypervisor , VirtualCPU , CR0_AM , CR0_ET , CR0_MP , CR0_NE , CR0_PE , CR0_PG , CR0_WP ,
41
44
CR4_OSFXSR , CR4_OSXMMEXCPT , CR4_PAE , EFER_LMA , EFER_LME , EFER_NX , EFER_SCE ,
42
45
} ;
43
46
use crate :: hypervisor:: fpu:: FP_CONTROL_WORD_DEFAULT ;
44
- use crate :: hypervisor:: hypervisor_handler:: HypervisorHandler ;
45
47
use crate :: hypervisor:: wrappers:: WHvGeneralRegisters ;
46
48
use crate :: mem:: memory_region:: { MemoryRegion , MemoryRegionFlags } ;
47
49
use crate :: mem:: ptr:: { GuestPtr , RawPtr } ;
@@ -56,6 +58,7 @@ pub(crate) struct HypervWindowsDriver {
56
58
entrypoint : u64 ,
57
59
orig_rsp : GuestPtr ,
58
60
mem_regions : Vec < MemoryRegion > ,
61
+ interrupt_handle : Arc < WindowsInterruptHandle > ,
59
62
}
60
63
/* This does not automatically impl Send/Sync because the host
61
64
* address of the shared memory region is a raw pointer, which are
@@ -90,6 +93,7 @@ impl HypervWindowsDriver {
90
93
91
94
let mut proc = VMProcessor :: new ( partition) ?;
92
95
Self :: setup_initial_sregs ( & mut proc, pml4_address) ?;
96
+ let partition_handle = proc. get_partition_hdl ( ) ;
93
97
94
98
// subtract 2 pages for the guard pages, since when we copy memory to and from surrogate process,
95
99
// we don't want to copy the guard pages themselves (that would cause access violation)
@@ -102,6 +106,11 @@ impl HypervWindowsDriver {
102
106
entrypoint,
103
107
orig_rsp : GuestPtr :: try_from ( RawPtr :: from ( rsp) ) ?,
104
108
mem_regions,
109
+ interrupt_handle : Arc :: new ( WindowsInterruptHandle {
110
+ running : AtomicBool :: new ( false ) ,
111
+ parition_handle : partition_handle,
112
+ dropped : AtomicBool :: new ( false ) ,
113
+ } ) ,
105
114
} )
106
115
}
107
116
@@ -151,11 +160,6 @@ impl HypervWindowsDriver {
151
160
error. push_str ( & format ! ( "Registers: \n {:#?}" , self . processor. get_regs( ) ?) ) ;
152
161
Ok ( error)
153
162
}
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
- }
159
163
}
160
164
161
165
impl Debug for HypervWindowsDriver {
@@ -307,7 +311,6 @@ impl Hypervisor for HypervWindowsDriver {
307
311
page_size : u32 ,
308
312
outb_hdl : OutBHandlerWrapper ,
309
313
mem_access_hdl : MemAccessHandlerWrapper ,
310
- hv_handler : Option < HypervisorHandler > ,
311
314
max_guest_log_level : Option < LevelFilter > ,
312
315
#[ cfg( gdb) ] dbg_mem_access_hdl : DbgMemAccessHandlerWrapper ,
313
316
) -> Result < ( ) > {
@@ -333,7 +336,6 @@ impl Hypervisor for HypervWindowsDriver {
333
336
334
337
VirtualCPU :: run (
335
338
self . as_mut_hypervisor ( ) ,
336
- hv_handler,
337
339
outb_hdl,
338
340
mem_access_hdl,
339
341
#[ cfg( gdb) ]
@@ -349,7 +351,6 @@ impl Hypervisor for HypervWindowsDriver {
349
351
dispatch_func_addr : RawPtr ,
350
352
outb_hdl : OutBHandlerWrapper ,
351
353
mem_access_hdl : MemAccessHandlerWrapper ,
352
- hv_handler : Option < HypervisorHandler > ,
353
354
#[ cfg( gdb) ] dbg_mem_access_hdl : DbgMemAccessHandlerWrapper ,
354
355
) -> Result < ( ) > {
355
356
// Reset general purpose registers, then set RIP and RSP
@@ -371,7 +372,6 @@ impl Hypervisor for HypervWindowsDriver {
371
372
372
373
VirtualCPU :: run (
373
374
self . as_mut_hypervisor ( ) ,
374
- hv_handler,
375
375
outb_hdl,
376
376
mem_access_hdl,
377
377
#[ cfg( gdb) ]
@@ -407,7 +407,11 @@ impl Hypervisor for HypervWindowsDriver {
407
407
408
408
#[ instrument( err( Debug ) , skip_all, parent = Span :: current( ) , level = "Trace" ) ]
409
409
fn run ( & mut self ) -> Result < super :: HyperlightExit > {
410
+ self . interrupt_handle . running . store ( true , Ordering :: Relaxed ) ;
410
411
let exit_context: WHV_RUN_VP_EXIT_CONTEXT = self . processor . run ( ) ?;
412
+ self . interrupt_handle
413
+ . running
414
+ . store ( false , Ordering :: Relaxed ) ;
411
415
412
416
let result = match exit_context. ExitReason {
413
417
// WHvRunVpExitReasonX64IoPortAccess
@@ -481,8 +485,8 @@ impl Hypervisor for HypervWindowsDriver {
481
485
Ok ( result)
482
486
}
483
487
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 ( )
486
490
}
487
491
488
492
#[ instrument( skip_all, parent = Span :: current( ) , level = "Trace" ) ]
@@ -496,28 +500,26 @@ impl Hypervisor for HypervWindowsDriver {
496
500
}
497
501
}
498
502
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
+ }
502
508
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
+ }
504
515
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
+ }
508
521
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 )
522
524
}
523
525
}
0 commit comments