diff options
-rw-r--r-- | configure.ac | 43 | ||||
-rw-r--r-- | src/Makefile.am | 2 | ||||
-rw-r--r-- | src/g10lib.h | 2 | ||||
-rw-r--r-- | src/global.c | 1 | ||||
-rw-r--r-- | src/hwf-arm.c | 113 | ||||
-rw-r--r-- | src/hwf-common.h | 1 | ||||
-rw-r--r-- | src/hwfeatures.c | 5 |
7 files changed, 166 insertions, 1 deletions
diff --git a/configure.ac b/configure.ac index b54b4d61..89b9366d 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 8eb46e6e..d4329c9d 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 198ab386..31131a54 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 9c80573e..44667cfb 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 00000000..9ab4cd0f --- /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@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 974f47dd..8f156b56 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 87d05d83..1e3c27dc 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; } |