Files
RedBear-OS/local/scripts/test-xhci-irq-qemu.sh
T
vasilito 569f05debc tests: boot low-level + storage proofs from live ISO, not stale harddrive.img
All six validation scripts (xhci-irq, msix, ps2, timer, iommu,
usb-storage) booted build/<arch>/<config>/harddrive.img, which is only
produced by older make-all flows and goes stale (the Jul-17 image).
Running them against it measured the wrong tree — the same trap that
produced the false '+rb0.3.0' bootloader reading and the first hub-test
failure. Each now prefers build/<arch>/<config>.iso via -cdrom and only
falls back to harddrive.img when no ISO exists. extra.img and
usb-storage.img remain as data drives in both modes.
2026-07-20 00:14:30 +09:00

196 lines
6.2 KiB
Bash
Executable File

#!/usr/bin/env bash
# Launch or validate xHCI interrupt-mode bring-up in QEMU.
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
}
usage() {
cat <<'USAGE'
Usage: test-xhci-irq-qemu.sh [--check] [config]
Boot or validate xHCI interrupt-mode bring-up on a Red Bear image in QEMU.
Defaults to redbear-mini (mapped to the in-tree redbear-mini image).
USAGE
}
check_mode=0
config="redbear-mini"
for arg in "$@"; do
case "$arg" in
--help|-h|help)
usage
exit 0
;;
--check)
check_mode=1
;;
redbear-*)
config="$arg"
;;
esac
done
if [[ "$config" == "redbear-mini" ]]; then
config="redbear-mini"
fi
firmware="$(find_uefi_firmware)" || {
echo "ERROR: no usable x86_64 UEFI firmware found" >&2
exit 1
}
arch="${ARCH:-$(uname -m)}"
# Prefer the live ISO (canonical build-redbear.sh artifact); harddrive.img is
# only produced by older make-all flows and goes stale, which would test the
# wrong tree. extra.img stays as a data drive in both modes.
iso="build/$arch/$config.iso"
image="build/$arch/$config/harddrive.img"
extra="build/$arch/$config/extra.img"
boot_media=""
if [[ -f "$iso" ]]; then
boot_media="iso"
elif [[ -f "$image" ]]; then
boot_media="harddrive"
else
echo "ERROR: no bootable image found ($iso or $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
if [[ "$boot_media" == "iso" ]]; then
boot_args=(-cdrom "$iso")
else
boot_args=(-drive file="$image",format=raw,if=none,id=drv0,snapshot=on -device nvme,drive=drv0,serial=NVME_SERIAL)
fi
pkill -f "qemu-system-x86_64.*$config" 2>/dev/null || true
sleep 1
if [[ "$check_mode" -eq 1 ]]; then
log_file="build/$arch/$config/xhci-irq-check.log"
rm -f "$log_file"
set +e
timeout 180s qemu-system-x86_64 \
-name "Red Bear OS x86_64" \
-device qemu-xhci,id=xhci \
-device usb-kbd,bus=xhci.0 \
-device usb-tablet,bus=xhci.0 \
-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 \
"${boot_args[@]}" \
-drive file="$extra",format=raw,if=none,id=drv1,snapshot=on \
-device nvme,drive=drv1,serial=NVME_EXTRA \
-enable-kvm -cpu host \
> "$log_file" 2>&1
status=$?
set -e
# --- Post-P0-A1 checks: the reactor MUST run the IRQ-driven path, NOT polling.
# The reactor logs at debug level:
# "Running IRQ reactor with IRQ file and event queue" (irq_file is Some)
# "Running IRQ reactor in polling mode." (irq_file is None)
if ! grep -q "Running IRQ reactor with IRQ file and event queue" "$log_file"; then
echo "ERROR: xhcid IRQ reactor did NOT run the interrupt-driven path" >&2
echo " Expected: 'Running IRQ reactor with IRQ file and event queue'" >&2
if grep -q "Running IRQ reactor in polling mode" "$log_file"; then
echo " Found: 'Running IRQ reactor in polling mode' (polling — IRQs still bypassed)" >&2
fi
echo " See $log_file" >&2
exit 1
fi
if grep -q "Running IRQ reactor in polling mode" "$log_file"; then
echo "ERROR: xhcid IRQ reactor logged polling mode alongside IRQ-driven mode" >&2
echo " Both 'Running IRQ reactor with IRQ file and event queue' AND" >&2
echo " 'Running IRQ reactor in polling mode' appeared in the same boot." >&2
echo " Only one reactor runs per xhcid instance — this should be impossible." >&2
echo " See $log_file" >&2
exit 1
fi
# Determine which interrupt delivery method was selected.
# get_int_method() at main.rs:54-101 logs at debug level:
# "Enabled MSI-X" (MSI-X was configured and enabled)
# "Legacy IRQ <n>" (MSI/MSI-X absent, falling back to INTx)
mode="unknown"
reason="unknown"
if grep -q "Enabled MSI-X" "$log_file"; then
mode="msi_or_msix"
reason="msix_configured"
elif grep -q "Legacy IRQ" "$log_file"; then
mode="legacy"
reason="fell_back_to_legacy_intx"
else
# If neither MSI-X nor Legacy IRQ logged, the reactor ran the IRQ path
# (proven above) but the delivery method wasn't captured — still a pass.
mode="irq_path_active"
reason="delivery_method_not_captured_in_log"
fi
# Verify the xHCI controller was actually detected.
# main.rs:143 logs at info level: "XHCI <pci_name>"
if ! grep -q "^.*XHCI " "$log_file"; then
echo "ERROR: xHCI controller not detected in boot log; see $log_file" >&2
exit 1
fi
echo "IRQ_DRIVER=xhcid"
echo "IRQ_MODE=$mode"
echo "IRQ_REASON=$reason"
echo "IRQ_LOG=$log_file"
echo "xHCI interrupt-driven mode confirmed in $log_file"
exit 0
fi
exec qemu-system-x86_64 \
-name "Red Bear OS x86_64" \
-device qemu-xhci,id=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" \
-vga std \
"${boot_args[@]}" \
-drive file="$extra",format=raw,if=none,id=drv1,snapshot=on \
-device nvme,drive=drv1,serial=NVME_EXTRA \
-enable-kvm -cpu host