2106c41ba5c5cb35c839b6631496a1f8bc128823
[dpdk.git] / lib / librte_eal / common / include / arch / arm / rte_cpuflags_32.h
1 /*
2  *   BSD LICENSE
3  *
4  *   Copyright(c) 2015 RehiveTech. All rights reserved.
5  *
6  *   Redistribution and use in source and binary forms, with or without
7  *   modification, are permitted provided that the following conditions
8  *   are met:
9  *
10  *     * Redistributions of source code must retain the above copyright
11  *       notice, this list of conditions and the following disclaimer.
12  *     * Redistributions in binary form must reproduce the above copyright
13  *       notice, this list of conditions and the following disclaimer in
14  *       the documentation and/or other materials provided with the
15  *       distribution.
16  *     * Neither the name of RehiveTech nor the names of its
17  *       contributors may be used to endorse or promote products derived
18  *       from this software without specific prior written permission.
19  *
20  *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21  *   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22  *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
23  *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
24  *   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
25  *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
26  *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27  *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28  *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29  *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30  *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31  */
32
33 #ifndef _RTE_CPUFLAGS_ARM32_H_
34 #define _RTE_CPUFLAGS_ARM32_H_
35
36 #ifdef __cplusplus
37 extern "C" {
38 #endif
39
40 #include <elf.h>
41 #include <fcntl.h>
42 #include <assert.h>
43 #include <unistd.h>
44 #include <string.h>
45
46 #include "generic/rte_cpuflags.h"
47
48 #ifndef AT_HWCAP
49 #define AT_HWCAP 16
50 #endif
51
52 #ifndef AT_HWCAP2
53 #define AT_HWCAP2 26
54 #endif
55
56 #ifndef AT_PLATFORM
57 #define AT_PLATFORM 15
58 #endif
59
60 /* software based registers */
61 enum cpu_register_t {
62         REG_HWCAP = 0,
63         REG_HWCAP2,
64         REG_PLATFORM,
65 };
66
67 /**
68  * Enumeration of all CPU features supported
69  */
70 enum rte_cpu_flag_t {
71         RTE_CPUFLAG_SWP = 0,
72         RTE_CPUFLAG_HALF,
73         RTE_CPUFLAG_THUMB,
74         RTE_CPUFLAG_A26BIT,
75         RTE_CPUFLAG_FAST_MULT,
76         RTE_CPUFLAG_FPA,
77         RTE_CPUFLAG_VFP,
78         RTE_CPUFLAG_EDSP,
79         RTE_CPUFLAG_JAVA,
80         RTE_CPUFLAG_IWMMXT,
81         RTE_CPUFLAG_CRUNCH,
82         RTE_CPUFLAG_THUMBEE,
83         RTE_CPUFLAG_NEON,
84         RTE_CPUFLAG_VFPv3,
85         RTE_CPUFLAG_VFPv3D16,
86         RTE_CPUFLAG_TLS,
87         RTE_CPUFLAG_VFPv4,
88         RTE_CPUFLAG_IDIVA,
89         RTE_CPUFLAG_IDIVT,
90         RTE_CPUFLAG_VFPD32,
91         RTE_CPUFLAG_LPAE,
92         RTE_CPUFLAG_EVTSTRM,
93         RTE_CPUFLAG_AES,
94         RTE_CPUFLAG_PMULL,
95         RTE_CPUFLAG_SHA1,
96         RTE_CPUFLAG_SHA2,
97         RTE_CPUFLAG_CRC32,
98         RTE_CPUFLAG_V7L,
99         /* The last item */
100         RTE_CPUFLAG_NUMFLAGS,/**< This should always be the last! */
101 };
102
103 static const struct feature_entry cpu_feature_table[] = {
104         FEAT_DEF(SWP,       0x00000001, 0, REG_HWCAP,  0)
105         FEAT_DEF(HALF,      0x00000001, 0, REG_HWCAP,  1)
106         FEAT_DEF(THUMB,     0x00000001, 0, REG_HWCAP,  2)
107         FEAT_DEF(A26BIT,    0x00000001, 0, REG_HWCAP,  3)
108         FEAT_DEF(FAST_MULT, 0x00000001, 0, REG_HWCAP,  4)
109         FEAT_DEF(FPA,       0x00000001, 0, REG_HWCAP,  5)
110         FEAT_DEF(VFP,       0x00000001, 0, REG_HWCAP,  6)
111         FEAT_DEF(EDSP,      0x00000001, 0, REG_HWCAP,  7)
112         FEAT_DEF(JAVA,      0x00000001, 0, REG_HWCAP,  8)
113         FEAT_DEF(IWMMXT,    0x00000001, 0, REG_HWCAP,  9)
114         FEAT_DEF(CRUNCH,    0x00000001, 0, REG_HWCAP,  10)
115         FEAT_DEF(THUMBEE,   0x00000001, 0, REG_HWCAP,  11)
116         FEAT_DEF(NEON,      0x00000001, 0, REG_HWCAP,  12)
117         FEAT_DEF(VFPv3,     0x00000001, 0, REG_HWCAP,  13)
118         FEAT_DEF(VFPv3D16,  0x00000001, 0, REG_HWCAP,  14)
119         FEAT_DEF(TLS,       0x00000001, 0, REG_HWCAP,  15)
120         FEAT_DEF(VFPv4,     0x00000001, 0, REG_HWCAP,  16)
121         FEAT_DEF(IDIVA,     0x00000001, 0, REG_HWCAP,  17)
122         FEAT_DEF(IDIVT,     0x00000001, 0, REG_HWCAP,  18)
123         FEAT_DEF(VFPD32,    0x00000001, 0, REG_HWCAP,  19)
124         FEAT_DEF(LPAE,      0x00000001, 0, REG_HWCAP,  20)
125         FEAT_DEF(EVTSTRM,   0x00000001, 0, REG_HWCAP,  21)
126         FEAT_DEF(AES,       0x00000001, 0, REG_HWCAP2,  0)
127         FEAT_DEF(PMULL,     0x00000001, 0, REG_HWCAP2,  1)
128         FEAT_DEF(SHA1,      0x00000001, 0, REG_HWCAP2,  2)
129         FEAT_DEF(SHA2,      0x00000001, 0, REG_HWCAP2,  3)
130         FEAT_DEF(CRC32,     0x00000001, 0, REG_HWCAP2,  4)
131         FEAT_DEF(V7L,       0x00000001, 0, REG_PLATFORM, 0)
132 };
133
134 /*
135  * Read AUXV software register and get cpu features for ARM
136  */
137 static inline void
138 rte_cpu_get_features(__attribute__((unused)) uint32_t leaf,
139         __attribute__((unused)) uint32_t subleaf, cpuid_registers_t out)
140 {
141         int auxv_fd;
142         Elf32_auxv_t auxv;
143
144         auxv_fd = open("/proc/self/auxv", O_RDONLY);
145         assert(auxv_fd);
146         while (read(auxv_fd, &auxv,
147                 sizeof(Elf32_auxv_t)) == sizeof(Elf32_auxv_t)) {
148                 if (auxv.a_type == AT_HWCAP)
149                         out[REG_HWCAP] = auxv.a_un.a_val;
150                 else if (auxv.a_type == AT_HWCAP2)
151                         out[REG_HWCAP2] = auxv.a_un.a_val;
152                 else if (auxv.a_type == AT_PLATFORM) {
153                         if (!strcmp((const char *)auxv.a_un.a_val, "v7l"))
154                                 out[REG_PLATFORM] = 0x0001;
155                 }
156         }
157 }
158
159 /*
160  * Checks if a particular flag is available on current machine.
161  */
162 static inline int
163 rte_cpu_get_flag_enabled(enum rte_cpu_flag_t feature)
164 {
165         const struct feature_entry *feat;
166         cpuid_registers_t regs = {0};
167
168         if (feature >= RTE_CPUFLAG_NUMFLAGS)
169                 /* Flag does not match anything in the feature tables */
170                 return -ENOENT;
171
172         feat = &cpu_feature_table[feature];
173
174         if (!feat->leaf)
175                 /* This entry in the table wasn't filled out! */
176                 return -EFAULT;
177
178         /* get the cpuid leaf containing the desired feature */
179         rte_cpu_get_features(feat->leaf, feat->subleaf, regs);
180
181         /* check if the feature is enabled */
182         return (regs[feat->reg] >> feat->bit) & 1;
183 }
184
185 #ifdef __cplusplus
186 }
187 #endif
188
189 #endif /* _RTE_CPUFLAGS_ARM32_H_ */