From 9a2661a9c86e3ae2b739b0497a2a639d76226b22 Mon Sep 17 00:00:00 2001 From: Oliver Anderson Date: Tue, 2 Jun 2026 16:22:27 +0200 Subject: [PATCH] hypervisor: Add get_feature_msrs method KVM defines feature MSRs as MSRs that expose host capabilities and processor features. CPU profiles will describe how to adjust such feature MSRs similarly to how they describe CPUID modifications. We thus introduce a method on the hypervisor trait that queries the hypervisor for the supported feature MSRs. This will later be used to obtain the feature MSRs that need to be adjusted when a CPU profile is applied. The method will also be used by the upcoming CPU profile generation tool which will be introduced in a follow up PR. Signed-off-by: Oliver Anderson On-behalf-of: SAP oliver.anderson@sap.com --- hypervisor/src/hypervisor.rs | 17 ++++++++++++++++- hypervisor/src/kvm/mod.rs | 36 ++++++++++++++++++++++++++++++++++++ hypervisor/src/mshv/mod.rs | 4 ++++ 3 files changed, 56 insertions(+), 1 deletion(-) 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 {