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