#include extern "C" { #include #include } #include #include #include #include #include #include namespace watchdog { namespace dump { void triggerHostbootDump(const uint32_t timeout) { constexpr auto HOST_STATE_DIAGNOSTIC_MODE = "obmc-host-diagnostic-mode@0.target"; constexpr auto HOST_STATE_QUIESCE_TGT = "obmc-host-quiesce@0.target"; // Put system into diagnostic mode transitionHost(HOST_STATE_DIAGNOSTIC_MODE); eventWatchdogTimeout(timeout); // Put system into quiesce state transitionHost(HOST_STATE_QUIESCE_TGT); } /** * @brief get SBE special callout information * * @details This function adds the special sbe callout in the user provided * json callout list. includes BMC0002 procedure callout with high priority * and processor callout with medium priority. * * @param[in] procTarget - pdbg processor target * @param[out] jsonCalloutDataList - reference to json callout list */ static void getSBECallout(struct pdbg_target* procTarget, json& jsonCalloutDataList) { using namespace openpower::phal::pdbg; json jsonProcedCallout; // Add procedure callout jsonProcedCallout["Procedure"] = "BMC0002"; jsonProcedCallout["Priority"] = "H"; jsonCalloutDataList.emplace_back(jsonProcedCallout); try { ATTR_LOCATION_CODE_Type locationCode; // Initialize with default data. memset(&locationCode, '\0', sizeof(locationCode)); // Get location code information openpower::phal::pdbg::getLocationCode(procTarget, locationCode); json jsonProcCallout; jsonProcCallout["LocationCode"] = locationCode; jsonProcCallout["Deconfigured"] = false; jsonProcCallout["Guarded"] = false; jsonProcCallout["Priority"] = "M"; jsonCalloutDataList.emplace_back(jsonProcCallout); } catch (const std::exception& e) { lg2::error("getLocationCode({LOCATION}): Exception({ERROR})", "LOCATION", pdbg_target_path(procTarget), "ERROR", e); } } void handleSbeBootError(struct pdbg_target* procTarget, const uint32_t timeout) { using namespace openpower::phal; sbeError_t sbeError; bool dumpIsRequired = false; try { // Capture FFDC information on primary processor sbeError = sbe::captureFFDC(procTarget); } catch (const std::exception& e) { // Failed to collect FFDC information lg2::error("captureFFDC: Exception{ERROR}", "ERROR", e); dumpIsRequired = true; } // event type std::string event; if ((sbeError.errType() == exception::SBE_FFDC_NO_DATA) || (sbeError.errType() == exception::SBE_CMD_TIMEOUT) || (dumpIsRequired)) { lg2::info("No FFDC data"); event = "org.open_power.Processor.Error.SbeBootTimeout"; dumpIsRequired = true; } else { lg2::error("SBE Boot failure"); event = "org.open_power.Processor.Error.SbeBootFailure"; } // Additional data std::map additionalData; // SRC6 : [0:15] chip position uint32_t index = pdbg_target_index(procTarget); additionalData.emplace("SRC6", std::to_string(index << 16)); additionalData.emplace("SBE_ERR_MSG", sbeError.what()); // FFDC auto ffdc = std::vector{}; // get SBE ffdc file descriptor auto fd = sbeError.getFd(); // Log error with additional ffdc if fd is valid if (fd > 0) { ffdc.push_back( std::make_tuple(sdbusplus::xyz::openbmc_project::Logging::server:: Create::FFDCFormat::Custom, static_cast(0xCB), static_cast(0x01), sbeError.getFd())); } std::unique_ptr ffdcFilePtr; try { if (dumpIsRequired) { // Additional callout is required for SBE timeout case // In this case no SBE FFDC information available and // required to add default callouts. json jsonCalloutDataList; jsonCalloutDataList = json::array(); getSBECallout(procTarget, jsonCalloutDataList); ffdcFilePtr = std::make_unique(jsonCalloutDataList); ffdc.push_back(std::make_tuple( sdbusplus::xyz::openbmc_project::Logging::server::Create:: FFDCFormat::JSON, static_cast(0xCA), static_cast(0x01), ffdcFilePtr->getFileDescriptor())); } } catch (const std::exception& e) { lg2::error("Skipping SBE special callout due to Exception({ERROR})", "ERROR", e); } auto pelId = createPel(event, additionalData, ffdc); if (dumpIsRequired) { try { using namespace openpower::phal; // Check SBE dump collection allowed bool dumpAllowed = sbe::isDumpAllowed(procTarget); if (!dumpAllowed) { // Possibly another collection in progress, skip dump collection lg2::error("Another collection is in progress, skipping " "dump collection"); return; } } catch (const std::exception& e) { lg2::error("Exception {ERROR} occurred", "ERROR", e); return; } DumpParameters dumpParameters; dumpParameters.logId = pelId; dumpParameters.unitId = index; dumpParameters.timeout = timeout; dumpParameters.dumpType = DumpType::SBE; // will not return until dump is complete or timeout requestDump(dumpParameters); } } } // namespace dump } // namespace watchdog