aboutsummaryrefslogtreecommitdiffstats
path: root/crypto/armcap.c
diff options
context:
space:
mode:
authorAndy Polyakov <appro@openssl.org>2014-06-01 17:21:06 +0200
committerAndy Polyakov <appro@openssl.org>2014-06-01 17:21:06 +0200
commite8d93e342b4b7d43c73e955e81e227c514d389d9 (patch)
treeefbe9abfc0cdcea810358ae088284fc2ddd0a3fc /crypto/armcap.c
parent992bba11d53985c8d4cbcb5dd95034dbe92d3671 (diff)
downloadopenssl-e8d93e342b4b7d43c73e955e81e227c514d389d9.tar.gz
Add linux-aarch64 taget.
armcap.c is shared between 32- and 64-bit builds and features link-time detection of getauxval. Submitted by: Ard Biesheuvel.
Diffstat (limited to 'crypto/armcap.c')
-rw-r--r--crypto/armcap.c71
1 files changed, 62 insertions, 9 deletions
diff --git a/crypto/armcap.c b/crypto/armcap.c
index 550414425d..7e46d07a32 100644
--- a/crypto/armcap.c
+++ b/crypto/armcap.c
@@ -23,9 +23,9 @@ void _armv8_aes_probe(void);
void _armv8_sha1_probe(void);
void _armv8_sha256_probe(void);
void _armv8_pmull_probe(void);
-unsigned int _armv7_tick(void);
+unsigned long _armv7_tick(void);
-unsigned int OPENSSL_rdtsc(void)
+unsigned long OPENSSL_rdtsc(void)
{
if (OPENSSL_armcap_P & ARMV7_TICK)
return _armv7_tick();
@@ -33,9 +33,41 @@ unsigned int OPENSSL_rdtsc(void)
return 0;
}
+/*
+ * Use a weak reference to getauxval() so we can use it if it is available but
+ * don't break the build if it is not.
+ */
#if defined(__GNUC__) && __GNUC__>=2
void OPENSSL_cpuid_setup(void) __attribute__((constructor));
+extern unsigned long getauxval(unsigned long type) __attribute__((weak));
+#else
+static unsigned long (*getauxval)(unsigned long) = NULL;
#endif
+
+/*
+ * ARM puts the the feature bits for Crypto Extensions in AT_HWCAP2, whereas
+ * AArch64 used AT_HWCAP.
+ */
+#if defined(__arm__) || defined (__arm)
+# define HWCAP 16 /* AT_HWCAP */
+# define HWCAP_NEON (1 << 12)
+
+# define HWCAP_CE 26 /* AT_HWCAP2 */
+# define HWCAP_CE_AES (1 << 0)
+# define HWCAP_CE_PMULL (1 << 1)
+# define HWCAP_CE_SHA1 (1 << 2)
+# define HWCAP_CE_SHA256 (1 << 3)
+#elif defined(__aarch64__)
+# define HWCAP 16 /* AT_HWCAP */
+# define HWCAP_NEON (1 << 1)
+
+# define HWCAP_CE HWCAP
+# define HWCAP_CE_AES (1 << 3)
+# define HWCAP_CE_PMULL (1 << 4)
+# define HWCAP_CE_SHA1 (1 << 5)
+# define HWCAP_CE_SHA256 (1 << 6)
+#endif
+
void OPENSSL_cpuid_setup(void)
{
char *e;
@@ -48,7 +80,7 @@ void OPENSSL_cpuid_setup(void)
if ((e=getenv("OPENSSL_armcap")))
{
- OPENSSL_armcap_P=strtoul(e,NULL,0);
+ OPENSSL_armcap_P=(unsigned int)strtoul(e,NULL,0);
return;
}
@@ -68,12 +100,38 @@ void OPENSSL_cpuid_setup(void)
sigprocmask(SIG_SETMASK,&ill_act.sa_mask,&oset);
sigaction(SIGILL,&ill_act,&ill_oact);
- if (sigsetjmp(ill_jmp,1) == 0)
+ if (getauxval != NULL)
+ {
+ if (getauxval(HWCAP) & HWCAP_NEON)
+ {
+ unsigned long hwcap = getauxval(HWCAP_CE);
+
+ OPENSSL_armcap_P |= ARMV7_NEON;
+
+ if (hwcap & HWCAP_CE_AES)
+ OPENSSL_armcap_P |= ARMV8_AES;
+
+ if (hwcap & HWCAP_CE_PMULL)
+ OPENSSL_armcap_P |= ARMV8_PMULL;
+
+ if (hwcap & HWCAP_CE_SHA1)
+ OPENSSL_armcap_P |= ARMV8_SHA1;
+
+ if (hwcap & HWCAP_CE_SHA256)
+ OPENSSL_armcap_P |= ARMV8_SHA256;
+ }
+ }
+ else if (sigsetjmp(ill_jmp,1) == 0)
{
_armv7_neon_probe();
OPENSSL_armcap_P |= ARMV7_NEON;
if (sigsetjmp(ill_jmp,1) == 0)
{
+ _armv8_pmull_probe();
+ OPENSSL_armcap_P |= ARMV8_PMULL|ARMV8_AES;
+ }
+ else if (sigsetjmp(ill_jmp,1) == 0)
+ {
_armv8_aes_probe();
OPENSSL_armcap_P |= ARMV8_AES;
}
@@ -87,11 +145,6 @@ void OPENSSL_cpuid_setup(void)
_armv8_sha256_probe();
OPENSSL_armcap_P |= ARMV8_SHA256;
}
- if (sigsetjmp(ill_jmp,1) == 0)
- {
- _armv8_pmull_probe();
- OPENSSL_armcap_P |= ARMV8_PMULL;
- }
}
if (sigsetjmp(ill_jmp,1) == 0)
{