|
|
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.