2 * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
6 * The contents of this file constitute Original Code as defined in and
7 * are subject to the Apple Public Source License Version 1.1 (the
8 * "License"). You may not use this file except in compliance with the
9 * License. Please obtain a copy of the License at
10 * http://www.apple.com/publicsource and read it before using this file.
12 * This Original Code and all software distributed under the License are
13 * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
14 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
15 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
17 * License for the specific language governing rights and limitations
20 * @APPLE_LICENSE_HEADER_END@
27 * Values from http://einstein.et.tudelft.nl/~offerman/chiplist.html
31 #include <kern/misc_protos.h>
32 #include <i386/cpuid.h>
35 * Generic product array (before CPUID)
37 unsigned int cpuid_i386_freq
[] = { 12, 16, 20, 25, 33, 0 };
38 unsigned int cpuid_i486_freq
[] = { 20, 25, 33, 50, 0 };
40 struct cpuid_product cpuid_generic
[] = {
42 0, CPUID_FAMILY_386
, 0,
43 80, cpuid_i386_freq
, "i386"
46 0, CPUID_FAMILY_486
, 0,
47 240, cpuid_i486_freq
, "i486"
54 unsigned int cpuid_i486_dx_freq
[] = { 20, 25, 33, 0 };
55 unsigned int cpuid_i486_dx_s_freq
[] = { 50, 0 };
56 unsigned int cpuid_i486_sx_freq
[] = { 16, 20, 25, 33, 0 };
57 unsigned int cpuid_i486_dx2_freq
[] = { 32, 40, 50, 66, 0 };
58 unsigned int cpuid_i486_sl_freq
[] = { 25, 33, 0 };
59 unsigned int cpuid_i486_sx2_freq
[] = { 50, 0 };
60 unsigned int cpuid_i486_dx2wb_freq
[] = { 50, 66, 0 };
61 unsigned int cpuid_i486_dx4_freq
[] = { 90, 100, 0 };
63 unsigned int cpuid_i486_dx2wb_od_freq
[] = { 32, 40, 50, 66, 0 };
64 unsigned int cpuid_i486_dx4_od_freq
[] = { 75, 99, 0 };
66 unsigned int cpuid_p5_freq
[] = { 60, 66, 0 };
67 unsigned int cpuid_p54_freq
[] = { 60, 66, 75, 90, 100, 120, 133, 166, 200, 0 };
69 unsigned int cpuid_p24t_freq
[] = { 25, 33, 0 };
70 unsigned int cpuid_p24ct_freq
[] = { 63, 83, 0 };
72 unsigned int cpuid_pii_freq
[] = { 300, 0 };
74 struct cpuid_product cpuid_intel
[] = {
76 CPUID_TYPE_OEM
, CPUID_FAMILY_486
, CPUID_MODEL_I486_DX
,
77 240, cpuid_i486_dx_freq
, "Intel 486DX"
80 CPUID_TYPE_OEM
, CPUID_FAMILY_486
, CPUID_MODEL_I486_DX_S
,
81 240, cpuid_i486_dx_s_freq
, "Intel 486DX-S"
84 CPUID_TYPE_OEM
, CPUID_FAMILY_486
, CPUID_MODEL_I486_SX
,
85 240, cpuid_i486_sx_freq
, "Intel 486SX"
88 CPUID_TYPE_OEM
, CPUID_FAMILY_486
, CPUID_MODEL_I486_DX2
,
89 240, cpuid_i486_dx2_freq
, "Intel 486DX2"
92 CPUID_TYPE_OEM
, CPUID_FAMILY_486
, CPUID_MODEL_I486_SL
,
93 240, cpuid_i486_sl_freq
, "Intel 486SL"
96 CPUID_TYPE_OEM
, CPUID_FAMILY_486
, CPUID_MODEL_I486_SX2
,
97 240, cpuid_i486_sx2_freq
, "Intel 486SX2"
100 CPUID_TYPE_OEM
, CPUID_FAMILY_486
, CPUID_MODEL_I486_DX2WB
,
101 240, cpuid_i486_dx2wb_freq
, "Intel 486DX2WB"
104 CPUID_TYPE_OEM
, CPUID_FAMILY_486
, CPUID_MODEL_I486_DX4
,
105 240, cpuid_i486_dx4_freq
, "Intel 486DX4"
108 CPUID_TYPE_OVERDRIVE
, CPUID_FAMILY_486
, CPUID_MODEL_I486_DX2
,
109 240, cpuid_i486_dx2_freq
, "Intel 486DX2 OverDrive"
112 CPUID_TYPE_OVERDRIVE
, CPUID_FAMILY_486
, CPUID_MODEL_I486_DX2WB
,
113 240, cpuid_i486_dx2wb_od_freq
, "Intel 486DX2WB OverDrive"
116 CPUID_TYPE_OVERDRIVE
, CPUID_FAMILY_486
, CPUID_MODEL_I486_DX4
,
117 240, cpuid_i486_dx4_od_freq
, "Intel 486DX4 OverDrive"
120 CPUID_TYPE_OVERDRIVE
, CPUID_FAMILY_P5
, CPUID_MODEL_P24T
,
121 208, cpuid_p24t_freq
, "Intel Pentium P24T OverDrive"
124 CPUID_TYPE_OVERDRIVE
, CPUID_FAMILY_P5
, CPUID_MODEL_P54
,
125 207, cpuid_p24ct_freq
, "Intel Pentium P24CT OverDrive"
128 CPUID_TYPE_OEM
, CPUID_FAMILY_P5
, CPUID_MODEL_P5A
,
129 207, cpuid_p5_freq
, "Intel Pentium P5 rev A"
132 CPUID_TYPE_OEM
, CPUID_FAMILY_P5
, CPUID_MODEL_P5
,
133 207, cpuid_p5_freq
, "Intel Pentium P5"
136 CPUID_TYPE_OEM
, CPUID_FAMILY_P5
, CPUID_MODEL_P54
,
137 207, cpuid_p54_freq
, "Intel Pentium P54"
140 CPUID_TYPE_OEM
, CPUID_FAMILY_PPRO
, CPUID_MODEL_PII
,
141 480, cpuid_pii_freq
, "Intel Pentium II"
144 unsigned int cpuid_intel_size
= sizeof (cpuid_intel
) / sizeof (cpuid_intel
[0]);
149 unsigned int cpuid_am486_dx_freq
[] = { 33, 40, 0 };
150 unsigned int cpuid_am486_dx2_freq
[] = { 50, 66, 80, 99, 0 };
151 unsigned int cpuid_am486_dx4_freq
[] = { 99, 120, 133, 0 };
152 unsigned int cpuid_am486_dx4wb_freq
[] = { 99, 120, 133, 0 };
157 unsigned int cpuid_u5sd_freq
[] = { 25, 33, 40, 0 };
158 unsigned int cpuid_u5s_freq
[] = { 25, 33, 40, 0 };
163 struct cpuid_name cpuid_name
[] = {
165 cpuid_intel
, sizeof (cpuid_intel
) / sizeof (cpuid_intel
[0])
168 (struct cpuid_product
*)0,
171 (struct cpuid_product
*)0,
174 (struct cpuid_product
*)0,
177 (struct cpuid_product
*)0
180 cpuid_generic
, sizeof (cpuid_generic
) / sizeof (cpuid_generic
[0])
187 * Feature Flag values
189 char *cpuid_flag
[] = {
190 "FPU", /* Floating point unit on-chip */
191 "VME", /* Virtual Mode Extension */
192 "DE", /* Debugging Extension */
193 "PSE", /* Page Size Extension */
194 "TSC", /* Time Stamp Counter */
195 "MSR", /* Model Specific Registers */
196 "PAE", /* Physical Address Extension */
197 "MCE", /* Machine Check Exception */
198 "CX8", /* CMPXCHG8 Instruction sSupported */
199 "APIC", /* Local APIC Supported */
202 "MTRR", /* Machine Type Range Register */
203 "PGE", /* Page Global Enable */
204 "MCA", /* Machine Check Architecture */
205 "CMOV", /* Conditional Move Instruction Supported */
213 "MMX", /* Supports MMX instructions */
225 * Cache description array
227 struct cpuid_cache_desc cpuid_cache_desc
[] = {
228 { CPUID_CACHE_ITLB_4K
,
229 "Instruction TBL, 4K, pages 4-way set associative, 64 entries"
231 { CPUID_CACHE_ITLB_4M
,
232 "Instruction TBL, 4M, pages 4-way set associative, 4 entries"
234 { CPUID_CACHE_DTLB_4K
,
235 "Data TBL, 4K pages, 4-way set associative, 64 entries"
237 { CPUID_CACHE_DTLB_4M
,
238 "Data TBL, 4M pages, 4-way set associative, 4 entries"
240 { CPUID_CACHE_ICACHE_8K
,
241 "Instruction L1 cache, 8K, 4-way set associative, 32byte line size"
243 { CPUID_CACHE_DCACHE_8K
,
244 "Data L1 cache, 8K, 2-way set associative, 32byte line size"
246 { CPUID_CACHE_UCACHE_128K
,
247 "Unified L2 cache, 128K, 4-way set associative, 32byte line size"
249 { CPUID_CACHE_UCACHE_256K
,
250 "Unified L2 cache, 256K, 4-way set associative, 32byte line size"
252 { CPUID_CACHE_UCACHE_512K
,
253 "Unified L2 cache, 512K, 4-way set associative, 32byte line size"
263 unsigned int cpuid_value
;
264 unsigned char cpuid_type
;
265 unsigned char cpuid_family
;
266 unsigned char cpuid_model
;
267 unsigned char cpuid_stepping
;
268 unsigned int cpuid_feature
;
269 char cpuid_vid
[CPUID_VID_SIZE
+ 1];
270 unsigned char cpuid_cache
[CPUID_CACHE_SIZE
];
273 * Return correct CPU_TYPE
280 #ifndef MACH_BSD /* FIXME - add more family/chip types */
281 switch (cpuid_family
) {
282 case CPUID_FAMILY_PPRO
:
283 return (CPU_TYPE_PENTIUMPRO
);
284 case CPUID_FAMILY_P5
:
285 return (CPU_TYPE_PENTIUM
);
286 case CPUID_FAMILY_486
:
287 return (CPU_TYPE_I486
);
292 return (CPU_TYPE_I386
);
296 * Display processor signature
304 struct cpuid_name
*name
;
308 unsigned int feature
;
310 extern unsigned int delaycount
;
315 for (name
= cpuid_name
; name
->name
!= (char *)0; name
++) {
316 char *p
= name
->name
;
318 while (*p
== *q
&& *p
!= 0) {
322 if (*p
== '\0' && *q
== '\0')
325 if (name
->name
== (char *)0) {
326 printf("Unrecognized processor vendor id = '%s'\n", cpuid_vid
);
331 * Identify Product ID
333 for (i
= 0; i
< name
->size
; i
++)
334 if (name
->product
[i
].type
== cpuid_type
&&
335 name
->product
[i
].family
== cpuid_family
&&
336 name
->product
[i
].model
== cpuid_model
)
338 if (i
== name
->size
) {
339 printf("%s processor (type = 0x%x, family = 0x%x, model = 0x%x)\n",
340 "Unrecognized", cpuid_type
, cpuid_family
, cpuid_model
);
345 * Look for frequency and adjust it to known values
347 mhz
= (1000 * delaycount
) / name
->product
[i
].delay
;
348 for (freq
= name
->product
[i
].frequency
; *freq
!= 0; freq
++)
353 else if (freq
== name
->product
[i
].frequency
)
355 else if (*freq
- mhz
> mhz
- *(freq
- 1))
357 else if (*freq
!= mhz
)
361 * Display product and frequency
363 printf("%s: %s at %d MHz (signature = %d/%d/%d/%d)\n",
364 header
, name
->product
[i
].name
, mhz
, cpuid_type
,
365 cpuid_family
, cpuid_model
, cpuid_stepping
);
368 * Display feature (if any)
373 for (feature
= cpuid_feature
; feature
!= 0; feature
>>= 1) {
376 printf("%s: %s", header
, *flag
);
379 printf(", %s", *flag
);
387 * Display processor configuration information
395 struct cpuid_cache_desc
*desc
;
398 if (cpuid_cache
[CPUID_CACHE_VALID
] == 1)
399 for (i
= 0; i
< CPUID_CACHE_SIZE
; i
++) {
400 if (i
!= CPUID_CACHE_VALID
|| cpuid_cache
[i
] == CPUID_CACHE_NULL
)
402 for (desc
= cpuid_cache_desc
;
403 desc
->description
!= (char *)0; desc
++)
404 if (desc
->value
== cpuid_cache
[i
])
406 if (desc
->description
!= (char *)0)
407 printf("%s: %s\n", header
, desc
->description
);