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( 253 analyzer::AnalysisType::SYSTEM_CHECKSTOP, dumpParameters); 254 if (0 == logid) 255 { 256 // A PEL should exist for a checkstop attention. 257 rc = RC_ANALYZER_ERROR; 258 } 259 else 260 { 261 requestDump(logid, dumpParameters); 262 util::dbus::transitionHost(util::dbus::HostState::Quiesce); 263 } 264 } 265 266 return rc; 267 } 268 269 /** 270 * @brief Handle special attention 271 * 272 * @param i_attention Attention object 273 * @return 0 indicates that the special attention was successfully handled 274 * 1 indicates that the special attention was NOT successfully handled 275 */ 276 int handleSpecial(Attention* i_attention) 277 { 278 int rc = RC_SUCCESS; // assume special attention handled 279 280 // The TI info chipop will give us a pointer to the TI info data 281 uint8_t* tiInfo = nullptr; // ptr to TI info data 282 uint32_t tiInfoLen = 0; // length of TI info data 283 pdbg_target* attnProc = i_attention->getTarget(); // proc with attention 284 285 bool tiInfoStatic = false; // assume TI info was provided (not created) 286 287 // need proc target to get dynamic TI info 288 if (nullptr != attnProc) 289 { 290 #ifdef CONFIG_PHAL_API 291 trace<level::INFO>("using libphal to get TI info"); 292 293 // phal library uses proc target for get ti info 294 if (PDBG_TARGET_ENABLED == pdbg_target_probe(attnProc)) 295 { 296 try 297 { 298 // get dynamic TI info 299 openpower::phal::sbe::getTiInfo(attnProc, &tiInfo, &tiInfoLen); 300 } 301 catch (openpower::phal::exception::SbeError& e) 302 { 303 // library threw an exception 304 uint32_t procNum = pdbg_target_index(attnProc); 305 phalSbeExceptionHandler(e, procNum); 306 } 307 } 308 #else 309 trace<level::INFO>("using libpdbg to get TI info"); 310 311 // pdbg library uses pib target for get ti info 312 char path[16]; 313 sprintf(path, "/proc%d/pib", pdbg_target_index(attnProc)); 314 pdbg_target* tiInfoTarget = pdbg_target_from_path(nullptr, path); 315 316 if (nullptr != tiInfoTarget) 317 { 318 if (PDBG_TARGET_ENABLED == pdbg_target_probe(tiInfoTarget)) 319 { 320 sbe_mpipl_get_ti_info(tiInfoTarget, &tiInfo, &tiInfoLen); 321 } 322 } 323 #endif 324 } 325 326 // dynamic TI info is not available 327 if (nullptr == tiInfo) 328 { 329 trace<level::INFO>("TI info data ptr is invalid"); 330 getStaticTiInfo(tiInfo); 331 tiInfoStatic = true; 332 } 333 334 // check TI info for validity and handle 335 if (true == tiInfoValid(tiInfo)) 336 { 337 // TI info is valid handle TI if support enabled 338 if (true == (i_attention->getConfig()->getFlag(enTerminate))) 339 { 340 // Call TI special attention handler 341 rc = tiHandler((TiDataArea*)tiInfo); 342 } 343 } 344 else 345 { 346 trace<level::INFO>("TI info NOT valid"); 347 348 // if configured to handle TI as default special attention 349 if (i_attention->getConfig()->getFlag(dfltTi)) 350 { 351 // TI handling may be disabled 352 if (true == (i_attention->getConfig()->getFlag(enTerminate))) 353 { 354 // Call TI special attention handler 355 rc = tiHandler((TiDataArea*)tiInfo); 356 } 357 } 358 // configured to handle breakpoint as default special attention 359 else 360 { 361 // breakpoint handling may be disabled 362 if (true == (i_attention->getConfig()->getFlag(enBreakpoints))) 363 { 364 // Call the breakpoint special attention handler 365 rc = bpHandler(); 366 } 367 } 368 } 369 370 // release TI data buffer if not ours 371 if (false == tiInfoStatic) 372 { 373 // sanity check 374 if (nullptr != tiInfo) 375 { 376 free(tiInfo); 377 } 378 } 379 380 // trace non-successful exit condition 381 if (RC_SUCCESS != rc) 382 { 383 trace<level::INFO>("Special attn not handled"); 384 } 385 386 return rc; 387 } 388 389 /** 390 * @brief Determine if attention is active and not masked 391 * 392 * Determine whether an attention needs to be handled and trace details of 393 * attention type and whether it is masked or not. 394 * 395 * @param i_val attention status register 396 * @param i_mask attention true mask register 397 * @param i_attn attention type 398 * @param i_proc processor associated with registers 399 * 400 * @return true if attention is active and not masked, otherwise false 401 */ 402 bool activeAttn(uint32_t i_val, uint32_t i_mask, uint32_t i_attn) 403 { 404 bool rc = false; // assume attn masked and/or inactive 405 406 // if attention active 407 if (0 != (i_val & i_attn)) 408 { 409 std::stringstream ss; 410 411 bool validAttn = true; // known attention type 412 413 switch (i_attn) 414 { 415 case SBE_ATTN: 416 ss << "SBE attn"; 417 break; 418 case CHECKSTOP_ATTN: 419 ss << "Checkstop attn"; 420 break; 421 case SPECIAL_ATTN: 422 ss << "Special attn"; 423 break; 424 default: 425 ss << "Unknown attn"; 426 validAttn = false; 427 } 428 429 // see if attention is masked 430 if (true == validAttn) 431 { 432 if (0 != (i_mask & i_attn)) 433 { 434 rc = true; // attention active and not masked 435 } 436 else 437 { 438 ss << " masked"; 439 } 440 } 441 442 std::string strobj = ss.str(); // ss.str() is temporary 443 trace<level::INFO>(strobj.c_str()); // commit trace stream 444 } 445 446 return rc; 447 } 448 449 #ifdef CONFIG_PHAL_API 450 /** 451 * @brief Handle phal sbe exception 452 * 453 * @param[in] e - exception object 454 * @param[in] procNum - processor number associated with sbe exception 455 */ 456 void phalSbeExceptionHandler(openpower::phal::exception::SbeError& e, 457 uint32_t procNum) 458 { 459 // trace exception details 460 std::string traceMsg = std::string(e.what()); 461 trace<level::ERROR>(traceMsg.c_str()); 462 463 // Handle SBE chipop timeout error 464 if (e.errType() == openpower::phal::exception::SBE_CHIPOP_NOT_ALLOWED) 465 { 466 eventPhalSbeChipop(procNum); 467 } 468 } 469 #endif 470 471 /** 472 * @brief Get static TI info data based on host state 473 * 474 * @param[out] tiInfo - pointer to static TI info data 475 */ 476 void getStaticTiInfo(uint8_t*& tiInfo) 477 { 478 util::dbus::HostRunningState runningState = util::dbus::hostRunningState(); 479 480 // assume host state is unknown 481 std::string stateString = "host state unknown"; 482 483 if ((util::dbus::HostRunningState::Started == runningState) || 484 (util::dbus::HostRunningState::Unknown == runningState)) 485 { 486 if (util::dbus::HostRunningState::Started == runningState) 487 { 488 stateString = "host started"; 489 } 490 tiInfo = (uint8_t*)defaultPhypTiInfo; 491 } 492 else 493 { 494 stateString = "host not started"; 495 tiInfo = (uint8_t*)defaultHbTiInfo; 496 } 497 498 // trace host state 499 trace<level::INFO>(stateString.c_str()); 500 } 501 502 /** 503 * @brief Check if TI info data is valid 504 * 505 * @param[in] tiInfo - pointer to TI info data 506 * @return true if TI info data is valid, else false 507 */ 508 bool tiInfoValid(uint8_t* tiInfo) 509 { 510 bool tiInfoValid = false; // assume TI info invalid 511 512 // TI info data[0] non-zero indicates TI info valid (usually) 513 if ((nullptr != tiInfo) && (0 != tiInfo[0])) 514 { 515 TiDataArea* tiDataArea = (TiDataArea*)tiInfo; 516 517 std::stringstream ss; // string stream object for tracing 518 std::string strobj; // string object for tracing 519 520 // trace a few known TI data area values 521 ss.str(std::string()); // empty the stream 522 ss.clear(); // clear the stream 523 ss << "TI data command = 0x" << std::setw(2) << std::setfill('0') 524 << std::hex << (int)tiDataArea->command; 525 strobj = ss.str(); 526 trace<level::INFO>(strobj.c_str()); 527 528 // Another check for valid TI Info since it has been seen that 529 // tiInfo[0] != 0 but TI info is not valid 530 if (0xa1 == tiDataArea->command) 531 { 532 tiInfoValid = true; 533 534 // trace some more data since TI info appears valid 535 ss.str(std::string()); // empty the stream 536 ss.clear(); // clear the stream 537 ss << "TI data term-type = 0x" << std::setw(2) << std::setfill('0') 538 << std::hex << (int)tiDataArea->hbTerminateType; 539 strobj = ss.str(); 540 trace<level::INFO>(strobj.c_str()); 541 542 ss.str(std::string()); // empty the stream 543 ss.clear(); // clear the stream 544 ss << "TI data SRC format = 0x" << std::setw(2) << std::setfill('0') 545 << std::hex << (int)tiDataArea->srcFormat; 546 strobj = ss.str(); 547 trace<level::INFO>(strobj.c_str()); 548 549 ss.str(std::string()); // empty the stream 550 ss.clear(); // clear the stream 551 ss << "TI data source = 0x" << std::setw(2) << std::setfill('0') 552 << std::hex << (int)tiDataArea->source; 553 strobj = ss.str(); 554 trace<level::INFO>(strobj.c_str()); 555 } 556 } 557 558 return tiInfoValid; 559 } 560 561 } // namespace attn 562