[PATCH 2/4] Add ARM HW feature detection module and add NEON detection
Jussi Kivilinna
jussi.kivilinna at iki.fi
Sat Aug 31 12:36:13 CEST 2013
* configure.ac: Add option --disable-neon-support.
(HAVE_GCC_INLINE_ASM_NEON): New.
(ENABLE_NEON_SUPPORT): New.
[arm]: Add 'hwf-arm.lo' as HW feature module.
* src/Makefile.am: Add 'hwf-arm.c'.
* src/g10lib.h (HWF_ARM_NEON): New macro.
* src/global.c (hwflist): Add HWF_ARM_NEON entry.
* src/hwf-arm.c: New file.
* src/hwf-common.h (_gcry_hwf_detect_arm): New prototype.
* src/hwfeatures.c (_gcry_detect_hw_features) [HAVE_CPU_ARCH_ARM]: Add
call to _gcry_hwf_detect_arm.
--
Add HW detection module for detecting ARM NEON instruction set. ARM does not
have cpuid instruction so we have to rely on OS to pass feature set information
to user-space. For linux, NEON support can be detected by parsing
'/proc/self/auxv' for hardware capabilities information. For other OSes, NEON
can be detected by checking if platform/compiler only supports NEON capable
CPUs (by check if __ARM_NEON__ macro is defined).
Signed-off-by: Jussi Kivilinna <jussi.kivilinna at iki.fi>
---
configure.ac | 43 +++++++++++++++++++++
src/Makefile.am | 2 -
src/g10lib.h | 2 +
src/global.c | 1
src/hwf-arm.c | 113 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
src/hwf-common.h | 1
src/hwfeatures.c | 5 ++
7 files changed, 166 insertions(+), 1 deletion(-)
create mode 100644 src/hwf-arm.c
diff --git a/configure.ac b/configure.ac
index b54b4d6..89b9366 100644
--- a/configure.ac
+++ b/configure.ac
@@ -595,6 +595,14 @@ AC_ARG_ENABLE(avx2-support,
avx2support=$enableval,avx2support=yes)
AC_MSG_RESULT($avx2support)
+# Implementation of the --disable-neon-support switch.
+AC_MSG_CHECKING([whether NEON support is requested])
+AC_ARG_ENABLE(neon-support,
+ AC_HELP_STRING([--disable-neon-support],
+ [Disable support for the ARM NEON instructions]),
+ neonsupport=$enableval,neonsupport=yes)
+AC_MSG_RESULT($neonsupport)
+
# Implementation of the --disable-O-flag-munging switch.
AC_MSG_CHECKING([whether a -O flag munging is requested])
AC_ARG_ENABLE([O-flag-munging],
@@ -988,6 +996,30 @@ fi
#
+# Check whether GCC inline assembler supports NEON instructions
+#
+AC_CACHE_CHECK([whether GCC inline assembler supports NEON instructions],
+ [gcry_cv_gcc_inline_asm_neon],
+ [gcry_cv_gcc_inline_asm_neon=no
+ AC_COMPILE_IFELSE([AC_LANG_SOURCE(
+ [[__asm__(
+ ".syntax unified\n\t"
+ ".thumb\n\t"
+ ".fpu neon\n\t"
+ "vld1.64 {%q0-%q1}, [%r0]!;\n\t"
+ "vrev64.8 %q0, %q3;\n\t"
+ "vadd.u64 %q0, %q1;\n\t"
+ "vadd.s64 %d3, %d2, %d3;\n\t"
+ );
+ ]])],
+ [gcry_cv_gcc_inline_asm_neon=yes])])
+if test "$gcry_cv_gcc_inline_asm_neon" = "yes" ; then
+ AC_DEFINE(HAVE_GCC_INLINE_ASM_NEON,1,
+ [Defined if inline assembler supports NEON instructions])
+fi
+
+
+#
# Check whether GCC assembler supports features needed for our ARM
# implementations
#
@@ -1269,6 +1301,11 @@ if test x"$avx2support" = xyes ; then
avx2support="no (unsupported by compiler)"
fi
fi
+if test x"$neonsupport" = xyes ; then
+ if test "$gcry_cv_gcc_inline_asm_neon" != "yes" ; then
+ neonsupport="no (unsupported by compiler)"
+ fi
+fi
if test x"$aesnisupport" = xyes ; then
AC_DEFINE(ENABLE_AESNI_SUPPORT, 1,
@@ -1282,6 +1319,10 @@ if test x"$avx2support" = xyes ; then
AC_DEFINE(ENABLE_AVX2_SUPPORT,1,
[Enable support for Intel AVX2 instructions.])
fi
+if test x"$neonsupport" = xyes ; then
+ AC_DEFINE(ENABLE_NEON_SUPPORT,1,
+ [Enable support for ARM NEON instructions.])
+fi
# Define conditional sources and config.h symbols depending on the
@@ -1597,6 +1638,7 @@ case "$mpi_cpu_arch" in
;;
arm)
AC_DEFINE(HAVE_CPU_ARCH_ARM, 1, [Defined for ARM platforms])
+ GCRYPT_HWF_MODULES="hwf-arm.lo"
;;
esac
AC_SUBST([GCRYPT_HWF_MODULES])
@@ -1660,6 +1702,7 @@ GCRY_MSG_SHOW([Try using AES-NI crypto: ],[$aesnisupport])
GCRY_MSG_SHOW([Try using DRNG (RDRAND): ],[$drngsupport])
GCRY_MSG_SHOW([Try using Intel AVX: ],[$avxsupport])
GCRY_MSG_SHOW([Try using Intel AVX2: ],[$avx2support])
+GCRY_MSG_SHOW([Try using ARM NEON: ],[$neonsupport])
GCRY_MSG_SHOW([],[])
if test "$print_egd_notice" = "yes"; then
diff --git a/src/Makefile.am b/src/Makefile.am
index 8eb46e6..d4329c9 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -64,7 +64,7 @@ libgcrypt_la_SOURCES = \
ec-context.h \
ath.h ath.c
-EXTRA_libgcrypt_la_SOURCES = hwf-x86.c
+EXTRA_libgcrypt_la_SOURCES = hwf-x86.c hwf-arm.c
gcrypt_hwf_modules = @GCRYPT_HWF_MODULES@
diff --git a/src/g10lib.h b/src/g10lib.h
index 198ab38..31131a5 100644
--- a/src/g10lib.h
+++ b/src/g10lib.h
@@ -155,6 +155,8 @@ int _gcry_log_verbosity( int level );
#define HWF_INTEL_AVX 1024
#define HWF_INTEL_AVX2 2048
+#define HWF_ARM_NEON 4096
+
unsigned int _gcry_get_hw_features (void);
void _gcry_detect_hw_features (unsigned int);
diff --git a/src/global.c b/src/global.c
index 9c80573..44667cf 100644
--- a/src/global.c
+++ b/src/global.c
@@ -70,6 +70,7 @@ static struct
{ HWF_INTEL_RDRAND,"intel-rdrand" },
{ HWF_INTEL_AVX, "intel-avx" },
{ HWF_INTEL_AVX2, "intel-avx2" },
+ { HWF_ARM_NEON, "arm-neon" },
{ 0, NULL}
};
diff --git a/src/hwf-arm.c b/src/hwf-arm.c
new file mode 100644
index 0000000..9ab4cd0
--- /dev/null
+++ b/src/hwf-arm.c
@@ -0,0 +1,113 @@
+/* hwf-arm.c - Detect hardware features - ARM part
+ * Copyright © 2013 Jussi Kivilinna <jussi.kivilinna at iki.fi>
+ *
+ * This file is part of Libgcrypt.
+ *
+ * Libgcrypt is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * Libgcrypt is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <config.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdarg.h>
+#include <unistd.h>
+
+#include "g10lib.h"
+#include "hwf-common.h"
+
+#if !defined (__arm__)
+# error Module build for wrong CPU.
+#endif
+
+#undef HAS_SYS_AT_HWCAP
+#ifdef __linux__
+
+#define HAS_SYS_AT_HWCAP 1
+
+#define AT_HWCAP 16
+#define HWCAP_NEON 4096
+
+static int get_hwcap(unsigned int *hwcap)
+{
+ struct { unsigned int a_type; unsigned int a_val; } auxv;
+ FILE *f;
+ int err = -1;
+ static int hwcap_initialized = 0;
+ static unsigned int stored_hwcap;
+
+ if (hwcap_initialized)
+ {
+ *hwcap = stored_hwcap;
+ return 0;
+ }
+
+ f = fopen("/proc/self/auxv", "r");
+ if (!f)
+ {
+ *hwcap = stored_hwcap;
+ return -1;
+ }
+
+ while (fread(&auxv, sizeof(auxv), 1, f) > 0)
+ {
+ if (auxv.a_type != AT_HWCAP)
+ continue;
+
+ stored_hwcap = auxv.a_val;
+ hwcap_initialized = 1;
+ err = 0;
+ break;
+ }
+
+ fclose(f);
+ *hwcap = stored_hwcap;
+ return err;
+}
+
+static unsigned int detect_arm_at_hwcap(void)
+{
+ unsigned int hwcap;
+ unsigned int features = 0;
+
+ if (get_hwcap(&hwcap) < 0)
+ return features;
+
+#ifdef ENABLE_NEON_SUPPORT
+ if (hwcap & HWCAP_NEON)
+ features |= HWF_ARM_NEON;
+#endif
+
+ return features;
+}
+
+#endif /* __linux__ */
+
+unsigned int
+_gcry_hwf_detect_arm (void)
+{
+ unsigned int ret = 0;
+
+#if defined (HAS_SYS_AT_HWCAP)
+ ret |= detect_arm_at_hwcap ();
+#else
+ ret |= 0;
+#endif
+
+#if defined(__ARM_NEON__) && defined(ENABLE_NEON_SUPPORT)
+ ret |= HWF_ARM_NEON;
+#endif
+
+ return ret;
+}
diff --git a/src/hwf-common.h b/src/hwf-common.h
index 974f47d..8f156b5 100644
--- a/src/hwf-common.h
+++ b/src/hwf-common.h
@@ -21,6 +21,7 @@
#define HWF_COMMON_H
unsigned int _gcry_hwf_detect_x86 (void);
+unsigned int _gcry_hwf_detect_arm (void);
#endif /*HWF_COMMON_H*/
diff --git a/src/hwfeatures.c b/src/hwfeatures.c
index 87d05d8..1e3c27d 100644
--- a/src/hwfeatures.c
+++ b/src/hwfeatures.c
@@ -59,6 +59,11 @@ _gcry_detect_hw_features (unsigned int disabled_features)
hw_features = _gcry_hwf_detect_x86 ();
}
#endif /* HAVE_CPU_ARCH_X86 */
+#if defined (HAVE_CPU_ARCH_ARM)
+ {
+ hw_features = _gcry_hwf_detect_arm ();
+ }
+#endif /* HAVE_CPU_ARCH_ARM */
hw_features &= ~disabled_features;
}
More information about the Gcrypt-devel
mailing list