2 Copyright © 2010, The AROS Development Team. All rights reserved.
7 #include <aros/debug.h>
9 #include <resources/processor.h>
12 #include "processor_arch_intern.h"
14 static const char *vendors
[] =
29 static void ReadVendorID(struct X86ProcessorInformation
* info
)
31 ULONG eax
, ebx
, ecx
, edx
;
32 ULONG
* ulongptr
= NULL
;
34 info
->Vendor
= VENDOR_UNKNOWN
;
35 info
->CPUIDHighestStandardFunction
= 0x0;
36 info
->CPUIDHighestExtendedFunction
= 0x0;
38 D(bug("[processor.x86] :%s()\n", __PRETTY_FUNCTION__
));
40 /* Reading CPU Vendor ID */
41 ulongptr
= (ULONG
*)info
->VendorID
;
44 info
->CPUIDHighestStandardFunction
= eax
;
45 ulongptr
[index
++] = ebx
;ulongptr
[index
++] = edx
;
46 ulongptr
[index
++] = ecx
;info
->VendorID
[12] = 0;
48 /* Select manufacturer based on Vendor ID */
49 for (index
= 0; vendors
[index
]; index
++)
51 if (strcmp(info
->VendorID
, vendors
[index
]) == 0)
53 info
->Vendor
= index
+ VENDOR_AMD
;
58 /* Reading Highest Extended Function */
60 info
->CPUIDHighestExtendedFunction
= eax
;
65 static void ReadBrandString(struct X86ProcessorInformation
* info
)
67 ULONG eax
, ebx
, ecx
, edx
;
68 ULONG
* ulongptr
= NULL
;
71 D(bug("[processor.x86] :%s()\n", __PRETTY_FUNCTION__
));
73 /* Reading CPU Brand String */
74 ulongptr
= (ULONG
*)info
->BrandStringBuffer
;
77 ulongptr
[index
++] = eax
;ulongptr
[index
++] = ebx
;
78 ulongptr
[index
++] = ecx
;ulongptr
[index
++] = edx
;
80 ulongptr
[index
++] = eax
;ulongptr
[index
++] = ebx
;
81 ulongptr
[index
++] = ecx
;ulongptr
[index
++] = edx
;
83 ulongptr
[index
++] = eax
;ulongptr
[index
++] = ebx
;
84 ulongptr
[index
++] = ecx
;ulongptr
[index
++] = edx
;
87 info
->BrandString
= info
->BrandStringBuffer
;
89 while(*info
->BrandString
== ' ') info
->BrandString
++;
93 static ULONG
AMDDeriveFamily(UBYTE basefamily
, UBYTE extendedfamily
)
98 D(bug("[processor.x86] :%s()\n", __PRETTY_FUNCTION__
));
100 if (basefamily
== 0x0f)
101 family
= basefamily
+ extendedfamily
;
107 case(0x0b): ret
= CPUFAMILY_AMD_K5
; break;
108 case(0x0c): ret
= CPUFAMILY_AMD_K6
; break;
109 case(0x0d): ret
= CPUFAMILY_AMD_K7
; break;
110 case(0x0e): ret
= CPUFAMILY_AMD_K8
; break;
111 case(0x0f): ret
= CPUFAMILY_AMD_K9
; break;
112 case(0x10): ret
= CPUFAMILY_AMD_K10
; break;
113 default: ret
= CPUFAMILY_UNKNOWN
; break;
119 static ULONG
IntelDeriveFamily(UBYTE basefamily
, UBYTE extendedfamily
)
121 ULONG family
= extendedfamily
+ basefamily
;
124 D(bug("[processor.x86] :%s()\n", __PRETTY_FUNCTION__
));
128 case(4): ret
= CPUFAMILY_INTEL_486
; break;
129 case(5): ret
= CPUFAMILY_INTEL_PENTIUM
; break;
130 case(6): ret
= CPUFAMILY_INTEL_PENTIUM_PRO
; break;
131 case(15): ret
= CPUFAMILY_INTEL_PENTIUM4
; break;
132 default: ret
= CPUFAMILY_UNKNOWN
; break;
138 static void ReadFamilyModelStepping(struct X86ProcessorInformation
* info
)
140 ULONG eax
, ebx
, ecx
, edx
;
141 UBYTE stepping
, basefamily
, extendedfamily
, basemodel
, extendedmodel
;
143 D(bug("[processor.x86] :%s()\n", __PRETTY_FUNCTION__
));
145 /* Reading Family/Model/Stepping */
148 stepping
= eax
& 0x0f;
149 basefamily
= (eax
>> 8) & 0x0f;
150 extendedfamily
= (eax
>> 20) & 0xff;
151 basemodel
= (eax
>> 4) & 0x0f;
152 extendedmodel
= (eax
>> 16) & 0x0f;
155 info
->Family
= CPUFAMILY_UNKNOWN
;
159 info
->Family
= AMDDeriveFamily(basefamily
, extendedfamily
);
160 info
->Model
= basemodel
| (basefamily
< 0x0f ? 0 : (extendedmodel
<< 4));
161 (void)stepping
; /* FIXME: Why is this unused? */
164 info
->Family
= IntelDeriveFamily(basefamily
, extendedfamily
);
165 info
->Model
= basemodel
| (extendedmodel
<< 4);
166 (void)stepping
; /* FIXME: Why is this unused? */
171 static void ReadFeaturesFlags(struct X86ProcessorInformation
* info
)
173 ULONG eax
, ebx
, ecx
, edx
;
175 D(bug("[processor.x86] :%s()\n", __PRETTY_FUNCTION__
));
177 /* Reading standard feature flags */
182 case(VENDOR_AMD
): edx
&= FEATURE_MASK_EDX_AMD
; ecx
&= FEATURE_MASK_ECX_AMD
; break;
183 case(VENDOR_INTEL
): edx
&= FEATURE_MASK_EDX_INTEL
; ecx
&= FEATURE_MASK_ECX_INTEL
; break;
184 default: edx
&= FEATURE_MASK_EDX_UNKNOWN
; ecx
&= FEATURE_MASK_ECX_UNKNOWN
; break;
187 info
->Features1
= edx
;
188 info
->Features2
= ecx
;
190 /* Read extended information */
194 case(VENDOR_AMD
): edx
&= FEATURE_MASK_EDX_EXT_AMD
; ecx
&= FEATURE_MASK_ECX_EXT_AMD
; break;
195 case(VENDOR_INTEL
): edx
&= FEATURE_MASK_EDX_EXT_INTEL
; ecx
&= FEATURE_MASK_ECX_EXT_INTEL
; break;
196 default: edx
&= FEATURE_MASK_EDX_UNKNOWN
; ecx
&= FEATURE_MASK_ECX_UNKNOWN
; break;
199 info
->Features3
= edx
;
200 info
->Features4
= ecx
;
202 /* Calculate the vector unit */
203 if (info
->Features2
& FEATF_SSE42
)
204 info
->VectorUnit
= VECTORTYPE_SSE42
;
205 else if (info
->Features2
& FEATF_SSE41
)
206 info
->VectorUnit
= VECTORTYPE_SSE41
;
207 else if (info
->Features4
& FEATF_SSE4A
)
208 info
->VectorUnit
= VECTORTYPE_SSE4A
;
209 else if (info
->Features2
& FEATF_SSSE3
)
210 info
->VectorUnit
= VECTORTYPE_SSSE3
;
211 else if (info
->Features2
& FEATF_SSE3
)
212 info
->VectorUnit
= VECTORTYPE_SSE3
;
213 else if (info
->Features1
& FEATF_SSE2
)
214 info
->VectorUnit
= VECTORTYPE_SSE2
;
215 else if (info
->Features1
& FEATF_SSE
)
216 info
->VectorUnit
= VECTORTYPE_SSE
;
217 else if (info
->Features3
& FEATF_3DNOWEXT
)
218 info
->VectorUnit
= VECTORTYPE_3DNOWEXT
;
219 else if (info
->Features3
& FEATF_3DNOW
)
220 info
->VectorUnit
= VECTORTYPE_3DNOW
;
221 else if (info
->Features3
& FEATF_MMXEXT
)
222 info
->VectorUnit
= VECTORTYPE_MMXEXT
;
223 else if (info
->Features1
& FEATF_MMX
)
224 info
->VectorUnit
= VECTORTYPE_MMX
;
226 info
->VectorUnit
= VECTORTYPE_NONE
;
229 static void AMDDeriveCacheInformation(struct X86ProcessorInformation
* info
)
231 ULONG eax
, ebx
, ecx
, edx
;
232 info
->CacheLineSize
= 0xff;
234 D(bug("[processor.x86] :%s()\n", __PRETTY_FUNCTION__
));
236 /* Reading L1 information */
239 info
->L1DataCacheSize
= (ecx
>> 24);
240 if ((ecx
& 0xff) < info
->CacheLineSize
) info
->CacheLineSize
= (ecx
& 0xff);
241 info
->L1InstructionCacheSize
= (edx
>> 24);
242 if ((edx
& 0xff) < info
->CacheLineSize
) info
->CacheLineSize
= (edx
& 0xff);
244 /* Reading L2/L3 information */
247 info
->L2CacheSize
= (ecx
>> 16);
248 if ((ecx
& 0xff) < info
->CacheLineSize
) info
->CacheLineSize
= (ecx
& 0xff);
249 info
->L3CacheSize
= (edx
>> 18) * 512;
250 if ((edx
& 0xff) < info
->CacheLineSize
) info
->CacheLineSize
= (edx
& 0xff);
253 #define min(a,b) (a > b ? b : a)
255 static void IntelDecodeCacheKeyValue(struct X86ProcessorInformation
* info
, UBYTE key
)
258 D(bug("[processor.x86] :%s()\n", __PRETTY_FUNCTION__
));
262 case(0x06): info
->L1InstructionCacheSize
= 8; info
->CacheLineSize
= min(32, info
->CacheLineSize
); break;
263 case(0x08): info
->L1InstructionCacheSize
= 16; info
->CacheLineSize
= min(32, info
->CacheLineSize
); break;
264 case(0x09): info
->L1InstructionCacheSize
= 32; info
->CacheLineSize
= min(64, info
->CacheLineSize
); break;
265 case(0x0A): info
->L1DataCacheSize
= 8; info
->CacheLineSize
= min(32, info
->CacheLineSize
); break;
266 case(0x0C): info
->L1DataCacheSize
= 16; info
->CacheLineSize
= min(32, info
->CacheLineSize
); break;
267 case(0x0D): info
->L1DataCacheSize
= 16; info
->CacheLineSize
= min(64, info
->CacheLineSize
); break;
268 case(0x21): info
->L2CacheSize
= 256; info
->CacheLineSize
= min(64, info
->CacheLineSize
); break;
269 case(0x22): info
->L3CacheSize
= 512; info
->CacheLineSize
= min(64, info
->CacheLineSize
); break;
270 case(0x23): info
->L3CacheSize
= 1024; info
->CacheLineSize
= min(64, info
->CacheLineSize
); break;
271 case(0x25): info
->L3CacheSize
= 2048; info
->CacheLineSize
= min(64, info
->CacheLineSize
); break;
272 case(0x29): info
->L3CacheSize
= 4096; info
->CacheLineSize
= min(64, info
->CacheLineSize
); break;
273 case(0x2C): info
->L1DataCacheSize
= 32; info
->CacheLineSize
= min(64, info
->CacheLineSize
); break;
274 case(0x30): info
->L1InstructionCacheSize
= 32; info
->CacheLineSize
= min(64, info
->CacheLineSize
); break;
275 case(0x39): info
->L2CacheSize
= 128; info
->CacheLineSize
= min(64, info
->CacheLineSize
); break;
276 case(0x3A): info
->L2CacheSize
= 192; info
->CacheLineSize
= min(64, info
->CacheLineSize
); break;
277 case(0x3B): info
->L2CacheSize
= 128; info
->CacheLineSize
= min(64, info
->CacheLineSize
); break;
278 case(0x3C): info
->L2CacheSize
= 256; info
->CacheLineSize
= min(64, info
->CacheLineSize
); break;
279 case(0x3D): info
->L2CacheSize
= 384; info
->CacheLineSize
= min(64, info
->CacheLineSize
); break;
280 case(0x3E): info
->L2CacheSize
= 512; info
->CacheLineSize
= min(64, info
->CacheLineSize
); break;
281 case(0x41): info
->L2CacheSize
= 128; info
->CacheLineSize
= min(32, info
->CacheLineSize
); break;
282 case(0x42): info
->L2CacheSize
= 256; info
->CacheLineSize
= min(32, info
->CacheLineSize
); break;
283 case(0x43): info
->L2CacheSize
= 512; info
->CacheLineSize
= min(32, info
->CacheLineSize
); break;
284 case(0x44): info
->L2CacheSize
= 1024; info
->CacheLineSize
= min(32, info
->CacheLineSize
); break;
285 case(0x45): info
->L2CacheSize
= 2048; info
->CacheLineSize
= min(32, info
->CacheLineSize
); break;
286 case(0x46): info
->L3CacheSize
= 4096; info
->CacheLineSize
= min(64, info
->CacheLineSize
); break;
287 case(0x47): info
->L3CacheSize
= 8192; info
->CacheLineSize
= min(64, info
->CacheLineSize
); break;
288 case(0x48): info
->L2CacheSize
= 3072; info
->CacheLineSize
= min(64, info
->CacheLineSize
); break;
289 case(0x49): info
->L2CacheSize
= 4096; info
->CacheLineSize
= min(64, info
->CacheLineSize
); break;
290 case(0x4A): info
->L3CacheSize
= 6144; info
->CacheLineSize
= min(64, info
->CacheLineSize
); break;
291 case(0x4B): info
->L3CacheSize
= 8192; info
->CacheLineSize
= min(64, info
->CacheLineSize
); break;
292 case(0x4C): info
->L3CacheSize
= 12288; info
->CacheLineSize
= min(64, info
->CacheLineSize
); break;
293 case(0x4D): info
->L3CacheSize
= 16384; info
->CacheLineSize
= min(64, info
->CacheLineSize
); break;
294 case(0x4E): info
->L2CacheSize
= 6144; info
->CacheLineSize
= min(64, info
->CacheLineSize
); break;
295 case(0x60): info
->L1DataCacheSize
= 16; info
->CacheLineSize
= min(64, info
->CacheLineSize
); break;
296 case(0x66): info
->L1DataCacheSize
= 8; info
->CacheLineSize
= min(64, info
->CacheLineSize
); break;
297 case(0x67): info
->L1DataCacheSize
= 16; info
->CacheLineSize
= min(64, info
->CacheLineSize
); break;
298 case(0x68): info
->L1DataCacheSize
= 32; info
->CacheLineSize
= min(64, info
->CacheLineSize
); break;
299 case(0x78): info
->L2CacheSize
= 1024; info
->CacheLineSize
= min(64, info
->CacheLineSize
); break;
300 case(0x79): info
->L2CacheSize
= 128; info
->CacheLineSize
= min(64, info
->CacheLineSize
); break;
301 case(0x7A): info
->L2CacheSize
= 256; info
->CacheLineSize
= min(64, info
->CacheLineSize
); break;
302 case(0x7B): info
->L2CacheSize
= 512; info
->CacheLineSize
= min(64, info
->CacheLineSize
); break;
303 case(0x7C): info
->L2CacheSize
= 1024; info
->CacheLineSize
= min(64, info
->CacheLineSize
); break;
304 case(0x7D): info
->L2CacheSize
= 2048; info
->CacheLineSize
= min(64, info
->CacheLineSize
); break;
305 case(0x7F): info
->L2CacheSize
= 512; info
->CacheLineSize
= min(64, info
->CacheLineSize
); break;
306 case(0x82): info
->L2CacheSize
= 256; info
->CacheLineSize
= min(32, info
->CacheLineSize
); break;
307 case(0x83): info
->L2CacheSize
= 512; info
->CacheLineSize
= min(32, info
->CacheLineSize
); break;
308 case(0x84): info
->L2CacheSize
= 1024; info
->CacheLineSize
= min(32, info
->CacheLineSize
); break;
309 case(0x85): info
->L2CacheSize
= 2048; info
->CacheLineSize
= min(32, info
->CacheLineSize
); break;
310 case(0x86): info
->L2CacheSize
= 512; info
->CacheLineSize
= min(64, info
->CacheLineSize
); break;
311 case(0x87): info
->L2CacheSize
= 1024; info
->CacheLineSize
= min(64, info
->CacheLineSize
); break;
312 case(0xD0): info
->L3CacheSize
= 512; info
->CacheLineSize
= min(64, info
->CacheLineSize
); break;
313 case(0xD1): info
->L3CacheSize
= 1024; info
->CacheLineSize
= min(64, info
->CacheLineSize
); break;
314 case(0xD2): info
->L3CacheSize
= 2048; info
->CacheLineSize
= min(64, info
->CacheLineSize
); break;
315 case(0xD6): info
->L3CacheSize
= 1024; info
->CacheLineSize
= min(64, info
->CacheLineSize
); break;
316 case(0xD7): info
->L3CacheSize
= 2048; info
->CacheLineSize
= min(64, info
->CacheLineSize
); break;
317 case(0xD8): info
->L3CacheSize
= 4096; info
->CacheLineSize
= min(64, info
->CacheLineSize
); break;
318 case(0xDC): info
->L3CacheSize
= 1536; info
->CacheLineSize
= min(64, info
->CacheLineSize
); break;
319 case(0xDD): info
->L3CacheSize
= 3072; info
->CacheLineSize
= min(64, info
->CacheLineSize
); break;
320 case(0xDE): info
->L3CacheSize
= 6144; info
->CacheLineSize
= min(64, info
->CacheLineSize
); break;
321 case(0xE2): info
->L3CacheSize
= 2048; info
->CacheLineSize
= min(64, info
->CacheLineSize
); break;
322 case(0xE3): info
->L3CacheSize
= 4096; info
->CacheLineSize
= min(64, info
->CacheLineSize
); break;
323 case(0xE4): info
->L3CacheSize
= 8192; info
->CacheLineSize
= min(64, info
->CacheLineSize
); break;
324 case(0xEA): info
->L3CacheSize
= 12288; info
->CacheLineSize
= min(64, info
->CacheLineSize
); break;
325 case(0xEB): info
->L3CacheSize
= 18432; info
->CacheLineSize
= min(64, info
->CacheLineSize
); break;
326 case(0xEC): info
->L3CacheSize
= 24576; info
->CacheLineSize
= min(64, info
->CacheLineSize
); break;
329 static void IntelDeriveCacheInformation(struct X86ProcessorInformation
* info
)
331 ULONG eax
, ebx
, ecx
, edx
;
332 info
->CacheLineSize
= 0xff;
334 D(bug("[processor.x86] :%s()\n", __PRETTY_FUNCTION__
));
336 /* Reading Cache Information */
339 if ((eax
>> 31) == 0)
343 temp
= ((eax
>> 24) & 0xff);
344 IntelDecodeCacheKeyValue(info
, temp
);
345 temp
= ((eax
>> 16) & 0xff);
346 IntelDecodeCacheKeyValue(info
, temp
);
347 temp
= ((eax
>> 8) & 0xff);
348 IntelDecodeCacheKeyValue(info
, temp
);
352 if ((ebx
>> 31) == 0)
356 temp
= ((ebx
>> 24) & 0xff);
357 IntelDecodeCacheKeyValue(info
, temp
);
358 temp
= ((ebx
>> 16) & 0xff);
359 IntelDecodeCacheKeyValue(info
, temp
);
360 temp
= ((ebx
>> 8) & 0xff);
361 IntelDecodeCacheKeyValue(info
, temp
);
363 IntelDecodeCacheKeyValue(info
, temp
);
366 if ((ecx
>> 31) == 0)
370 temp
= ((ecx
>> 24) & 0xff);
371 IntelDecodeCacheKeyValue(info
, temp
);
372 temp
= ((ecx
>> 16) & 0xff);
373 IntelDecodeCacheKeyValue(info
, temp
);
374 temp
= ((ecx
>> 8) & 0xff);
375 IntelDecodeCacheKeyValue(info
, temp
);
377 IntelDecodeCacheKeyValue(info
, temp
);
380 if ((edx
>> 31) == 0)
384 temp
= ((edx
>> 24) & 0xff);
385 IntelDecodeCacheKeyValue(info
, temp
);
386 temp
= ((edx
>> 16) & 0xff);
387 IntelDecodeCacheKeyValue(info
, temp
);
388 temp
= ((edx
>> 8) & 0xff);
389 IntelDecodeCacheKeyValue(info
, temp
);
391 IntelDecodeCacheKeyValue(info
, temp
);
395 static void ReadCacheInformation(struct X86ProcessorInformation
* info
)
398 D(bug("[processor.x86] :%s()\n", __PRETTY_FUNCTION__
));
400 info
->L1DataCacheSize
= 0;
401 info
->L1InstructionCacheSize
= 0;
402 info
->L2CacheSize
= 0;
403 info
->L3CacheSize
= 0;
404 info
->CacheLineSize
= 0;
408 case(VENDOR_AMD
): AMDDeriveCacheInformation(info
); break;
409 case(VENDOR_INTEL
): IntelDeriveCacheInformation(info
); break;
413 static void ReadMSRSupportInformation(struct X86ProcessorInformation
* info
)
415 ULONG eax
, ebx
, ecx
, edx
;
417 D(bug("[processor.x86] :%s()\n", __PRETTY_FUNCTION__
));
419 info
->APERFMPERF
= FALSE
;
421 /* Check if MSR is supported */
422 if (!(info
->Features1
& FEATF_MSR
))
425 if (info
->CPUIDHighestStandardFunction
> 0x00000005)
427 /* Reading Power Management Information */
430 info
->APERFMPERF
= TRUE
;
434 VOID
ReadProcessorInformation(struct X86ProcessorInformation
* info
)
436 D(bug("[processor.x86] :%s()\n", __PRETTY_FUNCTION__
));
439 ReadBrandString(info
);
440 ReadFamilyModelStepping(info
);
441 ReadFeaturesFlags(info
);
442 ReadCacheInformation(info
);
443 ReadMSRSupportInformation(info
);
444 ReadMaxFrequencyInformation(info
);