xref: /titanic_41/usr/src/cmd/fm/modules/sun4/cpumem-diagnosis/cmd_main.c (revision 45e662eb8429b38c18931ebeed30f2e5287ae51b)
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 (c) 2004, 2010, Oracle and/or its affiliates. All rights reserved.
23  */
24 
25 /*
26  * CPU/Memory error diagnosis engine for the UltraSPARC III, IV, T1,
27  * SPARC64 VI and SPARC64 VII families of processors.
28  */
29 
30 #include <cmd_state.h>
31 #include <cmd_cpu.h>
32 
33 #ifdef sun4u
34 #include <cmd_ecache.h>
35 #include <cmd_Lxcache.h>
36 #endif /* sun4u */
37 
38 #include <cmd_mem.h>
39 #include <cmd_page.h>
40 #include <cmd_dimm.h>
41 #ifdef sun4u
42 #include <cmd_dp.h>
43 #include <cmd_opl.h>
44 #endif
45 #include <cmd_bank.h>
46 #include <cmd.h>
47 
48 #include <errno.h>
49 #include <string.h>
50 #include <unistd.h>
51 #include <strings.h>
52 #include <fm/fmd_api.h>
53 #include <fm/libtopo.h>
54 #include <sys/fm/protocol.h>
55 #include <sys/async.h>
56 
57 #ifdef	sun4v
58 #include <sys/fm/ldom.h>
59 static fmd_hdl_t *init_hdl;
60 ldom_hdl_t *cpumem_diagnosis_lhp;
61 #endif
62 
63 cmd_t cmd;
64 
65 #ifdef sun4u
66 cmd_list_t opl_cpu_list;
67 #endif	/* sun4u */
68 
69 typedef struct cmd_subscriber {
70 	const char *subr_class;
71 	cmd_evdisp_t (*subr_func)(fmd_hdl_t *, fmd_event_t *, nvlist_t *,
72 	    const char *, cmd_errcl_t);
73 	cmd_errcl_t subr_arg;
74 	cmd_evdisp_stat_t subr_stat;
75 } cmd_subscriber_t;
76 
77 /*ARGSUSED*/
78 cmd_evdisp_t
cmd_nop(fmd_hdl_t * hdl,fmd_event_t * ep,nvlist_t * nvl,const char * class,cmd_errcl_t clcode)79 cmd_nop(fmd_hdl_t *hdl, fmd_event_t *ep, nvlist_t *nvl, const char *class,
80     cmd_errcl_t clcode)
81 {
82 	return (CMD_EVD_UNUSED);
83 }
84 
85 #ifdef sun4u
86 /*
87  * It used to be that cmd_opluecpu_detio() was called directly, with a
88  * 'class' argument of ereport.io.oberon.xxx.  But the code underlying
89  * cmd_opluecpu_detio() assumed that the class would always be of the form
90  * ereport.cpu.<cputype>.<subclass>.
91  *
92  * Rather than generalizing the underlying code, the following adjusts the
93  * input to cmd_opluecpu_detio() so that it conforms to the above expectation.
94  */
95 
96 /*ARGSUSED*/
97 cmd_evdisp_t
opl_opluecpu_detio(fmd_hdl_t * hdl,fmd_event_t * ep,nvlist_t * nvl,const char * class,cmd_errcl_t clcode)98 opl_opluecpu_detio(fmd_hdl_t *hdl, fmd_event_t *ep, nvlist_t *nvl,
99     const char *class, cmd_errcl_t clcode)
100 {
101 	return (cmd_opluecpu_detio(hdl, ep, nvl,
102 	    "ereport.cpu.SPARC64-VI.", clcode));
103 }
104 #endif	/* sun4u */
105 
106 static cmd_subscriber_t cmd_subscribers[] = {
107 #ifdef sun4u
108 	{ "ereport.cpu.*.ucc", 		cmd_xxc,	CMD_ERRCL_UCC |
109     CMD_CPU_LEVEL_CORE },
110 	{ "ereport.cpu.*.ucu",		cmd_xxu,	CMD_ERRCL_UCU |
111     CMD_CPU_LEVEL_CORE },
112 	{ "ereport.cpu.*.cpc",		cmd_xxc,	CMD_ERRCL_CPC |
113     CMD_CPU_LEVEL_CORE },
114 	{ "ereport.cpu.*.cpu",		cmd_xxu,	CMD_ERRCL_CPU |
115     CMD_CPU_LEVEL_CORE },
116 	{ "ereport.cpu.*.wdc",		cmd_xxc,	CMD_ERRCL_WDC |
117     CMD_CPU_LEVEL_CORE },
118 	{ "ereport.cpu.*.wdu",		cmd_xxu,	CMD_ERRCL_WDU |
119     CMD_CPU_LEVEL_CORE },
120 	{ "ereport.cpu.*.edc",		cmd_xxc,	CMD_ERRCL_EDC |
121     CMD_CPU_LEVEL_CORE },
122 	{ "ereport.cpu.*.edu-st",	cmd_xxu,	CMD_ERRCL_EDU_ST |
123     CMD_CPU_LEVEL_CORE },
124 	{ "ereport.cpu.*.edu-bl",	cmd_xxu,	CMD_ERRCL_EDU_BL |
125     CMD_CPU_LEVEL_CORE },
126 	{ "ereport.cpu.*.l3-ucc", 	cmd_xxc,	CMD_ERRCL_L3_UCC |
127     CMD_CPU_LEVEL_CORE },
128 	{ "ereport.cpu.*.l3-ucu",	cmd_xxu,	CMD_ERRCL_L3_UCU |
129     CMD_CPU_LEVEL_CORE },
130 	{ "ereport.cpu.*.l3-cpc",	cmd_xxc,	CMD_ERRCL_L3_CPC |
131     CMD_CPU_LEVEL_CORE },
132 	{ "ereport.cpu.*.l3-cpu",	cmd_xxu,	CMD_ERRCL_L3_CPU |
133     CMD_CPU_LEVEL_CORE },
134 	{ "ereport.cpu.*.l3-wdc",	cmd_xxc,	CMD_ERRCL_L3_WDC |
135     CMD_CPU_LEVEL_CORE },
136 	{ "ereport.cpu.*.l3-wdu",	cmd_xxu,	CMD_ERRCL_L3_WDU |
137     CMD_CPU_LEVEL_CORE },
138 	{ "ereport.cpu.*.l3-edc",	cmd_xxc,	CMD_ERRCL_L3_EDC |
139     CMD_CPU_LEVEL_CORE },
140 	{ "ereport.cpu.*.l3-edu-st",	cmd_xxu,	CMD_ERRCL_L3_EDU_ST |
141     CMD_CPU_LEVEL_CORE },
142 	{ "ereport.cpu.*.l3-edu-bl",	cmd_xxu,	CMD_ERRCL_L3_EDU_BL |
143     CMD_CPU_LEVEL_CORE },
144 	{ "ereport.cpu.*.l3-mecc",	cmd_xxu,	CMD_ERRCL_L3_MECC |
145     CMD_CPU_LEVEL_CORE },
146 	{ "ereport.cpu.*.ipe",		cmd_icache },
147 	{ "ereport.cpu.*.idspe",	cmd_icache },
148 	{ "ereport.cpu.*.itspe",	cmd_icache },
149 	{ "ereport.cpu.*.dpe",		cmd_dcache },
150 	{ "ereport.cpu.*.ddspe",	cmd_dcache },
151 	{ "ereport.cpu.*.dtspe",	cmd_dcache },
152 	{ "ereport.cpu.*.pdspe",	cmd_pcache },
153 	{ "ereport.cpu.*.itlbpe",	cmd_itlb },
154 	{ "ereport.cpu.*.dtlbpe",	cmd_dtlb },
155 	{ "ereport.cpu.*.thce",		cmd_txce, CMD_CPU_LEVEL_CORE },
156 	{ "ereport.cpu.*.tsce",		cmd_txce },
157 	{ "ereport.cpu.*.l3-thce",	cmd_l3_thce, CMD_CPU_LEVEL_CORE },
158 	{ "ereport.cpu.*.ce",		cmd_ce },
159 	{ "ereport.cpu.*.emc",		cmd_ce },
160 	{ "ereport.cpu.*.ue",		cmd_ue },
161 	{ "ereport.cpu.*.due",		cmd_ue },
162 	{ "ereport.cpu.*.emu",		cmd_ue },
163 	{ "ereport.cpu.*.frc",		cmd_frx,	CMD_ERRCL_FRC },
164 	{ "ereport.cpu.*.rce",		cmd_rxe,	CMD_ERRCL_RCE },
165 	{ "ereport.cpu.*.fru",		cmd_frx,	CMD_ERRCL_FRU },
166 	{ "ereport.cpu.*.rue",		cmd_rxe,	CMD_ERRCL_RUE },
167 	{ "ereport.cpu.*.eti",		cmd_txce },
168 	{ "ereport.cpu.*.etc",		cmd_txce },
169 	{ "ereport.io.*.ecc.drce",	cmd_ioxe,	CMD_ERRCL_IOCE },
170 	{ "ereport.io.*.ecc.dwce",	cmd_ioxe,	CMD_ERRCL_IOCE },
171 	{ "ereport.io.*.ecc.drue",	cmd_ioxe,	CMD_ERRCL_IOUE },
172 	{ "ereport.io.*.ecc.dwue",	cmd_ioxe,	CMD_ERRCL_IOUE },
173 	{ "ereport.io.*.ecc.s-drce",	cmd_ioxe_sec },
174 	{ "ereport.io.*.ecc.s-dwce",	cmd_ioxe_sec },
175 	{ "ereport.io.*.ecc.s-drue",	cmd_ioxe_sec },
176 	{ "ereport.io.*.ecc.s-dwue",	cmd_ioxe_sec },
177 	{ "ereport.io.fire.jbc.ce_asyn", cmd_ioxe,	CMD_ERRCL_IOCE },
178 	{ "ereport.io.fire.jbc.ue_asyn", cmd_ioxe,	CMD_ERRCL_IOUE },
179 	{ "ereport.asic.*.cds.cds-dp", 	cmd_dp_cds },
180 	{ "ereport.asic.*.dx.dx-dp",	cmd_dp_dx },
181 	{ "ereport.asic.*.sdi.sdi-dp", 	cmd_dp_ex },
182 	{ "ereport.asic.*.cp.cp-dp", 	cmd_dp_cp },
183 	{ "ereport.asic.*.rp.rp-dp", 	cmd_dp_cp },
184 	{ "ereport.asic.mac.mi-ue",			cmd_opl_mac_common },
185 	{ "ereport.asic.mac.ptrl-ue",			cmd_opl_mac_common },
186 	{ "ereport.asic.mac.mi-ce",			cmd_opl_mac_common },
187 	{ "ereport.asic.mac.ptrl-ce",			cmd_opl_mac_common },
188 	{ "ereport.asic.mac.ptrl-ice",			cmd_opl_mac_common },
189 	{ "ereport.asic.mac.mi-cmpe",			cmd_opl_mac_common },
190 	{ "ereport.asic.mac.ptrl-cmpe",			cmd_opl_mac_common },
191 	{ "ereport.asic.mac.mi-sue",			cmd_opl_mac_common },
192 	{ "ereport.asic.mac.ptrl-sue",			cmd_opl_mac_common },
193 	{ "ereport.asic.mac.mi-mue",			cmd_opl_mac_common },
194 	{ "ereport.asic.mac.ptrl-mue",			cmd_opl_mac_common },
195 	{ "ereport.cpu.*.ue-mem",			cmd_opl_cpu_mem },
196 	{ "ereport.cpu.*.ue-channel",			cmd_nop },
197 	{ "ereport.cpu.*.ue-cpu",			cmd_opluecpu_detcpu },
198 	{ "ereport.cpu.*.ue-path",			cmd_nop },
199 	{ "ereport.cpu.*.inv-sfsr",			cmd_oplinv_sfsr },
200 	{ "ereport.cpu.*.berr",				cmd_nop },
201 	{ "ereport.cpu.*.bto",				cmd_nop },
202 	{ "ereport.cpu.*.mtlb",				cmd_oplmtlb },
203 	{ "ereport.cpu.*.tlbp",				cmd_opltlbp },
204 	{ "ereport.cpu.*.inv-uge",			cmd_oplinv_urg },
205 	{ "ereport.cpu.*.cre",				cmd_oplcre },
206 	{ "ereport.cpu.*.tsb-ctx",			cmd_opltsb_ctx },
207 	{ "ereport.cpu.*.tsbp",				cmd_opltsbp },
208 	{ "ereport.cpu.*.pstate",			cmd_oplpstate },
209 	{ "ereport.cpu.*.tstate",			cmd_opltstate },
210 	{ "ereport.cpu.*.iug-f",			cmd_opliug_f },
211 	{ "ereport.cpu.*.iug-r",			cmd_opliug_r },
212 	{ "ereport.cpu.*.sdc",				cmd_oplsdc },
213 	{ "ereport.cpu.*.wdt",				cmd_oplwdt },
214 	{ "ereport.cpu.*.dtlb",				cmd_opldtlb },
215 	{ "ereport.cpu.*.itlb",				cmd_oplitlb },
216 	{ "ereport.cpu.*.core-err",			cmd_oplcore_err },
217 	{ "ereport.cpu.*.dae",				cmd_opldae },
218 	{ "ereport.cpu.*.iae",				cmd_opliae },
219 	{ "ereport.cpu.*.uge",				cmd_opluge },
220 	{ "ereport.io.oberon.ubc.dmarduea-mem",		cmd_opl_io_mem },
221 	{ "ereport.io.oberon.ubc.dmarduea-channel",	cmd_nop },
222 	{ "ereport.io.oberon.ubc.dmarduea-cpu",		opl_opluecpu_detio },
223 	{ "ereport.io.oberon.ubc.dmarduea-path",	cmd_nop },
224 	{ "ereport.io.oberon.ubc.dmardueb-mem",		cmd_opl_io_mem },
225 	{ "ereport.io.oberon.ubc.dmardueb-channel",	cmd_nop },
226 	{ "ereport.io.oberon.ubc.dmardueb-cpu",		opl_opluecpu_detio },
227 	{ "ereport.io.oberon.ubc.dmardueb-path",	cmd_nop },
228 	{ "ereport.io.oberon.ubc.piowtue-mem",		cmd_opl_io_mem },
229 	{ "ereport.io.oberon.ubc.piowtue-channel",	cmd_nop },
230 	{ "ereport.io.oberon.ubc.piowtue-cpu",		opl_opluecpu_detio },
231 	{ "ereport.io.oberon.ubc.piowtue-path",		cmd_nop },
232 	{ "ereport.io.oberon.ubc.piowbeue-mem",		cmd_opl_io_mem },
233 	{ "ereport.io.oberon.ubc.piowbeue-channel",	cmd_nop },
234 	{ "ereport.io.oberon.ubc.piowbeue-cpu",		opl_opluecpu_detio },
235 	{ "ereport.io.oberon.ubc.piowbeue-path",	cmd_nop },
236 	{ "ereport.io.oberon.ubc.piorbeue-mem",		cmd_opl_io_mem },
237 	{ "ereport.io.oberon.ubc.piorbeue-channel",	cmd_nop },
238 	{ "ereport.io.oberon.ubc.piorbeue-cpu",		opl_opluecpu_detio },
239 	{ "ereport.io.oberon.ubc.piorbeue-path",	cmd_nop },
240 #else /* i.e. sun4v */
241 	{ "ereport.cpu.*.irc",		cmd_irc },
242 	{ "ereport.cpu.*.iru", 		cmd_iru },
243 	{ "ereport.cpu.*.frc",		cmd_frc },
244 	{ "ereport.cpu.*.fru",		cmd_fru },
245 	{ "ereport.cpu.*.mau",		cmd_mau },
246 	{ "ereport.cpu.*.imdu",		cmd_itlb,	CMD_CPU_LEVEL_CORE },
247 	{ "ereport.cpu.*.dmdu",		cmd_dtlb,	CMD_CPU_LEVEL_CORE },
248 	{ "ereport.cpu.*.dmsu",		cmd_dtlb,	CMD_CPU_LEVEL_CORE },
249 	{ "ereport.cpu.*.imtu",		cmd_itlb,	CMD_CPU_LEVEL_CORE },
250 	{ "ereport.cpu.*.dmtu",		cmd_dtlb,	CMD_CPU_LEVEL_CORE },
251 	{ "ereport.cpu.*.itc",		cmd_icache,	CMD_CPU_LEVEL_CORE },
252 	{ "ereport.cpu.*.idc",		cmd_icache,	CMD_CPU_LEVEL_CORE },
253 	{ "ereport.cpu.*.dtc",		cmd_dcache,	CMD_CPU_LEVEL_CORE },
254 	{ "ereport.cpu.*.ddc",		cmd_dcache,	CMD_CPU_LEVEL_CORE },
255 	{ "ereport.cpu.*.irfc",		cmd_irc },
256 	{ "ereport.cpu.*.irfu",		cmd_iru },
257 	{ "ereport.cpu.*.frfc",		cmd_frc },
258 	{ "ereport.cpu.*.frfu",		cmd_fru },
259 
260 
261 
262 
263 
264 	{ "ereport.cpu.*.mamu",		cmd_mau,	CMD_CPU_LEVEL_CORE },
265 	{ "ereport.cpu.*.ittm",		cmd_itlb,	CMD_CPU_LEVEL_CORE },
266 	{ "ereport.cpu.*.ittp",		cmd_itlb,	CMD_CPU_LEVEL_CORE },
267 	{ "ereport.cpu.*.itdp",		cmd_itlb,	CMD_CPU_LEVEL_CORE },
268 	{ "ereport.cpu.*.itmu",		cmd_itlb,	CMD_CPU_LEVEL_CORE },
269 	{ "ereport.cpu.*.dttm",		cmd_dtlb,	CMD_CPU_LEVEL_CORE },
270 	{ "ereport.cpu.*.dttp",		cmd_dtlb,	CMD_CPU_LEVEL_CORE },
271 	{ "ereport.cpu.*.dtdp",		cmd_dtlb,	CMD_CPU_LEVEL_CORE },
272 	{ "ereport.cpu.*.dtmu",		cmd_dtlb,	CMD_CPU_LEVEL_CORE },
273 	{ "ereport.cpu.*.icvp",		cmd_icache,	CMD_CPU_LEVEL_CORE },
274 	{ "ereport.cpu.*.ictp",		cmd_icache,	CMD_CPU_LEVEL_CORE },
275 	{ "ereport.cpu.*.ictm",		cmd_icache,	CMD_CPU_LEVEL_CORE },
276 	{ "ereport.cpu.*.icdp",		cmd_xxc,
277 	    CMD_ERRCL_ICDP | CMD_CPU_LEVEL_CORE },
278 	{ "ereport.cpu.*.dcvp",		cmd_dcache,	CMD_CPU_LEVEL_CORE },
279 	{ "ereport.cpu.*.dctp",		cmd_dcache,	CMD_CPU_LEVEL_CORE },
280 	{ "ereport.cpu.*.dctm",		cmd_dcache,	CMD_CPU_LEVEL_CORE },
281 	{ "ereport.cpu.*.dcdp",		cmd_xxc,
282 	    CMD_ERRCL_DCDP | CMD_CPU_LEVEL_CORE },
283 	{ "ereport.cpu.*.itl2c",	cmd_xxc,	CMD_ERRCL_LDAC |
284 		CMD_CPU_LEVEL_CHIP },
285 	{ "ereport.cpu.*.dtl2c",	cmd_xxc,	CMD_ERRCL_LDAC |
286 		CMD_CPU_LEVEL_CHIP },
287 	{ "ereport.cpu.*.icl2c",	cmd_xxc,	CMD_ERRCL_LDAC |
288 		CMD_CPU_LEVEL_CHIP },
289 	{ "ereport.cpu.*.dcl2c",	cmd_xxc,	CMD_ERRCL_LDAC |
290 		CMD_CPU_LEVEL_CHIP },
291 	{ "ereport.cpu.*.mal2c",	cmd_xxc,	CMD_ERRCL_LDAC |
292 		CMD_CPU_LEVEL_CHIP },
293 	{ "ereport.cpu.*.cwql2c",	cmd_xxc,	CMD_ERRCL_LDAC |
294 		CMD_CPU_LEVEL_CHIP },
295 	{ "ereport.cpu.*.lvc",		cmd_txce,	CMD_CPU_LEVEL_CHIP },
296 	{ "ereport.cpu.*.itl2u",	cmd_xxu,	CMD_ERRCL_IL2U |
297 		CMD_CPU_LEVEL_CHIP },
298 	{ "ereport.cpu.*.dtl2u",	cmd_xxu,	CMD_ERRCL_DL2U |
299 		CMD_CPU_LEVEL_CHIP },
300 	{ "ereport.cpu.*.icl2u",	cmd_xxu,	CMD_ERRCL_IL2U |
301 		CMD_CPU_LEVEL_CHIP },
302 	{ "ereport.cpu.*.dcl2u",	cmd_xxu,	CMD_ERRCL_DL2U |
303 		CMD_CPU_LEVEL_CHIP },
304 	{ "ereport.cpu.*.mal2u",	cmd_xxu,	CMD_ERRCL_LDAU |
305 		CMD_CPU_LEVEL_CHIP },
306 	{ "ereport.cpu.*.cwql2u",	cmd_xxu,	CMD_ERRCL_LDAU |
307 		CMD_CPU_LEVEL_CHIP },
308 	{ "ereport.cpu.*.lvf",		cmd_l2ctl,	CMD_CPU_LEVEL_CHIP },
309 	{ "ereport.cpu.*.lrf",		cmd_l2ctl,	CMD_CPU_LEVEL_CHIP },
310 	{ "ereport.cpu.*.ltu",		cmd_l2ctl,	CMD_CPU_LEVEL_CHIP },
311 	{ "ereport.cpu.*.itl2nd",	cmd_nop_train,	CMD_ERRCL_IL2ND },
312 	{ "ereport.cpu.*.dtl2nd",	cmd_nop_train,	CMD_ERRCL_DL2ND },
313 	{ "ereport.cpu.*.icl2nd",	cmd_nop_train,	CMD_ERRCL_IL2ND },
314 	{ "ereport.cpu.*.dcl2nd",	cmd_nop_train,	CMD_ERRCL_DL2ND },
315 	{ "ereport.cpu.*.l2nd",		cmd_nop_train,	CMD_ERRCL_L2ND },
316 	{ "ereport.cpu.*.mal2nd",	cmd_nop_train,	CMD_ERRCL_L2ND },
317 	{ "ereport.cpu.*.cwql2nd",	cmd_nop_train,	CMD_ERRCL_L2ND },
318 	{ "ereport.cpu.*.ldac",		cmd_xxc, 	CMD_ERRCL_LDAC |
319 	    CMD_CPU_LEVEL_CHIP },
320 	{ "ereport.cpu.*.ldwc",		cmd_xxc,	CMD_ERRCL_LDWC |
321 	    CMD_CPU_LEVEL_CHIP },
322 	{ "ereport.cpu.*.ldrc",		cmd_xxc,	CMD_ERRCL_LDRC |
323 	    CMD_CPU_LEVEL_CHIP },
324 	{ "ereport.cpu.*.ldsc", 	cmd_xxc,	CMD_ERRCL_LDSC |
325 	    CMD_CPU_LEVEL_CHIP },
326 	{ "ereport.cpu.*.ltc",		cmd_txce,	CMD_CPU_LEVEL_CHIP },
327 	{ "ereport.cpu.*.ldau",		cmd_xxu, 	CMD_ERRCL_LDAU |
328 	    CMD_CPU_LEVEL_CHIP },
329 	{ "ereport.cpu.*.ldwu",		cmd_xxu,	CMD_ERRCL_LDWU |
330 	    CMD_CPU_LEVEL_CHIP },
331 	{ "ereport.cpu.*.ldru",		cmd_xxu,	CMD_ERRCL_LDRU |
332 	    CMD_CPU_LEVEL_CHIP },
333 	{ "ereport.cpu.*.ldsu",		cmd_xxu,	CMD_ERRCL_LDSU |
334 	    CMD_CPU_LEVEL_CHIP },
335 	{ "ereport.cpu.*.lvu",		cmd_l2ctl, 	CMD_CPU_LEVEL_CHIP },
336 	{ "ereport.cpu.*.lru",		cmd_l2ctl,	CMD_CPU_LEVEL_CHIP },
337 	{ "ereport.cpu.*.fbr",		cmd_fb },
338 	{ "ereport.cpu.*.fbu",		cmd_fb_train,	CMD_ERRCL_FBU },
339 	{ "ereport.cpu.*.dac",		cmd_ce,		CMD_ERRCL_DAC },
340 	{ "ereport.cpu.*.dsc",		cmd_ce,		CMD_ERRCL_DSC },
341 	{ "ereport.cpu.*.dau",		cmd_ue_train,	CMD_ERRCL_DAU },
342 	{ "ereport.cpu.*.dbu",		cmd_fw_defect,	CMD_ERRCL_DBU },
343 	{ "ereport.cpu.*.dsu",		cmd_ue,		CMD_ERRCL_DSU },
344 	{ "ereport.cpu.*.sbdpc",	cmd_miscregs_train,
345 	    CMD_ERRCL_SBDPC | CMD_CPU_LEVEL_THREAD },
346 	{ "ereport.cpu.*.sbdlc",	cmd_miscregs_train,
347 	    CMD_ERRCL_SBDLC | CMD_CPU_LEVEL_THREAD },
348 	{ "ereport.cpu.*.sbdpu",	cmd_miscregs_ue,
349 	    CMD_CPU_LEVEL_THREAD },
350 	{ "ereport.cpu.*.sbdlu",	cmd_miscregs_ue,
351 	    CMD_CPU_LEVEL_THREAD },
352 	{ "ereport.cpu.*.sbdio",	cmd_miscregs_ue,
353 	    CMD_CPU_LEVEL_THREAD },
354 	{ "ereport.cpu.*.sbapp",	cmd_miscregs_ue,
355 	    CMD_CPU_LEVEL_THREAD },
356 	{ "ereport.cpu.*.mrau",		cmd_miscregs_ue,
357 	    CMD_CPU_LEVEL_THREAD },
358 	{ "ereport.cpu.*.scac",		cmd_miscregs_train,
359 	    CMD_ERRCL_SBDPC | CMD_CPU_LEVEL_THREAD },
360 	{ "ereport.cpu.*.scau",		cmd_miscregs_ue,
361 	    CMD_CPU_LEVEL_THREAD },
362 	{ "ereport.cpu.*.tccp",		cmd_miscregs_train,
363 	    CMD_ERRCL_TCCP | CMD_CPU_LEVEL_THREAD },
364 	{ "ereport.cpu.*.tccd",		cmd_miscregs_train,
365 	    CMD_ERRCL_TCCD | CMD_CPU_LEVEL_THREAD },
366 	{ "ereport.cpu.*.tcup",		cmd_miscregs_ue,
367 	    CMD_CPU_LEVEL_THREAD },
368 	{ "ereport.cpu.*.tcud",		cmd_miscregs_ue,
369 	    CMD_CPU_LEVEL_THREAD },
370 	{ "ereport.cpu.*.tsac",		cmd_miscregs_train,
371 	    CMD_ERRCL_SBDPC | CMD_CPU_LEVEL_THREAD },
372 	{ "ereport.cpu.*.tsau",		cmd_miscregs_ue,
373 	    CMD_CPU_LEVEL_THREAD },
374 	{ "ereport.cpu.*.cbce",		cmd_xxc,	CMD_ERRCL_CBCE |
375 	    CMD_CPU_LEVEL_CHIP },
376 	{ "ereport.cpu.*.dce",		cmd_nop },
377 	{ "ereport.cpu.*.wbue",		cmd_xxu,	CMD_ERRCL_WBUE |
378 	    CMD_CPU_LEVEL_CHIP },
379 	{ "ereport.cpu.*.lfu-slf",	cmd_lfu_ce,	CMD_CPU_LEVEL_CHIP },
380 	{ "ereport.cpu.*.lfu-rtf",	cmd_lfu_ue,	CMD_CPU_LEVEL_CHIP },
381 	{ "ereport.cpu.*.lfu-tto",	cmd_lfu_ue,	CMD_CPU_LEVEL_CHIP },
382 	{ "ereport.cpu.*.lfu-cto",	cmd_lfu_ue,	CMD_CPU_LEVEL_CHIP },
383 	{ "ereport.cpu.*.lfu-mlf",	cmd_lfu_ue,	CMD_CPU_LEVEL_CHIP },
384 	{ "ereport.cpu.*.frack",	cmd_lfu_pe,	CMD_CPU_LEVEL_CHIP },
385 	{ "ereport.cpu.*.fsr",		cmd_lfu_pe,	CMD_CPU_LEVEL_CHIP },
386 	{ "ereport.cpu.*.fdr", 		cmd_lfu_pe,	CMD_CPU_LEVEL_CHIP },
387 	{ "ereport.cpu.*.to",  		cmd_lfu_pe,	CMD_CPU_LEVEL_CHIP },
388 	{ "ereport.cpu.*.snptyp",	cmd_lfu_pe,	CMD_CPU_LEVEL_CHIP },
389 	{ "ereport.fm.ferg.invalid",	cmd_fw_defect },
390 #endif /* sun4u */
391 	{ "ereport.cpu.*.fpu.hwcopy",	cmd_fpu },
392 	{ NULL, NULL }
393 };
394 
395 static void
cmd_recv(fmd_hdl_t * hdl,fmd_event_t * ep,nvlist_t * nvl,const char * class)396 cmd_recv(fmd_hdl_t *hdl, fmd_event_t *ep, nvlist_t *nvl, const char *class)
397 {
398 	cmd_subscriber_t *sp;
399 	int disp;
400 
401 	fmd_hdl_debug(hdl, "cmd_recv: begin: %s\n", strrchr(class, '.') + 1);
402 
403 	for (sp = cmd_subscribers; sp->subr_class != NULL; sp++) {
404 		if (fmd_nvl_class_match(hdl, nvl, sp->subr_class)) {
405 			disp = sp->subr_func(hdl, ep, nvl, class, sp->subr_arg);
406 			((fmd_stat_t *)&sp->subr_stat)[disp].fmds_value.ui64++;
407 			fmd_hdl_debug(hdl, "cmd_recv: done: %s (disp %d)\n",
408 			    strrchr(class, '.') + 1, disp);
409 			return;
410 		}
411 	}
412 
413 	fmd_hdl_debug(hdl, "cmd_recv: dropping %s - unable to handle\n", class);
414 }
415 
416 static void
cmd_timeout(fmd_hdl_t * hdl,id_t id,void * arg)417 cmd_timeout(fmd_hdl_t *hdl, id_t id, void *arg)
418 {
419 	uintptr_t	timertype = (uintptr_t)arg;
420 
421 	switch (timertype) {
422 		case CMD_TIMERTYPE_MEM:
423 			cmd_mem_timeout(hdl, id);
424 			break;
425 
426 #ifdef sun4u
427 		case CMD_TIMERTYPE_DP:
428 
429 			cmd_dp_timeout(hdl, id);
430 			break;
431 		case CMD_TIMERTYPE_ANONYMOUS_TAG_ERROR:
432 
433 			cmd_Lxcache_anonymous_tag_error_timeout(hdl, id);
434 			break;
435 #endif
436 
437 		case CMD_TIMERTYPE_CPU_UEC_FLUSH:
438 		case CMD_TIMERTYPE_CPU_XR_WAITER:
439 			cmd_cpu_timeout(hdl, id, (void *)timertype);
440 			break;
441 
442 		default:
443 			break;
444 	}
445 }
446 
447 static void
cmd_close(fmd_hdl_t * hdl,fmd_case_t * cp)448 cmd_close(fmd_hdl_t *hdl, fmd_case_t *cp)
449 {
450 	cmd_case_closer_t *cl = fmd_case_getspecific(hdl, cp);
451 	const char *uuid = fmd_case_uuid(hdl, cp);
452 
453 	/*
454 	 * Our active cases all have closers registered in case-specific data.
455 	 * Cases in the process of closing (for which we've freed all associated
456 	 * data, but which haven't had an fmd-initiated fmdo_close callback)
457 	 * have had their case-specific data nulled out.
458 	 */
459 	fmd_hdl_debug(hdl, "close case %s%s\n", uuid,
460 	    (cl == NULL ? " (no cl)" : ""));
461 
462 	if (cl != NULL)
463 		cl->cl_func(hdl, cl->cl_arg);
464 }
465 
466 static void
cmd_gc(fmd_hdl_t * hdl)467 cmd_gc(fmd_hdl_t *hdl)
468 {
469 	cmd_cpu_gc(hdl);
470 	cmd_mem_gc(hdl);
471 #ifdef sun4u
472 	cmd_Lxcache_gc(hdl);
473 #endif
474 }
475 
476 static cmd_stat_t cmd_stats = {
477 	{ "bad_det", FMD_TYPE_UINT64, "detector missing or malformed" },
478 	{ "bad_cpu_asru", FMD_TYPE_UINT64, "CPU ASRU missing or malformed" },
479 	{ "bad_mem_asru", FMD_TYPE_UINT64, "memory ASRU missing or malformed" },
480 	{ "bad_close", FMD_TYPE_UINT64, "case close for nonexistent case" },
481 	{ "old_erpt", FMD_TYPE_UINT64, "ereport out of date wrt hardware" },
482 	{ "cpu_creat", FMD_TYPE_UINT64, "created new cpu structure" },
483 	{ "dimm_creat", FMD_TYPE_UINT64, "created new mem module structure" },
484 	{ "bank_creat", FMD_TYPE_UINT64, "created new mem bank structure" },
485 	{ "page_creat", FMD_TYPE_UINT64, "created new page structure" },
486 	{ "cache_creat", FMD_TYPE_UINT64, "created new cache structure" },
487 	{ "ce_unknown", FMD_TYPE_UINT64, "unknown CEs" },
488 	{ "ce_interm", FMD_TYPE_UINT64, "intermittent CEs" },
489 	{ "ce_ppersis", FMD_TYPE_UINT64, "possibly persistent CEs" },
490 	{ "ce_persis", FMD_TYPE_UINT64, "persistent CEs" },
491 	{ "ce_leaky", FMD_TYPE_UINT64, "leaky CEs" },
492 	{ "ce_psticky_noptnr", FMD_TYPE_UINT64,
493 	    "possibly sticky CEs, no partner test" },
494 	{ "ce_psticky_ptnrnoerr", FMD_TYPE_UINT64,
495 	    "possibly sticky CEs, partner sees no CE" },
496 	{ "ce_psticky_ptnrclrd", FMD_TYPE_UINT64,
497 	    "possibly sticky CEs, partner can clear CE" },
498 	{ "ce_sticky", FMD_TYPE_UINT64, "sticky CEs" },
499 	{ "xxu_ue_match", FMD_TYPE_UINT64, "xxUs obviated by UEs" },
500 	{ "xxu_retr_flt", FMD_TYPE_UINT64, "xxUs obviated by faults" },
501 	{ "cpu_migrat", FMD_TYPE_UINT64, "CPUs migrated to new version" },
502 	{ "dimm_migrat", FMD_TYPE_UINT64, "DIMMs migrated to new version" },
503 	{ "bank_migrat", FMD_TYPE_UINT64, "banks migrated to new version" },
504 #ifdef sun4u
505 	{ "dp_ignored_ce", FMD_TYPE_UINT64,
506 	    "memory CEs ignored due to DP error or fault" },
507 	{ "dp_ignored_ue", FMD_TYPE_UINT64,
508 	    "memory UEs ignored due to DP fault" },
509 	{ "dp_deferred_ue", FMD_TYPE_UINT64,
510 	    "memory UEs deferred due to DP error" },
511 #endif
512 #ifdef sun4v
513 	{ "branch_creat", FMD_TYPE_UINT64, "created new mem branch structure" },
514 #endif
515 };
516 
517 static const fmd_prop_t fmd_props[] = {
518 	{ "icache_n", FMD_TYPE_UINT32, "8" },
519 	{ "icache_t", FMD_TYPE_TIME, "168h" },
520 	{ "dcache_n", FMD_TYPE_UINT32, "8" },
521 	{ "dcache_t", FMD_TYPE_TIME, "168h" },
522 	{ "pcache_n", FMD_TYPE_UINT32, "2" },
523 	{ "pcache_t", FMD_TYPE_TIME, "168h" },
524 #ifdef sun4u
525 	{ "itlb_n", FMD_TYPE_UINT32, "2" },
526 	{ "itlb_t", FMD_TYPE_TIME, "168h" },
527 	{ "dtlb_n", FMD_TYPE_UINT32, "2" },
528 	{ "dtlb_t", FMD_TYPE_TIME, "168h" },
529 	{ "l2tag_n", FMD_TYPE_UINT32, "4" },
530 	{ "l2tag_t", FMD_TYPE_TIME, "1h" },
531 	{ "l2data_n", FMD_TYPE_UINT32, "12" },
532 	{ "l2data_t", FMD_TYPE_TIME, "1h" },
533 #else
534 	{ "itlb_n", FMD_TYPE_UINT32, "8" },
535 	{ "itlb_t", FMD_TYPE_TIME, "168h" },
536 	{ "dtlb_n", FMD_TYPE_UINT32, "8" },
537 	{ "dtlb_t", FMD_TYPE_TIME, "168h" },
538 	{ "l2tag_n", FMD_TYPE_UINT32, "8" },
539 	{ "l2tag_t", FMD_TYPE_TIME, "20h" },
540 	{ "l2data_n", FMD_TYPE_UINT32, "8" },
541 	{ "l2data_t", FMD_TYPE_TIME, "2h" },
542 #endif
543 	{ "l3tag_n", FMD_TYPE_UINT32, "4" },
544 	{ "l3tag_t", FMD_TYPE_TIME, "1h" },
545 	{ "l3data_n", FMD_TYPE_UINT32, "12" },
546 	{ "l3data_t", FMD_TYPE_TIME, "1h" },
547 	{ "ce_n", FMD_TYPE_UINT32, "2" },
548 	{ "ce_t", FMD_TYPE_TIME, "72h" },
549 	{ "ireg_n", FMD_TYPE_UINT32, "8" },
550 	{ "ireg_t", FMD_TYPE_TIME, "168h" },
551 	{ "freg_n", FMD_TYPE_UINT32, "8" },
552 	{ "freg_t", FMD_TYPE_TIME, "168h" },
553 	{ "mau_n", FMD_TYPE_UINT32, "0" },
554 	{ "mau_t", FMD_TYPE_TIME, "168h" },
555 	{ "misc_regs_n", FMD_TYPE_UINT32, "8"},
556 	{ "misc_regs_t", FMD_TYPE_TIME, "168h" },
557 	{ "iorxefrx_window", FMD_TYPE_TIME, "3s" },
558 #ifdef sun4u
559 	{ "xxcu_trdelay", FMD_TYPE_TIME, "200ms" },
560 #else
561 	{ "xxcu_trdelay", FMD_TYPE_TIME, "15s"},
562 #endif /* sun4u */
563 	{ "xxcu_restart_delay", FMD_TYPE_TIME, "1s" },
564 	{ "num_xxcu_waiters", FMD_TYPE_UINT32, "128" },
565 	{ "thresh_tpct_sysmem", FMD_TYPE_UINT64, "100" },
566 	{ "thresh_abs_sysmem", FMD_TYPE_UINT64, "0" },
567 	{ "thresh_abs_badrw", FMD_TYPE_UINT64, "128" },
568 	{ "max_perm_ce_dimm", FMD_TYPE_UINT32, "128" },
569 	{ "low_ce_thresh", FMD_TYPE_UINT32, "128" },
570 	{ "hi_ce_thresh", FMD_TYPE_UINT32, "512" },
571 	{ "dupce", FMD_TYPE_UINT32, "120"},
572 	{ "nupos", FMD_TYPE_UINT32, "4"},
573 #ifdef sun4v
574 	{ "fbr_n", FMD_TYPE_UINT32, "14" },
575 	{ "fbr_t", FMD_TYPE_TIME, "30min"},
576 	/* delta_ena value = 0x500000000nsec ~= 22sec */
577 	{ "delta_ena", FMD_TYPE_UINT64, "0x50000000000000"},
578 #endif
579 	{ NULL, 0, NULL }
580 };
581 
582 static const fmd_hdl_ops_t fmd_ops = {
583 	cmd_recv,	/* fmdo_recv */
584 	cmd_timeout,	/* fmdo_timeout */
585 	cmd_close,	/* fmdo_close */
586 	NULL,		/* fmdo_stats */
587 	cmd_gc		/* fmdo_gc */
588 };
589 
590 static const fmd_hdl_info_t fmd_info = {
591 	"CPU/Memory Diagnosis", CMD_VERSION, &fmd_ops, fmd_props
592 };
593 
594 static const struct cmd_evdisp_name {
595 	const char *evn_name;
596 	const char *evn_desc;
597 } cmd_evdisp_names[] = {
598 	{ "%s", "ok %s ereports" },			/* CMD_EVD_OK */
599 	{ "bad_%s", "bad %s ereports" },		/* CMD_EVD_BAD */
600 	{ "unused_%s", "unused %s ereports" },		/* CMD_EVD_UNUSED */
601 	{ "redun_%s", "redundant %s ereports" },	/* CMD_EVD_REDUN */
602 };
603 
604 void
_fmd_fini(fmd_hdl_t * hdl)605 _fmd_fini(fmd_hdl_t *hdl)
606 {
607 
608 #ifdef	sun4v
609 	ldom_fini(cpumem_diagnosis_lhp);
610 #endif
611 	cmd_cpu_fini(hdl);
612 	cmd_mem_fini(hdl);
613 	cmd_page_fini(hdl);
614 #ifdef sun4u
615 	cmd_dp_fini(hdl);
616 #endif
617 
618 	fmd_hdl_free(hdl, cmd.cmd_xxcu_trw,
619 	    sizeof (cmd_xxcu_trw_t) * cmd.cmd_xxcu_ntrw);
620 	nvlist_free(cmd.cmd_auth);
621 }
622 
623 #ifdef	sun4v
624 static void *
cpumem_diagnosis_init_alloc(size_t size)625 cpumem_diagnosis_init_alloc(size_t size)
626 {
627 	return (fmd_hdl_alloc(init_hdl, size, FMD_SLEEP));
628 }
629 
630 static void
cpumem_diagnosis_init_free(void * addr,size_t size)631 cpumem_diagnosis_init_free(void *addr, size_t size)
632 {
633 	fmd_hdl_free(init_hdl, addr, size);
634 }
635 #endif
636 
637 /* find_auth -- find hardware platform authority within libtopo */
638 
639 /* ARGSUSED */
640 static int
find_auth(topo_hdl_t * thp,tnode_t * node,void * arg)641 find_auth(topo_hdl_t *thp, tnode_t *node, void *arg)
642 {
643 	int err;
644 	nvlist_t *rsrc, *auth;
645 
646 	if (cmd.cmd_auth != NULL)
647 		return (TOPO_WALK_TERMINATE); /* don't overwrite previous */
648 
649 	if (topo_node_resource(node, &rsrc, &err) < 0)
650 		return (TOPO_WALK_NEXT);	/* no resource, try next */
651 	if (nvlist_lookup_nvlist(rsrc, FM_FMRI_AUTHORITY, &auth) < 0) {
652 		nvlist_free(rsrc);
653 		return (TOPO_WALK_NEXT);	/* no authority, try next */
654 	}
655 	(void) nvlist_dup(auth, &cmd.cmd_auth, NV_UNIQUE_NAME);
656 	nvlist_free(rsrc);
657 	return (TOPO_WALK_TERMINATE);	/* if no space, give up */
658 }
659 
660 /* init_auth -- read hardware platform authority from libtopo */
661 
662 void
init_auth(fmd_hdl_t * hdl)663 init_auth(fmd_hdl_t *hdl)
664 {
665 	topo_hdl_t *thp;
666 	topo_walk_t *twp;
667 	int err;
668 
669 	if ((thp = fmd_hdl_topo_hold(hdl, TOPO_VERSION)) == NULL)
670 		return;
671 	if ((twp = topo_walk_init(thp,
672 	    FM_FMRI_SCHEME_HC, find_auth, NULL, &err))
673 	    == NULL) {
674 		fmd_hdl_topo_rele(hdl, thp);
675 		return;
676 	}
677 	(void) topo_walk_step(twp, TOPO_WALK_CHILD);
678 	topo_walk_fini(twp);
679 	fmd_hdl_topo_rele(hdl, thp);
680 }
681 
682 void
_fmd_init(fmd_hdl_t * hdl)683 _fmd_init(fmd_hdl_t *hdl)
684 {
685 	cmd_subscriber_t *sp;
686 	cpu_family_t cpu_family;
687 
688 	if (fmd_hdl_register(hdl, FMD_API_VERSION, &fmd_info) != 0)
689 		return; /* error in configuration file or fmd_info */
690 
691 	cpu_family = cmd_cpu_check_support();
692 
693 	if (cpu_family == CMD_CPU_FAM_UNSUPPORTED) {
694 		fmd_hdl_debug(hdl, "no supported CPUs found");
695 		fmd_hdl_unregister(hdl);
696 		return;
697 	}
698 
699 	fmd_hdl_subscribe(hdl, "ereport.cpu.ultraSPARC-III.*");
700 	fmd_hdl_subscribe(hdl, "ereport.cpu.ultraSPARC-IIIplus.*");
701 	fmd_hdl_subscribe(hdl, "ereport.cpu.ultraSPARC-IIIi.*");
702 	fmd_hdl_subscribe(hdl, "ereport.cpu.ultraSPARC-IIIiplus.*");
703 	fmd_hdl_subscribe(hdl, "ereport.cpu.ultraSPARC-IV.*");
704 	fmd_hdl_subscribe(hdl, "ereport.cpu.ultraSPARC-IVplus.*");
705 	fmd_hdl_subscribe(hdl, "ereport.cpu.ultraSPARC-T2.*");
706 	fmd_hdl_subscribe(hdl, "ereport.cpu.ultraSPARC-T2plus.*");
707 	fmd_hdl_subscribe(hdl, "ereport.cpu.ultraSPARC-T1.*");
708 	fmd_hdl_subscribe(hdl, "ereport.fm.ferg.invalid");
709 
710 	fmd_hdl_subscribe(hdl, "ereport.io.tom.ecc.drce");
711 	fmd_hdl_subscribe(hdl, "ereport.io.tom.ecc.dwce");
712 	fmd_hdl_subscribe(hdl, "ereport.io.tom.ecc.drue");
713 	fmd_hdl_subscribe(hdl, "ereport.io.tom.ecc.dwue");
714 	fmd_hdl_subscribe(hdl, "ereport.io.sch.ecc.drce");
715 	fmd_hdl_subscribe(hdl, "ereport.io.sch.ecc.dwce");
716 	fmd_hdl_subscribe(hdl, "ereport.io.sch.ecc.drue");
717 	fmd_hdl_subscribe(hdl, "ereport.io.sch.ecc.dwue");
718 	fmd_hdl_subscribe(hdl, "ereport.io.xmits.ecc.drce");
719 	fmd_hdl_subscribe(hdl, "ereport.io.xmits.ecc.dwce");
720 	fmd_hdl_subscribe(hdl, "ereport.io.xmits.ecc.drue");
721 	fmd_hdl_subscribe(hdl, "ereport.io.xmits.ecc.dwue");
722 
723 	/*
724 	 * Need to subscribe to secondary I/O ECC ereports, but
725 	 * since they contain no data regarding the failure we
726 	 * are unable to do anything with them.
727 	 */
728 	fmd_hdl_subscribe(hdl, "ereport.io.tom.ecc.s-drce");
729 	fmd_hdl_subscribe(hdl, "ereport.io.tom.ecc.s-dwce");
730 	fmd_hdl_subscribe(hdl, "ereport.io.tom.ecc.s-drue");
731 	fmd_hdl_subscribe(hdl, "ereport.io.tom.ecc.s-dwue");
732 	fmd_hdl_subscribe(hdl, "ereport.io.sch.ecc.s-drce");
733 	fmd_hdl_subscribe(hdl, "ereport.io.sch.ecc.s-dwce");
734 	fmd_hdl_subscribe(hdl, "ereport.io.sch.ecc.s-drue");
735 	fmd_hdl_subscribe(hdl, "ereport.io.sch.ecc.s-dwue");
736 	fmd_hdl_subscribe(hdl, "ereport.io.xmits.ecc.s-drce");
737 	fmd_hdl_subscribe(hdl, "ereport.io.xmits.ecc.s-dwce");
738 	fmd_hdl_subscribe(hdl, "ereport.io.xmits.ecc.s-drue");
739 	fmd_hdl_subscribe(hdl, "ereport.io.xmits.ecc.s-dwue");
740 
741 #ifdef sun4u
742 	/*
743 	 * Subscribe to datapath events
744 	 */
745 	fmd_hdl_subscribe(hdl, "ereport.asic.*.cds.cds-dp");
746 	fmd_hdl_subscribe(hdl, "ereport.asic.*.dx.dx-dp");
747 	fmd_hdl_subscribe(hdl, "ereport.asic.*.sdi.sdi-dp");
748 	fmd_hdl_subscribe(hdl, "ereport.asic.*.cp.cp-dp");
749 	fmd_hdl_subscribe(hdl, "ereport.asic.*.rp.rp-dp");
750 
751 	/*
752 	 * OPL platform specific subscriptions.
753 	 */
754 	fmd_hdl_subscribe(hdl, "ereport.cpu.SPARC64-VI.*");
755 	fmd_hdl_subscribe(hdl, "ereport.cpu.SPARC64-VII.*");
756 	fmd_hdl_subscribe(hdl, "ereport.asic.mac.*");
757 	fmd_hdl_subscribe(hdl, "ereport.io.oberon.ubc.dmarduea-mem");
758 	fmd_hdl_subscribe(hdl, "ereport.io.oberon.ubc.dmarduea-channel");
759 	fmd_hdl_subscribe(hdl, "ereport.io.oberon.ubc.dmarduea-cpu");
760 	fmd_hdl_subscribe(hdl, "ereport.io.oberon.ubc.dmarduea-path");
761 	fmd_hdl_subscribe(hdl, "ereport.io.oberon.ubc.dmardueb-mem");
762 	fmd_hdl_subscribe(hdl, "ereport.io.oberon.ubc.dmardueb-channel");
763 	fmd_hdl_subscribe(hdl, "ereport.io.oberon.ubc.dmardueb-cpu");
764 	fmd_hdl_subscribe(hdl, "ereport.io.oberon.ubc.dmardueb-path");
765 	fmd_hdl_subscribe(hdl, "ereport.io.oberon.ubc.piowtue-mem");
766 	fmd_hdl_subscribe(hdl, "ereport.io.oberon.ubc.piowtue-channel");
767 	fmd_hdl_subscribe(hdl, "ereport.io.oberon.ubc.piowtue-cpu");
768 	fmd_hdl_subscribe(hdl, "ereport.io.oberon.ubc.piowtue-path");
769 	fmd_hdl_subscribe(hdl, "ereport.io.oberon.ubc.piowbeue-mem");
770 	fmd_hdl_subscribe(hdl, "ereport.io.oberon.ubc.piowbeue-channel");
771 	fmd_hdl_subscribe(hdl, "ereport.io.oberon.ubc.piowbeue-cpu");
772 	fmd_hdl_subscribe(hdl, "ereport.io.oberon.ubc.piowbeue-path");
773 	fmd_hdl_subscribe(hdl, "ereport.io.oberon.ubc.piorbeue-mem");
774 	fmd_hdl_subscribe(hdl, "ereport.io.oberon.ubc.piorbeue-channel");
775 	fmd_hdl_subscribe(hdl, "ereport.io.oberon.ubc.piorbeue-cpu");
776 	fmd_hdl_subscribe(hdl, "ereport.io.oberon.ubc.piorbeue-path");
777 #endif
778 	fmd_hdl_subscribe(hdl, "ereport.io.fire.jbc.ce_asyn");
779 	fmd_hdl_subscribe(hdl, "ereport.io.fire.jbc.ue_asyn");
780 
781 	bzero(&cmd, sizeof (cmd_t));
782 
783 #ifdef sun4u
784 	bzero(&opl_cpu_list, sizeof (cmd_list_t));
785 #endif	/* sun4u */
786 
787 	cmd.cmd_stats = (cmd_stat_t *)fmd_stat_create(hdl, FMD_STAT_NOALLOC,
788 	    sizeof (cmd_stats) / sizeof (fmd_stat_t),
789 	    (fmd_stat_t *)&cmd_stats);
790 
791 	for (sp = cmd_subscribers; sp->subr_class != NULL; sp++) {
792 		const char *type = strrchr(sp->subr_class, '.') + 1;
793 		int i;
794 
795 		for (i = 0; i < sizeof (cmd_evdisp_names) /
796 		    sizeof (struct cmd_evdisp_name); i++) {
797 			fmd_stat_t *stat = ((fmd_stat_t *)&sp->subr_stat) + i;
798 
799 			(void) snprintf(stat->fmds_name,
800 			    sizeof (stat->fmds_name),
801 			    cmd_evdisp_names[i].evn_name, type);
802 
803 			stat->fmds_type = FMD_TYPE_UINT64;
804 			(void) snprintf(stat->fmds_desc,
805 			    sizeof (stat->fmds_desc),
806 			    cmd_evdisp_names[i].evn_desc, type);
807 
808 			(void) fmd_stat_create(hdl, FMD_STAT_NOALLOC, 1, stat);
809 		}
810 	}
811 
812 	cmd.cmd_pagesize = sysconf(_SC_PAGESIZE);
813 	cmd.cmd_pagemask = ~((uint64_t)cmd.cmd_pagesize - 1);
814 
815 	cmd.cmd_iorxefrx_window = fmd_prop_get_int64(hdl, "iorxefrx_window");
816 
817 #ifdef sun4u
818 	if (cmd_cpu_ecache_support() && cmd_ecache_init() < 0) {
819 		_fmd_fini(hdl);
820 		fmd_hdl_abort(hdl, "failed to find device for E-cache flush");
821 	}
822 #endif
823 
824 	if ((cmd.cmd_thresh_tpct_sysmem = fmd_prop_get_int64(hdl,
825 	    "thresh_tpct_sysmem")) > 100000) {
826 		_fmd_fini(hdl);
827 		fmd_hdl_abort(hdl, "page retirement threshold is >100%");
828 	}
829 
830 	cmd.cmd_thresh_abs_sysmem = fmd_prop_get_int64(hdl,
831 	    "thresh_abs_sysmem");
832 	cmd.cmd_thresh_abs_badrw = fmd_prop_get_int64(hdl,
833 	    "thresh_abs_badrw");
834 
835 	cmd.cmd_xxcu_trdelay = fmd_prop_get_int64(hdl, "xxcu_trdelay");
836 
837 	cmd.cmd_xxcu_ntrw = fmd_prop_get_int32(hdl, "num_xxcu_waiters");
838 	cmd.cmd_xxcu_trw = fmd_hdl_zalloc(hdl, sizeof (cmd_xxcu_trw_t) *
839 	    cmd.cmd_xxcu_ntrw, FMD_SLEEP);
840 	cmd.cmd_low_ce_thresh = fmd_prop_get_int32(hdl, "low_ce_thresh");
841 	cmd.cmd_hi_ce_thresh = fmd_prop_get_int32(hdl, "hi_ce_thresh");
842 	cmd.cmd_dupce = fmd_prop_get_int32(hdl, "dupce");
843 	cmd.cmd_nupos = fmd_prop_get_int32(hdl, "nupos");
844 
845 #ifdef sun4v
846 	cmd.cmd_delta_ena = fmd_prop_get_int64(hdl, "delta_ena");
847 #endif
848 
849 	cmd.cmd_l2data_serd.cs_name = "l2data";
850 	cmd.cmd_l2data_serd.cs_n = fmd_prop_get_int32(hdl, "l2data_n");
851 	cmd.cmd_l2data_serd.cs_t = fmd_prop_get_int64(hdl, "l2data_t");
852 
853 	cmd.cmd_l3data_serd.cs_name = "l3data";
854 	cmd.cmd_l3data_serd.cs_n = fmd_prop_get_int32(hdl, "l3data_n");
855 	cmd.cmd_l3data_serd.cs_t = fmd_prop_get_int64(hdl, "l3data_t");
856 
857 	cmd.cmd_miscregs_serd.cs_name = "misc_regs";
858 	cmd.cmd_miscregs_serd.cs_n = fmd_prop_get_int32(hdl, "misc_regs_n");
859 	cmd.cmd_miscregs_serd.cs_t = fmd_prop_get_int64(hdl, "misc_regs_t");
860 
861 	cmd.cmd_dcache_serd.cs_name = "dcache";
862 	cmd.cmd_dcache_serd.cs_n = fmd_prop_get_int32(hdl, "dcache_n");
863 	cmd.cmd_dcache_serd.cs_t = fmd_prop_get_int64(hdl, "dcache_t");
864 
865 	cmd.cmd_icache_serd.cs_name = "icache";
866 	cmd.cmd_icache_serd.cs_n = fmd_prop_get_int32(hdl, "icache_n");
867 	cmd.cmd_icache_serd.cs_t = fmd_prop_get_int64(hdl, "icache_t");
868 
869 	if (cmd_state_restore(hdl) < 0) {
870 		_fmd_fini(hdl);
871 		fmd_hdl_abort(hdl, "failed to restore saved state\n");
872 	}
873 
874 #ifdef	sun4v
875 	init_hdl = hdl;
876 	cpumem_diagnosis_lhp = ldom_init(cpumem_diagnosis_init_alloc,
877 	    cpumem_diagnosis_init_free);
878 #endif
879 
880 	init_auth(hdl);
881 }
882