Migrate Hera->Artemis storage-attach to a real message round-trip
Hera still polls xHCI and sig-checks attached drives, but the storage
registration step (blk_subsys_attach_device(), now wrapped as the
BLK-ATTACH primitive) moves to Artemis's own dictionary, reached via
HERA-BLK-ATTACH-REQ/BLK-ATTACH-ACK (VM-EXEC, since Hera can't load her
own messaging.4th -- see the doc comment in repl.c). Identity birth
(Zuse genesis / WIREBIND) is deferred until the ack confirms storage
actually succeeded, instead of running synchronously underneath a
storage call that might fail ("wait for ack, safer for identity data").
Caught and fixed a real bug live during acceptance testing: Artemis's
ACK-APPEND-NUM fed a single-cell value into <# #S #> (which expects a
double-cell pair), causing a stack underflow the first time
HERA-BLK-ATTACH-REQ ran. Fixed with the same `0 SWAP` convention every
other numeric-append helper in this codebase already uses.
Verified booting clean to (zuse) ok> with no VM-EXEC errors on all
three architectures (amd64/aarch64/riscv64).
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_014Ec88YKxxhZGG1RNnune78
This commit is contained in:
co-authored by
Claude Sonnet 5
parent
c4f94c409f
commit
63b8b3bc29
+127
-35
@@ -47,6 +47,7 @@
|
||||
#include "block_subsystem.h"
|
||||
#include "word_source/include/keyboard_words.h"
|
||||
#include "word_source/include/block_words.h"
|
||||
#include "word_registry.h"
|
||||
#include "freestanding/stdio.h"
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
@@ -153,6 +154,87 @@ blkio_dev_t *sk_repl_get_attached_blk_dev(void) {
|
||||
return g_attached_blk_dev;
|
||||
}
|
||||
|
||||
/* Storage-attach messaging migration (Bob, 2026-09-07): Hera keeps
|
||||
* polling/sig-checking, but no longer registers a newly-attached drive
|
||||
* into the block subsystem herself -- that's Artemis's own domain now,
|
||||
* reached via a real message (HERA-BLK-ATTACH-REQ, artemis:init.4th)
|
||||
* instead of a direct blk_subsys_attach_device() call. Hera cannot use
|
||||
* her own MSG-SEND for the outbound leg (kernel_main.c's own comment,
|
||||
* ~line 784: loading common:messaging.4th into her dictionary was
|
||||
* already tried and confirmed to silently drop every colon-definition
|
||||
* touching a STADIUM-* primitive) -- she uses VM-EXEC directly instead,
|
||||
* the same mechanism she already pumps MSG-TICK through. The reply
|
||||
* leg needs no such workaround: Artemis's own MSG-TICK delivers her
|
||||
* ack via VM-EXEC into Hera, which only requires BLK-ATTACH-ACK below
|
||||
* to exist as an ordinary word here -- not a full messaging vocabulary.
|
||||
*
|
||||
* usb_blk_dev_slots/usb_blk_dev_slot_count were function-local statics
|
||||
* inside sk_repl_idle() until now -- promoted to file scope so
|
||||
* sk_word_blk_attach_ack() below (a real dictionary word, called from a
|
||||
* completely different call stack than the idle loop) can resolve an
|
||||
* incoming ack's raw pointer back to the slot it belongs to. */
|
||||
static blkio_dev_t *g_usb_blk_dev_slots = (void *)0;
|
||||
static uint32_t g_usb_blk_dev_slot_count = 0;
|
||||
|
||||
/* One pending entry per slot, indexed the same way msc_slots[]/
|
||||
* usb_blk_dev_slots[] already are (index 0 unused, matches precedent).
|
||||
* Holds the sig-check result from the moment the storage-attach request
|
||||
* was sent, so the deferred Zuse/WIREBIND birth calls -- which need that
|
||||
* result -- can run once Artemis's ack confirms storage succeeded,
|
||||
* without re-reading the drive a second time. */
|
||||
typedef struct {
|
||||
int pending;
|
||||
homeblocks_sig_result_t sig_rc;
|
||||
homeblocks_sig_t sig;
|
||||
} sk_blk_attach_pending_t;
|
||||
static sk_blk_attach_pending_t *g_blk_attach_pending = (void *)0;
|
||||
|
||||
/* BLK-ATTACH-ACK ( dev-addr ok? -- ): VM-EXEC'd into Hera by Artemis's
|
||||
* own MSG-TICK once HERA-BLK-ATTACH-REQ's BLK-ATTACH call resolves.
|
||||
* Finds which slot the raw pointer belongs to, and -- only on success --
|
||||
* runs the same Zuse/WIREBIND attach logic sk_repl_idle() used to run
|
||||
* immediately and synchronously, now deferred until storage is
|
||||
* confirmed ("wait for ack, safer for identity data" -- Bob, 2026-09-07).
|
||||
* On failure, logs the same error sk_repl_idle() already logged for a
|
||||
* failed blk_subsys_attach_device() call, and simply never births
|
||||
* anything for this attach. */
|
||||
static void sk_word_blk_attach_ack(VM *vm) {
|
||||
if (vm->dsp < 1) { vm->error = 1; return; }
|
||||
cell_t ok_flag = vm_pop(vm);
|
||||
cell_t dev_addr = vm_pop(vm);
|
||||
blkio_dev_t *dev = (blkio_dev_t *)(uintptr_t)dev_addr;
|
||||
|
||||
if (!g_usb_blk_dev_slots || !g_blk_attach_pending) return;
|
||||
|
||||
uint32_t found_slot = 0;
|
||||
for (uint32_t i = 1; i < g_usb_blk_dev_slot_count; i++) {
|
||||
if (&g_usb_blk_dev_slots[i] == dev) { found_slot = i; break; }
|
||||
}
|
||||
if (found_slot == 0 || !g_blk_attach_pending[found_slot].pending) return;
|
||||
g_blk_attach_pending[found_slot].pending = 0;
|
||||
|
||||
if (!ok_flag) {
|
||||
log_message(LOG_ERROR, "xhci: USB MSC block-subsystem attach failed");
|
||||
return;
|
||||
}
|
||||
|
||||
xhci_dev_t *xdev = xhci_get_dev();
|
||||
xhci_msc_slot_t *ms = xdev ? xhci_msc_slot_for(xdev, found_slot) : (void *)0;
|
||||
if (ms) ms->bot_msc_attached = 1;
|
||||
g_attached_blk_dev = dev;
|
||||
|
||||
homeblocks_sig_result_t sig_rc = g_blk_attach_pending[found_slot].sig_rc;
|
||||
homeblocks_sig_t sig = g_blk_attach_pending[found_slot].sig;
|
||||
capsule_zuse_boot_try_attach(dev, sig_rc, &sig, (VM *)sk_get_mama_vm());
|
||||
if (sig_rc == HOMEBLOCKS_SIG_OK) {
|
||||
capsule_wirebind_try_attach(dev, &sig, (VM *)sk_get_mama_vm());
|
||||
}
|
||||
}
|
||||
|
||||
void sk_repl_register_words(VM *vm) {
|
||||
register_word(vm, "BLK-ATTACH-ACK", sk_word_blk_attach_ack);
|
||||
}
|
||||
|
||||
/*===========================================================================
|
||||
* Idle heartbeat service
|
||||
*
|
||||
@@ -261,22 +343,24 @@ static void sk_repl_idle(VM *active_vm)
|
||||
* serviced this tick, not just one -- a single `if` here used to mean
|
||||
* a second device's pending flag would sit unnoticed until the first's
|
||||
* flag was consumed and cleared. */
|
||||
static blkio_dev_t *usb_blk_dev_slots = (void *)0;
|
||||
static uint32_t usb_blk_dev_slot_count = 0;
|
||||
if (xdev && (!usb_blk_dev_slots || usb_blk_dev_slot_count < xdev->max_slots + 1)) {
|
||||
if (xdev && (!g_usb_blk_dev_slots || g_usb_blk_dev_slot_count < xdev->max_slots + 1)) {
|
||||
size_t bytes = (size_t)(xdev->max_slots + 1) * sizeof(blkio_dev_t);
|
||||
blkio_dev_t *fresh = (blkio_dev_t *)kmalloc_aligned(bytes, 64);
|
||||
if (fresh) {
|
||||
size_t pending_bytes = (size_t)(xdev->max_slots + 1) * sizeof(sk_blk_attach_pending_t);
|
||||
sk_blk_attach_pending_t *fresh_pending = (sk_blk_attach_pending_t *)kmalloc_aligned(pending_bytes, 64);
|
||||
if (fresh && fresh_pending) {
|
||||
memset(fresh, 0, bytes);
|
||||
usb_blk_dev_slots = fresh;
|
||||
usb_blk_dev_slot_count = xdev->max_slots + 1;
|
||||
memset(fresh_pending, 0, pending_bytes);
|
||||
g_usb_blk_dev_slots = fresh;
|
||||
g_usb_blk_dev_slot_count = xdev->max_slots + 1;
|
||||
g_blk_attach_pending = fresh_pending;
|
||||
}
|
||||
}
|
||||
for (uint32_t slot_id = 1; xdev && usb_blk_dev_slots && slot_id <= xdev->max_slots; slot_id++) {
|
||||
for (uint32_t slot_id = 1; xdev && g_usb_blk_dev_slots && slot_id <= xdev->max_slots; slot_id++) {
|
||||
xhci_msc_slot_t *ms = xhci_msc_slot_for(xdev, slot_id);
|
||||
if (!ms || !ms->bot_msc_attach_pending) continue;
|
||||
ms->bot_msc_attach_pending = 0;
|
||||
blkio_dev_t *usb_blk_dev = &usb_blk_dev_slots[slot_id];
|
||||
blkio_dev_t *usb_blk_dev = &g_usb_blk_dev_slots[slot_id];
|
||||
|
||||
int rc = blkio_usb_open_msc(usb_blk_dev, xdev, slot_id);
|
||||
if (rc == 0) {
|
||||
@@ -330,33 +414,41 @@ static void sk_repl_idle(VM *active_vm)
|
||||
break;
|
||||
}
|
||||
|
||||
/* FABRIC-2.md §F.20/§F.21: Zuse is thumbdrive-resident now,
|
||||
* not system-resident -- this is the only point in the boot
|
||||
* lifecycle a just-attached drive's sig result is known, so
|
||||
* genesis-mint/attach-authenticate has to happen from here,
|
||||
* not as a one-shot kernel_main.c step (a thumbdrive can't
|
||||
* be detected before the REPL's own idle polling exists to
|
||||
* detect it). No-ops immediately if Zuse already has a real
|
||||
* identity this boot. */
|
||||
capsule_zuse_boot_try_attach(usb_blk_dev, sig_rc, &sig, (VM *)sk_get_mama_vm());
|
||||
/* FABRIC-2.md §F.20/§F.21 / §F.5/§F.23 (WIREBIND): Zuse
|
||||
* genesis-mint/attach-authenticate and regular-identity
|
||||
* verify-then-birth-then-pair both used to run synchronously,
|
||||
* right here, before storage was even registered. Moved
|
||||
* (Bob, 2026-09-07, "wait for ack, safer for identity data")
|
||||
* to sk_word_blk_attach_ack() above, run only once Artemis
|
||||
* confirms the storage-attach succeeded -- identity birth
|
||||
* no longer happens on top of storage that might not have
|
||||
* registered. Stash what that deferred call needs. */
|
||||
if (g_blk_attach_pending) {
|
||||
g_blk_attach_pending[slot_id].pending = 1;
|
||||
g_blk_attach_pending[slot_id].sig_rc = sig_rc;
|
||||
g_blk_attach_pending[slot_id].sig = sig;
|
||||
}
|
||||
|
||||
/* FABRIC-2.md §F.5/§F.23 (WIREBIND): the real thumbdrive-
|
||||
* attach call site for a regular (non-Zuse) identity --
|
||||
* verify-then-birth-then-pair, replacing the RUNCAP-TEST/
|
||||
* PAIR-TEST diagnostic words that exercised each piece by
|
||||
* hand. Only meaningful for a drive that actually checked
|
||||
* out (HOMEBLOCKS_SIG_OK); capsule_wirebind_try_attach()
|
||||
* itself no-ops for a genesis-mode Zuse drive (no cert
|
||||
* region) or before Zuse has authenticated this boot. */
|
||||
if (sig_rc == HOMEBLOCKS_SIG_OK) {
|
||||
capsule_wirebind_try_attach(usb_blk_dev, &sig, (VM *)sk_get_mama_vm());
|
||||
/* Storage-attach registration (blk_subsys_attach_device(),
|
||||
* BLK-ATTACH C primitive) is Artemis's own domain now, not
|
||||
* Hera's -- she keeps polling/sig-checking but no longer
|
||||
* performs this step herself. Hera can't use her own
|
||||
* MSG-SEND (see g_usb_blk_dev_slots's own doc comment
|
||||
* above for why), so this is a direct VM-EXEC into
|
||||
* Artemis's dictionary -- the same mechanism the MSG-TICK
|
||||
* pump below already uses -- rather than a real enqueued
|
||||
* message. HERA-BLK-ATTACH-REQ (capsules/artemis/init.4th)
|
||||
* runs BLK-ATTACH then replies via her own real MSG-SEND,
|
||||
* delivered back to Hera by the ordinary MSG-TICK pump. */
|
||||
{
|
||||
char cmd[96];
|
||||
int n = snprintf(cmd, sizeof(cmd),
|
||||
"S\" %llu HERA-BLK-ATTACH-REQ\" S\" Artemis\" VM-EXEC",
|
||||
(unsigned long long)(uintptr_t)usb_blk_dev);
|
||||
if (n > 0 && (size_t)n < sizeof(cmd)) {
|
||||
vm_interpret((VM *)sk_get_mama_vm(), cmd);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (rc == 0 && blk_subsys_attach_device(usb_blk_dev) == BLK_OK) {
|
||||
ms->bot_msc_attached = 1;
|
||||
g_attached_blk_dev = usb_blk_dev;
|
||||
} else {
|
||||
log_message(LOG_ERROR, "xhci: USB MSC block-subsystem attach failed");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -369,11 +461,11 @@ static void sk_repl_idle(VM *active_vm)
|
||||
* block_subsystem.c (see bot_msc_detach_pending's own doc comment).
|
||||
* Per-slot loop now (FABRIC-3.md §VII, 2026-09-05), same reasoning as
|
||||
* the attach loop above. */
|
||||
for (uint32_t slot_id = 1; xdev && usb_blk_dev_slots && slot_id <= xdev->max_slots; slot_id++) {
|
||||
for (uint32_t slot_id = 1; xdev && g_usb_blk_dev_slots && slot_id <= xdev->max_slots; slot_id++) {
|
||||
xhci_msc_slot_t *ms = xhci_msc_slot_for(xdev, slot_id);
|
||||
if (!ms || !ms->bot_msc_detach_pending) continue;
|
||||
ms->bot_msc_detach_pending = 0;
|
||||
blkio_dev_t *usb_blk_dev = &usb_blk_dev_slots[slot_id];
|
||||
blkio_dev_t *usb_blk_dev = &g_usb_blk_dev_slots[slot_id];
|
||||
|
||||
blk_subsys_detach_device(usb_blk_dev);
|
||||
if (g_homeblocks_dev == usb_blk_dev) {
|
||||
|
||||
Reference in New Issue
Block a user