diff options
Diffstat (limited to 'tests/arch')
| -rw-r--r-- | tests/arch | 143 |
1 files changed, 143 insertions, 0 deletions
diff --git a/tests/arch b/tests/arch new file mode 100644 index 0000000..2f60451 --- /dev/null +++ b/tests/arch @@ -0,0 +1,143 @@ +# ARCH picks the qemu binary, the machine type and the display device. +# Nothing here needs /dev/kvm: another architecture is emulated. + +"$VMM" create ar1 64M >/dev/null 2>&1 +FW=/usr/share/qemu/edk2-aarch64-code.fd +[ -f "$FW" ] || FW=/usr/share/AAVMF/AAVMF_CODE.fd + +cfg ar1 <<EOF +ARCH=riscv64 +EOF +refuses 'ARCH must be' "an unsupported ARCH is refused" dryrun ar1 + +cfg ar1 <<EOF +ARCH=aarch64 +EOF +refuses 'requires FIRMWARE' "aarch64 without firmware is refused" dryrun ar1 + +cfg ar1 <<EOF +FIRMWARE=firmware.fd +EOF +refuses 'FIRMWARE must be an absolute path' "a relative FIRMWARE is refused" dryrun ar1 + +# The host's own architecture is accelerated. -cpu host means nothing +# anywhere else, and asking for it under emulation is an error. +: > "$VMMDIR/ar1/config" +outputs 'accel=kvm' "the host architecture gets kvm" dryrun ar1 +outputs "-cpu 'host'" "the host architecture gets the host cpu" dryrun ar1 + +# A host with no /dev/kvm can still run its own architecture, slowly. +cfg ar1 <<EOF +HWACCEL=no +EOF +outputs 'accel=tcg' "HWACCEL=no emulates the host architecture" dryrun ar1 +outputs "-cpu 'max'" "HWACCEL=no drops -cpu host, which needs kvm" dryrun ar1 + +cfg ar1 <<EOF +HWACCEL=maybe +EOF +refuses 'HWACCEL must be' "HWACCEL takes yes or no" dryrun ar1 + +cfg ar1 <<EOF +ARCH=aarch64 +FIRMWARE="$FW" +GRAPHICS=vnc +EOF +outputs 'qemu-system-aarch64' "ARCH picks the qemu binary" dryrun ar1 +outputs "machine 'virt" "aarch64 gets the virt machine" dryrun ar1 +outputs 'accel=tcg' "a foreign architecture is emulated" dryrun ar1 +outputs "-cpu 'max'" "an emulated guest does not ask for the host cpu" dryrun ar1 +outputs "bios '$FW'" "the firmware reaches the argv" dryrun ar1 +outputs 'virtio-gpu-pci' "aarch64 gets a display device that is not VGA" dryrun ar1 + +# ARCH names a binary that may not be installed. Saying so is instant; +# leaving it to setsid costs both monitor timeouts first. +NOQEMU=$WORK/noqemu-bin +mkdir -p "$NOQEMU" +for b in flock uname od awk cat tr; do + ln -sf "$(command -v "$b")" "$NOQEMU/$b" +done +: > "$VMMDIR/ar1/config" +out=$(PATH=$NOQEMU "$VMM" start ar1 2>&1) && got=0 || got=$? +if [ "$got" != 0 ] && printf '%s' "$out" | grep -q 'qemu-system-.* is not on PATH'; then + ok "a qemu that is not installed is named at once" +else + notok "a qemu that is not installed is named at once" "exit $got: $out" +fi + +# Emulated end to end: the firmware really runs and really talks to the +# serial console, which is the whole point of passing -bios. +if [ -f "$FW" ] && command -v qemu-system-aarch64 >/dev/null 2>&1; then + cfg ar1 <<EOF +ARCH=aarch64 +FIRMWARE="$FW" +MEM=512 +CPUS=1 +EOF + exits 0 "an emulated aarch64 guest starts" start ar1 + outputs 'running' "the emulated guest answers its monitor" \ + monitor ar1 info status + sleep 2 + holds "the emulated firmware writes to the serial console" \ + test -s "$VMMDIR/ar1/console.log" + "$VMM" kill ar1 >/dev/null 2>&1 || : +else + skip 3 "no qemu-system-aarch64 or no aarch64 firmware" +fi + +# Failure after spawn must reap only that child and remove every runtime +# object it may have created. +if command -v "qemu-system-$(uname -m)" >/dev/null 2>&1; then + "$VMM" create ar2 64M >/dev/null 2>&1 + printf 'not a qcow2 image\n' > "$VMMDIR/ar2/disk.qcow2" + cfg ar2 <<EOF +HWACCEL=no +MEM=256 +CPUS=1 +EOF + exits 1 "a qemu startup failure is reported" start ar2 + holds "a failed start leaves no pidfile" test ! -e "$VMMDIR/ar2/pid" + holds "a failed start leaves no input FIFO" test ! -e "$VMMDIR/ar2/qmp.in" + holds "a failed start leaves no output FIFO" test ! -e "$VMMDIR/ar2/qmp.out" + holds "a failed start releases its lock" \ + flock -n "$VMMDIR/ar2" true +else + skip 5 "no qemu for the host architecture" +fi + +# A qemu that never opens the monitor does not die of its own accord, and +# it has written no pidfile to be found by. It is still vmm's own child. +# The stand-in does not exec, so it keeps the argv this looks for. +FAKEBIN=$WORK/fake-qemu-bin +FAKE=$FAKEBIN/qemu-system-$(uname -m) +mkdir -p "$FAKEBIN" +cat > "$FAKE" <<'EOF' +#!/bin/sh +sleep 5 +EOF +chmod +x "$FAKE" +"$VMM" create ar3 64M >/dev/null 2>&1 +out=$(PATH=$FAKEBIN:$PATH MONITOR_TIMEOUT=1 "$VMM" start ar3 2>&1) && got=0 || got=$? +if [ "$got" = 1 ]; then + ok "a start whose monitor never answers fails" +else + notok "a start whose monitor never answers fails" "exit $got: $out" +fi +left= +for cmdline in /proc/[0-9]*/cmdline; do + line= + IFS= read -r line 2>/dev/null < "$cmdline" || : + case $line in + *"-pidfile$VMMDIR/ar3/pid") + p=${cmdline#/proc/} + left="$left ${p%/cmdline}" + ;; + esac +done +if [ -z "$left" ]; then + ok "and kills the child it spawned" +else + notok "and kills the child it spawned" "still running:$left" + # shellcheck disable=SC2086 # a list of pids this loop collected + kill -9 $left 2>/dev/null || : +fi |