Cores from the DTB /cpus or, on QEMU (ACPI, no DTB), the MADT GICC
entries; the MADT lookup is now shared (hal/acpi.c) with amd64. PSCI
CPU_ON through the discovered conduit into ap_entry.S, which copies the
boot core's MMU/control state, sets TPIDR_EL1 and parks. Core 1 online
at EL1 with its own block; its vCPU thread 0.0% on the host. QEMU aarch64
-smp 2 -name debug-threads=on. 3-ISA acceptance clean.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
hal/smp.c: dense logical core ids, a heap-sized core table, one-at-a-time
bring-up under a 1 s bound, park-wake reporting at the idle point.
amd64: MADT enumeration, a relocation-free real->long-mode trampoline
copied below 1 MiB, INIT-SIPI-SIPI via the LAPIC ICR; QEMU -smp 2.
Core 1 reports online with GS on its own block, parks with 0 wakes;
aarch64/riscv64 report 1 core until MC-1b/c. 3-ISA acceptance clean.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Every lock carries a rank (hermes < switch < registry < VM dict_lock <
VM tuning_lock < stadium < slot < doe < log < block < console < heap <
vmm < pmm); each core counts held locks per rank and an acquisition not
above the highest held rank counts an order violation, reported in full
at the idle point. Probe inversion reported exactly once; O-A, a 28-VM
churn and the standard sequence show 0 violations on all three ISAs.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
CONNECT-HERMES (birthed the removed hermes:init.4th; always failed) and
ARTEMIS-ANNOUNCE-READY (no callers) are gone; DoE CSV column 17 is now
hestia_heat_q48, same position. New baseline on all three ISAs:
word_count 544, M7.1a hash 0x927513aabd543433, Hera 0x4953a2e2d11fff34,
Artemis 0xc5a8cff4b805b6a0, Hestia unchanged.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
vm_physics_remove() retires the node (heat to the root) and frees it;
capsule_vm_kill() and capsule_vm_force_reap() call it, so WIREBIND/EJECT
kills and reaps now retire too (before, only the KILL word did). A dead
VM now leaves only its registry node (168 B). 3-ISA acceptance clean.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The ~3.4 KB/VM heap residual left after K-4 was each dead VM's CONTEXT
and FORTH first-character bucket arrays (84 blocks, 3,400 bytes per
worker), plus last_inference_outputs. New vocabulary_free_indexes();
both vm_cleanup()s call it and free the outputs. Per-VM residual is now
232 bytes: the registry node (kept by design) and the vm_physics node
(open finding). 3-ISA acceptance clean, hash 0x99b01134c3d3049c.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- Investigation (riscv64): completions are slow, not lost -- up to 15 ms,
while the ~1M-iteration bound was ~14 ms of guest time. Each timeout
left the request in the device while the driver forgot it; the next
request took its used entry as its own and returned before its own I/O
finished, and so did every later one (394 in one boot), rewriting
descriptors the device was still reading.
- Fix: VBLK_TIMEOUT_MS (2 s) on the raw hardware counter; each request
waits for exactly one more used entry; a timed-out request stays
outstanding and its completion is drained before anything is reused,
or the next request is refused untouched. Counters for timeouts, late
drains and busy refusals.
- After the fix, all three ISAs: 0 timeouts, 0 unaccounted completions
over 1,912 I/Os; riscv64 slowest completion 7.7 ms (was 15.1).
- Standard sequence on amd64/aarch64/riscv64: hash, G, ledger unchanged;
0 timeouts in the riscv64 log.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- The all target copied the hosted binary to lfs/<arch>/starforth,
rewriting a tracked file on every compile-sanity build (ruled: stop the
copy). A forced relink now leaves lfs/ untouched. Hosted build only; no
kernel change.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- New XHCI_INPUT_CTX_BYTES (control ctx + slot + 31 EP contexts).
Address Device allocates the Input Context at that size once per slot;
Configure Endpoint reuses it (bounds-checked). It allocated a fresh one
on every attach and never freed the old.
- Probe (removed), identical on all three ISAs: after the standard
sequence's attach/detach/re-attach, input-context allocations=2 (one
per xHCI slot) against configure-endpoint=3.
- Standard sequence on amd64/aarch64/riscv64: hash, G, ledger unchanged.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- stadium_release_quota(): evict every patron but pending messages, mark
the slot retiring; stadium_retire_sweep() releases a retiring slot once
nothing is resident -- free cells to the best donor (ruled), word row
and block-table entries cleared, slot free for reuse. Swept at release
and after evictions while any slot is retiring.
- Called on KILL and reap, and for the nine synthetic self-test ids after
the boot self-tests. Hera's slot never released.
- Admission fallback skips DELIVER (message) cells.
- Probe (removed): slots in use == live VMs after boot and after 56-64
churned VMs on all three ISAs; forced fallback kept the message cell
resident and intact; conserved everywhere; K-1's post-churn Hermes
refusal gone (1 2 + . -> 3 on the churned system). Heap growth per
28-VM churn halved (~3.4 KB/VM still retained -- open as K-8).
- Standard sequence on amd64/aarch64/riscv64: hash, G, ledger unchanged.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- Both looked up the retired Hermes VM and printed SKIPPED on every boot.
Drain test: target Hestia, nested VM-EXEC of "1 DROP". Policy test:
Hestia is the no-policy VM (never loads ACL.4th). A missing target now
prints FAIL, not SKIPPED.
- Both PASS on amd64/aarch64/riscv64; standard sequence passes (hash, G,
MINT/WIREBIND/USE, conserved, 0 idle growth). Ledger baseline now
pulled 262144 / returned 259359 (the drain test's real message).
- Found, not fixed: ARTEMIS-ANNOUNCE-READY, doe_log's "Hermes" heat
column and CONNECT-HERMES still reference the retired Hermes VM.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- Defect 1: COLD now forgets every word since the fence exactly as FORGET
does (new vm_dictionary_forget_to_fence(): untrack, metrics, entry) and
rewinds HERE to the fence. It rewound HERE alone to 1024, leaving live
words to be compiled over.
- Defect 2: PAD = BLK_VM_WINDOW_BASE - 512 (was inside the window's top
slot, shared with BLOCK/BUFFER).
- Probe (plain FORTH, all three ISAs identical): PAD..PAD+511 =
5238272..5238783 below the window (5238784); on a worker KA/KC found,
COLD, then KA/KB/KC not found, HERE at the fence (1424), new word works.
- Standard sequence on amd64/aarch64/riscv64: hash and G unchanged,
MINT/WIREBIND/USE ok, conserved, 0 idle growth.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- Kernel sf_realloc() is a real realloc (copy min(old,new) via new
kmalloc_usable_size(), free old, NULL-on-0 frees). It allocated fresh
and nothing else: every growth leaked, and vm_state_push()'s call-state
stack lost every saved state past depth 8 (found here).
- Shim realloc() copies min(old,new) (over-read when growing).
- Defect 9: FC bucket growth no longer leaks or patches a copy; no
sf_xrealloc() (freed a block the index still held on failure).
- Defect 5: heat snapshot heap-sized (was heats[1024], truncating).
- Defect 6: word refused whole when its metrics can't be allocated.
- Defect 7: vm_cleanup() (both) frees metrics' inner arrays.
- Defect 8: most-likely-next kept incrementally; no full id scan.
- Probe (removed): realloc keeps contents, heap returns exactly; call
stack depth 20 intact; all three ISAs. Churn criterion NOT met: ~7 KB
retained per churned VM (quota slots/word rows -- K-4 re-measures); a
post-churn CONSOLE-CMD refusal attributed to the quota leak, K-4 retests.
- Standard sequence on amd64/aarch64/riscv64: hashes, G, ledger unchanged.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- Ruling (Captain Bob): per-slot locks, not "own path needs no lock" --
a lock only on the cross-slot side can't exclude an unlocked owner
(Hermes release evicting a sender's cell while the sender admits).
FABRIC-3.10.0 §3.6 amended.
- StadiumVMQuota.lock covers the slot's lists, reservoir, consumed, word
row and its cells. Word dispatch holds only its own slot lock for the
whole dispatch (*_in_slot forms); peek-then-pull is one step.
- g_lock_stadium: grant slot allocation (new slot published with release
in_use) and the shared block table (ruled: the one shared-lock Stadium
path). Taken before a slot lock.
- Bitmap bytes set/cleared atomically (8 cells, possibly 8 slots).
- Cross-slot writers moved under the owner's lock: Hermes decay
(stadium_cell_decay), Hermes release ledger (stadium_evict_credit),
session pin (stadium_cell_set_pin). stadium_conserved() one hold.
- Word and block cell lookups check the cell is still this slot's.
- Probe (removed), identical on all three ISAs: 10,746,599 of 10,746,616
word dispatches took exactly one lock (own slot), the 17 others all row
growths; every live VM conserved; Hermes audit failures 0.
- Findings reported: births/USE run a VM's words while another VM is the
core's current VM (MC-3 claim must cover it); quota slots never
released; owner admission can evict a live message cell (latent, 0).
- Standard sequence on amd64/aarch64/riscv64: dict_hash set and G
byte-identical, MINT/WIREBIND/USE ok, conservation true, 0 idle growth.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- Dictionary lookup index is per VM (vm->fc_index, struct SfFcIndex):
was one global index rebuilt whenever a different VM was searched, and
heat reorganization could reorder another VM's buckets. Allocated on
first lookup, freed by vm_cleanup(); allocation failure counted/logged,
lookup falls back to a newest-first dictionary walk.
- PRNG: still one stream, stepped by compare-and-swap; SEED one store.
- state_variable removed (write-only; STATE is vm->mode).
- Sweep additions (Captain Bob's ruling): heartbeat_export.c delta
last-values moved into each VM's HeartbeatState (were statics shared by
every VM -- wrong across VMs today); TOP-WORDS list heap-sized per call
(was static [1000]); inference_outputs_to_string() takes a caller
buffer; three failure counters atomic; crc64 table published with
release/acquire.
- Confirmed, unchanged: g_runtime compiled out of the kernel,
g_hotwords_cache unreferenced, ttf cache core-0-only.
- Probe (removed): every VM has its own index; two VMs searched
alternately 2x5000 lookups: 0 rebuilds, 0 wrong-VM results, all three
ISAs.
- Standard sequence on amd64/aarch64/riscv64: dict_hash set unchanged,
G byte-identical, MINT/WIREBIND/USE ok, conservation true, 0 idle growth.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- block_subsystem.c (vendored): every public function's body becomes a
static *_locked function; bodies call each other only through the
_locked forms, breaking the internal cycles (relocate, meta relocate,
migration scan, firsttouch, the meta accessors). Thin public wrappers
take g_lock_block under __STARKERNEL__; hosted build has no lock and
still builds clean.
- Lock order: hermes, switch, registry, doe, log, block, console, heap,
vmm, pmm (Stadium, MC-0d, above block).
- Documented, not coverable by this lock: blk_get_buffer() pointers are
used after release -- block-buffer ownership across cores is open for
MC-3.
- Probe (removed): block lock balances on all three ISAs (2,057-2,379
acquisitions), 0 recursions, 0 held at switch; vblk_io timeouts
(0/0/4 probe, 0/0/2 acceptance) within the pre-lock riscv64 baseline
of 0-6.
- Standard sequence on amd64/aarch64/riscv64: hashes and G byte-identical
to MC-0b, MINT/WIREBIND/USE ok, conservation true, 0 idle growth.
- FABRIC-3.10.8 §3.2 wording fix; lock order noted as checked by
inspection only.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- New spinlock primitive (spinlock.h/.c): CAS on an owner word (core+1),
interrupts masked while any lock is held (state kept in the per-core
block, so release order doesn't matter). Recursion, release-not-held,
held-at-switch and destroyed-while-held are counted and logged, never
silent. Locks are no-ops until the boot core's block is installed
(riscv64's monolithic early boot prints before sk_percpu_boot_init()).
- Kernel locks in a documented order: hermes, switch, registry, doe, log,
console, heap, vmm, pmm. sf_mutex (dict_lock/tuning_lock) uses the same
lock word.
- Hermes: public functions over *_locked internals; never held across the
drain's vm_interpret_kind(); switch notifications after dropping the
lock; event payload moved off static storage. Switch table and registry
never call out while held (slot/entry copied under the lock).
- No lock crosses a switch: checked at context switch (leave, resume) and
the idle point.
- Probe (removed): every lock balances on all three ISAs; 0 held at
switch over 7.5M-51M checks; 0 recursions, 0 bad releases.
- Standard sequence on amd64/aarch64/riscv64: hashes and G byte-identical
to MC-0a, MINT/WIREBIND/USE ok, conservation true, 0 idle growth.
- Block subsystem split out as MC-0b2 (Captain Bob's ruling).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- New sk_percpu_t { self, core_id, current_vm }, reached via GS base
(amd64, %gs:0), TPIDR_EL1 (aarch64), tp (riscv64). Boot core's block is
one static object installed right after arch_early_init(); secondary
cores' blocks come with MC-1.
- switch.c's global g_switch_current_vm is gone; current VM is
sk_percpu()->current_vm, re-read after resume in the context switch.
- Probe (removed): normal path and every heartbeat ISR found core 0's
block on all three ISAs (ISR ok 889/1877/1625, bad 0).
- Standard sequence on amd64/aarch64/riscv64: hashes unchanged from O-C,
G A=40 B=40, MINT/WIREBIND/USE ok, conservation true, 0 idle growth.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- logs/20260925-112529/amd64/: O-D amd64 launch (12345 3 S" amd64" DOE,
rows on), stopped via QMP after 81 min / 131,537 rows with no trial
complete, so the row path could be fixed (row path A ruled).
- FABRIC-3.10.8: Captain Bob, 2026-09-25: "until we close everything, do
not do ant DoE eecution." MC-4's campaigns wait; stage evidence is the
standard sequence plus probes.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- Captain Bob, 2026-09-25: "pin observr and dynmically utilize worker VM's";
MC-R1..R5 as proposed; MC-R6 changed to start now; O-D relaunches with
row path A (serial-only DoE rows). The amd64 O-D launch was stopped after
81 min / 131,537 rows for this.
- FABRIC-3.10.8: the traced inventory of shared state (kernel subsystems
and the shared VM code -- notably one global dictionary lookup index for
all VMs), and stages MC-0a..MC-4 with evidence named in advance.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>