1 /* $NetBSD: errata.c,v 1.11 2007/10/17 19:58:16 garbled 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 * 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 /* 40 * Detect, report on, and work around known errata with x86 CPUs. 41 * 42 * This currently only handles AMD CPUs, and is generalised because 43 * there are quite a few problems that the BIOS can patch via MSR, 44 * but it is not known if the OS can patch these yet. The list is 45 * 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 * XXX This should perhaps be integrated with the identcpu code. 52 */ 53 54 #include <sys/cdefs.h> 55 __KERNEL_RCSID(0, "$NetBSD: errata.c,v 1.11 2007/10/17 19:58:16 garbled Exp $"); 56 57 #include "opt_multiprocessor.h" 58 #ifdef i386 59 #include "opt_cputype.h" 60 #endif 61 62 #include <sys/types.h> 63 #include <sys/systm.h> 64 65 #include <machine/cpu.h> 66 #include <machine/cpufunc.h> 67 #include <machine/specialreg.h> 68 69 #include <x86/cpuvar.h> 70 #include <x86/cputypes.h> 71 72 #if defined(I686_CPU) || defined(__x86_64__) 73 74 typedef struct errata { 75 u_short e_num; 76 u_short e_reported; 77 u_int e_data1; 78 const uint8_t *e_set; 79 bool (*e_act)(struct cpu_info *, struct errata *); 80 uint64_t e_data2; 81 } errata_t; 82 83 typedef enum cpurev { 84 BH_E4, CH_CG, CH_D0, DH_CG, DH_D0, DH_E3, DH_E6, JH_E1, 85 JH_E6, SH_B0, SH_B3, SH_C0, SH_CG, SH_D0, SH_E4, SH_E5, 86 OINK 87 } cpurev_t; 88 89 static const u_int cpurevs[] = { 90 BH_E4, 0x0020fb1, CH_CG, 0x0000f82, CH_CG, 0x0000fb2, 91 CH_D0, 0x0010f80, CH_D0, 0x0010fb0, DH_CG, 0x0000fc0, 92 DH_CG, 0x0000fe0, DH_CG, 0x0000ff0, DH_D0, 0x0010fc0, 93 DH_D0, 0x0010ff0, DH_E3, 0x0020fc0, DH_E3, 0x0020ff0, 94 DH_E6, 0x0020fc2, DH_E6, 0x0020ff2, JH_E1, 0x0020f10, 95 JH_E6, 0x0020f12, JH_E6, 0x0020f32, SH_B0, 0x0000f40, 96 SH_B3, 0x0000f51, SH_C0, 0x0000f48, SH_C0, 0x0000f58, 97 SH_CG, 0x0000f4a, SH_CG, 0x0000f5a, SH_CG, 0x0000f7a, 98 SH_D0, 0x0010f40, SH_D0, 0x0010f50, SH_D0, 0x0010f70, 99 SH_E4, 0x0020f51, SH_E4, 0x0020f71, SH_E5, 0x0020f42, 100 OINK 101 }; 102 103 static const uint8_t x86_errata_set1[] = { 104 SH_B3, SH_C0, SH_CG, DH_CG, CH_CG, OINK 105 }; 106 107 static const uint8_t x86_errata_set2[] = { 108 SH_B3, SH_C0, SH_CG, DH_CG, CH_CG, SH_D0, DH_D0, CH_D0, OINK 109 }; 110 111 static const uint8_t x86_errata_set3[] = { 112 JH_E1, DH_E3, OINK 113 }; 114 115 static const uint8_t x86_errata_set4[] = { 116 SH_C0, SH_CG, DH_CG, CH_CG, SH_D0, DH_D0, CH_D0, JH_E1, 117 DH_E3, SH_E4, BH_E4, SH_E5, DH_E6, JH_E6, OINK 118 }; 119 120 static const uint8_t x86_errata_set5[] = { 121 SH_B3, OINK 122 }; 123 124 static const uint8_t x86_errata_set6[] = { 125 SH_C0, SH_CG, DH_CG, CH_CG, OINK 126 }; 127 128 static const uint8_t x86_errata_set7[] = { 129 SH_C0, SH_CG, DH_CG, CH_CG, SH_D0, DH_D0, CH_D0, OINK 130 }; 131 132 static const uint8_t x86_errata_set8[] = { 133 BH_E4, CH_CG, CH_CG, CH_D0, CH_D0, DH_CG, DH_CG, DH_CG, 134 DH_D0, DH_D0, DH_E3, DH_E3, DH_E6, DH_E6, JH_E1, JH_E6, 135 JH_E6, SH_B0, SH_B3, SH_C0, SH_C0, SH_CG, SH_CG, SH_CG, 136 SH_D0, SH_D0, SH_D0, SH_E4, SH_E4, SH_E5, OINK 137 }; 138 139 static bool x86_errata_setmsr(struct cpu_info *, errata_t *); 140 static bool x86_errata_testmsr(struct cpu_info *, errata_t *); 141 142 static errata_t errata[] = { 143 /* 144 * 81: Cache Coherency Problem with Hardware Prefetching 145 * and Streaming Stores 146 */ 147 { 148 81, FALSE, MSR_DC_CFG, x86_errata_set5, 149 x86_errata_testmsr, DC_CFG_DIS_SMC_CHK_BUF 150 }, 151 /* 152 * 86: DRAM Data Masking Feature Can Cause ECC Failures 153 */ 154 { 155 86, FALSE, MSR_NB_CFG, x86_errata_set1, 156 x86_errata_testmsr, NB_CFG_DISDATMSK 157 }, 158 /* 159 * 89: Potential Deadlock With Locked Transactions 160 */ 161 { 162 89, FALSE, MSR_NB_CFG, x86_errata_set8, 163 x86_errata_testmsr, NB_CFG_DISIOREQLOCK 164 }, 165 /* 166 * 94: Sequential Prefetch Feature May Cause Incorrect 167 * Processor Operation 168 */ 169 { 170 94, FALSE, MSR_IC_CFG, x86_errata_set1, 171 x86_errata_testmsr, IC_CFG_DIS_SEQ_PREFETCH 172 }, 173 /* 174 * 97: 128-Bit Streaming Stores May Cause Coherency 175 * Failure 176 * 177 * XXX "This workaround must not be applied to processors 178 * prior to revision C0." We don't apply it, but if it 179 * can't be applied, it shouldn't be reported. 180 */ 181 { 182 97, FALSE, MSR_DC_CFG, x86_errata_set6, 183 x86_errata_testmsr, DC_CFG_DIS_CNV_WC_SSO 184 }, 185 /* 186 * 104: DRAM Data Masking Feature Causes ChipKill ECC 187 * Failures When Enabled With x8/x16 DRAM Devices 188 */ 189 { 190 104, FALSE, MSR_NB_CFG, x86_errata_set7, 191 x86_errata_testmsr, NB_CFG_DISDATMSK 192 }, 193 /* 194 * 113: Enhanced Write-Combining Feature Causes System Hang 195 */ 196 { 197 113, FALSE, MSR_BU_CFG, x86_errata_set3, 198 x86_errata_setmsr, BU_CFG_WBENHWSBDIS 199 }, 200 #ifdef MULTIPROCESSOR 201 /* 202 * 69: Multiprocessor Coherency Problem with Hardware 203 * Prefetch Mechanism 204 */ 205 { 206 69, FALSE, MSR_BU_CFG, x86_errata_set5, 207 x86_errata_setmsr, BU_CFG_WBPFSMCCHKDIS 208 }, 209 /* 210 * 101: DRAM Scrubber May Cause Data Corruption When Using 211 * Node-Interleaved Memory 212 */ 213 { 214 101, FALSE, 0, x86_errata_set2, 215 NULL, 0 216 }, 217 /* 218 * 106: Potential Deadlock with Tightly Coupled Semaphores 219 * in an MP System 220 */ 221 { 222 106, FALSE, MSR_LS_CFG, x86_errata_set2, 223 x86_errata_testmsr, LS_CFG_DIS_LS2_SQUISH 224 }, 225 /* 226 * 107: Possible Multiprocessor Coherency Problem with 227 * Setting Page Table A/D Bits 228 */ 229 { 230 107, FALSE, MSR_BU_CFG, x86_errata_set2, 231 x86_errata_testmsr, BU_CFG_THRL2IDXCMPDIS 232 }, 233 /* 234 * 122: TLB Flush Filter May Cause Coherency Problem in 235 * Multiprocessor Systems 236 */ 237 { 238 122, FALSE, MSR_HWCR, x86_errata_set4, 239 x86_errata_setmsr, HWCR_FFDIS 240 }, 241 #endif /* MULTIPROCESSOR */ 242 }; 243 244 static bool 245 x86_errata_testmsr(struct cpu_info *ci, errata_t *e) 246 { 247 uint64_t val; 248 249 (void)ci; 250 251 val = rdmsr_locked(e->e_data1, OPTERON_MSR_PASSCODE); 252 if ((val & e->e_data2) != 0) 253 return FALSE; 254 255 e->e_reported = TRUE; 256 return TRUE; 257 } 258 259 static bool 260 x86_errata_setmsr(struct cpu_info *ci, errata_t *e) 261 { 262 uint64_t val; 263 264 (void)ci; 265 266 val = rdmsr_locked(e->e_data1, OPTERON_MSR_PASSCODE); 267 if ((val & e->e_data2) != 0) 268 return FALSE; 269 wrmsr_locked(e->e_data1, OPTERON_MSR_PASSCODE, val | e->e_data2); 270 aprint_debug("%s: erratum %d patched\n", 271 ci->ci_dev->dv_xname, e->e_num); 272 273 return FALSE; 274 } 275 276 void 277 x86_errata(struct cpu_info *ci, int vendor) 278 { 279 uint32_t descs[4]; 280 errata_t *e, *ex; 281 cpurev_t rev; 282 int i, j, upgrade; 283 static int again; 284 285 if (vendor != CPUVENDOR_AMD) 286 return; 287 288 x86_cpuid(0x80000001, descs); 289 290 for (i = 0;; i += 2) { 291 if ((rev = cpurevs[i]) == OINK) 292 return; 293 if (cpurevs[i + 1] == descs[0]) 294 break; 295 } 296 297 ex = errata + sizeof(errata) / sizeof(errata[0]); 298 for (upgrade = 0, e = errata; e < ex; e++) { 299 if (e->e_reported) 300 continue; 301 if (e->e_set != NULL) { 302 for (j = 0; e->e_set[j] != OINK; j++) 303 if (e->e_set[j] == rev) 304 break; 305 if (e->e_set[j] == OINK) 306 continue; 307 } 308 309 aprint_debug("%s: testing for erratum %d\n", 310 ci->ci_dev->dv_xname, e->e_num); 311 312 if (e->e_act == NULL) 313 e->e_reported = TRUE; 314 else if ((*e->e_act)(ci, e) == FALSE) 315 continue; 316 317 aprint_debug("%s: erratum %d present\n", 318 ci->ci_dev->dv_xname, e->e_num); 319 upgrade = 1; 320 } 321 322 if (upgrade && !again) { 323 again = 1; 324 aprint_normal("%s: WARNING: AMD errata present, BIOS upgrade " 325 "may be\n", ci->ci_dev->dv_xname); 326 aprint_normal("%s: WARNING: necessary to ensure reliable " 327 "operation\n", ci->ci_dev->dv_xname); 328 } 329 } 330 331 #else /* defined(I686_CPU) || defined(__x86_64__) */ 332 333 void 334 x86_errata(struct cpu_info *ci, int vendor) 335 { 336 (void)ci; 337 (void)vendor; 338 } 339 340 #endif /* defined(I686_CPU) || defined(__x86_64__) */ 341