misc: Make CPU profile part of various configs

We integrate the CPU profile into the various configs that
ultimately get set by the user.

This quickly ends up involving multiple files, luckily Rust
helps us find which ones via compilation errors.

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
2025-10-07 05:34:22 +02:00
committed by Rob Bradford
parent a9440d2919
commit 549f3d6c04
8 changed files with 53 additions and 12 deletions

View File

@@ -37,7 +37,7 @@ use vm_memory::{
GuestMemoryRegion, GuestMemoryRegion,
}; };
use crate::{GuestMemoryMmap, InitramfsConfig, RegionType}; use crate::{CpuProfile, GuestMemoryMmap, InitramfsConfig, RegionType};
// While modern architectures support more than 255 CPUs via x2APIC, // While modern architectures support more than 255 CPUs via x2APIC,
// legacy devices such as mptable support at most 254 CPUs. // legacy devices such as mptable support at most 254 CPUs.
@@ -99,6 +99,7 @@ pub struct CpuidConfig {
#[cfg(feature = "tdx")] #[cfg(feature = "tdx")]
pub tdx: bool, pub tdx: bool,
pub amx: bool, pub amx: bool,
pub profile: CpuProfile,
} }
#[derive(Debug, Error)] #[derive(Debug, Error)]

View File

@@ -985,6 +985,7 @@ mod unit_tests {
features: CpuFeatures::default(), features: CpuFeatures::default(),
nested: true, nested: true,
core_scheduling: CoreScheduling::Vm, core_scheduling: CoreScheduling::Vm,
profile: Default::default(),
}, },
memory: MemoryConfig { memory: MemoryConfig {
size: 536_870_912, size: 536_870_912,

View File

@@ -136,6 +136,7 @@ impl RequestHandler for StubApiRequestHandler {
max_phys_bits: 46, max_phys_bits: 46,
affinity: None, affinity: None,
features: CpuFeatures::default(), features: CpuFeatures::default(),
profile: Default::default(),
nested: true, nested: true,
core_scheduling: CoreScheduling::default(), core_scheduling: CoreScheduling::default(),
}, },

View File

@@ -11,6 +11,7 @@ use std::result;
use std::str::FromStr; use std::str::FromStr;
use std::sync::LazyLock; use std::sync::LazyLock;
use arch::CpuProfile;
use block::ImageType; use block::ImageType;
use clap::ArgMatches; use clap::ArgMatches;
use log::{debug, warn}; use log::{debug, warn};
@@ -697,7 +698,8 @@ impl CpusConfig {
.add("affinity") .add("affinity")
.add("features") .add("features")
.add("nested") .add("nested")
.add("core_scheduling"); .add("core_scheduling")
.add("profile");
parser.parse(cpus).map_err(Error::ParseCpus)?; parser.parse(cpus).map_err(Error::ParseCpus)?;
let boot_vcpus: u32 = parser let boot_vcpus: u32 = parser
@@ -729,6 +731,12 @@ impl CpusConfig {
}) })
.collect() .collect()
}); });
let profile = parser
.convert::<CpuProfile>("profile")
.map_err(Error::ParseCpus)?
.unwrap_or_default();
let features_list = parser let features_list = parser
.convert::<StringList>("features") .convert::<StringList>("features")
.map_err(Error::ParseCpus)? .map_err(Error::ParseCpus)?
@@ -771,6 +779,7 @@ impl CpusConfig {
features, features,
nested, nested,
core_scheduling, core_scheduling,
profile,
}) })
} }
} }

View File

@@ -963,6 +963,7 @@ impl CpuManager {
#[cfg(feature = "tdx")] #[cfg(feature = "tdx")]
tdx, tdx,
amx: self.config.features.amx, amx: self.config.features.amx,
profile: self.config.profile,
}, },
) )
.map_err(Error::CommonCpuId)? .map_err(Error::CommonCpuId)?

View File

@@ -1428,17 +1428,27 @@ impl Vmm {
))); )));
} }
let amx = vm_config.lock().unwrap().cpus.features.amx; let (amx, max_phys_bits, profile, kvm_hyperv) = {
let phys_bits = let guard = vm_config.lock().unwrap();
vm::physical_bits(hypervisor, vm_config.lock().unwrap().cpus.max_phys_bits); (
guard.cpus.features.amx,
guard.cpus.max_phys_bits,
guard.cpus.profile,
guard.cpus.kvm_hyperv,
)
};
let phys_bits = vm::physical_bits(hypervisor, max_phys_bits);
arch::generate_common_cpuid( arch::generate_common_cpuid(
hypervisor, hypervisor,
&arch::CpuidConfig { &arch::CpuidConfig {
phys_bits, phys_bits,
kvm_hyperv: vm_config.lock().unwrap().cpus.kvm_hyperv, kvm_hyperv,
#[cfg(feature = "tdx")] #[cfg(feature = "tdx")]
tdx: false, tdx: false,
amx, amx,
profile,
}, },
) )
.map_err(|e| { .map_err(|e| {
@@ -1584,6 +1594,7 @@ impl Vmm {
#[cfg(feature = "tdx")] #[cfg(feature = "tdx")]
tdx: false, tdx: false,
amx: vm_config.cpus.features.amx, amx: vm_config.cpus.features.amx,
profile: vm_config.cpus.profile,
}, },
) )
.map_err(|e| { .map_err(|e| {
@@ -2653,6 +2664,8 @@ const DEVICE_MANAGER_SNAPSHOT_ID: &str = "device-manager";
mod unit_tests { mod unit_tests {
use std::path::PathBuf; use std::path::PathBuf;
use arch::CpuProfile;
use super::*; use super::*;
#[cfg(target_arch = "x86_64")] #[cfg(target_arch = "x86_64")]
use crate::vm_config::DebugConsoleConfig; use crate::vm_config::DebugConsoleConfig;
@@ -2690,6 +2703,7 @@ mod unit_tests {
features: CpuFeatures::default(), features: CpuFeatures::default(),
nested: true, nested: true,
core_scheduling: CoreScheduling::default(), core_scheduling: CoreScheduling::default(),
profile: CpuProfile::default(),
}, },
memory: MemoryConfig { memory: MemoryConfig {
size: 536_870_912, size: 536_870_912,

View File

@@ -3359,19 +3359,28 @@ impl Snapshottable for Vm {
#[cfg(all(feature = "kvm", target_arch = "x86_64"))] #[cfg(all(feature = "kvm", target_arch = "x86_64"))]
let common_cpuid = { let common_cpuid = {
let amx = self.config.lock().unwrap().cpus.features.amx; let (amx, max_phys_bits, kvm_hyperv, profile) = {
let phys_bits = physical_bits( let guard = self.config.lock().unwrap();
self.hypervisor.as_ref(), let VmConfig { cpus, .. } = &*guard;
self.config.lock().unwrap().cpus.max_phys_bits, (
); cpus.features.amx,
cpus.max_phys_bits,
cpus.kvm_hyperv,
cpus.profile,
)
};
let phys_bits = physical_bits(self.hypervisor.as_ref(), max_phys_bits);
arch::generate_common_cpuid( arch::generate_common_cpuid(
self.hypervisor.as_ref(), self.hypervisor.as_ref(),
&arch::CpuidConfig { &arch::CpuidConfig {
phys_bits, phys_bits,
kvm_hyperv: self.config.lock().unwrap().cpus.kvm_hyperv, kvm_hyperv,
#[cfg(feature = "tdx")] #[cfg(feature = "tdx")]
tdx: false, tdx: false,
amx, amx,
profile,
}, },
) )
.map_err(|e| { .map_err(|e| {

View File

@@ -9,6 +9,7 @@ use std::path::{Path, PathBuf};
use std::str::FromStr; use std::str::FromStr;
use std::{fs, result}; use std::{fs, result};
use arch::CpuProfile;
use block::ImageType; use block::ImageType;
pub use block::fcntl::LockGranularityChoice; pub use block::fcntl::LockGranularityChoice;
use log::{debug, warn}; use log::{debug, warn};
@@ -84,6 +85,9 @@ pub struct CpusConfig {
pub nested: bool, pub nested: bool,
#[serde(default)] #[serde(default)]
pub core_scheduling: CoreScheduling, pub core_scheduling: CoreScheduling,
// Defaults to "Host" if no profile is given.
#[serde(default)]
pub profile: CpuProfile,
} }
pub const DEFAULT_VCPUS: u32 = 1; pub const DEFAULT_VCPUS: u32 = 1;
@@ -100,6 +104,7 @@ impl Default for CpusConfig {
features: CpuFeatures::default(), features: CpuFeatures::default(),
nested: true, nested: true,
core_scheduling: CoreScheduling::default(), core_scheduling: CoreScheduling::default(),
profile: CpuProfile::default(),
} }
} }
} }