diff --git a/docs/de25-nano-tasks.md b/docs/de25-nano-tasks.md index ec24255..20808ed 100644 --- a/docs/de25-nano-tasks.md +++ b/docs/de25-nano-tasks.md @@ -402,7 +402,11 @@ Remaining, in unblock order: pointed to from the DE25 series; the aarch64 leg's `symlink` case is the acceptance test — it is the ONLY place 0031-on-7.x is executed rather than compiled.~~ **DONE 2026-09-06:** beta-local copy, DE25 series relinked, aarch64 leg 8/8, arm compile clean on the RT config. - Remaining: the first `ln -s` on an RT-booted DE10 (32-bit 7.x is still compile-only). + ~~Remaining: the first `ln -s` on an RT-booted DE10 (32-bit 7.x is still compile-only).~~ + **2026-09-11:** executed as 32-bit ARM by `scripts/test-initramfs.sh --kernel rt` (7.2.4, + `symlink`/`exfat`/`fsck-request` pass; the 6.18-form patch on 7.2.4 reproduces the Oops), + after the rig, still on a pre-rewrite RT 7.2.3, panicked on the Arcade Organizer's first + symlink (ADR 0002 §8b). Hardware boot of the fixed RT kernel still owed. 3. **Owner decisions still open**: a Renovate manager for the DE25 kernel pin; upstream submission of 0101/0102; patch 0002 (audio). Hardware is expected after the owner's vacation (ordered on return). diff --git a/docs/decisions/0002-initramfs.md b/docs/decisions/0002-initramfs.md index 2c74811..8b9f1e7 100644 --- a/docs/decisions/0002-initramfs.md +++ b/docs/decisions/0002-initramfs.md @@ -372,8 +372,19 @@ device directly and never sees a dirty bdev buffer), and does the `valid_size` / `zeroed_size` / `i_size` bookkeeping the write path would have done. Applies at `-F0` to pristine 7.2.3; compiles for arm with the RT `.config` and for arm64 with the DE25's; the aarch64 leg is **8/8** with the `symlink` case's full assertion set (hot+cold round-trip, -`DT_LNK`, the create+unlink cluster-leak tripwire via `statvfs`, host-side fsck-clean). What -remains unexecuted is 0031 on 32-bit 7.x — the RT kernel on a real board. +`DT_LNK`, the create+unlink cluster-leak tripwire via `statvfs`, host-side fsck-clean). + +**2026-09-11 — the 32-bit gap closed, the hard way first.** The maintainer's rig was still on +an RT 7.2.3 kernel built 2026-09-05, before the rewrite shipped there; `update_all.sh`'s +Arcade Organizer created its first `.mra` symlink on `/media/fat` and the board Oopsed +exactly as above (`PC is at 0x0`, `LR is at page_symlink+0x90`, from `exfat_symlink`; captured +by netconsole) and, with `CONFIG_PANIC_ON_OOPS=y` + `panic=15`, rebooted 17 s later. The +same day `scripts/test-initramfs.sh --kernel rt` was added: the DE10 leg built at the RT pin +(`BR2_PACKAGE_LINUX_RT_VERSION`) with `linux-patches-beta/0031`, on `qemu-system-arm`, so the +rewrite is executed as 32-bit ARM. Result at 7.2.4: `symlink`, `exfat`, `fsck-request` pass; +the negative control (the 6.18-form patch on the same 7.2.4 source) reproduces the rig's +Oops in QEMU, so the leg detects the bug it exists for. `ci-tests.sh` runs it after the +DE10 leg. What remains is the ordinary hardware claim: a board boot of the fixed RT kernel. ## 8c. Amendment 2026-09-11 — stage 1 becomes a package of the main build (ADR 0030) diff --git a/docs/rt-beta-kernel.md b/docs/rt-beta-kernel.md index a4db4cf..a6d6f6e 100644 --- a/docs/rt-beta-kernel.md +++ b/docs/rt-beta-kernel.md @@ -249,7 +249,7 @@ card, and nothing on the card referenced it), and deliberately NOT inside | **Module-tree merge into the one linux.img** | ✅ **green** — the row's "first green run pending" was overtaken by CI run 29758320422 (2026-07-20, rc4: `build-kernel` + `build` both green, so the merge assert ran). Re-verified locally on rc5 (2026-07-28): after `make rt`, a `make all` produced `output/target/usr/lib/modules/` holding exactly `6.18.40` and `7.2.0-rc5` — two trees, no stale third — and `linux.img` passed every `check-linux-img.sh` assertion (512 MiB, pinned UUID/hash-seed, the 14-feature stock-derived set, ADR 0015 ssh-key checks) | | **RT kernel boots on the DE10-Nano** | ⚠️ **NOT on the currently pinned 7.2 — re-opened 2026-08-17 by the rc7 → 7.2 bump.** ✅ **CONFIRMED 2026-07-20 on 7.2-rc4**, which booted and ran MiSTer on real hardware. That retired the single biggest open risk on the variant, and it is how the `0037` DualSense regression was caught: booting far enough to use a controller is what exposed the shifted PS5 button map (§7 item 3). ✅ **RE-CONFIRMED 2026-08-14 on 7.2-rc7** — the Wave-1 hardware pass ran on a `7.2.0-rc7 SMP PREEMPT_RT` kernel carrying `0043`, and the doorbell nodes enumerated and delivered events (that pass is also where H-1 and H-2 were found). Boot is a **per-version claim** and every bump re-opens it, which is exactly the state this row is in now: 7.2 final is patch-verified (**40/40** at `-F0`), DTS-verified, and **built on the whole 40-entry series** (`make rt` green from clean, 2026-08-17 — see the build rows above), but it has **not been booted**. Everything that can be checked without hardware has been checked and passed; none of it is a boot. This ✅ covers rc4 and rc7 and nothing else. It also does **not** cover `0044`, `0045`, `0046` or the re-added `0038`–`0042`: none were in the series when the rc7 kernel was built, and all six have since been built but never booted — §2, §8, §9 | | **vsync/IRQ-40 latency under RT threaded IRQs** | ❌ **unproven** (the point of the exercise) — boot and general operation are confirmed, but the latency measurement that motivates RT has not been taken | -| **Patch 0031 (exFAT Samsung symlinks) on 7.x** | ✅ **FIXED 2026-09-06 — after being found BROKEN the same day**, not by this variant but by the DE25's aarch64 initramfs QEMU leg (`scripts/test-initramfs.sh --board de25nano`), the first thing ever to EXECUTE 0031 on a 7.x kernel: `exfat_symlink()` → `page_symlink()` → `a_ops->write_begin` is NULL on 7.x exFAT (iomap; no `write_begin`/`write_end`) → Oops, `pc: 0x0`, on the first symlink created. `linux-patches-beta/0031` WAS a symlink to the shared 6.18 file, so this kernel had the same crash on any `ln -s` on `/media/fat` (reading existing links was fine). The "applies at -F0" and "compiles" rows above were true and insufficient. Now a **beta-local re-anchored copy** (the fifth): `exfat_symlink_write_target()` allocates clusters via 7.x's `exfat_map_cluster()`, writes the sectors through buffer heads, `sync_blockdev_range()`s them (iomap reads go straight to the device), and does the `valid_size`/`zeroed_size`/`i_size` bookkeeping; the DE25 series links to this copy. Verified: applies at `-F0` to pristine 7.2.3 (12/12 hunks), **compiles for arm with this variant's own `output-rt` `.config`** (`fs/exfat/`, zero warnings), and the aarch64 leg's `symlink` case passes — hot+cold round-trip, `DT_LNK`, the create+unlink cluster-leak tripwire, fsck-clean (ADR 0002 §8b). Still not executed on 32-bit ARM: the DE10 leg boots 6.18 only, so the first `ln -s` on an RT-booted board is the remaining proof. | +| **Patch 0031 (exFAT Samsung symlinks) on 7.x** | ✅ **FIXED 2026-09-06 — after being found BROKEN the same day**, not by this variant but by the DE25's aarch64 initramfs QEMU leg (`scripts/test-initramfs.sh --board de25nano`), the first thing ever to EXECUTE 0031 on a 7.x kernel: `exfat_symlink()` → `page_symlink()` → `a_ops->write_begin` is NULL on 7.x exFAT (iomap; no `write_begin`/`write_end`) → Oops, `pc: 0x0`, on the first symlink created. `linux-patches-beta/0031` WAS a symlink to the shared 6.18 file, so this kernel had the same crash on any `ln -s` on `/media/fat` (reading existing links was fine). The "applies at -F0" and "compiles" rows above were true and insufficient. Now a **beta-local re-anchored copy** (the fifth): `exfat_symlink_write_target()` allocates clusters via 7.x's `exfat_map_cluster()`, writes the sectors through buffer heads, `sync_blockdev_range()`s them (iomap reads go straight to the device), and does the `valid_size`/`zeroed_size`/`i_size` bookkeeping; the DE25 series links to this copy. Verified: applies at `-F0` to pristine 7.2.3 (12/12 hunks), **compiles for arm with this variant's own `output-rt` `.config`** (`fs/exfat/`, zero warnings), and the aarch64 leg's `symlink` case passes — hot+cold round-trip, `DT_LNK`, the create+unlink cluster-leak tripwire, fsck-clean (ADR 0002 §8b). Still not executed on 32-bit ARM: the DE10 leg boots 6.18 only, so the first `ln -s` on an RT-booted board is the remaining proof. **2026-09-11: executed as 32-bit ARM** — the rig (still on a pre-rewrite RT 7.2.3 from 2026-09-05) panicked on `update_all.sh`'s first Arcade Organizer symlink (netconsole: `PC is at 0x0`, `LR is at page_symlink+0x90`; `CONFIG_PANIC_ON_OOPS=y` + `panic=15` rebooted it), and `scripts/test-initramfs.sh --kernel rt` now builds the DE10 QEMU leg at the RT pin with `linux-patches-beta/0031`: 7.2.4 passes `symlink`/`exfat`/`fsck-request`; the 6.18-form patch on the same source reproduces the Oops. Only a hardware boot of the fixed kernel remains. | | `rtw88_8814au` firmware (`rtw88/rtw8814a_fw.bin`) present | ✅ ships via `BR2_PACKAGE_LINUX_FIRMWARE_RTL_RTW88` | ## 7. What is left diff --git a/scripts/ci-tests.sh b/scripts/ci-tests.sh index 1c6be23..7ae655c 100755 --- a/scripts/ci-tests.sh +++ b/scripts/ci-tests.sh @@ -300,6 +300,30 @@ else fi fi +# The same /init on the DE10's RT kernel series (7.2.y): the three cases that +# exercise the exfat driver, because 7.x exfat is iomap-based and board patch +# 0031 (Samsung-format symlinks, ADR 0019) is a separate re-anchored copy +# there (linux-patches-beta/). Its only other executions are aarch64 (the +# DE25 leg); the DE10-Nano runs it as 32-bit ARM, and the first field `ln -s` +# on an RT-booted board Oopsed (2026-09-11) on the pre-rewrite copy. Gated +# like the DE10 leg; a second multi_v7 kernel build, cached under +# work/test-initramfs-rt*. +if [ "${CI_TESTS_SKIP_QEMU_SYSTEM:-0}" = "1" ]; then + skip "test-initramfs.sh --kernel rt (32-bit QEMU boot test on the RT kernel, exfat cases)" "CI_TESTS_SKIP_QEMU_SYSTEM=1" +elif ! have qemu-system-arm; then + skip "test-initramfs.sh --kernel rt (32-bit QEMU boot test on the RT kernel, exfat cases)" "qemu-system-arm not found on PATH" +elif ! grep -q '^BR2_PACKAGE_LINUX_RT=y$' "$ROOT/configs/mister_de10nano_defconfig"; then + skip "test-initramfs.sh --kernel rt (32-bit QEMU boot test on the RT kernel, exfat cases)" "BR2_PACKAGE_LINUX_RT is not enabled in configs/mister_de10nano_defconfig" +else + printf -- '--- test-initramfs.sh --kernel rt: exfat fsck-request symlink ---\n' + printf ' (builds/reuses a second QEMU test kernel at the RT pin -- can take several minutes)\n' + if "$ROOT/scripts/test-initramfs.sh" --kernel rt exfat fsck-request symlink; then + pass "test-initramfs.sh --kernel rt (32-bit QEMU boot test on the RT kernel, 3 exfat cases)" + else + fail "test-initramfs.sh --kernel rt (32-bit QEMU boot test on the RT kernel, 3 exfat cases)" "one or more of the 3 cases failed -- see output above" + fi +fi + # The DE25-Nano's stage 1: the SAME package built for aarch64 by the DE25 # configuration -- once its stack enables BR2_LINUX_KERNEL_EXT_MISTER_INITRAMFS # (ADR 0029 D11 keeps that off until a board has booted). Gated on the cpio diff --git a/scripts/test-initramfs.sh b/scripts/test-initramfs.sh index 546150f..3392bcc 100755 --- a/scripts/test-initramfs.sh +++ b/scripts/test-initramfs.sh @@ -33,7 +33,7 @@ # entry on it, so this synthetic test is the only place that regression can # ever be caught (see the case function below for the full argument). # -# Usage: scripts/test-initramfs.sh [--board de10nano|de25nano] [case ...] +# Usage: scripts/test-initramfs.sh [--board de10nano|de25nano] [--kernel default|rt] [case ...] # With no case arguments, runs all eight cases. Exit 0 iff every requested # case passed; nonzero otherwise (wired for P4.1's CI job). # @@ -58,6 +58,16 @@ # DE10 leg deliberately does not (its product kernel # cannot run under QEMU at all). # +# ONE BOARD, TWO KERNEL SERIES (2026-09-11). `--kernel rt` (de10nano only) +# runs the same DE10 leg against the RT kernel's pin (BR2_PACKAGE_LINUX_RT_VERSION, +# 7.2.y) with the RT series' own re-anchored board patch 0031 +# (board/mister/de10nano/linux-patches-beta/). 7.x exfat is iomap-based and +# 0031 had to be rewritten for it; the DE25 leg executes that rewrite on +# aarch64, but the DE10-Nano runs it as 32-bit ARM, which nothing else boots +# -- the first field `ln -s` on an RT-booted board Oopsed (page_symlink -> +# NULL write_begin, 2026-09-11, before the rewrite had shipped there). This +# leg is the 32-bit proof; its caches live under work/test-initramfs-rt*. +# # Every case, cmdline and assertion is identical between the two legs. The # cross compiler for the DE25 leg is the DE25 build's own glibc toolchain # (output-de25/host/bin), so `make de25` is the only @@ -91,11 +101,18 @@ SUPPORT="$HERE/test-initramfs" # environment is the same switch for callers that cannot pass arguments # (ci-tests.sh's per-board legs use the flag). BOARD="${TEST_INITRAMFS_BOARD:-de10nano}" +# `--kernel` picks which of the board's kernel series the QEMU test kernel is +# built at: `default` (BR2_LINUX_KERNEL_CUSTOM_VERSION_VALUE, the shipped +# kernel) or `rt` (BR2_PACKAGE_LINUX_RT_VERSION with the RT series' own patch +# 0031). TEST_INITRAMFS_KERNEL is the environment form. +KERNEL="${TEST_INITRAMFS_KERNEL:-default}" _args=() while [ "$#" -gt 0 ]; do case "$1" in --board) shift; BOARD="${1:-}" ;; --board=*) BOARD="${1#--board=}" ;; + --kernel) shift; KERNEL="${1:-}" ;; + --kernel=*) KERNEL="${1#--kernel=}" ;; *) _args+=("$1") ;; esac shift @@ -117,6 +134,7 @@ de10nano) KERNEL_BASE_DEFCONFIG=multi_v7_defconfig KERNEL_BASE_FILES=() PIN_FRAGMENT="$ROOT/configs/mister_de10nano_defconfig" + PIN_SYMBOL=BR2_LINUX_KERNEL_CUSTOM_VERSION_VALUE EXFAT_SYMLINK_PATCH="$ROOT/board/mister/de10nano/linux-patches/0031-exfat-samsung-symlinks.patch" CACHE_TAG="" ;; @@ -138,6 +156,7 @@ de25nano) KERNEL_BASE_FILES=("$ROOT/board/mister/de25nano/linux.config" "$ROOT/board/mister/common/linux-mister.fragment") PIN_FRAGMENT="$ROOT/configs/mister_de25nano_defconfig" + PIN_SYMBOL=BR2_LINUX_KERNEL_CUSTOM_VERSION_VALUE # Resolved through the DE25's own patch dir, which links to the 7.x # re-anchored copy in linux-patches-beta/ (since 2026-09-06 -- this # very case found the shared 6.18 form Oopsing on 7.x, ADR 0002 §8b). @@ -150,6 +169,23 @@ de25nano) ;; esac +case "$BOARD/$KERNEL" in +*/default) + ;; +de10nano/rt) + # The RT series: its pin, its own 7.x-anchored 0031, its own caches (a + # 7.2.y source tree and O= build must never share work/ with the 6.18 + # ones -- ensure_qemu_kernel() reuses whatever it finds there). + PIN_SYMBOL=BR2_PACKAGE_LINUX_RT_VERSION + EXFAT_SYMLINK_PATCH="$ROOT/board/mister/de10nano/linux-patches-beta/0031-exfat-samsung-symlinks.patch" + CACHE_TAG="-rt" + ;; +*) + printf 'test-initramfs.sh: FATAL: unknown --kernel %s for --board %s (known: default; rt on de10nano)\n' "'$KERNEL'" "$BOARD" >&2 + exit 2 + ;; +esac + INIT_SRC="$ROOT/board/mister/common/initramfs-overlay/init" MARKER_C="$SUPPORT/marker-init.c" TEST_SYMLINK_C="$SUPPORT/test-symlink.c" @@ -171,14 +207,14 @@ KERNEL_SRC="${TEST_INITRAMFS_KERNEL_SRC:-$ROOT/work/test-initramfs$CACHE_TAG-ker # fails the QEMU kernel build with a confusing "too few arguments". Reading the # pin keeps this test kernel on the same version the image ships, which is what # this script's header already claims it does. -KERNEL_VERSION="${TEST_INITRAMFS_KERNEL_VERSION:-$(sed -n 's/^BR2_LINUX_KERNEL_CUSTOM_VERSION_VALUE="\(.*\)"$/\1/p' "$PIN_FRAGMENT")}" +KERNEL_VERSION="${TEST_INITRAMFS_KERNEL_VERSION:-$(sed -n "s/^$PIN_SYMBOL=\"\(.*\)\"\$/\1/p" "$PIN_FRAGMENT")}" # Inline, not die() -- that is defined further down, and this block runs before # it. Under `set -uo pipefail` (no -e) an undefined-function call would print # "command not found" and CARRY ON, which is exactly the silent failure this # guard exists to prevent. [ -n "$KERNEL_VERSION" ] || { printf 'test-initramfs.sh: FATAL: %s\n' \ - "could not read BR2_LINUX_KERNEL_CUSTOM_VERSION_VALUE from ${PIN_FRAGMENT#"$ROOT"/}" >&2 + "could not read $PIN_SYMBOL from ${PIN_FRAGMENT#"$ROOT"/}" >&2 exit 2 } # The pristine source tarball. Buildroot's own kernel build fetches it into @@ -1021,7 +1057,7 @@ main() { ensure_qemu_kernel build_marker_inits - log "board: $BOARD ($KARCH, $QEMU_SYSTEM ${QEMU_MACHINE[*]}, kernel $KERNEL_VERSION, cpio ${CPIO#"$ROOT"/})" + log "board: $BOARD ($KARCH, $QEMU_SYSTEM ${QEMU_MACHINE[*]}, kernel $KERNEL_VERSION [$KERNEL series, $(basename "$(dirname "$EXFAT_SYMLINK_PATCH")")/0031], cpio ${CPIO#"$ROOT"/})" log "running ${#requested[@]} case(s): ${requested[*]}" echo "" local c