Files
LithosAnanake/Kconfig.kernel
T
Robert Allan JamesandClaude Sonnet 5 00e657019e stadium: make VM population bound RAM-derived, not a static array of 4
Replaces STADIUM_MAX_VM_COUNT (Kconfig, hardcoded default 4) with a
boot-time computation, mirroring the pattern stadium_boot_init() already
used for the cell pool. New Kconfig STADIUM_VM_MEMORY_PERCENT (default
50): max_vm_count = (kmalloc_get_stats().free_bytes after the cell array
* STADIUM_VM_MEMORY_PERCENT / 100) / VM_MEMORY_SIZE, floored to 1, no
ceiling (population is not knowable in advance - could be 4, could be
4000). stadium_quotas and word_slots (plus stat_promotions/stat_evictions)
are now kmalloc'd to the computed count instead of declared with a macro.
New accessor stadium_max_vm_count() replaces every STADIUM_MAX_VM_COUNT
reference, including capsule_birth.c's birth-refusal gate.

Two things found and fixed along the way:

- The existing cell-pool budget was sourced from pmm_get_stats(), which
  reflects physical pages PMM hasn't handed to any subsystem yet - but
  the actual allocation is kmalloc(), which draws from the separate,
  fixed-size heap kmalloc_init() (M6) already carved out of PMM before
  stadium_boot_init() ever runs. Budgeting against PMM's leftover and
  allocating from the kmalloc heap are two different pools. Both the
  cell budget and the new VM-count budget now source from
  kmalloc_get_stats() instead.

- stadium_owner[] (which VM's quota owns each cell) was uint8_t, capped
  at 255 slots by a compile-time assert tied to the old macro. Widened
  to uint16_t (65535 slots of headroom) with a runtime clamp + log if
  the computed count ever exceeds that, since there's no ceiling anymore.

Three-arch QEMU acceptance: all clean to ok>, computed VM count genuinely
differs by actual available RAM (amd64/riscv64: 50 slots at -m 1024,
aarch64: 101 slots), Stadium conservation invariant identical across all
three (resident_sum=43691 reservoir=21845 sum=65536).
logs/20260815-080526/amd64, logs/20260815-080826/aarch64,
logs/20260815-080952/riscv64.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-15 08:11:21 -04:00

126 lines
5.9 KiB
Plaintext

menu "Kernel-only options"
if STARFORTH_VARIANT_KERNEL
config STARFORTH_ENABLE_VM
bool "Enable StarForth VM integration, M7 milestone (STARFORTH_ENABLE_VM)"
default y
help
Compiles the full StarForth VM source tree into the kernel image
and enables capsule birth/execution. Disabling this builds a
kernel that only reaches the M0-M6 hardware milestones (console,
PMM, VMM, interrupts, timers, kmalloc) with no FORTH interpreter,
no capsules, no "ok" REPL. Gates a large source-file selection
block in Makefile.starkernel, not just a handful of -D flags.
config PARITY_MODE
bool "Deterministic parity harness mode (PARITY_MODE)"
default n
help
Enables the parity/determinism verification harness used to
compare dict_hash and capsule state across independent runs.
Off by default (normal boot); on for parity-campaign builds.
config SK_PARITY_DEBUG
bool "Verbose parity/vocabulary debug logging (SK_PARITY_DEBUG)"
default n
help
Extra diagnostic logging in vocabulary_words.c and
vm_bootstrap.c's parity paths (src/starkernel/vm/vm_internal.h
guards these with #if defined(__STARKERNEL__) && SK_PARITY_DEBUG).
Previously opt-in-only via VM_FEATURE_FLAG_VARS with no Kconfig
presence at all; promoted here for discoverability, same
treatment as every other previously-unwired constant in this
migration.
config STADIUM_VM_MEMORY_PERCENT
int "Percent of remaining kmalloc heap the outer Stadium budgets for VM population (STADIUM_VM_MEMORY_PERCENT)"
default 50
help
Replaces the old fixed STADIUM_MAX_VM_COUNT bound (Captain Bob,
2026-08-15: a hardcoded population ceiling cannot be right when the
actual population is unknowable in advance -- could be 4, could be
4000). The outer Stadium's VM population bound is now computed at
boot, the same way the cell array already is (STADIUM_MEMORY_PERCENT
below): this percentage of the kmalloc heap's remaining free bytes
(kmalloc_get_stats(), taken AFTER the cell array's own allocation),
divided by VM_MEMORY_SIZE (5 MiB, include/vm.h), floored to 1 so Hera
can always boot. No upper ceiling -- birth is refused once the
computed bound is reached (FABRIC.md item 1.5's refusal behaviour is
unchanged), it just isn't a compile-time guess anymore. Default of
50% is an untuned placeholder, not a derived optimum, same DoE-later
treatment as STADIUM_MEMORY_PERCENT.
config STADIUM_CONTAINS_DEPTH_MAX
int "Patron containment chain depth cap (STADIUM_CONTAINS_DEPTH_MAX)"
default 5
help
Hard bound on how many patrons deep a `contains` chain (FABRIC.md
item 1.1, the ninth cell wire) may nest. A patron with a non-none
`contains` link cannot be reaped -- reap-gating enforcement of
this bound is item 3.5's scope, not yet implemented. Distinct
from the already-implemented VM-Stadium nesting depth (item 1.7,
default 2): that bounds VMs nested inside VMs, this bounds
patrons held inside patrons within one Stadium.
config STADIUM_CAPACITY_TICK
int "Capacity arbitration cadence, in virtual ticks (STADIUM_CAPACITY_TICK)"
default 1000
help
How often Hera re-evaluates capacity transfers between VMs
(FABRIC.md item 1.4), expressed in virtual ticks -- never
wall-clock. Default matches the existing precedent at
capsule_vm_physics.c's vm_physics_heartbeat_tick()
(HEARTBEAT_INFERENCE_FREQUENCY, also 1000), comfortably past
the "order of magnitude apart from the heat tick" minimum
(FABRIC.md §22.4). No consumer yet -- capacity arbitration
itself is not yet on the punch list.
config STADIUM_MEMORY_PERCENT
int "Percent of free physical memory the Stadium claims at boot (STADIUM_MEMORY_PERCENT)"
default 1
help
The Stadium's global cell array is sized at boot from
pmm_get_stats().free_bytes, taken at the point of allocation
(FABRIC.md item 3.2, §17.6 position (b): "sized at boot from the
memory budget", not a hardcoded cell count). This is the fraction
of that free-byte figure the array claims, rounded down to whole
64-byte cells. Default of 1% is conservative -- comfortably clears
the ~4096-cells-per-VM illustrative figure in FABRIC.md §23.3
against a QEMU -m 1024 test config while leaving the kernel heap
and everything else nearly all of physical memory.
config STADIUM_WORD_HEAT_QUANTUM
int "Q48.16 heat quantum moved per word touch/starter-grant (STADIUM_WORD_HEAT_QUANTUM)"
default 2048
help
FABRIC.md §17.7 (item 4.1): the fixed Q48.16 amount transferred between
a VM's Stadium reservoir and a word patron's cell on every touch
(already-resident) or starter-grant admission attempt (non-resident,
Option B). Q48_ONE is 65536; the default of 2048 is Q48_ONE divided by
HOTWORDS_CACHE_SIZE (32) -- the population of the cache mechanism this
item retires under __STARKERNEL__ -- so roughly 32 words could hold a
"fully loaded" starter share at once, matching the old cache's slot
count. An untuned placeholder, not a derived optimum: real tuning is
DoE work (item 5.1), same treatment as STADIUM_MEMORY_PERCENT above.
config STADIUM_WORD_COOL_RATE_Q48
int "Q48.16 fraction of resident heat removed per tick (STADIUM_WORD_COOL_RATE_Q48)"
default 21845
help
FABRIC.md §17.7 (item 4.1): redirects Loop #3's decay shape onto
Stadium word-patron heat instead of discarding it -- cooled heat
returns to the VM's reservoir rather than vanishing, so this must be a
fraction of the patron's OWN current heat removed per elapsed tick
(unit-safe for a conserved share of 1.0), not a flat per-tick amount
the way execution_heat's own decay works. Default reuses
INITIAL_DECAY_SLOPE_Q48's numeric value (21845, ~1/3) reinterpreted as
this fraction -- the existing inference engine converged on that
magnitude for the analogous cooling purpose on execution_heat, so it
is a reasonable starting point, not the same quantity. Untuned
placeholder: real tuning is DoE work (item 5.1).
endif # STARFORTH_VARIANT_KERNEL
endmenu