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

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

1.1       nbrk        1: /*     $OpenBSD: amd64errata.c,v 1.1 2007/02/17 17:35:43 tom Exp $     */
                      2: /*     $NetBSD: errata.c,v 1.6 2007/02/05 21:05:45 ad Exp $    */
                      3:
                      4: /*-
                      5:  * Copyright (c) 2007 The NetBSD Foundation, Inc.
                      6:  * All rights reserved.
                      7:  *
                      8:  * This code is derived from software contributed to The NetBSD Foundation
                      9:  * by Andrew Doran.
                     10:  *
                     11:  * Redistribution and use in source and binary forms, with or without
                     12:  * modification, are permitted provided that the following conditions
                     13:  * are met:
                     14:  * 1. Redistributions of source code must retain the above copyright
                     15:  *    notice, this list of conditions and the following disclaimer.
                     16:  * 2. Redistributions in binary form must reproduce the above copyright
                     17:  *    notice, this list of conditions and the following disclaimer in the
                     18:  *    documentation and/or other materials provided with the distribution.
                     19:  * 3. All advertising materials mentioning features or use of this software
                     20:  *    must display the following acknowledgement:
                     21:  *     This product includes software developed by the NetBSD
                     22:  *     Foundation, Inc. and its contributors.
                     23:  * 4. Neither the name of The NetBSD Foundation nor the names of its
                     24:  *    contributors may be used to endorse or promote products derived
                     25:  *    from this software without specific prior written permission.
                     26:  *
                     27:  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
                     28:  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
                     29:  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
                     30:  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
                     31:  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
                     32:  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
                     33:  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
                     34:  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
                     35:  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
                     36:  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
                     37:  * POSSIBILITY OF SUCH DAMAGE.
                     38:  */
                     39:
                     40: /*
                     41:  * Detect, report on, and work around known errata with AMD's amd64 CPUs.
                     42:  *
                     43:  * This is generalised because there are quite a few problems that the
                     44:  * BIOS can patch via MSR, but it is not known if the OS can patch these
                     45:  * yet.  The list is expected to grow over time.
                     46:  *
                     47:  * The data here are from: Revision Guide for AMD Athlon 64 and
                     48:  * AMD Opteron Processors, Publication #25759, Revision: 3.69,
                     49:  * Issue Date: September 2006
                     50:  */
                     51:
                     52: #include <sys/param.h>
                     53:
                     54: #include <sys/types.h>
                     55: #include <sys/systm.h>
                     56:
                     57: #include <machine/cpu.h>
                     58: #include <machine/cpufunc.h>
                     59: #include <machine/specialreg.h>
                     60:
                     61:
                     62: typedef struct errata {
                     63:        u_short         e_num;
                     64:        u_short         e_reported;
                     65:        u_int           e_data1;
                     66:        const uint8_t   *e_set;
                     67:        int             (*e_act)(struct cpu_info *, struct errata *);
                     68:        uint64_t        e_data2;
                     69: } errata_t;
                     70:
                     71: typedef enum cpurev {
                     72:        BH_E4, CH_CG, CH_D0, DH_CG, DH_D0, DH_E3, DH_E6, JH_E1,
                     73:        JH_E6, SH_B0, SH_B3, SH_C0, SH_CG, SH_D0, SH_E4, SH_E5,
                     74:        OINK
                     75: } cpurev_t;
                     76:
                     77: static const u_int cpurevs[] = {
                     78:        BH_E4, 0x0020fb1, CH_CG, 0x0000f82, CH_CG, 0x0000fb2,
                     79:        CH_D0, 0x0010f80, CH_D0, 0x0010fb0, DH_CG, 0x0000fc0,
                     80:        DH_CG, 0x0000fe0, DH_CG, 0x0000ff0, DH_D0, 0x0010fc0,
                     81:        DH_D0, 0x0010ff0, DH_E3, 0x0020fc0, DH_E3, 0x0020ff0,
                     82:        DH_E6, 0x0020fc2, DH_E6, 0x0020ff2, JH_E1, 0x0020f10,
                     83:        JH_E6, 0x0020f12, JH_E6, 0x0020f32, SH_B0, 0x0000f40,
                     84:        SH_B3, 0x0000f51, SH_C0, 0x0000f48, SH_C0, 0x0000f58,
                     85:        SH_CG, 0x0000f4a, SH_CG, 0x0000f5a, SH_CG, 0x0000f7a,
                     86:        SH_D0, 0x0010f40, SH_D0, 0x0010f50, SH_D0, 0x0010f70,
                     87:        SH_E4, 0x0020f51, SH_E4, 0x0020f71, SH_E5, 0x0020f42,
                     88:        OINK
                     89: };
                     90:
                     91: static const uint8_t amd64_errata_set1[] = {
                     92:        SH_B3, SH_C0, SH_CG, DH_CG, CH_CG, OINK
                     93: };
                     94:
                     95: static const uint8_t amd64_errata_set2[] = {
                     96:        SH_B3, SH_C0, SH_CG, DH_CG, CH_CG, SH_D0, DH_D0, CH_D0, OINK
                     97: };
                     98:
                     99: static const uint8_t amd64_errata_set3[] = {
                    100:        JH_E1, DH_E3, OINK
                    101: };
                    102:
                    103: static const uint8_t amd64_errata_set4[] = {
                    104:        SH_C0, SH_CG, DH_CG, CH_CG, SH_D0, DH_D0, CH_D0, JH_E1,
                    105:        DH_E3, SH_E4, BH_E4, SH_E5, DH_E6, JH_E6, OINK
                    106: };
                    107:
                    108: static const uint8_t amd64_errata_set5[] = {
                    109:        SH_B3, OINK
                    110: };
                    111:
                    112: static const uint8_t amd64_errata_set6[] = {
                    113:        SH_C0, SH_CG, DH_CG, CH_CG, OINK
                    114: };
                    115:
                    116: static const uint8_t amd64_errata_set7[] = {
                    117:        SH_C0, SH_CG, DH_CG, CH_CG, SH_D0, DH_D0, CH_D0, OINK
                    118: };
                    119:
                    120: static const uint8_t amd64_errata_set8[] = {
                    121:        BH_E4, CH_CG, CH_CG, CH_D0, CH_D0, DH_CG, DH_CG, DH_CG,
                    122:        DH_D0, DH_D0, DH_E3, DH_E3, DH_E6, DH_E6, JH_E1, JH_E6,
                    123:        JH_E6, SH_B0, SH_B3, SH_C0, SH_C0, SH_CG, SH_CG, SH_CG,
                    124:        SH_D0, SH_D0, SH_D0, SH_E4, SH_E4, SH_E5, OINK
                    125: };
                    126:
                    127: static int amd64_errata_setmsr(struct cpu_info *, errata_t *);
                    128: static int amd64_errata_testmsr(struct cpu_info *, errata_t *);
                    129:
                    130: static errata_t errata[] = {
                    131:        /*
                    132:         * 81: Cache Coherency Problem with Hardware Prefetching
                    133:         * and Streaming Stores
                    134:         */
                    135:        {
                    136:                81, 0, MSR_DC_CFG, amd64_errata_set5,
                    137:                amd64_errata_testmsr, DC_CFG_DIS_SMC_CHK_BUF
                    138:        },
                    139:        /*
                    140:         * 86: DRAM Data Masking Feature Can Cause ECC Failures
                    141:         */
                    142:        {
                    143:                86, 0, MSR_NB_CFG, amd64_errata_set1,
                    144:                amd64_errata_testmsr, NB_CFG_DISDATMSK
                    145:        },
                    146:        /*
                    147:         * 89: Potential Deadlock With Locked Transactions
                    148:         */
                    149:        {
                    150:                89, 0, MSR_NB_CFG, amd64_errata_set8,
                    151:                amd64_errata_testmsr, NB_CFG_DISIOREQLOCK
                    152:        },
                    153:        /*
                    154:         * 94: Sequential Prefetch Feature May Cause Incorrect
                    155:         * Processor Operation
                    156:         */
                    157:        {
                    158:                94, 0, MSR_IC_CFG, amd64_errata_set1,
                    159:                amd64_errata_testmsr, IC_CFG_DIS_SEQ_PREFETCH
                    160:        },
                    161:        /*
                    162:         * 97: 128-Bit Streaming Stores May Cause Coherency
                    163:         * Failure
                    164:         *
                    165:         * XXX "This workaround must not be applied to processors
                    166:         * prior to revision C0."  We don't apply it, but if it
                    167:         * can't be applied, it shouldn't be reported.
                    168:         */
                    169:        {
                    170:                97, 0, MSR_DC_CFG, amd64_errata_set6,
                    171:                amd64_errata_testmsr, DC_CFG_DIS_CNV_WC_SSO
                    172:        },
                    173:        /*
                    174:         * 104: DRAM Data Masking Feature Causes ChipKill ECC
                    175:         * Failures When Enabled With x8/x16 DRAM Devices
                    176:         */
                    177:        {
                    178:                104, 0, MSR_NB_CFG, amd64_errata_set7,
                    179:                amd64_errata_testmsr, NB_CFG_DISDATMSK
                    180:        },
                    181:        /*
                    182:         * 113: Enhanced Write-Combining Feature Causes System Hang
                    183:         */
                    184:        {
                    185:                113, 0, MSR_BU_CFG, amd64_errata_set3,
                    186:                amd64_errata_setmsr, BU_CFG_WBENHWSBDIS
                    187:        },
                    188: #ifdef MULTIPROCESSOR
                    189:        /*
                    190:         * 69: Multiprocessor Coherency Problem with Hardware
                    191:         * Prefetch Mechanism
                    192:         */
                    193:        {
                    194:                69, 0, MSR_BU_CFG, amd64_errata_set5,
                    195:                amd64_errata_setmsr, BU_CFG_WBPFSMCCHKDIS
                    196:        },
                    197:        /*
                    198:         * 101: DRAM Scrubber May Cause Data Corruption When Using
                    199:         * Node-Interleaved Memory
                    200:         */
                    201:        {
                    202:                101, 0, 0, amd64_errata_set2,
                    203:                NULL, 0
                    204:        },
                    205:        /*
                    206:         * 106: Potential Deadlock with Tightly Coupled Semaphores
                    207:         * in an MP System
                    208:         */
                    209:        {
                    210:                106, 0, MSR_LS_CFG, amd64_errata_set2,
                    211:                amd64_errata_testmsr, LS_CFG_DIS_LS2_SQUISH
                    212:        },
                    213:        /*
                    214:         * 107: Possible Multiprocessor Coherency Problem with
                    215:         * Setting Page Table A/D Bits
                    216:         */
                    217:        {
                    218:                107, 0, MSR_BU_CFG, amd64_errata_set2,
                    219:                amd64_errata_testmsr, BU_CFG_THRL2IDXCMPDIS
                    220:        },
                    221: #if 0
                    222:        /*
                    223:         * 122: TLB Flush Filter May Cause Coherency Problem in
                    224:         * Multiprocessor Systems
                    225:         */
                    226:        {
                    227:                122, 0, MSR_HWCR, amd64_errata_set4,
                    228:                amd64_errata_setmsr, HWCR_FFDIS
                    229:        },
                    230: #endif
                    231: #endif /* MULTIPROCESSOR */
                    232: };
                    233:
                    234: static int
                    235: amd64_errata_testmsr(struct cpu_info *ci, errata_t *e)
                    236: {
                    237:        uint64_t val;
                    238:
                    239:        (void)ci;
                    240:
                    241:        val = rdmsr_locked(e->e_data1, OPTERON_MSR_PASSCODE);
                    242:        if ((val & e->e_data2) != 0)
                    243:                return 0;               /* not found */
                    244:
                    245:        e->e_reported = 1;
                    246:        return 1;                       /* found */
                    247: }
                    248:
                    249: static int
                    250: amd64_errata_setmsr(struct cpu_info *ci, errata_t *e)
                    251: {
                    252:        uint64_t val;
                    253:
                    254:        (void)ci;
                    255:
                    256:        val = rdmsr_locked(e->e_data1, OPTERON_MSR_PASSCODE);
                    257:        if ((val & e->e_data2) != 0)
                    258:                return 0;               /* not found */
                    259:
                    260:        wrmsr_locked(e->e_data1, OPTERON_MSR_PASSCODE, val | e->e_data2);
                    261:
                    262: #ifdef ERRATA_DEBUG
                    263:        printf("ERRATA: writing a fix\n");
                    264:        val = rdmsr_locked(e->e_data1, OPTERON_MSR_PASSCODE);
                    265:        if ((val & e->e_data2) != 0)
                    266:                printf("ERRATA: fix seems to have worked!\n");
                    267: #endif
                    268:
                    269:        e->e_reported = 1;
                    270:        return 2;                       /* found and fixed */
                    271: }
                    272:
                    273: void
                    274: amd64_errata(struct cpu_info *ci)
                    275: {
                    276:        u_int32_t code, dummy;
                    277:        errata_t *e, *ex;
                    278:        cpurev_t rev;
                    279:        int i, j;
                    280:        int rc;
                    281:        int found = 0;
                    282:        int corrected = 0;
                    283:
                    284:        CPUID(0x80000001, code, dummy, dummy, dummy);
                    285:
                    286:        for (i = 0; ; i += 2) {
                    287:                if ((rev = cpurevs[i]) == OINK) {
                    288: #ifdef ERRATA_DEBUG
                    289:                        printf("ERRATA: this CPU ok\n");
                    290: #endif
                    291:                        return;
                    292:                }
                    293:                if (cpurevs[i + 1] == code) {
                    294: #ifdef ERRATA_DEBUG
                    295:                        printf("ERRATA: this CPU has errata\n");
                    296: #endif
                    297:                        break;
                    298:                }
                    299:        }
                    300:
                    301:        ex = errata + sizeof(errata) / sizeof(errata[0]);
                    302:
                    303:        /* Reset e_reporteds (for multiple CPUs) */
                    304:        for (e = errata; e < ex; e++)
                    305:                e->e_reported = 0;
                    306:
                    307:        for (e = errata; e < ex; e++) {
                    308:                if (e->e_reported)
                    309:                        continue;
                    310:                if (e->e_set != NULL) {
                    311:                        for (j = 0; e->e_set[j] != OINK; j++)
                    312:                                if (e->e_set[j] == rev)
                    313:                                        break;
                    314:                        if (e->e_set[j] == OINK)
                    315:                                continue;
                    316:                }
                    317:
                    318: #ifdef ERRATA_DEBUG
                    319:                printf("%s: testing for erratum %d\n",
                    320:                    ci->ci_dev->dv_xname, e->e_num);
                    321: #endif
                    322:
                    323:                /*
                    324:                 * If we have an action routine, call it, otherwise
                    325:                 * the default is that this erratum is present.
                    326:                 */
                    327:                rc = (e->e_act == NULL) ? 1 : (*e->e_act)(ci, e);
                    328:
                    329:                if (rc == 0)                    /* not found */
                    330:                        continue;
                    331:                if (rc == 1)
                    332:                        found++;
                    333:                if (rc == 2)
                    334:                        corrected++;
                    335:
                    336:                e->e_reported = rc;
                    337:
                    338: #ifdef ERRATA_DEBUG
                    339:                printf("%s: erratum %d present%s\n",
                    340:                    ci->ci_dev->dv_xname, e->e_num,
                    341:                    (rc == 2) ? " and patched" : "");
                    342: #endif
                    343:        }
                    344:
                    345: #define ERRATA_VERBOSE
                    346: #ifdef ERRATA_VERBOSE
                    347:        if (corrected) {
                    348:                int first = 1;
                    349:
                    350:                /* Print out found and corrected */
                    351:                printf("%s: AMD %s", ci->ci_dev->dv_xname,
                    352:                    (corrected == 1) ? "erratum" : "errata");
                    353:                for (e = errata; e < ex; e++) {
                    354:                        if (e->e_reported == 2) {
                    355:                                if (! first)
                    356:                                        printf(",");
                    357:                                printf(" %d", e->e_num);
                    358:                                first = 0;
                    359:                        }
                    360:                }
                    361:                printf(" detected and fixed\n");
                    362:        }
                    363: #endif
                    364:
                    365:        if (found) {
                    366:                int first = 1;
                    367:
                    368:                /* Print out found but not corrected */
                    369:                printf("%s: AMD %s", ci->ci_dev->dv_xname,
                    370:                    (found == 1) ? "erratum" : "errata");
                    371:                for (e = errata; e < ex; e++) {
                    372:                        if (e->e_reported == 1) {
                    373:                                if (! first)
                    374:                                        printf(",");
                    375:                                printf(" %d", e->e_num);
                    376:                                first = 0;
                    377:                        }
                    378:                }
                    379:                printf(" present, BIOS upgrade may be required\n");
                    380:        }
                    381: }

CVSweb