@@ -17,7 +17,7 @@ use crate::kvm_ioctls::*;
17
17
#[ cfg( any( target_arch = "aarch64" ) ) ]
18
18
use kvm_bindings:: KVM_VM_TYPE_ARM_IPA_SIZE_MASK ;
19
19
#[ cfg( any( target_arch = "x86" , target_arch = "x86_64" ) ) ]
20
- use kvm_bindings:: { CpuId , MsrList , KVM_MAX_CPUID_ENTRIES , KVM_MAX_MSR_ENTRIES } ;
20
+ use kvm_bindings:: { CpuId , MsrList , Msrs , KVM_MAX_CPUID_ENTRIES , KVM_MAX_MSR_ENTRIES } ;
21
21
use vmm_sys_util:: errno;
22
22
#[ cfg( any( target_arch = "x86" , target_arch = "x86_64" ) ) ]
23
23
use vmm_sys_util:: ioctl:: ioctl_with_mut_ptr;
@@ -425,7 +425,7 @@ impl Kvm {
425
425
426
426
// SAFETY: The kernel is trusted not to write beyond the bounds of the memory
427
427
// allocated for the struct. The limit is read from nmsrs, which is set to the allocated
428
- // size (MAX_KVM_MSR_ENTRIES ) above.
428
+ // size (KVM_MAX_MSR_ENTRIES ) above.
429
429
let ret = unsafe {
430
430
ioctl_with_mut_ptr (
431
431
self ,
@@ -441,6 +441,83 @@ impl Kvm {
441
441
Ok ( msr_list)
442
442
}
443
443
444
+ /// X86 specific call to get a list of MSRs that can be passed to the KVM_GET_MSRS system ioctl.
445
+ ///
446
+ /// See the documentation for `KVM_GET_MSR_FEATURE_INDEX_LIST`.
447
+ ///
448
+ /// # Example
449
+ ///
450
+ /// ```
451
+ /// use kvm_bindings::{kvm_msr_entry, Msrs};
452
+ /// use kvm_ioctls::Kvm;
453
+ ///
454
+ /// let kvm = Kvm::new().unwrap();
455
+ /// let msr_feature_index_list = kvm.get_msr_feature_index_list().unwrap();
456
+ /// ```
457
+ #[ cfg( any( target_arch = "x86" , target_arch = "x86_64" ) ) ]
458
+ pub fn get_msr_feature_index_list ( & self ) -> Result < MsrList > {
459
+ let mut msr_list =
460
+ MsrList :: new ( KVM_MAX_MSR_ENTRIES ) . map_err ( |_| errno:: Error :: new ( libc:: ENOMEM ) ) ?;
461
+
462
+ // SAFETY: The kernel is trusted not to write beyond the bounds of the memory
463
+ // allocated for the struct. The limit is read from nmsrs, which is set to the allocated
464
+ // size (KVM_MAX_MSR_ENTRIES) above.
465
+ let ret = unsafe {
466
+ ioctl_with_mut_ptr (
467
+ self ,
468
+ KVM_GET_MSR_FEATURE_INDEX_LIST ( ) ,
469
+ msr_list. as_mut_fam_struct_ptr ( ) ,
470
+ )
471
+ } ;
472
+ if ret < 0 {
473
+ return Err ( errno:: Error :: last ( ) ) ;
474
+ }
475
+
476
+ Ok ( msr_list)
477
+ }
478
+
479
+ /// X86 specific call to read the values of MSR-based features that are available for the VM.
480
+ /// As opposed to `VcpuFd::get_msrs()`, this call returns all the MSRs supported by the
481
+ /// system, similar to `get_supported_cpuid()` for CPUID.
482
+ ///
483
+ /// See the documentation for `KVM_GET_MSRS`.
484
+ ///
485
+ /// # Arguments
486
+ ///
487
+ /// * `msrs` - MSRs (input/output). For details check the `kvm_msrs` structure in the
488
+ /// [KVM API doc](https://www.kernel.org/doc/Documentation/virtual/kvm/api.txt).
489
+ ///
490
+ /// # Example
491
+ ///
492
+ /// ```
493
+ /// use kvm_bindings::{kvm_msr_entry, Msrs};
494
+ /// use kvm_ioctls::Kvm;
495
+ ///
496
+ /// let kvm = Kvm::new().unwrap();
497
+ /// let msr_feature_index_list = kvm.get_msr_feature_index_list().unwrap();
498
+ /// let mut msrs = Msrs::from_entries(
499
+ /// &msr_feature_index_list
500
+ /// .as_slice()
501
+ /// .iter()
502
+ /// .map(|&idx| kvm_msr_entry {
503
+ /// index: idx,
504
+ /// ..Default::default()
505
+ /// })
506
+ /// .collect::<Vec<_>>(),
507
+ /// )
508
+ /// .unwrap();
509
+ /// let ret = kvm.get_msrs(&mut msrs).unwrap();
510
+ /// ```
511
+ #[ cfg( any( target_arch = "x86" , target_arch = "x86_64" ) ) ]
512
+ pub fn get_msrs ( & self , msrs : & mut Msrs ) -> Result < usize > {
513
+ // SAFETY: Here we trust the kernel not to read past the end of the kvm_msrs struct.
514
+ let ret = unsafe { ioctl_with_mut_ptr ( self , KVM_GET_MSRS ( ) , msrs. as_mut_fam_struct_ptr ( ) ) } ;
515
+ if ret < 0 {
516
+ return Err ( errno:: Error :: last ( ) ) ;
517
+ }
518
+ Ok ( ret as usize )
519
+ }
520
+
444
521
/// Creates a VM fd using the KVM fd.
445
522
///
446
523
/// See the documentation for `KVM_CREATE_VM`.
@@ -812,6 +889,36 @@ mod tests {
812
889
assert ! ( msr_list. as_slice( ) . len( ) >= 2 ) ;
813
890
}
814
891
892
+ #[ test]
893
+ #[ cfg( any( target_arch = "x86" , target_arch = "x86_64" ) ) ]
894
+ fn get_msr_feature_index_list ( ) {
895
+ let kvm = Kvm :: new ( ) . unwrap ( ) ;
896
+ let msr_feature_index_list = kvm. get_msr_feature_index_list ( ) . unwrap ( ) ;
897
+ assert ! ( !msr_feature_index_list. as_slice( ) . is_empty( ) ) ;
898
+ }
899
+
900
+ #[ test]
901
+ #[ cfg( any( target_arch = "x86" , target_arch = "x86_64" ) ) ]
902
+ fn get_msrs ( ) {
903
+ use kvm_bindings:: kvm_msr_entry;
904
+
905
+ let kvm = Kvm :: new ( ) . unwrap ( ) ;
906
+ let mut msrs = Msrs :: from_entries ( & [
907
+ kvm_msr_entry {
908
+ index : 0x0000010a , // MSR_IA32_ARCH_CAPABILITIES
909
+ ..Default :: default ( )
910
+ } ,
911
+ kvm_msr_entry {
912
+ index : 0x00000345 , // MSR_IA32_PERF_CAPABILITIES
913
+ ..Default :: default ( )
914
+ } ,
915
+ ] )
916
+ . unwrap ( ) ;
917
+ let nmsrs = kvm. get_msrs ( & mut msrs) . unwrap ( ) ;
918
+
919
+ assert_eq ! ( nmsrs, 2 ) ;
920
+ }
921
+
815
922
#[ test]
816
923
fn test_bad_kvm_fd ( ) {
817
924
let badf_errno = libc:: EBADF ;
0 commit comments