9
9
#[ allow( deref_nullptr) ]
10
10
pub mod bindings;
11
11
12
+ #[ macro_use]
13
+ extern crate log;
14
+
12
15
use bindings:: * ;
13
16
14
17
#[ cfg( target_arch = "aarch64" ) ]
@@ -206,11 +209,39 @@ pub fn vcpu_set_vtimer_mask(vcpuid: u64, masked: bool) -> Result<(), Error> {
206
209
}
207
210
}
208
211
209
- pub struct HvfNestedBindings {
210
- hv_vm_config_get_el2_supported :
211
- libloading:: Symbol < ' static , unsafe extern "C" fn ( * mut bool ) -> hv_return_t > ,
212
- hv_vm_config_set_el2_enabled :
213
- libloading:: Symbol < ' static , unsafe extern "C" fn ( hv_vm_config_t , bool ) -> hv_return_t > ,
212
+ pub fn check_nested_virt ( ) -> Result < bool , Error > {
213
+ // Only M3 and newer chips will support nested virtualization. Query the
214
+ // system to verify if the chip has support.
215
+ let get_el2_supported: libloading:: Symbol <
216
+ ' static ,
217
+ unsafe extern "C" fn ( * mut bool ) -> hv_return_t ,
218
+ > = unsafe {
219
+ HVF . get ( b"hv_vm_config_get_el2_supported" )
220
+ . map_err ( Error :: FindSymbol ) ?
221
+ } ;
222
+ let mut el2_supported: bool = false ;
223
+ let ret = unsafe { ( get_el2_supported) ( & mut el2_supported) } ;
224
+ if ret != HV_SUCCESS {
225
+ error ! ( "processor does not support the nested virtualization functionality" ) ;
226
+ return Err ( Error :: NestedCheck ) ;
227
+ }
228
+
229
+ // nested virtualization requires macOS 15.0+
230
+ match std:: process:: Command :: new ( "sw_vers" )
231
+ . arg ( "--productVersion" )
232
+ . output ( )
233
+ {
234
+ Ok ( cmd_output) => {
235
+ let macos_version: u8 = String :: from_utf8_lossy ( & cmd_output. stdout ) [ ..2 ]
236
+ . parse ( )
237
+ . unwrap ( ) ;
238
+ Ok ( el2_supported && macos_version >= 15 )
239
+ }
240
+ Err ( e) => {
241
+ error ! ( "unable to check macOS version: {:?}" , e) ;
242
+ Err ( Error :: NestedCheck )
243
+ }
244
+ }
214
245
}
215
246
216
247
pub struct HvfVm { }
@@ -225,30 +256,16 @@ static HVF: LazyLock<libloading::Library> = LazyLock::new(|| unsafe {
225
256
impl HvfVm {
226
257
pub fn new ( nested_enabled : bool ) -> Result < Self , Error > {
227
258
let config = unsafe { hv_vm_config_create ( ) } ;
228
-
229
259
if nested_enabled {
230
- let bindings = unsafe {
231
- HvfNestedBindings {
232
- hv_vm_config_get_el2_supported : HVF
233
- . get ( b"hv_vm_config_get_el2_supported" )
234
- . map_err ( Error :: FindSymbol ) ?,
235
- hv_vm_config_set_el2_enabled : HVF
236
- . get ( b"hv_vm_config_set_el2_enabled" )
237
- . map_err ( Error :: FindSymbol ) ?,
238
- }
260
+ let set_el2_enabled: libloading:: Symbol <
261
+ ' static ,
262
+ unsafe extern "C" fn ( hv_vm_config_t , bool ) -> hv_return_t ,
263
+ > = unsafe {
264
+ HVF . get ( b"hv_vm_config_set_el2_enabled" )
265
+ . map_err ( Error :: FindSymbol ) ?
239
266
} ;
240
267
241
- let mut el2_supported: bool = false ;
242
- let ret = unsafe { ( bindings. hv_vm_config_get_el2_supported ) ( & mut el2_supported) } ;
243
- if ret != HV_SUCCESS {
244
- return Err ( Error :: NestedCheck ) ;
245
- }
246
-
247
- if !el2_supported {
248
- return Err ( Error :: NestedCheck ) ;
249
- }
250
-
251
- let ret = unsafe { ( bindings. hv_vm_config_set_el2_enabled ) ( config, true ) } ;
268
+ let ret = unsafe { ( set_el2_enabled) ( config, true ) } ;
252
269
if ret != HV_SUCCESS {
253
270
return Err ( Error :: EnableEL2 ) ;
254
271
}
0 commit comments