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 318b13a5b5SRadim Krčmář echo -n $@ 328b13a5b5SRadim Krčmář initrd_create && 338b13a5b5SRadim Krčmář 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) 64a51bab13SRadim Krčmář if [ -z "$(echo "$errors" | grep -vi warning)" ]; then 65b2a2aa5dSAndrew Jones ret=0 66b2a2aa5dSAndrew Jones fi 67b2a2aa5dSAndrew Jones fi 68b2a2aa5dSAndrew Jones 69b2a2aa5dSAndrew Jones return $ret 70b2a2aa5dSAndrew Jones} 71fd149358SAndrew Jones 72e0a8391eSRadim Krčmářrun_qemu_status () 73e0a8391eSRadim Krčmář{ 74e0a8391eSRadim Krčmář local stdout ret 75e0a8391eSRadim Krčmář 76e0a8391eSRadim Krčmář exec {stdout}>&1 77e0a8391eSRadim Krčmář lines=$(run_qemu "$@" > >(tee /dev/fd/$stdout)) 78e0a8391eSRadim Krčmář ret=$? 79e0a8391eSRadim Krčmář exec {stdout}>&- 80e0a8391eSRadim Krčmář 81e0a8391eSRadim Krčmář if [ $ret -eq 1 ]; then 82e0a8391eSRadim Krčmář testret=$(grep '^EXIT: ' <<<"$lines" | sed 's/.*STATUS=\([0-9][0-9]*\).*/\1/') 83e0a8391eSRadim Krčmář if [ "$testret" ]; then 84e0a8391eSRadim Krčmář if [ $testret -eq 1 ]; then 85e0a8391eSRadim Krčmář ret=0 86e0a8391eSRadim Krčmář else 87e0a8391eSRadim Krčmář ret=$testret 88e0a8391eSRadim Krčmář fi 89e0a8391eSRadim Krčmář fi 90e0a8391eSRadim Krčmář fi 91e0a8391eSRadim Krčmář 92e0a8391eSRadim Krčmář return $ret 93e0a8391eSRadim Krčmář} 94e0a8391eSRadim Krčmář 95fd149358SAndrew Jonestimeout_cmd () 96fd149358SAndrew Jones{ 97fd149358SAndrew Jones if [ "$TIMEOUT" ] && [ "$TIMEOUT" != "0" ]; then 98fd149358SAndrew Jones echo "timeout -k 1s --foreground $TIMEOUT" 99fd149358SAndrew Jones fi 100fd149358SAndrew Jones} 10137abdda9SThomas Huth 10237abdda9SThomas Huthqmp () 10337abdda9SThomas Huth{ 10437abdda9SThomas Huth echo '{ "execute": "qmp_capabilities" }{ "execute":' "$2" '}' | nc -U $1 10537abdda9SThomas Huth} 10637abdda9SThomas Huth 10737abdda9SThomas Huthrun_migration () 10837abdda9SThomas Huth{ 10937abdda9SThomas Huth if ! command -v nc >/dev/null 2>&1; then 11037abdda9SThomas Huth echo "$FUNCNAME needs nc (netcat)" >&2 11137abdda9SThomas Huth exit 2 11237abdda9SThomas Huth fi 11337abdda9SThomas Huth 11437abdda9SThomas Huth qemu=$1 11537abdda9SThomas Huth shift 11637abdda9SThomas Huth 11737abdda9SThomas Huth migsock=`mktemp -u -t mig-helper-socket.XXXXXXXXXX` 11837abdda9SThomas Huth migout1=`mktemp -t mig-helper-stdout1.XXXXXXXXXX` 11937abdda9SThomas Huth qmp1=`mktemp -u -t mig-helper-qmp1.XXXXXXXXXX` 12037abdda9SThomas Huth qmp2=`mktemp -u -t mig-helper-qmp2.XXXXXXXXXX` 12137abdda9SThomas Huth qmpout1=/dev/null 12237abdda9SThomas Huth qmpout2=/dev/null 12337abdda9SThomas Huth 12437abdda9SThomas Huth trap 'rm -f ${migout1} ${migsock} ${qmp1} ${qmp2}' EXIT 12537abdda9SThomas Huth 12637abdda9SThomas Huth $qemu "$@" -chardev socket,id=mon1,path=${qmp1},server,nowait \ 12737abdda9SThomas Huth -mon chardev=mon1,mode=control | tee ${migout1} & 12837abdda9SThomas Huth 12937abdda9SThomas Huth $qemu "$@" -chardev socket,id=mon2,path=${qmp2},server,nowait \ 13037abdda9SThomas Huth -mon chardev=mon2,mode=control -incoming unix:${migsock} & 13137abdda9SThomas Huth 13237abdda9SThomas Huth # The test must prompt the user to migrate, so wait for the "migrate" keyword 13337abdda9SThomas Huth while ! grep -q -i "migrate" < ${migout1} ; do 13437abdda9SThomas Huth sleep 1 13537abdda9SThomas Huth done 13637abdda9SThomas Huth 13737abdda9SThomas Huth qmp ${qmp1} '"migrate", "arguments": { "uri": "unix:'${migsock}'" }' > ${qmpout1} 13837abdda9SThomas Huth 13937abdda9SThomas Huth # Wait for the migration to complete 14037abdda9SThomas Huth migstatus=`qmp ${qmp1} '"query-migrate"' | grep return` 14137abdda9SThomas Huth while ! grep -q '"completed"' <<<"$migstatus" ; do 14237abdda9SThomas Huth sleep 1 14337abdda9SThomas Huth migstatus=`qmp ${qmp1} '"query-migrate"' | grep return` 14437abdda9SThomas Huth if grep -q '"failed"' <<<"$migstatus" ; then 14537abdda9SThomas Huth echo "ERROR: Migration failed." >&2 14637abdda9SThomas Huth qmp ${qmp1} '"quit"'> ${qmpout1} 2>/dev/null 14737abdda9SThomas Huth qmp ${qmp2} '"quit"'> ${qmpout2} 2>/dev/null 14837abdda9SThomas Huth exit 2 14937abdda9SThomas Huth fi 15037abdda9SThomas Huth done 15137abdda9SThomas Huth qmp ${qmp1} '"quit"'> ${qmpout1} 2>/dev/null 15237abdda9SThomas Huth 15337abdda9SThomas Huth qmp ${qmp2} '"inject-nmi"'> ${qmpout2} 15437abdda9SThomas Huth 15537abdda9SThomas Huth wait 15637abdda9SThomas Huth} 15737abdda9SThomas Huth 15837abdda9SThomas Huthmigration_cmd () 15937abdda9SThomas Huth{ 16037abdda9SThomas Huth if [ "$MIGRATION" = "yes" ]; then 16137abdda9SThomas Huth echo "run_migration" 16237abdda9SThomas Huth fi 16337abdda9SThomas Huth} 164531326aeSBalamuruhan S 165531326aeSBalamuruhan Ssearch_qemu_binary () 166531326aeSBalamuruhan S{ 167531326aeSBalamuruhan S local save_path=$PATH 168232f404aSAndrew Jones local qemucmd qemu 169232f404aSAndrew Jones 170531326aeSBalamuruhan S export PATH=$PATH:/usr/libexec 171232f404aSAndrew Jones for qemucmd in ${QEMU:-qemu-system-$ARCH_NAME qemu-kvm}; do 172232f404aSAndrew Jones if $qemucmd --help 2>/dev/null | grep -q 'QEMU'; then 173232f404aSAndrew Jones qemu="$qemucmd" 174531326aeSBalamuruhan S break 175531326aeSBalamuruhan S fi 176531326aeSBalamuruhan S done 177531326aeSBalamuruhan S 178232f404aSAndrew Jones if [ -z "$qemu" ]; then 179fcf4e0d9SRadim Krčmář echo "A QEMU binary was not found." >&2 180fcf4e0d9SRadim Krčmář echo "You can set a custom location by using the QEMU=<path> environment variable." >&2 181fcf4e0d9SRadim Krčmář return 2 182531326aeSBalamuruhan S fi 183232f404aSAndrew Jones command -v $qemu 184531326aeSBalamuruhan S export PATH=$save_path 185531326aeSBalamuruhan S} 1864da0bc9aSAndrew Jones 1874da0bc9aSAndrew Jonesinitrd_create () 1884da0bc9aSAndrew Jones{ 1898b13a5b5SRadim Krčmář local ret 1908b13a5b5SRadim Krčmář 1918ec99569SAndrew Jones env_add_errata 1928b13a5b5SRadim Krčmář ret=$? 1938b13a5b5SRadim Krčmář 1944da0bc9aSAndrew Jones unset INITRD 1954da0bc9aSAndrew Jones [ -f "$ENV" ] && INITRD="-initrd $ENV" 1968b13a5b5SRadim Krčmář 1978b13a5b5SRadim Krčmář return $ret 1984da0bc9aSAndrew Jones} 1998ec99569SAndrew Jones 2008ec99569SAndrew Jonesenv_add_errata () 2018ec99569SAndrew Jones{ 2028b13a5b5SRadim Krčmář local line errata ret=1 2038ec99569SAndrew Jones 2048ec99569SAndrew Jones if [ -f "$ENV" ] && grep -q '^ERRATA_' <(env); then 2058ec99569SAndrew Jones for line in $(grep '^ERRATA_' "$ENV"); do 2068ec99569SAndrew Jones errata=${line%%=*} 2078ec99569SAndrew Jones test -v $errata && continue 2088ec99569SAndrew Jones eval export "$line" 2098ec99569SAndrew Jones done 21070fcb64bSAndrew Jones elif [ ! -f "$ENV" ]; then 21170fcb64bSAndrew Jones env_generate_errata 2128ec99569SAndrew Jones fi 2138ec99569SAndrew Jones 2148ec99569SAndrew Jones if grep -q '^ERRATA_' <(env); then 2158ec99569SAndrew Jones export ENV_OLD="$ENV" 2168ec99569SAndrew Jones export ENV=$(mktemp) 2178ec99569SAndrew Jones trap_exit_push 'rm -f $ENV; [ "$ENV_OLD" ] && export ENV="$ENV_OLD" || unset ENV; unset ENV_OLD' 2188ec99569SAndrew Jones [ -f "$ENV_OLD" ] && grep -v '^ERRATA_' "$ENV_OLD" > $ENV 2198ec99569SAndrew Jones grep '^ERRATA_' <(env) >> $ENV 2208b13a5b5SRadim Krčmář ret=0 2218ec99569SAndrew Jones fi 2228b13a5b5SRadim Krčmář 2238b13a5b5SRadim Krčmář return $ret 2248ec99569SAndrew Jones} 2258ec99569SAndrew Jones 22670fcb64bSAndrew Jonesenv_generate_errata () 22770fcb64bSAndrew Jones{ 22870fcb64bSAndrew Jones local kernel_version_string=$(uname -r) 229*12a4328eSAndrew Jones local kernel_version kernel_patchlevel kernel_sublevel kernel_extraversion 230*12a4328eSAndrew Jones local line commit minver errata rest v p s x have 23170fcb64bSAndrew Jones 232*12a4328eSAndrew Jones IFS=. read kernel_version kernel_patchlevel rest <<<$kernel_version_string 233*12a4328eSAndrew Jones IFS=- read kernel_sublevel kernel_extraversion <<<$rest 23470fcb64bSAndrew Jones kernel_sublevel=${kernel_sublevel%%[!0-9]*} 235*12a4328eSAndrew Jones kernel_extraversion=${kernel_extraversion%%[!0-9]*} 236*12a4328eSAndrew Jones 237*12a4328eSAndrew Jones ! [[ $kernel_sublevel =~ ^[0-9]+$ ]] && unset $kernel_sublevel 238*12a4328eSAndrew Jones ! [[ $kernel_extraversion =~ ^[0-9]+$ ]] && unset $kernel_extraversion 23970fcb64bSAndrew Jones 24070fcb64bSAndrew Jones [ "$ENVIRON_DEFAULT" != "yes" ] && return 2411ea4709cSAndrew Jones [ ! -f "$ERRATATXT" ] && return 24270fcb64bSAndrew Jones 2431ea4709cSAndrew Jones for line in $(grep -v '^#' "$ERRATATXT" | tr -d '[:blank:]' | cut -d: -f1,2); do 24470fcb64bSAndrew Jones commit=${line%:*} 24570fcb64bSAndrew Jones minver=${line#*:} 24670fcb64bSAndrew Jones 24770fcb64bSAndrew Jones errata="ERRATA_$commit" 24870fcb64bSAndrew Jones test -v $errata && continue 24970fcb64bSAndrew Jones 250*12a4328eSAndrew Jones IFS=. read v p rest <<<$minver 251*12a4328eSAndrew Jones IFS=- read s x <<<$rest 25270fcb64bSAndrew Jones s=${s%%[!0-9]*} 253*12a4328eSAndrew Jones x=${x%%[!0-9]*} 254*12a4328eSAndrew Jones 255*12a4328eSAndrew Jones if ! [[ $v =~ ^[0-9]+$ ]] || ! [[ $p =~ ^[0-9]+$ ]]; then 256*12a4328eSAndrew Jones echo "Bad minimum kernel version in $ERRATATXT, $minver" 257*12a4328eSAndrew Jones exit 2 258*12a4328eSAndrew Jones fi 259*12a4328eSAndrew Jones ! [[ $s =~ ^[0-9]+$ ]] && unset $s 260*12a4328eSAndrew Jones ! [[ $x =~ ^[0-9]+$ ]] && unset $x 26170fcb64bSAndrew Jones 26270fcb64bSAndrew Jones if (( $kernel_version > $v || 26370fcb64bSAndrew Jones ($kernel_version == $v && $kernel_patchlevel > $p) )); then 26470fcb64bSAndrew Jones have=y 26570fcb64bSAndrew Jones elif (( $kernel_version == $v && $kernel_patchlevel == $p )); then 26670fcb64bSAndrew Jones if [ "$kernel_sublevel" ] && [ "$s" ]; then 267*12a4328eSAndrew Jones if (( $kernel_sublevel > $s )); then 26870fcb64bSAndrew Jones have=y 269*12a4328eSAndrew Jones elif (( $kernel_sublevel == $s )); then 270*12a4328eSAndrew Jones if [ "$kernel_extraversion" ] && [ "$x" ]; then 271*12a4328eSAndrew Jones if (( $kernel_extraversion >= $x )); then 272*12a4328eSAndrew Jones have=y 273*12a4328eSAndrew Jones else 274*12a4328eSAndrew Jones have=n 275*12a4328eSAndrew Jones fi 276*12a4328eSAndrew Jones elif [ "$x" ] && (( $x != 0 )); then 277*12a4328eSAndrew Jones have=n 278*12a4328eSAndrew Jones else 279*12a4328eSAndrew Jones have=y 280*12a4328eSAndrew Jones fi 28170fcb64bSAndrew Jones else 28270fcb64bSAndrew Jones have=n 28370fcb64bSAndrew Jones fi 28470fcb64bSAndrew Jones elif [ "$s" ] && (( $s != 0 )); then 28570fcb64bSAndrew Jones have=n 28670fcb64bSAndrew Jones else 28770fcb64bSAndrew Jones have=y 28870fcb64bSAndrew Jones fi 28970fcb64bSAndrew Jones else 29070fcb64bSAndrew Jones have=n 29170fcb64bSAndrew Jones fi 29270fcb64bSAndrew Jones eval export "$errata=$have" 29370fcb64bSAndrew Jones done 29470fcb64bSAndrew Jones} 29570fcb64bSAndrew Jones 2968ec99569SAndrew Jonestrap_exit_push () 2978ec99569SAndrew Jones{ 2988ec99569SAndrew Jones local old_exit=$(trap -p EXIT | sed "s/^[^']*'//;s/'[^']*$//") 2998ec99569SAndrew Jones trap -- "$1; $old_exit" EXIT 3008ec99569SAndrew Jones} 301f4d99928SRadim Krčmář 302f4d99928SRadim Krčmářkvm_available () 303f4d99928SRadim Krčmář{ 304f4d99928SRadim Krčmář [ -c /dev/kvm ] || 305f4d99928SRadim Krčmář return 1 306f4d99928SRadim Krčmář 307f4d99928SRadim Krčmář [ "$HOST" = "$ARCH_NAME" ] || 308f4d99928SRadim Krčmář [ "$HOST" = aarch64 -a "$ARCH" = arm ] || 309f4d99928SRadim Krčmář [ "$HOST" = x86_64 -a "$ARCH" = i386 ] 310f4d99928SRadim Krčmář} 311f4d99928SRadim Krčmář 312f4d99928SRadim Krčmářget_qemu_accelerator () 313f4d99928SRadim Krčmář{ 314f4d99928SRadim Krčmář if [ "$ACCEL" = "kvm" ] && ! kvm_available; then 315f4d99928SRadim Krčmář echo "KVM is needed, but not available on this host" >&2 316f4d99928SRadim Krčmář return 2 317f4d99928SRadim Krčmář fi 318f4d99928SRadim Krčmář 319f4d99928SRadim Krčmář if [ "$ACCEL" ]; then 320f4d99928SRadim Krčmář echo $ACCEL 321f4d99928SRadim Krčmář elif kvm_available; then 322f4d99928SRadim Krčmář echo kvm 323f4d99928SRadim Krčmář else 324f4d99928SRadim Krčmář echo tcg 325f4d99928SRadim Krčmář fi 326f4d99928SRadim Krčmář} 327