summary refs log tree commit diff
diff options
context:
space:
mode:
authorDmitry Torokhov <dtor@chromium.org>2019-01-17 16:20:33 -0800
committerchrome-bot <chrome-bot@chromium.org>2019-01-22 21:05:18 -0800
commit2c7e88199ea4f7e8a9486c1c76ecaeababad4d49 (patch)
tree814f2b2a341f34917b5492a7832771fd883a2575
parent5d471b454a04dbb38e8338017b204f1a403aadb9 (diff)
downloadcrosvm-2c7e88199ea4f7e8a9486c1c76ecaeababad4d49.tar
crosvm-2c7e88199ea4f7e8a9486c1c76ecaeababad4d49.tar.gz
crosvm-2c7e88199ea4f7e8a9486c1c76ecaeababad4d49.tar.bz2
crosvm-2c7e88199ea4f7e8a9486c1c76ecaeababad4d49.tar.lz
crosvm-2c7e88199ea4f7e8a9486c1c76ecaeababad4d49.tar.xz
crosvm-2c7e88199ea4f7e8a9486c1c76ecaeababad4d49.tar.zst
crosvm-2c7e88199ea4f7e8a9486c1c76ecaeababad4d49.zip
plugin: allow retrieving and setting VM clock
Add crossvm plugin API to allow reading and setting guest clock.

BUG=b:122878975
TEST=cargo test -p kvm; cargo test --features=plugin

Change-Id: I3fd656c06b0e7e43ac88a337ac5d0caec8c59dba
Signed-off-by: Dmitry Torokhov <dtor@chromium.org>
Reviewed-on: https://chromium-review.googlesource.com/1419373
Tested-by: kokoro <noreply+kokoro@google.com>
Reviewed-by: Zach Reizner <zachr@chromium.org>
-rw-r--r--Cargo.lock10
-rw-r--r--crosvm_plugin/Cargo.toml2
-rw-r--r--crosvm_plugin/crosvm.h9
-rw-r--r--crosvm_plugin/src/lib.rs31
-rw-r--r--plugin_proto/Cargo.toml2
-rw-r--r--plugin_proto/protos/plugin.proto2
-rw-r--r--src/plugin/process.rs11
-rw-r--r--tests/plugin_vm_state.c28
8 files changed, 84 insertions, 11 deletions
diff --git a/Cargo.lock b/Cargo.lock
index d43e449..86ba831 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -73,7 +73,7 @@ dependencies = [
  "arch 0.1.0",
  "bit_field 0.1.0",
  "byteorder 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "crosvm_plugin 0.16.0",
+ "crosvm_plugin 0.17.0",
  "data_model 0.1.0",
  "devices 0.1.0",
  "gpu_buffer 0.1.0",
@@ -86,7 +86,7 @@ dependencies = [
  "msg_socket 0.1.0",
  "net_util 0.1.0",
  "p9 0.1.0",
- "plugin_proto 0.16.0",
+ "plugin_proto 0.17.0",
  "protobuf 1.4.3 (registry+https://github.com/rust-lang/crates.io-index)",
  "qcow 0.1.0",
  "rand_ish 0.1.0",
@@ -101,12 +101,12 @@ dependencies = [
 
 [[package]]
 name = "crosvm_plugin"
-version = "0.16.0"
+version = "0.17.0"
 dependencies = [
  "kvm 0.1.0",
  "kvm_sys 0.1.0",
  "libc 0.2.44 (registry+https://github.com/rust-lang/crates.io-index)",
- "plugin_proto 0.16.0",
+ "plugin_proto 0.17.0",
  "protobuf 1.4.3 (registry+https://github.com/rust-lang/crates.io-index)",
  "sys_util 0.1.0",
 ]
@@ -281,7 +281,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
 name = "plugin_proto"
-version = "0.16.0"
+version = "0.17.0"
 dependencies = [
  "cc 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)",
  "kvm_sys 0.1.0",
diff --git a/crosvm_plugin/Cargo.toml b/crosvm_plugin/Cargo.toml
index 9406912..2233b6d 100644
--- a/crosvm_plugin/Cargo.toml
+++ b/crosvm_plugin/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "crosvm_plugin"
-version = "0.16.0"
+version = "0.17.0"
 authors = ["The Chromium OS Authors"]
 
 [lib]
diff --git a/crosvm_plugin/crosvm.h b/crosvm_plugin/crosvm.h
index 3f58739..81c8ade 100644
--- a/crosvm_plugin/crosvm.h
+++ b/crosvm_plugin/crosvm.h
@@ -47,7 +47,7 @@ extern "C" {
  * do not indicate anything about what version of crosvm is running.
  */
 #define CROSVM_API_MAJOR 0
-#define CROSVM_API_MINOR 16
+#define CROSVM_API_MINOR 17
 #define CROSVM_API_PATCH 0
 
 enum crosvm_address_space {
@@ -252,6 +252,13 @@ int crosvm_get_pit_state(struct crosvm *, struct kvm_pit_state2 *__pit_state);
 int crosvm_set_pit_state(struct crosvm *,
                          const struct kvm_pit_state2 *__pit_state);
 
+/* Gets the current timestamp of kvmclock as seen by the VM. */
+int crosvm_get_clock(struct crosvm *, struct kvm_clock_data *__clock_data);
+
+/* Sets the current timestamp of kvmclock for the VM. */
+int crosvm_set_clock(struct crosvm *,
+                     const struct kvm_clock_data *__clock_data);
+
 /* Sets the identity map address as in the KVM_SET_IDENTITY_MAP_ADDR ioctl. */
 int crosvm_set_identity_map_addr(struct crosvm*, uint32_t __addr);
 
diff --git a/crosvm_plugin/src/lib.rs b/crosvm_plugin/src/lib.rs
index 8fd9623..ac6b358 100644
--- a/crosvm_plugin/src/lib.rs
+++ b/crosvm_plugin/src/lib.rs
@@ -45,8 +45,9 @@ use sys_util::ScmSocket;
 use kvm::dirty_log_bitmap_size;
 
 use kvm_sys::{
-    kvm_cpuid_entry2, kvm_debugregs, kvm_fpu, kvm_ioapic_state, kvm_lapic_state, kvm_mp_state,
-    kvm_msr_entry, kvm_pic_state, kvm_pit_state2, kvm_regs, kvm_sregs, kvm_vcpu_events, kvm_xcrs,
+    kvm_clock_data, kvm_cpuid_entry2, kvm_debugregs, kvm_fpu, kvm_ioapic_state, kvm_lapic_state,
+    kvm_mp_state, kvm_msr_entry, kvm_pic_state, kvm_pit_state2, kvm_regs, kvm_sregs,
+    kvm_vcpu_events, kvm_xcrs,
 };
 
 use plugin_proto::*;
@@ -151,6 +152,8 @@ enum Stat {
     SetIoapicState,
     GetPitState,
     SetPitState,
+    GetClock,
+    SetClock,
     SetIdentityMapAddr,
     PauseVcpus,
     Start,
@@ -1356,6 +1359,30 @@ pub unsafe extern "C" fn crosvm_set_pit_state(
 }
 
 #[no_mangle]
+pub unsafe extern "C" fn crosvm_get_clock(
+    this: *mut crosvm,
+    clock_data: *mut kvm_clock_data,
+) -> c_int {
+    let _u = STATS.record(Stat::GetClock);
+    let this = &mut *this;
+    let state = from_raw_parts_mut(clock_data as *mut u8, size_of::<kvm_clock_data>());
+    let ret = this.get_state(MainRequest_StateSet::CLOCK, state);
+    to_crosvm_rc(ret)
+}
+
+#[no_mangle]
+pub unsafe extern "C" fn crosvm_set_clock(
+    this: *mut crosvm,
+    clock_data: *const kvm_clock_data,
+) -> c_int {
+    let _u = STATS.record(Stat::SetClock);
+    let this = &mut *this;
+    let state = from_raw_parts(clock_data as *mut u8, size_of::<kvm_clock_data>());
+    let ret = this.set_state(MainRequest_StateSet::CLOCK, state);
+    to_crosvm_rc(ret)
+}
+
+#[no_mangle]
 pub unsafe extern "C" fn crosvm_set_identity_map_addr(self_: *mut crosvm, addr: u32) -> c_int {
     let _u = STATS.record(Stat::SetIdentityMapAddr);
     let self_ = &mut (*self_);
diff --git a/plugin_proto/Cargo.toml b/plugin_proto/Cargo.toml
index 5f1c771..bd06b3d 100644
--- a/plugin_proto/Cargo.toml
+++ b/plugin_proto/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "plugin_proto"
-version = "0.16.0"
+version = "0.17.0"
 authors = ["The Chromium OS Authors"]
 build = "build.rs"
 
diff --git a/plugin_proto/protos/plugin.proto b/plugin_proto/protos/plugin.proto
index 005c314..5b6eec2 100644
--- a/plugin_proto/protos/plugin.proto
+++ b/plugin_proto/protos/plugin.proto
@@ -124,6 +124,8 @@ message MainRequest {
         IOAPIC = 2;
         // struct kvm_pit_state2
         PIT = 3;
+        // struct kvm_clock_data
+        CLOCK = 4;
     }
 
     message GetState {
diff --git a/src/plugin/process.rs b/src/plugin/process.rs
index 826b8d3..f3045fa 100644
--- a/src/plugin/process.rs
+++ b/src/plugin/process.rs
@@ -24,7 +24,7 @@ use protobuf::Message;
 
 use io_jail::Minijail;
 use kvm::{dirty_log_bitmap_size, Datamatch, IoeventAddress, IrqRoute, IrqSource, PicId, Vm};
-use kvm_sys::{kvm_ioapic_state, kvm_pic_state, kvm_pit_state2};
+use kvm_sys::{kvm_clock_data, kvm_ioapic_state, kvm_pic_state, kvm_pit_state2};
 use plugin_proto::*;
 use sync::Mutex;
 use sys_util::{
@@ -45,6 +45,9 @@ unsafe impl DataInit for VmIoapicState {}
 #[derive(Copy, Clone)]
 struct VmPitState(kvm_pit_state2);
 unsafe impl DataInit for VmPitState {}
+#[derive(Copy, Clone)]
+struct VmClockState(kvm_clock_data);
+unsafe impl DataInit for VmClockState {}
 
 fn get_vm_state(vm: &Vm, state_set: MainRequest_StateSet) -> SysResult<Vec<u8>> {
     Ok(match state_set {
@@ -56,6 +59,7 @@ fn get_vm_state(vm: &Vm, state_set: MainRequest_StateSet) -> SysResult<Vec<u8>>
             .to_vec(),
         MainRequest_StateSet::IOAPIC => VmIoapicState(vm.get_ioapic_state()?).as_slice().to_vec(),
         MainRequest_StateSet::PIT => VmPitState(vm.get_pit_state()?).as_slice().to_vec(),
+        MainRequest_StateSet::CLOCK => VmClockState(vm.get_clock()?).as_slice().to_vec(),
     })
 }
 
@@ -83,6 +87,11 @@ fn set_vm_state(vm: &Vm, state_set: MainRequest_StateSet, state: &[u8]) -> SysRe
                 .ok_or(SysError::new(EINVAL))?
                 .0,
         ),
+        MainRequest_StateSet::CLOCK => vm.set_clock(
+            &VmClockState::from_slice(state)
+                .ok_or(SysError::new(EINVAL))?
+                .0,
+        ),
     }
 }
 
diff --git a/tests/plugin_vm_state.c b/tests/plugin_vm_state.c
index 6026e29..450d324 100644
--- a/tests/plugin_vm_state.c
+++ b/tests/plugin_vm_state.c
@@ -115,5 +115,33 @@ int main(int argc, char** argv) {
         return 1;
     }
 
+    // Test retrieving and setting clock state.
+    struct kvm_clock_data clock_data = { .clock = 0, .flags = -1U, };
+    ret = crosvm_get_clock(crosvm, &clock_data);
+    if (ret < 0) {
+        fprintf(stderr, "failed to get initial clock state: %d\n", ret);
+        return 1;
+    }
+
+    if (clock_data.clock == 0 || clock_data.flags != 0) {
+        fprintf(stderr, "invalid clock data returned (%llu, %u)\n",
+                clock_data.clock, clock_data.flags);
+    }
+
+    clock_data.clock += 10000000;
+
+    ret = crosvm_set_clock(crosvm, &clock_data);
+    if (ret < 0) {
+        fprintf(stderr, "failed to update clock: %d\n", ret);
+        return 1;
+    }
+
+    clock_data.flags = -1U;
+    ret = crosvm_set_clock(crosvm, &clock_data);
+    if (ret >= 0) {
+        fprintf(stderr, "unexpected success updating clock\n");
+        return 1;
+    }
+
     return 0;
 }