1d84ed6e9SZane Shelley #include <assert.h> 287eabc65SBen Tyner #include <libpdbg.h> 39fb7393eSZane Shelley #include <unistd.h> 487eabc65SBen Tyner 54ed4be56SZane Shelley #include <analyzer/service_data.hpp> 60205f3b3SBen Tyner #include <hei_main.hpp> 79fb7393eSZane Shelley #include <phosphor-logging/log.hpp> 8f4bd5ff6SZane Shelley #include <util/pdbg.hpp> 9d84ed6e9SZane Shelley #include <util/trace.hpp> 100205f3b3SBen Tyner 11d84ed6e9SZane Shelley #include <algorithm> 1287eabc65SBen Tyner #include <fstream> 1387eabc65SBen Tyner #include <iostream> 14b1ebfcb1SBen Tyner #include <map> 15b1ebfcb1SBen Tyner #include <string> 16b1ebfcb1SBen Tyner 170205f3b3SBen Tyner namespace analyzer 180205f3b3SBen Tyner { 190205f3b3SBen Tyner 20f4bd5ff6SZane Shelley //------------------------------------------------------------------------------ 21b1ebfcb1SBen Tyner 22f4bd5ff6SZane Shelley // Forward references for externally defined functions. 2387eabc65SBen Tyner 24d3b9bac9SZane Shelley /** 25d3b9bac9SZane Shelley * @brief Will get the list of active chip and initialize the isolator. 26d3b9bac9SZane Shelley * @param o_chips The returned list of active chips. 27d3b9bac9SZane Shelley */ 28171a2e04SZane Shelley void initializeIsolator(std::vector<libhei::Chip>& o_chips); 2987eabc65SBen Tyner 30d3b9bac9SZane Shelley /** 31d3b9bac9SZane Shelley * @brief Will create and submit a PEL using the given data. 32d3b9bac9SZane Shelley * @param i_isoData The data gathered during isolation (for FFDC). 334ed4be56SZane Shelley * @param i_servData Data regarding service actions gathered during analysis. 34d3b9bac9SZane Shelley */ 35*8af9e46fSZane Shelley void createPel(const libhei::IsolationData& i_isoData, 364ed4be56SZane Shelley const ServiceData& i_servData); 37d3b9bac9SZane Shelley 38d84ed6e9SZane Shelley //------------------------------------------------------------------------------ 39d84ed6e9SZane Shelley 402f263181SZane Shelley const char* __attn(libhei::AttentionType_t i_attnType) 412f263181SZane Shelley { 422f263181SZane Shelley const char* str = ""; 432f263181SZane Shelley switch (i_attnType) 442f263181SZane Shelley { 452f263181SZane Shelley case libhei::ATTN_TYPE_CHECKSTOP: 462f263181SZane Shelley str = "CHECKSTOP"; 472f263181SZane Shelley break; 482f263181SZane Shelley case libhei::ATTN_TYPE_UNIT_CS: 492f263181SZane Shelley str = "UNIT_CS"; 502f263181SZane Shelley break; 512f263181SZane Shelley case libhei::ATTN_TYPE_RECOVERABLE: 522f263181SZane Shelley str = "RECOVERABLE"; 532f263181SZane Shelley break; 542f263181SZane Shelley case libhei::ATTN_TYPE_SP_ATTN: 552f263181SZane Shelley str = "SP_ATTN"; 562f263181SZane Shelley break; 572f263181SZane Shelley case libhei::ATTN_TYPE_HOST_ATTN: 582f263181SZane Shelley str = "HOST_ATTN"; 592f263181SZane Shelley break; 602f263181SZane Shelley default: 612f263181SZane Shelley trace::err("Unsupported attention type: %u", i_attnType); 622f263181SZane Shelley assert(0); 632f263181SZane Shelley } 642f263181SZane Shelley return str; 652f263181SZane Shelley } 662f263181SZane Shelley 672f263181SZane Shelley //------------------------------------------------------------------------------ 682f263181SZane Shelley 69cb457383SZane Shelley bool __filterRootCause(const libhei::IsolationData& i_isoData, 70cb457383SZane Shelley libhei::Signature& o_signature) 71097a71adSZane Shelley { 72cb457383SZane Shelley // We'll need to make a copy of the list so that the original list is 73cb457383SZane Shelley // maintained for the log. 74cb457383SZane Shelley std::vector<libhei::Signature> sigList{i_isoData.getSignatureList()}; 75cb457383SZane Shelley 762f263181SZane Shelley // For debug, trace out the original list of signatures before filtering. 77cb457383SZane Shelley for (const auto& sig : sigList) 782f263181SZane Shelley { 79f4bd5ff6SZane Shelley trace::inf("Signature: %s 0x%0" PRIx32 " %s", 80cb457383SZane Shelley util::pdbg::getPath(sig.getChip()), sig.toUint32(), 81f4bd5ff6SZane Shelley __attn(sig.getAttnType())); 822f263181SZane Shelley } 832f263181SZane Shelley 84097a71adSZane Shelley // Special and host attentions are not supported by this user application. 85097a71adSZane Shelley auto newEndItr = 86cb457383SZane Shelley std::remove_if(sigList.begin(), sigList.end(), [&](const auto& t) { 87097a71adSZane Shelley return (libhei::ATTN_TYPE_SP_ATTN == t.getAttnType() || 88097a71adSZane Shelley libhei::ATTN_TYPE_HOST_ATTN == t.getAttnType()); 89097a71adSZane Shelley }); 90097a71adSZane Shelley 91097a71adSZane Shelley // Shrink the vector, if needed. 92cb457383SZane Shelley sigList.resize(std::distance(sigList.begin(), newEndItr)); 93097a71adSZane Shelley 94097a71adSZane Shelley // START WORKAROUND 95097a71adSZane Shelley // TODO: Filtering should be determined by the RAS Data Files provided by 96097a71adSZane Shelley // the host firmware via the PNOR (similar to the Chip Data Files). 97097a71adSZane Shelley // Until that support is available, use a rudimentary filter that 98097a71adSZane Shelley // first looks for any recoverable attention, then any unit checkstop, 99097a71adSZane Shelley // and then any system checkstop. This is built on the premise that 100097a71adSZane Shelley // recoverable errors could be the root cause of an system checkstop 101097a71adSZane Shelley // attentions. Fortunately, we just need to sort the list by the 102097a71adSZane Shelley // greater attention type value. 103cb457383SZane Shelley std::sort(sigList.begin(), sigList.end(), 104097a71adSZane Shelley [&](const auto& a, const auto& b) { 105097a71adSZane Shelley return a.getAttnType() > b.getAttnType(); 106097a71adSZane Shelley }); 107097a71adSZane Shelley // END WORKAROUND 108cb457383SZane Shelley 109cb457383SZane Shelley // Check if a root cause attention was found. 110cb457383SZane Shelley if (!sigList.empty()) 111cb457383SZane Shelley { 112cb457383SZane Shelley // The entry at the front of the list will be the root cause. 113cb457383SZane Shelley o_signature = sigList.front(); 114cb457383SZane Shelley return true; 115cb457383SZane Shelley } 116cb457383SZane Shelley 117cb457383SZane Shelley return false; // default, no active attentions found. 118097a71adSZane Shelley } 119097a71adSZane Shelley 120097a71adSZane Shelley //------------------------------------------------------------------------------ 121097a71adSZane Shelley 122cb457383SZane Shelley bool __analyze(const libhei::IsolationData& i_isoData) 1239fb7393eSZane Shelley { 1249fb7393eSZane Shelley bool attnFound = false; 1259fb7393eSZane Shelley 126cb457383SZane Shelley libhei::Signature rootCause{}; 127cb457383SZane Shelley attnFound = __filterRootCause(i_isoData, rootCause); 128cb457383SZane Shelley 129cb457383SZane Shelley if (!attnFound) 1309fb7393eSZane Shelley { 131cb457383SZane Shelley // NOTE: It is possible for TI handling that there will not be an active 132cb457383SZane Shelley // attention. In which case, we will not do anything and let the 133cb457383SZane Shelley // caller of this function determine if this is the expected 134cb457383SZane Shelley // behavior. 1359fb7393eSZane Shelley trace::inf("No active attentions found"); 1369fb7393eSZane Shelley } 1379fb7393eSZane Shelley else 1389fb7393eSZane Shelley { 1399fb7393eSZane Shelley trace::inf("Root cause attention: %s 0x%0" PRIx32 " %s", 140cb457383SZane Shelley util::pdbg::getPath(rootCause.getChip()), 141cb457383SZane Shelley rootCause.toUint32(), __attn(rootCause.getAttnType())); 142cb457383SZane Shelley 1434ed4be56SZane Shelley // TODO: Perform service actions based on the root cause. The default 1444ed4be56SZane Shelley // callout if none other exist is level 2 support. 145*8af9e46fSZane Shelley ServiceData servData{rootCause}; 1464ed4be56SZane Shelley servData.addCallout(std::make_shared<ProcedureCallout>( 1474ed4be56SZane Shelley ProcedureCallout::NEXTLVL, Callout::Priority::HIGH)); 148d3b9bac9SZane Shelley 149d3b9bac9SZane Shelley // Create and commit a PEL. 150*8af9e46fSZane Shelley createPel(i_isoData, servData); 1519fb7393eSZane Shelley } 1529fb7393eSZane Shelley 1539fb7393eSZane Shelley return attnFound; 1549fb7393eSZane Shelley } 1559fb7393eSZane Shelley 1569fb7393eSZane Shelley //------------------------------------------------------------------------------ 1579fb7393eSZane Shelley 1589fb7393eSZane Shelley bool analyzeHardware() 15987eabc65SBen Tyner { 160097a71adSZane Shelley bool attnFound = false; 16187eabc65SBen Tyner 1622f263181SZane Shelley trace::inf(">>> enter analyzeHardware()"); 1632f263181SZane Shelley 1647ae9c8c7SZane Shelley if (util::pdbg::queryHardwareAnalysisSupported()) 1657ae9c8c7SZane Shelley { 166171a2e04SZane Shelley // Initialize the isolator and get all of the chips to be analyzed. 167f4bd5ff6SZane Shelley trace::inf("Initializing the isolator..."); 168171a2e04SZane Shelley std::vector<libhei::Chip> chips; 169f4bd5ff6SZane Shelley initializeIsolator(chips); 1702e994bcdSZane Shelley 171097a71adSZane Shelley // Isolate attentions. 172f4bd5ff6SZane Shelley trace::inf("Isolating errors: # of chips=%u", chips.size()); 173097a71adSZane Shelley libhei::IsolationData isoData{}; 174f4bd5ff6SZane Shelley libhei::isolate(chips, isoData); 17587eabc65SBen Tyner 176cb457383SZane Shelley // Analyze the isolation data and perform service actions if needed. 177cb457383SZane Shelley attnFound = __analyze(isoData); 17887eabc65SBen Tyner 179097a71adSZane Shelley // All done, clean up the isolator. 180f4bd5ff6SZane Shelley trace::inf("Uninitializing isolator..."); 181097a71adSZane Shelley libhei::uninitialize(); 1827ae9c8c7SZane Shelley } 1837ae9c8c7SZane Shelley else 1847ae9c8c7SZane Shelley { 1857ae9c8c7SZane Shelley trace::err("Hardware error analysis is not supported on this system"); 1867ae9c8c7SZane Shelley } 187b1ebfcb1SBen Tyner 1882f263181SZane Shelley trace::inf("<<< exit analyzeHardware()"); 1892f263181SZane Shelley 190097a71adSZane Shelley return attnFound; 1910205f3b3SBen Tyner } 1920205f3b3SBen Tyner 1930205f3b3SBen Tyner } // namespace analyzer 194