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
+68
View File
@@ -823,3 +823,71 @@ unreachable NULL-write, `m5_time_trust`/`m5_variance` dead fields.
closed items, four sequencing-blocked items (no ruling needed, just not startable yet), and closed items, four sequencing-blocked items (no ruling needed, just not startable yet), and
one code question. Nothing in either track's open half is closeable without either Artemis or one code question. Nothing in either track's open half is closeable without either Artemis or
an explicit decision from Captain Bob — which is the state this pass was asked to produce. an explicit decision from Captain Bob — which is the state this pass was asked to produce.
---
## G. Stadium VM population bound made RAM-derived — 2026-08-15
Captain Bob flagged, mid-conversation, that `STADIUM_MAX_VM_COUNT` being a hardcoded
compile-time `4` was not the design he had in mind: "The stadium has capacity that is
determined at boot time with the remaining ram... a static array of four, then we're
fucked." Confirmed by grep: `STADIUM_MAX_VM_COUNT` (Kconfig default 4) sized two genuinely
static compile-time arrays — `stadium_quotas[STADIUM_MAX_VM_COUNT]` and
`word_slots[STADIUM_MAX_VM_COUNT][DICTIONARY_SIZE]` — and gated `capsule_birth.c`'s birth
refusal, with zero RAM-based computation anywhere near it. Not an oversight: `FABRIC.md`
§20.5 item 1.5 (RESOLVED 2026-08-04) explicitly decided this the other way — "fixed for the
machine's lifetime once set at build... the outer total does not itself flex at runtime."
Captain Bob overruled that: population is not knowable in advance (could be 4, could be
4000), so the bound must be computed at boot, no ceiling.
**What was already correct, and what wasn't.** The Stadium's *cell pool* (actual patron
storage) was already boot-time RAM-derived — `stadium_boot_init()`
(`src/starkernel/vm/stadium.c:118`) already computed `ncells` from a percentage of free
memory and `kmalloc()`'d it. Only the *VM population ceiling* was static.
**A second, real bug found while fixing this.** The cell-pool budget was computed from
`pmm_get_stats().free_bytes` — physical pages PMM hasn't handed to any subsystem yet — but
the actual allocation was `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; the percentage was being applied to memory nothing here actually draws from. Fixed
as part of this change — both the existing cell budget and the new VM-count budget now
source from `kmalloc_get_stats()`.
**Owner-byte width.** `stadium_owner[]` (which VM's quota owns each cell) was `uint8_t`,
capped at 255 slots by the old compile-time assert. With no ceiling, this needed widening —
done, `uint16_t` (65535 slots of headroom), with a runtime clamp + log if the computed count
ever exceeds that.
**Mechanism (mirrors the existing cell-pool pattern exactly):** new Kconfig
`STADIUM_VM_MEMORY_PERCENT` (default 50, untuned placeholder like its `STADIUM_MEMORY_PERCENT`
sibling). At boot, after the cell array is allocated: `max_vm_count =
(kmalloc_get_stats().free_bytes * STADIUM_VM_MEMORY_PERCENT / 100) / VM_MEMORY_SIZE`
(`VM_MEMORY_SIZE` = 5 MiB, the real per-VM footprint — not the small bookkeeping tables),
floored to 1 so Hera can always boot, clamped to 65535. `stadium_quotas` and `word_slots`
(plus their `stat_promotions`/`stat_evictions` companions) are now `kmalloc()`'d to that
count instead of declared with the macro. New accessor `stadium_max_vm_count()` replaces
every `STADIUM_MAX_VM_COUNT` reference, including `capsule_birth.c`'s birth-refusal gate.
**Files touched:** `Kconfig.kernel`, `include/starforth_config.h`,
`include/starkernel/vm/stadium.h`, `include/starkernel/vm/stadium_words.h`,
`include/starkernel/capsule_run.h` (comment only), `src/starkernel/vm/stadium.c`,
`src/starkernel/vm/stadium_words.c`, `src/starkernel/capsule/capsule_birth.c`.
**Verification, all three architectures clean, computed VM count genuinely differs across
runs (proof it's really reading RAM, not a disguised constant):**
- **amd64:** `Stadium: 83886 cells (5242 KB), 50 VM slots``logs/20260815-080526/amd64/`
- **aarch64:** `Stadium: 167772 cells (10485 KB), 101 VM slots``logs/20260815-080826/aarch64/`
- **riscv64:** `Stadium: 83886 cells (5242 KB), 50 VM slots``logs/20260815-080952/riscv64/`
All three reached `ok>` clean with Hermes's self-test, an identical Stadium conservation
check (`resident_sum=43691 reservoir=21845 sum=65536`, `Q48_ONE=65536`), and KILL/rest all
passing — the RAM-derived count changed, the physics invariant it feeds into didn't, which
is exactly what should happen. Up from the old fixed `4` in every case.
**Related, same conversation:** this surfaced alongside a correction to §12 Q5's
`STADIUM_CAPACITY_TICK` framing (F.2 above) — Captain Bob's "the clock is only the
heartbeat, period" pushback, confirmed against `FABRIC.md` §16.4/§17.1's decided one-clock
rule. Both are Stadium-capacity-adjacent but independent: this item is the VM *population*
bound (a count), that one is the fleet-capacity *cadence* (a tick threshold).
+16 -10
View File
@@ -33,17 +33,23 @@ config SK_PARITY_DEBUG
treatment as every other previously-unwired constant in this treatment as every other previously-unwired constant in this
migration. migration.
config STADIUM_MAX_VM_COUNT config STADIUM_VM_MEMORY_PERCENT
int "Outer Stadium VM population bound (STADIUM_MAX_VM_COUNT)" int "Percent of remaining kmalloc heap the outer Stadium budgets for VM population (STADIUM_VM_MEMORY_PERCENT)"
default 4 default 50
help help
Hard bound on live VMs in the outer Stadium (FABRIC.md item 1.5). Replaces the old fixed STADIUM_MAX_VM_COUNT bound (Captain Bob,
Birth is refused once this many VMs are LIVE simultaneously; a 2026-08-15: a hardcoded population ceiling cannot be right when the
dead or stillborn VM's registry slot does not count against the actual population is unknowable in advance -- could be 4, could be
bound. Default of 4 matches Tripod's currently-known topology 4000). The outer Stadium's VM population bound is now computed at
(Hera + two Hermes instances + Artemis) -- an explicit placeholder boot, the same way the cell array already is (STADIUM_MEMORY_PERCENT
pending a DoE campaign to find an idealized default (item 5.1), below): this percentage of the kmalloc heap's remaining free bytes
not a padded estimate. (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 config STADIUM_CONTAINS_DEPTH_MAX
int "Patron containment chain depth cap (STADIUM_CONTAINS_DEPTH_MAX)" int "Patron containment chain depth cap (STADIUM_CONTAINS_DEPTH_MAX)"
+1 -1
View File
@@ -1,5 +1,5 @@
# Capsule Block Manifest — Auto-generated # Capsule Block Manifest — Auto-generated
<!-- Generated by mkcapsule --manifest 2026-08-15T00:21:57Z --> <!-- Generated by mkcapsule --manifest 2026-08-15T12:09:24Z -->
<!-- DO NOT EDIT — re-run mkcapsule --manifest to refresh. --> <!-- DO NOT EDIT — re-run mkcapsule --manifest to refresh. -->
<!-- Hand-written justifications and immutability notes live --> <!-- Hand-written justifications and immutability notes live -->
<!-- in MANIFEST.md alongside this auto-generated index. --> <!-- in MANIFEST.md alongside this auto-generated index. -->
BIN
View File
Binary file not shown.
+38 -38
View File
@@ -20,8 +20,8 @@ tick_number,elapsed_ns,tick_interval_ns,cache_hits_delta,bucket_hits_delta,word_
19,190000,10000,0,0,154,35,40,731,731,0,0,0,65536,0,0,65536,0,0 19,190000,10000,0,0,154,35,40,731,731,0,0,0,65536,0,0,65536,0,0
20,200000,10000,0,0,154,35,38,567,567,0,0,0,65536,0,0,65536,0,0 20,200000,10000,0,0,154,35,38,567,567,0,0,0,65536,0,0,65536,0,0
21,210000,10000,0,0,153,38,37,4096,0,0,0,0,65536,0,0,65536,0,0 21,210000,10000,0,0,153,38,37,4096,0,0,0,0,65536,0,0,65536,0,0
22,220000,10000,0,0,167,40,38,582,582,0,0,0,65536,0,0,65536,0,0 22,220000,10000,0,0,167,38,38,582,582,0,0,0,65536,0,0,65536,0,0
23,230000,10000,0,0,176,17,38,685,685,0,0,0,65536,0,0,65536,0,0 23,230000,10000,0,0,176,11,37,685,685,0,0,0,65536,0,0,65536,0,0
24,240000,10000,0,0,175,10,25,731,731,0,0,0,65536,0,0,65536,0,0 24,240000,10000,0,0,175,10,25,731,731,0,0,0,65536,0,0,65536,0,0
25,250000,10000,0,0,196,11,23,731,731,0,0,0,65536,0,0,65536,0,0 25,250000,10000,0,0,196,11,23,731,731,0,0,0,65536,0,0,65536,0,0
26,260000,10000,0,0,192,14,24,4096,0,0,0,0,65536,0,0,65536,0,0 26,260000,10000,0,0,192,14,24,4096,0,0,0,0,65536,0,0,65536,0,0
@@ -48,14 +48,14 @@ tick_number,elapsed_ns,tick_interval_ns,cache_hits_delta,bucket_hits_delta,word_
47,470000,10000,0,0,218,57,18,4096,198,0,0,0,65536,0,0,65536,0,0 47,470000,10000,0,0,218,57,18,4096,198,0,0,0,65536,0,0,65536,0,0
48,480000,10000,0,0,221,60,20,4096,350,0,0,0,65536,0,0,65536,0,0 48,480000,10000,0,0,221,60,20,4096,350,0,0,0,65536,0,0,65536,0,0
49,490000,10000,0,0,225,66,20,4096,528,0,0,0,65536,0,0,65536,0,0 49,490000,10000,0,0,225,66,20,4096,528,0,0,0,65536,0,0,65536,0,0
50,500000,10000,0,0,214,69,21,4096,694,0,0,0,65536,0,0,65536,0,0 50,500000,10000,0,0,214,69,22,4096,694,0,0,0,65536,0,0,65536,0,0
51,510000,10000,0,0,227,71,23,4096,883,0,0,0,65536,0,0,65536,0,0 51,510000,10000,0,0,227,71,23,4096,883,0,0,0,65536,0,0,65536,0,0
52,520000,10000,0,0,208,71,23,4096,1043,0,0,0,65536,0,0,65536,0,0 52,520000,10000,0,0,208,71,24,4096,1043,0,0,0,65536,0,0,65536,0,0
53,530000,10000,0,0,207,71,25,4096,1202,0,0,0,65536,0,0,65536,0,0 53,530000,10000,0,0,207,71,25,4096,1202,0,0,0,65536,0,0,65536,0,0
54,540000,10000,0,0,200,71,26,4096,1319,0,0,0,65536,0,0,65536,0,0 54,540000,10000,0,0,200,71,26,4096,1319,0,0,0,65536,0,0,65536,0,0
55,550000,10000,0,0,205,72,27,4096,1464,0,0,0,65536,0,0,65536,0,0 55,550000,10000,0,0,205,72,27,4096,1464,0,0,0,65536,0,0,65536,0,0
56,560000,10000,0,0,211,73,27,4096,1620,0,0,0,65536,0,0,65536,0,0 56,560000,10000,0,0,211,73,27,4096,1620,0,0,0,65536,0,0,65536,0,0
57,570000,10000,0,0,193,80,28,4096,1712,0,0,0,65536,0,0,65536,0,0 57,570000,10000,0,0,193,80,29,4096,1712,0,0,0,65536,0,0,65536,0,0
58,580000,10000,0,0,185,4,61,4096,1757,0,0,0,65536,0,0,65536,0,0 58,580000,10000,0,0,185,4,61,4096,1757,0,0,0,65536,0,0,65536,0,0
59,590000,10000,0,0,81,7,32,4096,1757,0,0,0,65536,0,0,65536,0,0 59,590000,10000,0,0,81,7,32,4096,1757,0,0,0,65536,0,0,65536,0,0
60,600000,10000,0,0,52,10,28,4096,1757,0,0,0,65536,0,0,65536,0,0 60,600000,10000,0,0,52,10,28,4096,1757,0,0,0,65536,0,0,65536,0,0
@@ -72,39 +72,39 @@ tick_number,elapsed_ns,tick_interval_ns,cache_hits_delta,bucket_hits_delta,word_
71,710000,10000,0,0,44,22,39,4096,1757,0,0,0,65536,0,0,65536,0,0 71,710000,10000,0,0,44,22,39,4096,1757,0,0,0,65536,0,0,65536,0,0
72,720000,10000,0,0,130,24,27,4096,1757,0,0,0,65536,0,0,65536,0,0 72,720000,10000,0,0,130,24,27,4096,1757,0,0,0,65536,0,0,65536,0,0
73,730000,10000,0,0,134,26,21,4096,1757,0,0,0,65536,0,0,65536,0,0 73,730000,10000,0,0,134,26,21,4096,1757,0,0,0,65536,0,0,65536,0,0
1,10000,18446744073708831616,0,0,117,4,4,4096,0,0,4895412794951728796,7,65536,0,0,65536,0,0 1,10000,18446744073708831616,0,0,117,4,4,4096,0,0,4895412794951728796,8,65536,0,0,65536,0,0
2,20000,10000,0,0,78,10,7,4096,0,0,0,8,65536,0,0,65536,0,0 2,20000,10000,0,0,78,10,7,4096,0,0,0,10,65536,0,0,65536,0,0
3,30000,10000,0,0,101,13,7,4096,0,0,0,10,65536,0,0,65536,0,0 3,30000,10000,0,0,101,13,7,4096,0,0,0,12,65536,0,0,65536,0,0
4,40000,10000,0,0,63,19,8,4096,0,0,0,11,65536,0,0,65536,0,0 4,40000,10000,0,0,63,19,8,4096,0,0,0,13,65536,0,0,65536,0,0
5,50000,10000,0,0,92,25,8,4096,2,0,0,13,65536,0,0,65536,0,0 5,50000,10000,0,0,92,25,8,4096,2,0,0,15,65536,0,0,65536,0,0
6,60000,10000,0,0,64,27,8,4096,2,0,0,17,65536,0,0,65536,0,0 6,60000,10000,0,0,64,27,8,4096,2,0,0,17,65536,0,0,65536,0,0
7,70000,10000,0,0,228,32,8,4096,210,0,0,22,65536,0,0,65536,0,0 7,70000,10000,0,0,228,32,8,4096,210,0,0,21,65536,0,0,65536,0,0
8,80000,10000,0,0,256,34,9,4096,466,0,0,22,65536,0,0,65536,0,0 8,80000,10000,0,0,256,34,9,4096,466,0,0,22,65536,0,0,65536,0,0
9,90000,10000,0,0,256,36,10,4096,722,0,0,23,65536,0,0,65536,0,0 9,90000,10000,0,0,256,36,10,4096,722,0,0,22,65536,0,0,65536,0,0
10,100000,10000,0,0,256,36,11,4096,978,0,0,23,65536,0,0,65536,0,0 10,100000,10000,0,0,256,36,11,4096,978,0,0,23,65536,0,0,65536,0,0
11,110000,10000,0,0,256,36,11,4096,1234,0,0,24,65536,0,0,65536,0,0 11,110000,10000,0,0,256,36,11,4096,1234,0,0,23,65536,0,0,65536,0,0
12,120000,10000,0,0,256,36,12,4096,1490,0,0,25,65536,0,0,65536,0,0 12,120000,10000,0,0,256,36,12,4096,1490,0,0,24,65536,0,0,65536,0,0
13,130000,10000,0,0,256,37,12,4096,1746,0,0,25,65536,0,0,65536,0,0 13,130000,10000,0,0,256,37,12,4096,1746,0,0,24,65536,0,0,65536,0,0
14,140000,10000,0,0,230,39,12,4096,1949,0,0,31,65536,0,0,65536,0,0 14,140000,10000,0,0,230,39,12,4096,1949,0,0,26,65536,0,0,65536,0,0
15,150000,10000,0,0,256,39,13,4096,2204,0,0,31,65536,0,0,65536,0,0 15,150000,10000,0,0,256,39,13,4096,2204,0,0,27,65536,0,0,65536,0,0
16,160000,10000,0,0,256,39,14,4096,2459,0,0,32,65536,0,0,65536,0,0 16,160000,10000,0,0,256,39,14,4096,2459,0,0,27,65536,0,0,65536,0,0
17,170000,10000,0,0,256,39,15,4096,2713,0,0,34,65536,0,0,65536,0,0 17,170000,10000,0,0,256,39,15,4096,2713,0,0,29,65536,0,0,65536,0,0
18,180000,10000,0,0,256,39,15,4096,2969,0,0,35,65536,0,0,65536,0,0 18,180000,10000,0,0,256,39,15,4096,2969,0,0,29,65536,0,0,65536,0,0
19,190000,10000,0,0,256,39,16,4096,3224,0,0,37,65536,0,1,65536,0,0 19,190000,10000,0,0,256,39,16,4096,3224,0,0,31,65536,0,1,65536,0,0
20,200000,10000,0,0,256,41,17,4096,3480,0,0,38,65536,0,1,65536,0,0 20,200000,10000,0,0,256,41,17,4096,3480,0,0,31,65536,0,1,65536,0,0
21,210000,10000,0,0,256,41,17,4096,3736,0,0,38,65536,0,1,65536,0,0 21,210000,10000,0,0,256,41,17,4096,3736,0,0,32,65536,0,1,65536,0,0
22,220000,10000,0,0,256,41,18,4096,3992,0,0,39,65536,0,1,65536,0,0 22,220000,10000,0,0,256,41,18,4096,3992,0,0,32,65536,0,1,65536,0,0
23,230000,10000,0,0,256,41,19,4096,4096,0,0,40,65536,0,1,65536,0,0 23,230000,10000,0,0,256,41,19,4096,4096,0,0,34,65536,0,1,65536,0,0
24,240000,10000,0,0,256,41,20,4096,4096,0,0,41,65536,0,1,65536,0,0 24,240000,10000,0,0,256,41,20,4096,4096,0,0,34,65536,0,1,65536,0,0
25,250000,10000,0,0,256,43,20,2048,2048,0,0,42,65536,0,1,65536,0,0 25,250000,10000,0,0,256,43,20,2048,2048,0,0,35,65536,0,1,65536,0,0
26,260000,10000,0,0,256,45,21,2048,2048,0,0,42,65536,0,1,65536,0,0 26,260000,10000,0,0,256,45,21,2048,2048,0,0,36,65536,0,1,65536,0,0
27,270000,10000,0,0,256,45,22,1024,1024,0,0,44,65536,0,1,65536,0,0 27,270000,10000,0,0,256,45,22,1024,1024,0,0,36,65536,0,1,65536,0,0
28,280000,10000,0,0,256,45,23,1024,1024,0,0,45,65536,0,1,65536,0,0 28,280000,10000,0,0,256,45,23,1024,1024,0,0,37,65536,0,1,65536,0,0
29,290000,10000,0,0,256,45,24,512,512,0,0,46,65536,0,1,65536,0,0 29,290000,10000,0,0,256,45,24,512,512,0,0,38,65536,0,1,65536,0,0
30,300000,10000,0,0,256,45,24,512,512,0,0,47,65536,0,1,65536,0,0 30,300000,10000,0,0,256,45,24,512,512,0,0,38,65536,0,1,65536,0,0
31,310000,10000,0,0,256,45,25,256,256,0,0,47,65536,0,1,65536,0,0 31,310000,10000,0,0,256,45,25,256,256,0,0,39,65536,0,1,65536,0,0
32,320000,10000,0,0,255,45,26,256,256,0,0,50,65536,0,1,65536,0,0 32,320000,10000,0,0,255,45,26,256,256,0,0,41,65536,0,1,65536,0,0
33,330000,10000,0,0,256,45,27,256,256,0,0,50,65536,0,1,65536,0,0 33,330000,10000,0,0,256,45,27,256,256,0,0,41,65536,0,1,65536,0,0
34,340000,10000,0,0,256,45,27,256,256,0,0,52,65536,0,1,65536,0,0 34,340000,10000,0,0,256,45,27,256,256,0,0,43,65536,0,1,65536,0,0
35,350000,10000,0,0,256,45,28,256,256,0,0,53,65536,0,1,65536,0,0 35,350000,10000,0,0,256,45,28,256,256,0,0,44,65536,0,1,65536,0,0
36,360000,10000,0,0,256,45,29,256,256,0,0,54,65536,0,1,65536,0,0 36,360000,10000,0,0,256,45,29,256,256,0,0,44,65536,0,1,65536,0,0
1 tick_number elapsed_ns tick_interval_ns cache_hits_delta bucket_hits_delta word_executions_delta hot_word_count avg_word_heat_q48 window_width actual_window_size predicted_label_hits jitter_bits apic_ticks time_trust_q48 variance_q48 vm_call_depth_max hera_heat_q48 hermes_heat_q48 artemis_heat_q48
20 19 190000 10000 0 0 154 35 40 731 731 0 0 0 65536 0 0 65536 0 0
21 20 200000 10000 0 0 154 35 38 567 567 0 0 0 65536 0 0 65536 0 0
22 21 210000 10000 0 0 153 38 37 4096 0 0 0 0 65536 0 0 65536 0 0
23 22 220000 10000 0 0 167 40 38 38 582 582 0 0 0 65536 0 0 65536 0 0
24 23 230000 10000 0 0 176 17 11 38 37 685 685 0 0 0 65536 0 0 65536 0 0
25 24 240000 10000 0 0 175 10 25 731 731 0 0 0 65536 0 0 65536 0 0
26 25 250000 10000 0 0 196 11 23 731 731 0 0 0 65536 0 0 65536 0 0
27 26 260000 10000 0 0 192 14 24 4096 0 0 0 0 65536 0 0 65536 0 0
48 47 470000 10000 0 0 218 57 18 4096 198 0 0 0 65536 0 0 65536 0 0
49 48 480000 10000 0 0 221 60 20 4096 350 0 0 0 65536 0 0 65536 0 0
50 49 490000 10000 0 0 225 66 20 4096 528 0 0 0 65536 0 0 65536 0 0
51 50 500000 10000 0 0 214 69 21 22 4096 694 0 0 0 65536 0 0 65536 0 0
52 51 510000 10000 0 0 227 71 23 4096 883 0 0 0 65536 0 0 65536 0 0
53 52 520000 10000 0 0 208 71 23 24 4096 1043 0 0 0 65536 0 0 65536 0 0
54 53 530000 10000 0 0 207 71 25 4096 1202 0 0 0 65536 0 0 65536 0 0
55 54 540000 10000 0 0 200 71 26 4096 1319 0 0 0 65536 0 0 65536 0 0
56 55 550000 10000 0 0 205 72 27 4096 1464 0 0 0 65536 0 0 65536 0 0
57 56 560000 10000 0 0 211 73 27 4096 1620 0 0 0 65536 0 0 65536 0 0
58 57 570000 10000 0 0 193 80 28 29 4096 1712 0 0 0 65536 0 0 65536 0 0
59 58 580000 10000 0 0 185 4 61 4096 1757 0 0 0 65536 0 0 65536 0 0
60 59 590000 10000 0 0 81 7 32 4096 1757 0 0 0 65536 0 0 65536 0 0
61 60 600000 10000 0 0 52 10 28 4096 1757 0 0 0 65536 0 0 65536 0 0
72 71 710000 10000 0 0 44 22 39 4096 1757 0 0 0 65536 0 0 65536 0 0
73 72 720000 10000 0 0 130 24 27 4096 1757 0 0 0 65536 0 0 65536 0 0
74 73 730000 10000 0 0 134 26 21 4096 1757 0 0 0 65536 0 0 65536 0 0
75 1 10000 18446744073708831616 0 0 117 4 4 4096 0 0 4895412794951728796 7 8 65536 0 0 65536 0 0
76 2 20000 10000 0 0 78 10 7 4096 0 0 0 8 10 65536 0 0 65536 0 0
77 3 30000 10000 0 0 101 13 7 4096 0 0 0 10 12 65536 0 0 65536 0 0
78 4 40000 10000 0 0 63 19 8 4096 0 0 0 11 13 65536 0 0 65536 0 0
79 5 50000 10000 0 0 92 25 8 4096 2 0 0 13 15 65536 0 0 65536 0 0
80 6 60000 10000 0 0 64 27 8 4096 2 0 0 17 65536 0 0 65536 0 0
81 7 70000 10000 0 0 228 32 8 4096 210 0 0 22 21 65536 0 0 65536 0 0
82 8 80000 10000 0 0 256 34 9 4096 466 0 0 22 65536 0 0 65536 0 0
83 9 90000 10000 0 0 256 36 10 4096 722 0 0 23 22 65536 0 0 65536 0 0
84 10 100000 10000 0 0 256 36 11 4096 978 0 0 23 65536 0 0 65536 0 0
85 11 110000 10000 0 0 256 36 11 4096 1234 0 0 24 23 65536 0 0 65536 0 0
86 12 120000 10000 0 0 256 36 12 4096 1490 0 0 25 24 65536 0 0 65536 0 0
87 13 130000 10000 0 0 256 37 12 4096 1746 0 0 25 24 65536 0 0 65536 0 0
88 14 140000 10000 0 0 230 39 12 4096 1949 0 0 31 26 65536 0 0 65536 0 0
89 15 150000 10000 0 0 256 39 13 4096 2204 0 0 31 27 65536 0 0 65536 0 0
90 16 160000 10000 0 0 256 39 14 4096 2459 0 0 32 27 65536 0 0 65536 0 0
91 17 170000 10000 0 0 256 39 15 4096 2713 0 0 34 29 65536 0 0 65536 0 0
92 18 180000 10000 0 0 256 39 15 4096 2969 0 0 35 29 65536 0 0 65536 0 0
93 19 190000 10000 0 0 256 39 16 4096 3224 0 0 37 31 65536 0 1 65536 0 0
94 20 200000 10000 0 0 256 41 17 4096 3480 0 0 38 31 65536 0 1 65536 0 0
95 21 210000 10000 0 0 256 41 17 4096 3736 0 0 38 32 65536 0 1 65536 0 0
96 22 220000 10000 0 0 256 41 18 4096 3992 0 0 39 32 65536 0 1 65536 0 0
97 23 230000 10000 0 0 256 41 19 4096 4096 0 0 40 34 65536 0 1 65536 0 0
98 24 240000 10000 0 0 256 41 20 4096 4096 0 0 41 34 65536 0 1 65536 0 0
99 25 250000 10000 0 0 256 43 20 2048 2048 0 0 42 35 65536 0 1 65536 0 0
100 26 260000 10000 0 0 256 45 21 2048 2048 0 0 42 36 65536 0 1 65536 0 0
101 27 270000 10000 0 0 256 45 22 1024 1024 0 0 44 36 65536 0 1 65536 0 0
102 28 280000 10000 0 0 256 45 23 1024 1024 0 0 45 37 65536 0 1 65536 0 0
103 29 290000 10000 0 0 256 45 24 512 512 0 0 46 38 65536 0 1 65536 0 0
104 30 300000 10000 0 0 256 45 24 512 512 0 0 47 38 65536 0 1 65536 0 0
105 31 310000 10000 0 0 256 45 25 256 256 0 0 47 39 65536 0 1 65536 0 0
106 32 320000 10000 0 0 255 45 26 256 256 0 0 50 41 65536 0 1 65536 0 0
107 33 330000 10000 0 0 256 45 27 256 256 0 0 50 41 65536 0 1 65536 0 0
108 34 340000 10000 0 0 256 45 27 256 256 0 0 52 43 65536 0 1 65536 0 0
109 35 350000 10000 0 0 256 45 28 256 256 0 0 53 44 65536 0 1 65536 0 0
110 36 360000 10000 0 0 256 45 29 256 256 0 0 54 44 65536 0 1 65536 0 0
@@ -0,0 +1,110 @@
tick_number,elapsed_ns,tick_interval_ns,cache_hits_delta,bucket_hits_delta,word_executions_delta,hot_word_count,avg_word_heat_q48,window_width,actual_window_size,predicted_label_hits,jitter_bits,apic_ticks,time_trust_q48,variance_q48,vm_call_depth_max,hera_heat_q48,hermes_heat_q48,artemis_heat_q48
1,10000,10000,0,0,183,4,45,731,731,0,0,0,65536,0,0,65536,0,0
2,20000,10000,0,0,173,5,44,582,582,0,0,0,65536,0,0,65536,0,0
3,30000,10000,0,0,184,6,60,582,582,0,0,0,65536,0,0,65536,0,0
4,40000,10000,0,0,174,8,71,4096,0,0,0,0,65536,0,0,65536,0,0
5,50000,10000,0,0,150,9,78,582,582,0,0,0,65536,0,0,65536,0,0
6,60000,10000,0,0,159,11,73,4096,0,0,0,0,65536,0,0,65536,0,0
7,70000,10000,0,0,188,15,71,685,685,0,0,0,65536,0,0,65536,0,0
8,80000,10000,0,0,214,16,83,685,685,0,0,0,65536,0,0,65536,0,0
9,90000,10000,0,0,216,19,82,4096,0,0,0,0,65536,0,0,65536,0,0
10,100000,10000,0,0,222,21,84,567,567,0,0,0,65536,0,0,65536,0,0
11,110000,10000,0,0,207,23,86,731,731,0,0,0,65536,0,0,65536,0,0
12,120000,10000,0,0,189,26,83,4096,0,0,0,0,65536,0,0,65536,0,0
13,130000,10000,0,0,221,28,80,731,731,0,0,0,65536,0,0,65536,0,0
14,140000,10000,0,0,204,29,83,685,685,0,0,0,65536,0,0,65536,0,0
15,150000,10000,0,0,203,30,82,731,731,0,0,0,65536,0,0,65536,0,0
16,160000,10000,0,0,201,32,83,567,567,0,0,0,65536,0,0,65536,0,0
17,170000,10000,0,0,190,34,86,731,731,0,0,0,65536,0,0,65536,0,0
18,180000,10000,0,0,170,35,73,582,582,0,0,0,65536,0,0,65536,0,0
19,190000,10000,0,0,154,35,40,731,731,0,0,0,65536,0,0,65536,0,0
20,200000,10000,0,0,154,35,38,567,567,0,0,0,65536,0,0,65536,0,0
21,210000,10000,0,0,153,38,37,4096,0,0,0,0,65536,0,0,65536,0,0
22,220000,10000,0,0,167,38,38,582,582,0,0,0,65536,0,0,65536,0,0
23,230000,10000,0,0,176,11,37,685,685,0,0,0,65536,0,0,65536,0,0
24,240000,10000,0,0,175,10,25,731,731,0,0,0,65536,0,0,65536,0,0
25,250000,10000,0,0,196,11,23,731,731,0,0,0,65536,0,0,65536,0,0
26,260000,10000,0,0,192,14,24,4096,0,0,0,0,65536,0,0,65536,0,0
27,270000,10000,0,0,158,16,30,685,685,0,0,0,65536,0,0,65536,0,0
28,280000,10000,0,0,158,17,23,4096,0,0,0,0,65536,0,0,65536,0,0
29,290000,10000,0,0,164,17,27,4096,0,0,0,0,65536,0,0,65536,0,0
30,300000,10000,0,0,154,18,26,685,685,0,0,0,65536,0,0,65536,0,0
31,310000,10000,0,0,172,6,25,582,582,0,0,0,65536,0,0,65536,0,0
32,320000,10000,0,0,180,9,22,567,567,0,0,0,65536,0,0,65536,0,0
33,330000,10000,0,0,145,11,29,567,567,0,0,0,65536,0,0,65536,0,0
34,340000,10000,0,0,203,14,30,582,582,0,0,0,65536,0,0,65536,0,0
35,350000,10000,0,0,154,16,36,731,731,0,0,0,65536,0,0,65536,0,0
36,360000,10000,0,0,144,18,32,4096,0,0,0,0,65536,0,0,65536,0,0
37,370000,10000,0,0,144,18,29,4096,0,0,0,0,65536,0,0,65536,0,0
38,380000,10000,0,0,132,18,28,4096,0,0,0,0,65536,0,0,65536,0,0
39,390000,10000,0,0,180,18,24,4096,0,0,0,0,65536,0,0,65536,0,0
40,400000,10000,0,0,220,23,20,4096,0,0,0,0,65536,0,0,65536,0,0
41,410000,10000,0,0,215,25,19,4096,24,0,0,0,65536,0,0,65536,0,0
42,420000,10000,0,0,208,32,20,4096,24,0,0,0,65536,0,0,65536,0,0
43,430000,10000,0,0,177,36,19,4096,24,0,0,0,65536,0,0,65536,0,0
44,440000,10000,0,0,199,42,20,4096,24,0,0,0,65536,0,0,65536,0,0
45,450000,10000,0,0,223,47,19,4096,30,0,0,0,65536,0,0,65536,0,0
46,460000,10000,0,0,202,50,17,4096,67,0,0,0,65536,0,0,65536,0,0
47,470000,10000,0,0,218,57,18,4096,198,0,0,0,65536,0,0,65536,0,0
48,480000,10000,0,0,221,60,20,4096,350,0,0,0,65536,0,0,65536,0,0
49,490000,10000,0,0,225,66,20,4096,528,0,0,0,65536,0,0,65536,0,0
50,500000,10000,0,0,214,69,22,4096,694,0,0,0,65536,0,0,65536,0,0
51,510000,10000,0,0,227,71,23,4096,883,0,0,0,65536,0,0,65536,0,0
52,520000,10000,0,0,208,71,24,4096,1043,0,0,0,65536,0,0,65536,0,0
53,530000,10000,0,0,207,71,25,4096,1202,0,0,0,65536,0,0,65536,0,0
54,540000,10000,0,0,200,71,26,4096,1319,0,0,0,65536,0,0,65536,0,0
55,550000,10000,0,0,205,72,27,4096,1464,0,0,0,65536,0,0,65536,0,0
56,560000,10000,0,0,211,73,27,4096,1620,0,0,0,65536,0,0,65536,0,0
57,570000,10000,0,0,193,80,29,4096,1712,0,0,0,65536,0,0,65536,0,0
58,580000,10000,0,0,185,4,61,4096,1757,0,0,0,65536,0,0,65536,0,0
59,590000,10000,0,0,81,7,32,4096,1757,0,0,0,65536,0,0,65536,0,0
60,600000,10000,0,0,52,10,28,4096,1757,0,0,0,65536,0,0,65536,0,0
61,610000,10000,0,0,63,17,25,4096,1757,0,0,0,65536,0,0,65536,0,0
62,620000,10000,0,0,85,19,24,4096,1757,0,0,0,65536,0,0,65536,0,0
63,630000,10000,0,0,68,20,23,4096,1757,0,0,0,65536,0,0,65536,0,0
64,640000,10000,0,0,39,20,23,4096,1757,0,0,0,65536,0,0,65536,0,0
65,650000,10000,0,0,45,20,25,4096,1757,0,0,0,65536,0,0,65536,0,0
66,660000,10000,0,0,42,20,29,4096,1757,0,0,0,65536,0,0,65536,0,0
67,670000,10000,0,0,47,20,31,4096,1757,0,0,0,65536,0,0,65536,0,0
68,680000,10000,0,0,43,20,34,4096,1757,0,0,0,65536,0,0,65536,0,0
69,690000,10000,0,0,48,20,35,4096,1757,0,0,0,65536,0,0,65536,0,0
70,700000,10000,0,0,48,21,38,4096,1757,0,0,0,65536,0,0,65536,0,0
71,710000,10000,0,0,44,22,39,4096,1757,0,0,0,65536,0,0,65536,0,0
72,720000,10000,0,0,130,24,27,4096,1757,0,0,0,65536,0,0,65536,0,0
73,730000,10000,0,0,134,26,21,4096,1757,0,0,0,65536,0,0,65536,0,0
1,10000,18446744073708831616,0,0,117,4,4,4096,0,0,4895412794951728796,8,65536,0,0,65536,0,0
2,20000,10000,0,0,78,10,7,4096,0,0,0,10,65536,0,0,65536,0,0
3,30000,10000,0,0,101,13,7,4096,0,0,0,12,65536,0,0,65536,0,0
4,40000,10000,0,0,63,19,8,4096,0,0,0,13,65536,0,0,65536,0,0
5,50000,10000,0,0,92,25,8,4096,2,0,0,15,65536,0,0,65536,0,0
6,60000,10000,0,0,64,27,8,4096,2,0,0,17,65536,0,0,65536,0,0
7,70000,10000,0,0,228,32,8,4096,210,0,0,21,65536,0,0,65536,0,0
8,80000,10000,0,0,256,34,9,4096,466,0,0,22,65536,0,0,65536,0,0
9,90000,10000,0,0,256,36,10,4096,722,0,0,22,65536,0,0,65536,0,0
10,100000,10000,0,0,256,36,11,4096,978,0,0,23,65536,0,0,65536,0,0
11,110000,10000,0,0,256,36,11,4096,1234,0,0,23,65536,0,0,65536,0,0
12,120000,10000,0,0,256,36,12,4096,1490,0,0,24,65536,0,0,65536,0,0
13,130000,10000,0,0,256,37,12,4096,1746,0,0,24,65536,0,0,65536,0,0
14,140000,10000,0,0,230,39,12,4096,1949,0,0,26,65536,0,0,65536,0,0
15,150000,10000,0,0,256,39,13,4096,2204,0,0,27,65536,0,0,65536,0,0
16,160000,10000,0,0,256,39,14,4096,2459,0,0,27,65536,0,0,65536,0,0
17,170000,10000,0,0,256,39,15,4096,2713,0,0,29,65536,0,0,65536,0,0
18,180000,10000,0,0,256,39,15,4096,2969,0,0,29,65536,0,0,65536,0,0
19,190000,10000,0,0,256,39,16,4096,3224,0,0,31,65536,0,1,65536,0,0
20,200000,10000,0,0,256,41,17,4096,3480,0,0,31,65536,0,1,65536,0,0
21,210000,10000,0,0,256,41,17,4096,3736,0,0,32,65536,0,1,65536,0,0
22,220000,10000,0,0,256,41,18,4096,3992,0,0,32,65536,0,1,65536,0,0
23,230000,10000,0,0,256,41,19,4096,4096,0,0,34,65536,0,1,65536,0,0
24,240000,10000,0,0,256,41,20,4096,4096,0,0,34,65536,0,1,65536,0,0
25,250000,10000,0,0,256,43,20,2048,2048,0,0,35,65536,0,1,65536,0,0
26,260000,10000,0,0,256,45,21,2048,2048,0,0,36,65536,0,1,65536,0,0
27,270000,10000,0,0,256,45,22,1024,1024,0,0,36,65536,0,1,65536,0,0
28,280000,10000,0,0,256,45,23,1024,1024,0,0,37,65536,0,1,65536,0,0
29,290000,10000,0,0,256,45,24,512,512,0,0,38,65536,0,1,65536,0,0
30,300000,10000,0,0,256,45,24,512,512,0,0,38,65536,0,1,65536,0,0
31,310000,10000,0,0,256,45,25,256,256,0,0,39,65536,0,1,65536,0,0
32,320000,10000,0,0,255,45,26,256,256,0,0,41,65536,0,1,65536,0,0
33,330000,10000,0,0,256,45,27,256,256,0,0,41,65536,0,1,65536,0,0
34,340000,10000,0,0,256,45,27,256,256,0,0,43,65536,0,1,65536,0,0
35,350000,10000,0,0,256,45,28,256,256,0,0,44,65536,0,1,65536,0,0
36,360000,10000,0,0,256,45,29,256,256,0,0,44,65536,0,1,65536,0,0
1 tick_number elapsed_ns tick_interval_ns cache_hits_delta bucket_hits_delta word_executions_delta hot_word_count avg_word_heat_q48 window_width actual_window_size predicted_label_hits jitter_bits apic_ticks time_trust_q48 variance_q48 vm_call_depth_max hera_heat_q48 hermes_heat_q48 artemis_heat_q48
2 1 10000 10000 0 0 183 4 45 731 731 0 0 0 65536 0 0 65536 0 0
3 2 20000 10000 0 0 173 5 44 582 582 0 0 0 65536 0 0 65536 0 0
4 3 30000 10000 0 0 184 6 60 582 582 0 0 0 65536 0 0 65536 0 0
5 4 40000 10000 0 0 174 8 71 4096 0 0 0 0 65536 0 0 65536 0 0
6 5 50000 10000 0 0 150 9 78 582 582 0 0 0 65536 0 0 65536 0 0
7 6 60000 10000 0 0 159 11 73 4096 0 0 0 0 65536 0 0 65536 0 0
8 7 70000 10000 0 0 188 15 71 685 685 0 0 0 65536 0 0 65536 0 0
9 8 80000 10000 0 0 214 16 83 685 685 0 0 0 65536 0 0 65536 0 0
10 9 90000 10000 0 0 216 19 82 4096 0 0 0 0 65536 0 0 65536 0 0
11 10 100000 10000 0 0 222 21 84 567 567 0 0 0 65536 0 0 65536 0 0
12 11 110000 10000 0 0 207 23 86 731 731 0 0 0 65536 0 0 65536 0 0
13 12 120000 10000 0 0 189 26 83 4096 0 0 0 0 65536 0 0 65536 0 0
14 13 130000 10000 0 0 221 28 80 731 731 0 0 0 65536 0 0 65536 0 0
15 14 140000 10000 0 0 204 29 83 685 685 0 0 0 65536 0 0 65536 0 0
16 15 150000 10000 0 0 203 30 82 731 731 0 0 0 65536 0 0 65536 0 0
17 16 160000 10000 0 0 201 32 83 567 567 0 0 0 65536 0 0 65536 0 0
18 17 170000 10000 0 0 190 34 86 731 731 0 0 0 65536 0 0 65536 0 0
19 18 180000 10000 0 0 170 35 73 582 582 0 0 0 65536 0 0 65536 0 0
20 19 190000 10000 0 0 154 35 40 731 731 0 0 0 65536 0 0 65536 0 0
21 20 200000 10000 0 0 154 35 38 567 567 0 0 0 65536 0 0 65536 0 0
22 21 210000 10000 0 0 153 38 37 4096 0 0 0 0 65536 0 0 65536 0 0
23 22 220000 10000 0 0 167 38 38 582 582 0 0 0 65536 0 0 65536 0 0
24 23 230000 10000 0 0 176 11 37 685 685 0 0 0 65536 0 0 65536 0 0
25 24 240000 10000 0 0 175 10 25 731 731 0 0 0 65536 0 0 65536 0 0
26 25 250000 10000 0 0 196 11 23 731 731 0 0 0 65536 0 0 65536 0 0
27 26 260000 10000 0 0 192 14 24 4096 0 0 0 0 65536 0 0 65536 0 0
28 27 270000 10000 0 0 158 16 30 685 685 0 0 0 65536 0 0 65536 0 0
29 28 280000 10000 0 0 158 17 23 4096 0 0 0 0 65536 0 0 65536 0 0
30 29 290000 10000 0 0 164 17 27 4096 0 0 0 0 65536 0 0 65536 0 0
31 30 300000 10000 0 0 154 18 26 685 685 0 0 0 65536 0 0 65536 0 0
32 31 310000 10000 0 0 172 6 25 582 582 0 0 0 65536 0 0 65536 0 0
33 32 320000 10000 0 0 180 9 22 567 567 0 0 0 65536 0 0 65536 0 0
34 33 330000 10000 0 0 145 11 29 567 567 0 0 0 65536 0 0 65536 0 0
35 34 340000 10000 0 0 203 14 30 582 582 0 0 0 65536 0 0 65536 0 0
36 35 350000 10000 0 0 154 16 36 731 731 0 0 0 65536 0 0 65536 0 0
37 36 360000 10000 0 0 144 18 32 4096 0 0 0 0 65536 0 0 65536 0 0
38 37 370000 10000 0 0 144 18 29 4096 0 0 0 0 65536 0 0 65536 0 0
39 38 380000 10000 0 0 132 18 28 4096 0 0 0 0 65536 0 0 65536 0 0
40 39 390000 10000 0 0 180 18 24 4096 0 0 0 0 65536 0 0 65536 0 0
41 40 400000 10000 0 0 220 23 20 4096 0 0 0 0 65536 0 0 65536 0 0
42 41 410000 10000 0 0 215 25 19 4096 24 0 0 0 65536 0 0 65536 0 0
43 42 420000 10000 0 0 208 32 20 4096 24 0 0 0 65536 0 0 65536 0 0
44 43 430000 10000 0 0 177 36 19 4096 24 0 0 0 65536 0 0 65536 0 0
45 44 440000 10000 0 0 199 42 20 4096 24 0 0 0 65536 0 0 65536 0 0
46 45 450000 10000 0 0 223 47 19 4096 30 0 0 0 65536 0 0 65536 0 0
47 46 460000 10000 0 0 202 50 17 4096 67 0 0 0 65536 0 0 65536 0 0
48 47 470000 10000 0 0 218 57 18 4096 198 0 0 0 65536 0 0 65536 0 0
49 48 480000 10000 0 0 221 60 20 4096 350 0 0 0 65536 0 0 65536 0 0
50 49 490000 10000 0 0 225 66 20 4096 528 0 0 0 65536 0 0 65536 0 0
51 50 500000 10000 0 0 214 69 22 4096 694 0 0 0 65536 0 0 65536 0 0
52 51 510000 10000 0 0 227 71 23 4096 883 0 0 0 65536 0 0 65536 0 0
53 52 520000 10000 0 0 208 71 24 4096 1043 0 0 0 65536 0 0 65536 0 0
54 53 530000 10000 0 0 207 71 25 4096 1202 0 0 0 65536 0 0 65536 0 0
55 54 540000 10000 0 0 200 71 26 4096 1319 0 0 0 65536 0 0 65536 0 0
56 55 550000 10000 0 0 205 72 27 4096 1464 0 0 0 65536 0 0 65536 0 0
57 56 560000 10000 0 0 211 73 27 4096 1620 0 0 0 65536 0 0 65536 0 0
58 57 570000 10000 0 0 193 80 29 4096 1712 0 0 0 65536 0 0 65536 0 0
59 58 580000 10000 0 0 185 4 61 4096 1757 0 0 0 65536 0 0 65536 0 0
60 59 590000 10000 0 0 81 7 32 4096 1757 0 0 0 65536 0 0 65536 0 0
61 60 600000 10000 0 0 52 10 28 4096 1757 0 0 0 65536 0 0 65536 0 0
62 61 610000 10000 0 0 63 17 25 4096 1757 0 0 0 65536 0 0 65536 0 0
63 62 620000 10000 0 0 85 19 24 4096 1757 0 0 0 65536 0 0 65536 0 0
64 63 630000 10000 0 0 68 20 23 4096 1757 0 0 0 65536 0 0 65536 0 0
65 64 640000 10000 0 0 39 20 23 4096 1757 0 0 0 65536 0 0 65536 0 0
66 65 650000 10000 0 0 45 20 25 4096 1757 0 0 0 65536 0 0 65536 0 0
67 66 660000 10000 0 0 42 20 29 4096 1757 0 0 0 65536 0 0 65536 0 0
68 67 670000 10000 0 0 47 20 31 4096 1757 0 0 0 65536 0 0 65536 0 0
69 68 680000 10000 0 0 43 20 34 4096 1757 0 0 0 65536 0 0 65536 0 0
70 69 690000 10000 0 0 48 20 35 4096 1757 0 0 0 65536 0 0 65536 0 0
71 70 700000 10000 0 0 48 21 38 4096 1757 0 0 0 65536 0 0 65536 0 0
72 71 710000 10000 0 0 44 22 39 4096 1757 0 0 0 65536 0 0 65536 0 0
73 72 720000 10000 0 0 130 24 27 4096 1757 0 0 0 65536 0 0 65536 0 0
74 73 730000 10000 0 0 134 26 21 4096 1757 0 0 0 65536 0 0 65536 0 0
75 1 10000 18446744073708831616 0 0 117 4 4 4096 0 0 4895412794951728796 8 65536 0 0 65536 0 0
76 2 20000 10000 0 0 78 10 7 4096 0 0 0 10 65536 0 0 65536 0 0
77 3 30000 10000 0 0 101 13 7 4096 0 0 0 12 65536 0 0 65536 0 0
78 4 40000 10000 0 0 63 19 8 4096 0 0 0 13 65536 0 0 65536 0 0
79 5 50000 10000 0 0 92 25 8 4096 2 0 0 15 65536 0 0 65536 0 0
80 6 60000 10000 0 0 64 27 8 4096 2 0 0 17 65536 0 0 65536 0 0
81 7 70000 10000 0 0 228 32 8 4096 210 0 0 21 65536 0 0 65536 0 0
82 8 80000 10000 0 0 256 34 9 4096 466 0 0 22 65536 0 0 65536 0 0
83 9 90000 10000 0 0 256 36 10 4096 722 0 0 22 65536 0 0 65536 0 0
84 10 100000 10000 0 0 256 36 11 4096 978 0 0 23 65536 0 0 65536 0 0
85 11 110000 10000 0 0 256 36 11 4096 1234 0 0 23 65536 0 0 65536 0 0
86 12 120000 10000 0 0 256 36 12 4096 1490 0 0 24 65536 0 0 65536 0 0
87 13 130000 10000 0 0 256 37 12 4096 1746 0 0 24 65536 0 0 65536 0 0
88 14 140000 10000 0 0 230 39 12 4096 1949 0 0 26 65536 0 0 65536 0 0
89 15 150000 10000 0 0 256 39 13 4096 2204 0 0 27 65536 0 0 65536 0 0
90 16 160000 10000 0 0 256 39 14 4096 2459 0 0 27 65536 0 0 65536 0 0
91 17 170000 10000 0 0 256 39 15 4096 2713 0 0 29 65536 0 0 65536 0 0
92 18 180000 10000 0 0 256 39 15 4096 2969 0 0 29 65536 0 0 65536 0 0
93 19 190000 10000 0 0 256 39 16 4096 3224 0 0 31 65536 0 1 65536 0 0
94 20 200000 10000 0 0 256 41 17 4096 3480 0 0 31 65536 0 1 65536 0 0
95 21 210000 10000 0 0 256 41 17 4096 3736 0 0 32 65536 0 1 65536 0 0
96 22 220000 10000 0 0 256 41 18 4096 3992 0 0 32 65536 0 1 65536 0 0
97 23 230000 10000 0 0 256 41 19 4096 4096 0 0 34 65536 0 1 65536 0 0
98 24 240000 10000 0 0 256 41 20 4096 4096 0 0 34 65536 0 1 65536 0 0
99 25 250000 10000 0 0 256 43 20 2048 2048 0 0 35 65536 0 1 65536 0 0
100 26 260000 10000 0 0 256 45 21 2048 2048 0 0 36 65536 0 1 65536 0 0
101 27 270000 10000 0 0 256 45 22 1024 1024 0 0 36 65536 0 1 65536 0 0
102 28 280000 10000 0 0 256 45 23 1024 1024 0 0 37 65536 0 1 65536 0 0
103 29 290000 10000 0 0 256 45 24 512 512 0 0 38 65536 0 1 65536 0 0
104 30 300000 10000 0 0 256 45 24 512 512 0 0 38 65536 0 1 65536 0 0
105 31 310000 10000 0 0 256 45 25 256 256 0 0 39 65536 0 1 65536 0 0
106 32 320000 10000 0 0 255 45 26 256 256 0 0 41 65536 0 1 65536 0 0
107 33 330000 10000 0 0 256 45 27 256 256 0 0 41 65536 0 1 65536 0 0
108 34 340000 10000 0 0 256 45 27 256 256 0 0 43 65536 0 1 65536 0 0
109 35 350000 10000 0 0 256 45 28 256 256 0 0 44 65536 0 1 65536 0 0
110 36 360000 10000 0 0 256 45 29 256 256 0 0 44 65536 0 1 65536 0 0
+3 -3
View File
@@ -70,7 +70,7 @@
#define STARFORTH_CONFIG_HEARTBEAT_THREAD_ENABLED_DEFAULT 1 #define STARFORTH_CONFIG_HEARTBEAT_THREAD_ENABLED_DEFAULT 1
#define STARFORTH_CONFIG_HEARTBEAT_TICK_NS_DEFAULT 10000ULL #define STARFORTH_CONFIG_HEARTBEAT_TICK_NS_DEFAULT 10000ULL
#define STARFORTH_CONFIG_HEARTBEAT_INFERENCE_FREQUENCY_DEFAULT 1000 #define STARFORTH_CONFIG_HEARTBEAT_INFERENCE_FREQUENCY_DEFAULT 1000
#define STARFORTH_CONFIG_STADIUM_MAX_VM_COUNT_DEFAULT 4 #define STARFORTH_CONFIG_STADIUM_VM_MEMORY_PERCENT_DEFAULT 50
#define STARFORTH_CONFIG_STADIUM_CONTAINS_DEPTH_MAX_DEFAULT 5 #define STARFORTH_CONFIG_STADIUM_CONTAINS_DEPTH_MAX_DEFAULT 5
#define STARFORTH_CONFIG_STADIUM_CAPACITY_TICK_DEFAULT 1000 #define STARFORTH_CONFIG_STADIUM_CAPACITY_TICK_DEFAULT 1000
#define STARFORTH_CONFIG_STADIUM_MEMORY_PERCENT_DEFAULT 1 #define STARFORTH_CONFIG_STADIUM_MEMORY_PERCENT_DEFAULT 1
@@ -161,8 +161,8 @@
#define HEARTBEAT_INFERENCE_FREQUENCY STARFORTH_CONFIG_HEARTBEAT_INFERENCE_FREQUENCY_DEFAULT #define HEARTBEAT_INFERENCE_FREQUENCY STARFORTH_CONFIG_HEARTBEAT_INFERENCE_FREQUENCY_DEFAULT
#endif #endif
#ifndef STADIUM_MAX_VM_COUNT #ifndef STADIUM_VM_MEMORY_PERCENT
#define STADIUM_MAX_VM_COUNT STARFORTH_CONFIG_STADIUM_MAX_VM_COUNT_DEFAULT #define STADIUM_VM_MEMORY_PERCENT STARFORTH_CONFIG_STADIUM_VM_MEMORY_PERCENT_DEFAULT
#endif #endif
#ifndef STADIUM_CONTAINS_DEPTH_MAX #ifndef STADIUM_CONTAINS_DEPTH_MAX
+1 -1
View File
@@ -55,7 +55,7 @@ typedef enum {
CAPSULE_RUN_ERR_EXEC_FAIL, /* Execution failed */ CAPSULE_RUN_ERR_EXEC_FAIL, /* Execution failed */
CAPSULE_RUN_ERR_HASH_MISMATCH, /* Post-run hash mismatch */ CAPSULE_RUN_ERR_HASH_MISMATCH, /* Post-run hash mismatch */
CAPSULE_RUN_ERR_STILLBORN, /* VM birth failed */ 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) */ CAPSULE_RUN_ERR_FLEET_FULL, /* Outer Stadium at stadium_max_vm_count() (FABRIC.md item 1.5/2.2) */
} CapsuleRunResult; } CapsuleRunResult;
/*=========================================================================== /*===========================================================================
+55 -29
View File
@@ -118,40 +118,53 @@ typedef char stadium_contains_depth_configured_check[(STADIUM_CONTAINS_DEPTH_MAX
typedef char stadium_capacity_tick_configured_check[(STADIUM_CAPACITY_TICK > 0) ? 1 : -1]; typedef char stadium_capacity_tick_configured_check[(STADIUM_CAPACITY_TICK > 0) ? 1 : -1];
/* /*
* Item 3.7: the per-cell owner array stores a quota-slot index in a single * Item 3.7, revised 2026-08-15: the per-cell owner array stores a quota-slot
* uint8_t, so STADIUM_MAX_VM_COUNT must fit in one byte. Default 4, so this * index. The VM population bound is no longer a compile-time constant (see
* holds by a wide margin -- checked because it is depended on, not because * stadium_max_vm_count() below), so this can no longer be a compile-time
* it is expected to fail. * assert -- the owner element type is now uint16_t (65535 slots of
* headroom), and stadium_boot_init() itself clamps the computed count to
* that range at runtime, logging if it ever has to.
*/ */
typedef char stadium_max_vm_count_fits_owner_byte_check[(STADIUM_MAX_VM_COUNT <= 255) ? 1 : -1];
/* /*
* stadium_boot_init - Boot-time allocation (FABRIC.md item 3.2, §17.6 position * stadium_boot_init - Boot-time allocation (FABRIC.md item 3.2, §17.6 position
* (b)). Sizes the global cell array from the memory budget actually observed * (b)). Sizes the global cell array from the memory budget actually observed
* at boot -- STADIUM_MEMORY_PERCENT of pmm_get_stats().free_bytes at the * at boot -- STADIUM_MEMORY_PERCENT of kmalloc_get_stats().free_bytes at the
* point of the call, rounded down to whole STADIUM_CELL_BYTES cells -- rather * point of the call, rounded down to whole STADIUM_CELL_BYTES cells -- rather
* than a hardcoded count. Also allocates the header/continuation discriminator * than a hardcoded count. (Corrected 2026-08-15 from pmm_get_stats(): PMM's
* bitmap item 3.1 declared but did not allocate: one bit per cell, bit set * free-byte figure reflects physical pages not yet handed to any subsystem,
* means the cell at that index is a patron header, clear means continuation * but kmalloc_init() (M6) already carved its own fixed-size heap out of PMM
* or not yet in use. Both are kmalloc'd (freestanding kernel, no separate * before this ever runs, and every allocation in this function actually
* PMM-backed region needed for this) and explicitly zero-filled, since * draws from that kmalloc heap, not raw PMM -- pmm_get_stats() was budgeting
* kmalloc does not zero. * against a pool nothing here actually allocates from.) Also computes the
* outer Stadium's VM population bound the same way, from the kmalloc heap's
* *remaining* free bytes after the cell array's own allocation: see
* stadium_max_vm_count() below. Also allocates the header/continuation
* discriminator bitmap item 3.1 declared but did not allocate: one bit per
* cell, bit set means the cell at that index is a patron header, clear means
* continuation or not yet in use. Both are kmalloc'd (freestanding kernel,
* no separate PMM-backed region needed for this) and explicitly zero-filled,
* since kmalloc does not zero.
* *
* (Item 3.7) Also allocates a per-cell owner byte array (which VM's quota a * (Item 3.7) Also allocates a per-cell owner array (which VM's quota a cell
* cell belongs to) and chains every cell into a single free list, in * belongs to; uint16_t as of 2026-08-15, see the note above) and chains
* ascending index order, granted in full to vm_id 0 (Hera) -- the only VM * every cell into a single free list, in ascending index order, granted in
* that exists (item 0.1). Ascending order guarantees the first-ever * full to vm_id 0 (Hera) -- the only VM that exists (item 0.1). Ascending
* admission pops cell 0, preserving item 3.6's "Hera is patron zero" * order guarantees the first-ever admission pops cell 0, preserving item
* invariant once real birth-wiring calls stadium_admit() for the first * 3.6's "Hera is patron zero" invariant once real birth-wiring calls
* time. The free-list next-pointer reuses each cell's own `link` field * stadium_admit() for the first time. The free-list next-pointer reuses
* while unresident -- a repurposing of documented-but-unspecified storage, * each cell's own `link` field while unresident -- a repurposing of
* not a header change; see stadium_admit()'s doc for why this doesn't * documented-but-unspecified storage, not a header change; see
* answer the separate, still-open continuation-chain question. * stadium_admit()'s doc for why this doesn't answer the separate,
* still-open continuation-chain question.
*
* Also allocates the VM quota array (stadium_quotas), sized to the
* computed stadium_max_vm_count() rather than a compile-time bound.
* *
* Must be called after M6 (kmalloc_init) and before any VM is born (§6). Does * Must be called after M6 (kmalloc_init) and before any VM is born (§6). Does
* not halt boot on failure -- nothing downstream consumes the Stadium yet. * not halt boot on failure -- nothing downstream consumes the Stadium yet.
* *
* @return 0 on success, -1 if kmalloc failed for any of the three allocations. * @return 0 on success, -1 if kmalloc failed for any of the four allocations.
*/ */
int stadium_boot_init(void); int stadium_boot_init(void);
@@ -161,6 +174,15 @@ int stadium_is_initialized(void);
/* stadium_cell_count - Number of cells in the array, 0 if not initialized. */ /* stadium_cell_count - Number of cells in the array, 0 if not initialized. */
size_t stadium_cell_count(void); size_t stadium_cell_count(void);
/*
* stadium_max_vm_count - The outer Stadium's VM population bound, computed
* at stadium_boot_init() from the kmalloc heap's remaining free bytes
* (replaces the old compile-time STADIUM_MAX_VM_COUNT, 2026-08-15 -- see
* stadium_boot_init()'s own doc). 0 if not initialized. capsule_birth.c's
* birth gate reads this instead of a macro.
*/
size_t stadium_max_vm_count(void);
/* stadium_cells - Pointer to the cell array, NULL if not initialized. */ /* stadium_cells - Pointer to the cell array, NULL if not initialized. */
StadiumCell *stadium_cells(void); StadiumCell *stadium_cells(void);
@@ -309,7 +331,7 @@ uint64_t stadium_reservoir_peek(VMUuid vm_id);
/* /*
* stadium_quota_slot_for_vm - Read-only: vm_id's quota slot index (0 to * stadium_quota_slot_for_vm - Read-only: vm_id's quota slot index (0 to
* STADIUM_MAX_VM_COUNT-1), for callers outside stadium.c that need to key * stadium_max_vm_count()-1), for callers outside stadium.c that need to key
* their own per-VM state the same way stadium.c's internal arrays already * their own per-VM state the same way stadium.c's internal arrays already
* do (FABRIC.md §25.5 item 4.2 -- stadium_words.c's word_id -> cell_index * do (FABRIC.md §25.5 item 4.2 -- stadium_words.c's word_id -> cell_index
* map needs this to stop colliding across VMs; word_id is scoped per-VM, * map needs this to stop colliding across VMs; word_id is scoped per-VM,
@@ -366,10 +388,14 @@ int stadium_evict(size_t cell_index);
/* /*
* StadiumVMQuota - per-VM ownership of a subset of the global cell array * StadiumVMQuota - per-VM ownership of a subset of the global cell array
* (FABRIC.md §22.3, item 3.7: "each VM holds its own free-list head index * (FABRIC.md §22.3, item 3.7: "each VM holds its own free-list head index
* into the global array"). A small table, linearly searched by vm_id -- a * into the global array"). Linearly searched by vm_id -- a VMUuid (item 3.8)
* VMUuid (item 3.8) can't be used as a direct array index anyway, and * can't be used as a direct array index anyway. Was a small, compile-time-
* STADIUM_MAX_VM_COUNT is small enough (default 4) that a linear scan costs * bounded table (linear scan "costs nothing" at the old default of 4);
* nothing. Not exposed outside stadium.c: nothing outside needs to inspect * since 2026-08-15 the table is sized at boot from stadium_max_vm_count()
* and could genuinely be large, so this scan is no longer assumed free --
* flagged here rather than silently carried forward as still-obviously-fine,
* though no algorithmic change was made in this pass. Not exposed outside
* stadium.c: nothing outside needs to inspect
* quota state directly yet. Slot emptiness is tracked by an internal * quota state directly yet. Slot emptiness is tracked by an internal
* `in_use` flag, not a vm_id sentinel value -- there is no unused vm_id bit * `in_use` flag, not a vm_id sentinel value -- there is no unused vm_id bit
* pattern to reserve for it. * pattern to reserve for it.
@@ -449,7 +475,7 @@ size_t stadium_admit(VMUuid vm_id, const StadiumPatronHeader *candidate);
* REFUSES (returns -1, does not crash) if: the Stadium is not initialized; * REFUSES (returns -1, does not crash) if: the Stadium is not initialized;
* new_vm_id already holds a quota; from_vm_id holds no quota; from_vm_id's * new_vm_id already holds a quota; from_vm_id holds no quota; from_vm_id's
* free list has fewer than 2 cells (nothing to split); or no empty quota * free list has fewer than 2 cells (nothing to split); or no empty quota
* slot remains (STADIUM_MAX_VM_COUNT exhausted). * slot remains (stadium_max_vm_count() exhausted).
* *
* @param new_vm_id The VM receiving a fresh quota. Must not already have one. * @param new_vm_id The VM receiving a fresh quota. Must not already have one.
* @param from_vm_id The VM whose free list is split. Must already hold a quota. * @param from_vm_id The VM whose free list is split. Must already hold a quota.
+9 -5
View File
@@ -47,11 +47,15 @@
#include "starkernel/vm_uuid.h" #include "starkernel/vm_uuid.h"
/* /*
* stadium_words_init - Zeroes the word_id -> cell_index map (DICTIONARY_SIZE * stadium_words_init - Allocates and zeroes the word_id -> cell_index map
* entries per VM quota slot, STADIUM_MAX_VM_COUNT slots, static -- no * (DICTIONARY_SIZE entries per VM quota slot, stadium_max_vm_count() slots,
* allocation). Must be called after stadium_boot_init() and * kmalloc'd -- was a flat static array before 2026-08-15, when the VM count
* stadium_birth_hera(), before any word ever dispatches. Safe to call again * bound became RAM-derived rather than a compile-time constant). Must be
* (re-zeroes for every slot); nothing does today. * called after stadium_boot_init() and stadium_birth_hera(), before any word
* ever dispatches. NOT safe to call twice -- unlike the old zero-only
* version, a second call would kmalloc a second set of tables and leak the
* first; guarded internally as a no-op if already initialized. Nothing
* calls it twice today.
* *
* item 4.2 (FABRIC.md §25.5): the map is keyed by quota slot, not just * item 4.2 (FABRIC.md §25.5): the map is keyed by quota slot, not just
* word_id -- word_id is assigned per-VM (vm->next_word_id), not globally * word_id -- word_id is assigned per-VM (vm->next_word_id), not globally
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
+1 -2
View File
@@ -34,7 +34,6 @@
#include "starkernel/vm/stadium.h" /* item 4.1a -- stadium_grant_quota() */ #include "starkernel/vm/stadium.h" /* item 4.1a -- stadium_grant_quota() */
#include "vm.h" #include "vm.h"
#include "platform_alloc.h" #include "platform_alloc.h"
#include "starforth_config.h" /* STADIUM_MAX_VM_COUNT */
/*=========================================================================== /*===========================================================================
* VM Execution Hooks * VM Execution Hooks
@@ -451,7 +450,7 @@ CapsuleRunResult capsule_birth_baby(
CapsuleValidateResult vr = capsule_validate(cap, arena, dir->arena_size, 1); CapsuleValidateResult vr = capsule_validate(cap, arena, dir->arena_size, 1);
if (vr != CAPSULE_VALID) return CAPSULE_RUN_ERR_INVALID; if (vr != CAPSULE_VALID) return CAPSULE_RUN_ERR_INVALID;
if (vm_registry_live_count() >= STADIUM_MAX_VM_COUNT) { if (vm_registry_live_count() >= stadium_max_vm_count()) {
capsule_parity_log_birth_failed(vm_uuid_none(), cap->capsule_id, capsule_parity_log_birth_failed(vm_uuid_none(), cap->capsule_id,
CAPSULE_RUN_ERR_FLEET_FULL, 0); CAPSULE_RUN_ERR_FLEET_FULL, 0);
return CAPSULE_RUN_ERR_FLEET_FULL; return CAPSULE_RUN_ERR_FLEET_FULL;
+81 -32
View File
@@ -39,12 +39,18 @@
#include "starkernel/console.h" #include "starkernel/console.h"
#include "starkernel/hal/hal.h" #include "starkernel/hal/hal.h"
#include "starkernel/q48_16.h" /* Q48_ONE -- item 4.1's reservoir starts each VM's quota at 1.0 */ #include "starkernel/q48_16.h" /* Q48_ONE -- item 4.1's reservoir starts each VM's quota at 1.0 */
#include "vm.h" /* VM_MEMORY_SIZE -- the per-VM footprint stadium_max_vm_count() budgets against */
static StadiumCell *stadium_cell_array = (StadiumCell *)0; static StadiumCell *stadium_cell_array = (StadiumCell *)0;
static uint8_t *stadium_bitmap = (uint8_t *)0; static uint8_t *stadium_bitmap = (uint8_t *)0;
static uint8_t *stadium_owner = (uint8_t *)0; static uint16_t *stadium_owner = (uint16_t *)0; /* widened from uint8_t
2026-08-15: the VM-count bound is no longer capped at
255 (see stadium_max_vm_count_val below), so a byte
could silently wrap. 65535 is ample headroom. */
static size_t stadium_ncells = 0; static size_t stadium_ncells = 0;
static int stadium_initialized = 0; static int stadium_initialized = 0;
static size_t stadium_max_vm_count_val = 0; /* computed at boot, see
stadium_boot_init() and stadium_max_vm_count() */
/* Sentinel for the header's `link` field while it is reused as a free-list /* Sentinel for the header's `link` field while it is reused as a free-list
* next-pointer (item 3.7): link is uint32_t, but STADIUM_CELL_NONE is * next-pointer (item 3.7): link is uint32_t, but STADIUM_CELL_NONE is
@@ -79,12 +85,15 @@ typedef struct {
* checks the fleet sum. */ * checks the fleet sum. */
} StadiumVMQuota; } StadiumVMQuota;
static StadiumVMQuota stadium_quotas[STADIUM_MAX_VM_COUNT]; /* kmalloc'd at stadium_boot_init() to stadium_max_vm_count_val entries,
* replacing the old static StadiumVMQuota stadium_quotas[STADIUM_MAX_VM_COUNT]
* (2026-08-15: the bound is computed from RAM, not a compile-time constant). */
static StadiumVMQuota *stadium_quotas = (StadiumVMQuota *)0;
/* Returns the quota slot index for vm_id, or -1 if none is granted. */ /* Returns the quota slot index for vm_id, or -1 if none is granted. */
static int quota_slot_for_vm(VMUuid vm_id) { static int quota_slot_for_vm(VMUuid vm_id) {
int i; size_t i;
for (i = 0; i < STADIUM_MAX_VM_COUNT; i++) { for (i = 0; i < stadium_max_vm_count_val; i++) {
if (stadium_quotas[i].in_use && vm_uuid_equal(stadium_quotas[i].vm_id, vm_id)) return i; if (stadium_quotas[i].in_use && vm_uuid_equal(stadium_quotas[i].vm_id, vm_id)) return i;
} }
return -1; return -1;
@@ -107,8 +116,14 @@ static void console_put_u64(uint64_t v) {
} }
int stadium_boot_init(void) { int stadium_boot_init(void) {
pmm_stats_t pmm = pmm_get_stats(); /* Budgeted from kmalloc_get_stats(), not pmm_get_stats() (corrected
uint64_t budget_bytes = (pmm.free_bytes * (uint64_t)STADIUM_MEMORY_PERCENT) / 100u; * 2026-08-15 -- see this function's doc in stadium.h): kmalloc_init()
* (M6) already carved its own fixed-size heap out of PMM before this
* ever runs, and every allocation below draws from that heap, not raw
* PMM, so PMM's own free-byte figure was the wrong pool to budget
* against. */
kmalloc_stats_t kstats = kmalloc_get_stats();
uint64_t budget_bytes = (kstats.free_bytes * (uint64_t)STADIUM_MEMORY_PERCENT) / 100u;
size_t ncells = (size_t)(budget_bytes / STADIUM_CELL_BYTES); size_t ncells = (size_t)(budget_bytes / STADIUM_CELL_BYTES);
size_t bitmap_bytes = (ncells + 7u) / 8u; size_t bitmap_bytes = (ncells + 7u) / 8u;
@@ -117,9 +132,9 @@ int stadium_boot_init(void) {
return -1; return -1;
} }
StadiumCell *cells = (StadiumCell *)kmalloc(ncells * STADIUM_CELL_BYTES); StadiumCell *cells = (StadiumCell *)kmalloc(ncells * STADIUM_CELL_BYTES);
uint8_t *bitmap = (uint8_t *)kmalloc(bitmap_bytes); uint8_t *bitmap = (uint8_t *)kmalloc(bitmap_bytes);
uint8_t *owner = (uint8_t *)kmalloc(ncells); uint16_t *owner = (uint16_t *)kmalloc(ncells * sizeof(uint16_t));
if (!cells || !bitmap || !owner) { if (!cells || !bitmap || !owner) {
console_println("Stadium: kmalloc failed for boot-time allocation"); console_println("Stadium: kmalloc failed for boot-time allocation");
if (cells) kfree(cells); if (cells) kfree(cells);
@@ -128,6 +143,32 @@ int stadium_boot_init(void) {
return -1; return -1;
} }
/* VM population bound (2026-08-15, replaces compile-time
* STADIUM_MAX_VM_COUNT): STADIUM_VM_MEMORY_PERCENT of whatever's left
* in the kmalloc heap AFTER the cell array above, divided by
* VM_MEMORY_SIZE (the real per-VM footprint -- 5 MiB, include/vm.h --
* not the small quota/word-slot bookkeeping tables). Floored to 1 so
* Hera can always boot; no ceiling otherwise (Captain Bob, 2026-08-15:
* the population is not knowable in advance). Clamped to what the
* uint16_t owner array can index, logged if that ever actually bites. */
kmalloc_stats_t kstats_after_cells = kmalloc_get_stats();
uint64_t vm_budget_bytes = (kstats_after_cells.free_bytes * (uint64_t)STADIUM_VM_MEMORY_PERCENT) / 100u;
size_t max_vm_count = (size_t)(vm_budget_bytes / VM_MEMORY_SIZE);
if (max_vm_count < 1u) max_vm_count = 1u;
if (max_vm_count > 65535u) {
console_println("Stadium: computed VM count exceeds owner-index range, clamped to 65535");
max_vm_count = 65535u;
}
StadiumVMQuota *quotas = (StadiumVMQuota *)kmalloc(max_vm_count * sizeof(StadiumVMQuota));
if (!quotas) {
console_println("Stadium: kmalloc failed for VM quota table");
kfree(cells);
kfree(bitmap);
kfree(owner);
return -1;
}
{ {
uint8_t *raw = (uint8_t *)cells; uint8_t *raw = (uint8_t *)cells;
size_t n = ncells * STADIUM_CELL_BYTES; size_t n = ncells * STADIUM_CELL_BYTES;
@@ -153,33 +194,37 @@ int stadium_boot_init(void) {
} }
} }
{ {
int i; size_t i;
for (i = 0; i < STADIUM_MAX_VM_COUNT; i++) { for (i = 0; i < max_vm_count; i++) {
stadium_quotas[i].vm_id = vm_uuid_none(); quotas[i].vm_id = vm_uuid_none();
stadium_quotas[i].in_use = 0; quotas[i].in_use = 0;
stadium_quotas[i].free_head = STADIUM_CELL_NONE; quotas[i].free_head = STADIUM_CELL_NONE;
stadium_quotas[i].reservoir = 0; quotas[i].reservoir = 0;
} }
} }
stadium_quotas[0].vm_id = vm_uuid_hera(); quotas[0].vm_id = vm_uuid_hera();
stadium_quotas[0].in_use = 1; quotas[0].in_use = 1;
stadium_quotas[0].free_head = 0; quotas[0].free_head = 0;
/* item 4.1, §17.7: at quota-grant time, before any resident patron /* item 4.1, §17.7: at quota-grant time, before any resident patron
* exists, the reservoir holds the VM's entire conserved share -- mirrors * exists, the reservoir holds the VM's entire conserved share -- mirrors
* Hera holding the fleet's whole Q48_ONE before any other VM is born. */ * Hera holding the fleet's whole Q48_ONE before any other VM is born. */
stadium_quotas[0].reservoir = Q48_ONE; quotas[0].reservoir = Q48_ONE;
stadium_cell_array = cells; stadium_cell_array = cells;
stadium_bitmap = bitmap; stadium_bitmap = bitmap;
stadium_owner = owner; stadium_owner = owner;
stadium_ncells = ncells; stadium_ncells = ncells;
stadium_initialized = 1; stadium_quotas = quotas;
stadium_max_vm_count_val = max_vm_count;
stadium_initialized = 1;
console_puts("Stadium: "); console_puts("Stadium: ");
console_put_u64((uint64_t)ncells); console_put_u64((uint64_t)ncells);
console_puts(" cells ("); console_puts(" cells (");
console_put_u64((uint64_t)(ncells * STADIUM_CELL_BYTES) / 1024u); console_put_u64((uint64_t)(ncells * STADIUM_CELL_BYTES) / 1024u);
console_println(" KB)"); console_puts(" KB), ");
console_put_u64((uint64_t)max_vm_count);
console_println(" VM slots");
return 0; return 0;
} }
@@ -192,6 +237,10 @@ size_t stadium_cell_count(void) {
return stadium_ncells; return stadium_ncells;
} }
size_t stadium_max_vm_count(void) {
return stadium_max_vm_count_val;
}
StadiumCell *stadium_cells(void) { StadiumCell *stadium_cells(void) {
return stadium_cell_array; return stadium_cell_array;
} }
@@ -276,7 +325,7 @@ static void bitmap_clear(size_t cell_index) {
*/ */
int stadium_evict(size_t cell_index) { int stadium_evict(size_t cell_index) {
StadiumPatronHeader *header; StadiumPatronHeader *header;
uint8_t slot; uint16_t slot;
if (cell_index >= stadium_ncells) return -1; if (cell_index >= stadium_ncells) return -1;
if (!bitmap_get(cell_index)) return -1; if (!bitmap_get(cell_index)) return -1;
@@ -361,7 +410,7 @@ size_t stadium_admit(VMUuid vm_id, const StadiumPatronHeader *candidate) {
/* Item 4.2 fix (§25.7): record ownership so stadium_evict()'s /* Item 4.2 fix (§25.7): record ownership so stadium_evict()'s
* reservoir credit and free-list return land on the VM that actually * reservoir credit and free-list return land on the VM that actually
* admitted this patron, not whatever owner[idx] held at boot. */ * admitted this patron, not whatever owner[idx] held at boot. */
stadium_owner[idx] = (uint8_t)slot; stadium_owner[idx] = (uint16_t)slot;
return idx; return idx;
} }
@@ -369,7 +418,7 @@ size_t stadium_admit(VMUuid vm_id, const StadiumPatronHeader *candidate) {
StadiumPatronHeader *h; StadiumPatronHeader *h;
if (!bitmap_get(i)) continue; if (!bitmap_get(i)) continue;
if (stadium_owner[i] != (uint8_t)slot) continue; if (stadium_owner[i] != (uint16_t)slot) continue;
h = &stadium_cell_array[i].header; h = &stadium_cell_array[i].header;
if (h->flags & STADIUM_FLAG_PIN) continue; if (h->flags & STADIUM_FLAG_PIN) continue;
if (h->contains != STADIUM_CONTAINS_NONE) continue; if (h->contains != STADIUM_CONTAINS_NONE) continue;
@@ -403,7 +452,7 @@ size_t stadium_admit(VMUuid vm_id, const StadiumPatronHeader *candidate) {
* owner[idx] = slot as part of reaping least_dense_index, so this is * owner[idx] = slot as part of reaping least_dense_index, so this is
* currently a no-op in practice, but it must not be assumed to stay a * currently a no-op in practice, but it must not be assumed to stay a
* no-op: this is the correctness statement, not a redundant write. */ * no-op: this is the correctness statement, not a redundant write. */
stadium_owner[idx] = (uint8_t)slot; stadium_owner[idx] = (uint16_t)slot;
return idx; return idx;
} }
@@ -425,7 +474,7 @@ int stadium_grant_quota(VMUuid new_vm_id, VMUuid from_vm_id) {
if (from_slot < 0) return -1; if (from_slot < 0) return -1;
new_slot = -1; new_slot = -1;
for (i = 0; i < STADIUM_MAX_VM_COUNT; i++) { for (i = 0; i < (int)stadium_max_vm_count_val; i++) {
if (!stadium_quotas[i].in_use) { new_slot = i; break; } if (!stadium_quotas[i].in_use) { new_slot = i; break; }
} }
if (new_slot < 0) return -1; if (new_slot < 0) return -1;
@@ -444,7 +493,7 @@ int stadium_grant_quota(VMUuid new_vm_id, VMUuid from_vm_id) {
idx = new_head; idx = new_head;
last_new = STADIUM_CELL_NONE; last_new = STADIUM_CELL_NONE;
for (i = 0; i < (int)half; i++) { for (i = 0; i < (int)half; i++) {
stadium_owner[idx] = (uint8_t)new_slot; stadium_owner[idx] = (uint16_t)new_slot;
last_new = idx; last_new = idx;
idx = link_to_size(stadium_cell_array[idx].header.link); idx = link_to_size(stadium_cell_array[idx].header.link);
} }
@@ -469,7 +518,7 @@ static int owned_resident_slot(VMUuid vm_id, size_t cell_index) {
if (slot < 0) return -1; if (slot < 0) return -1;
if (cell_index >= stadium_ncells) return -1; if (cell_index >= stadium_ncells) return -1;
if (!bitmap_get(cell_index)) return -1; if (!bitmap_get(cell_index)) return -1;
if (stadium_owner[cell_index] != (uint8_t)slot) return -1; if (stadium_owner[cell_index] != (uint16_t)slot) return -1;
return slot; return slot;
} }
@@ -539,7 +588,7 @@ uint64_t stadium_resident_sum(VMUuid vm_id) {
for (i = 0; i < stadium_ncells; i++) { for (i = 0; i < stadium_ncells; i++) {
if (!bitmap_get(i)) continue; if (!bitmap_get(i)) continue;
if (stadium_owner[i] != (uint8_t)slot) continue; if (stadium_owner[i] != (uint16_t)slot) continue;
sum += stadium_cell_array[i].header.heat; sum += stadium_cell_array[i].header.heat;
} }
return sum; return sum;
+53 -6
View File
@@ -32,6 +32,7 @@
#include "starkernel/vm/stadium.h" #include "starkernel/vm/stadium.h"
#include "starkernel/console.h" #include "starkernel/console.h"
#include "starkernel/kmalloc.h"
#include "starkernel/q48_16.h" /* Q48_ONE -- diagnostic print only */ #include "starkernel/q48_16.h" /* Q48_ONE -- diagnostic print only */
#include "vm.h" /* DICTIONARY_SIZE, WORD_ID_INVALID */ #include "vm.h" /* DICTIONARY_SIZE, WORD_ID_INVALID */
@@ -55,15 +56,61 @@ typedef struct {
uint64_t last_decay_tick; uint64_t last_decay_tick;
} StadiumWordSlot; } StadiumWordSlot;
static StadiumWordSlot word_slots[STADIUM_MAX_VM_COUNT][DICTIONARY_SIZE]; /* Row-per-quota-slot, kmalloc'd at stadium_words_init() to stadium_max_vm_
static int words_initialized = 0; * count() rows of DICTIONARY_SIZE entries each -- replaces the old static
static uint64_t stat_promotions[STADIUM_MAX_VM_COUNT]; * word_slots[STADIUM_MAX_VM_COUNT][DICTIONARY_SIZE] (2026-08-15: the VM
static uint64_t stat_evictions[STADIUM_MAX_VM_COUNT]; * count bound is computed from RAM, not a compile-time constant, so this
* can no longer be a flat static array). */
static StadiumWordSlot **word_slots = (StadiumWordSlot **)0;
static int words_initialized = 0;
static uint64_t *stat_promotions = (uint64_t *)0;
static uint64_t *stat_evictions = (uint64_t *)0;
void stadium_words_init(void) { void stadium_words_init(void) {
int slot; size_t slot;
uint32_t i; uint32_t i;
for (slot = 0; slot < STADIUM_MAX_VM_COUNT; slot++) { size_t count = stadium_max_vm_count();
if (words_initialized) return; /* not re-entrant -- see stadium_words.h */
if (count == 0) {
console_println("Stadium words: init skipped (Stadium not initialized)");
return;
}
word_slots = (StadiumWordSlot **)kmalloc(count * sizeof(StadiumWordSlot *));
stat_promotions = (uint64_t *)kmalloc(count * sizeof(uint64_t));
stat_evictions = (uint64_t *)kmalloc(count * sizeof(uint64_t));
if (!word_slots || !stat_promotions || !stat_evictions) {
console_println("Stadium words: kmalloc failed for per-VM tables");
if (word_slots) kfree(word_slots);
if (stat_promotions) kfree(stat_promotions);
if (stat_evictions) kfree(stat_evictions);
word_slots = (StadiumWordSlot **)0;
stat_promotions = (uint64_t *)0;
stat_evictions = (uint64_t *)0;
return;
}
for (slot = 0; slot < count; slot++) {
word_slots[slot] = (StadiumWordSlot *)kmalloc(DICTIONARY_SIZE * sizeof(StadiumWordSlot));
if (!word_slots[slot]) {
console_println("Stadium words: kmalloc failed for a word-slot row");
/* Free everything allocated so far, including this row's
* predecessors, and bail the same all-or-nothing way
* stadium_boot_init() does. */
{
size_t j;
for (j = 0; j < slot; j++) kfree(word_slots[j]);
}
kfree(word_slots);
kfree(stat_promotions);
kfree(stat_evictions);
word_slots = (StadiumWordSlot **)0;
stat_promotions = (uint64_t *)0;
stat_evictions = (uint64_t *)0;
return;
}
for (i = 0; i < DICTIONARY_SIZE; i++) { for (i = 0; i < DICTIONARY_SIZE; i++) {
word_slots[slot][i].cell_index = STADIUM_CELL_NONE; word_slots[slot][i].cell_index = STADIUM_CELL_NONE;
word_slots[slot][i].last_decay_tick = 0; word_slots[slot][i].last_decay_tick = 0;