@@ -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