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 31f0ca153cSRadim Krčmář # stdout to {stdout}, stderr to $errors and stderr 32b2a2aa5dSAndrew Jones exec {stdout}>&1 338c3f0d96SAndrew Jones errors=$("${@}" </dev/null 2> >(tee /dev/stderr) > /dev/fd/$stdout) 34b2a2aa5dSAndrew Jones ret=$? 35b2a2aa5dSAndrew Jones exec {stdout}>&- 368727c886SAndrew Jones 378727c886SAndrew Jones [ $ret -eq 134 ] && echo "QEMU Aborted" >&2 38b2a2aa5dSAndrew Jones 39b2a2aa5dSAndrew Jones if [ "$errors" ]; then 40b2a2aa5dSAndrew Jones sig=$(grep 'terminating on signal' <<<"$errors") 41b2a2aa5dSAndrew Jones if [ "$sig" ]; then 42b2a2aa5dSAndrew Jones sig=$(sed 's/.*terminating on signal \([0-9][0-9]*\).*/\1/' <<<"$sig") 43b2a2aa5dSAndrew Jones fi 44b2a2aa5dSAndrew Jones fi 45b2a2aa5dSAndrew Jones 46b2a2aa5dSAndrew Jones if [ $ret -eq 0 ]; then 47b2a2aa5dSAndrew Jones # Some signals result in a zero return status, but the 48b2a2aa5dSAndrew Jones # error log tells the truth. 49b2a2aa5dSAndrew Jones if [ "$sig" ]; then 50b2a2aa5dSAndrew Jones ((ret=sig+128)) 51b2a2aa5dSAndrew Jones else 52b2a2aa5dSAndrew Jones # Exiting with zero (non-debugexit) is an error 53b2a2aa5dSAndrew Jones ret=1 54b2a2aa5dSAndrew Jones fi 55b2a2aa5dSAndrew Jones elif [ $ret -eq 1 ]; then 56b2a2aa5dSAndrew Jones # Even when ret==1 (unittest success) if we also got stderr 57b2a2aa5dSAndrew Jones # logs, then we assume a QEMU failure. Otherwise we translate 58b2a2aa5dSAndrew Jones # status of 1 to 0 (SUCCESS) 59a51bab13SRadim Krčmář if [ -z "$(echo "$errors" | grep -vi warning)" ]; then 60b2a2aa5dSAndrew Jones ret=0 61b2a2aa5dSAndrew Jones fi 62b2a2aa5dSAndrew Jones fi 63b2a2aa5dSAndrew Jones 64b2a2aa5dSAndrew Jones return $ret 65b2a2aa5dSAndrew Jones} 66fd149358SAndrew Jones 67fd149358SAndrew Jonestimeout_cmd () 68fd149358SAndrew Jones{ 69fd149358SAndrew Jones if [ "$TIMEOUT" ] && [ "$TIMEOUT" != "0" ]; then 70fd149358SAndrew Jones echo "timeout -k 1s --foreground $TIMEOUT" 71fd149358SAndrew Jones fi 72fd149358SAndrew Jones} 7337abdda9SThomas Huth 7437abdda9SThomas Huthqmp () 7537abdda9SThomas Huth{ 7637abdda9SThomas Huth echo '{ "execute": "qmp_capabilities" }{ "execute":' "$2" '}' | nc -U $1 7737abdda9SThomas Huth} 7837abdda9SThomas Huth 7937abdda9SThomas Huthrun_migration () 8037abdda9SThomas Huth{ 8137abdda9SThomas Huth if ! command -v nc >/dev/null 2>&1; then 8237abdda9SThomas Huth echo "$FUNCNAME needs nc (netcat)" >&2 8337abdda9SThomas Huth exit 2 8437abdda9SThomas Huth fi 8537abdda9SThomas Huth 8637abdda9SThomas Huth qemu=$1 8737abdda9SThomas Huth shift 8837abdda9SThomas Huth 8937abdda9SThomas Huth migsock=`mktemp -u -t mig-helper-socket.XXXXXXXXXX` 9037abdda9SThomas Huth migout1=`mktemp -t mig-helper-stdout1.XXXXXXXXXX` 9137abdda9SThomas Huth qmp1=`mktemp -u -t mig-helper-qmp1.XXXXXXXXXX` 9237abdda9SThomas Huth qmp2=`mktemp -u -t mig-helper-qmp2.XXXXXXXXXX` 9337abdda9SThomas Huth qmpout1=/dev/null 9437abdda9SThomas Huth qmpout2=/dev/null 9537abdda9SThomas Huth 9637abdda9SThomas Huth trap 'rm -f ${migout1} ${migsock} ${qmp1} ${qmp2}' EXIT 9737abdda9SThomas Huth 9837abdda9SThomas Huth $qemu "$@" -chardev socket,id=mon1,path=${qmp1},server,nowait \ 9937abdda9SThomas Huth -mon chardev=mon1,mode=control | tee ${migout1} & 10037abdda9SThomas Huth 10137abdda9SThomas Huth $qemu "$@" -chardev socket,id=mon2,path=${qmp2},server,nowait \ 10237abdda9SThomas Huth -mon chardev=mon2,mode=control -incoming unix:${migsock} & 10337abdda9SThomas Huth 10437abdda9SThomas Huth # The test must prompt the user to migrate, so wait for the "migrate" keyword 10537abdda9SThomas Huth while ! grep -q -i "migrate" < ${migout1} ; do 10637abdda9SThomas Huth sleep 1 10737abdda9SThomas Huth done 10837abdda9SThomas Huth 10937abdda9SThomas Huth qmp ${qmp1} '"migrate", "arguments": { "uri": "unix:'${migsock}'" }' > ${qmpout1} 11037abdda9SThomas Huth 11137abdda9SThomas Huth # Wait for the migration to complete 11237abdda9SThomas Huth migstatus=`qmp ${qmp1} '"query-migrate"' | grep return` 11337abdda9SThomas Huth while ! grep -q '"completed"' <<<"$migstatus" ; do 11437abdda9SThomas Huth sleep 1 11537abdda9SThomas Huth migstatus=`qmp ${qmp1} '"query-migrate"' | grep return` 11637abdda9SThomas Huth if grep -q '"failed"' <<<"$migstatus" ; then 11737abdda9SThomas Huth echo "ERROR: Migration failed." >&2 11837abdda9SThomas Huth qmp ${qmp1} '"quit"'> ${qmpout1} 2>/dev/null 11937abdda9SThomas Huth qmp ${qmp2} '"quit"'> ${qmpout2} 2>/dev/null 12037abdda9SThomas Huth exit 2 12137abdda9SThomas Huth fi 12237abdda9SThomas Huth done 12337abdda9SThomas Huth qmp ${qmp1} '"quit"'> ${qmpout1} 2>/dev/null 12437abdda9SThomas Huth 12537abdda9SThomas Huth qmp ${qmp2} '"inject-nmi"'> ${qmpout2} 12637abdda9SThomas Huth 12737abdda9SThomas Huth wait 12837abdda9SThomas Huth} 12937abdda9SThomas Huth 13037abdda9SThomas Huthmigration_cmd () 13137abdda9SThomas Huth{ 13237abdda9SThomas Huth if [ "$MIGRATION" = "yes" ]; then 13337abdda9SThomas Huth echo "run_migration" 13437abdda9SThomas Huth fi 13537abdda9SThomas Huth} 136531326aeSBalamuruhan S 137531326aeSBalamuruhan Ssearch_qemu_binary () 138531326aeSBalamuruhan S{ 139531326aeSBalamuruhan S local save_path=$PATH 140232f404aSAndrew Jones local qemucmd qemu 141232f404aSAndrew Jones 142531326aeSBalamuruhan S export PATH=$PATH:/usr/libexec 143232f404aSAndrew Jones for qemucmd in ${QEMU:-qemu-system-$ARCH_NAME qemu-kvm}; do 144232f404aSAndrew Jones if $qemucmd --help 2>/dev/null | grep -q 'QEMU'; then 145232f404aSAndrew Jones qemu="$qemucmd" 146531326aeSBalamuruhan S break 147531326aeSBalamuruhan S fi 148531326aeSBalamuruhan S done 149531326aeSBalamuruhan S 150232f404aSAndrew Jones if [ -z "$qemu" ]; then 151232f404aSAndrew Jones echo "A QEMU binary was not found." 152232f404aSAndrew Jones echo "You can set a custom location by using the QEMU=<path> environment variable." 153531326aeSBalamuruhan S exit 2 154531326aeSBalamuruhan S fi 155232f404aSAndrew Jones command -v $qemu 156531326aeSBalamuruhan S export PATH=$save_path 157531326aeSBalamuruhan S} 1584da0bc9aSAndrew Jones 1594da0bc9aSAndrew Jonesinitrd_create () 1604da0bc9aSAndrew Jones{ 1618ec99569SAndrew Jones env_add_errata 1624da0bc9aSAndrew Jones unset INITRD 1634da0bc9aSAndrew Jones [ -f "$ENV" ] && INITRD="-initrd $ENV" 1644da0bc9aSAndrew Jones} 1658ec99569SAndrew Jones 1668ec99569SAndrew Jonesenv_add_errata () 1678ec99569SAndrew Jones{ 1688ec99569SAndrew Jones local line errata 1698ec99569SAndrew Jones 1708ec99569SAndrew Jones if [ -f "$ENV" ] && grep -q '^ERRATA_' <(env); then 1718ec99569SAndrew Jones for line in $(grep '^ERRATA_' "$ENV"); do 1728ec99569SAndrew Jones errata=${line%%=*} 1738ec99569SAndrew Jones test -v $errata && continue 1748ec99569SAndrew Jones eval export "$line" 1758ec99569SAndrew Jones done 176*70fcb64bSAndrew Jones elif [ ! -f "$ENV" ]; then 177*70fcb64bSAndrew Jones env_generate_errata 1788ec99569SAndrew Jones fi 1798ec99569SAndrew Jones 1808ec99569SAndrew Jones if grep -q '^ERRATA_' <(env); then 1818ec99569SAndrew Jones export ENV_OLD="$ENV" 1828ec99569SAndrew Jones export ENV=$(mktemp) 1838ec99569SAndrew Jones trap_exit_push 'rm -f $ENV; [ "$ENV_OLD" ] && export ENV="$ENV_OLD" || unset ENV; unset ENV_OLD' 1848ec99569SAndrew Jones [ -f "$ENV_OLD" ] && grep -v '^ERRATA_' "$ENV_OLD" > $ENV 1858ec99569SAndrew Jones grep '^ERRATA_' <(env) >> $ENV 1868ec99569SAndrew Jones fi 1878ec99569SAndrew Jones} 1888ec99569SAndrew Jones 189*70fcb64bSAndrew Jonesenv_generate_errata () 190*70fcb64bSAndrew Jones{ 191*70fcb64bSAndrew Jones local kernel_version_string=$(uname -r) 192*70fcb64bSAndrew Jones local kernel_version kernel_patchlevel kernel_sublevel 193*70fcb64bSAndrew Jones local line commit minver errata v p s have 194*70fcb64bSAndrew Jones 195*70fcb64bSAndrew Jones IFS=. read kernel_version kernel_patchlevel kernel_sublevel <<<$kernel_version_string 196*70fcb64bSAndrew Jones kernel_sublevel=${kernel_sublevel%%[!0-9]*} 197*70fcb64bSAndrew Jones 198*70fcb64bSAndrew Jones [ "$ENVIRON_DEFAULT" != "yes" ] && return 199*70fcb64bSAndrew Jones [ ! -f errata.txt ] && return 200*70fcb64bSAndrew Jones 201*70fcb64bSAndrew Jones for line in $(grep -v '^#' errata.txt | tr -d '[:blank:]' | cut -d: -f1,2); do 202*70fcb64bSAndrew Jones commit=${line%:*} 203*70fcb64bSAndrew Jones minver=${line#*:} 204*70fcb64bSAndrew Jones 205*70fcb64bSAndrew Jones errata="ERRATA_$commit" 206*70fcb64bSAndrew Jones test -v $errata && continue 207*70fcb64bSAndrew Jones 208*70fcb64bSAndrew Jones IFS=. read v p s <<<$minver 209*70fcb64bSAndrew Jones s=${s%%[!0-9]*} 210*70fcb64bSAndrew Jones 211*70fcb64bSAndrew Jones if (( $kernel_version > $v || 212*70fcb64bSAndrew Jones ($kernel_version == $v && $kernel_patchlevel > $p) )); then 213*70fcb64bSAndrew Jones have=y 214*70fcb64bSAndrew Jones elif (( $kernel_version == $v && $kernel_patchlevel == $p )); then 215*70fcb64bSAndrew Jones if [ "$kernel_sublevel" ] && [ "$s" ]; then 216*70fcb64bSAndrew Jones if (( $kernel_sublevel >= $s )); then 217*70fcb64bSAndrew Jones have=y 218*70fcb64bSAndrew Jones else 219*70fcb64bSAndrew Jones have=n 220*70fcb64bSAndrew Jones fi 221*70fcb64bSAndrew Jones elif [ "$s" ] && (( $s != 0 )); then 222*70fcb64bSAndrew Jones have=n 223*70fcb64bSAndrew Jones else 224*70fcb64bSAndrew Jones have=y 225*70fcb64bSAndrew Jones fi 226*70fcb64bSAndrew Jones else 227*70fcb64bSAndrew Jones have=n 228*70fcb64bSAndrew Jones fi 229*70fcb64bSAndrew Jones eval export "$errata=$have" 230*70fcb64bSAndrew Jones done 231*70fcb64bSAndrew Jones} 232*70fcb64bSAndrew Jones 2338ec99569SAndrew Jonestrap_exit_push () 2348ec99569SAndrew Jones{ 2358ec99569SAndrew Jones local old_exit=$(trap -p EXIT | sed "s/^[^']*'//;s/'[^']*$//") 2368ec99569SAndrew Jones trap -- "$1; $old_exit" EXIT 2378ec99569SAndrew Jones} 238