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 uint32_t __trgt(const libhei::Signature& i_sig) 672f263181SZane Shelley { 68a0299858SZane Shelley uint8_t type = util::pdbg::getTrgtType(i_sig.getChip()); 69a0299858SZane Shelley uint32_t pos = util::pdbg::getChipPos(i_sig.getChip()); 702f263181SZane Shelley 712f263181SZane Shelley // Technically, the FapiPos attribute is 32-bit, but not likely to ever go 722f263181SZane Shelley // over 24-bit. 732f263181SZane Shelley 742f263181SZane Shelley return type << 24 | (pos & 0xffffff); 752f263181SZane Shelley } 762f263181SZane Shelley 772f263181SZane Shelley uint32_t __sig(const libhei::Signature& i_sig) 782f263181SZane Shelley { 792f263181SZane Shelley return i_sig.getId() << 16 | i_sig.getInstance() << 8 | i_sig.getBit(); 802f263181SZane Shelley } 812f263181SZane Shelley 822f263181SZane Shelley //------------------------------------------------------------------------------ 832f263181SZane Shelley 84097a71adSZane Shelley // Takes a signature list that will be filtered and sorted. The first entry in 85097a71adSZane Shelley // the returned list will be the root cause. If the returned list is empty, 86097a71adSZane Shelley // analysis failed. 87097a71adSZane Shelley void __filterRootCause(std::vector<libhei::Signature>& io_list) 88097a71adSZane Shelley { 892f263181SZane Shelley // For debug, trace out the original list of signatures before filtering. 902f263181SZane Shelley for (const auto& sig : io_list) 912f263181SZane Shelley { 92f4bd5ff6SZane Shelley trace::inf("Signature: %s 0x%0" PRIx32 " %s", 93f4bd5ff6SZane Shelley util::pdbg::getPath(sig.getChip()), __sig(sig), 94f4bd5ff6SZane Shelley __attn(sig.getAttnType())); 952f263181SZane Shelley } 962f263181SZane Shelley 97097a71adSZane Shelley // Special and host attentions are not supported by this user application. 98097a71adSZane Shelley auto newEndItr = 99097a71adSZane Shelley std::remove_if(io_list.begin(), io_list.end(), [&](const auto& t) { 100097a71adSZane Shelley return (libhei::ATTN_TYPE_SP_ATTN == t.getAttnType() || 101097a71adSZane Shelley libhei::ATTN_TYPE_HOST_ATTN == t.getAttnType()); 102097a71adSZane Shelley }); 103097a71adSZane Shelley 104097a71adSZane Shelley // Shrink the vector, if needed. 105097a71adSZane Shelley io_list.resize(std::distance(io_list.begin(), newEndItr)); 106097a71adSZane Shelley 107097a71adSZane Shelley // START WORKAROUND 108097a71adSZane Shelley // TODO: Filtering should be determined by the RAS Data Files provided by 109097a71adSZane Shelley // the host firmware via the PNOR (similar to the Chip Data Files). 110097a71adSZane Shelley // Until that support is available, use a rudimentary filter that 111097a71adSZane Shelley // first looks for any recoverable attention, then any unit checkstop, 112097a71adSZane Shelley // and then any system checkstop. This is built on the premise that 113097a71adSZane Shelley // recoverable errors could be the root cause of an system checkstop 114097a71adSZane Shelley // attentions. Fortunately, we just need to sort the list by the 115097a71adSZane Shelley // greater attention type value. 116097a71adSZane Shelley std::sort(io_list.begin(), io_list.end(), 117097a71adSZane Shelley [&](const auto& a, const auto& b) { 118097a71adSZane Shelley return a.getAttnType() > b.getAttnType(); 119097a71adSZane Shelley }); 120097a71adSZane Shelley // END WORKAROUND 121097a71adSZane Shelley } 122097a71adSZane Shelley 123097a71adSZane Shelley //------------------------------------------------------------------------------ 124097a71adSZane Shelley 1259fb7393eSZane Shelley bool __logError(const std::vector<libhei::Signature>& i_sigList, 1269fb7393eSZane Shelley const libhei::IsolationData& i_isoData) 1279fb7393eSZane Shelley { 1289fb7393eSZane Shelley bool attnFound = false; 1299fb7393eSZane Shelley 1309fb7393eSZane Shelley if (i_sigList.empty()) 1319fb7393eSZane Shelley { 1329fb7393eSZane Shelley trace::inf("No active attentions found"); 1339fb7393eSZane Shelley } 1349fb7393eSZane Shelley else 1359fb7393eSZane Shelley { 1369fb7393eSZane Shelley attnFound = true; 1379fb7393eSZane Shelley 1389fb7393eSZane Shelley // The root cause attention is the first in the filtered list. 1399fb7393eSZane Shelley libhei::Signature root = i_sigList.front(); 1409fb7393eSZane Shelley 1419fb7393eSZane Shelley trace::inf("Root cause attention: %s 0x%0" PRIx32 " %s", 142d3b9bac9SZane Shelley util::pdbg::getPath(root.getChip()), root.toUint32(), 143f4bd5ff6SZane Shelley __attn(root.getAttnType())); 144d3b9bac9SZane Shelley 145d3b9bac9SZane Shelley // Create and commit a PEL. 146d3b9bac9SZane Shelley createPel(root, i_isoData); 1479fb7393eSZane Shelley } 1489fb7393eSZane Shelley 1499fb7393eSZane Shelley return attnFound; 1509fb7393eSZane Shelley } 1519fb7393eSZane Shelley 1529fb7393eSZane Shelley //------------------------------------------------------------------------------ 1539fb7393eSZane Shelley 1549fb7393eSZane Shelley bool analyzeHardware() 15587eabc65SBen Tyner { 156097a71adSZane Shelley bool attnFound = false; 15787eabc65SBen Tyner 1582f263181SZane Shelley trace::inf(">>> enter analyzeHardware()"); 1592f263181SZane Shelley 160*7ae9c8c7SZane Shelley if (util::pdbg::queryHardwareAnalysisSupported()) 161*7ae9c8c7SZane Shelley { 162171a2e04SZane Shelley // Initialize the isolator and get all of the chips to be analyzed. 163f4bd5ff6SZane Shelley trace::inf("Initializing the isolator..."); 164171a2e04SZane Shelley std::vector<libhei::Chip> chips; 165f4bd5ff6SZane Shelley initializeIsolator(chips); 1662e994bcdSZane Shelley 167097a71adSZane Shelley // Isolate attentions. 168f4bd5ff6SZane Shelley trace::inf("Isolating errors: # of chips=%u", chips.size()); 169097a71adSZane Shelley libhei::IsolationData isoData{}; 170f4bd5ff6SZane Shelley libhei::isolate(chips, isoData); 17187eabc65SBen Tyner 172*7ae9c8c7SZane Shelley // Filter signatures to determine root cause. We'll need to make a copy 173*7ae9c8c7SZane Shelley // of the list so that the original list is maintained for the log. 174097a71adSZane Shelley std::vector<libhei::Signature> sigList{isoData.getSignatureList()}; 175097a71adSZane Shelley __filterRootCause(sigList); 176097a71adSZane Shelley 1779fb7393eSZane Shelley // Create and commit a log. 1789fb7393eSZane Shelley attnFound = __logError(sigList, isoData); 17987eabc65SBen Tyner 180097a71adSZane Shelley // All done, clean up the isolator. 181f4bd5ff6SZane Shelley trace::inf("Uninitializing isolator..."); 182097a71adSZane Shelley libhei::uninitialize(); 183*7ae9c8c7SZane Shelley } 184*7ae9c8c7SZane Shelley else 185*7ae9c8c7SZane Shelley { 186*7ae9c8c7SZane Shelley trace::err("Hardware error analysis is not supported on this system"); 187*7ae9c8c7SZane Shelley } 188b1ebfcb1SBen Tyner 1892f263181SZane Shelley trace::inf("<<< exit analyzeHardware()"); 1902f263181SZane Shelley 191097a71adSZane Shelley return attnFound; 1920205f3b3SBen Tyner } 1930205f3b3SBen Tyner 1940205f3b3SBen Tyner } // namespace analyzer 195