On 14.03.2019 08:41, Niels Möller wrote:
> "Yuriy M. Kaminskiy" <[email protected]> writes:
> 
>> When compiled for armv6+ and getauxval() is present (glibc 2.16+),
>> avoid slow and unreliable /proc/cpuinfo parsing.
>>  
>> E.g. /proc/cpuinfo contains junk with qemu-user and can be unavailable
>> in some chroot environment.
> 
> Do you know what's the preferred way to do this on android? Do we still
> need /proc/cpuinfo, or are there any library facilities?

Google suggests https://developer.android.com/ndk/guides/cpu-features
I have no experience with it.

>> +#if __GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 16)
>> +#include <sys/auxv.h>
> 
> This part could be an AC_CHECK_HEADERS([sys/auxv.h]) in configure.ac.

Hmm... musl also provides it, I'll move detection to configure; then again,
musl does not define HWCAP_*, and I'm reluctant to fallback to <asm/hwcap.h> or
define HWCAP_* myself, so practically it still works on glibc only.

>>    else
>>      {
>> +#if defined(HAVE_GETAUXVAL) && __ARM_ARCH >= 6
> 
> Why the condition __ARM_ARCH >= 6? Is it because getauxval doesn't let us
> make the distinction between arch_version 5 and 6?

There are (const char *)getauxval(AT_PLATFORM); it is expected to be 
"v[45678][lb]";
probably, I should use it.

Things that should be checked: arm (32bit) userland with aarch64/arm64 kernel.

>> +      unsigned long hwcap = getauxval(AT_HWCAP);
>> +      features->arch_version = __ARM_ARCH;
> 
> Is it important to take the compile-time arch into account? The effect
> (when it makes a difference at all) will be to force use of certain
> features, even if runtime checks say we're running on an older arch.

I wanted to limit change to cases I'm sure will work (e.g. on debian/armhf
__ARM_ARCH is 7, on raspbian - 6; both are sufficient for nettle to use most
optimized code); and don't touch anything "unusual".

> Is the getauxval method missing a way to get cpu arch at runtime? In the
> docs
> (https://github.com/torvalds/linux/blob/master/arch/arm/include/uapi/asm/hwcap.h)
> I don't see anything corresponding to the "CPU arcitecture" line in
> /proc/cpuinfo.
> 
> I'd be happier about getauxval if we could find a way to also get the
> arch version without reading /proc/cpuinfo. But I don't think it's a
> blocker for this change.

>From 184cc27c1592eea98f3bcb7e48a32bf97e126709 Mon Sep 17 00:00:00 2001
From: "Yuriy M. Kaminskiy" <[email protected]>
Date: Sun, 10 Mar 2019 12:25:21 +0300
Subject: [PATCH] fat-arm.c: prefer getauxval() over /proc/cpuinfo parsing

When getauxval() is present (glibc 2.16+), avoid slow and unreliable
/proc/cpuinfo parsing.

Use compile-time ARM archeticture as a fallback.

Use VFPv3 as fallback to ARMv7 detection when AT_PLATFORM is not
recognized (NEON implies VFPv3 with VFPD32; VFPv4 implies VFPv3;
when NEON present, VFPv4 implies NEONv2; VFPv3 implies armv7)
---
 configure.ac |  4 ++++
 fat-arm.c    | 32 ++++++++++++++++++++++++++++++++
 2 files changed, 36 insertions(+)

diff --git a/configure.ac b/configure.ac
index 4a482bdd..76fabfef 100644
--- a/configure.ac
+++ b/configure.ac
@@ -193,6 +193,10 @@ AC_CHECK_HEADERS([openssl/evp.h openssl/ecdsa.h],,
 [enable_openssl=no
  break])
 
+# For --enable-fat on arm
+AC_CHECK_HEADERS([sys/auxv.h])
+AC_CHECK_FUNCS(getauxval)
+
 # For use by the testsuite
 AC_CHECK_HEADERS([valgrind/memcheck.h])
 AC_CHECK_HEADERS([dlfcn.h])
diff --git a/fat-arm.c b/fat-arm.c
index 6e4c8622..cdc137a2 100644
--- a/fat-arm.c
+++ b/fat-arm.c
@@ -40,6 +40,15 @@
 #include <stdlib.h>
 #include <string.h>
 
+#ifdef HAVE_SYS_AUXV_H
+#include <sys/auxv.h>
+#if !defined(AT_HWCAP) || !defined(HWCAP_ARM_NEON) || !defined(AT_PLATFORM)
+#undef HAVE_GETAUXVAL
+#endif
+#else
+#undef HAVE_GETAUXVAL
+#endif
+
 #include "nettle-types.h"
 
 #include "aes-internal.h"
@@ -64,7 +73,11 @@ static void
 get_arm_features (struct arm_features *features)
 {
   const char *s;
+#if __ARM_ARCH > 5 /* use compile-time arch as fallback */
+  features->arch_version = __ARM_ARCH;
+#else
   features->arch_version = 5;
+#endif
   features->have_neon = 0;
 
   s = secure_getenv (ENV_OVERRIDE);
@@ -87,6 +100,24 @@ get_arm_features (struct arm_features *features)
       }
   else
     {
+#if defined(HAVE_GETAUXVAL)
+      unsigned long hwcap = getauxval(AT_HWCAP);
+      const char *platform = (const char *)getauxval(AT_PLATFORM);
+
+      if (platform != NULL && platform[0] == 'v' &&
+	  (platform[1] >= '0' && platform[1] <= '9') &&
+	  (platform[2] == 'l' || platform[2] == 'b'))
+	features->arch_version = platform[1] - '0';
+      else
+        {
+	  /* fallback to VFPv3 as a proxy for armv7 detection */
+	  if (features->arch_version < 7 && (hwcap & HWCAP_ARM_VFPv3))
+	    features->arch_version = 7;
+	}
+
+      if ((hwcap & HWCAP_ARM_NEON))
+	features->have_neon = 1;
+#else
       FILE *f;
       char line[200];
       int seen_arch = 0;
@@ -132,6 +163,7 @@ get_arm_features (struct arm_features *features)
 	  features->have_neon = 1;
 	}
       fclose (f);
+#endif
     }
 }
 
-- 
2.11.0

_______________________________________________
nettle-bugs mailing list
[email protected]
http://lists.lysator.liu.se/mailman/listinfo/nettle-bugs

Reply via email to