Hello,

I've been getting "undefined instruction" errors in my syslog caused by the cpu features detection code in armcap.c. These messages show up when CONFIG_DEBUG_USER is enabled in the kernel.

To eliminate the errors I have updated the cpu detection code to use /proc/self/auxv and /proc/cpuinfo when compiled on Linux. Since the indentation style does not match the original code, I will redo
the patch if you decide you want to roll it into your source tree.

Correct my if I'm wrong, but I'm pretty sure that ARMV7_TICK should be
enabled only on cortex processors.

--- ./crypto/armcap.c.orig    2011-11-14 13:58:00.000000000 -0700
+++ ./crypto/armcap.c    2012-07-05 14:23:26.629064351 -0600
@@ -9,6 +9,87 @@

 unsigned int OPENSSL_armcap_P;

+#if defined(__linux__)
+
+#include <asm/hwcap.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/mman.h>
+#include <fcntl.h>
+#include <string.h>
+#include <elf.h>
+
+static unsigned int
+linux_auxv()
+{
+    int fd;
+    Elf32_auxv_t aux;
+    unsigned int cap = 0;
+
+    fd = open ("/proc/self/auxv", O_RDONLY);
+    if (fd >= 0)
+    {
+    while (read (fd, &aux, sizeof(Elf32_auxv_t)) == sizeof(Elf32_auxv_t))
+    {
+        if (aux.a_type == AT_HWCAP)
+        {
+        uint32_t hwcap = aux.a_un.a_val;
+        if ( (hwcap & HWCAP_NEON) )
+            cap |= ARMV7_NEON;
+        break;
+        }
+    }
+    close (fd);
+    }
+
+    return cap;
+}
+
+static unsigned int
+linux_cpuinfo()
+{
+    unsigned int cap = 0;
+    FILE *fp = fopen ("/proc/cpuinfo", "r");
+
+    if ( fp )
+    {
+        char *line = 0;
+        size_t len = 0;
+        ssize_t read;
+        unsigned int partNo = 0;
+
+        while ((read = getline(&line, &len, fp)) != -1)
+        {
+            if ( ! strncmp(line, "CPU part", 8) )
+            {
+                // "CPU part\t: 0x581" // marvell dove v7l
+                // "CPU part\t: 0xC05" // cortex a5
+                char *p = line + 11;
+
+                sscanf(p, "%x\n", &partNo);
+
+                if ( (partNo >> 16) == 0xC ) // cortex family
+                    cap |= ARMV7_TICK;
+
+                break;
+            }
+        }
+
+        free(line);
+        fclose(fp);
+    }
+
+    return cap;
+}
+
+static unsigned int linux_set_capabilities(void)
+{
+    return linux_auxv() | linux_cpuinfo();
+}
+
+#else
+
 static sigset_t all_masked;

 static sigjmp_buf ill_jmp;
@@ -28,12 +109,16 @@ unsigned int OPENSSL_rdtsc(void)
     else
         return 0;
     }
+#endif

 #if defined(__GNUC__) && __GNUC__>=2
 void OPENSSL_cpuid_setup(void) __attribute__((constructor));
 #endif
 void OPENSSL_cpuid_setup(void)
     {
+#if defined(__linux__)
+    OPENSSL_armcap_P = linux_set_capabilities();
+#else
     char *e;
     struct sigaction    ill_oact,ill_act;
     sigset_t        oset;
@@ -41,7 +126,7 @@ void OPENSSL_cpuid_setup(void)

     if (trigger) return;
     trigger=1;
-
+
     if ((e=getenv("OPENSSL_armcap")))
         {
         OPENSSL_armcap_P=strtoul(e,NULL,0);
@@ -77,4 +162,5 @@ void OPENSSL_cpuid_setup(void)

     sigaction (SIGILL,&ill_oact,NULL);
     sigprocmask(SIG_SETMASK,&oset,NULL);
+#endif
     }

______________________________________________________________________
OpenSSL Project                                 http://www.openssl.org
Development Mailing List                       [email protected]
Automated List Manager                           [email protected]

Reply via email to