blob: 2f604519f8121a6ffc9075f437cc1aaf7b1a2084 (
plain) (
blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
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
|