@@ -25,6 +25,8 @@ extern crate mshv_bindings3 as mshv_bindings;
2525extern crate mshv_ioctls3 as mshv_ioctls;
2626
2727use std:: fmt:: { Debug , Formatter } ;
28+ use std:: sync:: atomic:: { AtomicBool , AtomicU64 , Ordering } ;
29+ use std:: sync:: Arc ;
2830
2931use log:: { error, LevelFilter } ;
3032#[ cfg( mshv2) ]
@@ -56,8 +58,9 @@ use super::gdb::{DebugCommChannel, DebugMsg, DebugResponse, GuestDebug, MshvDebu
5658use super :: handlers:: DbgMemAccessHandlerWrapper ;
5759use super :: handlers:: { MemAccessHandlerWrapper , OutBHandlerWrapper } ;
5860use super :: {
59- Hypervisor , VirtualCPU , CR0_AM , CR0_ET , CR0_MP , CR0_NE , CR0_PE , CR0_PG , CR0_WP , CR4_OSFXSR ,
60- CR4_OSXMMEXCPT , CR4_PAE , EFER_LMA , EFER_LME , EFER_NX , EFER_SCE ,
61+ Hypervisor , InterruptHandle , LinuxInterruptHandle , VirtualCPU , CR0_AM , CR0_ET , CR0_MP , CR0_NE ,
62+ CR0_PE , CR0_PG , CR0_WP , CR4_OSFXSR , CR4_OSXMMEXCPT , CR4_PAE , EFER_LMA , EFER_LME , EFER_NX ,
63+ EFER_SCE ,
6164} ;
6265use crate :: hypervisor:: HyperlightExit ;
6366use crate :: mem:: memory_region:: { MemoryRegion , MemoryRegionFlags } ;
@@ -292,6 +295,7 @@ pub(crate) struct HypervLinuxDriver {
292295 entrypoint : u64 ,
293296 mem_regions : Vec < MemoryRegion > ,
294297 orig_rsp : GuestPtr ,
298+ interrupt_handle : Arc < LinuxInterruptHandle > ,
295299
296300 #[ cfg( gdb) ]
297301 debug : Option < MshvDebug > ,
@@ -389,6 +393,11 @@ impl HypervLinuxDriver {
389393 mem_regions,
390394 entrypoint : entrypoint_ptr. absolute ( ) ?,
391395 orig_rsp : rsp_ptr,
396+ interrupt_handle : Arc :: new ( LinuxInterruptHandle {
397+ running : AtomicBool :: new ( false ) ,
398+ tid : AtomicU64 :: new ( unsafe { libc:: pthread_self ( ) } ) ,
399+ dropped : AtomicBool :: new ( false ) ,
400+ } ) ,
392401
393402 #[ cfg( gdb) ]
394403 debug,
@@ -572,13 +581,38 @@ impl Hypervisor for HypervLinuxDriver {
572581 #[ cfg( gdb) ]
573582 const EXCEPTION_INTERCEPT : hv_message_type = hv_message_type_HVMSG_X64_EXCEPTION_INTERCEPT;
574583
584+ self . interrupt_handle
585+ . tid
586+ . store ( unsafe { libc:: pthread_self ( ) as u64 } , Ordering :: Relaxed ) ;
587+ // Note: if a `InterruptHandle::kill()` signal is delivered to this thread **here**
588+ // - before we've set the running to true,
589+ // Then the signal does not have any effect, because the signal handler is a no-op.
590+ self . interrupt_handle . running . store ( true , Ordering :: Relaxed ) ;
591+ // Note: if a `InterruptHandle::kill()` signal is delivered to this thread **here**
592+ // - after we've set the running to true,
593+ // - before we've called `VcpuFd::run()`
594+ // Then the individual signal is lost, because the signal is only processed after we've left userspace.
595+ // However, for this reason, we keep sending the signal again and again until we see that the atomic `running` is set to false.
575596 #[ cfg( mshv2) ]
576597 let run_result = {
577598 let hv_message: hv_message = Default :: default ( ) ;
578- & self . vcpu_fd . run ( hv_message)
599+ self . vcpu_fd . run ( hv_message)
579600 } ;
580601 #[ cfg( mshv3) ]
581- let run_result = & self . vcpu_fd . run ( ) ;
602+ let run_result = self . vcpu_fd . run ( ) ;
603+ // Note: if a `InterruptHandle::kill()` signal is delivered to this thread **here**
604+ // - after we've called `VcpuFd::run()`
605+ // - before we've set the running to false
606+ // Then this is fine because the call to `VcpuFd::run()` is already finished,
607+ // the signal handler itself is a no-op, and the signals will stop being sent
608+ // once we've set the `running` to false.
609+ self . interrupt_handle
610+ . running
611+ . store ( false , Ordering :: Relaxed ) ;
612+ // Note: if a `InterruptHandle::kill()` signal is delivered to this thread **here**
613+ // - after we've set the running to true,
614+ // Then the signal does not have any effect, because the signal handler is a no-op.
615+ // This is fine since we are already done with the `VcpuFd::run()` call.
582616
583617 let result = match run_result {
584618 Ok ( m) => match m. header . message_type {
@@ -673,6 +707,10 @@ impl Hypervisor for HypervLinuxDriver {
673707 self as & mut dyn Hypervisor
674708 }
675709
710+ fn interrupt_handle ( & self ) -> Arc < dyn InterruptHandle > {
711+ self . interrupt_handle . clone ( )
712+ }
713+
676714 #[ cfg( crashdump) ]
677715 fn get_memory_regions ( & self ) -> & [ MemoryRegion ] {
678716 & self . mem_regions
@@ -722,10 +760,6 @@ impl Hypervisor for HypervLinuxDriver {
722760
723761 Ok ( ( ) )
724762 }
725-
726- fn interrupt_handle ( & self ) -> std:: sync:: Arc < dyn super :: InterruptHandle > {
727- todo ! ( )
728- }
729763}
730764
731765impl Drop for HypervLinuxDriver {
0 commit comments