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 ef5834643..8598714c9 100644 --- a/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/CMakeLists.txt +++ b/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/CMakeLists.txt @@ -270,10 +270,6 @@ elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "^(powerpc|ppc)") endif() if(CMAKE_VERSION VERSION_GREATER 3.0 AND SUPPORTED_CPU_FEATURES_ARCH) - set(BUILD_PIC ON CACHE BOOL - "Build cpu_features with Position Independent Code (PIC)." - FORCE - ) set(USE_CPU_FEATURES ON) set(BUILD_SHARED_LIBS_SAVED "${BUILD_SHARED_LIBS}") set(BUILD_SHARED_LIBS OFF) 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..9001f224d 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 @@ -32,13 +32,11 @@ option(BUILD_TESTING "Enable test (depends on googletest)." OFF) # As a consequence it is discouraged to use cpu_features as a shared library because different compilers may interpret the code in different ways. # Prefer static linking from source whenever possible. option(BUILD_SHARED_LIBS "Build library as shared." OFF) -# PIC -option(BUILD_PIC "Build with Position Independant Code." OFF) # Default is off at least for GCC # Force PIC on unix when building shared libs # see: https://en.wikipedia.org/wiki/Position-independent_code if(BUILD_SHARED_LIBS AND UNIX) - set(BUILD_PIC ON) + option(CMAKE_POSITION_INDEPENDENT_CODE "Build with Position Independant Code." ON) endif() include(CheckIncludeFile) @@ -110,7 +108,6 @@ add_library(utils OBJECT ${PROJECT_SOURCE_DIR}/src/stack_line_reader.c ${PROJECT_SOURCE_DIR}/src/string_view.c ) -set_property(TARGET utils PROPERTY POSITION_INDEPENDENT_CODE ${BUILD_PIC}) setup_include_and_definitions(utils) # @@ -131,7 +128,6 @@ if(UNIX) if(HAVE_STRONG_GETAUXVAL) target_compile_definitions(unix_based_hardware_detection PRIVATE HAVE_STRONG_GETAUXVAL) endif() - set_property(TARGET unix_based_hardware_detection PROPERTY POSITION_INDEPENDENT_CODE ${BUILD_PIC}) endif() # @@ -148,7 +144,6 @@ add_library(cpu_features ${CPU_FEATURES_HDRS} ${CPU_FEATURES_SRCS}) set_target_properties(cpu_features PROPERTIES PUBLIC_HEADER "${CPU_FEATURES_HDRS}") setup_include_and_definitions(cpu_features) target_link_libraries(cpu_features PUBLIC ${CMAKE_DL_LIBS}) -set_property(TARGET cpu_features PROPERTY POSITION_INDEPENDENT_CODE ${BUILD_PIC}) target_include_directories(cpu_features PUBLIC $ ) @@ -237,6 +232,7 @@ install(TARGETS cpu_features list_cpu_features ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} + BUNDLE DESTINATION ${CMAKE_INSTALL_BINDIR} ) install(EXPORT CpuFeaturesTargets NAMESPACE CpuFeatures:: 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 faccfa84e..9abde468c 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 @@ -10,6 +10,11 @@ CPU_FEATURES_START_CPP_NAMESPACE +// CPUID Vendors +#define CPU_FEATURES_VENDOR_GENUINE_INTEL "GenuineIntel" +#define CPU_FEATURES_VENDOR_AUTHENTIC_AMD "AuthenticAMD" +#define CPU_FEATURES_VENDOR_HYGON_GENUINE "HygonGenuine" + // See https://en.wikipedia.org/wiki/CPUID for a list of x86 cpu features. // The field names are based on the short name provided in the wikipedia tables. typedef struct diff --git a/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/cpu_features/include/internal/string_view.h b/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/cpu_features/include/internal/string_view.h index 9fa0c9e25..b687da035 100644 --- a/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/cpu_features/include/internal/string_view.h +++ b/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/cpu_features/include/internal/string_view.h @@ -87,7 +87,8 @@ void CpuFeatures_StringView_CopyString(const StringView src, char* dst, // Checks if line contains the specified whitespace separated word. bool CpuFeatures_StringView_HasWord(const StringView line, - const char* const word); + const char* const word, + const char separator); // Get key/value from line. key and value are separated by ": ". // key and value are cleaned up from leading and trailing whitespaces. diff --git a/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/cpu_features/src/cpuinfo_aarch64.c b/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/cpu_features/src/cpuinfo_aarch64.c index 8d16acaa6..da7972763 100644 --- a/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/cpu_features/src/cpuinfo_aarch64.c +++ b/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/cpu_features/src/cpuinfo_aarch64.c @@ -107,8 +107,8 @@ static bool HandleAarch64Line(const LineResult result, { for (size_t i = 0; i < AARCH64_LAST_; ++i) { - kSetters[i](&info->features, - CpuFeatures_StringView_HasWord(value, kCpuInfoFlags[i])); + kSetters[i](&info->features, CpuFeatures_StringView_HasWord( + value, kCpuInfoFlags[i], ' ')); } } else if (CpuFeatures_StringView_IsEquals(key, str("CPU implementer"))) diff --git a/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/cpu_features/src/cpuinfo_arm.c b/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/cpu_features/src/cpuinfo_arm.c index 040aab95a..69abe91f4 100644 --- a/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/cpu_features/src/cpuinfo_arm.c +++ b/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/cpu_features/src/cpuinfo_arm.c @@ -71,8 +71,8 @@ static bool HandleArmLine(const LineResult result, ArmInfo* const info, { for (size_t i = 0; i < ARM_LAST_; ++i) { - kSetters[i](&info->features, - CpuFeatures_StringView_HasWord(value, kCpuInfoFlags[i])); + kSetters[i](&info->features, CpuFeatures_StringView_HasWord( + value, kCpuInfoFlags[i], ' ')); } } else if (CpuFeatures_StringView_IsEquals(key, str("CPU implementer"))) diff --git a/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/cpu_features/src/cpuinfo_mips.c b/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/cpu_features/src/cpuinfo_mips.c index 4d223d0e1..31794dc93 100644 --- a/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/cpu_features/src/cpuinfo_mips.c +++ b/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/cpu_features/src/cpuinfo_mips.c @@ -28,8 +28,8 @@ static bool HandleMipsLine(const LineResult result, { for (size_t i = 0; i < MIPS_LAST_; ++i) { - kSetters[i](features, - CpuFeatures_StringView_HasWord(value, kCpuInfoFlags[i])); + kSetters[i](features, CpuFeatures_StringView_HasWord( + value, kCpuInfoFlags[i], ' ')); } } } 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 def6b13a3..d2d68a437 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 @@ -71,7 +71,7 @@ static bool HandlePPCLine(const LineResult result, StringView key, value; if (CpuFeatures_StringView_GetAttributeKeyValue(line, &key, &value)) { - if (CpuFeatures_StringView_HasWord(key, "platform")) + if (CpuFeatures_StringView_HasWord(key, "platform", ' ')) { CpuFeatures_StringView_CopyString(value, strings->platform, sizeof(strings->platform)); 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 744ae8ac6..3863163ae 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 @@ -88,7 +88,6 @@ 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 #elif defined(CPU_FEATURES_OS_DARWIN) #if !defined(HAVE_SYSCTLBYNAME) #error "Darwin needs support for sysctlbyname" @@ -98,6 +97,8 @@ #error "Unsupported OS" #endif // CPU_FEATURES_OS +#include "internal/string_view.h" + //////////////////////////////////////////////////////////////////////////////// // Definitions for CpuId and GetXCR0Eax. //////////////////////////////////////////////////////////////////////////////// @@ -267,6 +268,11 @@ static int IsVendor(const Leaf leaf, const char* const name) return leaf.ebx == ebx && leaf.ecx == ecx && leaf.edx == edx; } +static int IsVendorByX86Info(const X86Info* info, const char* const name) +{ + return memcmp(info->vendor, name, sizeof(info->vendor)) == 0; +} + static const CacheLevelInfo kEmptyCacheLevelInfo; static CacheLevelInfo GetCacheLevelInfo(const uint32_t reg) @@ -1129,55 +1135,52 @@ static CacheLevelInfo GetCacheLevelInfo(const uint32_t reg) } } -static void GetByteArrayFromRegister(uint32_t result[4], const uint32_t reg) -{ - for (int i = 0; i < 4; ++i) - { - result[i] = ExtractBitRange(reg, (i + 1) * 8, i * 8); - } -} - +// From https://www.felixcloutier.com/x86/cpuid#tbl-3-12 static void ParseLeaf2(const int max_cpuid_leaf, CacheInfo* info) { Leaf leaf = SafeCpuId(max_cpuid_leaf, 2); - uint32_t registers[] = {leaf.eax, leaf.ebx, leaf.ecx, leaf.edx}; - for (int i = 0; i < 4; ++i) + // The least-significant byte in register EAX (register AL) will always return + // 01H. Software should ignore this value and not interpret it as an + // informational descriptor. + leaf.eax &= 0xFFFFFF00; // Zeroing out AL. 0 is the empty descriptor. + // The most significant bit (bit 31) of each register indicates whether the + // register contains valid information (set to 0) or is reserved (set to 1). + if (IsBitSet(leaf.eax, 31)) leaf.eax = 0; + if (IsBitSet(leaf.ebx, 31)) leaf.ebx = 0; + if (IsBitSet(leaf.ecx, 31)) leaf.ecx = 0; + if (IsBitSet(leaf.edx, 31)) leaf.edx = 0; + + uint8_t data[16]; +#if __STDC_VERSION__ >= 201112L + _Static_assert(sizeof(Leaf) == sizeof(data), "Leaf must be 16 bytes"); +#endif + memcpy(&data, &leaf, sizeof(data)); + for (size_t i = 0; i < sizeof(data); ++i) { - if (registers[i] & (1U << 31)) - { - continue; // register does not contains valid information - } - uint32_t bytes[4]; - GetByteArrayFromRegister(bytes, registers[i]); - for (int j = 0; j < 4; ++j) - { - if (bytes[j] == 0xFF) - break; // leaf 4 should be used to fetch cache information - info->levels[info->size] = GetCacheLevelInfo(bytes[j]); - } + const uint8_t descriptor = data[i]; + if (descriptor == 0) continue; + info->levels[info->size] = GetCacheLevelInfo(descriptor); info->size++; } } -static void ParseLeaf4(const int max_cpuid_leaf, CacheInfo* info) +// For newer Intel CPUs uses "CPUID, eax=0x00000004". +// For newer AMD CPUs uses "CPUID, eax=0x8000001D" +static void ParseCacheInfo(const int max_cpuid_leaf, uint32_t leaf_id, + CacheInfo* info) { - info->size = 0; for (int cache_id = 0; cache_id < CPU_FEATURES_MAX_CACHE_LEVEL; cache_id++) { - const Leaf leaf = SafeCpuIdEx(max_cpuid_leaf, 4, cache_id); + const Leaf leaf = SafeCpuIdEx(max_cpuid_leaf, leaf_id, cache_id); CacheType cache_type = ExtractBitRange(leaf.eax, 4, 0); - if (cache_type == CPU_FEATURE_CACHE_NULL) - { - info->levels[cache_id] = kEmptyCacheLevelInfo; - continue; - } + if (cache_type == CPU_FEATURE_CACHE_NULL) continue; int level = ExtractBitRange(leaf.eax, 7, 5); int line_size = ExtractBitRange(leaf.ebx, 11, 0) + 1; int partitioning = ExtractBitRange(leaf.ebx, 21, 12) + 1; int ways = ExtractBitRange(leaf.ebx, 31, 22) + 1; int tlb_entries = leaf.ecx + 1; int cache_size = (ways * partitioning * line_size * (tlb_entries)); - info->levels[cache_id] = (CacheLevelInfo){.level = level, + info->levels[info->size] = (CacheLevelInfo){.level = level, .cache_type = cache_type, .cache_size = cache_size, .ways = ways, @@ -1371,41 +1374,33 @@ static void ParseCpuId(const uint32_t max_cpuid_leaf, X86Info* info, { StackLineReader reader; StackLineReader_Initialize(&reader, fd); - for (;;) + for (bool stop = false; !stop;) { const LineResult result = StackLineReader_NextLine(&reader); + if (result.eof) stop = true; 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; + if (!CpuFeatures_StringView_StartsWith(line, str(" Features"))) + continue; + // Lines of interests are of the following form: + // " Features=0x1783fbff" + // We first extract the comma separated values between angle brackets. + StringView csv = result.line; + int index = CpuFeatures_StringView_IndexOfChar(csv, '<'); + if (index >= 0) csv = CpuFeatures_StringView_PopFront(csv, index + 1); + if (csv.size > 0 && CpuFeatures_StringView_Back(csv) == '>') + csv = CpuFeatures_StringView_PopBack(csv, 1); + if (CpuFeatures_StringView_HasWord(csv, "SSE", ',')) + features->sse = true; + if (CpuFeatures_StringView_HasWord(csv, "SSE2", ',')) + features->sse2 = true; + if (CpuFeatures_StringView_HasWord(csv, "SSE3", ',')) + features->sse3 = true; + if (CpuFeatures_StringView_HasWord(csv, "SSSE3", ',')) + features->ssse3 = true; + if (CpuFeatures_StringView_HasWord(csv, "SSE4.1", ',')) + features->sse4_1 = true; + if (CpuFeatures_StringView_HasWord(csv, "SSE4.2", ',')) + features->sse4_2 = true; } CpuFeatures_CloseFile(fd); } @@ -1416,25 +1411,22 @@ static void ParseCpuId(const uint32_t max_cpuid_leaf, X86Info* info, { StackLineReader reader; StackLineReader_Initialize(&reader, fd); - for (;;) + for (bool stop = false; !stop;) { const LineResult result = StackLineReader_NextLine(&reader); + if (result.eof) stop = true; 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; + if (!CpuFeatures_StringView_GetAttributeKeyValue(line, &key, &value)) + continue; + if (!CpuFeatures_StringView_IsEquals(key, str("flags"))) continue; + 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; } CpuFeatures_CloseFile(fd); } @@ -1450,11 +1442,15 @@ static void ParseCpuId(const uint32_t max_cpuid_leaf, X86Info* info, // Reference // https://en.wikipedia.org/wiki/CPUID#EAX=80000000h:_Get_Highest_Extended_Function_Implemented. +static Leaf GetLeafByIdAMD(uint32_t leaf_id) +{ + uint32_t max_extended = CpuId(0x80000000).eax; + return SafeCpuId(max_extended, leaf_id); +} + static void ParseExtraAMDCpuId(X86Info* info, OsPreserves os_preserves) { - const Leaf leaf_80000000 = CpuId(0x80000000); - const uint32_t max_extended_cpuid_leaf = leaf_80000000.eax; - const Leaf leaf_80000001 = SafeCpuId(max_extended_cpuid_leaf, 0x80000001); + const Leaf leaf_80000001 = GetLeafByIdAMD(0x80000001); X86Features* const features = &info->features; @@ -1477,9 +1473,9 @@ X86Info GetX86Info(void) { X86Info info = kEmptyX86Info; 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"); + const bool is_intel = IsVendor(leaf_0, CPU_FEATURES_VENDOR_GENUINE_INTEL); + const bool is_amd = IsVendor(leaf_0, CPU_FEATURES_VENDOR_AUTHENTIC_AMD); + const bool is_hygon = IsVendor(leaf_0, CPU_FEATURES_VENDOR_HYGON_GENUINE); SetVendor(leaf_0, info.vendor); if (is_intel || is_amd || is_hygon) { @@ -1498,11 +1494,25 @@ CacheInfo GetX86CacheInfo(void) { CacheInfo info = kEmptyCacheInfo; const Leaf leaf_0 = CpuId(0); - const uint32_t max_cpuid_leaf = leaf_0.eax; - if (IsVendor(leaf_0, "GenuineIntel")) + if (IsVendor(leaf_0, CPU_FEATURES_VENDOR_GENUINE_INTEL)) { - ParseLeaf2(max_cpuid_leaf, &info); - ParseLeaf4(max_cpuid_leaf, &info); + info.size = 0; + ParseLeaf2(leaf_0.eax, &info); + ParseCacheInfo(leaf_0.eax, 4, &info); + } + else if (IsVendor(leaf_0, CPU_FEATURES_VENDOR_AUTHENTIC_AMD) || + IsVendor(leaf_0, CPU_FEATURES_VENDOR_HYGON_GENUINE)) + { + const uint32_t max_ext = CpuId(0x80000000).eax; + const uint32_t cpuid_ext = SafeCpuId(max_ext, 0x80000001).ecx; + + // If CPUID Fn8000_0001_ECX[TopologyExtensions]==0 + // then CPUID Fn8000_0001_E[D,C,B,A]X is reserved. + // https://www.amd.com/system/files/TechDocs/25481.pdf + if (IsBitSet(cpuid_ext, 22)) + { + ParseCacheInfo(max_ext, 0x8000001D, &info); + } } return info; } @@ -1511,7 +1521,7 @@ CacheInfo GetX86CacheInfo(void) X86Microarchitecture GetX86Microarchitecture(const X86Info* info) { - if (memcmp(info->vendor, "GenuineIntel", sizeof(info->vendor)) == 0) + if (IsVendorByX86Info(info, CPU_FEATURES_VENDOR_GENUINE_INTEL)) { switch (CPUID(info->family, info->model)) { @@ -1616,7 +1626,7 @@ X86Microarchitecture GetX86Microarchitecture(const X86Info* info) return X86_UNKNOWN; } } - if (memcmp(info->vendor, "AuthenticAMD", sizeof(info->vendor)) == 0) + if (IsVendorByX86Info(info, CPU_FEATURES_VENDOR_AUTHENTIC_AMD)) { switch (CPUID(info->family, info->model)) { @@ -1726,7 +1736,7 @@ X86Microarchitecture GetX86Microarchitecture(const X86Info* info) return X86_UNKNOWN; } } - if (memcmp(info->vendor, "HygonGenuine", sizeof(info->vendor)) == 0) + if (IsVendorByX86Info(info, CPU_FEATURES_VENDOR_HYGON_GENUINE)) { switch (CPUID(info->family, info->model)) { @@ -1737,23 +1747,20 @@ X86Microarchitecture GetX86Microarchitecture(const X86Info* info) return X86_UNKNOWN; } -static void SetString(const uint32_t max_cpuid_ext_leaf, const uint32_t leaf_id, - char* buffer) -{ - const Leaf leaf = SafeCpuId(max_cpuid_ext_leaf, leaf_id); - // We allow calling memcpy from SetString which is only called when requesting - // X86BrandString. - memcpy(buffer, &leaf, sizeof(Leaf)); -} - void FillX86BrandString(char brand_string[49]) { const Leaf leaf_ext_0 = CpuId(0x80000000); const uint32_t max_cpuid_leaf_ext = leaf_ext_0.eax; - SetString(max_cpuid_leaf_ext, 0x80000002, brand_string); - SetString(max_cpuid_leaf_ext, 0x80000003, brand_string + 16); - SetString(max_cpuid_leaf_ext, 0x80000004, brand_string + 32); - brand_string[48] = '\0'; + const Leaf leaves[3] = { + SafeCpuId(max_cpuid_leaf_ext, 0x80000002), + SafeCpuId(max_cpuid_leaf_ext, 0x80000003), + SafeCpuId(max_cpuid_leaf_ext, 0x80000004), + }; +#if __STDC_VERSION__ >= 201112L + _Static_assert(sizeof(leaves) == 48, "Leaves must be packed"); +#endif + CpuFeatures_StringView_CopyString(view((const char*)leaves, sizeof(leaves)), + brand_string, 49); } //////////////////////////////////////////////////////////////////////////////// diff --git a/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/cpu_features/src/string_view.c b/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/cpu_features/src/string_view.c index e60e7fefe..3e8b8b8a5 100644 --- a/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/cpu_features/src/string_view.c +++ b/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/cpu_features/src/string_view.c @@ -158,7 +158,8 @@ void CpuFeatures_StringView_CopyString(const StringView src, char* dst, } bool CpuFeatures_StringView_HasWord(const StringView line, - const char* const word_str) + const char* const word_str, + const char separator) { const StringView word = str(word_str); StringView remainder = line; @@ -176,9 +177,9 @@ bool CpuFeatures_StringView_HasWord(const StringView line, const StringView after = CpuFeatures_StringView_PopFront(line, index_of_word + word.size); const bool valid_before = - before.size == 0 || CpuFeatures_StringView_Back(before) == ' '; + before.size == 0 || CpuFeatures_StringView_Back(before) == separator; const bool valid_after = - after.size == 0 || CpuFeatures_StringView_Front(after) == ' '; + after.size == 0 || CpuFeatures_StringView_Front(after) == separator; if (valid_before && valid_after) return true; remainder = CpuFeatures_StringView_PopFront(remainder, index_of_word + word.size); 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 f4fa1a9d3..4c242cf8b 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 @@ -76,26 +76,32 @@ private: uint32_t xcr0_eax_; }; -FakeCpu* g_fake_cpu = nullptr; +static FakeCpu* g_fake_cpu_instance = nullptr; + +static FakeCpu& cpu() +{ + assert(g_fake_cpu_instance != nullptr); + return *g_fake_cpu_instance; +} extern "C" Leaf GetCpuidLeaf(uint32_t leaf_id, int ecx) { - return g_fake_cpu->GetCpuidLeaf(leaf_id, ecx); + return cpu().GetCpuidLeaf(leaf_id, ecx); } -extern "C" uint32_t GetXCR0Eax(void) { return g_fake_cpu->GetXCR0Eax(); } +extern "C" uint32_t GetXCR0Eax(void) { return cpu().GetXCR0Eax(); } #if defined(CPU_FEATURES_OS_DARWIN) extern "C" bool GetDarwinSysCtlByName(const char* name) { - return g_fake_cpu->GetDarwinSysCtlByName(name); + return cpu().GetDarwinSysCtlByName(name); } #endif // CPU_FEATURES_OS_DARWIN #if defined(CPU_FEATURES_OS_WINDOWS) extern "C" bool GetWindowsIsProcessorFeaturePresent(DWORD ProcessorFeature) { - return g_fake_cpu->GetWindowsIsProcessorFeaturePresent(ProcessorFeature); + return cpu().GetWindowsIsProcessorFeaturePresent(ProcessorFeature); } #endif // CPU_FEATURES_OS_WINDOWS @@ -104,14 +110,22 @@ namespace class CpuidX86Test : public ::testing::Test { protected: - void SetUp() override { g_fake_cpu = new FakeCpu(); } - void TearDown() override { delete g_fake_cpu; } + void SetUp() override + { + assert(g_fake_cpu_instance == nullptr); + g_fake_cpu_instance = new FakeCpu(); + } + void TearDown() override + { + delete g_fake_cpu_instance; + g_fake_cpu_instance = nullptr; + } }; TEST_F(CpuidX86Test, SandyBridge) { - g_fake_cpu->SetOsBackupsExtendedRegisters(true); - g_fake_cpu->SetLeaves({ + cpu().SetOsBackupsExtendedRegisters(true); + cpu().SetLeaves({ {{0x00000000, 0}, Leaf{0x0000000D, 0x756E6547, 0x6C65746E, 0x49656E69}}, {{0x00000001, 0}, Leaf{0x000206A6, 0x00100800, 0x1F9AE3BF, 0xBFEBFBFF}}, {{0x00000007, 0}, Leaf{0x00000000, 0x00000000, 0x00000000, 0x00000000}}, @@ -153,28 +167,29 @@ TEST_F(CpuidX86Test, SandyBridge) EXPECT_FALSE(features.adx); } +const int UNDEF = -1; const int KiB = 1024; const int MiB = 1024 * KiB; TEST_F(CpuidX86Test, SandyBridgeTestOsSupport) { - g_fake_cpu->SetLeaves({ + cpu().SetLeaves({ {{0x00000000, 0}, Leaf{0x0000000D, 0x756E6547, 0x6C65746E, 0x49656E69}}, {{0x00000001, 0}, Leaf{0x000206A6, 0x00100800, 0x1F9AE3BF, 0xBFEBFBFF}}, {{0x00000007, 0}, Leaf{0x00000000, 0x00000000, 0x00000000, 0x00000000}}, }); // avx is disabled if os does not support backing up ymm registers. - g_fake_cpu->SetOsBackupsExtendedRegisters(false); + cpu().SetOsBackupsExtendedRegisters(false); EXPECT_FALSE(GetX86Info().features.avx); // avx is disabled if os does not support backing up ymm registers. - g_fake_cpu->SetOsBackupsExtendedRegisters(true); + cpu().SetOsBackupsExtendedRegisters(true); EXPECT_TRUE(GetX86Info().features.avx); } TEST_F(CpuidX86Test, SkyLake) { - g_fake_cpu->SetOsBackupsExtendedRegisters(true); - g_fake_cpu->SetLeaves({ + cpu().SetOsBackupsExtendedRegisters(true); + cpu().SetLeaves({ {{0x00000000, 0}, Leaf{0x00000016, 0x756E6547, 0x6C65746E, 0x49656E69}}, {{0x00000001, 0}, Leaf{0x000406E3, 0x00100800, 0x7FFAFBBF, 0xBFEBFBFF}}, {{0x00000007, 0}, Leaf{0x00000000, 0x029C67AF, 0x00000000, 0x00000000}}, @@ -189,7 +204,7 @@ TEST_F(CpuidX86Test, SkyLake) TEST_F(CpuidX86Test, Branding) { - g_fake_cpu->SetLeaves({ + cpu().SetLeaves({ {{0x00000000, 0}, Leaf{0x00000016, 0x756E6547, 0x6C65746E, 0x49656E69}}, {{0x00000001, 0}, Leaf{0x000406E3, 0x00100800, 0x7FFAFBBF, 0xBFEBFBFF}}, {{0x00000007, 0}, Leaf{0x00000000, 0x029C67AF, 0x00000000, 0x00000000}}, @@ -206,7 +221,7 @@ TEST_F(CpuidX86Test, Branding) TEST_F(CpuidX86Test, KabyLakeCache) { - g_fake_cpu->SetLeaves({ + cpu().SetLeaves({ {{0x00000000, 0}, Leaf{0x00000016, 0x756E6547, 0x6C65746E, 0x49656E69}}, {{0x00000001, 0}, Leaf{0x000406E3, 0x00100800, 0x7FFAFBBF, 0xBFEBFBFF}}, {{0x00000004, 0}, Leaf{0x1C004121, 0x01C0003F, 0x0000003F, 0x00000000}}, @@ -256,7 +271,7 @@ TEST_F(CpuidX86Test, KabyLakeCache) TEST_F(CpuidX86Test, HSWCache) { - g_fake_cpu->SetLeaves({ + cpu().SetLeaves({ {{0x00000000, 0}, Leaf{0x00000016, 0x756E6547, 0x6C65746E, 0x49656E69}}, {{0x00000001, 0}, Leaf{0x000406E3, 0x00100800, 0x7FFAFBBF, 0xBFEBFBFF}}, {{0x00000004, 0}, Leaf{0x1C004121, 0x01C0003F, 0x0000003F, 0x00000000}}, @@ -307,7 +322,7 @@ TEST_F(CpuidX86Test, HSWCache) // http://users.atw.hu/instlatx64/AuthenticAMD/AuthenticAMD0200F30_K11_Griffin_CPUID.txt TEST_F(CpuidX86Test, AMD_K11_GRIFFIN) { - g_fake_cpu->SetLeaves({ + cpu().SetLeaves({ {{0x00000000, 0}, Leaf{0x00000001, 0x68747541, 0x444D4163, 0x69746E65}}, {{0x00000001, 0}, Leaf{0x00200F30, 0x00020800, 0x00002001, 0x178BFBFF}}, {{0x80000000, 0}, Leaf{0x8000001A, 0x68747541, 0x444D4163, 0x69746E65}}, @@ -324,7 +339,7 @@ TEST_F(CpuidX86Test, AMD_K11_GRIFFIN) // http://users.atw.hu/instlatx64/AuthenticAMD/AuthenticAMD0300F10_K12_Llano_CPUID.txt TEST_F(CpuidX86Test, AMD_K12_LLANO) { - g_fake_cpu->SetLeaves({ + cpu().SetLeaves({ {{0x00000000, 0}, Leaf{0x00000006, 0x68747541, 0x444D4163, 0x69746E65}}, {{0x00000001, 0}, Leaf{0x00300F10, 0x00040800, 0x00802009, 0x178BFBFF}}, {{0x80000000, 0}, Leaf{0x8000001B, 0x68747541, 0x444D4163, 0x69746E65}}, @@ -341,7 +356,7 @@ TEST_F(CpuidX86Test, AMD_K12_LLANO) // http://users.atw.hu/instlatx64/AuthenticAMD/AuthenticAMD0500F01_K14_Bobcat_CPUID.txt TEST_F(CpuidX86Test, AMD_K14_BOBCAT_AMD0500F01) { - g_fake_cpu->SetLeaves({ + cpu().SetLeaves({ {{0x00000000, 0}, Leaf{0x00000006, 0x68747541, 0x444D4163, 0x69746E65}}, {{0x00000001, 0}, Leaf{0x00500F01, 0x00020800, 0x00802209, 0x178BFBFF}}, {{0x80000000, 0}, Leaf{0x8000001B, 0x68747541, 0x444D4163, 0x69746E65}}, @@ -358,7 +373,7 @@ TEST_F(CpuidX86Test, AMD_K14_BOBCAT_AMD0500F01) // http://users.atw.hu/instlatx64/AuthenticAMD/AuthenticAMD0500F10_K14_Bobcat_CPUID.txt TEST_F(CpuidX86Test, AMD_K14_BOBCAT_AMD0500F10) { - g_fake_cpu->SetLeaves({ + cpu().SetLeaves({ {{0x00000000, 0}, Leaf{0x00000006, 0x68747541, 0x444D4163, 0x69746E65}}, {{0x00000001, 0}, Leaf{0x00500F10, 0x00020800, 0x00802209, 0x178BFBFF}}, {{0x00000002, 0}, Leaf{0x00000000, 0x00000000, 0x00000000, 0x00000000}}, @@ -383,7 +398,7 @@ TEST_F(CpuidX86Test, AMD_K14_BOBCAT_AMD0500F10) // http://users.atw.hu/instlatx64/AuthenticAMD/AuthenticAMD0500F20_K14_Bobcat_CPUID.txt TEST_F(CpuidX86Test, AMD_K14_BOBCAT_AMD0500F20) { - g_fake_cpu->SetLeaves({ + cpu().SetLeaves({ {{0x00000000, 0}, Leaf{0x00000006, 0x68747541, 0x444D4163, 0x69746E65}}, {{0x00000001, 0}, Leaf{0x00500F20, 0x00020800, 0x00802209, 0x178BFBFF}}, {{0x80000000, 0}, Leaf{0x8000001B, 0x68747541, 0x444D4163, 0x69746E65}}, @@ -400,7 +415,7 @@ TEST_F(CpuidX86Test, AMD_K14_BOBCAT_AMD0500F20) // http://users.atw.hu/instlatx64/AuthenticAMD/AuthenticAMD0670F00_K15_StoneyRidge_CPUID.txt TEST_F(CpuidX86Test, AMD_K15_EXCAVATOR_STONEY_RIDGE) { - g_fake_cpu->SetLeaves({ + cpu().SetLeaves({ {{0x00000000, 0}, Leaf{0x0000000D, 0x68747541, 0x444D4163, 0x69746E65}}, {{0x00000001, 0}, Leaf{0x00670F00, 0x00020800, 0x7ED8320B, 0x178BFBFF}}, {{0x00000007, 0}, Leaf{0x00000000, 0x000001A9, 0x00000000, 0x00000000}}, @@ -426,7 +441,7 @@ TEST_F(CpuidX86Test, AMD_K15_EXCAVATOR_STONEY_RIDGE) // http://users.atw.hu/instlatx64/AuthenticAMD/AuthenticAMD0600F20_K15_AbuDhabi_CPUID0.txt TEST_F(CpuidX86Test, AMD_K15_PILEDRIVER_ABU_DHABI) { - g_fake_cpu->SetLeaves({ + cpu().SetLeaves({ {{0x00000000, 0}, Leaf{0x0000000D, 0x68747541, 0x444D4163, 0x69746E65}}, {{0x00000001, 0}, Leaf{0x00600F20, 0x00100800, 0x3E98320B, 0x178BFBFF}}, {{0x00000007, 0}, Leaf{0x00000000, 0x00000008, 0x00000000, 0x00000000}}, @@ -449,10 +464,59 @@ TEST_F(CpuidX86Test, AMD_K15_PILEDRIVER_ABU_DHABI) EXPECT_STREQ(brand_string, "AMD Opteron(tm) Processor 6376 "); } +// http://users.atw.hu/instlatx64/AuthenticAMD/AuthenticAMD0600F20_K15_AbuDhabi_CPUID0.txt +TEST_F(CpuidX86Test, AMD_K15_PILEDRIVER_ABU_DHABI_CACHE_INFO) +{ + cpu().SetLeaves({ + {{0x00000000, 0}, Leaf{0x0000000D, 0x68747541, 0x444D4163, 0x69746E65}}, + {{0x00000001, 0}, Leaf{0x00600F20, 0x00100800, 0x3E98320B, 0x178BFBFF}}, + {{0x80000000, 0}, Leaf{0x8000001E, 0x68747541, 0x444D4163, 0x69746E65}}, + {{0x80000001, 0}, Leaf{0x00600F20, 0x30000000, 0x01EBBFFF, 0x2FD3FBFF}}, + {{0x8000001D, 0}, Leaf{0x00000121, 0x00C0003F, 0x0000003F, 0x00000000}}, + {{0x8000001D, 1}, Leaf{0x00004122, 0x0040003F, 0x000001FF, 0x00000000}}, + {{0x8000001D, 2}, Leaf{0x00004143, 0x03C0003F, 0x000007FF, 0x00000001}}, + {{0x8000001D, 3}, Leaf{0x0001C163, 0x0BC0003F, 0x000007FF, 0x00000001}}, + }); + const auto info = GetX86CacheInfo(); + + EXPECT_EQ(info.size, 4); + EXPECT_EQ(info.levels[0].level, 1); + EXPECT_EQ(info.levels[0].cache_type, 1); + EXPECT_EQ(info.levels[0].cache_size, 16 * KiB); + EXPECT_EQ(info.levels[0].ways, 4); + EXPECT_EQ(info.levels[0].line_size, 64); + EXPECT_EQ(info.levels[0].tlb_entries, 64); + EXPECT_EQ(info.levels[0].partitioning, 1); + + EXPECT_EQ(info.levels[1].level, 1); + EXPECT_EQ(info.levels[1].cache_type, 2); + EXPECT_EQ(info.levels[1].cache_size, 64 * KiB); + EXPECT_EQ(info.levels[1].ways, 2); + EXPECT_EQ(info.levels[1].line_size, 64); + EXPECT_EQ(info.levels[1].tlb_entries, 512); + EXPECT_EQ(info.levels[1].partitioning, 1); + + EXPECT_EQ(info.levels[2].level, 2); + EXPECT_EQ(info.levels[2].cache_type, 3); + EXPECT_EQ(info.levels[2].cache_size, 2 * MiB); + EXPECT_EQ(info.levels[2].ways, 16); + EXPECT_EQ(info.levels[2].line_size, 64); + EXPECT_EQ(info.levels[2].tlb_entries, 2048); + EXPECT_EQ(info.levels[2].partitioning, 1); + + EXPECT_EQ(info.levels[3].level, 3); + EXPECT_EQ(info.levels[3].cache_type, 3); + EXPECT_EQ(info.levels[3].cache_size, 6 * MiB); + EXPECT_EQ(info.levels[3].ways, 48); + EXPECT_EQ(info.levels[3].line_size, 64); + EXPECT_EQ(info.levels[3].tlb_entries, 2048); + EXPECT_EQ(info.levels[3].partitioning, 1); +} + // http://users.atw.hu/instlatx64/AuthenticAMD/AuthenticAMD0600F12_K15_Interlagos_CPUID3.txt TEST_F(CpuidX86Test, AMD_K15_BULLDOZER_INTERLAGOS) { - g_fake_cpu->SetLeaves({ + cpu().SetLeaves({ {{0x00000000, 0}, Leaf{0x0000000D, 0x68747541, 0x444D4163, 0x69746E65}}, {{0x00000001, 0}, Leaf{0x00600F12, 0x000C0800, 0x1E98220B, 0x178BFBFF}}, {{0x00000007, 0}, Leaf{0x00000000, 0x00000000, 0x00000000, 0x00000000}}, @@ -478,7 +542,7 @@ TEST_F(CpuidX86Test, AMD_K15_BULLDOZER_INTERLAGOS) // http://users.atw.hu/instlatx64/AuthenticAMD0630F81_K15_Godavari_CPUID.txt TEST_F(CpuidX86Test, AMD_K15_STREAMROLLER_GODAVARI) { - g_fake_cpu->SetLeaves({ + cpu().SetLeaves({ {{0x00000000, 0}, Leaf{0x0000000D, 0x68747541, 0x444D4163, 0x69746E65}}, {{0x00000001, 0}, Leaf{0x00630F81, 0x00040800, 0x3E98320B, 0x178BFBFF}}, {{0x00000007, 0}, Leaf{0x00000000, 0x00000000, 0x00000000, 0x00000000}}, @@ -506,7 +570,7 @@ TEST_F(CpuidX86Test, AMD_K15_STREAMROLLER_GODAVARI) // http://users.atw.hu/instlatx64/AuthenticAMD/AuthenticAMD0700F01_K16_Kabini_CPUID.txt TEST_F(CpuidX86Test, AMD_K16_JAGUAR_KABINI) { - g_fake_cpu->SetLeaves({ + cpu().SetLeaves({ {{0x00000000, 0}, Leaf{0x0000000D, 0x68747541, 0x444D4163, 0x69746E65}}, {{0x00000001, 0}, Leaf{0x00700F01, 0x00040800, 0x3ED8220B, 0x178BFBFF}}, {{0x00000007, 0}, Leaf{0x00000000, 0x00000008, 0x00000000, 0x00000000}}, @@ -531,7 +595,7 @@ TEST_F(CpuidX86Test, AMD_K16_JAGUAR_KABINI) // http://users.atw.hu/instlatx64/AuthenticAMD/AuthenticAMD0730F01_K16_Beema_CPUID2.txt TEST_F(CpuidX86Test, AMD_K16_PUMA_BEEMA) { - g_fake_cpu->SetLeaves({ + cpu().SetLeaves({ {{0x00000000, 0}, Leaf{0x0000000D, 0x68747541, 0x444D4163, 0x69746E65}}, {{0x00000001, 0}, Leaf{0x00730F01, 0x00040800, 0x7ED8220B, 0x178BFBFF}}, {{0x00000007, 0}, Leaf{0x00000000, 0x00000008, 0x00000000, 0x00000000}}, @@ -556,7 +620,7 @@ TEST_F(CpuidX86Test, AMD_K16_PUMA_BEEMA) // http://users.atw.hu/instlatx64/AuthenticAMD/AuthenticAMD0820F01_K17_Dali_CPUID.txt TEST_F(CpuidX86Test, AMD_K17_ZEN_DALI) { - g_fake_cpu->SetLeaves({ + cpu().SetLeaves({ {{0x00000000, 0}, Leaf{0x0000000D, 0x68747541, 0x444D4163, 0x69746E65}}, {{0x00000001, 0}, Leaf{0x00820F01, 0x00020800, 0x7ED8320B, 0x178BFBFF}}, {{0x00000007, 0}, Leaf{0x00000000, 0x209C01A9, 0x00000000, 0x00000000}}, @@ -581,7 +645,7 @@ TEST_F(CpuidX86Test, AMD_K17_ZEN_DALI) // http://users.atw.hu/instlatx64/AuthenticAMD/AuthenticAMD0800F82_K17_ZenP_CPUID.txt TEST_F(CpuidX86Test, AMD_K17_ZEN_PLUS_PINNACLE_RIDGE) { - g_fake_cpu->SetLeaves({ + cpu().SetLeaves({ {{0x00000000, 0}, Leaf{0x0000000D, 0x68747541, 0x444D4163, 0x69746E65}}, {{0x00000001, 0}, Leaf{0x00800F82, 0x00100800, 0x7ED8320B, 0x178BFBFF}}, {{0x00000007, 0}, Leaf{0x00000000, 0x209C01A9, 0x00000000, 0x00000000}}, @@ -606,7 +670,7 @@ TEST_F(CpuidX86Test, AMD_K17_ZEN_PLUS_PINNACLE_RIDGE) // http://users.atw.hu/instlatx64/AuthenticAMD/AuthenticAMD0840F70_K17_CPUID.txt TEST_F(CpuidX86Test, AMD_K17_ZEN2_XBOX_SERIES_X) { - g_fake_cpu->SetLeaves({ + cpu().SetLeaves({ {{0x00000000, 0}, Leaf{0x00000010, 0x68747541, 0x444D4163, 0x69746E65}}, {{0x00000001, 0}, Leaf{0x00840F70, 0x00100800, 0x7ED8320B, 0x178BFBFF}}, {{0x00000007, 0}, Leaf{0x00000000, 0x219C91A9, 0x00400004, 0x00000000}}, @@ -631,7 +695,7 @@ TEST_F(CpuidX86Test, AMD_K17_ZEN2_XBOX_SERIES_X) // http://users.atw.hu/instlatx64/HygonGenuine/HygonGenuine0900F02_Hygon_CPUID3.txt TEST_F(CpuidX86Test, AMD_K18_ZEN_DHYANA) { - g_fake_cpu->SetLeaves({ + cpu().SetLeaves({ {{0x00000000, 0}, Leaf{0x0000000D, 0x6F677948, 0x656E6975, 0x6E65476E}}, {{0x00000001, 0}, Leaf{0x00900F02, 0x00100800, 0x74D83209, 0x178BFBFF}}, {{0x00000007, 0}, Leaf{0x00000000, 0x009C01A9, 0x0040068C, 0x00000000}}, @@ -653,10 +717,59 @@ TEST_F(CpuidX86Test, AMD_K18_ZEN_DHYANA) EXPECT_STREQ(brand_string, "Hygon C86 3185 8-core Processor "); } +// http://users.atw.hu/instlatx64/HygonGenuine/HygonGenuine0900F02_Hygon_CPUID.txt +TEST_F(CpuidX86Test, AMD_K18_ZEN_DHYANA_CACHE_INFO) +{ + cpu().SetLeaves({ + {{0x00000000, 0}, Leaf{0x0000000D, 0x6F677948, 0x656E6975, 0x6E65476E}}, + {{0x00000001, 0}, Leaf{0x00900F02, 0x00100800, 0x74D83209, 0x178BFBFF}}, + {{0x80000000, 0}, Leaf{0x8000001F, 0x6F677948, 0x656E6975, 0x6E65476E}}, + {{0x80000001, 0}, Leaf{0x00900F02, 0x60000000, 0x35C233FF, 0x2FD3FBFF}}, + {{0x8000001D, 0}, Leaf{0x00004121, 0x01C0003F, 0x0000003F, 0x00000000}}, + {{0x8000001D, 1}, Leaf{0x00004122, 0x00C0003F, 0x000000FF, 0x00000000}}, + {{0x8000001D, 2}, Leaf{0x00004143, 0x01C0003F, 0x000003FF, 0x00000002}}, + {{0x8000001D, 3}, Leaf{0x0001C163, 0x03C0003F, 0x00001FFF, 0x00000001}}, + }); + const auto info = GetX86CacheInfo(); + + EXPECT_EQ(info.size, 4); + EXPECT_EQ(info.levels[0].level, 1); + EXPECT_EQ(info.levels[0].cache_type, 1); + EXPECT_EQ(info.levels[0].cache_size, 32 * KiB); + EXPECT_EQ(info.levels[0].ways, 8); + EXPECT_EQ(info.levels[0].line_size, 64); + EXPECT_EQ(info.levels[0].tlb_entries, 64); + EXPECT_EQ(info.levels[0].partitioning, 1); + + EXPECT_EQ(info.levels[1].level, 1); + EXPECT_EQ(info.levels[1].cache_type, 2); + EXPECT_EQ(info.levels[1].cache_size, 64 * KiB); + EXPECT_EQ(info.levels[1].ways, 4); + EXPECT_EQ(info.levels[1].line_size, 64); + EXPECT_EQ(info.levels[1].tlb_entries, 256); + EXPECT_EQ(info.levels[1].partitioning, 1); + + EXPECT_EQ(info.levels[2].level, 2); + EXPECT_EQ(info.levels[2].cache_type, 3); + EXPECT_EQ(info.levels[2].cache_size, 512 * KiB); + EXPECT_EQ(info.levels[2].ways, 8); + EXPECT_EQ(info.levels[2].line_size, 64); + EXPECT_EQ(info.levels[2].tlb_entries, 1024); + EXPECT_EQ(info.levels[2].partitioning, 1); + + EXPECT_EQ(info.levels[3].level, 3); + EXPECT_EQ(info.levels[3].cache_type, 3); + EXPECT_EQ(info.levels[3].cache_size, 8 * MiB); + EXPECT_EQ(info.levels[3].ways, 16); + EXPECT_EQ(info.levels[3].line_size, 64); + EXPECT_EQ(info.levels[3].tlb_entries, 8192); + EXPECT_EQ(info.levels[3].partitioning, 1); +} + // http://users.atw.hu/instlatx64/AuthenticAMD/AuthenticAMD0A20F10_K19_Vermeer2_CPUID.txt TEST_F(CpuidX86Test, AMD_K19_ZEN3_VERMEER) { - g_fake_cpu->SetLeaves({ + cpu().SetLeaves({ {{0x00000000, 0}, Leaf{0x00000010, 0x68747541, 0x444D4163, 0x69746E65}}, {{0x00000001, 0}, Leaf{0x00A20F10, 0x01180800, 0x7ED8320B, 0x178BFBFF}}, {{0x00000007, 0}, Leaf{0x00000000, 0x219C97A9, 0x0040068C, 0x00000000}}, @@ -682,21 +795,18 @@ TEST_F(CpuidX86Test, AMD_K19_ZEN3_VERMEER) TEST_F(CpuidX86Test, Nehalem) { // Pre AVX cpus don't have xsave - g_fake_cpu->SetOsBackupsExtendedRegisters(false); + cpu().SetOsBackupsExtendedRegisters(false); #if defined(CPU_FEATURES_OS_WINDOWS) - g_fake_cpu->SetWindowsIsProcessorFeaturePresent( - PF_XMMI_INSTRUCTIONS_AVAILABLE); - g_fake_cpu->SetWindowsIsProcessorFeaturePresent( - PF_XMMI64_INSTRUCTIONS_AVAILABLE); - g_fake_cpu->SetWindowsIsProcessorFeaturePresent( - PF_SSE3_INSTRUCTIONS_AVAILABLE); + cpu().SetWindowsIsProcessorFeaturePresent(PF_XMMI_INSTRUCTIONS_AVAILABLE); + cpu().SetWindowsIsProcessorFeaturePresent(PF_XMMI64_INSTRUCTIONS_AVAILABLE); + cpu().SetWindowsIsProcessorFeaturePresent(PF_SSE3_INSTRUCTIONS_AVAILABLE); #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"); + cpu().SetDarwinSysCtlByName("hw.optional.sse"); + cpu().SetDarwinSysCtlByName("hw.optional.sse2"); + cpu().SetDarwinSysCtlByName("hw.optional.sse3"); + cpu().SetDarwinSysCtlByName("hw.optional.supplementalsse3"); + cpu().SetDarwinSysCtlByName("hw.optional.sse4_1"); + cpu().SetDarwinSysCtlByName("hw.optional.sse4_2"); #elif defined(CPU_FEATURES_OS_FREEBSD) auto& fs = GetEmptyFilesystem(); fs.CreateFile("/var/run/dmesg.boot", R"( @@ -713,7 +823,7 @@ real memory = 2147418112 (2047 MB) flags : fpu mmx sse sse2 sse3 ssse3 sse4_1 sse4_2 )"); #endif - g_fake_cpu->SetLeaves({ + cpu().SetLeaves({ {{0x00000000, 0}, Leaf{0x0000000B, 0x756E6547, 0x6C65746E, 0x49656E69}}, {{0x00000001, 0}, Leaf{0x000106A2, 0x00100800, 0x00BCE3BD, 0xBFEBFBFF}}, {{0x00000002, 0}, Leaf{0x55035A01, 0x00F0B0E3, 0x00000000, 0x09CA212C}}, @@ -768,21 +878,18 @@ flags : fpu mmx sse sse2 sse3 ssse3 sse4_1 sse4_2 TEST_F(CpuidX86Test, Atom) { // Pre AVX cpus don't have xsave - g_fake_cpu->SetOsBackupsExtendedRegisters(false); + cpu().SetOsBackupsExtendedRegisters(false); #if defined(CPU_FEATURES_OS_WINDOWS) - g_fake_cpu->SetWindowsIsProcessorFeaturePresent( - PF_XMMI_INSTRUCTIONS_AVAILABLE); - g_fake_cpu->SetWindowsIsProcessorFeaturePresent( - PF_XMMI64_INSTRUCTIONS_AVAILABLE); - g_fake_cpu->SetWindowsIsProcessorFeaturePresent( - PF_SSE3_INSTRUCTIONS_AVAILABLE); + cpu().SetWindowsIsProcessorFeaturePresent(PF_XMMI_INSTRUCTIONS_AVAILABLE); + cpu().SetWindowsIsProcessorFeaturePresent(PF_XMMI64_INSTRUCTIONS_AVAILABLE); + cpu().SetWindowsIsProcessorFeaturePresent(PF_SSE3_INSTRUCTIONS_AVAILABLE); #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"); + cpu().SetDarwinSysCtlByName("hw.optional.sse"); + cpu().SetDarwinSysCtlByName("hw.optional.sse2"); + cpu().SetDarwinSysCtlByName("hw.optional.sse3"); + cpu().SetDarwinSysCtlByName("hw.optional.supplementalsse3"); + cpu().SetDarwinSysCtlByName("hw.optional.sse4_1"); + cpu().SetDarwinSysCtlByName("hw.optional.sse4_2"); #elif defined(CPU_FEATURES_OS_FREEBSD) auto& fs = GetEmptyFilesystem(); fs.CreateFile("/var/run/dmesg.boot", R"( @@ -799,7 +906,7 @@ real memory = 2147418112 (2047 MB) flags : fpu mmx sse sse2 sse3 ssse3 sse4_1 sse4_2 )"); #endif - g_fake_cpu->SetLeaves({ + cpu().SetLeaves({ {{0x00000000, 0}, Leaf{0x0000000B, 0x756E6547, 0x6C65746E, 0x49656E69}}, {{0x00000001, 0}, Leaf{0x00030673, 0x00100800, 0x41D8E3BF, 0xBFEBFBFF}}, {{0x00000002, 0}, Leaf{0x61B3A001, 0x0000FFC2, 0x00000000, 0x00000000}}, @@ -850,16 +957,68 @@ flags : fpu mmx sse sse2 sse3 ssse3 sse4_1 sse4_2 #endif // !defined(CPU_FEATURES_OS_WINDOWS) } +// https://www.felixcloutier.com/x86/cpuid#example-3-1--example-of-cache-and-tlb-interpretation +TEST_F(CpuidX86Test, P4_CacheInfo) +{ + cpu().SetLeaves({ + {{0x00000000, 0}, Leaf{0x00000002, 0x756E6547, 0x6C65746E, 0x49656E69}}, + {{0x00000001, 0}, Leaf{0x00000F0A, 0x00010808, 0x00000000, 0x3FEBFBFF}}, + {{0x00000002, 0}, Leaf{0x665B5001, 0x00000000, 0x00000000, 0x007A7000}}, + }); + + const auto info = GetX86CacheInfo(); + EXPECT_EQ(info.size, 5); + + EXPECT_EQ(info.levels[0].level, UNDEF); + EXPECT_EQ(info.levels[0].cache_type, CPU_FEATURE_CACHE_TLB); + EXPECT_EQ(info.levels[0].cache_size, 4 * KiB); + EXPECT_EQ(info.levels[0].ways, UNDEF); + EXPECT_EQ(info.levels[0].line_size, UNDEF); + EXPECT_EQ(info.levels[0].tlb_entries, 64); + EXPECT_EQ(info.levels[0].partitioning, 0); + + EXPECT_EQ(info.levels[1].level, UNDEF); + EXPECT_EQ(info.levels[1].cache_type, CPU_FEATURE_CACHE_TLB); + EXPECT_EQ(info.levels[1].cache_size, 4 * KiB); + EXPECT_EQ(info.levels[1].ways, UNDEF); + EXPECT_EQ(info.levels[1].line_size, UNDEF); + EXPECT_EQ(info.levels[1].tlb_entries, 64); + EXPECT_EQ(info.levels[1].partitioning, 0); + + EXPECT_EQ(info.levels[2].level, 1); + EXPECT_EQ(info.levels[2].cache_type, CPU_FEATURE_CACHE_DATA); + EXPECT_EQ(info.levels[2].cache_size, 8 * KiB); + EXPECT_EQ(info.levels[2].ways, 4); + EXPECT_EQ(info.levels[2].line_size, 64); + EXPECT_EQ(info.levels[2].tlb_entries, UNDEF); + EXPECT_EQ(info.levels[2].partitioning, 0); + + EXPECT_EQ(info.levels[3].level, 1); + EXPECT_EQ(info.levels[3].cache_type, CPU_FEATURE_CACHE_INSTRUCTION); + EXPECT_EQ(info.levels[3].cache_size, 12 * KiB); + EXPECT_EQ(info.levels[3].ways, 8); + EXPECT_EQ(info.levels[3].line_size, UNDEF); + EXPECT_EQ(info.levels[3].tlb_entries, UNDEF); + EXPECT_EQ(info.levels[3].partitioning, 0); + + EXPECT_EQ(info.levels[4].level, 2); + EXPECT_EQ(info.levels[4].cache_type, CPU_FEATURE_CACHE_DATA); + EXPECT_EQ(info.levels[4].cache_size, 256 * KiB); + EXPECT_EQ(info.levels[4].ways, 8); + EXPECT_EQ(info.levels[4].line_size, 64); + EXPECT_EQ(info.levels[4].tlb_entries, UNDEF); + EXPECT_EQ(info.levels[4].partitioning, 2); +} + // https://github.com/InstLatx64/InstLatx64/blob/master/GenuineIntel/GenuineIntel0000673_P3_KatmaiDP_CPUID.txt TEST_F(CpuidX86Test, P3) { // Pre AVX cpus don't have xsave - g_fake_cpu->SetOsBackupsExtendedRegisters(false); + cpu().SetOsBackupsExtendedRegisters(false); #if defined(CPU_FEATURES_OS_WINDOWS) - g_fake_cpu->SetWindowsIsProcessorFeaturePresent( - PF_XMMI_INSTRUCTIONS_AVAILABLE); + cpu().SetWindowsIsProcessorFeaturePresent(PF_XMMI_INSTRUCTIONS_AVAILABLE); #elif defined(CPU_FEATURES_OS_DARWIN) - g_fake_cpu->SetDarwinSysCtlByName("hw.optional.sse"); + cpu().SetDarwinSysCtlByName("hw.optional.sse"); #elif defined(CPU_FEATURES_OS_FREEBSD) auto& fs = GetEmptyFilesystem(); fs.CreateFile("/var/run/dmesg.boot", R"( @@ -875,7 +1034,7 @@ real memory = 2147418112 (2047 MB) flags : fpu mmx sse )"); #endif - g_fake_cpu->SetLeaves({ + cpu().SetLeaves({ {{0x00000000, 0}, Leaf{0x00000003, 0x756E6547, 0x6C65746E, 0x49656E69}}, {{0x00000001, 0}, Leaf{0x00000673, 0x00000000, 0x00000000, 0x0387FBFF}}, {{0x00000002, 0}, Leaf{0x03020101, 0x00000000, 0x00000000, 0x0C040843}}, diff --git a/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/cpu_features/test/string_view_test.cc b/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/cpu_features/test/string_view_test.cc index 59c906d37..325f83a7a 100644 --- a/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/cpu_features/test/string_view_test.cc +++ b/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/cpu_features/test/string_view_test.cc @@ -167,15 +167,25 @@ TEST(StringViewTest, CpuFeatures_StringView_HasWord) { // Find flags at beginning, middle and end. EXPECT_TRUE( - CpuFeatures_StringView_HasWord(str("first middle last"), "first")); + CpuFeatures_StringView_HasWord(str("first middle last"), "first", ' ')); EXPECT_TRUE( - CpuFeatures_StringView_HasWord(str("first middle last"), "middle")); - EXPECT_TRUE(CpuFeatures_StringView_HasWord(str("first middle last"), "last")); + CpuFeatures_StringView_HasWord(str("first middle last"), "middle", ' ')); + EXPECT_TRUE( + CpuFeatures_StringView_HasWord(str("first middle last"), "last", ' ')); + // Find flags at beginning, middle and end with a different separator + EXPECT_TRUE( + CpuFeatures_StringView_HasWord(str("first-middle-last"), "first", '-')); + EXPECT_TRUE( + CpuFeatures_StringView_HasWord(str("first-middle-last"), "middle", '-')); + EXPECT_TRUE( + CpuFeatures_StringView_HasWord(str("first-middle-last"), "last", '-')); // Do not match partial flags EXPECT_FALSE( - CpuFeatures_StringView_HasWord(str("first middle last"), "irst")); - EXPECT_FALSE(CpuFeatures_StringView_HasWord(str("first middle last"), "mid")); - EXPECT_FALSE(CpuFeatures_StringView_HasWord(str("first middle last"), "las")); + CpuFeatures_StringView_HasWord(str("first middle last"), "irst", ' ')); + EXPECT_FALSE( + CpuFeatures_StringView_HasWord(str("first middle last"), "mid", ' ')); + EXPECT_FALSE( + CpuFeatures_StringView_HasWord(str("first middle last"), "las", ' ')); } TEST(StringViewTest, CpuFeatures_StringView_GetAttributeKeyValue)