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>
This commit is contained in:
Robert Allan James
2026-08-15 08:11:21 -04:00
co-authored by Claude Sonnet 5
parent 154eddeab0
commit 00e657019e
16 changed files with 26118 additions and 127 deletions
+16 -10
View File
@@ -33,17 +33,23 @@ config SK_PARITY_DEBUG
treatment as every other previously-unwired constant in this
migration.
config STADIUM_MAX_VM_COUNT
int "Outer Stadium VM population bound (STADIUM_MAX_VM_COUNT)"
default 4
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
Hard bound on live VMs in the outer Stadium (FABRIC.md item 1.5).
Birth is refused once this many VMs are LIVE simultaneously; a
dead or stillborn VM's registry slot does not count against the
bound. Default of 4 matches Tripod's currently-known topology
(Hera + two Hermes instances + Artemis) -- an explicit placeholder
pending a DoE campaign to find an idealized default (item 5.1),
not a padded estimate.
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)"