aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarat Dukhan <marat@fb.com>2017-11-28 11:07:11 -0800
committerMarat Dukhan <marat@fb.com>2017-11-28 11:07:11 -0800
commitdeaa898ad9e6474e2a96934604dd096d88ed9501 (patch)
tree488f6c5a41d9e39bfba6e9d505a891513213526a
parent595725424f46d6e363cec548f0746794d2a4fca9 (diff)
downloadcpuinfo-deaa898ad9e6474e2a96934604dd096d88ed9501.tar.gz
More robust ISA detection on ARM/Linux
-rw-r--r--CMakeLists.txt6
-rwxr-xr-xconfigure.py4
-rw-r--r--jni/Android.mk12
-rw-r--r--src/arm/linux/aarch32-isa.c (renamed from src/arm/linux/arm32-isa.c)18
-rw-r--r--src/arm/linux/aarch64-isa.c (renamed from src/arm/linux/arm64-isa.c)3
-rw-r--r--src/arm/linux/api.h8
-rw-r--r--src/arm/linux/init.c61
7 files changed, 72 insertions, 40 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
index f750a4c..ed829f6 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -84,12 +84,12 @@ ELSEIF(CMAKE_SYSTEM_PROCESSOR MATCHES "^(armv5te|armv7|armv7f|armv7s|armv7k|armv
src/arm/linux/chipset.c
src/arm/linux/midr.c)
IF(CMAKE_SYSTEM_PROCESSOR MATCHES "^(armv5te|armv7l|armv7-a)$")
- LIST(APPEND CPUINFO_SRCS src/arm/linux/arm32-isa.c)
+ LIST(APPEND CPUINFO_SRCS src/arm/linux/aarch32-isa.c)
IF(CMAKE_SYSTEM_NAME STREQUAL "Android" AND ANDROID_ABI STREQUAL "armeabi")
- SET_SOURCE_FILES_PROPERTIES(src/arm/linux/arm32-isa.c PROPERTIES COMPILE_FLAGS -marm)
+ SET_SOURCE_FILES_PROPERTIES(src/arm/linux/aarch32-isa.c PROPERTIES COMPILE_FLAGS -marm)
ENDIF()
ELSEIF(CMAKE_SYSTEM_PROCESSOR STREQUAL "aarch64")
- LIST(APPEND CPUINFO_SRCS src/arm/linux/arm64-isa.c)
+ LIST(APPEND CPUINFO_SRCS src/arm/linux/aarch64-isa.c)
ENDIF()
ELSEIF(CMAKE_SYSTEM_NAME STREQUAL "Darwin")
LIST(APPEND CPUINFO_SRCS
diff --git a/configure.py b/configure.py
index 271c454..0d8777a 100755
--- a/configure.py
+++ b/configure.py
@@ -46,9 +46,9 @@ def main(args):
"arm/linux/chipset.c",
]
if build.target.is_arm:
- sources.append("arm/linux/arm32-isa.c")
+ sources.append("arm/linux/aarch32-isa.c")
elif build.target.is_arm64:
- sources.append("arm/linux/arm64-isa.c")
+ sources.append("arm/linux/aarch64-isa.c")
if build.target.is_macos:
sources += ["mach/topology.c"]
diff --git a/jni/Android.mk b/jni/Android.mk
index e8c5621..f63d29c 100644
--- a/jni/Android.mk
+++ b/jni/Android.mk
@@ -22,13 +22,13 @@ LOCAL_SRC_FILES += \
$(LOCAL_PATH)/src/arm/linux/midr.c \
$(LOCAL_PATH)/src/arm/android/properties.c
ifeq ($(TARGET_ARCH_ABI),armeabi)
-LOCAL_SRC_FILES += $(LOCAL_PATH)/src/arm/linux/arm32-isa.c.arm
+LOCAL_SRC_FILES += $(LOCAL_PATH)/src/arm/linux/aarch32-isa.c.arm
endif # armeabi
ifeq ($(TARGET_ARCH_ABI),armeabi-v7a)
-LOCAL_SRC_FILES += $(LOCAL_PATH)/src/arm/linux/arm32-isa.c
+LOCAL_SRC_FILES += $(LOCAL_PATH)/src/arm/linux/aarch32-isa.c
endif # armeabi-v7a
ifeq ($(TARGET_ARCH_ABI),arm64-v8a)
-LOCAL_SRC_FILES += $(LOCAL_PATH)/src/arm/linux/arm64-isa.c
+LOCAL_SRC_FILES += $(LOCAL_PATH)/src/arm/linux/aarch64-isa.c
endif # arm64-v8a
endif # armeabi, armeabi-v7a, or arm64-v8a
ifeq ($(TARGET_ARCH_ABI),$(filter $(TARGET_ARCH_ABI),x86 x86_64))
@@ -74,13 +74,13 @@ LOCAL_SRC_FILES += \
$(LOCAL_PATH)/src/arm/linux/midr.c \
$(LOCAL_PATH)/src/arm/android/properties.c
ifeq ($(TARGET_ARCH_ABI),armeabi)
-LOCAL_SRC_FILES += $(LOCAL_PATH)/src/arm/linux/arm32-isa.c.arm
+LOCAL_SRC_FILES += $(LOCAL_PATH)/src/arm/linux/aarch32-isa.c.arm
endif # armeabi
ifeq ($(TARGET_ARCH_ABI),armeabi-v7a)
-LOCAL_SRC_FILES += $(LOCAL_PATH)/src/arm/linux/arm32-isa.c
+LOCAL_SRC_FILES += $(LOCAL_PATH)/src/arm/linux/aarch32-isa.c
endif # armeabi-v7a
ifeq ($(TARGET_ARCH_ABI),arm64-v8a)
-LOCAL_SRC_FILES += $(LOCAL_PATH)/src/arm/linux/arm64-isa.c
+LOCAL_SRC_FILES += $(LOCAL_PATH)/src/arm/linux/aarch64-isa.c
endif # arm64-v8a
endif # armeabi, armeabi-v7a, or arm64-v8a
ifeq ($(TARGET_ARCH_ABI),$(filter $(TARGET_ARCH_ABI),x86 x86_64))
diff --git a/src/arm/linux/arm32-isa.c b/src/arm/linux/aarch32-isa.c
index 092d50f..2d36182 100644
--- a/src/arm/linux/arm32-isa.c
+++ b/src/arm/linux/aarch32-isa.c
@@ -25,11 +25,13 @@
void cpuinfo_arm_linux_decode_isa_from_proc_cpuinfo(
- const struct cpuinfo_arm_linux_processor processor[restrict static 1],
+ uint32_t features,
+ uint32_t features2,
+ uint32_t midr,
+ uint32_t architecture_version,
+ uint32_t architecture_flags,
struct cpuinfo_arm_isa isa[restrict static 1])
{
- const uint32_t midr = processor->midr;
- uint32_t architecture_version = processor->architecture_version;
if (architecture_version >= 8) {
/*
* ARMv7 code running on ARMv8: IDIV, VFP, NEON are always supported,
@@ -60,8 +62,13 @@ void cpuinfo_arm_linux_decode_isa_from_proc_cpuinfo(
architecture_version = 6;
}
- const uint32_t features = processor->features;
- const uint32_t architecture_flags = processor->architecture_flags;
+ if (architecture_version < 7) {
+ const uint32_t armv7_features_mask = CPUINFO_ARM_LINUX_FEATURE_VFPV3 | CPUINFO_ARM_LINUX_FEATURE_VFPV3D16 | CPUINFO_ARM_LINUX_FEATURE_VFPD32 |
+ CPUINFO_ARM_LINUX_FEATURE_VFPV4 | CPUINFO_ARM_LINUX_FEATURE_NEON | CPUINFO_ARM_LINUX_FEATURE_IDIVT | CPUINFO_ARM_LINUX_FEATURE_IDIVA;
+ if (features & armv7_features_mask) {
+ architecture_version = 7;
+ }
+ }
if ((architecture_version >= 6) || (features & CPUINFO_ARM_LINUX_FEATURE_EDSP) || (architecture_flags & CPUINFO_ARM_LINUX_ARCH_E)) {
isa->armv5e = true;
}
@@ -175,7 +182,6 @@ void cpuinfo_arm_linux_decode_isa_from_proc_cpuinfo(
}
}
- const uint32_t features2 = processor->features2;
if (features2 & CPUINFO_ARM_LINUX_FEATURE2_AES) {
isa->aes = true;
}
diff --git a/src/arm/linux/arm64-isa.c b/src/arm/linux/aarch64-isa.c
index ae92d48..0b67a12 100644
--- a/src/arm/linux/arm64-isa.c
+++ b/src/arm/linux/aarch64-isa.c
@@ -5,10 +5,9 @@
void cpuinfo_arm64_linux_decode_isa_from_proc_cpuinfo(
- const struct cpuinfo_arm_linux_processor processor[restrict static 1],
+ uint32_t features,
struct cpuinfo_arm_isa isa[restrict static 1])
{
- const uint32_t features = processor->features;
if (features & CPUINFO_ARM_LINUX_FEATURE_AES) {
isa->aes = true;
}
diff --git a/src/arm/linux/api.h b/src/arm/linux/api.h
index 1c31ba1..6764032 100644
--- a/src/arm/linux/api.h
+++ b/src/arm/linux/api.h
@@ -247,11 +247,15 @@ bool cpuinfo_arm_linux_parse_proc_cpuinfo(
#if CPUINFO_ARCH_ARM
void cpuinfo_arm_linux_decode_isa_from_proc_cpuinfo(
- const struct cpuinfo_arm_linux_processor processors[restrict static 1],
+ uint32_t features,
+ uint32_t features2,
+ uint32_t midr,
+ uint32_t architecture_version,
+ uint32_t architecture_flags,
struct cpuinfo_arm_isa isa[restrict static 1]);
#elif CPUINFO_ARCH_ARM64
void cpuinfo_arm64_linux_decode_isa_from_proc_cpuinfo(
- const struct cpuinfo_arm_linux_processor processors[restrict static 1],
+ uint32_t features,
struct cpuinfo_arm_isa isa[restrict static 1]);
#endif
diff --git a/src/arm/linux/init.c b/src/arm/linux/init.c
index 6a7ab5d..d7ad54a 100644
--- a/src/arm/linux/init.c
+++ b/src/arm/linux/init.c
@@ -169,7 +169,9 @@ void cpuinfo_arm_linux_init(void) {
}
uint32_t usable_processors = 0;
- uint32_t known_processors = 0;
+ #if CPUINFO_ARCH_ARM
+ uint32_t last_midr = 0, last_architecture_version = 0, last_architecture_flags = 0;
+ #endif
for (uint32_t i = 0; i < arm_linux_processors_count; i++) {
arm_linux_processors[i].system_processor_id = i;
if (bitmask_all(arm_linux_processors[i].flags, CPUINFO_LINUX_MASK_USABLE)) {
@@ -183,25 +185,15 @@ void cpuinfo_arm_linux_init(void) {
cpuinfo_log_info("processor %"PRIu32" is not listed in /proc/cpuinfo", i);
}
- if (bitmask_all(arm_linux_processors[i].flags, CPUINFO_ARM_LINUX_VALID_INFO)) {
- if (known_processors == 0) {
- /*
- * This is the first processor for which we have complete information.
- * Use it to detect instruction set architecture.
- * If there are several cores with different microarchitecture, we expect
- * Linux kernel to report the same ISA extensions for each of them.
- */
- #if CPUINFO_ARCH_ARM
- cpuinfo_arm_linux_decode_isa_from_proc_cpuinfo(
- &arm_linux_processors[i], &cpuinfo_isa);
- #elif CPUINFO_ARCH_ARM64
- cpuinfo_arm64_linux_decode_isa_from_proc_cpuinfo(
- &arm_linux_processors[i], &cpuinfo_isa);
- #endif
+ #if CPUINFO_ARCH_ARM
+ if (bitmask_all(arm_linux_processors[i].flags, CPUINFO_ARM_LINUX_VALID_MIDR)) {
+ last_midr = arm_linux_processors[i].midr;
}
-
- known_processors += 1;
- }
+ if (bitmask_all(arm_linux_processors[i].flags, CPUINFO_ARM_LINUX_VALID_ARCHITECTURE)) {
+ last_architecture_version = arm_linux_processors[i].architecture_version;
+ last_architecture_flags = arm_linux_processors[i].architecture_flags;
+ }
+ #endif
} else {
/* Processor reported in /proc/cpuinfo, but not in possible and/or present lists: log and ignore */
if (!(arm_linux_processors[i].flags & CPUINFO_ARM_LINUX_VALID_PROCESSOR)) {
@@ -210,6 +202,37 @@ void cpuinfo_arm_linux_init(void) {
}
}
+ /* Detect ISA. If different processors report different ISA features, take the intersection. */
+ uint32_t isa_features = 0, processors_with_features = 0;
+ #if CPUINFO_ARCH_ARM
+ uint32_t isa_features2 = 0;
+ #endif
+ for (uint32_t i = 0; i < arm_linux_processors_count; i++) {
+ if (bitmask_all(arm_linux_processors[i].flags, CPUINFO_LINUX_MASK_USABLE | CPUINFO_ARM_LINUX_VALID_FEATURES)) {
+ if (processors_with_features == 0) {
+ isa_features = arm_linux_processors[i].features;
+ #if CPUINFO_ARCH_ARM
+ isa_features2 = arm_linux_processors[i].features2;
+ #endif
+ } else {
+ isa_features &= arm_linux_processors[i].features;
+ #if CPUINFO_ARCH_ARM
+ isa_features2 &= arm_linux_processors[i].features2;
+ #endif
+ }
+ processors_with_features += 1;
+ }
+ }
+ #if CPUINFO_ARCH_ARM
+ cpuinfo_arm_linux_decode_isa_from_proc_cpuinfo(
+ isa_features, isa_features2,
+ last_midr, last_architecture_version, last_architecture_flags,
+ &cpuinfo_isa);
+ #elif CPUINFO_ARCH_ARM64
+ cpuinfo_arm64_linux_decode_isa_from_proc_cpuinfo(
+ isa_features, &cpuinfo_isa);
+ #endif
+
/* Detect min/max frequency and package ID */
for (uint32_t i = 0; i < arm_linux_processors_count; i++) {
if (bitmask_all(arm_linux_processors[i].flags, CPUINFO_LINUX_MASK_USABLE)) {