The main aarch64 test suite boots gnumach via u-boot running under
QEMU, which uses `fdt mknod` to inject the multiboot,module DTB
nodes documented in aarch64/BOOTING. That exercises the kernel's
DTB reader through a real bootloader. Add a second, smaller path
that exercises the same kernel code directly via QEMU's `-device
guest-loader` — which synthesises the same /chosen/multiboot,module
nodes without a bootloader in between.
Why have both:
* **Fault isolation.** If the main u-boot tests start failing,
the dedicated test tells us whether it's u-boot/boot.scr/FAT
image generation breaking or the kernel itself. Without this
test, a regression in our scripting machinery looks identical
to a kernel regression and we'd have to debug from scratch.
* **Lower-dependency smoke test.** The dedicated test needs only
qemu-system-aarch64. No u-boot, no mkimage, no mkfs.vfat.
If the u-boot infrastructure breaks for environmental reasons
(qemu version, u-boot defconfig change in nixpkgs), the
dedicated test still validates the kernel.
* **Documentation by example.** Shows the bare-metal Bugaev path
concretely: this is what an embedded board with u-boot's
`fdt mknod` ends up handing the kernel; here's the qemu
equivalent that skips the bootloader.
test-multiboot-module-aarch64 reuses the test-hello module (its
only job is "kernel boots, runs the module, prints
TEST_SUCCESS_MARKER") so the test cost is just the runner script
+ a Makefrag.am entry, not a new test source.
The runner template lives in tests/run-multiboot-module-qemu.sh.template
rather than extending tests/run-qemu.sh.template — guest-loader's
bootargs= parameter needs eval-based shell quoting to thread
'${host-port}' / '$(...)' fragments verbatim to the boot-script
parser, and that machinery shouldn't pollute the main runner that
every other test uses.
Gated on HOST_aarch64 in tests/Makefrag.am; no effect on x86
builds. Adds one to the aarch64 test count: 11 standard u-boot
tests + 1 multiboot-module test = 12, matching x86's 12.
---
tests/Makefrag.am | 11 +++++
tests/run-multiboot-module-qemu.sh.template | 45 +++++++++++++++++++++
tests/user-qemu.mk | 25 ++++++++++++
3 files changed, 81 insertions(+)
create mode 100644 tests/run-multiboot-module-qemu.sh.template
diff --git a/tests/Makefrag.am b/tests/Makefrag.am
index d690adb8..206b0c6f 100644
--- a/tests/Makefrag.am
+++ b/tests/Makefrag.am
@@ -39,12 +39,23 @@ if !HOST_aarch64
TESTS += tests/test-multiboot
endif
TESTS += $(USER_TESTS)
+# tests/test-multiboot-module-aarch64 exercises the multiboot,module
+# DTB convention via QEMU's -device guest-loader — the alternate
+# bootstrap path for users hand-building modules with u-boot's `fdt
+# mknod` per aarch64/BOOTING. The rest of the test suite runs via
+# GRUB + linux,initrd-* (the standard arm64 boot protocol), so this
+# is the only test that gates the multiboot,module reader against
+# regressions.
+if HOST_aarch64
+TESTS += tests/test-multiboot-module-aarch64
+endif
EXTRA_DIST += \
tests/README \
tests/grub.cfg.single.template \
tests/uboot.script.template \
tests/run-qemu.sh.template \
+ tests/run-multiboot-module-qemu.sh.template \
tests/include/syscalls.h \
tests/include/testlib.h \
tests/include/device/cons.h \
diff --git a/tests/run-multiboot-module-qemu.sh.template
b/tests/run-multiboot-module-qemu.sh.template
new file mode 100644
index 00000000..de338613
--- /dev/null
+++ b/tests/run-multiboot-module-qemu.sh.template
@@ -0,0 +1,45 @@
+#!/bin/sh
+# Copyright (C) 2026 Free Software Foundation
+#
+# This program is free software ; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation ; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY ; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with the program ; if not, write to the Free Software
+# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+#
+# Boots gnumach via QEMU's `-device guest-loader`, which synthesises
+# /chosen/multiboot,module DTB nodes (bugaevc/wip-aarch64's
+# convention) — distinct from the standard GRUB + linux,initrd path
+# exercised by the rest of the test suite. Both paths share the
+# kernel's load_boot_modules_from_dtb() reader; this test gates the
+# multiboot,module branch so a regression there gets caught.
+
+set -e
+
+cmd='QEMU_BIN QEMU_OPTS -kernel GNUMACH_BIN -device
"guest-loader,kernel=tests/module-hello,addr=GUEST_LOADER_ADDR,bootargs=module-hello
\${host-port} \${device-port} \$(task-create) \$(task-resume)"'
+log="tests/test-multiboot-module-aarch64.raw"
+
+echo "temp log $log"
+if which QEMU_BIN >/dev/null ; then
+ if ! eval "timeout -v --foreground --kill-after=3 60s $cmd" \
+ | tee $log | sed -n "/TEST_START_MARKER/"',$p' ; then
+ exit 10 # timeout
+ fi
+ if grep -qi 'TEST_FAILURE_MARKER' $log; then
+ exit 99 # error marker found, test explicitely failed
+ fi
+ if ! grep -q 'TEST_SUCCESS_MARKER' $log; then
+ exit 12 # missing reboot marker, maybe the kernel crashed
+ fi
+else
+ echo "skipping, QEMU_BIN not found"
+ exit 77
+fi
diff --git a/tests/user-qemu.mk b/tests/user-qemu.mk
index a55d4f7b..01aa8a10 100644
--- a/tests/user-qemu.mk
+++ b/tests/user-qemu.mk
@@ -305,6 +305,31 @@ tests/test-%: $(TEST_DEPS)
$(srcdir)/tests/run-qemu.sh.template
>$@
chmod +x $@
+# Module load address for the multiboot,module test: RAM_BASE + 256 MB
+# under -M virt (RAM_BASE = 0x40000000), well clear of the kernel
+# image's load area and pmap_bootstrap's page-table allocations. The
+# DTB node `reg` property guest-loader synthesises exposes this
+# address to gnumach.
+if HOST_aarch64
+TEST_MULTIBOOT_MODULE_ADDR = 0x50000000
+
+tests/test-multiboot-module-aarch64: tests/module-hello $(GNUMACH) \
+
$(srcdir)/tests/run-multiboot-module-qemu.sh.template
+ < $(srcdir)/tests/run-multiboot-module-qemu.sh.template \
+ sed -e "s|QEMU_BIN|$(QEMU_BIN)|g" \
+ -e "s|QEMU_OPTS|$(QEMU_OPTS)|g" \
+ -e "s|GNUMACH_BIN|$(GNUMACH)|g" \
+ -e "s|GUEST_LOADER_ADDR|$(TEST_MULTIBOOT_MODULE_ADDR)|g"
\
+ -e "s|TEST_START_MARKER|$(TEST_START_MARKER)|g" \
+ -e "s|TEST_SUCCESS_MARKER|$(TEST_SUCCESS_MARKER)|g" \
+ -e "s|TEST_FAILURE_MARKER|$(TEST_FAILURE_MARKER)|g" \
+ >$@
+ chmod +x $@
+
+clean-test-multiboot-module-aarch64:
+ rm -f tests/test-multiboot-module-aarch64
tests/test-multiboot-module-aarch64.raw
+endif
+
clean-test-%:
rm -f tests/test-$* tests/test-$*.iso tests/test-$*.log
tests/test-$*.raw tests/test-$*.trs tests/module-$*
--
2.54.0