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 * Ereport-handling routines for CPU errors 28 */ 29 30 #include <cmd_cpu.h> 31 #include <cmd.h> 32 33 #include <strings.h> 34 #include <string.h> 35 #include <errno.h> 36 #include <fm/fmd_api.h> 37 #include <sys/fm/protocol.h> 38 #include <sys/async.h> 39 #ifdef sun4u 40 #include <sys/fm/cpu/UltraSPARC-III.h> 41 #include <cmd_Lxcache.h> 42 #include <cmd_opl.h> 43 #endif 44 45 /* 46 * We follow the same algorithm for handling all L1$, TLB, and L2/L3 cache 47 * tag events so we can have one common routine into which each handler 48 * calls. The two tests of (strcmp(serdnm, "") != 0) are used to eliminate 49 * the need for a separate macro for UEs which override SERD engine 50 * counting CEs leading to same fault. 51 */ 52 /*ARGSUSED9*/ 53 static cmd_evdisp_t 54 cmd_cpuerr_common(fmd_hdl_t *hdl, fmd_event_t *ep, cmd_cpu_t *cpu, 55 cmd_case_t *cc, cmd_ptrsubtype_t pstype, const char *serdnm, 56 const char *serdn, const char *serdt, const char *fltnm, 57 cmd_errcl_t clcode) 58 { 59 const char *uuid; 60 61 if (cc->cc_cp != NULL && fmd_case_solved(hdl, cc->cc_cp)) 62 return (CMD_EVD_REDUND); 63 64 if (cc->cc_cp == NULL) { 65 cc->cc_cp = cmd_case_create(hdl, &cpu->cpu_header, pstype, 66 &uuid); 67 if (strcmp(serdnm, "") != 0) { 68 cc->cc_serdnm = cmd_cpu_serdnm_create(hdl, cpu, 69 serdnm); 70 fmd_serd_create(hdl, cc->cc_serdnm, 71 fmd_prop_get_int32(hdl, serdn), 72 fmd_prop_get_int64(hdl, serdt)); 73 } 74 } 75 76 if (strcmp(serdnm, "") != 0) { 77 fmd_hdl_debug(hdl, "adding event to %s\n", cc->cc_serdnm); 78 if (fmd_serd_record(hdl, cc->cc_serdnm, ep) == FMD_B_FALSE) 79 return (CMD_EVD_OK); /* serd engine hasn't fired yet */ 80 81 fmd_case_add_serd(hdl, cc->cc_cp, cc->cc_serdnm); 82 } else { 83 if (cc->cc_serdnm != NULL) { 84 fmd_hdl_debug(hdl, 85 "destroying existing %s state for class %x\n", 86 cc->cc_serdnm, clcode); 87 fmd_serd_destroy(hdl, cc->cc_serdnm); 88 fmd_hdl_strfree(hdl, cc->cc_serdnm); 89 cc->cc_serdnm = NULL; 90 } 91 fmd_case_reset(hdl, cc->cc_cp); 92 fmd_case_add_ereport(hdl, cc->cc_cp, ep); 93 } 94 95 cmd_cpu_create_faultlist(hdl, cc->cc_cp, cpu, fltnm, NULL, 100); 96 97 fmd_case_solve(hdl, cc->cc_cp); 98 99 return (CMD_EVD_OK); 100 } 101 #ifdef sun4u 102 103 #define CMD_CPU_TAGHANDLER(name, casenm, ptr, ntname, fltname) \ 104 cmd_evdisp_t \ 105 cmd_##name(fmd_hdl_t *hdl, fmd_event_t *ep, nvlist_t *nvl, \ 106 const char *class, cmd_errcl_t clcode) \ 107 { \ 108 uint8_t level = clcode & CMD_ERRCL_LEVEL_EXTRACT; \ 109 cmd_cpu_t *cpu; \ 110 \ 111 clcode &= CMD_ERRCL_LEVEL_MASK; \ 112 if ((cpu = cmd_cpu_lookup_from_detector(hdl, nvl, class, \ 113 level)) == NULL || cpu->cpu_faulting) \ 114 return (CMD_EVD_UNUSED); \ 115 \ 116 if ((strstr(class, "ultraSPARC-IVplus.l3-thce") != 0) || \ 117 (strstr(class, "ultraSPARC-IVplus.thce") != 0)) { \ 118 return (cmd_us4plus_tag_err(hdl, ep, nvl, cpu, \ 119 ptr, ntname "_n", ntname "_t", fltname, clcode)); \ 120 } \ 121 return (cmd_cpuerr_common(hdl, ep, cpu, &cpu->cpu_##casenm, \ 122 ptr, ntname, ntname "_n", ntname "_t", fltname, clcode)); \ 123 } 124 #endif 125 126 #define CMD_CPU_SIMPLEHANDLER(name, casenm, ptr, ntname, fltname) \ 127 cmd_evdisp_t \ 128 cmd_##name(fmd_hdl_t *hdl, fmd_event_t *ep, nvlist_t *nvl, \ 129 const char *class, cmd_errcl_t clcode) \ 130 { \ 131 uint8_t level = clcode & CMD_ERRCL_LEVEL_EXTRACT; \ 132 cmd_cpu_t *cpu; \ 133 \ 134 clcode &= CMD_ERRCL_LEVEL_MASK; \ 135 if ((cpu = cmd_cpu_lookup_from_detector(hdl, nvl, class, \ 136 level)) == NULL || cpu->cpu_faulting) \ 137 return (CMD_EVD_UNUSED); \ 138 \ 139 return (cmd_cpuerr_common(hdl, ep, cpu, &cpu->cpu_##casenm, \ 140 ptr, ntname, ntname "_n", ntname "_t", fltname, clcode)); \ 141 } 142 143 #ifdef sun4u 144 CMD_CPU_TAGHANDLER(txce, l2tag, CMD_PTR_CPU_L2TAG, "l2tag", "l2cachetag") 145 CMD_CPU_TAGHANDLER(l3_thce, l3tag, CMD_PTR_CPU_L3TAG, "l3tag", "l3cachetag") 146 #else 147 CMD_CPU_SIMPLEHANDLER(txce, l2tag, CMD_PTR_CPU_L2TAG, "l2tag", "l2cachetag") 148 CMD_CPU_SIMPLEHANDLER(l3_thce, l3tag, CMD_PTR_CPU_L3TAG, "l3tag", "l3cachetag") 149 #endif 150 CMD_CPU_SIMPLEHANDLER(icache, icache, CMD_PTR_CPU_ICACHE, "icache", "icache") 151 CMD_CPU_SIMPLEHANDLER(dcache, dcache, CMD_PTR_CPU_DCACHE, "dcache", "dcache") 152 CMD_CPU_SIMPLEHANDLER(pcache, pcache, CMD_PTR_CPU_PCACHE, "pcache", "pcache") 153 CMD_CPU_SIMPLEHANDLER(itlb, itlb, CMD_PTR_CPU_ITLB, "itlb", "itlb") 154 CMD_CPU_SIMPLEHANDLER(dtlb, dtlb, CMD_PTR_CPU_DTLB, "dtlb", "dtlb") 155 CMD_CPU_SIMPLEHANDLER(irc, ireg, CMD_PTR_CPU_IREG, "ireg", "ireg") 156 CMD_CPU_SIMPLEHANDLER(frc, freg, CMD_PTR_CPU_FREG, "freg", "freg") 157 CMD_CPU_SIMPLEHANDLER(mau, mau, CMD_PTR_CPU_MAU, "mau", "mau") 158 CMD_CPU_SIMPLEHANDLER(miscregs_ce, misc_regs, CMD_PTR_CPU_MISC_REGS, 159 "misc_regs", "misc_reg") 160 CMD_CPU_SIMPLEHANDLER(l2c, l2data, CMD_PTR_CPU_L2DATA, "l2data", "l2data-c") 161 162 CMD_CPU_SIMPLEHANDLER(fpu, fpu, CMD_PTR_CPU_FPU, "", "fpu") 163 CMD_CPU_SIMPLEHANDLER(l2ctl, l2ctl, CMD_PTR_CPU_L2CTL, "", "l2cachectl") 164 CMD_CPU_SIMPLEHANDLER(iru, ireg, CMD_PTR_CPU_IREG, "", "ireg") 165 CMD_CPU_SIMPLEHANDLER(fru, freg, CMD_PTR_CPU_FREG, "", "freg") 166 CMD_CPU_SIMPLEHANDLER(miscregs_ue, misc_regs, CMD_PTR_CPU_MISC_REGS, 167 "", "misc_reg") 168 CMD_CPU_SIMPLEHANDLER(l2u, l2data, CMD_PTR_CPU_L2DATA, "", "l2data-u") 169 CMD_CPU_SIMPLEHANDLER(lfu_ue, lfu, CMD_PTR_CPU_LFU, "", "lfu-u") 170 CMD_CPU_SIMPLEHANDLER(lfu_ce, lfu, CMD_PTR_CPU_LFU, "", "lfu-f") 171 CMD_CPU_SIMPLEHANDLER(lfu_pe, lfu, CMD_PTR_CPU_LFU, "", "lfu-p") 172 173 174 #ifdef sun4u 175 /* 176 * The following macro handles UEs or CPU errors. 177 * It handles the error cases in which there is with or 178 * without "resource". 179 * 180 * If the "fltname" "core" is to be generated, the sibling CPUs 181 * within the core will be added to the suspect list. 182 * If the "fltname" "chip" is to be generated, the sibling CPUs 183 * within the chip will be added to the suspect list. 184 * If the "fltname" "strand" is to be generated, the strand 185 * itself will be in the suspect list. 186 */ 187 #define CMD_OPL_UEHANDLER(name, casenm, ptr, fltname, has_rsrc) \ 188 cmd_evdisp_t \ 189 cmd_##name(fmd_hdl_t *hdl, fmd_event_t *ep, nvlist_t *nvl, \ 190 const char *class, cmd_errcl_t clcode) \ 191 { \ 192 cmd_cpu_t *cpu; \ 193 cmd_case_t *cc; \ 194 cmd_evdisp_t rc; \ 195 nvlist_t *rsrc = NULL; \ 196 uint8_t cpumask, version = 1; \ 197 uint8_t lookup_rsrc = has_rsrc; \ 198 \ 199 fmd_hdl_debug(hdl, \ 200 "Enter cmd_opl_ue_cpu for class %x\n", clcode); \ 201 \ 202 if (lookup_rsrc) { \ 203 if (nvlist_lookup_nvlist(nvl, \ 204 FM_EREPORT_PAYLOAD_NAME_RESOURCE, &rsrc) != 0) \ 205 return (CMD_EVD_BAD); \ 206 \ 207 if ((cpu = cmd_cpu_lookup(hdl, rsrc, class, \ 208 CMD_CPU_LEVEL_THREAD)) == NULL || \ 209 cpu->cpu_faulting) \ 210 return (CMD_EVD_UNUSED); \ 211 } else { \ 212 if ((cpu = cmd_cpu_lookup_from_detector(hdl, nvl, class,\ 213 CMD_CPU_LEVEL_THREAD)) == NULL || cpu->cpu_faulting)\ 214 return (CMD_EVD_UNUSED); \ 215 \ 216 (void) nvlist_lookup_nvlist(nvl, \ 217 FM_EREPORT_DETECTOR, &rsrc); \ 218 } \ 219 \ 220 if (nvlist_lookup_uint8(rsrc, FM_VERSION, &version) != 0 || \ 221 version > FM_CPU_SCHEME_VERSION || \ 222 nvlist_lookup_uint8(rsrc, FM_FMRI_CPU_MASK, &cpumask) != 0) \ 223 return (CMD_EVD_BAD); \ 224 \ 225 cc = &cpu->cpu_##casenm; \ 226 rc = cmd_opl_ue_cpu(hdl, ep, class, fltname, \ 227 ptr, cpu, cc, cpumask); \ 228 return (rc); \ 229 } 230 231 /* 232 * CPU errors without resource 233 */ 234 CMD_OPL_UEHANDLER(oplinv_urg, opl_inv_urg, CMD_PTR_CPU_UGESR_INV_URG, "core", 0) 235 CMD_OPL_UEHANDLER(oplcre, opl_cre, CMD_PTR_CPU_UGESR_CRE, "core", 0) 236 CMD_OPL_UEHANDLER(opltsb_ctx, opl_tsb_ctx, CMD_PTR_CPU_UGESR_TSB_CTX, "core", 0) 237 CMD_OPL_UEHANDLER(opltsbp, opl_tsbp, CMD_PTR_CPU_UGESR_TSBP, "core", 0) 238 CMD_OPL_UEHANDLER(oplpstate, opl_pstate, CMD_PTR_CPU_UGESR_PSTATE, "core", 0) 239 CMD_OPL_UEHANDLER(opltstate, opl_tstate, CMD_PTR_CPU_UGESR_TSTATE, "core", 0) 240 CMD_OPL_UEHANDLER(opliug_f, opl_iug_f, CMD_PTR_CPU_UGESR_IUG_F, "core", 0) 241 CMD_OPL_UEHANDLER(opliug_r, opl_iug_r, CMD_PTR_CPU_UGESR_IUG_R, "core", 0) 242 CMD_OPL_UEHANDLER(oplsdc, opl_sdc, CMD_PTR_CPU_UGESR_SDC, "chip", 0) 243 CMD_OPL_UEHANDLER(oplwdt, opl_wdt, CMD_PTR_CPU_UGESR_WDT, "core", 0) 244 CMD_OPL_UEHANDLER(opldtlb, opl_dtlb, CMD_PTR_CPU_UGESR_DTLB, "core", 0) 245 CMD_OPL_UEHANDLER(oplitlb, opl_itlb, CMD_PTR_CPU_UGESR_ITLB, "core", 0) 246 CMD_OPL_UEHANDLER(oplcore_err, opl_core_err, CMD_PTR_CPU_UGESR_CORE_ERR, 247 "core", 0) 248 CMD_OPL_UEHANDLER(opldae, opl_dae, CMD_PTR_CPU_UGESR_DAE, "core", 0) 249 CMD_OPL_UEHANDLER(opliae, opl_iae, CMD_PTR_CPU_UGESR_IAE, "core", 0) 250 CMD_OPL_UEHANDLER(opluge, opl_uge, CMD_PTR_CPU_UGESR_UGE, "core", 0) 251 252 /* 253 * UEs with resource 254 */ 255 CMD_OPL_UEHANDLER(oplinv_sfsr, opl_invsfsr, CMD_PTR_CPU_INV_SFSR, "strand", 1) 256 CMD_OPL_UEHANDLER(opluecpu_detcpu, oplue_detcpu, CMD_PTR_CPU_UE_DET_CPU, 257 "core", 1) 258 CMD_OPL_UEHANDLER(opluecpu_detio, oplue_detio, CMD_PTR_CPU_UE_DET_IO, "core", 1) 259 CMD_OPL_UEHANDLER(oplmtlb, opl_mtlb, CMD_PTR_CPU_MTLB, "core", 1) 260 CMD_OPL_UEHANDLER(opltlbp, opl_tlbp, CMD_PTR_CPU_TLBP, "core", 1) 261 #endif /* sun4u */ 262 263 /*ARGSUSED*/ 264 static void 265 cmd_nop_hdlr(fmd_hdl_t *hdl, cmd_xr_t *xr, fmd_event_t *ep) 266 { 267 fmd_hdl_debug(hdl, "nop train resolved for clcode %llx\n", 268 xr->xr_clcode); 269 } 270 /*ARGSUSED*/ 271 static void 272 cmd_xxu_hdlr(fmd_hdl_t *hdl, cmd_xr_t *xr, fmd_event_t *ep) 273 { 274 const errdata_t *ed; 275 cmd_cpu_t *cpu = xr->xr_cpu; 276 cmd_case_t *cc; 277 const char *uuid; 278 nvlist_t *rsrc = NULL; 279 280 cmd_fill_errdata(xr->xr_clcode, cpu, &cc, &ed); 281 282 if (cpu->cpu_faulting) { 283 CMD_STAT_BUMP(xxu_retr_flt); 284 return; 285 } 286 287 if (cmd_afar_status_check(xr->xr_afar_status, xr->xr_clcode) < 0) { 288 fmd_hdl_debug(hdl, "xxU dropped, afar not VALID\n"); 289 return; 290 } 291 292 if (cmd_cpu_synd_check(xr->xr_synd, xr->xr_clcode) < 0) { 293 fmd_hdl_debug(hdl, "xxU/LDxU dropped due to syndrome\n"); 294 return; 295 } 296 297 #ifdef sun4u 298 /* 299 * UE cache needed for sun4u only, because sun4u doesn't poison 300 * uncorrectable data loaded into L2/L3 cache. 301 */ 302 if (cmd_cpu_uec_match(xr->xr_cpu, xr->xr_afar)) { 303 fmd_hdl_debug(hdl, "ue matched in UE cache\n"); 304 CMD_STAT_BUMP(xxu_ue_match); 305 return; 306 } 307 #endif /* sun4u */ 308 309 /* 310 * We didn't match in the UE cache. We don't need to sleep for UE 311 * arrival, as we've already slept once for the train match. 312 */ 313 314 if (cc->cc_cp == NULL) { 315 cc->cc_cp = cmd_case_create(hdl, &cpu->cpu_header, ed->ed_pst, 316 &uuid); 317 } else if (cc->cc_serdnm != NULL) { 318 fmd_hdl_debug(hdl, "destroying existing %s state\n", 319 cc->cc_serdnm); 320 321 fmd_serd_destroy(hdl, cc->cc_serdnm); 322 fmd_hdl_strfree(hdl, cc->cc_serdnm); 323 cc->cc_serdnm = NULL; 324 325 fmd_case_reset(hdl, cc->cc_cp); 326 } 327 328 if (xr->xr_rsrc_nvl != NULL && nvlist_dup(xr->xr_rsrc_nvl, 329 &rsrc, 0) != 0) { 330 fmd_hdl_abort(hdl, "failed to duplicate resource FMRI for " 331 "%s fault", ed->ed_fltnm); 332 } 333 334 fmd_case_add_ereport(hdl, cc->cc_cp, ep); 335 336 cmd_cpu_create_faultlist(hdl, cc->cc_cp, cpu, ed->ed_fltnm, rsrc, 100); 337 nvlist_free(rsrc); 338 fmd_case_solve(hdl, cc->cc_cp); 339 } 340 341 static void 342 cmd_xxc_hdlr(fmd_hdl_t *hdl, cmd_xr_t *xr, fmd_event_t *ep) 343 { 344 const errdata_t *ed; 345 cmd_cpu_t *cpu = xr->xr_cpu; 346 cmd_case_t *cc; 347 const char *uuid; 348 nvlist_t *rsrc = NULL; 349 350 #ifdef sun4u 351 if (cmd_cache_ce_panther(hdl, ep, xr) == 0) { 352 return; 353 } 354 #endif 355 cmd_fill_errdata(xr->xr_clcode, cpu, &cc, &ed); 356 357 if (cpu->cpu_faulting || (cc->cc_cp != NULL && 358 fmd_case_solved(hdl, cc->cc_cp))) 359 return; 360 361 if (cc->cc_cp == NULL) { 362 cc->cc_cp = cmd_case_create(hdl, &cpu->cpu_header, ed->ed_pst, 363 &uuid); 364 cc->cc_serdnm = cmd_cpu_serdnm_create(hdl, cpu, 365 ed->ed_serd->cs_name); 366 367 fmd_serd_create(hdl, cc->cc_serdnm, ed->ed_serd->cs_n, 368 ed->ed_serd->cs_t); 369 } 370 371 fmd_hdl_debug(hdl, "adding event to %s\n", cc->cc_serdnm); 372 373 if (fmd_serd_record(hdl, cc->cc_serdnm, ep) == FMD_B_FALSE) 374 return; /* serd engine hasn't fired yet */ 375 376 if (xr->xr_rsrc_nvl != NULL && nvlist_dup(xr->xr_rsrc_nvl, 377 &rsrc, 0) != 0) { 378 fmd_hdl_abort(hdl, "failed to duplicate resource FMRI for " 379 "%s fault", ed->ed_fltnm); 380 } 381 382 fmd_case_add_serd(hdl, cc->cc_cp, cc->cc_serdnm); 383 cmd_cpu_create_faultlist(hdl, cc->cc_cp, cpu, ed->ed_fltnm, rsrc, 100); 384 nvlist_free(rsrc); 385 fmd_case_solve(hdl, cc->cc_cp); 386 } 387 388 /* 389 * We're back from the timeout. Check to see if this event was part of a train. 390 * If it was, make sure to only process the cause of the train. If not, 391 * process the event directly. 392 */ 393 static void 394 cmd_xxcu_resolve(fmd_hdl_t *hdl, cmd_xr_t *xr, fmd_event_t *ep, 395 cmd_xr_hdlr_f *hdlr) 396 { 397 cmd_xxcu_trw_t *trw; 398 cmd_errcl_t cause; 399 uint64_t afar; 400 401 402 afar = NULL; 403 404 if (xr->xr_afar_status == AFLT_STAT_VALID) 405 afar = xr->xr_afar; 406 407 if ((trw = cmd_trw_lookup(xr->xr_ena, 408 xr->xr_afar_status, afar)) == NULL) { 409 fmd_hdl_debug(hdl, "cmd_trw_lookup: Not found\n"); 410 return; 411 } 412 413 fmd_hdl_debug(hdl, "found waiter with mask 0x%08llx\n", trw->trw_mask); 414 415 trw->trw_flags |= CMD_TRW_F_DELETING; 416 417 /* 418 * In sun4v, the matching train rule is changed. It matches only 419 * a portion of the train mask, so can't discard the rest of 420 * the error in the train mask. 421 */ 422 #ifdef sun4u 423 if (trw->trw_flags & CMD_TRW_F_CAUSESEEN) { 424 fmd_hdl_debug(hdl, "cause already seen -- discarding\n"); 425 goto done; 426 } 427 #endif 428 429 if ((cause = cmd_train_match(trw->trw_mask, xr->xr_clcode)) == 0) { 430 /* 431 * We didn't match in a train, so we're going to process each 432 * event individually. 433 */ 434 fmd_hdl_debug(hdl, "didn't match in a train\n"); 435 hdlr(hdl, xr, ep); 436 goto done; 437 } 438 439 fmd_hdl_debug(hdl, "found a match for train. cause is %llx, " 440 "this is %llx\n", cause, xr->xr_clcode); 441 442 /* 443 * We've got a train match. If this event is the cause of the train, 444 * process it. 445 */ 446 if (cause == xr->xr_clcode) { 447 trw->trw_flags |= CMD_TRW_F_CAUSESEEN; 448 hdlr(hdl, xr, ep); 449 } 450 451 done: 452 cmd_trw_deref(hdl, trw); 453 } 454 455 void 456 cmd_xxc_resolve(fmd_hdl_t *hdl, cmd_xr_t *xr, fmd_event_t *ep) 457 { 458 cmd_xxcu_resolve(hdl, xr, ep, cmd_xxc_hdlr); 459 } 460 461 void 462 cmd_xxu_resolve(fmd_hdl_t *hdl, cmd_xr_t *xr, fmd_event_t *ep) 463 { 464 cmd_xxcu_resolve(hdl, xr, ep, cmd_xxu_hdlr); 465 } 466 467 void 468 cmd_nop_resolve(fmd_hdl_t *hdl, cmd_xr_t *xr, fmd_event_t *ep) 469 { 470 cmd_xxcu_resolve(hdl, xr, ep, cmd_nop_hdlr); 471 } 472 473 cmd_evdisp_t 474 cmd_xxcu_initial(fmd_hdl_t *hdl, fmd_event_t *ep, nvlist_t *nvl, 475 const char *class, cmd_errcl_t clcode, uint_t hdlrid) 476 { 477 cmd_xxcu_trw_t *trw; 478 cmd_case_t *cc; 479 cmd_cpu_t *cpu; 480 cmd_xr_t *xr; 481 uint64_t ena; 482 uint64_t afar; 483 uint8_t level = clcode & CMD_ERRCL_LEVEL_EXTRACT; 484 uint8_t afar_status; 485 const errdata_t *ed = NULL; 486 int ref_incremented = 0; 487 488 clcode &= CMD_ERRCL_LEVEL_MASK; /* keep level bits out of train masks */ 489 490 if ((cpu = cmd_cpu_lookup_from_detector(hdl, nvl, class, 491 level)) == NULL || cpu->cpu_faulting) 492 return (CMD_EVD_UNUSED); 493 494 cmd_fill_errdata(clcode, cpu, &cc, &ed); 495 496 if (cc->cc_cp != NULL && fmd_case_solved(hdl, cc->cc_cp)) 497 return (CMD_EVD_REDUND); 498 499 (void) nvlist_lookup_uint64(nvl, FM_EREPORT_ENA, &ena); 500 501 if (cmd_afar_valid(hdl, nvl, clcode, &afar) != 0) { 502 afar_status = AFLT_STAT_INVALID; 503 afar = NULL; 504 } else { 505 afar_status = AFLT_STAT_VALID; 506 } 507 508 fmd_hdl_debug(hdl, "scheduling %s (%llx) for redelivery\n", 509 class, clcode); 510 fmd_hdl_debug(hdl, "looking up ena %llx,afar %llx with\n", ena, afar); 511 512 fmd_hdl_debug(hdl, "afar status of %02x\n", afar_status); 513 514 if ((trw = cmd_trw_lookup(ena, afar_status, afar)) == NULL) { 515 if ((trw = cmd_trw_alloc(ena, afar)) == NULL) { 516 fmd_hdl_debug(hdl, "failed to get new trw\n"); 517 goto redeliver; 518 } 519 } 520 521 if (trw->trw_flags & CMD_TRW_F_DELETING) 522 goto redeliver; 523 524 if (trw->trw_mask & clcode) { 525 fmd_hdl_debug(hdl, "clcode %llx is already in trw " 526 "(mask %llx)\n", clcode, trw->trw_mask); 527 return (CMD_EVD_UNUSED); 528 } 529 530 cmd_trw_ref(hdl, trw, clcode); 531 ref_incremented++; 532 533 fmd_hdl_debug(hdl, "trw rescheduled for train delivery\n"); 534 535 redeliver: 536 if ((xr = cmd_xr_create(hdl, ep, nvl, cpu, clcode)) == NULL) { 537 fmd_hdl_debug(hdl, "cmd_xr_create failed"); 538 if (ref_incremented) 539 cmd_trw_deref(hdl, trw); 540 return (CMD_EVD_BAD); 541 } 542 543 return (cmd_xr_reschedule(hdl, xr, hdlrid)); 544 } 545 546 547 cmd_evdisp_t 548 cmd_xxu(fmd_hdl_t *hdl, fmd_event_t *ep, nvlist_t *nvl, const char *class, 549 cmd_errcl_t clcode) 550 { 551 return (cmd_xxcu_initial(hdl, ep, nvl, class, clcode, CMD_XR_HDLR_XXU)); 552 } 553 554 cmd_evdisp_t 555 cmd_xxc(fmd_hdl_t *hdl, fmd_event_t *ep, nvlist_t *nvl, const char *class, 556 cmd_errcl_t clcode) 557 { 558 return (cmd_xxcu_initial(hdl, ep, nvl, class, clcode, CMD_XR_HDLR_XXC)); 559 } 560 561 cmd_evdisp_t 562 cmd_nop_train(fmd_hdl_t *hdl, fmd_event_t *ep, nvlist_t *nvl, 563 const char *class, cmd_errcl_t clcode) 564 { 565 return (cmd_xxcu_initial(hdl, ep, nvl, class, clcode, CMD_XR_HDLR_NOP)); 566 } 567 568 cmd_evdisp_t 569 cmd_miscregs_train(fmd_hdl_t *hdl, fmd_event_t *ep, nvlist_t *nvl, 570 const char *class, cmd_errcl_t clcode) 571 { 572 return (cmd_xxcu_initial(hdl, ep, nvl, class, clcode, 573 CMD_XR_HDLR_XXC)); 574 } 575 576 void 577 cmd_cpuerr_close(fmd_hdl_t *hdl, void *arg) 578 { 579 cmd_cpu_destroy(hdl, arg); 580 } 581