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