Artemis Milestone 2d: xHCI Event Ring servicing, polled not interrupt-driven
Implements Event Ring TRB parsing and ERDP dequeue-pointer update
(xhci_poll_events(), src/starkernel/usb/xhci.c), called from
sk_repl_idle()'s existing ~1s idle cadence rather than a per-arch
interrupt handler.
A first attempt wired real interrupt delivery (PCI->IOAPIC GSI routing,
a dedicated isr_stub34/vector 0x22, GIC/PLIC routing mirroring
virtio_input.c). Checked live via QMP query-pci before trusting it: the
amd64 PIRQ swizzle formula predicted GSI 16 for the xHCI controller at
PCI slot 4; the real QEMU-assigned IRQ was 10, and embedded ICH9
functions contradicted the same formula too. Reverted all of it back to
the exact committed baseline rather than chasing chipset PIRQ routing
further, and reframed around Section U item 6's own design intent
("interrupt-driven, coarse cadence, cheap early-exit... quick check
blocks... done") via sk_repl_idle() instead -- USB insertion is a
human-timescale event, not a hot path.
Added -device qemu-xhci to all three QEMU launch targets (required for
any of this to be testable). Verified end to end via genuine post-boot
hotplug (QMP device_add/device_del usb-storage): all three architectures
detect a live attach within seconds. A false-alarm heartbeat "freeze"
found mid-verification traced to querying the wrong counter
(vm->heartbeat.tick_count, which only advances during word execution,
not the kernel's real ISR-driven heartbeat_ticks()) -- confirmed via a
temporary diagnostic word, captured and reverted.
Full writeup, including the discarded interrupt-routing attempt and the
false-alarm investigation, in FABRIC-2.md's Milestone 2c/2d entries.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HZ8kNoTuP63pbQtro4qvrm
This commit is contained in:
co-authored by
Claude Sonnet 5
parent
c2f1d94c97
commit
2b16daba16
@@ -34,6 +34,10 @@ typedef struct {
|
||||
xhci_trb_t *evt_ring; /* Event Ring, XHCI_RING_TRB_COUNT TRBs */
|
||||
void *evt_ring_seg_table; /* Event Ring Segment Table (1 entry) */
|
||||
uint32_t evt_ring_cycle; /* current Event Ring Cycle State */
|
||||
uint32_t evt_ring_deq; /* current Event Ring dequeue index */
|
||||
xhci_intr_regs_t *intr0; /* Interrupter 0 register set, cached
|
||||
* by xhci_bringup() for
|
||||
* xhci_poll_events() */
|
||||
} xhci_dev_t;
|
||||
|
||||
/*
|
||||
@@ -56,14 +60,43 @@ int xhci_find_and_map(xhci_dev_t *dev);
|
||||
* halted state.
|
||||
*
|
||||
* Must be called after a successful xhci_find_and_map(). Does not enable
|
||||
* interrupts (USBCMD.INTE / IMAN.IE) — that's wired in a later increment
|
||||
* alongside the actual interrupt handler.
|
||||
* interrupts (USBCMD.INTE / IMAN.IE) -- this driver is polled, not
|
||||
* interrupt-driven (see xhci_poll_events()'s own doc comment for why).
|
||||
*
|
||||
* Returns 0 on success.
|
||||
* Returns -1 on reset timeout.
|
||||
* Returns -2 on allocation failure.
|
||||
* Returns -3 if the controller failed to leave the halted state after RUN.
|
||||
* On success, latches dev into the module-static pointer xhci_poll_events()
|
||||
* reads -- only one controller is supported, matching virtio_blk's
|
||||
* single-device precedent.
|
||||
*/
|
||||
int xhci_bringup(xhci_dev_t *dev);
|
||||
|
||||
/*
|
||||
* xhci_poll_events — read Interrupter 0's Event Ring, dispatching each TRB
|
||||
* by type (Port Status Change, Command Completion;
|
||||
* other types logged and skipped -- Milestone 2e/2g
|
||||
* consume them), then advance the Event Ring dequeue
|
||||
* pointer and clear ERDP.EHB.
|
||||
*
|
||||
* Polled, not interrupt-driven: an initial attempt at IRQ delivery
|
||||
* (Milestone 2d's first draft) found the amd64 PCI INTx routing formula
|
||||
* gives a demonstrably wrong GSI (checked live via QMP query-pci: xHCI at
|
||||
* PCI slot 4 reports IRQ 10, the formula predicted 16), and the
|
||||
* aarch64/riscv64 slot/pin-derived source IDs were unverified at the new
|
||||
* slot this controller occupies. Rather than guess further at chipset
|
||||
* PIRQ routing, this matches Section U item 6's own design intent
|
||||
* (Captain Bob: "interrupt-driven, coarse cadence, cheap early-exit...
|
||||
* quick check blocks... done") via sk_repl_idle()'s existing coarse-cadence
|
||||
* hook instead of a per-arch IRQ path -- USB insertion is a human-timescale
|
||||
* event, not a hot path, so polling costs nothing meaningful here.
|
||||
*
|
||||
* No arguments and no return value -- only one xHCI controller is
|
||||
* supported, so the caller needs no device handle. A no-op if
|
||||
* xhci_bringup() has not completed successfully (dev pointer not yet
|
||||
* latched).
|
||||
*/
|
||||
void xhci_poll_events(void);
|
||||
|
||||
#endif /* STARKERNEL_XHCI_DRIVER_H */
|
||||
|
||||
Reference in New Issue
Block a user