diff options
author | Marat Dukhan <maratek@gmail.com> | 2017-05-09 13:19:39 +0000 |
---|---|---|
committer | Marat Dukhan <maratek@gmail.com> | 2017-05-09 13:19:39 +0000 |
commit | ab42e7e6d27b15a2de7b829c3d1c667f99ffb2c5 (patch) | |
tree | ded38c912b6bcbae8282bca17dae5023fde96388 | |
parent | f55f67ea447f06a34ff0cd53b3b0b7ef54132d2c (diff) | |
download | cpuinfo-ab42e7e6d27b15a2de7b829c3d1c667f99ffb2c5.tar.gz |
Support ARM64 targets
-rwxr-xr-x | configure.py | 12 | ||||
-rw-r--r-- | include/cpuinfo.h | 53 | ||||
-rw-r--r-- | src/arm/api.h | 2 | ||||
-rw-r--r-- | src/arm/linux/api.h | 125 | ||||
-rw-r--r-- | src/arm/linux/cpuinfo.c | 80 | ||||
-rw-r--r-- | src/arm/linux/init.c | 71 | ||||
-rw-r--r-- | src/arm/linux/isa.c | 48 | ||||
-rw-r--r-- | src/arm/linux/isa64.c | 54 | ||||
-rw-r--r-- | src/arm/uarch.c | 10 | ||||
-rw-r--r-- | src/init.c | 2 | ||||
-rw-r--r-- | tools/isa-info.c | 15 |
11 files changed, 333 insertions, 139 deletions
diff --git a/configure.py b/configure.py index 032842a..98885b8 100755 --- a/configure.py +++ b/configure.py @@ -33,14 +33,18 @@ def main(args): elif build.target.is_linux: sources += ["x86/linux/init.c"] sources.append("x86/isa.c" if not build.target.is_nacl else "x86/nacl/isa.c") - if build.target.is_arm: + if build.target.is_arm or build.target.is_arm64: sources += ["arm/uarch.c", "arm/cache.c"] if build.target.is_linux: sources += [ "arm/linux/init.c", - "arm/linux/isa.c", "arm/linux/cpuinfo.c" ] + if build.target.is_arm: + sources.append("arm/linux/isa.c") + elif build.target.is_arm64: + sources.append("arm/linux/isa64.c") + if build.target.is_macos: sources += ["mach/topology.c"] if build.target.is_linux: @@ -65,12 +69,14 @@ def main(args): build.unittest("pandaboard-es-test", build.cxx("pandaboard-es.cc")) build.unittest("odroid-u2-test", build.cxx("odroid-u2.cc")) build.unittest("arndaleboard-test", build.cxx("arndaleboard.cc")) - build.unittest("jetson-tx1-test", build.cxx("jetson-tx1.cc")) build.unittest("nexus-s-test", build.cxx("nexus-s.cc")) build.unittest("galaxy-nexus-test", build.cxx("galaxy-nexus.cc")) build.unittest("nexus4-test", build.cxx("nexus4.cc")) build.unittest("nexus5-test", build.cxx("nexus5.cc")) + + if (build.target.is_arm or build.target.is_arm64) and build.target.is_linux: + build.unittest("jetson-tx1-test", build.cxx("jetson-tx1.cc")) build.unittest("nexus9-test", build.cxx("nexus9.cc")) return build diff --git a/include/cpuinfo.h b/include/cpuinfo.h index 63e6394..f1f1bf9 100644 --- a/include/cpuinfo.h +++ b/include/cpuinfo.h @@ -187,28 +187,37 @@ }; #endif -#if CPUINFO_ARCH_ARM +#if CPUINFO_ARCH_ARM || CPUINFO_ARCH_ARM64 struct cpuinfo_arm_isa { - bool thumb; - bool thumb2; - bool thumbee; - bool jazelle; - bool armv5e; - bool armv6; - bool armv6k; - bool armv7; - bool armv7mp; - bool idiv; - - bool vfpv2; - bool vfpv3; - bool d32; - bool fp16; - bool fma; - - bool wmmx; - bool wmmx2; - bool neon; + #if CPUINFO_ARCH_ARM + bool thumb; + bool thumb2; + bool thumbee; + bool jazelle; + bool armv5e; + bool armv6; + bool armv6k; + bool armv7; + bool armv7mp; + bool idiv; + + bool vfpv2; + bool vfpv3; + bool d32; + bool fp16; + bool fma; + + bool wmmx; + bool wmmx2; + bool neon; + #endif + #if CPUINFO_ARCH_ARM64 + bool atomics; + bool rdm; + bool fp16arith; + bool jscvt; + bool fcma; + #endif bool aes; bool sha1; @@ -607,7 +616,7 @@ void CPUINFO_ABI cpuinfo_deinitialize(void); extern struct cpuinfo_x86_isa cpuinfo_isa; #endif -#if CPUINFO_ARCH_ARM +#if CPUINFO_ARCH_ARM || CPUINFO_ARCH_ARM64 extern struct cpuinfo_arm_isa cpuinfo_isa; #endif diff --git a/src/arm/api.h b/src/arm/api.h index 3da0cf3..e68c2ef 100644 --- a/src/arm/api.h +++ b/src/arm/api.h @@ -9,7 +9,9 @@ void cpuinfo_arm_decode_vendor_uarch( uint32_t cpu_implementer, uint32_t cpu_part, +#if CPUINFO_ARCH_ARM bool has_vfpv4, +#endif enum cpuinfo_vendor vendor[restrict static 1], enum cpuinfo_uarch uarch[restrict static 1]); diff --git a/src/arm/linux/api.h b/src/arm/linux/api.h index fe0dc1e..cd62700 100644 --- a/src/arm/linux/api.h +++ b/src/arm/linux/api.h @@ -26,37 +26,57 @@ struct proc_cpuinfo_cache { uint32_t d_sets; }; -/* arch/arm/include/uapi/asm/hwcap.h */ +#if CPUINFO_ARCH_ARM + /* arch/arm/include/uapi/asm/hwcap.h */ -#define PROC_CPUINFO_FEATURE_SWP UINT32_C(0x00000001) -#define PROC_CPUINFO_FEATURE_HALF UINT32_C(0x00000002) -#define PROC_CPUINFO_FEATURE_THUMB UINT32_C(0x00000004) -#define PROC_CPUINFO_FEATURE_26BIT UINT32_C(0x00000008) -#define PROC_CPUINFO_FEATURE_FASTMULT UINT32_C(0x00000010) -#define PROC_CPUINFO_FEATURE_FPA UINT32_C(0x00000020) -#define PROC_CPUINFO_FEATURE_VFP UINT32_C(0x00000040) -#define PROC_CPUINFO_FEATURE_EDSP UINT32_C(0x00000080) -#define PROC_CPUINFO_FEATURE_JAVA UINT32_C(0x00000100) -#define PROC_CPUINFO_FEATURE_IWMMXT UINT32_C(0x00000200) -#define PROC_CPUINFO_FEATURE_CRUNCH UINT32_C(0x00000400) -#define PROC_CPUINFO_FEATURE_THUMBEE UINT32_C(0x00000800) -#define PROC_CPUINFO_FEATURE_NEON UINT32_C(0x00001000) -#define PROC_CPUINFO_FEATURE_VFPV3 UINT32_C(0x00002000) -#define PROC_CPUINFO_FEATURE_VFPV3D16 UINT32_C(0x00004000) /* Also set for VFPv4 with 16 double-precision registers */ -#define PROC_CPUINFO_FEATURE_TLS UINT32_C(0x00008000) -#define PROC_CPUINFO_FEATURE_VFPV4 UINT32_C(0x00010000) -#define PROC_CPUINFO_FEATURE_IDIVA UINT32_C(0x00020000) -#define PROC_CPUINFO_FEATURE_IDIVT UINT32_C(0x00040000) -#define PROC_CPUINFO_FEATURE_IDIV UINT32_C(0x00060000) -#define PROC_CPUINFO_FEATURE_VFPD32 UINT32_C(0x00080000) -#define PROC_CPUINFO_FEATURE_LPAE UINT32_C(0x00100000) -#define PROC_CPUINFO_FEATURE_EVTSTRM UINT32_C(0x00200000) + #define PROC_CPUINFO_FEATURE_SWP UINT32_C(0x00000001) + #define PROC_CPUINFO_FEATURE_HALF UINT32_C(0x00000002) + #define PROC_CPUINFO_FEATURE_THUMB UINT32_C(0x00000004) + #define PROC_CPUINFO_FEATURE_26BIT UINT32_C(0x00000008) + #define PROC_CPUINFO_FEATURE_FASTMULT UINT32_C(0x00000010) + #define PROC_CPUINFO_FEATURE_FPA UINT32_C(0x00000020) + #define PROC_CPUINFO_FEATURE_VFP UINT32_C(0x00000040) + #define PROC_CPUINFO_FEATURE_EDSP UINT32_C(0x00000080) + #define PROC_CPUINFO_FEATURE_JAVA UINT32_C(0x00000100) + #define PROC_CPUINFO_FEATURE_IWMMXT UINT32_C(0x00000200) + #define PROC_CPUINFO_FEATURE_CRUNCH UINT32_C(0x00000400) + #define PROC_CPUINFO_FEATURE_THUMBEE UINT32_C(0x00000800) + #define PROC_CPUINFO_FEATURE_NEON UINT32_C(0x00001000) + #define PROC_CPUINFO_FEATURE_VFPV3 UINT32_C(0x00002000) + #define PROC_CPUINFO_FEATURE_VFPV3D16 UINT32_C(0x00004000) /* Also set for VFPv4 with 16 double-precision registers */ + #define PROC_CPUINFO_FEATURE_TLS UINT32_C(0x00008000) + #define PROC_CPUINFO_FEATURE_VFPV4 UINT32_C(0x00010000) + #define PROC_CPUINFO_FEATURE_IDIVA UINT32_C(0x00020000) + #define PROC_CPUINFO_FEATURE_IDIVT UINT32_C(0x00040000) + #define PROC_CPUINFO_FEATURE_IDIV UINT32_C(0x00060000) + #define PROC_CPUINFO_FEATURE_VFPD32 UINT32_C(0x00080000) + #define PROC_CPUINFO_FEATURE_LPAE UINT32_C(0x00100000) + #define PROC_CPUINFO_FEATURE_EVTSTRM UINT32_C(0x00200000) -#define PROC_CPUINFO_FEATURE2_AES UINT32_C(0x00000001) -#define PROC_CPUINFO_FEATURE2_PMULL UINT32_C(0x00000002) -#define PROC_CPUINFO_FEATURE2_SHA1 UINT32_C(0x00000004) -#define PROC_CPUINFO_FEATURE2_SHA2 UINT32_C(0x00000008) -#define PROC_CPUINFO_FEATURE2_CRC32 UINT32_C(0x00000010) + #define PROC_CPUINFO_FEATURE2_AES UINT32_C(0x00000001) + #define PROC_CPUINFO_FEATURE2_PMULL UINT32_C(0x00000002) + #define PROC_CPUINFO_FEATURE2_SHA1 UINT32_C(0x00000004) + #define PROC_CPUINFO_FEATURE2_SHA2 UINT32_C(0x00000008) + #define PROC_CPUINFO_FEATURE2_CRC32 UINT32_C(0x00000010) +#elif CPUINFO_ARCH_ARM64 + /* arch/arm64/include/uapi/asm/hwcap.h */ + #define PROC_CPUINFO_FEATURE_FP UINT32_C(0x00000001) + #define PROC_CPUINFO_FEATURE_ASIMD UINT32_C(0x00000002) + #define PROC_CPUINFO_FEATURE_EVTSTRM UINT32_C(0x00000004) + #define PROC_CPUINFO_FEATURE_AES UINT32_C(0x00000008) + #define PROC_CPUINFO_FEATURE_PMULL UINT32_C(0x00000010) + #define PROC_CPUINFO_FEATURE_SHA1 UINT32_C(0x00000020) + #define PROC_CPUINFO_FEATURE_SHA2 UINT32_C(0x00000040) + #define PROC_CPUINFO_FEATURE_CRC32 UINT32_C(0x00000080) + #define PROC_CPUINFO_FEATURE_ATOMICS UINT32_C(0x00000100) + #define PROC_CPUINFO_FEATURE_FPHP UINT32_C(0x00000200) + #define PROC_CPUINFO_FEATURE_ASIMDHP UINT32_C(0x00000400) + #define PROC_CPUINFO_FEATURE_CPUID UINT32_C(0x00000800) + #define PROC_CPUINFO_FEATURE_ASIMDRDM UINT32_C(0x00001000) + #define PROC_CPUINFO_FEATURE_JSCVT UINT32_C(0x00002000) + #define PROC_CPUINFO_FEATURE_FCMA UINT32_C(0x00004000) + #define PROC_CPUINFO_FEATURE_LRCPC UINT32_C(0x00008000) +#endif #define PROC_CPUINFO_VALID_ARCHITECTURE UINT32_C(0x00000001) @@ -65,26 +85,33 @@ struct proc_cpuinfo_cache { #define PROC_CPUINFO_VALID_PART UINT32_C(0x00000008) #define PROC_CPUINFO_VALID_REVISION UINT32_C(0x00000010) #define PROC_CPUINFO_VALID_FEATURES UINT32_C(0x00000020) -#define PROC_CPUINFO_VALID_ICACHE_SIZE UINT32_C(0x00000100) -#define PROC_CPUINFO_VALID_ICACHE_SETS UINT32_C(0x00000200) -#define PROC_CPUINFO_VALID_ICACHE_WAYS UINT32_C(0x00000400) -#define PROC_CPUINFO_VALID_ICACHE_LINE UINT32_C(0x00000800) -#define PROC_CPUINFO_VALID_DCACHE_SIZE UINT32_C(0x00001000) -#define PROC_CPUINFO_VALID_DCACHE_SETS UINT32_C(0x00002000) -#define PROC_CPUINFO_VALID_DCACHE_WAYS UINT32_C(0x00004000) -#define PROC_CPUINFO_VALID_DCACHE_LINE UINT32_C(0x00008000) +#if CPUINFO_ARCH_ARM + #define PROC_CPUINFO_VALID_ICACHE_SIZE UINT32_C(0x00000100) + #define PROC_CPUINFO_VALID_ICACHE_SETS UINT32_C(0x00000200) + #define PROC_CPUINFO_VALID_ICACHE_WAYS UINT32_C(0x00000400) + #define PROC_CPUINFO_VALID_ICACHE_LINE UINT32_C(0x00000800) + #define PROC_CPUINFO_VALID_DCACHE_SIZE UINT32_C(0x00001000) + #define PROC_CPUINFO_VALID_DCACHE_SETS UINT32_C(0x00002000) + #define PROC_CPUINFO_VALID_DCACHE_WAYS UINT32_C(0x00004000) + #define PROC_CPUINFO_VALID_DCACHE_LINE UINT32_C(0x00008000) +#endif -#define PROC_CPUINFO_VALID_INFO UINT32_C(0x0000003F) -#define PROC_CPUINFO_VALID_ICACHE UINT32_C(0x00000F00) -#define PROC_CPUINFO_VALID_DCACHE UINT32_C(0x0000F000) -#define PROC_CPUINFO_VALID_CACHE_LINE UINT32_C(0x00008800) +#define PROC_CPUINFO_VALID_INFO UINT32_C(0x0000003F) +#if CPUINFO_ARCH_ARM + #define PROC_CPUINFO_VALID_ICACHE UINT32_C(0x00000F00) + #define PROC_CPUINFO_VALID_DCACHE UINT32_C(0x0000F000) + #define PROC_CPUINFO_VALID_CACHE_LINE UINT32_C(0x00008800) +#endif struct proc_cpuinfo { struct proc_cpuinfo_arch architecture; +#if CPUINFO_ARCH_ARM struct proc_cpuinfo_cache cache; +#endif uint32_t features; +#if CPUINFO_ARCH_ARM uint32_t features2; - uint32_t processor_number; +#endif uint32_t cpuid; uint32_t implementer; uint32_t variant; @@ -96,7 +123,13 @@ struct proc_cpuinfo { struct proc_cpuinfo* cpuinfo_arm_linux_parse_proc_cpuinfo( uint32_t processors_count[restrict static 1]); -void cpuinfo_arm_linux_decode_isa_from_proc_cpuinfo( - const struct proc_cpuinfo proc_cpuinfo[restrict static 1], - uint32_t proc_cpuinfo_count, - struct cpuinfo_arm_isa isa[restrict static 1]); +#if CPUINFO_ARCH_ARM + void cpuinfo_arm_linux_decode_isa_from_proc_cpuinfo( + const struct proc_cpuinfo proc_cpuinfo[restrict static 1], + uint32_t proc_cpuinfo_count, + struct cpuinfo_arm_isa isa[restrict static 1]); +#elif CPUINFO_ARCH_ARM64 + void cpuinfo_arm64_linux_decode_isa_from_proc_cpuinfo( + const struct proc_cpuinfo proc_cpuinfo[restrict static 1], + struct cpuinfo_arm_isa isa[restrict static 1]); +#endif diff --git a/src/arm/linux/cpuinfo.c b/src/arm/linux/cpuinfo.c index 960cb7f..8702ff3 100644 --- a/src/arm/linux/cpuinfo.c +++ b/src/arm/linux/cpuinfo.c @@ -138,10 +138,17 @@ static void parse_features( } } const size_t feature_length = (size_t) (feature_end - feature_start); - + switch (feature_length) { case 3: - if (memcmp(feature_start, "swp", feature_length) == 0) { + if (memcmp(feature_start, "aes", feature_length) == 0) { + #if CPUINFO_ARCH_ARM + proc_cpuinfo->features2 |= PROC_CPUINFO_FEATURE2_AES; + #elif CPUINFO_ARCH_ARM64 + proc_cpuinfo->features |= PROC_CPUINFO_FEATURE_AES; + #endif +#if CPUINFO_ARCH_ARM + } else if (memcmp(feature_start, "swp", feature_length) == 0) { proc_cpuinfo->features |= PROC_CPUINFO_FEATURE_SWP; } else if (memcmp(feature_start, "fpa", feature_length) == 0) { proc_cpuinfo->features |= PROC_CPUINFO_FEATURE_FPA; @@ -149,14 +156,26 @@ static void parse_features( proc_cpuinfo->features |= PROC_CPUINFO_FEATURE_VFP; } else if (memcmp(feature_start, "tls", feature_length) == 0) { proc_cpuinfo->features |= PROC_CPUINFO_FEATURE_TLS; - } else if (memcmp(feature_start, "aes", feature_length) == 0) { - proc_cpuinfo->features2 |= PROC_CPUINFO_FEATURE2_AES; +#endif /* CPUINFO_ARCH_ARM */ } else { goto unexpected; } break; case 4: - if (memcmp(feature_start, "half", feature_length) == 0) { + if (memcmp(feature_start, "sha1", feature_length) == 0) { + #if CPUINFO_ARCH_ARM + proc_cpuinfo->features2 |= PROC_CPUINFO_FEATURE2_SHA1; + #elif CPUINFO_ARCH_ARM64 + proc_cpuinfo->features |= PROC_CPUINFO_FEATURE_SHA1; + #endif + } else if (memcmp(feature_start, "sha2", feature_length) == 0) { + #if CPUINFO_ARCH_ARM + proc_cpuinfo->features2 |= PROC_CPUINFO_FEATURE2_SHA2; + #elif CPUINFO_ARCH_ARM64 + proc_cpuinfo->features |= PROC_CPUINFO_FEATURE_SHA2; + #endif +#if CPUINFO_ARCH_ARM + } else if (memcmp(feature_start, "half", feature_length) == 0) { proc_cpuinfo->features |= PROC_CPUINFO_FEATURE_HALF; } else if (memcmp(feature_start, "edsp", feature_length) == 0) { proc_cpuinfo->features |= PROC_CPUINFO_FEATURE_EDSP; @@ -166,16 +185,26 @@ static void parse_features( proc_cpuinfo->features |= PROC_CPUINFO_FEATURE_NEON; } else if (memcmp(feature_start, "lpae", feature_length) == 0) { proc_cpuinfo->features |= PROC_CPUINFO_FEATURE_LPAE; - } else if (memcmp(feature_start, "sha1", feature_length) == 0) { - proc_cpuinfo->features2 |= PROC_CPUINFO_FEATURE2_SHA1; - } else if (memcmp(feature_start, "sha2", feature_length) == 0) { - proc_cpuinfo->features2 |= PROC_CPUINFO_FEATURE2_SHA2; +#endif /* CPUINFO_ARCH_ARM */ } else { goto unexpected; } break; case 5: - if (memcmp(feature_start, "thumb", feature_length) == 0) { + if (memcmp(feature_start, "pmull", feature_length) == 0) { + #if CPUINFO_ARCH_ARM + proc_cpuinfo->features2 |= PROC_CPUINFO_FEATURE2_PMULL; + #elif CPUINFO_ARCH_ARM64 + proc_cpuinfo->features |= PROC_CPUINFO_FEATURE_PMULL; + #endif + } else if (memcmp(feature_start, "crc32", feature_length) == 0) { + #if CPUINFO_ARCH_ARM + proc_cpuinfo->features2 |= PROC_CPUINFO_FEATURE2_CRC32; + #elif CPUINFO_ARCH_ARM64 + proc_cpuinfo->features |= PROC_CPUINFO_FEATURE_CRC32; + #endif +#if CPUINFO_ARCH_ARM + } else if (memcmp(feature_start, "thumb", feature_length) == 0) { proc_cpuinfo->features |= PROC_CPUINFO_FEATURE_THUMB; } else if (memcmp(feature_start, "26bit", feature_length) == 0) { proc_cpuinfo->features |= PROC_CPUINFO_FEATURE_26BIT; @@ -187,14 +216,12 @@ static void parse_features( proc_cpuinfo->features |= PROC_CPUINFO_FEATURE_IDIVA; } else if (memcmp(feature_start, "idivt", feature_length) == 0) { proc_cpuinfo->features |= PROC_CPUINFO_FEATURE_IDIVT; - } else if (memcmp(feature_start, "pmull", feature_length) == 0) { - proc_cpuinfo->features2 |= PROC_CPUINFO_FEATURE2_PMULL; - } else if (memcmp(feature_start, "crc32", feature_length) == 0) { - proc_cpuinfo->features2 |= PROC_CPUINFO_FEATURE2_CRC32; +#endif /* CPUINFO_ARCH_ARM */ } else { goto unexpected; } break; +#if CPUINFO_ARCH_ARM case 6: if (memcmp(feature_start, "iwmmxt", feature_length) == 0) { proc_cpuinfo->features |= PROC_CPUINFO_FEATURE_IWMMXT; @@ -206,15 +233,19 @@ static void parse_features( goto unexpected; } break; +#endif /* CPUINFO_ARCH_ARM */ case 7: - if (memcmp(feature_start, "thumbee", feature_length) == 0) { - proc_cpuinfo->features |= PROC_CPUINFO_FEATURE_THUMBEE; - } else if (memcmp(feature_start, "evtstrm", feature_length) == 0) { + if (memcmp(feature_start, "evtstrm", feature_length) == 0) { proc_cpuinfo->features |= PROC_CPUINFO_FEATURE_EVTSTRM; +#if CPUINFO_ARCH_ARM + } else if (memcmp(feature_start, "thumbee", feature_length) == 0) { + proc_cpuinfo->features |= PROC_CPUINFO_FEATURE_THUMBEE; +#endif /* CPUINFO_ARCH_ARM */ } else { goto unexpected; } break; +#if CPUINFO_ARCH_ARM case 8: if (memcmp(feature_start, "fastmult", feature_length) == 0) { proc_cpuinfo->features |= PROC_CPUINFO_FEATURE_FASTMULT; @@ -224,6 +255,7 @@ static void parse_features( goto unexpected; } break; +#endif /* CPUINFO_ARCH_ARM */ default: unexpected: cpuinfo_log_warning("unexpected /proc/cpuinfo features %.*s is ignored", @@ -475,6 +507,7 @@ static void parse_cpu_revision( proc_cpuinfo->valid_mask |= PROC_CPUINFO_VALID_REVISION; } +#if CPUINFO_ARCH_ARM /* * Decode one of the cache-related numbers reported by Linux kernel * for pre-ARMv7 architecture. @@ -533,6 +566,7 @@ static void parse_cache_number( *number_ptr = number; *valid_mask |= number_mask; } +#endif /* CPUINFO_ARCH_ARM */ /* * Decode a single line of /proc/cpuinfo information. @@ -621,7 +655,10 @@ static uint32_t parse_line( const size_t key_length = key_end - line_start; switch (key_length) { case 6: - if (memcmp(line_start, "I size", key_length) == 0) { + if (memcmp(line_start, "Serial", key_length) == 0) { + /* Usually contains just zeros, useless */ +#if CPUINFO_ARCH_ARM + } else if (memcmp(line_start, "I size", key_length) == 0) { parse_cache_number(value_start, value_end, "instruction cache size", &proc_cpuinfo->cache.i_size, &proc_cpuinfo->valid_mask, PROC_CPUINFO_VALID_ICACHE_SIZE); @@ -637,12 +674,12 @@ static uint32_t parse_line( parse_cache_number(value_start, value_end, "data cache sets", &proc_cpuinfo->cache.d_sets, &proc_cpuinfo->valid_mask, PROC_CPUINFO_VALID_DCACHE_SETS); - } else if (memcmp(line_start, "Serial", key_length) == 0) { - /* Usually contains just zeros, useless */ +#endif /* CPUINFO_ARCH_ARM */ } else { goto unknown; } break; +#if CPUINFO_ARCH_ARM case 7: if (memcmp(line_start, "I assoc", key_length) == 0) { parse_cache_number(value_start, value_end, @@ -656,6 +693,7 @@ static uint32_t parse_line( goto unknown; } break; +#endif /* CPUINFO_ARCH_ARM */ case 8: if (memcmp(line_start, "CPU part", key_length) == 0) { parse_cpu_part(value_start, value_end, proc_cpuinfo); @@ -707,6 +745,7 @@ static uint32_t parse_line( goto unknown; } break; +#if CPUINFO_ARCH_ARM case 13: if (memcmp(line_start, "I line length", key_length) == 0) { parse_cache_number(value_start, value_end, @@ -720,6 +759,7 @@ static uint32_t parse_line( goto unknown; } break; +#endif /* CPUINFO_ARCH_ARM */ case 15: if (memcmp(line_start, "CPU implementer", key_length) == 0) { parse_cpu_implementer(value_start, value_end, proc_cpuinfo); diff --git a/src/arm/linux/init.c b/src/arm/linux/init.c index 5e47858..ba0f930 100644 --- a/src/arm/linux/init.c +++ b/src/arm/linux/init.c @@ -28,8 +28,13 @@ void cpuinfo_arm_linux_init(void) { struct proc_cpuinfo* proc_cpuinfo_entries = cpuinfo_arm_linux_parse_proc_cpuinfo(&proc_cpuinfo_count); if (proc_cpuinfo_count != 0) { - cpuinfo_arm_linux_decode_isa_from_proc_cpuinfo( - proc_cpuinfo_entries, proc_cpuinfo_count, &cpuinfo_isa); + #if CPUINFO_ARCH_ARM + cpuinfo_arm_linux_decode_isa_from_proc_cpuinfo( + proc_cpuinfo_entries, proc_cpuinfo_count, &cpuinfo_isa); + #elif CPUINFO_ARCH_ARM64 + cpuinfo_arm64_linux_decode_isa_from_proc_cpuinfo( + proc_cpuinfo_entries, &cpuinfo_isa); + #endif processors_count = proc_cpuinfo_count; processors = calloc(processors_count, sizeof(struct cpuinfo_processor)); @@ -42,7 +47,9 @@ void cpuinfo_arm_linux_init(void) { cpuinfo_arm_decode_vendor_uarch( proc_cpuinfo_entries[i].implementer, proc_cpuinfo_entries[i].part, +#if CPUINFO_ARCH_ARM !!(proc_cpuinfo_entries[i].features & PROC_CPUINFO_FEATURE_VFPV4), +#endif &processors[i].vendor, &processors[i].uarch); processors[i].topology = (struct cpuinfo_topology) { .thread_id = 0, @@ -91,22 +98,31 @@ void cpuinfo_arm_linux_init(void) { } for (uint32_t i = 0; i < l1i_count; i++) { /* L1I reported in /proc/cpuinfo overrides defaults */ - if ((proc_cpuinfo_entries[i].valid_mask & PROC_CPUINFO_VALID_ICACHE) == PROC_CPUINFO_VALID_ICACHE) { - l1i[i] = (struct cpuinfo_cache) { - .size = proc_cpuinfo_entries[i].cache.i_size, - .associativity = proc_cpuinfo_entries[i].cache.i_assoc, - .sets = proc_cpuinfo_entries[i].cache.i_sets, - .partitions = 1, - .line_size = proc_cpuinfo_entries[i].cache.i_line_length - }; - } else { + #if CPUINFO_ARCH_ARM + if ((proc_cpuinfo_entries[i].valid_mask & PROC_CPUINFO_VALID_ICACHE) == PROC_CPUINFO_VALID_ICACHE) { + l1i[i] = (struct cpuinfo_cache) { + .size = proc_cpuinfo_entries[i].cache.i_size, + .associativity = proc_cpuinfo_entries[i].cache.i_assoc, + .sets = proc_cpuinfo_entries[i].cache.i_sets, + .partitions = 1, + .line_size = proc_cpuinfo_entries[i].cache.i_line_length + }; + } else { + cpuinfo_arm_decode_cache( + processors[i].uarch, + proc_cpuinfo_count, + proc_cpuinfo_entries[i].part, + proc_cpuinfo_entries[i].architecture.version, + &l1i[i], &private_l1d, &shared_l2); + } + #elif CPUINFO_ARCH_ARM64 cpuinfo_arm_decode_cache( processors[i].uarch, proc_cpuinfo_count, proc_cpuinfo_entries[i].part, proc_cpuinfo_entries[i].architecture.version, &l1i[i], &private_l1d, &shared_l2); - } + #endif l1i[i].thread_start = i; l1i[i].thread_count = 1; } @@ -119,23 +135,32 @@ void cpuinfo_arm_linux_init(void) { goto cleanup; } for (uint32_t i = 0; i < l1d_count; i++) { - /* L1D reported in /proc/cpuinfo overrides defaults */ - if ((proc_cpuinfo_entries[i].valid_mask & PROC_CPUINFO_VALID_DCACHE) == PROC_CPUINFO_VALID_DCACHE) { - l1d[i] = (struct cpuinfo_cache) { - .size = proc_cpuinfo_entries[i].cache.d_size, - .associativity = proc_cpuinfo_entries[i].cache.d_assoc, - .sets = proc_cpuinfo_entries[i].cache.d_sets, - .partitions = 1, - .line_size = proc_cpuinfo_entries[i].cache.d_line_length - }; - } else { + #if CPUINFO_ARCH_ARM + /* L1D reported in /proc/cpuinfo overrides defaults */ + if ((proc_cpuinfo_entries[i].valid_mask & PROC_CPUINFO_VALID_DCACHE) == PROC_CPUINFO_VALID_DCACHE) { + l1d[i] = (struct cpuinfo_cache) { + .size = proc_cpuinfo_entries[i].cache.d_size, + .associativity = proc_cpuinfo_entries[i].cache.d_assoc, + .sets = proc_cpuinfo_entries[i].cache.d_sets, + .partitions = 1, + .line_size = proc_cpuinfo_entries[i].cache.d_line_length + }; + } else { + cpuinfo_arm_decode_cache( + processors[i].uarch, + proc_cpuinfo_count, + proc_cpuinfo_entries[i].part, + proc_cpuinfo_entries[i].architecture.version, + &private_l1i, &l1d[i], &shared_l2); + } + #elif CPUINFO_ARCH_ARM64 cpuinfo_arm_decode_cache( processors[i].uarch, proc_cpuinfo_count, proc_cpuinfo_entries[i].part, proc_cpuinfo_entries[i].architecture.version, &private_l1i, &l1d[i], &shared_l2); - } + #endif l1d[i].thread_start = i; l1d[i].thread_count = 1; } diff --git a/src/arm/linux/isa.c b/src/arm/linux/isa.c index 2b27845..217879e 100644 --- a/src/arm/linux/isa.c +++ b/src/arm/linux/isa.c @@ -64,17 +64,17 @@ void cpuinfo_arm_linux_decode_isa_from_proc_cpuinfo( const uint32_t features = proc_cpuinfo->features; if ((architecture >= 6) || (features & PROC_CPUINFO_FEATURE_EDSP) || (proc_cpuinfo->architecture.flags & PROC_CPUINFO_ARCH_E)) { - cpuinfo_isa.armv5e = true; + isa->armv5e = true; } if (architecture >= 6) { - cpuinfo_isa.armv6 = true; + isa->armv6 = true; } if (architecture >= 7) { - cpuinfo_isa.armv6k = true; - cpuinfo_isa.armv7 = true; + isa->armv6k = true; + isa->armv7 = true; if (proc_cpuinfo_count > 1) { - cpuinfo_isa.armv7mp = true; + isa->armv7mp = true; } } @@ -83,9 +83,9 @@ void cpuinfo_arm_linux_decode_isa_from_proc_cpuinfo( cpuinfo_log_debug("WCID = 0x%08"PRIx32, wcid); const uint32_t coprocessor_type = (wcid >> 8) & UINT32_C(0xFF); if (coprocessor_type >= 0x10) { - cpuinfo_isa.wmmx = true; + isa->wmmx = true; if (coprocessor_type >= 0x20) { - cpuinfo_isa.wmmx2 = true; + isa->wmmx2 = true; } } else { cpuinfo_log_warning("WMMX ISA disabled: OS reported iwmmxt feature, " @@ -95,32 +95,32 @@ void cpuinfo_arm_linux_decode_isa_from_proc_cpuinfo( } if ((features & PROC_CPUINFO_FEATURE_THUMB) || (proc_cpuinfo->architecture.flags & PROC_CPUINFO_ARCH_T)) { - cpuinfo_isa.thumb = true; + isa->thumb = true; /* * There is no separate feature flag for Thumb 2. * All ARMv7 processors and ARM 1156 (CPU part 0xB56) support Thumb 2. */ if (architecture >= 7 || (cpu_implementer == 'A' && cpu_part == 0xB56)) { - cpuinfo_isa.thumb2 = true; + isa->thumb2 = true; } } if (features & PROC_CPUINFO_FEATURE_THUMBEE) { - cpuinfo_isa.thumbee = true; + isa->thumbee = true; } if ((features & PROC_CPUINFO_FEATURE_JAVA) || (proc_cpuinfo->architecture.flags & PROC_CPUINFO_ARCH_J)) { - cpuinfo_isa.jazelle = true; + isa->jazelle = true; } if ((features & PROC_CPUINFO_FEATURE_IDIV) == PROC_CPUINFO_FEATURE_IDIV) { - cpuinfo_isa.idiv = true; + isa->idiv = true; } else { /* Qualcomm Krait may have buggy kernel configuration that doesn't report IDIV */ if (cpu_implementer == 'Q') { switch (cpu_part) { case 0x04D: /* Dual-core Krait */ case 0x06F: /* Quad-core Krait */ - cpuinfo_isa.idiv = true; + isa->idiv = true; } } } @@ -132,23 +132,23 @@ void cpuinfo_arm_linux_decode_isa_from_proc_cpuinfo( const uint32_t vfpv3_mask = PROC_CPUINFO_FEATURE_VFPV3 | PROC_CPUINFO_FEATURE_VFPV3D16 | \ PROC_CPUINFO_FEATURE_VFPD32 | PROC_CPUINFO_FEATURE_VFPV4 | PROC_CPUINFO_FEATURE_NEON; if ((architecture >= 7) | (features & vfpv3_mask)) { - cpuinfo_isa.vfpv3 = true; + isa->vfpv3 = true; const uint32_t d32_mask = PROC_CPUINFO_FEATURE_VFPD32 | PROC_CPUINFO_FEATURE_NEON; if (features & d32_mask) { - cpuinfo_isa.d32 = true; + isa->d32 = true; } } else { const uint32_t fpsid = read_fpsid(); cpuinfo_log_debug("FPSID = 0x%08"PRIx32, fpsid); const uint32_t subarchitecture = (fpsid >> 16) & UINT32_C(0x7F); if (subarchitecture >= 0x01) { - cpuinfo_isa.vfpv2 = true; + isa->vfpv2 = true; } } } if (features & PROC_CPUINFO_FEATURE_NEON) { - cpuinfo_isa.neon = true; + isa->neon = true; } /* @@ -157,28 +157,28 @@ void cpuinfo_arm_linux_decode_isa_from_proc_cpuinfo( * Additionally, ARM Cortex-A9 (CPU part 0xC09) supports FP16. */ if ((features & PROC_CPUINFO_FEATURE_VFPV4) || (cpu_implementer == 'A' && cpu_part == 0xC09)) { - cpuinfo_isa.fp16 = true; + isa->fp16 = true; } if (features & PROC_CPUINFO_FEATURE_VFPV4) { - cpuinfo_isa.fma = true; + isa->fma = true; } } const uint32_t features2 = proc_cpuinfo->features2; if (features2 & PROC_CPUINFO_FEATURE2_AES) { - cpuinfo_isa.aes = true; + isa->aes = true; } if (features2 & PROC_CPUINFO_FEATURE2_PMULL) { - cpuinfo_isa.pmull = true; + isa->pmull = true; } if (features2 & PROC_CPUINFO_FEATURE2_SHA1) { - cpuinfo_isa.sha1 = true; + isa->sha1 = true; } if (features2 & PROC_CPUINFO_FEATURE2_SHA2) { - cpuinfo_isa.sha2 = true; + isa->sha2 = true; } if (features2 & PROC_CPUINFO_FEATURE2_CRC32) { - cpuinfo_isa.crc32 = true; + isa->crc32 = true; } } diff --git a/src/arm/linux/isa64.c b/src/arm/linux/isa64.c new file mode 100644 index 0000000..fae9df2 --- /dev/null +++ b/src/arm/linux/isa64.c @@ -0,0 +1,54 @@ +#include <stdint.h> + +#include <arm/linux/api.h> +#include <arm/linux/cp.h> +#include <log.h> + + +void cpuinfo_arm64_linux_decode_isa_from_proc_cpuinfo( + const struct proc_cpuinfo proc_cpuinfo[restrict static 1], + struct cpuinfo_arm_isa isa[restrict static 1]) +{ + const uint32_t features = proc_cpuinfo->features; + if (features & PROC_CPUINFO_FEATURE_AES) { + isa->aes = true; + } + if (features & PROC_CPUINFO_FEATURE_PMULL) { + isa->pmull = true; + } + if (features & PROC_CPUINFO_FEATURE_SHA1) { + isa->sha1 = true; + } + if (features & PROC_CPUINFO_FEATURE_SHA2) { + isa->sha2 = true; + } + if (features & PROC_CPUINFO_FEATURE_CRC32) { + isa->crc32 = true; + } + if (features & PROC_CPUINFO_FEATURE_ATOMICS) { + isa->atomics = true; + } + const uint32_t fp16arith_mask = PROC_CPUINFO_FEATURE_FPHP | PROC_CPUINFO_FEATURE_ASIMDHP; + if ((features & fp16arith_mask) == fp16arith_mask) { + isa->fp16arith = true; + } else if (features & PROC_CPUINFO_FEATURE_FPHP) { + cpuinfo_log_warning("FP16 arithmetics disabled: detected support only for scalar operations"); + } else if (features & PROC_CPUINFO_FEATURE_ASIMDHP) { + cpuinfo_log_warning("FP16 arithmetics disabled: detected support only for SIMD operations"); + } + if (features & PROC_CPUINFO_FEATURE_ASIMDRDM) { + isa->rdm = true; + } + if (features & PROC_CPUINFO_FEATURE_JSCVT) { + isa->jscvt = true; + } + if (features & PROC_CPUINFO_FEATURE_ASIMDRDM) { + isa->rdm = true; + } + if (features & PROC_CPUINFO_FEATURE_JSCVT) { + isa->jscvt = true; + } + if (features & PROC_CPUINFO_FEATURE_FCMA) { + isa->fcma = true; + } +} diff --git a/src/arm/uarch.c b/src/arm/uarch.c index 5dbd4ec..c0ef6d7 100644 --- a/src/arm/uarch.c +++ b/src/arm/uarch.c @@ -7,7 +7,9 @@ void cpuinfo_arm_decode_vendor_uarch( uint32_t cpu_implementer, uint32_t cpu_part, +#if CPUINFO_ARCH_ARM bool has_vfpv4, +#endif /* CPUINFO_ARCH_ARM */ enum cpuinfo_vendor vendor[restrict static 1], enum cpuinfo_uarch uarch[restrict static 1]) { @@ -15,6 +17,7 @@ void cpuinfo_arm_decode_vendor_uarch( case 'A': *vendor = cpuinfo_vendor_arm; switch (cpu_part) { +#if CPUINFO_ARCH_ARM case 0xC05: *uarch = cpuinfo_uarch_cortex_a5; break; @@ -36,6 +39,7 @@ void cpuinfo_arm_decode_vendor_uarch( case 0xC0F: *uarch = cpuinfo_uarch_cortex_a15; break; +#endif /* CPUINFO_ARCH_ARM */ case 0xD01: *uarch = cpuinfo_uarch_cortex_a32; break; @@ -70,6 +74,7 @@ void cpuinfo_arm_decode_vendor_uarch( } } break; +#if CPUINFO_ARCH_ARM case 'i': *vendor = cpuinfo_vendor_intel; switch (cpu_part >> 8) { @@ -82,6 +87,7 @@ void cpuinfo_arm_decode_vendor_uarch( cpuinfo_log_warning("unknown Intel CPU part 0x%03"PRIx32" ignored", cpu_part); } break; +#endif /* CPUINFO_ARCH_ARM */ case 'N': *vendor = cpuinfo_vendor_nvidia; switch (cpu_part) { @@ -95,6 +101,7 @@ void cpuinfo_arm_decode_vendor_uarch( case 'Q': *vendor = cpuinfo_vendor_qualcomm; switch (cpu_part) { +#if CPUINFO_ARCH_ARM case 0x00F: /* Mostly Scorpions, but some Cortex A5 may report this value as well */ if (has_vfpv4) { @@ -112,6 +119,7 @@ void cpuinfo_arm_decode_vendor_uarch( case 0x06F: /* Quad-core Krait */ *uarch = cpuinfo_uarch_krait; break; +#endif /* CPUINFO_ARCH_ARM */ case 0x205: /* Low-power Kryo "Silver" */ case 0x211: /* High-performance Kryo "Gold" */ case 0x800: /* Low-power Kryo 800 */ @@ -132,10 +140,12 @@ void cpuinfo_arm_decode_vendor_uarch( cpuinfo_log_warning("unknown Samsung CPU part 0x%03"PRIx32" ignored", cpu_part); } break; +#if CPUINFO_ARCH_ARM case 'V': *vendor = cpuinfo_vendor_marvell; cpuinfo_log_warning("unknown Marvell CPU part 0x%03"PRIx32" ignored", cpu_part); break; +#endif /* CPUINFO_ARCH_ARM */ default: cpuinfo_log_warning("unknown CPU implementer '%c' (0x%02"PRIx32") with CPU part 0x%03"PRIx32" ignored", (char) cpu_implementer, cpu_implementer, cpu_part); @@ -24,7 +24,7 @@ void CPUINFO_ABI cpuinfo_initialize(void) { #else #error Unsupported target OS #endif -#elif CPUINFO_ARCH_ARM +#elif CPUINFO_ARCH_ARM || CPUINFO_ARCH_ARM64 #if defined(__linux__) pthread_once(&init_guard, &cpuinfo_arm_linux_init); #else diff --git a/tools/isa-info.c b/tools/isa-info.c index 76236db..a35fdf8 100644 --- a/tools/isa-info.c +++ b/tools/isa-info.c @@ -153,5 +153,20 @@ int main(int argc, char** argv) { printf("\tPMULL: %s\n", cpuinfo_isa.pmull ? "yes" : "no"); printf("\tCRC32: %s\n", cpuinfo_isa.crc32 ? "yes" : "no"); #endif /* CPUINFO_ARCH_ARM */ +#if CPUINFO_ARCH_ARM64 + printf("Instruction sets:\n"); + printf("\tARM v8.1 atomics: %s\n", cpuinfo_isa.atomics ? "yes" : "no"); + printf("\tARM v8.1 SQRDMLxH: %s\n", cpuinfo_isa.rdm ? "yes" : "no"); + printf("\tARM v8.2 FP16 arithmetics: %s\n", cpuinfo_isa.fp16arith ? "yes" : "no"); + printf("\tARM v8.3 JS conversion: %s\n", cpuinfo_isa.jscvt ? "yes" : "no"); + printf("\tARM v8.3 complex FMA: %s\n", cpuinfo_isa.fcma ? "yes" : "no"); + + printf("Cryptography extensions:\n"); + printf("\tAES: %s\n", cpuinfo_isa.aes ? "yes" : "no"); + printf("\tSHA1: %s\n", cpuinfo_isa.sha1 ? "yes" : "no"); + printf("\tSHA2: %s\n", cpuinfo_isa.sha2 ? "yes" : "no"); + printf("\tPMULL: %s\n", cpuinfo_isa.pmull ? "yes" : "no"); + printf("\tCRC32: %s\n", cpuinfo_isa.crc32 ? "yes" : "no"); +#endif } |