revert commit 56204.
[AROS.git] / arch / all-pc / processor / processor_util.c
blobe5ce0334af773edb93010a05e731d0caff1e58cf
1 /*
2 Copyright © 2010-2017, The AROS Development Team. All rights reserved.
3 $Id$
4 */
6 #define DEBUG 0
7 #include <aros/debug.h>
9 #include <resources/processor.h>
10 #include <string.h>
12 #include "processor_arch_intern.h"
14 static const char *vendors[] =
16 "AuthenticAMD",
17 "GenuineIntel",
18 "CyrixInstead",
19 "UMC UMC UMC ",
20 "NexGenDriven",
21 "CentaurHauls",
22 "RiseRiseRise",
23 "SiS SiS SiS ",
24 "GenuineTMx86",
25 "Geode by NSC",
26 NULL
29 static void ReadVendorID(struct X86ProcessorInformation * info)
31 ULONG eax, ebx, ecx, edx;
32 ULONG * ulongptr = NULL;
33 ULONG index = 0;
34 info->Vendor = VENDOR_UNKNOWN;
35 info->CPUIDHighestStandardFunction = 0x0;
36 info->CPUIDHighestExtendedFunction = 0x0;
38 D(bug("[processor.x86] :%s()\n", __func__));
40 /* Reading CPU Vendor ID */
41 ulongptr = (ULONG *)info->VendorID;
42 index = 0;
43 cpuid(0x00000000);
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;
54 break;
58 /* Reading Highest Extended Function */
59 cpuid(0x80000000);
60 info->CPUIDHighestExtendedFunction = eax;
65 static void ReadBrandString(struct X86ProcessorInformation * info)
67 ULONG eax, ebx, ecx, edx;
68 ULONG * ulongptr = NULL;
69 ULONG index = 0;
71 D(bug("[processor.x86] :%s()\n", __func__));
73 /* Reading CPU Brand String */
74 ulongptr = (ULONG *)info->BrandStringBuffer;
75 index = 0;
76 cpuid(0x80000002);
77 ulongptr[index++] = eax;ulongptr[index++] = ebx;
78 ulongptr[index++] = ecx;ulongptr[index++] = edx;
79 cpuid(0x80000003);
80 ulongptr[index++] = eax;ulongptr[index++] = ebx;
81 ulongptr[index++] = ecx;ulongptr[index++] = edx;
82 cpuid(0x80000004);
83 ulongptr[index++] = eax;ulongptr[index++] = ebx;
84 ulongptr[index++] = ecx;ulongptr[index++] = edx;
86 /* Left trim */
87 info->BrandString = info->BrandStringBuffer;
89 while(*info->BrandString == ' ') info->BrandString++;
93 static ULONG AMDDeriveFamily(UBYTE basefamily, UBYTE extendedfamily)
95 ULONG family = 0;
96 ULONG ret;
98 D(bug("[processor.x86] :%s()\n", __func__));
100 if (basefamily == 0x0f)
101 family = basefamily + extendedfamily;
102 else
103 family = basefamily;
105 switch(family)
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;
116 return ret;
119 static ULONG IntelDeriveFamily(UBYTE basefamily, UBYTE extendedfamily)
121 ULONG family = extendedfamily + basefamily;
122 ULONG ret;
124 D(bug("[processor.x86] :%s()\n", __func__));
126 switch(family)
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;
135 return ret;
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", __func__));
145 /* Reading Family/Model/Stepping */
146 cpuid(0x00000001);
148 stepping = eax & 0x0f;
149 basefamily = (eax >> 8) & 0x0f;
150 extendedfamily = (eax >> 20) & 0xff;
151 basemodel = (eax >> 4) & 0x0f;
152 extendedmodel = (eax >> 16) & 0x0f;
154 /* Read family */
155 info->Family = CPUFAMILY_UNKNOWN;
156 switch(info->Vendor)
158 case(VENDOR_AMD):
159 info->Family = AMDDeriveFamily(basefamily, extendedfamily);
160 info->Model = basemodel | (basefamily < 0x0f ? 0 : (extendedmodel << 4));
161 (void)stepping; /* FIXME: Why is this unused? */
162 break;
163 case(VENDOR_INTEL):
164 info->Family = IntelDeriveFamily(basefamily, extendedfamily);
165 info->Model = basemodel | (extendedmodel << 4);
166 (void)stepping; /* FIXME: Why is this unused? */
167 break;
171 static void ReadFeaturesFlags(struct X86ProcessorInformation * info)
173 ULONG eax, ebx, ecx, edx;
175 D(bug("[processor.x86] :%s()\n", __func__));
177 /* Reading standard feature flags */
178 cpuid(0x00000001);
180 switch(info->Vendor)
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 */
191 cpuid(0x80000001);
192 switch(info->Vendor)
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;
225 else
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", __func__));
236 /* Reading L1 information */
237 cpuid(0x80000005);
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 */
245 cpuid(0x80000006);
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", __func__));
260 switch(key)
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", __func__));
336 /* Reading Cache Information */
337 cpuid(0x00000002);
339 if ((eax >> 31) == 0)
341 UBYTE temp;
342 /* Decoding eax */
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);
349 /* AL is reserved */
352 if ((ebx >> 31) == 0)
354 UBYTE temp;
355 /* Decoding ebx */
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);
362 temp = (ebx & 0xff);
363 IntelDecodeCacheKeyValue(info, temp);
366 if ((ecx >> 31) == 0)
368 UBYTE temp;
369 /* Decoding ebx */
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);
376 temp = (ecx & 0xff);
377 IntelDecodeCacheKeyValue(info, temp);
380 if ((edx >> 31) == 0)
382 UBYTE temp;
383 /* Decoding ebx */
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);
390 temp = (edx & 0xff);
391 IntelDecodeCacheKeyValue(info, temp);
395 static void ReadCacheInformation(struct X86ProcessorInformation * info)
398 D(bug("[processor.x86] :%s()\n", __func__));
400 info->L1DataCacheSize = 0;
401 info->L1InstructionCacheSize = 0;
402 info->L2CacheSize = 0;
403 info->L3CacheSize = 0;
404 info->CacheLineSize = 0;
406 switch(info->Vendor)
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", __func__));
419 info->APERFMPERF = FALSE;
421 /* Check if MSR is supported */
422 if (!(info->Features1 & FEATF_MSR))
423 return;
425 if (info->CPUIDHighestStandardFunction > 0x00000005)
427 /* Reading Power Management Information */
428 cpuid(0x00000006);
429 if (ecx & 0x01)
430 info->APERFMPERF = TRUE;
434 VOID ReadProcessorInformation(struct X86ProcessorInformation * info)
436 D(bug("[processor.x86] :%s()\n", __func__));
438 ReadVendorID(info);
439 ReadBrandString(info);
440 ReadFamilyModelStepping(info);
441 ReadFeaturesFlags(info);
442 ReadCacheInformation(info);
443 ReadMSRSupportInformation(info);
444 ReadMaxFrequencyInformation(info);