Punch list §25 item 0.6 complete. Ruling applied (AskUserQuestion, this session): DTB is confirmed unreachable on this system's aarch64 firmware too (qemu-efi-aarch64 2025.11-3ubuntu7, same finding as riscv64's item 0.3), so GICD/GICC base addresses and the timer PPI are named QEMU-virt constants with a recorded caveat, not DTB-discovered as the item originally asked. Nothing here was recalled from memory. Base addresses (GICD 0x08000000, GICC 0x08010000) and the timer PPI (30, non-secure EL1 physical) were read out of QEMU 10.2.1's own internal devicetree via `qemu-system-aarch64 -machine virt,dumpdtb=...`, decoded with this tree's own fdt.c reader rather than a new tool -- correct for this exact QEMU version, not assumed stable across others. Bonus finding from the same dump: PPI 26 for the EL2 hypervisor timer, which item 0.7 will need for its EL2 path. Register offsets within each block (GICD_CTLR, GICC_IAR, etc.) are GICv2 architectural constants, not board-specific, and were cross-checked against Linux's own arm-gic.h driver header rather than recalled either. Acceptance amended before implementing (§25.0 "when an item is genuinely wrong"): the original text required observing a delivered-and-acknowledged timer interrupt, which cannot happen within this item's own scope -- apic_timer_start() (item 0.7) is still the no-op stub, so nothing arms the timer. This is the same defect the earlier review's C2 fix already applied to items 0.2 and 0.5; it was missed here. Acceptance is now: GIC initialises without fault, the IAR/EOIR path is wired into aarch64_irq_handler() and ready, boots with no regression -- item 0.7's tick-advance is what proves delivery, exactly as 0.5 already defers to 0.7. EL-aware (B3, same discipline as items 0.4/0.5): apic_init() selects PPI 30 or 26 from aarch64_current_el(), decided once and cached, not re-derived per interrupt. aarch64_irq_handler() now does real work: reads GICC_IAR (the GICv2 acknowledgement step), dispatches to heartbeat_tick() when the INTID matches the timer PPI, and always completes with GICC_EOIR (INTID 1023 = spurious handled per the GICv2 spec, not as a special case of "unrecognised"). This mirrors exactly how riscv64's item 0.2 built full cause-dispatch logic before its timer was armed in 0.3. Investigated and resolved a real scare during verification: QEMU's `-d int` trace showed 1,728 "Taking exception 5 [IRQ]" events by the time boot reached the prompt, which looked exactly like an interrupt storm (hypothesis: EDK2 firmware leaves CNTP_CTL_EL0 enabled with a stale comparator, and enabling the GIC path exposes it before item 0.7 reprograms the timer). A direct one-shot probe inside aarch64_irq_handler() itself -- ground truth for whether this code path runs at all -- fired zero times across a clean, bounded boot. The trace events were almost certainly from EDK2 firmware's own internal timer usage during its own boot phase, before control passes to this kernel; the earlier conclusion was drawn from the external trace alone without checking that distinction, and the probe (not the trace) is what settled it. Probe code fully reverted; not part of the commit. Verified: builds clean, boots to ok> with no regression, dict_hash 0x3d4e1daf289da94f unchanged from the item 0.1-0.5 baseline, EL banner and IDT-installed lines still print in order, GIC init line confirms PPI 30 selected. Only aarch64-scoped files touched; amd64/riscv64 not rebuilt. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
capsules/
FORTH personality files loaded by the VM at boot. A capsule is an immutable, content-addressed payload; its XXHash64 hash is its identity. Any mutation changes the hash and the birth protocol rejects the image.
Key files
| File | Type | Purpose |
|---|---|---|
init.4th |
(m) MAMA_INIT |
Default Mama VM personality — loaded at LBN 2048 |
ACL.4th |
user | Word-level ACL system; self-activating at boot |
zuse.4th |
user | Bootstrap superuser; loaded by ACL.4th |
doe.4th |
user | DoE workload words (EXEC-DOE) — opt-in |
init-0.4th … init-9.4th |
(p) |
Numbered personality variants |
init-l8-*.4th |
(p) |
L8 Jacquard mode variants (stable/volatile/diverse/temporal/transition/omni) |
hermes/init.4th |
(p) |
Hermes baby VM personality |
artemis/init.4th |
(p) |
Artemis baby VM personality |
Block namespace
Block ranges are shared across all loaded capsules — collisions cause silent word-definition overwrites.
| Range | Owner |
|---|---|
| 2048–2099 | init.4th |
| 2100–2199 | doe.4th |
| 3000–3999 | workload capsules |
| 4000+ | user-defined (ACL.4th, zuse.4th, …) |
Each block is limited to 1024 bytes. Verify with wc -c before committing.
See also
experiments/bare_metal/README.md— DoE protocols and block namespace rulesdocs/03-architecture/word-acl/DESIGN.md— ACL system designtools/mkcapsule.c— assembles capsules intocapsule_generated.c- Project root