[PATCH 2/3] Add HW feature check for ARMv8 Aarch64 and crypto extensions
Jussi Kivilinna
jussi.kivilinna at iki.fi
Sun Jul 3 17:42:12 CEST 2016
* configure.ac: Add '--disable-arm-crypto-support'; enable hwf-arm
module on 64-bit ARM.
(armcryptosupport, gcry_cv_gcc_inline_aarch32_crypto)
(gcry_cv_inline_asm_aarch64_neon)
(gcry_cv_gcc_inline_asm_aarch64_crypto): New.
* src/g10lib.h (HWF_ARM_AES, HWF_ARM_SHA1, HWF_ARM_SHA2)
(HWF_ARM_PMULL): New.
* src/hwf-arm.c [__aarch64__]: Enable building in Aarch64 mode.
(feature_map_s): New.
[__arm__] (AT_HWCAP, AT_HWCAP2, HWCAP2_AES, HWCAP2_PMULL)
(HWCAP2_SHA1, HWCAP2_SHA2, arm_features): New.
[__aarch64__] (AT_HWCAP, AT_HWCAP2, HWCAP_ASIMD, HWCAP_AES)
(HWCAP_PMULL, HWCAP_SHA1, HWCAP_SHA2, arm_features): New.
(get_hwcap): Add reading of 'AT_HWCAP2'; Change auxv use
'unsigned long'.
(detect_arm_at_hwcap): Add mapping of HWCAP/HWCAP2 to HWF flags.
(detect_arm_proc_cpuinfo): Add mapping of CPU features to HWF flags.
(_gcry_hwf_detect_arm): Use __ARM_NEON instead of legacy __ARM_NEON__.
* src/hwfeatures.c (hwflist): Add 'arm-aes', 'arm-sha1', 'arm-sha2'
and 'arm-pmull'.
--
Signed-off-by: Jussi Kivilinna <jussi.kivilinna at iki.fi>
---
0 files changed
diff --git a/configure.ac b/configure.ac
index 80e64fa..2001596 100644
--- a/configure.ac
+++ b/configure.ac
@@ -637,6 +637,14 @@ AC_ARG_ENABLE(neon-support,
neonsupport=$enableval,neonsupport=yes)
AC_MSG_RESULT($neonsupport)
+# Implementation of the --disable-arm-crypto-support switch.
+AC_MSG_CHECKING([whether ARMv8 Crypto Extension support is requested])
+AC_ARG_ENABLE(arm-crypto-support,
+ AC_HELP_STRING([--disable-arm-crypto-support],
+ [Disable support for the ARMv8 Crypto Extension instructions]),
+ armcryptosupport=$enableval,armcryptosupport=yes)
+AC_MSG_RESULT($armcryptosupport)
+
# Implementation of the --disable-O-flag-munging switch.
AC_MSG_CHECKING([whether a -O flag munging is requested])
AC_ARG_ENABLE([O-flag-munging],
@@ -1125,7 +1133,10 @@ if test "$mpi_cpu_arch" != "x86" ; then
fi
if test "$mpi_cpu_arch" != "arm" ; then
- neonsupport="n/a"
+ if test "$mpi_cpu_arch" != "aarch64" ; then
+ neonsupport="n/a"
+ armcryptosupport="n/a"
+ fi
fi
@@ -1532,6 +1543,116 @@ if test "$gcry_cv_gcc_inline_asm_neon" = "yes" ; then
fi
+#
+# Check whether GCC inline assembler supports Aarch32 Crypto Extension instructions
+#
+AC_CACHE_CHECK([whether GCC inline assembler supports Aarch32 Crypto Extension instructions],
+ [gcry_cv_gcc_inline_asm_aarch32_crypto],
+ [if test "$mpi_cpu_arch" != "arm" ; then
+ gcry_cv_gcc_inline_asm_aarch32_crypto="n/a"
+ else
+ gcry_cv_gcc_inline_asm_aarch32_crypto=no
+ AC_COMPILE_IFELSE([AC_LANG_SOURCE(
+ [[__asm__(
+ ".syntax unified\n\t"
+ ".arm\n\t"
+ ".fpu crypto-neon-fp-armv8\n\t"
+
+ "sha1h.32 q0, q0;\n\t"
+ "sha1c.32 q0, q0, q0;\n\t"
+ "sha1p.32 q0, q0, q0;\n\t"
+ "sha1su0.32 q0, q0, q0;\n\t"
+ "sha1su1.32 q0, q0;\n\t"
+
+ "sha256h.32 q0, q0, q0;\n\t"
+ "sha256h2.32 q0, q0, q0;\n\t"
+ "sha1p.32 q0, q0, q0;\n\t"
+ "sha256su0.32 q0, q0;\n\t"
+ "sha256su1.32 q0, q0, q15;\n\t"
+
+ "aese.8 q0, q0;\n\t"
+ "aesd.8 q0, q0;\n\t"
+ "aesmc.8 q0, q0;\n\t"
+ "aesimc.8 q0, q0;\n\t"
+
+ "vmull.p64 q0, d0, d0;\n\t"
+ );
+ ]])],
+ [gcry_cv_gcc_inline_asm_aarch32_crypto=yes])
+ fi])
+if test "$gcry_cv_gcc_inline_asm_aarch32_crypto" = "yes" ; then
+ AC_DEFINE(HAVE_GCC_INLINE_ASM_AARCH32_CRYPTO,1,
+ [Defined if inline assembler supports Aarch32 Crypto Extension instructions])
+fi
+
+
+#
+# Check whether GCC inline assembler supports Aarch64 NEON instructions
+#
+AC_CACHE_CHECK([whether GCC inline assembler supports Aarch64 NEON instructions],
+ [gcry_cv_gcc_inline_asm_aarch64_neon],
+ [if test "$mpi_cpu_arch" != "aarch64" ; then
+ gcry_cv_gcc_inline_asm_aarch64_neon="n/a"
+ else
+ gcry_cv_gcc_inline_asm_aarch64_neon=no
+ AC_COMPILE_IFELSE([AC_LANG_SOURCE(
+ [[__asm__(
+ ".arch armv8-a\n\t"
+ "mov w0, \#42;\n\t"
+ "dup v0.8b, w0;\n\t"
+ "ld4 {v0.8b,v1.8b,v2.8b,v3.8b},[x0],\#32;\n\t"
+ );
+ ]])],
+ [gcry_cv_gcc_inline_asm_aarch64_neon=yes])
+ fi])
+if test "$gcry_cv_gcc_inline_asm_aarch64_neon" = "yes" ; then
+ AC_DEFINE(HAVE_GCC_INLINE_ASM_AARCH64_NEON,1,
+ [Defined if inline assembler supports Aarch64 NEON instructions])
+fi
+
+
+#
+# Check whether GCC inline assembler supports Aarch64 Crypto Extension instructions
+#
+AC_CACHE_CHECK([whether GCC inline assembler supports Aarch64 Crypto Extension instructions],
+ [gcry_cv_gcc_inline_asm_aarch64_crypto],
+ [if test "$mpi_cpu_arch" != "aarch64" ; then
+ gcry_cv_gcc_inline_asm_aarch64_crypto="n/a"
+ else
+ gcry_cv_gcc_inline_asm_aarch64_crypto=no
+ AC_COMPILE_IFELSE([AC_LANG_SOURCE(
+ [[__asm__(
+ ".arch armv8-a+crypto\n\t"
+
+ "sha1h s0, s0;\n\t"
+ "sha1c q0, s0, v0.4s;\n\t"
+ "sha1p q0, s0, v0.4s;\n\t"
+ "sha1su0 v0.4s, v0.4s, v0.4s;\n\t"
+ "sha1su1 v0.4s, v0.4s;\n\t"
+
+ "sha256h q0, q0, v0.4s;\n\t"
+ "sha256h2 q0, q0, v0.4s;\n\t"
+ "sha1p q0, s0, v0.4s;\n\t"
+ "sha256su0 v0.4s, v0.4s;\n\t"
+ "sha256su1 v0.4s, v0.4s, v31.4s;\n\t"
+
+ "aese v0.16b, v0.16b;\n\t"
+ "aesd v0.16b, v0.16b;\n\t"
+ "aesmc v0.16b, v0.16b;\n\t"
+ "aesimc v0.16b, v0.16b;\n\t"
+
+ "pmull v0.1q, v0.1d, v31.1d;\n\t"
+ "pmull2 v0.1q, v0.2d, v31.2d;\n\t"
+ );
+ ]])],
+ [gcry_cv_gcc_inline_asm_aarch64_crypto=yes])
+ fi])
+if test "$gcry_cv_gcc_inline_asm_aarch64_crypto" = "yes" ; then
+ AC_DEFINE(HAVE_GCC_INLINE_ASM_AARCH64_CRYPTO,1,
+ [Defined if inline assembler supports Aarch64 Crypto Extension instructions])
+fi
+
+
#######################################
#### Checks for library functions. ####
#######################################
@@ -1758,7 +1879,16 @@ if test x"$avx2support" = xyes ; then
fi
if test x"$neonsupport" = xyes ; then
if test "$gcry_cv_gcc_inline_asm_neon" != "yes" ; then
- neonsupport="no (unsupported by compiler)"
+ if test "$gcry_cv_gcc_inline_asm_aarch64_neon" != "yes" ; then
+ neonsupport="no (unsupported by compiler)"
+ fi
+ fi
+fi
+if test x"$armcryptosupport" = xyes ; then
+ if test "$gcry_cv_gcc_inline_asm_aarch32_crypto" != "yes" ; then
+ if test "$gcry_cv_gcc_inline_asm_aarch64_crypto" != "yes" ; then
+ neonsupport="no (unsupported by compiler)"
+ fi
fi
fi
@@ -1786,6 +1916,10 @@ if test x"$neonsupport" = xyes ; then
AC_DEFINE(ENABLE_NEON_SUPPORT,1,
[Enable support for ARM NEON instructions.])
fi
+if test x"$armcryptosupport" = xyes ; then
+ AC_DEFINE(ENABLE_ARM_CRYPTO_SUPPORT,1,
+ [Enable support for ARMv8 Crypto Extension instructions.])
+fi
if test x"$padlocksupport" = xyes ; then
AC_DEFINE(ENABLE_PADLOCK_SUPPORT, 1,
[Enable support for the PadLock engine.])
@@ -2299,6 +2433,10 @@ case "$mpi_cpu_arch" in
AC_DEFINE(HAVE_CPU_ARCH_ARM, 1, [Defined for ARM platforms])
GCRYPT_HWF_MODULES="hwf-arm.lo"
;;
+ aarch64)
+ AC_DEFINE(HAVE_CPU_ARCH_ARM, 1, [Defined for ARM Aarch64 platforms])
+ GCRYPT_HWF_MODULES="hwf-arm.lo"
+ ;;
esac
AC_SUBST([GCRYPT_HWF_MODULES])
@@ -2384,6 +2522,7 @@ 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([Try using ARMv8 crypto: ],[$armcryptosupport])
GCRY_MSG_SHOW([],[])
if test "x${gpg_config_script_warn}" != x; then
diff --git a/src/g10lib.h b/src/g10lib.h
index 170ffa1..444c868 100644
--- a/src/g10lib.h
+++ b/src/g10lib.h
@@ -211,6 +211,10 @@ char **_gcry_strtokenize (const char *string, const char *delim);
#define HWF_INTEL_AVX2 (1 << 13)
#define HWF_ARM_NEON (1 << 14)
+#define HWF_ARM_AES (1 << 15)
+#define HWF_ARM_SHA1 (1 << 16)
+#define HWF_ARM_SHA2 (1 << 17)
+#define HWF_ARM_PMULL (1 << 18)
gpg_err_code_t _gcry_disable_hw_feature (const char *name);
diff --git a/src/hwf-arm.c b/src/hwf-arm.c
index 3dc050e..6f0bb95 100644
--- a/src/hwf-arm.c
+++ b/src/hwf-arm.c
@@ -27,7 +27,7 @@
#include "g10lib.h"
#include "hwf-common.h"
-#if !defined (__arm__)
+#if !defined (__arm__) && !defined (__aarch64__)
# error Module build for wrong CPU.
#endif
@@ -35,23 +35,81 @@
#undef HAS_PROC_CPUINFO
#ifdef __linux__
+struct feature_map_s {
+ unsigned int hwcap_flag;
+ unsigned int hwcap2_flag;
+ const char *feature_match;
+ unsigned int hwf_flag;
+};
+
#define HAS_SYS_AT_HWCAP 1
+#define HAS_PROC_CPUINFO 1
+
+#ifdef __arm__
+
+#define AT_HWCAP 16
+#define AT_HWCAP2 26
+
+#define HWCAP_NEON 4096
-#define AT_HWCAP 16
-#define HWCAP_NEON 4096
+#define HWCAP2_AES 1
+#define HWCAP2_PMULL 2
+#define HWCAP2_SHA1 3
+#define HWCAP2_SHA2 4
+
+static const struct feature_map_s arm_features[] =
+ {
+#ifdef ENABLE_NEON_SUPPORT
+ { HWCAP_NEON, 0, " neon", HWF_ARM_NEON },
+#endif
+#ifdef ENABLE_ARM_CRYPTO_SUPPORT
+ { 0, HWCAP2_AES, " aes", HWF_ARM_AES },
+ { 0, HWCAP2_SHA1," sha1", HWF_ARM_SHA1 },
+ { 0, HWCAP2_SHA2, " sha2", HWF_ARM_SHA2 },
+ { 0, HWCAP2_PMULL, " pmull", HWF_ARM_PMULL },
+#endif
+ };
+
+#elif defined(__aarch64__)
+
+#define AT_HWCAP 16
+#define AT_HWCAP2 -1
+
+#define HWCAP_ASIMD 2
+#define HWCAP_AES 8
+#define HWCAP_PMULL 16
+#define HWCAP_SHA1 32
+#define HWCAP_SHA2 64
+
+static const struct feature_map_s arm_features[] =
+ {
+#ifdef ENABLE_NEON_SUPPORT
+ { HWCAP_ASIMD, 0, " asimd", HWF_ARM_NEON },
+#endif
+#ifdef ENABLE_ARM_CRYPTO_SUPPORT
+ { HWCAP_AES, 0, " aes", HWF_ARM_AES },
+ { HWCAP_SHA1, 0, " sha1", HWF_ARM_SHA1 },
+ { HWCAP_SHA2, 0, " sha2", HWF_ARM_SHA2 },
+ { HWCAP_PMULL, 0, " pmull", HWF_ARM_PMULL },
+#endif
+ };
+
+#endif
static int
-get_hwcap(unsigned int *hwcap)
+get_hwcap(unsigned int *hwcap, unsigned int *hwcap2)
{
- struct { unsigned int a_type; unsigned int a_val; } auxv;
+ struct { unsigned long a_type; unsigned long a_val; } auxv;
FILE *f;
int err = -1;
static int hwcap_initialized = 0;
- static unsigned int stored_hwcap;
+ static unsigned int stored_hwcap = 0;
+ static unsigned int stored_hwcap2 = 0;
if (hwcap_initialized)
{
*hwcap = stored_hwcap;
+ *hwcap2 = stored_hwcap2;
return 0;
}
@@ -59,22 +117,31 @@ get_hwcap(unsigned int *hwcap)
if (!f)
{
*hwcap = stored_hwcap;
+ *hwcap2 = stored_hwcap2;
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;
+ if (auxv.a_type == AT_HWCAP)
+ {
+ stored_hwcap = auxv.a_val;
+ hwcap_initialized = 1;
+ }
+
+ if (auxv.a_type == AT_HWCAP2)
+ {
+ stored_hwcap2 = auxv.a_val;
+ hwcap_initialized = 1;
+ }
}
+ if (hwcap_initialized)
+ err = 0;
+
fclose(f);
*hwcap = stored_hwcap;
+ *hwcap2 = stored_hwcap2;
return err;
}
@@ -82,29 +149,34 @@ static unsigned int
detect_arm_at_hwcap(void)
{
unsigned int hwcap;
+ unsigned int hwcap2;
unsigned int features = 0;
+ unsigned int i;
- if (get_hwcap(&hwcap) < 0)
+ if (get_hwcap(&hwcap, &hwcap2) < 0)
return features;
-#ifdef ENABLE_NEON_SUPPORT
- if (hwcap & HWCAP_NEON)
- features |= HWF_ARM_NEON;
-#endif
+ for (i = 0; i < DIM(arm_features); i++)
+ {
+ if (hwcap & arm_features[i].hwcap_flag)
+ features |= arm_features[i].hwf_flag;
+
+ if (hwcap2 & arm_features[i].hwcap2_flag)
+ features |= arm_features[i].hwf_flag;
+ }
return features;
}
-#define HAS_PROC_CPUINFO 1
-
static unsigned int
detect_arm_proc_cpuinfo(unsigned int *broken_hwfs)
{
char buf[1024]; /* large enough */
- char *str_features, *str_neon;
+ char *str_features, *str_feat;
int cpu_implementer, cpu_arch, cpu_variant, cpu_part, cpu_revision;
FILE *f;
int readlen, i;
+ size_t mlen;
static int cpuinfo_initialized = 0;
static unsigned int stored_cpuinfo_features;
static unsigned int stored_broken_hwfs;
@@ -162,7 +234,11 @@ detect_arm_proc_cpuinfo(unsigned int *broken_hwfs)
continue;
str += 2;
- *cpu_entries[i].value = strtoul(str, NULL, 0);
+ if (strcmp(cpu_entries[i].name, "CPU architecture") == 0
+ && strcmp(str, "Aarch64") == 0)
+ *cpu_entries[i].value = 8;
+ else
+ *cpu_entries[i].value = strtoul(str, NULL, 0);
}
/* Lines to strings. */
@@ -170,10 +246,19 @@ detect_arm_proc_cpuinfo(unsigned int *broken_hwfs)
if (buf[i] == '\n')
buf[i] = '\0';
- /* Check for NEON. */
- str_neon = strstr(str_features, " neon");
- if (str_neon && (str_neon[5] == ' ' || str_neon[5] == '\0'))
- stored_cpuinfo_features |= HWF_ARM_NEON;
+ /* Check features. */
+ for (i = 0; i < DIM(arm_features); i++)
+ {
+ str_feat = strstr(str_features, arm_features[i].feature_match);
+ if (str_feat)
+ {
+ mlen = strlen(arm_features[i].feature_match);
+ if (str_feat[mlen] == ' ' || str_feat[mlen] == '\0')
+ {
+ stored_cpuinfo_features |= arm_features[i].hwf_flag;
+ }
+ }
+ }
/* Check for CPUs with broken NEON implementation. See
* https://code.google.com/p/chromium/issues/detail?id=341598
@@ -207,7 +292,7 @@ _gcry_hwf_detect_arm (void)
ret |= detect_arm_proc_cpuinfo (&broken_hwfs);
#endif
-#if defined(__ARM_NEON__) && defined(ENABLE_NEON_SUPPORT)
+#if defined(__ARM_NEON) && defined(ENABLE_NEON_SUPPORT)
ret |= HWF_ARM_NEON;
#endif
diff --git a/src/hwfeatures.c b/src/hwfeatures.c
index 4cafae1..07221e8 100644
--- a/src/hwfeatures.c
+++ b/src/hwfeatures.c
@@ -56,7 +56,11 @@ static struct
{ HWF_INTEL_RDRAND, "intel-rdrand" },
{ HWF_INTEL_AVX, "intel-avx" },
{ HWF_INTEL_AVX2, "intel-avx2" },
- { HWF_ARM_NEON, "arm-neon" }
+ { HWF_ARM_NEON, "arm-neon" },
+ { HWF_ARM_AES, "arm-aes" },
+ { HWF_ARM_SHA1, "arm-sha1" },
+ { HWF_ARM_SHA2, "arm-sha2" },
+ { HWF_ARM_PMULL, "arm-pmull" }
};
/* A bit vector with the hardware features which shall not be used.
More information about the Gcrypt-devel
mailing list