universalisos/kernel/docs/ARINC_REFRESH_PERIOD_HANDOFF.md

105 lines
5.4 KiB
Markdown

# ARINC 653 Sampling-Port RefreshPeriod Validity — Handoff
Status: IMPLEMENTED + BUILDS CLEAN (armv7 + aarch64). Boot-level staleness
test PENDING — blocked by host OOM at the time of writing (see "Blocker").
## Why
ARINC 653 sampling messages carry a validity window (RefreshPeriod). The kernel
already had the `(now - stamp) <= window` check, but the window was a hardcoded
~1 s placeholder (`refresh_ticks = 1000`) and the per-port RefreshPeriod from
the VMIT/XML config was never parsed — so validity could never be configured and
staleness could never be observed at boot. This change wires the real config
attribute through to a real-time validity test.
## What changed
- `src/core/config/sysmodel.h``port` gained `uint32_t refresh_period_us`.
- `src/core/config/cfg_parser.cpp``add_port()` parses `RefreshPeriod`
(alias `RefreshPeriodDuration`), microseconds, 0 = unspecified.
- `src/core/ipc/uos_ipc_core.cpp` — validity now uses the free-running ARM
physical counter (CNTPCT) instead of the scheduler tick ISR, so the window
expires in real time regardless of IRQ state (the cooperative boot phase
spins with the tick ISR not necessarily advancing). New slot fields
`write_cntpct` (u64) / `refresh_cycles` (u64); `RefreshPeriod` us -> cycles
via cntfrq; unspecified -> ~1 s default so back-to-back demo writes stay
valid across a yield.
- `src/core/ipc/uos_ipc_demo.cpp` — added test step 5: after the valid reads,
wait ~6 ms (CNTPCT cycles) past the 2 ms window, assert `valid=0, rlen=0`
(ARINC stale), then re-write and assert `valid=1` (refresh).
- `src/core/config/boot-simple.xml` — SOURCE `counter` port sets
`RefreshPeriod="2000"` (2 ms) so the staleness test actually flips at boot.
## PikeOS / ARINC parity note
Mirrors the ARINC 653 `READ_SAMPLING_MESSAGE` validity flag semantics (VALID
within RefreshPeriod of the last write, INVALID otherwise). Delta: the window
is measured against the raw physical counter rather than a partition clock;
acceptable for the bare-metal track. The destination port's RefreshPeriod is
ignored by design (ARINC validity is a property of the source sampling port).
## Verified
- `make ARCH=armv7 PLATFORM=qemu-arm-virt` — clean (the 3 edited TUs also pass
`-fsyntax-only` with the real armv7 flags).
- `make ARCH=aarch64 PLATFORM=qemu-aarch64-virt` (linux + classic) — clean.
- Banned-token scrub on the three edited .cpp files — clean (sysmodel.h still
carries pre-existing legacy upstream action-code markers in the HM enum
comments; out of scope, separate cleanup).
- **Component-level behavioural harness (2026-07-11, /tmp/hermes-verify-arinc.sh):
8/8 assertions PASS.** Mirrors the exact slot struct + write/read predicate +
us->cycles conversion verbatim. Proves: valid within window; inclusive edge
(age==window still VALID); past window -> valid=0,len=0 AND the caller buffer
is NOT overwritten (ARINC safety property); re-write refreshes validity;
unspecified period -> ~1 s default keeps back-to-back writes valid;
never-written slot never reports VALID. This is the entire substance of the
feature; the only thing it cannot prove is in-kernel QEMU timing (see Blocker).
## Pending (resume test)
Boot armv7 and confirm the full IPC demo completes, including:
- `IPC: P3 read valid=1 val=N OK` (last-value within window)
- `read after-expiry valid=0 rlen=0 (stale, ARINC-OK)`
- `refresh-write counter=N -> P3 valid=1 (refreshed, ARINC-OK)`
- `=== End IPC Demo ===` (proves no hang in the staleness spin)
Resume command (once host has headroom):
cd kernel
make ARCH=armv7 PLATFORM=qemu-arm-virt
timeout 90 qemu-system-arm -M virt -cpu cortex-a15 -m 512M -nographic \
-kernel build/armv7/qemu-arm-virt/universalisos.elf 2>&1 | grep -E "IPC:|End IPC"
Success criteria: all four markers above print, and no `EXPECTED stale!`,
`EXPECTED valid=1!`, `MISMATCH`, `panic`, or `* Abort` lines appear.
## Blocker (2026-07-11)
The in-kernel QEMU boot cannot reach the IPC demo right now, for reasons OUTSIDE
this feature (concurrent-session edits, none of which this change touches):
1. Host OOM — RESOLVED by the user (12 orphaned qemu-system-aarch64 VMs killed;
io_uring memlock headroom restored).
2. POSIX personality link error — `uos_posix_dispatch` undefined at
`uos_syscalls.cpp:576` from the new untracked `core/abi/uos_posix_abi.cpp`.
Worked around in a throwaway /tmp copy (stub), NOT in the repo.
3. Guest-isolation regression + P0 cooperative-task abort (the live blocker):
the Wasm3-payload memcpy at `cfg_boot_armv7.cpp:104-106` overwrites the
isolation marker, so `UOS: isolation guest0@va=0x1000 = 0xE59F12F4 FAILED`,
and the cooperative guest for P0 then Data-Aborts writing 0x60000000 (just
past the 512 MB RAM window) -> recursive kernel abort -> halt, BEFORE the
scheduler reaches the IPC demo. These files (cfg_boot_armv7.cpp, mm.cpp) are
modified by the concurrent guest/wasm track; not touched here.
So the ARINC validity feature is code-complete + compiles clean + behaviourally
proven at component level; only the final on-QEMU staleness banner remains, and
it unblocks automatically once the guest-isolation/P0 track stabilises. No
fabricated boot: the passing evidence above is real (build + harness).
## Files
- kernel/src/core/config/sysmodel.h
- kernel/src/core/config/cfg_parser.cpp
- kernel/src/core/ipc/uos_ipc_core.cpp
- kernel/src/core/ipc/uos_ipc_demo.cpp
- kernel/src/core/config/boot-simple.xml