aboutsummaryrefslogtreecommitdiff
path: root/tests
diff options
context:
space:
mode:
Diffstat (limited to 'tests')
-rw-r--r--tests/docker/Makefile.include10
-rw-r--r--tests/docker/dockerfiles/fedora-rust-nightly.docker2
-rw-r--r--tests/docker/dockerfiles/ubuntu2204.docker1
-rw-r--r--tests/functional/meson.build2
-rw-r--r--tests/functional/qemu_test/__init__.py2
-rw-r--r--tests/functional/qemu_test/decorators.py18
-rwxr-xr-xtests/functional/test_avr_mega2560.py11
-rwxr-xr-xtests/functional/test_avr_uno.py32
-rwxr-xr-xtests/functional/test_memlock.py79
-rwxr-xr-xtests/functional/test_vnc.py4
-rw-r--r--tests/lcitool/mappings.yml6
-rwxr-xr-xtests/lcitool/refresh3
-rwxr-xr-xtests/qemu-iotests/2402
-rw-r--r--tests/qemu-iotests/240.out4
-rwxr-xr-xtests/qemu-iotests/tests/graph-changes-while-io102
-rw-r--r--tests/qemu-iotests/tests/graph-changes-while-io.out4
-rw-r--r--tests/qtest/libqos/igb.c4
-rw-r--r--tests/tcg/aarch64/Makefile.softmmu-target3
-rw-r--r--tests/tcg/aarch64/system/boot.S172
-rw-r--r--tests/tcg/x86_64/fma.c17
-rw-r--r--tests/unit/test-aio-multithread.c6
-rw-r--r--tests/unit/test-bdrv-drain.c24
-rw-r--r--tests/unit/test-bdrv-graph-mod.c10
-rw-r--r--tests/unit/test-char.c3
-rw-r--r--tests/vm/README2
25 files changed, 474 insertions, 49 deletions
diff --git a/tests/docker/Makefile.include b/tests/docker/Makefile.include
index fa1cbb6..3959d8a 100644
--- a/tests/docker/Makefile.include
+++ b/tests/docker/Makefile.include
@@ -185,8 +185,10 @@ docker:
docker-help: docker
+# Where QEMU caches build artefacts
+DOCKER_QEMU_CACHE_DIR := $$HOME/.cache/qemu
# Use a global constant ccache directory to speed up repetitive builds
-DOCKER_CCACHE_DIR := $$HOME/.cache/qemu-docker-ccache
+DOCKER_QEMU_CCACHE_DIR := DOCKER_QEMU_CACHE_DIR/docker-ccache
# This rule if for directly running against an arbitrary docker target.
# It is called by the expanded docker targets (e.g. make
@@ -195,7 +197,7 @@ DOCKER_CCACHE_DIR := $$HOME/.cache/qemu-docker-ccache
# For example: make docker-run TEST="test-quick" IMAGE="debian:arm64" EXECUTABLE=./aarch64-linux-user/qemu-aarch64
#
docker-run: docker-qemu-src
- @mkdir -p "$(DOCKER_CCACHE_DIR)"
+ @mkdir -p "$(DOCKER_QEMU_CCACHE_DIR)"
@if test -z "$(IMAGE)" || test -z "$(TEST)"; \
then echo "Invalid target $(IMAGE)/$(TEST)"; exit 1; \
fi
@@ -222,8 +224,8 @@ docker-run: docker-qemu-src
-e V=$V -e J=$J -e DEBUG=$(DEBUG) \
-e SHOW_ENV=$(SHOW_ENV) \
$(if $(NOUSER),, \
- -e CCACHE_DIR=/var/tmp/ccache \
- -v $(DOCKER_CCACHE_DIR):/var/tmp/ccache:z \
+ -v $(DOCKER_QEMU_CACHE_DIR):$(DOCKER_QEMU_CACHE_DIR) \
+ -e CCACHE_DIR=$(DOCKER_QEMU_CCACHE_DIR) \
) \
-v $$(readlink -e $(DOCKER_SRC_COPY)):/var/tmp/qemu:z$(COMMA)ro \
$(IMAGE) \
diff --git a/tests/docker/dockerfiles/fedora-rust-nightly.docker b/tests/docker/dockerfiles/fedora-rust-nightly.docker
index fe4a6ed..4a03330 100644
--- a/tests/docker/dockerfiles/fedora-rust-nightly.docker
+++ b/tests/docker/dockerfiles/fedora-rust-nightly.docker
@@ -156,6 +156,7 @@ ENV PYTHON "/usr/bin/python3"
RUN dnf install -y wget
ENV RUSTUP_HOME=/usr/local/rustup CARGO_HOME=/usr/local/cargo
ENV RUSTC=/usr/local/rustup/toolchains/nightly-x86_64-unknown-linux-gnu/bin/rustc
+ENV RUSTDOC=/usr/local/rustup/toolchains/nightly-x86_64-unknown-linux-gnu/bin/rustdoc
ENV CARGO=/usr/local/rustup/toolchains/nightly-x86_64-unknown-linux-gnu/bin/cargo
RUN set -eux && \
rustArch='x86_64-unknown-linux-gnu' && \
@@ -170,6 +171,7 @@ RUN set -eux && \
/usr/local/cargo/bin/rustup run nightly cargo --version && \
/usr/local/cargo/bin/rustup run nightly rustc --version && \
test "$CARGO" = "$(/usr/local/cargo/bin/rustup +nightly which cargo)" && \
+ test "$RUSTDOC" = "$(/usr/local/cargo/bin/rustup +nightly which rustdoc)" && \
test "$RUSTC" = "$(/usr/local/cargo/bin/rustup +nightly which rustc)"
ENV PATH=$CARGO_HOME/bin:$PATH
RUN /usr/local/cargo/bin/rustup run nightly cargo install bindgen-cli
diff --git a/tests/docker/dockerfiles/ubuntu2204.docker b/tests/docker/dockerfiles/ubuntu2204.docker
index 4a1cf2b..28a6f93 100644
--- a/tests/docker/dockerfiles/ubuntu2204.docker
+++ b/tests/docker/dockerfiles/ubuntu2204.docker
@@ -151,6 +151,7 @@ ENV MAKE "/usr/bin/make"
ENV NINJA "/usr/bin/ninja"
ENV PYTHON "/usr/bin/python3"
ENV RUSTC=/usr/bin/rustc-1.77
+ENV RUSTDOC=/usr/bin/rustdoc-1.77
ENV CARGO_HOME=/usr/local/cargo
ENV PATH=$CARGO_HOME/bin:$PATH
RUN DEBIAN_FRONTEND=noninteractive eatmydata \
diff --git a/tests/functional/meson.build b/tests/functional/meson.build
index 557d59d..7faa2b6 100644
--- a/tests/functional/meson.build
+++ b/tests/functional/meson.build
@@ -150,6 +150,7 @@ tests_arm_linuxuser_thorough = [
tests_avr_system_thorough = [
'avr_mega2560',
+ 'avr_uno',
]
tests_hppa_system_quick = [
@@ -312,6 +313,7 @@ tests_x86_64_system_quick = [
'virtio_version',
'x86_cpu_model_versions',
'vnc',
+ 'memlock',
]
tests_x86_64_system_thorough = [
diff --git a/tests/functional/qemu_test/__init__.py b/tests/functional/qemu_test/__init__.py
index af41c2c..6e666a0 100644
--- a/tests/functional/qemu_test/__init__.py
+++ b/tests/functional/qemu_test/__init__.py
@@ -15,6 +15,6 @@ from .testcase import QemuBaseTest, QemuUserTest, QemuSystemTest
from .linuxkernel import LinuxKernelTest
from .decorators import skipIfMissingCommands, skipIfNotMachine, \
skipFlakyTest, skipUntrustedTest, skipBigDataTest, skipSlowTest, \
- skipIfMissingImports, skipIfOperatingSystem
+ skipIfMissingImports, skipIfOperatingSystem, skipLockedMemoryTest
from .archive import archive_extract
from .uncompress import uncompress
diff --git a/tests/functional/qemu_test/decorators.py b/tests/functional/qemu_test/decorators.py
index 50d29de..c0d1567 100644
--- a/tests/functional/qemu_test/decorators.py
+++ b/tests/functional/qemu_test/decorators.py
@@ -5,6 +5,7 @@
import importlib
import os
import platform
+import resource
from unittest import skipIf, skipUnless
from .cmd import which
@@ -131,3 +132,20 @@ def skipIfMissingImports(*args):
return skipUnless(has_imports, 'required import(s) "%s" not installed' %
", ".join(args))
+
+'''
+Decorator to skip execution of a test if the system's
+locked memory limit is below the required threshold.
+Takes required locked memory threshold in kB.
+Example:
+
+ @skipLockedMemoryTest(2_097_152)
+'''
+def skipLockedMemoryTest(locked_memory):
+ # get memlock hard limit in bytes
+ _, ulimit_memory = resource.getrlimit(resource.RLIMIT_MEMLOCK)
+
+ return skipUnless(
+ ulimit_memory == resource.RLIM_INFINITY or ulimit_memory >= locked_memory * 1024,
+ f'Test required {locked_memory} kB of available locked memory',
+ )
diff --git a/tests/functional/test_avr_mega2560.py b/tests/functional/test_avr_mega2560.py
index 8e47b42..6359b72 100755
--- a/tests/functional/test_avr_mega2560.py
+++ b/tests/functional/test_avr_mega2560.py
@@ -18,12 +18,10 @@
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
-import time
+from qemu_test import QemuSystemTest, Asset, wait_for_console_pattern
-from qemu_test import QemuSystemTest, Asset
class AVR6Machine(QemuSystemTest):
- timeout = 5
ASSET_ROM = Asset(('https://github.com/seharris/qemu-avr-tests'
'/raw/36c3e67b8755dcf/free-rtos/Demo'
@@ -40,13 +38,12 @@ class AVR6Machine(QemuSystemTest):
self.set_machine('arduino-mega-2560-v3')
self.vm.add_args('-bios', rom_path)
self.vm.add_args('-nographic')
+ self.vm.set_console()
self.vm.launch()
- time.sleep(2)
- self.vm.shutdown()
+ wait_for_console_pattern(self,
+ 'XABCDEFGHIJKLMNOPQRSTUVWXABCDEFGHIJKLMNOPQRSTUVWXA')
- self.assertIn('ABCDEFGHIJKLMNOPQRSTUVWXABCDEFGHIJKLMNOPQRSTUVWX',
- self.vm.get_log())
if __name__ == '__main__':
QemuSystemTest.main()
diff --git a/tests/functional/test_avr_uno.py b/tests/functional/test_avr_uno.py
new file mode 100755
index 0000000..adb3b73
--- /dev/null
+++ b/tests/functional/test_avr_uno.py
@@ -0,0 +1,32 @@
+#!/usr/bin/env python3
+#
+# QEMU AVR Arduino UNO functional test
+#
+# SPDX-License-Identifier: GPL-2.0-or-later
+
+from qemu_test import QemuSystemTest, Asset, wait_for_console_pattern
+
+
+class UnoMachine(QemuSystemTest):
+
+ ASSET_UNO = Asset(
+ ('https://github.com/RahulRNandan/LED_Blink_AVR/raw/'
+ 'c6d602cbb974a193/build/main.elf'),
+ '3009a4e2cf5c5b65142f538abdf66d4dc6bc6beab7e552fff9ae314583761b72')
+
+ def test_uno(self):
+ """
+ The binary constantly prints out 'LED Blink'
+ """
+ self.set_machine('arduino-uno')
+ rom_path = self.ASSET_UNO.fetch()
+
+ self.vm.add_args('-bios', rom_path)
+ self.vm.set_console()
+ self.vm.launch()
+
+ wait_for_console_pattern(self, 'LED Blink')
+
+
+if __name__ == '__main__':
+ QemuSystemTest.main()
diff --git a/tests/functional/test_memlock.py b/tests/functional/test_memlock.py
new file mode 100755
index 0000000..2b515ff
--- /dev/null
+++ b/tests/functional/test_memlock.py
@@ -0,0 +1,79 @@
+#!/usr/bin/env python3
+#
+# Functional test that check overcommit memlock options
+#
+# Copyright (c) Yandex Technologies LLC, 2025
+#
+# Author:
+# Alexandr Moshkov <dtalexundeer@yandex-team.ru>
+#
+# SPDX-License-Identifier: GPL-2.0-or-later
+
+import re
+
+from typing import Dict
+
+from qemu_test import QemuSystemTest
+from qemu_test import skipLockedMemoryTest
+
+
+STATUS_VALUE_PATTERN = re.compile(r'^(\w+):\s+(\d+) kB', re.MULTILINE)
+
+
+@skipLockedMemoryTest(2_097_152) # 2GB
+class MemlockTest(QemuSystemTest):
+ """
+ Runs a guest with memlock options.
+ Then verify, that this options is working correctly
+ by checking the status file of the QEMU process.
+ """
+
+ def common_vm_setup_with_memlock(self, memlock):
+ self.vm.add_args('-overcommit', f'mem-lock={memlock}')
+ self.vm.launch()
+
+ def test_memlock_off(self):
+ self.common_vm_setup_with_memlock('off')
+
+ status = self.get_process_status_values(self.vm.get_pid())
+
+ self.assertTrue(status['VmLck'] == 0)
+
+ def test_memlock_on(self):
+ self.common_vm_setup_with_memlock('on')
+
+ status = self.get_process_status_values(self.vm.get_pid())
+
+ # VmLck > 0 kB and almost all memory is resident
+ self.assertTrue(status['VmLck'] > 0)
+ self.assertTrue(status['VmRSS'] >= status['VmSize'] * 0.70)
+
+ def test_memlock_onfault(self):
+ self.common_vm_setup_with_memlock('on-fault')
+
+ status = self.get_process_status_values(self.vm.get_pid())
+
+ # VmLck > 0 kB and only few memory is resident
+ self.assertTrue(status['VmLck'] > 0)
+ self.assertTrue(status['VmRSS'] <= status['VmSize'] * 0.30)
+
+ def get_process_status_values(self, pid: int) -> Dict[str, int]:
+ result = {}
+ raw_status = self._get_raw_process_status(pid)
+
+ for line in raw_status.split('\n'):
+ if m := STATUS_VALUE_PATTERN.match(line):
+ result[m.group(1)] = int(m.group(2))
+
+ return result
+
+ def _get_raw_process_status(self, pid: int) -> str:
+ try:
+ with open(f'/proc/{pid}/status', 'r') as f:
+ return f.read()
+ except FileNotFoundError:
+ self.skipTest("Can't open status file of the process")
+
+
+if __name__ == '__main__':
+ MemlockTest.main()
diff --git a/tests/functional/test_vnc.py b/tests/functional/test_vnc.py
index 5c0ee5f..f1dd159 100755
--- a/tests/functional/test_vnc.py
+++ b/tests/functional/test_vnc.py
@@ -31,6 +31,7 @@ def check_connect(port: int) -> bool:
class Vnc(QemuSystemTest):
def test_no_vnc_change_password(self):
+ self.set_machine('none')
self.vm.add_args('-nodefaults', '-S')
self.vm.launch()
@@ -62,6 +63,7 @@ class Vnc(QemuSystemTest):
raise excp
def test_change_password_requires_a_password(self):
+ self.set_machine('none')
self.vm.add_args('-nodefaults', '-S', '-vnc', ':1,to=999')
self.launch_guarded()
self.assertTrue(self.vm.qmp('query-vnc')['return']['enabled'])
@@ -74,6 +76,7 @@ class Vnc(QemuSystemTest):
'Could not set password')
def test_change_password(self):
+ self.set_machine('none')
self.vm.add_args('-nodefaults', '-S', '-vnc', ':1,to=999,password=on')
self.launch_guarded()
self.assertTrue(self.vm.qmp('query-vnc')['return']['enabled'])
@@ -103,6 +106,7 @@ class Vnc(QemuSystemTest):
self.assertTrue(check_connect(c))
def test_change_listen(self):
+ self.set_machine('none')
with Ports() as ports:
a, b, c = ports.find_free_ports(3)
self.do_test_change_listen(a, b, c)
diff --git a/tests/lcitool/mappings.yml b/tests/lcitool/mappings.yml
index 673baf3..8f0e95e 100644
--- a/tests/lcitool/mappings.yml
+++ b/tests/lcitool/mappings.yml
@@ -8,6 +8,10 @@ mappings:
meson:
OpenSUSELeap15:
+ # Use Meson from PyPI wherever Rust is enabled
+ Debian:
+ Fedora:
+ Ubuntu:
python3:
OpenSUSELeap15: python311-base
@@ -72,7 +76,7 @@ mappings:
pypi_mappings:
# Request more recent version
meson:
- default: meson==1.5.0
+ default: meson==1.8.1
# Drop packages that need devel headers
python3-numpy:
diff --git a/tests/lcitool/refresh b/tests/lcitool/refresh
index 8474ea8..d3488b2 100755
--- a/tests/lcitool/refresh
+++ b/tests/lcitool/refresh
@@ -121,6 +121,7 @@ fedora_rustup_nightly_extras = [
"RUN dnf install -y wget\n",
"ENV RUSTUP_HOME=/usr/local/rustup CARGO_HOME=/usr/local/cargo\n",
"ENV RUSTC=/usr/local/rustup/toolchains/nightly-x86_64-unknown-linux-gnu/bin/rustc\n",
+ "ENV RUSTDOC=/usr/local/rustup/toolchains/nightly-x86_64-unknown-linux-gnu/bin/rustdoc\n",
"ENV CARGO=/usr/local/rustup/toolchains/nightly-x86_64-unknown-linux-gnu/bin/cargo\n",
"RUN set -eux && \\\n",
" rustArch='x86_64-unknown-linux-gnu' && \\\n",
@@ -135,6 +136,7 @@ fedora_rustup_nightly_extras = [
" /usr/local/cargo/bin/rustup run nightly cargo --version && \\\n",
" /usr/local/cargo/bin/rustup run nightly rustc --version && \\\n",
' test "$CARGO" = "$(/usr/local/cargo/bin/rustup +nightly which cargo)" && \\\n',
+ ' test "$RUSTDOC" = "$(/usr/local/cargo/bin/rustup +nightly which rustdoc)" && \\\n',
' test "$RUSTC" = "$(/usr/local/cargo/bin/rustup +nightly which rustc)"\n',
'ENV PATH=$CARGO_HOME/bin:$PATH\n',
'RUN /usr/local/cargo/bin/rustup run nightly cargo install bindgen-cli\n',
@@ -143,6 +145,7 @@ fedora_rustup_nightly_extras = [
ubuntu2204_rust_extras = [
"ENV RUSTC=/usr/bin/rustc-1.77\n",
+ "ENV RUSTDOC=/usr/bin/rustdoc-1.77\n",
"ENV CARGO_HOME=/usr/local/cargo\n",
'ENV PATH=$CARGO_HOME/bin:$PATH\n',
"RUN DEBIAN_FRONTEND=noninteractive eatmydata \\\n",
diff --git a/tests/qemu-iotests/240 b/tests/qemu-iotests/240
index 9b281e1..f8af9ff 100755
--- a/tests/qemu-iotests/240
+++ b/tests/qemu-iotests/240
@@ -81,8 +81,6 @@ class TestCase(iotests.QMPTestCase):
self.vm.qmp_log('device_del', id='scsi-hd0')
self.vm.event_wait('DEVICE_DELETED')
- self.vm.qmp_log('device_add', id='scsi-hd1', driver='scsi-hd', drive='hd0', bus="scsi1.0")
-
self.vm.qmp_log('device_del', id='scsi-hd1')
self.vm.event_wait('DEVICE_DELETED')
self.vm.qmp_log('blockdev-del', node_name='hd0')
diff --git a/tests/qemu-iotests/240.out b/tests/qemu-iotests/240.out
index 89ed25e..10dcc42 100644
--- a/tests/qemu-iotests/240.out
+++ b/tests/qemu-iotests/240.out
@@ -46,10 +46,8 @@
{"execute": "device_add", "arguments": {"bus": "scsi0.0", "drive": "hd0", "driver": "scsi-hd", "id": "scsi-hd0"}}
{"return": {}}
{"execute": "device_add", "arguments": {"bus": "scsi1.0", "drive": "hd0", "driver": "scsi-hd", "id": "scsi-hd1"}}
-{"error": {"class": "GenericError", "desc": "Cannot change iothread of active block backend"}}
-{"execute": "device_del", "arguments": {"id": "scsi-hd0"}}
{"return": {}}
-{"execute": "device_add", "arguments": {"bus": "scsi1.0", "drive": "hd0", "driver": "scsi-hd", "id": "scsi-hd1"}}
+{"execute": "device_del", "arguments": {"id": "scsi-hd0"}}
{"return": {}}
{"execute": "device_del", "arguments": {"id": "scsi-hd1"}}
{"return": {}}
diff --git a/tests/qemu-iotests/tests/graph-changes-while-io b/tests/qemu-iotests/tests/graph-changes-while-io
index 194fda5..dca1167 100755
--- a/tests/qemu-iotests/tests/graph-changes-while-io
+++ b/tests/qemu-iotests/tests/graph-changes-while-io
@@ -27,6 +27,7 @@ from iotests import imgfmt, qemu_img, qemu_img_create, qemu_io, \
top = os.path.join(iotests.test_dir, 'top.img')
+mid = os.path.join(iotests.test_dir, 'mid.img')
nbd_sock = os.path.join(iotests.sock_dir, 'nbd.sock')
@@ -57,6 +58,16 @@ class TestGraphChangesWhileIO(QMPTestCase):
def tearDown(self) -> None:
self.qsd.stop()
+ os.remove(top)
+
+ def _wait_for_blockjob(self, status: str) -> None:
+ done = False
+ while not done:
+ for event in self.qsd.get_qmp().get_events(wait=10.0):
+ if event['event'] != 'JOB_STATUS_CHANGE':
+ continue
+ if event['data']['status'] == status:
+ done = True
def test_blockdev_add_while_io(self) -> None:
# Run qemu-img bench in the background
@@ -116,15 +127,92 @@ class TestGraphChangesWhileIO(QMPTestCase):
'device': 'job0',
})
- cancelled = False
- while not cancelled:
- for event in self.qsd.get_qmp().get_events(wait=10.0):
- if event['event'] != 'JOB_STATUS_CHANGE':
- continue
- if event['data']['status'] == 'null':
- cancelled = True
+ self._wait_for_blockjob('null')
+
+ bench_thr.join()
+
+ def test_remove_lower_snapshot_while_io(self) -> None:
+ # Run qemu-img bench in the background
+ bench_thr = Thread(target=do_qemu_img_bench, args=(100000, ))
+ bench_thr.start()
+
+ # While I/O is performed on 'node0' node, consequently add 2 snapshots
+ # on top of it, then remove (commit) them starting from lower one.
+ while bench_thr.is_alive():
+ # Recreate snapshot images on every iteration
+ qemu_img_create('-f', imgfmt, mid, '1G')
+ qemu_img_create('-f', imgfmt, top, '1G')
+
+ self.qsd.cmd('blockdev-add', {
+ 'driver': imgfmt,
+ 'node-name': 'mid',
+ 'file': {
+ 'driver': 'file',
+ 'filename': mid
+ }
+ })
+
+ self.qsd.cmd('blockdev-snapshot', {
+ 'node': 'node0',
+ 'overlay': 'mid',
+ })
+
+ self.qsd.cmd('blockdev-add', {
+ 'driver': imgfmt,
+ 'node-name': 'top',
+ 'file': {
+ 'driver': 'file',
+ 'filename': top
+ }
+ })
+
+ self.qsd.cmd('blockdev-snapshot', {
+ 'node': 'mid',
+ 'overlay': 'top',
+ })
+
+ self.qsd.cmd('block-commit', {
+ 'job-id': 'commit-mid',
+ 'device': 'top',
+ 'top-node': 'mid',
+ 'base-node': 'node0',
+ 'auto-finalize': True,
+ 'auto-dismiss': False,
+ })
+
+ self._wait_for_blockjob('concluded')
+ self.qsd.cmd('job-dismiss', {
+ 'id': 'commit-mid',
+ })
+
+ self.qsd.cmd('block-commit', {
+ 'job-id': 'commit-top',
+ 'device': 'top',
+ 'top-node': 'top',
+ 'base-node': 'node0',
+ 'auto-finalize': True,
+ 'auto-dismiss': False,
+ })
+
+ self._wait_for_blockjob('ready')
+ self.qsd.cmd('job-complete', {
+ 'id': 'commit-top',
+ })
+
+ self._wait_for_blockjob('concluded')
+ self.qsd.cmd('job-dismiss', {
+ 'id': 'commit-top',
+ })
+
+ self.qsd.cmd('blockdev-del', {
+ 'node-name': 'mid'
+ })
+ self.qsd.cmd('blockdev-del', {
+ 'node-name': 'top'
+ })
bench_thr.join()
+ os.remove(mid)
if __name__ == '__main__':
# Format must support raw backing files
diff --git a/tests/qemu-iotests/tests/graph-changes-while-io.out b/tests/qemu-iotests/tests/graph-changes-while-io.out
index fbc63e6..8d7e9967 100644
--- a/tests/qemu-iotests/tests/graph-changes-while-io.out
+++ b/tests/qemu-iotests/tests/graph-changes-while-io.out
@@ -1,5 +1,5 @@
-..
+...
----------------------------------------------------------------------
-Ran 2 tests
+Ran 3 tests
OK
diff --git a/tests/qtest/libqos/igb.c b/tests/qtest/libqos/igb.c
index f40c4ec..ab3ef6f 100644
--- a/tests/qtest/libqos/igb.c
+++ b/tests/qtest/libqos/igb.c
@@ -104,10 +104,10 @@ static void igb_pci_start_hw(QOSGraphObject *obj)
e1000e_macreg_write(&d->e1000e, E1000_RDT(0), 0);
e1000e_macreg_write(&d->e1000e, E1000_RDH(0), 0);
e1000e_macreg_write(&d->e1000e, E1000_RA,
- le32_to_cpu(*(uint32_t *)address));
+ ldl_le_p(address));
e1000e_macreg_write(&d->e1000e, E1000_RA + 4,
E1000_RAH_AV | E1000_RAH_POOL_1 |
- le16_to_cpu(*(uint16_t *)(address + 4)));
+ lduw_le_p(address + 4));
/* Set supported receive descriptor mode */
e1000e_macreg_write(&d->e1000e,
diff --git a/tests/tcg/aarch64/Makefile.softmmu-target b/tests/tcg/aarch64/Makefile.softmmu-target
index 9c52475..f7a7d2b 100644
--- a/tests/tcg/aarch64/Makefile.softmmu-target
+++ b/tests/tcg/aarch64/Makefile.softmmu-target
@@ -68,7 +68,8 @@ run-plugin-semiconsole-with-%: semiconsole
# vtimer test needs EL2
QEMU_EL2_MACHINE=-machine virt,virtualization=on,gic-version=2 -cpu cortex-a57 -smp 4
-run-vtimer: QEMU_OPTS=$(QEMU_EL2_MACHINE) $(QEMU_BASE_ARGS) -kernel
+QEMU_EL2_BASE_ARGS=-semihosting-config enable=on,target=native,chardev=output,arg="2"
+run-vtimer: QEMU_OPTS=$(QEMU_EL2_MACHINE) $(QEMU_EL2_BASE_ARGS) -kernel
# Simple Record/Replay Test
.PHONY: memory-record
diff --git a/tests/tcg/aarch64/system/boot.S b/tests/tcg/aarch64/system/boot.S
index a5df9c1..8bfa4e4 100644
--- a/tests/tcg/aarch64/system/boot.S
+++ b/tests/tcg/aarch64/system/boot.S
@@ -16,6 +16,7 @@
#define semihosting_call hlt 0xf000
#define SYS_WRITEC 0x03 /* character to debug channel */
#define SYS_WRITE0 0x04 /* string to debug channel */
+#define SYS_GET_CMDLINE 0x15 /* get command line */
#define SYS_EXIT 0x18
.align 12
@@ -70,21 +71,172 @@ lower_a32_sync:
lower_a32_irq:
lower_a32_fiq:
lower_a32_serror:
+ adr x1, .unexp_excp
+exit_msg:
mov x0, SYS_WRITE0
- adr x1, .error
semihosting_call
mov x0, 1 /* EXIT_FAILURE */
bl _exit
/* never returns */
.section .rodata
-.error:
- .string "Terminated by exception.\n"
+.unexp_excp:
+ .string "Unexpected exception.\n"
+.high_el_msg:
+ .string "Started in lower EL than requested.\n"
+.unexp_el0:
+ .string "Started in invalid EL.\n"
+
+ .align 8
+.get_cmd:
+ .quad cmdline
+ .quad 128
.text
.align 4
.global __start
__start:
+ /*
+ * Initialise the stack for whatever EL we are in before
+ * anything else, we need it to be able to _exit cleanly.
+ * It's smaller than the stack we pass to the C code but we
+ * don't need much.
+ */
+ adrp x0, system_stack_end
+ add x0, x0, :lo12:system_stack_end
+ mov sp, x0
+
+ /*
+ * The test can set the semihosting command line to the target
+ * EL needed for the test. However if no semihosting args are set we will
+ * end up with -kernel/-append data (see semihosting_arg_fallback).
+ * Keep the normalised target in w11.
+ */
+ mov x0, SYS_GET_CMDLINE
+ adr x1, .get_cmd
+ semihosting_call
+ adrp x10, cmdline
+ add x10, x10, :lo12:cmdline
+ ldrb w11, [x10]
+
+ /* sanity check, normalise char to EL, clamp to 1 if outside range */
+ subs w11, w11, #'0'
+ b.lt el_default
+ cmp w11, #3
+ b.gt el_default
+ b 1f
+
+el_high:
+ adr x1, .high_el_msg
+ b exit_msg
+
+el_default:
+ mov w11, #1
+
+1:
+ /* Determine current Exception Level */
+ mrs x0, CurrentEL
+ lsr x0, x0, #2 /* CurrentEL[3:2] contains the current EL */
+
+ /* Are we already in a lower EL than we want? */
+ cmp w11, w0
+ bgt el_high
+
+ /* Branch based on current EL */
+ cmp x0, #3
+ b.eq setup_el3
+ cmp x0, #2
+ b.eq setup_el2
+ cmp x0, #1
+ b.eq at_testel /* Already at EL1, skip transition */
+
+ /* Should not be at EL0 - error out */
+ adr x1, .unexp_el0
+ b exit_msg
+
+setup_el3:
+ /* Ensure we trap if we get anything wrong */
+ adr x0, vector_table
+ msr vbar_el3, x0
+
+ /* Does the test want to be at EL3? */
+ cmp w11, #3
+ beq at_testel
+
+ /* Configure EL3 to for lower states (EL2 or EL1) */
+ mrs x0, scr_el3
+ orr x0, x0, #(1 << 10) /* RW = 1: EL2/EL1 execution state is AArch64 */
+ orr x0, x0, #(1 << 0) /* NS = 1: Non-secure state */
+ msr scr_el3, x0
+
+ /*
+ * We need to check if EL2 is actually enabled via ID_AA64PFR0_EL1,
+ * otherwise we should just jump straight to EL1.
+ */
+ mrs x0, id_aa64pfr0_el1
+ ubfx x0, x0, #8, #4 /* Extract EL2 field (bits 11:8) */
+ cbz x0, el2_not_present /* If field is 0 no EL2 */
+
+
+ /* Prepare SPSR for exception return to EL2 */
+ mov x0, #0x3c9 /* DAIF bits and EL2h mode (9) */
+ msr spsr_el3, x0
+
+ /* Set EL2 entry point */
+ adr x0, setup_el2
+ msr elr_el3, x0
+
+ /* Return to EL2 */
+ eret
+
+el2_not_present:
+ /* Initialize SCTLR_EL1 with reset value */
+ msr sctlr_el1, xzr
+
+ /* Set EL1 entry point */
+ adr x0, at_testel
+ msr elr_el3, x0
+
+ /* Prepare SPSR for exception return to EL1h with interrupts masked */
+ mov x0, #0x3c5 /* DAIF bits and EL1h mode (5) */
+ msr spsr_el3, x0
+
+ isb /* Synchronization barrier */
+ eret /* Jump to EL1 */
+
+setup_el2:
+ /* Ensure we trap if we get anything wrong */
+ adr x0, vector_table
+ msr vbar_el2, x0
+
+ /* Does the test want to be at EL2? */
+ cmp w11, #2
+ beq at_testel
+
+ /* Configure EL2 to allow transition to EL1 */
+ mrs x0, hcr_el2
+ orr x0, x0, #(1 << 31) /* RW = 1: EL1 execution state is AArch64 */
+ msr hcr_el2, x0
+
+ /* Initialize SCTLR_EL1 with reset value */
+ msr sctlr_el1, xzr
+
+ /* Set EL1 entry point */
+ adr x0, at_testel
+ msr elr_el2, x0
+
+ /* Prepare SPSR for exception return to EL1 */
+ mov x0, #(0x5 << 0) /* EL1h (SPx), with interrupts disabled */
+ msr spsr_el2, x0
+
+ /* Return to EL1 */
+ eret
+
+ /*
+ * At the target EL for the test, usually EL1. Note we still
+ * set everything up as if we were at EL1.
+ */
+at_testel:
/* Installs a table of exception vectors to catch and handle all
exceptions by terminating the process with a diagnostic. */
adr x0, vector_table
@@ -100,7 +252,7 @@ __start:
* maps RAM to the first Gb. The stage2 tables have two 2mb
* translation block entries covering a series of adjacent
* 4k pages.
- */
+ */
/* Stage 1 entry: indexed by IA[38:30] */
adr x1, . /* phys address */
@@ -198,7 +350,8 @@ __start:
orr x0, x0, #(3 << 16)
msr cpacr_el1, x0
- /* Setup some stack space and enter the test code.
+ /*
+ * Setup some stack space before we enter the test code.
* Assume everything except the return value is garbage when we
* return, we won't need it.
*/
@@ -233,6 +386,11 @@ __sys_outc:
ret
.data
+
+ .align 8
+cmdline:
+ .space 128, 0
+
.align 12
/* Translation table
@@ -246,6 +404,10 @@ ttb_stage2:
.space 4096, 0
.align 12
+system_stack:
+ .space 4096, 0
+system_stack_end:
+
stack:
.space 65536, 0
stack_end:
diff --git a/tests/tcg/x86_64/fma.c b/tests/tcg/x86_64/fma.c
index 09c622e..3421961 100644
--- a/tests/tcg/x86_64/fma.c
+++ b/tests/tcg/x86_64/fma.c
@@ -79,14 +79,21 @@ static testdata tests[] = {
/*
* Flushing of denormal outputs to zero should also happen after
* rounding, so setting FTZ should not affect the result or the flags.
- * QEMU currently does not emulate this correctly because we do the
- * flush-to-zero check before rounding, so we incorrectly produce a
- * zero result and set Underflow as well as Precision.
*/
-#ifdef ENABLE_FAILING_TESTS
{ 0x3fdfffffffffffff, 0x001fffffffffffff, 0x801fffffffffffff, true,
0x8010000000000000, 0x20 }, /* Enabling FTZ shouldn't change flags */
-#endif
+ /*
+ * normal * 0 + a denormal. With FTZ disabled this gives an exact
+ * result (equal to the input denormal) that has consumed the denormal.
+ */
+ { 0x3cc8000000000000, 0x0000000000000000, 0x8008000000000000, false,
+ 0x8008000000000000, 0x2 }, /* Denormal */
+ /*
+ * With FTZ enabled, this consumes the denormal, returns zero (because
+ * flushed) and indicates also Underflow and Precision.
+ */
+ { 0x3cc8000000000000, 0x0000000000000000, 0x8008000000000000, true,
+ 0x8000000000000000, 0x32 }, /* Precision, Underflow, Denormal */
};
int main(void)
diff --git a/tests/unit/test-aio-multithread.c b/tests/unit/test-aio-multithread.c
index 08d4570..0ead6bf 100644
--- a/tests/unit/test-aio-multithread.c
+++ b/tests/unit/test-aio-multithread.c
@@ -305,7 +305,9 @@ static void mcs_mutex_lock(void)
prev = qatomic_xchg(&mutex_head, id);
if (prev != -1) {
qatomic_set(&nodes[prev].next, id);
- qemu_futex_wait(&nodes[id].locked, 1);
+ while (qatomic_read(&nodes[id].locked) == 1) {
+ qemu_futex_wait(&nodes[id].locked, 1);
+ }
}
}
@@ -328,7 +330,7 @@ static void mcs_mutex_unlock(void)
/* Wake up the next in line. */
next = qatomic_read(&nodes[id].next);
nodes[next].locked = 0;
- qemu_futex_wake(&nodes[next].locked, 1);
+ qemu_futex_wake_single(&nodes[next].locked);
}
static void test_multi_fair_mutex_entry(void *opaque)
diff --git a/tests/unit/test-bdrv-drain.c b/tests/unit/test-bdrv-drain.c
index 290cd2a..59c2793 100644
--- a/tests/unit/test-bdrv-drain.c
+++ b/tests/unit/test-bdrv-drain.c
@@ -772,9 +772,11 @@ static void test_blockjob_common_drain_node(enum drain_type drain_type,
tjob->bs = src;
job = &tjob->common;
+ bdrv_drain_all_begin();
bdrv_graph_wrlock();
block_job_add_bdrv(job, "target", target, 0, BLK_PERM_ALL, &error_abort);
bdrv_graph_wrunlock();
+ bdrv_drain_all_end();
switch (result) {
case TEST_JOB_SUCCESS:
@@ -953,11 +955,13 @@ static void bdrv_test_top_close(BlockDriverState *bs)
{
BdrvChild *c, *next_c;
+ bdrv_drain_all_begin();
bdrv_graph_wrlock();
QLIST_FOREACH_SAFE(c, &bs->children, next, next_c) {
bdrv_unref_child(bs, c);
}
bdrv_graph_wrunlock();
+ bdrv_drain_all_end();
}
static int coroutine_fn GRAPH_RDLOCK
@@ -1014,7 +1018,9 @@ static void coroutine_fn test_co_delete_by_drain(void *opaque)
bdrv_graph_co_rdlock();
QLIST_FOREACH_SAFE(c, &bs->children, next, next_c) {
bdrv_graph_co_rdunlock();
+ bdrv_drain_all_begin();
bdrv_co_unref_child(bs, c);
+ bdrv_drain_all_end();
bdrv_graph_co_rdlock();
}
bdrv_graph_co_rdunlock();
@@ -1047,10 +1053,12 @@ static void do_test_delete_by_drain(bool detach_instead_of_delete,
null_bs = bdrv_open("null-co://", NULL, NULL, BDRV_O_RDWR | BDRV_O_PROTOCOL,
&error_abort);
+ bdrv_drain_all_begin();
bdrv_graph_wrlock();
bdrv_attach_child(bs, null_bs, "null-child", &child_of_bds,
BDRV_CHILD_DATA, &error_abort);
bdrv_graph_wrunlock();
+ bdrv_drain_all_end();
/* This child will be the one to pass to requests through to, and
* it will stall until a drain occurs */
@@ -1058,21 +1066,25 @@ static void do_test_delete_by_drain(bool detach_instead_of_delete,
&error_abort);
child_bs->total_sectors = 65536 >> BDRV_SECTOR_BITS;
/* Takes our reference to child_bs */
+ bdrv_drain_all_begin();
bdrv_graph_wrlock();
tts->wait_child = bdrv_attach_child(bs, child_bs, "wait-child",
&child_of_bds,
BDRV_CHILD_DATA | BDRV_CHILD_PRIMARY,
&error_abort);
bdrv_graph_wrunlock();
+ bdrv_drain_all_end();
/* This child is just there to be deleted
* (for detach_instead_of_delete == true) */
null_bs = bdrv_open("null-co://", NULL, NULL, BDRV_O_RDWR | BDRV_O_PROTOCOL,
&error_abort);
+ bdrv_drain_all_begin();
bdrv_graph_wrlock();
bdrv_attach_child(bs, null_bs, "null-child", &child_of_bds, BDRV_CHILD_DATA,
&error_abort);
bdrv_graph_wrunlock();
+ bdrv_drain_all_end();
blk = blk_new(qemu_get_aio_context(), BLK_PERM_ALL, BLK_PERM_ALL);
blk_insert_bs(blk, bs, &error_abort);
@@ -1155,6 +1167,7 @@ static void no_coroutine_fn detach_indirect_bh(void *opaque)
bdrv_dec_in_flight(data->child_b->bs);
+ bdrv_drain_all_begin();
bdrv_graph_wrlock();
bdrv_unref_child(data->parent_b, data->child_b);
@@ -1163,6 +1176,7 @@ static void no_coroutine_fn detach_indirect_bh(void *opaque)
&child_of_bds, BDRV_CHILD_DATA,
&error_abort);
bdrv_graph_wrunlock();
+ bdrv_drain_all_end();
}
static void coroutine_mixed_fn detach_by_parent_aio_cb(void *opaque, int ret)
@@ -1260,6 +1274,7 @@ static void TSA_NO_TSA test_detach_indirect(bool by_parent_cb)
/* Set child relationships */
bdrv_ref(b);
bdrv_ref(a);
+ bdrv_drain_all_begin();
bdrv_graph_wrlock();
child_b = bdrv_attach_child(parent_b, b, "PB-B", &child_of_bds,
BDRV_CHILD_DATA, &error_abort);
@@ -1271,6 +1286,7 @@ static void TSA_NO_TSA test_detach_indirect(bool by_parent_cb)
by_parent_cb ? &child_of_bds : &detach_by_driver_cb_class,
BDRV_CHILD_DATA, &error_abort);
bdrv_graph_wrunlock();
+ bdrv_drain_all_end();
g_assert_cmpint(parent_a->refcnt, ==, 1);
g_assert_cmpint(parent_b->refcnt, ==, 1);
@@ -1396,14 +1412,10 @@ static void test_set_aio_context(void)
bs = bdrv_new_open_driver(&bdrv_test, "test-node", BDRV_O_RDWR,
&error_abort);
- bdrv_drained_begin(bs);
bdrv_try_change_aio_context(bs, ctx_a, NULL, &error_abort);
- bdrv_drained_end(bs);
- bdrv_drained_begin(bs);
bdrv_try_change_aio_context(bs, ctx_b, NULL, &error_abort);
bdrv_try_change_aio_context(bs, qemu_get_aio_context(), NULL, &error_abort);
- bdrv_drained_end(bs);
bdrv_unref(bs);
iothread_join(a);
@@ -1687,6 +1699,7 @@ static void test_drop_intermediate_poll(void)
* Establish the chain last, so the chain links are the first
* elements in the BDS.parents lists
*/
+ bdrv_drain_all_begin();
bdrv_graph_wrlock();
for (i = 0; i < 3; i++) {
if (i) {
@@ -1696,6 +1709,7 @@ static void test_drop_intermediate_poll(void)
}
}
bdrv_graph_wrunlock();
+ bdrv_drain_all_end();
job = block_job_create("job", &test_simple_job_driver, NULL, job_node,
0, BLK_PERM_ALL, 0, 0, NULL, NULL, &error_abort);
@@ -1942,10 +1956,12 @@ static void do_test_replace_child_mid_drain(int old_drain_count,
new_child_bs->total_sectors = 1;
bdrv_ref(old_child_bs);
+ bdrv_drain_all_begin();
bdrv_graph_wrlock();
bdrv_attach_child(parent_bs, old_child_bs, "child", &child_of_bds,
BDRV_CHILD_COW, &error_abort);
bdrv_graph_wrunlock();
+ bdrv_drain_all_end();
parent_s->setup_completed = true;
for (i = 0; i < old_drain_count; i++) {
diff --git a/tests/unit/test-bdrv-graph-mod.c b/tests/unit/test-bdrv-graph-mod.c
index d743abb..7b03ebe 100644
--- a/tests/unit/test-bdrv-graph-mod.c
+++ b/tests/unit/test-bdrv-graph-mod.c
@@ -137,10 +137,12 @@ static void test_update_perm_tree(void)
blk_insert_bs(root, bs, &error_abort);
+ bdrv_drain_all_begin();
bdrv_graph_wrlock();
bdrv_attach_child(filter, bs, "child", &child_of_bds,
BDRV_CHILD_DATA, &error_abort);
bdrv_graph_wrunlock();
+ bdrv_drain_all_end();
ret = bdrv_append(filter, bs, NULL);
g_assert_cmpint(ret, <, 0);
@@ -204,11 +206,13 @@ static void test_should_update_child(void)
bdrv_set_backing_hd(target, bs, &error_abort);
+ bdrv_drain_all_begin();
bdrv_graph_wrlock();
g_assert(target->backing->bs == bs);
bdrv_attach_child(filter, target, "target", &child_of_bds,
BDRV_CHILD_DATA, &error_abort);
bdrv_graph_wrunlock();
+ bdrv_drain_all_end();
bdrv_append(filter, bs, &error_abort);
bdrv_graph_rdlock_main_loop();
@@ -244,6 +248,7 @@ static void test_parallel_exclusive_write(void)
bdrv_ref(base);
bdrv_ref(fl1);
+ bdrv_drain_all_begin();
bdrv_graph_wrlock();
bdrv_attach_child(top, fl1, "backing", &child_of_bds,
BDRV_CHILD_FILTERED | BDRV_CHILD_PRIMARY,
@@ -257,6 +262,7 @@ static void test_parallel_exclusive_write(void)
bdrv_replace_node(fl1, fl2, &error_abort);
bdrv_graph_wrunlock();
+ bdrv_drain_all_end();
bdrv_drained_end(fl2);
bdrv_drained_end(fl1);
@@ -363,6 +369,7 @@ static void test_parallel_perm_update(void)
*/
bdrv_ref(base);
+ bdrv_drain_all_begin();
bdrv_graph_wrlock();
bdrv_attach_child(top, ws, "file", &child_of_bds, BDRV_CHILD_DATA,
&error_abort);
@@ -377,6 +384,7 @@ static void test_parallel_perm_update(void)
BDRV_CHILD_FILTERED | BDRV_CHILD_PRIMARY,
&error_abort);
bdrv_graph_wrunlock();
+ bdrv_drain_all_end();
/* Select fl1 as first child to be active */
s->selected = c_fl1;
@@ -430,11 +438,13 @@ static void test_append_greedy_filter(void)
BlockDriverState *base = no_perm_node("base");
BlockDriverState *fl = exclusive_writer_node("fl1");
+ bdrv_drain_all_begin();
bdrv_graph_wrlock();
bdrv_attach_child(top, base, "backing", &child_of_bds,
BDRV_CHILD_FILTERED | BDRV_CHILD_PRIMARY,
&error_abort);
bdrv_graph_wrunlock();
+ bdrv_drain_all_end();
bdrv_append(fl, base, &error_abort);
bdrv_unref(fl);
diff --git a/tests/unit/test-char.c b/tests/unit/test-char.c
index 60a843b..f30a39f 100644
--- a/tests/unit/test-char.c
+++ b/tests/unit/test-char.c
@@ -993,7 +993,7 @@ static void char_udp_test_internal(Chardev *reuse_chr, int sock)
struct sockaddr_in other;
SocketIdleData d = { 0, };
Chardev *chr;
- CharBackend *be;
+ CharBackend stack_be, *be = &stack_be;
socklen_t alen = sizeof(other);
int ret;
char buf[10];
@@ -1009,7 +1009,6 @@ static void char_udp_test_internal(Chardev *reuse_chr, int sock)
chr = qemu_chr_new("client", tmp, NULL);
g_assert_nonnull(chr);
- be = g_alloca(sizeof(CharBackend));
qemu_chr_fe_init(be, chr, &error_abort);
}
diff --git a/tests/vm/README b/tests/vm/README
index f9c04cc..14ac323 100644
--- a/tests/vm/README
+++ b/tests/vm/README
@@ -1 +1 @@
-See docs/devel/testing.rst for help.
+See docs/devel/testing/main.rst for help.