cpuid_x64.h
Go to the documentation of this file.
1 //
2 // Bareflank Hypervisor
3 //
4 // Copyright (C) 2015 Assured Information Security, Inc.
5 // Author: Rian Quinn <quinnr@ainfosec.com>
6 // Author: Brendan Kerrigan <kerriganb@ainfosec.com>
7 //
8 // This library is free software; you can redistribute it and/or
9 // modify it under the terms of the GNU Lesser General Public
10 // License as published by the Free Software Foundation; either
11 // version 2.1 of the License, or (at your option) any later version.
12 //
13 // This library is distributed in the hope that it will be useful,
14 // but WITHOUT ANY WARRANTY; without even the implied warranty of
15 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 // Lesser General Public License for more details.
17 //
18 // You should have received a copy of the GNU Lesser General Public
19 // License along with this library; if not, write to the Free Software
20 // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
21 
22 #ifndef CPUID_X64_H
23 #define CPUID_X64_H
24 
25 #include <debug.h>
26 #include <bitmanip.h>
27 
28 extern "C" uint32_t __cpuid_eax(uint32_t val) noexcept;
29 extern "C" uint32_t __cpuid_ebx(uint32_t val) noexcept;
30 extern "C" uint32_t __cpuid_ecx(uint32_t val) noexcept;
31 extern "C" uint32_t __cpuid_edx(uint32_t val) noexcept;
32 extern "C" void __cpuid(void *eax, void *ebx, void *ecx, void *edx) noexcept;
33 
34 // *INDENT-OFF*
35 
36 namespace x64
37 {
38 namespace cpuid
39 {
40  using field_type = uint32_t;
41  using value_type = uint32_t;
42 
43  template<class T1, class T2, class T3, class T4,
44  class = typename std::enable_if<std::is_integral<T1>::value>::type,
45  class = typename std::enable_if<std::is_integral<T2>::value>::type,
46  class = typename std::enable_if<std::is_integral<T3>::value>::type,
47  class = typename std::enable_if<std::is_integral<T4>::value>::type>
48  auto get(T1 eax, T2 ebx, T3 ecx, T4 edx) noexcept
49  {
50  __cpuid(&eax, &ebx, &ecx, &edx);
51  return std::make_tuple(eax, ebx, ecx, edx);
52  }
53 
54  namespace eax
55  {
56  template<class T, class = typename std::enable_if<std::is_integral<T>::value>::type>
57  auto get(T eax) noexcept { return __cpuid_eax(gsl::narrow_cast<uint32_t>(eax)); }
58  }
59 
60  namespace ebx
61  {
62  template<class T, class = typename std::enable_if<std::is_integral<T>::value>::type>
63  auto get(T ebx) noexcept { return __cpuid_ebx(gsl::narrow_cast<uint32_t>(ebx)); }
64  }
65 
66  namespace ecx
67  {
68  template<class T, class = typename std::enable_if<std::is_integral<T>::value>::type>
69  auto get(T ecx) noexcept { return __cpuid_ecx(gsl::narrow_cast<uint32_t>(ecx)); }
70  }
71 
72  namespace edx
73  {
74  template<class T, class = typename std::enable_if<std::is_integral<T>::value>::type>
75  auto get(T edx) noexcept { return __cpuid_edx(gsl::narrow_cast<uint32_t>(edx)); }
76  }
77 
78  namespace addr_size
79  {
80  constexpr const auto addr = 0x80000008U;
81  constexpr const auto name = "addr_size";
82 
83  namespace phys
84  {
85  constexpr const auto mask = 0x000000FFU;
86  constexpr const auto from = 0;
87  constexpr const auto name = "phys";
88 
89  inline auto get() noexcept
90  { return get_bits(__cpuid_eax(addr), mask) >> from; }
91  }
92 
93  namespace linear
94  {
95  constexpr const auto mask = 0x0000FF00U;
96  constexpr const auto from = 8;
97  constexpr const auto name = "linear";
98 
99  inline auto get() noexcept
100  { return get_bits(__cpuid_eax(addr), mask) >> from; }
101  }
102  }
103 
104  namespace feature_information
105  {
106  constexpr const auto addr = 0x00000001U;
107  constexpr const auto name = "feature_information";
108 
109  namespace ecx
110  {
111  namespace sse3
112  {
113  constexpr const auto mask = 0x00000001U;
114  constexpr const auto from = 0;
115  constexpr const auto name = "sse3";
116 
117  inline auto get() noexcept
118  { return get_bit(__cpuid_ecx(addr), from) != 0; }
119  }
120 
121  namespace pclmulqdq
122  {
123  constexpr const auto mask = 0x00000002U;
124  constexpr const auto from = 1;
125  constexpr const auto name = "pclmulqdq";
126 
127  inline auto get() noexcept
128  { return get_bit(__cpuid_ecx(addr), from) != 0; }
129  }
130 
131  namespace dtes64
132  {
133  constexpr const auto mask = 0x00000004U;
134  constexpr const auto from = 2;
135  constexpr const auto name = "dtes64";
136 
137  inline auto get() noexcept
138  { return get_bit(__cpuid_ecx(addr), from) != 0; }
139  }
140 
141  namespace monitor
142  {
143  constexpr const auto mask = 0x00000008U;
144  constexpr const auto from = 3;
145  constexpr const auto name = "monitor";
146 
147  inline auto get() noexcept
148  { return get_bit(__cpuid_ecx(addr), from) != 0; }
149  }
150 
151  namespace ds_cpl
152  {
153  constexpr const auto mask = 0x00000010U;
154  constexpr const auto from = 4;
155  constexpr const auto name = "ds_cpl";
156 
157  inline auto get() noexcept
158  { return get_bit(__cpuid_ecx(addr), from) != 0; }
159  }
160 
161  namespace vmx
162  {
163  constexpr const auto mask = 0x00000020U;
164  constexpr const auto from = 5;
165  constexpr const auto name = "vmx";
166 
167  inline auto get() noexcept
168  { return get_bit(__cpuid_ecx(addr), from) != 0; }
169  }
170 
171  namespace smx
172  {
173  constexpr const auto mask = 0x00000040U;
174  constexpr const auto from = 6;
175  constexpr const auto name = "smx";
176 
177  inline auto get() noexcept
178  { return get_bit(__cpuid_ecx(addr), from) != 0; }
179  }
180 
181  namespace eist
182  {
183  constexpr const auto mask = 0x00000080U;
184  constexpr const auto from = 7;
185  constexpr const auto name = "eist";
186 
187  inline auto get() noexcept
188  { return get_bit(__cpuid_ecx(addr), from) != 0; }
189  }
190 
191  namespace tm2
192  {
193  constexpr const auto mask = 0x00000100U;
194  constexpr const auto from = 8;
195  constexpr const auto name = "tm2";
196 
197  inline auto get() noexcept
198  { return get_bit(__cpuid_ecx(addr), from) != 0; }
199  }
200 
201  namespace ssse3
202  {
203  constexpr const auto mask = 0x00000200U;
204  constexpr const auto from = 9;
205  constexpr const auto name = "ssse3";
206 
207  inline auto get() noexcept
208  { return get_bit(__cpuid_ecx(addr), from) != 0; }
209  }
210 
211  namespace cnxt_id
212  {
213  constexpr const auto mask = 0x00000400U;
214  constexpr const auto from = 10;
215  constexpr const auto name = "cnxt_id";
216 
217  inline auto get() noexcept
218  { return get_bit(__cpuid_ecx(addr), from) != 0; }
219  }
220 
221  namespace sdbg
222  {
223  constexpr const auto mask = 0x00000800U;
224  constexpr const auto from = 11;
225  constexpr const auto name = "sdbg";
226 
227  inline auto get() noexcept
228  { return get_bit(__cpuid_ecx(addr), from) != 0; }
229  }
230 
231  namespace fma
232  {
233  constexpr const auto mask = 0x00001000U;
234  constexpr const auto from = 12;
235  constexpr const auto name = "fma";
236 
237  inline auto get() noexcept
238  { return get_bit(__cpuid_ecx(addr), from) != 0; }
239  }
240 
241  namespace cmpxchg16b
242  {
243  constexpr const auto mask = 0x00002000U;
244  constexpr const auto from = 13;
245  constexpr const auto name = "cmpxchg16b";
246 
247  inline auto get() noexcept
248  { return get_bit(__cpuid_ecx(addr), from) != 0; }
249  }
250 
251  namespace xtpr_update_control
252  {
253  constexpr const auto mask = 0x00004000U;
254  constexpr const auto from = 14;
255  constexpr const auto name = "xtpr_update_control";
256 
257  inline auto get() noexcept
258  { return get_bit(__cpuid_ecx(addr), from) != 0; }
259  }
260 
261  namespace pdcm
262  {
263  constexpr const auto mask = 0x00008000U;
264  constexpr const auto from = 15;
265  constexpr const auto name = "pdcm";
266 
267  inline auto get() noexcept
268  { return get_bit(__cpuid_ecx(addr), from) != 0; }
269  }
270 
271  namespace pcid
272  {
273  constexpr const auto mask = 0x00020000U;
274  constexpr const auto from = 17;
275  constexpr const auto name = "pcid";
276 
277  inline auto get() noexcept
278  { return get_bit(__cpuid_ecx(addr), from) != 0; }
279  }
280 
281  namespace dca
282  {
283  constexpr const auto mask = 0x00040000U;
284  constexpr const auto from = 18;
285  constexpr const auto name = "dca";
286 
287  inline auto get() noexcept
288  { return get_bit(__cpuid_ecx(addr), from) != 0; }
289  }
290 
291  namespace sse41
292  {
293  constexpr const auto mask = 0x00080000U;
294  constexpr const auto from = 19;
295  constexpr const auto name = "sse41";
296 
297  inline auto get() noexcept
298  { return get_bit(__cpuid_ecx(addr), from) != 0; }
299  }
300 
301  namespace sse42
302  {
303  constexpr const auto mask = 0x00100000U;
304  constexpr const auto from = 20;
305  constexpr const auto name = "sse42";
306 
307  inline auto get() noexcept
308  { return get_bit(__cpuid_ecx(addr), from) != 0; }
309  }
310 
311  namespace x2apic
312  {
313  constexpr const auto mask = 0x00200000U;
314  constexpr const auto from = 21;
315  constexpr const auto name = "x2apic";
316 
317  inline auto get() noexcept
318  { return get_bit(__cpuid_ecx(addr), from) != 0; }
319  }
320 
321  namespace movbe
322  {
323  constexpr const auto mask = 0x00400000U;
324  constexpr const auto from = 22;
325  constexpr const auto name = "movbe";
326 
327  inline auto get() noexcept
328  { return get_bit(__cpuid_ecx(addr), from) != 0; }
329  }
330 
331  namespace popcnt
332  {
333  constexpr const auto mask = 0x00800000U;
334  constexpr const auto from = 23;
335  constexpr const auto name = "popcnt";
336 
337  inline auto get() noexcept
338  { return get_bit(__cpuid_ecx(addr), from) != 0; }
339  }
340 
341  namespace tsc_deadline
342  {
343  constexpr const auto mask = 0x01000000U;
344  constexpr const auto from = 24;
345  constexpr const auto name = "tsc_deadline";
346 
347  inline auto get() noexcept
348  { return get_bit(__cpuid_ecx(addr), from) != 0; }
349  }
350 
351  namespace aesni
352  {
353  constexpr const auto mask = 0x02000000U;
354  constexpr const auto from = 25;
355  constexpr const auto name = "aesni";
356 
357  inline auto get() noexcept
358  { return get_bit(__cpuid_ecx(addr), from) != 0; }
359  }
360 
361  namespace xsave
362  {
363  constexpr const auto mask = 0x04000000U;
364  constexpr const auto from = 26;
365  constexpr const auto name = "xsave";
366 
367  inline auto get() noexcept
368  { return get_bit(__cpuid_ecx(addr), from) != 0; }
369  }
370 
371  namespace osxsave
372  {
373  constexpr const auto mask = 0x08000000U;
374  constexpr const auto from = 27;
375  constexpr const auto name = "osxsave";
376 
377  inline auto get() noexcept
378  { return get_bit(__cpuid_ecx(addr), from) != 0; }
379  }
380 
381  namespace avx
382  {
383  constexpr const auto mask = 0x10000000U;
384  constexpr const auto from = 28;
385  constexpr const auto name = "avx";
386 
387  inline auto get() noexcept
388  { return get_bit(__cpuid_ecx(addr), from) != 0; }
389  }
390 
391  namespace f16c
392  {
393  constexpr const auto mask = 0x20000000U;
394  constexpr const auto from = 29;
395  constexpr const auto name = "f16c";
396 
397  inline auto get() noexcept
398  { return get_bit(__cpuid_ecx(addr), from) != 0; }
399  }
400 
401  namespace rdrand
402  {
403  constexpr const auto mask = 0x40000000U;
404  constexpr const auto from = 30;
405  constexpr const auto name = "rdrand";
406 
407  inline auto get() noexcept
408  { return get_bit(__cpuid_ecx(addr), from) != 0; }
409  }
410 
411  inline void dump() noexcept
412  {
413  bfdebug << "cpuid::feature_information::ecx enabled flags:" << bfendl;
414 
415  if (sse3::get())
416  bfdebug << " - sse3" << bfendl;
417 
418  if (pclmulqdq::get())
419  bfdebug << " - pclmulqdq" << bfendl;
420 
421  if (dtes64::get())
422  bfdebug << " - dtes64" << bfendl;
423 
424  if (monitor::get())
425  bfdebug << " - monitor" << bfendl;
426 
427  if (ds_cpl::get())
428  bfdebug << " - ds_cpl" << bfendl;
429 
430  if (vmx::get())
431  bfdebug << " - vmx" << bfendl;
432 
433  if (smx::get())
434  bfdebug << " - smx" << bfendl;
435 
436  if (eist::get())
437  bfdebug << " - eist" << bfendl;
438 
439  if (tm2::get())
440  bfdebug << " - tm2" << bfendl;
441 
442  if (ssse3::get())
443  bfdebug << " - ssse3" << bfendl;
444 
445  if (cnxt_id::get())
446  bfdebug << " - cnxt_id" << bfendl;
447 
448  if (sdbg::get())
449  bfdebug << " - sdbg" << bfendl;
450 
451  if (fma::get())
452  bfdebug << " - fma" << bfendl;
453 
454  if (cmpxchg16b::get())
455  bfdebug << " - cmpxchg16b" << bfendl;
456 
458  bfdebug << " - xtpr_update_control" << bfendl;
459 
460  if (pdcm::get())
461  bfdebug << " - pdcm" << bfendl;
462 
463  if (pcid::get())
464  bfdebug << " - pcid" << bfendl;
465 
466  if (dca::get())
467  bfdebug << " - dca" << bfendl;
468 
469  if (sse41::get())
470  bfdebug << " - sse41" << bfendl;
471 
472  if (sse42::get())
473  bfdebug << " - sse42" << bfendl;
474 
475  if (x2apic::get())
476  bfdebug << " - x2apic" << bfendl;
477 
478  if (movbe::get())
479  bfdebug << " - movbe" << bfendl;
480 
481  if (popcnt::get())
482  bfdebug << " - popcnt" << bfendl;
483 
484  if (tsc_deadline::get())
485  bfdebug << " - tsc_deadline" << bfendl;
486 
487  if (aesni::get())
488  bfdebug << " - aesni" << bfendl;
489 
490  if (xsave::get())
491  bfdebug << " - xsave" << bfendl;
492 
493  if (osxsave::get())
494  bfdebug << " - osxsave" << bfendl;
495 
496  if (avx::get())
497  bfdebug << " - avx" << bfendl;
498 
499  if (f16c::get())
500  bfdebug << " - f16c" << bfendl;
501 
502  if (rdrand::get())
503  bfdebug << " - rdrand" << bfendl;
504  }
505  }
506  }
507 
508  namespace extended_feature_flags
509  {
510  constexpr const auto addr = 0x00000007UL;
511  constexpr const auto name = "extended_feature_flags";
512 
513  namespace subleaf0
514  {
515  namespace ebx
516  {
517  namespace fsgsbase
518  {
519  constexpr const auto mask = 0x00000001UL;
520  constexpr const auto from = 0;
521  constexpr const auto name = "fsgsbase";
522 
523  inline auto get() noexcept
524  {
525  value_type eax = addr;
526  value_type ebx = 0U;
527  value_type ecx = 0U;
528  value_type edx = 0U;
529 
530  __cpuid(&eax, &ebx, &ecx, &edx);
531 
532  return (ebx & mask) != 0;
533  }
534  }
535 
536  namespace ia32_tsc_adjust
537  {
538  constexpr const auto mask = 0x00000002UL;
539  constexpr const auto from = 1;
540  constexpr const auto name = "ia32_tsc_adjust";
541 
542  inline auto get() noexcept
543  {
544  value_type eax = addr;
545  value_type ebx = 0U;
546  value_type ecx = 0U;
547  value_type edx = 0U;
548 
549  __cpuid(&eax, &ebx, &ecx, &edx);
550 
551  return (ebx & mask) != 0;
552  }
553  }
554 
555  namespace sgx
556  {
557  constexpr const auto mask = 0x00000004UL;
558  constexpr const auto from = 2;
559  constexpr const auto name = "sgx";
560 
561  inline auto get() noexcept
562  {
563  value_type eax = addr;
564  value_type ebx = 0U;
565  value_type ecx = 0U;
566  value_type edx = 0U;
567 
568  __cpuid(&eax, &ebx, &ecx, &edx);
569 
570  return (ebx & mask) != 0;
571  }
572  }
573 
574  namespace bmi1
575  {
576  constexpr const auto mask = 0x00000008UL;
577  constexpr const auto from = 3;
578  constexpr const auto name = "bmi1";
579 
580  inline auto get() noexcept
581  {
582  value_type eax = addr;
583  value_type ebx = 0U;
584  value_type ecx = 0U;
585  value_type edx = 0U;
586 
587  __cpuid(&eax, &ebx, &ecx, &edx);
588 
589  return (ebx & mask) != 0;
590  }
591  }
592 
593  namespace hle
594  {
595  constexpr const auto mask = 0x00000010UL;
596  constexpr const auto from = 4;
597  constexpr const auto name = "hle";
598 
599  inline auto get() noexcept
600  {
601  value_type eax = addr;
602  value_type ebx = 0U;
603  value_type ecx = 0U;
604  value_type edx = 0U;
605 
606  __cpuid(&eax, &ebx, &ecx, &edx);
607 
608  return (ebx & mask) != 0;
609  }
610  }
611 
612  namespace avx2
613  {
614  constexpr const auto mask = 0x00000020UL;
615  constexpr const auto from = 5;
616  constexpr const auto name = "avx2";
617 
618  inline auto get() noexcept
619  {
620  value_type eax = addr;
621  value_type ebx = 0U;
622  value_type ecx = 0U;
623  value_type edx = 0U;
624 
625  __cpuid(&eax, &ebx, &ecx, &edx);
626 
627  return (ebx & mask) != 0;
628  }
629  }
630 
631  namespace fdp_excptn_only
632  {
633  constexpr const auto mask = 0x00000040UL;
634  constexpr const auto from = 6;
635  constexpr const auto name = "fdp_excptn_only";
636 
637  inline auto get() noexcept
638  {
639  value_type eax = addr;
640  value_type ebx = 0U;
641  value_type ecx = 0U;
642  value_type edx = 0U;
643 
644  __cpuid(&eax, &ebx, &ecx, &edx);
645 
646  return (ebx & mask) != 0;
647  }
648  }
649 
650  namespace smep
651  {
652  constexpr const auto mask = 0x00000080UL;
653  constexpr const auto from = 7;
654  constexpr const auto name = "smep";
655 
656  inline auto get() noexcept
657  {
658  value_type eax = addr;
659  value_type ebx = 0U;
660  value_type ecx = 0U;
661  value_type edx = 0U;
662 
663  __cpuid(&eax, &ebx, &ecx, &edx);
664 
665  return (ebx & mask) != 0;
666  }
667  }
668 
669  namespace bmi2
670  {
671  constexpr const auto mask = 0x00000100UL;
672  constexpr const auto from = 8;
673  constexpr const auto name = "bmi2";
674 
675  inline auto get() noexcept
676  {
677  value_type eax = addr;
678  value_type ebx = 0U;
679  value_type ecx = 0U;
680  value_type edx = 0U;
681 
682  __cpuid(&eax, &ebx, &ecx, &edx);
683 
684  return (ebx & mask) != 0;
685  }
686  }
687 
688  namespace enhanced_rep
689  {
690  constexpr const auto mask = 0x00000200UL;
691  constexpr const auto from = 9;
692  constexpr const auto name = "enhanced_rep";
693 
694  inline auto get() noexcept
695  {
696  value_type eax = addr;
697  value_type ebx = 0U;
698  value_type ecx = 0U;
699  value_type edx = 0U;
700 
701  __cpuid(&eax, &ebx, &ecx, &edx);
702 
703  return (ebx & mask) != 0;
704  }
705  }
706 
707  namespace invpcid
708  {
709  constexpr const auto mask = 0x00000400UL;
710  constexpr const auto from = 10;
711  constexpr const auto name = "invpcid";
712 
713  inline auto get() noexcept
714  {
715  value_type eax = addr;
716  value_type ebx = 0U;
717  value_type ecx = 0U;
718  value_type edx = 0U;
719 
720  __cpuid(&eax, &ebx, &ecx, &edx);
721 
722  return (ebx & mask) != 0;
723  }
724  }
725 
726  namespace rtm
727  {
728  constexpr const auto mask = 0x00000800UL;
729  constexpr const auto from = 11;
730  constexpr const auto name = "rtm";
731 
732  inline auto get() noexcept
733  {
734  value_type eax = addr;
735  value_type ebx = 0U;
736  value_type ecx = 0U;
737  value_type edx = 0U;
738 
739  __cpuid(&eax, &ebx, &ecx, &edx);
740 
741  return (ebx & mask) != 0;
742  }
743  }
744 
745  namespace rdt_m
746  {
747  constexpr const auto mask = 0x00001000UL;
748  constexpr const auto from = 12;
749  constexpr const auto name = "rdt_m";
750 
751  inline auto get() noexcept
752  {
753  value_type eax = addr;
754  value_type ebx = 0U;
755  value_type ecx = 0U;
756  value_type edx = 0U;
757 
758  __cpuid(&eax, &ebx, &ecx, &edx);
759 
760  return (ebx & mask) != 0;
761  }
762  }
763 
764  namespace depreciated_fpu_cs_ds
765  {
766  constexpr const auto mask = 0x00002000UL;
767  constexpr const auto from = 13;
768  constexpr const auto name = "depreciated_fpu_cs_ds";
769 
770  inline auto get() noexcept
771  {
772  value_type eax = addr;
773  value_type ebx = 0U;
774  value_type ecx = 0U;
775  value_type edx = 0U;
776 
777  __cpuid(&eax, &ebx, &ecx, &edx);
778 
779  return (ebx & mask) != 0;
780  }
781  }
782 
783  namespace mpx
784  {
785  constexpr const auto mask = 0x00004000UL;
786  constexpr const auto from = 14;
787  constexpr const auto name = "mpx";
788 
789  inline auto get() noexcept
790  {
791  value_type eax = addr;
792  value_type ebx = 0U;
793  value_type ecx = 0U;
794  value_type edx = 0U;
795 
796  __cpuid(&eax, &ebx, &ecx, &edx);
797 
798  return (ebx & mask) != 0;
799  }
800  }
801 
802  namespace rdt_a
803  {
804  constexpr const auto mask = 0x00008000UL;
805  constexpr const auto from = 15;
806  constexpr const auto name = "rdt_a";
807 
808  inline auto get() noexcept
809  {
810  value_type eax = addr;
811  value_type ebx = 0U;
812  value_type ecx = 0U;
813  value_type edx = 0U;
814 
815  __cpuid(&eax, &ebx, &ecx, &edx);
816 
817  return (ebx & mask) != 0;
818  }
819  }
820 
821  namespace rdseed
822  {
823  constexpr const auto mask = 0x00040000UL;
824  constexpr const auto from = 18;
825  constexpr const auto name = "rdseed";
826 
827  inline auto get() noexcept
828  {
829  value_type eax = addr;
830  value_type ebx = 0U;
831  value_type ecx = 0U;
832  value_type edx = 0U;
833 
834  __cpuid(&eax, &ebx, &ecx, &edx);
835 
836  return (ebx & mask) != 0;
837  }
838  }
839 
840  namespace adx
841  {
842  constexpr const auto mask = 0x00080000UL;
843  constexpr const auto from = 19;
844  constexpr const auto name = "adx";
845 
846  inline auto get() noexcept
847  {
848  value_type eax = addr;
849  value_type ebx = 0U;
850  value_type ecx = 0U;
851  value_type edx = 0U;
852 
853  __cpuid(&eax, &ebx, &ecx, &edx);
854 
855  return (ebx & mask) != 0;
856  }
857  }
858 
859  namespace smap
860  {
861  constexpr const auto mask = 0x00100000UL;
862  constexpr const auto from = 20;
863  constexpr const auto name = "smap";
864 
865  inline auto get() noexcept
866  {
867  value_type eax = addr;
868  value_type ebx = 0U;
869  value_type ecx = 0U;
870  value_type edx = 0U;
871 
872  __cpuid(&eax, &ebx, &ecx, &edx);
873 
874  return (ebx & mask) != 0;
875  }
876  }
877 
878  namespace clflushopt
879  {
880  constexpr const auto mask = 0x00800000UL;
881  constexpr const auto from = 23;
882  constexpr const auto name = "clflushopt";
883 
884  inline auto get() noexcept
885  {
886  value_type eax = addr;
887  value_type ebx = 0U;
888  value_type ecx = 0U;
889  value_type edx = 0U;
890 
891  __cpuid(&eax, &ebx, &ecx, &edx);
892 
893  return (ebx & mask) != 0;
894  }
895  }
896 
897  namespace clwb
898  {
899  constexpr const auto mask = 0x01000000UL;
900  constexpr const auto from = 24;
901  constexpr const auto name = "clwb";
902 
903  inline auto get() noexcept
904  {
905  value_type eax = addr;
906  value_type ebx = 0U;
907  value_type ecx = 0U;
908  value_type edx = 0U;
909 
910  __cpuid(&eax, &ebx, &ecx, &edx);
911 
912  return (ebx & mask) != 0;
913  }
914  }
915 
916  namespace processor_trace
917  {
918  constexpr const auto mask = 0x02000000UL;
919  constexpr const auto from = 25;
920  constexpr const auto name = "processor_trace";
921 
922  inline auto get() noexcept
923  {
924  value_type eax = addr;
925  value_type ebx = 0U;
926  value_type ecx = 0U;
927  value_type edx = 0U;
928 
929  __cpuid(&eax, &ebx, &ecx, &edx);
930 
931  return (ebx & mask) != 0;
932  }
933  }
934 
935  namespace sha
936  {
937  constexpr const auto mask = 0x20000000UL;
938  constexpr const auto from = 29;
939  constexpr const auto name = "sha";
940 
941  inline auto get() noexcept
942  {
943  value_type eax = addr;
944  value_type ebx = 0U;
945  value_type ecx = 0U;
946  value_type edx = 0U;
947 
948  __cpuid(&eax, &ebx, &ecx, &edx);
949 
950  return (ebx & mask) != 0;
951  }
952  }
953 
954  inline void dump() noexcept
955  {
956  bfdebug << "cpuid::extended_feature_flags::subleaf0::ebx enabled flags:" << bfendl;
957 
958  if (fsgsbase::get())
959  bfdebug << " - fsgsbase" << bfendl;
960 
961  if (ia32_tsc_adjust::get())
962  bfdebug << " - ia32_tsc_adjust" << bfendl;
963 
964  if (sgx::get())
965  bfdebug << " - sgx" << bfendl;
966 
967  if (bmi1::get())
968  bfdebug << " - bmi1" << bfendl;
969 
970  if (hle::get())
971  bfdebug << " - hle" << bfendl;
972 
973  if (avx2::get())
974  bfdebug << " - avx2" << bfendl;
975 
976  if (fdp_excptn_only::get())
977  bfdebug << " - fdp_excptn_only" << bfendl;
978 
979  if (smep::get())
980  bfdebug << " - smep" << bfendl;
981 
982  if (bmi2::get())
983  bfdebug << " - bmi2" << bfendl;
984 
985  if (enhanced_rep::get())
986  bfdebug << " - enhanced_rep" << bfendl;
987 
988  if (invpcid::get())
989  bfdebug << " - invpcid" << bfendl;
990 
991  if (rtm::get())
992  bfdebug << " - rtm" << bfendl;
993 
994  if (rtm::get())
995  bfdebug << " - rtm" << bfendl;
996 
997  if (rdt_m::get())
998  bfdebug << " - rdt_m" << bfendl;
999 
1001  bfdebug << " - depreciated_fpu_cs_ds" << bfendl;
1002 
1003  if (mpx::get())
1004  bfdebug << " - mpx" << bfendl;
1005 
1006  if (rdt_a::get())
1007  bfdebug << " - rdt_a" << bfendl;
1008 
1009  if (rdseed::get())
1010  bfdebug << " - rdseed" << bfendl;
1011 
1012  if (adx::get())
1013  bfdebug << " - adx" << bfendl;
1014 
1015  if (smap::get())
1016  bfdebug << " - smap" << bfendl;
1017 
1018  if (clflushopt::get())
1019  bfdebug << " - clflushopt" << bfendl;
1020 
1021  if (clwb::get())
1022  bfdebug << " - clwb" << bfendl;
1023 
1024  if (processor_trace::get())
1025  bfdebug << " - processor_trace" << bfendl;
1026 
1027  if (sha::get())
1028  bfdebug << " - sha" << bfendl;
1029  }
1030  }
1031  }
1032  }
1033 
1034  namespace arch_perf_monitoring
1035  {
1036  constexpr const auto addr = 0x0000000AUL;
1037  constexpr const auto name = "arch_perf_monitoring";
1038 
1039  namespace eax
1040  {
1041  namespace version_id
1042  {
1043  constexpr const auto mask = 0x000000FFUL;
1044  constexpr const auto from = 0UL;
1045  constexpr const auto name = "version_id";
1046 
1047  inline auto get() noexcept
1048  { return get_bits(__cpuid_eax(addr), mask) >> from; }
1049  }
1050 
1051  namespace gppmc_count
1052  {
1053  constexpr const auto mask = 0x0000FF00UL;
1054  constexpr const auto from = 8UL;
1055  constexpr const auto name = "gppmc_count";
1056 
1057  inline auto get() noexcept
1058  { return get_bits(__cpuid_eax(addr), mask) >> from; }
1059  }
1060 
1061  namespace gppmc_bit_width
1062  {
1063  constexpr const auto mask = 0x00FF0000UL;
1064  constexpr const auto from = 16UL;
1065  constexpr const auto name = "gppmc_bit_width";
1066 
1067  inline auto get() noexcept
1068  { return get_bits(__cpuid_eax(addr), mask) >> from; }
1069  }
1070 
1071  namespace ebx_enumeration_length
1072  {
1073  constexpr const auto mask = 0xFF000000UL;
1074  constexpr const auto from = 24;
1075  constexpr const auto name = "ebx_enumeration_length";
1076 
1077  inline auto get() noexcept
1078  { return get_bits(__cpuid_eax(addr), mask) >> from; }
1079  }
1080  }
1081 
1082  namespace ebx
1083  {
1084  namespace core_cycle_event
1085  {
1086  constexpr const auto mask = 0x00000001UL;
1087  constexpr const auto from = 0UL;
1088  constexpr const auto name = "core_cycle_event";
1089 
1090  inline auto is_available() noexcept
1091  { return get_bit(__cpuid_ebx(addr), from) == 0; }
1092  }
1093 
1094  namespace instr_retired_event
1095  {
1096  constexpr const auto mask = 0x00000002UL;
1097  constexpr const auto from = 1UL;
1098  constexpr const auto name = "instr_retired_event";
1099 
1100  inline auto is_available() noexcept
1101  { return get_bit(__cpuid_ebx(addr), from) == 0; }
1102  }
1103 
1104  namespace reference_cycles_event
1105  {
1106  constexpr const auto mask = 0x00000004UL;
1107  constexpr const auto from = 2UL;
1108  constexpr const auto name = "reference_cycles_event";
1109 
1110  inline auto is_available() noexcept
1111  { return get_bit(__cpuid_ebx(addr), from) == 0; }
1112  }
1113 
1114  namespace llc_reference_event
1115  {
1116  constexpr const auto mask = 0x00000008UL;
1117  constexpr const auto from = 3UL;
1118  constexpr const auto name = "llc_reference_event";
1119 
1120  inline auto is_available() noexcept
1121  { return get_bit(__cpuid_ebx(addr), from) == 0; }
1122  }
1123 
1124  namespace llc_misses_event
1125  {
1126  constexpr const auto mask = 0x00000010UL;
1127  constexpr const auto from = 4UL;
1128  constexpr const auto name = "llc_misses_event";
1129 
1130  inline auto is_available() noexcept
1131  { return get_bit(__cpuid_ebx(addr), from) == 0; }
1132  }
1133 
1134  namespace branch_instr_retired_event
1135  {
1136  constexpr const auto mask = 0x00000020UL;
1137  constexpr const auto from = 5UL;
1138  constexpr const auto name = "branch_instr_retired_event";
1139 
1140  inline auto is_available() noexcept
1141  { return get_bit(__cpuid_ebx(addr), from) == 0; }
1142  }
1143 
1144  namespace branch_mispredict_retired_event
1145  {
1146  constexpr const auto mask = 0x00000040UL;
1147  constexpr const auto from = 6UL;
1148  constexpr const auto name = "branch_mispredict_retired_event";
1149 
1150  inline auto is_available() noexcept
1151  { return get_bit(__cpuid_ebx(addr), from) == 0; }
1152  }
1153  }
1154 
1155  namespace edx
1156  {
1157  namespace ffpmc_count
1158  {
1159  constexpr const auto mask = 0x0000001FUL;
1160  constexpr const auto from = 0;
1161  constexpr const auto name = "ffpmc_count";
1162 
1163  inline auto get() noexcept
1164  { return get_bits(__cpuid_edx(addr), mask) >> from; }
1165  }
1166 
1167  namespace ffpmc_bit_width
1168  {
1169  constexpr const auto mask = 0x00001FE0UL;
1170  constexpr const auto from = 5;
1171  constexpr const auto name = "ffpmc_bit_width";
1172 
1173  inline auto get() noexcept
1174  { return get_bits(__cpuid_edx(addr), mask) >> from; }
1175  }
1176  }
1177  }
1178 }
1179 }
1180 
1181 // *INDENT-ON*
1182 
1183 #endif
constexpr const auto mask
Definition: cpuid_x64.h:85
constexpr const auto name
Definition: cpuid_x64.h:107
uint32_t __cpuid_ecx(uint32_t val) noexcept
constexpr const auto addr
Definition: cpuid_x64.h:1036
constexpr const auto addr
Definition: cpuid_x64.h:510
uint32_t field_type
Definition: cpuid_x64.h:40
constexpr const auto from
Definition: cpuid_x64.h:96
constexpr const auto name
Definition: cpuid_x64.h:511
void __cpuid(void *eax, void *ebx, void *ecx, void *edx) noexcept
uint32_t value_type
Definition: cpuid_x64.h:41
uint32_t __cpuid_eax(uint32_t val) noexcept
auto get_bit(T t, B b) noexcept
Definition: bitmanip.h:42
void uint64_t uint64_t uint64_t *rdx noexcept
uint32_t __cpuid_edx(uint32_t val) noexcept
constexpr const auto from
Definition: cpuid_x64.h:86
constexpr const auto addr
Definition: cpuid_x64.h:80
constexpr const auto mask
Definition: cpuid_x64.h:95
uint32_t __cpuid_ebx(uint32_t val) noexcept
auto get(T1 eax, T2 ebx, T3 ecx, T4 edx) noexcept
Definition: cpuid_x64.h:48
constexpr const auto addr
Definition: cpuid_x64.h:106
auto get_bits(T t, M m) noexcept
Definition: bitmanip.h:65
constexpr const auto name
Definition: cpuid_x64.h:1037
constexpr const auto name
Definition: cpuid_x64.h:81
Definition: cache_x64.h:31