• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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)38 void 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)44 static 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)49 void 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)60 static 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