diff --git a/arch/src/x86_64/regs.rs b/arch/src/x86_64/regs.rs index e96aa9d43..48c283830 100644 --- a/arch/src/x86_64/regs.rs +++ b/arch/src/x86_64/regs.rs @@ -11,6 +11,8 @@ use std::result; use hypervisor::arch::x86::gdt::{gdt_entry, segment_from_gdt}; use hypervisor::arch::x86::regs::CR0_PE; use hypervisor::arch::x86::{FpuState, SpecialRegisters}; +#[cfg(all(feature = "kvm", not(feature = "sev_snp")))] +use log::error; use thiserror::Error; use vm_memory::{Address, Bytes, GuestMemoryBackend, GuestMemoryError}; @@ -33,6 +35,9 @@ pub enum Error { /// Setting up MSRs failed. #[error("Setting up MSRs failed")] SetModelSpecificRegisters(#[source] hypervisor::HypervisorCpuError), + /// Setting up MSRs failed because not all setup entries were set. + #[error("Some MSRs could not be set")] + SetModelSpecificRegistersAll, /// Failed to set SREGs for this CPU. #[error("Failed to set SREGs for this CPU")] SetStatusRegisters(#[source] hypervisor::HypervisorCpuError), @@ -81,10 +86,31 @@ pub fn setup_fpu(vcpu: &dyn hypervisor::Vcpu) -> Result<()> { /// # Arguments /// /// * `vcpu` - Structure for the VCPU that holds the VCPU's fd. +#[cfg_attr( + any(not(feature = "kvm"), feature = "sev_snp"), + allow(unused_variables) +)] pub fn setup_msrs(vcpu: &dyn hypervisor::Vcpu) -> Result<()> { - vcpu.set_msrs(vcpu.boot_msr_entries()) + let setup_entries = vcpu.boot_msr_entries(); + let num_msrs_set = vcpu + .set_msrs(&setup_entries) .map_err(Error::SetModelSpecificRegisters)?; + // Check that all setup entries were set. We can only do this for KVM + // (when SEV-SNP is not enabled) as MSHV always returns Ok(0) on success. + #[cfg(all(feature = "kvm", not(feature = "sev_snp")))] + if matches!(vcpu.hypervisor_type(), hypervisor::HypervisorType::Kvm) + && num_msrs_set != setup_entries.len() + { + for msr in &setup_entries[num_msrs_set..] { + error!( + "Could not set MSR with register address={:#x} and value={:#x}", + msr.index, msr.data + ); + } + + return Err(Error::SetModelSpecificRegistersAll); + } Ok(()) } diff --git a/hypervisor/src/cpu.rs b/hypervisor/src/cpu.rs index ce24e7b6f..8da9aefdd 100644 --- a/hypervisor/src/cpu.rs +++ b/hypervisor/src/cpu.rs @@ -614,7 +614,7 @@ pub trait Vcpu: Send + Sync { /// /// Return the list of initial MSR entries for a VCPU /// - fn boot_msr_entries(&self) -> &'static [MsrEntry]; + fn boot_msr_entries(&self) -> Vec; #[cfg(target_arch = "x86_64")] /// diff --git a/hypervisor/src/kvm/mod.rs b/hypervisor/src/kvm/mod.rs index 4c84feb88..4fde4b278 100644 --- a/hypervisor/src/kvm/mod.rs +++ b/hypervisor/src/kvm/mod.rs @@ -3549,10 +3549,12 @@ impl cpu::Vcpu for KvmVcpu { /// /// Return the list of initial MSR entries for a VCPU /// - fn boot_msr_entries(&self) -> &'static [MsrEntry] { + fn boot_msr_entries(&self) -> Vec { use crate::arch::x86::{MTRR_ENABLE, MTRR_MEM_TYPE_WB, msr_index}; - &[ + let mut boot_entries = self.feature_msrs.clone(); + + boot_entries.extend([ msr!(msr_index::MSR_IA32_SYSENTER_CS), msr!(msr_index::MSR_IA32_SYSENTER_ESP), msr!(msr_index::MSR_IA32_SYSENTER_EIP), @@ -3567,7 +3569,9 @@ impl cpu::Vcpu for KvmVcpu { msr_index::MSR_IA32_MISC_ENABLE_FAST_STRING as u64 ), msr_data!(msr_index::MSR_MTRRdefType, MTRR_ENABLE | MTRR_MEM_TYPE_WB), - ] + ]); + + boot_entries } #[cfg(target_arch = "aarch64")] diff --git a/hypervisor/src/mshv/mod.rs b/hypervisor/src/mshv/mod.rs index a56a290d8..a5378e87d 100644 --- a/hypervisor/src/mshv/mod.rs +++ b/hypervisor/src/mshv/mod.rs @@ -1564,10 +1564,10 @@ impl cpu::Vcpu for MshvVcpu { /// /// Return the list of initial MSR entries for a VCPU /// - fn boot_msr_entries(&self) -> &'static [MsrEntry] { + fn boot_msr_entries(&self) -> Vec { use crate::arch::x86::{MTRR_ENABLE, MTRR_MEM_TYPE_WB, msr_index}; - &[ + vec![ msr!(msr_index::MSR_IA32_SYSENTER_CS), msr!(msr_index::MSR_IA32_SYSENTER_ESP), msr!(msr_index::MSR_IA32_SYSENTER_EIP),