|
|
1.1 root 1: /*
2: * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
3: *
4: * @APPLE_LICENSE_HEADER_START@
5: *
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.
11: *
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
18: * under the License.
19: *
20: * @APPLE_LICENSE_HEADER_END@
21: */
22: /*
23: * @OSF_COPYRIGHT@
24: */
25:
26: /*
27: * Values from http://einstein.et.tudelft.nl/~offerman/chiplist.html
28: * (dated 18 Oct 1995)
29: */
30:
31: #include <kern/misc_protos.h>
32: #include <i386/cpuid.h>
33:
34: /*
35: * Generic product array (before CPUID)
36: */
37: unsigned int cpuid_i386_freq[] = { 12, 16, 20, 25, 33, 0 };
38: unsigned int cpuid_i486_freq[] = { 20, 25, 33, 50, 0 };
39:
40: struct cpuid_product cpuid_generic[] = {
41: {
42: 0, CPUID_FAMILY_386, 0,
43: 80, cpuid_i386_freq, "i386"
44: },
45: {
46: 0, CPUID_FAMILY_486, 0,
47: 240, cpuid_i486_freq, "i486"
48: },
49: };
50:
51: /*
52: * INTEL product array
53: */
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 };
62:
63: unsigned int cpuid_i486_dx2wb_od_freq[] = { 32, 40, 50, 66, 0 };
64: unsigned int cpuid_i486_dx4_od_freq[] = { 75, 99, 0 };
65:
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 };
68:
69: unsigned int cpuid_p24t_freq[] = { 25, 33, 0 };
70: unsigned int cpuid_p24ct_freq[] = { 63, 83, 0 };
71:
72: unsigned int cpuid_pii_freq[] = { 300, 0 };
73:
74: struct cpuid_product cpuid_intel[] = {
75: {
76: CPUID_TYPE_OEM, CPUID_FAMILY_486, CPUID_MODEL_I486_DX,
77: 240, cpuid_i486_dx_freq, "Intel 486DX"
78: },
79: {
80: CPUID_TYPE_OEM, CPUID_FAMILY_486, CPUID_MODEL_I486_DX_S,
81: 240, cpuid_i486_dx_s_freq, "Intel 486DX-S"
82: },
83: {
84: CPUID_TYPE_OEM, CPUID_FAMILY_486, CPUID_MODEL_I486_SX,
85: 240, cpuid_i486_sx_freq, "Intel 486SX"
86: },
87: {
88: CPUID_TYPE_OEM, CPUID_FAMILY_486, CPUID_MODEL_I486_DX2,
89: 240, cpuid_i486_dx2_freq, "Intel 486DX2"
90: },
91: {
92: CPUID_TYPE_OEM, CPUID_FAMILY_486, CPUID_MODEL_I486_SL,
93: 240, cpuid_i486_sl_freq, "Intel 486SL"
94: },
95: {
96: CPUID_TYPE_OEM, CPUID_FAMILY_486, CPUID_MODEL_I486_SX2,
97: 240, cpuid_i486_sx2_freq, "Intel 486SX2"
98: },
99: {
100: CPUID_TYPE_OEM, CPUID_FAMILY_486, CPUID_MODEL_I486_DX2WB,
101: 240, cpuid_i486_dx2wb_freq, "Intel 486DX2WB"
102: },
103: {
104: CPUID_TYPE_OEM, CPUID_FAMILY_486, CPUID_MODEL_I486_DX4,
105: 240, cpuid_i486_dx4_freq, "Intel 486DX4"
106: },
107: {
108: CPUID_TYPE_OVERDRIVE, CPUID_FAMILY_486, CPUID_MODEL_I486_DX2,
109: 240, cpuid_i486_dx2_freq, "Intel 486DX2 OverDrive"
110: },
111: {
112: CPUID_TYPE_OVERDRIVE, CPUID_FAMILY_486, CPUID_MODEL_I486_DX2WB,
113: 240, cpuid_i486_dx2wb_od_freq, "Intel 486DX2WB OverDrive"
114: },
115: {
116: CPUID_TYPE_OVERDRIVE, CPUID_FAMILY_486, CPUID_MODEL_I486_DX4,
117: 240, cpuid_i486_dx4_od_freq, "Intel 486DX4 OverDrive"
118: },
119: {
120: CPUID_TYPE_OVERDRIVE, CPUID_FAMILY_P5, CPUID_MODEL_P24T,
121: 208, cpuid_p24t_freq, "Intel Pentium P24T OverDrive"
122: },
123: {
124: CPUID_TYPE_OVERDRIVE, CPUID_FAMILY_P5, CPUID_MODEL_P54,
125: 207, cpuid_p24ct_freq, "Intel Pentium P24CT OverDrive"
126: },
127: {
128: CPUID_TYPE_OEM, CPUID_FAMILY_P5, CPUID_MODEL_P5A,
129: 207, cpuid_p5_freq, "Intel Pentium P5 rev A"
130: },
131: {
132: CPUID_TYPE_OEM, CPUID_FAMILY_P5, CPUID_MODEL_P5,
133: 207, cpuid_p5_freq, "Intel Pentium P5"
134: },
135: {
136: CPUID_TYPE_OEM, CPUID_FAMILY_P5, CPUID_MODEL_P54,
137: 207, cpuid_p54_freq, "Intel Pentium P54"
138: },
139: {
140: CPUID_TYPE_OEM, CPUID_FAMILY_PPRO, CPUID_MODEL_PII,
141: 480, cpuid_pii_freq, "Intel Pentium II"
142: }
143: };
144: unsigned int cpuid_intel_size = sizeof (cpuid_intel) / sizeof (cpuid_intel[0]);
145:
146: /*
147: * AMD product arrays
148: */
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 };
153:
154: /*
155: * UMC product array
156: */
157: unsigned int cpuid_u5sd_freq[] = { 25, 33, 40, 0 };
158: unsigned int cpuid_u5s_freq[] = { 25, 33, 40, 0 };
159:
160: /*
161: * Vendor ID array
162: */
163: struct cpuid_name cpuid_name[] = {
164: { CPUID_VID_INTEL,
165: cpuid_intel, sizeof (cpuid_intel) / sizeof (cpuid_intel[0])
166: },
167: { CPUID_VID_UMC,
168: (struct cpuid_product *)0,
169: },
170: { CPUID_VID_AMD,
171: (struct cpuid_product *)0,
172: },
173: { CPUID_VID_CYRIX,
174: (struct cpuid_product *)0,
175: },
176: { CPUID_VID_NEXTGEN,
177: (struct cpuid_product *)0
178: },
179: { "",
180: cpuid_generic, sizeof (cpuid_generic) / sizeof (cpuid_generic[0])
181: },
182: { (char *)0,
183: }
184: };
185:
186: /*
187: * Feature Flag values
188: */
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 */
200: "(bit 10)",
201: "(bit 11)",
202: "MTRR", /* Machine Type Range Register */
203: "PGE", /* Page Global Enable */
204: "MCA", /* Machine Check Architecture */
205: "CMOV", /* Conditional Move Instruction Supported */
206: "(bit 16)",
207: "(bit 17)",
208: "(bit 18)",
209: "(bit 19)",
210: "(bit 20)",
211: "(bit 21)",
212: "(bit 22)",
213: "MMX", /* Supports MMX instructions */
214: "(bit 24)",
215: "(bit 25)",
216: "(bit 26)",
217: "(bit 27)",
218: "(bit 28)",
219: "(bit 29)",
220: "(bit 30)",
221: "(bit 31)",
222: };
223:
224: /*
225: * Cache description array
226: */
227: struct cpuid_cache_desc cpuid_cache_desc[] = {
228: { CPUID_CACHE_ITLB_4K,
229: "Instruction TBL, 4K, pages 4-way set associative, 64 entries"
230: },
231: { CPUID_CACHE_ITLB_4M,
232: "Instruction TBL, 4M, pages 4-way set associative, 4 entries"
233: },
234: { CPUID_CACHE_DTLB_4K,
235: "Data TBL, 4K pages, 4-way set associative, 64 entries"
236: },
237: { CPUID_CACHE_DTLB_4M,
238: "Data TBL, 4M pages, 4-way set associative, 4 entries"
239: },
240: { CPUID_CACHE_ICACHE_8K,
241: "Instruction L1 cache, 8K, 4-way set associative, 32byte line size"
242: },
243: { CPUID_CACHE_DCACHE_8K,
244: "Data L1 cache, 8K, 2-way set associative, 32byte line size"
245: },
246: { CPUID_CACHE_UCACHE_128K,
247: "Unified L2 cache, 128K, 4-way set associative, 32byte line size"
248: },
249: { CPUID_CACHE_UCACHE_256K,
250: "Unified L2 cache, 256K, 4-way set associative, 32byte line size"
251: },
252: { CPUID_CACHE_UCACHE_512K,
253: "Unified L2 cache, 512K, 4-way set associative, 32byte line size"
254: },
255: { CPUID_CACHE_NULL,
256: (char *)0
257: }
258: };
259:
260: /*
261: * CPU identification
262: */
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];
271:
272: /*
273: * Return correct CPU_TYPE
274: */
275: /*ARGSUSED*/
276: cpu_type_t
277: cpuid_cputype(
278: int my_cpu)
279: {
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);
288: default:
289: break;
290: }
291: #endif
292: return (CPU_TYPE_I386);
293: }
294:
295: /*
296: * Display processor signature
297: */
298: /*ARGSUSED*/
299: void
300: cpuid_cpu_display(
301: char *header,
302: int my_cpu)
303: {
304: struct cpuid_name *name;
305: unsigned int i;
306: unsigned int *freq;
307: unsigned int mhz;
308: unsigned int feature;
309: char **flag;
310: extern unsigned int delaycount;
311:
312: /*
313: * Identify vendor ID
314: */
315: for (name = cpuid_name; name->name != (char *)0; name++) {
316: char *p = name->name;
317: char *q = cpuid_vid;
318: while (*p == *q && *p != 0) {
319: p++;
320: q++;
321: }
322: if (*p == '\0' && *q == '\0')
323: break;
324: }
325: if (name->name == (char *)0) {
326: printf("Unrecognized processor vendor id = '%s'\n", cpuid_vid);
327: return;
328: }
329:
330: /*
331: * Identify Product ID
332: */
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)
337: break;
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);
341: return;
342: }
343:
344: /*
345: * Look for frequency and adjust it to known values
346: */
347: mhz = (1000 * delaycount) / name->product[i].delay;
348: for (freq = name->product[i].frequency; *freq != 0; freq++)
349: if (*freq >= mhz)
350: break;
351: if (*freq == 0)
352: mhz = *(freq - 1);
353: else if (freq == name->product[i].frequency)
354: mhz = *freq;
355: else if (*freq - mhz > mhz - *(freq - 1))
356: mhz = *(freq - 1);
357: else if (*freq != mhz)
358: mhz = *freq;
359:
360: /*
361: * Display product and frequency
362: */
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);
366:
367: /*
368: * Display feature (if any)
369: */
370: if (cpuid_feature) {
371: i = 0;
372: flag = cpuid_flag;
373: for (feature = cpuid_feature; feature != 0; feature >>= 1) {
374: if (feature & 1)
375: if (i == 0) {
376: printf("%s: %s", header, *flag);
377: i = 1;
378: } else
379: printf(", %s", *flag);
380: flag++;
381: }
382: printf("\n");
383: }
384: }
385:
386: /*
387: * Display processor configuration information
388: */
389: /*ARGSUSED*/
390: void
391: cpuid_cache_display(
392: char *header,
393: int my_cpu)
394: {
395: struct cpuid_cache_desc *desc;
396: unsigned int i;
397:
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)
401: continue;
402: for (desc = cpuid_cache_desc;
403: desc->description != (char *)0; desc++)
404: if (desc->value == cpuid_cache[i])
405: break;
406: if (desc->description != (char *)0)
407: printf("%s: %s\n", header, desc->description);
408: }
409: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.