diff --git a/CHANGELOG.md b/CHANGELOG.md index 3bc0eebe51e..687547c87d9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -17,6 +17,8 @@ - Updated deserialization of `bitmap` for custom CPU templates to allow usage of '_' as a separator. +- Set FDP_EXCPTN_ONLY bit (CPUID.7h.0:EBX[6]) and ZERO_FCS_FDS bit + (CPUID.7h.0:EBX[13]) in Intel's CPUID normalization process. ### Fixed diff --git a/docs/cpu_templates/cpuid-normalization.md b/docs/cpu_templates/cpuid-normalization.md index 96779454a26..a9ef1ac538c 100644 --- a/docs/cpu_templates/cpuid-normalization.md +++ b/docs/cpu_templates/cpuid-normalization.md @@ -30,10 +30,12 @@ See also: [boot protocol settings](boot-protocol.md) ## Intel-specific CPUID normalization | Description | Leaf | Subleaf | Register | Bits | -|----------------------------------------------------------------|:----------------------------------:|:-------:|:------------------:|:----:| +|----------------------------------------------------------------|:----------------------------------:|:-------:|:------------------:|:-----:| | Update deterministic cache parameters | 0x4 | all | EAX | 31:14 | | Disable Intel Turbo Boost technology | 0x6 | - | EAX | 1 | | Disable frequency selection | 0x6 | - | ECX | 3 | +| Set FDP_EXCPTN_ONLY bit | 0x7 | 0x0 | EBX | 6 | +| Set "Deprecates FPU CS and FPU DS values" bit | 0x7 | 0x0 | EBX | 13 | | Disable performance monitoring | 0xa | - | EAX, EBX, ECX, EDX | all | | Update brand string to use a default format and real frequency | 0x80000002, 0x80000003, 0x80000004 | - | EAX, EBX, ECX, EDX | all | diff --git a/resources/tests/cpu_template_helper/fingerprint_INTEL_CASCADELAKE_4.14host.json b/resources/tests/cpu_template_helper/fingerprint_INTEL_CASCADELAKE_4.14host.json index a374f199139..fb607d2ba8c 100644 --- a/resources/tests/cpu_template_helper/fingerprint_INTEL_CASCADELAKE_4.14host.json +++ b/resources/tests/cpu_template_helper/fingerprint_INTEL_CASCADELAKE_4.14host.json @@ -270,7 +270,7 @@ }, { "register": "ebx", - "bitmap": "0b11010001100111110100011110101011" + "bitmap": "0b11010001100111110110011111101011" }, { "register": "ecx", diff --git a/resources/tests/cpu_template_helper/fingerprint_INTEL_CASCADELAKE_5.10host.json b/resources/tests/cpu_template_helper/fingerprint_INTEL_CASCADELAKE_5.10host.json index 82fb6df4c50..a9e5e29772a 100644 --- a/resources/tests/cpu_template_helper/fingerprint_INTEL_CASCADELAKE_5.10host.json +++ b/resources/tests/cpu_template_helper/fingerprint_INTEL_CASCADELAKE_5.10host.json @@ -270,7 +270,7 @@ }, { "register": "ebx", - "bitmap": "0b11010001100111110100011110101011" + "bitmap": "0b11010001100111110110011111101011" }, { "register": "ecx", diff --git a/resources/tests/cpu_template_helper/fingerprint_INTEL_ICELAKE_4.14host.json b/resources/tests/cpu_template_helper/fingerprint_INTEL_ICELAKE_4.14host.json index 1b10a337395..0578dc947e1 100644 --- a/resources/tests/cpu_template_helper/fingerprint_INTEL_ICELAKE_4.14host.json +++ b/resources/tests/cpu_template_helper/fingerprint_INTEL_ICELAKE_4.14host.json @@ -270,7 +270,7 @@ }, { "register": "ebx", - "bitmap": "0b11110001101111110000011110101011" + "bitmap": "0b11110001101111110010011111101011" }, { "register": "ecx", diff --git a/resources/tests/cpu_template_helper/fingerprint_INTEL_ICELAKE_5.10host.json b/resources/tests/cpu_template_helper/fingerprint_INTEL_ICELAKE_5.10host.json index 3146f827e78..686d53682b2 100644 --- a/resources/tests/cpu_template_helper/fingerprint_INTEL_ICELAKE_5.10host.json +++ b/resources/tests/cpu_template_helper/fingerprint_INTEL_ICELAKE_5.10host.json @@ -270,7 +270,7 @@ }, { "register": "ebx", - "bitmap": "0b11110001101111110000011110101011" + "bitmap": "0b11110001101111110010011111101011" }, { "register": "ecx", diff --git a/resources/tests/cpu_template_helper/fingerprint_INTEL_SKYLAKE_4.14host.json b/resources/tests/cpu_template_helper/fingerprint_INTEL_SKYLAKE_4.14host.json index 7b304265438..8c080cc7de9 100644 --- a/resources/tests/cpu_template_helper/fingerprint_INTEL_SKYLAKE_4.14host.json +++ b/resources/tests/cpu_template_helper/fingerprint_INTEL_SKYLAKE_4.14host.json @@ -270,7 +270,7 @@ }, { "register": "ebx", - "bitmap": "0b11010001100111110100111110111011" + "bitmap": "0b11010001100111110110111111111011" }, { "register": "ecx", diff --git a/resources/tests/cpu_template_helper/fingerprint_INTEL_SKYLAKE_5.10host.json b/resources/tests/cpu_template_helper/fingerprint_INTEL_SKYLAKE_5.10host.json index b6868763d78..a2efd03bd66 100644 --- a/resources/tests/cpu_template_helper/fingerprint_INTEL_SKYLAKE_5.10host.json +++ b/resources/tests/cpu_template_helper/fingerprint_INTEL_SKYLAKE_5.10host.json @@ -270,7 +270,7 @@ }, { "register": "ebx", - "bitmap": "0b11010001100111110100111110111011" + "bitmap": "0b11010001100111110110111111111011" }, { "register": "ecx", diff --git a/resources/tests/static_cpu_templates/c3.json b/resources/tests/static_cpu_templates/c3.json index 164815459a8..dcaebe0e5f5 100644 --- a/resources/tests/static_cpu_templates/c3.json +++ b/resources/tests/static_cpu_templates/c3.json @@ -26,7 +26,7 @@ "modifiers": [ { "register": "ebx", - "bitmap": "0b000000000x0x000000x000x0x00000xx" + "bitmap": "0b000000000x0x000000x000x0xx0000xx" }, { "register": "ecx", diff --git a/resources/tests/static_cpu_templates/t2.json b/resources/tests/static_cpu_templates/t2.json index 3d4ef835609..907c76f1274 100644 --- a/resources/tests/static_cpu_templates/t2.json +++ b/resources/tests/static_cpu_templates/t2.json @@ -26,7 +26,7 @@ "modifiers": [ { "register": "ebx", - "bitmap": "0b00000000000x000000000x1xx0x0x0xx" + "bitmap": "0b00000000000x000000x00x1xxxx0x0xx" }, { "register": "ecx", diff --git a/resources/tests/static_cpu_templates/t2a.json b/resources/tests/static_cpu_templates/t2a.json index 8d0eb36f39c..b25b1011378 100644 --- a/resources/tests/static_cpu_templates/t2a.json +++ b/resources/tests/static_cpu_templates/t2a.json @@ -26,7 +26,7 @@ "modifiers": [ { "register": "ebx", - "bitmap": "0b00000000000x000000000x1xx0x0x0xx" + "bitmap": "0b00000000000x000000x00x1xxxx0x0xx" }, { "register": "ecx", diff --git a/resources/tests/static_cpu_templates/t2cl.json b/resources/tests/static_cpu_templates/t2cl.json index fca11e1d360..96e7e641909 100644 --- a/resources/tests/static_cpu_templates/t2cl.json +++ b/resources/tests/static_cpu_templates/t2cl.json @@ -26,7 +26,7 @@ "modifiers": [ { "register": "ebx", - "bitmap": "0b00000000000x000000000x1xx0x0x0xx" + "bitmap": "0b00000000000x000000x00x1xxxx0x0xx" }, { "register": "ecx", diff --git a/resources/tests/static_cpu_templates/t2s.json b/resources/tests/static_cpu_templates/t2s.json index bb4dd8358a9..fe9d2024681 100644 --- a/resources/tests/static_cpu_templates/t2s.json +++ b/resources/tests/static_cpu_templates/t2s.json @@ -26,7 +26,7 @@ "modifiers": [ { "register": "ebx", - "bitmap": "0b00000000000x000000000x1xx0x0x0xx" + "bitmap": "0b00000000000x000000x00x1xxxx0x0xx" }, { "register": "ecx", 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 59ae40f59c2..ebee7058cc9 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 @@ -18,6 +18,9 @@ pub enum NormalizeCpuidError { /// Leaf 0x6 is missing from CPUID. #[error("Leaf 0x6 is missing from CPUID.")] MissingLeaf6, + /// Leaf 0x7 / subleaf 0 is missing from CPUID. + #[error("Leaf 0x7 / subleaf 0 is missing from CPUID.")] + MissingLeaf7, /// Leaf 0xA is missing from CPUID. #[error("Leaf 0xA is missing from CPUID.")] MissingLeafA, @@ -85,6 +88,7 @@ impl super::IntelCpuid { ) -> Result<(), NormalizeCpuidError> { self.update_deterministic_cache_entry(cpu_count, cpus_per_core)?; self.update_power_management_entry()?; + self.update_extended_feature_flags_entry()?; self.update_performance_monitoring_entry()?; self.update_brand_string_entry()?; @@ -197,6 +201,22 @@ impl super::IntelCpuid { Ok(()) } + /// Update structured extended feature flags enumeration leaf + 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)?; + + // Set FDP_EXCPTN_ONLY bit (bit 6) and ZERO_FCS_FDS bit (bit 13) as recommended in kernel + // doc. These bits are reserved in AMD. + // https://lore.kernel.org/all/20220322110712.222449-3-pbonzini@redhat.com/ + // https://github.com/torvalds/linux/commit/45016721de3c714902c6f475b705e10ae0bdd801 + set_bit(&mut leaf_7_0.result.ebx, 6, true); + set_bit(&mut leaf_7_0.result.ebx, 13, true); + + Ok(()) + } + /// Update performance monitoring entry fn update_performance_monitoring_entry(&mut self) -> Result<(), NormalizeCpuidError> { let leaf_a = self @@ -422,4 +442,30 @@ mod tests { }), ); } + + #[test] + fn test_update_extended_feature_flags_entry() { + let mut cpuid = + crate::cpu_config::x86_64::cpuid::IntelCpuid(std::collections::BTreeMap::from([( + crate::cpu_config::x86_64::cpuid::CpuidKey { + leaf: 0x7, + subleaf: 0, + }, + crate::cpu_config::x86_64::cpuid::CpuidEntry { + flags: crate::cpu_config::x86_64::cpuid::KvmCpuidFlags::SIGNIFICANT_INDEX, + ..Default::default() + }, + )])); + + cpuid.update_extended_feature_flags_entry().unwrap(); + + let leaf_7_0 = cpuid + .get(&crate::cpu_config::x86_64::cpuid::CpuidKey { + leaf: 0x7, + subleaf: 0, + }) + .unwrap(); + assert!((leaf_7_0.result.ebx & (1 << 6)) > 0); + assert!((leaf_7_0.result.ebx & (1 << 13)) > 0); + } } diff --git a/src/vmm/src/cpu_config/x86_64/static_cpu_templates/c3.rs b/src/vmm/src/cpu_config/x86_64/static_cpu_templates/c3.rs index cb336208445..3a6e89cc505 100644 --- a/src/vmm/src/cpu_config/x86_64/static_cpu_templates/c3.rs +++ b/src/vmm/src/cpu_config/x86_64/static_cpu_templates/c3.rs @@ -128,7 +128,6 @@ pub fn c3() -> CustomCpuTemplate { // - Bit 03: BMI1 // - Bit 04: HLE // - Bit 05: AVX2 - // - Bit 06: FDP_EXCPTN_ONLY // - Bit 08: BMI2 // - Bit 10: INVPCID // - Bit 11: RTM @@ -152,7 +151,7 @@ pub fn c3() -> CustomCpuTemplate { CpuidRegisterModifier { register: CpuidRegister::Ebx, bitmap: RegisterValueFilter { - filter: 0b1111_1111_1010_1111_1101_1101_0111_1100, + filter: 0b1111_1111_1010_1111_1101_1101_0011_1100, value: 0b0000_0000_0000_0000_0000_0000_0000_0000, }, }, diff --git a/src/vmm/src/cpu_config/x86_64/static_cpu_templates/t2.rs b/src/vmm/src/cpu_config/x86_64/static_cpu_templates/t2.rs index cec36adcbbb..731c699f79c 100644 --- a/src/vmm/src/cpu_config/x86_64/static_cpu_templates/t2.rs +++ b/src/vmm/src/cpu_config/x86_64/static_cpu_templates/t2.rs @@ -128,11 +128,9 @@ pub fn t2() -> CustomCpuTemplate { // EBX: // - Bit 02: SGX // - Bit 04: HLE - // - Bit 06: FDP_EXCPTN_ONLY // - Bit 09: Enhanced REP MOVSB/STOSB // - Bit 11: RTM // - Bit 12: RDT-M - // - Bit 13: Deprecates FPU CS and FPU DS // - Bit 14: MPX // - Bit 15: RDT-A // - Bit 16: AVX512F @@ -153,7 +151,7 @@ pub fn t2() -> CustomCpuTemplate { CpuidRegisterModifier { register: CpuidRegister::Ebx, bitmap: RegisterValueFilter { - filter: 0b1111_1111_1110_1111_1111_1010_0101_0100, + filter: 0b1111_1111_1110_1111_1101_1010_0001_0100, value: 0b0000_0000_0000_0000_0000_0010_0000_0000, }, }, diff --git a/src/vmm/src/cpu_config/x86_64/static_cpu_templates/t2a.rs b/src/vmm/src/cpu_config/x86_64/static_cpu_templates/t2a.rs index e00e1c96ebd..a4b93c7c590 100644 --- a/src/vmm/src/cpu_config/x86_64/static_cpu_templates/t2a.rs +++ b/src/vmm/src/cpu_config/x86_64/static_cpu_templates/t2a.rs @@ -85,11 +85,9 @@ pub fn t2a() -> CustomCpuTemplate { // EBX: // - Bit 02: Reserved (AMD APM) / SGX (Intel SDM) // - Bit 04: Reserved (AMD APM) / HLE (Intel SDM) - // - Bit 06: Reserved (AMD APM) / FDP_EXCPTN_ONLY (Intel SDM) // - Bit 09: Reserved (AMD APM) / Enhanced REP MOVSB/STOSB (Intel SDM) // - Bit 11: Reserved (AMD APM) / RTM (Intel SDM) // - Bit 12: PQM (AMD APM) / RDT-M (Intel SDM) - // - Bit 13: Reserved (AMD APM) / Deprecates FPU CS and FPU DS (Intel SDM) // - Bit 14: Reserved (AMD APM) / MPX (Intel SDM) // - Bit 15: PQE (AMD APM) / RDT-A (Intel SDM) // - Bit 16: Reserved (AMD APM) / AVX512F (Intel SDM) @@ -112,7 +110,7 @@ pub fn t2a() -> CustomCpuTemplate { CpuidRegisterModifier { register: CpuidRegister::Ebx, bitmap: RegisterValueFilter { - filter: 0b1111_1111_1110_1111_1111_1010_0101_0100, + filter: 0b1111_1111_1110_1111_1101_1010_0001_0100, value: 0b0000_0000_0000_0000_0000_0010_0000_0000, }, }, diff --git a/src/vmm/src/cpu_config/x86_64/static_cpu_templates/t2cl.rs b/src/vmm/src/cpu_config/x86_64/static_cpu_templates/t2cl.rs index 07353ab22b0..405ea654e47 100644 --- a/src/vmm/src/cpu_config/x86_64/static_cpu_templates/t2cl.rs +++ b/src/vmm/src/cpu_config/x86_64/static_cpu_templates/t2cl.rs @@ -86,11 +86,9 @@ pub fn t2cl() -> CustomCpuTemplate { // EBX: // - Bit 02: SGX (Intel SDM) / Reserved (AMD APM) // - Bit 04: HLE (Intel SDM) / Reserved (AMD APM) - // - Bit 06: FDP_EXCPTN_ONLY (Intel SDM) / Reserved (AMD APM) // - Bit 09: Enhanced REP MOVSB/STOSB (Intel SDM) / Reserved (AMD APM) // - Bit 11: RTM (Intel SDM) / Reserved (AMD APM) // - Bit 12: RDT-M (Intel SDM) / PQM (AMD APM) - // - Bit 13: Deprecates FPU CS and FPU DS (Intel SDM) / Reserved (AMD APM) // - Bit 14: MPX (Intel SDM) / Reserved (AMD APM) // - Bit 15: RDT-A (Intel SDM) / PQE (AMD APM) // - Bit 16: AVX512F (Intel SDM) / Reserved (AMD APM) @@ -113,7 +111,7 @@ pub fn t2cl() -> CustomCpuTemplate { CpuidRegisterModifier { register: CpuidRegister::Ebx, bitmap: RegisterValueFilter { - filter: 0b1111_1111_1110_1111_1111_1010_0101_0100, + filter: 0b1111_1111_1110_1111_1101_1010_0001_0100, value: 0b0000_0000_0000_0000_0000_0010_0000_0000, }, }, diff --git a/src/vmm/src/cpu_config/x86_64/static_cpu_templates/t2s.rs b/src/vmm/src/cpu_config/x86_64/static_cpu_templates/t2s.rs index ab709a6e726..6f2b56cc0cb 100644 --- a/src/vmm/src/cpu_config/x86_64/static_cpu_templates/t2s.rs +++ b/src/vmm/src/cpu_config/x86_64/static_cpu_templates/t2s.rs @@ -85,11 +85,9 @@ pub fn t2s() -> CustomCpuTemplate { // EBX: // - Bit 02: SGX // - Bit 04: HLE - // - Bit 06: FDP_EXCPTN_ONLY // - Bit 09: Enhanced REP MOVSB/STOSB // - Bit 11: RTM // - Bit 12: RDT-M - // - Bit 13: Deprecates FPU CS and FPU DS // - Bit 14: MPX // - Bit 15: RDT-A // - Bit 16: AVX512F @@ -110,7 +108,7 @@ pub fn t2s() -> CustomCpuTemplate { CpuidRegisterModifier { register: CpuidRegister::Ebx, bitmap: RegisterValueFilter { - filter: 0b1111_1111_1110_1111_1111_1010_0101_0100, + filter: 0b1111_1111_1110_1111_1101_1010_0001_0100, value: 0b0000_0000_0000_0000_0000_0010_0000_0000, }, }, diff --git a/tests/integration_tests/functional/test_cpu_features.py b/tests/integration_tests/functional/test_cpu_features.py index 82610e7be8e..f8bf52b5efd 100644 --- a/tests/integration_tests/functional/test_cpu_features.py +++ b/tests/integration_tests/functional/test_cpu_features.py @@ -821,7 +821,6 @@ def check_masked_features(test_microvm, cpu_template): (1 << 3) | # BMI1 (1 << 4) | # HLE (1 << 5) | # AVX2 - (1 << 6) | # FPDP (1 << 8) | # BMI2 (1 << 10) | # INVPCID (1 << 11) | # RTM @@ -907,7 +906,6 @@ def check_masked_features(test_microvm, cpu_template): (0x7, 0x0, "ebx", (1 << 2) | # SGX (1 << 4) | # HLE - (1 << 6) | # FPDP (1 << 11) | # RTM (1 << 12) | # RDT_M (1 << 14) | # MPX