Update cpu_features to 628c50e with support for Apple M1 already merged

This commit is contained in:
Carles Fernandez 2021-07-25 14:09:03 +02:00
parent 9107705ba9
commit 9e921d161c
No known key found for this signature in database
GPG Key ID: 4C583C52B0C3877D
21 changed files with 883 additions and 278 deletions

View File

@ -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

View File

@ -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

View File

@ -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()

View File

@ -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).

View File

@ -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:

View File

@ -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.

View File

@ -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_

View File

@ -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);

View File

@ -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,

View File

@ -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

View File

@ -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;
}

View File

@ -84,7 +84,8 @@
// microarchitectures.
#if defined(CPU_FEATURES_OS_WINDOWS)
#include <windows.h> // 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<PSE36,MMX,FXSR,SSE,SSE2,HTT>"
// 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";
}

View File

@ -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

View File

@ -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)

View File

@ -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)

View File

@ -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)");

View File

@ -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

View File

@ -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

View File

@ -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"(
---<<BOOT>>---
Copyright (c) 1992-2020 The FreeBSD Project.
FreeBSD is a registered trademark of The FreeBSD Foundation.
Features=0x1783fbff<FPU,VME,DE,PSE,TSC,MSR,PAE,MCE,CX8,APIC,SEP,MTRR,PGE,MCA,CMOV,PAT,PSE36,MMX,FXSR,SSE,SSE2,HTT>
Features2=0x5eda2203<SSE3,PCLMULQDQ,SSSE3,CX16,PCID,SSE4.1,SSE4.2,MOVBE,POPCNT,AESNI,XSAVE,OSXSAVE,RDRAND>
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"(
---<<BOOT>>---
Copyright (c) 1992-2020 The FreeBSD Project.
FreeBSD is a registered trademark of The FreeBSD Foundation.
Features=0x1783fbff<FPU,VME,DE,PSE,TSC,MSR,PAE,MCE,CX8,APIC,SEP,MTRR,PGE,MCA,CMOV,PAT,PSE36,MMX,FXSR,SSE,SSE2,HTT>
Features2=0x5eda2203<SSE3,PCLMULQDQ,SSSE3,CX16,PCID,SSE4.1,SSE4.2,MOVBE,POPCNT,AESNI,XSAVE,OSXSAVE,RDRAND>
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"(
---<<BOOT>>---
Copyright (c) 1992-2020 The FreeBSD Project.
FreeBSD is a registered trademark of The FreeBSD Foundation.
Features=0x1783fbff<FPU,VME,DE,PSE,TSC,MSR,PAE,MCE,CX8,APIC,SEP,MTRR,PGE,MCA,CMOV,PAT,PSE36,MMX,FXSR,SSE>
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.

View File

@ -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

View File

@ -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