1
0
mirror of https://github.com/gnss-sdr/gnss-sdr synced 2024-12-15 04:30:33 +00:00

Update cpu_features code layout to 69d39934e8

This commit is contained in:
Carles Fernandez 2021-12-24 15:14:26 +01:00
parent ce9bbf74b0
commit e373a7c860
No known key found for this signature in database
GPG Key ID: 4C583C52B0C3877D
37 changed files with 1793 additions and 1505 deletions

View File

@ -270,6 +270,7 @@ elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "^(powerpc|ppc)")
endif() endif()
if(CMAKE_VERSION VERSION_GREATER 3.0 AND SUPPORTED_CPU_FEATURES_ARCH) if(CMAKE_VERSION VERSION_GREATER 3.0 AND SUPPORTED_CPU_FEATURES_ARCH)
set(BUILD_TESTING OFF CACHE BOOL "Build cpu_features without tests." FORCE)
set(CMAKE_POSITION_INDEPENDENT_CODE ON CACHE BOOL set(CMAKE_POSITION_INDEPENDENT_CODE ON CACHE BOOL
"Build cpu_features with Position Independent Code (PIC)." "Build cpu_features with Position Independent Code (PIC)."
FORCE FORCE

View File

@ -23,9 +23,6 @@ if(NOT CMAKE_BUILD_TYPE)
FORCE) FORCE)
endif() endif()
# BUILD_TESTING is a standard CMake variable, but we declare it here to make it
# prominent in the GUI.
option(BUILD_TESTING "Enable test (depends on googletest)." OFF)
# BUILD_SHARED_LIBS is a standard CMake variable, but we declare it here to make # BUILD_SHARED_LIBS is a standard CMake variable, but we declare it here to make
# it prominent in the GUI. # 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). # cpu_features uses bit-fields which are - to some extends - implementation-defined (see https://en.cppreference.com/w/c/language/bit_field).
@ -61,7 +58,7 @@ set(PROCESSOR_IS_POWER FALSE)
if(CMAKE_SYSTEM_PROCESSOR MATCHES "^mips") if(CMAKE_SYSTEM_PROCESSOR MATCHES "^mips")
set(PROCESSOR_IS_MIPS TRUE) set(PROCESSOR_IS_MIPS TRUE)
elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "(^aarch64)|(arm64)") elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "^(aarch64|arm64)")
set(PROCESSOR_IS_AARCH64 TRUE) set(PROCESSOR_IS_AARCH64 TRUE)
elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "^arm") elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "^arm")
set(PROCESSOR_IS_ARM TRUE) set(PROCESSOR_IS_ARM TRUE)
@ -74,22 +71,19 @@ endif()
macro(add_cpu_features_headers_and_sources HDRS_LIST_NAME SRCS_LIST_NAME) macro(add_cpu_features_headers_and_sources HDRS_LIST_NAME SRCS_LIST_NAME)
list(APPEND ${HDRS_LIST_NAME} ${PROJECT_SOURCE_DIR}/include/cpu_features_macros.h) list(APPEND ${HDRS_LIST_NAME} ${PROJECT_SOURCE_DIR}/include/cpu_features_macros.h)
list(APPEND ${HDRS_LIST_NAME} ${PROJECT_SOURCE_DIR}/include/cpu_features_cache_info.h) list(APPEND ${HDRS_LIST_NAME} ${PROJECT_SOURCE_DIR}/include/cpu_features_cache_info.h)
file(GLOB IMPL_SOURCES CONFIGURE_DEPENDS "${PROJECT_SOURCE_DIR}/src/impl_*.c")
list(APPEND ${SRCS_LIST_NAME} ${IMPL_SOURCES})
if(PROCESSOR_IS_MIPS) if(PROCESSOR_IS_MIPS)
list(APPEND ${HDRS_LIST_NAME} ${PROJECT_SOURCE_DIR}/include/cpuinfo_mips.h) list(APPEND ${HDRS_LIST_NAME} ${PROJECT_SOURCE_DIR}/include/cpuinfo_mips.h)
list(APPEND ${SRCS_LIST_NAME} ${PROJECT_SOURCE_DIR}/src/cpuinfo_mips.c)
elseif(PROCESSOR_IS_ARM) elseif(PROCESSOR_IS_ARM)
list(APPEND ${HDRS_LIST_NAME} ${PROJECT_SOURCE_DIR}/include/cpuinfo_arm.h) list(APPEND ${HDRS_LIST_NAME} ${PROJECT_SOURCE_DIR}/include/cpuinfo_arm.h)
list(APPEND ${SRCS_LIST_NAME} ${PROJECT_SOURCE_DIR}/src/cpuinfo_arm.c)
elseif(PROCESSOR_IS_AARCH64) elseif(PROCESSOR_IS_AARCH64)
list(APPEND ${HDRS_LIST_NAME} ${PROJECT_SOURCE_DIR}/include/cpuinfo_aarch64.h) list(APPEND ${HDRS_LIST_NAME} ${PROJECT_SOURCE_DIR}/include/cpuinfo_aarch64.h)
list(APPEND ${SRCS_LIST_NAME} ${PROJECT_SOURCE_DIR}/src/cpuinfo_aarch64.c)
elseif(PROCESSOR_IS_X86) elseif(PROCESSOR_IS_X86)
list(APPEND ${HDRS_LIST_NAME} ${PROJECT_SOURCE_DIR}/include/cpuinfo_x86.h) list(APPEND ${HDRS_LIST_NAME} ${PROJECT_SOURCE_DIR}/include/cpuinfo_x86.h)
list(APPEND ${SRCS_LIST_NAME} ${PROJECT_SOURCE_DIR}/include/internal/cpuid_x86.h) list(APPEND ${SRCS_LIST_NAME} ${PROJECT_SOURCE_DIR}/include/internal/cpuid_x86.h)
list(APPEND ${SRCS_LIST_NAME} ${PROJECT_SOURCE_DIR}/src/cpuinfo_x86.c)
elseif(PROCESSOR_IS_POWER) elseif(PROCESSOR_IS_POWER)
list(APPEND ${HDRS_LIST_NAME} ${PROJECT_SOURCE_DIR}/include/cpuinfo_ppc.h) list(APPEND ${HDRS_LIST_NAME} ${PROJECT_SOURCE_DIR}/include/cpuinfo_ppc.h)
list(APPEND ${SRCS_LIST_NAME} ${PROJECT_SOURCE_DIR}/src/cpuinfo_ppc.c)
else() else()
message(FATAL_ERROR "Unsupported architectures ${CMAKE_SYSTEM_PROCESSOR}") message(FATAL_ERROR "Unsupported architectures ${CMAKE_SYSTEM_PROCESSOR}")
endif() endif()
@ -147,8 +141,10 @@ target_link_libraries(cpu_features PUBLIC ${CMAKE_DL_LIBS})
target_include_directories(cpu_features target_include_directories(cpu_features
PUBLIC $<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}/cpu_features> PUBLIC $<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}/cpu_features>
) )
if(APPLE AND (PROCESSOR_IS_X86 OR PROCESSOR_IS_AARCH64)) if(PROCESSOR_IS_X86)
target_compile_definitions(cpu_features PRIVATE HAVE_SYSCTLBYNAME) if(APPLE)
target_compile_definitions(cpu_features PRIVATE HAVE_SYSCTLBYNAME)
endif()
endif() endif()
add_library(CpuFeature::cpu_features ALIAS cpu_features) add_library(CpuFeature::cpu_features ALIAS cpu_features)

View File

@ -1,4 +1,4 @@
# CMake build instructions #CMake build instructions
<!-- prettier-ignore-start --> <!-- prettier-ignore-start -->
[comment]: # ( [comment]: # (
@ -29,11 +29,11 @@ cpu_features directly and use the `cpu_features` target in your project.
3- Add the `cpu_features` target to the `target_link_libraries()` section of 3- Add the `cpu_features` target to the `target_link_libraries()` section of
your executable or of your library. your executable or of your library.
## Enabling tests ## Disabling tests
CMake default options for cpu_features is Release built type with tests CMake default options for cpu_features is `Release` built type with tests
disabled. To enable testing set cmake `BUILD_TESTING` variable to `ON`, enabled. To disable testing set cmake `BUILD_TESTING` variable to `OFF`. e.g.
[.travis.yml](https://github.com/google/cpu_features/blob/master/.travis.yml)
and ```sh
[appveyor.yml](https://github.com/google/cpu_features/blob/master/appveyor.yml) cmake -S. -Bbuild -DBUILD_TESTING=OFF
have up to date examples. ```

View File

@ -8,7 +8,7 @@ project(googletest-download NONE)
include(ExternalProject) include(ExternalProject)
ExternalProject_Add(googletest ExternalProject_Add(googletest
GIT_REPOSITORY https://github.com/google/googletest.git GIT_REPOSITORY https://github.com/google/googletest.git
GIT_TAG master GIT_TAG main
SOURCE_DIR "${CMAKE_BINARY_DIR}/googletest-src" SOURCE_DIR "${CMAKE_BINARY_DIR}/googletest-src"
BINARY_DIR "${CMAKE_BINARY_DIR}/googletest-build" BINARY_DIR "${CMAKE_BINARY_DIR}/googletest-build"
CONFIGURE_COMMAND "" CONFIGURE_COMMAND ""

View File

@ -1,7 +1,6 @@
// SPDX-FileCopyrightText: 2017 Google LLC // SPDX-FileCopyrightText: 2017 Google LLC
// SPDX-License-Identifier: Apache-2.0 // SPDX-License-Identifier: Apache-2.0
#ifndef CPU_FEATURES_INCLUDE_CPU_FEATURES_MACROS_H_ #ifndef CPU_FEATURES_INCLUDE_CPU_FEATURES_MACROS_H_
#define CPU_FEATURES_INCLUDE_CPU_FEATURES_MACROS_H_ #define CPU_FEATURES_INCLUDE_CPU_FEATURES_MACROS_H_
@ -29,7 +28,7 @@
#define CPU_FEATURES_ARCH_ARM #define CPU_FEATURES_ARCH_ARM
#endif #endif
#if (defined(__aarch64__) || (defined(__APPLE__) && defined(__arm64__))) #if defined(__aarch64__)
#define CPU_FEATURES_ARCH_AARCH64 #define CPU_FEATURES_ARCH_AARCH64
#endif #endif
@ -57,24 +56,33 @@
// Os // Os
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
#if defined(__linux__) #if (defined(__freebsd__) || defined(__FreeBSD__))
#define CPU_FEATURES_OS_LINUX_OR_ANDROID #define CPU_FEATURES_OS_FREEBSD
#endif #endif
#if defined(__ANDROID__) #if defined(__ANDROID__)
#define CPU_FEATURES_OS_ANDROID #define CPU_FEATURES_OS_ANDROID
#endif #endif
#if defined(__linux__) && !defined(CPU_FEATURES_OS_FREEBSD) && \
!defined(CPU_FEATURES_OS_ANDROID)
#define CPU_FEATURES_OS_LINUX
#endif
#if (defined(_WIN64) || defined(_WIN32)) #if (defined(_WIN64) || defined(_WIN32))
#define CPU_FEATURES_OS_WINDOWS #define CPU_FEATURES_OS_WINDOWS
#endif #endif
#if (defined(__apple__) || defined(__APPLE__) || defined(__MACH__)) #if (defined(__apple__) || defined(__APPLE__) || defined(__MACH__))
#define CPU_FEATURES_OS_DARWIN // From https://stackoverflow.com/a/49560690
#include "TargetConditionals.h"
#if defined(TARGET_OS_OSX)
#define CPU_FEATURES_OS_MACOS
#endif
#if defined(TARGET_OS_IPHONE)
// This is set for any non-Mac Apple products (IOS, TV, WATCH)
#define CPU_FEATURES_OS_IPHONE
#endif #endif
#if (defined(__freebsd__) || defined(__FreeBSD__))
#define CPU_FEATURES_OS_FREEBSD
#endif #endif
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////

View File

@ -1,7 +1,6 @@
// SPDX-FileCopyrightText: 2017 Google LLC // SPDX-FileCopyrightText: 2017 Google LLC
// SPDX-License-Identifier: Apache-2.0 // SPDX-License-Identifier: Apache-2.0
#ifndef CPU_FEATURES_INCLUDE_CPUINFO_AARCH64_H_ #ifndef CPU_FEATURES_INCLUDE_CPUINFO_AARCH64_H_
#define CPU_FEATURES_INCLUDE_CPUINFO_AARCH64_H_ #define CPU_FEATURES_INCLUDE_CPUINFO_AARCH64_H_

View File

@ -1,7 +1,6 @@
// SPDX-FileCopyrightText: 2017 Google LLC // SPDX-FileCopyrightText: 2017 Google LLC
// SPDX-License-Identifier: Apache-2.0 // SPDX-License-Identifier: Apache-2.0
#ifndef CPU_FEATURES_INCLUDE_CPUINFO_ARM_H_ #ifndef CPU_FEATURES_INCLUDE_CPUINFO_ARM_H_
#define CPU_FEATURES_INCLUDE_CPUINFO_ARM_H_ #define CPU_FEATURES_INCLUDE_CPUINFO_ARM_H_

View File

@ -1,7 +1,6 @@
// SPDX-FileCopyrightText: 2017 Google LLC // SPDX-FileCopyrightText: 2017 Google LLC
// SPDX-License-Identifier: Apache-2.0 // SPDX-License-Identifier: Apache-2.0
#ifndef CPU_FEATURES_INCLUDE_CPUINFO_MIPS_H_ #ifndef CPU_FEATURES_INCLUDE_CPUINFO_MIPS_H_
#define CPU_FEATURES_INCLUDE_CPUINFO_MIPS_H_ #define CPU_FEATURES_INCLUDE_CPUINFO_MIPS_H_

View File

@ -1,7 +1,6 @@
// SPDX-FileCopyrightText: 2017 Google LLC // SPDX-FileCopyrightText: 2017 Google LLC
// SPDX-License-Identifier: Apache-2.0 // SPDX-License-Identifier: Apache-2.0
#ifndef CPU_FEATURES_INCLUDE_CPUINFO_PPC_H_ #ifndef CPU_FEATURES_INCLUDE_CPUINFO_PPC_H_
#define CPU_FEATURES_INCLUDE_CPUINFO_PPC_H_ #define CPU_FEATURES_INCLUDE_CPUINFO_PPC_H_
@ -62,7 +61,6 @@ typedef struct
PPCFeatures features; PPCFeatures features;
} PPCInfo; } PPCInfo;
// This function is guaranteed to be malloc, memset and memcpy free.
PPCInfo GetPPCInfo(void); PPCInfo GetPPCInfo(void);
typedef struct typedef struct
@ -113,7 +111,7 @@ typedef enum
PPC_ARCH_2_06, /* ISA 2.06 - POWER7 */ PPC_ARCH_2_06, /* ISA 2.06 - POWER7 */
PPC_HAS_VSX, /* Vector-scalar extension */ PPC_HAS_VSX, /* Vector-scalar extension */
PPC_PSERIES_PERFMON_COMPAT, /* Set of backwards compatibile performance PPC_PSERIES_PERFMON_COMPAT, /* Set of backwards compatibile performance
monitoring events */ monitoring events */
PPC_TRUE_LE, PPC_TRUE_LE,
PPC_PPC_LE, PPC_PPC_LE,
PPC_ARCH_2_07, /* ISA 2.07 - POWER8 */ PPC_ARCH_2_07, /* ISA 2.07 - POWER8 */

View File

@ -1,7 +1,6 @@
// SPDX-FileCopyrightText: 2017 Google LLC // SPDX-FileCopyrightText: 2017 Google LLC
// SPDX-License-Identifier: Apache-2.0 // SPDX-License-Identifier: Apache-2.0
#ifndef CPU_FEATURES_INCLUDE_CPUINFO_X86_H_ #ifndef CPU_FEATURES_INCLUDE_CPUINFO_X86_H_
#define CPU_FEATURES_INCLUDE_CPUINFO_X86_H_ #define CPU_FEATURES_INCLUDE_CPUINFO_X86_H_
@ -98,18 +97,19 @@ typedef struct
} X86Info; } X86Info;
// Calls cpuid and returns an initialized X86info. // Calls cpuid and returns an initialized X86info.
// This function is guaranteed to be malloc, memset and memcpy free.
X86Info GetX86Info(void); X86Info GetX86Info(void);
// Returns cache hierarchy informations. // Returns cache hierarchy informations.
// Can call cpuid multiple times. // Can call cpuid multiple times.
// Only works on Intel CPU at the moment. // Only works on Intel CPU at the moment.
// This function is guaranteed to be malloc, memset and memcpy free.
CacheInfo GetX86CacheInfo(void); CacheInfo GetX86CacheInfo(void);
typedef enum typedef enum
{ {
X86_UNKNOWN, X86_UNKNOWN,
INTEL_80486, // 80486
INTEL_P5, // P5
INTEL_LAKEMONT, // LAKEMONT
INTEL_CORE, // CORE INTEL_CORE, // CORE
INTEL_PNR, // PENRYN INTEL_PNR, // PENRYN
INTEL_NHM, // NEHALEM INTEL_NHM, // NEHALEM
@ -129,6 +129,13 @@ typedef enum
INTEL_ICL, // ICE LAKE INTEL_ICL, // ICE LAKE
INTEL_TGL, // TIGER LAKE INTEL_TGL, // TIGER LAKE
INTEL_SPR, // SAPPHIRE RAPIDS INTEL_SPR, // SAPPHIRE RAPIDS
INTEL_ADL, // ALDER LAKE
INTEL_RCL, // ROCKET LAKE
INTEL_KNIGHTS_M, // KNIGHTS MILL
INTEL_KNIGHTS_L, // KNIGHTS LANDING
INTEL_KNIGHTS_F, // KNIGHTS FERRY
INTEL_KNIGHTS_C, // KNIGHTS CORNER
INTEL_NETBURST, // NETBURST
AMD_HAMMER, // K8 HAMMER AMD_HAMMER, // K8 HAMMER
AMD_K10, // K10 AMD_K10, // K10
AMD_K11, // K11 AMD_K11, // K11
@ -144,6 +151,7 @@ typedef enum
AMD_ZEN_PLUS, // K17 ZEN+ AMD_ZEN_PLUS, // K17 ZEN+
AMD_ZEN2, // K17 ZEN 2 AMD_ZEN2, // K17 ZEN 2
AMD_ZEN3, // K19 ZEN 3 AMD_ZEN3, // K19 ZEN 3
X86_MICROARCHITECTURE_LAST_,
} X86Microarchitecture; } X86Microarchitecture;
// Returns the underlying microarchitecture by looking at X86Info's vendor, // Returns the underlying microarchitecture by looking at X86Info's vendor,
@ -153,7 +161,6 @@ X86Microarchitecture GetX86Microarchitecture(const X86Info* info);
// Calls cpuid and fills the brand_string. // Calls cpuid and fills the brand_string.
// - brand_string *must* be of size 49 (beware of array decaying). // - brand_string *must* be of size 49 (beware of array decaying).
// - brand_string will be zero terminated. // - brand_string will be zero terminated.
// - This function calls memcpy.
void FillX86BrandString(char brand_string[49]); void FillX86BrandString(char brand_string[49]);
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
@ -237,4 +244,4 @@ CPU_FEATURES_END_CPP_NAMESPACE
#error "Including cpuinfo_x86.h from a non-x86 target." #error "Including cpuinfo_x86.h from a non-x86 target."
#endif #endif
#endif // CPU_FEATURES_INCLUDE_CPUINFO_X86_H #endif // CPU_FEATURES_INCLUDE_CPUINFO_X86_H_

View File

@ -1,7 +1,6 @@
// SPDX-FileCopyrightText: 2017 Google LLC // SPDX-FileCopyrightText: 2017 Google LLC
// SPDX-License-Identifier: Apache-2.0 // SPDX-License-Identifier: Apache-2.0
#ifndef CPU_FEATURES_INCLUDE_INTERNAL_BIT_UTILS_H_ #ifndef CPU_FEATURES_INCLUDE_INTERNAL_BIT_UTILS_H_
#define CPU_FEATURES_INCLUDE_INTERNAL_BIT_UTILS_H_ #define CPU_FEATURES_INCLUDE_INTERNAL_BIT_UTILS_H_

View File

@ -1,7 +1,6 @@
// SPDX-FileCopyrightText: 2017 Google LLC // SPDX-FileCopyrightText: 2017 Google LLC
// SPDX-License-Identifier: Apache-2.0 // SPDX-License-Identifier: Apache-2.0
#ifndef CPU_FEATURES_INCLUDE_INTERNAL_CPUID_X86_H_ #ifndef CPU_FEATURES_INCLUDE_INTERNAL_CPUID_X86_H_
#define CPU_FEATURES_INCLUDE_INTERNAL_CPUID_X86_H_ #define CPU_FEATURES_INCLUDE_INTERNAL_CPUID_X86_H_

View File

@ -1,7 +1,6 @@
// SPDX-FileCopyrightText: 2017 Google LLC // SPDX-FileCopyrightText: 2017 Google LLC
// SPDX-License-Identifier: Apache-2.0 // SPDX-License-Identifier: Apache-2.0
// An interface for the filesystem that allows mocking the filesystem in // An interface for the filesystem that allows mocking the filesystem in
// unittests. // unittests.
#ifndef CPU_FEATURES_INCLUDE_INTERNAL_FILESYSTEM_H_ #ifndef CPU_FEATURES_INCLUDE_INTERNAL_FILESYSTEM_H_

View File

@ -1,7 +1,6 @@
// SPDX-FileCopyrightText: 2017 Google LLC // SPDX-FileCopyrightText: 2017 Google LLC
// SPDX-License-Identifier: Apache-2.0 // SPDX-License-Identifier: Apache-2.0
// Interface to retrieve hardware capabilities. It relies on Linux's getauxval // Interface to retrieve hardware capabilities. It relies on Linux's getauxval
// or `/proc/self/auxval` under the hood. // or `/proc/self/auxval` under the hood.
#ifndef CPU_FEATURES_INCLUDE_INTERNAL_HWCAPS_H_ #ifndef CPU_FEATURES_INCLUDE_INTERNAL_HWCAPS_H_

View File

@ -1,7 +1,6 @@
// SPDX-FileCopyrightText: 2017 Google LLC // SPDX-FileCopyrightText: 2017 Google LLC
// SPDX-License-Identifier: Apache-2.0 // SPDX-License-Identifier: Apache-2.0
// Reads a file line by line and stores the data on the stack. This allows // Reads a file line by line and stores the data on the stack. This allows
// parsing files in one go without allocating. // parsing files in one go without allocating.
#ifndef CPU_FEATURES_INCLUDE_INTERNAL_STACK_LINE_READER_H_ #ifndef CPU_FEATURES_INCLUDE_INTERNAL_STACK_LINE_READER_H_

View File

@ -1,7 +1,6 @@
// SPDX-FileCopyrightText: 2017 Google LLC // SPDX-FileCopyrightText: 2017 Google LLC
// SPDX-License-Identifier: Apache-2.0 // SPDX-License-Identifier: Apache-2.0
// A view over a piece of string. The view is not 0 terminated. // A view over a piece of string. The view is not 0 terminated.
#ifndef CPU_FEATURES_INCLUDE_INTERNAL_STRING_VIEW_H_ #ifndef CPU_FEATURES_INCLUDE_INTERNAL_STRING_VIEW_H_
#define CPU_FEATURES_INCLUDE_INTERNAL_STRING_VIEW_H_ #define CPU_FEATURES_INCLUDE_INTERNAL_STRING_VIEW_H_

View File

@ -3,210 +3,365 @@
# SPDX-FileCopyrightText: 2017 Google LLC # SPDX-FileCopyrightText: 2017 Google LLC
# SPDX-License-Identifier: Apache-2.0 # SPDX-License-Identifier: Apache-2.0
readonly SCRIPT_FOLDER=$(cd -P -- "$(dirname -- "$0")" && pwd -P) set -eo pipefail
readonly PROJECT_FOLDER="${SCRIPT_FOLDER}/.."
readonly ARCHIVE_FOLDER=~/cpu_features_archives
readonly QEMU_INSTALL=${ARCHIVE_FOLDER}/qemu
readonly DEFAULT_CMAKE_ARGS=" -DCMAKE_BUILD_TYPE=Debug -DBUILD_TESTING=ON"
function extract() { function extract() {
echo "Extracting ${1}..."
case $1 in case $1 in
*.tar.bz2) tar xjf "$1" ;; *.tar.bz2) tar xjf "$1" ;;
*.tar.xz) tar xJf "$1" ;; *.tar.xz) tar xJf "$1" ;;
*.tar.gz) tar xzf "$1" ;; *.tar.gz) tar xzf "$1" ;;
*) *)
echo "don't know how to extract '$1'..." >&2 echo "don't know how to extract '$1'..."
exit 1 exit 1
esac esac
} }
function unpackifnotexists() { function unpack() {
mkdir -p "${ARCHIVE_FOLDER}" mkdir -p "${ARCHIVE_DIR}"
cd "${ARCHIVE_FOLDER}" || exit cd "${ARCHIVE_DIR}" || exit 2
local URL=$1 local -r URL=$1
local RELATIVE_FOLDER=$2 local -r RELATIVE_DIR=$2
local DESTINATION="${ARCHIVE_FOLDER}/${RELATIVE_FOLDER}" local -r DESTINATION="${ARCHIVE_DIR}/${RELATIVE_DIR}"
if [[ ! -d "${DESTINATION}" ]] ; then if [[ ! -d "${DESTINATION}" ]] ; then
local ARCHIVE_NAME=$(echo ${URL} | sed 's/.*\///') echo "Downloading ${URL}..."
test -f "${ARCHIVE_NAME}" || wget -q "${URL}" local -r ARCHIVE_NAME=$(basename "${URL}")
test -f "${ARCHIVE_NAME}" || wget --no-verbose "${URL}"
extract "${ARCHIVE_NAME}" extract "${ARCHIVE_NAME}"
rm -f "${ARCHIVE_NAME}" rm -f "${ARCHIVE_NAME}"
fi fi
} }
function installqemuifneeded() { function install_qemu() {
local VERSION=${QEMU_VERSION:=2.11.1} if [[ "${QEMU_ARCH}" == "DISABLED" ]]; then
local ARCHES=${QEMU_ARCHES:=arm aarch64 i386 x86_64 mips mipsel mips64 mips64el} >&2 echo 'QEMU is disabled !'
local TARGETS=${QEMU_TARGETS:=$(echo "$ARCHES" | sed 's#$# #;s#\([^ ]*\) #\1-linux-user #g')} return 0
fi
local -r QEMU_VERSION=${QEMU_VERSION:=5.2.0}
local -r QEMU_TARGET=${QEMU_ARCH}-linux-user
if echo "${VERSION} ${TARGETS}" | cmp --silent ${QEMU_INSTALL}/.build -; then if echo "${QEMU_VERSION} ${QEMU_TARGET}" | cmp --silent "${QEMU_INSTALL}/.build" -; then
echo "qemu ${VERSION} up to date!" echo "qemu ${QEMU_VERSION} up to date!"
return 0 return 0
fi fi
echo "VERSION: ${VERSION}" echo "QEMU_VERSION: ${QEMU_VERSION}"
echo "TARGETS: ${TARGETS}" echo "QEMU_TARGET: ${QEMU_TARGET}"
rm -rf ${QEMU_INSTALL} rm -rf "${QEMU_INSTALL}"
# Checking for a tarball before downloading makes testing easier :-) # Checking for a tarball before downloading makes testing easier :-)
local QEMU_URL="http://wiki.qemu-project.org/download/qemu-${VERSION}.tar.xz" local -r QEMU_URL="http://wiki.qemu-project.org/download/qemu-${QEMU_VERSION}.tar.xz"
local QEMU_FOLDER="qemu-${VERSION}" local -r QEMU_DIR="qemu-${QEMU_VERSION}"
unpackifnotexists ${QEMU_URL} ${QEMU_FOLDER} unpack ${QEMU_URL} ${QEMU_DIR}
cd ${QEMU_FOLDER} || exit cd ${QEMU_DIR} || exit 2
# Qemu (meson based build) depends on: pkgconf, libglib2.0, python3, ninja
./configure \ ./configure \
--prefix="${QEMU_INSTALL}" \ --prefix="${QEMU_INSTALL}" \
--target-list="${TARGETS}" \ --target-list="${QEMU_TARGET}" \
--disable-docs \ --audio-drv-list= \
--disable-sdl \ --disable-brlapi \
--disable-gtk \ --disable-curl \
--disable-gnutls \
--disable-gcrypt \
--disable-nettle \
--disable-curses \ --disable-curses \
--static --disable-docs \
--disable-gcrypt \
--disable-gnutls \
--disable-gtk \
--disable-libnfs \
--disable-libssh \
--disable-nettle \
--disable-opengl \
--disable-sdl \
--disable-virglrenderer \
--disable-vte \
--enable-modules
make -j4 # --static Not supported on Archlinux
# so we use --enable-modules
# wrapper on ninja
make -j8
make install make install
echo "$VERSION $TARGETS" > ${QEMU_INSTALL}/.build echo "$QEMU_VERSION $QEMU_TARGET" > "${QEMU_INSTALL}/.build"
} }
function assert_defined(){ function assert_defined(){
local VALUE=${1} if [[ -z "${!1}" ]]; then
: "${VALUE?"${1} needs to be defined"}" >&2 echo "Variable '${1}' must be defined"
exit 1
fi
} }
function integrate() { function clean_build() {
cd "${PROJECT_FOLDER}" # Cleanup previous build
case "${OS}" in rm -rf "${BUILD_DIR}"
"Windows_NT") CMAKE_BUILD_ARGS="--config Debug --target ALL_BUILD" mkdir -p "${BUILD_DIR}"
CMAKE_TEST_FILES="${BUILD_DIR}/test/Debug/*_test.exe"
DEMO=${BUILD_DIR}/Debug/list_cpu_features.exe
;;
*) CMAKE_BUILD_ARGS="--target all"
CMAKE_TEST_FILES="${BUILD_DIR}/test/*_test"
DEMO=${BUILD_DIR}/list_cpu_features
;;
esac
# Generating CMake configuration
cmake -H. -B"${BUILD_DIR}" ${DEFAULT_CMAKE_ARGS} "${CMAKE_ADDITIONAL_ARGS[@]}" -G"${CMAKE_GENERATOR:-Unix Makefiles}"
# Building
cmake --build "${BUILD_DIR}" ${CMAKE_BUILD_ARGS}
# Running tests if needed
if [[ "${QEMU_ARCH}" == "DISABLED" ]]; then
return
fi
RUN_CMD=""
if [[ -n "${QEMU_ARCH}" ]]; then
installqemuifneeded
RUN_CMD="${QEMU_INSTALL}/bin/qemu-${QEMU_ARCH} ${QEMU_ARGS[@]}"
fi
for test_binary in ${CMAKE_TEST_FILES}; do
${RUN_CMD} ${test_binary}
done
${RUN_CMD} ${DEMO}
} }
function expand_linaro_config() { function expand_linaro_config() {
assert_defined TARGET #ref: https://releases.linaro.org/components/toolchain/binaries/
local LINARO_ROOT_URL=https://releases.linaro.org/components/toolchain/binaries/7.2-2017.11 local -r LINARO_VERSION=7.5-2019.12
local -r LINARO_ROOT_URL=https://releases.linaro.org/components/toolchain/binaries/${LINARO_VERSION}
local GCC_URL=${LINARO_ROOT_URL}/${TARGET}/gcc-linaro-7.2.1-2017.11-x86_64_${TARGET}.tar.xz local -r GCC_VERSION=7.5.0-2019.12
local GCC_RELATIVE_FOLDER="gcc-linaro-7.2.1-2017.11-x86_64_${TARGET}" local -r GCC_URL=${LINARO_ROOT_URL}/${TARGET}/gcc-linaro-${GCC_VERSION}-x86_64_${TARGET}.tar.xz
unpackifnotexists "${GCC_URL}" "${GCC_RELATIVE_FOLDER}" local -r GCC_RELATIVE_DIR="gcc-linaro-${GCC_VERSION}-x86_64_${TARGET}"
unpack "${GCC_URL}" "${GCC_RELATIVE_DIR}"
local SYSROOT_URL=${LINARO_ROOT_URL}/${TARGET}/sysroot-glibc-linaro-2.25-2017.11-${TARGET}.tar.xz local -r SYSROOT_VERSION=2.25-2019.12
local SYSROOT_RELATIVE_FOLDER=sysroot-glibc-linaro-2.25-2017.11-${TARGET} local -r SYSROOT_URL=${LINARO_ROOT_URL}/${TARGET}/sysroot-glibc-linaro-${SYSROOT_VERSION}-${TARGET}.tar.xz
unpackifnotexists "${SYSROOT_URL}" "${SYSROOT_RELATIVE_FOLDER}" local -r SYSROOT_RELATIVE_DIR=sysroot-glibc-linaro-${SYSROOT_VERSION}-${TARGET}
unpack "${SYSROOT_URL}" "${SYSROOT_RELATIVE_DIR}"
local SYSROOT_FOLDER=${ARCHIVE_FOLDER}/${SYSROOT_RELATIVE_FOLDER} local -r SYSROOT_DIR=${ARCHIVE_DIR}/${SYSROOT_RELATIVE_DIR}
local GCC_FOLDER=${ARCHIVE_FOLDER}/${GCC_RELATIVE_FOLDER} local -r STAGING_DIR=${ARCHIVE_DIR}/${SYSROOT_RELATIVE_DIR}-stage
local -r GCC_DIR=${ARCHIVE_DIR}/${GCC_RELATIVE_DIR}
CMAKE_ADDITIONAL_ARGS+=(-DCMAKE_SYSTEM_NAME=Linux) # Write a Toolchain file
CMAKE_ADDITIONAL_ARGS+=(-DCMAKE_SYSTEM_PROCESSOR=${TARGET}) # note: This is manadatory to use a file in order to have the CMake variable
# 'CMAKE_CROSSCOMPILING' set to TRUE.
# ref: https://cmake.org/cmake/help/latest/manual/cmake-toolchains.7.html#cross-compiling-for-linux
cat >"$TOOLCHAIN_FILE" <<EOL
set(CMAKE_SYSTEM_NAME Linux)
set(CMAKE_SYSTEM_PROCESSOR ${TARGET})
CMAKE_ADDITIONAL_ARGS+=(-DCMAKE_SYSROOT=${SYSROOT_FOLDER}) set(CMAKE_SYSROOT ${SYSROOT_DIR})
CMAKE_ADDITIONAL_ARGS+=(-DCMAKE_C_COMPILER=${GCC_FOLDER}/bin/${TARGET}-gcc) set(CMAKE_STAGING_PREFIX ${STAGING_DIR})
CMAKE_ADDITIONAL_ARGS+=(-DCMAKE_CXX_COMPILER=${GCC_FOLDER}/bin/${TARGET}-g++)
CMAKE_ADDITIONAL_ARGS+=(-DCMAKE_FIND_ROOT_PATH_MODE_PROGRAM=NEVER) set(tools ${GCC_DIR})
CMAKE_ADDITIONAL_ARGS+=(-DCMAKE_FIND_ROOT_PATH_MODE_INCLUDE=ONLY) set(CMAKE_C_COMPILER \${tools}/bin/${TARGET}-gcc)
CMAKE_ADDITIONAL_ARGS+=(-DCMAKE_FIND_ROOT_PATH_MODE_PACKAGE=ONLY) set(CMAKE_CXX_COMPILER \${tools}/bin/${TARGET}-g++)
QEMU_ARGS+=(-L ${SYSROOT_FOLDER}) set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
QEMU_ARGS+=(-E LD_LIBRARY_PATH=/lib) set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY)
EOL
CMAKE_ADDITIONAL_ARGS+=( -DCMAKE_TOOLCHAIN_FILE="${TOOLCHAIN_FILE}" )
QEMU_ARGS+=( -L "${SYSROOT_DIR}" )
QEMU_ARGS+=( -E LD_LIBRARY_PATH=/lib )
} }
function expand_codescape_config() { function expand_codescape_config() {
assert_defined TARGET # ref: https://codescape.mips.com/components/toolchain/2020.06-01/downloads.html
local DATE=2017.10-08 # ref: https://codescape.mips.com/components/toolchain/2019.02-04/downloads.html
local CODESCAPE_URL=https://codescape.mips.com/components/toolchain/${DATE}/Codescape.GNU.Tools.Package.${DATE}.for.MIPS.MTI.Linux.CentOS-5.x86_64.tar.gz local -r DATE=2020.06-01
local GCC_URL=${CODESCAPE_URL} #local -r DATE=2019.02-04
local GCC_RELATIVE_FOLDER="mips-mti-linux-gnu/${DATE}" local -r CODESCAPE_URL=https://codescape.mips.com/components/toolchain/${DATE}/Codescape.GNU.Tools.Package.${DATE}.for.MIPS.MTI.Linux.CentOS-6.x86_64.tar.gz
unpackifnotexists "${GCC_URL}" "${GCC_RELATIVE_FOLDER}" #local -r CODESCAPE_URL=https://codescape.mips.com/components/toolchain/${DATE}/Codescape.GNU.Tools.Package.${DATE}.for.MIPS.IMG.Linux.CentOS-6.x86_64.tar.gz
local -r GCC_URL=${CODESCAPE_URL}
local -r GCC_RELATIVE_DIR="mips-mti-linux-gnu/${DATE}"
#local -r GCC_RELATIVE_DIR="mips-img-linux-gnu/${DATE}"
unpack "${GCC_URL}" "${GCC_RELATIVE_DIR}"
local GCC_FOLDER=${ARCHIVE_FOLDER}/${GCC_RELATIVE_FOLDER} local -r GCC_DIR=${ARCHIVE_DIR}/${GCC_RELATIVE_DIR}
local MIPS_FLAGS="" local MIPS_FLAGS=""
local LIBC_FOLDER_SUFFIX="" local LIBC_DIR_SUFFIX=""
local FLAVOUR="" local FLAVOUR=""
case "${TARGET}" in case "${TARGET}" in
"mips32") MIPS_FLAGS="-EB -mabi=32"; FLAVOUR="mips-r2-hard"; LIBC_FOLDER_SUFFIX="lib" ;; "mips32")
"mips32el") MIPS_FLAGS="-EL -mabi=32"; FLAVOUR="mipsel-r2-hard"; LIBC_FOLDER_SUFFIX="lib" ;; MIPS_FLAGS="-EB -mips32r6 -mabi=32"
"mips64") MIPS_FLAGS="-EB -mabi=64"; FLAVOUR="mips-r2-hard"; LIBC_FOLDER_SUFFIX="lib64" ;; FLAVOUR="mips-r6-hard"
"mips64el") MIPS_FLAGS="-EL -mabi=64"; FLAVOUR="mipsel-r2-hard"; LIBC_FOLDER_SUFFIX="lib64" ;; #MIPS_FLAGS="-EB -mips32r2 -mabi=32"
*) echo 'unknown mips platform'; exit 1;; #FLAVOUR="mips-r2-hard"
LIBC_DIR_SUFFIX="lib"
;;
"mips32el")
MIPS_FLAGS="-EL -mips32r6 -mabi=32"
FLAVOUR="mipsel-r6-hard"
#MIPS_FLAGS="-EL -mips32r2 -mabi=32"
#FLAVOUR="mipsel-r2-hard"
LIBC_DIR_SUFFIX="lib"
;;
"mips64")
MIPS_FLAGS="-EB -mips64r6 -mabi=64"
FLAVOUR="mips-r6-hard"
#FLAVOUR="mips-r2-hard"
LIBC_DIR_SUFFIX="lib64"
;;
"mips64el")
MIPS_FLAGS="-EL -mips64r6 -mabi=64"
FLAVOUR="mipsel-r6-hard"
#FLAVOUR="mipsel-r2-hard"
LIBC_DIR_SUFFIX="lib64"
;;
*)
>&2 echo 'unknown mips platform'
exit 1 ;;
esac esac
local -r SYSROOT_DIR=${GCC_DIR}/sysroot
local -r STAGING_DIR=${SYSROOT_DIR}-stage
CMAKE_ADDITIONAL_ARGS+=(-DCMAKE_FIND_ROOT_PATH=${GCC_FOLDER}) # Write a Toolchain file
CMAKE_ADDITIONAL_ARGS+=(-DCMAKE_SYSTEM_NAME=Linux) # note: This is manadatory to use a file in order to have the CMake variable
CMAKE_ADDITIONAL_ARGS+=(-DCMAKE_SYSTEM_PROCESSOR=${TARGET}) # 'CMAKE_CROSSCOMPILING' set to TRUE.
CMAKE_ADDITIONAL_ARGS+=(-DCMAKE_C_COMPILER=mips-mti-linux-gnu-gcc) # ref: https://cmake.org/cmake/help/latest/manual/cmake-toolchains.7.html#cross-compiling-for-linux
CMAKE_ADDITIONAL_ARGS+=(-DCMAKE_CXX_COMPILER=mips-mti-linux-gnu-g++) cat >"${TOOLCHAIN_FILE}" <<EOL
CMAKE_ADDITIONAL_ARGS+=(-DCMAKE_C_COMPILER_ARG1="${MIPS_FLAGS}") set(CMAKE_SYSTEM_NAME Linux)
CMAKE_ADDITIONAL_ARGS+=(-DCMAKE_CXX_COMPILER_ARG1="${MIPS_FLAGS}") set(CMAKE_SYSTEM_PROCESSOR ${TARGET})
local SYSROOT_FOLDER=${GCC_FOLDER}/sysroot/${FLAVOUR} set(CMAKE_SYSROOT ${SYSROOT_DIR})
set(CMAKE_STAGING_PREFIX ${STAGING_DIR})
# Keeping only the sysroot of interest to save on travis cache. set(tools ${GCC_DIR})
if [[ "${CONTINUOUS_INTEGRATION}" = "true" ]]; then
for folder in ${GCC_FOLDER}/sysroot/*; do
if [[ "${folder}" != "${SYSROOT_FOLDER}" ]]; then
rm -rf ${folder}
fi
done
fi
local LIBC_FOLDER=${GCC_FOLDER}/mips-mti-linux-gnu/lib/${FLAVOUR}/${LIBC_FOLDER_SUFFIX} set(CMAKE_C_COMPILER \${tools}/bin/mips-mti-linux-gnu-gcc)
QEMU_ARGS+=(-L ${SYSROOT_FOLDER}) #set(CMAKE_C_COMPILER \${tools}/bin/mips-img-linux-gnu-gcc)
QEMU_ARGS+=(-E LD_PRELOAD=${LIBC_FOLDER}/libstdc++.so.6:${LIBC_FOLDER}/libgcc_s.so.1) set(CMAKE_C_FLAGS "${MIPS_FLAGS}")
set(CMAKE_CXX_COMPILER \${tools}/bin/mips-mti-linux-gnu-g++)
#set(CMAKE_CXX_COMPILER \${tools}/bin/mips-img-linux-gnu-g++)
set(CMAKE_CXX_FLAGS "${MIPS_FLAGS}")
set(CMAKE_FIND_ROOT_PATH ${GCC_DIR})
set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY)
EOL
CMAKE_ADDITIONAL_ARGS+=( -DCMAKE_TOOLCHAIN_FILE="${TOOLCHAIN_FILE}" )
QEMU_ARGS+=( -L "${SYSROOT_DIR}/${FLAVOUR}" )
local -r LIBC_DIR=${GCC_DIR}/mips-mti-linux-gnu/lib/${FLAVOUR}/${LIBC_DIR_SUFFIX}
#local -r LIBC_DIR=${GCC_DIR}/mips-img-linux-gnu/lib/${FLAVOUR}/${LIBC_DIR_SUFFIX}
QEMU_ARGS+=( -E LD_PRELOAD="${LIBC_DIR}/libstdc++.so.6:${LIBC_DIR}/libgcc_s.so.1" )
} }
function expand_environment_and_integrate() { function build() {
assert_defined PROJECT_FOLDER cd "${PROJECT_DIR}" || exit 2
set -x
clean_build
cmake -S. -B"${BUILD_DIR}" "${CMAKE_DEFAULT_ARGS[@]}" "${CMAKE_ADDITIONAL_ARGS[@]}"
cmake --build "${BUILD_DIR}" --target all -j8 -v
set +x
}
function run_test() {
assert_defined QEMU_ARCH
if [[ "${QEMU_ARCH}" == "DISABLED" ]]; then
>&2 echo "QEMU is disabled for ${TARGET}"
return
fi
install_qemu
RUN_CMD="${QEMU_INSTALL}/bin/qemu-${QEMU_ARCH} ${QEMU_ARGS[*]}"
cd "${BUILD_DIR}" || exit 2
set -x
for test_binary in "${BUILD_DIR}"/list_cpu_feature* ; do
${RUN_CMD} "${test_binary}"
done
set +x
}
function usage() {
local -r NAME=$(basename "$0")
echo -e "$NAME - Build using a cross toolchain.
SYNOPSIS
\t$NAME [-h|--help] [toolchain|build|qemu|test|all]
DESCRIPTION
\tCross compile using a cross toolchain.
\tYou MUST define the following variables before running this script:
\t* TARGET:
\t\tx86_64
\t\taarch64-linux-gnu aarch64_be-linux-gnu
\t\tarm-linux-gnueabihf armv8l-linux-gnueabihf arm-linux-gnueabi
\t\tarmeb-linux-gnueabihf armeb-linux-gnueabi
\t\tmips32 mips32el
\t\tmips64 mips64el
OPTIONS
\t-h --help: show this help text
\ttoolchain: download, unpack toolchain and generate CMake toolchain file
\tbuild: toolchain + build the project using the toolchain file (note: remove previous build dir)
\tqemu: download, unpack and build qemu
\ttest: qemu + run all executable using qemu (note: don't build !)
\tall: build + test (default)
EXAMPLES
* Using export:
export TARGET=aarch64-linux-gnu
$0
* One-liner:
TARGET=aarch64-linux-gnu $0"
}
# Main
function main() {
case ${1} in
-h | --help)
usage; exit ;;
esac
assert_defined TARGET assert_defined TARGET
BUILD_DIR="${PROJECT_FOLDER}/cmake_build/${TARGET}" declare -r PROJECT_DIR="$(cd -P -- "$(dirname -- "$0")/.." && pwd -P)"
mkdir -p "${BUILD_DIR}" declare -r ARCHIVE_DIR="${PROJECT_DIR}/build_cross/archives"
declare -r BUILD_DIR="${PROJECT_DIR}/build_cross/${TARGET}"
declare -r TOOLCHAIN_FILE=${ARCHIVE_DIR}/toolchain_${TARGET}.cmake
declare -a CONFIG_NAMES=() echo "Target: '${TARGET}'"
declare -a QEMU_ARGS=()
echo "Project dir: '${PROJECT_DIR}'"
echo "Archive dir: '${ARCHIVE_DIR}'"
echo "Build dir: '${BUILD_DIR}'"
echo "toolchain file: '${TOOLCHAIN_FILE}'"
declare -a CMAKE_DEFAULT_ARGS=( -G ${CMAKE_GENERATOR:-"Ninja"} )
declare -a CMAKE_ADDITIONAL_ARGS=() declare -a CMAKE_ADDITIONAL_ARGS=()
case ${TOOLCHAIN} in declare -a QEMU_ARGS=()
LINARO) expand_linaro_config ;; case ${TARGET} in
CODESCAPE) expand_codescape_config ;; x86_64)
NATIVE) QEMU_ARCH="" ;; declare -r QEMU_ARCH=x86_64 ;;
*) echo "Unknown toolchain '${TOOLCHAIN}'..."; exit 1;; arm-linux-gnueabihf | armv8l-linux-gnueabihf | arm-linux-gnueabi)
expand_linaro_config
declare -r QEMU_ARCH=arm ;;
armeb-linux-gnueabihf | armeb-linux-gnueabi)
expand_linaro_config
declare -r QEMU_ARCH=DISABLED ;;
aarch64-linux-gnu)
expand_linaro_config
declare -r QEMU_ARCH=aarch64 ;;
aarch64_be-linux-gnu)
expand_linaro_config
declare -r QEMU_ARCH=DISABLED ;;
mips32)
expand_codescape_config
declare -r QEMU_ARCH=mips ;;
mips32el)
expand_codescape_config
declare -r QEMU_ARCH=mipsel ;;
mips64)
expand_codescape_config
declare -r QEMU_ARCH=mips64 ;;
mips64el)
expand_codescape_config
declare -r QEMU_ARCH=mips64el ;;
*)
>&2 echo "Unknown TARGET '${TARGET}'..."
exit 1 ;;
esac
declare -r QEMU_INSTALL=${ARCHIVE_DIR}/qemu-${QEMU_ARCH}
case ${1} in
toolchain)
exit ;;
build)
build ;;
qemu)
install_qemu ;;
test)
run_test ;;
*)
build
run_test ;;
esac esac
integrate
} }
if [ "${CONTINUOUS_INTEGRATION}" = "true" ]; then main "${1:-all}"
QEMU_ARCHES=${QEMU_ARCH}
expand_environment_and_integrate
fi

View File

@ -3,85 +3,59 @@
# SPDX-FileCopyrightText: 2017 Google LLC # SPDX-FileCopyrightText: 2017 Google LLC
# SPDX-License-Identifier: Apache-2.0 # SPDX-License-Identifier: Apache-2.0
source "$(dirname -- "$0")"/run_integration.sh
# Toolchains for little-endian, 64-bit ARMv8 for GNU/Linux systems # Toolchains for little-endian, 64-bit ARMv8 for GNU/Linux systems
function set_aarch64-linux-gnu() { function set_aarch64-linux-gnu() {
TOOLCHAIN=LINARO export TARGET=aarch64-linux-gnu
TARGET=aarch64-linux-gnu
QEMU_ARCH=aarch64
} }
# Toolchains for little-endian, hard-float, 32-bit ARMv7 (and earlier) for GNU/Linux systems # Toolchains for little-endian, hard-float, 32-bit ARMv7 (and earlier) for GNU/Linux systems
function set_arm-linux-gnueabihf() { function set_arm-linux-gnueabihf() {
TOOLCHAIN=LINARO export TARGET=arm-linux-gnueabihf
TARGET=arm-linux-gnueabihf
QEMU_ARCH=arm
} }
# Toolchains for little-endian, 32-bit ARMv8 for GNU/Linux systems # Toolchains for little-endian, 32-bit ARMv8 for GNU/Linux systems
function set_armv8l-linux-gnueabihf() { function set_armv8l-linux-gnueabihf() {
TOOLCHAIN=LINARO export TARGET=armv8l-linux-gnueabihf
TARGET=armv8l-linux-gnueabihf
QEMU_ARCH=arm
} }
# Toolchains for little-endian, soft-float, 32-bit ARMv7 (and earlier) for GNU/Linux systems # Toolchains for little-endian, soft-float, 32-bit ARMv7 (and earlier) for GNU/Linux systems
function set_arm-linux-gnueabi() { function set_arm-linux-gnueabi() {
TOOLCHAIN=LINARO export TARGET=arm-linux-gnueabi
TARGET=arm-linux-gnueabi
QEMU_ARCH=arm
} }
# Toolchains for big-endian, 64-bit ARMv8 for GNU/Linux systems # Toolchains for big-endian, 64-bit ARMv8 for GNU/Linux systems
function set_aarch64_be-linux-gnu() { function set_aarch64_be-linux-gnu() {
TOOLCHAIN=LINARO export TARGET=aarch64_be-linux-gnu
TARGET=aarch64_be-linux-gnu
QEMU_ARCH=DISABLED
} }
# Toolchains for big-endian, hard-float, 32-bit ARMv7 (and earlier) for GNU/Linux systems # Toolchains for big-endian, hard-float, 32-bit ARMv7 (and earlier) for GNU/Linux systems
function set_armeb-linux-gnueabihf() { function set_armeb-linux-gnueabihf() {
TOOLCHAIN=LINARO export TARGET=armeb-linux-gnueabihf
TARGET=armeb-linux-gnueabihf
QEMU_ARCH=DISABLED
} }
# Toolchains for big-endian, soft-float, 32-bit ARMv7 (and earlier) for GNU/Linux systems # Toolchains for big-endian, soft-float, 32-bit ARMv7 (and earlier) for GNU/Linux systems
function set_armeb-linux-gnueabi() { function set_armeb-linux-gnueabi() {
TOOLCHAIN=LINARO export TARGET=armeb-linux-gnueabi
TARGET=armeb-linux-gnueabi
QEMU_ARCH=DISABLED
} }
function set_mips32() { function set_mips32() {
TOOLCHAIN=CODESCAPE export TARGET=mips32
TARGET=mips32
QEMU_ARCH=mips
} }
function set_mips32el() { function set_mips32el() {
TOOLCHAIN=CODESCAPE export TARGET=mips32el
TARGET=mips32el
QEMU_ARCH=mipsel
} }
function set_mips64() { function set_mips64() {
TOOLCHAIN=CODESCAPE export TARGET=mips64
TARGET=mips64
QEMU_ARCH=mips64
} }
function set_mips64el() { function set_mips64el() {
TOOLCHAIN=CODESCAPE export TARGET=mips64el
TARGET=mips64el
QEMU_ARCH=mips64el
} }
function set_native() { function set_x86_64() {
TOOLCHAIN=NATIVE export TARGET=x86_64
TARGET=native
QEMU_ARCH=""
} }
ENVIRONMENTS=" ENVIRONMENTS="
@ -96,14 +70,13 @@ ENVIRONMENTS="
set_mips32el set_mips32el
set_mips64 set_mips64
set_mips64el set_mips64el
set_native set_x86_64
" "
set -e set -e
CMAKE_GENERATOR="Ninja"
for SET_ENVIRONMENT in ${ENVIRONMENTS}; do for SET_ENVIRONMENT in ${ENVIRONMENTS}; do
echo "testing ${SET_ENVIRONMENT}"
${SET_ENVIRONMENT} ${SET_ENVIRONMENT}
expand_environment_and_integrate ./"$(dirname -- "$0")"/run_integration.sh
done done

View File

@ -0,0 +1,9 @@
// SPDX-FileCopyrightText: 2021 Google LLC
// SPDX-License-Identifier: Apache-2.0
#include <stddef.h>
static void copy(char *__restrict dst, const char *src, size_t count)
{
for (size_t i = 0; i < count; ++i) dst[i] = src[i];
}

View File

@ -1,210 +0,0 @@
// SPDX-FileCopyrightText: 2017 Google LLC
// SPDX-License-Identifier: Apache-2.0
#include "cpuinfo_aarch64.h"
#include "internal/filesystem.h"
#include "internal/hwcaps.h"
#include "internal/stack_line_reader.h"
#include "internal/string_view.h"
#include <assert.h>
#include <ctype.h>
#if defined(CPU_FEATURES_OS_DARWIN)
#if !defined(HAVE_SYSCTLBYNAME)
#error "Darwin needs support for sysctlbyname"
#endif
#include <sys/sysctl.h>
#if defined(CPU_FEATURES_MOCK_CPUID_ARM64)
extern bool GetDarwinSysCtlByName(const char*);
extern int GetDarwinSysCtlByNameValue(const char*);
#else // CPU_FEATURES_MOCK_CPUID_ARM64
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;
}
static int GetDarwinSysCtlByNameValue(const char* name)
{
int enabled;
size_t enabled_len = sizeof(enabled);
const int failure = sysctlbyname(name, &enabled, &enabled_len, NULL, 0);
return failure ? 0 : enabled;
}
#endif
#endif // CPU_FEATURES_OS_DARWIN
// 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) \
FEATURE(AARCH64_MTE, mte, "mte", 0, AARCH64_HWCAP2_MTE)
#define DEFINE_TABLE_FEATURE_TYPE Aarch64Features
#include "define_tables.h"
#if !defined(CPU_FEATURES_OS_DARWIN)
static bool HandleAarch64Line(const LineResult result,
Aarch64Info* const info)
{
StringView line = result.line;
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], ' '));
}
}
else if (CpuFeatures_StringView_IsEquals(key, str("CPU implementer")))
{
info->implementer = CpuFeatures_StringView_ParsePositiveNumber(value);
}
else if (CpuFeatures_StringView_IsEquals(key, str("CPU variant")))
{
info->variant = CpuFeatures_StringView_ParsePositiveNumber(value);
}
else if (CpuFeatures_StringView_IsEquals(key, str("CPU part")))
{
info->part = CpuFeatures_StringView_ParsePositiveNumber(value);
}
else if (CpuFeatures_StringView_IsEquals(key, str("CPU revision")))
{
info->revision = CpuFeatures_StringView_ParsePositiveNumber(value);
}
}
return !result.eof;
}
static void FillProcCpuInfoData(Aarch64Info* const info)
{
const int fd = CpuFeatures_OpenFile("/proc/cpuinfo");
if (fd >= 0)
{
StackLineReader reader;
StackLineReader_Initialize(&reader, fd);
for (;;)
{
if (!HandleAarch64Line(StackLineReader_NextLine(&reader), info))
{
break;
}
}
CpuFeatures_CloseFile(fd);
}
}
#endif /* !CPU_FEATURES_OS_DARWIN */
static const Aarch64Info kEmptyAarch64Info;
Aarch64Info GetAarch64Info(void)
{
// 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;
#if defined(CPU_FEATURES_OS_DARWIN)
// Handling Darwin platform through sysctlbyname
info.implementer = GetDarwinSysCtlByNameValue("hw.cputype");
info.variant = GetDarwinSysCtlByNameValue("hw.cpusubtype");
info.part = GetDarwinSysCtlByNameValue("hw.cpufamily");
info.revision = GetDarwinSysCtlByNameValue("hw.cpusubfamily");
info.features.fp = GetDarwinSysCtlByName("hw.optional.floatingpoint");
info.features.fphp = GetDarwinSysCtlByName("hw.optional.neon_hpfp");
info.features.sha512 = GetDarwinSysCtlByName("hw.optional.armv8_2_sha512");
info.features.atomics = GetDarwinSysCtlByName("hw.optional.armv8_1_atomics");
info.features.asimdfhm = GetDarwinSysCtlByName("hw.optional.armv8_2_fhm");
info.features.sha3 = GetDarwinSysCtlByName("hw.optional.armv8_2_sha3");
info.features.crc32 = GetDarwinSysCtlByName("hw.optional.armv8_crc32");
#else
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);
}
}
#endif
return info;
}
////////////////////////////////////////////////////////////////////////////////
// Introspection functions
int GetAarch64FeaturesEnumValue(const Aarch64Features* features,
Aarch64FeaturesEnum value)
{
if (value >= AARCH64_LAST_) return false;
return kGetters[value](features);
}
const char* GetAarch64FeaturesEnumName(Aarch64FeaturesEnum value)
{
if (value >= AARCH64_LAST_) return "unknown feature";
return kCpuInfoFlags[value];
}

View File

@ -1,175 +0,0 @@
// SPDX-FileCopyrightText: 2018 IBM.
// SPDX-License-Identifier: Apache-2.0
#include "cpuinfo_ppc.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 <assert.h>
#include <stdbool.h>
#include <string.h>
// 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 bool HandlePPCLine(const LineResult result,
PPCPlatformStrings* const strings)
{
StringView line = result.line;
StringView key, value;
if (CpuFeatures_StringView_GetAttributeKeyValue(line, &key, &value))
{
if (CpuFeatures_StringView_HasWord(key, "platform", ' '))
{
CpuFeatures_StringView_CopyString(value, strings->platform,
sizeof(strings->platform));
}
else if (CpuFeatures_StringView_IsEquals(key, str("model")))
{
CpuFeatures_StringView_CopyString(value, strings->model,
sizeof(strings->platform));
}
else if (CpuFeatures_StringView_IsEquals(key, str("machine")))
{
CpuFeatures_StringView_CopyString(value, strings->machine,
sizeof(strings->platform));
}
else if (CpuFeatures_StringView_IsEquals(key, str("cpu")))
{
CpuFeatures_StringView_CopyString(value, strings->cpu,
sizeof(strings->platform));
}
}
return !result.eof;
}
static void FillProcCpuInfoData(PPCPlatformStrings* const strings)
{
const int fd = CpuFeatures_OpenFile("/proc/cpuinfo");
if (fd >= 0)
{
StackLineReader reader;
StackLineReader_Initialize(&reader, fd);
for (;;)
{
if (!HandlePPCLine(StackLineReader_NextLine(&reader), strings))
{
break;
}
}
CpuFeatures_CloseFile(fd);
}
}
static const PPCInfo kEmptyPPCInfo;
PPCInfo GetPPCInfo(void)
{
/*
* On Power feature flags aren't currently in cpuinfo so we only look at
* 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);
}
}
return info;
}
static const PPCPlatformStrings kEmptyPPCPlatformStrings;
PPCPlatformStrings GetPPCPlatformStrings(void)
{
PPCPlatformStrings strings = kEmptyPPCPlatformStrings;
const char* platform = CpuFeatures_GetPlatformPointer();
const char* base_platform = CpuFeatures_GetBasePlatformPointer();
FillProcCpuInfoData(&strings);
if (platform != NULL)
{
CpuFeatures_StringView_CopyString(str(platform), strings.type.platform,
sizeof(strings.type.platform));
}
if (base_platform != NULL)
{
CpuFeatures_StringView_CopyString(str(base_platform),
strings.type.base_platform,
sizeof(strings.type.base_platform));
}
return strings;
}
////////////////////////////////////////////////////////////////////////////////
// Introspection functions
int GetPPCFeaturesEnumValue(const PPCFeatures* features,
PPCFeaturesEnum value)
{
if (value >= PPC_LAST_) return false;
return kGetters[value](features);
}
const char* GetPPCFeaturesEnumName(PPCFeaturesEnum value)
{
if (value >= PPC_LAST_) return "unknown feature";
return kCpuInfoFlags[value];
}

View File

@ -0,0 +1,79 @@
// SPDX-FileCopyrightText: 2017 Google LLC
// SPDX-License-Identifier: Apache-2.0
#ifndef INTROSPECTION_PREFIX
#error "missing INTROSPECTION_PREFIX"
#endif
#ifndef INTROSPECTION_ENUM_PREFIX
#error "missing INTROSPECTION_ENUM_PREFIX"
#endif
#ifndef INTROSPECTION_TABLE
#error "missing INTROSPECTION_TABLE"
#endif
#include <stdbool.h>
#define STRINGIZE_(s) #s
#define STRINGIZE(s) STRINGIZE_(s)
#define FEAT_TYPE_NAME__(X) X##Features
#define FEAT_TYPE_NAME_(X) FEAT_TYPE_NAME__(X)
#define FEAT_TYPE_NAME FEAT_TYPE_NAME_(INTROSPECTION_PREFIX)
#define FEAT_ENUM_NAME__(X) X##FeaturesEnum
#define FEAT_ENUM_NAME_(X) FEAT_ENUM_NAME__(X)
#define FEAT_ENUM_NAME FEAT_ENUM_NAME_(INTROSPECTION_PREFIX)
#define GET_FEAT_ENUM_VALUE__(X) Get##X##FeaturesEnumValue
#define GET_FEAT_ENUM_VALUE_(X) GET_FEAT_ENUM_VALUE__(X)
#define GET_FEAT_ENUM_VALUE GET_FEAT_ENUM_VALUE_(INTROSPECTION_PREFIX)
#define GET_FEAT_ENUM_NAME__(X) Get##X##FeaturesEnumName
#define GET_FEAT_ENUM_NAME_(X) GET_FEAT_ENUM_NAME__(X)
#define GET_FEAT_ENUM_NAME GET_FEAT_ENUM_NAME_(INTROSPECTION_PREFIX)
#define FEAT_ENUM_LAST__(X) X##_LAST_
#define FEAT_ENUM_LAST_(X) FEAT_ENUM_LAST__(X)
#define FEAT_ENUM_LAST FEAT_ENUM_LAST_(INTROSPECTION_ENUM_PREFIX)
// Generate individual getters and setters.
#define LINE(ENUM, NAME, A, B, C) \
static void set_##ENUM(FEAT_TYPE_NAME* features, bool value) \
{ \
features->NAME = value; \
} \
static int get_##ENUM(const FEAT_TYPE_NAME* features) \
{ \
return features->NAME; \
}
INTROSPECTION_TABLE
#undef LINE
// Generate getters table
#define LINE(ENUM, NAME, A, B, C) [ENUM] = get_##ENUM,
static int (*const kGetters[])(const FEAT_TYPE_NAME*) = {INTROSPECTION_TABLE};
#undef LINE
// Generate setters table
#define LINE(ENUM, NAME, A, B, C) [ENUM] = set_##ENUM,
static void (*const kSetters[])(FEAT_TYPE_NAME*, bool) = {INTROSPECTION_TABLE};
#undef LINE
// Implements the `GetXXXFeaturesEnumValue` API.
int GET_FEAT_ENUM_VALUE(const FEAT_TYPE_NAME* features, FEAT_ENUM_NAME value)
{
if (value >= FEAT_ENUM_LAST) return false;
return kGetters[value](features);
}
// Generate feature name table.
#define LINE(ENUM, NAME, A, B, C) [ENUM] = STRINGIZE(NAME),
static const char* kFeatureNames[] = {INTROSPECTION_TABLE};
#undef LINE
// Implements the `GetXXXFeaturesEnumName` API.
const char* GET_FEAT_ENUM_NAME(FEAT_ENUM_NAME value)
{
if (value >= FEAT_ENUM_LAST) return "unknown_feature";
return kFeatureNames[value];
}

View File

@ -0,0 +1,15 @@
// SPDX-FileCopyrightText: 2017 Google LLC
// SPDX-License-Identifier: Apache-2.0
#include "internal/hwcaps.h"
#include "define_introspection.inl"
#define LINE(ENUM, NAME, CPUINFO_FLAG, HWCAP, HWCAP2) \
[ENUM] = (HardwareCapabilities){HWCAP, HWCAP2},
static const HardwareCapabilities kHardwareCapabilities[] = {
INTROSPECTION_TABLE};
#undef LINE
#define LINE(ENUM, NAME, CPUINFO_FLAG, HWCAP, HWCAP2) [ENUM] = CPUINFO_FLAG,
static const char* kCpuInfoFlags[] = {INTROSPECTION_TABLE};
#undef LINE

View File

@ -1,58 +0,0 @@
// SPDX-FileCopyrightText: 2017 Google LLC
// SPDX-License-Identifier: Apache-2.0
// The following preprocessor constants must be defined before including this
// file:
// - DEFINE_TABLE_FEATURE_TYPE, the underlying type (e.g. X86Features)
// - DEFINE_TABLE_FEATURES, the list of FEATURE macros to be inserted.
// This file is to be included once per `cpuinfo_XXX.c` in order to construct
// feature getters and setters functions as well as several enum indexed tables
// from the db file.
// - `kGetters` a table of getters function pointers from feature enum to
// retrieve a feature,
// - `kSetters` a table of setters function pointers from feature enum to set a
// feature,
// - `kCpuInfoFlags` a table of strings from feature enum to /proc/cpuinfo
// flags,
// - `kHardwareCapabilities` a table of HardwareCapabilities structs indexed by
// their feature enum.
#ifndef SRC_DEFINE_TABLES_H_
#define SRC_DEFINE_TABLES_H_
#define FEATURE(ENUM, NAME, CPUINFO_FLAG, HWCAP, HWCAP2) [ENUM] = CPUINFO_FLAG,
static const char* kCpuInfoFlags[] = {DEFINE_TABLE_FEATURES};
#undef FEATURE
#ifndef DEFINE_TABLE_DONT_GENERATE_HWCAPS
#define FEATURE(ENUM, NAME, CPUINFO_FLAG, HWCAP, HWCAP2) \
[ENUM] = (HardwareCapabilities){HWCAP, HWCAP2},
static const HardwareCapabilities kHardwareCapabilities[] = {
DEFINE_TABLE_FEATURES};
#undef FEATURE
#endif // DEFINE_TABLE_DONT_GENERATE_HWCAPS
#define FEATURE(ENUM, NAME, CPUINFO_FLAG, HWCAP, HWCAP2) \
static void set_##ENUM(DEFINE_TABLE_FEATURE_TYPE* features, bool value) \
{ \
features->NAME = value; \
} \
static int get_##ENUM(const DEFINE_TABLE_FEATURE_TYPE* features) \
{ \
return features->NAME; \
}
DEFINE_TABLE_FEATURES
#undef FEATURE
#define FEATURE(ENUM, NAME, CPUINFO_FLAG, HWCAP, HWCAP2) [ENUM] = set_##ENUM,
static void (*const kSetters[])(DEFINE_TABLE_FEATURE_TYPE*,
bool) = {DEFINE_TABLE_FEATURES};
#undef FEATURE
#define FEATURE(ENUM, NAME, CPUINFO_FLAG, HWCAP, HWCAP2) [ENUM] = get_##ENUM,
static int (*const kGetters[])(const DEFINE_TABLE_FEATURE_TYPE*) = {
DEFINE_TABLE_FEATURES};
#undef FEATURE
#endif // SRC_DEFINE_TABLES_H_

View File

@ -0,0 +1,12 @@
// SPDX-FileCopyrightText: 2021 Google LLC
// SPDX-License-Identifier: Apache-2.0
#include <stdbool.h>
#include <stddef.h>
static bool equals(const char *lhs, const char *rhs, size_t count)
{
for (size_t i = 0; i < count; ++i)
if (lhs[i] != rhs[i]) return false;
return true;
}

View File

@ -0,0 +1,157 @@
// SPDX-FileCopyrightText: 2017 Google LLC
// SPDX-License-Identifier: Apache-2.0
#include "cpu_features_macros.h"
#ifdef CPU_FEATURES_ARCH_AARCH64
#if defined(CPU_FEATURES_OS_LINUX) || defined(CPU_FEATURES_OS_ANDROID)
#include "cpuinfo_aarch64.h"
////////////////////////////////////////////////////////////////////////////////
// Definitions for introspection.
////////////////////////////////////////////////////////////////////////////////
#define INTROSPECTION_TABLE \
LINE(AARCH64_FP, fp, "fp", AARCH64_HWCAP_FP, 0) \
LINE(AARCH64_ASIMD, asimd, "asimd", AARCH64_HWCAP_ASIMD, 0) \
LINE(AARCH64_EVTSTRM, evtstrm, "evtstrm", AARCH64_HWCAP_EVTSTRM, 0) \
LINE(AARCH64_AES, aes, "aes", AARCH64_HWCAP_AES, 0) \
LINE(AARCH64_PMULL, pmull, "pmull", AARCH64_HWCAP_PMULL, 0) \
LINE(AARCH64_SHA1, sha1, "sha1", AARCH64_HWCAP_SHA1, 0) \
LINE(AARCH64_SHA2, sha2, "sha2", AARCH64_HWCAP_SHA2, 0) \
LINE(AARCH64_CRC32, crc32, "crc32", AARCH64_HWCAP_CRC32, 0) \
LINE(AARCH64_ATOMICS, atomics, "atomics", AARCH64_HWCAP_ATOMICS, 0) \
LINE(AARCH64_FPHP, fphp, "fphp", AARCH64_HWCAP_FPHP, 0) \
LINE(AARCH64_ASIMDHP, asimdhp, "asimdhp", AARCH64_HWCAP_ASIMDHP, 0) \
LINE(AARCH64_CPUID, cpuid, "cpuid", AARCH64_HWCAP_CPUID, 0) \
LINE(AARCH64_ASIMDRDM, asimdrdm, "asimdrdm", AARCH64_HWCAP_ASIMDRDM, 0) \
LINE(AARCH64_JSCVT, jscvt, "jscvt", AARCH64_HWCAP_JSCVT, 0) \
LINE(AARCH64_FCMA, fcma, "fcma", AARCH64_HWCAP_FCMA, 0) \
LINE(AARCH64_LRCPC, lrcpc, "lrcpc", AARCH64_HWCAP_LRCPC, 0) \
LINE(AARCH64_DCPOP, dcpop, "dcpop", AARCH64_HWCAP_DCPOP, 0) \
LINE(AARCH64_SHA3, sha3, "sha3", AARCH64_HWCAP_SHA3, 0) \
LINE(AARCH64_SM3, sm3, "sm3", AARCH64_HWCAP_SM3, 0) \
LINE(AARCH64_SM4, sm4, "sm4", AARCH64_HWCAP_SM4, 0) \
LINE(AARCH64_ASIMDDP, asimddp, "asimddp", AARCH64_HWCAP_ASIMDDP, 0) \
LINE(AARCH64_SHA512, sha512, "sha512", AARCH64_HWCAP_SHA512, 0) \
LINE(AARCH64_SVE, sve, "sve", AARCH64_HWCAP_SVE, 0) \
LINE(AARCH64_ASIMDFHM, asimdfhm, "asimdfhm", AARCH64_HWCAP_ASIMDFHM, 0) \
LINE(AARCH64_DIT, dit, "dit", AARCH64_HWCAP_DIT, 0) \
LINE(AARCH64_USCAT, uscat, "uscat", AARCH64_HWCAP_USCAT, 0) \
LINE(AARCH64_ILRCPC, ilrcpc, "ilrcpc", AARCH64_HWCAP_ILRCPC, 0) \
LINE(AARCH64_FLAGM, flagm, "flagm", AARCH64_HWCAP_FLAGM, 0) \
LINE(AARCH64_SSBS, ssbs, "ssbs", AARCH64_HWCAP_SSBS, 0) \
LINE(AARCH64_SB, sb, "sb", AARCH64_HWCAP_SB, 0) \
LINE(AARCH64_PACA, paca, "paca", AARCH64_HWCAP_PACA, 0) \
LINE(AARCH64_PACG, pacg, "pacg", AARCH64_HWCAP_PACG, 0) \
LINE(AARCH64_DCPODP, dcpodp, "dcpodp", 0, AARCH64_HWCAP2_DCPODP) \
LINE(AARCH64_SVE2, sve2, "sve2", 0, AARCH64_HWCAP2_SVE2) \
LINE(AARCH64_SVEAES, sveaes, "sveaes", 0, AARCH64_HWCAP2_SVEAES) \
LINE(AARCH64_SVEPMULL, svepmull, "svepmull", 0, AARCH64_HWCAP2_SVEPMULL) \
LINE(AARCH64_SVEBITPERM, svebitperm, "svebitperm", 0, \
AARCH64_HWCAP2_SVEBITPERM) \
LINE(AARCH64_SVESHA3, svesha3, "svesha3", 0, AARCH64_HWCAP2_SVESHA3) \
LINE(AARCH64_SVESM4, svesm4, "svesm4", 0, AARCH64_HWCAP2_SVESM4) \
LINE(AARCH64_FLAGM2, flagm2, "flagm2", 0, AARCH64_HWCAP2_FLAGM2) \
LINE(AARCH64_FRINT, frint, "frint", 0, AARCH64_HWCAP2_FRINT) \
LINE(AARCH64_SVEI8MM, svei8mm, "svei8mm", 0, AARCH64_HWCAP2_SVEI8MM) \
LINE(AARCH64_SVEF32MM, svef32mm, "svef32mm", 0, AARCH64_HWCAP2_SVEF32MM) \
LINE(AARCH64_SVEF64MM, svef64mm, "svef64mm", 0, AARCH64_HWCAP2_SVEF64MM) \
LINE(AARCH64_SVEBF16, svebf16, "svebf16", 0, AARCH64_HWCAP2_SVEBF16) \
LINE(AARCH64_I8MM, i8mm, "i8mm", 0, AARCH64_HWCAP2_I8MM) \
LINE(AARCH64_BF16, bf16, "bf16", 0, AARCH64_HWCAP2_BF16) \
LINE(AARCH64_DGH, dgh, "dgh", 0, AARCH64_HWCAP2_DGH) \
LINE(AARCH64_RNG, rng, "rng", 0, AARCH64_HWCAP2_RNG) \
LINE(AARCH64_BTI, bti, "bti", 0, AARCH64_HWCAP2_BTI) \
LINE(AARCH64_MTE, mte, "mte", 0, AARCH64_HWCAP2_MTE)
#define INTROSPECTION_PREFIX Aarch64
#define INTROSPECTION_ENUM_PREFIX AARCH64
#include "define_introspection_and_hwcaps.inl"
////////////////////////////////////////////////////////////////////////////////
// Implementation.
////////////////////////////////////////////////////////////////////////////////
#include "internal/bit_utils.h"
#include "internal/filesystem.h"
#include "internal/stack_line_reader.h"
#include "internal/string_view.h"
#include <stdbool.h>
static bool HandleAarch64Line(const LineResult result,
Aarch64Info* const info)
{
StringView line = result.line;
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], ' '));
}
}
else if (CpuFeatures_StringView_IsEquals(key, str("CPU implementer")))
{
info->implementer = CpuFeatures_StringView_ParsePositiveNumber(value);
}
else if (CpuFeatures_StringView_IsEquals(key, str("CPU variant")))
{
info->variant = CpuFeatures_StringView_ParsePositiveNumber(value);
}
else if (CpuFeatures_StringView_IsEquals(key, str("CPU part")))
{
info->part = CpuFeatures_StringView_ParsePositiveNumber(value);
}
else if (CpuFeatures_StringView_IsEquals(key, str("CPU revision")))
{
info->revision = CpuFeatures_StringView_ParsePositiveNumber(value);
}
}
return !result.eof;
}
static void FillProcCpuInfoData(Aarch64Info* const info)
{
const int fd = CpuFeatures_OpenFile("/proc/cpuinfo");
if (fd >= 0)
{
StackLineReader reader;
StackLineReader_Initialize(&reader, fd);
for (;;)
{
if (!HandleAarch64Line(StackLineReader_NextLine(&reader), info))
{
break;
}
}
CpuFeatures_CloseFile(fd);
}
}
static const Aarch64Info kEmptyAarch64Info;
Aarch64Info GetAarch64Info(void)
{
// 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);
}
}
return info;
}
#endif // defined(CPU_FEATURES_OS_LINUX) || defined(CPU_FEATURES_OS_ANDROID)
#endif // CPU_FEATURES_ARCH_AARCH64

View File

@ -1,47 +1,58 @@
// SPDX-FileCopyrightText: 2017 Google LLC // SPDX-FileCopyrightText: 2017 Google LLC
// SPDX-License-Identifier: Apache-2.0 // SPDX-License-Identifier: Apache-2.0
#include "cpu_features_macros.h"
#ifdef CPU_FEATURES_ARCH_ARM
#if defined(CPU_FEATURES_OS_LINUX) || defined(CPU_FEATURES_OS_ANDROID)
#include "cpuinfo_arm.h" #include "cpuinfo_arm.h"
////////////////////////////////////////////////////////////////////////////////
// Definitions for introspection.
////////////////////////////////////////////////////////////////////////////////
#define INTROSPECTION_TABLE \
LINE(ARM_SWP, swp, "swp", ARM_HWCAP_SWP, 0) \
LINE(ARM_HALF, half, "half", ARM_HWCAP_HALF, 0) \
LINE(ARM_THUMB, thumb, "thumb", ARM_HWCAP_THUMB, 0) \
LINE(ARM_26BIT, _26bit, "26bit", ARM_HWCAP_26BIT, 0) \
LINE(ARM_FASTMULT, fastmult, "fastmult", ARM_HWCAP_FAST_MULT, 0) \
LINE(ARM_FPA, fpa, "fpa", ARM_HWCAP_FPA, 0) \
LINE(ARM_VFP, vfp, "vfp", ARM_HWCAP_VFP, 0) \
LINE(ARM_EDSP, edsp, "edsp", ARM_HWCAP_EDSP, 0) \
LINE(ARM_JAVA, java, "java", ARM_HWCAP_JAVA, 0) \
LINE(ARM_IWMMXT, iwmmxt, "iwmmxt", ARM_HWCAP_IWMMXT, 0) \
LINE(ARM_CRUNCH, crunch, "crunch", ARM_HWCAP_CRUNCH, 0) \
LINE(ARM_THUMBEE, thumbee, "thumbee", ARM_HWCAP_THUMBEE, 0) \
LINE(ARM_NEON, neon, "neon", ARM_HWCAP_NEON, 0) \
LINE(ARM_VFPV3, vfpv3, "vfpv3", ARM_HWCAP_VFPV3, 0) \
LINE(ARM_VFPV3D16, vfpv3d16, "vfpv3d16", ARM_HWCAP_VFPV3D16, 0) \
LINE(ARM_TLS, tls, "tls", ARM_HWCAP_TLS, 0) \
LINE(ARM_VFPV4, vfpv4, "vfpv4", ARM_HWCAP_VFPV4, 0) \
LINE(ARM_IDIVA, idiva, "idiva", ARM_HWCAP_IDIVA, 0) \
LINE(ARM_IDIVT, idivt, "idivt", ARM_HWCAP_IDIVT, 0) \
LINE(ARM_VFPD32, vfpd32, "vfpd32", ARM_HWCAP_VFPD32, 0) \
LINE(ARM_LPAE, lpae, "lpae", ARM_HWCAP_LPAE, 0) \
LINE(ARM_EVTSTRM, evtstrm, "evtstrm", ARM_HWCAP_EVTSTRM, 0) \
LINE(ARM_AES, aes, "aes", 0, ARM_HWCAP2_AES) \
LINE(ARM_PMULL, pmull, "pmull", 0, ARM_HWCAP2_PMULL) \
LINE(ARM_SHA1, sha1, "sha1", 0, ARM_HWCAP2_SHA1) \
LINE(ARM_SHA2, sha2, "sha2", 0, ARM_HWCAP2_SHA2) \
LINE(ARM_CRC32, crc32, "crc32", 0, ARM_HWCAP2_CRC32)
#define INTROSPECTION_PREFIX Arm
#define INTROSPECTION_ENUM_PREFIX ARM
#include "define_introspection_and_hwcaps.inl"
////////////////////////////////////////////////////////////////////////////////
// Implementation.
////////////////////////////////////////////////////////////////////////////////
#include "internal/bit_utils.h" #include "internal/bit_utils.h"
#include "internal/filesystem.h" #include "internal/filesystem.h"
#include "internal/hwcaps.h"
#include "internal/stack_line_reader.h" #include "internal/stack_line_reader.h"
#include "internal/string_view.h" #include "internal/string_view.h"
#include <assert.h>
#include <ctype.h> #include <ctype.h>
#include <stdbool.h>
// 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"
typedef struct typedef struct
{ {
@ -217,18 +228,5 @@ ArmInfo GetArmInfo(void)
return info; return info;
} }
//////////////////////////////////////////////////////////////////////////////// #endif // defined(CPU_FEATURES_OS_LINUX) || defined(CPU_FEATURES_OS_ANDROID)
// Introspection functions #endif // CPU_FEATURES_ARCH_ARM
int GetArmFeaturesEnumValue(const ArmFeatures* features,
ArmFeaturesEnum value)
{
if (value >= ARM_LAST_) return false;
return kGetters[value](features);
}
const char* GetArmFeaturesEnumName(ArmFeaturesEnum value)
{
if (value >= ARM_LAST_) return "unknown feature";
return kCpuInfoFlags[value];
}

View File

@ -1,21 +1,32 @@
// SPDX-FileCopyrightText: 2017 Google LLC // SPDX-FileCopyrightText: 2017 Google LLC
// SPDX-License-Identifier: Apache-2.0 // SPDX-License-Identifier: Apache-2.0
#include "cpu_features_macros.h"
#ifdef CPU_FEATURES_ARCH_MIPS
#if defined(CPU_FEATURES_OS_LINUX) || defined(CPU_FEATURES_OS_ANDROID)
#include "cpuinfo_mips.h" #include "cpuinfo_mips.h"
////////////////////////////////////////////////////////////////////////////////
// Definitions for introspection.
////////////////////////////////////////////////////////////////////////////////
#define INTROSPECTION_TABLE \
LINE(MIPS_MSA, msa, "msa", MIPS_HWCAP_MSA, 0) \
LINE(MIPS_EVA, eva, "eva", 0, 0) \
LINE(MIPS_R6, r6, "r6", MIPS_HWCAP_R6, 0)
#define INTROSPECTION_PREFIX Mips
#define INTROSPECTION_ENUM_PREFIX MIPS
#include "define_introspection_and_hwcaps.inl"
////////////////////////////////////////////////////////////////////////////////
// Implementation.
////////////////////////////////////////////////////////////////////////////////
#include "internal/filesystem.h" #include "internal/filesystem.h"
#include "internal/hwcaps.h" #include "internal/hwcaps.h"
#include "internal/stack_line_reader.h" #include "internal/stack_line_reader.h"
#include "internal/string_view.h" #include "internal/string_view.h"
#include <assert.h>
// 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 bool HandleMipsLine(const LineResult result, static bool HandleMipsLine(const LineResult result,
MipsFeatures* const features) MipsFeatures* const features)
@ -75,18 +86,5 @@ MipsInfo GetMipsInfo(void)
return info; return info;
} }
//////////////////////////////////////////////////////////////////////////////// #endif // defined(CPU_FEATURES_OS_LINUX) || defined(CPU_FEATURES_OS_ANDROID)
// Introspection functions #endif // CPU_FEATURES_ARCH_MIPS
int GetMipsFeaturesEnumValue(const MipsFeatures* features,
MipsFeaturesEnum value)
{
if (value >= MIPS_LAST_) return false;
return kGetters[value](features);
}
const char* GetMipsFeaturesEnumName(MipsFeaturesEnum value)
{
if (value >= MIPS_LAST_) return "unknown feature";
return kCpuInfoFlags[value];
}

View File

@ -0,0 +1,167 @@
// SPDX-FileCopyrightText: 2017 Google LLC
// SPDX-License-Identifier: Apache-2.0
#include "cpu_features_macros.h"
#ifdef CPU_FEATURES_ARCH_PPC
#ifdef CPU_FEATURES_OS_LINUX
#include "cpuinfo_ppc.h"
////////////////////////////////////////////////////////////////////////////////
// Definitions for introspection.
////////////////////////////////////////////////////////////////////////////////
#define INTROSPECTION_TABLE \
LINE(PPC_32, ppc32, "ppc32", PPC_FEATURE_32, 0) \
LINE(PPC_64, ppc64, "ppc64", PPC_FEATURE_64, 0) \
LINE(PPC_601_INSTR, ppc601, "ppc601", PPC_FEATURE_601_INSTR, 0) \
LINE(PPC_HAS_ALTIVEC, altivec, "altivec", PPC_FEATURE_HAS_ALTIVEC, 0) \
LINE(PPC_HAS_FPU, fpu, "fpu", PPC_FEATURE_HAS_FPU, 0) \
LINE(PPC_HAS_MMU, mmu, "mmu", PPC_FEATURE_HAS_MMU, 0) \
LINE(PPC_HAS_4xxMAC, mac_4xx, "4xxmac", PPC_FEATURE_HAS_4xxMAC, 0) \
LINE(PPC_UNIFIED_CACHE, unifiedcache, "ucache", PPC_FEATURE_UNIFIED_CACHE, \
0) \
LINE(PPC_HAS_SPE, spe, "spe", PPC_FEATURE_HAS_SPE, 0) \
LINE(PPC_HAS_EFP_SINGLE, efpsingle, "efpsingle", PPC_FEATURE_HAS_EFP_SINGLE, \
0) \
LINE(PPC_HAS_EFP_DOUBLE, efpdouble, "efpdouble", PPC_FEATURE_HAS_EFP_DOUBLE, \
0) \
LINE(PPC_NO_TB, no_tb, "notb", PPC_FEATURE_NO_TB, 0) \
LINE(PPC_POWER4, power4, "power4", PPC_FEATURE_POWER4, 0) \
LINE(PPC_POWER5, power5, "power5", PPC_FEATURE_POWER5, 0) \
LINE(PPC_POWER5_PLUS, power5plus, "power5+", PPC_FEATURE_POWER5_PLUS, 0) \
LINE(PPC_CELL, cell, "cellbe", PPC_FEATURE_CELL, 0) \
LINE(PPC_BOOKE, booke, "booke", PPC_FEATURE_BOOKE, 0) \
LINE(PPC_SMT, smt, "smt", PPC_FEATURE_SMT, 0) \
LINE(PPC_ICACHE_SNOOP, icachesnoop, "ic_snoop", PPC_FEATURE_ICACHE_SNOOP, 0) \
LINE(PPC_ARCH_2_05, arch205, "arch_2_05", PPC_FEATURE_ARCH_2_05, 0) \
LINE(PPC_PA6T, pa6t, "pa6t", PPC_FEATURE_PA6T, 0) \
LINE(PPC_HAS_DFP, dfp, "dfp", PPC_FEATURE_HAS_DFP, 0) \
LINE(PPC_POWER6_EXT, power6ext, "power6x", PPC_FEATURE_POWER6_EXT, 0) \
LINE(PPC_ARCH_2_06, arch206, "arch_2_06", PPC_FEATURE_ARCH_2_06, 0) \
LINE(PPC_HAS_VSX, vsx, "vsx", PPC_FEATURE_HAS_VSX, 0) \
LINE(PPC_PSERIES_PERFMON_COMPAT, pseries_perfmon_compat, "archpmu", \
PPC_FEATURE_PSERIES_PERFMON_COMPAT, 0) \
LINE(PPC_TRUE_LE, truele, "true_le", PPC_FEATURE_TRUE_LE, 0) \
LINE(PPC_PPC_LE, ppcle, "ppcle", PPC_FEATURE_PPC_LE, 0) \
LINE(PPC_ARCH_2_07, arch207, "arch_2_07", 0, PPC_FEATURE2_ARCH_2_07) \
LINE(PPC_HTM, htm, "htm", 0, PPC_FEATURE2_HTM) \
LINE(PPC_DSCR, dscr, "dscr", 0, PPC_FEATURE2_DSCR) \
LINE(PPC_EBB, ebb, "ebb", 0, PPC_FEATURE2_EBB) \
LINE(PPC_ISEL, isel, "isel", 0, PPC_FEATURE2_ISEL) \
LINE(PPC_TAR, tar, "tar", 0, PPC_FEATURE2_TAR) \
LINE(PPC_VEC_CRYPTO, vcrypto, "vcrypto", 0, PPC_FEATURE2_VEC_CRYPTO) \
LINE(PPC_HTM_NOSC, htm_nosc, "htm-nosc", 0, PPC_FEATURE2_HTM_NOSC) \
LINE(PPC_ARCH_3_00, arch300, "arch_3_00", 0, PPC_FEATURE2_ARCH_3_00) \
LINE(PPC_HAS_IEEE128, ieee128, "ieee128", 0, PPC_FEATURE2_HAS_IEEE128) \
LINE(PPC_DARN, darn, "darn", 0, PPC_FEATURE2_DARN) \
LINE(PPC_SCV, scv, "scv", 0, PPC_FEATURE2_SCV) \
LINE(PPC_HTM_NO_SUSPEND, htm_no_suspend, "htm-no-suspend", 0, \
PPC_FEATURE2_HTM_NO_SUSPEND)
#define INTROSPECTION_PREFIX PPC
#define INTROSPECTION_ENUM_PREFIX PPC
#include "define_introspection_and_hwcaps.inl"
////////////////////////////////////////////////////////////////////////////////
// Implementation.
////////////////////////////////////////////////////////////////////////////////
#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 <stdbool.h>
static bool HandlePPCLine(const LineResult result,
PPCPlatformStrings* const strings)
{
StringView line = result.line;
StringView key, value;
if (CpuFeatures_StringView_GetAttributeKeyValue(line, &key, &value))
{
if (CpuFeatures_StringView_HasWord(key, "platform", ' '))
{
CpuFeatures_StringView_CopyString(value, strings->platform,
sizeof(strings->platform));
}
else if (CpuFeatures_StringView_IsEquals(key, str("model")))
{
CpuFeatures_StringView_CopyString(value, strings->model,
sizeof(strings->platform));
}
else if (CpuFeatures_StringView_IsEquals(key, str("machine")))
{
CpuFeatures_StringView_CopyString(value, strings->machine,
sizeof(strings->platform));
}
else if (CpuFeatures_StringView_IsEquals(key, str("cpu")))
{
CpuFeatures_StringView_CopyString(value, strings->cpu,
sizeof(strings->platform));
}
}
return !result.eof;
}
static void FillProcCpuInfoData(PPCPlatformStrings* const strings)
{
const int fd = CpuFeatures_OpenFile("/proc/cpuinfo");
if (fd >= 0)
{
StackLineReader reader;
StackLineReader_Initialize(&reader, fd);
for (;;)
{
if (!HandlePPCLine(StackLineReader_NextLine(&reader), strings))
{
break;
}
}
CpuFeatures_CloseFile(fd);
}
}
static const PPCInfo kEmptyPPCInfo;
PPCInfo GetPPCInfo(void)
{
/*
* On Power feature flags aren't currently in cpuinfo so we only look at
* 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);
}
}
return info;
}
static const PPCPlatformStrings kEmptyPPCPlatformStrings;
PPCPlatformStrings GetPPCPlatformStrings(void)
{
PPCPlatformStrings strings = kEmptyPPCPlatformStrings;
const char* platform = CpuFeatures_GetPlatformPointer();
const char* base_platform = CpuFeatures_GetBasePlatformPointer();
FillProcCpuInfoData(&strings);
if (platform != NULL)
CpuFeatures_StringView_CopyString(str(platform), strings.type.platform,
sizeof(strings.type.platform));
if (base_platform != NULL)
CpuFeatures_StringView_CopyString(str(base_platform),
strings.type.base_platform,
sizeof(strings.type.base_platform));
return strings;
}
#endif // CPU_FEATURES_OS_LINUX
#endif // CPU_FEATURES_ARCH_PPC

View File

@ -0,0 +1,60 @@
// SPDX-FileCopyrightText: 2017 Google LLC
// SPDX-License-Identifier: Apache-2.0
#include "cpu_features_macros.h"
#ifdef CPU_FEATURES_ARCH_X86
#ifdef CPU_FEATURES_OS_FREEBSD
#include "impl_x86__base_implementation.inl"
static void OverrideOsPreserves(OsPreserves* os_preserves)
{
(void)os_preserves;
// No override
}
#include "internal/filesystem.h"
#include "internal/stack_line_reader.h"
#include "internal/string_view.h"
static void DetectFeaturesFromOs(X86Features* features)
{
// Handling FreeBSD platform through parsing /var/run/dmesg.boot.
const int fd = CpuFeatures_OpenFile("/var/run/dmesg.boot");
if (fd >= 0)
{
StackLineReader reader;
StackLineReader_Initialize(&reader, fd);
for (bool stop = false; !stop;)
{
const LineResult result = StackLineReader_NextLine(&reader);
if (result.eof) stop = true;
const StringView line = result.line;
if (!CpuFeatures_StringView_StartsWith(line, str(" Features"))) continue;
// Lines of interests are of the following form:
// " Features=0x1783fbff<PSE36,MMX,FXSR,SSE,SSE2,HTT>"
// We first extract the comma separated values between angle brackets.
StringView csv = result.line;
int index = CpuFeatures_StringView_IndexOfChar(csv, '<');
if (index >= 0) csv = CpuFeatures_StringView_PopFront(csv, index + 1);
if (csv.size > 0 && CpuFeatures_StringView_Back(csv) == '>')
csv = CpuFeatures_StringView_PopBack(csv, 1);
if (CpuFeatures_StringView_HasWord(csv, "SSE", ',')) features->sse = true;
if (CpuFeatures_StringView_HasWord(csv, "SSE2", ','))
features->sse2 = true;
if (CpuFeatures_StringView_HasWord(csv, "SSE3", ','))
features->sse3 = true;
if (CpuFeatures_StringView_HasWord(csv, "SSSE3", ','))
features->ssse3 = true;
if (CpuFeatures_StringView_HasWord(csv, "SSE4.1", ','))
features->sse4_1 = true;
if (CpuFeatures_StringView_HasWord(csv, "SSE4.2", ','))
features->sse4_2 = true;
}
CpuFeatures_CloseFile(fd);
}
}
#endif // CPU_FEATURES_OS_FREEBSD
#endif // CPU_FEATURES_ARCH_X86

View File

@ -0,0 +1,50 @@
// SPDX-FileCopyrightText: 2017 Google LLC
// SPDX-License-Identifier: Apache-2.0
#include "cpu_features_macros.h"
#ifdef CPU_FEATURES_ARCH_X86
#if defined(CPU_FEATURES_OS_LINUX) || defined(CPU_FEATURES_OS_ANDROID)
#include "impl_x86__base_implementation.inl"
static void OverrideOsPreserves(OsPreserves* os_preserves)
{
(void)os_preserves;
// No override
}
#include "internal/filesystem.h"
#include "internal/stack_line_reader.h"
#include "internal/string_view.h"
static void DetectFeaturesFromOs(X86Features* features)
{
// Handling Linux platform through /proc/cpuinfo.
const int fd = CpuFeatures_OpenFile("/proc/cpuinfo");
if (fd >= 0)
{
StackLineReader reader;
StackLineReader_Initialize(&reader, fd);
for (bool stop = false; !stop;)
{
const LineResult result = StackLineReader_NextLine(&reader);
if (result.eof) stop = true;
const StringView line = result.line;
StringView key, value;
if (!CpuFeatures_StringView_GetAttributeKeyValue(line, &key, &value))
continue;
if (!CpuFeatures_StringView_IsEquals(key, str("flags"))) continue;
features->sse = CpuFeatures_StringView_HasWord(value, "sse", ' ');
features->sse2 = CpuFeatures_StringView_HasWord(value, "sse2", ' ');
features->sse3 = CpuFeatures_StringView_HasWord(value, "sse3", ' ');
features->ssse3 = CpuFeatures_StringView_HasWord(value, "ssse3", ' ');
features->sse4_1 = CpuFeatures_StringView_HasWord(value, "sse4_1", ' ');
features->sse4_2 = CpuFeatures_StringView_HasWord(value, "sse4_2", ' ');
break;
}
CpuFeatures_CloseFile(fd);
}
}
#endif // defined(CPU_FEATURES_OS_LINUX) || defined(CPU_FEATURES_OS_ANDROID)
#endif // CPU_FEATURES_ARCH_X86

View File

@ -0,0 +1,48 @@
// SPDX-FileCopyrightText: 2017 Google LLC
// SPDX-License-Identifier: Apache-2.0
#include "cpu_features_macros.h"
#ifdef CPU_FEATURES_ARCH_X86
#ifdef CPU_FEATURES_OS_MACOS
#include "impl_x86__base_implementation.inl"
#if !defined(HAVE_SYSCTLBYNAME)
#error "Darwin needs support for sysctlbyname"
#endif
#include <sys/sysctl.h>
#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
static void OverrideOsPreserves(OsPreserves* os_preserves)
{
// On Darwin AVX512 support is On-demand.
// We have to query the OS instead of querying the Zmm save/restore state.
// https://github.com/apple/darwin-xnu/blob/8f02f2a044b9bb1ad951987ef5bab20ec9486310/osfmk/i386/fpu.c#L173-L199
os_preserves->avx512_registers = GetDarwinSysCtlByName("hw.optional.avx512f");
}
static void DetectFeaturesFromOs(X86Features* features)
{
// 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");
}
#endif // CPU_FEATURES_OS_MACOS
#endif // CPU_FEATURES_ARCH_X86

View File

@ -0,0 +1,41 @@
// SPDX-FileCopyrightText: 2017 Google LLC
// SPDX-License-Identifier: Apache-2.0
#include "cpu_features_macros.h"
#ifdef CPU_FEATURES_ARCH_X86
#ifdef CPU_FEATURES_OS_WINDOWS
#include "impl_x86__base_implementation.inl"
static void OverrideOsPreserves(OsPreserves* os_preserves)
{
(void)os_preserves;
// No override
}
#include <windows.h> // IsProcessorFeaturePresent
#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
static void DetectFeaturesFromOs(X86Features* features)
{
// Handling Windows platform through IsProcessorFeaturePresent.
// https://docs.microsoft.com/en-us/windows/win32/api/processthreadsapi/nf-processthreadsapi-isprocessorfeaturepresent
features->sse =
GetWindowsIsProcessorFeaturePresent(PF_XMMI_INSTRUCTIONS_AVAILABLE);
features->sse2 =
GetWindowsIsProcessorFeaturePresent(PF_XMMI64_INSTRUCTIONS_AVAILABLE);
features->sse3 =
GetWindowsIsProcessorFeaturePresent(PF_SSE3_INSTRUCTIONS_AVAILABLE);
}
#endif // CPU_FEATURES_OS_WINDOWS
#endif // CPU_FEATURES_ARCH_X86

View File

@ -1,4 +1,4 @@
// SPDX-FileCopyrightText: 2017 Google LLC // SPDX-FileCopyrightText: 2021 Google LLC
// SPDX-License-Identifier: Apache-2.0 // SPDX-License-Identifier: Apache-2.0
// This program dumps current host data to the standard output. // This program dumps current host data to the standard output.

View File

@ -50,7 +50,13 @@ add_test(NAME stack_line_reader_test COMMAND stack_line_reader_test)
##------------------------------------------------------------------------------ ##------------------------------------------------------------------------------
## cpuinfo_x86_test ## cpuinfo_x86_test
if(PROCESSOR_IS_X86) if(PROCESSOR_IS_X86)
add_executable(cpuinfo_x86_test cpuinfo_x86_test.cc ../src/cpuinfo_x86.c) add_executable(cpuinfo_x86_test
cpuinfo_x86_test.cc
../src/impl_x86_freebsd.c
../src/impl_x86_linux_or_android.c
../src/impl_x86_macos.c
../src/impl_x86_windows.c
)
target_compile_definitions(cpuinfo_x86_test PUBLIC CPU_FEATURES_MOCK_CPUID_X86) target_compile_definitions(cpuinfo_x86_test PUBLIC CPU_FEATURES_MOCK_CPUID_X86)
if(APPLE) if(APPLE)
target_compile_definitions(cpuinfo_x86_test PRIVATE HAVE_SYSCTLBYNAME) target_compile_definitions(cpuinfo_x86_test PRIVATE HAVE_SYSCTLBYNAME)
@ -61,32 +67,28 @@ endif()
##------------------------------------------------------------------------------ ##------------------------------------------------------------------------------
## cpuinfo_arm_test ## cpuinfo_arm_test
if(PROCESSOR_IS_ARM) if(PROCESSOR_IS_ARM)
add_executable(cpuinfo_arm_test cpuinfo_arm_test.cc ../src/cpuinfo_arm.c) add_executable(cpuinfo_arm_test cpuinfo_arm_test.cc ../src/impl_arm_linux_or_android.c)
target_link_libraries(cpuinfo_arm_test all_libraries) target_link_libraries(cpuinfo_arm_test all_libraries)
add_test(NAME cpuinfo_arm_test COMMAND cpuinfo_arm_test) add_test(NAME cpuinfo_arm_test COMMAND cpuinfo_arm_test)
endif() endif()
##------------------------------------------------------------------------------ ##------------------------------------------------------------------------------
## cpuinfo_aarch64_test ## cpuinfo_aarch64_test
if(PROCESSOR_IS_AARCH64) if(PROCESSOR_IS_AARCH64)
add_executable(cpuinfo_aarch64_test cpuinfo_aarch64_test.cc ../src/cpuinfo_aarch64.c) add_executable(cpuinfo_aarch64_test cpuinfo_aarch64_test.cc ../src/impl_aarch64_linux_or_android.c)
if(APPLE)
target_compile_definitions(cpuinfo_aarch64_test PUBLIC CPU_FEATURES_MOCK_CPUID_ARM64)
target_compile_definitions(cpuinfo_aarch64_test PRIVATE HAVE_SYSCTLBYNAME)
endif()
target_link_libraries(cpuinfo_aarch64_test all_libraries) target_link_libraries(cpuinfo_aarch64_test all_libraries)
add_test(NAME cpuinfo_aarch64_test COMMAND cpuinfo_aarch64_test) add_test(NAME cpuinfo_aarch64_test COMMAND cpuinfo_aarch64_test)
endif() endif()
##------------------------------------------------------------------------------ ##------------------------------------------------------------------------------
## cpuinfo_mips_test ## cpuinfo_mips_test
if(PROCESSOR_IS_MIPS) if(PROCESSOR_IS_MIPS)
add_executable(cpuinfo_mips_test cpuinfo_mips_test.cc ../src/cpuinfo_mips.c) add_executable(cpuinfo_mips_test cpuinfo_mips_test.cc ../src/impl_mips_linux_or_android.c)
target_link_libraries(cpuinfo_mips_test all_libraries) target_link_libraries(cpuinfo_mips_test all_libraries)
add_test(NAME cpuinfo_mips_test COMMAND cpuinfo_mips_test) add_test(NAME cpuinfo_mips_test COMMAND cpuinfo_mips_test)
endif() endif()
##------------------------------------------------------------------------------ ##------------------------------------------------------------------------------
## cpuinfo_ppc_test ## cpuinfo_ppc_test
if(PROCESSOR_IS_POWER) if(PROCESSOR_IS_POWER)
add_executable(cpuinfo_ppc_test cpuinfo_ppc_test.cc ../src/cpuinfo_ppc.c) add_executable(cpuinfo_ppc_test cpuinfo_ppc_test.cc ../src/impl_ppc_linux.c)
target_link_libraries(cpuinfo_ppc_test all_libraries) target_link_libraries(cpuinfo_ppc_test all_libraries)
add_test(NAME cpuinfo_ppc_test COMMAND cpuinfo_ppc_test) add_test(NAME cpuinfo_ppc_test COMMAND cpuinfo_ppc_test)
endif() endif()

View File

@ -16,6 +16,7 @@
namespace cpu_features namespace cpu_features
{ {
class FakeCpu class FakeCpu
{ {
public: public:
@ -41,7 +42,7 @@ public:
xcr0_eax_ = os_backups_extended_registers ? -1 : 0; xcr0_eax_ = os_backups_extended_registers ? -1 : 0;
} }
#if defined(CPU_FEATURES_OS_DARWIN) #if defined(CPU_FEATURES_OS_MACOS)
bool GetDarwinSysCtlByName(std::string name) const bool GetDarwinSysCtlByName(std::string name) const
{ {
return darwin_sysctlbyname_.count(name); return darwin_sysctlbyname_.count(name);
@ -51,7 +52,7 @@ public:
{ {
darwin_sysctlbyname_.insert(name); darwin_sysctlbyname_.insert(name);
} }
#endif // CPU_FEATURES_OS_DARWIN #endif // CPU_FEATURES_OS_MACOS
#if defined(CPU_FEATURES_OS_WINDOWS) #if defined(CPU_FEATURES_OS_WINDOWS)
bool GetWindowsIsProcessorFeaturePresent(DWORD ProcessorFeature) bool GetWindowsIsProcessorFeaturePresent(DWORD ProcessorFeature)
@ -67,9 +68,9 @@ public:
private: private:
std::map<std::pair<uint32_t, int>, Leaf> cpuid_leaves_; std::map<std::pair<uint32_t, int>, Leaf> cpuid_leaves_;
#if defined(CPU_FEATURES_OS_DARWIN) #if defined(CPU_FEATURES_OS_MACOS)
std::set<std::string> darwin_sysctlbyname_; std::set<std::string> darwin_sysctlbyname_;
#endif // CPU_FEATURES_OS_DARWIN #endif // CPU_FEATURES_OS_MACOS
#if defined(CPU_FEATURES_OS_WINDOWS) #if defined(CPU_FEATURES_OS_WINDOWS)
std::set<DWORD> windows_isprocessorfeaturepresent_; std::set<DWORD> windows_isprocessorfeaturepresent_;
#endif // CPU_FEATURES_OS_WINDOWS #endif // CPU_FEATURES_OS_WINDOWS
@ -91,12 +92,12 @@ extern "C" Leaf GetCpuidLeaf(uint32_t leaf_id, int ecx)
extern "C" uint32_t GetXCR0Eax(void) { return cpu().GetXCR0Eax(); } extern "C" uint32_t GetXCR0Eax(void) { return cpu().GetXCR0Eax(); }
#if defined(CPU_FEATURES_OS_DARWIN) #if defined(CPU_FEATURES_OS_MACOS)
extern "C" bool GetDarwinSysCtlByName(const char* name) extern "C" bool GetDarwinSysCtlByName(const char* name)
{ {
return cpu().GetDarwinSysCtlByName(name); return cpu().GetDarwinSysCtlByName(name);
} }
#endif // CPU_FEATURES_OS_DARWIN #endif // CPU_FEATURES_OS_MACOS
#if defined(CPU_FEATURES_OS_WINDOWS) #if defined(CPU_FEATURES_OS_WINDOWS)
extern "C" bool GetWindowsIsProcessorFeaturePresent(DWORD ProcessorFeature) extern "C" bool GetWindowsIsProcessorFeaturePresent(DWORD ProcessorFeature)
@ -107,6 +108,7 @@ extern "C" bool GetWindowsIsProcessorFeaturePresent(DWORD ProcessorFeature)
namespace namespace
{ {
class CpuidX86Test : public ::testing::Test class CpuidX86Test : public ::testing::Test
{ {
protected: protected:
@ -800,7 +802,7 @@ TEST_F(CpuidX86Test, Nehalem)
cpu().SetWindowsIsProcessorFeaturePresent(PF_XMMI_INSTRUCTIONS_AVAILABLE); cpu().SetWindowsIsProcessorFeaturePresent(PF_XMMI_INSTRUCTIONS_AVAILABLE);
cpu().SetWindowsIsProcessorFeaturePresent(PF_XMMI64_INSTRUCTIONS_AVAILABLE); cpu().SetWindowsIsProcessorFeaturePresent(PF_XMMI64_INSTRUCTIONS_AVAILABLE);
cpu().SetWindowsIsProcessorFeaturePresent(PF_SSE3_INSTRUCTIONS_AVAILABLE); cpu().SetWindowsIsProcessorFeaturePresent(PF_SSE3_INSTRUCTIONS_AVAILABLE);
#elif defined(CPU_FEATURES_OS_DARWIN) #elif defined(CPU_FEATURES_OS_MACOS)
cpu().SetDarwinSysCtlByName("hw.optional.sse"); cpu().SetDarwinSysCtlByName("hw.optional.sse");
cpu().SetDarwinSysCtlByName("hw.optional.sse2"); cpu().SetDarwinSysCtlByName("hw.optional.sse2");
cpu().SetDarwinSysCtlByName("hw.optional.sse3"); cpu().SetDarwinSysCtlByName("hw.optional.sse3");
@ -817,7 +819,7 @@ FreeBSD is a registered trademark of The FreeBSD Foundation.
Features2=0x5eda2203<SSE3,PCLMULQDQ,SSSE3,CX16,PCID,SSE4.1,SSE4.2,MOVBE,POPCNT,AESNI,XSAVE,OSXSAVE,RDRAND> Features2=0x5eda2203<SSE3,PCLMULQDQ,SSSE3,CX16,PCID,SSE4.1,SSE4.2,MOVBE,POPCNT,AESNI,XSAVE,OSXSAVE,RDRAND>
real memory = 2147418112 (2047 MB) real memory = 2147418112 (2047 MB)
)"); )");
#elif defined(CPU_FEATURES_OS_LINUX_OR_ANDROID) #elif defined(CPU_FEATURES_OS_LINUX) || defined(CPU_FEATURES_OS_ANDROID)
auto& fs = GetEmptyFilesystem(); auto& fs = GetEmptyFilesystem();
fs.CreateFile("/proc/cpuinfo", R"(processor : fs.CreateFile("/proc/cpuinfo", R"(processor :
flags : fpu mmx sse sse2 sse3 ssse3 sse4_1 sse4_2 flags : fpu mmx sse sse2 sse3 ssse3 sse4_1 sse4_2
@ -883,7 +885,7 @@ TEST_F(CpuidX86Test, Atom)
cpu().SetWindowsIsProcessorFeaturePresent(PF_XMMI_INSTRUCTIONS_AVAILABLE); cpu().SetWindowsIsProcessorFeaturePresent(PF_XMMI_INSTRUCTIONS_AVAILABLE);
cpu().SetWindowsIsProcessorFeaturePresent(PF_XMMI64_INSTRUCTIONS_AVAILABLE); cpu().SetWindowsIsProcessorFeaturePresent(PF_XMMI64_INSTRUCTIONS_AVAILABLE);
cpu().SetWindowsIsProcessorFeaturePresent(PF_SSE3_INSTRUCTIONS_AVAILABLE); cpu().SetWindowsIsProcessorFeaturePresent(PF_SSE3_INSTRUCTIONS_AVAILABLE);
#elif defined(CPU_FEATURES_OS_DARWIN) #elif defined(CPU_FEATURES_OS_MACOS)
cpu().SetDarwinSysCtlByName("hw.optional.sse"); cpu().SetDarwinSysCtlByName("hw.optional.sse");
cpu().SetDarwinSysCtlByName("hw.optional.sse2"); cpu().SetDarwinSysCtlByName("hw.optional.sse2");
cpu().SetDarwinSysCtlByName("hw.optional.sse3"); cpu().SetDarwinSysCtlByName("hw.optional.sse3");
@ -900,7 +902,7 @@ FreeBSD is a registered trademark of The FreeBSD Foundation.
Features2=0x5eda2203<SSE3,PCLMULQDQ,SSSE3,CX16,PCID,SSE4.1,SSE4.2,MOVBE,POPCNT,AESNI,XSAVE,OSXSAVE,RDRAND> Features2=0x5eda2203<SSE3,PCLMULQDQ,SSSE3,CX16,PCID,SSE4.1,SSE4.2,MOVBE,POPCNT,AESNI,XSAVE,OSXSAVE,RDRAND>
real memory = 2147418112 (2047 MB) real memory = 2147418112 (2047 MB)
)"); )");
#elif defined(CPU_FEATURES_OS_LINUX_OR_ANDROID) #elif defined(CPU_FEATURES_OS_LINUX) || defined(CPU_FEATURES_OS_ANDROID)
auto& fs = GetEmptyFilesystem(); auto& fs = GetEmptyFilesystem();
fs.CreateFile("/proc/cpuinfo", R"( fs.CreateFile("/proc/cpuinfo", R"(
flags : fpu mmx sse sse2 sse3 ssse3 sse4_1 sse4_2 flags : fpu mmx sse sse2 sse3 ssse3 sse4_1 sse4_2
@ -1017,7 +1019,7 @@ TEST_F(CpuidX86Test, P3)
cpu().SetOsBackupsExtendedRegisters(false); cpu().SetOsBackupsExtendedRegisters(false);
#if defined(CPU_FEATURES_OS_WINDOWS) #if defined(CPU_FEATURES_OS_WINDOWS)
cpu().SetWindowsIsProcessorFeaturePresent(PF_XMMI_INSTRUCTIONS_AVAILABLE); cpu().SetWindowsIsProcessorFeaturePresent(PF_XMMI_INSTRUCTIONS_AVAILABLE);
#elif defined(CPU_FEATURES_OS_DARWIN) #elif defined(CPU_FEATURES_OS_MACOS)
cpu().SetDarwinSysCtlByName("hw.optional.sse"); cpu().SetDarwinSysCtlByName("hw.optional.sse");
#elif defined(CPU_FEATURES_OS_FREEBSD) #elif defined(CPU_FEATURES_OS_FREEBSD)
auto& fs = GetEmptyFilesystem(); auto& fs = GetEmptyFilesystem();
@ -1028,7 +1030,7 @@ FreeBSD is a registered trademark of The FreeBSD Foundation.
Features=0x1783fbff<FPU,VME,DE,PSE,TSC,MSR,PAE,MCE,CX8,APIC,SEP,MTRR,PGE,MCA,CMOV,PAT,PSE36,MMX,FXSR,SSE> Features=0x1783fbff<FPU,VME,DE,PSE,TSC,MSR,PAE,MCE,CX8,APIC,SEP,MTRR,PGE,MCA,CMOV,PAT,PSE36,MMX,FXSR,SSE>
real memory = 2147418112 (2047 MB) real memory = 2147418112 (2047 MB)
)"); )");
#elif defined(CPU_FEATURES_OS_LINUX_OR_ANDROID) #elif defined(CPU_FEATURES_OS_LINUX) || defined(CPU_FEATURES_OS_ANDROID)
auto& fs = GetEmptyFilesystem(); auto& fs = GetEmptyFilesystem();
fs.CreateFile("/proc/cpuinfo", R"( fs.CreateFile("/proc/cpuinfo", R"(
flags : fpu mmx sse flags : fpu mmx sse
@ -1065,6 +1067,68 @@ flags : fpu mmx sse
#endif // !defined(CPU_FEATURES_OS_WINDOWS) #endif // !defined(CPU_FEATURES_OS_WINDOWS)
} }
// https://github.com/InstLatx64/InstLatx64/blob/master/GenuineIntel/GenuineIntel0000480_486_CPUID.txt
TEST_F(CpuidX86Test, INTEL_80486)
{
cpu().SetLeaves({
{{0x00000000, 0}, Leaf{0x00000001, 0x756E6547, 0x6C65746E, 0x49656E69}},
{{0x00000001, 0}, Leaf{0x00000480, 0x00000000, 0x00000000, 0x00000003}},
});
const auto info = GetX86Info();
EXPECT_STREQ(info.vendor, "GenuineIntel");
EXPECT_EQ(info.family, 0x04);
EXPECT_EQ(info.model, 0x08);
EXPECT_EQ(GetX86Microarchitecture(&info), X86Microarchitecture::INTEL_80486);
}
// https://github.com/InstLatx64/InstLatx64/blob/master/GenuineIntel/GenuineIntel0000526_P54C_CPUID.txt
TEST_F(CpuidX86Test, INTEL_P54C)
{
cpu().SetLeaves({
{{0x00000000, 0}, Leaf{0x00000001, 0x756E6547, 0x6C65746E, 0x49656E69}},
{{0x00000001, 0}, Leaf{0x00000525, 0x00000000, 0x00000000, 0x000001BF}},
});
const auto info = GetX86Info();
EXPECT_STREQ(info.vendor, "GenuineIntel");
EXPECT_EQ(info.family, 0x05);
EXPECT_EQ(info.model, 0x02);
EXPECT_EQ(GetX86Microarchitecture(&info), X86Microarchitecture::INTEL_P5);
}
// https://github.com/InstLatx64/InstLatx64/blob/master/GenuineIntel/GenuineIntel0000590_Lakemont_CPUID2.txt
TEST_F(CpuidX86Test, INTEL_LAKEMONT)
{
cpu().SetLeaves({
{{0x00000000, 0}, Leaf{0x00000002, 0x756E6547, 0x6c65746E, 0x49656E69}},
{{0x00000001, 0}, Leaf{0x00000590, 0x00000000, 0x00010200, 0x8000237B}},
});
const auto info = GetX86Info();
EXPECT_STREQ(info.vendor, "GenuineIntel");
EXPECT_EQ(info.family, 0x05);
EXPECT_EQ(info.model, 0x09);
EXPECT_EQ(GetX86Microarchitecture(&info),
X86Microarchitecture::INTEL_LAKEMONT);
}
// https://github.com/InstLatx64/InstLatx64/blob/master/GenuineIntel/GenuineIntel0050670_KnightsLanding_CPUID.txt
TEST_F(CpuidX86Test, INTEL_KNIGHTS_LANDING)
{
cpu().SetLeaves({
{{0x00000000, 0}, Leaf{0x0000000D, 0x756E6547, 0x6C65746E, 0x49656E69}},
{{0x00000001, 0}, Leaf{0x00050670, 0x02FF0800, 0x7FF8F3BF, 0xBFEBFBFF}},
});
const auto info = GetX86Info();
EXPECT_STREQ(info.vendor, "GenuineIntel");
EXPECT_EQ(info.family, 0x06);
EXPECT_EQ(info.model, 0x57);
EXPECT_EQ(GetX86Microarchitecture(&info),
X86Microarchitecture::INTEL_KNIGHTS_L);
}
// TODO(user): test what happens when xsave/osxsave are not present. // TODO(user): test what happens when xsave/osxsave are not present.
// TODO(user): test what happens when xmm/ymm/zmm os support are not // TODO(user): test what happens when xmm/ymm/zmm os support are not
// present. // present.