diff options
author | Zach Reizner <zachr@google.com> | 2018-02-01 19:12:32 -0800 |
---|---|---|
committer | chrome-bot <chrome-bot@chromium.org> | 2018-02-12 22:42:36 -0800 |
commit | 7a4d7b1f50d07e7f0ae350c27659c6e852da62c7 (patch) | |
tree | 5efb7e9cb9d7f32e90985a19b7875f9f6936470b /kvm | |
parent | 53528e33eda615ef309915447b227d2dcacb2090 (diff) | |
download | crosvm-7a4d7b1f50d07e7f0ae350c27659c6e852da62c7.tar crosvm-7a4d7b1f50d07e7f0ae350c27659c6e852da62c7.tar.gz crosvm-7a4d7b1f50d07e7f0ae350c27659c6e852da62c7.tar.bz2 crosvm-7a4d7b1f50d07e7f0ae350c27659c6e852da62c7.tar.lz crosvm-7a4d7b1f50d07e7f0ae350c27659c6e852da62c7.tar.xz crosvm-7a4d7b1f50d07e7f0ae350c27659c6e852da62c7.tar.zst crosvm-7a4d7b1f50d07e7f0ae350c27659c6e852da62c7.zip |
add plugin support for model specific registers
The MSRs are useful for booting a full operating system that requires them. TEST=cargo test --features plugin; cargo test -p kvm; ./build_test BUG=chromium:800626 Change-Id: I817fbf3e6868c85b373808bd48e568b5b2b458eb Reviewed-on: https://chromium-review.googlesource.com/897412 Commit-Ready: Zach Reizner <zachr@chromium.org> Tested-by: Zach Reizner <zachr@chromium.org> Reviewed-by: Zach Reizner <zachr@chromium.org>
Diffstat (limited to 'kvm')
-rw-r--r-- | kvm/src/lib.rs | 53 |
1 files changed, 53 insertions, 0 deletions
diff --git a/kvm/src/lib.rs b/kvm/src/lib.rs index 82e8939..1c1ce2e 100644 --- a/kvm/src/lib.rs +++ b/kvm/src/lib.rs @@ -830,6 +830,41 @@ impl Vcpu { Ok(()) } + /// X86 specific call to get the MSRS + /// + /// See the documentation for KVM_SET_MSRS. + #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] + pub fn get_msrs(&self, msr_entries: &mut [kvm_msr_entry]) -> Result<()> { + let vec_size_bytes = size_of::<kvm_msrs>() + + (msr_entries.len() * size_of::<kvm_msr_entry>()); + let vec: Vec<u8> = vec![0; vec_size_bytes]; + let msrs: &mut kvm_msrs = unsafe { + // Converting the vector's memory to a struct is unsafe. Carefully using the read-only + // vector to size and set the members ensures no out-of-bounds erros below. + &mut *(vec.as_ptr() as *mut kvm_msrs) + }; + unsafe { + // Mapping the unsized array to a slice is unsafe becase the length isn't known. + // Providing the length used to create the struct guarantees the entire slice is valid. + let entries: &mut [kvm_msr_entry] = msrs.entries.as_mut_slice(msr_entries.len()); + entries.copy_from_slice(&msr_entries); + } + msrs.nmsrs = msr_entries.len() as u32; + let ret = unsafe { + // Here we trust the kernel not to read or write past the end of the kvm_msrs struct. + ioctl_with_ref(self, KVM_GET_MSRS(), msrs) + }; + if ret < 0 { + // KVM_SET_MSRS actually returns the number of msr entries written. + return errno_result(); + } + unsafe { + let entries: &mut [kvm_msr_entry] = msrs.entries.as_mut_slice(msr_entries.len()); + msr_entries.copy_from_slice(&entries); + } + Ok(()) + } + /// X86 specific call to setup the MSRS /// /// See the documentation for KVM_SET_MSRS. @@ -1184,6 +1219,24 @@ mod tests { } #[test] + #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] + fn get_msrs() { + let kvm = Kvm::new().unwrap(); + let gm = GuestMemory::new(&vec![(GuestAddress(0), 0x10000)]).unwrap(); + let vm = Vm::new(&kvm, gm).unwrap(); + let vcpu = Vcpu::new(0, &kvm, &vm).unwrap(); + vcpu.get_msrs(&mut [kvm_msr_entry { + index: 0x0000011e, + ..Default::default() + }, + kvm_msr_entry { + index: 0x000003f1, + ..Default::default() + }]) + .unwrap(); + } + + #[test] fn vcpu_mmap_size() { let kvm = Kvm::new().unwrap(); let mmap_size = kvm.get_vcpu_mmap_size().unwrap(); |