Chameleon

Chameleon Svn Source Tree

Root/branches/slice/i386/libsaio/cpuid.h

1/* * cpuid.h * */#ifndef M_CPUID_H#define M_CPUID_H#include <machine/machine_routines.h>#include <pexpert/pexpert.h>#include <i386/proc_reg.h>#include <string.h>#defineCPUID_VID_INTEL"GenuineIntel"#defineCPUID_VID_AMD"AuthenticAMD"#define CPUID_STRING_UNKNOWN "Unknown CPU Typ"#define MSR_CORE_THREAD_COUNT 0x035#define _Bit(n)(1ULL << n)#define _HBit(n)(1ULL << ((n)+32))/* * The CPUID_FEATURE_XXX values define 64-bit values * returned in %ecx:%edx to a CPUID request with %eax of 1: */#defineCPUID_FEATURE_FPU _Bit(0)/* Floating point unit on-chip */#defineCPUID_FEATURE_VME _Bit(1)/* Virtual Mode Extension */#defineCPUID_FEATURE_DE _Bit(2)/* Debugging Extension */#defineCPUID_FEATURE_PSE _Bit(3)/* Page Size Extension */#defineCPUID_FEATURE_TSC _Bit(4)/* Time Stamp Counter */#defineCPUID_FEATURE_MSR _Bit(5)/* Model Specific Registers */#define CPUID_FEATURE_PAE _Bit(6)/* Physical Address Extension */#defineCPUID_FEATURE_MCE _Bit(7)/* Machine Check Exception */#defineCPUID_FEATURE_CX8 _Bit(8)/* CMPXCHG8B */#defineCPUID_FEATURE_APIC _Bit(9)/* On-chip APIC */#define CPUID_FEATURE_SEP _Bit(11)/* Fast System Call */#defineCPUID_FEATURE_MTRR _Bit(12)/* Memory Type Range Register */#defineCPUID_FEATURE_PGE _Bit(13)/* Page Global Enable */#defineCPUID_FEATURE_MCA _Bit(14)/* Machine Check Architecture */#defineCPUID_FEATURE_CMOV _Bit(15)/* Conditional Move Instruction */#define CPUID_FEATURE_PAT _Bit(16)/* Page Attribute Table */#define CPUID_FEATURE_PSE36 _Bit(17)/* 36-bit Page Size Extension */#define CPUID_FEATURE_PSN _Bit(18)/* Processor Serial Number */#define CPUID_FEATURE_CLFSH _Bit(19)/* CLFLUSH Instruction supported */#define CPUID_FEATURE_DS _Bit(21)/* Debug Store */#define CPUID_FEATURE_ACPI _Bit(22)/* Thermal monitor and Clock Ctrl */#define CPUID_FEATURE_MMX _Bit(23)/* MMX supported */#define CPUID_FEATURE_FXSR _Bit(24)/* Fast floating pt save/restore */#define CPUID_FEATURE_SSE _Bit(25)/* Streaming SIMD extensions */#define CPUID_FEATURE_SSE2 _Bit(26)/* Streaming SIMD extensions 2 */#define CPUID_FEATURE_SS _Bit(27)/* Self-Snoop */#define CPUID_FEATURE_HTT _Bit(28)/* Hyper-Threading Technology */#define CPUID_FEATURE_TM _Bit(29)/* Thermal Monitor (TM1) */#define CPUID_FEATURE_PBE _Bit(31)/* Pend Break Enable */#define CPUID_FEATURE_SSE3 _HBit(0)/* Streaming SIMD extensions 3 */#define CPUID_FEATURE_PCLMULQDQ _HBit(1) /* PCLMULQDQ Instruction */#define CPUID_FEATURE_MONITOR _HBit(3)/* Monitor/mwait */#define CPUID_FEATURE_DSCPL _HBit(4)/* Debug Store CPL */#define CPUID_FEATURE_VMX _HBit(5)/* VMX */#define CPUID_FEATURE_SMX _HBit(6)/* SMX */#define CPUID_FEATURE_EST _HBit(7)/* Enhanced SpeedsTep (GV3) */#define CPUID_FEATURE_TM2 _HBit(8)/* Thermal Monitor 2 */#define CPUID_FEATURE_SSSE3 _HBit(9)/* Supplemental SSE3 instructions */#define CPUID_FEATURE_CID _HBit(10)/* L1 Context ID */#define CPUID_FEATURE_CX16 _HBit(13)/* CmpXchg16b instruction */#define CPUID_FEATURE_xTPR _HBit(14)/* Send Task PRiority msgs */#define CPUID_FEATURE_PDCM _HBit(15)/* Perf/Debug Capability MSR */#define CPUID_FEATURE_DCA _HBit(18)/* Direct Cache Access */#define CPUID_FEATURE_SSE4_1 _HBit(19)/* Streaming SIMD extensions 4.1 */#define CPUID_FEATURE_SSE4_2 _HBit(20)/* Streaming SIMD extensions 4.2 */#define CPUID_FEATURE_xAPIC _HBit(21)/* Extended APIC Mode */#define CPUID_FEATURE_POPCNT _HBit(23)/* POPCNT instruction */#define CPUID_FEATURE_AES _HBit(25)/* AES instructions */#define CPUID_FEATURE_VMM _HBit(31)/* VMM (Hypervisor) present *//* * The CPUID_EXTFEATURE_XXX values define 64-bit values * returned in %ecx:%edx to a CPUID request with %eax of 0x80000001: */#define CPUID_EXTFEATURE_SYSCALL _Bit(11)/* SYSCALL/sysret */#define CPUID_EXTFEATURE_XD _Bit(20)/* eXecute Disable */#define CPUID_EXTFEATURE_1GBPAGE _Bit(26) /* 1G-Byte Page support */#define CPUID_EXTFEATURE_RDTSCP _Bit(27)/* RDTSCP */#define CPUID_EXTFEATURE_EM64T _Bit(29)/* Extended Mem 64 Technology *///#define CPUID_EXTFEATURE_LAHF _HBit(20)/* LAFH/SAHF instructions */// New definition with Snow kernel#define CPUID_EXTFEATURE_LAHF _HBit(0)/* LAHF/SAHF instructions *//* * The CPUID_EXTFEATURE_XXX values define 64-bit values * returned in %ecx:%edx to a CPUID request with %eax of 0x80000007: */#define CPUID_EXTFEATURE_TSCI _Bit(8)/* TSC Invariant */#defineCPUID_CACHE_SIZE16/* Number of descriptor values */#define CPUID_MWAIT_EXTENSION_Bit(0)/* enumeration of WMAIT extensions */#define CPUID_MWAIT_BREAK_Bit(1)/* interrupts are break events */#define CPU_MODEL_PENTIUM_M0x0D#define CPU_MODEL_YONAH0x0E#define CPU_MODEL_MEROM0x0F#define CPU_MODEL_PENRYN0x17#define CPU_MODEL_NEHALEM0x1A#define CPU_MODEL_ATOM0x1C#define CPU_MODEL_FIELDS0x1E/* Lynnfield, Clarksfield, Jasper */#define CPU_MODEL_DALES0x1F/* Havendale, Auburndale */#define CPU_MODEL_DALES_32NM0x25/* Clarkdale, Arrandale */#define CPU_MODEL_WESTMERE0x2C/* Gulftown, Westmere-EP, Westmere-WS */#define CPU_MODEL_NEHALEM_EX0x2E#define CPU_MODEL_WESTMERE_EX0x2F#include <stdint.h>#include <mach/mach_types.h>#include <kern/kern_types.h>#include <mach/machine.h>typedef enum { eax, ebx, ecx, edx } cpuid_register_t;static inline voidcpuid(uint32_t *data){__asm__ volatile("cpuid" : "=a" (data[eax]), "=b" (data[ebx]), "=c" (data[ecx]), "=d" (data[edx]) : "a" (data[eax]), "b" (data[ebx]), "c" (data[ecx]), "d" (data[edx]));}static inline voiddo_cpuid(uint32_t selector, uint32_t *data){__asm__ volatile("cpuid" : "=a" (data[0]), "=b" (data[1]), "=c" (data[2]), "=d" (data[3]) : "a"(selector));}/* * Cache ID descriptor structure, used to parse CPUID leaf 2. * Note: not used in kernel. */typedef enum { Lnone, L1I, L1D, L2U, L3U, LCACHE_MAX } cache_type_t ; typedef struct {unsigned charvalue; /* Descriptor value */cache_type_t type; /* Cache type */unsigned int size; /* Cache size */unsigned int linesize; /* Cache line size */const char*description; /* Cache description */} cpuid_cache_desc_t; #define CACHE_DESC(value,type,size,linesize,text) \{ value, type, size, linesize, text }#define _Bit(n) (1ULL << n)//#define _HBit(n) (1ULL << ((n) + 32))#define min(a,b) ((a) < (b) ? (a) : (b))#define quad(hi,lo) (((uint64_t)(hi)) << 32 | (lo))#define bit(n) (1UL << (n))#define bitmask(h,l) ((bit(h) | (bit(h) - 1)) & ~(bit(l) - 1))#define bitfield(x,h,l) (((x) & bitmask(h, l)) >> l)/* Physical CPU info - this is exported out of the kernel (kexts), so be wary of changes */typedef struct {charcpuid_vendor[16];charcpuid_brand_string[48];const char*cpuid_model_string;cpu_type_tcpuid_type;/* this is *not* a cpu_type_t in our <mach/machine.h> */uint8_tcpuid_family;uint8_tcpuid_model;uint8_tcpuid_extmodel;uint8_tcpuid_extfamily;uint8_tcpuid_stepping;uint64_tcpuid_features;uint64_tcpuid_extfeatures;uint32_tcpuid_signature;uint8_t cpuid_brand; uint32_tcache_size[LCACHE_MAX];uint32_tcache_linesize;uint8_tcache_info[64]; /* list of cache descriptors */uint32_tcpuid_cores_per_package;uint32_tcpuid_logical_per_package;uint32_tcache_sharing[LCACHE_MAX];uint32_tcache_partitions[LCACHE_MAX];cpu_type_tcpuid_cpu_type;/* <mach/machine.h> */cpu_subtype_tcpuid_cpu_subtype;/* <mach/machine.h> *//* Monitor/mwait Leaf: */uint32_tcpuid_mwait_linesize_min;uint32_tcpuid_mwait_linesize_max;uint32_tcpuid_mwait_extensions;uint32_tcpuid_mwait_sub_Cstates;/* Thermal and Power Management Leaf: */boolean_tcpuid_thermal_sensor;boolean_tcpuid_thermal_dynamic_acceleration;uint32_tcpuid_thermal_thresholds;boolean_tcpuid_thermal_ACNT_MCNT;/* Architectural Performance Monitoring Leaf: */uint8_tcpuid_arch_perf_version;uint8_tcpuid_arch_perf_number;uint8_tcpuid_arch_perf_width;uint8_tcpuid_arch_perf_events_number;uint32_tcpuid_arch_perf_events;uint8_tcpuid_arch_perf_fixed_number;uint8_tcpuid_arch_perf_fixed_width;/* Cache details: */uint32_tcpuid_cache_linesize;uint32_tcpuid_cache_L2_associativity;uint32_tcpuid_cache_size;/* Virtual and physical address aize: */uint32_tcpuid_address_bits_physical;uint32_tcpuid_address_bits_virtual;uint32_tcpuid_microcode_version;/* Numbers of tlbs per processor [i|d, small|large, level0|level1] */uint32_tcpuid_tlb[2][2][2];#defineTLB_INST0#defineTLB_DATA1#defineTLB_SMALL0#defineTLB_LARGE1uint32_tcpuid_stlb;uint32_tcore_count;uint32_tthread_count;/* Max leaf ids available from CPUID */uint32_tcpuid_max_basic;uint32_tcpuid_max_ext;} i386_cpu_info_t;static i386_cpu_info_t cpuid_cpu_info;static i386_cpu_info_t*cpuid_info(void){return &cpuid_cpu_info;}/*static uint32_t cpuid_count_cores(){uint32_t cpuid_reg[4];do_cpuid(1, cpuid_reg);return bitfield(cpuid_reg[1], 23, 16);}*/static void cpuid_update_generic_info(){ uint32_t cpuid_reg[4]; uint32_t max_extid; char str[128]; char* p;i386_cpu_info_t* info_p = cpuid_info(); /* Get vendor */ do_cpuid(0, cpuid_reg); bcopy((char *)&cpuid_reg[ebx], &info_p->cpuid_vendor[0], 4); /* ug */ bcopy((char *)&cpuid_reg[ecx], &info_p->cpuid_vendor[8], 4); bcopy((char *)&cpuid_reg[edx], &info_p->cpuid_vendor[4], 4); info_p->cpuid_vendor[12] = 0; /* Get extended CPUID results */ do_cpuid(0x80000000, cpuid_reg); max_extid = cpuid_reg[eax]; /* Check to see if we can get the brand string */ if (max_extid >= 0x80000004) { /* * The brand string is up to 48 bytes and is guaranteed to be * NUL terminated. */ do_cpuid(0x80000002, cpuid_reg); bcopy((char *)cpuid_reg, &str[0], 16); do_cpuid(0x80000003, cpuid_reg); bcopy((char *)cpuid_reg, &str[16], 16); do_cpuid(0x80000004, cpuid_reg); bcopy((char *)cpuid_reg, &str[32], 16); for (p = str; *p != '\0'; p++) { if (*p != ' ') break; } strncpy(info_p->cpuid_brand_string, p, sizeof(info_p->cpuid_brand_string)); if (!strncmp(info_p->cpuid_brand_string, CPUID_STRING_UNKNOWN, min(sizeof(info_p->cpuid_brand_string), strlen(CPUID_STRING_UNKNOWN) + 1))) { /* * This string means we have a firmware-programmable brand string, * and the firmware couldn't figure out what sort of CPU we have. */ info_p->cpuid_brand_string[0] = '\0'; } } /* Get cache and addressing info */ if (max_extid >= 0x80000006) { do_cpuid(0x80000006, cpuid_reg); info_p->cpuid_cache_linesize = bitfield(cpuid_reg[ecx], 7, 0); info_p->cpuid_cache_L2_associativity = bitfield(cpuid_reg[ecx], 15, 12); info_p->cpuid_cache_size = bitfield(cpuid_reg[ecx], 31, 16); do_cpuid(0x80000008, cpuid_reg); info_p->cpuid_address_bits_physical = bitfield(cpuid_reg[eax], 7, 0); info_p->cpuid_address_bits_virtual = bitfield(cpuid_reg[eax], 15, 8); } /* Get processor signature and decode */ do_cpuid(1, cpuid_reg); info_p->cpuid_signature = cpuid_reg[eax]; info_p->cpuid_stepping = bitfield(cpuid_reg[eax], 3, 0); info_p->cpuid_model = bitfield(cpuid_reg[eax], 7, 4); info_p->cpuid_family = bitfield(cpuid_reg[eax], 11, 8); info_p->cpuid_type = bitfield(cpuid_reg[eax], 13, 12); info_p->cpuid_extmodel = bitfield(cpuid_reg[eax], 19, 16); info_p->cpuid_extfamily = bitfield(cpuid_reg[eax], 27, 20); info_p->cpuid_brand = bitfield(cpuid_reg[ebx], 7, 0); info_p->cpuid_features = quad(cpuid_reg[ecx], cpuid_reg[edx]); /* Fold extensions into family/model */ if (info_p->cpuid_family == 0x0f) { info_p->cpuid_family += info_p->cpuid_extfamily; } if (info_p->cpuid_family == 0x0f || info_p->cpuid_family== 0x06) { info_p->cpuid_model += (info_p->cpuid_extmodel << 4); } if (info_p->cpuid_features & CPUID_FEATURE_HTT) { info_p->cpuid_logical_per_package = bitfield(cpuid_reg[ebx], 23, 16); } else { info_p->cpuid_logical_per_package = 1; } if (max_extid >= 0x80000001) { do_cpuid(0x80000001, cpuid_reg); info_p->cpuid_extfeatures = quad(cpuid_reg[ecx], cpuid_reg[edx]); } if (info_p->cpuid_extfeatures & CPUID_FEATURE_MONITOR) { do_cpuid(5, cpuid_reg); info_p->cpuid_mwait_linesize_min = cpuid_reg[eax]; info_p->cpuid_mwait_linesize_max = cpuid_reg[ebx]; info_p->cpuid_mwait_extensions = cpuid_reg[ecx]; info_p->cpuid_mwait_sub_Cstates = cpuid_reg[edx]; do_cpuid(6, cpuid_reg); info_p->cpuid_thermal_sensor = bitfield(cpuid_reg[eax], 0, 0); info_p->cpuid_thermal_dynamic_acceleration =bitfield(cpuid_reg[eax], 1, 1); info_p->cpuid_thermal_thresholds = bitfield(cpuid_reg[ebx], 3, 0); info_p->cpuid_thermal_ACNT_MCNT = bitfield(cpuid_reg[ecx], 0, 0); do_cpuid(0xa, cpuid_reg); info_p->cpuid_arch_perf_version = bitfield(cpuid_reg[eax], 7, 0); info_p->cpuid_arch_perf_number = bitfield(cpuid_reg[eax],15, 8); info_p->cpuid_arch_perf_width = bitfield(cpuid_reg[eax],23,16); info_p->cpuid_arch_perf_events_number = bitfield(cpuid_reg[eax],31,24); info_p->cpuid_arch_perf_events = cpuid_reg[ebx]; info_p->cpuid_arch_perf_fixed_number = bitfield(cpuid_reg[edx], 4, 0); info_p->cpuid_arch_perf_fixed_width = bitfield(cpuid_reg[edx],12, 5); }do_cpuid(4, cpuid_reg);info_p->cpuid_cores_per_package = bitfield(cpuid_reg[eax], 31, 26) + 1;if (info_p->cpuid_cores_per_package == 0) {info_p->cpuid_cores_per_package = 1;}switch (info_p->cpuid_model){case 0x1C:{//uint64_t msr = rdmsr64(MSR_CORE_THREAD_COUNT);info_p->core_count = 1; //bitfield((uint32_t)msr, 19, 16);info_p->thread_count = 2; //bitfield((uint32_t)msr, 15, 0);}break;case 0x1A: // Intel Core i7 LGA1366 (45nm)case 0x1E: // Intel Core i5, i7 LGA1156 (45nm)case 0x25: // Intel Core i3, i5, i7 LGA1156 (32nm){uint64_t msr = rdmsr64(MSR_CORE_THREAD_COUNT);info_p->core_count = bitfield((uint32_t)msr, 31, 16);info_p->thread_count = bitfield((uint32_t)msr, 15, 0);} break;case 0x2C: // Intel Core i7 LGA1366 (32nm) 6 Corecase 0x1F:case 0x2F:{uint64_t msr = rdmsr64(MSR_CORE_THREAD_COUNT);info_p->core_count = bitfield((uint32_t)msr, 19, 16);info_p->thread_count = bitfield((uint32_t)msr, 15, 0);break;}default:{do_cpuid(1, cpuid_reg);info_p->core_count = bitfield(cpuid_reg[1], 23, 16);} break;}if (info_p->core_count == 0) {info_p->core_count = info_p->cpuid_cores_per_package;info_p->thread_count = info_p->cpuid_logical_per_package;}}#endif /*M_CPUID_H*/

Archive Download this file

Revision: 723