G.4 (2h): bounded xHCI event-ring drain fixes boot-attach livelock

Root cause of the G.1 follow-up boot-time attach race: on pathological
controller behavior the xhci_poll_events() drain loop had no hard ceiling.
ERDP is written back only when the loop exits, so the controller cannot
reclaim event TRBs mid-drain; if it keeps producing events the head can
chase the software dequeue pointer forever. xhci_poll_events() never returns,
sk_repl_idle() never reaches its bot_msc_attach_pending check, and a fresh
USB BOT device that finished SET_CONFIGURATION is left flagged-but-never-
attached while the guest appears hung.

Fix: bound the drain to a full ring (XHCI_EVT_RING_MAX_DRAIN = 256), so
xhci_poll_events() always terminates and always writes ERDP each call.
Unprocessed events keep their cycle bit and are re-read next poll; nothing
is dropped. On the healthy path one drain processes only the one-or-few
events the controller posts per chained command, so the bound never triggers
except in the pathological case it breaks.

Beyond the G.1 additions: a new macro in include/starkernel/xhci.h and a
bounded loop in src/starkernel/usb/xhci.c. Builds clean on amd64. Verified
across six consecutive fresh QEMU boots (previously intermittently hung).
This commit is contained in:
Robert Allan James
2026-08-29 09:48:48 -04:00
parent 49a3faa331
commit dc2f38a1e1
5 changed files with 31 additions and 7 deletions
+5 -2
View File
@@ -1480,8 +1480,10 @@ void xhci_poll_events(void)
xhci_dev_t *dev = g_xhci_dev;
if (!dev) return;
while (((dev->evt_ring[dev->evt_ring_deq].control & XHCI_TRB_CONTROL_CYCLE) != 0)
== (dev->evt_ring_cycle != 0)) {
uint32_t evt_processed = 0;
while (evt_processed < XHCI_EVT_RING_MAX_DRAIN &&
((dev->evt_ring[dev->evt_ring_deq].control & XHCI_TRB_CONTROL_CYCLE) != 0)
== (dev->evt_ring_cycle != 0)) {
xhci_trb_t *trb = &dev->evt_ring[dev->evt_ring_deq];
uint32_t type = XHCI_TRB_TYPE(trb->control);
@@ -2060,6 +2062,7 @@ void xhci_poll_events(void)
dev->evt_ring_deq = 0;
dev->evt_ring_cycle ^= 1u;
}
evt_processed++;
}
/* Event Ring dequeue-pointer update (xHCI 1.2 spec §4.9.4): write the