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:
co-authored by
Claude Opus 5.5
parent
7f4d946d2e
commit
9bfd5071d2
+58
-19
@@ -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 */
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user