Add linux-aarch64 taget.
[openssl.git] / crypto / armcap.c
index 550414425d6bd9a8d1c56a5ac377abe03e57ac95..7e46d07a3232c06cb359fbc64110c21680c80e84 100644 (file)
@@ -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,11 +100,37 @@ 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)
                {