diff options
author | Marat Dukhan <marat@fb.com> | 2017-11-28 11:07:11 -0800 |
---|---|---|
committer | Marat Dukhan <marat@fb.com> | 2017-11-28 11:07:11 -0800 |
commit | deaa898ad9e6474e2a96934604dd096d88ed9501 (patch) | |
tree | 488f6c5a41d9e39bfba6e9d505a891513213526a | |
parent | 595725424f46d6e363cec548f0746794d2a4fca9 (diff) | |
download | cpuinfo-deaa898ad9e6474e2a96934604dd096d88ed9501.tar.gz |
More robust ISA detection on ARM/Linux
-rw-r--r-- | CMakeLists.txt | 6 | ||||
-rwxr-xr-x | configure.py | 4 | ||||
-rw-r--r-- | jni/Android.mk | 12 | ||||
-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.h | 8 | ||||
-rw-r--r-- | src/arm/linux/init.c | 61 |
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)) { |