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++

/*! \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