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> 7*f4bd5ff6SZane 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 19*f4bd5ff6SZane Shelley //------------------------------------------------------------------------------ 20b1ebfcb1SBen Tyner 21*f4bd5ff6SZane Shelley // Forward references for externally defined functions. 2287eabc65SBen Tyner 23*f4bd5ff6SZane Shelley void initializeIsolator(const std::vector<libhei::Chip>& i_chips); 2487eabc65SBen Tyner 25d84ed6e9SZane Shelley //------------------------------------------------------------------------------ 26d84ed6e9SZane Shelley 272f263181SZane Shelley uint8_t __attrType(pdbg_target* i_trgt) 282f263181SZane Shelley { 292f263181SZane Shelley uint8_t attr = 0; 302f263181SZane Shelley pdbg_target_get_attribute(i_trgt, "ATTR_TYPE", 1, 1, &attr); 312f263181SZane Shelley return attr; 322f263181SZane Shelley } 332f263181SZane Shelley 342f263181SZane Shelley uint32_t __attrFapiPos(pdbg_target* i_trgt) 352f263181SZane Shelley { 362f263181SZane Shelley uint32_t attr = 0; 372f263181SZane Shelley pdbg_target_get_attribute(i_trgt, "ATTR_FAPI_POS", 4, 1, &attr); 382f263181SZane Shelley return attr; 392f263181SZane Shelley } 402f263181SZane Shelley 412f263181SZane Shelley //------------------------------------------------------------------------------ 422f263181SZane Shelley 432f263181SZane Shelley const char* __attn(libhei::AttentionType_t i_attnType) 442f263181SZane Shelley { 452f263181SZane Shelley const char* str = ""; 462f263181SZane Shelley switch (i_attnType) 472f263181SZane Shelley { 482f263181SZane Shelley case libhei::ATTN_TYPE_CHECKSTOP: 492f263181SZane Shelley str = "CHECKSTOP"; 502f263181SZane Shelley break; 512f263181SZane Shelley case libhei::ATTN_TYPE_UNIT_CS: 522f263181SZane Shelley str = "UNIT_CS"; 532f263181SZane Shelley break; 542f263181SZane Shelley case libhei::ATTN_TYPE_RECOVERABLE: 552f263181SZane Shelley str = "RECOVERABLE"; 562f263181SZane Shelley break; 572f263181SZane Shelley case libhei::ATTN_TYPE_SP_ATTN: 582f263181SZane Shelley str = "SP_ATTN"; 592f263181SZane Shelley break; 602f263181SZane Shelley case libhei::ATTN_TYPE_HOST_ATTN: 612f263181SZane Shelley str = "HOST_ATTN"; 622f263181SZane Shelley break; 632f263181SZane Shelley default: 642f263181SZane Shelley trace::err("Unsupported attention type: %u", i_attnType); 652f263181SZane Shelley assert(0); 662f263181SZane Shelley } 672f263181SZane Shelley return str; 682f263181SZane Shelley } 692f263181SZane Shelley 702f263181SZane Shelley uint32_t __trgt(const libhei::Signature& i_sig) 712f263181SZane Shelley { 722f263181SZane Shelley auto trgt = (pdbg_target*)i_sig.getChip().getChip(); 732f263181SZane Shelley 742f263181SZane Shelley uint8_t type = __attrType(trgt); 752f263181SZane Shelley uint32_t pos = __attrFapiPos(trgt); 762f263181SZane Shelley 772f263181SZane Shelley // Technically, the FapiPos attribute is 32-bit, but not likely to ever go 782f263181SZane Shelley // over 24-bit. 792f263181SZane Shelley 802f263181SZane Shelley return type << 24 | (pos & 0xffffff); 812f263181SZane Shelley } 822f263181SZane Shelley 832f263181SZane Shelley uint32_t __sig(const libhei::Signature& i_sig) 842f263181SZane Shelley { 852f263181SZane Shelley return i_sig.getId() << 16 | i_sig.getInstance() << 8 | i_sig.getBit(); 862f263181SZane Shelley } 872f263181SZane Shelley 882f263181SZane Shelley //------------------------------------------------------------------------------ 892f263181SZane Shelley 90*f4bd5ff6SZane Shelley // Returns the chip model/level of the given target. 91*f4bd5ff6SZane Shelley libhei::ChipType_t __getChipType(pdbg_target* i_trgt) 92d84ed6e9SZane Shelley { 93d84ed6e9SZane Shelley libhei::ChipType_t type; 94d84ed6e9SZane Shelley 95d84ed6e9SZane Shelley // START WORKAROUND 96d84ed6e9SZane Shelley // TODO: Will need to grab the model/level from the target attributes when 97d84ed6e9SZane Shelley // they are available. For now, use ATTR_TYPE to determine which 98d84ed6e9SZane Shelley // currently supported value to use supported. 992f263181SZane Shelley uint8_t attrType = __attrType(i_trgt); 1002f263181SZane Shelley switch (attrType) 101d84ed6e9SZane Shelley { 102d84ed6e9SZane Shelley case 0x05: // PROC 103d84ed6e9SZane Shelley type = 0x120DA049; 104d84ed6e9SZane Shelley break; 105d84ed6e9SZane Shelley 106d84ed6e9SZane Shelley case 0x4b: // OCMB_CHIP 107d84ed6e9SZane Shelley type = 0x160D2000; 108d84ed6e9SZane Shelley break; 109d84ed6e9SZane Shelley 110d84ed6e9SZane Shelley default: 1112f263181SZane Shelley trace::err("Unsupported ATTR_TYPE value: 0x%02x", attrType); 112d84ed6e9SZane Shelley assert(0); 113d84ed6e9SZane Shelley } 114d84ed6e9SZane Shelley // END WORKAROUND 115d84ed6e9SZane Shelley 116d84ed6e9SZane Shelley return type; 117d84ed6e9SZane Shelley } 118d84ed6e9SZane Shelley 119d84ed6e9SZane Shelley //------------------------------------------------------------------------------ 120d84ed6e9SZane Shelley 121*f4bd5ff6SZane Shelley // Gathers list of active chips to analyze. 122*f4bd5ff6SZane Shelley void __getActiveChips(std::vector<libhei::Chip>& o_chips) 123d84ed6e9SZane Shelley { 124d84ed6e9SZane Shelley // Iterate each processor. 125d84ed6e9SZane Shelley pdbg_target* procTrgt; 126d84ed6e9SZane Shelley pdbg_for_each_class_target("proc", procTrgt) 127d84ed6e9SZane Shelley { 128d84ed6e9SZane Shelley // Active processors only. 129d84ed6e9SZane Shelley if (PDBG_TARGET_ENABLED != pdbg_target_probe(procTrgt)) 130d84ed6e9SZane Shelley continue; 131d84ed6e9SZane Shelley 132d84ed6e9SZane Shelley // Add the processor to the list. 133*f4bd5ff6SZane Shelley o_chips.emplace_back(procTrgt, __getChipType(procTrgt)); 134d84ed6e9SZane Shelley 135d84ed6e9SZane Shelley // Iterate the connected OCMBs, if they exist. 136d84ed6e9SZane Shelley pdbg_target* ocmbTrgt; 13706e10f91SZane Shelley pdbg_for_each_target("ocmb", procTrgt, ocmbTrgt) 138d84ed6e9SZane Shelley { 139d84ed6e9SZane Shelley // Active OCMBs only. 140d84ed6e9SZane Shelley if (PDBG_TARGET_ENABLED != pdbg_target_probe(ocmbTrgt)) 141d84ed6e9SZane Shelley continue; 142d84ed6e9SZane Shelley 143d84ed6e9SZane Shelley // Add the OCMB to the list. 144*f4bd5ff6SZane Shelley o_chips.emplace_back(ocmbTrgt, __getChipType(ocmbTrgt)); 145d84ed6e9SZane Shelley } 146d84ed6e9SZane Shelley } 1472e994bcdSZane Shelley } 1482e994bcdSZane Shelley 1492e994bcdSZane Shelley //------------------------------------------------------------------------------ 1502e994bcdSZane Shelley 151097a71adSZane Shelley // Takes a signature list that will be filtered and sorted. The first entry in 152097a71adSZane Shelley // the returned list will be the root cause. If the returned list is empty, 153097a71adSZane Shelley // analysis failed. 154097a71adSZane Shelley void __filterRootCause(std::vector<libhei::Signature>& io_list) 155097a71adSZane Shelley { 1562f263181SZane Shelley // For debug, trace out the original list of signatures before filtering. 1572f263181SZane Shelley for (const auto& sig : io_list) 1582f263181SZane Shelley { 159*f4bd5ff6SZane Shelley trace::inf("Signature: %s 0x%0" PRIx32 " %s", 160*f4bd5ff6SZane Shelley util::pdbg::getPath(sig.getChip()), __sig(sig), 161*f4bd5ff6SZane Shelley __attn(sig.getAttnType())); 1622f263181SZane Shelley } 1632f263181SZane Shelley 164097a71adSZane Shelley // Special and host attentions are not supported by this user application. 165097a71adSZane Shelley auto newEndItr = 166097a71adSZane Shelley std::remove_if(io_list.begin(), io_list.end(), [&](const auto& t) { 167097a71adSZane Shelley return (libhei::ATTN_TYPE_SP_ATTN == t.getAttnType() || 168097a71adSZane Shelley libhei::ATTN_TYPE_HOST_ATTN == t.getAttnType()); 169097a71adSZane Shelley }); 170097a71adSZane Shelley 171097a71adSZane Shelley // Shrink the vector, if needed. 172097a71adSZane Shelley io_list.resize(std::distance(io_list.begin(), newEndItr)); 173097a71adSZane Shelley 174097a71adSZane Shelley // START WORKAROUND 175097a71adSZane Shelley // TODO: Filtering should be determined by the RAS Data Files provided by 176097a71adSZane Shelley // the host firmware via the PNOR (similar to the Chip Data Files). 177097a71adSZane Shelley // Until that support is available, use a rudimentary filter that 178097a71adSZane Shelley // first looks for any recoverable attention, then any unit checkstop, 179097a71adSZane Shelley // and then any system checkstop. This is built on the premise that 180097a71adSZane Shelley // recoverable errors could be the root cause of an system checkstop 181097a71adSZane Shelley // attentions. Fortunately, we just need to sort the list by the 182097a71adSZane Shelley // greater attention type value. 183097a71adSZane Shelley std::sort(io_list.begin(), io_list.end(), 184097a71adSZane Shelley [&](const auto& a, const auto& b) { 185097a71adSZane Shelley return a.getAttnType() > b.getAttnType(); 186097a71adSZane Shelley }); 187097a71adSZane Shelley // END WORKAROUND 188097a71adSZane Shelley } 189097a71adSZane Shelley 190097a71adSZane Shelley //------------------------------------------------------------------------------ 191097a71adSZane Shelley 1929fb7393eSZane Shelley bool __logError(const std::vector<libhei::Signature>& i_sigList, 1939fb7393eSZane Shelley const libhei::IsolationData& i_isoData) 1949fb7393eSZane Shelley { 1959fb7393eSZane Shelley bool attnFound = false; 1969fb7393eSZane Shelley 1979fb7393eSZane Shelley // Get numerical values for the root cause. 1989fb7393eSZane Shelley uint32_t word6 = 0; // [ 0: 7]: chip target type 1999fb7393eSZane Shelley // [ 8:31]: chip FAPI position 2009fb7393eSZane Shelley // uint32_t word7 = 0; // TODO: chip target info 2019fb7393eSZane Shelley uint32_t word8 = 0; // [ 0:15]: node ID 2029fb7393eSZane Shelley // [16:23]: node instance 2039fb7393eSZane Shelley // [24:31]: bit position 2049fb7393eSZane Shelley // uint32_t word9 = 0; // [ 0: 7]: attention type 2059fb7393eSZane Shelley 2069fb7393eSZane Shelley if (i_sigList.empty()) 2079fb7393eSZane Shelley { 2089fb7393eSZane Shelley trace::inf("No active attentions found"); 2099fb7393eSZane Shelley } 2109fb7393eSZane Shelley else 2119fb7393eSZane Shelley { 2129fb7393eSZane Shelley attnFound = true; 2139fb7393eSZane Shelley 2149fb7393eSZane Shelley // The root cause attention is the first in the filtered list. 2159fb7393eSZane Shelley libhei::Signature root = i_sigList.front(); 2169fb7393eSZane Shelley 2179fb7393eSZane Shelley word6 = __trgt(root); 2189fb7393eSZane Shelley word8 = __sig(root); 2199fb7393eSZane Shelley 2209fb7393eSZane Shelley trace::inf("Root cause attention: %s 0x%0" PRIx32 " %s", 221*f4bd5ff6SZane Shelley util::pdbg::getPath(root.getChip()), word8, 222*f4bd5ff6SZane Shelley __attn(root.getAttnType())); 2239fb7393eSZane Shelley } 2249fb7393eSZane Shelley 2259fb7393eSZane Shelley // Get the log data. 2269fb7393eSZane Shelley std::map<std::string, std::string> logData; 2279fb7393eSZane Shelley logData["_PID"] = std::to_string(getpid()); 2289fb7393eSZane Shelley logData["CHIP_ID"] = std::to_string(word6); 2299fb7393eSZane Shelley logData["SIGNATURE"] = std::to_string(word8); 2309fb7393eSZane Shelley 2319fb7393eSZane Shelley // Get access to logging interface and method for creating log. 2329fb7393eSZane Shelley auto bus = sdbusplus::bus::new_default_system(); 2339fb7393eSZane Shelley 2349fb7393eSZane Shelley // Using direct create method (for additional data) 2359fb7393eSZane Shelley auto method = bus.new_method_call( 2369fb7393eSZane Shelley "xyz.openbmc_project.Logging", "/xyz/openbmc_project/logging", 2379fb7393eSZane Shelley "xyz.openbmc_project.Logging.Create", "Create"); 2389fb7393eSZane Shelley 2399fb7393eSZane Shelley // Attach additional data 2409fb7393eSZane Shelley method.append("org.open_power.HwDiags.Error.Checkstop", 2419fb7393eSZane Shelley "xyz.openbmc_project.Logging.Entry.Level.Error", logData); 2429fb7393eSZane Shelley 2439fb7393eSZane Shelley // Log the event. 2449fb7393eSZane Shelley // TODO: Should the reply be handled? 2459fb7393eSZane Shelley bus.call(method); 2469fb7393eSZane Shelley 2479fb7393eSZane Shelley return attnFound; 2489fb7393eSZane Shelley } 2499fb7393eSZane Shelley 2509fb7393eSZane Shelley //------------------------------------------------------------------------------ 2519fb7393eSZane Shelley 2529fb7393eSZane Shelley bool analyzeHardware() 25387eabc65SBen Tyner { 254097a71adSZane Shelley bool attnFound = false; 25587eabc65SBen Tyner 2562f263181SZane Shelley trace::inf(">>> enter analyzeHardware()"); 2572f263181SZane Shelley 258*f4bd5ff6SZane Shelley // Get the active chips to be analyzed. 259*f4bd5ff6SZane Shelley std::vector<libhei::Chip> chips; 260*f4bd5ff6SZane Shelley __getActiveChips(chips); 26187eabc65SBen Tyner 262*f4bd5ff6SZane Shelley // Initialize the isolator for all chips. 263*f4bd5ff6SZane Shelley trace::inf("Initializing the isolator..."); 264*f4bd5ff6SZane Shelley initializeIsolator(chips); 2652e994bcdSZane Shelley 266097a71adSZane Shelley // Isolate attentions. 267*f4bd5ff6SZane Shelley trace::inf("Isolating errors: # of chips=%u", chips.size()); 268097a71adSZane Shelley libhei::IsolationData isoData{}; 269*f4bd5ff6SZane Shelley libhei::isolate(chips, isoData); 27087eabc65SBen Tyner 2712f263181SZane Shelley // Filter signatures to determine root cause. We'll need to make a copy of 2722f263181SZane Shelley // the list so that the original list is maintained for the log. 273097a71adSZane Shelley std::vector<libhei::Signature> sigList{isoData.getSignatureList()}; 274097a71adSZane Shelley __filterRootCause(sigList); 275097a71adSZane Shelley 2769fb7393eSZane Shelley // Create and commit a log. 2779fb7393eSZane Shelley attnFound = __logError(sigList, isoData); 27887eabc65SBen Tyner 279097a71adSZane Shelley // All done, clean up the isolator. 280*f4bd5ff6SZane Shelley trace::inf("Uninitializing isolator..."); 281097a71adSZane Shelley libhei::uninitialize(); 282b1ebfcb1SBen Tyner 2832f263181SZane Shelley trace::inf("<<< exit analyzeHardware()"); 2842f263181SZane Shelley 285097a71adSZane Shelley return attnFound; 2860205f3b3SBen Tyner } 2870205f3b3SBen Tyner 2880205f3b3SBen Tyner } // namespace analyzer 289