aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndroid Build Coastguard Worker <android-build-coastguard-worker@google.com>2022-04-08 16:00:21 +0000
committerAndroid Build Coastguard Worker <android-build-coastguard-worker@google.com>2022-04-08 16:00:21 +0000
commiteff8d1b8a6ad648ce13901de4888d0550befa292 (patch)
tree04a81ba53053c150df2562f9fcc4814673ffc020
parent9b2b8a2d8952505740a6c80b123cf2454ef52994 (diff)
parent261550055f23a688466c7eb0c9642d0311146b63 (diff)
downloadcpu_features-eff8d1b8a6ad648ce13901de4888d0550befa292.tar.gz
Change-Id: I15bebbd368a19a78f983f321061278bcc70de305
-rw-r--r--.github/workflows/Dockerfile5
-rw-r--r--.github/workflows/clang_format.yml24
-rw-r--r--.gitignore3
-rw-r--r--.travis.yml12
-rw-r--r--Android.bp88
-rw-r--r--CMakeLists.txt33
-rw-r--r--LICENSE30
-rw-r--r--METADATA11
l---------NOTICE1
-rw-r--r--README.md27
-rw-r--r--TEST_MAPPING23
-rw-r--r--include/cpu_features_cache_info.h2
-rw-r--r--include/cpu_features_macros.h107
-rw-r--r--include/cpuinfo_aarch64.h104
-rw-r--r--include/cpuinfo_arm.h38
-rw-r--r--include/cpuinfo_mips.h4
-rw-r--r--include/cpuinfo_ppc.h2
-rw-r--r--include/cpuinfo_x86.h25
-rw-r--r--include/internal/bit_utils.h3
-rw-r--r--include/internal/cpuid_x86.h5
-rw-r--r--include/internal/filesystem.h3
-rw-r--r--include/internal/hwcaps.h50
-rw-r--r--include/internal/stack_line_reader.h2
-rw-r--r--include/internal/string_view.h3
-rw-r--r--include/internal/unix_features_aggregator.h60
-rw-r--r--ndk_compat/CMakeLists.txt1
-rw-r--r--ndk_compat/cpu-features.c7
-rw-r--r--ndk_compat/ndk-compat-test.c1
-rw-r--r--src/cpuinfo_aarch64.c126
-rw-r--r--src/cpuinfo_arm.c184
-rw-r--r--src/cpuinfo_mips.c60
-rw-r--r--src/cpuinfo_ppc.c249
-rw-r--r--src/cpuinfo_x86.c1556
-rw-r--r--src/define_tables.h67
-rw-r--r--src/filesystem.c2
-rw-r--r--src/hwcaps.c46
-rw-r--r--src/stack_line_reader.c5
-rw-r--r--src/string_view.c2
-rw-r--r--src/unix_features_aggregator.c52
-rw-r--r--src/utils/list_cpu_features.c506
-rw-r--r--test/CMakeLists.txt15
-rw-r--r--test/bit_utils_test.cc2
-rw-r--r--test/cpuinfo_aarch64_test.cc103
-rw-r--r--test/cpuinfo_arm_test.cc12
-rw-r--r--test/cpuinfo_mips_test.cc6
-rw-r--r--test/cpuinfo_ppc_test.cc4
-rw-r--r--test/cpuinfo_x86_test.cc282
-rw-r--r--test/filesystem_for_testing.cc2
-rw-r--r--test/filesystem_for_testing.h2
-rw-r--r--test/hwcaps_for_testing.cc5
-rw-r--r--test/hwcaps_for_testing.h2
-rw-r--r--test/stack_line_reader_test.cc4
-rw-r--r--test/string_view_test.cc50
-rw-r--r--test/unix_features_aggregator_test.cc95
54 files changed, 1423 insertions, 2690 deletions
diff --git a/.github/workflows/Dockerfile b/.github/workflows/Dockerfile
deleted file mode 100644
index 41dfc93..0000000
--- a/.github/workflows/Dockerfile
+++ /dev/null
@@ -1,5 +0,0 @@
-# Create a virtual environment with all tools installed
-# ref: https://hub.docker.com/_/alpine
-FROM alpine:edge
-# Install system build dependencies
-RUN apk add --no-cache git clang
diff --git a/.github/workflows/clang_format.yml b/.github/workflows/clang_format.yml
deleted file mode 100644
index 17d1567..0000000
--- a/.github/workflows/clang_format.yml
+++ /dev/null
@@ -1,24 +0,0 @@
-name: clang-format Check
-
-on: [push, pull_request]
-
-jobs:
- # Building using the github runner environement directly.
- clang-format:
- runs-on: ubuntu-latest
- steps:
- - uses: actions/checkout@v2
- - name: Fetch origin/master
- run: git fetch origin master
- - name: List of changed file(s)
- run: git diff --name-only FETCH_HEAD
-
- - name: Build clang-format docker
- run: cd .github/workflows && docker build --tag=linter .
- - name: Check clang-format
- run: docker run --rm --init -v $(pwd):/repo linter:latest clang-format --version
- - name: clang-format help
- run: docker run --rm --init -v $(pwd):/repo linter:latest clang-format --help
-
- - name: Check current commit
- run: docker run --rm --init -v $(pwd):/repo -w /repo linter:latest sh -c "git diff --diff-filter=d --name-only FETCH_HEAD | grep '\.c$\|\.h$\|\.cc$' | xargs clang-format --style=file --dry-run --Werror "
diff --git a/.gitignore b/.gitignore
index 6285424..0690aa4 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,4 +1 @@
cmake_build/
-build/
-
-*.swp
diff --git a/.travis.yml b/.travis.yml
index b5845be..e0b4f44 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -8,7 +8,8 @@ cache:
- $HOME/cpu_features_archives
addons:
- apt_packages:
+ apt:
+ packages:
- ninja-build
env:
@@ -40,19 +41,14 @@ matrix:
env:
TARGET=x86_64-windows
CMAKE_GENERATOR="Visual Studio 15 2017 Win64"
-
- # see: https://docs.travis-ci.com/user/multi-cpu-architectures/
- - os: linux
- arch: ppc64le
+ - os: linux-ppc64le
compiler: gcc
env:
TARGET=ppc64le-linux-gnu
- - os: linux
- arch: ppc64le
+ - os: linux-ppc64le
compiler: clang
env:
TARGET=ppc64le-linux-gnu
-
# Toolchains for little-endian, 64-bit ARMv8 for GNU/Linux systems
- os: linux
env:
diff --git a/Android.bp b/Android.bp
index 7f70060..c7569de 100644
--- a/Android.bp
+++ b/Android.bp
@@ -1,36 +1,6 @@
// This Blueprint file loosely follows the logic of cpu_features'
// CMakeLists.txt and test/CMakeLists.txt files.
-package {
- default_applicable_licenses: ["external_cpu_features_license"],
-}
-
-// Added automatically by a large-scale-change that took the approach of
-// 'apply every license found to every target'. While this makes sure we respect
-// every license restriction, it may not be entirely correct.
-//
-// e.g. GPL in an MIT project might only apply to the contrib/ directory.
-//
-// Please consider splitting the single license below into multiple licenses,
-// taking care not to lose any license_kind information, and overriding the
-// default license using the 'licenses: [...]' property on targets as needed.
-//
-// For unused files, consider creating a 'fileGroup' with "//visibility:private"
-// to attach the license to, and including a comment whether the files may be
-// used in the current project.
-// See: http://go/android-license-faq
-license {
- name: "external_cpu_features_license",
- visibility: [":__subpackages__"],
- license_kinds: [
- "SPDX-license-identifier-Apache-2.0",
- "SPDX-license-identifier-BSD",
- ],
- license_text: [
- "LICENSE",
- ],
-}
-
cc_defaults {
name: "cpu_features-defaults",
host_supported: true,
@@ -42,7 +12,6 @@ cc_defaults {
"-DSTACK_LINE_READER_BUFFER_SIZE=1024",
"-Wno-gnu-designator",
],
- min_sdk_version: "S",
}
cc_library {
@@ -58,17 +27,14 @@ cc_library {
enabled: true,
},
},
- apex_available: [
- "com.android.art",
- "com.android.art.debug",
- ],
}
cc_library {
- name: "libcpu_features-hwcaps",
+ name: "libcpu_features-unix_based_hardware_detection",
defaults: ["cpu_features-defaults"],
srcs: [
"src/hwcaps.c",
+ "src/unix_features_aggregator.c",
],
cflags: [
"-DHAVE_DLFCN_H",
@@ -83,10 +49,6 @@ cc_library {
static_libs: [
"libcpu_features-utils",
],
- apex_available: [
- "com.android.art",
- "com.android.art.debug",
- ],
}
cc_library {
@@ -104,7 +66,7 @@ cc_library {
"src/cpuinfo_arm.c",
],
whole_static_libs: [
- "libcpu_features-hwcaps",
+ "libcpu_features-unix_based_hardware_detection",
],
},
arm64: {
@@ -112,7 +74,7 @@ cc_library {
"src/cpuinfo_aarch64.c",
],
whole_static_libs: [
- "libcpu_features-hwcaps",
+ "libcpu_features-unix_based_hardware_detection",
],
cflags: [
"-Wno-gnu-designator",
@@ -140,10 +102,6 @@ cc_library {
enabled: true,
},
},
- apex_available: [
- "com.android.art",
- "com.android.art.debug",
- ],
}
cc_binary {
@@ -157,21 +115,6 @@ cc_binary {
static_libs: [
"libcpu_features",
],
- arch: {
- // Function `AddCacheInfo` in `src/utils/list_cpu_features.c` is only used on x86/x86_64 and
- // triggers an error with `-Werror and `-Wunused-function` on other architectures; disable
- // the latter flag to avoid compilation errors on those architectures.
- arm: {
- cflags: [
- "-Wno-unused-function",
- ],
- },
- arm64: {
- cflags: [
- "-Wno-unused-function",
- ],
- },
- },
}
// Tests.
@@ -216,10 +159,8 @@ cc_test_library {
defaults: ["cpu_features-test-defaults"],
cflags: [
"-DCPU_FEATURES_MOCK_GET_ELF_HWCAP_FROM_GETAUXVAL",
- "-DCPU_FEATURES_TEST",
],
srcs: [
- "src/hwcaps.c",
"test/hwcaps_for_testing.cc",
],
static_libs: [
@@ -271,6 +212,9 @@ cc_test_library {
"cpu_features-test-defaults",
"stack_line_reader-defaults",
],
+ srcs: [
+ "src/unix_features_aggregator.c",
+ ],
whole_static_libs: [
"libcpu_features-filesystem_for_testing",
"libcpu_features-hwcaps_for_testing",
@@ -319,6 +263,17 @@ cc_test {
}
cc_test {
+ name: "cpu_features-unix_features_aggregator_test",
+ defaults: ["cpu_features-test-defaults"],
+ srcs: [
+ "test/unix_features_aggregator_test.cc",
+ ],
+ static_libs: [
+ "libcpu_features-all_libraries",
+ ],
+}
+
+cc_test {
name: "cpu_features-cpuinfo_test",
defaults: [
"cpu_features-test-defaults",
@@ -326,9 +281,6 @@ cc_test {
static_libs: [
"libcpu_features-all_libraries",
],
- cflags: [
- "-DSTACK_LINE_READER_BUFFER_SIZE=1024",
- ],
arch: {
x86: {
cflags: [
@@ -351,6 +303,9 @@ cc_test {
],
},
arm: {
+ cflags: [
+ "-DSTACK_LINE_READER_BUFFER_SIZE=1024",
+ ],
srcs: [
"test/cpuinfo_arm_test.cc",
"src/cpuinfo_arm.c",
@@ -358,6 +313,7 @@ cc_test {
},
arm64: {
cflags: [
+ "-DSTACK_LINE_READER_BUFFER_SIZE=1024",
"-Wno-gnu-designator",
],
srcs: [
diff --git a/CMakeLists.txt b/CMakeLists.txt
index f9daeac..6a0a57b 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -1,12 +1,6 @@
cmake_minimum_required(VERSION 3.0)
-# option() honors normal variables.
-# see: https://cmake.org/cmake/help/git-stage/policy/CMP0077.html
-if(POLICY CMP0077)
- cmake_policy(SET CMP0077 NEW)
-endif()
-
-project(CpuFeatures VERSION 0.6.0 LANGUAGES C)
+project(CpuFeatures VERSION 0.1.0)
set(CMAKE_C_STANDARD 99)
@@ -22,19 +16,13 @@ endif(NOT CMAKE_BUILD_TYPE)
option(BUILD_TESTING "Enable test (depends on googletest)." OFF)
# BUILD_SHARED_LIBS is a standard CMake variable, but we declare it here to make
# it prominent in the GUI.
-# cpu_features uses bit-fields which are - to some extends - implementation-defined (see https://en.cppreference.com/w/c/language/bit_field).
-# As a consequence it is discouraged to use cpu_features as a shared library because different compilers may interpret the code in different ways.
+# cpu_features uses bit-fields which are - to some extends - implementation-defined (see https://en.cppreference.com/w/c/language/bit_field).
+# As a consequence it is discouraged to use cpu_features as a shared library because different compilers may interpret the code in different ways.
# Prefer static linking from source whenever possible.
option(BUILD_SHARED_LIBS "Build library as shared." OFF)
# PIC
option(BUILD_PIC "Build with Position Independant Code." OFF) # Default is off at least for GCC
-# Force PIC on unix when building shared libs
-# see: https://en.wikipedia.org/wiki/Position-independent_code
-if(BUILD_SHARED_LIBS AND UNIX)
- set(BUILD_PIC ON)
-endif()
-
include(CheckIncludeFile)
include(CheckSymbolExists)
include(GNUInstallDirs)
@@ -104,7 +92,6 @@ add_library(utils OBJECT
${PROJECT_SOURCE_DIR}/src/stack_line_reader.c
${PROJECT_SOURCE_DIR}/src/string_view.c
)
-set_property(TARGET utils PROPERTY POSITION_INDEPENDENT_CODE ${BUILD_PIC})
setup_include_and_definitions(utils)
#
@@ -114,7 +101,9 @@ setup_include_and_definitions(utils)
if(UNIX)
add_library(unix_based_hardware_detection OBJECT
${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/unix_features_aggregator.c
)
setup_include_and_definitions(unix_based_hardware_detection)
check_include_file(dlfcn.h HAVE_DLFCN_H)
@@ -146,12 +135,6 @@ set_property(TARGET cpu_features PROPERTY POSITION_INDEPENDENT_CODE ${BUILD_PIC}
target_include_directories(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)
#
# program : list_cpu_features
@@ -177,12 +160,6 @@ include(CTest)
if(BUILD_TESTING)
# Automatically incorporate googletest into the CMake Project if target not
# found.
- enable_language(CXX)
-
- set(CMAKE_CXX_STANDARD 11)
- set(CMAKE_CXX_STANDARD_REQUIRED ON)
- set(CMAKE_CXX_EXTENSIONS OFF) # prefer use of -std11 instead of -gnustd11
-
if(NOT TARGET gtest OR NOT TARGET gmock_main)
# Download and unpack googletest at configure time.
configure_file(
diff --git a/LICENSE b/LICENSE
index a7043c6..7a4a3ea 100644
--- a/LICENSE
+++ b/LICENSE
@@ -199,32 +199,4 @@
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
- limitations under the License.
-
---------------------------------------------------------------------------------
-For files in the `ndk_compat` folder:
---------------------------------------------------------------------------------
-
-Copyright (C) 2010 The Android Open Source Project
-All rights reserved.
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions
-are met:
- * Redistributions of source code must retain the above copyright
- notice, this list of conditions and the following disclaimer.
- * Redistributions in binary form must reproduce the above copyright
- notice, this list of conditions and the following disclaimer in
- the documentation and/or other materials provided with the
- distribution.
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
-FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
-COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
-INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
-BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
-OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
-AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
-OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
-OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
-SUCH DAMAGE.
+ limitations under the License. \ No newline at end of file
diff --git a/METADATA b/METADATA
index 5e2b871..8721c09 100644
--- a/METADATA
+++ b/METADATA
@@ -1,5 +1,5 @@
name: "cpu_features"
-description: "A cross platform C99 library to get cpu features at runtime."
+description: "A cross platform C99 library to get CPU features at runtime."
third_party {
url {
type: HOMEPAGE
@@ -9,11 +9,10 @@ third_party {
type: GIT
value: "https://github.com/google/cpu_features.git"
}
- version: "v0.6.0"
- license_type: NOTICE
+ version: "v0.4.1"
last_upgrade_date {
- year: 2020
- month: 10
- day: 15
+ year: 2019
+ month: 7
+ day: 16
}
}
diff --git a/NOTICE b/NOTICE
new file mode 120000
index 0000000..7a694c9
--- /dev/null
+++ b/NOTICE
@@ -0,0 +1 @@
+LICENSE \ No newline at end of file
diff --git a/README.md b/README.md
index 8a34168..29d7946 100644
--- a/README.md
+++ b/README.md
@@ -30,10 +30,6 @@ instructions) at runtime.
- **Unit tested.**
<a name="codesample"></a>
-## Code samples
-
-**Note:** For C++ code, the library functions are defined in the `CpuFeatures` namespace.
-
### Checking features at runtime
Here's a simple example that executes a codepath if the CPU supports both the
@@ -42,7 +38,6 @@ AES and the SSE4.2 instruction sets:
```c
#include "cpuinfo_x86.h"
-// For C++, add `using namespace CpuFeatures;`
static const X86Features features = GetX86Info().features;
void Compute(void) {
@@ -64,7 +59,6 @@ features and then check whether AES and NEON are supported.
#include <stdbool.h>
#include "cpuinfo_arm.h"
-// For C++, add `using namespace CpuFeatures;`
static const ArmFeatures features = GetArmInfo().features;
static const bool has_aes_and_neon = features.aes && features.neon;
@@ -84,7 +78,6 @@ instruction set (e.g., `g++ -mavx`) and sets `has_avx` accordingly.
#include <stdbool.h>
#include "cpuinfo_x86.h"
-// For C++, add `using namespace CpuFeatures;`
static const X86Features features = GetX86Info().features;
static const bool has_avx = CPU_FEATURES_COMPILED_X86_AVX || features.avx;
@@ -107,7 +100,6 @@ set&mdash;but only if it's not Sandy Bridge.
#include <stdbool.h>
#include "cpuinfo_x86.h"
-// For C++, add `using namespace CpuFeatures;`
static const X86Info info = GetX86Info();
static const X86Microarchitecture uarch = GetX86Microarchitecture(&info);
static const bool has_fast_avx = info.features.avx && uarch != INTEL_SNB;
@@ -120,7 +112,7 @@ This feature is currently available only for x86 microarchitectures.
<a name="usagesample"></a>
### Running sample code
-Building `cpu_features` (check [quickstart](#quickstart) below) brings a small executable to test the library.
+Building `cpu_features` brings a small executable to test the library.
```shell
% ./build/list_cpu_features
@@ -180,20 +172,3 @@ See [LICENSE](LICENSE) for more information.
## Build with CMake
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
-```
diff --git a/TEST_MAPPING b/TEST_MAPPING
index fbfe969..0af6ef9 100644
--- a/TEST_MAPPING
+++ b/TEST_MAPPING
@@ -1,15 +1,38 @@
{
"presubmit": [
{
+ "name": "cpu_features-bit_utils_test",
+ "host": true
+ },
+ {
"name": "cpu_features-bit_utils_test"
},
{
+ "name": "cpu_features-string_view_test",
+ "host": true
+ },
+ {
"name": "cpu_features-string_view_test"
},
{
+ "name": "cpu_features-stack_line_reader_test",
+ "host": true
+ },
+ {
"name": "cpu_features-stack_line_reader_test"
},
{
+ "name": "cpu_features-unix_features_aggregator_test",
+ "host": true
+ },
+ {
+ "name": "cpu_features-unix_features_aggregator_test"
+ },
+ {
+ "name": "cpu_features-cpuinfo_test",
+ "host": true
+ },
+ {
"name": "cpu_features-cpuinfo_test"
}
]
diff --git a/include/cpu_features_cache_info.h b/include/cpu_features_cache_info.h
index 1a61ee1..b7cc046 100644
--- a/include/cpu_features_cache_info.h
+++ b/include/cpu_features_cache_info.h
@@ -1,4 +1,4 @@
-// Copyright 2017 Google LLC
+// Copyright 2017 Google Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
diff --git a/include/cpu_features_macros.h b/include/cpu_features_macros.h
index 4b231a1..2227160 100644
--- a/include/cpu_features_macros.h
+++ b/include/cpu_features_macros.h
@@ -1,4 +1,4 @@
-// Copyright 2017 Google LLC
+// Copyright 2017 Google Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
@@ -79,10 +79,6 @@
#define CPU_FEATURES_OS_WINDOWS
#endif
-#if (defined(__apple__) || defined(__APPLE__) || defined(__MACH__))
-#define CPU_FEATURES_OS_DARWIN
-#endif
-
////////////////////////////////////////////////////////////////////////////////
// Compilers
////////////////////////////////////////////////////////////////////////////////
@@ -122,95 +118,26 @@
// Use the following to check if a feature is known to be available at
// compile time. See README.md for an example.
#if defined(CPU_FEATURES_ARCH_X86)
-
-#if defined(__AES__)
-#define CPU_FEATURES_COMPILED_X86_AES 1
-#else
-#define CPU_FEATURES_COMPILED_X86_AES 0
-#endif // defined(__AES__)
-
-#if defined(__F16C__)
-#define CPU_FEATURES_COMPILED_X86_F16C 1
-#else
-#define CPU_FEATURES_COMPILED_X86_F16C 0
-#endif // defined(__F16C__)
-
-#if defined(__BMI__)
-#define CPU_FEATURES_COMPILED_X86_BMI 1
-#else
-#define CPU_FEATURES_COMPILED_X86_BMI 0
-#endif // defined(__BMI__)
-
-#if defined(__BMI2__)
-#define CPU_FEATURES_COMPILED_X86_BMI2 1
-#else
-#define CPU_FEATURES_COMPILED_X86_BMI2 0
-#endif // defined(__BMI2__)
-
-#if (defined(__SSE__) || (_M_IX86_FP >= 1))
-#define CPU_FEATURES_COMPILED_X86_SSE 1
-#else
-#define CPU_FEATURES_COMPILED_X86_SSE 0
+#define CPU_FEATURES_COMPILED_X86_AES defined(__AES__)
+#define CPU_FEATURES_COMPILED_X86_F16C defined(__F16C__)
+#define CPU_FEATURES_COMPILED_X86_BMI defined(__BMI__)
+#define CPU_FEATURES_COMPILED_X86_BMI2 defined(__BMI2__)
+#define CPU_FEATURES_COMPILED_X86_SSE (defined(__SSE__) || (_M_IX86_FP >= 1))
+#define CPU_FEATURES_COMPILED_X86_SSE2 (defined(__SSE2__) || (_M_IX86_FP >= 2))
+#define CPU_FEATURES_COMPILED_X86_SSE3 defined(__SSE3__)
+#define CPU_FEATURES_COMPILED_X86_SSSE3 defined(__SSSE3__)
+#define CPU_FEATURES_COMPILED_X86_SSE4_1 defined(__SSE4_1__)
+#define CPU_FEATURES_COMPILED_X86_SSE4_2 defined(__SSE4_2__)
+#define CPU_FEATURES_COMPILED_X86_AVX defined(__AVX__)
+#define CPU_FEATURES_COMPILED_x86_AVX2 defined(__AVX2__)
#endif
-#if (defined(__SSE2__) || (_M_IX86_FP >= 2))
-#define CPU_FEATURES_COMPILED_X86_SSE2 1
-#else
-#define CPU_FEATURES_COMPILED_X86_SSE2 0
-#endif
-
-#if defined(__SSE3__)
-#define CPU_FEATURES_COMPILED_X86_SSE3 1
-#else
-#define CPU_FEATURES_COMPILED_X86_SSE3 0
-#endif // defined(__SSE3__)
-
-#if defined(__SSSE3__)
-#define CPU_FEATURES_COMPILED_X86_SSSE3 1
-#else
-#define CPU_FEATURES_COMPILED_X86_SSSE3 0
-#endif // defined(__SSSE3__)
-
-#if defined(__SSE4_1__)
-#define CPU_FEATURES_COMPILED_X86_SSE4_1 1
-#else
-#define CPU_FEATURES_COMPILED_X86_SSE4_1 0
-#endif // defined(__SSE4_1__)
-
-#if defined(__SSE4_2__)
-#define CPU_FEATURES_COMPILED_X86_SSE4_2 1
-#else
-#define CPU_FEATURES_COMPILED_X86_SSE4_2 0
-#endif // defined(__SSE4_2__)
-
-#if defined(__AVX__)
-#define CPU_FEATURES_COMPILED_X86_AVX 1
-#else
-#define CPU_FEATURES_COMPILED_X86_AVX 0
-#endif // defined(__AVX__)
-
-#if defined(__AVX2__)
-#define CPU_FEATURES_COMPILED_X86_AVX2 1
-#else
-#define CPU_FEATURES_COMPILED_X86_AVX2 0
-#endif // defined(__AVX2__)
-
-#endif // defined(CPU_FEATURES_ARCH_X86)
-
#if defined(CPU_FEATURES_ARCH_ANY_ARM)
-#if defined(__ARM_NEON__)
-#define CPU_FEATURES_COMPILED_ANY_ARM_NEON 1
-#else
-#define CPU_FEATURES_COMPILED_ANY_ARM_NEON 0
-#endif // defined(__ARM_NEON__)
-#endif // defined(CPU_FEATURES_ARCH_ANY_ARM)
+#define CPU_FEATURES_COMPILED_ANY_ARM_NEON defined(__ARM_NEON__)
+#endif
#if defined(CPU_FEATURES_ARCH_MIPS)
-#if defined(__mips_msa)
-#define CPU_FEATURES_COMPILED_MIPS_MSA 1
-#else
-#define CPU_FEATURES_COMPILED_MIPS_MSA 0
-#endif // defined(__mips_msa)
-#endif // defined(CPU_FEATURES_ARCH_MIPS)
+#define CPU_FEATURES_COMPILED_MIPS_MSA defined(__mips_msa)
+#endif
#endif // CPU_FEATURES_INCLUDE_CPU_FEATURES_MACROS_H_
diff --git a/include/cpuinfo_aarch64.h b/include/cpuinfo_aarch64.h
index d85d46d..cd3a676 100644
--- a/include/cpuinfo_aarch64.h
+++ b/include/cpuinfo_aarch64.h
@@ -1,4 +1,4 @@
-// Copyright 2017 Google LLC
+// Copyright 2017 Google Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
@@ -15,62 +15,19 @@
#ifndef CPU_FEATURES_INCLUDE_CPUINFO_AARCH64_H_
#define CPU_FEATURES_INCLUDE_CPUINFO_AARCH64_H_
-#include "cpu_features_cache_info.h"
#include "cpu_features_macros.h"
+#include "cpu_features_cache_info.h"
CPU_FEATURES_START_CPP_NAMESPACE
typedef struct {
- int fp : 1; // Floating-point.
- int asimd : 1; // Advanced SIMD.
- int evtstrm : 1; // Generic timer generated events.
- int aes : 1; // Hardware-accelerated Advanced Encryption Standard.
- int pmull : 1; // Polynomial multiply long.
- int sha1 : 1; // Hardware-accelerated SHA1.
- int sha2 : 1; // Hardware-accelerated SHA2-256.
- int crc32 : 1; // Hardware-accelerated CRC-32.
- int atomics : 1; // Armv8.1 atomic instructions.
- int fphp : 1; // Half-precision floating point support.
- int asimdhp : 1; // Advanced SIMD half-precision support.
- int cpuid : 1; // Access to certain ID registers.
- int asimdrdm : 1; // Rounding Double Multiply Accumulate/Subtract.
- int jscvt : 1; // Support for JavaScript conversion.
- int fcma : 1; // Floating point complex numbers.
- int lrcpc : 1; // Support for weaker release consistency.
- int dcpop : 1; // Data persistence writeback.
- int sha3 : 1; // Hardware-accelerated SHA3.
- int sm3 : 1; // Hardware-accelerated SM3.
- int sm4 : 1; // Hardware-accelerated SM4.
- int asimddp : 1; // Dot product instruction.
- int sha512 : 1; // Hardware-accelerated SHA512.
- int sve : 1; // Scalable Vector Extension.
- int asimdfhm : 1; // Additional half-precision instructions.
- int dit : 1; // Data independent timing.
- int uscat : 1; // Unaligned atomics support.
- int ilrcpc : 1; // Additional support for weaker release consistency.
- int flagm : 1; // Flag manipulation instructions.
- int ssbs : 1; // Speculative Store Bypass Safe PSTATE bit.
- int sb : 1; // Speculation barrier.
- int paca : 1; // Address 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.
+ int fp : 1; // Floating-point.
+ int asimd : 1; // Advanced SIMD.
+ int aes : 1; // Hardware-accelerated Advanced Encryption Standard.
+ int pmull : 1; // Polynomial multiply long.
+ int sha1 : 1; // Hardware-accelerated SHA1.
+ int sha2 : 1; // Hardware-accelerated SHA2-256.
+ int crc32 : 1; // Hardware-accelerated CRC-32.
// Make sure to update Aarch64FeaturesEnum below if you add a field here.
} Aarch64Features;
@@ -91,54 +48,11 @@ Aarch64Info GetAarch64Info(void);
typedef enum {
AARCH64_FP,
AARCH64_ASIMD,
- AARCH64_EVTSTRM,
AARCH64_AES,
AARCH64_PMULL,
AARCH64_SHA1,
AARCH64_SHA2,
AARCH64_CRC32,
- AARCH64_ATOMICS,
- AARCH64_FPHP,
- AARCH64_ASIMDHP,
- AARCH64_CPUID,
- AARCH64_ASIMDRDM,
- AARCH64_JSCVT,
- AARCH64_FCMA,
- AARCH64_LRCPC,
- AARCH64_DCPOP,
- AARCH64_SHA3,
- AARCH64_SM3,
- AARCH64_SM4,
- AARCH64_ASIMDDP,
- AARCH64_SHA512,
- AARCH64_SVE,
- AARCH64_ASIMDFHM,
- AARCH64_DIT,
- AARCH64_USCAT,
- AARCH64_ILRCPC,
- AARCH64_FLAGM,
- AARCH64_SSBS,
- AARCH64_SB,
- AARCH64_PACA,
- 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_,
} Aarch64FeaturesEnum;
diff --git a/include/cpuinfo_arm.h b/include/cpuinfo_arm.h
index 0952d7c..d15471f 100644
--- a/include/cpuinfo_arm.h
+++ b/include/cpuinfo_arm.h
@@ -1,4 +1,4 @@
-// Copyright 2017 Google LLC
+// Copyright 2017 Google Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
@@ -16,9 +16,8 @@
#define CPU_FEATURES_INCLUDE_CPUINFO_ARM_H_
#include <stdint.h> // uint32_t
-
-#include "cpu_features_cache_info.h"
#include "cpu_features_macros.h"
+#include "cpu_features_cache_info.h"
CPU_FEATURES_START_CPP_NAMESPACE
@@ -26,33 +25,30 @@ typedef struct {
int swp : 1; // SWP instruction (atomic read-modify-write)
int half : 1; // Half-word loads and stores
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 fpa : 1; // Floating point accelerator
int vfp : 1; // Vector Floating Point.
- int edsp : 1; // DSP extensions (the 'e' variant of the ARM9 CPUs, and all
- // others above)
- int java : 1; // Jazelle (Java bytecode accelerator)
- int iwmmxt : 1; // Intel Wireless MMX Technology.
- int crunch : 1; // MaverickCrunch coprocessor
- int thumbee : 1; // ThumbEE
- int neon : 1; // Advanced SIMD.
- int vfpv3 : 1; // VFP version 3
+ int edsp : 1; // DSP extensions (the 'e' variant of the ARM9 CPUs, and all others above)
+ int java : 1; // Jazelle (Java bytecode accelerator)
+ int iwmmxt : 1; // Intel Wireless MMX Technology.
+ int crunch : 1; // MaverickCrunch coprocessor
+ int thumbee : 1; // ThumbEE
+ int neon : 1; // Advanced SIMD.
+ int vfpv3 : 1; // VFP version 3
int vfpv3d16 : 1; // VFP version 3 with 16 D-registers
int tls : 1; // TLS register
int vfpv4 : 1; // VFP version 4 with fast context switching
int idiva : 1; // SDIV and UDIV hardware division in ARM mode.
int idivt : 1; // SDIV and UDIV hardware division in Thumb mode.
int vfpd32 : 1; // VFP with 32 D-registers
- 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 aes : 1; // Hardware-accelerated Advanced Encryption Standard.
- int pmull : 1; // Polynomial multiply long.
- int sha1 : 1; // Hardware-accelerated SHA1.
- int sha2 : 1; // Hardware-accelerated SHA2-256.
- int crc32 : 1; // Hardware-accelerated CRC-32.
+ 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 aes : 1; // Hardware-accelerated Advanced Encryption Standard.
+ int pmull : 1; // Polynomial multiply long.
+ int sha1 : 1; // Hardware-accelerated SHA1.
+ int sha2 : 1; // Hardware-accelerated SHA2-256.
+ int crc32 : 1; // Hardware-accelerated CRC-32.
// Make sure to update ArmFeaturesEnum below if you add a field here.
} ArmFeatures;
diff --git a/include/cpuinfo_mips.h b/include/cpuinfo_mips.h
index 9e5e7fc..d82ae85 100644
--- a/include/cpuinfo_mips.h
+++ b/include/cpuinfo_mips.h
@@ -1,4 +1,4 @@
-// Copyright 2017 Google LLC
+// Copyright 2017 Google Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
@@ -15,8 +15,8 @@
#ifndef CPU_FEATURES_INCLUDE_CPUINFO_MIPS_H_
#define CPU_FEATURES_INCLUDE_CPUINFO_MIPS_H_
-#include "cpu_features_cache_info.h"
#include "cpu_features_macros.h"
+#include "cpu_features_cache_info.h"
CPU_FEATURES_START_CPP_NAMESPACE
diff --git a/include/cpuinfo_ppc.h b/include/cpuinfo_ppc.h
index f691194..eaac7da 100644
--- a/include/cpuinfo_ppc.h
+++ b/include/cpuinfo_ppc.h
@@ -15,8 +15,8 @@
#ifndef CPU_FEATURES_INCLUDE_CPUINFO_PPC_H_
#define CPU_FEATURES_INCLUDE_CPUINFO_PPC_H_
-#include "cpu_features_cache_info.h"
#include "cpu_features_macros.h"
+#include "cpu_features_cache_info.h"
#include "internal/hwcaps.h"
CPU_FEATURES_START_CPP_NAMESPACE
diff --git a/include/cpuinfo_x86.h b/include/cpuinfo_x86.h
index 8d40f71..4d51b60 100644
--- a/include/cpuinfo_x86.h
+++ b/include/cpuinfo_x86.h
@@ -1,5 +1,4 @@
-// Copyright 2017 Google LLC
-// Copyright 2020 Intel Corporation
+// Copyright 2017 Google Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
@@ -32,7 +31,6 @@ typedef struct {
int aes : 1;
int erms : 1;
int f16c : 1;
- int fma4 : 1;
int fma3 : 1;
int vaes : 1;
int vpclmulqdq : 1;
@@ -50,7 +48,6 @@ typedef struct {
int ssse3 : 1;
int sse4_1 : 1;
int sse4_2 : 1;
- int sse4a : 1;
int avx : 1;
int avx2 : 1;
@@ -70,13 +67,6 @@ typedef struct {
int avx512vpopcntdq : 1;
int avx512_4vnniw : 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 smx : 1;
@@ -126,11 +116,7 @@ typedef enum {
INTEL_ATOM_GMT, // GOLDMONT
INTEL_KBL, // KABY LAKE
INTEL_CFL, // COFFEE LAKE
- INTEL_WHL, // WHISKEY LAKE
INTEL_CNL, // CANNON LAKE
- INTEL_ICL, // ICE LAKE
- INTEL_TGL, // TIGER LAKE
- INTEL_SPR, // SAPPHIRE RAPIDS
AMD_HAMMER, // K8
AMD_K10, // K10
AMD_BOBCAT, // K14
@@ -161,7 +147,6 @@ typedef enum {
X86_AES,
X86_ERMS,
X86_F16C,
- X86_FMA4,
X86_FMA3,
X86_VAES,
X86_VPCLMULQDQ,
@@ -178,7 +163,6 @@ typedef enum {
X86_SSSE3,
X86_SSE4_1,
X86_SSE4_2,
- X86_SSE4A,
X86_AVX,
X86_AVX2,
X86_AVX512F,
@@ -196,13 +180,6 @@ typedef enum {
X86_AVX512VPOPCNTDQ,
X86_AVX512_4VNNIW,
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_SMX,
X86_SGX,
diff --git a/include/internal/bit_utils.h b/include/internal/bit_utils.h
index 3467ff9..bc965cb 100644
--- a/include/internal/bit_utils.h
+++ b/include/internal/bit_utils.h
@@ -1,4 +1,4 @@
-// Copyright 2017 Google LLC
+// Copyright 2017 Google Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
@@ -18,7 +18,6 @@
#include <assert.h>
#include <stdbool.h>
#include <stdint.h>
-
#include "cpu_features_macros.h"
CPU_FEATURES_START_CPP_NAMESPACE
diff --git a/include/internal/cpuid_x86.h b/include/internal/cpuid_x86.h
index 33327a4..754ca38 100644
--- a/include/internal/cpuid_x86.h
+++ b/include/internal/cpuid_x86.h
@@ -1,4 +1,4 @@
-// Copyright 2017 Google LLC
+// Copyright 2017 Google Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
@@ -26,8 +26,7 @@ typedef struct {
uint32_t eax, ebx, ecx, edx;
} Leaf;
-// Returns the result of a call to the cpuid instruction.
-Leaf GetCpuidLeaf(uint32_t leaf_id, int ecx);
+Leaf CpuIdEx(uint32_t leaf_id, int ecx);
// Returns the eax value of the XCR0 register.
uint32_t GetXCR0Eax(void);
diff --git a/include/internal/filesystem.h b/include/internal/filesystem.h
index d8f2f6a..3378881 100644
--- a/include/internal/filesystem.h
+++ b/include/internal/filesystem.h
@@ -1,4 +1,4 @@
-// Copyright 2017 Google LLC
+// Copyright 2017 Google Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
@@ -19,7 +19,6 @@
#include <stddef.h>
#include <stdint.h>
-
#include "cpu_features_macros.h"
CPU_FEATURES_START_CPP_NAMESPACE
diff --git a/include/internal/hwcaps.h b/include/internal/hwcaps.h
index 62037c8..06a0f60 100644
--- a/include/internal/hwcaps.h
+++ b/include/internal/hwcaps.h
@@ -1,4 +1,4 @@
-// Copyright 2017 Google LLC
+// Copyright 2017 Google Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
@@ -17,9 +17,7 @@
#ifndef CPU_FEATURES_INCLUDE_INTERNAL_HWCAPS_H_
#define CPU_FEATURES_INCLUDE_INTERNAL_HWCAPS_H_
-#include <stdbool.h>
#include <stdint.h>
-
#include "cpu_features_macros.h"
CPU_FEATURES_START_CPP_NAMESPACE
@@ -30,55 +28,11 @@ CPU_FEATURES_START_CPP_NAMESPACE
// http://elixir.free-electrons.com/linux/latest/source/arch/arm64/include/uapi/asm/hwcap.h
#define AARCH64_HWCAP_FP (1UL << 0)
#define AARCH64_HWCAP_ASIMD (1UL << 1)
-#define AARCH64_HWCAP_EVTSTRM (1UL << 2)
#define AARCH64_HWCAP_AES (1UL << 3)
#define AARCH64_HWCAP_PMULL (1UL << 4)
#define AARCH64_HWCAP_SHA1 (1UL << 5)
#define AARCH64_HWCAP_SHA2 (1UL << 6)
#define AARCH64_HWCAP_CRC32 (1UL << 7)
-#define AARCH64_HWCAP_ATOMICS (1UL << 8)
-#define AARCH64_HWCAP_FPHP (1UL << 9)
-#define AARCH64_HWCAP_ASIMDHP (1UL << 10)
-#define AARCH64_HWCAP_CPUID (1UL << 11)
-#define AARCH64_HWCAP_ASIMDRDM (1UL << 12)
-#define AARCH64_HWCAP_JSCVT (1UL << 13)
-#define AARCH64_HWCAP_FCMA (1UL << 14)
-#define AARCH64_HWCAP_LRCPC (1UL << 15)
-#define AARCH64_HWCAP_DCPOP (1UL << 16)
-#define AARCH64_HWCAP_SHA3 (1UL << 17)
-#define AARCH64_HWCAP_SM3 (1UL << 18)
-#define AARCH64_HWCAP_SM4 (1UL << 19)
-#define AARCH64_HWCAP_ASIMDDP (1UL << 20)
-#define AARCH64_HWCAP_SHA512 (1UL << 21)
-#define AARCH64_HWCAP_SVE (1UL << 22)
-#define AARCH64_HWCAP_ASIMDFHM (1UL << 23)
-#define AARCH64_HWCAP_DIT (1UL << 24)
-#define AARCH64_HWCAP_USCAT (1UL << 25)
-#define AARCH64_HWCAP_ILRCPC (1UL << 26)
-#define AARCH64_HWCAP_FLAGM (1UL << 27)
-#define AARCH64_HWCAP_SSBS (1UL << 28)
-#define AARCH64_HWCAP_SB (1UL << 29)
-#define AARCH64_HWCAP_PACA (1UL << 30)
-#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
#define ARM_HWCAP_SWP (1UL << 0)
@@ -171,8 +125,6 @@ typedef struct {
} HardwareCapabilities;
HardwareCapabilities CpuFeatures_GetHardwareCapabilities(void);
-bool CpuFeatures_IsHwCapsSet(const HardwareCapabilities hwcaps_mask,
- const HardwareCapabilities hwcaps);
typedef struct {
char platform[64]; // 0 terminated string
diff --git a/include/internal/stack_line_reader.h b/include/internal/stack_line_reader.h
index 39c1b8b..c540f6b 100644
--- a/include/internal/stack_line_reader.h
+++ b/include/internal/stack_line_reader.h
@@ -1,4 +1,4 @@
-// Copyright 2017 Google LLC
+// Copyright 2017 Google Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
diff --git a/include/internal/string_view.h b/include/internal/string_view.h
index 64fed40..aa3779c 100644
--- a/include/internal/string_view.h
+++ b/include/internal/string_view.h
@@ -1,4 +1,4 @@
-// Copyright 2017 Google LLC
+// Copyright 2017 Google Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
@@ -19,7 +19,6 @@
#include <stdbool.h>
#include <stddef.h>
#include <string.h>
-
#include "cpu_features_macros.h"
CPU_FEATURES_START_CPP_NAMESPACE
diff --git a/include/internal/unix_features_aggregator.h b/include/internal/unix_features_aggregator.h
new file mode 100644
index 0000000..77661d4
--- /dev/null
+++ b/include/internal/unix_features_aggregator.h
@@ -0,0 +1,60 @@
+// Copyright 2017 Google Inc.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// 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 <ctype.h>
+#include <stdint.h>
+#include "cpu_features_macros.h"
+#include "internal/hwcaps.h"
+#include "internal/string_view.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; \
+ }
+
+// 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.
+} 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_
diff --git a/ndk_compat/CMakeLists.txt b/ndk_compat/CMakeLists.txt
index 186708a..d95e523 100644
--- a/ndk_compat/CMakeLists.txt
+++ b/ndk_compat/CMakeLists.txt
@@ -15,7 +15,6 @@ set (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})
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})
set_target_properties(ndk_compat PROPERTIES PUBLIC_HEADER "${NDK_COMPAT_HDRS}")
diff --git a/ndk_compat/cpu-features.c b/ndk_compat/cpu-features.c
index 27ff7bb..715dc4f 100644
--- a/ndk_compat/cpu-features.c
+++ b/ndk_compat/cpu-features.c
@@ -1,12 +1,11 @@
#include "cpu-features.h"
-
-#include <pthread.h>
-
#include "cpu_features_macros.h"
#include "internal/filesystem.h"
#include "internal/stack_line_reader.h"
#include "internal/string_view.h"
+#include <pthread.h>
+
#if defined(CPU_FEATURES_ARCH_ARM)
#include "cpuinfo_arm.h"
#elif defined(CPU_FEATURES_ARCH_X86)
@@ -116,7 +115,7 @@ static void android_cpuInit(void) {
if (info.features.crc32) g_cpuFeatures |= ANDROID_CPU_ARM_FEATURE_CRC32;
if (info.architecture >= 6)
g_cpuFeatures |= ANDROID_CPU_ARM_FEATURE_LDREX_STREX;
- if (info.features.vfp) g_cpuFeatures |= ANDROID_CPU_ARM_FEATURE_VFPv2;
+ if (info.features.vfpv) g_cpuFeatures |= ANDROID_CPU_ARM_FEATURE_VFPv2;
if (info.features.vfpv4) {
g_cpuFeatures |= ANDROID_CPU_ARM_FEATURE_VFP_FMA;
g_cpuFeatures |= ANDROID_CPU_ARM_FEATURE_NEON_FMA;
diff --git a/ndk_compat/ndk-compat-test.c b/ndk_compat/ndk-compat-test.c
index e4005d4..782dbbf 100644
--- a/ndk_compat/ndk-compat-test.c
+++ b/ndk_compat/ndk-compat-test.c
@@ -1,5 +1,4 @@
#include <stdio.h>
-
#include "cpu-features.h"
int main() {
diff --git a/src/cpuinfo_aarch64.c b/src/cpuinfo_aarch64.c
index 0a52718..26a07d3 100644
--- a/src/cpuinfo_aarch64.c
+++ b/src/cpuinfo_aarch64.c
@@ -1,4 +1,4 @@
-// Copyright 2017 Google LLC
+// Copyright 2017 Google Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
@@ -14,70 +14,34 @@
#include "cpuinfo_aarch64.h"
-#include <assert.h>
-#include <ctype.h>
-
#include "internal/filesystem.h"
#include "internal/hwcaps.h"
#include "internal/stack_line_reader.h"
#include "internal/string_view.h"
+#include "internal/unix_features_aggregator.h"
+
+#include <assert.h>
+#include <ctype.h>
+
+DECLARE_SETTER(Aarch64Features, fp)
+DECLARE_SETTER(Aarch64Features, asimd)
+DECLARE_SETTER(Aarch64Features, aes)
+DECLARE_SETTER(Aarch64Features, pmull)
+DECLARE_SETTER(Aarch64Features, sha1)
+DECLARE_SETTER(Aarch64Features, sha2)
+DECLARE_SETTER(Aarch64Features, crc32)
-// Generation of feature's getters/setters functions and kGetters, kSetters,
-// kCpuInfoFlags and kHardwareCapabilities global tables.
-#define DEFINE_TABLE_FEATURES \
- FEATURE(AARCH64_FP, fp, "fp", AARCH64_HWCAP_FP, 0) \
- FEATURE(AARCH64_ASIMD, asimd, "asimd", AARCH64_HWCAP_ASIMD, 0) \
- FEATURE(AARCH64_EVTSTRM, evtstrm, "evtstrm", AARCH64_HWCAP_EVTSTRM, 0) \
- FEATURE(AARCH64_AES, aes, "aes", AARCH64_HWCAP_AES, 0) \
- FEATURE(AARCH64_PMULL, pmull, "pmull", AARCH64_HWCAP_PMULL, 0) \
- FEATURE(AARCH64_SHA1, sha1, "sha1", AARCH64_HWCAP_SHA1, 0) \
- FEATURE(AARCH64_SHA2, sha2, "sha2", AARCH64_HWCAP_SHA2, 0) \
- FEATURE(AARCH64_CRC32, crc32, "crc32", AARCH64_HWCAP_CRC32, 0) \
- FEATURE(AARCH64_ATOMICS, atomics, "atomics", AARCH64_HWCAP_ATOMICS, 0) \
- FEATURE(AARCH64_FPHP, fphp, "fphp", AARCH64_HWCAP_FPHP, 0) \
- FEATURE(AARCH64_ASIMDHP, asimdhp, "asimdhp", AARCH64_HWCAP_ASIMDHP, 0) \
- FEATURE(AARCH64_CPUID, cpuid, "cpuid", AARCH64_HWCAP_CPUID, 0) \
- FEATURE(AARCH64_ASIMDRDM, asimdrdm, "asimdrdm", AARCH64_HWCAP_ASIMDRDM, 0) \
- FEATURE(AARCH64_JSCVT, jscvt, "jscvt", AARCH64_HWCAP_JSCVT, 0) \
- FEATURE(AARCH64_FCMA, fcma, "fcma", AARCH64_HWCAP_FCMA, 0) \
- FEATURE(AARCH64_LRCPC, lrcpc, "lrcpc", AARCH64_HWCAP_LRCPC, 0) \
- FEATURE(AARCH64_DCPOP, dcpop, "dcpop", AARCH64_HWCAP_DCPOP, 0) \
- FEATURE(AARCH64_SHA3, sha3, "sha3", AARCH64_HWCAP_SHA3, 0) \
- FEATURE(AARCH64_SM3, sm3, "sm3", AARCH64_HWCAP_SM3, 0) \
- FEATURE(AARCH64_SM4, sm4, "sm4", AARCH64_HWCAP_SM4, 0) \
- FEATURE(AARCH64_ASIMDDP, asimddp, "asimddp", AARCH64_HWCAP_ASIMDDP, 0) \
- FEATURE(AARCH64_SHA512, sha512, "sha512", AARCH64_HWCAP_SHA512, 0) \
- FEATURE(AARCH64_SVE, sve, "sve", AARCH64_HWCAP_SVE, 0) \
- FEATURE(AARCH64_ASIMDFHM, asimdfhm, "asimdfhm", AARCH64_HWCAP_ASIMDFHM, 0) \
- FEATURE(AARCH64_DIT, dit, "dit", AARCH64_HWCAP_DIT, 0) \
- FEATURE(AARCH64_USCAT, uscat, "uscat", AARCH64_HWCAP_USCAT, 0) \
- FEATURE(AARCH64_ILRCPC, ilrcpc, "ilrcpc", AARCH64_HWCAP_ILRCPC, 0) \
- FEATURE(AARCH64_FLAGM, flagm, "flagm", AARCH64_HWCAP_FLAGM, 0) \
- FEATURE(AARCH64_SSBS, ssbs, "ssbs", AARCH64_HWCAP_SSBS, 0) \
- FEATURE(AARCH64_SB, sb, "sb", AARCH64_HWCAP_SB, 0) \
- FEATURE(AARCH64_PACA, paca, "paca", AARCH64_HWCAP_PACA, 0) \
- FEATURE(AARCH64_PACG, pacg, "pacg", AARCH64_HWCAP_PACG, 0) \
- FEATURE(AARCH64_DCPODP, dcpodp, "dcpodp", 0, AARCH64_HWCAP2_DCPODP) \
- FEATURE(AARCH64_SVE2, sve2, "sve2", 0, AARCH64_HWCAP2_SVE2) \
- FEATURE(AARCH64_SVEAES, sveaes, "sveaes", 0, AARCH64_HWCAP2_SVEAES) \
- FEATURE(AARCH64_SVEPMULL, svepmull, "svepmull", 0, AARCH64_HWCAP2_SVEPMULL) \
- FEATURE(AARCH64_SVEBITPERM, svebitperm, "svebitperm", 0, \
- AARCH64_HWCAP2_SVEBITPERM) \
- FEATURE(AARCH64_SVESHA3, svesha3, "svesha3", 0, AARCH64_HWCAP2_SVESHA3) \
- FEATURE(AARCH64_SVESM4, svesm4, "svesm4", 0, AARCH64_HWCAP2_SVESM4) \
- FEATURE(AARCH64_FLAGM2, flagm2, "flagm2", 0, AARCH64_HWCAP2_FLAGM2) \
- FEATURE(AARCH64_FRINT, frint, "frint", 0, AARCH64_HWCAP2_FRINT) \
- FEATURE(AARCH64_SVEI8MM, svei8mm, "svei8mm", 0, AARCH64_HWCAP2_SVEI8MM) \
- FEATURE(AARCH64_SVEF32MM, svef32mm, "svef32mm", 0, AARCH64_HWCAP2_SVEF32MM) \
- FEATURE(AARCH64_SVEF64MM, svef64mm, "svef64mm", 0, AARCH64_HWCAP2_SVEF64MM) \
- FEATURE(AARCH64_SVEBF16, svebf16, "svebf16", 0, AARCH64_HWCAP2_SVEBF16) \
- FEATURE(AARCH64_I8MM, i8mm, "i8mm", 0, AARCH64_HWCAP2_I8MM) \
- FEATURE(AARCH64_BF16, bf16, "bf16", 0, AARCH64_HWCAP2_BF16) \
- FEATURE(AARCH64_DGH, dgh, "dgh", 0, AARCH64_HWCAP2_DGH) \
- FEATURE(AARCH64_RNG, rng, "rng", 0, AARCH64_HWCAP2_RNG) \
- FEATURE(AARCH64_BTI, bti, "bti", 0, AARCH64_HWCAP2_BTI)
-#define DEFINE_TABLE_FEATURE_TYPE Aarch64Features
-#include "define_tables.h"
+static const CapabilityConfig kConfigs[] = {
+ [AARCH64_FP] = {{AARCH64_HWCAP_FP, 0}, "fp", &set_fp}, //
+ [AARCH64_ASIMD] = {{AARCH64_HWCAP_ASIMD, 0}, "asimd", &set_asimd}, //
+ [AARCH64_AES] = {{AARCH64_HWCAP_AES, 0}, "aes", &set_aes}, //
+ [AARCH64_PMULL] = {{AARCH64_HWCAP_PMULL, 0}, "pmull", &set_pmull}, //
+ [AARCH64_SHA1] = {{AARCH64_HWCAP_SHA1, 0}, "sha1", &set_sha1}, //
+ [AARCH64_SHA2] = {{AARCH64_HWCAP_SHA2, 0}, "sha2", &set_sha2}, //
+ [AARCH64_CRC32] {{AARCH64_HWCAP_CRC32, 0}, "crc32", &set_crc32}, //
+};
+
+static const size_t kConfigsSize = sizeof(kConfigs) / sizeof(CapabilityConfig);
static bool HandleAarch64Line(const LineResult result,
Aarch64Info* const info) {
@@ -85,10 +49,7 @@ static bool HandleAarch64Line(const LineResult result,
StringView key, value;
if (CpuFeatures_StringView_GetAttributeKeyValue(line, &key, &value)) {
if (CpuFeatures_StringView_IsEquals(key, str("Features"))) {
- for (size_t i = 0; i < AARCH64_LAST_; ++i) {
- kSetters[i](&info->features,
- CpuFeatures_StringView_HasWord(value, kCpuInfoFlags[i]));
- }
+ CpuFeatures_SetFromFlags(kConfigsSize, kConfigs, value, &info->features);
} else if (CpuFeatures_StringView_IsEquals(key, str("CPU implementer"))) {
info->implementer = CpuFeatures_StringView_ParsePositiveNumber(value);
} else if (CpuFeatures_StringView_IsEquals(key, str("CPU variant"))) {
@@ -119,18 +80,17 @@ static void FillProcCpuInfoData(Aarch64Info* const info) {
static const Aarch64Info kEmptyAarch64Info;
Aarch64Info GetAarch64Info(void) {
+ assert(kConfigsSize == AARCH64_LAST_);
+
// capabilities are fetched from both getauxval and /proc/cpuinfo so we can
// have some information if the executable is sandboxed (aka no access to
// /proc/cpuinfo).
Aarch64Info info = kEmptyAarch64Info;
FillProcCpuInfoData(&info);
- const HardwareCapabilities hwcaps = CpuFeatures_GetHardwareCapabilities();
- for (size_t i = 0; i < AARCH64_LAST_; ++i) {
- if (CpuFeatures_IsHwCapsSet(kHardwareCapabilities[i], hwcaps)) {
- kSetters[i](&info.features, true);
- }
- }
+ CpuFeatures_OverrideFromHwCaps(kConfigsSize, kConfigs,
+ CpuFeatures_GetHardwareCapabilities(),
+ &info.features);
return info;
}
@@ -140,11 +100,29 @@ Aarch64Info GetAarch64Info(void) {
int GetAarch64FeaturesEnumValue(const Aarch64Features* features,
Aarch64FeaturesEnum value) {
- if (value >= AARCH64_LAST_) return false;
- return kGetters[value](features);
+ switch (value) {
+ case AARCH64_FP:
+ return features->fp;
+ case AARCH64_ASIMD:
+ return features->asimd;
+ case AARCH64_AES:
+ return features->aes;
+ case AARCH64_PMULL:
+ return features->pmull;
+ case AARCH64_SHA1:
+ return features->sha1;
+ case AARCH64_SHA2:
+ return features->sha2;
+ case AARCH64_CRC32:
+ return features->crc32;
+ case AARCH64_LAST_:
+ break;
+ }
+ return false;
}
const char* GetAarch64FeaturesEnumName(Aarch64FeaturesEnum value) {
- if (value >= AARCH64_LAST_) return "unknown feature";
- return kCpuInfoFlags[value];
+ if(value >= kConfigsSize)
+ return "unknown feature";
+ return kConfigs[value].proc_cpuinfo_flag;
}
diff --git a/src/cpuinfo_arm.c b/src/cpuinfo_arm.c
index 0f216bf..66c6d91 100644
--- a/src/cpuinfo_arm.c
+++ b/src/cpuinfo_arm.c
@@ -1,4 +1,4 @@
-// Copyright 2017 Google LLC
+// Copyright 2017 Google Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
@@ -14,47 +14,75 @@
#include "cpuinfo_arm.h"
-#include <assert.h>
-#include <ctype.h>
-
#include "internal/bit_utils.h"
#include "internal/filesystem.h"
#include "internal/hwcaps.h"
#include "internal/stack_line_reader.h"
#include "internal/string_view.h"
+#include "internal/unix_features_aggregator.h"
+
+#include <assert.h>
+#include <ctype.h>
+
+DECLARE_SETTER(ArmFeatures, swp)
+DECLARE_SETTER(ArmFeatures, half)
+DECLARE_SETTER(ArmFeatures, thumb)
+DECLARE_SETTER(ArmFeatures, _26bit)
+DECLARE_SETTER(ArmFeatures, fastmult)
+DECLARE_SETTER(ArmFeatures, fpa)
+DECLARE_SETTER(ArmFeatures, vfp)
+DECLARE_SETTER(ArmFeatures, edsp)
+DECLARE_SETTER(ArmFeatures, java)
+DECLARE_SETTER(ArmFeatures, iwmmxt)
+DECLARE_SETTER(ArmFeatures, crunch)
+DECLARE_SETTER(ArmFeatures, thumbee)
+DECLARE_SETTER(ArmFeatures, neon)
+DECLARE_SETTER(ArmFeatures, vfpv3)
+DECLARE_SETTER(ArmFeatures, vfpv3d16)
+DECLARE_SETTER(ArmFeatures, tls)
+DECLARE_SETTER(ArmFeatures, vfpv4)
+DECLARE_SETTER(ArmFeatures, idiva)
+DECLARE_SETTER(ArmFeatures, idivt)
+DECLARE_SETTER(ArmFeatures, vfpd32)
+DECLARE_SETTER(ArmFeatures, lpae)
+DECLARE_SETTER(ArmFeatures, evtstrm)
+DECLARE_SETTER(ArmFeatures, aes)
+DECLARE_SETTER(ArmFeatures, pmull)
+DECLARE_SETTER(ArmFeatures, sha1)
+DECLARE_SETTER(ArmFeatures, sha2)
+DECLARE_SETTER(ArmFeatures, crc32)
-// Generation of feature's getters/setters functions and kGetters, kSetters,
-// kCpuInfoFlags and kHardwareCapabilities global tables.
-#define DEFINE_TABLE_FEATURES \
- FEATURE(ARM_SWP, swp, "swp", ARM_HWCAP_SWP, 0) \
- FEATURE(ARM_HALF, half, "half", ARM_HWCAP_HALF, 0) \
- FEATURE(ARM_THUMB, thumb, "thumb", ARM_HWCAP_THUMB, 0) \
- FEATURE(ARM_26BIT, _26bit, "26bit", ARM_HWCAP_26BIT, 0) \
- FEATURE(ARM_FASTMULT, fastmult, "fastmult", ARM_HWCAP_FAST_MULT, 0) \
- FEATURE(ARM_FPA, fpa, "fpa", ARM_HWCAP_FPA, 0) \
- FEATURE(ARM_VFP, vfp, "vfp", ARM_HWCAP_VFP, 0) \
- FEATURE(ARM_EDSP, edsp, "edsp", ARM_HWCAP_EDSP, 0) \
- FEATURE(ARM_JAVA, java, "java", ARM_HWCAP_JAVA, 0) \
- FEATURE(ARM_IWMMXT, iwmmxt, "iwmmxt", ARM_HWCAP_IWMMXT, 0) \
- FEATURE(ARM_CRUNCH, crunch, "crunch", ARM_HWCAP_CRUNCH, 0) \
- FEATURE(ARM_THUMBEE, thumbee, "thumbee", ARM_HWCAP_THUMBEE, 0) \
- FEATURE(ARM_NEON, neon, "neon", ARM_HWCAP_NEON, 0) \
- FEATURE(ARM_VFPV3, vfpv3, "vfpv3", ARM_HWCAP_VFPV3, 0) \
- FEATURE(ARM_VFPV3D16, vfpv3d16, "vfpv3d16", ARM_HWCAP_VFPV3D16, 0) \
- FEATURE(ARM_TLS, tls, "tls", ARM_HWCAP_TLS, 0) \
- FEATURE(ARM_VFPV4, vfpv4, "vfpv4", ARM_HWCAP_VFPV4, 0) \
- FEATURE(ARM_IDIVA, idiva, "idiva", ARM_HWCAP_IDIVA, 0) \
- FEATURE(ARM_IDIVT, idivt, "idivt", ARM_HWCAP_IDIVT, 0) \
- FEATURE(ARM_VFPD32, vfpd32, "vfpd32", ARM_HWCAP_VFPD32, 0) \
- FEATURE(ARM_LPAE, lpae, "lpae", ARM_HWCAP_LPAE, 0) \
- FEATURE(ARM_EVTSTRM, evtstrm, "evtstrm", ARM_HWCAP_EVTSTRM, 0) \
- FEATURE(ARM_AES, aes, "aes", 0, ARM_HWCAP2_AES) \
- FEATURE(ARM_PMULL, pmull, "pmull", 0, ARM_HWCAP2_PMULL) \
- FEATURE(ARM_SHA1, sha1, "sha1", 0, ARM_HWCAP2_SHA1) \
- FEATURE(ARM_SHA2, sha2, "sha2", 0, ARM_HWCAP2_SHA2) \
- FEATURE(ARM_CRC32, crc32, "crc32", 0, ARM_HWCAP2_CRC32)
-#define DEFINE_TABLE_FEATURE_TYPE ArmFeatures
-#include "define_tables.h"
+static const CapabilityConfig kConfigs[] = {
+ [ARM_SWP] = {{ARM_HWCAP_SWP, 0}, "swp", &set_swp}, //
+ [ARM_HALF] = {{ARM_HWCAP_HALF, 0}, "half", &set_half}, //
+ [ARM_THUMB] = {{ARM_HWCAP_THUMB, 0}, "thumb", &set_thumb}, //
+ [ARM_26BIT] = {{ARM_HWCAP_26BIT, 0}, "26bit", &set__26bit}, //
+ [ARM_FASTMULT] = {{ARM_HWCAP_FAST_MULT, 0}, "fastmult", &set_fastmult}, //
+ [ARM_FPA] = {{ARM_HWCAP_FPA, 0}, "fpa", &set_fpa}, //
+ [ARM_VFP] = {{ARM_HWCAP_VFP, 0}, "vfp", &set_vfp}, //
+ [ARM_EDSP] = {{ARM_HWCAP_EDSP, 0}, "edsp", &set_edsp}, //
+ [ARM_JAVA] = {{ARM_HWCAP_JAVA, 0}, "java", &set_java}, //
+ [ARM_IWMMXT] = {{ARM_HWCAP_IWMMXT, 0}, "iwmmxt", &set_iwmmxt}, //
+ [ARM_CRUNCH] = {{ARM_HWCAP_CRUNCH, 0}, "crunch", &set_crunch}, //
+ [ARM_THUMBEE] = {{ARM_HWCAP_THUMBEE, 0}, "thumbee", &set_thumbee}, //
+ [ARM_NEON] = {{ARM_HWCAP_NEON, 0}, "neon", &set_neon}, //
+ [ARM_VFPV3] = {{ARM_HWCAP_VFPV3, 0}, "vfpv3", &set_vfpv3}, //
+ [ARM_VFPV3D16] = {{ARM_HWCAP_VFPV3D16, 0}, "vfpv3d16", &set_vfpv3d16}, //
+ [ARM_TLS] = {{ARM_HWCAP_TLS, 0}, "tls", &set_tls}, //
+ [ARM_VFPV4] = {{ARM_HWCAP_VFPV4, 0}, "vfpv4", &set_vfpv4}, //
+ [ARM_IDIVA] = {{ARM_HWCAP_IDIVA, 0}, "idiva", &set_idiva}, //
+ [ARM_IDIVT] = {{ARM_HWCAP_IDIVT, 0}, "idivt", &set_idivt}, //
+ [ARM_VFPD32] = {{ARM_HWCAP_VFPD32, 0}, "vfpd32", &set_vfpd32}, //
+ [ARM_LPAE] = {{ARM_HWCAP_LPAE, 0}, "lpae", &set_lpae}, //
+ [ARM_EVTSTRM] = {{ARM_HWCAP_EVTSTRM, 0}, "evtstrm", &set_evtstrm}, //
+ [ARM_AES] = {{0, ARM_HWCAP2_AES}, "aes", &set_aes}, //
+ [ARM_PMULL] = {{0, ARM_HWCAP2_PMULL}, "pmull", &set_pmull}, //
+ [ARM_SHA1] = {{0, ARM_HWCAP2_SHA1}, "sha1", &set_sha1}, //
+ [ARM_SHA2] = {{0, ARM_HWCAP2_SHA2}, "sha2", &set_sha2}, //
+ [ARM_CRC32] = {{0, ARM_HWCAP2_CRC32}, "crc32", &set_crc32}, //
+};
+
+static const size_t kConfigsSize = sizeof(kConfigs) / sizeof(CapabilityConfig);
typedef struct {
bool processor_reports_armv6;
@@ -76,10 +104,7 @@ static bool HandleArmLine(const LineResult result, ArmInfo* const info,
StringView key, value;
if (CpuFeatures_StringView_GetAttributeKeyValue(line, &key, &value)) {
if (CpuFeatures_StringView_IsEquals(key, str("Features"))) {
- for (size_t i = 0; i < ARM_LAST_; ++i) {
- kSetters[i](&info->features,
- CpuFeatures_StringView_HasWord(value, kCpuInfoFlags[i]));
- }
+ CpuFeatures_SetFromFlags(kConfigsSize, kConfigs, value, &info->features);
} else if (CpuFeatures_StringView_IsEquals(key, str("CPU implementer"))) {
info->implementer = CpuFeatures_StringView_ParsePositiveNumber(value);
} else if (CpuFeatures_StringView_IsEquals(key, str("CPU variant"))) {
@@ -94,8 +119,8 @@ static bool HandleArmLine(const LineResult result, ArmInfo* const info,
const StringView digits =
CpuFeatures_StringView_KeepFront(value, IndexOfNonDigit(value));
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
// also in "model name", Linux reports it only in "model name"
// see RaspberryPiZero (Linux) vs InvalidArmv7 (Android) test-cases
@@ -185,12 +210,9 @@ ArmInfo GetArmInfo(void) {
ProcCpuInfoData proc_cpu_info_data = kEmptyProcCpuInfoData;
FillProcCpuInfoData(&info, &proc_cpu_info_data);
- const HardwareCapabilities hwcaps = CpuFeatures_GetHardwareCapabilities();
- for (size_t i = 0; i < ARM_LAST_; ++i) {
- if (CpuFeatures_IsHwCapsSet(kHardwareCapabilities[i], hwcaps)) {
- kSetters[i](&info.features, true);
- }
- }
+ CpuFeatures_OverrideFromHwCaps(kConfigsSize, kConfigs,
+ CpuFeatures_GetHardwareCapabilities(),
+ &info.features);
FixErrors(&info, &proc_cpu_info_data);
@@ -202,11 +224,69 @@ ArmInfo GetArmInfo(void) {
int GetArmFeaturesEnumValue(const ArmFeatures* features,
ArmFeaturesEnum value) {
- if (value >= ARM_LAST_) return false;
- return kGetters[value](features);
+ switch (value) {
+ case ARM_SWP:
+ return features->swp;
+ case ARM_HALF:
+ return features->half;
+ case ARM_THUMB:
+ return features->thumb;
+ case ARM_26BIT:
+ return features->_26bit;
+ case ARM_FASTMULT:
+ return features->fastmult;
+ case ARM_FPA:
+ return features->fpa;
+ case ARM_VFP:
+ return features->vfp;
+ case ARM_EDSP:
+ return features->edsp;
+ case ARM_JAVA:
+ return features->java;
+ case ARM_IWMMXT:
+ return features->iwmmxt;
+ case ARM_CRUNCH:
+ return features->crunch;
+ case ARM_THUMBEE:
+ return features->thumbee;
+ case ARM_NEON:
+ return features->neon;
+ case ARM_VFPV3:
+ return features->vfpv3;
+ case ARM_VFPV3D16:
+ return features->vfpv3d16;
+ case ARM_TLS:
+ return features->tls;
+ case ARM_VFPV4:
+ return features->vfpv4;
+ case ARM_IDIVA:
+ return features->idiva;
+ case ARM_IDIVT:
+ return features->idivt;
+ case ARM_VFPD32:
+ return features->vfpd32;
+ case ARM_LPAE:
+ return features->lpae;
+ case ARM_EVTSTRM:
+ return features->evtstrm;
+ case ARM_AES:
+ return features->aes;
+ case ARM_PMULL:
+ return features->pmull;
+ case ARM_SHA1:
+ return features->sha1;
+ case ARM_SHA2:
+ return features->sha2;
+ case ARM_CRC32:
+ return features->crc32;
+ case ARM_LAST_:
+ break;
+ }
+ return false;
}
const char* GetArmFeaturesEnumName(ArmFeaturesEnum value) {
- if (value >= ARM_LAST_) return "unknown feature";
- return kCpuInfoFlags[value];
+ if(value >= kConfigsSize)
+ return "unknown feature";
+ return kConfigs[value].proc_cpuinfo_flag;
}
diff --git a/src/cpuinfo_mips.c b/src/cpuinfo_mips.c
index 83e959f..8769211 100644
--- a/src/cpuinfo_mips.c
+++ b/src/cpuinfo_mips.c
@@ -1,4 +1,4 @@
-// Copyright 2017 Google LLC
+// Copyright 2017 Google Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
@@ -14,21 +14,23 @@
#include "cpuinfo_mips.h"
-#include <assert.h>
-
#include "internal/filesystem.h"
-#include "internal/hwcaps.h"
#include "internal/stack_line_reader.h"
#include "internal/string_view.h"
+#include "internal/unix_features_aggregator.h"
+
+#include <assert.h>
+
+DECLARE_SETTER(MipsFeatures, msa)
+DECLARE_SETTER(MipsFeatures, eva)
+DECLARE_SETTER(MipsFeatures, r6)
-// Generation of feature's getters/setters functions and kGetters, kSetters,
-// kCpuInfoFlags and kHardwareCapabilities global tables.
-#define DEFINE_TABLE_FEATURES \
- FEATURE(MIPS_MSA, msa, "msa", MIPS_HWCAP_MSA, 0) \
- FEATURE(MIPS_EVA, eva, "eva", 0, 0) \
- FEATURE(MIPS_R6, r6, "r6", MIPS_HWCAP_R6, 0)
-#define DEFINE_TABLE_FEATURE_TYPE MipsFeatures
-#include "define_tables.h"
+static const CapabilityConfig kConfigs[] = {
+ [MIPS_MSA] = {{MIPS_HWCAP_MSA, 0}, "msa", &set_msa}, //
+ [MIPS_EVA] = {{0, 0}, "eva", &set_eva}, //
+ [MIPS_R6] = {{MIPS_HWCAP_R6, 0}, "r6", &set_r6}, //
+};
+static const size_t kConfigsSize = sizeof(kConfigs) / sizeof(CapabilityConfig);
static bool HandleMipsLine(const LineResult result,
MipsFeatures* const features) {
@@ -36,10 +38,7 @@ static bool HandleMipsLine(const LineResult result,
// See tests for an example.
if (CpuFeatures_StringView_GetAttributeKeyValue(result.line, &key, &value)) {
if (CpuFeatures_StringView_IsEquals(key, str("ASEs implemented"))) {
- for (size_t i = 0; i < MIPS_LAST_; ++i) {
- kSetters[i](features,
- CpuFeatures_StringView_HasWord(value, kCpuInfoFlags[i]));
- }
+ CpuFeatures_SetFromFlags(kConfigsSize, kConfigs, value, features);
}
}
return !result.eof;
@@ -62,18 +61,17 @@ static void FillProcCpuInfoData(MipsFeatures* const features) {
static const MipsInfo kEmptyMipsInfo;
MipsInfo GetMipsInfo(void) {
+ assert(kConfigsSize == MIPS_LAST_);
+
// capabilities are fetched from both getauxval and /proc/cpuinfo so we can
// have some information if the executable is sandboxed (aka no access to
// /proc/cpuinfo).
MipsInfo info = kEmptyMipsInfo;
FillProcCpuInfoData(&info.features);
- const HardwareCapabilities hwcaps = CpuFeatures_GetHardwareCapabilities();
- for (size_t i = 0; i < MIPS_LAST_; ++i) {
- if (CpuFeatures_IsHwCapsSet(kHardwareCapabilities[i], hwcaps)) {
- kSetters[i](&info.features, true);
- }
- }
+ CpuFeatures_OverrideFromHwCaps(kConfigsSize, kConfigs,
+ CpuFeatures_GetHardwareCapabilities(),
+ &info.features);
return info;
}
@@ -82,11 +80,21 @@ MipsInfo GetMipsInfo(void) {
int GetMipsFeaturesEnumValue(const MipsFeatures* features,
MipsFeaturesEnum value) {
- if (value >= MIPS_LAST_) return false;
- return kGetters[value](features);
+ switch (value) {
+ case MIPS_MSA:
+ return features->msa;
+ case MIPS_EVA:
+ return features->eva;
+ case MIPS_R6:
+ return features->r6;
+ case MIPS_LAST_:
+ break;
+ }
+ return false;
}
const char* GetMipsFeaturesEnumName(MipsFeaturesEnum value) {
- if (value >= MIPS_LAST_) return "unknown feature";
- return kCpuInfoFlags[value];
+ if(value >= kConfigsSize)
+ return "unknown feature";
+ return kConfigs[value].proc_cpuinfo_flag;
}
diff --git a/src/cpuinfo_ppc.c b/src/cpuinfo_ppc.c
index 24401f9..d6c49f8 100644
--- a/src/cpuinfo_ppc.c
+++ b/src/cpuinfo_ppc.c
@@ -12,69 +12,105 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-#include "cpuinfo_ppc.h"
-
#include <assert.h>
#include <stdbool.h>
#include <string.h>
+#include "cpuinfo_ppc.h"
#include "internal/bit_utils.h"
#include "internal/filesystem.h"
#include "internal/stack_line_reader.h"
#include "internal/string_view.h"
+#include "internal/unix_features_aggregator.h"
+
+DECLARE_SETTER(PPCFeatures, ppc32)
+DECLARE_SETTER(PPCFeatures, ppc64)
+DECLARE_SETTER(PPCFeatures, ppc601)
+DECLARE_SETTER(PPCFeatures, altivec)
+DECLARE_SETTER(PPCFeatures, fpu)
+DECLARE_SETTER(PPCFeatures, mmu)
+DECLARE_SETTER(PPCFeatures, mac_4xx)
+DECLARE_SETTER(PPCFeatures, unifiedcache)
+DECLARE_SETTER(PPCFeatures, spe)
+DECLARE_SETTER(PPCFeatures, efpsingle)
+DECLARE_SETTER(PPCFeatures, efpdouble)
+DECLARE_SETTER(PPCFeatures, no_tb)
+DECLARE_SETTER(PPCFeatures, power4)
+DECLARE_SETTER(PPCFeatures, power5)
+DECLARE_SETTER(PPCFeatures, power5plus)
+DECLARE_SETTER(PPCFeatures, cell)
+DECLARE_SETTER(PPCFeatures, booke)
+DECLARE_SETTER(PPCFeatures, smt)
+DECLARE_SETTER(PPCFeatures, icachesnoop)
+DECLARE_SETTER(PPCFeatures, arch205)
+DECLARE_SETTER(PPCFeatures, pa6t)
+DECLARE_SETTER(PPCFeatures, dfp)
+DECLARE_SETTER(PPCFeatures, power6ext)
+DECLARE_SETTER(PPCFeatures, arch206)
+DECLARE_SETTER(PPCFeatures, vsx)
+DECLARE_SETTER(PPCFeatures, pseries_perfmon_compat)
+DECLARE_SETTER(PPCFeatures, truele)
+DECLARE_SETTER(PPCFeatures, ppcle)
+DECLARE_SETTER(PPCFeatures, arch207)
+DECLARE_SETTER(PPCFeatures, htm)
+DECLARE_SETTER(PPCFeatures, dscr)
+DECLARE_SETTER(PPCFeatures, ebb)
+DECLARE_SETTER(PPCFeatures, isel)
+DECLARE_SETTER(PPCFeatures, tar)
+DECLARE_SETTER(PPCFeatures, vcrypto)
+DECLARE_SETTER(PPCFeatures, htm_nosc)
+DECLARE_SETTER(PPCFeatures, arch300)
+DECLARE_SETTER(PPCFeatures, ieee128)
+DECLARE_SETTER(PPCFeatures, darn)
+DECLARE_SETTER(PPCFeatures, scv)
+DECLARE_SETTER(PPCFeatures, htm_no_suspend)
-// Generation of feature's getters/setters functions and kGetters, kSetters,
-// kCpuInfoFlags and kHardwareCapabilities global tables.
-#define DEFINE_TABLE_FEATURES \
- FEATURE(PPC_32, ppc32, "ppc32", PPC_FEATURE_32, 0) \
- FEATURE(PPC_64, ppc64, "ppc64", PPC_FEATURE_64, 0) \
- FEATURE(PPC_601_INSTR, ppc601, "ppc601", PPC_FEATURE_601_INSTR, 0) \
- FEATURE(PPC_HAS_ALTIVEC, altivec, "altivec", PPC_FEATURE_HAS_ALTIVEC, 0) \
- FEATURE(PPC_HAS_FPU, fpu, "fpu", PPC_FEATURE_HAS_FPU, 0) \
- FEATURE(PPC_HAS_MMU, mmu, "mmu", PPC_FEATURE_HAS_MMU, 0) \
- FEATURE(PPC_HAS_4xxMAC, mac_4xx, "4xxmac", PPC_FEATURE_HAS_4xxMAC, 0) \
- FEATURE(PPC_UNIFIED_CACHE, unifiedcache, "ucache", \
- PPC_FEATURE_UNIFIED_CACHE, 0) \
- FEATURE(PPC_HAS_SPE, spe, "spe", PPC_FEATURE_HAS_SPE, 0) \
- FEATURE(PPC_HAS_EFP_SINGLE, efpsingle, "efpsingle", \
- PPC_FEATURE_HAS_EFP_SINGLE, 0) \
- FEATURE(PPC_HAS_EFP_DOUBLE, efpdouble, "efpdouble", \
- PPC_FEATURE_HAS_EFP_DOUBLE, 0) \
- FEATURE(PPC_NO_TB, no_tb, "notb", PPC_FEATURE_NO_TB, 0) \
- FEATURE(PPC_POWER4, power4, "power4", PPC_FEATURE_POWER4, 0) \
- FEATURE(PPC_POWER5, power5, "power5", PPC_FEATURE_POWER5, 0) \
- FEATURE(PPC_POWER5_PLUS, power5plus, "power5+", PPC_FEATURE_POWER5_PLUS, 0) \
- FEATURE(PPC_CELL, cell, "cellbe", PPC_FEATURE_CELL, 0) \
- FEATURE(PPC_BOOKE, booke, "booke", PPC_FEATURE_BOOKE, 0) \
- FEATURE(PPC_SMT, smt, "smt", PPC_FEATURE_SMT, 0) \
- FEATURE(PPC_ICACHE_SNOOP, icachesnoop, "ic_snoop", PPC_FEATURE_ICACHE_SNOOP, \
- 0) \
- FEATURE(PPC_ARCH_2_05, arch205, "arch_2_05", PPC_FEATURE_ARCH_2_05, 0) \
- FEATURE(PPC_PA6T, pa6t, "pa6t", PPC_FEATURE_PA6T, 0) \
- FEATURE(PPC_HAS_DFP, dfp, "dfp", PPC_FEATURE_HAS_DFP, 0) \
- FEATURE(PPC_POWER6_EXT, power6ext, "power6x", PPC_FEATURE_POWER6_EXT, 0) \
- FEATURE(PPC_ARCH_2_06, arch206, "arch_2_06", PPC_FEATURE_ARCH_2_06, 0) \
- FEATURE(PPC_HAS_VSX, vsx, "vsx", PPC_FEATURE_HAS_VSX, 0) \
- FEATURE(PPC_PSERIES_PERFMON_COMPAT, pseries_perfmon_compat, "archpmu", \
- PPC_FEATURE_PSERIES_PERFMON_COMPAT, 0) \
- FEATURE(PPC_TRUE_LE, truele, "true_le", PPC_FEATURE_TRUE_LE, 0) \
- FEATURE(PPC_PPC_LE, ppcle, "ppcle", PPC_FEATURE_PPC_LE, 0) \
- FEATURE(PPC_ARCH_2_07, arch207, "arch_2_07", 0, PPC_FEATURE2_ARCH_2_07) \
- FEATURE(PPC_HTM, htm, "htm", 0, PPC_FEATURE2_HTM) \
- FEATURE(PPC_DSCR, dscr, "dscr", 0, PPC_FEATURE2_DSCR) \
- FEATURE(PPC_EBB, ebb, "ebb", 0, PPC_FEATURE2_EBB) \
- FEATURE(PPC_ISEL, isel, "isel", 0, PPC_FEATURE2_ISEL) \
- FEATURE(PPC_TAR, tar, "tar", 0, PPC_FEATURE2_TAR) \
- FEATURE(PPC_VEC_CRYPTO, vcrypto, "vcrypto", 0, PPC_FEATURE2_VEC_CRYPTO) \
- FEATURE(PPC_HTM_NOSC, htm_nosc, "htm-nosc", 0, PPC_FEATURE2_HTM_NOSC) \
- FEATURE(PPC_ARCH_3_00, arch300, "arch_3_00", 0, PPC_FEATURE2_ARCH_3_00) \
- FEATURE(PPC_HAS_IEEE128, ieee128, "ieee128", 0, PPC_FEATURE2_HAS_IEEE128) \
- FEATURE(PPC_DARN, darn, "darn", 0, PPC_FEATURE2_DARN) \
- FEATURE(PPC_SCV, scv, "scv", 0, PPC_FEATURE2_SCV) \
- FEATURE(PPC_HTM_NO_SUSPEND, htm_no_suspend, "htm-no-suspend", 0, \
- PPC_FEATURE2_HTM_NO_SUSPEND)
-#define DEFINE_TABLE_FEATURE_TYPE PPCFeatures
-#include "define_tables.h"
+static const CapabilityConfig kConfigs[] = {
+ [PPC_32] = {{PPC_FEATURE_32, 0}, "ppc32", &set_ppc32},
+ [PPC_64] = {{PPC_FEATURE_64, 0}, "ppc64", &set_ppc64},
+ [PPC_601_INSTR] = {{PPC_FEATURE_601_INSTR, 0}, "ppc601", &set_ppc601},
+ [PPC_HAS_ALTIVEC] = {{PPC_FEATURE_HAS_ALTIVEC, 0}, "altivec", &set_altivec},
+ [PPC_HAS_FPU] = {{PPC_FEATURE_HAS_FPU, 0}, "fpu", &set_fpu},
+ [PPC_HAS_MMU] = {{PPC_FEATURE_HAS_MMU, 0}, "mmu", &set_mmu},
+ [PPC_HAS_4xxMAC] = {{PPC_FEATURE_HAS_4xxMAC, 0}, "4xxmac", &set_mac_4xx},
+ [PPC_UNIFIED_CACHE] = {{PPC_FEATURE_UNIFIED_CACHE, 0}, "ucache", &set_unifiedcache},
+ [PPC_HAS_SPE] = {{PPC_FEATURE_HAS_SPE, 0}, "spe", &set_spe},
+ [PPC_HAS_EFP_SINGLE] = {{PPC_FEATURE_HAS_EFP_SINGLE, 0}, "efpsingle", &set_efpsingle},
+ [PPC_HAS_EFP_DOUBLE] = {{PPC_FEATURE_HAS_EFP_DOUBLE, 0}, "efpdouble", &set_efpdouble},
+ [PPC_NO_TB] = {{PPC_FEATURE_NO_TB, 0}, "notb", &set_no_tb},
+ [PPC_POWER4] = {{PPC_FEATURE_POWER4, 0}, "power4", &set_power4},
+ [PPC_POWER5] = {{PPC_FEATURE_POWER5, 0}, "power5", &set_power5},
+ [PPC_POWER5_PLUS] = {{PPC_FEATURE_POWER5_PLUS, 0}, "power5+", &set_power5plus},
+ [PPC_CELL] = {{PPC_FEATURE_CELL, 0}, "cellbe", &set_cell},
+ [PPC_BOOKE] = {{PPC_FEATURE_BOOKE, 0}, "booke", &set_booke},
+ [PPC_SMT] = {{PPC_FEATURE_SMT, 0}, "smt", &set_smt},
+ [PPC_ICACHE_SNOOP] = {{PPC_FEATURE_ICACHE_SNOOP, 0}, "ic_snoop", &set_icachesnoop},
+ [PPC_ARCH_2_05] = {{PPC_FEATURE_ARCH_2_05, 0}, "arch_2_05", &set_arch205},
+ [PPC_PA6T] = {{PPC_FEATURE_PA6T, 0}, "pa6t", &set_pa6t},
+ [PPC_HAS_DFP] = {{PPC_FEATURE_HAS_DFP, 0}, "dfp", &set_dfp},
+ [PPC_POWER6_EXT] = {{PPC_FEATURE_POWER6_EXT, 0}, "power6x", &set_power6ext},
+ [PPC_ARCH_2_06] = {{PPC_FEATURE_ARCH_2_06, 0}, "arch_2_06", &set_arch206},
+ [PPC_HAS_VSX] = {{PPC_FEATURE_HAS_VSX, 0}, "vsx", &set_vsx},
+ [PPC_PSERIES_PERFMON_COMPAT] = {{PPC_FEATURE_PSERIES_PERFMON_COMPAT, 0},
+ "archpmu",
+ &set_pseries_perfmon_compat},
+ [PPC_TRUE_LE] = {{PPC_FEATURE_TRUE_LE, 0}, "true_le", &set_truele},
+ [PPC_PPC_LE] = {{PPC_FEATURE_PPC_LE, 0}, "ppcle", &set_ppcle},
+ [PPC_ARCH_2_07] = {{0, PPC_FEATURE2_ARCH_2_07}, "arch_2_07", &set_arch207},
+ [PPC_HTM] = {{0, PPC_FEATURE2_HTM}, "htm", &set_htm},
+ [PPC_DSCR] = {{0, PPC_FEATURE2_DSCR}, "dscr", &set_dscr},
+ [PPC_EBB] = {{0, PPC_FEATURE2_EBB}, "ebb", &set_ebb},
+ [PPC_ISEL] = {{0, PPC_FEATURE2_ISEL}, "isel", &set_isel},
+ [PPC_TAR] = {{0, PPC_FEATURE2_TAR}, "tar", &set_tar},
+ [PPC_VEC_CRYPTO] = {{0, PPC_FEATURE2_VEC_CRYPTO}, "vcrypto", &set_vcrypto},
+ [PPC_HTM_NOSC] = {{0, PPC_FEATURE2_HTM_NOSC}, "htm-nosc", &set_htm_nosc},
+ [PPC_ARCH_3_00] = {{0, PPC_FEATURE2_ARCH_3_00}, "arch_3_00", &set_arch300},
+ [PPC_HAS_IEEE128] = {{0, PPC_FEATURE2_HAS_IEEE128}, "ieee128", &set_ieee128},
+ [PPC_DARN] = {{0, PPC_FEATURE2_DARN}, "darn", &set_darn},
+ [PPC_SCV] = {{0, PPC_FEATURE2_SCV}, "scv", &set_scv},
+ [PPC_HTM_NO_SUSPEND] = {{0, PPC_FEATURE2_HTM_NO_SUSPEND}, "htm-no-suspend", &set_htm_no_suspend},
+};
+static const size_t kConfigsSize = sizeof(kConfigs) / sizeof(CapabilityConfig);
static bool HandlePPCLine(const LineResult result,
PPCPlatformStrings* const strings) {
@@ -120,12 +156,10 @@ PPCInfo GetPPCInfo(void) {
* the auxilary vector.
*/
PPCInfo info = kEmptyPPCInfo;
- const HardwareCapabilities hwcaps = CpuFeatures_GetHardwareCapabilities();
- for (size_t i = 0; i < PPC_LAST_; ++i) {
- if (CpuFeatures_IsHwCapsSet(kHardwareCapabilities[i], hwcaps)) {
- kSetters[i](&info.features, true);
- }
- }
+
+ CpuFeatures_OverrideFromHwCaps(kConfigsSize, kConfigs,
+ CpuFeatures_GetHardwareCapabilities(),
+ &info.features);
return info;
}
@@ -144,11 +178,98 @@ PPCPlatformStrings GetPPCPlatformStrings(void) {
int GetPPCFeaturesEnumValue(const PPCFeatures* features,
PPCFeaturesEnum value) {
- if (value >= PPC_LAST_) return false;
- return kGetters[value](features);
+ switch (value) {
+ case PPC_32:
+ return features->ppc32;
+ case PPC_64:
+ return features->ppc64;
+ case PPC_601_INSTR:
+ return features->ppc601;
+ case PPC_HAS_ALTIVEC:
+ return features->altivec;
+ case PPC_HAS_FPU:
+ return features->fpu;
+ case PPC_HAS_MMU:
+ return features->mmu;
+ case PPC_HAS_4xxMAC:
+ return features->mac_4xx;
+ case PPC_UNIFIED_CACHE:
+ return features->unifiedcache;
+ case PPC_HAS_SPE:
+ return features->spe;
+ case PPC_HAS_EFP_SINGLE:
+ return features->efpsingle;
+ case PPC_HAS_EFP_DOUBLE:
+ return features->efpdouble;
+ case PPC_NO_TB:
+ return features->no_tb;
+ case PPC_POWER4:
+ return features->power4;
+ case PPC_POWER5:
+ return features->power5;
+ case PPC_POWER5_PLUS:
+ return features->power5plus;
+ case PPC_CELL:
+ return features->cell;
+ case PPC_BOOKE:
+ return features->booke;
+ case PPC_SMT:
+ return features->smt;
+ case PPC_ICACHE_SNOOP:
+ return features->icachesnoop;
+ case PPC_ARCH_2_05:
+ return features->arch205;
+ case PPC_PA6T:
+ return features->pa6t;
+ case PPC_HAS_DFP:
+ return features->dfp;
+ case PPC_POWER6_EXT:
+ return features->power6ext;
+ case PPC_ARCH_2_06:
+ return features->arch206;
+ case PPC_HAS_VSX:
+ return features->vsx;
+ case PPC_PSERIES_PERFMON_COMPAT:
+ return features->pseries_perfmon_compat;
+ case PPC_TRUE_LE:
+ return features->truele;
+ case PPC_PPC_LE:
+ return features->ppcle;
+ case PPC_ARCH_2_07:
+ return features->arch207;
+ case PPC_HTM:
+ return features->htm;
+ case PPC_DSCR:
+ return features->dscr;
+ case PPC_EBB:
+ return features->ebb;
+ case PPC_ISEL:
+ return features->isel;
+ case PPC_TAR:
+ return features->tar;
+ case PPC_VEC_CRYPTO:
+ return features->vcrypto;
+ case PPC_HTM_NOSC:
+ return features->htm_nosc;
+ case PPC_ARCH_3_00:
+ return features->arch300;
+ case PPC_HAS_IEEE128:
+ return features->ieee128;
+ case PPC_DARN:
+ return features->darn;
+ case PPC_SCV:
+ return features->scv;
+ case PPC_HTM_NO_SUSPEND:
+ return features->htm_no_suspend;
+ case PPC_LAST_:
+ break;
+ }
+ return false;
}
+/* Have used the same names as glibc */
const char* GetPPCFeaturesEnumName(PPCFeaturesEnum value) {
- if (value >= PPC_LAST_) return "unknown feature";
- return kCpuInfoFlags[value];
+ if(value >= kConfigsSize)
+ return "unknown feature";
+ return kConfigs[value].proc_cpuinfo_flag;
}
diff --git a/src/cpuinfo_x86.c b/src/cpuinfo_x86.c
index 378ed05..c997b7b 100644
--- a/src/cpuinfo_x86.c
+++ b/src/cpuinfo_x86.c
@@ -1,5 +1,4 @@
-// Copyright 2017 Google LLC
-// Copyright 2020 Intel Corporation
+// Copyright 2017 Google Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
@@ -14,102 +13,16 @@
// limitations under the License.
#include "cpuinfo_x86.h"
+#include "internal/bit_utils.h"
+#include "internal/cpuid_x86.h"
#include <stdbool.h>
#include <string.h>
-#include "internal/bit_utils.h"
-#include "internal/cpuid_x86.h"
-
#if !defined(CPU_FEATURES_ARCH_X86)
#error "Cannot compile cpuinfo_x86 on a non x86 platform."
#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.
////////////////////////////////////////////////////////////////////////////////
@@ -120,7 +33,7 @@
#include <cpuid.h>
-Leaf GetCpuidLeaf(uint32_t leaf_id, int ecx) {
+Leaf CpuIdEx(uint32_t leaf_id, int ecx) {
Leaf leaf;
__cpuid_count(leaf_id, ecx, leaf.eax, leaf.ebx, leaf.ecx, leaf.edx);
return leaf;
@@ -140,7 +53,7 @@ uint32_t GetXCR0Eax(void) {
#include <immintrin.h>
#include <intrin.h> // For __cpuidex()
-Leaf GetCpuidLeaf(uint32_t leaf_id, int ecx) {
+Leaf CpuIdEx(uint32_t leaf_id, int ecx) {
Leaf leaf;
int data[4];
__cpuidex(data, leaf_id, ecx);
@@ -157,13 +70,13 @@ uint32_t GetXCR0Eax(void) { return (uint32_t)_xgetbv(0); }
#error "Unsupported compiler, x86 cpuid requires either GCC, Clang or MSVC."
#endif
-static Leaf CpuId(uint32_t leaf_id) { return GetCpuidLeaf(leaf_id, 0); }
+static Leaf CpuId(uint32_t leaf_id) { return CpuIdEx(leaf_id, 0); }
static const Leaf kEmptyLeaf;
static Leaf SafeCpuIdEx(uint32_t max_cpuid_leaf, uint32_t leaf_id, int ecx) {
if (leaf_id <= max_cpuid_leaf) {
- return GetCpuidLeaf(leaf_id, ecx);
+ return CpuIdEx(leaf_id, ecx);
} else {
return kEmptyLeaf;
}
@@ -178,8 +91,6 @@ static Leaf SafeCpuId(uint32_t max_cpuid_leaf, uint32_t leaf_id) {
#define MASK_MASKREG 0x20
#define MASK_ZMM0_15 0x40
#define MASK_ZMM16_31 0x80
-#define MASK_XTILECFG 0x20000
-#define MASK_XTILEDATA 0x40000
static bool HasMask(uint32_t value, uint32_t mask) {
return (value & mask) == mask;
@@ -204,42 +115,6 @@ static bool HasZmmOsXSave(uint32_t xcr0_eax) {
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) {
*(uint32_t*)(vendor) = leaf.ebx;
*(uint32_t*)(vendor + 4) = leaf.edx;
@@ -256,859 +131,345 @@ static int IsVendor(const Leaf leaf, const char* const name) {
static const CacheLevelInfo kEmptyCacheLevelInfo;
+static CacheLevelInfo MakeX86CacheLevelInfo(int level, CacheType cache_type,
+ int cache_size, int ways,
+ int line_size, int entries,
+ int partitioning) {
+ CacheLevelInfo info;
+ info.level = level;
+ info.cache_type = cache_type;
+ info.cache_size = cache_size;
+ info.ways = ways;
+ info.line_size = line_size;
+ info.tlb_entries = entries;
+ info.partitioning = partitioning;
+ return info;
+}
+
static CacheLevelInfo GetCacheLevelInfo(const uint32_t reg) {
const int UNDEF = -1;
const int KiB = 1024;
const int MiB = 1024 * KiB;
+ const int GiB = 1024 * MiB;
switch (reg) {
case 0x01:
- return (CacheLevelInfo){.level = UNDEF,
- .cache_type = CPU_FEATURE_CACHE_TLB,
- .cache_size = 4 * KiB,
- .ways = 4,
- .line_size = UNDEF,
- .tlb_entries = 32,
- .partitioning = 0};
+ return MakeX86CacheLevelInfo(UNDEF, CPU_FEATURE_CACHE_TLB, 4 * KiB, 4,
+ UNDEF, 32, 0);
case 0x02:
- return (CacheLevelInfo){.level = UNDEF,
- .cache_type = CPU_FEATURE_CACHE_TLB,
- .cache_size = 4 * MiB,
- .ways = 0xFF,
- .line_size = UNDEF,
- .tlb_entries = 2,
- .partitioning = 0};
+ return MakeX86CacheLevelInfo(UNDEF, CPU_FEATURE_CACHE_TLB, 4 * MiB, 0xFF,
+ UNDEF, 2, 0);
case 0x03:
- return (CacheLevelInfo){.level = UNDEF,
- .cache_type = CPU_FEATURE_CACHE_TLB,
- .cache_size = 4 * KiB,
- .ways = 4,
- .line_size = UNDEF,
- .tlb_entries = 64,
- .partitioning = 0};
+ return MakeX86CacheLevelInfo(UNDEF, CPU_FEATURE_CACHE_TLB, 4 * KiB, 4,
+ UNDEF, 64, 0);
case 0x04:
- return (CacheLevelInfo){.level = UNDEF,
- .cache_type = CPU_FEATURE_CACHE_TLB,
- .cache_size = 4 * MiB,
- .ways = 4,
- .line_size = UNDEF,
- .tlb_entries = 8,
- .partitioning = 0};
+ return MakeX86CacheLevelInfo(UNDEF, CPU_FEATURE_CACHE_TLB, 4 * MiB, 4,
+ UNDEF, 8, 0);
case 0x05:
- return (CacheLevelInfo){.level = UNDEF,
- .cache_type = CPU_FEATURE_CACHE_TLB,
- .cache_size = 4 * MiB,
- .ways = 4,
- .line_size = UNDEF,
- .tlb_entries = 32,
- .partitioning = 0};
+ return MakeX86CacheLevelInfo(UNDEF, CPU_FEATURE_CACHE_TLB, 4 * MiB, 4,
+ UNDEF, 32, 0);
case 0x06:
- return (CacheLevelInfo){.level = 1,
- .cache_type = CPU_FEATURE_CACHE_INSTRUCTION,
- .cache_size = 8 * KiB,
- .ways = 4,
- .line_size = 32,
- .tlb_entries = UNDEF,
- .partitioning = 0};
+ return MakeX86CacheLevelInfo(1, CPU_FEATURE_CACHE_INSTRUCTION, 8 * KiB, 4,
+ 32, UNDEF, 0);
case 0x08:
- return (CacheLevelInfo){.level = 1,
- .cache_type = CPU_FEATURE_CACHE_INSTRUCTION,
- .cache_size = 16 * KiB,
- .ways = 4,
- .line_size = 32,
- .tlb_entries = UNDEF,
- .partitioning = 0};
+ return MakeX86CacheLevelInfo(1, CPU_FEATURE_CACHE_INSTRUCTION, 16 * KiB,
+ 4, 32, UNDEF, 0);
case 0x09:
- return (CacheLevelInfo){.level = 1,
- .cache_type = CPU_FEATURE_CACHE_INSTRUCTION,
- .cache_size = 32 * KiB,
- .ways = 4,
- .line_size = 64,
- .tlb_entries = UNDEF,
- .partitioning = 0};
+ return MakeX86CacheLevelInfo(1, CPU_FEATURE_CACHE_INSTRUCTION, 32 * KiB,
+ 4, 64, UNDEF, 0);
case 0x0A:
- return (CacheLevelInfo){.level = 1,
- .cache_type = CPU_FEATURE_CACHE_DATA,
- .cache_size = 8 * KiB,
- .ways = 2,
- .line_size = 32,
- .tlb_entries = UNDEF,
- .partitioning = 0};
+ return MakeX86CacheLevelInfo(1, CPU_FEATURE_CACHE_DATA, 8 * KiB, 2, 32,
+ UNDEF, 0);
case 0x0B:
- return (CacheLevelInfo){.level = UNDEF,
- .cache_type = CPU_FEATURE_CACHE_TLB,
- .cache_size = 4 * MiB,
- .ways = 4,
- .line_size = UNDEF,
- .tlb_entries = 4,
- .partitioning = 0};
+ return MakeX86CacheLevelInfo(UNDEF, CPU_FEATURE_CACHE_TLB, 4 * MiB, 4,
+ UNDEF, 4, 0);
case 0x0C:
- return (CacheLevelInfo){.level = 1,
- .cache_type = CPU_FEATURE_CACHE_DATA,
- .cache_size = 16 * KiB,
- .ways = 4,
- .line_size = 32,
- .tlb_entries = UNDEF,
- .partitioning = 0};
+ return MakeX86CacheLevelInfo(1, CPU_FEATURE_CACHE_DATA, 16 * KiB, 4, 32,
+ UNDEF, 0);
case 0x0D:
- return (CacheLevelInfo){.level = 1,
- .cache_type = CPU_FEATURE_CACHE_DATA,
- .cache_size = 16 * KiB,
- .ways = 4,
- .line_size = 64,
- .tlb_entries = UNDEF,
- .partitioning = 0};
+ return MakeX86CacheLevelInfo(1, CPU_FEATURE_CACHE_DATA, 16 * KiB, 4, 64,
+ UNDEF, 0);
case 0x0E:
- return (CacheLevelInfo){.level = 1,
- .cache_type = CPU_FEATURE_CACHE_DATA,
- .cache_size = 24 * KiB,
- .ways = 6,
- .line_size = 64,
- .tlb_entries = UNDEF,
- .partitioning = 0};
+ return MakeX86CacheLevelInfo(1, CPU_FEATURE_CACHE_DATA, 24 * KiB, 6, 64,
+ UNDEF, 0);
case 0x1D:
- return (CacheLevelInfo){.level = 2,
- .cache_type = CPU_FEATURE_CACHE_DATA,
- .cache_size = 128 * KiB,
- .ways = 2,
- .line_size = 64,
- .tlb_entries = UNDEF,
- .partitioning = 0};
+ return MakeX86CacheLevelInfo(2, CPU_FEATURE_CACHE_DATA, 128 * KiB, 2, 64,
+ UNDEF, 0);
case 0x21:
- return (CacheLevelInfo){.level = 2,
- .cache_type = CPU_FEATURE_CACHE_DATA,
- .cache_size = 256 * KiB,
- .ways = 8,
- .line_size = 64,
- .tlb_entries = UNDEF,
- .partitioning = 0};
+ return MakeX86CacheLevelInfo(2, CPU_FEATURE_CACHE_DATA, 256 * KiB, 8, 64,
+ UNDEF, 0);
case 0x22:
- return (CacheLevelInfo){.level = 3,
- .cache_type = CPU_FEATURE_CACHE_DATA,
- .cache_size = 512 * KiB,
- .ways = 4,
- .line_size = 64,
- .tlb_entries = UNDEF,
- .partitioning = 2};
+ return MakeX86CacheLevelInfo(3, CPU_FEATURE_CACHE_DATA, 512 * KiB, 4, 64,
+ UNDEF, 2);
case 0x23:
- return (CacheLevelInfo){.level = 3,
- .cache_type = CPU_FEATURE_CACHE_DATA,
- .cache_size = 1 * MiB,
- .ways = 8,
- .line_size = 64,
- .tlb_entries = UNDEF,
- .partitioning = 2};
+ return MakeX86CacheLevelInfo(3, CPU_FEATURE_CACHE_DATA, 1 * MiB, 8, 64,
+ UNDEF, 2);
case 0x24:
- return (CacheLevelInfo){.level = 2,
- .cache_type = CPU_FEATURE_CACHE_DATA,
- .cache_size = 1 * MiB,
- .ways = 16,
- .line_size = 64,
- .tlb_entries = UNDEF,
- .partitioning = 0};
+ return MakeX86CacheLevelInfo(2, CPU_FEATURE_CACHE_DATA, 1 * MiB, 16, 64,
+ UNDEF, 0);
case 0x25:
- return (CacheLevelInfo){.level = 3,
- .cache_type = CPU_FEATURE_CACHE_DATA,
- .cache_size = 2 * MiB,
- .ways = 8,
- .line_size = 64,
- .tlb_entries = UNDEF,
- .partitioning = 2};
+ return MakeX86CacheLevelInfo(3, CPU_FEATURE_CACHE_DATA, 2 * MiB, 8, 64,
+ UNDEF, 2);
case 0x29:
- return (CacheLevelInfo){.level = 3,
- .cache_type = CPU_FEATURE_CACHE_DATA,
- .cache_size = 4 * MiB,
- .ways = 8,
- .line_size = 64,
- .tlb_entries = UNDEF,
- .partitioning = 2};
+ return MakeX86CacheLevelInfo(3, CPU_FEATURE_CACHE_DATA, 4 * MiB, 8, 64,
+ UNDEF, 2);
case 0x2C:
- return (CacheLevelInfo){.level = 1,
- .cache_type = CPU_FEATURE_CACHE_DATA,
- .cache_size = 32 * KiB,
- .ways = 8,
- .line_size = 64,
- .tlb_entries = UNDEF,
- .partitioning = 0};
+ return MakeX86CacheLevelInfo(1, CPU_FEATURE_CACHE_DATA, 32 * KiB, 8, 64,
+ UNDEF, 0);
case 0x30:
- return (CacheLevelInfo){.level = 1,
- .cache_type = CPU_FEATURE_CACHE_INSTRUCTION,
- .cache_size = 32 * KiB,
- .ways = 8,
- .line_size = 64,
- .tlb_entries = UNDEF,
- .partitioning = 0};
+ return MakeX86CacheLevelInfo(1, CPU_FEATURE_CACHE_INSTRUCTION, 32 * KiB,
+ 8, 64, UNDEF, 0);
case 0x40:
- return (CacheLevelInfo){.level = UNDEF,
- .cache_type = CPU_FEATURE_CACHE_DATA,
- .cache_size = UNDEF,
- .ways = UNDEF,
- .line_size = UNDEF,
- .tlb_entries = UNDEF,
- .partitioning = 0};
+ return MakeX86CacheLevelInfo(UNDEF, CPU_FEATURE_CACHE_DATA, UNDEF, UNDEF,
+ UNDEF, UNDEF, 0);
case 0x41:
- return (CacheLevelInfo){.level = 2,
- .cache_type = CPU_FEATURE_CACHE_DATA,
- .cache_size = 128 * KiB,
- .ways = 4,
- .line_size = 32,
- .tlb_entries = UNDEF,
- .partitioning = 0};
+ return MakeX86CacheLevelInfo(2, CPU_FEATURE_CACHE_DATA, 128 * KiB, 4, 32,
+ UNDEF, 0);
case 0x42:
- return (CacheLevelInfo){.level = 2,
- .cache_type = CPU_FEATURE_CACHE_DATA,
- .cache_size = 256 * KiB,
- .ways = 4,
- .line_size = 32,
- .tlb_entries = UNDEF,
- .partitioning = 0};
+ return MakeX86CacheLevelInfo(2, CPU_FEATURE_CACHE_DATA, 256 * KiB, 4, 32,
+ UNDEF, 0);
case 0x43:
- return (CacheLevelInfo){.level = 2,
- .cache_type = CPU_FEATURE_CACHE_DATA,
- .cache_size = 512 * KiB,
- .ways = 4,
- .line_size = 32,
- .tlb_entries = UNDEF,
- .partitioning = 0};
+ return MakeX86CacheLevelInfo(2, CPU_FEATURE_CACHE_DATA, 512 * KiB, 4, 32,
+ UNDEF, 0);
case 0x44:
- return (CacheLevelInfo){.level = 2,
- .cache_type = CPU_FEATURE_CACHE_DATA,
- .cache_size = 1 * MiB,
- .ways = 4,
- .line_size = 32,
- .tlb_entries = UNDEF,
- .partitioning = 0};
+ return MakeX86CacheLevelInfo(2, CPU_FEATURE_CACHE_DATA, 1 * MiB, 4, 32,
+ UNDEF, 0);
case 0x45:
- return (CacheLevelInfo){.level = 2,
- .cache_type = CPU_FEATURE_CACHE_DATA,
- .cache_size = 2 * MiB,
- .ways = 4,
- .line_size = 32,
- .tlb_entries = UNDEF,
- .partitioning = 0};
+ return MakeX86CacheLevelInfo(2, CPU_FEATURE_CACHE_DATA, 2 * MiB, 4, 32,
+ UNDEF, 0);
case 0x46:
- return (CacheLevelInfo){.level = 3,
- .cache_type = CPU_FEATURE_CACHE_DATA,
- .cache_size = 4 * MiB,
- .ways = 4,
- .line_size = 64,
- .tlb_entries = UNDEF,
- .partitioning = 0};
+ return MakeX86CacheLevelInfo(3, CPU_FEATURE_CACHE_DATA, 4 * MiB, 4, 64,
+ UNDEF, 0);
case 0x47:
- return (CacheLevelInfo){.level = 3,
- .cache_type = CPU_FEATURE_CACHE_DATA,
- .cache_size = 8 * MiB,
- .ways = 8,
- .line_size = 64,
- .tlb_entries = UNDEF,
- .partitioning = 0};
+ return MakeX86CacheLevelInfo(3, CPU_FEATURE_CACHE_DATA, 8 * MiB, 8, 64,
+ UNDEF, 0);
case 0x48:
- return (CacheLevelInfo){.level = 2,
- .cache_type = CPU_FEATURE_CACHE_DATA,
- .cache_size = 3 * MiB,
- .ways = 12,
- .line_size = 64,
- .tlb_entries = UNDEF,
- .partitioning = 0};
+ return MakeX86CacheLevelInfo(2, CPU_FEATURE_CACHE_DATA, 3 * MiB, 12, 64,
+ UNDEF, 0);
case 0x49:
- return (CacheLevelInfo){.level = 2,
- .cache_type = CPU_FEATURE_CACHE_DATA,
- .cache_size = 4 * MiB,
- .ways = 16,
- .line_size = 64,
- .tlb_entries = UNDEF,
- .partitioning = 0};
+ return MakeX86CacheLevelInfo(2, CPU_FEATURE_CACHE_DATA, 4 * MiB, 16, 64,
+ UNDEF, 0);
case (0x49 | (1 << 8)):
- return (CacheLevelInfo){.level = 3,
- .cache_type = CPU_FEATURE_CACHE_DATA,
- .cache_size = 4 * MiB,
- .ways = 16,
- .line_size = 64,
- .tlb_entries = UNDEF,
- .partitioning = 0};
+ return MakeX86CacheLevelInfo(3, CPU_FEATURE_CACHE_DATA, 4 * MiB, 16, 64,
+ UNDEF, 0);
case 0x4A:
- return (CacheLevelInfo){.level = 3,
- .cache_type = CPU_FEATURE_CACHE_DATA,
- .cache_size = 6 * MiB,
- .ways = 12,
- .line_size = 64,
- .tlb_entries = UNDEF,
- .partitioning = 0};
+ return MakeX86CacheLevelInfo(3, CPU_FEATURE_CACHE_DATA, 6 * MiB, 12, 64,
+ UNDEF, 0);
case 0x4B:
- return (CacheLevelInfo){.level = 3,
- .cache_type = CPU_FEATURE_CACHE_DATA,
- .cache_size = 8 * MiB,
- .ways = 16,
- .line_size = 64,
- .tlb_entries = UNDEF,
- .partitioning = 0};
+ return MakeX86CacheLevelInfo(3, CPU_FEATURE_CACHE_DATA, 8 * MiB, 16, 64,
+ UNDEF, 0);
case 0x4C:
- return (CacheLevelInfo){.level = 3,
- .cache_type = CPU_FEATURE_CACHE_DATA,
- .cache_size = 12 * MiB,
- .ways = 12,
- .line_size = 64,
- .tlb_entries = UNDEF,
- .partitioning = 0};
+ return MakeX86CacheLevelInfo(3, CPU_FEATURE_CACHE_DATA, 12 * MiB, 12, 64,
+ UNDEF, 0);
case 0x4D:
- return (CacheLevelInfo){.level = 3,
- .cache_type = CPU_FEATURE_CACHE_DATA,
- .cache_size = 16 * MiB,
- .ways = 16,
- .line_size = 64,
- .tlb_entries = UNDEF,
- .partitioning = 0};
+ return MakeX86CacheLevelInfo(3, CPU_FEATURE_CACHE_DATA, 16 * MiB, 16, 64,
+ UNDEF, 0);
case 0x4E:
- return (CacheLevelInfo){.level = 2,
- .cache_type = CPU_FEATURE_CACHE_DATA,
- .cache_size = 6 * MiB,
- .ways = 24,
- .line_size = 64,
- .tlb_entries = UNDEF,
- .partitioning = 0};
+ return MakeX86CacheLevelInfo(2, CPU_FEATURE_CACHE_DATA, 6 * MiB, 24, 64,
+ UNDEF, 0);
case 0x4F:
- return (CacheLevelInfo){.level = UNDEF,
- .cache_type = CPU_FEATURE_CACHE_TLB,
- .cache_size = 4 * KiB,
- .ways = UNDEF,
- .line_size = UNDEF,
- .tlb_entries = 32,
- .partitioning = 0};
+ return MakeX86CacheLevelInfo(UNDEF, CPU_FEATURE_CACHE_TLB, 4 * KiB, UNDEF,
+ UNDEF, 32, 0);
case 0x50:
- return (CacheLevelInfo){.level = UNDEF,
- .cache_type = CPU_FEATURE_CACHE_TLB,
- .cache_size = 4 * KiB,
- .ways = UNDEF,
- .line_size = UNDEF,
- .tlb_entries = 64,
- .partitioning = 0};
+ return MakeX86CacheLevelInfo(UNDEF, CPU_FEATURE_CACHE_TLB, 4 * KiB, UNDEF,
+ UNDEF, 64, 0);
case 0x51:
- return (CacheLevelInfo){.level = UNDEF,
- .cache_type = CPU_FEATURE_CACHE_TLB,
- .cache_size = 4 * KiB,
- .ways = UNDEF,
- .line_size = UNDEF,
- .tlb_entries = 128,
- .partitioning = 0};
+ return MakeX86CacheLevelInfo(UNDEF, CPU_FEATURE_CACHE_TLB, 4 * KiB, UNDEF,
+ UNDEF, 128, 0);
case 0x52:
- return (CacheLevelInfo){.level = UNDEF,
- .cache_type = CPU_FEATURE_CACHE_TLB,
- .cache_size = 4 * KiB,
- .ways = UNDEF,
- .line_size = UNDEF,
- .tlb_entries = 256,
- .partitioning = 0};
+ return MakeX86CacheLevelInfo(UNDEF, CPU_FEATURE_CACHE_TLB, 4 * KiB, UNDEF,
+ UNDEF, 256, 0);
case 0x55:
- return (CacheLevelInfo){.level = UNDEF,
- .cache_type = CPU_FEATURE_CACHE_TLB,
- .cache_size = 2 * MiB,
- .ways = 0xFF,
- .line_size = UNDEF,
- .tlb_entries = 7,
- .partitioning = 0};
+ return MakeX86CacheLevelInfo(UNDEF, CPU_FEATURE_CACHE_TLB, 2 * MiB, 0xFF,
+ UNDEF, 7, 0);
case 0x56:
- return (CacheLevelInfo){.level = UNDEF,
- .cache_type = CPU_FEATURE_CACHE_TLB,
- .cache_size = 4 * MiB,
- .ways = 4,
- .line_size = UNDEF,
- .tlb_entries = 16,
- .partitioning = 0};
+ return MakeX86CacheLevelInfo(UNDEF, CPU_FEATURE_CACHE_TLB, 4 * MiB, 4,
+ UNDEF, 16, 0);
case 0x57:
- return (CacheLevelInfo){.level = UNDEF,
- .cache_type = CPU_FEATURE_CACHE_TLB,
- .cache_size = 4 * KiB,
- .ways = 4,
- .line_size = UNDEF,
- .tlb_entries = 16,
- .partitioning = 0};
+ return MakeX86CacheLevelInfo(UNDEF, CPU_FEATURE_CACHE_TLB, 4 * KiB, 4,
+ UNDEF, 16, 0);
case 0x59:
- return (CacheLevelInfo){.level = UNDEF,
- .cache_type = CPU_FEATURE_CACHE_TLB,
- .cache_size = 4 * KiB,
- .ways = 0xFF,
- .line_size = UNDEF,
- .tlb_entries = 16,
- .partitioning = 0};
+ return MakeX86CacheLevelInfo(UNDEF, CPU_FEATURE_CACHE_TLB, 4 * KiB, 0xFF,
+ UNDEF, 16, 0);
case 0x5A:
- return (CacheLevelInfo){.level = UNDEF,
- .cache_type = CPU_FEATURE_CACHE_TLB,
- .cache_size = 2 * MiB,
- .ways = 4,
- .line_size = UNDEF,
- .tlb_entries = 32,
- .partitioning = 0};
+ return MakeX86CacheLevelInfo(UNDEF, CPU_FEATURE_CACHE_TLB, 2 * MiB, 4,
+ UNDEF, 32, 0);
case 0x5B:
- return (CacheLevelInfo){.level = UNDEF,
- .cache_type = CPU_FEATURE_CACHE_TLB,
- .cache_size = 4 * KiB,
- .ways = UNDEF,
- .line_size = UNDEF,
- .tlb_entries = 64,
- .partitioning = 0};
+ return MakeX86CacheLevelInfo(UNDEF, CPU_FEATURE_CACHE_TLB, 4 * KiB, UNDEF,
+ UNDEF, 64, 0);
case 0x5C:
- return (CacheLevelInfo){.level = UNDEF,
- .cache_type = CPU_FEATURE_CACHE_TLB,
- .cache_size = 4 * KiB,
- .ways = UNDEF,
- .line_size = UNDEF,
- .tlb_entries = 128,
- .partitioning = 0};
+ return MakeX86CacheLevelInfo(UNDEF, CPU_FEATURE_CACHE_TLB, 4 * KiB, UNDEF,
+ UNDEF, 128, 0);
case 0x5D:
- return (CacheLevelInfo){.level = UNDEF,
- .cache_type = CPU_FEATURE_CACHE_TLB,
- .cache_size = 4,
- .ways = UNDEF,
- .line_size = UNDEF,
- .tlb_entries = 256,
- .partitioning = 0};
+ return MakeX86CacheLevelInfo(UNDEF, CPU_FEATURE_CACHE_TLB, 4, UNDEF,
+ UNDEF, 256, 0);
case 0x60:
- return (CacheLevelInfo){.level = 1,
- .cache_type = CPU_FEATURE_CACHE_DATA,
- .cache_size = 16 * KiB,
- .ways = 8,
- .line_size = 64,
- .tlb_entries = UNDEF,
- .partitioning = 0};
+ return MakeX86CacheLevelInfo(1, CPU_FEATURE_CACHE_DATA, 16 * KiB, 8, 64,
+ UNDEF, 0);
case 0x61:
- return (CacheLevelInfo){.level = UNDEF,
- .cache_type = CPU_FEATURE_CACHE_TLB,
- .cache_size = 4 * KiB,
- .ways = 0xFF,
- .line_size = UNDEF,
- .tlb_entries = 48,
- .partitioning = 0};
+ return MakeX86CacheLevelInfo(UNDEF, CPU_FEATURE_CACHE_TLB, 4 * KiB, 0xFF,
+ UNDEF, 48, 0);
case 0x63:
- return (CacheLevelInfo){.level = UNDEF,
- .cache_type = CPU_FEATURE_CACHE_TLB,
- .cache_size = 2 * MiB,
- .ways = 4,
- .line_size = UNDEF,
- .tlb_entries = 4,
- .partitioning = 0};
+ return MakeX86CacheLevelInfo(UNDEF, CPU_FEATURE_CACHE_TLB, 2 * MiB, 4,
+ UNDEF, 4, 0);
case 0x66:
- return (CacheLevelInfo){.level = 1,
- .cache_type = CPU_FEATURE_CACHE_DATA,
- .cache_size = 8 * KiB,
- .ways = 4,
- .line_size = 64,
- .tlb_entries = UNDEF,
- .partitioning = 0};
+ return MakeX86CacheLevelInfo(1, CPU_FEATURE_CACHE_DATA, 8 * KiB, 4, 64,
+ UNDEF, 0);
case 0x67:
- return (CacheLevelInfo){.level = 1,
- .cache_type = CPU_FEATURE_CACHE_DATA,
- .cache_size = 16 * KiB,
- .ways = 4,
- .line_size = 64,
- .tlb_entries = UNDEF,
- .partitioning = 0};
+ return MakeX86CacheLevelInfo(1, CPU_FEATURE_CACHE_DATA, 16 * KiB, 4, 64,
+ UNDEF, 0);
case 0x68:
- return (CacheLevelInfo){.level = 1,
- .cache_type = CPU_FEATURE_CACHE_DATA,
- .cache_size = 32 * KiB,
- .ways = 4,
- .line_size = 64,
- .tlb_entries = UNDEF,
- .partitioning = 0};
+ return MakeX86CacheLevelInfo(1, CPU_FEATURE_CACHE_DATA, 32 * KiB, 4, 64,
+ UNDEF, 0);
case 0x70:
- return (CacheLevelInfo){.level = 1,
- .cache_type = CPU_FEATURE_CACHE_INSTRUCTION,
- .cache_size = 12 * KiB,
- .ways = 8,
- .line_size = UNDEF,
- .tlb_entries = UNDEF,
- .partitioning = 0};
+ return MakeX86CacheLevelInfo(1, CPU_FEATURE_CACHE_INSTRUCTION, 12 * KiB,
+ 8, UNDEF, UNDEF, 0);
case 0x71:
- return (CacheLevelInfo){.level = 1,
- .cache_type = CPU_FEATURE_CACHE_INSTRUCTION,
- .cache_size = 16 * KiB,
- .ways = 8,
- .line_size = UNDEF,
- .tlb_entries = UNDEF,
- .partitioning = 0};
+ return MakeX86CacheLevelInfo(1, CPU_FEATURE_CACHE_INSTRUCTION, 16 * KiB,
+ 8, UNDEF, UNDEF, 0);
case 0x72:
- return (CacheLevelInfo){.level = 1,
- .cache_type = CPU_FEATURE_CACHE_INSTRUCTION,
- .cache_size = 32 * KiB,
- .ways = 8,
- .line_size = UNDEF,
- .tlb_entries = UNDEF,
- .partitioning = 0};
+ return MakeX86CacheLevelInfo(1, CPU_FEATURE_CACHE_INSTRUCTION, 32 * KiB,
+ 8, UNDEF, UNDEF, 0);
case 0x76:
- return (CacheLevelInfo){.level = UNDEF,
- .cache_type = CPU_FEATURE_CACHE_TLB,
- .cache_size = 2 * MiB,
- .ways = 0xFF,
- .line_size = UNDEF,
- .tlb_entries = 8,
- .partitioning = 0};
+ return MakeX86CacheLevelInfo(UNDEF, CPU_FEATURE_CACHE_TLB, 2 * MiB, 0xFF,
+ UNDEF, 8, 0);
case 0x78:
- return (CacheLevelInfo){.level = 2,
- .cache_type = CPU_FEATURE_CACHE_DATA,
- .cache_size = 1 * MiB,
- .ways = 4,
- .line_size = 64,
- .tlb_entries = UNDEF,
- .partitioning = 0};
+ return MakeX86CacheLevelInfo(2, CPU_FEATURE_CACHE_DATA, 1 * MiB, 4, 64,
+ UNDEF, 0);
case 0x79:
- return (CacheLevelInfo){.level = 2,
- .cache_type = CPU_FEATURE_CACHE_DATA,
- .cache_size = 128 * KiB,
- .ways = 8,
- .line_size = 64,
- .tlb_entries = UNDEF,
- .partitioning = 2};
+ return MakeX86CacheLevelInfo(2, CPU_FEATURE_CACHE_DATA, 128 * KiB, 8, 64,
+ UNDEF, 2);
case 0x7A:
- return (CacheLevelInfo){.level = 2,
- .cache_type = CPU_FEATURE_CACHE_DATA,
- .cache_size = 256 * KiB,
- .ways = 8,
- .line_size = 64,
- .tlb_entries = UNDEF,
- .partitioning = 2};
+ return MakeX86CacheLevelInfo(2, CPU_FEATURE_CACHE_DATA, 256 * KiB, 8, 64,
+ UNDEF, 2);
case 0x7B:
- return (CacheLevelInfo){.level = 2,
- .cache_type = CPU_FEATURE_CACHE_DATA,
- .cache_size = 512 * KiB,
- .ways = 8,
- .line_size = 64,
- .tlb_entries = UNDEF,
- .partitioning = 2};
+ return MakeX86CacheLevelInfo(2, CPU_FEATURE_CACHE_DATA, 512 * KiB, 8, 64,
+ UNDEF, 2);
case 0x7C:
- return (CacheLevelInfo){.level = 2,
- .cache_type = CPU_FEATURE_CACHE_DATA,
- .cache_size = 1 * MiB,
- .ways = 8,
- .line_size = 64,
- .tlb_entries = UNDEF,
- .partitioning = 2};
+ return MakeX86CacheLevelInfo(2, CPU_FEATURE_CACHE_DATA, 1 * MiB, 8, 64,
+ UNDEF, 2);
case 0x7D:
- return (CacheLevelInfo){.level = 2,
- .cache_type = CPU_FEATURE_CACHE_DATA,
- .cache_size = 2 * MiB,
- .ways = 8,
- .line_size = 64,
- .tlb_entries = UNDEF,
- .partitioning = 0};
+ return MakeX86CacheLevelInfo(2, CPU_FEATURE_CACHE_DATA, 2 * MiB, 8, 64,
+ UNDEF, 0);
case 0x7F:
- return (CacheLevelInfo){.level = 2,
- .cache_type = CPU_FEATURE_CACHE_DATA,
- .cache_size = 512 * KiB,
- .ways = 2,
- .line_size = 64,
- .tlb_entries = UNDEF,
- .partitioning = 0};
+ return MakeX86CacheLevelInfo(2, CPU_FEATURE_CACHE_DATA, 512 * KiB, 2, 64,
+ UNDEF, 0);
case 0x80:
- return (CacheLevelInfo){.level = 2,
- .cache_type = CPU_FEATURE_CACHE_DATA,
- .cache_size = 512 * KiB,
- .ways = 8,
- .line_size = 64,
- .tlb_entries = UNDEF,
- .partitioning = 0};
+ return MakeX86CacheLevelInfo(2, CPU_FEATURE_CACHE_DATA, 512 * KiB, 8, 64,
+ UNDEF, 0);
case 0x82:
- return (CacheLevelInfo){.level = 2,
- .cache_type = CPU_FEATURE_CACHE_DATA,
- .cache_size = 256 * KiB,
- .ways = 8,
- .line_size = 32,
- .tlb_entries = UNDEF,
- .partitioning = 0};
+ return MakeX86CacheLevelInfo(2, CPU_FEATURE_CACHE_DATA, 256 * KiB, 8, 32,
+ UNDEF, 0);
case 0x83:
- return (CacheLevelInfo){.level = 2,
- .cache_type = CPU_FEATURE_CACHE_DATA,
- .cache_size = 512 * KiB,
- .ways = 8,
- .line_size = 32,
- .tlb_entries = UNDEF,
- .partitioning = 0};
+ return MakeX86CacheLevelInfo(2, CPU_FEATURE_CACHE_DATA, 512 * KiB, 8, 32,
+ UNDEF, 0);
case 0x84:
- return (CacheLevelInfo){.level = 2,
- .cache_type = CPU_FEATURE_CACHE_DATA,
- .cache_size = 1 * MiB,
- .ways = 8,
- .line_size = 32,
- .tlb_entries = UNDEF,
- .partitioning = 0};
+ return MakeX86CacheLevelInfo(2, CPU_FEATURE_CACHE_DATA, 1 * MiB, 8, 32,
+ UNDEF, 0);
case 0x85:
- return (CacheLevelInfo){.level = 2,
- .cache_type = CPU_FEATURE_CACHE_DATA,
- .cache_size = 2 * MiB,
- .ways = 8,
- .line_size = 32,
- .tlb_entries = UNDEF,
- .partitioning = 0};
+ return MakeX86CacheLevelInfo(2, CPU_FEATURE_CACHE_DATA, 2 * MiB, 8, 32,
+ UNDEF, 0);
case 0x86:
- return (CacheLevelInfo){.level = 2,
- .cache_type = CPU_FEATURE_CACHE_DATA,
- .cache_size = 512 * KiB,
- .ways = 4,
- .line_size = 32,
- .tlb_entries = UNDEF,
- .partitioning = 0};
+ return MakeX86CacheLevelInfo(2, CPU_FEATURE_CACHE_DATA, 512 * KiB, 4, 32,
+ UNDEF, 0);
case 0x87:
- return (CacheLevelInfo){.level = 2,
- .cache_type = CPU_FEATURE_CACHE_DATA,
- .cache_size = 1 * MiB,
- .ways = 8,
- .line_size = 64,
- .tlb_entries = UNDEF,
- .partitioning = 0};
+ return MakeX86CacheLevelInfo(2, CPU_FEATURE_CACHE_DATA, 1 * MiB, 8, 64,
+ UNDEF, 0);
case 0xA0:
- return (CacheLevelInfo){.level = UNDEF,
- .cache_type = CPU_FEATURE_CACHE_DTLB,
- .cache_size = 4 * KiB,
- .ways = 0xFF,
- .line_size = UNDEF,
- .tlb_entries = 32,
- .partitioning = 0};
+ return MakeX86CacheLevelInfo(UNDEF, CPU_FEATURE_CACHE_DTLB, 4 * KiB, 0xFF,
+ UNDEF, 32, 0);
case 0xB0:
- return (CacheLevelInfo){.level = UNDEF,
- .cache_type = CPU_FEATURE_CACHE_TLB,
- .cache_size = 4 * KiB,
- .ways = 4,
- .line_size = UNDEF,
- .tlb_entries = 128,
- .partitioning = 0};
+ return MakeX86CacheLevelInfo(UNDEF, CPU_FEATURE_CACHE_TLB, 4 * KiB, 4,
+ UNDEF, 128, 0);
case 0xB1:
- return (CacheLevelInfo){.level = UNDEF,
- .cache_type = CPU_FEATURE_CACHE_TLB,
- .cache_size = 2 * MiB,
- .ways = 4,
- .line_size = UNDEF,
- .tlb_entries = 8,
- .partitioning = 0};
+ return MakeX86CacheLevelInfo(UNDEF, CPU_FEATURE_CACHE_TLB, 2 * MiB, 4,
+ UNDEF, 8, 0);
case 0xB2:
- return (CacheLevelInfo){.level = UNDEF,
- .cache_type = CPU_FEATURE_CACHE_TLB,
- .cache_size = 4 * KiB,
- .ways = 4,
- .line_size = UNDEF,
- .tlb_entries = 64,
- .partitioning = 0};
+ return MakeX86CacheLevelInfo(UNDEF, CPU_FEATURE_CACHE_TLB, 4 * KiB, 4,
+ UNDEF, 64, 0);
case 0xB3:
- return (CacheLevelInfo){.level = UNDEF,
- .cache_type = CPU_FEATURE_CACHE_TLB,
- .cache_size = 4 * KiB,
- .ways = 4,
- .line_size = UNDEF,
- .tlb_entries = 128,
- .partitioning = 0};
+ return MakeX86CacheLevelInfo(UNDEF, CPU_FEATURE_CACHE_TLB, 4 * KiB, 4,
+ UNDEF, 128, 0);
case 0xB4:
- return (CacheLevelInfo){.level = UNDEF,
- .cache_type = CPU_FEATURE_CACHE_TLB,
- .cache_size = 4 * KiB,
- .ways = 4,
- .line_size = UNDEF,
- .tlb_entries = 256,
- .partitioning = 0};
+ return MakeX86CacheLevelInfo(UNDEF, CPU_FEATURE_CACHE_TLB, 4 * KiB, 4,
+ UNDEF, 256, 0);
case 0xB5:
- return (CacheLevelInfo){.level = UNDEF,
- .cache_type = CPU_FEATURE_CACHE_TLB,
- .cache_size = 4 * KiB,
- .ways = 8,
- .line_size = UNDEF,
- .tlb_entries = 64,
- .partitioning = 0};
+ return MakeX86CacheLevelInfo(UNDEF, CPU_FEATURE_CACHE_TLB, 4 * KiB, 8,
+ UNDEF, 64, 0);
case 0xB6:
- return (CacheLevelInfo){.level = UNDEF,
- .cache_type = CPU_FEATURE_CACHE_TLB,
- .cache_size = 4 * KiB,
- .ways = 8,
- .line_size = UNDEF,
- .tlb_entries = 128,
- .partitioning = 0};
+ return MakeX86CacheLevelInfo(UNDEF, CPU_FEATURE_CACHE_TLB, 4 * KiB, 8,
+ UNDEF, 128, 0);
case 0xBA:
- return (CacheLevelInfo){.level = UNDEF,
- .cache_type = CPU_FEATURE_CACHE_TLB,
- .cache_size = 4 * KiB,
- .ways = 4,
- .line_size = UNDEF,
- .tlb_entries = 64,
- .partitioning = 0};
+ return MakeX86CacheLevelInfo(UNDEF, CPU_FEATURE_CACHE_TLB, 4 * KiB, 4,
+ UNDEF, 64, 0);
case 0xC0:
- return (CacheLevelInfo){.level = UNDEF,
- .cache_type = CPU_FEATURE_CACHE_TLB,
- .cache_size = 4 * KiB,
- .ways = 4,
- .line_size = UNDEF,
- .tlb_entries = 8,
- .partitioning = 0};
+ return MakeX86CacheLevelInfo(UNDEF, CPU_FEATURE_CACHE_TLB, 4 * KiB, 4,
+ UNDEF, 8, 0);
case 0xC1:
- return (CacheLevelInfo){.level = UNDEF,
- .cache_type = CPU_FEATURE_CACHE_STLB,
- .cache_size = 4 * KiB,
- .ways = 8,
- .line_size = UNDEF,
- .tlb_entries = 1024,
- .partitioning = 0};
+ return MakeX86CacheLevelInfo(UNDEF, CPU_FEATURE_CACHE_STLB, 4 * KiB, 8,
+ UNDEF, 1024, 0);
case 0xC2:
- return (CacheLevelInfo){.level = UNDEF,
- .cache_type = CPU_FEATURE_CACHE_DTLB,
- .cache_size = 4 * KiB,
- .ways = 4,
- .line_size = UNDEF,
- .tlb_entries = 16,
- .partitioning = 0};
+ return MakeX86CacheLevelInfo(UNDEF, CPU_FEATURE_CACHE_DTLB, 4 * KiB, 4,
+ UNDEF, 16, 0);
case 0xC3:
- return (CacheLevelInfo){.level = UNDEF,
- .cache_type = CPU_FEATURE_CACHE_STLB,
- .cache_size = 4 * KiB,
- .ways = 6,
- .line_size = UNDEF,
- .tlb_entries = 1536,
- .partitioning = 0};
+ return MakeX86CacheLevelInfo(UNDEF, CPU_FEATURE_CACHE_STLB, 4 * KiB, 6,
+ UNDEF, 1536, 0);
case 0xCA:
- return (CacheLevelInfo){.level = UNDEF,
- .cache_type = CPU_FEATURE_CACHE_STLB,
- .cache_size = 4 * KiB,
- .ways = 4,
- .line_size = UNDEF,
- .tlb_entries = 512,
- .partitioning = 0};
+ return MakeX86CacheLevelInfo(UNDEF, CPU_FEATURE_CACHE_STLB, 4 * KiB, 4,
+ UNDEF, 512, 0);
case 0xD0:
- return (CacheLevelInfo){.level = 3,
- .cache_type = CPU_FEATURE_CACHE_DATA,
- .cache_size = 512 * KiB,
- .ways = 4,
- .line_size = 64,
- .tlb_entries = UNDEF,
- .partitioning = 0};
+ return MakeX86CacheLevelInfo(3, CPU_FEATURE_CACHE_DATA, 512 * KiB, 4, 64,
+ UNDEF, 0);
case 0xD1:
- return (CacheLevelInfo){.level = 3,
- .cache_type = CPU_FEATURE_CACHE_DATA,
- .cache_size = 1 * MiB,
- .ways = 4,
- .line_size = 64,
- .tlb_entries = UNDEF,
- .partitioning = 0};
+ return MakeX86CacheLevelInfo(3, CPU_FEATURE_CACHE_DATA, 1 * MiB, 4, 64,
+ UNDEF, 0);
case 0xD2:
- return (CacheLevelInfo){.level = 3,
- .cache_type = CPU_FEATURE_CACHE_DATA,
- .cache_size = 2 * MiB,
- .ways = 4,
- .line_size = 64,
- .tlb_entries = UNDEF,
- .partitioning = 0};
+ return MakeX86CacheLevelInfo(3, CPU_FEATURE_CACHE_DATA, 2 * MiB, 4, 64,
+ UNDEF, 0);
case 0xD6:
- return (CacheLevelInfo){.level = 3,
- .cache_type = CPU_FEATURE_CACHE_DATA,
- .cache_size = 1 * MiB,
- .ways = 8,
- .line_size = 64,
- .tlb_entries = UNDEF,
- .partitioning = 0};
+ return MakeX86CacheLevelInfo(3, CPU_FEATURE_CACHE_DATA, 1 * MiB, 8, 64,
+ UNDEF, 0);
case 0xD7:
- return (CacheLevelInfo){.level = 3,
- .cache_type = CPU_FEATURE_CACHE_DATA,
- .cache_size = 2 * MiB,
- .ways = 8,
- .line_size = 64,
- .tlb_entries = UNDEF,
- .partitioning = 0};
+ return MakeX86CacheLevelInfo(3, CPU_FEATURE_CACHE_DATA, 2 * MiB, 8, 64,
+ UNDEF, 0);
case 0xD8:
- return (CacheLevelInfo){.level = 3,
- .cache_type = CPU_FEATURE_CACHE_DATA,
- .cache_size = 4 * MiB,
- .ways = 8,
- .line_size = 64,
- .tlb_entries = UNDEF,
- .partitioning = 0};
+ return MakeX86CacheLevelInfo(3, CPU_FEATURE_CACHE_DATA, 4 * MiB, 8, 64,
+ UNDEF, 0);
case 0xDC:
- return (CacheLevelInfo){.level = 3,
- .cache_type = CPU_FEATURE_CACHE_DATA,
- .cache_size = 1 * 1536 * KiB,
- .ways = 12,
- .line_size = 64,
- .tlb_entries = UNDEF,
- .partitioning = 0};
+ return MakeX86CacheLevelInfo(3, CPU_FEATURE_CACHE_DATA, 1 * 1536 * KiB,
+ 12, 64, UNDEF, 0);
case 0xDD:
- return (CacheLevelInfo){.level = 3,
- .cache_type = CPU_FEATURE_CACHE_DATA,
- .cache_size = 3 * MiB,
- .ways = 12,
- .line_size = 64,
- .tlb_entries = UNDEF,
- .partitioning = 0};
+ return MakeX86CacheLevelInfo(3, CPU_FEATURE_CACHE_DATA, 3 * MiB, 12, 64,
+ UNDEF, 0);
case 0xDE:
- return (CacheLevelInfo){.level = 3,
- .cache_type = CPU_FEATURE_CACHE_DATA,
- .cache_size = 6 * MiB,
- .ways = 12,
- .line_size = 64,
- .tlb_entries = UNDEF,
- .partitioning = 0};
+ return MakeX86CacheLevelInfo(3, CPU_FEATURE_CACHE_DATA, 6 * MiB, 12, 64,
+ UNDEF, 0);
case 0xE2:
- return (CacheLevelInfo){.level = 3,
- .cache_type = CPU_FEATURE_CACHE_DATA,
- .cache_size = 2 * MiB,
- .ways = 16,
- .line_size = 64,
- .tlb_entries = UNDEF,
- .partitioning = 0};
+ return MakeX86CacheLevelInfo(3, CPU_FEATURE_CACHE_DATA, 2 * MiB, 16, 64,
+ UNDEF, 0);
case 0xE3:
- return (CacheLevelInfo){.level = 3,
- .cache_type = CPU_FEATURE_CACHE_DATA,
- .cache_size = 4 * MiB,
- .ways = 16,
- .line_size = 64,
- .tlb_entries = UNDEF,
- .partitioning = 0};
+ return MakeX86CacheLevelInfo(3, CPU_FEATURE_CACHE_DATA, 4 * MiB, 16, 64,
+ UNDEF, 0);
case 0xE4:
- return (CacheLevelInfo){.level = 3,
- .cache_type = CPU_FEATURE_CACHE_DATA,
- .cache_size = 8 * MiB,
- .ways = 16,
- .line_size = 64,
- .tlb_entries = UNDEF,
- .partitioning = 0};
+ return MakeX86CacheLevelInfo(3, CPU_FEATURE_CACHE_DATA, 8 * MiB, 16, 64,
+ UNDEF, 0);
case 0xEA:
- return (CacheLevelInfo){.level = 3,
- .cache_type = CPU_FEATURE_CACHE_DATA,
- .cache_size = 12 * MiB,
- .ways = 24,
- .line_size = 64,
- .tlb_entries = UNDEF,
- .partitioning = 0};
+ return MakeX86CacheLevelInfo(3, CPU_FEATURE_CACHE_DATA, 12 * MiB, 24, 64,
+ UNDEF, 0);
case 0xEB:
- return (CacheLevelInfo){.level = 3,
- .cache_type = CPU_FEATURE_CACHE_DATA,
- .cache_size = 18 * MiB,
- .ways = 24,
- .line_size = 64,
- .tlb_entries = UNDEF,
- .partitioning = 0};
+ return MakeX86CacheLevelInfo(3, CPU_FEATURE_CACHE_DATA, 18 * MiB, 24, 64,
+ UNDEF, 0);
case 0xEC:
- return (CacheLevelInfo){.level = 3,
- .cache_type = CPU_FEATURE_CACHE_DATA,
- .cache_size = 24 * MiB,
- .ways = 24,
- .line_size = 64,
- .tlb_entries = UNDEF,
- .partitioning = 0};
+ return MakeX86CacheLevelInfo(3, CPU_FEATURE_CACHE_DATA, 24 * MiB, 24, 64,
+ UNDEF, 0);
case 0xF0:
- return (CacheLevelInfo){.level = UNDEF,
- .cache_type = CPU_FEATURE_CACHE_PREFETCH,
- .cache_size = 64 * KiB,
- .ways = UNDEF,
- .line_size = UNDEF,
- .tlb_entries = UNDEF,
- .partitioning = 0};
+ return MakeX86CacheLevelInfo(UNDEF, CPU_FEATURE_CACHE_PREFETCH, 64 * KiB,
+ UNDEF, UNDEF, UNDEF, 0);
case 0xF1:
- return (CacheLevelInfo){.level = UNDEF,
- .cache_type = CPU_FEATURE_CACHE_PREFETCH,
- .cache_size = 128 * KiB,
- .ways = UNDEF,
- .line_size = UNDEF,
- .tlb_entries = UNDEF,
- .partitioning = 0};
+ return MakeX86CacheLevelInfo(UNDEF, CPU_FEATURE_CACHE_PREFETCH, 128 * KiB,
+ UNDEF, UNDEF, UNDEF, 0);
case 0xFF:
- return (CacheLevelInfo){.level = UNDEF,
- .cache_type = CPU_FEATURE_CACHE_NULL,
- .cache_size = UNDEF,
- .ways = UNDEF,
- .line_size = UNDEF,
- .tlb_entries = UNDEF,
- .partitioning = 0};
+ return MakeX86CacheLevelInfo(UNDEF, CPU_FEATURE_CACHE_NULL, UNDEF, UNDEF,
+ UNDEF, UNDEF, 0);
default:
return kEmptyCacheLevelInfo;
}
@@ -1124,15 +485,15 @@ static void ParseLeaf2(const int max_cpuid_leaf, CacheInfo* info) {
Leaf leaf = SafeCpuId(max_cpuid_leaf, 2);
uint32_t registers[] = {leaf.eax, leaf.ebx, leaf.ecx, leaf.edx};
for (int i = 0; i < 4; ++i) {
- if (registers[i] & (1U << 31)) {
+ if (registers[i] & (1 << 31)) {
continue; // register does not contains valid information
}
uint32_t bytes[4];
GetByteArrayFromRegister(bytes, registers[i]);
- for (int j = 0; j < 4; ++j) {
- if (bytes[j] == 0xFF)
+ for (int i = 0; i < 4; ++i) {
+ if (bytes[i] == 0xFF)
break; // leaf 4 should be used to fetch cache information
- info->levels[info->size] = GetCacheLevelInfo(bytes[j]);
+ info->levels[info->size] = GetCacheLevelInfo(bytes[i]);
}
info->size++;
}
@@ -1151,130 +512,25 @@ static void ParseLeaf4(const int max_cpuid_leaf, CacheInfo* info) {
int line_size = ExtractBitRange(leaf.ebx, 11, 0) + 1;
int partitioning = ExtractBitRange(leaf.ebx, 21, 12) + 1;
int ways = ExtractBitRange(leaf.ebx, 31, 22) + 1;
- int tlb_entries = leaf.ecx + 1;
- int cache_size = (ways * partitioning * line_size * (tlb_entries));
- info->levels[cache_id] = (CacheLevelInfo){.level = level,
- .cache_type = cache_type,
- .cache_size = cache_size,
- .ways = ways,
- .line_size = line_size,
- .tlb_entries = tlb_entries,
- .partitioning = partitioning};
+ int entries = leaf.ecx + 1;
+ int cache_size = (ways * partitioning * line_size * (entries));
+ info->levels[cache_id] = MakeX86CacheLevelInfo(
+ level, cache_type, cache_size, ways, line_size, entries, partitioning);
info->size++;
}
}
-// Internal structure to hold the OS support for vector operations.
-// Avoid to recompute them since each call to cpuid is ~100 cycles.
-typedef struct {
- bool have_sse_via_os;
- bool have_sse_via_cpuid;
- bool have_avx;
- bool have_avx512;
- bool have_amx;
-} OsSupport;
-
-static const OsSupport kEmptyOsSupport;
-
-static OsSupport CheckOsSupport(const uint32_t max_cpuid_leaf) {
- const Leaf leaf_1 = SafeCpuId(max_cpuid_leaf, 1);
- const bool have_xsave = IsBitSet(leaf_1.ecx, 26);
- const bool have_osxsave = IsBitSet(leaf_1.ecx, 27);
- const bool have_xcr0 = have_xsave && have_osxsave;
-
- OsSupport os_support = kEmptyOsSupport;
-
- if (have_xcr0) {
- // AVX capable cpu will expose XCR0.
- const uint32_t xcr0_eax = GetXCR0Eax();
- os_support.have_sse_via_cpuid = HasXmmOsXSave(xcr0_eax);
- os_support.have_avx = HasYmmOsXSave(xcr0_eax);
- 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.
-static void ParseCpuId(const uint32_t max_cpuid_leaf,
- const OsSupport os_support, X86Info* info) {
+static void ParseCpuId(const uint32_t max_cpuid_leaf, X86Info* info) {
const Leaf leaf_1 = SafeCpuId(max_cpuid_leaf, 1);
const Leaf leaf_7 = SafeCpuId(max_cpuid_leaf, 7);
- const Leaf leaf_7_1 = SafeCpuIdEx(max_cpuid_leaf, 7, 1);
+
+ const bool have_xsave = IsBitSet(leaf_1.ecx, 26);
+ const bool have_osxsave = IsBitSet(leaf_1.ecx, 27);
+ const uint32_t xcr0_eax = (have_xsave && have_osxsave) ? GetXCR0Eax() : 0;
+ const bool have_sse_os_support = HasXmmOsXSave(xcr0_eax);
+ const bool have_avx_os_support = HasYmmOsXSave(xcr0_eax);
+ const bool have_avx512_os_support = HasZmmOsXSave(xcr0_eax);
const uint32_t family = ExtractBitRange(leaf_1.eax, 11, 8);
const uint32_t extended_family = ExtractBitRange(leaf_1.eax, 27, 20);
@@ -1315,9 +571,7 @@ static void ParseCpuId(const uint32_t max_cpuid_leaf,
features->vaes = IsBitSet(leaf_7.ecx, 9);
features->vpclmulqdq = IsBitSet(leaf_7.ecx, 10);
- if (os_support.have_sse_via_os) {
- DetectSseViaOs(features);
- } else if (os_support.have_sse_via_cpuid) {
+ if (have_sse_os_support) {
features->sse = IsBitSet(leaf_1.edx, 25);
features->sse2 = IsBitSet(leaf_1.edx, 26);
features->sse3 = IsBitSet(leaf_1.ecx, 0);
@@ -1326,13 +580,13 @@ static void ParseCpuId(const uint32_t max_cpuid_leaf,
features->sse4_2 = IsBitSet(leaf_1.ecx, 20);
}
- if (os_support.have_avx) {
+ if (have_avx_os_support) {
features->fma3 = IsBitSet(leaf_1.ecx, 12);
features->avx = IsBitSet(leaf_1.ecx, 28);
features->avx2 = IsBitSet(leaf_7.ebx, 5);
}
- if (os_support.have_avx512) {
+ if (have_avx512_os_support) {
features->avx512f = IsBitSet(leaf_7.ebx, 16);
features->avx512cd = IsBitSet(leaf_7.ebx, 28);
features->avx512er = IsBitSet(leaf_7.ebx, 27);
@@ -1348,34 +602,6 @@ static void ParseCpuId(const uint32_t max_cpuid_leaf,
features->avx512vpopcntdq = IsBitSet(leaf_7.ecx, 14);
features->avx512_4vnniw = IsBitSet(leaf_7.edx, 2);
features->avx512_4vbmi2 = IsBitSet(leaf_7.edx, 3);
- features->avx512_second_fma = HasSecondFMA(info->model);
- features->avx512_4fmaps = IsBitSet(leaf_7.edx, 3);
- features->avx512_bf16 = IsBitSet(leaf_7_1.eax, 5);
- features->avx512_vp2intersect = IsBitSet(leaf_7.edx, 8);
- }
-
- if (os_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.
-static void ParseExtraAMDCpuId(X86Info* info, OsSupport os_support) {
- const Leaf leaf_80000000 = CpuId(0x80000000);
- const uint32_t max_extended_cpuid_leaf = leaf_80000000.eax;
- const Leaf leaf_80000001 = SafeCpuId(max_extended_cpuid_leaf, 0x80000001);
-
- X86Features* const features = &info->features;
-
- if (os_support.have_sse_via_cpuid) {
- features->sse4a = IsBitSet(leaf_80000001.ecx, 6);
- }
-
- if (os_support.have_avx) {
- features->fma4 = IsBitSet(leaf_80000001.ecx, 16);
}
}
@@ -1385,16 +611,10 @@ static const CacheInfo kEmptyCacheInfo;
X86Info GetX86Info(void) {
X86Info info = kEmptyX86Info;
const Leaf leaf_0 = CpuId(0);
- const bool is_intel = IsVendor(leaf_0, "GenuineIntel");
- const bool is_amd = IsVendor(leaf_0, "AuthenticAMD");
+ const uint32_t max_cpuid_leaf = leaf_0.eax;
SetVendor(leaf_0, info.vendor);
- if (is_intel || is_amd) {
- 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, "GenuineIntel") || IsVendor(leaf_0, "AuthenticAMD")) {
+ ParseCpuId(max_cpuid_leaf, &info);
}
return info;
}
@@ -1470,42 +690,10 @@ X86Microarchitecture GetX86Microarchitecture(const X86Info* info) {
case CPUID(0x06, 0x5E):
// https://en.wikipedia.org/wiki/Skylake_(microarchitecture)
return INTEL_SKL;
- case CPUID(0x06, 0x66):
- // https://en.wikipedia.org/wiki/Cannon_Lake_(microarchitecture)
- return INTEL_CNL;
- 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)
- 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):
- switch (info->stepping) {
- case 9:
- return INTEL_KBL; // https://en.wikipedia.org/wiki/Kaby_Lake
- case 10:
- return INTEL_CFL; // https://en.wikipedia.org/wiki/Coffee_Lake
- case 11:
- return INTEL_WHL; // https://en.wikipedia.org/wiki/Whiskey_Lake_(microarchitecture)
- default:
- return X86_UNKNOWN;
- }
case CPUID(0x06, 0x9E):
- if (info->stepping > 9) {
- // https://en.wikipedia.org/wiki/Coffee_Lake
- return INTEL_CFL;
- } else {
- // https://en.wikipedia.org/wiki/Kaby_Lake
- return INTEL_KBL;
- }
+ // https://en.wikipedia.org/wiki/Kaby_Lake
+ return INTEL_KBL;
default:
return X86_UNKNOWN;
}
@@ -1554,13 +742,223 @@ void FillX86BrandString(char brand_string[49]) {
int GetX86FeaturesEnumValue(const X86Features* features,
X86FeaturesEnum value) {
- if (value >= X86_LAST_) return false;
- return kGetters[value](features);
+ switch (value) {
+ 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_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_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) {
- if (value >= X86_LAST_) return "unknown_feature";
- return kCpuInfoFlags[value];
+ switch (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_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_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) {
@@ -1595,16 +993,8 @@ const char* GetX86MicroarchitectureName(X86Microarchitecture uarch) {
return "INTEL_KBL";
case INTEL_CFL:
return "INTEL_CFL";
- case INTEL_WHL:
- return "INTEL_WHL";
case INTEL_CNL:
return "INTEL_CNL";
- case INTEL_ICL:
- return "INTEL_ICL";
- case INTEL_TGL:
- return "INTEL_TGL";
- case INTEL_SPR:
- return "INTEL_SPR";
case AMD_HAMMER:
return "AMD_HAMMER";
case AMD_K10:
diff --git a/src/define_tables.h b/src/define_tables.h
deleted file mode 100644
index dc1485c..0000000
--- a/src/define_tables.h
+++ /dev/null
@@ -1,67 +0,0 @@
-// Copyright 2020 Google LLC
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-// 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_
diff --git a/src/filesystem.c b/src/filesystem.c
index 46c9906..2f7083b 100644
--- a/src/filesystem.c
+++ b/src/filesystem.c
@@ -1,4 +1,4 @@
-// Copyright 2017 Google LLC
+// Copyright 2017 Google Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
diff --git a/src/hwcaps.c b/src/hwcaps.c
index dd17e3b..815e5c1 100644
--- a/src/hwcaps.c
+++ b/src/hwcaps.c
@@ -1,4 +1,4 @@
-// Copyright 2017 Google LLC
+// Copyright 2017 Google Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
@@ -12,33 +12,14 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-#include "internal/hwcaps.h"
-
#include <stdlib.h>
#include <string.h>
#include "cpu_features_macros.h"
#include "internal/filesystem.h"
+#include "internal/hwcaps.h"
#include "internal/string_view.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)
#define D(...)
#else
@@ -54,12 +35,9 @@ PlatformType CpuFeatures_GetPlatformType(void);
// Implementation of GetElfHwcapFromGetauxval
////////////////////////////////////////////////////////////////////////////////
-#define AT_HWCAP 16
-#define AT_HWCAP2 26
-#define AT_PLATFORM 15
-#define AT_BASE_PLATFORM 24
-
-#if defined(HAVE_STRONG_GETAUXVAL)
+#if defined(CPU_FEATURES_MOCK_GET_ELF_HWCAP_FROM_GETAUXVAL)
+// Implementation will be provided by test/hwcaps_for_testing.cc.
+#elif defined(HAVE_STRONG_GETAUXVAL)
#include <sys/auxv.h>
static unsigned long GetElfHwcapFromGetauxval(uint32_t hwcap_type) {
return getauxval(hwcap_type);
@@ -81,13 +59,17 @@ static unsigned long GetElfHwcapFromGetauxval(uint32_t hwcap_type) {
// initialization layer.
#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);
static uint32_t GetElfHwcapFromGetauxval(uint32_t hwcap_type) {
uint32_t ret = 0;
- void *libc_handle = NULL;
- getauxval_func_t *func = NULL;
+ void* libc_handle = NULL;
+ getauxval_func_t* func = NULL;
dlerror(); // Cleaning error state before calling dlopen.
libc_handle = dlopen("libc.so", RTLD_NOW);
@@ -95,7 +77,7 @@ static uint32_t GetElfHwcapFromGetauxval(uint32_t hwcap_type) {
D("Could not dlopen() C library: %s\n", dlerror());
return 0;
}
- func = (getauxval_func_t *)dlsym(libc_handle, "getauxval");
+ func = (getauxval_func_t*)dlsym(libc_handle, "getauxval");
if (!func) {
D("Could not find getauxval() in C library\n");
} else {
@@ -127,7 +109,7 @@ static uint32_t GetElfHwcapFromProcSelfAuxv(uint32_t hwcap_type) {
return 0;
}
for (;;) {
- const int ret = CpuFeatures_ReadFile(fd, (char *)&entry, sizeof entry);
+ const int ret = CpuFeatures_ReadFile(fd, (char*)&entry, sizeof entry);
if (ret < 0) {
D("Error while reading %s\n", filepath);
break;
@@ -178,5 +160,3 @@ PlatformType CpuFeatures_GetPlatformType(void) {
sizeof(type.base_platform));
return type;
}
-
-#endif // CPU_FEATURES_TEST
diff --git a/src/stack_line_reader.c b/src/stack_line_reader.c
index ffc778d..b2c48ba 100644
--- a/src/stack_line_reader.c
+++ b/src/stack_line_reader.c
@@ -1,4 +1,4 @@
-// Copyright 2017 Google LLC
+// Copyright 2017 Google Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
@@ -13,13 +13,12 @@
// limitations under the License.
#include "internal/stack_line_reader.h"
+#include "internal/filesystem.h"
#include <assert.h>
#include <errno.h>
#include <stdio.h>
-#include "internal/filesystem.h"
-
void StackLineReader_Initialize(StackLineReader* reader, int fd) {
reader->view.ptr = reader->buffer;
reader->view.size = 0;
diff --git a/src/string_view.c b/src/string_view.c
index dc3158f..856731c 100644
--- a/src/string_view.c
+++ b/src/string_view.c
@@ -1,4 +1,4 @@
-// Copyright 2017 Google LLC
+// Copyright 2017 Google Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
diff --git a/src/unix_features_aggregator.c b/src/unix_features_aggregator.c
new file mode 100644
index 0000000..1b43a36
--- /dev/null
+++ b/src/unix_features_aggregator.c
@@ -0,0 +1,52 @@
+// Copyright 2017 Google Inc.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#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);
+ }
+ }
+}
diff --git a/src/utils/list_cpu_features.c b/src/utils/list_cpu_features.c
index c80ffc5..acda5e7 100644
--- a/src/utils/list_cpu_features.c
+++ b/src/utils/list_cpu_features.c
@@ -1,4 +1,4 @@
-// Copyright 2017 Google LLC
+// Copyright 2017 Google Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
@@ -12,13 +12,6 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-// This program dumps current host data to the standard output.
-// Output can be text or json if the `--json` flag is passed.
-
-#include <assert.h>
-#include <stdarg.h>
-#include <stdbool.h>
-#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@@ -37,178 +30,7 @@
#include "cpuinfo_ppc.h"
#endif
-// Design principles
-// -----------------
-// We build a tree structure containing all the data to be displayed.
-// Then depending on the output type (text or json) we walk the tree and display
-// the data accordingly.
-
-// We use a bump allocator to allocate strings and nodes of the tree,
-// Memory is not intended to be reclaimed.
-typedef struct {
- char* ptr;
- size_t size;
-} BumpAllocator;
-
-char gGlobalBuffer[64 * 1024];
-BumpAllocator gBumpAllocator = {.ptr = gGlobalBuffer,
- .size = sizeof(gGlobalBuffer)};
-
-static void internal_error() {
- fputs("internal error\n", stderr);
- exit(EXIT_FAILURE);
-}
-
-#define ALIGN 8
-
-static void assertAligned() {
- if ((uintptr_t)(gBumpAllocator.ptr) % ALIGN) internal_error();
-}
-
-static void BA_Align() {
- while (gBumpAllocator.size && (uintptr_t)(gBumpAllocator.ptr) % ALIGN) {
- --gBumpAllocator.size;
- ++gBumpAllocator.ptr;
- }
- assertAligned();
-}
-
-// Update the available memory left in the BumpAllocator.
-static void* BA_Bump(size_t size) {
- assertAligned();
- // Align size to next 8B boundary.
- size = (size + ALIGN - 1) / ALIGN * ALIGN;
- if (gBumpAllocator.size < size) internal_error();
- void* ptr = gBumpAllocator.ptr;
- gBumpAllocator.size -= size;
- gBumpAllocator.ptr += size;
- return ptr;
-}
-
-// The type of the nodes in the tree.
-typedef enum {
- NT_INVALID,
- NT_INT,
- NT_MAP,
- NT_MAP_ENTRY,
- NT_ARRAY,
- NT_ARRAY_ELEMENT,
- NT_STRING,
-} NodeType;
-
-// The node in the tree.
-typedef struct Node {
- NodeType type;
- unsigned integer;
- const char* string;
- struct Node* value;
- struct Node* next;
-} Node;
-
-// Creates an initialized Node.
-static Node* BA_CreateNode(NodeType type) {
- Node* tv = (Node*)BA_Bump(sizeof(Node));
- assert(tv);
- *tv = (Node){.type = type};
- return tv;
-}
-
-// Adds an integer node.
-static Node* CreateInt(int value) {
- Node* tv = BA_CreateNode(NT_INT);
- tv->integer = value;
- return tv;
-}
-
-// Adds a string node.
-// `value` must outlive the tree.
-static Node* CreateConstantString(const char* value) {
- Node* tv = BA_CreateNode(NT_STRING);
- tv->string = value;
- return tv;
-}
-
-// Adds a map node.
-static Node* CreateMap() { return BA_CreateNode(NT_MAP); }
-
-// Adds an array node.
-static Node* CreateArray() { return BA_CreateNode(NT_ARRAY); }
-
-// Adds a formatted string node.
-static Node* CreatePrintfString(const char* format, ...) {
- va_list arglist;
- va_start(arglist, format);
- char* const ptr = gBumpAllocator.ptr;
- const int written = vsnprintf(ptr, gBumpAllocator.size, format, arglist);
- va_end(arglist);
- if (written < 0 || written >= (int)gBumpAllocator.size) internal_error();
- return CreateConstantString((char*)BA_Bump(written));
-}
-
-// Adds a string node.
-static Node* CreateString(const char* value) {
- return CreatePrintfString("%s", value);
-}
-
-// Adds a map entry node.
-static void AddMapEntry(Node* map, const char* key, Node* value) {
- assert(map && map->type == NT_MAP);
- Node* current = map;
- while (current->next) current = current->next;
- current->next = (Node*)BA_Bump(sizeof(Node));
- *current->next = (Node){.type = NT_MAP_ENTRY, .string = key, .value = value};
-}
-
-// Adds an array element node.
-static void AddArrayElement(Node* array, Node* value) {
- assert(array && array->type == NT_ARRAY);
- Node* current = array;
- while (current->next) current = current->next;
- current->next = (Node*)BA_Bump(sizeof(Node));
- *current->next = (Node){.type = NT_ARRAY_ELEMENT, .value = value};
-}
-
-static int cmp(const void* p1, const void* p2) {
- return strcmp(*(const char* const*)p1, *(const char* const*)p2);
-}
-
-#define DEFINE_ADD_FLAGS(HasFeature, FeatureName, FeatureType, LastEnum) \
- static void AddFlags(Node* map, const FeatureType* features) { \
- size_t i; \
- const char* ptrs[LastEnum] = {0}; \
- size_t count = 0; \
- for (i = 0; i < LastEnum; ++i) { \
- if (HasFeature(features, i)) { \
- ptrs[count] = FeatureName(i); \
- ++count; \
- } \
- } \
- qsort((void*)ptrs, count, sizeof(char*), cmp); \
- Node* const array = CreateArray(); \
- for (i = 0; i < count; ++i) \
- AddArrayElement(array, CreateConstantString(ptrs[i])); \
- AddMapEntry(map, "flags", array); \
- }
-
-#if defined(CPU_FEATURES_ARCH_X86)
-DEFINE_ADD_FLAGS(GetX86FeaturesEnumValue, GetX86FeaturesEnumName, X86Features,
- X86_LAST_)
-#elif defined(CPU_FEATURES_ARCH_ARM)
-DEFINE_ADD_FLAGS(GetArmFeaturesEnumValue, GetArmFeaturesEnumName, ArmFeatures,
- ARM_LAST_)
-#elif defined(CPU_FEATURES_ARCH_AARCH64)
-DEFINE_ADD_FLAGS(GetAarch64FeaturesEnumValue, GetAarch64FeaturesEnumName,
- Aarch64Features, AARCH64_LAST_)
-#elif defined(CPU_FEATURES_ARCH_MIPS)
-DEFINE_ADD_FLAGS(GetMipsFeaturesEnumValue, GetMipsFeaturesEnumName,
- MipsFeatures, MIPS_LAST_)
-#elif defined(CPU_FEATURES_ARCH_PPC)
-DEFINE_ADD_FLAGS(GetPPCFeaturesEnumValue, GetPPCFeaturesEnumName, PPCFeatures,
- PPC_LAST_)
-#endif
-
-// Prints a json string with characters escaping.
-static void printJsonString(const char* str) {
+static void PrintEscapedAscii(const char* str) {
putchar('"');
for (; str && *str; ++str) {
switch (*str) {
@@ -227,201 +49,188 @@ static void printJsonString(const char* str) {
putchar('"');
}
-// Walks a Node and print it as json.
-static void printJson(const Node* current) {
- assert(current);
- switch (current->type) {
- case NT_INVALID:
- break;
- case NT_INT:
- printf("%d", current->integer);
- break;
- case NT_STRING:
- printJsonString(current->string);
- break;
- case NT_ARRAY:
- putchar('[');
- if (current->next) printJson(current->next);
- putchar(']');
- break;
- case NT_MAP:
- putchar('{');
- if (current->next) printJson(current->next);
- putchar('}');
- break;
- case NT_MAP_ENTRY:
- printf("\"%s\":", current->string);
- printJson(current->value);
- if (current->next) {
- putchar(',');
- printJson(current->next);
- }
- break;
- case NT_ARRAY_ELEMENT:
- printJson(current->value);
- if (current->next) {
- putchar(',');
- printJson(current->next);
- }
- break;
- }
+static void PrintVoid(void) {}
+static void PrintComma(void) { putchar(','); }
+static void PrintLineFeed(void) { putchar('\n'); }
+static void PrintOpenBrace(void) { putchar('{'); }
+static void PrintCloseBrace(void) { putchar('}'); }
+static void PrintOpenBracket(void) { putchar('['); }
+static void PrintCloseBracket(void) { putchar(']'); }
+static void PrintString(const char* field) { printf("%s", field); }
+static void PrintAlignedHeader(const char* field) { printf("%-15s : ", field); }
+static void PrintIntValue(int value) { printf("%d", value); }
+static void PrintDecHexValue(int value) {
+ printf("%3d (0x%02X)", value, value);
}
-
-// Walks a Node and print it as text.
-static void printTextField(const Node* current) {
- switch (current->type) {
- case NT_INVALID:
- break;
- case NT_INT:
- printf("%3d (0x%02X)", current->integer, current->integer);
- break;
- case NT_STRING:
- fputs(current->string, stdout);
- break;
- case NT_ARRAY:
- if (current->next) printTextField(current->next);
- break;
- case NT_MAP:
- if (current->next) {
- printf("{");
- printJson(current->next);
- printf("}");
- }
- break;
- case NT_MAP_ENTRY:
- printf("%-15s : ", current->string);
- printTextField(current->value);
- if (current->next) {
- putchar('\n');
- printTextField(current->next);
- }
- break;
- case NT_ARRAY_ELEMENT:
- printTextField(current->value);
- if (current->next) {
- putchar(',');
- printTextField(current->next);
- }
- break;
- }
+static void PrintJsonHeader(const char* field) {
+ PrintEscapedAscii(field);
+ putchar(':');
}
-static void printTextRoot(const Node* current) {
- if (current->type == NT_MAP && current->next) printTextField(current->next);
+typedef struct {
+ void (*Start)(void);
+ void (*ArrayStart)(void);
+ void (*ArraySeparator)(void);
+ void (*ArrayEnd)(void);
+ void (*PrintString)(const char* value);
+ void (*PrintValue)(int value);
+ void (*EndField)(void);
+ void (*StartField)(const char* field);
+ void (*End)(void);
+} Printer;
+
+static Printer getJsonPrinter(void) {
+ return (Printer){
+ .Start = &PrintOpenBrace,
+ .ArrayStart = &PrintOpenBracket,
+ .ArraySeparator = &PrintComma,
+ .ArrayEnd = &PrintCloseBracket,
+ .PrintString = &PrintEscapedAscii,
+ .PrintValue = &PrintIntValue,
+ .EndField = &PrintComma,
+ .StartField = &PrintJsonHeader,
+ .End = &PrintCloseBrace,
+ };
+}
+
+static Printer getTextPrinter(void) {
+ return (Printer){
+ .Start = &PrintVoid,
+ .ArrayStart = &PrintVoid,
+ .ArraySeparator = &PrintComma,
+ .ArrayEnd = &PrintVoid,
+ .PrintString = &PrintString,
+ .PrintValue = &PrintDecHexValue,
+ .EndField = &PrintLineFeed,
+ .StartField = &PrintAlignedHeader,
+ .End = &PrintVoid,
+ };
+}
+
+// Prints a named numeric value in both decimal and hexadecimal.
+static void PrintN(const Printer p, const char* field, int value) {
+ p.StartField(field);
+ p.PrintValue(value);
+ p.EndField();
+}
+
+// Prints a named string.
+static void PrintS(const Printer p, const char* field, const char* value) {
+ p.StartField(field);
+ p.PrintString(value);
+ p.EndField();
}
-static void showUsage(const char* name) {
- printf(
- "\n"
- "Usage: %s [options]\n"
- " Options:\n"
- " -h | --help Show help message.\n"
- " -j | --json Format output as json instead of plain text.\n"
- "\n",
- name);
+static int cmp(const void* p1, const void* p2) {
+ return strcmp(*(const char* const*)p1, *(const char* const*)p2);
}
-static Node* GetCacheTypeString(CacheType cache_type) {
- switch (cache_type) {
- case CPU_FEATURE_CACHE_NULL:
- return CreateConstantString("null");
- case CPU_FEATURE_CACHE_DATA:
- return CreateConstantString("data");
- case CPU_FEATURE_CACHE_INSTRUCTION:
- return CreateConstantString("instruction");
- case CPU_FEATURE_CACHE_UNIFIED:
- return CreateConstantString("unified");
- case CPU_FEATURE_CACHE_TLB:
- return CreateConstantString("tlb");
- case CPU_FEATURE_CACHE_DTLB:
- return CreateConstantString("dtlb");
- case CPU_FEATURE_CACHE_STLB:
- return CreateConstantString("stlb");
- case CPU_FEATURE_CACHE_PREFETCH:
- return CreateConstantString("prefetch");
+#define DEFINE_PRINT_FLAGS(HasFeature, FeatureName, FeatureType, LastEnum) \
+ static void PrintFlags(const Printer p, const FeatureType* features) { \
+ size_t i; \
+ const char* ptrs[LastEnum] = {0}; \
+ size_t count = 0; \
+ for (i = 0; i < LastEnum; ++i) { \
+ if (HasFeature(features, i)) { \
+ ptrs[count] = FeatureName(i); \
+ ++count; \
+ } \
+ } \
+ qsort((void*)ptrs, count, sizeof(char*), cmp); \
+ p.StartField("flags"); \
+ p.ArrayStart(); \
+ for (i = 0; i < count; ++i) { \
+ if (i > 0) p.ArraySeparator(); \
+ p.PrintString(ptrs[i]); \
+ } \
+ p.ArrayEnd(); \
}
-}
-static void AddCacheInfo(Node* root, const CacheInfo* cache_info) {
- Node* array = CreateArray();
- for (int i = 0; i < cache_info->size; ++i) {
- CacheLevelInfo info = cache_info->levels[i];
- Node* map = CreateMap();
- AddMapEntry(map, "level", CreateInt(info.level));
- AddMapEntry(map, "cache_type", GetCacheTypeString(info.cache_type));
- AddMapEntry(map, "cache_size", CreateInt(info.cache_size));
- AddMapEntry(map, "ways", CreateInt(info.ways));
- AddMapEntry(map, "line_size", CreateInt(info.line_size));
- AddMapEntry(map, "tlb_entries", CreateInt(info.tlb_entries));
- AddMapEntry(map, "partitioning", CreateInt(info.partitioning));
- AddArrayElement(array, map);
- }
- AddMapEntry(root, "cache_info", array);
-}
+#if defined(CPU_FEATURES_ARCH_X86)
+DEFINE_PRINT_FLAGS(GetX86FeaturesEnumValue, GetX86FeaturesEnumName, X86Features,
+ X86_LAST_)
+#elif defined(CPU_FEATURES_ARCH_ARM)
+DEFINE_PRINT_FLAGS(GetArmFeaturesEnumValue, GetArmFeaturesEnumName, ArmFeatures,
+ ARM_LAST_)
+#elif defined(CPU_FEATURES_ARCH_AARCH64)
+DEFINE_PRINT_FLAGS(GetAarch64FeaturesEnumValue, GetAarch64FeaturesEnumName,
+ Aarch64Features, AARCH64_LAST_)
+#elif defined(CPU_FEATURES_ARCH_MIPS)
+DEFINE_PRINT_FLAGS(GetMipsFeaturesEnumValue, GetMipsFeaturesEnumName,
+ MipsFeatures, MIPS_LAST_)
+#elif defined(CPU_FEATURES_ARCH_PPC)
+DEFINE_PRINT_FLAGS(GetPPCFeaturesEnumValue, GetPPCFeaturesEnumName, PPCFeatures,
+ PPC_LAST_)
+#endif
-static Node* CreateTree() {
- Node* root = CreateMap();
+static void PrintFeatures(const Printer printer) {
#if defined(CPU_FEATURES_ARCH_X86)
char brand_string[49];
const X86Info info = GetX86Info();
- const CacheInfo cache_info = GetX86CacheInfo();
FillX86BrandString(brand_string);
- AddMapEntry(root, "arch", CreateString("x86"));
- AddMapEntry(root, "brand", CreateString(brand_string));
- AddMapEntry(root, "family", CreateInt(info.family));
- AddMapEntry(root, "model", CreateInt(info.model));
- AddMapEntry(root, "stepping", CreateInt(info.stepping));
- AddMapEntry(root, "uarch",
- CreateString(
- GetX86MicroarchitectureName(GetX86Microarchitecture(&info))));
- AddFlags(root, &info.features);
- AddCacheInfo(root, &cache_info);
+ PrintS(printer, "arch", "x86");
+ PrintS(printer, "brand", brand_string);
+ PrintN(printer, "family", info.family);
+ PrintN(printer, "model", info.model);
+ PrintN(printer, "stepping", info.stepping);
+ PrintS(printer, "uarch",
+ GetX86MicroarchitectureName(GetX86Microarchitecture(&info)));
+ PrintFlags(printer, &info.features);
#elif defined(CPU_FEATURES_ARCH_ARM)
const ArmInfo info = GetArmInfo();
- AddMapEntry(root, "arch", CreateString("ARM"));
- AddMapEntry(root, "implementer", CreateInt(info.implementer));
- AddMapEntry(root, "architecture", CreateInt(info.architecture));
- AddMapEntry(root, "variant", CreateInt(info.variant));
- AddMapEntry(root, "part", CreateInt(info.part));
- AddMapEntry(root, "revision", CreateInt(info.revision));
- AddFlags(root, &info.features);
+ PrintS(printer, "arch", "ARM");
+ PrintN(printer, "implementer", info.implementer);
+ PrintN(printer, "architecture", info.architecture);
+ PrintN(printer, "variant", info.variant);
+ PrintN(printer, "part", info.part);
+ PrintN(printer, "revision", info.revision);
+ PrintFlags(printer, &info.features);
#elif defined(CPU_FEATURES_ARCH_AARCH64)
const Aarch64Info info = GetAarch64Info();
- AddMapEntry(root, "arch", CreateString("aarch64"));
- AddMapEntry(root, "implementer", CreateInt(info.implementer));
- AddMapEntry(root, "variant", CreateInt(info.variant));
- AddMapEntry(root, "part", CreateInt(info.part));
- AddMapEntry(root, "revision", CreateInt(info.revision));
- AddFlags(root, &info.features);
+ PrintS(printer, "arch", "aarch64");
+ PrintN(printer, "implementer", info.implementer);
+ PrintN(printer, "variant", info.variant);
+ PrintN(printer, "part", info.part);
+ PrintN(printer, "revision", info.revision);
+ PrintFlags(printer, &info.features);
#elif defined(CPU_FEATURES_ARCH_MIPS)
+ (void)&PrintN; // Remove unused function warning.
const MipsInfo info = GetMipsInfo();
- AddMapEntry(root, "arch", CreateString("mips"));
- AddFlags(root, &info.features);
+ PrintS(printer, "arch", "mips");
+ PrintFlags(printer, &info.features);
#elif defined(CPU_FEATURES_ARCH_PPC)
+ (void)&PrintN; // Remove unused function warning.
const PPCInfo info = GetPPCInfo();
const PPCPlatformStrings strings = GetPPCPlatformStrings();
- AddMapEntry(root, "arch", CreateString("ppc"));
- AddMapEntry(root, "platform", CreateString(strings.platform));
- AddMapEntry(root, "model", CreateString(strings.model));
- AddMapEntry(root, "machine", CreateString(strings.machine));
- AddMapEntry(root, "cpu", CreateString(strings.cpu));
- AddMapEntry(root, "instruction", CreateString(strings.type.platform));
- AddMapEntry(root, "microarchitecture",
- CreateString(strings.type.base_platform));
- AddFlags(root, &info.features);
+ PrintS(printer, "arch", "ppc");
+ PrintS(printer, "platform", strings.platform);
+ PrintS(printer, "model", strings.model);
+ PrintS(printer, "machine", strings.machine);
+ PrintS(printer, "cpu", strings.cpu);
+ PrintS(printer, "instruction set", strings.type.platform);
+ PrintS(printer, "microarchitecture", strings.type.base_platform);
+ PrintFlags(printer, &info.features);
#endif
- return root;
+}
+
+static void showUsage(const char* name) {
+ printf(
+ "\n"
+ "Usage: %s [options]\n"
+ " Options:\n"
+ " -h | --help Show help message.\n"
+ " -j | --json Format output as json instead of plain text.\n"
+ "\n",
+ name);
}
int main(int argc, char** argv) {
- BA_Align();
- const Node* const root = CreateTree();
- bool outputJson = false;
+ Printer printer = getTextPrinter();
int i = 1;
for (; i < argc; ++i) {
const char* arg = argv[i];
if (strcmp(arg, "-j") == 0 || strcmp(arg, "--json") == 0) {
- outputJson = true;
+ printer = getJsonPrinter();
} else {
showUsage(argv[0]);
if (strcmp(arg, "-h") == 0 || strcmp(arg, "--help") == 0)
@@ -429,10 +238,9 @@ int main(int argc, char** argv) {
return EXIT_FAILURE;
}
}
- if (outputJson)
- printJson(root);
- else
- printTextRoot(root);
- putchar('\n');
+ printer.Start();
+ PrintFeatures(printer);
+ printer.End();
+ PrintLineFeed();
return EXIT_SUCCESS;
}
diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt
index c10e617..a744ee9 100644
--- a/test/CMakeLists.txt
+++ b/test/CMakeLists.txt
@@ -2,6 +2,10 @@
# libraries for tests
#
+set(CMAKE_CXX_STANDARD 11)
+set(CMAKE_CXX_STANDARD_REQUIRED ON)
+set(CMAKE_CXX_EXTENSIONS OFF) # prefer use of -std11 instead of -gnustd11
+
include_directories(../include)
add_definitions(-DCPU_FEATURES_TEST)
@@ -12,6 +16,7 @@ add_library(filesystem_for_testing filesystem_for_testing.cc)
target_compile_definitions(filesystem_for_testing PUBLIC CPU_FEATURES_MOCK_FILESYSTEM)
##------------------------------------------------------------------------------
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)
##------------------------------------------------------------------------------
add_library(stack_line_reader ../src/stack_line_reader.c)
@@ -22,7 +27,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_link_libraries(stack_line_reader_for_test string_view filesystem_for_testing)
##------------------------------------------------------------------------------
-add_library(all_libraries ../src/hwcaps.c ../src/stack_line_reader.c)
+add_library(all_libraries ../src/stack_line_reader.c ../src/unix_features_aggregator.c)
target_link_libraries(all_libraries hwcaps_for_testing stack_line_reader string_view)
#
@@ -45,13 +50,15 @@ add_executable(stack_line_reader_test stack_line_reader_test.cc)
target_link_libraries(stack_line_reader_test stack_line_reader_for_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
if(PROCESSOR_IS_X86)
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)
- if(APPLE)
- target_compile_definitions(cpuinfo_x86_test PRIVATE HAVE_SYSCTLBYNAME)
- endif()
target_link_libraries(cpuinfo_x86_test all_libraries)
add_test(NAME cpuinfo_x86_test COMMAND cpuinfo_x86_test)
endif()
diff --git a/test/bit_utils_test.cc b/test/bit_utils_test.cc
index 3874e13..9c8c1bb 100644
--- a/test/bit_utils_test.cc
+++ b/test/bit_utils_test.cc
@@ -1,4 +1,4 @@
-// Copyright 2017 Google LLC
+// Copyright 2017 Google Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
diff --git a/test/cpuinfo_aarch64_test.cc b/test/cpuinfo_aarch64_test.cc
index 5afaaa8..bdb4d17 100644
--- a/test/cpuinfo_aarch64_test.cc
+++ b/test/cpuinfo_aarch64_test.cc
@@ -1,4 +1,4 @@
-// Copyright 2017 Google LLC
+// Copyright 2017 Google Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
@@ -13,11 +13,11 @@
// limitations under the License.
#include "cpuinfo_aarch64.h"
-
#include "filesystem_for_testing.h"
-#include "gtest/gtest.h"
#include "hwcaps_for_testing.h"
+#include "gtest/gtest.h"
+
namespace cpu_features {
namespace {
@@ -29,64 +29,11 @@ TEST(CpuinfoAarch64Test, FromHardwareCap) {
const auto info = GetAarch64Info();
EXPECT_TRUE(info.features.fp);
EXPECT_FALSE(info.features.asimd);
- EXPECT_FALSE(info.features.evtstrm);
EXPECT_TRUE(info.features.aes);
EXPECT_FALSE(info.features.pmull);
EXPECT_FALSE(info.features.sha1);
EXPECT_FALSE(info.features.sha2);
EXPECT_FALSE(info.features.crc32);
- EXPECT_FALSE(info.features.atomics);
- EXPECT_FALSE(info.features.fphp);
- EXPECT_FALSE(info.features.asimdhp);
- EXPECT_FALSE(info.features.cpuid);
- EXPECT_FALSE(info.features.asimdrdm);
- EXPECT_FALSE(info.features.jscvt);
- EXPECT_FALSE(info.features.fcma);
- EXPECT_FALSE(info.features.lrcpc);
- EXPECT_FALSE(info.features.dcpop);
- EXPECT_FALSE(info.features.sha3);
- EXPECT_FALSE(info.features.sm3);
- EXPECT_FALSE(info.features.sm4);
- EXPECT_FALSE(info.features.asimddp);
- EXPECT_FALSE(info.features.sha512);
- EXPECT_FALSE(info.features.sve);
- EXPECT_FALSE(info.features.asimdfhm);
- EXPECT_FALSE(info.features.dit);
- EXPECT_FALSE(info.features.uscat);
- EXPECT_FALSE(info.features.ilrcpc);
- EXPECT_FALSE(info.features.flagm);
- EXPECT_FALSE(info.features.ssbs);
- EXPECT_FALSE(info.features.sb);
- EXPECT_FALSE(info.features.paca);
- 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) {
@@ -116,55 +63,11 @@ CPU revision : 3)");
EXPECT_TRUE(info.features.fp);
EXPECT_TRUE(info.features.asimd);
- EXPECT_TRUE(info.features.evtstrm);
EXPECT_TRUE(info.features.aes);
EXPECT_TRUE(info.features.pmull);
EXPECT_TRUE(info.features.sha1);
EXPECT_TRUE(info.features.sha2);
EXPECT_TRUE(info.features.crc32);
-
- EXPECT_FALSE(info.features.atomics);
- EXPECT_FALSE(info.features.fphp);
- EXPECT_FALSE(info.features.asimdhp);
- EXPECT_FALSE(info.features.cpuid);
- EXPECT_FALSE(info.features.asimdrdm);
- EXPECT_FALSE(info.features.jscvt);
- EXPECT_FALSE(info.features.fcma);
- EXPECT_FALSE(info.features.lrcpc);
- EXPECT_FALSE(info.features.dcpop);
- EXPECT_FALSE(info.features.sha3);
- EXPECT_FALSE(info.features.sm3);
- EXPECT_FALSE(info.features.sm4);
- EXPECT_FALSE(info.features.asimddp);
- EXPECT_FALSE(info.features.sha512);
- EXPECT_FALSE(info.features.sve);
- EXPECT_FALSE(info.features.asimdfhm);
- EXPECT_FALSE(info.features.dit);
- EXPECT_FALSE(info.features.uscat);
- EXPECT_FALSE(info.features.ilrcpc);
- EXPECT_FALSE(info.features.flagm);
- EXPECT_FALSE(info.features.ssbs);
- EXPECT_FALSE(info.features.sb);
- EXPECT_FALSE(info.features.paca);
- 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
diff --git a/test/cpuinfo_arm_test.cc b/test/cpuinfo_arm_test.cc
index e0b08a4..9ddf90f 100644
--- a/test/cpuinfo_arm_test.cc
+++ b/test/cpuinfo_arm_test.cc
@@ -1,4 +1,4 @@
-// Copyright 2017 Google LLC
+// Copyright 2017 Google Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
@@ -13,11 +13,11 @@
// limitations under the License.
#include "cpuinfo_arm.h"
-
#include "filesystem_for_testing.h"
-#include "gtest/gtest.h"
#include "hwcaps_for_testing.h"
+#include "gtest/gtest.h"
+
namespace cpu_features {
namespace {
@@ -43,12 +43,6 @@ TEST(CpuinfoArmTest, FromHardwareCap) {
EXPECT_FALSE(info.features.pmull);
EXPECT_FALSE(info.features.sha1);
EXPECT_FALSE(info.features.sha2);
-
- // check some random features with EnumValue():
- EXPECT_TRUE(GetArmFeaturesEnumValue(&info.features, ARM_VFP));
- EXPECT_FALSE(GetArmFeaturesEnumValue(&info.features, ARM_VFPV4));
- // out of bound EnumValue() check
- EXPECT_FALSE(GetArmFeaturesEnumValue(&info.features, (ArmFeaturesEnum)~0x0));
}
TEST(CpuinfoArmTest, ODroidFromCpuInfo) {
diff --git a/test/cpuinfo_mips_test.cc b/test/cpuinfo_mips_test.cc
index d734058..fbec04d 100644
--- a/test/cpuinfo_mips_test.cc
+++ b/test/cpuinfo_mips_test.cc
@@ -1,4 +1,4 @@
-// Copyright 2017 Google LLC
+// Copyright 2017 Google Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
@@ -13,13 +13,13 @@
// limitations under the License.
#include "cpuinfo_mips.h"
-
#include "filesystem_for_testing.h"
-#include "gtest/gtest.h"
#include "hwcaps_for_testing.h"
#include "internal/stack_line_reader.h"
#include "internal/string_view.h"
+#include "gtest/gtest.h"
+
namespace cpu_features {
namespace {
diff --git a/test/cpuinfo_ppc_test.cc b/test/cpuinfo_ppc_test.cc
index 8f0cb65..5d5e798 100644
--- a/test/cpuinfo_ppc_test.cc
+++ b/test/cpuinfo_ppc_test.cc
@@ -13,12 +13,12 @@
// limitations under the License.
#include "cpuinfo_ppc.h"
-
#include "filesystem_for_testing.h"
-#include "gtest/gtest.h"
#include "hwcaps_for_testing.h"
#include "internal/string_view.h"
+#include "gtest/gtest.h"
+
namespace cpu_features {
namespace {
diff --git a/test/cpuinfo_x86_test.cc b/test/cpuinfo_x86_test.cc
index 636d0f9..10b9624 100644
--- a/test/cpuinfo_x86_test.cc
+++ b/test/cpuinfo_x86_test.cc
@@ -1,4 +1,4 @@
-// Copyright 2017 Google LLC
+// Copyright 2017 Google Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
@@ -12,25 +12,20 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-#include "cpuinfo_x86.h"
-
#include <cassert>
#include <cstdio>
#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 "cpuinfo_x86.h"
#include "internal/cpuid_x86.h"
namespace cpu_features {
class FakeCpu {
public:
- Leaf GetCpuidLeaf(uint32_t leaf_id, int ecx) const {
+ Leaf CpuIdEx(uint32_t leaf_id, int ecx) const {
const auto itr = cpuid_leaves_.find(std::make_pair(leaf_id, ecx));
if (itr != cpuid_leaves_.end()) {
return itr->second;
@@ -48,66 +43,22 @@ class FakeCpu {
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:
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_;
};
-FakeCpu* g_fake_cpu = nullptr;
+auto* g_fake_cpu = new FakeCpu();
-extern "C" Leaf GetCpuidLeaf(uint32_t leaf_id, int ecx) {
- return g_fake_cpu->GetCpuidLeaf(leaf_id, ecx);
+extern "C" Leaf CpuIdEx(uint32_t leaf_id, int ecx) {
+ return g_fake_cpu->CpuIdEx(leaf_id, ecx);
}
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 {
-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) {
+TEST(CpuidX86Test, SandyBridge) {
g_fake_cpu->SetOsBackupsExtendedRegisters(true);
g_fake_cpu->SetLeaves({
{{0x00000000, 0}, Leaf{0x0000000D, 0x756E6547, 0x6C65746E, 0x49656E69}},
@@ -137,7 +88,7 @@ TEST_F(CpuidX86Test, SandyBridge) {
EXPECT_FALSE(features.avx512bitalg);
EXPECT_FALSE(features.avx512vpopcntdq);
EXPECT_FALSE(features.avx512_4vnniw);
- EXPECT_FALSE(features.avx512_4fmaps);
+ EXPECT_FALSE(features.avx512_4vbmi2);
// All old cpu features should be set.
EXPECT_TRUE(features.aes);
EXPECT_TRUE(features.ssse3);
@@ -153,7 +104,7 @@ TEST_F(CpuidX86Test, SandyBridge) {
const int KiB = 1024;
const int MiB = 1024 * KiB;
-TEST_F(CpuidX86Test, SandyBridgeTestOsSupport) {
+TEST(CpuidX86Test, SandyBridgeTestOsSupport) {
g_fake_cpu->SetLeaves({
{{0x00000000, 0}, Leaf{0x0000000D, 0x756E6547, 0x6C65746E, 0x49656E69}},
{{0x00000001, 0}, Leaf{0x000206A6, 0x00100800, 0x1F9AE3BF, 0xBFEBFBFF}},
@@ -167,7 +118,7 @@ TEST_F(CpuidX86Test, SandyBridgeTestOsSupport) {
EXPECT_TRUE(GetX86Info().features.avx);
}
-TEST_F(CpuidX86Test, SkyLake) {
+TEST(CpuidX86Test, SkyLake) {
g_fake_cpu->SetOsBackupsExtendedRegisters(true);
g_fake_cpu->SetLeaves({
{{0x00000000, 0}, Leaf{0x00000016, 0x756E6547, 0x6C65746E, 0x49656E69}},
@@ -182,7 +133,7 @@ TEST_F(CpuidX86Test, SkyLake) {
EXPECT_EQ(GetX86Microarchitecture(&info), X86Microarchitecture::INTEL_SKL);
}
-TEST_F(CpuidX86Test, Branding) {
+TEST(CpuidX86Test, Branding) {
g_fake_cpu->SetLeaves({
{{0x00000000, 0}, Leaf{0x00000016, 0x756E6547, 0x6C65746E, 0x49656E69}},
{{0x00000001, 0}, Leaf{0x000406E3, 0x00100800, 0x7FFAFBBF, 0xBFEBFBFF}},
@@ -198,7 +149,7 @@ TEST_F(CpuidX86Test, Branding) {
EXPECT_STREQ(brand_string, "Intel(R) Core(TM) i7-6500U CPU @ 2.50GHz");
}
-TEST_F(CpuidX86Test, KabyLakeCache) {
+TEST(CpuidX86Test, KabyLakeCache) {
g_fake_cpu->SetLeaves({
{{0x00000000, 0}, Leaf{0x00000016, 0x756E6547, 0x6C65746E, 0x49656E69}},
{{0x00000001, 0}, Leaf{0x000406E3, 0x00100800, 0x7FFAFBBF, 0xBFEBFBFF}},
@@ -247,7 +198,7 @@ TEST_F(CpuidX86Test, KabyLakeCache) {
EXPECT_EQ(info.levels[3].partitioning, 1);
}
-TEST_F(CpuidX86Test, HSWCache) {
+TEST(CpuidX86Test, HSWCache) {
g_fake_cpu->SetLeaves({
{{0x00000000, 0}, Leaf{0x00000016, 0x756E6547, 0x6C65746E, 0x49656E69}},
{{0x00000001, 0}, Leaf{0x000406E3, 0x00100800, 0x7FFAFBBF, 0xBFEBFBFF}},
@@ -295,9 +246,8 @@ TEST_F(CpuidX86Test, HSWCache) {
EXPECT_EQ(info.levels[3].tlb_entries, 8192);
EXPECT_EQ(info.levels[3].partitioning, 1);
}
-
// http://users.atw.hu/instlatx64/AuthenticAMD0630F81_K15_Godavari_CPUID.txt
-TEST_F(CpuidX86Test, AMD_K15) {
+TEST(CpuidX86Test, AMD_K15) {
g_fake_cpu->SetLeaves({
{{0x00000000, 0}, Leaf{0x0000000D, 0x68747541, 0x444D4163, 0x69746E65}},
{{0x00000001, 0}, Leaf{0x00630F81, 0x00040800, 0x3E98320B, 0x178BFBFF}},
@@ -323,208 +273,6 @@ TEST_F(CpuidX86Test, AMD_K15) {
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 xmm/ymm/zmm os support are not
// present.
diff --git a/test/filesystem_for_testing.cc b/test/filesystem_for_testing.cc
index 648a53e..0a11416 100644
--- a/test/filesystem_for_testing.cc
+++ b/test/filesystem_for_testing.cc
@@ -1,4 +1,4 @@
-// Copyright 2017 Google LLC
+// Copyright 2017 Google Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
diff --git a/test/filesystem_for_testing.h b/test/filesystem_for_testing.h
index ef717fd..7474b5f 100644
--- a/test/filesystem_for_testing.h
+++ b/test/filesystem_for_testing.h
@@ -1,4 +1,4 @@
-// Copyright 2017 Google LLC
+// Copyright 2017 Google Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
diff --git a/test/hwcaps_for_testing.cc b/test/hwcaps_for_testing.cc
index a8086a0..07f68e8 100644
--- a/test/hwcaps_for_testing.cc
+++ b/test/hwcaps_for_testing.cc
@@ -1,4 +1,4 @@
-// Copyright 2017 Google LLC
+// Copyright 2017 Google Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
@@ -12,10 +12,9 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-#include "hwcaps_for_testing.h"
-
#include <string.h>
+#include "hwcaps_for_testing.h"
#include "internal/string_view.h"
namespace cpu_features {
diff --git a/test/hwcaps_for_testing.h b/test/hwcaps_for_testing.h
index bcab82e..0d03777 100644
--- a/test/hwcaps_for_testing.h
+++ b/test/hwcaps_for_testing.h
@@ -1,4 +1,4 @@
-// Copyright 2017 Google LLC
+// Copyright 2017 Google Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
diff --git a/test/stack_line_reader_test.cc b/test/stack_line_reader_test.cc
index 9ac5388..c8f9691 100644
--- a/test/stack_line_reader_test.cc
+++ b/test/stack_line_reader_test.cc
@@ -1,4 +1,4 @@
-// Copyright 2017 Google LLC
+// Copyright 2017 Google Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
@@ -13,8 +13,8 @@
// limitations under the License.
#include "internal/stack_line_reader.h"
-
#include "filesystem_for_testing.h"
+
#include "gtest/gtest.h"
namespace cpu_features {
diff --git a/test/string_view_test.cc b/test/string_view_test.cc
index ca3e023..abfcc2c 100644
--- a/test/string_view_test.cc
+++ b/test/string_view_test.cc
@@ -1,4 +1,4 @@
-// Copyright 2017 Google LLC
+// Copyright 2017 Google Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
@@ -38,8 +38,6 @@ TEST(StringViewTest, Build) {
TEST(StringViewTest, CpuFeatures_StringView_IndexOfChar) {
// Found.
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.
EXPECT_EQ(CpuFeatures_StringView_IndexOfChar(str("test"), 'z'), -1);
// Empty.
@@ -49,8 +47,6 @@ TEST(StringViewTest, CpuFeatures_StringView_IndexOfChar) {
TEST(StringViewTest, CpuFeatures_StringView_IndexOf) {
// Found.
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.
EXPECT_EQ(CpuFeatures_StringView_IndexOf(str("test"), str("aa")), -1);
// Empty.
@@ -60,9 +56,6 @@ TEST(StringViewTest, CpuFeatures_StringView_IndexOf) {
TEST(StringViewTest, CpuFeatures_StringView_StartsWith) {
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"), kEmptyStringView));
@@ -75,11 +68,8 @@ TEST(StringViewTest, CpuFeatures_StringView_IsEquals) {
CpuFeatures_StringView_IsEquals(kEmptyStringView, kEmptyStringView));
EXPECT_TRUE(CpuFeatures_StringView_IsEquals(kEmptyStringView, str("")));
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_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(kEmptyStringView, str("a")));
}
@@ -91,49 +81,11 @@ TEST(StringViewTest, CpuFeatures_StringView_PopFront) {
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) {
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("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("abc")), -1);
EXPECT_EQ(CpuFeatures_StringView_ParsePositiveNumber(str("")), -1);
diff --git a/test/unix_features_aggregator_test.cc b/test/unix_features_aggregator_test.cc
new file mode 100644
index 0000000..dd491f2
--- /dev/null
+++ b/test/unix_features_aggregator_test.cc
@@ -0,0 +1,95 @@
+// Copyright 2017 Google Inc.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include <array>
+
+#include "internal/unix_features_aggregator.h"
+
+#include "gtest/gtest.h"
+
+namespace cpu_features {
+
+namespace {
+
+struct Features {
+ bool a = false;
+ bool b = false;
+ bool c = false;
+};
+
+DECLARE_SETTER(Features, a)
+DECLARE_SETTER(Features, b)
+DECLARE_SETTER(Features, c)
+
+class LinuxFeatureAggregatorTest : public testing::Test {
+ public:
+ const std::array<CapabilityConfig, 3> kConfigs = {
+ {{{0b0001, 0b0000}, "a", &set_a},
+ {{0b0010, 0b0000}, "b", &set_b},
+ {{0b0000, 0b1100}, "c", &set_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);
+}
+
+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);
+}
+
+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);
+}
+
+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