fix(v4.0.0): POST leaves nothing, as v3 really does; and what the review of step 6b found

Captain Bob was told that v3 leaves the words POST's cases define in the
dictionary, and ruled that v4 should.  That was false: v3's run_test_suite
puts the dictionary back after each word's cases (test_common.c:333,
:365).  Shown that, he ruled that POST leaves nothing.  The boot now
seals the system, runs POST, and has the node do COLD, whose printing is
not shown; PARITY:V4_SYSTEM is the system as sealed.

A case the node does not come back from ends POST there, named, with how
many were not run: it would have stalled the boot for hours, where the
capsule had ended it.  The runner's test of it now uses a word that
really never ends.

hosted-check also requires that RS1 and T{ are unknown after boot, and
boots a program whose POST has failing cases (tests/post_cases_fail.c):
PARITY:FAIL, POST: FAILED, no prompt, none of a case's printing shown.

Comments and documents that still named the POST capsule or its two
hooks are brought up to date; NUCLEUS.md 6.3 says what v3 does, with the
lines, and how the wrong ruling came about.

make -C v4 test, sanitize and hosted-check pass; amd64, aarch64 and
riscv64 boot, POST 538 of 538, word_count=314, dict_hash
0x220ab283a504a3b3 on all six: logs/20261007-112638, -112901, -113220.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
rajames
2026-10-07 11:40:20 -04:00
co-authored by Claude Opus 5.5
parent eda6577a53
commit 18adf59091
17 changed files with 669 additions and 65 deletions
+1 -1
View File
@@ -1,5 +1,5 @@
# Capsule Block Manifest — Auto-generated
<!-- Generated by mkcapsule --manifest 2026-10-07T14:56:10Z -->
<!-- Generated by mkcapsule --manifest 2026-10-07T15:31:38Z -->
<!-- DO NOT EDIT — re-run mkcapsule --manifest to refresh. -->
<!-- Hand-written justifications and immutability notes live -->
<!-- in MANIFEST.md alongside this auto-generated index. -->
+2 -2
View File
@@ -194,7 +194,7 @@ program with the node as its interpreter. That is withdrawn. From here:
**What the two share (confirmed by Captain Bob the same day, "yes,
exactly"):** the engine in `v4/src`; the FORTH-79 capsule,
`capsules/v4/forth79.4th`; and its POST, `capsules/v4/post79.4th`. **The
`capsules/v4/forth79.4th`; and its POST (then `capsules/v4/post79.4th`; since `MESH.md` step 6b, 2026-10-07, the kernel's cases, `v4/system/post_cases.c`). **The
nuclei are separate.** The bare-metal nucleus needs word IDs in its
headers and words that are called where the hosted one compiles them in
line; the hosted nucleus need not have either. The hosted product may
@@ -346,7 +346,7 @@ not written yet. Nothing of it is built.
| `v4/system/boot.c`: its own capsule loader and `PARITY:V4_*` lines | Stays for the hosted product. On bare metal v3's birth protocol loads the capsules and prints v3's parity lines (step 4). |
| The node's prompt loop, and the code that strips ` ok` from its output | Goes at step 1. |
| `capsules/v4/forth79.4th`, `post79.4th`, `mkpost.py`, the rules | Stay. POST is the gate for every word moved out of the nucleus. |
| `(CATCH)`, `(EMIT-HOOK)`, `NODE-ERROR` by name | Stay; POST uses them. |
| `(CATCH)`, `(EMIT-HOOK)`, `NODE-ERROR` by name | `NODE-ERROR` stays. `(CATCH)` and `(EMIT-HOOK)` went with the POST capsule, `MESH.md` step 6b, 2026-10-07: POST is the kernel's and needs neither. |
| The per-call-target count (`v4/src/heat.c`, `call[]`) | Goes at step 3, when the node does at `call` what v3 does. |
| The hosted Linux product (`v4/tools/hosted.c`, `v4/system/boot.c`) | Stays, as its own product (3c). |
+18 -10
View File
@@ -753,15 +753,21 @@ Each is tested, committed and pushed before the next.
- *The boot* (`v4/system/boot.c`) runs it after the capsules, prints
`PARITY:V4_SYSTEM`, and seals. `capsules/v4/post79.4th`, `(CATCH)` and
`(EMIT-HOOK)` are gone.
- *First built* with what the cases define left in the dictionary
(`4bdb210a`; `logs/20261007-105118`, `-105335`, `-105651`).
- *Review, 2026-10-07*, by a fresh reviewer. It found that v3 does not
leave them (above, and `NUCLEUS.md` 6.3), and that a case the node did
not come back from would have stalled the boot for hours where the
capsule had ended it. Changed: the boot seals, runs POST, and has the
node do `COLD`; the runner ends POST at such a case and names it;
`hosted-check` boots a program whose POST has failing cases
(`v4/tests/post_cases_fail.c`) and requires `PARITY:FAIL`, `POST:
FAILED`, no prompt, and none of a case's printing on the console.
- *Verified.* `make -C v4 test`, `sanitize` and `hosted-check`; three
bare-metal boots, `logs/20261007-105118` (amd64), `-105335`
(aarch64), `-105651` (riscv64). On all six: POST 538 of 538,
`word_count=411`, `dict_hash=0x6fb1d09418b189ee`. At the prompt `T{`
is unknown, and `RS1`, which a case defines, prints `42 42` before and
after `COLD`. A hosted program built with one case's expected output
changed names the case and ends `PARITY:FAIL`, `POST: FAILED`.
- What the cases define takes 1,385 cells of the dictionary space's
5,632.
bare-metal boots, `logs/20261007-112638` (amd64), `-112901`
(aarch64), `-113220` (riscv64). On all six: POST 538 of 538,
`word_count=314`, `dict_hash=0x220ab283a504a3b3`. At the prompt `T{`
and `RS1` are unknown words, and `HERE` is 8300.
Acceptance, as approved:
1. *Same verdict.* The three hosted programs and the three bare-metal
@@ -771,8 +777,10 @@ Each is tested, committed and pushed before the next.
2. *Nothing of the harness is on the node.* At the prompt `T{` is an
unknown word, and `(CATCH)` and `(EMIT-HOOK)` are gone from the
nucleus.
3. *What the cases define is there.* A word a case defines can be used
at the prompt after boot, and survives `COLD`.
3. ~~What the cases define is there.~~ **Reversed 2026-10-07:** *POST
leaves nothing.* A word a case defines is unknown at the prompt
after boot. (The first form rested on a false statement about v3;
`NUCLEUS.md` 6.3.)
4. *The judge can fail.* Given a case with a wrong expected stack, one
with wrong expected output, one that must end in an error and does
not, and one that ends in an error and must not, the runner reports
+28 -10
View File
@@ -76,7 +76,7 @@ moved.
| File | Capsule name | Contents |
|---|---|---|
| `capsules/v4/forth79.4th` | `v4:forth79.4th` | The Required Word Set as colon definitions |
| `capsules/v4/post79.4th` | `v4:post79.4th` | The POST harness and its cases |
| ~~`capsules/v4/post79.4th`~~ | | Gone 2026-10-07: POST is the kernel's (6.3); its cases are `v4/system/post_cases.c` |
Both are ordinary `.4th` capsules: `Block N` headers, lines of at most 64
characters, at most 16 lines to a block. `tools/mkcapsule.c` bakes them into
@@ -168,8 +168,10 @@ for the record.
the interpreter, reads the VM's error flag, and puts the VM's stack
pointers, error and mode back (`test_common.c`, `run_single_test`). It
runs once at boot on the first VM, against block RAM of POST's own, and
the parity line is taken afterwards. Whatever the cases define stays in
the dictionary.
the parity line is taken afterwards. What the cases define does not stay:
`run_test_suite` saves the dictionary before each word's cases and puts it
back after them, "to remove test-created words" (`test_common.c:333`,
`:365`).
**v4.**
@@ -190,12 +192,28 @@ the dictionary.
ended in an error if any of its lines did.
- *What it prints.* For a failing case, `POST FAIL: name out<...>
stack<...>`. Then `PARITY:V4_POST tests=N pass=N fail=N`.
- *What is left.* What the cases define stays in the dictionary, as in
v3 (ruled 2026-10-07, on being told that the capsule had ended with
`FORGET` and left nothing). The system is sealed after POST, so `COLD`
comes back to those words and `FORGET` will not go below them. Measured
2026-10-07: they take about 1,290 cells of the 5,632 in the dictionary
space.
- *What is left: nothing*, as in v3. The system is sealed before POST,
and after the last case the kernel has the node do `COLD`, which comes
back to the system as sealed; what `COLD` prints is not shown. The
dictionary is put back once, after all the cases, and not after each
word's as v3 does: the expected results were taken from one v3 session
in which nothing was put back between cases (6.4), and the capsule did
the same with its one `FORGET` at the end.
**How this came to be ruled twice.** On 2026-10-07 Captain Bob was told
that v3 leaves the cases' definitions in the dictionary, and ruled "as
v3: they stay". That was false: it was read from `run_single_test`,
which puts back only the stacks, without reading `run_test_suite`. It
was built so, and the review of the step found it; shown what v3 does,
he ruled that POST leaves nothing.
- *A case the node does not come back from* — it has stopped, or runs for
ever — fails, and POST ends there: the runner names it and says how many
cases were not run.
- *What use still changes.* After POST and `COLD`, `HERE` and `LATEST` are
where they were, but the dictionary hash is not what it was before POST:
each word POST had interpreted has a different TTL in its entry, the
count of uses left before its access is checked again
(`v4/capsule/compile.v4`, `(ACL?)`). 138 cells, measured 2026-10-07. It
is the same on every system, so the six still agree.
- *Gone:* `capsules/v4/post79.4th` and its blocks 7000 up; the harness
words; `(CATCH)` and `(EMIT-HOOK)`, with what `EMIT` and the prompt
loop did for them.
@@ -332,7 +350,7 @@ check for the FPGA gateway and is not part of this acceptance.
| Hosted builds per ISA | `v4/Makefile` | Cross-compiler targets for aarch64 and riscv64 |
New: the shared v4 boot sequence (one file), the v4 dictionary hash, the
case-extraction script, `forth79.4th` and `post79.4th`.
case-extraction script, `forth79.4th` and `post79.4th` (the last gone since step 6b, 6.3).
The v3 boot is untouched: `STARFORTH_V4` defaults to off.
@@ -0,0 +1,155 @@
[=3hBdsDxe: loading Boot0002 "UEFI QEMU DVD-ROM QM00005 " from PciRoot(0x0)/Pci(0x1F,0x2)/Sata(0x2,0xFFFF,0x0)
BdsDxe: starting Boot0002 "UEFI QEMU DVD-ROM QM00005 " from PciRoot(0x0)/Pci(0x1F,0x2)/Sata(0x2,0xFFFF,0x0)
[=3hStarKernel UEFI Loader
Loading kernel from ESP...
[CKPT 001] Entered efi_main - ConOut live
RAW SERIAL UP
[CKPT 002] Serial (COM1) initialized
Monolithic build - kernel linked directly
Collecting boot information...
CmdLine: parsed OK
[CKPT 004] Command line parsed
[CKPT 005] Kernel stack allocation decided
[CKPT 006] Boot info collected (ACPI table located)
GOP: linear framebuffer found
[CKPT 007] GOP: linear framebuffer found
[CKPT 008] About to enter ExitBootServices retry loop
EBS...
EBS OK
Calling kernel_main (monolithic)...
_____ _ _ __ _
/ ____| | | |/ / | |
| (___ | |_ __ _ _ __| ' / ___ _ __ _ __ ___| |
\___ \| __/ _` | '__| < / _ \ '__| '_ \ / _ \ |
____) | || (_| | | | . \ __/ | | | | | __/ |
|_____/ \__\__,_|_| |_|\_\___|_| |_| |_|\___|_|
LithosAnanke v2.1.0
Architecture: amd64
Build: Oct 7 2026 11:26:09
UEFI BootServices: EXITED
=== StarKernel Boot Information ===
Memory map entries: 131
Total memory: 1023 MB
Usable memory: 966 MB
===================================
PMM initialized.
PMM statistics:
Total pages: 248742
Free pages : 247219
Used pages : 1523
Total MB : 971
Free MB : 965
Used MB : 5
VMM initialized (mapped RAM, CR3 switched)
VMM initialized (mapped RAM, CR3 switched)
VMM self-test: mapped OK at 0xffff800000000000
VMM self-test complete.
IDT installed.
APIC: init...
APIC: IA32_APIC_BASE MSR=0x00000000fee00900
APIC: stale-ISR drain: 0 EOI(s) issued
APIC: initialized (xAPIC MMIO, TPR=0, SIVR=0x1FF, EOI-clear)
APIC: init done
I/O APIC: init...
I/O APIC: base=0xfec00000, gsi_base=0, overrides=5
override: source=00 gsi=2 flags=0x0000
override: source=05 gsi=5 flags=0x000d
override: source=09 gsi=9 flags=0x000d
override: source=0a gsi=10 flags=0x000d
override: source=0b gsi=11 flags=0x000d
i8042: keyboard ACKed enable-scanning
i8042: IRQ1 enabled in controller config byte
I/O APIC: keyboard IRQ1 routed (masked)
Timer: init...
Timer: init start
Timer: PM_TMR_BLK discovered from FADT at port 1544
Timer: VM mode detected (hypervisor present).
Timer: HPET calibration disabled (VM-exit MMIO would poison timing).
Timer: WARNING: invariant TSC not present under hypervisor.
Timer: continuing in RELATIVE mode (no determinism guarantees).
Timer: RDTSCP not present; using RDTSC (less serialized).
Timer: CPUID frequency unavailable; trying PM Timer...
Timer: trust=1 (0=NONE,1=REL,2=ABS), TSC=1876630930 Hz
Timer: init done
Kernel heap initialized.
Heap statistics:
Total bytes: 536870872
Free bytes: 536870872
Used bytes: 0
Peak bytes: 0
Heap base addr: 24641536
Heap end addr: 561512448
Heartbeat: init...
APIC Timer: calibrating...
APIC Timer: apic_hz=908830414, tick_hz=100, initial_count=9088304
APIC Timer: configured (masked, ready to start)
Heartbeat: init done
Kernel initialization complete.
Boot successful!
StarForth v4: one host node, the F18-derived engine
V4: capsule v4:nucleus-64.f18 signature: missing (unsigned)
PARITY:V4_NUCLEUS name=v4:nucleus-64.f18 capsule_id=0x467b3793e193b467 capsule_hash=0x467b3793e193b467 words=308
V4: capsule v4:forth79.4th signature: missing (unsigned)
PARITY:V4_CAPSULE name=v4:forth79.4th capsule_id=0x4055641ee17d176b capsule_hash=0x4055641ee17d176b dict_hash=0xf268e314e12931c4
PARITY:V4_POST tests=538 pass=538 fail=0
PARITY:V4_SYSTEM word_count=314 dict_hash=0x220ab283a504a3b3
PARITY:OK
POST: PASSED
[HADES][INFO ] [KRELTSC: 0] blk: raw device LBN 2048..3071 (1024 blocks)
PCI: init...
PCI: ECAM mapped (amd64)
virtio-blk: found device
Artemis: virtio-blk attached
[HADES][INFO ] [KRELTSC: 80247384] blk: disk 'StarForth Volume' v2 LBN 3072..789009 (785938 user b
ok> : SQ DUP * ;
ok
ok> 7 SQ . 3 4 U* . .
49 0 12 ok
ok> T{
UNKNOWN WORD: 'T{'
ERROR
ok> RS1
UNKNOWN WORD: 'RS1'
ERROR
ok> COLD
FORTH-79 Cold Start
System initialized.
ok
ok> 3 4 U* . .
0 12 ok
ok> FORGET U*
Protected word
ERROR
ok> 9 KERNEL-WORD ASK9 ASK9
Argument out of range
ERROR
ok> 1 BLOCK C@ . 2047 BLOCK C@ .
0 0 ok
ok> 2100 BLOCK 1024 BLANK 65 2100 BLOCK C! UPDATE SAVE-BUFFERS EMPTY-BUFFERS 2100 BLOCK C@ .
65 ok
ok> 3072 BLOCK C@ .
0 ok
ok> 3072 BLOCK DROP UPDATE SAVE-BUFFERS
Storage refused
ERROR
ok> 9999999 BLOCK
Block out of range
ERROR
ok> HERE .
8300 ok
ok> BYE
BYE: cold restart
@@ -0,0 +1,128 @@
UEFI firmware (version 2025.11-3ubuntu7.3 built at 15:40:26 on Sep 23 2026)
[=3hBdsDxe: failed to load Boot0002 "UEFI Misc Device" from PciRoot(0x0)/Pci(0x2,0x0): Not Found
BdsDxe: failed to load Boot0003 "UEFI QEMU QEMU USB HARDDRIVE 1-0000:00:04.0-1" from PciRoot(0x0)/Pci(0x4,0x0)/USB(0x0,0x0): Not Found
BdsDxe: loading Boot0004 "UEFI Misc Device 2" from PciRoot(0x0)/Pci(0x6,0x0)
BdsDxe: starting Boot0004 "UEFI Misc Device 2" from PciRoot(0x0)/Pci(0x6,0x0)
[=3hStarKernel UEFI Loader
Loading kernel from ESP...
[CKPT 001] Entered efi_main - ConOut live
Collecting boot information...
[CKPT 004] Command line parsed
[CKPT 005] Kernel stack allocation decided
[CKPT 006] Boot info collected (ACPI table located)
[CKPT 007] GOP: linear framebuffer found
[CKPT 008] About to enter ExitBootServices retry loop
_____ _ _ __ _
/ ____| | | |/ / | |
| (___ | |_ __ _ _ __| ' / ___ _ __ _ __ ___| |
\___ \| __/ _` | '__| < / _ \ '__| '_ \ / _ \ |
____) | || (_| | | | . \ __/ | | | | | __/ |
|_____/ \__\__,_|_| |_|\_\___|_| |_| |_|\___|_|
LithosAnanke v2.1.0
Architecture: aarch64
Build: Oct 7 2026 11:28:32
UEFI BootServices: EXITED
=== StarKernel Boot Information ===
Memory map entries: 108
Total memory: 4093 MB
Usable memory: 4054 MB
===================================
PMM initialized.
PMM statistics:
Total pages: 1039356
Free pages : 1037945
Used pages : 1411
Total MB : 4059
Free MB : 4054
Used MB : 5
VMM initialized (mapped RAM, CR3 switched)
VMM initialized (mapped RAM, CR3 switched)
VMM self-test: mapped OK at 0xffff800000000000
VMM self-test complete.
AArch64: running at EL1
IDT installed.
APIC: init...
PSCI: no DTB -- using HVC (QEMU virt-machine default)
GICv2: no DTB GIC node -- using QEMU virt-machine defaults
GICv2: distributor+CPU interface enabled, PPI 30
APIC: init done
Timer: init...
Timer: AArch64 generic timer initialised.
Timer: init done
Kernel heap initialized.
Heap statistics:
Total bytes: 2147483608
Free bytes: 2147483608
Used bytes: 0
Peak bytes: 0
Heap base addr: 1207959552
Heap end addr: 3355443200
Heartbeat: init...
Heartbeat: init done
Kernel initialization complete.
Boot successful!
StarForth v4: one host node, the F18-derived engine
V4: capsule v4:nucleus-64.f18 signature: missing (unsigned)
PARITY:V4_NUCLEUS name=v4:nucleus-64.f18 capsule_id=0x467b3793e193b467 capsule_hash=0x467b3793e193b467 words=308
V4: capsule v4:forth79.4th signature: missing (unsigned)
PARITY:V4_CAPSULE name=v4:forth79.4th capsule_id=0x4055641ee17d176b capsule_hash=0x4055641ee17d176b dict_hash=0xf268e314e12931c4
PARITY:V4_POST tests=538 pass=538 fail=0
PARITY:V4_SYSTEM word_count=314 dict_hash=0x220ab283a504a3b3
PARITY:OK
POST: PASSED
[HADES][INFO ] [KRELTSC: 0] blk: raw device LBN 2048..3071 (1024 blocks)
PCI: init...
virtio-blk: found device
Artemis: virtio-blk attached
[HADES][INFO ] [KRELTSC: 1493527] blk: disk 'StarForth Volume' v2 LBN 3072..789009 (785938 user b
ok> : SQ DUP * ;
ok
ok> 7 SQ . 3 4 U* . .
49 0 12 ok
ok> T{
UNKNOWN WORD: 'T{'
ERROR
ok> RS1
UNKNOWN WORD: 'RS1'
ERROR
ok> COLD
FORTH-79 Cold Start
System initialized.
ok
ok> 3 4 U* . .
0 12 ok
ok> FORGET U*
Protected word
ERROR
ok> 9 KERNEL-WORD ASK9 ASK9
Argument out of range
ERROR
ok> 1 BLOCK C@ . 2047 BLOCK C@ .
0 0 ok
ok> 2100 BLOCK 1024 BLANK 65 2100 BLOCK C! UPDATE SAVE-BUFFERS EMPTY-BUFFERS 2100 BLOCK C@ .
65 ok
ok> 3072 BLOCK C@ .
0 ok
ok> 3072 BLOCK DROP UPDATE SAVE-BUFFERS
Storage refused
ERROR
ok> 9999999 BLOCK
Block out of range
ERROR
ok> HERE .
8300 ok
ok> BYE
BYE: cold restart
@@ -0,0 +1,198 @@
OpenSBI v1.8
____ _____ ____ _____
/ __ \ / ____| _ \_ _|
| | | |_ __ ___ _ __ | (___ | |_) || |
| | | | '_ \ / _ \ '_ \ \___ \| _ < | |
| |__| | |_) | __/ | | |____) | |_) || |_
\____/| .__/ \___|_| |_|_____/|____/_____|
| |
|_|
Platform Name : riscv-virtio,qemu
Platform Features : medeleg
Platform HART Count : 1
Platform HART Protection : pmp
Platform IPI Device : aclint-mswi
Platform Timer Device : aclint-mtimer @ 10000000Hz
Platform Console Device : uart8250
Platform HSM Device : ---
Platform PMU Device : ---
Platform Reboot Device : syscon-reboot
Platform Shutdown Device : syscon-poweroff
Platform Suspend Device : ---
Platform CPPC Device : ---
Firmware Base : 0x80000000
Firmware Size : 321 KB
Firmware RW Offset : 0x40000
Firmware RW Size : 65 KB
Firmware Heap Offset : 0x47000
Firmware Heap Size : 37 KB (total), 0 KB (reserved), 12 KB (used), 23 KB (free)
Firmware Scratch Size : 4096 B (total), 1464 B (used), 2632 B (free)
Runtime SBI Version : 3.0
Standard SBI Extensions : ipi,pmu,srst,sse,hsm,rfnc,fwft,time,base,legacy,dbcn,dbtr
Experimental SBI Extensions : none
Domain0 Name : root
Domain0 Boot HART : 0
Domain0 HARTs : 0*
Domain0 Region00 : 0x0000000080040000-0x000000008005ffff M: (F,R,W) S/U: ()
Domain0 Region01 : 0x0000000080000000-0x000000008003ffff M: (F,R,X) S/U: ()
Domain0 Region02 : 0x0000000000100000-0x0000000000100fff M: (I,R,W) S/U: (R,W)
Domain0 Region03 : 0x0000000010000000-0x0000000010000fff M: (I,R,W) S/U: (R,W)
Domain0 Region04 : 0x0000000002000000-0x000000000200ffff M: (I,R,W) S/U: ()
Domain0 Region05 : 0x000000000c400000-0x000000000c5fffff M: (I,R,W) S/U: (R,W)
Domain0 Region06 : 0x000000000c000000-0x000000000c3fffff M: (I,R,W) S/U: (R,W)
Domain0 Region07 : 0x0000000000000000-0xffffffffffffffff M: () S/U: (R,W,X)
Domain0 Next Address : 0x0000000020000000
Domain0 Next Arg1 : 0x00000000bfe00000
Domain0 Next Mode : S-mode
Domain0 SysReset : yes
Domain0 SysSuspend : yes
Boot HART ID : 0
Boot HART Domain : root
Boot HART Priv Version : v1.12
Boot HART Base ISA : rv64imafdch
Boot HART ISA Extensions : sstc,zicntr,zihpm,zicboz,zicbom,sdtrig,svadu
Boot HART PMP Count : 16
Boot HART PMP Granularity : 2 bits
Boot HART PMP Address Bits : 54
Boot HART MHPM Info : 16 (0x0007fff8)
Boot HART Debug Triggers : 2 triggers
Boot HART MIDELEG : 0x0000000000001666
Boot HART MEDELEG : 0x0000000000f4b509
[=3hRISC-V EDK2 firmware version 2025.11-3ubuntu7.3
Press ESCAPE within 5 seconds for boot options ERROR: C40000002:V03051002 I0 6D33944A-EC75-4855-A54D-809C75241F6C 83FFF850
BdsDxe: failed to load Boot0001 "UEFI Misc Device" fr
om PciRoot(0x0)/Pci(0x1,0x0): Not Found
[=3hStarKernel UEFI Loader
Loading kernel from ESP...
[CKPT 001] Entered efi_main - ConOut live
Monolithic build - kernel linked directly
Collecting boot information...
CmdLine: parsed OK
[CKPT 004] Command line parsed
[CKPT 005] Kernel stack allocation decided
[CKPT 006] Boot info collected (ACPI table located)
GOP: linear framebuffer found
[CKPT 007] GOP: linear framebuffer found
[CKPT 008] About to enter ExitBootServices retry loop
Calling kernel_main (monolithic)...
riscv64 item 4.3.5a: satp state at kernel entry (before switch)
satp.MODE = 0x000000000000000a
satp.PPN = 0x00000000000bf868
__kernel_start = 0x00000000bdca29f8
riscv64: satp cleared -- Bare mode, explicit (item 4.3.5a)
_____ _ _ __ _
/ ____| | | |/ / | |
| (___ | |_ __ _ _ __| ' / ___ _ __ _ __ ___| |
\___ \| __/ _` | '__| < / _ \ '__| '_ \ / _ \ |
____) | || (_| | | | . \ __/ | | | | | __/ |
|_____/ \__\__,_|_| |_|\_\___|_| |_| |_|\___|_|
LithosAnanke v2.1.0
Architecture: riscv64
Build: Oct 7 2026 11:31:39
UEFI BootServices: EXITED
=== StarKernel Boot Information ===
Memory map entries: 100
Total memory: 1020 MB
Usable memory: 975 MB
===================================
PMM initialized.
PMM statistics:
Total pages: 250273
Free pages : 249621
Used pages : 652
Total MB : 977
Free MB : 975
Used MB : 2
VMM initialized (mapped RAM, CR3 switched)
VMM initialized (mapped RAM, CR3 switched)
VMM self-test: mapped OK at 0xffff800000000000
VMM self-test complete.
IDT installed.
APIC: init...
PLIC: no DTB PLIC node -- using QEMU virt-machine default (base=0x0c000000)
PLIC: init (S-mode context 1, threshold=0)
APIC: init done
Timer: init...
Timer: RISC-V time CSR @ 10000000 Hz (FALLBACK, no devicetree)
Timer: init done
Kernel heap initialized.
Heap statistics:
Total bytes: 536870872
Free bytes: 536870872
Used bytes: 0
Peak bytes: 0
Heap base addr: 2214588416
Heap end addr: 2751459328
Heartbeat: init...
Heartbeat: init done
Kernel initialization complete.
Boot successful!
StarForth v4: one host node, the F18-derived engine
V4: capsule v4:nucleus-64.f18 signature: missing (unsigned)
PARITY:V4_NUCLEUS name=v4:nucleus-64.f18 capsule_id=0x467b3793e193b467 capsule_hash=0x467b3793e193b467 words=308
V4: capsule v4:forth79.4th signature: missing (unsigned)
PARITY:V4_CAPSULE name=v4:forth79.4th capsule_id=0x4055641ee17d176b capsule_hash=0x4055641ee17d176b dict_hash=0xf268e314e12931c4
PARITY:V4_POST tests=538 pass=538 fail=0
PARITY:V4_SYSTEM word_count=314 dict_hash=0x220ab283a504a3b3
PARITY:OK
POST: PASSED
[HADES][INFO ] [KRELTSC: 0] blk: raw device LBN 2048..3071 (1024 blocks)
PCI: init...
virtio-blk: found device
Artemis: virtio-blk attached
[HADES][INFO ] [KRELTSC: 24420207] blk: disk 'StarForth Volume' v2 LBN 3072..789009 (785938 user b
ok> : SQ DUP * ;
ok
ok> 7 SQ . 3 4 U* . .
49 0 12 ok
ok> T{
UNKNOWN WORD: 'T{'
ERROR
ok> RS1
UNKNOWN WORD: 'RS1'
ERROR
ok> COLD
FORTH-79 Cold Start
System initialized.
ok
ok> 3 4 U* . .
0 12 ok
ok> FORGET U*
Protected word
ERROR
ok> 9 KERNEL-WORD ASK9 ASK9
Argument out of range
ERROR
ok> 1 BLOCK C@ . 2047 BLOCK C@ .
0 0 ok
ok> 2100 BLOCK 1024 BLANK 65 2100 BLOCK C! UPDATE SAVE-BUFFERS EMPTY-BUFFERS 2100 BLOCK C@ .
65 ok
ok> 3072 BLOCK C@ .
0 ok
ok> 3072 BLOCK DROP UPDATE SAVE-BUFFERS
Storage refused
ERROR
ok> 9999999 BLOCK
Block out of range
ERROR
ok> HERE .
8300 ok
ok> BYE
BYE: cold restart
+20 -4
View File
@@ -27,7 +27,7 @@ CFLAGS ?= $(CSTD) $(WARN) $(OPT)
HERE := $(patsubst %/,%,$(dir $(abspath $(lastword $(MAKEFILE_LIST)))))
SRCS := $(wildcard $(HERE)/src/*.c)
TESTS := $(wildcard $(HERE)/tests/*.c)
TESTS := $(wildcard $(HERE)/tests/test_*.c)
# Cell widths to build and verify. 32 is the F18/Zynq case, 64 the aarch64
# host case; see DECOMPOSITION.md D-5.
@@ -183,10 +183,11 @@ post79:
# PARITY:OK, POST: PASSED and the prompt: the same hashes on every ISA. It
# also checks that what the boot loaded is part of the system: after COLD
# the capsule's words and the kernel's are still there, and FORGET refuses
# them.
# them; that POST has left nothing of itself or of what its cases defined;
# and that a boot whose POST has a failing case fails.
.PHONY: hosted hosted-check
hosted: $(foreach i,$(HOSTED_ISAS),$(BINDIR)/starforth4-$(i))
hosted-check: $(foreach i,$(HOSTED_ISAS),$(BINDIR)/boot-$(i).txt)
hosted-check: $(foreach i,$(HOSTED_ISAS),$(BINDIR)/boot-$(i).txt) $(BINDIR)/starforth4-postfail
@grep -q '^POST: PASSED$$' $(BINDIR)/boot-amd64.txt || { echo "hosted-check: no POST: PASSED"; exit 1; }
@cmp $(BINDIR)/boot-amd64.txt $(BINDIR)/boot-aarch64.txt
@cmp $(BINDIR)/boot-amd64.txt $(BINDIR)/boot-riscv64.txt
@@ -194,7 +195,22 @@ hosted-check: $(foreach i,$(HOSTED_ISAS),$(BINDIR)/boot-$(i).txt)
@grep -q '^ok> 0 12 ok$$' $(BINDIR)/cold-amd64.txt || { echo "hosted-check: COLD lost the capsule's words"; cat $(BINDIR)/cold-amd64.txt; exit 1; }
@grep -q '^ok> Protected word$$' $(BINDIR)/cold-amd64.txt || { echo "hosted-check: a capsule word could be forgotten"; exit 1; }
@grep -q '^ok> Goodbye!$$' $(BINDIR)/cold-amd64.txt || { echo "hosted-check: COLD lost BYE"; exit 1; }
@echo "hosted-check: amd64, aarch64 and riscv64 boot identically"
@printf 'RS1\nT{\nWORDS\n' | $(BINDIR)/starforth4-amd64 > $(BINDIR)/after-post-amd64.txt
@grep -q "^ok> UNKNOWN WORD: 'RS1'$$" $(BINDIR)/after-post-amd64.txt || { echo "hosted-check: a word a POST case defined is still there"; exit 1; }
@grep -q "^ok> UNKNOWN WORD: 'T{'$$" $(BINDIR)/after-post-amd64.txt || { echo "hosted-check: POST's harness is on the node"; exit 1; }
@$(BINDIR)/starforth4-postfail < /dev/null > $(BINDIR)/postfail.txt; test $$? -ne 0 || { echo "hosted-check: a boot with a failing case did not fail"; exit 1; }
@grep -q '^POST FAIL: fail.wrong out<5 5 $$' $(BINDIR)/postfail.txt || { echo "hosted-check: the failing case was not named"; cat $(BINDIR)/postfail.txt; exit 1; }
@grep -q '^POST FAIL: fail.many out<QQQQ' $(BINDIR)/postfail.txt || { echo "hosted-check: the case that prints too much was not named"; exit 1; }
@grep -q '^PARITY:V4_POST tests=4 pass=2 fail=2$$' $(BINDIR)/postfail.txt || { echo "hosted-check: the tally is wrong"; cat $(BINDIR)/postfail.txt; exit 1; }
@grep -q '^POST: FAILED$$' $(BINDIR)/postfail.txt && grep -q '^PARITY:FAIL$$' $(BINDIR)/postfail.txt || { echo "hosted-check: no PARITY:FAIL, POST: FAILED"; exit 1; }
@! grep -q '^ok> \|^5 5 $$\|PARITY:OK\|PARITY:V4_SYSTEM' $(BINDIR)/postfail.txt || { echo "hosted-check: a failed boot gave a prompt, or showed a case's printing"; exit 1; }
@echo "hosted-check: amd64, aarch64 and riscv64 boot identically; a boot with a failing case fails"
# A hosted program whose POST has a case that fails (tests/post_cases_fail.c
# in the place of system/post_cases.c): hosted-check boots it and requires
# that the boot stops there. docs/v4.0.0/MESH.md step 6b, acceptance 4.
$(BINDIR)/starforth4-postfail: $(BINDIR)/starforth4-amd64 $(HERE)/tests/post_cases_fail.c
$(CC) $(SYSTEM_CFLAGS) -static $(BINDIR)/hosted-amd64.o $(BINDIR)/v4_image_64.c $(CAPSULE_DIR_C) $(ENGINE_SRCS) $(filter-out %/post_cases.c,$(SYSTEM_SRCS)) $(HERE)/tests/post_cases_fail.c $(BINDIR)/v3o-amd64/*.o -o $@
.PHONY: all test sanitize clean $(addprefix test-,$(WIDTHS))
+9 -5
View File
@@ -62,7 +62,7 @@ load `v4:forth79.4th`, pass POST and reach `ok>`, with the same lines:
PARITY:V4_NUCLEUS name=v4:nucleus-64.f18 capsule_id=... capsule_hash=0x97a655081b2af559 words=298
PARITY:V4_CAPSULE name=v4:forth79.4th capsule_id=... dict_hash=...
PARITY:V4_POST tests=538 pass=538 fail=0
PARITY:V4_CAPSULE name=v4:post79.4th capsule_id=... dict_hash=...
PARITY:V4_SYSTEM word_count=314 dict_hash=...
PARITY:OK
POST: PASSED
ok>
@@ -174,10 +174,14 @@ and the v3 cases left out, are listed with reasons in
The runner, `v4/system/post.c`, feeds each case to the node a line at a
time, keeps what the node prints, reads its data stack from outside, and
judges: an error exactly if one is expected, and otherwise the stack and
every character printed. Nothing of POST is in the node's dictionary. What
the cases define stays there, as in v3, and the system is sealed after
POST. The boot then prints `PARITY:V4_SYSTEM word_count=N dict_hash=0x...`,
and passes only if no case failed (`v4/system/boot.c`).
every character printed. Nothing of POST is in the node's dictionary, and
POST leaves nothing: the system is sealed before it, and afterwards the
kernel puts the node back to the system as sealed, as v3 puts the
dictionary back after each of its suites. The boot then prints
`PARITY:V4_SYSTEM word_count=N dict_hash=0x...`, and passes only if no
case failed (`v4/system/boot.c`). A case the node does not come back from
ends POST there, named. `make -C v4 hosted-check` also boots a program
whose POST has failing cases and requires that the boot fails.
Not tested: `KEY`, `EXPECT`, `QUERY` (the keyboard) and `QUIT` (it returns
without ` ok`).
+1 -1
View File
@@ -5,7 +5,7 @@
\ written here as text for the text assembler (v4/include/v4/text.h).
\
\ Constants the loader supplies: N-1 (cell bits - 1), NODE-ERROR, CONSOLE-TX,
\ CONSOLE-RX, CONSOLE-STATUS, BASE, (EMIT-HOOK), (MSG), (REPLY), (ME), (OUT),
\ CONSOLE-RX, CONSOLE-STATUS, BASE, (MSG), (REPLY), (ME), (OUT),
\ (OUT^), (CONSOLE), (ROUTES), (ROUTE#), (ROUTE-DEFAULT), (PRINT-TO),
\ (PRINT-PORT).
\
+2 -2
View File
@@ -7,8 +7,8 @@
*
* PARITY:V4_NUCLEUS name=v4:nucleus-64.f18 capsule_id=0x... capsule_hash=0x... words=N
* PARITY:V4_CAPSULE name=v4:forth79.4th capsule_id=0x... capsule_hash=0x... dict_hash=0x...
* PARITY:V4_POST tests=N pass=N fail=N (printed by the POST capsule)
* PARITY:V4_CAPSULE name=v4:post79.4th capsule_id=0x... capsule_hash=0x... dict_hash=0x...
* PARITY:V4_POST tests=N pass=N fail=N (POST is the kernel's: v4/post.h)
* PARITY:V4_SYSTEM word_count=N dict_hash=0x... (the system as sealed, after POST)
* PARITY:OK
* POST: PASSED
*
+10 -3
View File
@@ -37,7 +37,14 @@ extern const unsigned v4_post_case_count;
* of it; and judges. A case passes when it ended in an error exactly if
* one was expected and, if none was, its stack and its printing are what
* the table has. It has ended in an error if any of its lines did. What
* the cases define stays in the node's dictionary, as in v3. */
* the cases define is still in the node's dictionary when the runner
* returns: whoever runs POST puts the dictionary back afterwards, as v3
* does after each of its suites (v3/src/test_runner/test_common.c,
* run_test_suite: "to remove test-created words").
*
* If the node does not come back from a line -- it has stopped, or runs for
* ever -- that case fails and POST ends there: the runner says which case
* it was and how many were not run. */
#define V4_POST_OUT 1024u /* the most of a case's printing that is kept */
typedef struct {
@@ -54,8 +61,8 @@ typedef struct {
typedef struct { unsigned tests, pass, fail; } v4_post_tally;
/* Run the cases. Prints "POST FAIL: name out<...> stack<...>" for each
* failing case and then "PARITY:V4_POST tests=N pass=N fail=N". Returns 1
* if none failed. */
* failing case and then "PARITY:V4_POST tests=N pass=N fail=N", where tests
* is how many were run. Returns 1 if every case was run and none failed. */
int v4_post_run(const v4_post_host *h, const v4_post_case *cases, unsigned count, v4_post_tally *tally);
#endif /* V4_POST_H */
+21 -6
View File
@@ -19,8 +19,9 @@ static const char *const boot_capsules[] = {
};
/* POST is part of the boot, and is the kernel's (v4/include/v4/post.h;
* docs/v4.0.0/NUCLEUS.md 6.3): when the capsules are in, the kernel feeds
* its cases to the node and judges them, and the boot passes only if none
* docs/v4.0.0/NUCLEUS.md 6.3): when the capsules are in and the system is
* sealed, the kernel feeds its cases to the node and judges them, puts the
* node back to the system as sealed, and the boot passes only if none
* failed. -DV4_POST_AT_BOOT=0 leaves it out, for work on a vocabulary
* that does not pass yet. */
#ifndef V4_POST_AT_BOOT
@@ -367,22 +368,36 @@ int v4_boot_run(const v4_boot *b)
for (i = 0; i < sizeof boot_capsules / sizeof boot_capsules[0]; i++)
if (!load_capsule(b, boot_capsules[i])) { say(b, "PARITY:FAIL\nPOST: FAILED\n"); return 0; }
/* The kernel's words and the capsules are the system: COLD comes back
* to here, and FORGET will not go below it. */
v4_image_seal(b->n, b->im);
#if V4_POST_AT_BOOT
{
static const char cold[] = "COLD";
v4_post_host host;
v4_post_tally tally;
unsigned printed = 0;
int how;
host.self = (void *)b; host.n = b->n; host.line = post_line; host.say = post_say;
if (!v4_post_run(&host, v4_post_cases, v4_post_case_count, &tally)) {
say(b, "V4: POST reported failures\nPARITY:FAIL\nPOST: FAILED\n");
return 0;
}
/* POST leaves nothing: the node is put back to the system as it was
* sealed, as v3 puts the dictionary back after each of its suites
* (v3/src/test_runner/test_common.c, run_test_suite). What COLD
* prints is not shown. */
v4_dstack_reset(&b->n->ds);
how = run_line(b, cold, (unsigned)sizeof cold - 1u, (char *)cold, 0u, &printed);
if (how != V4_TEXT_COMPLETED && how != V4_TEXT_QUIT) {
say(b, "V4: the node did not come back to the system after POST\nPARITY:FAIL\nPOST: FAILED\n");
return 0;
}
}
#endif
/* The kernel's words, the capsules and what POST's cases defined are
* the system, as in v3: COLD comes back to here, and FORGET will not go
* below it. */
v4_image_seal(b->n, b->im);
say(b, "PARITY:V4_SYSTEM word_count="); say_dec(b, word_count(b->n, b->im));
say(b, " dict_hash="); say_hex(b, v4_boot_dict_hash(b->n, b->im));
say(b, "\n");
+12 -2
View File
@@ -44,18 +44,19 @@ int v4_post_run(const v4_post_host *h, const v4_post_case *cases, unsigned count
for (i = 0; i < count; i++) {
const v4_post_case *c = &cases[i];
unsigned kept = 0, total = 0, len = 0, depth;
int errored = 0, came_back = 1, ok, how;
int errored = 0, came_back = 1, lost = 0, ok, how;
/* every case starts from the same state */
v4_dstack_reset(&h->n->ds);
how = h->line(h->self, state_line, (unsigned)sizeof state_line - 1u, out, 0u, &len);
if (how < 0) lost = 1;
if (how != V4_TEXT_COMPLETED) came_back = 0;
v4_dstack_reset(&h->n->ds);
for (k = 0; came_back && k < c->line_count; k++) {
len = 0;
how = h->line(h->self, c->lines[k], length(c->lines[k]), out + kept, V4_POST_OUT - kept, &len);
if (how < 0) { came_back = 0; break; }
if (how < 0) { came_back = 0; lost = 1; break; }
if (how == V4_TEXT_ERROR) errored = 1;
total += len;
kept = total < V4_POST_OUT ? total : V4_POST_OUT;
@@ -95,6 +96,15 @@ int v4_post_run(const v4_post_host *h, const v4_post_case *cases, unsigned count
say(h, "> stack<");
for (k = depth < SHOWN_STACK ? depth : SHOWN_STACK; k-- > 0; ) { say_number(h, (long long)left[k]); say(h, " "); }
say(h, ">\n");
/* The node did not come back from a line: it is stopped, or will
* run for ever. Nothing more can be asked of it, so POST ends
* here and says which case it was. */
if (lost) {
say(h, "POST: the node did not come back from "); say(h, c->name);
say(h, "; "); say_number(h, (long long)(count - i - 1u)); say(h, " not run\n");
break;
}
}
say(h, "PARITY:V4_POST tests="); say_number(h, (long long)tally->tests);
say(h, " pass="); say_number(h, (long long)tally->pass);
+24
View File
@@ -0,0 +1,24 @@
/* post_cases_fail.c -- a table of cases for the boot to fail on.
* docs/v4.0.0/MESH.md step 6b, acceptance 4; v4/Makefile, hosted-check.
*
* Linked into a hosted program in the place of v4/system/post_cases.c, so
* that the boot itself (v4/system/boot.c) is seen to stop on a failing
* case, to keep what a case prints off the console, and to hold no more of
* it than it has room for. It is not a test program of its own: the suite
* does not build it.
*/
#include "v4/post.h"
static const char *const l_right[] = { "5 DUP . . CR" };
static const char *const l_wrong[] = { "5 DUP . . CR" };
static const char *const l_many[] = { ": MANY 2000 0 DO 81 EMIT LOOP ;", "MANY" };
static const char *const l_two[] = { "65 EMIT", "66 EMIT" };
const v4_post_case v4_post_cases[] = {
{ "fail.right", l_right, 1u, V4_POST_STACK, 0, 0u, "5 5 \012", 5u },
{ "fail.wrong", l_wrong, 1u, V4_POST_STACK, 0, 0u, "5 6 \012", 5u },
{ "fail.many", l_many, 2u, V4_POST_STACK, 0, 0u, "Q", 1u },
{ "fail.twoline", l_two, 2u, V4_POST_STACK, 0, 0u, "AB", 2u },
};
const unsigned v4_post_case_count = 4u;
+23 -15
View File
@@ -361,10 +361,11 @@ static const char *say(const char *input)
}
/* POST's RUNNER (v4/system/post.c), with these tests as its host: a line is
* sent to the node as the console sends one, and what the node prints is
* handed back and not shown. `post_lost` is the text of a line that is
* never to come back, and `post_state_fails` makes the line that sets the
* state end in an error; `post_said` is what the runner printed. */
static const char *post_lost;
* handed back and not shown. `post_step_limit` is how long a line may
* take before the node is given up on, and `post_state_fails` makes the
* line that sets the state end in an error; `post_said` is what the runner
* printed. */
static long post_step_limit = 40000000;
static int post_state_fails;
static char post_said[4096];
static unsigned post_said_len;
@@ -373,12 +374,11 @@ static int post_line(void *self, const char *text, unsigned text_len, char *o, u
int ended;
(void)self;
*len = 0;
if (post_lost && strlen(post_lost) == text_len && memcmp(post_lost, text, text_len) == 0) return -1;
if (post_state_fails && text_len == 25 && memcmp(text, "DECIMAL FORTH DEFINITIONS", 25) == 0) text = "NOSUCHWORD-FOR-STATE ";
if (!v4_message_text(&to_node, 0, 1, V4_MSG_TEXT, text, text_len)) return -1;
to_sent = 0; from_node.count = 0;
shown_len = 0; shown_dropped = 0;
ended = run_line(40000000);
ended = run_line(post_step_limit);
if (ended != 1) return -1;
*len = shown_dropped ? (unsigned)sizeof shown + 1u : shown_len;
memcpy(o, shown, shown_len < cap ? shown_len : cap);
@@ -1259,22 +1259,30 @@ int main(void)
CHECK(post_one("many", "MANY", 0, V4_POST_STACK, 0, 0, big) == 0 && strstr(post_said, "POST FAIL: many ") != NULL, "a case that prints more than the runner keeps fails, by name");
CHECK(post_one("after.many", "1 2 +", 0, V4_POST_STACK, three, 1, "") == 1, "and the next case is judged as usual");
/* a line that never comes back */
post_lost = "LOST-LINE";
/* output on more than one line of a case */
CHECK(post_one("two.out", "65 EMIT", "66 EMIT", V4_POST_STACK, 0, 0, "AB") == 1 && post_one("two.out2", "65 EMIT", "66 EMIT", V4_POST_STACK, 0, 0, "AA") == 0,
"what a case prints on its second line follows what it printed on its first");
/* a case the node does not come back from: POST stops there */
CHECK(is(say(": SPIN BEGIN 0 UNTIL ;\n"), " ok\nok> "), "a word that never ends");
{
static const char *const la[] = { "1 2 +" }, *const lb[] = { "LOST-LINE" }, *const lc[] = { "65 EMIT" };
static const char *const la[] = { "1 2 +" }, *const lb[] = { "SPIN" }, *const lc[] = { "65 EMIT" };
static const v4_post_case three_cases[] = {
{ "first", la, 1u, V4_POST_STACK, three, 1u, "", 0u },
{ "lost", lb, 1u, V4_POST_STACK, 0, 0u, "", 0u },
{ "last", lc, 1u, V4_POST_STACK, 0, 0u, "A", 1u },
{ "spins", lb, 1u, V4_POST_STACK, 0, 0u, "", 0u },
{ "never.run", lc, 1u, V4_POST_STACK, 0, 0u, "A", 1u },
};
v4_post_tally t;
post_said_len = 0; post_said[0] = 0;
CHECK(v4_post_run(&post_host, three_cases, 3, &t) == 0 && t.tests == 3 && t.pass == 2 && t.fail == 1
&& strstr(post_said, "POST FAIL: lost ") != NULL && strstr(post_said, "PARITY:V4_POST tests=3 pass=2 fail=1\n") != NULL,
"a line that does not come back fails its case; the others are still judged, and the run is not a pass: \"%s\"", post_said);
post_step_limit = 2000000;
CHECK(v4_post_run(&post_host, three_cases, 3, &t) == 0 && t.tests == 2 && t.pass == 1 && t.fail == 1,
"the run is not a pass, and the case after it is not run: %u run, %u passed, %u failed", t.tests, t.pass, t.fail);
CHECK(strstr(post_said, "POST FAIL: spins ") != NULL && strstr(post_said, "POST: the node did not come back from spins; 1 not run\n") != NULL
&& strstr(post_said, "never.run") == NULL && strstr(post_said, "PARITY:V4_POST tests=2 pass=1 fail=1\n") != NULL,
"it is named as the case the node did not come back from, with how many were not run: \"%s\"", post_said);
post_step_limit = 40000000;
}
post_lost = 0;
boot(); /* the node was left spinning */
}
/* ---- nothing of POST is on the node (NUCLEUS.md 6.3) ---- */
+17 -4
View File
@@ -344,7 +344,7 @@ int main(void)
printf("v4 unit tests: V4_CELL_BITS=%d, V4_NODE_WORDS=%u\n", V4_CELL_BITS, (unsigned)V4_NODE_WORDS);
if (V4_CELL_BITS != 64) {
/* The capsules the unit is built from are the 64-bit products': the
* expected results in post79.4th are v3's, on 64-bit cells, and the
* expected results in POST's table are v3's, on 64-bit cells, and the
* nucleus capsule is nucleus-64. POST has never been run on 32-bit
* cells (docs/v4.0.0/MESH.md, step 5). */
printf(" not run at this width: the capsules are the 64-bit products'\n");
@@ -400,16 +400,30 @@ int main(void)
}
CHECK(strcmp(tell(10, "NODE-ME ."), "0 ") == 0 && refused == 0, "it asks where it is, and is answered");
CHECK(load(10, "forth79.4th") == 0, "it takes in FORTH-79");
CHECK(told(10, "(SEAL)"), "the nucleus and FORTH-79 are the system POST is run on");
{
static v4_cell before[V4_NODE_WORDS];
v4_post_host host;
v4_post_tally tally;
host.self = 0; host.n = node_numbered(10); host.line = post_line; host.say = post_say;
v4_node *hera = node_numbered(10);
v4_cell here = hera->mem[DP] / 4, k, changed = 0, first = -1;
uint64_t hash = v4_image_dict_hash(hera, &im);
memcpy(before, hera->mem, sizeof before);
host.self = 0; host.n = hera; host.line = post_line; host.say = post_say;
CHECK(v4_post_run(&host, v4_post_cases, v4_post_case_count, &tally) && tally.tests == 538 && tally.pass == 538 && tally.fail == 0
&& strstr(post_said, "PARITY:V4_POST tests=538 pass=538 fail=0\n") != NULL && strstr(post_said, "POST FAIL") == NULL,
"and passes POST, which the kernel runs on her: %u of %u, %u failed; \"%s\"", tally.pass, tally.tests, tally.fail, post_said);
CHECK(strcmp(tell(10, "RS1"), "42 42 \n") == 0, "while POST runs, what its cases define is on her: \"%s\"", printed);
CHECK(strstr(tell(10, "COLD"), "Cold Start") != NULL, "the kernel puts her back to the system as it was sealed");
CHECK(hera->mem[DP] == before[DP] && hera->mem[LATEST] == before[LATEST], "HERE and LATEST are where they were before POST");
for (k = 0; k < here; k++) if (hera->mem[k] != before[k]) { if (first < 0) first = k; changed++; }
/* What differs is the TTL in the entry of each word POST had interpreted: a count of uses left before
* the word's access is checked again, which every use counts down (compile.v4, (ACL?)), as in v3. */
printf(" after POST and COLD: %ld of the %ld cells below HERE differ from before POST (the first at %ld); dict_hash %s\n",
(long)changed, (long)here, (long)first, v4_image_dict_hash(hera, &im) == hash ? "the same" : "differs");
}
CHECK(strstr(tell(10, "T{"), "UNKNOWN WORD") != NULL, "nothing of POST's harness is on her: \"%s\"", printed);
CHECK(strcmp(tell(10, "RS1"), "42 42 \n") == 0, "what POST's cases defined is: \"%s\"", printed);
CHECK(strstr(tell(10, "RS1"), "UNKNOWN WORD") != NULL && strstr(tell(10, "ZERO"), "UNKNOWN WORD") != NULL, "nor anything POST's cases defined: POST leaves nothing, as in v3: \"%s\"", printed);
CHECK(load(10, "hera.4th") == 0, "and its own capsule, which makes it Hera");
CHECK(told(10, "(SEAL)"), "that is the system it comes back to");
@@ -423,7 +437,6 @@ int main(void)
CHECK(post_passed[10] == 0 && post_passed[11] == 0 && post_passed[12] == 0 && post_passed[13] == 0 && post_passed[14] == 0 && post_other == 0,
"a node she births is not POSTed, and no node prints a POST tally: POST is the kernel's, once, on Hera: %u %u %u %u %u, %u failed",
post_passed[10], post_passed[11], post_passed[12], post_passed[13], post_passed[14], post_other);
CHECK(strstr(tell(10, "COLD"), "Cold Start") != NULL && strcmp(tell(10, "RS1"), "42 42 \n") == 0, "COLD on Hera comes back to a system that has what POST's cases defined: \"%s\"", printed);
CHECK(parity_count == 4 && parity_number[0] == 11 && parity_number[1] == 12 && parity_number[2] == 13 && parity_number[3] == 14, "the parity of each was recorded: %u", parity_count);
CHECK(parity_hash[0] == parity_hash[1] && parity_hash[1] == parity_hash[2] && parity_hash[2] == parity_hash[3],
"and their dictionary hashes are the same: %016llx %016llx %016llx %016llx",