1 /* arm_features.c -- ARM processor features detection. 2 * 3 * Copyright 2018 The Chromium Authors. All rights reserved. 4 * Use of this source code is governed by a BSD-style license that can be 5 * found in the Chromium source repository LICENSE file. 6 */ 7 8 #include "arm_features.h" 9 #include "zutil.h" 10 #include <stdint.h> 11 12 int ZLIB_INTERNAL arm_cpu_enable_crc32 = 0; 13 int ZLIB_INTERNAL arm_cpu_enable_pmull = 0; 14 15 #if defined(ARMV8_OS_ANDROID) || defined(ARMV8_OS_LINUX) || defined(ARMV8_OS_FUCHSIA) 16 #include <pthread.h> 17 #endif 18 19 #if defined(ARMV8_OS_ANDROID) 20 #include <cpu-features.h> 21 #elif defined(ARMV8_OS_LINUX) 22 #include <asm/hwcap.h> 23 #include <sys/auxv.h> 24 #elif defined(ARMV8_OS_FUCHSIA) 25 #include <zircon/features.h> 26 #include <zircon/syscalls.h> 27 #include <zircon/types.h> 28 #elif defined(ARMV8_OS_WINDOWS) 29 #include <windows.h> 30 #else 31 #error arm_features.c ARM feature detection in not defined for your platform 32 #endif 33 34 static void _arm_check_features(void); 35 36 #if defined(ARMV8_OS_ANDROID) || defined(ARMV8_OS_LINUX) || defined(ARMV8_OS_FUCHSIA) 37 static pthread_once_t cpu_check_inited_once = PTHREAD_ONCE_INIT; arm_check_features(void)38void ZLIB_INTERNAL arm_check_features(void) 39 { 40 pthread_once(&cpu_check_inited_once, _arm_check_features); 41 } 42 #elif defined(ARMV8_OS_WINDOWS) 43 static INIT_ONCE cpu_check_inited_once = INIT_ONCE_STATIC_INIT; _arm_check_features_forwarder(PINIT_ONCE once,PVOID param,PVOID * context)44static BOOL CALLBACK _arm_check_features_forwarder(PINIT_ONCE once, PVOID param, PVOID* context) 45 { 46 _arm_check_features(); 47 return TRUE; 48 } arm_check_features(void)49void ZLIB_INTERNAL arm_check_features(void) 50 { 51 InitOnceExecuteOnce(&cpu_check_inited_once, _arm_check_features_forwarder, 52 NULL, NULL); 53 } 54 #endif 55 56 /* 57 * See http://bit.ly/2CcoEsr for run-time detection of ARM features and also 58 * crbug.com/931275 for android_getCpuFeatures() use in the Android sandbox. 59 */ _arm_check_features(void)60static void _arm_check_features(void) 61 { 62 #if defined(ARMV8_OS_ANDROID) && defined(__aarch64__) 63 uint64_t features = android_getCpuFeatures(); 64 arm_cpu_enable_crc32 = !!(features & ANDROID_CPU_ARM64_FEATURE_CRC32); 65 arm_cpu_enable_pmull = !!(features & ANDROID_CPU_ARM64_FEATURE_PMULL); 66 #elif defined(ARMV8_OS_ANDROID) /* aarch32 */ 67 uint64_t features = android_getCpuFeatures(); 68 arm_cpu_enable_crc32 = !!(features & ANDROID_CPU_ARM_FEATURE_CRC32); 69 arm_cpu_enable_pmull = !!(features & ANDROID_CPU_ARM_FEATURE_PMULL); 70 #elif defined(ARMV8_OS_LINUX) && defined(__aarch64__) 71 unsigned long features = getauxval(AT_HWCAP); 72 arm_cpu_enable_crc32 = !!(features & HWCAP_CRC32); 73 arm_cpu_enable_pmull = !!(features & HWCAP_PMULL); 74 #elif defined(ARMV8_OS_LINUX) && (defined(__ARM_NEON) || defined(__ARM_NEON__)) 75 /* Query HWCAP2 for ARMV8-A SoCs running in aarch32 mode */ 76 unsigned long features = getauxval(AT_HWCAP2); 77 arm_cpu_enable_crc32 = !!(features & HWCAP2_CRC32); 78 arm_cpu_enable_pmull = !!(features & HWCAP2_PMULL); 79 #elif defined(ARMV8_OS_FUCHSIA) 80 uint32_t features; 81 zx_status_t rc = zx_system_get_features(ZX_FEATURE_KIND_CPU, &features); 82 if (rc != ZX_OK || (features & ZX_ARM64_FEATURE_ISA_ASIMD) == 0) 83 return; /* Report nothing if ASIMD(NEON) is missing */ 84 arm_cpu_enable_crc32 = !!(features & ZX_ARM64_FEATURE_ISA_CRC32); 85 arm_cpu_enable_pmull = !!(features & ZX_ARM64_FEATURE_ISA_PMULL); 86 #elif defined(ARMV8_OS_WINDOWS) 87 arm_cpu_enable_crc32 = IsProcessorFeaturePresent(PF_ARM_V8_CRC32_INSTRUCTIONS_AVAILABLE); 88 arm_cpu_enable_pmull = IsProcessorFeaturePresent(PF_ARM_V8_CRYPTO_INSTRUCTIONS_AVAILABLE); 89 #endif 90 } 91