xref: /netbsd-src/sys/arch/x86/x86/errata.c (revision 7fa608457b817eca6e0977b37f758ae064f3c99c)
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