Remove macro hacks for internal vs. external functions. Part 1.
[libgcrypt.git] / src / hwf-arm.c
1 /* hwf-arm.c - Detect hardware features - ARM part
2  * Copyright © 2013  Jussi Kivilinna <jussi.kivilinna@iki.fi>
3  *
4  * This file is part of Libgcrypt.
5  *
6  * Libgcrypt is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU Lesser General Public License as
8  * published by the Free Software Foundation; either version 2.1 of
9  * the License, or (at your option) any later version.
10  *
11  * Libgcrypt is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this program; if not, see <http://www.gnu.org/licenses/>.
18  */
19
20 #include <config.h>
21 #include <stdio.h>
22 #include <stdlib.h>
23 #include <string.h>
24 #include <stdarg.h>
25 #include <unistd.h>
26
27 #include "g10lib.h"
28 #include "hwf-common.h"
29
30 #if !defined (__arm__)
31 # error Module build for wrong CPU.
32 #endif
33
34 #undef HAS_SYS_AT_HWCAP
35 #ifdef __linux__
36
37 #define HAS_SYS_AT_HWCAP 1
38
39 #define AT_HWCAP 16
40 #define HWCAP_NEON 4096
41
42 static int get_hwcap(unsigned int *hwcap)
43 {
44   struct { unsigned int a_type; unsigned int a_val; } auxv;
45   FILE *f;
46   int err = -1;
47   static int hwcap_initialized = 0;
48   static unsigned int stored_hwcap;
49
50   if (hwcap_initialized)
51     {
52       *hwcap = stored_hwcap;
53       return 0;
54     }
55
56   f = fopen("/proc/self/auxv", "r");
57   if (!f)
58     {
59       *hwcap = stored_hwcap;
60       return -1;
61     }
62
63   while (fread(&auxv, sizeof(auxv), 1, f) > 0)
64     {
65       if (auxv.a_type != AT_HWCAP)
66         continue;
67
68       stored_hwcap = auxv.a_val;
69       hwcap_initialized = 1;
70       err = 0;
71       break;
72     }
73
74   fclose(f);
75   *hwcap = stored_hwcap;
76   return err;
77 }
78
79 static unsigned int detect_arm_at_hwcap(void)
80 {
81   unsigned int hwcap;
82   unsigned int features = 0;
83
84   if (get_hwcap(&hwcap) < 0)
85     return features;
86
87 #ifdef ENABLE_NEON_SUPPORT
88   if (hwcap & HWCAP_NEON)
89     features |= HWF_ARM_NEON;
90 #endif
91
92   return features;
93 }
94
95 #endif /* __linux__ */
96
97 unsigned int
98 _gcry_hwf_detect_arm (void)
99 {
100   unsigned int ret = 0;
101
102 #if defined (HAS_SYS_AT_HWCAP)
103   ret |= detect_arm_at_hwcap ();
104 #else
105   ret |= 0;
106 #endif
107
108 #if defined(__ARM_NEON__) && defined(ENABLE_NEON_SUPPORT)
109   ret |= HWF_ARM_NEON;
110 #endif
111
112   return ret;
113 }