aboutsummaryrefslogtreecommitdiff
path: root/tests
diff options
context:
space:
mode:
Diffstat (limited to 'tests')
-rw-r--r--tests/data/acpi/pc/DSDTbin5125 -> 5014 bytes
-rw-r--r--tests/data/acpi/pc/DSDT.acpihmatbin6449 -> 6338 bytes
-rw-r--r--tests/data/acpi/pc/DSDT.bridgebin6984 -> 6873 bytes
-rw-r--r--tests/data/acpi/pc/DSDT.cphpbin5588 -> 5477 bytes
-rw-r--r--tests/data/acpi/pc/DSDT.dimmpxmbin6778 -> 6667 bytes
-rw-r--r--tests/data/acpi/pc/DSDT.ipmikcsbin5197 -> 5086 bytes
-rw-r--r--tests/data/acpi/pc/DSDT.memhpbin6484 -> 6373 bytes
-rw-r--r--tests/data/acpi/pc/DSDT.numamembin5131 -> 5020 bytes
-rw-r--r--tests/data/acpi/pc/SRAT.dimmpxmbin392 -> 392 bytes
-rw-r--r--tests/data/acpi/q35/DSDTbin7863 -> 7752 bytes
-rw-r--r--tests/data/acpi/q35/DSDT.acpihmatbin9187 -> 9076 bytes
-rw-r--r--tests/data/acpi/q35/DSDT.bridgebin7880 -> 7769 bytes
-rw-r--r--tests/data/acpi/q35/DSDT.cphpbin8326 -> 8215 bytes
-rw-r--r--tests/data/acpi/q35/DSDT.dimmpxmbin9516 -> 9405 bytes
-rw-r--r--tests/data/acpi/q35/DSDT.ipmibtbin7938 -> 7827 bytes
-rw-r--r--tests/data/acpi/q35/DSDT.memhpbin9222 -> 9111 bytes
-rw-r--r--tests/data/acpi/q35/DSDT.mmio64bin8993 -> 8882 bytes
-rw-r--r--tests/data/acpi/q35/DSDT.numamembin7869 -> 7758 bytes
-rw-r--r--tests/data/acpi/q35/DSDT.tisbin0 -> 8357 bytes
-rw-r--r--tests/data/acpi/q35/SRAT.dimmpxmbin392 -> 392 bytes
-rw-r--r--tests/data/acpi/q35/TPM2.tisbin0 -> 76 bytes
-rw-r--r--tests/data/acpi/virt/SRAT.memhpbin186 -> 226 bytes
-rw-r--r--tests/decode/err_pattern_group_nest1.decode11
-rw-r--r--tests/decode/err_pattern_group_nest2.decode6
-rw-r--r--tests/decode/err_pattern_group_nest3.decode14
-rw-r--r--tests/decode/succ_pattern_group_nest2.decode13
-rw-r--r--tests/decode/succ_pattern_group_nest3.decode11
-rw-r--r--tests/decode/succ_pattern_group_nest4.decode13
-rw-r--r--tests/docker/Makefile.include2
-rw-r--r--tests/docker/dockerfiles/centos7.docker2
-rw-r--r--tests/docker/dockerfiles/centos8.docker2
-rw-r--r--tests/docker/dockerfiles/debian-xtensa-cross.docker2
-rw-r--r--tests/docker/dockerfiles/debian10.docker2
-rw-r--r--tests/docker/dockerfiles/debian9.docker2
-rw-r--r--tests/docker/dockerfiles/fedora.docker2
-rw-r--r--tests/docker/dockerfiles/ubuntu.docker4
-rw-r--r--tests/docker/dockerfiles/ubuntu1804.docker2
-rw-r--r--tests/plugin/mem.c2
-rw-r--r--tests/qemu-iotests/031.out22
-rw-r--r--tests/qemu-iotests/036.out4
-rw-r--r--tests/qemu-iotests/061.out14
-rwxr-xr-xtests/qemu-iotests/1434
-rw-r--r--tests/qemu-iotests/143.out2
-rwxr-xr-xtests/qemu-iotests/19410
-rw-r--r--tests/qemu-iotests/194.out5
-rwxr-xr-xtests/qemu-iotests/2918
-rw-r--r--tests/qemu-iotests/291.out37
-rwxr-xr-xtests/qemu-iotests/qcow2.py218
-rw-r--r--tests/qemu-iotests/qcow2_format.py286
-rw-r--r--tests/qtest/Makefile.include1
-rw-r--r--tests/qtest/bios-tables-test.c58
-rw-r--r--tests/qtest/tpm-emu.c1
-rw-r--r--tests/qtest/tpm-emu.h3
-rw-r--r--tests/tcg/arm/Makefile.target2
-rw-r--r--tests/tcg/arm/commpage.c61
-rwxr-xr-xtests/vm/fedora1
-rwxr-xr-xtests/vm/freebsd1
-rwxr-xr-xtests/vm/netbsd1
-rwxr-xr-xtests/vm/openbsd1
-rwxr-xr-xtests/vm/ubuntu.i3862
60 files changed, 612 insertions, 220 deletions
diff --git a/tests/data/acpi/pc/DSDT b/tests/data/acpi/pc/DSDT
index ad4b2d46cc..384a82dbb3 100644
--- a/tests/data/acpi/pc/DSDT
+++ b/tests/data/acpi/pc/DSDT
Binary files differ
diff --git a/tests/data/acpi/pc/DSDT.acpihmat b/tests/data/acpi/pc/DSDT.acpihmat
index eff7aadfab..47ddfdb027 100644
--- a/tests/data/acpi/pc/DSDT.acpihmat
+++ b/tests/data/acpi/pc/DSDT.acpihmat
Binary files differ
diff --git a/tests/data/acpi/pc/DSDT.bridge b/tests/data/acpi/pc/DSDT.bridge
index 92ae808e2e..d1e2fa9fb8 100644
--- a/tests/data/acpi/pc/DSDT.bridge
+++ b/tests/data/acpi/pc/DSDT.bridge
Binary files differ
diff --git a/tests/data/acpi/pc/DSDT.cphp b/tests/data/acpi/pc/DSDT.cphp
index f357235851..54f481faf1 100644
--- a/tests/data/acpi/pc/DSDT.cphp
+++ b/tests/data/acpi/pc/DSDT.cphp
Binary files differ
diff --git a/tests/data/acpi/pc/DSDT.dimmpxm b/tests/data/acpi/pc/DSDT.dimmpxm
index 7fa09463c1..5d98016ae5 100644
--- a/tests/data/acpi/pc/DSDT.dimmpxm
+++ b/tests/data/acpi/pc/DSDT.dimmpxm
Binary files differ
diff --git a/tests/data/acpi/pc/DSDT.ipmikcs b/tests/data/acpi/pc/DSDT.ipmikcs
index 469d13e1f6..57b7835874 100644
--- a/tests/data/acpi/pc/DSDT.ipmikcs
+++ b/tests/data/acpi/pc/DSDT.ipmikcs
Binary files differ
diff --git a/tests/data/acpi/pc/DSDT.memhp b/tests/data/acpi/pc/DSDT.memhp
index aee75bea27..8cb90ef14e 100644
--- a/tests/data/acpi/pc/DSDT.memhp
+++ b/tests/data/acpi/pc/DSDT.memhp
Binary files differ
diff --git a/tests/data/acpi/pc/DSDT.numamem b/tests/data/acpi/pc/DSDT.numamem
index 9a747f6f08..f194bc6394 100644
--- a/tests/data/acpi/pc/DSDT.numamem
+++ b/tests/data/acpi/pc/DSDT.numamem
Binary files differ
diff --git a/tests/data/acpi/pc/SRAT.dimmpxm b/tests/data/acpi/pc/SRAT.dimmpxm
index f5c0267ea2..5a13c61b90 100644
--- a/tests/data/acpi/pc/SRAT.dimmpxm
+++ b/tests/data/acpi/pc/SRAT.dimmpxm
Binary files differ
diff --git a/tests/data/acpi/q35/DSDT b/tests/data/acpi/q35/DSDT
index 9fa4d5a405..6a5e4dd85a 100644
--- a/tests/data/acpi/q35/DSDT
+++ b/tests/data/acpi/q35/DSDT
Binary files differ
diff --git a/tests/data/acpi/q35/DSDT.acpihmat b/tests/data/acpi/q35/DSDT.acpihmat
index 2d834a854c..c1dd7773f3 100644
--- a/tests/data/acpi/q35/DSDT.acpihmat
+++ b/tests/data/acpi/q35/DSDT.acpihmat
Binary files differ
diff --git a/tests/data/acpi/q35/DSDT.bridge b/tests/data/acpi/q35/DSDT.bridge
index b75122b24a..2ef1e894a3 100644
--- a/tests/data/acpi/q35/DSDT.bridge
+++ b/tests/data/acpi/q35/DSDT.bridge
Binary files differ
diff --git a/tests/data/acpi/q35/DSDT.cphp b/tests/data/acpi/q35/DSDT.cphp
index c59c19ff46..74e86176e5 100644
--- a/tests/data/acpi/q35/DSDT.cphp
+++ b/tests/data/acpi/q35/DSDT.cphp
Binary files differ
diff --git a/tests/data/acpi/q35/DSDT.dimmpxm b/tests/data/acpi/q35/DSDT.dimmpxm
index 9edc104ee6..4bf8e9d64b 100644
--- a/tests/data/acpi/q35/DSDT.dimmpxm
+++ b/tests/data/acpi/q35/DSDT.dimmpxm
Binary files differ
diff --git a/tests/data/acpi/q35/DSDT.ipmibt b/tests/data/acpi/q35/DSDT.ipmibt
index 3910e9b767..38723daef8 100644
--- a/tests/data/acpi/q35/DSDT.ipmibt
+++ b/tests/data/acpi/q35/DSDT.ipmibt
Binary files differ
diff --git a/tests/data/acpi/q35/DSDT.memhp b/tests/data/acpi/q35/DSDT.memhp
index 8461e984c9..98328d1c41 100644
--- a/tests/data/acpi/q35/DSDT.memhp
+++ b/tests/data/acpi/q35/DSDT.memhp
Binary files differ
diff --git a/tests/data/acpi/q35/DSDT.mmio64 b/tests/data/acpi/q35/DSDT.mmio64
index fc0cc096ba..5916c0e9ce 100644
--- a/tests/data/acpi/q35/DSDT.mmio64
+++ b/tests/data/acpi/q35/DSDT.mmio64
Binary files differ
diff --git a/tests/data/acpi/q35/DSDT.numamem b/tests/data/acpi/q35/DSDT.numamem
index 498c843be1..cf3fde3449 100644
--- a/tests/data/acpi/q35/DSDT.numamem
+++ b/tests/data/acpi/q35/DSDT.numamem
Binary files differ
diff --git a/tests/data/acpi/q35/DSDT.tis b/tests/data/acpi/q35/DSDT.tis
new file mode 100644
index 0000000000..56b6fb0c32
--- /dev/null
+++ b/tests/data/acpi/q35/DSDT.tis
Binary files differ
diff --git a/tests/data/acpi/q35/SRAT.dimmpxm b/tests/data/acpi/q35/SRAT.dimmpxm
index f5c0267ea2..5a13c61b90 100644
--- a/tests/data/acpi/q35/SRAT.dimmpxm
+++ b/tests/data/acpi/q35/SRAT.dimmpxm
Binary files differ
diff --git a/tests/data/acpi/q35/TPM2.tis b/tests/data/acpi/q35/TPM2.tis
new file mode 100644
index 0000000000..7878a6e79a
--- /dev/null
+++ b/tests/data/acpi/q35/TPM2.tis
Binary files differ
diff --git a/tests/data/acpi/virt/SRAT.memhp b/tests/data/acpi/virt/SRAT.memhp
index 1b57db2072..9a35adb40c 100644
--- a/tests/data/acpi/virt/SRAT.memhp
+++ b/tests/data/acpi/virt/SRAT.memhp
Binary files differ
diff --git a/tests/decode/err_pattern_group_nest1.decode b/tests/decode/err_pattern_group_nest1.decode
index 92e971c3c5..7d09891a1c 100644
--- a/tests/decode/err_pattern_group_nest1.decode
+++ b/tests/decode/err_pattern_group_nest1.decode
@@ -3,11 +3,12 @@
%sub1 0:8
%sub2 8:8
-%sub3 16:8
-%sub4 24:8
-# Groups with no overlap are supposed to fail
+# Make sure braces are matched
{
- top 00000000 00000000 00000000 00000000
- sub4 ........ ........ ........ ........ %sub1 %sub2 %sub3 %sub4
+ top 00000000 00000000 00000000 00000000
+ [
+ sub1 00000000 00000000 00000000 ........ %sub1
+ sub2 00000000 00000000 ........ ........ %sub1 %sub2
+ }
}
diff --git a/tests/decode/err_pattern_group_nest2.decode b/tests/decode/err_pattern_group_nest2.decode
new file mode 100644
index 0000000000..c172239e9b
--- /dev/null
+++ b/tests/decode/err_pattern_group_nest2.decode
@@ -0,0 +1,6 @@
+# This work is licensed under the terms of the GNU LGPL, version 2 or later.
+# See the COPYING.LIB file in the top-level directory.
+
+# Make sure braces are matched
+{
+ [
diff --git a/tests/decode/err_pattern_group_nest3.decode b/tests/decode/err_pattern_group_nest3.decode
new file mode 100644
index 0000000000..b085d01410
--- /dev/null
+++ b/tests/decode/err_pattern_group_nest3.decode
@@ -0,0 +1,14 @@
+# This work is licensed under the terms of the GNU LGPL, version 2 or later.
+# See the COPYING.LIB file in the top-level directory.
+
+%sub1 0:8
+%sub2 8:8
+
+# The exclusive group should error for overlap.
+{
+ top 00000000 00000000 00000000 00000000
+ [
+ sub1 00000000 00000000 00000000 ........ %sub1
+ sub2 00000000 00000000 ........ ........ %sub1 %sub2
+ ]
+}
diff --git a/tests/decode/succ_pattern_group_nest2.decode b/tests/decode/succ_pattern_group_nest2.decode
new file mode 100644
index 0000000000..8d5ab4b2d3
--- /dev/null
+++ b/tests/decode/succ_pattern_group_nest2.decode
@@ -0,0 +1,13 @@
+# This work is licensed under the terms of the GNU LGPL, version 2 or later.
+# See the COPYING.LIB file in the top-level directory.
+
+%sub1 0:8
+%sub2 8:8
+%sub3 16:8
+%sub4 24:8
+
+# Group with complete overlap of the two patterns
+{
+ top 00000000 00000000 00000000 00000000
+ sub4 ........ ........ ........ ........ %sub1 %sub2 %sub3 %sub4
+}
diff --git a/tests/decode/succ_pattern_group_nest3.decode b/tests/decode/succ_pattern_group_nest3.decode
new file mode 100644
index 0000000000..156249f090
--- /dev/null
+++ b/tests/decode/succ_pattern_group_nest3.decode
@@ -0,0 +1,11 @@
+# This work is licensed under the terms of the GNU LGPL, version 2 or later.
+# See the COPYING.LIB file in the top-level directory.
+
+{
+ [
+ sub1 00000000 a:8 b:8 c:8
+ sub2 00000001 a:8 b:8 c:8
+ sub3 00000010 a:8 b:8 c:8
+ ]
+ sub4 000000 d:2 a:8 b:8 c:8
+}
diff --git a/tests/decode/succ_pattern_group_nest4.decode b/tests/decode/succ_pattern_group_nest4.decode
new file mode 100644
index 0000000000..dc54a1d285
--- /dev/null
+++ b/tests/decode/succ_pattern_group_nest4.decode
@@ -0,0 +1,13 @@
+# This work is licensed under the terms of the GNU LGPL, version 2 or later.
+# See the COPYING.LIB file in the top-level directory.
+
+# Verify deeper nesting, and a single element in the groups.
+{
+ [
+ {
+ [
+ sub1 00000000 a:8 b:8 c:8
+ ]
+ }
+ ]
+}
diff --git a/tests/docker/Makefile.include b/tests/docker/Makefile.include
index f32a95b488..3e3617816e 100644
--- a/tests/docker/Makefile.include
+++ b/tests/docker/Makefile.include
@@ -130,7 +130,7 @@ docker-image-debian-sparc64-cross: docker-image-debian10
docker-image-travis: NOUSER=1
# Specialist build images, sometimes very limited tools
-docker-image-tricore-cross: docker-image-debian9
+docker-image-debian-tricore-cross: docker-image-debian9
docker-image-debian-arm64-test-cross: docker-image-debian11
# These images may be good enough for building tests but not for test builds
diff --git a/tests/docker/dockerfiles/centos7.docker b/tests/docker/dockerfiles/centos7.docker
index 9a2a2e515d..e197acdc3c 100644
--- a/tests/docker/dockerfiles/centos7.docker
+++ b/tests/docker/dockerfiles/centos7.docker
@@ -5,13 +5,11 @@ RUN yum -y update
# Please keep this list sorted alphabetically
ENV PACKAGES \
- bison \
bzip2 \
bzip2-devel \
ccache \
csnappy-devel \
dbus-daemon \
- flex \
gcc-c++ \
gcc \
gettext \
diff --git a/tests/docker/dockerfiles/centos8.docker b/tests/docker/dockerfiles/centos8.docker
index bfa0d33c9c..9852c5b9ee 100644
--- a/tests/docker/dockerfiles/centos8.docker
+++ b/tests/docker/dockerfiles/centos8.docker
@@ -3,11 +3,9 @@ FROM centos:8.1.1911
RUN dnf -y update
ENV PACKAGES \
SDL-devel \
- bison \
bzip2 \
bzip2-devel \
dbus-daemon \
- flex \
gcc \
gcc-c++ \
gettext \
diff --git a/tests/docker/dockerfiles/debian-xtensa-cross.docker b/tests/docker/dockerfiles/debian-xtensa-cross.docker
index e6f93f65ee..beb73f46ba 100644
--- a/tests/docker/dockerfiles/debian-xtensa-cross.docker
+++ b/tests/docker/dockerfiles/debian-xtensa-cross.docker
@@ -11,11 +11,9 @@ RUN apt-get update && \
DEBIAN_FRONTEND=noninteractive apt install -yy eatmydata && \
DEBIAN_FRONTEND=noninteractive eatmydata \
apt-get install -y --no-install-recommends \
- bison \
build-essential \
ca-certificates \
curl \
- flex \
gettext \
git \
python3-minimal
diff --git a/tests/docker/dockerfiles/debian10.docker b/tests/docker/dockerfiles/debian10.docker
index 0769700a41..bcdff04ddf 100644
--- a/tests/docker/dockerfiles/debian10.docker
+++ b/tests/docker/dockerfiles/debian10.docker
@@ -18,12 +18,10 @@ RUN apt update && \
DEBIAN_FRONTEND=noninteractive eatmydata \
apt install -y --no-install-recommends \
bc \
- bison \
build-essential \
ca-certificates \
clang \
dbus \
- flex \
gdb-multiarch \
gettext \
git \
diff --git a/tests/docker/dockerfiles/debian9.docker b/tests/docker/dockerfiles/debian9.docker
index 08cc970feb..0f0ebe530a 100644
--- a/tests/docker/dockerfiles/debian9.docker
+++ b/tests/docker/dockerfiles/debian9.docker
@@ -18,11 +18,9 @@ RUN apt update && \
DEBIAN_FRONTEND=noninteractive eatmydata \
apt install -y --no-install-recommends \
bc \
- bison \
build-essential \
ca-certificates \
clang \
- flex \
gdb-multiarch \
gettext \
git \
diff --git a/tests/docker/dockerfiles/fedora.docker b/tests/docker/dockerfiles/fedora.docker
index 179575ecaa..92b6e11c8a 100644
--- a/tests/docker/dockerfiles/fedora.docker
+++ b/tests/docker/dockerfiles/fedora.docker
@@ -3,7 +3,6 @@ FROM fedora:30
# Please keep this list sorted alphabetically
ENV PACKAGES \
bc \
- bison \
brlapi-devel \
bzip2 \
bzip2-devel \
@@ -13,7 +12,6 @@ ENV PACKAGES \
dbus-daemon \
device-mapper-multipath-devel \
findutils \
- flex \
gcc \
gcc-c++ \
gettext \
diff --git a/tests/docker/dockerfiles/ubuntu.docker b/tests/docker/dockerfiles/ubuntu.docker
index eeb3b22bf2..161806e6b8 100644
--- a/tests/docker/dockerfiles/ubuntu.docker
+++ b/tests/docker/dockerfiles/ubuntu.docker
@@ -9,8 +9,8 @@
# system won't pick up that it has changed.
#
-FROM ubuntu:19.04
-ENV PACKAGES flex bison \
+FROM ubuntu:20.04
+ENV PACKAGES \
ccache \
clang \
dbus \
diff --git a/tests/docker/dockerfiles/ubuntu1804.docker b/tests/docker/dockerfiles/ubuntu1804.docker
index f66b06f4cf..a10ea2850b 100644
--- a/tests/docker/dockerfiles/ubuntu1804.docker
+++ b/tests/docker/dockerfiles/ubuntu1804.docker
@@ -1,5 +1,5 @@
FROM ubuntu:18.04
-ENV PACKAGES flex bison \
+ENV PACKAGES \
ccache \
clang \
gcc \
diff --git a/tests/plugin/mem.c b/tests/plugin/mem.c
index 878abf09d1..4725bd851d 100644
--- a/tests/plugin/mem.c
+++ b/tests/plugin/mem.c
@@ -28,7 +28,7 @@ static void plugin_exit(qemu_plugin_id_t id, void *p)
g_string_printf(out, "mem accesses: %" PRIu64 "\n", mem_count);
if (do_haddr) {
- g_string_append_printf(out, "io accesses: %" PRIu64 "\n", mem_count);
+ g_string_append_printf(out, "io accesses: %" PRIu64 "\n", io_count);
}
qemu_plugin_outs(out->str);
}
diff --git a/tests/qemu-iotests/031.out b/tests/qemu-iotests/031.out
index 5a4beda6a2..4b21d6a9ba 100644
--- a/tests/qemu-iotests/031.out
+++ b/tests/qemu-iotests/031.out
@@ -25,7 +25,7 @@ refcount_order 4
header_length 72
Header extension:
-magic 0x12345678
+magic 0x12345678 (<unknown>)
length 31
data 'This is a test header extension'
@@ -53,7 +53,7 @@ refcount_order 4
header_length 72
Header extension:
-magic 0x12345678
+magic 0x12345678 (<unknown>)
length 31
data 'This is a test header extension'
@@ -81,12 +81,12 @@ refcount_order 4
header_length 72
Header extension:
-magic 0xe2792aca
+magic 0xe2792aca (Backing format)
length 11
data 'host_device'
Header extension:
-magic 0x12345678
+magic 0x12345678 (<unknown>)
length 31
data 'This is a test header extension'
@@ -116,12 +116,12 @@ refcount_order 4
header_length 112
Header extension:
-magic 0x6803f857
+magic 0x6803f857 (Feature table)
length 336
data <binary>
Header extension:
-magic 0x12345678
+magic 0x12345678 (<unknown>)
length 31
data 'This is a test header extension'
@@ -149,12 +149,12 @@ refcount_order 4
header_length 112
Header extension:
-magic 0x6803f857
+magic 0x6803f857 (Feature table)
length 336
data <binary>
Header extension:
-magic 0x12345678
+magic 0x12345678 (<unknown>)
length 31
data 'This is a test header extension'
@@ -182,17 +182,17 @@ refcount_order 4
header_length 112
Header extension:
-magic 0xe2792aca
+magic 0xe2792aca (Backing format)
length 11
data 'host_device'
Header extension:
-magic 0x6803f857
+magic 0x6803f857 (Feature table)
length 336
data <binary>
Header extension:
-magic 0x12345678
+magic 0x12345678 (<unknown>)
length 31
data 'This is a test header extension'
diff --git a/tests/qemu-iotests/036.out b/tests/qemu-iotests/036.out
index e409acf60e..a9bed828e5 100644
--- a/tests/qemu-iotests/036.out
+++ b/tests/qemu-iotests/036.out
@@ -25,7 +25,7 @@ incompatible_features []
compatible_features []
autoclear_features [63]
Header extension:
-magic 0x6803f857
+magic 0x6803f857 (Feature table)
length 336
data <binary>
@@ -37,7 +37,7 @@ incompatible_features []
compatible_features []
autoclear_features []
Header extension:
-magic 0x6803f857
+magic 0x6803f857 (Feature table)
length 336
data <binary>
diff --git a/tests/qemu-iotests/061.out b/tests/qemu-iotests/061.out
index a51ad1b5ba..2f03cf045c 100644
--- a/tests/qemu-iotests/061.out
+++ b/tests/qemu-iotests/061.out
@@ -25,7 +25,7 @@ refcount_order 4
header_length 112
Header extension:
-magic 0x6803f857
+magic 0x6803f857 (Feature table)
length 336
data <binary>
@@ -83,7 +83,7 @@ refcount_order 4
header_length 112
Header extension:
-magic 0x6803f857
+magic 0x6803f857 (Feature table)
length 336
data <binary>
@@ -139,7 +139,7 @@ refcount_order 4
header_length 112
Header extension:
-magic 0x6803f857
+magic 0x6803f857 (Feature table)
length 336
data <binary>
@@ -194,7 +194,7 @@ refcount_order 4
header_length 112
Header extension:
-magic 0x6803f857
+magic 0x6803f857 (Feature table)
length 336
data <binary>
@@ -263,7 +263,7 @@ refcount_order 4
header_length 112
Header extension:
-magic 0x6803f857
+magic 0x6803f857 (Feature table)
length 336
data <binary>
@@ -325,7 +325,7 @@ refcount_order 4
header_length 112
Header extension:
-magic 0x6803f857
+magic 0x6803f857 (Feature table)
length 336
data <binary>
@@ -354,7 +354,7 @@ refcount_order 4
header_length 112
Header extension:
-magic 0x6803f857
+magic 0x6803f857 (Feature table)
length 336
data <binary>
diff --git a/tests/qemu-iotests/143 b/tests/qemu-iotests/143
index f649b36195..d2349903b1 100755
--- a/tests/qemu-iotests/143
+++ b/tests/qemu-iotests/143
@@ -58,6 +58,10 @@ _send_qemu_cmd $QEMU_HANDLE \
$QEMU_IO_PROG -f raw -c quit \
"nbd+unix:///no_such_export?socket=$SOCK_DIR/nbd" 2>&1 \
| _filter_qemu_io | _filter_nbd
+# Likewise, with longest possible name permitted in NBD protocol
+$QEMU_IO_PROG -f raw -c quit \
+ "nbd+unix:///$(printf %4096d 1 | tr ' ' a)?socket=$SOCK_DIR/nbd" 2>&1 \
+ | _filter_qemu_io | _filter_nbd | sed 's/aaaa*aa/aa--aa/'
_send_qemu_cmd $QEMU_HANDLE \
"{ 'execute': 'quit' }" \
diff --git a/tests/qemu-iotests/143.out b/tests/qemu-iotests/143.out
index 1f4001c601..fc9c0a761f 100644
--- a/tests/qemu-iotests/143.out
+++ b/tests/qemu-iotests/143.out
@@ -5,6 +5,8 @@ QA output created by 143
{"return": {}}
qemu-io: can't open device nbd+unix:///no_such_export?socket=SOCK_DIR/nbd: Requested export not available
server reported: export 'no_such_export' not present
+qemu-io: can't open device nbd+unix:///aa--aa1?socket=SOCK_DIR/nbd: Requested export not available
+server reported: export 'aa--aa...' not present
{ 'execute': 'quit' }
{"return": {}}
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false, "reason": "host-qmp-quit"}}
diff --git a/tests/qemu-iotests/194 b/tests/qemu-iotests/194
index 3fad7c6c1a..da7c4265ec 100755
--- a/tests/qemu-iotests/194
+++ b/tests/qemu-iotests/194
@@ -87,4 +87,14 @@ with iotests.FilePath('source.img') as source_img_path, \
iotests.log(dest_vm.qmp('nbd-server-stop'))
break
+ iotests.log('Wait for migration completion on target...')
+ migr_events = (('MIGRATION', {'data': {'status': 'completed'}}),
+ ('MIGRATION', {'data': {'status': 'failed'}}))
+ event = dest_vm.events_wait(migr_events)
+ iotests.log(event, filters=[iotests.filter_qmp_event])
+
+ iotests.log('Check bitmaps on source:')
iotests.log(source_vm.qmp('query-block')['return'][0]['dirty-bitmaps'])
+
+ iotests.log('Check bitmaps on target:')
+ iotests.log(dest_vm.qmp('query-block')['return'][0]['dirty-bitmaps'])
diff --git a/tests/qemu-iotests/194.out b/tests/qemu-iotests/194.out
index dd60dcc14f..a51bdb2d4f 100644
--- a/tests/qemu-iotests/194.out
+++ b/tests/qemu-iotests/194.out
@@ -21,4 +21,9 @@ Gracefully ending the `drive-mirror` job on source...
{"data": {"device": "mirror-job0", "len": 1073741824, "offset": 1073741824, "speed": 0, "type": "mirror"}, "event": "BLOCK_JOB_COMPLETED", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}}
Stopping the NBD server on destination...
{"return": {}}
+Wait for migration completion on target...
+{"data": {"status": "completed"}, "event": "MIGRATION", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}}
+Check bitmaps on source:
+[{"busy": false, "count": 0, "granularity": 65536, "name": "bitmap0", "persistent": false, "recording": true, "status": "active"}]
+Check bitmaps on target:
[{"busy": false, "count": 0, "granularity": 65536, "name": "bitmap0", "persistent": false, "recording": true, "status": "active"}]
diff --git a/tests/qemu-iotests/291 b/tests/qemu-iotests/291
index 3ca83b9cd1..404f8521f7 100755
--- a/tests/qemu-iotests/291
+++ b/tests/qemu-iotests/291
@@ -62,6 +62,8 @@ $QEMU_IO -c 'w 1M 1M' -f $IMGFMT "$TEST_IMG" | _filter_qemu_io
$QEMU_IMG bitmap --disable -f $IMGFMT "$TEST_IMG" b1
$QEMU_IMG bitmap --enable -f $IMGFMT "$TEST_IMG" b2
$QEMU_IO -c 'w 2M 1M' -f $IMGFMT "$TEST_IMG" | _filter_qemu_io
+echo "Check resulting qcow2 header extensions:"
+$PYTHON qcow2.py "$TEST_IMG" dump-header-exts
echo
echo "=== Bitmap preservation not possible to non-qcow2 ==="
@@ -77,7 +79,7 @@ echo
# Only bitmaps from the active layer are copied
$QEMU_IMG convert --bitmaps -O qcow2 "$TEST_IMG.orig" "$TEST_IMG"
-$QEMU_IMG info "$TEST_IMG" | _filter_img_info --format-specific
+_img_info --format-specific
# But we can also merge in bitmaps from other layers. This test is a bit
# contrived to cover more code paths, in reality, you could merge directly
# into b0 without going through tmp
@@ -87,7 +89,9 @@ $QEMU_IMG bitmap --add --merge b0 -b "$TEST_IMG.base" -F $IMGFMT \
$QEMU_IMG bitmap --merge tmp -f $IMGFMT "$TEST_IMG" b0
$QEMU_IMG bitmap --remove --image-opts \
driver=$IMGFMT,file.driver=file,file.filename="$TEST_IMG" tmp
-$QEMU_IMG info "$TEST_IMG" | _filter_img_info --format-specific
+_img_info --format-specific
+echo "Check resulting qcow2 header extensions:"
+$PYTHON qcow2.py "$TEST_IMG" dump-header-exts
echo
echo "=== Check bitmap contents ==="
diff --git a/tests/qemu-iotests/291.out b/tests/qemu-iotests/291.out
index 8c62017567..08bfaaaa6b 100644
--- a/tests/qemu-iotests/291.out
+++ b/tests/qemu-iotests/291.out
@@ -14,6 +14,25 @@ wrote 1048576/1048576 bytes at offset 1048576
1 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
wrote 1048576/1048576 bytes at offset 2097152
1 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+Check resulting qcow2 header extensions:
+Header extension:
+magic 0xe2792aca (Backing format)
+length 5
+data 'qcow2'
+
+Header extension:
+magic 0x6803f857 (Feature table)
+length 336
+data <binary>
+
+Header extension:
+magic 0x23852875 (Bitmaps)
+length 24
+nb_bitmaps 2
+reserved32 0
+bitmap_directory_size 0x40
+bitmap_directory_offset 0x510000
+
=== Bitmap preservation not possible to non-qcow2 ===
@@ -24,7 +43,7 @@ qemu-img: Format driver 'raw' does not support bitmaps
image: TEST_DIR/t.IMGFMT
file format: IMGFMT
virtual size: 10 MiB (10485760 bytes)
-disk size: 4.39 MiB
+cluster_size: 65536
Format specific information:
compat: 1.1
compression type: zlib
@@ -44,7 +63,7 @@ Format specific information:
image: TEST_DIR/t.IMGFMT
file format: IMGFMT
virtual size: 10 MiB (10485760 bytes)
-disk size: 4.48 MiB
+cluster_size: 65536
Format specific information:
compat: 1.1
compression type: zlib
@@ -65,6 +84,20 @@ Format specific information:
granularity: 65536
refcount bits: 16
corrupt: false
+Check resulting qcow2 header extensions:
+Header extension:
+magic 0x6803f857 (Feature table)
+length 336
+data <binary>
+
+Header extension:
+magic 0x23852875 (Bitmaps)
+length 24
+nb_bitmaps 3
+reserved32 0
+bitmap_directory_size 0x60
+bitmap_directory_offset 0x520000
+
=== Check bitmap contents ===
diff --git a/tests/qemu-iotests/qcow2.py b/tests/qemu-iotests/qcow2.py
index 94a07b2f6f..8c187e9a72 100755
--- a/tests/qemu-iotests/qcow2.py
+++ b/tests/qemu-iotests/qcow2.py
@@ -1,181 +1,50 @@
#!/usr/bin/env python3
+#
+# Manipulations with qcow2 image
+#
+# 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/>.
+#
import sys
-import struct
-import string
-
-class QcowHeaderExtension:
-
- def __init__(self, magic, length, data):
- if length % 8 != 0:
- padding = 8 - (length % 8)
- data += b"\0" * padding
-
- self.magic = magic
- self.length = length
- self.data = data
-
- @classmethod
- def create(cls, magic, data):
- return QcowHeaderExtension(magic, len(data), data)
-
-class QcowHeader:
-
- uint32_t = 'I'
- uint64_t = 'Q'
-
- fields = [
- # Version 2 header fields
- [ uint32_t, '%#x', 'magic' ],
- [ uint32_t, '%d', 'version' ],
- [ uint64_t, '%#x', 'backing_file_offset' ],
- [ uint32_t, '%#x', 'backing_file_size' ],
- [ uint32_t, '%d', 'cluster_bits' ],
- [ uint64_t, '%d', 'size' ],
- [ uint32_t, '%d', 'crypt_method' ],
- [ uint32_t, '%d', 'l1_size' ],
- [ uint64_t, '%#x', 'l1_table_offset' ],
- [ uint64_t, '%#x', 'refcount_table_offset' ],
- [ uint32_t, '%d', 'refcount_table_clusters' ],
- [ uint32_t, '%d', 'nb_snapshots' ],
- [ uint64_t, '%#x', 'snapshot_offset' ],
-
- # Version 3 header fields
- [ uint64_t, 'mask', 'incompatible_features' ],
- [ uint64_t, 'mask', 'compatible_features' ],
- [ uint64_t, 'mask', 'autoclear_features' ],
- [ uint32_t, '%d', 'refcount_order' ],
- [ uint32_t, '%d', 'header_length' ],
- ];
-
- fmt = '>' + ''.join(field[0] for field in fields)
-
- def __init__(self, fd):
-
- buf_size = struct.calcsize(QcowHeader.fmt)
-
- fd.seek(0)
- buf = fd.read(buf_size)
-
- header = struct.unpack(QcowHeader.fmt, buf)
- self.__dict__ = dict((field[2], header[i])
- for i, field in enumerate(QcowHeader.fields))
-
- self.set_defaults()
- self.cluster_size = 1 << self.cluster_bits
-
- fd.seek(self.header_length)
- self.load_extensions(fd)
-
- if self.backing_file_offset:
- fd.seek(self.backing_file_offset)
- self.backing_file = fd.read(self.backing_file_size)
- else:
- self.backing_file = None
-
- def set_defaults(self):
- if self.version == 2:
- self.incompatible_features = 0
- self.compatible_features = 0
- self.autoclear_features = 0
- self.refcount_order = 4
- self.header_length = 72
-
- def load_extensions(self, fd):
- self.extensions = []
-
- if self.backing_file_offset != 0:
- end = min(self.cluster_size, self.backing_file_offset)
- else:
- end = self.cluster_size
-
- while fd.tell() < end:
- (magic, length) = struct.unpack('>II', fd.read(8))
- if magic == 0:
- break
- else:
- padded = (length + 7) & ~7
- data = fd.read(padded)
- self.extensions.append(QcowHeaderExtension(magic, length, data))
-
- def update_extensions(self, fd):
-
- fd.seek(self.header_length)
- extensions = self.extensions
- extensions.append(QcowHeaderExtension(0, 0, b""))
- for ex in extensions:
- buf = struct.pack('>II', ex.magic, ex.length)
- fd.write(buf)
- fd.write(ex.data)
-
- if self.backing_file != None:
- self.backing_file_offset = fd.tell()
- fd.write(self.backing_file)
-
- if fd.tell() > self.cluster_size:
- raise Exception("I think I just broke the image...")
-
-
- def update(self, fd):
- header_bytes = self.header_length
-
- self.update_extensions(fd)
-
- fd.seek(0)
- header = tuple(self.__dict__[f] for t, p, f in QcowHeader.fields)
- buf = struct.pack(QcowHeader.fmt, *header)
- buf = buf[0:header_bytes-1]
- fd.write(buf)
-
- def dump(self):
- for f in QcowHeader.fields:
- value = self.__dict__[f[2]]
- if f[1] == 'mask':
- bits = []
- for bit in range(64):
- if value & (1 << bit):
- bits.append(bit)
- value_str = str(bits)
- else:
- value_str = f[1] % value
-
- print("%-25s" % f[2], value_str)
- print("")
-
- def dump_extensions(self):
- for ex in self.extensions:
- data = ex.data[:ex.length]
- if all(c in string.printable.encode('ascii') for c in data):
- data = "'%s'" % data.decode('ascii')
- else:
- data = "<binary>"
-
- print("Header extension:")
- print("%-25s %#x" % ("magic", ex.magic))
- print("%-25s %d" % ("length", ex.length))
- print("%-25s %s" % ("data", data))
- print("")
+from qcow2_format import (
+ QcowHeader,
+ QcowHeaderExtension
+)
def cmd_dump_header(fd):
h = QcowHeader(fd)
h.dump()
+ print()
h.dump_extensions()
+
def cmd_dump_header_exts(fd):
h = QcowHeader(fd)
h.dump_extensions()
+
def cmd_set_header(fd, name, value):
try:
value = int(value, 0)
- except:
+ except ValueError:
print("'%s' is not a valid number" % value)
sys.exit(1)
fields = (field[2] for field in QcowHeader.fields)
- if not name in fields:
+ if name not in fields:
print("'%s' is not a known header field" % name)
sys.exit(1)
@@ -183,25 +52,29 @@ def cmd_set_header(fd, name, value):
h.__dict__[name] = value
h.update(fd)
+
def cmd_add_header_ext(fd, magic, data):
try:
magic = int(magic, 0)
- except:
+ except ValueError:
print("'%s' is not a valid magic number" % magic)
sys.exit(1)
h = QcowHeader(fd)
- h.extensions.append(QcowHeaderExtension.create(magic, data.encode('ascii')))
+ h.extensions.append(QcowHeaderExtension.create(magic,
+ data.encode('ascii')))
h.update(fd)
+
def cmd_add_header_ext_stdio(fd, magic):
data = sys.stdin.read()
cmd_add_header_ext(fd, magic, data)
+
def cmd_del_header_ext(fd, magic):
try:
magic = int(magic, 0)
- except:
+ except ValueError:
print("'%s' is not a valid magic number" % magic)
sys.exit(1)
@@ -219,12 +92,13 @@ def cmd_del_header_ext(fd, magic):
h.update(fd)
+
def cmd_set_feature_bit(fd, group, bit):
try:
bit = int(bit, 0)
if bit < 0 or bit >= 64:
raise ValueError
- except:
+ except ValueError:
print("'%s' is not a valid bit number in range [0, 64)" % bit)
sys.exit(1)
@@ -236,21 +110,27 @@ def cmd_set_feature_bit(fd, group, bit):
elif group == 'autoclear':
h.autoclear_features |= 1 << bit
else:
- print("'%s' is not a valid group, try 'incompatible', 'compatible', or 'autoclear'" % group)
+ print("'%s' is not a valid group, try "
+ "'incompatible', 'compatible', or 'autoclear'" % group)
sys.exit(1)
h.update(fd)
+
cmds = [
- [ 'dump-header', cmd_dump_header, 0, 'Dump image header and header extensions' ],
- [ 'dump-header-exts', cmd_dump_header_exts, 0, 'Dump image header extensions' ],
- [ 'set-header', cmd_set_header, 2, 'Set a field in the header'],
- [ 'add-header-ext', cmd_add_header_ext, 2, 'Add a header extension' ],
- [ 'add-header-ext-stdio', cmd_add_header_ext_stdio, 1, 'Add a header extension, data from stdin' ],
- [ 'del-header-ext', cmd_del_header_ext, 1, 'Delete a header extension' ],
- [ 'set-feature-bit', cmd_set_feature_bit, 2, 'Set a feature bit'],
+ ['dump-header', cmd_dump_header, 0,
+ 'Dump image header and header extensions'],
+ ['dump-header-exts', cmd_dump_header_exts, 0,
+ 'Dump image header extensions'],
+ ['set-header', cmd_set_header, 2, 'Set a field in the header'],
+ ['add-header-ext', cmd_add_header_ext, 2, 'Add a header extension'],
+ ['add-header-ext-stdio', cmd_add_header_ext_stdio, 1,
+ 'Add a header extension, data from stdin'],
+ ['del-header-ext', cmd_del_header_ext, 1, 'Delete a header extension'],
+ ['set-feature-bit', cmd_set_feature_bit, 2, 'Set a feature bit'],
]
+
def main(filename, cmd, args):
fd = open(filename, "r+b")
try:
@@ -267,6 +147,7 @@ def main(filename, cmd, args):
finally:
fd.close()
+
def usage():
print("Usage: %s <file> <cmd> [<arg>, ...]" % sys.argv[0])
print("")
@@ -274,6 +155,7 @@ def usage():
for name, handler, num_args, desc in cmds:
print(" %-20s - %s" % (name, desc))
+
if __name__ == '__main__':
if len(sys.argv) < 3:
usage()
diff --git a/tests/qemu-iotests/qcow2_format.py b/tests/qemu-iotests/qcow2_format.py
new file mode 100644
index 0000000000..0f65fd161d
--- /dev/null
+++ b/tests/qemu-iotests/qcow2_format.py
@@ -0,0 +1,286 @@
+# Library for manipulations with qcow2 image
+#
+# Copyright (c) 2020 Virtuozzo International GmbH.
+#
+# 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/>.
+#
+
+import struct
+import string
+
+
+class Qcow2Field:
+
+ def __init__(self, value):
+ self.value = value
+
+ def __str__(self):
+ return str(self.value)
+
+
+class Flags64(Qcow2Field):
+
+ def __str__(self):
+ bits = []
+ for bit in range(64):
+ if self.value & (1 << bit):
+ bits.append(bit)
+ return str(bits)
+
+
+class Enum(Qcow2Field):
+
+ def __str__(self):
+ return f'{self.value:#x} ({self.mapping.get(self.value, "<unknown>")})'
+
+
+class Qcow2StructMeta(type):
+
+ # Mapping from c types to python struct format
+ ctypes = {
+ 'u8': 'B',
+ 'u16': 'H',
+ 'u32': 'I',
+ 'u64': 'Q'
+ }
+
+ def __init__(self, name, bases, attrs):
+ if 'fields' in attrs:
+ self.fmt = '>' + ''.join(self.ctypes[f[0]] for f in self.fields)
+
+
+class Qcow2Struct(metaclass=Qcow2StructMeta):
+
+ """Qcow2Struct: base class for qcow2 data structures
+
+ Successors should define fields class variable, which is: list of tuples,
+ each of three elements:
+ - c-type (one of 'u8', 'u16', 'u32', 'u64')
+ - format (format_spec to use with .format() when dump or 'mask' to dump
+ bitmasks)
+ - field name
+ """
+
+ def __init__(self, fd=None, offset=None, data=None):
+ """
+ Two variants:
+ 1. Specify data. fd and offset must be None.
+ 2. Specify fd and offset, data must be None. offset may be omitted
+ in this case, than current position of fd is used.
+ """
+ if data is None:
+ assert fd is not None
+ buf_size = struct.calcsize(self.fmt)
+ if offset is not None:
+ fd.seek(offset)
+ data = fd.read(buf_size)
+ else:
+ assert fd is None and offset is None
+
+ values = struct.unpack(self.fmt, data)
+ self.__dict__ = dict((field[2], values[i])
+ for i, field in enumerate(self.fields))
+
+ def dump(self):
+ for f in self.fields:
+ value = self.__dict__[f[2]]
+ if isinstance(f[1], str):
+ value_str = f[1].format(value)
+ else:
+ value_str = str(f[1](value))
+
+ print('{:<25} {}'.format(f[2], value_str))
+
+
+class Qcow2BitmapExt(Qcow2Struct):
+
+ fields = (
+ ('u32', '{}', 'nb_bitmaps'),
+ ('u32', '{}', 'reserved32'),
+ ('u64', '{:#x}', 'bitmap_directory_size'),
+ ('u64', '{:#x}', 'bitmap_directory_offset')
+ )
+
+
+QCOW2_EXT_MAGIC_BITMAPS = 0x23852875
+
+
+class QcowHeaderExtension(Qcow2Struct):
+
+ class Magic(Enum):
+ mapping = {
+ 0xe2792aca: 'Backing format',
+ 0x6803f857: 'Feature table',
+ 0x0537be77: 'Crypto header',
+ QCOW2_EXT_MAGIC_BITMAPS: 'Bitmaps',
+ 0x44415441: 'Data file'
+ }
+
+ fields = (
+ ('u32', Magic, 'magic'),
+ ('u32', '{}', 'length')
+ # length bytes of data follows
+ # then padding to next multiply of 8
+ )
+
+ def __init__(self, magic=None, length=None, data=None, fd=None):
+ """
+ Support both loading from fd and creation from user data.
+ For fd-based creation current position in a file will be used to read
+ the data.
+
+ This should be somehow refactored and functionality should be moved to
+ superclass (to allow creation of any qcow2 struct), but then, fields
+ of variable length (data here) should be supported in base class
+ somehow. Note also, that we probably want to parse different
+ extensions. Should they be subclasses of this class, or how to do it
+ better? Should it be something like QAPI union with discriminator field
+ (magic here). So, it's a TODO. We'll see how to properly refactor this
+ when we have more qcow2 structures.
+ """
+ if fd is None:
+ assert all(v is not None for v in (magic, length, data))
+ self.magic = magic
+ self.length = length
+ if length % 8 != 0:
+ padding = 8 - (length % 8)
+ data += b'\0' * padding
+ self.data = data
+ else:
+ assert all(v is None for v in (magic, length, data))
+ super().__init__(fd=fd)
+ padded = (self.length + 7) & ~7
+ self.data = fd.read(padded)
+ assert self.data is not None
+
+ if self.magic == QCOW2_EXT_MAGIC_BITMAPS:
+ self.obj = Qcow2BitmapExt(data=self.data)
+ else:
+ self.obj = None
+
+ def dump(self):
+ super().dump()
+
+ if self.obj is None:
+ data = self.data[:self.length]
+ if all(c in string.printable.encode('ascii') for c in data):
+ data = f"'{ data.decode('ascii') }'"
+ else:
+ data = '<binary>'
+ print(f'{"data":<25} {data}')
+ else:
+ self.obj.dump()
+
+ @classmethod
+ def create(cls, magic, data):
+ return QcowHeaderExtension(magic, len(data), data)
+
+
+class QcowHeader(Qcow2Struct):
+
+ fields = (
+ # Version 2 header fields
+ ('u32', '{:#x}', 'magic'),
+ ('u32', '{}', 'version'),
+ ('u64', '{:#x}', 'backing_file_offset'),
+ ('u32', '{:#x}', 'backing_file_size'),
+ ('u32', '{}', 'cluster_bits'),
+ ('u64', '{}', 'size'),
+ ('u32', '{}', 'crypt_method'),
+ ('u32', '{}', 'l1_size'),
+ ('u64', '{:#x}', 'l1_table_offset'),
+ ('u64', '{:#x}', 'refcount_table_offset'),
+ ('u32', '{}', 'refcount_table_clusters'),
+ ('u32', '{}', 'nb_snapshots'),
+ ('u64', '{:#x}', 'snapshot_offset'),
+
+ # Version 3 header fields
+ ('u64', Flags64, 'incompatible_features'),
+ ('u64', Flags64, 'compatible_features'),
+ ('u64', Flags64, 'autoclear_features'),
+ ('u32', '{}', 'refcount_order'),
+ ('u32', '{}', 'header_length'),
+ )
+
+ def __init__(self, fd):
+ super().__init__(fd=fd, offset=0)
+
+ self.set_defaults()
+ self.cluster_size = 1 << self.cluster_bits
+
+ fd.seek(self.header_length)
+ self.load_extensions(fd)
+
+ if self.backing_file_offset:
+ fd.seek(self.backing_file_offset)
+ self.backing_file = fd.read(self.backing_file_size)
+ else:
+ self.backing_file = None
+
+ def set_defaults(self):
+ if self.version == 2:
+ self.incompatible_features = 0
+ self.compatible_features = 0
+ self.autoclear_features = 0
+ self.refcount_order = 4
+ self.header_length = 72
+
+ def load_extensions(self, fd):
+ self.extensions = []
+
+ if self.backing_file_offset != 0:
+ end = min(self.cluster_size, self.backing_file_offset)
+ else:
+ end = self.cluster_size
+
+ while fd.tell() < end:
+ ext = QcowHeaderExtension(fd=fd)
+ if ext.magic == 0:
+ break
+ else:
+ self.extensions.append(ext)
+
+ def update_extensions(self, fd):
+
+ fd.seek(self.header_length)
+ extensions = self.extensions
+ extensions.append(QcowHeaderExtension(0, 0, b''))
+ for ex in extensions:
+ buf = struct.pack('>II', ex.magic, ex.length)
+ fd.write(buf)
+ fd.write(ex.data)
+
+ if self.backing_file is not None:
+ self.backing_file_offset = fd.tell()
+ fd.write(self.backing_file)
+
+ if fd.tell() > self.cluster_size:
+ raise Exception('I think I just broke the image...')
+
+ def update(self, fd):
+ header_bytes = self.header_length
+
+ self.update_extensions(fd)
+
+ fd.seek(0)
+ header = tuple(self.__dict__[f] for t, p, f in QcowHeader.fields)
+ buf = struct.pack(QcowHeader.fmt, *header)
+ buf = buf[0:header_bytes-1]
+ fd.write(buf)
+
+ def dump_extensions(self):
+ for ex in self.extensions:
+ print('Header extension:')
+ ex.dump()
+ print()
diff --git a/tests/qtest/Makefile.include b/tests/qtest/Makefile.include
index 9e5a51d033..5023fa413d 100644
--- a/tests/qtest/Makefile.include
+++ b/tests/qtest/Makefile.include
@@ -262,6 +262,7 @@ tests/qtest/hd-geo-test$(EXESUF): tests/qtest/hd-geo-test.o $(libqos-obj-y)
tests/qtest/boot-order-test$(EXESUF): tests/qtest/boot-order-test.o $(libqos-obj-y)
tests/qtest/boot-serial-test$(EXESUF): tests/qtest/boot-serial-test.o $(libqos-obj-y)
tests/qtest/bios-tables-test$(EXESUF): tests/qtest/bios-tables-test.o \
+ tests/qtest/tpm-emu.o $(test-io-obj-y) \
tests/qtest/boot-sector.o tests/qtest/acpi-utils.o $(libqos-obj-y)
tests/qtest/pxe-test$(EXESUF): tests/qtest/pxe-test.o tests/qtest/boot-sector.o $(libqos-obj-y)
tests/qtest/microbit-test$(EXESUF): tests/qtest/microbit-test.o
diff --git a/tests/qtest/bios-tables-test.c b/tests/qtest/bios-tables-test.c
index c9843829b3..53f104a9c5 100644
--- a/tests/qtest/bios-tables-test.c
+++ b/tests/qtest/bios-tables-test.c
@@ -57,6 +57,9 @@
#include "qemu/bitmap.h"
#include "acpi-utils.h"
#include "boot-sector.h"
+#include "tpm-emu.h"
+#include "hw/acpi/tpm.h"
+
#define MACHINE_PC "pc"
#define MACHINE_Q35 "q35"
@@ -874,6 +877,60 @@ static void test_acpi_piix4_tcg_numamem(void)
free_test_data(&data);
}
+uint64_t tpm_tis_base_addr;
+
+static void test_acpi_tcg_tpm(const char *machine, const char *tpm_if,
+ uint64_t base)
+{
+ 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;
+ test_data data;
+ GThread *thread;
+ char *args, *variant = g_strdup_printf(".%s", tpm_if);
+
+ tpm_tis_base_addr = base;
+
+ module_call_init(MODULE_INIT_QOM);
+
+ test.addr = g_new0(SocketAddress, 1);
+ test.addr->type = SOCKET_ADDRESS_TYPE_UNIX;
+ test.addr->u.q_unix.path = g_build_filename(tmp_path, "sock", NULL);
+ g_mutex_init(&test.data_mutex);
+ g_cond_init(&test.data_cond);
+ test.data_cond_signal = false;
+
+ thread = g_thread_new(NULL, tpm_emu_ctrl_thread, &test);
+ tpm_emu_test_wait_cond(&test);
+
+ memset(&data, 0, sizeof(data));
+ data.machine = machine;
+ data.variant = variant;
+
+ args = g_strdup_printf(
+ " -chardev socket,id=chr,path=%s"
+ " -tpmdev emulator,id=dev,chardev=chr"
+ " -device tpm-%s,tpmdev=dev",
+ test.addr->u.q_unix.path, tpm_if);
+
+ test_acpi_one(args, &data);
+
+ g_thread_join(thread);
+ g_unlink(test.addr->u.q_unix.path);
+ qapi_free_SocketAddress(test.addr);
+ g_rmdir(tmp_path);
+ g_free(variant);
+ g_free(tmp_path);
+ g_free(tmp_dir_name);
+ free_test_data(&data);
+}
+
+static void test_acpi_q35_tcg_tpm_tis(void)
+{
+ test_acpi_tcg_tpm("q35", "tis", 0xFED40000);
+}
+
static void test_acpi_tcg_dimm_pxm(const char *machine)
{
test_data data;
@@ -1037,6 +1094,7 @@ int main(int argc, char *argv[])
return ret;
}
+ qtest_add_func("acpi/q35/tpm-tis", test_acpi_q35_tcg_tpm_tis);
qtest_add_func("acpi/piix4", test_acpi_piix4_tcg);
qtest_add_func("acpi/piix4/bridge", test_acpi_piix4_tcg_bridge);
qtest_add_func("acpi/q35", test_acpi_q35_tcg);
diff --git a/tests/qtest/tpm-emu.c b/tests/qtest/tpm-emu.c
index c43ac4aef8..298d0eec74 100644
--- a/tests/qtest/tpm-emu.c
+++ b/tests/qtest/tpm-emu.c
@@ -49,7 +49,6 @@ static void *tpm_emu_tpm_thread(void *data)
s->tpm_msg->tag = be16_to_cpu(s->tpm_msg->tag);
s->tpm_msg->len = be32_to_cpu(s->tpm_msg->len);
g_assert_cmpint(s->tpm_msg->len, >=, minhlen);
- g_assert_cmpint(s->tpm_msg->tag, ==, TPM2_ST_NO_SESSIONS);
s->tpm_msg = g_realloc(s->tpm_msg, s->tpm_msg->len);
qio_channel_read(ioc, (char *)&s->tpm_msg->code,
diff --git a/tests/qtest/tpm-emu.h b/tests/qtest/tpm-emu.h
index a4f1d64226..73f3bed0c4 100644
--- a/tests/qtest/tpm-emu.h
+++ b/tests/qtest/tpm-emu.h
@@ -16,6 +16,9 @@
#define TPM_RC_FAILURE 0x101
#define TPM2_ST_NO_SESSIONS 0x8001
+#include "qemu/sockets.h"
+#include "io/channel.h"
+
struct tpm_hdr {
uint16_t tag;
uint32_t len;
diff --git a/tests/tcg/arm/Makefile.target b/tests/tcg/arm/Makefile.target
index 11c39c601e..3da09a38be 100644
--- a/tests/tcg/arm/Makefile.target
+++ b/tests/tcg/arm/Makefile.target
@@ -68,6 +68,8 @@ run-semiconsole-arm: semiconsole-arm
run-plugin-semiconsole-arm-with-%:
$(call skip-test, $<, "MANUAL ONLY")
+ARM_TESTS += commpage
+
TESTS += $(ARM_TESTS)
# On ARM Linux only supports 4k pages
diff --git a/tests/tcg/arm/commpage.c b/tests/tcg/arm/commpage.c
new file mode 100644
index 0000000000..c76e70cb8b
--- /dev/null
+++ b/tests/tcg/arm/commpage.c
@@ -0,0 +1,61 @@
+/*
+ * Verify the COMMPAGE emulation
+ *
+ * The ARM commpage is a set of user space helper functions provided
+ * by the kernel in an effort to ease portability of user space code
+ * between different CPUs with potentially different capabilities. It
+ * is a 32 bit invention and similar to the vdso segment in many ways.
+ *
+ * The ABI is documented in the Linux kernel:
+ * Documentation/arm/kernel_userspace_helpers.rst
+ *
+ * Copyright (c) 2020 Linaro Ltd
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <stdint.h>
+
+#define ARM_COMMPAGE (0xffff0f00u)
+#define ARM_KUSER_VERSION (*(int32_t *)(ARM_COMMPAGE + 0xfc))
+typedef void * (get_tls_fn)(void);
+#define ARM_KUSER_GET_TLS (*(get_tls_fn *)(ARM_COMMPAGE + 0xe0))
+typedef int (cmpxchg_fn)(int oldval, int newval, volatile int *ptr);
+#define ARM_KUSER_CMPXCHG (*(cmpxchg_fn *)(ARM_COMMPAGE + 0xc0))
+typedef void (dmb_fn)(void);
+#define ARM_KUSER_DMB (*(dmb_fn *)(ARM_COMMPAGE + 0xa0))
+typedef int (cmpxchg64_fn)(const int64_t *oldval,
+ const int64_t *newval,
+ volatile int64_t *ptr);
+#define ARM_KUSER_CMPXCHG64 (*(cmpxchg64_fn *)(ARM_COMMPAGE + 0x60))
+
+#define fail_unless(x) \
+ do { \
+ if (!(x)) { \
+ fprintf(stderr, "FAILED at %s:%d\n", __FILE__, __LINE__); \
+ exit(EXIT_FAILURE); \
+ } \
+ } while (0)
+
+
+int main(int argc, char *argv[argc])
+{
+ void *kuser_tls;
+ int val = 1;
+ const int64_t oldval = 1, newval = 2;
+ int64_t val64 = 1;
+
+ fail_unless(ARM_KUSER_VERSION == 0x5);
+ kuser_tls = ARM_KUSER_GET_TLS();
+ printf("TLS = %p\n", kuser_tls);
+ fail_unless(kuser_tls != 0);
+ fail_unless(ARM_KUSER_CMPXCHG(1, 2, &val) == 0);
+ printf("val = %d\n", val);
+ /* this is a crash test, not checking an actual barrier occurs */
+ ARM_KUSER_DMB();
+ fail_unless(ARM_KUSER_CMPXCHG64(&oldval, &newval, &val64) == 0);
+ printf("val64 = %lld\n", val64);
+ return 0;
+}
diff --git a/tests/vm/fedora b/tests/vm/fedora
index bd9c6cf295..a9195670f4 100755
--- a/tests/vm/fedora
+++ b/tests/vm/fedora
@@ -32,7 +32,6 @@ class FedoraVM(basevm.BaseVM):
pkgs = [
# tools
'git-core',
- 'flex', 'bison',
'gcc', 'binutils', 'make',
# perl
diff --git a/tests/vm/freebsd b/tests/vm/freebsd
index 298967fe9c..f87db2b126 100755
--- a/tests/vm/freebsd
+++ b/tests/vm/freebsd
@@ -38,7 +38,6 @@ class FreeBSDVM(basevm.BaseVM):
"bash",
"gmake",
"gsed",
- "flex", "bison",
# libs: crypto
"gnutls",
diff --git a/tests/vm/netbsd b/tests/vm/netbsd
index b10c9d429d..cdac502dad 100755
--- a/tests/vm/netbsd
+++ b/tests/vm/netbsd
@@ -36,7 +36,6 @@ class NetBSDVM(basevm.BaseVM):
"bash",
"gmake",
"gsed",
- "flex", "bison",
# libs: crypto
"gnutls",
diff --git a/tests/vm/openbsd b/tests/vm/openbsd
index 0b705f4945..13e7f9a6d5 100755
--- a/tests/vm/openbsd
+++ b/tests/vm/openbsd
@@ -35,7 +35,6 @@ class OpenBSDVM(basevm.BaseVM):
"bash",
"gmake",
"gsed",
- "bison",
# libs: usb
"libusb1",
diff --git a/tests/vm/ubuntu.i386 b/tests/vm/ubuntu.i386
index 1570775335..24527cc78c 100755
--- a/tests/vm/ubuntu.i386
+++ b/tests/vm/ubuntu.i386
@@ -52,7 +52,7 @@ class UbuntuX86VM(basevm.BaseVM):
self.ssh_root_check("sed -ie s/^#\ deb-src/deb-src/g /etc/apt/sources.list")
self.ssh_root_check("apt-get update")
self.ssh_root_check("apt-get build-dep -y qemu")
- self.ssh_root_check("apt-get install -y libfdt-dev flex bison language-pack-en")
+ self.ssh_root_check("apt-get install -y libfdt-dev language-pack-en")
self.ssh_root("poweroff")
self.wait()
os.rename(img_tmp, img)