569f05debc
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.
196 lines
6.2 KiB
Bash
Executable File
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
|