Artemis Milestone 2e: real connect drives Enable Slot, slot ID correlated
xhci_poll_events()'s Port Status Change connect branch now calls xhci_cmd_enable_slot() directly (the earlier boot-time smoke test call is gone), tracked via a new dev->pending_connect_port_id -- since this driver only ever has one command outstanding at a time, that alone identifies which port a later Command Completion Event answers, without needing to match the Command TRB Pointer yet. On success the returned Slot ID is recorded in a new dev->port_slot_id[], a fixed uint32_t[XHCI_MAX_TRACKED_PORTS] (32) indexed by port. Disconnect clears the port's tracked slot (real teardown -- Disable Slot, DCBAA clear, Section U callback -- is still a later increment). Fixed array, not heap-allocated: a first attempt sized port_slot_id dynamically via kmalloc_aligned(dev->max_ports * sizeof(uint32_t), 64) inside xhci_bringup() and it crashed amd64 with a page fault (IFETCH at RIP=CR2=0xA0000, the legacy VGA hole) during the unrelated Mama-VM-birth phase afterward -- a heap-corruption signature, not chased to root cause. Switching to a fixed array (matching this driver's existing preference for fixed over dynamic allocation) made the crash go away; the crashing boot's log is kept (logs/20260822-102516/) as the evidence trail. Verified live via QMP hotplug, all three architectures: connect -> "enable slot command submitted" -> "enable slot succeeded", with a disconnect/reconnect cycle repeating cleanly and no port wedge. 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
dd043bbfeb
commit
6d330efdd8
+37
-7
@@ -3207,8 +3207,9 @@ Final three-arch acceptance (probe-free, `clean qemu`): all three boot to `ok>`
|
||||
**2e. Hotplug detection (the actual trigger for everything in Section U)**
|
||||
- [x] On a Port Status Change event, read the corresponding Port Register to determine
|
||||
connect vs. disconnect — **done 2026-08-22**, see writeup below
|
||||
- [ ] On connect: allocate a Device Slot (Enable Slot command via the Command Ring), address
|
||||
the device (Address Device command), read its device descriptor
|
||||
- [x] On connect: allocate a Device Slot (Enable Slot command via the Command Ring) — **Enable
|
||||
Slot done 2026-08-22**, see writeup below; Address Device + device descriptor read still
|
||||
open (needs enumeration groundwork from 2f)
|
||||
- [ ] On disconnect: tear down the corresponding device slot and signal to whatever higher-
|
||||
level code (Section U's identity/VM logic) that the device is gone — **this is the
|
||||
first point where Section U/V's design actually gets a real trigger to hang off**
|
||||
@@ -3251,11 +3252,40 @@ Full connect→disconnect→connect cycle confirmed on amd64
|
||||
(`logs/20260822-100654/amd64/`); single connect confirmed on aarch64
|
||||
(`logs/20260822-100814/aarch64/`) and riscv64 (`logs/20260822-100940/riscv64/`).
|
||||
|
||||
Still open: correlating the Command Completion Event back to its issuing command (currently
|
||||
only logged, slot ID/context bookkeeping not read from the event TRB), actually calling Enable
|
||||
Slot / Address Device from the connect path above (today's Enable Slot call remains the
|
||||
boot-time smoke test from the previous increment, not yet triggered by a real connect event),
|
||||
and the callback surface into Section U's higher-level code.
|
||||
**Connect -> Enable Slot -> slot correlation, done 2026-08-22.** The boot-time smoke test call
|
||||
is gone; a real connect event now drives `xhci_cmd_enable_slot()` directly from
|
||||
`xhci_poll_events()`'s PSC branch. Correlation between "which port asked for a slot" and "which
|
||||
Command Completion Event answered" uses a new `dev->pending_connect_port_id` (0 = idle, else
|
||||
the port whose Enable Slot is outstanding) rather than matching the Command TRB Pointer in the
|
||||
completion's `parameter` field — sound today because this driver only ever has one command
|
||||
in flight (synchronous with respect to connect events, not a queue); revisit with real TRB
|
||||
Pointer matching once Address Device commands can also be outstanding concurrently. On success
|
||||
the returned Slot ID (`XHCI_EVT_SLOT_ID()`, decoded from `control[31:24]`) is recorded in a new
|
||||
`dev->port_slot_id[]`, indexed by port — a **fixed** `uint32_t[XHCI_MAX_TRACKED_PORTS]` (32),
|
||||
not heap-allocated. That fixed-size choice wasn't cosmetic: a first attempt sized this
|
||||
dynamically via `kmalloc_aligned(dev->max_ports * sizeof(uint32_t), 64)` inside
|
||||
`xhci_bringup()` and it crashed on amd64 — a page fault (`IFETCH` at `RIP=CR2=0xA0000`,
|
||||
inside the legacy VGA hole) during the unrelated Mama-VM-birth phase that runs afterward,
|
||||
strongly suggesting heap corruption rather than a fault in the new code itself. Root cause not
|
||||
chased further — reverting to a fixed array matching this driver's own existing preference
|
||||
(xhci.h's ring-sizing rationale) sidesteps the heap interaction entirely and is simpler besides.
|
||||
If a future device genuinely needs >32 tracked ports, that heap interaction needs revisiting
|
||||
before growing this array dynamically again.
|
||||
|
||||
Disconnect clears the port's tracked slot ID (real teardown — Disable Slot command, DCBAA entry
|
||||
clear, Section U callback — is still a later increment; this only stops treating the port as
|
||||
occupied so a future connect on it isn't confused for one already in progress).
|
||||
|
||||
Verified live via QMP hotplug, all three architectures: connect logs `port status change --
|
||||
device connected` -> `enable slot command submitted` -> `enable slot succeeded`; a
|
||||
disconnect/reconnect cycle repeats cleanly with no wedge. Full cycle on amd64
|
||||
(`logs/20260822-102849/amd64/`); single connect confirmed on aarch64
|
||||
(`logs/20260822-103005/aarch64/`) and riscv64 (`logs/20260822-103137/riscv64/`).
|
||||
|
||||
Still open: correlating the Command Completion Event back to its issuing command via the real
|
||||
Command TRB Pointer (not needed yet, see above), Address Device + device descriptor read
|
||||
(needs 2f's enumeration groundwork), and the callback surface into Section U's higher-level
|
||||
code.
|
||||
|
||||
**2f. USB device enumeration (post-connect, before it's usable as storage)**
|
||||
- [ ] Request and parse the device descriptor (confirm vendor/product IDs are even needed,
|
||||
|
||||
Reference in New Issue
Block a user