@@ -17,7 +17,7 @@ use kvm_ioctls::*;
17
17
use vmm_sys_util:: errno;
18
18
use vmm_sys_util:: ioctl:: { ioctl, ioctl_with_mut_ref, ioctl_with_ref} ;
19
19
#[ 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 } ;
21
21
22
22
/// Reasons for vCPU exits.
23
23
///
@@ -1339,6 +1339,61 @@ impl VcpuFd {
1339
1339
let kvm_run = self . kvm_run_ptr . as_mut_ref ( ) ;
1340
1340
kvm_run. immediate_exit = val;
1341
1341
}
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
+ }
1342
1397
}
1343
1398
1344
1399
/// Helper function to create a new `VcpuFd`.
@@ -2043,6 +2098,8 @@ mod tests {
2043
2098
faulty_vcpu_fd. kvmclock_ctrl( ) . unwrap_err( ) . errno( ) ,
2044
2099
badf_errno
2045
2100
) ;
2101
+ assert ! ( faulty_vcpu_fd. get_tsc_khz( ) . is_err( ) ) ;
2102
+ assert ! ( faulty_vcpu_fd. set_tsc_khz( 1000000 ) . is_err( ) ) ;
2046
2103
}
2047
2104
2048
2105
#[ test]
@@ -2172,4 +2229,35 @@ mod tests {
2172
2229
vcpu. enable_cap ( & cap) . unwrap ( ) ;
2173
2230
}
2174
2231
}
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
+ }
2175
2263
}
0 commit comments