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