Files
RedBear-OS/local/scripts/test-xhci-irq-qemu.sh
T
vasilito 33465b59e0 test-xhci-irq-qemu.sh: grep for actual xHCI reactor log lines
The old --check section looked for log strings that do not exist in the
xhcid codebase ("xhcid: using MSI/MSI-X interrupt delivery" etc.).
All six grep patterns were fictitious — the script was written ahead of
P0-A1 anticipating different logging.

Rewrite to match actual debug-level output from xhcid:

  irq_reactor.rs:208 — "Running IRQ reactor with IRQ file and event queue"
    (irq_file is Some — this is the main proof that interrupts fired)
  irq_reactor.rs:125 — "Running IRQ reactor in polling mode."
    (irq_file is None — must NOT appear in a passing run)
  main.rs:88        — "Enabled MSI-X"  (debug, MSI-X configured)
  main.rs:95        — "Legacy IRQ <n>" (debug, INTx fallback)
  main.rs:143       — "XHCI <pci_name>" (info, controller detected)

Also fails if both polling and IRQ-driven mode appear in the same boot.
2026-07-07 00:44:30 +03:00

183 lines
5.8 KiB
Bash

#!/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)}"
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
pkill -f "qemu-system-x86_64.*$image" 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 \
-drive file="$image",format=raw,if=none,id=drv0,snapshot=on \
-device nvme,drive=drv0,serial=NVME_SERIAL \
-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 \
-drive file="$image",format=raw,if=none,id=drv0,snapshot=on \
-device nvme,drive=drv0,serial=NVME_SERIAL \
-drive file="$extra",format=raw,if=none,id=drv1,snapshot=on \
-device nvme,drive=drv1,serial=NVME_EXTRA \
-enable-kvm -cpu host