Annotation of XNU/osfmk/i386/cpuid.c, revision 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.