@@ -17,7 +17,7 @@ use kvm_ioctls::*;
1717use vmm_sys_util:: errno;
1818use vmm_sys_util:: ioctl:: { ioctl, ioctl_with_mut_ref, ioctl_with_ref} ;
1919#[ cfg( any( target_arch = "x86" , target_arch = "x86_64" ) ) ]
20- use vmm_sys_util:: ioctl:: { ioctl_with_mut_ptr, ioctl_with_ptr} ;
20+ use vmm_sys_util:: ioctl:: { ioctl_with_mut_ptr, ioctl_with_ptr, ioctl_with_val } ;
2121
2222/// Reasons for vCPU exits.
2323///
@@ -1339,6 +1339,61 @@ impl VcpuFd {
13391339 let kvm_run = self . kvm_run_ptr . as_mut_ref ( ) ;
13401340 kvm_run. immediate_exit = val;
13411341 }
1342+
1343+ /// Returns the vCPU TSC frequency in KHz or an error if the host has unstable TSC.
1344+ ///
1345+ /// # Example
1346+ ///
1347+ /// ```rust
1348+ /// # extern crate kvm_ioctls;
1349+ /// # use kvm_ioctls::Kvm;
1350+ /// let kvm = Kvm::new().unwrap();
1351+ /// let vm = kvm.create_vm().unwrap();
1352+ /// let vcpu = vm.create_vcpu(0).unwrap();
1353+ /// let tsc_khz = vcpu.get_tsc_khz().unwrap();
1354+ /// ```
1355+ ///
1356+ #[ cfg( any( target_arch = "x86" , target_arch = "x86_64" ) ) ]
1357+ pub fn get_tsc_khz ( & self ) -> Result < u32 > {
1358+ // Safe because we know that our file is a KVM fd and that the request is one of the ones
1359+ // defined by kernel.
1360+ let ret = unsafe { ioctl ( self , KVM_GET_TSC_KHZ ( ) ) } ;
1361+ if ret >= 0 {
1362+ Ok ( ret as u32 )
1363+ } else {
1364+ Err ( errno:: Error :: new ( ret) )
1365+ }
1366+ }
1367+
1368+ /// Sets the specified vCPU TSC frequency.
1369+ ///
1370+ /// # Arguments
1371+ ///
1372+ /// * `freq` - The frequency unit is KHz as per the the KVM API documentation
1373+ /// for `KVM_SET_TSC_KHZ`.
1374+ ///
1375+ /// # Example
1376+ ///
1377+ /// ```rust
1378+ /// # extern crate kvm_ioctls;
1379+ /// # use kvm_ioctls::Kvm;
1380+ /// let kvm = Kvm::new().unwrap();
1381+ /// let vm = kvm.create_vm().unwrap();
1382+ /// let vcpu = vm.create_vcpu(0).unwrap();
1383+ /// vcpu.set_tsc_khz(1000).unwrap();
1384+ /// ```
1385+ ///
1386+ #[ cfg( any( target_arch = "x86" , target_arch = "x86_64" ) ) ]
1387+ pub fn set_tsc_khz ( & self , freq : u32 ) -> Result < ( ) > {
1388+ // Safe because we know that our file is a KVM fd and that the request is one of the ones
1389+ // defined by kernel.
1390+ let ret = unsafe { ioctl_with_val ( self , KVM_SET_TSC_KHZ ( ) , freq as u64 ) } ;
1391+ if ret < 0 {
1392+ Err ( errno:: Error :: last ( ) )
1393+ } else {
1394+ Ok ( ( ) )
1395+ }
1396+ }
13421397}
13431398
13441399/// Helper function to create a new `VcpuFd`.
@@ -2043,6 +2098,8 @@ mod tests {
20432098 faulty_vcpu_fd. kvmclock_ctrl( ) . unwrap_err( ) . errno( ) ,
20442099 badf_errno
20452100 ) ;
2101+ assert ! ( faulty_vcpu_fd. get_tsc_khz( ) . is_err( ) ) ;
2102+ assert ! ( faulty_vcpu_fd. set_tsc_khz( 1000000 ) . is_err( ) ) ;
20462103 }
20472104
20482105 #[ test]
@@ -2172,4 +2229,35 @@ mod tests {
21722229 vcpu. enable_cap ( & cap) . unwrap ( ) ;
21732230 }
21742231 }
2232+ #[ cfg( target_arch = "x86_64" ) ]
2233+ #[ test]
2234+ fn test_get_tsc_khz ( ) {
2235+ let kvm = Kvm :: new ( ) . unwrap ( ) ;
2236+ let vm = kvm. create_vm ( ) . unwrap ( ) ;
2237+ let vcpu = vm. create_vcpu ( 0 ) . unwrap ( ) ;
2238+
2239+ if !kvm. check_extension ( Cap :: GetTscKhz ) {
2240+ assert ! ( vcpu. get_tsc_khz( ) . is_err( ) )
2241+ } else {
2242+ assert ! ( vcpu. get_tsc_khz( ) . unwrap( ) > 0 ) ;
2243+ }
2244+ }
2245+
2246+ #[ cfg( target_arch = "x86_64" ) ]
2247+ #[ test]
2248+ fn test_set_tsc_khz ( ) {
2249+ let kvm = Kvm :: new ( ) . unwrap ( ) ;
2250+ let vm = kvm. create_vm ( ) . unwrap ( ) ;
2251+ let vcpu = vm. create_vcpu ( 0 ) . unwrap ( ) ;
2252+ let freq = vcpu. get_tsc_khz ( ) . unwrap ( ) ;
2253+
2254+ if !( kvm. check_extension ( Cap :: GetTscKhz ) && kvm. check_extension ( Cap :: TscControl ) ) {
2255+ assert ! ( vcpu. set_tsc_khz( 0 ) . is_err( ) ) ;
2256+ } else {
2257+ assert ! ( vcpu. set_tsc_khz( freq - 500000 ) . is_ok( ) ) ;
2258+ assert_eq ! ( vcpu. get_tsc_khz( ) . unwrap( ) , freq - 500000 ) ;
2259+ assert ! ( vcpu. set_tsc_khz( freq + 500000 ) . is_ok( ) ) ;
2260+ assert_eq ! ( vcpu. get_tsc_khz( ) . unwrap( ) , freq + 500000 ) ;
2261+ }
2262+ }
21752263}
0 commit comments