1b2a2aa5dSAndrew Jones############################################################################## 2b2a2aa5dSAndrew Jones# run_qemu translates the ambiguous exit status in Table1 to that in Table2. 3b2a2aa5dSAndrew Jones# Table3 simply documents the complete status table. 4b2a2aa5dSAndrew Jones# 5b2a2aa5dSAndrew Jones# Table1: Before fixup 6b2a2aa5dSAndrew Jones# -------------------- 7b2a2aa5dSAndrew Jones# 0 - Unexpected exit from QEMU (possible signal), or the unittest did 8b2a2aa5dSAndrew Jones# not use debug-exit 9b2a2aa5dSAndrew Jones# 1 - most likely unittest succeeded, or QEMU failed 10b2a2aa5dSAndrew Jones# 11b2a2aa5dSAndrew Jones# Table2: After fixup 12b2a2aa5dSAndrew Jones# ------------------- 13b2a2aa5dSAndrew Jones# 0 - Everything succeeded 14b2a2aa5dSAndrew Jones# 1 - most likely QEMU failed 15b2a2aa5dSAndrew Jones# 16b2a2aa5dSAndrew Jones# Table3: Complete table 17b2a2aa5dSAndrew Jones# ---------------------- 18b2a2aa5dSAndrew Jones# 0 - SUCCESS 19b2a2aa5dSAndrew Jones# 1 - most likely QEMU failed 20b2a2aa5dSAndrew Jones# 2 - most likely a run script failed 21b2a2aa5dSAndrew Jones# 3 - most likely the unittest failed 22fd149358SAndrew Jones# 124 - most likely the unittest timed out 23b2a2aa5dSAndrew Jones# 127 - most likely the unittest called abort() 24b2a2aa5dSAndrew Jones# 1..127 - FAILURE (could be QEMU, a run script, or the unittest) 25b2a2aa5dSAndrew Jones# >= 128 - Signal (signum = status - 128) 26b2a2aa5dSAndrew Jones############################################################################## 27b2a2aa5dSAndrew Jonesrun_qemu () 28b2a2aa5dSAndrew Jones{ 298c3f0d96SAndrew Jones local stdout errors ret sig 30b2a2aa5dSAndrew Jones 31b16df9eeSAndrew Jones initrd_create || return $? 32d76bf076SAndrew Jones echo -n "$@" 33b16df9eeSAndrew Jones [ "$ENVIRON_DEFAULT" = "yes" ] && echo -n " #" 348b13a5b5SRadim Krčmář echo " $INITRD" 358b13a5b5SRadim Krčmář 36f0ca153cSRadim Krčmář # stdout to {stdout}, stderr to $errors and stderr 37b2a2aa5dSAndrew Jones exec {stdout}>&1 388b13a5b5SRadim Krčmář errors=$("${@}" $INITRD </dev/null 2> >(tee /dev/stderr) > /dev/fd/$stdout) 39b2a2aa5dSAndrew Jones ret=$? 40b2a2aa5dSAndrew Jones exec {stdout}>&- 418727c886SAndrew Jones 428727c886SAndrew Jones [ $ret -eq 134 ] && echo "QEMU Aborted" >&2 43b2a2aa5dSAndrew Jones 44b2a2aa5dSAndrew Jones if [ "$errors" ]; then 45b2a2aa5dSAndrew Jones sig=$(grep 'terminating on signal' <<<"$errors") 46b2a2aa5dSAndrew Jones if [ "$sig" ]; then 47b2a2aa5dSAndrew Jones sig=$(sed 's/.*terminating on signal \([0-9][0-9]*\).*/\1/' <<<"$sig") 48b2a2aa5dSAndrew Jones fi 49b2a2aa5dSAndrew Jones fi 50b2a2aa5dSAndrew Jones 51b2a2aa5dSAndrew Jones if [ $ret -eq 0 ]; then 52b2a2aa5dSAndrew Jones # Some signals result in a zero return status, but the 53b2a2aa5dSAndrew Jones # error log tells the truth. 54b2a2aa5dSAndrew Jones if [ "$sig" ]; then 55b2a2aa5dSAndrew Jones ((ret=sig+128)) 56b2a2aa5dSAndrew Jones else 57b2a2aa5dSAndrew Jones # Exiting with zero (non-debugexit) is an error 58b2a2aa5dSAndrew Jones ret=1 59b2a2aa5dSAndrew Jones fi 60b2a2aa5dSAndrew Jones elif [ $ret -eq 1 ]; then 61b2a2aa5dSAndrew Jones # Even when ret==1 (unittest success) if we also got stderr 62b2a2aa5dSAndrew Jones # logs, then we assume a QEMU failure. Otherwise we translate 63b2a2aa5dSAndrew Jones # status of 1 to 0 (SUCCESS) 645bf124ffSNicholas Piggin if [ "$errors" ]; then 655bf124ffSNicholas Piggin if ! grep -qvi warning <<<"$errors" ; then 665bf124ffSNicholas Piggin ret=0 675bf124ffSNicholas Piggin fi 685bf124ffSNicholas Piggin else 69b2a2aa5dSAndrew Jones ret=0 70b2a2aa5dSAndrew Jones fi 71b2a2aa5dSAndrew Jones fi 72b2a2aa5dSAndrew Jones 73b2a2aa5dSAndrew Jones return $ret 74b2a2aa5dSAndrew Jones} 75fd149358SAndrew Jones 76e0a8391eSRadim Krčmářrun_qemu_status () 77e0a8391eSRadim Krčmář{ 78e0a8391eSRadim Krčmář local stdout ret 79e0a8391eSRadim Krčmář 80e0a8391eSRadim Krčmář exec {stdout}>&1 81e0a8391eSRadim Krčmář lines=$(run_qemu "$@" > >(tee /dev/fd/$stdout)) 82e0a8391eSRadim Krčmář ret=$? 83e0a8391eSRadim Krčmář exec {stdout}>&- 84e0a8391eSRadim Krčmář 85e0a8391eSRadim Krčmář if [ $ret -eq 1 ]; then 86a6e2b9e6SNicholas Piggin testret=$(grep '^EXIT: ' <<<"$lines" | head -n1 | sed 's/.*STATUS=\([0-9][0-9]*\).*/\1/') 87e0a8391eSRadim Krčmář if [ "$testret" ]; then 88e0a8391eSRadim Krčmář if [ $testret -eq 1 ]; then 89e0a8391eSRadim Krčmář ret=0 90e0a8391eSRadim Krčmář else 91e0a8391eSRadim Krčmář ret=$testret 92e0a8391eSRadim Krčmář fi 93e0a8391eSRadim Krčmář fi 94e0a8391eSRadim Krčmář fi 95e0a8391eSRadim Krčmář 96e0a8391eSRadim Krčmář return $ret 97e0a8391eSRadim Krčmář} 98e0a8391eSRadim Krčmář 99fd149358SAndrew Jonestimeout_cmd () 100fd149358SAndrew Jones{ 10115a12650SAndrew Jones local s 10215a12650SAndrew Jones 103fd149358SAndrew Jones if [ "$TIMEOUT" ] && [ "$TIMEOUT" != "0" ]; then 10415a12650SAndrew Jones if [ "$CONFIG_EFI" = 'y' ]; then 10515a12650SAndrew Jones s=${TIMEOUT: -1} 10615a12650SAndrew Jones if [ "$s" = 's' ]; then 10715a12650SAndrew Jones TIMEOUT=${TIMEOUT:0:-1} 10815a12650SAndrew Jones ((TIMEOUT += 10)) # Add 10 seconds for booting UEFI 10915a12650SAndrew Jones TIMEOUT="${TIMEOUT}s" 11015a12650SAndrew Jones fi 11115a12650SAndrew Jones fi 112fd149358SAndrew Jones echo "timeout -k 1s --foreground $TIMEOUT" 113fd149358SAndrew Jones fi 114fd149358SAndrew Jones} 11537abdda9SThomas Huth 11637abdda9SThomas Huthqmp () 11737abdda9SThomas Huth{ 118b508e114SJamie Iles echo '{ "execute": "qmp_capabilities" }{ "execute":' "$2" '}' | ncat -U $1 11937abdda9SThomas Huth} 12037abdda9SThomas Huth 1215f65d6f4SNico Boehrqmp_events () 1225f65d6f4SNico Boehr{ 1235f65d6f4SNico Boehr while ! test -S "$1"; do sleep 0.1; done 1245f65d6f4SNico Boehr echo '{ "execute": "qmp_capabilities" }{ "execute": "cont" }' | 1255f65d6f4SNico Boehr ncat --no-shutdown -U $1 | 1265f65d6f4SNico Boehr jq -c 'select(has("event"))' 1275f65d6f4SNico Boehr} 1285f65d6f4SNico Boehr 1294aadd216SNicholas Pigginfilter_quiet_msgs () 1304aadd216SNicholas Piggin{ 1314aadd216SNicholas Piggin grep -v "Now migrate the VM (quiet)" 1324aadd216SNicholas Piggin} 1334aadd216SNicholas Piggin 1344aadd216SNicholas Pigginseen_migrate_msg () 1354aadd216SNicholas Piggin{ 1364aadd216SNicholas Piggin grep -q -e "Now migrate the VM" < $1 1374aadd216SNicholas Piggin} 1384aadd216SNicholas Piggin 13937abdda9SThomas Huthrun_migration () 14037abdda9SThomas Huth{ 141b508e114SJamie Iles if ! command -v ncat >/dev/null 2>&1; then 142b508e114SJamie Iles echo "${FUNCNAME[0]} needs ncat (netcat)" >&2 1432176d963SThomas Huth return 77 14437abdda9SThomas Huth fi 14537abdda9SThomas Huth 14614ea7bdaSNicholas Piggin migcmdline=$@ 14714ea7bdaSNicholas Piggin 148af3484fcSNicholas Piggin trap 'trap - TERM ; kill 0 ; exit 2' INT TERM 149cd45aeb7SNicholas Piggin trap 'rm -f ${src_out} ${dst_out} ${src_outfifo} ${dst_outfifo} ${dst_incoming} ${src_qmp} ${dst_qmp} ${dst_infifo}' RETURN EXIT 150af3484fcSNicholas Piggin 151cd45aeb7SNicholas Piggin dst_incoming=$(mktemp -u -t mig-helper-socket-incoming.XXXXXXXXXX) 152cd45aeb7SNicholas Piggin src_out=$(mktemp -t mig-helper-stdout1.XXXXXXXXXX) 153cd45aeb7SNicholas Piggin src_outfifo=$(mktemp -u -t mig-helper-fifo-stdout1.XXXXXXXXXX) 154cd45aeb7SNicholas Piggin dst_out=$(mktemp -t mig-helper-stdout2.XXXXXXXXXX) 155cd45aeb7SNicholas Piggin dst_outfifo=$(mktemp -u -t mig-helper-fifo-stdout2.XXXXXXXXXX) 156cd45aeb7SNicholas Piggin src_qmp=$(mktemp -u -t mig-helper-qmp1.XXXXXXXXXX) 157cd45aeb7SNicholas Piggin dst_qmp=$(mktemp -u -t mig-helper-qmp2.XXXXXXXXXX) 158cd45aeb7SNicholas Piggin dst_infifo=$(mktemp -u -t mig-helper-fifo-stdin.XXXXXXXXXX) 159cd45aeb7SNicholas Piggin src_qmpout=/dev/null 160cd45aeb7SNicholas Piggin dst_qmpout=/dev/null 16137abdda9SThomas Huth 162cd45aeb7SNicholas Piggin mkfifo ${src_outfifo} 163cd45aeb7SNicholas Piggin mkfifo ${dst_outfifo} 16414ea7bdaSNicholas Piggin 165*49bbfc65SNicholas Piggin # Holding both ends of the input fifo open prevents opens from 166*49bbfc65SNicholas Piggin # blocking and readers getting EOF when a writer closes it. 167*49bbfc65SNicholas Piggin mkfifo ${dst_infifo} 168*49bbfc65SNicholas Piggin exec {dst_infifo_fd}<>${dst_infifo} 169*49bbfc65SNicholas Piggin 17014ea7bdaSNicholas Piggin eval "$migcmdline" \ 171cd45aeb7SNicholas Piggin -chardev socket,id=mon,path=${src_qmp},server=on,wait=off \ 172cd45aeb7SNicholas Piggin -mon chardev=mon,mode=control > ${src_outfifo} & 173659557c0SNicholas Piggin live_pid=$! 1744aadd216SNicholas Piggin cat ${src_outfifo} | tee ${src_out} | filter_quiet_msgs & 17537abdda9SThomas Huth 17614ea7bdaSNicholas Piggin # Start the first destination QEMU machine in advance of the test 17714ea7bdaSNicholas Piggin # reaching the migration point, since we expect at least one migration. 17814ea7bdaSNicholas Piggin # Then destination machines are started after the test outputs 17914ea7bdaSNicholas Piggin # subsequent "Now migrate the VM" messages. 18014ea7bdaSNicholas Piggin do_migration || return $? 18137abdda9SThomas Huth 18214ea7bdaSNicholas Piggin while ps -p ${live_pid} > /dev/null ; do 18314ea7bdaSNicholas Piggin # Wait for test exit or further migration messages. 1844aadd216SNicholas Piggin if ! seen_migrate_msg ${src_out} ; then 18514ea7bdaSNicholas Piggin sleep 0.1 18614ea7bdaSNicholas Piggin else 18714ea7bdaSNicholas Piggin do_migration || return $? 18814ea7bdaSNicholas Piggin fi 18914ea7bdaSNicholas Piggin done 19014ea7bdaSNicholas Piggin 19114ea7bdaSNicholas Piggin wait ${live_pid} 19214ea7bdaSNicholas Piggin ret=$? 19314ea7bdaSNicholas Piggin 19414ea7bdaSNicholas Piggin while (( $(jobs -r | wc -l) > 0 )); do 19514ea7bdaSNicholas Piggin sleep 0.1 19614ea7bdaSNicholas Piggin done 19714ea7bdaSNicholas Piggin 19814ea7bdaSNicholas Piggin return $ret 19914ea7bdaSNicholas Piggin} 20014ea7bdaSNicholas Piggin 20114ea7bdaSNicholas Piggindo_migration () 20214ea7bdaSNicholas Piggin{ 20314ea7bdaSNicholas Piggin eval "$migcmdline" \ 204cd45aeb7SNicholas Piggin -chardev socket,id=mon,path=${dst_qmp},server=on,wait=off \ 205cd45aeb7SNicholas Piggin -mon chardev=mon,mode=control -incoming unix:${dst_incoming} \ 206*49bbfc65SNicholas Piggin < ${dst_infifo} > ${dst_outfifo} & 20714ea7bdaSNicholas Piggin incoming_pid=$! 2084aadd216SNicholas Piggin cat ${dst_outfifo} | tee ${dst_out} | filter_quiet_msgs & 20914ea7bdaSNicholas Piggin 21014ea7bdaSNicholas Piggin # The test must prompt the user to migrate, so wait for the 2114aadd216SNicholas Piggin # "Now migrate VM" or similar console message. 2124aadd216SNicholas Piggin while ! seen_migrate_msg ${src_out} ; do 213bfe5d7d0SNicholas Piggin if ! ps -p ${live_pid} > /dev/null ; then 214bfe5d7d0SNicholas Piggin echo "ERROR: Test exit before migration point." >&2 215cd45aeb7SNicholas Piggin echo > ${dst_infifo} 216cd45aeb7SNicholas Piggin qmp ${src_qmp} '"quit"'> ${src_qmpout} 2>/dev/null 217cd45aeb7SNicholas Piggin qmp ${dst_qmp} '"quit"'> ${dst_qmpout} 2>/dev/null 218bfe5d7d0SNicholas Piggin return 3 219bfe5d7d0SNicholas Piggin fi 22014ea7bdaSNicholas Piggin sleep 0.1 22137abdda9SThomas Huth done 22237abdda9SThomas Huth 223659557c0SNicholas Piggin # Wait until the destination has created the incoming and qmp sockets 224cd45aeb7SNicholas Piggin while ! [ -S ${dst_incoming} ] ; do sleep 0.1 ; done 225cd45aeb7SNicholas Piggin while ! [ -S ${dst_qmp} ] ; do sleep 0.1 ; done 226659557c0SNicholas Piggin 227cd45aeb7SNicholas Piggin qmp ${src_qmp} '"migrate", "arguments": { "uri": "unix:'${dst_incoming}'" }' > ${src_qmpout} 22837abdda9SThomas Huth 22937abdda9SThomas Huth # Wait for the migration to complete 23009e55926SNicholas Piggin migstatus=$(qmp ${src_qmp} '"query-migrate"' | grep return) 23137abdda9SThomas Huth while ! grep -q '"completed"' <<<"$migstatus" ; do 23214ea7bdaSNicholas Piggin sleep 0.1 23309e55926SNicholas Piggin if ! migstatus=$(qmp ${src_qmp} '"query-migrate"'); then 23409e8c119SNico Boehr echo "ERROR: Querying migration state failed." >&2 235cd45aeb7SNicholas Piggin echo > ${dst_infifo} 236cd45aeb7SNicholas Piggin qmp ${dst_qmp} '"quit"'> ${dst_qmpout} 2>/dev/null 23709e8c119SNico Boehr return 2 23809e8c119SNico Boehr fi 23909e55926SNicholas Piggin migstatus=$(grep return <<<"$migstatus") 24037abdda9SThomas Huth if grep -q '"failed"' <<<"$migstatus"; then 24137abdda9SThomas Huth echo "ERROR: Migration failed." >&2 242cd45aeb7SNicholas Piggin echo > ${dst_infifo} 243cd45aeb7SNicholas Piggin qmp ${src_qmp} '"quit"'> ${src_qmpout} 2>/dev/null 244cd45aeb7SNicholas Piggin qmp ${dst_qmp} '"quit"'> ${dst_qmpout} 2>/dev/null 2459806f62dSAndrew Jones return 2 24637abdda9SThomas Huth fi 24737abdda9SThomas Huth done 24814ea7bdaSNicholas Piggin 249cd45aeb7SNicholas Piggin qmp ${src_qmp} '"quit"'> ${src_qmpout} 2>/dev/null 25014ea7bdaSNicholas Piggin 25114ea7bdaSNicholas Piggin # keypress to dst so getchar completes and test continues 252cd45aeb7SNicholas Piggin echo > ${dst_infifo} 25314ea7bdaSNicholas Piggin 2544b54f4faSNico Boehr # Wait for the incoming socket being removed, ready for next destination 2554b54f4faSNico Boehr while [ -S ${dst_incoming} ] ; do sleep 0.1 ; done 25614ea7bdaSNicholas Piggin 25714ea7bdaSNicholas Piggin wait ${live_pid} 2589806f62dSAndrew Jones ret=$? 259394d1421SAndrew Jones 260cd45aeb7SNicholas Piggin # Now flip the variables because destination machine becomes source 261cd45aeb7SNicholas Piggin # for the next migration. 26214ea7bdaSNicholas Piggin live_pid=${incoming_pid} 263cd45aeb7SNicholas Piggin tmp=${src_out} 264cd45aeb7SNicholas Piggin src_out=${dst_out} 265cd45aeb7SNicholas Piggin dst_out=${tmp} 266cd45aeb7SNicholas Piggin tmp=${src_outfifo} 267cd45aeb7SNicholas Piggin src_outfifo=${dst_outfifo} 268cd45aeb7SNicholas Piggin dst_outfifo=${tmp} 269cd45aeb7SNicholas Piggin tmp=${src_qmp} 270cd45aeb7SNicholas Piggin src_qmp=${dst_qmp} 271cd45aeb7SNicholas Piggin dst_qmp=${tmp} 272394d1421SAndrew Jones 2739806f62dSAndrew Jones return $ret 27437abdda9SThomas Huth} 27537abdda9SThomas Huth 2765f65d6f4SNico Boehrrun_panic () 2775f65d6f4SNico Boehr{ 2785f65d6f4SNico Boehr if ! command -v ncat >/dev/null 2>&1; then 2795f65d6f4SNico Boehr echo "${FUNCNAME[0]} needs ncat (netcat)" >&2 2805f65d6f4SNico Boehr return 77 2815f65d6f4SNico Boehr fi 2825f65d6f4SNico Boehr 2835f65d6f4SNico Boehr if ! command -v jq >/dev/null 2>&1; then 2845f65d6f4SNico Boehr echo "${FUNCNAME[0]} needs jq" >&2 2855f65d6f4SNico Boehr return 77 2865f65d6f4SNico Boehr fi 2875f65d6f4SNico Boehr 288af3484fcSNicholas Piggin trap 'trap - TERM ; kill 0 ; exit 2' INT TERM 2895f65d6f4SNico Boehr trap 'rm -f ${qmp}' RETURN EXIT 2905f65d6f4SNico Boehr 291af3484fcSNicholas Piggin qmp=$(mktemp -u -t panic-qmp.XXXXXXXXXX) 292af3484fcSNicholas Piggin 2935f65d6f4SNico Boehr # start VM stopped so we don't miss any events 294cd45aeb7SNicholas Piggin eval "$@" -chardev socket,id=mon,path=${qmp},server=on,wait=off \ 295cd45aeb7SNicholas Piggin -mon chardev=mon,mode=control -S & 2965f65d6f4SNico Boehr 2975f65d6f4SNico Boehr panic_event_count=$(qmp_events ${qmp} | jq -c 'select(.event == "GUEST_PANICKED")' | wc -l) 2985f65d6f4SNico Boehr if [ "$panic_event_count" -lt 1 ]; then 2995f65d6f4SNico Boehr echo "FAIL: guest did not panic" 3005f65d6f4SNico Boehr ret=3 3015f65d6f4SNico Boehr else 3025f65d6f4SNico Boehr # some QEMU versions report multiple panic events 3035f65d6f4SNico Boehr echo "PASS: guest panicked" 3045f65d6f4SNico Boehr ret=1 3055f65d6f4SNico Boehr fi 3065f65d6f4SNico Boehr 3075f65d6f4SNico Boehr return $ret 3085f65d6f4SNico Boehr} 3095f65d6f4SNico Boehr 31037abdda9SThomas Huthmigration_cmd () 31137abdda9SThomas Huth{ 31237abdda9SThomas Huth if [ "$MIGRATION" = "yes" ]; then 31337abdda9SThomas Huth echo "run_migration" 31437abdda9SThomas Huth fi 31537abdda9SThomas Huth} 316531326aeSBalamuruhan S 3175f65d6f4SNico Boehrpanic_cmd () 3185f65d6f4SNico Boehr{ 3195f65d6f4SNico Boehr if [ "$PANIC" = "yes" ]; then 3205f65d6f4SNico Boehr echo "run_panic" 3215f65d6f4SNico Boehr fi 3225f65d6f4SNico Boehr} 3235f65d6f4SNico Boehr 324531326aeSBalamuruhan Ssearch_qemu_binary () 325531326aeSBalamuruhan S{ 326531326aeSBalamuruhan S local save_path=$PATH 327232f404aSAndrew Jones local qemucmd qemu 328232f404aSAndrew Jones 329ee5a8a1aSAndrew Jones : "${QEMU_ARCH:=$ARCH_NAME}" 330ee5a8a1aSAndrew Jones 331531326aeSBalamuruhan S export PATH=$PATH:/usr/libexec 332ee5a8a1aSAndrew Jones for qemucmd in ${QEMU:-qemu-system-$QEMU_ARCH qemu-kvm}; do 333232f404aSAndrew Jones if $qemucmd --help 2>/dev/null | grep -q 'QEMU'; then 334232f404aSAndrew Jones qemu="$qemucmd" 335531326aeSBalamuruhan S break 336531326aeSBalamuruhan S fi 337531326aeSBalamuruhan S done 338531326aeSBalamuruhan S 339232f404aSAndrew Jones if [ -z "$qemu" ]; then 340fcf4e0d9SRadim Krčmář echo "A QEMU binary was not found." >&2 341fcf4e0d9SRadim Krčmář echo "You can set a custom location by using the QEMU=<path> environment variable." >&2 342fcf4e0d9SRadim Krčmář return 2 343531326aeSBalamuruhan S fi 344232f404aSAndrew Jones command -v $qemu 345531326aeSBalamuruhan S export PATH=$save_path 346531326aeSBalamuruhan S} 3474da0bc9aSAndrew Jones 348c8764266SNicholas Piggininitrd_cleanup () 349c8764266SNicholas Piggin{ 350c8764266SNicholas Piggin rm -f $KVM_UNIT_TESTS_ENV 351c8764266SNicholas Piggin if [ "$KVM_UNIT_TESTS_ENV_OLD" ]; then 352c8764266SNicholas Piggin export KVM_UNIT_TESTS_ENV="$KVM_UNIT_TESTS_ENV_OLD" 353c8764266SNicholas Piggin else 354c8764266SNicholas Piggin unset KVM_UNIT_TESTS_ENV 355c8764266SNicholas Piggin fi 356c8764266SNicholas Piggin unset KVM_UNIT_TESTS_ENV_OLD 357c8764266SNicholas Piggin} 358c8764266SNicholas Piggin 3594da0bc9aSAndrew Jonesinitrd_create () 3604da0bc9aSAndrew Jones{ 361b16df9eeSAndrew Jones if [ "$ENVIRON_DEFAULT" = "yes" ]; then 362c8764266SNicholas Piggin trap_exit_push 'initrd_cleanup' 363b16df9eeSAndrew Jones [ -f "$KVM_UNIT_TESTS_ENV" ] && export KVM_UNIT_TESTS_ENV_OLD="$KVM_UNIT_TESTS_ENV" 364b16df9eeSAndrew Jones export KVM_UNIT_TESTS_ENV=$(mktemp) 365b16df9eeSAndrew Jones env_params 366b16df9eeSAndrew Jones env_file 367b16df9eeSAndrew Jones env_errata || return $? 368b16df9eeSAndrew Jones fi 3698b13a5b5SRadim Krčmář 3704da0bc9aSAndrew Jones unset INITRD 37163dd93ecSAndrew Jones [ -f "$KVM_UNIT_TESTS_ENV" ] && INITRD="-initrd $KVM_UNIT_TESTS_ENV" 3728b13a5b5SRadim Krčmář 373b16df9eeSAndrew Jones return 0 3744da0bc9aSAndrew Jones} 3758ec99569SAndrew Jones 376b16df9eeSAndrew Jonesenv_add_params () 3778ec99569SAndrew Jones{ 378b16df9eeSAndrew Jones local p 3798ec99569SAndrew Jones 380b16df9eeSAndrew Jones for p in "$@"; do 381b16df9eeSAndrew Jones if eval test -v $p; then 382b16df9eeSAndrew Jones eval export "$p" 383b16df9eeSAndrew Jones else 384b16df9eeSAndrew Jones eval export "$p=" 385b16df9eeSAndrew Jones fi 386b16df9eeSAndrew Jones grep "^$p=" <(env) >>$KVM_UNIT_TESTS_ENV 3878ec99569SAndrew Jones done 388b16df9eeSAndrew Jones} 389b16df9eeSAndrew Jones 390b16df9eeSAndrew Jonesenv_params () 391b16df9eeSAndrew Jones{ 392b16df9eeSAndrew Jones local qemu have_qemu 393b16df9eeSAndrew Jones local _ rest 394b16df9eeSAndrew Jones 395b16df9eeSAndrew Jones qemu=$(search_qemu_binary) && have_qemu=1 396b16df9eeSAndrew Jones 397b16df9eeSAndrew Jones if [ "$have_qemu" ]; then 398b16df9eeSAndrew Jones if [ -n "$ACCEL" ] || [ -n "$QEMU_ACCEL" ]; then 399b16df9eeSAndrew Jones [ -n "$ACCEL" ] && QEMU_ACCEL=$ACCEL 400b16df9eeSAndrew Jones fi 401b16df9eeSAndrew Jones QEMU_VERSION_STRING="$($qemu -h | head -1)" 402b16df9eeSAndrew Jones IFS='[ .]' read -r _ _ _ QEMU_MAJOR QEMU_MINOR QEMU_MICRO rest <<<"$QEMU_VERSION_STRING" 403b16df9eeSAndrew Jones fi 404b16df9eeSAndrew Jones env_add_params QEMU_ACCEL QEMU_VERSION_STRING QEMU_MAJOR QEMU_MINOR QEMU_MICRO 405b16df9eeSAndrew Jones 406b16df9eeSAndrew Jones KERNEL_VERSION_STRING=$(uname -r) 407b16df9eeSAndrew Jones IFS=. read -r KERNEL_VERSION KERNEL_PATCHLEVEL rest <<<"$KERNEL_VERSION_STRING" 408b16df9eeSAndrew Jones IFS=- read -r KERNEL_SUBLEVEL KERNEL_EXTRAVERSION <<<"$rest" 409b16df9eeSAndrew Jones KERNEL_SUBLEVEL=${KERNEL_SUBLEVEL%%[!0-9]*} 410b16df9eeSAndrew Jones KERNEL_EXTRAVERSION=${KERNEL_EXTRAVERSION%%[!0-9]*} 411b16df9eeSAndrew Jones ! [[ $KERNEL_SUBLEVEL =~ ^[0-9]+$ ]] && unset $KERNEL_SUBLEVEL 412b16df9eeSAndrew Jones ! [[ $KERNEL_EXTRAVERSION =~ ^[0-9]+$ ]] && unset $KERNEL_EXTRAVERSION 413b16df9eeSAndrew Jones env_add_params KERNEL_VERSION_STRING KERNEL_VERSION KERNEL_PATCHLEVEL KERNEL_SUBLEVEL KERNEL_EXTRAVERSION 414b16df9eeSAndrew Jones} 415b16df9eeSAndrew Jones 416b16df9eeSAndrew Jonesenv_file () 417b16df9eeSAndrew Jones{ 418b16df9eeSAndrew Jones local line var 419b16df9eeSAndrew Jones 420b16df9eeSAndrew Jones [ ! -f "$KVM_UNIT_TESTS_ENV_OLD" ] && return 421b16df9eeSAndrew Jones 422ec11048dSNicholas Piggin grep -E '^[[:blank:]]*[[:alpha:]_][[:alnum:]_]*=' "$KVM_UNIT_TESTS_ENV_OLD" | while IFS= read -r line ; do 423b16df9eeSAndrew Jones var=${line%%=*} 424b16df9eeSAndrew Jones if ! grep -q "^$var=" $KVM_UNIT_TESTS_ENV; then 425b16df9eeSAndrew Jones eval export "$line" 426b16df9eeSAndrew Jones grep "^$var=" <(env) >>$KVM_UNIT_TESTS_ENV 427b16df9eeSAndrew Jones fi 428b16df9eeSAndrew Jones done 429b16df9eeSAndrew Jones} 430b16df9eeSAndrew Jones 431b16df9eeSAndrew Jonesenv_errata () 432b16df9eeSAndrew Jones{ 433d50fa5a8SNicholas Piggin local new_env 434d50fa5a8SNicholas Piggin 435ec2f5147SAlex Bennée if [ "$ACCEL" = "tcg" ]; then 436ec2f5147SAlex Bennée export "ERRATA_FORCE=y" 437ec2f5147SAlex Bennée elif [ "$ERRATATXT" ] && [ ! -f "$ERRATATXT" ]; then 438b16df9eeSAndrew Jones echo "$ERRATATXT not found. (ERRATATXT=$ERRATATXT)" >&2 439b16df9eeSAndrew Jones return 2 440b16df9eeSAndrew Jones elif [ "$ERRATATXT" ]; then 44170fcb64bSAndrew Jones env_generate_errata 4428ec99569SAndrew Jones fi 443d50fa5a8SNicholas Piggin new_env=$(sort <(env | grep '^ERRATA_') <(grep '^ERRATA_' $KVM_UNIT_TESTS_ENV) | uniq -u) 444d50fa5a8SNicholas Piggin echo "$new_env" >>$KVM_UNIT_TESTS_ENV 4458ec99569SAndrew Jones} 4468ec99569SAndrew Jones 44770fcb64bSAndrew Jonesenv_generate_errata () 44870fcb64bSAndrew Jones{ 44912a4328eSAndrew Jones local line commit minver errata rest v p s x have 45070fcb64bSAndrew Jones 4511ea4709cSAndrew Jones for line in $(grep -v '^#' "$ERRATATXT" | tr -d '[:blank:]' | cut -d: -f1,2); do 45270fcb64bSAndrew Jones commit=${line%:*} 45370fcb64bSAndrew Jones minver=${line#*:} 45470fcb64bSAndrew Jones 455171aa3a2SPeter Shier test -z "$commit" && continue 45670fcb64bSAndrew Jones errata="ERRATA_$commit" 457d1bc9395SAndrew Jones [ -n "${!errata}" ] && continue 45870fcb64bSAndrew Jones 459d38b111bSJim Mattson IFS=. read -r v p rest <<<"$minver" 460d38b111bSJim Mattson IFS=- read -r s x <<<"$rest" 46170fcb64bSAndrew Jones s=${s%%[!0-9]*} 46212a4328eSAndrew Jones x=${x%%[!0-9]*} 46312a4328eSAndrew Jones 46412a4328eSAndrew Jones if ! [[ $v =~ ^[0-9]+$ ]] || ! [[ $p =~ ^[0-9]+$ ]]; then 46512a4328eSAndrew Jones echo "Bad minimum kernel version in $ERRATATXT, $minver" 4669806f62dSAndrew Jones return 2 46712a4328eSAndrew Jones fi 46812a4328eSAndrew Jones ! [[ $s =~ ^[0-9]+$ ]] && unset $s 46912a4328eSAndrew Jones ! [[ $x =~ ^[0-9]+$ ]] && unset $x 47070fcb64bSAndrew Jones 471b16df9eeSAndrew Jones if (( $KERNEL_VERSION > $v || 472b16df9eeSAndrew Jones ($KERNEL_VERSION == $v && $KERNEL_PATCHLEVEL > $p) )); then 47370fcb64bSAndrew Jones have=y 474b16df9eeSAndrew Jones elif (( $KERNEL_VERSION == $v && $KERNEL_PATCHLEVEL == $p )); then 475b16df9eeSAndrew Jones if [ "$KERNEL_SUBLEVEL" ] && [ "$s" ]; then 476b16df9eeSAndrew Jones if (( $KERNEL_SUBLEVEL > $s )); then 47770fcb64bSAndrew Jones have=y 478b16df9eeSAndrew Jones elif (( $KERNEL_SUBLEVEL == $s )); then 479b16df9eeSAndrew Jones if [ "$KERNEL_EXTRAVERSION" ] && [ "$x" ]; then 480b16df9eeSAndrew Jones if (( $KERNEL_EXTRAVERSION >= $x )); then 48112a4328eSAndrew Jones have=y 48212a4328eSAndrew Jones else 48312a4328eSAndrew Jones have=n 48412a4328eSAndrew Jones fi 48512a4328eSAndrew Jones elif [ "$x" ] && (( $x != 0 )); then 48612a4328eSAndrew Jones have=n 48712a4328eSAndrew Jones else 48812a4328eSAndrew Jones have=y 48912a4328eSAndrew Jones fi 49070fcb64bSAndrew Jones else 49170fcb64bSAndrew Jones have=n 49270fcb64bSAndrew Jones fi 49370fcb64bSAndrew Jones elif [ "$s" ] && (( $s != 0 )); then 49470fcb64bSAndrew Jones have=n 49570fcb64bSAndrew Jones else 49670fcb64bSAndrew Jones have=y 49770fcb64bSAndrew Jones fi 49870fcb64bSAndrew Jones else 49970fcb64bSAndrew Jones have=n 50070fcb64bSAndrew Jones fi 50170fcb64bSAndrew Jones eval export "$errata=$have" 50270fcb64bSAndrew Jones done 50370fcb64bSAndrew Jones} 50470fcb64bSAndrew Jones 5058ec99569SAndrew Jonestrap_exit_push () 5068ec99569SAndrew Jones{ 5078ec99569SAndrew Jones local old_exit=$(trap -p EXIT | sed "s/^[^']*'//;s/'[^']*$//") 5088ec99569SAndrew Jones trap -- "$1; $old_exit" EXIT 5098ec99569SAndrew Jones} 510f4d99928SRadim Krčmář 511f4d99928SRadim Krčmářkvm_available () 512f4d99928SRadim Krčmář{ 513f4d99928SRadim Krčmář [ -c /dev/kvm ] || 514f4d99928SRadim Krčmář return 1 515f4d99928SRadim Krčmář 516f4d99928SRadim Krčmář [ "$HOST" = "$ARCH_NAME" ] || 517d76bf076SAndrew Jones ( [ "$HOST" = aarch64 ] && [ "$ARCH" = arm ] ) || 518d76bf076SAndrew Jones ( [ "$HOST" = x86_64 ] && [ "$ARCH" = i386 ] ) 519f4d99928SRadim Krčmář} 520f4d99928SRadim Krčmář 5217edd698eSRoman Bolshakovhvf_available () 5227edd698eSRoman Bolshakov{ 5237edd698eSRoman Bolshakov [ "$(sysctl -n kern.hv_support 2>/dev/null)" = "1" ] || return 1 5247edd698eSRoman Bolshakov [ "$HOST" = "$ARCH_NAME" ] || 5257edd698eSRoman Bolshakov ( [ "$HOST" = x86_64 ] && [ "$ARCH" = i386 ] ) 5267edd698eSRoman Bolshakov} 5277edd698eSRoman Bolshakov 52801e047d0SGavin Shanset_qemu_accelerator () 529f4d99928SRadim Krčmář{ 53001e047d0SGavin Shan ACCEL_PROPS=${ACCEL#"${ACCEL%%,*}"} 53101e047d0SGavin Shan ACCEL=${ACCEL%%,*} 53201e047d0SGavin Shan 533f4d99928SRadim Krčmář if [ "$ACCEL" = "kvm" ] && ! kvm_available; then 534f4d99928SRadim Krčmář echo "KVM is needed, but not available on this host" >&2 535f4d99928SRadim Krčmář return 2 536f4d99928SRadim Krčmář fi 5377edd698eSRoman Bolshakov if [ "$ACCEL" = "hvf" ] && ! hvf_available; then 5387edd698eSRoman Bolshakov echo "HVF is needed, but not available on this host" >&2 5397edd698eSRoman Bolshakov return 2 5407edd698eSRoman Bolshakov fi 541f4d99928SRadim Krčmář 54201e047d0SGavin Shan if [ -z "$ACCEL" ]; then 54301e047d0SGavin Shan if kvm_available; then 54401e047d0SGavin Shan ACCEL="kvm" 5457edd698eSRoman Bolshakov elif hvf_available; then 54601e047d0SGavin Shan ACCEL="hvf" 547f4d99928SRadim Krčmář else 54801e047d0SGavin Shan ACCEL="tcg" 549f4d99928SRadim Krčmář fi 55001e047d0SGavin Shan fi 55101e047d0SGavin Shan 55201e047d0SGavin Shan return 0 553f4d99928SRadim Krčmář} 554