1 /* 2 * Copyright 2008 Veselin Georgiev, 3 * anrieffNOSPAM @ mgail_DOT.com (convert to gmail) 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 16 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 17 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 18 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 19 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 20 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 21 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 22 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 24 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 */ 26 #ifndef __LIBCPUID_H__ 27 #define __LIBCPUID_H__ 28 /** 29 * \file libcpuid.h 30 * \author Veselin Georgiev 31 * \date Oct 2008 32 * \version 0.5.1 33 * 34 * Version history: 35 * 36 * * 0.1.0 (2008-10-15): initial adaptation from wxfractgui sources 37 * * 0.1.1 (2009-07-06): Added intel_fn11 fields to cpu_raw_data_t to handle 38 * new processor topology enumeration required on Core i7 39 * * 0.1.2 (2009-09-26): Added support for MSR reading through self-extracting 40 * kernel driver on Win32. 41 * * 0.1.3 (2010-04-20): Added support for greater more accurate CPU clock 42 * measurements with cpu_clock_by_ic() 43 * * 0.2.0 (2011-10-11): Support for AMD Bulldozer CPUs, 128-bit SSE unit size 44 * checking. A backwards-incompatible change, since the 45 * sizeof cpu_id_t is now different. 46 * * 0.2.1 (2012-05-26): Support for Ivy Bridge, and detecting the presence of 47 * the RdRand instruction. 48 * * 0.2.2 (2015-11-04): Support for newer processors up to Haswell and Vishera. 49 * Fix clock detection in cpu_clock_by_ic() for Bulldozer. 50 * More entries supported in cpu_msrinfo(). 51 * *BSD and Solaris support (unofficial). 52 * * 0.3.0 (2016-07-09): Support for Skylake; MSR ops in FreeBSD; INFO_VOLTAGE 53 * for AMD CPUs. Level 4 cache support for Crystalwell 54 * (a backwards-incompatible change since the sizeof 55 * cpu_raw_data_t is now different). 56 * * 0.4.0 (2016-09-30): Better detection of AMD clock multiplier with msrinfo. 57 * Support for Intel SGX detection 58 * (a backwards-incompatible change since the sizeof 59 * cpu_raw_data_t and cpu_id_t is now different). 60 * * 0.4.1 (2019-02-05): A lot of DB updates, and better RDMSR 61 * * 0.5.0 (2020-05-23): A lot of DB updates, detection of new CPU features, 62 * (a backwards-incompatible change since the sizeof 63 * cpu_raw_data_t and cpu_id_t is now different). 64 * * 0.5.1 (2021-03-20): A lot of DB updates 65 */ 66 67 /** @mainpage A simple libcpuid introduction 68 * 69 * LibCPUID provides CPU identification and access to the CPUID and RDTSC 70 * instructions on the x86. 71 * <p> 72 * To execute CPUID, use \ref cpu_exec_cpuid <br> 73 * To execute RDTSC, use \ref cpu_rdtsc <br> 74 * To fetch the CPUID info needed for CPU identification, use 75 * \ref cpuid_get_raw_data <br> 76 * To make sense of that data (decode, extract features), use \ref cpu_identify <br> 77 * To detect the CPU speed, use either \ref cpu_clock, \ref cpu_clock_by_os, 78 * \ref cpu_tsc_mark + \ref cpu_tsc_unmark + \ref cpu_clock_by_mark, 79 * \ref cpu_clock_measure or \ref cpu_clock_by_ic. 80 * Read carefully for pros/cons of each method. <br> 81 * 82 * To read MSRs, use \ref cpu_msr_driver_open to get a handle, and then 83 * \ref cpu_rdmsr for querying abilities. Some MSR decoding is available on recent 84 * CPUs, and can be queried through \ref cpu_msrinfo; the various types of queries 85 * are described in \ref cpu_msrinfo_request_t. 86 * </p> 87 */ 88 89 /** @defgroup libcpuid LibCPUID 90 * @brief LibCPUID provides CPU identification 91 @{ */ 92 93 /* Include some integer type specifications: */ 94 #include "libcpuid_types.h" 95 96 /* Some limits and other constants */ 97 #include "libcpuid_constants.h" 98 99 #ifdef __cplusplus 100 extern "C" { 101 #endif 102 103 /** 104 * @brief CPU vendor, as guessed from the Vendor String. 105 */ 106 typedef enum { 107 VENDOR_INTEL = 0, /*!< Intel CPU */ 108 VENDOR_AMD, /*!< AMD CPU */ 109 VENDOR_CYRIX, /*!< Cyrix CPU */ 110 VENDOR_NEXGEN, /*!< NexGen CPU */ 111 VENDOR_TRANSMETA, /*!< Transmeta CPU */ 112 VENDOR_UMC, /*!< x86 CPU by UMC */ 113 VENDOR_CENTAUR, /*!< x86 CPU by IDT */ 114 VENDOR_RISE, /*!< x86 CPU by Rise Technology */ 115 VENDOR_SIS, /*!< x86 CPU by SiS */ 116 VENDOR_NSC, /*!< x86 CPU by National Semiconductor */ 117 VENDOR_HYGON, /*!< Hygon CPU */ 118 119 NUM_CPU_VENDORS, /*!< Valid CPU vendor ids: 0..NUM_CPU_VENDORS - 1 */ 120 VENDOR_UNKNOWN = -1, 121 } cpu_vendor_t; 122 #define NUM_CPU_VENDORS NUM_CPU_VENDORS 123 124 /** 125 * @brief Contains just the raw CPUID data. 126 * 127 * This contains only the most basic CPU data, required to do identification 128 * and feature recognition. Every processor should be identifiable using this 129 * data only. 130 */ 131 struct cpu_raw_data_t { 132 /** contains results of CPUID for eax = 0, 1, ...*/ 133 uint32_t basic_cpuid[MAX_CPUID_LEVEL][NUM_REGS]; 134 135 /** contains results of CPUID for eax = 0x80000000, 0x80000001, ...*/ 136 uint32_t ext_cpuid[MAX_EXT_CPUID_LEVEL][NUM_REGS]; 137 138 /** when the CPU is intel and it supports deterministic cache 139 information: this contains the results of CPUID for eax = 4 140 and ecx = 0, 1, ... */ 141 uint32_t intel_fn4[MAX_INTELFN4_LEVEL][NUM_REGS]; 142 143 /** when the CPU is intel and it supports leaf 0Bh (Extended Topology 144 enumeration leaf), this stores the result of CPUID with 145 eax = 11 and ecx = 0, 1, 2... */ 146 uint32_t intel_fn11[MAX_INTELFN11_LEVEL][NUM_REGS]; 147 148 /** when the CPU is intel and supports leaf 12h (SGX enumeration leaf), 149 * this stores the result of CPUID with eax = 0x12 and 150 * ecx = 0, 1, 2... */ 151 uint32_t intel_fn12h[MAX_INTELFN12H_LEVEL][NUM_REGS]; 152 153 /** when the CPU is intel and supports leaf 14h (Intel Processor Trace 154 * capabilities leaf). 155 * this stores the result of CPUID with eax = 0x12 and 156 * ecx = 0, 1, 2... */ 157 uint32_t intel_fn14h[MAX_INTELFN14H_LEVEL][NUM_REGS]; 158 159 /** when the CPU is AMD and supports leaf 8000001Dh 160 * (topology information for the DC) 161 * this stores the result of CPUID with eax = 8000001Dh and 162 * ecx = 0, 1, 2... */ 163 uint32_t amd_fn8000001dh[MAX_AMDFN8000001DH_LEVEL][NUM_REGS]; 164 }; 165 166 /** 167 * @brief This contains information about SGX features of the processor 168 * Example usage: 169 * @code 170 * ... 171 * struct cpu_raw_data_t raw; 172 * struct cpu_id_t id; 173 * 174 * if (cpuid_get_raw_data(&raw) == 0 && cpu_identify(&raw, &id) == 0 && id.sgx.present) { 175 * printf("SGX is present.\n"); 176 * printf("SGX1 instructions: %s.\n", id.sgx.flags[INTEL_SGX1] ? "present" : "absent"); 177 * printf("SGX2 instructions: %s.\n", id.sgx.flags[INTEL_SGX2] ? "present" : "absent"); 178 * printf("Max 32-bit enclave size: 2^%d bytes.\n", id.sgx.max_enclave_32bit); 179 * printf("Max 64-bit enclave size: 2^%d bytes.\n", id.sgx.max_enclave_64bit); 180 * for (int i = 0; i < id.sgx.num_epc_sections; i++) { 181 * struct cpu_epc_t epc = cpuid_get_epc(i, NULL); 182 * printf("EPC section #%d: address = %x, size = %d bytes.\n", epc.address, epc.size); 183 * } 184 * } else { 185 * printf("SGX is not present.\n"); 186 * } 187 * @endcode 188 */ 189 struct cpu_sgx_t { 190 /** Whether SGX is present (boolean) */ 191 uint32_t present; 192 193 /** Max enclave size in 32-bit mode. This is a power-of-two value: 194 * if it is "31", then the max enclave size is 2^31 bytes (2 GiB). 195 */ 196 uint8_t max_enclave_32bit; 197 198 /** Max enclave size in 64-bit mode. This is a power-of-two value: 199 * if it is "36", then the max enclave size is 2^36 bytes (64 GiB). 200 */ 201 uint8_t max_enclave_64bit; 202 203 /** 204 * contains SGX feature flags. See the \ref cpu_sgx_feature_t 205 * "INTEL_SGX*" macros below. 206 */ 207 uint8_t flags[SGX_FLAGS_MAX]; 208 209 /** number of Enclave Page Cache (EPC) sections. Info for each 210 * section is available through the \ref cpuid_get_epc() function 211 */ 212 int num_epc_sections; 213 214 /** bit vector of the supported extended features that can be written 215 * to the MISC region of the SSA (Save State Area) 216 */ 217 uint32_t misc_select; 218 219 /** a bit vector of the attributes that can be set to SECS.ATTRIBUTES 220 * via ECREATE. Corresponds to bits 0-63 (incl.) of SECS.ATTRIBUTES. 221 */ 222 uint64_t secs_attributes; 223 224 /** a bit vector of the bits that can be set in the XSAVE feature 225 * request mask; Corresponds to bits 64-127 of SECS.ATTRIBUTES. 226 */ 227 uint64_t secs_xfrm; 228 }; 229 230 /** 231 * @brief This contains the recognized CPU features/info 232 */ 233 struct cpu_id_t { 234 /** contains the CPU vendor string, e.g. "GenuineIntel" */ 235 char vendor_str[VENDOR_STR_MAX]; 236 237 /** contains the brand string, e.g. "Intel(R) Xeon(TM) CPU 2.40GHz" */ 238 char brand_str[BRAND_STR_MAX]; 239 240 /** contains the recognized CPU vendor */ 241 cpu_vendor_t vendor; 242 243 /** 244 * contain CPU flags. Used to test for features. See 245 * the \ref cpu_feature_t "CPU_FEATURE_*" macros below. 246 * @see Features 247 */ 248 uint8_t flags[CPU_FLAGS_MAX]; 249 250 /** CPU family */ 251 int32_t family; 252 253 /** CPU model */ 254 int32_t model; 255 256 /** CPU stepping */ 257 int32_t stepping; 258 259 /** CPU extended family */ 260 int32_t ext_family; 261 262 /** CPU extended model */ 263 int32_t ext_model; 264 265 /** Number of CPU cores on the current processor */ 266 int32_t num_cores; 267 268 /** 269 * Number of logical processors on the current processor. 270 * Could be more than the number of physical cores, 271 * e.g. when the processor has HyperThreading. 272 */ 273 int32_t num_logical_cpus; 274 275 /** 276 * The total number of logical processors. 277 * The same value is available through \ref cpuid_get_total_cpus. 278 * 279 * This is num_logical_cpus * {total physical processors in the system} 280 * (but only on a real system, under a VM this number may be lower). 281 * 282 * If you're writing a multithreaded program and you want to run it on 283 * all CPUs, this is the number of threads you need. 284 * 285 * @note in a VM, this will exactly match the number of CPUs set in 286 * the VM's configuration. 287 * 288 */ 289 int32_t total_logical_cpus; 290 291 /** 292 * L1 data cache size in KB. Could be zero, if the CPU lacks cache. 293 * If the size cannot be determined, it will be -1. 294 */ 295 int32_t l1_data_cache; 296 297 /** 298 * L1 instruction cache size in KB. Could be zero, if the CPU lacks 299 * cache. If the size cannot be determined, it will be -1. 300 * @note On some Intel CPUs, whose instruction cache is in fact 301 * a trace cache, the size will be expressed in K uOps. 302 */ 303 int32_t l1_instruction_cache; 304 305 /** 306 * L2 cache size in KB. Could be zero, if the CPU lacks L2 cache. 307 * If the size of the cache could not be determined, it will be -1 308 */ 309 int32_t l2_cache; 310 311 /** L3 cache size in KB. Zero on most systems */ 312 int32_t l3_cache; 313 314 /** L4 cache size in KB. Zero on most systems */ 315 int32_t l4_cache; 316 317 /** Cache associativity for the L1 data cache. -1 if undetermined 318 * @deprecated replaced by \ref cpu_id_t::l1_data_assoc 319 */ 320 int32_t l1_assoc; 321 322 /** Cache associativity for the L1 data cache. -1 if undetermined */ 323 int32_t l1_data_assoc; 324 325 /** Cache associativity for the L1 intruction cache. -1 if undetermined */ 326 int32_t l1_instruction_assoc; 327 328 /** Cache associativity for the L2 cache. -1 if undetermined */ 329 int32_t l2_assoc; 330 331 /** Cache associativity for the L3 cache. -1 if undetermined */ 332 int32_t l3_assoc; 333 334 /** Cache associativity for the L4 cache. -1 if undetermined */ 335 int32_t l4_assoc; 336 337 /** Cache-line size for L1 data cache. -1 if undetermined 338 * @deprecated replaced by \ref cpu_id_t::l1_data_cacheline 339 */ 340 int32_t l1_cacheline; 341 342 /** Cache-line size for L1 data cache. -1 if undetermined */ 343 int32_t l1_data_cacheline; 344 345 /** Cache-line size for L1 intruction cache. -1 if undetermined */ 346 int32_t l1_instruction_cacheline; 347 348 /** Cache-line size for L2 cache. -1 if undetermined */ 349 int32_t l2_cacheline; 350 351 /** Cache-line size for L3 cache. -1 if undetermined */ 352 int32_t l3_cacheline; 353 354 /** Cache-line size for L4 cache. -1 if undetermined */ 355 int32_t l4_cacheline; 356 357 /** 358 * The brief and human-friendly CPU codename, which was recognized.<br> 359 * Examples: 360 * @code 361 * +--------+--------+-------+-------+-------+---------------------------------------+-----------------------+ 362 * | Vendor | Family | Model | Step. | Cache | Brand String | cpu_id_t.cpu_codename | 363 * +--------+--------+-------+-------+-------+---------------------------------------+-----------------------+ 364 * | AMD | 6 | 8 | 0 | 256 | (not available - will be ignored) | "K6-2" | 365 * | Intel | 15 | 2 | 5 | 512 | "Intel(R) Xeon(TM) CPU 2.40GHz" | "Xeon (Prestonia)" | 366 * | Intel | 6 | 15 | 11 | 4096 | "Intel(R) Core(TM)2 Duo CPU E6550..." | "Conroe (Core 2 Duo)" | 367 * | AMD | 15 | 35 | 2 | 1024 | "Dual Core AMD Opteron(tm) Proces..." | "Opteron (Dual Core)" | 368 * +--------+--------+-------+-------+-------+---------------------------------------+-----------------------+ 369 * @endcode 370 */ 371 char cpu_codename[64]; 372 373 /** SSE execution unit size (64 or 128; -1 if N/A) */ 374 int32_t sse_size; 375 376 /** 377 * contain miscellaneous detection information. Used to test about specifics of 378 * certain detected features. See \ref cpu_hint_t "CPU_HINT_*" macros below. 379 * @see Hints 380 */ 381 uint8_t detection_hints[CPU_HINTS_MAX]; 382 383 /** contains information about SGX features if the processor, if present */ 384 struct cpu_sgx_t sgx; 385 }; 386 387 /** 388 * @brief CPU feature identifiers 389 * 390 * Usage: 391 * @code 392 * ... 393 * struct cpu_raw_data_t raw; 394 * struct cpu_id_t id; 395 * if (cpuid_get_raw_data(&raw) == 0 && cpu_identify(&raw, &id) == 0) { 396 * if (id.flags[CPU_FEATURE_SSE2]) { 397 * // The CPU has SSE2... 398 * ... 399 * } else { 400 * // no SSE2 401 * } 402 * } else { 403 * // processor cannot be determined. 404 * } 405 * @endcode 406 */ 407 typedef enum { 408 CPU_FEATURE_FPU = 0, /*!< Floating point unit */ 409 CPU_FEATURE_VME, /*!< Virtual mode extension */ 410 CPU_FEATURE_DE, /*!< Debugging extension */ 411 CPU_FEATURE_PSE, /*!< Page size extension */ 412 CPU_FEATURE_TSC, /*!< Time-stamp counter */ 413 CPU_FEATURE_MSR, /*!< Model-specific regsisters, RDMSR/WRMSR supported */ 414 CPU_FEATURE_PAE, /*!< Physical address extension */ 415 CPU_FEATURE_MCE, /*!< Machine check exception */ 416 CPU_FEATURE_CX8, /*!< CMPXCHG8B instruction supported */ 417 CPU_FEATURE_APIC, /*!< APIC support */ 418 CPU_FEATURE_MTRR, /*!< Memory type range registers */ 419 CPU_FEATURE_SEP, /*!< SYSENTER / SYSEXIT instructions supported */ 420 CPU_FEATURE_PGE, /*!< Page global enable */ 421 CPU_FEATURE_MCA, /*!< Machine check architecture */ 422 CPU_FEATURE_CMOV, /*!< CMOVxx instructions supported */ 423 CPU_FEATURE_PAT, /*!< Page attribute table */ 424 CPU_FEATURE_PSE36, /*!< 36-bit page address extension */ 425 CPU_FEATURE_PN, /*!< Processor serial # implemented (Intel P3 only) */ 426 CPU_FEATURE_CLFLUSH, /*!< CLFLUSH instruction supported */ 427 CPU_FEATURE_DTS, /*!< Debug store supported */ 428 CPU_FEATURE_ACPI, /*!< ACPI support (power states) */ 429 CPU_FEATURE_MMX, /*!< MMX instruction set supported */ 430 CPU_FEATURE_FXSR, /*!< FXSAVE / FXRSTOR supported */ 431 CPU_FEATURE_SSE, /*!< Streaming-SIMD Extensions (SSE) supported */ 432 CPU_FEATURE_SSE2, /*!< SSE2 instructions supported */ 433 CPU_FEATURE_SS, /*!< Self-snoop */ 434 CPU_FEATURE_HT, /*!< Hyper-threading supported (but might be disabled) */ 435 CPU_FEATURE_TM, /*!< Thermal monitor */ 436 CPU_FEATURE_IA64, /*!< IA64 supported (Itanium only) */ 437 CPU_FEATURE_PBE, /*!< Pending-break enable */ 438 CPU_FEATURE_PNI, /*!< PNI (SSE3) instructions supported */ 439 CPU_FEATURE_PCLMUL, /*!< PCLMULQDQ instruction supported */ 440 CPU_FEATURE_DTS64, /*!< 64-bit Debug store supported */ 441 CPU_FEATURE_MONITOR, /*!< MONITOR / MWAIT supported */ 442 CPU_FEATURE_DS_CPL, /*!< CPL Qualified Debug Store */ 443 CPU_FEATURE_VMX, /*!< Virtualization technology supported */ 444 CPU_FEATURE_SMX, /*!< Safer mode exceptions */ 445 CPU_FEATURE_EST, /*!< Enhanced SpeedStep */ 446 CPU_FEATURE_TM2, /*!< Thermal monitor 2 */ 447 CPU_FEATURE_SSSE3, /*!< SSSE3 instructionss supported (this is different from SSE3!) */ 448 CPU_FEATURE_CID, /*!< Context ID supported */ 449 CPU_FEATURE_CX16, /*!< CMPXCHG16B instruction supported */ 450 CPU_FEATURE_XTPR, /*!< Send Task Priority Messages disable */ 451 CPU_FEATURE_PDCM, /*!< Performance capabilities MSR supported */ 452 CPU_FEATURE_DCA, /*!< Direct cache access supported */ 453 CPU_FEATURE_SSE4_1, /*!< SSE 4.1 instructions supported */ 454 CPU_FEATURE_SSE4_2, /*!< SSE 4.2 instructions supported */ 455 CPU_FEATURE_SYSCALL, /*!< SYSCALL / SYSRET instructions supported */ 456 CPU_FEATURE_XD, /*!< Execute disable bit supported */ 457 CPU_FEATURE_MOVBE, /*!< MOVBE instruction supported */ 458 CPU_FEATURE_POPCNT, /*!< POPCNT instruction supported */ 459 CPU_FEATURE_AES, /*!< AES* instructions supported */ 460 CPU_FEATURE_XSAVE, /*!< XSAVE/XRSTOR/etc instructions supported */ 461 CPU_FEATURE_OSXSAVE, /*!< non-privileged copy of OSXSAVE supported */ 462 CPU_FEATURE_AVX, /*!< Advanced vector extensions supported */ 463 CPU_FEATURE_MMXEXT, /*!< AMD MMX-extended instructions supported */ 464 CPU_FEATURE_3DNOW, /*!< AMD 3DNow! instructions supported */ 465 CPU_FEATURE_3DNOWEXT, /*!< AMD 3DNow! extended instructions supported */ 466 CPU_FEATURE_NX, /*!< No-execute bit supported */ 467 CPU_FEATURE_FXSR_OPT, /*!< FFXSR: FXSAVE and FXRSTOR optimizations */ 468 CPU_FEATURE_RDTSCP, /*!< RDTSCP instruction supported (AMD-only) */ 469 CPU_FEATURE_LM, /*!< Long mode (x86_64/EM64T) supported */ 470 CPU_FEATURE_LAHF_LM, /*!< LAHF/SAHF supported in 64-bit mode */ 471 CPU_FEATURE_CMP_LEGACY, /*!< core multi-processing legacy mode */ 472 CPU_FEATURE_SVM, /*!< AMD Secure virtual machine */ 473 CPU_FEATURE_ABM, /*!< LZCNT instruction support */ 474 CPU_FEATURE_MISALIGNSSE,/*!< Misaligned SSE supported */ 475 CPU_FEATURE_SSE4A, /*!< SSE 4a from AMD */ 476 CPU_FEATURE_3DNOWPREFETCH, /*!< PREFETCH/PREFETCHW support */ 477 CPU_FEATURE_OSVW, /*!< OS Visible Workaround (AMD) */ 478 CPU_FEATURE_IBS, /*!< Instruction-based sampling */ 479 CPU_FEATURE_SSE5, /*!< SSE 5 instructions supported (deprecated, will never be 1) */ 480 CPU_FEATURE_SKINIT, /*!< SKINIT / STGI supported */ 481 CPU_FEATURE_WDT, /*!< Watchdog timer support */ 482 CPU_FEATURE_TS, /*!< Temperature sensor */ 483 CPU_FEATURE_FID, /*!< Frequency ID control */ 484 CPU_FEATURE_VID, /*!< Voltage ID control */ 485 CPU_FEATURE_TTP, /*!< THERMTRIP */ 486 CPU_FEATURE_TM_AMD, /*!< AMD-specified hardware thermal control */ 487 CPU_FEATURE_STC, /*!< Software thermal control */ 488 CPU_FEATURE_100MHZSTEPS,/*!< 100 MHz multiplier control */ 489 CPU_FEATURE_HWPSTATE, /*!< Hardware P-state control */ 490 CPU_FEATURE_CONSTANT_TSC, /*!< TSC ticks at constant rate */ 491 CPU_FEATURE_XOP, /*!< The XOP instruction set (same as the old CPU_FEATURE_SSE5) */ 492 CPU_FEATURE_FMA3, /*!< The FMA3 instruction set */ 493 CPU_FEATURE_FMA4, /*!< The FMA4 instruction set */ 494 CPU_FEATURE_TBM, /*!< Trailing bit manipulation instruction support */ 495 CPU_FEATURE_F16C, /*!< 16-bit FP convert instruction support */ 496 CPU_FEATURE_RDRAND, /*!< RdRand instruction */ 497 CPU_FEATURE_X2APIC, /*!< x2APIC, APIC_BASE.EXTD, MSRs 0000_0800h...0000_0BFFh 64-bit ICR (+030h but not +031h), no DFR (+00Eh), SELF_IPI (+040h) also see standard level 0000_000Bh */ 498 CPU_FEATURE_CPB, /*!< Core performance boost */ 499 CPU_FEATURE_APERFMPERF, /*!< MPERF/APERF MSRs support */ 500 CPU_FEATURE_PFI, /*!< Processor Feedback Interface support */ 501 CPU_FEATURE_PA, /*!< Processor accumulator */ 502 CPU_FEATURE_AVX2, /*!< AVX2 instructions */ 503 CPU_FEATURE_BMI1, /*!< BMI1 instructions */ 504 CPU_FEATURE_BMI2, /*!< BMI2 instructions */ 505 CPU_FEATURE_HLE, /*!< Hardware Lock Elision prefixes */ 506 CPU_FEATURE_RTM, /*!< Restricted Transactional Memory instructions */ 507 CPU_FEATURE_AVX512F, /*!< AVX-512 Foundation */ 508 CPU_FEATURE_AVX512DQ, /*!< AVX-512 Double/Quad granular insns */ 509 CPU_FEATURE_AVX512PF, /*!< AVX-512 Prefetch */ 510 CPU_FEATURE_AVX512ER, /*!< AVX-512 Exponential/Reciprocal */ 511 CPU_FEATURE_AVX512CD, /*!< AVX-512 Conflict detection */ 512 CPU_FEATURE_SHA_NI, /*!< SHA-1/SHA-256 instructions */ 513 CPU_FEATURE_AVX512BW, /*!< AVX-512 Byte/Word granular insns */ 514 CPU_FEATURE_AVX512VL, /*!< AVX-512 128/256 vector length extensions */ 515 CPU_FEATURE_SGX, /*!< SGX extensions. Non-autoritative, check cpu_id_t::sgx::present to verify presence */ 516 CPU_FEATURE_RDSEED, /*!< RDSEED instruction */ 517 CPU_FEATURE_ADX, /*!< ADX extensions (arbitrary precision) */ 518 CPU_FEATURE_AVX512VNNI, /*!< AVX-512 Vector Neural Network Instructions */ 519 CPU_FEATURE_AVX512VBMI, /*!< AVX-512 Vector Bit ManipulationInstructions (version 1) */ 520 CPU_FEATURE_AVX512VBMI2, /*!< AVX-512 Vector Bit ManipulationInstructions (version 2) */ 521 /* termination: */ 522 NUM_CPU_FEATURES, 523 } cpu_feature_t; 524 525 /** 526 * @brief CPU detection hints identifiers 527 * 528 * Usage: similar to the flags usage 529 */ 530 typedef enum { 531 CPU_HINT_SSE_SIZE_AUTH = 0, /*!< SSE unit size is authoritative (not only a Family/Model guesswork, but based on an actual CPUID bit) */ 532 /* termination */ 533 NUM_CPU_HINTS, 534 } cpu_hint_t; 535 536 /** 537 * @brief SGX features flags 538 * \see cpu_sgx_t 539 * 540 * Usage: 541 * @code 542 * ... 543 * struct cpu_raw_data_t raw; 544 * struct cpu_id_t id; 545 * if (cpuid_get_raw_data(&raw) == 0 && cpu_identify(&raw, &id) == 0 && id.sgx.present) { 546 * if (id.sgx.flags[INTEL_SGX1]) 547 * // The CPU has SGX1 instructions support... 548 * ... 549 * } else { 550 * // no SGX 551 * } 552 * } else { 553 * // processor cannot be determined. 554 * } 555 * @endcode 556 */ 557 558 typedef enum { 559 INTEL_SGX1, /*!< SGX1 instructions support */ 560 INTEL_SGX2, /*!< SGX2 instructions support */ 561 562 /* termination: */ 563 NUM_SGX_FEATURES, 564 } cpu_sgx_feature_t; 565 566 /** 567 * @brief Describes common library error codes 568 */ 569 typedef enum { 570 ERR_OK = 0, /*!< No error */ 571 ERR_NO_CPUID = -1, /*!< CPUID instruction is not supported */ 572 ERR_NO_RDTSC = -2, /*!< RDTSC instruction is not supported */ 573 ERR_NO_MEM = -3, /*!< Memory allocation failed */ 574 ERR_OPEN = -4, /*!< File open operation failed */ 575 ERR_BADFMT = -5, /*!< Bad file format */ 576 ERR_NOT_IMP = -6, /*!< Not implemented */ 577 ERR_CPU_UNKN = -7, /*!< Unsupported processor */ 578 ERR_NO_RDMSR = -8, /*!< RDMSR instruction is not supported */ 579 ERR_NO_DRIVER= -9, /*!< RDMSR driver error (generic) */ 580 ERR_NO_PERMS = -10, /*!< No permissions to install RDMSR driver */ 581 ERR_EXTRACT = -11, /*!< Cannot extract RDMSR driver (read only media?) */ 582 ERR_HANDLE = -12, /*!< Bad handle */ 583 ERR_INVMSR = -13, /*!< Invalid MSR */ 584 ERR_INVCNB = -14, /*!< Invalid core number */ 585 ERR_HANDLE_R = -15, /*!< Error on handle read */ 586 ERR_INVRANGE = -16, /*!< Invalid given range */ 587 } cpu_error_t; 588 589 /** 590 * @brief Internal structure, used in cpu_tsc_mark, cpu_tsc_unmark and 591 * cpu_clock_by_mark 592 */ 593 struct cpu_mark_t { 594 uint64_t tsc; /*!< Time-stamp from RDTSC */ 595 uint64_t sys_clock; /*!< In microsecond resolution */ 596 }; 597 598 /** 599 * @brief Returns the total number of logical CPU threads (even if CPUID is not present). 600 * 601 * Under VM, this number (and total_logical_cpus, since they are fetched with the same code) 602 * may be nonsensical, i.e. might not equal NumPhysicalCPUs*NumCoresPerCPU*HyperThreading. 603 * This is because no matter how many logical threads the host machine has, you may limit them 604 * in the VM to any number you like. **This** is the number returned by cpuid_get_total_cpus(). 605 * 606 * @returns Number of logical CPU threads available. Equals the \ref cpu_id_t::total_logical_cpus. 607 */ 608 int cpuid_get_total_cpus(void); 609 610 /** 611 * @brief Checks if the CPUID instruction is supported 612 * @retval 1 if CPUID is present 613 * @retval 0 the CPU doesn't have CPUID. 614 */ 615 int cpuid_present(void); 616 617 /** 618 * @brief Executes the CPUID instruction 619 * @param eax - the value of the EAX register when executing CPUID 620 * @param regs - the results will be stored here. regs[0] = EAX, regs[1] = EBX, ... 621 * @note CPUID will be executed with EAX set to the given value and EBX, ECX, 622 * EDX set to zero. 623 */ 624 void cpu_exec_cpuid(uint32_t eax, uint32_t* regs); 625 626 /** 627 * @brief Executes the CPUID instruction with the given input registers 628 * @note This is just a bit more generic version of cpu_exec_cpuid - it allows 629 * you to control all the registers. 630 * @param regs - Input/output. Prior to executing CPUID, EAX, EBX, ECX and 631 * EDX will be set to regs[0], regs[1], regs[2] and regs[3]. 632 * After CPUID, this array will contain the results. 633 */ 634 void cpu_exec_cpuid_ext(uint32_t* regs); 635 636 /** 637 * @brief Obtains the raw CPUID data from the current CPU 638 * @param data - a pointer to cpu_raw_data_t structure 639 * @returns zero if successful, and some negative number on error. 640 * The error message can be obtained by calling \ref cpuid_error. 641 * @see cpu_error_t 642 */ 643 int cpuid_get_raw_data(struct cpu_raw_data_t* data); 644 645 /** 646 * @brief Writes the raw CPUID data to a text file 647 * @param data - a pointer to cpu_raw_data_t structure 648 * @param filename - the path of the file, where the serialized data should be 649 * written. If empty, stdout will be used. 650 * @note This is intended primarily for debugging. On some processor, which is 651 * not currently supported or not completely recognized by cpu_identify, 652 * one can still successfully get the raw data and write it to a file. 653 * libcpuid developers can later import this file and debug the detection 654 * code as if running on the actual hardware. 655 * The file is simple text format of "something=value" pairs. Version info 656 * is also written, but the format is not intended to be neither backward- 657 * nor forward compatible. 658 * @returns zero if successful, and some negative number on error. 659 * The error message can be obtained by calling \ref cpuid_error. 660 * @see cpu_error_t 661 */ 662 int cpuid_serialize_raw_data(struct cpu_raw_data_t* data, const char* filename); 663 664 /** 665 * @brief Reads raw CPUID data from file 666 * @param data - a pointer to cpu_raw_data_t structure. The deserialized data will 667 * be written here. 668 * @param filename - the path of the file, containing the serialized raw data. 669 * If empty, stdin will be used. 670 * @note This function may fail, if the file is created by different version of 671 * the library. Also, see the notes on cpuid_serialize_raw_data. 672 * @returns zero if successful, and some negative number on error. 673 * The error message can be obtained by calling \ref cpuid_error. 674 * @see cpu_error_t 675 */ 676 int cpuid_deserialize_raw_data(struct cpu_raw_data_t* data, const char* filename); 677 678 /** 679 * @brief Identifies the CPU 680 * @param raw - Input - a pointer to the raw CPUID data, which is obtained 681 * either by cpuid_get_raw_data or cpuid_deserialize_raw_data. 682 * Can also be NULL, in which case the functions calls 683 * cpuid_get_raw_data itself. 684 * @param data - Output - the decoded CPU features/info is written here. 685 * @note The function will not fail, even if some of the information 686 * cannot be obtained. Even when the CPU is new and thus unknown to 687 * libcpuid, some generic info, such as "AMD K9 family CPU" will be 688 * written to data.cpu_codename, and most other things, such as the 689 * CPU flags, cache sizes, etc. should be detected correctly anyway. 690 * However, the function CAN fail, if the CPU is completely alien to 691 * libcpuid. 692 * @note While cpu_identify() and cpuid_get_raw_data() are fast for most 693 * purposes, running them several thousand times per second can hamper 694 * performance significantly. Specifically, avoid writing "cpu feature 695 * checker" wrapping function, which calls cpu_identify and returns the 696 * value of some flag, if that function is going to be called frequently. 697 * @returns zero if successful, and some negative number on error. 698 * The error message can be obtained by calling \ref cpuid_error. 699 * @see cpu_error_t 700 */ 701 int cpu_identify(struct cpu_raw_data_t* raw, struct cpu_id_t* data); 702 703 /** 704 * @brief Returns the short textual representation of a CPU flag 705 * @param feature - the feature, whose textual representation is wanted. 706 * @returns a constant string like "fpu", "tsc", "sse2", etc. 707 * @note the names of the returned flags are compatible with those from 708 * /proc/cpuinfo in Linux, with the exception of `tm_amd' 709 */ 710 const char* cpu_feature_str(cpu_feature_t feature); 711 712 /** 713 * @brief Returns textual description of the last error 714 * 715 * libcpuid stores an `errno'-style error status, whose description 716 * can be obtained with this function. 717 * @note This function is not thread-safe 718 * @see cpu_error_t 719 */ 720 const char* cpuid_error(void); 721 722 /** 723 * @brief Executes RDTSC 724 * 725 * The RDTSC (ReaD Time Stamp Counter) instruction gives access to an 726 * internal 64-bit counter, which usually increments at each clock cycle. 727 * This can be used for various timing routines, and as a very precise 728 * clock source. It is set to zero on system startup. Beware that may not 729 * increment at the same frequency as the CPU. Consecutive calls of RDTSC 730 * are, however, guaranteed to return monotonically-increasing values. 731 * 732 * @param result - a pointer to a 64-bit unsigned integer, where the TSC value 733 * will be stored 734 * 735 * @note If 100% compatibility is a concern, you must first check if the 736 * RDTSC instruction is present (if it is not, your program will crash 737 * with "invalid opcode" exception). Only some very old processors (i486, 738 * early AMD K5 and some Cyrix CPUs) lack that instruction - they should 739 * have become exceedingly rare these days. To verify RDTSC presence, 740 * run cpu_identify() and check flags[CPU_FEATURE_TSC]. 741 * 742 * @note The monotonically increasing nature of the TSC may be violated 743 * on SMP systems, if their TSC clocks run at different rate. If the OS 744 * doesn't account for that, the TSC drift may become arbitrary large. 745 */ 746 void cpu_rdtsc(uint64_t* result); 747 748 /** 749 * @brief Store TSC and timing info 750 * 751 * This function stores the current TSC value and current 752 * time info from a precise OS-specific clock source in the cpu_mark_t 753 * structure. The sys_clock field contains time with microsecond resolution. 754 * The values can later be used to measure time intervals, number of clocks, 755 * FPU frequency, etc. 756 * @see cpu_rdtsc 757 * 758 * @param mark [out] - a pointer to a cpu_mark_t structure 759 */ 760 void cpu_tsc_mark(struct cpu_mark_t* mark); 761 762 /** 763 * @brief Calculate TSC and timing difference 764 * 765 * @param mark - input/output: a pointer to a cpu_mark_t structure, which has 766 * already been initialized by cpu_tsc_mark. The difference in 767 * TSC and time will be written here. 768 * 769 * This function calculates the TSC and time difference, by obtaining the 770 * current TSC and timing values and subtracting the contents of the `mark' 771 * structure from them. Results are written in the same structure. 772 * 773 * Example: 774 * @code 775 * ... 776 * struct cpu_mark_t mark; 777 * cpu_tsc_mark(&mark); 778 * foo(); 779 * cpu_tsc_unmark(&mark); 780 * printf("Foo finished. Executed in %llu cycles and %llu usecs\n", 781 * mark.tsc, mark.sys_clock); 782 * ... 783 * @endcode 784 */ 785 void cpu_tsc_unmark(struct cpu_mark_t* mark); 786 787 /** 788 * @brief Calculates the CPU clock 789 * 790 * @param mark - pointer to a cpu_mark_t structure, which has been initialized 791 * with cpu_tsc_mark and later `stopped' with cpu_tsc_unmark. 792 * 793 * @note For reliable results, the marked time interval should be at least about 794 * 10 ms. 795 * 796 * @returns the CPU clock frequency, in MHz. Due to measurement error, it will 797 * differ from the true value in a few least-significant bits. Accuracy depends 798 * on the timing interval - the more, the better. If the timing interval is 799 * insufficient, the result is -1. Also, see the comment on cpu_clock_measure 800 * for additional issues and pitfalls in using RDTSC for CPU frequency 801 * measurements. 802 */ 803 int cpu_clock_by_mark(struct cpu_mark_t* mark); 804 805 /** 806 * @brief Returns the CPU clock, as reported by the OS 807 * 808 * This function uses OS-specific functions to obtain the CPU clock. It may 809 * differ from the true clock for several reasons:<br><br> 810 * 811 * i) The CPU might be in some power saving state, while the OS reports its 812 * full-power frequency, or vice-versa.<br> 813 * ii) In some cases you can raise or lower the CPU frequency with overclocking 814 * utilities and the OS will not notice. 815 * 816 * @returns the CPU clock frequency in MHz. If the OS is not (yet) supported 817 * or lacks the necessary reporting machinery, the return value is -1 818 */ 819 int cpu_clock_by_os(void); 820 821 /** 822 * @brief Measure the CPU clock frequency 823 * 824 * @param millis - How much time to waste in the busy-wait cycle. In millisecs. 825 * Useful values 10 - 1000 826 * @param quad_check - Do a more thorough measurement if nonzero 827 * (see the explanation). 828 * 829 * The function performs a busy-wait cycle for the given time and calculates 830 * the CPU frequency by the difference of the TSC values. The accuracy of the 831 * calculation depends on the length of the busy-wait cycle: more is better, 832 * but 100ms should be enough for most purposes. 833 * 834 * While this will calculate the CPU frequency correctly in most cases, there are 835 * several reasons why it might be incorrect:<br> 836 * 837 * i) RDTSC doesn't guarantee it will run at the same clock as the CPU. 838 * Apparently there aren't CPUs at the moment, but still, there's no 839 * guarantee.<br> 840 * ii) The CPU might be in a low-frequency power saving mode, and the CPU 841 * might be switched to higher frequency at any time. If this happens 842 * during the measurement, the result can be anywhere between the 843 * low and high frequencies. Also, if you're interested in the 844 * high frequency value only, this function might return the low one 845 * instead.<br> 846 * iii) On SMP systems exhibiting TSC drift (see \ref cpu_rdtsc) 847 * 848 * the quad_check option will run four consecutive measurements and 849 * then return the average of the two most-consistent results. The total 850 * runtime of the function will still be `millis' - consider using 851 * a bit more time for the timing interval. 852 * 853 * Finally, for benchmarking / CPU intensive applications, the best strategy is 854 * to use the cpu_tsc_mark() / cpu_tsc_unmark() / cpu_clock_by_mark() method. 855 * Begin by mark()-ing about one second after application startup (allowing the 856 * power-saving manager to kick in and rise the frequency during that time), 857 * then unmark() just before application finishing. The result will most 858 * acurately represent at what frequency your app was running. 859 * 860 * @returns the CPU clock frequency in MHz (within some measurement error 861 * margin). If RDTSC is not supported, the result is -1. 862 */ 863 int cpu_clock_measure(int millis, int quad_check); 864 865 /** 866 * @brief Measure the CPU clock frequency using instruction-counting 867 * 868 * @param millis - how much time to allocate for each run, in milliseconds 869 * @param runs - how many runs to perform 870 * 871 * The function performs a busy-wait cycle using a known number of "heavy" (SSE) 872 * instructions. These instructions run at (more or less guaranteed) 1 IPC rate, 873 * so by running a busy loop for a fixed amount of time, and measuring the 874 * amount of instructions done, the CPU clock is accurately measured. 875 * 876 * Of course, this function is still affected by the power-saving schemes, so 877 * the warnings as of cpu_clock_measure() still apply. However, this function is 878 * immune to problems with detection, related to the Intel Nehalem's "Turbo" 879 * mode, where the internal clock is raised, but the RDTSC rate is unaffected. 880 * 881 * The function will run for about (millis * runs) milliseconds. 882 * You can make only a single busy-wait run (runs == 1); however, this can 883 * be affected by task scheduling (which will break the counting), so allowing 884 * more than one run is recommended. As run length is not imperative for 885 * accurate readings (e.g., 50ms is sufficient), you can afford a lot of short 886 * runs, e.g. 10 runs of 50ms or 20 runs of 25ms. 887 * 888 * Recommended values - millis = 50, runs = 4. For more robustness, 889 * increase the number of runs. 890 * 891 * NOTE: on Bulldozer and later CPUs, the busy-wait cycle runs at 1.4 IPC, thus 892 * the results are skewed. This is corrected internally by dividing the resulting 893 * value by 1.4. 894 * However, this only occurs if the thread is executed on a single CMT 895 * module - if there are other threads competing for resources, the results are 896 * unpredictable. Make sure you run cpu_clock_by_ic() on a CPU that is free from 897 * competing threads, or if there are such threads, they shouldn't exceed the 898 * number of modules. On a Bulldozer X8, that means 4 threads. 899 * 900 * @returns the CPU clock frequency in MHz (within some measurement error 901 * margin). If SSE is not supported, the result is -1. If the input parameters 902 * are incorrect, or some other internal fault is detected, the result is -2. 903 */ 904 int cpu_clock_by_ic(int millis, int runs); 905 906 /** 907 * @brief Get the CPU clock frequency (all-in-one method) 908 * 909 * This is an all-in-one method for getting the CPU clock frequency. 910 * It tries to use the OS for that. If the OS doesn't have this info, it 911 * uses cpu_clock_measure with 200ms time interval and quadruple checking. 912 * 913 * @returns the CPU clock frequency in MHz. If every possible method fails, 914 * the result is -1. 915 */ 916 int cpu_clock(void); 917 918 919 /** 920 * @brief The return value of cpuid_get_epc(). 921 * @details 922 * Describes an EPC (Enclave Page Cache) layout (physical address and size). 923 * A CPU may have one or more EPC areas, and information about each is 924 * fetched via \ref cpuid_get_epc. 925 */ 926 struct cpu_epc_t { 927 uint64_t start_addr; 928 uint64_t length; 929 }; 930 931 /** 932 * @brief Fetches information about an EPC (Enclave Page Cache) area. 933 * @param index - zero-based index, valid range [0..cpu_id_t.egx.num_epc_sections) 934 * @param raw - a pointer to fetched raw CPUID data. Needed only for testing, 935 * you can safely pass NULL here (if you pass a real structure, 936 * it will be used for fetching the leaf 12h data if index < 2; 937 * otherwise the real CPUID instruction will be used). 938 * @returns the requested data. If the CPU doesn't support SGX, or if 939 * index >= cpu_id_t.egx.num_epc_sections, both fields of the returned 940 * structure will be zeros. 941 */ 942 struct cpu_epc_t cpuid_get_epc(int index, const struct cpu_raw_data_t* raw); 943 944 /** 945 * @brief Returns the libcpuid version 946 * 947 * @returns the string representation of the libcpuid version, like "0.1.1" 948 */ 949 const char* cpuid_lib_version(void); 950 951 typedef void (*libcpuid_warn_fn_t) (const char *msg); 952 /** 953 * @brief Sets the warning print function 954 * 955 * In some cases, the internal libcpuid machinery would like to emit useful 956 * debug warnings. By default, these warnings are written to stderr. However, 957 * you can set a custom function that will receive those warnings. 958 * 959 * @param warn_fun - the warning function you want to set. If NULL, warnings 960 * are disabled. The function takes const char* argument. 961 * 962 * @returns the current warning function. You can use the return value to 963 * keep the previous warning function and restore it at your discretion. 964 */ 965 libcpuid_warn_fn_t cpuid_set_warn_function(libcpuid_warn_fn_t warn_fun); 966 967 /** 968 * @brief Sets the verbosiness level 969 * 970 * When the verbosiness level is above zero, some functions might print 971 * diagnostic information about what are they doing. The higher the level is, 972 * the more detail is printed. Level zero is guaranteed to omit all such 973 * output. The output is written using the same machinery as the warnings, 974 * @see cpuid_set_warn_function() 975 * 976 * @param level the desired verbosiness level. Useful values 0..2 inclusive 977 */ 978 void cpuid_set_verbosiness_level(int level); 979 980 981 /** 982 * @brief Obtains the CPU vendor from CPUID from the current CPU 983 * @note The result is cached. 984 * @returns VENDOR_UNKNOWN if failed, otherwise the CPU vendor type. 985 * @see cpu_vendor_t 986 */ 987 cpu_vendor_t cpuid_get_vendor(void); 988 989 /** 990 * @brief a structure that holds a list of processor names 991 */ 992 struct cpu_list_t { 993 /** Number of entries in the list */ 994 int num_entries; 995 /** Pointers to names. There will be num_entries of them */ 996 char **names; 997 }; 998 999 /** 1000 * @brief Gets a list of all known CPU names from a specific vendor. 1001 * 1002 * This function compiles a list of all known CPU (code)names 1003 * (i.e. the possible values of cpu_id_t::cpu_codename) for the given vendor. 1004 * 1005 * There are about 100 entries for Intel and AMD, and a few for the other 1006 * vendors. The list is written out in approximate chronological introduction 1007 * order of the parts. 1008 * 1009 * @param vendor the vendor to be queried 1010 * @param list [out] the resulting list will be written here. 1011 * NOTE: As the memory is dynamically allocated, be sure to call 1012 * cpuid_free_cpu_list() after you're done with the data 1013 * @see cpu_list_t 1014 */ 1015 void cpuid_get_cpu_list(cpu_vendor_t vendor, struct cpu_list_t* list); 1016 1017 /** 1018 * @brief Frees a CPU list 1019 * 1020 * This function deletes all the memory associated with a CPU list, as obtained 1021 * by cpuid_get_cpu_list() 1022 * 1023 * @param list - the list to be free()'d. 1024 */ 1025 void cpuid_free_cpu_list(struct cpu_list_t* list); 1026 1027 struct msr_driver_t; 1028 /** 1029 * @brief Starts/opens a driver, needed to read MSRs (Model Specific Registers) 1030 * 1031 * On systems that support it, this function will create a temporary 1032 * system driver, that has privileges to execute the RDMSR instruction. 1033 * After the driver is created, you can read MSRs by calling \ref cpu_rdmsr 1034 * 1035 * @returns a handle to the driver on success, and NULL on error. 1036 * The error message can be obtained by calling \ref cpuid_error. 1037 * @see cpu_error_t 1038 */ 1039 struct msr_driver_t* cpu_msr_driver_open(void); 1040 1041 /** 1042 * @brief Similar to \ref cpu_msr_driver_open, but accept one parameter 1043 * 1044 * This function works on certain operating systems (GNU/Linux, FreeBSD) 1045 * 1046 * @param core_num specify the core number for MSR. 1047 * The first core number is 0. 1048 * The last core number is \ref cpuid_get_total_cpus - 1. 1049 * 1050 * @returns a handle to the driver on success, and NULL on error. 1051 * The error message can be obtained by calling \ref cpuid_error. 1052 * @see cpu_error_t 1053 */ 1054 struct msr_driver_t* cpu_msr_driver_open_core(unsigned core_num); 1055 1056 /** 1057 * @brief Reads a Model-Specific Register (MSR) 1058 * 1059 * If the CPU has MSRs (as indicated by the CPU_FEATURE_MSR flag), you can 1060 * read a MSR with the given index by calling this function. 1061 * 1062 * There are several prerequisites you must do before reading MSRs: 1063 * 1) You must ensure the CPU has RDMSR. Check the CPU_FEATURE_MSR flag 1064 * in cpu_id_t::flags 1065 * 2) You must ensure that the CPU implements the specific MSR you intend to 1066 * read. 1067 * 3) You must open a MSR-reader driver. RDMSR is a privileged instruction and 1068 * needs ring-0 access in order to work. This temporary driver is created 1069 * by calling \ref cpu_msr_driver_open 1070 * 1071 * @param handle - a handle to the MSR reader driver, as created by 1072 * cpu_msr_driver_open 1073 * @param msr_index - the numeric ID of the MSR you want to read 1074 * @param result - a pointer to a 64-bit integer, where the MSR value is stored 1075 * 1076 * @returns zero if successful, and some negative number on error. 1077 * The error message can be obtained by calling \ref cpuid_error. 1078 * @see cpu_error_t 1079 */ 1080 int cpu_rdmsr(struct msr_driver_t* handle, uint32_t msr_index, uint64_t* result); 1081 1082 1083 typedef enum { 1084 INFO_MPERF, /*!< Maximum performance frequency clock. This 1085 is a counter, which increments as a 1086 proportion of the actual processor speed. */ 1087 INFO_APERF, /*!< Actual performance frequency clock. This 1088 accumulates the core clock counts when the 1089 core is active. */ 1090 INFO_MIN_MULTIPLIER, /*!< Minimum CPU:FSB ratio for this CPU, 1091 multiplied by 100. */ 1092 INFO_CUR_MULTIPLIER, /*!< Current CPU:FSB ratio, multiplied by 100. 1093 e.g., a CPU:FSB value of 18.5 reads as 1094 "1850". */ 1095 INFO_MAX_MULTIPLIER, /*!< Maximum CPU:FSB ratio for this CPU, 1096 multiplied by 100. */ 1097 INFO_TEMPERATURE, /*!< The current core temperature in Celsius. */ 1098 INFO_THROTTLING, /*!< 1 if the current logical processor is 1099 throttling. 0 if it is running normally. */ 1100 INFO_VOLTAGE, /*!< The current core voltage in Volt, 1101 multiplied by 100. */ 1102 INFO_BCLK, /*!< See \ref INFO_BUS_CLOCK. */ 1103 INFO_BUS_CLOCK, /*!< The main bus clock in MHz, 1104 e.g., FSB/QPI/DMI/HT base clock, 1105 multiplied by 100. */ 1106 } cpu_msrinfo_request_t; 1107 1108 /** 1109 * @brief Similar to \ref cpu_rdmsr, but extract a range of bits 1110 * 1111 * @param handle - a handle to the MSR reader driver, as created by 1112 * cpu_msr_driver_open 1113 * @param msr_index - the numeric ID of the MSR you want to read 1114 * @param highbit - the high bit in range, must be inferior to 64 1115 * @param lowbit - the low bit in range, must be equal or superior to 0 1116 * @param result - a pointer to a 64-bit integer, where the MSR value is stored 1117 * 1118 * @returns zero if successful, and some negative number on error. 1119 * The error message can be obtained by calling \ref cpuid_error. 1120 * @see cpu_error_t 1121 */ 1122 int cpu_rdmsr_range(struct msr_driver_t* handle, uint32_t msr_index, uint8_t highbit, 1123 uint8_t lowbit, uint64_t* result); 1124 1125 /** 1126 * @brief Reads extended CPU information from Model-Specific Registers. 1127 * @param handle - a handle to an open MSR driver, @see cpu_msr_driver_open 1128 * @param which - which info field should be returned. A list of 1129 * available information entities is listed in the 1130 * cpu_msrinfo_request_t enum. 1131 * @retval - if the requested information is available for the current 1132 * processor model, the respective value is returned. 1133 * if no information is available, or the CPU doesn't support 1134 * the query, the special value CPU_INVALID_VALUE is returned 1135 * @note This function is not MT-safe. If you intend to call it from multiple 1136 * threads, guard it through a mutex or a similar primitive. 1137 */ 1138 int cpu_msrinfo(struct msr_driver_t* handle, cpu_msrinfo_request_t which); 1139 #define CPU_INVALID_VALUE 0x3fffffff 1140 1141 /** 1142 * @brief Writes the raw MSR data to a text file 1143 * @param handle - a handle to the MSR reader driver, as created by cpu_msr_driver_open 1144 * @param filename - the path of the file, where the serialized data should be 1145 * written. If empty, stdout will be used. 1146 * @note This is intended primarily for debugging. On some processor, which is 1147 * not currently supported or not completely recognized by cpu_identify, 1148 * one can still successfully get the raw data and write it to a file. 1149 * libcpuid developers can later import this file and debug the detection 1150 * code as if running on the actual hardware. 1151 * The file is simple text format of "something=value" pairs. Version info 1152 * is also written, but the format is not intended to be neither backward- 1153 * nor forward compatible. 1154 * @returns zero if successful, and some negative number on error. 1155 * The error message can be obtained by calling \ref cpuid_error. 1156 * @see cpu_error_t 1157 */ 1158 int msr_serialize_raw_data(struct msr_driver_t* handle, const char* filename); 1159 1160 /** 1161 * @brief Closes an open MSR driver 1162 * 1163 * This function unloads the MSR driver opened by cpu_msr_driver_open and 1164 * frees any resources associated with it. 1165 * 1166 * @param handle - a handle to the MSR reader driver, as created by cpu_msr_driver_open 1167 * 1168 * @returns zero if successful, and some negative number on error. 1169 * The error message can be obtained by calling \ref cpuid_error. 1170 * @see cpu_error_t 1171 */ 1172 int cpu_msr_driver_close(struct msr_driver_t* handle); 1173 1174 #ifdef __cplusplus 1175 } /* extern "C" */ 1176 #endif 1177 1178 1179 /** @} */ 1180 1181 #endif /* __LIBCPUID_H__ */ 1182