From f1801f0ca1550c1e86425e0b44022a17d0916523 Mon Sep 17 00:00:00 2001 From: Mykola Hohsadze Date: Mon, 31 Jan 2022 11:15:17 +0200 Subject: [PATCH] Fix list_cpu_features.exe does not detect SSE42 on Xeon X5650 (Windows) (#220) --- src/impl_x86__base_implementation.inl | 4 ++-- src/impl_x86_freebsd.c | 3 ++- src/impl_x86_linux_or_android.c | 3 ++- src/impl_x86_macos.c | 3 ++- src/impl_x86_windows.c | 11 ++++++++++- test/cpuinfo_x86_test.cc | 26 ++++++++++++++++++++++++++ 6 files changed, 44 insertions(+), 6 deletions(-) diff --git a/src/impl_x86__base_implementation.inl b/src/impl_x86__base_implementation.inl index 184c35a..e7991bd 100644 --- a/src/impl_x86__base_implementation.inl +++ b/src/impl_x86__base_implementation.inl @@ -246,7 +246,7 @@ typedef struct { // These two functions have to be implemented by the OS, that is the file // including this file. static void OverrideOsPreserves(OsPreserves* os_preserves); -static void DetectFeaturesFromOs(X86Features* features); +static void DetectFeaturesFromOs(X86Info* info, X86Features* features); // Reference https://en.wikipedia.org/wiki/CPUID. static void ParseCpuId(const Leaves* leaves, X86Info* info, @@ -371,7 +371,7 @@ static void ParseCpuId(const Leaves* leaves, X86Info* info, } else { // When XCR0 is not available (Atom based or older cpus) we need to defer to // the OS via custom code. - DetectFeaturesFromOs(features); + DetectFeaturesFromOs(info, features); // Now that we have queried the OS for SSE support, we report this back to // os_preserves. This is needed in case of AMD CPU's to enable testing of // sse4a (See ParseExtraAMDCpuId below). diff --git a/src/impl_x86_freebsd.c b/src/impl_x86_freebsd.c index 0777e29..ba6c6e3 100644 --- a/src/impl_x86_freebsd.c +++ b/src/impl_x86_freebsd.c @@ -28,7 +28,8 @@ static void OverrideOsPreserves(OsPreserves* os_preserves) { #include "internal/stack_line_reader.h" #include "internal/string_view.h" -static void DetectFeaturesFromOs(X86Features* features) { +static void DetectFeaturesFromOs(X86Info* info, X86Features* features) { + (void)info; // Handling FreeBSD platform through parsing /var/run/dmesg.boot. const int fd = CpuFeatures_OpenFile("/var/run/dmesg.boot"); if (fd >= 0) { diff --git a/src/impl_x86_linux_or_android.c b/src/impl_x86_linux_or_android.c index 9c9f49a..d6a2de4 100644 --- a/src/impl_x86_linux_or_android.c +++ b/src/impl_x86_linux_or_android.c @@ -27,7 +27,8 @@ static void OverrideOsPreserves(OsPreserves* os_preserves) { #include "internal/filesystem.h" #include "internal/stack_line_reader.h" #include "internal/string_view.h" -static void DetectFeaturesFromOs(X86Features* features) { +static void DetectFeaturesFromOs(X86Info* info, X86Features* features) { + (void)info; // Handling Linux platform through /proc/cpuinfo. const int fd = CpuFeatures_OpenFile("/proc/cpuinfo"); if (fd >= 0) { diff --git a/src/impl_x86_macos.c b/src/impl_x86_macos.c index 6133686..e5a5c35 100644 --- a/src/impl_x86_macos.c +++ b/src/impl_x86_macos.c @@ -42,7 +42,8 @@ static void OverrideOsPreserves(OsPreserves* os_preserves) { os_preserves->avx512_registers = GetDarwinSysCtlByName("hw.optional.avx512f"); } -static void DetectFeaturesFromOs(X86Features* features) { +static void DetectFeaturesFromOs(X86Info* info, X86Features* features) { + (void)info; // Handling Darwin platform through sysctlbyname. features->sse = GetDarwinSysCtlByName("hw.optional.sse"); features->sse2 = GetDarwinSysCtlByName("hw.optional.sse2"); diff --git a/src/impl_x86_windows.c b/src/impl_x86_windows.c index e970539..0b330d0 100644 --- a/src/impl_x86_windows.c +++ b/src/impl_x86_windows.c @@ -34,7 +34,7 @@ static bool GetWindowsIsProcessorFeaturePresent(DWORD ProcessorFeature) { } #endif -static void DetectFeaturesFromOs(X86Features* features) { +static void DetectFeaturesFromOs(X86Info* info, X86Features* features) { // Handling Windows platform through IsProcessorFeaturePresent. // https://docs.microsoft.com/en-us/windows/win32/api/processthreadsapi/nf-processthreadsapi-isprocessorfeaturepresent features->sse = @@ -43,6 +43,15 @@ static void DetectFeaturesFromOs(X86Features* features) { GetWindowsIsProcessorFeaturePresent(PF_XMMI64_INSTRUCTIONS_AVAILABLE); features->sse3 = GetWindowsIsProcessorFeaturePresent(PF_SSE3_INSTRUCTIONS_AVAILABLE); + +// https://github.com/google/cpu_features/issues/200 +#if (_WIN32_WINNT >= 0x0601) // Win7+ + if (GetX86Microarchitecture(info) == INTEL_WSM) { + features->ssse3 = true; + features->sse4_1 = true; + features->sse4_2 = true; + } +#endif } #endif // CPU_FEATURES_OS_WINDOWS diff --git a/test/cpuinfo_x86_test.cc b/test/cpuinfo_x86_test.cc index 0972c08..4674989 100644 --- a/test/cpuinfo_x86_test.cc +++ b/test/cpuinfo_x86_test.cc @@ -1117,6 +1117,32 @@ TEST_F(CpuidX86Test, INTEL_KNIGHTS_LANDING) { X86Microarchitecture::INTEL_KNIGHTS_L); } +// https://github.com/google/cpu_features/issues/200 +// http://users.atw.hu/instlatx64/GenuineIntel/GenuineIntel00206F2_Eagleton_CPUID.txt +#if defined(CPU_FEATURES_OS_WINDOWS) +TEST_F(CpuidX86Test, WIN_INTEL_WESTMERE_EX) { + cpu().SetLeaves({ + {{0x00000000, 0}, Leaf{0x0000000B, 0x756E6547, 0x6C65746E, 0x49656E69}}, + {{0x00000001, 0}, Leaf{0x000206F2, 0x00400800, 0x02BEE3FF, 0xBFEBFBFF}}, + }); + const auto info = GetX86Info(); + + EXPECT_EQ(info.family, 0x06); + EXPECT_EQ(info.model, 0x2F); + EXPECT_EQ(GetX86Microarchitecture(&info), X86Microarchitecture::INTEL_WSM); + +#if (_WIN32_WINNT < 0x0601) // before Win7 + EXPECT_FALSE(info.features.ssse3); + EXPECT_FALSE(info.features.sse4_1); + EXPECT_FALSE(info.features.sse4_2); +#else + EXPECT_TRUE(info.features.ssse3); + EXPECT_TRUE(info.features.sse4_1); + EXPECT_TRUE(info.features.sse4_2); +#endif +} +#endif // CPU_FEATURES_OS_WINDOWS + // TODO(user): test what happens when xsave/osxsave are not present. // TODO(user): test what happens when xmm/ymm/zmm os support are not // present.