From 3e40b51a62b08dc27dcaa7fbec630e047713aba1 Mon Sep 17 00:00:00 2001 From: Dmitry Torokhov Date: Mon, 26 Mar 2018 17:14:19 -0700 Subject: plugin: allow retrieving and setting VM and VCPU states This change allows plugin to retrieve and set various VM and VCPU states: interrupt controller, PIT, LAPIC and MP state. BUG=b:76083711 TEST=cargo test -p kvm Change-Id: Ie32a67b0cd4a1f0a19ccd826a6e1c9dc25670f95 Signed-off-by: Dmitry Torokhov Reviewed-on: https://chromium-review.googlesource.com/986511 Reviewed-by: Zach Reizner --- crosvm_plugin/Cargo.toml | 2 +- crosvm_plugin/crosvm.h | 39 +++++++++++++- crosvm_plugin/src/lib.rs | 138 ++++++++++++++++++++++++++++++++++++++++++++++- 3 files changed, 176 insertions(+), 3 deletions(-) (limited to 'crosvm_plugin') diff --git a/crosvm_plugin/Cargo.toml b/crosvm_plugin/Cargo.toml index 42516ad..5b775e3 100644 --- a/crosvm_plugin/Cargo.toml +++ b/crosvm_plugin/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "crosvm_plugin" -version = "0.12.0" +version = "0.13.0" authors = ["The Chromium OS Authors"] [lib] diff --git a/crosvm_plugin/crosvm.h b/crosvm_plugin/crosvm.h index 30b32c1..c7589e2 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 12 +#define CROSVM_API_MINOR 13 #define CROSVM_API_PATCH 0 enum crosvm_address_space { @@ -222,6 +222,29 @@ static_assert(sizeof(struct crosvm_irq_route) == 24, int crosvm_set_irq_routing(struct crosvm*, uint32_t __route_count, const struct crosvm_irq_route* __routes); +/* Gets the state of interrupt controller in a VM. */ +int crosvm_get_pic_state(struct crosvm *, bool __primary, + struct kvm_pic_state *__pic_state); + +/* Sets the state of interrupt controller in a VM. */ +int crosvm_set_pic_state(struct crosvm *, bool __primary, + struct kvm_pic_state *__pic_state); + +/* Gets the state of IOAPIC in a VM. */ +int crosvm_get_ioapic_state(struct crosvm *, + struct kvm_ioapic_state *__ioapic_state); + +/* Sets the state of IOAPIC in a VM. */ +int crosvm_set_ioapic_state(struct crosvm *, + struct kvm_ioapic_state *__ioapic_state); + +/* Gets the state of interrupt controller in a VM. */ +int crosvm_get_pit_state(struct crosvm *, struct kvm_pit_state2 *__pit_state); + +/* Sets the state of interrupt controller in a VM. */ +int crosvm_set_pit_state(struct crosvm *, + const struct kvm_pit_state2 *__pit_state); + /* 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); @@ -483,6 +506,20 @@ int crosvm_vcpu_set_msrs(struct crosvm_vcpu*, uint32_t __msr_count, int crosvm_vcpu_set_cpuid(struct crosvm_vcpu*, uint32_t __cpuid_count, const struct kvm_cpuid_entry2 *__cpuid_entries); +/* Gets state of LAPIC of the VCPU. */ +int crosvm_vcpu_get_lapic_state(struct crosvm_vcpu *, + struct kvm_lapic_state *__lapic_state); +/* Sets state of LAPIC of the VCPU. */ +int crosvm_vcpu_set_lapic_state(struct crosvm_vcpu *, + const struct kvm_lapic_state *__lapic_state); + +/* Gets the "multiprocessor state" of given VCPU. */ +int crosvm_vcpu_get_mp_state(struct crosvm_vcpu *, + struct kvm_mp_state *__mp_state); +/* Sets the "multiprocessor state" of given VCPU. */ +int crosvm_vcpu_set_mp_state(struct crosvm_vcpu *, + const struct kvm_mp_state *__mp_state); + #ifdef __cplusplus } #endif diff --git a/crosvm_plugin/src/lib.rs b/crosvm_plugin/src/lib.rs index e5c9844..3fa4338 100644 --- a/crosvm_plugin/src/lib.rs +++ b/crosvm_plugin/src/lib.rs @@ -43,7 +43,8 @@ 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}; +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 plugin_proto::*; @@ -354,6 +355,34 @@ impl crosvm { Ok(()) } + fn get_state(&mut self, state_set: MainRequest_StateSet, out: &mut [u8]) + -> result::Result<(), c_int> { + let mut r = MainRequest::new(); + r.mut_get_state().set = state_set; + let (response, _) = self.main_transaction(&r, &[])?; + if !response.has_get_state() { + return Err(EPROTO); + } + let get_state: &MainResponse_GetState = response.get_get_state(); + if get_state.state.len() != out.len() { + return Err(EPROTO); + } + out.copy_from_slice(&get_state.state); + Ok(()) + } + + fn set_state(&mut self, state_set: MainRequest_StateSet, new_state: &[u8]) + -> result::Result<(), c_int> { + let mut r = MainRequest::new(); + { + let set_state: &mut MainRequest_SetState = r.mut_set_state(); + set_state.set = state_set; + set_state.state = new_state.to_vec(); + } + self.main_transaction(&r, &[])?; + Ok(()) + } + fn set_identity_map_addr(&mut self, addr: u32) -> result::Result<(), c_int> { let mut r = MainRequest::new(); r.mut_set_identity_map_addr().address = addr; @@ -1001,6 +1030,71 @@ pub unsafe extern "C" fn crosvm_set_irq_routing(self_: *mut crosvm, to_crosvm_rc(ret) } +#[no_mangle] +pub unsafe extern "C" fn crosvm_get_pic_state(this: *mut crosvm, + primary: bool, + state: *mut kvm_pic_state) + -> c_int { + let this = &mut *this; + let state_set = if primary { MainRequest_StateSet::PIC0 } else { MainRequest_StateSet::PIC1 }; + let state = from_raw_parts_mut(state as *mut u8, size_of::()); + let ret = this.get_state(state_set, state); + to_crosvm_rc(ret) +} + +#[no_mangle] +pub unsafe extern "C" fn crosvm_set_pic_state(this: *mut crosvm, + primary: bool, + state: *mut kvm_pic_state) + -> c_int { + let this = &mut *this; + let state_set = if primary { MainRequest_StateSet::PIC0 } else { MainRequest_StateSet::PIC1 }; + let state = from_raw_parts(state as *mut u8, size_of::()); + let ret = this.set_state(state_set, state); + to_crosvm_rc(ret) +} + +#[no_mangle] +pub unsafe extern "C" fn crosvm_get_ioapic_state(this: *mut crosvm, + state: *mut kvm_ioapic_state) + -> c_int { + let this = &mut *this; + let state = from_raw_parts_mut(state as *mut u8, size_of::()); + let ret = this.get_state(MainRequest_StateSet::IOAPIC, state); + to_crosvm_rc(ret) +} + +#[no_mangle] +pub unsafe extern "C" fn crosvm_set_ioapic_state(this: *mut crosvm, + state: *const kvm_ioapic_state) + -> c_int { + + let this = &mut *this; + let state = from_raw_parts(state as *mut u8, size_of::()); + let ret = this.set_state(MainRequest_StateSet::IOAPIC, state); + to_crosvm_rc(ret) +} + +#[no_mangle] +pub unsafe extern "C" fn crosvm_get_pit_state(this: *mut crosvm, + state: *mut kvm_pit_state2) + -> c_int { + let this = &mut *this; + let state = from_raw_parts_mut(state as *mut u8, size_of::()); + let ret = this.get_state(MainRequest_StateSet::PIT, state); + to_crosvm_rc(ret) +} + +#[no_mangle] +pub unsafe extern "C" fn crosvm_set_pit_state(this: *mut crosvm, + state: *const kvm_pit_state2) + -> c_int { + let this = &mut *this; + let state = from_raw_parts(state as *mut u8, size_of::()); + let ret = this.set_state(MainRequest_StateSet::PIT, 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 self_ = &mut (*self_); @@ -1164,3 +1258,45 @@ pub unsafe extern "C" fn crosvm_vcpu_set_cpuid(this: *mut crosvm_vcpu, let ret = this.set_cpuid(cpuid_entries); to_crosvm_rc(ret) } + +#[no_mangle] +pub unsafe extern "C" fn crosvm_vcpu_get_lapic_state(this: *mut crosvm_vcpu, + state: *mut kvm_lapic_state) + -> c_int { + let this = &mut *this; + let state = from_raw_parts_mut(state as *mut u8, size_of::()); + let ret = this.get_state(VcpuRequest_StateSet::LAPIC, state); + to_crosvm_rc(ret) +} + +#[no_mangle] +pub unsafe extern "C" fn crosvm_vcpu_set_lapic_state(this: *mut crosvm_vcpu, + state: *const kvm_lapic_state) + -> c_int { + + let this = &mut *this; + let state = from_raw_parts(state as *mut u8, size_of::()); + let ret = this.set_state(VcpuRequest_StateSet::LAPIC, state); + to_crosvm_rc(ret) +} + +#[no_mangle] +pub unsafe extern "C" fn crosvm_vcpu_get_mp_state(this: *mut crosvm_vcpu, + state: *mut kvm_mp_state) + -> c_int { + let this = &mut *this; + let state = from_raw_parts_mut(state as *mut u8, size_of::()); + let ret = this.get_state(VcpuRequest_StateSet::MP, state); + to_crosvm_rc(ret) +} + +#[no_mangle] +pub unsafe extern "C" fn crosvm_vcpu_set_mp_state(this: *mut crosvm_vcpu, + state: *const kvm_mp_state) + -> c_int { + + let this = &mut *this; + let state = from_raw_parts(state as *mut u8, size_of::()); + let ret = this.set_state(VcpuRequest_StateSet::MP, state); + to_crosvm_rc(ret) +} -- cgit 1.4.1