aboutsummaryrefslogtreecommitdiff
path: root/tests
diff options
context:
space:
mode:
Diffstat (limited to 'tests')
-rw-r--r--tests/acceptance/boot_linux_console.py6
-rw-r--r--tests/data/acpi/q35/DSDT.tis.tpm12bin0 -> 8894 bytes
-rw-r--r--tests/data/acpi/q35/DSDT.tis.tpm2 (renamed from tests/data/acpi/q35/DSDT.tis)bin8894 -> 8894 bytes
-rw-r--r--tests/data/acpi/q35/TCPA.tis.tpm12bin0 -> 50 bytes
-rw-r--r--tests/data/acpi/q35/TPM2.tis.tpm2 (renamed from tests/data/acpi/q35/TPM2.tis)bin76 -> 76 bytes
-rwxr-xr-xtests/qemu-iotests/222159
-rw-r--r--tests/qemu-iotests/222.out67
-rwxr-xr-xtests/qemu-iotests/28335
-rw-r--r--tests/qemu-iotests/283.out4
-rwxr-xr-xtests/qemu-iotests/2972
-rwxr-xr-xtests/qemu-iotests/check15
-rw-r--r--tests/qemu-iotests/common.qemu7
-rw-r--r--tests/qemu-iotests/common.rc8
-rw-r--r--tests/qemu-iotests/iotests.py75
-rw-r--r--tests/qemu-iotests/testenv.py23
-rwxr-xr-xtests/qemu-iotests/tests/image-fleecing192
-rw-r--r--tests/qemu-iotests/tests/image-fleecing.out139
-rw-r--r--tests/qtest/arm-cpu-features.c13
-rw-r--r--tests/qtest/bios-tables-test.c26
-rw-r--r--tests/qtest/boot-serial-test.c2
-rw-r--r--tests/qtest/fuzz-xlnx-dp-test.c33
-rw-r--r--tests/qtest/libqos/arm-raspi2-machine.c8
-rw-r--r--tests/qtest/libqos/qgraph.h6
-rw-r--r--tests/qtest/libqos/qgraph_internal.h2
-rw-r--r--tests/qtest/meson.build1
-rw-r--r--tests/qtest/tpm-crb-test.c5
-rw-r--r--tests/qtest/tpm-emu.c62
-rw-r--r--tests/qtest/tpm-emu.h20
-rw-r--r--tests/qtest/tpm-tis-device-test.c3
-rw-r--r--tests/qtest/tpm-tis-test.c3
-rw-r--r--tests/qtest/tpm-tis-util.c2
-rw-r--r--tests/unit/test-qgraph.c2
32 files changed, 612 insertions, 308 deletions
diff --git a/tests/acceptance/boot_linux_console.py b/tests/acceptance/boot_linux_console.py
index 5248c8097d..0a49c0e276 100644
--- a/tests/acceptance/boot_linux_console.py
+++ b/tests/acceptance/boot_linux_console.py
@@ -475,7 +475,7 @@ class BootLinuxConsole(LinuxKernelTest):
def test_arm_raspi2_uart0(self):
"""
:avocado: tags=arch:arm
- :avocado: tags=machine:raspi2
+ :avocado: tags=machine:raspi2b
:avocado: tags=device:pl011
:avocado: tags=accel:tcg
"""
@@ -484,7 +484,7 @@ class BootLinuxConsole(LinuxKernelTest):
def test_arm_raspi2_initrd(self):
"""
:avocado: tags=arch:arm
- :avocado: tags=machine:raspi2
+ :avocado: tags=machine:raspi2b
"""
deb_url = ('http://archive.raspberrypi.org/debian/'
'pool/main/r/raspberrypi-firmware/'
@@ -971,7 +971,7 @@ class BootLinuxConsole(LinuxKernelTest):
def test_aarch64_raspi3_atf(self):
"""
:avocado: tags=arch:aarch64
- :avocado: tags=machine:raspi3
+ :avocado: tags=machine:raspi3b
:avocado: tags=cpu:cortex-a53
:avocado: tags=device:pl011
:avocado: tags=atf
diff --git a/tests/data/acpi/q35/DSDT.tis.tpm12 b/tests/data/acpi/q35/DSDT.tis.tpm12
new file mode 100644
index 0000000000..6735e73971
--- /dev/null
+++ b/tests/data/acpi/q35/DSDT.tis.tpm12
Binary files differ
diff --git a/tests/data/acpi/q35/DSDT.tis b/tests/data/acpi/q35/DSDT.tis.tpm2
index d1433e3c14..d1433e3c14 100644
--- a/tests/data/acpi/q35/DSDT.tis
+++ b/tests/data/acpi/q35/DSDT.tis.tpm2
Binary files differ
diff --git a/tests/data/acpi/q35/TCPA.tis.tpm12 b/tests/data/acpi/q35/TCPA.tis.tpm12
new file mode 100644
index 0000000000..a56961b413
--- /dev/null
+++ b/tests/data/acpi/q35/TCPA.tis.tpm12
Binary files differ
diff --git a/tests/data/acpi/q35/TPM2.tis b/tests/data/acpi/q35/TPM2.tis.tpm2
index fe0f05987b..fe0f05987b 100644
--- a/tests/data/acpi/q35/TPM2.tis
+++ b/tests/data/acpi/q35/TPM2.tis.tpm2
Binary files differ
diff --git a/tests/qemu-iotests/222 b/tests/qemu-iotests/222
deleted file mode 100755
index b48afe623e..0000000000
--- a/tests/qemu-iotests/222
+++ /dev/null
@@ -1,159 +0,0 @@
-#!/usr/bin/env python3
-# group: rw quick
-#
-# This test covers the basic fleecing workflow, which provides a
-# point-in-time snapshot of a node that can be queried over NBD.
-#
-# Copyright (C) 2018 Red Hat, Inc.
-# John helped, too.
-#
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation; either version 2 of the License, or
-# (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program. If not, see <http://www.gnu.org/licenses/>.
-#
-# Creator/Owner: John Snow <jsnow@redhat.com>
-
-import iotests
-from iotests import log, qemu_img, qemu_io, qemu_io_silent
-
-iotests.script_initialize(
- supported_fmts=['qcow2', 'qcow', 'qed', 'vmdk', 'vhdx', 'raw'],
- supported_platforms=['linux'],
-)
-
-patterns = [("0x5d", "0", "64k"),
- ("0xd5", "1M", "64k"),
- ("0xdc", "32M", "64k"),
- ("0xcd", "0x3ff0000", "64k")] # 64M - 64K
-
-overwrite = [("0xab", "0", "64k"), # Full overwrite
- ("0xad", "0x00f8000", "64k"), # Partial-left (1M-32K)
- ("0x1d", "0x2008000", "64k"), # Partial-right (32M+32K)
- ("0xea", "0x3fe0000", "64k")] # Adjacent-left (64M - 128K)
-
-zeroes = [("0", "0x00f8000", "32k"), # Left-end of partial-left (1M-32K)
- ("0", "0x2010000", "32k"), # Right-end of partial-right (32M+64K)
- ("0", "0x3fe0000", "64k")] # overwrite[3]
-
-remainder = [("0xd5", "0x108000", "32k"), # Right-end of partial-left [1]
- ("0xdc", "32M", "32k"), # Left-end of partial-right [2]
- ("0xcd", "0x3ff0000", "64k")] # patterns[3]
-
-with iotests.FilePath('base.img') as base_img_path, \
- iotests.FilePath('fleece.img') as fleece_img_path, \
- iotests.FilePath('nbd.sock', base_dir=iotests.sock_dir) as nbd_sock_path, \
- iotests.VM() as vm:
-
- log('--- Setting up images ---')
- log('')
-
- assert qemu_img('create', '-f', iotests.imgfmt, base_img_path, '64M') == 0
- assert qemu_img('create', '-f', "qcow2", fleece_img_path, '64M') == 0
-
- for p in patterns:
- qemu_io('-f', iotests.imgfmt,
- '-c', 'write -P%s %s %s' % p, base_img_path)
-
- log('Done')
-
- log('')
- log('--- Launching VM ---')
- log('')
-
- vm.add_drive(base_img_path)
- vm.launch()
- log('Done')
-
- log('')
- log('--- Setting up Fleecing Graph ---')
- log('')
-
- src_node = "drive0"
- tgt_node = "fleeceNode"
-
- # create tgt_node backed by src_node
- log(vm.qmp("blockdev-add", **{
- "driver": "qcow2",
- "node-name": tgt_node,
- "file": {
- "driver": "file",
- "filename": fleece_img_path,
- },
- "backing": src_node,
- }))
-
- # Establish COW from source to fleecing node
- log(vm.qmp("blockdev-backup",
- device=src_node,
- target=tgt_node,
- sync="none"))
-
- log('')
- log('--- Setting up NBD Export ---')
- log('')
-
- nbd_uri = 'nbd+unix:///%s?socket=%s' % (tgt_node, nbd_sock_path)
- log(vm.qmp("nbd-server-start",
- **{"addr": { "type": "unix",
- "data": { "path": nbd_sock_path } } }))
-
- log(vm.qmp("nbd-server-add", device=tgt_node))
-
- log('')
- log('--- Sanity Check ---')
- log('')
-
- for p in (patterns + zeroes):
- cmd = "read -P%s %s %s" % p
- log(cmd)
- assert qemu_io_silent('-r', '-f', 'raw', '-c', cmd, nbd_uri) == 0
-
- log('')
- log('--- Testing COW ---')
- log('')
-
- for p in overwrite:
- cmd = "write -P%s %s %s" % p
- log(cmd)
- log(vm.hmp_qemu_io(src_node, cmd))
-
- log('')
- log('--- Verifying Data ---')
- log('')
-
- for p in (patterns + zeroes):
- cmd = "read -P%s %s %s" % p
- log(cmd)
- assert qemu_io_silent('-r', '-f', 'raw', '-c', cmd, nbd_uri) == 0
-
- log('')
- log('--- Cleanup ---')
- log('')
-
- log(vm.qmp('block-job-cancel', device=src_node))
- log(vm.event_wait('BLOCK_JOB_CANCELLED'),
- filters=[iotests.filter_qmp_event])
- log(vm.qmp('nbd-server-stop'))
- log(vm.qmp('blockdev-del', node_name=tgt_node))
- vm.shutdown()
-
- log('')
- log('--- Confirming writes ---')
- log('')
-
- for p in (overwrite + remainder):
- cmd = "read -P%s %s %s" % p
- log(cmd)
- assert qemu_io_silent(base_img_path, '-c', cmd) == 0
-
- log('')
- log('Done')
diff --git a/tests/qemu-iotests/222.out b/tests/qemu-iotests/222.out
deleted file mode 100644
index 16643dde30..0000000000
--- a/tests/qemu-iotests/222.out
+++ /dev/null
@@ -1,67 +0,0 @@
---- Setting up images ---
-
-Done
-
---- Launching VM ---
-
-Done
-
---- Setting up Fleecing Graph ---
-
-{"return": {}}
-{"return": {}}
-
---- Setting up NBD Export ---
-
-{"return": {}}
-{"return": {}}
-
---- Sanity Check ---
-
-read -P0x5d 0 64k
-read -P0xd5 1M 64k
-read -P0xdc 32M 64k
-read -P0xcd 0x3ff0000 64k
-read -P0 0x00f8000 32k
-read -P0 0x2010000 32k
-read -P0 0x3fe0000 64k
-
---- Testing COW ---
-
-write -P0xab 0 64k
-{"return": ""}
-write -P0xad 0x00f8000 64k
-{"return": ""}
-write -P0x1d 0x2008000 64k
-{"return": ""}
-write -P0xea 0x3fe0000 64k
-{"return": ""}
-
---- Verifying Data ---
-
-read -P0x5d 0 64k
-read -P0xd5 1M 64k
-read -P0xdc 32M 64k
-read -P0xcd 0x3ff0000 64k
-read -P0 0x00f8000 32k
-read -P0 0x2010000 32k
-read -P0 0x3fe0000 64k
-
---- Cleanup ---
-
-{"return": {}}
-{"data": {"device": "drive0", "len": 67108864, "offset": 393216, "speed": 0, "type": "backup"}, "event": "BLOCK_JOB_CANCELLED", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}}
-{"return": {}}
-{"return": {}}
-
---- Confirming writes ---
-
-read -P0xab 0 64k
-read -P0xad 0x00f8000 64k
-read -P0x1d 0x2008000 64k
-read -P0xea 0x3fe0000 64k
-read -P0xd5 0x108000 32k
-read -P0xdc 32M 32k
-read -P0xcd 0x3ff0000 64k
-
-Done
diff --git a/tests/qemu-iotests/283 b/tests/qemu-iotests/283
index 010c22f0a2..a09e0183ae 100755
--- a/tests/qemu-iotests/283
+++ b/tests/qemu-iotests/283
@@ -1,7 +1,7 @@
#!/usr/bin/env python3
# group: auto quick
#
-# Test for backup-top filter permission activation failure
+# Test for copy-before-write filter permission conflict
#
# Copyright (c) 2019 Virtuozzo International GmbH.
#
@@ -31,13 +31,13 @@ size = 1024 * 1024
""" Test description
When performing a backup, all writes on the source subtree must go through the
-backup-top filter so it can copy all data to the target before it is changed.
-backup-top filter is appended above source node, to achieve this thing, so all
-parents of source node are handled. A configuration with side parents of source
-sub-tree with write permission is unsupported (we'd have append several
-backup-top filter like nodes to handle such parents). The test create an
-example of such configuration and checks that a backup is then not allowed
-(blockdev-backup command should fail).
+copy-before-write filter so it can copy all data to the target before it is
+changed. copy-before-write filter is appended above source node, to achieve
+this thing, so all parents of source node are handled. A configuration with
+side parents of source sub-tree with write permission is unsupported (we'd have
+append several copy-before-write filter like nodes to handle such parents). The
+test create an example of such configuration and checks that a backup is then
+not allowed (blockdev-backup command should fail).
The configuration:
@@ -57,11 +57,10 @@ The configuration:
│ base │ ◀──────────── │ other │
└─────────────┘ └───────┘
-On activation (see .active field of backup-top state in block/backup-top.c),
-backup-top is going to unshare write permission on its source child. Write
-unsharing will be propagated to the "source->base" link and will conflict with
-other node write permission. So permission update will fail and backup job will
-not be started.
+copy-before-write filter wants to unshare write permission on its source child.
+Write unsharing will be propagated to the "source->base" link and will conflict
+with other node write permission. So permission update will fail and backup job
+will not be started.
Note, that the only thing which prevents backup of running on such
configuration is default permission propagation scheme. It may be altered by
@@ -99,13 +98,9 @@ vm.qmp_log('blockdev-backup', sync='full', device='source', target='target')
vm.shutdown()
-print('\n=== backup-top should be gone after job-finalize ===\n')
+print('\n=== copy-before-write filter should be gone after job-finalize ===\n')
-# Check that the backup-top node is gone after job-finalize.
-#
-# During finalization, the node becomes inactive and can no longer
-# function. If it is still present, new parents might be attached, and
-# there would be no meaningful way to handle their I/O requests.
+# Check that the copy-before-write node is gone after job-finalize.
vm = iotests.VM()
vm.launch()
@@ -131,7 +126,7 @@ vm.qmp_log('blockdev-backup',
vm.event_wait('BLOCK_JOB_PENDING', 5.0)
-# The backup-top filter should still be present prior to finalization
+# The copy-before-write filter should still be present prior to finalization
assert vm.node_info('backup-filter') is not None
vm.qmp_log('job-finalize', id='backup')
diff --git a/tests/qemu-iotests/283.out b/tests/qemu-iotests/283.out
index c6e12b15c5..5bb75952ef 100644
--- a/tests/qemu-iotests/283.out
+++ b/tests/qemu-iotests/283.out
@@ -5,9 +5,9 @@
{"execute": "blockdev-add", "arguments": {"driver": "blkdebug", "image": "base", "node-name": "other", "take-child-perms": ["write"]}}
{"return": {}}
{"execute": "blockdev-backup", "arguments": {"device": "source", "sync": "full", "target": "target"}}
-{"error": {"class": "GenericError", "desc": "Cannot append backup-top filter: Permission conflict on node 'base': permissions 'write' are both required by node 'other' (uses node 'base' as 'image' child) and unshared by node 'source' (uses node 'base' as 'image' child)."}}
+{"error": {"class": "GenericError", "desc": "Permission conflict on node 'base': permissions 'write' are both required by node 'other' (uses node 'base' as 'image' child) and unshared by node 'source' (uses node 'base' as 'image' child)."}}
-=== backup-top should be gone after job-finalize ===
+=== copy-before-write filter should be gone after job-finalize ===
{"execute": "blockdev-add", "arguments": {"driver": "null-co", "node-name": "source"}}
{"return": {}}
diff --git a/tests/qemu-iotests/297 b/tests/qemu-iotests/297
index 433b732336..345b617b34 100755
--- a/tests/qemu-iotests/297
+++ b/tests/qemu-iotests/297
@@ -31,7 +31,7 @@ SKIP_FILES = (
'096', '118', '124', '132', '136', '139', '147', '148', '149',
'151', '152', '155', '163', '165', '169', '194', '196', '199', '202',
'203', '205', '206', '207', '208', '210', '211', '212', '213', '216',
- '218', '219', '222', '224', '228', '234', '235', '236', '237', '238',
+ '218', '219', '224', '228', '234', '235', '236', '237', '238',
'240', '242', '245', '246', '248', '255', '256', '257', '258', '260',
'262', '264', '266', '274', '277', '280', '281', '295', '296', '298',
'299', '302', '303', '304', '307',
diff --git a/tests/qemu-iotests/check b/tests/qemu-iotests/check
index 2dd529eb75..da1bfb839e 100755
--- a/tests/qemu-iotests/check
+++ b/tests/qemu-iotests/check
@@ -36,6 +36,15 @@ def make_argparser() -> argparse.ArgumentParser:
help='pretty print output for make check')
p.add_argument('-d', dest='debug', action='store_true', help='debug')
+ p.add_argument('-p', dest='print', action='store_true',
+ help='redirects qemu\'s stdout and stderr to the test output')
+ p.add_argument('-gdb', action='store_true',
+ help="start gdbserver with $GDB_OPTIONS options \
+ ('localhost:12345' if $GDB_OPTIONS is empty)")
+ p.add_argument('-valgrind', action='store_true',
+ help='use valgrind, sets VALGRIND_QEMU environment '
+ 'variable')
+
p.add_argument('-misalign', action='store_true',
help='misalign memory allocations')
p.add_argument('--color', choices=['on', 'off', 'auto'],
@@ -85,9 +94,6 @@ def make_argparser() -> argparse.ArgumentParser:
g_bash.add_argument('-o', dest='imgopts',
help='options to pass to qemu-img create/convert, '
'sets IMGOPTS environment variable')
- g_bash.add_argument('-valgrind', action='store_true',
- help='use valgrind, sets VALGRIND_QEMU environment '
- 'variable')
g_sel = p.add_argument_group('test selecting options',
'The following options specify test set '
@@ -114,7 +120,8 @@ if __name__ == '__main__':
env = TestEnv(imgfmt=args.imgfmt, imgproto=args.imgproto,
aiomode=args.aiomode, cachemode=args.cachemode,
imgopts=args.imgopts, misalign=args.misalign,
- debug=args.debug, valgrind=args.valgrind)
+ debug=args.debug, valgrind=args.valgrind,
+ gdb=args.gdb, qprint=args.print)
if len(sys.argv) > 1 and sys.argv[-len(args.tests)-1] == '--':
if not args.tests:
diff --git a/tests/qemu-iotests/common.qemu b/tests/qemu-iotests/common.qemu
index 0fc52d20d7..0f1fecc68e 100644
--- a/tests/qemu-iotests/common.qemu
+++ b/tests/qemu-iotests/common.qemu
@@ -85,7 +85,12 @@ _timed_wait_for()
timeout=yes
QEMU_STATUS[$h]=0
- while IFS= read -t ${QEMU_COMM_TIMEOUT} resp <&${QEMU_OUT[$h]}
+ read_timeout="-t ${QEMU_COMM_TIMEOUT}"
+ if [ -n "${GDB_OPTIONS}" ]; then
+ read_timeout=
+ fi
+
+ while IFS= read ${read_timeout} resp <&${QEMU_OUT[$h]}
do
if [ -n "$capture_events" ]; then
capture=0
diff --git a/tests/qemu-iotests/common.rc b/tests/qemu-iotests/common.rc
index 609d82de89..d8582454de 100644
--- a/tests/qemu-iotests/common.rc
+++ b/tests/qemu-iotests/common.rc
@@ -166,8 +166,14 @@ _qemu_wrapper()
if [ -n "${QEMU_NEED_PID}" ]; then
echo $BASHPID > "${QEMU_TEST_DIR}/qemu-${_QEMU_HANDLE}.pid"
fi
+
+ GDB=""
+ if [ -n "${GDB_OPTIONS}" ]; then
+ GDB="gdbserver ${GDB_OPTIONS}"
+ fi
+
VALGRIND_QEMU="${VALGRIND_QEMU_VM}" _qemu_proc_exec "${VALGRIND_LOGFILE}" \
- "$QEMU_PROG" $QEMU_OPTIONS "$@"
+ $GDB "$QEMU_PROG" $QEMU_OPTIONS "$@"
)
RETVAL=$?
_qemu_proc_valgrind_log "${VALGRIND_LOGFILE}" $RETVAL
diff --git a/tests/qemu-iotests/iotests.py b/tests/qemu-iotests/iotests.py
index 89663dac06..11276f380a 100644
--- a/tests/qemu-iotests/iotests.py
+++ b/tests/qemu-iotests/iotests.py
@@ -74,6 +74,13 @@ if os.environ.get('QEMU_NBD_OPTIONS'):
qemu_prog = os.environ.get('QEMU_PROG', 'qemu')
qemu_opts = os.environ.get('QEMU_OPTIONS', '').strip().split(' ')
+gdb_qemu_env = os.environ.get('GDB_OPTIONS')
+qemu_gdb = []
+if gdb_qemu_env:
+ qemu_gdb = ['gdbserver'] + gdb_qemu_env.strip().split(' ')
+
+qemu_print = os.environ.get('PRINT_QEMU', False)
+
imgfmt = os.environ.get('IMGFMT', 'raw')
imgproto = os.environ.get('IMGPROTO', 'file')
output_dir = os.environ.get('OUTPUT_DIR', '.')
@@ -91,6 +98,17 @@ except KeyError:
sys.stderr.write('Please run this test via the "check" script\n')
sys.exit(os.EX_USAGE)
+qemu_valgrind = []
+if os.environ.get('VALGRIND_QEMU') == "y" and \
+ os.environ.get('NO_VALGRIND') != "y":
+ valgrind_logfile = "--log-file=" + test_dir
+ # %p allows to put the valgrind process PID, since
+ # we don't know it a priori (subprocess.Popen is
+ # not yet invoked)
+ valgrind_logfile += "/%p.valgrind"
+
+ qemu_valgrind = ['valgrind', valgrind_logfile, '--error-exitcode=99']
+
socket_scm_helper = os.environ.get('SOCKET_SCM_HELPER', 'socket_scm_helper')
luks_default_secret_object = 'secret,id=keysec0,data=' + \
@@ -219,18 +237,18 @@ def qemu_io_silent(*args):
default_args = qemu_io_args
args = default_args + list(args)
- exitcode = subprocess.call(args, stdout=open('/dev/null', 'w'))
- if exitcode < 0:
+ result = subprocess.run(args, stdout=subprocess.DEVNULL, check=False)
+ if result.returncode < 0:
sys.stderr.write('qemu-io received signal %i: %s\n' %
- (-exitcode, ' '.join(args)))
- return exitcode
+ (-result.returncode, ' '.join(args)))
+ return result.returncode
def qemu_io_silent_check(*args):
'''Run qemu-io and return the true if subprocess returned 0'''
args = qemu_io_args + list(args)
- exitcode = subprocess.call(args, stdout=open('/dev/null', 'w'),
- stderr=subprocess.STDOUT)
- return exitcode == 0
+ result = subprocess.run(args, stdout=subprocess.DEVNULL,
+ stderr=subprocess.STDOUT, check=False)
+ return result.returncode == 0
class QemuIoInteractive:
def __init__(self, *args):
@@ -472,10 +490,14 @@ class Timeout:
self.seconds = seconds
self.errmsg = errmsg
def __enter__(self):
+ if qemu_gdb or qemu_valgrind:
+ return self
signal.signal(signal.SIGALRM, self.timeout)
signal.setitimer(signal.ITIMER_REAL, self.seconds)
return self
def __exit__(self, exc_type, value, traceback):
+ if qemu_gdb or qemu_valgrind:
+ return False
signal.setitimer(signal.ITIMER_REAL, 0)
return False
def timeout(self, signum, frame):
@@ -570,12 +592,35 @@ class VM(qtest.QEMUQtestMachine):
def __init__(self, path_suffix=''):
name = "qemu%s-%d" % (path_suffix, os.getpid())
- super().__init__(qemu_prog, qemu_opts, name=name,
+ timer = 15.0 if not (qemu_gdb or qemu_valgrind) else None
+ if qemu_gdb and qemu_valgrind:
+ sys.stderr.write('gdb and valgrind are mutually exclusive\n')
+ sys.exit(1)
+ wrapper = qemu_gdb if qemu_gdb else qemu_valgrind
+ super().__init__(qemu_prog, qemu_opts, wrapper=wrapper,
+ name=name,
base_temp_dir=test_dir,
socket_scm_helper=socket_scm_helper,
- sock_dir=sock_dir)
+ sock_dir=sock_dir, qmp_timer=timer)
self._num_drives = 0
+ def _post_shutdown(self) -> None:
+ super()._post_shutdown()
+ if not qemu_valgrind or not self._popen:
+ return
+ valgrind_filename = f"{test_dir}/{self._popen.pid}.valgrind"
+ if self.exitcode() == 99:
+ with open(valgrind_filename) as f:
+ print(f.read())
+ else:
+ os.remove(valgrind_filename)
+
+ def _pre_launch(self) -> None:
+ super()._pre_launch()
+ if qemu_print:
+ # set QEMU binary output to stdout
+ self._close_qemu_log_file()
+
def add_object(self, opts):
self._args.append('-object')
self._args.append(opts)
@@ -651,9 +696,10 @@ class VM(qtest.QEMUQtestMachine):
self.hmp(f'qemu-io {drive} "remove_break bp_{drive}"')
def hmp_qemu_io(self, drive: str, cmd: str,
- use_log: bool = False) -> QMPMessage:
+ use_log: bool = False, qdev: bool = False) -> QMPMessage:
"""Write to a given drive using an HMP command"""
- return self.hmp(f'qemu-io {drive} "{cmd}"', use_log=use_log)
+ d = '-d ' if qdev else ''
+ return self.hmp(f'qemu-io {d}{drive} "{cmd}"', use_log=use_log)
def flatten_qmp_object(self, obj, output=None, basestr=''):
if output is None:
@@ -1075,7 +1121,8 @@ def notrun(reason):
# Each test in qemu-iotests has a number ("seq")
seq = os.path.basename(sys.argv[0])
- open('%s/%s.notrun' % (output_dir, seq), 'w').write(reason + '\n')
+ with open('%s/%s.notrun' % (output_dir, seq), 'w') as outfile:
+ outfile.write(reason + '\n')
logger.warning("%s not run: %s", seq, reason)
sys.exit(0)
@@ -1088,8 +1135,8 @@ def case_notrun(reason):
# Each test in qemu-iotests has a number ("seq")
seq = os.path.basename(sys.argv[0])
- open('%s/%s.casenotrun' % (output_dir, seq), 'a').write(
- ' [case not run] ' + reason + '\n')
+ with open('%s/%s.casenotrun' % (output_dir, seq), 'a') as outfile:
+ outfile.write(' [case not run] ' + reason + '\n')
def _verify_image_format(supported_fmts: Sequence[str] = (),
unsupported_fmts: Sequence[str] = ()) -> None:
diff --git a/tests/qemu-iotests/testenv.py b/tests/qemu-iotests/testenv.py
index 0c3fe75636..70da0d60c8 100644
--- a/tests/qemu-iotests/testenv.py
+++ b/tests/qemu-iotests/testenv.py
@@ -27,6 +27,7 @@ import subprocess
import glob
from typing import List, Dict, Any, Optional, ContextManager
+DEF_GDB_OPTIONS = 'localhost:12345'
def isxfile(path: str) -> bool:
return os.path.isfile(path) and os.access(path, os.X_OK)
@@ -72,7 +73,8 @@ class TestEnv(ContextManager['TestEnv']):
'QEMU_NBD_OPTIONS', 'IMGOPTS', 'IMGFMT', 'IMGPROTO',
'AIOMODE', 'CACHEMODE', 'VALGRIND_QEMU',
'CACHEMODE_IS_DEFAULT', 'IMGFMT_GENERIC', 'IMGOPTSSYNTAX',
- 'IMGKEYSECRET', 'QEMU_DEFAULT_MACHINE', 'MALLOC_PERTURB_']
+ 'IMGKEYSECRET', 'QEMU_DEFAULT_MACHINE', 'MALLOC_PERTURB_',
+ 'GDB_OPTIONS', 'PRINT_QEMU']
def prepare_subprocess(self, args: List[str]) -> Dict[str, str]:
if self.debug:
@@ -178,7 +180,9 @@ class TestEnv(ContextManager['TestEnv']):
imgopts: Optional[str] = None,
misalign: bool = False,
debug: bool = False,
- valgrind: bool = False) -> None:
+ valgrind: bool = False,
+ gdb: bool = False,
+ qprint: bool = False) -> None:
self.imgfmt = imgfmt
self.imgproto = imgproto
self.aiomode = aiomode
@@ -186,6 +190,18 @@ class TestEnv(ContextManager['TestEnv']):
self.misalign = misalign
self.debug = debug
+ if qprint:
+ self.print_qemu = 'y'
+
+ if gdb:
+ self.gdb_options = os.getenv('GDB_OPTIONS', DEF_GDB_OPTIONS)
+ if not self.gdb_options:
+ # cover the case 'export GDB_OPTIONS='
+ self.gdb_options = DEF_GDB_OPTIONS
+ elif 'GDB_OPTIONS' in os.environ:
+ # to not propagate it in prepare_subprocess()
+ del os.environ['GDB_OPTIONS']
+
if valgrind:
self.valgrind_qemu = 'y'
@@ -285,6 +301,9 @@ PLATFORM -- {platform}
TEST_DIR -- {TEST_DIR}
SOCK_DIR -- {SOCK_DIR}
SOCKET_SCM_HELPER -- {SOCKET_SCM_HELPER}
+GDB_OPTIONS -- {GDB_OPTIONS}
+VALGRIND_QEMU -- {VALGRIND_QEMU}
+PRINT_QEMU_OUTPUT -- {PRINT_QEMU}
"""
args = collections.defaultdict(str, self.get_env())
diff --git a/tests/qemu-iotests/tests/image-fleecing b/tests/qemu-iotests/tests/image-fleecing
new file mode 100755
index 0000000000..f6318492c6
--- /dev/null
+++ b/tests/qemu-iotests/tests/image-fleecing
@@ -0,0 +1,192 @@
+#!/usr/bin/env python3
+# group: rw quick
+#
+# This test covers the basic fleecing workflow, which provides a
+# point-in-time snapshot of a node that can be queried over NBD.
+#
+# Copyright (C) 2018 Red Hat, Inc.
+# John helped, too.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+#
+# Creator/Owner: John Snow <jsnow@redhat.com>
+
+import iotests
+from iotests import log, qemu_img, qemu_io, qemu_io_silent
+
+iotests.script_initialize(
+ supported_fmts=['qcow2', 'qcow', 'qed', 'vmdk', 'vhdx', 'raw'],
+ supported_platforms=['linux'],
+)
+
+patterns = [('0x5d', '0', '64k'),
+ ('0xd5', '1M', '64k'),
+ ('0xdc', '32M', '64k'),
+ ('0xcd', '0x3ff0000', '64k')] # 64M - 64K
+
+overwrite = [('0xab', '0', '64k'), # Full overwrite
+ ('0xad', '0x00f8000', '64k'), # Partial-left (1M-32K)
+ ('0x1d', '0x2008000', '64k'), # Partial-right (32M+32K)
+ ('0xea', '0x3fe0000', '64k')] # Adjacent-left (64M - 128K)
+
+zeroes = [('0', '0x00f8000', '32k'), # Left-end of partial-left (1M-32K)
+ ('0', '0x2010000', '32k'), # Right-end of partial-right (32M+64K)
+ ('0', '0x3fe0000', '64k')] # overwrite[3]
+
+remainder = [('0xd5', '0x108000', '32k'), # Right-end of partial-left [1]
+ ('0xdc', '32M', '32k'), # Left-end of partial-right [2]
+ ('0xcd', '0x3ff0000', '64k')] # patterns[3]
+
+def do_test(use_cbw, base_img_path, fleece_img_path, nbd_sock_path, vm):
+ log('--- Setting up images ---')
+ log('')
+
+ assert qemu_img('create', '-f', iotests.imgfmt, base_img_path, '64M') == 0
+ assert qemu_img('create', '-f', 'qcow2', fleece_img_path, '64M') == 0
+
+ for p in patterns:
+ qemu_io('-f', iotests.imgfmt,
+ '-c', 'write -P%s %s %s' % p, base_img_path)
+
+ log('Done')
+
+ log('')
+ log('--- Launching VM ---')
+ log('')
+
+ src_node = 'source'
+ tmp_node = 'temp'
+ qom_path = '/machine/peripheral/sda'
+ vm.add_blockdev(f'driver={iotests.imgfmt},file.driver=file,'
+ f'file.filename={base_img_path},node-name={src_node}')
+ vm.add_device('virtio-scsi')
+ vm.add_device(f'scsi-hd,id=sda,drive={src_node}')
+ vm.launch()
+ log('Done')
+
+ log('')
+ log('--- Setting up Fleecing Graph ---')
+ log('')
+
+
+ # create tmp_node backed by src_node
+ log(vm.qmp('blockdev-add', {
+ 'driver': 'qcow2',
+ 'node-name': tmp_node,
+ 'file': {
+ 'driver': 'file',
+ 'filename': fleece_img_path,
+ },
+ 'backing': src_node,
+ }))
+
+ # Establish CBW from source to fleecing node
+ if use_cbw:
+ log(vm.qmp('blockdev-add', {
+ 'driver': 'copy-before-write',
+ 'node-name': 'fl-cbw',
+ 'file': src_node,
+ 'target': tmp_node
+ }))
+
+ log(vm.qmp('qom-set', path=qom_path, property='drive', value='fl-cbw'))
+ else:
+ log(vm.qmp('blockdev-backup',
+ job_id='fleecing',
+ device=src_node,
+ target=tmp_node,
+ sync='none'))
+
+ log('')
+ log('--- Setting up NBD Export ---')
+ log('')
+
+ nbd_uri = 'nbd+unix:///%s?socket=%s' % (tmp_node, nbd_sock_path)
+ log(vm.qmp('nbd-server-start',
+ {'addr': { 'type': 'unix',
+ 'data': { 'path': nbd_sock_path } } }))
+
+ log(vm.qmp('nbd-server-add', device=tmp_node))
+
+ log('')
+ log('--- Sanity Check ---')
+ log('')
+
+ for p in patterns + zeroes:
+ cmd = 'read -P%s %s %s' % p
+ log(cmd)
+ assert qemu_io_silent('-r', '-f', 'raw', '-c', cmd, nbd_uri) == 0
+
+ log('')
+ log('--- Testing COW ---')
+ log('')
+
+ for p in overwrite:
+ cmd = 'write -P%s %s %s' % p
+ log(cmd)
+ log(vm.hmp_qemu_io(qom_path, cmd, qdev=True))
+
+ log('')
+ log('--- Verifying Data ---')
+ log('')
+
+ for p in patterns + zeroes:
+ cmd = 'read -P%s %s %s' % p
+ log(cmd)
+ assert qemu_io_silent('-r', '-f', 'raw', '-c', cmd, nbd_uri) == 0
+
+ log('')
+ log('--- Cleanup ---')
+ log('')
+
+ if use_cbw:
+ log(vm.qmp('qom-set', path=qom_path, property='drive', value=src_node))
+ log(vm.qmp('blockdev-del', node_name='fl-cbw'))
+ else:
+ log(vm.qmp('block-job-cancel', device='fleecing'))
+ e = vm.event_wait('BLOCK_JOB_CANCELLED')
+ assert e is not None
+ log(e, filters=[iotests.filter_qmp_event])
+
+ log(vm.qmp('nbd-server-stop'))
+ log(vm.qmp('blockdev-del', node_name=tmp_node))
+ vm.shutdown()
+
+ log('')
+ log('--- Confirming writes ---')
+ log('')
+
+ for p in overwrite + remainder:
+ cmd = 'read -P%s %s %s' % p
+ log(cmd)
+ assert qemu_io_silent(base_img_path, '-c', cmd) == 0
+
+ log('')
+ log('Done')
+
+
+def test(use_cbw):
+ with iotests.FilePath('base.img') as base_img_path, \
+ iotests.FilePath('fleece.img') as fleece_img_path, \
+ iotests.FilePath('nbd.sock',
+ base_dir=iotests.sock_dir) as nbd_sock_path, \
+ iotests.VM() as vm:
+ do_test(use_cbw, base_img_path, fleece_img_path, nbd_sock_path, vm)
+
+
+log('=== Test backup(sync=none) based fleecing ===\n')
+test(False)
+
+log('=== Test filter based fleecing ===\n')
+test(True)
diff --git a/tests/qemu-iotests/tests/image-fleecing.out b/tests/qemu-iotests/tests/image-fleecing.out
new file mode 100644
index 0000000000..e96d122a8b
--- /dev/null
+++ b/tests/qemu-iotests/tests/image-fleecing.out
@@ -0,0 +1,139 @@
+=== Test backup(sync=none) based fleecing ===
+
+--- Setting up images ---
+
+Done
+
+--- Launching VM ---
+
+Done
+
+--- Setting up Fleecing Graph ---
+
+{"return": {}}
+{"return": {}}
+
+--- Setting up NBD Export ---
+
+{"return": {}}
+{"return": {}}
+
+--- Sanity Check ---
+
+read -P0x5d 0 64k
+read -P0xd5 1M 64k
+read -P0xdc 32M 64k
+read -P0xcd 0x3ff0000 64k
+read -P0 0x00f8000 32k
+read -P0 0x2010000 32k
+read -P0 0x3fe0000 64k
+
+--- Testing COW ---
+
+write -P0xab 0 64k
+{"return": ""}
+write -P0xad 0x00f8000 64k
+{"return": ""}
+write -P0x1d 0x2008000 64k
+{"return": ""}
+write -P0xea 0x3fe0000 64k
+{"return": ""}
+
+--- Verifying Data ---
+
+read -P0x5d 0 64k
+read -P0xd5 1M 64k
+read -P0xdc 32M 64k
+read -P0xcd 0x3ff0000 64k
+read -P0 0x00f8000 32k
+read -P0 0x2010000 32k
+read -P0 0x3fe0000 64k
+
+--- Cleanup ---
+
+{"return": {}}
+{"data": {"device": "fleecing", "len": 67108864, "offset": 393216, "speed": 0, "type": "backup"}, "event": "BLOCK_JOB_CANCELLED", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}}
+{"return": {}}
+{"return": {}}
+
+--- Confirming writes ---
+
+read -P0xab 0 64k
+read -P0xad 0x00f8000 64k
+read -P0x1d 0x2008000 64k
+read -P0xea 0x3fe0000 64k
+read -P0xd5 0x108000 32k
+read -P0xdc 32M 32k
+read -P0xcd 0x3ff0000 64k
+
+Done
+=== Test filter based fleecing ===
+
+--- Setting up images ---
+
+Done
+
+--- Launching VM ---
+
+Done
+
+--- Setting up Fleecing Graph ---
+
+{"return": {}}
+{"return": {}}
+{"return": {}}
+
+--- Setting up NBD Export ---
+
+{"return": {}}
+{"return": {}}
+
+--- Sanity Check ---
+
+read -P0x5d 0 64k
+read -P0xd5 1M 64k
+read -P0xdc 32M 64k
+read -P0xcd 0x3ff0000 64k
+read -P0 0x00f8000 32k
+read -P0 0x2010000 32k
+read -P0 0x3fe0000 64k
+
+--- Testing COW ---
+
+write -P0xab 0 64k
+{"return": ""}
+write -P0xad 0x00f8000 64k
+{"return": ""}
+write -P0x1d 0x2008000 64k
+{"return": ""}
+write -P0xea 0x3fe0000 64k
+{"return": ""}
+
+--- Verifying Data ---
+
+read -P0x5d 0 64k
+read -P0xd5 1M 64k
+read -P0xdc 32M 64k
+read -P0xcd 0x3ff0000 64k
+read -P0 0x00f8000 32k
+read -P0 0x2010000 32k
+read -P0 0x3fe0000 64k
+
+--- Cleanup ---
+
+{"return": {}}
+{"return": {}}
+{"return": {}}
+{"return": {}}
+
+--- Confirming writes ---
+
+read -P0xab 0 64k
+read -P0xad 0x00f8000 64k
+read -P0x1d 0x2008000 64k
+read -P0xea 0x3fe0000 64k
+read -P0xd5 0x108000 32k
+read -P0xdc 32M 32k
+read -P0xcd 0x3ff0000 64k
+
+Done
diff --git a/tests/qtest/arm-cpu-features.c b/tests/qtest/arm-cpu-features.c
index 8252b85bb8..90a87f0ea9 100644
--- a/tests/qtest/arm-cpu-features.c
+++ b/tests/qtest/arm-cpu-features.c
@@ -473,6 +473,19 @@ static void test_query_cpu_model_expansion(const void *data)
assert_has_feature_enabled(qts, "cortex-a57", "pmu");
assert_has_feature_enabled(qts, "cortex-a57", "aarch64");
+ assert_has_feature_enabled(qts, "a64fx", "pmu");
+ assert_has_feature_enabled(qts, "a64fx", "aarch64");
+ /*
+ * A64FX does not support any other vector lengths besides those
+ * that are enabled by default(128bit, 256bits, 512bit).
+ */
+ assert_has_feature_enabled(qts, "a64fx", "sve");
+ assert_sve_vls(qts, "a64fx", 0xb, NULL);
+ assert_error(qts, "a64fx", "cannot enable sve384",
+ "{ 'sve384': true }");
+ assert_error(qts, "a64fx", "cannot enable sve640",
+ "{ 'sve640': true }");
+
sve_tests_default(qts, "max");
pauth_tests_default(qts, "max");
diff --git a/tests/qtest/bios-tables-test.c b/tests/qtest/bios-tables-test.c
index 51d3a4e239..4f11d03055 100644
--- a/tests/qtest/bios-tables-test.c
+++ b/tests/qtest/bios-tables-test.c
@@ -1092,16 +1092,16 @@ static void test_acpi_piix4_tcg_numamem(void)
uint64_t tpm_tis_base_addr;
static void test_acpi_tcg_tpm(const char *machine, const char *tpm_if,
- uint64_t base)
+ uint64_t base, enum TPMVersion tpm_version)
{
-#ifdef CONFIG_TPM
gchar *tmp_dir_name = g_strdup_printf("qemu-test_acpi_%s_tcg_%s.XXXXXX",
machine, tpm_if);
char *tmp_path = g_dir_make_tmp(tmp_dir_name, NULL);
- TestState test;
+ TPMTestState test;
test_data data;
GThread *thread;
- char *args, *variant = g_strdup_printf(".%s", tpm_if);
+ const char *suffix = tpm_version == TPM_VERSION_2_0 ? "tpm2" : "tpm12";
+ char *args, *variant = g_strdup_printf(".%s.%s", tpm_if, suffix);
tpm_tis_base_addr = base;
@@ -1113,6 +1113,7 @@ static void test_acpi_tcg_tpm(const char *machine, const char *tpm_if,
g_mutex_init(&test.data_mutex);
g_cond_init(&test.data_cond);
test.data_cond_signal = false;
+ test.tpm_version = tpm_version;
thread = g_thread_new(NULL, tpm_emu_ctrl_thread, &test);
tpm_emu_test_wait_cond(&test);
@@ -1138,14 +1139,16 @@ static void test_acpi_tcg_tpm(const char *machine, const char *tpm_if,
g_free(tmp_dir_name);
g_free(args);
free_test_data(&data);
-#else
- g_test_skip("TPM disabled");
-#endif
}
-static void test_acpi_q35_tcg_tpm_tis(void)
+static void test_acpi_q35_tcg_tpm2_tis(void)
+{
+ test_acpi_tcg_tpm("q35", "tis", 0xFED40000, TPM_VERSION_2_0);
+}
+
+static void test_acpi_q35_tcg_tpm12_tis(void)
{
- test_acpi_tcg_tpm("q35", "tis", 0xFED40000);
+ test_acpi_tcg_tpm("q35", "tis", 0xFED40000, TPM_VERSION_1_2);
}
static void test_acpi_tcg_dimm_pxm(const char *machine)
@@ -1516,7 +1519,10 @@ int main(int argc, char *argv[])
return ret;
}
qtest_add_func("acpi/q35/oem-fields", test_acpi_oem_fields_q35);
- qtest_add_func("acpi/q35/tpm-tis", test_acpi_q35_tcg_tpm_tis);
+ if (tpm_model_is_available("-machine q35", "tpm-tis")) {
+ qtest_add_func("acpi/q35/tpm2-tis", test_acpi_q35_tcg_tpm2_tis);
+ qtest_add_func("acpi/q35/tpm12-tis", test_acpi_q35_tcg_tpm12_tis);
+ }
qtest_add_func("acpi/piix4", test_acpi_piix4_tcg);
qtest_add_func("acpi/oem-fields", test_acpi_oem_fields_pc);
qtest_add_func("acpi/piix4/bridge", test_acpi_piix4_tcg_bridge);
diff --git a/tests/qtest/boot-serial-test.c b/tests/qtest/boot-serial-test.c
index 96849cec91..83828ba270 100644
--- a/tests/qtest/boot-serial-test.c
+++ b/tests/qtest/boot-serial-test.c
@@ -173,7 +173,7 @@ static testdef_t tests[] = {
sizeof(kernel_pls3adsp1800), kernel_pls3adsp1800 },
{ "microblazeel", "petalogix-ml605", "", "TT",
sizeof(kernel_plml605), kernel_plml605 },
- { "arm", "raspi2", "", "TT", sizeof(bios_raspi2), 0, bios_raspi2 },
+ { "arm", "raspi2b", "", "TT", sizeof(bios_raspi2), 0, bios_raspi2 },
/* For hppa, force bios to output to serial by disabling graphics. */
{ "hppa", "hppa", "-vga none", "SeaBIOS wants SYSTEM HALT" },
{ "aarch64", "virt", "-cpu max", "TT", sizeof(kernel_aarch64),
diff --git a/tests/qtest/fuzz-xlnx-dp-test.c b/tests/qtest/fuzz-xlnx-dp-test.c
new file mode 100644
index 0000000000..69eb6c0eb1
--- /dev/null
+++ b/tests/qtest/fuzz-xlnx-dp-test.c
@@ -0,0 +1,33 @@
+/*
+ * QTest fuzzer-generated testcase for xlnx-dp display device
+ *
+ * Copyright (c) 2021 Qiang Liu <cyruscyliu@gmail.com>
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+#include "qemu/osdep.h"
+#include "libqos/libqtest.h"
+
+/*
+ * This used to trigger the out-of-bounds read in xlnx_dp_read
+ */
+static void test_fuzz_xlnx_dp_0x3ac(void)
+{
+ QTestState *s = qtest_init("-M xlnx-zcu102 -display none ");
+ qtest_readl(s, 0xfd4a03ac);
+ qtest_quit(s);
+}
+
+int main(int argc, char **argv)
+{
+ const char *arch = qtest_get_arch();
+
+ g_test_init(&argc, &argv, NULL);
+
+ if (strcmp(arch, "aarch64") == 0) {
+ qtest_add_func("fuzz/test_fuzz_xlnx_dp/3ac", test_fuzz_xlnx_dp_0x3ac);
+ }
+
+ return g_test_run();
+}
diff --git a/tests/qtest/libqos/arm-raspi2-machine.c b/tests/qtest/libqos/arm-raspi2-machine.c
index 35bb4709a4..09ca863c10 100644
--- a/tests/qtest/libqos/arm-raspi2-machine.c
+++ b/tests/qtest/libqos/arm-raspi2-machine.c
@@ -42,7 +42,7 @@ static void *raspi2_get_driver(void *object, const char *interface)
return &machine->alloc;
}
- fprintf(stderr, "%s not present in arm/raspi2\n", interface);
+ fprintf(stderr, "%s not present in arm/raspi2b\n", interface);
g_assert_not_reached();
}
@@ -53,7 +53,7 @@ static QOSGraphObject *raspi2_get_device(void *obj, const char *device)
return &machine->sdhci.obj;
}
- fprintf(stderr, "%s not present in arm/raspi2\n", device);
+ fprintf(stderr, "%s not present in arm/raspi2b\n", device);
g_assert_not_reached();
}
@@ -85,8 +85,8 @@ static void *qos_create_machine_arm_raspi2(QTestState *qts)
static void raspi2_register_nodes(void)
{
- qos_node_create_machine("arm/raspi2", qos_create_machine_arm_raspi2);
- qos_node_contains("arm/raspi2", "generic-sdhci", NULL);
+ qos_node_create_machine("arm/raspi2b", qos_create_machine_arm_raspi2);
+ qos_node_contains("arm/raspi2b", "generic-sdhci", NULL);
}
libqos_init(raspi2_register_nodes);
diff --git a/tests/qtest/libqos/qgraph.h b/tests/qtest/libqos/qgraph.h
index 54672350c8..871740c0dc 100644
--- a/tests/qtest/libqos/qgraph.h
+++ b/tests/qtest/libqos/qgraph.h
@@ -252,17 +252,17 @@ void qos_node_create_driver_named(const char *name, const char *qemu_name,
* This function can be useful when there are multiple devices
* with the same node name contained in a machine/other node
*
- * For example, if ``arm/raspi2`` contains 2 ``generic-sdhci``
+ * For example, if ``arm/raspi2b`` contains 2 ``generic-sdhci``
* devices, the right commands will be:
*
* .. code::
*
- * qos_node_create_machine("arm/raspi2");
+ * qos_node_create_machine("arm/raspi2b");
* qos_node_create_driver("generic-sdhci", constructor);
* // assume rest of the fields are set NULL
* QOSGraphEdgeOptions op1 = { .edge_name = "emmc" };
* QOSGraphEdgeOptions op2 = { .edge_name = "sdcard" };
- * qos_node_contains("arm/raspi2", "generic-sdhci", &op1, &op2, NULL);
+ * qos_node_contains("arm/raspi2b", "generic-sdhci", &op1, &op2, NULL);
*
* Of course this also requires that the @container's get_device function
* should implement a case for "emmc" and "sdcard".
diff --git a/tests/qtest/libqos/qgraph_internal.h b/tests/qtest/libqos/qgraph_internal.h
index c0025f5ab9..7d62fd17af 100644
--- a/tests/qtest/libqos/qgraph_internal.h
+++ b/tests/qtest/libqos/qgraph_internal.h
@@ -230,7 +230,7 @@ void qos_graph_foreach_test_path(QOSTestCallback fn);
/**
* qos_get_machine_type(): return QEMU machine type for a machine node.
* This function requires every machine @name to be in the form
- * <arch>/<machine_name>, like "arm/raspi2" or "x86_64/pc".
+ * <arch>/<machine_name>, like "arm/raspi2b" or "x86_64/pc".
*
* The function will validate the format and return a pointer to
* @machine to <machine_name>. For example, when passed "x86_64/pc"
diff --git a/tests/qtest/meson.build b/tests/qtest/meson.build
index 2bc3efd49f..757bb8499a 100644
--- a/tests/qtest/meson.build
+++ b/tests/qtest/meson.build
@@ -187,6 +187,7 @@ qtests_aarch64 = \
'numa-test',
'boot-serial-test',
'xlnx-can-test',
+ 'fuzz-xlnx-dp-test',
'migration-test']
qtests_s390x = \
diff --git a/tests/qtest/tpm-crb-test.c b/tests/qtest/tpm-crb-test.c
index ed533900d1..7b94453390 100644
--- a/tests/qtest/tpm-crb-test.c
+++ b/tests/qtest/tpm-crb-test.c
@@ -26,7 +26,7 @@ uint64_t tpm_tis_base_addr = TPM_TIS_ADDR_BASE;
static void tpm_crb_test(const void *data)
{
- const TestState *s = data;
+ const TPMTestState *s = data;
uint32_t intfid = readl(TPM_CRB_ADDR_BASE + A_CRB_INTF_ID);
uint32_t csize = readl(TPM_CRB_ADDR_BASE + A_CRB_CTRL_CMD_SIZE);
uint64_t caddr = readq(TPM_CRB_ADDR_BASE + A_CRB_CTRL_CMD_LADDR);
@@ -145,7 +145,7 @@ int main(int argc, char **argv)
int ret;
char *args, *tmp_path = g_dir_make_tmp("qemu-tpm-crb-test.XXXXXX", NULL);
GThread *thread;
- TestState test;
+ TPMTestState test;
module_call_init(MODULE_INIT_QOM);
g_test_init(&argc, &argv, NULL);
@@ -156,6 +156,7 @@ int main(int argc, char **argv)
g_mutex_init(&test.data_mutex);
g_cond_init(&test.data_cond);
test.data_cond_signal = false;
+ test.tpm_version = TPM_VERSION_2_0;
thread = g_thread_new(NULL, tpm_emu_ctrl_thread, &test);
tpm_emu_test_wait_cond(&test);
diff --git a/tests/qtest/tpm-emu.c b/tests/qtest/tpm-emu.c
index 2e8eb7b94f..2994d1cf42 100644
--- a/tests/qtest/tpm-emu.c
+++ b/tests/qtest/tpm-emu.c
@@ -16,9 +16,11 @@
#include "backends/tpm/tpm_ioctl.h"
#include "io/channel-socket.h"
#include "qapi/error.h"
+#include "qapi/qmp/qlist.h"
+#include "qapi/qmp/qstring.h"
#include "tpm-emu.h"
-void tpm_emu_test_wait_cond(TestState *s)
+void tpm_emu_test_wait_cond(TPMTestState *s)
{
gint64 end_time = g_get_monotonic_time() + 5 * G_TIME_SPAN_SECOND;
@@ -36,7 +38,7 @@ void tpm_emu_test_wait_cond(TestState *s)
static void *tpm_emu_tpm_thread(void *data)
{
- TestState *s = data;
+ TPMTestState *s = data;
QIOChannel *ioc = s->tpm_ioc;
s->tpm_msg = g_new(struct tpm_hdr, 1);
@@ -56,9 +58,21 @@ static void *tpm_emu_tpm_thread(void *data)
s->tpm_msg->code = be32_to_cpu(s->tpm_msg->code);
/* reply error */
- s->tpm_msg->tag = cpu_to_be16(TPM2_ST_NO_SESSIONS);
- s->tpm_msg->len = cpu_to_be32(sizeof(struct tpm_hdr));
- s->tpm_msg->code = cpu_to_be32(TPM_RC_FAILURE);
+ switch (s->tpm_version) {
+ case TPM_VERSION_2_0:
+ s->tpm_msg->tag = cpu_to_be16(TPM2_ST_NO_SESSIONS);
+ s->tpm_msg->len = cpu_to_be32(sizeof(struct tpm_hdr));
+ s->tpm_msg->code = cpu_to_be32(TPM_RC_FAILURE);
+ break;
+ case TPM_VERSION_1_2:
+ s->tpm_msg->tag = cpu_to_be16(TPM_TAG_RSP_COMMAND);
+ s->tpm_msg->len = cpu_to_be32(sizeof(struct tpm_hdr));
+ s->tpm_msg->code = cpu_to_be32(TPM_FAIL);
+ break;
+ default:
+ g_debug("unsupport TPM version %u", s->tpm_version);
+ g_assert_not_reached();
+ }
qio_channel_write(ioc, (char *)s->tpm_msg, be32_to_cpu(s->tpm_msg->len),
&error_abort);
}
@@ -71,7 +85,7 @@ static void *tpm_emu_tpm_thread(void *data)
void *tpm_emu_ctrl_thread(void *data)
{
- TestState *s = data;
+ TPMTestState *s = data;
QIOChannelSocket *lioc = qio_channel_socket_new();
QIOChannel *ioc;
@@ -180,3 +194,39 @@ void *tpm_emu_ctrl_thread(void *data)
object_unref(OBJECT(lioc));
return NULL;
}
+
+bool tpm_model_is_available(const char *args, const char *tpm_if)
+{
+ QTestState *qts;
+ QDict *rsp_tpm;
+ bool ret = false;
+
+ qts = qtest_init(args);
+ if (!qts) {
+ return false;
+ }
+
+ rsp_tpm = qtest_qmp(qts, "{ 'execute': 'query-tpm'}");
+ if (!qdict_haskey(rsp_tpm, "error")) {
+ QDict *rsp_models = qtest_qmp(qts,
+ "{ 'execute': 'query-tpm-models'}");
+ if (qdict_haskey(rsp_models, "return")) {
+ QList *models = qdict_get_qlist(rsp_models, "return");
+ QListEntry *e;
+
+ QLIST_FOREACH_ENTRY(models, e) {
+ QString *s = qobject_to(QString, qlist_entry_obj(e));
+ const char *ename = qstring_get_str(s);
+ if (!strcmp(ename, tpm_if)) {
+ ret = true;
+ break;
+ }
+ }
+ }
+ qobject_unref(rsp_models);
+ }
+ qobject_unref(rsp_tpm);
+ qtest_quit(qts);
+
+ return ret;
+}
diff --git a/tests/qtest/tpm-emu.h b/tests/qtest/tpm-emu.h
index 73f3bed0c4..c33d99af37 100644
--- a/tests/qtest/tpm-emu.h
+++ b/tests/qtest/tpm-emu.h
@@ -16,8 +16,13 @@
#define TPM_RC_FAILURE 0x101
#define TPM2_ST_NO_SESSIONS 0x8001
+#define TPM_FAIL 9
+#define TPM_TAG_RSP_COMMAND 0xc4
+
#include "qemu/sockets.h"
#include "io/channel.h"
+#include "sysemu/tpm.h"
+#include "libqos/libqtest.h"
struct tpm_hdr {
uint16_t tag;
@@ -26,7 +31,14 @@ struct tpm_hdr {
char buffer[];
} QEMU_PACKED;
-typedef struct TestState {
+#ifndef CONFIG_TPM
+enum TPMVersion {
+ TPM_VERSION_1_2 = 1,
+ TPM_VERSION_2_0 = 2,
+};
+#endif
+
+typedef struct TPMTestState {
GMutex data_mutex;
GCond data_cond;
bool data_cond_signal;
@@ -34,9 +46,11 @@ typedef struct TestState {
QIOChannel *tpm_ioc;
GThread *emu_tpm_thread;
struct tpm_hdr *tpm_msg;
-} TestState;
+ enum TPMVersion tpm_version;
+} TPMTestState;
-void tpm_emu_test_wait_cond(TestState *s);
+void tpm_emu_test_wait_cond(TPMTestState *s);
void *tpm_emu_ctrl_thread(void *data);
+bool tpm_model_is_available(const char *args, const char *tpm_if);
#endif /* TESTS_TPM_EMU_H */
diff --git a/tests/qtest/tpm-tis-device-test.c b/tests/qtest/tpm-tis-device-test.c
index 63ed36440f..3ddefb51ec 100644
--- a/tests/qtest/tpm-tis-device-test.c
+++ b/tests/qtest/tpm-tis-device-test.c
@@ -33,7 +33,7 @@ int main(int argc, char **argv)
{
char *tmp_path = g_dir_make_tmp("qemu-tpm-tis-device-test.XXXXXX", NULL);
GThread *thread;
- TestState test;
+ TPMTestState test;
char *args;
int ret;
@@ -46,6 +46,7 @@ int main(int argc, char **argv)
g_mutex_init(&test.data_mutex);
g_cond_init(&test.data_cond);
test.data_cond_signal = false;
+ test.tpm_version = TPM_VERSION_2_0;
thread = g_thread_new(NULL, tpm_emu_ctrl_thread, &test);
tpm_emu_test_wait_cond(&test);
diff --git a/tests/qtest/tpm-tis-test.c b/tests/qtest/tpm-tis-test.c
index 79ffbc943e..a4a25ba745 100644
--- a/tests/qtest/tpm-tis-test.c
+++ b/tests/qtest/tpm-tis-test.c
@@ -29,7 +29,7 @@ int main(int argc, char **argv)
int ret;
char *args, *tmp_path = g_dir_make_tmp("qemu-tpm-tis-test.XXXXXX", NULL);
GThread *thread;
- TestState test;
+ TPMTestState test;
module_call_init(MODULE_INIT_QOM);
g_test_init(&argc, &argv, NULL);
@@ -40,6 +40,7 @@ int main(int argc, char **argv)
g_mutex_init(&test.data_mutex);
g_cond_init(&test.data_cond);
test.data_cond_signal = false;
+ test.tpm_version = TPM_VERSION_2_0;
thread = g_thread_new(NULL, tpm_emu_ctrl_thread, &test);
tpm_emu_test_wait_cond(&test);
diff --git a/tests/qtest/tpm-tis-util.c b/tests/qtest/tpm-tis-util.c
index 9aff503fd8..939893bf01 100644
--- a/tests/qtest/tpm-tis-util.c
+++ b/tests/qtest/tpm-tis-util.c
@@ -373,7 +373,7 @@ void tpm_tis_test_check_access_reg_release(const void *data)
*/
void tpm_tis_test_check_transmit(const void *data)
{
- const TestState *s = data;
+ const TPMTestState *s = data;
uint8_t access;
uint32_t sts;
uint16_t bcount;
diff --git a/tests/unit/test-qgraph.c b/tests/unit/test-qgraph.c
index f819430e2c..334c76c8e7 100644
--- a/tests/unit/test-qgraph.c
+++ b/tests/unit/test-qgraph.c
@@ -21,7 +21,7 @@
#include "../qtest/libqos/qgraph_internal.h"
#define MACHINE_PC "x86_64/pc"
-#define MACHINE_RASPI2 "arm/raspi2"
+#define MACHINE_RASPI2 "arm/raspi2b"
#define I440FX "i440FX-pcihost"
#define PCIBUS_PC "pcibus-pc"
#define SDHCI "sdhci"