feat(v4.0.0): the block words are the kernel's -- v3's way in full

Ruled 2026-10-07.  BLOCK, BUFFER, UPDATE, SAVE-BUFFERS and EMPTY-BUFFERS
are each one kernel request on port 0, by block number only.  The node
has a window of four slots in its memory, as a v3 VM has; the kernel
copies blocks into it, keeps the record of which block is in which slot,
and decides when a block is written (v4/system/blocks.c).  The node keeps
no record and gives the kernel no address, so a request cannot overwrite
the node's code.  When a block is written stays FORTH-79's: UPDATE marks
it.  When the chain of devices changes the slots are let go, as in v3.

The window is 512 cells more than the two buffers were; the dictionary
space ends that much lower, at 13824.

MESH.md 8.5 had said, from the review, that a v3 VM's BLOCK is the
kernel's buffer.  It is not, and the section now says what was reported,
what v3 does, and what was ruled.

make -C v4 test, sanitize and hosted-check pass; amd64, aarch64 and
riscv64 boot, POST 538 of 538, the same hashes on all six:
logs/20261007-092835, -093112, -093456.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
rajames
2026-10-07 09:37:30 -04:00
co-authored by Claude Opus 5.5
parent 7f4d946d2e
commit 9bfd5071d2
21 changed files with 991 additions and 330 deletions
+58 -19
View File
@@ -4,42 +4,81 @@
*
* A node only ever asks for a block by number, and it asks the kernel: a
* request written to the port where its kernel is, as any kernel word is.
* There are two, the same for every node,
* This is v3's way (v3/src/word_source/block_words.c). The node has a
* WINDOW in its memory, V4_BLOCK_SLOTS slots of 256 cells, as a v3 VM has
* four slots of 1 KiB at the top of its memory. The kernel keeps the
* record of which block is in which slot and does all the copying, and it
* writes into the window and nowhere else in the node. The requests, the
* same for every node:
*
* V4_REQ_BLOCK_READ ( n waddr -- status ) block n into the 256 cells at waddr
* V4_REQ_BLOCK_WRITE ( n waddr -- status ) block n from them
* V4_REQ_BLOCK ( n -- waddr status ) the slot that holds block n, read
* from storage if it is not in one
* V4_REQ_BUFFER ( n -- waddr status ) a slot for block n, of zeros if it
* is not in one: nothing is read
* V4_REQ_UPDATE ( -- status ) the block most recently asked for
* is marked changed
* V4_REQ_SAVE_BUFFERS ( -- status ) every block marked is written
* V4_REQ_EMPTY_BUFFERS ( -- ) every slot is let go; nothing is
* written
*
* and their numbers are below zero: the requests a host names for its own
* words (KERNEL-WORD) count up from 1. The status is 0, or
* V4_BLOCK_REFUSED -- the cells are not all in the node's memory, or
* storage will not have it, or the stack did not hold both arguments, in
* which case the status is all that is left on it -- or V4_BLOCK_RANGE,
* there is no such block.
* Their numbers are below zero: the requests a host names for its own
* words (KERNEL-WORD) count up from 1.
*
* waddr is the word address of the slot, or 0 when the status is not 0.
* The status is 0; or V4_BLOCK_RANGE, there is no such block; or
* V4_BLOCK_REFUSED: storage would not have a block that had to be written,
* the stack did not hold the request's argument, or the window is not all
* in the node's memory.
*
* WHEN A BLOCK IS WRITTEN is FORTH-79's: UPDATE marks it, and it is written
* by SAVE-BUFFERS or when its slot is wanted for another block. (v3's
* UPDATE copies the slot to the kernel at once; the standard is followed.)
* A slot whose block is not marked is taken before one whose block is. A
* block that storage would not take is let go of: its slot is empty.
*
* When the kernel's chain of devices changes, everything in the slots is
* let go and nothing of it is written, as v3 does (blk_vm_check_epoch).
*
* A block is 1024 bytes and 256 cells, four bytes to a cell, the first
* lowest, whatever the cell width: a read leaves the rest of each cell
* zero, and a write takes the low 32 bits.
* lowest, whatever the cell width: a block read leaves the rest of each
* cell zero, and a write takes the low 32 bits.
*
* The blocks are the kernel's block subsystem's (v3/src/block_subsystem.c):
* the device chain, the metadata and the map are its, as they were. Who
* may have which block is not checked here yet (MESH.md 8.4).
* The blocks are the kernel's block subsystem's (v3/src/block_subsystem.c).
* Who may have which block is not checked here yet (MESH.md 8.4).
*/
#ifndef V4_BLOCKS_H
#define V4_BLOCKS_H
#include "v4/node.h"
#define V4_REQ_BLOCK_READ (-1)
#define V4_REQ_BLOCK_WRITE (-2)
#define V4_REQ_BLOCK (-1)
#define V4_REQ_BUFFER (-2)
#define V4_REQ_UPDATE (-3)
#define V4_REQ_SAVE_BUFFERS (-4)
#define V4_REQ_EMPTY_BUFFERS (-5)
#define V4_BLOCK_OK 0
#define V4_BLOCK_REFUSED 2
#define V4_BLOCK_RANGE 3
/* If `request` is one of the two, serve it for the node, whose data stack
* holds its arguments and is left holding its status, and return 1.
#define V4_BLOCK_SLOTS 4u
/* What the kernel keeps for one node. */
typedef struct {
v4_cell window; /* word address of the first slot */
uint32_t block[V4_BLOCK_SLOTS]; /* the block in each slot; 0: none */
unsigned char changed[V4_BLOCK_SLOTS]; /* UPDATEd and not yet written */
unsigned next; /* where the search for a slot to take begins */
int last; /* the slot most recently asked for; -1: none */
uint64_t epoch; /* the chain as it was when the slots were filled */
} v4_blocks;
/* A node's window is at `window`, and nothing is in it. */
void v4_blocks_init(v4_blocks *w, v4_cell window);
/* If `request` is one of the five, serve it for the node and return 1.
* Otherwise touch nothing and return 0. The node is stopped, blocked at
* its port, when this is called. */
int v4_blocks_serve(v4_node *n, v4_cell request);
int v4_blocks_serve(v4_blocks *w, v4_node *n, v4_cell request);
#endif /* V4_BLOCKS_H */
+4
View File
@@ -54,6 +54,10 @@ typedef struct {
* that loads capsules when it boots sets them again when it has
* (v4_image_seal). */
v4_cell boot_cells, fence;
/* the block window: the word address of the slots the kernel copies
* blocks into (v4/blocks.h) */
v4_cell block_window;
} v4_image;
/* The description of the nucleus built from v4/capsule (the generated file