FABRIC-3.10.8 MC-2: observers stay on core 0

The decision's observer pass runs only on core 0; a switch into an
observer on any other core is refused and counted (a guard, 0 in every
run). Probe posing as core 1: no observer chosen, switch refused 0 -> 1;
as core 0 the same decision returns Hestia. 3-ISA acceptance clean.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Robert Allan James
2026-09-26 14:24:47 -04:00
co-authored by Claude Opus 5.5
parent 3c07636ecd
commit c8b754fd80
12 changed files with 36665 additions and 2 deletions
+21
View File
@@ -964,3 +964,24 @@ The boot hart HSM chose (0) is the one OpenSBI names as `Boot HART ID`.
- `sk_vm_switch_decide()` returns no observer; it returns a participant or nothing.
- `sk_vm_context_switch()` to Hestia is refused, and the refusal count goes from 0 to 1.
- With `core_id` back at 0, the same decision returns Hestia.
### 6.1 MC-2 — executed (2026-09-26)
**Change.**
- **`capsule_vm_switch_signal.c`:** the observer pass of `sk_vm_switch_decide()` runs only when `sk_percpu()->core_id == 0`.
- **`switch.c`:** `sk_vm_context_switch()` refuses, before touching any state, to enter an observer on any other core. It counts the refusal (`sk_vm_switch_observer_refusals()`, declared in `switch.h`). The idle point logs `SWITCH: observer refused off core 0 xN` when the count changes.
**Probe** (temporary `MC2-PROBE` word; amd64, `logs/20260926-135242`). One console line queued a message for Hestia (`S" 1 DROP" S" Hestia" SEND .`) and then ran the probe, so Hestia held an event.
- The probe printed: `MC2 PROBE: as core 1 decide -> nothing; switch to Hestia rc=-1, refusals 0 -> 1; as core 0 decide -> Hestia`.
- The idle point then logged `SWITCH: observer refused off core 0 x1`.
- The decisions were made with no calling VM, because Hera, mid-line, would keep the CPU as an observer in progress. There were no workers, so "nothing" is the participant pass's correct answer.
**Standard sequence** (clean build, probe reverted; the tree is byte-identical to the saved stage diff):
| ISA | log | result |
|---|---|---|
| amd64 | `logs/20260926-135440` | K-10 hashes, G A=40 B=40 byte-identical, HHH, all ok `3`, ledger unchanged, 0 B idle, 0 / 0; 2 cores online; **0 observer refusals**, 0 park wakes, 0 `LOCK:` |
| aarch64 | `logs/20260926-140427` | same |
| riscv64 | `logs/20260926-141508` | same; 0 `timed out` |
**MC-2 is complete.** Next: MC-3, where worker cores claim through the shared decision. It is the stage that makes the extra cores do work, and it needs its own design section first: the claim by compare-and-swap, per-core idle contexts and beats, wake by IPI with each core's interrupt controller, and the §5.3 findings.