eal/arm: add CPU flags for ARMv7
[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
45 #include "generic/rte_cpuflags.h"
46
47 #ifndef AT_HWCAP
48 #define AT_HWCAP 16
49 #endif
50
51 #ifndef AT_HWCAP2
52 #define AT_HWCAP2 26
53 #endif
54
55 /* software based registers */
56 enum cpu_register_t {
57         REG_HWCAP = 0,
58         REG_HWCAP2,
59 };
60
61 /**
62  * Enumeration of all CPU features supported
63  */
64 enum rte_cpu_flag_t {
65         RTE_CPUFLAG_SWP = 0,
66         RTE_CPUFLAG_HALF,
67         RTE_CPUFLAG_THUMB,
68         RTE_CPUFLAG_A26BIT,
69         RTE_CPUFLAG_FAST_MULT,
70         RTE_CPUFLAG_FPA,
71         RTE_CPUFLAG_VFP,
72         RTE_CPUFLAG_EDSP,
73         RTE_CPUFLAG_JAVA,
74         RTE_CPUFLAG_IWMMXT,
75         RTE_CPUFLAG_CRUNCH,
76         RTE_CPUFLAG_THUMBEE,
77         RTE_CPUFLAG_NEON,
78         RTE_CPUFLAG_VFPv3,
79         RTE_CPUFLAG_VFPv3D16,
80         RTE_CPUFLAG_TLS,
81         RTE_CPUFLAG_VFPv4,
82         RTE_CPUFLAG_IDIVA,
83         RTE_CPUFLAG_IDIVT,
84         RTE_CPUFLAG_VFPD32,
85         RTE_CPUFLAG_LPAE,
86         RTE_CPUFLAG_EVTSTRM,
87         RTE_CPUFLAG_AES,
88         RTE_CPUFLAG_PMULL,
89         RTE_CPUFLAG_SHA1,
90         RTE_CPUFLAG_SHA2,
91         RTE_CPUFLAG_CRC32,
92         /* The last item */
93         RTE_CPUFLAG_NUMFLAGS,/**< This should always be the last! */
94 };
95
96 static const struct feature_entry cpu_feature_table[] = {
97         FEAT_DEF(SWP,       0x00000001, 0, REG_HWCAP,  0)
98         FEAT_DEF(HALF,      0x00000001, 0, REG_HWCAP,  1)
99         FEAT_DEF(THUMB,     0x00000001, 0, REG_HWCAP,  2)
100         FEAT_DEF(A26BIT,    0x00000001, 0, REG_HWCAP,  3)
101         FEAT_DEF(FAST_MULT, 0x00000001, 0, REG_HWCAP,  4)
102         FEAT_DEF(FPA,       0x00000001, 0, REG_HWCAP,  5)
103         FEAT_DEF(VFP,       0x00000001, 0, REG_HWCAP,  6)
104         FEAT_DEF(EDSP,      0x00000001, 0, REG_HWCAP,  7)
105         FEAT_DEF(JAVA,      0x00000001, 0, REG_HWCAP,  8)
106         FEAT_DEF(IWMMXT,    0x00000001, 0, REG_HWCAP,  9)
107         FEAT_DEF(CRUNCH,    0x00000001, 0, REG_HWCAP,  10)
108         FEAT_DEF(THUMBEE,   0x00000001, 0, REG_HWCAP,  11)
109         FEAT_DEF(NEON,      0x00000001, 0, REG_HWCAP,  12)
110         FEAT_DEF(VFPv3,     0x00000001, 0, REG_HWCAP,  13)
111         FEAT_DEF(VFPv3D16,  0x00000001, 0, REG_HWCAP,  14)
112         FEAT_DEF(TLS,       0x00000001, 0, REG_HWCAP,  15)
113         FEAT_DEF(VFPv4,     0x00000001, 0, REG_HWCAP,  16)
114         FEAT_DEF(IDIVA,     0x00000001, 0, REG_HWCAP,  17)
115         FEAT_DEF(IDIVT,     0x00000001, 0, REG_HWCAP,  18)
116         FEAT_DEF(VFPD32,    0x00000001, 0, REG_HWCAP,  19)
117         FEAT_DEF(LPAE,      0x00000001, 0, REG_HWCAP,  20)
118         FEAT_DEF(EVTSTRM,   0x00000001, 0, REG_HWCAP,  21)
119         FEAT_DEF(AES,       0x00000001, 0, REG_HWCAP2,  0)
120         FEAT_DEF(PMULL,     0x00000001, 0, REG_HWCAP2,  1)
121         FEAT_DEF(SHA1,      0x00000001, 0, REG_HWCAP2,  2)
122         FEAT_DEF(SHA2,      0x00000001, 0, REG_HWCAP2,  3)
123         FEAT_DEF(CRC32,     0x00000001, 0, REG_HWCAP2,  4)
124 };
125
126 /*
127  * Read AUXV software register and get cpu features for ARM
128  */
129 static inline void
130 rte_cpu_get_features(__attribute__((unused)) uint32_t leaf,
131         __attribute__((unused)) uint32_t subleaf, cpuid_registers_t out)
132 {
133         int auxv_fd;
134         Elf32_auxv_t auxv;
135
136         auxv_fd = open("/proc/self/auxv", O_RDONLY);
137         assert(auxv_fd);
138         while (read(auxv_fd, &auxv,
139                 sizeof(Elf32_auxv_t)) == sizeof(Elf32_auxv_t)) {
140                 if (auxv.a_type == AT_HWCAP)
141                         out[REG_HWCAP] = auxv.a_un.a_val;
142                 else if (auxv.a_type == AT_HWCAP2)
143                         out[REG_HWCAP2] = auxv.a_un.a_val;
144         }
145 }
146
147 /*
148  * Checks if a particular flag is available on current machine.
149  */
150 static inline int
151 rte_cpu_get_flag_enabled(enum rte_cpu_flag_t feature)
152 {
153         const struct feature_entry *feat;
154         cpuid_registers_t regs = {0};
155
156         if (feature >= RTE_CPUFLAG_NUMFLAGS)
157                 /* Flag does not match anything in the feature tables */
158                 return -ENOENT;
159
160         feat = &cpu_feature_table[feature];
161
162         if (!feat->leaf)
163                 /* This entry in the table wasn't filled out! */
164                 return -EFAULT;
165
166         /* get the cpuid leaf containing the desired feature */
167         rte_cpu_get_features(feat->leaf, feat->subleaf, regs);
168
169         /* check if the feature is enabled */
170         return (regs[feat->reg] >> feat->bit) & 1;
171 }
172
173 #ifdef __cplusplus
174 }
175 #endif
176
177 #endif /* _RTE_CPUFLAGS_ARM32_H_ */