1 #include <stdbool.h>
2 #include <stdint.h>
3 #include <stddef.h>
4
5 #include <x86/cpuid.h>
6 #include <cpuinfo.h>
7
8
9 #if CPUINFO_ARCH_X86
10 #ifdef _MSC_VER
11 #pragma pack(push, 2)
12 #endif
13 struct fxsave_region {
14 uint16_t fpu_control_word;
15 uint16_t fpu_status_word;
16 uint16_t fpu_tag_word;
17 uint16_t fpu_opcode;
18 uint32_t fpu_instruction_pointer_offset;
19 uint32_t fpu_instruction_pointer_selector;
20 uint32_t fpu_operand_pointer_offset;
21 uint32_t fpu_operand_pointer_selector;
22 uint32_t mxcsr_state;
23 uint32_t mxcsr_mask;
24 uint64_t fpu_registers[8 * 2];
25 uint64_t xmm_registers[8 * 2];
26 uint64_t padding[28];
27 }
28 #ifndef _MSC_VER
29 __attribute__((__aligned__(16), __packed__))
30 #endif
31 ; /* end of fxsave_region structure */
32 #ifdef _MSC_VER
33 #pragma pack(pop, 2)
34 #endif
35 #endif
36
37
cpuinfo_x86_detect_isa(const struct cpuid_regs basic_info,const struct cpuid_regs extended_info,uint32_t max_base_index,uint32_t max_extended_index,enum cpuinfo_vendor vendor,enum cpuinfo_uarch uarch)38 struct cpuinfo_x86_isa cpuinfo_x86_detect_isa(
39 const struct cpuid_regs basic_info, const struct cpuid_regs extended_info,
40 uint32_t max_base_index, uint32_t max_extended_index,
41 enum cpuinfo_vendor vendor, enum cpuinfo_uarch uarch)
42 {
43 struct cpuinfo_x86_isa isa = { 0 };
44
45 const struct cpuid_regs structured_feature_info0 =
46 (max_base_index >= 7) ? cpuidex(7, 0) : (struct cpuid_regs) { 0, 0, 0, 0};
47 const struct cpuid_regs structured_feature_info1 =
48 (max_base_index >= 7) ? cpuidex(7, 1) : (struct cpuid_regs) { 0, 0, 0, 0};
49
50 const uint32_t processor_capacity_info_index = UINT32_C(0x80000008);
51 const struct cpuid_regs processor_capacity_info =
52 (max_extended_index >= processor_capacity_info_index) ?
53 cpuid(processor_capacity_info_index) : (struct cpuid_regs) { 0, 0, 0, 0 };
54
55 bool avx_regs = false, avx512_regs = false, mpx_regs = false;
56 /*
57 * OSXSAVE: Operating system enabled XSAVE instructions for application use:
58 * - Intel, AMD: ecx[bit 26] in basic info = XSAVE/XRSTOR instructions supported by a chip.
59 * - Intel, AMD: ecx[bit 27] in basic info = XSAVE/XRSTOR instructions enabled by OS.
60 */
61 const uint32_t osxsave_mask = UINT32_C(0x0C000000);
62 if ((basic_info.ecx & osxsave_mask) == osxsave_mask) {
63 uint64_t xcr0_valid_bits = 0;
64 if (max_base_index >= 0xD) {
65 const struct cpuid_regs regs = cpuidex(0xD, 0);
66 xcr0_valid_bits = ((uint64_t) regs.edx << 32) | regs.eax;
67 }
68
69 const uint64_t xfeature_enabled_mask = xgetbv(0);
70
71 /*
72 * AVX registers:
73 * - Intel, AMD: XFEATURE_ENABLED_MASK[bit 1] for low 128 bits of ymm registers
74 * - Intel, AMD: XFEATURE_ENABLED_MASK[bit 2] for high 128 bits of ymm registers
75 */
76 const uint64_t avx_regs_mask = UINT64_C(0x0000000000000006);
77 if ((xcr0_valid_bits & avx_regs_mask) == avx_regs_mask) {
78 avx_regs = (xfeature_enabled_mask & avx_regs_mask) == avx_regs_mask;
79 }
80
81 /*
82 * AVX512 registers:
83 * - Intel, AMD: XFEATURE_ENABLED_MASK[bit 1] for low 128 bits of zmm registers
84 * - Intel, AMD: XFEATURE_ENABLED_MASK[bit 2] for bits 128-255 of zmm registers
85 * - Intel: XFEATURE_ENABLED_MASK[bit 5] for 8 64-bit OpMask registers (k0-k7)
86 * - Intel: XFEATURE_ENABLED_MASK[bit 6] for the high 256 bits of the zmm registers zmm0-zmm15
87 * - Intel: XFEATURE_ENABLED_MASK[bit 7] for the 512-bit zmm registers zmm16-zmm31
88 */
89 const uint64_t avx512_regs_mask = UINT64_C(0x00000000000000E6);
90 if ((xcr0_valid_bits & avx512_regs_mask) == avx512_regs_mask) {
91 avx512_regs = (xfeature_enabled_mask & avx512_regs_mask) == avx512_regs_mask;
92 }
93
94 /*
95 * MPX registers:
96 * - Intel: XFEATURE_ENABLED_MASK[bit 3] for BNDREGS
97 * - Intel: XFEATURE_ENABLED_MASK[bit 4] for BNDCSR
98 */
99 const uint64_t mpx_regs_mask = UINT64_C(0x0000000000000018);
100 if ((xcr0_valid_bits & mpx_regs_mask) == mpx_regs_mask) {
101 mpx_regs = (xfeature_enabled_mask & mpx_regs_mask) == mpx_regs_mask;
102 }
103 }
104
105 #if CPUINFO_ARCH_X86
106 /*
107 * RDTSC instruction:
108 * - Intel, AMD: edx[bit 4] in basic info.
109 * - AMD: edx[bit 4] in extended info (reserved bit on Intel CPUs).
110 */
111 isa.rdtsc = !!((basic_info.edx | extended_info.edx) & UINT32_C(0x00000010));
112 #endif
113
114 /*
115 * SYSENTER/SYSEXIT instructions:
116 * - Intel, AMD: edx[bit 11] in basic info.
117 */
118 isa.sysenter = !!(basic_info.edx & UINT32_C(0x00000800));
119
120 #if CPUINFO_ARCH_X86
121 /*
122 * SYSCALL/SYSRET instructions:
123 * - Intel, AMD: edx[bit 11] in extended info.
124 */
125 isa.syscall = !!(extended_info.edx & UINT32_C(0x00000800));
126 #endif
127
128 /*
129 * RDMSR/WRMSR instructions:
130 * - Intel, AMD: edx[bit 5] in basic info.
131 * - AMD: edx[bit 5] in extended info (reserved bit on Intel CPUs).
132 */
133 isa.msr = !!((basic_info.edx | extended_info.edx) & UINT32_C(0x00000020));
134
135 /*
136 * CLZERO instruction:
137 * - AMD: ebx[bit 0] in processor capacity info (reserved bit on Intel CPUs).
138 */
139 isa.clzero = !!(processor_capacity_info.ebx & UINT32_C(0x00000001));
140
141 /*
142 * CLFLUSH instruction:
143 * - Intel, AMD: edx[bit 19] in basic info.
144 */
145 isa.clflush = !!(basic_info.edx & UINT32_C(0x00080000));
146
147 /*
148 * CLFLUSHOPT instruction:
149 * - Intel: ebx[bit 23] in structured feature info (ecx = 0).
150 */
151 isa.clflushopt = !!(structured_feature_info0.ebx & UINT32_C(0x00800000));
152
153 /*
154 * MWAIT/MONITOR instructions:
155 * - Intel, AMD: ecx[bit 3] in basic info.
156 */
157 isa.mwait = !!(basic_info.ecx & UINT32_C(0x00000008));
158
159 /*
160 * MWAITX/MONITORX instructions:
161 * - AMD: ecx[bit 29] in extended info.
162 */
163 isa.mwaitx = !!(extended_info.ecx & UINT32_C(0x20000000));
164
165 /*
166 * FXSAVE/FXRSTOR instructions:
167 * - Intel, AMD: edx[bit 24] in basic info.
168 * - AMD: edx[bit 24] in extended info (zero bit on Intel CPUs, EMMX bit on Cyrix CPUs).
169 */
170 switch (vendor) {
171 #if CPUINFO_ARCH_X86
172 case cpuinfo_vendor_cyrix:
173 case cpuinfo_vendor_nsc:
174 isa.emmx = !!(extended_info.edx & UINT32_C(0x01000000));
175 break;
176 #endif
177 default:
178 isa.fxsave = !!((basic_info.edx | extended_info.edx) & UINT32_C(0x01000000));
179 break;
180 }
181
182 /*
183 * XSAVE/XRSTOR instructions:
184 * - Intel, AMD: ecx[bit 26] in basic info.
185 */
186 isa.xsave = !!(basic_info.ecx & UINT32_C(0x04000000));
187
188 #if CPUINFO_ARCH_X86
189 /*
190 * x87 FPU instructions:
191 * - Intel, AMD: edx[bit 0] in basic info.
192 * - AMD: edx[bit 0] in extended info (reserved bit on Intel CPUs).
193 */
194 isa.fpu = !!((basic_info.edx | extended_info.edx) & UINT32_C(0x00000001));
195
196 /*
197 * MMX instructions:
198 * - Intel, AMD: edx[bit 23] in basic info.
199 * - AMD: edx[bit 23] in extended info (zero bit on Intel CPUs).
200 */
201 isa.mmx = !!((basic_info.edx | extended_info.edx) & UINT32_C(0x00800000));
202
203 /*
204 * MMX+/Integer SSE instructions:
205 * - Intel, AMD: edx[bit 25] in basic info (SSE feature flag).
206 * - Pre-SSE AMD: edx[bit 22] in extended info (zero bit on Intel CPUs).
207 */
208 isa.mmx_plus = !!((basic_info.edx & UINT32_C(0x02000000)) | (extended_info.edx & UINT32_C(0x00400000)));
209 #endif
210
211 /*
212 * 3dnow! instructions:
213 * - AMD: edx[bit 31] of extended info (zero bit on Intel CPUs).
214 */
215 isa.three_d_now = !!(extended_info.edx & UINT32_C(0x80000000));
216
217 /*
218 * 3dnow!+ instructions:
219 * - AMD: edx[bit 30] of extended info (zero bit on Intel CPUs).
220 */
221 isa.three_d_now_plus = !!(extended_info.edx & UINT32_C(0x40000000));
222
223 #if CPUINFO_ARCH_X86
224 /*
225 * 3dnow! Geode instructions:
226 * - No CPUID bit, detect as Geode microarchitecture + 3dnow!+ support
227 */
228 isa.three_d_now_geode = isa.three_d_now_plus && (uarch == cpuinfo_uarch_geode);
229 #endif
230
231 /*
232 * PREFETCH instruction:
233 * - AMD: ecx[bit 8] of extended info (one of 3dnow! prefetch instructions).
234 * On Intel this bit indicates PREFETCHW, but not PREFETCH support.
235 * - AMD: edx[bit 31] of extended info (implied by 3dnow! support). Reserved bit on Intel CPUs.
236 * - AMD: edx[bit 30] of extended info (implied by 3dnow!+ support). Reserved bit on Intel CPUs.
237 * - AMD: edx[bit 29] of extended info (x86-64 support). Does not imply PREFETCH support on non-AMD CPUs!!!
238 */
239 switch (vendor) {
240 case cpuinfo_vendor_intel:
241 /*
242 * Instruction is not documented in the manual,
243 * and the 3dnow! prefetch CPUID bit indicates PREFETCHW instruction.
244 */
245 break;
246 case cpuinfo_vendor_amd:
247 isa.prefetch = !!((extended_info.ecx & UINT32_C(0x00000100)) | (extended_info.edx & UINT32_C(0xE0000000)));
248 break;
249 default:
250 /*
251 * Conservatively assume, that 3dnow!/3dnow!+ support implies PREFETCH support, but
252 * 3dnow! prefetch CPUID bit follows Intel spec (PREFETCHW, but not PREFETCH).
253 */
254 isa.prefetch = !!(extended_info.edx & UINT32_C(0xC0000000));
255 break;
256 }
257
258 /*
259 * PREFETCHW instruction:
260 * - AMD: ecx[bit 8] of extended info (one of 3dnow! prefetch instructions).
261 * - Intel: ecx[bit 8] of extended info (PREFETCHW instruction only).
262 * - AMD: edx[bit 31] of extended info (implied by 3dnow! support). Reserved bit on Intel CPUs.
263 * - AMD: edx[bit 30] of extended info (implied by 3dnow!+ support). Reserved bit on Intel CPUs.
264 * - AMD: edx[bit 29] of extended info (x86-64 support). Does not imply PREFETCHW support on non-AMD CPUs!!!
265 */
266 switch (vendor) {
267 case cpuinfo_vendor_amd:
268 isa.prefetchw = !!((extended_info.ecx & UINT32_C(0x00000100)) | (extended_info.edx & UINT32_C(0xE0000000)));
269 break;
270 default:
271 /* Assume, that 3dnow!/3dnow!+ support implies PREFETCHW support, not implications from x86-64 support */
272 isa.prefetchw = !!((extended_info.ecx & UINT32_C(0x00000100)) | (extended_info.edx & UINT32_C(0xC0000000)));
273 break;
274 }
275
276 /*
277 * PREFETCHWT1 instruction:
278 * - Intel: ecx[bit 0] of structured feature info (ecx = 0). Reserved bit on AMD.
279 */
280 isa.prefetchwt1 = !!(structured_feature_info0.ecx & UINT32_C(0x00000001));
281
282 #if CPUINFO_ARCH_X86
283 /*
284 * SSE instructions:
285 * - Intel, AMD: edx[bit 25] in basic info.
286 */
287 isa.sse = !!(basic_info.edx & UINT32_C(0x02000000));
288
289 /*
290 * SSE2 instructions:
291 * - Intel, AMD: edx[bit 26] in basic info.
292 */
293 isa.sse2 = !!(basic_info.edx & UINT32_C(0x04000000));
294 #endif
295
296 /*
297 * SSE3 instructions:
298 * - Intel, AMD: ecx[bit 0] in basic info.
299 */
300 isa.sse3 = !!(basic_info.ecx & UINT32_C(0x00000001));
301
302 #if CPUINFO_ARCH_X86
303 /*
304 * CPUs with x86-64 or SSE3 always support DAZ (denormals-as-zero) mode.
305 * Only early Pentium 4 models may not support it.
306 */
307 if (isa.sse3) {
308 isa.daz = true;
309 } else {
310 /* Detect DAZ support from masked MXCSR bits */
311 if (isa.sse && isa.fxsave) {
312 struct fxsave_region region = { 0 };
313 #ifdef _MSC_VER
314 _fxsave(®ion);
315 #else
316 __asm__ __volatile__ ("fxsave %[region];" : [region] "+m" (region));
317 #endif
318
319 /*
320 * Denormals-as-zero (DAZ) flag:
321 * - Intel, AMD: MXCSR[bit 6]
322 */
323 isa.daz = !!(region.mxcsr_mask & UINT32_C(0x00000040));
324 }
325 }
326 #endif
327
328 /*
329 * SSSE3 instructions:
330 * - Intel, AMD: ecx[bit 9] in basic info.
331 */
332 isa.ssse3 = !!(basic_info.ecx & UINT32_C(0x0000200));
333
334
335 /*
336 * SSE4.1 instructions:
337 * - Intel, AMD: ecx[bit 19] in basic info.
338 */
339 isa.sse4_1 = !!(basic_info.ecx & UINT32_C(0x00080000));
340
341 /*
342 * SSE4.2 instructions:
343 * - Intel: ecx[bit 20] in basic info (reserved bit on AMD CPUs).
344 */
345 isa.sse4_2 = !!(basic_info.ecx & UINT32_C(0x00100000));
346
347 /*
348 * SSE4A instructions:
349 * - AMD: ecx[bit 6] in extended info (reserved bit on Intel CPUs).
350 */
351 isa.sse4a = !!(extended_info.ecx & UINT32_C(0x00000040));
352
353 /*
354 * Misaligned memory operands in SSE instructions:
355 * - AMD: ecx[bit 7] in extended info (reserved bit on Intel CPUs).
356 */
357 isa.misaligned_sse = !!(extended_info.ecx & UINT32_C(0x00000080));
358
359 /*
360 * AVX instructions:
361 * - Intel, AMD: ecx[bit 28] in basic info.
362 */
363 isa.avx = avx_regs && !!(basic_info.ecx & UINT32_C(0x10000000));
364
365 /*
366 * FMA3 instructions:
367 * - Intel: ecx[bit 12] in basic info (reserved bit on AMD CPUs).
368 */
369 isa.fma3 = avx_regs && !!(basic_info.ecx & UINT32_C(0x00001000));
370
371 /*
372 * FMA4 instructions:
373 * - AMD: ecx[bit 16] in extended info (reserved bit on Intel CPUs).
374 */
375 isa.fma4 = avx_regs && !!(extended_info.ecx & UINT32_C(0x00010000));
376
377 /*
378 * XOP instructions:
379 * - AMD: ecx[bit 11] in extended info (reserved bit on Intel CPUs).
380 */
381 isa.xop = avx_regs && !!(extended_info.ecx & UINT32_C(0x00000800));
382
383 /*
384 * F16C instructions:
385 * - Intel, AMD: ecx[bit 29] in basic info.
386 */
387 isa.f16c = avx_regs && !!(basic_info.ecx & UINT32_C(0x20000000));
388
389 /*
390 * AVX2 instructions:
391 * - Intel: ebx[bit 5] in structured feature info (ecx = 0).
392 */
393 isa.avx2 = avx_regs && !!(structured_feature_info0.ebx & UINT32_C(0x00000020));
394
395 /*
396 * AVX512F instructions:
397 * - Intel: ebx[bit 16] in structured feature info (ecx = 0).
398 */
399 isa.avx512f = avx512_regs && !!(structured_feature_info0.ebx & UINT32_C(0x00010000));
400
401 /*
402 * AVX512PF instructions:
403 * - Intel: ebx[bit 26] in structured feature info (ecx = 0).
404 */
405 isa.avx512pf = avx512_regs && !!(structured_feature_info0.ebx & UINT32_C(0x04000000));
406
407 /*
408 * AVX512ER instructions:
409 * - Intel: ebx[bit 27] in structured feature info (ecx = 0).
410 */
411 isa.avx512er = avx512_regs && !!(structured_feature_info0.ebx & UINT32_C(0x08000000));
412
413 /*
414 * AVX512CD instructions:
415 * - Intel: ebx[bit 28] in structured feature info (ecx = 0).
416 */
417 isa.avx512cd = avx512_regs && !!(structured_feature_info0.ebx & UINT32_C(0x10000000));
418
419 /*
420 * AVX512DQ instructions:
421 * - Intel: ebx[bit 17] in structured feature info (ecx = 0).
422 */
423 isa.avx512dq = avx512_regs && !!(structured_feature_info0.ebx & UINT32_C(0x00020000));
424
425 /*
426 * AVX512BW instructions:
427 * - Intel: ebx[bit 30] in structured feature info (ecx = 0).
428 */
429 isa.avx512bw = avx512_regs && !!(structured_feature_info0.ebx & UINT32_C(0x40000000));
430
431 /*
432 * AVX512VL instructions:
433 * - Intel: ebx[bit 31] in structured feature info (ecx = 0).
434 */
435 isa.avx512vl = avx512_regs && !!(structured_feature_info0.ebx & UINT32_C(0x80000000));
436
437 /*
438 * AVX512IFMA instructions:
439 * - Intel: ebx[bit 21] in structured feature info (ecx = 0).
440 */
441 isa.avx512ifma = avx512_regs && !!(structured_feature_info0.ebx & UINT32_C(0x00200000));
442
443 /*
444 * AVX512VBMI instructions:
445 * - Intel: ecx[bit 1] in structured feature info (ecx = 0).
446 */
447 isa.avx512vbmi = avx512_regs && !!(structured_feature_info0.ecx & UINT32_C(0x00000002));
448
449 /*
450 * AVX512VBMI2 instructions:
451 * - Intel: ecx[bit 6] in structured feature info (ecx = 0).
452 */
453 isa.avx512vbmi2 = avx512_regs && !!(structured_feature_info0.ecx & UINT32_C(0x00000040));
454
455 /*
456 * AVX512BITALG instructions:
457 * - Intel: ecx[bit 12] in structured feature info (ecx = 0).
458 */
459 isa.avx512bitalg = avx512_regs && !!(structured_feature_info0.ecx & UINT32_C(0x00001000));
460
461 /*
462 * AVX512VPOPCNTDQ instructions:
463 * - Intel: ecx[bit 14] in structured feature info (ecx = 0).
464 */
465 isa.avx512vpopcntdq = avx512_regs && !!(structured_feature_info0.ecx & UINT32_C(0x00004000));
466
467 /*
468 * AVX512VNNI instructions:
469 * - Intel: ecx[bit 11] in structured feature info (ecx = 0).
470 */
471 isa.avx512vnni = avx512_regs && !!(structured_feature_info0.ecx & UINT32_C(0x00000800));
472
473 /*
474 * AVX512_4VNNIW instructions:
475 * - Intel: edx[bit 2] in structured feature info (ecx = 0).
476 */
477 isa.avx512_4vnniw = avx512_regs && !!(structured_feature_info0.edx & UINT32_C(0x00000004));
478
479 /*
480 * AVX512_4FMAPS instructions:
481 * - Intel: edx[bit 3] in structured feature info (ecx = 0).
482 */
483 isa.avx512_4fmaps = avx512_regs && !!(structured_feature_info0.edx & UINT32_C(0x00000008));
484
485 /*
486 * AVX512_VP2INTERSECT instructions:
487 * - Intel: edx[bit 8] in structured feature info (ecx = 0).
488 */
489 isa.avx512vp2intersect = avx512_regs && !!(structured_feature_info0.edx & UINT32_C(0x00000100));
490
491 /*
492 * AVX512_BF16 instructions:
493 * - Intel: eax[bit 5] in structured feature info (ecx = 1).
494 */
495 isa.avx512bf16 = avx512_regs && !!(structured_feature_info1.eax & UINT32_C(0x00000020));
496
497 /*
498 * HLE instructions:
499 * - Intel: ebx[bit 4] in structured feature info (ecx = 0).
500 */
501 isa.hle = !!(structured_feature_info0.ebx & UINT32_C(0x00000010));
502
503 /*
504 * RTM instructions:
505 * - Intel: ebx[bit 11] in structured feature info (ecx = 0).
506 */
507 isa.rtm = !!(structured_feature_info0.ebx & UINT32_C(0x00000800));
508
509 /*
510 * XTEST instruction:
511 * - Intel: either HLE or RTM is supported
512 */
513 isa.xtest = isa.hle || isa.rtm;
514
515 /*
516 * MPX registers and instructions:
517 * - Intel: ebx[bit 14] in structured feature info (ecx = 0).
518 */
519 isa.mpx = mpx_regs && !!(structured_feature_info0.ebx & UINT32_C(0x00004000));
520
521 #if CPUINFO_ARCH_X86
522 /*
523 * CMOV instructions:
524 * - Intel, AMD: edx[bit 15] in basic info.
525 * - AMD: edx[bit 15] in extended info (zero bit on Intel CPUs).
526 */
527 isa.cmov = !!((basic_info.edx | extended_info.edx) & UINT32_C(0x00008000));
528
529 /*
530 * CMPXCHG8B instruction:
531 * - Intel, AMD: edx[bit 8] in basic info.
532 * - AMD: edx[bit 8] in extended info (reserved bit on Intel CPUs).
533 */
534 isa.cmpxchg8b = !!((basic_info.edx | extended_info.edx) & UINT32_C(0x00000100));
535 #endif
536
537 /*
538 * CMPXCHG16B instruction:
539 * - Intel, AMD: ecx[bit 13] in basic info.
540 */
541 isa.cmpxchg16b = !!(basic_info.ecx & UINT32_C(0x00002000));
542
543 /*
544 * CLWB instruction:
545 * - Intel: ebx[bit 24] in structured feature info (ecx = 0).
546 */
547 isa.clwb = !!(structured_feature_info0.ebx & UINT32_C(0x01000000));
548
549 /*
550 * MOVBE instruction:
551 * - Intel: ecx[bit 22] in basic info.
552 */
553 isa.movbe = !!(basic_info.ecx & UINT32_C(0x00400000));
554
555 #if CPUINFO_ARCH_X86_64
556 /*
557 * Some early x86-64 CPUs lack LAHF & SAHF instructions.
558 * A special CPU feature bit must be checked to ensure their availability:
559 * - Intel, AMD: ecx[bit 0] in extended info.
560 */
561 isa.lahf_sahf = !!(extended_info.ecx & UINT32_C(0x00000001));
562 #endif
563
564 /*
565 * RDFSBASE/RDGSBASE/WRFSBASE/WRGSBASE instructions.
566 * - Intel: ebx[bit 0] in structured feature info (ecx = 0).
567 */
568 isa.fs_gs_base = !!(structured_feature_info0.ebx & UINT32_C(0x00000001));
569
570 /*
571 * LZCNT instruction:
572 * - Intel, AMD: ecx[bit 5] in extended info.
573 */
574 isa.lzcnt = !!(extended_info.ecx & UINT32_C(0x00000020));
575
576 /*
577 * POPCNT instruction:
578 * - Intel, AMD: ecx[bit 23] in basic info.
579 */
580 isa.popcnt = !!(basic_info.ecx & UINT32_C(0x00800000));
581
582 /*
583 * TBM instructions:
584 * - AMD: ecx[bit 21] in extended info (reserved bit on Intel CPUs).
585 */
586 isa.tbm = !!(extended_info.ecx & UINT32_C(0x00200000));
587
588 /*
589 * BMI instructions:
590 * - Intel, AMD: ebx[bit 3] in structured feature info (ecx = 0).
591 */
592 isa.bmi = !!(structured_feature_info0.ebx & UINT32_C(0x00000008));
593
594 /*
595 * BMI2 instructions:
596 * - Intel: ebx[bit 8] in structured feature info (ecx = 0).
597 */
598 isa.bmi2 = !!(structured_feature_info0.ebx & UINT32_C(0x00000100));
599
600 /*
601 * ADCX/ADOX instructions:
602 * - Intel: ebx[bit 19] in structured feature info (ecx = 0).
603 */
604 isa.adx = !!(structured_feature_info0.ebx & UINT32_C(0x00080000));
605
606 /*
607 * AES instructions:
608 * - Intel: ecx[bit 25] in basic info (reserved bit on AMD CPUs).
609 */
610 isa.aes = !!(basic_info.ecx & UINT32_C(0x02000000));
611
612 /*
613 * VAES instructions:
614 * - Intel: ecx[bit 9] in structured feature info (ecx = 0).
615 */
616 isa.vaes = !!(structured_feature_info0.ecx & UINT32_C(0x00000200));
617
618 /*
619 * PCLMULQDQ instruction:
620 * - Intel: ecx[bit 1] in basic info (reserved bit on AMD CPUs).
621 */
622 isa.pclmulqdq = !!(basic_info.ecx & UINT32_C(0x00000002));
623
624 /*
625 * VPCLMULQDQ instruction:
626 * - Intel: ecx[bit 10] in structured feature info (ecx = 0).
627 */
628 isa.vpclmulqdq = !!(structured_feature_info0.ecx & UINT32_C(0x00000400));
629
630 /*
631 * GFNI instructions:
632 * - Intel: ecx[bit 8] in structured feature info (ecx = 0).
633 */
634 isa.gfni = !!(structured_feature_info0.ecx & UINT32_C(0x00000100));
635
636 /*
637 * RDRAND instruction:
638 * - Intel: ecx[bit 30] in basic info (reserved bit on AMD CPUs).
639 */
640 isa.rdrand = !!(basic_info.ecx & UINT32_C(0x40000000));
641
642 /*
643 * RDSEED instruction:
644 * - Intel: ebx[bit 18] in structured feature info (ecx = 0).
645 */
646 isa.rdseed = !!(structured_feature_info0.ebx & UINT32_C(0x00040000));
647
648 /*
649 * SHA instructions:
650 * - Intel: ebx[bit 29] in structured feature info (ecx = 0).
651 */
652 isa.sha = !!(structured_feature_info0.ebx & UINT32_C(0x20000000));
653
654 if (vendor == cpuinfo_vendor_via) {
655 const struct cpuid_regs padlock_meta_info = cpuid(UINT32_C(0xC0000000));
656 const uint32_t max_padlock_index = padlock_meta_info.eax;
657 const uint32_t padlock_info_index = UINT32_C(0xC0000001);
658 if (max_padlock_index >= padlock_info_index) {
659 const struct cpuid_regs padlock_info = cpuid(padlock_info_index);
660
661 /*
662 * Padlock RNG extension:
663 * - VIA: edx[bit 2] in padlock info = RNG exists on chip flag.
664 * - VIA: edx[bit 3] in padlock info = RNG enabled by OS.
665 */
666 const uint32_t padlock_rng_mask = UINT32_C(0x0000000C);
667 isa.rng = (padlock_info.edx & padlock_rng_mask) == padlock_rng_mask;
668
669 /*
670 * Padlock ACE extension:
671 * - VIA: edx[bit 6] in padlock info = ACE exists on chip flag.
672 * - VIA: edx[bit 7] in padlock info = ACE enabled by OS.
673 */
674 const uint32_t padlock_ace_mask = UINT32_C(0x000000C0);
675 isa.ace = (padlock_info.edx & padlock_ace_mask) == padlock_ace_mask;
676
677 /*
678 * Padlock ACE 2 extension:
679 * - VIA: edx[bit 8] in padlock info = ACE2 exists on chip flag.
680 * - VIA: edx[bit 9] in padlock info = ACE 2 enabled by OS.
681 */
682 const uint32_t padlock_ace2_mask = UINT32_C(0x00000300);
683 isa.ace2 = (padlock_info.edx & padlock_ace2_mask) == padlock_ace2_mask;
684
685 /*
686 * Padlock PHE extension:
687 * - VIA: edx[bit 10] in padlock info = PHE exists on chip flag.
688 * - VIA: edx[bit 11] in padlock info = PHE enabled by OS.
689 */
690 const uint32_t padlock_phe_mask = UINT32_C(0x00000C00);
691 isa.phe = (padlock_info.edx & padlock_phe_mask) == padlock_phe_mask;
692
693 /*
694 * Padlock PMM extension:
695 * - VIA: edx[bit 12] in padlock info = PMM exists on chip flag.
696 * - VIA: edx[bit 13] in padlock info = PMM enabled by OS.
697 */
698 const uint32_t padlock_pmm_mask = UINT32_C(0x00003000);
699 isa.pmm = (padlock_info.edx & padlock_pmm_mask) == padlock_pmm_mask;
700 }
701 }
702
703 /*
704 * LWP instructions:
705 * - AMD: ecx[bit 15] in extended info (reserved bit on Intel CPUs).
706 */
707 isa.lwp = !!(extended_info.ecx & UINT32_C(0x00008000));
708
709 /*
710 * RDTSCP instruction:
711 * - Intel, AMD: edx[bit 27] in extended info.
712 */
713 isa.rdtscp = !!(extended_info.edx & UINT32_C(0x08000000));
714
715 /*
716 * RDPID instruction:
717 * - Intel: ecx[bit 22] in structured feature info (ecx = 0).
718 */
719 isa.rdpid = !!(structured_feature_info0.ecx & UINT32_C(0x00400000));
720
721 return isa;
722 }
723