Nie możesz wybrać więcej, niż 25 tematów Tematy muszą się zaczynać od litery lub cyfry, mogą zawierać myślniki ('-') i mogą mieć do 35 znaków.
 
 
 
 

363 wiersze
16 KiB

  1. #pragma once
  2. #include <string.h>
  3. #ifdef MSVC
  4. #include <immintrin.h>
  5. #define platform_independent_cpuid(function_id, array_of_registers) \
  6. __cpuid(array_of_registers, function_id)
  7. #define platform_independent_cpuidex(function_id, sub_function_id, array_of_registers) \
  8. __cpuid_count(array_of_registers, function_id, sub_function_id)
  9. #else
  10. #include <cpuid.h>
  11. #define platform_independent_cpuid(function_id, array_of_registers) \
  12. __cpuid(function_id, array_of_registers[0], array_of_registers[1], \
  13. array_of_registers[2],array_of_registers[3])
  14. #define platform_independent_cpuidex(function_id, sub_function_id, array_of_registers) \
  15. __cpuid_count (function_id, sub_function_id, array_of_registers[0], \
  16. array_of_registers[1], array_of_registers[2], \
  17. array_of_registers[3])
  18. #endif
  19. enum struct Edx_1_Feature_Flags {
  20. fpu = 1<<0, // Onboard x87 FPU
  21. vme = 1<<1, // Virtual 8086 mode extensions (such as VIF, VIP, PIV)
  22. de = 1<<2, // Debugging extensions (CR4 bit 3)
  23. pse = 1<<3, // Page Size Extension
  24. tsc = 1<<4, // Time Stamp Counter
  25. msr = 1<<5, // Model-specific registers
  26. pae = 1<<6, // Physical Address Extension
  27. mce = 1<<7, // Machine Check Exception
  28. cx8 = 1<<8, // CMPXCHG8 (compare-and-swap) instruction
  29. apic = 1<<9, // Onboard Advanced Programmable Interrupt Controller
  30. _resv1 = 1<<10, // (reserved)
  31. sep = 1<<11, // SYSENTER and SYSEXIT instructions
  32. mtrr = 1<<12, // Memory Type Range Registers
  33. pge = 1<<13, // Page Global Enable bit in CR4
  34. mca = 1<<14, // Machine check architecture
  35. cmov = 1<<15, // Conditional move and FCMOV instructions
  36. pat = 1<<16, // Page Attribute Table
  37. pse_36 = 1<<17, // 36-bit page size extension
  38. psn = 1<<18, // Processor Serial Number
  39. clfsh = 1<<19, // CLFLUSH instruction (SSE2)
  40. _resv2 = 1<<20, // (reserved)
  41. ds = 1<<21, // Debug store: save trace of executed jumps
  42. acpi = 1<<22, // Onboard thermal control MSRs for ACPI
  43. mmx = 1<<23, // MMX instructions
  44. fxsr = 1<<24, // FXSAVE, FXRESTOR instructions, CR4 bit 9
  45. sse = 1<<25, // SSE instructions (a.k.a. Katmai New Instructions)
  46. sse2 = 1<<26, // SSE2 instructions
  47. ss = 1<<27, // CPU cache implements self-snoop
  48. htt = 1<<28, // Hyper-threading
  49. tm = 1<<29, // Thermal monitor automatically limits temperature
  50. ia64 = 1<<30, // IA64 processor emulating x86
  51. pbe = 1<<31, // Pending Break Enable (PBE# pin) wakeup capability
  52. };
  53. enum struct Ecx_1_Feature_Flags {
  54. sse3 = 1<<0, // Prescott New Instructions-SSE3 (PNI)
  55. pclmulqdq = 1<<1, // PCLMULQDQ
  56. dtes64 = 1<<2, // 64-bit debug store (edx bit 21)
  57. monitor = 1<<3, // MONITOR and MWAIT instructions (SSE3)
  58. ds_cpl = 1<<4, // CPL qualified debug store
  59. vmx = 1<<5, // Virtual Machine eXtensions
  60. smx = 1<<6, // Safer Mode Extensions (LaGrande)
  61. est = 1<<7, // Enhanced SpeedStep
  62. tm2 = 1<<8, // Thermal Monitor 2
  63. ssse3 = 1<<9, // Supplemental SSE3 instructions
  64. cnxt_id = 1<<10, // L1 Context ID
  65. sdbg = 1<<11, // Silicon Debug interface
  66. fma = 1<<12, // Fused multiply-add (FMA3)
  67. cx16 = 1<<13, // CMPXCHG16B instruction
  68. xtpr = 1<<14, // Can disable sending task priority messages
  69. pdcm = 1<<15, // Perfmon & debug capability
  70. _resv1 = 1<<16, // (reserved)
  71. pcid = 1<<17, // Process context identifiers (CR4 bit 17)
  72. dca = 1<<18, // Direct cache access for DMA writes
  73. sse4_1 = 1<<19, // SSE4.1 instructions
  74. sse4_2 = 1<<20, // SSE4.2 instructions
  75. x2apic = 1<<21, // x2APIC
  76. movbe = 1<<22, // MOVBE instruction (big-endian)
  77. popcnt = 1<<23, // POPCNT instruction
  78. tsc_deadline = 1<<24, // APIC implements one-shot operation using a TSC deadline value
  79. aes = 1<<25, // AES instruction set
  80. xsave = 1<<26, // XSAVE, XRESTOR, XSETBV, XGETBV
  81. osxsave = 1<<27, // XSAVE enabled by OS
  82. avx = 1<<28, // Advanced Vector Extensions
  83. f16c = 1<<29, // F16C (half-precision) FP feature
  84. rdrnd = 1<<30, // RDRAND (on-chip random number generator) feature
  85. hypervisor = 1<<31, // Hypervisor present (always zero on physical CPUs)
  86. };
  87. enum struct Ebx_7_Extended_Feature_Flags {
  88. fsgsbase = 1<<0, // Access to base of %fs and %gs
  89. _idk1 = 1<<1, //
  90. sgx = 1<<2, // Software Guard Extensions
  91. bmi1 = 1<<3, // Bit Manipulation Instruction Set 1
  92. hle = 1<<4, // TSX Hardware Lock Elision
  93. avx2 = 1<<5, // Advanced Vector Extensions 2
  94. _idk2 = 1<<6, //
  95. smep = 1<<7, // Supervisor Mode Execution Prevention
  96. bmi2 = 1<<8, // Bit Manipulation Instruction Set 2
  97. erms = 1<<9, // Enhanced REP MOVSB/STOSB
  98. invpcid = 1<<10, // INVPCID instruction
  99. rtm = 1<<11, // TSX Restricted Transactional Memory
  100. pqm = 1<<12, // Platform Quality of Service Monitoring
  101. _idk3 = 1<<13, //
  102. mpx = 1<<14, // Intel MPX (Memory Protection Extensions)
  103. pqe = 1<<15, // Platform Quality of Service Enforcement
  104. avx512_f = 1<<16, // AVX-512 Foundation
  105. avx512_dq = 1<<17, // AVX-512 Doubleword and Quadword Instructions
  106. rdseed = 1<<18, // RDSEED instruction
  107. adx = 1<<19, // Intel ADX (Multi-Precision Add-Carry Instruction Extensions)
  108. smap = 1<<20, // Supervisor Mode Access Prevention
  109. avx512_ifma = 1<<21, // AVX-512 Integer Fused Multiply-Add Instructions
  110. pcommit = 1<<22, // PCOMMIT instruction
  111. clflushopt = 1<<23, // CLFLUSHOPT instruction
  112. clwb = 1<<24, // CLWB instruction
  113. intel_pt = 1<<25, // Intel Processor Trace
  114. avx512_pf = 1<<26, // AVX-512 Prefetch Instructions
  115. avx512_er = 1<<27, // AVX-512 Exponential and Reciprocal Instructions
  116. avx512_cd = 1<<28, // AVX-512 Conflict Detection Instructions
  117. sha = 1<<29, // Intel SHA extensions
  118. avx512_bw = 1<<30, // AVX-512 Byte and Word Instructions
  119. avx512_vl = 1<<31, // AVX-512 Vector Length Extensions
  120. };
  121. enum struct Ecx_7_Extended_Feature_Flags {
  122. prefetchwt1 = 1<<0, // PREFETCHWT1 instruction
  123. avx512_vbmi = 1<<1, // AVX-512 Vector Bit Manipulation Instructions
  124. umip = 1<<2, // User-mode Instruction Prevention
  125. pku = 1<<3, // Memory Protection Keys for User-mode pages
  126. ospke = 1<<4, // PKU enabled by OS
  127. waitpkg = 1<<5, // Timed pause and user-level monitor/wait
  128. avx512_vbmi2 = 1<<6, // AVX-512 Vector Bit Manipulation Instructions 2
  129. cet_ss = 1<<7, // Control flow enforcement (CET) shadow stack
  130. gfni = 1<<8, // Galois Field instructions
  131. vaes = 1<<9, // Vector AES instruction set (VEX-256/EVEX)
  132. vpclmulqdq = 1<<10, // CLMUL instruction set (VEX-256/EVEX)
  133. avx512_vnni = 1<<11, // AVX-512 Vector Neural Network Instructions
  134. avx512_bitalg = 1<<12, // AVX-512 BITALG instructions
  135. _resv1 = 1<<13, // (reserved)
  136. avx512_vpopcntdq = 1<<14, // AVX-512 Vector Population Count Double and Quad-word
  137. _resv2 = 1<<15, // (reserved)
  138. intel_5lp = 1<<16, // 5-level paging
  139. mawau1 = 1<<17, // The value of userspace MPX Address-Width Adjust used ...
  140. mawau2 = 1<<18, // ... by the BNDLDX and BNDSTX Intel MPX instructions ...
  141. mawau3 = 1<<19, // ... in 64-bit mode
  142. mawau4 = 1<<20, //
  143. mawau5 = 1<<21, //
  144. rdpid = 1<<22, // Read Processor ID and IA32_TSC_AUX
  145. _resv3 = 1<<23, // (reserved)
  146. _resv4 = 1<<24, // (reserved)
  147. cldemote = 1<<25, // Cache line demote
  148. _resv5 = 1<<26, // (reserved)
  149. movdiri = 1<<27, //
  150. movdir64b = 1<<28, //
  151. enqcmd = 1<<29, // Enqueue Stores
  152. sgx_lc = 1<<30, // SGX Launch Configuration
  153. pks = 1<<31, // Protection keys for supervisor-mode pages
  154. };
  155. enum struct Edx_7_Extended_Feature_Flags {
  156. _resv1 = 1<<0, // (reserved)
  157. _resv2 = 1<<1, // (reserved)
  158. avx512_4vnniw = 1<<2, // AVX-512 4-register Neural Network Instructions
  159. avx512_4fmaps = 1<<3, // AVX-512 4-register Multiply Accumulation Single precision
  160. fsrm = 1<<4, // Fast Short REP MOVSB
  161. _resv3 = 1<<5, // (reserved)
  162. _resv4 = 1<<6, // (reserved)
  163. _resv5 = 1<<7, // (reserved)
  164. avx512_vp2intersect = 1<<8, // AVX-512 VP2INTERSECT Doubleword and Quadword Instructions
  165. SRBDS_CTRL = 1<<9, // Special Register Buffer Data Sampling Mitigations
  166. md_clear = 1<<10, // VERW instruction clears CPU buffers
  167. _resv6 = 1<<11, // (reserved)
  168. _resv7 = 1<<12, // (reserved)
  169. tsx_force_abort = 1<<13, //
  170. serialize = 1<<14, // Serialize instruction execution
  171. hybrid = 1<<15, //
  172. TSXLDTRK = 1<<16, // TSX suspend load address tracking
  173. _resv8 = 1<<17, // (reserved)
  174. pconfig = 1<<18, // Platform configuration (Memory Encryption Technologies Instructions)
  175. lbr = 1<<19, // Architectural Last Branch Records
  176. cet_ibt = 1<<20, // Control flow enforcement (CET) indirect branch tracking
  177. _resv9 = 1<<21, // (reserved)
  178. amx_bf16 = 1<<22, // Tile computation on bfloat16 numbers
  179. _resv10 = 1<<23, // (reserved)
  180. amx_tile = 1<<24, // Tile architecture
  181. amx_int8 = 1<<25, // Tile computation on 8-bit integers
  182. spec_ctrl = 1<<26,
  183. // Speculation Control, part of Indirect Branch Control (IBC):
  184. // Indirect Branch Restricted Speculation (IBRS) and
  185. // Indirect Branch Prediction Barrier (IBPB)
  186. stibp = 1<<27, // Single Thread Indirect Branch Predictor, part of IBC
  187. l1d_flush = 1<<28, // IA32_FLUSH_CMD MSR
  188. ia32_arch_capabilities = 1<<29, // Speculative Side Channel Mitigations
  189. ia32_core_capabilities = 1<<30, // Support for a MSR listing model-specific core capabilities
  190. ssbd = 1<<31, // Speculative Store Bypass Disable, as mitigation for Speculative Store Bypass (IA32_SPEC_CTRL)
  191. };
  192. // NOTE(Felix): Left out flags are duplicates from Edx_1_Feature_Flags
  193. enum struct Edx_81_Extended_Feature_Flags {
  194. syscall = 1<<11, // SYSCALL and SYSRET instructions
  195. mp = 1<<19, // Multiprocessor Capable
  196. nx = 1<<20, // NX (no-execute) bit
  197. mmxext = 1<<22, // Extended MMX
  198. fxsr_opt = 1<<25, // FXSAVE/FXRSTOR optimizations
  199. pdpe1gb = 1<<26, // Gibibyte pages
  200. rdtscp = 1<<27, // RDTSCP instruction
  201. l1d_flush = 1<<28, // IA32_FLUSH_CMD MSR
  202. lm = 1<<29, // Long mode
  203. _3dnowext = 1<<30, // Extended 3DNow!
  204. _3dnow = 1<<31, // 3DNow!
  205. };
  206. enum struct Ecx_81_Extended_Feature_Flags {
  207. lahf_lm = 1<<0, // LAHF/SAHF in long mode
  208. cmp_legacy = 1<<1, // Hyperthreading not valid
  209. svm = 1<<2, // Secure Virtual Machine
  210. extapic = 1<<3, // Extended APIC space
  211. cr8_legacy = 1<<4, // CR8 in 32-bit mode
  212. abm = 1<<5, // Advanced bit manipulation (lzcnt and popcnt)
  213. sse4a = 1<<6, // SSE4a
  214. misalignsse = 1<<7, // Misaligned SSE mode
  215. _3dnowprefetch= 1<<8, // PREFETCH and PREFETCHW instructions
  216. osvw = 1<<9, // OS Visible Workaround
  217. ibs = 1<<10, // Instruction Based Sampling
  218. xop = 1<<11, // XOP instruction set
  219. skinit = 1<<12, // SKINIT/STGI instructions
  220. wdt = 1<<13, // Watchdog timer
  221. _resv1 = 1<<14, // (reserved)
  222. lwp = 1<<15, // Light Weight Profiling
  223. fma4 = 1<<16, // 4 operands fused multiply-add
  224. tce = 1<<17, // Translation Cache Extension
  225. _resv2 = 1<<18, // (reserved)
  226. nodeid_msr = 1<<19, // NodeID MSR
  227. _resv3 = 1<<20, // (reserved)
  228. tbm = 1<<21, // Trailing Bit Manipulation
  229. topoext = 1<<22, // opology Extensions
  230. perfctr_core = 1<<23, // Core performance counter extensions
  231. perfctr_nb = 1<<24, // NB performance counter extensions
  232. _resv4 = 1<<25, // (reserved)
  233. dbx = 1<<26, // Data breakpoint extensions
  234. perftsc = 1<<27, // Performance TSC
  235. pcx_l2i = 1<<28, // L2I perf counter extensions
  236. _resv5 = 1<<29, // (reserved)
  237. _resv6 = 1<<30, // (reserved)
  238. _resv7 = 1<<31, // (reserved)
  239. };
  240. struct Cpu_Info {
  241. char vendor[0x20];
  242. char brand[0x40];
  243. bool is_intel;
  244. bool is_amd;
  245. int f_1_ECX;
  246. int f_1_EDX;
  247. int f_7_EBX;
  248. int f_7_ECX;
  249. int f_7_EDX;
  250. int f_81_ECX;
  251. int f_81_EDX;
  252. };
  253. inline auto query_cpu_feature(Cpu_Info* info, Edx_1_Feature_Flags flag) -> bool {
  254. return info->f_1_EDX & (int)flag;
  255. }
  256. inline auto query_cpu_feature(Cpu_Info* info, Ecx_1_Feature_Flags flag) -> bool {
  257. return info->f_1_ECX & (int)flag;
  258. }
  259. inline auto query_cpu_feature(Cpu_Info* info, Ebx_7_Extended_Feature_Flags flag) -> bool {
  260. return info->f_7_EBX & (int)flag;
  261. }
  262. inline auto query_cpu_feature(Cpu_Info* info, Ecx_7_Extended_Feature_Flags flag) -> bool {
  263. return info->f_7_ECX & (int)flag;
  264. }
  265. inline auto query_cpu_feature(Cpu_Info* info, Edx_7_Extended_Feature_Flags flag) -> bool {
  266. return info->f_7_EDX & (int)flag;
  267. }
  268. inline auto query_cpu_feature(Cpu_Info* info, Edx_81_Extended_Feature_Flags flag) -> bool {
  269. return info->f_81_EDX & (int)flag;
  270. }
  271. inline auto query_cpu_feature(Cpu_Info* info, Ecx_81_Extended_Feature_Flags flag) -> bool {
  272. return info->f_81_ECX & (int)flag;
  273. }
  274. auto get_cpu_info(Cpu_Info* info) -> void {
  275. *info = {};
  276. int nIds_ = 0;
  277. int nExIds_ = 0;
  278. int register_sets[3][4];
  279. info->is_intel = false;
  280. info->is_amd = false;
  281. // Calling __cpuid with 0x0 as the function_id argument
  282. // gets the number of the highest valid function ID.
  283. platform_independent_cpuid(0, register_sets[0]);
  284. nIds_ = register_sets[0][0];
  285. // Capture vendor string
  286. memset(info->vendor, 0, sizeof(info->vendor));
  287. memcpy(info->vendor + 0, register_sets[0]+1, sizeof(int));
  288. memcpy(info->vendor + 4, register_sets[0]+3, sizeof(int));
  289. memcpy(info->vendor + 8, register_sets[0]+2, sizeof(int));
  290. if (strcmp(info->vendor, "GenuineIntel") == 0) {
  291. info->is_intel = true;
  292. } else if (strcmp(info->vendor, "AuthenticAMD") == 0) {
  293. info->is_amd = true;
  294. }
  295. if (nIds_ >= 1) {
  296. platform_independent_cpuidex(1, 0, register_sets[0]);
  297. info->f_1_ECX = register_sets[0][2];
  298. info->f_1_EDX = register_sets[0][3];
  299. if (nIds_ >= 7) {
  300. platform_independent_cpuidex(7, 0, register_sets[1]);
  301. info->f_7_EBX = register_sets[1][1];
  302. info->f_7_ECX = register_sets[1][2];
  303. info->f_7_EDX = register_sets[1][3];
  304. }
  305. }
  306. // Calling __cpuid with 0x80000000 as the function_id argument
  307. // gets the number of the highest valid extended ID.
  308. platform_independent_cpuid(0x80000000, register_sets[2]);
  309. nExIds_ = register_sets[2][0];
  310. memset(info->brand, 0, sizeof(info->brand));
  311. // load bitset with flags for function 0x80000001
  312. if (nExIds_ >= 0x80000001) {
  313. platform_independent_cpuidex(0x80000001, 0, register_sets[2]);
  314. info->f_81_ECX = register_sets[2][2];
  315. info->f_81_EDX = register_sets[2][3];
  316. // Interpret CPU brand string if reported
  317. if (nExIds_ >= 0x80000004) {
  318. platform_independent_cpuidex(0x80000002, 0, register_sets[0]);
  319. platform_independent_cpuidex(0x80000003, 0, register_sets[1]);
  320. platform_independent_cpuidex(0x80000004, 0, register_sets[2]);
  321. memcpy(info->brand + 0, register_sets[0], sizeof(register_sets[0]));
  322. memcpy(info->brand + 16, register_sets[1], sizeof(register_sets[1]));
  323. memcpy(info->brand + 32, register_sets[2], sizeof(register_sets[2]));
  324. }
  325. }
  326. }