blob: 873d479b5a269b59002d2adaec928c4c0705ce2c [file] [log] [blame]
Martin Roth9b1b3352016-02-24 12:27:06 -08001/*
2 * cpuid.h --
Martin Roth4dcd13d2016-02-24 13:53:07 -08003 * contains the data structures required for CPUID
Martin Roth9b1b3352016-02-24 12:27:06 -08004 * implementation.
5 */
6
7#define CPUID_VENDOR_LENGTH 3 /* 3 GPRs hold vendor ID */
8#define CPUID_VENDOR_STR_LENGTH (CPUID_VENDOR_LENGTH * sizeof(uint32_t) + 1)
9#define CPUID_BRAND_LENGTH 12 /* 12 GPRs hold vendor ID */
10#define CPUID_BRAND_STR_LENGTH (CPUID_BRAND_LENGTH * sizeof(uint32_t) + 1)
11
12extern struct cpu_ident cpu_id;
13
14static inline void __cpuid(unsigned int *eax, unsigned int *ebx,
15 unsigned int *ecx, unsigned int *edx)
16{
17 /* ecx is often an input as well as an output. */
18 asm volatile("\t"
19 "push %%ebx; cpuid; mov %%ebx, %%edi; pop %%ebx"
20 : "=a" (*eax),
21 "=D" (*ebx),
22 "=c" (*ecx),
23 "=d" (*edx)
24 : "0" (*eax), "2" (*ecx));
25}
26
27static inline void cpuid(unsigned int op,
28 unsigned int *eax, unsigned int *ebx,
29 unsigned int *ecx, unsigned int *edx)
30{
31 *eax = op;
32 *ecx = 0;
33 __cpuid(eax, ebx, ecx, edx);
34}
35
36/* Some CPUID calls want 'count' to be placed in ecx */
37static inline void cpuid_count(unsigned int op, int count,
38 unsigned int *eax, unsigned int *ebx,
39 unsigned int *ecx, unsigned int *edx)
40{
41 *eax = op;
42 *ecx = count;
43 __cpuid(eax, ebx, ecx, edx);
44}
45
46/* Typedef for storing the Cache Information */
47typedef union {
48 unsigned char ch[48];
49 uint32_t uint[12];
50 struct {
51 uint32_t fill1:24; /* Bit 0 */
52 uint32_t l1_i_sz:8;
Martin Roth4dcd13d2016-02-24 13:53:07 -080053 uint32_t fill2:24;
Martin Roth9b1b3352016-02-24 12:27:06 -080054 uint32_t l1_d_sz:8;
Martin Roth4dcd13d2016-02-24 13:53:07 -080055 uint32_t fill3:16;
Martin Roth9b1b3352016-02-24 12:27:06 -080056 uint32_t l2_sz:16;
Martin Roth4dcd13d2016-02-24 13:53:07 -080057 uint32_t fill4:18;
Martin Roth9b1b3352016-02-24 12:27:06 -080058 uint32_t l3_sz:14;
59 uint32_t fill5[8];
60 } amd;
61} cpuid_cache_info_t;
62
63/* Typedef for storing the CPUID Vendor String */
64typedef union {
65 /* Note: the extra byte in the char array is for '\0'. */
66 char char_array[CPUID_VENDOR_STR_LENGTH];
67 uint32_t uint32_array[CPUID_VENDOR_LENGTH];
68} cpuid_vendor_string_t;
69
70/* Typedef for storing the CPUID Brand String */
71typedef union {
72 /* Note: the extra byte in the char array is for '\0'. */
73 char char_array[CPUID_BRAND_STR_LENGTH];
74 uint32_t uint32_array[CPUID_BRAND_LENGTH];
75} cpuid_brand_string_t;
76
77/* Typedef for storing CPUID Version */
78typedef union {
79 uint32_t flat;
80 struct {
81 uint32_t stepping:4; /* Bit 0 */
82 uint32_t model:4;
83 uint32_t family:4;
84 uint32_t processorType:2;
85 uint32_t reserved1514:2;
86 uint32_t extendedModel:4;
87 uint32_t extendedFamily:8;
88 uint32_t reserved3128:4; /* Bit 31 */
Martin Roth4dcd13d2016-02-24 13:53:07 -080089 } bits;
Martin Roth9b1b3352016-02-24 12:27:06 -080090} cpuid_version_t;
91
92/* Typedef for storing CPUID Processor Information */
93typedef union {
94 uint32_t flat;
95 struct {
96 uint32_t brandIndex:8; /* Bit 0 */
97 uint32_t cflushLineSize:8;
98 uint32_t logicalProcessorCount:8;
99 uint32_t apicID:8; /* Bit 31 */
Martin Roth4dcd13d2016-02-24 13:53:07 -0800100 } bits;
Martin Roth9b1b3352016-02-24 12:27:06 -0800101} cpuid_proc_info_t;
102
103/* Typedef for storing CPUID Feature flags */
104typedef union {
105 uint32_t flat;
106 struct {
Martin Roth4dcd13d2016-02-24 13:53:07 -0800107 uint32_t :1;
Martin Roth9b1b3352016-02-24 12:27:06 -0800108 } bits;
109} cpuid_custom_features;
110
111/* Typedef for storing CPUID Feature flags */
112typedef union {
113 uint32_t uint32_array[3];
114 struct {
115 uint32_t fpu:1; /* EDX feature flags, bit 0 */
116 uint32_t vme:1;
117 uint32_t de:1;
118 uint32_t pse:1;
119 uint32_t rdtsc:1;
120 uint32_t msr:1;
121 uint32_t pae:1;
122 uint32_t mce:1;
123 uint32_t cx8:1;
124 uint32_t apic:1;
125 uint32_t bit10:1;
126 uint32_t sep:1;
127 uint32_t mtrr:1;
128 uint32_t pge:1;
129 uint32_t mca:1;
130 uint32_t cmov:1;
131 uint32_t pat:1;
132 uint32_t pse36:1;
133 uint32_t psn:1;
134 uint32_t cflush:1;
135 uint32_t bit20:1;
136 uint32_t ds:1;
137 uint32_t acpi:1;
138 uint32_t mmx:1;
139 uint32_t fxsr:1;
140 uint32_t sse:1;
141 uint32_t sse2:1;
142 uint32_t ss:1;
143 uint32_t htt:1;
144 uint32_t tm:1;
145 uint32_t bit30:1;
146 uint32_t pbe:1; /* EDX feature flags, bit 31 */
147 uint32_t sse3:1; /* ECX feature flags, bit 0 */
148 uint32_t mulq:1;
149 uint32_t bit2:1;
150 uint32_t mon:1;
151 uint32_t dscpl:1;
152 uint32_t vmx:1;
Martin Roth4dcd13d2016-02-24 13:53:07 -0800153 uint32_t smx:1;
154 uint32_t eist:1;
155 uint32_t tm2:1;
Martin Roth9b1b3352016-02-24 12:27:06 -0800156 uint32_t bits_9_31:23;
157 uint32_t bits0_28:29; /* EDX extended feature flags, bit 0 */
158 uint32_t lm:1; /* Long Mode */
159 uint32_t bits_30_31:2; /* EDX extended feature flags, bit 32 */
160 } bits;
161} cpuid_feature_flags_t;
162
163/* An overall structure to cache all of the CPUID information */
164struct cpu_ident {
165 uint32_t max_cpuid;
166 uint32_t max_xcpuid;
167 uint32_t dts_pmp;
168 cpuid_version_t vers;
169 cpuid_proc_info_t info;
170 cpuid_feature_flags_t fid;
171 cpuid_vendor_string_t vend_id;
172 cpuid_brand_string_t brand_id;
173 cpuid_cache_info_t cache_info;
174 cpuid_custom_features custom;
175};
176
177struct cpuid4_eax {
178 uint32_t ctype:5;
179 uint32_t level:3;
180 uint32_t is_self_initializing:1;
181 uint32_t is_fully_associative:1;
182 uint32_t reserved:4;
183 uint32_t num_threads_sharing:12;
184 uint32_t num_cores_on_die:6;
185};
186
187struct cpuid4_ebx {
188 uint32_t coherency_line_size:12;
189 uint32_t physical_line_partition:10;
190 uint32_t ways_of_associativity:10;
191};
192
193struct cpuid4_ecx {
194 uint32_t number_of_sets:32;
195};
196