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 <oliver.anderson@cyberus-technology.de>
On-behalf-of: SAP oliver.anderson@sap.com
This commit is contained in:
Oliver Anderson
2026-06-02 16:22:27 +02:00
committed by Rob Bradford
parent ebcf81d6ff
commit 9a2661a9c8
3 changed files with 56 additions and 1 deletions

View File

@@ -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<Vec<CpuIdEntry>>;
#[cfg(target_arch = "x86_64")]
///
/// Get feature MSRs supported by the hardware and hypervisor
///
fn get_feature_msrs(&self) -> Result<Vec<MsrEntry>>;
///
/// Check particular extensions if any
///

View File

@@ -1825,6 +1825,42 @@ impl hypervisor::Hypervisor for KvmHypervisor {
Ok(v)
}
#[cfg(target_arch = "x86_64")]
fn get_feature_msrs(&self) -> hypervisor::Result<Vec<MsrEntry>> {
let list = self
.kvm
.get_msr_feature_index_list()
.map_err(|e| hypervisor::HypervisorError::GetFeatureMsrs(e.into()))?;
let kvm_msrs: Vec<kvm_msr_entry> = 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.

View File

@@ -399,6 +399,10 @@ impl hypervisor::Hypervisor for MshvHypervisor {
}
Ok(cpuid)
}
#[cfg(target_arch = "x86_64")]
fn get_feature_msrs(&self) -> hypervisor::Result<Vec<MsrEntry>> {
unimplemented!()
}
/// Get maximum number of vCPUs
fn get_max_vcpus(&self) -> u32 {