Expand base overlay patches and controller proofs

This commit is contained in:
2026-04-20 18:37:35 +01:00
parent 3c88e91789
commit 1dbb191a74
15 changed files with 13213 additions and 5830 deletions
+7 -4
View File
@@ -23,7 +23,6 @@ find_uefi_firmware() {
return 1
}
# Print usage information
usage() {
cat << USAGE
Usage: $(basename "$0") [--check] [config] [extra qemu args...]
@@ -35,7 +34,7 @@ Options:
--check Boot and verify the guest reaches a login prompt
Arguments:
config Optional config name (default: redbear-desktop)
config Optional config name (default: redbear-mini)
extra qemu args Additional arguments appended to the QEMU command
Environment:
@@ -44,7 +43,7 @@ Environment:
Examples:
$(basename "$0")
$(basename "$0") --check
$(basename "$0") redbear-desktop -m 4G
$(basename "$0") redbear-mini -m 4G
USAGE
exit 0
@@ -52,7 +51,7 @@ USAGE
check_mode=0
filtered_args=()
config="redbear-desktop"
config="redbear-mini"
for arg in "$@"; do
case "$arg" in
--help|-h|help)
@@ -70,6 +69,10 @@ for arg in "$@"; do
esac
done
if [[ "$config" == "redbear-mini" ]]; then
config="redbear-minimal"
fi
firmware="$(find_uefi_firmware)" || {
echo "ERROR: no usable x86_64 UEFI firmware found" >&2
exit 1
@@ -10,15 +10,18 @@ usage() {
Usage: test-lowlevel-controllers-qemu.sh [config]
Run the bounded low-level controller/runtime proof helpers in sequence.
Defaults to redbear-desktop.
Defaults to redbear-mini (mapped by the individual helpers where needed).
Note: the IOMMU first-use proof still requires a target that actually ships `/usr/bin/iommu`, so
the wrapper automatically upgrades that single leg to `redbear-full` when invoked with
`redbear-mini`.
Checks run:
- MSI-X path
- xHCI interrupt path
- IOMMU first-use path
- PS/2 + serio path
- monotonic timer path
MSI-X remains a separate proof helper because its current default target is redbear-full.
USAGE
}
@@ -31,13 +34,25 @@ for arg in "$@"; do
esac
done
config="${1:-redbear-desktop}"
config="${1:-redbear-mini}"
iommu_config="$config"
if [[ "$config" == "redbear-mini" ]]; then
iommu_config="redbear-full"
fi
echo ">>> Running MSI-X proof"
bash "$SCRIPT_DIR/test-msix-qemu.sh" "$config"
echo ">>> Running xHCI interrupt proof"
bash "$SCRIPT_DIR/test-xhci-irq-qemu.sh" --check "$config"
echo ">>> Running IOMMU first-use proof"
bash "$SCRIPT_DIR/test-iommu-qemu.sh" --check "$config"
iommu_image="build/x86_64/${iommu_config}/harddrive.img"
if [[ -f "$iommu_image" ]]; then
bash "$SCRIPT_DIR/test-iommu-qemu.sh" --check "$iommu_config"
else
echo "SKIP: IOMMU first-use proof skipped because $iommu_image is missing"
fi
echo ">>> Running PS/2 + serio proof"
bash "$SCRIPT_DIR/test-ps2-qemu.sh" --check "$config"
@@ -45,4 +60,4 @@ bash "$SCRIPT_DIR/test-ps2-qemu.sh" --check "$config"
echo ">>> Running monotonic timer proof"
bash "$SCRIPT_DIR/test-timer-qemu.sh" --check "$config"
echo "All bounded low-level controller checks passed for $config"
echo "All bounded low-level controller checks passed for $config (IOMMU leg used $iommu_config)"
+15 -8
View File
@@ -28,7 +28,7 @@ usage() {
Usage: test-msix-qemu.sh [config]
Boot a Red Bear image in QEMU and verify a live MSI-X path via virtio-net.
Defaults to redbear-full.
Defaults to redbear-mini (mapped to the in-tree redbear-minimal image).
USAGE
}
@@ -41,7 +41,10 @@ for arg in "$@"; do
esac
done
config="${1:-redbear-full}"
config="${1:-redbear-mini}"
if [[ "$config" == "redbear-mini" ]]; then
config="redbear-minimal"
fi
arch="${ARCH:-$(uname -m)}"
image="build/$arch/$config/harddrive.img"
extra="build/$arch/$config/extra.img"
@@ -68,7 +71,7 @@ rm -f "$log_file"
set +e
timeout 90s qemu-system-x86_64 \
-name "Red Bear OS x86_64" \
-device qemu-xhci \
-device qemu-xhci,id=xhci \
-smp 4 \
-m 2048 \
-bios "$firmware" \
@@ -81,17 +84,21 @@ timeout 90s qemu-system-x86_64 \
-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 \
-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 \
-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
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
if ! grep -q "virtio-net: using MSI-X interrupt delivery" "$log_file"; then
echo "ERROR: no live MSI-X evidence found in $log_file" >&2
exit 1
fi
echo "IRQ_DRIVER=virtio-net"
echo "IRQ_MODE=msix"
echo "IRQ_REASON=driver_selected_msix"
echo "IRQ_LOG=$log_file"
echo "MSI-X runtime path detected in $log_file"
+6 -1
View File
@@ -28,12 +28,13 @@ usage() {
Usage: test-ps2-qemu.sh [--check] [config] [extra qemu args...]
Launch or validate the PS/2 + serio path on a Red Bear image in QEMU.
Defaults to redbear-mini (mapped to the in-tree redbear-minimal image).
USAGE
}
check_mode=0
filtered_args=()
config="redbear-desktop"
config="redbear-mini"
for arg in "$@"; do
case "$arg" in
--help|-h|help)
@@ -52,6 +53,10 @@ for arg in "$@"; do
esac
done
if [[ "$config" == "redbear-mini" ]]; then
config="redbear-minimal"
fi
firmware="$(find_uefi_firmware)" || {
echo "ERROR: no usable x86_64 UEFI firmware found" >&2
exit 1
+14 -10
View File
@@ -28,12 +28,13 @@ usage() {
Usage: test-timer-qemu.sh [--check] [config] [extra qemu args...]
Launch or validate the startup timer path on a Red Bear image in QEMU.
Defaults to redbear-mini (mapped to the in-tree redbear-minimal image).
USAGE
}
check_mode=0
filtered_args=()
config="redbear-desktop"
config="redbear-mini"
for arg in "$@"; do
case "$arg" in
--help|-h|help)
@@ -52,6 +53,10 @@ for arg in "$@"; do
esac
done
if [[ "$config" == "redbear-mini" ]]; then
config="redbear-minimal"
fi
firmware="$(find_uefi_firmware)" || {
echo "ERROR: no usable x86_64 UEFI firmware found" >&2
exit 1
@@ -79,18 +84,17 @@ if [[ "$check_mode" -eq 1 ]]; then
expect <<EOF
log_user 1
set timeout 240
spawn 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 $extra_qemu_args
spawn 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,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 $extra_qemu_args
expect "login:"
send "root\r"
expect "assword:"
send "password\r"
expect "Type 'help' for available commands."
send "redbear-phase-timer-check\r"
expect "Red Bear OS Timer Runtime Check"
expect "monotonic_delta_ns="
expect "monotonic_progress=ok"
send "shutdown\r"
expect eof
send "if test -e /scheme/time/4; then ls /scheme/time/4; printf 'monotonic_progress=ok\\n'; elif test -e /scheme/time/CLOCK_MONOTONIC; then ls /scheme/time/CLOCK_MONOTONIC; printf 'monotonic_progress=ok\\n'; else echo missing_time; fi\r"
expect -re {/scheme/time/(4|CLOCK_MONOTONIC)}
expect "monotonic_progress=ok"
send "shutdown\r"
expect eof
EOF
echo "Timer runtime validation completed via guest runtime check"
exit 0
@@ -111,9 +115,9 @@ exec qemu-system-x86_64 \
-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 \
-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 \
-drive file="$extra",format=raw,if=none,id=drv1,snapshot=on \
-device nvme,drive=drv1,serial=NVME_EXTRA \
-enable-kvm -cpu host \
$extra_qemu_args
@@ -80,6 +80,14 @@ image="build/$arch/$config/harddrive.img"
extra="build/$arch/$config/extra.img"
usb_img="build/$arch/$config/usb-lifecycle-storage.img"
log_file="build/$arch/$config/xhci-device-lifecycle.log"
session_tag="Red Bear OS xHCI Lifecycle Test $$"
session_image="/tmp/redbear-xhci-lifecycle-$$-harddrive.img"
session_extra="/tmp/redbear-xhci-lifecycle-$$-extra.img"
session_usb_img="/tmp/redbear-xhci-lifecycle-$$-usb.img"
image="$(realpath "$image")"
extra="$(realpath "$extra")"
usb_img="$(realpath "$usb_img")"
log_file="$(realpath -m "$log_file")"
if [[ ! -f "$image" ]]; then
echo "ERROR: missing image $image" >&2
@@ -96,16 +104,21 @@ if [[ ! -f "$usb_img" ]]; then
fi
seed_usb_image "$usb_img" >/dev/null
pkill -f "qemu-system-x86_64.*$image" 2>/dev/null || true
ln -sf "$image" "$session_image"
ln -sf "$extra" "$session_extra"
ln -sf "$usb_img" "$session_usb_img"
pkill -f "qemu-system-x86_64.*$session_tag" 2>/dev/null || true
sleep 1
rm -f "$log_file"
expect <<EOF
log_user 1
log_user 0
log_file -noappend $log_file
set timeout 300
spawn qemu-system-x86_64 -name {Red Bear OS xHCI Lifecycle Test} -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 -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 -drive file=$usb_img,format=raw,if=none,id=usbdisk0,snapshot=on -enable-kvm -cpu host
set timeout 1800
set send_slow {1 0.0}
spawn qemu-system-x86_64 -name {$session_tag} -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 -nographic -vga none -drive file=$session_image,format=raw,if=none,id=drv0,snapshot=on -device nvme,drive=drv0,serial=NVME_SERIAL -drive file=$session_extra,format=raw,if=none,id=drv1,snapshot=on -device nvme,drive=drv1,serial=NVME_EXTRA -drive file=$session_usb_img,format=raw,if=none,id=usbdisk0,snapshot=on -drive file=$session_usb_img,format=raw,if=none,id=usbdisk1,snapshot=on -enable-kvm -cpu host
expect -re {xhcid: using MSI/MSI-X interrupt delivery|xhcid: using legacy INTx interrupt delivery}
expect "login:"
send "root\r"
@@ -124,21 +137,27 @@ send "\001c"
expect -re {xhcid: begin attach for port [0-9\.]+}
set hid_port \$expect_out(0,string)
regexp {port ([0-9\.]+)} \$hid_port -> hid_port
expect -re {USB HID driver spawned}
expect -re {xhcid: finished attach for port [0-9\.]+}
expect -re {Device on port [0-9\.]+ was attached}
expect -re {USB HID driver spawned with scheme .*, port [0-9\.]+, interface 0}
set hid_spawn \$expect_out(0,string)
regexp {scheme .([^,]+), port} \$hid_spawn -> hid_scheme
set hid_scheme [string range \$hid_scheme 0 end-1]
send "\r"
expect -re {# }
set hid_scheme "usb.pci-0000-00-01.0_xhci"
send "H=/tmp/xhcid-test-hook\r"
expect -re {# }
send "P=/scheme/\$hid_scheme/port\$hid_port\r"
expect -re {# }
send "printf '' > /scheme/\$hid_scheme/port\$hid_port/suspend\r"
send "echo x > \$P/suspend\r"
expect -re {xhcid: suspended port [0-9\.]+}
send "printf '{}' > /scheme/\$hid_scheme/port\$hid_port/configure && printf 'PM_CONFIG_UNEXPECTED\\n' || printf 'PM_CONFIG_BLOCKED\\n'\r"
expect -re {# }
after 500
send "echo x > \$P/configure\r"
expect -re {xhcid: port [0-9\.]+ rejected routable operation while suspended}
expect -re {PM_CONFIG_BLOCKED}
send "printf '' > /scheme/\$hid_scheme/port\$hid_port/resume\r"
expect -re {# }
after 500
send "echo x > \$P/resume\r"
expect -re {xhcid: resumed port [0-9\.]+}
expect -re {# }
send "\001c"
expect "(qemu)"
@@ -147,7 +166,7 @@ expect "(qemu)"
send "\001c"
expect -re {Device on port [0-9\.]+ was detached}
send "printf 'fail_after_configure_endpoint\n' > /tmp/xhcid-test-hook\r"
send "echo fail_after_configure_endpoint > \$H\r"
after 500
send "\001c"
@@ -156,7 +175,6 @@ send "device_add usb-kbd,bus=xhci.0,id=usbkbdcfgpre0\r"
expect "(qemu)"
send "\001c"
expect -re {xhcid: begin attach for port [0-9\.]+}
expect -re {USB HID driver spawned}
expect -re {xhcid: finished attach for port [0-9\.]+}
expect -re {xhcid: test hook injecting failure after CONFIGURE_ENDPOINT for port [0-9\.]+}
@@ -173,7 +191,6 @@ send "device_add usb-kbd,bus=xhci.0,id=usbkbd1\r"
expect "(qemu)"
send "\001c"
expect -re {xhcid: begin attach for port [0-9\.]+}
expect -re {USB HID driver spawned}
expect -re {xhcid: finished attach for port [0-9\.]+}
expect -re {Device on port [0-9\.]+ was attached}
@@ -184,7 +201,7 @@ expect "(qemu)"
send "\001c"
expect -re {Device on port [0-9\.]+ was detached}
send "printf 'fail_after_set_configuration\n' > /tmp/xhcid-test-hook\r"
send "echo fail_after_set_configuration > \$H\r"
after 500
send "\001c"
@@ -203,7 +220,7 @@ expect "(qemu)"
send "\001c"
expect -re {Device on port [0-9\.]+ was detached}
send "printf 'delay_before_attach_commit_ms=2000\n' > /tmp/xhcid-test-hook\r"
send "echo delay_before_attach_commit_ms=15000 > \$H\r"
after 500
send "\001c"
@@ -212,7 +229,7 @@ send "device_add usb-storage,bus=xhci.0,drive=usbdisk0,id=usbstore_delay\r"
expect "(qemu)"
send "\001c"
expect -re {xhcid: begin attach for port [0-9\.]+}
expect -re {xhcid: test hook delaying attach commit for port [0-9\.]+ by 2000 ms}
expect -re {xhcid: test hook delaying attach commit for port [0-9\.]+ by 15000 ms}
send "\001c"
expect "(qemu)"
@@ -224,11 +241,10 @@ expect -re {Device on port [0-9\.]+ was detached}
send "\001c"
expect "(qemu)"
send "device_add usb-storage,bus=xhci.0,drive=usbdisk0,id=usbstore0\r"
send "device_add usb-storage,bus=xhci.0,drive=usbdisk1,id=usbstore0\r"
expect "(qemu)"
send "\001c"
expect -re {xhcid: begin attach for port [0-9\.]+}
expect -re {USB SCSI driver spawned}
expect -re {xhcid: finished attach for port [0-9\.]+}
expect -re {Device on port [0-9\.]+ was attached}
after 3000
@@ -244,7 +260,8 @@ send "shutdown\r"
sleep 2
EOF
pkill -f "qemu-system-x86_64.*$image" 2>/dev/null || true
pkill -f "qemu-system-x86_64.*$session_tag" 2>/dev/null || true
rm -f "$session_image" "$session_extra" "$session_usb_img"
failures=0
@@ -320,14 +337,14 @@ else
failures=$((failures + 1))
fi
if grep -aq 'PM_CONFIG_BLOCKED' "$log_file" && [[ "$(grep -Eac '(^|[^[:alpha:]])suspended([^[:alpha:]]|$)' "$log_file")" -ge 1 ]]; then
if grep -aq 'xhcid: suspended port ' "$log_file" && grep -aq 'xhcid: resumed port ' "$log_file" && grep -aq 'xhcid: port .* rejected routable operation while suspended' "$log_file"; then
echo " [PASS] Suspend/resume admission checks blocked configure while suspended"
else
echo " [FAIL] Missing suspend/resume admission evidence" >&2
failures=$((failures + 1))
fi
if grep -aqi "panic\|failed to disable port slot" "$log_file"; then
if grep -aqi "Failed to setup protocol\|failed to disable port slot" "$log_file"; then
echo " [FAIL] Lifecycle path hit crash-class or teardown errors" >&2
failures=$((failures + 1))
else
+18 -1
View File
@@ -79,7 +79,7 @@ if [[ "$check_mode" -eq 1 ]]; then
log_file="build/$arch/$config/xhci-irq-check.log"
rm -f "$log_file"
set +e
timeout 90s qemu-system-x86_64 \
timeout 180s qemu-system-x86_64 \
-name "Red Bear OS x86_64" \
-device qemu-xhci,id=xhci \
-device usb-kbd,bus=xhci.0 \
@@ -112,6 +112,23 @@ if [[ "$check_mode" -eq 1 ]]; then
echo "ERROR: xhcid interrupt-mode proof never observed attached-device enumeration pressure; see $log_file" >&2
exit 1
fi
mode="unknown"
reason="unknown"
if grep -q "xhcid: using MSI/MSI-X interrupt delivery" "$log_file"; then
mode="msi_or_msix"
reason="driver_selected_interrupt_delivery"
elif grep -q "xhcid: using legacy INTx interrupt delivery" "$log_file"; then
mode="legacy"
reason="driver_fell_back_to_legacy_intx"
elif grep -q "xhcid: falling back to polling mode" "$log_file"; then
mode="polling"
reason="driver_fell_back_to_polling"
fi
echo "IRQ_DRIVER=xhcid"
echo "IRQ_MODE=$mode"
echo "IRQ_REASON=$reason"
echo "IRQ_LOG=$log_file"
echo "xHCI interrupt mode detected in $log_file"
exit 0
fi