diff --git a/CMakeLists.txt b/CMakeLists.txt index 73e1eb4..2138601 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -114,9 +114,7 @@ setup_include_and_definitions(utils) if(UNIX) add_library(unix_based_hardware_detection OBJECT ${PROJECT_SOURCE_DIR}/include/internal/hwcaps.h - ${PROJECT_SOURCE_DIR}/include/internal/unix_features_aggregator.h ${PROJECT_SOURCE_DIR}/src/hwcaps.c - ${PROJECT_SOURCE_DIR}/src/unix_features_aggregator.c ) setup_include_and_definitions(unix_based_hardware_detection) check_include_file(dlfcn.h HAVE_DLFCN_H) diff --git a/include/internal/hwcaps.h b/include/internal/hwcaps.h index 1c99e7b..62037c8 100644 --- a/include/internal/hwcaps.h +++ b/include/internal/hwcaps.h @@ -17,6 +17,7 @@ #ifndef CPU_FEATURES_INCLUDE_INTERNAL_HWCAPS_H_ #define CPU_FEATURES_INCLUDE_INTERNAL_HWCAPS_H_ +#include #include #include "cpu_features_macros.h" @@ -170,6 +171,8 @@ typedef struct { } HardwareCapabilities; HardwareCapabilities CpuFeatures_GetHardwareCapabilities(void); +bool CpuFeatures_IsHwCapsSet(const HardwareCapabilities hwcaps_mask, + const HardwareCapabilities hwcaps); typedef struct { char platform[64]; // 0 terminated string diff --git a/include/internal/unix_features_aggregator.h b/include/internal/unix_features_aggregator.h deleted file mode 100644 index 56abd6c..0000000 --- a/include/internal/unix_features_aggregator.h +++ /dev/null @@ -1,73 +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. - -// CapabilityConfig provides a way to map cpu features to hardware caps and -// /proc/cpuinfo flags. We then provide functions to update capabilities from -// either source. -#ifndef CPU_FEATURES_INCLUDE_INTERNAL_LINUX_FEATURES_AGGREGATOR_H_ -#define CPU_FEATURES_INCLUDE_INTERNAL_LINUX_FEATURES_AGGREGATOR_H_ - -#include -#include - -#include "cpu_features_macros.h" -#include "internal/hwcaps.h" -#include "internal/string_view.h" - -CPU_FEATURES_START_CPP_NAMESPACE - -// Use the following macro to declare setter functions to be used in -// CapabilityConfig. -#define DECLARE_SETTER(FeatureType, FeatureName) \ - static void set_##FeatureName(void* const features, bool value) { \ - ((FeatureType*)features)->FeatureName = value; \ - } - -// Use the following macro to declare getter functions to be used in -// CapabilityConfig. -#define DECLARE_GETTER(FeatureType, FeatureName) \ - static int get_##FeatureName(void* const features) { \ - return ((FeatureType*)features)->FeatureName; \ - } - -#define DECLARE_SETTER_AND_GETTER(FeatureType, FeatureName) \ - DECLARE_SETTER(FeatureType, FeatureName) \ - DECLARE_GETTER(FeatureType, FeatureName) - -// Describes the relationship between hardware caps and /proc/cpuinfo flags. -typedef struct { - const HardwareCapabilities hwcaps_mask; - const char* const proc_cpuinfo_flag; - void (*set_bit)(void* const, bool); // setter for the corresponding bit. - int (*get_bit)(void* const); // getter for the corresponding bit. -} CapabilityConfig; - -// For every config, looks into flags_line for the presence of the -// corresponding proc_cpuinfo_flag, calls `set_bit` accordingly. -// Note: features is a pointer to the underlying Feature struct. -void CpuFeatures_SetFromFlags(const size_t configs_size, - const CapabilityConfig* configs, - const StringView flags_line, - void* const features); - -// For every config, looks into hwcaps for the presence of the feature. Calls -// `set_bit` with true if the hardware capability is found. -// Note: features is a pointer to the underlying Feature struct. -void CpuFeatures_OverrideFromHwCaps(const size_t configs_size, - const CapabilityConfig* configs, - const HardwareCapabilities hwcaps, - void* const features); - -CPU_FEATURES_END_CPP_NAMESPACE -#endif // CPU_FEATURES_INCLUDE_INTERNAL_LINUX_FEATURES_AGGREGATOR_H_ diff --git a/src/cpuinfo_aarch64.c b/src/cpuinfo_aarch64.c index 195f96f..542663b 100644 --- a/src/cpuinfo_aarch64.c +++ b/src/cpuinfo_aarch64.c @@ -21,115 +21,12 @@ #include "internal/hwcaps.h" #include "internal/stack_line_reader.h" #include "internal/string_view.h" -#include "internal/unix_features_aggregator.h" -DECLARE_SETTER_AND_GETTER(Aarch64Features, fp) -DECLARE_SETTER_AND_GETTER(Aarch64Features, asimd) -DECLARE_SETTER_AND_GETTER(Aarch64Features, evtstrm) -DECLARE_SETTER_AND_GETTER(Aarch64Features, aes) -DECLARE_SETTER_AND_GETTER(Aarch64Features, pmull) -DECLARE_SETTER_AND_GETTER(Aarch64Features, sha1) -DECLARE_SETTER_AND_GETTER(Aarch64Features, sha2) -DECLARE_SETTER_AND_GETTER(Aarch64Features, crc32) -DECLARE_SETTER_AND_GETTER(Aarch64Features, atomics) -DECLARE_SETTER_AND_GETTER(Aarch64Features, fphp) -DECLARE_SETTER_AND_GETTER(Aarch64Features, asimdhp) -DECLARE_SETTER_AND_GETTER(Aarch64Features, cpuid) -DECLARE_SETTER_AND_GETTER(Aarch64Features, asimdrdm) -DECLARE_SETTER_AND_GETTER(Aarch64Features, jscvt) -DECLARE_SETTER_AND_GETTER(Aarch64Features, fcma) -DECLARE_SETTER_AND_GETTER(Aarch64Features, lrcpc) -DECLARE_SETTER_AND_GETTER(Aarch64Features, dcpop) -DECLARE_SETTER_AND_GETTER(Aarch64Features, sha3) -DECLARE_SETTER_AND_GETTER(Aarch64Features, sm3) -DECLARE_SETTER_AND_GETTER(Aarch64Features, sm4) -DECLARE_SETTER_AND_GETTER(Aarch64Features, asimddp) -DECLARE_SETTER_AND_GETTER(Aarch64Features, sha512) -DECLARE_SETTER_AND_GETTER(Aarch64Features, sve) -DECLARE_SETTER_AND_GETTER(Aarch64Features, asimdfhm) -DECLARE_SETTER_AND_GETTER(Aarch64Features, dit) -DECLARE_SETTER_AND_GETTER(Aarch64Features, uscat) -DECLARE_SETTER_AND_GETTER(Aarch64Features, ilrcpc) -DECLARE_SETTER_AND_GETTER(Aarch64Features, flagm) -DECLARE_SETTER_AND_GETTER(Aarch64Features, ssbs) -DECLARE_SETTER_AND_GETTER(Aarch64Features, sb) -DECLARE_SETTER_AND_GETTER(Aarch64Features, paca) -DECLARE_SETTER_AND_GETTER(Aarch64Features, pacg) -DECLARE_SETTER_AND_GETTER(Aarch64Features, dcpodp) -DECLARE_SETTER_AND_GETTER(Aarch64Features, sve2) -DECLARE_SETTER_AND_GETTER(Aarch64Features, sveaes) -DECLARE_SETTER_AND_GETTER(Aarch64Features, svepmull) -DECLARE_SETTER_AND_GETTER(Aarch64Features, svebitperm) -DECLARE_SETTER_AND_GETTER(Aarch64Features, svesha3) -DECLARE_SETTER_AND_GETTER(Aarch64Features, svesm4) -DECLARE_SETTER_AND_GETTER(Aarch64Features, flagm2) -DECLARE_SETTER_AND_GETTER(Aarch64Features, frint) -DECLARE_SETTER_AND_GETTER(Aarch64Features, svei8mm) -DECLARE_SETTER_AND_GETTER(Aarch64Features, svef32mm) -DECLARE_SETTER_AND_GETTER(Aarch64Features, svef64mm) -DECLARE_SETTER_AND_GETTER(Aarch64Features, svebf16) -DECLARE_SETTER_AND_GETTER(Aarch64Features, i8mm) -DECLARE_SETTER_AND_GETTER(Aarch64Features, bf16) -DECLARE_SETTER_AND_GETTER(Aarch64Features, dgh) -DECLARE_SETTER_AND_GETTER(Aarch64Features, rng) -DECLARE_SETTER_AND_GETTER(Aarch64Features, bti) - -static const CapabilityConfig kConfigs[] = { - // clang-format off - [AARCH64_FP] = {{AARCH64_HWCAP_FP, 0}, "fp", &set_fp, &get_fp}, - [AARCH64_ASIMD] = {{AARCH64_HWCAP_ASIMD, 0}, "asimd", &set_asimd, &get_asimd}, - [AARCH64_EVTSTRM] = {{AARCH64_HWCAP_EVTSTRM, 0}, "evtstrm", &set_evtstrm, &get_evtstrm}, - [AARCH64_AES] = {{AARCH64_HWCAP_AES, 0}, "aes", &set_aes, &get_aes}, - [AARCH64_PMULL] = {{AARCH64_HWCAP_PMULL, 0}, "pmull", &set_pmull, &get_pmull}, - [AARCH64_SHA1] = {{AARCH64_HWCAP_SHA1, 0}, "sha1", &set_sha1, &get_sha1}, - [AARCH64_SHA2] = {{AARCH64_HWCAP_SHA2, 0}, "sha2", &set_sha2, &get_sha2}, - [AARCH64_CRC32] = {{AARCH64_HWCAP_CRC32, 0}, "crc32", &set_crc32, &get_crc32}, - [AARCH64_ATOMICS] = {{AARCH64_HWCAP_ATOMICS, 0}, "atomics", &set_atomics, &get_atomics}, - [AARCH64_FPHP] = {{AARCH64_HWCAP_FPHP, 0}, "fphp", &set_fphp, &get_fphp}, - [AARCH64_ASIMDHP] = {{AARCH64_HWCAP_ASIMDHP, 0}, "asimdhp", &set_asimdhp, &get_asimdhp}, - [AARCH64_CPUID] = {{AARCH64_HWCAP_CPUID, 0}, "cpuid", &set_cpuid, &get_cpuid}, - [AARCH64_ASIMDRDM] = {{AARCH64_HWCAP_ASIMDRDM, 0}, "asimdrdm", &set_asimdrdm, &get_asimdrdm}, - [AARCH64_JSCVT] = {{AARCH64_HWCAP_JSCVT, 0}, "jscvt", &set_jscvt, &get_jscvt}, - [AARCH64_FCMA] = {{AARCH64_HWCAP_FCMA, 0}, "fcma", &set_fcma, &get_fcma}, - [AARCH64_LRCPC] = {{AARCH64_HWCAP_LRCPC, 0}, "lrcpc", &set_lrcpc, &get_lrcpc}, - [AARCH64_DCPOP] = {{AARCH64_HWCAP_DCPOP, 0}, "dcpop", &set_dcpop, &get_dcpop}, - [AARCH64_SHA3] = {{AARCH64_HWCAP_SHA3, 0}, "sha3", &set_sha3, &get_sha3}, - [AARCH64_SM3] = {{AARCH64_HWCAP_SM3, 0}, "sm3", &set_sm3, &get_sm3}, - [AARCH64_SM4] = {{AARCH64_HWCAP_SM4, 0}, "sm4", &set_sm4, &get_sm4}, - [AARCH64_ASIMDDP] = {{AARCH64_HWCAP_ASIMDDP, 0}, "asimddp", &set_asimddp, &get_asimddp}, - [AARCH64_SHA512] = {{AARCH64_HWCAP_SHA512, 0}, "sha512", &set_sha512, &get_sha512}, - [AARCH64_SVE] = {{AARCH64_HWCAP_SVE, 0}, "sve", &set_sve, &get_sve}, - [AARCH64_ASIMDFHM] = {{AARCH64_HWCAP_ASIMDFHM, 0}, "asimdfhm", &set_asimdfhm, &get_asimdfhm}, - [AARCH64_DIT] = {{AARCH64_HWCAP_DIT, 0}, "dit", &set_dit, &get_dit}, - [AARCH64_USCAT] = {{AARCH64_HWCAP_USCAT, 0}, "uscat", &set_uscat, &get_uscat}, - [AARCH64_ILRCPC] = {{AARCH64_HWCAP_ILRCPC, 0}, "ilrcpc", &set_ilrcpc, &get_ilrcpc}, - [AARCH64_FLAGM] = {{AARCH64_HWCAP_FLAGM, 0}, "flagm", &set_flagm, &get_flagm}, - [AARCH64_SSBS] = {{AARCH64_HWCAP_SSBS, 0}, "ssbs", &set_ssbs, &get_ssbs}, - [AARCH64_SB] = {{AARCH64_HWCAP_SB, 0}, "sb", &set_sb, &get_sb}, - [AARCH64_PACA] = {{AARCH64_HWCAP_PACA, 0}, "paca", &set_paca, &get_paca}, - [AARCH64_PACG] = {{AARCH64_HWCAP_PACG, 0}, "pacg", &set_pacg, &get_pacg}, - [AARCH64_DCPODP] = {{0, AARCH64_HWCAP2_DCPODP}, "dcpodp", &set_dcpodp, &get_dcpodp}, - [AARCH64_SVE2] = {{0, AARCH64_HWCAP2_SVE2}, "sve2", &set_sve2, &get_sve2}, - [AARCH64_SVEAES] = {{0, AARCH64_HWCAP2_SVEAES}, "sveaes", &set_sveaes, &get_sveaes}, - [AARCH64_SVEPMULL] = {{0, AARCH64_HWCAP2_SVEPMULL}, "svepmull", &set_svepmull, &get_svepmull}, - [AARCH64_SVEBITPERM] = {{0, AARCH64_HWCAP2_SVEBITPERM}, "svebitperm", &set_svebitperm, &get_svebitperm}, - [AARCH64_SVESHA3] = {{0, AARCH64_HWCAP2_SVESHA3}, "svesha3", &set_svesha3, &get_svesha3}, - [AARCH64_SVESM4] = {{0, AARCH64_HWCAP2_SVESM4}, "svesm4", &set_svesm4, &get_svesm4}, - [AARCH64_FLAGM2] = {{0, AARCH64_HWCAP2_FLAGM2}, "flagm2", &set_flagm2, &get_flagm2}, - [AARCH64_FRINT] = {{0, AARCH64_HWCAP2_FRINT}, "frint", &set_frint, &get_frint}, - [AARCH64_SVEI8MM] = {{0, AARCH64_HWCAP2_SVEI8MM}, "svei8mm", &set_svei8mm, &get_svei8mm}, - [AARCH64_SVEF32MM] = {{0, AARCH64_HWCAP2_SVEF32MM}, "svef32mm", &set_svef32mm, &get_svef32mm}, - [AARCH64_SVEF64MM] = {{0, AARCH64_HWCAP2_SVEF64MM}, "svef64mm", &set_svef64mm, &get_svef64mm}, - [AARCH64_SVEBF16] = {{0, AARCH64_HWCAP2_SVEBF16}, "svebf16", &set_svebf16, &get_svebf16}, - [AARCH64_I8MM] = {{0, AARCH64_HWCAP2_I8MM}, "i8mm", &set_i8mm, &get_i8mm}, - [AARCH64_BF16] = {{0, AARCH64_HWCAP2_BF16}, "bf16", &set_bf16, &get_bf16}, - [AARCH64_DGH] = {{0, AARCH64_HWCAP2_DGH}, "dgh", &set_dgh, &get_dgh}, - [AARCH64_RNG] = {{0, AARCH64_HWCAP2_RNG}, "rng", &set_rng, &get_rng}, - [AARCH64_BTI] = {{0, AARCH64_HWCAP2_BTI}, "bti", &set_bti, &get_bti}, - // clang-format on -}; - -static const size_t kConfigsSize = sizeof(kConfigs) / sizeof(CapabilityConfig); +// Generation of feature's getters/setters functions and kGetters, kSetters, +// kCpuInfoFlags and kHardwareCapabilities global tables. +#define DEFINE_TABLE_FEATURE_TYPE Aarch64Features +#define DEFINE_TABLE_DB_FILENAME "cpuinfo_aarch64_db.inl" +#include "define_tables.h" static bool HandleAarch64Line(const LineResult result, Aarch64Info* const info) { @@ -137,7 +34,10 @@ static bool HandleAarch64Line(const LineResult result, StringView key, value; if (CpuFeatures_StringView_GetAttributeKeyValue(line, &key, &value)) { if (CpuFeatures_StringView_IsEquals(key, str("Features"))) { - CpuFeatures_SetFromFlags(kConfigsSize, kConfigs, value, &info->features); + for (size_t i = 0; i < AARCH64_LAST_; ++i) { + kSetters[i](&info->features, + CpuFeatures_StringView_HasWord(value, kCpuInfoFlags[i])); + } } else if (CpuFeatures_StringView_IsEquals(key, str("CPU implementer"))) { info->implementer = CpuFeatures_StringView_ParsePositiveNumber(value); } else if (CpuFeatures_StringView_IsEquals(key, str("CPU variant"))) { @@ -168,17 +68,18 @@ static void FillProcCpuInfoData(Aarch64Info* const info) { static const Aarch64Info kEmptyAarch64Info; Aarch64Info GetAarch64Info(void) { - assert(kConfigsSize == AARCH64_LAST_); - // capabilities are fetched from both getauxval and /proc/cpuinfo so we can // have some information if the executable is sandboxed (aka no access to // /proc/cpuinfo). Aarch64Info info = kEmptyAarch64Info; FillProcCpuInfoData(&info); - CpuFeatures_OverrideFromHwCaps(kConfigsSize, kConfigs, - CpuFeatures_GetHardwareCapabilities(), - &info.features); + 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; } @@ -188,11 +89,11 @@ Aarch64Info GetAarch64Info(void) { int GetAarch64FeaturesEnumValue(const Aarch64Features* features, Aarch64FeaturesEnum value) { - if (value >= kConfigsSize) return false; - return kConfigs[value].get_bit((Aarch64Features*)features); + if (value >= AARCH64_LAST_) return false; + return kGetters[value](features); } const char* GetAarch64FeaturesEnumName(Aarch64FeaturesEnum value) { - if (value >= kConfigsSize) return "unknown feature"; - return kConfigs[value].proc_cpuinfo_flag; + if (value >= AARCH64_LAST_) return "unknown feature"; + return kCpuInfoFlags[value]; } diff --git a/src/cpuinfo_aarch64_db.inl b/src/cpuinfo_aarch64_db.inl new file mode 100644 index 0000000..b3200f4 --- /dev/null +++ b/src/cpuinfo_aarch64_db.inl @@ -0,0 +1,71 @@ +// 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. + +#if defined(FEATURE) +// FEATURE(ENUM, NAME, CPUINFO_FLAG, HWCAP, HWCAP2) +// clang-format off +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) +// clang-format on +#else +#error "The FEATURE macro must be defined" +#endif // FEATURE diff --git a/src/cpuinfo_arm.c b/src/cpuinfo_arm.c index 0895a53..add38ce 100644 --- a/src/cpuinfo_arm.c +++ b/src/cpuinfo_arm.c @@ -22,69 +22,12 @@ #include "internal/hwcaps.h" #include "internal/stack_line_reader.h" #include "internal/string_view.h" -#include "internal/unix_features_aggregator.h" -DECLARE_SETTER_AND_GETTER(ArmFeatures, swp) -DECLARE_SETTER_AND_GETTER(ArmFeatures, half) -DECLARE_SETTER_AND_GETTER(ArmFeatures, thumb) -DECLARE_SETTER_AND_GETTER(ArmFeatures, _26bit) -DECLARE_SETTER_AND_GETTER(ArmFeatures, fastmult) -DECLARE_SETTER_AND_GETTER(ArmFeatures, fpa) -DECLARE_SETTER_AND_GETTER(ArmFeatures, vfp) -DECLARE_SETTER_AND_GETTER(ArmFeatures, edsp) -DECLARE_SETTER_AND_GETTER(ArmFeatures, java) -DECLARE_SETTER_AND_GETTER(ArmFeatures, iwmmxt) -DECLARE_SETTER_AND_GETTER(ArmFeatures, crunch) -DECLARE_SETTER_AND_GETTER(ArmFeatures, thumbee) -DECLARE_SETTER_AND_GETTER(ArmFeatures, neon) -DECLARE_SETTER_AND_GETTER(ArmFeatures, vfpv3) -DECLARE_SETTER_AND_GETTER(ArmFeatures, vfpv3d16) -DECLARE_SETTER_AND_GETTER(ArmFeatures, tls) -DECLARE_SETTER_AND_GETTER(ArmFeatures, vfpv4) -DECLARE_SETTER_AND_GETTER(ArmFeatures, idiva) -DECLARE_SETTER_AND_GETTER(ArmFeatures, idivt) -DECLARE_SETTER_AND_GETTER(ArmFeatures, vfpd32) -DECLARE_SETTER_AND_GETTER(ArmFeatures, lpae) -DECLARE_SETTER_AND_GETTER(ArmFeatures, evtstrm) -DECLARE_SETTER_AND_GETTER(ArmFeatures, aes) -DECLARE_SETTER_AND_GETTER(ArmFeatures, pmull) -DECLARE_SETTER_AND_GETTER(ArmFeatures, sha1) -DECLARE_SETTER_AND_GETTER(ArmFeatures, sha2) -DECLARE_SETTER_AND_GETTER(ArmFeatures, crc32) - -static const CapabilityConfig kConfigs[] = { - // clang-format off - [ARM_SWP] = {{ARM_HWCAP_SWP, 0}, "swp", &set_swp, &get_swp}, - [ARM_HALF] = {{ARM_HWCAP_HALF, 0}, "half", &set_half, &get_half}, - [ARM_THUMB] = {{ARM_HWCAP_THUMB, 0}, "thumb", &set_thumb, &get_thumb}, - [ARM_26BIT] = {{ARM_HWCAP_26BIT, 0}, "26bit", &set__26bit, &get__26bit}, - [ARM_FASTMULT] = {{ARM_HWCAP_FAST_MULT, 0}, "fastmult", &set_fastmult, &get_fastmult}, - [ARM_FPA] = {{ARM_HWCAP_FPA, 0}, "fpa", &set_fpa, &get_fpa}, - [ARM_VFP] = {{ARM_HWCAP_VFP, 0}, "vfp", &set_vfp, &get_vfp}, - [ARM_EDSP] = {{ARM_HWCAP_EDSP, 0}, "edsp", &set_edsp, &get_edsp}, - [ARM_JAVA] = {{ARM_HWCAP_JAVA, 0}, "java", &set_java, &get_java}, - [ARM_IWMMXT] = {{ARM_HWCAP_IWMMXT, 0}, "iwmmxt", &set_iwmmxt, &get_iwmmxt}, - [ARM_CRUNCH] = {{ARM_HWCAP_CRUNCH, 0}, "crunch", &set_crunch, &get_crunch}, - [ARM_THUMBEE] = {{ARM_HWCAP_THUMBEE, 0}, "thumbee", &set_thumbee, &get_thumbee}, - [ARM_NEON] = {{ARM_HWCAP_NEON, 0}, "neon", &set_neon, &get_neon}, - [ARM_VFPV3] = {{ARM_HWCAP_VFPV3, 0}, "vfpv3", &set_vfpv3, &get_vfpv3}, - [ARM_VFPV3D16] = {{ARM_HWCAP_VFPV3D16, 0}, "vfpv3d16", &set_vfpv3d16, &get_vfpv3d16}, - [ARM_TLS] = {{ARM_HWCAP_TLS, 0}, "tls", &set_tls, &get_tls}, - [ARM_VFPV4] = {{ARM_HWCAP_VFPV4, 0}, "vfpv4", &set_vfpv4, &get_vfpv4}, - [ARM_IDIVA] = {{ARM_HWCAP_IDIVA, 0}, "idiva", &set_idiva, &get_idiva}, - [ARM_IDIVT] = {{ARM_HWCAP_IDIVT, 0}, "idivt", &set_idivt, &get_idivt}, - [ARM_VFPD32] = {{ARM_HWCAP_VFPD32, 0}, "vfpd32", &set_vfpd32, &get_vfpd32}, - [ARM_LPAE] = {{ARM_HWCAP_LPAE, 0}, "lpae", &set_lpae, &get_lpae}, - [ARM_EVTSTRM] = {{ARM_HWCAP_EVTSTRM, 0}, "evtstrm", &set_evtstrm, &get_evtstrm}, - [ARM_AES] = {{0, ARM_HWCAP2_AES}, "aes", &set_aes, &get_aes}, - [ARM_PMULL] = {{0, ARM_HWCAP2_PMULL}, "pmull", &set_pmull, &get_pmull}, - [ARM_SHA1] = {{0, ARM_HWCAP2_SHA1}, "sha1", &set_sha1, &get_sha1}, - [ARM_SHA2] = {{0, ARM_HWCAP2_SHA2}, "sha2", &set_sha2, &get_sha2}, - [ARM_CRC32] = {{0, ARM_HWCAP2_CRC32}, "crc32", &set_crc32, &get_crc32}, - // clang-format on -}; - -static const size_t kConfigsSize = sizeof(kConfigs) / sizeof(CapabilityConfig); +// Generation of feature's getters/setters functions and kGetters, kSetters, +// kCpuInfoFlags and kHardwareCapabilities global tables. +#define DEFINE_TABLE_FEATURE_TYPE ArmFeatures +#define DEFINE_TABLE_DB_FILENAME "cpuinfo_arm_db.inl" +#include "define_tables.h" typedef struct { bool processor_reports_armv6; @@ -106,7 +49,10 @@ static bool HandleArmLine(const LineResult result, ArmInfo* const info, StringView key, value; if (CpuFeatures_StringView_GetAttributeKeyValue(line, &key, &value)) { if (CpuFeatures_StringView_IsEquals(key, str("Features"))) { - CpuFeatures_SetFromFlags(kConfigsSize, kConfigs, value, &info->features); + for (size_t i = 0; i < ARM_LAST_; ++i) { + kSetters[i](&info->features, + CpuFeatures_StringView_HasWord(value, kCpuInfoFlags[i])); + } } else if (CpuFeatures_StringView_IsEquals(key, str("CPU implementer"))) { info->implementer = CpuFeatures_StringView_ParsePositiveNumber(value); } else if (CpuFeatures_StringView_IsEquals(key, str("CPU variant"))) { @@ -212,9 +158,12 @@ ArmInfo GetArmInfo(void) { ProcCpuInfoData proc_cpu_info_data = kEmptyProcCpuInfoData; FillProcCpuInfoData(&info, &proc_cpu_info_data); - CpuFeatures_OverrideFromHwCaps(kConfigsSize, kConfigs, - CpuFeatures_GetHardwareCapabilities(), - &info.features); + const HardwareCapabilities hwcaps = CpuFeatures_GetHardwareCapabilities(); + for (size_t i = 0; i < ARM_LAST_; ++i) { + if (CpuFeatures_IsHwCapsSet(kHardwareCapabilities[i], hwcaps)) { + kSetters[i](&info.features, true); + } + } FixErrors(&info, &proc_cpu_info_data); @@ -226,11 +175,11 @@ ArmInfo GetArmInfo(void) { int GetArmFeaturesEnumValue(const ArmFeatures* features, ArmFeaturesEnum value) { - if (value >= kConfigsSize) return false; - return kConfigs[value].get_bit((ArmFeatures*)features); + if (value >= ARM_LAST_) return false; + return kGetters[value](features); } const char* GetArmFeaturesEnumName(ArmFeaturesEnum value) { - if (value >= kConfigsSize) return "unknown feature"; - return kConfigs[value].proc_cpuinfo_flag; + if (value >= ARM_LAST_) return "unknown feature"; + return kCpuInfoFlags[value]; } diff --git a/src/cpuinfo_arm_db.inl b/src/cpuinfo_arm_db.inl new file mode 100644 index 0000000..3270389 --- /dev/null +++ b/src/cpuinfo_arm_db.inl @@ -0,0 +1,48 @@ +// 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. + +#if defined(FEATURE) +// FEATURE(ENUM, NAME, CPUINFO_FLAG, HWCAP, HWCAP2) +// clang-format off +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) +// clang-format on +#else +#error "The FEATURE macro must be defined" +#endif // FEATURE diff --git a/src/cpuinfo_mips.c b/src/cpuinfo_mips.c index 055cf21..8e71a31 100644 --- a/src/cpuinfo_mips.c +++ b/src/cpuinfo_mips.c @@ -17,20 +17,15 @@ #include #include "internal/filesystem.h" +#include "internal/hwcaps.h" #include "internal/stack_line_reader.h" #include "internal/string_view.h" -#include "internal/unix_features_aggregator.h" -DECLARE_SETTER_AND_GETTER(MipsFeatures, msa) -DECLARE_SETTER_AND_GETTER(MipsFeatures, eva) -DECLARE_SETTER_AND_GETTER(MipsFeatures, r6) - -static const CapabilityConfig kConfigs[] = { - [MIPS_MSA] = {{MIPS_HWCAP_MSA, 0}, "msa", &set_msa, &get_msa}, - [MIPS_EVA] = {{0, 0}, "eva", &set_eva, &get_eva}, - [MIPS_R6] = {{MIPS_HWCAP_R6, 0}, "r6", &set_r6, &get_r6}, -}; -static const size_t kConfigsSize = sizeof(kConfigs) / sizeof(CapabilityConfig); +// Generation of feature's getters/setters functions and kGetters, kSetters, +// kCpuInfoFlags and kHardwareCapabilities global tables. +#define DEFINE_TABLE_FEATURE_TYPE MipsFeatures +#define DEFINE_TABLE_DB_FILENAME "cpuinfo_mips_db.inl" +#include "define_tables.h" static bool HandleMipsLine(const LineResult result, MipsFeatures* const features) { @@ -38,7 +33,10 @@ static bool HandleMipsLine(const LineResult result, // See tests for an example. if (CpuFeatures_StringView_GetAttributeKeyValue(result.line, &key, &value)) { if (CpuFeatures_StringView_IsEquals(key, str("ASEs implemented"))) { - CpuFeatures_SetFromFlags(kConfigsSize, kConfigs, value, features); + for (size_t i = 0; i < MIPS_LAST_; ++i) { + kSetters[i](features, + CpuFeatures_StringView_HasWord(value, kCpuInfoFlags[i])); + } } } return !result.eof; @@ -61,17 +59,18 @@ static void FillProcCpuInfoData(MipsFeatures* const features) { static const MipsInfo kEmptyMipsInfo; MipsInfo GetMipsInfo(void) { - assert(kConfigsSize == MIPS_LAST_); - // capabilities are fetched from both getauxval and /proc/cpuinfo so we can // have some information if the executable is sandboxed (aka no access to // /proc/cpuinfo). MipsInfo info = kEmptyMipsInfo; FillProcCpuInfoData(&info.features); - CpuFeatures_OverrideFromHwCaps(kConfigsSize, kConfigs, - CpuFeatures_GetHardwareCapabilities(), - &info.features); + const HardwareCapabilities hwcaps = CpuFeatures_GetHardwareCapabilities(); + for (size_t i = 0; i < MIPS_LAST_; ++i) { + if (CpuFeatures_IsHwCapsSet(kHardwareCapabilities[i], hwcaps)) { + kSetters[i](&info.features, true); + } + } return info; } @@ -80,11 +79,11 @@ MipsInfo GetMipsInfo(void) { int GetMipsFeaturesEnumValue(const MipsFeatures* features, MipsFeaturesEnum value) { - if (value >= kConfigsSize) return false; - return kConfigs[value].get_bit((MipsFeatures*)features); + if (value >= MIPS_LAST_) return false; + return kGetters[value](features); } const char* GetMipsFeaturesEnumName(MipsFeaturesEnum value) { - if (value >= kConfigsSize) return "unknown feature"; - return kConfigs[value].proc_cpuinfo_flag; + if (value >= MIPS_LAST_) return "unknown feature"; + return kCpuInfoFlags[value]; } diff --git a/src/cpuinfo_mips_db.inl b/src/cpuinfo_mips_db.inl new file mode 100644 index 0000000..61edb2b --- /dev/null +++ b/src/cpuinfo_mips_db.inl @@ -0,0 +1,24 @@ +// 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. + +#if defined(FEATURE) +// FEATURE(ENUM, NAME, CPUINFO_FLAG, HWCAP, HWCAP2) +// clang-format off +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) +// clang-format on +#else +#error "The FEATURE macro must be defined" +#endif // FEATURE diff --git a/src/cpuinfo_ppc.c b/src/cpuinfo_ppc.c index 4353099..3be2935 100644 --- a/src/cpuinfo_ppc.c +++ b/src/cpuinfo_ppc.c @@ -22,96 +22,12 @@ #include "internal/filesystem.h" #include "internal/stack_line_reader.h" #include "internal/string_view.h" -#include "internal/unix_features_aggregator.h" -DECLARE_SETTER_AND_GETTER(PPCFeatures, ppc32) -DECLARE_SETTER_AND_GETTER(PPCFeatures, ppc64) -DECLARE_SETTER_AND_GETTER(PPCFeatures, ppc601) -DECLARE_SETTER_AND_GETTER(PPCFeatures, altivec) -DECLARE_SETTER_AND_GETTER(PPCFeatures, fpu) -DECLARE_SETTER_AND_GETTER(PPCFeatures, mmu) -DECLARE_SETTER_AND_GETTER(PPCFeatures, mac_4xx) -DECLARE_SETTER_AND_GETTER(PPCFeatures, unifiedcache) -DECLARE_SETTER_AND_GETTER(PPCFeatures, spe) -DECLARE_SETTER_AND_GETTER(PPCFeatures, efpsingle) -DECLARE_SETTER_AND_GETTER(PPCFeatures, efpdouble) -DECLARE_SETTER_AND_GETTER(PPCFeatures, no_tb) -DECLARE_SETTER_AND_GETTER(PPCFeatures, power4) -DECLARE_SETTER_AND_GETTER(PPCFeatures, power5) -DECLARE_SETTER_AND_GETTER(PPCFeatures, power5plus) -DECLARE_SETTER_AND_GETTER(PPCFeatures, cell) -DECLARE_SETTER_AND_GETTER(PPCFeatures, booke) -DECLARE_SETTER_AND_GETTER(PPCFeatures, smt) -DECLARE_SETTER_AND_GETTER(PPCFeatures, icachesnoop) -DECLARE_SETTER_AND_GETTER(PPCFeatures, arch205) -DECLARE_SETTER_AND_GETTER(PPCFeatures, pa6t) -DECLARE_SETTER_AND_GETTER(PPCFeatures, dfp) -DECLARE_SETTER_AND_GETTER(PPCFeatures, power6ext) -DECLARE_SETTER_AND_GETTER(PPCFeatures, arch206) -DECLARE_SETTER_AND_GETTER(PPCFeatures, vsx) -DECLARE_SETTER_AND_GETTER(PPCFeatures, pseries_perfmon_compat) -DECLARE_SETTER_AND_GETTER(PPCFeatures, truele) -DECLARE_SETTER_AND_GETTER(PPCFeatures, ppcle) -DECLARE_SETTER_AND_GETTER(PPCFeatures, arch207) -DECLARE_SETTER_AND_GETTER(PPCFeatures, htm) -DECLARE_SETTER_AND_GETTER(PPCFeatures, dscr) -DECLARE_SETTER_AND_GETTER(PPCFeatures, ebb) -DECLARE_SETTER_AND_GETTER(PPCFeatures, isel) -DECLARE_SETTER_AND_GETTER(PPCFeatures, tar) -DECLARE_SETTER_AND_GETTER(PPCFeatures, vcrypto) -DECLARE_SETTER_AND_GETTER(PPCFeatures, htm_nosc) -DECLARE_SETTER_AND_GETTER(PPCFeatures, arch300) -DECLARE_SETTER_AND_GETTER(PPCFeatures, ieee128) -DECLARE_SETTER_AND_GETTER(PPCFeatures, darn) -DECLARE_SETTER_AND_GETTER(PPCFeatures, scv) -DECLARE_SETTER_AND_GETTER(PPCFeatures, htm_no_suspend) - -static const CapabilityConfig kConfigs[] = { - // clang-format off - [PPC_32] = {{PPC_FEATURE_32, 0}, "ppc32", &set_ppc32, &get_ppc32}, - [PPC_64] = {{PPC_FEATURE_64, 0}, "ppc64", &set_ppc64, &get_ppc64}, - [PPC_601_INSTR] = {{PPC_FEATURE_601_INSTR, 0}, "ppc601", &set_ppc601, &get_ppc601}, - [PPC_HAS_ALTIVEC] = {{PPC_FEATURE_HAS_ALTIVEC, 0}, "altivec", &set_altivec, &get_altivec}, - [PPC_HAS_FPU] = {{PPC_FEATURE_HAS_FPU, 0}, "fpu", &set_fpu, &get_fpu}, - [PPC_HAS_MMU] = {{PPC_FEATURE_HAS_MMU, 0}, "mmu", &set_mmu, &get_mmu}, - [PPC_HAS_4xxMAC] = {{PPC_FEATURE_HAS_4xxMAC, 0}, "4xxmac", &set_mac_4xx, &get_mac_4xx}, - [PPC_UNIFIED_CACHE] = {{PPC_FEATURE_UNIFIED_CACHE, 0}, "ucache", &set_unifiedcache, &get_unifiedcache}, - [PPC_HAS_SPE] = {{PPC_FEATURE_HAS_SPE, 0}, "spe", &set_spe, &get_spe}, - [PPC_HAS_EFP_SINGLE] = {{PPC_FEATURE_HAS_EFP_SINGLE, 0}, "efpsingle", &set_efpsingle, &get_efpsingle}, - [PPC_HAS_EFP_DOUBLE] = {{PPC_FEATURE_HAS_EFP_DOUBLE, 0}, "efpdouble", &set_efpdouble, &get_efpdouble}, - [PPC_NO_TB] = {{PPC_FEATURE_NO_TB, 0}, "notb", &set_no_tb, &get_no_tb}, - [PPC_POWER4] = {{PPC_FEATURE_POWER4, 0}, "power4", &set_power4, &get_power4}, - [PPC_POWER5] = {{PPC_FEATURE_POWER5, 0}, "power5", &set_power5, &get_power5}, - [PPC_POWER5_PLUS] = {{PPC_FEATURE_POWER5_PLUS, 0}, "power5+", &set_power5plus, &get_power5plus}, - [PPC_CELL] = {{PPC_FEATURE_CELL, 0}, "cellbe", &set_cell, &get_cell}, - [PPC_BOOKE] = {{PPC_FEATURE_BOOKE, 0}, "booke", &set_booke, &get_booke}, - [PPC_SMT] = {{PPC_FEATURE_SMT, 0}, "smt", &set_smt, &get_smt}, - [PPC_ICACHE_SNOOP] = {{PPC_FEATURE_ICACHE_SNOOP, 0}, "ic_snoop", &set_icachesnoop, &get_icachesnoop}, - [PPC_ARCH_2_05] = {{PPC_FEATURE_ARCH_2_05, 0}, "arch_2_05", &set_arch205, &get_arch205}, - [PPC_PA6T] = {{PPC_FEATURE_PA6T, 0}, "pa6t", &set_pa6t, &get_pa6t}, - [PPC_HAS_DFP] = {{PPC_FEATURE_HAS_DFP, 0}, "dfp", &set_dfp, &get_dfp}, - [PPC_POWER6_EXT] = {{PPC_FEATURE_POWER6_EXT, 0}, "power6x", &set_power6ext, &get_power6ext}, - [PPC_ARCH_2_06] = {{PPC_FEATURE_ARCH_2_06, 0}, "arch_2_06", &set_arch206, &get_arch206}, - [PPC_HAS_VSX] = {{PPC_FEATURE_HAS_VSX, 0}, "vsx", &set_vsx, &get_vsx}, - [PPC_PSERIES_PERFMON_COMPAT] = {{PPC_FEATURE_PSERIES_PERFMON_COMPAT, 0}, "archpmu", &set_pseries_perfmon_compat, &get_pseries_perfmon_compat}, - [PPC_TRUE_LE] = {{PPC_FEATURE_TRUE_LE, 0}, "true_le", &set_truele, &get_truele}, - [PPC_PPC_LE] = {{PPC_FEATURE_PPC_LE, 0}, "ppcle", &set_ppcle, &get_ppcle}, - [PPC_ARCH_2_07] = {{0, PPC_FEATURE2_ARCH_2_07}, "arch_2_07", &set_arch207, &get_arch207}, - [PPC_HTM] = {{0, PPC_FEATURE2_HTM}, "htm", &set_htm, &get_htm}, - [PPC_DSCR] = {{0, PPC_FEATURE2_DSCR}, "dscr", &set_dscr, &get_dscr}, - [PPC_EBB] = {{0, PPC_FEATURE2_EBB}, "ebb", &set_ebb, &get_ebb}, - [PPC_ISEL] = {{0, PPC_FEATURE2_ISEL}, "isel", &set_isel, &get_isel}, - [PPC_TAR] = {{0, PPC_FEATURE2_TAR}, "tar", &set_tar, &get_tar}, - [PPC_VEC_CRYPTO] = {{0, PPC_FEATURE2_VEC_CRYPTO}, "vcrypto", &set_vcrypto, &get_vcrypto}, - [PPC_HTM_NOSC] = {{0, PPC_FEATURE2_HTM_NOSC}, "htm-nosc", &set_htm_nosc, &get_htm_nosc}, - [PPC_ARCH_3_00] = {{0, PPC_FEATURE2_ARCH_3_00}, "arch_3_00", &set_arch300, &get_arch300}, - [PPC_HAS_IEEE128] = {{0, PPC_FEATURE2_HAS_IEEE128}, "ieee128", &set_ieee128, &get_ieee128}, - [PPC_DARN] = {{0, PPC_FEATURE2_DARN}, "darn", &set_darn, &get_darn}, - [PPC_SCV] = {{0, PPC_FEATURE2_SCV}, "scv", &set_scv, &get_scv}, - [PPC_HTM_NO_SUSPEND] = {{0, PPC_FEATURE2_HTM_NO_SUSPEND}, "htm-no-suspend", &set_htm_no_suspend, &get_htm_no_suspend}, - // clang-format on -}; -static const size_t kConfigsSize = sizeof(kConfigs) / sizeof(CapabilityConfig); +// Generation of feature's getters/setters functions and kGetters, kSetters, +// kCpuInfoFlags and kHardwareCapabilities global tables. +#define DEFINE_TABLE_FEATURE_TYPE PPCFeatures +#define DEFINE_TABLE_DB_FILENAME "cpuinfo_ppc_db.inl" +#include "define_tables.h" static bool HandlePPCLine(const LineResult result, PPCPlatformStrings* const strings) { @@ -157,10 +73,12 @@ PPCInfo GetPPCInfo(void) { * the auxilary vector. */ PPCInfo info = kEmptyPPCInfo; - - CpuFeatures_OverrideFromHwCaps(kConfigsSize, kConfigs, - CpuFeatures_GetHardwareCapabilities(), - &info.features); + 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; } @@ -179,11 +97,11 @@ PPCPlatformStrings GetPPCPlatformStrings(void) { int GetPPCFeaturesEnumValue(const PPCFeatures* features, PPCFeaturesEnum value) { - if (value >= kConfigsSize) return false; - return kConfigs[value].get_bit((PPCFeatures*)features); + if (value >= PPC_LAST_) return false; + return kGetters[value](features); } const char* GetPPCFeaturesEnumName(PPCFeaturesEnum value) { - if (value >= kConfigsSize) return "unknown feature"; - return kConfigs[value].proc_cpuinfo_flag; + if (value >= PPC_LAST_) return "unknown feature"; + return kCpuInfoFlags[value]; } diff --git a/src/cpuinfo_ppc_db.inl b/src/cpuinfo_ppc_db.inl new file mode 100644 index 0000000..eb4aaf4 --- /dev/null +++ b/src/cpuinfo_ppc_db.inl @@ -0,0 +1,62 @@ +// 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. + +#if defined(FEATURE) +// FEATURE(ENUM, NAME, CPUINFO_FLAG, HWCAP, HWCAP2) +// clang-format off +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) +// clang-format on +#else +#error "The FEATURE macro must be defined" +#endif // FEATURE diff --git a/src/cpuinfo_x86.c b/src/cpuinfo_x86.c index 9254413..09c707a 100644 --- a/src/cpuinfo_x86.c +++ b/src/cpuinfo_x86.c @@ -25,6 +25,13 @@ #error "Cannot compile cpuinfo_x86 on a non x86 platform." #endif +// Generation of feature's getters/setters functions and kGetters, kSetters, +// kCpuInfoFlags global tables. +#define DEFINE_TABLE_FEATURE_TYPE X86Features +#define DEFINE_TABLE_DB_FILENAME "cpuinfo_x86_db.inl" +#define DEFINE_TABLE_DONT_GENERATE_HWCAPS +#include "define_tables.h" + // The following includes are necessary to provide SSE detections on pre-AVX // microarchitectures. #if defined(CPU_FEATURES_OS_WINDOWS) @@ -1486,259 +1493,13 @@ void FillX86BrandString(char brand_string[49]) { int GetX86FeaturesEnumValue(const X86Features* features, X86FeaturesEnum value) { - switch (value) { - case X86_FPU: - return features->fpu; - case X86_TSC: - return features->tsc; - case X86_CX8: - return features->cx8; - case X86_CLFSH: - return features->clfsh; - case X86_MMX: - return features->mmx; - case X86_AES: - return features->aes; - case X86_ERMS: - return features->erms; - case X86_F16C: - return features->f16c; - case X86_FMA4: - return features->fma4; - case X86_FMA3: - return features->fma3; - case X86_VAES: - return features->vaes; - case X86_VPCLMULQDQ: - return features->vpclmulqdq; - case X86_BMI1: - return features->bmi1; - case X86_HLE: - return features->hle; - case X86_BMI2: - return features->bmi2; - case X86_RTM: - return features->rtm; - case X86_RDSEED: - return features->rdseed; - case X86_CLFLUSHOPT: - return features->clflushopt; - case X86_CLWB: - return features->clwb; - case X86_SSE: - return features->sse; - case X86_SSE2: - return features->sse2; - case X86_SSE3: - return features->sse3; - case X86_SSSE3: - return features->ssse3; - case X86_SSE4_1: - return features->sse4_1; - case X86_SSE4_2: - return features->sse4_2; - case X86_SSE4A: - return features->sse4a; - case X86_AVX: - return features->avx; - case X86_AVX2: - return features->avx2; - case X86_AVX512F: - return features->avx512f; - case X86_AVX512CD: - return features->avx512cd; - case X86_AVX512ER: - return features->avx512er; - case X86_AVX512PF: - return features->avx512pf; - case X86_AVX512BW: - return features->avx512bw; - case X86_AVX512DQ: - return features->avx512dq; - case X86_AVX512VL: - return features->avx512vl; - case X86_AVX512IFMA: - return features->avx512ifma; - case X86_AVX512VBMI: - return features->avx512vbmi; - case X86_AVX512VBMI2: - return features->avx512vbmi2; - case X86_AVX512VNNI: - return features->avx512vnni; - case X86_AVX512BITALG: - return features->avx512bitalg; - case X86_AVX512VPOPCNTDQ: - return features->avx512vpopcntdq; - case X86_AVX512_4VNNIW: - return features->avx512_4vnniw; - case X86_AVX512_4VBMI2: - return features->avx512_4vbmi2; - case X86_AVX512_SECOND_FMA: - return features->avx512_second_fma; - case X86_AVX512_4FMAPS: - return features->avx512_4fmaps; - case X86_AVX512_BF16: - return features->avx512_bf16; - case X86_AVX512_VP2INTERSECT: - return features->avx512_vp2intersect; - case X86_AMX_BF16: - return features->amx_bf16; - case X86_AMX_TILE: - return features->amx_tile; - case X86_AMX_INT8: - return features->amx_int8; - case X86_PCLMULQDQ: - return features->pclmulqdq; - case X86_SMX: - return features->smx; - case X86_SGX: - return features->sgx; - case X86_CX16: - return features->cx16; - case X86_SHA: - return features->sha; - case X86_POPCNT: - return features->popcnt; - case X86_MOVBE: - return features->movbe; - case X86_RDRND: - return features->rdrnd; - case X86_DCA: - return features->dca; - case X86_SS: - return features->ss; - case X86_LAST_: - break; - } - return false; + if (value >= X86_LAST_) return false; + return kGetters[value](features); } const char* GetX86FeaturesEnumName(X86FeaturesEnum value) { - switch (value) { - case X86_FPU: - return "fpu"; - case X86_TSC: - return "tsc"; - case X86_CX8: - return "cx8"; - case X86_CLFSH: - return "clfsh"; - case X86_MMX: - return "mmx"; - case X86_AES: - return "aes"; - case X86_ERMS: - return "erms"; - case X86_F16C: - return "f16c"; - case X86_FMA4: - return "fma4"; - case X86_FMA3: - return "fma3"; - case X86_VAES: - return "vaes"; - case X86_VPCLMULQDQ: - return "vpclmulqdq"; - case X86_BMI1: - return "bmi1"; - case X86_HLE: - return "hle"; - case X86_BMI2: - return "bmi2"; - case X86_RTM: - return "rtm"; - case X86_RDSEED: - return "rdseed"; - case X86_CLFLUSHOPT: - return "clflushopt"; - case X86_CLWB: - return "clwb"; - case X86_SSE: - return "sse"; - case X86_SSE2: - return "sse2"; - case X86_SSE3: - return "sse3"; - case X86_SSSE3: - return "ssse3"; - case X86_SSE4_1: - return "sse4_1"; - case X86_SSE4_2: - return "sse4_2"; - case X86_SSE4A: - return "sse4a"; - case X86_AVX: - return "avx"; - case X86_AVX2: - return "avx2"; - case X86_AVX512F: - return "avx512f"; - case X86_AVX512CD: - return "avx512cd"; - case X86_AVX512ER: - return "avx512er"; - case X86_AVX512PF: - return "avx512pf"; - case X86_AVX512BW: - return "avx512bw"; - case X86_AVX512DQ: - return "avx512dq"; - case X86_AVX512VL: - return "avx512vl"; - case X86_AVX512IFMA: - return "avx512ifma"; - case X86_AVX512VBMI: - return "avx512vbmi"; - case X86_AVX512VBMI2: - return "avx512vbmi2"; - case X86_AVX512VNNI: - return "avx512vnni"; - case X86_AVX512BITALG: - return "avx512bitalg"; - case X86_AVX512VPOPCNTDQ: - return "avx512vpopcntdq"; - case X86_AVX512_4VNNIW: - return "avx512_4vnniw"; - case X86_AVX512_4VBMI2: - return "avx512_4vbmi2"; - case X86_AVX512_SECOND_FMA: - return "avx512_second_fma"; - case X86_AVX512_4FMAPS: - return "avx512_4fmaps"; - case X86_AVX512_BF16: - return "avx512_bf16"; - case X86_AVX512_VP2INTERSECT: - return "avx512_vp2intersect"; - case X86_AMX_BF16: - return "amx_bf16"; - case X86_AMX_TILE: - return "amx_tile"; - case X86_AMX_INT8: - return "amx_int8"; - case X86_PCLMULQDQ: - return "pclmulqdq"; - case X86_SMX: - return "smx"; - case X86_SGX: - return "sgx"; - case X86_CX16: - return "cx16"; - case X86_SHA: - return "sha"; - case X86_POPCNT: - return "popcnt"; - case X86_MOVBE: - return "movbe"; - case X86_RDRND: - return "rdrnd"; - case X86_DCA: - return "dca"; - case X86_SS: - return "ss"; - case X86_LAST_: - break; - } - return "unknown_feature"; + if (value >= X86_LAST_) return "unknown_feature"; + return kCpuInfoFlags[value]; } const char* GetX86MicroarchitectureName(X86Microarchitecture uarch) { diff --git a/src/cpuinfo_x86_db.inl b/src/cpuinfo_x86_db.inl new file mode 100644 index 0000000..3ea280d --- /dev/null +++ b/src/cpuinfo_x86_db.inl @@ -0,0 +1,81 @@ +// 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. + +#if defined(FEATURE) +// FEATURE(ENUM, NAME, CPUINFO_FLAG, HWCAP, HWCAP2) +// clang-format off +FEATURE(X86_FPU, fpu, "fpu", 0, 0) +FEATURE(X86_TSC, tsc, "tsc", 0, 0) +FEATURE(X86_CX8, cx8, "cx8", 0, 0) +FEATURE(X86_CLFSH, clfsh, "clfsh", 0, 0) +FEATURE(X86_MMX, mmx, "mmx", 0, 0) +FEATURE(X86_AES, aes, "aes", 0, 0) +FEATURE(X86_ERMS, erms, "erms", 0, 0) +FEATURE(X86_F16C, f16c, "f16c", 0, 0) +FEATURE(X86_FMA4, fma4, "fma4", 0, 0) +FEATURE(X86_FMA3, fma3, "fma3", 0, 0) +FEATURE(X86_VAES, vaes, "vaes", 0, 0) +FEATURE(X86_VPCLMULQDQ, vpclmulqdq, "vpclmulqdq", 0, 0) +FEATURE(X86_BMI1, bmi1, "bmi1", 0, 0) +FEATURE(X86_HLE, hle, "hle", 0, 0) +FEATURE(X86_BMI2, bmi2, "bmi2", 0, 0) +FEATURE(X86_RTM, rtm, "rtm", 0, 0) +FEATURE(X86_RDSEED, rdseed, "rdseed", 0, 0) +FEATURE(X86_CLFLUSHOPT, clflushopt, "clflushopt", 0, 0) +FEATURE(X86_CLWB, clwb, "clwb", 0, 0) +FEATURE(X86_SSE, sse, "sse", 0, 0) +FEATURE(X86_SSE2, sse2, "sse2", 0, 0) +FEATURE(X86_SSE3, sse3, "sse3", 0, 0) +FEATURE(X86_SSSE3, ssse3, "ssse3", 0, 0) +FEATURE(X86_SSE4_1, sse4_1, "sse4_1", 0, 0) +FEATURE(X86_SSE4_2, sse4_2, "sse4_2", 0, 0) +FEATURE(X86_SSE4A, sse4a, "sse4a", 0, 0) +FEATURE(X86_AVX, avx, "avx", 0, 0) +FEATURE(X86_AVX2, avx2, "avx2", 0, 0) +FEATURE(X86_AVX512F, avx512f, "avx512f", 0, 0) +FEATURE(X86_AVX512CD, avx512cd, "avx512cd", 0, 0) +FEATURE(X86_AVX512ER, avx512er, "avx512er", 0, 0) +FEATURE(X86_AVX512PF, avx512pf, "avx512pf", 0, 0) +FEATURE(X86_AVX512BW, avx512bw, "avx512bw", 0, 0) +FEATURE(X86_AVX512DQ, avx512dq, "avx512dq", 0, 0) +FEATURE(X86_AVX512VL, avx512vl, "avx512vl", 0, 0) +FEATURE(X86_AVX512IFMA, avx512ifma, "avx512ifma", 0, 0) +FEATURE(X86_AVX512VBMI, avx512vbmi, "avx512vbmi", 0, 0) +FEATURE(X86_AVX512VBMI2, avx512vbmi2, "avx512vbmi2", 0, 0) +FEATURE(X86_AVX512VNNI, avx512vnni, "avx512vnni", 0, 0) +FEATURE(X86_AVX512BITALG, avx512bitalg, "avx512bitalg", 0, 0) +FEATURE(X86_AVX512VPOPCNTDQ, avx512vpopcntdq, "avx512vpopcntdq", 0, 0) +FEATURE(X86_AVX512_4VNNIW, avx512_4vnniw, "avx512_4vnniw", 0, 0) +FEATURE(X86_AVX512_4VBMI2, avx512_4vbmi2, "avx512_4vbmi2", 0, 0) +FEATURE(X86_AVX512_SECOND_FMA, avx512_second_fma, "avx512_second_fma", 0, 0) +FEATURE(X86_AVX512_4FMAPS, avx512_4fmaps, "avx512_4fmaps", 0, 0) +FEATURE(X86_AVX512_BF16, avx512_bf16, "avx512_bf16", 0, 0) +FEATURE(X86_AVX512_VP2INTERSECT, avx512_vp2intersect, "avx512_vp2intersect", 0, 0) +FEATURE(X86_AMX_BF16, amx_bf16, "amx_bf16", 0, 0) +FEATURE(X86_AMX_TILE, amx_tile, "amx_tile", 0, 0) +FEATURE(X86_AMX_INT8, amx_int8, "amx_int8", 0, 0) +FEATURE(X86_PCLMULQDQ, pclmulqdq, "pclmulqdq", 0, 0) +FEATURE(X86_SMX, smx, "smx", 0, 0) +FEATURE(X86_SGX, sgx, "sgx", 0, 0) +FEATURE(X86_CX16, cx16, "cx16", 0, 0) +FEATURE(X86_SHA, sha, "sha", 0, 0) +FEATURE(X86_POPCNT, popcnt, "popcnt", 0, 0) +FEATURE(X86_MOVBE, movbe, "movbe", 0, 0) +FEATURE(X86_RDRND, rdrnd, "rdrnd", 0, 0) +FEATURE(X86_DCA, dca, "dca", 0, 0) +FEATURE(X86_SS, ss, "ss", 0, 0) +// clang-format on +#else +#error "The FEATURE macro must be defined" +#endif // FEATURE diff --git a/src/define_tables.h b/src/define_tables.h new file mode 100644 index 0000000..cb5ff37 --- /dev/null +++ b/src/define_tables.h @@ -0,0 +1,72 @@ +// 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_DB_FILENAME, the db file (e.g. "cpuinfo_x86_db.inl") + +// 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[] = { +#include DEFINE_TABLE_DB_FILENAME +}; +#undef FEATURE + +#ifndef DEFINE_TABLE_DONT_GENERATE_HWCAPS +#define FEATURE(ENUM, NAME, CPUINFO_FLAG, HWCAP, HWCAP2) \ + [ENUM] = (HardwareCapabilities){HWCAP, HWCAP2}, +static const HardwareCapabilities kHardwareCapabilities[] = { +#include DEFINE_TABLE_DB_FILENAME +}; +#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; \ + } +#include DEFINE_TABLE_DB_FILENAME +#undef FEATURE + +#define FEATURE(ENUM, NAME, CPUINFO_FLAG, HWCAP, HWCAP2) [ENUM] = set_##ENUM, +static void (*const kSetters[])(DEFINE_TABLE_FEATURE_TYPE*, bool) = { +#include DEFINE_TABLE_DB_FILENAME +}; +#undef FEATURE + +#define FEATURE(ENUM, NAME, CPUINFO_FLAG, HWCAP, HWCAP2) [ENUM] = get_##ENUM, +static int (*const kGetters[])(const DEFINE_TABLE_FEATURE_TYPE*) = { +#include DEFINE_TABLE_DB_FILENAME +}; +#undef FEATURE + +#endif // SRC_DEFINE_TABLES_H_ diff --git a/src/hwcaps.c b/src/hwcaps.c index 1592d17..dd17e3b 100644 --- a/src/hwcaps.c +++ b/src/hwcaps.c @@ -21,6 +21,24 @@ #include "internal/filesystem.h" #include "internal/string_view.h" +static bool IsSet(const uint32_t mask, const uint32_t value) { + if (mask == 0) return false; + return (value & mask) == mask; +} + +bool CpuFeatures_IsHwCapsSet(const HardwareCapabilities hwcaps_mask, + const HardwareCapabilities hwcaps) { + return IsSet(hwcaps_mask.hwcaps, hwcaps.hwcaps) || + IsSet(hwcaps_mask.hwcaps2, hwcaps.hwcaps2); +} + +#ifdef CPU_FEATURES_TEST +// In test mode, hwcaps_for_testing will define the following functions. +HardwareCapabilities CpuFeatures_GetHardwareCapabilities(void); +PlatformType CpuFeatures_GetPlatformType(void); +#else + +// Debug facilities #if defined(NDEBUG) #define D(...) #else @@ -36,9 +54,12 @@ // Implementation of GetElfHwcapFromGetauxval //////////////////////////////////////////////////////////////////////////////// -#if defined(CPU_FEATURES_MOCK_GET_ELF_HWCAP_FROM_GETAUXVAL) -// Implementation will be provided by test/hwcaps_for_testing.cc. -#elif defined(HAVE_STRONG_GETAUXVAL) +#define AT_HWCAP 16 +#define AT_HWCAP2 26 +#define AT_PLATFORM 15 +#define AT_BASE_PLATFORM 24 + +#if defined(HAVE_STRONG_GETAUXVAL) #include static unsigned long GetElfHwcapFromGetauxval(uint32_t hwcap_type) { return getauxval(hwcap_type); @@ -60,10 +81,6 @@ static unsigned long GetElfHwcapFromGetauxval(uint32_t hwcap_type) { // initialization layer. #include -#define AT_HWCAP 16 -#define AT_HWCAP2 26 -#define AT_PLATFORM 15 -#define AT_BASE_PLATFORM 24 typedef unsigned long getauxval_func_t(unsigned long); @@ -161,3 +178,5 @@ PlatformType CpuFeatures_GetPlatformType(void) { sizeof(type.base_platform)); return type; } + +#endif // CPU_FEATURES_TEST diff --git a/src/unix_features_aggregator.c b/src/unix_features_aggregator.c deleted file mode 100644 index cc79d14..0000000 --- a/src/unix_features_aggregator.c +++ /dev/null @@ -1,53 +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 "internal/unix_features_aggregator.h" - -#include "internal/string_view.h" - -void CpuFeatures_SetFromFlags(const size_t configs_size, - const CapabilityConfig* configs, - const StringView flags_line, - void* const features) { - size_t i = 0; - for (; i < configs_size; ++i) { - const CapabilityConfig config = configs[i]; - config.set_bit(features, CpuFeatures_StringView_HasWord( - flags_line, config.proc_cpuinfo_flag)); - } -} - -static bool IsSet(const uint32_t mask, const uint32_t value) { - if (mask == 0) return false; - return (value & mask) == mask; -} - -static bool IsHwCapsSet(const HardwareCapabilities hwcaps_mask, - const HardwareCapabilities hwcaps) { - return IsSet(hwcaps_mask.hwcaps, hwcaps.hwcaps) || - IsSet(hwcaps_mask.hwcaps2, hwcaps.hwcaps2); -} - -void CpuFeatures_OverrideFromHwCaps(const size_t configs_size, - const CapabilityConfig* configs, - const HardwareCapabilities hwcaps, - void* const features) { - size_t i = 0; - for (; i < configs_size; ++i) { - const CapabilityConfig* config = &configs[i]; - if (IsHwCapsSet(config->hwcaps_mask, hwcaps)) { - config->set_bit(features, true); - } - } -} diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 834eec1..c10e617 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -12,7 +12,6 @@ add_library(filesystem_for_testing filesystem_for_testing.cc) target_compile_definitions(filesystem_for_testing PUBLIC CPU_FEATURES_MOCK_FILESYSTEM) ##------------------------------------------------------------------------------ add_library(hwcaps_for_testing hwcaps_for_testing.cc) -target_compile_definitions(hwcaps_for_testing PUBLIC CPU_FEATURES_MOCK_GET_ELF_HWCAP_FROM_GETAUXVAL) target_link_libraries(hwcaps_for_testing filesystem_for_testing) ##------------------------------------------------------------------------------ add_library(stack_line_reader ../src/stack_line_reader.c) @@ -23,7 +22,7 @@ add_library(stack_line_reader_for_test ../src/stack_line_reader.c) target_compile_definitions(stack_line_reader_for_test PUBLIC STACK_LINE_READER_BUFFER_SIZE=16) target_link_libraries(stack_line_reader_for_test string_view filesystem_for_testing) ##------------------------------------------------------------------------------ -add_library(all_libraries ../src/stack_line_reader.c ../src/unix_features_aggregator.c) +add_library(all_libraries ../src/hwcaps.c ../src/stack_line_reader.c) target_link_libraries(all_libraries hwcaps_for_testing stack_line_reader string_view) # @@ -46,11 +45,6 @@ add_executable(stack_line_reader_test stack_line_reader_test.cc) target_link_libraries(stack_line_reader_test stack_line_reader_for_test) add_test(NAME stack_line_reader_test COMMAND stack_line_reader_test) ##------------------------------------------------------------------------------ -## unix_features_aggregator_test -add_executable(unix_features_aggregator_test unix_features_aggregator_test.cc) -target_link_libraries(unix_features_aggregator_test all_libraries) -add_test(NAME unix_features_aggregator_test COMMAND unix_features_aggregator_test) -##------------------------------------------------------------------------------ ## cpuinfo_x86_test if(PROCESSOR_IS_X86) add_executable(cpuinfo_x86_test cpuinfo_x86_test.cc ../src/cpuinfo_x86.c) diff --git a/test/unix_features_aggregator_test.cc b/test/unix_features_aggregator_test.cc deleted file mode 100644 index 3a36804..0000000 --- a/test/unix_features_aggregator_test.cc +++ /dev/null @@ -1,105 +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 "internal/unix_features_aggregator.h" - -#include - -#include "gtest/gtest.h" - -namespace cpu_features { - -namespace { - -struct Features { - bool a = false; - bool b = false; - bool c = false; -}; - -enum eFeatures { TEST_a, TEST_b, TEST_c }; - -DECLARE_SETTER_AND_GETTER(Features, a) -DECLARE_SETTER_AND_GETTER(Features, b) -DECLARE_SETTER_AND_GETTER(Features, c) - -class LinuxFeatureAggregatorTest : public testing::Test { - public: - const std::array kConfigs = { - {{{0b0001, 0b0000}, "a", &set_a, &get_a}, - {{0b0010, 0b0000}, "b", &set_b, &get_b}, - {{0b0000, 0b1100}, "c", &set_c, &get_c}}}; -}; - -TEST_F(LinuxFeatureAggregatorTest, FromFlagsEmpty) { - Features features; - CpuFeatures_SetFromFlags(kConfigs.size(), kConfigs.data(), str(""), - &features); - EXPECT_FALSE(features.a); - EXPECT_FALSE(features.b); - EXPECT_FALSE(features.c); - - EXPECT_FALSE(kConfigs[TEST_a].get_bit(&features)); -} - -TEST_F(LinuxFeatureAggregatorTest, FromFlagsAllSet) { - Features features; - CpuFeatures_SetFromFlags(kConfigs.size(), kConfigs.data(), str("a c b"), - &features); - EXPECT_TRUE(features.a); - EXPECT_TRUE(features.b); - EXPECT_TRUE(features.c); - - EXPECT_TRUE(kConfigs[TEST_a].get_bit(&features)); -} - -TEST_F(LinuxFeatureAggregatorTest, FromFlagsOnlyA) { - Features features; - CpuFeatures_SetFromFlags(kConfigs.size(), kConfigs.data(), str("a"), - &features); - EXPECT_TRUE(features.a); - EXPECT_FALSE(features.b); - EXPECT_FALSE(features.c); - - EXPECT_TRUE(kConfigs[TEST_a].get_bit(&features)); - EXPECT_FALSE(kConfigs[TEST_b].get_bit(&features)); - EXPECT_FALSE(kConfigs[TEST_c].get_bit(&features)); -} - -TEST_F(LinuxFeatureAggregatorTest, FromHwcapsNone) { - HardwareCapabilities capability; - capability.hwcaps = 0; // matches none - capability.hwcaps2 = 0; // matches none - Features features; - CpuFeatures_OverrideFromHwCaps(kConfigs.size(), kConfigs.data(), capability, - &features); - EXPECT_FALSE(features.a); - EXPECT_FALSE(features.b); - EXPECT_FALSE(features.c); -} - -TEST_F(LinuxFeatureAggregatorTest, FromHwcapsSet) { - HardwareCapabilities capability; - capability.hwcaps = 0b0010; // matches b but not a - capability.hwcaps2 = 0b1111; // matches c - Features features; - CpuFeatures_OverrideFromHwCaps(kConfigs.size(), kConfigs.data(), capability, - &features); - EXPECT_FALSE(features.a); - EXPECT_TRUE(features.b); - EXPECT_TRUE(features.c); -} - -} // namespace -} // namespace cpu_features