You cannot select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
				
	
	
		
			202 lines
		
	
	
		
			9.1 KiB
		
	
	
	
		
			C++
		
	
			
		
		
	
	
			202 lines
		
	
	
		
			9.1 KiB
		
	
	
	
		
			C++
		
	
| /*! \file
 | |
|  * \brief \ref CPUID queries information about the processor
 | |
|  */
 | |
| #pragma once
 | |
| #include "../types.h"
 | |
| 
 | |
| /*! \brief Query information about the processor
 | |
|  *
 | |
|  * \note This is an interface to the `cpuid` instruction, which can return
 | |
|  * information about the processor. It should therefor **not** be confused with
 | |
|  * functionality to
 | |
|  * \ref Core::getID() "retrieve the ID of the current CPU (core)"!
 | |
|  */
 | |
| namespace CPUID {
 | |
| 
 | |
| /*! \brief Structure for register values returned by `cpuid` instruction
 | |
|  */
 | |
| union Reg {
 | |
|   struct {
 | |
|     uint32_t ebx, edx, ecx, eax;
 | |
|   };
 | |
|   char value[16];
 | |
| };
 | |
| 
 | |
| enum Function {
 | |
|   HIGHEST_FUNCTION_PARAMETER = 0x0,  ///< Maximum Input Value for Basic CPUID
 | |
|                                      ///< Information (in register `eax`)
 | |
|   MANUFACTURER_ID = 0x0,  ///< CPU String (in register `ebx`, `ecx` and `edx`)
 | |
|   PROCESSOR_INFO = 0x1,   ///< Version Information like Type, Family, Model (in
 | |
|                           ///< register `eax`)
 | |
|   FEATURE_BITS = 0x1,     ///< Feature Information (in register `ecx` and `edx`)
 | |
|   CACHE_INFORMATION = 0x2,        ///< Cache and TLB Information
 | |
|   PROCESSOR_SERIAL_NUMBER = 0x3,  ///< deprecated
 | |
|   HIGHEST_EXTENDED_FUNCTION =
 | |
|       0x80000000,  ///< Maximum Input Value for Extended Function CPUID (in
 | |
|                    ///< register `eax`)
 | |
|   EXTENDED_PROCESSOR_INFO = 0x80000001,    ///< Extended Processor Signature and
 | |
|                                            ///< Feature Bits (in register `eax`)
 | |
|   EXTENDED_FEATURE_BITS = 0x80000001,      ///< Extended Feature Information (in
 | |
|                                            ///< register `ecx` and `edx`)
 | |
|   PROCESSOR_BRAND_STRING_1 = 0x80000002,   ///< Processor Brand String (1/3)
 | |
|   PROCESSOR_BRAND_STRING_2 = 0x80000003,   ///< Processor Brand String (2/3)
 | |
|   PROCESSOR_BRAND_STRING_3 = 0x80000004,   ///< Processor Brand String (3/3)
 | |
|   ADVANCED_POWER_MANAGEMENT = 0x80000007,  ///< Advanced Power Management (with
 | |
|                                            ///< Invariant TSC in register `edx`)
 | |
|   ADDRESS_SIZES =
 | |
|       0x80000008,  ///< Linear/Physical Address size (in register `eax`)
 | |
| };
 | |
| 
 | |
| /*! \brief Get CPU identification and feature information
 | |
|  *
 | |
|  * \param eax Requested feature
 | |
|  * \return Register values filled by instruction `cpuid` for the requested
 | |
|  * feature
 | |
|  *
 | |
|  * \see [ISDMv2, Chapter 3. CPUID - CPU
 | |
|  * Identification](intel_manual_vol2.pdf#page=292)
 | |
|  */
 | |
| inline Reg get(Function eax) {
 | |
|   Reg r;
 | |
|   asm volatile("cpuid \n\t"
 | |
|                : "=a"(r.eax), "=b"(r.ebx), "=c"(r.ecx), "=d"(r.edx)
 | |
|                : "0"(eax));
 | |
|   return r;
 | |
| }
 | |
| 
 | |
| enum FeatureECX {
 | |
|   FEATURE_SSE3 = 1 << 0,     ///< Prescott New Instructions-SSE3 (PNI)
 | |
|   FEATURE_PCLMUL = 1 << 1,   ///< Carry-less Multiplication
 | |
|   FEATURE_DTES64 = 1 << 2,   ///< 64-bit debug store (edx bit 21)
 | |
|   FEATURE_MONITOR = 1 << 3,  ///< MONITOR and MWAIT instructions (SSE3)
 | |
|   FEATURE_DS_CPL = 1 << 4,   ///< CPL qualified debug store
 | |
|   FEATURE_VMX = 1 << 5,      ///< Virtual Machine eXtensions
 | |
|   FEATURE_SMX = 1 << 6,      ///< Safer Mode Extensions (LaGrande)
 | |
|   FEATURE_EST = 1 << 7,      ///< Enhanced SpeedStep
 | |
|   FEATURE_TM2 = 1 << 8,      ///< Thermal Monitor 2
 | |
|   FEATURE_SSSE3 = 1 << 9,    ///< Supplemental SSE3 instructions
 | |
|   FEATURE_CID = 1 << 10,     ///< L1 Context ID
 | |
|   FEATURE_SDBG = 1 << 11,    ///< Silicon Debug interface
 | |
|   FEATURE_FMA = 1 << 12,     ///< Fused multiply-add (FMA3)
 | |
|   FEATURE_CX16 = 1 << 13,    ///< CMPXCHG16B instruction
 | |
|   FEATURE_ETPRD = 1 << 14,   ///< Can disable sending task priority messages
 | |
|   FEATURE_PDCM = 1 << 15,    ///< Perfmon & debug capability
 | |
|   FEATURE_PCIDE = 1 << 17,   ///< Process context identifiers (CR4 bit 17)
 | |
|   FEATURE_DCA = 1 << 18,     ///< Direct cache access for DMA writes
 | |
|   FEATURE_SSE4_1 = 1 << 19,  ///< SSE4.1 instructions
 | |
|   FEATURE_SSE4_2 = 1 << 20,  ///< SSE4.2 instructions
 | |
|   FEATURE_X2APIC = 1 << 21,  ///< x2APIC
 | |
|   FEATURE_MOVBE = 1 << 22,   ///< MOVBE instruction (big-endian)
 | |
|   FEATURE_POPCNT = 1 << 23,  ///< POPCNT instruction
 | |
|   FEATURE_TSC_DEADLINE =
 | |
|       1
 | |
|       << 24,  ///< APIC implements one-shot operation using a TSC deadline value
 | |
|   FEATURE_AES = 1 << 25,      ///< AES instruction set
 | |
|   FEATURE_XSAVE = 1 << 26,    ///< XSAVE, XRESTOR, XSETBV, XGETBV
 | |
|   FEATURE_OSXSAVE = 1 << 27,  ///< XSAVE enabled by OS
 | |
|   FEATURE_AVX = 1 << 28,      ///< Advanced Vector Extensions
 | |
|   FEATURE_F16C = 1 << 29,     ///< F16C (half-precision) FP feature
 | |
|   FEATURE_RDRND =
 | |
|       1 << 30,  ///< RDRAND (on-chip random number generator) feature
 | |
|   FEATURE_HYPERVISOR =
 | |
|       1 << 31  ///< Hypervisor present (always zero on physical CPUs)
 | |
| };
 | |
| 
 | |
| enum FeatureEDX {
 | |
|   FEATURE_FPU = 1 << 0,  ///< Onboard x87 FPU
 | |
|   FEATURE_VME =
 | |
|       1 << 1,  ///< Virtual 8086 mode extensions (such as VIF, VIP, PIV)
 | |
|   FEATURE_DE = 1 << 2,   ///< Debugging extensions (CR4 bit 3)
 | |
|   FEATURE_PSE = 1 << 3,  ///< Page Size Extension
 | |
|   FEATURE_TSC = 1 << 4,  ///< Time Stamp Counter
 | |
|   FEATURE_MSR = 1 << 5,  ///< Model-specific registers
 | |
|   FEATURE_PAE = 1 << 6,  ///< Physical Address Extension
 | |
|   FEATURE_MCE = 1 << 7,  ///< Machine Check Exception
 | |
|   FEATURE_CX8 = 1 << 8,  ///< CMPXCHG8 (compare-and-swap) instruction
 | |
|   FEATURE_APIC =
 | |
|       1 << 9,  ///< Onboard Advanced Programmable Interrupt Controller
 | |
|   FEATURE_SEP = 1 << 11,    ///< SYSENTER and SYSEXIT instructions
 | |
|   FEATURE_MTRR = 1 << 12,   ///< Memory Type Range Registers
 | |
|   FEATURE_PGE = 1 << 13,    ///< Page Global Enable bit in CR4
 | |
|   FEATURE_MCA = 1 << 14,    ///< Machine check architecture
 | |
|   FEATURE_CMOV = 1 << 15,   ///< Conditional move and FCMOV instructions
 | |
|   FEATURE_PAT = 1 << 16,    ///< Page Attribute Table
 | |
|   FEATURE_PSE36 = 1 << 17,  ///< 36-bit page size extension
 | |
|   FEATURE_PSN = 1 << 18,    ///< Processor Serial Number
 | |
|   FEATURE_CLF = 1 << 19,    ///< CLFLUSH instruction (SSE2)
 | |
|   FEATURE_DTES = 1 << 21,   ///< Debug store: save trace of executed jumps
 | |
|   FEATURE_ACPI = 1 << 22,   ///< Onboard thermal control MSRs for ACPI
 | |
|   FEATURE_MMX = 1 << 23,    ///< MMX instructions
 | |
|   FEATURE_FXSR = 1 << 24,   ///< FXSAVE, FXRESTOR instructions, CR4 bit 9
 | |
|   FEATURE_SSE = 1 << 25,  ///< SSE instructions (a.k.a. Katmai New Instructions)
 | |
|   FEATURE_SSE2 = 1 << 26,  ///< SSE2 instructions
 | |
|   FEATURE_SS = 1 << 27,    ///< CPU cache implements self-snoop
 | |
|   FEATURE_HTT = 1 << 28,   ///< Hyper-threading
 | |
|   FEATURE_TM1 = 1 << 29,   ///< Thermal monitor automatically limits temperature
 | |
|   FEATURE_IA64 = 1 << 30,  ///< IA64 processor emulating x86
 | |
|   FEATURE_PBE = 1 << 31  ///< Pending Break Enable (PBE# pin) wakeup capability
 | |
| };
 | |
| 
 | |
| enum ExtendedFeatureEDX {
 | |
|   EXTENDED_FEATURE_FPU = 1 << 0,  ///< Onboard x87 FPU
 | |
|   EXTENDED_FEATURE_VME =
 | |
|       1 << 1,  ///< Virtual 8086 mode extensions (such as VIF, VIP, PIV)
 | |
|   EXTENDED_FEATURE_DE = 1 << 2,   ///< Debugging extensions (CR4 bit 3)
 | |
|   EXTENDED_FEATURE_PSE = 1 << 3,  ///< Page Size Extension
 | |
|   EXTENDED_FEATURE_TSC = 1 << 4,  ///< Time Stamp Counter
 | |
|   EXTENDED_FEATURE_MSR = 1 << 5,  ///< Model-specific registers
 | |
|   EXTENDED_FEATURE_PAE = 1 << 6,  ///< Physical Address Extension
 | |
|   EXTENDED_FEATURE_MCE = 1 << 7,  ///< Machine Check Exception
 | |
|   EXTENDED_FEATURE_CX8 = 1 << 8,  ///< CMPXCHG8 (compare-and-swap) instruction
 | |
|   EXTENDED_FEATURE_APIC =
 | |
|       1 << 9,  ///< Onboard Advanced Programmable Interrupt Controller
 | |
|   EXTENDED_FEATURE_SYSCALL = 1 << 11,  ///< SYSCALL and SYSRET instructions
 | |
|   EXTENDED_FEATURE_MTRR = 1 << 12,     ///< Memory Type Range Registers
 | |
|   EXTENDED_FEATURE_PGE = 1 << 13,      ///< Page Global Enable bit in CR4
 | |
|   EXTENDED_FEATURE_MCA = 1 << 14,      ///< Machine check architecture
 | |
|   EXTENDED_FEATURE_CMOV = 1 << 15,  ///< Conditional move and FCMOV instructions
 | |
|   EXTENDED_FEATURE_PAT = 1 << 16,   ///< Page Attribute Table
 | |
|   EXTENDED_FEATURE_PSE36 = 1 << 17,   ///< 36-bit page size extension
 | |
|   EXTENDED_FEATURE_MP = 1 << 19,      ///< Multiprocessor Capable
 | |
|   EXTENDED_FEATURE_NX = 1 << 20,      ///< Non-executable bit
 | |
|   EXTENDED_FEATURE_MMXEXT = 1 << 22,  ///< extended MMX instructions
 | |
|   EXTENDED_FEATURE_MMX = 1 << 23,     ///< MMX instructions
 | |
|   EXTENDED_FEATURE_FXSR = 1
 | |
|                           << 24,  ///< FXSAVE, FXRESTOR instructions, CR4 bit 9
 | |
|   EXTENDED_FEATURE_FXSR_OPT = 1 << 25,  ///< FXSAVE, FXRESTOR optimizations
 | |
|   EXTENDED_FEATURE_PDPE1GB = 1 << 26,   ///< Gibibyte Pages
 | |
|   EXTENDED_FEATURE_RDTSCP = 1 << 27,    ///< CPU cache implements self-snoop
 | |
|   EXTENDED_FEATURE_LM = 1 << 29,        ///< Long Mode (x64)
 | |
|   EXTENDED_FEATURE_3DNOWEXT = 1 << 30,  ///< Extended 3DNow! instructions
 | |
|   EXTENDED_FEATURE_3DNOW = 1 << 31      ///< 3DNow! instructions
 | |
| };
 | |
| 
 | |
| /*! \brief Check if feature is provided by this system
 | |
|  *
 | |
|  * \param feature Feature to test
 | |
|  * \return `true` if available, `false` otherwise
 | |
|  */
 | |
| inline bool has(enum FeatureECX feature) {
 | |
|   return (get(FEATURE_BITS).ecx & feature) != 0;
 | |
| }
 | |
| 
 | |
| /*! \brief Check if feature is provided by this system
 | |
|  *
 | |
|  * \param feature Feature to test
 | |
|  * \return `true` if available, `false` otherwise
 | |
|  */
 | |
| inline bool has(enum FeatureEDX feature) {
 | |
|   return (get(FEATURE_BITS).edx & feature) != 0;
 | |
| }
 | |
| 
 | |
| /*! \brief Check if feature is provided by this system
 | |
|  *
 | |
|  * \param feature Extended feature to test
 | |
|  * \return `true` if available, `false` if either feature or extended features
 | |
|  * are unavailable
 | |
|  */
 | |
| inline bool has(enum ExtendedFeatureEDX feature) {
 | |
|   return (get(EXTENDED_FEATURE_BITS).edx & feature) != 0;
 | |
| }
 | |
| }  // namespace CPUID
 |