From 5572e5e42985648a16a4d2a4b1ee45bb470441f5 Mon Sep 17 00:00:00 2001 From: Robert Allan James Date: Tue, 4 Aug 2026 13:30:06 -0400 Subject: [PATCH] WIP: item 2.2 -- bound the VM registry (not complete, do not check off) Partial work toward FABRIC.md punch list item 2.2. Adds the STADIUM_MAX_VM_COUNT Kconfig symbol (default 4, per item 1.5) wired through Makefile.starkernel, a new CAPSULE_RUN_ERR_FLEET_FULL result code, and a vm_registry_live_count() helper in capsule_birth.c that counts LIVE VMs only (distinct from the existing monotonic vm_registry_count, which never decrements on death). NOT YET DONE: nothing calls vm_registry_live_count() yet -- the actual birth-refusal check is not wired into capsule_birth_baby(). Not built, not boot-tested. FABRIC.md's item 2.2 checkbox is deliberately left unchecked; this commit exists only to save in-progress work before a pause, not to claim the item complete. Co-Authored-By: Claude Sonnet 5 --- Kconfig.kernel | 12 ++++++++++++ Makefile.starkernel | 3 ++- include/starkernel/capsule_run.h | 1 + src/starkernel/capsule/capsule_birth.c | 19 +++++++++++++++++++ 4 files changed, 34 insertions(+), 1 deletion(-) diff --git a/Kconfig.kernel b/Kconfig.kernel index 1d8bb77..ffbe2bc 100644 --- a/Kconfig.kernel +++ b/Kconfig.kernel @@ -42,6 +42,18 @@ config HEARTBEAT_DOE_LOG (experiments/bare_metal/). On by default; the DoE tooling expects this log to be present. +config STADIUM_MAX_VM_COUNT + int "Outer Stadium VM population bound (STADIUM_MAX_VM_COUNT)" + default 4 + 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. + endif # STARFORTH_VARIANT_KERNEL endmenu diff --git a/Makefile.starkernel b/Makefile.starkernel index 70c4a50..c551468 100644 --- a/Makefile.starkernel +++ b/Makefile.starkernel @@ -277,6 +277,7 @@ $(eval $(call kconfig_int,INITIAL_DECAY_SLOPE_Q48,21845)) $(eval $(call kconfig_int,DECAY_MIN_INTERVAL,500)) $(eval $(call kconfig_int,DECAY_RATE_PER_US_Q16,1)) $(eval $(call kconfig_int,HEARTBEAT_INFERENCE_FREQUENCY,1000)) +$(eval $(call kconfig_int,STADIUM_MAX_VM_COUNT,4)) $(eval $(call kconfig_int,SSM_ENTROPY_HIGH_THRESHOLD,0.75)) $(eval $(call kconfig_int,SSM_CV_HIGH_THRESHOLD,0.15)) $(eval $(call kconfig_int,SSM_TEMPORAL_DECAY_THRESHOLD,0.5)) @@ -320,7 +321,7 @@ VM_FEATURE_FLAG_VARS := \ HEARTBEAT_TICK_NS HEARTBEAT_INFERENCE_FREQUENCY \ HEARTBEAT_CHECK_FREQUENCY HEARTBEAT_WINDOW_TUNING_FREQUENCY \ HEARTBEAT_SLOPE_VALIDATION_FREQUENCY SK_PARITY_DEBUG \ - EMERGENCY_CONSOLE_ENABLED \ + EMERGENCY_CONSOLE_ENABLED STADIUM_MAX_VM_COUNT \ SSM_ENTROPY_HIGH_THRESHOLD SSM_CV_HIGH_THRESHOLD \ SSM_TEMPORAL_DECAY_THRESHOLD SSM_TEMPORAL_DECAY_LOW_THRESHOLD \ SSM_HYSTERESIS_TICKS \ diff --git a/include/starkernel/capsule_run.h b/include/starkernel/capsule_run.h index 2c44e42..2201b21 100644 --- a/include/starkernel/capsule_run.h +++ b/include/starkernel/capsule_run.h @@ -54,6 +54,7 @@ typedef enum { CAPSULE_RUN_ERR_EXEC_FAIL, /* Execution failed */ CAPSULE_RUN_ERR_HASH_MISMATCH, /* Post-run hash mismatch */ CAPSULE_RUN_ERR_STILLBORN, /* VM birth failed */ + CAPSULE_RUN_ERR_FLEET_FULL, /* Outer Stadium at STADIUM_MAX_VM_COUNT (FABRIC.md item 1.5/2.2) */ } CapsuleRunResult; /*=========================================================================== diff --git a/src/starkernel/capsule/capsule_birth.c b/src/starkernel/capsule/capsule_birth.c index ecb0d6a..f136cf2 100644 --- a/src/starkernel/capsule/capsule_birth.c +++ b/src/starkernel/capsule/capsule_birth.c @@ -180,6 +180,25 @@ uint32_t capsule_vm_registry_count(void) { return vm_registry_count; } +/* Live population, distinct from vm_registry_count above: vm_registry_count + * is monotonic (incremented on every vm_registry_alloc(), never decremented + * on death), so it counts every VM ever born, not the outer Stadium's + * current occupancy. FABRIC.md item 1.5's bound is on LIVE VMs -- a dead or + * stillborn slot doesn't hold Stadium capacity, and gating on the monotonic + * total would mean the fleet could never regrow after any VM's death, + * which contradicts Hera's own kill-then-rebirth lifecycle (TRIPOD-TEST's + * "K soak" check, capsule_vm_physics.c). Not exposed in the public header: + * only capsule_birth_baby's bound check needs it today. */ +static uint32_t vm_registry_live_count(void) { + vm_node_t *node = vm_registry_head; + uint32_t live = 0; + while (node) { + if (node->entry.state == VM_STATE_LIVE) live++; + node = node->next; + } + return live; +} + int capsule_vm_find_by_name(const char *name, VMRegistryEntry *out) { vm_node_t *node; if (!name || !out) return -1;