mirror of
https://github.com/google/cpu_features.git
synced 2025-04-27 15:12:30 +02:00
New code layout - breaking change in cpu_features_macros.h (#194)
This commit helps with platform code separation (fixes #3). It should also help with the build as we can simply include all `impl_*.c` files regardless of OS / arch. Note: this patch contains breaking changes in `include/cpu_features_macros.h` - `CPU_FEATURES_OS_LINUX_OR_ANDROID` does not exist anymore - `CPU_FEATURES_OS_FREEBSD`, `CPU_FEATURES_OS_ANDROID` and `CPU_FEATURES_OS_LINUX` are now mutually exclusive (i.e. `CPU_FEATURES_OS_ANDROID` does not imply `CPU_FEATURES_OS_LINUX`) - `CPU_FEATURES_OS_DARWIN` has been renamed into `CPU_FEATURES_OS_MACOS` to be able to target non-Mac Apple products (IOS, TV, WATCH). They are now targetable with `CPU_FEATURES_OS_IPHONE`. This matches Apple naming convention described in [this stackoverflow](https://stackoverflow.com/a/49560690).
This commit is contained in:
parent
0dd8b41eca
commit
deb2a61b80
@ -65,22 +65,19 @@ endif()
|
||||
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_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)
|
||||
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)
|
||||
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)
|
||||
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)
|
||||
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}/src/cpuinfo_x86.c)
|
||||
elseif(PROCESSOR_IS_POWER)
|
||||
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()
|
||||
message(FATAL_ERROR "Unsupported architectures ${CMAKE_SYSTEM_PROCESSOR}")
|
||||
endif()
|
||||
|
@ -67,24 +67,33 @@
|
||||
// Os
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#if defined(__linux__)
|
||||
#define CPU_FEATURES_OS_LINUX_OR_ANDROID
|
||||
#if (defined(__freebsd__) || defined(__FreeBSD__))
|
||||
#define CPU_FEATURES_OS_FREEBSD
|
||||
#endif
|
||||
|
||||
#if defined(__ANDROID__)
|
||||
#define CPU_FEATURES_OS_ANDROID
|
||||
#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))
|
||||
#define CPU_FEATURES_OS_WINDOWS
|
||||
#endif
|
||||
|
||||
#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
|
||||
|
||||
#if (defined(__freebsd__) || defined(__FreeBSD__))
|
||||
#define CPU_FEATURES_OS_FREEBSD
|
||||
#endif
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -152,6 +152,7 @@ typedef enum {
|
||||
AMD_ZEN_PLUS, // K17 ZEN+
|
||||
AMD_ZEN2, // K17 ZEN 2
|
||||
AMD_ZEN3, // K19 ZEN 3
|
||||
X86_MICROARCHITECTURE_LAST_,
|
||||
} X86Microarchitecture;
|
||||
|
||||
// Returns the underlying microarchitecture by looking at X86Info's vendor,
|
||||
|
33
src/copy.h
Normal file
33
src/copy.h
Normal file
@ -0,0 +1,33 @@
|
||||
// Copyright 2021 Google LLC
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
static void copy(char *__restrict dst, const char *src, size_t count) {
|
||||
size_t offset = 0;
|
||||
|
||||
#define CHUNK_COPY(TYPE) \
|
||||
while (count - offset >= sizeof(TYPE)) { \
|
||||
*(TYPE *)(dst + offset) = *(const TYPE *)(src + offset); \
|
||||
offset += sizeof(TYPE); \
|
||||
}
|
||||
|
||||
CHUNK_COPY(uint64_t)
|
||||
CHUNK_COPY(uint32_t)
|
||||
CHUNK_COPY(uint16_t)
|
||||
CHUNK_COPY(uint8_t)
|
||||
|
||||
#undef CHUNK_COPY
|
||||
}
|
@ -1,151 +0,0 @@
|
||||
// Copyright 2017 Google LLC
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include "cpuinfo_aarch64.h"
|
||||
|
||||
#include <assert.h>
|
||||
#include <ctype.h>
|
||||
|
||||
#include "internal/filesystem.h"
|
||||
#include "internal/hwcaps.h"
|
||||
#include "internal/stack_line_reader.h"
|
||||
#include "internal/string_view.h"
|
||||
|
||||
// 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"
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// 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];
|
||||
}
|
84
src/define_introspection.inl
Normal file
84
src/define_introspection.inl
Normal file
@ -0,0 +1,84 @@
|
||||
// Copyright 2017 Google LLC
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#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) \
|
||||
void set_##ENUM(FEAT_TYPE_NAME* features, bool value) { \
|
||||
features->NAME = value; \
|
||||
} \
|
||||
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];
|
||||
}
|
26
src/define_introspection_and_hwcaps.inl
Normal file
26
src/define_introspection_and_hwcaps.inl
Normal file
@ -0,0 +1,26 @@
|
||||
// Copyright 2017 Google LLC
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include "define_introspection.inl"
|
||||
#include "internal/hwcaps.h"
|
||||
|
||||
#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
|
@ -1,67 +0,0 @@
|
||||
// Copyright 2020 Google LLC
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
// The following preprocessor constants must be defined before including this
|
||||
// file:
|
||||
// - DEFINE_TABLE_FEATURE_TYPE, the underlying type (e.g. X86Features)
|
||||
// - DEFINE_TABLE_FEATURES, the list of FEATURE macros to be inserted.
|
||||
|
||||
// This file is to be included once per `cpuinfo_XXX.c` in order to construct
|
||||
// feature getters and setters functions as well as several enum indexed tables
|
||||
// from the db file.
|
||||
// - `kGetters` a table of getters function pointers from feature enum to
|
||||
// retrieve a feature,
|
||||
// - `kSetters` a table of setters function pointers from feature enum to set a
|
||||
// feature,
|
||||
// - `kCpuInfoFlags` a table of strings from feature enum to /proc/cpuinfo
|
||||
// flags,
|
||||
// - `kHardwareCapabilities` a table of HardwareCapabilities structs indexed by
|
||||
// their feature enum.
|
||||
|
||||
#ifndef SRC_DEFINE_TABLES_H_
|
||||
#define SRC_DEFINE_TABLES_H_
|
||||
|
||||
#define FEATURE(ENUM, NAME, CPUINFO_FLAG, HWCAP, HWCAP2) [ENUM] = CPUINFO_FLAG,
|
||||
static const char* kCpuInfoFlags[] = {DEFINE_TABLE_FEATURES};
|
||||
#undef FEATURE
|
||||
|
||||
#ifndef DEFINE_TABLE_DONT_GENERATE_HWCAPS
|
||||
#define FEATURE(ENUM, NAME, CPUINFO_FLAG, HWCAP, HWCAP2) \
|
||||
[ENUM] = (HardwareCapabilities){HWCAP, HWCAP2},
|
||||
static const HardwareCapabilities kHardwareCapabilities[] = {
|
||||
DEFINE_TABLE_FEATURES};
|
||||
#undef FEATURE
|
||||
#endif // DEFINE_TABLE_DONT_GENERATE_HWCAPS
|
||||
|
||||
#define FEATURE(ENUM, NAME, CPUINFO_FLAG, HWCAP, HWCAP2) \
|
||||
static void set_##ENUM(DEFINE_TABLE_FEATURE_TYPE* features, bool value) { \
|
||||
features->NAME = value; \
|
||||
} \
|
||||
static int get_##ENUM(const DEFINE_TABLE_FEATURE_TYPE* features) { \
|
||||
return features->NAME; \
|
||||
}
|
||||
DEFINE_TABLE_FEATURES
|
||||
#undef FEATURE
|
||||
|
||||
#define FEATURE(ENUM, NAME, CPUINFO_FLAG, HWCAP, HWCAP2) [ENUM] = set_##ENUM,
|
||||
static void (*const kSetters[])(DEFINE_TABLE_FEATURE_TYPE*,
|
||||
bool) = {DEFINE_TABLE_FEATURES};
|
||||
#undef FEATURE
|
||||
|
||||
#define FEATURE(ENUM, NAME, CPUINFO_FLAG, HWCAP, HWCAP2) [ENUM] = get_##ENUM,
|
||||
static int (*const kGetters[])(const DEFINE_TABLE_FEATURE_TYPE*) = {
|
||||
DEFINE_TABLE_FEATURES};
|
||||
#undef FEATURE
|
||||
|
||||
#endif // SRC_DEFINE_TABLES_H_
|
37
src/equals.h
Normal file
37
src/equals.h
Normal file
@ -0,0 +1,37 @@
|
||||
// Copyright 2021 Google LLC
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
static bool equals(const char *lhs, const char *rhs, size_t count) {
|
||||
size_t offset = 0;
|
||||
|
||||
#define CHUNK_EQUALS(TYPE) \
|
||||
while (count - offset >= sizeof(TYPE)) { \
|
||||
TYPE l = *(const TYPE *)(lhs + offset); \
|
||||
TYPE r = *(const TYPE *)(rhs + offset); \
|
||||
if (l != r) return false; \
|
||||
offset += sizeof(TYPE); \
|
||||
}
|
||||
|
||||
CHUNK_EQUALS(uint64_t)
|
||||
CHUNK_EQUALS(uint32_t)
|
||||
CHUNK_EQUALS(uint16_t)
|
||||
CHUNK_EQUALS(uint8_t)
|
||||
#undef CHUNK_EQUALS
|
||||
|
||||
return true;
|
||||
}
|
150
src/impl_aarch64_linux_or_android.c
Normal file
150
src/impl_aarch64_linux_or_android.c
Normal file
@ -0,0 +1,150 @@
|
||||
// Copyright 2017 Google LLC
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#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 <stdbool.h>
|
||||
|
||||
#include "internal/bit_utils.h"
|
||||
#include "internal/filesystem.h"
|
||||
#include "internal/stack_line_reader.h"
|
||||
#include "internal/string_view.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
|
@ -12,50 +12,59 @@
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#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 <assert.h>
|
||||
#include <ctype.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 <stdbool.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"
|
||||
|
||||
// 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 {
|
||||
bool processor_reports_armv6;
|
||||
bool hardware_reports_goldfish;
|
||||
@ -197,16 +206,5 @@ ArmInfo GetArmInfo(void) {
|
||||
return info;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Introspection functions
|
||||
|
||||
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];
|
||||
}
|
||||
#endif // defined(CPU_FEATURES_OS_LINUX) || defined(CPU_FEATURES_OS_ANDROID)
|
||||
#endif // CPU_FEATURES_ARCH_ARM
|
@ -1,5 +1,3 @@
|
||||
// Copyright 2017 Google LLC
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
@ -12,24 +10,33 @@
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#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 <assert.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/hwcaps.h"
|
||||
#include "internal/stack_line_reader.h"
|
||||
#include "internal/string_view.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,
|
||||
MipsFeatures* const features) {
|
||||
StringView key, value;
|
||||
@ -77,16 +84,5 @@ MipsInfo GetMipsInfo(void) {
|
||||
return info;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Introspection functions
|
||||
|
||||
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];
|
||||
}
|
||||
#endif // defined(CPU_FEATURES_OS_LINUX) || defined(CPU_FEATURES_OS_ANDROID)
|
||||
#endif // CPU_FEATURES_ARCH_MIPS
|
@ -12,11 +12,72 @@
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include "cpu_features_macros.h"
|
||||
|
||||
#ifdef CPU_FEATURES_ARCH_PPC
|
||||
#ifdef CPU_FEATURES_OS_LINUX
|
||||
|
||||
#include "cpuinfo_ppc.h"
|
||||
|
||||
#include <assert.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 <stdbool.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "internal/bit_utils.h"
|
||||
#include "internal/filesystem.h"
|
||||
@ -24,59 +85,6 @@
|
||||
#include "internal/stack_line_reader.h"
|
||||
#include "internal/string_view.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;
|
||||
@ -150,16 +158,5 @@ PPCPlatformStrings GetPPCPlatformStrings(void) {
|
||||
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];
|
||||
}
|
||||
#endif // CPU_FEATURES_OS_LINUX
|
||||
#endif // CPU_FEATURES_ARCH_PPC
|
File diff suppressed because it is too large
Load Diff
66
src/impl_x86_freebsd.c
Normal file
66
src/impl_x86_freebsd.c
Normal file
@ -0,0 +1,66 @@
|
||||
// Copyright 2017 Google LLC
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#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) {
|
||||
// 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
|
56
src/impl_x86_linux_or_android.c
Normal file
56
src/impl_x86_linux_or_android.c
Normal file
@ -0,0 +1,56 @@
|
||||
// Copyright 2017 Google LLC
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#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) {
|
||||
// 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
|
56
src/impl_x86_macos.c
Normal file
56
src/impl_x86_macos.c
Normal file
@ -0,0 +1,56 @@
|
||||
// Copyright 2017 Google LLC
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#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
|
48
src/impl_x86_windows.c
Normal file
48
src/impl_x86_windows.c
Normal file
@ -0,0 +1,48 @@
|
||||
// Copyright 2017 Google LLC
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#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) {
|
||||
// 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
|
@ -16,11 +16,19 @@
|
||||
|
||||
#include <assert.h>
|
||||
#include <ctype.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "copy.h"
|
||||
#include "equals.h"
|
||||
|
||||
static const char* CpuFeatures_memchr(const char* ptr, size_t size, char c) {
|
||||
for (; ptr && *ptr != '\0'; ++ptr)
|
||||
if (*ptr == c) return ptr;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int CpuFeatures_StringView_IndexOfChar(const StringView view, char c) {
|
||||
if (view.ptr && view.size) {
|
||||
const char* const found = (const char*)memchr(view.ptr, c, view.size);
|
||||
const char* const found = CpuFeatures_memchr(view.ptr, view.size, c);
|
||||
if (found) {
|
||||
return (int)(found - view.ptr);
|
||||
}
|
||||
@ -48,14 +56,14 @@ int CpuFeatures_StringView_IndexOf(const StringView view,
|
||||
|
||||
bool CpuFeatures_StringView_IsEquals(const StringView a, const StringView b) {
|
||||
if (a.size == b.size) {
|
||||
return a.ptr == b.ptr || memcmp(a.ptr, b.ptr, b.size) == 0;
|
||||
return a.ptr == b.ptr || equals(a.ptr, b.ptr, b.size);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool CpuFeatures_StringView_StartsWith(const StringView a, const StringView b) {
|
||||
return a.ptr && b.ptr && b.size && a.size >= b.size
|
||||
? memcmp(a.ptr, b.ptr, b.size) == 0
|
||||
? equals(a.ptr, b.ptr, b.size)
|
||||
: false;
|
||||
}
|
||||
|
||||
@ -138,7 +146,7 @@ void CpuFeatures_StringView_CopyString(const StringView src, char* dst,
|
||||
const size_t max_copy_size = dst_size - 1;
|
||||
const size_t copy_size =
|
||||
src.size > max_copy_size ? max_copy_size : src.size;
|
||||
memcpy(dst, src.ptr, copy_size);
|
||||
copy(dst, src.ptr, copy_size);
|
||||
dst[copy_size] = '\0';
|
||||
}
|
||||
}
|
||||
|
@ -47,7 +47,13 @@ add_test(NAME stack_line_reader_test COMMAND stack_line_reader_test)
|
||||
##------------------------------------------------------------------------------
|
||||
## cpuinfo_x86_test
|
||||
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)
|
||||
if(APPLE)
|
||||
target_compile_definitions(cpuinfo_x86_test PRIVATE HAVE_SYSCTLBYNAME)
|
||||
@ -58,28 +64,28 @@ endif()
|
||||
##------------------------------------------------------------------------------
|
||||
## cpuinfo_arm_test
|
||||
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)
|
||||
add_test(NAME cpuinfo_arm_test COMMAND cpuinfo_arm_test)
|
||||
endif()
|
||||
##------------------------------------------------------------------------------
|
||||
## cpuinfo_aarch64_test
|
||||
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)
|
||||
target_link_libraries(cpuinfo_aarch64_test all_libraries)
|
||||
add_test(NAME cpuinfo_aarch64_test COMMAND cpuinfo_aarch64_test)
|
||||
endif()
|
||||
##------------------------------------------------------------------------------
|
||||
## cpuinfo_mips_test
|
||||
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)
|
||||
add_test(NAME cpuinfo_mips_test COMMAND cpuinfo_mips_test)
|
||||
endif()
|
||||
##------------------------------------------------------------------------------
|
||||
## cpuinfo_ppc_test
|
||||
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)
|
||||
add_test(NAME cpuinfo_ppc_test COMMAND cpuinfo_ppc_test)
|
||||
endif()
|
||||
|
@ -48,7 +48,7 @@ class FakeCpu {
|
||||
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 {
|
||||
return darwin_sysctlbyname_.count(name);
|
||||
}
|
||||
@ -56,7 +56,7 @@ class FakeCpu {
|
||||
void SetDarwinSysCtlByName(std::string name) {
|
||||
darwin_sysctlbyname_.insert(name);
|
||||
}
|
||||
#endif // CPU_FEATURES_OS_DARWIN
|
||||
#endif // CPU_FEATURES_OS_MACOS
|
||||
|
||||
#if defined(CPU_FEATURES_OS_WINDOWS)
|
||||
bool GetWindowsIsProcessorFeaturePresent(DWORD ProcessorFeature) {
|
||||
@ -70,9 +70,9 @@ class FakeCpu {
|
||||
|
||||
private:
|
||||
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_;
|
||||
#endif // CPU_FEATURES_OS_DARWIN
|
||||
#endif // CPU_FEATURES_OS_MACOS
|
||||
#if defined(CPU_FEATURES_OS_WINDOWS)
|
||||
std::set<DWORD> windows_isprocessorfeaturepresent_;
|
||||
#endif // CPU_FEATURES_OS_WINDOWS
|
||||
@ -92,11 +92,11 @@ extern "C" Leaf GetCpuidLeaf(uint32_t leaf_id, int ecx) {
|
||||
|
||||
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) {
|
||||
return cpu().GetDarwinSysCtlByName(name);
|
||||
}
|
||||
#endif // CPU_FEATURES_OS_DARWIN
|
||||
#endif // CPU_FEATURES_OS_MACOS
|
||||
|
||||
#if defined(CPU_FEATURES_OS_WINDOWS)
|
||||
extern "C" bool GetWindowsIsProcessorFeaturePresent(DWORD ProcessorFeature) {
|
||||
@ -771,7 +771,7 @@ TEST_F(CpuidX86Test, Nehalem) {
|
||||
cpu().SetWindowsIsProcessorFeaturePresent(PF_XMMI_INSTRUCTIONS_AVAILABLE);
|
||||
cpu().SetWindowsIsProcessorFeaturePresent(PF_XMMI64_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.sse2");
|
||||
cpu().SetDarwinSysCtlByName("hw.optional.sse3");
|
||||
@ -788,7 +788,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>
|
||||
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();
|
||||
fs.CreateFile("/proc/cpuinfo", R"(processor :
|
||||
flags : fpu mmx sse sse2 sse3 ssse3 sse4_1 sse4_2
|
||||
@ -853,7 +853,7 @@ TEST_F(CpuidX86Test, Atom) {
|
||||
cpu().SetWindowsIsProcessorFeaturePresent(PF_XMMI_INSTRUCTIONS_AVAILABLE);
|
||||
cpu().SetWindowsIsProcessorFeaturePresent(PF_XMMI64_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.sse2");
|
||||
cpu().SetDarwinSysCtlByName("hw.optional.sse3");
|
||||
@ -870,7 +870,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>
|
||||
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();
|
||||
fs.CreateFile("/proc/cpuinfo", R"(
|
||||
flags : fpu mmx sse sse2 sse3 ssse3 sse4_1 sse4_2
|
||||
@ -985,7 +985,7 @@ TEST_F(CpuidX86Test, P3) {
|
||||
cpu().SetOsBackupsExtendedRegisters(false);
|
||||
#if defined(CPU_FEATURES_OS_WINDOWS)
|
||||
cpu().SetWindowsIsProcessorFeaturePresent(PF_XMMI_INSTRUCTIONS_AVAILABLE);
|
||||
#elif defined(CPU_FEATURES_OS_DARWIN)
|
||||
#elif defined(CPU_FEATURES_OS_MACOS)
|
||||
cpu().SetDarwinSysCtlByName("hw.optional.sse");
|
||||
#elif defined(CPU_FEATURES_OS_FREEBSD)
|
||||
auto& fs = GetEmptyFilesystem();
|
||||
@ -996,7 +996,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>
|
||||
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();
|
||||
fs.CreateFile("/proc/cpuinfo", R"(
|
||||
flags : fpu mmx sse
|
||||
|
Loading…
x
Reference in New Issue
Block a user