blob: 96392d8da0875cc229a2a59b312a8b519a405393 [file] [log] [blame]
Adam Langleyd749af72015-01-14 16:37:38 -08001/* Copyright (c) 2014, Google Inc.
Adam Langley95c29f32014-06-20 12:00:00 -07002 *
Adam Langleyd749af72015-01-14 16:37:38 -08003 * Permission to use, copy, modify, and/or distribute this software for any
4 * purpose with or without fee is hereby granted, provided that the above
5 * copyright notice and this permission notice appear in all copies.
Adam Langley95c29f32014-06-20 12:00:00 -07006 *
Adam Langleyd749af72015-01-14 16:37:38 -08007 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
8 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
9 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
10 * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
11 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
12 * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
13 * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */
Adam Langley95c29f32014-06-20 12:00:00 -070014
15#include <openssl/cpu.h>
16
Adam Langley3e652652015-01-09 15:44:37 -080017#if defined(OPENSSL_ARM) || defined(OPENSSL_AARCH64)
Adam Langley95c29f32014-06-20 12:00:00 -070018
Adam Langley95c29f32014-06-20 12:00:00 -070019#include <inttypes.h>
Adam Langley3e652652015-01-09 15:44:37 -080020#include <stdio.h>
Adam Langley95c29f32014-06-20 12:00:00 -070021
22#include "arm_arch.h"
23
Adam Langley95c29f32014-06-20 12:00:00 -070024
Adam Langleyd749af72015-01-14 16:37:38 -080025/* We can't include <sys/auxv.h> because the Android SDK version against which
26 * Chromium builds is too old to have it. Instead we define all the constants
27 * that we need and have a weak pointer to getauxval. */
28
29unsigned long getauxval(unsigned long type) __attribute__((weak));
30
31static const unsigned long AT_HWCAP = 16;
32static const unsigned long AT_HWCAP2 = 26;
33
David Benjaminc44d2f42014-08-20 16:24:00 -040034char CRYPTO_is_NEON_capable(void) {
Adam Langley95c29f32014-06-20 12:00:00 -070035 return (OPENSSL_armcap_P & ARMV7_NEON) != 0;
36}
37
38void CRYPTO_set_NEON_capable(char neon_capable) {
39 if (neon_capable) {
40 OPENSSL_armcap_P |= ARMV7_NEON;
41 } else {
42 OPENSSL_armcap_P &= ~ARMV7_NEON;
43 }
44}
45
David Benjaminc44d2f42014-08-20 16:24:00 -040046char CRYPTO_is_NEON_functional(void) {
Adam Langley31ebde92014-07-31 12:16:48 -070047 static const uint32_t kWantFlags = ARMV7_NEON | ARMV7_NEON_FUNCTIONAL;
48 return (OPENSSL_armcap_P & kWantFlags) == kWantFlags;
49}
50
51void CRYPTO_set_NEON_functional(char neon_functional) {
52 if (neon_functional) {
53 OPENSSL_armcap_P |= ARMV7_NEON_FUNCTIONAL;
54 } else {
55 OPENSSL_armcap_P &= ~ARMV7_NEON_FUNCTIONAL;
56 }
57}
58
Adam Langley3e652652015-01-09 15:44:37 -080059void OPENSSL_cpuid_setup(void) {
Adam Langleyd749af72015-01-14 16:37:38 -080060 if (getauxval == NULL) {
61 return;
62 }
63
Adam Langley3e652652015-01-09 15:44:37 -080064 unsigned long hwcap = getauxval(AT_HWCAP);
65
66#if defined(OPENSSL_ARM)
67 static const unsigned long kNEON = 1 << 12;
68 if ((hwcap & kNEON) == 0) {
69 return;
70 }
71
72 /* In 32-bit mode, the ARMv8 feature bits are in a different aux vector
73 * value. */
74 hwcap = getauxval(AT_HWCAP2);
75
76 /* See /usr/include/asm/hwcap.h on an ARM installation for the source of
77 * these values. */
78 static const unsigned long kAES = 1 << 0;
79 static const unsigned long kPMULL = 1 << 1;
80 static const unsigned long kSHA1 = 1 << 2;
81 static const unsigned long kSHA256 = 1 << 3;
82#elif defined(OPENSSL_AARCH64)
83 /* See /usr/include/asm/hwcap.h on an aarch64 installation for the source of
84 * these values. */
85 static const unsigned long kNEON = 1 << 1;
86 static const unsigned long kAES = 1 << 3;
87 static const unsigned long kPMULL = 1 << 4;
88 static const unsigned long kSHA1 = 1 << 5;
89 static const unsigned long kSHA256 = 1 << 6;
90
91 if ((hwcap & kNEON) == 0) {
92 return;
93 }
94#endif
95
96 OPENSSL_armcap_P |= ARMV7_NEON | ARMV7_NEON_FUNCTIONAL;
97
98 if (hwcap & kAES) {
99 OPENSSL_armcap_P |= ARMV8_AES;
100 }
101 if (hwcap & kPMULL) {
102 OPENSSL_armcap_P |= ARMV8_PMULL;
103 }
104 if (hwcap & kSHA1) {
105 OPENSSL_armcap_P |= ARMV8_SHA1;
106 }
107 if (hwcap & kSHA256) {
108 OPENSSL_armcap_P |= ARMV8_SHA256;
109 }
110}
111
112#endif /* defined(OPENSSL_ARM) || defined(OPENSSL_AARCH64) */