summary refs log tree commit diff
path: root/kvm
diff options
context:
space:
mode:
authorDmitry Torokhov <dtor@chromium.org>2019-01-17 12:04:18 -0800
committerchrome-bot <chrome-bot@chromium.org>2019-01-22 21:05:18 -0800
commit5d471b454a04dbb38e8338017b204f1a403aadb9 (patch)
tree7e90183b312c620c3b620a3aeb4b8e2198728387 /kvm
parentb6d842fa56f0ccb9e5084d0e06100c53170d46f7 (diff)
downloadcrosvm-5d471b454a04dbb38e8338017b204f1a403aadb9.tar
crosvm-5d471b454a04dbb38e8338017b204f1a403aadb9.tar.gz
crosvm-5d471b454a04dbb38e8338017b204f1a403aadb9.tar.bz2
crosvm-5d471b454a04dbb38e8338017b204f1a403aadb9.tar.lz
crosvm-5d471b454a04dbb38e8338017b204f1a403aadb9.tar.xz
crosvm-5d471b454a04dbb38e8338017b204f1a403aadb9.tar.zst
crosvm-5d471b454a04dbb38e8338017b204f1a403aadb9.zip
kvm: plumb accessors for KVM_GET_CLOCK/KVM_SET_CLOCK
Plumb in KVM_GET_CLOCK and KVM_SET_CLOCK to allow clients synchronize
timers handled by KVM (LAPIC, PIT) with timers handled by the virtual
device layer.

BUG=b:122878975
TEST=cargo test -p kvm

Change-Id: I2f8867918b82f8ac303e6b60fce2736e38ce2883
Signed-off-by: Dmitry Torokhov <dtor@chromium.org>
Reviewed-on: https://chromium-review.googlesource.com/1419372
Tested-by: kokoro <noreply+kokoro@google.com>
Reviewed-by: Zach Reizner <zachr@chromium.org>
Diffstat (limited to 'kvm')
-rw-r--r--kvm/src/lib.rs42
1 files changed, 42 insertions, 0 deletions
diff --git a/kvm/src/lib.rs b/kvm/src/lib.rs
index beaad55..65c4ee5 100644
--- a/kvm/src/lib.rs
+++ b/kvm/src/lib.rs
@@ -486,6 +486,37 @@ impl Vm {
         }
     }
 
+    /// Retrieves the current timestamp of kvmclock as seen by the current guest.
+    ///
+    /// See the documentation on the KVM_GET_CLOCK ioctl.
+    #[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
+    pub fn get_clock(&self) -> Result<kvm_clock_data> {
+        // Safe because we know that our file is a VM fd, we know the kernel will only write
+        // correct amount of memory to our pointer, and we verify the return result.
+        let mut clock_data = unsafe { std::mem::zeroed() };
+        let ret = unsafe { ioctl_with_mut_ref(self, KVM_GET_CLOCK(), &mut clock_data) };
+        if ret == 0 {
+            Ok(clock_data)
+        } else {
+            errno_result()
+        }
+    }
+
+    /// Sets the current timestamp of kvmclock to the specified value.
+    ///
+    /// See the documentation on the KVM_SET_CLOCK ioctl.
+    #[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
+    pub fn set_clock(&self, clock_data: &kvm_clock_data) -> Result<()> {
+        // Safe because we know that our file is a VM fd, we know the kernel will only read
+        // correct amount of memory from our pointer, and we verify the return result.
+        let ret = unsafe { ioctl_with_ref(self, KVM_SET_CLOCK(), clock_data) };
+        if ret == 0 {
+            Ok(())
+        } else {
+            errno_result()
+        }
+    }
+
     /// Crates an in kernel interrupt controller.
     ///
     /// See the documentation on the KVM_CREATE_IRQCHIP ioctl.
@@ -1675,6 +1706,17 @@ mod tests {
     }
 
     #[test]
+    #[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
+    fn clock_handling() {
+        let kvm = Kvm::new().unwrap();
+        let gm = GuestMemory::new(&vec![(GuestAddress(0), 0x10000)]).unwrap();
+        let vm = Vm::new(&kvm, gm).unwrap();
+        let mut clock_data = vm.get_clock().unwrap();
+        clock_data.clock += 1000;
+        vm.set_clock(&clock_data).unwrap();
+    }
+
+    #[test]
     fn pic_handling() {
         let kvm = Kvm::new().unwrap();
         let gm = GuestMemory::new(&vec![(GuestAddress(0), 0x10000)]).unwrap();