From 9e921d161c9b8bc2ec1d66639861487242e2ca34 Mon Sep 17 00:00:00 2001 From: Carles Fernandez Date: Sun, 25 Jul 2021 14:09:03 +0200 Subject: [PATCH] Update cpu_features to 628c50e with support for Apple M1 already merged --- docs/CHANGELOG.md | 3 +- .../volk_gnsssdr/.gitignore | 7 + .../volk_gnsssdr/CMakeLists.txt | 7 + .../volk_gnsssdr/cpu_features/CMakeLists.txt | 3 - .../volk_gnsssdr/cpu_features/README.md | 15 +- .../volk_gnsssdr/cpu_features/cmake/README.md | 12 +- .../include/cpu_features_macros.h | 17 + .../cpu_features/include/cpuinfo_ppc.h | 9 +- .../cpu_features/include/cpuinfo_x86.h | 60 ++- .../cpu_features/include/internal/hwcaps.h | 16 +- .../cpu_features/src/cpuinfo_ppc.c | 16 +- .../cpu_features/src/cpuinfo_x86.c | 467 ++++++++++++------ .../volk_gnsssdr/cpu_features/src/hwcaps.c | 22 +- .../src/utils/list_cpu_features.c | 3 +- .../cpu_features/test/cpuinfo_aarch64_test.cc | 4 +- .../cpu_features/test/cpuinfo_arm_test.cc | 26 +- .../cpu_features/test/cpuinfo_mips_test.cc | 10 +- .../cpu_features/test/cpuinfo_ppc_test.cc | 17 +- .../cpu_features/test/cpuinfo_x86_test.cc | 415 +++++++++++++++- .../cpu_features/test/hwcaps_for_testing.cc | 26 +- .../cpu_features/test/hwcaps_for_testing.h | 6 +- 21 files changed, 883 insertions(+), 278 deletions(-) diff --git a/docs/CHANGELOG.md b/docs/CHANGELOG.md index 8069b0485..86a7b325a 100644 --- a/docs/CHANGELOG.md +++ b/docs/CHANGELOG.md @@ -71,7 +71,8 @@ All notable changes to GNSS-SDR will be documented in this file. 3.8. - If the Matio library is not found, now it is configured and built by CMake instead of using autotools. -- Added support for Apple M1 AArch64 architecture processor. +- Added support for Apple M1 AArch64 architecture processor and for FreeBSD on + x86, improved AMD microarchitecture detection. ### Improvements in Reliability diff --git a/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/.gitignore b/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/.gitignore index 1a5b58e41..a3bcb1ddf 100644 --- a/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/.gitignore +++ b/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/.gitignore @@ -5,7 +5,14 @@ *.pyo html/ build/ +cmake_build/ +cmake-build-*/ +out/ .project .cproject +.vagrant/ +.vscode/ +.vs/ +*.swp /.DS_Store /gen/volk_gnsssdr_arch_defs.py diff --git a/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/CMakeLists.txt b/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/CMakeLists.txt index 54dcf88cc..65fa128f1 100644 --- a/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/CMakeLists.txt +++ b/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/CMakeLists.txt @@ -277,7 +277,14 @@ if(CMAKE_VERSION VERSION_GREATER 3.0 AND SUPPORTED_CPU_FEATURES_ARCH) if(CpuFeatures_FOUND) message(STATUS "Found CpuFeatures: (found version ${CpuFeatures_VERSION})") else() + if(BUILD_TESTING) + set(BUILD_TESTING_AUX ${BUILD_TESTING}) + endif() + set(BUILD_TESTING OFF) add_subdirectory(cpu_features) + if(BUILD_TESTING_AUX) + set(BUILD_TESTING ${BUILD_TESTING_AUX}) + endif() endif() set(BUILD_SHARED_LIBS "${BUILD_SHARED_LIBS_SAVED}") endif() diff --git a/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/cpu_features/CMakeLists.txt b/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/cpu_features/CMakeLists.txt index 2feca7715..30c8f27b0 100644 --- a/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/cpu_features/CMakeLists.txt +++ b/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/cpu_features/CMakeLists.txt @@ -23,9 +23,6 @@ if(NOT CMAKE_BUILD_TYPE) FORCE) endif() -# BUILD_TESTING is a standard CMake variable, but we declare it here to make it -# prominent in the GUI. -option(BUILD_TESTING "Enable test (depends on googletest)." OFF) # BUILD_SHARED_LIBS is a standard CMake variable, but we declare it here to make # it prominent in the GUI. # cpu_features uses bit-fields which are - to some extends - implementation-defined (see https://en.cppreference.com/w/c/language/bit_field). diff --git a/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/cpu_features/README.md b/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/cpu_features/README.md index 638e62874..6e35d3537 100644 --- a/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/cpu_features/README.md +++ b/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/cpu_features/README.md @@ -157,13 +157,14 @@ flags : aes,avx,cx16,smx,sse4_1,sse4_2,ssse3 ## What's supported -| | x86³ | ARM | AArch64 | MIPS⁴ | POWER | -| ------- | :--: | :-----: | :-----: | :---: | :---: | -| Android | yes² | yes¹ | yes¹ | yes¹ | N/A | -| iOS | N/A | not yet | not yet | N/A | N/A | -| Linux | yes² | yes¹ | yes¹ | yes¹ | yes¹ | -| MacOS | yes² | N/A | yes² | N/A | no | -| Windows | yes² | not yet | not yet | N/A | N/A | +| | x86³ | ARM | AArch64 | MIPS⁴ | POWER | +|---------|:----:|:-------:|:-------:|:-------:|:-------:| +| Android | yes² | yes¹ | yes¹ | yes¹ | N/A | +| iOS | N/A | not yet | not yet | N/A | N/A | +| Linux | yes² | yes¹ | yes¹ | yes¹ | yes¹ | +| MacOS | yes² | N/A | yes² | N/A | no | +| Windows | yes² | not yet | not yet | N/A | N/A | +| FreeBSD | yes² | not yet | not yet | not yet | not yet | 1. **Features revealed from Linux.** We gather data from several sources depending on availability: diff --git a/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/cpu_features/cmake/README.md b/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/cpu_features/cmake/README.md index 3fcac9fcd..23b205ec1 100644 --- a/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/cpu_features/cmake/README.md +++ b/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/cpu_features/cmake/README.md @@ -29,9 +29,11 @@ cpu_features directly and use the `cpu_features` target in your project. 3- Add the `cpu_features` target to the `target_link_libraries()` section of your executable or of your library. -## Enabling tests +## Disabling tests -CMake default options for cpu_features is Release built type with tests -disabled. To enable testing set cmake `BUILD_TESTING` variable to `ON`, -[.travis.yml](../.travis.yml) and [appveyor.yml](../appveyor.yml) have up to -date examples. +CMake default options for cpu_features is Release built type with tests enabled. +To disable testing set cmake `BUILD_TESTING` variable to `OFF`, +[.travis.yml](https://github.com/google/cpu_features/blob/master/.travis.yml) +and +[appveyor.yml](https://github.com/google/cpu_features/blob/master/appveyor.yml) +have up to date examples. diff --git a/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/cpu_features/include/cpu_features_macros.h b/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/cpu_features/include/cpu_features_macros.h index a36629a06..78ecbdad1 100644 --- a/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/cpu_features/include/cpu_features_macros.h +++ b/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/cpu_features/include/cpu_features_macros.h @@ -73,6 +73,10 @@ #define CPU_FEATURES_OS_DARWIN #endif +#if (defined(__freebsd__) || defined(__FreeBSD__)) +#define CPU_FEATURES_OS_FREEBSD +#endif + //////////////////////////////////////////////////////////////////////////////// // Compilers //////////////////////////////////////////////////////////////////////////////// @@ -205,4 +209,17 @@ #endif // defined(__mips_msa) #endif // defined(CPU_FEATURES_ARCH_MIPS) +//////////////////////////////////////////////////////////////////////////////// +// Utils +//////////////////////////////////////////////////////////////////////////////// + +// Communicates to the compiler that the block is unreachable +#if defined(CPU_FEATURES_COMPILER_CLANG) || defined(CPU_FEATURES_COMPILER_GCC) +#define UNREACHABLE() __builtin_unreachable() +#elif defined(CPU_FEATURES_COMPILER_MSC) +#define UNREACHABLE() __assume(0) +#else +#define UNREACHABLE() +#endif + #endif // CPU_FEATURES_INCLUDE_CPU_FEATURES_MACROS_H_ diff --git a/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/cpu_features/include/cpuinfo_ppc.h b/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/cpu_features/include/cpuinfo_ppc.h index 2a9ab2ba8..f626eae53 100644 --- a/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/cpu_features/include/cpuinfo_ppc.h +++ b/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/cpu_features/include/cpuinfo_ppc.h @@ -7,7 +7,6 @@ #include "cpu_features_cache_info.h" #include "cpu_features_macros.h" -#include "internal/hwcaps.h" CPU_FEATURES_START_CPP_NAMESPACE @@ -66,13 +65,19 @@ typedef struct // This function is guaranteed to be malloc, memset and memcpy free. PPCInfo GetPPCInfo(void); +typedef struct +{ + char platform[64]; // 0 terminated string + char base_platform[64]; // 0 terminated string +} PPCPlatformTypeStrings; + typedef struct { char platform[64]; // 0 terminated string char model[64]; // 0 terminated string char machine[64]; // 0 terminated string char cpu[64]; // 0 terminated string - PlatformType type; + PPCPlatformTypeStrings type; } PPCPlatformStrings; PPCPlatformStrings GetPPCPlatformStrings(void); diff --git a/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/cpu_features/include/cpuinfo_x86.h b/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/cpu_features/include/cpuinfo_x86.h index 4831f6db0..faccfa84e 100644 --- a/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/cpu_features/include/cpuinfo_x86.h +++ b/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/cpu_features/include/cpuinfo_x86.h @@ -105,32 +105,40 @@ CacheInfo GetX86CacheInfo(void); typedef enum { X86_UNKNOWN, - INTEL_CORE, // CORE - INTEL_PNR, // PENRYN - INTEL_NHM, // NEHALEM - INTEL_ATOM_BNL, // BONNELL - INTEL_WSM, // WESTMERE - INTEL_SNB, // SANDYBRIDGE - INTEL_IVB, // IVYBRIDGE - INTEL_ATOM_SMT, // SILVERMONT - INTEL_HSW, // HASWELL - INTEL_BDW, // BROADWELL - INTEL_SKL, // SKYLAKE - INTEL_ATOM_GMT, // GOLDMONT - INTEL_KBL, // KABY LAKE - INTEL_CFL, // COFFEE LAKE - INTEL_WHL, // WHISKEY LAKE - INTEL_CNL, // CANNON LAKE - INTEL_ICL, // ICE LAKE - INTEL_TGL, // TIGER LAKE - INTEL_SPR, // SAPPHIRE RAPIDS - AMD_HAMMER, // K8 - AMD_K10, // K10 - AMD_BOBCAT, // K14 - AMD_BULLDOZER, // K15 - AMD_JAGUAR, // K16 - AMD_ZEN, // K17 - AMD_ZEN3, // K19 + INTEL_CORE, // CORE + INTEL_PNR, // PENRYN + INTEL_NHM, // NEHALEM + INTEL_ATOM_BNL, // BONNELL + INTEL_WSM, // WESTMERE + INTEL_SNB, // SANDYBRIDGE + INTEL_IVB, // IVYBRIDGE + INTEL_ATOM_SMT, // SILVERMONT + INTEL_HSW, // HASWELL + INTEL_BDW, // BROADWELL + INTEL_SKL, // SKYLAKE + INTEL_ATOM_GMT, // GOLDMONT + INTEL_KBL, // KABY LAKE + INTEL_CFL, // COFFEE LAKE + INTEL_WHL, // WHISKEY LAKE + INTEL_CNL, // CANNON LAKE + INTEL_ICL, // ICE LAKE + INTEL_TGL, // TIGER LAKE + INTEL_SPR, // SAPPHIRE RAPIDS + AMD_HAMMER, // K8 HAMMER + AMD_K10, // K10 + AMD_K11, // K11 + AMD_K12, // K12 + AMD_BOBCAT, // K14 BOBCAT + AMD_PILEDRIVER, // K15 PILEDRIVER + AMD_STREAMROLLER, // K15 STREAMROLLER + AMD_EXCAVATOR, // K15 EXCAVATOR + AMD_BULLDOZER, // K15 BULLDOZER + AMD_JAGUAR, // K16 JAGUAR + AMD_PUMA, // K16 PUMA + AMD_ZEN, // K17 ZEN + AMD_ZEN_PLUS, // K17 ZEN+ + AMD_ZEN2, // K17 ZEN 2 + AMD_ZEN3, // K19 ZEN 3 } X86Microarchitecture; // Returns the underlying microarchitecture by looking at X86Info's vendor, diff --git a/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/cpu_features/include/internal/hwcaps.h b/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/cpu_features/include/internal/hwcaps.h index 34c364e94..8651b08a6 100644 --- a/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/cpu_features/include/internal/hwcaps.h +++ b/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/cpu_features/include/internal/hwcaps.h @@ -161,17 +161,19 @@ typedef struct unsigned long hwcaps2; } HardwareCapabilities; +// Retrieves values from auxiliary vector for types AT_HWCAP and AT_HWCAP2. +// First tries to call getauxval(), if not available falls back to reading +// "/proc/self/auxv". HardwareCapabilities CpuFeatures_GetHardwareCapabilities(void); + +// Checks whether value for AT_HWCAP (or AT_HWCAP2) match hwcaps_mask. bool CpuFeatures_IsHwCapsSet(const HardwareCapabilities hwcaps_mask, const HardwareCapabilities hwcaps); -typedef struct -{ - char platform[64]; // 0 terminated string - char base_platform[64]; // 0 terminated string -} PlatformType; - -PlatformType CpuFeatures_GetPlatformType(void); +// Get pointer for the AT_PLATFORM type. +const char* CpuFeatures_GetPlatformPointer(void); +// Get pointer for the AT_BASE_PLATFORM type. +const char* CpuFeatures_GetBasePlatformPointer(void); CPU_FEATURES_END_CPP_NAMESPACE diff --git a/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/cpu_features/src/cpuinfo_ppc.c b/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/cpu_features/src/cpuinfo_ppc.c index efce92bdb..6b7eb3f2d 100644 --- a/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/cpu_features/src/cpuinfo_ppc.c +++ b/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/cpu_features/src/cpuinfo_ppc.c @@ -137,9 +137,23 @@ static const PPCPlatformStrings kEmptyPPCPlatformStrings; PPCPlatformStrings GetPPCPlatformStrings(void) { PPCPlatformStrings strings = kEmptyPPCPlatformStrings; + const char* platform = CpuFeatures_GetPlatformPointer(); + const char* base_platform = CpuFeatures_GetBasePlatformPointer(); FillProcCpuInfoData(&strings); - strings.type = CpuFeatures_GetPlatformType(); + + if (platform != NULL) + { + CpuFeatures_StringView_CopyString(str(platform), strings.type.platform, + sizeof(strings.type.platform)); + } + if (base_platform != NULL) + { + CpuFeatures_StringView_CopyString(str(base_platform), + strings.type.base_platform, + sizeof(strings.type.base_platform)); + } + return strings; } diff --git a/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/cpu_features/src/cpuinfo_x86.c b/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/cpu_features/src/cpuinfo_x86.c index 15e846a88..744ae8ac6 100644 --- a/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/cpu_features/src/cpuinfo_x86.c +++ b/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/cpu_features/src/cpuinfo_x86.c @@ -84,7 +84,8 @@ // microarchitectures. #if defined(CPU_FEATURES_OS_WINDOWS) #include // IsProcessorFeaturePresent -#elif defined(CPU_FEATURES_OS_LINUX_OR_ANDROID) +#elif defined(CPU_FEATURES_OS_LINUX_OR_ANDROID) || \ + defined(CPU_FEATURES_OS_FREEBSD) #include "internal/filesystem.h" // Needed to parse /proc/cpuinfo #include "internal/stack_line_reader.h" // Needed to parse /proc/cpuinfo #include "internal/string_view.h" // Needed to parse /proc/cpuinfo @@ -200,9 +201,9 @@ static bool HasYmmOsXSave(uint32_t xcr0_eax) return HasMask(xcr0_eax, MASK_XMM | MASK_YMM); } +#if !defined(CPU_FEATURES_OS_DARWIN) // Checks that operating system saves and restores zmm registers during context // switches. -#if !defined(CPU_FEATURES_OS_DARWIN) static bool HasZmmOsXSave(uint32_t xcr0_eax) { return HasMask(xcr0_eax, MASK_XMM | MASK_YMM | MASK_MASKREG | MASK_ZMM0_15 | @@ -1205,45 +1206,11 @@ static bool GetDarwinSysCtlByName(const char* name) // Avoid to recompute them since each call to cpuid is ~100 cycles. typedef struct { - bool have_sse_via_os; - bool have_sse_via_cpuid; - bool have_avx; - bool have_avx512; - bool have_amx; -} OsSupport; - -static const OsSupport kEmptyOsSupport; - -static OsSupport CheckOsSupport(const uint32_t max_cpuid_leaf) -{ - const Leaf leaf_1 = SafeCpuId(max_cpuid_leaf, 1); - const bool have_xsave = IsBitSet(leaf_1.ecx, 26); - const bool have_osxsave = IsBitSet(leaf_1.ecx, 27); - const bool have_xcr0 = have_xsave && have_osxsave; - - OsSupport os_support = kEmptyOsSupport; - - if (have_xcr0) - { - // AVX capable cpu will expose XCR0. - const uint32_t xcr0_eax = GetXCR0Eax(); - os_support.have_sse_via_cpuid = HasXmmOsXSave(xcr0_eax); - os_support.have_avx = HasYmmOsXSave(xcr0_eax); -#if defined(CPU_FEATURES_OS_DARWIN) - os_support.have_avx512 = GetDarwinSysCtlByName("hw.optional.avx512f"); -#else - os_support.have_avx512 = HasZmmOsXSave(xcr0_eax); -#endif // CPU_FEATURES_OS_DARWIN - os_support.have_amx = HasTmmOsXSave(xcr0_eax); - } - else - { - // Atom based or older cpus need to ask the OS for sse support. - os_support.have_sse_via_os = true; - } - - return os_support; -} + bool sse_registers; + bool avx_registers; + bool avx512_registers; + bool amx_registers; +} OsPreserves; #if defined(CPU_FEATURES_OS_WINDOWS) #if defined(CPU_FEATURES_MOCK_CPUID_X86) @@ -1256,66 +1223,18 @@ static bool GetWindowsIsProcessorFeaturePresent(DWORD ProcessorFeature) #endif #endif // CPU_FEATURES_OS_WINDOWS -static void DetectSseViaOs(X86Features* features) -{ -#if defined(CPU_FEATURES_OS_WINDOWS) - // https://docs.microsoft.com/en-us/windows/win32/api/processthreadsapi/nf-processthreadsapi-isprocessorfeaturepresent - features->sse = - GetWindowsIsProcessorFeaturePresent(PF_XMMI_INSTRUCTIONS_AVAILABLE); - features->sse2 = - GetWindowsIsProcessorFeaturePresent(PF_XMMI64_INSTRUCTIONS_AVAILABLE); - features->sse3 = - GetWindowsIsProcessorFeaturePresent(PF_SSE3_INSTRUCTIONS_AVAILABLE); -#elif defined(CPU_FEATURES_OS_DARWIN) - // Handling Darwin platform through sysctlbyname. - features->sse = GetDarwinSysCtlByName("hw.optional.sse"); - features->sse2 = GetDarwinSysCtlByName("hw.optional.sse2"); - features->sse3 = GetDarwinSysCtlByName("hw.optional.sse3"); - features->ssse3 = GetDarwinSysCtlByName("hw.optional.supplementalsse3"); - features->sse4_1 = GetDarwinSysCtlByName("hw.optional.sse4_1"); - features->sse4_2 = GetDarwinSysCtlByName("hw.optional.sse4_2"); -#elif defined(CPU_FEATURES_OS_LINUX_OR_ANDROID) - // Handling Linux platform through /proc/cpuinfo. - const int fd = CpuFeatures_OpenFile("/proc/cpuinfo"); - if (fd >= 0) - { - StackLineReader reader; - StackLineReader_Initialize(&reader, fd); - for (;;) - { - const LineResult result = StackLineReader_NextLine(&reader); - const StringView line = result.line; - StringView key, value; - if (CpuFeatures_StringView_GetAttributeKeyValue(line, &key, &value)) - { - if (CpuFeatures_StringView_IsEquals(key, str("flags"))) - { - features->sse = CpuFeatures_StringView_HasWord(value, "sse"); - features->sse2 = CpuFeatures_StringView_HasWord(value, "sse2"); - features->sse3 = CpuFeatures_StringView_HasWord(value, "sse3"); - features->ssse3 = CpuFeatures_StringView_HasWord(value, "ssse3"); - features->sse4_1 = CpuFeatures_StringView_HasWord(value, "sse4_1"); - features->sse4_2 = CpuFeatures_StringView_HasWord(value, "sse4_2"); - break; - } - } - if (result.eof) break; - } - CpuFeatures_CloseFile(fd); - } -#else -#error "Unsupported fallback detection of SSE OS support." -#endif -} - // Reference https://en.wikipedia.org/wiki/CPUID. -static void ParseCpuId(const uint32_t max_cpuid_leaf, - const OsSupport os_support, X86Info* info) +static void ParseCpuId(const uint32_t max_cpuid_leaf, X86Info* info, + OsPreserves* os_preserves) { const Leaf leaf_1 = SafeCpuId(max_cpuid_leaf, 1); const Leaf leaf_7 = SafeCpuId(max_cpuid_leaf, 7); const Leaf leaf_7_1 = SafeCpuIdEx(max_cpuid_leaf, 7, 1); + const bool have_xsave = IsBitSet(leaf_1.ecx, 26); + const bool have_osxsave = IsBitSet(leaf_1.ecx, 27); + const bool have_xcr0 = have_xsave && have_osxsave; + const uint32_t family = ExtractBitRange(leaf_1.eax, 11, 8); const uint32_t extended_family = ExtractBitRange(leaf_1.eax, 27, 20); const uint32_t model = ExtractBitRange(leaf_1.eax, 7, 4); @@ -1356,61 +1275,182 @@ static void ParseCpuId(const uint32_t max_cpuid_leaf, features->vpclmulqdq = IsBitSet(leaf_7.ecx, 10); features->adx = IsBitSet(leaf_7.ebx, 19); - if (os_support.have_sse_via_os) - { - DetectSseViaOs(features); - } - else if (os_support.have_sse_via_cpuid) - { - features->sse = IsBitSet(leaf_1.edx, 25); - features->sse2 = IsBitSet(leaf_1.edx, 26); - features->sse3 = IsBitSet(leaf_1.ecx, 0); - features->ssse3 = IsBitSet(leaf_1.ecx, 9); - features->sse4_1 = IsBitSet(leaf_1.ecx, 19); - features->sse4_2 = IsBitSet(leaf_1.ecx, 20); - } + ///////////////////////////////////////////////////////////////////////////// + // The following section is devoted to Vector Extensions. + ///////////////////////////////////////////////////////////////////////////// - if (os_support.have_avx) + // CPU with AVX expose XCR0 which enables checking vector extensions OS + // support through cpuid. + if (have_xcr0) { - features->fma3 = IsBitSet(leaf_1.ecx, 12); - features->avx = IsBitSet(leaf_1.ecx, 28); - features->avx2 = IsBitSet(leaf_7.ebx, 5); - } + // Here we rely exclusively on cpuid for both CPU and OS support of vector + // extensions. + const uint32_t xcr0_eax = GetXCR0Eax(); + os_preserves->sse_registers = HasXmmOsXSave(xcr0_eax); + os_preserves->avx_registers = HasYmmOsXSave(xcr0_eax); +#if defined(CPU_FEATURES_OS_DARWIN) + // On Darwin AVX512 support is On-demand. + // We have to query the OS instead of querying the Zmm save/restore state. + // https://github.com/apple/darwin-xnu/blob/8f02f2a044b9bb1ad951987ef5bab20ec9486310/osfmk/i386/fpu.c#L173-L199 + os_preserves->avx512_registers = + GetDarwinSysCtlByName("hw.optional.avx512f"); +#else + os_preserves->avx512_registers = HasZmmOsXSave(xcr0_eax); +#endif // CPU_FEATURES_OS_DARWIN + os_preserves->amx_registers = HasTmmOsXSave(xcr0_eax); - if (os_support.have_avx512) - { - features->avx512f = IsBitSet(leaf_7.ebx, 16); - features->avx512cd = IsBitSet(leaf_7.ebx, 28); - features->avx512er = IsBitSet(leaf_7.ebx, 27); - features->avx512pf = IsBitSet(leaf_7.ebx, 26); - features->avx512bw = IsBitSet(leaf_7.ebx, 30); - features->avx512dq = IsBitSet(leaf_7.ebx, 17); - features->avx512vl = IsBitSet(leaf_7.ebx, 31); - features->avx512ifma = IsBitSet(leaf_7.ebx, 21); - features->avx512vbmi = IsBitSet(leaf_7.ecx, 1); - features->avx512vbmi2 = IsBitSet(leaf_7.ecx, 6); - features->avx512vnni = IsBitSet(leaf_7.ecx, 11); - features->avx512bitalg = IsBitSet(leaf_7.ecx, 12); - features->avx512vpopcntdq = IsBitSet(leaf_7.ecx, 14); - features->avx512_4vnniw = IsBitSet(leaf_7.edx, 2); - features->avx512_4vbmi2 = IsBitSet(leaf_7.edx, 3); - features->avx512_second_fma = HasSecondFMA(info->model); - features->avx512_4fmaps = IsBitSet(leaf_7.edx, 3); - features->avx512_bf16 = IsBitSet(leaf_7_1.eax, 5); - features->avx512_vp2intersect = IsBitSet(leaf_7.edx, 8); + if (os_preserves->sse_registers) + { + features->sse = IsBitSet(leaf_1.edx, 25); + features->sse2 = IsBitSet(leaf_1.edx, 26); + features->sse3 = IsBitSet(leaf_1.ecx, 0); + features->ssse3 = IsBitSet(leaf_1.ecx, 9); + features->sse4_1 = IsBitSet(leaf_1.ecx, 19); + features->sse4_2 = IsBitSet(leaf_1.ecx, 20); + } + if (os_preserves->avx_registers) + { + features->fma3 = IsBitSet(leaf_1.ecx, 12); + features->avx = IsBitSet(leaf_1.ecx, 28); + features->avx2 = IsBitSet(leaf_7.ebx, 5); + } + if (os_preserves->avx512_registers) + { + features->avx512f = IsBitSet(leaf_7.ebx, 16); + features->avx512cd = IsBitSet(leaf_7.ebx, 28); + features->avx512er = IsBitSet(leaf_7.ebx, 27); + features->avx512pf = IsBitSet(leaf_7.ebx, 26); + features->avx512bw = IsBitSet(leaf_7.ebx, 30); + features->avx512dq = IsBitSet(leaf_7.ebx, 17); + features->avx512vl = IsBitSet(leaf_7.ebx, 31); + features->avx512ifma = IsBitSet(leaf_7.ebx, 21); + features->avx512vbmi = IsBitSet(leaf_7.ecx, 1); + features->avx512vbmi2 = IsBitSet(leaf_7.ecx, 6); + features->avx512vnni = IsBitSet(leaf_7.ecx, 11); + features->avx512bitalg = IsBitSet(leaf_7.ecx, 12); + features->avx512vpopcntdq = IsBitSet(leaf_7.ecx, 14); + features->avx512_4vnniw = IsBitSet(leaf_7.edx, 2); + features->avx512_4vbmi2 = IsBitSet(leaf_7.edx, 3); + features->avx512_second_fma = HasSecondFMA(info->model); + features->avx512_4fmaps = IsBitSet(leaf_7.edx, 3); + features->avx512_bf16 = IsBitSet(leaf_7_1.eax, 5); + features->avx512_vp2intersect = IsBitSet(leaf_7.edx, 8); + } + if (os_preserves->amx_registers) + { + features->amx_bf16 = IsBitSet(leaf_7.edx, 22); + features->amx_tile = IsBitSet(leaf_7.edx, 24); + features->amx_int8 = IsBitSet(leaf_7.edx, 25); + } } - - if (os_support.have_amx) + else { - features->amx_bf16 = IsBitSet(leaf_7.edx, 22); - features->amx_tile = IsBitSet(leaf_7.edx, 24); - features->amx_int8 = IsBitSet(leaf_7.edx, 25); + // When XCR0 is not available (Atom based or older cpus) we need to defer to + // the OS via custom code. +#if defined(CPU_FEATURES_OS_WINDOWS) + // Handling Windows platform through IsProcessorFeaturePresent. + // https://docs.microsoft.com/en-us/windows/win32/api/processthreadsapi/nf-processthreadsapi-isprocessorfeaturepresent + features->sse = + GetWindowsIsProcessorFeaturePresent(PF_XMMI_INSTRUCTIONS_AVAILABLE); + features->sse2 = + GetWindowsIsProcessorFeaturePresent(PF_XMMI64_INSTRUCTIONS_AVAILABLE); + features->sse3 = + GetWindowsIsProcessorFeaturePresent(PF_SSE3_INSTRUCTIONS_AVAILABLE); +#elif defined(CPU_FEATURES_OS_DARWIN) + // Handling Darwin platform through sysctlbyname. + features->sse = GetDarwinSysCtlByName("hw.optional.sse"); + features->sse2 = GetDarwinSysCtlByName("hw.optional.sse2"); + features->sse3 = GetDarwinSysCtlByName("hw.optional.sse3"); + features->ssse3 = GetDarwinSysCtlByName("hw.optional.supplementalsse3"); + features->sse4_1 = GetDarwinSysCtlByName("hw.optional.sse4_1"); + features->sse4_2 = GetDarwinSysCtlByName("hw.optional.sse4_2"); +#elif defined(CPU_FEATURES_OS_FREEBSD) + // Handling FreeBSD platform through parsing /var/run/dmesg.boot. + const int fd = CpuFeatures_OpenFile("/var/run/dmesg.boot"); + if (fd >= 0) + { + StackLineReader reader; + StackLineReader_Initialize(&reader, fd); + for (;;) + { + const LineResult result = StackLineReader_NextLine(&reader); + const StringView line = result.line; + const bool is_feature = + CpuFeatures_StringView_StartsWith(line, str(" Features=")); + const bool is_feature2 = + CpuFeatures_StringView_StartsWith(line, str(" Features2=")); + if (is_feature || is_feature2) + { + // Lines of interests are of the following form: + // " Features=0x1783fbff" + // We replace '<', '>' and ',' with space so we can search by + // whitespace separated word. + // TODO: Fix CpuFeatures_StringView_HasWord to allow for different + // separators. + for (size_t i = 0; i < line.size; ++i) + { + char* c = (char*)(&(line.ptr[i])); + if (*c == '<' || *c == '>' || *c == ',') *c = ' '; + } + if (is_feature) + { + features->sse = CpuFeatures_StringView_HasWord(line, "SSE"); + features->sse2 = CpuFeatures_StringView_HasWord(line, "SSE2"); + } + if (is_feature2) + { + features->sse3 = CpuFeatures_StringView_HasWord(line, "SSE3"); + features->ssse3 = CpuFeatures_StringView_HasWord(line, "SSSE3"); + features->sse4_1 = CpuFeatures_StringView_HasWord(line, "SSE4.1"); + features->sse4_2 = CpuFeatures_StringView_HasWord(line, "SSE4.2"); + } + } + if (result.eof) break; + } + CpuFeatures_CloseFile(fd); + } +#elif defined(CPU_FEATURES_OS_LINUX_OR_ANDROID) + // Handling Linux platform through /proc/cpuinfo. + const int fd = CpuFeatures_OpenFile("/proc/cpuinfo"); + if (fd >= 0) + { + StackLineReader reader; + StackLineReader_Initialize(&reader, fd); + for (;;) + { + const LineResult result = StackLineReader_NextLine(&reader); + const StringView line = result.line; + StringView key, value; + if (CpuFeatures_StringView_GetAttributeKeyValue(line, &key, &value)) + { + if (CpuFeatures_StringView_IsEquals(key, str("flags"))) + { + features->sse = CpuFeatures_StringView_HasWord(value, "sse"); + features->sse2 = CpuFeatures_StringView_HasWord(value, "sse2"); + features->sse3 = CpuFeatures_StringView_HasWord(value, "sse3"); + features->ssse3 = CpuFeatures_StringView_HasWord(value, "ssse3"); + features->sse4_1 = CpuFeatures_StringView_HasWord(value, "sse4_1"); + features->sse4_2 = CpuFeatures_StringView_HasWord(value, "sse4_2"); + break; + } + } + if (result.eof) break; + } + CpuFeatures_CloseFile(fd); + } +#else +#error "Unsupported fallback detection of SSE OS support." +#endif + // 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). + if (features->sse) os_preserves->sse_registers = true; } } // Reference // https://en.wikipedia.org/wiki/CPUID#EAX=80000000h:_Get_Highest_Extended_Function_Implemented. -static void ParseExtraAMDCpuId(X86Info* info, OsSupport os_support) +static void ParseExtraAMDCpuId(X86Info* info, OsPreserves os_preserves) { const Leaf leaf_80000000 = CpuId(0x80000000); const uint32_t max_extended_cpuid_leaf = leaf_80000000.eax; @@ -1418,12 +1458,12 @@ static void ParseExtraAMDCpuId(X86Info* info, OsSupport os_support) X86Features* const features = &info->features; - if (os_support.have_sse_via_cpuid) + if (os_preserves.sse_registers) { features->sse4a = IsBitSet(leaf_80000001.ecx, 6); } - if (os_support.have_avx) + if (os_preserves.avx_registers) { features->fma4 = IsBitSet(leaf_80000001.ecx, 16); } @@ -1431,6 +1471,7 @@ static void ParseExtraAMDCpuId(X86Info* info, OsSupport os_support) static const X86Info kEmptyX86Info; static const CacheInfo kEmptyCacheInfo; +static const OsPreserves kEmptyOsPreserves; X86Info GetX86Info(void) { @@ -1438,15 +1479,16 @@ X86Info GetX86Info(void) const Leaf leaf_0 = CpuId(0); const bool is_intel = IsVendor(leaf_0, "GenuineIntel"); const bool is_amd = IsVendor(leaf_0, "AuthenticAMD"); + const bool is_hygon = IsVendor(leaf_0, "HygonGenuine"); SetVendor(leaf_0, info.vendor); - if (is_intel || is_amd) + if (is_intel || is_amd || is_hygon) { + OsPreserves os_preserves = kEmptyOsPreserves; const uint32_t max_cpuid_leaf = leaf_0.eax; - const OsSupport os_support = CheckOsSupport(max_cpuid_leaf); - ParseCpuId(max_cpuid_leaf, os_support, &info); - if (is_amd) + ParseCpuId(max_cpuid_leaf, &info, &os_preserves); + if (is_amd || is_hygon) { - ParseExtraAMDCpuId(&info, os_support); + ParseExtraAMDCpuId(&info, os_preserves); } } return info; @@ -1473,8 +1515,10 @@ X86Microarchitecture GetX86Microarchitecture(const X86Info* info) { switch (CPUID(info->family, info->model)) { + case CPUID(0x06, 0x1C): // Intel(R) Atom(TM) CPU 230 @ 1.60GHz case CPUID(0x06, 0x35): case CPUID(0x06, 0x36): + case CPUID(0x06, 0x70): // https://en.wikichip.org/wiki/intel/atom/230 // https://en.wikipedia.org/wiki/Bonnell_(microarchitecture) return INTEL_ATOM_BNL; case CPUID(0x06, 0x37): @@ -1574,27 +1618,122 @@ X86Microarchitecture GetX86Microarchitecture(const X86Info* info) } if (memcmp(info->vendor, "AuthenticAMD", sizeof(info->vendor)) == 0) { - switch (info->family) + switch (CPUID(info->family, info->model)) { - // https://en.wikipedia.org/wiki/List_of_AMD_CPU_microarchitectures - case 0x0F: + // https://en.wikichip.org/wiki/amd/cpuid + case CPUID(0xF, 0x04): + case CPUID(0xF, 0x05): + case CPUID(0xF, 0x07): + case CPUID(0xF, 0x08): + case CPUID(0xF, 0x0C): + case CPUID(0xF, 0x0E): + case CPUID(0xF, 0x0F): + case CPUID(0xF, 0x14): + case CPUID(0xF, 0x15): + case CPUID(0xF, 0x17): + case CPUID(0xF, 0x18): + case CPUID(0xF, 0x1B): + case CPUID(0xF, 0x1C): + case CPUID(0xF, 0x1F): + case CPUID(0xF, 0x21): + case CPUID(0xF, 0x23): + case CPUID(0xF, 0x24): + case CPUID(0xF, 0x25): + case CPUID(0xF, 0x27): + case CPUID(0xF, 0x2B): + case CPUID(0xF, 0x2C): + case CPUID(0xF, 0x2F): + case CPUID(0xF, 0x41): + case CPUID(0xF, 0x43): + case CPUID(0xF, 0x48): + case CPUID(0xF, 0x4B): + case CPUID(0xF, 0x4C): + case CPUID(0xF, 0x4F): + case CPUID(0xF, 0x5D): + case CPUID(0xF, 0x5F): + case CPUID(0xF, 0x68): + case CPUID(0xF, 0x6B): + case CPUID(0xF, 0x6F): + case CPUID(0xF, 0x7F): + case CPUID(0xF, 0xC1): return AMD_HAMMER; - case 0x10: + case CPUID(0x10, 0x02): + case CPUID(0x10, 0x04): + case CPUID(0x10, 0x05): + case CPUID(0x10, 0x06): + case CPUID(0x10, 0x08): + case CPUID(0x10, 0x09): + case CPUID(0x10, 0x0A): return AMD_K10; - case 0x14: + case CPUID(0x11, 0x03): + // http://developer.amd.com/wordpress/media/2012/10/41788.pdf + return AMD_K11; + case CPUID(0x12, 0x01): + // https://www.amd.com/system/files/TechDocs/44739_12h_Rev_Gd.pdf + return AMD_K12; + case CPUID(0x14, 0x00): + case CPUID(0x14, 0x01): + case CPUID(0x14, 0x02): + // https://www.amd.com/system/files/TechDocs/47534_14h_Mod_00h-0Fh_Rev_Guide.pdf return AMD_BOBCAT; - case 0x15: + case CPUID(0x15, 0x01): + // https://en.wikichip.org/wiki/amd/microarchitectures/bulldozer return AMD_BULLDOZER; - case 0x16: + case CPUID(0x15, 0x02): + case CPUID(0x15, 0x11): + case CPUID(0x15, 0x13): + // https://en.wikichip.org/wiki/amd/microarchitectures/piledriver + return AMD_PILEDRIVER; + case CPUID(0x15, 0x30): + case CPUID(0x15, 0x38): + // https://en.wikichip.org/wiki/amd/microarchitectures/steamroller + return AMD_STREAMROLLER; + case CPUID(0x15, 0x60): + case CPUID(0x15, 0x65): + case CPUID(0x15, 0x70): + // https://en.wikichip.org/wiki/amd/microarchitectures/excavator + return AMD_EXCAVATOR; + case CPUID(0x16, 0x00): return AMD_JAGUAR; - case 0x17: + case CPUID(0x16, 0x30): + return AMD_PUMA; + case CPUID(0x17, 0x01): + case CPUID(0x17, 0x11): + case CPUID(0x17, 0x18): + case CPUID(0x17, 0x20): + // https://en.wikichip.org/wiki/amd/microarchitectures/zen return AMD_ZEN; - case 0x19: + case CPUID(0x17, 0x08): + // https://en.wikichip.org/wiki/amd/microarchitectures/zen%2B + return AMD_ZEN_PLUS; + case CPUID(0x17, 0x31): + case CPUID(0x17, 0x47): + case CPUID(0x17, 0x60): + case CPUID(0x17, 0x68): + case CPUID(0x17, 0x71): + case CPUID(0x17, 0x90): + case CPUID(0x17, 0x98): + // https://en.wikichip.org/wiki/amd/microarchitectures/zen_2 + return AMD_ZEN2; + case CPUID(0x19, 0x01): + case CPUID(0x19, 0x21): + case CPUID(0x19, 0x30): + case CPUID(0x19, 0x40): + case CPUID(0x19, 0x50): + // https://en.wikichip.org/wiki/amd/microarchitectures/zen_3 return AMD_ZEN3; default: return X86_UNKNOWN; } } + if (memcmp(info->vendor, "HygonGenuine", sizeof(info->vendor)) == 0) + { + switch (CPUID(info->family, info->model)) + { + case CPUID(0x18, 0x00): + return AMD_ZEN; + } + } return X86_UNKNOWN; } @@ -1681,14 +1820,30 @@ const char* GetX86MicroarchitectureName(X86Microarchitecture uarch) return "AMD_HAMMER"; case AMD_K10: return "AMD_K10"; + case AMD_K11: + return "AMD_K11"; + case AMD_K12: + return "AMD_K12"; case AMD_BOBCAT: return "AMD_BOBCAT"; + case AMD_PILEDRIVER: + return "AMD_PILEDRIVER"; + case AMD_STREAMROLLER: + return "AMD_STREAMROLLER"; + case AMD_EXCAVATOR: + return "AMD_EXCAVATOR"; case AMD_BULLDOZER: return "AMD_BULLDOZER"; + case AMD_PUMA: + return "AMD_PUMA"; case AMD_JAGUAR: return "AMD_JAGUAR"; case AMD_ZEN: return "AMD_ZEN"; + case AMD_ZEN_PLUS: + return "AMD_ZEN_PLUS"; + case AMD_ZEN2: + return "AMD_ZEN2"; case AMD_ZEN3: return "AMD_ZEN3"; } diff --git a/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/cpu_features/src/hwcaps.c b/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/cpu_features/src/hwcaps.c index 35b499487..111a4b84d 100644 --- a/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/cpu_features/src/hwcaps.c +++ b/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/cpu_features/src/hwcaps.c @@ -24,7 +24,8 @@ bool CpuFeatures_IsHwCapsSet(const HardwareCapabilities hwcaps_mask, #ifdef CPU_FEATURES_TEST // In test mode, hwcaps_for_testing will define the following functions. HardwareCapabilities CpuFeatures_GetHardwareCapabilities(void); -PlatformType CpuFeatures_GetPlatformType(void); +const char* CpuFeatures_GetPlatformPointer(void); +const char* CpuFeatures_GetBasePlatformPointer(void); #else // Debug facilities @@ -170,21 +171,14 @@ HardwareCapabilities CpuFeatures_GetHardwareCapabilities(void) return capabilities; } -PlatformType kEmptyPlatformType; - -PlatformType CpuFeatures_GetPlatformType(void) +const char *CpuFeatures_GetPlatformPointer(void) { - PlatformType type = kEmptyPlatformType; - char *platform = (char *)GetHardwareCapabilitiesFor(AT_PLATFORM); - char *base_platform = (char *)GetHardwareCapabilitiesFor(AT_BASE_PLATFORM); + return (const char *)GetHardwareCapabilitiesFor(AT_PLATFORM); +} - if (platform != NULL) - CpuFeatures_StringView_CopyString(str(platform), type.platform, - sizeof(type.platform)); - if (base_platform != NULL) - CpuFeatures_StringView_CopyString(str(base_platform), type.base_platform, - sizeof(type.base_platform)); - return type; +const char *CpuFeatures_GetBasePlatformPointer(void) +{ + return (const char *)GetHardwareCapabilitiesFor(AT_BASE_PLATFORM); } #endif // CPU_FEATURES_TEST diff --git a/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/cpu_features/src/utils/list_cpu_features.c b/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/cpu_features/src/utils/list_cpu_features.c index 53aae4011..db72230c7 100644 --- a/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/cpu_features/src/utils/list_cpu_features.c +++ b/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/cpu_features/src/utils/list_cpu_features.c @@ -362,9 +362,8 @@ static Node* GetCacheTypeString(CacheType cache_type) return CreateConstantString("stlb"); case CPU_FEATURE_CACHE_PREFETCH: return CreateConstantString("prefetch"); - default: - return CreateConstantString("null"); } + UNREACHABLE(); } static void AddCacheInfo(Node* root, const CacheInfo* cache_info) diff --git a/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/cpu_features/test/cpuinfo_aarch64_test.cc b/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/cpu_features/test/cpuinfo_aarch64_test.cc index 40c9c2f90..d7b9304ed 100644 --- a/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/cpu_features/test/cpuinfo_aarch64_test.cc +++ b/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/cpu_features/test/cpuinfo_aarch64_test.cc @@ -137,6 +137,7 @@ void DisableHardwareCapabilities() TEST(CpuinfoAarch64Test, FromHardwareCap) { + ResetHwcaps(); SetHardwareCapabilities(AARCH64_HWCAP_FP | AARCH64_HWCAP_AES, 0); GetEmptyFilesystem(); // disabling /proc/cpuinfo const auto info = GetAarch64Info(); @@ -176,6 +177,7 @@ TEST(CpuinfoAarch64Test, FromHardwareCap) TEST(CpuinfoAarch64Test, FromHardwareCap2) { + ResetHwcaps(); SetHardwareCapabilities(AARCH64_HWCAP_FP, AARCH64_HWCAP2_SVE2 | AARCH64_HWCAP2_BTI); GetEmptyFilesystem(); // disabling /proc/cpuinfo @@ -205,7 +207,7 @@ TEST(CpuinfoAarch64Test, FromHardwareCap2) TEST(CpuinfoAarch64Test, ARMCortexA53) { - DisableHardwareCapabilities(); + ResetHwcaps(); auto& fs = GetEmptyFilesystem(); fs.CreateFile("/proc/cpuinfo", R"(Processor : AArch64 Processor rev 3 (aarch64) diff --git a/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/cpu_features/test/cpuinfo_arm_test.cc b/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/cpu_features/test/cpuinfo_arm_test.cc index 13c8eb4c8..44676a6aa 100644 --- a/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/cpu_features/test/cpuinfo_arm_test.cc +++ b/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/cpu_features/test/cpuinfo_arm_test.cc @@ -10,10 +10,9 @@ namespace cpu_features { namespace { -void DisableHardwareCapabilities() { SetHardwareCapabilities(0, 0); } - TEST(CpuinfoArmTest, FromHardwareCap) { + ResetHwcaps(); SetHardwareCapabilities(ARM_HWCAP_NEON, ARM_HWCAP2_AES | ARM_HWCAP2_CRC32); GetEmptyFilesystem(); // disabling /proc/cpuinfo const auto info = GetArmInfo(); @@ -43,7 +42,7 @@ TEST(CpuinfoArmTest, FromHardwareCap) TEST(CpuinfoArmTest, ODroidFromCpuInfo) { - DisableHardwareCapabilities(); + ResetHwcaps(); auto& fs = GetEmptyFilesystem(); fs.CreateFile("/proc/cpuinfo", R"(processor : 0 model name : ARMv7 Processor rev 3 (v71) @@ -93,7 +92,7 @@ CPU revision : 3)"); // Linux test-case TEST(CpuinfoArmTest, RaspberryPiZeroFromCpuInfo) { - DisableHardwareCapabilities(); + ResetHwcaps(); auto& fs = GetEmptyFilesystem(); fs.CreateFile("/proc/cpuinfo", R"(processor : 0 model name : ARMv6-compatible processor rev 7 (v6l) @@ -104,6 +103,7 @@ CPU architecture: 7 CPU variant : 0x0 CPU part : 0xb76 CPU revision : 7 + Hardware : BCM2835 Revision : 9000c1 Serial : 000000006cd946f3)"); @@ -145,7 +145,7 @@ Serial : 000000006cd946f3)"); TEST(CpuinfoArmTest, MarvellArmadaFromCpuInfo) { - DisableHardwareCapabilities(); + ResetHwcaps(); auto& fs = GetEmptyFilesystem(); fs.CreateFile("/proc/cpuinfo", R"(processor : 0 model name : ARMv7 Processor rev 1 (v7l) @@ -156,6 +156,7 @@ CPU architecture: 7 CPU variant : 0x4 CPU part : 0xc09 CPU revision : 1 + processor : 1 model name : ARMv7 Processor rev 1 (v7l) BogoMIPS : 50.00 @@ -165,6 +166,7 @@ CPU architecture: 7 CPU variant : 0x4 CPU part : 0xc09 CPU revision : 1 + Hardware : Marvell Armada 380/385 (Device Tree) Revision : 0000 Serial : 0000000000000000)"); @@ -208,7 +210,7 @@ Serial : 0000000000000000)"); // http://code.google.com/p/android/issues/detail?id=10812 TEST(CpuinfoArmTest, InvalidArmv7) { - DisableHardwareCapabilities(); + ResetHwcaps(); auto& fs = GetEmptyFilesystem(); fs.CreateFile("/proc/cpuinfo", R"(Processor : ARMv6-compatible processor rev 6 (v6l) @@ -219,6 +221,7 @@ CPU architecture: 7 CPU variant : 0x0 CPU part : 0xb76 CPU revision : 6 + Hardware : SPICA Revision : 0020 Serial : 33323613546d00ec )"); @@ -258,19 +261,23 @@ Serial : 33323613546d00ec )"); // https://crbug.com/341598. TEST(CpuinfoArmTest, InvalidNeon) { + ResetHwcaps(); auto& fs = GetEmptyFilesystem(); fs.CreateFile("/proc/cpuinfo", R"(Processor: ARMv7 Processory rev 0 (v71) processor: 0 BogoMIPS: 13.50 + Processor: 1 BogoMIPS: 13.50 + Features: swp half thumb fastmult vfp edsp neon vfpv3 tls vfpv4 idiva idivt CPU implementer : 0x51 CPU architecture: 7 CPU variant: 0x1 CPU part: 0x04d CPU revision: 0 + Hardware: SAMSUNG M2 Revision: 0010 Serial: 00001e030000354e)"); @@ -283,7 +290,7 @@ Serial: 00001e030000354e)"); // support. TEST(CpuinfoArmTest, Nexus4_0x510006f2) { - DisableHardwareCapabilities(); + ResetHwcaps(); auto& fs = GetEmptyFilesystem(); fs.CreateFile("/proc/cpuinfo", R"(CPU implementer : 0x51 @@ -302,7 +309,7 @@ CPU revision : 2)"); // support. TEST(CpuinfoArmTest, Nexus4_0x510006f3) { - DisableHardwareCapabilities(); + ResetHwcaps(); auto& fs = GetEmptyFilesystem(); fs.CreateFile("/proc/cpuinfo", R"(CPU implementer : 0x51 @@ -322,7 +329,7 @@ CPU revision : 3)"); // CPU implemented by the emulator. TEST(CpuinfoArmTest, EmulatorSpecificIdiv) { - DisableHardwareCapabilities(); + ResetHwcaps(); auto& fs = GetEmptyFilesystem(); fs.CreateFile("/proc/cpuinfo", R"(Processor : ARMv7 Processor rev 0 (v7l) @@ -333,6 +340,7 @@ CPU architecture: 7 CPU variant : 0x0 CPU part : 0xc08 CPU revision : 0 + Hardware : Goldfish Revision : 0000 Serial : 0000000000000000)"); diff --git a/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/cpu_features/test/cpuinfo_mips_test.cc b/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/cpu_features/test/cpuinfo_mips_test.cc index 0503d843d..f5ec19ff8 100644 --- a/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/cpu_features/test/cpuinfo_mips_test.cc +++ b/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/cpu_features/test/cpuinfo_mips_test.cc @@ -12,10 +12,9 @@ namespace cpu_features { namespace { -void DisableHardwareCapabilities() { SetHardwareCapabilities(0, 0); } - TEST(CpuinfoMipsTest, FromHardwareCapBoth) { + ResetHwcaps(); SetHardwareCapabilities(MIPS_HWCAP_MSA | MIPS_HWCAP_R6, 0); GetEmptyFilesystem(); // disabling /proc/cpuinfo const auto info = GetMipsInfo(); @@ -26,6 +25,7 @@ TEST(CpuinfoMipsTest, FromHardwareCapBoth) TEST(CpuinfoMipsTest, FromHardwareCapOnlyOne) { + ResetHwcaps(); SetHardwareCapabilities(MIPS_HWCAP_MSA, 0); GetEmptyFilesystem(); // disabling /proc/cpuinfo const auto info = GetMipsInfo(); @@ -35,7 +35,7 @@ TEST(CpuinfoMipsTest, FromHardwareCapOnlyOne) TEST(CpuinfoMipsTest, Ci40) { - DisableHardwareCapabilities(); + ResetHwcaps(); auto& fs = GetEmptyFilesystem(); fs.CreateFile("/proc/cpuinfo", R"(system type : IMG Pistachio SoC (B0) machine : IMG Marduk – Ci40 with cc2520 @@ -64,7 +64,7 @@ VPE : 0 TEST(CpuinfoMipsTest, AR7161) { - DisableHardwareCapabilities(); + ResetHwcaps(); auto& fs = GetEmptyFilesystem(); fs.CreateFile("/proc/cpuinfo", R"(system type : Atheros AR7161 rev 2 @@ -91,7 +91,7 @@ VCEI exceptions : not available TEST(CpuinfoMipsTest, Goldfish) { - DisableHardwareCapabilities(); + ResetHwcaps(); auto& fs = GetEmptyFilesystem(); fs.CreateFile("/proc/cpuinfo", R"(system type : MIPS-Goldfish Hardware : goldfish diff --git a/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/cpu_features/test/cpuinfo_ppc_test.cc b/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/cpu_features/test/cpuinfo_ppc_test.cc index d657d9b6a..78e556734 100644 --- a/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/cpu_features/test/cpuinfo_ppc_test.cc +++ b/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/cpu_features/test/cpuinfo_ppc_test.cc @@ -11,10 +11,9 @@ namespace cpu_features { namespace { -void DisableHardwareCapabilities() { SetHardwareCapabilities(0, 0); } - TEST(CpustringsPPCTest, FromHardwareCap) { + ResetHwcaps(); SetHardwareCapabilities(PPC_FEATURE_HAS_FPU | PPC_FEATURE_HAS_VSX, PPC_FEATURE2_ARCH_3_00); GetEmptyFilesystem(); // disabling /proc/cpuinfo @@ -31,22 +30,25 @@ TEST(CpustringsPPCTest, FromHardwareCap) TEST(CpustringsPPCTest, Blade) { - DisableHardwareCapabilities(); + ResetHwcaps(); auto& fs = GetEmptyFilesystem(); fs.CreateFile("/proc/cpuinfo", R"(processor : 14 cpu : POWER7 (architected), altivec supported clock : 3000.000000MHz revision : 2.1 (pvr 003f 0201) + processor : 15 cpu : POWER7 (architected), altivec supported clock : 3000.000000MHz revision : 2.1 (pvr 003f 0201) + timebase : 512000000 platform : pSeries model : IBM,8406-70Y machine : CHRP IBM,8406-70Y)"); - SetPlatformTypes("power7", "power8"); + SetPlatformPointer("power7"); + SetBasePlatformPointer("power8"); const auto strings = GetPPCPlatformStrings(); ASSERT_STREQ(strings.platform, "pSeries"); ASSERT_STREQ(strings.model, "IBM,8406-70Y"); @@ -58,17 +60,19 @@ machine : CHRP IBM,8406-70Y)"); TEST(CpustringsPPCTest, Firestone) { - DisableHardwareCapabilities(); + ResetHwcaps(); auto& fs = GetEmptyFilesystem(); fs.CreateFile("/proc/cpuinfo", R"(processor : 126 cpu : POWER8 (raw), altivec supported clock : 2061.000000MHz revision : 2.0 (pvr 004d 0200) + processor : 127 cpu : POWER8 (raw), altivec supported clock : 2061.000000MHz revision : 2.0 (pvr 004d 0200) + timebase : 512000000 platform : PowerNV model : 8335-GTA @@ -83,13 +87,14 @@ firmware : OPAL v3)"); TEST(CpustringsPPCTest, w8) { - DisableHardwareCapabilities(); + ResetHwcaps(); auto& fs = GetEmptyFilesystem(); fs.CreateFile("/proc/cpuinfo", R"(processor : 143 cpu : POWER9, altivec supported clock : 2300.000000MHz revision : 2.2 (pvr 004e 1202) + timebase : 512000000 platform : PowerNV model : 0000000000000000 diff --git a/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/cpu_features/test/cpuinfo_x86_test.cc b/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/cpu_features/test/cpuinfo_x86_test.cc index c43b6c367..f4fa1a9d3 100644 --- a/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/cpu_features/test/cpuinfo_x86_test.cc +++ b/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/cpu_features/test/cpuinfo_x86_test.cc @@ -304,8 +304,179 @@ TEST_F(CpuidX86Test, HSWCache) EXPECT_EQ(info.levels[3].partitioning, 1); } +// http://users.atw.hu/instlatx64/AuthenticAMD/AuthenticAMD0200F30_K11_Griffin_CPUID.txt +TEST_F(CpuidX86Test, AMD_K11_GRIFFIN) +{ + g_fake_cpu->SetLeaves({ + {{0x00000000, 0}, Leaf{0x00000001, 0x68747541, 0x444D4163, 0x69746E65}}, + {{0x00000001, 0}, Leaf{0x00200F30, 0x00020800, 0x00002001, 0x178BFBFF}}, + {{0x80000000, 0}, Leaf{0x8000001A, 0x68747541, 0x444D4163, 0x69746E65}}, + {{0x80000001, 0}, Leaf{0x00200F30, 0x20000000, 0x0000131F, 0xEBD3FBFF}}, + }); + const auto info = GetX86Info(); + + EXPECT_STREQ(info.vendor, "AuthenticAMD"); + EXPECT_EQ(info.family, 0x11); + EXPECT_EQ(info.model, 0x03); + EXPECT_EQ(GetX86Microarchitecture(&info), X86Microarchitecture::AMD_K11); +} + +// http://users.atw.hu/instlatx64/AuthenticAMD/AuthenticAMD0300F10_K12_Llano_CPUID.txt +TEST_F(CpuidX86Test, AMD_K12_LLANO) +{ + g_fake_cpu->SetLeaves({ + {{0x00000000, 0}, Leaf{0x00000006, 0x68747541, 0x444D4163, 0x69746E65}}, + {{0x00000001, 0}, Leaf{0x00300F10, 0x00040800, 0x00802009, 0x178BFBFF}}, + {{0x80000000, 0}, Leaf{0x8000001B, 0x68747541, 0x444D4163, 0x69746E65}}, + {{0x80000001, 0}, Leaf{0x00300F10, 0x20002B31, 0x000037FF, 0xEFD3FBFF}}, + }); + const auto info = GetX86Info(); + + EXPECT_STREQ(info.vendor, "AuthenticAMD"); + EXPECT_EQ(info.family, 0x12); + EXPECT_EQ(info.model, 0x01); + EXPECT_EQ(GetX86Microarchitecture(&info), X86Microarchitecture::AMD_K12); +} + +// http://users.atw.hu/instlatx64/AuthenticAMD/AuthenticAMD0500F01_K14_Bobcat_CPUID.txt +TEST_F(CpuidX86Test, AMD_K14_BOBCAT_AMD0500F01) +{ + g_fake_cpu->SetLeaves({ + {{0x00000000, 0}, Leaf{0x00000006, 0x68747541, 0x444D4163, 0x69746E65}}, + {{0x00000001, 0}, Leaf{0x00500F01, 0x00020800, 0x00802209, 0x178BFBFF}}, + {{0x80000000, 0}, Leaf{0x8000001B, 0x68747541, 0x444D4163, 0x69746E65}}, + {{0x80000001, 0}, Leaf{0x00500F01, 0x00000000, 0x000035FF, 0x2FD3FBFF}}, + }); + const auto info = GetX86Info(); + + EXPECT_STREQ(info.vendor, "AuthenticAMD"); + EXPECT_EQ(info.family, 0x14); + EXPECT_EQ(info.model, 0x00); + EXPECT_EQ(GetX86Microarchitecture(&info), X86Microarchitecture::AMD_BOBCAT); +} + +// http://users.atw.hu/instlatx64/AuthenticAMD/AuthenticAMD0500F10_K14_Bobcat_CPUID.txt +TEST_F(CpuidX86Test, AMD_K14_BOBCAT_AMD0500F10) +{ + g_fake_cpu->SetLeaves({ + {{0x00000000, 0}, Leaf{0x00000006, 0x68747541, 0x444D4163, 0x69746E65}}, + {{0x00000001, 0}, Leaf{0x00500F10, 0x00020800, 0x00802209, 0x178BFBFF}}, + {{0x00000002, 0}, Leaf{0x00000000, 0x00000000, 0x00000000, 0x00000000}}, + {{0x00000003, 0}, Leaf{0x00000000, 0x00000000, 0x00000000, 0x00000000}}, + {{0x00000005, 0}, Leaf{0x00000040, 0x00000040, 0x00000003, 0x00000000}}, + {{0x00000006, 0}, Leaf{0x00000000, 0x00000000, 0x00000001, 0x00000000}}, + {{0x80000000, 0}, Leaf{0x8000001B, 0x68747541, 0x444D4163, 0x69746E65}}, + {{0x80000001, 0}, Leaf{0x00500F10, 0x00001242, 0x000035FF, 0x2FD3FBFF}}, + {{0x80000002, 0}, Leaf{0x20444D41, 0x35332D45, 0x72502030, 0x7365636F}}, + {{0x80000003, 0}, Leaf{0x00726F73, 0x00000000, 0x00000000, 0x00000000}}, + {{0x80000004, 0}, Leaf{0x00000000, 0x00000000, 0x00000000, 0x00000000}}, + {{0x80000005, 0}, Leaf{0xFF08FF08, 0xFF280000, 0x20080140, 0x20020140}}, + }); + const auto info = GetX86Info(); + + EXPECT_STREQ(info.vendor, "AuthenticAMD"); + EXPECT_EQ(info.family, 0x14); + EXPECT_EQ(info.model, 0x01); + EXPECT_EQ(GetX86Microarchitecture(&info), X86Microarchitecture::AMD_BOBCAT); +} + +// http://users.atw.hu/instlatx64/AuthenticAMD/AuthenticAMD0500F20_K14_Bobcat_CPUID.txt +TEST_F(CpuidX86Test, AMD_K14_BOBCAT_AMD0500F20) +{ + g_fake_cpu->SetLeaves({ + {{0x00000000, 0}, Leaf{0x00000006, 0x68747541, 0x444D4163, 0x69746E65}}, + {{0x00000001, 0}, Leaf{0x00500F20, 0x00020800, 0x00802209, 0x178BFBFF}}, + {{0x80000000, 0}, Leaf{0x8000001B, 0x68747541, 0x444D4163, 0x69746E65}}, + {{0x80000001, 0}, Leaf{0x00500F20, 0x000012E9, 0x000035FF, 0x2FD3FBFF}}, + }); + const auto info = GetX86Info(); + + EXPECT_STREQ(info.vendor, "AuthenticAMD"); + EXPECT_EQ(info.family, 0x14); + EXPECT_EQ(info.model, 0x02); + EXPECT_EQ(GetX86Microarchitecture(&info), X86Microarchitecture::AMD_BOBCAT); +} + +// http://users.atw.hu/instlatx64/AuthenticAMD/AuthenticAMD0670F00_K15_StoneyRidge_CPUID.txt +TEST_F(CpuidX86Test, AMD_K15_EXCAVATOR_STONEY_RIDGE) +{ + g_fake_cpu->SetLeaves({ + {{0x00000000, 0}, Leaf{0x0000000D, 0x68747541, 0x444D4163, 0x69746E65}}, + {{0x00000001, 0}, Leaf{0x00670F00, 0x00020800, 0x7ED8320B, 0x178BFBFF}}, + {{0x00000007, 0}, Leaf{0x00000000, 0x000001A9, 0x00000000, 0x00000000}}, + {{0x80000000, 0}, Leaf{0x8000001E, 0x68747541, 0x444D4163, 0x69746E65}}, + {{0x80000001, 0}, Leaf{0x00670F00, 0x00000000, 0x2FABBFFF, 0x2FD3FBFF}}, + {{0x80000002, 0}, Leaf{0x20444D41, 0x392D3941, 0x20303134, 0x45444152}}, + {{0x80000003, 0}, Leaf{0x52204E4F, 0x35202C35, 0x4D4F4320, 0x45545550}}, + {{0x80000004, 0}, Leaf{0x524F4320, 0x32205345, 0x47332B43, 0x00202020}}, + }); + const auto info = GetX86Info(); + + EXPECT_STREQ(info.vendor, "AuthenticAMD"); + EXPECT_EQ(info.family, 0x15); + EXPECT_EQ(info.model, 0x70); + EXPECT_EQ(GetX86Microarchitecture(&info), + X86Microarchitecture::AMD_EXCAVATOR); + + char brand_string[49]; + FillX86BrandString(brand_string); + EXPECT_STREQ(brand_string, "AMD A9-9410 RADEON R5, 5 COMPUTE CORES 2C+3G "); +} + +// http://users.atw.hu/instlatx64/AuthenticAMD/AuthenticAMD0600F20_K15_AbuDhabi_CPUID0.txt +TEST_F(CpuidX86Test, AMD_K15_PILEDRIVER_ABU_DHABI) +{ + g_fake_cpu->SetLeaves({ + {{0x00000000, 0}, Leaf{0x0000000D, 0x68747541, 0x444D4163, 0x69746E65}}, + {{0x00000001, 0}, Leaf{0x00600F20, 0x00100800, 0x3E98320B, 0x178BFBFF}}, + {{0x00000007, 0}, Leaf{0x00000000, 0x00000008, 0x00000000, 0x00000000}}, + {{0x80000000, 0}, Leaf{0x8000001E, 0x68747541, 0x444D4163, 0x69746E65}}, + {{0x80000001, 0}, Leaf{0x00600F20, 0x30000000, 0x01EBBFFF, 0x2FD3FBFF}}, + {{0x80000002, 0}, Leaf{0x20444D41, 0x6574704F, 0x286E6F72, 0x20296D74}}, + {{0x80000003, 0}, Leaf{0x636F7250, 0x6F737365, 0x33362072, 0x20203637}}, + {{0x80000004, 0}, Leaf{0x20202020, 0x20202020, 0x20202020, 0x00202020}}, + }); + const auto info = GetX86Info(); + + EXPECT_STREQ(info.vendor, "AuthenticAMD"); + EXPECT_EQ(info.family, 0x15); + EXPECT_EQ(info.model, 0x02); + EXPECT_EQ(GetX86Microarchitecture(&info), + X86Microarchitecture::AMD_PILEDRIVER); + + char brand_string[49]; + FillX86BrandString(brand_string); + EXPECT_STREQ(brand_string, "AMD Opteron(tm) Processor 6376 "); +} + +// http://users.atw.hu/instlatx64/AuthenticAMD/AuthenticAMD0600F12_K15_Interlagos_CPUID3.txt +TEST_F(CpuidX86Test, AMD_K15_BULLDOZER_INTERLAGOS) +{ + g_fake_cpu->SetLeaves({ + {{0x00000000, 0}, Leaf{0x0000000D, 0x68747541, 0x444D4163, 0x69746E65}}, + {{0x00000001, 0}, Leaf{0x00600F12, 0x000C0800, 0x1E98220B, 0x178BFBFF}}, + {{0x00000007, 0}, Leaf{0x00000000, 0x00000000, 0x00000000, 0x00000000}}, + {{0x80000000, 0}, Leaf{0x8000001E, 0x68747541, 0x444D4163, 0x69746E65}}, + {{0x80000001, 0}, Leaf{0x00600F12, 0x30000000, 0x01C9BFFF, 0x2FD3FBFF}}, + {{0x80000002, 0}, Leaf{0x20444D41, 0x6574704F, 0x286E6F72, 0x20294D54}}, + {{0x80000003, 0}, Leaf{0x636F7250, 0x6F737365, 0x32362072, 0x20203833}}, + {{0x80000004, 0}, Leaf{0x20202020, 0x20202020, 0x20202020, 0x00202020}}, + }); + const auto info = GetX86Info(); + + EXPECT_STREQ(info.vendor, "AuthenticAMD"); + EXPECT_EQ(info.family, 0x15); + EXPECT_EQ(info.model, 0x01); + EXPECT_EQ(GetX86Microarchitecture(&info), + X86Microarchitecture::AMD_BULLDOZER); + + char brand_string[49]; + FillX86BrandString(brand_string); + EXPECT_STREQ(brand_string, "AMD Opteron(TM) Processor 6238 "); +} + // http://users.atw.hu/instlatx64/AuthenticAMD0630F81_K15_Godavari_CPUID.txt -TEST_F(CpuidX86Test, AMD_K15) +TEST_F(CpuidX86Test, AMD_K15_STREAMROLLER_GODAVARI) { g_fake_cpu->SetLeaves({ {{0x00000000, 0}, Leaf{0x0000000D, 0x68747541, 0x444D4163, 0x69746E65}}, @@ -325,13 +496,188 @@ TEST_F(CpuidX86Test, AMD_K15) EXPECT_EQ(info.model, 0x38); EXPECT_EQ(info.stepping, 0x01); EXPECT_EQ(GetX86Microarchitecture(&info), - X86Microarchitecture::AMD_BULLDOZER); + X86Microarchitecture::AMD_STREAMROLLER); char brand_string[49]; FillX86BrandString(brand_string); EXPECT_STREQ(brand_string, "AMD A8-7670K Radeon R7, 10 Compute Cores 4C+6G "); } +// http://users.atw.hu/instlatx64/AuthenticAMD/AuthenticAMD0700F01_K16_Kabini_CPUID.txt +TEST_F(CpuidX86Test, AMD_K16_JAGUAR_KABINI) +{ + g_fake_cpu->SetLeaves({ + {{0x00000000, 0}, Leaf{0x0000000D, 0x68747541, 0x444D4163, 0x69746E65}}, + {{0x00000001, 0}, Leaf{0x00700F01, 0x00040800, 0x3ED8220B, 0x178BFBFF}}, + {{0x00000007, 0}, Leaf{0x00000000, 0x00000008, 0x00000000, 0x00000000}}, + {{0x80000000, 0}, Leaf{0x8000001E, 0x68747541, 0x444D4163, 0x69746E65}}, + {{0x80000001, 0}, Leaf{0x00700F01, 0x00000000, 0x154037FF, 0x2FD3FBFF}}, + {{0x80000002, 0}, Leaf{0x20444D41, 0x352D3441, 0x20303030, 0x20555041}}, + {{0x80000003, 0}, Leaf{0x68746977, 0x64615220, 0x286E6F65, 0x20294D54}}, + {{0x80000004, 0}, Leaf{0x47204448, 0x68706172, 0x20736369, 0x00202020}}, + }); + const auto info = GetX86Info(); + + EXPECT_STREQ(info.vendor, "AuthenticAMD"); + EXPECT_EQ(info.family, 0x16); + EXPECT_EQ(info.model, 0x00); + EXPECT_EQ(GetX86Microarchitecture(&info), X86Microarchitecture::AMD_JAGUAR); + + char brand_string[49]; + FillX86BrandString(brand_string); + EXPECT_STREQ(brand_string, "AMD A4-5000 APU with Radeon(TM) HD Graphics "); +} + +// http://users.atw.hu/instlatx64/AuthenticAMD/AuthenticAMD0730F01_K16_Beema_CPUID2.txt +TEST_F(CpuidX86Test, AMD_K16_PUMA_BEEMA) +{ + g_fake_cpu->SetLeaves({ + {{0x00000000, 0}, Leaf{0x0000000D, 0x68747541, 0x444D4163, 0x69746E65}}, + {{0x00000001, 0}, Leaf{0x00730F01, 0x00040800, 0x7ED8220B, 0x178BFBFF}}, + {{0x00000007, 0}, Leaf{0x00000000, 0x00000008, 0x00000000, 0x00000000}}, + {{0x80000000, 0}, Leaf{0x8000001E, 0x68747541, 0x444D4163, 0x69746E65}}, + {{0x80000001, 0}, Leaf{0x00730F01, 0x00000000, 0x1D4037FF, 0x2FD3FBFF}}, + {{0x80000002, 0}, Leaf{0x20444D41, 0x362D3641, 0x20303133, 0x20555041}}, + {{0x80000003, 0}, Leaf{0x68746977, 0x444D4120, 0x64615220, 0x206E6F65}}, + {{0x80000004, 0}, Leaf{0x47203452, 0x68706172, 0x20736369, 0x00202020}}, + }); + const auto info = GetX86Info(); + + EXPECT_STREQ(info.vendor, "AuthenticAMD"); + EXPECT_EQ(info.family, 0x16); + EXPECT_EQ(info.model, 0x30); + EXPECT_EQ(GetX86Microarchitecture(&info), X86Microarchitecture::AMD_PUMA); + + char brand_string[49]; + FillX86BrandString(brand_string); + EXPECT_STREQ(brand_string, "AMD A6-6310 APU with AMD Radeon R4 Graphics "); +} + +// http://users.atw.hu/instlatx64/AuthenticAMD/AuthenticAMD0820F01_K17_Dali_CPUID.txt +TEST_F(CpuidX86Test, AMD_K17_ZEN_DALI) +{ + g_fake_cpu->SetLeaves({ + {{0x00000000, 0}, Leaf{0x0000000D, 0x68747541, 0x444D4163, 0x69746E65}}, + {{0x00000001, 0}, Leaf{0x00820F01, 0x00020800, 0x7ED8320B, 0x178BFBFF}}, + {{0x00000007, 0}, Leaf{0x00000000, 0x209C01A9, 0x00000000, 0x00000000}}, + {{0x80000000, 0}, Leaf{0x8000001F, 0x68747541, 0x444D4163, 0x69746E65}}, + {{0x80000001, 0}, Leaf{0x00820F01, 0x00000000, 0x35C233FF, 0x2FD3FBFF}}, + {{0x80000002, 0}, Leaf{0x20444D41, 0x30323033, 0x69772065, 0x52206874}}, + {{0x80000003, 0}, Leaf{0x6F656461, 0x7247206E, 0x69687061, 0x20207363}}, + {{0x80000004, 0}, Leaf{0x20202020, 0x20202020, 0x20202020, 0x00202020}}, + }); + const auto info = GetX86Info(); + + EXPECT_STREQ(info.vendor, "AuthenticAMD"); + EXPECT_EQ(info.family, 0x17); + EXPECT_EQ(info.model, 0x20); + EXPECT_EQ(GetX86Microarchitecture(&info), X86Microarchitecture::AMD_ZEN); + + char brand_string[49]; + FillX86BrandString(brand_string); + EXPECT_STREQ(brand_string, "AMD 3020e with Radeon Graphics "); +} + +// http://users.atw.hu/instlatx64/AuthenticAMD/AuthenticAMD0800F82_K17_ZenP_CPUID.txt +TEST_F(CpuidX86Test, AMD_K17_ZEN_PLUS_PINNACLE_RIDGE) +{ + g_fake_cpu->SetLeaves({ + {{0x00000000, 0}, Leaf{0x0000000D, 0x68747541, 0x444D4163, 0x69746E65}}, + {{0x00000001, 0}, Leaf{0x00800F82, 0x00100800, 0x7ED8320B, 0x178BFBFF}}, + {{0x00000007, 0}, Leaf{0x00000000, 0x209C01A9, 0x00000000, 0x00000000}}, + {{0x80000000, 0}, Leaf{0x8000001F, 0x68747541, 0x444D4163, 0x69746E65}}, + {{0x80000001, 0}, Leaf{0x00800F82, 0x20000000, 0x35C233FF, 0x2FD3FBFF}}, + {{0x80000002, 0}, Leaf{0x20444D41, 0x657A7952, 0x2037206E, 0x30303732}}, + {{0x80000003, 0}, Leaf{0x69452058, 0x2D746867, 0x65726F43, 0x6F725020}}, + {{0x80000004, 0}, Leaf{0x73736563, 0x2020726F, 0x20202020, 0x00202020}}, + }); + const auto info = GetX86Info(); + + EXPECT_STREQ(info.vendor, "AuthenticAMD"); + EXPECT_EQ(info.family, 0x17); + EXPECT_EQ(info.model, 0x08); + EXPECT_EQ(GetX86Microarchitecture(&info), X86Microarchitecture::AMD_ZEN_PLUS); + + char brand_string[49]; + FillX86BrandString(brand_string); + EXPECT_STREQ(brand_string, "AMD Ryzen 7 2700X Eight-Core Processor "); +} + +// http://users.atw.hu/instlatx64/AuthenticAMD/AuthenticAMD0840F70_K17_CPUID.txt +TEST_F(CpuidX86Test, AMD_K17_ZEN2_XBOX_SERIES_X) +{ + g_fake_cpu->SetLeaves({ + {{0x00000000, 0}, Leaf{0x00000010, 0x68747541, 0x444D4163, 0x69746E65}}, + {{0x00000001, 0}, Leaf{0x00840F70, 0x00100800, 0x7ED8320B, 0x178BFBFF}}, + {{0x00000007, 0}, Leaf{0x00000000, 0x219C91A9, 0x00400004, 0x00000000}}, + {{0x80000000, 0}, Leaf{0x80000020, 0x68747541, 0x444D4163, 0x69746E65}}, + {{0x80000001, 0}, Leaf{0x00840F70, 0x00000000, 0xF5C2B7FF, 0x2FD3FBFF}}, + {{0x80000002, 0}, Leaf{0x20444D41, 0x30303734, 0x2D382053, 0x65726F43}}, + {{0x80000003, 0}, Leaf{0x6F725020, 0x73736563, 0x4420726F, 0x746B7365}}, + {{0x80000004, 0}, Leaf{0x4B20706F, 0x00007469, 0x00000000, 0x00000000}}, + }); + const auto info = GetX86Info(); + + EXPECT_STREQ(info.vendor, "AuthenticAMD"); + EXPECT_EQ(info.family, 0x17); + EXPECT_EQ(info.model, 0x47); + EXPECT_EQ(GetX86Microarchitecture(&info), X86Microarchitecture::AMD_ZEN2); + + char brand_string[49]; + FillX86BrandString(brand_string); + EXPECT_STREQ(brand_string, "AMD 4700S 8-Core Processor Desktop Kit"); +} + +// http://users.atw.hu/instlatx64/HygonGenuine/HygonGenuine0900F02_Hygon_CPUID3.txt +TEST_F(CpuidX86Test, AMD_K18_ZEN_DHYANA) +{ + g_fake_cpu->SetLeaves({ + {{0x00000000, 0}, Leaf{0x0000000D, 0x6F677948, 0x656E6975, 0x6E65476E}}, + {{0x00000001, 0}, Leaf{0x00900F02, 0x00100800, 0x74D83209, 0x178BFBFF}}, + {{0x00000007, 0}, Leaf{0x00000000, 0x009C01A9, 0x0040068C, 0x00000000}}, + {{0x80000000, 0}, Leaf{0x8000001F, 0x6F677948, 0x656E6975, 0x6E65476E}}, + {{0x80000001, 0}, Leaf{0x00900F02, 0x60000000, 0x35C233FF, 0x2FD3FBFF}}, + {{0x80000002, 0}, Leaf{0x6F677948, 0x3843206E, 0x31332036, 0x20203538}}, + {{0x80000003, 0}, Leaf{0x6F632D38, 0x50206572, 0x65636F72, 0x726F7373}}, + {{0x80000004, 0}, Leaf{0x20202020, 0x20202020, 0x20202020, 0x00202020}}, + }); + const auto info = GetX86Info(); + + EXPECT_STREQ(info.vendor, "HygonGenuine"); + EXPECT_EQ(info.family, 0x18); + EXPECT_EQ(info.model, 0x00); + EXPECT_EQ(GetX86Microarchitecture(&info), X86Microarchitecture::AMD_ZEN); + + char brand_string[49]; + FillX86BrandString(brand_string); + EXPECT_STREQ(brand_string, "Hygon C86 3185 8-core Processor "); +} + +// http://users.atw.hu/instlatx64/AuthenticAMD/AuthenticAMD0A20F10_K19_Vermeer2_CPUID.txt +TEST_F(CpuidX86Test, AMD_K19_ZEN3_VERMEER) +{ + g_fake_cpu->SetLeaves({ + {{0x00000000, 0}, Leaf{0x00000010, 0x68747541, 0x444D4163, 0x69746E65}}, + {{0x00000001, 0}, Leaf{0x00A20F10, 0x01180800, 0x7ED8320B, 0x178BFBFF}}, + {{0x00000007, 0}, Leaf{0x00000000, 0x219C97A9, 0x0040068C, 0x00000000}}, + {{0x80000000, 0}, Leaf{0x80000023, 0x68747541, 0x444D4163, 0x69746E65}}, + {{0x80000001, 0}, Leaf{0x00A20F10, 0x20000000, 0x75C237FF, 0x2FD3FBFF}}, + {{0x80000002, 0}, Leaf{0x20444D41, 0x657A7952, 0x2039206E, 0x30303935}}, + {{0x80000003, 0}, Leaf{0x32312058, 0x726F432D, 0x72502065, 0x7365636F}}, + {{0x80000004, 0}, Leaf{0x20726F73, 0x20202020, 0x20202020, 0x00202020}}, + }); + const auto info = GetX86Info(); + + EXPECT_STREQ(info.vendor, "AuthenticAMD"); + EXPECT_EQ(info.family, 0x19); + EXPECT_EQ(info.model, 0x21); + EXPECT_EQ(GetX86Microarchitecture(&info), X86Microarchitecture::AMD_ZEN3); + + char brand_string[49]; + FillX86BrandString(brand_string); + EXPECT_STREQ(brand_string, "AMD Ryzen 9 5900X 12-Core Processor "); +} + // https://github.com/InstLatx64/InstLatx64/blob/master/GenuineIntel/GenuineIntel00106A1_Nehalem_CPUID.txt TEST_F(CpuidX86Test, Nehalem) { @@ -344,21 +690,29 @@ TEST_F(CpuidX86Test, Nehalem) PF_XMMI64_INSTRUCTIONS_AVAILABLE); g_fake_cpu->SetWindowsIsProcessorFeaturePresent( PF_SSE3_INSTRUCTIONS_AVAILABLE); -#endif // CPU_FEATURES_OS_WINDOWS -#if defined(CPU_FEATURES_OS_DARWIN) +#elif defined(CPU_FEATURES_OS_DARWIN) g_fake_cpu->SetDarwinSysCtlByName("hw.optional.sse"); g_fake_cpu->SetDarwinSysCtlByName("hw.optional.sse2"); g_fake_cpu->SetDarwinSysCtlByName("hw.optional.sse3"); g_fake_cpu->SetDarwinSysCtlByName("hw.optional.supplementalsse3"); g_fake_cpu->SetDarwinSysCtlByName("hw.optional.sse4_1"); g_fake_cpu->SetDarwinSysCtlByName("hw.optional.sse4_2"); -#endif // CPU_FEATURES_OS_DARWIN -#if defined(CPU_FEATURES_OS_LINUX_OR_ANDROID) +#elif defined(CPU_FEATURES_OS_FREEBSD) + auto& fs = GetEmptyFilesystem(); + fs.CreateFile("/var/run/dmesg.boot", R"( + ---<>--- +Copyright (c) 1992-2020 The FreeBSD Project. +FreeBSD is a registered trademark of The FreeBSD Foundation. + Features=0x1783fbff + Features2=0x5eda2203 +real memory = 2147418112 (2047 MB) +)"); +#elif defined(CPU_FEATURES_OS_LINUX_OR_ANDROID) auto& fs = GetEmptyFilesystem(); fs.CreateFile("/proc/cpuinfo", R"(processor : flags : fpu mmx sse sse2 sse3 ssse3 sse4_1 sse4_2 )"); -#endif // CPU_FEATURES_OS_LINUX_OR_ANDROID +#endif g_fake_cpu->SetLeaves({ {{0x00000000, 0}, Leaf{0x0000000B, 0x756E6547, 0x6C65746E, 0x49656E69}}, {{0x00000001, 0}, Leaf{0x000106A2, 0x00100800, 0x00BCE3BD, 0xBFEBFBFF}}, @@ -401,13 +755,13 @@ flags : fpu mmx sse sse2 sse3 ssse3 sse4_1 sse4_2 EXPECT_TRUE(info.features.sse); EXPECT_TRUE(info.features.sse2); EXPECT_TRUE(info.features.sse3); -#ifndef CPU_FEATURES_OS_WINDOWS +#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 // CPU_FEATURES_OS_WINDOWS +#endif // !defined(CPU_FEATURES_OS_WINDOWS) } // https://github.com/InstLatx64/InstLatx64/blob/master/GenuineIntel/GenuineIntel0030673_Silvermont3_CPUID.txt @@ -422,21 +776,29 @@ TEST_F(CpuidX86Test, Atom) PF_XMMI64_INSTRUCTIONS_AVAILABLE); g_fake_cpu->SetWindowsIsProcessorFeaturePresent( PF_SSE3_INSTRUCTIONS_AVAILABLE); -#endif // CPU_FEATURES_OS_WINDOWS -#if defined(CPU_FEATURES_OS_DARWIN) +#elif defined(CPU_FEATURES_OS_DARWIN) g_fake_cpu->SetDarwinSysCtlByName("hw.optional.sse"); g_fake_cpu->SetDarwinSysCtlByName("hw.optional.sse2"); g_fake_cpu->SetDarwinSysCtlByName("hw.optional.sse3"); g_fake_cpu->SetDarwinSysCtlByName("hw.optional.supplementalsse3"); g_fake_cpu->SetDarwinSysCtlByName("hw.optional.sse4_1"); g_fake_cpu->SetDarwinSysCtlByName("hw.optional.sse4_2"); -#endif // CPU_FEATURES_OS_DARWIN -#if defined(CPU_FEATURES_OS_LINUX_OR_ANDROID) +#elif defined(CPU_FEATURES_OS_FREEBSD) + auto& fs = GetEmptyFilesystem(); + fs.CreateFile("/var/run/dmesg.boot", R"( + ---<>--- +Copyright (c) 1992-2020 The FreeBSD Project. +FreeBSD is a registered trademark of The FreeBSD Foundation. + Features=0x1783fbff + Features2=0x5eda2203 +real memory = 2147418112 (2047 MB) +)"); +#elif defined(CPU_FEATURES_OS_LINUX_OR_ANDROID) auto& fs = GetEmptyFilesystem(); fs.CreateFile("/proc/cpuinfo", R"( flags : fpu mmx sse sse2 sse3 ssse3 sse4_1 sse4_2 )"); -#endif // CPU_FEATURES_OS_LINUX_OR_ANDROID +#endif g_fake_cpu->SetLeaves({ {{0x00000000, 0}, Leaf{0x0000000B, 0x756E6547, 0x6C65746E, 0x49656E69}}, {{0x00000001, 0}, Leaf{0x00030673, 0x00100800, 0x41D8E3BF, 0xBFEBFBFF}}, @@ -479,13 +841,13 @@ flags : fpu mmx sse sse2 sse3 ssse3 sse4_1 sse4_2 EXPECT_TRUE(info.features.sse); EXPECT_TRUE(info.features.sse2); EXPECT_TRUE(info.features.sse3); -#ifndef CPU_FEATURES_OS_WINDOWS +#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 // CPU_FEATURES_OS_WINDOWS +#endif // !defined(CPU_FEATURES_OS_WINDOWS) } // https://github.com/InstLatx64/InstLatx64/blob/master/GenuineIntel/GenuineIntel0000673_P3_KatmaiDP_CPUID.txt @@ -496,16 +858,23 @@ TEST_F(CpuidX86Test, P3) #if defined(CPU_FEATURES_OS_WINDOWS) g_fake_cpu->SetWindowsIsProcessorFeaturePresent( PF_XMMI_INSTRUCTIONS_AVAILABLE); -#endif // CPU_FEATURES_OS_WINDOWS -#if defined(CPU_FEATURES_OS_DARWIN) +#elif defined(CPU_FEATURES_OS_DARWIN) g_fake_cpu->SetDarwinSysCtlByName("hw.optional.sse"); -#endif // CPU_FEATURES_OS_DARWIN -#if defined(CPU_FEATURES_OS_LINUX_OR_ANDROID) +#elif defined(CPU_FEATURES_OS_FREEBSD) + auto& fs = GetEmptyFilesystem(); + fs.CreateFile("/var/run/dmesg.boot", R"( + ---<>--- +Copyright (c) 1992-2020 The FreeBSD Project. +FreeBSD is a registered trademark of The FreeBSD Foundation. + Features=0x1783fbff +real memory = 2147418112 (2047 MB) +)"); +#elif defined(CPU_FEATURES_OS_LINUX_OR_ANDROID) auto& fs = GetEmptyFilesystem(); fs.CreateFile("/proc/cpuinfo", R"( flags : fpu mmx sse )"); -#endif // CPU_FEATURES_OS_LINUX_OR_ANDROID +#endif g_fake_cpu->SetLeaves({ {{0x00000000, 0}, Leaf{0x00000003, 0x756E6547, 0x6C65746E, 0x49656E69}}, {{0x00000001, 0}, Leaf{0x00000673, 0x00000000, 0x00000000, 0x0387FBFF}}, @@ -528,13 +897,13 @@ flags : fpu mmx sse EXPECT_TRUE(info.features.sse); EXPECT_FALSE(info.features.sse2); EXPECT_FALSE(info.features.sse3); -#ifndef CPU_FEATURES_OS_WINDOWS +#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 // CPU_FEATURES_OS_WINDOWS +#endif // !defined(CPU_FEATURES_OS_WINDOWS) } // TODO(user): test what happens when xsave/osxsave are not present. diff --git a/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/cpu_features/test/hwcaps_for_testing.cc b/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/cpu_features/test/hwcaps_for_testing.cc index 6a474108a..1fba4409c 100644 --- a/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/cpu_features/test/hwcaps_for_testing.cc +++ b/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/cpu_features/test/hwcaps_for_testing.cc @@ -10,7 +10,8 @@ namespace cpu_features namespace { static auto* const g_hardware_capabilities = new HardwareCapabilities(); -static auto* const g_platform_types = new PlatformType(); +static const char* g_platform_pointer = nullptr; +static const char* g_base_platform_pointer = nullptr; } // namespace void SetHardwareCapabilities(uint32_t hwcaps, uint32_t hwcaps2) @@ -18,20 +19,27 @@ void SetHardwareCapabilities(uint32_t hwcaps, uint32_t hwcaps2) g_hardware_capabilities->hwcaps = hwcaps; g_hardware_capabilities->hwcaps2 = hwcaps2; } +void SetPlatformPointer(const char* string) { g_platform_pointer = string; } +void SetBasePlatformPointer(const char* string) +{ + g_base_platform_pointer = string; +} + +void ResetHwcaps() +{ + SetHardwareCapabilities(0, 0); + SetPlatformPointer(nullptr); + SetBasePlatformPointer(nullptr); +} HardwareCapabilities CpuFeatures_GetHardwareCapabilities(void) { return *g_hardware_capabilities; } - -void SetPlatformTypes(const char* platform, const char* base_platform) +const char* CpuFeatures_GetPlatformPointer(void) { return g_platform_pointer; } +const char* CpuFeatures_GetBasePlatformPointer(void) { - CpuFeatures_StringView_CopyString(str(platform), g_platform_types->platform, - sizeof(g_platform_types->platform)); - CpuFeatures_StringView_CopyString(str(base_platform), - g_platform_types->base_platform, - sizeof(g_platform_types->base_platform)); + return g_base_platform_pointer; } -PlatformType CpuFeatures_GetPlatformType(void) { return *g_platform_types; } } // namespace cpu_features diff --git a/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/cpu_features/test/hwcaps_for_testing.h b/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/cpu_features/test/hwcaps_for_testing.h index 327a8b42e..5e7ac0224 100644 --- a/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/cpu_features/test/hwcaps_for_testing.h +++ b/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/cpu_features/test/hwcaps_for_testing.h @@ -9,7 +9,11 @@ namespace cpu_features { void SetHardwareCapabilities(uint32_t hwcaps, uint32_t hwcaps2); -void SetPlatformTypes(const char *platform, const char *base_platform); +void SetPlatformPointer(const char* string); +void SetBasePlatformPointer(const char* string); + +// To be called before each test. +void ResetHwcaps(); } // namespace cpu_features