summary refs log tree commit diff
diff options
context:
space:
mode:
authorDmitry Torokhov <dtor@chromium.org>2018-05-16 11:03:52 -0700
committerchrome-bot <chrome-bot@chromium.org>2018-05-18 20:08:21 -0700
commitbb6580167937475e2d54e39bbf4babd402202a08 (patch)
treec35bd28c8e9194f5d00fd46763f6b21ecefa21c3
parentf0656b661c97281f56d91e24224334b7e4d6ebc4 (diff)
downloadcrosvm-bb6580167937475e2d54e39bbf4babd402202a08.tar
crosvm-bb6580167937475e2d54e39bbf4babd402202a08.tar.gz
crosvm-bb6580167937475e2d54e39bbf4babd402202a08.tar.bz2
crosvm-bb6580167937475e2d54e39bbf4babd402202a08.tar.lz
crosvm-bb6580167937475e2d54e39bbf4babd402202a08.tar.xz
crosvm-bb6580167937475e2d54e39bbf4babd402202a08.tar.zst
crosvm-bb6580167937475e2d54e39bbf4babd402202a08.zip
plugin: allow retrieving and setting XCR VCPU states
Add crossvm plugin API to allow fetching and setting XCRs for VCPU.

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

Change-Id: I2a988279c08051a8d8865efc1e60f9692fa26272
Signed-off-by: Dmitry Torokhov <dtor@chromium.org>
Reviewed-on: https://chromium-review.googlesource.com/1062646
Commit-Ready: ChromeOS CL Exonerator Bot <chromiumos-cl-exonerator@appspot.gserviceaccount.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.h5
-rw-r--r--crosvm_plugin/src/lib.rs29
-rw-r--r--plugin_proto/Cargo.toml2
-rw-r--r--plugin_proto/protos/plugin.proto2
-rw-r--r--src/plugin/vcpu.rs11
-rw-r--r--tests/plugins.rs58
8 files changed, 109 insertions, 10 deletions
diff --git a/Cargo.lock b/Cargo.lock
index 1422dcf..84b5594 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -48,7 +48,7 @@ dependencies = [
  "aarch64 0.1.0",
  "arch 0.1.0",
  "byteorder 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "crosvm_plugin 0.13.0",
+ "crosvm_plugin 0.14.0",
  "data_model 0.1.0",
  "device_manager 0.1.0",
  "devices 0.1.0",
@@ -60,7 +60,7 @@ dependencies = [
  "kvm_sys 0.1.0",
  "libc 0.2.34 (registry+https://github.com/rust-lang/crates.io-index)",
  "net_util 0.1.0",
- "plugin_proto 0.13.0",
+ "plugin_proto 0.14.0",
  "protobuf 1.4.3 (registry+https://github.com/rust-lang/crates.io-index)",
  "qcow 0.1.0",
  "qcow_utils 0.1.0",
@@ -73,12 +73,12 @@ dependencies = [
 
 [[package]]
 name = "crosvm_plugin"
-version = "0.13.0"
+version = "0.14.0"
 dependencies = [
  "kvm 0.1.0",
  "kvm_sys 0.1.0",
  "libc 0.2.34 (registry+https://github.com/rust-lang/crates.io-index)",
- "plugin_proto 0.13.0",
+ "plugin_proto 0.14.0",
  "protobuf 1.4.3 (registry+https://github.com/rust-lang/crates.io-index)",
  "sys_util 0.1.0",
 ]
@@ -212,7 +212,7 @@ dependencies = [
 
 [[package]]
 name = "plugin_proto"
-version = "0.13.0"
+version = "0.14.0"
 dependencies = [
  "gcc 0.3.54 (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 5b775e3..3c61aa4 100644
--- a/crosvm_plugin/Cargo.toml
+++ b/crosvm_plugin/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "crosvm_plugin"
-version = "0.13.0"
+version = "0.14.0"
 authors = ["The Chromium OS Authors"]
 
 [lib]
diff --git a/crosvm_plugin/crosvm.h b/crosvm_plugin/crosvm.h
index c7589e2..42c979a 100644
--- a/crosvm_plugin/crosvm.h
+++ b/crosvm_plugin/crosvm.h
@@ -495,6 +495,11 @@ int crosvm_vcpu_get_debugregs(struct crosvm_vcpu*, struct kvm_debugregs*);
 /* Sets the state of the vcpu's debug registers */
 int crosvm_vcpu_set_debugregs(struct crosvm_vcpu*, const struct kvm_debugregs*);
 
+/* Gets the state of the vcpu's xcr registers. */
+int crosvm_vcpu_get_xcrs(struct crosvm_vcpu*, struct kvm_xcrs*);
+/* Sets the state of the vcpu's xcr registers. */
+int crosvm_vcpu_set_xcrs(struct crosvm_vcpu*, const struct kvm_xcrs*);
+
 /* Gets the MSRs of the vcpu indicated by the index field of each entry. */
 int crosvm_vcpu_get_msrs(struct crosvm_vcpu*, uint32_t __msr_count,
                          struct kvm_msr_entry *__msr_entries);
diff --git a/crosvm_plugin/src/lib.rs b/crosvm_plugin/src/lib.rs
index 6bd1be8..231ee25 100644
--- a/crosvm_plugin/src/lib.rs
+++ b/crosvm_plugin/src/lib.rs
@@ -44,8 +44,9 @@ use sys_util::Scm;
 
 use kvm::dirty_log_bitmap_size;
 
-use kvm_sys::{kvm_regs, kvm_sregs, kvm_fpu, kvm_debugregs, kvm_msr_entry, kvm_cpuid_entry2,
-              kvm_lapic_state, kvm_mp_state, kvm_pic_state, kvm_ioapic_state, kvm_pit_state2};
+use kvm_sys::{kvm_regs, kvm_sregs, kvm_fpu, kvm_debugregs, kvm_xcrs, kvm_msr_entry,
+              kvm_cpuid_entry2, kvm_lapic_state, kvm_mp_state, kvm_pic_state, kvm_ioapic_state,
+              kvm_pit_state2};
 
 use plugin_proto::*;
 
@@ -162,6 +163,8 @@ enum Stat {
     SetFpu,
     GetDebugRegs,
     SetDebugRegs,
+    GetXCRegs,
+    SetXCRegs,
     VcpuGetMsrs,
     VcpuSetMsrs,
     VcpuSetCpuid,
@@ -1383,6 +1386,28 @@ pub unsafe extern "C" fn crosvm_vcpu_set_debugregs(this: *mut crosvm_vcpu,
 }
 
 #[no_mangle]
+pub unsafe extern "C" fn crosvm_vcpu_get_xcrs(this: *mut crosvm_vcpu,
+                                              xcrs: *mut kvm_xcrs)
+                                              -> c_int {
+    let _u = STATS.record(Stat::GetXCRegs);
+    let this = &mut *this;
+    let xcrs = from_raw_parts_mut(xcrs as *mut u8, size_of::<kvm_xcrs>());
+    let ret = this.get_state(VcpuRequest_StateSet::XCREGS, xcrs);
+    to_crosvm_rc(ret)
+}
+
+#[no_mangle]
+pub unsafe extern "C" fn crosvm_vcpu_set_xcrs(this: *mut crosvm_vcpu,
+                                              xcrs: *const kvm_xcrs)
+                                              -> c_int {
+    let _u = STATS.record(Stat::SetXCRegs);
+    let this = &mut *this;
+    let xcrs = from_raw_parts(xcrs as *mut u8, size_of::<kvm_xcrs>());
+    let ret = this.set_state(VcpuRequest_StateSet::XCREGS, xcrs);
+    to_crosvm_rc(ret)
+}
+
+#[no_mangle]
 pub unsafe extern "C" fn crosvm_vcpu_get_msrs(this: *mut crosvm_vcpu,
                                               msr_count: u32,
                                               msr_entries: *mut kvm_msr_entry)
diff --git a/plugin_proto/Cargo.toml b/plugin_proto/Cargo.toml
index 381a0ea..e410f14 100644
--- a/plugin_proto/Cargo.toml
+++ b/plugin_proto/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "plugin_proto"
-version = "0.13.0"
+version = "0.14.0"
 authors = ["The Chromium OS Authors"]
 build = "build.rs"
 
diff --git a/plugin_proto/protos/plugin.proto b/plugin_proto/protos/plugin.proto
index 58d0b40..399e02a 100644
--- a/plugin_proto/protos/plugin.proto
+++ b/plugin_proto/protos/plugin.proto
@@ -275,6 +275,8 @@ message VcpuRequest {
         LAPIC = 4;
         // struct kvm_mp_state
         MP = 5;
+        // struct kvm_xcrs
+        XCREGS = 6;
     }
 
     message GetState {
diff --git a/src/plugin/vcpu.rs b/src/plugin/vcpu.rs
index 477cf61..4ea6482 100644
--- a/src/plugin/vcpu.rs
+++ b/src/plugin/vcpu.rs
@@ -17,7 +17,7 @@ use protobuf::Message;
 
 use data_model::DataInit;
 use kvm::{Vcpu, CpuId};
-use kvm_sys::{kvm_regs, kvm_sregs, kvm_fpu, kvm_debugregs, kvm_msrs, kvm_msr_entry,
+use kvm_sys::{kvm_regs, kvm_sregs, kvm_fpu, kvm_debugregs, kvm_xcrs, kvm_msrs, kvm_msr_entry,
               KVM_CPUID_FLAG_SIGNIFCANT_INDEX, kvm_lapic_state, kvm_mp_state};
 use plugin_proto::*;
 
@@ -67,6 +67,9 @@ unsafe impl DataInit for VcpuFpu {}
 struct VcpuDebugregs(kvm_debugregs);
 unsafe impl DataInit for VcpuDebugregs {}
 #[derive(Copy, Clone)]
+struct VcpuXcregs(kvm_xcrs);
+unsafe impl DataInit for VcpuXcregs {}
+#[derive(Copy, Clone)]
 struct VcpuLapicState(kvm_lapic_state);
 unsafe impl DataInit for VcpuLapicState {}
 #[derive(Copy, Clone)]
@@ -81,6 +84,7 @@ fn get_vcpu_state(vcpu: &Vcpu, state_set: VcpuRequest_StateSet) -> SysResult<Vec
            VcpuRequest_StateSet::DEBUGREGS => {
                VcpuDebugregs(vcpu.get_debugregs()?).as_slice().to_vec()
            }
+           VcpuRequest_StateSet::XCREGS => VcpuXcregs(vcpu.get_xcrs()?).as_slice().to_vec(),
            VcpuRequest_StateSet::LAPIC => VcpuLapicState(vcpu.get_lapic()?).as_slice().to_vec(),
            VcpuRequest_StateSet::MP => VcpuMpState(vcpu.get_mp_state()?).as_slice().to_vec(),
        })
@@ -108,6 +112,11 @@ fn set_vcpu_state(vcpu: &Vcpu, state_set: VcpuRequest_StateSet, state: &[u8]) ->
                                     .ok_or(SysError::new(EINVAL))?
                                     .0)
         }
+        VcpuRequest_StateSet::XCREGS => {
+            vcpu.set_xcrs(&VcpuXcregs::from_slice(state)
+                              .ok_or(SysError::new(EINVAL))?
+                              .0)
+        }
         VcpuRequest_StateSet::LAPIC => {
             vcpu.set_lapic(&VcpuLapicState::from_slice(state)
                                 .ok_or(SysError::new(EINVAL))?
diff --git a/tests/plugins.rs b/tests/plugins.rs
index cb956bb..b1d8e4d 100644
--- a/tests/plugins.rs
+++ b/tests/plugins.rs
@@ -328,6 +328,64 @@ fn test_debugregs() {
 }
 
 #[test]
+fn test_xcrs() {
+    let mini_plugin = MiniPlugin {
+        assembly_src: "org 0x1000
+             bits 16
+             mov byte [0x3000], 1",
+        src: r#"
+            #define XCR0_VALUE 0x1
+            #define KILL_ADDRESS 0x3000
+
+            int g_kill_evt;
+            struct kvm_xcrs g_xcrs;
+
+            int setup_vm(struct crosvm *crosvm, void *mem) {
+                g_kill_evt = crosvm_get_shutdown_eventfd(crosvm);
+                crosvm_reserve_range(crosvm, CROSVM_ADDRESS_SPACE_MMIO, KILL_ADDRESS, 1);
+                return 0;
+            }
+
+            int handle_vpcu_init(struct crosvm_vcpu *vcpu, struct kvm_regs *regs,
+                                 struct kvm_sregs *sregs)
+            {
+                struct kvm_xcrs xcrs = {};
+                xcrs.nr_xcrs = 1;
+                xcrs.xcrs[0].value = XCR0_VALUE;
+                crosvm_vcpu_set_xcrs(vcpu, &xcrs);
+                return 0;
+            }
+
+            int handle_vpcu_evt(struct crosvm_vcpu *vcpu, struct crosvm_vcpu_event evt) {
+                if (evt.kind == CROSVM_VCPU_EVENT_KIND_IO_ACCESS &&
+                        evt.io_access.address_space == CROSVM_ADDRESS_SPACE_MMIO &&
+                        evt.io_access.address == KILL_ADDRESS &&
+                        evt.io_access.is_write &&
+                        evt.io_access.length == 1 &&
+                        evt.io_access.data[0] == 1)
+                {
+                    uint64_t dummy = 1;
+                    crosvm_vcpu_get_xcrs(vcpu, &g_xcrs);
+                    write(g_kill_evt, &dummy, sizeof(dummy));
+                    return 1;
+                }
+                return 0;
+            }
+
+            int check_result(struct crosvm *vcpu, void *mem) {
+                if (g_xcrs.xcrs[0].value != XCR0_VALUE) {
+                    fprintf(stderr, "xcr0 register has unexpected value: 0x%x\n",
+                            g_xcrs.xcrs[0].value);
+                    return 1;
+                }
+                return 0;
+            }"#,
+        ..Default::default()
+    };
+    test_mini_plugin(&mini_plugin);
+}
+
+#[test]
 fn test_msrs() {
     let mini_plugin = MiniPlugin {
         assembly_src: "org 0x1000