diff --git a/CHANGELOG.md b/CHANGELOG.md index ead297b7b84..8f20df232d7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -21,6 +21,9 @@ and this project adheres to so users need to regenerate snapshots. - [#4731](https://github.com/firecracker-microvm/firecracker/pull/4731): Added support for modifying the host TAP device name during snapshot restore. +- [#5186](https://github.com/firecracker-microvm/firecracker/pull/5186): Pass + through CPUID leaves 15h and 16h on Intel CPUs (Crystal clock, processor, and + and bus frequencies). ### Changed diff --git a/src/vmm/src/cpu_config/x86_64/cpuid/intel/normalize.rs b/src/vmm/src/cpu_config/x86_64/cpuid/intel/normalize.rs index fa5e6766635..c742ca98741 100644 --- a/src/vmm/src/cpu_config/x86_64/cpuid/intel/normalize.rs +++ b/src/vmm/src/cpu_config/x86_64/cpuid/intel/normalize.rs @@ -5,7 +5,7 @@ use crate::cpu_config::x86_64::cpuid::normalize::{ CheckedAssignError, get_range, set_bit, set_range, }; use crate::cpu_config::x86_64::cpuid::{ - BRAND_STRING_LENGTH, CpuidKey, CpuidRegisters, CpuidTrait, MissingBrandStringLeaves, + BRAND_STRING_LENGTH, CpuidKey, CpuidRegisters, CpuidTrait, MissingBrandStringLeaves, cpuid, host_brand_string, }; @@ -14,12 +14,8 @@ use crate::cpu_config::x86_64::cpuid::{ pub enum NormalizeCpuidError { /// Failed to set deterministic cache leaf: {0} DeterministicCache(#[from] DeterministicCacheError), - /// Leaf 0x6 is missing from CPUID. - MissingLeaf6, - /// Leaf 0x7 / subleaf 0 is missing from CPUID. - MissingLeaf7, - /// Leaf 0xA is missing from CPUID. - MissingLeafA, + /// Leaf {0} is missing from CPUID. + MissingLeaf(usize), /// Failed to get brand string: {0} GetBrandString(DefaultBrandStringError), /// Failed to set brand string: {0} @@ -75,10 +71,53 @@ impl super::IntelCpuid { self.update_performance_monitoring_entry()?; self.update_extended_topology_v2_entry(); self.update_brand_string_entry()?; + self.update_frequency_information(); Ok(()) } + /// Passes through the host value of cpuid leaves 15h and 16h if they + /// are not already configured via cpu template. + fn update_frequency_information(&mut self) { + let Some(leaf_15h) = self.get_mut(&CpuidKey::leaf(0x15)) else { + return; + }; + + if leaf_15h.result == CpuidRegisters::default() { + let host_leaf_15 = cpuid(0x15); + + // CPUID.15H:EAX[31:0] + // Ratio of TSC frequency to Core Crystal Clock frequency, denominator + leaf_15h.result.eax = host_leaf_15.eax; + // CPUID.15H:EBX[31:0] + // Ratio of TSC frequency to Core Crystal Clock frequency, numerator + leaf_15h.result.ebx = host_leaf_15.ebx; + // CPUID.15H:ECX[31:0] + // Core Crystal Clock frequency, in units of Hz + leaf_15h.result.ecx = host_leaf_15.ecx; + // edx is reserved + } + + let Some(leaf_16h) = self.get_mut(&CpuidKey::leaf(0x16)) else { + return; + }; + + if leaf_16h.result == CpuidRegisters::default() { + let host_leaf_16 = cpuid(0x16); + + // CPUID.16H:EAX[15:0] + // Processor Base Frequency (in MHz) + leaf_16h.result.eax = host_leaf_16.eax; + // CPUID.16H:EBX[15:0] + // Processor Maximum Frequency (in MHz) + leaf_16h.result.ebx = host_leaf_16.ebx; + // CPUID.16H:ECX[15:0] + // Bus/Reference frequency (in MHz) + leaf_16h.result.ecx = host_leaf_16.ecx; + // edx is reserved + } + } + /// Update deterministic cache entry #[allow(clippy::unwrap_in_result)] fn update_deterministic_cache_entry( @@ -164,7 +203,7 @@ impl super::IntelCpuid { fn update_power_management_entry(&mut self) -> Result<(), NormalizeCpuidError> { let leaf_6 = self .get_mut(&CpuidKey::leaf(0x6)) - .ok_or(NormalizeCpuidError::MissingLeaf6)?; + .ok_or(NormalizeCpuidError::MissingLeaf(6))?; // CPUID.06H:EAX[1] // Intel Turbo Boost Technology available (see description of IA32_MISC_ENABLE[38]). @@ -184,7 +223,7 @@ impl super::IntelCpuid { fn update_extended_feature_flags_entry(&mut self) -> Result<(), NormalizeCpuidError> { let leaf_7_0 = self .get_mut(&CpuidKey::subleaf(0x7, 0)) - .ok_or(NormalizeCpuidError::MissingLeaf7)?; + .ok_or(NormalizeCpuidError::MissingLeaf(7))?; // Set the following bits as recommended in kernel doc. These bits are reserved in AMD. // - CPUID.07H:EBX[6] (FDP_EXCPTN_ONLY) @@ -243,7 +282,7 @@ impl super::IntelCpuid { fn update_performance_monitoring_entry(&mut self) -> Result<(), NormalizeCpuidError> { let leaf_a = self .get_mut(&CpuidKey::leaf(0xA)) - .ok_or(NormalizeCpuidError::MissingLeafA)?; + .ok_or(NormalizeCpuidError::MissingLeaf(0xA))?; leaf_a.result = CpuidRegisters { eax: 0, ebx: 0,