diff options
author | Dmitry Torokhov <dtor@chromium.org> | 2018-07-26 13:48:56 -0700 |
---|---|---|
committer | chrome-bot <chrome-bot@chromium.org> | 2018-07-31 16:37:06 -0700 |
commit | c017a764d7237432f805d3b3f8f1ce7f5fdae107 (patch) | |
tree | adef847509b7723baba7f335ab2f82666609a57a | |
parent | 0ed91abecd7876d2344128848fe5f7bf6bf89255 (diff) | |
download | crosvm-c017a764d7237432f805d3b3f8f1ce7f5fdae107.tar crosvm-c017a764d7237432f805d3b3f8f1ce7f5fdae107.tar.gz crosvm-c017a764d7237432f805d3b3f8f1ce7f5fdae107.tar.bz2 crosvm-c017a764d7237432f805d3b3f8f1ce7f5fdae107.tar.lz crosvm-c017a764d7237432f805d3b3f8f1ce7f5fdae107.tar.xz crosvm-c017a764d7237432f805d3b3f8f1ce7f5fdae107.tar.zst crosvm-c017a764d7237432f805d3b3f8f1ce7f5fdae107.zip |
kvm: plumb accessor for KVM_GET_MSR_INDEX_LIST
Plumb in KVM_GET_MSR_INDEX_LIST to allow clients to figure out what MSRs are supported. BUG=b:111083877 TEST=cargo test -p kvm Change-Id: I69deba32a21fb9360f8cd53001d717338523fb71 Signed-off-by: Dmitry Torokhov <dtor@chromium.org> Reviewed-on: https://chromium-review.googlesource.com/1152228 Reviewed-by: Zach Reizner <zachr@chromium.org>
-rw-r--r-- | kvm/src/lib.rs | 47 |
1 files changed, 47 insertions, 0 deletions
diff --git a/kvm/src/lib.rs b/kvm/src/lib.rs index ea288eb..2d858db 100644 --- a/kvm/src/lib.rs +++ b/kvm/src/lib.rs @@ -160,6 +160,45 @@ impl Kvm { pub fn get_emulated_cpuid(&self) -> Result<CpuId> { self.get_cpuid(KVM_GET_EMULATED_CPUID()) } + + /// X86 specific call to get list of supported MSRS + /// + /// See the documentation for KVM_GET_MSR_INDEX_LIST. + #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] + pub fn get_msr_index_list(&self) -> Result<Vec<u32>> { + const MAX_KVM_MSR_ENTRIES: usize = 256; + + let vec_size_bytes = size_of::<kvm_msr_list>() + + MAX_KVM_MSR_ENTRIES * size_of::<u32>(); + let bytes: Vec<u8> = vec![0; vec_size_bytes]; + let msr_list: &mut kvm_msr_list = unsafe { + // We have ensured in new that there is enough space for the structure so this + // conversion is safe. + &mut *(bytes.as_ptr() as *mut kvm_msr_list) + }; + msr_list.nmsrs = MAX_KVM_MSR_ENTRIES as u32; + + let ret = unsafe { + // ioctl is unsafe. The kernel is trusted not to write beyond the bounds of the memory + // allocated for the struct. The limit is read from nmsrs, which is set to the allocated + // size (MAX_KVM_MSR_ENTRIES) above. + ioctl_with_mut_ref(self, KVM_GET_MSR_INDEX_LIST(), msr_list) + }; + if ret < 0 { + return errno_result(); + } + + // Mapping the unsized array to a slice is unsafe because the length isn't known. Using + // the length we originally allocated with eliminates the possibility of overflow. + let indices: &[u32] = unsafe { + if msr_list.nmsrs > MAX_KVM_MSR_ENTRIES as u32 { + msr_list.nmsrs = MAX_KVM_MSR_ENTRIES as u32; + } + msr_list.indices.as_slice(msr_list.nmsrs as usize) + }; + + Ok(indices.to_vec()) + } } impl AsRawFd for Kvm { @@ -1392,6 +1431,14 @@ mod tests { } #[test] + #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] + fn get_msr_index_list() { + let kvm = Kvm::new().unwrap(); + let msr_list = kvm.get_msr_index_list().unwrap(); + assert!(msr_list.len() >= 2); + } + + #[test] fn add_memory() { let kvm = Kvm::new().unwrap(); let gm = GuestMemory::new(&vec![(GuestAddress(0), 0x1000)]).unwrap(); |