§H.12 steps 5-6: pin Hera/Hermes/Artemis in generic capsule-birth admission
capsule_birth.c's generic admission block now registers a session for every born VM (session_register) and pins it (session_set_pinned) when the birthing capsule is Hera/Hermes/Artemis. Bug found and fixed via a temporary probe (written, run, captured, reverted): the fleet-foundation name check first used an exact-match comparison against "Hermes"/"Artemis", but capsule_name is actually "hermes:init.4th"/"artemis:init.4th" (the real namespace:filename convention) -- the check silently never matched, both would-be-pinned VMs stayed unpinned. Fixed with a new vm_name_prefix_eq_nocase() helper matching everything before a literal ':'. Probe confirmed pinned=0 before the fix, pinned=1 after, on all relevant VMs. Session.parent is hardcoded to vm_uuid_hera() for now (every birth through this path is Hera-initiated today); step 7 generalizes this to the actual birthing VM's own id. Verified 3-arch boot to ok> (amd64/aarch64/riscv64) on the final, probe-free code. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5
parent
67793ea4a1
commit
09998af999
+17
-5
@@ -3982,11 +3982,23 @@ work, not new invention.
|
||||
unaffected.
|
||||
|
||||
**Phase 2 — Pin Hermes/Artemis (Correction 1 above)**
|
||||
- [ ] **5.** In `capsule_birth.c`'s existing generic admission block, add a name check
|
||||
("Hera"/"Hermes"/"Artemis" → pinned, everything else → unpinned) routed through
|
||||
`session_register()`/`session_set_pinned()`.
|
||||
- [ ] **6.** Confirm (boot-log/diagnostic) Hermes and Artemis now admit pinned; ordinary
|
||||
births still admit unpinned.
|
||||
- [x] **5. DONE 2026-09-03, one bug found and fixed via probe.** `capsule_birth.c`'s generic
|
||||
admission block now registers a session for every born VM and pins it if
|
||||
`is_fleet_foundation` (Hera/Hermes/Artemis). Admits unpinned then pins after, same ordering
|
||||
as step 4 (`stadium_admit()` confirmed to have no admission-time pin handling). **Bug found
|
||||
by step 6's probe**: the fleet-foundation name check first used
|
||||
`vm_name_eq_nocase(capsule_name, "Hermes")`, exact match — but `capsule_name` is actually
|
||||
`"hermes:init.4th"`/`"artemis:init.4th"` (the real "namespace:filename" convention), never
|
||||
a bare name, so the check silently never matched. Fixed with a new
|
||||
`vm_name_prefix_eq_nocase()` helper matching everything before a literal `:`. Parent is
|
||||
hardcoded to `vm_uuid_hera()` for now (every birth through this path is Hera-initiated
|
||||
today) — step 7 generalizes this to the actual birthing VM's own id.
|
||||
- [x] **6. DONE 2026-09-03.** Confirmed via a temporary probe (`console_println` after
|
||||
`session_set_pinned()`, captured once then reverted per this project's probe convention):
|
||||
first run showed `hermes:init.4th pinned=0` / `artemis:init.4th pinned=0` (the bug above),
|
||||
second run after the fix showed `pinned=1` for both. Probe code fully reverted before
|
||||
commit — only its finding (the `:`-suffixed capsule-name format) remains, in step 5's doc
|
||||
comment and this entry.
|
||||
|
||||
**Phase 3 — Session fields wired at birth**
|
||||
- [ ] **7.** Populate `Session.parent` from the birthing VM's `stadium_vm_id`.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
# Capsule Block Manifest — Auto-generated
|
||||
<!-- Generated by mkcapsule --manifest 2026-09-03T10:14:23Z -->
|
||||
<!-- Generated by mkcapsule --manifest 2026-09-03T10:24:56Z -->
|
||||
<!-- DO NOT EDIT — re-run mkcapsule --manifest to refresh. -->
|
||||
<!-- Hand-written justifications and immutability notes live -->
|
||||
<!-- in MANIFEST.md alongside this auto-generated index. -->
|
||||
|
||||
Binary file not shown.
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
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -34,6 +34,7 @@
|
||||
#include "starkernel/kmalloc.h"
|
||||
#include "starkernel/console.h"
|
||||
#include "starkernel/vm/stadium.h" /* item 4.1a -- stadium_grant_quota() */
|
||||
#include "starkernel/session.h" /* session_register()/session_set_pinned() -- FABRIC-3.md §H.12 step 5 */
|
||||
#include "vm.h"
|
||||
#include "platform_alloc.h"
|
||||
/* No LOG_LINE_MAX include-order constraint anymore: vm.h's own
|
||||
@@ -259,6 +260,21 @@ static int vm_name_eq_nocase(const char *a, const char *b) {
|
||||
return *a == *b;
|
||||
}
|
||||
|
||||
/* Case-insensitive ASCII prefix match up to (and not including) a literal
|
||||
* ':' in `str`, or the whole of `str` if it has no ':' -- capsule names use
|
||||
* a "namespace:filename" convention (e.g. "hermes:init.4th"), confirmed
|
||||
* live via a temporary probe (§H.12 step 6) rather than assumed: bare
|
||||
* vm_name_eq_nocase(capsule_name, "Hermes") never matched. `prefix` has no
|
||||
* ':' of its own. */
|
||||
static int vm_name_prefix_eq_nocase(const char *str, const char *prefix) {
|
||||
while (*str && *str != ':' && *prefix) {
|
||||
if (vm_to_lower(*str) != vm_to_lower(*prefix)) return 0;
|
||||
str++; prefix++;
|
||||
}
|
||||
if (*prefix) return 0; /* prefix longer than str's namespace segment */
|
||||
return (*str == '\0' || *str == ':');
|
||||
}
|
||||
|
||||
int capsule_vm_find_by_name_nocase(const char *name, VMRegistryEntry *out) {
|
||||
vm_node_t *node;
|
||||
if (!name || !out) return -1;
|
||||
@@ -572,22 +588,41 @@ CapsuleRunResult capsule_birth_baby(
|
||||
|
||||
/* FABRIC-3.md SS B, VM-COOL: admit this VM as a patron of its own
|
||||
* quota -- identity 0 (same convention stadium_birth_hera() uses for
|
||||
* "patron zero"), heat 0 (no reservoir cost), unpinned (unlike Hera --
|
||||
* there is no unpin primitive, and pinning here would make the
|
||||
* explicit KILL-time eviction below unreachable without adding one).
|
||||
* Unpinned means unrelated quota pressure on this VM's own words/
|
||||
* blocks could naturally evict this cell before KILL ever runs; that
|
||||
* is tolerated, not a bug -- nothing wires COOL's dispatch body to
|
||||
* kill anything, so the only visible effect is entry->stadium_
|
||||
* patron_cell going stale, which the KILL-time eviction below already
|
||||
* tolerates (stadium_evict() simply refuses if it's already gone).
|
||||
* "patron zero"), heat 0 (no reservoir cost). Admitted unpinned here
|
||||
* regardless of which VM this is -- pinning (when it applies) happens
|
||||
* through session_set_pinned() below, after admission, same
|
||||
* unpinned-then-pin ordering §H.12 step 4 already established for
|
||||
* Hera (stadium_admit() has no admission-time-special pin handling,
|
||||
* just copies the candidate header, so this ordering is safe).
|
||||
*
|
||||
* FABRIC-3.md §H.12 step 5: fleet-foundation VMs (Hera/Hermes/Artemis)
|
||||
* are pinned -- permanent, exempt from COOL, per §H.1's decision.
|
||||
* Ordinary/user VMs stay unpinned, matching the original comment's own
|
||||
* reasoning here (unrelated quota pressure can naturally evict this
|
||||
* cell before an explicit KILL runs; tolerated, not a bug -- nothing
|
||||
* wires COOL's dispatch body to kill anything, so the only visible
|
||||
* effect is entry->stadium_patron_cell going stale, which the
|
||||
* KILL-time eviction below already tolerates). The original comment's
|
||||
* "there is no unpin primitive" concern no longer applies to Hera
|
||||
* herself (session_set_pinned() now provides one, §H.12 step 3) but
|
||||
* still correctly describes why ordinary VMs -- which DO get killed --
|
||||
* must stay unpinned: nothing here ever un-pins a killed ordinary VM,
|
||||
* so it must never have been pinned to begin with.
|
||||
*
|
||||
* Soft failure, same as stadium_grant_quota() above -- a refused
|
||||
* admission leaves stadium_patron_cell at STADIUM_CELL_NONE, and
|
||||
* nothing downstream depends on it succeeding. */
|
||||
* nothing downstream depends on it succeeding. session_register()/
|
||||
* session_set_pinned() failures are soft-fail the same way (logged,
|
||||
* non-fatal) -- same reasoning §H.12 step 4 already established for
|
||||
* Hera. */
|
||||
{
|
||||
StadiumPatronHeader vm_patron;
|
||||
uint8_t *raw = (uint8_t *)&vm_patron;
|
||||
size_t i;
|
||||
int is_fleet_foundation =
|
||||
vm_name_prefix_eq_nocase(capsule_name, "Hera") ||
|
||||
vm_name_prefix_eq_nocase(capsule_name, "Hermes") ||
|
||||
vm_name_prefix_eq_nocase(capsule_name, "Artemis");
|
||||
|
||||
for (i = 0; i < sizeof(vm_patron); i++) raw[i] = 0;
|
||||
vm_patron.identity = 0;
|
||||
@@ -600,6 +635,14 @@ CapsuleRunResult capsule_birth_baby(
|
||||
vm_patron.behaviour = (uint8_t)STADIUM_BEHAVIOUR_COOL;
|
||||
|
||||
entry->stadium_patron_cell = stadium_admit(vm_id, &vm_patron);
|
||||
|
||||
if (entry->stadium_patron_cell != STADIUM_CELL_NONE) {
|
||||
Session *s = session_register(vm_id, vm_uuid_hera(), capsule_name);
|
||||
if (s) {
|
||||
s->stadium_cell = entry->stadium_patron_cell;
|
||||
if (is_fleet_foundation) session_set_pinned(vm_id, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const uint8_t *payload = capsule_get_payload(cap, arena);
|
||||
|
||||
Reference in New Issue
Block a user