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