cmd_cpu.c revision 4759:3a228be89946
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 2007 Sun Microsystems, Inc.  All rights reserved.
23 * Use is subject to license terms.
24 */
25
26#pragma ident	"%Z%%M%	%I%	%E% SMI"
27
28/*
29 * Support routines for managing per-CPU state.
30 */
31
32#include <cmd_cpu.h>
33
34#ifdef sun4u
35#include <cmd_ecache.h>
36#endif /* sun4u */
37
38#include <cmd_mem.h>
39#include <cmd.h>
40
41#include <stdio.h>
42#include <string.h>
43#include <strings.h>
44#include <errno.h>
45#include <kstat.h>
46#include <fm/fmd_api.h>
47#include <sys/async.h>
48#include <sys/fm/protocol.h>
49
50#ifdef sun4u
51#include <sys/cheetahregs.h>
52#include <sys/fm/cpu/UltraSPARC-III.h>
53#include <cmd_opl.h>
54#else /* sun4u */
55#include <sys/niagararegs.h>
56#include <sys/fm/cpu/UltraSPARC-T1.h>
57#include <cmd_hc_sun4v.h>
58#endif /* sun4u */
59
60#define	CMD_CPU_UEC_INCR	10
61
62/* Must be in sync with cmd_cpu_type_t */
63static const char *const cpu_names[] = {
64	NULL,
65	"ultraSPARC-III",
66	"ultraSPARC-IIIplus",
67	"ultraSPARC-IIIi",
68	"ultraSPARC-IV",
69	"ultraSPARC-IVplus",
70	"ultraSPARC-IIIiplus",
71	"ultraSPARC-T1",
72	"SPARC64-VI",
73	"ultraSPARC-T2",
74	"ultraSPARC-T2plus"
75};
76
77/*
78 * This needs to be in sync with cpu_family_t.
79 */
80static 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
87static cmd_cpu_t *cpu_lookup_by_cpuid(uint32_t, uint8_t);
88static cmd_cpu_t *cpu_create(fmd_hdl_t *, nvlist_t *, uint32_t,
89    uint8_t, cmd_cpu_type_t);
90static void cpu_buf_write(fmd_hdl_t *, cmd_cpu_t *);
91
92static const char *
93cpu_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
101static cmd_cpu_type_t
102cpu_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
117const 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
123static void
124core2cpus(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
209uint32_t
210cmd_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
260static void
261cpu_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
280static void
281cpu_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
293static void
294cpu_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
302static void
303cpu_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
314static void
315cpu_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
332static void
333cpu_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, sizeof (uint64_t) *
357		    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
389void
390cmd_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
432void
433cmd_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
445int
446cmd_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
477void
478cmd_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
487static cmd_xr_hdlr_f *
488cmd_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	default:
496		fmd_hdl_abort(hdl, "cmd_xr_id2hdlr called with bad hdlrid %x\n",
497		    id);
498	}
499
500	return (NULL);
501}
502
503cmd_xr_t *
504cmd_xr_create(fmd_hdl_t *hdl, fmd_event_t *ep, nvlist_t *nvl,
505    cmd_cpu_t *cpu, cmd_errcl_t clcode)
506{
507	cmd_xr_t *xr = fmd_hdl_zalloc(hdl, sizeof (cmd_xr_t),
508	    FMD_SLEEP);
509	nvlist_t *rsrc = NULL;
510	const char *uuid;
511	int err = 0;
512
513	err |= nvlist_lookup_uint64(nvl, FM_EREPORT_ENA, &xr->xr_ena);
514
515	/*
516	 * Skip the cmd_xr_fill() for misc reg errors because
517	 * these data are not in the misc reg ereport
518	 */
519	if (!CMD_ERRCL_ISMISCREGS(clcode))
520		err |= cmd_xr_fill(hdl, nvl, xr, clcode);
521
522	(void) nvlist_lookup_nvlist(nvl, FM_EREPORT_PAYLOAD_NAME_RESOURCE,
523	    &rsrc);
524
525	if (err != 0) {
526		fmd_hdl_free(hdl, xr, sizeof (cmd_xr_t));
527		return (NULL);
528	}
529
530	xr->xr_cpu = cpu;
531	xr->xr_cpuid = cpu->cpu_cpuid;
532	xr->xr_clcode = clcode;
533	xr->xr_case = cmd_case_create(hdl, &cpu->cpu_header,
534	    CMD_PTR_CPU_XR_RETRY, &uuid);
535	fmd_case_setprincipal(hdl, xr->xr_case, ep);
536
537	if (rsrc != NULL) {
538		cmd_fmri_init(hdl, &xr->xr_rsrc, rsrc, "%s_rsrc",
539		    fmd_case_uuid(hdl, xr->xr_case));
540	}
541
542	cmd_xr_write(hdl, xr);
543	return (xr);
544}
545
546cmd_evdisp_t
547cmd_xr_reschedule(fmd_hdl_t *hdl, cmd_xr_t *xr, uint_t hdlrid)
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	if (CMD_ERRCL_ISMISCREGS(xr->xr_clcode))
556		xr->xr_id = fmd_timer_install(hdl,
557		    (void *)CMD_TIMERTYPE_CPU_XR_WAITER, NULL,
558		    cmd.cmd_miscregs_trdelay);
559	else
560		xr->xr_id = fmd_timer_install(hdl,
561		    (void *)CMD_TIMERTYPE_CPU_XR_WAITER,
562		    NULL, cmd.cmd_xxcu_trdelay);
563
564	if (xr->xr_ref++ == 0)
565		cmd_list_append(&cmd.cmd_xxcu_redelivs, xr);
566
567	cmd_xr_write(hdl, xr);
568	return (CMD_EVD_OK);
569}
570
571static void
572cmd_xr_destroy(fmd_hdl_t *hdl, cmd_xr_t *xr)
573{
574	fmd_hdl_debug(hdl, "destroying xr (clcode %llx) at %p\n",
575	    xr->xr_clcode, xr);
576
577	fmd_case_reset(hdl, xr->xr_case);
578	cmd_case_fini(hdl, xr->xr_case, FMD_B_TRUE);
579
580	if (xr->xr_rsrc_nvl != NULL)
581		cmd_fmri_fini(hdl, &xr->xr_rsrc, FMD_B_TRUE);
582
583	fmd_buf_destroy(hdl, xr->xr_case, "redelivery");
584	fmd_hdl_free(hdl, xr, sizeof (cmd_xr_t));
585}
586
587void
588cmd_xr_deref(fmd_hdl_t *hdl, cmd_xr_t *xr)
589{
590	if (xr->xr_ref == 0)
591		fmd_hdl_abort(hdl, "attempt to deref xr with zero ref\n");
592
593	fmd_hdl_debug(hdl, "deref xr %p [%d]\n", xr, xr->xr_ref);
594
595	if (--xr->xr_ref == 0) {
596		cmd_list_delete(&cmd.cmd_xxcu_redelivs, xr);
597		cmd_xr_destroy(hdl, xr);
598	}
599}
600
601static void
602cmd_xr_restore(fmd_hdl_t *hdl, cmd_cpu_t *cpu, fmd_case_t *cp)
603{
604	cmd_xr_t *xr;
605
606	if ((xr = cmd_buf_read(hdl, cp, "redelivery", sizeof (cmd_xr_t))) ==
607	    NULL) {
608		fmd_hdl_abort(hdl, "failed to find redelivery for case %s\n",
609		    fmd_case_uuid(hdl, cp));
610	}
611
612	xr->xr_case = cp;
613	xr->xr_hdlr = cmd_xr_id2hdlr(hdl, xr->xr_hdlrid);
614	if (xr->xr_rsrc_nvl != NULL)
615		cmd_fmri_restore(hdl, &xr->xr_rsrc);
616	xr->xr_cpu = cpu;
617
618	/*
619	 * fmd is still in the process of starting up.  If we reschedule this
620	 * event with the normal redelivery timeout, it'll get redelivered
621	 * before initialization has completed, we'll potentially fail to
622	 * match the train, deref() the waiter (causing any subsequent side-
623	 * effects to miss the waiter), and use this ereport to blame the CPU.
624	 * The other side-effects will blame the CPU too, since we'll have
625	 * deref()'d the waiter out of existence.  We can get up to three
626	 * additions to the SERD engine this way, which is bad.  To keep that
627	 * from happening, we're going to schedule an arbitrarily long timeout,
628	 * which *should* be long enough.  It's pretty bad, but there's no
629	 * real way to keep the other side-effects from taking out the CPU.
630	 */
631	xr->xr_id = fmd_timer_install(hdl, (void *)CMD_TIMERTYPE_CPU_XR_WAITER,
632	    NULL, fmd_prop_get_int64(hdl, "xxcu_restart_delay"));
633
634	cmd_list_append(&cmd.cmd_xxcu_redelivs, xr);
635
636	fmd_hdl_debug(hdl, "revived xr for class %llx\n", xr->xr_clcode);
637}
638
639typedef struct cmd_xxcu_train {
640	cmd_errcl_t tr_mask;	/* errors we must see to match this train */
641	cmd_errcl_t tr_cause;	/* the error at the root of this train */
642} cmd_xxcu_train_t;
643
644#define	CMD_TRAIN(cause, side_effects)	{ (cause) | (side_effects), (cause) }
645
646static const cmd_xxcu_train_t cmd_xxcu_trains[] = {
647#ifdef sun4u
648	/* UCC: WDC */
649	CMD_TRAIN(CMD_ERRCL_UCC,	CMD_ERRCL_WDC),
650
651	/* UCU: WDU, WDU+L3_WDU */
652	CMD_TRAIN(CMD_ERRCL_UCU,	CMD_ERRCL_WDU),
653	CMD_TRAIN(CMD_ERRCL_UCU,	CMD_ERRCL_L3_WDU | CMD_ERRCL_WDU),
654
655	/* EDC: WDC */
656	CMD_TRAIN(CMD_ERRCL_EDC,	CMD_ERRCL_WDC),
657
658	/* EDU: WDU, WDU+L3_WDU */
659	CMD_TRAIN(CMD_ERRCL_EDU_ST,	CMD_ERRCL_WDU),
660	CMD_TRAIN(CMD_ERRCL_EDU_BL,	CMD_ERRCL_WDU),
661	CMD_TRAIN(CMD_ERRCL_EDU_ST,	CMD_ERRCL_L3_WDU | CMD_ERRCL_WDU),
662	CMD_TRAIN(CMD_ERRCL_EDU_BL,	CMD_ERRCL_L3_WDU | CMD_ERRCL_WDU),
663
664	/* CPC: WDC, EDC+WDC, UCC+WDC, EDC+UCC+WDC */
665	CMD_TRAIN(CMD_ERRCL_CPC,	CMD_ERRCL_WDC),
666	CMD_TRAIN(CMD_ERRCL_CPC,	CMD_ERRCL_EDC | CMD_ERRCL_WDC),
667	CMD_TRAIN(CMD_ERRCL_CPC,	CMD_ERRCL_UCC | CMD_ERRCL_WDC),
668	CMD_TRAIN(CMD_ERRCL_CPC,	CMD_ERRCL_EDC | CMD_ERRCL_UCC |
669	    CMD_ERRCL_WDC),
670
671	/* CPU: WDU, WDU+L3_WDU, UCU+WDU, UCU+WDU+L3_WDU */
672	CMD_TRAIN(CMD_ERRCL_CPU,	CMD_ERRCL_WDU),
673	CMD_TRAIN(CMD_ERRCL_CPU,	CMD_ERRCL_L3_WDU | CMD_ERRCL_WDU),
674	CMD_TRAIN(CMD_ERRCL_CPU,	CMD_ERRCL_UCU | CMD_ERRCL_WDU),
675	CMD_TRAIN(CMD_ERRCL_CPU,	CMD_ERRCL_UCU | CMD_ERRCL_L3_WDU |
676	    CMD_ERRCL_WDU),
677
678	/* CPU: EDU+WDU, EDU+WDU+L3_WDU, EDU+UCU+WDU,  EDU+UCU+WDU+L3_WDU */
679	CMD_TRAIN(CMD_ERRCL_CPU,	CMD_ERRCL_EDU_ST | CMD_ERRCL_WDU),
680	CMD_TRAIN(CMD_ERRCL_CPU,	CMD_ERRCL_EDU_BL | CMD_ERRCL_WDU),
681	CMD_TRAIN(CMD_ERRCL_CPU,	CMD_ERRCL_EDU_ST | CMD_ERRCL_EDU_BL |
682	    CMD_ERRCL_WDU),
683	CMD_TRAIN(CMD_ERRCL_CPU,	CMD_ERRCL_EDU_ST | CMD_ERRCL_WDU |
684	    CMD_ERRCL_L3_WDU),
685	CMD_TRAIN(CMD_ERRCL_CPU,	CMD_ERRCL_EDU_BL | CMD_ERRCL_WDU |
686	    CMD_ERRCL_L3_WDU),
687	CMD_TRAIN(CMD_ERRCL_CPU,	CMD_ERRCL_EDU_ST | CMD_ERRCL_EDU_BL |
688	    CMD_ERRCL_WDU | CMD_ERRCL_L3_WDU),
689	CMD_TRAIN(CMD_ERRCL_CPU,	CMD_ERRCL_EDU_ST | CMD_ERRCL_UCU |
690	    CMD_ERRCL_WDU),
691	CMD_TRAIN(CMD_ERRCL_CPU,	CMD_ERRCL_EDU_BL | CMD_ERRCL_UCU |
692	    CMD_ERRCL_WDU),
693	CMD_TRAIN(CMD_ERRCL_CPU,	CMD_ERRCL_EDU_ST | CMD_ERRCL_EDU_BL |
694	    CMD_ERRCL_UCU | CMD_ERRCL_WDU),
695	CMD_TRAIN(CMD_ERRCL_CPU,	CMD_ERRCL_EDU_ST | CMD_ERRCL_UCU |
696	    CMD_ERRCL_WDU | CMD_ERRCL_L3_WDU),
697	CMD_TRAIN(CMD_ERRCL_CPU,	CMD_ERRCL_EDU_BL | CMD_ERRCL_UCU |
698	    CMD_ERRCL_WDU | CMD_ERRCL_L3_WDU),
699	CMD_TRAIN(CMD_ERRCL_CPU,	CMD_ERRCL_EDU_ST | CMD_ERRCL_EDU_BL |
700	    CMD_ERRCL_UCU | CMD_ERRCL_WDU | CMD_ERRCL_L3_WDU),
701
702	/* WDU: L3_WDU */
703	CMD_TRAIN(CMD_ERRCL_WDU,	CMD_ERRCL_L3_WDU),
704
705	/* L3_UCC: WDC+(zero or more of EDC, CPC, UCC) */
706	CMD_TRAIN(CMD_ERRCL_L3_UCC,	CMD_ERRCL_WDC),
707	CMD_TRAIN(CMD_ERRCL_L3_UCC,	CMD_ERRCL_WDC | CMD_ERRCL_EDC),
708	CMD_TRAIN(CMD_ERRCL_L3_UCC,	CMD_ERRCL_WDC | CMD_ERRCL_CPC),
709	CMD_TRAIN(CMD_ERRCL_L3_UCC,	CMD_ERRCL_WDC | CMD_ERRCL_UCC),
710	CMD_TRAIN(CMD_ERRCL_L3_UCC,	CMD_ERRCL_WDC | CMD_ERRCL_EDC |
711	    CMD_ERRCL_CPC),
712	CMD_TRAIN(CMD_ERRCL_L3_UCC,	CMD_ERRCL_WDC | CMD_ERRCL_EDC |
713	    CMD_ERRCL_UCC),
714	CMD_TRAIN(CMD_ERRCL_L3_UCC,	CMD_ERRCL_WDC | CMD_ERRCL_CPC |
715	    CMD_ERRCL_UCC),
716	CMD_TRAIN(CMD_ERRCL_L3_UCC,	CMD_ERRCL_WDC | CMD_ERRCL_EDC |
717	    CMD_ERRCL_CPC | CMD_ERRCL_UCC),
718
719	/* L3_UCU: WDU+(zero or more of EDU, CPU, UCU) */
720	CMD_TRAIN(CMD_ERRCL_L3_UCU,	CMD_ERRCL_WDU),
721	CMD_TRAIN(CMD_ERRCL_L3_UCU,	CMD_ERRCL_WDU | CMD_ERRCL_EDU_ST),
722	CMD_TRAIN(CMD_ERRCL_L3_UCU,	CMD_ERRCL_WDU | CMD_ERRCL_EDU_BL),
723	CMD_TRAIN(CMD_ERRCL_L3_UCU,	CMD_ERRCL_WDU | CMD_ERRCL_EDU_ST |
724	    CMD_ERRCL_EDU_BL),
725	CMD_TRAIN(CMD_ERRCL_L3_UCU,	CMD_ERRCL_WDU | CMD_ERRCL_CPU),
726	CMD_TRAIN(CMD_ERRCL_L3_UCU,	CMD_ERRCL_WDU | CMD_ERRCL_UCU),
727	CMD_TRAIN(CMD_ERRCL_L3_UCU,	CMD_ERRCL_WDU | CMD_ERRCL_EDU_ST |
728	    CMD_ERRCL_CPU),
729	CMD_TRAIN(CMD_ERRCL_L3_UCU,	CMD_ERRCL_WDU | CMD_ERRCL_EDU_BL |
730	    CMD_ERRCL_CPU),
731	CMD_TRAIN(CMD_ERRCL_L3_UCU,	CMD_ERRCL_WDU | CMD_ERRCL_EDU_ST |
732	    CMD_ERRCL_EDU_BL | CMD_ERRCL_CPU),
733	CMD_TRAIN(CMD_ERRCL_L3_UCU,	CMD_ERRCL_WDU | CMD_ERRCL_EDU_ST |
734	    CMD_ERRCL_UCU),
735	CMD_TRAIN(CMD_ERRCL_L3_UCU,	CMD_ERRCL_WDU | CMD_ERRCL_EDU_BL |
736	    CMD_ERRCL_UCU),
737	CMD_TRAIN(CMD_ERRCL_L3_UCU,	CMD_ERRCL_WDU | CMD_ERRCL_EDU_ST |
738	    CMD_ERRCL_EDU_BL | CMD_ERRCL_UCU),
739	CMD_TRAIN(CMD_ERRCL_L3_UCU,	CMD_ERRCL_WDU | CMD_ERRCL_CPU |
740	    CMD_ERRCL_UCU),
741	CMD_TRAIN(CMD_ERRCL_L3_UCU,	CMD_ERRCL_WDU | CMD_ERRCL_EDU_ST |
742	    CMD_ERRCL_CPU | CMD_ERRCL_UCU),
743	CMD_TRAIN(CMD_ERRCL_L3_UCU,	CMD_ERRCL_WDU | CMD_ERRCL_EDU_BL |
744	    CMD_ERRCL_CPU | CMD_ERRCL_UCU),
745	CMD_TRAIN(CMD_ERRCL_L3_UCU,	CMD_ERRCL_WDU | CMD_ERRCL_EDU_ST |
746	    CMD_ERRCL_EDU_BL | CMD_ERRCL_CPU | CMD_ERRCL_UCU),
747
748	/* L3_UCU: WDU+(zero or more of EDU, CPU, UCU)+L3_WDU */
749	CMD_TRAIN(CMD_ERRCL_L3_UCU,	CMD_ERRCL_WDU | CMD_ERRCL_L3_WDU),
750	CMD_TRAIN(CMD_ERRCL_L3_UCU,	CMD_ERRCL_WDU | CMD_ERRCL_EDU_ST |
751	    CMD_ERRCL_L3_WDU),
752	CMD_TRAIN(CMD_ERRCL_L3_UCU,	CMD_ERRCL_WDU | CMD_ERRCL_EDU_BL |
753	    CMD_ERRCL_L3_WDU),
754	CMD_TRAIN(CMD_ERRCL_L3_UCU,	CMD_ERRCL_WDU | CMD_ERRCL_EDU_ST |
755	    CMD_ERRCL_EDU_BL | CMD_ERRCL_L3_WDU),
756	CMD_TRAIN(CMD_ERRCL_L3_UCU,	CMD_ERRCL_WDU | CMD_ERRCL_CPU |
757	    CMD_ERRCL_L3_WDU),
758	CMD_TRAIN(CMD_ERRCL_L3_UCU,	CMD_ERRCL_WDU | CMD_ERRCL_UCU |
759	    CMD_ERRCL_L3_WDU),
760	CMD_TRAIN(CMD_ERRCL_L3_UCU,	CMD_ERRCL_WDU | CMD_ERRCL_EDU_ST |
761	    CMD_ERRCL_CPU | CMD_ERRCL_L3_WDU),
762	CMD_TRAIN(CMD_ERRCL_L3_UCU,	CMD_ERRCL_WDU | CMD_ERRCL_EDU_BL |
763	    CMD_ERRCL_CPU | 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_CPU | CMD_ERRCL_L3_WDU),
766	CMD_TRAIN(CMD_ERRCL_L3_UCU,	CMD_ERRCL_WDU | CMD_ERRCL_EDU_ST |
767	    CMD_ERRCL_UCU | CMD_ERRCL_L3_WDU),
768	CMD_TRAIN(CMD_ERRCL_L3_UCU,	CMD_ERRCL_WDU | CMD_ERRCL_EDU_BL |
769	    CMD_ERRCL_UCU | CMD_ERRCL_L3_WDU),
770	CMD_TRAIN(CMD_ERRCL_L3_UCU,	CMD_ERRCL_WDU | CMD_ERRCL_EDU_ST |
771	    CMD_ERRCL_EDU_BL | CMD_ERRCL_UCU | CMD_ERRCL_L3_WDU),
772	CMD_TRAIN(CMD_ERRCL_L3_UCU,	CMD_ERRCL_WDU | CMD_ERRCL_CPU |
773	    CMD_ERRCL_UCU | CMD_ERRCL_L3_WDU),
774	CMD_TRAIN(CMD_ERRCL_L3_UCU,	CMD_ERRCL_WDU | CMD_ERRCL_EDU_ST |
775	    CMD_ERRCL_CPU | CMD_ERRCL_UCU | CMD_ERRCL_L3_WDU),
776	CMD_TRAIN(CMD_ERRCL_L3_UCU,	CMD_ERRCL_WDU | CMD_ERRCL_EDU_BL |
777	    CMD_ERRCL_CPU | CMD_ERRCL_UCU | CMD_ERRCL_L3_WDU),
778	CMD_TRAIN(CMD_ERRCL_L3_UCU,	CMD_ERRCL_WDU | CMD_ERRCL_EDU_ST |
779	    CMD_ERRCL_EDU_BL | CMD_ERRCL_CPU | CMD_ERRCL_UCU |
780	    CMD_ERRCL_L3_WDU),
781
782	/* L3_EDC: WDC+(zero or more of EDC, CPC, UCC) */
783	CMD_TRAIN(CMD_ERRCL_L3_EDC,	CMD_ERRCL_WDC),
784	CMD_TRAIN(CMD_ERRCL_L3_EDC,	CMD_ERRCL_WDC | CMD_ERRCL_EDC),
785	CMD_TRAIN(CMD_ERRCL_L3_EDC,	CMD_ERRCL_WDC | CMD_ERRCL_CPC),
786	CMD_TRAIN(CMD_ERRCL_L3_EDC,	CMD_ERRCL_WDC | CMD_ERRCL_UCC),
787	CMD_TRAIN(CMD_ERRCL_L3_EDC,	CMD_ERRCL_WDC | CMD_ERRCL_EDC |
788	    CMD_ERRCL_CPC),
789	CMD_TRAIN(CMD_ERRCL_L3_EDC,	CMD_ERRCL_WDC | CMD_ERRCL_EDC |
790	    CMD_ERRCL_UCC),
791	CMD_TRAIN(CMD_ERRCL_L3_EDC,	CMD_ERRCL_WDC | CMD_ERRCL_CPC |
792	    CMD_ERRCL_UCC),
793	CMD_TRAIN(CMD_ERRCL_L3_EDC,	CMD_ERRCL_WDC | CMD_ERRCL_EDC |
794	    CMD_ERRCL_CPC | CMD_ERRCL_UCC),
795
796	/* L3_EDU: WDU+(zero or more of EDU, CPU, UCU) */
797	CMD_TRAIN(CMD_ERRCL_L3_EDU_ST,	CMD_ERRCL_WDU),
798	CMD_TRAIN(CMD_ERRCL_L3_EDU_ST,	CMD_ERRCL_WDU | CMD_ERRCL_EDU_ST),
799	CMD_TRAIN(CMD_ERRCL_L3_EDU_ST,	CMD_ERRCL_WDU | CMD_ERRCL_EDU_BL),
800	CMD_TRAIN(CMD_ERRCL_L3_EDU_ST,	CMD_ERRCL_WDU | CMD_ERRCL_EDU_ST |
801	    CMD_ERRCL_EDU_BL),
802	CMD_TRAIN(CMD_ERRCL_L3_EDU_ST,	CMD_ERRCL_WDU | CMD_ERRCL_CPU),
803	CMD_TRAIN(CMD_ERRCL_L3_EDU_ST,	CMD_ERRCL_WDU | CMD_ERRCL_UCU),
804	CMD_TRAIN(CMD_ERRCL_L3_EDU_ST,	CMD_ERRCL_WDU | CMD_ERRCL_EDU_ST |
805	    CMD_ERRCL_CPU),
806	CMD_TRAIN(CMD_ERRCL_L3_EDU_ST,	CMD_ERRCL_WDU | CMD_ERRCL_EDU_BL |
807	    CMD_ERRCL_CPU),
808	CMD_TRAIN(CMD_ERRCL_L3_EDU_ST,	CMD_ERRCL_WDU | CMD_ERRCL_EDU_ST |
809	    CMD_ERRCL_EDU_BL | CMD_ERRCL_CPU),
810	CMD_TRAIN(CMD_ERRCL_L3_EDU_ST,	CMD_ERRCL_WDU | CMD_ERRCL_EDU_ST |
811	    CMD_ERRCL_UCU),
812	CMD_TRAIN(CMD_ERRCL_L3_EDU_ST,	CMD_ERRCL_WDU | CMD_ERRCL_EDU_BL |
813	    CMD_ERRCL_UCU),
814	CMD_TRAIN(CMD_ERRCL_L3_EDU_ST,	CMD_ERRCL_WDU | CMD_ERRCL_EDU_ST |
815	    CMD_ERRCL_EDU_BL | CMD_ERRCL_UCU),
816	CMD_TRAIN(CMD_ERRCL_L3_EDU_ST,	CMD_ERRCL_WDU | CMD_ERRCL_CPU |
817	    CMD_ERRCL_UCU),
818	CMD_TRAIN(CMD_ERRCL_L3_EDU_ST,	CMD_ERRCL_WDU | CMD_ERRCL_EDU_ST |
819	    CMD_ERRCL_CPU | CMD_ERRCL_UCU),
820	CMD_TRAIN(CMD_ERRCL_L3_EDU_ST,	CMD_ERRCL_WDU | CMD_ERRCL_EDU_BL |
821	    CMD_ERRCL_CPU | CMD_ERRCL_UCU),
822	CMD_TRAIN(CMD_ERRCL_L3_EDU_ST,	CMD_ERRCL_WDU | CMD_ERRCL_EDU_ST |
823	    CMD_ERRCL_EDU_BL | CMD_ERRCL_CPU | CMD_ERRCL_UCU),
824	CMD_TRAIN(CMD_ERRCL_L3_EDU_BL,	CMD_ERRCL_WDU),
825	CMD_TRAIN(CMD_ERRCL_L3_EDU_BL,	CMD_ERRCL_WDU | CMD_ERRCL_EDU_ST),
826	CMD_TRAIN(CMD_ERRCL_L3_EDU_BL,	CMD_ERRCL_WDU | CMD_ERRCL_EDU_BL),
827	CMD_TRAIN(CMD_ERRCL_L3_EDU_BL,	CMD_ERRCL_WDU | CMD_ERRCL_EDU_ST |
828	    CMD_ERRCL_EDU_BL),
829	CMD_TRAIN(CMD_ERRCL_L3_EDU_BL,	CMD_ERRCL_WDU | CMD_ERRCL_CPU),
830	CMD_TRAIN(CMD_ERRCL_L3_EDU_BL,	CMD_ERRCL_WDU | CMD_ERRCL_UCU),
831	CMD_TRAIN(CMD_ERRCL_L3_EDU_BL,	CMD_ERRCL_WDU | CMD_ERRCL_EDU_ST |
832	    CMD_ERRCL_CPU),
833	CMD_TRAIN(CMD_ERRCL_L3_EDU_BL,	CMD_ERRCL_WDU | CMD_ERRCL_EDU_BL |
834	    CMD_ERRCL_CPU),
835	CMD_TRAIN(CMD_ERRCL_L3_EDU_BL,	CMD_ERRCL_WDU | CMD_ERRCL_EDU_ST |
836	    CMD_ERRCL_EDU_BL | CMD_ERRCL_CPU),
837	CMD_TRAIN(CMD_ERRCL_L3_EDU_BL,	CMD_ERRCL_WDU | CMD_ERRCL_EDU_ST |
838	    CMD_ERRCL_UCU),
839	CMD_TRAIN(CMD_ERRCL_L3_EDU_BL,	CMD_ERRCL_WDU | CMD_ERRCL_EDU_BL |
840	    CMD_ERRCL_UCU),
841	CMD_TRAIN(CMD_ERRCL_L3_EDU_BL,	CMD_ERRCL_WDU | CMD_ERRCL_EDU_ST |
842	    CMD_ERRCL_EDU_BL | CMD_ERRCL_UCU),
843	CMD_TRAIN(CMD_ERRCL_L3_EDU_BL,	CMD_ERRCL_WDU | CMD_ERRCL_CPU |
844	    CMD_ERRCL_UCU),
845	CMD_TRAIN(CMD_ERRCL_L3_EDU_BL,	CMD_ERRCL_WDU | CMD_ERRCL_EDU_ST |
846	    CMD_ERRCL_CPU | CMD_ERRCL_UCU),
847	CMD_TRAIN(CMD_ERRCL_L3_EDU_BL,	CMD_ERRCL_WDU | CMD_ERRCL_EDU_BL |
848	    CMD_ERRCL_CPU | CMD_ERRCL_UCU),
849	CMD_TRAIN(CMD_ERRCL_L3_EDU_BL,	CMD_ERRCL_WDU | CMD_ERRCL_EDU_ST |
850	    CMD_ERRCL_EDU_BL | CMD_ERRCL_CPU | CMD_ERRCL_UCU),
851
852	/* L3_EDU: WDU+(zero or more of EDU, CPU, UCU)+L3_WDU */
853	CMD_TRAIN(CMD_ERRCL_L3_EDU_ST,	CMD_ERRCL_WDU | CMD_ERRCL_L3_WDU),
854	CMD_TRAIN(CMD_ERRCL_L3_EDU_ST,	CMD_ERRCL_WDU | CMD_ERRCL_EDU_ST |
855	    CMD_ERRCL_L3_WDU),
856	CMD_TRAIN(CMD_ERRCL_L3_EDU_ST,	CMD_ERRCL_WDU | CMD_ERRCL_EDU_BL |
857	    CMD_ERRCL_L3_WDU),
858	CMD_TRAIN(CMD_ERRCL_L3_EDU_ST,	CMD_ERRCL_WDU | CMD_ERRCL_EDU_ST |
859	    CMD_ERRCL_EDU_BL | CMD_ERRCL_L3_WDU),
860	CMD_TRAIN(CMD_ERRCL_L3_EDU_ST,	CMD_ERRCL_WDU | CMD_ERRCL_CPU |
861	    CMD_ERRCL_L3_WDU),
862	CMD_TRAIN(CMD_ERRCL_L3_EDU_ST,	CMD_ERRCL_WDU | CMD_ERRCL_UCU |
863	    CMD_ERRCL_L3_WDU),
864	CMD_TRAIN(CMD_ERRCL_L3_EDU_ST,	CMD_ERRCL_WDU | CMD_ERRCL_EDU_ST |
865	    CMD_ERRCL_CPU | CMD_ERRCL_L3_WDU),
866	CMD_TRAIN(CMD_ERRCL_L3_EDU_ST,	CMD_ERRCL_WDU | CMD_ERRCL_EDU_BL |
867	    CMD_ERRCL_CPU | 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_CPU | CMD_ERRCL_L3_WDU),
870	CMD_TRAIN(CMD_ERRCL_L3_EDU_ST,	CMD_ERRCL_WDU | CMD_ERRCL_EDU_ST |
871	    CMD_ERRCL_UCU | CMD_ERRCL_L3_WDU),
872	CMD_TRAIN(CMD_ERRCL_L3_EDU_ST,	CMD_ERRCL_WDU | CMD_ERRCL_EDU_BL |
873	    CMD_ERRCL_UCU | CMD_ERRCL_L3_WDU),
874	CMD_TRAIN(CMD_ERRCL_L3_EDU_ST,	CMD_ERRCL_WDU | CMD_ERRCL_EDU_ST |
875	    CMD_ERRCL_EDU_BL | CMD_ERRCL_UCU | CMD_ERRCL_L3_WDU),
876	CMD_TRAIN(CMD_ERRCL_L3_EDU_ST,	CMD_ERRCL_WDU | CMD_ERRCL_CPU |
877	    CMD_ERRCL_UCU | CMD_ERRCL_L3_WDU),
878	CMD_TRAIN(CMD_ERRCL_L3_EDU_ST,	CMD_ERRCL_WDU | CMD_ERRCL_EDU_ST |
879	    CMD_ERRCL_CPU | CMD_ERRCL_UCU | CMD_ERRCL_L3_WDU),
880	CMD_TRAIN(CMD_ERRCL_L3_EDU_ST,	CMD_ERRCL_WDU | CMD_ERRCL_EDU_BL |
881	    CMD_ERRCL_CPU | CMD_ERRCL_UCU | CMD_ERRCL_L3_WDU),
882	CMD_TRAIN(CMD_ERRCL_L3_EDU_ST,	CMD_ERRCL_WDU | CMD_ERRCL_EDU_ST |
883	    CMD_ERRCL_EDU_BL | CMD_ERRCL_CPU | CMD_ERRCL_UCU |
884	    CMD_ERRCL_L3_WDU),
885	CMD_TRAIN(CMD_ERRCL_L3_EDU_BL,	CMD_ERRCL_WDU | CMD_ERRCL_L3_WDU),
886	CMD_TRAIN(CMD_ERRCL_L3_EDU_BL,	CMD_ERRCL_WDU | CMD_ERRCL_EDU_ST |
887	    CMD_ERRCL_L3_WDU),
888	CMD_TRAIN(CMD_ERRCL_L3_EDU_BL,	CMD_ERRCL_WDU | CMD_ERRCL_EDU_BL |
889	    CMD_ERRCL_L3_WDU),
890	CMD_TRAIN(CMD_ERRCL_L3_EDU_BL,	CMD_ERRCL_WDU | CMD_ERRCL_EDU_ST |
891	    CMD_ERRCL_EDU_BL | CMD_ERRCL_L3_WDU),
892	CMD_TRAIN(CMD_ERRCL_L3_EDU_BL,	CMD_ERRCL_WDU | CMD_ERRCL_CPU |
893	    CMD_ERRCL_L3_WDU),
894	CMD_TRAIN(CMD_ERRCL_L3_EDU_BL,	CMD_ERRCL_WDU | CMD_ERRCL_UCU |
895	    CMD_ERRCL_L3_WDU),
896	CMD_TRAIN(CMD_ERRCL_L3_EDU_BL,	CMD_ERRCL_WDU | CMD_ERRCL_EDU_ST |
897	    CMD_ERRCL_CPU | CMD_ERRCL_L3_WDU),
898	CMD_TRAIN(CMD_ERRCL_L3_EDU_BL,	CMD_ERRCL_WDU | CMD_ERRCL_EDU_BL |
899	    CMD_ERRCL_CPU | 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_CPU | CMD_ERRCL_L3_WDU),
902	CMD_TRAIN(CMD_ERRCL_L3_EDU_BL,	CMD_ERRCL_WDU | CMD_ERRCL_EDU_ST |
903	    CMD_ERRCL_UCU | CMD_ERRCL_L3_WDU),
904	CMD_TRAIN(CMD_ERRCL_L3_EDU_BL,	CMD_ERRCL_WDU | CMD_ERRCL_EDU_BL |
905	    CMD_ERRCL_UCU | CMD_ERRCL_L3_WDU),
906	CMD_TRAIN(CMD_ERRCL_L3_EDU_BL,	CMD_ERRCL_WDU | CMD_ERRCL_EDU_ST |
907	    CMD_ERRCL_EDU_BL | CMD_ERRCL_UCU | CMD_ERRCL_L3_WDU),
908	CMD_TRAIN(CMD_ERRCL_L3_EDU_BL,	CMD_ERRCL_WDU | CMD_ERRCL_CPU |
909	    CMD_ERRCL_UCU | CMD_ERRCL_L3_WDU),
910	CMD_TRAIN(CMD_ERRCL_L3_EDU_BL,	CMD_ERRCL_WDU | CMD_ERRCL_EDU_ST |
911	    CMD_ERRCL_CPU | CMD_ERRCL_UCU | CMD_ERRCL_L3_WDU),
912	CMD_TRAIN(CMD_ERRCL_L3_EDU_BL,	CMD_ERRCL_WDU | CMD_ERRCL_EDU_BL |
913	    CMD_ERRCL_CPU | CMD_ERRCL_UCU | CMD_ERRCL_L3_WDU),
914	CMD_TRAIN(CMD_ERRCL_L3_EDU_BL,	CMD_ERRCL_WDU | CMD_ERRCL_EDU_ST |
915	    CMD_ERRCL_EDU_BL | CMD_ERRCL_CPU | CMD_ERRCL_UCU |
916	    CMD_ERRCL_L3_WDU),
917
918	/* L3_CPC: L3_WDC */
919	CMD_TRAIN(CMD_ERRCL_L3_CPC,	CMD_ERRCL_L3_WDC),
920
921	/* L3_CPC: L3_EDC+ WDC+(zero or more of EDC, CPC, UCC) */
922	CMD_TRAIN(CMD_ERRCL_L3_CPC,	CMD_ERRCL_L3_EDC | CMD_ERRCL_WDC),
923	CMD_TRAIN(CMD_ERRCL_L3_CPC,	CMD_ERRCL_L3_EDC | CMD_ERRCL_WDC |
924	    CMD_ERRCL_EDC),
925	CMD_TRAIN(CMD_ERRCL_L3_CPC,	CMD_ERRCL_L3_EDC | CMD_ERRCL_WDC |
926	    CMD_ERRCL_CPC),
927	CMD_TRAIN(CMD_ERRCL_L3_CPC,	CMD_ERRCL_L3_EDC | CMD_ERRCL_WDC |
928	    CMD_ERRCL_UCC),
929	CMD_TRAIN(CMD_ERRCL_L3_CPC,	CMD_ERRCL_L3_EDC | CMD_ERRCL_WDC |
930	    CMD_ERRCL_EDC | CMD_ERRCL_CPC),
931	CMD_TRAIN(CMD_ERRCL_L3_CPC,	CMD_ERRCL_L3_EDC | CMD_ERRCL_WDC |
932	    CMD_ERRCL_EDC | CMD_ERRCL_UCC),
933	CMD_TRAIN(CMD_ERRCL_L3_CPC,	CMD_ERRCL_L3_EDC | CMD_ERRCL_WDC |
934	    CMD_ERRCL_CPC | CMD_ERRCL_UCC),
935	CMD_TRAIN(CMD_ERRCL_L3_CPC,	CMD_ERRCL_L3_EDC | CMD_ERRCL_WDC |
936	    CMD_ERRCL_EDC | CMD_ERRCL_CPC | CMD_ERRCL_UCC),
937
938	/* L3_CPC: L3_UCC+WDC+(zero or more of EDC, CPC, UCC) */
939	CMD_TRAIN(CMD_ERRCL_L3_CPC,	CMD_ERRCL_L3_UCC | CMD_ERRCL_WDC),
940	CMD_TRAIN(CMD_ERRCL_L3_CPC,	CMD_ERRCL_L3_UCC | CMD_ERRCL_WDC |
941	    CMD_ERRCL_EDC),
942	CMD_TRAIN(CMD_ERRCL_L3_CPC,	CMD_ERRCL_L3_UCC | CMD_ERRCL_WDC |
943	    CMD_ERRCL_CPC),
944	CMD_TRAIN(CMD_ERRCL_L3_CPC,	CMD_ERRCL_L3_UCC | CMD_ERRCL_WDC |
945	    CMD_ERRCL_UCC),
946	CMD_TRAIN(CMD_ERRCL_L3_CPC,	CMD_ERRCL_L3_UCC | CMD_ERRCL_WDC |
947	    CMD_ERRCL_EDC | CMD_ERRCL_CPC),
948	CMD_TRAIN(CMD_ERRCL_L3_CPC,	CMD_ERRCL_L3_UCC | CMD_ERRCL_WDC |
949	    CMD_ERRCL_EDC | CMD_ERRCL_UCC),
950	CMD_TRAIN(CMD_ERRCL_L3_CPC,	CMD_ERRCL_L3_UCC | CMD_ERRCL_WDC |
951	    CMD_ERRCL_CPC | CMD_ERRCL_UCC),
952	CMD_TRAIN(CMD_ERRCL_L3_CPC,	CMD_ERRCL_L3_UCC | CMD_ERRCL_WDC |
953	    CMD_ERRCL_EDC | CMD_ERRCL_CPC | CMD_ERRCL_UCC),
954
955	/* L3_CPU: L3_WDU */
956	CMD_TRAIN(CMD_ERRCL_L3_CPU,	CMD_ERRCL_L3_WDU),
957
958	/* L3_CPU: L3_EDU+WDU+(zero or more of EDU, CPU, UCU) */
959	CMD_TRAIN(CMD_ERRCL_L3_CPU,	CMD_ERRCL_L3_EDU_ST | CMD_ERRCL_WDU),
960	CMD_TRAIN(CMD_ERRCL_L3_CPU,	CMD_ERRCL_L3_EDU_BL | CMD_ERRCL_WDU),
961	CMD_TRAIN(CMD_ERRCL_L3_CPU,	CMD_ERRCL_L3_EDU_ST |
962	    CMD_ERRCL_L3_EDU_BL | CMD_ERRCL_WDU),
963	CMD_TRAIN(CMD_ERRCL_L3_CPU,	CMD_ERRCL_L3_EDU_ST | CMD_ERRCL_WDU |
964	    CMD_ERRCL_EDU_ST),
965	CMD_TRAIN(CMD_ERRCL_L3_CPU,	CMD_ERRCL_L3_EDU_BL | CMD_ERRCL_WDU |
966	    CMD_ERRCL_EDU_ST),
967	CMD_TRAIN(CMD_ERRCL_L3_CPU,	CMD_ERRCL_L3_EDU_ST |
968	    CMD_ERRCL_L3_EDU_BL | CMD_ERRCL_WDU | CMD_ERRCL_EDU_ST),
969	CMD_TRAIN(CMD_ERRCL_L3_CPU,	CMD_ERRCL_L3_EDU_ST | CMD_ERRCL_WDU |
970	    CMD_ERRCL_EDU_BL),
971	CMD_TRAIN(CMD_ERRCL_L3_CPU,	CMD_ERRCL_L3_EDU_BL | CMD_ERRCL_WDU |
972	    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_BL),
975	CMD_TRAIN(CMD_ERRCL_L3_CPU,	CMD_ERRCL_L3_EDU_ST | CMD_ERRCL_WDU |
976	    CMD_ERRCL_EDU_ST | CMD_ERRCL_EDU_BL),
977	CMD_TRAIN(CMD_ERRCL_L3_CPU,	CMD_ERRCL_L3_EDU_BL | CMD_ERRCL_WDU |
978	    CMD_ERRCL_EDU_ST | CMD_ERRCL_EDU_BL),
979	CMD_TRAIN(CMD_ERRCL_L3_CPU,	CMD_ERRCL_L3_EDU_ST |
980	    CMD_ERRCL_L3_EDU_BL | CMD_ERRCL_WDU | CMD_ERRCL_EDU_ST |
981	    CMD_ERRCL_EDU_BL),
982	CMD_TRAIN(CMD_ERRCL_L3_CPU,	CMD_ERRCL_L3_EDU_ST | CMD_ERRCL_WDU |
983	    CMD_ERRCL_CPU),
984	CMD_TRAIN(CMD_ERRCL_L3_CPU,	CMD_ERRCL_L3_EDU_BL | CMD_ERRCL_WDU |
985	    CMD_ERRCL_CPU),
986	CMD_TRAIN(CMD_ERRCL_L3_CPU,	CMD_ERRCL_L3_EDU_ST |
987	    CMD_ERRCL_L3_EDU_BL | CMD_ERRCL_WDU | CMD_ERRCL_CPU),
988	CMD_TRAIN(CMD_ERRCL_L3_CPU,	CMD_ERRCL_L3_EDU_ST | CMD_ERRCL_WDU |
989	    CMD_ERRCL_UCU),
990	CMD_TRAIN(CMD_ERRCL_L3_CPU,	CMD_ERRCL_L3_EDU_BL | CMD_ERRCL_WDU |
991	    CMD_ERRCL_UCU),
992	CMD_TRAIN(CMD_ERRCL_L3_CPU,	CMD_ERRCL_L3_EDU_ST |
993	    CMD_ERRCL_L3_EDU_BL | CMD_ERRCL_WDU | CMD_ERRCL_UCU),
994	CMD_TRAIN(CMD_ERRCL_L3_CPU,	CMD_ERRCL_L3_EDU_ST | CMD_ERRCL_WDU |
995	    CMD_ERRCL_EDU_ST | CMD_ERRCL_CPU),
996	CMD_TRAIN(CMD_ERRCL_L3_CPU,	CMD_ERRCL_L3_EDU_BL | CMD_ERRCL_WDU |
997	    CMD_ERRCL_EDU_ST | CMD_ERRCL_CPU),
998	CMD_TRAIN(CMD_ERRCL_L3_CPU,	CMD_ERRCL_L3_EDU_ST |
999	    CMD_ERRCL_L3_EDU_BL | CMD_ERRCL_WDU | CMD_ERRCL_EDU_ST |
1000	    CMD_ERRCL_CPU),
1001	CMD_TRAIN(CMD_ERRCL_L3_CPU,	CMD_ERRCL_L3_EDU_ST | CMD_ERRCL_WDU |
1002	    CMD_ERRCL_EDU_BL | CMD_ERRCL_CPU),
1003	CMD_TRAIN(CMD_ERRCL_L3_CPU,	CMD_ERRCL_L3_EDU_BL | CMD_ERRCL_WDU |
1004	    CMD_ERRCL_EDU_BL | CMD_ERRCL_CPU),
1005	CMD_TRAIN(CMD_ERRCL_L3_CPU,	CMD_ERRCL_L3_EDU_ST |
1006	    CMD_ERRCL_L3_EDU_BL | CMD_ERRCL_WDU | CMD_ERRCL_EDU_BL |
1007	    CMD_ERRCL_CPU),
1008	CMD_TRAIN(CMD_ERRCL_L3_CPU,	CMD_ERRCL_L3_EDU_ST | CMD_ERRCL_WDU |
1009	    CMD_ERRCL_EDU_ST | CMD_ERRCL_EDU_BL | CMD_ERRCL_CPU),
1010	CMD_TRAIN(CMD_ERRCL_L3_CPU,	CMD_ERRCL_L3_EDU_BL | CMD_ERRCL_WDU |
1011	    CMD_ERRCL_EDU_ST | CMD_ERRCL_EDU_BL | CMD_ERRCL_CPU),
1012	CMD_TRAIN(CMD_ERRCL_L3_CPU,	CMD_ERRCL_L3_EDU_ST |
1013	    CMD_ERRCL_L3_EDU_BL | CMD_ERRCL_WDU | CMD_ERRCL_EDU_ST |
1014	    CMD_ERRCL_EDU_BL | CMD_ERRCL_CPU),
1015	CMD_TRAIN(CMD_ERRCL_L3_CPU,	CMD_ERRCL_L3_EDU_ST | CMD_ERRCL_WDU |
1016	    CMD_ERRCL_EDU_ST | CMD_ERRCL_UCU),
1017	CMD_TRAIN(CMD_ERRCL_L3_CPU,	CMD_ERRCL_L3_EDU_BL | CMD_ERRCL_WDU |
1018	    CMD_ERRCL_EDU_ST | CMD_ERRCL_UCU),
1019	CMD_TRAIN(CMD_ERRCL_L3_CPU,	CMD_ERRCL_L3_EDU_ST |
1020	    CMD_ERRCL_L3_EDU_BL | CMD_ERRCL_WDU | CMD_ERRCL_EDU_ST |
1021	    CMD_ERRCL_UCU),
1022	CMD_TRAIN(CMD_ERRCL_L3_CPU,	CMD_ERRCL_L3_EDU_ST | CMD_ERRCL_WDU |
1023	    CMD_ERRCL_EDU_BL | CMD_ERRCL_UCU),
1024	CMD_TRAIN(CMD_ERRCL_L3_CPU,	CMD_ERRCL_L3_EDU_BL | CMD_ERRCL_WDU |
1025	    CMD_ERRCL_EDU_BL | CMD_ERRCL_UCU),
1026	CMD_TRAIN(CMD_ERRCL_L3_CPU,	CMD_ERRCL_L3_EDU_ST |
1027	    CMD_ERRCL_L3_EDU_BL | CMD_ERRCL_WDU | CMD_ERRCL_EDU_BL |
1028	    CMD_ERRCL_UCU),
1029	CMD_TRAIN(CMD_ERRCL_L3_CPU,	CMD_ERRCL_L3_EDU_ST | CMD_ERRCL_WDU |
1030	    CMD_ERRCL_EDU_ST | CMD_ERRCL_EDU_BL | CMD_ERRCL_UCU),
1031	CMD_TRAIN(CMD_ERRCL_L3_CPU,	CMD_ERRCL_L3_EDU_BL | CMD_ERRCL_WDU |
1032	    CMD_ERRCL_EDU_ST | CMD_ERRCL_EDU_BL | CMD_ERRCL_UCU),
1033	CMD_TRAIN(CMD_ERRCL_L3_CPU,	CMD_ERRCL_L3_EDU_ST |
1034	    CMD_ERRCL_L3_EDU_BL | CMD_ERRCL_WDU | CMD_ERRCL_EDU_ST |
1035	    CMD_ERRCL_EDU_BL | CMD_ERRCL_UCU),
1036	CMD_TRAIN(CMD_ERRCL_L3_CPU,	CMD_ERRCL_L3_EDU_ST | CMD_ERRCL_WDU |
1037	    CMD_ERRCL_CPU | CMD_ERRCL_UCU),
1038	CMD_TRAIN(CMD_ERRCL_L3_CPU,	CMD_ERRCL_L3_EDU_BL | CMD_ERRCL_WDU |
1039	    CMD_ERRCL_CPU | CMD_ERRCL_UCU),
1040	CMD_TRAIN(CMD_ERRCL_L3_CPU,	CMD_ERRCL_L3_EDU_ST |
1041	    CMD_ERRCL_L3_EDU_BL | CMD_ERRCL_WDU | CMD_ERRCL_CPU |
1042	    CMD_ERRCL_UCU),
1043	CMD_TRAIN(CMD_ERRCL_L3_CPU,	CMD_ERRCL_L3_EDU_ST | CMD_ERRCL_WDU |
1044	    CMD_ERRCL_EDU_ST | CMD_ERRCL_CPU | CMD_ERRCL_UCU),
1045	CMD_TRAIN(CMD_ERRCL_L3_CPU,	CMD_ERRCL_L3_EDU_BL | CMD_ERRCL_WDU |
1046	    CMD_ERRCL_EDU_ST | CMD_ERRCL_CPU | CMD_ERRCL_UCU),
1047	CMD_TRAIN(CMD_ERRCL_L3_CPU,	CMD_ERRCL_L3_EDU_ST |
1048	    CMD_ERRCL_L3_EDU_BL | CMD_ERRCL_WDU | CMD_ERRCL_EDU_ST |
1049	    CMD_ERRCL_CPU | CMD_ERRCL_UCU),
1050	CMD_TRAIN(CMD_ERRCL_L3_CPU,	CMD_ERRCL_L3_EDU_ST | CMD_ERRCL_WDU |
1051	    CMD_ERRCL_EDU_BL | CMD_ERRCL_CPU | CMD_ERRCL_UCU),
1052	CMD_TRAIN(CMD_ERRCL_L3_CPU,	CMD_ERRCL_L3_EDU_BL | CMD_ERRCL_WDU |
1053	    CMD_ERRCL_EDU_BL | CMD_ERRCL_CPU | CMD_ERRCL_UCU),
1054	CMD_TRAIN(CMD_ERRCL_L3_CPU,	CMD_ERRCL_L3_EDU_ST |
1055	    CMD_ERRCL_L3_EDU_BL | CMD_ERRCL_WDU | CMD_ERRCL_EDU_BL |
1056	    CMD_ERRCL_CPU | CMD_ERRCL_UCU),
1057	CMD_TRAIN(CMD_ERRCL_L3_CPU,	CMD_ERRCL_L3_EDU_ST | CMD_ERRCL_WDU |
1058	    CMD_ERRCL_EDU_ST | CMD_ERRCL_EDU_BL | CMD_ERRCL_CPU |
1059	    CMD_ERRCL_UCU),
1060	CMD_TRAIN(CMD_ERRCL_L3_CPU,	CMD_ERRCL_L3_EDU_BL | CMD_ERRCL_WDU |
1061	    CMD_ERRCL_EDU_ST | CMD_ERRCL_EDU_BL | CMD_ERRCL_CPU |
1062	    CMD_ERRCL_UCU),
1063	CMD_TRAIN(CMD_ERRCL_L3_CPU,	CMD_ERRCL_L3_EDU_ST |
1064	    CMD_ERRCL_L3_EDU_BL | CMD_ERRCL_WDU | CMD_ERRCL_EDU_ST |
1065	    CMD_ERRCL_EDU_BL | CMD_ERRCL_CPU | CMD_ERRCL_UCU),
1066
1067	/* L3_CPU: L3_UCU+WDU+(zero or more of EDU, CPU, UCU) */
1068	CMD_TRAIN(CMD_ERRCL_L3_CPU,	CMD_ERRCL_L3_UCU | CMD_ERRCL_WDU),
1069	CMD_TRAIN(CMD_ERRCL_L3_CPU,	CMD_ERRCL_L3_UCU | CMD_ERRCL_WDU |
1070	    CMD_ERRCL_EDU_ST),
1071	CMD_TRAIN(CMD_ERRCL_L3_CPU,	CMD_ERRCL_L3_UCU | CMD_ERRCL_WDU |
1072	    CMD_ERRCL_EDU_BL),
1073	CMD_TRAIN(CMD_ERRCL_L3_CPU,	CMD_ERRCL_L3_UCU | CMD_ERRCL_WDU |
1074	    CMD_ERRCL_EDU_ST |CMD_ERRCL_EDU_BL),
1075	CMD_TRAIN(CMD_ERRCL_L3_CPU,	CMD_ERRCL_L3_UCU | CMD_ERRCL_WDU |
1076	    CMD_ERRCL_CPU),
1077	CMD_TRAIN(CMD_ERRCL_L3_CPU,	CMD_ERRCL_L3_UCU | CMD_ERRCL_WDU |
1078	    CMD_ERRCL_UCU),
1079	CMD_TRAIN(CMD_ERRCL_L3_CPU,	CMD_ERRCL_L3_UCU | CMD_ERRCL_WDU |
1080	    CMD_ERRCL_EDU_ST | CMD_ERRCL_CPU),
1081	CMD_TRAIN(CMD_ERRCL_L3_CPU,	CMD_ERRCL_L3_UCU | CMD_ERRCL_WDU |
1082	    CMD_ERRCL_EDU_BL | CMD_ERRCL_CPU),
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_CPU),
1085	CMD_TRAIN(CMD_ERRCL_L3_CPU,	CMD_ERRCL_L3_UCU | CMD_ERRCL_WDU |
1086	    CMD_ERRCL_EDU_ST | CMD_ERRCL_UCU),
1087	CMD_TRAIN(CMD_ERRCL_L3_CPU,	CMD_ERRCL_L3_UCU | CMD_ERRCL_WDU |
1088	    CMD_ERRCL_EDU_BL | CMD_ERRCL_UCU),
1089	CMD_TRAIN(CMD_ERRCL_L3_CPU,	CMD_ERRCL_L3_UCU | CMD_ERRCL_WDU |
1090	    CMD_ERRCL_EDU_ST | CMD_ERRCL_EDU_BL | CMD_ERRCL_UCU),
1091	CMD_TRAIN(CMD_ERRCL_L3_CPU,	CMD_ERRCL_L3_UCU | CMD_ERRCL_WDU |
1092	    CMD_ERRCL_CPU | CMD_ERRCL_UCU),
1093	CMD_TRAIN(CMD_ERRCL_L3_CPU,	CMD_ERRCL_L3_UCU | CMD_ERRCL_WDU |
1094	    CMD_ERRCL_EDU_ST | CMD_ERRCL_CPU | CMD_ERRCL_UCU),
1095	CMD_TRAIN(CMD_ERRCL_L3_CPU,	CMD_ERRCL_L3_UCU | CMD_ERRCL_WDU |
1096	    CMD_ERRCL_EDU_BL | CMD_ERRCL_CPU | CMD_ERRCL_UCU),
1097	CMD_TRAIN(CMD_ERRCL_L3_CPU,	CMD_ERRCL_L3_UCU | CMD_ERRCL_WDU |
1098	    CMD_ERRCL_EDU_ST | CMD_ERRCL_EDU_BL | CMD_ERRCL_CPU |
1099	    CMD_ERRCL_UCU),
1100
1101	/* L3_CPU: L3_EDU+WDU+(zero or more of EDU, CPU, UCU)+L3_WDU */
1102	CMD_TRAIN(CMD_ERRCL_L3_CPU,	CMD_ERRCL_L3_EDU_ST | CMD_ERRCL_WDU |
1103	    CMD_ERRCL_L3_WDU),
1104	CMD_TRAIN(CMD_ERRCL_L3_CPU,	CMD_ERRCL_L3_EDU_BL | CMD_ERRCL_WDU |
1105	    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_L3_WDU),
1108	CMD_TRAIN(CMD_ERRCL_L3_CPU,	CMD_ERRCL_L3_EDU_ST | CMD_ERRCL_WDU |
1109	    CMD_ERRCL_EDU_ST | CMD_ERRCL_L3_WDU),
1110	CMD_TRAIN(CMD_ERRCL_L3_CPU,	CMD_ERRCL_L3_EDU_BL | CMD_ERRCL_WDU |
1111	    CMD_ERRCL_EDU_ST | CMD_ERRCL_L3_WDU),
1112	CMD_TRAIN(CMD_ERRCL_L3_CPU,	CMD_ERRCL_L3_EDU_ST |
1113	    CMD_ERRCL_L3_EDU_BL | CMD_ERRCL_WDU | CMD_ERRCL_EDU_ST |
1114	    CMD_ERRCL_L3_WDU),
1115	CMD_TRAIN(CMD_ERRCL_L3_CPU,	CMD_ERRCL_L3_EDU_ST | CMD_ERRCL_WDU |
1116	    CMD_ERRCL_EDU_BL | CMD_ERRCL_L3_WDU),
1117	CMD_TRAIN(CMD_ERRCL_L3_CPU,	CMD_ERRCL_L3_EDU_BL | CMD_ERRCL_WDU |
1118	    CMD_ERRCL_EDU_BL | CMD_ERRCL_L3_WDU),
1119	CMD_TRAIN(CMD_ERRCL_L3_CPU,	CMD_ERRCL_L3_EDU_ST |
1120	    CMD_ERRCL_L3_EDU_BL | CMD_ERRCL_WDU | CMD_ERRCL_EDU_BL |
1121	    CMD_ERRCL_L3_WDU),
1122	CMD_TRAIN(CMD_ERRCL_L3_CPU,	CMD_ERRCL_L3_EDU_ST | CMD_ERRCL_WDU |
1123	    CMD_ERRCL_EDU_ST | CMD_ERRCL_EDU_BL | CMD_ERRCL_L3_WDU),
1124	CMD_TRAIN(CMD_ERRCL_L3_CPU,	CMD_ERRCL_L3_EDU_BL | CMD_ERRCL_WDU |
1125	    CMD_ERRCL_EDU_ST | CMD_ERRCL_EDU_BL | CMD_ERRCL_L3_WDU),
1126	CMD_TRAIN(CMD_ERRCL_L3_CPU,	CMD_ERRCL_L3_EDU_ST |
1127	    CMD_ERRCL_L3_EDU_BL | CMD_ERRCL_WDU | CMD_ERRCL_EDU_ST |
1128	    CMD_ERRCL_EDU_BL | CMD_ERRCL_L3_WDU),
1129	CMD_TRAIN(CMD_ERRCL_L3_CPU,	CMD_ERRCL_L3_EDU_ST | CMD_ERRCL_WDU |
1130	    CMD_ERRCL_CPU | CMD_ERRCL_L3_WDU),
1131	CMD_TRAIN(CMD_ERRCL_L3_CPU,	CMD_ERRCL_L3_EDU_BL | CMD_ERRCL_WDU |
1132	    CMD_ERRCL_CPU | CMD_ERRCL_L3_WDU),
1133	CMD_TRAIN(CMD_ERRCL_L3_CPU,	CMD_ERRCL_L3_EDU_ST |
1134	    CMD_ERRCL_L3_EDU_BL | CMD_ERRCL_WDU | CMD_ERRCL_CPU |
1135	    CMD_ERRCL_L3_WDU),
1136	CMD_TRAIN(CMD_ERRCL_L3_CPU,	CMD_ERRCL_L3_EDU_ST | CMD_ERRCL_WDU |
1137	    CMD_ERRCL_UCU | CMD_ERRCL_L3_WDU),
1138	CMD_TRAIN(CMD_ERRCL_L3_CPU,	CMD_ERRCL_L3_EDU_BL | CMD_ERRCL_WDU |
1139	    CMD_ERRCL_UCU | CMD_ERRCL_L3_WDU),
1140	CMD_TRAIN(CMD_ERRCL_L3_CPU,	CMD_ERRCL_L3_EDU_ST |
1141	    CMD_ERRCL_L3_EDU_BL | CMD_ERRCL_WDU | CMD_ERRCL_UCU |
1142	    CMD_ERRCL_L3_WDU),
1143	CMD_TRAIN(CMD_ERRCL_L3_CPU,	CMD_ERRCL_L3_EDU_ST | CMD_ERRCL_WDU |
1144	    CMD_ERRCL_EDU_ST | CMD_ERRCL_CPU | CMD_ERRCL_L3_WDU),
1145	CMD_TRAIN(CMD_ERRCL_L3_CPU,	CMD_ERRCL_L3_EDU_BL | CMD_ERRCL_WDU |
1146	    CMD_ERRCL_EDU_ST | CMD_ERRCL_CPU | CMD_ERRCL_L3_WDU),
1147	CMD_TRAIN(CMD_ERRCL_L3_CPU,	CMD_ERRCL_L3_EDU_ST |
1148	    CMD_ERRCL_L3_EDU_BL | CMD_ERRCL_WDU | CMD_ERRCL_EDU_ST |
1149	    CMD_ERRCL_CPU | CMD_ERRCL_L3_WDU),
1150	CMD_TRAIN(CMD_ERRCL_L3_CPU,	CMD_ERRCL_L3_EDU_ST | CMD_ERRCL_WDU |
1151	    CMD_ERRCL_EDU_BL | CMD_ERRCL_CPU | CMD_ERRCL_L3_WDU),
1152	CMD_TRAIN(CMD_ERRCL_L3_CPU,	CMD_ERRCL_L3_EDU_BL | CMD_ERRCL_WDU |
1153	    CMD_ERRCL_EDU_BL | CMD_ERRCL_CPU | CMD_ERRCL_L3_WDU),
1154	CMD_TRAIN(CMD_ERRCL_L3_CPU,	CMD_ERRCL_L3_EDU_ST |
1155	    CMD_ERRCL_L3_EDU_BL | CMD_ERRCL_WDU | CMD_ERRCL_EDU_BL |
1156	    CMD_ERRCL_CPU | CMD_ERRCL_L3_WDU),
1157	CMD_TRAIN(CMD_ERRCL_L3_CPU,	CMD_ERRCL_L3_EDU_ST | CMD_ERRCL_WDU |
1158	    CMD_ERRCL_EDU_ST | CMD_ERRCL_EDU_BL | CMD_ERRCL_CPU |
1159	    CMD_ERRCL_L3_WDU),
1160	CMD_TRAIN(CMD_ERRCL_L3_CPU,	CMD_ERRCL_L3_EDU_BL | CMD_ERRCL_WDU |
1161	    CMD_ERRCL_EDU_ST | CMD_ERRCL_EDU_BL | CMD_ERRCL_CPU |
1162	    CMD_ERRCL_L3_WDU),
1163	CMD_TRAIN(CMD_ERRCL_L3_CPU,	CMD_ERRCL_L3_EDU_ST |
1164	    CMD_ERRCL_L3_EDU_BL | CMD_ERRCL_WDU | CMD_ERRCL_EDU_ST |
1165	    CMD_ERRCL_EDU_BL | CMD_ERRCL_CPU | CMD_ERRCL_L3_WDU),
1166	CMD_TRAIN(CMD_ERRCL_L3_CPU,	CMD_ERRCL_L3_EDU_ST | CMD_ERRCL_WDU |
1167	    CMD_ERRCL_EDU_ST | CMD_ERRCL_UCU | CMD_ERRCL_L3_WDU),
1168	CMD_TRAIN(CMD_ERRCL_L3_CPU,	CMD_ERRCL_L3_EDU_BL | CMD_ERRCL_WDU |
1169	    CMD_ERRCL_EDU_ST | CMD_ERRCL_UCU | CMD_ERRCL_L3_WDU),
1170	CMD_TRAIN(CMD_ERRCL_L3_CPU,	CMD_ERRCL_L3_EDU_ST |
1171	    CMD_ERRCL_L3_EDU_BL | CMD_ERRCL_WDU | CMD_ERRCL_EDU_ST |
1172	    CMD_ERRCL_UCU | CMD_ERRCL_L3_WDU),
1173	CMD_TRAIN(CMD_ERRCL_L3_CPU,	CMD_ERRCL_L3_EDU_ST | CMD_ERRCL_WDU |
1174	    CMD_ERRCL_EDU_BL | CMD_ERRCL_UCU | CMD_ERRCL_L3_WDU),
1175	CMD_TRAIN(CMD_ERRCL_L3_CPU,	CMD_ERRCL_L3_EDU_BL | CMD_ERRCL_WDU |
1176	    CMD_ERRCL_EDU_BL | CMD_ERRCL_UCU | CMD_ERRCL_L3_WDU),
1177	CMD_TRAIN(CMD_ERRCL_L3_CPU,	CMD_ERRCL_L3_EDU_ST |
1178	    CMD_ERRCL_L3_EDU_BL | CMD_ERRCL_WDU | CMD_ERRCL_EDU_BL |
1179	    CMD_ERRCL_UCU | CMD_ERRCL_L3_WDU),
1180	CMD_TRAIN(CMD_ERRCL_L3_CPU,	CMD_ERRCL_L3_EDU_ST | CMD_ERRCL_WDU |
1181	    CMD_ERRCL_EDU_ST | CMD_ERRCL_EDU_BL | CMD_ERRCL_UCU |
1182	    CMD_ERRCL_L3_WDU),
1183	CMD_TRAIN(CMD_ERRCL_L3_CPU,	CMD_ERRCL_L3_EDU_BL | CMD_ERRCL_WDU |
1184	    CMD_ERRCL_EDU_ST | CMD_ERRCL_EDU_BL | CMD_ERRCL_UCU |
1185	    CMD_ERRCL_L3_WDU),
1186	CMD_TRAIN(CMD_ERRCL_L3_CPU,	CMD_ERRCL_L3_EDU_ST |
1187	    CMD_ERRCL_L3_EDU_BL | CMD_ERRCL_WDU | CMD_ERRCL_EDU_ST |
1188	    CMD_ERRCL_EDU_BL | CMD_ERRCL_UCU | CMD_ERRCL_L3_WDU),
1189	CMD_TRAIN(CMD_ERRCL_L3_CPU,	CMD_ERRCL_L3_EDU_ST | CMD_ERRCL_WDU |
1190	    CMD_ERRCL_CPU | CMD_ERRCL_UCU | CMD_ERRCL_L3_WDU),
1191	CMD_TRAIN(CMD_ERRCL_L3_CPU,	CMD_ERRCL_L3_EDU_BL | CMD_ERRCL_WDU |
1192	    CMD_ERRCL_CPU | CMD_ERRCL_UCU | CMD_ERRCL_L3_WDU),
1193	CMD_TRAIN(CMD_ERRCL_L3_CPU,	CMD_ERRCL_L3_EDU_ST |
1194	    CMD_ERRCL_L3_EDU_BL | CMD_ERRCL_WDU | CMD_ERRCL_CPU |
1195	    CMD_ERRCL_UCU | CMD_ERRCL_L3_WDU),
1196	CMD_TRAIN(CMD_ERRCL_L3_CPU,	CMD_ERRCL_L3_EDU_ST | CMD_ERRCL_WDU |
1197	    CMD_ERRCL_EDU_ST | CMD_ERRCL_CPU | CMD_ERRCL_UCU |
1198	    CMD_ERRCL_L3_WDU),
1199	CMD_TRAIN(CMD_ERRCL_L3_CPU,	CMD_ERRCL_L3_EDU_BL | CMD_ERRCL_WDU |
1200	    CMD_ERRCL_EDU_ST | CMD_ERRCL_CPU | CMD_ERRCL_UCU |
1201	    CMD_ERRCL_L3_WDU),
1202	CMD_TRAIN(CMD_ERRCL_L3_CPU,	CMD_ERRCL_L3_EDU_ST |
1203	    CMD_ERRCL_L3_EDU_BL | CMD_ERRCL_WDU | CMD_ERRCL_EDU_ST |
1204	    CMD_ERRCL_CPU | CMD_ERRCL_UCU | CMD_ERRCL_L3_WDU),
1205	CMD_TRAIN(CMD_ERRCL_L3_CPU,	CMD_ERRCL_L3_EDU_ST | CMD_ERRCL_WDU |
1206	    CMD_ERRCL_EDU_BL | CMD_ERRCL_CPU | CMD_ERRCL_UCU |
1207	    CMD_ERRCL_L3_WDU),
1208	CMD_TRAIN(CMD_ERRCL_L3_CPU,	CMD_ERRCL_L3_EDU_BL | CMD_ERRCL_WDU |
1209	    CMD_ERRCL_EDU_BL | CMD_ERRCL_CPU | CMD_ERRCL_UCU |
1210	    CMD_ERRCL_L3_WDU),
1211	CMD_TRAIN(CMD_ERRCL_L3_CPU,	CMD_ERRCL_L3_EDU_ST |
1212	    CMD_ERRCL_L3_EDU_BL | CMD_ERRCL_WDU | CMD_ERRCL_EDU_BL |
1213	    CMD_ERRCL_CPU | CMD_ERRCL_UCU | CMD_ERRCL_L3_WDU),
1214	CMD_TRAIN(CMD_ERRCL_L3_CPU,	CMD_ERRCL_L3_EDU_ST | CMD_ERRCL_WDU |
1215	    CMD_ERRCL_EDU_ST | CMD_ERRCL_EDU_BL | CMD_ERRCL_CPU |
1216	    CMD_ERRCL_UCU | CMD_ERRCL_L3_WDU),
1217	CMD_TRAIN(CMD_ERRCL_L3_CPU,	CMD_ERRCL_L3_EDU_BL | CMD_ERRCL_WDU |
1218	    CMD_ERRCL_EDU_ST | CMD_ERRCL_EDU_BL | CMD_ERRCL_CPU |
1219	    CMD_ERRCL_UCU | CMD_ERRCL_L3_WDU),
1220	CMD_TRAIN(CMD_ERRCL_L3_CPU,	CMD_ERRCL_L3_EDU_ST |
1221	    CMD_ERRCL_L3_EDU_BL | CMD_ERRCL_WDU | CMD_ERRCL_EDU_ST |
1222	    CMD_ERRCL_EDU_BL | CMD_ERRCL_CPU | CMD_ERRCL_UCU |
1223	    CMD_ERRCL_L3_WDU),
1224
1225	/* L3_CPU: L3_UCU+WDU+(zero or more of EDU, CPU, UCU)+L3_WDU */
1226	CMD_TRAIN(CMD_ERRCL_L3_CPU,	CMD_ERRCL_L3_UCU | CMD_ERRCL_WDU
1227	    | CMD_ERRCL_L3_WDU),
1228	CMD_TRAIN(CMD_ERRCL_L3_CPU,	CMD_ERRCL_L3_UCU | CMD_ERRCL_WDU |
1229	    CMD_ERRCL_EDU_ST | CMD_ERRCL_L3_WDU),
1230	CMD_TRAIN(CMD_ERRCL_L3_CPU,	CMD_ERRCL_L3_UCU | CMD_ERRCL_WDU |
1231	    CMD_ERRCL_EDU_BL | 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_EDU_BL | CMD_ERRCL_L3_WDU),
1234	CMD_TRAIN(CMD_ERRCL_L3_CPU,	CMD_ERRCL_L3_UCU | CMD_ERRCL_WDU |
1235	    CMD_ERRCL_CPU | CMD_ERRCL_L3_WDU),
1236	CMD_TRAIN(CMD_ERRCL_L3_CPU,	CMD_ERRCL_L3_UCU | CMD_ERRCL_WDU |
1237	    CMD_ERRCL_UCU | CMD_ERRCL_L3_WDU),
1238	CMD_TRAIN(CMD_ERRCL_L3_CPU,	CMD_ERRCL_L3_UCU | CMD_ERRCL_WDU |
1239	    CMD_ERRCL_EDU_ST | CMD_ERRCL_CPU | CMD_ERRCL_L3_WDU),
1240	CMD_TRAIN(CMD_ERRCL_L3_CPU,	CMD_ERRCL_L3_UCU | CMD_ERRCL_WDU |
1241	    CMD_ERRCL_EDU_BL | CMD_ERRCL_CPU | CMD_ERRCL_L3_WDU),
1242	CMD_TRAIN(CMD_ERRCL_L3_CPU,	CMD_ERRCL_L3_UCU | CMD_ERRCL_WDU |
1243	    CMD_ERRCL_EDU_ST | CMD_ERRCL_EDU_BL | CMD_ERRCL_CPU |
1244	    CMD_ERRCL_L3_WDU),
1245	CMD_TRAIN(CMD_ERRCL_L3_CPU,	CMD_ERRCL_L3_UCU | CMD_ERRCL_WDU |
1246	    CMD_ERRCL_EDU_ST | CMD_ERRCL_UCU | CMD_ERRCL_L3_WDU),
1247	CMD_TRAIN(CMD_ERRCL_L3_CPU,	CMD_ERRCL_L3_UCU | CMD_ERRCL_WDU |
1248	    CMD_ERRCL_EDU_BL | CMD_ERRCL_UCU | CMD_ERRCL_L3_WDU),
1249	CMD_TRAIN(CMD_ERRCL_L3_CPU,	CMD_ERRCL_L3_UCU | CMD_ERRCL_WDU |
1250	    CMD_ERRCL_EDU_ST | CMD_ERRCL_EDU_BL | CMD_ERRCL_UCU |
1251	    CMD_ERRCL_L3_WDU),
1252	CMD_TRAIN(CMD_ERRCL_L3_CPU,	CMD_ERRCL_L3_UCU | CMD_ERRCL_WDU |
1253	    CMD_ERRCL_CPU | CMD_ERRCL_UCU | 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_CPU | CMD_ERRCL_UCU |
1256	    CMD_ERRCL_L3_WDU),
1257	CMD_TRAIN(CMD_ERRCL_L3_CPU,	CMD_ERRCL_L3_UCU | CMD_ERRCL_WDU |
1258	    CMD_ERRCL_EDU_BL | CMD_ERRCL_CPU | CMD_ERRCL_UCU |
1259	    CMD_ERRCL_L3_WDU),
1260	CMD_TRAIN(CMD_ERRCL_L3_CPU,	CMD_ERRCL_L3_UCU | CMD_ERRCL_WDU |
1261	    CMD_ERRCL_EDU_ST | CMD_ERRCL_EDU_BL | CMD_ERRCL_CPU |
1262	    CMD_ERRCL_UCU | CMD_ERRCL_L3_WDU),
1263#else /* sun4u */
1264	CMD_TRAIN(CMD_ERRCL_LDAC,	CMD_ERRCL_LDWC),
1265	CMD_TRAIN(CMD_ERRCL_LDRC,	CMD_ERRCL_LDWC),
1266	CMD_TRAIN(CMD_ERRCL_LDSC,	CMD_ERRCL_LDWC),
1267	CMD_TRAIN(CMD_ERRCL_LDAU,	CMD_ERRCL_LDWU),
1268	CMD_TRAIN(CMD_ERRCL_LDRU,	CMD_ERRCL_LDWU),
1269	CMD_TRAIN(CMD_ERRCL_LDSU,	CMD_ERRCL_LDWU),
1270	/* SBDLC: SBDPC */
1271	CMD_TRAIN(CMD_ERRCL_SBDLC,	CMD_ERRCL_SBDPC),
1272	/* TCCP: TCCD */
1273	CMD_TRAIN(CMD_ERRCL_TCCP,	CMD_ERRCL_TCCD),
1274	/* TCCD: TCCD */
1275	CMD_TRAIN(CMD_ERRCL_TCCD,	CMD_ERRCL_TCCD),
1276#endif /* sun4u */
1277	CMD_TRAIN(0, 0)
1278};
1279
1280cmd_errcl_t
1281cmd_xxcu_train_match(cmd_errcl_t mask)
1282{
1283	int i;
1284
1285	for (i = 0; cmd_xxcu_trains[i].tr_mask != 0; i++) {
1286		if (cmd_xxcu_trains[i].tr_mask == mask)
1287			return (cmd_xxcu_trains[i].tr_cause);
1288	}
1289
1290	return (0);
1291}
1292/*
1293 * Search for the entry that matches the ena and the AFAR
1294 * if we have a valid AFAR, otherwise just match the ENA
1295 */
1296cmd_xxcu_trw_t *
1297cmd_trw_lookup(uint64_t ena, uint8_t afar_status, uint64_t afar)
1298{
1299	int i;
1300
1301	if (afar_status == AFLT_STAT_VALID) {
1302		for (i = 0; i < cmd.cmd_xxcu_ntrw; i++) {
1303			if (cmd.cmd_xxcu_trw[i].trw_ena == ena &&
1304			    cmd.cmd_xxcu_trw[i].trw_afar == afar)
1305				return (&cmd.cmd_xxcu_trw[i]);
1306		}
1307	} else  {
1308		for (i = 0; i < cmd.cmd_xxcu_ntrw; i++) {
1309		if (cmd.cmd_xxcu_trw[i].trw_ena == ena)
1310			return (&cmd.cmd_xxcu_trw[i]);
1311		}
1312	}
1313	return (NULL);
1314}
1315
1316cmd_xxcu_trw_t *
1317cmd_trw_alloc(uint64_t ena, uint64_t afar)
1318{
1319	int i;
1320
1321	for (i = 0; i < cmd.cmd_xxcu_ntrw; i++) {
1322		cmd_xxcu_trw_t *trw = &cmd.cmd_xxcu_trw[i];
1323		if (trw->trw_ena == NULL) {
1324			trw->trw_ena = ena;
1325			trw->trw_afar = afar;
1326			return (trw);
1327		}
1328	}
1329
1330	return (NULL);
1331}
1332
1333void
1334cmd_trw_write(fmd_hdl_t *hdl)
1335{
1336	fmd_buf_write(hdl, NULL, "waiters", cmd.cmd_xxcu_trw,
1337	    cmd.cmd_xxcu_ntrw * sizeof (cmd_xxcu_trw_t));
1338}
1339
1340/*ARGSUSED*/
1341void
1342cmd_trw_ref(fmd_hdl_t *hdl, cmd_xxcu_trw_t *trw, cmd_errcl_t clcode)
1343{
1344	trw->trw_ref++;
1345	trw->trw_mask |= clcode;
1346	cmd_trw_write(hdl);
1347}
1348
1349void
1350cmd_trw_deref(fmd_hdl_t *hdl, cmd_xxcu_trw_t *trw)
1351{
1352	if (trw->trw_ref == 0)
1353		fmd_hdl_abort(hdl, "attempt to deref trw with zero ref\n");
1354
1355	if (--trw->trw_ref == 0)
1356		bzero(trw, sizeof (cmd_xxcu_trw_t));
1357
1358	cmd_trw_write(hdl);
1359}
1360
1361void
1362cmd_trw_restore(fmd_hdl_t *hdl)
1363{
1364	size_t sz;
1365
1366	if ((sz = fmd_buf_size(hdl, NULL, "waiters")) != 0) {
1367		uint_t ntrw = sz / sizeof (cmd_xxcu_trw_t);
1368
1369		if (sz % sizeof (cmd_xxcu_trw_t) != 0) {
1370			fmd_hdl_abort(hdl, "waiters array isn't of "
1371			    "correct size\n");
1372		}
1373
1374		/*
1375		 * If the existing buffer is larger than our tuned size,
1376		 * we'll only read as many as will fit.
1377		 */
1378		if (ntrw > cmd.cmd_xxcu_ntrw)
1379			ntrw = cmd.cmd_xxcu_ntrw;
1380
1381		fmd_buf_read(hdl, NULL, "waiters", cmd.cmd_xxcu_trw,
1382		    ntrw * sizeof (cmd_xxcu_trw_t));
1383
1384		if (ntrw * sizeof (cmd_xxcu_trw_t) != sz) {
1385			fmd_buf_destroy(hdl, NULL, "waiters");
1386			fmd_buf_write(hdl, NULL, "waiters", cmd.cmd_xxcu_trw,
1387			    ntrw * sizeof (cmd_xxcu_trw_t));
1388		}
1389	}
1390}
1391
1392char *
1393cmd_cpu_serdnm_create(fmd_hdl_t *hdl, cmd_cpu_t *cpu, const char *serdbase)
1394{
1395	char *nm;
1396	const char *fmt;
1397	size_t sz;
1398	if (cpu->cpu_level == CMD_CPU_LEVEL_THREAD) {
1399		fmt = "cpu_%d_%s_serd";
1400		sz = snprintf(NULL, 0, fmt, cpu->cpu_cpuid, serdbase) + 1;
1401		nm = fmd_hdl_alloc(hdl, sz, FMD_SLEEP);
1402		(void) snprintf(nm, sz, fmt, cpu->cpu_cpuid, serdbase);
1403	} else {
1404		fmt = "cpu_%d_%d_%s_serd";
1405		sz = snprintf(NULL, 0, fmt, cpu->cpu_cpuid, cpu->cpu_level,
1406		    serdbase) + 1;
1407		nm = fmd_hdl_alloc(hdl, sz, FMD_SLEEP);
1408		(void) snprintf(nm, sz, fmt, cpu->cpu_cpuid, cpu->cpu_level,
1409		    serdbase);
1410	}
1411
1412	return (nm);
1413}
1414
1415/*
1416 * cmd_cpu_create_faultlist is a combination of the former cmd_cpu_create_fault
1417 * and fmd_case_add_suspect.  If a 'cpu' structure represents a set of threads
1418 * (level > CMD_CPU_LEVEL_THREAD), then we must add multiple faults to
1419 * this case, under loop control.  Use call to cmd_cpu_create_faultlist to
1420 * replace the sequence
1421 *
1422 *	flt = cmd_cpu_create_fault(...);
1423 *	fmd_case_add_suspect(hdl, cc->cp, flt);
1424 */
1425
1426void
1427cmd_cpu_create_faultlist(fmd_hdl_t *hdl, fmd_case_t *casep, cmd_cpu_t *cpu,
1428    const char *type, nvlist_t *rsrc, uint_t cert)
1429{
1430	char fltnm[64];
1431	uint32_t cpuinit, cpufinal, cpustep, i;
1432	nvlist_t *flt;
1433
1434	(void) snprintf(fltnm, sizeof (fltnm), "fault.cpu.%s.%s",
1435	    cpu_type2name(hdl, cpu->cpu_type), type);
1436
1437	cpu->cpu_faulting = FMD_B_TRUE;
1438	cpu_buf_write(hdl, cpu);
1439
1440	if (cpu->cpu_level > CMD_CPU_LEVEL_THREAD) {
1441		core2cpus(cpu->cpu_cpuid, cpu->cpu_type, cpu->cpu_level,
1442		    &cpuinit, &cpufinal, &cpustep);
1443		for (i = cpuinit; i <= cpufinal; i += cpustep) {
1444			cmd_cpu_t *cpui = cpu_lookup_by_cpuid(i,
1445			    CMD_CPU_LEVEL_THREAD);
1446			if (cpui == NULL) {
1447				nvlist_t *asru;
1448				if (nvlist_dup(cpu->cpu_asru_nvl,
1449				    &asru, 0) != 0) {
1450					fmd_hdl_abort(hdl, "unable to alloc"
1451					    "ASRU for thread in core\n");
1452				}
1453				(void) nvlist_remove_all(asru,
1454				    FM_FMRI_CPU_ID);
1455				if (nvlist_add_uint32(asru,
1456				    FM_FMRI_CPU_ID, i) != 0) {
1457					fmd_hdl_abort(hdl,
1458					    "unable to create thread struct\n");
1459				}
1460				cpui = cpu_create(hdl, asru, i,
1461				    CMD_CPU_LEVEL_THREAD, cpu->cpu_type);
1462				nvlist_free(asru);
1463			}
1464			cpui->cpu_faulting = FMD_B_TRUE;
1465			cpu_buf_write(hdl, cpui);
1466			flt = fmd_nvl_create_fault(hdl, fltnm, cert,
1467			    cpui->cpu_asru_nvl, cpu->cpu_fru_nvl, rsrc);
1468#ifdef sun4v
1469			flt = cmd_fault_add_location(hdl, flt, "MB");
1470#endif /* sun4v */
1471			fmd_case_add_suspect(hdl, casep, flt);
1472		}
1473	} else {
1474		flt = fmd_nvl_create_fault(hdl, fltnm, cert,
1475		    cpu->cpu_asru_nvl, cpu->cpu_fru_nvl, rsrc);
1476#ifdef sun4v
1477		flt = cmd_fault_add_location(hdl, flt, "MB");
1478#endif /* sun4v */
1479		fmd_case_add_suspect(hdl, casep, flt);
1480	}
1481}
1482
1483static void
1484cmd_cpu_free(fmd_hdl_t *hdl, cmd_cpu_t *cpu, int destroy)
1485{
1486	int i;
1487
1488	for (i = 0; i < sizeof (cmd_cpu_cases_t) / sizeof (cmd_case_t); i++) {
1489		cmd_case_t *cc = &(((cmd_case_t *)&cpu->cpu_cases)[i]);
1490
1491		if (cc->cc_cp != NULL) {
1492			cmd_case_fini(hdl, cc->cc_cp, destroy);
1493			if (cc->cc_serdnm != NULL) {
1494				if (fmd_serd_exists(hdl, cc->cc_serdnm) &&
1495				    destroy)
1496					fmd_serd_destroy(hdl, cc->cc_serdnm);
1497				fmd_hdl_strfree(hdl, cc->cc_serdnm);
1498			}
1499		}
1500	}
1501
1502#ifdef sun4u
1503	cpu_uec_free(hdl, &cpu->cpu_uec, destroy);
1504	cpu_uec_free(hdl, &cpu->cpu_olduec, destroy);
1505#endif /* sun4u */
1506
1507	cmd_fmri_fini(hdl, &cpu->cpu_asru, destroy);
1508	cmd_fmri_fini(hdl, &cpu->cpu_fru, destroy);
1509
1510	cmd_list_delete(&cmd.cmd_cpus, cpu);
1511
1512	if (destroy)
1513		fmd_buf_destroy(hdl, NULL, cpu->cpu_bufname);
1514	fmd_hdl_free(hdl, cpu, sizeof (cmd_cpu_t));
1515}
1516
1517void
1518cmd_cpu_destroy(fmd_hdl_t *hdl, cmd_cpu_t *cpu)
1519{
1520	cmd_cpu_free(hdl, cpu, FMD_B_TRUE);
1521}
1522
1523static cmd_cpu_t *
1524cpu_lookup_by_cpuid(uint32_t cpuid, uint8_t level)
1525{
1526	cmd_cpu_t *cpu;
1527
1528	for (cpu = cmd_list_next(&cmd.cmd_cpus); cpu != NULL;
1529	    cpu = cmd_list_next(cpu)) {
1530		if ((cpu->cpu_cpuid == cpuid) &&
1531		    (cpu->cpu_level == level))
1532			return (cpu);
1533	}
1534
1535	return (NULL);
1536}
1537
1538static nvlist_t *
1539cpu_getfru(fmd_hdl_t *hdl, cmd_cpu_t *cp)
1540{
1541	char *frustr, *partstr, *serialstr;
1542	nvlist_t *nvlp;
1543
1544	if ((frustr = cmd_cpu_getfrustr(hdl, cp)) == NULL) {
1545		return (NULL);
1546	}
1547	partstr = cmd_cpu_getpartstr(hdl, cp);
1548	serialstr = cmd_cpu_getserialstr(hdl, cp);
1549	nvlp = cmd_cpu_mkfru(frustr, serialstr, partstr);
1550	fmd_hdl_strfree(hdl, frustr);
1551	fmd_hdl_strfree(hdl, partstr);
1552	fmd_hdl_strfree(hdl, serialstr);
1553
1554	return (nvlp);
1555}
1556
1557static void
1558cpu_buf_write(fmd_hdl_t *hdl, cmd_cpu_t *cpu)
1559{
1560	if (fmd_buf_size(hdl, NULL, cpu->cpu_bufname) !=
1561	    sizeof (cmd_cpu_pers_t))
1562		fmd_buf_destroy(hdl, NULL, cpu->cpu_bufname);
1563
1564	fmd_buf_write(hdl, NULL, cpu->cpu_bufname, &cpu->cpu_pers,
1565	    sizeof (cmd_cpu_pers_t));
1566}
1567
1568static void
1569cpu_buf_create(fmd_hdl_t *hdl, cmd_cpu_t *cpu)
1570{
1571	size_t sz;
1572
1573	/*
1574	 * We need to be tolerant of leaked CPU buffers, as their effects can
1575	 * be severe.  Consider the following scenario: we create a version 0
1576	 * cmd_cpu_t in response to some error, commit it to a persistent
1577	 * buffer, and then leak it.  We then upgrade, and restart the DE using
1578	 * version 1 cmd_cpu_t's.  Another error comes along, for the same CPU
1579	 * whose struct was leaked.  Not knowing about the leaked buffer, we
1580	 * create a new cmd_cpu_t for that CPU, and create a buffer for it.  As
1581	 * the v1 cmd_cpu_t is smaller than the v0 cmd_cpu_t, fmd will use the
1582	 * pre-existing (leaked) buffer.  We'll therefore have an x-byte, v1
1583	 * cmd_cpu_t in a y-byte buffer, where y > x.  Upon the next DE restart,
1584	 * we'll attempt to restore the cmd_cpu_t, but will do version
1585	 * validation using the size of the buffer (y).  This won't match what
1586	 * we're expecting (x), and the DE will abort.
1587	 *
1588	 * To protect against such a scenario, we're going to check for and
1589	 * remove the pre-existing cmd_cpu_t for this CPU, if one exists.  While
1590	 * this won't fix the leak, it'll allow us to continue functioning
1591	 * properly in spite of it.
1592	 */
1593	if ((sz = fmd_buf_size(hdl, NULL, cpu->cpu_bufname)) != 0 &&
1594	    sz != sizeof (cmd_cpu_pers_t)) {
1595		fmd_hdl_debug(hdl, "removing unexpected pre-existing cpu "
1596		    "buffer %s (size %u bytes)\n", cpu->cpu_bufname, sz);
1597		fmd_buf_destroy(hdl, NULL, cpu->cpu_bufname);
1598	}
1599
1600	cpu_buf_write(hdl, cpu);
1601}
1602
1603static cmd_cpu_t *
1604cpu_create(fmd_hdl_t *hdl, nvlist_t *asru, uint32_t cpuid, uint8_t level,
1605    cmd_cpu_type_t type)
1606{
1607	cmd_cpu_t *cpu;
1608	nvlist_t *fru;
1609
1610	/*
1611	 * No CPU state matches the CPU described in the ereport.  Create a new
1612	 * one, add it to the list, and pass it back.
1613	 */
1614	fmd_hdl_debug(hdl, "cpu_lookup: creating new cpuid %u\n", cpuid);
1615	CMD_STAT_BUMP(cpu_creat);
1616
1617	cpu = fmd_hdl_zalloc(hdl, sizeof (cmd_cpu_t), FMD_SLEEP);
1618	cpu->cpu_nodetype = CMD_NT_CPU;
1619	cpu->cpu_cpuid = cpuid;
1620	cpu->cpu_level = level;
1621	cpu->cpu_type = type;
1622	cpu->cpu_version = CMD_CPU_VERSION;
1623
1624	if (cpu->cpu_level > CMD_CPU_LEVEL_THREAD) {
1625		cmd_bufname(cpu->cpu_bufname, sizeof (cpu->cpu_bufname),
1626		    "cpu_%d", cpu->cpu_cpuid);
1627	} else {
1628		cmd_bufname(cpu->cpu_bufname, sizeof (cpu->cpu_bufname),
1629		    "cpu_%d_%d", cpu->cpu_cpuid, cpu->cpu_level);
1630	}
1631
1632#ifdef sun4u
1633	cpu_uec_create(hdl, cpu, &cpu->cpu_uec, "cpu_uec_%d", cpu->cpu_cpuid);
1634	cpu_uec_create(hdl, cpu, &cpu->cpu_olduec, "cpu_olduec_%d",
1635	    cpu->cpu_cpuid);
1636#endif /* sun4u */
1637
1638	cmd_fmri_init(hdl, &cpu->cpu_asru, asru, "cpu_asru_%d", cpu->cpu_cpuid);
1639
1640	if ((fru = cpu_getfru(hdl, cpu)) != NULL) {
1641		cmd_fmri_init(hdl, &cpu->cpu_fru, fru, "cpu_fru_%d",
1642		    cpu->cpu_cpuid);
1643		nvlist_free(fru);
1644	} else {
1645		cmd_fmri_init(hdl, &cpu->cpu_fru, asru, "cpu_fru_%d",
1646		    cpu->cpu_cpuid);
1647	}
1648
1649	cpu_buf_create(hdl, cpu);
1650
1651	cmd_list_append(&cmd.cmd_cpus, cpu);
1652
1653	return (cpu);
1654}
1655
1656/*
1657 * As its name implies, 'cpu_all_threads_invalid' determines if all cpu
1658 * threads (level 0) contained within the cpu structure are invalid.
1659 * This is done by checking all the (level 0) threads which may be
1660 * contained within this chip, core, or thread; if all are invalid, return
1661 * FMD_B_TRUE; if any are valid, return FMD_B_FALSE.
1662 */
1663
1664int
1665cpu_all_threads_invalid(fmd_hdl_t *hdl, cmd_cpu_t *cpu)
1666{
1667	nvlist_t *asru;
1668	uint32_t cpuinit, cpufinal, cpustep, i;
1669
1670	core2cpus(cpu->cpu_cpuid, cpu->cpu_type, cpu->cpu_level,
1671	    &cpuinit, &cpufinal, &cpustep);
1672
1673	if (cpuinit == cpufinal) {
1674		if (fmd_nvl_fmri_present(hdl, cpu->cpu_asru_nvl) &&
1675		    !fmd_nvl_fmri_unusable(hdl, cpu->cpu_asru_nvl))
1676			return (FMD_B_FALSE);
1677		else return (FMD_B_TRUE);
1678	} else {
1679
1680		if (nvlist_dup(cpu->cpu_asru_nvl, &asru, 0) != 0)
1681			fmd_hdl_abort(hdl, "cannot copy asru\n");
1682		for (i = cpuinit; i <= cpufinal; i += cpustep) {
1683			(void) nvlist_remove_all(asru, FM_FMRI_CPU_ID);
1684			if (nvlist_add_uint32(asru, FM_FMRI_CPU_ID, i) != 0) {
1685				fmd_hdl_abort(hdl, "cpu_all_threads_invalid: ",
1686				    "cannot add thread %d to asru\n", i);
1687			}
1688			if (fmd_nvl_fmri_present(hdl, asru) &&
1689			    !fmd_nvl_fmri_unusable(hdl, asru)) {
1690				nvlist_free(asru);
1691				return (FMD_B_FALSE);
1692			}
1693		}
1694	}
1695	nvlist_free(asru);
1696	return (FMD_B_TRUE);
1697}
1698
1699/*
1700 * Locate the state structure for this CPU, creating a new one if one doesn't
1701 * already exist.  Before passing it back, we also need to validate it against
1702 * the current state of the world, checking to ensure that the CPU described by
1703 * the ereport, the CPU indicated in the cmd_cpu_t, and the CPU currently
1704 * residing at the indicated cpuid are the same.  We do this by comparing the
1705 * serial IDs from the three entities.
1706 */
1707cmd_cpu_t *
1708cmd_cpu_lookup(fmd_hdl_t *hdl, nvlist_t *asru, const char *class,
1709    uint8_t level)
1710{
1711	cmd_cpu_t *cpu;
1712	uint8_t vers;
1713	const char *scheme, *cpuname;
1714	uint32_t cpuid;
1715	cmd_cpu_type_t ct;
1716
1717	if (fmd_nvl_fmri_expand(hdl, asru) < 0) {
1718		CMD_STAT_BUMP(bad_cpu_asru);
1719		return (NULL);
1720	}
1721
1722	if (nvlist_lookup_pairs(asru, 0,
1723	    FM_VERSION, DATA_TYPE_UINT8, &vers,
1724	    FM_FMRI_SCHEME, DATA_TYPE_STRING, &scheme,
1725	    FM_FMRI_CPU_ID, DATA_TYPE_UINT32, &cpuid,
1726	    NULL) != 0 || (vers != CPU_SCHEME_VERSION0 &&
1727	    vers != CPU_SCHEME_VERSION1) ||
1728	    strcmp(scheme, FM_FMRI_SCHEME_CPU) != 0) {
1729		CMD_STAT_BUMP(bad_cpu_asru);
1730		return (NULL);
1731	}
1732
1733	/*
1734	 * 'cpuid' at this point refers to a thread, because it
1735	 * was extracted from a detector FMRI
1736	 */
1737
1738	cpuname = class + sizeof ("ereport.cpu");
1739	ct = cpu_nname2type(hdl, cpuname,
1740	    (size_t)(strchr(cpuname, '.') - cpuname));
1741
1742	cpu = cpu_lookup_by_cpuid(cmd_cpu2core(cpuid, ct, level), level);
1743
1744	if (cpu != NULL &&
1745	    cpu_all_threads_invalid(hdl, cpu) == FMD_B_TRUE) {
1746		fmd_hdl_debug(hdl, "cpu_lookup: discarding old state\n");
1747		cmd_cpu_destroy(hdl, cpu);
1748		cpu = NULL;
1749	}
1750
1751	/*
1752	 * Check to see if the CPU described by the ereport has been removed
1753	 * from the system.  If it has, return to the caller without a CPU.
1754	 */
1755	if (!fmd_nvl_fmri_present(hdl, asru) ||
1756	    fmd_nvl_fmri_unusable(hdl, asru)) {
1757		fmd_hdl_debug(hdl, "cpu_lookup: discarding old ereport\n");
1758		return (NULL);
1759	}
1760
1761	if (cpu == NULL) {
1762		cpu = cpu_create(hdl, asru,
1763		    cmd_cpu2core(cpuid, ct, level), level, ct);
1764	}
1765
1766	return (cpu);
1767}
1768
1769cmd_cpu_t *
1770cmd_cpu_lookup_from_detector(fmd_hdl_t *hdl, nvlist_t *nvl, const char *class,
1771    uint8_t level)
1772{
1773	nvlist_t *det;
1774
1775	(void) nvlist_lookup_nvlist(nvl, FM_EREPORT_DETECTOR, &det);
1776
1777	return (cmd_cpu_lookup(hdl, det, class, level));
1778}
1779
1780static cmd_cpu_t *
1781cpu_v0tov3(fmd_hdl_t *hdl, cmd_cpu_0_t *old, size_t oldsz)
1782{
1783	cmd_cpu_t *new;
1784
1785	if (oldsz != sizeof (cmd_cpu_0_t)) {
1786		fmd_hdl_abort(hdl, "size of state doesn't match size of "
1787		    "version 0 state (%u bytes).\n", sizeof (cmd_cpu_0_t));
1788	}
1789
1790	new = fmd_hdl_zalloc(hdl, sizeof (cmd_cpu_t), FMD_SLEEP);
1791	new->cpu_header = old->cpu0_header;
1792	new->cpu_version = CMD_CPU_VERSION;
1793	new->cpu_cpuid = old->cpu0_cpuid;
1794	new->cpu_type = old->cpu0_type;
1795	new->cpu_faulting = old->cpu0_faulting;
1796	new->cpu_level = CMD_CPU_LEVEL_THREAD;
1797	new->cpu_asru = old->cpu0_asru;
1798	new->cpu_fru = old->cpu0_fru;
1799	new->cpu_uec = old->cpu0_uec;
1800	new->cpu_olduec = old->cpu0_olduec;
1801
1802	fmd_hdl_free(hdl, old, oldsz);
1803	return (new);
1804}
1805
1806static cmd_cpu_t *
1807cpu_v1tov3(fmd_hdl_t *hdl, cmd_cpu_1_t *old, size_t oldsz)
1808{
1809	cmd_cpu_t *new;
1810
1811	if (oldsz != sizeof (cmd_cpu_1_t)) {
1812		fmd_hdl_abort(hdl, "size of state doesn't match size of "
1813		    "version 1 state (%u bytes).\n", sizeof (cmd_cpu_1_t));
1814	}
1815
1816	new = fmd_hdl_zalloc(hdl, sizeof (cmd_cpu_t), FMD_SLEEP);
1817	new->cpu_header = old->cpu1_header;
1818	new->cpu_version = CMD_CPU_VERSION;
1819	new->cpu_cpuid = old->cpu1_cpuid;
1820	new->cpu_type = old->cpu1_type;
1821	new->cpu_faulting = old->cpu1_faulting;
1822	new->cpu_level = CMD_CPU_LEVEL_THREAD;
1823	new->cpu_asru = old->cpu1_asru;
1824	new->cpu_fru = old->cpu1_fru;
1825	new->cpu_uec = old->cpu1_uec;
1826	new->cpu_olduec = old->cpu1_olduec;
1827
1828	fmd_hdl_free(hdl, old, oldsz);
1829	return (new);
1830}
1831
1832static cmd_cpu_t *
1833cpu_v2tov3(fmd_hdl_t *hdl, cmd_cpu_2_t *old, size_t oldsz)
1834{
1835	cmd_cpu_t *new;
1836
1837	if (oldsz != sizeof (cmd_cpu_2_t)) {
1838		fmd_hdl_abort(hdl, "size of state doesn't match size of "
1839		    "version 2 state (%u bytes).\n", sizeof (cmd_cpu_2_t));
1840	}
1841
1842	new = fmd_hdl_zalloc(hdl, sizeof (cmd_cpu_t), FMD_SLEEP);
1843
1844	new->cpu_header = old->cpu2_header;
1845	new->cpu_cpuid = old->cpu2_cpuid;
1846	new->cpu_type = old->cpu2_type;
1847	new->cpu_faulting = old->cpu2_faulting;
1848	new->cpu_asru = old->cpu2_asru;
1849	new->cpu_fru = old->cpu2_fru;
1850	new->cpu_uec = old->cpu2_uec;
1851	new->cpu_olduec = old->cpu2_olduec;
1852	new->cpu_version = CMD_CPU_VERSION;
1853	new->cpu_level = CMD_CPU_LEVEL_THREAD;
1854	fmd_hdl_free(hdl, old, oldsz);
1855	return (new);
1856}
1857
1858static cmd_cpu_t *
1859cpu_wrapv3(fmd_hdl_t *hdl, cmd_cpu_pers_t *pers, size_t psz)
1860{
1861	cmd_cpu_t *cpu;
1862
1863	if (psz != sizeof (cmd_cpu_pers_t)) {
1864		fmd_hdl_abort(hdl, "size of state doesn't match size of "
1865		    "version 3 state (%u bytes).\n", sizeof (cmd_cpu_pers_t));
1866	}
1867
1868	cpu = fmd_hdl_zalloc(hdl, sizeof (cmd_cpu_t), FMD_SLEEP);
1869	bcopy(pers, cpu, sizeof (cmd_cpu_pers_t));
1870	fmd_hdl_free(hdl, pers, psz);
1871	return (cpu);
1872}
1873
1874static void
1875cpu_case_restore(fmd_hdl_t *hdl, cmd_cpu_t *cpu, cmd_case_t *cc, fmd_case_t *cp,
1876    const char *serdbase)
1877{
1878	cmd_case_restore(hdl, cc, cp, cmd_cpu_serdnm_create(hdl, cpu,
1879	    serdbase));
1880}
1881
1882void *
1883cmd_cpu_restore(fmd_hdl_t *hdl, fmd_case_t *cp, cmd_case_ptr_t *ptr)
1884{
1885	cmd_cpu_t *cpu;
1886
1887	for (cpu = cmd_list_next(&cmd.cmd_cpus); cpu != NULL;
1888	    cpu = cmd_list_next(cpu)) {
1889		if (strcmp(cpu->cpu_bufname, ptr->ptr_name) == 0)
1890			break;
1891	}
1892
1893	if (cpu == NULL) {
1894		int migrated = 0;
1895		size_t cpusz;
1896
1897		fmd_hdl_debug(hdl, "restoring cpu from %s\n", ptr->ptr_name);
1898
1899		if ((cpusz = fmd_buf_size(hdl, NULL, ptr->ptr_name)) == 0) {
1900			fmd_hdl_abort(hdl, "cpu referenced by case %s does "
1901			    "not exist in saved state\n",
1902			    fmd_case_uuid(hdl, cp));
1903		} else if (cpusz > CMD_CPU_MAXSIZE || cpusz < CMD_CPU_MINSIZE) {
1904			fmd_hdl_abort(hdl, "cpu buffer referenced by case %s "
1905			    "is out of bounds (is %u bytes)\n",
1906			    fmd_case_uuid(hdl, cp), cpusz);
1907		}
1908
1909		if ((cpu = cmd_buf_read(hdl, NULL, ptr->ptr_name,
1910		    cpusz)) == NULL) {
1911			fmd_hdl_abort(hdl, "failed to read buf %s",
1912			    ptr->ptr_name);
1913		}
1914
1915		fmd_hdl_debug(hdl, "found %d in version field\n",
1916		    cpu->cpu_version);
1917
1918		if (CMD_CPU_VERSIONED(cpu)) {
1919			switch (cpu->cpu_version) {
1920			case CMD_CPU_VERSION_1:
1921				cpu = cpu_v1tov3(hdl, (cmd_cpu_1_t *)cpu,
1922				    cpusz);
1923				migrated = 1;
1924				break;
1925			case CMD_CPU_VERSION_2:
1926				cpu = cpu_v2tov3(hdl, (cmd_cpu_2_t *)cpu,
1927				    cpusz);
1928				migrated = 1;
1929				break;
1930			case CMD_CPU_VERSION_3:
1931				cpu = cpu_wrapv3(hdl, (cmd_cpu_pers_t *)cpu,
1932				    cpusz);
1933				break;
1934			default:
1935				fmd_hdl_abort(hdl, "unknown version (found %d) "
1936				    "for cpu state referenced by case %s.\n",
1937				    cpu->cpu_version, fmd_case_uuid(hdl, cp));
1938				break;
1939			}
1940		} else {
1941			cpu = cpu_v0tov3(hdl, (cmd_cpu_0_t *)cpu, cpusz);
1942			migrated = 1;
1943		}
1944
1945		if (migrated) {
1946			CMD_STAT_BUMP(cpu_migrat);
1947			cpu_buf_write(hdl, cpu);
1948		}
1949
1950		cmd_fmri_restore(hdl, &cpu->cpu_asru);
1951		cmd_fmri_restore(hdl, &cpu->cpu_fru);
1952#ifdef sun4u
1953		cpu_uec_restore(hdl, &cpu->cpu_uec);
1954		cpu_uec_restore(hdl, &cpu->cpu_olduec);
1955
1956		if (cpu->cpu_uec.uec_cache != NULL)
1957			cpu_uec_flush(hdl, cpu);
1958#endif /* sun4u */
1959		bzero(&cpu->cpu_xxu_retries, sizeof (cmd_list_t));
1960
1961		cmd_list_append(&cmd.cmd_cpus, cpu);
1962	}
1963
1964	switch (ptr->ptr_subtype) {
1965	case CMD_PTR_CPU_ICACHE:
1966		cpu_case_restore(hdl, cpu, &cpu->cpu_icache, cp, "icache");
1967		break;
1968	case CMD_PTR_CPU_DCACHE:
1969		cpu_case_restore(hdl, cpu, &cpu->cpu_dcache, cp, "dcache");
1970		break;
1971	case CMD_PTR_CPU_PCACHE:
1972		cpu_case_restore(hdl, cpu, &cpu->cpu_pcache, cp, "pcache");
1973		break;
1974	case CMD_PTR_CPU_ITLB:
1975		cpu_case_restore(hdl, cpu, &cpu->cpu_itlb, cp, "itlb");
1976		break;
1977	case CMD_PTR_CPU_DTLB:
1978		cpu_case_restore(hdl, cpu, &cpu->cpu_dtlb, cp, "dtlb");
1979		break;
1980	case CMD_PTR_CPU_L2DATA:
1981		cpu_case_restore(hdl, cpu, &cpu->cpu_l2data, cp,
1982		    cmd.cmd_l2data_serd.cs_name);
1983		break;
1984	case CMD_PTR_CPU_L2DATA_UERETRY:
1985		/* No longer used -- discard */
1986		break;
1987	case CMD_PTR_CPU_L2TAG:
1988		cpu_case_restore(hdl, cpu, &cpu->cpu_l2tag, cp, "l2tag");
1989		break;
1990	case CMD_PTR_CPU_L3DATA:
1991		cpu_case_restore(hdl, cpu, &cpu->cpu_l3data, cp,
1992		    cmd.cmd_l3data_serd.cs_name);
1993		break;
1994	case CMD_PTR_CPU_L3DATA_UERETRY:
1995		/* No longer used -- discard */
1996		break;
1997	case CMD_PTR_CPU_L3TAG:
1998		cpu_case_restore(hdl, cpu, &cpu->cpu_l3tag, cp, "l3tag");
1999		break;
2000	case CMD_PTR_CPU_FPU:
2001		cpu_case_restore(hdl, cpu, &cpu->cpu_fpu, cp, "fpu");
2002		break;
2003	case CMD_PTR_CPU_XR_RETRY:
2004		cmd_xr_restore(hdl, cpu, cp);
2005		break;
2006	case CMD_PTR_CPU_IREG:
2007		cpu_case_restore(hdl, cpu, &cpu->cpu_ireg, cp, "ireg");
2008		break;
2009	case CMD_PTR_CPU_FREG:
2010		cpu_case_restore(hdl, cpu, &cpu->cpu_freg, cp, "freg");
2011		break;
2012	case CMD_PTR_CPU_MAU:
2013		cpu_case_restore(hdl, cpu, &cpu->cpu_mau, cp, "mau");
2014		break;
2015	case CMD_PTR_CPU_L2CTL:
2016		cpu_case_restore(hdl, cpu, &cpu->cpu_l2ctl, cp, "l2ctl");
2017		break;
2018	case CMD_PTR_CPU_MISC_REGS:
2019		cpu_case_restore(hdl, cpu, &cpu->cpu_misc_regs, cp,
2020		    "misc_regs");
2021		break;
2022	case CMD_PTR_CPU_LFU:
2023		cpu_case_restore(hdl, cpu, &cpu->cpu_lfu, cp, "lfu");
2024		break;
2025#ifdef sun4u
2026	case CMD_PTR_CPU_INV_SFSR:
2027		cpu_case_restore(hdl, cpu, &cpu->cpu_opl_invsfsr, cp,
2028		    "opl_invsfsr");
2029		break;
2030	case CMD_PTR_CPU_UE_DET_CPU:
2031		cpu_case_restore(hdl, cpu, &cpu->cpu_oplue_detcpu, cp,
2032		    "oplue_detcpu");
2033		break;
2034	case CMD_PTR_CPU_UE_DET_IO:
2035		cpu_case_restore(hdl, cpu, &cpu->cpu_oplue_detio, cp,
2036		    "oplue_detio");
2037		break;
2038	case CMD_PTR_CPU_MTLB:
2039		cpu_case_restore(hdl, cpu, &cpu->cpu_opl_mtlb, cp,
2040		    "opl_mtlb");
2041		break;
2042	case CMD_PTR_CPU_TLBP:
2043		cpu_case_restore(hdl, cpu, &cpu->cpu_opl_tlbp, cp,
2044		    "opl_tlbp");
2045		break;
2046	case CMD_PTR_CPU_UGESR_INV_URG:
2047		cpu_case_restore(hdl, cpu, &cpu->cpu_opl_inv_urg, cp,
2048		    "opl_inv_urg");
2049		break;
2050	case CMD_PTR_CPU_UGESR_CRE:
2051		cpu_case_restore(hdl, cpu, &cpu->cpu_opl_cre, cp,
2052		    "opl_cre");
2053		break;
2054	case CMD_PTR_CPU_UGESR_TSB_CTX:
2055		cpu_case_restore(hdl, cpu, &cpu->cpu_opl_tsb_ctx, cp,
2056		    "opl_tsb_ctx");
2057		break;
2058	case CMD_PTR_CPU_UGESR_TSBP:
2059		cpu_case_restore(hdl, cpu, &cpu->cpu_opl_tsbp, cp,
2060		    "opl_tsbp");
2061		break;
2062	case CMD_PTR_CPU_UGESR_PSTATE:
2063		cpu_case_restore(hdl, cpu, &cpu->cpu_opl_pstate, cp,
2064		    "opl_pstate");
2065		break;
2066	case CMD_PTR_CPU_UGESR_TSTATE:
2067		cpu_case_restore(hdl, cpu, &cpu->cpu_opl_tstate, cp,
2068		    "opl_tstate");
2069		break;
2070	case CMD_PTR_CPU_UGESR_IUG_F:
2071		cpu_case_restore(hdl, cpu, &cpu->cpu_opl_iug_f, cp,
2072		    "opl_iug_f");
2073		break;
2074	case CMD_PTR_CPU_UGESR_IUG_R:
2075		cpu_case_restore(hdl, cpu, &cpu->cpu_opl_iug_r, cp,
2076		    "opl_iug_r");
2077		break;
2078	case CMD_PTR_CPU_UGESR_SDC:
2079		cpu_case_restore(hdl, cpu, &cpu->cpu_opl_sdc, cp,
2080		    "opl_sdc");
2081		break;
2082	case CMD_PTR_CPU_UGESR_WDT:
2083		cpu_case_restore(hdl, cpu, &cpu->cpu_opl_wdt, cp,
2084		    "opl_wdt");
2085		break;
2086	case CMD_PTR_CPU_UGESR_DTLB:
2087		cpu_case_restore(hdl, cpu, &cpu->cpu_opl_dtlb, cp,
2088		    "opl_dtlb");
2089		break;
2090	case CMD_PTR_CPU_UGESR_ITLB:
2091		cpu_case_restore(hdl, cpu, &cpu->cpu_opl_itlb, cp,
2092		    "opl_itlb");
2093		break;
2094	case CMD_PTR_CPU_UGESR_CORE_ERR:
2095		cpu_case_restore(hdl, cpu, &cpu->cpu_opl_core_err, cp,
2096		    "opl_core_err");
2097		break;
2098	case CMD_PTR_CPU_UGESR_DAE:
2099		cpu_case_restore(hdl, cpu, &cpu->cpu_opl_dae, cp,
2100		    "opl_dae");
2101		break;
2102	case CMD_PTR_CPU_UGESR_IAE:
2103		cpu_case_restore(hdl, cpu, &cpu->cpu_opl_iae, cp,
2104		    "opl_iae");
2105		break;
2106	case CMD_PTR_CPU_UGESR_UGE:
2107		cpu_case_restore(hdl, cpu, &cpu->cpu_opl_uge, cp,
2108		    "opl_uge");
2109		break;
2110#endif	/* sun4u */
2111	default:
2112		fmd_hdl_abort(hdl, "invalid %s subtype %d\n",
2113		    ptr->ptr_name, ptr->ptr_subtype);
2114	}
2115
2116	return (cpu);
2117}
2118
2119void
2120cmd_cpu_validate(fmd_hdl_t *hdl)
2121{
2122	cmd_xr_t *xr, *xrn;
2123	cmd_cpu_t *cpu, *cpun;
2124
2125	for (cpu = cmd_list_next(&cmd.cmd_cpus); cpu != NULL;
2126	    cpu = cmd_list_next(cpu)) {
2127		if (cpu_all_threads_invalid(hdl, cpu) == FMD_B_TRUE)
2128			cpu->cpu_flags |= CMD_CPU_F_DELETING;
2129	}
2130
2131	for (xr = cmd_list_next(&cmd.cmd_xxcu_redelivs); xr != NULL; xr = xrn) {
2132		xrn = cmd_list_next(xr);
2133
2134		if (xr->xr_cpu->cpu_flags & CMD_CPU_F_DELETING)
2135			cmd_xr_destroy(hdl, xr);
2136	}
2137
2138	for (cpu = cmd_list_next(&cmd.cmd_cpus); cpu != NULL; cpu = cpun) {
2139		cpun = cmd_list_next(cpu);
2140
2141		if (cpu->cpu_flags & CMD_CPU_F_DELETING)
2142			cmd_cpu_destroy(hdl, cpu);
2143	}
2144}
2145
2146static void
2147cmd_xxcu_timeout(fmd_hdl_t *hdl, id_t id)
2148{
2149	cmd_xr_t *xr;
2150
2151	for (xr = cmd_list_next(&cmd.cmd_xxcu_redelivs); xr != NULL;
2152	    xr = cmd_list_next(xr)) {
2153		if (xr->xr_id == id) {
2154			fmd_event_t *ep = fmd_case_getprincipal(hdl,
2155			    xr->xr_case);
2156			xr->xr_hdlr(hdl, xr, ep);
2157			cmd_xr_deref(hdl, xr);
2158			return;
2159		}
2160	}
2161}
2162
2163/*ARGSUSED*/
2164static void
2165cmd_xxu_flush_timeout(fmd_hdl_t *hdl, id_t id)
2166{
2167#ifdef sun4u
2168	cmd_cpu_t *cpu;
2169
2170	for (cpu = cmd_list_next(&cmd.cmd_cpus); cpu != NULL;
2171	    cpu = cmd_list_next(cpu)) {
2172		if (cpu->cpu_uec_flush == id) {
2173			cpu_uec_flush_finish(hdl, cpu);
2174			return;
2175		}
2176	}
2177#else /* sun4u */
2178	return;
2179#endif /* sun4u */
2180}
2181
2182void
2183cmd_cpu_timeout(fmd_hdl_t *hdl, id_t id, void *type)
2184{
2185	switch ((uintptr_t)type) {
2186	case (uintptr_t)CMD_TIMERTYPE_CPU_UEC_FLUSH:
2187		cmd_xxu_flush_timeout(hdl, id);
2188		break;
2189	case (uintptr_t)CMD_TIMERTYPE_CPU_XR_WAITER:
2190		cmd_xxcu_timeout(hdl, id);
2191		break;
2192	}
2193}
2194
2195static int
2196cpu_gc_keep_one(fmd_hdl_t *hdl, cmd_cpu_t *cpu)
2197{
2198	int i;
2199
2200	if (cpu_all_threads_invalid(hdl, cpu) == FMD_B_TRUE) {
2201		fmd_hdl_debug(hdl, "GC of CPU %d: no longer working\n",
2202		    cpu->cpu_cpuid);
2203		return (0);
2204	}
2205
2206	for (i = 0; i < sizeof (cmd_cpu_cases_t) / sizeof (cmd_case_t); i++) {
2207		cmd_case_t *cp = &((cmd_case_t *)&cpu->cpu_cases)[i];
2208
2209		if (cp->cc_cp == NULL || cp->cc_serdnm == NULL)
2210			continue;
2211
2212		if (fmd_serd_exists(hdl, cp->cc_serdnm) &&
2213		    !fmd_serd_empty(hdl, cp->cc_serdnm))
2214			return (1);
2215	}
2216
2217	if (cmd_list_next(&cpu->cpu_xxu_retries) != NULL)
2218		return (1);
2219
2220	if (cpu->cpu_uec.uec_cache != NULL ||
2221	    cpu->cpu_olduec.uec_cache != NULL)
2222		return (1);
2223
2224	return (0);
2225}
2226
2227/*ARGSUSED*/
2228void
2229cmd_cpu_gc(fmd_hdl_t *hdl)
2230{
2231	cmd_cpu_t *cpu, *next;
2232
2233	fmd_hdl_debug(hdl, "GC of CPUs\n");
2234
2235	for (cpu = cmd_list_next(&cmd.cmd_cpus); cpu != NULL; cpu = next) {
2236		next = cmd_list_next(cpu);
2237
2238		if (!cpu_gc_keep_one(hdl, cpu)) {
2239			fmd_hdl_debug(hdl, "GC of CPU %d: destroying\n",
2240			    cpu->cpu_cpuid);
2241			continue;
2242		}
2243#ifdef sun4u
2244		if (cpu->cpu_uec.uec_cache != NULL)
2245			cpu_uec_flush(hdl, cpu);
2246#endif /* sun4u */
2247		cpu->cpu_uec_nflushes = 0;
2248	}
2249}
2250
2251void
2252cmd_cpu_fini(fmd_hdl_t *hdl)
2253{
2254	cmd_cpu_t *cpu;
2255
2256	while ((cpu = cmd_list_next(&cmd.cmd_cpus)) != NULL)
2257		cmd_cpu_free(hdl, cpu, FMD_B_FALSE);
2258}
2259
2260typedef struct {
2261    const char *fam_name;
2262    cpu_family_t fam_value;
2263} famdata_t;
2264
2265static famdata_t famdata_tbl[] = {
2266	{"UltraSPARC-III",	CMD_CPU_FAM_CHEETAH},
2267	{"UltraSPARC-IV",	CMD_CPU_FAM_CHEETAH},
2268	{"UltraSPARC-T",	CMD_CPU_FAM_NIAGARA},
2269	{"SPARC64-VI",		CMD_CPU_FAM_SPARC64}
2270};
2271
2272cpu_family_t
2273cpu_family(char *knsp)
2274{
2275	int j;
2276
2277	for (j = 0; j < sizeof (famdata_tbl)/sizeof (famdata_t); j++) {
2278		if (strncmp(knsp, famdata_tbl[j].fam_name,
2279		    strlen(famdata_tbl[j].fam_name)) == 0) {
2280			return (famdata_tbl[j].fam_value);
2281		}
2282	}
2283	return (CMD_CPU_FAM_UNSUPPORTED);
2284}
2285
2286/*
2287 * Determine which CPU family this diagnosis is being run on.
2288 * This assumes that ereports are being generated by this system.
2289 */
2290
2291cpu_family_t
2292cmd_cpu_check_support(void)
2293{
2294	kstat_named_t *kn;
2295	kstat_ctl_t *kc;
2296	kstat_t *ksp;
2297	int i;
2298
2299	if ((kc = kstat_open()) == NULL)
2300		return (CMD_CPU_FAM_UNSUPPORTED);
2301
2302	for (ksp = kc->kc_chain; ksp != NULL; ksp = ksp->ks_next) {
2303		if (strcmp(ksp->ks_module, "cpu_info") != 0)
2304			continue;
2305
2306		if (kstat_read(kc, ksp, NULL) == -1) {
2307			(void) kstat_close(kc);
2308			return (CMD_CPU_FAM_UNSUPPORTED);
2309		}
2310
2311		for (kn = ksp->ks_data, i = 0; i < ksp->ks_ndata; i++, kn++) {
2312			cpu_family_t family;
2313			if (strcmp(kn->name, "implementation") != 0)
2314				continue;
2315			family = cpu_family(KSTAT_NAMED_STR_PTR(kn));
2316			(void) kstat_close(kc);
2317			return (family);
2318		}
2319	}
2320	(void) kstat_close(kc);
2321	return (CMD_CPU_FAM_UNSUPPORTED);
2322}
2323
2324boolean_t
2325cmd_cpu_ecache_support(void)
2326{
2327	cpu_family_t value;
2328
2329	value = cmd_cpu_check_support();
2330	return (fam_info_tbl[value].ecache_flush_needed);
2331}
2332
2333/*
2334 * This function builds the fmri of the
2335 * given cpuid based on the cpu scheme.
2336 */
2337nvlist_t *
2338cmd_cpu_fmri_create(uint32_t cpuid, uint8_t cpumask)
2339{
2340	nvlist_t *fmri;
2341
2342	if ((errno = nvlist_alloc(&fmri, NV_UNIQUE_NAME, 0)) != 0)
2343		return (NULL);
2344
2345	if (nvlist_add_uint8(fmri, FM_VERSION,
2346	    FM_CPU_SCHEME_VERSION) != 0 || nvlist_add_string(fmri,
2347	    FM_FMRI_SCHEME, FM_FMRI_SCHEME_CPU) != 0 ||
2348	    nvlist_add_uint32(fmri, FM_FMRI_CPU_ID, cpuid) != 0 ||
2349	    nvlist_add_uint8(fmri, FM_FMRI_CPU_MASK, cpumask) != 0) {
2350		nvlist_free(fmri);
2351		return (NULL);
2352	}
2353
2354	return (fmri);
2355}
2356