xref: /openbmc/openpower-hw-diags/attn/attn_dump.cpp (revision 0c1487cb3db64d0781a7a36d78d3d810d1d79c9c)
1*0c1487cbSDhruvaraj Subhashchandran #include "config.h"
2*0c1487cbSDhruvaraj Subhashchandran 
37029e525SBen Tyner #include <attn/attn_dbus.hpp>
47029e525SBen Tyner #include <attn/attn_dump.hpp>
57029e525SBen Tyner #include <attn/attn_logging.hpp>
67029e525SBen Tyner #include <sdbusplus/bus.hpp>
77029e525SBen Tyner #include <sdbusplus/exception.hpp>
8a92dc027SDeepa Karthikeyan #include <util/dbus.hpp>
9bfa831a8Saustinfcui #include <util/trace.hpp>
107029e525SBen Tyner 
11e38a90bdSBen Tyner constexpr uint64_t dumpTimeout = 3600000000; // microseconds
12e38a90bdSBen Tyner 
13e38a90bdSBen Tyner constexpr auto operationStatusInProgress =
14e38a90bdSBen Tyner     "xyz.openbmc_project.Common.Progress.OperationStatus.InProgress";
15e38a90bdSBen Tyner 
167029e525SBen Tyner namespace attn
177029e525SBen Tyner {
187029e525SBen Tyner 
197029e525SBen Tyner /**
207029e525SBen Tyner  *  Callback for dump request properties change signal monitor
217029e525SBen Tyner  *
227029e525SBen Tyner  * @param[in] i_msg         Dbus message from the dbus match infrastructure
23e38a90bdSBen Tyner  * @param[out] o_dumpStatus Dump status dbus response string
24e38a90bdSBen Tyner  * @return Always non-zero indicating no error, no cascading callbacks
257029e525SBen Tyner  */
dumpStatusChanged(sdbusplus::message_t & i_msg,std::string & o_dumpStatus)26e212fb06SPatrick Williams uint dumpStatusChanged(sdbusplus::message_t& i_msg, std::string& o_dumpStatus)
277029e525SBen Tyner {
287029e525SBen Tyner     // reply (msg) will be a property change message
297029e525SBen Tyner     std::string interface;
307029e525SBen Tyner     std::map<std::string, std::variant<std::string, uint8_t>> property;
317029e525SBen Tyner     i_msg.read(interface, property);
327029e525SBen Tyner 
337029e525SBen Tyner     // looking for property Status changes
347029e525SBen Tyner     std::string propertyType = "Status";
357029e525SBen Tyner     auto dumpStatus = property.find(propertyType);
367029e525SBen Tyner 
377029e525SBen Tyner     if (dumpStatus != property.end())
387029e525SBen Tyner     {
397029e525SBen Tyner         const std::string* status =
407029e525SBen Tyner             std::get_if<std::string>(&(dumpStatus->second));
417029e525SBen Tyner 
42e38a90bdSBen Tyner         if (nullptr != status)
437029e525SBen Tyner         {
44e38a90bdSBen Tyner             o_dumpStatus = *status;
457029e525SBen Tyner         }
467029e525SBen Tyner     }
477029e525SBen Tyner 
487029e525SBen Tyner     return 1; // non-negative return code for successful callback
497029e525SBen Tyner }
507029e525SBen Tyner 
517029e525SBen Tyner /**
527029e525SBen Tyner  * Register a callback for dump progress status changes
537029e525SBen Tyner  *
547029e525SBen Tyner  * @param[in] i_path The object path of the dump to monitor
557029e525SBen Tyner  */
monitorDump(const std::string & i_path)567029e525SBen Tyner void monitorDump(const std::string& i_path)
577029e525SBen Tyner {
587029e525SBen Tyner     // setup the signal match rules and callback
597029e525SBen Tyner     std::string matchInterface = "xyz.openbmc_project.Common.Progress";
607029e525SBen Tyner     auto bus = sdbusplus::bus::new_system();
617029e525SBen Tyner 
62e38a90bdSBen Tyner     // monitor dump status change property, will update dumpStatus
63e38a90bdSBen Tyner     std::string dumpStatus = "requested";
647029e525SBen Tyner     std::unique_ptr<sdbusplus::bus::match_t> match =
657029e525SBen Tyner         std::make_unique<sdbusplus::bus::match_t>(
667029e525SBen Tyner             bus,
677029e525SBen Tyner             sdbusplus::bus::match::rules::propertiesChanged(
687029e525SBen Tyner                 i_path.c_str(), matchInterface.c_str()),
69e38a90bdSBen Tyner             [&](auto& msg) { return dumpStatusChanged(msg, dumpStatus); });
707029e525SBen Tyner 
717029e525SBen Tyner     // wait for dump status to be completed (complete == true)
72e38a90bdSBen Tyner     trace::inf("dump requested %s", i_path.c_str());
73e38a90bdSBen Tyner 
74e38a90bdSBen Tyner     // wait for dump status not InProgress or timeout
75e38a90bdSBen Tyner     uint64_t timeRemaining = dumpTimeout;
76e38a90bdSBen Tyner 
77e38a90bdSBen Tyner     std::chrono::steady_clock::time_point begin =
78e38a90bdSBen Tyner         std::chrono::steady_clock::now();
79e38a90bdSBen Tyner 
80e38a90bdSBen Tyner     while (("requested" == dumpStatus ||
81e38a90bdSBen Tyner             operationStatusInProgress == dumpStatus) &&
82e38a90bdSBen Tyner            0 != timeRemaining)
837029e525SBen Tyner     {
84e38a90bdSBen Tyner         bus.wait(timeRemaining);
85e38a90bdSBen Tyner         uint64_t timeElapsed =
86e38a90bdSBen Tyner             std::chrono::duration_cast<std::chrono::microseconds>(
87e38a90bdSBen Tyner                 std::chrono::steady_clock::now() - begin)
88e38a90bdSBen Tyner                 .count();
89e38a90bdSBen Tyner 
90e38a90bdSBen Tyner         timeRemaining =
91e38a90bdSBen Tyner             timeElapsed > timeRemaining ? 0 : timeRemaining - timeElapsed;
92e38a90bdSBen Tyner 
937029e525SBen Tyner         bus.process_discard();
947029e525SBen Tyner     }
95e38a90bdSBen Tyner 
96e38a90bdSBen Tyner     if (0 == timeRemaining)
97e38a90bdSBen Tyner     {
98e38a90bdSBen Tyner         trace::err("dump request timed out after %" PRIu64 " microseconds",
99e38a90bdSBen Tyner                    dumpTimeout);
100e38a90bdSBen Tyner     }
101e38a90bdSBen Tyner 
102e38a90bdSBen Tyner     trace::inf("dump status: %s", dumpStatus.c_str());
1037029e525SBen Tyner }
1047029e525SBen Tyner 
105a92dc027SDeepa Karthikeyan /** Api used to enable or disable watchdog dbus property */
enableWatchdog(bool enable)106a92dc027SDeepa Karthikeyan void enableWatchdog(bool enable)
107a92dc027SDeepa Karthikeyan {
108a92dc027SDeepa Karthikeyan     constexpr auto service = "xyz.openbmc_project.Watchdog";
109a92dc027SDeepa Karthikeyan     constexpr auto object = "/xyz/openbmc_project/watchdog/host0";
110a92dc027SDeepa Karthikeyan     constexpr auto interface = "xyz.openbmc_project.State.Watchdog";
111a92dc027SDeepa Karthikeyan     constexpr auto property = "Enabled";
112a92dc027SDeepa Karthikeyan     util::dbus::setProperty<bool>(service, object, interface, property, enable);
113a92dc027SDeepa Karthikeyan }
114a92dc027SDeepa Karthikeyan 
1157029e525SBen Tyner /** Request a dump from the dump manager */
requestDump(uint32_t i_logId,const DumpParameters & i_dumpParameters)116611b3442SZane Shelley void requestDump(uint32_t i_logId, const DumpParameters& i_dumpParameters)
1177029e525SBen Tyner {
1187029e525SBen Tyner     constexpr auto interface = "xyz.openbmc_project.Dump.Create";
1197029e525SBen Tyner     constexpr auto function = "CreateDump";
1207029e525SBen Tyner 
121e212fb06SPatrick Williams     sdbusplus::message_t method;
122a92dc027SDeepa Karthikeyan     bool watchdogDisabled = false;
1237029e525SBen Tyner 
124*0c1487cbSDhruvaraj Subhashchandran     if (0 == dbusMethod(OP_DUMP_OBJ_PATH, interface, function, method))
1257029e525SBen Tyner     {
1267029e525SBen Tyner         try
1277029e525SBen Tyner         {
128a92dc027SDeepa Karthikeyan             // During a checkstop attention, the system is not functioning
129a92dc027SDeepa Karthikeyan             // normally. So a hardware or hostboot dump is collected and it
130a92dc027SDeepa Karthikeyan             // could take a while to get completed. So disable the watchdog when
131a92dc027SDeepa Karthikeyan             // the dump collection is in progress.
132a92dc027SDeepa Karthikeyan             if (DumpType::Hostboot == i_dumpParameters.dumpType ||
133a92dc027SDeepa Karthikeyan                 DumpType::Hardware == i_dumpParameters.dumpType)
134a92dc027SDeepa Karthikeyan             {
135a92dc027SDeepa Karthikeyan                 watchdogDisabled = true;
136a92dc027SDeepa Karthikeyan                 enableWatchdog(false);
137a92dc027SDeepa Karthikeyan             }
1387029e525SBen Tyner             // dbus call arguments
1397029e525SBen Tyner             std::map<std::string, std::variant<std::string, uint64_t>>
1407029e525SBen Tyner                 createParams;
1417029e525SBen Tyner             createParams["com.ibm.Dump.Create.CreateParameters.ErrorLogId"] =
142611b3442SZane Shelley                 uint64_t(i_logId);
1437029e525SBen Tyner             if (DumpType::Hostboot == i_dumpParameters.dumpType)
1447029e525SBen Tyner             {
1457029e525SBen Tyner                 createParams["com.ibm.Dump.Create.CreateParameters.DumpType"] =
1467029e525SBen Tyner                     "com.ibm.Dump.Create.DumpType.Hostboot";
1477029e525SBen Tyner             }
1487029e525SBen Tyner             else if (DumpType::Hardware == i_dumpParameters.dumpType)
1497029e525SBen Tyner             {
1507029e525SBen Tyner                 createParams["com.ibm.Dump.Create.CreateParameters.DumpType"] =
1517029e525SBen Tyner                     "com.ibm.Dump.Create.DumpType.Hardware";
1527029e525SBen Tyner                 createParams
1537029e525SBen Tyner                     ["com.ibm.Dump.Create.CreateParameters.FailingUnitId"] =
1547029e525SBen Tyner                         i_dumpParameters.unitId;
1557029e525SBen Tyner             }
1567f6ce6acSBen Tyner             else if (DumpType::SBE == i_dumpParameters.dumpType)
1577f6ce6acSBen Tyner             {
1587f6ce6acSBen Tyner                 createParams["com.ibm.Dump.Create.CreateParameters.DumpType"] =
1597f6ce6acSBen Tyner                     "com.ibm.Dump.Create.DumpType.SBE";
1607f6ce6acSBen Tyner                 createParams
1617f6ce6acSBen Tyner                     ["com.ibm.Dump.Create.CreateParameters.FailingUnitId"] =
1627f6ce6acSBen Tyner                         i_dumpParameters.unitId;
1637f6ce6acSBen Tyner             }
1647029e525SBen Tyner             method.append(createParams);
1657029e525SBen Tyner 
1667029e525SBen Tyner             // using system dbus
1677029e525SBen Tyner             auto bus = sdbusplus::bus::new_system();
1687029e525SBen Tyner             auto response = bus.call(method);
1697029e525SBen Tyner 
1707029e525SBen Tyner             // reply will be type dbus::ObjectPath
1717029e525SBen Tyner             sdbusplus::message::object_path reply;
1727029e525SBen Tyner             response.read(reply);
1737029e525SBen Tyner 
1747029e525SBen Tyner             // monitor dump progress
1757029e525SBen Tyner             monitorDump(reply);
1767029e525SBen Tyner         }
1777029e525SBen Tyner         catch (const sdbusplus::exception::SdBusError& e)
1787029e525SBen Tyner         {
179bfa831a8Saustinfcui             trace::err("requestDump exception");
180bfa831a8Saustinfcui             trace::err(e.what());
1817029e525SBen Tyner         }
182a92dc027SDeepa Karthikeyan 
183a92dc027SDeepa Karthikeyan         if (watchdogDisabled)
184a92dc027SDeepa Karthikeyan         {
185a92dc027SDeepa Karthikeyan             // Dump collection is over, enable the watchdog
186a92dc027SDeepa Karthikeyan             enableWatchdog(true);
187a92dc027SDeepa Karthikeyan         }
1887029e525SBen Tyner     }
1897029e525SBen Tyner }
1907029e525SBen Tyner 
1917029e525SBen Tyner } // namespace attn
192