[BACK]Return to cacheinfo.c CVS log [TXT][DIR] Up to [local] / sys / arch / amd64 / amd64

Annotation of sys/arch/amd64/amd64/cacheinfo.c, Revision 1.1.1.1

1.1       nbrk        1: /*     $OpenBSD: cacheinfo.c,v 1.3 2006/05/09 13:02:29 mickey Exp $    */
                      2:
                      3: /*-
                      4:  * Copyright (c) 2000 The NetBSD Foundation, Inc.
                      5:  * All rights reserved.
                      6:  *
                      7:  * This code is derived from software contributed to The NetBSD Foundation
                      8:  * by Jason R. Thorpe.
                      9:  *
                     10:  * Redistribution and use in source and binary forms, with or without
                     11:  * modification, are permitted provided that the following conditions
                     12:  * are met:
                     13:  * 1. Redistributions of source code must retain the above copyright
                     14:  *    notice, this list of conditions and the following disclaimer.
                     15:  * 2. Redistributions in binary form must reproduce the above copyright
                     16:  *    notice, this list of conditions and the following disclaimer in the
                     17:  *    documentation and/or other materials provided with the distribution.
                     18:  * 3. All advertising materials mentioning features or use of this software
                     19:  *    must display the following acknowledgement:
                     20:  *      This product includes software developed by the NetBSD
                     21:  *      Foundation, Inc. and its contributors.
                     22:  * 4. Neither the name of The NetBSD Foundation nor the names of its
                     23:  *    contributors may be used to endorse or promote products derived
                     24:  *    from this software without specific prior written permission.
                     25:  *
                     26:  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
                     27:  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
                     28:  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
                     29:  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
                     30:  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
                     31:  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
                     32:  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
                     33:  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
                     34:  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
                     35:  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
                     36:  * POSSIBILITY OF SUCH DAMAGE.
                     37:  */
                     38:
                     39: #include <sys/param.h>
                     40: #include <sys/systm.h>
                     41:
                     42: #include <machine/cpu.h>
                     43: #include <machine/specialreg.h>
                     44:
                     45: static char *print_cache_config(struct cpu_info *, int, char *, char *);
                     46: static char *print_tlb_config(struct cpu_info *, int, char *, char *);
                     47:
                     48: static char *
                     49: print_cache_config(struct cpu_info *ci, int cache_tag, char *name, char *sep)
                     50: {
                     51:        struct x86_cache_info *cai = &ci->ci_cinfo[cache_tag];
                     52:
                     53:        if (cai->cai_totalsize == 0)
                     54:                return sep;
                     55:
                     56:        if (sep == NULL)
                     57:                printf("%s: ", ci->ci_dev->dv_xname);
                     58:        else
                     59:                printf("%s", sep);
                     60:
                     61:        if (cai->cai_string != NULL)
                     62:                printf("%s ", cai->cai_string);
                     63:        else if (cai->cai_totalsize >= 1024*1024)
                     64:                printf("%dMB %db/line ", cai->cai_totalsize / 1024 / 1024,
                     65:                    cai->cai_linesize);
                     66:        else
                     67:                printf("%dKB %db/line ", cai->cai_totalsize / 1024,
                     68:                    cai->cai_linesize);
                     69:
                     70:        switch (cai->cai_associativity) {
                     71:        case    0:
                     72:                printf("disabled");
                     73:                break;
                     74:        case    1:
                     75:                printf("direct-mapped");
                     76:                break;
                     77:        case 0xff:
                     78:                printf("fully associative");
                     79:                break;
                     80:        default:
                     81:                printf("%d-way", cai->cai_associativity);
                     82:                break;
                     83:        }
                     84:
                     85:        if (name != NULL)
                     86:                printf(" %s", name);
                     87:
                     88:        return ", ";
                     89: }
                     90:
                     91: static char *
                     92: print_tlb_config(struct cpu_info *ci, int cache_tag, char *name, char *sep)
                     93: {
                     94:        struct x86_cache_info *cai = &ci->ci_cinfo[cache_tag];
                     95:
                     96:        if (cai->cai_totalsize == 0)
                     97:                return sep;
                     98:
                     99:        if (sep == NULL)
                    100:                printf("%s: ", ci->ci_dev->dv_xname);
                    101:        else
                    102:                printf("%s", sep);
                    103:        if (name != NULL)
                    104:                printf("%s ", name);
                    105:
                    106:        if (cai->cai_string != NULL) {
                    107:                printf("%s", cai->cai_string);
                    108:        } else {
                    109:                if (cai->cai_linesize >= 1024*1024)
                    110:                        printf("%d %dMB entries ", cai->cai_totalsize,
                    111:                            cai->cai_linesize / 1024 / 1024);
                    112:                else
                    113:                        printf("%d %dKB entries ", cai->cai_totalsize,
                    114:                            cai->cai_linesize / 1024);
                    115:                switch (cai->cai_associativity) {
                    116:                case 0:
                    117:                        printf("disabled");
                    118:                        break;
                    119:                case 1:
                    120:                        printf("direct-mapped");
                    121:                        break;
                    122:                case 0xff:
                    123:                        printf("fully associative");
                    124:                        break;
                    125:                default:
                    126:                        printf("%d-way", cai->cai_associativity);
                    127:                        break;
                    128:                }
                    129:        }
                    130:        return ", ";
                    131: }
                    132:
                    133: const struct x86_cache_info *
                    134: cache_info_lookup(const struct x86_cache_info *cai, u_int8_t desc)
                    135: {
                    136:        int i;
                    137:
                    138:        for (i = 0; cai[i].cai_desc != 0; i++) {
                    139:                if (cai[i].cai_desc == desc)
                    140:                        return (&cai[i]);
                    141:        }
                    142:
                    143:        return (NULL);
                    144: }
                    145:
                    146:
                    147: static const struct x86_cache_info amd_cpuid_l2cache_assoc_info[] = {
                    148:        { 0, 0x01,    1 },
                    149:        { 0, 0x02,    2 },
                    150:        { 0, 0x04,    4 },
                    151:        { 0, 0x06,    8 },
                    152:        { 0, 0x08,   16 },
                    153:        { 0, 0x0f, 0xff },
                    154:        { 0, 0x00,    0 },
                    155: };
                    156:
                    157: void
                    158: amd_cpu_cacheinfo(struct cpu_info *ci)
                    159: {
                    160:        const struct x86_cache_info *cp;
                    161:        struct x86_cache_info *cai;
                    162:        int family, model;
                    163:        u_int descs[4];
                    164:        u_int lfunc;
                    165:
                    166:        family = (ci->ci_signature >> 8) & 15;
                    167:        model = CPUID2MODEL(ci->ci_signature);
                    168:
                    169:        /*
                    170:         * K5 model 0 has none of this info.
                    171:         */
                    172:        if (family == 5 && model == 0)
                    173:                return;
                    174:
                    175:        /*
                    176:         * Get extended values for K8 and up.
                    177:         */
                    178:        if (family == 0xf) {
                    179:                family += (ci->ci_signature >> 20) & 0xff;
                    180:                model += (ci->ci_signature >> 16) & 0xf;
                    181:        }
                    182:
                    183:        /*
                    184:         * Determine the largest extended function value.
                    185:         */
                    186:        CPUID(0x80000000, descs[0], descs[1], descs[2], descs[3]);
                    187:        lfunc = descs[0];
                    188:
                    189:        /*
                    190:         * Determine L1 cache/TLB info.
                    191:         */
                    192:        if (lfunc < 0x80000005) {
                    193:                /* No L1 cache info available. */
                    194:                return;
                    195:        }
                    196:
                    197:        CPUID(0x80000005, descs[0], descs[1], descs[2], descs[3]);
                    198:
                    199:        /*
                    200:         * K6-III and higher have large page TLBs.
                    201:         */
                    202:        if ((family == 5 && model >= 9) || family >= 6) {
                    203:                cai = &ci->ci_cinfo[CAI_ITLB2];
                    204:                cai->cai_totalsize = AMD_L1_EAX_ITLB_ENTRIES(descs[0]);
                    205:                cai->cai_associativity = AMD_L1_EAX_ITLB_ASSOC(descs[0]);
                    206:                cai->cai_linesize = (4 * 1024 * 1024);
                    207:
                    208:                cai = &ci->ci_cinfo[CAI_DTLB2];
                    209:                cai->cai_totalsize = AMD_L1_EAX_DTLB_ENTRIES(descs[0]);
                    210:                cai->cai_associativity = AMD_L1_EAX_DTLB_ASSOC(descs[0]);
                    211:                cai->cai_linesize = (4 * 1024 * 1024);
                    212:        }
                    213:
                    214:        cai = &ci->ci_cinfo[CAI_ITLB];
                    215:        cai->cai_totalsize = AMD_L1_EBX_ITLB_ENTRIES(descs[1]);
                    216:        cai->cai_associativity = AMD_L1_EBX_ITLB_ASSOC(descs[1]);
                    217:        cai->cai_linesize = (4 * 1024);
                    218:
                    219:        cai = &ci->ci_cinfo[CAI_DTLB];
                    220:        cai->cai_totalsize = AMD_L1_EBX_DTLB_ENTRIES(descs[1]);
                    221:        cai->cai_associativity = AMD_L1_EBX_DTLB_ASSOC(descs[1]);
                    222:        cai->cai_linesize = (4 * 1024);
                    223:
                    224:        cai = &ci->ci_cinfo[CAI_DCACHE];
                    225:        cai->cai_totalsize = AMD_L1_ECX_DC_SIZE(descs[2]);
                    226:        cai->cai_associativity = AMD_L1_ECX_DC_ASSOC(descs[2]);
                    227:        cai->cai_linesize = AMD_L1_EDX_IC_LS(descs[2]);
                    228:
                    229:        cai = &ci->ci_cinfo[CAI_ICACHE];
                    230:        cai->cai_totalsize = AMD_L1_EDX_IC_SIZE(descs[3]);
                    231:        cai->cai_associativity = AMD_L1_EDX_IC_ASSOC(descs[3]);
                    232:        cai->cai_linesize = AMD_L1_EDX_IC_LS(descs[3]);
                    233:
                    234:        /*
                    235:         * Determine L2 cache/TLB info.
                    236:         */
                    237:        if (lfunc < 0x80000006) {
                    238:                /* No L2 cache info available. */
                    239:                return;
                    240:        }
                    241:
                    242:        CPUID(0x80000006, descs[0], descs[1], descs[2], descs[3]);
                    243:
                    244:        cai = &ci->ci_cinfo[CAI_L2CACHE];
                    245:        cai->cai_totalsize = AMD_L2_ECX_C_SIZE(descs[2]);
                    246:        cai->cai_associativity = AMD_L2_ECX_C_ASSOC(descs[2]);
                    247:        cai->cai_linesize = AMD_L2_ECX_C_LS(descs[2]);
                    248:
                    249:        cp = cache_info_lookup(amd_cpuid_l2cache_assoc_info,
                    250:            cai->cai_associativity);
                    251:        if (cp != NULL)
                    252:                cai->cai_associativity = cp->cai_associativity;
                    253:        else
                    254:                cai->cai_associativity = 0;     /* XXX Unknown/reserved */
                    255: }
                    256:
                    257: void
                    258: x86_print_cacheinfo(struct cpu_info *ci)
                    259: {
                    260:        char *sep;
                    261:
                    262:        sep = NULL;
                    263:        if (ci->ci_cinfo[CAI_ICACHE].cai_totalsize != 0 ||
                    264:            ci->ci_cinfo[CAI_DCACHE].cai_totalsize != 0) {
                    265:                sep = print_cache_config(ci, CAI_ICACHE, "I-cache", NULL);
                    266:                sep = print_cache_config(ci, CAI_DCACHE, "D-cache", sep);
                    267:        }
                    268:        if (ci->ci_cinfo[CAI_L2CACHE].cai_totalsize != 0) {
                    269:                sep = print_cache_config(ci, CAI_L2CACHE, "L2 cache", sep);
                    270:                if (sep != NULL)
                    271:                        printf("\n");
                    272:        }
                    273:        if (ci->ci_cinfo[CAI_ITLB].cai_totalsize != 0) {
                    274:                sep = print_tlb_config(ci, CAI_ITLB, "ITLB", NULL);
                    275:                sep = print_tlb_config(ci, CAI_ITLB2, NULL, sep);
                    276:                if (sep != NULL)
                    277:                        printf("\n");
                    278:        }
                    279:        if (ci->ci_cinfo[CAI_DTLB].cai_totalsize != 0) {
                    280:                sep = print_tlb_config(ci, CAI_DTLB, "DTLB", NULL);
                    281:                sep = print_tlb_config(ci, CAI_DTLB2, NULL, sep);
                    282:                if (sep != NULL)
                    283:                        printf("\n");
                    284:        }
                    285: }

CVSweb