diff options
author | Dmitry Torokhov <dtor@chromium.org> | 2018-05-16 11:03:52 -0700 |
---|---|---|
committer | chrome-bot <chrome-bot@chromium.org> | 2018-05-18 20:08:21 -0700 |
commit | bb6580167937475e2d54e39bbf4babd402202a08 (patch) | |
tree | c35bd28c8e9194f5d00fd46763f6b21ecefa21c3 | |
parent | f0656b661c97281f56d91e24224334b7e4d6ebc4 (diff) | |
download | crosvm-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.lock | 10 | ||||
-rw-r--r-- | crosvm_plugin/Cargo.toml | 2 | ||||
-rw-r--r-- | crosvm_plugin/crosvm.h | 5 | ||||
-rw-r--r-- | crosvm_plugin/src/lib.rs | 29 | ||||
-rw-r--r-- | plugin_proto/Cargo.toml | 2 | ||||
-rw-r--r-- | plugin_proto/protos/plugin.proto | 2 | ||||
-rw-r--r-- | src/plugin/vcpu.rs | 11 | ||||
-rw-r--r-- | tests/plugins.rs | 58 |
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 |