Lines Matching +full:host +full:- +full:ipmid

1 // SPDX-License-Identifier: Apache-2.0
7 #include <ipmid/api.h>
10 #include <systemd/sd-bus.h>
11 #include <systemd/sd-event.h>
13 #include <ipmid-host/cmd-utils.hpp>
14 #include <ipmid-host/cmd.hpp>
15 #include <ipmid/api.hpp>
16 #include <phosphor-logging/log.hpp>
37 The primary motivation of the Host I/O Mapping protocol (HIOMAP) is to mediate
38 host access to a BMC-controlled flash chip housing the host's boot firmware.
40 openpower-host-ipmi-flash facilitates the system design of transporting the
43 BMC and the host.
47 Using IPMI in this way has a number of challenges, a lot of them on the host
53 BMC-side System Design and Integration Issues
54 ---------------------------------------------
59 DBus interface to receive messages from ipmid. ipmid in-turn knows nothing of
61 from interface-specific daemons, e.g. btbridged[2].
70 start-up *and* shutdown order, in stack push / pop order respectively.
71 2. Clearly ipmid depends on btbridged to receive messages sent by signals and
74 3. mboxd depends on ipmid to receive messages sent by method call, and issues a
77 Point 3. suggests mboxd should have a Wants=/Before= relationship with ipmid to
78 ensure ipmid can call into mboxd as messages arrive. However, this causes some
79 grief with shutdown of the BMC, as mboxd needs to issue a state-change
80 notification when it is shut down to inform the host that will not respond to
82 Wants=/Before= relationship with ipmid this message will never propagate to the
83 host, as ipmid will be shut by systemd before mboxd.
85 The above leads to mboxd having a Wants=/After= relationship with ipmid. This
87 propagated to the host. The case where ipmid attempts to call into mboxd's DBus
89 BMC status, which will not yet be set, preventing a conforming host from
92 While this ordering prevents mboxd from being terminated before ipmid, there is
94 signal emitted by mboxd before mboxd is terminated is seen by ipmid before
95 *ipmid* is also terminated. This leads to our first implementation wart:
97 On the basis that mboxd has a Wants=/After= relationship with ipmid,
98 openpower-host-ipmi-flash will emit an HIOMAP BMC status event to the host
102 If ipmid has received SIGTERM the assumption is that it is systemd that is
104 been terminated before ipmid receives SIGTERM. By ensuring
105 openpower-host-ipmi-flash emits the BMC event state we close the race where the
106 host is not informed of the termination of mboxd due to scheduling ipmid (to
107 deliver SIGTERM) prior to scheduling dbus-daemon, where the PropertiesChanged
108 event would be delivered from mboxd to ipmid.
110 Observations on the IPMI Specification and Design Details of ipmid
111 ------------------------------------------------------------------
113 In addition to the system-level design problems with delivering
114 PropertiesChanged signals during shutdown, IPMI specification and ipmid design
116 delivered to the host.
119 change events from mboxd to the host over IPMI uses the SMS ATN bit to indicate
120 a message is ready for delivery from the BMC to the host system. Retrieving the
121 BMC state data involves the host recognising that the SMS ATN bit is set,
128 ipmid can win the race against SIGTERM to receive the PropertiesChanged event
129 from mboxd, but lose the race to complete delivery to the host.
131 On this basis, we need to block the delivery of SIGTERM to ipmid until ipmid
133 transactions with the host
141 The existing design of ipmid makes it feasible to block and unblock
144 phosphor::host::command::Manager::getNextCommand(). The documentation for
145 phosphor::host::command::Manager::getNextCommand() says:
153 passed to the host (which is required when calling this)
156 host
159 invoked when ipmid *dequeues* the data to send to the host: Delivery of the
160 data to the host occurs at some *after* the callback has been invoked.
162 Invoking the callback before completion of delivery of the data to the host
164 associated with sending the HIOMAP BMC state event to the host, as the BMC
166 invoked and the host receiving the BMC state event data.
168 Overcoming this issue hinges on a significant implementation detail of ipmid:
170 ipmid uses an sd_event loop in the main function to pump DBus events.
177 The fact that sd_event is used to pump DBus events means that ipmid can remain
178 a single-threaded process. By remaining single-threaded we know that events
188 ------------------------------------------------------
197 BMC_EVENT_PROTOCOL_RESET state to the host if necessary, otherwise terminate
199 4. If it is necessary to send BMC_EVENT_PROTOCOL_RESET to the host in 3, assign
206 1. The scheduler race between mboxd, dbus-daemon and ipmid, by having
207 openpower-host-ipmi-flash conditionally deliver the protocol reset event if
209 2. The race between delivering the BMC status event to the host and ipmid
212 3. The race to deliver the BMC status data to the host after unblocking
213 asynchronous SIGTERM in the host command callback and before receiving
216 Ultimately, ipmid could benefit from a redesign that fires the callback *after*
217 delivering the associated data to the host, but brief inspection determined
218 that this involved a non-trivial amount of effort.
223 using namespace phosphor::host::command;
245 /* XXX: ipmid is currently single-threaded, pumping dbus events in sequence
246 * via the main event loop. Thus the code is not forced to be re-entrant. We
299 {ETIMEDOUT, 0xc3}, /* FIXME: Replace when defined in ipmid-api.h */
300 {ENOSPC, 0xc4}, /* FIXME: Replace when defined in ipmid-api.h */
305 {-1, IPMI_CC_UNSPECIFIED_ERROR},
312 while (!(entry->err == err || entry->err == -1)) in hiomap_xlate_errno()
317 return entry->cc; in hiomap_xlate_errno()
326 log<level::ERR>("Failed to deliver host command", in ipmi_hiomap_event_response()
331 active_event_updates--; in ipmi_hiomap_event_response()
359 if (!ctx->event_lookup.count(x.first)) in hiomap_handle_property_update()
365 uint8_t mask = ctx->event_lookup[x.first]; in hiomap_handle_property_update()
370 ctx->bmc_events |= mask; in hiomap_handle_property_update()
374 ctx->bmc_events &= ~mask; in hiomap_handle_property_update()
378 auto cmd = std::make_pair(IPMI_CMD_HIOMAP_EVENT, ctx->bmc_events); in hiomap_handle_property_update()
388 // If this is running in signal context, ipmid will shutdown in hiomap_protocol_reset_response()
396 if (ctx->bmc_events == BMC_EVENT_PROTOCOL_RESET) in hiomap_protocol_reset()
398 // If this is running in signal context, ipmid will shutdown in hiomap_protocol_reset()
407 * (BMC_EVENT_PROTOCOL_RESET set) to indicate to the host that it needs to in hiomap_protocol_reset()
411 * openpower-host-ipmi-flash, as hiomapd's unit depends on in hiomap_protocol_reset()
412 * phosphor-ipmi-host, and thus hiomapd has been terminated before ipmid in hiomap_protocol_reset()
429 *ctx->bus, properties, in hiomap_match_properties()
441 auto m = ctx->bus->new_method_call(HIOMAPD_SERVICE, HIOMAPD_OBJECT, in hiomap_reset()
445 ctx->bus->call(m); in hiomap_reset()
469 auto m = ctx->bus->new_method_call(HIOMAPD_SERVICE, HIOMAPD_OBJECT, in hiomap_get_info()
475 auto reply = ctx->bus->call(m); in hiomap_get_info()
505 auto m = ctx->bus->new_method_call(HIOMAPD_SERVICE, HIOMAPD_OBJECT, in hiomap_get_flash_info()
509 auto reply = ctx->bus->call(m); in hiomap_get_flash_info()
540 auto m = ctx->bus->new_method_call(HIOMAPD_SERVICE, HIOMAPD_OBJECT, in hiomap_create_window()
547 auto reply = ctx->bus->call(m); in hiomap_create_window()
599 auto m = ctx->bus->new_method_call(HIOMAPD_SERVICE, HIOMAPD_OBJECT, in hiomap_close_window()
605 auto reply = ctx->bus->call(m); in hiomap_close_window()
629 auto m = ctx->bus->new_method_call(HIOMAPD_SERVICE, HIOMAPD_OBJECT, in hiomap_mark_dirty()
637 auto reply = ctx->bus->call(m); in hiomap_mark_dirty()
655 auto m = ctx->bus->new_method_call(HIOMAPD_SERVICE, HIOMAPD_OBJECT, in hiomap_flush()
661 auto reply = ctx->bus->call(m); in hiomap_flush()
685 auto m = ctx->bus->new_method_call(HIOMAPD_SERVICE, HIOMAPD_OBJECT, in hiomap_ack()
692 auto reply = ctx->bus->call(m); in hiomap_ack()
716 auto m = ctx->bus->new_method_call(HIOMAPD_SERVICE, HIOMAPD_OBJECT, in hiomap_erase()
724 auto reply = ctx->bus->call(m); in hiomap_erase()
782 if (hiomap_cmd == 0 || hiomap_cmd > hiomap_commands.size() - 1) in hiomap_dispatch()
791 if (!is_unversioned && ctx->seq == ipmi_req[1]) in hiomap_dispatch()
797 ctx->seq = ipmi_req[1]; in hiomap_dispatch()
800 size_t flash_len = *data_len - 2; in hiomap_dispatch()
809 ipmi_ret_t cc = command->second(flash_req, flash_resp, &flash_len, context); in hiomap_dispatch()
818 ipmi_resp[1] = ctx->seq; in hiomap_dispatch()
835 ctx->event_lookup["DaemonReady"] = BMC_EVENT_DAEMON_READY; in register_openpower_hiomap_commands()
836 ctx->event_lookup["FlashControlLost"] = BMC_EVENT_FLASH_CTRL_LOST; in register_openpower_hiomap_commands()
837 ctx->event_lookup["WindowReset"] = BMC_EVENT_WINDOW_RESET; in register_openpower_hiomap_commands()
838 ctx->event_lookup["ProtocolReset"] = BMC_EVENT_PROTOCOL_RESET; in register_openpower_hiomap_commands()
840 ctx->bus = new bus_t(ipmid_get_sd_bus_connection()); in register_openpower_hiomap_commands()
848 ctx->properties = new bus::match_t(std::move(hiomap_match_properties(ctx))); in register_openpower_hiomap_commands()