1d84ed6e9SZane Shelley #include <assert.h> 287eabc65SBen Tyner #include <libpdbg.h> 39fb7393eSZane Shelley #include <unistd.h> 487eabc65SBen Tyner 50205f3b3SBen Tyner #include <hei_main.hpp> 69fb7393eSZane Shelley #include <phosphor-logging/log.hpp> 7f4bd5ff6SZane Shelley #include <util/pdbg.hpp> 8d84ed6e9SZane Shelley #include <util/trace.hpp> 90205f3b3SBen Tyner 10d84ed6e9SZane Shelley #include <algorithm> 1187eabc65SBen Tyner #include <fstream> 1287eabc65SBen Tyner #include <iostream> 13b1ebfcb1SBen Tyner #include <map> 14b1ebfcb1SBen Tyner #include <string> 15b1ebfcb1SBen Tyner 160205f3b3SBen Tyner namespace analyzer 170205f3b3SBen Tyner { 180205f3b3SBen Tyner 19f4bd5ff6SZane Shelley //------------------------------------------------------------------------------ 20b1ebfcb1SBen Tyner 21f4bd5ff6SZane Shelley // Forward references for externally defined functions. 2287eabc65SBen Tyner 23d3b9bac9SZane Shelley /** 24d3b9bac9SZane Shelley * @brief Will get the list of active chip and initialize the isolator. 25d3b9bac9SZane Shelley * @param o_chips The returned list of active chips. 26d3b9bac9SZane Shelley */ 27171a2e04SZane Shelley void initializeIsolator(std::vector<libhei::Chip>& o_chips); 2887eabc65SBen Tyner 29d3b9bac9SZane Shelley /** 30d3b9bac9SZane Shelley * @brief Will create and submit a PEL using the given data. 31d3b9bac9SZane Shelley * @param i_rootCause A signature defining the attention root cause. 32d3b9bac9SZane Shelley * @param i_isoData The data gathered during isolation (for FFDC). 33d3b9bac9SZane Shelley */ 34d3b9bac9SZane Shelley void createPel(const libhei::Signature& i_rootCause, 35d3b9bac9SZane Shelley const libhei::IsolationData& i_isoData); 36d3b9bac9SZane Shelley 37d84ed6e9SZane Shelley //------------------------------------------------------------------------------ 38d84ed6e9SZane Shelley 392f263181SZane Shelley const char* __attn(libhei::AttentionType_t i_attnType) 402f263181SZane Shelley { 412f263181SZane Shelley const char* str = ""; 422f263181SZane Shelley switch (i_attnType) 432f263181SZane Shelley { 442f263181SZane Shelley case libhei::ATTN_TYPE_CHECKSTOP: 452f263181SZane Shelley str = "CHECKSTOP"; 462f263181SZane Shelley break; 472f263181SZane Shelley case libhei::ATTN_TYPE_UNIT_CS: 482f263181SZane Shelley str = "UNIT_CS"; 492f263181SZane Shelley break; 502f263181SZane Shelley case libhei::ATTN_TYPE_RECOVERABLE: 512f263181SZane Shelley str = "RECOVERABLE"; 522f263181SZane Shelley break; 532f263181SZane Shelley case libhei::ATTN_TYPE_SP_ATTN: 542f263181SZane Shelley str = "SP_ATTN"; 552f263181SZane Shelley break; 562f263181SZane Shelley case libhei::ATTN_TYPE_HOST_ATTN: 572f263181SZane Shelley str = "HOST_ATTN"; 582f263181SZane Shelley break; 592f263181SZane Shelley default: 602f263181SZane Shelley trace::err("Unsupported attention type: %u", i_attnType); 612f263181SZane Shelley assert(0); 622f263181SZane Shelley } 632f263181SZane Shelley return str; 642f263181SZane Shelley } 652f263181SZane Shelley 662f263181SZane Shelley //------------------------------------------------------------------------------ 672f263181SZane Shelley 68*cb457383SZane Shelley bool __filterRootCause(const libhei::IsolationData& i_isoData, 69*cb457383SZane Shelley libhei::Signature& o_signature) 70097a71adSZane Shelley { 71*cb457383SZane Shelley // We'll need to make a copy of the list so that the original list is 72*cb457383SZane Shelley // maintained for the log. 73*cb457383SZane Shelley std::vector<libhei::Signature> sigList{i_isoData.getSignatureList()}; 74*cb457383SZane Shelley 752f263181SZane Shelley // For debug, trace out the original list of signatures before filtering. 76*cb457383SZane Shelley for (const auto& sig : sigList) 772f263181SZane Shelley { 78f4bd5ff6SZane Shelley trace::inf("Signature: %s 0x%0" PRIx32 " %s", 79*cb457383SZane Shelley util::pdbg::getPath(sig.getChip()), sig.toUint32(), 80f4bd5ff6SZane Shelley __attn(sig.getAttnType())); 812f263181SZane Shelley } 822f263181SZane Shelley 83097a71adSZane Shelley // Special and host attentions are not supported by this user application. 84097a71adSZane Shelley auto newEndItr = 85*cb457383SZane Shelley std::remove_if(sigList.begin(), sigList.end(), [&](const auto& t) { 86097a71adSZane Shelley return (libhei::ATTN_TYPE_SP_ATTN == t.getAttnType() || 87097a71adSZane Shelley libhei::ATTN_TYPE_HOST_ATTN == t.getAttnType()); 88097a71adSZane Shelley }); 89097a71adSZane Shelley 90097a71adSZane Shelley // Shrink the vector, if needed. 91*cb457383SZane Shelley sigList.resize(std::distance(sigList.begin(), newEndItr)); 92097a71adSZane Shelley 93097a71adSZane Shelley // START WORKAROUND 94097a71adSZane Shelley // TODO: Filtering should be determined by the RAS Data Files provided by 95097a71adSZane Shelley // the host firmware via the PNOR (similar to the Chip Data Files). 96097a71adSZane Shelley // Until that support is available, use a rudimentary filter that 97097a71adSZane Shelley // first looks for any recoverable attention, then any unit checkstop, 98097a71adSZane Shelley // and then any system checkstop. This is built on the premise that 99097a71adSZane Shelley // recoverable errors could be the root cause of an system checkstop 100097a71adSZane Shelley // attentions. Fortunately, we just need to sort the list by the 101097a71adSZane Shelley // greater attention type value. 102*cb457383SZane Shelley std::sort(sigList.begin(), sigList.end(), 103097a71adSZane Shelley [&](const auto& a, const auto& b) { 104097a71adSZane Shelley return a.getAttnType() > b.getAttnType(); 105097a71adSZane Shelley }); 106097a71adSZane Shelley // END WORKAROUND 107*cb457383SZane Shelley 108*cb457383SZane Shelley // Check if a root cause attention was found. 109*cb457383SZane Shelley if (!sigList.empty()) 110*cb457383SZane Shelley { 111*cb457383SZane Shelley // The entry at the front of the list will be the root cause. 112*cb457383SZane Shelley o_signature = sigList.front(); 113*cb457383SZane Shelley return true; 114*cb457383SZane Shelley } 115*cb457383SZane Shelley 116*cb457383SZane Shelley return false; // default, no active attentions found. 117097a71adSZane Shelley } 118097a71adSZane Shelley 119097a71adSZane Shelley //------------------------------------------------------------------------------ 120097a71adSZane Shelley 121*cb457383SZane Shelley bool __analyze(const libhei::IsolationData& i_isoData) 1229fb7393eSZane Shelley { 1239fb7393eSZane Shelley bool attnFound = false; 1249fb7393eSZane Shelley 125*cb457383SZane Shelley libhei::Signature rootCause{}; 126*cb457383SZane Shelley attnFound = __filterRootCause(i_isoData, rootCause); 127*cb457383SZane Shelley 128*cb457383SZane Shelley if (!attnFound) 1299fb7393eSZane Shelley { 130*cb457383SZane Shelley // NOTE: It is possible for TI handling that there will not be an active 131*cb457383SZane Shelley // attention. In which case, we will not do anything and let the 132*cb457383SZane Shelley // caller of this function determine if this is the expected 133*cb457383SZane Shelley // behavior. 1349fb7393eSZane Shelley trace::inf("No active attentions found"); 1359fb7393eSZane Shelley } 1369fb7393eSZane Shelley else 1379fb7393eSZane Shelley { 1389fb7393eSZane Shelley trace::inf("Root cause attention: %s 0x%0" PRIx32 " %s", 139*cb457383SZane Shelley util::pdbg::getPath(rootCause.getChip()), 140*cb457383SZane Shelley rootCause.toUint32(), __attn(rootCause.getAttnType())); 141*cb457383SZane Shelley 142*cb457383SZane Shelley // TODO: Perform service actions based on the root cause. 143d3b9bac9SZane Shelley 144d3b9bac9SZane Shelley // Create and commit a PEL. 145*cb457383SZane Shelley createPel(rootCause, i_isoData); 1469fb7393eSZane Shelley } 1479fb7393eSZane Shelley 1489fb7393eSZane Shelley return attnFound; 1499fb7393eSZane Shelley } 1509fb7393eSZane Shelley 1519fb7393eSZane Shelley //------------------------------------------------------------------------------ 1529fb7393eSZane Shelley 1539fb7393eSZane Shelley bool analyzeHardware() 15487eabc65SBen Tyner { 155097a71adSZane Shelley bool attnFound = false; 15687eabc65SBen Tyner 1572f263181SZane Shelley trace::inf(">>> enter analyzeHardware()"); 1582f263181SZane Shelley 1597ae9c8c7SZane Shelley if (util::pdbg::queryHardwareAnalysisSupported()) 1607ae9c8c7SZane Shelley { 161171a2e04SZane Shelley // Initialize the isolator and get all of the chips to be analyzed. 162f4bd5ff6SZane Shelley trace::inf("Initializing the isolator..."); 163171a2e04SZane Shelley std::vector<libhei::Chip> chips; 164f4bd5ff6SZane Shelley initializeIsolator(chips); 1652e994bcdSZane Shelley 166097a71adSZane Shelley // Isolate attentions. 167f4bd5ff6SZane Shelley trace::inf("Isolating errors: # of chips=%u", chips.size()); 168097a71adSZane Shelley libhei::IsolationData isoData{}; 169f4bd5ff6SZane Shelley libhei::isolate(chips, isoData); 17087eabc65SBen Tyner 171*cb457383SZane Shelley // Analyze the isolation data and perform service actions if needed. 172*cb457383SZane Shelley attnFound = __analyze(isoData); 17387eabc65SBen Tyner 174097a71adSZane Shelley // All done, clean up the isolator. 175f4bd5ff6SZane Shelley trace::inf("Uninitializing isolator..."); 176097a71adSZane Shelley libhei::uninitialize(); 1777ae9c8c7SZane Shelley } 1787ae9c8c7SZane Shelley else 1797ae9c8c7SZane Shelley { 1807ae9c8c7SZane Shelley trace::err("Hardware error analysis is not supported on this system"); 1817ae9c8c7SZane Shelley } 182b1ebfcb1SBen Tyner 1832f263181SZane Shelley trace::inf("<<< exit analyzeHardware()"); 1842f263181SZane Shelley 185097a71adSZane Shelley return attnFound; 1860205f3b3SBen Tyner } 1870205f3b3SBen Tyner 1880205f3b3SBen Tyner } // namespace analyzer 189