1# The following parameters are enabled by default when running a test with 2# kvmtool: 3# --nodefaults: suppress VM configuration that cannot be disabled (like 4# modifying the supplied kernel command line). Otherwise tests 5# that use the command line will fail without this parameter. 6# --network mode=none: do not create a network device. kvmtool tries to help the 7# user by automatically create one, and then prints a warning 8# when the VM terminates if the device hasn't been initialized. 9# --loglevel=warning: reduce verbosity 10: "${KVMTOOL_DEFAULT_OPTS:="--nodefaults --network mode=none --loglevel=warning"}" 11 12############################################################################## 13# qemu_fixup_return_code translates the ambiguous exit status in Table1 to that 14# in Table2. Table3 simply documents the complete status table. 15# 16# Table1: Before fixup 17# -------------------- 18# 0 - Unexpected exit from QEMU (possible signal), or the unittest did 19# not use debug-exit 20# 1 - most likely unittest succeeded, or QEMU failed 21# 22# Table2: After fixup 23# ------------------- 24# 0 - Everything succeeded 25# 1 - most likely QEMU failed 26# 27# Table3: Complete table 28# ---------------------- 29# 0 - SUCCESS 30# 1 - most likely QEMU failed 31# 2 - most likely a run script failed 32# 3 - most likely the unittest failed 33# 124 - most likely the unittest timed out 34# 127 - most likely the unittest called abort() 35# 1..127 - FAILURE (could be QEMU, a run script, or the unittest) 36# >= 128 - Signal (signum = status - 128) 37############################################################################## 38function qemu_fixup_return_code() 39{ 40 local ret=$1 41 # Remove $ret from the list of arguments 42 shift 1 43 local errors=$* 44 local sig 45 46 [ $ret -eq 134 ] && echo "QEMU Aborted" >&2 47 48 if [ "$errors" ]; then 49 sig=$(grep 'terminating on signal' <<<"$errors") 50 if [ "$sig" ]; then 51 # This is too complex for ${var/search/replace} 52 # shellcheck disable=SC2001 53 sig=$(sed 's/.*terminating on signal \([0-9][0-9]*\).*/\1/' <<<"$sig") 54 fi 55 fi 56 57 if [ $ret -eq 0 ]; then 58 # Some signals result in a zero return status, but the 59 # error log tells the truth. 60 if [ "$sig" ]; then 61 ((ret=sig+128)) 62 else 63 # Exiting with zero (non-debugexit) is an error 64 ret=1 65 fi 66 elif [ $ret -eq 1 ]; then 67 # Even when ret==1 (unittest success) if we also got stderr 68 # logs, then we assume a QEMU failure. Otherwise we translate 69 # status of 1 to 0 (SUCCESS) 70 if [ "$errors" ]; then 71 if ! grep -qvi warning <<<"$errors" ; then 72 ret=0 73 fi 74 else 75 ret=0 76 fi 77 fi 78 79 echo $ret 80} 81 82function qemu_parse_premature_failure() 83{ 84 local log=$* 85 86 echo "$log" | grep "_NO_FILE_4Uhere_" | 87 grep -q -e "[Cc]ould not \(load\|open\) kernel" \ 88 -e "error loading" \ 89 -e "failed to load" && 90 return 1 91 return 0 92} 93 94# 95# Probe for MAX_SMP, in case it's less than the number of host cpus. 96# 97function qemu_probe_maxsmp() 98{ 99 local runtime_arch_run="$1" 100 local smp 101 102 if smp=$($runtime_arch_run _NO_FILE_4Uhere_ -smp $MAX_SMP |& grep 'SMP CPUs'); then 103 smp=${smp##* } 104 smp=${smp/\(} 105 smp=${smp/\)} 106 echo "Restricting MAX_SMP from ($MAX_SMP) to the max supported ($smp)" >&2 107 MAX_SMP=$smp 108 fi 109} 110 111function kvmtool_fixup_return_code() 112{ 113 local ret=$1 114 115 # Force run_test_status() to interpret the STATUS line. 116 if [ $ret -eq 0 ]; then 117 ret=1 118 fi 119 120 echo $ret 121} 122 123function kvmtool_parse_premature_failure() 124{ 125 local log=$* 126 127 echo "$log" | grep "Fatal: Unable to open kernel _NO_FILE_4Uhere_" && 128 return 1 129 return 0 130} 131 132function kvmtool_probe_maxsmp() 133{ 134 echo "kvmtool automatically limits the number of VCPUs to maximum supported" 135 echo "The 'smp' test parameter won't be modified" 136} 137 138declare -A vmm_optname=( 139 [qemu,args]='-append' 140 [qemu,default_opts]='' 141 [qemu,fixup_return_code]=qemu_fixup_return_code 142 [qemu,initrd]='-initrd' 143 [qemu,nr_cpus]='-smp' 144 [qemu,parse_premature_failure]=qemu_parse_premature_failure 145 [qemu,probe_maxsmp]=qemu_probe_maxsmp 146 147 [kvmtool,args]='--params' 148 [kvmtool,default_opts]="$KVMTOOL_DEFAULT_OPTS" 149 [kvmtool,fixup_return_code]=kvmtool_fixup_return_code 150 [kvmtool,initrd]='--initrd' 151 [kvmtool,nr_cpus]='--cpus' 152 [kvmtool,parse_premature_failure]=kvmtool_parse_premature_failure 153 [kvmtool,probe_maxsmp]=kvmtool_probe_maxsmp 154) 155 156function vmm_optname_args() 157{ 158 echo ${vmm_optname[$(vmm_get_target),args]} 159} 160 161function vmm_default_opts() 162{ 163 echo ${vmm_optname[$(vmm_get_target),default_opts]} 164} 165 166function vmm_fixup_return_code() 167{ 168 ${vmm_optname[$(vmm_get_target),fixup_return_code]} "$@" 169} 170 171function vmm_optname_initrd() 172{ 173 echo ${vmm_optname[$(vmm_get_target),initrd]} 174} 175 176function vmm_optname_nr_cpus() 177{ 178 echo ${vmm_optname[$(vmm_get_target),nr_cpus]} 179} 180 181function vmm_parse_premature_failure() 182{ 183 ${vmm_optname[$(vmm_get_target),parse_premature_failure]} "$@" 184} 185 186function vmm_probe_maxsmp() 187{ 188 ${vmm_optname[$(vmm_get_target),probe_maxsmp]} "$1" 189} 190 191function vmm_get_target() 192{ 193 if [[ -z "$TARGET" ]]; then 194 echo "qemu" 195 else 196 echo "$TARGET" 197 fi 198} 199 200function vmm_check_supported() 201{ 202 # We're not interested in the return code for vmm_get_target(). 203 # shellcheck disable=SC2155 204 local target=$(vmm_get_target) 205 206 case "$target" in 207 qemu) 208 return 0 209 ;; 210 *) 211 echo "$0 does not support target '$target'" 212 exit 2 213 ;; 214 esac 215} 216 217function vmm_unittest_params_name() 218{ 219 # shellcheck disable=SC2155 220 local target=$(vmm_get_target) 221 222 case "$target" in 223 qemu) 224 echo "extra_params|qemu_params" 225 ;; 226 kvmtool) 227 echo "kvmtool_params" 228 ;; 229 *) 230 echo "$0 does not support '$target'" 231 exit 2 232 ;; 233 esac 234} 235