Home | History | Annotate | Download | only in cpumem-diagnosis
      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