FABRIC-3.10.8 MC-1c: riscv64's second hart online and parked; MC-1 complete

Harts from the DTB /cpus or, on QEMU (ACPI, no DTB), the MADT RINTC
entries; the boot hart is the one SBI HSM reports STARTED. SBI HSM
hart_start into ap_entry.S (stvec/satp copied, FPU on, tp set), park.
Hart 1 online in S-mode with its own block; its vCPU thread 0.0% on the
host. QEMU riscv64 -smp 2 -name debug-threads=on. All three ISAs now
boot two cores; 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 13:50:26 -04:00
co-authored by Claude Opus 5.5
parent 3a2ba5149f
commit c081bcf87a
11 changed files with 27828 additions and 8 deletions
+33
View File
@@ -915,3 +915,36 @@ Core 1 is halted, not spinning.
**Found, not changed:** core 0's vCPU burns about 64% of a host CPU while the system is idle. The boot core's idle loop (the console poll and idle point) polls rather than halting. This predates MC-1. MC-3's criterion "idle worker cores halted, not spinning" applies to the new cores; whether core 0 should halt when idle too is a separate question for MC-3's design.
**MC-1b is complete.** Next: MC-1c (riscv64, SBI HSM `hart_start`).
### 5.3 MC-1c — riscv64's second hart online and parked; MC-1 complete (2026-09-26)
**Change.**
- **Enumeration** (`arch/riscv64/smp.c`): the devicetree's `/cpus` children (`device_type = "cpu"`, not `status = "disabled"`, `reg` = hartid) when there is a DTB. Otherwise, the ACPI MADT's enabled RINTC entries (type 0x18, hartid at +8). QEMU's EDK2 hands over ACPI and no DTB.
- **The boot hart:** S-mode cannot read `mhartid`. After probing that the HSM extension exists, the filling pass asks SBI HSM `hart_get_status` for every hart, prints each status, and takes the one STARTED hart as the boot hart. If it isn't exactly one, it says so and brings up no other hart.
- `hal/smp.c` now reads the boot core's hw id **after** the filling pass, for this reason. It makes no difference on amd64 and aarch64.
- **Start:** SBI HSM `hart_start(hartid, entry, opaque)` into `ap_entry.S` with a1 = the hart's boot block. A non-zero SBI error is printed and the start refused.
- **`ap_entry.S`:**
- It masks SIE and clears `sie`, records the a0 hartid in its boot block, and takes the boot hart's `stvec` and `satp` (Bare today, item 4.3.5a).
- It sets `sstatus.FS = Initial` with `fcsr = 0` (kernel C is lp64d), sets `tp` to its block, loads its stack, and calls `sk_smp_secondary_main()`.
- Neither `gp` nor `sscratch` is used by this kernel, so neither is copied.
- **Park:** `csrci sstatus, SIE` and `wfi`.
- **The online line** says "S-mode, a0 = its hartid" when the hartid SBI passed matches the one started.
- **QEMU:** `-smp 2 -name debug-threads=on` on the `make qemu` riscv64 line only.
**Evidence** (clean builds; the source diff is identical to the saved stage diff):
| ISA | log | SMP lines | standard sequence |
|---|---|---|---|
| riscv64 (`-smp 2`) | `logs/20260926-131910` | OpenSBI: `Platform HART Count: 2`, `Boot HART ID: 0`. `SMP: hart 0 HSM status 0 (started)`; `SMP: hart 1 HSM status 1 (stopped)`; `SMP: 2 core(s) found`; `SMP: core 1 online: hw id 0x1, block 0x0000000083fff130, per-CPU register 0x0000000083fff130 (its own block), S-mode, a0 = its hartid, 740 us, parked`; `SMP: 2 core(s) online` | K-10 hashes, G A=40 B=40 byte-identical, HHH, all ok `3`, ledger unchanged, 0 B idle, 0 / 0; **0 park-wake lines, 0 `LOCK:` lines, 0 `timed out`** |
| amd64 (`-smp 2`) | `logs/20260926-133004` | core 1 online, long mode, its own block, 82 us | same; 0 park wakes, 0 `LOCK:` |
| aarch64 (`-smp 2`) | `logs/20260926-133959` | core 1 online, EL1, its own block, 3314 us | same; 0 park wakes, 0 `LOCK:` |
The boot hart HSM chose (0) is the one OpenSBI names as `Boot HART ID`.
**Host side, riscv64** (`ps -L` after O-A, then 20 s later): `CPU 0/TCG` 64.9%, 5:14 → 5:27; `CPU 1/TCG` **0.0%, 0:00 → 0:00**. Core 1 is halted.
**MC-1 is complete:** every ISA boots two cores, and the second is parked, halted, and never woken.
**Before MC-2 (observers get core-0 affinity) and MC-3 (worker cores claim), open findings:**
- Core 0's idle loop polls at about 64% of a host CPU (§5.2).
- In MC-1 the parked cores run no timer, take no interrupts, and have no GIC/PLIC/LAPIC setup of their own. MC-3's wake-by-IPI needs each core's interrupt controller initialised: the LAPIC on amd64, the GIC CPU interface on aarch64, and the SIE/SSIP path on riscv64.