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
|