diff --git a/arch/src/x86_64/mod.rs b/arch/src/x86_64/mod.rs index 5d3941eab..5ca200702 100644 --- a/arch/src/x86_64/mod.rs +++ b/arch/src/x86_64/mod.rs @@ -37,7 +37,7 @@ use vm_memory::{ GuestMemoryRegion, }; -use crate::{GuestMemoryMmap, InitramfsConfig, RegionType}; +use crate::{CpuProfile, GuestMemoryMmap, InitramfsConfig, RegionType}; // While modern architectures support more than 255 CPUs via x2APIC, // legacy devices such as mptable support at most 254 CPUs. @@ -99,6 +99,7 @@ pub struct CpuidConfig { #[cfg(feature = "tdx")] pub tdx: bool, pub amx: bool, + pub profile: CpuProfile, } #[derive(Debug, Error)] diff --git a/cloud-hypervisor/src/main.rs b/cloud-hypervisor/src/main.rs index 8fb9a8318..750f7aba9 100644 --- a/cloud-hypervisor/src/main.rs +++ b/cloud-hypervisor/src/main.rs @@ -985,6 +985,7 @@ mod unit_tests { features: CpuFeatures::default(), nested: true, core_scheduling: CoreScheduling::Vm, + profile: Default::default(), }, memory: MemoryConfig { size: 536_870_912, diff --git a/fuzz/fuzz_targets/http_api.rs b/fuzz/fuzz_targets/http_api.rs index a4687f490..16957983e 100644 --- a/fuzz/fuzz_targets/http_api.rs +++ b/fuzz/fuzz_targets/http_api.rs @@ -136,6 +136,7 @@ impl RequestHandler for StubApiRequestHandler { max_phys_bits: 46, affinity: None, features: CpuFeatures::default(), + profile: Default::default(), nested: true, core_scheduling: CoreScheduling::default(), }, diff --git a/vmm/src/config.rs b/vmm/src/config.rs index 40f043a51..c9ba9c064 100644 --- a/vmm/src/config.rs +++ b/vmm/src/config.rs @@ -11,6 +11,7 @@ use std::result; use std::str::FromStr; use std::sync::LazyLock; +use arch::CpuProfile; use block::ImageType; use clap::ArgMatches; use log::{debug, warn}; @@ -697,7 +698,8 @@ impl CpusConfig { .add("affinity") .add("features") .add("nested") - .add("core_scheduling"); + .add("core_scheduling") + .add("profile"); parser.parse(cpus).map_err(Error::ParseCpus)?; let boot_vcpus: u32 = parser @@ -729,6 +731,12 @@ impl CpusConfig { }) .collect() }); + + let profile = parser + .convert::("profile") + .map_err(Error::ParseCpus)? + .unwrap_or_default(); + let features_list = parser .convert::("features") .map_err(Error::ParseCpus)? @@ -771,6 +779,7 @@ impl CpusConfig { features, nested, core_scheduling, + profile, }) } } diff --git a/vmm/src/cpu.rs b/vmm/src/cpu.rs index 6a905d837..e7a6056e8 100644 --- a/vmm/src/cpu.rs +++ b/vmm/src/cpu.rs @@ -963,6 +963,7 @@ impl CpuManager { #[cfg(feature = "tdx")] tdx, amx: self.config.features.amx, + profile: self.config.profile, }, ) .map_err(Error::CommonCpuId)? diff --git a/vmm/src/lib.rs b/vmm/src/lib.rs index 58abd061f..548eb23fe 100644 --- a/vmm/src/lib.rs +++ b/vmm/src/lib.rs @@ -1428,17 +1428,27 @@ impl Vmm { ))); } - let amx = vm_config.lock().unwrap().cpus.features.amx; - let phys_bits = - vm::physical_bits(hypervisor, vm_config.lock().unwrap().cpus.max_phys_bits); + let (amx, max_phys_bits, profile, kvm_hyperv) = { + let guard = vm_config.lock().unwrap(); + ( + 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( hypervisor, &arch::CpuidConfig { phys_bits, - kvm_hyperv: vm_config.lock().unwrap().cpus.kvm_hyperv, + kvm_hyperv, #[cfg(feature = "tdx")] tdx: false, amx, + profile, }, ) .map_err(|e| { @@ -1584,6 +1594,7 @@ impl Vmm { #[cfg(feature = "tdx")] tdx: false, amx: vm_config.cpus.features.amx, + profile: vm_config.cpus.profile, }, ) .map_err(|e| { @@ -2653,6 +2664,8 @@ const DEVICE_MANAGER_SNAPSHOT_ID: &str = "device-manager"; mod unit_tests { use std::path::PathBuf; + use arch::CpuProfile; + use super::*; #[cfg(target_arch = "x86_64")] use crate::vm_config::DebugConsoleConfig; @@ -2690,6 +2703,7 @@ mod unit_tests { features: CpuFeatures::default(), nested: true, core_scheduling: CoreScheduling::default(), + profile: CpuProfile::default(), }, memory: MemoryConfig { size: 536_870_912, diff --git a/vmm/src/vm.rs b/vmm/src/vm.rs index cfcb71fa1..69d02e07b 100644 --- a/vmm/src/vm.rs +++ b/vmm/src/vm.rs @@ -3359,19 +3359,28 @@ impl Snapshottable for Vm { #[cfg(all(feature = "kvm", target_arch = "x86_64"))] let common_cpuid = { - let amx = self.config.lock().unwrap().cpus.features.amx; - let phys_bits = physical_bits( - self.hypervisor.as_ref(), - self.config.lock().unwrap().cpus.max_phys_bits, - ); + let (amx, max_phys_bits, kvm_hyperv, profile) = { + let guard = self.config.lock().unwrap(); + let VmConfig { cpus, .. } = &*guard; + ( + 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( self.hypervisor.as_ref(), &arch::CpuidConfig { phys_bits, - kvm_hyperv: self.config.lock().unwrap().cpus.kvm_hyperv, + kvm_hyperv, #[cfg(feature = "tdx")] tdx: false, amx, + profile, }, ) .map_err(|e| { diff --git a/vmm/src/vm_config.rs b/vmm/src/vm_config.rs index b6f0eb17f..745ae0d69 100644 --- a/vmm/src/vm_config.rs +++ b/vmm/src/vm_config.rs @@ -9,6 +9,7 @@ use std::path::{Path, PathBuf}; use std::str::FromStr; use std::{fs, result}; +use arch::CpuProfile; use block::ImageType; pub use block::fcntl::LockGranularityChoice; use log::{debug, warn}; @@ -84,6 +85,9 @@ pub struct CpusConfig { pub nested: bool, #[serde(default)] pub core_scheduling: CoreScheduling, + // Defaults to "Host" if no profile is given. + #[serde(default)] + pub profile: CpuProfile, } pub const DEFAULT_VCPUS: u32 = 1; @@ -100,6 +104,7 @@ impl Default for CpusConfig { features: CpuFeatures::default(), nested: true, core_scheduling: CoreScheduling::default(), + profile: CpuProfile::default(), } } }