Annotation of XNU/osfmk/i386/cpuid.c, revision 1.1.1.1

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: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.