Teach the arm runner to use kvmtool when kvm-unit-tests has been configured
appropriately.

The test is ran using run_test_status(), and a 0 return code (which means
success) is converted to 1, because kvmtool does not have a testdev device
to return the test exit code, so kvm-unit-tests must always parse the
"EXIT: STATUS" line for the exit code.

Signed-off-by: Alexandru Elisei <alexandru.eli...@arm.com>
---
 arm/run               | 161 ++++++++++++++++++++++++++----------------
 powerpc/run           |   4 +-
 riscv/run             |   4 +-
 s390x/run             |   2 +-
 scripts/arch-run.bash | 112 +++++++++++------------------
 scripts/vmm.bash      |  89 +++++++++++++++++++++++
 x86/run               |   4 +-
 7 files changed, 236 insertions(+), 140 deletions(-)

diff --git a/arm/run b/arm/run
index 56562ed1628f..e3c4ffc49136 100755
--- a/arm/run
+++ b/arm/run
@@ -12,80 +12,117 @@ fi
 
 check_vmm_supported
 
-qemu_cpu="$TARGET_CPU"
-
-if [ "$QEMU" ] && [ -z "$ACCEL" ] &&
-   [ "$HOST" = "aarch64" ] && [ "$ARCH" = "arm" ] &&
-   [ "$(basename $QEMU)" = "qemu-system-arm" ]; then
-       ACCEL="tcg"
-fi
+function arch_run_qemu()
+{
+       qemu_cpu="$TARGET_CPU"
+
+       if [ "$QEMU" ] && [ -z "$ACCEL" ] &&
+          [ "$HOST" = "aarch64" ] && [ "$ARCH" = "arm" ] &&
+          [ "$(basename $QEMU)" = "qemu-system-arm" ]; then
+               ACCEL="tcg"
+       fi
 
-set_qemu_accelerator || exit $?
-if [ "$ACCEL" = "kvm" ]; then
-       QEMU_ARCH=$HOST
-fi
+       set_qemu_accelerator || exit $?
+       if [ "$ACCEL" = "kvm" ]; then
+               QEMU_ARCH=$HOST
+       fi
 
-qemu=$(search_qemu_binary) ||
-       exit $?
+       qemu=$(search_qemu_binary) ||
+               exit $?
 
-if ! $qemu -machine '?' | grep -q 'ARM Virtual Machine'; then
-       echo "$qemu doesn't support mach-virt ('-machine virt'). Exiting."
-       exit 2
-fi
+       if ! $qemu -machine '?' | grep -q 'ARM Virtual Machine'; then
+               echo "$qemu doesn't support mach-virt ('-machine virt'). 
Exiting."
+               exit 2
+       fi
 
-M='-machine virt'
+       M='-machine virt'
 
-if [ "$ACCEL" = "kvm" ]; then
-       if $qemu $M,\? | grep -q gic-version; then
-               M+=',gic-version=host'
+       if [ "$ACCEL" = "kvm" ]; then
+               if $qemu $M,\? | grep -q gic-version; then
+                       M+=',gic-version=host'
+               fi
        fi
-fi
 
-if [ -z "$qemu_cpu" ]; then
-       if ( [ "$ACCEL" = "kvm" ] || [ "$ACCEL" = "hvf" ] ) &&
-          ( [ "$HOST" = "aarch64" ] || [ "$HOST" = "arm" ] ); then
-               qemu_cpu="host"
-               if [ "$ARCH" = "arm" ] && [ "$HOST" = "aarch64" ]; then
-                       qemu_cpu+=",aarch64=off"
+       if [ -z "$qemu_cpu" ]; then
+               if ( [ "$ACCEL" = "kvm" ] || [ "$ACCEL" = "hvf" ] ) &&
+                  ( [ "$HOST" = "aarch64" ] || [ "$HOST" = "arm" ] ); then
+                       qemu_cpu="host"
+                       if [ "$ARCH" = "arm" ] && [ "$HOST" = "aarch64" ]; then
+                               qemu_cpu+=",aarch64=off"
+                       fi
+               else
+                       qemu_cpu="$DEFAULT_QEMU_CPU"
                fi
-       else
-               qemu_cpu="$DEFAULT_QEMU_CPU"
        fi
-fi
 
-if [ "$ARCH" = "arm" ]; then
-       M+=",highmem=off"
-fi
+       if [ "$ARCH" = "arm" ]; then
+               M+=",highmem=off"
+       fi
 
-if ! $qemu $M -device '?' | grep -q virtconsole; then
-       echo "$qemu doesn't support virtio-console for chr-testdev. Exiting."
-       exit 2
-fi
+       if ! $qemu $M -device '?' | grep -q virtconsole; then
+               echo "$qemu doesn't support virtio-console for chr-testdev. 
Exiting."
+               exit 2
+       fi
 
-if ! $qemu $M -chardev '?' | grep -q testdev; then
-       echo "$qemu doesn't support chr-testdev. Exiting."
-       exit 2
-fi
+       if ! $qemu $M -chardev '?' | grep -q testdev; then
+               echo "$qemu doesn't support chr-testdev. Exiting."
+               exit 2
+       fi
 
-if [ "$UEFI_SHELL_RUN" != "y" ] && [ "$EFI_USE_ACPI" != "y" ]; then
-       chr_testdev='-device virtio-serial-device'
-       chr_testdev+=' -device virtconsole,chardev=ctd -chardev testdev,id=ctd'
-fi
+       if [ "$UEFI_SHELL_RUN" != "y" ] && [ "$EFI_USE_ACPI" != "y" ]; then
+               chr_testdev='-device virtio-serial-device'
+               chr_testdev+=' -device virtconsole,chardev=ctd -chardev 
testdev,id=ctd'
+       fi
 
-pci_testdev=
-if $qemu $M -device '?' | grep -q pci-testdev; then
-       pci_testdev="-device pci-testdev"
-fi
+       pci_testdev=
+       if $qemu $M -device '?' | grep -q pci-testdev; then
+               pci_testdev="-device pci-testdev"
+       fi
 
-A="-accel $ACCEL$ACCEL_PROPS"
-command="$qemu -nodefaults $M $A -cpu $qemu_cpu $chr_testdev $pci_testdev"
-command+=" -display none -serial stdio"
-command="$(migration_cmd) $(timeout_cmd) $command"
-
-if [ "$UEFI_SHELL_RUN" = "y" ]; then
-       ENVIRON_DEFAULT=n run_qemu_status $command "$@"
-elif [ "$EFI_USE_ACPI" = "y" ]; then
-       run_qemu_status $command -kernel "$@"
-else
-       run_qemu $command -kernel "$@"
-fi
+       A="-accel $ACCEL$ACCEL_PROPS"
+       command="$qemu -nodefaults $M $A -cpu $qemu_cpu $chr_testdev 
$pci_testdev"
+       command+=" -display none -serial stdio"
+       command="$(migration_cmd) $(timeout_cmd) $command"
+
+       if [ "$UEFI_SHELL_RUN" = "y" ]; then
+               ENVIRON_DEFAULT=n run_test_status $command "$@"
+       elif [ "$EFI_USE_ACPI" = "y" ]; then
+               run_test_status $command -kernel "$@"
+       else
+               run_test $command -kernel "$@"
+       fi
+}
+
+function arch_run_kvmtool()
+{
+       local command
+
+       kvmtool=$(search_kvmtool_binary) ||
+               exit $?
+
+       if [ "$ACCEL" ] && [ "$ACCEL" != "kvm" ]; then
+               echo "kvmtool does not support $ACCEL" >&2
+               exit 2
+       fi
+
+       if ! kvm_available; then
+               echo "kvmtool requires KVM but not available on the host" >&2
+               exit 2
+       fi
+
+       command="$(timeout_cmd) $kvmtool run"
+       if [ "$HOST" = "aarch64" ] && [ "$ARCH" = "arm" ]; then
+               run_test_status $command --kernel "$@" --aarch32
+       else
+               run_test_status $command --kernel "$@"
+       fi
+}
+
+case $TARGET in
+qemu)
+       arch_run_qemu "$@"
+       ;;
+kvmtool)
+       arch_run_kvmtool "$@"
+       ;;
+esac
diff --git a/powerpc/run b/powerpc/run
index 27abf1ef6a4d..0b25a227429a 100755
--- a/powerpc/run
+++ b/powerpc/run
@@ -59,8 +59,8 @@ command+=" -display none -serial stdio -kernel"
 command="$(migration_cmd) $(timeout_cmd) $command"
 
 # powerpc tests currently exit with rtas-poweroff, which exits with 0.
-# run_qemu treats that as a failure exit and returns 1, so we need
+# run_test treats that as a failure exit and returns 1, so we need
 # to fixup the fixup below by parsing the true exit code from the output.
 # The second fixup is also a FIXME, because once we add chr-testdev
 # support for powerpc, we won't need the second fixup.
-run_qemu_status $command "$@"
+run_test_status $command "$@"
diff --git a/riscv/run b/riscv/run
index 3b2fc36f2afb..562347e8bea2 100755
--- a/riscv/run
+++ b/riscv/run
@@ -36,8 +36,8 @@ command+=" $mach $acc $firmware -cpu $qemu_cpu "
 command="$(migration_cmd) $(timeout_cmd) $command"
 
 if [ "$UEFI_SHELL_RUN" = "y" ]; then
-       ENVIRON_DEFAULT=n run_qemu_status $command "$@"
+       ENVIRON_DEFAULT=n run_test_status $command "$@"
 else
        # We return the exit code via stdout, not via the QEMU return code
-       run_qemu_status $command -kernel "$@"
+       run_test_status $command -kernel "$@"
 fi
diff --git a/s390x/run b/s390x/run
index 34552c2747d4..9ecfaf983a3d 100755
--- a/s390x/run
+++ b/s390x/run
@@ -47,4 +47,4 @@ command+=" -kernel"
 command="$(panic_cmd) $(migration_cmd) $(timeout_cmd) $command"
 
 # We return the exit code via stdout, not via the QEMU return code
-run_qemu_status $command "$@"
+run_test_status $command "$@"
diff --git a/scripts/arch-run.bash b/scripts/arch-run.bash
index 8643bab3b252..8cf67e4f3b51 100644
--- a/scripts/arch-run.bash
+++ b/scripts/arch-run.bash
@@ -1,30 +1,7 @@
-##############################################################################
-# run_qemu 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)
-##############################################################################
-run_qemu ()
+source config.mak
+source scripts/vmm.bash
+
+run_test ()
 {
        local stdout errors ret sig
 
@@ -39,48 +16,17 @@ run_qemu ()
        ret=$?
        exec {stdout}>&-
 
-       [ $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
+       ret=$(${vmm_opts[$TARGET:fixup_return_code]} $ret $errors)
 
        return $ret
 }
 
-run_qemu_status ()
+run_test_status ()
 {
        local stdout ret
 
        exec {stdout}>&1
-       lines=$(run_qemu "$@" > >(tee /dev/fd/$stdout))
+       lines=$(run_test "$@" > >(tee /dev/fd/$stdout))
        ret=$?
        exec {stdout}>&-
 
@@ -422,6 +368,25 @@ search_qemu_binary ()
        export PATH=$save_path
 }
 
+search_kvmtool_binary ()
+{
+       local kvmtoolcmd kvmtool
+
+       for kvmtoolcmd in lkvm vm lkvm-static; do
+               if "$kvmtoolcmd" --help 2>/dev/null| grep -q 'The most commonly 
used'; then
+                       kvmtool="$kvmtoolcmd"
+                       break
+               fi
+       done
+
+       if [ -z "$kvmtool" ]; then
+               echo "A kvmtool binary was not found." >&2
+               return 2
+       fi
+
+       command -v $kvmtool
+}
+
 initrd_cleanup ()
 {
        rm -f $KVM_UNIT_TESTS_ENV
@@ -447,7 +412,7 @@ initrd_create ()
        fi
 
        unset INITRD
-       [ -f "$KVM_UNIT_TESTS_ENV" ] && INITRD="-initrd $KVM_UNIT_TESTS_ENV"
+       [ -f "$KVM_UNIT_TESTS_ENV" ] && INITRD="${vmm_opts[$TARGET:initrd]} 
$KVM_UNIT_TESTS_ENV"
 
        return 0
 }
@@ -471,18 +436,23 @@ env_params ()
        local qemu have_qemu
        local _ rest
 
-       qemu=$(search_qemu_binary) && have_qemu=1
+       env_add_params TARGET
 
-       if [ "$have_qemu" ]; then
-               if [ -n "$ACCEL" ] || [ -n "$QEMU_ACCEL" ]; then
-                       [ -n "$ACCEL" ] && QEMU_ACCEL=$ACCEL
+       # kvmtool's versioning has been broken since it was split from the
+       # kernel source.
+       if [ $TARGET = "qemu" ]; then
+               qemu=$(search_qemu_binary) && have_qemu=1
+               if [ "$have_qemu" ]; then
+                       if [ -n "$ACCEL" ] || [ -n "$QEMU_ACCEL" ]; then
+                               [ -n "$ACCEL" ] && QEMU_ACCEL=$ACCEL
+                       fi
+                       QEMU_VERSION_STRING="$($qemu -h | head -1)"
+                       # Shellcheck does not see QEMU_MAJOR|MINOR|MICRO are 
used
+                       # shellcheck disable=SC2034
+                       IFS='[ .]' read -r _ _ _ QEMU_MAJOR QEMU_MINOR 
QEMU_MICRO rest <<<"$QEMU_VERSION_STRING"
                fi
-               QEMU_VERSION_STRING="$($qemu -h | head -1)"
-               # Shellcheck does not see QEMU_MAJOR|MINOR|MICRO are used
-               # shellcheck disable=SC2034
-               IFS='[ .]' read -r _ _ _ QEMU_MAJOR QEMU_MINOR QEMU_MICRO rest 
<<<"$QEMU_VERSION_STRING"
+               env_add_params QEMU_ACCEL QEMU_VERSION_STRING QEMU_MAJOR 
QEMU_MINOR QEMU_MICRO
        fi
-       env_add_params QEMU_ACCEL QEMU_VERSION_STRING QEMU_MAJOR QEMU_MINOR 
QEMU_MICRO
 
        KERNEL_VERSION_STRING=$(uname -r)
        IFS=. read -r KERNEL_VERSION KERNEL_PATCHLEVEL rest 
<<<"$KERNEL_VERSION_STRING"
diff --git a/scripts/vmm.bash b/scripts/vmm.bash
index b02055a5c0b6..20968f2e6b10 100644
--- a/scripts/vmm.bash
+++ b/scripts/vmm.bash
@@ -1,10 +1,99 @@
 source config.mak
 
+##############################################################################
+# 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)
+##############################################################################
+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
+}
+
+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
+}
+
 declare -A vmm_opts=(
        [qemu:nr_cpus]='-smp'
        [qemu:kernel]='-kernel'
        [qemu:args]='-append'
        [qemu:initrd]='-initrd'
+       [qemu:fixup_return_code]=qemu_fixup_return_code
+
+       [kvmtool:nr_cpus]='--cpus'
+       [kvmtool:kernel]='--kernel'
+       [kvmtool:args]='--params'
+       [kvmtool:initrd]='--initrd'
+       [kvmtool:fixup_return_code]=kvmtool_fixup_return_code
 )
 
 function check_vmm_supported()
diff --git a/x86/run b/x86/run
index a3d3e7db8891..91bcd0b9ae41 100755
--- a/x86/run
+++ b/x86/run
@@ -49,7 +49,7 @@ if [ "${CONFIG_EFI}" = y ]; then
        # UEFI, the test case binaries are passed to QEMU through the disk
        # image, not through the '-kernel' flag. And QEMU reports an error if it
        # gets '-initrd' without a '-kernel'
-       ENVIRON_DEFAULT=n run_qemu ${command} "$@"
+       ENVIRON_DEFAULT=n run_test ${command} "$@"
 else
-       run_qemu ${command} "$@"
+       run_test ${command} "$@"
 fi
-- 
2.49.0


Reply via email to