1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License (the "License").
6  * You may not use this file except in compliance with the License.
7  *
8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9  * or http://www.opensolaris.org/os/licensing.
10  * See the License for the specific language governing permissions
11  * and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL HEADER in each
14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15  * If applicable, add the following below this CDDL HEADER, with the
16  * fields enclosed by brackets "[]" replaced with your own identifying
17  * information: Portions Copyright [yyyy] [name of copyright owner]
18  *
19  * CDDL HEADER END
20  */
21 /*
22  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
23  * Use is subject to license terms.
24  * Copyright (c) 2019 Peter Tribble.
25  */
26 
27 /*
28  * Support routines for managing per-CPU state.
29  */
30 
31 #include <cmd_cpu.h>
32 
33 #ifdef sun4u
34 #include <cmd_ecache.h>
35 #endif /* sun4u */
36 
37 #include <cmd_mem.h>
38 #include <cmd.h>
39 
40 #include <stdio.h>
41 #include <string.h>
42 #include <strings.h>
43 #include <errno.h>
44 #include <kstat.h>
45 #include <fm/fmd_api.h>
46 #include <sys/async.h>
47 #include <sys/fm/protocol.h>
48 
49 #ifdef sun4u
50 #include <sys/cheetahregs.h>
51 #include <sys/fm/cpu/UltraSPARC-III.h>
52 #include <cmd_opl.h>
53 #include <cmd_Lxcache.h>
54 #else /* sun4u */
55 #include <sys/niagararegs.h>
56 #include <sys/fm/cpu/UltraSPARC-T1.h>
57 #include <cmd_hc_sun4v.h>
58 #endif /* sun4u */
59 
60 #define	CMD_CPU_UEC_INCR	10
61 
62 /* Must be in sync with cmd_cpu_type_t */
63 static const char *const cpu_names[] = {
64 	NULL,
65 	"ultraSPARC-III",
66 	"ultraSPARC-IIIplus",
67 	"ultraSPARC-IIIi",
68 	"ultraSPARC-IV",
69 	"ultraSPARC-IVplus",
70 	"ultraSPARC-IIIiplus",
71 	"ultraSPARC-T1",
72 	"SPARC64-VI",
73 	"SPARC64-VII",
74 	"ultraSPARC-T2",
75 	"ultraSPARC-T2plus"
76 };
77 
78 /*
79  * This needs to be in sync with cpu_family_t.
80  */
81 static const faminfo_t fam_info_tbl[] = {
82 	{ CMD_CPU_FAM_UNSUPPORTED,	B_FALSE },
83 	{ CMD_CPU_FAM_CHEETAH,		B_TRUE },
84 	{ CMD_CPU_FAM_NIAGARA,		B_FALSE },
85 	{ CMD_CPU_FAM_SPARC64,		B_FALSE }
86 };
87 
88 static cmd_cpu_t *cpu_lookup_by_cpuid(uint32_t, uint8_t);
89 static cmd_cpu_t *cpu_create(fmd_hdl_t *, nvlist_t *, uint32_t,
90     uint8_t, cmd_cpu_type_t);
91 static void cpu_buf_write(fmd_hdl_t *, cmd_cpu_t *);
92 
93 const char *
cmd_cpu_type2name(fmd_hdl_t * hdl,cmd_cpu_type_t type)94 cmd_cpu_type2name(fmd_hdl_t *hdl, cmd_cpu_type_t type)
95 {
96 	if (type < 1 || type > sizeof (cpu_names) / sizeof (char *))
97 		fmd_hdl_abort(hdl, "illegal CPU type %d\n", type);
98 
99 	return (cpu_names[type]);
100 }
101 
102 static cmd_cpu_type_t
cpu_nname2type(fmd_hdl_t * hdl,const char * name,size_t n)103 cpu_nname2type(fmd_hdl_t *hdl, const char *name, size_t n)
104 {
105 	int i;
106 
107 	for (i = 1; i < sizeof (cpu_names) / sizeof (char *); i++) {
108 		if (strlen(cpu_names[i]) == n &&
109 		    strncmp(cpu_names[i], name, n) == 0)
110 			return (i);
111 	}
112 
113 	fmd_hdl_abort(hdl, "illegal CPU name %*.*s\n", n, n, name);
114 	/*NOTREACHED*/
115 	return (0);
116 }
117 
118 const char *fmd_fmri_get_platform();
119 #define	is_serengeti	(strcmp(fmd_fmri_get_platform(), \
120 "SUNW,Sun-Fire") == 0)
121 
122 static void
core2cpus(uint32_t core,cmd_cpu_type_t type,uint8_t level,uint32_t * cpuinit,uint32_t * cpufinal,uint32_t * cpustep)123 core2cpus(uint32_t core, cmd_cpu_type_t type, uint8_t level,
124     uint32_t *cpuinit, uint32_t *cpufinal, uint32_t *cpustep)
125 {
126 	switch (type) {
127 #ifdef sun4u
128 
129 #define	US4P_SGTI_CPUS_PER_CORE		2
130 #define	US4P_SGTI_CPU_CORE_STEP		512
131 #define	US4P_DAKC_CPUS_PER_CORE		2
132 #define	US4P_DAKC_CPU_CORE_STEP		16
133 
134 	case CPU_ULTRASPARC_IVplus:
135 		switch (level) {
136 		case CMD_CPU_LEVEL_CORE:
137 			if (is_serengeti)
138 				*cpustep = US4P_SGTI_CPU_CORE_STEP;
139 			else
140 				*cpustep = US4P_DAKC_CPU_CORE_STEP;
141 			*cpuinit = core;
142 			*cpufinal = *cpuinit + *cpustep;
143 			return;
144 		default:
145 			*cpuinit = *cpufinal = core;
146 			*cpustep = 1;
147 			return;
148 		}
149 #else /* i.e. sun4v */
150 
151 #define	UST1_CPUS_PER_CORE		4
152 #define	UST1_CPU_CORE_STEP		1
153 #define	UST1_CPUS_PER_CHIP		32
154 #define	UST1_CPU_CHIP_STEP		1
155 #define	UST2_CPUS_PER_CORE		8
156 #define	UST2_CPU_CORE_STEP		1
157 #define	UST2_CPUS_PER_CHIP		64
158 #define	UST2_CPU_CHIP_STEP		1
159 
160 	case CPU_ULTRASPARC_T1:
161 		switch (level) {
162 		case CMD_CPU_LEVEL_CORE:
163 			*cpuinit = core * UST1_CPUS_PER_CORE;
164 			*cpufinal = *cpuinit + UST1_CPUS_PER_CORE - 1;
165 			*cpustep = UST1_CPU_CORE_STEP;
166 			return;
167 		case CMD_CPU_LEVEL_CHIP:
168 			*cpuinit = core * UST1_CPUS_PER_CHIP;
169 			*cpufinal = *cpuinit + UST1_CPUS_PER_CHIP - 1;
170 			*cpustep = UST1_CPU_CHIP_STEP;
171 			return;
172 		default:
173 			*cpuinit = *cpufinal = core;
174 			*cpustep = 1;
175 			return;
176 		}
177 	case CPU_ULTRASPARC_T2:
178 	case CPU_ULTRASPARC_T2plus:
179 		switch (level) {
180 		case CMD_CPU_LEVEL_CORE:
181 			*cpuinit = core * UST2_CPUS_PER_CORE;
182 			*cpufinal = *cpuinit + UST2_CPUS_PER_CORE - 1;
183 			*cpustep = UST2_CPU_CORE_STEP;
184 			return;
185 		case CMD_CPU_LEVEL_CHIP:
186 			*cpuinit = core * UST2_CPUS_PER_CHIP;
187 			*cpufinal = *cpuinit + UST2_CPUS_PER_CHIP - 1;
188 			*cpustep = UST2_CPU_CHIP_STEP;
189 			return;
190 		default:
191 			*cpuinit = *cpufinal = core;
192 			*cpustep = 1;
193 			return;
194 		}
195 
196 #endif /* sun4u */
197 	default:
198 		*cpuinit = *cpufinal = core;
199 		*cpustep = 1;
200 		return;
201 	}
202 }
203 
204 uint32_t
cmd_cpu2core(uint32_t cpuid,cmd_cpu_type_t type,uint8_t level)205 cmd_cpu2core(uint32_t cpuid, cmd_cpu_type_t type, uint8_t level)
206 {
207 	switch (type) {
208 #ifdef sun4u
209 
210 	case CPU_ULTRASPARC_IVplus:
211 		switch (level) {
212 		case CMD_CPU_LEVEL_CORE:
213 			if (is_serengeti)
214 				return (cpuid % US4P_SGTI_CPU_CORE_STEP);
215 			else
216 				return (cpuid % US4P_DAKC_CPU_CORE_STEP);
217 		default:
218 			return (cpuid);
219 		}
220 #else /* i.e. sun4v */
221 	case CPU_ULTRASPARC_T1:
222 		switch (level) {
223 		case CMD_CPU_LEVEL_CORE:
224 			return (cpuid/UST1_CPUS_PER_CORE);
225 		case CMD_CPU_LEVEL_CHIP:
226 			return (cpuid/UST1_CPUS_PER_CHIP);
227 		default:
228 			return (cpuid);
229 		}
230 	case CPU_ULTRASPARC_T2:
231 	case CPU_ULTRASPARC_T2plus:
232 		switch (level) {
233 		case CMD_CPU_LEVEL_CORE:
234 			return (cpuid/UST2_CPUS_PER_CORE);
235 		case CMD_CPU_LEVEL_CHIP:
236 			return (cpuid/UST2_CPUS_PER_CHIP);
237 		default:
238 			return (cpuid);
239 		}
240 
241 #endif /* sun4u */
242 	default:
243 		return (cpuid);
244 	}
245 }
246 
247 #ifdef sun4u
248 static void
cpu_uec_write(fmd_hdl_t * hdl,cmd_cpu_t * cpu,cmd_cpu_uec_t * uec)249 cpu_uec_write(fmd_hdl_t *hdl, cmd_cpu_t *cpu, cmd_cpu_uec_t *uec)
250 {
251 	/*
252 	 * The UE cache may change size.  fmd expects statically-sized buffers,
253 	 * so we must delete and re-create it if the size has changed from the
254 	 * last time it was written.
255 	 */
256 	if (fmd_buf_size(hdl, NULL, uec->uec_bufname) != sizeof (uint64_t) *
257 	    uec->uec_nent)
258 		fmd_buf_destroy(hdl, NULL, uec->uec_bufname);
259 
260 	if (uec->uec_cache != NULL) {
261 		fmd_buf_write(hdl, NULL, uec->uec_bufname, uec->uec_cache,
262 		    sizeof (uint64_t) * uec->uec_nent);
263 	}
264 
265 	cpu_buf_write(hdl, cpu);
266 }
267 
268 static void
cpu_uec_create(fmd_hdl_t * hdl,cmd_cpu_t * cpu,cmd_cpu_uec_t * uec,const char * fmt,...)269 cpu_uec_create(fmd_hdl_t *hdl, cmd_cpu_t *cpu, cmd_cpu_uec_t *uec,
270     const char *fmt, ...)
271 {
272 	va_list ap;
273 
274 	va_start(ap, fmt);
275 	cmd_vbufname(uec->uec_bufname, sizeof (uec->uec_bufname), fmt, ap);
276 	va_end(ap);
277 
278 	cpu_uec_write(hdl, cpu, uec);
279 }
280 
281 static void
cpu_uec_restore(fmd_hdl_t * hdl,cmd_cpu_uec_t * uec)282 cpu_uec_restore(fmd_hdl_t *hdl, cmd_cpu_uec_t *uec)
283 {
284 	if (uec->uec_cache != NULL) {
285 		uec->uec_cache = cmd_buf_read(hdl, NULL, uec->uec_bufname,
286 		    sizeof (uint64_t) * uec->uec_nent);
287 	}
288 }
289 
290 static void
cpu_uec_free(fmd_hdl_t * hdl,cmd_cpu_uec_t * uec,int destroy)291 cpu_uec_free(fmd_hdl_t *hdl, cmd_cpu_uec_t *uec, int destroy)
292 {
293 	if (uec->uec_cache == NULL)
294 		return;
295 
296 	if (destroy)
297 		fmd_buf_destroy(hdl, NULL, uec->uec_bufname);
298 
299 	fmd_hdl_free(hdl, uec->uec_cache, sizeof (uint64_t) * uec->uec_nent);
300 }
301 
302 static void
cpu_uec_flush_finish(fmd_hdl_t * hdl,cmd_cpu_t * cpu)303 cpu_uec_flush_finish(fmd_hdl_t *hdl, cmd_cpu_t *cpu)
304 {
305 	fmd_hdl_debug(hdl, "completing UE cache flush\n");
306 	if (cpu->cpu_olduec.uec_cache != NULL) {
307 		fmd_hdl_free(hdl, cpu->cpu_olduec.uec_cache, sizeof (uint64_t) *
308 		    cpu->cpu_olduec.uec_nent);
309 
310 		cpu->cpu_olduec.uec_cache = NULL;
311 		cpu->cpu_olduec.uec_nent = 0;
312 		cpu->cpu_olduec.uec_flags = 0;
313 		cpu_uec_write(hdl, cpu, &cpu->cpu_olduec);
314 	}
315 
316 	cpu->cpu_uec_flush = 0;
317 	cpu_buf_write(hdl, cpu);
318 }
319 
320 static void
cpu_uec_flush(fmd_hdl_t * hdl,cmd_cpu_t * cpu)321 cpu_uec_flush(fmd_hdl_t *hdl, cmd_cpu_t *cpu)
322 {
323 	if (cpu->cpu_uec.uec_cache == NULL && !cpu->cpu_uec.uec_flags)
324 		return; /* nothing to flush */
325 
326 	fmd_hdl_debug(hdl, "flushing UE cache for CPU %d\n", cpu->cpu_cpuid);
327 
328 	if (cmd_ecache_flush(cpu->cpu_cpuid) < 0) {
329 		fmd_hdl_debug(hdl, "failed to flush E$ for CPU %d\n",
330 		    cpu->cpu_cpuid);
331 		return; /* don't flush the UE cache unless we can flush E$ */
332 	}
333 
334 	if (cpu->cpu_olduec.uec_cache != NULL) {
335 		/*
336 		 * If there's already an old UE cache, we're racing with another
337 		 * flush.  For safety, we'll add the current contents of the
338 		 * cache to the existing old cache.
339 		 */
340 		size_t nent = cpu->cpu_olduec.uec_nent + cpu->cpu_uec.uec_nent;
341 		uint64_t *new = fmd_hdl_alloc(hdl, sizeof (uint64_t) * nent,
342 		    FMD_SLEEP);
343 
344 		bcopy(cpu->cpu_olduec.uec_cache, new,
345 		    sizeof (uint64_t) * cpu->cpu_olduec.uec_nent);
346 		bcopy(cpu->cpu_uec.uec_cache, new + cpu->cpu_olduec.uec_nent,
347 		    sizeof (uint64_t) * cpu->cpu_uec.uec_nent);
348 
349 		fmd_hdl_free(hdl, cpu->cpu_olduec.uec_cache,
350 		    sizeof (uint64_t) * cpu->cpu_olduec.uec_nent);
351 		fmd_hdl_free(hdl, cpu->cpu_uec.uec_cache,
352 		    sizeof (uint64_t) * cpu->cpu_uec.uec_nent);
353 
354 		cpu->cpu_olduec.uec_cache = new;
355 		cpu->cpu_olduec.uec_nent = nent;
356 		cpu->cpu_olduec.uec_flags |= cpu->cpu_uec.uec_flags;
357 	} else {
358 		cpu->cpu_olduec.uec_cache = cpu->cpu_uec.uec_cache;
359 		cpu->cpu_olduec.uec_nent = cpu->cpu_uec.uec_nent;
360 		cpu->cpu_olduec.uec_flags = cpu->cpu_uec.uec_flags;
361 	}
362 	cpu_uec_write(hdl, cpu, &cpu->cpu_olduec);
363 
364 	cpu->cpu_uec.uec_cache = NULL;
365 	cpu->cpu_uec.uec_nent = 0;
366 	cpu->cpu_uec.uec_flags = 0;
367 	cpu_uec_write(hdl, cpu, &cpu->cpu_uec);
368 
369 	if (cpu->cpu_uec_flush != 0)
370 		fmd_timer_remove(hdl, cpu->cpu_uec_flush);
371 
372 	cpu->cpu_uec_flush = fmd_timer_install(hdl,
373 	    (void *)CMD_TIMERTYPE_CPU_UEC_FLUSH, NULL, NANOSEC);
374 	cpu_buf_write(hdl, cpu);
375 }
376 
377 void
cmd_cpu_uec_add(fmd_hdl_t * hdl,cmd_cpu_t * cpu,uint64_t pa)378 cmd_cpu_uec_add(fmd_hdl_t *hdl, cmd_cpu_t *cpu, uint64_t pa)
379 {
380 	cmd_cpu_uec_t *uec = &cpu->cpu_uec;
381 	uint64_t *new, *tgt = NULL;
382 	int i;
383 
384 	pa = pa & cmd.cmd_pagemask;
385 
386 	fmd_hdl_debug(hdl, "adding 0x%llx to CPU %d's UE cache\n",
387 	    (u_longlong_t)pa, cpu->cpu_cpuid);
388 
389 	if (uec->uec_cache != NULL) {
390 		for (tgt = NULL, i = 0; i < uec->uec_nent; i++) {
391 			if (tgt == NULL && uec->uec_cache[i] == 0)
392 				tgt = &uec->uec_cache[i];
393 
394 			if (uec->uec_cache[i] == pa)
395 				return; /* already there */
396 		}
397 	}
398 
399 	if (tgt == NULL) {
400 		/* no space - resize the cache */
401 		new = fmd_hdl_zalloc(hdl, sizeof (uint64_t) *
402 		    (uec->uec_nent + CMD_CPU_UEC_INCR), FMD_SLEEP);
403 
404 		if (uec->uec_cache != NULL) {
405 			bcopy(uec->uec_cache, new, sizeof (uint64_t) *
406 			    uec->uec_nent);
407 			fmd_hdl_free(hdl, uec->uec_cache, sizeof (uint64_t) *
408 			    uec->uec_nent);
409 		}
410 
411 		uec->uec_cache = new;
412 		tgt = &uec->uec_cache[uec->uec_nent];
413 		uec->uec_nent += CMD_CPU_UEC_INCR;
414 	}
415 
416 	*tgt = pa;
417 	cpu_uec_write(hdl, cpu, uec);
418 }
419 
420 void
cmd_cpu_uec_set_allmatch(fmd_hdl_t * hdl,cmd_cpu_t * cpu)421 cmd_cpu_uec_set_allmatch(fmd_hdl_t *hdl, cmd_cpu_t *cpu)
422 {
423 	fmd_hdl_debug(hdl, "setting cpu %d's uec to allmatch\n",
424 	    cpu->cpu_cpuid);
425 
426 	cpu->cpu_uec.uec_flags |= CPU_UEC_F_ALLMATCH;
427 	cpu_uec_write(hdl, cpu, &cpu->cpu_uec);
428 
429 	if (++cpu->cpu_uec_nflushes <= CPU_UEC_FLUSH_MAX)
430 		cpu_uec_flush(hdl, cpu);
431 }
432 
433 int
cmd_cpu_uec_match(cmd_cpu_t * cpu,uint64_t pa)434 cmd_cpu_uec_match(cmd_cpu_t *cpu, uint64_t pa)
435 {
436 	int i;
437 
438 	/*
439 	 * The UE cache works as long as we are able to add an entry for every
440 	 * UE seen by a given CPU.  If we see a UE with a non-valid AFAR, we
441 	 * can't guarantee our ability to filter a corresponding xxU, and must,
442 	 * for safety, assume that every subsequent xxU (until the E$ and UE
443 	 * cache are flushed) has a matching UE.
444 	 */
445 	if ((cpu->cpu_uec.uec_flags & CPU_UEC_F_ALLMATCH) ||
446 	    (cpu->cpu_olduec.uec_flags & CPU_UEC_F_ALLMATCH))
447 		return (1);
448 
449 	pa = pa & cmd.cmd_pagemask;
450 
451 	for (i = 0; i < cpu->cpu_uec.uec_nent; i++) {
452 		if (cpu->cpu_uec.uec_cache[i] == pa)
453 			return (1);
454 	}
455 
456 	for (i = 0; i < cpu->cpu_olduec.uec_nent; i++) {
457 		if (cpu->cpu_olduec.uec_cache[i] == pa)
458 			return (1);
459 	}
460 
461 	return (0);
462 }
463 #endif /* sun4u */
464 
465 void
cmd_xr_write(fmd_hdl_t * hdl,cmd_xr_t * xr)466 cmd_xr_write(fmd_hdl_t *hdl, cmd_xr_t *xr)
467 {
468 	fmd_hdl_debug(hdl, "writing redelivery clcode %llx for case %s\n",
469 	    xr->xr_clcode, fmd_case_uuid(hdl, xr->xr_case));
470 
471 	fmd_buf_write(hdl, xr->xr_case, "redelivery", xr,
472 	    sizeof (cmd_xr_t));
473 }
474 
475 static cmd_xr_hdlr_f *
cmd_xr_id2hdlr(fmd_hdl_t * hdl,uint_t id)476 cmd_xr_id2hdlr(fmd_hdl_t *hdl, uint_t id)
477 {
478 	switch (id) {
479 	case CMD_XR_HDLR_XXC:
480 		return (cmd_xxc_resolve);
481 	case CMD_XR_HDLR_XXU:
482 		return (cmd_xxu_resolve);
483 	case CMD_XR_HDLR_NOP:
484 		return (cmd_nop_resolve);
485 	default:
486 		fmd_hdl_abort(hdl, "cmd_xr_id2hdlr called with bad hdlrid %x\n",
487 		    id);
488 	}
489 
490 	return (NULL);
491 }
492 
493 cmd_xr_t *
cmd_xr_create(fmd_hdl_t * hdl,fmd_event_t * ep,nvlist_t * nvl,cmd_cpu_t * cpu,cmd_errcl_t clcode)494 cmd_xr_create(fmd_hdl_t *hdl, fmd_event_t *ep, nvlist_t *nvl,
495     cmd_cpu_t *cpu, cmd_errcl_t clcode)
496 {
497 	cmd_xr_t *xr = fmd_hdl_zalloc(hdl, sizeof (cmd_xr_t),
498 	    FMD_SLEEP);
499 	nvlist_t *rsrc = NULL;
500 	const char *uuid;
501 	int err = 0;
502 
503 	err |= nvlist_lookup_uint64(nvl, FM_EREPORT_ENA, &xr->xr_ena);
504 
505 	err |= cmd_xr_fill(hdl, nvl, xr, clcode);
506 #ifdef sun4u
507 	err |= cmd_xr_pn_cache_fill(hdl, nvl, xr, cpu, clcode);
508 #endif
509 	(void) nvlist_lookup_nvlist(nvl, FM_EREPORT_PAYLOAD_NAME_RESOURCE,
510 	    &rsrc);
511 
512 	if (err != 0) {
513 		fmd_hdl_free(hdl, xr, sizeof (cmd_xr_t));
514 		return (NULL);
515 	}
516 
517 	xr->xr_cpu = cpu;
518 	xr->xr_cpuid = cpu->cpu_cpuid;
519 	xr->xr_clcode = clcode;
520 	xr->xr_case = cmd_case_create(hdl, &cpu->cpu_header,
521 	    CMD_PTR_CPU_XR_RETRY, &uuid);
522 	fmd_case_setprincipal(hdl, xr->xr_case, ep);
523 
524 	if (rsrc != NULL) {
525 		cmd_fmri_init(hdl, &xr->xr_rsrc, rsrc, "%s_rsrc",
526 		    fmd_case_uuid(hdl, xr->xr_case));
527 	}
528 
529 	cmd_xr_write(hdl, xr);
530 	return (xr);
531 }
532 
533 cmd_evdisp_t
cmd_xr_reschedule(fmd_hdl_t * hdl,cmd_xr_t * xr,uint_t hdlrid)534 cmd_xr_reschedule(fmd_hdl_t *hdl, cmd_xr_t *xr, uint_t hdlrid)
535 {
536 
537 	fmd_hdl_debug(hdl, "scheduling redelivery of %llx with xr %p\n",
538 	    xr->xr_clcode, xr);
539 
540 	xr->xr_hdlrid = hdlrid;
541 	xr->xr_hdlr = cmd_xr_id2hdlr(hdl, hdlrid);
542 
543 	xr->xr_id = fmd_timer_install(hdl, (void *)CMD_TIMERTYPE_CPU_XR_WAITER,
544 	    NULL, cmd.cmd_xxcu_trdelay);
545 
546 	if (xr->xr_ref++ == 0)
547 		cmd_list_append(&cmd.cmd_xxcu_redelivs, xr);
548 
549 	cmd_xr_write(hdl, xr);
550 	return (CMD_EVD_OK);
551 }
552 
553 static void
cmd_xr_destroy(fmd_hdl_t * hdl,cmd_xr_t * xr)554 cmd_xr_destroy(fmd_hdl_t *hdl, cmd_xr_t *xr)
555 {
556 	fmd_hdl_debug(hdl, "destroying xr (clcode %llx) at %p\n",
557 	    xr->xr_clcode, xr);
558 
559 	fmd_case_reset(hdl, xr->xr_case);
560 	cmd_case_fini(hdl, xr->xr_case, FMD_B_TRUE);
561 
562 	if (xr->xr_rsrc_nvl != NULL)
563 		cmd_fmri_fini(hdl, &xr->xr_rsrc, FMD_B_TRUE);
564 
565 	fmd_buf_destroy(hdl, xr->xr_case, "redelivery");
566 	fmd_hdl_free(hdl, xr, sizeof (cmd_xr_t));
567 }
568 
569 void
cmd_xr_deref(fmd_hdl_t * hdl,cmd_xr_t * xr)570 cmd_xr_deref(fmd_hdl_t *hdl, cmd_xr_t *xr)
571 {
572 	if (xr->xr_ref == 0)
573 		fmd_hdl_abort(hdl, "attempt to deref xr with zero ref\n");
574 
575 	fmd_hdl_debug(hdl, "deref xr %p [%d]\n", xr, xr->xr_ref);
576 
577 	if (--xr->xr_ref == 0) {
578 		cmd_list_delete(&cmd.cmd_xxcu_redelivs, xr);
579 		cmd_xr_destroy(hdl, xr);
580 	}
581 }
582 
583 static void
cmd_xr_restore(fmd_hdl_t * hdl,cmd_cpu_t * cpu,fmd_case_t * cp)584 cmd_xr_restore(fmd_hdl_t *hdl, cmd_cpu_t *cpu, fmd_case_t *cp)
585 {
586 	cmd_xr_t *xr;
587 
588 	if ((xr = cmd_buf_read(hdl, cp, "redelivery", sizeof (cmd_xr_t))) ==
589 	    NULL) {
590 		fmd_hdl_abort(hdl, "failed to find redelivery for case %s\n",
591 		    fmd_case_uuid(hdl, cp));
592 	}
593 
594 	xr->xr_case = cp;
595 	xr->xr_hdlr = cmd_xr_id2hdlr(hdl, xr->xr_hdlrid);
596 	if (xr->xr_rsrc_nvl != NULL)
597 		cmd_fmri_restore(hdl, &xr->xr_rsrc);
598 	xr->xr_cpu = cpu;
599 
600 	/*
601 	 * fmd is still in the process of starting up.  If we reschedule this
602 	 * event with the normal redelivery timeout, it'll get redelivered
603 	 * before initialization has completed, we'll potentially fail to
604 	 * match the train, deref() the waiter (causing any subsequent side-
605 	 * effects to miss the waiter), and use this ereport to blame the CPU.
606 	 * The other side-effects will blame the CPU too, since we'll have
607 	 * deref()'d the waiter out of existence.  We can get up to three
608 	 * additions to the SERD engine this way, which is bad.  To keep that
609 	 * from happening, we're going to schedule an arbitrarily long timeout,
610 	 * which *should* be long enough.  It's pretty bad, but there's no
611 	 * real way to keep the other side-effects from taking out the CPU.
612 	 */
613 	xr->xr_id = fmd_timer_install(hdl, (void *)CMD_TIMERTYPE_CPU_XR_WAITER,
614 	    NULL, fmd_prop_get_int64(hdl, "xxcu_restart_delay"));
615 
616 	cmd_list_append(&cmd.cmd_xxcu_redelivs, xr);
617 
618 	fmd_hdl_debug(hdl, "revived xr for class %llx\n", xr->xr_clcode);
619 }
620 
621 typedef struct cmd_xxcu_train {
622 	cmd_errcl_t tr_mask;	/* errors we must see to match this train */
623 	cmd_errcl_t tr_cause;	/* the error at the root of this train */
624 } cmd_xxcu_train_t;
625 
626 #define	CMD_TRAIN(cause, side_effects)	{ (cause) | (side_effects), (cause) }
627 
628 static const cmd_xxcu_train_t cmd_xxcu_trains[] = {
629 #ifdef sun4u
630 	/* UCC: WDC */
631 	CMD_TRAIN(CMD_ERRCL_UCC,	CMD_ERRCL_WDC),
632 
633 	/* UCU: WDU, WDU+L3_WDU */
634 	CMD_TRAIN(CMD_ERRCL_UCU,	CMD_ERRCL_WDU),
635 	CMD_TRAIN(CMD_ERRCL_UCU,	CMD_ERRCL_L3_WDU | CMD_ERRCL_WDU),
636 
637 	/* EDC: WDC */
638 	CMD_TRAIN(CMD_ERRCL_EDC,	CMD_ERRCL_WDC),
639 
640 	/* EDU: WDU, WDU+L3_WDU */
641 	CMD_TRAIN(CMD_ERRCL_EDU_ST,	CMD_ERRCL_WDU),
642 	CMD_TRAIN(CMD_ERRCL_EDU_BL,	CMD_ERRCL_WDU),
643 	CMD_TRAIN(CMD_ERRCL_EDU_ST,	CMD_ERRCL_L3_WDU | CMD_ERRCL_WDU),
644 	CMD_TRAIN(CMD_ERRCL_EDU_BL,	CMD_ERRCL_L3_WDU | CMD_ERRCL_WDU),
645 
646 	/* CPC: WDC, EDC+WDC, UCC+WDC, EDC+UCC+WDC */
647 	CMD_TRAIN(CMD_ERRCL_CPC,	CMD_ERRCL_WDC),
648 	CMD_TRAIN(CMD_ERRCL_CPC,	CMD_ERRCL_EDC | CMD_ERRCL_WDC),
649 	CMD_TRAIN(CMD_ERRCL_CPC,	CMD_ERRCL_UCC | CMD_ERRCL_WDC),
650 	CMD_TRAIN(CMD_ERRCL_CPC,	CMD_ERRCL_EDC | CMD_ERRCL_UCC |
651 	    CMD_ERRCL_WDC),
652 
653 	/* CPU: WDU, WDU+L3_WDU, UCU+WDU, UCU+WDU+L3_WDU */
654 	CMD_TRAIN(CMD_ERRCL_CPU,	CMD_ERRCL_WDU),
655 	CMD_TRAIN(CMD_ERRCL_CPU,	CMD_ERRCL_L3_WDU | CMD_ERRCL_WDU),
656 	CMD_TRAIN(CMD_ERRCL_CPU,	CMD_ERRCL_UCU | CMD_ERRCL_WDU),
657 	CMD_TRAIN(CMD_ERRCL_CPU,	CMD_ERRCL_UCU | CMD_ERRCL_L3_WDU |
658 	    CMD_ERRCL_WDU),
659 
660 	/* CPU: EDU+WDU, EDU+WDU+L3_WDU, EDU+UCU+WDU,  EDU+UCU+WDU+L3_WDU */
661 	CMD_TRAIN(CMD_ERRCL_CPU,	CMD_ERRCL_EDU_ST | CMD_ERRCL_WDU),
662 	CMD_TRAIN(CMD_ERRCL_CPU,	CMD_ERRCL_EDU_BL | CMD_ERRCL_WDU),
663 	CMD_TRAIN(CMD_ERRCL_CPU,	CMD_ERRCL_EDU_ST | CMD_ERRCL_EDU_BL |
664 	    CMD_ERRCL_WDU),
665 	CMD_TRAIN(CMD_ERRCL_CPU,	CMD_ERRCL_EDU_ST | CMD_ERRCL_WDU |
666 	    CMD_ERRCL_L3_WDU),
667 	CMD_TRAIN(CMD_ERRCL_CPU,	CMD_ERRCL_EDU_BL | CMD_ERRCL_WDU |
668 	    CMD_ERRCL_L3_WDU),
669 	CMD_TRAIN(CMD_ERRCL_CPU,	CMD_ERRCL_EDU_ST | CMD_ERRCL_EDU_BL |
670 	    CMD_ERRCL_WDU | CMD_ERRCL_L3_WDU),
671 	CMD_TRAIN(CMD_ERRCL_CPU,	CMD_ERRCL_EDU_ST | CMD_ERRCL_UCU |
672 	    CMD_ERRCL_WDU),
673 	CMD_TRAIN(CMD_ERRCL_CPU,	CMD_ERRCL_EDU_BL | CMD_ERRCL_UCU |
674 	    CMD_ERRCL_WDU),
675 	CMD_TRAIN(CMD_ERRCL_CPU,	CMD_ERRCL_EDU_ST | CMD_ERRCL_EDU_BL |
676 	    CMD_ERRCL_UCU | CMD_ERRCL_WDU),
677 	CMD_TRAIN(CMD_ERRCL_CPU,	CMD_ERRCL_EDU_ST | CMD_ERRCL_UCU |
678 	    CMD_ERRCL_WDU | CMD_ERRCL_L3_WDU),
679 	CMD_TRAIN(CMD_ERRCL_CPU,	CMD_ERRCL_EDU_BL | CMD_ERRCL_UCU |
680 	    CMD_ERRCL_WDU | CMD_ERRCL_L3_WDU),
681 	CMD_TRAIN(CMD_ERRCL_CPU,	CMD_ERRCL_EDU_ST | CMD_ERRCL_EDU_BL |
682 	    CMD_ERRCL_UCU | CMD_ERRCL_WDU | CMD_ERRCL_L3_WDU),
683 
684 	/* WDU: L3_WDU */
685 	CMD_TRAIN(CMD_ERRCL_WDU,	CMD_ERRCL_L3_WDU),
686 
687 	/* L3_UCC: WDC+(zero or more of EDC, CPC, UCC) */
688 	CMD_TRAIN(CMD_ERRCL_L3_UCC,	CMD_ERRCL_WDC),
689 	CMD_TRAIN(CMD_ERRCL_L3_UCC,	CMD_ERRCL_WDC | CMD_ERRCL_EDC),
690 	CMD_TRAIN(CMD_ERRCL_L3_UCC,	CMD_ERRCL_WDC | CMD_ERRCL_CPC),
691 	CMD_TRAIN(CMD_ERRCL_L3_UCC,	CMD_ERRCL_WDC | CMD_ERRCL_UCC),
692 	CMD_TRAIN(CMD_ERRCL_L3_UCC,	CMD_ERRCL_WDC | CMD_ERRCL_EDC |
693 	    CMD_ERRCL_CPC),
694 	CMD_TRAIN(CMD_ERRCL_L3_UCC,	CMD_ERRCL_WDC | CMD_ERRCL_EDC |
695 	    CMD_ERRCL_UCC),
696 	CMD_TRAIN(CMD_ERRCL_L3_UCC,	CMD_ERRCL_WDC | CMD_ERRCL_CPC |
697 	    CMD_ERRCL_UCC),
698 	CMD_TRAIN(CMD_ERRCL_L3_UCC,	CMD_ERRCL_WDC | CMD_ERRCL_EDC |
699 	    CMD_ERRCL_CPC | CMD_ERRCL_UCC),
700 
701 	/* L3_UCU: WDU+(zero or more of EDU, CPU, UCU) */
702 	CMD_TRAIN(CMD_ERRCL_L3_UCU,	CMD_ERRCL_WDU),
703 	CMD_TRAIN(CMD_ERRCL_L3_UCU,	CMD_ERRCL_WDU | CMD_ERRCL_EDU_ST),
704 	CMD_TRAIN(CMD_ERRCL_L3_UCU,	CMD_ERRCL_WDU | CMD_ERRCL_EDU_BL),
705 	CMD_TRAIN(CMD_ERRCL_L3_UCU,	CMD_ERRCL_WDU | CMD_ERRCL_EDU_ST |
706 	    CMD_ERRCL_EDU_BL),
707 	CMD_TRAIN(CMD_ERRCL_L3_UCU,	CMD_ERRCL_WDU | CMD_ERRCL_CPU),
708 	CMD_TRAIN(CMD_ERRCL_L3_UCU,	CMD_ERRCL_WDU | CMD_ERRCL_UCU),
709 	CMD_TRAIN(CMD_ERRCL_L3_UCU,	CMD_ERRCL_WDU | CMD_ERRCL_EDU_ST |
710 	    CMD_ERRCL_CPU),
711 	CMD_TRAIN(CMD_ERRCL_L3_UCU,	CMD_ERRCL_WDU | CMD_ERRCL_EDU_BL |
712 	    CMD_ERRCL_CPU),
713 	CMD_TRAIN(CMD_ERRCL_L3_UCU,	CMD_ERRCL_WDU | CMD_ERRCL_EDU_ST |
714 	    CMD_ERRCL_EDU_BL | CMD_ERRCL_CPU),
715 	CMD_TRAIN(CMD_ERRCL_L3_UCU,	CMD_ERRCL_WDU | CMD_ERRCL_EDU_ST |
716 	    CMD_ERRCL_UCU),
717 	CMD_TRAIN(CMD_ERRCL_L3_UCU,	CMD_ERRCL_WDU | CMD_ERRCL_EDU_BL |
718 	    CMD_ERRCL_UCU),
719 	CMD_TRAIN(CMD_ERRCL_L3_UCU,	CMD_ERRCL_WDU | CMD_ERRCL_EDU_ST |
720 	    CMD_ERRCL_EDU_BL | CMD_ERRCL_UCU),
721 	CMD_TRAIN(CMD_ERRCL_L3_UCU,	CMD_ERRCL_WDU | CMD_ERRCL_CPU |
722 	    CMD_ERRCL_UCU),
723 	CMD_TRAIN(CMD_ERRCL_L3_UCU,	CMD_ERRCL_WDU | CMD_ERRCL_EDU_ST |
724 	    CMD_ERRCL_CPU | CMD_ERRCL_UCU),
725 	CMD_TRAIN(CMD_ERRCL_L3_UCU,	CMD_ERRCL_WDU | CMD_ERRCL_EDU_BL |
726 	    CMD_ERRCL_CPU | CMD_ERRCL_UCU),
727 	CMD_TRAIN(CMD_ERRCL_L3_UCU,	CMD_ERRCL_WDU | CMD_ERRCL_EDU_ST |
728 	    CMD_ERRCL_EDU_BL | CMD_ERRCL_CPU | CMD_ERRCL_UCU),
729 
730 	/* L3_UCU: WDU+(zero or more of EDU, CPU, UCU)+L3_WDU */
731 	CMD_TRAIN(CMD_ERRCL_L3_UCU,	CMD_ERRCL_WDU | CMD_ERRCL_L3_WDU),
732 	CMD_TRAIN(CMD_ERRCL_L3_UCU,	CMD_ERRCL_WDU | CMD_ERRCL_EDU_ST |
733 	    CMD_ERRCL_L3_WDU),
734 	CMD_TRAIN(CMD_ERRCL_L3_UCU,	CMD_ERRCL_WDU | CMD_ERRCL_EDU_BL |
735 	    CMD_ERRCL_L3_WDU),
736 	CMD_TRAIN(CMD_ERRCL_L3_UCU,	CMD_ERRCL_WDU | CMD_ERRCL_EDU_ST |
737 	    CMD_ERRCL_EDU_BL | CMD_ERRCL_L3_WDU),
738 	CMD_TRAIN(CMD_ERRCL_L3_UCU,	CMD_ERRCL_WDU | CMD_ERRCL_CPU |
739 	    CMD_ERRCL_L3_WDU),
740 	CMD_TRAIN(CMD_ERRCL_L3_UCU,	CMD_ERRCL_WDU | CMD_ERRCL_UCU |
741 	    CMD_ERRCL_L3_WDU),
742 	CMD_TRAIN(CMD_ERRCL_L3_UCU,	CMD_ERRCL_WDU | CMD_ERRCL_EDU_ST |
743 	    CMD_ERRCL_CPU | CMD_ERRCL_L3_WDU),
744 	CMD_TRAIN(CMD_ERRCL_L3_UCU,	CMD_ERRCL_WDU | CMD_ERRCL_EDU_BL |
745 	    CMD_ERRCL_CPU | CMD_ERRCL_L3_WDU),
746 	CMD_TRAIN(CMD_ERRCL_L3_UCU,	CMD_ERRCL_WDU | CMD_ERRCL_EDU_ST |
747 	    CMD_ERRCL_EDU_BL | CMD_ERRCL_CPU | CMD_ERRCL_L3_WDU),
748 	CMD_TRAIN(CMD_ERRCL_L3_UCU,	CMD_ERRCL_WDU | CMD_ERRCL_EDU_ST |
749 	    CMD_ERRCL_UCU | CMD_ERRCL_L3_WDU),
750 	CMD_TRAIN(CMD_ERRCL_L3_UCU,	CMD_ERRCL_WDU | CMD_ERRCL_EDU_BL |
751 	    CMD_ERRCL_UCU | CMD_ERRCL_L3_WDU),
752 	CMD_TRAIN(CMD_ERRCL_L3_UCU,	CMD_ERRCL_WDU | CMD_ERRCL_EDU_ST |
753 	    CMD_ERRCL_EDU_BL | CMD_ERRCL_UCU | CMD_ERRCL_L3_WDU),
754 	CMD_TRAIN(CMD_ERRCL_L3_UCU,	CMD_ERRCL_WDU | CMD_ERRCL_CPU |
755 	    CMD_ERRCL_UCU | CMD_ERRCL_L3_WDU),
756 	CMD_TRAIN(CMD_ERRCL_L3_UCU,	CMD_ERRCL_WDU | CMD_ERRCL_EDU_ST |
757 	    CMD_ERRCL_CPU | CMD_ERRCL_UCU | CMD_ERRCL_L3_WDU),
758 	CMD_TRAIN(CMD_ERRCL_L3_UCU,	CMD_ERRCL_WDU | CMD_ERRCL_EDU_BL |
759 	    CMD_ERRCL_CPU | CMD_ERRCL_UCU | CMD_ERRCL_L3_WDU),
760 	CMD_TRAIN(CMD_ERRCL_L3_UCU,	CMD_ERRCL_WDU | CMD_ERRCL_EDU_ST |
761 	    CMD_ERRCL_EDU_BL | CMD_ERRCL_CPU | CMD_ERRCL_UCU |
762 	    CMD_ERRCL_L3_WDU),
763 
764 	/* L3_EDC: WDC+(zero or more of EDC, CPC, UCC) */
765 	CMD_TRAIN(CMD_ERRCL_L3_EDC,	CMD_ERRCL_WDC),
766 	CMD_TRAIN(CMD_ERRCL_L3_EDC,	CMD_ERRCL_WDC | CMD_ERRCL_EDC),
767 	CMD_TRAIN(CMD_ERRCL_L3_EDC,	CMD_ERRCL_WDC | CMD_ERRCL_CPC),
768 	CMD_TRAIN(CMD_ERRCL_L3_EDC,	CMD_ERRCL_WDC | CMD_ERRCL_UCC),
769 	CMD_TRAIN(CMD_ERRCL_L3_EDC,	CMD_ERRCL_WDC | CMD_ERRCL_EDC |
770 	    CMD_ERRCL_CPC),
771 	CMD_TRAIN(CMD_ERRCL_L3_EDC,	CMD_ERRCL_WDC | CMD_ERRCL_EDC |
772 	    CMD_ERRCL_UCC),
773 	CMD_TRAIN(CMD_ERRCL_L3_EDC,	CMD_ERRCL_WDC | CMD_ERRCL_CPC |
774 	    CMD_ERRCL_UCC),
775 	CMD_TRAIN(CMD_ERRCL_L3_EDC,	CMD_ERRCL_WDC | CMD_ERRCL_EDC |
776 	    CMD_ERRCL_CPC | CMD_ERRCL_UCC),
777 
778 	/* L3_EDU: WDU+(zero or more of EDU, CPU, UCU) */
779 	CMD_TRAIN(CMD_ERRCL_L3_EDU_ST,	CMD_ERRCL_WDU),
780 	CMD_TRAIN(CMD_ERRCL_L3_EDU_ST,	CMD_ERRCL_WDU | CMD_ERRCL_EDU_ST),
781 	CMD_TRAIN(CMD_ERRCL_L3_EDU_ST,	CMD_ERRCL_WDU | CMD_ERRCL_EDU_BL),
782 	CMD_TRAIN(CMD_ERRCL_L3_EDU_ST,	CMD_ERRCL_WDU | CMD_ERRCL_EDU_ST |
783 	    CMD_ERRCL_EDU_BL),
784 	CMD_TRAIN(CMD_ERRCL_L3_EDU_ST,	CMD_ERRCL_WDU | CMD_ERRCL_CPU),
785 	CMD_TRAIN(CMD_ERRCL_L3_EDU_ST,	CMD_ERRCL_WDU | CMD_ERRCL_UCU),
786 	CMD_TRAIN(CMD_ERRCL_L3_EDU_ST,	CMD_ERRCL_WDU | CMD_ERRCL_EDU_ST |
787 	    CMD_ERRCL_CPU),
788 	CMD_TRAIN(CMD_ERRCL_L3_EDU_ST,	CMD_ERRCL_WDU | CMD_ERRCL_EDU_BL |
789 	    CMD_ERRCL_CPU),
790 	CMD_TRAIN(CMD_ERRCL_L3_EDU_ST,	CMD_ERRCL_WDU | CMD_ERRCL_EDU_ST |
791 	    CMD_ERRCL_EDU_BL | CMD_ERRCL_CPU),
792 	CMD_TRAIN(CMD_ERRCL_L3_EDU_ST,	CMD_ERRCL_WDU | CMD_ERRCL_EDU_ST |
793 	    CMD_ERRCL_UCU),
794 	CMD_TRAIN(CMD_ERRCL_L3_EDU_ST,	CMD_ERRCL_WDU | CMD_ERRCL_EDU_BL |
795 	    CMD_ERRCL_UCU),
796 	CMD_TRAIN(CMD_ERRCL_L3_EDU_ST,	CMD_ERRCL_WDU | CMD_ERRCL_EDU_ST |
797 	    CMD_ERRCL_EDU_BL | CMD_ERRCL_UCU),
798 	CMD_TRAIN(CMD_ERRCL_L3_EDU_ST,	CMD_ERRCL_WDU | CMD_ERRCL_CPU |
799 	    CMD_ERRCL_UCU),
800 	CMD_TRAIN(CMD_ERRCL_L3_EDU_ST,	CMD_ERRCL_WDU | CMD_ERRCL_EDU_ST |
801 	    CMD_ERRCL_CPU | CMD_ERRCL_UCU),
802 	CMD_TRAIN(CMD_ERRCL_L3_EDU_ST,	CMD_ERRCL_WDU | CMD_ERRCL_EDU_BL |
803 	    CMD_ERRCL_CPU | CMD_ERRCL_UCU),
804 	CMD_TRAIN(CMD_ERRCL_L3_EDU_ST,	CMD_ERRCL_WDU | CMD_ERRCL_EDU_ST |
805 	    CMD_ERRCL_EDU_BL | CMD_ERRCL_CPU | CMD_ERRCL_UCU),
806 	CMD_TRAIN(CMD_ERRCL_L3_EDU_BL,	CMD_ERRCL_WDU),
807 	CMD_TRAIN(CMD_ERRCL_L3_EDU_BL,	CMD_ERRCL_WDU | CMD_ERRCL_EDU_ST),
808 	CMD_TRAIN(CMD_ERRCL_L3_EDU_BL,	CMD_ERRCL_WDU | CMD_ERRCL_EDU_BL),
809 	CMD_TRAIN(CMD_ERRCL_L3_EDU_BL,	CMD_ERRCL_WDU | CMD_ERRCL_EDU_ST |
810 	    CMD_ERRCL_EDU_BL),
811 	CMD_TRAIN(CMD_ERRCL_L3_EDU_BL,	CMD_ERRCL_WDU | CMD_ERRCL_CPU),
812 	CMD_TRAIN(CMD_ERRCL_L3_EDU_BL,	CMD_ERRCL_WDU | CMD_ERRCL_UCU),
813 	CMD_TRAIN(CMD_ERRCL_L3_EDU_BL,	CMD_ERRCL_WDU | CMD_ERRCL_EDU_ST |
814 	    CMD_ERRCL_CPU),
815 	CMD_TRAIN(CMD_ERRCL_L3_EDU_BL,	CMD_ERRCL_WDU | CMD_ERRCL_EDU_BL |
816 	    CMD_ERRCL_CPU),
817 	CMD_TRAIN(CMD_ERRCL_L3_EDU_BL,	CMD_ERRCL_WDU | CMD_ERRCL_EDU_ST |
818 	    CMD_ERRCL_EDU_BL | CMD_ERRCL_CPU),
819 	CMD_TRAIN(CMD_ERRCL_L3_EDU_BL,	CMD_ERRCL_WDU | CMD_ERRCL_EDU_ST |
820 	    CMD_ERRCL_UCU),
821 	CMD_TRAIN(CMD_ERRCL_L3_EDU_BL,	CMD_ERRCL_WDU | CMD_ERRCL_EDU_BL |
822 	    CMD_ERRCL_UCU),
823 	CMD_TRAIN(CMD_ERRCL_L3_EDU_BL,	CMD_ERRCL_WDU | CMD_ERRCL_EDU_ST |
824 	    CMD_ERRCL_EDU_BL | CMD_ERRCL_UCU),
825 	CMD_TRAIN(CMD_ERRCL_L3_EDU_BL,	CMD_ERRCL_WDU | CMD_ERRCL_CPU |
826 	    CMD_ERRCL_UCU),
827 	CMD_TRAIN(CMD_ERRCL_L3_EDU_BL,	CMD_ERRCL_WDU | CMD_ERRCL_EDU_ST |
828 	    CMD_ERRCL_CPU | CMD_ERRCL_UCU),
829 	CMD_TRAIN(CMD_ERRCL_L3_EDU_BL,	CMD_ERRCL_WDU | CMD_ERRCL_EDU_BL |
830 	    CMD_ERRCL_CPU | CMD_ERRCL_UCU),
831 	CMD_TRAIN(CMD_ERRCL_L3_EDU_BL,	CMD_ERRCL_WDU | CMD_ERRCL_EDU_ST |
832 	    CMD_ERRCL_EDU_BL | CMD_ERRCL_CPU | CMD_ERRCL_UCU),
833 
834 	/* L3_EDU: WDU+(zero or more of EDU, CPU, UCU)+L3_WDU */
835 	CMD_TRAIN(CMD_ERRCL_L3_EDU_ST,	CMD_ERRCL_WDU | CMD_ERRCL_L3_WDU),
836 	CMD_TRAIN(CMD_ERRCL_L3_EDU_ST,	CMD_ERRCL_WDU | CMD_ERRCL_EDU_ST |
837 	    CMD_ERRCL_L3_WDU),
838 	CMD_TRAIN(CMD_ERRCL_L3_EDU_ST,	CMD_ERRCL_WDU | CMD_ERRCL_EDU_BL |
839 	    CMD_ERRCL_L3_WDU),
840 	CMD_TRAIN(CMD_ERRCL_L3_EDU_ST,	CMD_ERRCL_WDU | CMD_ERRCL_EDU_ST |
841 	    CMD_ERRCL_EDU_BL | CMD_ERRCL_L3_WDU),
842 	CMD_TRAIN(CMD_ERRCL_L3_EDU_ST,	CMD_ERRCL_WDU | CMD_ERRCL_CPU |
843 	    CMD_ERRCL_L3_WDU),
844 	CMD_TRAIN(CMD_ERRCL_L3_EDU_ST,	CMD_ERRCL_WDU | CMD_ERRCL_UCU |
845 	    CMD_ERRCL_L3_WDU),
846 	CMD_TRAIN(CMD_ERRCL_L3_EDU_ST,	CMD_ERRCL_WDU | CMD_ERRCL_EDU_ST |
847 	    CMD_ERRCL_CPU | CMD_ERRCL_L3_WDU),
848 	CMD_TRAIN(CMD_ERRCL_L3_EDU_ST,	CMD_ERRCL_WDU | CMD_ERRCL_EDU_BL |
849 	    CMD_ERRCL_CPU | CMD_ERRCL_L3_WDU),
850 	CMD_TRAIN(CMD_ERRCL_L3_EDU_ST,	CMD_ERRCL_WDU | CMD_ERRCL_EDU_ST |
851 	    CMD_ERRCL_EDU_BL | CMD_ERRCL_CPU | CMD_ERRCL_L3_WDU),
852 	CMD_TRAIN(CMD_ERRCL_L3_EDU_ST,	CMD_ERRCL_WDU | CMD_ERRCL_EDU_ST |
853 	    CMD_ERRCL_UCU | CMD_ERRCL_L3_WDU),
854 	CMD_TRAIN(CMD_ERRCL_L3_EDU_ST,	CMD_ERRCL_WDU | CMD_ERRCL_EDU_BL |
855 	    CMD_ERRCL_UCU | CMD_ERRCL_L3_WDU),
856 	CMD_TRAIN(CMD_ERRCL_L3_EDU_ST,	CMD_ERRCL_WDU | CMD_ERRCL_EDU_ST |
857 	    CMD_ERRCL_EDU_BL | CMD_ERRCL_UCU | CMD_ERRCL_L3_WDU),
858 	CMD_TRAIN(CMD_ERRCL_L3_EDU_ST,	CMD_ERRCL_WDU | CMD_ERRCL_CPU |
859 	    CMD_ERRCL_UCU | CMD_ERRCL_L3_WDU),
860 	CMD_TRAIN(CMD_ERRCL_L3_EDU_ST,	CMD_ERRCL_WDU | CMD_ERRCL_EDU_ST |
861 	    CMD_ERRCL_CPU | CMD_ERRCL_UCU | CMD_ERRCL_L3_WDU),
862 	CMD_TRAIN(CMD_ERRCL_L3_EDU_ST,	CMD_ERRCL_WDU | CMD_ERRCL_EDU_BL |
863 	    CMD_ERRCL_CPU | CMD_ERRCL_UCU | CMD_ERRCL_L3_WDU),
864 	CMD_TRAIN(CMD_ERRCL_L3_EDU_ST,	CMD_ERRCL_WDU | CMD_ERRCL_EDU_ST |
865 	    CMD_ERRCL_EDU_BL | CMD_ERRCL_CPU | CMD_ERRCL_UCU |
866 	    CMD_ERRCL_L3_WDU),
867 	CMD_TRAIN(CMD_ERRCL_L3_EDU_BL,	CMD_ERRCL_WDU | CMD_ERRCL_L3_WDU),
868 	CMD_TRAIN(CMD_ERRCL_L3_EDU_BL,	CMD_ERRCL_WDU | CMD_ERRCL_EDU_ST |
869 	    CMD_ERRCL_L3_WDU),
870 	CMD_TRAIN(CMD_ERRCL_L3_EDU_BL,	CMD_ERRCL_WDU | CMD_ERRCL_EDU_BL |
871 	    CMD_ERRCL_L3_WDU),
872 	CMD_TRAIN(CMD_ERRCL_L3_EDU_BL,	CMD_ERRCL_WDU | CMD_ERRCL_EDU_ST |
873 	    CMD_ERRCL_EDU_BL | CMD_ERRCL_L3_WDU),
874 	CMD_TRAIN(CMD_ERRCL_L3_EDU_BL,	CMD_ERRCL_WDU | CMD_ERRCL_CPU |
875 	    CMD_ERRCL_L3_WDU),
876 	CMD_TRAIN(CMD_ERRCL_L3_EDU_BL,	CMD_ERRCL_WDU | CMD_ERRCL_UCU |
877 	    CMD_ERRCL_L3_WDU),
878 	CMD_TRAIN(CMD_ERRCL_L3_EDU_BL,	CMD_ERRCL_WDU | CMD_ERRCL_EDU_ST |
879 	    CMD_ERRCL_CPU | CMD_ERRCL_L3_WDU),
880 	CMD_TRAIN(CMD_ERRCL_L3_EDU_BL,	CMD_ERRCL_WDU | CMD_ERRCL_EDU_BL |
881 	    CMD_ERRCL_CPU | CMD_ERRCL_L3_WDU),
882 	CMD_TRAIN(CMD_ERRCL_L3_EDU_BL,	CMD_ERRCL_WDU | CMD_ERRCL_EDU_ST |
883 	    CMD_ERRCL_EDU_BL | CMD_ERRCL_CPU | CMD_ERRCL_L3_WDU),
884 	CMD_TRAIN(CMD_ERRCL_L3_EDU_BL,	CMD_ERRCL_WDU | CMD_ERRCL_EDU_ST |
885 	    CMD_ERRCL_UCU | CMD_ERRCL_L3_WDU),
886 	CMD_TRAIN(CMD_ERRCL_L3_EDU_BL,	CMD_ERRCL_WDU | CMD_ERRCL_EDU_BL |
887 	    CMD_ERRCL_UCU | CMD_ERRCL_L3_WDU),
888 	CMD_TRAIN(CMD_ERRCL_L3_EDU_BL,	CMD_ERRCL_WDU | CMD_ERRCL_EDU_ST |
889 	    CMD_ERRCL_EDU_BL | CMD_ERRCL_UCU | CMD_ERRCL_L3_WDU),
890 	CMD_TRAIN(CMD_ERRCL_L3_EDU_BL,	CMD_ERRCL_WDU | CMD_ERRCL_CPU |
891 	    CMD_ERRCL_UCU | CMD_ERRCL_L3_WDU),
892 	CMD_TRAIN(CMD_ERRCL_L3_EDU_BL,	CMD_ERRCL_WDU | CMD_ERRCL_EDU_ST |
893 	    CMD_ERRCL_CPU | CMD_ERRCL_UCU | CMD_ERRCL_L3_WDU),
894 	CMD_TRAIN(CMD_ERRCL_L3_EDU_BL,	CMD_ERRCL_WDU | CMD_ERRCL_EDU_BL |
895 	    CMD_ERRCL_CPU | CMD_ERRCL_UCU | CMD_ERRCL_L3_WDU),
896 	CMD_TRAIN(CMD_ERRCL_L3_EDU_BL,	CMD_ERRCL_WDU | CMD_ERRCL_EDU_ST |
897 	    CMD_ERRCL_EDU_BL | CMD_ERRCL_CPU | CMD_ERRCL_UCU |
898 	    CMD_ERRCL_L3_WDU),
899 
900 	/* L3_CPC: L3_WDC */
901 	CMD_TRAIN(CMD_ERRCL_L3_CPC,	CMD_ERRCL_L3_WDC),
902 
903 	/* L3_CPC: L3_EDC+ WDC+(zero or more of EDC, CPC, UCC) */
904 	CMD_TRAIN(CMD_ERRCL_L3_CPC,	CMD_ERRCL_L3_EDC | CMD_ERRCL_WDC),
905 	CMD_TRAIN(CMD_ERRCL_L3_CPC,	CMD_ERRCL_L3_EDC | CMD_ERRCL_WDC |
906 	    CMD_ERRCL_EDC),
907 	CMD_TRAIN(CMD_ERRCL_L3_CPC,	CMD_ERRCL_L3_EDC | CMD_ERRCL_WDC |
908 	    CMD_ERRCL_CPC),
909 	CMD_TRAIN(CMD_ERRCL_L3_CPC,	CMD_ERRCL_L3_EDC | CMD_ERRCL_WDC |
910 	    CMD_ERRCL_UCC),
911 	CMD_TRAIN(CMD_ERRCL_L3_CPC,	CMD_ERRCL_L3_EDC | CMD_ERRCL_WDC |
912 	    CMD_ERRCL_EDC | CMD_ERRCL_CPC),
913 	CMD_TRAIN(CMD_ERRCL_L3_CPC,	CMD_ERRCL_L3_EDC | CMD_ERRCL_WDC |
914 	    CMD_ERRCL_EDC | CMD_ERRCL_UCC),
915 	CMD_TRAIN(CMD_ERRCL_L3_CPC,	CMD_ERRCL_L3_EDC | CMD_ERRCL_WDC |
916 	    CMD_ERRCL_CPC | CMD_ERRCL_UCC),
917 	CMD_TRAIN(CMD_ERRCL_L3_CPC,	CMD_ERRCL_L3_EDC | CMD_ERRCL_WDC |
918 	    CMD_ERRCL_EDC | CMD_ERRCL_CPC | CMD_ERRCL_UCC),
919 
920 	/* L3_CPC: L3_UCC+WDC+(zero or more of EDC, CPC, UCC) */
921 	CMD_TRAIN(CMD_ERRCL_L3_CPC,	CMD_ERRCL_L3_UCC | CMD_ERRCL_WDC),
922 	CMD_TRAIN(CMD_ERRCL_L3_CPC,	CMD_ERRCL_L3_UCC | CMD_ERRCL_WDC |
923 	    CMD_ERRCL_EDC),
924 	CMD_TRAIN(CMD_ERRCL_L3_CPC,	CMD_ERRCL_L3_UCC | CMD_ERRCL_WDC |
925 	    CMD_ERRCL_CPC),
926 	CMD_TRAIN(CMD_ERRCL_L3_CPC,	CMD_ERRCL_L3_UCC | CMD_ERRCL_WDC |
927 	    CMD_ERRCL_UCC),
928 	CMD_TRAIN(CMD_ERRCL_L3_CPC,	CMD_ERRCL_L3_UCC | CMD_ERRCL_WDC |
929 	    CMD_ERRCL_EDC | CMD_ERRCL_CPC),
930 	CMD_TRAIN(CMD_ERRCL_L3_CPC,	CMD_ERRCL_L3_UCC | CMD_ERRCL_WDC |
931 	    CMD_ERRCL_EDC | CMD_ERRCL_UCC),
932 	CMD_TRAIN(CMD_ERRCL_L3_CPC,	CMD_ERRCL_L3_UCC | CMD_ERRCL_WDC |
933 	    CMD_ERRCL_CPC | CMD_ERRCL_UCC),
934 	CMD_TRAIN(CMD_ERRCL_L3_CPC,	CMD_ERRCL_L3_UCC | CMD_ERRCL_WDC |
935 	    CMD_ERRCL_EDC | CMD_ERRCL_CPC | CMD_ERRCL_UCC),
936 
937 	/* L3_CPU: L3_WDU */
938 	CMD_TRAIN(CMD_ERRCL_L3_CPU,	CMD_ERRCL_L3_WDU),
939 
940 	/* L3_CPU: L3_EDU+WDU+(zero or more of EDU, CPU, UCU) */
941 	CMD_TRAIN(CMD_ERRCL_L3_CPU,	CMD_ERRCL_L3_EDU_ST | CMD_ERRCL_WDU),
942 	CMD_TRAIN(CMD_ERRCL_L3_CPU,	CMD_ERRCL_L3_EDU_BL | CMD_ERRCL_WDU),
943 	CMD_TRAIN(CMD_ERRCL_L3_CPU,	CMD_ERRCL_L3_EDU_ST |
944 	    CMD_ERRCL_L3_EDU_BL | CMD_ERRCL_WDU),
945 	CMD_TRAIN(CMD_ERRCL_L3_CPU,	CMD_ERRCL_L3_EDU_ST | CMD_ERRCL_WDU |
946 	    CMD_ERRCL_EDU_ST),
947 	CMD_TRAIN(CMD_ERRCL_L3_CPU,	CMD_ERRCL_L3_EDU_BL | CMD_ERRCL_WDU |
948 	    CMD_ERRCL_EDU_ST),
949 	CMD_TRAIN(CMD_ERRCL_L3_CPU,	CMD_ERRCL_L3_EDU_ST |
950 	    CMD_ERRCL_L3_EDU_BL | CMD_ERRCL_WDU | CMD_ERRCL_EDU_ST),
951 	CMD_TRAIN(CMD_ERRCL_L3_CPU,	CMD_ERRCL_L3_EDU_ST | CMD_ERRCL_WDU |
952 	    CMD_ERRCL_EDU_BL),
953 	CMD_TRAIN(CMD_ERRCL_L3_CPU,	CMD_ERRCL_L3_EDU_BL | CMD_ERRCL_WDU |
954 	    CMD_ERRCL_EDU_BL),
955 	CMD_TRAIN(CMD_ERRCL_L3_CPU,	CMD_ERRCL_L3_EDU_ST |
956 	    CMD_ERRCL_L3_EDU_BL | CMD_ERRCL_WDU | CMD_ERRCL_EDU_BL),
957 	CMD_TRAIN(CMD_ERRCL_L3_CPU,	CMD_ERRCL_L3_EDU_ST | CMD_ERRCL_WDU |
958 	    CMD_ERRCL_EDU_ST | CMD_ERRCL_EDU_BL),
959 	CMD_TRAIN(CMD_ERRCL_L3_CPU,	CMD_ERRCL_L3_EDU_BL | CMD_ERRCL_WDU |
960 	    CMD_ERRCL_EDU_ST | CMD_ERRCL_EDU_BL),
961 	CMD_TRAIN(CMD_ERRCL_L3_CPU,	CMD_ERRCL_L3_EDU_ST |
962 	    CMD_ERRCL_L3_EDU_BL | CMD_ERRCL_WDU | CMD_ERRCL_EDU_ST |
963 	    CMD_ERRCL_EDU_BL),
964 	CMD_TRAIN(CMD_ERRCL_L3_CPU,	CMD_ERRCL_L3_EDU_ST | CMD_ERRCL_WDU |
965 	    CMD_ERRCL_CPU),
966 	CMD_TRAIN(CMD_ERRCL_L3_CPU,	CMD_ERRCL_L3_EDU_BL | CMD_ERRCL_WDU |
967 	    CMD_ERRCL_CPU),
968 	CMD_TRAIN(CMD_ERRCL_L3_CPU,	CMD_ERRCL_L3_EDU_ST |
969 	    CMD_ERRCL_L3_EDU_BL | CMD_ERRCL_WDU | CMD_ERRCL_CPU),
970 	CMD_TRAIN(CMD_ERRCL_L3_CPU,	CMD_ERRCL_L3_EDU_ST | CMD_ERRCL_WDU |
971 	    CMD_ERRCL_UCU),
972 	CMD_TRAIN(CMD_ERRCL_L3_CPU,	CMD_ERRCL_L3_EDU_BL | CMD_ERRCL_WDU |
973 	    CMD_ERRCL_UCU),
974 	CMD_TRAIN(CMD_ERRCL_L3_CPU,	CMD_ERRCL_L3_EDU_ST |
975 	    CMD_ERRCL_L3_EDU_BL | CMD_ERRCL_WDU | CMD_ERRCL_UCU),
976 	CMD_TRAIN(CMD_ERRCL_L3_CPU,	CMD_ERRCL_L3_EDU_ST | CMD_ERRCL_WDU |
977 	    CMD_ERRCL_EDU_ST | CMD_ERRCL_CPU),
978 	CMD_TRAIN(CMD_ERRCL_L3_CPU,	CMD_ERRCL_L3_EDU_BL | CMD_ERRCL_WDU |
979 	    CMD_ERRCL_EDU_ST | CMD_ERRCL_CPU),
980 	CMD_TRAIN(CMD_ERRCL_L3_CPU,	CMD_ERRCL_L3_EDU_ST |
981 	    CMD_ERRCL_L3_EDU_BL | CMD_ERRCL_WDU | CMD_ERRCL_EDU_ST |
982 	    CMD_ERRCL_CPU),
983 	CMD_TRAIN(CMD_ERRCL_L3_CPU,	CMD_ERRCL_L3_EDU_ST | CMD_ERRCL_WDU |
984 	    CMD_ERRCL_EDU_BL | CMD_ERRCL_CPU),
985 	CMD_TRAIN(CMD_ERRCL_L3_CPU,	CMD_ERRCL_L3_EDU_BL | CMD_ERRCL_WDU |
986 	    CMD_ERRCL_EDU_BL | CMD_ERRCL_CPU),
987 	CMD_TRAIN(CMD_ERRCL_L3_CPU,	CMD_ERRCL_L3_EDU_ST |
988 	    CMD_ERRCL_L3_EDU_BL | CMD_ERRCL_WDU | CMD_ERRCL_EDU_BL |
989 	    CMD_ERRCL_CPU),
990 	CMD_TRAIN(CMD_ERRCL_L3_CPU,	CMD_ERRCL_L3_EDU_ST | CMD_ERRCL_WDU |
991 	    CMD_ERRCL_EDU_ST | CMD_ERRCL_EDU_BL | CMD_ERRCL_CPU),
992 	CMD_TRAIN(CMD_ERRCL_L3_CPU,	CMD_ERRCL_L3_EDU_BL | CMD_ERRCL_WDU |
993 	    CMD_ERRCL_EDU_ST | CMD_ERRCL_EDU_BL | CMD_ERRCL_CPU),
994 	CMD_TRAIN(CMD_ERRCL_L3_CPU,	CMD_ERRCL_L3_EDU_ST |
995 	    CMD_ERRCL_L3_EDU_BL | CMD_ERRCL_WDU | CMD_ERRCL_EDU_ST |
996 	    CMD_ERRCL_EDU_BL | CMD_ERRCL_CPU),
997 	CMD_TRAIN(CMD_ERRCL_L3_CPU,	CMD_ERRCL_L3_EDU_ST | CMD_ERRCL_WDU |
998 	    CMD_ERRCL_EDU_ST | CMD_ERRCL_UCU),
999 	CMD_TRAIN(CMD_ERRCL_L3_CPU,	CMD_ERRCL_L3_EDU_BL | CMD_ERRCL_WDU |
1000 	    CMD_ERRCL_EDU_ST | CMD_ERRCL_UCU),
1001 	CMD_TRAIN(CMD_ERRCL_L3_CPU,	CMD_ERRCL_L3_EDU_ST |
1002 	    CMD_ERRCL_L3_EDU_BL | CMD_ERRCL_WDU | CMD_ERRCL_EDU_ST |
1003 	    CMD_ERRCL_UCU),
1004 	CMD_TRAIN(CMD_ERRCL_L3_CPU,	CMD_ERRCL_L3_EDU_ST | CMD_ERRCL_WDU |
1005 	    CMD_ERRCL_EDU_BL | CMD_ERRCL_UCU),
1006 	CMD_TRAIN(CMD_ERRCL_L3_CPU,	CMD_ERRCL_L3_EDU_BL | CMD_ERRCL_WDU |
1007 	    CMD_ERRCL_EDU_BL | CMD_ERRCL_UCU),
1008 	CMD_TRAIN(CMD_ERRCL_L3_CPU,	CMD_ERRCL_L3_EDU_ST |
1009 	    CMD_ERRCL_L3_EDU_BL | CMD_ERRCL_WDU | CMD_ERRCL_EDU_BL |
1010 	    CMD_ERRCL_UCU),
1011 	CMD_TRAIN(CMD_ERRCL_L3_CPU,	CMD_ERRCL_L3_EDU_ST | CMD_ERRCL_WDU |
1012 	    CMD_ERRCL_EDU_ST | CMD_ERRCL_EDU_BL | CMD_ERRCL_UCU),
1013 	CMD_TRAIN(CMD_ERRCL_L3_CPU,	CMD_ERRCL_L3_EDU_BL | CMD_ERRCL_WDU |
1014 	    CMD_ERRCL_EDU_ST | CMD_ERRCL_EDU_BL | CMD_ERRCL_UCU),
1015 	CMD_TRAIN(CMD_ERRCL_L3_CPU,	CMD_ERRCL_L3_EDU_ST |
1016 	    CMD_ERRCL_L3_EDU_BL | CMD_ERRCL_WDU | CMD_ERRCL_EDU_ST |
1017 	    CMD_ERRCL_EDU_BL | CMD_ERRCL_UCU),
1018 	CMD_TRAIN(CMD_ERRCL_L3_CPU,	CMD_ERRCL_L3_EDU_ST | CMD_ERRCL_WDU |
1019 	    CMD_ERRCL_CPU | CMD_ERRCL_UCU),
1020 	CMD_TRAIN(CMD_ERRCL_L3_CPU,	CMD_ERRCL_L3_EDU_BL | CMD_ERRCL_WDU |
1021 	    CMD_ERRCL_CPU | CMD_ERRCL_UCU),
1022 	CMD_TRAIN(CMD_ERRCL_L3_CPU,	CMD_ERRCL_L3_EDU_ST |
1023 	    CMD_ERRCL_L3_EDU_BL | CMD_ERRCL_WDU | CMD_ERRCL_CPU |
1024 	    CMD_ERRCL_UCU),
1025 	CMD_TRAIN(CMD_ERRCL_L3_CPU,	CMD_ERRCL_L3_EDU_ST | CMD_ERRCL_WDU |
1026 	    CMD_ERRCL_EDU_ST | CMD_ERRCL_CPU | CMD_ERRCL_UCU),
1027 	CMD_TRAIN(CMD_ERRCL_L3_CPU,	CMD_ERRCL_L3_EDU_BL | CMD_ERRCL_WDU |
1028 	    CMD_ERRCL_EDU_ST | CMD_ERRCL_CPU | CMD_ERRCL_UCU),
1029 	CMD_TRAIN(CMD_ERRCL_L3_CPU,	CMD_ERRCL_L3_EDU_ST |
1030 	    CMD_ERRCL_L3_EDU_BL | CMD_ERRCL_WDU | CMD_ERRCL_EDU_ST |
1031 	    CMD_ERRCL_CPU | CMD_ERRCL_UCU),
1032 	CMD_TRAIN(CMD_ERRCL_L3_CPU,	CMD_ERRCL_L3_EDU_ST | CMD_ERRCL_WDU |
1033 	    CMD_ERRCL_EDU_BL | CMD_ERRCL_CPU | CMD_ERRCL_UCU),
1034 	CMD_TRAIN(CMD_ERRCL_L3_CPU,	CMD_ERRCL_L3_EDU_BL | CMD_ERRCL_WDU |
1035 	    CMD_ERRCL_EDU_BL | CMD_ERRCL_CPU | CMD_ERRCL_UCU),
1036 	CMD_TRAIN(CMD_ERRCL_L3_CPU,	CMD_ERRCL_L3_EDU_ST |
1037 	    CMD_ERRCL_L3_EDU_BL | CMD_ERRCL_WDU | CMD_ERRCL_EDU_BL |
1038 	    CMD_ERRCL_CPU | CMD_ERRCL_UCU),
1039 	CMD_TRAIN(CMD_ERRCL_L3_CPU,	CMD_ERRCL_L3_EDU_ST | CMD_ERRCL_WDU |
1040 	    CMD_ERRCL_EDU_ST | CMD_ERRCL_EDU_BL | CMD_ERRCL_CPU |
1041 	    CMD_ERRCL_UCU),
1042 	CMD_TRAIN(CMD_ERRCL_L3_CPU,	CMD_ERRCL_L3_EDU_BL | CMD_ERRCL_WDU |
1043 	    CMD_ERRCL_EDU_ST | CMD_ERRCL_EDU_BL | CMD_ERRCL_CPU |
1044 	    CMD_ERRCL_UCU),
1045 	CMD_TRAIN(CMD_ERRCL_L3_CPU,	CMD_ERRCL_L3_EDU_ST |
1046 	    CMD_ERRCL_L3_EDU_BL | CMD_ERRCL_WDU | CMD_ERRCL_EDU_ST |
1047 	    CMD_ERRCL_EDU_BL | CMD_ERRCL_CPU | CMD_ERRCL_UCU),
1048 
1049 	/* L3_CPU: L3_UCU+WDU+(zero or more of EDU, CPU, UCU) */
1050 	CMD_TRAIN(CMD_ERRCL_L3_CPU,	CMD_ERRCL_L3_UCU | CMD_ERRCL_WDU),
1051 	CMD_TRAIN(CMD_ERRCL_L3_CPU,	CMD_ERRCL_L3_UCU | CMD_ERRCL_WDU |
1052 	    CMD_ERRCL_EDU_ST),
1053 	CMD_TRAIN(CMD_ERRCL_L3_CPU,	CMD_ERRCL_L3_UCU | CMD_ERRCL_WDU |
1054 	    CMD_ERRCL_EDU_BL),
1055 	CMD_TRAIN(CMD_ERRCL_L3_CPU,	CMD_ERRCL_L3_UCU | CMD_ERRCL_WDU |
1056 	    CMD_ERRCL_EDU_ST |CMD_ERRCL_EDU_BL),
1057 	CMD_TRAIN(CMD_ERRCL_L3_CPU,	CMD_ERRCL_L3_UCU | CMD_ERRCL_WDU |
1058 	    CMD_ERRCL_CPU),
1059 	CMD_TRAIN(CMD_ERRCL_L3_CPU,	CMD_ERRCL_L3_UCU | CMD_ERRCL_WDU |
1060 	    CMD_ERRCL_UCU),
1061 	CMD_TRAIN(CMD_ERRCL_L3_CPU,	CMD_ERRCL_L3_UCU | CMD_ERRCL_WDU |
1062 	    CMD_ERRCL_EDU_ST | CMD_ERRCL_CPU),
1063 	CMD_TRAIN(CMD_ERRCL_L3_CPU,	CMD_ERRCL_L3_UCU | CMD_ERRCL_WDU |
1064 	    CMD_ERRCL_EDU_BL | CMD_ERRCL_CPU),
1065 	CMD_TRAIN(CMD_ERRCL_L3_CPU,	CMD_ERRCL_L3_UCU | CMD_ERRCL_WDU |
1066 	    CMD_ERRCL_EDU_ST | CMD_ERRCL_EDU_BL | CMD_ERRCL_CPU),
1067 	CMD_TRAIN(CMD_ERRCL_L3_CPU,	CMD_ERRCL_L3_UCU | CMD_ERRCL_WDU |
1068 	    CMD_ERRCL_EDU_ST | CMD_ERRCL_UCU),
1069 	CMD_TRAIN(CMD_ERRCL_L3_CPU,	CMD_ERRCL_L3_UCU | CMD_ERRCL_WDU |
1070 	    CMD_ERRCL_EDU_BL | CMD_ERRCL_UCU),
1071 	CMD_TRAIN(CMD_ERRCL_L3_CPU,	CMD_ERRCL_L3_UCU | CMD_ERRCL_WDU |
1072 	    CMD_ERRCL_EDU_ST | CMD_ERRCL_EDU_BL | CMD_ERRCL_UCU),
1073 	CMD_TRAIN(CMD_ERRCL_L3_CPU,	CMD_ERRCL_L3_UCU | CMD_ERRCL_WDU |
1074 	    CMD_ERRCL_CPU | CMD_ERRCL_UCU),
1075 	CMD_TRAIN(CMD_ERRCL_L3_CPU,	CMD_ERRCL_L3_UCU | CMD_ERRCL_WDU |
1076 	    CMD_ERRCL_EDU_ST | CMD_ERRCL_CPU | CMD_ERRCL_UCU),
1077 	CMD_TRAIN(CMD_ERRCL_L3_CPU,	CMD_ERRCL_L3_UCU | CMD_ERRCL_WDU |
1078 	    CMD_ERRCL_EDU_BL | CMD_ERRCL_CPU | CMD_ERRCL_UCU),
1079 	CMD_TRAIN(CMD_ERRCL_L3_CPU,	CMD_ERRCL_L3_UCU | CMD_ERRCL_WDU |
1080 	    CMD_ERRCL_EDU_ST | CMD_ERRCL_EDU_BL | CMD_ERRCL_CPU |
1081 	    CMD_ERRCL_UCU),
1082 
1083 	/* L3_CPU: L3_EDU+WDU+(zero or more of EDU, CPU, UCU)+L3_WDU */
1084 	CMD_TRAIN(CMD_ERRCL_L3_CPU,	CMD_ERRCL_L3_EDU_ST | CMD_ERRCL_WDU |
1085 	    CMD_ERRCL_L3_WDU),
1086 	CMD_TRAIN(CMD_ERRCL_L3_CPU,	CMD_ERRCL_L3_EDU_BL | CMD_ERRCL_WDU |
1087 	    CMD_ERRCL_L3_WDU),
1088 	CMD_TRAIN(CMD_ERRCL_L3_CPU,	CMD_ERRCL_L3_EDU_ST |
1089 	    CMD_ERRCL_L3_EDU_BL | CMD_ERRCL_WDU | CMD_ERRCL_L3_WDU),
1090 	CMD_TRAIN(CMD_ERRCL_L3_CPU,	CMD_ERRCL_L3_EDU_ST | CMD_ERRCL_WDU |
1091 	    CMD_ERRCL_EDU_ST | CMD_ERRCL_L3_WDU),
1092 	CMD_TRAIN(CMD_ERRCL_L3_CPU,	CMD_ERRCL_L3_EDU_BL | CMD_ERRCL_WDU |
1093 	    CMD_ERRCL_EDU_ST | CMD_ERRCL_L3_WDU),
1094 	CMD_TRAIN(CMD_ERRCL_L3_CPU,	CMD_ERRCL_L3_EDU_ST |
1095 	    CMD_ERRCL_L3_EDU_BL | CMD_ERRCL_WDU | CMD_ERRCL_EDU_ST |
1096 	    CMD_ERRCL_L3_WDU),
1097 	CMD_TRAIN(CMD_ERRCL_L3_CPU,	CMD_ERRCL_L3_EDU_ST | CMD_ERRCL_WDU |
1098 	    CMD_ERRCL_EDU_BL | CMD_ERRCL_L3_WDU),
1099 	CMD_TRAIN(CMD_ERRCL_L3_CPU,	CMD_ERRCL_L3_EDU_BL | CMD_ERRCL_WDU |
1100 	    CMD_ERRCL_EDU_BL | CMD_ERRCL_L3_WDU),
1101 	CMD_TRAIN(CMD_ERRCL_L3_CPU,	CMD_ERRCL_L3_EDU_ST |
1102 	    CMD_ERRCL_L3_EDU_BL | CMD_ERRCL_WDU | CMD_ERRCL_EDU_BL |
1103 	    CMD_ERRCL_L3_WDU),
1104 	CMD_TRAIN(CMD_ERRCL_L3_CPU,	CMD_ERRCL_L3_EDU_ST | CMD_ERRCL_WDU |
1105 	    CMD_ERRCL_EDU_ST | CMD_ERRCL_EDU_BL | CMD_ERRCL_L3_WDU),
1106 	CMD_TRAIN(CMD_ERRCL_L3_CPU,	CMD_ERRCL_L3_EDU_BL | CMD_ERRCL_WDU |
1107 	    CMD_ERRCL_EDU_ST | CMD_ERRCL_EDU_BL | CMD_ERRCL_L3_WDU),
1108 	CMD_TRAIN(CMD_ERRCL_L3_CPU,	CMD_ERRCL_L3_EDU_ST |
1109 	    CMD_ERRCL_L3_EDU_BL | CMD_ERRCL_WDU | CMD_ERRCL_EDU_ST |
1110 	    CMD_ERRCL_EDU_BL | CMD_ERRCL_L3_WDU),
1111 	CMD_TRAIN(CMD_ERRCL_L3_CPU,	CMD_ERRCL_L3_EDU_ST | CMD_ERRCL_WDU |
1112 	    CMD_ERRCL_CPU | CMD_ERRCL_L3_WDU),
1113 	CMD_TRAIN(CMD_ERRCL_L3_CPU,	CMD_ERRCL_L3_EDU_BL | CMD_ERRCL_WDU |
1114 	    CMD_ERRCL_CPU | CMD_ERRCL_L3_WDU),
1115 	CMD_TRAIN(CMD_ERRCL_L3_CPU,	CMD_ERRCL_L3_EDU_ST |
1116 	    CMD_ERRCL_L3_EDU_BL | CMD_ERRCL_WDU | CMD_ERRCL_CPU |
1117 	    CMD_ERRCL_L3_WDU),
1118 	CMD_TRAIN(CMD_ERRCL_L3_CPU,	CMD_ERRCL_L3_EDU_ST | CMD_ERRCL_WDU |
1119 	    CMD_ERRCL_UCU | CMD_ERRCL_L3_WDU),
1120 	CMD_TRAIN(CMD_ERRCL_L3_CPU,	CMD_ERRCL_L3_EDU_BL | CMD_ERRCL_WDU |
1121 	    CMD_ERRCL_UCU | CMD_ERRCL_L3_WDU),
1122 	CMD_TRAIN(CMD_ERRCL_L3_CPU,	CMD_ERRCL_L3_EDU_ST |
1123 	    CMD_ERRCL_L3_EDU_BL | CMD_ERRCL_WDU | CMD_ERRCL_UCU |
1124 	    CMD_ERRCL_L3_WDU),
1125 	CMD_TRAIN(CMD_ERRCL_L3_CPU,	CMD_ERRCL_L3_EDU_ST | CMD_ERRCL_WDU |
1126 	    CMD_ERRCL_EDU_ST | CMD_ERRCL_CPU | CMD_ERRCL_L3_WDU),
1127 	CMD_TRAIN(CMD_ERRCL_L3_CPU,	CMD_ERRCL_L3_EDU_BL | CMD_ERRCL_WDU |
1128 	    CMD_ERRCL_EDU_ST | CMD_ERRCL_CPU | CMD_ERRCL_L3_WDU),
1129 	CMD_TRAIN(CMD_ERRCL_L3_CPU,	CMD_ERRCL_L3_EDU_ST |
1130 	    CMD_ERRCL_L3_EDU_BL | CMD_ERRCL_WDU | CMD_ERRCL_EDU_ST |
1131 	    CMD_ERRCL_CPU | CMD_ERRCL_L3_WDU),
1132 	CMD_TRAIN(CMD_ERRCL_L3_CPU,	CMD_ERRCL_L3_EDU_ST | CMD_ERRCL_WDU |
1133 	    CMD_ERRCL_EDU_BL | CMD_ERRCL_CPU | CMD_ERRCL_L3_WDU),
1134 	CMD_TRAIN(CMD_ERRCL_L3_CPU,	CMD_ERRCL_L3_EDU_BL | CMD_ERRCL_WDU |
1135 	    CMD_ERRCL_EDU_BL | CMD_ERRCL_CPU | CMD_ERRCL_L3_WDU),
1136 	CMD_TRAIN(CMD_ERRCL_L3_CPU,	CMD_ERRCL_L3_EDU_ST |
1137 	    CMD_ERRCL_L3_EDU_BL | CMD_ERRCL_WDU | CMD_ERRCL_EDU_BL |
1138 	    CMD_ERRCL_CPU | CMD_ERRCL_L3_WDU),
1139 	CMD_TRAIN(CMD_ERRCL_L3_CPU,	CMD_ERRCL_L3_EDU_ST | CMD_ERRCL_WDU |
1140 	    CMD_ERRCL_EDU_ST | CMD_ERRCL_EDU_BL | CMD_ERRCL_CPU |
1141 	    CMD_ERRCL_L3_WDU),
1142 	CMD_TRAIN(CMD_ERRCL_L3_CPU,	CMD_ERRCL_L3_EDU_BL | CMD_ERRCL_WDU |
1143 	    CMD_ERRCL_EDU_ST | CMD_ERRCL_EDU_BL | CMD_ERRCL_CPU |
1144 	    CMD_ERRCL_L3_WDU),
1145 	CMD_TRAIN(CMD_ERRCL_L3_CPU,	CMD_ERRCL_L3_EDU_ST |
1146 	    CMD_ERRCL_L3_EDU_BL | CMD_ERRCL_WDU | CMD_ERRCL_EDU_ST |
1147 	    CMD_ERRCL_EDU_BL | CMD_ERRCL_CPU | CMD_ERRCL_L3_WDU),
1148 	CMD_TRAIN(CMD_ERRCL_L3_CPU,	CMD_ERRCL_L3_EDU_ST | CMD_ERRCL_WDU |
1149 	    CMD_ERRCL_EDU_ST | CMD_ERRCL_UCU | CMD_ERRCL_L3_WDU),
1150 	CMD_TRAIN(CMD_ERRCL_L3_CPU,	CMD_ERRCL_L3_EDU_BL | CMD_ERRCL_WDU |
1151 	    CMD_ERRCL_EDU_ST | CMD_ERRCL_UCU | CMD_ERRCL_L3_WDU),
1152 	CMD_TRAIN(CMD_ERRCL_L3_CPU,	CMD_ERRCL_L3_EDU_ST |
1153 	    CMD_ERRCL_L3_EDU_BL | CMD_ERRCL_WDU | CMD_ERRCL_EDU_ST |
1154 	    CMD_ERRCL_UCU | CMD_ERRCL_L3_WDU),
1155 	CMD_TRAIN(CMD_ERRCL_L3_CPU,	CMD_ERRCL_L3_EDU_ST | CMD_ERRCL_WDU |
1156 	    CMD_ERRCL_EDU_BL | CMD_ERRCL_UCU | CMD_ERRCL_L3_WDU),
1157 	CMD_TRAIN(CMD_ERRCL_L3_CPU,	CMD_ERRCL_L3_EDU_BL | CMD_ERRCL_WDU |
1158 	    CMD_ERRCL_EDU_BL | CMD_ERRCL_UCU | CMD_ERRCL_L3_WDU),
1159 	CMD_TRAIN(CMD_ERRCL_L3_CPU,	CMD_ERRCL_L3_EDU_ST |
1160 	    CMD_ERRCL_L3_EDU_BL | CMD_ERRCL_WDU | CMD_ERRCL_EDU_BL |
1161 	    CMD_ERRCL_UCU | CMD_ERRCL_L3_WDU),
1162 	CMD_TRAIN(CMD_ERRCL_L3_CPU,	CMD_ERRCL_L3_EDU_ST | CMD_ERRCL_WDU |
1163 	    CMD_ERRCL_EDU_ST | CMD_ERRCL_EDU_BL | CMD_ERRCL_UCU |
1164 	    CMD_ERRCL_L3_WDU),
1165 	CMD_TRAIN(CMD_ERRCL_L3_CPU,	CMD_ERRCL_L3_EDU_BL | CMD_ERRCL_WDU |
1166 	    CMD_ERRCL_EDU_ST | CMD_ERRCL_EDU_BL | CMD_ERRCL_UCU |
1167 	    CMD_ERRCL_L3_WDU),
1168 	CMD_TRAIN(CMD_ERRCL_L3_CPU,	CMD_ERRCL_L3_EDU_ST |
1169 	    CMD_ERRCL_L3_EDU_BL | CMD_ERRCL_WDU | CMD_ERRCL_EDU_ST |
1170 	    CMD_ERRCL_EDU_BL | CMD_ERRCL_UCU | CMD_ERRCL_L3_WDU),
1171 	CMD_TRAIN(CMD_ERRCL_L3_CPU,	CMD_ERRCL_L3_EDU_ST | CMD_ERRCL_WDU |
1172 	    CMD_ERRCL_CPU | CMD_ERRCL_UCU | CMD_ERRCL_L3_WDU),
1173 	CMD_TRAIN(CMD_ERRCL_L3_CPU,	CMD_ERRCL_L3_EDU_BL | CMD_ERRCL_WDU |
1174 	    CMD_ERRCL_CPU | CMD_ERRCL_UCU | CMD_ERRCL_L3_WDU),
1175 	CMD_TRAIN(CMD_ERRCL_L3_CPU,	CMD_ERRCL_L3_EDU_ST |
1176 	    CMD_ERRCL_L3_EDU_BL | CMD_ERRCL_WDU | CMD_ERRCL_CPU |
1177 	    CMD_ERRCL_UCU | CMD_ERRCL_L3_WDU),
1178 	CMD_TRAIN(CMD_ERRCL_L3_CPU,	CMD_ERRCL_L3_EDU_ST | CMD_ERRCL_WDU |
1179 	    CMD_ERRCL_EDU_ST | CMD_ERRCL_CPU | CMD_ERRCL_UCU |
1180 	    CMD_ERRCL_L3_WDU),
1181 	CMD_TRAIN(CMD_ERRCL_L3_CPU,	CMD_ERRCL_L3_EDU_BL | CMD_ERRCL_WDU |
1182 	    CMD_ERRCL_EDU_ST | CMD_ERRCL_CPU | CMD_ERRCL_UCU |
1183 	    CMD_ERRCL_L3_WDU),
1184 	CMD_TRAIN(CMD_ERRCL_L3_CPU,	CMD_ERRCL_L3_EDU_ST |
1185 	    CMD_ERRCL_L3_EDU_BL | CMD_ERRCL_WDU | CMD_ERRCL_EDU_ST |
1186 	    CMD_ERRCL_CPU | CMD_ERRCL_UCU | CMD_ERRCL_L3_WDU),
1187 	CMD_TRAIN(CMD_ERRCL_L3_CPU,	CMD_ERRCL_L3_EDU_ST | CMD_ERRCL_WDU |
1188 	    CMD_ERRCL_EDU_BL | CMD_ERRCL_CPU | CMD_ERRCL_UCU |
1189 	    CMD_ERRCL_L3_WDU),
1190 	CMD_TRAIN(CMD_ERRCL_L3_CPU,	CMD_ERRCL_L3_EDU_BL | CMD_ERRCL_WDU |
1191 	    CMD_ERRCL_EDU_BL | CMD_ERRCL_CPU | CMD_ERRCL_UCU |
1192 	    CMD_ERRCL_L3_WDU),
1193 	CMD_TRAIN(CMD_ERRCL_L3_CPU,	CMD_ERRCL_L3_EDU_ST |
1194 	    CMD_ERRCL_L3_EDU_BL | CMD_ERRCL_WDU | CMD_ERRCL_EDU_BL |
1195 	    CMD_ERRCL_CPU | CMD_ERRCL_UCU | CMD_ERRCL_L3_WDU),
1196 	CMD_TRAIN(CMD_ERRCL_L3_CPU,	CMD_ERRCL_L3_EDU_ST | CMD_ERRCL_WDU |
1197 	    CMD_ERRCL_EDU_ST | CMD_ERRCL_EDU_BL | CMD_ERRCL_CPU |
1198 	    CMD_ERRCL_UCU | CMD_ERRCL_L3_WDU),
1199 	CMD_TRAIN(CMD_ERRCL_L3_CPU,	CMD_ERRCL_L3_EDU_BL | CMD_ERRCL_WDU |
1200 	    CMD_ERRCL_EDU_ST | CMD_ERRCL_EDU_BL | CMD_ERRCL_CPU |
1201 	    CMD_ERRCL_UCU | CMD_ERRCL_L3_WDU),
1202 	CMD_TRAIN(CMD_ERRCL_L3_CPU,	CMD_ERRCL_L3_EDU_ST |
1203 	    CMD_ERRCL_L3_EDU_BL | CMD_ERRCL_WDU | CMD_ERRCL_EDU_ST |
1204 	    CMD_ERRCL_EDU_BL | CMD_ERRCL_CPU | CMD_ERRCL_UCU |
1205 	    CMD_ERRCL_L3_WDU),
1206 
1207 	/* L3_CPU: L3_UCU+WDU+(zero or more of EDU, CPU, UCU)+L3_WDU */
1208 	CMD_TRAIN(CMD_ERRCL_L3_CPU,	CMD_ERRCL_L3_UCU | CMD_ERRCL_WDU
1209 	    | CMD_ERRCL_L3_WDU),
1210 	CMD_TRAIN(CMD_ERRCL_L3_CPU,	CMD_ERRCL_L3_UCU | CMD_ERRCL_WDU |
1211 	    CMD_ERRCL_EDU_ST | CMD_ERRCL_L3_WDU),
1212 	CMD_TRAIN(CMD_ERRCL_L3_CPU,	CMD_ERRCL_L3_UCU | CMD_ERRCL_WDU |
1213 	    CMD_ERRCL_EDU_BL | CMD_ERRCL_L3_WDU),
1214 	CMD_TRAIN(CMD_ERRCL_L3_CPU,	CMD_ERRCL_L3_UCU | CMD_ERRCL_WDU |
1215 	    CMD_ERRCL_EDU_ST |CMD_ERRCL_EDU_BL | CMD_ERRCL_L3_WDU),
1216 	CMD_TRAIN(CMD_ERRCL_L3_CPU,	CMD_ERRCL_L3_UCU | CMD_ERRCL_WDU |
1217 	    CMD_ERRCL_CPU | CMD_ERRCL_L3_WDU),
1218 	CMD_TRAIN(CMD_ERRCL_L3_CPU,	CMD_ERRCL_L3_UCU | CMD_ERRCL_WDU |
1219 	    CMD_ERRCL_UCU | CMD_ERRCL_L3_WDU),
1220 	CMD_TRAIN(CMD_ERRCL_L3_CPU,	CMD_ERRCL_L3_UCU | CMD_ERRCL_WDU |
1221 	    CMD_ERRCL_EDU_ST | CMD_ERRCL_CPU | CMD_ERRCL_L3_WDU),
1222 	CMD_TRAIN(CMD_ERRCL_L3_CPU,	CMD_ERRCL_L3_UCU | CMD_ERRCL_WDU |
1223 	    CMD_ERRCL_EDU_BL | CMD_ERRCL_CPU | CMD_ERRCL_L3_WDU),
1224 	CMD_TRAIN(CMD_ERRCL_L3_CPU,	CMD_ERRCL_L3_UCU | CMD_ERRCL_WDU |
1225 	    CMD_ERRCL_EDU_ST | CMD_ERRCL_EDU_BL | CMD_ERRCL_CPU |
1226 	    CMD_ERRCL_L3_WDU),
1227 	CMD_TRAIN(CMD_ERRCL_L3_CPU,	CMD_ERRCL_L3_UCU | CMD_ERRCL_WDU |
1228 	    CMD_ERRCL_EDU_ST | CMD_ERRCL_UCU | CMD_ERRCL_L3_WDU),
1229 	CMD_TRAIN(CMD_ERRCL_L3_CPU,	CMD_ERRCL_L3_UCU | CMD_ERRCL_WDU |
1230 	    CMD_ERRCL_EDU_BL | CMD_ERRCL_UCU | CMD_ERRCL_L3_WDU),
1231 	CMD_TRAIN(CMD_ERRCL_L3_CPU,	CMD_ERRCL_L3_UCU | CMD_ERRCL_WDU |
1232 	    CMD_ERRCL_EDU_ST | CMD_ERRCL_EDU_BL | CMD_ERRCL_UCU |
1233 	    CMD_ERRCL_L3_WDU),
1234 	CMD_TRAIN(CMD_ERRCL_L3_CPU,	CMD_ERRCL_L3_UCU | CMD_ERRCL_WDU |
1235 	    CMD_ERRCL_CPU | CMD_ERRCL_UCU | CMD_ERRCL_L3_WDU),
1236 	CMD_TRAIN(CMD_ERRCL_L3_CPU,	CMD_ERRCL_L3_UCU | CMD_ERRCL_WDU |
1237 	    CMD_ERRCL_EDU_ST | CMD_ERRCL_CPU | CMD_ERRCL_UCU |
1238 	    CMD_ERRCL_L3_WDU),
1239 	CMD_TRAIN(CMD_ERRCL_L3_CPU,	CMD_ERRCL_L3_UCU | CMD_ERRCL_WDU |
1240 	    CMD_ERRCL_EDU_BL | CMD_ERRCL_CPU | CMD_ERRCL_UCU |
1241 	    CMD_ERRCL_L3_WDU),
1242 	CMD_TRAIN(CMD_ERRCL_L3_CPU,	CMD_ERRCL_L3_UCU | CMD_ERRCL_WDU |
1243 	    CMD_ERRCL_EDU_ST | CMD_ERRCL_EDU_BL | CMD_ERRCL_CPU |
1244 	    CMD_ERRCL_UCU | CMD_ERRCL_L3_WDU),
1245 #else /* sun4u */
1246 	CMD_TRAIN(CMD_ERRCL_LDAC,	CMD_ERRCL_LDWC),
1247 	CMD_TRAIN(CMD_ERRCL_LDRC,	CMD_ERRCL_LDWC),
1248 	CMD_TRAIN(CMD_ERRCL_LDSC,	CMD_ERRCL_LDWC),
1249 	CMD_TRAIN(CMD_ERRCL_CBCE,	CMD_ERRCL_LDWC),
1250 	CMD_TRAIN(CMD_ERRCL_LDAU,	CMD_ERRCL_LDWU),
1251 	CMD_TRAIN(CMD_ERRCL_LDAU,	CMD_ERRCL_WBUE),
1252 	CMD_TRAIN(CMD_ERRCL_LDAU,	CMD_ERRCL_DCDP),
1253 	CMD_TRAIN(CMD_ERRCL_LDRU,	CMD_ERRCL_LDWU),
1254 	CMD_TRAIN(CMD_ERRCL_LDRU,	CMD_ERRCL_WBUE),
1255 	CMD_TRAIN(CMD_ERRCL_LDRU,	CMD_ERRCL_DCDP),
1256 	CMD_TRAIN(CMD_ERRCL_LDSU,	CMD_ERRCL_LDWU),
1257 	CMD_TRAIN(CMD_ERRCL_LDSU,	CMD_ERRCL_WBUE),
1258 	CMD_TRAIN(CMD_ERRCL_LDSU,	CMD_ERRCL_DCDP),
1259 	CMD_TRAIN(CMD_ERRCL_SBDLC,	CMD_ERRCL_SBDPC),
1260 	CMD_TRAIN(CMD_ERRCL_TCCP,	CMD_ERRCL_TCCD),
1261 	CMD_TRAIN(CMD_ERRCL_TCCD,	CMD_ERRCL_TCCD),
1262 	CMD_TRAIN(CMD_ERRCL_DBU,	CMD_ERRCL_DCDP),
1263 	CMD_TRAIN(CMD_ERRCL_DBU,	CMD_ERRCL_ICDP),
1264 	CMD_TRAIN(CMD_ERRCL_FBU,	CMD_ERRCL_DCDP),
1265 	CMD_TRAIN(CMD_ERRCL_FBU,	CMD_ERRCL_ICDP),
1266 	CMD_TRAIN(CMD_ERRCL_DAU,	CMD_ERRCL_DCDP),
1267 	CMD_TRAIN(CMD_ERRCL_DAU,	CMD_ERRCL_ICDP),
1268 	/*
1269 	 * sun4v also has the following trains, but the train
1270 	 * algorithm does an exhaustive search and compare
1271 	 * all pairs in the train mask, so we don't need
1272 	 * to define these trains
1273 	 *		dl2nd->ldwu (wbue), dcdp
1274 	 *		il2nd->ldwu (wbue), icdp
1275 	 *		dxl2u->ldwu (wbue), dcdp
1276 	 *		ixl2u->ldwu (wbue), icdp
1277 	 */
1278 	CMD_TRAIN(CMD_ERRCL_DL2ND,	CMD_ERRCL_DCDP),
1279 	CMD_TRAIN(CMD_ERRCL_DL2ND,	CMD_ERRCL_LDWU),
1280 	CMD_TRAIN(CMD_ERRCL_DL2ND,	CMD_ERRCL_WBUE),
1281 	CMD_TRAIN(CMD_ERRCL_IL2ND,	CMD_ERRCL_ICDP),
1282 	CMD_TRAIN(CMD_ERRCL_IL2ND,	CMD_ERRCL_LDWU),
1283 	CMD_TRAIN(CMD_ERRCL_IL2ND,	CMD_ERRCL_WBUE),
1284 	CMD_TRAIN(CMD_ERRCL_L2ND,	CMD_ERRCL_LDWU),
1285 	CMD_TRAIN(CMD_ERRCL_L2ND,	CMD_ERRCL_WBUE),
1286 	CMD_TRAIN(CMD_ERRCL_DL2U,	CMD_ERRCL_DCDP),
1287 	CMD_TRAIN(CMD_ERRCL_DL2U,	CMD_ERRCL_LDWU),
1288 	CMD_TRAIN(CMD_ERRCL_DL2U,	CMD_ERRCL_WBUE),
1289 	CMD_TRAIN(CMD_ERRCL_IL2U,	CMD_ERRCL_ICDP),
1290 	CMD_TRAIN(CMD_ERRCL_IL2U,	CMD_ERRCL_LDWU),
1291 	CMD_TRAIN(CMD_ERRCL_IL2U,	CMD_ERRCL_WBUE),
1292 #endif /* sun4u */
1293 	CMD_TRAIN(0, 0)
1294 };
1295 
1296 cmd_errcl_t
cmd_xxcu_train_match(cmd_errcl_t mask)1297 cmd_xxcu_train_match(cmd_errcl_t mask)
1298 {
1299 	int i;
1300 
1301 	for (i = 0; cmd_xxcu_trains[i].tr_mask != 0; i++) {
1302 		if (cmd_xxcu_trains[i].tr_mask == mask)
1303 			return (cmd_xxcu_trains[i].tr_cause);
1304 	}
1305 
1306 	return (0);
1307 }
1308 
1309 cmd_xxcu_trw_t *
cmd_trw_alloc(uint64_t ena,uint64_t afar)1310 cmd_trw_alloc(uint64_t ena, uint64_t afar)
1311 {
1312 	int i;
1313 
1314 	for (i = 0; i < cmd.cmd_xxcu_ntrw; i++) {
1315 		cmd_xxcu_trw_t *trw = &cmd.cmd_xxcu_trw[i];
1316 		if (trw->trw_ena == 0) {
1317 			trw->trw_ena = ena;
1318 			trw->trw_afar = afar;
1319 			return (trw);
1320 		}
1321 	}
1322 
1323 	return (NULL);
1324 }
1325 
1326 void
cmd_trw_write(fmd_hdl_t * hdl)1327 cmd_trw_write(fmd_hdl_t *hdl)
1328 {
1329 	fmd_buf_write(hdl, NULL, "waiters", cmd.cmd_xxcu_trw,
1330 	    cmd.cmd_xxcu_ntrw * sizeof (cmd_xxcu_trw_t));
1331 }
1332 
1333 /*ARGSUSED*/
1334 void
cmd_trw_ref(fmd_hdl_t * hdl,cmd_xxcu_trw_t * trw,cmd_errcl_t clcode)1335 cmd_trw_ref(fmd_hdl_t *hdl, cmd_xxcu_trw_t *trw, cmd_errcl_t clcode)
1336 {
1337 	trw->trw_ref++;
1338 	trw->trw_mask |= clcode;
1339 	cmd_trw_write(hdl);
1340 }
1341 
1342 void
cmd_trw_deref(fmd_hdl_t * hdl,cmd_xxcu_trw_t * trw)1343 cmd_trw_deref(fmd_hdl_t *hdl, cmd_xxcu_trw_t *trw)
1344 {
1345 	if (trw->trw_ref == 0)
1346 		fmd_hdl_abort(hdl, "attempt to deref trw with zero ref\n");
1347 
1348 	if (--trw->trw_ref == 0)
1349 		bzero(trw, sizeof (cmd_xxcu_trw_t));
1350 
1351 	cmd_trw_write(hdl);
1352 }
1353 
1354 void
cmd_trw_restore(fmd_hdl_t * hdl)1355 cmd_trw_restore(fmd_hdl_t *hdl)
1356 {
1357 	size_t sz = fmd_buf_size(hdl, NULL, "waiters");
1358 	if (sz == cmd.cmd_xxcu_ntrw * sizeof (cmd_xxcu_trw_t)) {
1359 		/*
1360 		 * Previous size == current size.  In absence of
1361 		 * versioning, assume that the structure and # of elements
1362 		 * have not changed.
1363 		 */
1364 		fmd_buf_read(hdl, NULL, "waiters", cmd.cmd_xxcu_trw,
1365 		    cmd.cmd_xxcu_ntrw * sizeof (cmd_xxcu_trw_t));
1366 	} else {
1367 		/*
1368 		 * Previous size != current size.  Something has changed;
1369 		 * hence we cannot rely on the contents of this buffer.
1370 		 * Delete the buffer and start fresh.
1371 		 */
1372 		fmd_buf_destroy(hdl, NULL, "waiters");
1373 		fmd_buf_write(hdl, NULL, "waiters", cmd.cmd_xxcu_trw,
1374 		    cmd.cmd_xxcu_ntrw * sizeof (cmd_xxcu_trw_t));
1375 	}
1376 }
1377 
1378 char *
cmd_cpu_serdnm_create(fmd_hdl_t * hdl,cmd_cpu_t * cpu,const char * serdbase)1379 cmd_cpu_serdnm_create(fmd_hdl_t *hdl, cmd_cpu_t *cpu, const char *serdbase)
1380 {
1381 	char *nm;
1382 	const char *fmt;
1383 	size_t sz;
1384 	if (cpu->cpu_level == CMD_CPU_LEVEL_THREAD) {
1385 		fmt = "cpu_%d_%s_serd";
1386 		sz = snprintf(NULL, 0, fmt, cpu->cpu_cpuid, serdbase) + 1;
1387 		nm = fmd_hdl_alloc(hdl, sz, FMD_SLEEP);
1388 		(void) snprintf(nm, sz, fmt, cpu->cpu_cpuid, serdbase);
1389 	} else {
1390 		fmt = "cpu_%d_%d_%s_serd";
1391 		sz = snprintf(NULL, 0, fmt, cpu->cpu_cpuid, cpu->cpu_level,
1392 		    serdbase) + 1;
1393 		nm = fmd_hdl_alloc(hdl, sz, FMD_SLEEP);
1394 		(void) snprintf(nm, sz, fmt, cpu->cpu_cpuid, cpu->cpu_level,
1395 		    serdbase);
1396 	}
1397 
1398 	return (nm);
1399 }
1400 
1401 /*
1402  * cmd_cpu_create_faultlist is a combination of the former cmd_cpu_create_fault
1403  * and fmd_case_add_suspect.  If a 'cpu' structure represents a set of threads
1404  * (level > CMD_CPU_LEVEL_THREAD), then we must add multiple faults to
1405  * this case, under loop control.  Use call to cmd_cpu_create_faultlist to
1406  * replace the sequence
1407  *
1408  *	flt = cmd_cpu_create_fault(...);
1409  *	fmd_case_add_suspect(hdl, cc->cp, flt);
1410  */
1411 
1412 void
cmd_cpu_create_faultlist(fmd_hdl_t * hdl,fmd_case_t * casep,cmd_cpu_t * cpu,const char * type,nvlist_t * rsrc,uint_t cert)1413 cmd_cpu_create_faultlist(fmd_hdl_t *hdl, fmd_case_t *casep, cmd_cpu_t *cpu,
1414     const char *type, nvlist_t *rsrc, uint_t cert)
1415 {
1416 	char fltnm[64];
1417 	uint32_t cpuinit, cpufinal, cpustep, i;
1418 	nvlist_t *flt;
1419 #ifdef sun4v
1420 	char *loc;
1421 	nvlist_t *mb_rsrc;
1422 #endif
1423 
1424 	(void) snprintf(fltnm, sizeof (fltnm), "fault.cpu.%s.%s",
1425 	    cmd_cpu_type2name(hdl, cpu->cpu_type), type);
1426 
1427 	cpu->cpu_faulting = FMD_B_TRUE;
1428 	cpu_buf_write(hdl, cpu);
1429 #ifdef sun4v
1430 
1431 	loc = cmd_getfru_loc(hdl, cpu->cpu_asru_nvl);
1432 
1433 	/*
1434 	 * Add motherboard fault to t5440 lfu suspect.list.
1435 	 */
1436 	if ((strstr(loc, CPUBOARD) != NULL) && (strstr(fltnm, "lfu") != NULL)) {
1437 		/* get mb fmri from libtopo */
1438 		mb_rsrc = init_mb(hdl);
1439 		if (mb_rsrc != NULL) {
1440 			fmd_hdl_debug(hdl, "cmd_cpu: create MB fault\n");
1441 			cert = BK_LFUFAULT_CERT;
1442 			flt = cmd_boardfru_create_fault(hdl, mb_rsrc, fltnm,
1443 			    cert, "MB");
1444 			fmd_case_add_suspect(hdl, casep, flt);
1445 			nvlist_free(mb_rsrc);
1446 		}
1447 	}
1448 #endif
1449 
1450 	if (cpu->cpu_level > CMD_CPU_LEVEL_THREAD) {
1451 		core2cpus(cpu->cpu_cpuid, cpu->cpu_type, cpu->cpu_level,
1452 		    &cpuinit, &cpufinal, &cpustep);
1453 		for (i = cpuinit; i <= cpufinal; i += cpustep) {
1454 			cmd_cpu_t *cpui = cpu_lookup_by_cpuid(i,
1455 			    CMD_CPU_LEVEL_THREAD);
1456 			if (cpui == NULL) {
1457 				nvlist_t *asru;
1458 				if (nvlist_dup(cpu->cpu_asru_nvl,
1459 				    &asru, 0) != 0) {
1460 					fmd_hdl_abort(hdl, "unable to alloc"
1461 					    "ASRU for thread in core\n");
1462 				}
1463 				(void) nvlist_remove_all(asru,
1464 				    FM_FMRI_CPU_ID);
1465 				if (nvlist_add_uint32(asru,
1466 				    FM_FMRI_CPU_ID, i) != 0) {
1467 					fmd_hdl_abort(hdl,
1468 					    "unable to create thread struct\n");
1469 				}
1470 				cpui = cpu_create(hdl, asru, i,
1471 				    CMD_CPU_LEVEL_THREAD, cpu->cpu_type);
1472 				nvlist_free(asru);
1473 			}
1474 			if (!fmd_nvl_fmri_present(hdl, cpui->cpu_asru_nvl))
1475 				continue;
1476 			cpui->cpu_faulting = FMD_B_TRUE;
1477 			cpu_buf_write(hdl, cpui);
1478 			flt = cmd_nvl_create_fault(hdl, fltnm, cert,
1479 			    cpui->cpu_asru_nvl, cpu->cpu_fru_nvl, rsrc);
1480 #ifdef sun4v
1481 			flt = cmd_fault_add_location(hdl, flt, loc);
1482 #endif /* sun4v */
1483 			fmd_case_add_suspect(hdl, casep, flt);
1484 		}
1485 	} else {
1486 		flt = cmd_nvl_create_fault(hdl, fltnm, cert,
1487 		    cpu->cpu_asru_nvl, cpu->cpu_fru_nvl, rsrc);
1488 #ifdef sun4v
1489 		flt = cmd_fault_add_location(hdl, flt, loc);
1490 
1491 #endif /* sun4v */
1492 		fmd_case_add_suspect(hdl, casep, flt);
1493 	}
1494 #ifdef sun4v
1495 	if (loc != NULL)
1496 		fmd_hdl_strfree(hdl, loc);
1497 #endif
1498 }
1499 
1500 static void
cmd_cpu_free(fmd_hdl_t * hdl,cmd_cpu_t * cpu,int destroy)1501 cmd_cpu_free(fmd_hdl_t *hdl, cmd_cpu_t *cpu, int destroy)
1502 {
1503 	int i;
1504 #ifdef sun4u
1505 	cmd_Lxcache_t *Lxcache;
1506 #endif
1507 
1508 	for (i = 0; i < sizeof (cmd_cpu_cases_t) / sizeof (cmd_case_t); i++) {
1509 		cmd_case_t *cc = &(((cmd_case_t *)&cpu->cpu_cases)[i]);
1510 
1511 		if (cc->cc_cp != NULL) {
1512 			cmd_case_fini(hdl, cc->cc_cp, destroy);
1513 			if (cc->cc_serdnm != NULL) {
1514 				if (fmd_serd_exists(hdl, cc->cc_serdnm) &&
1515 				    destroy)
1516 					fmd_serd_destroy(hdl, cc->cc_serdnm);
1517 				fmd_hdl_strfree(hdl, cc->cc_serdnm);
1518 			}
1519 		}
1520 	}
1521 
1522 #ifdef sun4u
1523 	/*
1524 	 * free Lxcache also.
1525 	 */
1526 
1527 	for (Lxcache = cmd_list_next(&cpu->cpu_Lxcaches); Lxcache != NULL;
1528 	    Lxcache = cmd_list_next(&cpu->cpu_Lxcaches)) {
1529 		(void) cmd_Lxcache_free(hdl, cpu, Lxcache, destroy);
1530 	}
1531 	cpu_uec_free(hdl, &cpu->cpu_uec, destroy);
1532 	cpu_uec_free(hdl, &cpu->cpu_olduec, destroy);
1533 #endif /* sun4u */
1534 
1535 	cmd_fmri_fini(hdl, &cpu->cpu_asru, destroy);
1536 	cmd_fmri_fini(hdl, &cpu->cpu_fru, destroy);
1537 
1538 	cmd_list_delete(&cmd.cmd_cpus, cpu);
1539 
1540 	if (destroy)
1541 		fmd_buf_destroy(hdl, NULL, cpu->cpu_bufname);
1542 	fmd_hdl_free(hdl, cpu, sizeof (cmd_cpu_t));
1543 }
1544 
1545 void
cmd_cpu_destroy(fmd_hdl_t * hdl,cmd_cpu_t * cpu)1546 cmd_cpu_destroy(fmd_hdl_t *hdl, cmd_cpu_t *cpu)
1547 {
1548 	cmd_cpu_free(hdl, cpu, FMD_B_TRUE);
1549 }
1550 
1551 static cmd_cpu_t *
cpu_lookup_by_cpuid(uint32_t cpuid,uint8_t level)1552 cpu_lookup_by_cpuid(uint32_t cpuid, uint8_t level)
1553 {
1554 	cmd_cpu_t *cpu;
1555 
1556 	for (cpu = cmd_list_next(&cmd.cmd_cpus); cpu != NULL;
1557 	    cpu = cmd_list_next(cpu)) {
1558 		if ((cpu->cpu_cpuid == cpuid) &&
1559 		    (cpu->cpu_level == level))
1560 			return (cpu);
1561 	}
1562 
1563 	return (NULL);
1564 }
1565 
1566 static nvlist_t *
cpu_getfru(fmd_hdl_t * hdl,cmd_cpu_t * cp)1567 cpu_getfru(fmd_hdl_t *hdl, cmd_cpu_t *cp)
1568 {
1569 	char *frustr, *partstr, *serialstr;
1570 	nvlist_t *nvlp;
1571 
1572 	if ((frustr = cmd_cpu_getfrustr(hdl, cp)) == NULL) {
1573 		return (NULL);
1574 	}
1575 	partstr = cmd_cpu_getpartstr(hdl, cp);
1576 	serialstr = cmd_cpu_getserialstr(hdl, cp);
1577 	nvlp = cmd_cpu_mkfru(hdl, frustr, serialstr, partstr);
1578 	fmd_hdl_strfree(hdl, frustr);
1579 	fmd_hdl_strfree(hdl, partstr);
1580 	fmd_hdl_strfree(hdl, serialstr);
1581 
1582 	return (nvlp);
1583 }
1584 
1585 static void
cpu_buf_write(fmd_hdl_t * hdl,cmd_cpu_t * cpu)1586 cpu_buf_write(fmd_hdl_t *hdl, cmd_cpu_t *cpu)
1587 {
1588 	if (fmd_buf_size(hdl, NULL, cpu->cpu_bufname) !=
1589 	    sizeof (cmd_cpu_pers_t))
1590 		fmd_buf_destroy(hdl, NULL, cpu->cpu_bufname);
1591 
1592 	fmd_buf_write(hdl, NULL, cpu->cpu_bufname, &cpu->cpu_pers,
1593 	    sizeof (cmd_cpu_pers_t));
1594 }
1595 
1596 static void
cpu_buf_create(fmd_hdl_t * hdl,cmd_cpu_t * cpu)1597 cpu_buf_create(fmd_hdl_t *hdl, cmd_cpu_t *cpu)
1598 {
1599 	size_t sz;
1600 
1601 	/*
1602 	 * We need to be tolerant of leaked CPU buffers, as their effects can
1603 	 * be severe.  Consider the following scenario: we create a version 0
1604 	 * cmd_cpu_t in response to some error, commit it to a persistent
1605 	 * buffer, and then leak it.  We then upgrade, and restart the DE using
1606 	 * version 1 cmd_cpu_t's.  Another error comes along, for the same CPU
1607 	 * whose struct was leaked.  Not knowing about the leaked buffer, we
1608 	 * create a new cmd_cpu_t for that CPU, and create a buffer for it.  As
1609 	 * the v1 cmd_cpu_t is smaller than the v0 cmd_cpu_t, fmd will use the
1610 	 * pre-existing (leaked) buffer.  We'll therefore have an x-byte, v1
1611 	 * cmd_cpu_t in a y-byte buffer, where y > x.  Upon the next DE restart,
1612 	 * we'll attempt to restore the cmd_cpu_t, but will do version
1613 	 * validation using the size of the buffer (y).  This won't match what
1614 	 * we're expecting (x), and the DE will abort.
1615 	 *
1616 	 * To protect against such a scenario, we're going to check for and
1617 	 * remove the pre-existing cmd_cpu_t for this CPU, if one exists.  While
1618 	 * this won't fix the leak, it'll allow us to continue functioning
1619 	 * properly in spite of it.
1620 	 */
1621 	if ((sz = fmd_buf_size(hdl, NULL, cpu->cpu_bufname)) != 0 &&
1622 	    sz != sizeof (cmd_cpu_pers_t)) {
1623 		fmd_hdl_debug(hdl, "removing unexpected pre-existing cpu "
1624 		    "buffer %s (size %u bytes)\n", cpu->cpu_bufname, sz);
1625 		fmd_buf_destroy(hdl, NULL, cpu->cpu_bufname);
1626 	}
1627 
1628 	cpu_buf_write(hdl, cpu);
1629 }
1630 
1631 static cmd_cpu_t *
cpu_create(fmd_hdl_t * hdl,nvlist_t * asru,uint32_t cpuid,uint8_t level,cmd_cpu_type_t type)1632 cpu_create(fmd_hdl_t *hdl, nvlist_t *asru, uint32_t cpuid, uint8_t level,
1633     cmd_cpu_type_t type)
1634 {
1635 	cmd_cpu_t *cpu;
1636 	nvlist_t *fru;
1637 
1638 	/*
1639 	 * No CPU state matches the CPU described in the ereport.  Create a new
1640 	 * one, add it to the list, and pass it back.
1641 	 */
1642 	fmd_hdl_debug(hdl, "cpu_lookup: creating new cpuid %u\n", cpuid);
1643 	CMD_STAT_BUMP(cpu_creat);
1644 
1645 	cpu = fmd_hdl_zalloc(hdl, sizeof (cmd_cpu_t), FMD_SLEEP);
1646 	cpu->cpu_nodetype = CMD_NT_CPU;
1647 	cpu->cpu_cpuid = cpuid;
1648 	cpu->cpu_level = level;
1649 	cpu->cpu_type = type;
1650 	cpu->cpu_version = CMD_CPU_VERSION;
1651 
1652 	if (cpu->cpu_level == CMD_CPU_LEVEL_THREAD) {
1653 		cmd_bufname(cpu->cpu_bufname, sizeof (cpu->cpu_bufname),
1654 		    "cpu_%d", cpu->cpu_cpuid);
1655 	} else {
1656 		cmd_bufname(cpu->cpu_bufname, sizeof (cpu->cpu_bufname),
1657 		    "cpu_%d_%d", cpu->cpu_cpuid, cpu->cpu_level);
1658 	}
1659 
1660 #ifdef sun4u
1661 	cpu_uec_create(hdl, cpu, &cpu->cpu_uec, "cpu_uec_%d", cpu->cpu_cpuid);
1662 	cpu_uec_create(hdl, cpu, &cpu->cpu_olduec, "cpu_olduec_%d",
1663 	    cpu->cpu_cpuid);
1664 #endif /* sun4u */
1665 
1666 	if (cpu->cpu_level == CMD_CPU_LEVEL_THREAD) {
1667 		cmd_fmri_init(hdl, &cpu->cpu_asru, asru, "cpu_asru_%d",
1668 		    cpu->cpu_cpuid);
1669 	} else {
1670 		cmd_fmri_init(hdl, &cpu->cpu_asru, asru, "cpu_asru_%d_%d",
1671 		    cpu->cpu_cpuid, cpu->cpu_level);
1672 	}
1673 
1674 	if ((fru = cpu_getfru(hdl, cpu)) != NULL) {
1675 		if (cpu->cpu_level == CMD_CPU_LEVEL_THREAD) {
1676 			cmd_fmri_init(hdl, &cpu->cpu_fru, fru, "cpu_fru_%d",
1677 			    cpu->cpu_cpuid);
1678 		} else {
1679 			cmd_fmri_init(hdl, &cpu->cpu_fru, fru, "cpu_fru_%d_%d",
1680 			    cpu->cpu_cpuid, cpu->cpu_level);
1681 		}
1682 		nvlist_free(fru);
1683 	} else {
1684 		if (cpu->cpu_level == CMD_CPU_LEVEL_THREAD) {
1685 			cmd_fmri_init(hdl, &cpu->cpu_fru, asru, "cpu_fru_%d",
1686 			    cpu->cpu_cpuid);
1687 		} else {
1688 			cmd_fmri_init(hdl, &cpu->cpu_fru, asru, "cpu_fru_%d_%d",
1689 			    cpu->cpu_cpuid, cpu->cpu_level);
1690 		}
1691 	}
1692 
1693 	cpu_buf_create(hdl, cpu);
1694 
1695 	cmd_list_append(&cmd.cmd_cpus, cpu);
1696 
1697 	return (cpu);
1698 }
1699 
1700 /*
1701  * As its name implies, 'cpu_all_threads_invalid' determines if all cpu
1702  * threads (level 0) contained within the cpu structure are invalid.
1703  * This is done by checking all the (level 0) threads which may be
1704  * contained within this chip, core, or thread; if all are invalid, return
1705  * FMD_B_TRUE; if any are valid, return FMD_B_FALSE.
1706  */
1707 
1708 int
cpu_all_threads_invalid(fmd_hdl_t * hdl,cmd_cpu_t * cpu)1709 cpu_all_threads_invalid(fmd_hdl_t *hdl, cmd_cpu_t *cpu)
1710 {
1711 	nvlist_t *asru;
1712 	uint32_t cpuinit, cpufinal, cpustep, i;
1713 
1714 	core2cpus(cpu->cpu_cpuid, cpu->cpu_type, cpu->cpu_level,
1715 	    &cpuinit, &cpufinal, &cpustep);
1716 
1717 	if (cpuinit == cpufinal) {
1718 		if (fmd_nvl_fmri_present(hdl, cpu->cpu_asru_nvl) &&
1719 		    !fmd_nvl_fmri_unusable(hdl, cpu->cpu_asru_nvl))
1720 			return (FMD_B_FALSE);
1721 		else return (FMD_B_TRUE);
1722 	} else {
1723 
1724 		if (nvlist_dup(cpu->cpu_asru_nvl, &asru, 0) != 0)
1725 			fmd_hdl_abort(hdl, "cannot copy asru\n");
1726 		for (i = cpuinit; i <= cpufinal; i += cpustep) {
1727 			(void) nvlist_remove_all(asru, FM_FMRI_CPU_ID);
1728 			if (nvlist_add_uint32(asru, FM_FMRI_CPU_ID, i) != 0) {
1729 				fmd_hdl_abort(hdl, "cpu_all_threads_invalid: ",
1730 				    "cannot add thread %d to asru\n", i);
1731 			}
1732 			if (fmd_nvl_fmri_present(hdl, asru) &&
1733 			    !fmd_nvl_fmri_unusable(hdl, asru)) {
1734 				nvlist_free(asru);
1735 				return (FMD_B_FALSE);
1736 			}
1737 		}
1738 	}
1739 	nvlist_free(asru);
1740 	return (FMD_B_TRUE);
1741 }
1742 
1743 /*
1744  * Locate the state structure for this CPU, creating a new one if one doesn't
1745  * already exist.  Before passing it back, we also need to validate it against
1746  * the current state of the world, checking to ensure that the CPU described by
1747  * the ereport, the CPU indicated in the cmd_cpu_t, and the CPU currently
1748  * residing at the indicated cpuid are the same.  We do this by comparing the
1749  * serial IDs from the three entities.
1750  */
1751 cmd_cpu_t *
cmd_cpu_lookup(fmd_hdl_t * hdl,nvlist_t * asru,const char * class,uint8_t level)1752 cmd_cpu_lookup(fmd_hdl_t *hdl, nvlist_t *asru, const char *class,
1753     uint8_t level)
1754 {
1755 	cmd_cpu_t *cpu;
1756 	uint8_t vers;
1757 	const char *scheme, *cpuname;
1758 	uint32_t cpuid;
1759 	cmd_cpu_type_t ct;
1760 
1761 	if (fmd_nvl_fmri_expand(hdl, asru) < 0) {
1762 		CMD_STAT_BUMP(bad_cpu_asru);
1763 		return (NULL);
1764 	}
1765 
1766 	if (nvlist_lookup_pairs(asru, 0,
1767 	    FM_VERSION, DATA_TYPE_UINT8, &vers,
1768 	    FM_FMRI_SCHEME, DATA_TYPE_STRING, &scheme,
1769 	    FM_FMRI_CPU_ID, DATA_TYPE_UINT32, &cpuid,
1770 	    NULL) != 0 || (vers != CPU_SCHEME_VERSION0 &&
1771 	    vers != CPU_SCHEME_VERSION1) ||
1772 	    strcmp(scheme, FM_FMRI_SCHEME_CPU) != 0) {
1773 		CMD_STAT_BUMP(bad_cpu_asru);
1774 		return (NULL);
1775 	}
1776 
1777 	/*
1778 	 * 'cpuid' at this point refers to a thread, because it
1779 	 * was extracted from a detector FMRI
1780 	 */
1781 
1782 	cpuname = class + sizeof ("ereport.cpu");
1783 	ct = cpu_nname2type(hdl, cpuname,
1784 	    (size_t)(strchr(cpuname, '.') - cpuname));
1785 
1786 	cpu = cpu_lookup_by_cpuid(cmd_cpu2core(cpuid, ct, level), level);
1787 
1788 	if (cpu != NULL &&
1789 	    cpu_all_threads_invalid(hdl, cpu) == FMD_B_TRUE) {
1790 		fmd_hdl_debug(hdl, "cpu_lookup: discarding old state\n");
1791 		cmd_cpu_destroy(hdl, cpu);
1792 		cpu = NULL;
1793 	}
1794 
1795 	/*
1796 	 * Check to see if the CPU described by the ereport has been removed
1797 	 * from the system.  If it has, return to the caller without a CPU.
1798 	 */
1799 	if (!fmd_nvl_fmri_present(hdl, asru) ||
1800 	    fmd_nvl_fmri_unusable(hdl, asru)) {
1801 		fmd_hdl_debug(hdl, "cpu_lookup: discarding old ereport\n");
1802 		return (NULL);
1803 	}
1804 
1805 	if (cpu == NULL) {
1806 		cpu = cpu_create(hdl, asru,
1807 		    cmd_cpu2core(cpuid, ct, level), level, ct);
1808 	}
1809 
1810 	return (cpu);
1811 }
1812 
1813 cmd_cpu_t *
cmd_cpu_lookup_from_detector(fmd_hdl_t * hdl,nvlist_t * nvl,const char * class,uint8_t level)1814 cmd_cpu_lookup_from_detector(fmd_hdl_t *hdl, nvlist_t *nvl, const char *class,
1815     uint8_t level)
1816 {
1817 	nvlist_t *det;
1818 
1819 	(void) nvlist_lookup_nvlist(nvl, FM_EREPORT_DETECTOR, &det);
1820 
1821 	return (cmd_cpu_lookup(hdl, det, class, level));
1822 }
1823 
1824 static cmd_cpu_t *
cpu_v0tov3(fmd_hdl_t * hdl,cmd_cpu_0_t * old,size_t oldsz)1825 cpu_v0tov3(fmd_hdl_t *hdl, cmd_cpu_0_t *old, size_t oldsz)
1826 {
1827 	cmd_cpu_t *new;
1828 
1829 	if (oldsz != sizeof (cmd_cpu_0_t)) {
1830 		fmd_hdl_abort(hdl, "size of state doesn't match size of "
1831 		    "version 0 state (%u bytes).\n", sizeof (cmd_cpu_0_t));
1832 	}
1833 
1834 	new = fmd_hdl_zalloc(hdl, sizeof (cmd_cpu_t), FMD_SLEEP);
1835 	new->cpu_header = old->cpu0_header;
1836 	new->cpu_version = CMD_CPU_VERSION;
1837 	new->cpu_cpuid = old->cpu0_cpuid;
1838 	new->cpu_type = old->cpu0_type;
1839 	new->cpu_faulting = old->cpu0_faulting;
1840 	new->cpu_level = CMD_CPU_LEVEL_THREAD;
1841 	new->cpu_asru = old->cpu0_asru;
1842 	new->cpu_fru = old->cpu0_fru;
1843 	new->cpu_uec = old->cpu0_uec;
1844 	new->cpu_olduec = old->cpu0_olduec;
1845 
1846 	fmd_hdl_free(hdl, old, oldsz);
1847 	return (new);
1848 }
1849 
1850 static cmd_cpu_t *
cpu_v1tov3(fmd_hdl_t * hdl,cmd_cpu_1_t * old,size_t oldsz)1851 cpu_v1tov3(fmd_hdl_t *hdl, cmd_cpu_1_t *old, size_t oldsz)
1852 {
1853 	cmd_cpu_t *new;
1854 
1855 	if (oldsz != sizeof (cmd_cpu_1_t)) {
1856 		fmd_hdl_abort(hdl, "size of state doesn't match size of "
1857 		    "version 1 state (%u bytes).\n", sizeof (cmd_cpu_1_t));
1858 	}
1859 
1860 	new = fmd_hdl_zalloc(hdl, sizeof (cmd_cpu_t), FMD_SLEEP);
1861 	new->cpu_header = old->cpu1_header;
1862 	new->cpu_version = CMD_CPU_VERSION;
1863 	new->cpu_cpuid = old->cpu1_cpuid;
1864 	new->cpu_type = old->cpu1_type;
1865 	new->cpu_faulting = old->cpu1_faulting;
1866 	new->cpu_level = CMD_CPU_LEVEL_THREAD;
1867 	new->cpu_asru = old->cpu1_asru;
1868 	new->cpu_fru = old->cpu1_fru;
1869 	new->cpu_uec = old->cpu1_uec;
1870 	new->cpu_olduec = old->cpu1_olduec;
1871 
1872 	fmd_hdl_free(hdl, old, oldsz);
1873 	return (new);
1874 }
1875 
1876 static cmd_cpu_t *
cpu_v2tov3(fmd_hdl_t * hdl,cmd_cpu_2_t * old,size_t oldsz)1877 cpu_v2tov3(fmd_hdl_t *hdl, cmd_cpu_2_t *old, size_t oldsz)
1878 {
1879 	cmd_cpu_t *new;
1880 
1881 	if (oldsz != sizeof (cmd_cpu_2_t)) {
1882 		fmd_hdl_abort(hdl, "size of state doesn't match size of "
1883 		    "version 2 state (%u bytes).\n", sizeof (cmd_cpu_2_t));
1884 	}
1885 
1886 	new = fmd_hdl_zalloc(hdl, sizeof (cmd_cpu_t), FMD_SLEEP);
1887 
1888 	new->cpu_header = old->cpu2_header;
1889 	new->cpu_cpuid = old->cpu2_cpuid;
1890 	new->cpu_type = old->cpu2_type;
1891 	new->cpu_faulting = old->cpu2_faulting;
1892 	new->cpu_asru = old->cpu2_asru;
1893 	new->cpu_fru = old->cpu2_fru;
1894 	new->cpu_uec = old->cpu2_uec;
1895 	new->cpu_olduec = old->cpu2_olduec;
1896 	new->cpu_version = CMD_CPU_VERSION;
1897 	new->cpu_level = CMD_CPU_LEVEL_THREAD;
1898 	fmd_hdl_free(hdl, old, oldsz);
1899 	return (new);
1900 }
1901 
1902 static cmd_cpu_t *
cpu_wrapv3(fmd_hdl_t * hdl,cmd_cpu_pers_t * pers,size_t psz)1903 cpu_wrapv3(fmd_hdl_t *hdl, cmd_cpu_pers_t *pers, size_t psz)
1904 {
1905 	cmd_cpu_t *cpu;
1906 
1907 	if (psz != sizeof (cmd_cpu_pers_t)) {
1908 		fmd_hdl_abort(hdl, "size of state doesn't match size of "
1909 		    "version 3 state (%u bytes).\n", sizeof (cmd_cpu_pers_t));
1910 	}
1911 
1912 	cpu = fmd_hdl_zalloc(hdl, sizeof (cmd_cpu_t), FMD_SLEEP);
1913 	bcopy(pers, cpu, sizeof (cmd_cpu_pers_t));
1914 	fmd_hdl_free(hdl, pers, psz);
1915 	return (cpu);
1916 }
1917 
1918 static void
cpu_case_restore(fmd_hdl_t * hdl,cmd_cpu_t * cpu,cmd_case_t * cc,fmd_case_t * cp,const char * serdbase)1919 cpu_case_restore(fmd_hdl_t *hdl, cmd_cpu_t *cpu, cmd_case_t *cc, fmd_case_t *cp,
1920     const char *serdbase)
1921 {
1922 	cmd_case_restore(hdl, cc, cp, cmd_cpu_serdnm_create(hdl, cpu,
1923 	    serdbase));
1924 }
1925 
1926 cmd_cpu_t *
cmd_restore_cpu_only(fmd_hdl_t * hdl,fmd_case_t * cp,char * cpu_hdr_bufname)1927 cmd_restore_cpu_only(fmd_hdl_t *hdl, fmd_case_t *cp, char *cpu_hdr_bufname)
1928 {
1929 	cmd_cpu_t *cpu;
1930 
1931 	for (cpu = cmd_list_next(&cmd.cmd_cpus); cpu != NULL;
1932 	    cpu = cmd_list_next(cpu)) {
1933 		if (strcmp(cpu->cpu_bufname, cpu_hdr_bufname) == 0)
1934 			break;
1935 	}
1936 
1937 	if (cpu == NULL) {
1938 		int migrated = 0;
1939 		size_t cpusz;
1940 
1941 		fmd_hdl_debug(hdl, "restoring cpu from %s\n", cpu_hdr_bufname);
1942 
1943 		if ((cpusz = fmd_buf_size(hdl, NULL, cpu_hdr_bufname)) == 0) {
1944 			if (fmd_case_solved(hdl, cp) ||
1945 			    fmd_case_closed(hdl, cp)) {
1946 				fmd_hdl_debug(hdl, "cpu buffer %s from case %s "
1947 				    "not found. Case is already solved or "
1948 				    "closed\n",
1949 				    cpu_hdr_bufname, fmd_case_uuid(hdl, cp));
1950 				return (NULL);
1951 			} else {
1952 				fmd_hdl_abort(hdl, "cpu referenced by case %s "
1953 				    "does not exist in saved state\n",
1954 				    fmd_case_uuid(hdl, cp));
1955 			}
1956 		} else if (cpusz > CMD_CPU_MAXSIZE || cpusz < CMD_CPU_MINSIZE) {
1957 			fmd_hdl_abort(hdl, "cpu buffer referenced by case %s "
1958 			    "is out of bounds (is %u bytes)\n",
1959 			    fmd_case_uuid(hdl, cp), cpusz);
1960 		}
1961 
1962 		if ((cpu = cmd_buf_read(hdl, NULL, cpu_hdr_bufname,
1963 		    cpusz)) == NULL) {
1964 			fmd_hdl_abort(hdl, "failed to read buf %s",
1965 			    cpu_hdr_bufname);
1966 		}
1967 
1968 		fmd_hdl_debug(hdl, "found %d in version field\n",
1969 		    cpu->cpu_version);
1970 
1971 		if (CMD_CPU_VERSIONED(cpu)) {
1972 			switch (cpu->cpu_version) {
1973 			case CMD_CPU_VERSION_1:
1974 				cpu = cpu_v1tov3(hdl, (cmd_cpu_1_t *)cpu,
1975 				    cpusz);
1976 				migrated = 1;
1977 				break;
1978 			case CMD_CPU_VERSION_2:
1979 				cpu = cpu_v2tov3(hdl, (cmd_cpu_2_t *)cpu,
1980 				    cpusz);
1981 				migrated = 1;
1982 				break;
1983 			case CMD_CPU_VERSION_3:
1984 				cpu = cpu_wrapv3(hdl, (cmd_cpu_pers_t *)cpu,
1985 				    cpusz);
1986 				break;
1987 			default:
1988 				fmd_hdl_abort(hdl, "unknown version (found %d) "
1989 				    "for cpu state referenced by case %s.\n",
1990 				    cpu->cpu_version, fmd_case_uuid(hdl, cp));
1991 				break;
1992 			}
1993 		} else {
1994 			cpu = cpu_v0tov3(hdl, (cmd_cpu_0_t *)cpu, cpusz);
1995 			migrated = 1;
1996 		}
1997 
1998 		if (migrated) {
1999 			CMD_STAT_BUMP(cpu_migrat);
2000 			cpu_buf_write(hdl, cpu);
2001 		}
2002 
2003 		cmd_fmri_restore(hdl, &cpu->cpu_asru);
2004 		cmd_fmri_restore(hdl, &cpu->cpu_fru);
2005 #ifdef sun4u
2006 		cpu_uec_restore(hdl, &cpu->cpu_uec);
2007 		cpu_uec_restore(hdl, &cpu->cpu_olduec);
2008 
2009 		if (cpu->cpu_uec.uec_cache != NULL)
2010 			cpu_uec_flush(hdl, cpu);
2011 #endif /* sun4u */
2012 		bzero(&cpu->cpu_xxu_retries, sizeof (cmd_list_t));
2013 
2014 		cmd_list_append(&cmd.cmd_cpus, cpu);
2015 	}
2016 	return (cpu);
2017 }
2018 
2019 void *
cmd_cpu_restore(fmd_hdl_t * hdl,fmd_case_t * cp,cmd_case_ptr_t * ptr)2020 cmd_cpu_restore(fmd_hdl_t *hdl, fmd_case_t *cp, cmd_case_ptr_t *ptr)
2021 {
2022 	cmd_cpu_t *cpu;
2023 
2024 	cpu = cmd_restore_cpu_only(hdl, cp, ptr->ptr_name);
2025 	if (cpu == NULL)
2026 		return (NULL);
2027 
2028 	switch (ptr->ptr_subtype) {
2029 	case CMD_PTR_CPU_ICACHE:
2030 		cpu_case_restore(hdl, cpu, &cpu->cpu_icache, cp, "icache");
2031 		break;
2032 	case CMD_PTR_CPU_DCACHE:
2033 		cpu_case_restore(hdl, cpu, &cpu->cpu_dcache, cp, "dcache");
2034 		break;
2035 	case CMD_PTR_CPU_PCACHE:
2036 		cpu_case_restore(hdl, cpu, &cpu->cpu_pcache, cp, "pcache");
2037 		break;
2038 	case CMD_PTR_CPU_ITLB:
2039 		cpu_case_restore(hdl, cpu, &cpu->cpu_itlb, cp, "itlb");
2040 		break;
2041 	case CMD_PTR_CPU_DTLB:
2042 		cpu_case_restore(hdl, cpu, &cpu->cpu_dtlb, cp, "dtlb");
2043 		break;
2044 	case CMD_PTR_CPU_L2DATA:
2045 		cpu_case_restore(hdl, cpu, &cpu->cpu_l2data, cp,
2046 		    cmd.cmd_l2data_serd.cs_name);
2047 		break;
2048 	case CMD_PTR_CPU_L2DATA_UERETRY:
2049 		/* No longer used -- discard */
2050 		break;
2051 	case CMD_PTR_CPU_L2TAG:
2052 		cpu_case_restore(hdl, cpu, &cpu->cpu_l2tag, cp, "l2tag");
2053 		break;
2054 	case CMD_PTR_CPU_L3DATA:
2055 		cpu_case_restore(hdl, cpu, &cpu->cpu_l3data, cp,
2056 		    cmd.cmd_l3data_serd.cs_name);
2057 		break;
2058 	case CMD_PTR_CPU_L3DATA_UERETRY:
2059 		/* No longer used -- discard */
2060 		break;
2061 	case CMD_PTR_CPU_L3TAG:
2062 		cpu_case_restore(hdl, cpu, &cpu->cpu_l3tag, cp, "l3tag");
2063 		break;
2064 	case CMD_PTR_CPU_FPU:
2065 		cpu_case_restore(hdl, cpu, &cpu->cpu_fpu, cp, "fpu");
2066 		break;
2067 	case CMD_PTR_CPU_XR_RETRY:
2068 		cmd_xr_restore(hdl, cpu, cp);
2069 		break;
2070 	case CMD_PTR_CPU_IREG:
2071 		cpu_case_restore(hdl, cpu, &cpu->cpu_ireg, cp, "ireg");
2072 		break;
2073 	case CMD_PTR_CPU_FREG:
2074 		cpu_case_restore(hdl, cpu, &cpu->cpu_freg, cp, "freg");
2075 		break;
2076 	case CMD_PTR_CPU_MAU:
2077 		cpu_case_restore(hdl, cpu, &cpu->cpu_mau, cp, "mau");
2078 		break;
2079 	case CMD_PTR_CPU_L2CTL:
2080 		cpu_case_restore(hdl, cpu, &cpu->cpu_l2ctl, cp, "l2ctl");
2081 		break;
2082 	case CMD_PTR_CPU_MISC_REGS:
2083 		cpu_case_restore(hdl, cpu, &cpu->cpu_misc_regs, cp,
2084 		    "misc_regs");
2085 		break;
2086 	case CMD_PTR_CPU_LFU:
2087 		cpu_case_restore(hdl, cpu, &cpu->cpu_lfu, cp, "lfu");
2088 		break;
2089 #ifdef sun4u
2090 	case CMD_PTR_CPU_INV_SFSR:
2091 		cpu_case_restore(hdl, cpu, &cpu->cpu_opl_invsfsr, cp,
2092 		    "opl_invsfsr");
2093 		break;
2094 	case CMD_PTR_CPU_UE_DET_CPU:
2095 		cpu_case_restore(hdl, cpu, &cpu->cpu_oplue_detcpu, cp,
2096 		    "oplue_detcpu");
2097 		break;
2098 	case CMD_PTR_CPU_UE_DET_IO:
2099 		cpu_case_restore(hdl, cpu, &cpu->cpu_oplue_detio, cp,
2100 		    "oplue_detio");
2101 		break;
2102 	case CMD_PTR_CPU_MTLB:
2103 		cpu_case_restore(hdl, cpu, &cpu->cpu_opl_mtlb, cp,
2104 		    "opl_mtlb");
2105 		break;
2106 	case CMD_PTR_CPU_TLBP:
2107 		cpu_case_restore(hdl, cpu, &cpu->cpu_opl_tlbp, cp,
2108 		    "opl_tlbp");
2109 		break;
2110 	case CMD_PTR_CPU_UGESR_INV_URG:
2111 		cpu_case_restore(hdl, cpu, &cpu->cpu_opl_inv_urg, cp,
2112 		    "opl_inv_urg");
2113 		break;
2114 	case CMD_PTR_CPU_UGESR_CRE:
2115 		cpu_case_restore(hdl, cpu, &cpu->cpu_opl_cre, cp,
2116 		    "opl_cre");
2117 		break;
2118 	case CMD_PTR_CPU_UGESR_TSB_CTX:
2119 		cpu_case_restore(hdl, cpu, &cpu->cpu_opl_tsb_ctx, cp,
2120 		    "opl_tsb_ctx");
2121 		break;
2122 	case CMD_PTR_CPU_UGESR_TSBP:
2123 		cpu_case_restore(hdl, cpu, &cpu->cpu_opl_tsbp, cp,
2124 		    "opl_tsbp");
2125 		break;
2126 	case CMD_PTR_CPU_UGESR_PSTATE:
2127 		cpu_case_restore(hdl, cpu, &cpu->cpu_opl_pstate, cp,
2128 		    "opl_pstate");
2129 		break;
2130 	case CMD_PTR_CPU_UGESR_TSTATE:
2131 		cpu_case_restore(hdl, cpu, &cpu->cpu_opl_tstate, cp,
2132 		    "opl_tstate");
2133 		break;
2134 	case CMD_PTR_CPU_UGESR_IUG_F:
2135 		cpu_case_restore(hdl, cpu, &cpu->cpu_opl_iug_f, cp,
2136 		    "opl_iug_f");
2137 		break;
2138 	case CMD_PTR_CPU_UGESR_IUG_R:
2139 		cpu_case_restore(hdl, cpu, &cpu->cpu_opl_iug_r, cp,
2140 		    "opl_iug_r");
2141 		break;
2142 	case CMD_PTR_CPU_UGESR_SDC:
2143 		cpu_case_restore(hdl, cpu, &cpu->cpu_opl_sdc, cp,
2144 		    "opl_sdc");
2145 		break;
2146 	case CMD_PTR_CPU_UGESR_WDT:
2147 		cpu_case_restore(hdl, cpu, &cpu->cpu_opl_wdt, cp,
2148 		    "opl_wdt");
2149 		break;
2150 	case CMD_PTR_CPU_UGESR_DTLB:
2151 		cpu_case_restore(hdl, cpu, &cpu->cpu_opl_dtlb, cp,
2152 		    "opl_dtlb");
2153 		break;
2154 	case CMD_PTR_CPU_UGESR_ITLB:
2155 		cpu_case_restore(hdl, cpu, &cpu->cpu_opl_itlb, cp,
2156 		    "opl_itlb");
2157 		break;
2158 	case CMD_PTR_CPU_UGESR_CORE_ERR:
2159 		cpu_case_restore(hdl, cpu, &cpu->cpu_opl_core_err, cp,
2160 		    "opl_core_err");
2161 		break;
2162 	case CMD_PTR_CPU_UGESR_DAE:
2163 		cpu_case_restore(hdl, cpu, &cpu->cpu_opl_dae, cp,
2164 		    "opl_dae");
2165 		break;
2166 	case CMD_PTR_CPU_UGESR_IAE:
2167 		cpu_case_restore(hdl, cpu, &cpu->cpu_opl_iae, cp,
2168 		    "opl_iae");
2169 		break;
2170 	case CMD_PTR_CPU_UGESR_UGE:
2171 		cpu_case_restore(hdl, cpu, &cpu->cpu_opl_uge, cp,
2172 		    "opl_uge");
2173 		break;
2174 #endif	/* sun4u */
2175 	default:
2176 		fmd_hdl_abort(hdl, "invalid %s subtype %d\n",
2177 		    ptr->ptr_name, ptr->ptr_subtype);
2178 	}
2179 
2180 	return (cpu);
2181 }
2182 
2183 void
cmd_cpu_validate(fmd_hdl_t * hdl)2184 cmd_cpu_validate(fmd_hdl_t *hdl)
2185 {
2186 	cmd_xr_t *xr, *xrn;
2187 	cmd_cpu_t *cpu, *cpun;
2188 
2189 	for (cpu = cmd_list_next(&cmd.cmd_cpus); cpu != NULL;
2190 	    cpu = cmd_list_next(cpu)) {
2191 		if (cpu_all_threads_invalid(hdl, cpu) == FMD_B_TRUE)
2192 			cpu->cpu_flags |= CMD_CPU_F_DELETING;
2193 	}
2194 
2195 	for (xr = cmd_list_next(&cmd.cmd_xxcu_redelivs); xr != NULL; xr = xrn) {
2196 		xrn = cmd_list_next(xr);
2197 
2198 		if (xr->xr_cpu->cpu_flags & CMD_CPU_F_DELETING)
2199 			cmd_xr_destroy(hdl, xr);
2200 	}
2201 
2202 	for (cpu = cmd_list_next(&cmd.cmd_cpus); cpu != NULL; cpu = cpun) {
2203 		cpun = cmd_list_next(cpu);
2204 
2205 		if (cpu->cpu_flags & CMD_CPU_F_DELETING)
2206 			cmd_cpu_destroy(hdl, cpu);
2207 	}
2208 }
2209 
2210 static void
cmd_xxcu_timeout(fmd_hdl_t * hdl,id_t id)2211 cmd_xxcu_timeout(fmd_hdl_t *hdl, id_t id)
2212 {
2213 	cmd_xr_t *xr;
2214 
2215 	for (xr = cmd_list_next(&cmd.cmd_xxcu_redelivs); xr != NULL;
2216 	    xr = cmd_list_next(xr)) {
2217 		if (xr->xr_id == id) {
2218 			fmd_event_t *ep = fmd_case_getprincipal(hdl,
2219 			    xr->xr_case);
2220 			xr->xr_hdlr(hdl, xr, ep);
2221 			cmd_xr_deref(hdl, xr);
2222 			return;
2223 		}
2224 	}
2225 }
2226 
2227 /*ARGSUSED*/
2228 static void
cmd_xxu_flush_timeout(fmd_hdl_t * hdl,id_t id)2229 cmd_xxu_flush_timeout(fmd_hdl_t *hdl, id_t id)
2230 {
2231 #ifdef sun4u
2232 	cmd_cpu_t *cpu;
2233 
2234 	for (cpu = cmd_list_next(&cmd.cmd_cpus); cpu != NULL;
2235 	    cpu = cmd_list_next(cpu)) {
2236 		if (cpu->cpu_uec_flush == id) {
2237 			cpu_uec_flush_finish(hdl, cpu);
2238 			return;
2239 		}
2240 	}
2241 #else /* sun4u */
2242 	return;
2243 #endif /* sun4u */
2244 }
2245 
2246 void
cmd_cpu_timeout(fmd_hdl_t * hdl,id_t id,void * type)2247 cmd_cpu_timeout(fmd_hdl_t *hdl, id_t id, void *type)
2248 {
2249 	switch ((uintptr_t)type) {
2250 	case (uintptr_t)CMD_TIMERTYPE_CPU_UEC_FLUSH:
2251 		cmd_xxu_flush_timeout(hdl, id);
2252 		break;
2253 	case (uintptr_t)CMD_TIMERTYPE_CPU_XR_WAITER:
2254 		cmd_xxcu_timeout(hdl, id);
2255 		break;
2256 	}
2257 }
2258 
2259 static int
cpu_gc_keep_one(fmd_hdl_t * hdl,cmd_cpu_t * cpu)2260 cpu_gc_keep_one(fmd_hdl_t *hdl, cmd_cpu_t *cpu)
2261 {
2262 	int i;
2263 
2264 	if (cpu_all_threads_invalid(hdl, cpu) == FMD_B_TRUE) {
2265 		fmd_hdl_debug(hdl, "GC of CPU %d: no longer working\n",
2266 		    cpu->cpu_cpuid);
2267 		return (0);
2268 	}
2269 
2270 	for (i = 0; i < sizeof (cmd_cpu_cases_t) / sizeof (cmd_case_t); i++) {
2271 		cmd_case_t *cp = &((cmd_case_t *)&cpu->cpu_cases)[i];
2272 
2273 		if (cp->cc_cp == NULL || cp->cc_serdnm == NULL)
2274 			continue;
2275 
2276 		if (fmd_serd_exists(hdl, cp->cc_serdnm) &&
2277 		    !fmd_serd_empty(hdl, cp->cc_serdnm))
2278 			return (1);
2279 	}
2280 
2281 	if (cmd_list_next(&cpu->cpu_xxu_retries) != NULL)
2282 		return (1);
2283 
2284 	if (cpu->cpu_uec.uec_cache != NULL ||
2285 	    cpu->cpu_olduec.uec_cache != NULL)
2286 		return (1);
2287 
2288 	return (0);
2289 }
2290 
2291 /*ARGSUSED*/
2292 void
cmd_cpu_gc(fmd_hdl_t * hdl)2293 cmd_cpu_gc(fmd_hdl_t *hdl)
2294 {
2295 	cmd_cpu_t *cpu, *next;
2296 
2297 	fmd_hdl_debug(hdl, "GC of CPUs\n");
2298 
2299 	for (cpu = cmd_list_next(&cmd.cmd_cpus); cpu != NULL; cpu = next) {
2300 		next = cmd_list_next(cpu);
2301 
2302 		if (!cpu_gc_keep_one(hdl, cpu)) {
2303 			fmd_hdl_debug(hdl, "GC of CPU %d: destroying\n",
2304 			    cpu->cpu_cpuid);
2305 			continue;
2306 		}
2307 #ifdef sun4u
2308 		if (cpu->cpu_uec.uec_cache != NULL)
2309 			cpu_uec_flush(hdl, cpu);
2310 #endif /* sun4u */
2311 		cpu->cpu_uec_nflushes = 0;
2312 	}
2313 }
2314 
2315 void
cmd_cpu_fini(fmd_hdl_t * hdl)2316 cmd_cpu_fini(fmd_hdl_t *hdl)
2317 {
2318 	cmd_cpu_t *cpu;
2319 
2320 	while ((cpu = cmd_list_next(&cmd.cmd_cpus)) != NULL)
2321 		cmd_cpu_free(hdl, cpu, FMD_B_FALSE);
2322 }
2323 
2324 typedef struct {
2325     const char *fam_name;
2326     cpu_family_t fam_value;
2327 } famdata_t;
2328 
2329 static famdata_t famdata_tbl[] = {
2330 	{"UltraSPARC-III",	CMD_CPU_FAM_CHEETAH},
2331 	{"UltraSPARC-IV",	CMD_CPU_FAM_CHEETAH},
2332 	{"UltraSPARC-T",	CMD_CPU_FAM_NIAGARA},
2333 	{"SPARC64-VI",		CMD_CPU_FAM_SPARC64},
2334 	{"SPARC64-VII",		CMD_CPU_FAM_SPARC64}
2335 };
2336 
2337 cpu_family_t
cpu_family(char * knsp)2338 cpu_family(char *knsp)
2339 {
2340 	int j;
2341 
2342 	for (j = 0; j < sizeof (famdata_tbl)/sizeof (famdata_t); j++) {
2343 		if (strncmp(knsp, famdata_tbl[j].fam_name,
2344 		    strlen(famdata_tbl[j].fam_name)) == 0) {
2345 			return (famdata_tbl[j].fam_value);
2346 		}
2347 	}
2348 	return (CMD_CPU_FAM_UNSUPPORTED);
2349 }
2350 
2351 /*
2352  * Determine which CPU family this diagnosis is being run on.
2353  * This assumes that ereports are being generated by this system.
2354  */
2355 
2356 cpu_family_t
cmd_cpu_check_support(void)2357 cmd_cpu_check_support(void)
2358 {
2359 	kstat_named_t *kn;
2360 	kstat_ctl_t *kc;
2361 	kstat_t *ksp;
2362 	int i;
2363 
2364 	if ((kc = kstat_open()) == NULL)
2365 		return (CMD_CPU_FAM_UNSUPPORTED);
2366 
2367 	for (ksp = kc->kc_chain; ksp != NULL; ksp = ksp->ks_next) {
2368 		if (strcmp(ksp->ks_module, "cpu_info") != 0)
2369 			continue;
2370 
2371 		if (kstat_read(kc, ksp, NULL) == -1) {
2372 			(void) kstat_close(kc);
2373 			return (CMD_CPU_FAM_UNSUPPORTED);
2374 		}
2375 
2376 		for (kn = ksp->ks_data, i = 0; i < ksp->ks_ndata; i++, kn++) {
2377 			cpu_family_t family;
2378 			if (strcmp(kn->name, "implementation") != 0)
2379 				continue;
2380 			family = cpu_family(KSTAT_NAMED_STR_PTR(kn));
2381 			(void) kstat_close(kc);
2382 			return (family);
2383 		}
2384 	}
2385 	(void) kstat_close(kc);
2386 	return (CMD_CPU_FAM_UNSUPPORTED);
2387 }
2388 
2389 boolean_t
cmd_cpu_ecache_support(void)2390 cmd_cpu_ecache_support(void)
2391 {
2392 	cpu_family_t value;
2393 
2394 	value = cmd_cpu_check_support();
2395 	return (fam_info_tbl[value].ecache_flush_needed);
2396 }
2397 
2398 /*
2399  * This function builds the fmri of the
2400  * given cpuid based on the cpu scheme.
2401  */
2402 nvlist_t *
cmd_cpu_fmri_create(uint32_t cpuid,uint8_t cpumask)2403 cmd_cpu_fmri_create(uint32_t cpuid, uint8_t cpumask)
2404 {
2405 	nvlist_t *fmri;
2406 
2407 	if ((errno = nvlist_alloc(&fmri, NV_UNIQUE_NAME, 0)) != 0)
2408 		return (NULL);
2409 
2410 	if (nvlist_add_uint8(fmri, FM_VERSION,
2411 	    FM_CPU_SCHEME_VERSION) != 0 || nvlist_add_string(fmri,
2412 	    FM_FMRI_SCHEME, FM_FMRI_SCHEME_CPU) != 0 ||
2413 	    nvlist_add_uint32(fmri, FM_FMRI_CPU_ID, cpuid) != 0 ||
2414 	    nvlist_add_uint8(fmri, FM_FMRI_CPU_MASK, cpumask) != 0) {
2415 		nvlist_free(fmri);
2416 		return (NULL);
2417 	}
2418 
2419 	return (fmri);
2420 }
2421