@@ -959,6 +959,46 @@ impl VcpuFd {
959
959
Ok ( ( ) )
960
960
}
961
961
962
+ /// Returns the guest registers that are supported for the
963
+ /// KVM_GET_ONE_REG/KVM_SET_ONE_REG calls.
964
+ ///
965
+ /// # Arguments
966
+ ///
967
+ /// * `reg_list` - list of registers (input/output). For details check the `kvm_reg_list`
968
+ /// structure in the
969
+ /// [KVM API doc](https://www.kernel.org/doc/Documentation/virtual/kvm/api.txt).
970
+ ///
971
+ /// # Example
972
+ ///
973
+ /// ```rust
974
+ /// # extern crate kvm_ioctls;
975
+ /// # extern crate kvm_bindings;
976
+ /// # use kvm_ioctls::Kvm;
977
+ /// # use kvm_bindings::RegList;
978
+ /// let kvm = Kvm::new().unwrap();
979
+ /// let vm = kvm.create_vm().unwrap();
980
+ /// let vcpu = vm.create_vcpu(0).unwrap();
981
+ ///
982
+ /// // KVM_GET_REG_LIST demands that the vcpus be initalized.
983
+ /// let mut kvi: kvm_bindings::kvm_vcpu_init = kvm_bindings::kvm_vcpu_init::default();
984
+ /// vm.get_preferred_target(&mut kvi).unwrap();
985
+ /// vcpu.vcpu_init(&kvi).expect("Cannot initialize vcpu");
986
+ ///
987
+ /// let mut reg_list = RegList::new(500);
988
+ /// vcpu.get_reg_list(&mut reg_list).unwrap();
989
+ /// assert!(reg_list.as_fam_struct_ref().n > 0);
990
+ /// ```
991
+ ///
992
+ #[ cfg( any( target_arch = "arm" , target_arch = "aarch64" ) ) ]
993
+ pub fn get_reg_list ( & self , reg_list : & mut RegList ) -> Result < ( ) > {
994
+ let ret =
995
+ unsafe { ioctl_with_mut_ref ( self , KVM_GET_REG_LIST ( ) , reg_list. as_mut_fam_struct ( ) ) } ;
996
+ if ret < 0 {
997
+ return Err ( errno:: Error :: last ( ) ) ;
998
+ }
999
+ Ok ( ( ) )
1000
+ }
1001
+
962
1002
/// Sets the value of one register for this vCPU.
963
1003
///
964
1004
/// The id of the register is encoded as specified in the kernel documentation
@@ -1838,6 +1878,35 @@ mod tests {
1838
1878
) ;
1839
1879
}
1840
1880
1881
+ #[ test]
1882
+ #[ cfg( any( target_arch = "arm" , target_arch = "aarch64" ) ) ]
1883
+ fn test_get_reg_list ( ) {
1884
+ let kvm = Kvm :: new ( ) . unwrap ( ) ;
1885
+ let vm = kvm. create_vm ( ) . unwrap ( ) ;
1886
+ let vcpu = vm. create_vcpu ( 0 ) . unwrap ( ) ;
1887
+
1888
+ let mut reg_list = RegList :: new ( 1 ) ;
1889
+ // KVM_GET_REG_LIST demands that the vcpus be initalized, so we expect this to fail.
1890
+ let err = vcpu. get_reg_list ( & mut reg_list) . unwrap_err ( ) ;
1891
+ assert ! ( err. errno( ) == libc:: ENOEXEC ) ;
1892
+
1893
+ let mut kvi: kvm_bindings:: kvm_vcpu_init = kvm_bindings:: kvm_vcpu_init:: default ( ) ;
1894
+ vm. get_preferred_target ( & mut kvi)
1895
+ . expect ( "Cannot get preferred target" ) ;
1896
+ vcpu. vcpu_init ( & kvi) . expect ( "Cannot initialize vcpu" ) ;
1897
+
1898
+ // KVM_GET_REG_LIST offers us a number of registers for which we have
1899
+ // not allocated memory, so the first time it fails.
1900
+ let err = vcpu. get_reg_list ( & mut reg_list) . unwrap_err ( ) ;
1901
+ assert ! ( err. errno( ) == libc:: E2BIG ) ;
1902
+ assert ! ( reg_list. as_mut_fam_struct( ) . n > 0 ) ;
1903
+
1904
+ // We make use of the number of registers returned to allocate memory and
1905
+ // try one more time.
1906
+ let mut reg_list = RegList :: new ( reg_list. as_mut_fam_struct ( ) . n as usize ) ;
1907
+ assert ! ( vcpu. get_reg_list( & mut reg_list) . is_ok( ) ) ;
1908
+ }
1909
+
1841
1910
#[ test]
1842
1911
fn set_kvm_immediate_exit ( ) {
1843
1912
let kvm = Kvm :: new ( ) . unwrap ( ) ;
0 commit comments