Fix xHCI heap corruption: allocate the Output Device Context full size at Address Device, never swap it (found at O-C)

xhci_cmd_address_device() sized the Output Device Context for Slot + EP0
(64 bytes); xhci_cmd_configure_endpoint() then allocated a bigger copy and
repointed DCBAA[slot_id]. The controller keeps the address it was given at
Address Device (QEMU caches it), so every bulk Endpoint Context was written
past the 64-byte block into the next kmalloc header -- on every USB
mass-storage attach, every ISA. After O-C's smoke campaign reshuffled the
heap, a kfree at thumbdrive unplug walked into it: #GP in coalesce_neighbors().

Found with temporary instrumentation (load base, code bytes at RIP, event
crumbs, a heap-list checker): the corrupt word was an EP Context (Bulk IN,
Running, MPS 1024) exactly DCI 3 x 32 bytes into the 64-byte context.

Now: XHCI_DEVICE_CTX_BYTES (32 contexts x 32 bytes) allocated once per
slot at Address Device, zeroed whole, never reallocated; Configure
Endpoint just fills it. Also ends the per-attach leak of the old context.

Verified: heap checker clean from boot; campaign -> O-A -> MINT -> unplug
-> re-attach passes with 0 exceptions; 3-ISA acceptance passes, parity and
dict_hash set unchanged.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Robert Allan James
2026-09-25 10:57:43 -04:00
co-authored by Claude Opus 5.5
parent ee4c401d1c
commit df150e8626
28 changed files with 110993 additions and 24 deletions
+61
View File
@@ -738,3 +738,64 @@ Evidence is named **before** each stage runs.
- The relay and `BLK-ATTACH` flows are unchanged: mint → WIREBIND → `USE` → `3`, with the - The relay and `BLK-ATTACH` flows are unchanged: mint → WIREBIND → `USE` → `3`, with the
ledger at the standard `held=2048 pulled=258048 returned=255263 consumed=737`. ledger at the standard `held=2048 pulled=258048 returned=255263 consumed=737`.
- Idle log growth is 0, there are no faults, and QEMU exits cleanly. - Idle log growth is 0, there are no faults, and QEMU exits cleanly.
- [x] **Fix, found at O-C: the xHCI driver corrupted the kernel heap on every USB mass-storage
attach** (2026-09-25). Captain Bob: *"1, investigate the crash first"*, then *"go ahead with
the xHCI fix"*.
**The symptom.** After O-C's 1-rep smoke campaign, the standard sequence halted with a `#GP`
(vector 13) right after `MINT`, when Bob's thumbdrive is unplugged:
- `logs/20260925-013706/amd64/`;
- reproduced as `-043257`, `-055533` and `-071858`.
The kernel was unchanged since O-B; O-C is capsule-only. A fresh boot passed
(`-025933`), and so did 28 births and kills with trivial jobs (`-041213`). Only a real
campaign followed by the unplug crashed.
**How it was found** (temporary instrumentation, all reverted):
- **Mapping the fault.** Printing the load base showed that the amd64 kernel is relocated by
a whole number of pages plus 0x440, and differently on every boot. RIP-to-symbol mapping
against the wrong base was the earlier dead end.
- **Code bytes at RIP.** Dumping them and matching them in the ELF located the fault exactly:
`kfree` → `coalesce_neighbors()`, at `mov %rdx,0x20(%rax)`, writing a free-list neighbour's
`prev` through a garbage pointer.
- **Event breadcrumbs** put it inside `blk_subsys_detach_device()`, between `blkio_close()`
and the end of the two `free()`s.
- **A heap-list checker, run at every event,** found the corruption already at boot, during
the first USB attach, Zuse's thumbdrive (`-084150`, `-084728`). One allocated block's
header `prev` field held `0x0400003600000001`.
**The defect.** That value is the first 8 bytes of an xHCI **Endpoint Context**: EP State
Running (1); EP Type 6 (Bulk IN), CErr 3, Max Packet Size 1024.
- The controller writes it at DCI 3 × 32 = 0x60 bytes into the device context.
- 0x3253060 − 0x60 = 0x3253000 is the start of the **64-byte Output Device Context** allocated
at Address Device, whose heap block ends at the damaged header, 0x3253040.
- `xhci_cmd_address_device()` sized that context for Slot + EP0 only.
- `xhci_cmd_configure_endpoint()` then allocated a bigger copy and repointed `DCBAA[slot_id]`.
- But the controller takes the Output Device Context address at Address Device and keeps it.
QEMU caches it and never re-reads DCBAA. So every bulk EP Context was written past the end
of the 64-byte block, into the next heap header, on every mass-storage attach, on every ISA.
- It is usually harmless in practice: the damaged header is never walked. The campaign's
churn moves the heap so that a later `kfree` at unplug walks straight into it.
- The old context also leaked on every attach.
**The fix** (`xhci.c`, `xhci.h`, `xhci_driver.h`):
- The Output Device Context is allocated **full size** at Address Device, once per slot:
`XHCI_DEVICE_CTX_BYTES` = 32 contexts × 32 bytes (CSZ = 0, the only mode this driver
implements).
- It is zeroed across its whole length and never swapped.
- Configure Endpoint no longer grows, copies or repoints it. It refuses a DCI past the context.
- That also ends the per-attach leak.
**Verification:**
- Instrumented, fixed kernel (`-090302`): **0** heap-checker reports at boot attach and
throughout. Then the full reproduction (smoke campaign, 6/6 trials `fail=0`, O-A, `MINT` →
unplug → re-attach → `WIREBIND` → `3`) passes with **0** exceptions.
- Clean tree, instrumentation reverted, 3-ISA acceptance (`logs/20260925-101854/amd64/`,
`-103145/aarch64/`, `-104448/riscv64/`): boot parity and the `dict_hash` set unchanged (546
words, `0x99b01134c3d3049c`), the O-A checks pass, mint → WIREBIND → `USE` → `3` with the
standard ledger, idle growth 0, no faults.
- These boots also carry O-C's capsules and serve as its standard sequence (next entry).
**Process note.** During the investigation, a `make clean` for amd64 was run while that
ISA's QEMU was up. It deleted the running QEMU's control sockets; that QEMU was stopped with
SIGTERM, since no QMP socket was left, and its log was discarded as flawed.
@@ -0,0 +1,9 @@
vm_name,vm_id_hex,tick_number,elapsed_ns,tick_interval_ns,cache_hits_delta,bucket_hits_delta,word_executions_delta,hot_word_count,avg_word_heat_q48,window_width,actual_window_size,predicted_label_hits,jitter_bits,apic_ticks,time_trust_q48,variance_q48,vm_call_depth_max,hera_heat_q48,hermes_heat_q48,artemis_heat_q48,fleet_k_q48,fleet_conserved,switch_count_cumulative,switch_current_slot,switch_hera_readiness,switch_hermes_readiness,switch_artemis_readiness,switch_ticks_since
Hera,0000000000000000-0000000000000000,76,760000,10000,0,0,256,61,35,4096,4096,0,0,20011,65533,3,1,65536,0,0,65536,1,0,2,0,0,0,9
Hera,0000000000000000-0000000000000000,77,770000,10000,0,0,256,62,36,2048,2048,0,0,20012,65533,3,1,65536,0,0,65536,1,0,2,0,0,0,10
Hera,0000000000000000-0000000000000000,78,780000,10000,0,0,256,62,37,2048,2048,0,0,20014,65533,3,1,65536,0,0,65536,1,0,2,0,0,0,11
,3a3611885b52444c-91aeb2c971167037,1,10000,18446744073708781616,0,0,93,4,4,4096,0,0,4895412794951728771,20125,65533,3,0,65536,0,0,65536,1,0,2,0,0,0,11
Hera,0000000000000000-0000000000000000,79,790000,780000,0,0,15572,67,38,1024,1024,0,4694861461728526336,20132,65533,3,1,65536,0,0,65536,1,0,2,0,0,0,12
,edaab92527ee4080-ac1e0c431056e4e7,1,10000,18446744073708771616,0,0,98,7,8,4096,0,0,4895412794951728766,20253,65533,3,0,65536,0,0,65536,1,0,2,0,0,0,12
Hera,0000000000000000-0000000000000000,80,800000,790000,0,0,15823,69,39,1024,1024,0,4694947361074446336,20260,65533,3,1,65536,0,0,65536,1,0,2,0,0,0,13
Hera,0000000000000000-0000000000000000,81,810000,10000,0,0,256,71,40,512,512,0,0,20309,65533,3,1,65536,0,0,65536,1,0,2,0,0,0,14
1 vm_name vm_id_hex tick_number elapsed_ns tick_interval_ns cache_hits_delta bucket_hits_delta word_executions_delta hot_word_count avg_word_heat_q48 window_width actual_window_size predicted_label_hits jitter_bits apic_ticks time_trust_q48 variance_q48 vm_call_depth_max hera_heat_q48 hermes_heat_q48 artemis_heat_q48 fleet_k_q48 fleet_conserved switch_count_cumulative switch_current_slot switch_hera_readiness switch_hermes_readiness switch_artemis_readiness switch_ticks_since
2 Hera 0000000000000000-0000000000000000 76 760000 10000 0 0 256 61 35 4096 4096 0 0 20011 65533 3 1 65536 0 0 65536 1 0 2 0 0 0 9
3 Hera 0000000000000000-0000000000000000 77 770000 10000 0 0 256 62 36 2048 2048 0 0 20012 65533 3 1 65536 0 0 65536 1 0 2 0 0 0 10
4 Hera 0000000000000000-0000000000000000 78 780000 10000 0 0 256 62 37 2048 2048 0 0 20014 65533 3 1 65536 0 0 65536 1 0 2 0 0 0 11
5 3a3611885b52444c-91aeb2c971167037 1 10000 18446744073708781616 0 0 93 4 4 4096 0 0 4895412794951728771 20125 65533 3 0 65536 0 0 65536 1 0 2 0 0 0 11
6 Hera 0000000000000000-0000000000000000 79 790000 780000 0 0 15572 67 38 1024 1024 0 4694861461728526336 20132 65533 3 1 65536 0 0 65536 1 0 2 0 0 0 12
7 edaab92527ee4080-ac1e0c431056e4e7 1 10000 18446744073708771616 0 0 98 7 8 4096 0 0 4895412794951728766 20253 65533 3 0 65536 0 0 65536 1 0 2 0 0 0 12
8 Hera 0000000000000000-0000000000000000 80 800000 790000 0 0 15823 69 39 1024 1024 0 4694947361074446336 20260 65533 3 1 65536 0 0 65536 1 0 2 0 0 0 13
9 Hera 0000000000000000-0000000000000000 81 810000 10000 0 0 256 71 40 512 512 0 0 20309 65533 3 1 65536 0 0 65536 1 0 2 0 0 0 14
@@ -0,0 +1,9 @@
vm_name,vm_id_hex,tick_number,elapsed_ns,tick_interval_ns,cache_hits_delta,bucket_hits_delta,word_executions_delta,hot_word_count,avg_word_heat_q48,window_width,actual_window_size,predicted_label_hits,jitter_bits,apic_ticks,time_trust_q48,variance_q48,vm_call_depth_max,hera_heat_q48,hermes_heat_q48,artemis_heat_q48,fleet_k_q48,fleet_conserved,switch_count_cumulative,switch_current_slot,switch_hera_readiness,switch_hermes_readiness,switch_artemis_readiness,switch_ticks_since
Hera,0000000000000000-0000000000000000,76,760000,10000,0,0,256,61,35,4096,4096,0,0,19515,65535,1,1,65536,0,0,65536,1,0,2,0,0,0,9
Hera,0000000000000000-0000000000000000,77,770000,10000,0,0,256,62,36,2048,2048,0,0,19517,65535,1,1,65536,0,0,65536,1,0,2,0,0,0,10
Hera,0000000000000000-0000000000000000,78,780000,10000,0,0,256,62,37,2048,2048,0,0,19519,65535,1,1,65536,0,0,65536,1,0,2,0,0,0,11
,3a3611885b52444c-91aeb2c971167037,1,10000,18446744073708781616,0,0,93,4,4,4096,0,0,4895412794951728771,19634,65535,1,0,65536,0,0,65536,1,0,2,0,0,0,11
Hera,0000000000000000-0000000000000000,79,790000,780000,0,0,15572,67,38,1024,1024,0,4694861461728526336,19639,65535,1,1,65536,0,0,65536,1,0,2,0,0,0,12
,edaab92527ee4080-ac1e0c431056e4e7,1,10000,18446744073708771616,0,0,98,7,8,4096,0,0,4895412794951728766,19763,65535,1,0,65536,0,0,65536,1,0,2,0,0,0,12
Hera,0000000000000000-0000000000000000,80,800000,790000,0,0,15823,69,39,1024,1024,0,4694947361074446336,19770,65535,1,1,65536,0,0,65536,1,0,2,0,0,0,13
Hera,0000000000000000-0000000000000000,81,810000,10000,0,0,256,71,40,512,512,0,0,19820,65535,1,1,65536,0,0,65536,1,0,2,0,0,0,14
1 vm_name vm_id_hex tick_number elapsed_ns tick_interval_ns cache_hits_delta bucket_hits_delta word_executions_delta hot_word_count avg_word_heat_q48 window_width actual_window_size predicted_label_hits jitter_bits apic_ticks time_trust_q48 variance_q48 vm_call_depth_max hera_heat_q48 hermes_heat_q48 artemis_heat_q48 fleet_k_q48 fleet_conserved switch_count_cumulative switch_current_slot switch_hera_readiness switch_hermes_readiness switch_artemis_readiness switch_ticks_since
2 Hera 0000000000000000-0000000000000000 76 760000 10000 0 0 256 61 35 4096 4096 0 0 19515 65535 1 1 65536 0 0 65536 1 0 2 0 0 0 9
3 Hera 0000000000000000-0000000000000000 77 770000 10000 0 0 256 62 36 2048 2048 0 0 19517 65535 1 1 65536 0 0 65536 1 0 2 0 0 0 10
4 Hera 0000000000000000-0000000000000000 78 780000 10000 0 0 256 62 37 2048 2048 0 0 19519 65535 1 1 65536 0 0 65536 1 0 2 0 0 0 11
5 3a3611885b52444c-91aeb2c971167037 1 10000 18446744073708781616 0 0 93 4 4 4096 0 0 4895412794951728771 19634 65535 1 0 65536 0 0 65536 1 0 2 0 0 0 11
6 Hera 0000000000000000-0000000000000000 79 790000 780000 0 0 15572 67 38 1024 1024 0 4694861461728526336 19639 65535 1 1 65536 0 0 65536 1 0 2 0 0 0 12
7 edaab92527ee4080-ac1e0c431056e4e7 1 10000 18446744073708771616 0 0 98 7 8 4096 0 0 4895412794951728766 19763 65535 1 0 65536 0 0 65536 1 0 2 0 0 0 12
8 Hera 0000000000000000-0000000000000000 80 800000 790000 0 0 15823 69 39 1024 1024 0 4694947361074446336 19770 65535 1 1 65536 0 0 65536 1 0 2 0 0 0 13
9 Hera 0000000000000000-0000000000000000 81 810000 10000 0 0 256 71 40 512 512 0 0 19820 65535 1 1 65536 0 0 65536 1 0 2 0 0 0 14
@@ -0,0 +1,9 @@
vm_name,vm_id_hex,tick_number,elapsed_ns,tick_interval_ns,cache_hits_delta,bucket_hits_delta,word_executions_delta,hot_word_count,avg_word_heat_q48,window_width,actual_window_size,predicted_label_hits,jitter_bits,apic_ticks,time_trust_q48,variance_q48,vm_call_depth_max,hera_heat_q48,hermes_heat_q48,artemis_heat_q48,fleet_k_q48,fleet_conserved,switch_count_cumulative,switch_current_slot,switch_hera_readiness,switch_hermes_readiness,switch_artemis_readiness,switch_ticks_since
Hera,0000000000000000-0000000000000000,76,760000,10000,0,0,256,61,35,4096,4096,0,0,20858,65534,2,1,65536,0,0,65536,1,0,2,0,0,0,9
Hera,0000000000000000-0000000000000000,77,770000,10000,0,0,256,62,36,2048,2048,0,0,20860,65534,2,1,65536,0,0,65536,1,0,2,0,0,0,10
Hera,0000000000000000-0000000000000000,78,780000,10000,0,0,256,62,37,2048,2048,0,0,20862,65534,2,1,65536,0,0,65536,1,0,2,0,0,0,11
,3a3611885b52444c-91aeb2c971167037,1,10000,18446744073708781616,0,0,93,4,4,4096,0,0,4895412794951728771,20971,65534,2,0,65536,0,0,65536,1,0,2,0,0,0,11
Hera,0000000000000000-0000000000000000,79,790000,780000,0,0,15572,67,38,1024,1024,0,4694861461728526336,20976,65534,2,1,65536,0,0,65536,1,0,2,0,0,0,12
,edaab92527ee4080-ac1e0c431056e4e7,1,10000,18446744073708771616,0,0,98,7,8,4096,0,0,4895412794951728766,21095,65534,2,0,65536,0,0,65536,1,0,2,0,0,0,12
Hera,0000000000000000-0000000000000000,80,800000,790000,0,0,15823,69,39,1024,1024,0,4694947361074446336,21104,65534,2,1,65536,0,0,65536,1,0,2,0,0,0,13
Hera,0000000000000000-0000000000000000,81,810000,10000,0,0,256,71,40,512,512,0,0,21152,65534,2,1,65536,0,0,65536,1,0,2,0,0,0,14
1 vm_name vm_id_hex tick_number elapsed_ns tick_interval_ns cache_hits_delta bucket_hits_delta word_executions_delta hot_word_count avg_word_heat_q48 window_width actual_window_size predicted_label_hits jitter_bits apic_ticks time_trust_q48 variance_q48 vm_call_depth_max hera_heat_q48 hermes_heat_q48 artemis_heat_q48 fleet_k_q48 fleet_conserved switch_count_cumulative switch_current_slot switch_hera_readiness switch_hermes_readiness switch_artemis_readiness switch_ticks_since
2 Hera 0000000000000000-0000000000000000 76 760000 10000 0 0 256 61 35 4096 4096 0 0 20858 65534 2 1 65536 0 0 65536 1 0 2 0 0 0 9
3 Hera 0000000000000000-0000000000000000 77 770000 10000 0 0 256 62 36 2048 2048 0 0 20860 65534 2 1 65536 0 0 65536 1 0 2 0 0 0 10
4 Hera 0000000000000000-0000000000000000 78 780000 10000 0 0 256 62 37 2048 2048 0 0 20862 65534 2 1 65536 0 0 65536 1 0 2 0 0 0 11
5 3a3611885b52444c-91aeb2c971167037 1 10000 18446744073708781616 0 0 93 4 4 4096 0 0 4895412794951728771 20971 65534 2 0 65536 0 0 65536 1 0 2 0 0 0 11
6 Hera 0000000000000000-0000000000000000 79 790000 780000 0 0 15572 67 38 1024 1024 0 4694861461728526336 20976 65534 2 1 65536 0 0 65536 1 0 2 0 0 0 12
7 edaab92527ee4080-ac1e0c431056e4e7 1 10000 18446744073708771616 0 0 98 7 8 4096 0 0 4895412794951728766 21095 65534 2 0 65536 0 0 65536 1 0 2 0 0 0 12
8 Hera 0000000000000000-0000000000000000 80 800000 790000 0 0 15823 69 39 1024 1024 0 4694947361074446336 21104 65534 2 1 65536 0 0 65536 1 0 2 0 0 0 13
9 Hera 0000000000000000-0000000000000000 81 810000 10000 0 0 256 71 40 512 512 0 0 21152 65534 2 1 65536 0 0 65536 1 0 2 0 0 0 14
@@ -0,0 +1,9 @@
vm_name,vm_id_hex,tick_number,elapsed_ns,tick_interval_ns,cache_hits_delta,bucket_hits_delta,word_executions_delta,hot_word_count,avg_word_heat_q48,window_width,actual_window_size,predicted_label_hits,jitter_bits,apic_ticks,time_trust_q48,variance_q48,vm_call_depth_max,hera_heat_q48,hermes_heat_q48,artemis_heat_q48,fleet_k_q48,fleet_conserved,switch_count_cumulative,switch_current_slot,switch_hera_readiness,switch_hermes_readiness,switch_artemis_readiness,switch_ticks_since
Hera,0000000000000000-0000000000000000,76,760000,10000,0,0,256,61,35,4096,4096,0,0,20795,65536,0,1,65536,0,0,65536,1,0,2,0,0,0,9
Hera,0000000000000000-0000000000000000,77,770000,10000,0,0,256,62,36,2048,2048,0,0,20799,65536,0,1,65536,0,0,65536,1,0,2,0,0,0,10
Hera,0000000000000000-0000000000000000,78,780000,10000,0,0,256,62,37,2048,2048,0,0,20801,65536,0,1,65536,0,0,65536,1,0,2,0,0,0,11
,3a3611885b52444c-91aeb2c971167037,1,10000,18446744073708781616,0,0,93,4,4,4096,0,0,4895412794951728771,20912,65536,0,0,65536,0,0,65536,1,0,2,0,0,0,11
Hera,0000000000000000-0000000000000000,79,790000,780000,0,0,15572,67,38,1024,1024,0,4694861461728526336,20917,65536,0,1,65536,0,0,65536,1,0,2,0,0,0,12
,edaab92527ee4080-ac1e0c431056e4e7,1,10000,18446744073708771616,0,0,98,7,8,4096,0,0,4895412794951728766,21037,65536,0,0,65536,0,0,65536,1,0,2,0,0,0,12
Hera,0000000000000000-0000000000000000,80,800000,790000,0,0,15823,69,39,1024,1024,0,4694947361074446336,21045,65536,0,1,65536,0,0,65536,1,0,2,0,0,0,13
Hera,0000000000000000-0000000000000000,81,810000,10000,0,0,256,71,40,512,512,0,0,21093,65536,0,1,65536,0,0,65536,1,0,2,0,0,0,14
1 vm_name vm_id_hex tick_number elapsed_ns tick_interval_ns cache_hits_delta bucket_hits_delta word_executions_delta hot_word_count avg_word_heat_q48 window_width actual_window_size predicted_label_hits jitter_bits apic_ticks time_trust_q48 variance_q48 vm_call_depth_max hera_heat_q48 hermes_heat_q48 artemis_heat_q48 fleet_k_q48 fleet_conserved switch_count_cumulative switch_current_slot switch_hera_readiness switch_hermes_readiness switch_artemis_readiness switch_ticks_since
2 Hera 0000000000000000-0000000000000000 76 760000 10000 0 0 256 61 35 4096 4096 0 0 20795 65536 0 1 65536 0 0 65536 1 0 2 0 0 0 9
3 Hera 0000000000000000-0000000000000000 77 770000 10000 0 0 256 62 36 2048 2048 0 0 20799 65536 0 1 65536 0 0 65536 1 0 2 0 0 0 10
4 Hera 0000000000000000-0000000000000000 78 780000 10000 0 0 256 62 37 2048 2048 0 0 20801 65536 0 1 65536 0 0 65536 1 0 2 0 0 0 11
5 3a3611885b52444c-91aeb2c971167037 1 10000 18446744073708781616 0 0 93 4 4 4096 0 0 4895412794951728771 20912 65536 0 0 65536 0 0 65536 1 0 2 0 0 0 11
6 Hera 0000000000000000-0000000000000000 79 790000 780000 0 0 15572 67 38 1024 1024 0 4694861461728526336 20917 65536 0 1 65536 0 0 65536 1 0 2 0 0 0 12
7 edaab92527ee4080-ac1e0c431056e4e7 1 10000 18446744073708771616 0 0 98 7 8 4096 0 0 4895412794951728766 21037 65536 0 0 65536 0 0 65536 1 0 2 0 0 0 12
8 Hera 0000000000000000-0000000000000000 80 800000 790000 0 0 15823 69 39 1024 1024 0 4694947361074446336 21045 65536 0 1 65536 0 0 65536 1 0 2 0 0 0 13
9 Hera 0000000000000000-0000000000000000 81 810000 10000 0 0 256 71 40 512 512 0 0 21093 65536 0 1 65536 0 0 65536 1 0 2 0 0 0 14
@@ -0,0 +1,9 @@
vm_name,vm_id_hex,tick_number,elapsed_ns,tick_interval_ns,cache_hits_delta,bucket_hits_delta,word_executions_delta,hot_word_count,avg_word_heat_q48,window_width,actual_window_size,predicted_label_hits,jitter_bits,apic_ticks,time_trust_q48,variance_q48,vm_call_depth_max,hera_heat_q48,hermes_heat_q48,artemis_heat_q48,fleet_k_q48,fleet_conserved,switch_count_cumulative,switch_current_slot,switch_hera_readiness,switch_hermes_readiness,switch_artemis_readiness,switch_ticks_since
Hera,0000000000000000-0000000000000000,76,760000,10000,0,0,256,61,35,4096,4096,0,0,20870,65535,1,1,65536,0,0,65536,1,0,2,0,0,0,9
Hera,0000000000000000-0000000000000000,77,770000,10000,0,0,256,62,36,2048,2048,0,0,20872,65535,1,1,65536,0,0,65536,1,0,2,0,0,0,10
Hera,0000000000000000-0000000000000000,78,780000,10000,0,0,256,62,37,2048,2048,0,0,20874,65535,1,1,65536,0,0,65536,1,0,2,0,0,0,11
,3a3611885b52444c-91aeb2c971167037,1,10000,18446744073708781616,0,0,93,4,4,4096,0,0,4895412794951728771,20982,65535,1,0,65536,0,0,65536,1,0,2,0,0,0,11
Hera,0000000000000000-0000000000000000,79,790000,780000,0,0,15572,67,38,1024,1024,0,4694861461728526336,20988,65535,1,1,65536,0,0,65536,1,0,2,0,0,0,12
,edaab92527ee4080-ac1e0c431056e4e7,1,10000,18446744073708771616,0,0,98,7,8,4096,0,0,4895412794951728766,21109,65535,1,0,65536,0,0,65536,1,0,2,0,0,0,12
Hera,0000000000000000-0000000000000000,80,800000,790000,0,0,15823,69,39,1024,1024,0,4694947361074446336,21116,65535,1,1,65536,0,0,65536,1,0,2,0,0,0,13
Hera,0000000000000000-0000000000000000,81,810000,10000,0,0,256,71,40,512,512,0,0,21165,65535,1,1,65536,0,0,65536,1,0,2,0,0,0,14
1 vm_name vm_id_hex tick_number elapsed_ns tick_interval_ns cache_hits_delta bucket_hits_delta word_executions_delta hot_word_count avg_word_heat_q48 window_width actual_window_size predicted_label_hits jitter_bits apic_ticks time_trust_q48 variance_q48 vm_call_depth_max hera_heat_q48 hermes_heat_q48 artemis_heat_q48 fleet_k_q48 fleet_conserved switch_count_cumulative switch_current_slot switch_hera_readiness switch_hermes_readiness switch_artemis_readiness switch_ticks_since
2 Hera 0000000000000000-0000000000000000 76 760000 10000 0 0 256 61 35 4096 4096 0 0 20870 65535 1 1 65536 0 0 65536 1 0 2 0 0 0 9
3 Hera 0000000000000000-0000000000000000 77 770000 10000 0 0 256 62 36 2048 2048 0 0 20872 65535 1 1 65536 0 0 65536 1 0 2 0 0 0 10
4 Hera 0000000000000000-0000000000000000 78 780000 10000 0 0 256 62 37 2048 2048 0 0 20874 65535 1 1 65536 0 0 65536 1 0 2 0 0 0 11
5 3a3611885b52444c-91aeb2c971167037 1 10000 18446744073708781616 0 0 93 4 4 4096 0 0 4895412794951728771 20982 65535 1 0 65536 0 0 65536 1 0 2 0 0 0 11
6 Hera 0000000000000000-0000000000000000 79 790000 780000 0 0 15572 67 38 1024 1024 0 4694861461728526336 20988 65535 1 1 65536 0 0 65536 1 0 2 0 0 0 12
7 edaab92527ee4080-ac1e0c431056e4e7 1 10000 18446744073708771616 0 0 98 7 8 4096 0 0 4895412794951728766 21109 65535 1 0 65536 0 0 65536 1 0 2 0 0 0 12
8 Hera 0000000000000000-0000000000000000 80 800000 790000 0 0 15823 69 39 1024 1024 0 4694947361074446336 21116 65535 1 1 65536 0 0 65536 1 0 2 0 0 0 13
9 Hera 0000000000000000-0000000000000000 81 810000 10000 0 0 256 71 40 512 512 0 0 21165 65535 1 1 65536 0 0 65536 1 0 2 0 0 0 14
@@ -0,0 +1,9 @@
vm_name,vm_id_hex,tick_number,elapsed_ns,tick_interval_ns,cache_hits_delta,bucket_hits_delta,word_executions_delta,hot_word_count,avg_word_heat_q48,window_width,actual_window_size,predicted_label_hits,jitter_bits,apic_ticks,time_trust_q48,variance_q48,vm_call_depth_max,hera_heat_q48,hermes_heat_q48,artemis_heat_q48,fleet_k_q48,fleet_conserved,switch_count_cumulative,switch_current_slot,switch_hera_readiness,switch_hermes_readiness,switch_artemis_readiness,switch_ticks_since
Hera,0000000000000000-0000000000000000,76,760000,10000,0,0,256,61,35,4096,4096,0,0,22526,65536,0,1,65536,0,0,65536,1,0,2,0,0,0,9
Hera,0000000000000000-0000000000000000,77,770000,10000,0,0,256,62,36,2048,2048,0,0,22528,65536,0,1,65536,0,0,65536,1,0,2,0,0,0,10
Hera,0000000000000000-0000000000000000,78,780000,10000,0,0,256,62,37,2048,2048,0,0,22531,65536,0,1,65536,0,0,65536,1,0,2,0,0,0,11
,3a3611885b52444c-91aeb2c971167037,1,10000,18446744073708781616,0,0,93,4,4,4096,0,0,4895412794951728771,22646,65536,0,0,65536,0,0,65536,1,0,2,0,0,0,11
Hera,0000000000000000-0000000000000000,79,790000,780000,0,0,15572,67,38,1024,1024,0,4694861461728526336,22654,65536,0,1,65536,0,0,65536,1,0,2,0,0,0,12
,edaab92527ee4080-ac1e0c431056e4e7,1,10000,18446744073708771616,0,0,98,7,8,4096,0,0,4895412794951728766,22778,65536,0,0,65536,0,0,65536,1,0,2,0,0,0,12
Hera,0000000000000000-0000000000000000,80,800000,790000,0,0,15823,69,39,1024,1024,0,4694947361074446336,22787,65536,0,1,65536,0,0,65536,1,0,2,0,0,0,13
Hera,0000000000000000-0000000000000000,81,810000,10000,0,0,256,71,40,512,512,0,0,22857,65536,0,1,65536,0,0,65536,1,0,2,0,0,0,14
1 vm_name vm_id_hex tick_number elapsed_ns tick_interval_ns cache_hits_delta bucket_hits_delta word_executions_delta hot_word_count avg_word_heat_q48 window_width actual_window_size predicted_label_hits jitter_bits apic_ticks time_trust_q48 variance_q48 vm_call_depth_max hera_heat_q48 hermes_heat_q48 artemis_heat_q48 fleet_k_q48 fleet_conserved switch_count_cumulative switch_current_slot switch_hera_readiness switch_hermes_readiness switch_artemis_readiness switch_ticks_since
2 Hera 0000000000000000-0000000000000000 76 760000 10000 0 0 256 61 35 4096 4096 0 0 22526 65536 0 1 65536 0 0 65536 1 0 2 0 0 0 9
3 Hera 0000000000000000-0000000000000000 77 770000 10000 0 0 256 62 36 2048 2048 0 0 22528 65536 0 1 65536 0 0 65536 1 0 2 0 0 0 10
4 Hera 0000000000000000-0000000000000000 78 780000 10000 0 0 256 62 37 2048 2048 0 0 22531 65536 0 1 65536 0 0 65536 1 0 2 0 0 0 11
5 3a3611885b52444c-91aeb2c971167037 1 10000 18446744073708781616 0 0 93 4 4 4096 0 0 4895412794951728771 22646 65536 0 0 65536 0 0 65536 1 0 2 0 0 0 11
6 Hera 0000000000000000-0000000000000000 79 790000 780000 0 0 15572 67 38 1024 1024 0 4694861461728526336 22654 65536 0 1 65536 0 0 65536 1 0 2 0 0 0 12
7 edaab92527ee4080-ac1e0c431056e4e7 1 10000 18446744073708771616 0 0 98 7 8 4096 0 0 4895412794951728766 22778 65536 0 0 65536 0 0 65536 1 0 2 0 0 0 12
8 Hera 0000000000000000-0000000000000000 80 800000 790000 0 0 15823 69 39 1024 1024 0 4694947361074446336 22787 65536 0 1 65536 0 0 65536 1 0 2 0 0 0 13
9 Hera 0000000000000000-0000000000000000 81 810000 10000 0 0 256 71 40 512 512 0 0 22857 65536 0 1 65536 0 0 65536 1 0 2 0 0 0 14
+7
View File
@@ -443,6 +443,13 @@ typedef struct {
volatile uint32_t reserved[3]; volatile uint32_t reserved[3];
} xhci_ep_ctx32_t; } xhci_ep_ctx32_t;
/* The whole Output Device Context (xHCI 1.2 spec section 6.2.1): the Slot
* Context plus 31 Endpoint Contexts, 32-byte each (CSZ=0, the only mode
* this driver implements). Allocated at this size once, at Address Device
* -- the controller keeps the address it was given there. */
#define XHCI_DEVICE_CTX_ENTRIES 32u
#define XHCI_DEVICE_CTX_BYTES (XHCI_DEVICE_CTX_ENTRIES * sizeof(xhci_ep_ctx32_t))
#define XHCI_EP_CTX_TYPE_SHIFT 3 #define XHCI_EP_CTX_TYPE_SHIFT 3
#define XHCI_EP_CTX_TYPE_CONTROL_BIDI 4u /* EP0 */ #define XHCI_EP_CTX_TYPE_CONTROL_BIDI 4u /* EP0 */
#define XHCI_EP_CTX_TYPE_BULK_OUT 2u /* xHCI 1.2 spec table 6-9 */ #define XHCI_EP_CTX_TYPE_BULK_OUT 2u /* xHCI 1.2 spec table 6-9 */
+2 -1
View File
@@ -98,7 +98,8 @@ typedef struct {
* device_ctx/ep0_ring* before this fix; single-drive-at-a-time scope * device_ctx/ep0_ring* before this fix; single-drive-at-a-time scope
* removed, each attached device now gets its own. */ * removed, each attached device now gets its own. */
void *input_ctx; /* Input Control Ctx + Slot Ctx + EP0 Ctx (96 bytes, 32-byte contexts) */ void *input_ctx; /* Input Control Ctx + Slot Ctx + EP0 Ctx (96 bytes, 32-byte contexts) */
void *device_ctx; /* Slot Ctx + EP0 Ctx (64 bytes) -- DCBAA[slot_id] points here */ void *device_ctx; /* full Output Device Context (XHCI_DEVICE_CTX_BYTES, all 32
* contexts) -- DCBAA[slot_id] points here, never swapped */
xhci_trb_t *ep0_ring; /* EP0 Transfer Ring, XHCI_RING_TRB_COUNT TRBs */ xhci_trb_t *ep0_ring; /* EP0 Transfer Ring, XHCI_RING_TRB_COUNT TRBs */
uint32_t ep0_ring_cycle; uint32_t ep0_ring_cycle;
uint32_t ep0_ring_enq; uint32_t ep0_ring_enq;
File diff suppressed because one or more lines are too long
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because it is too large Load Diff
File diff suppressed because one or more lines are too long
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
+22 -23
View File
@@ -489,9 +489,18 @@ int xhci_cmd_address_device(xhci_dev_t *dev, uint32_t slot_id,
sizeof(xhci_ep_ctx32_t), 64); sizeof(xhci_ep_ctx32_t), 64);
if (!ms->input_ctx) return -1; if (!ms->input_ctx) return -1;
} }
/* FABRIC-3.9.8 (found at Stage O-C, 2026-09-25): the Output Device
* Context is allocated FULL SIZE here, once -- Slot Context plus all 31
* Endpoint Contexts (XHCI_DEVICE_CTX_BYTES). It used to be sized for
* Slot + EP0 only (64 bytes) and swapped for a bigger one in
* xhci_cmd_configure_endpoint(), repointing DCBAA[slot_id]. But the
* controller takes the Output Device Context's address at Address
* Device and keeps writing there (QEMU caches it; it does not re-read
* DCBAA), so the bulk endpoints' contexts landed past the end of the
* 64-byte block -- corrupting the next kmalloc header on every mass
* storage attach, until a later kfree walked into it and #GP'd. */
if (!ms->device_ctx) { if (!ms->device_ctx) {
ms->device_ctx = kmalloc_aligned( ms->device_ctx = kmalloc_aligned(XHCI_DEVICE_CTX_BYTES, 64);
sizeof(xhci_slot_ctx32_t) + sizeof(xhci_ep_ctx32_t), 64);
if (!ms->device_ctx) return -1; if (!ms->device_ctx) return -1;
} }
if (!ms->ep0_ring) { if (!ms->ep0_ring) {
@@ -522,7 +531,7 @@ int xhci_cmd_address_device(xhci_dev_t *dev, uint32_t slot_id,
* controller writes this on Address Device success, software must not * controller writes this on Address Device success, software must not
* pre-fill it. */ * pre-fill it. */
uint8_t *dctx = (uint8_t *)ms->device_ctx; uint8_t *dctx = (uint8_t *)ms->device_ctx;
for (size_t i = 0; i < sizeof(xhci_slot_ctx32_t) + sizeof(xhci_ep_ctx32_t); i++) dctx[i] = 0; for (size_t i = 0; i < XHCI_DEVICE_CTX_BYTES; i++) dctx[i] = 0;
((uint64_t *)dev->dcbaa)[slot_id] = (uint64_t)(uintptr_t)ms->device_ctx; ((uint64_t *)dev->dcbaa)[slot_id] = (uint64_t)(uintptr_t)ms->device_ctx;
/* Input Context: Input Control Context, then Slot Context, then EP0 /* Input Context: Input Control Context, then Slot Context, then EP0
@@ -602,26 +611,16 @@ int xhci_cmd_configure_endpoint(xhci_dev_t *dev, uint32_t slot_id)
uint32_t out_dci = XHCI_EP_ADDR_TO_DCI(ms->bulk_out_ep_addr); uint32_t out_dci = XHCI_EP_ADDR_TO_DCI(ms->bulk_out_ep_addr);
uint32_t max_dci = (in_dci > out_dci) ? in_dci : out_dci; uint32_t max_dci = (in_dci > out_dci) ? in_dci : out_dci;
/* DCBAA[slot_id]'s Device Context also needs to grow to hold the new /* The Output Device Context is NOT grown or swapped here (FABRIC-3.9.8,
* EP Contexts -- it's currently sized for Slot+EP0 only (from Address * found at Stage O-C): xhci_cmd_address_device() allocated it full size
* Device). Unlike the Input Context below, this one's *existing* * (XHCI_DEVICE_CTX_BYTES, every DCI) and pointed DCBAA[slot_id] at it,
* content must be preserved, not zeroed: xHCI 1.2 spec section 4.6.6 * and the controller keeps using that address. This used to allocate a
* only has the controller write the DCIs actually named in this * bigger copy and repoint DCBAA -- the controller never saw the swap,
* command's Add/Drop flags (EP0's entry here is neither), so it * wrote the new bulk EP Contexts past the end of the original 64-byte
* expects to find EP0's live output state (its current TR Dequeue * block, and corrupted the heap. Every DCI up to max_dci already has
* Pointer in particular) still intact in the Device Context it reads * room; EP0's live output state is left exactly where the controller
* -- swapping in a freshly zeroed buffer would hand the controller a * put it. */
* blank EP0 out from under an endpoint it isn't being asked to touch. */ if (max_dci >= XHCI_DEVICE_CTX_ENTRIES) return -1;
size_t old_device_ctx_bytes = sizeof(xhci_slot_ctx32_t) + sizeof(xhci_ep_ctx32_t);
size_t new_device_ctx_bytes = (1 + (size_t)max_dci) * sizeof(xhci_ep_ctx32_t);
void *new_device_ctx = kmalloc_aligned(new_device_ctx_bytes, 64);
if (!new_device_ctx) return -1;
uint8_t *ndctx = (uint8_t *)new_device_ctx;
for (size_t i = 0; i < new_device_ctx_bytes; i++) ndctx[i] = 0;
const uint8_t *odctx = (const uint8_t *)ms->device_ctx;
for (size_t i = 0; i < old_device_ctx_bytes; i++) ndctx[i] = odctx[i];
ms->device_ctx = new_device_ctx;
((uint64_t *)dev->dcbaa)[slot_id] = (uint64_t)(uintptr_t)ms->device_ctx;
/* ms->input_ctx is reused from Address Device -- same allocation /* ms->input_ctx is reused from Address Device -- same allocation
* (96 bytes: Input Control Ctx + Slot Ctx + one EP Ctx) is too small * (96 bytes: Input Control Ctx + Slot Ctx + one EP Ctx) is too small