arch: Generate required_msr_updates function

We introduce a function somewhat analogous to `generate_common_cpuid`,
except that it is only relevant for CPU profiles.

This function is more "high level" than the
CpuProfile::required_msr_updates method and is intended to be called
from the vmm crate.

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-10 20:45:28 +02:00
committed by Rob Bradford
parent faa94bddec
commit 6d9dd42abb

View File

@@ -25,7 +25,7 @@ mod smbios;
use std::arch::x86_64;
use helpers::{deserialize_u32_hex, serialize_u32_hex};
use hypervisor::arch::x86::{CPUID_FLAG_VALID_INDEX, CpuIdEntry};
use hypervisor::arch::x86::{CPUID_FLAG_VALID_INDEX, CpuIdEntry, VcpuMsrConfigUpdate};
use hypervisor::{CpuVendor, HypervisorCpuError, HypervisorError};
use linux_loader::loader::bootparam::{boot_params, setup_header};
use linux_loader::loader::elf::start_info::{
@@ -185,6 +185,15 @@ pub enum Error {
)]
CpuProfileMsrIncompatibility,
/// Error when trying to apply a CPU profile because the MSR index list could not be obtained
#[error("The selected CPU profile could not be utilized: failed to obtain MSR index list")]
CpuProfileMsrIndexList(#[source] HypervisorError),
/// Error when trying to apply a CPU profile because the feature MSRs could not be obtained
/// from the hypervisor.
#[error("The selected CPU profile could not be utilized: failed to obtain feature MSRs")]
CpuProfileFeatureMsrs(#[source] HypervisorError),
// Error writing EBDA address
#[error("Error writing EBDA address")]
EbdaSetup(#[source] vm_memory::GuestMemoryError),
@@ -715,6 +724,61 @@ pub fn generate_common_cpuid(
}
}
/// Generates the MSR related updates that are required in order to be compatible with the given CPU profile (if any).
///
/// An error is returned if any MSR required by the given CPU profile is not reported by the hypervisor. If
/// the `kvm_hyperv` parameter is `false` then Hyper-V related MSRs are exempt from this check.
///
/// If nested is `false` then feature MSRs describing virtualization capabilities will not be considered part of
/// the CPU profile.
///
/// ## Feature MSRs compatibility
///
/// The hypervisor is expected to reject setting feature MSRs that are incompatible with the host. This is why this
/// function does **NOT perform such compatibility checks** itself.
///
/// The one and only exception to this rule is the IA32_ARCH_CAPABILITIES MSR. This function will check that the
/// host is compatible with the CPU profile's value for that MSR when present as KVM permits setting it regardless
/// of what the host actually supports.
pub fn generate_required_msr_updates(
hypervisor: &dyn hypervisor::Hypervisor,
cpu_profile: CpuProfile,
kvm_hyperv: bool,
nested: bool,
) -> super::Result<Option<VcpuMsrConfigUpdate>> {
if matches!(cpu_profile, CpuProfile::Host) {
return Ok(None);
}
let host_supported_msrs = hypervisor
.get_msr_index_list()
.map_err(Error::CpuProfileMsrIndexList)?;
let host_feature_msrs = hypervisor
.get_feature_msrs()
.map_err(Error::CpuProfileFeatureMsrs)?;
let required_updates = cpu_profile.required_msr_updates(
&host_feature_msrs,
&host_supported_msrs,
kvm_hyperv,
nested,
)?;
if let Some(required_updates) = &required_updates {
// If IA32_ARCH_CAPABILITIES is present then we need to check for compatibility.
// This MSR is only available on Intel CPUs as of now, but we do not check for vendor equality here.
//
// TODO: Consider adding a CPU vendor equality requirement to `check_cpuid_compatibility` even though
// it is extremely unlikely that CPUs from different vendors will pass the existing checks.
arch_capabilities_checks::valid_required_arch_capabilities_update(
required_updates,
&host_feature_msrs,
)?;
}
Ok(required_updates)
}
/// Apply updates to common CPUID (not vCPU specific) that are necessary regardless of
/// the chosen CPU profile.
fn required_common_cpuid_updates(