feat(v4.0.0): every node asks the kernel for its blocks; a born node is not POSTed

A block is a kernel request, as ENGINE.md 3.3 has it: the node puts the
block's number and the address of 256 cells on its stack and writes the
request to port 0, and the kernel leaves the status there.  The requests
are -1, read, and -2, write, the same for every node.  v4/system/blocks.c
serves them from the kernel's block subsystem, which is v3's.  The four
storage registers are gone from the engine.

The device that spoke block messages (4a505a15) is withdrawn with its
test and its message types: Captain Bob ruled on 2026-10-07 that it, a
node's own drive, and nodes with no storage had left the OS as designed
(docs/v4.0.0/MESH.md 8.5).

Hera no longer sends POST to the nodes she births: POST is the kernel's,
once.  Every node has its kernel on port 0; it serves a node's blocks and,
for Hera alone, her requests for nodes and capsules.

Bare metal: the node boots and is POSTed against POST's own block RAM,
and the kernel's chain -- fast RAM, the ramdrive, the virtio disk -- is
set up after POST and before the prompt, as on the v3 path.  The disk is
read and not written: nothing in v4 yet gives the owner's word that it
may be formatted.  A hosted program has the chain's fast RAM, as hosted
v3 has with no disk.  Error 17 is Storage refused.

make -C v4 test and sanitize pass at both widths; hosted-check passes on
three ISAs; amd64, aarch64 and riscv64 boot, POST 538 of 538, with the
typed session: logs/20261007-081603, -081839, -082226.  The hashes are
the same on all six.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
rajames
2026-10-07 08:24:47 -04:00
co-authored by Claude Opus 5.5
parent 26a0748455
commit d5b7235464
34 changed files with 953 additions and 725 deletions
+41 -2
View File
@@ -459,6 +459,45 @@ void kernel_main(BootInfo *boot_info) {
kernel_main_deep(boot_info);
}
#ifdef STARFORTH_V4
/* THE BLOCK CHAIN, for the v4 node. It asks this kernel for its blocks
* (v4/include/v4/blocks.h, docs/v4.0.0/MESH.md 8.3). The chain is set up
* with the calls the v3 path makes and in its order -- fast RAM and the
* ramdrive, then PCI, then the virtio disk -- and, as there, after POST.
* What the v3 path does next with that disk is not done here, because it is
* Artemis's and Zuse's and v4 has neither yet: the genesis signature,
* Zuse's root key, and the owner's word that the disk may be formatted.
* Until an owner gives that word the subsystem reads the disk and will not
* write it. */
static BootInfo *sk_v4_boot_info;
static void sk_v4_block_chain(void)
{
const size_t ram_size = (size_t)BLK_RAM_BLOCKS * BLK_FORTH_SIZE, krd_size = 1024u * 1024u;
uint8_t *blk_ram = (uint8_t *)kmalloc(ram_size);
uint8_t *krd = (uint8_t *)kmalloc(krd_size);
static blkio_dev_t artemis_dev;
size_t i;
if (!blk_ram || !krd) {
console_println("StarForth v4: no memory for the block chain");
for (;;) { }
}
for (i = 0; i < krd_size; i++) krd[i] = 0;
if (capsule_blk_init(NULL, blk_ram, ram_size, krd) != 0) {
console_println("StarForth v4: the block chain could not be set up");
for (;;) { }
}
console_println("PCI: init...");
pci_init(sk_v4_boot_info->acpi_table);
if (virtio_blk_find_artemis(&artemis_dev) == 0) {
console_println("Artemis: virtio-blk attached");
blk_subsys_attach_device(&artemis_dev);
} else {
console_println("Artemis: no virtio-blk disk");
}
}
#endif
/**
* @brief Deep kernel initialisation — M5 heartbeat, M7 VM bootstrap, and REPL.
*
@@ -519,8 +558,8 @@ static void kernel_main_deep(BootInfo *boot_info) {
/* StarForth v4 at a single prompt (Kconfig STARFORTH_V4): one host node
* of the F18-derived engine, in place of the v3 VM and everything below.
* It does not return. */
(void)boot_info;
sk_v4_run();
sk_v4_boot_info = boot_info;
sk_v4_run(sk_v4_block_chain);
#endif
#ifdef STARFORTH_ENABLE_VM
+10 -4
View File
@@ -20,17 +20,21 @@
#include "starkernel/console.h"
#include "starkernel/arch.h"
#include "v4/boot.h"
#include "block_subsystem.h"
#define SK_V4_BLOCKS 64u
#define SK_V4_LINE 255u /* what the line editor here takes */
static v4_node sk_v4_node;
static v4_exec_state sk_v4_es;
static v4_heat sk_v4_heat;
static unsigned char sk_v4_disk[SK_V4_BLOCKS * V4_BLOCK_BYTES];
static char sk_v4_text[SK_V4_LINE + 1u];
/* POST's block RAM, as the v3 path has (sk_vm_bootstrap.c, sk_post_blk_ram):
* the node boots and is POSTed with these blocks, 1 to 2047 and nothing
* above them, and the kernel's real chain is set up afterwards. */
static uint8_t sk_v4_post_blk_ram[BLK_RAM_BLOCKS * BLK_FORTH_SIZE];
static void sk_v4_out(const char *text, unsigned len)
{
unsigned i;
@@ -78,7 +82,7 @@ static unsigned sk_v4_readline(void)
}
}
void sk_v4_run(void)
void sk_v4_run(void (*chain)(void))
{
v4_boot boot;
@@ -86,10 +90,12 @@ void sk_v4_run(void)
boot.n = &sk_v4_node; boot.es = &sk_v4_es; boot.h = &sk_v4_heat; boot.im = &v4_capsule_image;
boot.out = sk_v4_out; boot.key = sk_v4_key;
boot.words = sk_v4_words; boot.word_count = sizeof sk_v4_words / sizeof sk_v4_words[0]; boot.serve = sk_v4_serve;
if (!v4_boot_run(&boot, sk_v4_disk, SK_V4_BLOCKS)) {
blk_subsys_init(sk_v4_post_blk_ram, sizeof(sk_v4_post_blk_ram));
if (!v4_boot_run(&boot)) {
console_println("StarForth v4: not started");
for (;;) { }
}
if (chain) chain();
/* The prompt is the host's: read a line, hand it to the node, say how it
* ended. */