>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

Reply via email to