| #include <attn/attention.hpp> |
| #include <attn/attn_common.hpp> |
| #include <attn/attn_dump.hpp> |
| #include <attn/attn_handler.hpp> |
| #include <attn/attn_logging.hpp> |
| #include <sdbusplus/bus.hpp> |
| #include <util/dbus.hpp> |
| #include <util/pdbg.hpp> |
| #include <util/pldm.hpp> |
| #include <util/trace.hpp> |
| |
| namespace attn |
| { |
| /* |
| * @brief Request SBE hreset and try to clear sbe attentions |
| * |
| * @param[in] sbeInstance - sbe instance to hreset (0 based) |
| * |
| * @return true if hreset is successful and attentions cleared |
| */ |
| bool attemptSbeRecovery(int sbeInstance) |
| { |
| // attempt sbe hreset and attention interrupt clear |
| if (!util::pldm::hresetSbe(sbeInstance)) |
| { |
| return false; |
| } |
| |
| trace::inf("hreset completed"); |
| |
| // try to clear attention interrupts |
| clearAttnInterrupts(); |
| |
| // loop through processors checking attention interrupts |
| bool recovered = true; |
| pdbg_target* procTarget; |
| pdbg_for_each_class_target("proc", procTarget) |
| { |
| // active processors only |
| if (PDBG_TARGET_ENABLED != |
| pdbg_target_probe(util::pdbg::getPibTrgt(procTarget))) |
| { |
| continue; |
| } |
| |
| // get cfam is an fsi read |
| pdbg_target* fsiTarget = util::pdbg::getFsiTrgt(procTarget); |
| uint32_t int_val; |
| |
| // get attention interrupts on processor |
| if (RC_SUCCESS == fsi_read(fsiTarget, 0x100b, &int_val)) |
| { |
| if (int_val & SBE_ATTN) |
| { |
| trace::err("sbe attention did not clear"); |
| recovered = false; |
| break; |
| } |
| } |
| else |
| { |
| // log cfam read error |
| trace::err("cfam read error"); |
| recovered = false; |
| break; |
| } |
| } |
| |
| if (recovered) |
| { |
| trace::inf("sbe attention cleared"); |
| } |
| |
| return recovered; |
| } |
| |
| /** |
| * @brief Check for active checkstop attention |
| * |
| * @param procInstance - proc to check for attentions |
| * |
| * @pre pdbg target associated with proc instance is enabled for fsi access |
| * |
| * @return true if checkstop acive false otherwise |
| * */ |
| bool checkstopActive(int procInstance) |
| { |
| // get fsi target |
| char path[16]; |
| sprintf(path, "/proc%d/fsi", procInstance); |
| pdbg_target* fsiTarget = pdbg_target_from_path(nullptr, path); |
| if (nullptr == fsiTarget) |
| { |
| trace::inf("fsi path or target not found"); |
| return false; |
| } |
| |
| // check for active checkstop attention |
| int r; |
| uint32_t isr_val, isr_mask; |
| |
| isr_val = 0xffffffff; |
| r = fsi_read(fsiTarget, 0x1007, &isr_val); |
| if ((RC_SUCCESS != r) || (0xffffffff == isr_val)) |
| { |
| trace::err("cfam 1007 read error"); |
| return false; |
| } |
| |
| isr_mask = 0xffffffff; |
| r = fsi_read(fsiTarget, 0x100d, &isr_mask); |
| if ((RC_SUCCESS != r) || (0xffffffff == isr_mask)) |
| { |
| trace::err("cfam 100d read error"); |
| return false; |
| } |
| |
| return activeAttn(isr_val, isr_mask, CHECKSTOP_ATTN); |
| } |
| |
| /** |
| * @brief Handle SBE vital attention |
| * |
| * @param i_attention - attention object |
| * |
| * @return non-zero if attention was not successfully handled |
| */ |
| int handleVital(Attention* i_attention) |
| { |
| trace::inf("vital handler started"); |
| |
| // if vital handling disabled |
| if (false == (i_attention->getConfig()->getFlag(enVital))) |
| { |
| trace::inf("vital handling disabled"); |
| return RC_NOT_HANDLED; |
| } |
| |
| // if power fault then we don't do anything |
| sleepSeconds(POWER_FAULT_WAIT); |
| if (util::dbus::powerFault()) |
| { |
| trace::inf("power fault was reported"); |
| return RC_SUCCESS; |
| } |
| |
| // if no checkstop and host is running |
| int instance = |
| pdbg_target_index(i_attention->getTarget()); // get processor number |
| |
| if (!checkstopActive(instance) && |
| util::dbus::HostRunningState::Started == util::dbus::hostRunningState()) |
| { |
| // attempt to recover the sbe |
| if (attemptSbeRecovery(instance)) |
| { |
| eventVital(levelPelInfo); |
| return RC_SUCCESS; |
| } |
| } |
| |
| // host not running, checkstop active or recovery failed |
| auto pelId = eventVital(levelPelError); |
| requestDump(pelId, DumpParameters{0, DumpType::SBE}); |
| util::dbus::transitionHost(util::dbus::HostState::Quiesce); |
| |
| return RC_SUCCESS; |
| } |
| |
| } // namespace attn |