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