boards/BRINGUP.md A1, FABRIC-3 SXLII. xhci.c keeps a table of controllers
(up to 8) and services each; kernel_main brings up index 0, 1, ... until
there is none. repl.c's and blkio_usb.c's per-slot state is per
controller now (a slot ID is a controller's own), and each USB keyboard
keeps its own last report and lights; an unplugged keyboard releases what
it held.
Test first: keyboard and identity on a second controller behind a bridge,
Zuse on the first -- before, only Zuse; after, all three, on all three
ISAs. Hot-plug and unplug on the second controller. Acceptance unchanged.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
boards/BRINGUP.md A3 and S3, FABRIC-3 SXLI. A HID boot keyboard is
configured (interrupt IN endpoint, SET_PROTOCOL boot) and its reports
become the same Linux-keycode events as PS/2 and virtio (usb_kbd.c): the
full layout -- F-keys, navigation block, arrows, Num Lock, keypad. The
console treats Caps and Num Lock as toggles shown on the keyboard's
lights, and the keypad as digits or navigation. While a USB keyboard
runs, its event ring is serviced every tick, not once a second.
Found on the way: with no i8042 (port 0x64 reads 0xFF) the kernel hung at
boot in an endless drain -- a legacy-free PC would stop there. Detected
and skipped now; drains bounded.
QEMU, amd64 with the USB keyboard the only one: 1 2 + . on main keys and
keypad, Caps Lock, Num Lock all right; aarch64/riscv64 configure it too.
Acceptance on three ISAs unchanged; identities hot-plug.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Any identity could have arbitrary FORTH run as Zuse: KH-ELEVATE-SEND and
KH-BLK-ATTACH-SEND sent any text to Hera, from any VM (shown live). And the
drain popped a message after running it, so a payload calling a colon word
ran twice. Both fixed test first (FABRIC-3 SXXXVII):
- KH-BLK-ATTACH-SEND is ( dev-addr ok? -- sent? ), Artemis only; the kernel
writes the reply text. BLK-ATTACH-ACK is Hera's only.
- The drain pops before it runs.
- Elevation, ruled not needed: KH-ELEVATE-SEND, message type 8,
zuse-eligibility.4th, ZUSE-ELIGIBLE?/ZUSE-ELIGIBILITY-ADD/
ELEVATE-PUBKEY-UNPACK and the eligibility list removed; its disk area
stays reserved, unused. FABRIC-3.7 closed.
Three ISAs: POST 1052 passed; new parity baseline word_count=523
hash=0xb73b58052d591638 (deliberate).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
FABRIC-3.5 SXXXII, closing FABRIC-3 SXXIX bug 2 (SXXXVI). A send marks the
receiver for the switch signal; the VM's own loop on its native stack takes
its messages and yields; Hera's idle beat makes the pending switch instead
of running other VMs' messages on her stack; every VM gets switcher turns
from birth; the drain refuses any call outside the VM's own context (the
test: it held every relayed line before, none now).
Found on the way: amd64's first-entry frame left rsp 8 bytes off the SysV
entry alignment (#GP on the first interpreter run on a VM's own stack), and
a VM yielding from its loop was marked SWITCHED_OUT, which stopped console
relay after one message and would have made KILL refuse it.
Relay of four lines to a WIREBIND identity on all three ISAs, five
hot-plugged identities, and standard acceptance (POST 1052, hash
0x08873e0f44b7cb2a) all pass.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Built with EMERGENCY_CONSOLE_ENABLED=1 and booted with no identity logged
in, the prompt printed "ok> ok" without end, 1.4 million times in 200
seconds (logs/20261013-210442). sk_console_readline() gave up at once
whenever no identity was present. The production build answers that by
going silent until a login; the bring-up build, which needs no login,
took it as an empty line and asked again. The give-up is now the
production build's only.
Found rehearsing boards/BRINGUP.md; it predates the console change of
c9519173 (the image built from the commit before that did the same).
The riscv64 bring-up build, no thumbdrive, three lines typed
(logs/20261013-235129): one prompt that waits, and 3, 56 and 81.
Acceptance of the production build, one QEMU at a time: amd64
(-235255), aarch64 (-235411), riscv64 (-235620) to the zuse prompt, no
unknown word, hash 0x08873e0f44b7cb2a on all three.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Source tree reorganization:
- Move StarForth v3 engine to v3/ (src/, include/, Makefile)
- Move kernel to kernel/ (src/, include/, linker/, Makefile)
- Create v4/ skeleton for F18-ISA golden model (DECOMPOSITION.md, JUSTIFICATION.md)
- Move FABRIC-0..4.md to docs/fabric/
- Move ONTOLOGY.md and ROADMAP.md to docs/
Board infrastructure:
- Add boards/ser5/, boards/raspi/, boards/milkv/, boards/zynq7020/
- Each board has board.mk (ISA, CPU flags, boot recipe) and README.md
- Root Makefile becomes thin dispatcher: boot_image, all, clean, docs take TARGET
- make boot_image TARGET=SER5|RASPI|MILKV builds one GPT/MBR image per board
- ZYNQ7020 target exists but stops with clear error (ARMv7 port not built yet)
- scripts/mkdiskimage.sh builds disk images for all boards
Docs pipeline:
- docs/book/ with LaTeX master (main.tex) and Makefile
- pandoc converts Markdown to LaTeX at build time
- Two Lua filters: table-widths.lua (wide tables wrap), code-breaks.lua (inline code breaks)
- make docs builds single PDF (754 pages, 0 missing characters)
- make docs TARGET=<board> adds board appendix
- build/docs/<book|board>/meta.tex stamps git commit into PDF
Bug fixes:
- 42 include paths that only worked by accident now use correct relative paths
- clang-18 hardcode replaced with configurable CC variable (fixed aarch64 build)
- Pi 5: kernel_2712.img linked at 0x80000, .bss zeroed, memory reserved
- Doxyfile, .clang-tidy, README.md, Kconfig paths updated
Verified:
- Hosted v3 build passes 1012 tests, 0 failures
- SER5 image boots in QEMU (OVMF), POST passes, K exact (65536 = Q48_ONE)
- Milk-V image boots in QEMU (OpenSBI + U-Boot + bootefi), POST passes
- make clean TARGET=<board> removes only that board and its ISA objects
- make all builds all boards, hosted v3, and docs in one run
Co-authored-by: Junie <junie@jetbrains.com>