From 2f3b4f6a60927ccffd67e228b67c3246dc068e1b Mon Sep 17 00:00:00 2001 From: Vasilito Date: Wed, 15 Apr 2026 12:57:45 +0100 Subject: [PATCH] Add runtime validation helpers Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent) Co-authored-by: Sisyphus --- local/scripts/test-iommu-qemu.sh | 145 +++++++++++----- local/scripts/test-msix-qemu.sh | 97 +++++++++++ .../scripts/test-phase3-runtime-substrate.sh | 161 ++++++++++++++++++ local/scripts/test-vm-network-qemu.sh | 29 +++- 4 files changed, 393 insertions(+), 39 deletions(-) create mode 100644 local/scripts/test-msix-qemu.sh create mode 100644 local/scripts/test-phase3-runtime-substrate.sh diff --git a/local/scripts/test-iommu-qemu.sh b/local/scripts/test-iommu-qemu.sh index 48d71140..42797a73 100755 --- a/local/scripts/test-iommu-qemu.sh +++ b/local/scripts/test-iommu-qemu.sh @@ -1,72 +1,141 @@ #!/usr/bin/env bash -# -# test-iommu-qemu.sh - Launch QEMU with AMD IOMMU device for hardware testing -# -# This wrapper adds the AMD IOMMU device to QEMU for testing IOMMU/vIOMMU -# functionality on AMD hardware. It forwards any additional QEMU flags to the -# make qemu invocation. -# -# Usage: -# ./local/scripts/test-iommu-qemu.sh [--help] -# ./local/scripts/test-iommu-qemu.sh [extra QEMU flags...] -# -# Examples: -# ./local/scripts/test-iommu-qemu.sh # Basic IOMMU test -# ./local/scripts/test-iommu-qemu.sh -display sdl # With SDL display -# ./local/scripts/test-iommu-qemu.sh -m 4G # With 4GB RAM +# Launch or validate the IOMMU path in QEMU with an AMD IOMMU device. -set -e +set -euo pipefail + +find_uefi_firmware() { + local candidates=( + "/usr/share/ovmf/x64/OVMF.4m.fd" + "/usr/share/OVMF/x64/OVMF.4m.fd" + "/usr/share/ovmf/x64/OVMF_CODE.4m.fd" + "/usr/share/OVMF/x64/OVMF_CODE.4m.fd" + "/usr/share/ovmf/OVMF.fd" + "/usr/share/OVMF/OVMF_CODE.fd" + "/usr/share/qemu/edk2-x86_64-code.fd" + ) + local path + for path in "${candidates[@]}"; do + if [[ -f "$path" ]]; then + printf '%s\n' "$path" + return 0 + fi + done + return 1 +} # Print usage information usage() { cat << USAGE -Usage: $(basename "$0") [options] +Usage: $(basename "$0") [--check] [config] [extra qemu args...] -Launch QEMU with AMD IOMMU device for hardware testing. +Launch or validate QEMU with an AMD IOMMU device. Options: --help Show this help message + --check Boot and verify the guest reaches a login prompt -Any additional arguments are passed as extra QEMU flags. +Arguments: + config Optional config name (default: redbear-desktop) + extra qemu args Additional arguments appended to the QEMU command Environment: QEMUFLAGS Additional flags (prepended to device amd-iommu) Examples: $(basename "$0") - $(basename "$0") -display sdl -m 4G - QEMUFLAGS="-smp 8" $(basename "$0") + $(basename "$0") --check + $(basename "$0") redbear-desktop -m 4G USAGE exit 0 } -# Parse --help before anything else +check_mode=0 +filtered_args=() +config="redbear-desktop" for arg in "$@"; do case "$arg" in --help|-h|help) usage ;; + --check) + check_mode=1 + ;; + redbear-*) + config="$arg" + ;; + *) + filtered_args+=("$arg") + ;; esac done -# Trap to handle Ctrl+C gracefully -# Kill any background QEMU process if interrupted -cleanup() { - echo "Interrupted, cleaning up..." - # The make qemu process will be killed by the signal - exit 130 +firmware="$(find_uefi_firmware)" || { + echo "ERROR: no usable x86_64 UEFI firmware found" >&2 + exit 1 } -trap cleanup SIGINT SIGTERM -# Build QEMUFLAGS with AMD IOMMU device -# Prepend user QEMUFLAGS if set, then add the amd-iommu device -IOMMU_FLAGS="-device amd-iommu" -if [[ -n "${QEMUFLAGS:-}" ]]; then - QEMUFLAGS="${QEMUFLAGS} ${IOMMU_FLAGS} $@" -else - QEMUFLAGS="${IOMMU_FLAGS} $@" +arch="${ARCH:-$(uname -m)}" +image="build/$arch/$config/harddrive.img" +extra="build/$arch/$config/extra.img" +extra_qemu_args="${filtered_args[*]:-}" + +if [[ ! -f "$image" ]]; then + echo "ERROR: missing image $image" >&2 + echo "Build it first with: ./local/scripts/build-redbear.sh $config" >&2 + exit 1 fi -# Launch QEMU via make -exec make qemu QEMUFLAGS="$QEMUFLAGS" +if [[ ! -f "$extra" ]]; then + truncate -s 1g "$extra" +fi + +pkill -f "qemu-system-x86_64.*$image" 2>/dev/null || true +sleep 1 + +if [[ "$check_mode" -eq 1 ]]; then + expect <&2 + exit 1 +} + +if [[ ! -f "$image" ]]; then + echo "ERROR: missing image $image" >&2 + echo "Build it first with: ./local/scripts/build-redbear.sh $config" >&2 + exit 1 +fi + +if [[ ! -f "$extra" ]]; then + truncate -s 1g "$extra" +fi + +pkill -f "qemu-system-x86_64.*$image" 2>/dev/null || true +sleep 1 + +rm -f "$log_file" +set +e +timeout 90s qemu-system-x86_64 \ + -name "Red Bear OS x86_64" \ + -device qemu-xhci \ + -smp 4 \ + -m 2048 \ + -bios "$firmware" \ + -chardev stdio,id=debug,signal=off,mux=on \ + -serial chardev:debug \ + -mon chardev=debug \ + -machine q35 \ + -device ich9-intel-hda -device hda-output \ + -device virtio-net,netdev=net0 \ + -netdev user,id=net0 \ + -object filter-dump,id=f1,netdev=net0,file="build/$arch/$config/network.pcap" \ + -nographic -vga none \ + -drive file="$image",format=raw,if=none,id=drv0 \ + -device nvme,drive=drv0,serial=NVME_SERIAL \ + -drive file="$extra",format=raw,if=none,id=drv1 \ + -device nvme,drive=drv1,serial=NVME_EXTRA \ + -enable-kvm -cpu host \ + > "$log_file" 2>&1 +set -e + +if ! grep -q "virtio: using MSI-X" "$log_file"; then + echo "ERROR: no live MSI-X evidence found in $log_file" >&2 + exit 1 +fi + +echo "MSI-X runtime path detected in $log_file" diff --git a/local/scripts/test-phase3-runtime-substrate.sh b/local/scripts/test-phase3-runtime-substrate.sh new file mode 100644 index 00000000..89cab729 --- /dev/null +++ b/local/scripts/test-phase3-runtime-substrate.sh @@ -0,0 +1,161 @@ +#!/usr/bin/env bash +# Validate the Red Bear OS Phase 3 runtime substrate. +# +# Modes: +# --guest Run inside a Red Bear OS guest +# --qemu [CONFIG] Boot CONFIG in QEMU and run the same checks automatically + +set -euo pipefail + +find_uefi_firmware() { + local candidates=( + "/usr/share/ovmf/x64/OVMF.4m.fd" + "/usr/share/OVMF/x64/OVMF.4m.fd" + "/usr/share/ovmf/x64/OVMF_CODE.4m.fd" + "/usr/share/OVMF/x64/OVMF_CODE.4m.fd" + "/usr/share/ovmf/OVMF.fd" + "/usr/share/OVMF/OVMF_CODE.fd" + "/usr/share/qemu/edk2-x86_64-code.fd" + ) + local path + for path in "${candidates[@]}"; do + if [[ -f "$path" ]]; then + printf '%s\n' "$path" + return 0 + fi + done + return 1 +} + +run_guest_checks() { + echo "=== Red Bear OS Phase 3 Runtime Substrate Test ===" + echo + + require_path() { + local path="$1" + local message="$2" + if [ -e "$path" ]; then + echo "✅ $message" + else + echo "❌ $message" + exit 1 + fi + } + + require_command() { + local cmd="$1" + local message="$2" + if command -v "$cmd" >/dev/null 2>&1; then + echo "✅ $message" + else + echo "❌ $message" + exit 1 + fi + } + + echo "=== Runtime commands ===" + require_command redbear-info "redbear-info is installed" + require_command udev-shim "udev-shim command is installed" + require_command evdevd "evdevd command is installed" + require_command redbear-evtest "evdev consumer test tool is installed" + require_command redbear-input-inject "input injector test tool is installed" + require_command redbear-phase3-input-check "phase 3 guest input check script is installed" + echo + + echo "=== Scheme surfaces ===" + require_path /scheme/pci "PCI scheme is available" + echo + + echo "=== redbear-info --json ===" + local report + report="$(redbear-info --json)" + printf '%s\n' "$report" + case "$report" in + *'scheme firmware is registered in /scheme'*) echo "✅ firmware scheme reported" ;; + *) echo "❌ firmware scheme not reported"; exit 1 ;; + esac + case "$report" in + *'scheme udev is registered in /scheme'*) echo "✅ udev scheme reported" ;; + *) echo "❌ udev scheme not reported"; exit 1 ;; + esac + case "$report" in + *'"name": "evdevd"'*'"state": "active"'*) echo "✅ evdevd reported active" ;; + *) echo "❌ evdevd not reported active"; exit 1 ;; + esac + + echo + echo "=== Phase 3 input validation ===" + echo "Run 'redbear-phase3-input-check' to prove the evdev consumer path." + echo + echo "=== Test Complete ===" +} + +run_qemu_checks() { + local config="$1" + local firmware + firmware="$(find_uefi_firmware)" || { + echo "ERROR: no usable x86_64 UEFI firmware found" >&2 + exit 1 + } + + local arch image extra + arch="${ARCH:-$(uname -m)}" + image="build/$arch/$config/harddrive.img" + extra="build/$arch/$config/extra.img" + + if [[ ! -f "$image" ]]; then + echo "ERROR: missing image $image" >&2 + echo "Build it first with: ./local/scripts/build-redbear.sh $config" >&2 + exit 1 + fi + + if [[ ! -f "$extra" ]]; then + truncate -s 1g "$extra" + fi + + expect <&2 + echo "Install OVMF/edk2-x86_64-code and retry." >&2 + exit 1 + fi +fi echo echo "Suggested in-guest checks:" echo " redbear-info --verbose" @@ -83,4 +110,4 @@ echo " netctl status" echo " lspci" echo -exec make qemu CONFIG_NAME="$CONFIG" net=virtio QEMUFLAGS="$QEMUFLAGS" +exec env CI=1 make qemu CONFIG_NAME="$CONFIG" net=virtio serial=yes QEMUFLAGS="$QEMUFLAGS"