#ifndef CPUID_H_
#define CPUID_H_
#include "stdin.h"
/*
* cpuid.h --
* contains the data structures required for CPUID
* implementation.
*/
#define CPUID_VENDOR_LENGTH 3 /* 3 GPRs hold vendor ID */
#define CPUID_VENDOR_STR_LENGTH (CPUID_VENDOR_LENGTH * sizeof(uint32_t) + 1)
#define CPUID_BRAND_LENGTH 12 /* 12 GPRs hold vendor ID */
#define CPUID_BRAND_STR_LENGTH (CPUID_BRAND_LENGTH * sizeof(uint32_t) + 1)
extern struct cpu_ident cpu_id;
static inline void __cpuid(unsigned int *eax, unsigned int *ebx,
unsigned int *ecx, unsigned int *edx)
{
/* ecx is often an input as well as an output. */
asm volatile("\t"
"push %%ebx; cpuid; mov %%ebx, %%edi; pop %%ebx"
: "=a" (*eax),
"=D" (*ebx),
"=c" (*ecx),
"=d" (*edx)
: "0" (*eax), "2" (*ecx));
}
static inline void cpuid(unsigned int op,
unsigned int *eax, unsigned int *ebx,
unsigned int *ecx, unsigned int *edx)
{
*eax = op;
*ecx = 0;
__cpuid(eax, ebx, ecx, edx);
}
/* Some CPUID calls want 'count' to be placed in ecx */
static inline void cpuid_count(unsigned int op, int count,
unsigned int *eax, unsigned int *ebx,
unsigned int *ecx, unsigned int *edx)
{
*eax = op;
*ecx = count;
__cpuid(eax, ebx, ecx, edx);
}
/* Typedef for storing the Cache Information */
typedef union {
unsigned char ch[48];
uint32_t uint[12];
struct {
uint32_t fill1:24; /* Bit 0 */
uint32_t l1_i_sz:8;
uint32_t fill2:24;
uint32_t l1_d_sz:8;
uint32_t fill3:16;
uint32_t l2_sz:16;
uint32_t fill4:18;
uint32_t l3_sz:14;
uint32_t fill5[8];
} amd;
} cpuid_cache_info_t;
/* Typedef for storing the CPUID Vendor String */
typedef union {
/* Note: the extra byte in the char array is for '\0'. */
char char_array[CPUID_VENDOR_STR_LENGTH];
uint32_t uint32_array[CPUID_VENDOR_LENGTH];
} cpuid_vendor_string_t;
/* Typedef for storing the CPUID Brand String */
typedef union {
/* Note: the extra byte in the char array is for '\0'. */
char char_array[CPUID_BRAND_STR_LENGTH];
uint32_t uint32_array[CPUID_BRAND_LENGTH];
} cpuid_brand_string_t;
/* Typedef for storing CPUID Version */
typedef union {
uint32_t flat;
struct {
uint32_t stepping:4; /* Bit 0 */
uint32_t model:4;
uint32_t family:4;
uint32_t processorType:2;
uint32_t reserved1514:2;
uint32_t extendedModel:4;
uint32_t extendedFamily:8;
uint32_t reserved3128:4; /* Bit 31 */
} bits;
} cpuid_version_t;
/* Typedef for storing CPUID Processor Information */
typedef union {
uint32_t flat;
struct {
uint32_t brandIndex:8; /* Bit 0 */
uint32_t cflushLineSize:8;
uint32_t logicalProcessorCount:8;
uint32_t apicID:8; /* Bit 31 */
} bits;
} cpuid_proc_info_t;
/* Typedef for storing CPUID Feature flags */
typedef union {
uint32_t flat;
struct {
uint32_t :1;
} bits;
} cpuid_custom_features;
/* Typedef for storing CPUID Feature flags */
typedef union {
uint32_t uint32_array[3];
struct {
uint32_t fpu:1; /* EDX feature flags, bit 0 */
uint32_t vme:1;
uint32_t de:1;
uint32_t pse:1;
uint32_t rdtsc:1;
uint32_t msr:1;
uint32_t pae:1;
uint32_t mce:1;
uint32_t cx8:1;
uint32_t apic:1;
uint32_t bit10:1;
uint32_t sep:1;
uint32_t mtrr:1;
uint32_t pge:1;
uint32_t mca:1;
uint32_t cmov:1;
uint32_t pat:1;
uint32_t pse36:1;
uint32_t psn:1;
uint32_t cflush:1;
uint32_t bit20:1;
uint32_t ds:1;
uint32_t acpi:1;
uint32_t mmx:1;
uint32_t fxsr:1;
uint32_t sse:1;
uint32_t sse2:1;
uint32_t ss:1;
uint32_t htt:1;
uint32_t tm:1;
uint32_t bit30:1;
uint32_t pbe:1; /* EDX feature flags, bit 31 */
uint32_t sse3:1; /* ECX feature flags, bit 0 */
uint32_t mulq:1;
uint32_t bit2:1;
uint32_t mon:1;
uint32_t dscpl:1;
uint32_t vmx:1;
uint32_t smx:1;
uint32_t eist:1;
uint32_t tm2:1;
uint32_t bits_9_31:23;
uint32_t bits0_28:29; /* EDX extended feature flags, bit 0 */
uint32_t lm:1; /* Long Mode */
uint32_t bits_30_31:2; /* EDX extended feature flags, bit 32 */
} bits;
} cpuid_feature_flags_t;
/* An overall structure to cache all of the CPUID information */
struct cpu_ident {
uint32_t max_cpuid;
uint32_t max_xcpuid;
uint32_t dts_pmp;
cpuid_version_t vers;
cpuid_proc_info_t info;
cpuid_feature_flags_t fid;
cpuid_vendor_string_t vend_id;
cpuid_brand_string_t brand_id;
cpuid_cache_info_t cache_info;
cpuid_custom_features custom;
};
struct cpuid4_eax {
uint32_t ctype:5;
uint32_t level:3;
uint32_t is_self_initializing:1;
uint32_t is_fully_associative:1;
uint32_t reserved:4;
uint32_t num_threads_sharing:12;
uint32_t num_cores_on_die:6;
};
struct cpuid4_ebx {
uint32_t coherency_line_size:12;
uint32_t physical_line_partition:10;
uint32_t ways_of_associativity:10;
};
struct cpuid4_ecx {
uint32_t number_of_sets:32;
};
void get_cpuid();
#endif // CPUID_H_