From aaede83bda9ee2edff7348d83dbbc71ab163b580 Mon Sep 17 00:00:00 2001 From: Mykola Hohsdze Date: Wed, 1 Feb 2023 03:31:08 +0200 Subject: [PATCH 01/10] Add FreeBSD Arm64 detection Getting all the features is handled by reading /var/run/dmesg.boot. Feature detections were taken from the freebsd kernel code sys/arm64/arm64/identcpu.c --- src/impl_aarch64_freebsd.c | 359 +++++++++++++++++++++++++++++++++++++ 1 file changed, 359 insertions(+) create mode 100644 src/impl_aarch64_freebsd.c diff --git a/src/impl_aarch64_freebsd.c b/src/impl_aarch64_freebsd.c new file mode 100644 index 00000000..de11b022 --- /dev/null +++ b/src/impl_aarch64_freebsd.c @@ -0,0 +1,359 @@ +#include "cpu_features_macros.h" + +#ifdef CPU_FEATURES_ARCH_AARCH64 +#ifdef CPU_FEATURES_OS_FREEBSD + +#include "cpuinfo_aarch64.h" + +//////////////////////////////////////////////////////////////////////////////// +// Definitions for introspection. +//////////////////////////////////////////////////////////////////////////////// +#define INTROSPECTION_TABLE \ + LINE(AARCH64_FP, fp, , , ) \ + LINE(AARCH64_ASIMD, asimd, , , ) \ + LINE(AARCH64_EVTSTRM, evtstrm, , , ) \ + LINE(AARCH64_AES, aes, , , ) \ + LINE(AARCH64_PMULL, pmull, , , ) \ + LINE(AARCH64_SHA1, sha1, , , ) \ + LINE(AARCH64_SHA2, sha2, , , ) \ + LINE(AARCH64_CRC32, crc32, , , ) \ + LINE(AARCH64_ATOMICS, atomics, , , ) \ + LINE(AARCH64_FPHP, fphp, , , ) \ + LINE(AARCH64_ASIMDHP, asimdhp, , , ) \ + LINE(AARCH64_CPUID, cpuid, , , ) \ + LINE(AARCH64_ASIMDRDM, asimdrdm, , , ) \ + LINE(AARCH64_JSCVT, jscvt, , , ) \ + LINE(AARCH64_FCMA, fcma, , , ) \ + LINE(AARCH64_LRCPC, lrcpc, , , ) \ + LINE(AARCH64_DCPOP, dcpop, , , ) \ + LINE(AARCH64_SHA3, sha3, , , ) \ + LINE(AARCH64_SM3, sm3, , , ) \ + LINE(AARCH64_SM4, sm4, , , ) \ + LINE(AARCH64_ASIMDDP, asimddp, , , ) \ + LINE(AARCH64_SHA512, sha512, , , ) \ + LINE(AARCH64_SVE, sve, , , ) \ + LINE(AARCH64_ASIMDFHM, asimdfhm, , , ) \ + LINE(AARCH64_DIT, dit, , , ) \ + LINE(AARCH64_USCAT, uscat, , , ) \ + LINE(AARCH64_ILRCPC, ilrcpc, , , ) \ + LINE(AARCH64_FLAGM, flagm, , , ) \ + LINE(AARCH64_SSBS, ssbs, , , ) \ + LINE(AARCH64_SB, sb, , , ) \ + LINE(AARCH64_PACA, paca, , , ) \ + LINE(AARCH64_PACG, pacg, , , ) \ + LINE(AARCH64_DCPODP, dcpodp, , , ) \ + LINE(AARCH64_SVE2, sve2, , , ) \ + LINE(AARCH64_SVEAES, sveaes, , , ) \ + LINE(AARCH64_SVEPMULL, svepmull, , , ) \ + LINE(AARCH64_SVEBITPERM, svebitperm, , , ) \ + LINE(AARCH64_SVESHA3, svesha3, , , ) \ + LINE(AARCH64_SVESM4, svesm4, , , ) \ + LINE(AARCH64_FLAGM2, flagm2, , , ) \ + LINE(AARCH64_FRINT, frint, , , ) \ + LINE(AARCH64_SVEI8MM, svei8mm, , , ) \ + LINE(AARCH64_SVEF32MM, svef32mm, , , ) \ + LINE(AARCH64_SVEF64MM, svef64mm, , , ) \ + LINE(AARCH64_SVEBF16, svebf16, , , ) \ + LINE(AARCH64_I8MM, i8mm, , , ) \ + LINE(AARCH64_BF16, bf16, , , ) \ + LINE(AARCH64_DGH, dgh, , , ) \ + LINE(AARCH64_RNG, rng, , , ) \ + LINE(AARCH64_BTI, bti, , , ) \ + LINE(AARCH64_MTE, mte, , , ) \ + LINE(AARCH64_ECV, ecv, , , ) \ + LINE(AARCH64_AFP, afp, , , ) \ + LINE(AARCH64_RPRES, rpres, , , ) +#define INTROSPECTION_PREFIX Aarch64 +#define INTROSPECTION_ENUM_PREFIX AARCH64 +#include "define_introspection.inl" + +//////////////////////////////////////////////////////////////////////////////// +// Implementation. +//////////////////////////////////////////////////////////////////////////////// + +#include "internal/filesystem.h" +#include "internal/stack_line_reader.h" +#include "internal/string_view.h" + +static const Aarch64Info kEmptyAarch64Info; + +#define ID_AA64ISAR0_KEY " Instruction Set Attributes 0" +#define ID_AA64ISAR1_KEY " Instruction Set Attributes 1" +#define ID_AA64ISAR2_KEY " Instruction Set Attributes 2" +#define ID_AA64PFR0_KEY " Processor Features 0" +#define ID_AA64PFR1_KEY " Processor Features 1" +#define ID_AA64ZFR0_KEY " SVE Features 0" + +typedef struct { + const char* name; + Aarch64FeaturesEnum* features_enum; +} MrsFeature; + +#define MRS_FEATURE(feature, mrs_prefix, feat_suffix) \ + (MrsFeature) { feature, mrs_prefix##_##feat_suffix } + +#define MRS_FEATURE_END \ + (MrsFeature) { NULL, NULL } + +#define ID_AA64ISAR0_SET_FEATURE(feat_name, feature) \ + MRS_FEATURE(feature, id_aa64isar0, feat_name) + +#define ID_AA64ISAR1_SET_FEATURE(feat_name, feature) \ + MRS_FEATURE(feature, id_aa64isar1, feat_name) + +#define ID_AA64ISAR2_SET_FEATURE(feat_name, feature) \ + MRS_FEATURE(feature, id_aa64isar2, feat_name) + +#define ID_AA64PFR0_SET_FEATURE(feat_name, feature) \ + MRS_FEATURE(feature, id_aa64pfr0, feat_name) + +#define ID_AA64PFR1_SET_FEATURE(feat_name, feature) \ + MRS_FEATURE(feature, id_aa64pfr1, feat_name) + +#define ID_AA64ZFR0_SET_FEATURE(feat_name, feature) \ + MRS_FEATURE(feature, id_aa64zfr0, feat_name) + +typedef struct { + const char* key; + MrsFeature* features; +} MrsField; + +#define MRS_FIELD(mrs, mrs_features) \ + (MrsField) { mrs, mrs_features } + +#define MRS_FIELD_END \ + (MrsField) { NULL, NULL } + +#define AARCH64_FEAT_END AARCH64_LAST_ + +#define MRS_FEATURES(mrs_name, feat_name, ...) \ + static Aarch64FeaturesEnum mrs_name##_##feat_name[] = { \ + __VA_ARGS__, \ + AARCH64_FEAT_END, \ + }; + +#define ID_AA64ISAR0_FEATURES(feat_name, ...) \ + MRS_FEATURES(id_aa64isar0, feat_name, __VA_ARGS__) + +#define ID_AA64ISAR1_FEATURES(feat_name, ...) \ + MRS_FEATURES(id_aa64isar1, feat_name, __VA_ARGS__) + +#define ID_AA64ISAR2_FEATURES(feat_name, ...) \ + MRS_FEATURES(id_aa64isar2, feat_name, __VA_ARGS__) + +#define ID_AA64PFR0_FEATURES(feat_name, ...) \ + MRS_FEATURES(id_aa64pfr0, feat_name, __VA_ARGS__) + +#define ID_AA64PFR1_FEATURES(feat_name, ...) \ + MRS_FEATURES(id_aa64pfr1, feat_name, __VA_ARGS__) + +#define ID_AA64ZFR0_FEATURES(feat_name, ...) \ + MRS_FEATURES(id_aa64zfr0, feat_name, __VA_ARGS__) + +// ID_AA64ISAR0_EL1 +// ----------------------------------------------------------------------------- +ID_AA64ISAR0_FEATURES(fhm, AARCH64_ASIMDFHM) +ID_AA64ISAR0_FEATURES(dp, AARCH64_ASIMDDP) +ID_AA64ISAR0_FEATURES(crc32, AARCH64_CRC32) +ID_AA64ISAR0_FEATURES(rdm, AARCH64_ASIMDRDM) +ID_AA64ISAR0_FEATURES(atomics, AARCH64_ATOMICS) +ID_AA64ISAR0_FEATURES(aes, AARCH64_AES) +ID_AA64ISAR0_FEATURES(sha1, AARCH64_SHA1) +ID_AA64ISAR0_FEATURES(sha2, AARCH64_SHA2) +ID_AA64ISAR0_FEATURES(sha3, AARCH64_SHA3) +ID_AA64ISAR0_FEATURES(sm3, AARCH64_SM3) +ID_AA64ISAR0_FEATURES(sm4, AARCH64_SM4) +ID_AA64ISAR0_FEATURES(aes_pmull, AARCH64_AES, AARCH64_PMULL) +ID_AA64ISAR0_FEATURES(sha2_sha512, AARCH64_SHA2, AARCH64_SHA512) + +static MrsFeature id_aa64isar0[] = { + ID_AA64ISAR0_SET_FEATURE(fhm, "FHM"), + ID_AA64ISAR0_SET_FEATURE(dp, "DP"), + ID_AA64ISAR0_SET_FEATURE(crc32, "CRC32"), + ID_AA64ISAR0_SET_FEATURE(rdm, "RDM"), + ID_AA64ISAR0_SET_FEATURE(atomics, "Atomic"), + ID_AA64ISAR0_SET_FEATURE(aes, "AES"), + ID_AA64ISAR0_SET_FEATURE(sha1, "SHA1"), + ID_AA64ISAR0_SET_FEATURE(sha2, "SHA2"), + ID_AA64ISAR0_SET_FEATURE(sha3, "SHA3"), + ID_AA64ISAR0_SET_FEATURE(sm3, "SM3"), + ID_AA64ISAR0_SET_FEATURE(sm4, "SM4"), + ID_AA64ISAR0_SET_FEATURE(aes_pmull, "AES+PMULL"), + ID_AA64ISAR0_SET_FEATURE(sha2_sha512, "SHA2+SHA512"), + MRS_FEATURE_END, +}; + +// ID_AA64ISAR1_EL1 +// ----------------------------------------------------------------------------- +ID_AA64ISAR1_FEATURES(i8mm, AARCH64_I8MM) +ID_AA64ISAR1_FEATURES(dgh, AARCH64_DGH) +ID_AA64ISAR1_FEATURES(bf16, AARCH64_BF16) +ID_AA64ISAR1_FEATURES(sb, AARCH64_SB) +ID_AA64ISAR1_FEATURES(frint, AARCH64_FRINT) +ID_AA64ISAR1_FEATURES(pacg, AARCH64_PACG) +ID_AA64ISAR1_FEATURES(paca, AARCH64_PACA) +ID_AA64ISAR1_FEATURES(lrcpc, AARCH64_LRCPC) +ID_AA64ISAR1_FEATURES(ilrcpc, AARCH64_LRCPC, AARCH64_ILRCPC) +ID_AA64ISAR1_FEATURES(fcma, AARCH64_FCMA) +ID_AA64ISAR1_FEATURES(jscvt, AARCH64_JSCVT) +ID_AA64ISAR1_FEATURES(dcpop, AARCH64_DCPOP) +ID_AA64ISAR1_FEATURES(dcpodp, AARCH64_DCPOP, AARCH64_DCPODP) + +static MrsFeature id_aa64isar1[] = { + ID_AA64ISAR1_SET_FEATURE(i8mm, "I8MM"), + ID_AA64ISAR1_SET_FEATURE(dgh, "DGH"), + ID_AA64ISAR1_SET_FEATURE(bf16, "BF16"), + ID_AA64ISAR1_SET_FEATURE(sb, "SB"), + ID_AA64ISAR1_SET_FEATURE(frint, "FRINTTS"), + ID_AA64ISAR1_SET_FEATURE(pacg, "GPI"), + ID_AA64ISAR1_SET_FEATURE(paca, "GPA"), + ID_AA64ISAR1_SET_FEATURE(lrcpc, "RCPC-8.3"), + ID_AA64ISAR1_SET_FEATURE(ilrcpc, "RCPC-8.4"), + ID_AA64ISAR1_SET_FEATURE(fcma, "FCMA"), + ID_AA64ISAR1_SET_FEATURE(jscvt, "JSCVT"), + ID_AA64ISAR1_SET_FEATURE(dcpop, "DCPoP"), + ID_AA64ISAR1_SET_FEATURE(dcpodp, "DCCVADP"), + MRS_FEATURE_END, +}; + +// ID_AA64ISAR2_EL1 +// ----------------------------------------------------------------------------- +ID_AA64ISAR2_FEATURES(rpres, AARCH64_RPRES) + +static MrsFeature id_aa64isar2[] = { + ID_AA64ISAR2_SET_FEATURE(rpres, "RPRES"), + MRS_FEATURE_END, +}; + +// ID_AA64PFR0_EL1 +// ----------------------------------------------------------------------------- +ID_AA64PFR0_FEATURES(fp, AARCH64_FP) +ID_AA64PFR0_FEATURES(fphp, AARCH64_FP, AARCH64_FPHP) +ID_AA64PFR0_FEATURES(asimd, AARCH64_ASIMD) +ID_AA64PFR0_FEATURES(asimdhp, AARCH64_ASIMD, AARCH64_ASIMDHP) +ID_AA64PFR0_FEATURES(dit, AARCH64_DIT) +ID_AA64PFR0_FEATURES(sve, AARCH64_SVE) + +static MrsFeature id_aa64pfr0[] = { + ID_AA64PFR0_SET_FEATURE(fp, "FP"), + ID_AA64PFR0_SET_FEATURE(fphp, "FP+HP"), + ID_AA64PFR0_SET_FEATURE(asimd, "AdvSIMD"), + ID_AA64PFR0_SET_FEATURE(asimdhp, "AdvSIMD+HP"), + ID_AA64PFR0_SET_FEATURE(dit, "PSTATE.DIT"), + ID_AA64PFR0_SET_FEATURE(sve, "SVE"), + MRS_FEATURE_END, +}; + +// ID_AA64PFR1_EL1 +// ----------------------------------------------------------------------------- +ID_AA64PFR1_FEATURES(ssbs, AARCH64_SSBS) +// TODO: Add ssbs2 detection +ID_AA64PFR1_FEATURES(ssbs2, AARCH64_SSBS) +ID_AA64PFR1_FEATURES(mte, AARCH64_MTE) +ID_AA64PFR1_FEATURES(bti, AARCH64_BTI) + +static MrsFeature id_aa64pfr1[] = { + ID_AA64PFR1_SET_FEATURE(ssbs, "PSTATE.SSBS"), + ID_AA64PFR1_SET_FEATURE(ssbs2, "PSTATE.SSBS MSR"), + ID_AA64PFR1_SET_FEATURE(mte, "MTE"), + ID_AA64PFR1_SET_FEATURE(bti, "BTI"), + MRS_FEATURE_END, +}; + +// ID_AA64ZFR0_EL1 +// ----------------------------------------------------------------------------- +ID_AA64ZFR0_FEATURES(svef64mm, AARCH64_SVEF64MM) +ID_AA64ZFR0_FEATURES(svef32mm, AARCH64_SVEF32MM) +ID_AA64ZFR0_FEATURES(svei8mm, AARCH64_SVEI8MM) +ID_AA64ZFR0_FEATURES(svesm4, AARCH64_SVESM4) +ID_AA64ZFR0_FEATURES(svesha3, AARCH64_SVESHA3) +ID_AA64ZFR0_FEATURES(svebf16, AARCH64_SVEBF16) +// TODO: Add sveebf16 detection +ID_AA64ZFR0_FEATURES(sveebf16, AARCH64_SVEBF16) +ID_AA64ZFR0_FEATURES(svebitper, AARCH64_SVEBITPERM) +ID_AA64ZFR0_FEATURES(sveaes, AARCH64_SVEAES) +ID_AA64ZFR0_FEATURES(sve_aes_pmull, AARCH64_SVEAES, AARCH64_SVEPMULL) +ID_AA64ZFR0_FEATURES(sve2, AARCH64_SVE2) + +static MrsFeature id_aa64zfr0[] = { + ID_AA64ZFR0_SET_FEATURE(svef64mm, "F64MM"), + ID_AA64ZFR0_SET_FEATURE(svef32mm, "F32MM"), + ID_AA64ZFR0_SET_FEATURE(svei8mm, "I8MM"), + ID_AA64ZFR0_SET_FEATURE(svesm4, "SM4"), + ID_AA64ZFR0_SET_FEATURE(svesha3, "SHA3"), + ID_AA64ZFR0_SET_FEATURE(svebf16, "BF16"), + ID_AA64ZFR0_SET_FEATURE(sveebf16, "BF16+EBF"), + ID_AA64ZFR0_SET_FEATURE(svebitper, "BitPerm"), + ID_AA64ZFR0_SET_FEATURE(sveaes, "AES"), + ID_AA64ZFR0_SET_FEATURE(sve_aes_pmull, "AES+PMULL"), + ID_AA64ZFR0_SET_FEATURE(sve2, "SVE2"), + MRS_FEATURE_END, +}; + +static const MrsField mrs_fields[] = { + MRS_FIELD(ID_AA64ISAR0_KEY, id_aa64isar0), + MRS_FIELD(ID_AA64ISAR1_KEY, id_aa64isar1), + MRS_FIELD(ID_AA64ISAR2_KEY, id_aa64isar2), + MRS_FIELD(ID_AA64PFR0_KEY, id_aa64pfr0), + MRS_FIELD(ID_AA64PFR1_KEY, id_aa64pfr1), + MRS_FIELD(ID_AA64ZFR0_KEY, id_aa64zfr0), + MRS_FIELD_END, +}; + +static bool HasFeature(StringView csv, const char* feature) { + return CpuFeatures_StringView_HasWord(csv, feature, ','); +} + +static bool DetectAarch64Features(StringView csv, MrsFeature* mrs_features, + Aarch64Features* features) { + for (int i = 0; mrs_features[i].name != NULL; ++i) { + MrsFeature mrs_feature = mrs_features[i]; + if (!HasFeature(csv, mrs_feature.name)) continue; + for (int j = 0; mrs_feature.features_enum[j] != AARCH64_FEAT_END; ++j) { + int feat_idx = mrs_feature.features_enum[j]; + kSetters[feat_idx](features, true); + } + } +} + +static bool HandleAarch64Line(const LineResult result, + Aarch64Features* features) { + const StringView line = result.line; + for (int i = 0; mrs_fields[i].key != NULL; ++i) { + MrsField mrs_field = mrs_fields[i]; + if (!CpuFeatures_StringView_StartsWith(line, str(mrs_field.key))) continue; + 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); + } + DetectAarch64Features(csv, mrs_field.features, features); + } + return !result.eof; +} + +static void DetectFeaturesFromOs(Aarch64Features* 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 (;;) { + if (!HandleAarch64Line(StackLineReader_NextLine(&reader), features)) + break; + } + CpuFeatures_CloseFile(fd); + } +} + +Aarch64Info GetAarch64Info(void) { + Aarch64Info info = kEmptyAarch64Info; + DetectFeaturesFromOs(&info.features); + return info; +} + +#endif // CPU_FEATURES_OS_FREEBSD +#endif // CPU_FEATURES_ARCH_AARCH64 From 3137b9c84cfc0fe6ebfa2ede27bef93c4e70b41f Mon Sep 17 00:00:00 2001 From: Mykola Hohsdze Date: Wed, 1 Feb 2023 03:33:01 +0200 Subject: [PATCH 02/10] Add FreeBSD Arm64 tests --- test/CMakeLists.txt | 1 + test/cpuinfo_aarch64_test.cc | 164 +++++++++++++++++++++++++++++++++++ 2 files changed, 165 insertions(+) diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index f21ff985..122414f2 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -76,6 +76,7 @@ if(PROCESSOR_IS_AARCH64) ../src/impl_aarch64_linux_or_android.c ../src/impl_aarch64_windows.c ../src/impl_aarch64_macos_or_iphone.c + ../src/impl_aarch64_freebsd.c ) if(APPLE) target_compile_definitions(cpuinfo_aarch64_test PUBLIC CPU_FEATURES_MOCK_SYSCTL_AARCH64) diff --git a/test/cpuinfo_aarch64_test.cc b/test/cpuinfo_aarch64_test.cc index 6aefa6ba..2fab4999 100644 --- a/test/cpuinfo_aarch64_test.cc +++ b/test/cpuinfo_aarch64_test.cc @@ -113,6 +113,170 @@ class CpuidAarch64Test : public ::testing::Test { g_fake_cpu_instance = nullptr; } }; +#if defined(CPU_FEATURES_OS_FREEBSD) +// https://people.freebsd.org/~dch/posts/2021-07-02-oci-bringup.html +TEST(CpuinfoAarch64Test, FREEBSD_NEOVERSE_N1) { + auto& fs = GetEmptyFilesystem(); + fs.CreateFile("/var/run/dmesg.boot", R"( +CPU 0: ARM Neoverse-N1 r3p1 affinity: 0 + Cache Type = <64 byte D-cacheline,64 byte I-cacheline,PIPT ICache,64 byte ERG,64 byte CWG,IDC> + Instruction Set Attributes 0 = + Instruction Set Attributes 1 = + Processor Features 0 = + Processor Features 1 = + Memory Model Features 0 = + Memory Model Features 1 = + Memory Model Features 2 = <32bit CCIDX,48bit VA,UAO,CnP> + Debug Features 0 = + Debug Features 1 = <> + Auxiliary Features 0 = <> + Auxiliary Features 1 = <> +)"); + const auto info = GetAarch64Info(); + + EXPECT_TRUE(info.features.fp); + EXPECT_TRUE(info.features.asimd); + EXPECT_TRUE(info.features.aes); + EXPECT_TRUE(info.features.pmull); + EXPECT_TRUE(info.features.sha1); + EXPECT_TRUE(info.features.sha2); + EXPECT_TRUE(info.features.crc32); + EXPECT_TRUE(info.features.asimdrdm); + EXPECT_TRUE(info.features.asimdhp); + EXPECT_TRUE(info.features.atomics); + EXPECT_TRUE(info.features.fphp); + EXPECT_TRUE(info.features.lrcpc); + EXPECT_TRUE(info.features.asimddp); + EXPECT_TRUE(info.features.ssbs); + EXPECT_TRUE(info.features.dcpop); + + EXPECT_FALSE(info.features.evtstrm); + EXPECT_FALSE(info.features.cpuid); + EXPECT_FALSE(info.features.jscvt); + EXPECT_FALSE(info.features.fcma); + EXPECT_FALSE(info.features.sha3); + EXPECT_FALSE(info.features.sm3); + EXPECT_FALSE(info.features.sm4); + EXPECT_FALSE(info.features.sha512); + EXPECT_FALSE(info.features.sve); + EXPECT_FALSE(info.features.asimdfhm); + EXPECT_FALSE(info.features.dit); + EXPECT_FALSE(info.features.uscat); + EXPECT_FALSE(info.features.ilrcpc); + EXPECT_FALSE(info.features.flagm); + EXPECT_FALSE(info.features.sb); + EXPECT_FALSE(info.features.paca); + EXPECT_FALSE(info.features.pacg); + EXPECT_FALSE(info.features.dcpodp); + EXPECT_FALSE(info.features.sve2); + EXPECT_FALSE(info.features.sveaes); + EXPECT_FALSE(info.features.svepmull); + EXPECT_FALSE(info.features.svebitperm); + EXPECT_FALSE(info.features.svesha3); + EXPECT_FALSE(info.features.svesm4); + EXPECT_FALSE(info.features.flagm2); + EXPECT_FALSE(info.features.frint); + EXPECT_FALSE(info.features.svei8mm); + EXPECT_FALSE(info.features.svef32mm); + EXPECT_FALSE(info.features.svef64mm); + EXPECT_FALSE(info.features.svebf16); + EXPECT_FALSE(info.features.i8mm); + EXPECT_FALSE(info.features.bf16); + EXPECT_FALSE(info.features.dgh); + EXPECT_FALSE(info.features.rng); + EXPECT_FALSE(info.features.bti); + EXPECT_FALSE(info.features.mte); + EXPECT_FALSE(info.features.ecv); + EXPECT_FALSE(info.features.afp); + EXPECT_FALSE(info.features.rpres); +} + +TEST(CpuinfoAarch64Test, FREEBSD_RPI4) { + auto& fs = GetEmptyFilesystem(); + fs.CreateFile("/var/run/dmesg.boot", R"( +CPU 0: ARM Cortex-A72 r0p3 affinity: 0 + Cache Type = <64 byte D-cacheline,64 byte I-cacheline,PIPT ICache,64 byte ERG,64 byte CWG> + Instruction Set Attributes 0 = + Instruction Set Attributes 1 = <> + Instruction Set Attributes 2 = <> + Processor Features 0 = + Processor Features 1 = <> + Memory Model Features 0 = + Memory Model Features 1 = <8bit VMID> + Memory Model Features 2 = <32bit CCIDX,48bit VA> + Debug Features 0 = + Debug Features 1 = <> + Auxiliary Features 0 = <> + Auxiliary Features 1 = <> +AArch32 Instruction Set Attributes 5 = +AArch32 Media and VFP Features 0 = +AArch32 Media and VFP Features 1 = +CPU 1: ARM Cortex-A72 r0p3 affinity: 1 +CPU 2: ARM Cortex-A72 r0p3 affinity: 2 +CPU 3: ARM Cortex-A72 r0p3 affinity: 3 +)"); + const auto info = GetAarch64Info(); + + EXPECT_TRUE(info.features.fp); + EXPECT_TRUE(info.features.asimd); + EXPECT_TRUE(info.features.crc32); + + EXPECT_FALSE(info.features.aes); + EXPECT_FALSE(info.features.pmull); + EXPECT_FALSE(info.features.sha1); + EXPECT_FALSE(info.features.sha2); + EXPECT_FALSE(info.features.asimdrdm); + EXPECT_FALSE(info.features.asimdhp); + EXPECT_FALSE(info.features.atomics); + EXPECT_FALSE(info.features.fphp); + EXPECT_FALSE(info.features.lrcpc); + EXPECT_FALSE(info.features.asimddp); + EXPECT_FALSE(info.features.ssbs); + EXPECT_FALSE(info.features.dcpop); + EXPECT_FALSE(info.features.evtstrm); + EXPECT_FALSE(info.features.cpuid); + EXPECT_FALSE(info.features.jscvt); + EXPECT_FALSE(info.features.fcma); + EXPECT_FALSE(info.features.sha3); + EXPECT_FALSE(info.features.sm3); + EXPECT_FALSE(info.features.sm4); + EXPECT_FALSE(info.features.sha512); + EXPECT_FALSE(info.features.sve); + EXPECT_FALSE(info.features.asimdfhm); + EXPECT_FALSE(info.features.dit); + EXPECT_FALSE(info.features.uscat); + EXPECT_FALSE(info.features.ilrcpc); + EXPECT_FALSE(info.features.flagm); + EXPECT_FALSE(info.features.sb); + EXPECT_FALSE(info.features.paca); + EXPECT_FALSE(info.features.pacg); + EXPECT_FALSE(info.features.dcpodp); + EXPECT_FALSE(info.features.sve2); + EXPECT_FALSE(info.features.sveaes); + EXPECT_FALSE(info.features.svepmull); + EXPECT_FALSE(info.features.svebitperm); + EXPECT_FALSE(info.features.svesha3); + EXPECT_FALSE(info.features.svesm4); + EXPECT_FALSE(info.features.flagm2); + EXPECT_FALSE(info.features.frint); + EXPECT_FALSE(info.features.svei8mm); + EXPECT_FALSE(info.features.svef32mm); + EXPECT_FALSE(info.features.svef64mm); + EXPECT_FALSE(info.features.svebf16); + EXPECT_FALSE(info.features.i8mm); + EXPECT_FALSE(info.features.bf16); + EXPECT_FALSE(info.features.dgh); + EXPECT_FALSE(info.features.rng); + EXPECT_FALSE(info.features.bti); + EXPECT_FALSE(info.features.mte); + EXPECT_FALSE(info.features.ecv); + EXPECT_FALSE(info.features.afp); + EXPECT_FALSE(info.features.rpres); +} +#endif // CPU_FEATURES_OS_FREEBSD + +#if defined(CPU_FEATURES_OS_LINUX) +void DisableHardwareCapabilities() { SetHardwareCapabilities(0, 0); } TEST_F(CpuidAarch64Test, Aarch64FeaturesEnum) { const char* last_name = GetAarch64FeaturesEnumName(AARCH64_LAST_); From 5ebeac1824daa79f920e83cdfcdf0139b944fd7a Mon Sep 17 00:00:00 2001 From: Mykola Hohsdze Date: Wed, 1 Feb 2023 04:41:51 +0200 Subject: [PATCH 03/10] Add flagm, flagm2 and rng detection --- src/impl_aarch64_freebsd.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/impl_aarch64_freebsd.c b/src/impl_aarch64_freebsd.c index de11b022..f6db958d 100644 --- a/src/impl_aarch64_freebsd.c +++ b/src/impl_aarch64_freebsd.c @@ -165,6 +165,9 @@ ID_AA64ISAR0_FEATURES(sm3, AARCH64_SM3) ID_AA64ISAR0_FEATURES(sm4, AARCH64_SM4) ID_AA64ISAR0_FEATURES(aes_pmull, AARCH64_AES, AARCH64_PMULL) ID_AA64ISAR0_FEATURES(sha2_sha512, AARCH64_SHA2, AARCH64_SHA512) +ID_AA64ISAR0_FEATURES(flagm, AARCH64_FLAGM) +ID_AA64ISAR0_FEATURES(flagm2, AARCH64_FLAGM, AARCH64_FLAGM2) +ID_AA64ISAR0_FEATURES(rng, AARCH64_RNG) static MrsFeature id_aa64isar0[] = { ID_AA64ISAR0_SET_FEATURE(fhm, "FHM"), @@ -180,6 +183,9 @@ static MrsFeature id_aa64isar0[] = { ID_AA64ISAR0_SET_FEATURE(sm4, "SM4"), ID_AA64ISAR0_SET_FEATURE(aes_pmull, "AES+PMULL"), ID_AA64ISAR0_SET_FEATURE(sha2_sha512, "SHA2+SHA512"), + ID_AA64ISAR0_SET_FEATURE(flagm, "CondM-8.4"), + ID_AA64ISAR0_SET_FEATURE(flagm2, "CondM-8.5"), + ID_AA64ISAR0_SET_FEATURE(rng, "RNG"), MRS_FEATURE_END, }; From 4b16730a323c85f81e832925deadbdb970dd3d0b Mon Sep 17 00:00:00 2001 From: Mykola Hohsadze Date: Fri, 8 Sep 2023 20:03:19 +0300 Subject: [PATCH 04/10] Add HWCAP FreeBSD AArch64 --- CMakeLists.txt | 10 +- include/internal/hwcaps.h | 5 - include/internal/hwcaps_linux_or_android.h | 25 +++ src/hwcaps.c | 143 ------------------ src/hwcaps_freebsd.c | 43 ++++++ src/hwcaps_linux_or_android.c | 160 ++++++++++++++++++++ src/impl_aarch64_freebsd.c | 17 ++- test/cpuinfo_aarch64_test.cc | 168 +-------------------- 8 files changed, 255 insertions(+), 316 deletions(-) create mode 100644 include/internal/hwcaps_linux_or_android.h create mode 100644 src/hwcaps_freebsd.c create mode 100644 src/hwcaps_linux_or_android.c diff --git a/CMakeLists.txt b/CMakeLists.txt index 42c964ca..76a02e73 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -146,6 +146,9 @@ setup_include_and_definitions(utils) if(UNIX) add_library(unix_based_hardware_detection OBJECT ${PROJECT_SOURCE_DIR}/include/internal/hwcaps.h + ${PROJECT_SOURCE_DIR}/include/internal/hwcaps_linux_or_android.h + ${PROJECT_SOURCE_DIR}/src/hwcaps_linux_or_android.c + ${PROJECT_SOURCE_DIR}/src/hwcaps_freebsd.c ${PROJECT_SOURCE_DIR}/src/hwcaps.c ) setup_include_and_definitions(unix_based_hardware_detection) @@ -154,16 +157,21 @@ if(UNIX) target_compile_definitions(unix_based_hardware_detection PRIVATE HAVE_DLFCN_H) endif() check_symbol_exists(getauxval "sys/auxv.h" HAVE_STRONG_GETAUXVAL) + check_symbol_exists(elf_aux_info "sys/auxv.h" HAVE_STRONG_ELF_AUX_INFO) if(HAVE_STRONG_GETAUXVAL) target_compile_definitions(unix_based_hardware_detection PRIVATE HAVE_STRONG_GETAUXVAL) endif() + if(HAVE_STRONG_ELF_AUX_INFO) + target_compile_definitions(unix_based_hardware_detection PUBLIC HAVE_STRONG_ELF_AUX_INFO) + endif() endif() # # library : cpu_features # set (CPU_FEATURES_HDRS) -set (CPU_FEATURES_SRCS) +set (CPU_FEATURES_SRCS + include/internal/hwcaps_linux_or_android.h) add_cpu_features_headers_and_sources(CPU_FEATURES_HDRS CPU_FEATURES_SRCS) list(APPEND CPU_FEATURES_SRCS $) if(NOT PROCESSOR_IS_X86 AND UNIX) diff --git a/include/internal/hwcaps.h b/include/internal/hwcaps.h index 59e16576..4d0a8073 100644 --- a/include/internal/hwcaps.h +++ b/include/internal/hwcaps.h @@ -267,11 +267,6 @@ HardwareCapabilities CpuFeatures_GetHardwareCapabilities(void); bool CpuFeatures_IsHwCapsSet(const HardwareCapabilities hwcaps_mask, const HardwareCapabilities hwcaps); -// Get pointer for the AT_PLATFORM type. -const char* CpuFeatures_GetPlatformPointer(void); -// Get pointer for the AT_BASE_PLATFORM type. -const char* CpuFeatures_GetBasePlatformPointer(void); - CPU_FEATURES_END_CPP_NAMESPACE #endif // CPU_FEATURES_INCLUDE_INTERNAL_HWCAPS_H_ diff --git a/include/internal/hwcaps_linux_or_android.h b/include/internal/hwcaps_linux_or_android.h new file mode 100644 index 00000000..95d9e46a --- /dev/null +++ b/include/internal/hwcaps_linux_or_android.h @@ -0,0 +1,25 @@ +// Copyright 2023 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 CPU_FEATURES_HWCAPS_LINUX_OR_ANDROID_H_ +#define CPU_FEATURES_HWCAPS_LINUX_OR_ANDROID_H_ + +#include "internal/hwcaps.h" + +// Get pointer for the AT_PLATFORM type. +const char* CpuFeatures_GetPlatformPointer(void); +// Get pointer for the AT_BASE_PLATFORM type. +const char* CpuFeatures_GetBasePlatformPointer(void); + +#endif // CPU_FEATURES_HWCAPS_LINUX_OR_ANDROID_H_ diff --git a/src/hwcaps.c b/src/hwcaps.c index f44f6c39..18dd35b3 100644 --- a/src/hwcaps.c +++ b/src/hwcaps.c @@ -14,13 +14,6 @@ #include "internal/hwcaps.h" -#include -#include - -#include "cpu_features_macros.h" -#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; @@ -31,139 +24,3 @@ bool CpuFeatures_IsHwCapsSet(const HardwareCapabilities hwcaps_mask, 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); -const char* CpuFeatures_GetPlatformPointer(void); -const char* CpuFeatures_GetBasePlatformPointer(void); -#else - -// Debug facilities -#if defined(NDEBUG) -#define D(...) -#else -#include -#define D(...) \ - do { \ - printf(__VA_ARGS__); \ - fflush(stdout); \ - } while (0) -#endif - -//////////////////////////////////////////////////////////////////////////////// -// Implementation of GetElfHwcapFromGetauxval -//////////////////////////////////////////////////////////////////////////////// - -#define AT_HWCAP 16 -#define AT_HWCAP2 26 -#define AT_PLATFORM 15 -#define AT_BASE_PLATFORM 24 - -#if defined(HAVE_STRONG_GETAUXVAL) -#include -static unsigned long GetElfHwcapFromGetauxval(uint32_t hwcap_type) { - return getauxval(hwcap_type); -} -#elif defined(HAVE_DLFCN_H) -// On Android we probe the system's C library for a 'getauxval' function and -// call it if it exits, or return 0 for failure. This function is available -// since API level 18. -// -// Note that getauxval() can't really be re-implemented here, because its -// implementation does not parse /proc/self/auxv. Instead it depends on values -// that are passed by the kernel at process-init time to the C runtime -// initialization layer. - -#include - -typedef unsigned long getauxval_func_t(unsigned long); - -static uint32_t GetElfHwcapFromGetauxval(uint32_t hwcap_type) { - uint32_t ret = 0; - void *libc_handle = NULL; - getauxval_func_t *func = NULL; - - dlerror(); // Cleaning error state before calling dlopen. - libc_handle = dlopen("libc.so", RTLD_NOW); - if (!libc_handle) { - D("Could not dlopen() C library: %s\n", dlerror()); - return 0; - } - func = (getauxval_func_t *)dlsym(libc_handle, "getauxval"); - if (!func) { - D("Could not find getauxval() in C library\n"); - } else { - // Note: getauxval() returns 0 on failure. Doesn't touch errno. - ret = (uint32_t)(*func)(hwcap_type); - } - dlclose(libc_handle); - return ret; -} -#else -#error "This platform does not provide hardware capabilities." -#endif - -// Implementation of GetHardwareCapabilities for OS that provide -// GetElfHwcapFromGetauxval(). - -// Fallback when getauxval is not available, retrieves hwcaps from -// "/proc/self/auxv". -static uint32_t GetElfHwcapFromProcSelfAuxv(uint32_t hwcap_type) { - struct { - uint32_t tag; - uint32_t value; - } entry; - uint32_t result = 0; - const char filepath[] = "/proc/self/auxv"; - const int fd = CpuFeatures_OpenFile(filepath); - if (fd < 0) { - D("Could not open %s\n", filepath); - return 0; - } - for (;;) { - const int ret = CpuFeatures_ReadFile(fd, (char *)&entry, sizeof entry); - if (ret < 0) { - D("Error while reading %s\n", filepath); - break; - } - // Detect end of list. - if (ret == 0 || (entry.tag == 0 && entry.value == 0)) { - break; - } - if (entry.tag == hwcap_type) { - result = entry.value; - break; - } - } - CpuFeatures_CloseFile(fd); - return result; -} - -// Retrieves hardware capabilities by first trying to call getauxval, if not -// available falls back to reading "/proc/self/auxv". -static unsigned long GetHardwareCapabilitiesFor(uint32_t type) { - unsigned long hwcaps = GetElfHwcapFromGetauxval(type); - if (!hwcaps) { - D("Parsing /proc/self/auxv to extract ELF hwcaps!\n"); - hwcaps = GetElfHwcapFromProcSelfAuxv(type); - } - return hwcaps; -} - -HardwareCapabilities CpuFeatures_GetHardwareCapabilities(void) { - HardwareCapabilities capabilities; - capabilities.hwcaps = GetHardwareCapabilitiesFor(AT_HWCAP); - capabilities.hwcaps2 = GetHardwareCapabilitiesFor(AT_HWCAP2); - return capabilities; -} - -const char *CpuFeatures_GetPlatformPointer(void) { - return (const char *)GetHardwareCapabilitiesFor(AT_PLATFORM); -} - -const char *CpuFeatures_GetBasePlatformPointer(void) { - return (const char *)GetHardwareCapabilitiesFor(AT_BASE_PLATFORM); -} - -#endif // CPU_FEATURES_TEST diff --git a/src/hwcaps_freebsd.c b/src/hwcaps_freebsd.c new file mode 100644 index 00000000..509b75a6 --- /dev/null +++ b/src/hwcaps_freebsd.c @@ -0,0 +1,43 @@ +// Copyright 2023 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_FREEBSD) + +#if defined(HAVE_STRONG_ELF_AUX_INFO) +#include +#include + +#include "internal/hwcaps.h" + +static unsigned long GetElfHwcapFromElfAuxInfo(int hwcap_type) { + unsigned long hwcap; + elf_aux_info(hwcap_type, &hwcap, sizeof(hwcap)); + return hwcap; +} + +HardwareCapabilities CpuFeatures_GetHardwareCapabilities(void) { + HardwareCapabilities capabilities; + capabilities.hwcaps = GetElfHwcapFromElfAuxInfo(AT_HWCAP); + capabilities.hwcaps2 = GetElfHwcapFromElfAuxInfo(AT_HWCAP2); + return capabilities; +} +#else +#error "Error" +#endif // HAVE_STRONG_ELF_AUX_INFO + +#endif // CPU_FEATURES_OS_FREEBSD +#endif // CPU_FEATURES_ARCH_AARCH64 diff --git a/src/hwcaps_linux_or_android.c b/src/hwcaps_linux_or_android.c new file mode 100644 index 00000000..8f7a10a3 --- /dev/null +++ b/src/hwcaps_linux_or_android.c @@ -0,0 +1,160 @@ +// Copyright 2023 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 "internal/hwcaps_linux_or_android.h" + +#include +#include + +#include "cpu_features_macros.h" +#include "internal/filesystem.h" +#include "internal/string_view.h" + +#ifdef CPU_FEATURES_TEST +// In test mode, hwcaps_for_testing will define the following functions. +HardwareCapabilities CpuFeatures_GetHardwareCapabilities(void); +const char* CpuFeatures_GetPlatformPointer(void); +const char* CpuFeatures_GetBasePlatformPointer(void); +#else + +// Debug facilities +#if defined(NDEBUG) +#define D(...) +#else +#include +#define D(...) \ + do { \ + printf(__VA_ARGS__); \ + fflush(stdout); \ + } while (0) +#endif + +//////////////////////////////////////////////////////////////////////////////// +// Implementation of GetElfHwcapFromGetauxval +//////////////////////////////////////////////////////////////////////////////// + +#if defined(HAVE_STRONG_GETAUXVAL) +#include +static unsigned long GetElfHwcapFromGetauxval(uint32_t hwcap_type) { + return getauxval(hwcap_type); +} +#elif defined(HAVE_DLFCN_H) +// On Android we probe the system's C library for a 'getauxval' function and +// call it if it exits, or return 0 for failure. This function is available +// since API level 18. +// +// Note that getauxval() can't really be re-implemented here, because its +// implementation does not parse /proc/self/auxv. Instead it depends on values +// that are passed by the kernel at process-init time to the C runtime +// initialization layer. + +#include + +typedef unsigned long getauxval_func_t(unsigned long); + +static uint32_t GetElfHwcapFromGetauxval(uint32_t hwcap_type) { + uint32_t ret = 0; + void *libc_handle = NULL; + getauxval_func_t *func = NULL; + + dlerror(); // Cleaning error state before calling dlopen. + libc_handle = dlopen("libc.so", RTLD_NOW); + if (!libc_handle) { + D("Could not dlopen() C library: %s\n", dlerror()); + return 0; + } + func = (getauxval_func_t *)dlsym(libc_handle, "getauxval"); + if (!func) { + D("Could not find getauxval() in C library\n"); + } else { + // Note: getauxval() returns 0 on failure. Doesn't touch errno. + ret = (uint32_t)(*func)(hwcap_type); + } + dlclose(libc_handle); + return ret; +} +#else +#error "This platform does not provide hardware capabilities." +#endif + +// Implementation of GetHardwareCapabilities for OS that provide +// GetElfHwcapFromGetauxval(). + +// Fallback when getauxval is not available, retrieves hwcaps from +// "/proc/self/auxv". +static uint32_t GetElfHwcapFromProcSelfAuxv(uint32_t hwcap_type) { + struct { + uint32_t tag; + uint32_t value; + } entry; + uint32_t result = 0; + const char filepath[] = "/proc/self/auxv"; + const int fd = CpuFeatures_OpenFile(filepath); + if (fd < 0) { + D("Could not open %s\n", filepath); + return 0; + } + for (;;) { + const int ret = CpuFeatures_ReadFile(fd, (char *)&entry, sizeof entry); + if (ret < 0) { + D("Error while reading %s\n", filepath); + break; + } + // Detect end of list. + if (ret == 0 || (entry.tag == 0 && entry.value == 0)) { + break; + } + if (entry.tag == hwcap_type) { + result = entry.value; + break; + } + } + CpuFeatures_CloseFile(fd); + return result; +} + +// Retrieves hardware capabilities by first trying to call getauxval, if not +// available falls back to reading "/proc/self/auxv". +static unsigned long GetHardwareCapabilitiesFor(uint32_t type) { + unsigned long hwcaps = GetElfHwcapFromGetauxval(type); + if (!hwcaps) { + D("Parsing /proc/self/auxv to extract ELF hwcaps!\n"); + hwcaps = GetElfHwcapFromProcSelfAuxv(type); + } + return hwcaps; +} + +HardwareCapabilities CpuFeatures_GetHardwareCapabilities(void) { + HardwareCapabilities capabilities; + capabilities.hwcaps = GetHardwareCapabilitiesFor(AT_HWCAP); + capabilities.hwcaps2 = GetHardwareCapabilitiesFor(AT_HWCAP2); + return capabilities; +} + +const char *CpuFeatures_GetPlatformPointer(void) { + return (const char *)GetHardwareCapabilitiesFor(AT_PLATFORM); +} + +const char *CpuFeatures_GetBasePlatformPointer(void) { + return (const char *)GetHardwareCapabilitiesFor(AT_BASE_PLATFORM); +} + +#endif // CPU_FEATURES_TEST +#endif // defined(CPU_FEATURES_OS_LINUX) || defined(CPU_FEATURES_OS_ANDROID) +#endif // CPU_FEATURES_ARCH_AARCH64 diff --git a/src/impl_aarch64_freebsd.c b/src/impl_aarch64_freebsd.c index f6db958d..3247c6a2 100644 --- a/src/impl_aarch64_freebsd.c +++ b/src/impl_aarch64_freebsd.c @@ -196,7 +196,13 @@ ID_AA64ISAR1_FEATURES(dgh, AARCH64_DGH) ID_AA64ISAR1_FEATURES(bf16, AARCH64_BF16) ID_AA64ISAR1_FEATURES(sb, AARCH64_SB) ID_AA64ISAR1_FEATURES(frint, AARCH64_FRINT) -ID_AA64ISAR1_FEATURES(pacg, AARCH64_PACG) +ID_AA64ISAR1_FEATURES(pacg_gpi, AARCH64_PACG) +ID_AA64ISAR1_FEATURES(pacg_gpa, AARCH64_PACG) +ID_AA64ISAR1_FEATURES(api_pac, AARCH64_PACA) +ID_AA64ISAR1_FEATURES(api_epac, AARCH64_PACA) +ID_AA64ISAR1_FEATURES(api_epac2, AARCH64_PACA) +ID_AA64ISAR1_FEATURES(api_fpac, AARCH64_PACA) +ID_AA64ISAR1_FEATURES(api_fpac_combined, AARCH64_PACA) ID_AA64ISAR1_FEATURES(paca, AARCH64_PACA) ID_AA64ISAR1_FEATURES(lrcpc, AARCH64_LRCPC) ID_AA64ISAR1_FEATURES(ilrcpc, AARCH64_LRCPC, AARCH64_ILRCPC) @@ -211,14 +217,19 @@ static MrsFeature id_aa64isar1[] = { ID_AA64ISAR1_SET_FEATURE(bf16, "BF16"), ID_AA64ISAR1_SET_FEATURE(sb, "SB"), ID_AA64ISAR1_SET_FEATURE(frint, "FRINTTS"), - ID_AA64ISAR1_SET_FEATURE(pacg, "GPI"), - ID_AA64ISAR1_SET_FEATURE(paca, "GPA"), + ID_AA64ISAR1_SET_FEATURE(pacg_gpi, "GPI"), + ID_AA64ISAR1_SET_FEATURE(pacg_gpa, "GPA"), ID_AA64ISAR1_SET_FEATURE(lrcpc, "RCPC-8.3"), ID_AA64ISAR1_SET_FEATURE(ilrcpc, "RCPC-8.4"), ID_AA64ISAR1_SET_FEATURE(fcma, "FCMA"), ID_AA64ISAR1_SET_FEATURE(jscvt, "JSCVT"), ID_AA64ISAR1_SET_FEATURE(dcpop, "DCPoP"), ID_AA64ISAR1_SET_FEATURE(dcpodp, "DCCVADP"), + ID_AA64ISAR1_SET_FEATURE(api_pac, "API PAC"), + ID_AA64ISAR1_SET_FEATURE(api_epac, "API EPAC"), + ID_AA64ISAR1_SET_FEATURE(api_epac2, "Impl PAuth+EPAC2"), + ID_AA64ISAR1_SET_FEATURE(api_fpac, "Impl PAuth+FPAC"), + ID_AA64ISAR1_SET_FEATURE(api_fpac_combined, "Impl PAuth+FPAC+Combined"), MRS_FEATURE_END, }; diff --git a/test/cpuinfo_aarch64_test.cc b/test/cpuinfo_aarch64_test.cc index 2fab4999..219a74e8 100644 --- a/test/cpuinfo_aarch64_test.cc +++ b/test/cpuinfo_aarch64_test.cc @@ -113,170 +113,6 @@ class CpuidAarch64Test : public ::testing::Test { g_fake_cpu_instance = nullptr; } }; -#if defined(CPU_FEATURES_OS_FREEBSD) -// https://people.freebsd.org/~dch/posts/2021-07-02-oci-bringup.html -TEST(CpuinfoAarch64Test, FREEBSD_NEOVERSE_N1) { - auto& fs = GetEmptyFilesystem(); - fs.CreateFile("/var/run/dmesg.boot", R"( -CPU 0: ARM Neoverse-N1 r3p1 affinity: 0 - Cache Type = <64 byte D-cacheline,64 byte I-cacheline,PIPT ICache,64 byte ERG,64 byte CWG,IDC> - Instruction Set Attributes 0 = - Instruction Set Attributes 1 = - Processor Features 0 = - Processor Features 1 = - Memory Model Features 0 = - Memory Model Features 1 = - Memory Model Features 2 = <32bit CCIDX,48bit VA,UAO,CnP> - Debug Features 0 = - Debug Features 1 = <> - Auxiliary Features 0 = <> - Auxiliary Features 1 = <> -)"); - const auto info = GetAarch64Info(); - - EXPECT_TRUE(info.features.fp); - EXPECT_TRUE(info.features.asimd); - EXPECT_TRUE(info.features.aes); - EXPECT_TRUE(info.features.pmull); - EXPECT_TRUE(info.features.sha1); - EXPECT_TRUE(info.features.sha2); - EXPECT_TRUE(info.features.crc32); - EXPECT_TRUE(info.features.asimdrdm); - EXPECT_TRUE(info.features.asimdhp); - EXPECT_TRUE(info.features.atomics); - EXPECT_TRUE(info.features.fphp); - EXPECT_TRUE(info.features.lrcpc); - EXPECT_TRUE(info.features.asimddp); - EXPECT_TRUE(info.features.ssbs); - EXPECT_TRUE(info.features.dcpop); - - EXPECT_FALSE(info.features.evtstrm); - EXPECT_FALSE(info.features.cpuid); - EXPECT_FALSE(info.features.jscvt); - EXPECT_FALSE(info.features.fcma); - EXPECT_FALSE(info.features.sha3); - EXPECT_FALSE(info.features.sm3); - EXPECT_FALSE(info.features.sm4); - EXPECT_FALSE(info.features.sha512); - EXPECT_FALSE(info.features.sve); - EXPECT_FALSE(info.features.asimdfhm); - EXPECT_FALSE(info.features.dit); - EXPECT_FALSE(info.features.uscat); - EXPECT_FALSE(info.features.ilrcpc); - EXPECT_FALSE(info.features.flagm); - EXPECT_FALSE(info.features.sb); - EXPECT_FALSE(info.features.paca); - EXPECT_FALSE(info.features.pacg); - EXPECT_FALSE(info.features.dcpodp); - EXPECT_FALSE(info.features.sve2); - EXPECT_FALSE(info.features.sveaes); - EXPECT_FALSE(info.features.svepmull); - EXPECT_FALSE(info.features.svebitperm); - EXPECT_FALSE(info.features.svesha3); - EXPECT_FALSE(info.features.svesm4); - EXPECT_FALSE(info.features.flagm2); - EXPECT_FALSE(info.features.frint); - EXPECT_FALSE(info.features.svei8mm); - EXPECT_FALSE(info.features.svef32mm); - EXPECT_FALSE(info.features.svef64mm); - EXPECT_FALSE(info.features.svebf16); - EXPECT_FALSE(info.features.i8mm); - EXPECT_FALSE(info.features.bf16); - EXPECT_FALSE(info.features.dgh); - EXPECT_FALSE(info.features.rng); - EXPECT_FALSE(info.features.bti); - EXPECT_FALSE(info.features.mte); - EXPECT_FALSE(info.features.ecv); - EXPECT_FALSE(info.features.afp); - EXPECT_FALSE(info.features.rpres); -} - -TEST(CpuinfoAarch64Test, FREEBSD_RPI4) { - auto& fs = GetEmptyFilesystem(); - fs.CreateFile("/var/run/dmesg.boot", R"( -CPU 0: ARM Cortex-A72 r0p3 affinity: 0 - Cache Type = <64 byte D-cacheline,64 byte I-cacheline,PIPT ICache,64 byte ERG,64 byte CWG> - Instruction Set Attributes 0 = - Instruction Set Attributes 1 = <> - Instruction Set Attributes 2 = <> - Processor Features 0 = - Processor Features 1 = <> - Memory Model Features 0 = - Memory Model Features 1 = <8bit VMID> - Memory Model Features 2 = <32bit CCIDX,48bit VA> - Debug Features 0 = - Debug Features 1 = <> - Auxiliary Features 0 = <> - Auxiliary Features 1 = <> -AArch32 Instruction Set Attributes 5 = -AArch32 Media and VFP Features 0 = -AArch32 Media and VFP Features 1 = -CPU 1: ARM Cortex-A72 r0p3 affinity: 1 -CPU 2: ARM Cortex-A72 r0p3 affinity: 2 -CPU 3: ARM Cortex-A72 r0p3 affinity: 3 -)"); - const auto info = GetAarch64Info(); - - EXPECT_TRUE(info.features.fp); - EXPECT_TRUE(info.features.asimd); - EXPECT_TRUE(info.features.crc32); - - EXPECT_FALSE(info.features.aes); - EXPECT_FALSE(info.features.pmull); - EXPECT_FALSE(info.features.sha1); - EXPECT_FALSE(info.features.sha2); - EXPECT_FALSE(info.features.asimdrdm); - EXPECT_FALSE(info.features.asimdhp); - EXPECT_FALSE(info.features.atomics); - EXPECT_FALSE(info.features.fphp); - EXPECT_FALSE(info.features.lrcpc); - EXPECT_FALSE(info.features.asimddp); - EXPECT_FALSE(info.features.ssbs); - EXPECT_FALSE(info.features.dcpop); - EXPECT_FALSE(info.features.evtstrm); - EXPECT_FALSE(info.features.cpuid); - EXPECT_FALSE(info.features.jscvt); - EXPECT_FALSE(info.features.fcma); - EXPECT_FALSE(info.features.sha3); - EXPECT_FALSE(info.features.sm3); - EXPECT_FALSE(info.features.sm4); - EXPECT_FALSE(info.features.sha512); - EXPECT_FALSE(info.features.sve); - EXPECT_FALSE(info.features.asimdfhm); - EXPECT_FALSE(info.features.dit); - EXPECT_FALSE(info.features.uscat); - EXPECT_FALSE(info.features.ilrcpc); - EXPECT_FALSE(info.features.flagm); - EXPECT_FALSE(info.features.sb); - EXPECT_FALSE(info.features.paca); - EXPECT_FALSE(info.features.pacg); - EXPECT_FALSE(info.features.dcpodp); - EXPECT_FALSE(info.features.sve2); - EXPECT_FALSE(info.features.sveaes); - EXPECT_FALSE(info.features.svepmull); - EXPECT_FALSE(info.features.svebitperm); - EXPECT_FALSE(info.features.svesha3); - EXPECT_FALSE(info.features.svesm4); - EXPECT_FALSE(info.features.flagm2); - EXPECT_FALSE(info.features.frint); - EXPECT_FALSE(info.features.svei8mm); - EXPECT_FALSE(info.features.svef32mm); - EXPECT_FALSE(info.features.svef64mm); - EXPECT_FALSE(info.features.svebf16); - EXPECT_FALSE(info.features.i8mm); - EXPECT_FALSE(info.features.bf16); - EXPECT_FALSE(info.features.dgh); - EXPECT_FALSE(info.features.rng); - EXPECT_FALSE(info.features.bti); - EXPECT_FALSE(info.features.mte); - EXPECT_FALSE(info.features.ecv); - EXPECT_FALSE(info.features.afp); - EXPECT_FALSE(info.features.rpres); -} -#endif // CPU_FEATURES_OS_FREEBSD - -#if defined(CPU_FEATURES_OS_LINUX) -void DisableHardwareCapabilities() { SetHardwareCapabilities(0, 0); } TEST_F(CpuidAarch64Test, Aarch64FeaturesEnum) { const char* last_name = GetAarch64FeaturesEnumName(AARCH64_LAST_); @@ -291,6 +127,9 @@ TEST_F(CpuidAarch64Test, Aarch64FeaturesEnum) { } } +#if defined(CPU_FEATURES_OS_LINUX) +void DisableHardwareCapabilities() { SetHardwareCapabilities(0, 0); } + // OS dependent tests #if defined(CPU_FEATURES_OS_LINUX) TEST_F(CpuidAarch64Test, FromHardwareCap) { @@ -547,6 +386,7 @@ TEST_F(CpuidAarch64Test, WINDOWS_AARCH64_RPI4) { EXPECT_FALSE(info.features.jscvt); EXPECT_FALSE(info.features.lrcpc); } +#endif #endif // CPU_FEATURES_OS_WINDOWS } // namespace } // namespace cpu_features From c783f81568e7dde3f269113f19a9c4361213cbe2 Mon Sep 17 00:00:00 2001 From: Mykola Hohsadze Date: Fri, 8 Sep 2023 20:04:17 +0300 Subject: [PATCH 05/10] Update include to use linux hwcaps for powerpc --- src/impl_ppc_linux.c | 2 +- src/impl_s390x_linux.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/impl_ppc_linux.c b/src/impl_ppc_linux.c index 46a72d77..2e1e0f3a 100644 --- a/src/impl_ppc_linux.c +++ b/src/impl_ppc_linux.c @@ -82,7 +82,7 @@ #include "internal/bit_utils.h" #include "internal/filesystem.h" -#include "internal/hwcaps.h" +#include "internal/hwcaps_linux_or_android.h" #include "internal/stack_line_reader.h" #include "internal/string_view.h" diff --git a/src/impl_s390x_linux.c b/src/impl_s390x_linux.c index 2b8b865d..534c2c18 100644 --- a/src/impl_s390x_linux.c +++ b/src/impl_s390x_linux.c @@ -58,7 +58,7 @@ #include "internal/bit_utils.h" #include "internal/filesystem.h" -#include "internal/hwcaps.h" +#include "internal/hwcaps_linux_or_android.h" #include "internal/stack_line_reader.h" #include "internal/string_view.h" From 2b7c47a0291999349f7ce131a61b9750309164c7 Mon Sep 17 00:00:00 2001 From: Mykola Hohsadze Date: Fri, 8 Sep 2023 20:05:32 +0300 Subject: [PATCH 06/10] Add FreeBSD aarch64 impl --- src/impl_aarch64_freebsd.c | 380 ++----------------------------------- 1 file changed, 21 insertions(+), 359 deletions(-) diff --git a/src/impl_aarch64_freebsd.c b/src/impl_aarch64_freebsd.c index 3247c6a2..677219ef 100644 --- a/src/impl_aarch64_freebsd.c +++ b/src/impl_aarch64_freebsd.c @@ -1,3 +1,17 @@ +// Copyright 2023 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 @@ -5,370 +19,18 @@ #include "cpuinfo_aarch64.h" -//////////////////////////////////////////////////////////////////////////////// -// Definitions for introspection. -//////////////////////////////////////////////////////////////////////////////// -#define INTROSPECTION_TABLE \ - LINE(AARCH64_FP, fp, , , ) \ - LINE(AARCH64_ASIMD, asimd, , , ) \ - LINE(AARCH64_EVTSTRM, evtstrm, , , ) \ - LINE(AARCH64_AES, aes, , , ) \ - LINE(AARCH64_PMULL, pmull, , , ) \ - LINE(AARCH64_SHA1, sha1, , , ) \ - LINE(AARCH64_SHA2, sha2, , , ) \ - LINE(AARCH64_CRC32, crc32, , , ) \ - LINE(AARCH64_ATOMICS, atomics, , , ) \ - LINE(AARCH64_FPHP, fphp, , , ) \ - LINE(AARCH64_ASIMDHP, asimdhp, , , ) \ - LINE(AARCH64_CPUID, cpuid, , , ) \ - LINE(AARCH64_ASIMDRDM, asimdrdm, , , ) \ - LINE(AARCH64_JSCVT, jscvt, , , ) \ - LINE(AARCH64_FCMA, fcma, , , ) \ - LINE(AARCH64_LRCPC, lrcpc, , , ) \ - LINE(AARCH64_DCPOP, dcpop, , , ) \ - LINE(AARCH64_SHA3, sha3, , , ) \ - LINE(AARCH64_SM3, sm3, , , ) \ - LINE(AARCH64_SM4, sm4, , , ) \ - LINE(AARCH64_ASIMDDP, asimddp, , , ) \ - LINE(AARCH64_SHA512, sha512, , , ) \ - LINE(AARCH64_SVE, sve, , , ) \ - LINE(AARCH64_ASIMDFHM, asimdfhm, , , ) \ - LINE(AARCH64_DIT, dit, , , ) \ - LINE(AARCH64_USCAT, uscat, , , ) \ - LINE(AARCH64_ILRCPC, ilrcpc, , , ) \ - LINE(AARCH64_FLAGM, flagm, , , ) \ - LINE(AARCH64_SSBS, ssbs, , , ) \ - LINE(AARCH64_SB, sb, , , ) \ - LINE(AARCH64_PACA, paca, , , ) \ - LINE(AARCH64_PACG, pacg, , , ) \ - LINE(AARCH64_DCPODP, dcpodp, , , ) \ - LINE(AARCH64_SVE2, sve2, , , ) \ - LINE(AARCH64_SVEAES, sveaes, , , ) \ - LINE(AARCH64_SVEPMULL, svepmull, , , ) \ - LINE(AARCH64_SVEBITPERM, svebitperm, , , ) \ - LINE(AARCH64_SVESHA3, svesha3, , , ) \ - LINE(AARCH64_SVESM4, svesm4, , , ) \ - LINE(AARCH64_FLAGM2, flagm2, , , ) \ - LINE(AARCH64_FRINT, frint, , , ) \ - LINE(AARCH64_SVEI8MM, svei8mm, , , ) \ - LINE(AARCH64_SVEF32MM, svef32mm, , , ) \ - LINE(AARCH64_SVEF64MM, svef64mm, , , ) \ - LINE(AARCH64_SVEBF16, svebf16, , , ) \ - LINE(AARCH64_I8MM, i8mm, , , ) \ - LINE(AARCH64_BF16, bf16, , , ) \ - LINE(AARCH64_DGH, dgh, , , ) \ - LINE(AARCH64_RNG, rng, , , ) \ - LINE(AARCH64_BTI, bti, , , ) \ - LINE(AARCH64_MTE, mte, , , ) \ - LINE(AARCH64_ECV, ecv, , , ) \ - LINE(AARCH64_AFP, afp, , , ) \ - LINE(AARCH64_RPRES, rpres, , , ) -#define INTROSPECTION_PREFIX Aarch64 -#define INTROSPECTION_ENUM_PREFIX AARCH64 -#include "define_introspection.inl" - -//////////////////////////////////////////////////////////////////////////////// -// Implementation. -//////////////////////////////////////////////////////////////////////////////// - -#include "internal/filesystem.h" -#include "internal/stack_line_reader.h" -#include "internal/string_view.h" +#include "impl_aarch64__base_implementation.inl" static const Aarch64Info kEmptyAarch64Info; -#define ID_AA64ISAR0_KEY " Instruction Set Attributes 0" -#define ID_AA64ISAR1_KEY " Instruction Set Attributes 1" -#define ID_AA64ISAR2_KEY " Instruction Set Attributes 2" -#define ID_AA64PFR0_KEY " Processor Features 0" -#define ID_AA64PFR1_KEY " Processor Features 1" -#define ID_AA64ZFR0_KEY " SVE Features 0" - -typedef struct { - const char* name; - Aarch64FeaturesEnum* features_enum; -} MrsFeature; - -#define MRS_FEATURE(feature, mrs_prefix, feat_suffix) \ - (MrsFeature) { feature, mrs_prefix##_##feat_suffix } - -#define MRS_FEATURE_END \ - (MrsFeature) { NULL, NULL } - -#define ID_AA64ISAR0_SET_FEATURE(feat_name, feature) \ - MRS_FEATURE(feature, id_aa64isar0, feat_name) - -#define ID_AA64ISAR1_SET_FEATURE(feat_name, feature) \ - MRS_FEATURE(feature, id_aa64isar1, feat_name) - -#define ID_AA64ISAR2_SET_FEATURE(feat_name, feature) \ - MRS_FEATURE(feature, id_aa64isar2, feat_name) - -#define ID_AA64PFR0_SET_FEATURE(feat_name, feature) \ - MRS_FEATURE(feature, id_aa64pfr0, feat_name) - -#define ID_AA64PFR1_SET_FEATURE(feat_name, feature) \ - MRS_FEATURE(feature, id_aa64pfr1, feat_name) - -#define ID_AA64ZFR0_SET_FEATURE(feat_name, feature) \ - MRS_FEATURE(feature, id_aa64zfr0, feat_name) - -typedef struct { - const char* key; - MrsFeature* features; -} MrsField; - -#define MRS_FIELD(mrs, mrs_features) \ - (MrsField) { mrs, mrs_features } - -#define MRS_FIELD_END \ - (MrsField) { NULL, NULL } - -#define AARCH64_FEAT_END AARCH64_LAST_ - -#define MRS_FEATURES(mrs_name, feat_name, ...) \ - static Aarch64FeaturesEnum mrs_name##_##feat_name[] = { \ - __VA_ARGS__, \ - AARCH64_FEAT_END, \ - }; - -#define ID_AA64ISAR0_FEATURES(feat_name, ...) \ - MRS_FEATURES(id_aa64isar0, feat_name, __VA_ARGS__) - -#define ID_AA64ISAR1_FEATURES(feat_name, ...) \ - MRS_FEATURES(id_aa64isar1, feat_name, __VA_ARGS__) - -#define ID_AA64ISAR2_FEATURES(feat_name, ...) \ - MRS_FEATURES(id_aa64isar2, feat_name, __VA_ARGS__) - -#define ID_AA64PFR0_FEATURES(feat_name, ...) \ - MRS_FEATURES(id_aa64pfr0, feat_name, __VA_ARGS__) - -#define ID_AA64PFR1_FEATURES(feat_name, ...) \ - MRS_FEATURES(id_aa64pfr1, feat_name, __VA_ARGS__) - -#define ID_AA64ZFR0_FEATURES(feat_name, ...) \ - MRS_FEATURES(id_aa64zfr0, feat_name, __VA_ARGS__) - -// ID_AA64ISAR0_EL1 -// ----------------------------------------------------------------------------- -ID_AA64ISAR0_FEATURES(fhm, AARCH64_ASIMDFHM) -ID_AA64ISAR0_FEATURES(dp, AARCH64_ASIMDDP) -ID_AA64ISAR0_FEATURES(crc32, AARCH64_CRC32) -ID_AA64ISAR0_FEATURES(rdm, AARCH64_ASIMDRDM) -ID_AA64ISAR0_FEATURES(atomics, AARCH64_ATOMICS) -ID_AA64ISAR0_FEATURES(aes, AARCH64_AES) -ID_AA64ISAR0_FEATURES(sha1, AARCH64_SHA1) -ID_AA64ISAR0_FEATURES(sha2, AARCH64_SHA2) -ID_AA64ISAR0_FEATURES(sha3, AARCH64_SHA3) -ID_AA64ISAR0_FEATURES(sm3, AARCH64_SM3) -ID_AA64ISAR0_FEATURES(sm4, AARCH64_SM4) -ID_AA64ISAR0_FEATURES(aes_pmull, AARCH64_AES, AARCH64_PMULL) -ID_AA64ISAR0_FEATURES(sha2_sha512, AARCH64_SHA2, AARCH64_SHA512) -ID_AA64ISAR0_FEATURES(flagm, AARCH64_FLAGM) -ID_AA64ISAR0_FEATURES(flagm2, AARCH64_FLAGM, AARCH64_FLAGM2) -ID_AA64ISAR0_FEATURES(rng, AARCH64_RNG) - -static MrsFeature id_aa64isar0[] = { - ID_AA64ISAR0_SET_FEATURE(fhm, "FHM"), - ID_AA64ISAR0_SET_FEATURE(dp, "DP"), - ID_AA64ISAR0_SET_FEATURE(crc32, "CRC32"), - ID_AA64ISAR0_SET_FEATURE(rdm, "RDM"), - ID_AA64ISAR0_SET_FEATURE(atomics, "Atomic"), - ID_AA64ISAR0_SET_FEATURE(aes, "AES"), - ID_AA64ISAR0_SET_FEATURE(sha1, "SHA1"), - ID_AA64ISAR0_SET_FEATURE(sha2, "SHA2"), - ID_AA64ISAR0_SET_FEATURE(sha3, "SHA3"), - ID_AA64ISAR0_SET_FEATURE(sm3, "SM3"), - ID_AA64ISAR0_SET_FEATURE(sm4, "SM4"), - ID_AA64ISAR0_SET_FEATURE(aes_pmull, "AES+PMULL"), - ID_AA64ISAR0_SET_FEATURE(sha2_sha512, "SHA2+SHA512"), - ID_AA64ISAR0_SET_FEATURE(flagm, "CondM-8.4"), - ID_AA64ISAR0_SET_FEATURE(flagm2, "CondM-8.5"), - ID_AA64ISAR0_SET_FEATURE(rng, "RNG"), - MRS_FEATURE_END, -}; - -// ID_AA64ISAR1_EL1 -// ----------------------------------------------------------------------------- -ID_AA64ISAR1_FEATURES(i8mm, AARCH64_I8MM) -ID_AA64ISAR1_FEATURES(dgh, AARCH64_DGH) -ID_AA64ISAR1_FEATURES(bf16, AARCH64_BF16) -ID_AA64ISAR1_FEATURES(sb, AARCH64_SB) -ID_AA64ISAR1_FEATURES(frint, AARCH64_FRINT) -ID_AA64ISAR1_FEATURES(pacg_gpi, AARCH64_PACG) -ID_AA64ISAR1_FEATURES(pacg_gpa, AARCH64_PACG) -ID_AA64ISAR1_FEATURES(api_pac, AARCH64_PACA) -ID_AA64ISAR1_FEATURES(api_epac, AARCH64_PACA) -ID_AA64ISAR1_FEATURES(api_epac2, AARCH64_PACA) -ID_AA64ISAR1_FEATURES(api_fpac, AARCH64_PACA) -ID_AA64ISAR1_FEATURES(api_fpac_combined, AARCH64_PACA) -ID_AA64ISAR1_FEATURES(paca, AARCH64_PACA) -ID_AA64ISAR1_FEATURES(lrcpc, AARCH64_LRCPC) -ID_AA64ISAR1_FEATURES(ilrcpc, AARCH64_LRCPC, AARCH64_ILRCPC) -ID_AA64ISAR1_FEATURES(fcma, AARCH64_FCMA) -ID_AA64ISAR1_FEATURES(jscvt, AARCH64_JSCVT) -ID_AA64ISAR1_FEATURES(dcpop, AARCH64_DCPOP) -ID_AA64ISAR1_FEATURES(dcpodp, AARCH64_DCPOP, AARCH64_DCPODP) - -static MrsFeature id_aa64isar1[] = { - ID_AA64ISAR1_SET_FEATURE(i8mm, "I8MM"), - ID_AA64ISAR1_SET_FEATURE(dgh, "DGH"), - ID_AA64ISAR1_SET_FEATURE(bf16, "BF16"), - ID_AA64ISAR1_SET_FEATURE(sb, "SB"), - ID_AA64ISAR1_SET_FEATURE(frint, "FRINTTS"), - ID_AA64ISAR1_SET_FEATURE(pacg_gpi, "GPI"), - ID_AA64ISAR1_SET_FEATURE(pacg_gpa, "GPA"), - ID_AA64ISAR1_SET_FEATURE(lrcpc, "RCPC-8.3"), - ID_AA64ISAR1_SET_FEATURE(ilrcpc, "RCPC-8.4"), - ID_AA64ISAR1_SET_FEATURE(fcma, "FCMA"), - ID_AA64ISAR1_SET_FEATURE(jscvt, "JSCVT"), - ID_AA64ISAR1_SET_FEATURE(dcpop, "DCPoP"), - ID_AA64ISAR1_SET_FEATURE(dcpodp, "DCCVADP"), - ID_AA64ISAR1_SET_FEATURE(api_pac, "API PAC"), - ID_AA64ISAR1_SET_FEATURE(api_epac, "API EPAC"), - ID_AA64ISAR1_SET_FEATURE(api_epac2, "Impl PAuth+EPAC2"), - ID_AA64ISAR1_SET_FEATURE(api_fpac, "Impl PAuth+FPAC"), - ID_AA64ISAR1_SET_FEATURE(api_fpac_combined, "Impl PAuth+FPAC+Combined"), - MRS_FEATURE_END, -}; - -// ID_AA64ISAR2_EL1 -// ----------------------------------------------------------------------------- -ID_AA64ISAR2_FEATURES(rpres, AARCH64_RPRES) - -static MrsFeature id_aa64isar2[] = { - ID_AA64ISAR2_SET_FEATURE(rpres, "RPRES"), - MRS_FEATURE_END, -}; - -// ID_AA64PFR0_EL1 -// ----------------------------------------------------------------------------- -ID_AA64PFR0_FEATURES(fp, AARCH64_FP) -ID_AA64PFR0_FEATURES(fphp, AARCH64_FP, AARCH64_FPHP) -ID_AA64PFR0_FEATURES(asimd, AARCH64_ASIMD) -ID_AA64PFR0_FEATURES(asimdhp, AARCH64_ASIMD, AARCH64_ASIMDHP) -ID_AA64PFR0_FEATURES(dit, AARCH64_DIT) -ID_AA64PFR0_FEATURES(sve, AARCH64_SVE) - -static MrsFeature id_aa64pfr0[] = { - ID_AA64PFR0_SET_FEATURE(fp, "FP"), - ID_AA64PFR0_SET_FEATURE(fphp, "FP+HP"), - ID_AA64PFR0_SET_FEATURE(asimd, "AdvSIMD"), - ID_AA64PFR0_SET_FEATURE(asimdhp, "AdvSIMD+HP"), - ID_AA64PFR0_SET_FEATURE(dit, "PSTATE.DIT"), - ID_AA64PFR0_SET_FEATURE(sve, "SVE"), - MRS_FEATURE_END, -}; - -// ID_AA64PFR1_EL1 -// ----------------------------------------------------------------------------- -ID_AA64PFR1_FEATURES(ssbs, AARCH64_SSBS) -// TODO: Add ssbs2 detection -ID_AA64PFR1_FEATURES(ssbs2, AARCH64_SSBS) -ID_AA64PFR1_FEATURES(mte, AARCH64_MTE) -ID_AA64PFR1_FEATURES(bti, AARCH64_BTI) - -static MrsFeature id_aa64pfr1[] = { - ID_AA64PFR1_SET_FEATURE(ssbs, "PSTATE.SSBS"), - ID_AA64PFR1_SET_FEATURE(ssbs2, "PSTATE.SSBS MSR"), - ID_AA64PFR1_SET_FEATURE(mte, "MTE"), - ID_AA64PFR1_SET_FEATURE(bti, "BTI"), - MRS_FEATURE_END, -}; - -// ID_AA64ZFR0_EL1 -// ----------------------------------------------------------------------------- -ID_AA64ZFR0_FEATURES(svef64mm, AARCH64_SVEF64MM) -ID_AA64ZFR0_FEATURES(svef32mm, AARCH64_SVEF32MM) -ID_AA64ZFR0_FEATURES(svei8mm, AARCH64_SVEI8MM) -ID_AA64ZFR0_FEATURES(svesm4, AARCH64_SVESM4) -ID_AA64ZFR0_FEATURES(svesha3, AARCH64_SVESHA3) -ID_AA64ZFR0_FEATURES(svebf16, AARCH64_SVEBF16) -// TODO: Add sveebf16 detection -ID_AA64ZFR0_FEATURES(sveebf16, AARCH64_SVEBF16) -ID_AA64ZFR0_FEATURES(svebitper, AARCH64_SVEBITPERM) -ID_AA64ZFR0_FEATURES(sveaes, AARCH64_SVEAES) -ID_AA64ZFR0_FEATURES(sve_aes_pmull, AARCH64_SVEAES, AARCH64_SVEPMULL) -ID_AA64ZFR0_FEATURES(sve2, AARCH64_SVE2) - -static MrsFeature id_aa64zfr0[] = { - ID_AA64ZFR0_SET_FEATURE(svef64mm, "F64MM"), - ID_AA64ZFR0_SET_FEATURE(svef32mm, "F32MM"), - ID_AA64ZFR0_SET_FEATURE(svei8mm, "I8MM"), - ID_AA64ZFR0_SET_FEATURE(svesm4, "SM4"), - ID_AA64ZFR0_SET_FEATURE(svesha3, "SHA3"), - ID_AA64ZFR0_SET_FEATURE(svebf16, "BF16"), - ID_AA64ZFR0_SET_FEATURE(sveebf16, "BF16+EBF"), - ID_AA64ZFR0_SET_FEATURE(svebitper, "BitPerm"), - ID_AA64ZFR0_SET_FEATURE(sveaes, "AES"), - ID_AA64ZFR0_SET_FEATURE(sve_aes_pmull, "AES+PMULL"), - ID_AA64ZFR0_SET_FEATURE(sve2, "SVE2"), - MRS_FEATURE_END, -}; - -static const MrsField mrs_fields[] = { - MRS_FIELD(ID_AA64ISAR0_KEY, id_aa64isar0), - MRS_FIELD(ID_AA64ISAR1_KEY, id_aa64isar1), - MRS_FIELD(ID_AA64ISAR2_KEY, id_aa64isar2), - MRS_FIELD(ID_AA64PFR0_KEY, id_aa64pfr0), - MRS_FIELD(ID_AA64PFR1_KEY, id_aa64pfr1), - MRS_FIELD(ID_AA64ZFR0_KEY, id_aa64zfr0), - MRS_FIELD_END, -}; - -static bool HasFeature(StringView csv, const char* feature) { - return CpuFeatures_StringView_HasWord(csv, feature, ','); -} - -static bool DetectAarch64Features(StringView csv, MrsFeature* mrs_features, - Aarch64Features* features) { - for (int i = 0; mrs_features[i].name != NULL; ++i) { - MrsFeature mrs_feature = mrs_features[i]; - if (!HasFeature(csv, mrs_feature.name)) continue; - for (int j = 0; mrs_feature.features_enum[j] != AARCH64_FEAT_END; ++j) { - int feat_idx = mrs_feature.features_enum[j]; - kSetters[feat_idx](features, true); - } - } -} - -static bool HandleAarch64Line(const LineResult result, - Aarch64Features* features) { - const StringView line = result.line; - for (int i = 0; mrs_fields[i].key != NULL; ++i) { - MrsField mrs_field = mrs_fields[i]; - if (!CpuFeatures_StringView_StartsWith(line, str(mrs_field.key))) continue; - 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); - } - DetectAarch64Features(csv, mrs_field.features, features); - } - return !result.eof; -} - -static void DetectFeaturesFromOs(Aarch64Features* 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 (;;) { - if (!HandleAarch64Line(StackLineReader_NextLine(&reader), features)) - break; - } - CpuFeatures_CloseFile(fd); - } -} - Aarch64Info GetAarch64Info(void) { Aarch64Info info = kEmptyAarch64Info; - DetectFeaturesFromOs(&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; } From befb237a361046bc74e5591f6d86cea9b330b233 Mon Sep 17 00:00:00 2001 From: Mykola Hohsdze Date: Mon, 10 Apr 2023 23:49:52 +0300 Subject: [PATCH 07/10] Separate Hwacps to freebsd and linux implementation --- BUILD.bazel | 17 ++++++++++++--- CMakeLists.txt | 4 +--- bazel/platforms.bzl | 6 ++++++ include/internal/hwcaps.h | 5 +++++ include/internal/hwcaps_linux_or_android.h | 25 ---------------------- src/hwcaps.c | 2 ++ src/hwcaps_freebsd.c | 22 ++++++++++++++----- src/hwcaps_linux_or_android.c | 5 +---- src/impl_aarch64_freebsd.c | 1 - src/impl_ppc_linux.c | 2 +- src/impl_s390x_linux.c | 2 +- test/CMakeLists.txt | 6 +++++- test/cpuinfo_aarch64_test.cc | 11 +++++----- 13 files changed, 58 insertions(+), 50 deletions(-) delete mode 100644 include/internal/hwcaps_linux_or_android.h diff --git a/BUILD.bazel b/BUILD.bazel index 69259445..14b148a1 100644 --- a/BUILD.bazel +++ b/BUILD.bazel @@ -2,7 +2,7 @@ load("@bazel_skylib//lib:selects.bzl", "selects") load("//:bazel/platforms.bzl", "PLATFORM_CPU_ARM", "PLATFORM_CPU_ARM64", "PLATFORM_CPU_MIPS", "PLATFORM_CPU_PPC", "PLATFORM_CPU_RISCV32", "PLATFORM_CPU_RISCV64", "PLATFORM_CPU_X86_64") -load("//:bazel/platforms.bzl", "PLATFORM_OS_MACOS") +load("//:bazel/platforms.bzl", "PLATFORM_OS_MACOS", "PLATFORM_OS_LINUX", "PLATFORM_OS_FREEBSD", "PLATFORM_OS_ANDROID") package( default_visibility = ["//visibility:public"], @@ -169,11 +169,18 @@ cc_library( cc_library( name = "hwcaps", - srcs = ["src/hwcaps.c"], + srcs = [ + "src/hwcaps.c", + "src/hwcaps_freebsd.c", + "src/hwcaps_linux_or_android.c", + ], copts = C99_FLAGS, defines = selects.with_or({ PLATFORM_OS_MACOS: ["HAVE_DLFCN_H"], - "//conditions:default": ["HAVE_STRONG_GETAUXVAL"], + PLATFORM_OS_FREEBSD: ["HAVE_STRONG_ELF_AUX_INFO"], + PLATFORM_OS_LINUX: ["HAVE_STRONG_GETAUXVAL"], + PLATFORM_OS_ANDROID: ["HAVE_STRONG_GETAUXVAL"], + "//conditions:default": [], }), includes = INCLUDES, textual_hdrs = ["include/internal/hwcaps.h"], @@ -189,6 +196,8 @@ cc_library( testonly = 1, srcs = [ "src/hwcaps.c", + "src/hwcaps_freebsd.c", + "src/hwcaps_linux_or_android.c", "test/hwcaps_for_testing.cc", ], hdrs = [ @@ -221,6 +230,7 @@ cc_library( "src/impl_aarch64_linux_or_android.c", "src/impl_aarch64_macos_or_iphone.c", "src/impl_aarch64_windows.c", + "src/impl_aarch64_freebsd.c", ], PLATFORM_CPU_MIPS: ["src/impl_mips_linux_or_android.c"], PLATFORM_CPU_PPC: ["src/impl_ppc_linux.c"], @@ -281,6 +291,7 @@ cc_library( "src/impl_aarch64_linux_or_android.c", "src/impl_aarch64_macos_or_iphone.c", "src/impl_aarch64_windows.c", + "src/impl_aarch64_freebsd.c", ], PLATFORM_CPU_MIPS: ["src/impl_mips_linux_or_android.c"], PLATFORM_CPU_PPC: ["src/impl_ppc_linux.c"], diff --git a/CMakeLists.txt b/CMakeLists.txt index 76a02e73..a070e944 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -146,7 +146,6 @@ 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/hwcaps_linux_or_android.h ${PROJECT_SOURCE_DIR}/src/hwcaps_linux_or_android.c ${PROJECT_SOURCE_DIR}/src/hwcaps_freebsd.c ${PROJECT_SOURCE_DIR}/src/hwcaps.c @@ -170,8 +169,7 @@ endif() # library : cpu_features # set (CPU_FEATURES_HDRS) -set (CPU_FEATURES_SRCS - include/internal/hwcaps_linux_or_android.h) +set (CPU_FEATURES_SRCS) add_cpu_features_headers_and_sources(CPU_FEATURES_HDRS CPU_FEATURES_SRCS) list(APPEND CPU_FEATURES_SRCS $) if(NOT PROCESSOR_IS_X86 AND UNIX) diff --git a/bazel/platforms.bzl b/bazel/platforms.bzl index eb025cec..7ced3d1d 100644 --- a/bazel/platforms.bzl +++ b/bazel/platforms.bzl @@ -16,3 +16,9 @@ PLATFORM_CPU_RISCV64 = ("@platforms//cpu:riscv64") PLATFORM_OS_MACOS = ("@platforms//os:macos") + +PLATFORM_OS_LINUX = ("@platforms//os:linux") + +PLATFORM_OS_ANDROID = ("@platforms//os:android") + +PLATFORM_OS_FREEBSD = ("@platforms//os:freebsd") diff --git a/include/internal/hwcaps.h b/include/internal/hwcaps.h index 4d0a8073..59e16576 100644 --- a/include/internal/hwcaps.h +++ b/include/internal/hwcaps.h @@ -267,6 +267,11 @@ HardwareCapabilities CpuFeatures_GetHardwareCapabilities(void); bool CpuFeatures_IsHwCapsSet(const HardwareCapabilities hwcaps_mask, const HardwareCapabilities hwcaps); +// Get pointer for the AT_PLATFORM type. +const char* CpuFeatures_GetPlatformPointer(void); +// Get pointer for the AT_BASE_PLATFORM type. +const char* CpuFeatures_GetBasePlatformPointer(void); + CPU_FEATURES_END_CPP_NAMESPACE #endif // CPU_FEATURES_INCLUDE_INTERNAL_HWCAPS_H_ diff --git a/include/internal/hwcaps_linux_or_android.h b/include/internal/hwcaps_linux_or_android.h deleted file mode 100644 index 95d9e46a..00000000 --- a/include/internal/hwcaps_linux_or_android.h +++ /dev/null @@ -1,25 +0,0 @@ -// Copyright 2023 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 CPU_FEATURES_HWCAPS_LINUX_OR_ANDROID_H_ -#define CPU_FEATURES_HWCAPS_LINUX_OR_ANDROID_H_ - -#include "internal/hwcaps.h" - -// Get pointer for the AT_PLATFORM type. -const char* CpuFeatures_GetPlatformPointer(void); -// Get pointer for the AT_BASE_PLATFORM type. -const char* CpuFeatures_GetBasePlatformPointer(void); - -#endif // CPU_FEATURES_HWCAPS_LINUX_OR_ANDROID_H_ diff --git a/src/hwcaps.c b/src/hwcaps.c index 18dd35b3..6e2e9a85 100644 --- a/src/hwcaps.c +++ b/src/hwcaps.c @@ -14,6 +14,8 @@ #include "internal/hwcaps.h" +#include + static bool IsSet(const uint32_t mask, const uint32_t value) { if (mask == 0) return false; return (value & mask) == mask; diff --git a/src/hwcaps_freebsd.c b/src/hwcaps_freebsd.c index 509b75a6..d46bafc9 100644 --- a/src/hwcaps_freebsd.c +++ b/src/hwcaps_freebsd.c @@ -15,14 +15,21 @@ #include "cpu_features_macros.h" #ifdef CPU_FEATURES_ARCH_AARCH64 -#if defined(CPU_FEATURES_OS_FREEBSD) +#ifdef CPU_FEATURES_OS_FREEBSD -#if defined(HAVE_STRONG_ELF_AUX_INFO) +#include "internal/hwcaps.h" + +#ifdef CPU_FEATURES_TEST +// In test mode, hwcaps_for_testing will define the following functions. +HardwareCapabilities CpuFeatures_GetHardwareCapabilities(void); +const char* CpuFeatures_GetPlatformPointer(void); +const char* CpuFeatures_GetBasePlatformPointer(void); +#else + +#ifdef HAVE_STRONG_ELF_AUX_INFO #include #include -#include "internal/hwcaps.h" - static unsigned long GetElfHwcapFromElfAuxInfo(int hwcap_type) { unsigned long hwcap; elf_aux_info(hwcap_type, &hwcap, sizeof(hwcap)); @@ -35,9 +42,14 @@ HardwareCapabilities CpuFeatures_GetHardwareCapabilities(void) { capabilities.hwcaps2 = GetElfHwcapFromElfAuxInfo(AT_HWCAP2); return capabilities; } + +const char *CpuFeatures_GetPlatformPointer(void) { return NULL; } + +const char *CpuFeatures_GetBasePlatformPointer(void) { return NULL; } #else -#error "Error" +#error "FreeBSD needs support for elf_aux_info" #endif // HAVE_STRONG_ELF_AUX_INFO +#endif // CPU_FEATURES_TEST #endif // CPU_FEATURES_OS_FREEBSD #endif // CPU_FEATURES_ARCH_AARCH64 diff --git a/src/hwcaps_linux_or_android.c b/src/hwcaps_linux_or_android.c index 8f7a10a3..d4f58eaf 100644 --- a/src/hwcaps_linux_or_android.c +++ b/src/hwcaps_linux_or_android.c @@ -14,16 +14,14 @@ #include "cpu_features_macros.h" -#ifdef CPU_FEATURES_ARCH_AARCH64 #if defined(CPU_FEATURES_OS_LINUX) || defined(CPU_FEATURES_OS_ANDROID) -#include "internal/hwcaps_linux_or_android.h" - #include #include #include "cpu_features_macros.h" #include "internal/filesystem.h" +#include "internal/hwcaps.h" #include "internal/string_view.h" #ifdef CPU_FEATURES_TEST @@ -157,4 +155,3 @@ const char *CpuFeatures_GetBasePlatformPointer(void) { #endif // CPU_FEATURES_TEST #endif // defined(CPU_FEATURES_OS_LINUX) || defined(CPU_FEATURES_OS_ANDROID) -#endif // CPU_FEATURES_ARCH_AARCH64 diff --git a/src/impl_aarch64_freebsd.c b/src/impl_aarch64_freebsd.c index 677219ef..7caada3e 100644 --- a/src/impl_aarch64_freebsd.c +++ b/src/impl_aarch64_freebsd.c @@ -18,7 +18,6 @@ #ifdef CPU_FEATURES_OS_FREEBSD #include "cpuinfo_aarch64.h" - #include "impl_aarch64__base_implementation.inl" static const Aarch64Info kEmptyAarch64Info; diff --git a/src/impl_ppc_linux.c b/src/impl_ppc_linux.c index 2e1e0f3a..46a72d77 100644 --- a/src/impl_ppc_linux.c +++ b/src/impl_ppc_linux.c @@ -82,7 +82,7 @@ #include "internal/bit_utils.h" #include "internal/filesystem.h" -#include "internal/hwcaps_linux_or_android.h" +#include "internal/hwcaps.h" #include "internal/stack_line_reader.h" #include "internal/string_view.h" diff --git a/src/impl_s390x_linux.c b/src/impl_s390x_linux.c index 534c2c18..2b8b865d 100644 --- a/src/impl_s390x_linux.c +++ b/src/impl_s390x_linux.c @@ -58,7 +58,7 @@ #include "internal/bit_utils.h" #include "internal/filesystem.h" -#include "internal/hwcaps_linux_or_android.h" +#include "internal/hwcaps.h" #include "internal/stack_line_reader.h" #include "internal/string_view.h" diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 122414f2..12f3a214 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -22,7 +22,11 @@ add_library(stack_line_reader_for_test ../src/stack_line_reader.c) target_compile_definitions(stack_line_reader_for_test PUBLIC STACK_LINE_READER_BUFFER_SIZE=16) target_link_libraries(stack_line_reader_for_test string_view filesystem_for_testing) ##------------------------------------------------------------------------------ -add_library(all_libraries ../src/hwcaps.c ../src/stack_line_reader.c) +add_library(all_libraries + ../src/hwcaps.c + ../src/hwcaps_linux_or_android.c + ../src/hwcaps_freebsd.c + ../src/stack_line_reader.c) target_link_libraries(all_libraries hwcaps_for_testing stack_line_reader string_view) # diff --git a/test/cpuinfo_aarch64_test.cc b/test/cpuinfo_aarch64_test.cc index 219a74e8..0c050d63 100644 --- a/test/cpuinfo_aarch64_test.cc +++ b/test/cpuinfo_aarch64_test.cc @@ -127,11 +127,8 @@ TEST_F(CpuidAarch64Test, Aarch64FeaturesEnum) { } } -#if defined(CPU_FEATURES_OS_LINUX) -void DisableHardwareCapabilities() { SetHardwareCapabilities(0, 0); } - -// OS dependent tests -#if defined(CPU_FEATURES_OS_LINUX) +// AT_HWCAP tests +#if defined(CPU_FEATURES_OS_LINUX) || defined(CPU_FEATURES_OS_FREEBSD) TEST_F(CpuidAarch64Test, FromHardwareCap) { ResetHwcaps(); SetHardwareCapabilities(AARCH64_HWCAP_FP | AARCH64_HWCAP_AES, 0); @@ -199,7 +196,10 @@ TEST_F(CpuidAarch64Test, FromHardwareCap2) { EXPECT_FALSE(info.features.dgh); EXPECT_FALSE(info.features.rng); } +#endif // defined(CPU_FEATURES_OS_LINUX) || defined(CPU_FEATURES_OS_FREEBSD) +// OS dependent tests +#if defined(CPU_FEATURES_OS_LINUX) TEST_F(CpuidAarch64Test, ARMCortexA53) { ResetHwcaps(); auto& fs = GetEmptyFilesystem(); @@ -386,7 +386,6 @@ TEST_F(CpuidAarch64Test, WINDOWS_AARCH64_RPI4) { EXPECT_FALSE(info.features.jscvt); EXPECT_FALSE(info.features.lrcpc); } -#endif #endif // CPU_FEATURES_OS_WINDOWS } // namespace } // namespace cpu_features From d773ad7fbfd44fa3eb1c8ee0663bce0d5490b3ca Mon Sep 17 00:00:00 2001 From: Mykola Hohsadze Date: Fri, 15 Sep 2023 05:38:04 +0300 Subject: [PATCH 08/10] Add aarch64 midr_el1 implementation --- BUILD.bazel | 6 ++++- CMakeLists.txt | 1 + include/internal/cpuid_aarch64.h | 28 +++++++++++++++++++++++ src/impl_aarch64_cpuid.c | 39 ++++++++++++++++++++++++++++++++ src/impl_aarch64_freebsd.c | 16 +++++++++++++ 5 files changed, 89 insertions(+), 1 deletion(-) create mode 100644 include/internal/cpuid_aarch64.h create mode 100644 src/impl_aarch64_cpuid.c diff --git a/BUILD.bazel b/BUILD.bazel index 14b148a1..e9f192e3 100644 --- a/BUILD.bazel +++ b/BUILD.bazel @@ -244,7 +244,10 @@ cc_library( "include/internal/windows_utils.h", ], PLATFORM_CPU_ARM: ["include/cpuinfo_arm.h"], - PLATFORM_CPU_ARM64: ["include/cpuinfo_aarch64.h"], + PLATFORM_CPU_ARM64: [ + "include/cpuinfo_aarch64.h", + "include/internal/cpuid_aarch64.h", + ], PLATFORM_CPU_MIPS: ["include/cpuinfo_mips.h"], PLATFORM_CPU_PPC: ["include/cpuinfo_ppc.h"], PLATFORM_CPU_RISCV32: ["include/cpuinfo_riscv.h"], @@ -288,6 +291,7 @@ cc_library( ], PLATFORM_CPU_ARM: ["src/impl_arm_linux_or_android.c"], PLATFORM_CPU_ARM64: [ + "src/impl_aarch64_cpuid.c", "src/impl_aarch64_linux_or_android.c", "src/impl_aarch64_macos_or_iphone.c", "src/impl_aarch64_windows.c", diff --git a/CMakeLists.txt b/CMakeLists.txt index a070e944..5b513493 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -106,6 +106,7 @@ macro(add_cpu_features_headers_and_sources HDRS_LIST_NAME SRCS_LIST_NAME) list(APPEND ${HDRS_LIST_NAME} ${PROJECT_SOURCE_DIR}/include/cpuinfo_arm.h) elseif(PROCESSOR_IS_AARCH64) list(APPEND ${HDRS_LIST_NAME} ${PROJECT_SOURCE_DIR}/include/cpuinfo_aarch64.h) + list(APPEND ${SRCS_LIST_NAME} ${PROJECT_SOURCE_DIR}/include/internal/cpuid_aarch64.h) list(APPEND ${SRCS_LIST_NAME} ${PROJECT_SOURCE_DIR}/include/internal/windows_utils.h) elseif(PROCESSOR_IS_X86) list(APPEND ${HDRS_LIST_NAME} ${PROJECT_SOURCE_DIR}/include/cpuinfo_x86.h) diff --git a/include/internal/cpuid_aarch64.h b/include/internal/cpuid_aarch64.h new file mode 100644 index 00000000..ca70fb0a --- /dev/null +++ b/include/internal/cpuid_aarch64.h @@ -0,0 +1,28 @@ +// Copyright 2023 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 CPU_FEATURES_INCLUDE_CPUID_AARCH64_H_ +#define CPU_FEATURES_INCLUDE_CPUID_AARCH64_H_ + +#include + +#include "cpu_features_macros.h" + +CPU_FEATURES_START_CPP_NAMESPACE + +uint64_t GetMidrEl1(); + +CPU_FEATURES_END_CPP_NAMESPACE + +#endif // CPU_FEATURES_INCLUDE_CPUID_AARCH64_H_ diff --git a/src/impl_aarch64_cpuid.c b/src/impl_aarch64_cpuid.c new file mode 100644 index 00000000..6f7c3697 --- /dev/null +++ b/src/impl_aarch64_cpuid.c @@ -0,0 +1,39 @@ +// Copyright 2023 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 +#ifdef CPU_FEATURES_OS_FREEBSD +#if (defined(CPU_FEATURES_COMPILER_GCC) || defined(CPU_FEATURES_COMPILER_CLANG)) + +#include "internal/cpuid_aarch64.h" + +#ifdef CPU_FEATURES_MOCK_CPUID_AARCH64 +// Implementation will be provided by test/cpuinfo_aarch64_test.cc. +#else + +uint64_t GetMidrEl1() { + uint64_t midr_el1; + __asm("mrs %0, MIDR_EL1" : "=r"(midr_el1)); + return midr_el1; +} +#endif // CPU_FEATURES_MOCK_CPUID_AARCH64 + +#else +#error "Unsupported compiler, aarch64 cpuid requires either GCC or Clang." +#endif // (defined(CPU_FEATURES_COMPILER_GCC) || + // defined(CPU_FEATURES_COMPILER_CLANG)) +#endif // CPU_FEATURES_OS_FREEBSD +#endif // CPU_FEATURES_ARCH_AARCH64 \ No newline at end of file diff --git a/src/impl_aarch64_freebsd.c b/src/impl_aarch64_freebsd.c index 7caada3e..64499ef5 100644 --- a/src/impl_aarch64_freebsd.c +++ b/src/impl_aarch64_freebsd.c @@ -12,13 +12,17 @@ // See the License for the specific language governing permissions and // limitations under the License. +#include + #include "cpu_features_macros.h" #ifdef CPU_FEATURES_ARCH_AARCH64 #ifdef CPU_FEATURES_OS_FREEBSD #include "cpuinfo_aarch64.h" +#include "internal/cpuid_aarch64.h" #include "impl_aarch64__base_implementation.inl" +#include "sys/auxv.h" static const Aarch64Info kEmptyAarch64Info; @@ -30,6 +34,18 @@ Aarch64Info GetAarch64Info(void) { kSetters[i](&info.features, true); } } + + unsigned long hwcap_cpuid; + elf_aux_info(HWCAP_CPUID, &hwcap_cpuid, sizeof(hwcap_cpuid)); + + if (hwcap_cpuid) { + info.features.cpuid = true; + const uint64_t midr_el1 = GetMidrEl1(); + info.implementer = (int) ExtractBitRange(midr_el1, 31, 24); + info.variant = (int) ExtractBitRange(midr_el1, 23, 20); + info.part = (int) ExtractBitRange(midr_el1, 15, 4); + info.revision = (int) ExtractBitRange(midr_el1, 3, 0); + } return info; } From 31793e39d6b05e3f81751070a2d1e315717a1a54 Mon Sep 17 00:00:00 2001 From: Mykola Hohsadze Date: Fri, 15 Sep 2023 21:37:39 +0300 Subject: [PATCH 09/10] Add detection hwcap cpuid to hwcaps.h --- BUILD.bazel | 1 + src/hwcaps_freebsd.c | 3 +-- src/hwcaps_linux_or_android.c | 4 ++++ src/impl_aarch64_cpuid.c | 2 +- src/impl_aarch64_freebsd.c | 21 +++++++-------------- 5 files changed, 14 insertions(+), 17 deletions(-) diff --git a/BUILD.bazel b/BUILD.bazel index e9f192e3..eb19bbc3 100644 --- a/BUILD.bazel +++ b/BUILD.bazel @@ -227,6 +227,7 @@ cc_library( ], PLATFORM_CPU_ARM: ["src/impl_arm_linux_or_android.c"], PLATFORM_CPU_ARM64: [ + "src/impl_aarch64_cpuid.c", "src/impl_aarch64_linux_or_android.c", "src/impl_aarch64_macos_or_iphone.c", "src/impl_aarch64_windows.c", diff --git a/src/hwcaps_freebsd.c b/src/hwcaps_freebsd.c index d46bafc9..eb227504 100644 --- a/src/hwcaps_freebsd.c +++ b/src/hwcaps_freebsd.c @@ -14,7 +14,6 @@ #include "cpu_features_macros.h" -#ifdef CPU_FEATURES_ARCH_AARCH64 #ifdef CPU_FEATURES_OS_FREEBSD #include "internal/hwcaps.h" @@ -46,10 +45,10 @@ HardwareCapabilities CpuFeatures_GetHardwareCapabilities(void) { const char *CpuFeatures_GetPlatformPointer(void) { return NULL; } const char *CpuFeatures_GetBasePlatformPointer(void) { return NULL; } + #else #error "FreeBSD needs support for elf_aux_info" #endif // HAVE_STRONG_ELF_AUX_INFO #endif // CPU_FEATURES_TEST #endif // CPU_FEATURES_OS_FREEBSD -#endif // CPU_FEATURES_ARCH_AARCH64 diff --git a/src/hwcaps_linux_or_android.c b/src/hwcaps_linux_or_android.c index d4f58eaf..4de5b348 100644 --- a/src/hwcaps_linux_or_android.c +++ b/src/hwcaps_linux_or_android.c @@ -153,5 +153,9 @@ const char *CpuFeatures_GetBasePlatformPointer(void) { return (const char *)GetHardwareCapabilitiesFor(AT_BASE_PLATFORM); } +bool CpuFeatures_IsHwCapCpuidSupported() { + return GetElfHwcapFromGetauxval(AARCH64_HWCAP_CPUID); +} + #endif // CPU_FEATURES_TEST #endif // defined(CPU_FEATURES_OS_LINUX) || defined(CPU_FEATURES_OS_ANDROID) diff --git a/src/impl_aarch64_cpuid.c b/src/impl_aarch64_cpuid.c index 6f7c3697..85feb336 100644 --- a/src/impl_aarch64_cpuid.c +++ b/src/impl_aarch64_cpuid.c @@ -36,4 +36,4 @@ uint64_t GetMidrEl1() { #endif // (defined(CPU_FEATURES_COMPILER_GCC) || // defined(CPU_FEATURES_COMPILER_CLANG)) #endif // CPU_FEATURES_OS_FREEBSD -#endif // CPU_FEATURES_ARCH_AARCH64 \ No newline at end of file +#endif // CPU_FEATURES_ARCH_AARCH64 diff --git a/src/impl_aarch64_freebsd.c b/src/impl_aarch64_freebsd.c index 64499ef5..d1696408 100644 --- a/src/impl_aarch64_freebsd.c +++ b/src/impl_aarch64_freebsd.c @@ -12,17 +12,15 @@ // See the License for the specific language governing permissions and // limitations under the License. -#include - #include "cpu_features_macros.h" #ifdef CPU_FEATURES_ARCH_AARCH64 #ifdef CPU_FEATURES_OS_FREEBSD #include "cpuinfo_aarch64.h" -#include "internal/cpuid_aarch64.h" #include "impl_aarch64__base_implementation.inl" -#include "sys/auxv.h" +#include "internal/cpuid_aarch64.h" +#include "internal/hwcaps.h" static const Aarch64Info kEmptyAarch64Info; @@ -34,17 +32,12 @@ Aarch64Info GetAarch64Info(void) { kSetters[i](&info.features, true); } } - - unsigned long hwcap_cpuid; - elf_aux_info(HWCAP_CPUID, &hwcap_cpuid, sizeof(hwcap_cpuid)); - - if (hwcap_cpuid) { - info.features.cpuid = true; + if (info.features.cpuid) { const uint64_t midr_el1 = GetMidrEl1(); - info.implementer = (int) ExtractBitRange(midr_el1, 31, 24); - info.variant = (int) ExtractBitRange(midr_el1, 23, 20); - info.part = (int) ExtractBitRange(midr_el1, 15, 4); - info.revision = (int) ExtractBitRange(midr_el1, 3, 0); + info.implementer = (int)ExtractBitRange(midr_el1, 31, 24); + info.variant = (int)ExtractBitRange(midr_el1, 23, 20); + info.part = (int)ExtractBitRange(midr_el1, 15, 4); + info.revision = (int)ExtractBitRange(midr_el1, 3, 0); } return info; } From a21ff2c818e276cd4ad7ba7dd31df69adb680a5c Mon Sep 17 00:00:00 2001 From: Mykola Hohsadze Date: Sun, 17 Sep 2023 15:21:31 +0300 Subject: [PATCH 10/10] Add MIDR_EL1 tests --- BUILD.bazel | 5 +++- include/internal/cpuid_aarch64.h | 2 +- src/impl_aarch64_cpuid.c | 9 +++--- test/CMakeLists.txt | 1 + test/cpuinfo_aarch64_test.cc | 50 ++++++++++++++++++++++++++++---- 5 files changed, 56 insertions(+), 11 deletions(-) diff --git a/BUILD.bazel b/BUILD.bazel index eb19bbc3..031eb630 100644 --- a/BUILD.bazel +++ b/BUILD.bazel @@ -310,7 +310,10 @@ cc_library( "include/internal/windows_utils.h", ], PLATFORM_CPU_ARM: ["include/cpuinfo_arm.h"], - PLATFORM_CPU_ARM64: ["include/cpuinfo_aarch64.h"], + PLATFORM_CPU_ARM64: [ + "include/cpuinfo_aarch64.h", + "include/internal/cpuid_aarch64.h" + ], PLATFORM_CPU_MIPS: ["include/cpuinfo_mips.h"], PLATFORM_CPU_PPC: ["include/cpuinfo_ppc.h"], PLATFORM_CPU_RISCV32: ["include/cpuinfo_riscv.h"], diff --git a/include/internal/cpuid_aarch64.h b/include/internal/cpuid_aarch64.h index ca70fb0a..a09a4c8a 100644 --- a/include/internal/cpuid_aarch64.h +++ b/include/internal/cpuid_aarch64.h @@ -21,7 +21,7 @@ CPU_FEATURES_START_CPP_NAMESPACE -uint64_t GetMidrEl1(); +uint64_t GetMidrEl1(void); CPU_FEATURES_END_CPP_NAMESPACE diff --git a/src/impl_aarch64_cpuid.c b/src/impl_aarch64_cpuid.c index 85feb336..1ca56cd4 100644 --- a/src/impl_aarch64_cpuid.c +++ b/src/impl_aarch64_cpuid.c @@ -15,7 +15,8 @@ #include "cpu_features_macros.h" #ifdef CPU_FEATURES_ARCH_AARCH64 -#ifdef CPU_FEATURES_OS_FREEBSD +#if (defined(CPU_FEATURES_OS_FREEBSD) || defined(CPU_FEATURES_OS_LINUX) || \ + defined(CPU_FEATURES_OS_ANDROID)) #if (defined(CPU_FEATURES_COMPILER_GCC) || defined(CPU_FEATURES_COMPILER_CLANG)) #include "internal/cpuid_aarch64.h" @@ -23,8 +24,7 @@ #ifdef CPU_FEATURES_MOCK_CPUID_AARCH64 // Implementation will be provided by test/cpuinfo_aarch64_test.cc. #else - -uint64_t GetMidrEl1() { +uint64_t GetMidrEl1(void) { uint64_t midr_el1; __asm("mrs %0, MIDR_EL1" : "=r"(midr_el1)); return midr_el1; @@ -35,5 +35,6 @@ uint64_t GetMidrEl1() { #error "Unsupported compiler, aarch64 cpuid requires either GCC or Clang." #endif // (defined(CPU_FEATURES_COMPILER_GCC) || // defined(CPU_FEATURES_COMPILER_CLANG)) -#endif // CPU_FEATURES_OS_FREEBSD +#endif // (defined(CPU_FEATURES_OS_FREEBSD) || defined(CPU_FEATURES_OS_LINUX) + // || defined(CPU_FEATURES_OS_ANDROID)) #endif // CPU_FEATURES_ARCH_AARCH64 diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 12f3a214..d2177f22 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -77,6 +77,7 @@ endif() if(PROCESSOR_IS_AARCH64) add_executable(cpuinfo_aarch64_test cpuinfo_aarch64_test.cc + ../src/impl_aarch64_cpuid.c ../src/impl_aarch64_linux_or_android.c ../src/impl_aarch64_windows.c ../src/impl_aarch64_macos_or_iphone.c diff --git a/test/cpuinfo_aarch64_test.cc b/test/cpuinfo_aarch64_test.cc index 0c050d63..7836d949 100644 --- a/test/cpuinfo_aarch64_test.cc +++ b/test/cpuinfo_aarch64_test.cc @@ -22,11 +22,20 @@ #if defined(CPU_FEATURES_OS_WINDOWS) #include "internal/windows_utils.h" #endif // CPU_FEATURES_OS_WINDOWS +#if defined(CPU_FEATURES_OS_FREEBSD) || defined(CPU_FEATURES_OS_LINUX) +#include "internal/cpuid_aarch64.h" +#endif // defined(CPU_FEATURES_OS_FREEBSD) || defined(CPU_FEATURES_OS_LINUX) namespace cpu_features { class FakeCpuAarch64 { -#if defined(CPU_FEATURES_OS_LINUX) - // No particular implementation for Linux as we use /proc/cpuinfo +#if defined(CPU_FEATURES_OS_FREEBSD) || defined(CPU_FEATURES_OS_LINUX) + public: + uint64_t GetMidrEl1() const { return _midr_el1; } + + void SetMidrEl1(uint64_t midr_el1) { _midr_el1 = midr_el1; } + + private: + uint64_t _midr_el1; #elif defined(CPU_FEATURES_OS_MACOS) std::set darwin_sysctlbyname_; std::map darwin_sysctlbynamevalue_; @@ -80,8 +89,8 @@ static FakeCpuAarch64& cpu() { } // Define OS dependent mock functions -#if defined(CPU_FEATURES_OS_LINUX) -// No particular functions to implement for Linux as we use /proc/cpuinfo +#if defined(CPU_FEATURES_OS_FREEBSD) || defined(CPU_FEATURES_OS_LINUX) +extern "C" uint64_t GetMidrEl1(void) { return cpu().GetMidrEl1(); } #elif defined(CPU_FEATURES_OS_MACOS) extern "C" bool GetDarwinSysCtlByName(const char* name) { return cpu().GetDarwinSysCtlByName(name); @@ -386,6 +395,37 @@ TEST_F(CpuidAarch64Test, WINDOWS_AARCH64_RPI4) { EXPECT_FALSE(info.features.jscvt); EXPECT_FALSE(info.features.lrcpc); } -#endif // CPU_FEATURES_OS_WINDOWS +#elif defined(CPU_FEATURES_OS_FREEBSD) +TEST_F(CpuidAarch64Test, MrsMidrEl1_RPI4) { + ResetHwcaps(); + SetHardwareCapabilities(AARCH64_HWCAP_FP | AARCH64_HWCAP_CPUID, 0); + cpu().SetMidrEl1(0x410FD083); + const auto info = GetAarch64Info(); + + EXPECT_EQ(info.implementer, 0x41); + EXPECT_EQ(info.variant, 0); + EXPECT_EQ(info.part, 0xD08); + EXPECT_EQ(info.revision, 0x3); + + EXPECT_TRUE(info.features.fp); + + EXPECT_FALSE(info.features.dcpodp); + EXPECT_FALSE(info.features.sveaes); + EXPECT_FALSE(info.features.svepmull); + EXPECT_FALSE(info.features.svebitperm); + EXPECT_FALSE(info.features.svesha3); + EXPECT_FALSE(info.features.svesm4); + EXPECT_FALSE(info.features.flagm2); + EXPECT_FALSE(info.features.frint); + EXPECT_FALSE(info.features.svei8mm); + EXPECT_FALSE(info.features.svef32mm); + EXPECT_FALSE(info.features.svef64mm); + EXPECT_FALSE(info.features.svebf16); + EXPECT_FALSE(info.features.i8mm); + EXPECT_FALSE(info.features.bf16); + EXPECT_FALSE(info.features.dgh); + EXPECT_FALSE(info.features.rng); +} +#endif // CPU_FEATURES_OS_FREEBSD } // namespace } // namespace cpu_features