diff --git a/hypervisor/src/hypervisor.rs b/hypervisor/src/hypervisor.rs index 2c3ce6fb9..e71d64d8e 100644 --- a/hypervisor/src/hypervisor.rs +++ b/hypervisor/src/hypervisor.rs @@ -16,7 +16,7 @@ use thiserror::Error; #[cfg(target_arch = "x86_64")] use crate::arch::x86::{ - AmxGuestSupportError, CpuIdEntry, amx_supported, request_guest_amx_support, + AmxGuestSupportError, CpuIdEntry, MsrEntry, amx_supported, request_guest_amx_support, }; #[cfg(target_arch = "x86_64")] use crate::cpu::CpuVendor; @@ -104,6 +104,16 @@ pub enum HypervisorError { /// #[error("Failed to retrieve SEV-SNP capabilities:{0}")] SevSnpCapabilities(#[source] anyhow::Error), + /// + /// Unable to read the requested feature MSRs + /// + #[error("Failed to get feature MSRs")] + GetFeatureMsrs(#[source] anyhow::Error), + /// + /// Unable to read all feature MSRs advertised by the Hypervisor + /// + #[error("Unable to read all feature MSRs")] + GetFeatureMsrsPartial, } /// @@ -131,6 +141,11 @@ pub trait Hypervisor: Send + Sync { /// Get the supported CpuID /// fn get_supported_cpuid(&self) -> Result>; + #[cfg(target_arch = "x86_64")] + /// + /// Get feature MSRs supported by the hardware and hypervisor + /// + fn get_feature_msrs(&self) -> Result>; /// /// Check particular extensions if any /// diff --git a/hypervisor/src/kvm/mod.rs b/hypervisor/src/kvm/mod.rs index 8a09de5ff..a69cecf4f 100644 --- a/hypervisor/src/kvm/mod.rs +++ b/hypervisor/src/kvm/mod.rs @@ -1825,6 +1825,42 @@ impl hypervisor::Hypervisor for KvmHypervisor { Ok(v) } + #[cfg(target_arch = "x86_64")] + fn get_feature_msrs(&self) -> hypervisor::Result> { + let list = self + .kvm + .get_msr_feature_index_list() + .map_err(|e| hypervisor::HypervisorError::GetFeatureMsrs(e.into()))?; + + let kvm_msrs: Vec = list + .as_slice() + .iter() + .copied() + .map(|index| kvm_msr_entry { + index, + ..Default::default() + }) + .collect(); + + let mut kvm_msrs = MsrEntries::from_entries(&kvm_msrs).unwrap(); + + let num_feature_msrs = self + .kvm + .get_msrs(&mut kvm_msrs) + .map_err(|e| hypervisor::HypervisorError::GetFeatureMsrs(e.into()))?; + + if list.as_slice().len() == num_feature_msrs { + Ok(kvm_msrs + .as_slice() + .iter() + .copied() + .map(MsrEntry::from) + .collect()) + } else { + Err(hypervisor::HypervisorError::GetFeatureMsrsPartial) + } + } + #[cfg(target_arch = "aarch64")] /// /// Retrieve AArch64 host maximum IPA size supported by KVM. diff --git a/hypervisor/src/mshv/mod.rs b/hypervisor/src/mshv/mod.rs index ffdad3091..d9cbbf186 100644 --- a/hypervisor/src/mshv/mod.rs +++ b/hypervisor/src/mshv/mod.rs @@ -399,6 +399,10 @@ impl hypervisor::Hypervisor for MshvHypervisor { } Ok(cpuid) } + #[cfg(target_arch = "x86_64")] + fn get_feature_msrs(&self) -> hypervisor::Result> { + unimplemented!() + } /// Get maximum number of vCPUs fn get_max_vcpus(&self) -> u32 {