9eff12209098552e9e23043cfe5cd9b9313583e3
165
Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
9eff122090 |
Fix aarch64 Stadium/COOL O(ncells) scan; rerun std79 DoE clean, 81/81 (FABRIC-3.md §XVI)
Root cause of the 90+ minute aarch64 VM-birth stall found in §XV: stadium_admit()'s eviction-fallback scan iterated the entire stadium_ncells array filtered by owner, not the calling VM's own resident cells as its own doc comment claimed. Combined with stadium_grant_quota() always splitting from Hera's shrinking free list and stadium_word_dispatch() calling stadium_admit() per distinct word a VM's capsule executes, this compounded into a real O(n) blowup — catastrophic specifically on aarch64 because its -m 4096 (vs 1024 on amd64/riscv64) inflates the kmalloc heap kmalloc_init() bisects down to, which inflates stadium_ncells 4x (335,544 vs 83,886 cells, measured from boot logs). Fixed by threading a real per-VM doubly-linked resident-cell list (StadiumVMQuota.resident_head + stadium_resident_next[]/stadium_resident_prev[]) so the fallback scan is bounded by that VM's own resident count, not the global cell array size. Verified with a full rerun of the 3x9x3 std79 DoE campaign from scratch: one continuous boot per architecture, all 9 identities simultaneously live throughout (the 3-boot aarch64/riscv64 batching workaround is no longer needed). 81/81 trials correct, 0 mismatches, DOE-RUN header sequence md5-identical across all three raw logs. Identity 04's attach on aarch64, which stalled 90+ minutes before, now completes in ~34s; full boot-to-DoE-complete in ~290s. Corrects an earlier misreading (carried into §XV, std79-doe.fth's comments, and the project memory note) that described the symptom as a runaway "335,000+ cycles" dispatch counter — those were cell array indices, not an event count. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01EXieurDfDSsDFdnSyusuWo |
||
|
|
e2abc56306 |
3(arch) x 9(identity) x 3(rep) randomized full-factorial std79 DoE: 81/81 correct (FABRIC-3.md §XV)
Formal successor to §XII's ad hoc exerciser campaign, requested as a genuine randomized full-factorial design matching this project's own DoE methodology (capsules/doe.4th's Fisher-Yates shuffle), and written entirely in FORTH per explicit request -- not host-orchestrated shell scripting. experiments/std79-doe/std79-doe.fth: builds a 27-cell (9 identity x 3 replicate) run matrix, Fisher-Yates shuffles it with a fixed seed (matching doe.4th's own default), then dispatches each of the 24 exerciser test cases directly into the target identity's own live VM via VM-EXEC -- no console USE redirection, no per-trial host interaction. The zuse case runs as directly-compiled native code (RUN-TEST-NATIVE) rather than VM-EXEC targeting "Hera" herself: VM-EXEC's own vm_state_push/pop only saves rsp/exit_colon/ecw_nesting, not input_buffer/input_pos, so a self-targeting call while this capsule's own vm_interpret call is still mid-line would risk exactly the class of bug the idle-tick reentrancy guards exist for. amd64: all 27 trials ran with all 9 identities simultaneously live in one boot -- clean, zero mismatches. aarch64: hit a real, uninvestigated bug attaching all 9 simultaneously -- the 6th live VM's birth stalled for 90+ minutes at 100%+ CPU with a Stadium COOL-dispatch counter already at 335,000+ cycles, versus tens of thousands at the same checkpoint for earlier identities. Not root-caused here (flagged in FABRIC-3.md for later); worked around by splitting into 3 boots of 3 simultaneously-live identities each, every boot sharing the same seed so the master 27-slot shuffle is identical, filtered per boot by a new ACTIVE-LO/ACTIVE-HI range (EXEC-STD79-DOE's signature: seed lo hi -- ). run_id is always the slot's true position in the master shuffle, so trial order stays comparable across boots -- standard DoE blocking. riscv64: same 3-boot pattern, clean. Grand total: 81/81 trials correct, 0 mismatches, across all three architectures, all nine identities, all three replicates. Also flagged (FABRIC-3.md §XIV, not fixed): attaching several WIREBIND identities near-simultaneously (whether via rapid hotplug or all present from boot) causes the kernel to silently detect only some of them -- confirmed at the host/QMP level that every device was genuinely present. Worked around throughout this campaign by attaching one identity at a time with confirmed waits; real hardware hotplug could hit the same gap, so it's a genuine robustness concern, not just a test-harness inconvenience. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01EXieurDfDSsDFdnSyusuWo |
||
|
|
70db955ac9 |
Fix M/MOD: hand-rolled 128/64 bit-serial division (FABRIC-3.md §XII.4)
mixed_math_word_m_slash_mod() had the identical bug class already fixed
in M* (commit
|
||
|
|
9a09949c69 |
Fix M*: use __int128 for a genuine 128-bit double-cell product (FABRIC-3.md §XII.4)
mixed_math_word_m_star() confused "double" (two full cell_t-width cells,
128 bits total on this 64-bit build -- what D+/D-/D./etc. all actually
expect) with "the low/high 32-bit halves of a single 64-bit product" --
code clearly written assuming cell_t is 32-bit. It computed an ordinary
64-bit `long long` product (already wrong for any true product exceeding
64 bits, since long long is the same width as one cell here) and split
that into 32-bit halves via `result & 0xFFFFFFFF` / `result >> 32`. For a
small negative product like -56088, this produced a positive, zero-
extended low cell paired with a correctly-looking dhigh=-1 -- D.'s
overflow check (correctly) rejected the resulting malformed double, on
every architecture, every time (this bug was never architecture-specific,
unlike the D+/D-/DNEGATE/d_compare family already fixed in bea8d74/
|
||
|
|
1a716c8048 |
Fix d_compare: use ucell_t instead of unsigned long (FABRIC-3.md §XII.4)
d_compare() (double_words.c), the static helper backing DMAX/DMIN/D</D=,
had the same bare-unsigned-long pattern already fixed in D+/D-/DNEGATE
(commit
|
||
|
|
bea8d7436a |
Fix D+/D-/DNEGATE: use ucell_t instead of unsigned long (FABRIC-3.md §XII.4)
double_word_d_plus(), double_word_d_minus(), and double_word_dnegate() (double_words.c) all cast through plain `unsigned long` for their carry/ borrow-detection arithmetic. On this aarch64 bare-metal cross-compile target, unsigned long is 32-bit (confirmed: sizeof(unsigned long)==4) -- amd64 and riscv64 both happen to have a 64-bit long, so the identical code only broke on aarch64. The low-cell arithmetic silently truncated to 32 bits, then widened back to cell_t via ordinary (non-sign-extending) conversion, producing a wrong result whenever the true 64-bit result was negative -- D. then correctly, faithfully reported DOUBLE-OVERFLOW on the resulting malformed double. vm.h already defines ucell_t for exactly this: same conditional as cell_t, guaranteed width-matched on every target. print_number_formatted() (format_words.c) already used it correctly; these three words didn't. Switched all three to ucell_t -- a one-word-class fix, no logic change. Verified: rebuilt and booted all three architectures clean. T19 (D+) on aarch64 now correctly prints -2, matching amd64/riscv64; T20 (DNEGATE) unaffected everywhere. Additional manual cases beyond the original exerciser, run live on aarch64 to specifically exercise the >32-bit-magnitude path the old bug depended on: D- (-5-3=-8), DNEGATE on 2^33 (8589934592 -> -8589934592), D+ crossing the same boundary (3+8589934592=8589934595) -- all correct. d_compare() (backing DMAX/DMIN/D</D=) has the identical latent pattern but is out of scope for this fix (not named in the request, never exercised by the campaign) -- left open, flagged in FABRIC-3.md. M*'s separate, universal-across-all-three-architectures DOUBLE-OVERFLOW bug is also untouched -- unrelated defect, not part of this fix. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01EXieurDfDSsDFdnSyusuWo |
||
|
|
91f7b39d3c |
Root-cause the aarch64-only D+ DOUBLE-OVERFLOW bug (FABRIC-3.md §XII.4)
Confirmed the exact mechanism behind the aarch64-specific D+/D. divergence
found in the std79 exerciser campaign (commit
|
||
|
|
cc81edf00a |
std79 exerciser campaign: 27/27 legs clean, two real D. bugs found (FABRIC-3.md §XII.4)
Completed the FORTH-79 standard-dictionary cross-ISA exerciser campaign: all
9 identities (zuse, rajames/bob, 00-06) x all 3 architectures (amd64,
aarch64, riscv64), 27 legs total. No crashes, no heap corruption across the
full run -- real-world validation that the WIREBIND use-after-free fix
(commit
|
||
|
|
9142dda2d6 |
Fix use-after-free in sk_repl_idle()'s idle-tick VM resolution (FABRIC-3.md §XIII)
Root-caused a heap-corruption bug that reliably failed WIREBIND identity attach on the third attach/detach cycle in one boot. sk_console_readline() and sk_console_getkey() captured `active_vm` once from their caller and kept passing that same (possibly long-stale) pointer to sk_repl_idle() on every idle tick serviced while blocked waiting for input. If the VM it pointed at was killed (WIREBIND detach) mid-block, the existing bailout only checked a generic "is anyone attached" boolean -- masked as soon as a different identity attached next -- so blk_vm_flush_all() kept writing into a freed VM struct sitting on kmalloc's own free list, corrupting the free list's linked-list metadata itself. Both idle branches now re-resolve the live active VM fresh from g_repl_active_vm on every tick, matching the dispatch-side fix already made for the sibling bug in §XII.3. Verified: rebuilt amd64, reran the exact three-cycle repro that reliably corrupted the heap before the fix -- free-list census stayed stable through the same idle window that previously collapsed to zero. All three architectures (amd64/aarch64/riscv64) boot clean to the zuse)ok> prompt. kmalloc_debug_census()/kmalloc_debug_census_bytes() kept as permanent diagnostic infrastructure; every other temporary probe added during the investigation was reverted. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01EXieurDfDSsDFdnSyusuWo |
||
|
|
70421bdd43 |
Fix real WIREBIND crash: stale active-VM pointer dispatched after blocking read (FABRIC-3.md §XII.3)
The interpreter_enabled guard added in the previous commit (
|
||
|
|
662ef44e59 |
Fix EXEC/LOAD block-persistence gap and WIREBIND/USE interpreter-race panic (FABRIC-3.md §XII)
Found live while building a cross-ISA FORTH-79 dictionary exerciser: - capsule_exec_init() zeroed a capsule's block content immediately after running it, so LOAD (a genuine FORTH-79 standard word, ACL-allowed even for locked identities) could never actually read back what EXEC had just written. Removed the clear from capsule_exec_init(); block content now persists like any other Standard BLOCK/BUFFER/UPDATE write. kernel_main.c's own explicit post-birth clear of Mama's init.4th range is untouched. - USE could redirect the console to a WIREBIND identity's VM before that VM's vm_enable_interpreter() step of its own birth sequence had run, causing the next typed line to hit vm_assert_interpreter_enabled() and panic the entire machine -- not the per-session-recoverable ACL-fault path a redirected VM otherwise gets. USE now checks interpreter_enabled first and refuses with a retry message instead. Also includes the amd64/aarch64/riscv64 acceptance boot logs and DoE CSVs from this session. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01EXieurDfDSsDFdnSyusuWo |
||
|
|
d5722986b2 |
Re-mint bob with the restricted personality, closing out the identity set (FABRIC-3.md §XI.6)
bob-thumb-ident.img predated MINT_PERSONALITY_STD79_LOCKDOWN (minted
2026-09-06,
|
||
|
|
b301317902 |
xHCI: drive Port Reset on port reuse; WIREBIND: kill the console VM too (FABRIC-3.md §XI.5)
Two independent bugs that together caused a reliable hotplug wedge: reusing an xHCI port for a second identity right after an unclean detach of a first would leave no further hotplug events reaching the guest at all. Bug 1 (xhci.c/xhci_driver.h): the xHCI driver never drove PORTSC.PR -- a known, named gap since Milestone 2e (the code's own comment flagged it, PORTSC_PR/PRC were defined but never referenced). A port's first connect each boot reads PED already set, so skipping the reset happened to work; a second device on the same port after a prior disconnect reads PED clear, and Address Device reliably failed without an explicit reset cycle. New XHCI_CONN_AWAIT_PORT_RESET state drives PR and waits for PED to read set before proceeding to Enable Slot. Bug 2 (capsule_wirebind.c): capsule_wirebind_eject()/unclean_detach() compared g_repl_active_vm against the *user* VM's pointer (g_wirebind_attached_vm_id tracks that one, not the console VM) -- never equal, since USE/g_repl_active_vm always points at the console VM. The guard never fired and the console VM was never killed at all, only orphaned -- paired to a dead user VM but still the REPL's active session. New wirebind_teardown_console() helper resolves and tears down the console VM by its own tracked bare username. Verified live on amd64: the exact repro (identity 01 on port 2, unclean detach, identity 02 on the same port immediately after) -- previously wedged with "xhci: address device failed" and no further hotplug activity; now attaches cleanly and fast, both VMs' KILL messages appear, console is immediately interactive on the new identity. Three-arch clean qemu acceptance passed, all clean on the first attempt. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_014Ec88YKxxhZGG1RNnune78 |
||
|
|
9ea5580ace |
FABRIC-3.md §XI.4: record all 7 identities individually verified
00-06 each confirmed standalone (no Zuse): fast attach, USE, a standard word computing correctly, and an ACL-denied VM-EXEC recovering gracefully instead of halting -- exercising the fault- scoping fix from the prior commit across every minted identity, not just 00/01. Also notes an out-of-scope hotplug finding: reusing an xHCI port for a second identity right after an unclean (non-EJECT) detach of a first wedges that port for further attaches. Worked around (fresh port/boot per identity) rather than root-caused -- not part of this session's task. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_014Ec88YKxxhZGG1RNnune78 |
||
|
|
d6661b5eed |
Scope VM fault halt to the faulting identity's own session (FABRIC-3.md §XI.4)
A standalone WIREBIND identity (no Zuse, USE'd in directly) hitting an ACL-denied word halted the entire machine -- Hera, Hermes, Artemis, all of it -- instead of just that identity's own session. sk_fault_handler() was being called unconditionally on whichever VM's ->error was set, with no distinction between Hera's own root session (where "no fallthrough surface" is the correct, deliberate fail-closed behavior) and a USE'd-in guest identity (which should recover and resume at its own prompt instead of taking the fleet down with it). Both call sites (sk_repl_step, sk_repl_run) now compare the faulting VM against Hera before deciding: Hera's own session still halts by design; any other VM prints a recovery message, clears its fault state, and continues. Also: mint identities 01-06 with the same FORTH-79/83 restricted personality identity 00 already had, verified via the fixed fault scoping above (which this verification pass surfaced). Verified live on amd64 (both the Hera-halts and identity-recovers branches); three-arch clean qemu acceptance passed (riscv64's first attempt hit an unrelated virtio_blk I/O timeout hang, a known QEMU/TCG flake -- a clean retry booted normally). Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_014Ec88YKxxhZGG1RNnune78 |
||
|
|
9bcc70647b |
FABRIC-3.md §XI: document the ACL lockdown, messaging migration, and the
two-bug "identity attach without Zuse" investigation Covers three entangled threads from 2026-09-07/09: the FORTH-79/83 MINT lockdown personality (commit |
||
|
|
8471d529bc |
FABRIC-3.md §X.4: correct a false claim about kmalloc.c lacking block splitting
The claim ("coalesces but doesn't split") was never actually checked
against kmalloc.c -- it was carried over from alloc_kernel.c's own doc
comment about itself and mis-applied to a different file. Asked to fix
it, re-reading kmalloc.c showed allocate_from_block() already has a
complete, unconditional splitting implementation. Nothing was broken;
correcting the record instead of "fixing" working code.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_014Ec88YKxxhZGG1RNnune78
|
||
|
|
b106a4b0b5 |
FABRIC-3.md §X.4: document the allocator resolution — sf_malloc/sf_free now on the real kernel heap
Updates §X.4 (and §X's own title) from "capacity question still OPEN"
to resolved: Captain Bob's framing (unknown VM count in advance, heap
should use whatever memory is actually available once this is a full
OS) led to routing alloc_kernel.c's sf_malloc()/sf_free() through the
kernel's existing kmalloc.c heap (2 GiB floor, PMM-backed, coalescing,
already boot-tested) instead of a separate 4MB arena -- commit
|
||
|
|
36f1d6ae9e |
FABRIC-3.md §X: document the §IX.5 follow-on — xHCI root-cause/fix, live hotplug walkthrough, identity heap capacity findings
Documents three commits' worth of live-tested work in one continuous arc, picking up exactly where §IX.5 left off: - X.1: the "4th-device enumeration failure" was a QEMU test-harness port-topology artifact, not a driver bug (commit |
||
|
|
2c1b3cd695 |
Four bugs found live verifying the 8 identity thumbdrives (FABRIC-3.md §IX)
All found by actually running the identity workflow §VII/§VIII made possible, not by code review: 1. Zuse/WIREBIND cross-contamination on detach: capsule_zuse_boot_logout() and capsule_wirebind_unclean_detach() both had no device parameter, so an unrelated device detaching (while the real owner's own stayed attached) incorrectly tore down the wrong session. Both now compare the departing device against their own tracked one, mirroring capsule_wirebind.c's pre-existing g_wirebind_attached_dev precedent. 2. Dictionary-entry memory leak: vm_create_word()'s sf_malloc()'d DictEntry (plus a second per-entry allocation for transition_metrics) was never freed by vm_cleanup(), in both the hosted and kernel implementations. Caused a real kernel PANIC after 8-9 repeated VM birth/kill cycles in one boot. Fixed by walking vm->latest in both. 3. sf_malloc/sf_free (alloc_kernel.c) was a 4MB bump arena with a deliberate no-op free, sized on "VM born once, never killed" -- fix #2 alone didn't stop the panic because free() itself discarded the pointer regardless. Given a real free list (first-fit reuse). 4. Headless-console gate didn't re-engage after a mid-boot logout: the original fix (sk_console_mark_login(), one-way sticky) only gated the first login of the boot. Replaced with a live check (sk_console_identity_present()) re-evaluated continuously, including inside sk_console_readline()'s own blocking idle loop -- the console is normally sitting blocked there when a hot-unplug logout happens, so checking only at the top of the REPL loop wasn't enough. Also: MINT now verifies its own write (verify_mint(), capsule_mint.c) by reading back through the same check a real attach performs, rather than trusting blkio_write()'s BLK_OK alone -- logged via log_message(), not console_println(), per direct instruction. Verified live, amd64: the full 8-identity repeated attach/detach cycle that previously panicked at the same point every time now completes clean, and a full serial-log sweep found zero bare unauthenticated prompts anywhere in the run. Three-arch clean-qemu acceptance passed. Still open, not fixed here: a 3+-simultaneous-device USB enumeration failure found in a separate live test, not yet root-caused. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_018EjXFo7mPXjUMjfJeuUUz4 |
||
|
|
9e81de3f43 |
xHCI/BOT driver: genuine multi-device support (FABRIC-3.md §VII)
Per-slot registry (xhci_msc_slot_t/dev->msc_slots, sized off the controller's own reported max_slots) replaces the single-device scalar fields the driver carried since Milestones 2e-2h. Boot-time port scan no longer stops at the first connected device; a connect/disconnect that arrives while the Command Ring is busy is now queued and drained instead of dropped. blkio_usb.c and repl.c's own single-device state (device descriptor buffers, blkio_dev_t, attach bookkeeping) became per-slot registries the same way. Live multi-device testing (not just compiling) surfaced a second, more severe bug outside the original plan: transfer_purpose and next_action were also single scalars shared across the whole controller. Two devices enumerating concurrently could have one's completion silently overwrite the other's still-outstanding one, permanently stalling it with no error. Fixed by moving both per-slot and, critically, reading the Transfer Event TRB's own real Slot ID field instead of trusting external bookkeeping. Verified live, all three architectures, mandatory clean-qemu acceptance: existing single-device path unchanged, and two devices attached simultaneously (amd64) both progress independently through enumeration without corrupting or stalling each other. Also in this pass (implemented and verified in earlier turns this session, committed together per direct instruction): - Headless-until-login console policy: no prompt/banner until a real identity logs in via an attached thumbdrive (WIREBIND or Zuse, neither special), reusing EMERGENCY_CONSOLE_ENABLED as the debug/recovery escape hatch (now default-off). - KILL/g_repl_active_vm dangling-pointer fix: killing the VM the console is currently USE'd onto now detaches back to Hera first, matching the existing EJECT/UNCLEAN precedent. FABRIC-3.md §VII/§VIII carry full closure notes for all three. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_018EjXFo7mPXjUMjfJeuUUz4 |
||
|
|
cc6fcb6a0b |
FABRIC-3.md §VII: rewrite punch list to real code-level detail
Previous pass was too abstract for this series' own bar. Re-traced xhci.c/repl.c function-by-function: found max_slots is already read and correctly sizes the DCBAA (so the fix reuses that value, not "start reading a register"); found xhci_scan_ports_for_already_connected() deliberately breaks after the first hit, missing a second already- connected device at boot entirely; found block_subsystem.c's attach layer is already multi-device-capable, narrowing the real singleton to xhci_dev_t's own fields plus three repl.c pointers. Punch list items now name exact functions/fields/line numbers and what's proposed vs. already true. Also drops the earlier small-fixed-N concurrency bound per direct correction -- size off dev->max_slots, not a guessed ceiling. Still plan-only. No driver code touched. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_018EjXFo7mPXjUMjfJeuUUz4 |
||
|
|
c3db963164 |
FABRIC-3.md §VII: xHCI/BOT single-device architecture — plan only, halted
Documents the full scope of the driver's single-device-at-a-time state (connect/enumerate, control-transfer, and BOT state machines), the persistent-vs-in-flight distinction that bounds the fix, the concurrency target, and a numbered punch list. No driver code has been touched — implementation is explicitly held pending go-ahead. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_018EjXFo7mPXjUMjfJeuUUz4 |
||
|
|
1bd041e84d |
FABRIC-3.md §IV.3 item 5: pci_init() DTB path re-scoped, doc-only, nothing implementable this pass
Re-examined the Pi 5 RP1 PCIe access re-scoping (§IV.3 item 5) to see what
was actually buildable before real hardware arrives (2026-09-17), and
found nothing safely implementable this pass -- recorded three corrections:
1. The "vmm_map_range() needed for native boot" secondary finding is
wrong as stated: arch_mmu_init() is a stub on both non-amd64 ISAs,
vmm.c's load_cr3() is a no-op outside __x86_64__, and riscv64's satp
is explicitly left at Bare (this session's own §V.3 item 7 fix). No
non-amd64 ISA ever turns its own MMU on today, so VA==PA and there is
nothing to map. Reframed as a future concern conditional on MMU
bring-up, not a current prerequisite.
2. No silent-wrong-answer risk exists today: with no ACPI on native Pi 5
boot, pci_init()'s MCFG parse already fails cleanly and aarch64 takes
no ECAM fallback, rather than misreading RP1's 37 KB indirect window
as flat ECAM.
3. The "make config-space dispatch runtime instead of compile-time" half
of the re-scoped fix, considered on its own, isn't separable:
portio_read32() and siblings use outl/inl inline asm that cannot exist
in an aarch64/riscv64 translation unit, so any case referencing them
stays #ifdef-gated regardless -- an enum wearing the same compile-time
selection. It only becomes real dispatch once a second non-amd64
mechanism is actually compiled in.
Broadcom indirect access itself remains unimplemented: no QEMU model
exists for "brcm,bcm2712-pcie" (zero branches would ever execute before
real hardware, unlike the guard-exercised GIC/PLIC DTB fixes), and
config-space access alone is insufficient for RP1 to enumerate without
the real driver's controller bring-up (link training, PERST, window
setup) -- building only the index/data window would compile and boot
while silently never working.
No code changed. 3-arch acceptance run anyway per convention: all three
reach zuse)ok> with identical virtio-blk/xHCI PCI device discovery to
the pre-change baseline (commit
|
||
|
|
9b6de5d6c7 |
riscv64: PLIC base address DTB-discovered, QEMU-virt constant as fallback (§V.3 item 3)
plic_init() now takes boot_info->dtb (threaded through apic_init()) and tries fdt_find_node_by_compatible(dtb, "sifive,plic-1.0.0") -> fdt_find_prop_in_node(..., "reg", ...) before falling back to the QEMU-virt-specific constant it previously hardcoded unconditionally. Reuses the node-scoped DTB lookup primitive built for the aarch64 GIC base fix unchanged. s_plic_base is now a runtime uintptr_t, same shape as apic.c's s_gicd_base/s_gicc_base. This system's QEMU/UEFI riscv64 firmware does not forward a DTB to the guest (timer.c's own timebase-frequency read falls back too, confirmed in this boot's own log), so only the no-DTB fallback branch is exercised here -- the success branch (a real DTB with a matching PLIC node) stays unverified until real Milk-V Mars hardware. FABRIC-3.md's first-drafted claim that the success branch would run (based on a stale comment in plic.c's own pre-fix header) was checked against the actual log and corrected before this commit. 3-arch acceptance: amd64/aarch64 don't compile these files, so their runs are non-regression on untouched files only. riscv64's own boot log confirms the fallback path prints exactly as designed and boot reaches zuse)ok> unchanged. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_019YcT3H2PQeyujrzjqS3Var |
||
|
|
90ee8deb6d |
riscv64: skip satp Bare-mode switch when already Bare (§V.3 item 7 audit fix)
arch_early_init() unconditionally cleared satp on every boot, justified only by behavior observed under QEMU/EDK2 firmware (satp.MODE=10/Sv57, kernel identity-mapped within it). That reasoning never applied to the native U-Boot+OpenSBI boot path, where satp is conventionally already 0 at S-mode handoff -- the unconditional clear was likely a harmless no-op there, but on an unverified assumption. Fix: read satp.MODE first and return early when it's already 0 (nothing to switch away from, no safety argument needed). The unconditional csrw/sfence pair still runs unchanged for the confirmed QEMU/EDK2 case. No Sv39/Sv48/Sv57 page-table walker built -- out of proportion to this finding's severity. 3-arch acceptance: amd64/aarch64 don't compile this file, so their runs are non-regression on untouched files only. riscv64's own boot log confirms satp.MODE = 0xa at entry, so the mode != 0 branch ran and "satp cleared -- Bare mode, explicit" printed exactly as before the fix. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_019YcT3H2PQeyujrzjqS3Var |
||
|
|
350287850f |
arch/aarch64: fix VBAR_EL2 stale comment + hardcode HVC PSCI conduit
FABRIC-3.md §IV.3 item 7's code audit found two more findings; fixed both
per direct instruction naming them specifically.
Comments only, no behavior change:
interrupts.c's arch_interrupts_init() doc comment (and its matching
runtime EL2 console message) claimed VBAR_EL2 was "a known gap... not yet
wired." Checked against isr.S's aarch64_install_vectors() and found that
claim stale: the assembly already branches on aarch64_current_el() and
writes vbar_el2/vbar_el1 correctly, threading the same answer through
el2_mode_flag for the IRQ trampoline's ELR/SPSR selection too. There was
no gap to close -- only the comment was wrong. Also fixed a same-vintage
one-word staleness in arch.c's aarch64_install_vectors extern comment
("installs VBAR_EL1" -> EL-aware), caught while touching this.
Real behavior change, gated to preserve existing QEMU behavior:
arch_cold_reset() hardcoded the PSCI conduit to HVC, a documented
QEMU-specific workaround (QEMU's AAVMF has no genuine EL3 to answer SMC).
Real Pi 5 hardware's ATF means EL3 exists there; confirmed further this
pass that bcm2712.dtsi's own /psci node declares method="smc" directly,
not just inferred from ATF's presence.
New aarch64_psci_conduit_init(dtb) in arch.c: fdt_valid(dtb) ->
fdt_find_node_by_compatible(dtb, "arm,psci-1.0") ->
fdt_find_prop_in_node(..., "method", ...) -- sets a module-static
s_psci_use_smc flag to 1 only when method reads exactly "smc"; every
other outcome (no DTB, no PSCI node, method="hvc", property absent)
leaves it at its default 0/HVC, preserving this system's existing QEMU
behavior exactly. arch_cold_reset() now branches on that flag between
smc #0/hvc #0. Called once from apic_init() (arch/aarch64/apic.c), the
one point in boot with boot_info->dtb already in hand -- collocated with
its consumer in arch.c rather than defined in apic.c, since
arch_cold_reset() has no boot_info of its own by the time it runs (called
from deep in VM execution, via BYE).
Three-arch QEMU acceptance run exercised both new guard branches: the
aarch64 boot log shows "PSCI: no DTB -- using HVC (QEMU virt-machine
default)" immediately before the existing GIC discovery lines, then
boots clean to zuse)ok> -- confirming the QEMU/UEFI path is unchanged.
The SMC success branch itself stays unverified until real Pi 5 hardware
runs BYE.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019YcT3H2PQeyujrzjqS3Var
|
||
|
|
dc9445abec |
apic.c (aarch64): fix GIC base address for real Pi 5 hardware
FABRIC-3.md §IV.3 item 7's code audit found GICD_BASE_PA/GICC_BASE_PA hardcoded to QEMU virt-machine constants (0x08000000/0x08010000), self-documented as a deliberate exception because QEMU's aarch64 UEFI firmware never forwards a DTB. That premise doesn't hold on the native Pi 5 boot path (rpi5_native_boot.c), which does have a real DTB and calls this same, unmodified apic_init() -- which ignored boot_info entirely and always programmed the QEMU addresses. Real BCM2712 GIC-400 is at 0x10_7fff9000 (confirmed against bcm2712.dtsi's axi/gicv2 nodes), a completely different region of the address space. Fixed per direct instruction, naming this finding specifically. apic_init() now calls gic_bases_from_dtb() first: fdt_valid(dtb) -> fdt_find_node_by_compatible(dtb, "arm,gic-400") -> fdt_find_prop_in_node(..., "reg", ...), reading the first two 2-address-cell/2-size-cell entries (GICD, then GICC -- the standard arm,gic-400 binding order). Falls back to the QEMU constants on any failure (no DTB, no matching node), so the existing QEMU/UEFI path is unchanged. GICD_BASE_PA/GICC_BASE_PA became s_gicd_base/s_gicc_base (module-static uintptr_t, no longer compile-time constants on this path) -- every MMIO call site (apic_init, apic_spi_enable, apic_read_iar, apic_eoi_intid) now reads through them. Three-arch QEMU acceptance run exercised the guard itself, not just compiled it: the aarch64 boot log shows "GICv2: no DTB GIC node -- using QEMU virt-machine defaults" followed by the unchanged "distributor+CPU interface enabled, PPI 30" line, then boots clean to zuse)ok>. The success branch (a real DTB with a matching node) stays unverified until real Pi 5 hardware -- this build never has a devicetree to exercise it against. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_019YcT3H2PQeyujrzjqS3Var |
||
|
|
0f798256a0 |
FABRIC-3.md: aarch64/riscv64 boot-path code audit pass (§IV.3/§V.3 item 7)
Reviewed arch/aarch64/{apic,arch,timer,interrupts}.c and
arch/riscv64/{apic,plic,arch,interrupts,timer}.c for the same class of
QEMU-virt-vs-real-hardware assumption §III item 6's amd64 audit looked for.
Report only, per this project's "identify, don't fix unless asked" rule --
no source files changed.
Findings, aarch64:
- Severe, confirmed live: apic.c's GICD/GICC base addresses are hardcoded
QEMU-virt constants, self-documented as a deliberate exception because
QEMU's aarch64 firmware never forwards a DTB. That premise no longer
holds -- the native Pi 5 boot path (item 2) receives a real DTB and
calls the same, unmodified kernel_main(), whose M4 sequence calls
apic_init(boot_info) unconditionally (kernel_main.c:413); apic_init()
still ignores boot_info entirely. Real BCM2712 GIC-400 is at
0x10_7fff9000, confirmed against bcm2712.dtsi -- a different region of
the address space entirely from the hardcoded 0x08000000. With the MMU
off at this point in boot, this blocks reaching ok> on real hardware as
the code stands.
- Doc-only correction: interrupts.c's own comment claims VBAR_EL2 is never
installed ("a known gap"). Checked against isr.S and found stale -- the
actual implementation already branches on aarch64_current_el() and
installs vbar_el2/vbar_el1 correctly. No functional gap; the comment
describes one the code already closed.
- arch_cold_reset() hardcodes the PSCI conduit to HVC, a QEMU-specific
workaround (QEMU's AAVMF has no genuine EL3). The Pi 5's real ATF means
EL3 firmware exists there, making SMC the conventional real-hardware
conduit -- no runtime detection exists.
Findings, riscv64:
- plic.c's QEMU-virt-hardcoded PLIC_BASE is already tracked (§V.3 item 3);
this pass confirms rather than rediscovers it.
- arch_early_init()'s satp clear is justified entirely by behavior
observed under QEMU's EDK2 firmware; the native boot path (U-Boot+
OpenSBI, no EDK2) doesn't share that observation, though the action is
likely still safe since OpenSBI's handoff conventionally leaves satp=0
already. Lowest-severity finding in the set.
- Clean: the SBI timer path and arch_cold_reset()'s SBI SRST call are both
genuinely hardware-independent -- named as the portable pattern amd64's
i8042-pulse reset and aarch64's hardcoded-HVC PSCI call both lack.
Doc-only change. Three-arch QEMU acceptance (amd64/aarch64/riscv64, in
order) run to confirm non-regression only.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019YcT3H2PQeyujrzjqS3Var
|
||
|
|
6a6ff9353f |
FABRIC-3.md: amd64 boot-path code audit pass (§III item 6)
Reviewed src/starkernel/boot/uefi_loader.c and every file in arch/amd64/ (arch.c, apic.c, ioapic.c, interrupts.c, i8042.c, timer.c) for anything that assumes SER5-specific hardware rather than standard UEFI/ACPI. Report only, per this project's "identify, don't fix unless asked" rule -- no source files changed. Verified clean: uefi_loader.c's COM1 presence probe, its two-pass ACPI 2.0-then-1.0 GUID preference, the GetMemoryMap/ExitBootServices golden path, and GOP BltOnly degradation. apic.c/ioapic.c derive LAPIC mode, APIC timer frequency, and I/O APIC base/GSI at runtime, not from hardcoded constants. Four findings recorded (not fixed): 1. HPET base (timer.c) hardcoded at 0xFED00000, never cross-checked against the ACPI "HPET" table -- the same bug class this file's own comment already documents and fixed for the PM_TMR port. 2. LAPIC base always 0xFEE00000; apic_init()'s own doc comment flags MADT relocation as unimplemented. Narrower than that suggests: ioapic.c's parser already reads MadtHeader.local_apic_address, just never plumbs it to apic.c. MADT type 5 (Local APIC Address Override) isn't parsed at all. 3. i8042 PS/2 controller (i8042.c) and the legacy 8259 PIC (interrupts.c) are poked unconditionally with no ACPI FADT presence check, unlike this same file's own raw_serial_init() COM1 probe. 4. arch_cold_reset() (confirmed live via BYE, mama_forth_words.c:1437) pulses the i8042 reset line instead of using the FADT's standards-defined RESET_REG/RESET_VALUE, which doesn't depend on i8042 existing at all. None are certain to bite on the real SER5 -- the conventions assumed hold on the large majority of PC-compatible x86_64 systems -- but the decision in FABRIC-3.md §III requires arguing genericity from standards compliance, not from "it booted," and these are the concrete gaps. Doc-only change. Three-arch QEMU acceptance (amd64/aarch64/riscv64, in order) run to confirm non-regression only. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_019YcT3H2PQeyujrzjqS3Var |
||
|
|
ecdb32e0d6 |
boot_media/rpi5/config.txt: Pi 5 native boot config (FABRIC-3.md §IV.3 item 6)
Researched against the official raspberrypi.com config.txt reference and one real, working Pi 5 bare-metal project's own checked-in config.txt (leopoldch/BatMetal), not assumed from general Pi knowledge: - kernel=kernel_2712.img, os_check=0, device_tree=bcm2712-rpi-5-b.dtb - enable_uart=1 added (correction to the item's original text): costs nothing when unused, and is the only diagnostic channel that would survive a framebuffer failure on the untested mailbox path (rpi5_native_boot.c). - arm_64bit=1 dropped (correction to the item's original text): confirmed inert on Pi 5 by official docs. - dtparam=pciex1 researched, deliberately omitted with rationale recorded -- community-reported only, not needed until item 5's re-scoped RP1/PCIe work. - os_check=0 vs. BatMetal's own config (which omits it) recorded as an open, unresolved discrepancy rather than silently picked. boot_media/rpi5/README.md notes the one remaining gap this exposes: kernel_2712.img names a file nothing currently builds (item 1's separate-image build target is still outstanding future work). Doc-and-config only, no compiled code changed. Three-arch QEMU acceptance (amd64/aarch64/riscv64, in order) run to confirm non-regression only. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_019YcT3H2PQeyujrzjqS3Var |
||
|
|
11c93773d0 |
FABRIC-3.md: pci_init() DTB path item was wrong -- re-scope, don't build the ECAM version
Investigated before writing code, per this document's own discipline, and
found the original item 5 text's assumption doesn't hold: it framed this
as "swap the ACPI MCFG lookup for a DTB one, same flat-ECAM access
underneath." Confirmed against three primary sources that this is wrong:
- bcm2712-rpi-5-b.dts: RP1 sits under pcie2 ("brcm,bcm2712-pcie"),
reg = <0x10 0x00120000 0x00 0x9310> -- a ~37KB window, far too small
for a flat 256MB ECAM region.
- pcie-brcmstb.c (the real Linux driver for this compatible string):
brcm_pcie_map_bus() computes a standard ECAM-shaped offset but accesses
it through an IDX_ADDR/DATA_ADDR indirect index+window pair, not a
direct MMIO read. A real third config-access mechanism, not a bigger
version of the DTB-lookup task.
Re-scoped item 5 (§IV.3) to record the real shape: pci.c's cfg_read32/
cfg_write32 family dispatches today via #ifdef ARCH_AMD64 vs. everything
else (flat ECAM) -- but QEMU aarch64 (flat ECAM, real ACPI MCFG) and Pi 5
aarch64 (Broadcom indirect windowing) are the same build, so this needs a
runtime dispatch change to a file all three architectures currently boot
through, not a small addition. Also flagged: pci_init()'s vmm_map_range()
for the ECAM window is amd64-only today (aarch64/riscv64 rely on UEFI's
identity map); native boot has no UEFI identity map at all, so any PCIe
work here needs its own explicit mapping regardless of access mechanism.
Also corrected §V.3 item 5's now-stale "shares the same code" cross-
reference -- the Mars's JH7110 PCIe controller needs its own primary-
source check, not an assumed-shared implementation with RP1's.
Not implemented this pass -- recording the real shape is the deliverable;
building the runtime-dispatch version is a materially larger, separate
task. Doc-only change; 3-arch boot verified per the project's standing
rule, proving only that nothing regressed.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019YcT3H2PQeyujrzjqS3Var
|
||
|
|
7187d68082 |
rpi5_native_boot.c: carve /reserved-memory out of the Pi 5 memory map
Previously deferred (rpi5_native_boot.c's own header comment flagged this as needing interval-splitting logic written blind against hardware not yet in hand) -- revisited by fetching bcm2712-ds.dtsi directly rather than assuming reserved-memory was empty or absent. It has one static child (atf@0, ARM Trusted Firmware's own region) and one dynamic child (linux,cma, size/alloc-ranges only, no fixed reg) -- the dynamic one is skipped, nothing fixed to carve and no allocator this early to service it against anyway. Adds two fdt.c primitives: fdt_find_node_by_name() (reserved-memory has neither compatible nor device_type per DT spec) and fdt_next_child_node() -- one exported symbol, not the two-primitive general sibling-walker originally sketched, collapsed after review since the only real use here is "iterate one node's direct children." collect_reserved_ranges() reads each child's own #address-cells/ #size-cells with a fallback to root's only if absent -- confirmed necessary, not just defensive: reserved-memory's own declared <2>/<1> genuinely differs from root's <2>/<2>. emit_region_with_carveouts() clips a sorted reserved-range list against each RAM region, emitting alternating EfiConventionalMemory gaps and EfiReservedMemoryType carve-outs (insertion sort, no libc qsort in freestanding). RPI5_MAX_MEMMAP_ENTRIES is the exact worst-case count, recomputed rather than estimated -- the rpi5_mailbox.c buffer-size bug is the standing lesson for this pattern. Compile-only-verified; nothing in the existing UEFI/QEMU path calls rpi5_native_boot(), so this cannot be exercised until real hardware. Verified 3-arch boot to ok>/zuse)ok>. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_019YcT3H2PQeyujrzjqS3Var |
||
|
|
67e3fb7459 |
rpi5_native_boot.c: Pi 5 DTB->BootInfo constructor (FABRIC-3.md §IV.3 item 2)
rpi5_native_boot() populates the existing BootInfo struct from the devicetree instead of UEFI protocols, then calls the existing, unmodified kernel_main() -- the crux of why most of M1-M9 stays shared between the UEFI and native boot paths. native_rpi5_entry.S now tail-calls into it instead of halting. memory_map is built from /memory's own reg, honoring the *root* node's #address-cells/#size-cells (confirmed against bcm2712.dtsi's actual root node -- <2>/<2> -- not assumed; a wrong cell width here would compile and boot clean in QEMU while silently corrupting the real memory map on real silicon). Required a new fdt_find_node_by_device_type() since /memory is identified by device_type = "memory" per DT spec, not compatible. args comes from /chosen's bootargs fed into the existing cmdline_parse_ascii() (confirmed pure C99 with no UEFI coupling before reusing it). framebuffer comes from the already-built rpi5_mailbox_get_framebuffer() at a fixed 1920x1080x32 default -- no EDID query exists in this codebase, flagged rather than guessed past. Deliberately scoped out, not silently skipped: /reserved-memory is not parsed. Carving reserved sub-ranges out of /memory's span needs interval-splitting logic that would be written blind against hardware not yet in hand -- exactly the kind of code that hides a bug until real silicon. pmm.c's Pass 3 only ever clears pages this file lists as EfiConventionalMemory, so the gap is "less usable RAM than optimal," never "reserved RAM wrongly marked free." Left as its own future item. Also fixes a real link failure this work surfaced: boot/cmdline.c was only in LOADER_SRCS_BASE (the .efi target), not KERNEL_SRCS_BASE (the separate .elf target arch/aarch64/*.c also wildcards into) -- added it there too. Compile-only-verified; nothing in the existing UEFI/QEMU path calls rpi5_native_boot(), so this cannot be exercised until real hardware. Verified 3-arch boot to ok>/zuse)ok>. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_019YcT3H2PQeyujrzjqS3Var |
||
|
|
281de9547c |
native_rpi5_entry.S: Pi 5 native (non-UEFI) boot entry stub (FABRIC-3.md §IV.3 item 1)
rpi5_native_start masks x0 down to the documented 32-bit DTB-pointer range (the firmware's own entry protocol leaves the upper 32 bits unspecified), stores it into g_rpi5_dtb_ptr for the still-open DTB->BootInfo constructor (item 2) to read, then switches sp to a dedicated 2 MiB BSS stack -- this path has no EDK2 boot stack to inherit, unlike every other entry path in this codebase. Intentionally halts (wfe/b loop) afterward rather than tail-calling into item 2's constructor, which doesn't exist yet -- no stub function pretending to be more than it is. Not yet linked at the real 0x80000 load address; that needs its own linker script/build target, not scoped into this item. Compiles and links into the existing ARCH=aarch64 QEMU/UEFI acceptance build as dead code (ELF kernel build's KERNEL_ASM wildcards every *.S in arch/aarch64/; nothing there branches to it), same as rpi5_dtb.c/rpi5_mailbox.c before it. Verified 3-arch boot to ok>/zuse)ok>. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_019YcT3H2PQeyujrzjqS3Var |
||
|
|
a32b0ebcbe |
rpi5_mailbox.c: wire the VideoCore mailbox message protocol (FABRIC-3.md §IV.3 item 3)
New rpi5_mailbox_get_framebuffer() sends one property-tag request buffer (phys size, virt size, depth, pixel order, virtual offset, allocate-buffer, get-pitch) over the register layout rpi5_dtb.c already discovers, populating an Rpi5FramebufferInfo kept in exact field-for-field sync with uefi.h's FramebufferInfo so console.c/vt100.c/framebuffer.c need no downstream changes once this is wired into a real entry stub. Register offsets (+0x00/+0x18 MBOX0 read/status, +0x20/+0x38 MBOX1 write/status) confirmed against a Pi-5-specific bare-metal reference, independently cross-checked against this codebase's own rpi5_dtb.c translated base address. Caught and fixed a real buffer-overflow bug before compiling: the static request buffer was sized 32 words against an actual 35-word requirement for the 7-tag sequence, recomputed exactly rather than re-estimated; resized to 40 words. Two things flagged as genuinely unverified against real hardware (not guessed past the comment): the allocate-buffer tag's request-size field value, and whether its response address needs classic bus-alias masking on Pi 5 specifically. Compile-only-verified -- no caller yet (that's the still-open entry-stub/DTB constructor items). Verified 3-arch boot to ok>/zuse)ok>. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_019YcT3H2PQeyujrzjqS3Var |
||
|
|
ca52ce8243 |
rpi5_dtb.c: wire fdt.c's node-scoped lookup into the Pi 5 UART/mailbox addresses
New include/starkernel/rpi5_dtb.h / src/starkernel/arch/aarch64/rpi5_dtb.c:
rpi5_uart_base()/rpi5_mailbox_base(), each finding their peripheral by
compatible string ("arm,pl011" / "brcm,bcm2835-mbox") via fdt_find_node_by_
compatible() then reading its "reg" via fdt_find_prop_in_node().
Found and fixed a real translation gap before it could have silently
produced a wrong address: confirmed directly against bcm2712.dtsi
(raspberrypi/linux) that both peripherals live under one "soc"
simple-bus node whose ranges property adds a fixed 0x10_0000_0000
offset to every child reg value. fdt.c's reader deliberately doesn't
apply ranges translation generally (not a general devicetree
library); this file applies that one, fixed, SoC-wide offset
explicitly, documented with the exact devicetree excerpt that
confirmed it.
Compile-only verification -- no caller wired in yet, these two
functions are what the still-open entry-stub and mailbox-framebuffer-
driver punch-list items will call. Verified 3-arch boot to ok>
(amd64/aarch64/riscv64, each in the foreground; rpi5_dtb.o confirmed
built on aarch64, the only arch that compiles this file).
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019YcT3H2PQeyujrzjqS3Var
|
||
|
|
5e46f18fd9 |
fdt.c: node-scoped lookup extension (FABRIC-3.md SSIV.3/SSV.3 shared item)
Adds fdt_find_node_by_compatible() and fdt_find_prop_in_node() to the
minimal FDT reader -- the extension fdt.h's own header comment already
flagged as a known future need ("item 0.6 will need node-scoped reg
lookups"), now with real consumers: the Pi 5's UART/mailbox register
addresses (native boot, no ACPI) and the Milk-V Mars's real PLIC base
address (currently hardcoded to QEMU-virt's own value).
fdt_find_node_by_compatible() matches any entry in a node's
NUL-separated "compatible" list, first match in document order.
fdt_find_prop_in_node() scopes to that one node's own direct
properties only -- stops at the first child node or the node's own
end, per the DT spec's ordering guarantee that a node's properties
always precede its children. Same minimal, non-tree-building,
single-linear-scan-per-call style as the existing reader; no new
state, no allocation.
Compile-only verification -- no caller wired in yet, this is the
shared primitive both boards' own punch-list items will call once
built. Verified 3-arch boot to ok> (amd64/aarch64/riscv64, each in
the foreground).
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019YcT3H2PQeyujrzjqS3Var
|
||
|
|
bffd87615d |
FABRIC-3.md: riscv64 (Milk-V Mars) planning decided + punch list
Resolved SS V.1's flagged gap: standard RISC-V SBI boot protocol, confirmed via OpenSBI's own docs -- a0=hart ID, a1=DTB pointer, S-mode entry, universal across FW_DYNAMIC firmware regardless of vendor, not chain-specific guesswork. Decided: observation is HDMI-only, same reasoning and constraint as the Pi 5 (no bridge hardware for this board's own first bring-up either). Traced boot_info->acpi_table's real riscv64 consumers the same way as aarch64: pci_init() again (Mars's M.2 slot is PCIe-attached, same shape of gap as the Pi 5's RP1); timer.c is already fully DTB-driven, no work needed there. One real, already-flagged risk found while tracing this: PLIC_BASE is a QEMU-virt-specific constant, not DTB-discovered -- arch/riscv64/ plic.c's own doc comment already warned about this; it becomes concrete now that real hardware is actually in scope. Real punch-list item, not hypothetical. 6-item no-hardware-needed punch list (entry stub, DTB->BootInfo constructor, DTB-discovered PLIC base, unresearched JH7110 framebuffer flagged honestly rather than assumed, shared pci_init() DTB path with the Pi 5, image-packaging tooling) plus 5 items deferred to 2026-09-17. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_019YcT3H2PQeyujrzjqS3Var |
||
|
|
1ec2a29384 |
FABRIC-3.md: aarch64 (Pi 5) planning decided + punch list
Decisions from conversation: observation is HDMI-only for this
board's own bring-up (no second Pi, no dedicated USB-serial adapter;
using the Milk-V Mars as a bridge before it's independently validated
would be circular). Both boards arrive 2026-09-17, giving real runway
to finish design/code work first ("plan well before doing").
Traced boot_info->acpi_table's actual aarch64 consumers against real
code before writing the punch list: only pci_init() (unconditional,
relevant since RP1 is PCIe-attached) and this session's own
running_under_hypervisor() (already degrades safely on NULL). GIC
init (arch/aarch64/apic.c) already only tries boot_info->dtb, never
acpi_table -- Pi 5 native boot removes its stated blocker for free.
6-item no-hardware-needed punch list: entry stub at 0x80000, a DTB ->
BootInfo constructor calling the existing unmodified kernel_main()
(the crux of why most of M1-M9 stays shared), the mailbox-interface
framebuffer driver, an fdt.c node-scoped-lookup extension (its own
header already flagged this as a known future need), a DTB-based
pci_init() path for RP1, and config.txt contents. Plus 5 items
deliberately deferred until hardware is in hand 2026-09-17.
Also fixed a formatting slip from an in-progress edit (a bullet
accidentally turned into a malformed heading) before it could compound.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019YcT3H2PQeyujrzjqS3Var
|
||
|
|
9142d50b73 |
FABRIC-3.md: Zynq-7000 (Puzhi PZ7010/PZ7020 StarLite) added to hardware reference
Recorded only, no work scoped -- but unlike BeagleBone Black, this one isn't a random addition: ROADMAP.md already names Zynq FPGA as the next big milestone beyond v2.5.0 (the "configurable silicon" step, tied to the three-product split's HOL-proven sealed-execution hardware product). This puts a concrete, purchasable board under that already-named milestone: Puzhi PZ7010-StarLite (XC7Z010) or PZ7020-StarLite (XC7Z020), dual-core Cortex-A9 PS + Artix-7/Kintex-7 PL fabric, DDR3/JTAG/UART/HDMI/GbE/USB2.0/40-pin, MIPI CSI on the 7020 variant only. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_019YcT3H2PQeyujrzjqS3Var |
||
|
|
5eeb993ca2 |
FABRIC-3.md: riscv64 boot chain resolved, BeagleBone Black noted, header bug fixed
Milk-V Mars boot chain resolved via VisionFive 2 research: the Mars is a documented mainline U-Boot target using the exact same binaries as the VisionFive 2 (same StarFive JH7110 SoC) -- U-Boot + OpenSBI + devicetree, not UEFI, same fork already decided for aarch64. Entry point 0x40000000, mhartid CSR for core ID, UART at 0x10000000/115200 -- DTB pointer/hart-ID register convention at actual kernel entry not yet confirmed for this specific chain. Fixes a real bug from the earlier aarch64 edit: the "## V. riscv64 -- Milk-V Mars" section header had been accidentally dropped, leaving a stale duplicate "Already true"/"Genuinely open" block sitting where the real section should have started. Removed the duplicate, restored the header, folded today's research into the section properly. BeagleBone Black added to SS VI's hardware-identification reference per direct instruction -- recorded only, no work scoped around it: it's a 32-bit ARM (TI AM335x, Cortex-A8) SoC, a genuinely different, fourth architecture this kernel has no support for, not another board under an existing one. FABRIC-4.md SS2: captured the pinned-GPIO-VM idea raised in conversation (Pi 5 needs one, Milk-V Mars explicitly undecided) as a theory-stage note, cross-referenced from SSIV/SSV's own open-questions lists. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_019YcT3H2PQeyujrzjqS3Var |
||
|
|
987c751352 |
FABRIC-3.md: per-board hardware-identification reference (SS VI)
Consolidated SoC/CPU/RAM/I-O facts for all three real-hardware targets, researched via web search with sources cited rather than assumed from memory: - amd64 (Beelink SER5): Ryzen 7 family confirmed; exact SKU (5700U/5800H/7735HS all shipped under this branding) not yet confirmed against the actual unit -- flagged, not guessed. - aarch64 (Raspberry Pi 5): BCM2712, quad-core Cortex-A76 @ 2.4GHz, VideoCore VII GPU, LPDDR4X-4267. FEAT_RNG (RNDR) presence on this core flagged as unconfirmed either way. - riscv64 (Milk-V Mars): StarFive JH7110, 4x SiFive U74-MC + 1x S7 monitor core, up to 1.5GHz. Noted it shares its SoC with the StarFive VisionFive 2 -- existing VisionFive 2 bring-up material may transfer directly. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_019YcT3H2PQeyujrzjqS3Var |
||
|
|
a66af477ac |
FABRIC-3.md: aarch64 boot-chain decision -- native boot flow, not UEFI
Researched both options before deciding. The UEFI path (rpi5-uefi, TF-A+EDK2, SBBR-compliant) is real but archived since 2025-02-04 -- support ended when newer Pi EEPROM firmware broke compatibility, and its own README says ACPI support is limited/incomplete. Decided: native boot flow instead (config.txt/kernel_2712.img/DTB, x0=DTB pointer at entry, no ACPI at all). Named the real scope rather than estimating it small: a new, non-UEFI aarch64 entry path, a DTB-driven BootInfo equivalent, and a new mailbox-property-interface framebuffer driver (no precedent in this codebase). The one genuine piece of reusable groundwork: starkernel/hal/fdt.c's minimal FDT reader, already built for riscv64's timebase-frequency lookup, extends directly to Pi 5 peripheral discovery. Also documents the peripheral-RNG research: BCM2712 has no brcm,bcm2712-rng200 (or equivalent) entry anywhere in current mainline Linux, and RP1's own published peripheral list doesn't mention an RNG -- genuinely unresolved, not just under-researched. Not yet turned into a punch list -- the boot-chain fork's own shape needs thinking through first. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_019YcT3H2PQeyujrzjqS3Var |
||
|
|
e5e28d5198 |
FABRIC-3.md: amd64 bare-metal-boot planning decided + punch list
Decisions from conversation: observation is HDMI (interactive) + serial via the Raspberry Pi's own GPIO UART as the bridge, if the SER5 exposes a UART header (not yet confirmed); genericity is verified by a code audit against real UEFI/ACPI standards rather than a second physical machine (none available); Secure Boot is already disabled on this SER5, so no signed-loader work is needed for this pass. 9-item punch list follows: build+flash the thumbdrive image, physically inspect for a UART header, connect HDMI, boot, a code-audit pass for SER5-specific assumptions (the actual genericity bar), capture the boot (POST/ok>/rdrand backend/serial transcript), mint+re-attach Zuse on real hardware, then update this section with results before moving to aarch64. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_019YcT3H2PQeyujrzjqS3Var |
||
|
|
7f9a4d4d4a |
FABRIC-3.md: three per-architecture bare-metal-boot planning sections
Per direct instruction: amd64's real goal is genericity (any x86_64 laptop/desktop/tower/mini, not just the Beelink SER5 reference machine); aarch64 targets the Raspberry Pi 5 exclusively; riscv64 targets the Milk-V Mars exclusively -- no cross-board genericity requirement for the latter two, unlike amd64. Each section starts from what's already true (ROADMAP.md's existing v2.2.0/v2.4.0/v2.5.0 board-by-board gates, the already-built thumbdrive/iso-usb Makefile targets, the amd64 RDRAND backend) and names what's genuinely still unknown rather than assuming -- most notably whether the Milk-V Mars boots via UEFI (like this project's QEMU riscv64 target) or via U-Boot+OpenSBI+devicetree, which would need a different boot entry path, not just different peripheral addresses. Doc-only change, no acceptance build needed. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_019YcT3H2PQeyujrzjqS3Var |
||
|
|
8717416d36 |
FABRIC-3.md: version correction -- LITHOS_VERSION back to 2.0.0, plus a rename-gap fix
LITHOS_VERSION 2.0.1 was premature: per this project's own versioning policy, 2.0.1 claims SER5 hardware-track progress (RDRAND backend + thumbdrive image) that was never actually verified on real hardware -- that verification is FABRIC-3.md's own open topic. Reset to 2.0.0 (still a QEMU-only release, correctly). Verified 3-arch boot shows "LithosAnanke v2.0.0" in each serial log directly, not assumed from the Makefile edit alone. Also closes a real gap found in today's earlier FABRIC-series rename: Makefile.starkernel, Kconfig.kernel, scripts/bleach_zuse_img.sh, four proof/*.thy files, and isr.S were never swept -- the original file list only matched *.md/*.c/*.h/*.4th, silently skipping every other extension. Fixed with the same safe placeholder substitution. .claude/settings.local.json's historical permission-grant log and ClaudeEXPORT/'s frozen export were deliberately left untouched. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_019YcT3H2PQeyujrzjqS3Var |
||
|
|
fcba528273 |
FABRIC-3.md: Task 1 closed -- master fast-forwarded to v2.0.1, verified
master ( |
||
|
|
72c14cb9eb |
FABRIC-3.md: open new living document (bare metal boot); close FABRIC-2.md
FABRIC-2.md closed/archival as of 2026-09-04 -- its full punch list (§I) was worked through to completion this session. FABRIC-3.md opens as the new living document, topic: bare metal boot (FABRIC-2.md §I.6's own Milestone 8, the one item that couldn't close from a coding session -- needs a real machine and a human present). First task written up before executing, per this series' own standing discipline: merge v2.0.1 into master and verify build/function equivalence on a clean master tree. Investigated the branch topology first -- master is a strict ancestor of v2.0.1 (47 commits behind, no divergent history), so this is a pure fast-forward, not a real merge. Updated FABRIC-4.md's and .claude/CLAUDE.md's stale pointers at FABRIC-2.md as "current/living" to point at FABRIC-3.md instead. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_019YcT3H2PQeyujrzjqS3Var |
||
|
|
b031b802e3 |
Rename FABRIC series: FABRIC.md->0, FABRIC-2.md->1, FABRIC-3.md->2, FABRIC-4.md unchanged
FABRIC.md -> FABRIC-0.md FABRIC-2.md -> FABRIC-1.md FABRIC-3.md -> FABRIC-2.md (the current/living document) FABRIC-4.md unchanged (new #3 to follow separately) Every cross-reference repo-wide updated to match, including doc-comment citations inside kernel source (.c/.h) files -- done via an ordered placeholder substitution (FABRIC-3.md->placeholder2, FABRIC-2.md-> placeholder1, FABRIC.md->placeholder0, then placeholders resolved to final names) in a single pass per file to avoid double-shifting already-renamed references. One line in capsules/font.4th grew past the 64-char block-format limit as a side effect of the longer filename; shortened it and reverified with mkcapsule --lint (34/34 pass) before rebuilding. Verified 3-arch boot to ok> (amd64/aarch64/riscv64, each in the foreground) after the fix; logs and DoE CSVs from this session's verification runs included per this repo's own audit-artifact convention. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_019YcT3H2PQeyujrzjqS3Var |