diff --git a/BUILD.bazel b/BUILD.bazel index 1b62d66f..e78e0ed9 100644 --- a/BUILD.bazel +++ b/BUILD.bazel @@ -221,6 +221,7 @@ cc_library( PLATFORM_CPU_X86_64: [ "include/cpuinfo_x86.h", "include/internal/cpuid_x86.h", + "include/internal/windows_utils.h", ], PLATFORM_CPU_ARM: ["include/cpuinfo_arm.h"], PLATFORM_CPU_ARM64: ["include/cpuinfo_aarch64.h"], @@ -267,6 +268,7 @@ cc_library( PLATFORM_CPU_X86_64: [ "include/cpuinfo_x86.h", "include/internal/cpuid_x86.h", + "include/internal/windows_utils.h", ], PLATFORM_CPU_ARM: ["include/cpuinfo_arm.h"], PLATFORM_CPU_ARM64: ["include/cpuinfo_aarch64.h"], diff --git a/CMakeLists.txt b/CMakeLists.txt index 81451d4c..15d7aad6 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -76,6 +76,7 @@ macro(add_cpu_features_headers_and_sources HDRS_LIST_NAME SRCS_LIST_NAME) elseif(PROCESSOR_IS_X86) list(APPEND ${HDRS_LIST_NAME} ${PROJECT_SOURCE_DIR}/include/cpuinfo_x86.h) list(APPEND ${SRCS_LIST_NAME} ${PROJECT_SOURCE_DIR}/include/internal/cpuid_x86.h) + list(APPEND ${SRCS_LIST_NAME} ${PROJECT_SOURCE_DIR}/include/internal/windows_utils.h) elseif(PROCESSOR_IS_POWER) list(APPEND ${HDRS_LIST_NAME} ${PROJECT_SOURCE_DIR}/include/cpuinfo_ppc.h) else() diff --git a/include/internal/windows_utils.h b/include/internal/windows_utils.h new file mode 100644 index 00000000..8e83e568 --- /dev/null +++ b/include/internal/windows_utils.h @@ -0,0 +1,33 @@ +// Copyright 2022 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#ifndef CPU_FEATURES_INCLUDE_INTERNAL_WINDOWS_UTILS_H_ +#define CPU_FEATURES_INCLUDE_INTERNAL_WINDOWS_UTILS_H_ + +#include // IsProcessorFeaturePresent + +// modern WinSDK winnt.h contains newer features detection definitions +#if !defined(PF_SSSE3_INSTRUCTIONS_AVAILABLE) +#define PF_SSSE3_INSTRUCTIONS_AVAILABLE 36 +#endif + +#if !defined(PF_SSE4_1_INSTRUCTIONS_AVAILABLE) +#define PF_SSE4_1_INSTRUCTIONS_AVAILABLE 37 +#endif + +#if !defined(PF_SSE4_2_INSTRUCTIONS_AVAILABLE) +#define PF_SSE4_2_INSTRUCTIONS_AVAILABLE 38 +#endif + +#endif // CPU_FEATURES_INCLUDE_INTERNAL_WINDOWS_UTILS_H_ diff --git a/src/impl_x86_windows.c b/src/impl_x86_windows.c index 0b330d08..8a82823a 100644 --- a/src/impl_x86_windows.c +++ b/src/impl_x86_windows.c @@ -24,7 +24,7 @@ static void OverrideOsPreserves(OsPreserves* os_preserves) { // No override } -#include // IsProcessorFeaturePresent +#include "internal/windows_utils.h" #if defined(CPU_FEATURES_MOCK_CPUID_X86) extern bool GetWindowsIsProcessorFeaturePresent(DWORD); @@ -43,15 +43,15 @@ static void DetectFeaturesFromOs(X86Info* info, 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 + features->ssse3 = + GetWindowsIsProcessorFeaturePresent(PF_SSSE3_INSTRUCTIONS_AVAILABLE); + features->sse4_1 = + GetWindowsIsProcessorFeaturePresent(PF_SSE4_1_INSTRUCTIONS_AVAILABLE); + features->sse4_2 = + GetWindowsIsProcessorFeaturePresent(PF_SSE4_2_INSTRUCTIONS_AVAILABLE); + +// do not bother checking PF_AVX* +// cause AVX enabled processor will have XCR0 be exposed and this function will be skipped at all } #endif // CPU_FEATURES_OS_WINDOWS diff --git a/test/cpuinfo_x86_test.cc b/test/cpuinfo_x86_test.cc index 951d5d72..140ecce8 100644 --- a/test/cpuinfo_x86_test.cc +++ b/test/cpuinfo_x86_test.cc @@ -19,7 +19,7 @@ #include #include #if defined(CPU_FEATURES_OS_WINDOWS) -#include // IsProcessorFeaturePresent +#include "internal/windows_utils.h" #endif // CPU_FEATURES_OS_WINDOWS #include "filesystem_for_testing.h" @@ -834,6 +834,9 @@ TEST_F(CpuidX86Test, Nehalem) { cpu().SetWindowsIsProcessorFeaturePresent(PF_XMMI_INSTRUCTIONS_AVAILABLE); cpu().SetWindowsIsProcessorFeaturePresent(PF_XMMI64_INSTRUCTIONS_AVAILABLE); cpu().SetWindowsIsProcessorFeaturePresent(PF_SSE3_INSTRUCTIONS_AVAILABLE); + cpu().SetWindowsIsProcessorFeaturePresent(PF_SSSE3_INSTRUCTIONS_AVAILABLE); + cpu().SetWindowsIsProcessorFeaturePresent(PF_SSE4_1_INSTRUCTIONS_AVAILABLE); + cpu().SetWindowsIsProcessorFeaturePresent(PF_SSE4_2_INSTRUCTIONS_AVAILABLE); #elif defined(CPU_FEATURES_OS_MACOS) cpu().SetDarwinSysCtlByName("hw.optional.sse"); cpu().SetDarwinSysCtlByName("hw.optional.sse2"); @@ -901,13 +904,9 @@ flags : fpu mmx sse sse2 pni ssse3 sse4_1 sse4_2 EXPECT_TRUE(info.features.sse); EXPECT_TRUE(info.features.sse2); EXPECT_TRUE(info.features.sse3); -#if !defined(CPU_FEATURES_OS_WINDOWS) - // Currently disabled on Windows as IsProcessorFeaturePresent do not support - // feature detection > sse3. EXPECT_TRUE(info.features.ssse3); EXPECT_TRUE(info.features.sse4_1); EXPECT_TRUE(info.features.sse4_2); -#endif // !defined(CPU_FEATURES_OS_WINDOWS) } // https://github.com/InstLatx64/InstLatx64/blob/master/GenuineIntel/GenuineIntel0030673_Silvermont3_CPUID.txt @@ -918,6 +917,9 @@ TEST_F(CpuidX86Test, Atom) { cpu().SetWindowsIsProcessorFeaturePresent(PF_XMMI_INSTRUCTIONS_AVAILABLE); cpu().SetWindowsIsProcessorFeaturePresent(PF_XMMI64_INSTRUCTIONS_AVAILABLE); cpu().SetWindowsIsProcessorFeaturePresent(PF_SSE3_INSTRUCTIONS_AVAILABLE); + cpu().SetWindowsIsProcessorFeaturePresent(PF_SSSE3_INSTRUCTIONS_AVAILABLE); + cpu().SetWindowsIsProcessorFeaturePresent(PF_SSE4_1_INSTRUCTIONS_AVAILABLE); + cpu().SetWindowsIsProcessorFeaturePresent(PF_SSE4_2_INSTRUCTIONS_AVAILABLE); #elif defined(CPU_FEATURES_OS_MACOS) cpu().SetDarwinSysCtlByName("hw.optional.sse"); cpu().SetDarwinSysCtlByName("hw.optional.sse2"); @@ -985,13 +987,9 @@ flags : fpu mmx sse sse2 pni ssse3 sse4_1 sse4_2 EXPECT_TRUE(info.features.sse); EXPECT_TRUE(info.features.sse2); EXPECT_TRUE(info.features.sse3); -#if !defined(CPU_FEATURES_OS_WINDOWS) - // Currently disabled on Windows as IsProcessorFeaturePresent do not support - // feature detection > sse3. EXPECT_TRUE(info.features.ssse3); EXPECT_TRUE(info.features.sse4_1); EXPECT_TRUE(info.features.sse4_2); -#endif // !defined(CPU_FEATURES_OS_WINDOWS) } // https://www.felixcloutier.com/x86/cpuid#example-3-1--example-of-cache-and-tlb-interpretation @@ -1092,13 +1090,9 @@ flags : fpu mmx sse EXPECT_TRUE(info.features.sse); EXPECT_FALSE(info.features.sse2); EXPECT_FALSE(info.features.sse3); -#if !defined(CPU_FEATURES_OS_WINDOWS) - // Currently disabled on Windows as IsProcessorFeaturePresent do not support - // feature detection > sse3. EXPECT_FALSE(info.features.ssse3); EXPECT_FALSE(info.features.sse4_1); EXPECT_FALSE(info.features.sse4_2); -#endif // !defined(CPU_FEATURES_OS_WINDOWS) } // https://github.com/InstLatx64/InstLatx64/blob/master/GenuineIntel/GenuineIntel0000480_486_CPUID.txt @@ -1163,6 +1157,15 @@ TEST_F(CpuidX86Test, INTEL_KNIGHTS_LANDING) { // http://users.atw.hu/instlatx64/GenuineIntel/GenuineIntel00206F2_Eagleton_CPUID.txt #if defined(CPU_FEATURES_OS_WINDOWS) TEST_F(CpuidX86Test, WIN_INTEL_WESTMERE_EX) { + // Pre AVX cpus don't have xsave + cpu().SetOsBackupsExtendedRegisters(false); + cpu().SetWindowsIsProcessorFeaturePresent(PF_XMMI_INSTRUCTIONS_AVAILABLE); + cpu().SetWindowsIsProcessorFeaturePresent(PF_XMMI64_INSTRUCTIONS_AVAILABLE); + cpu().SetWindowsIsProcessorFeaturePresent(PF_SSE3_INSTRUCTIONS_AVAILABLE); + cpu().SetWindowsIsProcessorFeaturePresent(PF_SSSE3_INSTRUCTIONS_AVAILABLE); + cpu().SetWindowsIsProcessorFeaturePresent(PF_SSE4_1_INSTRUCTIONS_AVAILABLE); + cpu().SetWindowsIsProcessorFeaturePresent(PF_SSE4_2_INSTRUCTIONS_AVAILABLE); + cpu().SetLeaves({ {{0x00000000, 0}, Leaf{0x0000000B, 0x756E6547, 0x6C65746E, 0x49656E69}}, {{0x00000001, 0}, Leaf{0x000206F2, 0x00400800, 0x02BEE3FF, 0xBFEBFBFF}}, @@ -1173,15 +1176,12 @@ TEST_F(CpuidX86Test, WIN_INTEL_WESTMERE_EX) { 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.sse); + EXPECT_TRUE(info.features.sse2); + EXPECT_TRUE(info.features.sse3); EXPECT_TRUE(info.features.ssse3); EXPECT_TRUE(info.features.sse4_1); EXPECT_TRUE(info.features.sse4_2); -#endif } #endif // CPU_FEATURES_OS_WINDOWS