aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarat Dukhan <maratek@gmail.com>2017-05-09 13:19:39 +0000
committerMarat Dukhan <maratek@gmail.com>2017-05-09 13:19:39 +0000
commitab42e7e6d27b15a2de7b829c3d1c667f99ffb2c5 (patch)
treeded38c912b6bcbae8282bca17dae5023fde96388
parentf55f67ea447f06a34ff0cd53b3b0b7ef54132d2c (diff)
downloadcpuinfo-ab42e7e6d27b15a2de7b829c3d1c667f99ffb2c5.tar.gz
Support ARM64 targets
-rwxr-xr-xconfigure.py12
-rw-r--r--include/cpuinfo.h53
-rw-r--r--src/arm/api.h2
-rw-r--r--src/arm/linux/api.h125
-rw-r--r--src/arm/linux/cpuinfo.c80
-rw-r--r--src/arm/linux/init.c71
-rw-r--r--src/arm/linux/isa.c48
-rw-r--r--src/arm/linux/isa64.c54
-rw-r--r--src/arm/uarch.c10
-rw-r--r--src/init.c2
-rw-r--r--tools/isa-info.c15
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);
diff --git a/src/init.c b/src/init.c
index 3c29aa2..5a4f1c7 100644
--- a/src/init.c
+++ b/src/init.c
@@ -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
}