1 #include <fmt/format.h> 2 extern "C" 3 { 4 #include <libpdbg.h> 5 #include <libpdbg_sbe.h> 6 } 7 8 #include <libphal.H> 9 10 #include <phosphor-logging/log.hpp> 11 #include <watchdog_common.hpp> 12 #include <watchdog_dbus.hpp> 13 #include <watchdog_handler.hpp> 14 #include <watchdog_logging.hpp> 15 16 namespace watchdog 17 { 18 namespace dump 19 { 20 21 using namespace phosphor::logging; 22 23 void triggerHostbootDump(const uint32_t timeout) 24 { 25 constexpr auto HOST_STATE_DIAGNOSTIC_MODE = 26 "obmc-host-diagnostic-mode@0.target"; 27 constexpr auto HOST_STATE_QUIESCE_TGT = "obmc-host-quiesce@0.target"; 28 29 // Put system into diagnostic mode 30 transitionHost(HOST_STATE_DIAGNOSTIC_MODE); 31 32 eventWatchdogTimeout(timeout); 33 34 // Put system into quiesce state 35 transitionHost(HOST_STATE_QUIESCE_TGT); 36 } 37 38 void handleSbeBootError(struct pdbg_target* procTarget, const uint32_t timeout) 39 { 40 using namespace openpower::phal; 41 42 sbeError_t sbeError; 43 bool dumpIsRequired = false; 44 45 try 46 { 47 // Capture FFDC information on primary processor 48 sbeError = sbe::captureFFDC(procTarget); 49 } 50 catch (const std::exception& e) 51 { 52 // Failed to collect FFDC information 53 log<level::ERR>( 54 fmt::format("captureFFDC: Exception{}", e.what()).c_str()); 55 dumpIsRequired = true; 56 } 57 58 // event type 59 std::string event; 60 if ((sbeError.errType() == exception::SBE_FFDC_NO_DATA) || 61 (sbeError.errType() == exception::SBE_CMD_TIMEOUT) || (dumpIsRequired)) 62 { 63 log<level::INFO>("No FFDC data"); 64 event = "org.open_power.Processor.Error.SbeBootTimeout"; 65 dumpIsRequired = true; 66 } 67 else 68 { 69 log<level::ERR>("SBE Boot failure"); 70 event = "org.open_power.Processor.Error.SbeBootFailure"; 71 } 72 73 // Additional data 74 std::map<std::string, std::string> additionalData; 75 76 // SRC6 : [0:15] chip position 77 uint32_t index = pdbg_target_index(procTarget); 78 additionalData.emplace("SRC6", std::to_string(index << 16)); 79 additionalData.emplace("SBE_ERR_MSG", sbeError.what()); 80 81 // FFDC 82 auto ffdc = std::vector<FFDCTuple>{}; 83 // get SBE ffdc file descriptor 84 auto fd = sbeError.getFd(); 85 86 // Log error with additional ffdc if fd is valid 87 if (fd > 0) 88 { 89 ffdc.push_back( 90 std::make_tuple(sdbusplus::xyz::openbmc_project::Logging::server:: 91 Create::FFDCFormat::Custom, 92 static_cast<uint8_t>(0xCB), 93 static_cast<uint8_t>(0x01), sbeError.getFd())); 94 } 95 96 auto pelId = createPel(event, additionalData, ffdc); 97 98 if (dumpIsRequired) 99 { 100 try 101 { 102 using namespace openpower::phal; 103 104 // Check SBE dump collection allowed 105 bool dumpAllowed = sbe::isDumpAllowed(procTarget); 106 if (!dumpAllowed) 107 { 108 // Possibly another collection in progress, skip dump collection 109 log<level::INFO>("Another collection is in progress, skipping " 110 "dump collection"); 111 return; 112 } 113 } 114 catch (const std::exception& e) 115 { 116 log<level::ERR>( 117 fmt::format("Exception {} occurred", e.what()).c_str()); 118 return; 119 } 120 121 DumpParameters dumpParameters; 122 dumpParameters.logId = pelId; 123 dumpParameters.unitId = index; 124 dumpParameters.timeout = timeout; 125 dumpParameters.dumpType = DumpType::SBE; 126 127 // will not return until dump is complete or timeout 128 requestDump(dumpParameters); 129 } 130 } 131 132 } // namespace dump 133 } // namespace watchdog 134