Source tree reorganization: - Move StarForth v3 engine to v3/ (src/, include/, Makefile) - Move kernel to kernel/ (src/, include/, linker/, Makefile) - Create v4/ skeleton for F18-ISA golden model (DECOMPOSITION.md, JUSTIFICATION.md) - Move FABRIC-0..4.md to docs/fabric/ - Move ONTOLOGY.md and ROADMAP.md to docs/ Board infrastructure: - Add boards/ser5/, boards/raspi/, boards/milkv/, boards/zynq7020/ - Each board has board.mk (ISA, CPU flags, boot recipe) and README.md - Root Makefile becomes thin dispatcher: boot_image, all, clean, docs take TARGET - make boot_image TARGET=SER5|RASPI|MILKV builds one GPT/MBR image per board - ZYNQ7020 target exists but stops with clear error (ARMv7 port not built yet) - scripts/mkdiskimage.sh builds disk images for all boards Docs pipeline: - docs/book/ with LaTeX master (main.tex) and Makefile - pandoc converts Markdown to LaTeX at build time - Two Lua filters: table-widths.lua (wide tables wrap), code-breaks.lua (inline code breaks) - make docs builds single PDF (754 pages, 0 missing characters) - make docs TARGET=<board> adds board appendix - build/docs/<book|board>/meta.tex stamps git commit into PDF Bug fixes: - 42 include paths that only worked by accident now use correct relative paths - clang-18 hardcode replaced with configurable CC variable (fixed aarch64 build) - Pi 5: kernel_2712.img linked at 0x80000, .bss zeroed, memory reserved - Doxyfile, .clang-tidy, README.md, Kconfig paths updated Verified: - Hosted v3 build passes 1012 tests, 0 failures - SER5 image boots in QEMU (OVMF), POST passes, K exact (65536 = Q48_ONE) - Milk-V image boots in QEMU (OpenSBI + U-Boot + bootefi), POST passes - make clean TARGET=<board> removes only that board and its ISA objects - make all builds all boards, hosted v3, and docs in one run Co-authored-by: Junie <junie@jetbrains.com>
125 lines
5.7 KiB
C
125 lines
5.7 KiB
C
/*
|
||
StarForth — Steady-State Virtual Machine Runtime
|
||
|
||
Copyright (c) 2023–2025 Robert A. James
|
||
All rights reserved.
|
||
|
||
This file is part of the StarForth project.
|
||
|
||
Licensed under the StarForth License, Version 1.0 (the "License");
|
||
you may not use this file except in compliance with the License.
|
||
|
||
You may obtain a copy of the License at:
|
||
https://github.com/star.4th@proton.me/StarForth/LICENSE.txt
|
||
|
||
This software is provided "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||
express or implied, including but not limited to the warranties of
|
||
merchantability, fitness for a particular purpose, and noninfringement.
|
||
|
||
See the License for the specific language governing permissions and
|
||
limitations under the License.
|
||
|
||
*/
|
||
|
||
/**
|
||
* stadium_blocks.h - Block patrons on the Stadium (FABRIC-2.md §B/§D,
|
||
* MIGRATE punch-list item)
|
||
*
|
||
* The block-specific layer on top of the generic L0 engine (stadium.h), same
|
||
* relationship stadium_words.h/.c already has: nothing in stadium.c/.h knows
|
||
* a block patron exists -- it only ever sees cell_index, VMUuid, and
|
||
* StadiumPatronHeader. This file is where "block" becomes a concrete
|
||
* meaning: an (owning quota slot, LBN) -> cell_index map, the starter-grant
|
||
* admission rule (mirrors stadium_word_dispatch()'s Option B exactly), and
|
||
* the reservoir-quantum touch/cool that feeds and drains a resident block's
|
||
* Stadium heat.
|
||
*
|
||
* Unlike words, LBN is not densely bounded (block_subsystem.c's unified LBN
|
||
* space spans RAM/RAMDRIVE/DISK/USB and can be large), so the map here is a
|
||
* fixed-capacity open-addressing hash table sized off stadium_cell_count()
|
||
* at init, not a dense per-VM array -- see stadium_blocks.c for the layout.
|
||
* A block's actual 1024 content bytes are never copied into a Stadium cell;
|
||
* they stay exactly where block_subsystem.c already keeps them. The cell
|
||
* only ever carries identity (the LBN) and heat/bookkeeping, same as a word
|
||
* patron's cell never carries the word's own dictionary entry.
|
||
*/
|
||
|
||
#ifndef STARKERNEL_VM_STADIUM_BLOCKS_H
|
||
#define STARKERNEL_VM_STADIUM_BLOCKS_H
|
||
|
||
#ifdef __STARKERNEL__
|
||
|
||
#include <stdint.h>
|
||
#include "starkernel/vm_uuid.h"
|
||
|
||
/*
|
||
* stadium_blocks_init - Allocates and zeroes the (quota slot, LBN) ->
|
||
* cell_index hash table (capacity computed from stadium_cell_count() *
|
||
* STADIUM_BLOCK_TRACK_CAP_MULT at call time, kmalloc'd). Must be called
|
||
* after stadium_boot_init() -- so stadium_cell_count() is non-zero -- and
|
||
* before any block ever dispatches; the real boot site is immediately after
|
||
* the existing stadium_words_init() call (kernel_main.c), same M7/M7.1
|
||
* ordering. Not safe to call twice -- guarded internally as a no-op if
|
||
* already initialized, same convention as stadium_words_init().
|
||
*/
|
||
void stadium_blocks_init(void);
|
||
|
||
/*
|
||
* stadium_block_dispatch - The per-touch entry point, called from
|
||
* block_word_block()/block_word_buffer()/block_word_update()
|
||
* (src/word_source/block_words.c) -- mirroring stadium_word_dispatch()'s
|
||
* call pattern and cooling/admission logic 1:1, keyed by LBN instead of
|
||
* word_id.
|
||
*
|
||
* If (vm_id, lbn) is already resident: applies the same redirected Loop #3
|
||
* cooling stadium_word_dispatch() applies (fraction of the cell's own
|
||
* current heat, scaled by elapsed_ticks since this block's own last touch --
|
||
* STADIUM_BLOCK_COOL_RATE_Q48), crediting the cooled amount back to vm_id's
|
||
* reservoir, then pulls STADIUM_BLOCK_HEAT_QUANTUM from the reservoir into
|
||
* the cell -- clamped to the reservoir's actual balance AND to the same
|
||
* Q48_ONE / 3 floor stadium_word_dispatch() enforces, so block-touch
|
||
* admission alone can never starve other reservoir consumers sharing the
|
||
* same VM.
|
||
*
|
||
* If not resident (or the table's entry is stale -- self-healing check
|
||
* against the cell's discriminator bit and identity, same pattern
|
||
* resolve_resident_cell() uses in stadium_words.c): attempts starter-grant
|
||
* admission -- pulls STADIUM_BLOCK_HEAT_QUANTUM (same floor), builds an
|
||
* unpinned MIGRATE candidate (identity = lbn, mass = 1, payload unused --
|
||
* the block's real content is never copied here), calls stadium_admit(). On
|
||
* refusal, pushes the pulled quantum back (rollback). On success, records
|
||
* the mapping. If the hash table itself is full and has no slot for this
|
||
* (vm_id, lbn) pair, this touch is silently skipped -- Stadium's own
|
||
* capacity already bounds real residency, so a table miss under load is
|
||
* graceful degradation, not an error.
|
||
*
|
||
* No-op if vm_id holds no Stadium quota, or stadium_blocks_init() has not
|
||
* run.
|
||
*
|
||
* @param vm_id Owning VM -- vm->stadium_vm_id at every call site,
|
||
* same quota-isolation reasoning stadium_word_
|
||
* dispatch() already documents (LBN numbering is
|
||
* global, not per-VM, but quota scoping still keeps
|
||
* two VMs' admissions from evicting each other).
|
||
* @param lbn Logical block number being touched.
|
||
* @param heartbeat_ticks Current vm->heartbeat.tick_count.
|
||
*/
|
||
void stadium_block_dispatch(VMUuid vm_id, uint32_t lbn, uint64_t heartbeat_ticks);
|
||
|
||
/*
|
||
* stadium_blocks_print_boot_diagnostics - Console output mirroring
|
||
* stadium_words_print_boot_diagnostics(): promotions/evictions for vm_id's
|
||
* own block-touch table, plus a conservation check
|
||
* (Σ(resident block heat) + reservoir against Q48_ONE is NOT a standalone
|
||
* invariant here -- word-execution heat and any other resident shares the
|
||
* same reservoir, so this prints the block-only resident sum as a
|
||
* diagnostic term, not a claim that it alone should equal Q48_ONE).
|
||
*
|
||
* @param vm_id The VM whose block-touch table/reservoir to read.
|
||
*/
|
||
void stadium_blocks_print_boot_diagnostics(VMUuid vm_id);
|
||
|
||
#endif /* __STARKERNEL__ */
|
||
|
||
#endif /* STARKERNEL_VM_STADIUM_BLOCKS_H */
|