Console-VM + user-VM pair: real async message-passing relay
Console sessions now route through the same general VM-to-VM messaging system (Phase C) any VM can already use for its own reasons -- not a synchronous shortcut. Per direct instruction: real async MSG-SEND/ MSG-DELIVER (Option B), not a VM-EXEC-based synchronous relay, because messaging is a general capability, not a console-specific mechanism. New CONSOLE-CMD-EVENT message type (common:messaging.4th). New sk_repl_dispatch_line() (repl.c), called from both sk_repl_step and sk_repl_run in place of a direct vm_interpret(): if the active VM's own name has a live "<name>~user" counterpart registered, the raw input line is wrapped as an S"-embedded CONSOLE-CMD-EVENT MSG-SEND and interpreted on the console VM instead of being run directly -- the console's own next MSG-TICK (Hera's idle pump) delivers it into the paired user VM via VM-EXEC, same mechanism every other message already uses. Falls back to direct interpretation if there's no pairing, or if the line contains a `"` (known v1 limitation, warned about explicitly rather than silently mishandled). New capsule_console_birth() (capsule_console.h/.c): a bare VM whose only content is loading common:messaging.4th -- the console side of a pairing, parallel in shape to RUNCAP's user-VM birth but with fixed embedded content instead of a devblock read (no identity, no thumbdrive involved). New PAIR-TEST diagnostic word (mama_forth_words.c, matches RUNCAP-TEST's own precedent): births both halves of a pairing and registers the "<name>~user" mapping. Not the real pairing call site -- that's the eventual attach/onboarding flow -- this exists to exercise the relay live before that flow exists. Found and fixed a real, serious bug live: console_set_vm_name() stored the caller's raw pointer instead of copying it. mama_word_use() (USE) passes a VMRegistryEntry field living on its own stack frame -- once USE returns, that pointer dangles, corrupting every console tag after the first USE (observed directly as garbled "[[]" / binary-looking prefixes instead of "[CaptBob]"). Fixed at the source: console_set_ vm_name() now copies into internal storage. That surfaced a second, related bug across every console_get_vm_name()-based save/restore call site in mama_forth_words.c (BIRTH, VM-STEP, VM-EXEC, CONNECT-HERMES, CONNECT-ARTEMIS): saving just a pointer into the single internal buffer meant an intervening console_set_vm_name() call silently corrupted the saved value before the restore ever ran. New console_save_vm_name() copies into caller-owned storage; every save/restore site updated. Verified end-to-end, live in QEMU: typed WELCOME at a paired console VM -- it did not execute directly (no UNKNOWN WORD), printed ok immediately (queued, async), and on the next idle tick "[CaptBob~user] Minted identity -- default personality" appeared on its own -- genuine delivery and execution in the paired user VM through the real MSG-SEND/MSG-DELIVER pipeline. Console tags confirmed clean (no garbling) across all three architectures' full regression boot. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_019ZGkimpfyh63EZyRkNbkPD
This commit is contained in:
co-authored by
Claude Sonnet 5
parent
71b6937deb
commit
b0f12710bb
@@ -0,0 +1,47 @@
|
||||
/*
|
||||
StarForth — Steady-State Virtual Machine Runtime
|
||||
|
||||
Copyright (c) 2023–2025 Robert A. James
|
||||
All rights reserved.
|
||||
|
||||
Licensed under the StarForth License, Version 1.0
|
||||
*/
|
||||
|
||||
/**
|
||||
* capsule_console.h - Bare console-VM birth (FABRIC-3.md Phase F,
|
||||
* 2026-08-28): a minimal VM whose only job is loading
|
||||
* common:messaging.4th and being the physical REPL's relay target
|
||||
* (sk_repl_dispatch_line(), repl.c) for a paired user VM
|
||||
* (capsule_runcap_birth(), capsule_runcap.h). Not identity-bearing
|
||||
* content -- no thumbdrive read, fixed embedded source, same
|
||||
* heap-built-single-entry-directory shape RUNCAP already established
|
||||
* (§F.6/§F.18), just with compile-time content instead of a devblock
|
||||
* read.
|
||||
*/
|
||||
|
||||
#ifndef STARKERNEL_CAPSULE_CONSOLE_H
|
||||
#define STARKERNEL_CAPSULE_CONSOLE_H
|
||||
|
||||
#ifdef __STARKERNEL__
|
||||
|
||||
#include "starkernel/capsule_run.h"
|
||||
#include "starkernel/vm_uuid.h"
|
||||
|
||||
/**
|
||||
* capsule_console_birth - Birth a bare console VM.
|
||||
*
|
||||
* @param console_name Symbolic name for the new VM -- by convention
|
||||
* the same name a user's own identity uses (e.g.
|
||||
* "CaptBob"); sk_repl_dispatch_line() looks for a
|
||||
* live "<name>~user" counterpart to decide
|
||||
* whether a given active VM is a console.
|
||||
* @param out_vm_id Output: assigned VM ID.
|
||||
* @param out_vm_ctx Output: new VM context (may be NULL).
|
||||
* @return CAPSULE_RUN_OK on success, error code otherwise.
|
||||
*/
|
||||
CapsuleRunResult capsule_console_birth(const char *console_name,
|
||||
VMUuid *out_vm_id, void **out_vm_ctx);
|
||||
|
||||
#endif /* __STARKERNEL__ */
|
||||
|
||||
#endif /* STARKERNEL_CAPSULE_CONSOLE_H */
|
||||
@@ -54,6 +54,7 @@
|
||||
#define STARKERNEL_CONSOLE_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
#include "uefi.h"
|
||||
|
||||
/**
|
||||
@@ -141,11 +142,30 @@ int console_poll(void);
|
||||
/**
|
||||
* Set the active VM name shown as [Name] prefix on each output line.
|
||||
* Pass NULL to suppress the prefix (kernel-only output before any VM).
|
||||
* The pointer must remain valid for as long as it is active.
|
||||
* Copies into internal storage (FABRIC-3.md Phase F, 2026-08-28) -- the
|
||||
* caller's own pointer does not need to remain valid afterward.
|
||||
*/
|
||||
void console_set_vm_name(const char *name);
|
||||
const char *console_get_vm_name(void);
|
||||
|
||||
/**
|
||||
* console_save_vm_name - Copy the current active-VM name into the
|
||||
* caller's own buffer, for a later console_set_vm_name() restore.
|
||||
*
|
||||
* console_get_vm_name() alone is NOT safe for save-then-restore: it
|
||||
* returns a pointer into the single internal buffer console_set_vm_name()
|
||||
* copies into, so an intervening console_set_vm_name() call (the normal
|
||||
* "switch, do work, switch back" pattern every BIRTH/VM-EXEC/CONNECT-*
|
||||
* call site uses) overwrites the very bytes the saved pointer points at
|
||||
* before the restore ever runs -- found live 2026-08-28, the restore
|
||||
* silently no-ops. Copies at most cap-1 bytes plus a NUL terminator;
|
||||
* writes "" if there was no active name (NULL) to save.
|
||||
*
|
||||
* @param out Caller-owned buffer.
|
||||
* @param cap Its size in bytes.
|
||||
*/
|
||||
void console_save_vm_name(char *out, size_t cap);
|
||||
|
||||
/* Last FORTH word name set by the dispatcher before entry->func(vm).
|
||||
* Printed by the #GP fault handler to identify the faulting word. */
|
||||
extern volatile const char *g_sk_fault_word;
|
||||
|
||||
Reference in New Issue
Block a user