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