summary refs log tree commit diff
diff options
context:
space:
mode:
authorDmitry Torokhov <dtor@chromium.org>2018-07-26 13:48:56 -0700
committerchrome-bot <chrome-bot@chromium.org>2018-07-31 16:37:06 -0700
commitc017a764d7237432f805d3b3f8f1ce7f5fdae107 (patch)
treeadef847509b7723baba7f335ab2f82666609a57a
parent0ed91abecd7876d2344128848fe5f7bf6bf89255 (diff)
downloadcrosvm-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.rs47
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();