Stage MC-0a: per-core block on one core -- current VM moves behind the per-CPU register (FABRIC-3.10.8 §3.1)
- New sk_percpu_t { self, core_id, current_vm }, reached via GS base
(amd64, %gs:0), TPIDR_EL1 (aarch64), tp (riscv64). Boot core's block is
one static object installed right after arch_early_init(); secondary
cores' blocks come with MC-1.
- switch.c's global g_switch_current_vm is gone; current VM is
sk_percpu()->current_vm, re-read after resume in the context switch.
- Probe (removed): normal path and every heartbeat ISR found core 0's
block on all three ISAs (ISR ok 889/1877/1625, bad 0).
- Standard sequence on amd64/aarch64/riscv64: hashes unchanged from O-C,
G A=40 B=40, MINT/WIREBIND/USE ok, conservation true, 0 idle growth.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5.5
parent
8d33f7a959
commit
8409e376cf
+37
-1
@@ -78,4 +78,40 @@ Everything that would break if two cores ran kernel or VM code at the same momen
|
||||
|
||||
## 3. Execution log
|
||||
|
||||
*(none yet)*
|
||||
### 3.1 MC-0a — the per-core block, on one core (2026-09-25)
|
||||
|
||||
**Change.**
|
||||
- `include/starkernel/percpu.h` (new): `sk_percpu_t { self, core_id, current_vm }`, with `self` first.
|
||||
- `sk_percpu()` reads this core's block: `movq %gs:0` on amd64, `mrs tpidr_el1` on aarch64, `mv tp` on riscv64.
|
||||
- `sk_percpu_install()` writes the register: `IA32_GS_BASE` via `wrmsr`, `TPIDR_EL1`, or `tp`.
|
||||
- `src/starkernel/hal/percpu.c` (new): the boot core's block is one static object, not a table sized to a core count. Secondary cores get theirs as they come online (MC-1).
|
||||
- `kernel_main.c`: `sk_percpu_boot_init()` runs straight after `arch_early_init()`, because on amd64 that call reloads GS, which would reset the base.
|
||||
- `switch.c`: the global `g_switch_current_vm` is gone.
|
||||
- `sk_vm_switch_current_vm()`, the setter, the idle point and `sk_vm_context_switch()` use `sk_percpu()->current_vm`.
|
||||
- After resume, the context switch re-reads the block rather than trusting a pointer cached before the switch.
|
||||
|
||||
**Probe** (temporary; removed before commit).
|
||||
- `kernel_main.c` checked, from the normal path after the Tripod came up, that:
|
||||
- `sk_percpu()->self == sk_percpu()`;
|
||||
- `core_id == 0`;
|
||||
- `current_vm` is Hera;
|
||||
- `sk_vm_switch_current_vm()` agrees.
|
||||
- `heartbeat_tick()` ran the same self-check from interrupt context on every beat.
|
||||
|
||||
| ISA | log | normal path | core_id | current_vm is Hera | switch.c agrees | interrupt path ok / bad |
|
||||
|---|---|---|---|---|---|---|
|
||||
| amd64 | `logs/20260925-130335` | ok | 0 | 1 | 1 | 889 / 0 |
|
||||
| aarch64 | `logs/20260925-130905` | ok | 0 | 1 | 1 | 1877 / 0 |
|
||||
| riscv64 | `logs/20260925-131337` | ok | 0 | 1 | 1 | 1625 / 0 |
|
||||
|
||||
**Standard sequence** (clean build, with the probe reverted; the tree was checked byte-for-byte against the saved stage diff).
|
||||
|
||||
| ISA | log | O-A (G, PREC, LOAD) | M7.1a hash | MINT / WIREBIND / USE / `1 2 + .` | idle growth | UNKNOWN / faults |
|
||||
|---|---|---|---|---|---|---|
|
||||
| amd64 | `logs/20260925-131805` | A=40 B=40, HHH, ok | `0x99b01134c3d3049c` | all ok, `3` | 0 B / 20 s | 0 / 0 |
|
||||
| aarch64 | `logs/20260925-133049` | A=40 B=40, HHH, ok | `0x99b01134c3d3049c` | all ok, `3` | 0 B / 20 s | 0 / 0 |
|
||||
| riscv64 | `logs/20260925-134357` | A=40 B=40, HHH, ok | `0x99b01134c3d3049c` | all ok, `3` | 0 B / 20 s | 0 / 0 |
|
||||
|
||||
- The `dict_hash` values (Hera `0x00340a8b2c842eb7`, Hestia `0x78bf28439e4a643f`, Artemis `0x66886d174d5f3b5a`) are identical across ISAs and unchanged from O-C.
|
||||
- The ledger line matches across ISAs: held=2048, pulled=258048, returned=255263, consumed=737, conserved=true.
|
||||
- No stop condition was hit. **MC-0a done.**
|
||||
|
||||
Reference in New Issue
Block a user