mirror of
https://github.com/gnss-sdr/gnss-sdr
synced 2024-12-15 04:30:33 +00:00
Update cpu_features, fix integration
This commit is contained in:
parent
292d084478
commit
97224e60d2
@ -229,8 +229,10 @@ endif()
|
|||||||
|
|
||||||
# cpu_features
|
# cpu_features
|
||||||
if(CMAKE_VERSION VERSION_GREATER 3.0)
|
if(CMAKE_VERSION VERSION_GREATER 3.0)
|
||||||
set(CMAKE_POSITION_INDEPENDENT_CODE ON)
|
set(BUILD_PIC ON CACHE BOOL
|
||||||
set(BUILD_PIC ON)
|
"Build cpu_features with Position Independent Code (PIC)."
|
||||||
|
FORCE
|
||||||
|
)
|
||||||
set(USE_CPU_FEATURES ON)
|
set(USE_CPU_FEATURES ON)
|
||||||
add_subdirectory(cpu_features)
|
add_subdirectory(cpu_features)
|
||||||
endif()
|
endif()
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
|
||||||
set(CMAKE_SYSTEM_NAME Linux)
|
set(CMAKE_SYSTEM_NAME Linux)
|
||||||
set(CMAKE_SYSTEM_PROCESSOR ARM)
|
set(CMAKE_SYSTEM_PROCESSOR aarch64)
|
||||||
|
|
||||||
if(MINGW OR CYGWIN OR WIN32)
|
if(MINGW OR CYGWIN OR WIN32)
|
||||||
set(UTIL_SEARCH_CMD where)
|
set(UTIL_SEARCH_CMD where)
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
|
||||||
set(CMAKE_SYSTEM_NAME Linux)
|
set(CMAKE_SYSTEM_NAME Linux)
|
||||||
set(CMAKE_SYSTEM_PROCESSOR ARM)
|
set(CMAKE_SYSTEM_PROCESSOR arm)
|
||||||
|
|
||||||
if(MINGW OR CYGWIN OR WIN32)
|
if(MINGW OR CYGWIN OR WIN32)
|
||||||
set(UTIL_SEARCH_CMD where)
|
set(UTIL_SEARCH_CMD where)
|
||||||
|
@ -9,19 +9,16 @@ if(POLICY CMP0077)
|
|||||||
cmake_policy(SET CMP0077 NEW)
|
cmake_policy(SET CMP0077 NEW)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
project(CpuFeatures VERSION 0.1.0 LANGUAGES C)
|
project(CpuFeatures VERSION 0.6.0 LANGUAGES C)
|
||||||
|
|
||||||
|
set(CMAKE_C_STANDARD 99)
|
||||||
|
|
||||||
if(NOT (CMAKE_VERSION VERSION_LESS "3.1"))
|
|
||||||
set(CMAKE_C_STANDARD 99)
|
|
||||||
else()
|
|
||||||
add_compile_options("$<$<STREQUAL:$<TARGET_PROPERTY:LINKER_LANGUAGE>,C>:-std=gnu99>")
|
|
||||||
endif()
|
|
||||||
# Default Build Type to be Release
|
# Default Build Type to be Release
|
||||||
if(NOT CMAKE_BUILD_TYPE)
|
if(NOT CMAKE_BUILD_TYPE)
|
||||||
set(CMAKE_BUILD_TYPE "Release" CACHE STRING
|
set(CMAKE_BUILD_TYPE "Release" CACHE STRING
|
||||||
"Choose the type of build, options are: Debug Release RelWithDebInfo MinSizeRel."
|
"Choose the type of build, options are: Debug Release RelWithDebInfo MinSizeRel."
|
||||||
FORCE)
|
FORCE)
|
||||||
endif()
|
endif(NOT CMAKE_BUILD_TYPE)
|
||||||
|
|
||||||
# BUILD_TESTING is a standard CMake variable, but we declare it here to make it
|
# BUILD_TESTING is a standard CMake variable, but we declare it here to make it
|
||||||
# prominent in the GUI.
|
# prominent in the GUI.
|
||||||
@ -120,9 +117,7 @@ setup_include_and_definitions(utils)
|
|||||||
if(UNIX)
|
if(UNIX)
|
||||||
add_library(unix_based_hardware_detection OBJECT
|
add_library(unix_based_hardware_detection OBJECT
|
||||||
${PROJECT_SOURCE_DIR}/include/internal/hwcaps.h
|
${PROJECT_SOURCE_DIR}/include/internal/hwcaps.h
|
||||||
${PROJECT_SOURCE_DIR}/include/internal/unix_features_aggregator.h
|
|
||||||
${PROJECT_SOURCE_DIR}/src/hwcaps.c
|
${PROJECT_SOURCE_DIR}/src/hwcaps.c
|
||||||
${PROJECT_SOURCE_DIR}/src/unix_features_aggregator.c
|
|
||||||
)
|
)
|
||||||
setup_include_and_definitions(unix_based_hardware_detection)
|
setup_include_and_definitions(unix_based_hardware_detection)
|
||||||
check_include_file(dlfcn.h HAVE_DLFCN_H)
|
check_include_file(dlfcn.h HAVE_DLFCN_H)
|
||||||
@ -139,8 +134,8 @@ endif()
|
|||||||
#
|
#
|
||||||
# library : cpu_features
|
# library : cpu_features
|
||||||
#
|
#
|
||||||
set(CPU_FEATURES_HDRS)
|
set (CPU_FEATURES_HDRS)
|
||||||
set(CPU_FEATURES_SRCS)
|
set (CPU_FEATURES_SRCS)
|
||||||
add_cpu_features_headers_and_sources(CPU_FEATURES_HDRS CPU_FEATURES_SRCS)
|
add_cpu_features_headers_and_sources(CPU_FEATURES_HDRS CPU_FEATURES_SRCS)
|
||||||
list(APPEND CPU_FEATURES_SRCS $<TARGET_OBJECTS:utils>)
|
list(APPEND CPU_FEATURES_SRCS $<TARGET_OBJECTS:utils>)
|
||||||
if(NOT PROCESSOR_IS_X86 AND UNIX)
|
if(NOT PROCESSOR_IS_X86 AND UNIX)
|
||||||
@ -154,6 +149,11 @@ set_property(TARGET cpu_features PROPERTY POSITION_INDEPENDENT_CODE ${BUILD_PIC}
|
|||||||
target_include_directories(cpu_features
|
target_include_directories(cpu_features
|
||||||
PUBLIC $<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}/cpu_features>
|
PUBLIC $<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}/cpu_features>
|
||||||
)
|
)
|
||||||
|
if(PROCESSOR_IS_X86)
|
||||||
|
if(APPLE)
|
||||||
|
target_compile_definitions(cpu_features PRIVATE HAVE_SYSCTLBYNAME)
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
add_library(CpuFeature::cpu_features ALIAS cpu_features)
|
add_library(CpuFeature::cpu_features ALIAS cpu_features)
|
||||||
|
|
||||||
#
|
#
|
||||||
@ -219,8 +219,7 @@ if(BUILD_TESTING)
|
|||||||
# gtest_main targets.
|
# gtest_main targets.
|
||||||
add_subdirectory(${CMAKE_BINARY_DIR}/googletest-src
|
add_subdirectory(${CMAKE_BINARY_DIR}/googletest-src
|
||||||
${CMAKE_BINARY_DIR}/googletest-build
|
${CMAKE_BINARY_DIR}/googletest-build
|
||||||
EXCLUDE_FROM_ALL
|
EXCLUDE_FROM_ALL)
|
||||||
)
|
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
add_subdirectory(test)
|
add_subdirectory(test)
|
||||||
|
@ -6,7 +6,7 @@ SPDX-License-Identifier: Apache-2.0
|
|||||||
)
|
)
|
||||||
|
|
||||||
[comment]: # (
|
[comment]: # (
|
||||||
SPDX-FileCopyrightText: 2017 Google Inc.
|
SPDX-FileCopyrightText: 2017 Google LLC
|
||||||
)
|
)
|
||||||
<!-- prettier-ignore-end -->
|
<!-- prettier-ignore-end -->
|
||||||
|
|
||||||
@ -42,6 +42,11 @@ instructions) at runtime.
|
|||||||
|
|
||||||
<a name="codesample"></a>
|
<a name="codesample"></a>
|
||||||
|
|
||||||
|
## Code samples
|
||||||
|
|
||||||
|
**Note:** For C++ code, the library functions are defined in the `CpuFeatures`
|
||||||
|
namespace.
|
||||||
|
|
||||||
### Checking features at runtime
|
### Checking features at runtime
|
||||||
|
|
||||||
Here's a simple example that executes a codepath if the CPU supports both the
|
Here's a simple example that executes a codepath if the CPU supports both the
|
||||||
@ -50,6 +55,7 @@ AES and the SSE4.2 instruction sets:
|
|||||||
```c
|
```c
|
||||||
#include "cpuinfo_x86.h"
|
#include "cpuinfo_x86.h"
|
||||||
|
|
||||||
|
// For C++, add `using namespace CpuFeatures;`
|
||||||
static const X86Features features = GetX86Info().features;
|
static const X86Features features = GetX86Info().features;
|
||||||
|
|
||||||
void Compute(void) {
|
void Compute(void) {
|
||||||
@ -71,6 +77,7 @@ features and then check whether AES and NEON are supported.
|
|||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
#include "cpuinfo_arm.h"
|
#include "cpuinfo_arm.h"
|
||||||
|
|
||||||
|
// For C++, add `using namespace CpuFeatures;`
|
||||||
static const ArmFeatures features = GetArmInfo().features;
|
static const ArmFeatures features = GetArmInfo().features;
|
||||||
static const bool has_aes_and_neon = features.aes && features.neon;
|
static const bool has_aes_and_neon = features.aes && features.neon;
|
||||||
|
|
||||||
@ -90,6 +97,7 @@ instruction set (e.g., `g++ -mavx`) and sets `has_avx` accordingly.
|
|||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
#include "cpuinfo_x86.h"
|
#include "cpuinfo_x86.h"
|
||||||
|
|
||||||
|
// For C++, add `using namespace CpuFeatures;`
|
||||||
static const X86Features features = GetX86Info().features;
|
static const X86Features features = GetX86Info().features;
|
||||||
static const bool has_avx = CPU_FEATURES_COMPILED_X86_AVX || features.avx;
|
static const bool has_avx = CPU_FEATURES_COMPILED_X86_AVX || features.avx;
|
||||||
|
|
||||||
@ -112,6 +120,7 @@ set—but only if it's not Sandy Bridge.
|
|||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
#include "cpuinfo_x86.h"
|
#include "cpuinfo_x86.h"
|
||||||
|
|
||||||
|
// For C++, add `using namespace CpuFeatures;`
|
||||||
static const X86Info info = GetX86Info();
|
static const X86Info info = GetX86Info();
|
||||||
static const X86Microarchitecture uarch = GetX86Microarchitecture(&info);
|
static const X86Microarchitecture uarch = GetX86Microarchitecture(&info);
|
||||||
static const bool has_fast_avx = info.features.avx && uarch != INTEL_SNB;
|
static const bool has_fast_avx = info.features.avx && uarch != INTEL_SNB;
|
||||||
@ -125,7 +134,8 @@ This feature is currently available only for x86 microarchitectures.
|
|||||||
|
|
||||||
### Running sample code
|
### Running sample code
|
||||||
|
|
||||||
Building `cpu_features` brings a small executable to test the library.
|
Building `cpu_features` (check [quickstart](#quickstart) below) brings a small
|
||||||
|
executable to test the library.
|
||||||
|
|
||||||
```shell
|
```shell
|
||||||
% ./build/list_cpu_features
|
% ./build/list_cpu_features
|
||||||
@ -190,3 +200,23 @@ The cpu_features library is licensed under the terms of the Apache license. See
|
|||||||
## Build with CMake
|
## Build with CMake
|
||||||
|
|
||||||
Please check the [CMake build instructions](cmake/README.md).
|
Please check the [CMake build instructions](cmake/README.md).
|
||||||
|
|
||||||
|
<a name="quickstart"></a>
|
||||||
|
|
||||||
|
### Quickstart with `Ninja`
|
||||||
|
|
||||||
|
- build `list_cpu_features`
|
||||||
|
|
||||||
|
```
|
||||||
|
cmake -B/tmp/cpu_features -H. -GNinja -DCMAKE_BUILD_TYPE=Release
|
||||||
|
ninja -C/tmp/cpu_features
|
||||||
|
/tmp/cpu_features/list_cpu_features --json
|
||||||
|
```
|
||||||
|
|
||||||
|
- run tests
|
||||||
|
|
||||||
|
```
|
||||||
|
cmake -B/tmp/cpu_features -H. -GNinja -DBUILD_TESTING=ON
|
||||||
|
ninja -C/tmp/cpu_features
|
||||||
|
ninja -C/tmp/cpu_features test
|
||||||
|
```
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
# SPDX-FileCopyrightText: 2017 Google Inc.
|
# SPDX-FileCopyrightText: 2017 Google LLC
|
||||||
# SPDX-License-Identifier: Apache-2.0
|
# SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
# CpuFeatures CMake configuration file
|
# CpuFeatures CMake configuration file
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
# SPDX-FileCopyrightText: 2017 Google Inc.
|
# SPDX-FileCopyrightText: 2017 Google LLC
|
||||||
# SPDX-License-Identifier: Apache-2.0
|
# SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
# CpuFeaturesNdkCompat CMake configuration file
|
# CpuFeaturesNdkCompat CMake configuration file
|
||||||
|
@ -6,7 +6,7 @@ SPDX-License-Identifier: Apache-2.0
|
|||||||
)
|
)
|
||||||
|
|
||||||
[comment]: # (
|
[comment]: # (
|
||||||
SPDX-FileCopyrightText: 2017 Google Inc.
|
SPDX-FileCopyrightText: 2017 Google LLC
|
||||||
)
|
)
|
||||||
<!-- prettier-ignore-end -->
|
<!-- prettier-ignore-end -->
|
||||||
|
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
# SPDX-FileCopyrightText: 2017 Google Inc.
|
# SPDX-FileCopyrightText: 2017 Google LLC
|
||||||
# SPDX-License-Identifier: Apache-2.0
|
# SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
cmake_minimum_required(VERSION 2.8.2)
|
cmake_minimum_required(VERSION 2.8.2)
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
// SPDX-FileCopyrightText: 2017 Google Inc.
|
// SPDX-FileCopyrightText: 2017 Google LLC
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
#ifndef CPU_FEATURES_INCLUDE_CPUINFO_COMMON_H_
|
#ifndef CPU_FEATURES_INCLUDE_CPUINFO_COMMON_H_
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
// SPDX-FileCopyrightText: 2017 Google Inc.
|
// SPDX-FileCopyrightText: 2017 Google LLC
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
|
|
||||||
@ -69,6 +69,10 @@
|
|||||||
#define CPU_FEATURES_OS_WINDOWS
|
#define CPU_FEATURES_OS_WINDOWS
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if (defined(__apple__) || defined(__APPLE__) || defined(__MACH__))
|
||||||
|
#define CPU_FEATURES_OS_DARWIN
|
||||||
|
#endif
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
// Compilers
|
// Compilers
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
// SPDX-FileCopyrightText: 2017 Google Inc.
|
// SPDX-FileCopyrightText: 2017 Google LLC
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
|
|
||||||
@ -44,6 +44,24 @@ typedef struct
|
|||||||
int sb : 1; // Speculation barrier.
|
int sb : 1; // Speculation barrier.
|
||||||
int paca : 1; // Address authentication.
|
int paca : 1; // Address authentication.
|
||||||
int pacg : 1; // Generic authentication.
|
int pacg : 1; // Generic authentication.
|
||||||
|
int dcpodp : 1; // Data cache clean to point of persistence.
|
||||||
|
int sve2 : 1; // Scalable Vector Extension (version 2).
|
||||||
|
int sveaes : 1; // SVE AES instructions.
|
||||||
|
int svepmull : 1; // SVE polynomial multiply long instructions.
|
||||||
|
int svebitperm : 1; // SVE bit permute instructions.
|
||||||
|
int svesha3 : 1; // SVE SHA3 instructions.
|
||||||
|
int svesm4 : 1; // SVE SM4 instructions.
|
||||||
|
int flagm2 : 1; // Additional flag manipulation instructions.
|
||||||
|
int frint : 1; // Floating point to integer rounding.
|
||||||
|
int svei8mm : 1; // SVE Int8 matrix multiplication instructions.
|
||||||
|
int svef32mm : 1; // SVE FP32 matrix multiplication instruction.
|
||||||
|
int svef64mm : 1; // SVE FP64 matrix multiplication instructions.
|
||||||
|
int svebf16 : 1; // SVE BFloat16 instructions.
|
||||||
|
int i8mm : 1; // Int8 matrix multiplication instructions.
|
||||||
|
int bf16 : 1; // BFloat16 instructions.
|
||||||
|
int dgh : 1; // Data Gathering Hint instruction.
|
||||||
|
int rng : 1; // True random number generator support.
|
||||||
|
int bti : 1; // Branch target identification.
|
||||||
|
|
||||||
// Make sure to update Aarch64FeaturesEnum below if you add a field here.
|
// Make sure to update Aarch64FeaturesEnum below if you add a field here.
|
||||||
} Aarch64Features;
|
} Aarch64Features;
|
||||||
@ -96,6 +114,24 @@ typedef enum
|
|||||||
AARCH64_SB,
|
AARCH64_SB,
|
||||||
AARCH64_PACA,
|
AARCH64_PACA,
|
||||||
AARCH64_PACG,
|
AARCH64_PACG,
|
||||||
|
AARCH64_DCPODP,
|
||||||
|
AARCH64_SVE2,
|
||||||
|
AARCH64_SVEAES,
|
||||||
|
AARCH64_SVEPMULL,
|
||||||
|
AARCH64_SVEBITPERM,
|
||||||
|
AARCH64_SVESHA3,
|
||||||
|
AARCH64_SVESM4,
|
||||||
|
AARCH64_FLAGM2,
|
||||||
|
AARCH64_FRINT,
|
||||||
|
AARCH64_SVEI8MM,
|
||||||
|
AARCH64_SVEF32MM,
|
||||||
|
AARCH64_SVEF64MM,
|
||||||
|
AARCH64_SVEBF16,
|
||||||
|
AARCH64_I8MM,
|
||||||
|
AARCH64_BF16,
|
||||||
|
AARCH64_DGH,
|
||||||
|
AARCH64_RNG,
|
||||||
|
AARCH64_BTI,
|
||||||
AARCH64_LAST_,
|
AARCH64_LAST_,
|
||||||
} Aarch64FeaturesEnum;
|
} Aarch64FeaturesEnum;
|
||||||
|
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
// SPDX-FileCopyrightText: 2017 Google Inc.
|
// SPDX-FileCopyrightText: 2017 Google LLC
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
|
|
||||||
@ -16,11 +16,13 @@ typedef struct
|
|||||||
int swp : 1; // SWP instruction (atomic read-modify-write)
|
int swp : 1; // SWP instruction (atomic read-modify-write)
|
||||||
int half : 1; // Half-word loads and stores
|
int half : 1; // Half-word loads and stores
|
||||||
int thumb : 1; // Thumb (16-bit instruction set)
|
int thumb : 1; // Thumb (16-bit instruction set)
|
||||||
int _26bit : 1; // "26 Bit" Model (Processor status register folded into program counter)
|
int _26bit : 1; // "26 Bit" Model (Processor status register folded into
|
||||||
|
// program counter)
|
||||||
int fastmult : 1; // 32x32->64-bit multiplication
|
int fastmult : 1; // 32x32->64-bit multiplication
|
||||||
int fpa : 1; // Floating point accelerator
|
int fpa : 1; // Floating point accelerator
|
||||||
int vfp : 1; // Vector Floating Point.
|
int vfp : 1; // Vector Floating Point.
|
||||||
int edsp : 1; // DSP extensions (the 'e' variant of the ARM9 CPUs, and all others above)
|
int edsp : 1; // DSP extensions (the 'e' variant of the ARM9 CPUs, and all
|
||||||
|
// others above)
|
||||||
int java : 1; // Jazelle (Java bytecode accelerator)
|
int java : 1; // Jazelle (Java bytecode accelerator)
|
||||||
int iwmmxt : 1; // Intel Wireless MMX Technology.
|
int iwmmxt : 1; // Intel Wireless MMX Technology.
|
||||||
int crunch : 1; // MaverickCrunch coprocessor
|
int crunch : 1; // MaverickCrunch coprocessor
|
||||||
@ -33,7 +35,8 @@ typedef struct
|
|||||||
int idiva : 1; // SDIV and UDIV hardware division in ARM mode.
|
int idiva : 1; // SDIV and UDIV hardware division in ARM mode.
|
||||||
int idivt : 1; // SDIV and UDIV hardware division in Thumb mode.
|
int idivt : 1; // SDIV and UDIV hardware division in Thumb mode.
|
||||||
int vfpd32 : 1; // VFP with 32 D-registers
|
int vfpd32 : 1; // VFP with 32 D-registers
|
||||||
int lpae : 1; // Large Physical Address Extension (>4GB physical memory on 32-bit architecture)
|
int lpae : 1; // Large Physical Address Extension (>4GB physical memory on
|
||||||
|
// 32-bit architecture)
|
||||||
int evtstrm : 1; // kernel event stream using generic architected timer
|
int evtstrm : 1; // kernel event stream using generic architected timer
|
||||||
int aes : 1; // Hardware-accelerated Advanced Encryption Standard.
|
int aes : 1; // Hardware-accelerated Advanced Encryption Standard.
|
||||||
int pmull : 1; // Polynomial multiply long.
|
int pmull : 1; // Polynomial multiply long.
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
// SPDX-FileCopyrightText: 2017 Google Inc.
|
// SPDX-FileCopyrightText: 2017 Google LLC
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
|
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
// SPDX-FileCopyrightText: 2017 Google Inc.
|
// SPDX-FileCopyrightText: 2017 Google LLC
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
|
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
// SPDX-FileCopyrightText: 2017 Google Inc.
|
// SPDX-FileCopyrightText: 2017 Google LLC
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
|
|
||||||
@ -60,6 +60,13 @@ typedef struct
|
|||||||
int avx512vpopcntdq : 1;
|
int avx512vpopcntdq : 1;
|
||||||
int avx512_4vnniw : 1;
|
int avx512_4vnniw : 1;
|
||||||
int avx512_4vbmi2 : 1;
|
int avx512_4vbmi2 : 1;
|
||||||
|
int avx512_second_fma : 1;
|
||||||
|
int avx512_4fmaps : 1;
|
||||||
|
int avx512_bf16 : 1;
|
||||||
|
int avx512_vp2intersect : 1;
|
||||||
|
int amx_bf16 : 1;
|
||||||
|
int amx_tile : 1;
|
||||||
|
int amx_int8 : 1;
|
||||||
|
|
||||||
int pclmulqdq : 1;
|
int pclmulqdq : 1;
|
||||||
int smx : 1;
|
int smx : 1;
|
||||||
@ -114,6 +121,8 @@ typedef enum
|
|||||||
INTEL_WHL, // WHISKEY LAKE
|
INTEL_WHL, // WHISKEY LAKE
|
||||||
INTEL_CNL, // CANNON LAKE
|
INTEL_CNL, // CANNON LAKE
|
||||||
INTEL_ICL, // ICE LAKE
|
INTEL_ICL, // ICE LAKE
|
||||||
|
INTEL_TGL, // TIGER LAKE
|
||||||
|
INTEL_SPR, // SAPPHIRE RAPIDS
|
||||||
AMD_HAMMER, // K8
|
AMD_HAMMER, // K8
|
||||||
AMD_K10, // K10
|
AMD_K10, // K10
|
||||||
AMD_BOBCAT, // K14
|
AMD_BOBCAT, // K14
|
||||||
@ -180,6 +189,13 @@ typedef enum
|
|||||||
X86_AVX512VPOPCNTDQ,
|
X86_AVX512VPOPCNTDQ,
|
||||||
X86_AVX512_4VNNIW,
|
X86_AVX512_4VNNIW,
|
||||||
X86_AVX512_4VBMI2,
|
X86_AVX512_4VBMI2,
|
||||||
|
X86_AVX512_SECOND_FMA,
|
||||||
|
X86_AVX512_4FMAPS,
|
||||||
|
X86_AVX512_BF16,
|
||||||
|
X86_AVX512_VP2INTERSECT,
|
||||||
|
X86_AMX_BF16,
|
||||||
|
X86_AMX_TILE,
|
||||||
|
X86_AMX_INT8,
|
||||||
X86_PCLMULQDQ,
|
X86_PCLMULQDQ,
|
||||||
X86_SMX,
|
X86_SMX,
|
||||||
X86_SGX,
|
X86_SGX,
|
||||||
@ -205,4 +221,4 @@ CPU_FEATURES_END_CPP_NAMESPACE
|
|||||||
#error "Including cpuinfo_x86.h from a non-x86 target."
|
#error "Including cpuinfo_x86.h from a non-x86 target."
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif // CPU_FEATURES_INCLUDE_CPUINFO_X86_H_
|
#endif // CPU_FEATURES_INCLUDE_CPUINFO_X86_H
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
// SPDX-FileCopyrightText: 2017 Google Inc.
|
// SPDX-FileCopyrightText: 2017 Google LLC
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
|
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
// SPDX-FileCopyrightText: 2017 Google Inc.
|
// SPDX-FileCopyrightText: 2017 Google LLC
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
|
|
||||||
@ -16,7 +16,8 @@ typedef struct
|
|||||||
uint32_t eax, ebx, ecx, edx;
|
uint32_t eax, ebx, ecx, edx;
|
||||||
} Leaf;
|
} Leaf;
|
||||||
|
|
||||||
Leaf CpuIdEx(uint32_t leaf_id, int ecx);
|
// Returns the result of a call to the cpuid instruction.
|
||||||
|
Leaf GetCpuidLeaf(uint32_t leaf_id, int ecx);
|
||||||
|
|
||||||
// Returns the eax value of the XCR0 register.
|
// Returns the eax value of the XCR0 register.
|
||||||
uint32_t GetXCR0Eax(void);
|
uint32_t GetXCR0Eax(void);
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
// SPDX-FileCopyrightText: 2017 Google Inc.
|
// SPDX-FileCopyrightText: 2017 Google LLC
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
|
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
// SPDX-FileCopyrightText: 2017 Google Inc.
|
// SPDX-FileCopyrightText: 2017 Google LLC
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
|
|
||||||
@ -8,6 +8,7 @@
|
|||||||
#define CPU_FEATURES_INCLUDE_INTERNAL_HWCAPS_H_
|
#define CPU_FEATURES_INCLUDE_INTERNAL_HWCAPS_H_
|
||||||
|
|
||||||
#include "cpu_features_macros.h"
|
#include "cpu_features_macros.h"
|
||||||
|
#include <stdbool.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
CPU_FEATURES_START_CPP_NAMESPACE
|
CPU_FEATURES_START_CPP_NAMESPACE
|
||||||
@ -49,6 +50,25 @@ CPU_FEATURES_START_CPP_NAMESPACE
|
|||||||
#define AARCH64_HWCAP_PACA (1UL << 30)
|
#define AARCH64_HWCAP_PACA (1UL << 30)
|
||||||
#define AARCH64_HWCAP_PACG (1UL << 31)
|
#define AARCH64_HWCAP_PACG (1UL << 31)
|
||||||
|
|
||||||
|
#define AARCH64_HWCAP2_DCPODP (1UL << 0)
|
||||||
|
#define AARCH64_HWCAP2_SVE2 (1UL << 1)
|
||||||
|
#define AARCH64_HWCAP2_SVEAES (1UL << 2)
|
||||||
|
#define AARCH64_HWCAP2_SVEPMULL (1UL << 3)
|
||||||
|
#define AARCH64_HWCAP2_SVEBITPERM (1UL << 4)
|
||||||
|
#define AARCH64_HWCAP2_SVESHA3 (1UL << 5)
|
||||||
|
#define AARCH64_HWCAP2_SVESM4 (1UL << 6)
|
||||||
|
#define AARCH64_HWCAP2_FLAGM2 (1UL << 7)
|
||||||
|
#define AARCH64_HWCAP2_FRINT (1UL << 8)
|
||||||
|
#define AARCH64_HWCAP2_SVEI8MM (1UL << 9)
|
||||||
|
#define AARCH64_HWCAP2_SVEF32MM (1UL << 10)
|
||||||
|
#define AARCH64_HWCAP2_SVEF64MM (1UL << 11)
|
||||||
|
#define AARCH64_HWCAP2_SVEBF16 (1UL << 12)
|
||||||
|
#define AARCH64_HWCAP2_I8MM (1UL << 13)
|
||||||
|
#define AARCH64_HWCAP2_BF16 (1UL << 14)
|
||||||
|
#define AARCH64_HWCAP2_DGH (1UL << 15)
|
||||||
|
#define AARCH64_HWCAP2_RNG (1UL << 16)
|
||||||
|
#define AARCH64_HWCAP2_BTI (1UL << 17)
|
||||||
|
|
||||||
// http://elixir.free-electrons.com/linux/latest/source/arch/arm/include/uapi/asm/hwcap.h
|
// http://elixir.free-electrons.com/linux/latest/source/arch/arm/include/uapi/asm/hwcap.h
|
||||||
#define ARM_HWCAP_SWP (1UL << 0)
|
#define ARM_HWCAP_SWP (1UL << 0)
|
||||||
#define ARM_HWCAP_HALF (1UL << 1)
|
#define ARM_HWCAP_HALF (1UL << 1)
|
||||||
@ -141,6 +161,8 @@ typedef struct
|
|||||||
} HardwareCapabilities;
|
} HardwareCapabilities;
|
||||||
|
|
||||||
HardwareCapabilities CpuFeatures_GetHardwareCapabilities(void);
|
HardwareCapabilities CpuFeatures_GetHardwareCapabilities(void);
|
||||||
|
bool CpuFeatures_IsHwCapsSet(const HardwareCapabilities hwcaps_mask,
|
||||||
|
const HardwareCapabilities hwcaps);
|
||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
// SPDX-FileCopyrightText: 2017 Google Inc.
|
// SPDX-FileCopyrightText: 2017 Google LLC
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
|
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
// SPDX-FileCopyrightText: 2017 Google Inc.
|
// SPDX-FileCopyrightText: 2017 Google LLC
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
|
|
||||||
|
@ -1,65 +0,0 @@
|
|||||||
// SPDX-FileCopyrightText: 2017 Google Inc.
|
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
|
||||||
|
|
||||||
|
|
||||||
// CapabilityConfig provides a way to map cpu features to hardware caps and
|
|
||||||
// /proc/cpuinfo flags. We then provide functions to update capabilities from
|
|
||||||
// either source.
|
|
||||||
#ifndef CPU_FEATURES_INCLUDE_INTERNAL_LINUX_FEATURES_AGGREGATOR_H_
|
|
||||||
#define CPU_FEATURES_INCLUDE_INTERNAL_LINUX_FEATURES_AGGREGATOR_H_
|
|
||||||
|
|
||||||
#include "cpu_features_macros.h"
|
|
||||||
#include "internal/hwcaps.h"
|
|
||||||
#include "internal/string_view.h"
|
|
||||||
#include <ctype.h>
|
|
||||||
#include <stdint.h>
|
|
||||||
|
|
||||||
CPU_FEATURES_START_CPP_NAMESPACE
|
|
||||||
|
|
||||||
// Use the following macro to declare setter functions to be used in
|
|
||||||
// CapabilityConfig.
|
|
||||||
#define DECLARE_SETTER(FeatureType, FeatureName) \
|
|
||||||
static void set_##FeatureName(void* const features, bool value) \
|
|
||||||
{ \
|
|
||||||
((FeatureType*)features)->FeatureName = value; \
|
|
||||||
}
|
|
||||||
|
|
||||||
// Use the following macro to declare getter functions to be used in
|
|
||||||
// CapabilityConfig.
|
|
||||||
#define DECLARE_GETTER(FeatureType, FeatureName) \
|
|
||||||
static int get_##FeatureName(void* const features) \
|
|
||||||
{ \
|
|
||||||
return ((FeatureType*)features)->FeatureName; \
|
|
||||||
}
|
|
||||||
|
|
||||||
#define DECLARE_SETTER_AND_GETTER(FeatureType, FeatureName) \
|
|
||||||
DECLARE_SETTER(FeatureType, FeatureName) \
|
|
||||||
DECLARE_GETTER(FeatureType, FeatureName)
|
|
||||||
|
|
||||||
// Describes the relationship between hardware caps and /proc/cpuinfo flags.
|
|
||||||
typedef struct
|
|
||||||
{
|
|
||||||
const HardwareCapabilities hwcaps_mask;
|
|
||||||
const char* const proc_cpuinfo_flag;
|
|
||||||
void (*set_bit)(void* const, bool); // setter for the corresponding bit.
|
|
||||||
int (*get_bit)(void* const); // getter for the corresponding bit.
|
|
||||||
} CapabilityConfig;
|
|
||||||
|
|
||||||
// For every config, looks into flags_line for the presence of the
|
|
||||||
// corresponding proc_cpuinfo_flag, calls `set_bit` accordingly.
|
|
||||||
// Note: features is a pointer to the underlying Feature struct.
|
|
||||||
void CpuFeatures_SetFromFlags(const size_t configs_size,
|
|
||||||
const CapabilityConfig* configs,
|
|
||||||
const StringView flags_line,
|
|
||||||
void* const features);
|
|
||||||
|
|
||||||
// For every config, looks into hwcaps for the presence of the feature. Calls
|
|
||||||
// `set_bit` with true if the hardware capability is found.
|
|
||||||
// Note: features is a pointer to the underlying Feature struct.
|
|
||||||
void CpuFeatures_OverrideFromHwCaps(const size_t configs_size,
|
|
||||||
const CapabilityConfig* configs,
|
|
||||||
const HardwareCapabilities hwcaps,
|
|
||||||
void* const features);
|
|
||||||
|
|
||||||
CPU_FEATURES_END_CPP_NAMESPACE
|
|
||||||
#endif // CPU_FEATURES_INCLUDE_INTERNAL_LINUX_FEATURES_AGGREGATOR_H_
|
|
@ -5,8 +5,8 @@
|
|||||||
# library : NDK compat
|
# library : NDK compat
|
||||||
#
|
#
|
||||||
find_package(Threads REQUIRED)
|
find_package(Threads REQUIRED)
|
||||||
set(NDK_COMPAT_HDRS cpu-features.h)
|
set (NDK_COMPAT_HDRS cpu-features.h)
|
||||||
set(NDK_COMPAT_SRCS
|
set (NDK_COMPAT_SRCS
|
||||||
cpu-features.c
|
cpu-features.c
|
||||||
$<TARGET_OBJECTS:utils>
|
$<TARGET_OBJECTS:utils>
|
||||||
$<TARGET_OBJECTS:unix_based_hardware_detection>
|
$<TARGET_OBJECTS:unix_based_hardware_detection>
|
||||||
@ -17,6 +17,7 @@ set(NDK_COMPAT_SRCS
|
|||||||
add_cpu_features_headers_and_sources(NDK_COMPAT_SRCS NDK_COMPAT_SRCS)
|
add_cpu_features_headers_and_sources(NDK_COMPAT_SRCS NDK_COMPAT_SRCS)
|
||||||
add_library(ndk_compat ${NDK_COMPAT_HDRS} ${NDK_COMPAT_SRCS})
|
add_library(ndk_compat ${NDK_COMPAT_HDRS} ${NDK_COMPAT_SRCS})
|
||||||
setup_include_and_definitions(ndk_compat)
|
setup_include_and_definitions(ndk_compat)
|
||||||
|
target_include_directories(ndk_compat PUBLIC $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}>)
|
||||||
target_link_libraries(ndk_compat PUBLIC ${CMAKE_DL_LIBS} ${CMAKE_THREAD_LIBS_INIT})
|
target_link_libraries(ndk_compat PUBLIC ${CMAKE_DL_LIBS} ${CMAKE_THREAD_LIBS_INIT})
|
||||||
set_target_properties(ndk_compat PROPERTIES PUBLIC_HEADER "${NDK_COMPAT_HDRS}")
|
set_target_properties(ndk_compat PROPERTIES PUBLIC_HEADER "${NDK_COMPAT_HDRS}")
|
||||||
|
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
#!/usr/bin/env bash
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
# SPDX-FileCopyrightText: 2017 Google Inc.
|
# SPDX-FileCopyrightText: 2017 Google LLC
|
||||||
# SPDX-License-Identifier: Apache-2.0
|
# SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
readonly SCRIPT_FOLDER=$(cd -P -- "$(dirname -- "$0")" && pwd -P)
|
readonly SCRIPT_FOLDER=$(cd -P -- "$(dirname -- "$0")" && pwd -P)
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
#!/usr/bin/env bash
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
# SPDX-FileCopyrightText: 2017 Google Inc.
|
# SPDX-FileCopyrightText: 2017 Google LLC
|
||||||
# SPDX-License-Identifier: Apache-2.0
|
# SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
source "$(dirname -- "$0")"/run_integration.sh
|
source "$(dirname -- "$0")"/run_integration.sh
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
// SPDX-FileCopyrightText: 2017 Google Inc.
|
// SPDX-FileCopyrightText: 2017 Google LLC
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
#include "cpuinfo_aarch64.h"
|
#include "cpuinfo_aarch64.h"
|
||||||
@ -6,79 +6,65 @@
|
|||||||
#include "internal/hwcaps.h"
|
#include "internal/hwcaps.h"
|
||||||
#include "internal/stack_line_reader.h"
|
#include "internal/stack_line_reader.h"
|
||||||
#include "internal/string_view.h"
|
#include "internal/string_view.h"
|
||||||
#include "internal/unix_features_aggregator.h"
|
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
|
|
||||||
DECLARE_SETTER_AND_GETTER(Aarch64Features, fp)
|
// Generation of feature's getters/setters functions and kGetters, kSetters,
|
||||||
DECLARE_SETTER_AND_GETTER(Aarch64Features, asimd)
|
// kCpuInfoFlags and kHardwareCapabilities global tables.
|
||||||
DECLARE_SETTER_AND_GETTER(Aarch64Features, evtstrm)
|
#define DEFINE_TABLE_FEATURES \
|
||||||
DECLARE_SETTER_AND_GETTER(Aarch64Features, aes)
|
FEATURE(AARCH64_FP, fp, "fp", AARCH64_HWCAP_FP, 0) \
|
||||||
DECLARE_SETTER_AND_GETTER(Aarch64Features, pmull)
|
FEATURE(AARCH64_ASIMD, asimd, "asimd", AARCH64_HWCAP_ASIMD, 0) \
|
||||||
DECLARE_SETTER_AND_GETTER(Aarch64Features, sha1)
|
FEATURE(AARCH64_EVTSTRM, evtstrm, "evtstrm", AARCH64_HWCAP_EVTSTRM, 0) \
|
||||||
DECLARE_SETTER_AND_GETTER(Aarch64Features, sha2)
|
FEATURE(AARCH64_AES, aes, "aes", AARCH64_HWCAP_AES, 0) \
|
||||||
DECLARE_SETTER_AND_GETTER(Aarch64Features, crc32)
|
FEATURE(AARCH64_PMULL, pmull, "pmull", AARCH64_HWCAP_PMULL, 0) \
|
||||||
DECLARE_SETTER_AND_GETTER(Aarch64Features, atomics)
|
FEATURE(AARCH64_SHA1, sha1, "sha1", AARCH64_HWCAP_SHA1, 0) \
|
||||||
DECLARE_SETTER_AND_GETTER(Aarch64Features, fphp)
|
FEATURE(AARCH64_SHA2, sha2, "sha2", AARCH64_HWCAP_SHA2, 0) \
|
||||||
DECLARE_SETTER_AND_GETTER(Aarch64Features, asimdhp)
|
FEATURE(AARCH64_CRC32, crc32, "crc32", AARCH64_HWCAP_CRC32, 0) \
|
||||||
DECLARE_SETTER_AND_GETTER(Aarch64Features, cpuid)
|
FEATURE(AARCH64_ATOMICS, atomics, "atomics", AARCH64_HWCAP_ATOMICS, 0) \
|
||||||
DECLARE_SETTER_AND_GETTER(Aarch64Features, asimdrdm)
|
FEATURE(AARCH64_FPHP, fphp, "fphp", AARCH64_HWCAP_FPHP, 0) \
|
||||||
DECLARE_SETTER_AND_GETTER(Aarch64Features, jscvt)
|
FEATURE(AARCH64_ASIMDHP, asimdhp, "asimdhp", AARCH64_HWCAP_ASIMDHP, 0) \
|
||||||
DECLARE_SETTER_AND_GETTER(Aarch64Features, fcma)
|
FEATURE(AARCH64_CPUID, cpuid, "cpuid", AARCH64_HWCAP_CPUID, 0) \
|
||||||
DECLARE_SETTER_AND_GETTER(Aarch64Features, lrcpc)
|
FEATURE(AARCH64_ASIMDRDM, asimdrdm, "asimdrdm", AARCH64_HWCAP_ASIMDRDM, 0) \
|
||||||
DECLARE_SETTER_AND_GETTER(Aarch64Features, dcpop)
|
FEATURE(AARCH64_JSCVT, jscvt, "jscvt", AARCH64_HWCAP_JSCVT, 0) \
|
||||||
DECLARE_SETTER_AND_GETTER(Aarch64Features, sha3)
|
FEATURE(AARCH64_FCMA, fcma, "fcma", AARCH64_HWCAP_FCMA, 0) \
|
||||||
DECLARE_SETTER_AND_GETTER(Aarch64Features, sm3)
|
FEATURE(AARCH64_LRCPC, lrcpc, "lrcpc", AARCH64_HWCAP_LRCPC, 0) \
|
||||||
DECLARE_SETTER_AND_GETTER(Aarch64Features, sm4)
|
FEATURE(AARCH64_DCPOP, dcpop, "dcpop", AARCH64_HWCAP_DCPOP, 0) \
|
||||||
DECLARE_SETTER_AND_GETTER(Aarch64Features, asimddp)
|
FEATURE(AARCH64_SHA3, sha3, "sha3", AARCH64_HWCAP_SHA3, 0) \
|
||||||
DECLARE_SETTER_AND_GETTER(Aarch64Features, sha512)
|
FEATURE(AARCH64_SM3, sm3, "sm3", AARCH64_HWCAP_SM3, 0) \
|
||||||
DECLARE_SETTER_AND_GETTER(Aarch64Features, sve)
|
FEATURE(AARCH64_SM4, sm4, "sm4", AARCH64_HWCAP_SM4, 0) \
|
||||||
DECLARE_SETTER_AND_GETTER(Aarch64Features, asimdfhm)
|
FEATURE(AARCH64_ASIMDDP, asimddp, "asimddp", AARCH64_HWCAP_ASIMDDP, 0) \
|
||||||
DECLARE_SETTER_AND_GETTER(Aarch64Features, dit)
|
FEATURE(AARCH64_SHA512, sha512, "sha512", AARCH64_HWCAP_SHA512, 0) \
|
||||||
DECLARE_SETTER_AND_GETTER(Aarch64Features, uscat)
|
FEATURE(AARCH64_SVE, sve, "sve", AARCH64_HWCAP_SVE, 0) \
|
||||||
DECLARE_SETTER_AND_GETTER(Aarch64Features, ilrcpc)
|
FEATURE(AARCH64_ASIMDFHM, asimdfhm, "asimdfhm", AARCH64_HWCAP_ASIMDFHM, 0) \
|
||||||
DECLARE_SETTER_AND_GETTER(Aarch64Features, flagm)
|
FEATURE(AARCH64_DIT, dit, "dit", AARCH64_HWCAP_DIT, 0) \
|
||||||
DECLARE_SETTER_AND_GETTER(Aarch64Features, ssbs)
|
FEATURE(AARCH64_USCAT, uscat, "uscat", AARCH64_HWCAP_USCAT, 0) \
|
||||||
DECLARE_SETTER_AND_GETTER(Aarch64Features, sb)
|
FEATURE(AARCH64_ILRCPC, ilrcpc, "ilrcpc", AARCH64_HWCAP_ILRCPC, 0) \
|
||||||
DECLARE_SETTER_AND_GETTER(Aarch64Features, paca)
|
FEATURE(AARCH64_FLAGM, flagm, "flagm", AARCH64_HWCAP_FLAGM, 0) \
|
||||||
DECLARE_SETTER_AND_GETTER(Aarch64Features, pacg)
|
FEATURE(AARCH64_SSBS, ssbs, "ssbs", AARCH64_HWCAP_SSBS, 0) \
|
||||||
|
FEATURE(AARCH64_SB, sb, "sb", AARCH64_HWCAP_SB, 0) \
|
||||||
static const CapabilityConfig kConfigs[] = {
|
FEATURE(AARCH64_PACA, paca, "paca", AARCH64_HWCAP_PACA, 0) \
|
||||||
[AARCH64_FP] = {{AARCH64_HWCAP_FP, 0}, "fp", &set_fp, &get_fp},
|
FEATURE(AARCH64_PACG, pacg, "pacg", AARCH64_HWCAP_PACG, 0) \
|
||||||
[AARCH64_ASIMD] = {{AARCH64_HWCAP_ASIMD, 0}, "asimd", &set_asimd, &get_asimd},
|
FEATURE(AARCH64_DCPODP, dcpodp, "dcpodp", 0, AARCH64_HWCAP2_DCPODP) \
|
||||||
[AARCH64_EVTSTRM] = {{AARCH64_HWCAP_EVTSTRM, 0}, "evtstrm", &set_evtstrm, &get_evtstrm},
|
FEATURE(AARCH64_SVE2, sve2, "sve2", 0, AARCH64_HWCAP2_SVE2) \
|
||||||
[AARCH64_AES] = {{AARCH64_HWCAP_AES, 0}, "aes", &set_aes, &get_aes},
|
FEATURE(AARCH64_SVEAES, sveaes, "sveaes", 0, AARCH64_HWCAP2_SVEAES) \
|
||||||
[AARCH64_PMULL] = {{AARCH64_HWCAP_PMULL, 0}, "pmull", &set_pmull, &get_pmull},
|
FEATURE(AARCH64_SVEPMULL, svepmull, "svepmull", 0, AARCH64_HWCAP2_SVEPMULL) \
|
||||||
[AARCH64_SHA1] = {{AARCH64_HWCAP_SHA1, 0}, "sha1", &set_sha1, &get_sha1},
|
FEATURE(AARCH64_SVEBITPERM, svebitperm, "svebitperm", 0, \
|
||||||
[AARCH64_SHA2] = {{AARCH64_HWCAP_SHA2, 0}, "sha2", &set_sha2, &get_sha2},
|
AARCH64_HWCAP2_SVEBITPERM) \
|
||||||
[AARCH64_CRC32] = {{AARCH64_HWCAP_CRC32, 0}, "crc32", &set_crc32, &get_crc32},
|
FEATURE(AARCH64_SVESHA3, svesha3, "svesha3", 0, AARCH64_HWCAP2_SVESHA3) \
|
||||||
[AARCH64_ATOMICS] = {{AARCH64_HWCAP_ATOMICS, 0}, "atomics", &set_atomics, &get_atomics},
|
FEATURE(AARCH64_SVESM4, svesm4, "svesm4", 0, AARCH64_HWCAP2_SVESM4) \
|
||||||
[AARCH64_FPHP] = {{AARCH64_HWCAP_FPHP, 0}, "fphp", &set_fphp, &get_fphp},
|
FEATURE(AARCH64_FLAGM2, flagm2, "flagm2", 0, AARCH64_HWCAP2_FLAGM2) \
|
||||||
[AARCH64_ASIMDHP] = {{AARCH64_HWCAP_ASIMDHP, 0}, "asimdhp", &set_asimdhp, &get_asimdhp},
|
FEATURE(AARCH64_FRINT, frint, "frint", 0, AARCH64_HWCAP2_FRINT) \
|
||||||
[AARCH64_CPUID] = {{AARCH64_HWCAP_CPUID, 0}, "cpuid", &set_cpuid, &get_cpuid},
|
FEATURE(AARCH64_SVEI8MM, svei8mm, "svei8mm", 0, AARCH64_HWCAP2_SVEI8MM) \
|
||||||
[AARCH64_ASIMDRDM] = {{AARCH64_HWCAP_ASIMDRDM, 0}, "asimdrdm", &set_asimdrdm, &get_asimdrdm},
|
FEATURE(AARCH64_SVEF32MM, svef32mm, "svef32mm", 0, AARCH64_HWCAP2_SVEF32MM) \
|
||||||
[AARCH64_JSCVT] = {{AARCH64_HWCAP_JSCVT, 0}, "jscvt", &set_jscvt, &get_jscvt},
|
FEATURE(AARCH64_SVEF64MM, svef64mm, "svef64mm", 0, AARCH64_HWCAP2_SVEF64MM) \
|
||||||
[AARCH64_FCMA] = {{AARCH64_HWCAP_FCMA, 0}, "fcma", &set_fcma, &get_fcma},
|
FEATURE(AARCH64_SVEBF16, svebf16, "svebf16", 0, AARCH64_HWCAP2_SVEBF16) \
|
||||||
[AARCH64_LRCPC] = {{AARCH64_HWCAP_LRCPC, 0}, "lrcpc", &set_lrcpc, &get_lrcpc},
|
FEATURE(AARCH64_I8MM, i8mm, "i8mm", 0, AARCH64_HWCAP2_I8MM) \
|
||||||
[AARCH64_DCPOP] = {{AARCH64_HWCAP_DCPOP, 0}, "dcpop", &set_dcpop, &get_dcpop},
|
FEATURE(AARCH64_BF16, bf16, "bf16", 0, AARCH64_HWCAP2_BF16) \
|
||||||
[AARCH64_SHA3] = {{AARCH64_HWCAP_SHA3, 0}, "sha3", &set_sha3, &get_sha3},
|
FEATURE(AARCH64_DGH, dgh, "dgh", 0, AARCH64_HWCAP2_DGH) \
|
||||||
[AARCH64_SM3] = {{AARCH64_HWCAP_SM3, 0}, "sm3", &set_sm3, &get_sm3},
|
FEATURE(AARCH64_RNG, rng, "rng", 0, AARCH64_HWCAP2_RNG) \
|
||||||
[AARCH64_SM4] = {{AARCH64_HWCAP_SM4, 0}, "sm4", &set_sm4, &get_sm4},
|
FEATURE(AARCH64_BTI, bti, "bti", 0, AARCH64_HWCAP2_BTI)
|
||||||
[AARCH64_ASIMDDP] = {{AARCH64_HWCAP_ASIMDDP, 0}, "asimddp", &set_asimddp, &get_asimddp},
|
#define DEFINE_TABLE_FEATURE_TYPE Aarch64Features
|
||||||
[AARCH64_SHA512] = {{AARCH64_HWCAP_SHA512, 0}, "sha512", &set_sha512, &get_sha512},
|
#include "define_tables.h"
|
||||||
[AARCH64_SVE] = {{AARCH64_HWCAP_SVE, 0}, "sve", &set_sve, &get_sve},
|
|
||||||
[AARCH64_ASIMDFHM] = {{AARCH64_HWCAP_ASIMDFHM, 0}, "asimdfhm", &set_asimdfhm, &get_asimdfhm},
|
|
||||||
[AARCH64_DIT] = {{AARCH64_HWCAP_DIT, 0}, "dit", &set_dit, &get_dit},
|
|
||||||
[AARCH64_USCAT] = {{AARCH64_HWCAP_USCAT, 0}, "uscat", &set_uscat, &get_uscat},
|
|
||||||
[AARCH64_ILRCPC] = {{AARCH64_HWCAP_ILRCPC, 0}, "ilrcpc", &set_ilrcpc, &get_ilrcpc},
|
|
||||||
[AARCH64_FLAGM] = {{AARCH64_HWCAP_FLAGM, 0}, "flagm", &set_flagm, &get_flagm},
|
|
||||||
[AARCH64_SSBS] = {{AARCH64_HWCAP_SSBS, 0}, "ssbs", &set_ssbs, &get_ssbs},
|
|
||||||
[AARCH64_SB] = {{AARCH64_HWCAP_SB, 0}, "sb", &set_sb, &get_sb},
|
|
||||||
[AARCH64_PACA] = {{AARCH64_HWCAP_PACA, 0}, "paca", &set_paca, &get_paca},
|
|
||||||
[AARCH64_PACG] = {{AARCH64_HWCAP_PACG, 0}, "pacg", &set_pacg, &get_pacg},
|
|
||||||
};
|
|
||||||
|
|
||||||
static const size_t kConfigsSize = sizeof(kConfigs) / sizeof(CapabilityConfig);
|
|
||||||
|
|
||||||
static bool HandleAarch64Line(const LineResult result,
|
static bool HandleAarch64Line(const LineResult result,
|
||||||
Aarch64Info* const info)
|
Aarch64Info* const info)
|
||||||
@ -89,7 +75,11 @@ static bool HandleAarch64Line(const LineResult result,
|
|||||||
{
|
{
|
||||||
if (CpuFeatures_StringView_IsEquals(key, str("Features")))
|
if (CpuFeatures_StringView_IsEquals(key, str("Features")))
|
||||||
{
|
{
|
||||||
CpuFeatures_SetFromFlags(kConfigsSize, kConfigs, value, &info->features);
|
for (size_t i = 0; i < AARCH64_LAST_; ++i)
|
||||||
|
{
|
||||||
|
kSetters[i](&info->features,
|
||||||
|
CpuFeatures_StringView_HasWord(value, kCpuInfoFlags[i]));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else if (CpuFeatures_StringView_IsEquals(key, str("CPU implementer")))
|
else if (CpuFeatures_StringView_IsEquals(key, str("CPU implementer")))
|
||||||
{
|
{
|
||||||
@ -133,17 +123,20 @@ static const Aarch64Info kEmptyAarch64Info;
|
|||||||
|
|
||||||
Aarch64Info GetAarch64Info(void)
|
Aarch64Info GetAarch64Info(void)
|
||||||
{
|
{
|
||||||
assert(kConfigsSize == AARCH64_LAST_);
|
|
||||||
|
|
||||||
// capabilities are fetched from both getauxval and /proc/cpuinfo so we can
|
// capabilities are fetched from both getauxval and /proc/cpuinfo so we can
|
||||||
// have some information if the executable is sandboxed (aka no access to
|
// have some information if the executable is sandboxed (aka no access to
|
||||||
// /proc/cpuinfo).
|
// /proc/cpuinfo).
|
||||||
Aarch64Info info = kEmptyAarch64Info;
|
Aarch64Info info = kEmptyAarch64Info;
|
||||||
|
|
||||||
FillProcCpuInfoData(&info);
|
FillProcCpuInfoData(&info);
|
||||||
CpuFeatures_OverrideFromHwCaps(kConfigsSize, kConfigs,
|
const HardwareCapabilities hwcaps = CpuFeatures_GetHardwareCapabilities();
|
||||||
CpuFeatures_GetHardwareCapabilities(),
|
for (size_t i = 0; i < AARCH64_LAST_; ++i)
|
||||||
&info.features);
|
{
|
||||||
|
if (CpuFeatures_IsHwCapsSet(kHardwareCapabilities[i], hwcaps))
|
||||||
|
{
|
||||||
|
kSetters[i](&info.features, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return info;
|
return info;
|
||||||
}
|
}
|
||||||
@ -154,14 +147,12 @@ Aarch64Info GetAarch64Info(void)
|
|||||||
int GetAarch64FeaturesEnumValue(const Aarch64Features* features,
|
int GetAarch64FeaturesEnumValue(const Aarch64Features* features,
|
||||||
Aarch64FeaturesEnum value)
|
Aarch64FeaturesEnum value)
|
||||||
{
|
{
|
||||||
if (value >= kConfigsSize)
|
if (value >= AARCH64_LAST_) return false;
|
||||||
return false;
|
return kGetters[value](features);
|
||||||
return kConfigs[value].get_bit((Aarch64Features*)features);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const char* GetAarch64FeaturesEnumName(Aarch64FeaturesEnum value)
|
const char* GetAarch64FeaturesEnumName(Aarch64FeaturesEnum value)
|
||||||
{
|
{
|
||||||
if (value >= kConfigsSize)
|
if (value >= AARCH64_LAST_) return "unknown feature";
|
||||||
return "unknown feature";
|
return kCpuInfoFlags[value];
|
||||||
return kConfigs[value].proc_cpuinfo_flag;
|
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
// SPDX-FileCopyrightText: 2017 Google Inc.
|
// SPDX-FileCopyrightText: 2017 Google LLC
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
#include "cpuinfo_arm.h"
|
#include "cpuinfo_arm.h"
|
||||||
@ -7,69 +7,41 @@
|
|||||||
#include "internal/hwcaps.h"
|
#include "internal/hwcaps.h"
|
||||||
#include "internal/stack_line_reader.h"
|
#include "internal/stack_line_reader.h"
|
||||||
#include "internal/string_view.h"
|
#include "internal/string_view.h"
|
||||||
#include "internal/unix_features_aggregator.h"
|
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
|
|
||||||
DECLARE_SETTER_AND_GETTER(ArmFeatures, swp)
|
// Generation of feature's getters/setters functions and kGetters, kSetters,
|
||||||
DECLARE_SETTER_AND_GETTER(ArmFeatures, half)
|
// kCpuInfoFlags and kHardwareCapabilities global tables.
|
||||||
DECLARE_SETTER_AND_GETTER(ArmFeatures, thumb)
|
#define DEFINE_TABLE_FEATURES \
|
||||||
DECLARE_SETTER_AND_GETTER(ArmFeatures, _26bit)
|
FEATURE(ARM_SWP, swp, "swp", ARM_HWCAP_SWP, 0) \
|
||||||
DECLARE_SETTER_AND_GETTER(ArmFeatures, fastmult)
|
FEATURE(ARM_HALF, half, "half", ARM_HWCAP_HALF, 0) \
|
||||||
DECLARE_SETTER_AND_GETTER(ArmFeatures, fpa)
|
FEATURE(ARM_THUMB, thumb, "thumb", ARM_HWCAP_THUMB, 0) \
|
||||||
DECLARE_SETTER_AND_GETTER(ArmFeatures, vfp)
|
FEATURE(ARM_26BIT, _26bit, "26bit", ARM_HWCAP_26BIT, 0) \
|
||||||
DECLARE_SETTER_AND_GETTER(ArmFeatures, edsp)
|
FEATURE(ARM_FASTMULT, fastmult, "fastmult", ARM_HWCAP_FAST_MULT, 0) \
|
||||||
DECLARE_SETTER_AND_GETTER(ArmFeatures, java)
|
FEATURE(ARM_FPA, fpa, "fpa", ARM_HWCAP_FPA, 0) \
|
||||||
DECLARE_SETTER_AND_GETTER(ArmFeatures, iwmmxt)
|
FEATURE(ARM_VFP, vfp, "vfp", ARM_HWCAP_VFP, 0) \
|
||||||
DECLARE_SETTER_AND_GETTER(ArmFeatures, crunch)
|
FEATURE(ARM_EDSP, edsp, "edsp", ARM_HWCAP_EDSP, 0) \
|
||||||
DECLARE_SETTER_AND_GETTER(ArmFeatures, thumbee)
|
FEATURE(ARM_JAVA, java, "java", ARM_HWCAP_JAVA, 0) \
|
||||||
DECLARE_SETTER_AND_GETTER(ArmFeatures, neon)
|
FEATURE(ARM_IWMMXT, iwmmxt, "iwmmxt", ARM_HWCAP_IWMMXT, 0) \
|
||||||
DECLARE_SETTER_AND_GETTER(ArmFeatures, vfpv3)
|
FEATURE(ARM_CRUNCH, crunch, "crunch", ARM_HWCAP_CRUNCH, 0) \
|
||||||
DECLARE_SETTER_AND_GETTER(ArmFeatures, vfpv3d16)
|
FEATURE(ARM_THUMBEE, thumbee, "thumbee", ARM_HWCAP_THUMBEE, 0) \
|
||||||
DECLARE_SETTER_AND_GETTER(ArmFeatures, tls)
|
FEATURE(ARM_NEON, neon, "neon", ARM_HWCAP_NEON, 0) \
|
||||||
DECLARE_SETTER_AND_GETTER(ArmFeatures, vfpv4)
|
FEATURE(ARM_VFPV3, vfpv3, "vfpv3", ARM_HWCAP_VFPV3, 0) \
|
||||||
DECLARE_SETTER_AND_GETTER(ArmFeatures, idiva)
|
FEATURE(ARM_VFPV3D16, vfpv3d16, "vfpv3d16", ARM_HWCAP_VFPV3D16, 0) \
|
||||||
DECLARE_SETTER_AND_GETTER(ArmFeatures, idivt)
|
FEATURE(ARM_TLS, tls, "tls", ARM_HWCAP_TLS, 0) \
|
||||||
DECLARE_SETTER_AND_GETTER(ArmFeatures, vfpd32)
|
FEATURE(ARM_VFPV4, vfpv4, "vfpv4", ARM_HWCAP_VFPV4, 0) \
|
||||||
DECLARE_SETTER_AND_GETTER(ArmFeatures, lpae)
|
FEATURE(ARM_IDIVA, idiva, "idiva", ARM_HWCAP_IDIVA, 0) \
|
||||||
DECLARE_SETTER_AND_GETTER(ArmFeatures, evtstrm)
|
FEATURE(ARM_IDIVT, idivt, "idivt", ARM_HWCAP_IDIVT, 0) \
|
||||||
DECLARE_SETTER_AND_GETTER(ArmFeatures, aes)
|
FEATURE(ARM_VFPD32, vfpd32, "vfpd32", ARM_HWCAP_VFPD32, 0) \
|
||||||
DECLARE_SETTER_AND_GETTER(ArmFeatures, pmull)
|
FEATURE(ARM_LPAE, lpae, "lpae", ARM_HWCAP_LPAE, 0) \
|
||||||
DECLARE_SETTER_AND_GETTER(ArmFeatures, sha1)
|
FEATURE(ARM_EVTSTRM, evtstrm, "evtstrm", ARM_HWCAP_EVTSTRM, 0) \
|
||||||
DECLARE_SETTER_AND_GETTER(ArmFeatures, sha2)
|
FEATURE(ARM_AES, aes, "aes", 0, ARM_HWCAP2_AES) \
|
||||||
DECLARE_SETTER_AND_GETTER(ArmFeatures, crc32)
|
FEATURE(ARM_PMULL, pmull, "pmull", 0, ARM_HWCAP2_PMULL) \
|
||||||
|
FEATURE(ARM_SHA1, sha1, "sha1", 0, ARM_HWCAP2_SHA1) \
|
||||||
static const CapabilityConfig kConfigs[] = {
|
FEATURE(ARM_SHA2, sha2, "sha2", 0, ARM_HWCAP2_SHA2) \
|
||||||
[ARM_SWP] = {{ARM_HWCAP_SWP, 0}, "swp", &set_swp, &get_swp}, //
|
FEATURE(ARM_CRC32, crc32, "crc32", 0, ARM_HWCAP2_CRC32)
|
||||||
[ARM_HALF] = {{ARM_HWCAP_HALF, 0}, "half", &set_half, &get_half}, //
|
#define DEFINE_TABLE_FEATURE_TYPE ArmFeatures
|
||||||
[ARM_THUMB] = {{ARM_HWCAP_THUMB, 0}, "thumb", &set_thumb, &get_thumb}, //
|
#include "define_tables.h"
|
||||||
[ARM_26BIT] = {{ARM_HWCAP_26BIT, 0}, "26bit", &set__26bit, &get__26bit}, //
|
|
||||||
[ARM_FASTMULT] = {{ARM_HWCAP_FAST_MULT, 0}, "fastmult", &set_fastmult, &get_fastmult}, //
|
|
||||||
[ARM_FPA] = {{ARM_HWCAP_FPA, 0}, "fpa", &set_fpa, &get_fpa}, //
|
|
||||||
[ARM_VFP] = {{ARM_HWCAP_VFP, 0}, "vfp", &set_vfp, &get_vfp}, //
|
|
||||||
[ARM_EDSP] = {{ARM_HWCAP_EDSP, 0}, "edsp", &set_edsp, &get_edsp}, //
|
|
||||||
[ARM_JAVA] = {{ARM_HWCAP_JAVA, 0}, "java", &set_java, &get_java}, //
|
|
||||||
[ARM_IWMMXT] = {{ARM_HWCAP_IWMMXT, 0}, "iwmmxt", &set_iwmmxt, &get_iwmmxt}, //
|
|
||||||
[ARM_CRUNCH] = {{ARM_HWCAP_CRUNCH, 0}, "crunch", &set_crunch, &get_crunch}, //
|
|
||||||
[ARM_THUMBEE] = {{ARM_HWCAP_THUMBEE, 0}, "thumbee", &set_thumbee, &get_thumbee}, //
|
|
||||||
[ARM_NEON] = {{ARM_HWCAP_NEON, 0}, "neon", &set_neon, &get_neon}, //
|
|
||||||
[ARM_VFPV3] = {{ARM_HWCAP_VFPV3, 0}, "vfpv3", &set_vfpv3, &get_vfpv3}, //
|
|
||||||
[ARM_VFPV3D16] = {{ARM_HWCAP_VFPV3D16, 0}, "vfpv3d16", &set_vfpv3d16, &get_vfpv3d16}, //
|
|
||||||
[ARM_TLS] = {{ARM_HWCAP_TLS, 0}, "tls", &set_tls, &get_tls}, //
|
|
||||||
[ARM_VFPV4] = {{ARM_HWCAP_VFPV4, 0}, "vfpv4", &set_vfpv4, &get_vfpv4}, //
|
|
||||||
[ARM_IDIVA] = {{ARM_HWCAP_IDIVA, 0}, "idiva", &set_idiva, &get_idiva}, //
|
|
||||||
[ARM_IDIVT] = {{ARM_HWCAP_IDIVT, 0}, "idivt", &set_idivt, &get_idivt}, //
|
|
||||||
[ARM_VFPD32] = {{ARM_HWCAP_VFPD32, 0}, "vfpd32", &set_vfpd32, &get_vfpd32}, //
|
|
||||||
[ARM_LPAE] = {{ARM_HWCAP_LPAE, 0}, "lpae", &set_lpae, &get_lpae}, //
|
|
||||||
[ARM_EVTSTRM] = {{ARM_HWCAP_EVTSTRM, 0}, "evtstrm", &set_evtstrm, &get_evtstrm}, //
|
|
||||||
[ARM_AES] = {{0, ARM_HWCAP2_AES}, "aes", &set_aes, &get_aes}, //
|
|
||||||
[ARM_PMULL] = {{0, ARM_HWCAP2_PMULL}, "pmull", &set_pmull, &get_pmull}, //
|
|
||||||
[ARM_SHA1] = {{0, ARM_HWCAP2_SHA1}, "sha1", &set_sha1, &get_sha1}, //
|
|
||||||
[ARM_SHA2] = {{0, ARM_HWCAP2_SHA2}, "sha2", &set_sha2, &get_sha2}, //
|
|
||||||
[ARM_CRC32] = {{0, ARM_HWCAP2_CRC32}, "crc32", &set_crc32, &get_crc32}, //
|
|
||||||
};
|
|
||||||
|
|
||||||
static const size_t kConfigsSize = sizeof(kConfigs) / sizeof(CapabilityConfig);
|
|
||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
@ -97,7 +69,11 @@ static bool HandleArmLine(const LineResult result, ArmInfo* const info,
|
|||||||
{
|
{
|
||||||
if (CpuFeatures_StringView_IsEquals(key, str("Features")))
|
if (CpuFeatures_StringView_IsEquals(key, str("Features")))
|
||||||
{
|
{
|
||||||
CpuFeatures_SetFromFlags(kConfigsSize, kConfigs, value, &info->features);
|
for (size_t i = 0; i < ARM_LAST_; ++i)
|
||||||
|
{
|
||||||
|
kSetters[i](&info->features,
|
||||||
|
CpuFeatures_StringView_HasWord(value, kCpuInfoFlags[i]));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else if (CpuFeatures_StringView_IsEquals(key, str("CPU implementer")))
|
else if (CpuFeatures_StringView_IsEquals(key, str("CPU implementer")))
|
||||||
{
|
{
|
||||||
@ -123,7 +99,8 @@ static bool HandleArmLine(const LineResult result, ArmInfo* const info,
|
|||||||
CpuFeatures_StringView_KeepFront(value, IndexOfNonDigit(value));
|
CpuFeatures_StringView_KeepFront(value, IndexOfNonDigit(value));
|
||||||
info->architecture = CpuFeatures_StringView_ParsePositiveNumber(digits);
|
info->architecture = CpuFeatures_StringView_ParsePositiveNumber(digits);
|
||||||
}
|
}
|
||||||
else if (CpuFeatures_StringView_IsEquals(key, str("Processor")) || CpuFeatures_StringView_IsEquals(key, str("model name")))
|
else if (CpuFeatures_StringView_IsEquals(key, str("Processor")) ||
|
||||||
|
CpuFeatures_StringView_IsEquals(key, str("model name")))
|
||||||
{
|
{
|
||||||
// Android reports this in a non-Linux standard "Processor" but sometimes
|
// Android reports this in a non-Linux standard "Processor" but sometimes
|
||||||
// also in "model name", Linux reports it only in "model name"
|
// also in "model name", Linux reports it only in "model name"
|
||||||
@ -226,9 +203,14 @@ ArmInfo GetArmInfo(void)
|
|||||||
ProcCpuInfoData proc_cpu_info_data = kEmptyProcCpuInfoData;
|
ProcCpuInfoData proc_cpu_info_data = kEmptyProcCpuInfoData;
|
||||||
|
|
||||||
FillProcCpuInfoData(&info, &proc_cpu_info_data);
|
FillProcCpuInfoData(&info, &proc_cpu_info_data);
|
||||||
CpuFeatures_OverrideFromHwCaps(kConfigsSize, kConfigs,
|
const HardwareCapabilities hwcaps = CpuFeatures_GetHardwareCapabilities();
|
||||||
CpuFeatures_GetHardwareCapabilities(),
|
for (size_t i = 0; i < ARM_LAST_; ++i)
|
||||||
&info.features);
|
{
|
||||||
|
if (CpuFeatures_IsHwCapsSet(kHardwareCapabilities[i], hwcaps))
|
||||||
|
{
|
||||||
|
kSetters[i](&info.features, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
FixErrors(&info, &proc_cpu_info_data);
|
FixErrors(&info, &proc_cpu_info_data);
|
||||||
|
|
||||||
@ -241,14 +223,12 @@ ArmInfo GetArmInfo(void)
|
|||||||
int GetArmFeaturesEnumValue(const ArmFeatures* features,
|
int GetArmFeaturesEnumValue(const ArmFeatures* features,
|
||||||
ArmFeaturesEnum value)
|
ArmFeaturesEnum value)
|
||||||
{
|
{
|
||||||
if (value >= kConfigsSize)
|
if (value >= ARM_LAST_) return false;
|
||||||
return false;
|
return kGetters[value](features);
|
||||||
return kConfigs[value].get_bit((ArmFeatures*)features);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const char* GetArmFeaturesEnumName(ArmFeaturesEnum value)
|
const char* GetArmFeaturesEnumName(ArmFeaturesEnum value)
|
||||||
{
|
{
|
||||||
if (value >= kConfigsSize)
|
if (value >= ARM_LAST_) return "unknown feature";
|
||||||
return "unknown feature";
|
return kCpuInfoFlags[value];
|
||||||
return kConfigs[value].proc_cpuinfo_flag;
|
|
||||||
}
|
}
|
||||||
|
@ -1,23 +1,21 @@
|
|||||||
// SPDX-FileCopyrightText: 2017 Google Inc.
|
// SPDX-FileCopyrightText: 2017 Google LLC
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
#include "cpuinfo_mips.h"
|
#include "cpuinfo_mips.h"
|
||||||
#include "internal/filesystem.h"
|
#include "internal/filesystem.h"
|
||||||
|
#include "internal/hwcaps.h"
|
||||||
#include "internal/stack_line_reader.h"
|
#include "internal/stack_line_reader.h"
|
||||||
#include "internal/string_view.h"
|
#include "internal/string_view.h"
|
||||||
#include "internal/unix_features_aggregator.h"
|
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
|
|
||||||
DECLARE_SETTER_AND_GETTER(MipsFeatures, msa)
|
// Generation of feature's getters/setters functions and kGetters, kSetters,
|
||||||
DECLARE_SETTER_AND_GETTER(MipsFeatures, eva)
|
// kCpuInfoFlags and kHardwareCapabilities global tables.
|
||||||
DECLARE_SETTER_AND_GETTER(MipsFeatures, r6)
|
#define DEFINE_TABLE_FEATURES \
|
||||||
|
FEATURE(MIPS_MSA, msa, "msa", MIPS_HWCAP_MSA, 0) \
|
||||||
static const CapabilityConfig kConfigs[] = {
|
FEATURE(MIPS_EVA, eva, "eva", 0, 0) \
|
||||||
[MIPS_MSA] = {{MIPS_HWCAP_MSA, 0}, "msa", &set_msa, &get_msa}, //
|
FEATURE(MIPS_R6, r6, "r6", MIPS_HWCAP_R6, 0)
|
||||||
[MIPS_EVA] = {{0, 0}, "eva", &set_eva, &get_eva}, //
|
#define DEFINE_TABLE_FEATURE_TYPE MipsFeatures
|
||||||
[MIPS_R6] = {{MIPS_HWCAP_R6, 0}, "r6", &set_r6, &get_r6}, //
|
#include "define_tables.h"
|
||||||
};
|
|
||||||
static const size_t kConfigsSize = sizeof(kConfigs) / sizeof(CapabilityConfig);
|
|
||||||
|
|
||||||
static bool HandleMipsLine(const LineResult result,
|
static bool HandleMipsLine(const LineResult result,
|
||||||
MipsFeatures* const features)
|
MipsFeatures* const features)
|
||||||
@ -28,7 +26,11 @@ static bool HandleMipsLine(const LineResult result,
|
|||||||
{
|
{
|
||||||
if (CpuFeatures_StringView_IsEquals(key, str("ASEs implemented")))
|
if (CpuFeatures_StringView_IsEquals(key, str("ASEs implemented")))
|
||||||
{
|
{
|
||||||
CpuFeatures_SetFromFlags(kConfigsSize, kConfigs, value, features);
|
for (size_t i = 0; i < MIPS_LAST_; ++i)
|
||||||
|
{
|
||||||
|
kSetters[i](features,
|
||||||
|
CpuFeatures_StringView_HasWord(value, kCpuInfoFlags[i]));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return !result.eof;
|
return !result.eof;
|
||||||
@ -56,17 +58,20 @@ static const MipsInfo kEmptyMipsInfo;
|
|||||||
|
|
||||||
MipsInfo GetMipsInfo(void)
|
MipsInfo GetMipsInfo(void)
|
||||||
{
|
{
|
||||||
assert(kConfigsSize == MIPS_LAST_);
|
|
||||||
|
|
||||||
// capabilities are fetched from both getauxval and /proc/cpuinfo so we can
|
// capabilities are fetched from both getauxval and /proc/cpuinfo so we can
|
||||||
// have some information if the executable is sandboxed (aka no access to
|
// have some information if the executable is sandboxed (aka no access to
|
||||||
// /proc/cpuinfo).
|
// /proc/cpuinfo).
|
||||||
MipsInfo info = kEmptyMipsInfo;
|
MipsInfo info = kEmptyMipsInfo;
|
||||||
|
|
||||||
FillProcCpuInfoData(&info.features);
|
FillProcCpuInfoData(&info.features);
|
||||||
CpuFeatures_OverrideFromHwCaps(kConfigsSize, kConfigs,
|
const HardwareCapabilities hwcaps = CpuFeatures_GetHardwareCapabilities();
|
||||||
CpuFeatures_GetHardwareCapabilities(),
|
for (size_t i = 0; i < MIPS_LAST_; ++i)
|
||||||
&info.features);
|
{
|
||||||
|
if (CpuFeatures_IsHwCapsSet(kHardwareCapabilities[i], hwcaps))
|
||||||
|
{
|
||||||
|
kSetters[i](&info.features, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
return info;
|
return info;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -76,14 +81,12 @@ MipsInfo GetMipsInfo(void)
|
|||||||
int GetMipsFeaturesEnumValue(const MipsFeatures* features,
|
int GetMipsFeaturesEnumValue(const MipsFeatures* features,
|
||||||
MipsFeaturesEnum value)
|
MipsFeaturesEnum value)
|
||||||
{
|
{
|
||||||
if (value >= kConfigsSize)
|
if (value >= MIPS_LAST_) return false;
|
||||||
return false;
|
return kGetters[value](features);
|
||||||
return kConfigs[value].get_bit((MipsFeatures*)features);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const char* GetMipsFeaturesEnumName(MipsFeaturesEnum value)
|
const char* GetMipsFeaturesEnumName(MipsFeaturesEnum value)
|
||||||
{
|
{
|
||||||
if (value >= kConfigsSize)
|
if (value >= MIPS_LAST_) return "unknown feature";
|
||||||
return "unknown feature";
|
return kCpuInfoFlags[value];
|
||||||
return kConfigs[value].proc_cpuinfo_flag;
|
|
||||||
}
|
}
|
||||||
|
@ -6,99 +6,62 @@
|
|||||||
#include "internal/filesystem.h"
|
#include "internal/filesystem.h"
|
||||||
#include "internal/stack_line_reader.h"
|
#include "internal/stack_line_reader.h"
|
||||||
#include "internal/string_view.h"
|
#include "internal/string_view.h"
|
||||||
#include "internal/unix_features_aggregator.h"
|
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
DECLARE_SETTER_AND_GETTER(PPCFeatures, ppc32)
|
// Generation of feature's getters/setters functions and kGetters, kSetters,
|
||||||
DECLARE_SETTER_AND_GETTER(PPCFeatures, ppc64)
|
// kCpuInfoFlags and kHardwareCapabilities global tables.
|
||||||
DECLARE_SETTER_AND_GETTER(PPCFeatures, ppc601)
|
#define DEFINE_TABLE_FEATURES \
|
||||||
DECLARE_SETTER_AND_GETTER(PPCFeatures, altivec)
|
FEATURE(PPC_32, ppc32, "ppc32", PPC_FEATURE_32, 0) \
|
||||||
DECLARE_SETTER_AND_GETTER(PPCFeatures, fpu)
|
FEATURE(PPC_64, ppc64, "ppc64", PPC_FEATURE_64, 0) \
|
||||||
DECLARE_SETTER_AND_GETTER(PPCFeatures, mmu)
|
FEATURE(PPC_601_INSTR, ppc601, "ppc601", PPC_FEATURE_601_INSTR, 0) \
|
||||||
DECLARE_SETTER_AND_GETTER(PPCFeatures, mac_4xx)
|
FEATURE(PPC_HAS_ALTIVEC, altivec, "altivec", PPC_FEATURE_HAS_ALTIVEC, 0) \
|
||||||
DECLARE_SETTER_AND_GETTER(PPCFeatures, unifiedcache)
|
FEATURE(PPC_HAS_FPU, fpu, "fpu", PPC_FEATURE_HAS_FPU, 0) \
|
||||||
DECLARE_SETTER_AND_GETTER(PPCFeatures, spe)
|
FEATURE(PPC_HAS_MMU, mmu, "mmu", PPC_FEATURE_HAS_MMU, 0) \
|
||||||
DECLARE_SETTER_AND_GETTER(PPCFeatures, efpsingle)
|
FEATURE(PPC_HAS_4xxMAC, mac_4xx, "4xxmac", PPC_FEATURE_HAS_4xxMAC, 0) \
|
||||||
DECLARE_SETTER_AND_GETTER(PPCFeatures, efpdouble)
|
FEATURE(PPC_UNIFIED_CACHE, unifiedcache, "ucache", \
|
||||||
DECLARE_SETTER_AND_GETTER(PPCFeatures, no_tb)
|
PPC_FEATURE_UNIFIED_CACHE, 0) \
|
||||||
DECLARE_SETTER_AND_GETTER(PPCFeatures, power4)
|
FEATURE(PPC_HAS_SPE, spe, "spe", PPC_FEATURE_HAS_SPE, 0) \
|
||||||
DECLARE_SETTER_AND_GETTER(PPCFeatures, power5)
|
FEATURE(PPC_HAS_EFP_SINGLE, efpsingle, "efpsingle", \
|
||||||
DECLARE_SETTER_AND_GETTER(PPCFeatures, power5plus)
|
PPC_FEATURE_HAS_EFP_SINGLE, 0) \
|
||||||
DECLARE_SETTER_AND_GETTER(PPCFeatures, cell)
|
FEATURE(PPC_HAS_EFP_DOUBLE, efpdouble, "efpdouble", \
|
||||||
DECLARE_SETTER_AND_GETTER(PPCFeatures, booke)
|
PPC_FEATURE_HAS_EFP_DOUBLE, 0) \
|
||||||
DECLARE_SETTER_AND_GETTER(PPCFeatures, smt)
|
FEATURE(PPC_NO_TB, no_tb, "notb", PPC_FEATURE_NO_TB, 0) \
|
||||||
DECLARE_SETTER_AND_GETTER(PPCFeatures, icachesnoop)
|
FEATURE(PPC_POWER4, power4, "power4", PPC_FEATURE_POWER4, 0) \
|
||||||
DECLARE_SETTER_AND_GETTER(PPCFeatures, arch205)
|
FEATURE(PPC_POWER5, power5, "power5", PPC_FEATURE_POWER5, 0) \
|
||||||
DECLARE_SETTER_AND_GETTER(PPCFeatures, pa6t)
|
FEATURE(PPC_POWER5_PLUS, power5plus, "power5+", PPC_FEATURE_POWER5_PLUS, 0) \
|
||||||
DECLARE_SETTER_AND_GETTER(PPCFeatures, dfp)
|
FEATURE(PPC_CELL, cell, "cellbe", PPC_FEATURE_CELL, 0) \
|
||||||
DECLARE_SETTER_AND_GETTER(PPCFeatures, power6ext)
|
FEATURE(PPC_BOOKE, booke, "booke", PPC_FEATURE_BOOKE, 0) \
|
||||||
DECLARE_SETTER_AND_GETTER(PPCFeatures, arch206)
|
FEATURE(PPC_SMT, smt, "smt", PPC_FEATURE_SMT, 0) \
|
||||||
DECLARE_SETTER_AND_GETTER(PPCFeatures, vsx)
|
FEATURE(PPC_ICACHE_SNOOP, icachesnoop, "ic_snoop", PPC_FEATURE_ICACHE_SNOOP, \
|
||||||
DECLARE_SETTER_AND_GETTER(PPCFeatures, pseries_perfmon_compat)
|
0) \
|
||||||
DECLARE_SETTER_AND_GETTER(PPCFeatures, truele)
|
FEATURE(PPC_ARCH_2_05, arch205, "arch_2_05", PPC_FEATURE_ARCH_2_05, 0) \
|
||||||
DECLARE_SETTER_AND_GETTER(PPCFeatures, ppcle)
|
FEATURE(PPC_PA6T, pa6t, "pa6t", PPC_FEATURE_PA6T, 0) \
|
||||||
DECLARE_SETTER_AND_GETTER(PPCFeatures, arch207)
|
FEATURE(PPC_HAS_DFP, dfp, "dfp", PPC_FEATURE_HAS_DFP, 0) \
|
||||||
DECLARE_SETTER_AND_GETTER(PPCFeatures, htm)
|
FEATURE(PPC_POWER6_EXT, power6ext, "power6x", PPC_FEATURE_POWER6_EXT, 0) \
|
||||||
DECLARE_SETTER_AND_GETTER(PPCFeatures, dscr)
|
FEATURE(PPC_ARCH_2_06, arch206, "arch_2_06", PPC_FEATURE_ARCH_2_06, 0) \
|
||||||
DECLARE_SETTER_AND_GETTER(PPCFeatures, ebb)
|
FEATURE(PPC_HAS_VSX, vsx, "vsx", PPC_FEATURE_HAS_VSX, 0) \
|
||||||
DECLARE_SETTER_AND_GETTER(PPCFeatures, isel)
|
FEATURE(PPC_PSERIES_PERFMON_COMPAT, pseries_perfmon_compat, "archpmu", \
|
||||||
DECLARE_SETTER_AND_GETTER(PPCFeatures, tar)
|
PPC_FEATURE_PSERIES_PERFMON_COMPAT, 0) \
|
||||||
DECLARE_SETTER_AND_GETTER(PPCFeatures, vcrypto)
|
FEATURE(PPC_TRUE_LE, truele, "true_le", PPC_FEATURE_TRUE_LE, 0) \
|
||||||
DECLARE_SETTER_AND_GETTER(PPCFeatures, htm_nosc)
|
FEATURE(PPC_PPC_LE, ppcle, "ppcle", PPC_FEATURE_PPC_LE, 0) \
|
||||||
DECLARE_SETTER_AND_GETTER(PPCFeatures, arch300)
|
FEATURE(PPC_ARCH_2_07, arch207, "arch_2_07", 0, PPC_FEATURE2_ARCH_2_07) \
|
||||||
DECLARE_SETTER_AND_GETTER(PPCFeatures, ieee128)
|
FEATURE(PPC_HTM, htm, "htm", 0, PPC_FEATURE2_HTM) \
|
||||||
DECLARE_SETTER_AND_GETTER(PPCFeatures, darn)
|
FEATURE(PPC_DSCR, dscr, "dscr", 0, PPC_FEATURE2_DSCR) \
|
||||||
DECLARE_SETTER_AND_GETTER(PPCFeatures, scv)
|
FEATURE(PPC_EBB, ebb, "ebb", 0, PPC_FEATURE2_EBB) \
|
||||||
DECLARE_SETTER_AND_GETTER(PPCFeatures, htm_no_suspend)
|
FEATURE(PPC_ISEL, isel, "isel", 0, PPC_FEATURE2_ISEL) \
|
||||||
|
FEATURE(PPC_TAR, tar, "tar", 0, PPC_FEATURE2_TAR) \
|
||||||
static const CapabilityConfig kConfigs[] = {
|
FEATURE(PPC_VEC_CRYPTO, vcrypto, "vcrypto", 0, PPC_FEATURE2_VEC_CRYPTO) \
|
||||||
[PPC_32] = {{PPC_FEATURE_32, 0}, "ppc32", &set_ppc32, &get_ppc32},
|
FEATURE(PPC_HTM_NOSC, htm_nosc, "htm-nosc", 0, PPC_FEATURE2_HTM_NOSC) \
|
||||||
[PPC_64] = {{PPC_FEATURE_64, 0}, "ppc64", &set_ppc64, &get_ppc64},
|
FEATURE(PPC_ARCH_3_00, arch300, "arch_3_00", 0, PPC_FEATURE2_ARCH_3_00) \
|
||||||
[PPC_601_INSTR] = {{PPC_FEATURE_601_INSTR, 0}, "ppc601", &set_ppc601, &get_ppc601},
|
FEATURE(PPC_HAS_IEEE128, ieee128, "ieee128", 0, PPC_FEATURE2_HAS_IEEE128) \
|
||||||
[PPC_HAS_ALTIVEC] = {{PPC_FEATURE_HAS_ALTIVEC, 0}, "altivec", &set_altivec, &get_altivec},
|
FEATURE(PPC_DARN, darn, "darn", 0, PPC_FEATURE2_DARN) \
|
||||||
[PPC_HAS_FPU] = {{PPC_FEATURE_HAS_FPU, 0}, "fpu", &set_fpu, &get_fpu},
|
FEATURE(PPC_SCV, scv, "scv", 0, PPC_FEATURE2_SCV) \
|
||||||
[PPC_HAS_MMU] = {{PPC_FEATURE_HAS_MMU, 0}, "mmu", &set_mmu, &get_mmu},
|
FEATURE(PPC_HTM_NO_SUSPEND, htm_no_suspend, "htm-no-suspend", 0, \
|
||||||
[PPC_HAS_4xxMAC] = {{PPC_FEATURE_HAS_4xxMAC, 0}, "4xxmac", &set_mac_4xx, &get_mac_4xx},
|
PPC_FEATURE2_HTM_NO_SUSPEND)
|
||||||
[PPC_UNIFIED_CACHE] = {{PPC_FEATURE_UNIFIED_CACHE, 0}, "ucache", &set_unifiedcache, &get_unifiedcache},
|
#define DEFINE_TABLE_FEATURE_TYPE PPCFeatures
|
||||||
[PPC_HAS_SPE] = {{PPC_FEATURE_HAS_SPE, 0}, "spe", &set_spe, &get_spe},
|
#include "define_tables.h"
|
||||||
[PPC_HAS_EFP_SINGLE] = {{PPC_FEATURE_HAS_EFP_SINGLE, 0}, "efpsingle", &set_efpsingle, &get_efpsingle},
|
|
||||||
[PPC_HAS_EFP_DOUBLE] = {{PPC_FEATURE_HAS_EFP_DOUBLE, 0}, "efpdouble", &set_efpdouble, &get_efpdouble},
|
|
||||||
[PPC_NO_TB] = {{PPC_FEATURE_NO_TB, 0}, "notb", &set_no_tb, &get_no_tb},
|
|
||||||
[PPC_POWER4] = {{PPC_FEATURE_POWER4, 0}, "power4", &set_power4, &get_power4},
|
|
||||||
[PPC_POWER5] = {{PPC_FEATURE_POWER5, 0}, "power5", &set_power5, &get_power5},
|
|
||||||
[PPC_POWER5_PLUS] = {{PPC_FEATURE_POWER5_PLUS, 0}, "power5+", &set_power5plus, &get_power5plus},
|
|
||||||
[PPC_CELL] = {{PPC_FEATURE_CELL, 0}, "cellbe", &set_cell, &get_cell},
|
|
||||||
[PPC_BOOKE] = {{PPC_FEATURE_BOOKE, 0}, "booke", &set_booke, &get_booke},
|
|
||||||
[PPC_SMT] = {{PPC_FEATURE_SMT, 0}, "smt", &set_smt, &get_smt},
|
|
||||||
[PPC_ICACHE_SNOOP] = {{PPC_FEATURE_ICACHE_SNOOP, 0}, "ic_snoop", &set_icachesnoop, &get_icachesnoop},
|
|
||||||
[PPC_ARCH_2_05] = {{PPC_FEATURE_ARCH_2_05, 0}, "arch_2_05", &set_arch205, &get_arch205},
|
|
||||||
[PPC_PA6T] = {{PPC_FEATURE_PA6T, 0}, "pa6t", &set_pa6t, &get_pa6t},
|
|
||||||
[PPC_HAS_DFP] = {{PPC_FEATURE_HAS_DFP, 0}, "dfp", &set_dfp, &get_dfp},
|
|
||||||
[PPC_POWER6_EXT] = {{PPC_FEATURE_POWER6_EXT, 0}, "power6x", &set_power6ext, &get_power6ext},
|
|
||||||
[PPC_ARCH_2_06] = {{PPC_FEATURE_ARCH_2_06, 0}, "arch_2_06", &set_arch206, &get_arch206},
|
|
||||||
[PPC_HAS_VSX] = {{PPC_FEATURE_HAS_VSX, 0}, "vsx", &set_vsx, &get_vsx},
|
|
||||||
[PPC_PSERIES_PERFMON_COMPAT] = {{PPC_FEATURE_PSERIES_PERFMON_COMPAT, 0}, "archpmu",
|
|
||||||
&set_pseries_perfmon_compat, &get_pseries_perfmon_compat},
|
|
||||||
[PPC_TRUE_LE] = {{PPC_FEATURE_TRUE_LE, 0}, "true_le", &set_truele, &get_truele},
|
|
||||||
[PPC_PPC_LE] = {{PPC_FEATURE_PPC_LE, 0}, "ppcle", &set_ppcle, &get_ppcle},
|
|
||||||
[PPC_ARCH_2_07] = {{0, PPC_FEATURE2_ARCH_2_07}, "arch_2_07", &set_arch207, &get_arch207},
|
|
||||||
[PPC_HTM] = {{0, PPC_FEATURE2_HTM}, "htm", &set_htm, &get_htm},
|
|
||||||
[PPC_DSCR] = {{0, PPC_FEATURE2_DSCR}, "dscr", &set_dscr, &get_dscr},
|
|
||||||
[PPC_EBB] = {{0, PPC_FEATURE2_EBB}, "ebb", &set_ebb, &get_ebb},
|
|
||||||
[PPC_ISEL] = {{0, PPC_FEATURE2_ISEL}, "isel", &set_isel, &get_isel},
|
|
||||||
[PPC_TAR] = {{0, PPC_FEATURE2_TAR}, "tar", &set_tar, &get_tar},
|
|
||||||
[PPC_VEC_CRYPTO] = {{0, PPC_FEATURE2_VEC_CRYPTO}, "vcrypto", &set_vcrypto, &get_vcrypto},
|
|
||||||
[PPC_HTM_NOSC] = {{0, PPC_FEATURE2_HTM_NOSC}, "htm-nosc", &set_htm_nosc, &get_htm_nosc},
|
|
||||||
[PPC_ARCH_3_00] = {{0, PPC_FEATURE2_ARCH_3_00}, "arch_3_00", &set_arch300, &get_arch300},
|
|
||||||
[PPC_HAS_IEEE128] = {{0, PPC_FEATURE2_HAS_IEEE128}, "ieee128", &set_ieee128, &get_ieee128},
|
|
||||||
[PPC_DARN] = {{0, PPC_FEATURE2_DARN}, "darn", &set_darn, &get_darn},
|
|
||||||
[PPC_SCV] = {{0, PPC_FEATURE2_SCV}, "scv", &set_scv, &get_scv},
|
|
||||||
[PPC_HTM_NO_SUSPEND] = {{0, PPC_FEATURE2_HTM_NO_SUSPEND}, "htm-no-suspend", &set_htm_no_suspend,
|
|
||||||
&get_htm_no_suspend},
|
|
||||||
};
|
|
||||||
static const size_t kConfigsSize = sizeof(kConfigs) / sizeof(CapabilityConfig);
|
|
||||||
|
|
||||||
static bool HandlePPCLine(const LineResult result,
|
static bool HandlePPCLine(const LineResult result,
|
||||||
PPCPlatformStrings* const strings)
|
PPCPlatformStrings* const strings)
|
||||||
@ -158,10 +121,14 @@ PPCInfo GetPPCInfo(void)
|
|||||||
* the auxilary vector.
|
* the auxilary vector.
|
||||||
*/
|
*/
|
||||||
PPCInfo info = kEmptyPPCInfo;
|
PPCInfo info = kEmptyPPCInfo;
|
||||||
|
const HardwareCapabilities hwcaps = CpuFeatures_GetHardwareCapabilities();
|
||||||
CpuFeatures_OverrideFromHwCaps(kConfigsSize, kConfigs,
|
for (size_t i = 0; i < PPC_LAST_; ++i)
|
||||||
CpuFeatures_GetHardwareCapabilities(),
|
{
|
||||||
&info.features);
|
if (CpuFeatures_IsHwCapsSet(kHardwareCapabilities[i], hwcaps))
|
||||||
|
{
|
||||||
|
kSetters[i](&info.features, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
return info;
|
return info;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -182,14 +149,12 @@ PPCPlatformStrings GetPPCPlatformStrings(void)
|
|||||||
int GetPPCFeaturesEnumValue(const PPCFeatures* features,
|
int GetPPCFeaturesEnumValue(const PPCFeatures* features,
|
||||||
PPCFeaturesEnum value)
|
PPCFeaturesEnum value)
|
||||||
{
|
{
|
||||||
if (value >= kConfigsSize)
|
if (value >= PPC_LAST_) return false;
|
||||||
return false;
|
return kGetters[value](features);
|
||||||
return kConfigs[value].get_bit((PPCFeatures*)features);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const char* GetPPCFeaturesEnumName(PPCFeaturesEnum value)
|
const char* GetPPCFeaturesEnumName(PPCFeaturesEnum value)
|
||||||
{
|
{
|
||||||
if (value >= kConfigsSize)
|
if (value >= PPC_LAST_) return "unknown feature";
|
||||||
return "unknown feature";
|
return kCpuInfoFlags[value];
|
||||||
return kConfigs[value].proc_cpuinfo_flag;
|
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
// SPDX-FileCopyrightText: 2017 Google Inc.
|
// SPDX-FileCopyrightText: 2017 Google LLC
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
#include "cpuinfo_x86.h"
|
#include "cpuinfo_x86.h"
|
||||||
@ -11,6 +11,91 @@
|
|||||||
#error "Cannot compile cpuinfo_x86 on a non x86 platform."
|
#error "Cannot compile cpuinfo_x86 on a non x86 platform."
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
// Generation of feature's getters/setters functions and kGetters, kSetters,
|
||||||
|
// kCpuInfoFlags global tables.
|
||||||
|
#define DEFINE_TABLE_FEATURES \
|
||||||
|
FEATURE(X86_FPU, fpu, "fpu", 0, 0) \
|
||||||
|
FEATURE(X86_TSC, tsc, "tsc", 0, 0) \
|
||||||
|
FEATURE(X86_CX8, cx8, "cx8", 0, 0) \
|
||||||
|
FEATURE(X86_CLFSH, clfsh, "clfsh", 0, 0) \
|
||||||
|
FEATURE(X86_MMX, mmx, "mmx", 0, 0) \
|
||||||
|
FEATURE(X86_AES, aes, "aes", 0, 0) \
|
||||||
|
FEATURE(X86_ERMS, erms, "erms", 0, 0) \
|
||||||
|
FEATURE(X86_F16C, f16c, "f16c", 0, 0) \
|
||||||
|
FEATURE(X86_FMA4, fma4, "fma4", 0, 0) \
|
||||||
|
FEATURE(X86_FMA3, fma3, "fma3", 0, 0) \
|
||||||
|
FEATURE(X86_VAES, vaes, "vaes", 0, 0) \
|
||||||
|
FEATURE(X86_VPCLMULQDQ, vpclmulqdq, "vpclmulqdq", 0, 0) \
|
||||||
|
FEATURE(X86_BMI1, bmi1, "bmi1", 0, 0) \
|
||||||
|
FEATURE(X86_HLE, hle, "hle", 0, 0) \
|
||||||
|
FEATURE(X86_BMI2, bmi2, "bmi2", 0, 0) \
|
||||||
|
FEATURE(X86_RTM, rtm, "rtm", 0, 0) \
|
||||||
|
FEATURE(X86_RDSEED, rdseed, "rdseed", 0, 0) \
|
||||||
|
FEATURE(X86_CLFLUSHOPT, clflushopt, "clflushopt", 0, 0) \
|
||||||
|
FEATURE(X86_CLWB, clwb, "clwb", 0, 0) \
|
||||||
|
FEATURE(X86_SSE, sse, "sse", 0, 0) \
|
||||||
|
FEATURE(X86_SSE2, sse2, "sse2", 0, 0) \
|
||||||
|
FEATURE(X86_SSE3, sse3, "sse3", 0, 0) \
|
||||||
|
FEATURE(X86_SSSE3, ssse3, "ssse3", 0, 0) \
|
||||||
|
FEATURE(X86_SSE4_1, sse4_1, "sse4_1", 0, 0) \
|
||||||
|
FEATURE(X86_SSE4_2, sse4_2, "sse4_2", 0, 0) \
|
||||||
|
FEATURE(X86_SSE4A, sse4a, "sse4a", 0, 0) \
|
||||||
|
FEATURE(X86_AVX, avx, "avx", 0, 0) \
|
||||||
|
FEATURE(X86_AVX2, avx2, "avx2", 0, 0) \
|
||||||
|
FEATURE(X86_AVX512F, avx512f, "avx512f", 0, 0) \
|
||||||
|
FEATURE(X86_AVX512CD, avx512cd, "avx512cd", 0, 0) \
|
||||||
|
FEATURE(X86_AVX512ER, avx512er, "avx512er", 0, 0) \
|
||||||
|
FEATURE(X86_AVX512PF, avx512pf, "avx512pf", 0, 0) \
|
||||||
|
FEATURE(X86_AVX512BW, avx512bw, "avx512bw", 0, 0) \
|
||||||
|
FEATURE(X86_AVX512DQ, avx512dq, "avx512dq", 0, 0) \
|
||||||
|
FEATURE(X86_AVX512VL, avx512vl, "avx512vl", 0, 0) \
|
||||||
|
FEATURE(X86_AVX512IFMA, avx512ifma, "avx512ifma", 0, 0) \
|
||||||
|
FEATURE(X86_AVX512VBMI, avx512vbmi, "avx512vbmi", 0, 0) \
|
||||||
|
FEATURE(X86_AVX512VBMI2, avx512vbmi2, "avx512vbmi2", 0, 0) \
|
||||||
|
FEATURE(X86_AVX512VNNI, avx512vnni, "avx512vnni", 0, 0) \
|
||||||
|
FEATURE(X86_AVX512BITALG, avx512bitalg, "avx512bitalg", 0, 0) \
|
||||||
|
FEATURE(X86_AVX512VPOPCNTDQ, avx512vpopcntdq, "avx512vpopcntdq", 0, 0) \
|
||||||
|
FEATURE(X86_AVX512_4VNNIW, avx512_4vnniw, "avx512_4vnniw", 0, 0) \
|
||||||
|
FEATURE(X86_AVX512_4VBMI2, avx512_4vbmi2, "avx512_4vbmi2", 0, 0) \
|
||||||
|
FEATURE(X86_AVX512_SECOND_FMA, avx512_second_fma, "avx512_second_fma", 0, 0) \
|
||||||
|
FEATURE(X86_AVX512_4FMAPS, avx512_4fmaps, "avx512_4fmaps", 0, 0) \
|
||||||
|
FEATURE(X86_AVX512_BF16, avx512_bf16, "avx512_bf16", 0, 0) \
|
||||||
|
FEATURE(X86_AVX512_VP2INTERSECT, avx512_vp2intersect, "avx512_vp2intersect", \
|
||||||
|
0, 0) \
|
||||||
|
FEATURE(X86_AMX_BF16, amx_bf16, "amx_bf16", 0, 0) \
|
||||||
|
FEATURE(X86_AMX_TILE, amx_tile, "amx_tile", 0, 0) \
|
||||||
|
FEATURE(X86_AMX_INT8, amx_int8, "amx_int8", 0, 0) \
|
||||||
|
FEATURE(X86_PCLMULQDQ, pclmulqdq, "pclmulqdq", 0, 0) \
|
||||||
|
FEATURE(X86_SMX, smx, "smx", 0, 0) \
|
||||||
|
FEATURE(X86_SGX, sgx, "sgx", 0, 0) \
|
||||||
|
FEATURE(X86_CX16, cx16, "cx16", 0, 0) \
|
||||||
|
FEATURE(X86_SHA, sha, "sha", 0, 0) \
|
||||||
|
FEATURE(X86_POPCNT, popcnt, "popcnt", 0, 0) \
|
||||||
|
FEATURE(X86_MOVBE, movbe, "movbe", 0, 0) \
|
||||||
|
FEATURE(X86_RDRND, rdrnd, "rdrnd", 0, 0) \
|
||||||
|
FEATURE(X86_DCA, dca, "dca", 0, 0) \
|
||||||
|
FEATURE(X86_SS, ss, "ss", 0, 0)
|
||||||
|
#define DEFINE_TABLE_FEATURE_TYPE X86Features
|
||||||
|
#define DEFINE_TABLE_DONT_GENERATE_HWCAPS
|
||||||
|
#include "define_tables.h"
|
||||||
|
|
||||||
|
// The following includes are necessary to provide SSE detections on pre-AVX
|
||||||
|
// microarchitectures.
|
||||||
|
#if defined(CPU_FEATURES_OS_WINDOWS)
|
||||||
|
#include <windows.h> // IsProcessorFeaturePresent
|
||||||
|
#elif defined(CPU_FEATURES_OS_LINUX_OR_ANDROID)
|
||||||
|
#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"
|
||||||
|
#endif
|
||||||
|
#include <sys/sysctl.h>
|
||||||
|
#else
|
||||||
|
#error "Unsupported OS"
|
||||||
|
#endif // CPU_FEATURES_OS
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
// Definitions for CpuId and GetXCR0Eax.
|
// Definitions for CpuId and GetXCR0Eax.
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
@ -21,7 +106,7 @@
|
|||||||
|
|
||||||
#include <cpuid.h>
|
#include <cpuid.h>
|
||||||
|
|
||||||
Leaf CpuIdEx(uint32_t leaf_id, int ecx)
|
Leaf GetCpuidLeaf(uint32_t leaf_id, int ecx)
|
||||||
{
|
{
|
||||||
Leaf leaf;
|
Leaf leaf;
|
||||||
__cpuid_count(leaf_id, ecx, leaf.eax, leaf.ebx, leaf.ecx, leaf.edx);
|
__cpuid_count(leaf_id, ecx, leaf.eax, leaf.ebx, leaf.ecx, leaf.edx);
|
||||||
@ -45,7 +130,7 @@ uint32_t GetXCR0Eax(void)
|
|||||||
#include <immintrin.h>
|
#include <immintrin.h>
|
||||||
#include <intrin.h> // For __cpuidex()
|
#include <intrin.h> // For __cpuidex()
|
||||||
|
|
||||||
Leaf CpuIdEx(uint32_t leaf_id, int ecx)
|
Leaf GetCpuidLeaf(uint32_t leaf_id, int ecx)
|
||||||
{
|
{
|
||||||
Leaf leaf;
|
Leaf leaf;
|
||||||
int data[4];
|
int data[4];
|
||||||
@ -65,7 +150,7 @@ uint32_t GetXCR0Eax(void) { return (uint32_t)_xgetbv(0); }
|
|||||||
|
|
||||||
static Leaf CpuId(uint32_t leaf_id)
|
static Leaf CpuId(uint32_t leaf_id)
|
||||||
{
|
{
|
||||||
return CpuIdEx(leaf_id, 0);
|
return GetCpuidLeaf(leaf_id, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
static const Leaf kEmptyLeaf;
|
static const Leaf kEmptyLeaf;
|
||||||
@ -74,7 +159,7 @@ static Leaf SafeCpuIdEx(uint32_t max_cpuid_leaf, uint32_t leaf_id, int ecx)
|
|||||||
{
|
{
|
||||||
if (leaf_id <= max_cpuid_leaf)
|
if (leaf_id <= max_cpuid_leaf)
|
||||||
{
|
{
|
||||||
return CpuIdEx(leaf_id, ecx);
|
return GetCpuidLeaf(leaf_id, ecx);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -92,6 +177,8 @@ static Leaf SafeCpuId(uint32_t max_cpuid_leaf, uint32_t leaf_id)
|
|||||||
#define MASK_MASKREG 0x20
|
#define MASK_MASKREG 0x20
|
||||||
#define MASK_ZMM0_15 0x40
|
#define MASK_ZMM0_15 0x40
|
||||||
#define MASK_ZMM16_31 0x80
|
#define MASK_ZMM16_31 0x80
|
||||||
|
#define MASK_XTILECFG 0x20000
|
||||||
|
#define MASK_XTILEDATA 0x40000
|
||||||
|
|
||||||
static bool HasMask(uint32_t value, uint32_t mask)
|
static bool HasMask(uint32_t value, uint32_t mask)
|
||||||
{
|
{
|
||||||
@ -120,6 +207,46 @@ static bool HasZmmOsXSave(uint32_t xcr0_eax)
|
|||||||
MASK_ZMM16_31);
|
MASK_ZMM16_31);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Checks that operating system saves and restores AMX/TMUL state during context
|
||||||
|
// switches.
|
||||||
|
static bool HasTmmOsXSave(uint32_t xcr0_eax)
|
||||||
|
{
|
||||||
|
return HasMask(xcr0_eax, MASK_XMM | MASK_YMM | MASK_MASKREG | MASK_ZMM0_15 |
|
||||||
|
MASK_ZMM16_31 | MASK_XTILECFG | MASK_XTILEDATA);
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool HasSecondFMA(uint32_t model)
|
||||||
|
{
|
||||||
|
// Skylake server
|
||||||
|
if (model == 0x55)
|
||||||
|
{
|
||||||
|
char proc_name[49] = {0};
|
||||||
|
FillX86BrandString(proc_name);
|
||||||
|
// detect Xeon
|
||||||
|
if (proc_name[9] == 'X')
|
||||||
|
{
|
||||||
|
// detect Silver or Bronze
|
||||||
|
if (proc_name[17] == 'S' || proc_name[17] == 'B') return false;
|
||||||
|
// detect Gold 5_20 and below, except for Gold 53__
|
||||||
|
if (proc_name[17] == 'G' && proc_name[22] == '5')
|
||||||
|
return ((proc_name[23] == '3') ||
|
||||||
|
(proc_name[24] == '2' && proc_name[25] == '2'));
|
||||||
|
// detect Xeon W 210x
|
||||||
|
if (proc_name[17] == 'W' && proc_name[21] == '0') return false;
|
||||||
|
// detect Xeon D 2xxx
|
||||||
|
if (proc_name[17] == 'D' && proc_name[19] == '2' && proc_name[20] == '1')
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
// Cannon Lake client
|
||||||
|
if (model == 0x66) return false;
|
||||||
|
// Ice Lake client
|
||||||
|
if (model == 0x7d || model == 0x7e) return false;
|
||||||
|
// This is the right default...
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
static void SetVendor(const Leaf leaf, char* const vendor)
|
static void SetVendor(const Leaf leaf, char* const vendor)
|
||||||
{
|
{
|
||||||
*(uint32_t*)(vendor) = leaf.ebx;
|
*(uint32_t*)(vendor) = leaf.ebx;
|
||||||
@ -1061,23 +1188,126 @@ static void ParseLeaf4(const int max_cpuid_leaf, CacheInfo* info)
|
|||||||
// Avoid to recompute them since each call to cpuid is ~100 cycles.
|
// Avoid to recompute them since each call to cpuid is ~100 cycles.
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
bool have_sse;
|
bool have_sse_via_os;
|
||||||
|
bool have_sse_via_cpuid;
|
||||||
bool have_avx;
|
bool have_avx;
|
||||||
bool have_avx512;
|
bool have_avx512;
|
||||||
|
bool have_amx;
|
||||||
} OsSupport;
|
} 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);
|
||||||
|
os_support.have_avx512 = HasZmmOsXSave(xcr0_eax);
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if defined(CPU_FEATURES_OS_WINDOWS)
|
||||||
|
#if defined(CPU_FEATURES_MOCK_CPUID_X86)
|
||||||
|
extern bool GetWindowsIsProcessorFeaturePresent(DWORD);
|
||||||
|
#else // CPU_FEATURES_MOCK_CPUID_X86
|
||||||
|
static bool GetWindowsIsProcessorFeaturePresent(DWORD ProcessorFeature)
|
||||||
|
{
|
||||||
|
return IsProcessorFeaturePresent(ProcessorFeature);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
#endif // CPU_FEATURES_OS_WINDOWS
|
||||||
|
|
||||||
|
#if defined(CPU_FEATURES_OS_DARWIN)
|
||||||
|
#if defined(CPU_FEATURES_MOCK_CPUID_X86)
|
||||||
|
extern bool GetDarwinSysCtlByName(const char*);
|
||||||
|
#else // CPU_FEATURES_MOCK_CPUID_X86
|
||||||
|
static bool GetDarwinSysCtlByName(const char* name)
|
||||||
|
{
|
||||||
|
int enabled;
|
||||||
|
size_t enabled_len = sizeof(enabled);
|
||||||
|
const int failure = sysctlbyname(name, &enabled, &enabled_len, NULL, 0);
|
||||||
|
return failure ? false : enabled;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
#endif // CPU_FEATURES_OS_DARWIN
|
||||||
|
|
||||||
|
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.
|
// Reference https://en.wikipedia.org/wiki/CPUID.
|
||||||
static void ParseCpuId(const uint32_t max_cpuid_leaf, X86Info* info, OsSupport* os_support)
|
static void ParseCpuId(const uint32_t max_cpuid_leaf,
|
||||||
|
const OsSupport os_support, X86Info* info)
|
||||||
{
|
{
|
||||||
const Leaf leaf_1 = SafeCpuId(max_cpuid_leaf, 1);
|
const Leaf leaf_1 = SafeCpuId(max_cpuid_leaf, 1);
|
||||||
const Leaf leaf_7 = SafeCpuId(max_cpuid_leaf, 7);
|
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 uint32_t xcr0_eax = (have_xsave && have_osxsave) ? GetXCR0Eax() : 0;
|
|
||||||
os_support->have_sse = HasXmmOsXSave(xcr0_eax);
|
|
||||||
os_support->have_avx = HasYmmOsXSave(xcr0_eax);
|
|
||||||
os_support->have_avx512 = HasZmmOsXSave(xcr0_eax);
|
|
||||||
|
|
||||||
const uint32_t family = ExtractBitRange(leaf_1.eax, 11, 8);
|
const uint32_t family = ExtractBitRange(leaf_1.eax, 11, 8);
|
||||||
const uint32_t extended_family = ExtractBitRange(leaf_1.eax, 27, 20);
|
const uint32_t extended_family = ExtractBitRange(leaf_1.eax, 27, 20);
|
||||||
@ -1118,7 +1348,11 @@ static void ParseCpuId(const uint32_t max_cpuid_leaf, X86Info* info, OsSupport*
|
|||||||
features->vaes = IsBitSet(leaf_7.ecx, 9);
|
features->vaes = IsBitSet(leaf_7.ecx, 9);
|
||||||
features->vpclmulqdq = IsBitSet(leaf_7.ecx, 10);
|
features->vpclmulqdq = IsBitSet(leaf_7.ecx, 10);
|
||||||
|
|
||||||
if (os_support->have_sse)
|
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->sse = IsBitSet(leaf_1.edx, 25);
|
||||||
features->sse2 = IsBitSet(leaf_1.edx, 26);
|
features->sse2 = IsBitSet(leaf_1.edx, 26);
|
||||||
@ -1128,14 +1362,14 @@ static void ParseCpuId(const uint32_t max_cpuid_leaf, X86Info* info, OsSupport*
|
|||||||
features->sse4_2 = IsBitSet(leaf_1.ecx, 20);
|
features->sse4_2 = IsBitSet(leaf_1.ecx, 20);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (os_support->have_avx)
|
if (os_support.have_avx)
|
||||||
{
|
{
|
||||||
features->fma3 = IsBitSet(leaf_1.ecx, 12);
|
features->fma3 = IsBitSet(leaf_1.ecx, 12);
|
||||||
features->avx = IsBitSet(leaf_1.ecx, 28);
|
features->avx = IsBitSet(leaf_1.ecx, 28);
|
||||||
features->avx2 = IsBitSet(leaf_7.ebx, 5);
|
features->avx2 = IsBitSet(leaf_7.ebx, 5);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (os_support->have_avx512)
|
if (os_support.have_avx512)
|
||||||
{
|
{
|
||||||
features->avx512f = IsBitSet(leaf_7.ebx, 16);
|
features->avx512f = IsBitSet(leaf_7.ebx, 16);
|
||||||
features->avx512cd = IsBitSet(leaf_7.ebx, 28);
|
features->avx512cd = IsBitSet(leaf_7.ebx, 28);
|
||||||
@ -1152,18 +1386,31 @@ static void ParseCpuId(const uint32_t max_cpuid_leaf, X86Info* info, OsSupport*
|
|||||||
features->avx512vpopcntdq = IsBitSet(leaf_7.ecx, 14);
|
features->avx512vpopcntdq = IsBitSet(leaf_7.ecx, 14);
|
||||||
features->avx512_4vnniw = IsBitSet(leaf_7.edx, 2);
|
features->avx512_4vnniw = IsBitSet(leaf_7.edx, 2);
|
||||||
features->avx512_4vbmi2 = IsBitSet(leaf_7.edx, 3);
|
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_support.have_amx)
|
||||||
|
{
|
||||||
|
features->amx_bf16 = IsBitSet(leaf_7.edx, 22);
|
||||||
|
features->amx_tile = IsBitSet(leaf_7.edx, 24);
|
||||||
|
features->amx_int8 = IsBitSet(leaf_7.edx, 25);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Reference https://en.wikipedia.org/wiki/CPUID#EAX=80000000h:_Get_Highest_Extended_Function_Implemented.
|
// Reference
|
||||||
static void ParseExtraAMDCpuId(const uint32_t max_cpuid_leaf, X86Info* info, OsSupport os_support)
|
// https://en.wikipedia.org/wiki/CPUID#EAX=80000000h:_Get_Highest_Extended_Function_Implemented.
|
||||||
|
static void ParseExtraAMDCpuId(X86Info* info, OsSupport os_support)
|
||||||
{
|
{
|
||||||
const Leaf leaf_80000000 = CpuId(0x80000000);
|
const Leaf leaf_80000000 = CpuId(0x80000000);
|
||||||
const Leaf leaf_80000001 = SafeCpuId(leaf_80000000.eax, 0x80000001);
|
const uint32_t max_extended_cpuid_leaf = leaf_80000000.eax;
|
||||||
|
const Leaf leaf_80000001 = SafeCpuId(max_extended_cpuid_leaf, 0x80000001);
|
||||||
|
|
||||||
X86Features* const features = &info->features;
|
X86Features* const features = &info->features;
|
||||||
|
|
||||||
if (os_support.have_sse)
|
if (os_support.have_sse_via_cpuid)
|
||||||
{
|
{
|
||||||
features->sse4a = IsBitSet(leaf_80000001.ecx, 6);
|
features->sse4a = IsBitSet(leaf_80000001.ecx, 6);
|
||||||
}
|
}
|
||||||
@ -1175,23 +1422,24 @@ static void ParseExtraAMDCpuId(const uint32_t max_cpuid_leaf, X86Info* info, OsS
|
|||||||
}
|
}
|
||||||
|
|
||||||
static const X86Info kEmptyX86Info;
|
static const X86Info kEmptyX86Info;
|
||||||
static const OsSupport kEmptyOsSupport;
|
|
||||||
static const CacheInfo kEmptyCacheInfo;
|
static const CacheInfo kEmptyCacheInfo;
|
||||||
|
|
||||||
X86Info GetX86Info(void)
|
X86Info GetX86Info(void)
|
||||||
{
|
{
|
||||||
X86Info info = kEmptyX86Info;
|
X86Info info = kEmptyX86Info;
|
||||||
OsSupport os_support = kEmptyOsSupport;
|
|
||||||
const Leaf leaf_0 = CpuId(0);
|
const Leaf leaf_0 = CpuId(0);
|
||||||
const uint32_t max_cpuid_leaf = leaf_0.eax;
|
const bool is_intel = IsVendor(leaf_0, "GenuineIntel");
|
||||||
|
const bool is_amd = IsVendor(leaf_0, "AuthenticAMD");
|
||||||
SetVendor(leaf_0, info.vendor);
|
SetVendor(leaf_0, info.vendor);
|
||||||
if (IsVendor(leaf_0, "GenuineIntel") || IsVendor(leaf_0, "AuthenticAMD"))
|
if (is_intel || is_amd)
|
||||||
{
|
{
|
||||||
ParseCpuId(max_cpuid_leaf, &info, &os_support);
|
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)
|
||||||
|
{
|
||||||
|
ParseExtraAMDCpuId(&info, os_support);
|
||||||
}
|
}
|
||||||
if (IsVendor(leaf_0, "AuthenticAMD"))
|
|
||||||
{
|
|
||||||
ParseExtraAMDCpuId(max_cpuid_leaf, &info, os_support);
|
|
||||||
}
|
}
|
||||||
return info;
|
return info;
|
||||||
}
|
}
|
||||||
@ -1275,9 +1523,20 @@ X86Microarchitecture GetX86Microarchitecture(const X86Info* info)
|
|||||||
case CPUID(0x06, 0x66):
|
case CPUID(0x06, 0x66):
|
||||||
// https://en.wikipedia.org/wiki/Cannon_Lake_(microarchitecture)
|
// https://en.wikipedia.org/wiki/Cannon_Lake_(microarchitecture)
|
||||||
return INTEL_CNL;
|
return INTEL_CNL;
|
||||||
case CPUID(0x06, 0x7E):
|
case CPUID(0x06, 0x7D): // client
|
||||||
|
case CPUID(0x06, 0x7E): // client
|
||||||
|
case CPUID(0x06, 0x9D): // NNP-I
|
||||||
|
case CPUID(0x06, 0x6A): // server
|
||||||
|
case CPUID(0x06, 0x6C): // server
|
||||||
// https://en.wikipedia.org/wiki/Ice_Lake_(microprocessor)
|
// https://en.wikipedia.org/wiki/Ice_Lake_(microprocessor)
|
||||||
return INTEL_ICL;
|
return INTEL_ICL;
|
||||||
|
case CPUID(0x06, 0x8C):
|
||||||
|
case CPUID(0x06, 0x8D):
|
||||||
|
// https://en.wikipedia.org/wiki/Tiger_Lake_(microarchitecture)
|
||||||
|
return INTEL_TGL;
|
||||||
|
case CPUID(0x06, 0x8F):
|
||||||
|
// https://en.wikipedia.org/wiki/Sapphire_Rapids
|
||||||
|
return INTEL_SPR;
|
||||||
case CPUID(0x06, 0x8E):
|
case CPUID(0x06, 0x8E):
|
||||||
switch (info->stepping)
|
switch (info->stepping)
|
||||||
{
|
{
|
||||||
@ -1354,234 +1613,14 @@ void FillX86BrandString(char brand_string[49])
|
|||||||
int GetX86FeaturesEnumValue(const X86Features* features,
|
int GetX86FeaturesEnumValue(const X86Features* features,
|
||||||
X86FeaturesEnum value)
|
X86FeaturesEnum value)
|
||||||
{
|
{
|
||||||
switch (value)
|
if (value >= X86_LAST_) return false;
|
||||||
{
|
return kGetters[value](features);
|
||||||
case X86_FPU:
|
|
||||||
return features->fpu;
|
|
||||||
case X86_TSC:
|
|
||||||
return features->tsc;
|
|
||||||
case X86_CX8:
|
|
||||||
return features->cx8;
|
|
||||||
case X86_CLFSH:
|
|
||||||
return features->clfsh;
|
|
||||||
case X86_MMX:
|
|
||||||
return features->mmx;
|
|
||||||
case X86_AES:
|
|
||||||
return features->aes;
|
|
||||||
case X86_ERMS:
|
|
||||||
return features->erms;
|
|
||||||
case X86_F16C:
|
|
||||||
return features->f16c;
|
|
||||||
case X86_FMA4:
|
|
||||||
return features->fma4;
|
|
||||||
case X86_FMA3:
|
|
||||||
return features->fma3;
|
|
||||||
case X86_VAES:
|
|
||||||
return features->vaes;
|
|
||||||
case X86_VPCLMULQDQ:
|
|
||||||
return features->vpclmulqdq;
|
|
||||||
case X86_BMI1:
|
|
||||||
return features->bmi1;
|
|
||||||
case X86_HLE:
|
|
||||||
return features->hle;
|
|
||||||
case X86_BMI2:
|
|
||||||
return features->bmi2;
|
|
||||||
case X86_RTM:
|
|
||||||
return features->rtm;
|
|
||||||
case X86_RDSEED:
|
|
||||||
return features->rdseed;
|
|
||||||
case X86_CLFLUSHOPT:
|
|
||||||
return features->clflushopt;
|
|
||||||
case X86_CLWB:
|
|
||||||
return features->clwb;
|
|
||||||
case X86_SSE:
|
|
||||||
return features->sse;
|
|
||||||
case X86_SSE2:
|
|
||||||
return features->sse2;
|
|
||||||
case X86_SSE3:
|
|
||||||
return features->sse3;
|
|
||||||
case X86_SSSE3:
|
|
||||||
return features->ssse3;
|
|
||||||
case X86_SSE4_1:
|
|
||||||
return features->sse4_1;
|
|
||||||
case X86_SSE4_2:
|
|
||||||
return features->sse4_2;
|
|
||||||
case X86_SSE4A:
|
|
||||||
return features->sse4a;
|
|
||||||
case X86_AVX:
|
|
||||||
return features->avx;
|
|
||||||
case X86_AVX2:
|
|
||||||
return features->avx2;
|
|
||||||
case X86_AVX512F:
|
|
||||||
return features->avx512f;
|
|
||||||
case X86_AVX512CD:
|
|
||||||
return features->avx512cd;
|
|
||||||
case X86_AVX512ER:
|
|
||||||
return features->avx512er;
|
|
||||||
case X86_AVX512PF:
|
|
||||||
return features->avx512pf;
|
|
||||||
case X86_AVX512BW:
|
|
||||||
return features->avx512bw;
|
|
||||||
case X86_AVX512DQ:
|
|
||||||
return features->avx512dq;
|
|
||||||
case X86_AVX512VL:
|
|
||||||
return features->avx512vl;
|
|
||||||
case X86_AVX512IFMA:
|
|
||||||
return features->avx512ifma;
|
|
||||||
case X86_AVX512VBMI:
|
|
||||||
return features->avx512vbmi;
|
|
||||||
case X86_AVX512VBMI2:
|
|
||||||
return features->avx512vbmi2;
|
|
||||||
case X86_AVX512VNNI:
|
|
||||||
return features->avx512vnni;
|
|
||||||
case X86_AVX512BITALG:
|
|
||||||
return features->avx512bitalg;
|
|
||||||
case X86_AVX512VPOPCNTDQ:
|
|
||||||
return features->avx512vpopcntdq;
|
|
||||||
case X86_AVX512_4VNNIW:
|
|
||||||
return features->avx512_4vnniw;
|
|
||||||
case X86_AVX512_4VBMI2:
|
|
||||||
return features->avx512_4vbmi2;
|
|
||||||
case X86_PCLMULQDQ:
|
|
||||||
return features->pclmulqdq;
|
|
||||||
case X86_SMX:
|
|
||||||
return features->smx;
|
|
||||||
case X86_SGX:
|
|
||||||
return features->sgx;
|
|
||||||
case X86_CX16:
|
|
||||||
return features->cx16;
|
|
||||||
case X86_SHA:
|
|
||||||
return features->sha;
|
|
||||||
case X86_POPCNT:
|
|
||||||
return features->popcnt;
|
|
||||||
case X86_MOVBE:
|
|
||||||
return features->movbe;
|
|
||||||
case X86_RDRND:
|
|
||||||
return features->rdrnd;
|
|
||||||
case X86_DCA:
|
|
||||||
return features->dca;
|
|
||||||
case X86_SS:
|
|
||||||
return features->ss;
|
|
||||||
case X86_LAST_:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const char* GetX86FeaturesEnumName(X86FeaturesEnum value)
|
const char* GetX86FeaturesEnumName(X86FeaturesEnum value)
|
||||||
{
|
{
|
||||||
switch (value)
|
if (value >= X86_LAST_) return "unknown_feature";
|
||||||
{
|
return kCpuInfoFlags[value];
|
||||||
case X86_FPU:
|
|
||||||
return "fpu";
|
|
||||||
case X86_TSC:
|
|
||||||
return "tsc";
|
|
||||||
case X86_CX8:
|
|
||||||
return "cx8";
|
|
||||||
case X86_CLFSH:
|
|
||||||
return "clfsh";
|
|
||||||
case X86_MMX:
|
|
||||||
return "mmx";
|
|
||||||
case X86_AES:
|
|
||||||
return "aes";
|
|
||||||
case X86_ERMS:
|
|
||||||
return "erms";
|
|
||||||
case X86_F16C:
|
|
||||||
return "f16c";
|
|
||||||
case X86_FMA4:
|
|
||||||
return "fma4";
|
|
||||||
case X86_FMA3:
|
|
||||||
return "fma3";
|
|
||||||
case X86_VAES:
|
|
||||||
return "vaes";
|
|
||||||
case X86_VPCLMULQDQ:
|
|
||||||
return "vpclmulqdq";
|
|
||||||
case X86_BMI1:
|
|
||||||
return "bmi1";
|
|
||||||
case X86_HLE:
|
|
||||||
return "hle";
|
|
||||||
case X86_BMI2:
|
|
||||||
return "bmi2";
|
|
||||||
case X86_RTM:
|
|
||||||
return "rtm";
|
|
||||||
case X86_RDSEED:
|
|
||||||
return "rdseed";
|
|
||||||
case X86_CLFLUSHOPT:
|
|
||||||
return "clflushopt";
|
|
||||||
case X86_CLWB:
|
|
||||||
return "clwb";
|
|
||||||
case X86_SSE:
|
|
||||||
return "sse";
|
|
||||||
case X86_SSE2:
|
|
||||||
return "sse2";
|
|
||||||
case X86_SSE3:
|
|
||||||
return "sse3";
|
|
||||||
case X86_SSSE3:
|
|
||||||
return "ssse3";
|
|
||||||
case X86_SSE4_1:
|
|
||||||
return "sse4_1";
|
|
||||||
case X86_SSE4_2:
|
|
||||||
return "sse4_2";
|
|
||||||
case X86_SSE4A:
|
|
||||||
return "sse4a";
|
|
||||||
case X86_AVX:
|
|
||||||
return "avx";
|
|
||||||
case X86_AVX2:
|
|
||||||
return "avx2";
|
|
||||||
case X86_AVX512F:
|
|
||||||
return "avx512f";
|
|
||||||
case X86_AVX512CD:
|
|
||||||
return "avx512cd";
|
|
||||||
case X86_AVX512ER:
|
|
||||||
return "avx512er";
|
|
||||||
case X86_AVX512PF:
|
|
||||||
return "avx512pf";
|
|
||||||
case X86_AVX512BW:
|
|
||||||
return "avx512bw";
|
|
||||||
case X86_AVX512DQ:
|
|
||||||
return "avx512dq";
|
|
||||||
case X86_AVX512VL:
|
|
||||||
return "avx512vl";
|
|
||||||
case X86_AVX512IFMA:
|
|
||||||
return "avx512ifma";
|
|
||||||
case X86_AVX512VBMI:
|
|
||||||
return "avx512vbmi";
|
|
||||||
case X86_AVX512VBMI2:
|
|
||||||
return "avx512vbmi2";
|
|
||||||
case X86_AVX512VNNI:
|
|
||||||
return "avx512vnni";
|
|
||||||
case X86_AVX512BITALG:
|
|
||||||
return "avx512bitalg";
|
|
||||||
case X86_AVX512VPOPCNTDQ:
|
|
||||||
return "avx512vpopcntdq";
|
|
||||||
case X86_AVX512_4VNNIW:
|
|
||||||
return "avx512_4vnniw";
|
|
||||||
case X86_AVX512_4VBMI2:
|
|
||||||
return "avx512_4vbmi2";
|
|
||||||
case X86_PCLMULQDQ:
|
|
||||||
return "pclmulqdq";
|
|
||||||
case X86_SMX:
|
|
||||||
return "smx";
|
|
||||||
case X86_SGX:
|
|
||||||
return "sgx";
|
|
||||||
case X86_CX16:
|
|
||||||
return "cx16";
|
|
||||||
case X86_SHA:
|
|
||||||
return "sha";
|
|
||||||
case X86_POPCNT:
|
|
||||||
return "popcnt";
|
|
||||||
case X86_MOVBE:
|
|
||||||
return "movbe";
|
|
||||||
case X86_RDRND:
|
|
||||||
return "rdrnd";
|
|
||||||
case X86_DCA:
|
|
||||||
return "dca";
|
|
||||||
case X86_SS:
|
|
||||||
return "ss";
|
|
||||||
case X86_LAST_:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
return "unknown_feature";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const char* GetX86MicroarchitectureName(X86Microarchitecture uarch)
|
const char* GetX86MicroarchitectureName(X86Microarchitecture uarch)
|
||||||
@ -1624,6 +1663,10 @@ const char* GetX86MicroarchitectureName(X86Microarchitecture uarch)
|
|||||||
return "INTEL_CNL";
|
return "INTEL_CNL";
|
||||||
case INTEL_ICL:
|
case INTEL_ICL:
|
||||||
return "INTEL_ICL";
|
return "INTEL_ICL";
|
||||||
|
case INTEL_TGL:
|
||||||
|
return "INTEL_TGL";
|
||||||
|
case INTEL_SPR:
|
||||||
|
return "INTEL_SPR";
|
||||||
case AMD_HAMMER:
|
case AMD_HAMMER:
|
||||||
return "AMD_HAMMER";
|
return "AMD_HAMMER";
|
||||||
case AMD_K10:
|
case AMD_K10:
|
||||||
|
@ -0,0 +1,58 @@
|
|||||||
|
// SPDX-FileCopyrightText: 2017 Google LLC
|
||||||
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
|
// The following preprocessor constants must be defined before including this
|
||||||
|
// file:
|
||||||
|
// - DEFINE_TABLE_FEATURE_TYPE, the underlying type (e.g. X86Features)
|
||||||
|
// - DEFINE_TABLE_FEATURES, the list of FEATURE macros to be inserted.
|
||||||
|
|
||||||
|
// This file is to be included once per `cpuinfo_XXX.c` in order to construct
|
||||||
|
// feature getters and setters functions as well as several enum indexed tables
|
||||||
|
// from the db file.
|
||||||
|
// - `kGetters` a table of getters function pointers from feature enum to
|
||||||
|
// retrieve a feature,
|
||||||
|
// - `kSetters` a table of setters function pointers from feature enum to set a
|
||||||
|
// feature,
|
||||||
|
// - `kCpuInfoFlags` a table of strings from feature enum to /proc/cpuinfo
|
||||||
|
// flags,
|
||||||
|
// - `kHardwareCapabilities` a table of HardwareCapabilities structs indexed by
|
||||||
|
// their feature enum.
|
||||||
|
|
||||||
|
#ifndef SRC_DEFINE_TABLES_H_
|
||||||
|
#define SRC_DEFINE_TABLES_H_
|
||||||
|
|
||||||
|
#define FEATURE(ENUM, NAME, CPUINFO_FLAG, HWCAP, HWCAP2) [ENUM] = CPUINFO_FLAG,
|
||||||
|
static const char* kCpuInfoFlags[] = {DEFINE_TABLE_FEATURES};
|
||||||
|
#undef FEATURE
|
||||||
|
|
||||||
|
#ifndef DEFINE_TABLE_DONT_GENERATE_HWCAPS
|
||||||
|
#define FEATURE(ENUM, NAME, CPUINFO_FLAG, HWCAP, HWCAP2) \
|
||||||
|
[ENUM] = (HardwareCapabilities){HWCAP, HWCAP2},
|
||||||
|
static const HardwareCapabilities kHardwareCapabilities[] = {
|
||||||
|
DEFINE_TABLE_FEATURES};
|
||||||
|
#undef FEATURE
|
||||||
|
#endif // DEFINE_TABLE_DONT_GENERATE_HWCAPS
|
||||||
|
|
||||||
|
#define FEATURE(ENUM, NAME, CPUINFO_FLAG, HWCAP, HWCAP2) \
|
||||||
|
static void set_##ENUM(DEFINE_TABLE_FEATURE_TYPE* features, bool value) \
|
||||||
|
{ \
|
||||||
|
features->NAME = value; \
|
||||||
|
} \
|
||||||
|
static int get_##ENUM(const DEFINE_TABLE_FEATURE_TYPE* features) \
|
||||||
|
{ \
|
||||||
|
return features->NAME; \
|
||||||
|
}
|
||||||
|
DEFINE_TABLE_FEATURES
|
||||||
|
#undef FEATURE
|
||||||
|
|
||||||
|
#define FEATURE(ENUM, NAME, CPUINFO_FLAG, HWCAP, HWCAP2) [ENUM] = set_##ENUM,
|
||||||
|
static void (*const kSetters[])(DEFINE_TABLE_FEATURE_TYPE*,
|
||||||
|
bool) = {DEFINE_TABLE_FEATURES};
|
||||||
|
#undef FEATURE
|
||||||
|
|
||||||
|
#define FEATURE(ENUM, NAME, CPUINFO_FLAG, HWCAP, HWCAP2) [ENUM] = get_##ENUM,
|
||||||
|
static int (*const kGetters[])(const DEFINE_TABLE_FEATURE_TYPE*) = {
|
||||||
|
DEFINE_TABLE_FEATURES};
|
||||||
|
#undef FEATURE
|
||||||
|
|
||||||
|
#endif // SRC_DEFINE_TABLES_H_
|
@ -1,4 +1,4 @@
|
|||||||
// SPDX-FileCopyrightText: 2017 Google Inc.
|
// SPDX-FileCopyrightText: 2017 Google LLC
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
#include "internal/filesystem.h"
|
#include "internal/filesystem.h"
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
// SPDX-FileCopyrightText: 2017 Google Inc.
|
// SPDX-FileCopyrightText: 2017 Google LLC
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
#include "internal/hwcaps.h"
|
#include "internal/hwcaps.h"
|
||||||
@ -8,6 +8,26 @@
|
|||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
|
static bool IsSet(const uint32_t mask, const uint32_t value)
|
||||||
|
{
|
||||||
|
if (mask == 0) return false;
|
||||||
|
return (value & mask) == mask;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CpuFeatures_IsHwCapsSet(const HardwareCapabilities hwcaps_mask,
|
||||||
|
const HardwareCapabilities hwcaps)
|
||||||
|
{
|
||||||
|
return IsSet(hwcaps_mask.hwcaps, hwcaps.hwcaps) ||
|
||||||
|
IsSet(hwcaps_mask.hwcaps2, hwcaps.hwcaps2);
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef CPU_FEATURES_TEST
|
||||||
|
// In test mode, hwcaps_for_testing will define the following functions.
|
||||||
|
HardwareCapabilities CpuFeatures_GetHardwareCapabilities(void);
|
||||||
|
PlatformType CpuFeatures_GetPlatformType(void);
|
||||||
|
#else
|
||||||
|
|
||||||
|
// Debug facilities
|
||||||
#if defined(NDEBUG)
|
#if defined(NDEBUG)
|
||||||
#define D(...)
|
#define D(...)
|
||||||
#else
|
#else
|
||||||
@ -25,9 +45,12 @@
|
|||||||
// Implementation of GetElfHwcapFromGetauxval
|
// Implementation of GetElfHwcapFromGetauxval
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
#if defined(CPU_FEATURES_MOCK_GET_ELF_HWCAP_FROM_GETAUXVAL)
|
#define AT_HWCAP 16
|
||||||
// Implementation will be provided by test/hwcaps_for_testing.cc.
|
#define AT_HWCAP2 26
|
||||||
#elif defined(HAVE_STRONG_GETAUXVAL)
|
#define AT_PLATFORM 15
|
||||||
|
#define AT_BASE_PLATFORM 24
|
||||||
|
|
||||||
|
#if defined(HAVE_STRONG_GETAUXVAL)
|
||||||
#include <sys/auxv.h>
|
#include <sys/auxv.h>
|
||||||
static unsigned long GetElfHwcapFromGetauxval(uint32_t hwcap_type)
|
static unsigned long GetElfHwcapFromGetauxval(uint32_t hwcap_type)
|
||||||
{
|
{
|
||||||
@ -50,10 +73,6 @@ static unsigned long GetElfHwcapFromGetauxval(uint32_t hwcap_type)
|
|||||||
// initialization layer.
|
// initialization layer.
|
||||||
|
|
||||||
#include <dlfcn.h>
|
#include <dlfcn.h>
|
||||||
#define AT_HWCAP 16
|
|
||||||
#define AT_HWCAP2 26
|
|
||||||
#define AT_PLATFORM 15
|
|
||||||
#define AT_BASE_PLATFORM 24
|
|
||||||
|
|
||||||
typedef unsigned long getauxval_func_t(unsigned long);
|
typedef unsigned long getauxval_func_t(unsigned long);
|
||||||
|
|
||||||
@ -167,3 +186,5 @@ PlatformType CpuFeatures_GetPlatformType(void)
|
|||||||
sizeof(type.base_platform));
|
sizeof(type.base_platform));
|
||||||
return type;
|
return type;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#endif // CPU_FEATURES_TEST
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
// SPDX-FileCopyrightText: 2017 Google Inc.
|
// SPDX-FileCopyrightText: 2017 Google LLC
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
#include "internal/stack_line_reader.h"
|
#include "internal/stack_line_reader.h"
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
// SPDX-FileCopyrightText: 2017 Google Inc.
|
// SPDX-FileCopyrightText: 2017 Google LLC
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
#include "internal/string_view.h"
|
#include "internal/string_view.h"
|
||||||
|
@ -1,49 +0,0 @@
|
|||||||
// SPDX-FileCopyrightText: 2017 Google Inc.
|
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
|
||||||
|
|
||||||
|
|
||||||
#include "internal/unix_features_aggregator.h"
|
|
||||||
#include "internal/string_view.h"
|
|
||||||
|
|
||||||
void CpuFeatures_SetFromFlags(const size_t configs_size,
|
|
||||||
const CapabilityConfig* configs,
|
|
||||||
const StringView flags_line,
|
|
||||||
void* const features)
|
|
||||||
{
|
|
||||||
size_t i = 0;
|
|
||||||
for (; i < configs_size; ++i)
|
|
||||||
{
|
|
||||||
const CapabilityConfig config = configs[i];
|
|
||||||
config.set_bit(features, CpuFeatures_StringView_HasWord(
|
|
||||||
flags_line, config.proc_cpuinfo_flag));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool IsSet(const uint32_t mask, const uint32_t value)
|
|
||||||
{
|
|
||||||
if (mask == 0) return false;
|
|
||||||
return (value & mask) == mask;
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool IsHwCapsSet(const HardwareCapabilities hwcaps_mask,
|
|
||||||
const HardwareCapabilities hwcaps)
|
|
||||||
{
|
|
||||||
return IsSet(hwcaps_mask.hwcaps, hwcaps.hwcaps) ||
|
|
||||||
IsSet(hwcaps_mask.hwcaps2, hwcaps.hwcaps2);
|
|
||||||
}
|
|
||||||
|
|
||||||
void CpuFeatures_OverrideFromHwCaps(const size_t configs_size,
|
|
||||||
const CapabilityConfig* configs,
|
|
||||||
const HardwareCapabilities hwcaps,
|
|
||||||
void* const features)
|
|
||||||
{
|
|
||||||
size_t i = 0;
|
|
||||||
for (; i < configs_size; ++i)
|
|
||||||
{
|
|
||||||
const CapabilityConfig* config = &configs[i];
|
|
||||||
if (IsHwCapsSet(config->hwcaps_mask, hwcaps))
|
|
||||||
{
|
|
||||||
config->set_bit(features, true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,4 +1,4 @@
|
|||||||
// SPDX-FileCopyrightText: 2017 Google Inc.
|
// SPDX-FileCopyrightText: 2017 Google LLC
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
// This program dumps current host data to the standard output.
|
// This program dumps current host data to the standard output.
|
||||||
@ -32,7 +32,7 @@
|
|||||||
// the data accordingly.
|
// the data accordingly.
|
||||||
|
|
||||||
// We use a bump allocator to allocate strings and nodes of the tree,
|
// We use a bump allocator to allocate strings and nodes of the tree,
|
||||||
// Memory is not intented to be reclaimed.
|
// Memory is not intended to be reclaimed.
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
char* ptr;
|
char* ptr;
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
# SPDX-FileCopyrightText: 2017 Google Inc.
|
# SPDX-FileCopyrightText: 2017 Google LLC
|
||||||
# SPDX-License-Identifier: Apache-2.0
|
# SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
#
|
#
|
||||||
@ -15,7 +15,6 @@ add_library(filesystem_for_testing filesystem_for_testing.cc)
|
|||||||
target_compile_definitions(filesystem_for_testing PUBLIC CPU_FEATURES_MOCK_FILESYSTEM)
|
target_compile_definitions(filesystem_for_testing PUBLIC CPU_FEATURES_MOCK_FILESYSTEM)
|
||||||
##------------------------------------------------------------------------------
|
##------------------------------------------------------------------------------
|
||||||
add_library(hwcaps_for_testing hwcaps_for_testing.cc)
|
add_library(hwcaps_for_testing hwcaps_for_testing.cc)
|
||||||
target_compile_definitions(hwcaps_for_testing PUBLIC CPU_FEATURES_MOCK_GET_ELF_HWCAP_FROM_GETAUXVAL)
|
|
||||||
target_link_libraries(hwcaps_for_testing filesystem_for_testing)
|
target_link_libraries(hwcaps_for_testing filesystem_for_testing)
|
||||||
##------------------------------------------------------------------------------
|
##------------------------------------------------------------------------------
|
||||||
add_library(stack_line_reader ../src/stack_line_reader.c)
|
add_library(stack_line_reader ../src/stack_line_reader.c)
|
||||||
@ -26,7 +25,7 @@ add_library(stack_line_reader_for_test ../src/stack_line_reader.c)
|
|||||||
target_compile_definitions(stack_line_reader_for_test PUBLIC STACK_LINE_READER_BUFFER_SIZE=16)
|
target_compile_definitions(stack_line_reader_for_test PUBLIC STACK_LINE_READER_BUFFER_SIZE=16)
|
||||||
target_link_libraries(stack_line_reader_for_test string_view filesystem_for_testing)
|
target_link_libraries(stack_line_reader_for_test string_view filesystem_for_testing)
|
||||||
##------------------------------------------------------------------------------
|
##------------------------------------------------------------------------------
|
||||||
add_library(all_libraries ../src/stack_line_reader.c ../src/unix_features_aggregator.c)
|
add_library(all_libraries ../src/hwcaps.c ../src/stack_line_reader.c)
|
||||||
target_link_libraries(all_libraries hwcaps_for_testing stack_line_reader string_view)
|
target_link_libraries(all_libraries hwcaps_for_testing stack_line_reader string_view)
|
||||||
|
|
||||||
#
|
#
|
||||||
@ -49,15 +48,13 @@ add_executable(stack_line_reader_test stack_line_reader_test.cc)
|
|||||||
target_link_libraries(stack_line_reader_test stack_line_reader_for_test)
|
target_link_libraries(stack_line_reader_test stack_line_reader_for_test)
|
||||||
add_test(NAME stack_line_reader_test COMMAND stack_line_reader_test)
|
add_test(NAME stack_line_reader_test COMMAND stack_line_reader_test)
|
||||||
##------------------------------------------------------------------------------
|
##------------------------------------------------------------------------------
|
||||||
## unix_features_aggregator_test
|
|
||||||
add_executable(unix_features_aggregator_test unix_features_aggregator_test.cc)
|
|
||||||
target_link_libraries(unix_features_aggregator_test all_libraries)
|
|
||||||
add_test(NAME unix_features_aggregator_test COMMAND unix_features_aggregator_test)
|
|
||||||
##------------------------------------------------------------------------------
|
|
||||||
## cpuinfo_x86_test
|
## cpuinfo_x86_test
|
||||||
if(PROCESSOR_IS_X86)
|
if(PROCESSOR_IS_X86)
|
||||||
add_executable(cpuinfo_x86_test cpuinfo_x86_test.cc ../src/cpuinfo_x86.c)
|
add_executable(cpuinfo_x86_test cpuinfo_x86_test.cc ../src/cpuinfo_x86.c)
|
||||||
target_compile_definitions(cpuinfo_x86_test PUBLIC CPU_FEATURES_MOCK_CPUID_X86)
|
target_compile_definitions(cpuinfo_x86_test PUBLIC CPU_FEATURES_MOCK_CPUID_X86)
|
||||||
|
if(APPLE)
|
||||||
|
target_compile_definitions(cpuinfo_x86_test PRIVATE HAVE_SYSCTLBYNAME)
|
||||||
|
endif()
|
||||||
target_link_libraries(cpuinfo_x86_test all_libraries)
|
target_link_libraries(cpuinfo_x86_test all_libraries)
|
||||||
add_test(NAME cpuinfo_x86_test COMMAND cpuinfo_x86_test)
|
add_test(NAME cpuinfo_x86_test COMMAND cpuinfo_x86_test)
|
||||||
endif()
|
endif()
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
// SPDX-FileCopyrightText: 2017 Google Inc.
|
// SPDX-FileCopyrightText: 2017 Google LLC
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
#include "gtest/gtest.h"
|
#include "gtest/gtest.h"
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
// SPDX-FileCopyrightText: 2017 Google Inc.
|
// SPDX-FileCopyrightText: 2017 Google LLC
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
#include "cpuinfo_aarch64.h"
|
#include "cpuinfo_aarch64.h"
|
||||||
@ -51,6 +51,35 @@ TEST(CpuinfoAarch64Test, FromHardwareCap)
|
|||||||
EXPECT_FALSE(info.features.pacg);
|
EXPECT_FALSE(info.features.pacg);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST(CpuinfoAarch64Test, FromHardwareCap2)
|
||||||
|
{
|
||||||
|
SetHardwareCapabilities(AARCH64_HWCAP_FP,
|
||||||
|
AARCH64_HWCAP2_SVE2 | AARCH64_HWCAP2_BTI);
|
||||||
|
GetEmptyFilesystem(); // disabling /proc/cpuinfo
|
||||||
|
const auto info = GetAarch64Info();
|
||||||
|
EXPECT_TRUE(info.features.fp);
|
||||||
|
|
||||||
|
EXPECT_TRUE(info.features.sve2);
|
||||||
|
EXPECT_TRUE(info.features.bti);
|
||||||
|
|
||||||
|
EXPECT_FALSE(info.features.dcpodp);
|
||||||
|
EXPECT_FALSE(info.features.sveaes);
|
||||||
|
EXPECT_FALSE(info.features.svepmull);
|
||||||
|
EXPECT_FALSE(info.features.svebitperm);
|
||||||
|
EXPECT_FALSE(info.features.svesha3);
|
||||||
|
EXPECT_FALSE(info.features.svesm4);
|
||||||
|
EXPECT_FALSE(info.features.flagm2);
|
||||||
|
EXPECT_FALSE(info.features.frint);
|
||||||
|
EXPECT_FALSE(info.features.svei8mm);
|
||||||
|
EXPECT_FALSE(info.features.svef32mm);
|
||||||
|
EXPECT_FALSE(info.features.svef64mm);
|
||||||
|
EXPECT_FALSE(info.features.svebf16);
|
||||||
|
EXPECT_FALSE(info.features.i8mm);
|
||||||
|
EXPECT_FALSE(info.features.bf16);
|
||||||
|
EXPECT_FALSE(info.features.dgh);
|
||||||
|
EXPECT_FALSE(info.features.rng);
|
||||||
|
}
|
||||||
|
|
||||||
TEST(CpuinfoAarch64Test, ARMCortexA53)
|
TEST(CpuinfoAarch64Test, ARMCortexA53)
|
||||||
{
|
{
|
||||||
DisableHardwareCapabilities();
|
DisableHardwareCapabilities();
|
||||||
@ -110,6 +139,24 @@ CPU revision : 3)");
|
|||||||
EXPECT_FALSE(info.features.sb);
|
EXPECT_FALSE(info.features.sb);
|
||||||
EXPECT_FALSE(info.features.paca);
|
EXPECT_FALSE(info.features.paca);
|
||||||
EXPECT_FALSE(info.features.pacg);
|
EXPECT_FALSE(info.features.pacg);
|
||||||
|
EXPECT_FALSE(info.features.dcpodp);
|
||||||
|
EXPECT_FALSE(info.features.sve2);
|
||||||
|
EXPECT_FALSE(info.features.sveaes);
|
||||||
|
EXPECT_FALSE(info.features.svepmull);
|
||||||
|
EXPECT_FALSE(info.features.svebitperm);
|
||||||
|
EXPECT_FALSE(info.features.svesha3);
|
||||||
|
EXPECT_FALSE(info.features.svesm4);
|
||||||
|
EXPECT_FALSE(info.features.flagm2);
|
||||||
|
EXPECT_FALSE(info.features.frint);
|
||||||
|
EXPECT_FALSE(info.features.svei8mm);
|
||||||
|
EXPECT_FALSE(info.features.svef32mm);
|
||||||
|
EXPECT_FALSE(info.features.svef64mm);
|
||||||
|
EXPECT_FALSE(info.features.svebf16);
|
||||||
|
EXPECT_FALSE(info.features.i8mm);
|
||||||
|
EXPECT_FALSE(info.features.bf16);
|
||||||
|
EXPECT_FALSE(info.features.dgh);
|
||||||
|
EXPECT_FALSE(info.features.rng);
|
||||||
|
EXPECT_FALSE(info.features.bti);
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
// SPDX-FileCopyrightText: 2017 Google Inc.
|
// SPDX-FileCopyrightText: 2017 Google LLC
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
#include "cpuinfo_arm.h"
|
#include "cpuinfo_arm.h"
|
||||||
@ -104,7 +104,6 @@ CPU architecture: 7
|
|||||||
CPU variant : 0x0
|
CPU variant : 0x0
|
||||||
CPU part : 0xb76
|
CPU part : 0xb76
|
||||||
CPU revision : 7
|
CPU revision : 7
|
||||||
|
|
||||||
Hardware : BCM2835
|
Hardware : BCM2835
|
||||||
Revision : 9000c1
|
Revision : 9000c1
|
||||||
Serial : 000000006cd946f3)");
|
Serial : 000000006cd946f3)");
|
||||||
@ -157,7 +156,6 @@ CPU architecture: 7
|
|||||||
CPU variant : 0x4
|
CPU variant : 0x4
|
||||||
CPU part : 0xc09
|
CPU part : 0xc09
|
||||||
CPU revision : 1
|
CPU revision : 1
|
||||||
|
|
||||||
processor : 1
|
processor : 1
|
||||||
model name : ARMv7 Processor rev 1 (v7l)
|
model name : ARMv7 Processor rev 1 (v7l)
|
||||||
BogoMIPS : 50.00
|
BogoMIPS : 50.00
|
||||||
@ -167,7 +165,6 @@ CPU architecture: 7
|
|||||||
CPU variant : 0x4
|
CPU variant : 0x4
|
||||||
CPU part : 0xc09
|
CPU part : 0xc09
|
||||||
CPU revision : 1
|
CPU revision : 1
|
||||||
|
|
||||||
Hardware : Marvell Armada 380/385 (Device Tree)
|
Hardware : Marvell Armada 380/385 (Device Tree)
|
||||||
Revision : 0000
|
Revision : 0000
|
||||||
Serial : 0000000000000000)");
|
Serial : 0000000000000000)");
|
||||||
@ -222,7 +219,6 @@ CPU architecture: 7
|
|||||||
CPU variant : 0x0
|
CPU variant : 0x0
|
||||||
CPU part : 0xb76
|
CPU part : 0xb76
|
||||||
CPU revision : 6
|
CPU revision : 6
|
||||||
|
|
||||||
Hardware : SPICA
|
Hardware : SPICA
|
||||||
Revision : 0020
|
Revision : 0020
|
||||||
Serial : 33323613546d00ec )");
|
Serial : 33323613546d00ec )");
|
||||||
@ -267,17 +263,14 @@ TEST(CpuinfoArmTest, InvalidNeon)
|
|||||||
R"(Processor: ARMv7 Processory rev 0 (v71)
|
R"(Processor: ARMv7 Processory rev 0 (v71)
|
||||||
processor: 0
|
processor: 0
|
||||||
BogoMIPS: 13.50
|
BogoMIPS: 13.50
|
||||||
|
|
||||||
Processor: 1
|
Processor: 1
|
||||||
BogoMIPS: 13.50
|
BogoMIPS: 13.50
|
||||||
|
|
||||||
Features: swp half thumb fastmult vfp edsp neon vfpv3 tls vfpv4 idiva idivt
|
Features: swp half thumb fastmult vfp edsp neon vfpv3 tls vfpv4 idiva idivt
|
||||||
CPU implementer : 0x51
|
CPU implementer : 0x51
|
||||||
CPU architecture: 7
|
CPU architecture: 7
|
||||||
CPU variant: 0x1
|
CPU variant: 0x1
|
||||||
CPU part: 0x04d
|
CPU part: 0x04d
|
||||||
CPU revision: 0
|
CPU revision: 0
|
||||||
|
|
||||||
Hardware: SAMSUNG M2
|
Hardware: SAMSUNG M2
|
||||||
Revision: 0010
|
Revision: 0010
|
||||||
Serial: 00001e030000354e)");
|
Serial: 00001e030000354e)");
|
||||||
@ -340,7 +333,6 @@ CPU architecture: 7
|
|||||||
CPU variant : 0x0
|
CPU variant : 0x0
|
||||||
CPU part : 0xc08
|
CPU part : 0xc08
|
||||||
CPU revision : 0
|
CPU revision : 0
|
||||||
|
|
||||||
Hardware : Goldfish
|
Hardware : Goldfish
|
||||||
Revision : 0000
|
Revision : 0000
|
||||||
Serial : 0000000000000000)");
|
Serial : 0000000000000000)");
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
// SPDX-FileCopyrightText: 2017 Google Inc.
|
// SPDX-FileCopyrightText: 2017 Google LLC
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
#include "cpuinfo_mips.h"
|
#include "cpuinfo_mips.h"
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
// SPDX-FileCopyrightText: 2017 Google Inc.
|
// SPDX-FileCopyrightText: 2017 Google LLC
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
#include "cpuinfo_ppc.h"
|
#include "cpuinfo_ppc.h"
|
||||||
@ -38,12 +38,10 @@ TEST(CpustringsPPCTest, Blade)
|
|||||||
cpu : POWER7 (architected), altivec supported
|
cpu : POWER7 (architected), altivec supported
|
||||||
clock : 3000.000000MHz
|
clock : 3000.000000MHz
|
||||||
revision : 2.1 (pvr 003f 0201)
|
revision : 2.1 (pvr 003f 0201)
|
||||||
|
|
||||||
processor : 15
|
processor : 15
|
||||||
cpu : POWER7 (architected), altivec supported
|
cpu : POWER7 (architected), altivec supported
|
||||||
clock : 3000.000000MHz
|
clock : 3000.000000MHz
|
||||||
revision : 2.1 (pvr 003f 0201)
|
revision : 2.1 (pvr 003f 0201)
|
||||||
|
|
||||||
timebase : 512000000
|
timebase : 512000000
|
||||||
platform : pSeries
|
platform : pSeries
|
||||||
model : IBM,8406-70Y
|
model : IBM,8406-70Y
|
||||||
@ -67,12 +65,10 @@ TEST(CpustringsPPCTest, Firestone)
|
|||||||
cpu : POWER8 (raw), altivec supported
|
cpu : POWER8 (raw), altivec supported
|
||||||
clock : 2061.000000MHz
|
clock : 2061.000000MHz
|
||||||
revision : 2.0 (pvr 004d 0200)
|
revision : 2.0 (pvr 004d 0200)
|
||||||
|
|
||||||
processor : 127
|
processor : 127
|
||||||
cpu : POWER8 (raw), altivec supported
|
cpu : POWER8 (raw), altivec supported
|
||||||
clock : 2061.000000MHz
|
clock : 2061.000000MHz
|
||||||
revision : 2.0 (pvr 004d 0200)
|
revision : 2.0 (pvr 004d 0200)
|
||||||
|
|
||||||
timebase : 512000000
|
timebase : 512000000
|
||||||
platform : PowerNV
|
platform : PowerNV
|
||||||
model : 8335-GTA
|
model : 8335-GTA
|
||||||
@ -94,7 +90,6 @@ TEST(CpustringsPPCTest, w8)
|
|||||||
cpu : POWER9, altivec supported
|
cpu : POWER9, altivec supported
|
||||||
clock : 2300.000000MHz
|
clock : 2300.000000MHz
|
||||||
revision : 2.2 (pvr 004e 1202)
|
revision : 2.2 (pvr 004e 1202)
|
||||||
|
|
||||||
timebase : 512000000
|
timebase : 512000000
|
||||||
platform : PowerNV
|
platform : PowerNV
|
||||||
model : 0000000000000000
|
model : 0000000000000000
|
||||||
|
@ -1,19 +1,25 @@
|
|||||||
// SPDX-FileCopyrightText: 2017 Google Inc.
|
// SPDX-FileCopyrightText: 2017 Google LLC
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
#include "cpuinfo_x86.h"
|
#include "cpuinfo_x86.h"
|
||||||
#include "gtest/gtest.h"
|
|
||||||
#include "internal/cpuid_x86.h"
|
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
#include <cstdio>
|
#include <cstdio>
|
||||||
#include <map>
|
#include <map>
|
||||||
|
#include <set>
|
||||||
|
#if defined(CPU_FEATURES_OS_WINDOWS)
|
||||||
|
#include <windows.h> // IsProcessorFeaturePresent
|
||||||
|
#endif // CPU_FEATURES_OS_WINDOWS
|
||||||
|
|
||||||
|
#include "filesystem_for_testing.h"
|
||||||
|
#include "gtest/gtest.h"
|
||||||
|
#include "internal/cpuid_x86.h"
|
||||||
|
|
||||||
namespace cpu_features
|
namespace cpu_features
|
||||||
{
|
{
|
||||||
class FakeCpu
|
class FakeCpu
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
Leaf CpuIdEx(uint32_t leaf_id, int ecx) const
|
Leaf GetCpuidLeaf(uint32_t leaf_id, int ecx) const
|
||||||
{
|
{
|
||||||
const auto itr = cpuid_leaves_.find(std::make_pair(leaf_id, ecx));
|
const auto itr = cpuid_leaves_.find(std::make_pair(leaf_id, ecx));
|
||||||
if (itr != cpuid_leaves_.end())
|
if (itr != cpuid_leaves_.end())
|
||||||
@ -35,23 +41,74 @@ public:
|
|||||||
xcr0_eax_ = os_backups_extended_registers ? -1 : 0;
|
xcr0_eax_ = os_backups_extended_registers ? -1 : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if defined(CPU_FEATURES_OS_DARWIN)
|
||||||
|
bool GetDarwinSysCtlByName(std::string name) const
|
||||||
|
{
|
||||||
|
return darwin_sysctlbyname_.count(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SetDarwinSysCtlByName(std::string name)
|
||||||
|
{
|
||||||
|
darwin_sysctlbyname_.insert(name);
|
||||||
|
}
|
||||||
|
#endif // CPU_FEATURES_OS_DARWIN
|
||||||
|
|
||||||
|
#if defined(CPU_FEATURES_OS_WINDOWS)
|
||||||
|
bool GetWindowsIsProcessorFeaturePresent(DWORD ProcessorFeature)
|
||||||
|
{
|
||||||
|
return windows_isprocessorfeaturepresent_.count(ProcessorFeature);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SetWindowsIsProcessorFeaturePresent(DWORD ProcessorFeature)
|
||||||
|
{
|
||||||
|
windows_isprocessorfeaturepresent_.insert(ProcessorFeature);
|
||||||
|
}
|
||||||
|
#endif // CPU_FEATURES_OS_WINDOWS
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::map<std::pair<uint32_t, int>, Leaf> cpuid_leaves_;
|
std::map<std::pair<uint32_t, int>, Leaf> cpuid_leaves_;
|
||||||
|
#if defined(CPU_FEATURES_OS_DARWIN)
|
||||||
|
std::set<std::string> darwin_sysctlbyname_;
|
||||||
|
#endif // CPU_FEATURES_OS_DARWIN
|
||||||
|
#if defined(CPU_FEATURES_OS_WINDOWS)
|
||||||
|
std::set<DWORD> windows_isprocessorfeaturepresent_;
|
||||||
|
#endif // CPU_FEATURES_OS_WINDOWS
|
||||||
uint32_t xcr0_eax_;
|
uint32_t xcr0_eax_;
|
||||||
};
|
};
|
||||||
|
|
||||||
auto* g_fake_cpu = new FakeCpu();
|
FakeCpu* g_fake_cpu = nullptr;
|
||||||
|
|
||||||
extern "C" Leaf CpuIdEx(uint32_t leaf_id, int ecx)
|
extern "C" Leaf GetCpuidLeaf(uint32_t leaf_id, int ecx)
|
||||||
{
|
{
|
||||||
return g_fake_cpu->CpuIdEx(leaf_id, ecx);
|
return g_fake_cpu->GetCpuidLeaf(leaf_id, ecx);
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C" uint32_t GetXCR0Eax(void) { return g_fake_cpu->GetXCR0Eax(); }
|
extern "C" uint32_t GetXCR0Eax(void) { return g_fake_cpu->GetXCR0Eax(); }
|
||||||
|
|
||||||
|
#if defined(CPU_FEATURES_OS_DARWIN)
|
||||||
|
extern "C" bool GetDarwinSysCtlByName(const char* name)
|
||||||
|
{
|
||||||
|
return g_fake_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);
|
||||||
|
}
|
||||||
|
#endif // CPU_FEATURES_OS_WINDOWS
|
||||||
|
|
||||||
namespace
|
namespace
|
||||||
{
|
{
|
||||||
TEST(CpuidX86Test, SandyBridge)
|
class CpuidX86Test : public ::testing::Test
|
||||||
|
{
|
||||||
|
protected:
|
||||||
|
void SetUp() override { g_fake_cpu = new FakeCpu(); }
|
||||||
|
void TearDown() override { delete g_fake_cpu; }
|
||||||
|
};
|
||||||
|
|
||||||
|
TEST_F(CpuidX86Test, SandyBridge)
|
||||||
{
|
{
|
||||||
g_fake_cpu->SetOsBackupsExtendedRegisters(true);
|
g_fake_cpu->SetOsBackupsExtendedRegisters(true);
|
||||||
g_fake_cpu->SetLeaves({
|
g_fake_cpu->SetLeaves({
|
||||||
@ -82,7 +139,7 @@ TEST(CpuidX86Test, SandyBridge)
|
|||||||
EXPECT_FALSE(features.avx512bitalg);
|
EXPECT_FALSE(features.avx512bitalg);
|
||||||
EXPECT_FALSE(features.avx512vpopcntdq);
|
EXPECT_FALSE(features.avx512vpopcntdq);
|
||||||
EXPECT_FALSE(features.avx512_4vnniw);
|
EXPECT_FALSE(features.avx512_4vnniw);
|
||||||
EXPECT_FALSE(features.avx512_4vbmi2);
|
EXPECT_FALSE(features.avx512_4fmaps);
|
||||||
// All old cpu features should be set.
|
// All old cpu features should be set.
|
||||||
EXPECT_TRUE(features.aes);
|
EXPECT_TRUE(features.aes);
|
||||||
EXPECT_TRUE(features.ssse3);
|
EXPECT_TRUE(features.ssse3);
|
||||||
@ -98,7 +155,7 @@ TEST(CpuidX86Test, SandyBridge)
|
|||||||
const int KiB = 1024;
|
const int KiB = 1024;
|
||||||
const int MiB = 1024 * KiB;
|
const int MiB = 1024 * KiB;
|
||||||
|
|
||||||
TEST(CpuidX86Test, SandyBridgeTestOsSupport)
|
TEST_F(CpuidX86Test, SandyBridgeTestOsSupport)
|
||||||
{
|
{
|
||||||
g_fake_cpu->SetLeaves({
|
g_fake_cpu->SetLeaves({
|
||||||
{{0x00000000, 0}, Leaf{0x0000000D, 0x756E6547, 0x6C65746E, 0x49656E69}},
|
{{0x00000000, 0}, Leaf{0x0000000D, 0x756E6547, 0x6C65746E, 0x49656E69}},
|
||||||
@ -113,7 +170,7 @@ TEST(CpuidX86Test, SandyBridgeTestOsSupport)
|
|||||||
EXPECT_TRUE(GetX86Info().features.avx);
|
EXPECT_TRUE(GetX86Info().features.avx);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(CpuidX86Test, SkyLake)
|
TEST_F(CpuidX86Test, SkyLake)
|
||||||
{
|
{
|
||||||
g_fake_cpu->SetOsBackupsExtendedRegisters(true);
|
g_fake_cpu->SetOsBackupsExtendedRegisters(true);
|
||||||
g_fake_cpu->SetLeaves({
|
g_fake_cpu->SetLeaves({
|
||||||
@ -129,7 +186,7 @@ TEST(CpuidX86Test, SkyLake)
|
|||||||
EXPECT_EQ(GetX86Microarchitecture(&info), X86Microarchitecture::INTEL_SKL);
|
EXPECT_EQ(GetX86Microarchitecture(&info), X86Microarchitecture::INTEL_SKL);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(CpuidX86Test, Branding)
|
TEST_F(CpuidX86Test, Branding)
|
||||||
{
|
{
|
||||||
g_fake_cpu->SetLeaves({
|
g_fake_cpu->SetLeaves({
|
||||||
{{0x00000000, 0}, Leaf{0x00000016, 0x756E6547, 0x6C65746E, 0x49656E69}},
|
{{0x00000000, 0}, Leaf{0x00000016, 0x756E6547, 0x6C65746E, 0x49656E69}},
|
||||||
@ -146,7 +203,7 @@ TEST(CpuidX86Test, Branding)
|
|||||||
EXPECT_STREQ(brand_string, "Intel(R) Core(TM) i7-6500U CPU @ 2.50GHz");
|
EXPECT_STREQ(brand_string, "Intel(R) Core(TM) i7-6500U CPU @ 2.50GHz");
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(CpuidX86Test, KabyLakeCache)
|
TEST_F(CpuidX86Test, KabyLakeCache)
|
||||||
{
|
{
|
||||||
g_fake_cpu->SetLeaves({
|
g_fake_cpu->SetLeaves({
|
||||||
{{0x00000000, 0}, Leaf{0x00000016, 0x756E6547, 0x6C65746E, 0x49656E69}},
|
{{0x00000000, 0}, Leaf{0x00000016, 0x756E6547, 0x6C65746E, 0x49656E69}},
|
||||||
@ -196,7 +253,7 @@ TEST(CpuidX86Test, KabyLakeCache)
|
|||||||
EXPECT_EQ(info.levels[3].partitioning, 1);
|
EXPECT_EQ(info.levels[3].partitioning, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(CpuidX86Test, HSWCache)
|
TEST_F(CpuidX86Test, HSWCache)
|
||||||
{
|
{
|
||||||
g_fake_cpu->SetLeaves({
|
g_fake_cpu->SetLeaves({
|
||||||
{{0x00000000, 0}, Leaf{0x00000016, 0x756E6547, 0x6C65746E, 0x49656E69}},
|
{{0x00000000, 0}, Leaf{0x00000016, 0x756E6547, 0x6C65746E, 0x49656E69}},
|
||||||
@ -245,8 +302,9 @@ TEST(CpuidX86Test, HSWCache)
|
|||||||
EXPECT_EQ(info.levels[3].tlb_entries, 8192);
|
EXPECT_EQ(info.levels[3].tlb_entries, 8192);
|
||||||
EXPECT_EQ(info.levels[3].partitioning, 1);
|
EXPECT_EQ(info.levels[3].partitioning, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
// http://users.atw.hu/instlatx64/AuthenticAMD0630F81_K15_Godavari_CPUID.txt
|
// http://users.atw.hu/instlatx64/AuthenticAMD0630F81_K15_Godavari_CPUID.txt
|
||||||
TEST(CpuidX86Test, AMD_K15)
|
TEST_F(CpuidX86Test, AMD_K15)
|
||||||
{
|
{
|
||||||
g_fake_cpu->SetLeaves({
|
g_fake_cpu->SetLeaves({
|
||||||
{{0x00000000, 0}, Leaf{0x0000000D, 0x68747541, 0x444D4163, 0x69746E65}},
|
{{0x00000000, 0}, Leaf{0x0000000D, 0x68747541, 0x444D4163, 0x69746E65}},
|
||||||
@ -273,6 +331,211 @@ TEST(CpuidX86Test, AMD_K15)
|
|||||||
EXPECT_STREQ(brand_string, "AMD A8-7670K Radeon R7, 10 Compute Cores 4C+6G ");
|
EXPECT_STREQ(brand_string, "AMD A8-7670K Radeon R7, 10 Compute Cores 4C+6G ");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// https://github.com/InstLatx64/InstLatx64/blob/master/GenuineIntel/GenuineIntel00106A1_Nehalem_CPUID.txt
|
||||||
|
TEST_F(CpuidX86Test, Nehalem)
|
||||||
|
{
|
||||||
|
// Pre AVX cpus don't have xsave
|
||||||
|
g_fake_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);
|
||||||
|
#endif // CPU_FEATURES_OS_WINDOWS
|
||||||
|
#if 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)
|
||||||
|
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
|
||||||
|
g_fake_cpu->SetLeaves({
|
||||||
|
{{0x00000000, 0}, Leaf{0x0000000B, 0x756E6547, 0x6C65746E, 0x49656E69}},
|
||||||
|
{{0x00000001, 0}, Leaf{0x000106A2, 0x00100800, 0x00BCE3BD, 0xBFEBFBFF}},
|
||||||
|
{{0x00000002, 0}, Leaf{0x55035A01, 0x00F0B0E3, 0x00000000, 0x09CA212C}},
|
||||||
|
{{0x00000003, 0}, Leaf{0x00000000, 0x00000000, 0x00000000, 0x00000000}},
|
||||||
|
{{0x00000004, 0}, Leaf{0x1C004121, 0x01C0003F, 0x0000003F, 0x00000000}},
|
||||||
|
{{0x00000004, 0}, Leaf{0x1C004122, 0x00C0003F, 0x0000007F, 0x00000000}},
|
||||||
|
{{0x00000004, 0}, Leaf{0x1C004143, 0x01C0003F, 0x000001FF, 0x00000000}},
|
||||||
|
{{0x00000004, 0}, Leaf{0x1C03C163, 0x03C0003F, 0x00000FFF, 0x00000002}},
|
||||||
|
{{0x00000005, 0}, Leaf{0x00000040, 0x00000040, 0x00000003, 0x00021120}},
|
||||||
|
{{0x00000006, 0}, Leaf{0x00000001, 0x00000002, 0x00000001, 0x00000000}},
|
||||||
|
{{0x00000007, 0}, Leaf{0x00000000, 0x00000000, 0x00000000, 0x00000000}},
|
||||||
|
{{0x00000008, 0}, Leaf{0x00000000, 0x00000000, 0x00000000, 0x00000000}},
|
||||||
|
{{0x00000009, 0}, Leaf{0x00000000, 0x00000000, 0x00000000, 0x00000000}},
|
||||||
|
{{0x0000000A, 0}, Leaf{0x07300403, 0x00000000, 0x00000000, 0x00000603}},
|
||||||
|
{{0x0000000B, 0}, Leaf{0x00000001, 0x00000001, 0x00000100, 0x00000000}},
|
||||||
|
{{0x0000000B, 0}, Leaf{0x00000004, 0x00000002, 0x00000201, 0x00000000}},
|
||||||
|
{{0x80000000, 0}, Leaf{0x80000008, 0x00000000, 0x00000000, 0x00000000}},
|
||||||
|
{{0x80000001, 0}, Leaf{0x00000000, 0x00000000, 0x00000001, 0x28100000}},
|
||||||
|
{{0x80000002, 0}, Leaf{0x756E6547, 0x20656E69, 0x65746E49, 0x2952286C}},
|
||||||
|
{{0x80000003, 0}, Leaf{0x55504320, 0x20202020, 0x20202020, 0x40202020}},
|
||||||
|
{{0x80000004, 0}, Leaf{0x30303020, 0x20402030, 0x37382E31, 0x007A4847}},
|
||||||
|
{{0x80000005, 0}, Leaf{0x00000000, 0x00000000, 0x00000000, 0x00000000}},
|
||||||
|
{{0x80000006, 0}, Leaf{0x00000000, 0x00000000, 0x01006040, 0x00000000}},
|
||||||
|
{{0x80000007, 0}, Leaf{0x00000000, 0x00000000, 0x00000000, 0x00000100}},
|
||||||
|
{{0x80000008, 0}, Leaf{0x00003028, 0x00000000, 0x00000000, 0x00000000}},
|
||||||
|
});
|
||||||
|
const auto info = GetX86Info();
|
||||||
|
|
||||||
|
EXPECT_STREQ(info.vendor, "GenuineIntel");
|
||||||
|
EXPECT_EQ(info.family, 0x06);
|
||||||
|
EXPECT_EQ(info.model, 0x1A);
|
||||||
|
EXPECT_EQ(info.stepping, 0x02);
|
||||||
|
EXPECT_EQ(GetX86Microarchitecture(&info), X86Microarchitecture::INTEL_NHM);
|
||||||
|
|
||||||
|
char brand_string[49];
|
||||||
|
FillX86BrandString(brand_string);
|
||||||
|
EXPECT_STREQ(brand_string, "Genuine Intel(R) CPU @ 0000 @ 1.87GHz");
|
||||||
|
|
||||||
|
EXPECT_TRUE(info.features.sse);
|
||||||
|
EXPECT_TRUE(info.features.sse2);
|
||||||
|
EXPECT_TRUE(info.features.sse3);
|
||||||
|
#ifndef 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
|
||||||
|
}
|
||||||
|
|
||||||
|
// https://github.com/InstLatx64/InstLatx64/blob/master/GenuineIntel/GenuineIntel0030673_Silvermont3_CPUID.txt
|
||||||
|
TEST_F(CpuidX86Test, Atom)
|
||||||
|
{
|
||||||
|
// Pre AVX cpus don't have xsave
|
||||||
|
g_fake_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);
|
||||||
|
#endif // CPU_FEATURES_OS_WINDOWS
|
||||||
|
#if 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)
|
||||||
|
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
|
||||||
|
g_fake_cpu->SetLeaves({
|
||||||
|
{{0x00000000, 0}, Leaf{0x0000000B, 0x756E6547, 0x6C65746E, 0x49656E69}},
|
||||||
|
{{0x00000001, 0}, Leaf{0x00030673, 0x00100800, 0x41D8E3BF, 0xBFEBFBFF}},
|
||||||
|
{{0x00000002, 0}, Leaf{0x61B3A001, 0x0000FFC2, 0x00000000, 0x00000000}},
|
||||||
|
{{0x00000003, 0}, Leaf{0x00000000, 0x00000000, 0x00000000, 0x00000000}},
|
||||||
|
{{0x00000004, 0}, Leaf{0x1C000121, 0x0140003F, 0x0000003F, 0x00000001}},
|
||||||
|
{{0x00000004, 1}, Leaf{0x1C000122, 0x01C0003F, 0x0000003F, 0x00000001}},
|
||||||
|
{{0x00000004, 2}, Leaf{0x1C00C143, 0x03C0003F, 0x000003FF, 0x00000001}},
|
||||||
|
{{0x00000005, 0}, Leaf{0x00000040, 0x00000040, 0x00000003, 0x33000020}},
|
||||||
|
{{0x00000006, 0}, Leaf{0x00000005, 0x00000002, 0x00000009, 0x00000000}},
|
||||||
|
{{0x00000007, 0}, Leaf{0x00000000, 0x00002282, 0x00000000, 0x00000000}},
|
||||||
|
{{0x00000008, 0}, Leaf{0x00000000, 0x00000000, 0x00000000, 0x00000000}},
|
||||||
|
{{0x00000009, 0}, Leaf{0x00000000, 0x00000000, 0x00000000, 0x00000000}},
|
||||||
|
{{0x0000000A, 0}, Leaf{0x07280203, 0x00000000, 0x00000000, 0x00004503}},
|
||||||
|
{{0x0000000B, 0}, Leaf{0x00000001, 0x00000001, 0x00000100, 0x00000000}},
|
||||||
|
{{0x0000000B, 1}, Leaf{0x00000004, 0x00000004, 0x00000201, 0x00000000}},
|
||||||
|
{{0x80000000, 0}, Leaf{0x80000008, 0x00000000, 0x00000000, 0x00000000}},
|
||||||
|
{{0x80000001, 0}, Leaf{0x00000000, 0x00000000, 0x00000101, 0x28100000}},
|
||||||
|
{{0x80000002, 0}, Leaf{0x20202020, 0x6E492020, 0x286C6574, 0x43202952}},
|
||||||
|
{{0x80000003, 0}, Leaf{0x72656C65, 0x52286E6F, 0x50432029, 0x4A202055}},
|
||||||
|
{{0x80000004, 0}, Leaf{0x30303931, 0x20402020, 0x39392E31, 0x007A4847}},
|
||||||
|
{{0x80000005, 0}, Leaf{0x00000000, 0x00000000, 0x00000000, 0x00000000}},
|
||||||
|
{{0x80000006, 0}, Leaf{0x00000000, 0x00000000, 0x04008040, 0x00000000}},
|
||||||
|
{{0x80000007, 0}, Leaf{0x00000000, 0x00000000, 0x00000000, 0x00000100}},
|
||||||
|
{{0x80000008, 0}, Leaf{0x00003024, 0x00000000, 0x00000000, 0x00000000}},
|
||||||
|
});
|
||||||
|
const auto info = GetX86Info();
|
||||||
|
|
||||||
|
EXPECT_STREQ(info.vendor, "GenuineIntel");
|
||||||
|
EXPECT_EQ(info.family, 0x06);
|
||||||
|
EXPECT_EQ(info.model, 0x37);
|
||||||
|
EXPECT_EQ(info.stepping, 0x03);
|
||||||
|
EXPECT_EQ(GetX86Microarchitecture(&info),
|
||||||
|
X86Microarchitecture::INTEL_ATOM_SMT);
|
||||||
|
|
||||||
|
char brand_string[49];
|
||||||
|
FillX86BrandString(brand_string);
|
||||||
|
EXPECT_STREQ(brand_string, " Intel(R) Celeron(R) CPU J1900 @ 1.99GHz");
|
||||||
|
|
||||||
|
EXPECT_TRUE(info.features.sse);
|
||||||
|
EXPECT_TRUE(info.features.sse2);
|
||||||
|
EXPECT_TRUE(info.features.sse3);
|
||||||
|
#ifndef 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
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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);
|
||||||
|
#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)
|
||||||
|
g_fake_cpu->SetDarwinSysCtlByName("hw.optional.sse");
|
||||||
|
#endif // CPU_FEATURES_OS_DARWIN
|
||||||
|
#if 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
|
||||||
|
g_fake_cpu->SetLeaves({
|
||||||
|
{{0x00000000, 0}, Leaf{0x00000003, 0x756E6547, 0x6C65746E, 0x49656E69}},
|
||||||
|
{{0x00000001, 0}, Leaf{0x00000673, 0x00000000, 0x00000000, 0x0387FBFF}},
|
||||||
|
{{0x00000002, 0}, Leaf{0x03020101, 0x00000000, 0x00000000, 0x0C040843}},
|
||||||
|
{{0x00000003, 0}, Leaf{0x00000000, 0x00000000, 0x4CECC782, 0x00006778}},
|
||||||
|
});
|
||||||
|
const auto info = GetX86Info();
|
||||||
|
|
||||||
|
EXPECT_STREQ(info.vendor, "GenuineIntel");
|
||||||
|
EXPECT_EQ(info.family, 0x06);
|
||||||
|
EXPECT_EQ(info.model, 0x07);
|
||||||
|
EXPECT_EQ(info.stepping, 0x03);
|
||||||
|
EXPECT_EQ(GetX86Microarchitecture(&info), X86Microarchitecture::X86_UNKNOWN);
|
||||||
|
|
||||||
|
char brand_string[49];
|
||||||
|
FillX86BrandString(brand_string);
|
||||||
|
EXPECT_STREQ(brand_string, "");
|
||||||
|
|
||||||
|
EXPECT_TRUE(info.features.mmx);
|
||||||
|
EXPECT_TRUE(info.features.sse);
|
||||||
|
EXPECT_FALSE(info.features.sse2);
|
||||||
|
EXPECT_FALSE(info.features.sse3);
|
||||||
|
#ifndef 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
|
||||||
|
}
|
||||||
|
|
||||||
// TODO(user): test what happens when xsave/osxsave are not present.
|
// TODO(user): test what happens when xsave/osxsave are not present.
|
||||||
// TODO(user): test what happens when xmm/ymm/zmm os support are not
|
// TODO(user): test what happens when xmm/ymm/zmm os support are not
|
||||||
// present.
|
// present.
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
// SPDX-FileCopyrightText: 2017 Google Inc.
|
// SPDX-FileCopyrightText: 2017 Google LLC
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
#include "filesystem_for_testing.h"
|
#include "filesystem_for_testing.h"
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
// SPDX-FileCopyrightText: 2017 Google Inc.
|
// SPDX-FileCopyrightText: 2017 Google LLC
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
// Implements a fake filesystem, useful for tests.
|
// Implements a fake filesystem, useful for tests.
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
// SPDX-FileCopyrightText: 2017 Google Inc.
|
// SPDX-FileCopyrightText: 2017 Google LLC
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
#include "hwcaps_for_testing.h"
|
#include "hwcaps_for_testing.h"
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
// SPDX-FileCopyrightText: 2017 Google Inc.
|
// SPDX-FileCopyrightText: 2017 Google LLC
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
#ifndef CPU_FEATURES_TEST_HWCAPS_FOR_TESTING_H_
|
#ifndef CPU_FEATURES_TEST_HWCAPS_FOR_TESTING_H_
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
// SPDX-FileCopyrightText: 2017 Google Inc.
|
// SPDX-FileCopyrightText: 2017 Google LLC
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
#include "filesystem_for_testing.h"
|
#include "filesystem_for_testing.h"
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
// SPDX-FileCopyrightText: 2017 Google Inc.
|
// SPDX-FileCopyrightText: 2017 Google LLC
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
#include "gtest/gtest.h"
|
#include "gtest/gtest.h"
|
||||||
@ -30,6 +30,8 @@ TEST(StringViewTest, CpuFeatures_StringView_IndexOfChar)
|
|||||||
{
|
{
|
||||||
// Found.
|
// Found.
|
||||||
EXPECT_EQ(CpuFeatures_StringView_IndexOfChar(str("test"), 'e'), 1);
|
EXPECT_EQ(CpuFeatures_StringView_IndexOfChar(str("test"), 'e'), 1);
|
||||||
|
EXPECT_EQ(CpuFeatures_StringView_IndexOfChar(str("test"), 't'), 0);
|
||||||
|
EXPECT_EQ(CpuFeatures_StringView_IndexOfChar(str("beef"), 'e'), 1);
|
||||||
// Not found.
|
// Not found.
|
||||||
EXPECT_EQ(CpuFeatures_StringView_IndexOfChar(str("test"), 'z'), -1);
|
EXPECT_EQ(CpuFeatures_StringView_IndexOfChar(str("test"), 'z'), -1);
|
||||||
// Empty.
|
// Empty.
|
||||||
@ -40,6 +42,8 @@ TEST(StringViewTest, CpuFeatures_StringView_IndexOf)
|
|||||||
{
|
{
|
||||||
// Found.
|
// Found.
|
||||||
EXPECT_EQ(CpuFeatures_StringView_IndexOf(str("test"), str("es")), 1);
|
EXPECT_EQ(CpuFeatures_StringView_IndexOf(str("test"), str("es")), 1);
|
||||||
|
EXPECT_EQ(CpuFeatures_StringView_IndexOf(str("test"), str("test")), 0);
|
||||||
|
EXPECT_EQ(CpuFeatures_StringView_IndexOf(str("tesstest"), str("test")), 4);
|
||||||
// Not found.
|
// Not found.
|
||||||
EXPECT_EQ(CpuFeatures_StringView_IndexOf(str("test"), str("aa")), -1);
|
EXPECT_EQ(CpuFeatures_StringView_IndexOf(str("test"), str("aa")), -1);
|
||||||
// Empty.
|
// Empty.
|
||||||
@ -50,6 +54,9 @@ TEST(StringViewTest, CpuFeatures_StringView_IndexOf)
|
|||||||
TEST(StringViewTest, CpuFeatures_StringView_StartsWith)
|
TEST(StringViewTest, CpuFeatures_StringView_StartsWith)
|
||||||
{
|
{
|
||||||
EXPECT_TRUE(CpuFeatures_StringView_StartsWith(str("test"), str("te")));
|
EXPECT_TRUE(CpuFeatures_StringView_StartsWith(str("test"), str("te")));
|
||||||
|
EXPECT_TRUE(CpuFeatures_StringView_StartsWith(str("test"), str("test")));
|
||||||
|
EXPECT_FALSE(CpuFeatures_StringView_StartsWith(str("test"), str("st")));
|
||||||
|
EXPECT_FALSE(CpuFeatures_StringView_StartsWith(str("test"), str("est")));
|
||||||
EXPECT_FALSE(CpuFeatures_StringView_StartsWith(str("test"), str("")));
|
EXPECT_FALSE(CpuFeatures_StringView_StartsWith(str("test"), str("")));
|
||||||
EXPECT_FALSE(
|
EXPECT_FALSE(
|
||||||
CpuFeatures_StringView_StartsWith(str("test"), kEmptyStringView));
|
CpuFeatures_StringView_StartsWith(str("test"), kEmptyStringView));
|
||||||
@ -63,8 +70,11 @@ TEST(StringViewTest, CpuFeatures_StringView_IsEquals)
|
|||||||
CpuFeatures_StringView_IsEquals(kEmptyStringView, kEmptyStringView));
|
CpuFeatures_StringView_IsEquals(kEmptyStringView, kEmptyStringView));
|
||||||
EXPECT_TRUE(CpuFeatures_StringView_IsEquals(kEmptyStringView, str("")));
|
EXPECT_TRUE(CpuFeatures_StringView_IsEquals(kEmptyStringView, str("")));
|
||||||
EXPECT_TRUE(CpuFeatures_StringView_IsEquals(str(""), kEmptyStringView));
|
EXPECT_TRUE(CpuFeatures_StringView_IsEquals(str(""), kEmptyStringView));
|
||||||
|
EXPECT_TRUE(CpuFeatures_StringView_IsEquals(str("test"), str("test")));
|
||||||
EXPECT_TRUE(CpuFeatures_StringView_IsEquals(str("a"), str("a")));
|
EXPECT_TRUE(CpuFeatures_StringView_IsEquals(str("a"), str("a")));
|
||||||
EXPECT_FALSE(CpuFeatures_StringView_IsEquals(str("a"), str("b")));
|
EXPECT_FALSE(CpuFeatures_StringView_IsEquals(str("a"), str("b")));
|
||||||
|
EXPECT_FALSE(CpuFeatures_StringView_IsEquals(str("aa"), str("a")));
|
||||||
|
EXPECT_FALSE(CpuFeatures_StringView_IsEquals(str("a"), str("aa")));
|
||||||
EXPECT_FALSE(CpuFeatures_StringView_IsEquals(str("a"), kEmptyStringView));
|
EXPECT_FALSE(CpuFeatures_StringView_IsEquals(str("a"), kEmptyStringView));
|
||||||
EXPECT_FALSE(CpuFeatures_StringView_IsEquals(kEmptyStringView, str("a")));
|
EXPECT_FALSE(CpuFeatures_StringView_IsEquals(kEmptyStringView, str("a")));
|
||||||
}
|
}
|
||||||
@ -77,12 +87,55 @@ TEST(StringViewTest, CpuFeatures_StringView_PopFront)
|
|||||||
EXPECT_EQ(CpuFeatures_StringView_PopFront(str("test"), 100), str(""));
|
EXPECT_EQ(CpuFeatures_StringView_PopFront(str("test"), 100), str(""));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST(StringViewTest, CpuFeatures_StringView_PopBack)
|
||||||
|
{
|
||||||
|
EXPECT_EQ(CpuFeatures_StringView_PopBack(str("test"), 2), str("te"));
|
||||||
|
EXPECT_EQ(CpuFeatures_StringView_PopBack(str("test"), 0), str("test"));
|
||||||
|
EXPECT_EQ(CpuFeatures_StringView_PopBack(str("test"), 4), str(""));
|
||||||
|
EXPECT_EQ(CpuFeatures_StringView_PopBack(str("test"), 100), str(""));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(StringViewTest, CpuFeatures_StringView_KeepFront)
|
||||||
|
{
|
||||||
|
EXPECT_EQ(CpuFeatures_StringView_KeepFront(str("test"), 2), str("te"));
|
||||||
|
EXPECT_EQ(CpuFeatures_StringView_KeepFront(str("test"), 0), str(""));
|
||||||
|
EXPECT_EQ(CpuFeatures_StringView_KeepFront(str("test"), 4), str("test"));
|
||||||
|
EXPECT_EQ(CpuFeatures_StringView_KeepFront(str("test"), 6), str("test"));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(StringViewTest, CpuFeatures_StringView_Front)
|
||||||
|
{
|
||||||
|
EXPECT_EQ(CpuFeatures_StringView_Front(str("apple")), 'a');
|
||||||
|
EXPECT_EQ(CpuFeatures_StringView_Front(str("a")), 'a');
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(StringViewTest, CpuFeatures_StringView_Back)
|
||||||
|
{
|
||||||
|
EXPECT_EQ(CpuFeatures_StringView_Back(str("apple")), 'e');
|
||||||
|
EXPECT_EQ(CpuFeatures_StringView_Back(str("a")), 'a');
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(StringViewTest, CpuFeatures_StringView_TrimWhitespace)
|
||||||
|
{
|
||||||
|
EXPECT_EQ(CpuFeatures_StringView_TrimWhitespace(str(" first middle last ")),
|
||||||
|
str("first middle last"));
|
||||||
|
EXPECT_EQ(CpuFeatures_StringView_TrimWhitespace(str("first middle last ")),
|
||||||
|
str("first middle last"));
|
||||||
|
EXPECT_EQ(CpuFeatures_StringView_TrimWhitespace(str(" first middle last")),
|
||||||
|
str("first middle last"));
|
||||||
|
EXPECT_EQ(CpuFeatures_StringView_TrimWhitespace(str("first middle last")),
|
||||||
|
str("first middle last"));
|
||||||
|
}
|
||||||
|
|
||||||
TEST(StringViewTest, CpuFeatures_StringView_ParsePositiveNumber)
|
TEST(StringViewTest, CpuFeatures_StringView_ParsePositiveNumber)
|
||||||
{
|
{
|
||||||
EXPECT_EQ(CpuFeatures_StringView_ParsePositiveNumber(str("42")), 42);
|
EXPECT_EQ(CpuFeatures_StringView_ParsePositiveNumber(str("42")), 42);
|
||||||
EXPECT_EQ(CpuFeatures_StringView_ParsePositiveNumber(str("0x2a")), 42);
|
EXPECT_EQ(CpuFeatures_StringView_ParsePositiveNumber(str("0x2a")), 42);
|
||||||
EXPECT_EQ(CpuFeatures_StringView_ParsePositiveNumber(str("0x2A")), 42);
|
EXPECT_EQ(CpuFeatures_StringView_ParsePositiveNumber(str("0x2A")), 42);
|
||||||
|
EXPECT_EQ(CpuFeatures_StringView_ParsePositiveNumber(str("0x2A2a")), 10794);
|
||||||
|
EXPECT_EQ(CpuFeatures_StringView_ParsePositiveNumber(str("0x2a2A")), 10794);
|
||||||
|
|
||||||
|
EXPECT_EQ(CpuFeatures_StringView_ParsePositiveNumber(str("-10")), -1);
|
||||||
EXPECT_EQ(CpuFeatures_StringView_ParsePositiveNumber(str("-0x2A")), -1);
|
EXPECT_EQ(CpuFeatures_StringView_ParsePositiveNumber(str("-0x2A")), -1);
|
||||||
EXPECT_EQ(CpuFeatures_StringView_ParsePositiveNumber(str("abc")), -1);
|
EXPECT_EQ(CpuFeatures_StringView_ParsePositiveNumber(str("abc")), -1);
|
||||||
EXPECT_EQ(CpuFeatures_StringView_ParsePositiveNumber(str("")), -1);
|
EXPECT_EQ(CpuFeatures_StringView_ParsePositiveNumber(str("")), -1);
|
||||||
|
@ -1,103 +0,0 @@
|
|||||||
// SPDX-FileCopyrightText: 2017 Google Inc.
|
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
|
||||||
|
|
||||||
#include "gtest/gtest.h"
|
|
||||||
#include "internal/unix_features_aggregator.h"
|
|
||||||
#include <array>
|
|
||||||
|
|
||||||
namespace cpu_features
|
|
||||||
{
|
|
||||||
namespace
|
|
||||||
{
|
|
||||||
struct Features
|
|
||||||
{
|
|
||||||
bool a = false;
|
|
||||||
bool b = false;
|
|
||||||
bool c = false;
|
|
||||||
};
|
|
||||||
|
|
||||||
enum eFeatures
|
|
||||||
{
|
|
||||||
TEST_a,
|
|
||||||
TEST_b,
|
|
||||||
TEST_c
|
|
||||||
};
|
|
||||||
|
|
||||||
DECLARE_SETTER_AND_GETTER(Features, a)
|
|
||||||
DECLARE_SETTER_AND_GETTER(Features, b)
|
|
||||||
DECLARE_SETTER_AND_GETTER(Features, c)
|
|
||||||
|
|
||||||
class LinuxFeatureAggregatorTest : public testing::Test
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
const std::array<CapabilityConfig, 3> kConfigs = {{{{0b0001, 0b0000}, "a", &set_a, &get_a},
|
|
||||||
{{0b0010, 0b0000}, "b", &set_b, &get_b},
|
|
||||||
{{0b0000, 0b1100}, "c", &set_c, &get_c}}};
|
|
||||||
};
|
|
||||||
|
|
||||||
TEST_F(LinuxFeatureAggregatorTest, FromFlagsEmpty)
|
|
||||||
{
|
|
||||||
Features features;
|
|
||||||
CpuFeatures_SetFromFlags(kConfigs.size(), kConfigs.data(), str(""),
|
|
||||||
&features);
|
|
||||||
EXPECT_FALSE(features.a);
|
|
||||||
EXPECT_FALSE(features.b);
|
|
||||||
EXPECT_FALSE(features.c);
|
|
||||||
|
|
||||||
EXPECT_FALSE(kConfigs[TEST_a].get_bit(&features));
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST_F(LinuxFeatureAggregatorTest, FromFlagsAllSet)
|
|
||||||
{
|
|
||||||
Features features;
|
|
||||||
CpuFeatures_SetFromFlags(kConfigs.size(), kConfigs.data(), str("a c b"),
|
|
||||||
&features);
|
|
||||||
EXPECT_TRUE(features.a);
|
|
||||||
EXPECT_TRUE(features.b);
|
|
||||||
EXPECT_TRUE(features.c);
|
|
||||||
|
|
||||||
EXPECT_TRUE(kConfigs[TEST_a].get_bit(&features));
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST_F(LinuxFeatureAggregatorTest, FromFlagsOnlyA)
|
|
||||||
{
|
|
||||||
Features features;
|
|
||||||
CpuFeatures_SetFromFlags(kConfigs.size(), kConfigs.data(), str("a"),
|
|
||||||
&features);
|
|
||||||
EXPECT_TRUE(features.a);
|
|
||||||
EXPECT_FALSE(features.b);
|
|
||||||
EXPECT_FALSE(features.c);
|
|
||||||
|
|
||||||
EXPECT_TRUE(kConfigs[TEST_a].get_bit(&features));
|
|
||||||
EXPECT_FALSE(kConfigs[TEST_b].get_bit(&features));
|
|
||||||
EXPECT_FALSE(kConfigs[TEST_c].get_bit(&features));
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST_F(LinuxFeatureAggregatorTest, FromHwcapsNone)
|
|
||||||
{
|
|
||||||
HardwareCapabilities capability;
|
|
||||||
capability.hwcaps = 0; // matches none
|
|
||||||
capability.hwcaps2 = 0; // matches none
|
|
||||||
Features features;
|
|
||||||
CpuFeatures_OverrideFromHwCaps(kConfigs.size(), kConfigs.data(), capability,
|
|
||||||
&features);
|
|
||||||
EXPECT_FALSE(features.a);
|
|
||||||
EXPECT_FALSE(features.b);
|
|
||||||
EXPECT_FALSE(features.c);
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST_F(LinuxFeatureAggregatorTest, FromHwcapsSet)
|
|
||||||
{
|
|
||||||
HardwareCapabilities capability;
|
|
||||||
capability.hwcaps = 0b0010; // matches b but not a
|
|
||||||
capability.hwcaps2 = 0b1111; // matches c
|
|
||||||
Features features;
|
|
||||||
CpuFeatures_OverrideFromHwCaps(kConfigs.size(), kConfigs.data(), capability,
|
|
||||||
&features);
|
|
||||||
EXPECT_FALSE(features.a);
|
|
||||||
EXPECT_TRUE(features.b);
|
|
||||||
EXPECT_TRUE(features.c);
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace
|
|
||||||
} // namespace cpu_features
|
|
@ -42,6 +42,13 @@ if(MSVC) # its not set otherwise
|
|||||||
set(COMPILER_NAME MSVC)
|
set(COMPILER_NAME MSVC)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
# Assume "AppleClang == Clang".
|
||||||
|
string(TOLOWER ${COMPILER_NAME} COMPILER_NAME_LOWER)
|
||||||
|
string(REGEX MATCH "clang" COMPILER_NAME_LOWER ${COMPILER_NAME_LOWER})
|
||||||
|
if(${COMPILER_NAME_LOWER} MATCHES "clang")
|
||||||
|
set(COMPILER_NAME "Clang")
|
||||||
|
endif()
|
||||||
|
|
||||||
message(STATUS "Compiler name: ${COMPILER_NAME}")
|
message(STATUS "Compiler name: ${COMPILER_NAME}")
|
||||||
|
|
||||||
if(NOT DEFINED COMPILER_NAME)
|
if(NOT DEFINED COMPILER_NAME)
|
||||||
@ -143,33 +150,8 @@ endmacro()
|
|||||||
# the xgetbv instruction, or {if not cross-compiling and the xgetbv
|
# the xgetbv instruction, or {if not cross-compiling and the xgetbv
|
||||||
# executable does not function correctly}.
|
# executable does not function correctly}.
|
||||||
########################################################################
|
########################################################################
|
||||||
set(HAVE_XGETBV 0)
|
|
||||||
set(HAVE_AVX_CVTPI32_PS 0)
|
set(HAVE_AVX_CVTPI32_PS 0)
|
||||||
if(CPU_IS_x86)
|
if(CPU_IS_x86)
|
||||||
# check to see if the compiler/linker works with xgetb instruction
|
|
||||||
if(NOT MSVC)
|
|
||||||
file(WRITE ${CMAKE_CURRENT_BINARY_DIR}/test_xgetbv.c "#include <volk_gnsssdr/volk_gnsssdr_common.h>\n unsigned long long _xgetbv(unsigned int index) { unsigned int eax, edx; __VOLK_ASM __VOLK_VOLATILE(\"xgetbv\" : \"=a\"(eax), \"=d\"(edx) : \"c\"(index)); return ((unsigned long long)edx << 32) | eax; } int main (void) { (void) _xgetbv(0); return (0); }")
|
|
||||||
set(_AUX_INCLUDE_FLAG -I${PROJECT_SOURCE_DIR}/include)
|
|
||||||
else()
|
|
||||||
# MSVC defines an intrinsic
|
|
||||||
file(WRITE ${CMAKE_CURRENT_BINARY_DIR}/test_xgetbv.c "#include <stdio.h> \n #include <intrin.h> \n int main() { int avxSupported = 0; \n#if (_MSC_FULL_VER >= 160040219) \nint cpuInfo[4]; __cpuid(cpuInfo, 1);\nif ((cpuInfo[2] & (1 << 27) || 0) && (cpuInfo[2] & (1 << 28) || 0)) \n{\nunsigned long long xcrFeatureMask = _xgetbv(_XCR_XFEATURE_ENABLED_MASK);\n avxSupported = (xcrFeatureMask & 0x6) == 6;}\n#endif \n return 1- avxSupported; }")
|
|
||||||
endif()
|
|
||||||
execute_process(COMMAND ${CMAKE_C_COMPILER} ${_AUX_INCLUDE_FLAG} -o
|
|
||||||
${CMAKE_CURRENT_BINARY_DIR}/test_xgetbv
|
|
||||||
${CMAKE_CURRENT_BINARY_DIR}/test_xgetbv.c
|
|
||||||
OUTPUT_QUIET ERROR_QUIET
|
|
||||||
RESULT_VARIABLE avx_compile_result
|
|
||||||
)
|
|
||||||
if(NOT ${avx_compile_result} EQUAL 0)
|
|
||||||
overrule_arch(avx "Compiler or linker missing xgetbv instruction")
|
|
||||||
else()
|
|
||||||
# compiler/linker seems to work; assume working
|
|
||||||
set(HAVE_XGETBV 1)
|
|
||||||
endif()
|
|
||||||
file(REMOVE ${CMAKE_CURRENT_BINARY_DIR}/test_xgetbv
|
|
||||||
${CMAKE_CURRENT_BINARY_DIR}/test_xgetbv.c
|
|
||||||
)
|
|
||||||
|
|
||||||
#########################################################################
|
#########################################################################
|
||||||
# eliminate AVX if cvtpi32_ps intrinsic fails like some versions of clang
|
# eliminate AVX if cvtpi32_ps intrinsic fails like some versions of clang
|
||||||
#########################################################################
|
#########################################################################
|
||||||
@ -215,10 +197,6 @@ if(CPU_IS_x86)
|
|||||||
endif()
|
endif()
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if(${HAVE_XGETBV})
|
|
||||||
add_definitions(-DHAVE_XGETBV)
|
|
||||||
endif()
|
|
||||||
|
|
||||||
if(${HAVE_AVX_CVTPI32_PS})
|
if(${HAVE_AVX_CVTPI32_PS})
|
||||||
add_definitions(-DHAVE_AVX_CVTPI32_PS)
|
add_definitions(-DHAVE_AVX_CVTPI32_PS)
|
||||||
endif()
|
endif()
|
||||||
@ -569,6 +547,7 @@ if(NOT (CMAKE_GENERATOR STREQUAL Xcode))
|
|||||||
PRIVATE $<BUILD_INTERFACE:${PROJECT_BINARY_DIR}/include>
|
PRIVATE $<BUILD_INTERFACE:${PROJECT_BINARY_DIR}/include>
|
||||||
PRIVATE $<BUILD_INTERFACE:${PROJECT_SOURCE_DIR}/include>
|
PRIVATE $<BUILD_INTERFACE:${PROJECT_SOURCE_DIR}/include>
|
||||||
PRIVATE $<BUILD_INTERFACE:${PROJECT_SOURCE_DIR}/kernels>
|
PRIVATE $<BUILD_INTERFACE:${PROJECT_SOURCE_DIR}/kernels>
|
||||||
|
PRIVATE $<TARGET_PROPERTY:cpu_features,INTERFACE_INCLUDE_DIRECTORIES>
|
||||||
PRIVATE ${CMAKE_CURRENT_BINARY_DIR}
|
PRIVATE ${CMAKE_CURRENT_BINARY_DIR}
|
||||||
PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
|
PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
|
||||||
)
|
)
|
||||||
|
Loading…
Reference in New Issue
Block a user