From 6bd7969601117b46caf0e2a7176c0bd2d4877393 Mon Sep 17 00:00:00 2001 From: mert-kurttutan Date: Wed, 17 Jul 2024 22:39:44 +0200 Subject: [PATCH] Implemented Extended Features for Subleaf Ecx=0x1 - Implementation - Modify Test Cases based on new features. --- src/lib.rs | 102 ++++++++++++++++++++++++++++++++++++ src/tests/i5_3337u.rs | 16 ++++++ src/tests/ryzen_matisse.rs | 1 + src/tests/xeon_gold_6252.rs | 1 + 4 files changed, 120 insertions(+) diff --git a/src/lib.rs b/src/lib.rs index 5e44439..31ab295 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -511,11 +511,16 @@ impl CpuId { pub fn get_extended_feature_info(&self) -> Option { if self.leaf_is_supported(EAX_STRUCTURED_EXTENDED_FEATURE_INFO) { let res = self.read.cpuid1(EAX_STRUCTURED_EXTENDED_FEATURE_INFO); + let res1 = self.read.cpuid2(EAX_STRUCTURED_EXTENDED_FEATURE_INFO, 1); Some(ExtendedFeatures { _eax: res.eax, ebx: ExtendedFeaturesEbx::from_bits_truncate(res.ebx), ecx: ExtendedFeaturesEcx::from_bits_truncate(res.ecx), edx: ExtendedFeaturesEdx::from_bits_truncate(res.edx), + eax1: ExtendedFeaturesEax1::from_bits_truncate(res1.eax), + _ebx1: res1.ebx, + _ecx1: res1.ecx, + edx1: ExtendedFeaturesEdx1::from_bits_truncate(res1.edx), }) } else { None @@ -3219,6 +3224,10 @@ pub struct ExtendedFeatures { ebx: ExtendedFeaturesEbx, ecx: ExtendedFeaturesEcx, edx: ExtendedFeaturesEdx, + eax1: ExtendedFeaturesEax1, + _ebx1: u32, + _ecx1: u32, + edx1: ExtendedFeaturesEdx1, } impl ExtendedFeatures { @@ -3728,6 +3737,69 @@ impl ExtendedFeatures { pub const fn has_amx_int8(&self) -> bool { self.edx.contains(ExtendedFeaturesEdx::AMX_INT8) } + + /// Supports AVX_VNNI. + /// + /// # Platforms + /// ❌ AMD (reserved) ✅ Intel + #[inline] + pub const fn has_avx_vnni(&self) -> bool { + self.eax1.contains(ExtendedFeaturesEax1::AVX_VNNI) + } + + /// Supports AVX512_BF16. + /// + /// # Platforms + /// ❌ AMD (reserved) ✅ Intel + #[inline] + pub const fn has_avx512_bf16(&self) -> bool { + self.eax1.contains(ExtendedFeaturesEax1::AVX512_BF16) + } + + /// Supports Fast zero-length REP MOVSB + /// + /// # Platforms + /// ❌ AMD (reserved) ✅ Intel + #[inline] + pub const fn has_fzrm(&self) -> bool { + self.eax1.contains(ExtendedFeaturesEax1::FZRM) + } + + /// Supports Fast Short REP STOSB + /// + /// # Platforms + /// ❌ AMD (reserved) ✅ Intel + #[inline] + pub const fn has_fsrs(&self) -> bool { + self.eax1.contains(ExtendedFeaturesEax1::FSRS) + } + + /// Supports Fast Short REP CMPSB, REP SCASB + /// + /// # Platforms + /// ❌ AMD (reserved) ✅ Intel + #[inline] + pub const fn has_fsrcrs(&self) -> bool { + self.eax1.contains(ExtendedFeaturesEax1::FSRCRS) + } + + /// Supports HRESET + /// + /// # Platforms + /// ❌ AMD (reserved) ✅ Intel + #[inline] + pub const fn has_hreset(&self) -> bool { + self.eax1.contains(ExtendedFeaturesEax1::HRESET) + } + + /// Supports CET_SSS + /// + /// # Platforms + /// ❌ AMD (reserved) ✅ Intel + #[inline] + pub const fn has_cet_sss(&self) -> bool { + self.edx1.contains(ExtendedFeaturesEdx1::CET_SSS) + } } impl Debug for ExtendedFeatures { @@ -3886,6 +3958,36 @@ bitflags! { } } +bitflags! { + #[repr(transparent)] + #[derive(Debug, Clone, Copy, PartialEq, Eq)] + struct ExtendedFeaturesEax1: u32 { + // Some of the Unimplemented bits are reserved and maybe release in future CPUs, see Intel SDM for future features (Date of comment: 07.17.2024) + /// Bit 04: AVX_VNNI. AVX (VEX-encoded) versions of the Vector Neural Network Instructions. + const AVX_VNNI = 1 << 4; + /// Bit 05: AVX512_BF16. Vector Neural Network Instructions supporting BFLOAT16 inputs and conversion instructions from IEEE single precision. + const AVX512_BF16 = 1 << 5; + /// Bit 10: If 1, supports fast zero-length REP MOVSB. + const FZRM = 1 << 10; + /// Bit 11: If 1, supports fast short REP STOSB. + const FSRS = 1 << 11; + /// Bit 12: If 1, supports fast short REP CMPSB, REP SCASB. + const FSRCRS = 1 << 12; + /// Bit 22: If 1, supports history reset via the HRESET instruction and the IA32_HRESET_ENABLE MSR. When set, indicates that the Processor History Reset Leaf (EAX = 20H) is valid. + const HRESET = 1 << 22; + } +} + +bitflags! { + #[repr(transparent)] + #[derive(Debug, Clone, Copy, PartialEq, Eq)] + struct ExtendedFeaturesEdx1: u32 { + // Some of the Unimplemented bits are reserved and maybe release in future CPUs, see Intel SDM for future features (Date of comment: 07.17.2024) + /// Bit 18: CET_SSS. If 1, indicates that an operating system can enable supervisor shadow stacks as long as it ensures that a supervisor shadow stack cannot become prematurely busy due to page faults + const CET_SSS = 1 << 18; + } +} + /// Direct cache access info (LEAF=0x09). /// /// # Platforms diff --git a/src/tests/i5_3337u.rs b/src/tests/i5_3337u.rs index a715746..f4b56c8 100644 --- a/src/tests/i5_3337u.rs +++ b/src/tests/i5_3337u.rs @@ -240,6 +240,10 @@ fn extended_features() { ebx: ExtendedFeaturesEbx::from_bits_truncate(641), ecx: ExtendedFeaturesEcx::from_bits_truncate(0), edx: ExtendedFeaturesEdx::from_bits_truncate(0), + eax1: ExtendedFeaturesEax1::from_bits_truncate(0), + _ebx1: 0, + _ecx1: 0, + edx1: ExtendedFeaturesEdx1::from_bits_truncate(0), }; assert!(tpfeatures._eax == 0); assert!(tpfeatures.has_fsgsbase()); @@ -274,6 +278,10 @@ fn extended_features() { | ExtendedFeaturesEbx::PROCESSOR_TRACE, ecx: ExtendedFeaturesEcx::from_bits_truncate(0), edx: ExtendedFeaturesEdx::from_bits_truncate(201326592), + eax1: ExtendedFeaturesEax1::from_bits_truncate(0), + _ebx1: 0, + _ecx1: 0, + edx1: ExtendedFeaturesEdx1::from_bits_truncate(0), }; assert!(tpfeatures2.has_fsgsbase()); @@ -299,6 +307,14 @@ fn extended_features() { assert!(!tpfeatures2.has_avx512_fp16()); assert!(!tpfeatures2.has_amx_tile()); assert!(!tpfeatures2.has_amx_int8()); + + assert!(!tpfeatures2.has_avx_vnni()); + assert!(!tpfeatures2.has_avx512_bf16()); + assert!(!tpfeatures2.has_fzrm()); + assert!(!tpfeatures2.has_fsrs()); + assert!(!tpfeatures2.has_fsrcrs()); + assert!(!tpfeatures2.has_hreset()); + assert!(!tpfeatures2.has_cet_sss()); } #[test] diff --git a/src/tests/ryzen_matisse.rs b/src/tests/ryzen_matisse.rs index 1d4d495..eaf8c1b 100644 --- a/src/tests/ryzen_matisse.rs +++ b/src/tests/ryzen_matisse.rs @@ -618,6 +618,7 @@ static CPUID_VALUE_MAP: phf::Map = phf_map! { 0x00000005_00000000u64 => CpuIdResult { eax: 0x00000040, ebx: 0x00000040, ecx: 0x00000003, edx: 0x00000011 }, 0x00000006_00000000u64 => CpuIdResult { eax: 0x00000004, ebx: 0x00000000, ecx: 0x00000001, edx: 0x00000000 }, 0x00000007_00000000u64 => CpuIdResult { eax: 0x00000000, ebx: 0x219c91a9, ecx: 0x00400004, edx: 0x00000000 }, + 0x00000007_00000001u64 => CpuIdResult { eax: 0x00000000, ebx: 0x00000000, ecx: 0x00000000, edx: 0x00000000 }, 0x00000008_00000000u64 => CpuIdResult { eax: 0x00000000, ebx: 0x00000000, ecx: 0x00000000, edx: 0x00000000 }, 0x00000009_00000000u64 => CpuIdResult { eax: 0x00000000, ebx: 0x00000000, ecx: 0x00000000, edx: 0x00000000 }, 0x0000000a_00000000u64 => CpuIdResult { eax: 0x00000000, ebx: 0x00000000, ecx: 0x00000000, edx: 0x00000000 }, diff --git a/src/tests/xeon_gold_6252.rs b/src/tests/xeon_gold_6252.rs index ce7d492..0a2377a 100644 --- a/src/tests/xeon_gold_6252.rs +++ b/src/tests/xeon_gold_6252.rs @@ -548,6 +548,7 @@ static CPUID_VALUE_MAP: phf::Map = phf_map! { 0x00000005_00000000u64 => CpuIdResult { eax: 0x00000040, ebx: 0x00000040, ecx: 0x00000003, edx: 0x00002020 }, 0x00000006_00000000u64 => CpuIdResult { eax: 0x00000077, ebx: 0x00000002, ecx: 0x00000009, edx: 0x00000000 }, 0x00000007_00000000u64 => CpuIdResult { eax: 0x00000000, ebx: 0xd39ff7eb, ecx: 0x00000818, edx: 0xbc000400 }, + 0x00000007_00000001u64 => CpuIdResult { eax: 0x00000000, ebx: 0x00000000, ecx: 0x00000000, edx: 0x00000000 }, 0x00000008_00000000u64 => CpuIdResult { eax: 0x00000000, ebx: 0x00000000, ecx: 0x00000000, edx: 0x00000000 }, 0x00000009_00000000u64 => CpuIdResult { eax: 0x00000000, ebx: 0x00000000, ecx: 0x00000000, edx: 0x00000000 }, 0x0000000a_00000000u64 => CpuIdResult { eax: 0x07300404, ebx: 0x00000000, ecx: 0x00000000, edx: 0x00000603 },