| # The following parameters are enabled by default when running a test with |
| # kvmtool: |
| # --nodefaults: suppress VM configuration that cannot be disabled (like |
| # modifying the supplied kernel command line). Otherwise tests |
| # that use the command line will fail without this parameter. |
| # --network mode=none: do not create a network device. kvmtool tries to help the |
| # user by automatically create one, and then prints a warning |
| # when the VM terminates if the device hasn't been initialized. |
| # --loglevel=warning: reduce verbosity |
| : "${KVMTOOL_DEFAULT_OPTS:="--nodefaults --network mode=none --loglevel=warning"}" |
| |
| ############################################################################## |
| # qemu_fixup_return_code translates the ambiguous exit status in Table1 to that |
| # in Table2. Table3 simply documents the complete status table. |
| # |
| # Table1: Before fixup |
| # -------------------- |
| # 0 - Unexpected exit from QEMU (possible signal), or the unittest did |
| # not use debug-exit |
| # 1 - most likely unittest succeeded, or QEMU failed |
| # |
| # Table2: After fixup |
| # ------------------- |
| # 0 - Everything succeeded |
| # 1 - most likely QEMU failed |
| # |
| # Table3: Complete table |
| # ---------------------- |
| # 0 - SUCCESS |
| # 1 - most likely QEMU failed |
| # 2 - most likely a run script failed |
| # 3 - most likely the unittest failed |
| # 124 - most likely the unittest timed out |
| # 127 - most likely the unittest called abort() |
| # 1..127 - FAILURE (could be QEMU, a run script, or the unittest) |
| # >= 128 - Signal (signum = status - 128) |
| ############################################################################## |
| function qemu_fixup_return_code() |
| { |
| local ret=$1 |
| # Remove $ret from the list of arguments |
| shift 1 |
| local errors=$* |
| local sig |
| |
| [ $ret -eq 134 ] && echo "QEMU Aborted" >&2 |
| |
| if [ "$errors" ]; then |
| sig=$(grep 'terminating on signal' <<<"$errors") |
| if [ "$sig" ]; then |
| # This is too complex for ${var/search/replace} |
| # shellcheck disable=SC2001 |
| sig=$(sed 's/.*terminating on signal \([0-9][0-9]*\).*/\1/' <<<"$sig") |
| fi |
| fi |
| |
| if [ $ret -eq 0 ]; then |
| # Some signals result in a zero return status, but the |
| # error log tells the truth. |
| if [ "$sig" ]; then |
| ((ret=sig+128)) |
| else |
| # Exiting with zero (non-debugexit) is an error |
| ret=1 |
| fi |
| elif [ $ret -eq 1 ]; then |
| # Even when ret==1 (unittest success) if we also got stderr |
| # logs, then we assume a QEMU failure. Otherwise we translate |
| # status of 1 to 0 (SUCCESS) |
| if [ "$errors" ]; then |
| if ! grep -qvi warning <<<"$errors" ; then |
| ret=0 |
| fi |
| else |
| ret=0 |
| fi |
| fi |
| |
| echo $ret |
| } |
| |
| function qemu_parse_premature_failure() |
| { |
| local log=$* |
| |
| echo "$log" | grep "_NO_FILE_4Uhere_" | |
| grep -q -e "[Cc]ould not \(load\|open\) kernel" \ |
| -e "error loading" \ |
| -e "failed to load" && |
| return 1 |
| return 0 |
| } |
| |
| # |
| # Probe for MAX_SMP, in case it's less than the number of host cpus. |
| # |
| function qemu_probe_maxsmp() |
| { |
| local runtime_arch_run="$1" |
| local smp |
| |
| if smp=$($runtime_arch_run _NO_FILE_4Uhere_ -smp $MAX_SMP |& grep 'SMP CPUs'); then |
| smp=${smp##* } |
| smp=${smp/\(} |
| smp=${smp/\)} |
| echo "Restricting MAX_SMP from ($MAX_SMP) to the max supported ($smp)" >&2 |
| MAX_SMP=$smp |
| fi |
| } |
| |
| function kvmtool_fixup_return_code() |
| { |
| local ret=$1 |
| |
| # Force run_test_status() to interpret the STATUS line. |
| if [ $ret -eq 0 ]; then |
| ret=1 |
| fi |
| |
| echo $ret |
| } |
| |
| function kvmtool_parse_premature_failure() |
| { |
| local log=$* |
| |
| echo "$log" | grep "Fatal: Unable to open kernel _NO_FILE_4Uhere_" && |
| return 1 |
| return 0 |
| } |
| |
| function kvmtool_probe_maxsmp() |
| { |
| echo "kvmtool automatically limits the number of VCPUs to maximum supported" |
| echo "The 'smp' test parameter won't be modified" |
| } |
| |
| declare -A vmm_optname=( |
| [qemu,args]='-append' |
| [qemu,default_opts]='' |
| [qemu,fixup_return_code]=qemu_fixup_return_code |
| [qemu,initrd]='-initrd' |
| [qemu,nr_cpus]='-smp' |
| [qemu,parse_premature_failure]=qemu_parse_premature_failure |
| [qemu,probe_maxsmp]=qemu_probe_maxsmp |
| |
| [kvmtool,args]='--params' |
| [kvmtool,default_opts]="$KVMTOOL_DEFAULT_OPTS" |
| [kvmtool,fixup_return_code]=kvmtool_fixup_return_code |
| [kvmtool,initrd]='--initrd' |
| [kvmtool,nr_cpus]='--cpus' |
| [kvmtool,parse_premature_failure]=kvmtool_parse_premature_failure |
| [kvmtool,probe_maxsmp]=kvmtool_probe_maxsmp |
| ) |
| |
| function vmm_optname_args() |
| { |
| echo ${vmm_optname[$(vmm_get_target),args]} |
| } |
| |
| function vmm_default_opts() |
| { |
| echo ${vmm_optname[$(vmm_get_target),default_opts]} |
| } |
| |
| function vmm_fixup_return_code() |
| { |
| ${vmm_optname[$(vmm_get_target),fixup_return_code]} "$@" |
| } |
| |
| function vmm_optname_initrd() |
| { |
| echo ${vmm_optname[$(vmm_get_target),initrd]} |
| } |
| |
| function vmm_optname_nr_cpus() |
| { |
| echo ${vmm_optname[$(vmm_get_target),nr_cpus]} |
| } |
| |
| function vmm_parse_premature_failure() |
| { |
| ${vmm_optname[$(vmm_get_target),parse_premature_failure]} "$@" |
| } |
| |
| function vmm_probe_maxsmp() |
| { |
| ${vmm_optname[$(vmm_get_target),probe_maxsmp]} "$1" |
| } |
| |
| function vmm_get_target() |
| { |
| if [[ -z "$TARGET" ]]; then |
| echo "qemu" |
| else |
| echo "$TARGET" |
| fi |
| } |
| |
| function vmm_check_supported() |
| { |
| # We're not interested in the return code for vmm_get_target(). |
| # shellcheck disable=SC2155 |
| local target=$(vmm_get_target) |
| |
| case "$target" in |
| qemu | kvmtool) |
| return 0 |
| ;; |
| *) |
| echo "$0 does not support target '$target'" |
| exit 2 |
| ;; |
| esac |
| } |
| |
| function vmm_unittest_params_name() |
| { |
| # shellcheck disable=SC2155 |
| local target=$(vmm_get_target) |
| |
| case "$target" in |
| qemu) |
| echo "extra_params|qemu_params" |
| ;; |
| kvmtool) |
| echo "kvmtool_params" |
| ;; |
| *) |
| echo "$0 does not support '$target'" |
| exit 2 |
| ;; |
| esac |
| } |