diff options
author | Jussi Kivilinna <jussi.kivilinna@iki.fi> | 2013-08-31 12:48:30 +0300 |
---|---|---|
committer | Jussi Kivilinna <jussi.kivilinna@iki.fi> | 2013-08-31 12:48:30 +0300 |
commit | 9c95be105f518d18407115c2c06893857c24b116 (patch) | |
tree | 7c554e2f270dbd8b870766045bfd2a06333181fa /src/hwf-arm.c | |
parent | 7b0ebe69fe35f2ee13e1e1beb2766a1eaadb7f0c (diff) | |
download | libgcrypt-9c95be105f518d18407115c2c06893857c24b116.tar.gz |
Add ARM HW feature detection module and add NEON detection
* 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@iki.fi>
Diffstat (limited to 'src/hwf-arm.c')
-rw-r--r-- | src/hwf-arm.c | 113 |
1 files changed, 113 insertions, 0 deletions
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; +} |