1 extern "C" 2 { 3 #include <libpdbg.h> 4 #include <libpdbg_sbe.h> 5 } 6 7 #include <config.h> 8 9 #ifdef CONFIG_PHAL_API 10 #include <libphal.H> 11 #endif 12 13 #include <analyzer/analyzer_main.hpp> 14 #include <attn/attention.hpp> 15 #include <attn/attn_common.hpp> 16 #include <attn/attn_config.hpp> 17 #include <attn/attn_dbus.hpp> 18 #include <attn/attn_handler.hpp> 19 #include <attn/attn_logging.hpp> 20 #include <attn/bp_handler.hpp> 21 #include <attn/ti_handler.hpp> 22 #include <attn/vital_handler.hpp> 23 #include <util/dbus.hpp> 24 25 #include <algorithm> 26 #include <iomanip> 27 #include <map> 28 #include <sstream> 29 #include <vector> 30 31 namespace attn 32 { 33 34 /** 35 * @brief Handle checkstop attention 36 * 37 * @param i_attention Attention object 38 * @return 0 indicates that the checkstop attention was successfully handled 39 * 1 indicates that the checkstop attention was NOT successfully 40 * handled. 41 */ 42 int handleCheckstop(Attention* i_attention); 43 44 /** 45 * @brief Handle special attention 46 * 47 * @param i_attention Attention object 48 * @return 0 indicates that the special attention was successfully handled 49 * 1 indicates that the special attention was NOT successfully handled 50 */ 51 int handleSpecial(Attention* i_attention); 52 53 /** @brief Determine if attention is active and not masked */ 54 bool activeAttn(uint32_t i_val, uint32_t i_mask, uint32_t i_attn); 55 56 #ifdef CONFIG_PHAL_API 57 /** @brief Handle phal sbe exception */ 58 void phalSbeExceptionHandler(openpower::phal::exception::SbeError& e, 59 uint32_t procNum); 60 #endif 61 62 /** @brief Get static TI info data based on host state */ 63 void getStaticTiInfo(uint8_t*& tiInfoPtr); 64 65 /** @brief Check if TI info data is valid */ 66 bool tiInfoValid(uint8_t* tiInfo); 67 68 /** 69 * @brief The main attention handler logic 70 * 71 * @param i_breakpoints true = breakpoint special attn handling enabled 72 */ 73 void attnHandler(Config* i_config) 74 { 75 // Vector of active attentions to be handled 76 std::vector<Attention> active_attentions; 77 78 uint32_t isr_val, isr_mask; 79 80 // loop through processors looking for active attentions 81 trace<level::INFO>("Attention handler started"); 82 83 pdbg_target* target; 84 pdbg_for_each_class_target("proc", target) 85 { 86 if (PDBG_TARGET_ENABLED == pdbg_target_probe(target)) 87 { 88 auto proc = pdbg_target_index(target); // get processor number 89 90 // Use PIB target to determine if a processor is enabled 91 char path[16]; 92 sprintf(path, "/proc%d/pib", proc); 93 pdbg_target* pibTarget = pdbg_target_from_path(nullptr, path); 94 95 // sanity check 96 if (nullptr == pibTarget) 97 { 98 trace<level::INFO>("pib path or target not found"); 99 continue; 100 } 101 102 // check if pib target is enabled 103 if (PDBG_TARGET_ENABLED == pdbg_target_probe(pibTarget)) 104 { 105 // The processor FSI target is required for CFAM read 106 sprintf(path, "/proc%d/fsi", proc); 107 pdbg_target* fsiTarget = pdbg_target_from_path(nullptr, path); 108 109 // sanity check 110 if (nullptr == fsiTarget) 111 { 112 trace<level::INFO>("fsi path or target not found"); 113 continue; 114 } 115 116 // trace the proc number 117 std::string traceMsg = "proc: " + std::to_string(proc); 118 trace<level::INFO>(traceMsg.c_str()); 119 120 isr_val = 0xffffffff; // invalid isr value 121 122 // get active attentions on processor 123 if (RC_SUCCESS != fsi_read(fsiTarget, 0x1007, &isr_val)) 124 { 125 // log cfam read error 126 trace<level::INFO>("Error! cfam read 0x1007 FAILED"); 127 eventAttentionFail((int)AttnSection::attnHandler | 128 ATTN_PDBG_CFAM); 129 } 130 else if (0xffffffff == isr_val) 131 { 132 trace<level::INFO>("Error! cfam read 0x1007 INVALID"); 133 continue; 134 } 135 else 136 { 137 // trace isr value 138 std::stringstream ssIsr; 139 ssIsr << "cfam 0x1007 = 0x" << std::setw(8) 140 << std::setfill('0') << std::hex << isr_val; 141 std::string strobjIsr = ssIsr.str(); 142 trace<level::INFO>(strobjIsr.c_str()); 143 144 isr_mask = 0xffffffff; // invalid isr mask 145 146 // get interrupt enabled special attentions mask 147 if (RC_SUCCESS != fsi_read(fsiTarget, 0x100d, &isr_mask)) 148 { 149 // log cfam read error 150 trace<level::INFO>("Error! cfam read 0x100d FAILED"); 151 eventAttentionFail((int)AttnSection::attnHandler | 152 ATTN_PDBG_CFAM); 153 } 154 else if (0xffffffff == isr_mask) 155 { 156 trace<level::INFO>("Error! cfam read 0x100d INVALID"); 157 continue; 158 } 159 else 160 { 161 // trace true mask 162 std::stringstream ssMask; 163 ssMask << "cfam 0x100d = 0x" << std::setw(8) 164 << std::setfill('0') << std::hex << isr_mask; 165 std::string strobjMask = ssMask.str(); 166 trace<level::INFO>(strobjMask.c_str()); 167 168 // SBE vital attention active and not masked? 169 if (true == activeAttn(isr_val, isr_mask, SBE_ATTN)) 170 { 171 active_attentions.emplace_back(Attention::Vital, 172 handleVital, target, 173 i_config); 174 } 175 176 // Checkstop attention active and not masked? 177 if (true == 178 activeAttn(isr_val, isr_mask, CHECKSTOP_ATTN)) 179 { 180 active_attentions.emplace_back(Attention::Checkstop, 181 handleCheckstop, 182 target, i_config); 183 } 184 185 // Special attention active and not masked? 186 if (true == activeAttn(isr_val, isr_mask, SPECIAL_ATTN)) 187 { 188 active_attentions.emplace_back(Attention::Special, 189 handleSpecial, 190 target, i_config); 191 } 192 } // cfam 0x100d valid 193 } // cfam 0x1007 valid 194 } // fsi target enabled 195 } // pib target enabled 196 } // next processor 197 198 // convert to heap, highest priority is at front 199 if (!std::is_heap(active_attentions.begin(), active_attentions.end())) 200 { 201 std::make_heap(active_attentions.begin(), active_attentions.end()); 202 } 203 204 // call the attention handler until one is handled or all were attempted 205 while (false == active_attentions.empty()) 206 { 207 // handle highest priority attention, done if successful 208 if (RC_SUCCESS == active_attentions.front().handle()) 209 { 210 // an attention was handled so we are done 211 break; 212 } 213 214 // move attention to back of vector 215 std::pop_heap(active_attentions.begin(), active_attentions.end()); 216 217 // remove attention from vector 218 active_attentions.pop_back(); 219 } 220 } 221 222 /** 223 * @brief Handle checkstop attention 224 * 225 * @param i_attention Attention object 226 * @return 0 indicates that the checkstop attention was successfully handled 227 * 1 indicates that the checkstop attention was NOT successfully 228 * handled. 229 */ 230 int handleCheckstop(Attention* i_attention) 231 { 232 int rc = RC_SUCCESS; // assume checkstop handled 233 234 trace<level::INFO>("checkstop handler started"); 235 236 // capture some additional data for logs/traces 237 addHbStatusRegs(); 238 239 // if checkstop handling enabled, handle checkstop attention 240 if (false == (i_attention->getConfig()->getFlag(enCheckstop))) 241 { 242 trace<level::INFO>("Checkstop handling disabled"); 243 } 244 else 245 { 246 // wait for power fault handling before starting analyses 247 sleepSeconds(POWER_FAULT_WAIT); 248 249 // Look for any attentions found in hardware. This will generate and 250 // commit a PEL if any errors are found. 251 DumpParameters dumpParameters; 252 auto logid = analyzer::analyzeHardware(dumpParameters); 253 if (0 == logid) 254 { 255 // A PEL should exist for a checkstop attention. 256 rc = RC_ANALYZER_ERROR; 257 } 258 else 259 { 260 requestDump(logid, dumpParameters); 261 util::dbus::transitionHost(util::dbus::HostState::Quiesce); 262 } 263 } 264 265 return rc; 266 } 267 268 /** 269 * @brief Handle special attention 270 * 271 * @param i_attention Attention object 272 * @return 0 indicates that the special attention was successfully handled 273 * 1 indicates that the special attention was NOT successfully handled 274 */ 275 int handleSpecial(Attention* i_attention) 276 { 277 int rc = RC_SUCCESS; // assume special attention handled 278 279 // The TI info chipop will give us a pointer to the TI info data 280 uint8_t* tiInfo = nullptr; // ptr to TI info data 281 uint32_t tiInfoLen = 0; // length of TI info data 282 pdbg_target* attnProc = i_attention->getTarget(); // proc with attention 283 284 bool tiInfoStatic = false; // assume TI info was provided (not created) 285 286 // need proc target to get dynamic TI info 287 if (nullptr != attnProc) 288 { 289 #ifdef CONFIG_PHAL_API 290 trace<level::INFO>("using libphal to get TI info"); 291 292 // phal library uses proc target for get ti info 293 if (PDBG_TARGET_ENABLED == pdbg_target_probe(attnProc)) 294 { 295 try 296 { 297 // get dynamic TI info 298 openpower::phal::sbe::getTiInfo(attnProc, &tiInfo, &tiInfoLen); 299 } 300 catch (openpower::phal::exception::SbeError& e) 301 { 302 // library threw an exception 303 uint32_t procNum = pdbg_target_index(attnProc); 304 phalSbeExceptionHandler(e, procNum); 305 } 306 } 307 #else 308 trace<level::INFO>("using libpdbg to get TI info"); 309 310 // pdbg library uses pib target for get ti info 311 char path[16]; 312 sprintf(path, "/proc%d/pib", pdbg_target_index(attnProc)); 313 pdbg_target* tiInfoTarget = pdbg_target_from_path(nullptr, path); 314 315 if (nullptr != tiInfoTarget) 316 { 317 if (PDBG_TARGET_ENABLED == pdbg_target_probe(tiInfoTarget)) 318 { 319 sbe_mpipl_get_ti_info(tiInfoTarget, &tiInfo, &tiInfoLen); 320 } 321 } 322 #endif 323 } 324 325 // dynamic TI info is not available 326 if (nullptr == tiInfo) 327 { 328 trace<level::INFO>("TI info data ptr is invalid"); 329 getStaticTiInfo(tiInfo); 330 tiInfoStatic = true; 331 } 332 333 // check TI info for validity and handle 334 if (true == tiInfoValid(tiInfo)) 335 { 336 // TI info is valid handle TI if support enabled 337 if (true == (i_attention->getConfig()->getFlag(enTerminate))) 338 { 339 // Call TI special attention handler 340 rc = tiHandler((TiDataArea*)tiInfo); 341 } 342 } 343 else 344 { 345 trace<level::INFO>("TI info NOT valid"); 346 347 // if configured to handle TI as default special attention 348 if (i_attention->getConfig()->getFlag(dfltTi)) 349 { 350 // TI handling may be disabled 351 if (true == (i_attention->getConfig()->getFlag(enTerminate))) 352 { 353 // Call TI special attention handler 354 rc = tiHandler((TiDataArea*)tiInfo); 355 } 356 } 357 // configured to handle breakpoint as default special attention 358 else 359 { 360 // breakpoint handling may be disabled 361 if (true == (i_attention->getConfig()->getFlag(enBreakpoints))) 362 { 363 // Call the breakpoint special attention handler 364 rc = bpHandler(); 365 } 366 } 367 } 368 369 // release TI data buffer if not ours 370 if (false == tiInfoStatic) 371 { 372 // sanity check 373 if (nullptr != tiInfo) 374 { 375 free(tiInfo); 376 } 377 } 378 379 // trace non-successful exit condition 380 if (RC_SUCCESS != rc) 381 { 382 trace<level::INFO>("Special attn not handled"); 383 } 384 385 return rc; 386 } 387 388 /** 389 * @brief Determine if attention is active and not masked 390 * 391 * Determine whether an attention needs to be handled and trace details of 392 * attention type and whether it is masked or not. 393 * 394 * @param i_val attention status register 395 * @param i_mask attention true mask register 396 * @param i_attn attention type 397 * @param i_proc processor associated with registers 398 * 399 * @return true if attention is active and not masked, otherwise false 400 */ 401 bool activeAttn(uint32_t i_val, uint32_t i_mask, uint32_t i_attn) 402 { 403 bool rc = false; // assume attn masked and/or inactive 404 405 // if attention active 406 if (0 != (i_val & i_attn)) 407 { 408 std::stringstream ss; 409 410 bool validAttn = true; // known attention type 411 412 switch (i_attn) 413 { 414 case SBE_ATTN: 415 ss << "SBE attn"; 416 break; 417 case CHECKSTOP_ATTN: 418 ss << "Checkstop attn"; 419 break; 420 case SPECIAL_ATTN: 421 ss << "Special attn"; 422 break; 423 default: 424 ss << "Unknown attn"; 425 validAttn = false; 426 } 427 428 // see if attention is masked 429 if (true == validAttn) 430 { 431 if (0 != (i_mask & i_attn)) 432 { 433 rc = true; // attention active and not masked 434 } 435 else 436 { 437 ss << " masked"; 438 } 439 } 440 441 std::string strobj = ss.str(); // ss.str() is temporary 442 trace<level::INFO>(strobj.c_str()); // commit trace stream 443 } 444 445 return rc; 446 } 447 448 #ifdef CONFIG_PHAL_API 449 /** 450 * @brief Handle phal sbe exception 451 * 452 * @param[in] e - exception object 453 * @param[in] procNum - processor number associated with sbe exception 454 */ 455 void phalSbeExceptionHandler(openpower::phal::exception::SbeError& e, 456 uint32_t procNum) 457 { 458 // trace exception details 459 std::string traceMsg = std::string(e.what()); 460 trace<level::ERROR>(traceMsg.c_str()); 461 462 // Handle SBE chipop timeout error 463 if (e.errType() == openpower::phal::exception::SBE_CHIPOP_NOT_ALLOWED) 464 { 465 eventPhalSbeChipop(procNum); 466 } 467 } 468 #endif 469 470 /** 471 * @brief Get static TI info data based on host state 472 * 473 * @param[out] tiInfo - pointer to static TI info data 474 */ 475 void getStaticTiInfo(uint8_t*& tiInfo) 476 { 477 util::dbus::HostRunningState runningState = util::dbus::hostRunningState(); 478 479 // assume host state is unknown 480 std::string stateString = "host state unknown"; 481 482 if ((util::dbus::HostRunningState::Started == runningState) || 483 (util::dbus::HostRunningState::Unknown == runningState)) 484 { 485 if (util::dbus::HostRunningState::Started == runningState) 486 { 487 stateString = "host started"; 488 } 489 tiInfo = (uint8_t*)defaultPhypTiInfo; 490 } 491 else 492 { 493 stateString = "host not started"; 494 tiInfo = (uint8_t*)defaultHbTiInfo; 495 } 496 497 // trace host state 498 trace<level::INFO>(stateString.c_str()); 499 } 500 501 /** 502 * @brief Check if TI info data is valid 503 * 504 * @param[in] tiInfo - pointer to TI info data 505 * @return true if TI info data is valid, else false 506 */ 507 bool tiInfoValid(uint8_t* tiInfo) 508 { 509 bool tiInfoValid = false; // assume TI info invalid 510 511 // TI info data[0] non-zero indicates TI info valid (usually) 512 if ((nullptr != tiInfo) && (0 != tiInfo[0])) 513 { 514 TiDataArea* tiDataArea = (TiDataArea*)tiInfo; 515 516 std::stringstream ss; // string stream object for tracing 517 std::string strobj; // string object for tracing 518 519 // trace a few known TI data area values 520 ss.str(std::string()); // empty the stream 521 ss.clear(); // clear the stream 522 ss << "TI data command = 0x" << std::setw(2) << std::setfill('0') 523 << std::hex << (int)tiDataArea->command; 524 strobj = ss.str(); 525 trace<level::INFO>(strobj.c_str()); 526 527 // Another check for valid TI Info since it has been seen that 528 // tiInfo[0] != 0 but TI info is not valid 529 if (0xa1 == tiDataArea->command) 530 { 531 tiInfoValid = true; 532 533 // trace some more data since TI info appears valid 534 ss.str(std::string()); // empty the stream 535 ss.clear(); // clear the stream 536 ss << "TI data term-type = 0x" << std::setw(2) << std::setfill('0') 537 << std::hex << (int)tiDataArea->hbTerminateType; 538 strobj = ss.str(); 539 trace<level::INFO>(strobj.c_str()); 540 541 ss.str(std::string()); // empty the stream 542 ss.clear(); // clear the stream 543 ss << "TI data SRC format = 0x" << std::setw(2) << std::setfill('0') 544 << std::hex << (int)tiDataArea->srcFormat; 545 strobj = ss.str(); 546 trace<level::INFO>(strobj.c_str()); 547 548 ss.str(std::string()); // empty the stream 549 ss.clear(); // clear the stream 550 ss << "TI data source = 0x" << std::setw(2) << std::setfill('0') 551 << std::hex << (int)tiDataArea->source; 552 strobj = ss.str(); 553 trace<level::INFO>(strobj.c_str()); 554 } 555 } 556 557 return tiInfoValid; 558 } 559 560 } // namespace attn 561