diff --git a/hypervisor/src/kvm/x86_64.rs b/hypervisor/src/kvm/x86_64.rs index e9702f3f4f..dd7c022488 100644 --- a/hypervisor/src/kvm/x86_64.rs +++ b/hypervisor/src/kvm/x86_64.rs @@ -903,11 +903,25 @@ impl VcpuX86_64 for KvmVcpu { ioctl_with_ref(self, KVM_SET_MSRS(), &msrs[0]) }; // KVM_SET_MSRS actually returns the number of msr entries written. - if ret >= 0 { - Ok(()) - } else { - errno_result() + if ret < 0 { + return errno_result(); } + let num_set = ret as usize; + if num_set != vec.len() { + if let Some(register) = vec.get(num_set) { + error!( + "failed to set MSR {:#x?} to {:#x?}", + register.id, register.value + ); + } else { + error!( + "unexpected KVM_SET_MSRS return value {num_set} (nmsrs={})", + vec.len() + ); + } + return Err(base::Error::new(libc::EPERM)); + } + Ok(()) } fn set_cpuid(&self, cpuid: &CpuId) -> Result<()> { diff --git a/hypervisor/tests/kvm/x86_64.rs b/hypervisor/tests/kvm/x86_64.rs index 5f3cf3e0d2..0b71d8ac35 100644 --- a/hypervisor/tests/kvm/x86_64.rs +++ b/hypervisor/tests/kvm/x86_64.rs @@ -408,6 +408,20 @@ fn set_msrs() { assert_eq!(msrs[0].value, 42); } +#[test] +fn set_msrs_unsupported() { + let kvm = Kvm::new().unwrap(); + let gm = GuestMemory::new(&[(GuestAddress(0), 0x10000)]).unwrap(); + let vm = KvmVm::new(&kvm, gm, Default::default()).unwrap(); + let vcpu = vm.create_vcpu(0).unwrap(); + + let msrs = vec![Register { + id: u32::MAX, + value: u64::MAX, + }]; + assert_eq!(vcpu.set_msrs(&msrs), Err(base::Error::new(libc::EPERM))); +} + #[test] fn get_hyperv_cpuid() { let kvm = Kvm::new().unwrap();