xref: /dpdk/lib/eal/x86/rte_cpuflags.c (revision 4225db8dc0fa83c9ba1247ac5aec54ab7f3f8d94)
1 /* SPDX-License-Identifier: BSD-3-Clause
2  * Copyright(c) 2010-2015 Intel Corporation
3  */
4 
5 #include "rte_cpuflags.h"
6 
7 #include <stdio.h>
8 #include <errno.h>
9 #include <stdint.h>
10 #include <string.h>
11 #include <stdbool.h>
12 
13 #include "rte_cpuid.h"
14 #include "rte_atomic.h"
15 
16 /**
17  * Struct to hold a processor feature entry
18  */
19 struct feature_entry {
20 	uint32_t leaf;				/**< cpuid leaf */
21 	uint32_t subleaf;			/**< cpuid subleaf */
22 	uint32_t reg;				/**< cpuid register */
23 	uint32_t bit;				/**< cpuid register bit */
24 #define CPU_FLAG_NAME_MAX_LEN 64
25 	char name[CPU_FLAG_NAME_MAX_LEN];       /**< String for printing */
26 	bool has_value;
27 	bool value;
28 };
29 
30 #define FEAT_DEF(name, leaf, subleaf, reg, bit) \
31 	[RTE_CPUFLAG_##name] = {leaf, subleaf, reg, bit, #name },
32 
33 struct feature_entry rte_cpu_feature_table[] = {
34 	FEAT_DEF(SSE3, 0x00000001, 0, RTE_REG_ECX,  0)
35 	FEAT_DEF(PCLMULQDQ, 0x00000001, 0, RTE_REG_ECX,  1)
36 	FEAT_DEF(DTES64, 0x00000001, 0, RTE_REG_ECX,  2)
37 	FEAT_DEF(MONITOR, 0x00000001, 0, RTE_REG_ECX,  3)
38 	FEAT_DEF(DS_CPL, 0x00000001, 0, RTE_REG_ECX,  4)
39 	FEAT_DEF(VMX, 0x00000001, 0, RTE_REG_ECX,  5)
40 	FEAT_DEF(SMX, 0x00000001, 0, RTE_REG_ECX,  6)
41 	FEAT_DEF(EIST, 0x00000001, 0, RTE_REG_ECX,  7)
42 	FEAT_DEF(TM2, 0x00000001, 0, RTE_REG_ECX,  8)
43 	FEAT_DEF(SSSE3, 0x00000001, 0, RTE_REG_ECX,  9)
44 	FEAT_DEF(CNXT_ID, 0x00000001, 0, RTE_REG_ECX, 10)
45 	FEAT_DEF(FMA, 0x00000001, 0, RTE_REG_ECX, 12)
46 	FEAT_DEF(CMPXCHG16B, 0x00000001, 0, RTE_REG_ECX, 13)
47 	FEAT_DEF(XTPR, 0x00000001, 0, RTE_REG_ECX, 14)
48 	FEAT_DEF(PDCM, 0x00000001, 0, RTE_REG_ECX, 15)
49 	FEAT_DEF(PCID, 0x00000001, 0, RTE_REG_ECX, 17)
50 	FEAT_DEF(DCA, 0x00000001, 0, RTE_REG_ECX, 18)
51 	FEAT_DEF(SSE4_1, 0x00000001, 0, RTE_REG_ECX, 19)
52 	FEAT_DEF(SSE4_2, 0x00000001, 0, RTE_REG_ECX, 20)
53 	FEAT_DEF(X2APIC, 0x00000001, 0, RTE_REG_ECX, 21)
54 	FEAT_DEF(MOVBE, 0x00000001, 0, RTE_REG_ECX, 22)
55 	FEAT_DEF(POPCNT, 0x00000001, 0, RTE_REG_ECX, 23)
56 	FEAT_DEF(TSC_DEADLINE, 0x00000001, 0, RTE_REG_ECX, 24)
57 	FEAT_DEF(AES, 0x00000001, 0, RTE_REG_ECX, 25)
58 	FEAT_DEF(XSAVE, 0x00000001, 0, RTE_REG_ECX, 26)
59 	FEAT_DEF(OSXSAVE, 0x00000001, 0, RTE_REG_ECX, 27)
60 	FEAT_DEF(AVX, 0x00000001, 0, RTE_REG_ECX, 28)
61 	FEAT_DEF(F16C, 0x00000001, 0, RTE_REG_ECX, 29)
62 	FEAT_DEF(RDRAND, 0x00000001, 0, RTE_REG_ECX, 30)
63 	FEAT_DEF(HYPERVISOR, 0x00000001, 0, RTE_REG_ECX, 31)
64 
65 	FEAT_DEF(FPU, 0x00000001, 0, RTE_REG_EDX,  0)
66 	FEAT_DEF(VME, 0x00000001, 0, RTE_REG_EDX,  1)
67 	FEAT_DEF(DE, 0x00000001, 0, RTE_REG_EDX,  2)
68 	FEAT_DEF(PSE, 0x00000001, 0, RTE_REG_EDX,  3)
69 	FEAT_DEF(TSC, 0x00000001, 0, RTE_REG_EDX,  4)
70 	FEAT_DEF(MSR, 0x00000001, 0, RTE_REG_EDX,  5)
71 	FEAT_DEF(PAE, 0x00000001, 0, RTE_REG_EDX,  6)
72 	FEAT_DEF(MCE, 0x00000001, 0, RTE_REG_EDX,  7)
73 	FEAT_DEF(CX8, 0x00000001, 0, RTE_REG_EDX,  8)
74 	FEAT_DEF(APIC, 0x00000001, 0, RTE_REG_EDX,  9)
75 	FEAT_DEF(SEP, 0x00000001, 0, RTE_REG_EDX, 11)
76 	FEAT_DEF(MTRR, 0x00000001, 0, RTE_REG_EDX, 12)
77 	FEAT_DEF(PGE, 0x00000001, 0, RTE_REG_EDX, 13)
78 	FEAT_DEF(MCA, 0x00000001, 0, RTE_REG_EDX, 14)
79 	FEAT_DEF(CMOV, 0x00000001, 0, RTE_REG_EDX, 15)
80 	FEAT_DEF(PAT, 0x00000001, 0, RTE_REG_EDX, 16)
81 	FEAT_DEF(PSE36, 0x00000001, 0, RTE_REG_EDX, 17)
82 	FEAT_DEF(PSN, 0x00000001, 0, RTE_REG_EDX, 18)
83 	FEAT_DEF(CLFSH, 0x00000001, 0, RTE_REG_EDX, 19)
84 	FEAT_DEF(DS, 0x00000001, 0, RTE_REG_EDX, 21)
85 	FEAT_DEF(ACPI, 0x00000001, 0, RTE_REG_EDX, 22)
86 	FEAT_DEF(MMX, 0x00000001, 0, RTE_REG_EDX, 23)
87 	FEAT_DEF(FXSR, 0x00000001, 0, RTE_REG_EDX, 24)
88 	FEAT_DEF(SSE, 0x00000001, 0, RTE_REG_EDX, 25)
89 	FEAT_DEF(SSE2, 0x00000001, 0, RTE_REG_EDX, 26)
90 	FEAT_DEF(SS, 0x00000001, 0, RTE_REG_EDX, 27)
91 	FEAT_DEF(HTT, 0x00000001, 0, RTE_REG_EDX, 28)
92 	FEAT_DEF(TM, 0x00000001, 0, RTE_REG_EDX, 29)
93 	FEAT_DEF(PBE, 0x00000001, 0, RTE_REG_EDX, 31)
94 
95 	FEAT_DEF(DIGTEMP, 0x00000006, 0, RTE_REG_EAX,  0)
96 	FEAT_DEF(TRBOBST, 0x00000006, 0, RTE_REG_EAX,  1)
97 	FEAT_DEF(ARAT, 0x00000006, 0, RTE_REG_EAX,  2)
98 	FEAT_DEF(PLN, 0x00000006, 0, RTE_REG_EAX,  4)
99 	FEAT_DEF(ECMD, 0x00000006, 0, RTE_REG_EAX,  5)
100 	FEAT_DEF(PTM, 0x00000006, 0, RTE_REG_EAX,  6)
101 
102 	FEAT_DEF(MPERF_APERF_MSR, 0x00000006, 0, RTE_REG_ECX,  0)
103 	FEAT_DEF(ACNT2, 0x00000006, 0, RTE_REG_ECX,  1)
104 	FEAT_DEF(ENERGY_EFF, 0x00000006, 0, RTE_REG_ECX,  3)
105 
106 	FEAT_DEF(FSGSBASE, 0x00000007, 0, RTE_REG_EBX,  0)
107 	FEAT_DEF(BMI1, 0x00000007, 0, RTE_REG_EBX,  3)
108 	FEAT_DEF(HLE, 0x00000007, 0, RTE_REG_EBX,  4)
109 	FEAT_DEF(AVX2, 0x00000007, 0, RTE_REG_EBX,  5)
110 	FEAT_DEF(SMEP, 0x00000007, 0, RTE_REG_EBX,  7)
111 	FEAT_DEF(BMI2, 0x00000007, 0, RTE_REG_EBX,  8)
112 	FEAT_DEF(ERMS, 0x00000007, 0, RTE_REG_EBX,  9)
113 	FEAT_DEF(INVPCID, 0x00000007, 0, RTE_REG_EBX, 10)
114 	FEAT_DEF(RTM, 0x00000007, 0, RTE_REG_EBX, 11)
115 	FEAT_DEF(AVX512F, 0x00000007, 0, RTE_REG_EBX, 16)
116 	FEAT_DEF(AVX512DQ, 0x00000007, 0, RTE_REG_EBX, 17)
117 	FEAT_DEF(RDSEED, 0x00000007, 0, RTE_REG_EBX, 18)
118 	FEAT_DEF(AVX512IFMA, 0x00000007, 0, RTE_REG_EBX, 21)
119 	FEAT_DEF(AVX512CD, 0x00000007, 0, RTE_REG_EBX, 28)
120 	FEAT_DEF(AVX512BW, 0x00000007, 0, RTE_REG_EBX, 30)
121 	FEAT_DEF(AVX512VL, 0x00000007, 0, RTE_REG_EBX, 31)
122 
123 	FEAT_DEF(AVX512VBMI, 0x00000007, 0, RTE_REG_ECX,  1)
124 	FEAT_DEF(WAITPKG, 0x00000007, 0, RTE_REG_ECX,  5)
125 	FEAT_DEF(AVX512VBMI2, 0x00000007, 0, RTE_REG_ECX,  6)
126 	FEAT_DEF(GFNI, 0x00000007, 0, RTE_REG_ECX,  8)
127 	FEAT_DEF(VAES, 0x00000007, 0, RTE_REG_ECX,  9)
128 	FEAT_DEF(VPCLMULQDQ, 0x00000007, 0, RTE_REG_ECX, 10)
129 	FEAT_DEF(AVX512VNNI, 0x00000007, 0, RTE_REG_ECX, 11)
130 	FEAT_DEF(AVX512BITALG, 0x00000007, 0, RTE_REG_ECX, 12)
131 	FEAT_DEF(AVX512VPOPCNTDQ, 0x00000007, 0, RTE_REG_ECX, 14)
132 	FEAT_DEF(CLDEMOTE, 0x00000007, 0, RTE_REG_ECX, 25)
133 	FEAT_DEF(MOVDIRI, 0x00000007, 0, RTE_REG_ECX, 27)
134 	FEAT_DEF(MOVDIR64B, 0x00000007, 0, RTE_REG_ECX, 28)
135 
136 	FEAT_DEF(AVX512VP2INTERSECT, 0x00000007, 0, RTE_REG_EDX,  8)
137 
138 	FEAT_DEF(LAHF_SAHF, 0x80000001, 0, RTE_REG_ECX,  0)
139 	FEAT_DEF(LZCNT, 0x80000001, 0, RTE_REG_ECX,  4)
140 	FEAT_DEF(MONITORX, 0x80000001, 0, RTE_REG_ECX,  29)
141 
142 	FEAT_DEF(SYSCALL, 0x80000001, 0, RTE_REG_EDX, 11)
143 	FEAT_DEF(XD, 0x80000001, 0, RTE_REG_EDX, 20)
144 	FEAT_DEF(1GB_PG, 0x80000001, 0, RTE_REG_EDX, 26)
145 	FEAT_DEF(RDTSCP, 0x80000001, 0, RTE_REG_EDX, 27)
146 	FEAT_DEF(EM64T, 0x80000001, 0, RTE_REG_EDX, 29)
147 
148 	FEAT_DEF(INVTSC, 0x80000007, 0, RTE_REG_EDX,  8)
149 };
150 
151 int
152 rte_cpu_get_flag_enabled(enum rte_cpu_flag_t feature)
153 {
154 	struct feature_entry *feat;
155 	cpuid_registers_t regs;
156 	unsigned int maxleaf;
157 
158 	if ((unsigned int)feature >= RTE_DIM(rte_cpu_feature_table))
159 		/* Flag does not match anything in the feature tables */
160 		return -ENOENT;
161 
162 	feat = &rte_cpu_feature_table[feature];
163 	if (feat->has_value)
164 		return feat->value;
165 
166 	if (!feat->leaf)
167 		/* This entry in the table wasn't filled out! */
168 		return -EFAULT;
169 
170 	maxleaf = __get_cpuid_max(feat->leaf & 0x80000000, NULL);
171 
172 	if (maxleaf < feat->leaf) {
173 		feat->value = 0;
174 		goto out;
175 	}
176 
177 #ifdef RTE_TOOLCHAIN_MSVC
178 	__cpuidex(regs, feat->leaf, feat->subleaf);
179 #else
180 	__cpuid_count(feat->leaf, feat->subleaf,
181 			 regs[RTE_REG_EAX], regs[RTE_REG_EBX],
182 			 regs[RTE_REG_ECX], regs[RTE_REG_EDX]);
183 #endif
184 
185 	/* check if the feature is enabled */
186 	feat->value = (regs[feat->reg] >> feat->bit) & 1;
187 out:
188 	rte_compiler_barrier();
189 	feat->has_value = true;
190 	return feat->value;
191 }
192 
193 const char *
194 rte_cpu_get_flag_name(enum rte_cpu_flag_t feature)
195 {
196 	if ((unsigned int)feature >= RTE_DIM(rte_cpu_feature_table))
197 		return NULL;
198 	return rte_cpu_feature_table[feature].name;
199 }
200 
201 void
202 rte_cpu_get_intrinsics_support(struct rte_cpu_intrinsics *intrinsics)
203 {
204 	memset(intrinsics, 0, sizeof(*intrinsics));
205 
206 	if (rte_cpu_get_flag_enabled(RTE_CPUFLAG_WAITPKG)) {
207 		intrinsics->power_monitor = 1;
208 		intrinsics->power_pause = 1;
209 		if (rte_cpu_get_flag_enabled(RTE_CPUFLAG_RTM))
210 			intrinsics->power_monitor_multi = 1;
211 	} else if (rte_cpu_get_flag_enabled(RTE_CPUFLAG_MONITORX)) {
212 		intrinsics->power_monitor = 1;
213 	}
214 }
215