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
197
198
199
200
201
202
203
204
|
#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_
|