142506393SWilliam A. Kennington III #pragma once 242506393SWilliam A. Kennington III 342506393SWilliam A. Kennington III #include <sdbusplus/bus.hpp> 442506393SWilliam A. Kennington III #include <sdbusplus/server/object.hpp> 542506393SWilliam A. Kennington III #include <sdeventplus/event.hpp> 642506393SWilliam A. Kennington III #include <sdeventplus/utility/timer.hpp> 76ac6a347SPatrick Williams #include <xyz/openbmc_project/State/Watchdog/server.hpp> 86ac6a347SPatrick Williams 96ac6a347SPatrick Williams #include <functional> 106ac6a347SPatrick Williams #include <optional> 119ef0d0fbSWilly Tu #include <string_view> 1242506393SWilliam A. Kennington III #include <unordered_map> 1342506393SWilliam A. Kennington III #include <utility> 1442506393SWilliam A. Kennington III 1542506393SWilliam A. Kennington III namespace phosphor 1642506393SWilliam A. Kennington III { 1742506393SWilliam A. Kennington III namespace watchdog 1842506393SWilliam A. Kennington III { 1942506393SWilliam A. Kennington III 2042506393SWilliam A. Kennington III constexpr auto DEFAULT_MIN_INTERVAL_MS = 0; 2142506393SWilliam A. Kennington III namespace Base = sdbusplus::xyz::openbmc_project::State::server; 2273bd5277SPatrick Williams using WatchdogInherits = sdbusplus::server::object_t<Base::Watchdog>; 2342506393SWilliam A. Kennington III 2442506393SWilliam A. Kennington III /** @class Watchdog 2542506393SWilliam A. Kennington III * @brief OpenBMC watchdog implementation. 2642506393SWilliam A. Kennington III * @details A concrete implementation for the 2742506393SWilliam A. Kennington III * xyz.openbmc_project.State.Watchdog DBus API. 2842506393SWilliam A. Kennington III */ 2942506393SWilliam A. Kennington III class Watchdog : public WatchdogInherits 3042506393SWilliam A. Kennington III { 3142506393SWilliam A. Kennington III public: 3242506393SWilliam A. Kennington III Watchdog() = delete; 3342506393SWilliam A. Kennington III ~Watchdog() = default; 3442506393SWilliam A. Kennington III Watchdog(const Watchdog&) = delete; 3542506393SWilliam A. Kennington III Watchdog& operator=(const Watchdog&) = delete; 3642506393SWilliam A. Kennington III Watchdog(Watchdog&&) = delete; 3742506393SWilliam A. Kennington III Watchdog& operator=(Watchdog&&) = delete; 3842506393SWilliam A. Kennington III 3942506393SWilliam A. Kennington III /** @brief Type used to hold the name of a systemd target. 4042506393SWilliam A. Kennington III */ 4142506393SWilliam A. Kennington III using TargetName = std::string; 4242506393SWilliam A. Kennington III 4342506393SWilliam A. Kennington III /** @brief Type used to store the mapping of a Watchdog timeout 4442506393SWilliam A. Kennington III * action to a systemd target. 4542506393SWilliam A. Kennington III */ 4642506393SWilliam A. Kennington III using ActionTargetMap = std::unordered_map<Action, TargetName>; 4742506393SWilliam A. Kennington III 4842506393SWilliam A. Kennington III /** @brief Type used to specify the parameters of a fallback watchdog 4942506393SWilliam A. Kennington III */ 5042506393SWilliam A. Kennington III struct Fallback 5142506393SWilliam A. Kennington III { 5242506393SWilliam A. Kennington III Action action; 5342506393SWilliam A. Kennington III uint64_t interval; 5442506393SWilliam A. Kennington III bool always; 5542506393SWilliam A. Kennington III }; 5642506393SWilliam A. Kennington III 5742506393SWilliam A. Kennington III /** @brief Constructs the Watchdog object 5842506393SWilliam A. Kennington III * 5942506393SWilliam A. Kennington III * @param[in] bus - DBus bus to attach to. 6042506393SWilliam A. Kennington III * @param[in] objPath - Object path to attach to. 6142506393SWilliam A. Kennington III * @param[in] event - reference to sdeventplus::Event loop 6242506393SWilliam A. Kennington III * @param[in] actionTargets - map of systemd targets called on timeout 63afc369adSAndrew Geissler * @param[in] fallback - fallback watchdog 64afc369adSAndrew Geissler * @param[in] minInterval - minimum intervale value allowed 65afc369adSAndrew Geissler * @param[in] defaultInterval - default interval to start with 66d1b1e79bSWilliam A. Kennington III * @param[in] exitAfterTimeout - should the event loop be terminated 6742506393SWilliam A. Kennington III */ Watchdog(sdbusplus::bus_t & bus,const char * objPath,const sdeventplus::Event & event,ActionTargetMap && actionTargetMap={},std::optional<Fallback> && fallback=std::nullopt,uint64_t minInterval=DEFAULT_MIN_INTERVAL_MS,uint64_t defaultInterval=0,bool exitAfterTimeout=false)6873bd5277SPatrick Williams Watchdog(sdbusplus::bus_t& bus, const char* objPath, 6942506393SWilliam A. Kennington III const sdeventplus::Event& event, 7042506393SWilliam A. Kennington III ActionTargetMap&& actionTargetMap = {}, 7142506393SWilliam A. Kennington III std::optional<Fallback>&& fallback = std::nullopt, 72afc369adSAndrew Geissler uint64_t minInterval = DEFAULT_MIN_INTERVAL_MS, 73d1b1e79bSWilliam A. Kennington III uint64_t defaultInterval = 0, bool exitAfterTimeout = false) : 74*923a9080SPatrick Williams WatchdogInherits(bus, objPath), bus(bus), 75*923a9080SPatrick Williams actionTargetMap(std::move(actionTargetMap)), fallback(fallback), 76*923a9080SPatrick Williams minInterval(minInterval), 779ef0d0fbSWilly Tu timer(event, std::bind(&Watchdog::timeOutHandler, this)), 78d1b1e79bSWilliam A. Kennington III objPath(objPath), exitAfterTimeout(exitAfterTimeout) 7942506393SWilliam A. Kennington III { 80afc369adSAndrew Geissler // Use default if passed in otherwise just use default that comes 81afc369adSAndrew Geissler // with object 82afc369adSAndrew Geissler if (defaultInterval) 83afc369adSAndrew Geissler { 84afc369adSAndrew Geissler interval(defaultInterval); 85afc369adSAndrew Geissler } 86afc369adSAndrew Geissler else 87afc369adSAndrew Geissler { 8842506393SWilliam A. Kennington III interval(interval()); 89afc369adSAndrew Geissler } 9042506393SWilliam A. Kennington III // We need to poke the enable mechanism to make sure that the timer 9142506393SWilliam A. Kennington III // enters the fallback state if the fallback is always enabled. 9242506393SWilliam A. Kennington III tryFallbackOrDisable(); 9342506393SWilliam A. Kennington III } 9442506393SWilliam A. Kennington III 9542506393SWilliam A. Kennington III /** @brief Resets the TimeRemaining to the configured Interval 9642506393SWilliam A. Kennington III * Optionally enables the watchdog. 9742506393SWilliam A. Kennington III * 9842506393SWilliam A. Kennington III * @param[in] enableWatchdog - Should the call enable the watchdog 9942506393SWilliam A. Kennington III */ 10042506393SWilliam A. Kennington III void resetTimeRemaining(bool enableWatchdog) override; 10142506393SWilliam A. Kennington III 10242506393SWilliam A. Kennington III /** @brief Since we are overriding the setter-enabled but not the 10342506393SWilliam A. Kennington III * getter-enabled, we need to have this using in order to 10442506393SWilliam A. Kennington III * allow passthrough usage of the getter-enabled. 10542506393SWilliam A. Kennington III */ 10642506393SWilliam A. Kennington III using Base::Watchdog::enabled; 10742506393SWilliam A. Kennington III 10842506393SWilliam A. Kennington III /** @brief Enable or disable watchdog 10942506393SWilliam A. Kennington III * If a watchdog state is changed from disable to enable, 11042506393SWilliam A. Kennington III * the watchdog timer is set with the default expiration 11142506393SWilliam A. Kennington III * interval and it starts counting down. 11242506393SWilliam A. Kennington III * If a watchdog is already enabled, setting @value to true 11342506393SWilliam A. Kennington III * has no effect. 11442506393SWilliam A. Kennington III * 11542506393SWilliam A. Kennington III * @param[in] value - 'true' to enable. 'false' to disable 11642506393SWilliam A. Kennington III * 11742506393SWilliam A. Kennington III * @return : applied value if success, previous value otherwise 11842506393SWilliam A. Kennington III */ 11942506393SWilliam A. Kennington III bool enabled(bool value) override; 12042506393SWilliam A. Kennington III 12142506393SWilliam A. Kennington III /** @brief Gets the remaining time before watchdog expires. 12242506393SWilliam A. Kennington III * 12342506393SWilliam A. Kennington III * @return 0 if watchdog is expired. 12442506393SWilliam A. Kennington III * Remaining time in milliseconds otherwise. 12542506393SWilliam A. Kennington III */ 12642506393SWilliam A. Kennington III uint64_t timeRemaining() const override; 12742506393SWilliam A. Kennington III 12842506393SWilliam A. Kennington III /** @brief Reset timer to expire after new timeout in milliseconds. 12942506393SWilliam A. Kennington III * 13042506393SWilliam A. Kennington III * @param[in] value - the time in milliseconds after which 13142506393SWilliam A. Kennington III * the watchdog will expire 13242506393SWilliam A. Kennington III * 13342506393SWilliam A. Kennington III * @return: updated timeout value if watchdog is enabled. 13442506393SWilliam A. Kennington III * 0 otherwise. 13542506393SWilliam A. Kennington III */ 13642506393SWilliam A. Kennington III uint64_t timeRemaining(uint64_t value) override; 13742506393SWilliam A. Kennington III 13842506393SWilliam A. Kennington III /** @brief Get value of Interval 13942506393SWilliam A. Kennington III * 14042506393SWilliam A. Kennington III * 14142506393SWilliam A. Kennington III * @return: current interval 14242506393SWilliam A. Kennington III * 14342506393SWilliam A. Kennington III */ 14442506393SWilliam A. Kennington III using WatchdogInherits::interval; 14542506393SWilliam A. Kennington III 14642506393SWilliam A. Kennington III /** @brief Set value of Interval 14742506393SWilliam A. Kennington III * 14842506393SWilliam A. Kennington III * @param[in] value - interval time to set 14942506393SWilliam A. Kennington III * 15042506393SWilliam A. Kennington III * @return: interval that was set 15142506393SWilliam A. Kennington III * 15242506393SWilliam A. Kennington III */ 153cf4ce3c1SWilly Tu uint64_t interval(uint64_t value) override; 15442506393SWilliam A. Kennington III 15542506393SWilliam A. Kennington III /** @brief Tells if the referenced timer is expired or not */ timerExpired() const15642506393SWilliam A. Kennington III inline auto timerExpired() const 15742506393SWilliam A. Kennington III { 15842506393SWilliam A. Kennington III return timer.hasExpired(); 15942506393SWilliam A. Kennington III } 16042506393SWilliam A. Kennington III 16142506393SWilliam A. Kennington III /** @brief Tells if the timer is running or not */ timerEnabled() const16242506393SWilliam A. Kennington III inline bool timerEnabled() const 16342506393SWilliam A. Kennington III { 16442506393SWilliam A. Kennington III return timer.isEnabled(); 16542506393SWilliam A. Kennington III } 16642506393SWilliam A. Kennington III 16742506393SWilliam A. Kennington III private: 16842506393SWilliam A. Kennington III /** @brief sdbusplus handle */ 16973bd5277SPatrick Williams sdbusplus::bus_t& bus; 17042506393SWilliam A. Kennington III 17142506393SWilliam A. Kennington III /** @brief Map of systemd units to be started when the timer expires */ 17242506393SWilliam A. Kennington III ActionTargetMap actionTargetMap; 17342506393SWilliam A. Kennington III 17442506393SWilliam A. Kennington III /** @brief Fallback timer options */ 17542506393SWilliam A. Kennington III std::optional<Fallback> fallback; 17642506393SWilliam A. Kennington III 17742506393SWilliam A. Kennington III /** @brief Minimum watchdog interval value */ 17842506393SWilliam A. Kennington III uint64_t minInterval; 17942506393SWilliam A. Kennington III 18042506393SWilliam A. Kennington III /** @brief Contained timer object */ 18142506393SWilliam A. Kennington III sdeventplus::utility::Timer<sdeventplus::ClockId::Monotonic> timer; 18242506393SWilliam A. Kennington III 18342506393SWilliam A. Kennington III /** @brief Optional Callback handler on timer expirartion */ 18442506393SWilliam A. Kennington III void timeOutHandler(); 18542506393SWilliam A. Kennington III 18642506393SWilliam A. Kennington III /** @brief Attempt to enter the fallback watchdog or disables it */ 18742506393SWilliam A. Kennington III void tryFallbackOrDisable(); 1889ef0d0fbSWilly Tu 1899ef0d0fbSWilly Tu /** @brief Object path of the watchdog */ 1909ef0d0fbSWilly Tu std::string_view objPath; 191d1b1e79bSWilliam A. Kennington III 192d1b1e79bSWilliam A. Kennington III /** @brief Do we terminate after exit */ 193d1b1e79bSWilliam A. Kennington III bool exitAfterTimeout; 19442506393SWilliam A. Kennington III }; 19542506393SWilliam A. Kennington III 19642506393SWilliam A. Kennington III } // namespace watchdog 19742506393SWilliam A. Kennington III } // namespace phosphor 198