>From [email protected] Fri Jun 13 2026From: Suresh Marisetty
><[email protected]>Date: Fri, 13 Jun 2026 18:00:03 -0700Subject: [PATCH
>3/3] hw/ipmi: Accept any extern BMC msg_id to fix SMM firmware deadlockTo:
>[email protected]: Corey Minyard <[email protected]>, Peter Maydell
><[email protected]>, Philippe Mathieu-Daude <[email protected]>,
>Michael S. Tsirkin <[email protected]>Message-Id:
><[email protected]>In-Reply-To:
><[email protected]>References:
><[email protected]>MIME-Version: 1.0Content-Type:
>text/plain; charset=UTF-8 ipmi_bt_handle_rsp() accepts a response from the
>extern BMC only when: ib->waiting_rsp == msg_id || msg_id == 0xFF This
>strict msg_id matching cannot be satisfied by firmware that sendsIPMI BT
>commands from System Management Mode (SMM). Root cause — SMM and the QEMU main
>loop are mutually exclusive: When a guest vCPU enters SMM, the vCPU thread
>holds the Big QEMU Lock(BQL) for the duration of the SMM handler. The
>ipmi-bmc-extern chardevreceive callback (ipmi_bmc_extern_receive) runs in the
>QEMU main eventloop, which cannot execute while the BQL is held. Consequently,
>any ACKsent by the extern BMC in response to an IPMI BT command issued fromSMM
>can only be received and processed by QEMU *after* the SMM handlerhas exited
>and released the BQL. This creates an unresolvable deadlock if SMM firmware
>polls for B_BUSYto clear after sending a BT frame: the firmware waits inside
>SMM forB_BUSY to deassert, but QEMU cannot process the extern BMC ACK
>(whichwould deassert B_BUSY) until SMM exits. SMM never exits because it
>iswaiting for B_BUSY. Secondary cause — sequence counter divergence between
>DXE and SMM: UEFI platforms typically have multiple firmware modules sharing
>the sameIPMI BT interface: DXE-phase drivers (e.g. TFLiteDxe) and SMM
>handlers(e.g. TrustForgeSmmDxe) each have independent instances of the
>BTlibrary with independent msg_id counters starting from 0. DXE sendsframes
>with msg_id=0,1,... advancing QEMU's waiting_rsp counter. WhenSMM subsequently
>sends frames starting from msg_id=0 or a differentbase, the msg_id values no
>longer match waiting_rsp, and all SMM ACKsare silently dropped. B_BUSY remains
>set permanently. Correct design for SMM BT usage: Firmware that sends IPMI BT
>from SMM must use a "fire-and-forget"pattern: write the BT frame, assert
>H2B_ATN, and return from SMMimmediately without polling for B_BUSY or B2H_ATN.
>QEMU then processesthe frame after SMM exits, the extern BMC sends an ACK, and
>QEMU clearsB_BUSY. The next SMI entry can drain the pending ACK from the BT
>FIFObefore sending the next frame. This pattern requires QEMU to accept
>theextern BMC ACK regardless of msg_id. Fix: Remove the waiting_rsp == msg_id
>check. Accept any response from theextern BMC unconditionally. waiting_rsp
>continues to increment so thatthe outgoing BT sequence presented to the guest
>firmware (via theGET_BT_INTERFACE_CAPABILITIES "outstanding requests" field)
>remainsconsistent. The existing msg_id == 0xFF special case for the extern
>init timeout issubsumed by this change. This bug affects any QEMU version
>where firmware sends IPMI BT commandsfrom SMM, including all versions through
>10.0.0. Reported-by: Suresh Marisetty <[email protected]>Signed-off-by:
>Suresh Marisetty <[email protected]>--- hw/ipmi/ipmi_bt.c | 12 +++++++++---
>1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/hw/ipmi/ipmi_bt.c
>b/hw/ipmi/ipmi_bt.cindex c3f7e25a91..8b4d2e7f03 100644---
>a/hw/ipmi/ipmi_bt.c+++ b/hw/ipmi/ipmi_bt.c@@ -152,9 +152,15 @@ static void
>ipmi_bt_handle_rsp(IPMIInterface *ii, uint8_t msg_id, IPMIInterfaceClass
>*iic = IPMI_INTERFACE_GET_CLASS(ii); IPMIBT *ib =
>iic->get_backend_data(ii); - if (ib->waiting_rsp == msg_id || msg_id ==
>0xFF) { /* 0xFF = extern init timeout */- ib->waiting_rsp++;-
>if (rsp_len > (sizeof(ib->outmsg) - 2)) {+ /*+ * Accept any msg_id from
>the extern BMC unconditionally.+ *+ * SMM firmware cannot guarantee
>msg_id matches waiting_rsp: the QEMU+ * main loop is paused while the vCPU
>executes SMM (BQL held), so the+ * extern chardev receive callback only
>runs after SMM exits. Firmware+ * using fire-and-forget BT sends from SMM
>has independent msg_id+ * counters (per DXE/SMM module instance) that
>diverge from+ * waiting_rsp, causing all SMM responses to be silently
>dropped.+ *+ * waiting_rsp increments unconditionally to maintain BT
>sequencing.+ */+ (void)msg_id;+ {+ ib->waiting_rsp++;+
>if (rsp_len > (sizeof(ib->outmsg) - 2)) {--2.39.0