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