@@ -16,6 +16,7 @@ limitations under the License.
1616
1717use  std:: convert:: TryFrom ; 
1818use  std:: fmt:: Debug ; 
19+ use  std:: sync:: OnceLock ; 
1920#[ cfg( gdb) ]  
2021use  std:: sync:: { Arc ,  Mutex } ; 
2122
@@ -42,26 +43,38 @@ use crate::mem::ptr::{GuestPtr, RawPtr};
4243use  crate :: HyperlightError ; 
4344use  crate :: { log_then_return,  new_error,  Result } ; 
4445
45- /// Return `true` if the KVM API is available, version 12, and has UserMemory capability, or `false` otherwise 
46+ /// Static global KVM handle to avoid reopening /dev/kvm for every sandbox 
47+ static  KVM_HANDLE :  OnceLock < Option < Kvm > >  = OnceLock :: new ( ) ; 
48+ 
49+ /// Get the global KVM handle, initializing it if needed 
4650#[ instrument( skip_all,  parent = Span :: current( ) ,  level = "Trace" ) ]  
47- pub ( crate )  fn  is_hypervisor_present ( )  -> bool  { 
48-     if  let  Ok ( kvm)  = Kvm :: new ( )  { 
49-         let  api_version = kvm. get_api_version ( ) ; 
50-         match  api_version { 
51-             version if  version == 12  && kvm. check_extension ( UserMemory )  => true , 
52-             12  => { 
53-                 log:: info!( "KVM does not have KVM_CAP_USER_MEMORY capability" ) ; 
54-                 false 
55-             } 
56-             version => { 
57-                 log:: info!( "KVM GET_API_VERSION returned {}, expected 12" ,  version) ; 
58-                 false 
51+ pub ( crate )  fn  get_kvm_handle ( )  -> & ' static  Option < Kvm >  { 
52+     KVM_HANDLE . get_or_init ( || match  Kvm :: new ( )  { 
53+         Ok ( kvm)  => { 
54+             let  api_version = kvm. get_api_version ( ) ; 
55+             match  api_version { 
56+                 version if  version == 12  && kvm. check_extension ( UserMemory )  => Some ( kvm) , 
57+                 12  => { 
58+                     log:: info!( "KVM does not have KVM_CAP_USER_MEMORY capability" ) ; 
59+                     None 
60+                 } 
61+                 version => { 
62+                     log:: info!( "KVM GET_API_VERSION returned {}, expected 12" ,  version) ; 
63+                     None 
64+                 } 
5965            } 
6066        } 
61-     }  else  { 
62-         log:: info!( "KVM is not available on this system" ) ; 
63-         false 
64-     } 
67+         Err ( e)  => { 
68+             log:: info!( "KVM is not available on this system: {}" ,  e) ; 
69+             None 
70+         } 
71+     } ) 
72+ } 
73+ 
74+ /// Return `true` if the KVM API is available, version 12, and has UserMemory capability, or `false` otherwise 
75+ #[ instrument( skip_all,  parent = Span :: current( ) ,  level = "Trace" ) ]  
76+ pub ( crate )  fn  is_hypervisor_present ( )  -> bool  { 
77+     get_kvm_handle ( ) . is_some ( ) 
6578} 
6679
6780#[ cfg( gdb) ]  
@@ -300,7 +313,10 @@ impl KVMDriver {
300313        rsp :  u64 , 
301314        #[ cfg( gdb) ]   gdb_conn :  Option < DebugCommChannel < DebugResponse ,  DebugMsg > > , 
302315    )  -> Result < Self >  { 
303-         let  kvm = Kvm :: new ( ) ?; 
316+         let  kvm = match  get_kvm_handle ( )  { 
317+             Some ( kvm)  => kvm. clone ( ) , 
318+             None  => return  Err ( new_error ! ( "KVM is not available on this system" ) ) , 
319+         } ; 
304320
305321        let  vm_fd = kvm. create_vm_with_type ( 0 ) ?; 
306322
0 commit comments