kvm: fix get_msrs() to handle case where KVM does not fetch all MSRs

KVM may not return all MSRs that were requested in KVM_GET_MSRS call and
instead stop early. We should handle this case.

BUG=None
TEST=cargo test -p kvm

Change-Id: I18402c0a07b1d0c7657c171873d521fd2f223611
Signed-off-by: Dmitry Torokhov <dtor@chromium.org>
Reviewed-on: https://chromium-review.googlesource.com/1192231
Reviewed-by: Zach Reizner <zachr@chromium.org>
Reviewed-by: Dylan Reid <dgreid@chromium.org>
This commit is contained in:
Dmitry Torokhov 2018-08-27 12:35:49 -07:00 committed by chrome-bot
parent 45e6c843bb
commit 9dec40e242

View file

@ -1076,7 +1076,7 @@ impl Vcpu {
/// ///
/// See the documentation for KVM_SET_MSRS. /// See the documentation for KVM_SET_MSRS.
#[cfg(any(target_arch = "x86", target_arch = "x86_64"))] #[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
pub fn get_msrs(&self, msr_entries: &mut [kvm_msr_entry]) -> Result<()> { pub fn get_msrs(&self, msr_entries: &mut Vec<kvm_msr_entry>) -> Result<()> {
let vec_size_bytes = size_of::<kvm_msrs>() + let vec_size_bytes = size_of::<kvm_msrs>() +
(msr_entries.len() * size_of::<kvm_msr_entry>()); (msr_entries.len() * size_of::<kvm_msr_entry>());
let vec: Vec<u8> = vec![0; vec_size_bytes]; let vec: Vec<u8> = vec![0; vec_size_bytes];
@ -1101,7 +1101,10 @@ impl Vcpu {
return errno_result(); return errno_result();
} }
unsafe { unsafe {
let entries: &mut [kvm_msr_entry] = msrs.entries.as_mut_slice(msr_entries.len()); let count = ret as usize;
assert!(count <= msr_entries.len());
let entries: &mut [kvm_msr_entry] = msrs.entries.as_mut_slice(count);
msr_entries.truncate(count);
msr_entries.copy_from_slice(&entries); msr_entries.copy_from_slice(&entries);
} }
Ok(()) Ok(())
@ -1691,15 +1694,14 @@ mod tests {
let gm = GuestMemory::new(&vec![(GuestAddress(0), 0x10000)]).unwrap(); let gm = GuestMemory::new(&vec![(GuestAddress(0), 0x10000)]).unwrap();
let vm = Vm::new(&kvm, gm).unwrap(); let vm = Vm::new(&kvm, gm).unwrap();
let vcpu = Vcpu::new(0, &kvm, &vm).unwrap(); let vcpu = Vcpu::new(0, &kvm, &vm).unwrap();
vcpu.get_msrs(&mut [kvm_msr_entry { let mut msrs = vec![
index: 0x0000011e, // This one should succeed
..Default::default() kvm_msr_entry { index: 0x0000011e, ..Default::default() },
}, // This one will fail to fetch
kvm_msr_entry { kvm_msr_entry { index: 0x000003f1, ..Default::default() },
index: 0x000003f1, ];
..Default::default() vcpu.get_msrs(&mut msrs).unwrap();
}]) assert_eq!(msrs.len(), 1);
.unwrap();
} }
#[test] #[test]