mirror of
https://chromium.googlesource.com/crosvm/crosvm
synced 2024-12-25 04:14:06 +00:00
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>
This commit is contained in:
parent
f0656b661c
commit
bb65801679
8 changed files with 109 additions and 10 deletions
10
Cargo.lock
generated
10
Cargo.lock
generated
|
@ -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",
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
[package]
|
||||
name = "crosvm_plugin"
|
||||
version = "0.13.0"
|
||||
version = "0.14.0"
|
||||
authors = ["The Chromium OS Authors"]
|
||||
|
||||
[lib]
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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,
|
||||
|
@ -1382,6 +1385,28 @@ pub unsafe extern "C" fn crosvm_vcpu_set_debugregs(this: *mut crosvm_vcpu,
|
|||
to_crosvm_rc(ret)
|
||||
}
|
||||
|
||||
#[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,
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
[package]
|
||||
name = "plugin_proto"
|
||||
version = "0.13.0"
|
||||
version = "0.14.0"
|
||||
authors = ["The Chromium OS Authors"]
|
||||
build = "build.rs"
|
||||
|
||||
|
|
|
@ -275,6 +275,8 @@ message VcpuRequest {
|
|||
LAPIC = 4;
|
||||
// struct kvm_mp_state
|
||||
MP = 5;
|
||||
// struct kvm_xcrs
|
||||
XCREGS = 6;
|
||||
}
|
||||
|
||||
message GetState {
|
||||
|
|
|
@ -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))?
|
||||
|
|
|
@ -327,6 +327,64 @@ fn test_debugregs() {
|
|||
test_mini_plugin(&mini_plugin);
|
||||
}
|
||||
|
||||
#[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 {
|
||||
|
|
Loading…
Reference in a new issue