mirror of
https://github.com/cloud-hypervisor/cloud-hypervisor.git
synced 2026-08-05 02:19:16 +00:00
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:
committed by
Rob Bradford
parent
faa94bddec
commit
6d9dd42abb
@@ -25,7 +25,7 @@ mod smbios;
|
|||||||
use std::arch::x86_64;
|
use std::arch::x86_64;
|
||||||
|
|
||||||
use helpers::{deserialize_u32_hex, serialize_u32_hex};
|
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 hypervisor::{CpuVendor, HypervisorCpuError, HypervisorError};
|
||||||
use linux_loader::loader::bootparam::{boot_params, setup_header};
|
use linux_loader::loader::bootparam::{boot_params, setup_header};
|
||||||
use linux_loader::loader::elf::start_info::{
|
use linux_loader::loader::elf::start_info::{
|
||||||
@@ -185,6 +185,15 @@ pub enum Error {
|
|||||||
)]
|
)]
|
||||||
CpuProfileMsrIncompatibility,
|
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 writing EBDA address
|
||||||
#[error("Error writing EBDA address")]
|
#[error("Error writing EBDA address")]
|
||||||
EbdaSetup(#[source] vm_memory::GuestMemoryError),
|
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
|
/// Apply updates to common CPUID (not vCPU specific) that are necessary regardless of
|
||||||
/// the chosen CPU profile.
|
/// the chosen CPU profile.
|
||||||
fn required_common_cpuid_updates(
|
fn required_common_cpuid_updates(
|
||||||
|
|||||||
Reference in New Issue
Block a user