[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     ! 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