From bfd109b68766061f7ba572656b480f038a0ab460 Mon Sep 17 00:00:00 2001 From: "Dr.-Ing. Patrick Siegl" Date: Wed, 26 Jun 2019 12:56:52 +0200 Subject: [PATCH] Completed all missing ARM hwcaps. (#79) --- include/cpuinfo_arm.h | 16 +++++++ include/internal/hwcaps.h | 8 ++++ src/cpuinfo_arm.c | 46 +++++++++++++++++++ test/cpuinfo_arm_test.cc | 93 ++++++++++++++++++++++++++++++++++++++- 4 files changed, 161 insertions(+), 2 deletions(-) diff --git a/include/cpuinfo_arm.h b/include/cpuinfo_arm.h index 8389082..bd92ac8 100644 --- a/include/cpuinfo_arm.h +++ b/include/cpuinfo_arm.h @@ -21,13 +21,18 @@ CPU_FEATURES_START_CPP_NAMESPACE typedef struct { + int swp : 1; // SWP instruction (atomic read-modify-write) int half : 1; // Half-word loads and stores int thumb : 1; // Thumb (16-bit instruction set) + int _26bit : 1; // "26 Bit" Model (Processor status register folded into program counter) int fastmult : 1; // 32x32->64-bit multiplication + int fpa : 1; // Floating point accelerator int vfp : 1; // Vector Floating Point. int edsp : 1; // DSP extensions (the 'e' variant of the ARM9 CPUs, and all others above) int java : 1; // Jazelle (Java bytecode accelerator) int iwmmxt : 1; // Intel Wireless MMX Technology. + int crunch : 1; // MaverickCrunch coprocessor + int thumbee : 1; // ThumbEE int neon : 1; // Advanced SIMD. int vfpv3 : 1; // VFP version 3 int vfpv3d16 : 1; // VFP version 3 with 16 D-registers @@ -35,6 +40,9 @@ typedef struct { int vfpv4 : 1; // VFP version 4 with fast context switching int idiva : 1; // SDIV and UDIV hardware division in ARM mode. int idivt : 1; // SDIV and UDIV hardware division in Thumb mode. + int vfpd32 : 1; // VFP with 32 D-registers + int lpae : 1; // Large Physical Address Extension (>4GB physical memory on 32-bit architecture) + int evtstrm : 1; // kernel event stream using generic architected timer int aes : 1; // Hardware-accelerated Advanced Encryption Standard. int pmull : 1; // Polynomial multiply long. int sha1 : 1; // Hardware-accelerated SHA1. @@ -65,13 +73,18 @@ uint32_t GetArmCpuId(const ArmInfo* const info); // Introspection functions typedef enum { + ARM_SWP, ARM_HALF, ARM_THUMB, + ARM_26BIT, ARM_FASTMULT, + ARM_FPA, ARM_VFP, ARM_EDSP, ARM_JAVA, ARM_IWMMXT, + ARM_CRUNCH, + ARM_THUMBEE, ARM_NEON, ARM_VFPV3, ARM_VFPV3D16, @@ -79,6 +92,9 @@ typedef enum { ARM_VFPV4, ARM_IDIVA, ARM_IDIVT, + ARM_VFPD32, + ARM_LPAE, + ARM_EVTSTRM, ARM_AES, ARM_PMULL, ARM_SHA1, diff --git a/include/internal/hwcaps.h b/include/internal/hwcaps.h index 222ea71..06a0f60 100644 --- a/include/internal/hwcaps.h +++ b/include/internal/hwcaps.h @@ -35,13 +35,18 @@ CPU_FEATURES_START_CPP_NAMESPACE #define AARCH64_HWCAP_CRC32 (1UL << 7) // http://elixir.free-electrons.com/linux/latest/source/arch/arm/include/uapi/asm/hwcap.h +#define ARM_HWCAP_SWP (1UL << 0) #define ARM_HWCAP_HALF (1UL << 1) #define ARM_HWCAP_THUMB (1UL << 2) +#define ARM_HWCAP_26BIT (1UL << 3) #define ARM_HWCAP_FAST_MULT (1UL << 4) +#define ARM_HWCAP_FPA (1UL << 5) #define ARM_HWCAP_VFP (1UL << 6) #define ARM_HWCAP_EDSP (1UL << 7) #define ARM_HWCAP_JAVA (1UL << 8) #define ARM_HWCAP_IWMMXT (1UL << 9) +#define ARM_HWCAP_CRUNCH (1UL << 10) +#define ARM_HWCAP_THUMBEE (1UL << 11) #define ARM_HWCAP_NEON (1UL << 12) #define ARM_HWCAP_VFPV3 (1UL << 13) #define ARM_HWCAP_VFPV3D16 (1UL << 14) @@ -49,6 +54,9 @@ CPU_FEATURES_START_CPP_NAMESPACE #define ARM_HWCAP_VFPV4 (1UL << 16) #define ARM_HWCAP_IDIVA (1UL << 17) #define ARM_HWCAP_IDIVT (1UL << 18) +#define ARM_HWCAP_VFPD32 (1UL << 19) +#define ARM_HWCAP_LPAE (1UL << 20) +#define ARM_HWCAP_EVTSTRM (1UL << 21) #define ARM_HWCAP2_AES (1UL << 0) #define ARM_HWCAP2_PMULL (1UL << 1) #define ARM_HWCAP2_SHA1 (1UL << 2) diff --git a/src/cpuinfo_arm.c b/src/cpuinfo_arm.c index 16cf748..096e6ae 100644 --- a/src/cpuinfo_arm.c +++ b/src/cpuinfo_arm.c @@ -23,13 +23,18 @@ #include +DECLARE_SETTER(ArmFeatures, swp) DECLARE_SETTER(ArmFeatures, half) DECLARE_SETTER(ArmFeatures, thumb) +DECLARE_SETTER(ArmFeatures, _26bit) DECLARE_SETTER(ArmFeatures, fastmult) +DECLARE_SETTER(ArmFeatures, fpa) DECLARE_SETTER(ArmFeatures, vfp) DECLARE_SETTER(ArmFeatures, edsp) DECLARE_SETTER(ArmFeatures, java) DECLARE_SETTER(ArmFeatures, iwmmxt) +DECLARE_SETTER(ArmFeatures, crunch) +DECLARE_SETTER(ArmFeatures, thumbee) DECLARE_SETTER(ArmFeatures, neon) DECLARE_SETTER(ArmFeatures, vfpv3) DECLARE_SETTER(ArmFeatures, vfpv3d16) @@ -37,6 +42,9 @@ DECLARE_SETTER(ArmFeatures, tls) DECLARE_SETTER(ArmFeatures, vfpv4) DECLARE_SETTER(ArmFeatures, idiva) DECLARE_SETTER(ArmFeatures, idivt) +DECLARE_SETTER(ArmFeatures, vfpd32) +DECLARE_SETTER(ArmFeatures, lpae) +DECLARE_SETTER(ArmFeatures, evtstrm) DECLARE_SETTER(ArmFeatures, aes) DECLARE_SETTER(ArmFeatures, pmull) DECLARE_SETTER(ArmFeatures, sha1) @@ -44,13 +52,18 @@ DECLARE_SETTER(ArmFeatures, sha2) DECLARE_SETTER(ArmFeatures, crc32) static const CapabilityConfig kConfigs[] = { + {{ARM_HWCAP_SWP, 0}, "swp", &set_swp}, // {{ARM_HWCAP_HALF, 0}, "half", &set_half}, // {{ARM_HWCAP_THUMB, 0}, "thumb", &set_thumb}, // + {{ARM_HWCAP_26BIT, 0}, "26bit", &set__26bit}, // {{ARM_HWCAP_FAST_MULT, 0}, "fastmult", &set_fastmult}, // + {{ARM_HWCAP_FPA, 0}, "fpa", &set_fpa}, // {{ARM_HWCAP_VFP, 0}, "vfp", &set_vfp}, // {{ARM_HWCAP_EDSP, 0}, "edsp", &set_edsp}, // {{ARM_HWCAP_JAVA, 0}, "java", &set_java}, // {{ARM_HWCAP_IWMMXT, 0}, "iwmmxt", &set_iwmmxt}, // + {{ARM_HWCAP_CRUNCH, 0}, "crunch", &set_crunch}, // + {{ARM_HWCAP_THUMBEE, 0}, "thumbee", &set_thumbee}, // {{ARM_HWCAP_NEON, 0}, "neon", &set_neon}, // {{ARM_HWCAP_VFPV3, 0}, "vfpv3", &set_vfpv3}, // {{ARM_HWCAP_VFPV3D16, 0}, "vfpv3d16", &set_vfpv3d16}, // @@ -58,6 +71,9 @@ static const CapabilityConfig kConfigs[] = { {{ARM_HWCAP_VFPV4, 0}, "vfpv4", &set_vfpv4}, // {{ARM_HWCAP_IDIVA, 0}, "idiva", &set_idiva}, // {{ARM_HWCAP_IDIVT, 0}, "idivt", &set_idivt}, // + {{ARM_HWCAP_VFPD32, 0}, "vfpd32", &set_vfpd32}, // + {{ARM_HWCAP_LPAE, 0}, "lpae", &set_lpae}, // + {{ARM_HWCAP_EVTSTRM, 0}, "evtstrm", &set_evtstrm}, // {{0, ARM_HWCAP2_AES}, "aes", &set_aes}, // {{0, ARM_HWCAP2_PMULL}, "pmull", &set_pmull}, // {{0, ARM_HWCAP2_SHA1}, "sha1", &set_sha1}, // @@ -208,12 +224,18 @@ ArmInfo GetArmInfo(void) { int GetArmFeaturesEnumValue(const ArmFeatures* features, ArmFeaturesEnum value) { switch (value) { + case ARM_SWP: + return features->swp; case ARM_HALF: return features->half; case ARM_THUMB: return features->thumb; + case ARM_26BIT: + return features->_26bit; case ARM_FASTMULT: return features->fastmult; + case ARM_FPA: + return features->fpa; case ARM_VFP: return features->vfp; case ARM_EDSP: @@ -222,6 +244,10 @@ int GetArmFeaturesEnumValue(const ArmFeatures* features, return features->java; case ARM_IWMMXT: return features->iwmmxt; + case ARM_CRUNCH: + return features->crunch; + case ARM_THUMBEE: + return features->thumbee; case ARM_NEON: return features->neon; case ARM_VFPV3: @@ -236,6 +262,12 @@ int GetArmFeaturesEnumValue(const ArmFeatures* features, return features->idiva; case ARM_IDIVT: return features->idivt; + case ARM_VFPD32: + return features->vfpd32; + case ARM_LPAE: + return features->lpae; + case ARM_EVTSTRM: + return features->evtstrm; case ARM_AES: return features->aes; case ARM_PMULL: @@ -254,12 +286,16 @@ int GetArmFeaturesEnumValue(const ArmFeatures* features, const char* GetArmFeaturesEnumName(ArmFeaturesEnum value) { switch (value) { + case ARM_SWP: + return "swp"; case ARM_HALF: return "half"; case ARM_THUMB: return "thumb"; case ARM_FASTMULT: return "fastmult"; + case ARM_FPA: + return "fpa"; case ARM_VFP: return "vfp"; case ARM_EDSP: @@ -268,6 +304,10 @@ const char* GetArmFeaturesEnumName(ArmFeaturesEnum value) { return "java"; case ARM_IWMMXT: return "iwmmxt"; + case ARM_CRUNCH: + return "crunch"; + case ARM_THUMBEE: + return "thumbee"; case ARM_NEON: return "neon"; case ARM_VFPV3: @@ -282,6 +322,12 @@ const char* GetArmFeaturesEnumName(ArmFeaturesEnum value) { return "idiva"; case ARM_IDIVT: return "idivt"; + case ARM_VFPD32: + return "vfpd32"; + case ARM_LPAE: + return "lpae"; + case ARM_EVTSTRM: + return "evtstrm"; case ARM_AES: return "aes"; case ARM_PMULL: diff --git a/test/cpuinfo_arm_test.cc b/test/cpuinfo_arm_test.cc index 59d8022..9ddf90f 100644 --- a/test/cpuinfo_arm_test.cc +++ b/test/cpuinfo_arm_test.cc @@ -35,6 +35,8 @@ TEST(CpuinfoArmTest, FromHardwareCap) { EXPECT_FALSE(info.features.vfpv4); EXPECT_FALSE(info.features.iwmmxt); + EXPECT_FALSE(info.features.crunch); + EXPECT_FALSE(info.features.thumbee); EXPECT_FALSE(info.features.vfpv3d16); EXPECT_FALSE(info.features.idiva); EXPECT_FALSE(info.features.idivt); @@ -62,13 +64,18 @@ CPU revision : 3)"); EXPECT_EQ(info.revision, 3); EXPECT_EQ(info.architecture, 7); + EXPECT_FALSE(info.features.swp); EXPECT_TRUE(info.features.half); EXPECT_TRUE(info.features.thumb); + EXPECT_FALSE(info.features._26bit); EXPECT_TRUE(info.features.fastmult); + EXPECT_FALSE(info.features.fpa); EXPECT_TRUE(info.features.vfp); EXPECT_TRUE(info.features.edsp); EXPECT_FALSE(info.features.java); EXPECT_FALSE(info.features.iwmmxt); + EXPECT_FALSE(info.features.crunch); + EXPECT_FALSE(info.features.thumbee); EXPECT_TRUE(info.features.neon); EXPECT_TRUE(info.features.vfpv3); EXPECT_FALSE(info.features.vfpv3d16); @@ -76,6 +83,9 @@ CPU revision : 3)"); EXPECT_TRUE(info.features.vfpv4); EXPECT_TRUE(info.features.idiva); EXPECT_TRUE(info.features.idivt); + EXPECT_TRUE(info.features.vfpd32); + EXPECT_TRUE(info.features.lpae); + EXPECT_FALSE(info.features.evtstrm); EXPECT_FALSE(info.features.aes); EXPECT_FALSE(info.features.pmull); EXPECT_FALSE(info.features.sha1); @@ -84,10 +94,10 @@ CPU revision : 3)"); } // Linux test-case -TEST(CpuinfoArmTest, RaspberryPiZero) { +TEST(CpuinfoArmTest, RaspberryPiZeroFromCpuInfo) { DisableHardwareCapabilities(); auto& fs = GetEmptyFilesystem(); - fs.CreateFile("/proc/cpuinfo", R"(processor : 0 + fs.CreateFile("/proc/cpuinfo", R"(processor : 0 model name : ARMv6-compatible processor rev 7 (v6l) BogoMIPS : 697.95 Features : half thumb fastmult vfp edsp java tls @@ -107,13 +117,18 @@ Serial : 000000006cd946f3)"); EXPECT_EQ(info.revision, 7); EXPECT_EQ(info.architecture, 6); + EXPECT_FALSE(info.features.swp); EXPECT_TRUE(info.features.half); EXPECT_TRUE(info.features.thumb); + EXPECT_FALSE(info.features._26bit); EXPECT_TRUE(info.features.fastmult); + EXPECT_FALSE(info.features.fpa); EXPECT_TRUE(info.features.vfp); EXPECT_TRUE(info.features.edsp); EXPECT_TRUE(info.features.java); EXPECT_FALSE(info.features.iwmmxt); + EXPECT_FALSE(info.features.crunch); + EXPECT_FALSE(info.features.thumbee); EXPECT_FALSE(info.features.neon); EXPECT_FALSE(info.features.vfpv3); EXPECT_FALSE(info.features.vfpv3d16); @@ -121,6 +136,71 @@ Serial : 000000006cd946f3)"); EXPECT_FALSE(info.features.vfpv4); EXPECT_FALSE(info.features.idiva); EXPECT_FALSE(info.features.idivt); + EXPECT_FALSE(info.features.vfpd32); + EXPECT_FALSE(info.features.lpae); + EXPECT_FALSE(info.features.evtstrm); + EXPECT_FALSE(info.features.aes); + EXPECT_FALSE(info.features.pmull); + EXPECT_FALSE(info.features.sha1); + EXPECT_FALSE(info.features.sha2); + EXPECT_FALSE(info.features.crc32); +} + +TEST(CpuinfoArmTest, MarvellArmadaFromCpuInfo) { + DisableHardwareCapabilities(); + auto& fs = GetEmptyFilesystem(); + fs.CreateFile("/proc/cpuinfo", R"(processor : 0 +model name : ARMv7 Processor rev 1 (v7l) +BogoMIPS : 50.00 +Features : half thumb fastmult vfp edsp neon vfpv3 tls vfpd32 +CPU implementer : 0x41 +CPU architecture: 7 +CPU variant : 0x4 +CPU part : 0xc09 +CPU revision : 1 + +processor : 1 +model name : ARMv7 Processor rev 1 (v7l) +BogoMIPS : 50.00 +Features : half thumb fastmult vfp edsp neon vfpv3 tls vfpd32 +CPU implementer : 0x41 +CPU architecture: 7 +CPU variant : 0x4 +CPU part : 0xc09 +CPU revision : 1 + +Hardware : Marvell Armada 380/385 (Device Tree) +Revision : 0000 +Serial : 0000000000000000)"); + const auto info = GetArmInfo(); + EXPECT_EQ(info.implementer, 0x41); + EXPECT_EQ(info.variant, 0x4); + EXPECT_EQ(info.part, 0xc09); + EXPECT_EQ(info.revision, 1); + EXPECT_EQ(info.architecture, 7); + + EXPECT_FALSE(info.features.swp); + EXPECT_TRUE(info.features.half); + EXPECT_TRUE(info.features.thumb); + EXPECT_FALSE(info.features._26bit); + EXPECT_TRUE(info.features.fastmult); + EXPECT_FALSE(info.features.fpa); + EXPECT_TRUE(info.features.vfp); + EXPECT_TRUE(info.features.edsp); + EXPECT_FALSE(info.features.java); + EXPECT_FALSE(info.features.iwmmxt); + EXPECT_FALSE(info.features.crunch); + EXPECT_FALSE(info.features.thumbee); + EXPECT_TRUE(info.features.neon); + EXPECT_TRUE(info.features.vfpv3); + EXPECT_FALSE(info.features.vfpv3d16); + EXPECT_TRUE(info.features.tls); + EXPECT_FALSE(info.features.vfpv4); + EXPECT_FALSE(info.features.idiva); + EXPECT_FALSE(info.features.idivt); + EXPECT_TRUE(info.features.vfpd32); + EXPECT_FALSE(info.features.lpae); + EXPECT_FALSE(info.features.evtstrm); EXPECT_FALSE(info.features.aes); EXPECT_FALSE(info.features.pmull); EXPECT_FALSE(info.features.sha1); @@ -149,13 +229,18 @@ Serial : 33323613546d00ec )"); const auto info = GetArmInfo(); EXPECT_EQ(info.architecture, 6); + EXPECT_TRUE(info.features.swp); EXPECT_TRUE(info.features.half); EXPECT_TRUE(info.features.thumb); + EXPECT_FALSE(info.features._26bit); EXPECT_TRUE(info.features.fastmult); + EXPECT_FALSE(info.features.fpa); EXPECT_TRUE(info.features.vfp); EXPECT_TRUE(info.features.edsp); EXPECT_TRUE(info.features.java); EXPECT_FALSE(info.features.iwmmxt); + EXPECT_FALSE(info.features.crunch); + EXPECT_FALSE(info.features.thumbee); EXPECT_FALSE(info.features.neon); EXPECT_FALSE(info.features.vfpv3); EXPECT_FALSE(info.features.vfpv3d16); @@ -163,6 +248,9 @@ Serial : 33323613546d00ec )"); EXPECT_FALSE(info.features.vfpv4); EXPECT_FALSE(info.features.idiva); EXPECT_FALSE(info.features.idivt); + EXPECT_FALSE(info.features.vfpd32); + EXPECT_FALSE(info.features.lpae); + EXPECT_FALSE(info.features.evtstrm); EXPECT_FALSE(info.features.aes); EXPECT_FALSE(info.features.pmull); EXPECT_FALSE(info.features.sha1); @@ -193,6 +281,7 @@ Hardware: SAMSUNG M2 Revision: 0010 Serial: 00001e030000354e)"); const auto info = GetArmInfo(); + EXPECT_TRUE(info.features.swp); EXPECT_FALSE(info.features.neon); }