1 /* $NetBSD: errata.c,v 1.16 2008/05/21 01:16:20 ad Exp $ */ 2 3 /*- 4 * Copyright (c) 2007 The NetBSD Foundation, Inc. 5 * All rights reserved. 6 * 7 * This code is derived from software contributed to The NetBSD Foundation 8 * by Andrew Doran. 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 * 19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 * POSSIBILITY OF SUCH DAMAGE. 30 */ 31 32 /* 33 * Detect, report on, and work around known errata with x86 CPUs. 34 * 35 * This currently only handles AMD CPUs, and is generalised because 36 * there are quite a few problems that the BIOS can patch via MSR, 37 * but it is not known if the OS can patch these yet. The list is 38 * expected to grow over time. 39 * 40 * The data here are from: Revision Guide for AMD Athlon 64 and 41 * AMD Opteron Processors, Publication #25759, Revision: 3.69, 42 * Issue Date: September 2006 43 * 44 * XXX This should perhaps be integrated with the identcpu code. 45 */ 46 47 #include <sys/cdefs.h> 48 __KERNEL_RCSID(0, "$NetBSD: errata.c,v 1.16 2008/05/21 01:16:20 ad Exp $"); 49 50 #include <sys/types.h> 51 #include <sys/systm.h> 52 53 #include <machine/cpu.h> 54 #include <machine/cpufunc.h> 55 #include <machine/specialreg.h> 56 57 #include <x86/cpuvar.h> 58 #include <x86/cputypes.h> 59 60 typedef struct errata { 61 u_short e_num; 62 u_short e_reported; 63 u_int e_data1; 64 const uint8_t *e_set; 65 bool (*e_act)(struct cpu_info *, struct errata *); 66 uint64_t e_data2; 67 } errata_t; 68 69 typedef enum cpurev { 70 BH_E4, CH_CG, CH_D0, DH_CG, DH_D0, DH_E3, DH_E6, JH_E1, 71 JH_E6, SH_B0, SH_B3, SH_C0, SH_CG, SH_D0, SH_E4, SH_E5, 72 OINK 73 } cpurev_t; 74 75 static const u_int cpurevs[] = { 76 BH_E4, 0x0020fb1, CH_CG, 0x0000f82, CH_CG, 0x0000fb2, 77 CH_D0, 0x0010f80, CH_D0, 0x0010fb0, DH_CG, 0x0000fc0, 78 DH_CG, 0x0000fe0, DH_CG, 0x0000ff0, DH_D0, 0x0010fc0, 79 DH_D0, 0x0010ff0, DH_E3, 0x0020fc0, DH_E3, 0x0020ff0, 80 DH_E6, 0x0020fc2, DH_E6, 0x0020ff2, JH_E1, 0x0020f10, 81 JH_E6, 0x0020f12, JH_E6, 0x0020f32, SH_B0, 0x0000f40, 82 SH_B3, 0x0000f51, SH_C0, 0x0000f48, SH_C0, 0x0000f58, 83 SH_CG, 0x0000f4a, SH_CG, 0x0000f5a, SH_CG, 0x0000f7a, 84 SH_D0, 0x0010f40, SH_D0, 0x0010f50, SH_D0, 0x0010f70, 85 SH_E4, 0x0020f51, SH_E4, 0x0020f71, SH_E5, 0x0020f42, 86 OINK 87 }; 88 89 static const uint8_t x86_errata_set1[] = { 90 SH_B3, SH_C0, SH_CG, DH_CG, CH_CG, OINK 91 }; 92 93 static const uint8_t x86_errata_set2[] = { 94 SH_B3, SH_C0, SH_CG, DH_CG, CH_CG, SH_D0, DH_D0, CH_D0, OINK 95 }; 96 97 static const uint8_t x86_errata_set3[] = { 98 JH_E1, DH_E3, OINK 99 }; 100 101 static const uint8_t x86_errata_set4[] = { 102 SH_C0, SH_CG, DH_CG, CH_CG, SH_D0, DH_D0, CH_D0, JH_E1, 103 DH_E3, SH_E4, BH_E4, SH_E5, DH_E6, JH_E6, OINK 104 }; 105 106 static const uint8_t x86_errata_set5[] = { 107 SH_B3, OINK 108 }; 109 110 static const uint8_t x86_errata_set6[] = { 111 SH_C0, SH_CG, DH_CG, CH_CG, OINK 112 }; 113 114 static const uint8_t x86_errata_set7[] = { 115 SH_C0, SH_CG, DH_CG, CH_CG, SH_D0, DH_D0, CH_D0, OINK 116 }; 117 118 static const uint8_t x86_errata_set8[] = { 119 BH_E4, CH_CG, CH_CG, CH_D0, CH_D0, DH_CG, DH_CG, DH_CG, 120 DH_D0, DH_D0, DH_E3, DH_E3, DH_E6, DH_E6, JH_E1, JH_E6, 121 JH_E6, SH_B0, SH_B3, SH_C0, SH_C0, SH_CG, SH_CG, SH_CG, 122 SH_D0, SH_D0, SH_D0, SH_E4, SH_E4, SH_E5, OINK 123 }; 124 125 static bool x86_errata_setmsr(struct cpu_info *, errata_t *); 126 static bool x86_errata_testmsr(struct cpu_info *, errata_t *); 127 128 static errata_t errata[] = { 129 /* 130 * 81: Cache Coherency Problem with Hardware Prefetching 131 * and Streaming Stores 132 */ 133 { 134 81, FALSE, MSR_DC_CFG, x86_errata_set5, 135 x86_errata_testmsr, DC_CFG_DIS_SMC_CHK_BUF 136 }, 137 /* 138 * 86: DRAM Data Masking Feature Can Cause ECC Failures 139 */ 140 { 141 86, FALSE, MSR_NB_CFG, x86_errata_set1, 142 x86_errata_testmsr, NB_CFG_DISDATMSK 143 }, 144 /* 145 * 89: Potential Deadlock With Locked Transactions 146 */ 147 { 148 89, FALSE, MSR_NB_CFG, x86_errata_set8, 149 x86_errata_testmsr, NB_CFG_DISIOREQLOCK 150 }, 151 /* 152 * 94: Sequential Prefetch Feature May Cause Incorrect 153 * Processor Operation 154 */ 155 { 156 94, FALSE, MSR_IC_CFG, x86_errata_set1, 157 x86_errata_testmsr, IC_CFG_DIS_SEQ_PREFETCH 158 }, 159 /* 160 * 97: 128-Bit Streaming Stores May Cause Coherency 161 * Failure 162 * 163 * XXX "This workaround must not be applied to processors 164 * prior to revision C0." We don't apply it, but if it 165 * can't be applied, it shouldn't be reported. 166 */ 167 { 168 97, FALSE, MSR_DC_CFG, x86_errata_set6, 169 x86_errata_testmsr, DC_CFG_DIS_CNV_WC_SSO 170 }, 171 /* 172 * 104: DRAM Data Masking Feature Causes ChipKill ECC 173 * Failures When Enabled With x8/x16 DRAM Devices 174 */ 175 { 176 104, FALSE, MSR_NB_CFG, x86_errata_set7, 177 x86_errata_testmsr, NB_CFG_DISDATMSK 178 }, 179 /* 180 * 113: Enhanced Write-Combining Feature Causes System Hang 181 */ 182 { 183 113, FALSE, MSR_BU_CFG, x86_errata_set3, 184 x86_errata_setmsr, BU_CFG_WBENHWSBDIS 185 }, 186 /* 187 * 69: Multiprocessor Coherency Problem with Hardware 188 * Prefetch Mechanism 189 */ 190 { 191 69, FALSE, MSR_BU_CFG, x86_errata_set5, 192 x86_errata_setmsr, BU_CFG_WBPFSMCCHKDIS 193 }, 194 /* 195 * 101: DRAM Scrubber May Cause Data Corruption When Using 196 * Node-Interleaved Memory 197 */ 198 { 199 101, FALSE, 0, x86_errata_set2, 200 NULL, 0 201 }, 202 /* 203 * 106: Potential Deadlock with Tightly Coupled Semaphores 204 * in an MP System 205 */ 206 { 207 106, FALSE, MSR_LS_CFG, x86_errata_set2, 208 x86_errata_testmsr, LS_CFG_DIS_LS2_SQUISH 209 }, 210 /* 211 * 107: Possible Multiprocessor Coherency Problem with 212 * Setting Page Table A/D Bits 213 */ 214 { 215 107, FALSE, MSR_BU_CFG, x86_errata_set2, 216 x86_errata_testmsr, BU_CFG_THRL2IDXCMPDIS 217 }, 218 /* 219 * 122: TLB Flush Filter May Cause Coherency Problem in 220 * Multiprocessor Systems 221 */ 222 { 223 122, FALSE, MSR_HWCR, x86_errata_set4, 224 x86_errata_setmsr, HWCR_FFDIS 225 }, 226 }; 227 228 static bool 229 x86_errata_testmsr(struct cpu_info *ci, errata_t *e) 230 { 231 uint64_t val; 232 233 (void)ci; 234 235 val = rdmsr_locked(e->e_data1, OPTERON_MSR_PASSCODE); 236 if ((val & e->e_data2) != 0) 237 return FALSE; 238 239 e->e_reported = TRUE; 240 return TRUE; 241 } 242 243 static bool 244 x86_errata_setmsr(struct cpu_info *ci, errata_t *e) 245 { 246 uint64_t val; 247 248 (void)ci; 249 250 val = rdmsr_locked(e->e_data1, OPTERON_MSR_PASSCODE); 251 if ((val & e->e_data2) != 0) 252 return FALSE; 253 wrmsr_locked(e->e_data1, OPTERON_MSR_PASSCODE, val | e->e_data2); 254 aprint_debug_dev(ci->ci_dev, "erratum %d patched\n", 255 e->e_num); 256 257 return FALSE; 258 } 259 260 void 261 x86_errata(void) 262 { 263 struct cpu_info *ci; 264 uint32_t descs[4]; 265 errata_t *e, *ex; 266 cpurev_t rev; 267 int i, j, upgrade; 268 static int again; 269 270 if (cpu_vendor != CPUVENDOR_AMD) 271 return; 272 273 ci = curcpu(); 274 275 x86_cpuid(0x80000001, descs); 276 277 for (i = 0;; i += 2) { 278 if ((rev = cpurevs[i]) == OINK) 279 return; 280 if (cpurevs[i + 1] == descs[0]) 281 break; 282 } 283 284 ex = errata + sizeof(errata) / sizeof(errata[0]); 285 for (upgrade = 0, e = errata; e < ex; e++) { 286 if (e->e_reported) 287 continue; 288 if (e->e_set != NULL) { 289 for (j = 0; e->e_set[j] != OINK; j++) 290 if (e->e_set[j] == rev) 291 break; 292 if (e->e_set[j] == OINK) 293 continue; 294 } 295 296 aprint_debug_dev(ci->ci_dev, "testing for erratum %d\n", 297 e->e_num); 298 299 if (e->e_act == NULL) 300 e->e_reported = TRUE; 301 else if ((*e->e_act)(ci, e) == FALSE) 302 continue; 303 304 aprint_debug_dev(ci->ci_dev, "erratum %d present\n", 305 e->e_num); 306 upgrade = 1; 307 } 308 309 if (upgrade && !again) { 310 again = 1; 311 aprint_normal_dev(ci->ci_dev, "WARNING: errata present, BIOS upgrade " 312 "may be\n"); 313 aprint_normal_dev(ci->ci_dev, "WARNING: necessary to ensure reliable " 314 "operation\n"); 315 } 316 } 317