diff --git a/arch/src/x86_64/mod.rs b/arch/src/x86_64/mod.rs index a743b3000..1e1ad9346 100644 --- a/arch/src/x86_64/mod.rs +++ b/arch/src/x86_64/mod.rs @@ -629,6 +629,69 @@ pub fn check_required_kvm_extensions(kvm: &Kvm) -> super::Result<()> { Ok(()) } +pub fn update_cpuid_topology( + cpuid: &mut CpuId, + threads_per_core: u8, + cores_per_die: u8, + dies_per_package: u8, +) { + let thread_width = 8 - (threads_per_core - 1).leading_zeros(); + let core_width = (8 - (cores_per_die - 1).leading_zeros()) + thread_width; + let die_width = (8 - (dies_per_package - 1).leading_zeros()) + core_width; + + // CPU Topology leaf 0xb + CpuidPatch::set_cpuid_reg(cpuid, 0xb, Some(0), CpuidReg::EAX, thread_width); + CpuidPatch::set_cpuid_reg( + cpuid, + 0xb, + Some(0), + CpuidReg::EBX, + u32::from(threads_per_core), + ); + CpuidPatch::set_cpuid_reg(cpuid, 0xb, Some(0), CpuidReg::ECX, 1 << 8); + + CpuidPatch::set_cpuid_reg(cpuid, 0xb, Some(1), CpuidReg::EAX, die_width); + CpuidPatch::set_cpuid_reg( + cpuid, + 0xb, + Some(1), + CpuidReg::EBX, + u32::from(dies_per_package * cores_per_die * threads_per_core), + ); + CpuidPatch::set_cpuid_reg(cpuid, 0xb, Some(1), CpuidReg::ECX, 2 << 8); + + // CPU Topology leaf 0x1f + CpuidPatch::set_cpuid_reg(cpuid, 0x1f, Some(0), CpuidReg::EAX, thread_width); + CpuidPatch::set_cpuid_reg( + cpuid, + 0x1f, + Some(0), + CpuidReg::EBX, + u32::from(threads_per_core), + ); + CpuidPatch::set_cpuid_reg(cpuid, 0x1f, Some(0), CpuidReg::ECX, 1 << 8); + + CpuidPatch::set_cpuid_reg(cpuid, 0x1f, Some(1), CpuidReg::EAX, core_width); + CpuidPatch::set_cpuid_reg( + cpuid, + 0x1f, + Some(1), + CpuidReg::EBX, + u32::from(cores_per_die * threads_per_core), + ); + CpuidPatch::set_cpuid_reg(cpuid, 0x1f, Some(1), CpuidReg::ECX, 2 << 8); + + CpuidPatch::set_cpuid_reg(cpuid, 0x1f, Some(2), CpuidReg::EAX, die_width); + CpuidPatch::set_cpuid_reg( + cpuid, + 0x1f, + Some(2), + CpuidReg::EBX, + u32::from(dies_per_package * cores_per_die * threads_per_core), + ); + CpuidPatch::set_cpuid_reg(cpuid, 0x1f, Some(2), CpuidReg::ECX, 5 << 8); +} + #[cfg(test)] mod tests { use super::*; diff --git a/vmm/src/cpu.rs b/vmm/src/cpu.rs index dd0cc065f..edbeef563 100644 --- a/vmm/src/cpu.rs +++ b/vmm/src/cpu.rs @@ -11,7 +11,7 @@ // SPDX-License-Identifier: Apache-2.0 AND BSD-3-Clause // -use crate::config::CpusConfig; +use crate::config::{CpuTopology, CpusConfig}; use crate::device_manager::DeviceManager; use crate::CPU_MANAGER_SNAPSHOT_ID; #[cfg(feature = "acpi")] @@ -686,7 +686,7 @@ impl CpuManager { let device_manager = device_manager.lock().unwrap(); #[cfg(target_arch = "x86_64")] - let cpuid = CpuManager::patch_cpuid(kvm)?; + let cpuid = CpuManager::patch_cpuid(kvm, &config.topology)?; let cpu_manager = Arc::new(Mutex::new(CpuManager { config: config.clone(), #[cfg(target_arch = "x86_64")] @@ -725,7 +725,7 @@ impl CpuManager { } #[cfg(target_arch = "x86_64")] - fn patch_cpuid(kvm: &Kvm) -> Result { + fn patch_cpuid(kvm: &Kvm, topology: &Option) -> Result { let mut cpuid_patches = Vec::new(); // Patch tsc deadline timer bit @@ -757,6 +757,15 @@ impl CpuManager { CpuidPatch::patch_cpuid(&mut cpuid, cpuid_patches); + if let Some(t) = topology { + arch::x86_64::update_cpuid_topology( + &mut cpuid, + t.threads_per_core, + t.cores_per_die, + t.dies_per_package, + ); + } + Ok(cpuid) }