mirror of
https://chromium.googlesource.com/crosvm/crosvm
synced 2025-01-27 02:28:22 +00:00
plugin: allow retrieving and setting VCPU events
Add crosvm plugin API to allow fetching and setting VCPU events. BUG=b:110056268 TEST=cargo test --features plugin -p kvm Change-Id: Id66230f180f4bdb95bd1850ed050e439083701cc Reviewed-on: https://chromium-review.googlesource.com/1128045 Commit-Ready: Slava Malyugin <slavamn@chromium.org> Tested-by: Slava Malyugin <slavamn@chromium.org> Reviewed-by: Zach Reizner <zachr@chromium.org>
This commit is contained in:
parent
cc08cdbd83
commit
d1e391b8d4
9 changed files with 110 additions and 14 deletions
10
Cargo.lock
generated
10
Cargo.lock
generated
|
@ -53,7 +53,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.14.0",
|
||||
"crosvm_plugin 0.15.0",
|
||||
"data_model 0.1.0",
|
||||
"devices 0.1.0",
|
||||
"gpu_buffer 0.1.0",
|
||||
|
@ -66,7 +66,7 @@ dependencies = [
|
|||
"libc 0.2.40 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"net_util 0.1.0",
|
||||
"p9 0.1.0",
|
||||
"plugin_proto 0.14.0",
|
||||
"plugin_proto 0.15.0",
|
||||
"protobuf 1.4.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"qcow 0.1.0",
|
||||
"qcow_utils 0.1.0",
|
||||
|
@ -80,12 +80,12 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "crosvm_plugin"
|
||||
version = "0.14.0"
|
||||
version = "0.15.0"
|
||||
dependencies = [
|
||||
"kvm 0.1.0",
|
||||
"kvm_sys 0.1.0",
|
||||
"libc 0.2.40 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"plugin_proto 0.14.0",
|
||||
"plugin_proto 0.15.0",
|
||||
"protobuf 1.4.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"sys_util 0.1.0",
|
||||
]
|
||||
|
@ -221,7 +221,7 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "plugin_proto"
|
||||
version = "0.14.0"
|
||||
version = "0.15.0"
|
||||
dependencies = [
|
||||
"cc 1.0.15 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"kvm_sys 0.1.0",
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
[package]
|
||||
name = "crosvm_plugin"
|
||||
version = "0.14.0"
|
||||
version = "0.15.0"
|
||||
authors = ["The Chromium OS Authors"]
|
||||
|
||||
[lib]
|
||||
|
|
|
@ -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 13
|
||||
#define CROSVM_API_MINOR 15
|
||||
#define CROSVM_API_PATCH 0
|
||||
|
||||
enum crosvm_address_space {
|
||||
|
@ -525,6 +525,14 @@ int crosvm_vcpu_get_mp_state(struct crosvm_vcpu *,
|
|||
int crosvm_vcpu_set_mp_state(struct crosvm_vcpu *,
|
||||
const struct kvm_mp_state *__mp_state);
|
||||
|
||||
/* Gets currently pending exceptions, interrupts, NMIs, etc for VCPU. */
|
||||
int crosvm_vcpu_get_vcpu_events(struct crosvm_vcpu *,
|
||||
struct kvm_vcpu_events *);
|
||||
|
||||
/* Sets currently pending exceptions, interrupts, NMIs, etc for VCPU. */
|
||||
int crosvm_vcpu_set_vcpu_events(struct crosvm_vcpu *,
|
||||
const struct kvm_vcpu_events *);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -46,7 +46,7 @@ use kvm::dirty_log_bitmap_size;
|
|||
|
||||
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};
|
||||
kvm_pit_state2, kvm_vcpu_events};
|
||||
|
||||
use plugin_proto::*;
|
||||
|
||||
|
@ -172,6 +172,8 @@ enum Stat {
|
|||
VcpuSetLapicState,
|
||||
VcpuGetMpState,
|
||||
VcpuSetMpState,
|
||||
VcpuGetVcpuEvents,
|
||||
VcpuSetVcpuEvents,
|
||||
NewConnection,
|
||||
|
||||
Count,
|
||||
|
@ -1487,3 +1489,27 @@ pub unsafe extern "C" fn crosvm_vcpu_set_mp_state(this: *mut crosvm_vcpu,
|
|||
let ret = this.set_state(VcpuRequest_StateSet::MP, state);
|
||||
to_crosvm_rc(ret)
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn crosvm_vcpu_get_vcpu_events(this: *mut crosvm_vcpu,
|
||||
events: *mut kvm_vcpu_events)
|
||||
-> c_int {
|
||||
let _u = STATS.record(Stat::VcpuGetVcpuEvents);
|
||||
let this = &mut *this;
|
||||
let events = from_raw_parts_mut(events as *mut u8,
|
||||
size_of::<kvm_vcpu_events>());
|
||||
let ret = this.get_state(VcpuRequest_StateSet::EVENTS, events);
|
||||
to_crosvm_rc(ret)
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn crosvm_vcpu_set_vcpu_events(this: *mut crosvm_vcpu,
|
||||
events: *const kvm_vcpu_events)
|
||||
-> c_int {
|
||||
let _u = STATS.record(Stat::VcpuSetVcpuEvents);
|
||||
let this = &mut *this;
|
||||
let events = from_raw_parts(events as *mut u8,
|
||||
size_of::<kvm_vcpu_events>());
|
||||
let ret = this.set_state(VcpuRequest_StateSet::EVENTS, events);
|
||||
to_crosvm_rc(ret)
|
||||
}
|
||||
|
|
|
@ -1169,6 +1169,41 @@ impl Vcpu {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
/// Gets the vcpu's currently pending exceptions, interrupts, NMIs, etc
|
||||
///
|
||||
/// See the documentation for KVM_GET_VCPU_EVENTS.
|
||||
///
|
||||
#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
|
||||
pub fn get_vcpu_events(&self) -> Result<kvm_vcpu_events> {
|
||||
// Safe because we know that our file is a VCPU fd, we know the kernel
|
||||
// will only write correct amount of memory to our pointer, and we
|
||||
// verify the return result.
|
||||
let mut events: kvm_vcpu_events = unsafe { std::mem::zeroed() };
|
||||
let ret = unsafe { ioctl_with_mut_ref(self, KVM_GET_VCPU_EVENTS(),
|
||||
&mut events) };
|
||||
if ret < 0 {
|
||||
return errno_result();
|
||||
}
|
||||
Ok(events)
|
||||
}
|
||||
|
||||
/// Sets the vcpu's currently pending exceptions, interrupts, NMIs, etc
|
||||
///
|
||||
/// See the documentation for KVM_SET_VCPU_EVENTS.
|
||||
///
|
||||
#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
|
||||
pub fn set_vcpu_events(&self, events: &kvm_vcpu_events) -> Result<()> {
|
||||
let ret = unsafe {
|
||||
// The ioctl is safe because the kernel will only read from the
|
||||
// kvm_vcpu_events.
|
||||
ioctl_with_ref(self, KVM_SET_VCPU_EVENTS(), events)
|
||||
};
|
||||
if ret < 0 {
|
||||
return errno_result();
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Specifies set of signals that are blocked during execution of KVM_RUN.
|
||||
/// Signals that are not blocked will will cause KVM_RUN to return
|
||||
/// with -EINTR.
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
[package]
|
||||
name = "plugin_proto"
|
||||
version = "0.14.0"
|
||||
version = "0.15.0"
|
||||
authors = ["The Chromium OS Authors"]
|
||||
build = "build.rs"
|
||||
|
||||
|
|
|
@ -277,6 +277,8 @@ message VcpuRequest {
|
|||
MP = 5;
|
||||
// struct kvm_xcrs
|
||||
XCREGS = 6;
|
||||
// struct kvm_vcpu_events
|
||||
EVENTS = 7;
|
||||
}
|
||||
|
||||
message GetState {
|
||||
|
@ -285,7 +287,9 @@ message VcpuRequest {
|
|||
|
||||
message SetState {
|
||||
StateSet set = 1;
|
||||
// The in memory representation of a struct kvm_regs, struct kvm_sregs, or struct kvm_fpu,
|
||||
// The in memory representation of a struct kvm_regs, struct kvm_sregs,
|
||||
// struct kvm_fpu, struct kvm_debugregs, struct kvm_lapic_state,
|
||||
// struct kvm_mp_state, struct kvm_xcrs or struct kvm_vcpu_events
|
||||
// depending on the value of the StateSet.
|
||||
bytes state = 2;
|
||||
}
|
||||
|
@ -355,9 +359,10 @@ message VcpuResponse {
|
|||
message Resume {}
|
||||
|
||||
message GetState {
|
||||
// The in memory representation of a struct kvm_regs, struct kvm_sregs, struct kvm_fpu,
|
||||
// struct kvm_lapic_state, or struct kvm_mp_state, depending on what StateSet was
|
||||
// requested in GetState.
|
||||
// The in memory representation of a struct kvm_regs, struct kvm_sregs,
|
||||
// struct kvm_fpu, struct kvm_debugregs, struct kvm_lapic_state,
|
||||
// struct kvm_mp_state, struct kvm_xcrs or struct kvm_vcpu_events
|
||||
// depending on the value of the StateSet.
|
||||
bytes state = 1;
|
||||
}
|
||||
|
||||
|
|
|
@ -18,7 +18,7 @@ use protobuf::Message;
|
|||
use data_model::DataInit;
|
||||
use kvm::{Vcpu, CpuId};
|
||||
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};
|
||||
KVM_CPUID_FLAG_SIGNIFCANT_INDEX, kvm_lapic_state, kvm_mp_state, kvm_vcpu_events};
|
||||
use plugin_proto::*;
|
||||
|
||||
use super::*;
|
||||
|
@ -75,6 +75,9 @@ unsafe impl DataInit for VcpuLapicState {}
|
|||
#[derive(Copy, Clone)]
|
||||
struct VcpuMpState(kvm_mp_state);
|
||||
unsafe impl DataInit for VcpuMpState {}
|
||||
#[derive(Copy, Clone)]
|
||||
struct VcpuEvents(kvm_vcpu_events);
|
||||
unsafe impl DataInit for VcpuEvents {}
|
||||
|
||||
fn get_vcpu_state(vcpu: &Vcpu, state_set: VcpuRequest_StateSet) -> SysResult<Vec<u8>> {
|
||||
Ok(match state_set {
|
||||
|
@ -87,6 +90,7 @@ fn get_vcpu_state(vcpu: &Vcpu, state_set: VcpuRequest_StateSet) -> SysResult<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(),
|
||||
VcpuRequest_StateSet::EVENTS => VcpuEvents(vcpu.get_vcpu_events()?).as_slice().to_vec(),
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -127,6 +131,11 @@ fn set_vcpu_state(vcpu: &Vcpu, state_set: VcpuRequest_StateSet, state: &[u8]) ->
|
|||
.ok_or(SysError::new(EINVAL))?
|
||||
.0)
|
||||
}
|
||||
VcpuRequest_StateSet::EVENTS => {
|
||||
vcpu.set_vcpu_events(&VcpuEvents::from_slice(state)
|
||||
.ok_or(SysError::new(EINVAL))?
|
||||
.0)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -644,6 +644,19 @@ fn test_vcpu_state_manipulation() {
|
|||
return 1;
|
||||
}
|
||||
|
||||
struct kvm_vcpu_events events;
|
||||
ret = crosvm_vcpu_get_vcpu_events(vcpu, &events);
|
||||
if (ret < 0) {
|
||||
fprintf(stderr, "failed to get VCPU events: %d\n", ret);
|
||||
return 1;
|
||||
}
|
||||
|
||||
ret = crosvm_vcpu_set_vcpu_events(vcpu, &events);
|
||||
if (ret < 0) {
|
||||
fprintf(stderr, "failed to set VCPU events: %d\n", ret);
|
||||
return 1;
|
||||
}
|
||||
|
||||
success = true;
|
||||
return 0;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue