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