summary refs log tree commit diff
path: root/src/plugin/vcpu.rs
diff options
context:
space:
mode:
authorZach Reizner <zachr@google.com>2018-02-01 19:12:32 -0800
committerchrome-bot <chrome-bot@chromium.org>2018-02-12 22:42:36 -0800
commit7a4d7b1f50d07e7f0ae350c27659c6e852da62c7 (patch)
tree5efb7e9cb9d7f32e90985a19b7875f9f6936470b /src/plugin/vcpu.rs
parent53528e33eda615ef309915447b227d2dcacb2090 (diff)
downloadcrosvm-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 'src/plugin/vcpu.rs')
-rw-r--r--src/plugin/vcpu.rs46
1 files changed, 45 insertions, 1 deletions
diff --git a/src/plugin/vcpu.rs b/src/plugin/vcpu.rs
index ce8b67d..fcd6543 100644
--- a/src/plugin/vcpu.rs
+++ b/src/plugin/vcpu.rs
@@ -6,6 +6,7 @@ use std::cell::{Cell, RefCell};
 use std::cmp::min;
 use std::cmp::{self, Ord, PartialOrd, PartialEq};
 use std::collections::btree_set::BTreeSet;
+use std::mem::size_of;
 use std::os::unix::net::UnixDatagram;
 use std::sync::{Arc, Mutex, RwLock};
 
@@ -16,7 +17,7 @@ use protobuf::Message;
 
 use data_model::DataInit;
 use kvm::Vcpu;
-use kvm_sys::{kvm_regs, kvm_sregs, kvm_fpu, kvm_debugregs};
+use kvm_sys::{kvm_regs, kvm_sregs, kvm_fpu, kvm_debugregs, kvm_msrs, kvm_msr_entry};
 use plugin_proto::*;
 
 use super::*;
@@ -404,6 +405,49 @@ impl PluginVcpu {
             response.mut_set_state();
             let set_state = request.get_set_state();
             set_vcpu_state(vcpu, set_state.set, set_state.get_state())
+        } else if request.has_get_msrs() {
+            let entry_data = &mut response.mut_get_msrs().entry_data;
+            let entry_indices = &request.get_get_msrs().entry_indices;
+            let mut msr_entries = Vec::with_capacity(entry_indices.len());
+            for &index in entry_indices {
+                msr_entries.push(kvm_msr_entry {
+                                     index,
+                                     ..Default::default()
+                                 });
+            }
+            match vcpu.get_msrs(&mut msr_entries) {
+                Ok(()) => {
+                    for msr_entry in msr_entries {
+                        entry_data.push(msr_entry.data);
+                    }
+                    Ok(())
+                }
+                Err(e) => Err(e),
+            }
+        } else if request.has_set_msrs() {
+            response.mut_set_msrs();
+            let request_entries = &request.get_set_msrs().entries;
+            let vec_size_bytes = size_of::<kvm_msrs>() +
+                                 (request_entries.len() * size_of::<kvm_msr_entry>());
+            let vec: Vec<u8> = vec![0; vec_size_bytes];
+            let kvm_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 kvm_msr_entries: &mut [kvm_msr_entry] =
+                    kvm_msrs.entries.as_mut_slice(request_entries.len());
+                for (msr_entry, entry) in kvm_msr_entries.iter_mut().zip(request_entries.iter()) {
+                    msr_entry.index = entry.index;
+                    msr_entry.data = entry.data;
+                }
+            }
+            kvm_msrs.nmsrs = request_entries.len() as u32;
+            vcpu.set_msrs(&kvm_msrs)
         } else {
             Err(SysError::new(-ENOTTY))
         };