1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196
|
/*
* 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;
};
|