Merge remote-tracking branch 'remotes/ehabkost/tags/machine-next-pull-request' into staging
machine queue, 2020-05-13
Bug fixes:
* hostmem: don't use mbind() if host-nodes is empty (Igor Mammedov)
# gpg: Signature made Wed 13 May 2020 15:00:25 BST
# gpg: using RSA key 5A322FD5ABC4D3DBACCFD1AA2807936F984DC5A6
# gpg: issuer "ehabkost@redhat.com"
# gpg: Good signature from "Eduardo Habkost <ehabkost@redhat.com>" [full]
# Primary key fingerprint: 5A32 2FD5 ABC4 D3DB ACCF D1AA 2807 936F 984D C5A6
* remotes/ehabkost/tags/machine-next-pull-request:
hostmem: don't use mbind() if host-nodes is empty
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
diff --git a/.gitlab-ci-edk2.yml b/.gitlab-ci.d/edk2.yml
similarity index 100%
rename from .gitlab-ci-edk2.yml
rename to .gitlab-ci.d/edk2.yml
diff --git a/.gitlab-ci-opensbi.yml b/.gitlab-ci.d/opensbi.yml
similarity index 100%
rename from .gitlab-ci-opensbi.yml
rename to .gitlab-ci.d/opensbi.yml
diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index b889fb9..349c77a 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -1,12 +1,24 @@
include:
- - local: '/.gitlab-ci-edk2.yml'
- - local: '/.gitlab-ci-opensbi.yml'
+ - local: '/.gitlab-ci.d/edk2.yml'
+ - local: '/.gitlab-ci.d/opensbi.yml'
-before_script:
- - apt-get update -qq
- - apt-get install -y -qq flex bison libglib2.0-dev libpixman-1-dev genisoimage
+.update_apt_template: &before_script_apt
+ before_script:
+ - apt-get update -qq
+ - apt-get install -y -qq git gcc libglib2.0-dev libpixman-1-dev make
+ genisoimage
+ - JOBS=$(expr $(nproc) + 1)
+
+.update_dnf_template: &before_script_dnf
+ before_script:
+ - dnf update -y
+ - dnf install -y bzip2 diffutils gcc git genisoimage findutils glib2-devel
+ make python3 perl-podlators perl-Test-Harness pixman-devel zlib-devel
+ - JOBS=$(expr $(nproc) + 1)
build-system1:
+ image: ubuntu:19.10
+ <<: *before_script_apt
script:
- apt-get install -y -qq libgtk-3-dev libvte-dev nettle-dev libcacard-dev
libusb-dev libvde-dev libspice-protocol-dev libgl1-mesa-dev libvdeplug-dev
@@ -15,23 +27,27 @@
- ../configure --enable-werror --target-list="aarch64-softmmu alpha-softmmu
cris-softmmu hppa-softmmu lm32-softmmu moxie-softmmu microblazeel-softmmu
mips64el-softmmu m68k-softmmu ppc-softmmu riscv64-softmmu sparc-softmmu"
- - make -j2
- - make -j2 check
+ - make -j"$JOBS"
+ - make -j"$JOBS" check
build-system2:
+ image: fedora:latest
+ <<: *before_script_dnf
script:
- - apt-get install -y -qq libsdl2-dev libgcrypt-dev libbrlapi-dev libaio-dev
- libfdt-dev liblzo2-dev librdmacm-dev libibverbs-dev libibumad-dev
- libzstd-dev
+ - yum install -y SDL2-devel libgcrypt-devel brlapi-devel libaio-devel
+ libfdt-devel lzo-devel librdmacm-devel libibverbs-devel libibumad-devel
+ libzstd-devel
- mkdir build
- cd build
- ../configure --enable-werror --target-list="tricore-softmmu unicore32-softmmu
microblaze-softmmu mips-softmmu riscv32-softmmu s390x-softmmu sh4-softmmu
sparc64-softmmu x86_64-softmmu xtensa-softmmu nios2-softmmu or1k-softmmu"
- - make -j2
- - make -j2 check
+ - make -j"$JOBS"
+ - make -j"$JOBS" check
build-disabled:
+ image: fedora:latest
+ <<: *before_script_dnf
script:
- mkdir build
- cd build
@@ -42,16 +58,18 @@
--disable-qom-cast-debug --disable-spice --disable-vhost-vsock
--disable-vhost-net --disable-vhost-crypto --disable-vhost-user
--target-list="i386-softmmu ppc64-softmmu mips64-softmmu i386-linux-user"
- - make -j2
- - make -j2 check-qtest SPEED=slow
+ - make -j"$JOBS"
+ - make -j"$JOBS" check-qtest SPEED=slow
build-tcg-disabled:
+ image: centos:8
+ <<: *before_script_dnf
script:
- - apt-get install -y -qq clang libgtk-3-dev libusb-dev
+ - dnf install -y clang gtk3-devel libusbx-devel libgcrypt-devel
- mkdir build
- cd build
- ../configure --cc=clang --enable-werror --disable-tcg --audio-drv-list=""
- - make -j2
+ - make -j"$JOBS"
- make check-unit
- make check-qapi-schema
- cd tests/qemu-iotests/
@@ -64,34 +82,39 @@
260 261 262 263 264 270 272 273 277 279
build-user:
+ <<: *before_script_apt
script:
- mkdir build
- cd build
- ../configure --enable-werror --disable-system --disable-guest-agent
--disable-capstone --disable-slirp --disable-fdt
- - make -j2
+ - make -j"$JOBS"
- make run-tcg-tests-i386-linux-user run-tcg-tests-x86_64-linux-user
build-clang:
+ image: fedora:latest
+ <<: *before_script_dnf
script:
- - apt-get install -y -qq clang libsdl2-dev libattr1-dev libcap-ng-dev
- xfslibs-dev libiscsi-dev libnfs-dev libseccomp-dev gnutls-dev librbd-dev
+ - yum install -y clang SDL2-devel libattr-devel libcap-ng-devel xfsprogs-devel
+ libiscsi-devel libnfs-devel libseccomp-devel gnutls-devel librbd-devel
- mkdir build
- cd build
- ../configure --cc=clang --cxx=clang++ --enable-werror
--target-list="alpha-softmmu arm-softmmu m68k-softmmu mips64-softmmu
ppc-softmmu s390x-softmmu x86_64-softmmu arm-linux-user"
- - make -j2
- - make -j2 check
+ - make -j"$JOBS"
+ - make -j"$JOBS" check
build-tci:
+ image: centos:8
+ <<: *before_script_dnf
script:
- TARGETS="aarch64 alpha arm hppa m68k microblaze moxie ppc64 s390x x86_64"
- mkdir build
- cd build
- ../configure --enable-tcg-interpreter
--target-list="$(for tg in $TARGETS; do echo -n ${tg}'-softmmu '; done)"
- - make -j2
+ - make -j"$JOBS"
- make run-tcg-tests-x86_64-softmmu
- make tests/qtest/boot-serial-test tests/qtest/cdrom-test tests/qtest/pxe-test
- for tg in $TARGETS ; do
diff --git a/.mailmap b/.mailmap
index 6412067..e3628c7 100644
--- a/.mailmap
+++ b/.mailmap
@@ -42,7 +42,8 @@
Aleksandar Markovic <aleksandar.qemu.devel@gmail.com> <aleksandar.markovic@mips.com>
Aleksandar Markovic <aleksandar.qemu.devel@gmail.com> <aleksandar.markovic@imgtec.com>
Aleksandar Markovic <aleksandar.qemu.devel@gmail.com> <amarkovic@wavecomp.com>
-Aleksandar Rikalo <aleksandar.rikalo@rt-rk.com> <arikalo@wavecomp.com>
+Aleksandar Rikalo <aleksandar.rikalo@syrmia.com> <arikalo@wavecomp.com>
+Aleksandar Rikalo <aleksandar.rikalo@syrmia.com> <aleksandar.rikalo@rt-rk.com>
Anthony Liguori <anthony@codemonkey.ws> Anthony Liguori <aliguori@us.ibm.com>
James Hogan <jhogan@kernel.org> <james.hogan@imgtec.com>
Leif Lindholm <leif@nuviainc.com> <leif.lindholm@linaro.org>
diff --git a/.travis.yml b/.travis.yml
index fe70879..564be50 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -205,14 +205,15 @@
# Test with Clang for compile portability (Travis uses clang-5.0)
- name: "Clang (user)"
env:
- - CONFIG="--disable-system"
+ - CONFIG="--disable-system --host-cc=clang --cxx=clang++"
- CACHE_NAME="${TRAVIS_BRANCH}-linux-clang-default"
compiler: clang
- name: "Clang (main-softmmu)"
env:
- - CONFIG="--target-list=${MAIN_SOFTMMU_TARGETS} "
+ - CONFIG="--target-list=${MAIN_SOFTMMU_TARGETS}
+ --host-cc=clang --cxx=clang++"
- CACHE_NAME="${TRAVIS_BRANCH}-linux-clang-sanitize"
compiler: clang
before_script:
@@ -222,7 +223,8 @@
- name: "Clang (other-softmmu)"
env:
- - CONFIG="--disable-user --target-list-exclude=${MAIN_SOFTMMU_TARGETS}"
+ - CONFIG="--disable-user --target-list-exclude=${MAIN_SOFTMMU_TARGETS}
+ --host-cc=clang --cxx=clang++"
- CACHE_NAME="${TRAVIS_BRANCH}-linux-clang-default"
compiler: clang
@@ -502,9 +504,10 @@
$(exit $BUILD_RC);
fi
- - name: "[s390x] GCC check (KVM)"
+ - name: "[s390x] Clang (disable-tcg)"
arch: s390x
dist: bionic
+ compiler: clang
addons:
apt_packages:
- libaio-dev
@@ -528,21 +531,10 @@
- libusb-1.0-0-dev
- libvdeplug-dev
- libvte-2.91-dev
- # Tests dependencies
- - genisoimage
env:
- TEST_CMD="make check-unit"
- - CONFIG="--disable-containers --disable-tcg --enable-kvm --disable-tools"
- script:
- - ( cd ${SRC_DIR} ; git submodule update --init roms/SLOF )
- - BUILD_RC=0 && make -j${JOBS} || BUILD_RC=$?
- - |
- if [ "$BUILD_RC" -eq 0 ] ; then
- mv pc-bios/s390-ccw/*.img pc-bios/ ;
- ${TEST_CMD} ;
- else
- $(exit $BUILD_RC);
- fi
+ - CONFIG="--disable-containers --disable-tcg --enable-kvm
+ --disable-tools --host-cc=clang --cxx=clang++"
# Release builds
# The make-release script expect a QEMU version, so our tag must start with a 'v'.
diff --git a/MAINTAINERS b/MAINTAINERS
index 1f84e3a..0944d9c 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -115,6 +115,7 @@
R: Paolo Bonzini <pbonzini@redhat.com>
S: Maintained
F: cpus.c
+F: cpus-common.c
F: exec.c
F: accel/tcg/
F: accel/stubs/tcg-stub.c
@@ -212,7 +213,7 @@
MIPS TCG CPUs
M: Aleksandar Markovic <aleksandar.qemu.devel@gmail.com>
R: Aurelien Jarno <aurelien@aurel32.net>
-R: Aleksandar Rikalo <aleksandar.rikalo@rt-rk.com>
+R: Aleksandar Rikalo <aleksandar.rikalo@syrmia.com>
S: Maintained
F: target/mips/
F: default-configs/*mips*
@@ -607,6 +608,7 @@
F: include/hw/arm/digic.h
F: hw/*/digic*
F: include/hw/*/digic*
+F: tests/acceptance/machine_arm_canona1100.py
Goldfish RTC
M: Anup Patel <anup.patel@wdc.com>
@@ -631,8 +633,10 @@
F: hw/arm/fsl-imx25.c
F: hw/arm/imx25_pdk.c
F: hw/misc/imx25_ccm.c
+F: hw/watchdog/wdt_imx2.c
F: include/hw/arm/fsl-imx25.h
F: include/hw/misc/imx25_ccm.h
+F: include/hw/watchdog/wdt_imx2.h
i.MX31 (kzm)
M: Peter Chubb <peter.chubb@nicta.com.au>
@@ -699,12 +703,14 @@
F: include/hw/misc/armsse-cpuid.h
F: hw/misc/armsse-mhu.c
F: include/hw/misc/armsse-mhu.h
+F: docs/system/arm/mps2.rst
Musca
M: Peter Maydell <peter.maydell@linaro.org>
L: qemu-arm@nongnu.org
S: Maintained
F: hw/arm/musca.c
+F: docs/system/arm/musca.rst
Musicpal
M: Jan Kiszka <jan.kiszka@web.de>
@@ -826,6 +832,7 @@
L: qemu-arm@nongnu.org
S: Maintained
F: hw/arm/vexpress.c
+F: docs/system/arm/vexpress.rst
Versatile PB
M: Peter Maydell <peter.maydell@linaro.org>
@@ -1041,9 +1048,9 @@
-------------
Jazz
M: Hervé Poussineau <hpoussin@reactos.org>
-R: Aleksandar Rikalo <aleksandar.rikalo@rt-rk.com>
+R: Aleksandar Rikalo <aleksandar.rikalo@syrmia.com>
S: Maintained
-F: hw/mips/mips_jazz.c
+F: hw/mips/jazz.c
F: hw/display/jazz_led.c
F: hw/dma/rc4030.c
@@ -1054,7 +1061,7 @@
S: Maintained
F: hw/isa/piix4.c
F: hw/acpi/piix4.c
-F: hw/mips/mips_malta.c
+F: hw/mips/malta.c
F: hw/mips/gt64xxx_pci.c
F: include/hw/southbridge/piix.h
F: tests/acceptance/linux_ssh_mips_malta.py
@@ -1062,30 +1069,32 @@
Mipssim
M: Aleksandar Markovic <aleksandar.qemu.devel@gmail.com>
-R: Aleksandar Rikalo <aleksandar.rikalo@rt-rk.com>
+R: Aleksandar Rikalo <aleksandar.rikalo@syrmia.com>
S: Odd Fixes
-F: hw/mips/mips_mipssim.c
+F: hw/mips/mipssim.c
F: hw/net/mipsnet.c
R4000
M: Aleksandar Markovic <aleksandar.qemu.devel@gmail.com>
R: Aurelien Jarno <aurelien@aurel32.net>
-R: Aleksandar Rikalo <aleksandar.rikalo@rt-rk.com>
+R: Aleksandar Rikalo <aleksandar.rikalo@syrmia.com>
S: Obsolete
-F: hw/mips/mips_r4k.c
+F: hw/mips/r4k.c
-Fulong 2E
+Fuloong 2E
+M: Huacai Chen <chenhc@lemote.com>
M: Philippe Mathieu-Daudé <f4bug@amsat.org>
M: Aleksandar Markovic <aleksandar.qemu.devel@gmail.com>
+R: Jiaxun Yang <jiaxun.yang@flygoat.com>
S: Odd Fixes
-F: hw/mips/mips_fulong2e.c
+F: hw/mips/fuloong2e.c
F: hw/isa/vt82c686.c
F: hw/pci-host/bonito.c
F: include/hw/isa/vt82c686.h
Boston
M: Paul Burton <pburton@wavecomp.com>
-R: Aleksandar Rikalo <aleksandar.rikalo@rt-rk.com>
+R: Aleksandar Rikalo <aleksandar.rikalo@syrmia.com>
S: Maintained
F: hw/core/loader-fit.c
F: hw/mips/boston.c
@@ -1516,6 +1525,15 @@
F: tests/qtest/acpi-utils.[hc]
F: tests/data/acpi/
+ACPI/HEST/GHES
+R: Dongjiu Geng <gengdongjiu@huawei.com>
+R: Xiang Zheng <zhengxiang9@huawei.com>
+L: qemu-arm@nongnu.org
+S: Maintained
+F: hw/acpi/ghes.c
+F: include/hw/acpi/ghes.h
+F: docs/specs/acpi_hest_ghes.rst
+
ppc4xx
M: David Gibson <david@gibson.dropbear.id.au>
L: qemu-ppc@nongnu.org
@@ -1657,7 +1675,7 @@
virtio-9p
M: Greg Kurz <groug@kaod.org>
-R: Christian Schoenebeck <qemu_oss@crudebyte.com>
+M: Christian Schoenebeck <qemu_oss@crudebyte.com>
S: Odd Fixes
F: hw/9pfs/
X: hw/9pfs/xen-9p*
@@ -2001,19 +2019,21 @@
T: git https://repo.or.cz/qemu/armbru.git block-next
Dirty Bitmaps
-M: John Snow <jsnow@redhat.com>
-R: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
+M: Eric Blake <eblake@redhat.com>
+M: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
+R: John Snow <jsnow@redhat.com>
L: qemu-block@nongnu.org
S: Supported
F: include/qemu/hbitmap.h
F: include/block/dirty-bitmap.h
+F: block/monitor/bitmap-qmp-cmds.c
F: block/dirty-bitmap.c
F: block/qcow2-bitmap.c
F: migration/block-dirty-bitmap.c
F: util/hbitmap.c
F: tests/test-hbitmap.c
F: docs/interop/bitmaps.rst
-T: git https://github.com/jnsnow/qemu.git bitmaps
+T: git https://repo.or.cz/qemu/ericb.git bitmaps
Character device backends
M: Marc-André Lureau <marcandre.lureau@redhat.com>
@@ -2315,6 +2335,12 @@
F: include/net/slirp.h
T: git https://people.debian.org/~sthibault/qemu.git slirp
+Streams
+M: Edgar E. Iglesias <edgar.iglesias@gmail.com>
+S: Maintained
+F: hw/core/stream.c
+F: include/hw/stream.h
+
Stubs
M: Paolo Bonzini <pbonzini@redhat.com>
S: Maintained
@@ -2516,7 +2542,7 @@
F: roms/edk2-*
F: tests/data/uefi-boot-images/
F: tests/uefi-test-tools/
-F: .gitlab-ci-edk2.yml
+F: .gitlab-ci.d/edk2.yml
F: .gitlab-ci.d/edk2/
Usermode Emulation
@@ -2582,7 +2608,7 @@
MIPS TCG target
M: Aleksandar Markovic <aleksandar.qemu.devel@gmail.com>
R: Aurelien Jarno <aurelien@aurel32.net>
-R: Aleksandar Rikalo <aleksandar.rikalo@rt-rk.com>
+R: Aleksandar Rikalo <aleksandar.rikalo@syrmia.com>
S: Maintained
F: tcg/mips/
@@ -2875,6 +2901,9 @@
GitLab Continuous Integration
M: Thomas Huth <thuth@redhat.com>
+M: Philippe Mathieu-Daudé <philmd@redhat.com>
+M: Alex Bennée <alex.bennee@linaro.org>
+R: Wainer dos Santos Moschetta <wainersm@redhat.com>
S: Maintained
F: .gitlab-ci.yml
diff --git a/Makefile b/Makefile
index 34275f5..40e4f76 100644
--- a/Makefile
+++ b/Makefile
@@ -1252,7 +1252,11 @@
@$(if $(TARGET_DIRS), \
echo 'Architecture specific targets:'; \
$(foreach t, $(TARGET_DIRS), \
- $(call print-help-run,$(t)/all,Build for $(t));) \
+ $(call print-help-run,$(t)/all,Build for $(t)); \
+ $(if $(CONFIG_FUZZ), \
+ $(if $(findstring softmmu,$(t)), \
+ $(call print-help-run,$(t)/fuzz,Build fuzzer for $(t)); \
+ ))) \
echo '')
@$(if $(TOOLS), \
echo 'Tools targets:'; \
diff --git a/Makefile.objs b/Makefile.objs
index a7c9676..99774cf 100644
--- a/Makefile.objs
+++ b/Makefile.objs
@@ -13,9 +13,8 @@
authz-obj-y = authz/
-block-obj-y = nbd/
+block-obj-y = block/ block/monitor/ nbd/ scsi/
block-obj-y += block.o blockjob.o job.o
-block-obj-y += block/ scsi/
block-obj-y += qemu-io-cmds.o
block-obj-$(CONFIG_REPLICATION) += replication.o
diff --git a/accel/kvm/kvm-all.c b/accel/kvm/kvm-all.c
index 439a4ef..d06cc04 100644
--- a/accel/kvm/kvm-all.c
+++ b/accel/kvm/kvm-all.c
@@ -44,6 +44,7 @@
#include "qapi/visitor.h"
#include "qapi/qapi-types-common.h"
#include "qapi/qapi-visit-common.h"
+#include "sysemu/reset.h"
#include "hw/boards.h"
@@ -883,6 +884,39 @@
return ret;
}
+typedef struct HWPoisonPage {
+ ram_addr_t ram_addr;
+ QLIST_ENTRY(HWPoisonPage) list;
+} HWPoisonPage;
+
+static QLIST_HEAD(, HWPoisonPage) hwpoison_page_list =
+ QLIST_HEAD_INITIALIZER(hwpoison_page_list);
+
+static void kvm_unpoison_all(void *param)
+{
+ HWPoisonPage *page, *next_page;
+
+ QLIST_FOREACH_SAFE(page, &hwpoison_page_list, list, next_page) {
+ QLIST_REMOVE(page, list);
+ qemu_ram_remap(page->ram_addr, TARGET_PAGE_SIZE);
+ g_free(page);
+ }
+}
+
+void kvm_hwpoison_page_add(ram_addr_t ram_addr)
+{
+ HWPoisonPage *page;
+
+ QLIST_FOREACH(page, &hwpoison_page_list, list) {
+ if (page->ram_addr == ram_addr) {
+ return;
+ }
+ }
+ page = g_new(HWPoisonPage, 1);
+ page->ram_addr = ram_addr;
+ QLIST_INSERT_HEAD(&hwpoison_page_list, page, list);
+}
+
static uint32_t adjust_ioeventfd_endianness(uint32_t val, uint32_t size)
{
#if defined(HOST_WORDS_BIGENDIAN) != defined(TARGET_WORDS_BIGENDIAN)
@@ -2085,6 +2119,8 @@
s->kernel_irqchip_split = mc->default_kernel_irqchip_split ? ON_OFF_AUTO_ON : ON_OFF_AUTO_OFF;
}
+ qemu_register_reset(kvm_unpoison_all, NULL);
+
if (s->kernel_irqchip_allowed) {
kvm_irqchip_create(s);
}
@@ -3075,15 +3111,15 @@
object_class_property_add(oc, "kernel-irqchip", "on|off|split",
NULL, kvm_set_kernel_irqchip,
- NULL, NULL, &error_abort);
+ NULL, NULL);
object_class_property_set_description(oc, "kernel-irqchip",
- "Configure KVM in-kernel irqchip", &error_abort);
+ "Configure KVM in-kernel irqchip");
object_class_property_add(oc, "kvm-shadow-mem", "int",
kvm_get_kvm_shadow_mem, kvm_set_kvm_shadow_mem,
- NULL, NULL, &error_abort);
+ NULL, NULL);
object_class_property_set_description(oc, "kvm-shadow-mem",
- "KVM shadow MMU size", &error_abort);
+ "KVM shadow MMU size");
}
static const TypeInfo kvm_accel_type = {
diff --git a/accel/tcg/tcg-all.c b/accel/tcg/tcg-all.c
index acfdcfd..3b4fda5 100644
--- a/accel/tcg/tcg-all.c
+++ b/accel/tcg/tcg-all.c
@@ -203,14 +203,13 @@
object_class_property_add_str(oc, "thread",
tcg_get_thread,
- tcg_set_thread,
- NULL);
+ tcg_set_thread);
object_class_property_add(oc, "tb-size", "int",
tcg_get_tb_size, tcg_set_tb_size,
- NULL, NULL, &error_abort);
+ NULL, NULL);
object_class_property_set_description(oc, "tb-size",
- "TCG translation block cache size", &error_abort);
+ "TCG translation block cache size");
}
diff --git a/accel/tcg/trace-events b/accel/tcg/trace-events
index 0185221..385b9f7 100644
--- a/accel/tcg/trace-events
+++ b/accel/tcg/trace-events
@@ -1,10 +1,10 @@
# See docs/devel/tracing.txt for syntax documentation.
-# TCG related tracing (mostly disabled by default)
+# TCG related tracing
# cpu-exec.c
-disable exec_tb(void *tb, uintptr_t pc) "tb:%p pc=0x%"PRIxPTR
-disable exec_tb_nocache(void *tb, uintptr_t pc) "tb:%p pc=0x%"PRIxPTR
-disable exec_tb_exit(void *last_tb, unsigned int flags) "tb:%p flags=0x%x"
+exec_tb(void *tb, uintptr_t pc) "tb:%p pc=0x%"PRIxPTR
+exec_tb_nocache(void *tb, uintptr_t pc) "tb:%p pc=0x%"PRIxPTR
+exec_tb_exit(void *last_tb, unsigned int flags) "tb:%p flags=0x%x"
# translate-all.c
translate_block(void *tb, uintptr_t pc, uint8_t *tb_code) "tb:%p, pc:0x%"PRIxPTR", tb_code:%p"
diff --git a/accel/tcg/translate-all.c b/accel/tcg/translate-all.c
index 9924e66..42ce1df 100644
--- a/accel/tcg/translate-all.c
+++ b/accel/tcg/translate-all.c
@@ -173,8 +173,13 @@
#define TB_FOR_EACH_JMP(head_tb, tb, n) \
TB_FOR_EACH_TAGGED((head_tb)->jmp_list_head, tb, n, jmp_list_next)
-/* In system mode we want L1_MAP to be based on ram offsets,
- while in user mode we want it to be based on virtual addresses. */
+/*
+ * In system mode we want L1_MAP to be based on ram offsets,
+ * while in user mode we want it to be based on virtual addresses.
+ *
+ * TODO: For user mode, see the caveat re host vs guest virtual
+ * address spaces near GUEST_ADDR_MAX.
+ */
#if !defined(CONFIG_USER_ONLY)
#if HOST_LONG_BITS < TARGET_PHYS_ADDR_SPACE_BITS
# define L1_MAP_ADDR_SPACE_BITS HOST_LONG_BITS
@@ -182,7 +187,7 @@
# define L1_MAP_ADDR_SPACE_BITS TARGET_PHYS_ADDR_SPACE_BITS
#endif
#else
-# define L1_MAP_ADDR_SPACE_BITS TARGET_VIRT_ADDR_SPACE_BITS
+# define L1_MAP_ADDR_SPACE_BITS MIN(HOST_LONG_BITS, TARGET_ABI_BITS)
#endif
/* Size of the L2 (and L3, etc) page tables. */
@@ -1789,14 +1794,43 @@
if (qemu_loglevel_mask(CPU_LOG_TB_OUT_ASM) &&
qemu_log_in_addr_range(tb->pc)) {
FILE *logfile = qemu_log_lock();
+ int code_size, data_size = 0;
+ g_autoptr(GString) note = g_string_new("[tb header & initial instruction]");
+ size_t chunk_start = 0;
+ int insn = 0;
qemu_log("OUT: [size=%d]\n", gen_code_size);
if (tcg_ctx->data_gen_ptr) {
- size_t code_size = tcg_ctx->data_gen_ptr - tb->tc.ptr;
- size_t data_size = gen_code_size - code_size;
- size_t i;
+ code_size = tcg_ctx->data_gen_ptr - tb->tc.ptr;
+ data_size = gen_code_size - code_size;
+ } else {
+ code_size = gen_code_size;
+ }
- log_disas(tb->tc.ptr, code_size);
+ /* Dump header and the first instruction */
+ chunk_start = tcg_ctx->gen_insn_end_off[insn];
+ log_disas(tb->tc.ptr, chunk_start, note->str);
+ /*
+ * Dump each instruction chunk, wrapping up empty chunks into
+ * the next instruction. The whole array is offset so the
+ * first entry is the beginning of the 2nd instruction.
+ */
+ while (insn <= tb->icount && chunk_start < code_size) {
+ size_t chunk_end = tcg_ctx->gen_insn_end_off[insn];
+ if (chunk_end > chunk_start) {
+ g_string_printf(note, "[guest addr: " TARGET_FMT_lx "]",
+ tcg_ctx->gen_insn_data[insn][0]);
+ log_disas(tb->tc.ptr + chunk_start, chunk_end - chunk_start,
+ note->str);
+ chunk_start = chunk_end;
+ }
+ insn++;
+ }
+
+ /* Finally dump any data we may have after the block */
+ if (data_size) {
+ int i;
+ qemu_log(" data: [size=%d]\n", data_size);
for (i = 0; i < data_size; i += sizeof(tcg_target_ulong)) {
if (sizeof(tcg_target_ulong) == 8) {
qemu_log("0x%08" PRIxPTR ": .quad 0x%016" PRIx64 "\n",
@@ -1808,8 +1842,6 @@
*(uint32_t *)(tcg_ctx->data_gen_ptr + i));
}
}
- } else {
- log_disas(tb->tc.ptr, gen_code_size);
}
qemu_log("\n");
qemu_log_flush();
@@ -2497,9 +2529,7 @@
/* This function should never be called with addresses outside the
guest address space. If this assert fires, it probably indicates
a missing call to h2g_valid. */
-#if TARGET_ABI_BITS > L1_MAP_ADDR_SPACE_BITS
- assert(end <= ((target_ulong)1 << L1_MAP_ADDR_SPACE_BITS));
-#endif
+ assert(end - 1 <= GUEST_ADDR_MAX);
assert(start < end);
assert_memory_lock();
diff --git a/audio/Makefile.objs b/audio/Makefile.objs
index d7490a3..b4a4c11 100644
--- a/audio/Makefile.objs
+++ b/audio/Makefile.objs
@@ -28,3 +28,8 @@
sdl.mo-objs = sdlaudio.o
sdl.mo-cflags := $(SDL_CFLAGS)
sdl.mo-libs := $(SDL_LIBS)
+
+# jack module
+common-obj-$(CONFIG_AUDIO_JACK) += jack.mo
+jack.mo-objs = jackaudio.o
+jack.mo-libs := $(JACK_LIBS)
diff --git a/audio/audio.c b/audio/audio.c
index 7a9e680..ce8c6de 100644
--- a/audio/audio.c
+++ b/audio/audio.c
@@ -649,7 +649,7 @@
total += isamp;
}
- if (!hw->pcm_ops->volume_in) {
+ if (hw->pcm_ops && !hw->pcm_ops->volume_in) {
mixeng_volume (sw->buf, ret, &sw->vol);
}
@@ -736,7 +736,7 @@
if (swlim) {
sw->conv (sw->buf, buf, swlim);
- if (!sw->hw->pcm_ops->volume_out) {
+ if (sw->hw->pcm_ops && !sw->hw->pcm_ops->volume_out) {
mixeng_volume (sw->buf, swlim, &sw->vol);
}
}
@@ -1969,6 +1969,7 @@
CASE(ALSA, alsa, Alsa);
CASE(COREAUDIO, coreaudio, Coreaudio);
CASE(DSOUND, dsound, );
+ CASE(JACK, jack, Jack);
CASE(OSS, oss, Oss);
CASE(PA, pa, Pa);
CASE(SDL, sdl, );
diff --git a/audio/audio.h b/audio/audio.h
index 0db3c7d..b883ebf 100644
--- a/audio/audio.h
+++ b/audio/audio.h
@@ -60,7 +60,7 @@
struct audio_capture_ops {
void (*notify) (void *opaque, audcnotification_e cmd);
- void (*capture) (void *opaque, void *buf, int size);
+ void (*capture) (void *opaque, const void *buf, int size);
void (*destroy) (void *opaque);
};
@@ -163,7 +163,7 @@
bool audio_is_cleaning_up(void);
void audio_cleanup(void);
-void audio_sample_to_uint64(void *samples, int pos,
+void audio_sample_to_uint64(const void *samples, int pos,
uint64_t *left, uint64_t *right);
void audio_sample_from_uint64(void *samples, int pos,
uint64_t left, uint64_t right);
diff --git a/audio/audio_template.h b/audio/audio_template.h
index 7013d30..8dd48ce 100644
--- a/audio/audio_template.h
+++ b/audio/audio_template.h
@@ -330,6 +330,8 @@
dev->u.coreaudio.TYPE);
case AUDIODEV_DRIVER_DSOUND:
return dev->u.dsound.TYPE;
+ case AUDIODEV_DRIVER_JACK:
+ return qapi_AudiodevJackPerDirectionOptions_base(dev->u.jack.TYPE);
case AUDIODEV_DRIVER_OSS:
return qapi_AudiodevOssPerDirectionOptions_base(dev->u.oss.TYPE);
case AUDIODEV_DRIVER_PA:
diff --git a/audio/jackaudio.c b/audio/jackaudio.c
new file mode 100644
index 0000000..722ddb1
--- /dev/null
+++ b/audio/jackaudio.c
@@ -0,0 +1,667 @@
+/*
+ * QEMU JACK Audio Connection Kit Client
+ *
+ * Copyright (c) 2020 Geoffrey McRae (gnif)
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include "qemu/osdep.h"
+#include "qemu/module.h"
+#include "qemu/atomic.h"
+#include "qemu-common.h"
+#include "audio.h"
+
+#define AUDIO_CAP "jack"
+#include "audio_int.h"
+
+#include <jack/jack.h>
+#include <jack/thread.h>
+
+struct QJack;
+
+typedef enum QJackState {
+ QJACK_STATE_DISCONNECTED,
+ QJACK_STATE_STOPPED,
+ QJACK_STATE_RUNNING,
+ QJACK_STATE_SHUTDOWN
+}
+QJackState;
+
+typedef struct QJackBuffer {
+ int channels;
+ int frames;
+ uint32_t used;
+ int rptr, wptr;
+ float **data;
+}
+QJackBuffer;
+
+typedef struct QJackClient {
+ AudiodevJackPerDirectionOptions *opt;
+
+ bool out;
+ bool finished;
+ bool connect_ports;
+ int packets;
+
+ QJackState state;
+ jack_client_t *client;
+ jack_nframes_t freq;
+
+ struct QJack *j;
+ int nchannels;
+ int buffersize;
+ jack_port_t **port;
+ QJackBuffer fifo;
+}
+QJackClient;
+
+typedef struct QJackOut {
+ HWVoiceOut hw;
+ QJackClient c;
+}
+QJackOut;
+
+typedef struct QJackIn {
+ HWVoiceIn hw;
+ QJackClient c;
+}
+QJackIn;
+
+static int qjack_client_init(QJackClient *c);
+static void qjack_client_connect_ports(QJackClient *c);
+static void qjack_client_fini(QJackClient *c);
+
+static void qjack_buffer_create(QJackBuffer *buffer, int channels, int frames)
+{
+ buffer->channels = channels;
+ buffer->frames = frames;
+ buffer->used = 0;
+ buffer->rptr = 0;
+ buffer->wptr = 0;
+ buffer->data = g_malloc(channels * sizeof(float *));
+ for (int i = 0; i < channels; ++i) {
+ buffer->data[i] = g_malloc(frames * sizeof(float));
+ }
+}
+
+static void qjack_buffer_clear(QJackBuffer *buffer)
+{
+ assert(buffer->data);
+ atomic_store_release(&buffer->used, 0);
+ buffer->rptr = 0;
+ buffer->wptr = 0;
+}
+
+static void qjack_buffer_free(QJackBuffer *buffer)
+{
+ if (!buffer->data) {
+ return;
+ }
+
+ for (int i = 0; i < buffer->channels; ++i) {
+ g_free(buffer->data[i]);
+ }
+
+ g_free(buffer->data);
+ buffer->data = NULL;
+}
+
+/* write PCM interleaved */
+static int qjack_buffer_write(QJackBuffer *buffer, float *data, int size)
+{
+ assert(buffer->data);
+ const int samples = size / sizeof(float);
+ int frames = samples / buffer->channels;
+ const int avail = buffer->frames - atomic_load_acquire(&buffer->used);
+
+ if (frames > avail) {
+ frames = avail;
+ }
+
+ int copy = frames;
+ int wptr = buffer->wptr;
+
+ while (copy) {
+
+ for (int c = 0; c < buffer->channels; ++c) {
+ buffer->data[c][wptr] = *data++;
+ }
+
+ if (++wptr == buffer->frames) {
+ wptr = 0;
+ }
+
+ --copy;
+ }
+
+ buffer->wptr = wptr;
+
+ atomic_add(&buffer->used, frames);
+ return frames * buffer->channels * sizeof(float);
+};
+
+/* write PCM linear */
+static int qjack_buffer_write_l(QJackBuffer *buffer, float **dest, int frames)
+{
+ assert(buffer->data);
+ const int avail = buffer->frames - atomic_load_acquire(&buffer->used);
+ int wptr = buffer->wptr;
+
+ if (frames > avail) {
+ frames = avail;
+ }
+
+ int right = buffer->frames - wptr;
+ if (right > frames) {
+ right = frames;
+ }
+
+ const int left = frames - right;
+ for (int c = 0; c < buffer->channels; ++c) {
+ memcpy(buffer->data[c] + wptr, dest[c] , right * sizeof(float));
+ memcpy(buffer->data[c] , dest[c] + right, left * sizeof(float));
+ }
+
+ wptr += frames;
+ if (wptr >= buffer->frames) {
+ wptr -= buffer->frames;
+ }
+ buffer->wptr = wptr;
+
+ atomic_add(&buffer->used, frames);
+ return frames;
+}
+
+/* read PCM interleaved */
+static int qjack_buffer_read(QJackBuffer *buffer, float *dest, int size)
+{
+ assert(buffer->data);
+ const int samples = size / sizeof(float);
+ int frames = samples / buffer->channels;
+ const int avail = atomic_load_acquire(&buffer->used);
+
+ if (frames > avail) {
+ frames = avail;
+ }
+
+ int copy = frames;
+ int rptr = buffer->rptr;
+
+ while (copy) {
+
+ for (int c = 0; c < buffer->channels; ++c) {
+ *dest++ = buffer->data[c][rptr];
+ }
+
+ if (++rptr == buffer->frames) {
+ rptr = 0;
+ }
+
+ --copy;
+ }
+
+ buffer->rptr = rptr;
+
+ atomic_sub(&buffer->used, frames);
+ return frames * buffer->channels * sizeof(float);
+}
+
+/* read PCM linear */
+static int qjack_buffer_read_l(QJackBuffer *buffer, float **dest, int frames)
+{
+ assert(buffer->data);
+ int copy = frames;
+ const int used = atomic_load_acquire(&buffer->used);
+ int rptr = buffer->rptr;
+
+ if (copy > used) {
+ copy = used;
+ }
+
+ int right = buffer->frames - rptr;
+ if (right > copy) {
+ right = copy;
+ }
+
+ const int left = copy - right;
+ for (int c = 0; c < buffer->channels; ++c) {
+ memcpy(dest[c] , buffer->data[c] + rptr, right * sizeof(float));
+ memcpy(dest[c] + right, buffer->data[c] , left * sizeof(float));
+ }
+
+ rptr += copy;
+ if (rptr >= buffer->frames) {
+ rptr -= buffer->frames;
+ }
+ buffer->rptr = rptr;
+
+ atomic_sub(&buffer->used, copy);
+ return copy;
+}
+
+static int qjack_process(jack_nframes_t nframes, void *arg)
+{
+ QJackClient *c = (QJackClient *)arg;
+
+ if (c->state != QJACK_STATE_RUNNING) {
+ return 0;
+ }
+
+ /* get the buffers for the ports */
+ float *buffers[c->nchannels];
+ for (int i = 0; i < c->nchannels; ++i) {
+ buffers[i] = jack_port_get_buffer(c->port[i], nframes);
+ }
+
+ if (c->out) {
+ qjack_buffer_read_l(&c->fifo, buffers, nframes);
+ } else {
+ qjack_buffer_write_l(&c->fifo, buffers, nframes);
+ }
+
+ return 0;
+}
+
+static void qjack_port_registration(jack_port_id_t port, int reg, void *arg)
+{
+ if (reg) {
+ QJackClient *c = (QJackClient *)arg;
+ c->connect_ports = true;
+ }
+}
+
+static int qjack_xrun(void *arg)
+{
+ QJackClient *c = (QJackClient *)arg;
+ if (c->state != QJACK_STATE_RUNNING) {
+ return 0;
+ }
+
+ qjack_buffer_clear(&c->fifo);
+ return 0;
+}
+
+static void qjack_shutdown(void *arg)
+{
+ QJackClient *c = (QJackClient *)arg;
+ c->state = QJACK_STATE_SHUTDOWN;
+}
+
+static void qjack_client_recover(QJackClient *c)
+{
+ if (c->state == QJACK_STATE_SHUTDOWN) {
+ qjack_client_fini(c);
+ }
+
+ /* packets is used simply to throttle this */
+ if (c->state == QJACK_STATE_DISCONNECTED &&
+ c->packets % 100 == 0) {
+
+ /* if not finished then attempt to recover */
+ if (!c->finished) {
+ dolog("attempting to reconnect to server\n");
+ qjack_client_init(c);
+ }
+ }
+}
+
+static size_t qjack_write(HWVoiceOut *hw, void *buf, size_t len)
+{
+ QJackOut *jo = (QJackOut *)hw;
+ ++jo->c.packets;
+
+ if (jo->c.state != QJACK_STATE_RUNNING) {
+ qjack_client_recover(&jo->c);
+ return len;
+ }
+
+ qjack_client_connect_ports(&jo->c);
+ return qjack_buffer_write(&jo->c.fifo, buf, len);
+}
+
+static size_t qjack_read(HWVoiceIn *hw, void *buf, size_t len)
+{
+ QJackIn *ji = (QJackIn *)hw;
+ ++ji->c.packets;
+
+ if (ji->c.state != QJACK_STATE_RUNNING) {
+ qjack_client_recover(&ji->c);
+ return len;
+ }
+
+ qjack_client_connect_ports(&ji->c);
+ return qjack_buffer_read(&ji->c.fifo, buf, len);
+}
+
+static void qjack_client_connect_ports(QJackClient *c)
+{
+ if (!c->connect_ports || !c->opt->connect_ports) {
+ return;
+ }
+
+ c->connect_ports = false;
+ const char **ports;
+ ports = jack_get_ports(c->client, c->opt->connect_ports, NULL,
+ c->out ? JackPortIsInput : JackPortIsOutput);
+
+ if (!ports) {
+ return;
+ }
+
+ for (int i = 0; i < c->nchannels && ports[i]; ++i) {
+ const char *p = jack_port_name(c->port[i]);
+ if (jack_port_connected_to(c->port[i], ports[i])) {
+ continue;
+ }
+
+ if (c->out) {
+ dolog("connect %s -> %s\n", p, ports[i]);
+ jack_connect(c->client, p, ports[i]);
+ } else {
+ dolog("connect %s -> %s\n", ports[i], p);
+ jack_connect(c->client, ports[i], p);
+ }
+ }
+}
+
+static int qjack_client_init(QJackClient *c)
+{
+ jack_status_t status;
+ char client_name[jack_client_name_size()];
+ jack_options_t options = JackNullOption;
+
+ c->finished = false;
+ c->connect_ports = true;
+
+ snprintf(client_name, sizeof(client_name), "%s-%s",
+ c->out ? "out" : "in",
+ c->opt->client_name ? c->opt->client_name : qemu_get_vm_name());
+
+ if (c->opt->exact_name) {
+ options |= JackUseExactName;
+ }
+
+ if (!c->opt->start_server) {
+ options |= JackNoStartServer;
+ }
+
+ if (c->opt->server_name) {
+ options |= JackServerName;
+ }
+
+ c->client = jack_client_open(client_name, options, &status,
+ c->opt->server_name);
+
+ if (c->client == NULL) {
+ dolog("jack_client_open failed: status = 0x%2.0x\n", status);
+ if (status & JackServerFailed) {
+ dolog("unable to connect to JACK server\n");
+ }
+ return -1;
+ }
+
+ c->freq = jack_get_sample_rate(c->client);
+
+ if (status & JackServerStarted) {
+ dolog("JACK server started\n");
+ }
+
+ if (status & JackNameNotUnique) {
+ dolog("JACK unique name assigned %s\n",
+ jack_get_client_name(c->client));
+ }
+
+ jack_set_process_callback(c->client, qjack_process , c);
+ jack_set_port_registration_callback(c->client, qjack_port_registration, c);
+ jack_set_xrun_callback(c->client, qjack_xrun, c);
+ jack_on_shutdown(c->client, qjack_shutdown, c);
+
+ /*
+ * ensure the buffersize is no smaller then 512 samples, some (all?) qemu
+ * virtual devices do not work correctly otherwise
+ */
+ if (c->buffersize < 512) {
+ c->buffersize = 512;
+ }
+
+ /* create a 2 period buffer */
+ qjack_buffer_create(&c->fifo, c->nchannels, c->buffersize * 2);
+
+ /* allocate and register the ports */
+ c->port = g_malloc(sizeof(jack_port_t *) * c->nchannels);
+ for (int i = 0; i < c->nchannels; ++i) {
+
+ char port_name[16];
+ snprintf(
+ port_name,
+ sizeof(port_name),
+ c->out ? "output %d" : "input %d",
+ i);
+
+ c->port[i] = jack_port_register(
+ c->client,
+ port_name,
+ JACK_DEFAULT_AUDIO_TYPE,
+ c->out ? JackPortIsOutput : JackPortIsInput,
+ 0);
+ }
+
+ /* activate the session */
+ jack_activate(c->client);
+ c->buffersize = jack_get_buffer_size(c->client);
+
+ qjack_client_connect_ports(c);
+ c->state = QJACK_STATE_RUNNING;
+ return 0;
+}
+
+static int qjack_init_out(HWVoiceOut *hw, struct audsettings *as,
+ void *drv_opaque)
+{
+ QJackOut *jo = (QJackOut *)hw;
+ Audiodev *dev = (Audiodev *)drv_opaque;
+
+ if (jo->c.state != QJACK_STATE_DISCONNECTED) {
+ return 0;
+ }
+
+ jo->c.out = true;
+ jo->c.nchannels = as->nchannels;
+ jo->c.opt = dev->u.jack.out;
+ int ret = qjack_client_init(&jo->c);
+ if (ret != 0) {
+ return ret;
+ }
+
+ /* report the buffer size to qemu */
+ hw->samples = jo->c.buffersize;
+
+ /* report the audio format we support */
+ struct audsettings os = {
+ .freq = jo->c.freq,
+ .nchannels = jo->c.nchannels,
+ .fmt = AUDIO_FORMAT_F32,
+ .endianness = 0
+ };
+ audio_pcm_init_info(&hw->info, &os);
+
+ dolog("JACK output configured for %dHz (%d samples)\n",
+ jo->c.freq, jo->c.buffersize);
+
+ return 0;
+}
+
+static int qjack_init_in(HWVoiceIn *hw, struct audsettings *as,
+ void *drv_opaque)
+{
+ QJackIn *ji = (QJackIn *)hw;
+ Audiodev *dev = (Audiodev *)drv_opaque;
+
+ if (ji->c.state != QJACK_STATE_DISCONNECTED) {
+ return 0;
+ }
+
+ ji->c.out = false;
+ ji->c.nchannels = as->nchannels;
+ ji->c.opt = dev->u.jack.in;
+ int ret = qjack_client_init(&ji->c);
+ if (ret != 0) {
+ return ret;
+ }
+
+ /* report the buffer size to qemu */
+ hw->samples = ji->c.buffersize;
+
+ /* report the audio format we support */
+ struct audsettings is = {
+ .freq = ji->c.freq,
+ .nchannels = ji->c.nchannels,
+ .fmt = AUDIO_FORMAT_F32,
+ .endianness = 0
+ };
+ audio_pcm_init_info(&hw->info, &is);
+
+ dolog("JACK input configured for %dHz (%d samples)\n",
+ ji->c.freq, ji->c.buffersize);
+
+ return 0;
+}
+
+static void qjack_client_fini(QJackClient *c)
+{
+ switch (c->state) {
+ case QJACK_STATE_RUNNING:
+ /* fallthrough */
+
+ case QJACK_STATE_STOPPED:
+ for (int i = 0; i < c->nchannels; ++i) {
+ jack_port_unregister(c->client, c->port[i]);
+ }
+ jack_deactivate(c->client);
+ /* fallthrough */
+
+ case QJACK_STATE_SHUTDOWN:
+ jack_client_close(c->client);
+ /* fallthrough */
+
+ case QJACK_STATE_DISCONNECTED:
+ break;
+ }
+
+ qjack_buffer_free(&c->fifo);
+ g_free(c->port);
+
+ c->state = QJACK_STATE_DISCONNECTED;
+}
+
+static void qjack_fini_out(HWVoiceOut *hw)
+{
+ QJackOut *jo = (QJackOut *)hw;
+ jo->c.finished = true;
+ qjack_client_fini(&jo->c);
+}
+
+static void qjack_fini_in(HWVoiceIn *hw)
+{
+ QJackIn *ji = (QJackIn *)hw;
+ ji->c.finished = true;
+ qjack_client_fini(&ji->c);
+}
+
+static void qjack_enable_out(HWVoiceOut *hw, bool enable)
+{
+}
+
+static void qjack_enable_in(HWVoiceIn *hw, bool enable)
+{
+}
+
+static int qjack_thread_creator(jack_native_thread_t *thread,
+ const pthread_attr_t *attr, void *(*function)(void *), void *arg)
+{
+ int ret = pthread_create(thread, attr, function, arg);
+ if (ret != 0) {
+ return ret;
+ }
+
+ /* set the name of the thread */
+ pthread_setname_np(*thread, "jack-client");
+
+ return ret;
+}
+
+static void *qjack_init(Audiodev *dev)
+{
+ assert(dev->driver == AUDIODEV_DRIVER_JACK);
+
+ dev->u.jack.has_in = false;
+
+ return dev;
+}
+
+static void qjack_fini(void *opaque)
+{
+}
+
+static struct audio_pcm_ops jack_pcm_ops = {
+ .init_out = qjack_init_out,
+ .fini_out = qjack_fini_out,
+ .write = qjack_write,
+ .run_buffer_out = audio_generic_run_buffer_out,
+ .enable_out = qjack_enable_out,
+
+ .init_in = qjack_init_in,
+ .fini_in = qjack_fini_in,
+ .read = qjack_read,
+ .enable_in = qjack_enable_in
+};
+
+static struct audio_driver jack_driver = {
+ .name = "jack",
+ .descr = "JACK Audio Connection Kit Client",
+ .init = qjack_init,
+ .fini = qjack_fini,
+ .pcm_ops = &jack_pcm_ops,
+ .can_be_default = 1,
+ .max_voices_out = INT_MAX,
+ .max_voices_in = INT_MAX,
+ .voice_size_out = sizeof(QJackOut),
+ .voice_size_in = sizeof(QJackIn)
+};
+
+static void qjack_error(const char *msg)
+{
+ dolog("E: %s\n", msg);
+}
+
+static void qjack_info(const char *msg)
+{
+ dolog("I: %s\n", msg);
+}
+
+static void register_audio_jack(void)
+{
+ audio_driver_register(&jack_driver);
+ jack_set_thread_creator(qjack_thread_creator);
+ jack_set_error_function(qjack_error);
+ jack_set_info_function(qjack_info);
+}
+type_init(register_audio_jack);
diff --git a/audio/mixeng.c b/audio/mixeng.c
index 739a500..f27deb1 100644
--- a/audio/mixeng.c
+++ b/audio/mixeng.c
@@ -271,11 +271,12 @@
#define CONV_NATURAL_FLOAT(x) (x)
#define CLIP_NATURAL_FLOAT(x) (x)
#else
-static const float float_scale = UINT_MAX / 2.f;
+/* macros to map [-1.f, 1.f] <-> [INT32_MIN, INT32_MAX + 1] */
+static const float float_scale = (int64_t)INT32_MAX + 1;
#define CONV_NATURAL_FLOAT(x) ((x) * float_scale)
#ifdef RECIPROCAL
-static const float float_scale_reciprocal = 2.f / UINT_MAX;
+static const float float_scale_reciprocal = 1.f / ((int64_t)INT32_MAX + 1);
#define CLIP_NATURAL_FLOAT(x) ((x) * float_scale_reciprocal)
#else
#define CLIP_NATURAL_FLOAT(x) ((x) / float_scale)
@@ -338,10 +339,10 @@
clip_natural_float_from_stereo,
};
-void audio_sample_to_uint64(void *samples, int pos,
+void audio_sample_to_uint64(const void *samples, int pos,
uint64_t *left, uint64_t *right)
{
- struct st_sample *sample = samples;
+ const struct st_sample *sample = samples;
sample += pos;
#ifdef FLOAT_MIXENG
error_report(
diff --git a/audio/wavcapture.c b/audio/wavcapture.c
index 8d7ce2e..17e87ed 100644
--- a/audio/wavcapture.c
+++ b/audio/wavcapture.c
@@ -71,7 +71,7 @@
g_free (wav->path);
}
-static void wav_capture (void *opaque, void *buf, int size)
+static void wav_capture(void *opaque, const void *buf, int size)
{
WAVState *wav = opaque;
diff --git a/authz/list.c b/authz/list.c
index 5a48074..8e904bf 100644
--- a/authz/list.c
+++ b/authz/list.c
@@ -124,13 +124,12 @@
"QAuthZListPolicy",
&QAuthZListPolicy_lookup,
qauthz_list_prop_get_policy,
- qauthz_list_prop_set_policy,
- NULL);
+ qauthz_list_prop_set_policy);
object_class_property_add(oc, "rules", "QAuthZListRule",
qauthz_list_prop_get_rules,
qauthz_list_prop_set_rules,
- NULL, NULL, NULL);
+ NULL, NULL);
authz->is_allowed = qauthz_list_is_allowed;
}
diff --git a/authz/listfile.c b/authz/listfile.c
index b71f57d..666df87 100644
--- a/authz/listfile.c
+++ b/authz/listfile.c
@@ -221,12 +221,10 @@
object_class_property_add_str(oc, "filename",
qauthz_list_file_prop_get_filename,
- qauthz_list_file_prop_set_filename,
- NULL);
+ qauthz_list_file_prop_set_filename);
object_class_property_add_bool(oc, "refresh",
qauthz_list_file_prop_get_refresh,
- qauthz_list_file_prop_set_refresh,
- NULL);
+ qauthz_list_file_prop_set_refresh);
authz->is_allowed = qauthz_list_file_is_allowed;
}
diff --git a/authz/pamacct.c b/authz/pamacct.c
index a8ad25b..3c6be43 100644
--- a/authz/pamacct.c
+++ b/authz/pamacct.c
@@ -107,8 +107,7 @@
object_class_property_add_str(oc, "service",
qauthz_pam_prop_get_service,
- qauthz_pam_prop_set_service,
- NULL);
+ qauthz_pam_prop_set_service);
}
diff --git a/authz/simple.c b/authz/simple.c
index 008912d..84954b8 100644
--- a/authz/simple.c
+++ b/authz/simple.c
@@ -74,8 +74,7 @@
object_class_property_add_str(oc, "identity",
qauthz_simple_prop_get_identity,
- qauthz_simple_prop_set_identity,
- NULL);
+ qauthz_simple_prop_set_identity);
}
diff --git a/backends/cryptodev-vhost-user.c b/backends/cryptodev-vhost-user.c
index 6edada8..8b8cbc4 100644
--- a/backends/cryptodev-vhost-user.c
+++ b/backends/cryptodev-vhost-user.c
@@ -340,8 +340,7 @@
{
object_property_add_str(obj, "chardev",
cryptodev_vhost_user_get_chardev,
- cryptodev_vhost_user_set_chardev,
- NULL);
+ cryptodev_vhost_user_set_chardev);
}
static void cryptodev_vhost_user_finalize(Object *obj)
diff --git a/backends/cryptodev.c b/backends/cryptodev.c
index 5a97356..a3841c4 100644
--- a/backends/cryptodev.c
+++ b/backends/cryptodev.c
@@ -213,7 +213,7 @@
object_property_add(obj, "queues", "uint32",
cryptodev_backend_get_queues,
cryptodev_backend_set_queues,
- NULL, NULL, NULL);
+ NULL, NULL);
/* Initialize devices' queues property to 1 */
object_property_set_int(obj, 1, "queues", NULL);
}
diff --git a/backends/dbus-vmstate.c b/backends/dbus-vmstate.c
index cc594a7..56361a6 100644
--- a/backends/dbus-vmstate.c
+++ b/backends/dbus-vmstate.c
@@ -481,11 +481,9 @@
vc->get_id = dbus_vmstate_get_id;
object_class_property_add_str(oc, "addr",
- get_dbus_addr, set_dbus_addr,
- &error_abort);
+ get_dbus_addr, set_dbus_addr);
object_class_property_add_str(oc, "id-list",
- get_id_list, set_id_list,
- &error_abort);
+ get_id_list, set_id_list);
}
static const TypeInfo dbus_vmstate_info = {
diff --git a/backends/hostmem-file.c b/backends/hostmem-file.c
index c8c355f..cdabb41 100644
--- a/backends/hostmem-file.c
+++ b/backends/hostmem-file.c
@@ -184,18 +184,15 @@
oc->unparent = file_backend_unparent;
object_class_property_add_bool(oc, "discard-data",
- file_memory_backend_get_discard_data, file_memory_backend_set_discard_data,
- &error_abort);
+ file_memory_backend_get_discard_data, file_memory_backend_set_discard_data);
object_class_property_add_str(oc, "mem-path",
- get_mem_path, set_mem_path,
- &error_abort);
+ get_mem_path, set_mem_path);
object_class_property_add(oc, "align", "int",
file_memory_backend_get_align,
file_memory_backend_set_align,
- NULL, NULL, &error_abort);
+ NULL, NULL);
object_class_property_add_bool(oc, "pmem",
- file_memory_backend_get_pmem, file_memory_backend_set_pmem,
- &error_abort);
+ file_memory_backend_get_pmem, file_memory_backend_set_pmem);
}
static void file_backend_instance_finalize(Object *o)
diff --git a/backends/hostmem-memfd.c b/backends/hostmem-memfd.c
index 74ba987..1b5e4bf 100644
--- a/backends/hostmem-memfd.c
+++ b/backends/hostmem-memfd.c
@@ -141,26 +141,21 @@
if (qemu_memfd_check(MFD_HUGETLB)) {
object_class_property_add_bool(oc, "hugetlb",
memfd_backend_get_hugetlb,
- memfd_backend_set_hugetlb,
- &error_abort);
+ memfd_backend_set_hugetlb);
object_class_property_set_description(oc, "hugetlb",
- "Use huge pages",
- &error_abort);
+ "Use huge pages");
object_class_property_add(oc, "hugetlbsize", "int",
memfd_backend_get_hugetlbsize,
memfd_backend_set_hugetlbsize,
- NULL, NULL, &error_abort);
+ NULL, NULL);
object_class_property_set_description(oc, "hugetlbsize",
- "Huge pages size (ex: 2M, 1G)",
- &error_abort);
+ "Huge pages size (ex: 2M, 1G)");
}
object_class_property_add_bool(oc, "seal",
memfd_backend_get_seal,
- memfd_backend_set_seal,
- &error_abort);
+ memfd_backend_set_seal);
object_class_property_set_description(oc, "seal",
- "Seal growing & shrinking",
- &error_abort);
+ "Seal growing & shrinking");
}
static const TypeInfo memfd_backend_info = {
diff --git a/backends/hostmem.c b/backends/hostmem.c
index 0efd7b7..61e3255 100644
--- a/backends/hostmem.c
+++ b/backends/hostmem.c
@@ -465,51 +465,50 @@
object_class_property_add_bool(oc, "merge",
host_memory_backend_get_merge,
- host_memory_backend_set_merge, &error_abort);
+ host_memory_backend_set_merge);
object_class_property_set_description(oc, "merge",
- "Mark memory as mergeable", &error_abort);
+ "Mark memory as mergeable");
object_class_property_add_bool(oc, "dump",
host_memory_backend_get_dump,
- host_memory_backend_set_dump, &error_abort);
+ host_memory_backend_set_dump);
object_class_property_set_description(oc, "dump",
- "Set to 'off' to exclude from core dump", &error_abort);
+ "Set to 'off' to exclude from core dump");
object_class_property_add_bool(oc, "prealloc",
host_memory_backend_get_prealloc,
- host_memory_backend_set_prealloc, &error_abort);
+ host_memory_backend_set_prealloc);
object_class_property_set_description(oc, "prealloc",
- "Preallocate memory", &error_abort);
+ "Preallocate memory");
object_class_property_add(oc, "prealloc-threads", "int",
host_memory_backend_get_prealloc_threads,
host_memory_backend_set_prealloc_threads,
- NULL, NULL, &error_abort);
+ NULL, NULL);
object_class_property_set_description(oc, "prealloc-threads",
- "Number of CPU threads to use for prealloc", &error_abort);
+ "Number of CPU threads to use for prealloc");
object_class_property_add(oc, "size", "int",
host_memory_backend_get_size,
host_memory_backend_set_size,
- NULL, NULL, &error_abort);
+ NULL, NULL);
object_class_property_set_description(oc, "size",
- "Size of the memory region (ex: 500M)", &error_abort);
+ "Size of the memory region (ex: 500M)");
object_class_property_add(oc, "host-nodes", "int",
host_memory_backend_get_host_nodes,
host_memory_backend_set_host_nodes,
- NULL, NULL, &error_abort);
+ NULL, NULL);
object_class_property_set_description(oc, "host-nodes",
- "Binds memory to the list of NUMA host nodes", &error_abort);
+ "Binds memory to the list of NUMA host nodes");
object_class_property_add_enum(oc, "policy", "HostMemPolicy",
&HostMemPolicy_lookup,
host_memory_backend_get_policy,
- host_memory_backend_set_policy, &error_abort);
+ host_memory_backend_set_policy);
object_class_property_set_description(oc, "policy",
- "Set the NUMA policy", &error_abort);
+ "Set the NUMA policy");
object_class_property_add_bool(oc, "share",
- host_memory_backend_get_share, host_memory_backend_set_share,
- &error_abort);
+ host_memory_backend_get_share, host_memory_backend_set_share);
object_class_property_set_description(oc, "share",
- "Mark the memory as private to QEMU or shared", &error_abort);
+ "Mark the memory as private to QEMU or shared");
object_class_property_add_bool(oc, "x-use-canonical-path-for-ramblock-id",
host_memory_backend_get_use_canonical_path,
- host_memory_backend_set_use_canonical_path, &error_abort);
+ host_memory_backend_set_use_canonical_path);
}
static const TypeInfo host_memory_backend_info = {
diff --git a/backends/rng-egd.c b/backends/rng-egd.c
index e380519..7aaa6ee 100644
--- a/backends/rng-egd.c
+++ b/backends/rng-egd.c
@@ -138,8 +138,7 @@
static void rng_egd_init(Object *obj)
{
object_property_add_str(obj, "chardev",
- rng_egd_get_chardev, rng_egd_set_chardev,
- NULL);
+ rng_egd_get_chardev, rng_egd_set_chardev);
}
static void rng_egd_finalize(Object *obj)
diff --git a/backends/rng-random.c b/backends/rng-random.c
index a810581..32998d8 100644
--- a/backends/rng-random.c
+++ b/backends/rng-random.c
@@ -110,8 +110,7 @@
object_property_add_str(obj, "filename",
rng_random_get_filename,
- rng_random_set_filename,
- NULL);
+ rng_random_set_filename);
s->filename = g_strdup("/dev/urandom");
s->fd = -1;
diff --git a/backends/rng.c b/backends/rng.c
index 391888b..597f0ec 100644
--- a/backends/rng.c
+++ b/backends/rng.c
@@ -108,8 +108,7 @@
object_property_add_bool(obj, "opened",
rng_backend_prop_get_opened,
- rng_backend_prop_set_opened,
- NULL);
+ rng_backend_prop_set_opened);
}
static void rng_backend_finalize(Object *obj)
diff --git a/backends/vhost-user.c b/backends/vhost-user.c
index 2bf3406..9e6e198 100644
--- a/backends/vhost-user.c
+++ b/backends/vhost-user.c
@@ -177,7 +177,7 @@
static void vhost_user_backend_init(Object *obj)
{
- object_property_add_str(obj, "chardev", get_chardev, set_chardev, NULL);
+ object_property_add_str(obj, "chardev", get_chardev, set_chardev);
}
static void vhost_user_backend_finalize(Object *obj)
diff --git a/block.c b/block.c
index 0653ccb..8416376 100644
--- a/block.c
+++ b/block.c
@@ -76,7 +76,8 @@
const char *reference,
QDict *options, int flags,
BlockDriverState *parent,
- const BdrvChildRole *child_role,
+ const BdrvChildClass *child_class,
+ BdrvChildRole child_role,
Error **errp);
/* If non-zero, use only whitelisted block drivers */
@@ -1093,18 +1094,6 @@
bdrv_drained_end_no_poll(bs, drained_end_counter);
}
-static void bdrv_child_cb_attach(BdrvChild *child)
-{
- BlockDriverState *bs = child->opaque;
- bdrv_apply_subtree_drain(child, bs);
-}
-
-static void bdrv_child_cb_detach(BdrvChild *child)
-{
- BlockDriverState *bs = child->opaque;
- bdrv_unapply_subtree_drain(child, bs);
-}
-
static int bdrv_child_cb_inactivate(BdrvChild *child)
{
BlockDriverState *bs = child->opaque;
@@ -1149,82 +1138,6 @@
*child_flags &= ~BDRV_O_NATIVE_AIO;
}
-/*
- * Returns the options and flags that bs->file should get if a protocol driver
- * is expected, based on the given options and flags for the parent BDS
- */
-static void bdrv_inherited_options(int *child_flags, QDict *child_options,
- int parent_flags, QDict *parent_options)
-{
- int flags = parent_flags;
-
- /* Enable protocol handling, disable format probing for bs->file */
- flags |= BDRV_O_PROTOCOL;
-
- /* If the cache mode isn't explicitly set, inherit direct and no-flush from
- * the parent. */
- qdict_copy_default(child_options, parent_options, BDRV_OPT_CACHE_DIRECT);
- qdict_copy_default(child_options, parent_options, BDRV_OPT_CACHE_NO_FLUSH);
- qdict_copy_default(child_options, parent_options, BDRV_OPT_FORCE_SHARE);
-
- /* Inherit the read-only option from the parent if it's not set */
- qdict_copy_default(child_options, parent_options, BDRV_OPT_READ_ONLY);
- qdict_copy_default(child_options, parent_options, BDRV_OPT_AUTO_READ_ONLY);
-
- /* Our block drivers take care to send flushes and respect unmap policy,
- * so we can default to enable both on lower layers regardless of the
- * corresponding parent options. */
- qdict_set_default_str(child_options, BDRV_OPT_DISCARD, "unmap");
-
- /* Clear flags that only apply to the top layer */
- flags &= ~(BDRV_O_SNAPSHOT | BDRV_O_NO_BACKING | BDRV_O_COPY_ON_READ |
- BDRV_O_NO_IO);
-
- *child_flags = flags;
-}
-
-const BdrvChildRole child_file = {
- .parent_is_bds = true,
- .get_parent_desc = bdrv_child_get_parent_desc,
- .inherit_options = bdrv_inherited_options,
- .drained_begin = bdrv_child_cb_drained_begin,
- .drained_poll = bdrv_child_cb_drained_poll,
- .drained_end = bdrv_child_cb_drained_end,
- .attach = bdrv_child_cb_attach,
- .detach = bdrv_child_cb_detach,
- .inactivate = bdrv_child_cb_inactivate,
- .can_set_aio_ctx = bdrv_child_cb_can_set_aio_ctx,
- .set_aio_ctx = bdrv_child_cb_set_aio_ctx,
-};
-
-/*
- * Returns the options and flags that bs->file should get if the use of formats
- * (and not only protocols) is permitted for it, based on the given options and
- * flags for the parent BDS
- */
-static void bdrv_inherited_fmt_options(int *child_flags, QDict *child_options,
- int parent_flags, QDict *parent_options)
-{
- child_file.inherit_options(child_flags, child_options,
- parent_flags, parent_options);
-
- *child_flags &= ~(BDRV_O_PROTOCOL | BDRV_O_NO_IO);
-}
-
-const BdrvChildRole child_format = {
- .parent_is_bds = true,
- .get_parent_desc = bdrv_child_get_parent_desc,
- .inherit_options = bdrv_inherited_fmt_options,
- .drained_begin = bdrv_child_cb_drained_begin,
- .drained_poll = bdrv_child_cb_drained_poll,
- .drained_end = bdrv_child_cb_drained_end,
- .attach = bdrv_child_cb_attach,
- .detach = bdrv_child_cb_detach,
- .inactivate = bdrv_child_cb_inactivate,
- .can_set_aio_ctx = bdrv_child_cb_can_set_aio_ctx,
- .set_aio_ctx = bdrv_child_cb_set_aio_ctx,
-};
-
static void bdrv_backing_attach(BdrvChild *c)
{
BlockDriverState *parent = c->opaque;
@@ -1266,8 +1179,6 @@
parent->backing_blocker);
bdrv_op_unblock(backing_hd, BLOCK_OP_TYPE_BACKUP_TARGET,
parent->backing_blocker);
-
- bdrv_child_cb_attach(c);
}
static void bdrv_backing_detach(BdrvChild *c)
@@ -1278,34 +1189,6 @@
bdrv_op_unblock_all(c->bs, parent->backing_blocker);
error_free(parent->backing_blocker);
parent->backing_blocker = NULL;
-
- bdrv_child_cb_detach(c);
-}
-
-/*
- * Returns the options and flags that bs->backing should get, based on the
- * given options and flags for the parent BDS
- */
-static void bdrv_backing_options(int *child_flags, QDict *child_options,
- int parent_flags, QDict *parent_options)
-{
- int flags = parent_flags;
-
- /* The cache mode is inherited unmodified for backing files; except WCE,
- * which is only applied on the top level (BlockBackend) */
- qdict_copy_default(child_options, parent_options, BDRV_OPT_CACHE_DIRECT);
- qdict_copy_default(child_options, parent_options, BDRV_OPT_CACHE_NO_FLUSH);
- qdict_copy_default(child_options, parent_options, BDRV_OPT_FORCE_SHARE);
-
- /* backing files always opened read-only */
- qdict_set_default_str(child_options, BDRV_OPT_READ_ONLY, "on");
- qdict_set_default_str(child_options, BDRV_OPT_AUTO_READ_ONLY, "off");
- flags &= ~BDRV_O_COPY_ON_READ;
-
- /* snapshot=on is handled on the top layer */
- flags &= ~(BDRV_O_SNAPSHOT | BDRV_O_TEMPORARY);
-
- *child_flags = flags;
}
static int bdrv_backing_update_filename(BdrvChild *c, BlockDriverState *base,
@@ -1335,19 +1218,130 @@
return ret;
}
-const BdrvChildRole child_backing = {
+/*
+ * Returns the options and flags that a generic child of a BDS should
+ * get, based on the given options and flags for the parent BDS.
+ */
+static void bdrv_inherited_options(BdrvChildRole role, bool parent_is_format,
+ int *child_flags, QDict *child_options,
+ int parent_flags, QDict *parent_options)
+{
+ int flags = parent_flags;
+
+ /*
+ * First, decide whether to set, clear, or leave BDRV_O_PROTOCOL.
+ * Generally, the question to answer is: Should this child be
+ * format-probed by default?
+ */
+
+ /*
+ * Pure and non-filtered data children of non-format nodes should
+ * be probed by default (even when the node itself has BDRV_O_PROTOCOL
+ * set). This only affects a very limited set of drivers (namely
+ * quorum and blkverify when this comment was written).
+ * Force-clear BDRV_O_PROTOCOL then.
+ */
+ if (!parent_is_format &&
+ (role & BDRV_CHILD_DATA) &&
+ !(role & (BDRV_CHILD_METADATA | BDRV_CHILD_FILTERED)))
+ {
+ flags &= ~BDRV_O_PROTOCOL;
+ }
+
+ /*
+ * All children of format nodes (except for COW children) and all
+ * metadata children in general should never be format-probed.
+ * Force-set BDRV_O_PROTOCOL then.
+ */
+ if ((parent_is_format && !(role & BDRV_CHILD_COW)) ||
+ (role & BDRV_CHILD_METADATA))
+ {
+ flags |= BDRV_O_PROTOCOL;
+ }
+
+ /*
+ * If the cache mode isn't explicitly set, inherit direct and no-flush from
+ * the parent.
+ */
+ qdict_copy_default(child_options, parent_options, BDRV_OPT_CACHE_DIRECT);
+ qdict_copy_default(child_options, parent_options, BDRV_OPT_CACHE_NO_FLUSH);
+ qdict_copy_default(child_options, parent_options, BDRV_OPT_FORCE_SHARE);
+
+ if (role & BDRV_CHILD_COW) {
+ /* backing files are opened read-only by default */
+ qdict_set_default_str(child_options, BDRV_OPT_READ_ONLY, "on");
+ qdict_set_default_str(child_options, BDRV_OPT_AUTO_READ_ONLY, "off");
+ } else {
+ /* Inherit the read-only option from the parent if it's not set */
+ qdict_copy_default(child_options, parent_options, BDRV_OPT_READ_ONLY);
+ qdict_copy_default(child_options, parent_options,
+ BDRV_OPT_AUTO_READ_ONLY);
+ }
+
+ /*
+ * bdrv_co_pdiscard() respects unmap policy for the parent, so we
+ * can default to enable it on lower layers regardless of the
+ * parent option.
+ */
+ qdict_set_default_str(child_options, BDRV_OPT_DISCARD, "unmap");
+
+ /* Clear flags that only apply to the top layer */
+ flags &= ~(BDRV_O_SNAPSHOT | BDRV_O_NO_BACKING | BDRV_O_COPY_ON_READ);
+
+ if (role & BDRV_CHILD_METADATA) {
+ flags &= ~BDRV_O_NO_IO;
+ }
+ if (role & BDRV_CHILD_COW) {
+ flags &= ~BDRV_O_TEMPORARY;
+ }
+
+ *child_flags = flags;
+}
+
+static void bdrv_child_cb_attach(BdrvChild *child)
+{
+ BlockDriverState *bs = child->opaque;
+
+ if (child->role & BDRV_CHILD_COW) {
+ bdrv_backing_attach(child);
+ }
+
+ bdrv_apply_subtree_drain(child, bs);
+}
+
+static void bdrv_child_cb_detach(BdrvChild *child)
+{
+ BlockDriverState *bs = child->opaque;
+
+ if (child->role & BDRV_CHILD_COW) {
+ bdrv_backing_detach(child);
+ }
+
+ bdrv_unapply_subtree_drain(child, bs);
+}
+
+static int bdrv_child_cb_update_filename(BdrvChild *c, BlockDriverState *base,
+ const char *filename, Error **errp)
+{
+ if (c->role & BDRV_CHILD_COW) {
+ return bdrv_backing_update_filename(c, base, filename, errp);
+ }
+ return 0;
+}
+
+const BdrvChildClass child_of_bds = {
.parent_is_bds = true,
.get_parent_desc = bdrv_child_get_parent_desc,
- .attach = bdrv_backing_attach,
- .detach = bdrv_backing_detach,
- .inherit_options = bdrv_backing_options,
+ .inherit_options = bdrv_inherited_options,
.drained_begin = bdrv_child_cb_drained_begin,
.drained_poll = bdrv_child_cb_drained_poll,
.drained_end = bdrv_child_cb_drained_end,
+ .attach = bdrv_child_cb_attach,
+ .detach = bdrv_child_cb_detach,
.inactivate = bdrv_child_cb_inactivate,
- .update_filename = bdrv_backing_update_filename,
.can_set_aio_ctx = bdrv_child_cb_can_set_aio_ctx,
.set_aio_ctx = bdrv_child_cb_set_aio_ctx,
+ .update_filename = bdrv_child_cb_update_filename,
};
static int bdrv_open_flags(BlockDriverState *bs, int flags)
@@ -1953,7 +1947,7 @@
}
static void bdrv_child_perm(BlockDriverState *bs, BlockDriverState *child_bs,
- BdrvChild *c, const BdrvChildRole *role,
+ BdrvChild *c, BdrvChildRole role,
BlockReopenQueue *reopen_queue,
uint64_t parent_perm, uint64_t parent_shared,
uint64_t *nperm, uint64_t *nshared)
@@ -2145,8 +2139,8 @@
static char *bdrv_child_user_desc(BdrvChild *c)
{
- if (c->role->get_parent_desc) {
- return c->role->get_parent_desc(c);
+ if (c->klass->get_parent_desc) {
+ return c->klass->get_parent_desc(c);
}
return g_strdup("another user");
@@ -2348,66 +2342,132 @@
uint64_t perms, shared;
bdrv_get_cumulative_perm(bs, &parent_perms, &parent_shared);
- bdrv_child_perm(bs, c->bs, c, c->role, NULL, parent_perms, parent_shared,
- &perms, &shared);
+ bdrv_child_perm(bs, c->bs, c, c->role, NULL,
+ parent_perms, parent_shared, &perms, &shared);
return bdrv_child_try_set_perm(c, perms, shared, errp);
}
-void bdrv_filter_default_perms(BlockDriverState *bs, BdrvChild *c,
- const BdrvChildRole *role,
- BlockReopenQueue *reopen_queue,
- uint64_t perm, uint64_t shared,
- uint64_t *nperm, uint64_t *nshared)
+/*
+ * Default implementation for .bdrv_child_perm() for block filters:
+ * Forward CONSISTENT_READ, WRITE, WRITE_UNCHANGED, and RESIZE to the
+ * filtered child.
+ */
+static void bdrv_filter_default_perms(BlockDriverState *bs, BdrvChild *c,
+ BdrvChildRole role,
+ BlockReopenQueue *reopen_queue,
+ uint64_t perm, uint64_t shared,
+ uint64_t *nperm, uint64_t *nshared)
{
*nperm = perm & DEFAULT_PERM_PASSTHROUGH;
*nshared = (shared & DEFAULT_PERM_PASSTHROUGH) | DEFAULT_PERM_UNCHANGED;
}
-void bdrv_format_default_perms(BlockDriverState *bs, BdrvChild *c,
- const BdrvChildRole *role,
- BlockReopenQueue *reopen_queue,
- uint64_t perm, uint64_t shared,
- uint64_t *nperm, uint64_t *nshared)
+static void bdrv_default_perms_for_cow(BlockDriverState *bs, BdrvChild *c,
+ BdrvChildRole role,
+ BlockReopenQueue *reopen_queue,
+ uint64_t perm, uint64_t shared,
+ uint64_t *nperm, uint64_t *nshared)
{
- bool backing = (role == &child_backing);
- assert(role == &child_backing || role == &child_file);
+ assert(role & BDRV_CHILD_COW);
- if (!backing) {
- int flags = bdrv_reopen_get_flags(reopen_queue, bs);
+ /*
+ * We want consistent read from backing files if the parent needs it.
+ * No other operations are performed on backing files.
+ */
+ perm &= BLK_PERM_CONSISTENT_READ;
- /* Apart from the modifications below, the same permissions are
- * forwarded and left alone as for filters */
- bdrv_filter_default_perms(bs, c, role, reopen_queue, perm, shared,
- &perm, &shared);
+ /*
+ * If the parent can deal with changing data, we're okay with a
+ * writable and resizable backing file.
+ * TODO Require !(perm & BLK_PERM_CONSISTENT_READ), too?
+ */
+ if (shared & BLK_PERM_WRITE) {
+ shared = BLK_PERM_WRITE | BLK_PERM_RESIZE;
+ } else {
+ shared = 0;
+ }
+ shared |= BLK_PERM_CONSISTENT_READ | BLK_PERM_GRAPH_MOD |
+ BLK_PERM_WRITE_UNCHANGED;
+
+ if (bs->open_flags & BDRV_O_INACTIVE) {
+ shared |= BLK_PERM_WRITE | BLK_PERM_RESIZE;
+ }
+
+ *nperm = perm;
+ *nshared = shared;
+}
+
+static void bdrv_default_perms_for_storage(BlockDriverState *bs, BdrvChild *c,
+ BdrvChildRole role,
+ BlockReopenQueue *reopen_queue,
+ uint64_t perm, uint64_t shared,
+ uint64_t *nperm, uint64_t *nshared)
+{
+ int flags;
+
+ assert(role & (BDRV_CHILD_METADATA | BDRV_CHILD_DATA));
+
+ flags = bdrv_reopen_get_flags(reopen_queue, bs);
+
+ /*
+ * Apart from the modifications below, the same permissions are
+ * forwarded and left alone as for filters
+ */
+ bdrv_filter_default_perms(bs, c, role, reopen_queue,
+ perm, shared, &perm, &shared);
+
+ if (role & BDRV_CHILD_METADATA) {
/* Format drivers may touch metadata even if the guest doesn't write */
if (bdrv_is_writable_after_reopen(bs, reopen_queue)) {
perm |= BLK_PERM_WRITE | BLK_PERM_RESIZE;
}
- /* bs->file always needs to be consistent because of the metadata. We
- * can never allow other users to resize or write to it. */
+ /*
+ * bs->file always needs to be consistent because of the
+ * metadata. We can never allow other users to resize or write
+ * to it.
+ */
if (!(flags & BDRV_O_NO_IO)) {
perm |= BLK_PERM_CONSISTENT_READ;
}
shared &= ~(BLK_PERM_WRITE | BLK_PERM_RESIZE);
- } else {
- /* We want consistent read from backing files if the parent needs it.
- * No other operations are performed on backing files. */
- perm &= BLK_PERM_CONSISTENT_READ;
+ }
- /* If the parent can deal with changing data, we're okay with a
- * writable and resizable backing file. */
- /* TODO Require !(perm & BLK_PERM_CONSISTENT_READ), too? */
- if (shared & BLK_PERM_WRITE) {
- shared = BLK_PERM_WRITE | BLK_PERM_RESIZE;
- } else {
- shared = 0;
+ if (role & BDRV_CHILD_DATA) {
+ /*
+ * Technically, everything in this block is a subset of the
+ * BDRV_CHILD_METADATA path taken above, and so this could
+ * be an "else if" branch. However, that is not obvious, and
+ * this function is not performance critical, therefore we let
+ * this be an independent "if".
+ */
+
+ /*
+ * We cannot allow other users to resize the file because the
+ * format driver might have some assumptions about the size
+ * (e.g. because it is stored in metadata, or because the file
+ * is split into fixed-size data files).
+ */
+ shared &= ~BLK_PERM_RESIZE;
+
+ /*
+ * WRITE_UNCHANGED often cannot be performed as such on the
+ * data file. For example, the qcow2 driver may still need to
+ * write copied clusters on copy-on-read.
+ */
+ if (perm & BLK_PERM_WRITE_UNCHANGED) {
+ perm |= BLK_PERM_WRITE;
}
- shared |= BLK_PERM_CONSISTENT_READ | BLK_PERM_GRAPH_MOD |
- BLK_PERM_WRITE_UNCHANGED;
+ /*
+ * If the data file is written to, the format driver may
+ * expect to be able to resize it by writing beyond the EOF.
+ */
+ if (perm & BLK_PERM_WRITE) {
+ perm |= BLK_PERM_RESIZE;
+ }
}
if (bs->open_flags & BDRV_O_INACTIVE) {
@@ -2418,6 +2478,28 @@
*nshared = shared;
}
+void bdrv_default_perms(BlockDriverState *bs, BdrvChild *c,
+ BdrvChildRole role, BlockReopenQueue *reopen_queue,
+ uint64_t perm, uint64_t shared,
+ uint64_t *nperm, uint64_t *nshared)
+{
+ if (role & BDRV_CHILD_FILTERED) {
+ assert(!(role & (BDRV_CHILD_DATA | BDRV_CHILD_METADATA |
+ BDRV_CHILD_COW)));
+ bdrv_filter_default_perms(bs, c, role, reopen_queue,
+ perm, shared, nperm, nshared);
+ } else if (role & BDRV_CHILD_COW) {
+ assert(!(role & (BDRV_CHILD_DATA | BDRV_CHILD_METADATA)));
+ bdrv_default_perms_for_cow(bs, c, role, reopen_queue,
+ perm, shared, nperm, nshared);
+ } else if (role & (BDRV_CHILD_METADATA | BDRV_CHILD_DATA)) {
+ bdrv_default_perms_for_storage(bs, c, role, reopen_queue,
+ perm, shared, nperm, nshared);
+ } else {
+ g_assert_not_reached();
+ }
+}
+
uint64_t bdrv_qapi_perm_to_blk_perm(BlockPermission qapi_perm)
{
static const uint64_t permissions[] = {
@@ -2456,7 +2538,7 @@
* If the new child node is drained but the old one was not, flush
* all outstanding requests to the old child node.
*/
- while (drain_saldo > 0 && child->role->drained_begin) {
+ while (drain_saldo > 0 && child->klass->drained_begin) {
bdrv_parent_drained_begin_single(child, true);
drain_saldo--;
}
@@ -2465,8 +2547,8 @@
/* Detach first so that the recursive drain sections coming from @child
* are already gone and we only end the drain sections that came from
* elsewhere. */
- if (child->role->detach) {
- child->role->detach(child);
+ if (child->klass->detach) {
+ child->klass->detach(child);
}
QLIST_REMOVE(child, next_parent);
}
@@ -2488,8 +2570,8 @@
/* Attach only after starting new drained sections, so that recursive
* drain sections coming from @child don't get an extra .drained_begin
* callback. */
- if (child->role->attach) {
- child->role->attach(child);
+ if (child->klass->attach) {
+ child->klass->attach(child);
}
}
@@ -2497,7 +2579,7 @@
* If the old child node was drained but the new one is not, allow
* requests to come in only after the new node has been attached.
*/
- while (drain_saldo < 0 && child->role->drained_end) {
+ while (drain_saldo < 0 && child->klass->drained_end) {
bdrv_parent_drained_end_single(child);
drain_saldo++;
}
@@ -2570,7 +2652,8 @@
*/
BdrvChild *bdrv_root_attach_child(BlockDriverState *child_bs,
const char *child_name,
- const BdrvChildRole *child_role,
+ const BdrvChildClass *child_class,
+ BdrvChildRole child_role,
AioContext *ctx,
uint64_t perm, uint64_t shared_perm,
void *opaque, Error **errp)
@@ -2591,6 +2674,7 @@
*child = (BdrvChild) {
.bs = NULL,
.name = g_strdup(child_name),
+ .klass = child_class,
.role = child_role,
.perm = perm,
.shared_perm = shared_perm,
@@ -2602,15 +2686,15 @@
* try moving the parent into the AioContext of child_bs instead. */
if (bdrv_get_aio_context(child_bs) != ctx) {
ret = bdrv_try_set_aio_context(child_bs, ctx, &local_err);
- if (ret < 0 && child_role->can_set_aio_ctx) {
+ if (ret < 0 && child_class->can_set_aio_ctx) {
GSList *ignore = g_slist_prepend(NULL, child);
ctx = bdrv_get_aio_context(child_bs);
- if (child_role->can_set_aio_ctx(child, ctx, &ignore, NULL)) {
+ if (child_class->can_set_aio_ctx(child, ctx, &ignore, NULL)) {
error_free(local_err);
ret = 0;
g_slist_free(ignore);
ignore = g_slist_prepend(NULL, child);
- child_role->set_aio_ctx(child, ctx, &ignore);
+ child_class->set_aio_ctx(child, ctx, &ignore);
}
g_slist_free(ignore);
}
@@ -2643,7 +2727,8 @@
BdrvChild *bdrv_attach_child(BlockDriverState *parent_bs,
BlockDriverState *child_bs,
const char *child_name,
- const BdrvChildRole *child_role,
+ const BdrvChildClass *child_class,
+ BdrvChildRole child_role,
Error **errp)
{
BdrvChild *child;
@@ -2655,8 +2740,8 @@
bdrv_child_perm(parent_bs, child_bs, NULL, child_role, NULL,
perm, shared_perm, &perm, &shared_perm);
- child = bdrv_root_attach_child(child_bs, child_name, child_role,
- bdrv_get_aio_context(parent_bs),
+ child = bdrv_root_attach_child(child_bs, child_name, child_class,
+ child_role, bdrv_get_aio_context(parent_bs),
perm, shared_perm, parent_bs, errp);
if (child == NULL) {
return NULL;
@@ -2728,8 +2813,8 @@
{
BdrvChild *c;
QLIST_FOREACH(c, &bs->parents, next_parent) {
- if (c->role->change_media) {
- c->role->change_media(c, load);
+ if (c->klass->change_media) {
+ c->klass->change_media(c, load);
}
}
}
@@ -2747,6 +2832,20 @@
}
/*
+ * Return the BdrvChildRole for @bs's backing child. bs->backing is
+ * mostly used for COW backing children (role = COW), but also for
+ * filtered children (role = FILTERED | PRIMARY).
+ */
+static BdrvChildRole bdrv_backing_role(BlockDriverState *bs)
+{
+ if (bs->drv && bs->drv->is_filter) {
+ return BDRV_CHILD_FILTERED | BDRV_CHILD_PRIMARY;
+ } else {
+ return BDRV_CHILD_COW;
+ }
+}
+
+/*
* Sets the backing file link of a BDS. A new reference is created; callers
* which don't need their own reference any more must call bdrv_unref().
*/
@@ -2773,8 +2872,8 @@
goto out;
}
- bs->backing = bdrv_attach_child(bs, backing_hd, "backing", &child_backing,
- errp);
+ bs->backing = bdrv_attach_child(bs, backing_hd, "backing", &child_of_bds,
+ bdrv_backing_role(bs), errp);
/* If backing_hd was already part of bs's backing chain, and
* inherits_from pointed recursively to bs then let's update it to
* point directly to bs (else it will become NULL). */
@@ -2871,7 +2970,7 @@
}
backing_hd = bdrv_open_inherit(backing_filename, reference, options, 0, bs,
- &child_backing, errp);
+ &child_of_bds, bdrv_backing_role(bs), errp);
if (!backing_hd) {
bs->open_flags |= BDRV_O_NO_BACKING;
error_prepend(errp, "Could not open backing file: ");
@@ -2905,15 +3004,15 @@
static BlockDriverState *
bdrv_open_child_bs(const char *filename, QDict *options, const char *bdref_key,
- BlockDriverState *parent, const BdrvChildRole *child_role,
- bool allow_none, Error **errp)
+ BlockDriverState *parent, const BdrvChildClass *child_class,
+ BdrvChildRole child_role, bool allow_none, Error **errp)
{
BlockDriverState *bs = NULL;
QDict *image_options;
char *bdref_key_dot;
const char *reference;
- assert(child_role != NULL);
+ assert(child_class != NULL);
bdref_key_dot = g_strdup_printf("%s.", bdref_key);
qdict_extract_subqdict(options, &image_options, bdref_key_dot);
@@ -2937,7 +3036,7 @@
}
bs = bdrv_open_inherit(filename, reference, image_options, 0,
- parent, child_role, errp);
+ parent, child_class, child_role, errp);
if (!bs) {
goto done;
}
@@ -2964,22 +3063,26 @@
BdrvChild *bdrv_open_child(const char *filename,
QDict *options, const char *bdref_key,
BlockDriverState *parent,
- const BdrvChildRole *child_role,
+ const BdrvChildClass *child_class,
+ BdrvChildRole child_role,
bool allow_none, Error **errp)
{
BlockDriverState *bs;
- bs = bdrv_open_child_bs(filename, options, bdref_key, parent, child_role,
- allow_none, errp);
+ bs = bdrv_open_child_bs(filename, options, bdref_key, parent, child_class,
+ child_role, allow_none, errp);
if (bs == NULL) {
return NULL;
}
- return bdrv_attach_child(parent, bs, bdref_key, child_role, errp);
+ return bdrv_attach_child(parent, bs, bdref_key, child_class, child_role,
+ errp);
}
-/* TODO Future callers may need to specify parent/child_role in order for
- * option inheritance to work. Existing callers use it for the root node. */
+/*
+ * TODO Future callers may need to specify parent/child_class in order for
+ * option inheritance to work. Existing callers use it for the root node.
+ */
BlockDriverState *bdrv_open_blockdev_ref(BlockdevRef *ref, Error **errp)
{
BlockDriverState *bs = NULL;
@@ -3011,7 +3114,7 @@
}
- bs = bdrv_open_inherit(NULL, reference, qdict, 0, NULL, NULL, errp);
+ bs = bdrv_open_inherit(NULL, reference, qdict, 0, NULL, NULL, 0, errp);
obj = NULL;
qobject_unref(obj);
visit_free(v);
@@ -3107,7 +3210,8 @@
const char *reference,
QDict *options, int flags,
BlockDriverState *parent,
- const BdrvChildRole *child_role,
+ const BdrvChildClass *child_class,
+ BdrvChildRole child_role,
Error **errp)
{
int ret;
@@ -3121,8 +3225,8 @@
QDict *snapshot_options = NULL;
int snapshot_flags = 0;
- assert(!child_role || !flags);
- assert(!child_role == !parent);
+ assert(!child_class || !flags);
+ assert(!child_class == !parent);
if (reference) {
bool options_non_empty = options ? qdict_size(options) : false;
@@ -3158,10 +3262,24 @@
bs->explicit_options = qdict_clone_shallow(options);
- if (child_role) {
+ if (child_class) {
+ bool parent_is_format;
+
+ if (parent->drv) {
+ parent_is_format = parent->drv->is_format;
+ } else {
+ /*
+ * parent->drv is not set yet because this node is opened for
+ * (potential) format probing. That means that @parent is going
+ * to be a format node.
+ */
+ parent_is_format = true;
+ }
+
bs->inherits_from = parent;
- child_role->inherit_options(&flags, options,
- parent->open_flags, parent->options);
+ child_class->inherit_options(child_role, parent_is_format,
+ &flags, options,
+ parent->open_flags, parent->options);
}
ret = bdrv_fill_options(&options, filename, &flags, &local_err);
@@ -3189,7 +3307,8 @@
flags, options);
/* Let bdrv_backing_options() override "read-only" */
qdict_del(options, BDRV_OPT_READ_ONLY);
- bdrv_backing_options(&flags, options, flags, options);
+ bdrv_inherited_options(BDRV_CHILD_COW, true,
+ &flags, options, flags, options);
}
bs->open_flags = flags;
@@ -3231,7 +3350,8 @@
BlockDriverState *file_bs;
file_bs = bdrv_open_child_bs(filename, options, "file", bs,
- &child_file, true, &local_err);
+ &child_of_bds, BDRV_CHILD_IMAGE,
+ true, &local_err);
if (local_err) {
goto fail;
}
@@ -3376,7 +3496,7 @@
QDict *options, int flags, Error **errp)
{
return bdrv_open_inherit(filename, reference, options, flags, NULL,
- NULL, errp);
+ NULL, 0, errp);
}
/* Return true if the NULL-terminated @list contains @str */
@@ -3472,7 +3592,9 @@
static BlockReopenQueue *bdrv_reopen_queue_child(BlockReopenQueue *bs_queue,
BlockDriverState *bs,
QDict *options,
- const BdrvChildRole *role,
+ const BdrvChildClass *klass,
+ BdrvChildRole role,
+ bool parent_is_format,
QDict *parent_options,
int parent_flags,
bool keep_old_opts)
@@ -3528,7 +3650,8 @@
/* Inherit from parent node */
if (parent_options) {
flags = 0;
- role->inherit_options(&flags, options, parent_flags, parent_options);
+ klass->inherit_options(role, parent_is_format, &flags, options,
+ parent_flags, parent_options);
} else {
flags = bdrv_get_flags(bs);
}
@@ -3619,7 +3742,8 @@
}
bdrv_reopen_queue_child(bs_queue, child->bs, new_child_options,
- child->role, options, flags, child_keep_old);
+ child->klass, child->role, bs->drv->is_format,
+ options, flags, child_keep_old);
}
return bs_queue;
@@ -3629,8 +3753,8 @@
BlockDriverState *bs,
QDict *options, bool keep_old_opts)
{
- return bdrv_reopen_queue_child(bs_queue, bs, options, NULL, NULL, 0,
- keep_old_opts);
+ return bdrv_reopen_queue_child(bs_queue, bs, options, NULL, 0, false,
+ NULL, 0, keep_old_opts);
}
/*
@@ -3676,8 +3800,8 @@
if (state->replace_backing_bs && state->new_backing_bs) {
uint64_t nperm, nshared;
bdrv_child_perm(state->bs, state->new_backing_bs,
- NULL, &child_backing, bs_queue,
- state->perm, state->shared_perm,
+ NULL, bdrv_backing_role(state->bs),
+ bs_queue, state->perm, state->shared_perm,
&nperm, &nshared);
ret = bdrv_check_update_perm(state->new_backing_bs, NULL,
nperm, nshared, NULL, NULL, errp);
@@ -4305,7 +4429,7 @@
GHashTable *found;
bool ret;
- if (c->role->stay_at_node) {
+ if (c->klass->stay_at_node) {
return false;
}
@@ -4776,9 +4900,9 @@
}
/* If so, update the backing file path in the image file */
- if (c->role->update_filename) {
- ret = c->role->update_filename(c, base, backing_file_str,
- &local_err);
+ if (c->klass->update_filename) {
+ ret = c->klass->update_filename(c, base, backing_file_str,
+ &local_err);
if (ret < 0) {
bdrv_abort_perm_update(base);
error_report_err(local_err);
@@ -5226,8 +5350,8 @@
/* If multiple parents have a name, just pick the first one. */
QLIST_FOREACH(c, &bs->parents, next_parent) {
- if (c->role->get_name) {
- name = c->role->get_name(c);
+ if (c->klass->get_name) {
+ name = c->klass->get_name(c);
if (name && *name) {
return name;
}
@@ -5586,8 +5710,8 @@
}
QLIST_FOREACH(parent, &bs->parents, next_parent) {
- if (parent->role->activate) {
- parent->role->activate(parent, &local_err);
+ if (parent->klass->activate) {
+ parent->klass->activate(parent, &local_err);
if (local_err) {
bs->open_flags |= BDRV_O_INACTIVE;
error_propagate(errp, local_err);
@@ -5655,7 +5779,7 @@
BdrvChild *parent;
QLIST_FOREACH(parent, &bs->parents, next_parent) {
- if (parent->role->parent_is_bds) {
+ if (parent->klass->parent_is_bds) {
BlockDriverState *parent_bs = parent->opaque;
if (!only_active || !(parent_bs->open_flags & BDRV_O_INACTIVE)) {
return true;
@@ -5694,8 +5818,8 @@
}
QLIST_FOREACH(parent, &bs->parents, next_parent) {
- if (parent->role->inactivate) {
- ret = parent->role->inactivate(parent);
+ if (parent->klass->inactivate) {
+ ret = parent->klass->inactivate(parent);
if (ret < 0) {
return ret;
}
@@ -6195,9 +6319,9 @@
if (g_slist_find(*ignore, child)) {
continue;
}
- assert(child->role->set_aio_ctx);
+ assert(child->klass->set_aio_ctx);
*ignore = g_slist_prepend(*ignore, child);
- child->role->set_aio_ctx(child, new_context, ignore);
+ child->klass->set_aio_ctx(child, new_context, ignore);
}
bdrv_detach_aio_context(bs);
@@ -6237,15 +6361,17 @@
}
*ignore = g_slist_prepend(*ignore, c);
- /* A BdrvChildRole that doesn't handle AioContext changes cannot
- * tolerate any AioContext changes */
- if (!c->role->can_set_aio_ctx) {
+ /*
+ * A BdrvChildClass that doesn't handle AioContext changes cannot
+ * tolerate any AioContext changes
+ */
+ if (!c->klass->can_set_aio_ctx) {
char *user = bdrv_child_user_desc(c);
error_setg(errp, "Changing iothreads is not supported by %s", user);
g_free(user);
return false;
}
- if (!c->role->can_set_aio_ctx(c, ctx, ignore, errp)) {
+ if (!c->klass->can_set_aio_ctx(c, ctx, ignore, errp)) {
assert(!errp || *errp);
return false;
}
@@ -6631,7 +6757,7 @@
drv->bdrv_gather_child_options(bs, opts, backing_overridden);
} else {
QLIST_FOREACH(child, &bs->children, next) {
- if (child->role == &child_backing && !backing_overridden) {
+ if (child == bs->backing && !backing_overridden) {
/* We can skip the backing BDS if it has not been overridden */
continue;
}
@@ -6764,3 +6890,26 @@
parent_bs->drv->bdrv_del_child(parent_bs, child, errp);
}
+
+int bdrv_make_empty(BdrvChild *c, Error **errp)
+{
+ BlockDriver *drv = c->bs->drv;
+ int ret;
+
+ assert(c->perm & (BLK_PERM_WRITE | BLK_PERM_WRITE_UNCHANGED));
+
+ if (!drv->bdrv_make_empty) {
+ error_setg(errp, "%s does not support emptying nodes",
+ drv->format_name);
+ return -ENOTSUP;
+ }
+
+ ret = drv->bdrv_make_empty(c->bs);
+ if (ret < 0) {
+ error_setg_errno(errp, -ret, "Failed to empty %s",
+ c->bs->filename);
+ return ret;
+ }
+
+ return 0;
+}
diff --git a/block/backup-top.c b/block/backup-top.c
index 79b268e..af2f20f 100644
--- a/block/backup-top.c
+++ b/block/backup-top.c
@@ -122,7 +122,7 @@
}
static void backup_top_child_perm(BlockDriverState *bs, BdrvChild *c,
- const BdrvChildRole *role,
+ BdrvChildRole role,
BlockReopenQueue *reopen_queue,
uint64_t perm, uint64_t shared,
uint64_t *nperm, uint64_t *nshared)
@@ -142,7 +142,7 @@
return;
}
- if (role == &child_file) {
+ if (!(role & BDRV_CHILD_FILTERED)) {
/*
* Target child
*
@@ -155,8 +155,8 @@
*nperm = BLK_PERM_WRITE;
} else {
/* Source child */
- bdrv_filter_default_perms(bs, c, role, reopen_queue, perm, shared,
- nperm, nshared);
+ bdrv_default_perms(bs, c, role, reopen_queue,
+ perm, shared, nperm, nshared);
if (perm & BLK_PERM_WRITE) {
*nperm = *nperm | BLK_PERM_CONSISTENT_READ;
@@ -214,7 +214,8 @@
source->supported_zero_flags);
bdrv_ref(target);
- state->target = bdrv_attach_child(top, target, "target", &child_file, errp);
+ state->target = bdrv_attach_child(top, target, "target", &child_of_bds,
+ BDRV_CHILD_DATA, errp);
if (!state->target) {
bdrv_unref(target);
bdrv_unref(top);
diff --git a/block/blkdebug.c b/block/blkdebug.c
index af44aa9..7194bc7 100644
--- a/block/blkdebug.c
+++ b/block/blkdebug.c
@@ -497,7 +497,9 @@
/* Open the image file */
bs->file = bdrv_open_child(qemu_opt_get(opts, "x-image"), options, "image",
- bs, &child_file, false, &local_err);
+ bs, &child_of_bds,
+ BDRV_CHILD_FILTERED | BDRV_CHILD_PRIMARY,
+ false, &local_err);
if (local_err) {
ret = -EINVAL;
error_propagate(errp, local_err);
@@ -993,15 +995,15 @@
}
static void blkdebug_child_perm(BlockDriverState *bs, BdrvChild *c,
- const BdrvChildRole *role,
+ BdrvChildRole role,
BlockReopenQueue *reopen_queue,
uint64_t perm, uint64_t shared,
uint64_t *nperm, uint64_t *nshared)
{
BDRVBlkdebugState *s = bs->opaque;
- bdrv_filter_default_perms(bs, c, role, reopen_queue, perm, shared,
- nperm, nshared);
+ bdrv_default_perms(bs, c, role, reopen_queue,
+ perm, shared, nperm, nshared);
*nperm |= s->take_child_perms;
*nshared &= ~s->unshare_child_perms;
diff --git a/block/blklogwrites.c b/block/blklogwrites.c
index 04d8b33..6753bd9 100644
--- a/block/blklogwrites.c
+++ b/block/blklogwrites.c
@@ -157,7 +157,8 @@
}
/* Open the file */
- bs->file = bdrv_open_child(NULL, options, "file", bs, &child_file, false,
+ bs->file = bdrv_open_child(NULL, options, "file", bs, &child_of_bds,
+ BDRV_CHILD_FILTERED | BDRV_CHILD_PRIMARY, false,
&local_err);
if (local_err) {
ret = -EINVAL;
@@ -166,8 +167,8 @@
}
/* Open the log file */
- s->log_file = bdrv_open_child(NULL, options, "log", bs, &child_file, false,
- &local_err);
+ s->log_file = bdrv_open_child(NULL, options, "log", bs, &child_of_bds,
+ BDRV_CHILD_METADATA, false, &local_err);
if (local_err) {
ret = -EINVAL;
error_propagate(errp, local_err);
@@ -282,7 +283,7 @@
}
static void blk_log_writes_child_perm(BlockDriverState *bs, BdrvChild *c,
- const BdrvChildRole *role,
+ BdrvChildRole role,
BlockReopenQueue *ro_q,
uint64_t perm, uint64_t shrd,
uint64_t *nperm, uint64_t *nshrd)
@@ -293,11 +294,8 @@
return;
}
- if (!strcmp(c->name, "log")) {
- bdrv_format_default_perms(bs, c, role, ro_q, perm, shrd, nperm, nshrd);
- } else {
- bdrv_filter_default_perms(bs, c, role, ro_q, perm, shrd, nperm, nshrd);
- }
+ bdrv_default_perms(bs, c, role, ro_q, perm, shrd,
+ nperm, nshrd);
}
static void blk_log_writes_refresh_limits(BlockDriverState *bs, Error **errp)
diff --git a/block/blkreplay.c b/block/blkreplay.c
index c96ac8f..30a0f5d 100644
--- a/block/blkreplay.c
+++ b/block/blkreplay.c
@@ -27,8 +27,9 @@
int ret;
/* Open the image file */
- bs->file = bdrv_open_child(NULL, options, "image",
- bs, &child_file, false, &local_err);
+ bs->file = bdrv_open_child(NULL, options, "image", bs, &child_of_bds,
+ BDRV_CHILD_FILTERED | BDRV_CHILD_PRIMARY,
+ false, &local_err);
if (local_err) {
ret = -EINVAL;
error_propagate(errp, local_err);
@@ -135,9 +136,10 @@
static BlockDriver bdrv_blkreplay = {
.format_name = "blkreplay",
.instance_size = 0,
+ .is_filter = true,
.bdrv_open = blkreplay_open,
- .bdrv_child_perm = bdrv_filter_default_perms,
+ .bdrv_child_perm = bdrv_default_perms,
.bdrv_getlength = blkreplay_getlength,
.bdrv_co_preadv = blkreplay_co_preadv,
diff --git a/block/blkverify.c b/block/blkverify.c
index ba6b185..2f261de 100644
--- a/block/blkverify.c
+++ b/block/blkverify.c
@@ -125,7 +125,9 @@
/* Open the raw file */
bs->file = bdrv_open_child(qemu_opt_get(opts, "x-raw"), options, "raw",
- bs, &child_file, false, &local_err);
+ bs, &child_of_bds,
+ BDRV_CHILD_FILTERED | BDRV_CHILD_PRIMARY,
+ false, &local_err);
if (local_err) {
ret = -EINVAL;
error_propagate(errp, local_err);
@@ -134,8 +136,8 @@
/* Open the test file */
s->test_file = bdrv_open_child(qemu_opt_get(opts, "x-image"), options,
- "test", bs, &child_format, false,
- &local_err);
+ "test", bs, &child_of_bds, BDRV_CHILD_DATA,
+ false, &local_err);
if (local_err) {
ret = -EINVAL;
error_propagate(errp, local_err);
@@ -317,7 +319,7 @@
.bdrv_parse_filename = blkverify_parse_filename,
.bdrv_file_open = blkverify_open,
.bdrv_close = blkverify_close,
- .bdrv_child_perm = bdrv_filter_default_perms,
+ .bdrv_child_perm = bdrv_default_perms,
.bdrv_getlength = blkverify_getlength,
.bdrv_refresh_filename = blkverify_refresh_filename,
.bdrv_dirname = blkverify_dirname,
diff --git a/block/block-backend.c b/block/block-backend.c
index f494486..6936b25 100644
--- a/block/block-backend.c
+++ b/block/block-backend.c
@@ -120,7 +120,8 @@
static QTAILQ_HEAD(, BlockBackend) monitor_block_backends =
QTAILQ_HEAD_INITIALIZER(monitor_block_backends);
-static void blk_root_inherit_options(int *child_flags, QDict *child_options,
+static void blk_root_inherit_options(BdrvChildRole role, bool parent_is_format,
+ int *child_flags, QDict *child_options,
int parent_flags, QDict *parent_options)
{
/* We're not supposed to call this function for root nodes */
@@ -297,7 +298,7 @@
}
}
-static const BdrvChildRole child_root = {
+static const BdrvChildClass child_root = {
.inherit_options = blk_root_inherit_options,
.change_media = blk_root_change_media,
@@ -423,8 +424,9 @@
return NULL;
}
- blk->root = bdrv_root_attach_child(bs, "root", &child_root, blk->ctx,
- perm, BLK_PERM_ALL, blk, errp);
+ blk->root = bdrv_root_attach_child(bs, "root", &child_root,
+ BDRV_CHILD_FILTERED | BDRV_CHILD_PRIMARY,
+ blk->ctx, perm, BLK_PERM_ALL, blk, errp);
if (!blk->root) {
blk_unref(blk);
return NULL;
@@ -716,7 +718,7 @@
{
BdrvChild *child;
QLIST_FOREACH(child, &bs->parents, next_parent) {
- if (child->role == &child_root) {
+ if (child->klass == &child_root) {
return child->opaque;
}
}
@@ -740,7 +742,7 @@
BdrvChild *c;
QLIST_FOREACH(c, &bs->parents, next_parent) {
- if (c->role != &child_root) {
+ if (c->klass != &child_root) {
return false;
}
}
@@ -834,8 +836,10 @@
{
ThrottleGroupMember *tgm = &blk->public.throttle_group_member;
bdrv_ref(bs);
- blk->root = bdrv_root_attach_child(bs, "root", &child_root, blk->ctx,
- blk->perm, blk->shared_perm, blk, errp);
+ blk->root = bdrv_root_attach_child(bs, "root", &child_root,
+ BDRV_CHILD_FILTERED | BDRV_CHILD_PRIMARY,
+ blk->ctx, blk->perm, blk->shared_perm,
+ blk, errp);
if (blk->root == NULL) {
return -EPERM;
}
@@ -2402,3 +2406,13 @@
{
return blk->root;
}
+
+int blk_make_empty(BlockBackend *blk, Error **errp)
+{
+ if (!blk_is_available(blk)) {
+ error_setg(errp, "No medium inserted");
+ return -ENOMEDIUM;
+ }
+
+ return bdrv_make_empty(blk->root, errp);
+}
diff --git a/block/block-copy.c b/block/block-copy.c
index 0350068..bb8d056 100644
--- a/block/block-copy.c
+++ b/block/block-copy.c
@@ -343,9 +343,7 @@
~BDRV_REQ_WRITE_COMPRESSED);
if (ret < 0) {
trace_block_copy_write_zeroes_fail(s, offset, ret);
- if (error_is_read) {
- *error_is_read = false;
- }
+ *error_is_read = false;
}
return ret;
}
@@ -393,9 +391,7 @@
ret = bdrv_co_pread(s->source, offset, nbytes, bounce_buffer, 0);
if (ret < 0) {
trace_block_copy_read_fail(s, offset, ret);
- if (error_is_read) {
- *error_is_read = true;
- }
+ *error_is_read = true;
goto out;
}
@@ -403,9 +399,7 @@
s->write_flags);
if (ret < 0) {
trace_block_copy_write_fail(s, offset, ret);
- if (error_is_read) {
- *error_is_read = false;
- }
+ *error_is_read = false;
goto out;
}
@@ -418,7 +412,7 @@
static coroutine_fn int block_copy_task_entry(AioTask *task)
{
BlockCopyTask *t = container_of(task, BlockCopyTask, task);
- bool error_is_read;
+ bool error_is_read = false;
int ret;
ret = block_copy_do_copy(t->s, t->offset, t->bytes, t->zeroes,
@@ -591,13 +585,13 @@
}
if (s->skip_unallocated && !(ret & BDRV_BLOCK_ALLOCATED)) {
block_copy_task_end(task, 0);
- g_free(task);
progress_set_remaining(s->progress,
bdrv_get_dirty_count(s->copy_bitmap) +
s->in_flight_bytes);
trace_block_copy_skip_range(s, task->offset, task->bytes);
offset = task_end(task);
bytes = end - offset;
+ g_free(task);
continue;
}
task->zeroes = ret & BDRV_BLOCK_ZERO;
diff --git a/block/bochs.c b/block/bochs.c
index 32bb83b..2f010ab 100644
--- a/block/bochs.c
+++ b/block/bochs.c
@@ -110,8 +110,8 @@
return ret;
}
- bs->file = bdrv_open_child(NULL, options, "file", bs, &child_file,
- false, errp);
+ bs->file = bdrv_open_child(NULL, options, "file", bs, &child_of_bds,
+ BDRV_CHILD_IMAGE, false, errp);
if (!bs->file) {
return -EINVAL;
}
@@ -297,10 +297,11 @@
.instance_size = sizeof(BDRVBochsState),
.bdrv_probe = bochs_probe,
.bdrv_open = bochs_open,
- .bdrv_child_perm = bdrv_format_default_perms,
+ .bdrv_child_perm = bdrv_default_perms,
.bdrv_refresh_limits = bochs_refresh_limits,
.bdrv_co_preadv = bochs_co_preadv,
.bdrv_close = bochs_close,
+ .is_format = true,
};
static void bdrv_bochs_init(void)
diff --git a/block/cloop.c b/block/cloop.c
index 4de9487..c99192a 100644
--- a/block/cloop.c
+++ b/block/cloop.c
@@ -71,8 +71,8 @@
return ret;
}
- bs->file = bdrv_open_child(NULL, options, "file", bs, &child_file,
- false, errp);
+ bs->file = bdrv_open_child(NULL, options, "file", bs, &child_of_bds,
+ BDRV_CHILD_IMAGE, false, errp);
if (!bs->file) {
return -EINVAL;
}
@@ -293,10 +293,11 @@
.instance_size = sizeof(BDRVCloopState),
.bdrv_probe = cloop_probe,
.bdrv_open = cloop_open,
- .bdrv_child_perm = bdrv_format_default_perms,
+ .bdrv_child_perm = bdrv_default_perms,
.bdrv_refresh_limits = cloop_refresh_limits,
.bdrv_co_preadv = cloop_co_preadv,
.bdrv_close = cloop_close,
+ .is_format = true,
};
static void bdrv_cloop_init(void)
diff --git a/block/commit.c b/block/commit.c
index 87f6096..7732d02 100644
--- a/block/commit.c
+++ b/block/commit.c
@@ -223,7 +223,7 @@
}
static void bdrv_commit_top_child_perm(BlockDriverState *bs, BdrvChild *c,
- const BdrvChildRole *role,
+ BdrvChildRole role,
BlockReopenQueue *reopen_queue,
uint64_t perm, uint64_t shared,
uint64_t *nperm, uint64_t *nshared)
@@ -240,6 +240,8 @@
.bdrv_co_block_status = bdrv_co_block_status_from_backing,
.bdrv_refresh_filename = bdrv_commit_top_refresh_filename,
.bdrv_child_perm = bdrv_commit_top_child_perm,
+
+ .is_filter = true,
};
void commit_start(const char *job_id, BlockDriverState *bs,
@@ -414,7 +416,9 @@
}
ctx = bdrv_get_aio_context(bs);
- src = blk_new(ctx, BLK_PERM_CONSISTENT_READ, BLK_PERM_ALL);
+ /* WRITE_UNCHANGED is required for bdrv_make_empty() */
+ src = blk_new(ctx, BLK_PERM_CONSISTENT_READ | BLK_PERM_WRITE_UNCHANGED,
+ BLK_PERM_ALL);
backing = blk_new(ctx, BLK_PERM_WRITE | BLK_PERM_RESIZE, BLK_PERM_ALL);
ret = blk_insert_bs(src, bs, &local_err);
@@ -492,14 +496,14 @@
}
}
- if (drv->bdrv_make_empty) {
- ret = drv->bdrv_make_empty(bs);
- if (ret < 0) {
- goto ro_cleanup;
- }
- blk_flush(src);
+ ret = blk_make_empty(src, NULL);
+ /* Ignore -ENOTSUP */
+ if (ret < 0 && ret != -ENOTSUP) {
+ goto ro_cleanup;
}
+ blk_flush(src);
+
/*
* Make sure all data we wrote to the backing device is actually
* stable on disk.
diff --git a/block/copy-on-read.c b/block/copy-on-read.c
index 242d3ff..a6e3c74 100644
--- a/block/copy-on-read.c
+++ b/block/copy-on-read.c
@@ -28,8 +28,9 @@
static int cor_open(BlockDriverState *bs, QDict *options, int flags,
Error **errp)
{
- bs->file = bdrv_open_child(NULL, options, "file", bs, &child_file, false,
- errp);
+ bs->file = bdrv_open_child(NULL, options, "file", bs, &child_of_bds,
+ BDRV_CHILD_FILTERED | BDRV_CHILD_PRIMARY,
+ false, errp);
if (!bs->file) {
return -EINVAL;
}
@@ -51,7 +52,7 @@
#define PERM_UNCHANGED (BLK_PERM_ALL & ~PERM_PASSTHROUGH)
static void cor_child_perm(BlockDriverState *bs, BdrvChild *c,
- const BdrvChildRole *role,
+ BdrvChildRole role,
BlockReopenQueue *reopen_queue,
uint64_t perm, uint64_t shared,
uint64_t *nperm, uint64_t *nshared)
diff --git a/block/crypto.c b/block/crypto.c
index 6b21d6b..973b57b 100644
--- a/block/crypto.c
+++ b/block/crypto.c
@@ -218,8 +218,8 @@
unsigned int cflags = 0;
QDict *cryptoopts = NULL;
- bs->file = bdrv_open_child(NULL, options, "file", bs, &child_file,
- false, errp);
+ bs->file = bdrv_open_child(NULL, options, "file", bs, &child_of_bds,
+ BDRV_CHILD_IMAGE, false, errp);
if (!bs->file) {
return -EINVAL;
}
@@ -552,7 +552,7 @@
* Unallocated blocks are still encrypted so allocation status makes no
* difference to the file size.
*/
- info = g_new(BlockMeasureInfo, 1);
+ info = g_new0(BlockMeasureInfo, 1);
info->fully_allocated = luks_payload_size + size;
info->required = luks_payload_size + size;
return info;
@@ -756,7 +756,7 @@
.bdrv_close = block_crypto_close,
/* This driver doesn't modify LUKS metadata except when creating image.
* Allow share-rw=on as a special case. */
- .bdrv_child_perm = bdrv_filter_default_perms,
+ .bdrv_child_perm = bdrv_default_perms,
.bdrv_co_create = block_crypto_co_create_luks,
.bdrv_co_create_opts = block_crypto_co_create_opts_luks,
.bdrv_co_truncate = block_crypto_co_truncate,
@@ -771,6 +771,8 @@
.bdrv_get_info = block_crypto_get_info_luks,
.bdrv_get_specific_info = block_crypto_get_specific_info_luks,
+ .is_format = true,
+
.strong_runtime_opts = block_crypto_strong_runtime_opts,
};
diff --git a/block/dirty-bitmap.c b/block/dirty-bitmap.c
index 063793e..c01319b 100644
--- a/block/dirty-bitmap.c
+++ b/block/dirty-bitmap.c
@@ -478,6 +478,15 @@
}
}
+bool
+bdrv_supports_persistent_dirty_bitmap(BlockDriverState *bs)
+{
+ if (bs->drv && bs->drv->bdrv_supports_persistent_dirty_bitmap) {
+ return bs->drv->bdrv_supports_persistent_dirty_bitmap(bs);
+ }
+ return false;
+}
+
static bool coroutine_fn
bdrv_co_can_store_new_dirty_bitmap(BlockDriverState *bs, const char *name,
uint32_t granularity, Error **errp)
@@ -809,6 +818,19 @@
return false;
}
+bool bdrv_has_named_bitmaps(BlockDriverState *bs)
+{
+ BdrvDirtyBitmap *bm;
+
+ QLIST_FOREACH(bm, &bs->dirty_bitmaps, list) {
+ if (bdrv_dirty_bitmap_name(bm)) {
+ return true;
+ }
+ }
+
+ return false;
+}
+
/* Called with BQL taken. */
void bdrv_dirty_bitmap_set_persistence(BdrvDirtyBitmap *bitmap, bool persistent)
{
diff --git a/block/dmg.c b/block/dmg.c
index 4a045f2..0d6c317 100644
--- a/block/dmg.c
+++ b/block/dmg.c
@@ -439,8 +439,8 @@
return ret;
}
- bs->file = bdrv_open_child(NULL, options, "file", bs, &child_file,
- false, errp);
+ bs->file = bdrv_open_child(NULL, options, "file", bs, &child_of_bds,
+ BDRV_CHILD_IMAGE, false, errp);
if (!bs->file) {
return -EINVAL;
}
@@ -750,9 +750,10 @@
.bdrv_probe = dmg_probe,
.bdrv_open = dmg_open,
.bdrv_refresh_limits = dmg_refresh_limits,
- .bdrv_child_perm = bdrv_format_default_perms,
+ .bdrv_child_perm = bdrv_default_perms,
.bdrv_co_preadv = dmg_co_preadv,
.bdrv_close = dmg_close,
+ .is_format = true,
};
static void bdrv_dmg_init(void)
diff --git a/block/filter-compress.c b/block/filter-compress.c
index 82c315b..8ec1991 100644
--- a/block/filter-compress.c
+++ b/block/filter-compress.c
@@ -30,8 +30,9 @@
static int compress_open(BlockDriverState *bs, QDict *options, int flags,
Error **errp)
{
- bs->file = bdrv_open_child(NULL, options, "file", bs, &child_file, false,
- errp);
+ bs->file = bdrv_open_child(NULL, options, "file", bs, &child_of_bds,
+ BDRV_CHILD_FILTERED | BDRV_CHILD_PRIMARY,
+ false, errp);
if (!bs->file) {
return -EINVAL;
}
@@ -132,7 +133,7 @@
.format_name = "compress",
.bdrv_open = compress_open,
- .bdrv_child_perm = bdrv_filter_default_perms,
+ .bdrv_child_perm = bdrv_default_perms,
.bdrv_getlength = compress_getlength,
diff --git a/block/io.c b/block/io.c
index 7d30e61..121ce17 100644
--- a/block/io.c
+++ b/block/io.c
@@ -50,7 +50,7 @@
BdrvChild *c, *next;
QLIST_FOREACH_SAFE(c, &bs->parents, next_parent, next) {
- if (c == ignore || (ignore_bds_parents && c->role->parent_is_bds)) {
+ if (c == ignore || (ignore_bds_parents && c->klass->parent_is_bds)) {
continue;
}
bdrv_parent_drained_begin_single(c, false);
@@ -62,8 +62,8 @@
{
assert(c->parent_quiesce_counter > 0);
c->parent_quiesce_counter--;
- if (c->role->drained_end) {
- c->role->drained_end(c, drained_end_counter);
+ if (c->klass->drained_end) {
+ c->klass->drained_end(c, drained_end_counter);
}
}
@@ -81,7 +81,7 @@
BdrvChild *c;
QLIST_FOREACH(c, &bs->parents, next_parent) {
- if (c == ignore || (ignore_bds_parents && c->role->parent_is_bds)) {
+ if (c == ignore || (ignore_bds_parents && c->klass->parent_is_bds)) {
continue;
}
bdrv_parent_drained_end_single_no_poll(c, drained_end_counter);
@@ -90,8 +90,8 @@
static bool bdrv_parent_drained_poll_single(BdrvChild *c)
{
- if (c->role->drained_poll) {
- return c->role->drained_poll(c);
+ if (c->klass->drained_poll) {
+ return c->klass->drained_poll(c);
}
return false;
}
@@ -103,7 +103,7 @@
bool busy = false;
QLIST_FOREACH_SAFE(c, &bs->parents, next_parent, next) {
- if (c == ignore || (ignore_bds_parents && c->role->parent_is_bds)) {
+ if (c == ignore || (ignore_bds_parents && c->klass->parent_is_bds)) {
continue;
}
busy |= bdrv_parent_drained_poll_single(c);
@@ -115,8 +115,8 @@
void bdrv_parent_drained_begin_single(BdrvChild *c, bool poll)
{
c->parent_quiesce_counter++;
- if (c->role->drained_begin) {
- c->role->drained_begin(c);
+ if (c->klass->drained_begin) {
+ c->klass->drained_begin(c);
}
if (poll) {
BDRV_POLL_WHILE(c->bs, bdrv_parent_drained_poll_single(c));
@@ -3326,8 +3326,8 @@
{
BdrvChild *c;
QLIST_FOREACH(c, &bs->parents, next_parent) {
- if (c->role->resize) {
- c->role->resize(c);
+ if (c->klass->resize) {
+ c->klass->resize(c);
}
}
}
diff --git a/block/mirror.c b/block/mirror.c
index aca95c9..e8e8844 100644
--- a/block/mirror.c
+++ b/block/mirror.c
@@ -872,6 +872,7 @@
BlockDriverState *target_bs = blk_bs(s->target);
bool need_drain = true;
int64_t length;
+ int64_t target_length;
BlockDriverInfo bdi;
char backing_filename[2]; /* we only need 2 characters because we are only
checking for a NULL string */
@@ -887,24 +888,26 @@
goto immediate_exit;
}
+ target_length = blk_getlength(s->target);
+ if (target_length < 0) {
+ ret = target_length;
+ goto immediate_exit;
+ }
+
/* Active commit must resize the base image if its size differs from the
* active layer. */
if (s->base == blk_bs(s->target)) {
- int64_t base_length;
-
- base_length = blk_getlength(s->target);
- if (base_length < 0) {
- ret = base_length;
- goto immediate_exit;
- }
-
- if (s->bdev_length > base_length) {
+ if (s->bdev_length > target_length) {
ret = blk_truncate(s->target, s->bdev_length, false,
PREALLOC_MODE_OFF, 0, NULL);
if (ret < 0) {
goto immediate_exit;
}
}
+ } else if (s->bdev_length != target_length) {
+ error_setg(errp, "Source and target image have different sizes");
+ ret = -EINVAL;
+ goto immediate_exit;
}
if (s->bdev_length == 0) {
@@ -1489,7 +1492,7 @@
}
static void bdrv_mirror_top_child_perm(BlockDriverState *bs, BdrvChild *c,
- const BdrvChildRole *role,
+ BdrvChildRole role,
BlockReopenQueue *reopen_queue,
uint64_t perm, uint64_t shared,
uint64_t *nperm, uint64_t *nshared)
@@ -1527,6 +1530,8 @@
.bdrv_co_block_status = bdrv_co_block_status_from_backing,
.bdrv_refresh_filename = bdrv_mirror_top_refresh_filename,
.bdrv_child_perm = bdrv_mirror_top_child_perm,
+
+ .is_filter = true,
};
static BlockJob *mirror_start_job(
diff --git a/block/monitor/Makefile.objs b/block/monitor/Makefile.objs
index 0a74f9a..39acf85 100644
--- a/block/monitor/Makefile.objs
+++ b/block/monitor/Makefile.objs
@@ -1 +1,2 @@
common-obj-y += block-hmp-cmds.o
+block-obj-y += bitmap-qmp-cmds.o
diff --git a/block/monitor/bitmap-qmp-cmds.c b/block/monitor/bitmap-qmp-cmds.c
new file mode 100644
index 0000000..9f11dee
--- /dev/null
+++ b/block/monitor/bitmap-qmp-cmds.c
@@ -0,0 +1,321 @@
+/*
+ * QEMU block dirty bitmap QMP commands
+ *
+ * Copyright (c) 2003-2008 Fabrice Bellard
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or
+ * later. See the COPYING file in the top-level directory.
+ *
+ * This file incorporates work covered by the following copyright and
+ * permission notice:
+ *
+ * Copyright (c) 2003-2008 Fabrice Bellard
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include "qemu/osdep.h"
+
+#include "block/block_int.h"
+#include "qapi/qapi-commands-block.h"
+#include "qapi/error.h"
+
+/**
+ * block_dirty_bitmap_lookup:
+ * Return a dirty bitmap (if present), after validating
+ * the node reference and bitmap names.
+ *
+ * @node: The name of the BDS node to search for bitmaps
+ * @name: The name of the bitmap to search for
+ * @pbs: Output pointer for BDS lookup, if desired. Can be NULL.
+ * @errp: Output pointer for error information. Can be NULL.
+ *
+ * @return: A bitmap object on success, or NULL on failure.
+ */
+BdrvDirtyBitmap *block_dirty_bitmap_lookup(const char *node,
+ const char *name,
+ BlockDriverState **pbs,
+ Error **errp)
+{
+ BlockDriverState *bs;
+ BdrvDirtyBitmap *bitmap;
+
+ if (!node) {
+ error_setg(errp, "Node cannot be NULL");
+ return NULL;
+ }
+ if (!name) {
+ error_setg(errp, "Bitmap name cannot be NULL");
+ return NULL;
+ }
+ bs = bdrv_lookup_bs(node, node, NULL);
+ if (!bs) {
+ error_setg(errp, "Node '%s' not found", node);
+ return NULL;
+ }
+
+ bitmap = bdrv_find_dirty_bitmap(bs, name);
+ if (!bitmap) {
+ error_setg(errp, "Dirty bitmap '%s' not found", name);
+ return NULL;
+ }
+
+ if (pbs) {
+ *pbs = bs;
+ }
+
+ return bitmap;
+}
+
+void qmp_block_dirty_bitmap_add(const char *node, const char *name,
+ bool has_granularity, uint32_t granularity,
+ bool has_persistent, bool persistent,
+ bool has_disabled, bool disabled,
+ Error **errp)
+{
+ BlockDriverState *bs;
+ BdrvDirtyBitmap *bitmap;
+ AioContext *aio_context;
+
+ if (!name || name[0] == '\0') {
+ error_setg(errp, "Bitmap name cannot be empty");
+ return;
+ }
+
+ bs = bdrv_lookup_bs(node, node, errp);
+ if (!bs) {
+ return;
+ }
+
+ aio_context = bdrv_get_aio_context(bs);
+ aio_context_acquire(aio_context);
+
+ if (has_granularity) {
+ if (granularity < 512 || !is_power_of_2(granularity)) {
+ error_setg(errp, "Granularity must be power of 2 "
+ "and at least 512");
+ goto out;
+ }
+ } else {
+ /* Default to cluster size, if available: */
+ granularity = bdrv_get_default_bitmap_granularity(bs);
+ }
+
+ if (!has_persistent) {
+ persistent = false;
+ }
+
+ if (!has_disabled) {
+ disabled = false;
+ }
+
+ if (persistent &&
+ !bdrv_can_store_new_dirty_bitmap(bs, name, granularity, errp))
+ {
+ goto out;
+ }
+
+ bitmap = bdrv_create_dirty_bitmap(bs, granularity, name, errp);
+ if (bitmap == NULL) {
+ goto out;
+ }
+
+ if (disabled) {
+ bdrv_disable_dirty_bitmap(bitmap);
+ }
+
+ bdrv_dirty_bitmap_set_persistence(bitmap, persistent);
+
+out:
+ aio_context_release(aio_context);
+}
+
+BdrvDirtyBitmap *block_dirty_bitmap_remove(const char *node, const char *name,
+ bool release,
+ BlockDriverState **bitmap_bs,
+ Error **errp)
+{
+ BlockDriverState *bs;
+ BdrvDirtyBitmap *bitmap;
+ AioContext *aio_context;
+
+ bitmap = block_dirty_bitmap_lookup(node, name, &bs, errp);
+ if (!bitmap || !bs) {
+ return NULL;
+ }
+
+ aio_context = bdrv_get_aio_context(bs);
+ aio_context_acquire(aio_context);
+
+ if (bdrv_dirty_bitmap_check(bitmap, BDRV_BITMAP_BUSY | BDRV_BITMAP_RO,
+ errp)) {
+ aio_context_release(aio_context);
+ return NULL;
+ }
+
+ if (bdrv_dirty_bitmap_get_persistence(bitmap) &&
+ bdrv_remove_persistent_dirty_bitmap(bs, name, errp) < 0)
+ {
+ aio_context_release(aio_context);
+ return NULL;
+ }
+
+ if (release) {
+ bdrv_release_dirty_bitmap(bitmap);
+ }
+
+ if (bitmap_bs) {
+ *bitmap_bs = bs;
+ }
+
+ aio_context_release(aio_context);
+ return release ? NULL : bitmap;
+}
+
+void qmp_block_dirty_bitmap_remove(const char *node, const char *name,
+ Error **errp)
+{
+ block_dirty_bitmap_remove(node, name, true, NULL, errp);
+}
+
+/**
+ * Completely clear a bitmap, for the purposes of synchronizing a bitmap
+ * immediately after a full backup operation.
+ */
+void qmp_block_dirty_bitmap_clear(const char *node, const char *name,
+ Error **errp)
+{
+ BdrvDirtyBitmap *bitmap;
+ BlockDriverState *bs;
+
+ bitmap = block_dirty_bitmap_lookup(node, name, &bs, errp);
+ if (!bitmap || !bs) {
+ return;
+ }
+
+ if (bdrv_dirty_bitmap_check(bitmap, BDRV_BITMAP_DEFAULT, errp)) {
+ return;
+ }
+
+ bdrv_clear_dirty_bitmap(bitmap, NULL);
+}
+
+void qmp_block_dirty_bitmap_enable(const char *node, const char *name,
+ Error **errp)
+{
+ BlockDriverState *bs;
+ BdrvDirtyBitmap *bitmap;
+
+ bitmap = block_dirty_bitmap_lookup(node, name, &bs, errp);
+ if (!bitmap) {
+ return;
+ }
+
+ if (bdrv_dirty_bitmap_check(bitmap, BDRV_BITMAP_ALLOW_RO, errp)) {
+ return;
+ }
+
+ bdrv_enable_dirty_bitmap(bitmap);
+}
+
+void qmp_block_dirty_bitmap_disable(const char *node, const char *name,
+ Error **errp)
+{
+ BlockDriverState *bs;
+ BdrvDirtyBitmap *bitmap;
+
+ bitmap = block_dirty_bitmap_lookup(node, name, &bs, errp);
+ if (!bitmap) {
+ return;
+ }
+
+ if (bdrv_dirty_bitmap_check(bitmap, BDRV_BITMAP_ALLOW_RO, errp)) {
+ return;
+ }
+
+ bdrv_disable_dirty_bitmap(bitmap);
+}
+
+BdrvDirtyBitmap *block_dirty_bitmap_merge(const char *node, const char *target,
+ BlockDirtyBitmapMergeSourceList *bms,
+ HBitmap **backup, Error **errp)
+{
+ BlockDriverState *bs;
+ BdrvDirtyBitmap *dst, *src, *anon;
+ BlockDirtyBitmapMergeSourceList *lst;
+ Error *local_err = NULL;
+
+ dst = block_dirty_bitmap_lookup(node, target, &bs, errp);
+ if (!dst) {
+ return NULL;
+ }
+
+ anon = bdrv_create_dirty_bitmap(bs, bdrv_dirty_bitmap_granularity(dst),
+ NULL, errp);
+ if (!anon) {
+ return NULL;
+ }
+
+ for (lst = bms; lst; lst = lst->next) {
+ switch (lst->value->type) {
+ const char *name, *node;
+ case QTYPE_QSTRING:
+ name = lst->value->u.local;
+ src = bdrv_find_dirty_bitmap(bs, name);
+ if (!src) {
+ error_setg(errp, "Dirty bitmap '%s' not found", name);
+ dst = NULL;
+ goto out;
+ }
+ break;
+ case QTYPE_QDICT:
+ node = lst->value->u.external.node;
+ name = lst->value->u.external.name;
+ src = block_dirty_bitmap_lookup(node, name, NULL, errp);
+ if (!src) {
+ dst = NULL;
+ goto out;
+ }
+ break;
+ default:
+ abort();
+ }
+
+ bdrv_merge_dirty_bitmap(anon, src, NULL, &local_err);
+ if (local_err) {
+ error_propagate(errp, local_err);
+ dst = NULL;
+ goto out;
+ }
+ }
+
+ /* Merge into dst; dst is unchanged on failure. */
+ bdrv_merge_dirty_bitmap(dst, anon, backup, errp);
+
+ out:
+ bdrv_release_dirty_bitmap(anon);
+ return dst;
+}
+
+void qmp_block_dirty_bitmap_merge(const char *node, const char *target,
+ BlockDirtyBitmapMergeSourceList *bitmaps,
+ Error **errp)
+{
+ block_dirty_bitmap_merge(node, target, bitmaps, NULL, errp);
+}
diff --git a/block/parallels.c b/block/parallels.c
index e7717c5..63a1cde 100644
--- a/block/parallels.c
+++ b/block/parallels.c
@@ -739,8 +739,8 @@
Error *local_err = NULL;
char *buf;
- bs->file = bdrv_open_child(NULL, options, "file", bs, &child_file,
- false, errp);
+ bs->file = bdrv_open_child(NULL, options, "file", bs, &child_of_bds,
+ BDRV_CHILD_IMAGE, false, errp);
if (!bs->file) {
return -EINVAL;
}
@@ -912,12 +912,13 @@
.bdrv_probe = parallels_probe,
.bdrv_open = parallels_open,
.bdrv_close = parallels_close,
- .bdrv_child_perm = bdrv_format_default_perms,
+ .bdrv_child_perm = bdrv_default_perms,
.bdrv_co_block_status = parallels_co_block_status,
.bdrv_has_zero_init = bdrv_has_zero_init_1,
.bdrv_co_flush_to_os = parallels_co_flush_to_os,
.bdrv_co_readv = parallels_co_readv,
.bdrv_co_writev = parallels_co_writev,
+ .is_format = true,
.supports_backing = true,
.bdrv_co_create = parallels_co_create,
.bdrv_co_create_opts = parallels_co_create_opts,
diff --git a/block/qcow.c b/block/qcow.c
index b0475b7..ee5d35f 100644
--- a/block/qcow.c
+++ b/block/qcow.c
@@ -130,8 +130,8 @@
qdict_extract_subqdict(options, &encryptopts, "encrypt.");
encryptfmt = qdict_get_try_str(encryptopts, "format");
- bs->file = bdrv_open_child(NULL, options, "file", bs, &child_file,
- false, errp);
+ bs->file = bdrv_open_child(NULL, options, "file", bs, &child_of_bds,
+ BDRV_CHILD_IMAGE, false, errp);
if (!bs->file) {
ret = -EINVAL;
goto fail;
@@ -1180,11 +1180,12 @@
.bdrv_probe = qcow_probe,
.bdrv_open = qcow_open,
.bdrv_close = qcow_close,
- .bdrv_child_perm = bdrv_format_default_perms,
+ .bdrv_child_perm = bdrv_default_perms,
.bdrv_reopen_prepare = qcow_reopen_prepare,
.bdrv_co_create = qcow_co_create,
.bdrv_co_create_opts = qcow_co_create_opts,
.bdrv_has_zero_init = bdrv_has_zero_init_1,
+ .is_format = true,
.supports_backing = true,
.bdrv_refresh_limits = qcow_refresh_limits,
diff --git a/block/qcow2-bitmap.c b/block/qcow2-bitmap.c
index cb06954..7bf1250 100644
--- a/block/qcow2-bitmap.c
+++ b/block/qcow2-bitmap.c
@@ -1748,3 +1748,46 @@
name, bdrv_get_device_or_node_name(bs));
return false;
}
+
+bool qcow2_supports_persistent_dirty_bitmap(BlockDriverState *bs)
+{
+ BDRVQcow2State *s = bs->opaque;
+
+ return s->qcow_version >= 3;
+}
+
+/*
+ * Compute the space required for bitmaps in @bs.
+ *
+ * The computation is based as if copying to a new image with the
+ * given @cluster_size, which may differ from the cluster size in @bs.
+ */
+uint64_t qcow2_get_persistent_dirty_bitmap_size(BlockDriverState *bs,
+ uint32_t cluster_size)
+{
+ uint64_t bitmaps_size = 0;
+ BdrvDirtyBitmap *bm;
+ size_t bitmap_dir_size = 0;
+
+ FOR_EACH_DIRTY_BITMAP(bs, bm) {
+ if (bdrv_dirty_bitmap_get_persistence(bm)) {
+ const char *name = bdrv_dirty_bitmap_name(bm);
+ uint32_t granularity = bdrv_dirty_bitmap_granularity(bm);
+ uint64_t bmbytes =
+ get_bitmap_bytes_needed(bdrv_dirty_bitmap_size(bm),
+ granularity);
+ uint64_t bmclusters = DIV_ROUND_UP(bmbytes, cluster_size);
+
+ /* Assume the entire bitmap is allocated */
+ bitmaps_size += bmclusters * cluster_size;
+ /* Also reserve space for the bitmap table entries */
+ bitmaps_size += ROUND_UP(bmclusters * sizeof(uint64_t),
+ cluster_size);
+ /* And space for contribution to bitmap directory size */
+ bitmap_dir_size += calc_dir_entry_size(strlen(name), 0);
+ }
+ }
+ bitmaps_size += ROUND_UP(bitmap_dir_size, cluster_size);
+
+ return bitmaps_size;
+}
diff --git a/block/qcow2-threads.c b/block/qcow2-threads.c
index a68126f..1914baf 100644
--- a/block/qcow2-threads.c
+++ b/block/qcow2-threads.c
@@ -28,6 +28,11 @@
#define ZLIB_CONST
#include <zlib.h>
+#ifdef CONFIG_ZSTD
+#include <zstd.h>
+#include <zstd_errors.h>
+#endif
+
#include "qcow2.h"
#include "block/thread-pool.h"
#include "crypto.h"
@@ -74,7 +79,9 @@
} Qcow2CompressData;
/*
- * qcow2_compress()
+ * qcow2_zlib_compress()
+ *
+ * Compress @src_size bytes of data using zlib compression method
*
* @dest - destination buffer, @dest_size bytes
* @src - source buffer, @src_size bytes
@@ -83,8 +90,8 @@
* -ENOMEM destination buffer is not enough to store compressed data
* -EIO on any other error
*/
-static ssize_t qcow2_compress(void *dest, size_t dest_size,
- const void *src, size_t src_size)
+static ssize_t qcow2_zlib_compress(void *dest, size_t dest_size,
+ const void *src, size_t src_size)
{
ssize_t ret;
z_stream strm;
@@ -119,10 +126,10 @@
}
/*
- * qcow2_decompress()
+ * qcow2_zlib_decompress()
*
* Decompress some data (not more than @src_size bytes) to produce exactly
- * @dest_size bytes.
+ * @dest_size bytes using zlib compression method
*
* @dest - destination buffer, @dest_size bytes
* @src - source buffer, @src_size bytes
@@ -130,8 +137,8 @@
* Returns: 0 on success
* -EIO on fail
*/
-static ssize_t qcow2_decompress(void *dest, size_t dest_size,
- const void *src, size_t src_size)
+static ssize_t qcow2_zlib_decompress(void *dest, size_t dest_size,
+ const void *src, size_t src_size)
{
int ret;
z_stream strm;
@@ -164,6 +171,160 @@
return ret;
}
+#ifdef CONFIG_ZSTD
+
+/*
+ * qcow2_zstd_compress()
+ *
+ * Compress @src_size bytes of data using zstd compression method
+ *
+ * @dest - destination buffer, @dest_size bytes
+ * @src - source buffer, @src_size bytes
+ *
+ * Returns: compressed size on success
+ * -ENOMEM destination buffer is not enough to store compressed data
+ * -EIO on any other error
+ */
+static ssize_t qcow2_zstd_compress(void *dest, size_t dest_size,
+ const void *src, size_t src_size)
+{
+ ssize_t ret;
+ size_t zstd_ret;
+ ZSTD_outBuffer output = {
+ .dst = dest,
+ .size = dest_size,
+ .pos = 0
+ };
+ ZSTD_inBuffer input = {
+ .src = src,
+ .size = src_size,
+ .pos = 0
+ };
+ ZSTD_CCtx *cctx = ZSTD_createCCtx();
+
+ if (!cctx) {
+ return -EIO;
+ }
+ /*
+ * Use the zstd streamed interface for symmetry with decompression,
+ * where streaming is essential since we don't record the exact
+ * compressed size.
+ *
+ * ZSTD_compressStream2() tries to compress everything it could
+ * with a single call. Although, ZSTD docs says that:
+ * "You must continue calling ZSTD_compressStream2() with ZSTD_e_end
+ * until it returns 0, at which point you are free to start a new frame",
+ * in out tests we saw the only case when it returned with >0 -
+ * when the output buffer was too small. In that case,
+ * ZSTD_compressStream2() expects a bigger buffer on the next call.
+ * We can't provide a bigger buffer because we are limited with dest_size
+ * which we pass to the ZSTD_compressStream2() at once.
+ * So, we don't need any loops and just abort the compression when we
+ * don't get 0 result on the first call.
+ */
+ zstd_ret = ZSTD_compressStream2(cctx, &output, &input, ZSTD_e_end);
+
+ if (zstd_ret) {
+ if (zstd_ret > output.size - output.pos) {
+ ret = -ENOMEM;
+ } else {
+ ret = -EIO;
+ }
+ goto out;
+ }
+
+ /* make sure that zstd didn't overflow the dest buffer */
+ assert(output.pos <= dest_size);
+ ret = output.pos;
+out:
+ ZSTD_freeCCtx(cctx);
+ return ret;
+}
+
+/*
+ * qcow2_zstd_decompress()
+ *
+ * Decompress some data (not more than @src_size bytes) to produce exactly
+ * @dest_size bytes using zstd compression method
+ *
+ * @dest - destination buffer, @dest_size bytes
+ * @src - source buffer, @src_size bytes
+ *
+ * Returns: 0 on success
+ * -EIO on any error
+ */
+static ssize_t qcow2_zstd_decompress(void *dest, size_t dest_size,
+ const void *src, size_t src_size)
+{
+ size_t zstd_ret = 0;
+ ssize_t ret = 0;
+ ZSTD_outBuffer output = {
+ .dst = dest,
+ .size = dest_size,
+ .pos = 0
+ };
+ ZSTD_inBuffer input = {
+ .src = src,
+ .size = src_size,
+ .pos = 0
+ };
+ ZSTD_DCtx *dctx = ZSTD_createDCtx();
+
+ if (!dctx) {
+ return -EIO;
+ }
+
+ /*
+ * The compressed stream from the input buffer may consist of more
+ * than one zstd frame. So we iterate until we get a fully
+ * uncompressed cluster.
+ * From zstd docs related to ZSTD_decompressStream:
+ * "return : 0 when a frame is completely decoded and fully flushed"
+ * We suppose that this means: each time ZSTD_decompressStream reads
+ * only ONE full frame and returns 0 if and only if that frame
+ * is completely decoded and flushed. Only after returning 0,
+ * ZSTD_decompressStream reads another ONE full frame.
+ */
+ while (output.pos < output.size) {
+ size_t last_in_pos = input.pos;
+ size_t last_out_pos = output.pos;
+ zstd_ret = ZSTD_decompressStream(dctx, &output, &input);
+
+ if (ZSTD_isError(zstd_ret)) {
+ ret = -EIO;
+ break;
+ }
+
+ /*
+ * The ZSTD manual is vague about what to do if it reads
+ * the buffer partially, and we don't want to get stuck
+ * in an infinite loop where ZSTD_decompressStream
+ * returns > 0 waiting for another input chunk. So, we add
+ * a check which ensures that the loop makes some progress
+ * on each step.
+ */
+ if (last_in_pos >= input.pos &&
+ last_out_pos >= output.pos) {
+ ret = -EIO;
+ break;
+ }
+ }
+ /*
+ * Make sure that we have the frame fully flushed here
+ * if not, we somehow managed to get uncompressed cluster
+ * greater then the cluster size, possibly because of its
+ * damage.
+ */
+ if (zstd_ret > 0) {
+ ret = -EIO;
+ }
+
+ ZSTD_freeDCtx(dctx);
+ assert(ret == 0 || ret == -EIO);
+ return ret;
+}
+#endif
+
static int qcow2_compress_pool_func(void *opaque)
{
Qcow2CompressData *data = opaque;
@@ -191,20 +352,77 @@
return arg.ret;
}
+/*
+ * qcow2_co_compress()
+ *
+ * Compress @src_size bytes of data using the compression
+ * method defined by the image compression type
+ *
+ * @dest - destination buffer, @dest_size bytes
+ * @src - source buffer, @src_size bytes
+ *
+ * Returns: compressed size on success
+ * a negative error code on failure
+ */
ssize_t coroutine_fn
qcow2_co_compress(BlockDriverState *bs, void *dest, size_t dest_size,
const void *src, size_t src_size)
{
- return qcow2_co_do_compress(bs, dest, dest_size, src, src_size,
- qcow2_compress);
+ BDRVQcow2State *s = bs->opaque;
+ Qcow2CompressFunc fn;
+
+ switch (s->compression_type) {
+ case QCOW2_COMPRESSION_TYPE_ZLIB:
+ fn = qcow2_zlib_compress;
+ break;
+
+#ifdef CONFIG_ZSTD
+ case QCOW2_COMPRESSION_TYPE_ZSTD:
+ fn = qcow2_zstd_compress;
+ break;
+#endif
+ default:
+ abort();
+ }
+
+ return qcow2_co_do_compress(bs, dest, dest_size, src, src_size, fn);
}
+/*
+ * qcow2_co_decompress()
+ *
+ * Decompress some data (not more than @src_size bytes) to produce exactly
+ * @dest_size bytes using the compression method defined by the image
+ * compression type
+ *
+ * @dest - destination buffer, @dest_size bytes
+ * @src - source buffer, @src_size bytes
+ *
+ * Returns: 0 on success
+ * a negative error code on failure
+ */
ssize_t coroutine_fn
qcow2_co_decompress(BlockDriverState *bs, void *dest, size_t dest_size,
const void *src, size_t src_size)
{
- return qcow2_co_do_compress(bs, dest, dest_size, src, src_size,
- qcow2_decompress);
+ BDRVQcow2State *s = bs->opaque;
+ Qcow2CompressFunc fn;
+
+ switch (s->compression_type) {
+ case QCOW2_COMPRESSION_TYPE_ZLIB:
+ fn = qcow2_zlib_decompress;
+ break;
+
+#ifdef CONFIG_ZSTD
+ case QCOW2_COMPRESSION_TYPE_ZSTD:
+ fn = qcow2_zstd_decompress;
+ break;
+#endif
+ default:
+ abort();
+ }
+
+ return qcow2_co_do_compress(bs, dest, dest_size, src, src_size, fn);
}
diff --git a/block/qcow2.c b/block/qcow2.c
index 1ad95ff..0cd2e67 100644
--- a/block/qcow2.c
+++ b/block/qcow2.c
@@ -1242,6 +1242,42 @@
return ret;
}
+static int validate_compression_type(BDRVQcow2State *s, Error **errp)
+{
+ switch (s->compression_type) {
+ case QCOW2_COMPRESSION_TYPE_ZLIB:
+#ifdef CONFIG_ZSTD
+ case QCOW2_COMPRESSION_TYPE_ZSTD:
+#endif
+ break;
+
+ default:
+ error_setg(errp, "qcow2: unknown compression type: %u",
+ s->compression_type);
+ return -ENOTSUP;
+ }
+
+ /*
+ * if the compression type differs from QCOW2_COMPRESSION_TYPE_ZLIB
+ * the incompatible feature flag must be set
+ */
+ if (s->compression_type == QCOW2_COMPRESSION_TYPE_ZLIB) {
+ if (s->incompatible_features & QCOW2_INCOMPAT_COMPRESSION) {
+ error_setg(errp, "qcow2: Compression type incompatible feature "
+ "bit must not be set");
+ return -EINVAL;
+ }
+ } else {
+ if (!(s->incompatible_features & QCOW2_INCOMPAT_COMPRESSION)) {
+ error_setg(errp, "qcow2: Compression type incompatible feature "
+ "bit must be set");
+ return -EINVAL;
+ }
+ }
+
+ return 0;
+}
+
/* Called with s->lock held. */
static int coroutine_fn qcow2_do_open(BlockDriverState *bs, QDict *options,
int flags, Error **errp)
@@ -1357,6 +1393,23 @@
s->compatible_features = header.compatible_features;
s->autoclear_features = header.autoclear_features;
+ /*
+ * Handle compression type
+ * Older qcow2 images don't contain the compression type header.
+ * Distinguish them by the header length and use
+ * the only valid (default) compression type in that case
+ */
+ if (header.header_length > offsetof(QCowHeader, compression_type)) {
+ s->compression_type = header.compression_type;
+ } else {
+ s->compression_type = QCOW2_COMPRESSION_TYPE_ZLIB;
+ }
+
+ ret = validate_compression_type(s, errp);
+ if (ret) {
+ goto fail;
+ }
+
if (s->incompatible_features & ~QCOW2_INCOMPAT_MASK) {
void *feature_table = NULL;
qcow2_read_extensions(bs, header.header_length, ext_end,
@@ -1537,7 +1590,8 @@
}
/* Open external data file */
- s->data_file = bdrv_open_child(NULL, options, "data-file", bs, &child_file,
+ s->data_file = bdrv_open_child(NULL, options, "data-file", bs,
+ &child_of_bds, BDRV_CHILD_DATA,
true, &local_err);
if (local_err) {
error_propagate(errp, local_err);
@@ -1548,8 +1602,8 @@
if (s->incompatible_features & QCOW2_INCOMPAT_DATA_FILE) {
if (!s->data_file && s->image_data_file) {
s->data_file = bdrv_open_child(s->image_data_file, options,
- "data-file", bs, &child_file,
- false, errp);
+ "data-file", bs, &child_of_bds,
+ BDRV_CHILD_DATA, false, errp);
if (!s->data_file) {
ret = -EINVAL;
goto fail;
@@ -1560,6 +1614,12 @@
ret = -EINVAL;
goto fail;
}
+
+ /* No data here */
+ bs->file->role &= ~BDRV_CHILD_DATA;
+
+ /* Must succeed because we have given up permissions if anything */
+ bdrv_child_refresh_perms(bs, bs->file, &error_abort);
} else {
if (s->data_file) {
error_setg(errp, "'data-file' can only be set for images with an "
@@ -1810,8 +1870,8 @@
.ret = -EINPROGRESS
};
- bs->file = bdrv_open_child(NULL, options, "file", bs, &child_file,
- false, errp);
+ bs->file = bdrv_open_child(NULL, options, "file", bs, &child_of_bds,
+ BDRV_CHILD_IMAGE, false, errp);
if (!bs->file) {
return -EINVAL;
}
@@ -2728,6 +2788,11 @@
total_size = bs->total_sectors * BDRV_SECTOR_SIZE;
refcount_table_clusters = s->refcount_table_size >> (s->cluster_bits - 3);
+ ret = validate_compression_type(s, NULL);
+ if (ret) {
+ goto fail;
+ }
+
*header = (QCowHeader) {
/* Version 2 fields */
.magic = cpu_to_be32(QCOW_MAGIC),
@@ -2750,6 +2815,7 @@
.autoclear_features = cpu_to_be64(s->autoclear_features),
.refcount_order = cpu_to_be32(s->refcount_order),
.header_length = cpu_to_be32(header_length),
+ .compression_type = s->compression_type,
};
/* For older versions, write a shorter header */
@@ -2850,6 +2916,11 @@
.name = "external data file",
},
{
+ .type = QCOW2_FEAT_TYPE_INCOMPATIBLE,
+ .bit = QCOW2_INCOMPAT_COMPRESSION_BITNR,
+ .name = "compression type",
+ },
+ {
.type = QCOW2_FEAT_TYPE_COMPATIBLE,
.bit = QCOW2_COMPAT_LAZY_REFCOUNTS_BITNR,
.name = "lazy refcounts",
@@ -3287,6 +3358,7 @@
uint64_t* refcount_table;
Error *local_err = NULL;
int ret;
+ uint8_t compression_type = QCOW2_COMPRESSION_TYPE_ZLIB;
assert(create_options->driver == BLOCKDEV_DRIVER_QCOW2);
qcow2_opts = &create_options->u.qcow2;
@@ -3404,6 +3476,31 @@
}
}
+ if (qcow2_opts->has_compression_type &&
+ qcow2_opts->compression_type != QCOW2_COMPRESSION_TYPE_ZLIB) {
+
+ ret = -EINVAL;
+
+ if (version < 3) {
+ error_setg(errp, "Non-zlib compression type is only supported with "
+ "compatibility level 1.1 and above (use version=v3 or "
+ "greater)");
+ goto out;
+ }
+
+ switch (qcow2_opts->compression_type) {
+#ifdef CONFIG_ZSTD
+ case QCOW2_COMPRESSION_TYPE_ZSTD:
+ break;
+#endif
+ default:
+ error_setg(errp, "Unknown compression type");
+ goto out;
+ }
+
+ compression_type = qcow2_opts->compression_type;
+ }
+
/* Create BlockBackend to write to the image */
blk = blk_new_with_bs(bs, BLK_PERM_WRITE | BLK_PERM_RESIZE, BLK_PERM_ALL,
errp);
@@ -3426,6 +3523,8 @@
.refcount_table_offset = cpu_to_be64(cluster_size),
.refcount_table_clusters = cpu_to_be32(1),
.refcount_order = cpu_to_be32(refcount_order),
+ /* don't deal with endianness since compression_type is 1 byte long */
+ .compression_type = compression_type,
.header_length = cpu_to_be32(sizeof(*header)),
};
@@ -3444,6 +3543,10 @@
header->autoclear_features |=
cpu_to_be64(QCOW2_AUTOCLEAR_DATA_FILE_RAW);
}
+ if (compression_type != QCOW2_COMPRESSION_TYPE_ZLIB) {
+ header->incompatible_features |=
+ cpu_to_be64(QCOW2_INCOMPAT_COMPRESSION);
+ }
ret = blk_pwrite(blk, 0, header, cluster_size, 0);
g_free(header);
@@ -3629,6 +3732,7 @@
{ BLOCK_OPT_ENCRYPT, BLOCK_OPT_ENCRYPT_FORMAT },
{ BLOCK_OPT_COMPAT_LEVEL, "version" },
{ BLOCK_OPT_DATA_FILE_RAW, "data-file-raw" },
+ { BLOCK_OPT_COMPRESSION_TYPE, "compression-type" },
{ NULL, NULL },
};
@@ -4849,16 +4953,24 @@
required = virtual_size;
}
- info = g_new(BlockMeasureInfo, 1);
+ info = g_new0(BlockMeasureInfo, 1);
info->fully_allocated =
qcow2_calc_prealloc_size(virtual_size, cluster_size,
ctz32(refcount_bits)) + luks_payload_size;
- /* Remove data clusters that are not required. This overestimates the
+ /*
+ * Remove data clusters that are not required. This overestimates the
* required size because metadata needed for the fully allocated file is
- * still counted.
+ * still counted. Show bitmaps only if both source and destination
+ * would support them.
*/
info->required = info->fully_allocated - virtual_size + required;
+ info->has_bitmaps = version >= 3 && in_bs &&
+ bdrv_supports_persistent_dirty_bitmap(in_bs);
+ if (info->has_bitmaps) {
+ info->bitmaps = qcow2_get_persistent_dirty_bitmap_size(in_bs,
+ cluster_size);
+ }
return info;
err:
@@ -4925,6 +5037,7 @@
.data_file = g_strdup(s->image_data_file),
.has_data_file_raw = has_data_file(bs),
.data_file_raw = data_file_is_raw(bs),
+ .compression_type = s->compression_type,
};
} else {
/* if this assertion fails, this probably means a new version was
@@ -5330,6 +5443,22 @@
"images");
return -EINVAL;
}
+ } else if (!strcmp(desc->name, BLOCK_OPT_COMPRESSION_TYPE)) {
+ const char *ct_name =
+ qemu_opt_get(opts, BLOCK_OPT_COMPRESSION_TYPE);
+ int compression_type =
+ qapi_enum_parse(&Qcow2CompressionType_lookup, ct_name, -1,
+ NULL);
+ if (compression_type == -1) {
+ error_setg(errp, "Unknown compression type: %s", ct_name);
+ return -ENOTSUP;
+ }
+
+ if (compression_type != s->compression_type) {
+ error_setg(errp, "Changing the compression type "
+ "is not supported");
+ return -ENOTSUP;
+ }
} else {
/* if this point is reached, this probably means a new option was
* added without having it covered here */
@@ -5596,6 +5725,12 @@
.help = "Width of a reference count entry in bits",
.def_value_str = "16"
},
+ {
+ .name = BLOCK_OPT_COMPRESSION_TYPE,
+ .type = QEMU_OPT_STRING,
+ .help = "Compression method used for image cluster compression",
+ .def_value_str = "zlib"
+ },
{ /* end of list */ }
}
};
@@ -5617,7 +5752,7 @@
.bdrv_reopen_commit_post = qcow2_reopen_commit_post,
.bdrv_reopen_abort = qcow2_reopen_abort,
.bdrv_join_options = qcow2_join_options,
- .bdrv_child_perm = bdrv_format_default_perms,
+ .bdrv_child_perm = bdrv_default_perms,
.bdrv_co_create_opts = qcow2_co_create_opts,
.bdrv_co_create = qcow2_co_create,
.bdrv_has_zero_init = qcow2_has_zero_init,
@@ -5647,6 +5782,7 @@
.bdrv_save_vmstate = qcow2_save_vmstate,
.bdrv_load_vmstate = qcow2_load_vmstate,
+ .is_format = true,
.supports_backing = true,
.bdrv_change_backing_file = qcow2_change_backing_file,
@@ -5663,6 +5799,8 @@
.bdrv_detach_aio_context = qcow2_detach_aio_context,
.bdrv_attach_aio_context = qcow2_attach_aio_context,
+ .bdrv_supports_persistent_dirty_bitmap =
+ qcow2_supports_persistent_dirty_bitmap,
.bdrv_co_can_store_new_dirty_bitmap = qcow2_co_can_store_new_dirty_bitmap,
.bdrv_co_remove_persistent_dirty_bitmap =
qcow2_co_remove_persistent_dirty_bitmap,
diff --git a/block/qcow2.h b/block/qcow2.h
index f4de0a2..7ce2c23 100644
--- a/block/qcow2.h
+++ b/block/qcow2.h
@@ -146,8 +146,16 @@
uint32_t refcount_order;
uint32_t header_length;
+
+ /* Additional fields */
+ uint8_t compression_type;
+
+ /* header must be a multiple of 8 */
+ uint8_t padding[7];
} QEMU_PACKED QCowHeader;
+QEMU_BUILD_BUG_ON(!QEMU_IS_ALIGNED(sizeof(QCowHeader), 8));
+
typedef struct QEMU_PACKED QCowSnapshotHeader {
/* header is 8 byte aligned */
uint64_t l1_table_offset;
@@ -216,13 +224,16 @@
QCOW2_INCOMPAT_DIRTY_BITNR = 0,
QCOW2_INCOMPAT_CORRUPT_BITNR = 1,
QCOW2_INCOMPAT_DATA_FILE_BITNR = 2,
+ QCOW2_INCOMPAT_COMPRESSION_BITNR = 3,
QCOW2_INCOMPAT_DIRTY = 1 << QCOW2_INCOMPAT_DIRTY_BITNR,
QCOW2_INCOMPAT_CORRUPT = 1 << QCOW2_INCOMPAT_CORRUPT_BITNR,
QCOW2_INCOMPAT_DATA_FILE = 1 << QCOW2_INCOMPAT_DATA_FILE_BITNR,
+ QCOW2_INCOMPAT_COMPRESSION = 1 << QCOW2_INCOMPAT_COMPRESSION_BITNR,
QCOW2_INCOMPAT_MASK = QCOW2_INCOMPAT_DIRTY
| QCOW2_INCOMPAT_CORRUPT
- | QCOW2_INCOMPAT_DATA_FILE,
+ | QCOW2_INCOMPAT_DATA_FILE
+ | QCOW2_INCOMPAT_COMPRESSION,
};
/* Compatible feature bits */
@@ -366,6 +377,13 @@
bool metadata_preallocation_checked;
bool metadata_preallocation;
+ /*
+ * Compression type used for the image. Default: 0 - ZLIB
+ * The image compression type is set on image creation.
+ * For now, the only way to change the compression type
+ * is to convert the image with the desired compression type set.
+ */
+ Qcow2CompressionType compression_type;
} BDRVQcow2State;
typedef struct Qcow2COWRegion {
@@ -764,6 +782,9 @@
int qcow2_co_remove_persistent_dirty_bitmap(BlockDriverState *bs,
const char *name,
Error **errp);
+bool qcow2_supports_persistent_dirty_bitmap(BlockDriverState *bs);
+uint64_t qcow2_get_persistent_dirty_bitmap_size(BlockDriverState *bs,
+ uint32_t cluster_size);
ssize_t coroutine_fn
qcow2_co_compress(BlockDriverState *bs, void *dest, size_t dest_size,
diff --git a/block/qed.c b/block/qed.c
index 5da9726..c0c6501 100644
--- a/block/qed.c
+++ b/block/qed.c
@@ -547,8 +547,8 @@
.ret = -EINPROGRESS
};
- bs->file = bdrv_open_child(NULL, options, "file", bs, &child_file,
- false, errp);
+ bs->file = bdrv_open_child(NULL, options, "file", bs, &child_of_bds,
+ BDRV_CHILD_IMAGE, false, errp);
if (!bs->file) {
return -EINVAL;
}
@@ -1665,13 +1665,14 @@
.format_name = "qed",
.instance_size = sizeof(BDRVQEDState),
.create_opts = &qed_create_opts,
+ .is_format = true,
.supports_backing = true,
.bdrv_probe = bdrv_qed_probe,
.bdrv_open = bdrv_qed_open,
.bdrv_close = bdrv_qed_close,
.bdrv_reopen_prepare = bdrv_qed_reopen_prepare,
- .bdrv_child_perm = bdrv_format_default_perms,
+ .bdrv_child_perm = bdrv_default_perms,
.bdrv_co_create = bdrv_qed_co_create,
.bdrv_co_create_opts = bdrv_qed_co_create_opts,
.bdrv_has_zero_init = bdrv_has_zero_init_1,
diff --git a/block/quorum.c b/block/quorum.c
index 6d7a56b..7cf7ab1 100644
--- a/block/quorum.c
+++ b/block/quorum.c
@@ -977,7 +977,8 @@
assert(ret < 32);
s->children[i] = bdrv_open_child(NULL, options, indexstr, bs,
- &child_format, false, &local_err);
+ &child_of_bds, BDRV_CHILD_DATA, false,
+ &local_err);
if (local_err) {
ret = -EINVAL;
goto close_exit;
@@ -1053,7 +1054,8 @@
/* We can safely add the child now */
bdrv_ref(child_bs);
- child = bdrv_attach_child(bs, child_bs, indexstr, &child_format, errp);
+ child = bdrv_attach_child(bs, child_bs, indexstr, &child_of_bds,
+ BDRV_CHILD_DATA, errp);
if (child == NULL) {
s->next_child_index--;
goto out;
@@ -1151,7 +1153,7 @@
}
static void quorum_child_perm(BlockDriverState *bs, BdrvChild *c,
- const BdrvChildRole *role,
+ BdrvChildRole role,
BlockReopenQueue *reopen_queue,
uint64_t perm, uint64_t shared,
uint64_t *nperm, uint64_t *nshared)
diff --git a/block/raw-format.c b/block/raw-format.c
index 9108e43..233d019 100644
--- a/block/raw-format.c
+++ b/block/raw-format.c
@@ -71,20 +71,13 @@
}
};
-static int raw_read_options(QDict *options, BlockDriverState *bs,
- BDRVRawState *s, Error **errp)
+static int raw_read_options(QDict *options, uint64_t *offset, bool *has_size,
+ uint64_t *size, Error **errp)
{
Error *local_err = NULL;
QemuOpts *opts = NULL;
- int64_t real_size = 0;
int ret;
- real_size = bdrv_getlength(bs->file->bs);
- if (real_size < 0) {
- error_setg_errno(errp, -real_size, "Could not get image size");
- return real_size;
- }
-
opts = qemu_opts_create(&raw_runtime_opts, NULL, 0, &error_abort);
qemu_opts_absorb_qdict(opts, options, &local_err);
if (local_err) {
@@ -93,64 +86,84 @@
goto end;
}
- s->offset = qemu_opt_get_size(opts, "offset", 0);
- if (s->offset > real_size) {
- error_setg(errp, "Offset (%" PRIu64 ") cannot be greater than "
- "size of the containing file (%" PRId64 ")",
- s->offset, real_size);
- ret = -EINVAL;
- goto end;
- }
+ *offset = qemu_opt_get_size(opts, "offset", 0);
+ *has_size = qemu_opt_find(opts, "size");
+ *size = qemu_opt_get_size(opts, "size", 0);
- if (qemu_opt_find(opts, "size") != NULL) {
- s->size = qemu_opt_get_size(opts, "size", 0);
- s->has_size = true;
- } else {
- s->has_size = false;
- s->size = real_size - s->offset;
+ ret = 0;
+end:
+ qemu_opts_del(opts);
+ return ret;
+}
+
+static int raw_apply_options(BlockDriverState *bs, BDRVRawState *s,
+ uint64_t offset, bool has_size, uint64_t size,
+ Error **errp)
+{
+ int64_t real_size = 0;
+
+ real_size = bdrv_getlength(bs->file->bs);
+ if (real_size < 0) {
+ error_setg_errno(errp, -real_size, "Could not get image size");
+ return real_size;
}
/* Check size and offset */
- if ((real_size - s->offset) < s->size) {
+ if (offset > real_size) {
+ error_setg(errp, "Offset (%" PRIu64 ") cannot be greater than "
+ "size of the containing file (%" PRId64 ")",
+ s->offset, real_size);
+ return -EINVAL;
+ }
+
+ if (has_size && (real_size - offset) < size) {
error_setg(errp, "The sum of offset (%" PRIu64 ") and size "
- "(%" PRIu64 ") has to be smaller or equal to the "
- " actual size of the containing file (%" PRId64 ")",
- s->offset, s->size, real_size);
- ret = -EINVAL;
- goto end;
+ "(%" PRIu64 ") has to be smaller or equal to the "
+ " actual size of the containing file (%" PRId64 ")",
+ s->offset, s->size, real_size);
+ return -EINVAL;
}
/* Make sure size is multiple of BDRV_SECTOR_SIZE to prevent rounding
* up and leaking out of the specified area. */
- if (s->has_size && !QEMU_IS_ALIGNED(s->size, BDRV_SECTOR_SIZE)) {
+ if (has_size && !QEMU_IS_ALIGNED(size, BDRV_SECTOR_SIZE)) {
error_setg(errp, "Specified size is not multiple of %llu",
- BDRV_SECTOR_SIZE);
- ret = -EINVAL;
- goto end;
+ BDRV_SECTOR_SIZE);
+ return -EINVAL;
}
- ret = 0;
+ s->offset = offset;
+ s->has_size = has_size;
+ s->size = has_size ? size : real_size - offset;
-end:
-
- qemu_opts_del(opts);
-
- return ret;
+ return 0;
}
static int raw_reopen_prepare(BDRVReopenState *reopen_state,
BlockReopenQueue *queue, Error **errp)
{
+ bool has_size;
+ uint64_t offset, size;
+ int ret;
+
assert(reopen_state != NULL);
assert(reopen_state->bs != NULL);
reopen_state->opaque = g_new0(BDRVRawState, 1);
- return raw_read_options(
- reopen_state->options,
- reopen_state->bs,
- reopen_state->opaque,
- errp);
+ ret = raw_read_options(reopen_state->options, &offset, &has_size, &size,
+ errp);
+ if (ret < 0) {
+ return ret;
+ }
+
+ ret = raw_apply_options(reopen_state->bs, reopen_state->opaque,
+ offset, has_size, size, errp);
+ if (ret < 0) {
+ return ret;
+ }
+
+ return 0;
}
static void raw_reopen_commit(BDRVReopenState *state)
@@ -346,7 +359,7 @@
BDRV_SECTOR_SIZE);
}
- info = g_new(BlockMeasureInfo, 1);
+ info = g_new0(BlockMeasureInfo, 1);
info->required = required;
/* Unallocated sectors count towards the file size in raw images */
@@ -426,10 +439,28 @@
Error **errp)
{
BDRVRawState *s = bs->opaque;
+ bool has_size;
+ uint64_t offset, size;
+ BdrvChildRole file_role;
int ret;
- bs->file = bdrv_open_child(NULL, options, "file", bs, &child_file,
- false, errp);
+ ret = raw_read_options(options, &offset, &has_size, &size, errp);
+ if (ret < 0) {
+ return ret;
+ }
+
+ /*
+ * Without offset and a size limit, this driver behaves very much
+ * like a filter. With any such limit, it does not.
+ */
+ if (offset || has_size) {
+ file_role = BDRV_CHILD_DATA | BDRV_CHILD_PRIMARY;
+ } else {
+ file_role = BDRV_CHILD_FILTERED | BDRV_CHILD_PRIMARY;
+ }
+
+ bs->file = bdrv_open_child(NULL, options, "file", bs, &child_of_bds,
+ file_role, false, errp);
if (!bs->file) {
return -EINVAL;
}
@@ -455,7 +486,7 @@
bs->file->bs->filename);
}
- ret = raw_read_options(options, bs, s, errp);
+ ret = raw_apply_options(bs, s, offset, has_size, size, errp);
if (ret < 0) {
return ret;
}
@@ -555,7 +586,7 @@
.bdrv_reopen_commit = &raw_reopen_commit,
.bdrv_reopen_abort = &raw_reopen_abort,
.bdrv_open = &raw_open,
- .bdrv_child_perm = bdrv_filter_default_perms,
+ .bdrv_child_perm = bdrv_default_perms,
.bdrv_co_create_opts = &raw_co_create_opts,
.bdrv_co_preadv = &raw_co_preadv,
.bdrv_co_pwritev = &raw_co_pwritev,
@@ -566,6 +597,7 @@
.bdrv_co_copy_range_to = &raw_co_copy_range_to,
.bdrv_co_truncate = &raw_co_truncate,
.bdrv_getlength = &raw_getlength,
+ .is_format = true,
.has_variable_length = true,
.bdrv_measure = &raw_measure,
.bdrv_get_info = &raw_get_info,
diff --git a/block/replication.c b/block/replication.c
index 971f0fe..ccf7b78 100644
--- a/block/replication.c
+++ b/block/replication.c
@@ -90,7 +90,8 @@
const char *mode;
const char *top_id;
- bs->file = bdrv_open_child(NULL, options, "file", bs, &child_file,
+ bs->file = bdrv_open_child(NULL, options, "file", bs, &child_of_bds,
+ BDRV_CHILD_FILTERED | BDRV_CHILD_PRIMARY,
false, errp);
if (!bs->file) {
return -EINVAL;
@@ -163,7 +164,7 @@
}
static void replication_child_perm(BlockDriverState *bs, BdrvChild *c,
- const BdrvChildRole *role,
+ BdrvChildRole role,
BlockReopenQueue *reopen_queue,
uint64_t perm, uint64_t shared,
uint64_t *nperm, uint64_t *nshared)
@@ -331,9 +332,8 @@
return;
}
- ret = s->active_disk->bs->drv->bdrv_make_empty(s->active_disk->bs);
+ ret = bdrv_make_empty(s->active_disk, errp);
if (ret < 0) {
- error_setg(errp, "Cannot make active disk empty");
return;
}
@@ -343,9 +343,18 @@
return;
}
- ret = s->hidden_disk->bs->drv->bdrv_make_empty(s->hidden_disk->bs);
+ BlockBackend *blk = blk_new(qemu_get_current_aio_context(),
+ BLK_PERM_WRITE, BLK_PERM_ALL);
+ blk_insert_bs(blk, s->hidden_disk->bs, &local_err);
+ if (local_err) {
+ error_propagate(errp, local_err);
+ blk_unref(blk);
+ return;
+ }
+
+ ret = blk_make_empty(blk, errp);
+ blk_unref(blk);
if (ret < 0) {
- error_setg(errp, "Cannot make hidden disk empty");
return;
}
}
@@ -398,6 +407,8 @@
BDRVReplicationState *s = bs->opaque;
BlockDriverState *top_bs;
+ s->backup_job = NULL;
+
top_bs = bdrv_lookup_bs(s->top_id, s->top_id, NULL);
if (!top_bs) {
return;
diff --git a/block/throttle-groups.c b/block/throttle-groups.c
index 37695b0..784fa4a 100644
--- a/block/throttle-groups.c
+++ b/block/throttle-groups.c
@@ -954,8 +954,7 @@
"int",
throttle_group_get,
throttle_group_set,
- NULL, &properties[i],
- &error_abort);
+ NULL, &properties[i]);
}
/* ThrottleLimits */
@@ -963,8 +962,7 @@
"limits", "ThrottleLimits",
throttle_group_get_limits,
throttle_group_set_limits,
- NULL, NULL,
- &error_abort);
+ NULL, NULL);
}
static const TypeInfo throttle_group_info = {
diff --git a/block/throttle.c b/block/throttle.c
index 71f4bb0..0ebbad0 100644
--- a/block/throttle.c
+++ b/block/throttle.c
@@ -81,8 +81,9 @@
char *group;
int ret;
- bs->file = bdrv_open_child(NULL, options, "file", bs,
- &child_file, false, errp);
+ bs->file = bdrv_open_child(NULL, options, "file", bs, &child_of_bds,
+ BDRV_CHILD_FILTERED | BDRV_CHILD_PRIMARY,
+ false, errp);
if (!bs->file) {
return -EINVAL;
}
@@ -236,7 +237,7 @@
.bdrv_close = throttle_close,
.bdrv_co_flush = throttle_co_flush,
- .bdrv_child_perm = bdrv_filter_default_perms,
+ .bdrv_child_perm = bdrv_default_perms,
.bdrv_getlength = throttle_getlength,
diff --git a/block/vdi.c b/block/vdi.c
index 2d28046..2f506a0 100644
--- a/block/vdi.c
+++ b/block/vdi.c
@@ -378,8 +378,8 @@
Error *local_err = NULL;
QemuUUID uuid_link, uuid_parent;
- bs->file = bdrv_open_child(NULL, options, "file", bs, &child_file,
- false, errp);
+ bs->file = bdrv_open_child(NULL, options, "file", bs, &child_of_bds,
+ BDRV_CHILD_IMAGE, false, errp);
if (!bs->file) {
return -EINVAL;
}
@@ -1039,7 +1039,7 @@
.bdrv_open = vdi_open,
.bdrv_close = vdi_close,
.bdrv_reopen_prepare = vdi_reopen_prepare,
- .bdrv_child_perm = bdrv_format_default_perms,
+ .bdrv_child_perm = bdrv_default_perms,
.bdrv_co_create = vdi_co_create,
.bdrv_co_create_opts = vdi_co_create_opts,
.bdrv_has_zero_init = vdi_has_zero_init,
@@ -1053,6 +1053,7 @@
.bdrv_get_info = vdi_get_info,
+ .is_format = true,
.create_opts = &vdi_create_opts,
.bdrv_co_check = vdi_co_check,
};
diff --git a/block/vhdx.c b/block/vhdx.c
index 53e7564..fa9e544 100644
--- a/block/vhdx.c
+++ b/block/vhdx.c
@@ -996,8 +996,8 @@
uint64_t signature;
Error *local_err = NULL;
- bs->file = bdrv_open_child(NULL, options, "file", bs, &child_file,
- false, errp);
+ bs->file = bdrv_open_child(NULL, options, "file", bs, &child_of_bds,
+ BDRV_CHILD_IMAGE, false, errp);
if (!bs->file) {
return -EINVAL;
}
@@ -2245,7 +2245,7 @@
.bdrv_open = vhdx_open,
.bdrv_close = vhdx_close,
.bdrv_reopen_prepare = vhdx_reopen_prepare,
- .bdrv_child_perm = bdrv_format_default_perms,
+ .bdrv_child_perm = bdrv_default_perms,
.bdrv_co_readv = vhdx_co_readv,
.bdrv_co_writev = vhdx_co_writev,
.bdrv_co_create = vhdx_co_create,
@@ -2254,6 +2254,7 @@
.bdrv_co_check = vhdx_co_check,
.bdrv_has_zero_init = vhdx_has_zero_init,
+ .is_format = true,
.create_opts = &vhdx_create_opts,
};
diff --git a/block/vmdk.c b/block/vmdk.c
index b18f128..62da465 100644
--- a/block/vmdk.c
+++ b/block/vmdk.c
@@ -1089,6 +1089,7 @@
char *desc_file_dir = NULL;
char *extent_path;
BdrvChild *extent_file;
+ BdrvChildRole extent_role;
BDRVVmdkState *s = bs->opaque;
VmdkExtent *extent;
char extent_opt_prefix[32];
@@ -1151,8 +1152,15 @@
ret = snprintf(extent_opt_prefix, 32, "extents.%d", s->num_extents);
assert(ret < 32);
+ extent_role = BDRV_CHILD_DATA;
+ if (strcmp(type, "FLAT") != 0 && strcmp(type, "VMFS") != 0) {
+ /* non-flat extents have metadata */
+ extent_role |= BDRV_CHILD_METADATA;
+ }
+
extent_file = bdrv_open_child(extent_path, options, extent_opt_prefix,
- bs, &child_file, false, &local_err);
+ bs, &child_of_bds, extent_role, false,
+ &local_err);
g_free(extent_path);
if (local_err) {
error_propagate(errp, local_err);
@@ -1257,8 +1265,8 @@
uint32_t magic;
Error *local_err = NULL;
- bs->file = bdrv_open_child(NULL, options, "file", bs, &child_file,
- false, errp);
+ bs->file = bdrv_open_child(NULL, options, "file", bs, &child_of_bds,
+ BDRV_CHILD_IMAGE, false, errp);
if (!bs->file) {
return -EINVAL;
}
@@ -1277,6 +1285,12 @@
s->desc_offset = 0x200;
break;
default:
+ /* No data in the descriptor file */
+ bs->file->role &= ~BDRV_CHILD_DATA;
+
+ /* Must succeed because we have given up permissions if anything */
+ bdrv_child_refresh_perms(bs, bs->file, &error_abort);
+
ret = vmdk_open_desc_file(bs, flags, buf, options, errp);
break;
}
@@ -3053,7 +3067,7 @@
.bdrv_open = vmdk_open,
.bdrv_co_check = vmdk_co_check,
.bdrv_reopen_prepare = vmdk_reopen_prepare,
- .bdrv_child_perm = bdrv_format_default_perms,
+ .bdrv_child_perm = bdrv_default_perms,
.bdrv_co_preadv = vmdk_co_preadv,
.bdrv_co_pwritev = vmdk_co_pwritev,
.bdrv_co_pwritev_compressed = vmdk_co_pwritev_compressed,
@@ -3070,6 +3084,7 @@
.bdrv_get_info = vmdk_get_info,
.bdrv_gather_child_options = vmdk_gather_child_options,
+ .is_format = true,
.supports_backing = true,
.create_opts = &vmdk_create_opts,
};
diff --git a/block/vpc.c b/block/vpc.c
index 5e31dd1..c055591 100644
--- a/block/vpc.c
+++ b/block/vpc.c
@@ -228,8 +228,8 @@
int ret;
int64_t bs_size;
- bs->file = bdrv_open_child(NULL, options, "file", bs, &child_file,
- false, errp);
+ bs->file = bdrv_open_child(NULL, options, "file", bs, &child_of_bds,
+ BDRV_CHILD_IMAGE, false, errp);
if (!bs->file) {
return -EINVAL;
}
@@ -1240,7 +1240,7 @@
.bdrv_open = vpc_open,
.bdrv_close = vpc_close,
.bdrv_reopen_prepare = vpc_reopen_prepare,
- .bdrv_child_perm = bdrv_format_default_perms,
+ .bdrv_child_perm = bdrv_default_perms,
.bdrv_co_create = vpc_co_create,
.bdrv_co_create_opts = vpc_co_create_opts,
@@ -1250,6 +1250,7 @@
.bdrv_get_info = vpc_get_info,
+ .is_format = true,
.create_opts = &vpc_create_opts,
.bdrv_has_zero_init = vpc_has_zero_init,
.strong_runtime_opts = vpc_strong_runtime_opts,
diff --git a/block/vvfat.c b/block/vvfat.c
index 6d5c090..c65a98e 100644
--- a/block/vvfat.c
+++ b/block/vvfat.c
@@ -2960,9 +2960,7 @@
return ret;
}
- if (s->qcow->bs->drv && s->qcow->bs->drv->bdrv_make_empty) {
- s->qcow->bs->drv->bdrv_make_empty(s->qcow->bs);
- }
+ bdrv_make_empty(s->qcow, NULL);
memset(s->used_clusters, 0, sector2cluster(s, s->sector_count));
@@ -3130,7 +3128,8 @@
.bdrv_co_pwritev = write_target_commit,
};
-static void vvfat_qcow_options(int *child_flags, QDict *child_options,
+static void vvfat_qcow_options(BdrvChildRole role, bool parent_is_format,
+ int *child_flags, QDict *child_options,
int parent_flags, QDict *parent_options)
{
qdict_set_default_str(child_options, BDRV_OPT_READ_ONLY, "off");
@@ -3138,7 +3137,7 @@
qdict_set_default_str(child_options, BDRV_OPT_CACHE_NO_FLUSH, "on");
}
-static const BdrvChildRole child_vvfat_qcow = {
+static const BdrvChildClass child_vvfat_qcow = {
.parent_is_bds = true,
.inherit_options = vvfat_qcow_options,
};
@@ -3185,7 +3184,9 @@
options = qdict_new();
qdict_put_str(options, "write-target.driver", "qcow");
s->qcow = bdrv_open_child(s->qcow_filename, options, "write-target", bs,
- &child_vvfat_qcow, false, errp);
+ &child_vvfat_qcow,
+ BDRV_CHILD_DATA | BDRV_CHILD_METADATA,
+ false, errp);
qobject_unref(options);
if (!s->qcow) {
ret = -EINVAL;
@@ -3212,14 +3213,14 @@
}
static void vvfat_child_perm(BlockDriverState *bs, BdrvChild *c,
- const BdrvChildRole *role,
+ BdrvChildRole role,
BlockReopenQueue *reopen_queue,
uint64_t perm, uint64_t shared,
uint64_t *nperm, uint64_t *nshared)
{
BDRVVVFATState *s = bs->opaque;
- assert(c == s->qcow || role == &child_backing);
+ assert(c == s->qcow || (role & BDRV_CHILD_COW));
if (c == s->qcow) {
/* This is a private node, nobody should try to attach to it */
diff --git a/blockdev.c b/blockdev.c
index b3c840e..72df193 100644
--- a/blockdev.c
+++ b/blockdev.c
@@ -1185,53 +1185,6 @@
return NULL;
}
-/**
- * block_dirty_bitmap_lookup:
- * Return a dirty bitmap (if present), after validating
- * the node reference and bitmap names.
- *
- * @node: The name of the BDS node to search for bitmaps
- * @name: The name of the bitmap to search for
- * @pbs: Output pointer for BDS lookup, if desired. Can be NULL.
- * @errp: Output pointer for error information. Can be NULL.
- *
- * @return: A bitmap object on success, or NULL on failure.
- */
-static BdrvDirtyBitmap *block_dirty_bitmap_lookup(const char *node,
- const char *name,
- BlockDriverState **pbs,
- Error **errp)
-{
- BlockDriverState *bs;
- BdrvDirtyBitmap *bitmap;
-
- if (!node) {
- error_setg(errp, "Node cannot be NULL");
- return NULL;
- }
- if (!name) {
- error_setg(errp, "Bitmap name cannot be NULL");
- return NULL;
- }
- bs = bdrv_lookup_bs(node, node, NULL);
- if (!bs) {
- error_setg(errp, "Node '%s' not found", node);
- return NULL;
- }
-
- bitmap = bdrv_find_dirty_bitmap(bs, name);
- if (!bitmap) {
- error_setg(errp, "Dirty bitmap '%s' not found", name);
- return NULL;
- }
-
- if (pbs) {
- *pbs = bs;
- }
-
- return bitmap;
-}
-
/* New and old BlockDriverState structs for atomic group operations */
typedef struct BlkActionState BlkActionState;
@@ -2171,11 +2124,6 @@
}
}
-static BdrvDirtyBitmap *do_block_dirty_bitmap_merge(
- const char *node, const char *target,
- BlockDirtyBitmapMergeSourceList *bitmaps,
- HBitmap **backup, Error **errp);
-
static void block_dirty_bitmap_merge_prepare(BlkActionState *common,
Error **errp)
{
@@ -2189,15 +2137,11 @@
action = common->action->u.block_dirty_bitmap_merge.data;
- state->bitmap = do_block_dirty_bitmap_merge(action->node, action->target,
- action->bitmaps, &state->backup,
- errp);
+ state->bitmap = block_dirty_bitmap_merge(action->node, action->target,
+ action->bitmaps, &state->backup,
+ errp);
}
-static BdrvDirtyBitmap *do_block_dirty_bitmap_remove(
- const char *node, const char *name, bool release,
- BlockDriverState **bitmap_bs, Error **errp);
-
static void block_dirty_bitmap_remove_prepare(BlkActionState *common,
Error **errp)
{
@@ -2211,8 +2155,8 @@
action = common->action->u.block_dirty_bitmap_remove.data;
- state->bitmap = do_block_dirty_bitmap_remove(action->node, action->name,
- false, &state->bs, errp);
+ state->bitmap = block_dirty_bitmap_remove(action->node, action->name,
+ false, &state->bs, errp);
if (state->bitmap) {
bdrv_dirty_bitmap_skip_store(state->bitmap, true);
bdrv_dirty_bitmap_set_busy(state->bitmap, true);
@@ -2441,243 +2385,6 @@
"Setting block passwords directly is no longer supported");
}
-void qmp_block_dirty_bitmap_add(const char *node, const char *name,
- bool has_granularity, uint32_t granularity,
- bool has_persistent, bool persistent,
- bool has_disabled, bool disabled,
- Error **errp)
-{
- BlockDriverState *bs;
- BdrvDirtyBitmap *bitmap;
- AioContext *aio_context;
-
- if (!name || name[0] == '\0') {
- error_setg(errp, "Bitmap name cannot be empty");
- return;
- }
-
- bs = bdrv_lookup_bs(node, node, errp);
- if (!bs) {
- return;
- }
-
- aio_context = bdrv_get_aio_context(bs);
- aio_context_acquire(aio_context);
-
- if (has_granularity) {
- if (granularity < 512 || !is_power_of_2(granularity)) {
- error_setg(errp, "Granularity must be power of 2 "
- "and at least 512");
- goto out;
- }
- } else {
- /* Default to cluster size, if available: */
- granularity = bdrv_get_default_bitmap_granularity(bs);
- }
-
- if (!has_persistent) {
- persistent = false;
- }
-
- if (!has_disabled) {
- disabled = false;
- }
-
- if (persistent &&
- !bdrv_can_store_new_dirty_bitmap(bs, name, granularity, errp))
- {
- goto out;
- }
-
- bitmap = bdrv_create_dirty_bitmap(bs, granularity, name, errp);
- if (bitmap == NULL) {
- goto out;
- }
-
- if (disabled) {
- bdrv_disable_dirty_bitmap(bitmap);
- }
-
- bdrv_dirty_bitmap_set_persistence(bitmap, persistent);
-
-out:
- aio_context_release(aio_context);
-}
-
-static BdrvDirtyBitmap *do_block_dirty_bitmap_remove(
- const char *node, const char *name, bool release,
- BlockDriverState **bitmap_bs, Error **errp)
-{
- BlockDriverState *bs;
- BdrvDirtyBitmap *bitmap;
- AioContext *aio_context;
-
- bitmap = block_dirty_bitmap_lookup(node, name, &bs, errp);
- if (!bitmap || !bs) {
- return NULL;
- }
-
- aio_context = bdrv_get_aio_context(bs);
- aio_context_acquire(aio_context);
-
- if (bdrv_dirty_bitmap_check(bitmap, BDRV_BITMAP_BUSY | BDRV_BITMAP_RO,
- errp)) {
- aio_context_release(aio_context);
- return NULL;
- }
-
- if (bdrv_dirty_bitmap_get_persistence(bitmap) &&
- bdrv_remove_persistent_dirty_bitmap(bs, name, errp) < 0)
- {
- aio_context_release(aio_context);
- return NULL;
- }
-
- if (release) {
- bdrv_release_dirty_bitmap(bitmap);
- }
-
- if (bitmap_bs) {
- *bitmap_bs = bs;
- }
-
- aio_context_release(aio_context);
- return release ? NULL : bitmap;
-}
-
-void qmp_block_dirty_bitmap_remove(const char *node, const char *name,
- Error **errp)
-{
- do_block_dirty_bitmap_remove(node, name, true, NULL, errp);
-}
-
-/**
- * Completely clear a bitmap, for the purposes of synchronizing a bitmap
- * immediately after a full backup operation.
- */
-void qmp_block_dirty_bitmap_clear(const char *node, const char *name,
- Error **errp)
-{
- BdrvDirtyBitmap *bitmap;
- BlockDriverState *bs;
-
- bitmap = block_dirty_bitmap_lookup(node, name, &bs, errp);
- if (!bitmap || !bs) {
- return;
- }
-
- if (bdrv_dirty_bitmap_check(bitmap, BDRV_BITMAP_DEFAULT, errp)) {
- return;
- }
-
- bdrv_clear_dirty_bitmap(bitmap, NULL);
-}
-
-void qmp_block_dirty_bitmap_enable(const char *node, const char *name,
- Error **errp)
-{
- BlockDriverState *bs;
- BdrvDirtyBitmap *bitmap;
-
- bitmap = block_dirty_bitmap_lookup(node, name, &bs, errp);
- if (!bitmap) {
- return;
- }
-
- if (bdrv_dirty_bitmap_check(bitmap, BDRV_BITMAP_ALLOW_RO, errp)) {
- return;
- }
-
- bdrv_enable_dirty_bitmap(bitmap);
-}
-
-void qmp_block_dirty_bitmap_disable(const char *node, const char *name,
- Error **errp)
-{
- BlockDriverState *bs;
- BdrvDirtyBitmap *bitmap;
-
- bitmap = block_dirty_bitmap_lookup(node, name, &bs, errp);
- if (!bitmap) {
- return;
- }
-
- if (bdrv_dirty_bitmap_check(bitmap, BDRV_BITMAP_ALLOW_RO, errp)) {
- return;
- }
-
- bdrv_disable_dirty_bitmap(bitmap);
-}
-
-static BdrvDirtyBitmap *do_block_dirty_bitmap_merge(
- const char *node, const char *target,
- BlockDirtyBitmapMergeSourceList *bitmaps,
- HBitmap **backup, Error **errp)
-{
- BlockDriverState *bs;
- BdrvDirtyBitmap *dst, *src, *anon;
- BlockDirtyBitmapMergeSourceList *lst;
- Error *local_err = NULL;
-
- dst = block_dirty_bitmap_lookup(node, target, &bs, errp);
- if (!dst) {
- return NULL;
- }
-
- anon = bdrv_create_dirty_bitmap(bs, bdrv_dirty_bitmap_granularity(dst),
- NULL, errp);
- if (!anon) {
- return NULL;
- }
-
- for (lst = bitmaps; lst; lst = lst->next) {
- switch (lst->value->type) {
- const char *name, *node;
- case QTYPE_QSTRING:
- name = lst->value->u.local;
- src = bdrv_find_dirty_bitmap(bs, name);
- if (!src) {
- error_setg(errp, "Dirty bitmap '%s' not found", name);
- dst = NULL;
- goto out;
- }
- break;
- case QTYPE_QDICT:
- node = lst->value->u.external.node;
- name = lst->value->u.external.name;
- src = block_dirty_bitmap_lookup(node, name, NULL, errp);
- if (!src) {
- dst = NULL;
- goto out;
- }
- break;
- default:
- abort();
- }
-
- bdrv_merge_dirty_bitmap(anon, src, NULL, &local_err);
- if (local_err) {
- error_propagate(errp, local_err);
- dst = NULL;
- goto out;
- }
- }
-
- /* Merge into dst; dst is unchanged on failure. */
- bdrv_merge_dirty_bitmap(dst, anon, backup, errp);
-
- out:
- bdrv_release_dirty_bitmap(anon);
- return dst;
-}
-
-void qmp_block_dirty_bitmap_merge(const char *node, const char *target,
- BlockDirtyBitmapMergeSourceList *bitmaps,
- Error **errp)
-{
- do_block_dirty_bitmap_merge(node, target, bitmaps, NULL, errp);
-}
-
BlockDirtyBitmapSha256 *qmp_x_debug_block_dirty_bitmap_sha256(const char *node,
const char *name,
Error **errp)
diff --git a/blockjob.c b/blockjob.c
index 2affa18..470facf 100644
--- a/blockjob.c
+++ b/blockjob.c
@@ -163,7 +163,7 @@
job->job.aio_context = ctx;
}
-static const BdrvChildRole child_job = {
+static const BdrvChildClass child_job = {
.get_parent_desc = child_job_get_parent_desc,
.drained_begin = child_job_drained_begin,
.drained_poll = child_job_drained_poll,
@@ -217,8 +217,9 @@
if (job->job.aio_context != qemu_get_aio_context()) {
aio_context_release(job->job.aio_context);
}
- c = bdrv_root_attach_child(bs, name, &child_job, job->job.aio_context,
- perm, shared_perm, job, errp);
+ c = bdrv_root_attach_child(bs, name, &child_job, 0,
+ job->job.aio_context, perm, shared_perm, job,
+ errp);
if (job->job.aio_context != qemu_get_aio_context()) {
aio_context_acquire(job->job.aio_context);
}
diff --git a/bootdevice.c b/bootdevice.c
index 03aaffc..0ff55e2 100644
--- a/bootdevice.c
+++ b/bootdevice.c
@@ -327,9 +327,8 @@
void device_add_bootindex_property(Object *obj, int32_t *bootindex,
const char *name, const char *suffix,
- DeviceState *dev, Error **errp)
+ DeviceState *dev)
{
- Error *local_err = NULL;
BootIndexProperty *prop = g_malloc0(sizeof(*prop));
prop->bootindex = bootindex;
@@ -340,13 +339,8 @@
device_get_bootindex,
device_set_bootindex,
property_release_bootindex,
- prop, &local_err);
+ prop);
- if (local_err) {
- error_propagate(errp, local_err);
- g_free(prop);
- return;
- }
/* initialize devices' bootindex property to -1 */
object_property_set_int(obj, -1, name, NULL);
}
diff --git a/bsd-user/main.c b/bsd-user/main.c
index 28f122b..0bfe46c 100644
--- a/bsd-user/main.c
+++ b/bsd-user/main.c
@@ -42,7 +42,7 @@
int singlestep;
unsigned long mmap_min_addr;
unsigned long guest_base;
-int have_guest_base;
+bool have_guest_base;
unsigned long reserved_va;
static const char *interp_prefix = CONFIG_QEMU_INTERP_PREFIX;
@@ -828,7 +828,7 @@
}
} else if (!strcmp(r, "B")) {
guest_base = strtol(argv[optind++], NULL, 0);
- have_guest_base = 1;
+ have_guest_base = true;
} else if (!strcmp(r, "drop-ld-preload")) {
(void) envlist_unsetenv(envlist, "LD_PRELOAD");
} else if (!strcmp(r, "bsd")) {
diff --git a/chardev/char-socket.c b/chardev/char-socket.c
index 185fe38..db253d4 100644
--- a/chardev/char-socket.c
+++ b/chardev/char-socket.c
@@ -138,8 +138,9 @@
SocketChardev *s = SOCKET_CHARDEV(chr);
if (!s->connect_err_reported) {
- error_report("Unable to connect character device %s: %s",
- chr->label, error_get_pretty(err));
+ error_reportf_err(err,
+ "Unable to connect character device %s: ",
+ chr->label);
s->connect_err_reported = true;
}
qemu_chr_socket_restart_timer(chr);
@@ -1380,6 +1381,8 @@
const char *host = qemu_opt_get(opts, "host");
const char *port = qemu_opt_get(opts, "port");
const char *fd = qemu_opt_get(opts, "fd");
+ bool tight = qemu_opt_get_bool(opts, "tight", true);
+ bool abstract = qemu_opt_get_bool(opts, "abstract", false);
SocketAddressLegacy *addr;
ChardevSocket *sock;
@@ -1431,6 +1434,8 @@
addr->type = SOCKET_ADDRESS_LEGACY_KIND_UNIX;
q_unix = addr->u.q_unix.data = g_new0(UnixSocketAddress, 1);
q_unix->path = g_strdup(path);
+ q_unix->tight = tight;
+ q_unix->abstract = abstract;
} else if (host) {
addr->type = SOCKET_ADDRESS_LEGACY_KIND_INET;
addr->u.inet.data = g_new(InetSocketAddress, 1);
@@ -1489,10 +1494,10 @@
object_class_property_add(oc, "addr", "SocketAddress",
char_socket_get_addr, NULL,
- NULL, NULL, &error_abort);
+ NULL, NULL);
object_class_property_add_bool(oc, "connected", char_socket_get_connected,
- NULL, &error_abort);
+ NULL);
}
static const TypeInfo char_socket_type_info = {
diff --git a/chardev/char.c b/chardev/char.c
index e775640..ea06c5f 100644
--- a/chardev/char.c
+++ b/chardev/char.c
@@ -939,6 +939,13 @@
},{
.name = "logappend",
.type = QEMU_OPT_BOOL,
+ },{
+ .name = "tight",
+ .type = QEMU_OPT_BOOL,
+ .def_value_str = "on",
+ },{
+ .name = "abstract",
+ .type = QEMU_OPT_BOOL,
},
{ /* end of list */ }
},
@@ -986,10 +993,7 @@
}
if (id) {
- object_property_add_child(get_chardevs_root(), id, obj, &local_err);
- if (local_err) {
- goto end;
- }
+ object_property_add_child(get_chardevs_root(), id, obj);
object_unref(obj);
}
@@ -1116,7 +1120,7 @@
object_unparent(OBJECT(chr));
object_property_add_child(get_chardevs_root(), chr_new->label,
- OBJECT(chr_new), &error_abort);
+ OBJECT(chr_new));
object_unref(OBJECT(chr_new));
ret = g_new0(ChardevReturn, 1);
diff --git a/configure b/configure
index 0d69c36..f087d2b 100755
--- a/configure
+++ b/configure
@@ -198,7 +198,7 @@
arm:arm | aarch64:aarch64 | \
i386:i386 | i386:x86_64 | i386:x32 | \
x86_64:i386 | x86_64:x86_64 | x86_64:x32 | \
- mips:mips | mipsel:mips | \
+ mips:mips | mipsel:mips | mips64:mips | mips64el:mips | \
ppc:ppc | ppc64:ppc | ppc:ppc64 | ppc64:ppc64 | ppc64:ppc64le | \
s390x:s390x)
return 0
@@ -941,7 +941,7 @@
# Check for ancillary tools used in testing
genisoimage=
-for binary in genisoimage
+for binary in genisoimage mkisofs
do
if has $binary
then
@@ -1861,7 +1861,7 @@
lzfse support of lzfse compression library
(for reading lzfse-compressed dmg images)
zstd support for zstd compression library
- (for migration compression)
+ (for migration compression and qcow2 cluster compression)
seccomp seccomp support
coroutine-pool coroutine freelist (better performance)
glusterfs GlusterFS backend
@@ -2897,7 +2897,7 @@
if test "$gtk" != "no"; then
gtkpackage="gtk+-3.0"
gtkx11package="gtk+-x11-3.0"
- gtkversion="3.14.0"
+ gtkversion="3.22.0"
if $pkg_config --exists "$gtkpackage >= $gtkversion"; then
gtk_cflags=$($pkg_config --cflags $gtkpackage)
gtk_libs=$($pkg_config --libs $gtkpackage)
@@ -3629,6 +3629,22 @@
oss_libs="$oss_lib"
;;
+ jack | try-jack)
+ if $pkg_config jack --exists; then
+ jack_libs=$($pkg_config jack --libs)
+ if test "$drv" = "try-jack"; then
+ audio_drv_list=$(echo "$audio_drv_list" | sed -e 's/try-jack/jack/')
+ fi
+ else
+ if test "$drv" = "try-jack"; then
+ audio_drv_list=$(echo "$audio_drv_list" | sed -e 's/try-jack//')
+ else
+ error_exit "$drv check failed" \
+ "Make sure to have the $drv libs and headers installed."
+ fi
+ fi
+ ;;
+
*)
echo "$audio_possible_drivers" | grep -q "\<$drv\>" || {
error_exit "Unknown driver '$drv' selected" \
@@ -6904,6 +6920,7 @@
echo "COREAUDIO_LIBS=$coreaudio_libs" >> $config_host_mak
echo "DSOUND_LIBS=$dsound_libs" >> $config_host_mak
echo "OSS_LIBS=$oss_libs" >> $config_host_mak
+echo "JACK_LIBS=$jack_libs" >> $config_host_mak
if test "$audio_win_int" = "yes" ; then
echo "CONFIG_AUDIO_WIN_INT=y" >> $config_host_mak
fi
@@ -7806,14 +7823,14 @@
TARGET_SYSTBL_ABI=common,oabi
bflt="yes"
mttcg="yes"
- gdb_xml_files="arm-core.xml arm-vfp.xml arm-vfp3.xml arm-neon.xml"
+ gdb_xml_files="arm-core.xml arm-vfp.xml arm-vfp3.xml arm-neon.xml arm-m-profile.xml"
;;
aarch64|aarch64_be)
TARGET_ARCH=aarch64
TARGET_BASE_ARCH=arm
bflt="yes"
mttcg="yes"
- gdb_xml_files="aarch64-core.xml aarch64-fpu.xml arm-core.xml arm-vfp.xml arm-vfp3.xml arm-neon.xml"
+ gdb_xml_files="aarch64-core.xml aarch64-fpu.xml arm-core.xml arm-vfp.xml arm-vfp3.xml arm-neon.xml arm-m-profile.xml"
;;
cris)
;;
diff --git a/cpus-common.c b/cpus-common.c
index 55d5df8..70a9d12 100644
--- a/cpus-common.c
+++ b/cpus-common.c
@@ -61,13 +61,15 @@
static int cpu_get_free_index(void)
{
CPUState *some_cpu;
- int cpu_index = 0;
+ int max_cpu_index = 0;
cpu_index_auto_assigned = true;
CPU_FOREACH(some_cpu) {
- cpu_index++;
+ if (some_cpu->cpu_index >= max_cpu_index) {
+ max_cpu_index = some_cpu->cpu_index + 1;
+ }
}
- return cpu_index;
+ return max_cpu_index;
}
void cpu_list_add(CPUState *cpu)
@@ -90,8 +92,6 @@
return;
}
- assert(!(cpu_index_auto_assigned && cpu != QTAILQ_LAST(&cpus)));
-
QTAILQ_REMOVE_RCU(&cpus, cpu, node);
cpu->cpu_index = UNASSIGNED_CPU_INDEX;
}
diff --git a/crypto/secret.c b/crypto/secret.c
index a846a3c..3107aec 100644
--- a/crypto/secret.c
+++ b/crypto/secret.c
@@ -369,30 +369,24 @@
object_class_property_add_bool(oc, "loaded",
qcrypto_secret_prop_get_loaded,
- qcrypto_secret_prop_set_loaded,
- NULL);
+ qcrypto_secret_prop_set_loaded);
object_class_property_add_enum(oc, "format",
"QCryptoSecretFormat",
&QCryptoSecretFormat_lookup,
qcrypto_secret_prop_get_format,
- qcrypto_secret_prop_set_format,
- NULL);
+ qcrypto_secret_prop_set_format);
object_class_property_add_str(oc, "data",
qcrypto_secret_prop_get_data,
- qcrypto_secret_prop_set_data,
- NULL);
+ qcrypto_secret_prop_set_data);
object_class_property_add_str(oc, "file",
qcrypto_secret_prop_get_file,
- qcrypto_secret_prop_set_file,
- NULL);
+ qcrypto_secret_prop_set_file);
object_class_property_add_str(oc, "keyid",
qcrypto_secret_prop_get_keyid,
- qcrypto_secret_prop_set_keyid,
- NULL);
+ qcrypto_secret_prop_set_keyid);
object_class_property_add_str(oc, "iv",
qcrypto_secret_prop_get_iv,
- qcrypto_secret_prop_set_iv,
- NULL);
+ qcrypto_secret_prop_set_iv);
}
diff --git a/crypto/tlscreds.c b/crypto/tlscreds.c
index 4e657b8..b68735f 100644
--- a/crypto/tlscreds.c
+++ b/crypto/tlscreds.c
@@ -226,22 +226,18 @@
{
object_class_property_add_bool(oc, "verify-peer",
qcrypto_tls_creds_prop_get_verify,
- qcrypto_tls_creds_prop_set_verify,
- NULL);
+ qcrypto_tls_creds_prop_set_verify);
object_class_property_add_str(oc, "dir",
qcrypto_tls_creds_prop_get_dir,
- qcrypto_tls_creds_prop_set_dir,
- NULL);
+ qcrypto_tls_creds_prop_set_dir);
object_class_property_add_enum(oc, "endpoint",
"QCryptoTLSCredsEndpoint",
&QCryptoTLSCredsEndpoint_lookup,
qcrypto_tls_creds_prop_get_endpoint,
- qcrypto_tls_creds_prop_set_endpoint,
- NULL);
+ qcrypto_tls_creds_prop_set_endpoint);
object_class_property_add_str(oc, "priority",
qcrypto_tls_creds_prop_get_priority,
- qcrypto_tls_creds_prop_set_priority,
- NULL);
+ qcrypto_tls_creds_prop_set_priority);
}
diff --git a/crypto/tlscredsanon.c b/crypto/tlscredsanon.c
index a235f60..fc078d5 100644
--- a/crypto/tlscredsanon.c
+++ b/crypto/tlscredsanon.c
@@ -187,8 +187,7 @@
object_class_property_add_bool(oc, "loaded",
qcrypto_tls_creds_anon_prop_get_loaded,
- qcrypto_tls_creds_anon_prop_set_loaded,
- NULL);
+ qcrypto_tls_creds_anon_prop_set_loaded);
}
diff --git a/crypto/tlscredspsk.c b/crypto/tlscredspsk.c
index 15d12e2..f01b64d 100644
--- a/crypto/tlscredspsk.c
+++ b/crypto/tlscredspsk.c
@@ -275,12 +275,10 @@
object_class_property_add_bool(oc, "loaded",
qcrypto_tls_creds_psk_prop_get_loaded,
- qcrypto_tls_creds_psk_prop_set_loaded,
- NULL);
+ qcrypto_tls_creds_psk_prop_set_loaded);
object_class_property_add_str(oc, "username",
qcrypto_tls_creds_psk_prop_get_username,
- qcrypto_tls_creds_psk_prop_set_username,
- NULL);
+ qcrypto_tls_creds_psk_prop_set_username);
}
diff --git a/crypto/tlscredsx509.c b/crypto/tlscredsx509.c
index 53a4368..e337d68 100644
--- a/crypto/tlscredsx509.c
+++ b/crypto/tlscredsx509.c
@@ -806,16 +806,13 @@
object_class_property_add_bool(oc, "loaded",
qcrypto_tls_creds_x509_prop_get_loaded,
- qcrypto_tls_creds_x509_prop_set_loaded,
- NULL);
+ qcrypto_tls_creds_x509_prop_set_loaded);
object_class_property_add_bool(oc, "sanity-check",
qcrypto_tls_creds_x509_prop_get_sanity,
- qcrypto_tls_creds_x509_prop_set_sanity,
- NULL);
+ qcrypto_tls_creds_x509_prop_set_sanity);
object_class_property_add_str(oc, "passwordid",
qcrypto_tls_creds_x509_prop_get_passwordid,
- qcrypto_tls_creds_x509_prop_set_passwordid,
- NULL);
+ qcrypto_tls_creds_x509_prop_set_passwordid);
}
diff --git a/default-configs/arm-softmmu.mak b/default-configs/arm-softmmu.mak
index 36a0e89..8fc09a4 100644
--- a/default-configs/arm-softmmu.mak
+++ b/default-configs/arm-softmmu.mak
@@ -42,3 +42,4 @@
CONFIG_FSL_IMX6UL=y
CONFIG_SEMIHOSTING=y
CONFIG_ALLWINNER_H3=y
+CONFIG_ACPI_APEI=y
diff --git a/default-configs/mips64el-softmmu.mak b/default-configs/mips64el-softmmu.mak
index 8b0c9b1..9f8a3ef 100644
--- a/default-configs/mips64el-softmmu.mak
+++ b/default-configs/mips64el-softmmu.mak
@@ -2,7 +2,7 @@
include mips-softmmu-common.mak
CONFIG_IDE_VIA=y
-CONFIG_FULONG=y
+CONFIG_FULOONG=y
CONFIG_ATI_VGA=y
CONFIG_RTL8139_PCI=y
CONFIG_JAZZ=y
diff --git a/disas.c b/disas.c
index 3937da6..45285d3 100644
--- a/disas.c
+++ b/disas.c
@@ -260,7 +260,8 @@
}
}
-static void cap_dump_insn(disassemble_info *info, cs_insn *insn)
+static void cap_dump_insn(disassemble_info *info, cs_insn *insn,
+ const char *note)
{
fprintf_function print = info->fprintf_func;
int i, n, split;
@@ -281,7 +282,11 @@
}
/* Print the actual instruction. */
- print(info->stream, " %-8s %s\n", insn->mnemonic, insn->op_str);
+ print(info->stream, " %-8s %s", insn->mnemonic, insn->op_str);
+ if (note) {
+ print(info->stream, "\t\t%s", note);
+ }
+ print(info->stream, "\n");
/* Dump any remaining part of the insn on subsequent lines. */
for (i = split; i < n; i += split) {
@@ -313,7 +318,7 @@
size -= tsize;
while (cs_disasm_iter(handle, &cbuf, &csize, &pc, insn)) {
- cap_dump_insn(info, insn);
+ cap_dump_insn(info, insn, NULL);
}
/* If the target memory is not consumed, go back for more... */
@@ -342,7 +347,8 @@
}
/* Disassemble SIZE bytes at CODE for the host. */
-static bool cap_disas_host(disassemble_info *info, void *code, size_t size)
+static bool cap_disas_host(disassemble_info *info, void *code, size_t size,
+ const char *note)
{
csh handle;
const uint8_t *cbuf;
@@ -358,7 +364,8 @@
pc = (uintptr_t)code;
while (cs_disasm_iter(handle, &cbuf, &size, &pc, insn)) {
- cap_dump_insn(info, insn);
+ cap_dump_insn(info, insn, note);
+ note = NULL;
}
if (size != 0) {
(*info->fprintf_func)(info->stream,
@@ -402,7 +409,7 @@
csize += tsize;
if (cs_disasm_iter(handle, &cbuf, &csize, &pc, insn)) {
- cap_dump_insn(info, insn);
+ cap_dump_insn(info, insn, NULL);
if (--count <= 0) {
break;
}
@@ -416,7 +423,7 @@
#endif /* !CONFIG_USER_ONLY */
#else
# define cap_disas_target(i, p, s) false
-# define cap_disas_host(i, p, s) false
+# define cap_disas_host(i, p, s, n) false
# define cap_disas_monitor(i, p, c) false
# define cap_disas_plugin(i, p, c) false
#endif /* CONFIG_CAPSTONE */
@@ -586,7 +593,7 @@
}
/* Disassemble this for me please... (debugging). */
-void disas(FILE *out, void *code, unsigned long size)
+void disas(FILE *out, void *code, unsigned long size, const char *note)
{
uintptr_t pc;
int count;
@@ -664,7 +671,7 @@
print_insn = print_insn_hppa;
#endif
- if (s.info.cap_arch >= 0 && cap_disas_host(&s.info, code, size)) {
+ if (s.info.cap_arch >= 0 && cap_disas_host(&s.info, code, size, note)) {
return;
}
@@ -674,10 +681,16 @@
for (pc = (uintptr_t)code; size > 0; pc += count, size -= count) {
fprintf(out, "0x%08" PRIxPTR ": ", pc);
count = print_insn(pc, &s.info);
- fprintf(out, "\n");
- if (count < 0)
- break;
+ if (note) {
+ fprintf(out, "\t\t%s", note);
+ note = NULL;
+ }
+ fprintf(out, "\n");
+ if (count < 0) {
+ break;
+ }
}
+
}
/* Look up symbol for debugging purpose. Returns "" if unknown. */
diff --git a/docs/interop/qcow2.txt b/docs/interop/qcow2.txt
index 298a031..cb72346 100644
--- a/docs/interop/qcow2.txt
+++ b/docs/interop/qcow2.txt
@@ -212,6 +212,7 @@
Available compression type values:
0: zlib <https://www.zlib.net/>
+ 1: zstd <http://github.com/facebook/zstd>
=== Header padding ===
diff --git a/docs/specs/acpi_hest_ghes.rst b/docs/specs/acpi_hest_ghes.rst
new file mode 100644
index 0000000..68f1fbe
--- /dev/null
+++ b/docs/specs/acpi_hest_ghes.rst
@@ -0,0 +1,110 @@
+APEI tables generating and CPER record
+======================================
+
+..
+ Copyright (c) 2020 HUAWEI TECHNOLOGIES CO., LTD.
+
+ This work is licensed under the terms of the GNU GPL, version 2 or later.
+ See the COPYING file in the top-level directory.
+
+Design Details
+--------------
+
+::
+
+ etc/acpi/tables etc/hardware_errors
+ ==================== ===============================
+ + +--------------------------+ +----------------------------+
+ | | HEST | +--------->| error_block_address1 |------+
+ | +--------------------------+ | +----------------------------+ |
+ | | GHES1 | | +------->| error_block_address2 |------+-+
+ | +--------------------------+ | | +----------------------------+ | |
+ | | ................. | | | | .............. | | |
+ | | error_status_address-----+-+ | -----------------------------+ | |
+ | | ................. | | +--->| error_block_addressN |------+-+---+
+ | | read_ack_register--------+-+ | | +----------------------------+ | | |
+ | | read_ack_preserve | +-+---+--->| read_ack_register1 | | | |
+ | | read_ack_write | | | +----------------------------+ | | |
+ + +--------------------------+ | +-+--->| read_ack_register2 | | | |
+ | | GHES2 | | | | +----------------------------+ | | |
+ + +--------------------------+ | | | | ............. | | | |
+ | | ................. | | | | +----------------------------+ | | |
+ | | error_status_address-----+---+ | | +->| read_ack_registerN | | | |
+ | | ................. | | | | +----------------------------+ | | |
+ | | read_ack_register--------+-----+ | | |Generic Error Status Block 1|<-----+ | |
+ | | read_ack_preserve | | | |-+------------------------+-+ | |
+ | | read_ack_write | | | | | CPER | | | |
+ + +--------------------------| | | | | CPER | | | |
+ | | ............... | | | | | .... | | | |
+ + +--------------------------+ | | | | CPER | | | |
+ | | GHESN | | | |-+------------------------+-| | |
+ + +--------------------------+ | | |Generic Error Status Block 2|<-------+ |
+ | | ................. | | | |-+------------------------+-+ |
+ | | error_status_address-----+-------+ | | | CPER | | |
+ | | ................. | | | | CPER | | |
+ | | read_ack_register--------+---------+ | | .... | | |
+ | | read_ack_preserve | | | CPER | | |
+ | | read_ack_write | +-+------------------------+-+ |
+ + +--------------------------+ | .......... | |
+ |----------------------------+ |
+ |Generic Error Status Block N |<----------+
+ |-+-------------------------+-+
+ | | CPER | |
+ | | CPER | |
+ | | .... | |
+ | | CPER | |
+ +-+-------------------------+-+
+
+
+(1) QEMU generates the ACPI HEST table. This table goes in the current
+ "etc/acpi/tables" fw_cfg blob. Each error source has different
+ notification types.
+
+(2) A new fw_cfg blob called "etc/hardware_errors" is introduced. QEMU
+ also needs to populate this blob. The "etc/hardware_errors" fw_cfg blob
+ contains an address registers table and an Error Status Data Block table.
+
+(3) The address registers table contains N Error Block Address entries
+ and N Read Ack Register entries. The size for each entry is 8-byte.
+ The Error Status Data Block table contains N Error Status Data Block
+ entries. The size for each entry is 4096(0x1000) bytes. The total size
+ for the "etc/hardware_errors" fw_cfg blob is (N * 8 * 2 + N * 4096) bytes.
+ N is the number of the kinds of hardware error sources.
+
+(4) QEMU generates the ACPI linker/loader script for the firmware. The
+ firmware pre-allocates memory for "etc/acpi/tables", "etc/hardware_errors"
+ and copies blob contents there.
+
+(5) QEMU generates N ADD_POINTER commands, which patch addresses in the
+ "error_status_address" fields of the HEST table with a pointer to the
+ corresponding "address registers" in the "etc/hardware_errors" blob.
+
+(6) QEMU generates N ADD_POINTER commands, which patch addresses in the
+ "read_ack_register" fields of the HEST table with a pointer to the
+ corresponding "read_ack_register" within the "etc/hardware_errors" blob.
+
+(7) QEMU generates N ADD_POINTER commands for the firmware, which patch
+ addresses in the "error_block_address" fields with a pointer to the
+ respective "Error Status Data Block" in the "etc/hardware_errors" blob.
+
+(8) QEMU defines a third and write-only fw_cfg blob which is called
+ "etc/hardware_errors_addr". Through that blob, the firmware can send back
+ the guest-side allocation addresses to QEMU. The "etc/hardware_errors_addr"
+ blob contains a 8-byte entry. QEMU generates a single WRITE_POINTER command
+ for the firmware. The firmware will write back the start address of
+ "etc/hardware_errors" blob to the fw_cfg file "etc/hardware_errors_addr".
+
+(9) When QEMU gets a SIGBUS from the kernel, QEMU writes CPER into corresponding
+ "Error Status Data Block", guest memory, and then injects platform specific
+ interrupt (in case of arm/virt machine it's Synchronous External Abort) as a
+ notification which is necessary for notifying the guest.
+
+(10) This notification (in virtual hardware) will be handled by the guest
+ kernel, on receiving notification, guest APEI driver could read the CPER error
+ and take appropriate action.
+
+(11) kvm_arch_on_sigbus_vcpu() uses source_id as index in "etc/hardware_errors" to
+ find out "Error Status Data Block" entry corresponding to error source. So supported
+ source_id values should be assigned here and not be changed afterwards to make sure
+ that guest will write error into expected "Error Status Data Block" even if guest was
+ migrated to a newer QEMU.
diff --git a/docs/specs/index.rst b/docs/specs/index.rst
index de46a8b..426632a 100644
--- a/docs/specs/index.rst
+++ b/docs/specs/index.rst
@@ -14,3 +14,4 @@
ppc-spapr-xive
acpi_hw_reduced_hotplug
tpm
+ acpi_hest_ghes
diff --git a/docs/system/arm/integratorcp.rst b/docs/system/arm/integratorcp.rst
index e6f050f..5944380 100644
--- a/docs/system/arm/integratorcp.rst
+++ b/docs/system/arm/integratorcp.rst
@@ -1,5 +1,5 @@
-Integrator/CP (``integratorcp``)
-================================
+Arm Integrator/CP (``integratorcp``)
+====================================
The Arm Integrator/CP board is emulated with the following devices:
diff --git a/docs/system/arm/mps2.rst b/docs/system/arm/mps2.rst
new file mode 100644
index 0000000..3a98cb5
--- /dev/null
+++ b/docs/system/arm/mps2.rst
@@ -0,0 +1,29 @@
+Arm MPS2 boards (``mps2-an385``, ``mps2-an505``, ``mps2-an511``, ``mps2-an521``)
+================================================================================
+
+These board models all use Arm M-profile CPUs.
+
+The Arm MPS2 and MPS2+ dev boards are FPGA based (the 2+ has a bigger
+FPGA but is otherwise the same as the 2). Since the CPU itself
+and most of the devices are in the FPGA, the details of the board
+as seen by the guest depend significantly on the FPGA image.
+
+QEMU models the following FPGA images:
+
+``mps2-an385``
+ Cortex-M3 as documented in ARM Application Note AN385
+``mps2-an511``
+ Cortex-M3 'DesignStart' as documented in AN511
+``mps2-an505``
+ Cortex-M33 as documented in ARM Application Note AN505
+``mps2-an521``
+ Dual Cortex-M33 as documented in Application Note AN521
+
+Differences between QEMU and real hardware:
+
+- AN385 remapping of low 16K of memory to either ZBT SSRAM1 or to
+ block RAM is unimplemented (QEMU always maps this to ZBT SSRAM1, as
+ if zbt_boot_ctrl is always zero)
+- QEMU provides a LAN9118 ethernet rather than LAN9220; the only guest
+ visible difference is that the LAN9118 doesn't support checksum
+ offloading
diff --git a/docs/system/arm/musca.rst b/docs/system/arm/musca.rst
new file mode 100644
index 0000000..81e3dc9
--- /dev/null
+++ b/docs/system/arm/musca.rst
@@ -0,0 +1,31 @@
+Arm Musca boards (``musca-a``, ``musca-b1``)
+============================================
+
+The Arm Musca development boards are a reference implementation
+of a system using the SSE-200 Subsystem for Embedded. They are
+dual Cortex-M33 systems.
+
+QEMU provides models of the A and B1 variants of this board.
+
+Unimplemented devices:
+
+- SPI
+- |I2C|
+- |I2S|
+- PWM
+- QSPI
+- Timer
+- SCC
+- GPIO
+- eFlash
+- MHU
+- PVT
+- SDIO
+- CryptoCell
+
+Note that (like the real hardware) the Musca-A machine is
+asymmetric: CPU 0 does not have the FPU or DSP extensions,
+but CPU 1 does. Also like the real hardware, the memory maps
+for the A and B1 variants differ significantly, so guest
+software must be built for the right variant.
+
diff --git a/docs/system/arm/vexpress.rst b/docs/system/arm/vexpress.rst
new file mode 100644
index 0000000..7f1bcbe
--- /dev/null
+++ b/docs/system/arm/vexpress.rst
@@ -0,0 +1,60 @@
+Arm Versatile Express boards (``vexpress-a9``, ``vexpress-a15``)
+================================================================
+
+QEMU models two variants of the Arm Versatile Express development
+board family:
+
+- ``vexpress-a9`` models the combination of the Versatile Express
+ motherboard and the CoreTile Express A9x4 daughterboard
+- ``vexpress-a15`` models the combination of the Versatile Express
+ motherboard and the CoreTile Express A15x2 daughterboard
+
+Note that as this hardware does not have PCI, IDE or SCSI,
+the only available storage option is emulated SD card.
+
+Implemented devices:
+
+- PL041 audio
+- PL181 SD controller
+- PL050 keyboard and mouse
+- PL011 UARTs
+- SP804 timers
+- I2C controller
+- PL031 RTC
+- PL111 LCD display controller
+- Flash memory
+- LAN9118 ethernet
+
+Unimplemented devices:
+
+- SP810 system control block
+- PCI-express
+- USB controller (Philips ISP1761)
+- Local DAP ROM
+- CoreSight interfaces
+- PL301 AXI interconnect
+- SCC
+- System counter
+- HDLCD controller (``vexpress-a15``)
+- SP805 watchdog
+- PL341 dynamic memory controller
+- DMA330 DMA controller
+- PL354 static memory controller
+- BP147 TrustZone Protection Controller
+- TrustZone Address Space Controller
+
+Other differences between the hardware and the QEMU model:
+
+- QEMU will default to creating one CPU unless you pass a different
+ ``-smp`` argument
+- QEMU allows the amount of RAM provided to be specified with the
+ ``-m`` argument
+- QEMU defaults to providing a CPU which does not provide either
+ TrustZone or the Virtualization Extensions: if you want these you
+ must enable them with ``-machine secure=on`` and ``-machine
+ virtualization=on``
+- QEMU provides 4 virtio-mmio virtio transports; these start at
+ address ``0x10013000`` for ``vexpress-a9`` and at ``0x1c130000`` for
+ ``vexpress-a15``, and have IRQs from 40 upwards. If a dtb is
+ provided on the command line then QEMU will edit it to include
+ suitable entries describing these transports for the guest.
diff --git a/docs/system/deprecated.rst b/docs/system/deprecated.rst
index 3142fac..f0061f9 100644
--- a/docs/system/deprecated.rst
+++ b/docs/system/deprecated.rst
@@ -368,6 +368,11 @@
This machine type is very old and unmaintained. Users should use the ``malta``
machine type instead.
+mips ``fulong2e`` machine (since 5.1)
+'''''''''''''''''''''''''''''''''''''
+
+This machine has been renamed ``fuloong2e``.
+
``pc-1.0``, ``pc-1.1``, ``pc-1.2`` and ``pc-1.3`` (since 5.0)
'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
diff --git a/docs/system/target-arm.rst b/docs/system/target-arm.rst
index 324e2af..dce384c 100644
--- a/docs/system/target-arm.rst
+++ b/docs/system/target-arm.rst
@@ -67,19 +67,27 @@
undocumented; you can get a complete list by running
``qemu-system-aarch64 --machine help``.
+..
+ This table of contents should be kept sorted alphabetically
+ by the title text of each file, which isn't the same ordering
+ as an alphabetical sort by filename.
+
.. toctree::
:maxdepth: 1
arm/integratorcp
- arm/versatile
+ arm/mps2
+ arm/musca
arm/realview
- arm/xscale
- arm/palm
- arm/nseries
- arm/stellaris
+ arm/versatile
+ arm/vexpress
arm/musicpal
- arm/sx1
+ arm/nseries
arm/orangepi
+ arm/palm
+ arm/xscale
+ arm/sx1
+ arm/stellaris
Arm CPU features
================
diff --git a/docs/system/target-mips.rst b/docs/system/target-mips.rst
index 2736fd0..cd2a931 100644
--- a/docs/system/target-mips.rst
+++ b/docs/system/target-mips.rst
@@ -74,7 +74,7 @@
- G364 framebuffer
-The Fulong 2E emulation supports:
+The Fuloong 2E emulation supports:
- Loongson 2E CPU
diff --git a/docs/tools/qemu-img.rst b/docs/tools/qemu-img.rst
index 0080f83..69cd9a3 100644
--- a/docs/tools/qemu-img.rst
+++ b/docs/tools/qemu-img.rst
@@ -142,30 +142,6 @@
the documentation of the emulator's ``-drive cache=...`` option for allowed
values.
-Parameters to snapshot subcommand:
-
-.. program:: qemu-img-snapshot
-
-.. option:: snapshot
-
- Is the name of the snapshot to create, apply or delete
-
-.. option:: -a
-
- Applies a snapshot (revert disk to saved state)
-
-.. option:: -c
-
- Creates a snapshot
-
-.. option:: -d
-
- Deletes a snapshot
-
-.. option:: -l
-
- Lists all snapshots in the given image
-
Parameters to compare subcommand:
.. program:: qemu-img-compare
@@ -186,6 +162,10 @@
.. program:: qemu-img-convert
+.. option:: --bitmaps
+
+ Additionally copy all persistent bitmaps from the top layer of the source
+
.. option:: -n
Skip the creation of the target volume
@@ -245,6 +225,30 @@
Sets the number of input blocks to skip
+Parameters to snapshot subcommand:
+
+.. program:: qemu-img-snapshot
+
+.. option:: snapshot
+
+ Is the name of the snapshot to create, apply or delete
+
+.. option:: -a
+
+ Applies a snapshot (revert disk to saved state)
+
+.. option:: -c
+
+ Creates a snapshot
+
+.. option:: -d
+
+ Deletes a snapshot
+
+.. option:: -l
+
+ Lists all snapshots in the given image
+
Command description:
.. program:: qemu-img-commands
@@ -281,6 +285,30 @@
For write tests, by default a buffer filled with zeros is written. This can be
overridden with a pattern byte specified by *PATTERN*.
+.. option:: bitmap (--merge SOURCE | --add | --remove | --clear | --enable | --disable)... [-b SOURCE_FILE [-F SOURCE_FMT]] [-g GRANULARITY] [--object OBJECTDEF] [--image-opts | -f FMT] FILENAME BITMAP
+
+ Perform one or more modifications of the persistent bitmap *BITMAP*
+ in the disk image *FILENAME*. The various modifications are:
+
+ ``--add`` to create *BITMAP*, enabled to record future edits.
+
+ ``--remove`` to remove *BITMAP*.
+
+ ``--clear`` to clear *BITMAP*.
+
+ ``--enable`` to change *BITMAP* to start recording future edits.
+
+ ``--disable`` to change *BITMAP* to stop recording future edits.
+
+ ``--merge`` to merge the contents of *SOURCE_BITMAP* into *BITMAP*.
+
+ Additional options include ``-g`` which sets a non-default
+ *GRANULARITY* for ``--add``, and ``-b`` and ``-F`` which select an
+ alternative source file for all *SOURCE* bitmaps used by
+ ``--merge``.
+
+ To see what bitmaps are present in an image, use ``qemu-img info``.
+
.. option:: check [--object OBJECTDEF] [--image-opts] [-q] [-f FMT] [--output=OFMT] [-r [leaks | all]] [-T SRC_CACHE] [-U] FILENAME
Perform a consistency check on the disk image *FILENAME*. The command can
@@ -373,7 +401,7 @@
4
Error on reading data
-.. option:: convert [--object OBJECTDEF] [--image-opts] [--target-image-opts] [--target-is-zero] [-U] [-C] [-c] [-p] [-q] [-n] [-f FMT] [-t CACHE] [-T SRC_CACHE] [-O OUTPUT_FMT] [-B BACKING_FILE] [-o OPTIONS] [-l SNAPSHOT_PARAM] [-S SPARSE_SIZE] [-m NUM_COROUTINES] [-W] FILENAME [FILENAME2 [...]] OUTPUT_FILENAME
+.. option:: convert [--object OBJECTDEF] [--image-opts] [--target-image-opts] [--target-is-zero] [--bitmaps] [-U] [-C] [-c] [-p] [-q] [-n] [-f FMT] [-t CACHE] [-T SRC_CACHE] [-O OUTPUT_FMT] [-B BACKING_FILE] [-o OPTIONS] [-l SNAPSHOT_PARAM] [-S SPARSE_SIZE] [-m NUM_COROUTINES] [-W] FILENAME [FILENAME2 [...]] OUTPUT_FILENAME
Convert the disk image *FILENAME* or a snapshot *SNAPSHOT_PARAM*
to disk image *OUTPUT_FILENAME* using format *OUTPUT_FMT*. It can
@@ -519,7 +547,7 @@
``ImageInfoSpecific*`` QAPI object (e.g. ``ImageInfoSpecificQCow2``
for qcow2 images).
-.. option:: map [--object OBJECTDEF] [--image-opts] [-f FMT] [--output=OFMT] [-U] FILENAME
+.. option:: map [--object OBJECTDEF] [--image-opts] [-f FMT] [--start-offset=OFFSET] [--max-length=LEN] [--output=OFMT] [-U] FILENAME
Dump the metadata of image *FILENAME* and its backing file chain.
In particular, this commands dumps the allocation state of every sector
@@ -592,6 +620,7 @@
required size: 524288
fully allocated size: 1074069504
+ bitmaps size: 0
The ``required size`` is the file size of the new image. It may be smaller
than the virtual disk size if the image format supports compact representation.
@@ -601,6 +630,12 @@
occupy with the exception of internal snapshots, dirty bitmaps, vmstate data,
and other advanced image format features.
+ The ``bitmaps size`` is the additional size required in order to
+ copy bitmaps from a source image in addition to the guest-visible
+ data; the line is omitted if either source or destination lacks
+ bitmap support, or 0 if bitmaps are supported but there is nothing
+ to copy.
+
.. option:: snapshot [--object OBJECTDEF] [--image-opts] [-U] [-q] [-l | -a SNAPSHOT | -c SNAPSHOT | -d SNAPSHOT] FILENAME
List, apply, create or delete snapshots in image *FILENAME*.
diff --git a/fpu/softfloat-specialize.inc.c b/fpu/softfloat-specialize.inc.c
index 5ab2fa1..44f5b66 100644
--- a/fpu/softfloat-specialize.inc.c
+++ b/fpu/softfloat-specialize.inc.c
@@ -93,7 +93,7 @@
* 2008 revision and backward compatibility with their original choice.
* Thus for MIPS we must make the choice at runtime.
*/
-static inline flag snan_bit_is_one(float_status *status)
+static inline bool snan_bit_is_one(float_status *status)
{
#if defined(TARGET_MIPS)
return status->snan_bit_is_one;
@@ -114,7 +114,7 @@
#ifdef NO_SIGNALING_NANS
return false;
#else
- flag msb = extract64(frac, DECOMPOSED_BINARY_POINT - 1, 1);
+ bool msb = extract64(frac, DECOMPOSED_BINARY_POINT - 1, 1);
return msb == snan_bit_is_one(status);
#endif
}
@@ -236,7 +236,7 @@
| Internal canonical NaN format.
*----------------------------------------------------------------------------*/
typedef struct {
- flag sign;
+ bool sign;
uint64_t high, low;
} commonNaNT;
@@ -245,7 +245,7 @@
| NaN; otherwise returns 0.
*----------------------------------------------------------------------------*/
-int float16_is_quiet_nan(float16 a_, float_status *status)
+bool float16_is_quiet_nan(float16 a_, float_status *status)
{
#ifdef NO_SIGNALING_NANS
return float16_is_any_nan(a_);
@@ -264,7 +264,7 @@
| NaN; otherwise returns 0.
*----------------------------------------------------------------------------*/
-int float16_is_signaling_nan(float16 a_, float_status *status)
+bool float16_is_signaling_nan(float16 a_, float_status *status)
{
#ifdef NO_SIGNALING_NANS
return 0;
@@ -283,7 +283,7 @@
| NaN; otherwise returns 0.
*----------------------------------------------------------------------------*/
-int float32_is_quiet_nan(float32 a_, float_status *status)
+bool float32_is_quiet_nan(float32 a_, float_status *status)
{
#ifdef NO_SIGNALING_NANS
return float32_is_any_nan(a_);
@@ -302,7 +302,7 @@
| NaN; otherwise returns 0.
*----------------------------------------------------------------------------*/
-int float32_is_signaling_nan(float32 a_, float_status *status)
+bool float32_is_signaling_nan(float32 a_, float_status *status)
{
#ifdef NO_SIGNALING_NANS
return 0;
@@ -374,7 +374,7 @@
*----------------------------------------------------------------------------*/
static int pickNaN(FloatClass a_cls, FloatClass b_cls,
- flag aIsLargerSignificand)
+ bool aIsLargerSignificand)
{
#if defined(TARGET_ARM) || defined(TARGET_MIPS) || defined(TARGET_HPPA)
/* ARM mandated NaN propagation rules (see FPProcessNaNs()), take
@@ -584,7 +584,7 @@
static float32 propagateFloat32NaN(float32 a, float32 b, float_status *status)
{
- flag aIsLargerSignificand;
+ bool aIsLargerSignificand;
uint32_t av, bv;
FloatClass a_cls, b_cls;
@@ -637,7 +637,7 @@
| NaN; otherwise returns 0.
*----------------------------------------------------------------------------*/
-int float64_is_quiet_nan(float64 a_, float_status *status)
+bool float64_is_quiet_nan(float64 a_, float_status *status)
{
#ifdef NO_SIGNALING_NANS
return float64_is_any_nan(a_);
@@ -657,7 +657,7 @@
| NaN; otherwise returns 0.
*----------------------------------------------------------------------------*/
-int float64_is_signaling_nan(float64 a_, float_status *status)
+bool float64_is_signaling_nan(float64 a_, float_status *status)
{
#ifdef NO_SIGNALING_NANS
return 0;
@@ -722,7 +722,7 @@
static float64 propagateFloat64NaN(float64 a, float64 b, float_status *status)
{
- flag aIsLargerSignificand;
+ bool aIsLargerSignificand;
uint64_t av, bv;
FloatClass a_cls, b_cls;
@@ -890,7 +890,7 @@
floatx80 propagateFloatx80NaN(floatx80 a, floatx80 b, float_status *status)
{
- flag aIsLargerSignificand;
+ bool aIsLargerSignificand;
FloatClass a_cls, b_cls;
/* This is not complete, but is good enough for pickNaN. */
@@ -939,7 +939,7 @@
| NaN; otherwise returns 0.
*----------------------------------------------------------------------------*/
-int float128_is_quiet_nan(float128 a, float_status *status)
+bool float128_is_quiet_nan(float128 a, float_status *status)
{
#ifdef NO_SIGNALING_NANS
return float128_is_any_nan(a);
@@ -959,7 +959,7 @@
| signaling NaN; otherwise returns 0.
*----------------------------------------------------------------------------*/
-int float128_is_signaling_nan(float128 a, float_status *status)
+bool float128_is_signaling_nan(float128 a, float_status *status)
{
#ifdef NO_SIGNALING_NANS
return 0;
@@ -1038,7 +1038,7 @@
static float128 propagateFloat128NaN(float128 a, float128 b,
float_status *status)
{
- flag aIsLargerSignificand;
+ bool aIsLargerSignificand;
FloatClass a_cls, b_cls;
/* This is not complete, but is good enough for pickNaN. */
diff --git a/fpu/softfloat.c b/fpu/softfloat.c
index ae6ba71..6c8f2d5 100644
--- a/fpu/softfloat.c
+++ b/fpu/softfloat.c
@@ -339,12 +339,10 @@
return float64_is_infinity(a.s);
}
-/* Note: @fast_test and @post can be NULL */
static inline float32
float32_gen2(float32 xa, float32 xb, float_status *s,
hard_f32_op2_fn hard, soft_f32_op2_fn soft,
- f32_check_fn pre, f32_check_fn post,
- f32_check_fn fast_test, soft_f32_op2_fn fast_op)
+ f32_check_fn pre, f32_check_fn post)
{
union_float32 ua, ub, ur;
@@ -359,17 +357,12 @@
if (unlikely(!pre(ua, ub))) {
goto soft;
}
- if (fast_test && fast_test(ua, ub)) {
- return fast_op(ua.s, ub.s, s);
- }
ur.h = hard(ua.h, ub.h);
if (unlikely(f32_is_inf(ur))) {
s->float_exception_flags |= float_flag_overflow;
- } else if (unlikely(fabsf(ur.h) <= FLT_MIN)) {
- if (post == NULL || post(ua, ub)) {
- goto soft;
- }
+ } else if (unlikely(fabsf(ur.h) <= FLT_MIN) && post(ua, ub)) {
+ goto soft;
}
return ur.s;
@@ -380,8 +373,7 @@
static inline float64
float64_gen2(float64 xa, float64 xb, float_status *s,
hard_f64_op2_fn hard, soft_f64_op2_fn soft,
- f64_check_fn pre, f64_check_fn post,
- f64_check_fn fast_test, soft_f64_op2_fn fast_op)
+ f64_check_fn pre, f64_check_fn post)
{
union_float64 ua, ub, ur;
@@ -396,17 +388,12 @@
if (unlikely(!pre(ua, ub))) {
goto soft;
}
- if (fast_test && fast_test(ua, ub)) {
- return fast_op(ua.s, ub.s, s);
- }
ur.h = hard(ua.h, ub.h);
if (unlikely(f64_is_inf(ur))) {
s->float_exception_flags |= float_flag_overflow;
- } else if (unlikely(fabs(ur.h) <= DBL_MIN)) {
- if (post == NULL || post(ua, ub)) {
- goto soft;
- }
+ } else if (unlikely(fabs(ur.h) <= DBL_MIN) && post(ua, ub)) {
+ goto soft;
}
return ur.s;
@@ -436,7 +423,7 @@
| Returns the sign bit of the single-precision floating-point value `a'.
*----------------------------------------------------------------------------*/
-static inline flag extractFloat32Sign(float32 a)
+static inline bool extractFloat32Sign(float32 a)
{
return float32_val(a) >> 31;
}
@@ -463,7 +450,7 @@
| Returns the sign bit of the double-precision floating-point value `a'.
*----------------------------------------------------------------------------*/
-static inline flag extractFloat64Sign(float64 a)
+static inline bool extractFloat64Sign(float64 a)
{
return float64_val(a) >> 63;
}
@@ -757,8 +744,7 @@
p.cls = float_class_zero;
goto do_zero;
} else {
- bool is_tiny = (s->float_detect_tininess
- == float_tininess_before_rounding)
+ bool is_tiny = s->tininess_before_rounding
|| (exp < 0)
|| !((frac + inc) & DECOMPOSED_OVERFLOW_BIT);
@@ -773,6 +759,8 @@
case float_round_to_odd:
inc = frac & frac_lsb ? 0 : round_mask;
break;
+ default:
+ break;
}
flags |= float_flag_inexact;
frac += inc;
@@ -1115,7 +1103,7 @@
return a - b;
}
-static bool f32_addsub_post(union_float32 a, union_float32 b)
+static bool f32_addsubmul_post(union_float32 a, union_float32 b)
{
if (QEMU_HARDFLOAT_2F32_USE_FP) {
return !(fpclassify(a.h) == FP_ZERO && fpclassify(b.h) == FP_ZERO);
@@ -1123,7 +1111,7 @@
return !(float32_is_zero(a.s) && float32_is_zero(b.s));
}
-static bool f64_addsub_post(union_float64 a, union_float64 b)
+static bool f64_addsubmul_post(union_float64 a, union_float64 b)
{
if (QEMU_HARDFLOAT_2F64_USE_FP) {
return !(fpclassify(a.h) == FP_ZERO && fpclassify(b.h) == FP_ZERO);
@@ -1136,14 +1124,14 @@
hard_f32_op2_fn hard, soft_f32_op2_fn soft)
{
return float32_gen2(a, b, s, hard, soft,
- f32_is_zon2, f32_addsub_post, NULL, NULL);
+ f32_is_zon2, f32_addsubmul_post);
}
static float64 float64_addsub(float64 a, float64 b, float_status *s,
hard_f64_op2_fn hard, soft_f64_op2_fn soft)
{
return float64_gen2(a, b, s, hard, soft,
- f64_is_zon2, f64_addsub_post, NULL, NULL);
+ f64_is_zon2, f64_addsubmul_post);
}
float32 QEMU_FLATTEN
@@ -1258,42 +1246,18 @@
return a * b;
}
-static bool f32_mul_fast_test(union_float32 a, union_float32 b)
-{
- return float32_is_zero(a.s) || float32_is_zero(b.s);
-}
-
-static bool f64_mul_fast_test(union_float64 a, union_float64 b)
-{
- return float64_is_zero(a.s) || float64_is_zero(b.s);
-}
-
-static float32 f32_mul_fast_op(float32 a, float32 b, float_status *s)
-{
- bool signbit = float32_is_neg(a) ^ float32_is_neg(b);
-
- return float32_set_sign(float32_zero, signbit);
-}
-
-static float64 f64_mul_fast_op(float64 a, float64 b, float_status *s)
-{
- bool signbit = float64_is_neg(a) ^ float64_is_neg(b);
-
- return float64_set_sign(float64_zero, signbit);
-}
-
float32 QEMU_FLATTEN
float32_mul(float32 a, float32 b, float_status *s)
{
return float32_gen2(a, b, s, hard_f32_mul, soft_f32_mul,
- f32_is_zon2, NULL, f32_mul_fast_test, f32_mul_fast_op);
+ f32_is_zon2, f32_addsubmul_post);
}
float64 QEMU_FLATTEN
float64_mul(float64 a, float64 b, float_status *s)
{
return float64_gen2(a, b, s, hard_f64_mul, soft_f64_mul,
- f64_is_zon2, NULL, f64_mul_fast_test, f64_mul_fast_op);
+ f64_is_zon2, f64_addsubmul_post);
}
/*
@@ -1834,14 +1798,14 @@
float32_div(float32 a, float32 b, float_status *s)
{
return float32_gen2(a, b, s, hard_f32_div, soft_f32_div,
- f32_div_pre, f32_div_post, NULL, NULL);
+ f32_div_pre, f32_div_post);
}
float64 QEMU_FLATTEN
float64_div(float64 a, float64 b, float_status *s)
{
return float64_gen2(a, b, s, hard_f64_div, soft_f64_div,
- f64_div_pre, f64_div_post, NULL, NULL);
+ f64_div_pre, f64_div_post);
}
/*
@@ -1966,7 +1930,7 @@
* Arithmetic.
*/
-static FloatParts round_to_int(FloatParts a, int rmode,
+static FloatParts round_to_int(FloatParts a, FloatRoundMode rmode,
int scale, float_status *s)
{
switch (a.cls) {
@@ -2099,8 +2063,8 @@
* is returned.
*/
-static int64_t round_to_int_and_pack(FloatParts in, int rmode, int scale,
- int64_t min, int64_t max,
+static int64_t round_to_int_and_pack(FloatParts in, FloatRoundMode rmode,
+ int scale, int64_t min, int64_t max,
float_status *s)
{
uint64_t r;
@@ -2145,63 +2109,63 @@
}
}
-int16_t float16_to_int16_scalbn(float16 a, int rmode, int scale,
+int16_t float16_to_int16_scalbn(float16 a, FloatRoundMode rmode, int scale,
float_status *s)
{
return round_to_int_and_pack(float16_unpack_canonical(a, s),
rmode, scale, INT16_MIN, INT16_MAX, s);
}
-int32_t float16_to_int32_scalbn(float16 a, int rmode, int scale,
+int32_t float16_to_int32_scalbn(float16 a, FloatRoundMode rmode, int scale,
float_status *s)
{
return round_to_int_and_pack(float16_unpack_canonical(a, s),
rmode, scale, INT32_MIN, INT32_MAX, s);
}
-int64_t float16_to_int64_scalbn(float16 a, int rmode, int scale,
+int64_t float16_to_int64_scalbn(float16 a, FloatRoundMode rmode, int scale,
float_status *s)
{
return round_to_int_and_pack(float16_unpack_canonical(a, s),
rmode, scale, INT64_MIN, INT64_MAX, s);
}
-int16_t float32_to_int16_scalbn(float32 a, int rmode, int scale,
+int16_t float32_to_int16_scalbn(float32 a, FloatRoundMode rmode, int scale,
float_status *s)
{
return round_to_int_and_pack(float32_unpack_canonical(a, s),
rmode, scale, INT16_MIN, INT16_MAX, s);
}
-int32_t float32_to_int32_scalbn(float32 a, int rmode, int scale,
+int32_t float32_to_int32_scalbn(float32 a, FloatRoundMode rmode, int scale,
float_status *s)
{
return round_to_int_and_pack(float32_unpack_canonical(a, s),
rmode, scale, INT32_MIN, INT32_MAX, s);
}
-int64_t float32_to_int64_scalbn(float32 a, int rmode, int scale,
+int64_t float32_to_int64_scalbn(float32 a, FloatRoundMode rmode, int scale,
float_status *s)
{
return round_to_int_and_pack(float32_unpack_canonical(a, s),
rmode, scale, INT64_MIN, INT64_MAX, s);
}
-int16_t float64_to_int16_scalbn(float64 a, int rmode, int scale,
+int16_t float64_to_int16_scalbn(float64 a, FloatRoundMode rmode, int scale,
float_status *s)
{
return round_to_int_and_pack(float64_unpack_canonical(a, s),
rmode, scale, INT16_MIN, INT16_MAX, s);
}
-int32_t float64_to_int32_scalbn(float64 a, int rmode, int scale,
+int32_t float64_to_int32_scalbn(float64 a, FloatRoundMode rmode, int scale,
float_status *s)
{
return round_to_int_and_pack(float64_unpack_canonical(a, s),
rmode, scale, INT32_MIN, INT32_MAX, s);
}
-int64_t float64_to_int64_scalbn(float64 a, int rmode, int scale,
+int64_t float64_to_int64_scalbn(float64 a, FloatRoundMode rmode, int scale,
float_status *s)
{
return round_to_int_and_pack(float64_unpack_canonical(a, s),
@@ -2311,8 +2275,9 @@
* flag.
*/
-static uint64_t round_to_uint_and_pack(FloatParts in, int rmode, int scale,
- uint64_t max, float_status *s)
+static uint64_t round_to_uint_and_pack(FloatParts in, FloatRoundMode rmode,
+ int scale, uint64_t max,
+ float_status *s)
{
int orig_flags = get_float_exception_flags(s);
FloatParts p = round_to_int(in, rmode, scale, s);
@@ -2357,63 +2322,63 @@
}
}
-uint16_t float16_to_uint16_scalbn(float16 a, int rmode, int scale,
+uint16_t float16_to_uint16_scalbn(float16 a, FloatRoundMode rmode, int scale,
float_status *s)
{
return round_to_uint_and_pack(float16_unpack_canonical(a, s),
rmode, scale, UINT16_MAX, s);
}
-uint32_t float16_to_uint32_scalbn(float16 a, int rmode, int scale,
+uint32_t float16_to_uint32_scalbn(float16 a, FloatRoundMode rmode, int scale,
float_status *s)
{
return round_to_uint_and_pack(float16_unpack_canonical(a, s),
rmode, scale, UINT32_MAX, s);
}
-uint64_t float16_to_uint64_scalbn(float16 a, int rmode, int scale,
+uint64_t float16_to_uint64_scalbn(float16 a, FloatRoundMode rmode, int scale,
float_status *s)
{
return round_to_uint_and_pack(float16_unpack_canonical(a, s),
rmode, scale, UINT64_MAX, s);
}
-uint16_t float32_to_uint16_scalbn(float32 a, int rmode, int scale,
+uint16_t float32_to_uint16_scalbn(float32 a, FloatRoundMode rmode, int scale,
float_status *s)
{
return round_to_uint_and_pack(float32_unpack_canonical(a, s),
rmode, scale, UINT16_MAX, s);
}
-uint32_t float32_to_uint32_scalbn(float32 a, int rmode, int scale,
+uint32_t float32_to_uint32_scalbn(float32 a, FloatRoundMode rmode, int scale,
float_status *s)
{
return round_to_uint_and_pack(float32_unpack_canonical(a, s),
rmode, scale, UINT32_MAX, s);
}
-uint64_t float32_to_uint64_scalbn(float32 a, int rmode, int scale,
+uint64_t float32_to_uint64_scalbn(float32 a, FloatRoundMode rmode, int scale,
float_status *s)
{
return round_to_uint_and_pack(float32_unpack_canonical(a, s),
rmode, scale, UINT64_MAX, s);
}
-uint16_t float64_to_uint16_scalbn(float64 a, int rmode, int scale,
+uint16_t float64_to_uint16_scalbn(float64 a, FloatRoundMode rmode, int scale,
float_status *s)
{
return round_to_uint_and_pack(float64_unpack_canonical(a, s),
rmode, scale, UINT16_MAX, s);
}
-uint32_t float64_to_uint32_scalbn(float64 a, int rmode, int scale,
+uint32_t float64_to_uint32_scalbn(float64 a, FloatRoundMode rmode, int scale,
float_status *s)
{
return round_to_uint_and_pack(float64_unpack_canonical(a, s),
rmode, scale, UINT32_MAX, s);
}
-uint64_t float64_to_uint64_scalbn(float64 a, int rmode, int scale,
+uint64_t float64_to_uint64_scalbn(float64 a, FloatRoundMode rmode, int scale,
float_status *s)
{
return round_to_uint_and_pack(float64_unpack_canonical(a, s),
@@ -2883,8 +2848,8 @@
#undef MINMAX
/* Floating point compare */
-static int compare_floats(FloatParts a, FloatParts b, bool is_quiet,
- float_status *s)
+static FloatRelation compare_floats(FloatParts a, FloatParts b, bool is_quiet,
+ float_status *s)
{
if (is_nan(a.cls) || is_nan(b.cls)) {
if (!is_quiet ||
@@ -2955,17 +2920,17 @@
#undef COMPARE
-int float16_compare(float16 a, float16 b, float_status *s)
+FloatRelation float16_compare(float16 a, float16 b, float_status *s)
{
return soft_f16_compare(a, b, false, s);
}
-int float16_compare_quiet(float16 a, float16 b, float_status *s)
+FloatRelation float16_compare_quiet(float16 a, float16 b, float_status *s)
{
return soft_f16_compare(a, b, true, s);
}
-static int QEMU_FLATTEN
+static FloatRelation QEMU_FLATTEN
f32_compare(float32 xa, float32 xb, bool is_quiet, float_status *s)
{
union_float32 ua, ub;
@@ -2994,17 +2959,17 @@
return soft_f32_compare(ua.s, ub.s, is_quiet, s);
}
-int float32_compare(float32 a, float32 b, float_status *s)
+FloatRelation float32_compare(float32 a, float32 b, float_status *s)
{
return f32_compare(a, b, false, s);
}
-int float32_compare_quiet(float32 a, float32 b, float_status *s)
+FloatRelation float32_compare_quiet(float32 a, float32 b, float_status *s)
{
return f32_compare(a, b, true, s);
}
-static int QEMU_FLATTEN
+static FloatRelation QEMU_FLATTEN
f64_compare(float64 xa, float64 xb, bool is_quiet, float_status *s)
{
union_float64 ua, ub;
@@ -3033,12 +2998,12 @@
return soft_f64_compare(ua.s, ub.s, is_quiet, s);
}
-int float64_compare(float64 a, float64 b, float_status *s)
+FloatRelation float64_compare(float64 a, float64 b, float_status *s)
{
return f64_compare(a, b, false, s);
}
-int float64_compare_quiet(float64 a, float64 b, float_status *s)
+FloatRelation float64_compare_quiet(float64 a, float64 b, float_status *s)
{
return f64_compare(a, b, true, s);
}
@@ -3365,10 +3330,11 @@
| positive or negative integer is returned.
*----------------------------------------------------------------------------*/
-static int32_t roundAndPackInt32(flag zSign, uint64_t absZ, float_status *status)
+static int32_t roundAndPackInt32(bool zSign, uint64_t absZ,
+ float_status *status)
{
int8_t roundingMode;
- flag roundNearestEven;
+ bool roundNearestEven;
int8_t roundIncrement, roundBits;
int32_t z;
@@ -3422,11 +3388,11 @@
| returned.
*----------------------------------------------------------------------------*/
-static int64_t roundAndPackInt64(flag zSign, uint64_t absZ0, uint64_t absZ1,
+static int64_t roundAndPackInt64(bool zSign, uint64_t absZ0, uint64_t absZ1,
float_status *status)
{
int8_t roundingMode;
- flag roundNearestEven, increment;
+ bool roundNearestEven, increment;
int64_t z;
roundingMode = status->float_rounding_mode;
@@ -3480,11 +3446,11 @@
| exception is raised and the largest unsigned integer is returned.
*----------------------------------------------------------------------------*/
-static int64_t roundAndPackUint64(flag zSign, uint64_t absZ0,
+static int64_t roundAndPackUint64(bool zSign, uint64_t absZ0,
uint64_t absZ1, float_status *status)
{
int8_t roundingMode;
- flag roundNearestEven, increment;
+ bool roundNearestEven, increment;
roundingMode = status->float_rounding_mode;
roundNearestEven = (roundingMode == float_round_nearest_even);
@@ -3568,13 +3534,13 @@
| Binary Floating-Point Arithmetic.
*----------------------------------------------------------------------------*/
-static float32 roundAndPackFloat32(flag zSign, int zExp, uint32_t zSig,
+static float32 roundAndPackFloat32(bool zSign, int zExp, uint32_t zSig,
float_status *status)
{
int8_t roundingMode;
- flag roundNearestEven;
+ bool roundNearestEven;
int8_t roundIncrement, roundBits;
- flag isTiny;
+ bool isTiny;
roundingMode = status->float_rounding_mode;
roundNearestEven = ( roundingMode == float_round_nearest_even );
@@ -3615,11 +3581,9 @@
float_raise(float_flag_output_denormal, status);
return packFloat32(zSign, 0, 0);
}
- isTiny =
- (status->float_detect_tininess
- == float_tininess_before_rounding)
- || ( zExp < -1 )
- || ( zSig + roundIncrement < 0x80000000 );
+ isTiny = status->tininess_before_rounding
+ || (zExp < -1)
+ || (zSig + roundIncrement < 0x80000000);
shift32RightJamming( zSig, - zExp, &zSig );
zExp = 0;
roundBits = zSig & 0x7F;
@@ -3655,7 +3619,7 @@
*----------------------------------------------------------------------------*/
static float32
- normalizeRoundAndPackFloat32(flag zSign, int zExp, uint32_t zSig,
+ normalizeRoundAndPackFloat32(bool zSign, int zExp, uint32_t zSig,
float_status *status)
{
int8_t shiftCount;
@@ -3695,7 +3659,7 @@
| significand.
*----------------------------------------------------------------------------*/
-static inline float64 packFloat64(flag zSign, int zExp, uint64_t zSig)
+static inline float64 packFloat64(bool zSign, int zExp, uint64_t zSig)
{
return make_float64(
@@ -3725,13 +3689,13 @@
| Binary Floating-Point Arithmetic.
*----------------------------------------------------------------------------*/
-static float64 roundAndPackFloat64(flag zSign, int zExp, uint64_t zSig,
+static float64 roundAndPackFloat64(bool zSign, int zExp, uint64_t zSig,
float_status *status)
{
int8_t roundingMode;
- flag roundNearestEven;
+ bool roundNearestEven;
int roundIncrement, roundBits;
- flag isTiny;
+ bool isTiny;
roundingMode = status->float_rounding_mode;
roundNearestEven = ( roundingMode == float_round_nearest_even );
@@ -3771,11 +3735,9 @@
float_raise(float_flag_output_denormal, status);
return packFloat64(zSign, 0, 0);
}
- isTiny =
- (status->float_detect_tininess
- == float_tininess_before_rounding)
- || ( zExp < -1 )
- || ( zSig + roundIncrement < UINT64_C(0x8000000000000000) );
+ isTiny = status->tininess_before_rounding
+ || (zExp < -1)
+ || (zSig + roundIncrement < UINT64_C(0x8000000000000000));
shift64RightJamming( zSig, - zExp, &zSig );
zExp = 0;
roundBits = zSig & 0x3FF;
@@ -3811,7 +3773,7 @@
*----------------------------------------------------------------------------*/
static float64
- normalizeRoundAndPackFloat64(flag zSign, int zExp, uint64_t zSig,
+ normalizeRoundAndPackFloat64(bool zSign, int zExp, uint64_t zSig,
float_status *status)
{
int8_t shiftCount;
@@ -3863,12 +3825,12 @@
| Floating-Point Arithmetic.
*----------------------------------------------------------------------------*/
-floatx80 roundAndPackFloatx80(int8_t roundingPrecision, flag zSign,
+floatx80 roundAndPackFloatx80(int8_t roundingPrecision, bool zSign,
int32_t zExp, uint64_t zSig0, uint64_t zSig1,
float_status *status)
{
int8_t roundingMode;
- flag roundNearestEven, increment, isTiny;
+ bool roundNearestEven, increment, isTiny;
int64_t roundIncrement, roundMask, roundBits;
roundingMode = status->float_rounding_mode;
@@ -3914,11 +3876,9 @@
float_raise(float_flag_output_denormal, status);
return packFloatx80(zSign, 0, 0);
}
- isTiny =
- (status->float_detect_tininess
- == float_tininess_before_rounding)
- || ( zExp < 0 )
- || ( zSig0 <= zSig0 + roundIncrement );
+ isTiny = status->tininess_before_rounding
+ || (zExp < 0 )
+ || (zSig0 <= zSig0 + roundIncrement);
shift64RightJamming( zSig0, 1 - zExp, &zSig0 );
zExp = 0;
roundBits = zSig0 & roundMask;
@@ -3992,12 +3952,10 @@
floatx80_infinity_low);
}
if ( zExp <= 0 ) {
- isTiny =
- (status->float_detect_tininess
- == float_tininess_before_rounding)
- || ( zExp < 0 )
- || ! increment
- || ( zSig0 < UINT64_C(0xFFFFFFFFFFFFFFFF) );
+ isTiny = status->tininess_before_rounding
+ || (zExp < 0)
+ || !increment
+ || (zSig0 < UINT64_C(0xFFFFFFFFFFFFFFFF));
shift64ExtraRightJamming( zSig0, zSig1, 1 - zExp, &zSig0, &zSig1 );
zExp = 0;
if (isTiny && zSig1) {
@@ -4062,7 +4020,7 @@
*----------------------------------------------------------------------------*/
floatx80 normalizeRoundAndPackFloatx80(int8_t roundingPrecision,
- flag zSign, int32_t zExp,
+ bool zSign, int32_t zExp,
uint64_t zSig0, uint64_t zSig1,
float_status *status)
{
@@ -4121,11 +4079,9 @@
| Returns the sign bit of the quadruple-precision floating-point value `a'.
*----------------------------------------------------------------------------*/
-static inline flag extractFloat128Sign( float128 a )
+static inline bool extractFloat128Sign(float128 a)
{
-
- return a.high>>63;
-
+ return a.high >> 63;
}
/*----------------------------------------------------------------------------
@@ -4183,14 +4139,13 @@
*----------------------------------------------------------------------------*/
static inline float128
- packFloat128( flag zSign, int32_t zExp, uint64_t zSig0, uint64_t zSig1 )
+packFloat128(bool zSign, int32_t zExp, uint64_t zSig0, uint64_t zSig1)
{
float128 z;
z.low = zSig1;
- z.high = ( ( (uint64_t) zSign )<<63 ) + ( ( (uint64_t) zExp )<<48 ) + zSig0;
+ z.high = ((uint64_t)zSign << 63) + ((uint64_t)zExp << 48) + zSig0;
return z;
-
}
/*----------------------------------------------------------------------------
@@ -4214,12 +4169,12 @@
| overflow follows the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
*----------------------------------------------------------------------------*/
-static float128 roundAndPackFloat128(flag zSign, int32_t zExp,
+static float128 roundAndPackFloat128(bool zSign, int32_t zExp,
uint64_t zSig0, uint64_t zSig1,
uint64_t zSig2, float_status *status)
{
int8_t roundingMode;
- flag roundNearestEven, increment, isTiny;
+ bool roundNearestEven, increment, isTiny;
roundingMode = status->float_rounding_mode;
roundNearestEven = ( roundingMode == float_round_nearest_even );
@@ -4276,17 +4231,12 @@
float_raise(float_flag_output_denormal, status);
return packFloat128(zSign, 0, 0, 0);
}
- isTiny =
- (status->float_detect_tininess
- == float_tininess_before_rounding)
- || ( zExp < -1 )
- || ! increment
- || lt128(
- zSig0,
- zSig1,
- UINT64_C(0x0001FFFFFFFFFFFF),
- UINT64_C(0xFFFFFFFFFFFFFFFF)
- );
+ isTiny = status->tininess_before_rounding
+ || (zExp < -1)
+ || !increment
+ || lt128(zSig0, zSig1,
+ UINT64_C(0x0001FFFFFFFFFFFF),
+ UINT64_C(0xFFFFFFFFFFFFFFFF));
shift128ExtraRightJamming(
zSig0, zSig1, zSig2, - zExp, &zSig0, &zSig1, &zSig2 );
zExp = 0;
@@ -4339,7 +4289,7 @@
| point exponent.
*----------------------------------------------------------------------------*/
-static float128 normalizeRoundAndPackFloat128(flag zSign, int32_t zExp,
+static float128 normalizeRoundAndPackFloat128(bool zSign, int32_t zExp,
uint64_t zSig0, uint64_t zSig1,
float_status *status)
{
@@ -4375,7 +4325,7 @@
floatx80 int32_to_floatx80(int32_t a, float_status *status)
{
- flag zSign;
+ bool zSign;
uint32_t absA;
int8_t shiftCount;
uint64_t zSig;
@@ -4397,7 +4347,7 @@
float128 int32_to_float128(int32_t a, float_status *status)
{
- flag zSign;
+ bool zSign;
uint32_t absA;
int8_t shiftCount;
uint64_t zSig0;
@@ -4420,7 +4370,7 @@
floatx80 int64_to_floatx80(int64_t a, float_status *status)
{
- flag zSign;
+ bool zSign;
uint64_t absA;
int8_t shiftCount;
@@ -4440,7 +4390,7 @@
float128 int64_to_float128(int64_t a, float_status *status)
{
- flag zSign;
+ bool zSign;
uint64_t absA;
int8_t shiftCount;
int32_t zExp;
@@ -4488,7 +4438,7 @@
floatx80 float32_to_floatx80(float32 a, float_status *status)
{
- flag aSign;
+ bool aSign;
int aExp;
uint32_t aSig;
@@ -4498,7 +4448,9 @@
aSign = extractFloat32Sign( a );
if ( aExp == 0xFF ) {
if (aSig) {
- return commonNaNToFloatx80(float32ToCommonNaN(a, status), status);
+ floatx80 res = commonNaNToFloatx80(float32ToCommonNaN(a, status),
+ status);
+ return floatx80_silence_nan(res, status);
}
return packFloatx80(aSign,
floatx80_infinity_high,
@@ -4522,7 +4474,7 @@
float128 float32_to_float128(float32 a, float_status *status)
{
- flag aSign;
+ bool aSign;
int aExp;
uint32_t aSig;
@@ -4553,7 +4505,7 @@
float32 float32_rem(float32 a, float32 b, float_status *status)
{
- flag aSign, zSign;
+ bool aSign, zSign;
int aExp, bExp, expDiff;
uint32_t aSig, bSig;
uint32_t q;
@@ -4688,7 +4640,7 @@
float32 float32_exp2(float32 a, float_status *status)
{
- flag aSign;
+ bool aSign;
int aExp;
uint32_t aSig;
float64 r, x, xn;
@@ -4738,7 +4690,7 @@
*----------------------------------------------------------------------------*/
float32 float32_log2(float32 a, float_status *status)
{
- flag aSign, zSign;
+ bool aSign, zSign;
int aExp;
uint32_t aSig, zSig, i;
@@ -4782,222 +4734,6 @@
}
/*----------------------------------------------------------------------------
-| Returns 1 if the single-precision floating-point value `a' is equal to
-| the corresponding value `b', and 0 otherwise. The invalid exception is
-| raised if either operand is a NaN. Otherwise, the comparison is performed
-| according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
-*----------------------------------------------------------------------------*/
-
-int float32_eq(float32 a, float32 b, float_status *status)
-{
- uint32_t av, bv;
- a = float32_squash_input_denormal(a, status);
- b = float32_squash_input_denormal(b, status);
-
- if ( ( ( extractFloat32Exp( a ) == 0xFF ) && extractFloat32Frac( a ) )
- || ( ( extractFloat32Exp( b ) == 0xFF ) && extractFloat32Frac( b ) )
- ) {
- float_raise(float_flag_invalid, status);
- return 0;
- }
- av = float32_val(a);
- bv = float32_val(b);
- return ( av == bv ) || ( (uint32_t) ( ( av | bv )<<1 ) == 0 );
-}
-
-/*----------------------------------------------------------------------------
-| Returns 1 if the single-precision floating-point value `a' is less than
-| or equal to the corresponding value `b', and 0 otherwise. The invalid
-| exception is raised if either operand is a NaN. The comparison is performed
-| according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
-*----------------------------------------------------------------------------*/
-
-int float32_le(float32 a, float32 b, float_status *status)
-{
- flag aSign, bSign;
- uint32_t av, bv;
- a = float32_squash_input_denormal(a, status);
- b = float32_squash_input_denormal(b, status);
-
- if ( ( ( extractFloat32Exp( a ) == 0xFF ) && extractFloat32Frac( a ) )
- || ( ( extractFloat32Exp( b ) == 0xFF ) && extractFloat32Frac( b ) )
- ) {
- float_raise(float_flag_invalid, status);
- return 0;
- }
- aSign = extractFloat32Sign( a );
- bSign = extractFloat32Sign( b );
- av = float32_val(a);
- bv = float32_val(b);
- if ( aSign != bSign ) return aSign || ( (uint32_t) ( ( av | bv )<<1 ) == 0 );
- return ( av == bv ) || ( aSign ^ ( av < bv ) );
-
-}
-
-/*----------------------------------------------------------------------------
-| Returns 1 if the single-precision floating-point value `a' is less than
-| the corresponding value `b', and 0 otherwise. The invalid exception is
-| raised if either operand is a NaN. The comparison is performed according
-| to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
-*----------------------------------------------------------------------------*/
-
-int float32_lt(float32 a, float32 b, float_status *status)
-{
- flag aSign, bSign;
- uint32_t av, bv;
- a = float32_squash_input_denormal(a, status);
- b = float32_squash_input_denormal(b, status);
-
- if ( ( ( extractFloat32Exp( a ) == 0xFF ) && extractFloat32Frac( a ) )
- || ( ( extractFloat32Exp( b ) == 0xFF ) && extractFloat32Frac( b ) )
- ) {
- float_raise(float_flag_invalid, status);
- return 0;
- }
- aSign = extractFloat32Sign( a );
- bSign = extractFloat32Sign( b );
- av = float32_val(a);
- bv = float32_val(b);
- if ( aSign != bSign ) return aSign && ( (uint32_t) ( ( av | bv )<<1 ) != 0 );
- return ( av != bv ) && ( aSign ^ ( av < bv ) );
-
-}
-
-/*----------------------------------------------------------------------------
-| Returns 1 if the single-precision floating-point values `a' and `b' cannot
-| be compared, and 0 otherwise. The invalid exception is raised if either
-| operand is a NaN. The comparison is performed according to the IEC/IEEE
-| Standard for Binary Floating-Point Arithmetic.
-*----------------------------------------------------------------------------*/
-
-int float32_unordered(float32 a, float32 b, float_status *status)
-{
- a = float32_squash_input_denormal(a, status);
- b = float32_squash_input_denormal(b, status);
-
- if ( ( ( extractFloat32Exp( a ) == 0xFF ) && extractFloat32Frac( a ) )
- || ( ( extractFloat32Exp( b ) == 0xFF ) && extractFloat32Frac( b ) )
- ) {
- float_raise(float_flag_invalid, status);
- return 1;
- }
- return 0;
-}
-
-/*----------------------------------------------------------------------------
-| Returns 1 if the single-precision floating-point value `a' is equal to
-| the corresponding value `b', and 0 otherwise. Quiet NaNs do not cause an
-| exception. The comparison is performed according to the IEC/IEEE Standard
-| for Binary Floating-Point Arithmetic.
-*----------------------------------------------------------------------------*/
-
-int float32_eq_quiet(float32 a, float32 b, float_status *status)
-{
- a = float32_squash_input_denormal(a, status);
- b = float32_squash_input_denormal(b, status);
-
- if ( ( ( extractFloat32Exp( a ) == 0xFF ) && extractFloat32Frac( a ) )
- || ( ( extractFloat32Exp( b ) == 0xFF ) && extractFloat32Frac( b ) )
- ) {
- if (float32_is_signaling_nan(a, status)
- || float32_is_signaling_nan(b, status)) {
- float_raise(float_flag_invalid, status);
- }
- return 0;
- }
- return ( float32_val(a) == float32_val(b) ) ||
- ( (uint32_t) ( ( float32_val(a) | float32_val(b) )<<1 ) == 0 );
-}
-
-/*----------------------------------------------------------------------------
-| Returns 1 if the single-precision floating-point value `a' is less than or
-| equal to the corresponding value `b', and 0 otherwise. Quiet NaNs do not
-| cause an exception. Otherwise, the comparison is performed according to the
-| IEC/IEEE Standard for Binary Floating-Point Arithmetic.
-*----------------------------------------------------------------------------*/
-
-int float32_le_quiet(float32 a, float32 b, float_status *status)
-{
- flag aSign, bSign;
- uint32_t av, bv;
- a = float32_squash_input_denormal(a, status);
- b = float32_squash_input_denormal(b, status);
-
- if ( ( ( extractFloat32Exp( a ) == 0xFF ) && extractFloat32Frac( a ) )
- || ( ( extractFloat32Exp( b ) == 0xFF ) && extractFloat32Frac( b ) )
- ) {
- if (float32_is_signaling_nan(a, status)
- || float32_is_signaling_nan(b, status)) {
- float_raise(float_flag_invalid, status);
- }
- return 0;
- }
- aSign = extractFloat32Sign( a );
- bSign = extractFloat32Sign( b );
- av = float32_val(a);
- bv = float32_val(b);
- if ( aSign != bSign ) return aSign || ( (uint32_t) ( ( av | bv )<<1 ) == 0 );
- return ( av == bv ) || ( aSign ^ ( av < bv ) );
-
-}
-
-/*----------------------------------------------------------------------------
-| Returns 1 if the single-precision floating-point value `a' is less than
-| the corresponding value `b', and 0 otherwise. Quiet NaNs do not cause an
-| exception. Otherwise, the comparison is performed according to the IEC/IEEE
-| Standard for Binary Floating-Point Arithmetic.
-*----------------------------------------------------------------------------*/
-
-int float32_lt_quiet(float32 a, float32 b, float_status *status)
-{
- flag aSign, bSign;
- uint32_t av, bv;
- a = float32_squash_input_denormal(a, status);
- b = float32_squash_input_denormal(b, status);
-
- if ( ( ( extractFloat32Exp( a ) == 0xFF ) && extractFloat32Frac( a ) )
- || ( ( extractFloat32Exp( b ) == 0xFF ) && extractFloat32Frac( b ) )
- ) {
- if (float32_is_signaling_nan(a, status)
- || float32_is_signaling_nan(b, status)) {
- float_raise(float_flag_invalid, status);
- }
- return 0;
- }
- aSign = extractFloat32Sign( a );
- bSign = extractFloat32Sign( b );
- av = float32_val(a);
- bv = float32_val(b);
- if ( aSign != bSign ) return aSign && ( (uint32_t) ( ( av | bv )<<1 ) != 0 );
- return ( av != bv ) && ( aSign ^ ( av < bv ) );
-
-}
-
-/*----------------------------------------------------------------------------
-| Returns 1 if the single-precision floating-point values `a' and `b' cannot
-| be compared, and 0 otherwise. Quiet NaNs do not cause an exception. The
-| comparison is performed according to the IEC/IEEE Standard for Binary
-| Floating-Point Arithmetic.
-*----------------------------------------------------------------------------*/
-
-int float32_unordered_quiet(float32 a, float32 b, float_status *status)
-{
- a = float32_squash_input_denormal(a, status);
- b = float32_squash_input_denormal(b, status);
-
- if ( ( ( extractFloat32Exp( a ) == 0xFF ) && extractFloat32Frac( a ) )
- || ( ( extractFloat32Exp( b ) == 0xFF ) && extractFloat32Frac( b ) )
- ) {
- if (float32_is_signaling_nan(a, status)
- || float32_is_signaling_nan(b, status)) {
- float_raise(float_flag_invalid, status);
- }
- return 1;
- }
- return 0;
-}
-
-/*----------------------------------------------------------------------------
| Returns the result of converting the double-precision floating-point value
| `a' to the extended double-precision floating-point format. The conversion
| is performed according to the IEC/IEEE Standard for Binary Floating-Point
@@ -5006,7 +4742,7 @@
floatx80 float64_to_floatx80(float64 a, float_status *status)
{
- flag aSign;
+ bool aSign;
int aExp;
uint64_t aSig;
@@ -5016,7 +4752,9 @@
aSign = extractFloat64Sign( a );
if ( aExp == 0x7FF ) {
if (aSig) {
- return commonNaNToFloatx80(float64ToCommonNaN(a, status), status);
+ floatx80 res = commonNaNToFloatx80(float64ToCommonNaN(a, status),
+ status);
+ return floatx80_silence_nan(res, status);
}
return packFloatx80(aSign,
floatx80_infinity_high,
@@ -5041,7 +4779,7 @@
float128 float64_to_float128(float64 a, float_status *status)
{
- flag aSign;
+ bool aSign;
int aExp;
uint64_t aSig, zSig0, zSig1;
@@ -5074,7 +4812,7 @@
float64 float64_rem(float64 a, float64 b, float_status *status)
{
- flag aSign, zSign;
+ bool aSign, zSign;
int aExp, bExp, expDiff;
uint64_t aSig, bSig;
uint64_t q, alternateASig;
@@ -5161,7 +4899,7 @@
*----------------------------------------------------------------------------*/
float64 float64_log2(float64 a, float_status *status)
{
- flag aSign, zSign;
+ bool aSign, zSign;
int aExp;
uint64_t aSig, aSig0, aSig1, zSig, i;
a = float64_squash_input_denormal(a, status);
@@ -5204,226 +4942,6 @@
}
/*----------------------------------------------------------------------------
-| Returns 1 if the double-precision floating-point value `a' is equal to the
-| corresponding value `b', and 0 otherwise. The invalid exception is raised
-| if either operand is a NaN. Otherwise, the comparison is performed
-| according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
-*----------------------------------------------------------------------------*/
-
-int float64_eq(float64 a, float64 b, float_status *status)
-{
- uint64_t av, bv;
- a = float64_squash_input_denormal(a, status);
- b = float64_squash_input_denormal(b, status);
-
- if ( ( ( extractFloat64Exp( a ) == 0x7FF ) && extractFloat64Frac( a ) )
- || ( ( extractFloat64Exp( b ) == 0x7FF ) && extractFloat64Frac( b ) )
- ) {
- float_raise(float_flag_invalid, status);
- return 0;
- }
- av = float64_val(a);
- bv = float64_val(b);
- return ( av == bv ) || ( (uint64_t) ( ( av | bv )<<1 ) == 0 );
-
-}
-
-/*----------------------------------------------------------------------------
-| Returns 1 if the double-precision floating-point value `a' is less than or
-| equal to the corresponding value `b', and 0 otherwise. The invalid
-| exception is raised if either operand is a NaN. The comparison is performed
-| according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
-*----------------------------------------------------------------------------*/
-
-int float64_le(float64 a, float64 b, float_status *status)
-{
- flag aSign, bSign;
- uint64_t av, bv;
- a = float64_squash_input_denormal(a, status);
- b = float64_squash_input_denormal(b, status);
-
- if ( ( ( extractFloat64Exp( a ) == 0x7FF ) && extractFloat64Frac( a ) )
- || ( ( extractFloat64Exp( b ) == 0x7FF ) && extractFloat64Frac( b ) )
- ) {
- float_raise(float_flag_invalid, status);
- return 0;
- }
- aSign = extractFloat64Sign( a );
- bSign = extractFloat64Sign( b );
- av = float64_val(a);
- bv = float64_val(b);
- if ( aSign != bSign ) return aSign || ( (uint64_t) ( ( av | bv )<<1 ) == 0 );
- return ( av == bv ) || ( aSign ^ ( av < bv ) );
-
-}
-
-/*----------------------------------------------------------------------------
-| Returns 1 if the double-precision floating-point value `a' is less than
-| the corresponding value `b', and 0 otherwise. The invalid exception is
-| raised if either operand is a NaN. The comparison is performed according
-| to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
-*----------------------------------------------------------------------------*/
-
-int float64_lt(float64 a, float64 b, float_status *status)
-{
- flag aSign, bSign;
- uint64_t av, bv;
-
- a = float64_squash_input_denormal(a, status);
- b = float64_squash_input_denormal(b, status);
- if ( ( ( extractFloat64Exp( a ) == 0x7FF ) && extractFloat64Frac( a ) )
- || ( ( extractFloat64Exp( b ) == 0x7FF ) && extractFloat64Frac( b ) )
- ) {
- float_raise(float_flag_invalid, status);
- return 0;
- }
- aSign = extractFloat64Sign( a );
- bSign = extractFloat64Sign( b );
- av = float64_val(a);
- bv = float64_val(b);
- if ( aSign != bSign ) return aSign && ( (uint64_t) ( ( av | bv )<<1 ) != 0 );
- return ( av != bv ) && ( aSign ^ ( av < bv ) );
-
-}
-
-/*----------------------------------------------------------------------------
-| Returns 1 if the double-precision floating-point values `a' and `b' cannot
-| be compared, and 0 otherwise. The invalid exception is raised if either
-| operand is a NaN. The comparison is performed according to the IEC/IEEE
-| Standard for Binary Floating-Point Arithmetic.
-*----------------------------------------------------------------------------*/
-
-int float64_unordered(float64 a, float64 b, float_status *status)
-{
- a = float64_squash_input_denormal(a, status);
- b = float64_squash_input_denormal(b, status);
-
- if ( ( ( extractFloat64Exp( a ) == 0x7FF ) && extractFloat64Frac( a ) )
- || ( ( extractFloat64Exp( b ) == 0x7FF ) && extractFloat64Frac( b ) )
- ) {
- float_raise(float_flag_invalid, status);
- return 1;
- }
- return 0;
-}
-
-/*----------------------------------------------------------------------------
-| Returns 1 if the double-precision floating-point value `a' is equal to the
-| corresponding value `b', and 0 otherwise. Quiet NaNs do not cause an
-| exception.The comparison is performed according to the IEC/IEEE Standard
-| for Binary Floating-Point Arithmetic.
-*----------------------------------------------------------------------------*/
-
-int float64_eq_quiet(float64 a, float64 b, float_status *status)
-{
- uint64_t av, bv;
- a = float64_squash_input_denormal(a, status);
- b = float64_squash_input_denormal(b, status);
-
- if ( ( ( extractFloat64Exp( a ) == 0x7FF ) && extractFloat64Frac( a ) )
- || ( ( extractFloat64Exp( b ) == 0x7FF ) && extractFloat64Frac( b ) )
- ) {
- if (float64_is_signaling_nan(a, status)
- || float64_is_signaling_nan(b, status)) {
- float_raise(float_flag_invalid, status);
- }
- return 0;
- }
- av = float64_val(a);
- bv = float64_val(b);
- return ( av == bv ) || ( (uint64_t) ( ( av | bv )<<1 ) == 0 );
-
-}
-
-/*----------------------------------------------------------------------------
-| Returns 1 if the double-precision floating-point value `a' is less than or
-| equal to the corresponding value `b', and 0 otherwise. Quiet NaNs do not
-| cause an exception. Otherwise, the comparison is performed according to the
-| IEC/IEEE Standard for Binary Floating-Point Arithmetic.
-*----------------------------------------------------------------------------*/
-
-int float64_le_quiet(float64 a, float64 b, float_status *status)
-{
- flag aSign, bSign;
- uint64_t av, bv;
- a = float64_squash_input_denormal(a, status);
- b = float64_squash_input_denormal(b, status);
-
- if ( ( ( extractFloat64Exp( a ) == 0x7FF ) && extractFloat64Frac( a ) )
- || ( ( extractFloat64Exp( b ) == 0x7FF ) && extractFloat64Frac( b ) )
- ) {
- if (float64_is_signaling_nan(a, status)
- || float64_is_signaling_nan(b, status)) {
- float_raise(float_flag_invalid, status);
- }
- return 0;
- }
- aSign = extractFloat64Sign( a );
- bSign = extractFloat64Sign( b );
- av = float64_val(a);
- bv = float64_val(b);
- if ( aSign != bSign ) return aSign || ( (uint64_t) ( ( av | bv )<<1 ) == 0 );
- return ( av == bv ) || ( aSign ^ ( av < bv ) );
-
-}
-
-/*----------------------------------------------------------------------------
-| Returns 1 if the double-precision floating-point value `a' is less than
-| the corresponding value `b', and 0 otherwise. Quiet NaNs do not cause an
-| exception. Otherwise, the comparison is performed according to the IEC/IEEE
-| Standard for Binary Floating-Point Arithmetic.
-*----------------------------------------------------------------------------*/
-
-int float64_lt_quiet(float64 a, float64 b, float_status *status)
-{
- flag aSign, bSign;
- uint64_t av, bv;
- a = float64_squash_input_denormal(a, status);
- b = float64_squash_input_denormal(b, status);
-
- if ( ( ( extractFloat64Exp( a ) == 0x7FF ) && extractFloat64Frac( a ) )
- || ( ( extractFloat64Exp( b ) == 0x7FF ) && extractFloat64Frac( b ) )
- ) {
- if (float64_is_signaling_nan(a, status)
- || float64_is_signaling_nan(b, status)) {
- float_raise(float_flag_invalid, status);
- }
- return 0;
- }
- aSign = extractFloat64Sign( a );
- bSign = extractFloat64Sign( b );
- av = float64_val(a);
- bv = float64_val(b);
- if ( aSign != bSign ) return aSign && ( (uint64_t) ( ( av | bv )<<1 ) != 0 );
- return ( av != bv ) && ( aSign ^ ( av < bv ) );
-
-}
-
-/*----------------------------------------------------------------------------
-| Returns 1 if the double-precision floating-point values `a' and `b' cannot
-| be compared, and 0 otherwise. Quiet NaNs do not cause an exception. The
-| comparison is performed according to the IEC/IEEE Standard for Binary
-| Floating-Point Arithmetic.
-*----------------------------------------------------------------------------*/
-
-int float64_unordered_quiet(float64 a, float64 b, float_status *status)
-{
- a = float64_squash_input_denormal(a, status);
- b = float64_squash_input_denormal(b, status);
-
- if ( ( ( extractFloat64Exp( a ) == 0x7FF ) && extractFloat64Frac( a ) )
- || ( ( extractFloat64Exp( b ) == 0x7FF ) && extractFloat64Frac( b ) )
- ) {
- if (float64_is_signaling_nan(a, status)
- || float64_is_signaling_nan(b, status)) {
- float_raise(float_flag_invalid, status);
- }
- return 1;
- }
- return 0;
-}
-
-/*----------------------------------------------------------------------------
| Returns the result of converting the extended double-precision floating-
| point value `a' to the 32-bit two's complement integer format. The
| conversion is performed according to the IEC/IEEE Standard for Binary
@@ -5435,7 +4953,7 @@
int32_t floatx80_to_int32(floatx80 a, float_status *status)
{
- flag aSign;
+ bool aSign;
int32_t aExp, shiftCount;
uint64_t aSig;
@@ -5466,7 +4984,7 @@
int32_t floatx80_to_int32_round_to_zero(floatx80 a, float_status *status)
{
- flag aSign;
+ bool aSign;
int32_t aExp, shiftCount;
uint64_t aSig, savedASig;
int32_t z;
@@ -5517,7 +5035,7 @@
int64_t floatx80_to_int64(floatx80 a, float_status *status)
{
- flag aSign;
+ bool aSign;
int32_t aExp, shiftCount;
uint64_t aSig, aSigExtra;
@@ -5558,7 +5076,7 @@
int64_t floatx80_to_int64_round_to_zero(floatx80 a, float_status *status)
{
- flag aSign;
+ bool aSign;
int32_t aExp, shiftCount;
uint64_t aSig;
int64_t z;
@@ -5605,7 +5123,7 @@
float32 floatx80_to_float32(floatx80 a, float_status *status)
{
- flag aSign;
+ bool aSign;
int32_t aExp;
uint64_t aSig;
@@ -5618,7 +5136,9 @@
aSign = extractFloatx80Sign( a );
if ( aExp == 0x7FFF ) {
if ( (uint64_t) ( aSig<<1 ) ) {
- return commonNaNToFloat32(floatx80ToCommonNaN(a, status), status);
+ float32 res = commonNaNToFloat32(floatx80ToCommonNaN(a, status),
+ status);
+ return float32_silence_nan(res, status);
}
return packFloat32( aSign, 0xFF, 0 );
}
@@ -5637,7 +5157,7 @@
float64 floatx80_to_float64(floatx80 a, float_status *status)
{
- flag aSign;
+ bool aSign;
int32_t aExp;
uint64_t aSig, zSig;
@@ -5650,7 +5170,9 @@
aSign = extractFloatx80Sign( a );
if ( aExp == 0x7FFF ) {
if ( (uint64_t) ( aSig<<1 ) ) {
- return commonNaNToFloat64(floatx80ToCommonNaN(a, status), status);
+ float64 res = commonNaNToFloat64(floatx80ToCommonNaN(a, status),
+ status);
+ return float64_silence_nan(res, status);
}
return packFloat64( aSign, 0x7FF, 0 );
}
@@ -5669,7 +5191,7 @@
float128 floatx80_to_float128(floatx80 a, float_status *status)
{
- flag aSign;
+ bool aSign;
int aExp;
uint64_t aSig, zSig0, zSig1;
@@ -5681,7 +5203,9 @@
aExp = extractFloatx80Exp( a );
aSign = extractFloatx80Sign( a );
if ( ( aExp == 0x7FFF ) && (uint64_t) ( aSig<<1 ) ) {
- return commonNaNToFloat128(floatx80ToCommonNaN(a, status), status);
+ float128 res = commonNaNToFloat128(floatx80ToCommonNaN(a, status),
+ status);
+ return float128_silence_nan(res, status);
}
shift128Right( aSig<<1, 0, 16, &zSig0, &zSig1 );
return packFloat128( aSign, aExp, zSig0, zSig1 );
@@ -5713,7 +5237,7 @@
floatx80 floatx80_round_to_int(floatx80 a, float_status *status)
{
- flag aSign;
+ bool aSign;
int32_t aExp;
uint64_t lastBitMask, roundBitsMask;
floatx80 z;
@@ -5731,7 +5255,7 @@
}
if ( aExp < 0x3FFF ) {
if ( ( aExp == 0 )
- && ( (uint64_t) ( extractFloatx80Frac( a )<<1 ) == 0 ) ) {
+ && ( (uint64_t) ( extractFloatx80Frac( a ) ) == 0 ) ) {
return a;
}
status->float_exception_flags |= float_flag_inexact;
@@ -5758,6 +5282,11 @@
return
aSign ? packFloatx80( 1, 0, 0 )
: packFloatx80( 0, 0x3FFF, UINT64_C(0x8000000000000000));
+
+ case float_round_to_zero:
+ break;
+ default:
+ g_assert_not_reached();
}
return packFloatx80( aSign, 0, 0 );
}
@@ -5810,7 +5339,7 @@
| Floating-Point Arithmetic.
*----------------------------------------------------------------------------*/
-static floatx80 addFloatx80Sigs(floatx80 a, floatx80 b, flag zSign,
+static floatx80 addFloatx80Sigs(floatx80 a, floatx80 b, bool zSign,
float_status *status)
{
int32_t aExp, bExp, zExp;
@@ -5856,6 +5385,12 @@
zSig1 = 0;
zSig0 = aSig + bSig;
if ( aExp == 0 ) {
+ if ((aSig | bSig) & UINT64_C(0x8000000000000000) && zSig0 < aSig) {
+ /* At least one of the values is a pseudo-denormal,
+ * and there is a carry out of the result. */
+ zExp = 1;
+ goto shiftRight1;
+ }
if (zSig0 == 0) {
return packFloatx80(zSign, 0, 0);
}
@@ -5884,7 +5419,7 @@
| Standard for Binary Floating-Point Arithmetic.
*----------------------------------------------------------------------------*/
-static floatx80 subFloatx80Sigs(floatx80 a, floatx80 b, flag zSign,
+static floatx80 subFloatx80Sigs(floatx80 a, floatx80 b, bool zSign,
float_status *status)
{
int32_t aExp, bExp, zExp;
@@ -5953,7 +5488,7 @@
floatx80 floatx80_add(floatx80 a, floatx80 b, float_status *status)
{
- flag aSign, bSign;
+ bool aSign, bSign;
if (floatx80_invalid_encoding(a) || floatx80_invalid_encoding(b)) {
float_raise(float_flag_invalid, status);
@@ -5978,7 +5513,7 @@
floatx80 floatx80_sub(floatx80 a, floatx80 b, float_status *status)
{
- flag aSign, bSign;
+ bool aSign, bSign;
if (floatx80_invalid_encoding(a) || floatx80_invalid_encoding(b)) {
float_raise(float_flag_invalid, status);
@@ -6003,7 +5538,7 @@
floatx80 floatx80_mul(floatx80 a, floatx80 b, float_status *status)
{
- flag aSign, bSign, zSign;
+ bool aSign, bSign, zSign;
int32_t aExp, bExp, zExp;
uint64_t aSig, bSig, zSig0, zSig1;
@@ -6065,7 +5600,7 @@
floatx80 floatx80_div(floatx80 a, floatx80 b, float_status *status)
{
- flag aSign, bSign, zSign;
+ bool aSign, bSign, zSign;
int32_t aExp, bExp, zExp;
uint64_t aSig, bSig, zSig0, zSig1;
uint64_t rem0, rem1, rem2, term0, term1, term2;
@@ -6152,7 +5687,7 @@
floatx80 floatx80_rem(floatx80 a, floatx80 b, float_status *status)
{
- flag aSign, zSign;
+ bool aSign, zSign;
int32_t aExp, bExp, expDiff;
uint64_t aSig0, aSig1, bSig;
uint64_t q, term0, term1, alternateASig0, alternateASig1;
@@ -6251,7 +5786,7 @@
floatx80 floatx80_sqrt(floatx80 a, float_status *status)
{
- flag aSign;
+ bool aSign;
int32_t aExp, zExp;
uint64_t aSig0, aSig1, zSig0, zSig1, doubleZSig0;
uint64_t rem0, rem1, rem2, rem3, term0, term1, term2, term3;
@@ -6315,263 +5850,6 @@
}
/*----------------------------------------------------------------------------
-| Returns 1 if the extended double-precision floating-point value `a' is equal
-| to the corresponding value `b', and 0 otherwise. The invalid exception is
-| raised if either operand is a NaN. Otherwise, the comparison is performed
-| according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
-*----------------------------------------------------------------------------*/
-
-int floatx80_eq(floatx80 a, floatx80 b, float_status *status)
-{
-
- if (floatx80_invalid_encoding(a) || floatx80_invalid_encoding(b)
- || (extractFloatx80Exp(a) == 0x7FFF
- && (uint64_t) (extractFloatx80Frac(a) << 1))
- || (extractFloatx80Exp(b) == 0x7FFF
- && (uint64_t) (extractFloatx80Frac(b) << 1))
- ) {
- float_raise(float_flag_invalid, status);
- return 0;
- }
- return
- ( a.low == b.low )
- && ( ( a.high == b.high )
- || ( ( a.low == 0 )
- && ( (uint16_t) ( ( a.high | b.high )<<1 ) == 0 ) )
- );
-
-}
-
-/*----------------------------------------------------------------------------
-| Returns 1 if the extended double-precision floating-point value `a' is
-| less than or equal to the corresponding value `b', and 0 otherwise. The
-| invalid exception is raised if either operand is a NaN. The comparison is
-| performed according to the IEC/IEEE Standard for Binary Floating-Point
-| Arithmetic.
-*----------------------------------------------------------------------------*/
-
-int floatx80_le(floatx80 a, floatx80 b, float_status *status)
-{
- flag aSign, bSign;
-
- if (floatx80_invalid_encoding(a) || floatx80_invalid_encoding(b)
- || (extractFloatx80Exp(a) == 0x7FFF
- && (uint64_t) (extractFloatx80Frac(a) << 1))
- || (extractFloatx80Exp(b) == 0x7FFF
- && (uint64_t) (extractFloatx80Frac(b) << 1))
- ) {
- float_raise(float_flag_invalid, status);
- return 0;
- }
- aSign = extractFloatx80Sign( a );
- bSign = extractFloatx80Sign( b );
- if ( aSign != bSign ) {
- return
- aSign
- || ( ( ( (uint16_t) ( ( a.high | b.high )<<1 ) ) | a.low | b.low )
- == 0 );
- }
- return
- aSign ? le128( b.high, b.low, a.high, a.low )
- : le128( a.high, a.low, b.high, b.low );
-
-}
-
-/*----------------------------------------------------------------------------
-| Returns 1 if the extended double-precision floating-point value `a' is
-| less than the corresponding value `b', and 0 otherwise. The invalid
-| exception is raised if either operand is a NaN. The comparison is performed
-| according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
-*----------------------------------------------------------------------------*/
-
-int floatx80_lt(floatx80 a, floatx80 b, float_status *status)
-{
- flag aSign, bSign;
-
- if (floatx80_invalid_encoding(a) || floatx80_invalid_encoding(b)
- || (extractFloatx80Exp(a) == 0x7FFF
- && (uint64_t) (extractFloatx80Frac(a) << 1))
- || (extractFloatx80Exp(b) == 0x7FFF
- && (uint64_t) (extractFloatx80Frac(b) << 1))
- ) {
- float_raise(float_flag_invalid, status);
- return 0;
- }
- aSign = extractFloatx80Sign( a );
- bSign = extractFloatx80Sign( b );
- if ( aSign != bSign ) {
- return
- aSign
- && ( ( ( (uint16_t) ( ( a.high | b.high )<<1 ) ) | a.low | b.low )
- != 0 );
- }
- return
- aSign ? lt128( b.high, b.low, a.high, a.low )
- : lt128( a.high, a.low, b.high, b.low );
-
-}
-
-/*----------------------------------------------------------------------------
-| Returns 1 if the extended double-precision floating-point values `a' and `b'
-| cannot be compared, and 0 otherwise. The invalid exception is raised if
-| either operand is a NaN. The comparison is performed according to the
-| IEC/IEEE Standard for Binary Floating-Point Arithmetic.
-*----------------------------------------------------------------------------*/
-int floatx80_unordered(floatx80 a, floatx80 b, float_status *status)
-{
- if (floatx80_invalid_encoding(a) || floatx80_invalid_encoding(b)
- || (extractFloatx80Exp(a) == 0x7FFF
- && (uint64_t) (extractFloatx80Frac(a) << 1))
- || (extractFloatx80Exp(b) == 0x7FFF
- && (uint64_t) (extractFloatx80Frac(b) << 1))
- ) {
- float_raise(float_flag_invalid, status);
- return 1;
- }
- return 0;
-}
-
-/*----------------------------------------------------------------------------
-| Returns 1 if the extended double-precision floating-point value `a' is
-| equal to the corresponding value `b', and 0 otherwise. Quiet NaNs do not
-| cause an exception. The comparison is performed according to the IEC/IEEE
-| Standard for Binary Floating-Point Arithmetic.
-*----------------------------------------------------------------------------*/
-
-int floatx80_eq_quiet(floatx80 a, floatx80 b, float_status *status)
-{
-
- if (floatx80_invalid_encoding(a) || floatx80_invalid_encoding(b)) {
- float_raise(float_flag_invalid, status);
- return 0;
- }
- if ( ( ( extractFloatx80Exp( a ) == 0x7FFF )
- && (uint64_t) ( extractFloatx80Frac( a )<<1 ) )
- || ( ( extractFloatx80Exp( b ) == 0x7FFF )
- && (uint64_t) ( extractFloatx80Frac( b )<<1 ) )
- ) {
- if (floatx80_is_signaling_nan(a, status)
- || floatx80_is_signaling_nan(b, status)) {
- float_raise(float_flag_invalid, status);
- }
- return 0;
- }
- return
- ( a.low == b.low )
- && ( ( a.high == b.high )
- || ( ( a.low == 0 )
- && ( (uint16_t) ( ( a.high | b.high )<<1 ) == 0 ) )
- );
-
-}
-
-/*----------------------------------------------------------------------------
-| Returns 1 if the extended double-precision floating-point value `a' is less
-| than or equal to the corresponding value `b', and 0 otherwise. Quiet NaNs
-| do not cause an exception. Otherwise, the comparison is performed according
-| to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
-*----------------------------------------------------------------------------*/
-
-int floatx80_le_quiet(floatx80 a, floatx80 b, float_status *status)
-{
- flag aSign, bSign;
-
- if (floatx80_invalid_encoding(a) || floatx80_invalid_encoding(b)) {
- float_raise(float_flag_invalid, status);
- return 0;
- }
- if ( ( ( extractFloatx80Exp( a ) == 0x7FFF )
- && (uint64_t) ( extractFloatx80Frac( a )<<1 ) )
- || ( ( extractFloatx80Exp( b ) == 0x7FFF )
- && (uint64_t) ( extractFloatx80Frac( b )<<1 ) )
- ) {
- if (floatx80_is_signaling_nan(a, status)
- || floatx80_is_signaling_nan(b, status)) {
- float_raise(float_flag_invalid, status);
- }
- return 0;
- }
- aSign = extractFloatx80Sign( a );
- bSign = extractFloatx80Sign( b );
- if ( aSign != bSign ) {
- return
- aSign
- || ( ( ( (uint16_t) ( ( a.high | b.high )<<1 ) ) | a.low | b.low )
- == 0 );
- }
- return
- aSign ? le128( b.high, b.low, a.high, a.low )
- : le128( a.high, a.low, b.high, b.low );
-
-}
-
-/*----------------------------------------------------------------------------
-| Returns 1 if the extended double-precision floating-point value `a' is less
-| than the corresponding value `b', and 0 otherwise. Quiet NaNs do not cause
-| an exception. Otherwise, the comparison is performed according to the
-| IEC/IEEE Standard for Binary Floating-Point Arithmetic.
-*----------------------------------------------------------------------------*/
-
-int floatx80_lt_quiet(floatx80 a, floatx80 b, float_status *status)
-{
- flag aSign, bSign;
-
- if (floatx80_invalid_encoding(a) || floatx80_invalid_encoding(b)) {
- float_raise(float_flag_invalid, status);
- return 0;
- }
- if ( ( ( extractFloatx80Exp( a ) == 0x7FFF )
- && (uint64_t) ( extractFloatx80Frac( a )<<1 ) )
- || ( ( extractFloatx80Exp( b ) == 0x7FFF )
- && (uint64_t) ( extractFloatx80Frac( b )<<1 ) )
- ) {
- if (floatx80_is_signaling_nan(a, status)
- || floatx80_is_signaling_nan(b, status)) {
- float_raise(float_flag_invalid, status);
- }
- return 0;
- }
- aSign = extractFloatx80Sign( a );
- bSign = extractFloatx80Sign( b );
- if ( aSign != bSign ) {
- return
- aSign
- && ( ( ( (uint16_t) ( ( a.high | b.high )<<1 ) ) | a.low | b.low )
- != 0 );
- }
- return
- aSign ? lt128( b.high, b.low, a.high, a.low )
- : lt128( a.high, a.low, b.high, b.low );
-
-}
-
-/*----------------------------------------------------------------------------
-| Returns 1 if the extended double-precision floating-point values `a' and `b'
-| cannot be compared, and 0 otherwise. Quiet NaNs do not cause an exception.
-| The comparison is performed according to the IEC/IEEE Standard for Binary
-| Floating-Point Arithmetic.
-*----------------------------------------------------------------------------*/
-int floatx80_unordered_quiet(floatx80 a, floatx80 b, float_status *status)
-{
- if (floatx80_invalid_encoding(a) || floatx80_invalid_encoding(b)) {
- float_raise(float_flag_invalid, status);
- return 1;
- }
- if ( ( ( extractFloatx80Exp( a ) == 0x7FFF )
- && (uint64_t) ( extractFloatx80Frac( a )<<1 ) )
- || ( ( extractFloatx80Exp( b ) == 0x7FFF )
- && (uint64_t) ( extractFloatx80Frac( b )<<1 ) )
- ) {
- if (floatx80_is_signaling_nan(a, status)
- || floatx80_is_signaling_nan(b, status)) {
- float_raise(float_flag_invalid, status);
- }
- return 1;
- }
- return 0;
-}
-
-/*----------------------------------------------------------------------------
| Returns the result of converting the quadruple-precision floating-point
| value `a' to the 32-bit two's complement integer format. The conversion
| is performed according to the IEC/IEEE Standard for Binary Floating-Point
@@ -6583,7 +5861,7 @@
int32_t float128_to_int32(float128 a, float_status *status)
{
- flag aSign;
+ bool aSign;
int32_t aExp, shiftCount;
uint64_t aSig0, aSig1;
@@ -6612,7 +5890,7 @@
int32_t float128_to_int32_round_to_zero(float128 a, float_status *status)
{
- flag aSign;
+ bool aSign;
int32_t aExp, shiftCount;
uint64_t aSig0, aSig1, savedASig;
int32_t z;
@@ -6662,7 +5940,7 @@
int64_t float128_to_int64(float128 a, float_status *status)
{
- flag aSign;
+ bool aSign;
int32_t aExp, shiftCount;
uint64_t aSig0, aSig1;
@@ -6705,7 +5983,7 @@
int64_t float128_to_int64_round_to_zero(float128 a, float_status *status)
{
- flag aSign;
+ bool aSign;
int32_t aExp, shiftCount;
uint64_t aSig0, aSig1;
int64_t z;
@@ -6770,7 +6048,7 @@
uint64_t float128_to_uint64(float128 a, float_status *status)
{
- flag aSign;
+ bool aSign;
int aExp;
int shiftCount;
uint64_t aSig0, aSig1;
@@ -6881,7 +6159,7 @@
float32 float128_to_float32(float128 a, float_status *status)
{
- flag aSign;
+ bool aSign;
int32_t aExp;
uint64_t aSig0, aSig1;
uint32_t zSig;
@@ -6916,7 +6194,7 @@
float64 float128_to_float64(float128 a, float_status *status)
{
- flag aSign;
+ bool aSign;
int32_t aExp;
uint64_t aSig0, aSig1;
@@ -6949,7 +6227,7 @@
floatx80 float128_to_floatx80(float128 a, float_status *status)
{
- flag aSign;
+ bool aSign;
int32_t aExp;
uint64_t aSig0, aSig1;
@@ -6959,7 +6237,9 @@
aSign = extractFloat128Sign( a );
if ( aExp == 0x7FFF ) {
if ( aSig0 | aSig1 ) {
- return commonNaNToFloatx80(float128ToCommonNaN(a, status), status);
+ floatx80 res = commonNaNToFloatx80(float128ToCommonNaN(a, status),
+ status);
+ return floatx80_silence_nan(res, status);
}
return packFloatx80(aSign, floatx80_infinity_high,
floatx80_infinity_low);
@@ -6985,7 +6265,7 @@
float128 float128_round_to_int(float128 a, float_status *status)
{
- flag aSign;
+ bool aSign;
int32_t aExp;
uint64_t lastBitMask, roundBitsMask;
float128 z;
@@ -7082,6 +6362,9 @@
case float_round_to_odd:
return packFloat128(aSign, 0x3FFF, 0, 0);
+
+ case float_round_to_zero:
+ break;
}
return packFloat128( aSign, 0, 0, 0 );
}
@@ -7140,7 +6423,7 @@
| Floating-Point Arithmetic.
*----------------------------------------------------------------------------*/
-static float128 addFloat128Sigs(float128 a, float128 b, flag zSign,
+static float128 addFloat128Sigs(float128 a, float128 b, bool zSign,
float_status *status)
{
int32_t aExp, bExp, zExp;
@@ -7231,7 +6514,7 @@
| Standard for Binary Floating-Point Arithmetic.
*----------------------------------------------------------------------------*/
-static float128 subFloat128Sigs(float128 a, float128 b, flag zSign,
+static float128 subFloat128Sigs(float128 a, float128 b, bool zSign,
float_status *status)
{
int32_t aExp, bExp, zExp;
@@ -7319,7 +6602,7 @@
float128 float128_add(float128 a, float128 b, float_status *status)
{
- flag aSign, bSign;
+ bool aSign, bSign;
aSign = extractFloat128Sign( a );
bSign = extractFloat128Sign( b );
@@ -7340,7 +6623,7 @@
float128 float128_sub(float128 a, float128 b, float_status *status)
{
- flag aSign, bSign;
+ bool aSign, bSign;
aSign = extractFloat128Sign( a );
bSign = extractFloat128Sign( b );
@@ -7361,7 +6644,7 @@
float128 float128_mul(float128 a, float128 b, float_status *status)
{
- flag aSign, bSign, zSign;
+ bool aSign, bSign, zSign;
int32_t aExp, bExp, zExp;
uint64_t aSig0, aSig1, bSig0, bSig1, zSig0, zSig1, zSig2, zSig3;
@@ -7424,7 +6707,7 @@
float128 float128_div(float128 a, float128 b, float_status *status)
{
- flag aSign, bSign, zSign;
+ bool aSign, bSign, zSign;
int32_t aExp, bExp, zExp;
uint64_t aSig0, aSig1, bSig0, bSig1, zSig0, zSig1, zSig2;
uint64_t rem0, rem1, rem2, rem3, term0, term1, term2, term3;
@@ -7511,7 +6794,7 @@
float128 float128_rem(float128 a, float128 b, float_status *status)
{
- flag aSign, zSign;
+ bool aSign, zSign;
int32_t aExp, bExp, expDiff;
uint64_t aSig0, aSig1, bSig0, bSig1, q, term0, term1, term2;
uint64_t allZero, alternateASig0, alternateASig1, sigMean1;
@@ -7618,7 +6901,7 @@
float128 float128_sqrt(float128 a, float_status *status)
{
- flag aSign;
+ bool aSign;
int32_t aExp, zExp;
uint64_t aSig0, aSig1, zSig0, zSig1, zSig2, doubleZSig0;
uint64_t rem0, rem1, rem2, rem3, term0, term1, term2, term3;
@@ -7678,248 +6961,11 @@
}
-/*----------------------------------------------------------------------------
-| Returns 1 if the quadruple-precision floating-point value `a' is equal to
-| the corresponding value `b', and 0 otherwise. The invalid exception is
-| raised if either operand is a NaN. Otherwise, the comparison is performed
-| according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
-*----------------------------------------------------------------------------*/
-
-int float128_eq(float128 a, float128 b, float_status *status)
+static inline FloatRelation
+floatx80_compare_internal(floatx80 a, floatx80 b, bool is_quiet,
+ float_status *status)
{
-
- if ( ( ( extractFloat128Exp( a ) == 0x7FFF )
- && ( extractFloat128Frac0( a ) | extractFloat128Frac1( a ) ) )
- || ( ( extractFloat128Exp( b ) == 0x7FFF )
- && ( extractFloat128Frac0( b ) | extractFloat128Frac1( b ) ) )
- ) {
- float_raise(float_flag_invalid, status);
- return 0;
- }
- return
- ( a.low == b.low )
- && ( ( a.high == b.high )
- || ( ( a.low == 0 )
- && ( (uint64_t) ( ( a.high | b.high )<<1 ) == 0 ) )
- );
-
-}
-
-/*----------------------------------------------------------------------------
-| Returns 1 if the quadruple-precision floating-point value `a' is less than
-| or equal to the corresponding value `b', and 0 otherwise. The invalid
-| exception is raised if either operand is a NaN. The comparison is performed
-| according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
-*----------------------------------------------------------------------------*/
-
-int float128_le(float128 a, float128 b, float_status *status)
-{
- flag aSign, bSign;
-
- if ( ( ( extractFloat128Exp( a ) == 0x7FFF )
- && ( extractFloat128Frac0( a ) | extractFloat128Frac1( a ) ) )
- || ( ( extractFloat128Exp( b ) == 0x7FFF )
- && ( extractFloat128Frac0( b ) | extractFloat128Frac1( b ) ) )
- ) {
- float_raise(float_flag_invalid, status);
- return 0;
- }
- aSign = extractFloat128Sign( a );
- bSign = extractFloat128Sign( b );
- if ( aSign != bSign ) {
- return
- aSign
- || ( ( ( (uint64_t) ( ( a.high | b.high )<<1 ) ) | a.low | b.low )
- == 0 );
- }
- return
- aSign ? le128( b.high, b.low, a.high, a.low )
- : le128( a.high, a.low, b.high, b.low );
-
-}
-
-/*----------------------------------------------------------------------------
-| Returns 1 if the quadruple-precision floating-point value `a' is less than
-| the corresponding value `b', and 0 otherwise. The invalid exception is
-| raised if either operand is a NaN. The comparison is performed according
-| to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
-*----------------------------------------------------------------------------*/
-
-int float128_lt(float128 a, float128 b, float_status *status)
-{
- flag aSign, bSign;
-
- if ( ( ( extractFloat128Exp( a ) == 0x7FFF )
- && ( extractFloat128Frac0( a ) | extractFloat128Frac1( a ) ) )
- || ( ( extractFloat128Exp( b ) == 0x7FFF )
- && ( extractFloat128Frac0( b ) | extractFloat128Frac1( b ) ) )
- ) {
- float_raise(float_flag_invalid, status);
- return 0;
- }
- aSign = extractFloat128Sign( a );
- bSign = extractFloat128Sign( b );
- if ( aSign != bSign ) {
- return
- aSign
- && ( ( ( (uint64_t) ( ( a.high | b.high )<<1 ) ) | a.low | b.low )
- != 0 );
- }
- return
- aSign ? lt128( b.high, b.low, a.high, a.low )
- : lt128( a.high, a.low, b.high, b.low );
-
-}
-
-/*----------------------------------------------------------------------------
-| Returns 1 if the quadruple-precision floating-point values `a' and `b' cannot
-| be compared, and 0 otherwise. The invalid exception is raised if either
-| operand is a NaN. The comparison is performed according to the IEC/IEEE
-| Standard for Binary Floating-Point Arithmetic.
-*----------------------------------------------------------------------------*/
-
-int float128_unordered(float128 a, float128 b, float_status *status)
-{
- if ( ( ( extractFloat128Exp( a ) == 0x7FFF )
- && ( extractFloat128Frac0( a ) | extractFloat128Frac1( a ) ) )
- || ( ( extractFloat128Exp( b ) == 0x7FFF )
- && ( extractFloat128Frac0( b ) | extractFloat128Frac1( b ) ) )
- ) {
- float_raise(float_flag_invalid, status);
- return 1;
- }
- return 0;
-}
-
-/*----------------------------------------------------------------------------
-| Returns 1 if the quadruple-precision floating-point value `a' is equal to
-| the corresponding value `b', and 0 otherwise. Quiet NaNs do not cause an
-| exception. The comparison is performed according to the IEC/IEEE Standard
-| for Binary Floating-Point Arithmetic.
-*----------------------------------------------------------------------------*/
-
-int float128_eq_quiet(float128 a, float128 b, float_status *status)
-{
-
- if ( ( ( extractFloat128Exp( a ) == 0x7FFF )
- && ( extractFloat128Frac0( a ) | extractFloat128Frac1( a ) ) )
- || ( ( extractFloat128Exp( b ) == 0x7FFF )
- && ( extractFloat128Frac0( b ) | extractFloat128Frac1( b ) ) )
- ) {
- if (float128_is_signaling_nan(a, status)
- || float128_is_signaling_nan(b, status)) {
- float_raise(float_flag_invalid, status);
- }
- return 0;
- }
- return
- ( a.low == b.low )
- && ( ( a.high == b.high )
- || ( ( a.low == 0 )
- && ( (uint64_t) ( ( a.high | b.high )<<1 ) == 0 ) )
- );
-
-}
-
-/*----------------------------------------------------------------------------
-| Returns 1 if the quadruple-precision floating-point value `a' is less than
-| or equal to the corresponding value `b', and 0 otherwise. Quiet NaNs do not
-| cause an exception. Otherwise, the comparison is performed according to the
-| IEC/IEEE Standard for Binary Floating-Point Arithmetic.
-*----------------------------------------------------------------------------*/
-
-int float128_le_quiet(float128 a, float128 b, float_status *status)
-{
- flag aSign, bSign;
-
- if ( ( ( extractFloat128Exp( a ) == 0x7FFF )
- && ( extractFloat128Frac0( a ) | extractFloat128Frac1( a ) ) )
- || ( ( extractFloat128Exp( b ) == 0x7FFF )
- && ( extractFloat128Frac0( b ) | extractFloat128Frac1( b ) ) )
- ) {
- if (float128_is_signaling_nan(a, status)
- || float128_is_signaling_nan(b, status)) {
- float_raise(float_flag_invalid, status);
- }
- return 0;
- }
- aSign = extractFloat128Sign( a );
- bSign = extractFloat128Sign( b );
- if ( aSign != bSign ) {
- return
- aSign
- || ( ( ( (uint64_t) ( ( a.high | b.high )<<1 ) ) | a.low | b.low )
- == 0 );
- }
- return
- aSign ? le128( b.high, b.low, a.high, a.low )
- : le128( a.high, a.low, b.high, b.low );
-
-}
-
-/*----------------------------------------------------------------------------
-| Returns 1 if the quadruple-precision floating-point value `a' is less than
-| the corresponding value `b', and 0 otherwise. Quiet NaNs do not cause an
-| exception. Otherwise, the comparison is performed according to the IEC/IEEE
-| Standard for Binary Floating-Point Arithmetic.
-*----------------------------------------------------------------------------*/
-
-int float128_lt_quiet(float128 a, float128 b, float_status *status)
-{
- flag aSign, bSign;
-
- if ( ( ( extractFloat128Exp( a ) == 0x7FFF )
- && ( extractFloat128Frac0( a ) | extractFloat128Frac1( a ) ) )
- || ( ( extractFloat128Exp( b ) == 0x7FFF )
- && ( extractFloat128Frac0( b ) | extractFloat128Frac1( b ) ) )
- ) {
- if (float128_is_signaling_nan(a, status)
- || float128_is_signaling_nan(b, status)) {
- float_raise(float_flag_invalid, status);
- }
- return 0;
- }
- aSign = extractFloat128Sign( a );
- bSign = extractFloat128Sign( b );
- if ( aSign != bSign ) {
- return
- aSign
- && ( ( ( (uint64_t) ( ( a.high | b.high )<<1 ) ) | a.low | b.low )
- != 0 );
- }
- return
- aSign ? lt128( b.high, b.low, a.high, a.low )
- : lt128( a.high, a.low, b.high, b.low );
-
-}
-
-/*----------------------------------------------------------------------------
-| Returns 1 if the quadruple-precision floating-point values `a' and `b' cannot
-| be compared, and 0 otherwise. Quiet NaNs do not cause an exception. The
-| comparison is performed according to the IEC/IEEE Standard for Binary
-| Floating-Point Arithmetic.
-*----------------------------------------------------------------------------*/
-
-int float128_unordered_quiet(float128 a, float128 b, float_status *status)
-{
- if ( ( ( extractFloat128Exp( a ) == 0x7FFF )
- && ( extractFloat128Frac0( a ) | extractFloat128Frac1( a ) ) )
- || ( ( extractFloat128Exp( b ) == 0x7FFF )
- && ( extractFloat128Frac0( b ) | extractFloat128Frac1( b ) ) )
- ) {
- if (float128_is_signaling_nan(a, status)
- || float128_is_signaling_nan(b, status)) {
- float_raise(float_flag_invalid, status);
- }
- return 1;
- }
- return 0;
-}
-
-static inline int floatx80_compare_internal(floatx80 a, floatx80 b,
- int is_quiet, float_status *status)
-{
- flag aSign, bSign;
+ bool aSign, bSign;
if (floatx80_invalid_encoding(a) || floatx80_invalid_encoding(b)) {
float_raise(float_flag_invalid, status);
@@ -7948,6 +6994,13 @@
return 1 - (2 * aSign);
}
} else {
+ /* Normalize pseudo-denormals before comparison. */
+ if ((a.high & 0x7fff) == 0 && a.low & UINT64_C(0x8000000000000000)) {
+ ++a.high;
+ }
+ if ((b.high & 0x7fff) == 0 && b.low & UINT64_C(0x8000000000000000)) {
+ ++b.high;
+ }
if (a.low == b.low && a.high == b.high) {
return float_relation_equal;
} else {
@@ -7956,20 +7009,22 @@
}
}
-int floatx80_compare(floatx80 a, floatx80 b, float_status *status)
+FloatRelation floatx80_compare(floatx80 a, floatx80 b, float_status *status)
{
return floatx80_compare_internal(a, b, 0, status);
}
-int floatx80_compare_quiet(floatx80 a, floatx80 b, float_status *status)
+FloatRelation floatx80_compare_quiet(floatx80 a, floatx80 b,
+ float_status *status)
{
return floatx80_compare_internal(a, b, 1, status);
}
-static inline int float128_compare_internal(float128 a, float128 b,
- int is_quiet, float_status *status)
+static inline FloatRelation
+float128_compare_internal(float128 a, float128 b, bool is_quiet,
+ float_status *status)
{
- flag aSign, bSign;
+ bool aSign, bSign;
if (( ( extractFloat128Exp( a ) == 0x7fff ) &&
( extractFloat128Frac0( a ) | extractFloat128Frac1( a ) ) ) ||
@@ -8000,19 +7055,20 @@
}
}
-int float128_compare(float128 a, float128 b, float_status *status)
+FloatRelation float128_compare(float128 a, float128 b, float_status *status)
{
return float128_compare_internal(a, b, 0, status);
}
-int float128_compare_quiet(float128 a, float128 b, float_status *status)
+FloatRelation float128_compare_quiet(float128 a, float128 b,
+ float_status *status)
{
return float128_compare_internal(a, b, 1, status);
}
floatx80 floatx80_scalbn(floatx80 a, int n, float_status *status)
{
- flag aSign;
+ bool aSign;
int32_t aExp;
uint64_t aSig;
@@ -8051,7 +7107,7 @@
float128 float128_scalbn(float128 a, int n, float_status *status)
{
- flag aSign;
+ bool aSign;
int32_t aExp;
uint64_t aSig0, aSig1;
diff --git a/gdb-xml/arm-m-profile.xml b/gdb-xml/arm-m-profile.xml
new file mode 100644
index 0000000..5319d76
--- /dev/null
+++ b/gdb-xml/arm-m-profile.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0"?>
+<!-- Copyright (C) 2010-2020 Free Software Foundation, Inc.
+
+ Copying and distribution of this file, with or without modification,
+ are permitted in any medium without royalty provided the copyright
+ notice and this notice are preserved. -->
+
+<!DOCTYPE feature SYSTEM "gdb-target.dtd">
+<feature name="org.gnu.gdb.arm.m-profile">
+ <reg name="r0" bitsize="32"/>
+ <reg name="r1" bitsize="32"/>
+ <reg name="r2" bitsize="32"/>
+ <reg name="r3" bitsize="32"/>
+ <reg name="r4" bitsize="32"/>
+ <reg name="r5" bitsize="32"/>
+ <reg name="r6" bitsize="32"/>
+ <reg name="r7" bitsize="32"/>
+ <reg name="r8" bitsize="32"/>
+ <reg name="r9" bitsize="32"/>
+ <reg name="r10" bitsize="32"/>
+ <reg name="r11" bitsize="32"/>
+ <reg name="r12" bitsize="32"/>
+ <reg name="sp" bitsize="32" type="data_ptr"/>
+ <reg name="lr" bitsize="32"/>
+ <reg name="pc" bitsize="32" type="code_ptr"/>
+ <reg name="xpsr" bitsize="32" regnum="25"/>
+</feature>
diff --git a/hmp-commands.hx b/hmp-commands.hx
index 7f0f397..2825620 100644
--- a/hmp-commands.hx
+++ b/hmp-commands.hx
@@ -1791,8 +1791,22 @@
ERST
{
+ .name = "qom-get",
+ .args_type = "path:s,property:s",
+ .params = "path property",
+ .help = "print QOM property",
+ .cmd = hmp_qom_get,
+ .flags = "p",
+ },
+
+SRST
+``qom-get`` *path* *property*
+ Print QOM property *property* of object at location *path*
+ERST
+
+ {
.name = "qom-set",
- .args_type = "path:s,property:s,value:s",
+ .args_type = "path:s,property:s,value:S",
.params = "path property value",
.help = "set QOM property",
.cmd = hmp_qom_set,
diff --git a/hw/9pfs/9p-util.h b/hw/9pfs/9p-util.h
index 79ed6b2..546f46d 100644
--- a/hw/9pfs/9p-util.h
+++ b/hw/9pfs/9p-util.h
@@ -37,9 +37,22 @@
{
int fd, serrno, ret;
+again:
fd = openat(dirfd, name, flags | O_NOFOLLOW | O_NOCTTY | O_NONBLOCK,
mode);
if (fd == -1) {
+ if (errno == EPERM && (flags & O_NOATIME)) {
+ /*
+ * The client passed O_NOATIME but we lack permissions to honor it.
+ * Rather than failing the open, fall back without O_NOATIME. This
+ * doesn't break the semantics on the client side, as the Linux
+ * open(2) man page notes that O_NOATIME "may not be effective on
+ * all filesystems". In particular, NFS and other network
+ * filesystems ignore it entirely.
+ */
+ flags &= ~O_NOATIME;
+ goto again;
+ }
return -1;
}
diff --git a/hw/9pfs/9p.c b/hw/9pfs/9p.c
index 9e046f7..45a788f 100644
--- a/hw/9pfs/9p.c
+++ b/hw/9pfs/9p.c
@@ -28,6 +28,7 @@
#include "sysemu/qtest.h"
#include "qemu/xxhash.h"
#include <math.h>
+#include <linux/limits.h>
int open_fd_hw;
int total_open_fd;
@@ -2102,29 +2103,22 @@
* with qemu_iovec_destroy().
*/
static void v9fs_init_qiov_from_pdu(QEMUIOVector *qiov, V9fsPDU *pdu,
- size_t skip, size_t *size,
+ size_t skip, size_t size,
bool is_write)
{
QEMUIOVector elem;
struct iovec *iov;
unsigned int niov;
- size_t alloc_size = *size + skip;
if (is_write) {
- pdu->s->transport->init_out_iov_from_pdu(pdu, &iov, &niov, alloc_size);
+ pdu->s->transport->init_out_iov_from_pdu(pdu, &iov, &niov, size + skip);
} else {
- pdu->s->transport->init_in_iov_from_pdu(pdu, &iov, &niov, &alloc_size);
- }
-
- if (alloc_size < skip) {
- *size = 0;
- } else {
- *size = alloc_size - skip;
+ pdu->s->transport->init_in_iov_from_pdu(pdu, &iov, &niov, size + skip);
}
qemu_iovec_init_external(&elem, iov, niov);
qemu_iovec_init(qiov, niov);
- qemu_iovec_concat(qiov, &elem, skip, *size);
+ qemu_iovec_concat(qiov, &elem, skip, size);
}
static int v9fs_xattr_read(V9fsState *s, V9fsPDU *pdu, V9fsFidState *fidp,
@@ -2132,14 +2126,15 @@
{
ssize_t err;
size_t offset = 7;
- size_t read_count;
+ uint64_t read_count;
QEMUIOVector qiov_full;
if (fidp->fs.xattr.len < off) {
read_count = 0;
- } else if (fidp->fs.xattr.len - off < max_count) {
- read_count = fidp->fs.xattr.len - off;
} else {
+ read_count = fidp->fs.xattr.len - off;
+ }
+ if (read_count > max_count) {
read_count = max_count;
}
err = pdu_marshal(pdu, offset, "d", read_count);
@@ -2148,7 +2143,7 @@
}
offset += err;
- v9fs_init_qiov_from_pdu(&qiov_full, pdu, offset, &read_count, false);
+ v9fs_init_qiov_from_pdu(&qiov_full, pdu, offset, read_count, false);
err = v9fs_pack(qiov_full.iov, qiov_full.niov, 0,
((char *)fidp->fs.xattr.value) + off,
read_count);
@@ -2277,11 +2272,9 @@
QEMUIOVector qiov_full;
QEMUIOVector qiov;
int32_t len;
- size_t size = max_count;
- v9fs_init_qiov_from_pdu(&qiov_full, pdu, offset + 4, &size, false);
+ v9fs_init_qiov_from_pdu(&qiov_full, pdu, offset + 4, max_count, false);
qemu_iovec_init(&qiov, qiov_full.niov);
- max_count = size;
do {
qemu_iovec_reset(&qiov);
qemu_iovec_concat(&qiov, &qiov_full, count, qiov_full.size - count);
@@ -2532,7 +2525,6 @@
int32_t len = 0;
int32_t total = 0;
size_t offset = 7;
- size_t size;
V9fsFidState *fidp;
V9fsPDU *pdu = opaque;
V9fsState *s = pdu->s;
@@ -2545,9 +2537,7 @@
return;
}
offset += err;
- size = count;
- v9fs_init_qiov_from_pdu(&qiov_full, pdu, offset, &size, true);
- count = size;
+ v9fs_init_qiov_from_pdu(&qiov_full, pdu, offset, count, true);
trace_v9fs_write(pdu->tag, pdu->id, fid, off, count, qiov_full.niov);
fidp = get_fid(pdu, fid);
@@ -4124,13 +4114,13 @@
rc = 0;
out:
if (rc) {
- v9fs_device_unrealize_common(s, NULL);
+ v9fs_device_unrealize_common(s);
}
v9fs_path_free(&path);
return rc;
}
-void v9fs_device_unrealize_common(V9fsState *s, Error **errp)
+void v9fs_device_unrealize_common(V9fsState *s)
{
if (s->ops && s->ops->cleanup) {
s->ops->cleanup(&s->ctx);
diff --git a/hw/9pfs/9p.h b/hw/9pfs/9p.h
index b8f72a3..ee22716 100644
--- a/hw/9pfs/9p.h
+++ b/hw/9pfs/9p.h
@@ -197,22 +197,22 @@
typedef struct V9fsDir {
DIR *stream;
- QemuMutex readdir_mutex;
+ CoMutex readdir_mutex;
} V9fsDir;
static inline void v9fs_readdir_lock(V9fsDir *dir)
{
- qemu_mutex_lock(&dir->readdir_mutex);
+ qemu_co_mutex_lock(&dir->readdir_mutex);
}
static inline void v9fs_readdir_unlock(V9fsDir *dir)
{
- qemu_mutex_unlock(&dir->readdir_mutex);
+ qemu_co_mutex_unlock(&dir->readdir_mutex);
}
static inline void v9fs_readdir_init(V9fsDir *dir)
{
- qemu_mutex_init(&dir->readdir_mutex);
+ qemu_co_mutex_init(&dir->readdir_mutex);
}
/*
@@ -423,7 +423,7 @@
const char *name, V9fsPath *path);
int v9fs_device_realize_common(V9fsState *s, const V9fsTransport *t,
Error **errp);
-void v9fs_device_unrealize_common(V9fsState *s, Error **errp);
+void v9fs_device_unrealize_common(V9fsState *s);
V9fsPDU *pdu_alloc(V9fsState *s);
void pdu_free(V9fsPDU *pdu);
@@ -436,7 +436,7 @@
ssize_t (*pdu_vunmarshal)(V9fsPDU *pdu, size_t offset, const char *fmt,
va_list ap);
void (*init_in_iov_from_pdu)(V9fsPDU *pdu, struct iovec **piov,
- unsigned int *pniov, size_t *size);
+ unsigned int *pniov, size_t size);
void (*init_out_iov_from_pdu)(V9fsPDU *pdu, struct iovec **piov,
unsigned int *pniov, size_t size);
void (*push_and_notify)(V9fsPDU *pdu);
diff --git a/hw/9pfs/virtio-9p-device.c b/hw/9pfs/virtio-9p-device.c
index 536447a..36f3aa9 100644
--- a/hw/9pfs/virtio-9p-device.c
+++ b/hw/9pfs/virtio-9p-device.c
@@ -147,22 +147,19 @@
}
static void virtio_init_in_iov_from_pdu(V9fsPDU *pdu, struct iovec **piov,
- unsigned int *pniov, size_t *size)
+ unsigned int *pniov, size_t size)
{
V9fsState *s = pdu->s;
V9fsVirtioState *v = container_of(s, V9fsVirtioState, state);
VirtQueueElement *elem = v->elems[pdu->idx];
size_t buf_size = iov_size(elem->in_sg, elem->in_num);
- if (buf_size < P9_IOHDRSZ) {
+ if (buf_size < size) {
VirtIODevice *vdev = VIRTIO_DEVICE(v);
virtio_error(vdev,
- "VirtFS reply type %d needs %zu bytes, buffer has %zu, less than minimum",
- pdu->id + 1, *size, buf_size);
- }
- if (buf_size < *size) {
- *size = buf_size;
+ "VirtFS reply type %d needs %zu bytes, buffer has %zu",
+ pdu->id + 1, size, buf_size);
}
*piov = elem->in_sg;
@@ -212,7 +209,7 @@
v->vq = virtio_add_queue(vdev, MAX_REQ, handle_9p_output);
}
-static void virtio_9p_device_unrealize(DeviceState *dev, Error **errp)
+static void virtio_9p_device_unrealize(DeviceState *dev)
{
VirtIODevice *vdev = VIRTIO_DEVICE(dev);
V9fsVirtioState *v = VIRTIO_9P(dev);
@@ -220,7 +217,7 @@
virtio_delete_queue(v->vq);
virtio_cleanup(vdev);
- v9fs_device_unrealize_common(s, errp);
+ v9fs_device_unrealize_common(s);
}
/* virtio-9p device */
diff --git a/hw/9pfs/xen-9p-backend.c b/hw/9pfs/xen-9p-backend.c
index 18fe5b7..a969fcc 100644
--- a/hw/9pfs/xen-9p-backend.c
+++ b/hw/9pfs/xen-9p-backend.c
@@ -21,7 +21,7 @@
#define VERSIONS "1"
#define MAX_RINGS 8
-#define MAX_RING_ORDER 8
+#define MAX_RING_ORDER 9
typedef struct Xen9pfsRing {
struct Xen9pfsDev *priv;
@@ -37,6 +37,7 @@
struct iovec *sg;
QEMUBH *bh;
+ Coroutine *co;
/* local copies, so that we can read/write PDU data directly from
* the ring */
@@ -137,7 +138,8 @@
ret = v9fs_iov_vmarshal(in_sg, num, offset, 0, fmt, ap);
if (ret < 0) {
xen_pv_printf(&xen_9pfs->xendev, 0,
- "Failed to encode VirtFS request type %d\n", pdu->id + 1);
+ "Failed to encode VirtFS reply type %d\n",
+ pdu->id + 1);
xen_be_set_state(&xen_9pfs->xendev, XenbusStateClosing);
xen_9pfs_disconnect(&xen_9pfs->xendev);
}
@@ -187,7 +189,7 @@
static void xen_9pfs_init_in_iov_from_pdu(V9fsPDU *pdu,
struct iovec **piov,
unsigned int *pniov,
- size_t *size)
+ size_t size)
{
Xen9pfsDev *xen_9pfs = container_of(pdu->s, Xen9pfsDev, state);
Xen9pfsRing *ring = &xen_9pfs->rings[pdu->tag % xen_9pfs->num_rings];
@@ -197,19 +199,20 @@
g_free(ring->sg);
ring->sg = g_new0(struct iovec, 2);
- xen_9pfs_in_sg(ring, ring->sg, &num, pdu->idx, *size);
+ ring->co = qemu_coroutine_self();
+ /* make sure other threads see ring->co changes before continuing */
+ smp_wmb();
+again:
+ xen_9pfs_in_sg(ring, ring->sg, &num, pdu->idx, size);
buf_size = iov_size(ring->sg, num);
- if (buf_size < P9_IOHDRSZ) {
- xen_pv_printf(&xen_9pfs->xendev, 0, "Xen 9pfs request type %d"
- "needs %zu bytes, buffer has %zu, less than minimum\n",
- pdu->id, *size, buf_size);
- xen_be_set_state(&xen_9pfs->xendev, XenbusStateClosing);
- xen_9pfs_disconnect(&xen_9pfs->xendev);
+ if (buf_size < size) {
+ qemu_coroutine_yield();
+ goto again;
}
- if (buf_size < *size) {
- *size = buf_size;
- }
+ ring->co = NULL;
+ /* make sure other threads see ring->co changes before continuing */
+ smp_wmb();
*piov = ring->sg;
*pniov = num;
@@ -294,6 +297,20 @@
static void xen_9pfs_bh(void *opaque)
{
Xen9pfsRing *ring = opaque;
+ bool wait;
+
+again:
+ wait = ring->co != NULL && qemu_coroutine_entered(ring->co);
+ /* paired with the smb_wmb barriers in xen_9pfs_init_in_iov_from_pdu */
+ smp_rmb();
+ if (wait) {
+ cpu_relax();
+ goto again;
+ }
+
+ if (ring->co != NULL) {
+ qemu_coroutine_enter_if_inactive(ring->co);
+ }
xen_9pfs_receive(ring);
}
diff --git a/hw/acpi/Kconfig b/hw/acpi/Kconfig
index 54209c6..1932f66 100644
--- a/hw/acpi/Kconfig
+++ b/hw/acpi/Kconfig
@@ -28,6 +28,10 @@
bool
depends on ACPI
+config ACPI_APEI
+ bool
+ depends on ACPI
+
config ACPI_PCI
bool
depends on ACPI && PCI
diff --git a/hw/acpi/Makefile.objs b/hw/acpi/Makefile.objs
index cab9bcd..72886c7 100644
--- a/hw/acpi/Makefile.objs
+++ b/hw/acpi/Makefile.objs
@@ -8,6 +8,7 @@
common-obj-$(CONFIG_ACPI_VMGENID) += vmgenid.o
common-obj-$(CONFIG_ACPI_HW_REDUCED) += generic_event_device.o
common-obj-$(CONFIG_ACPI_HMAT) += hmat.o
+common-obj-$(CONFIG_ACPI_APEI) += ghes.o
common-obj-$(call lnot,$(CONFIG_ACPI_X86)) += acpi-stub.o
common-obj-$(call lnot,$(CONFIG_PC)) += acpi-x86-stub.o
diff --git a/hw/acpi/aml-build.c b/hw/acpi/aml-build.c
index 2c3702b..3681ec6 100644
--- a/hw/acpi/aml-build.c
+++ b/hw/acpi/aml-build.c
@@ -1578,6 +1578,7 @@
tables->table_data = g_array_new(false, true /* clear */, 1);
tables->tcpalog = g_array_new(false, true /* clear */, 1);
tables->vmgenid = g_array_new(false, true /* clear */, 1);
+ tables->hardware_errors = g_array_new(false, true /* clear */, 1);
tables->linker = bios_linker_loader_init();
}
@@ -1588,6 +1589,7 @@
g_array_free(tables->table_data, true);
g_array_free(tables->tcpalog, mfre);
g_array_free(tables->vmgenid, mfre);
+ g_array_free(tables->hardware_errors, mfre);
}
/*
diff --git a/hw/acpi/generic_event_device.c b/hw/acpi/generic_event_device.c
index 5d17f78..b1cbdd8 100644
--- a/hw/acpi/generic_event_device.c
+++ b/hw/acpi/generic_event_device.c
@@ -247,6 +247,24 @@
}
};
+static bool ghes_needed(void *opaque)
+{
+ AcpiGedState *s = opaque;
+ return s->ghes_state.ghes_addr_le;
+}
+
+static const VMStateDescription vmstate_ghes_state = {
+ .name = "acpi-ged/ghes",
+ .version_id = 1,
+ .minimum_version_id = 1,
+ .needed = ghes_needed,
+ .fields = (VMStateField[]) {
+ VMSTATE_STRUCT(ghes_state, AcpiGedState, 1,
+ vmstate_ghes_state, AcpiGhesState),
+ VMSTATE_END_OF_LIST()
+ }
+};
+
static const VMStateDescription vmstate_acpi_ged = {
.name = "acpi-ged",
.version_id = 1,
@@ -257,6 +275,7 @@
},
.subsections = (const VMStateDescription * []) {
&vmstate_memhp_state,
+ &vmstate_ghes_state,
NULL
}
};
diff --git a/hw/acpi/ghes.c b/hw/acpi/ghes.c
new file mode 100644
index 0000000..b363bc3
--- /dev/null
+++ b/hw/acpi/ghes.c
@@ -0,0 +1,448 @@
+/*
+ * Support for generating APEI tables and recording CPER for Guests
+ *
+ * Copyright (c) 2020 HUAWEI TECHNOLOGIES CO., LTD.
+ *
+ * Author: Dongjiu Geng <gengdongjiu@huawei.com>
+ *
+ * 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/>.
+ */
+
+#include "qemu/osdep.h"
+#include "qemu/units.h"
+#include "hw/acpi/ghes.h"
+#include "hw/acpi/aml-build.h"
+#include "qemu/error-report.h"
+#include "hw/acpi/generic_event_device.h"
+#include "hw/nvram/fw_cfg.h"
+#include "qemu/uuid.h"
+
+#define ACPI_GHES_ERRORS_FW_CFG_FILE "etc/hardware_errors"
+#define ACPI_GHES_DATA_ADDR_FW_CFG_FILE "etc/hardware_errors_addr"
+
+/* The max size in bytes for one error block */
+#define ACPI_GHES_MAX_RAW_DATA_LENGTH (1 * KiB)
+
+/* Now only support ARMv8 SEA notification type error source */
+#define ACPI_GHES_ERROR_SOURCE_COUNT 1
+
+/* Generic Hardware Error Source version 2 */
+#define ACPI_GHES_SOURCE_GENERIC_ERROR_V2 10
+
+/* Address offset in Generic Address Structure(GAS) */
+#define GAS_ADDR_OFFSET 4
+
+/*
+ * The total size of Generic Error Data Entry
+ * ACPI 6.1/6.2: 18.3.2.7.1 Generic Error Data,
+ * Table 18-343 Generic Error Data Entry
+ */
+#define ACPI_GHES_DATA_LENGTH 72
+
+/* The memory section CPER size, UEFI 2.6: N.2.5 Memory Error Section */
+#define ACPI_GHES_MEM_CPER_LENGTH 80
+
+/* Masks for block_status flags */
+#define ACPI_GEBS_UNCORRECTABLE 1
+
+/*
+ * Total size for Generic Error Status Block except Generic Error Data Entries
+ * ACPI 6.2: 18.3.2.7.1 Generic Error Data,
+ * Table 18-380 Generic Error Status Block
+ */
+#define ACPI_GHES_GESB_SIZE 20
+
+/*
+ * Values for error_severity field
+ */
+enum AcpiGenericErrorSeverity {
+ ACPI_CPER_SEV_RECOVERABLE = 0,
+ ACPI_CPER_SEV_FATAL = 1,
+ ACPI_CPER_SEV_CORRECTED = 2,
+ ACPI_CPER_SEV_NONE = 3,
+};
+
+/*
+ * Hardware Error Notification
+ * ACPI 4.0: 17.3.2.7 Hardware Error Notification
+ * Composes dummy Hardware Error Notification descriptor of specified type
+ */
+static void build_ghes_hw_error_notification(GArray *table, const uint8_t type)
+{
+ /* Type */
+ build_append_int_noprefix(table, type, 1);
+ /*
+ * Length:
+ * Total length of the structure in bytes
+ */
+ build_append_int_noprefix(table, 28, 1);
+ /* Configuration Write Enable */
+ build_append_int_noprefix(table, 0, 2);
+ /* Poll Interval */
+ build_append_int_noprefix(table, 0, 4);
+ /* Vector */
+ build_append_int_noprefix(table, 0, 4);
+ /* Switch To Polling Threshold Value */
+ build_append_int_noprefix(table, 0, 4);
+ /* Switch To Polling Threshold Window */
+ build_append_int_noprefix(table, 0, 4);
+ /* Error Threshold Value */
+ build_append_int_noprefix(table, 0, 4);
+ /* Error Threshold Window */
+ build_append_int_noprefix(table, 0, 4);
+}
+
+/*
+ * Generic Error Data Entry
+ * ACPI 6.1: 18.3.2.7.1 Generic Error Data
+ */
+static void acpi_ghes_generic_error_data(GArray *table,
+ const uint8_t *section_type, uint32_t error_severity,
+ uint8_t validation_bits, uint8_t flags,
+ uint32_t error_data_length, QemuUUID fru_id,
+ uint64_t time_stamp)
+{
+ const uint8_t fru_text[20] = {0};
+
+ /* Section Type */
+ g_array_append_vals(table, section_type, 16);
+
+ /* Error Severity */
+ build_append_int_noprefix(table, error_severity, 4);
+ /* Revision */
+ build_append_int_noprefix(table, 0x300, 2);
+ /* Validation Bits */
+ build_append_int_noprefix(table, validation_bits, 1);
+ /* Flags */
+ build_append_int_noprefix(table, flags, 1);
+ /* Error Data Length */
+ build_append_int_noprefix(table, error_data_length, 4);
+
+ /* FRU Id */
+ g_array_append_vals(table, fru_id.data, ARRAY_SIZE(fru_id.data));
+
+ /* FRU Text */
+ g_array_append_vals(table, fru_text, sizeof(fru_text));
+
+ /* Timestamp */
+ build_append_int_noprefix(table, time_stamp, 8);
+}
+
+/*
+ * Generic Error Status Block
+ * ACPI 6.1: 18.3.2.7.1 Generic Error Data
+ */
+static void acpi_ghes_generic_error_status(GArray *table, uint32_t block_status,
+ uint32_t raw_data_offset, uint32_t raw_data_length,
+ uint32_t data_length, uint32_t error_severity)
+{
+ /* Block Status */
+ build_append_int_noprefix(table, block_status, 4);
+ /* Raw Data Offset */
+ build_append_int_noprefix(table, raw_data_offset, 4);
+ /* Raw Data Length */
+ build_append_int_noprefix(table, raw_data_length, 4);
+ /* Data Length */
+ build_append_int_noprefix(table, data_length, 4);
+ /* Error Severity */
+ build_append_int_noprefix(table, error_severity, 4);
+}
+
+/* UEFI 2.6: N.2.5 Memory Error Section */
+static void acpi_ghes_build_append_mem_cper(GArray *table,
+ uint64_t error_physical_addr)
+{
+ /*
+ * Memory Error Record
+ */
+
+ /* Validation Bits */
+ build_append_int_noprefix(table,
+ (1ULL << 14) | /* Type Valid */
+ (1ULL << 1) /* Physical Address Valid */,
+ 8);
+ /* Error Status */
+ build_append_int_noprefix(table, 0, 8);
+ /* Physical Address */
+ build_append_int_noprefix(table, error_physical_addr, 8);
+ /* Skip all the detailed information normally found in such a record */
+ build_append_int_noprefix(table, 0, 48);
+ /* Memory Error Type */
+ build_append_int_noprefix(table, 0 /* Unknown error */, 1);
+ /* Skip all the detailed information normally found in such a record */
+ build_append_int_noprefix(table, 0, 7);
+}
+
+static int acpi_ghes_record_mem_error(uint64_t error_block_address,
+ uint64_t error_physical_addr)
+{
+ GArray *block;
+
+ /* Memory Error Section Type */
+ const uint8_t uefi_cper_mem_sec[] =
+ UUID_LE(0xA5BC1114, 0x6F64, 0x4EDE, 0xB8, 0x63, 0x3E, 0x83, \
+ 0xED, 0x7C, 0x83, 0xB1);
+
+ /* invalid fru id: ACPI 4.0: 17.3.2.6.1 Generic Error Data,
+ * Table 17-13 Generic Error Data Entry
+ */
+ QemuUUID fru_id = {};
+ uint32_t data_length;
+
+ block = g_array_new(false, true /* clear */, 1);
+
+ /* This is the length if adding a new generic error data entry*/
+ data_length = ACPI_GHES_DATA_LENGTH + ACPI_GHES_MEM_CPER_LENGTH;
+
+ /*
+ * Check whether it will run out of the preallocated memory if adding a new
+ * generic error data entry
+ */
+ if ((data_length + ACPI_GHES_GESB_SIZE) > ACPI_GHES_MAX_RAW_DATA_LENGTH) {
+ error_report("Not enough memory to record new CPER!!!");
+ g_array_free(block, true);
+ return -1;
+ }
+
+ /* Build the new generic error status block header */
+ acpi_ghes_generic_error_status(block, ACPI_GEBS_UNCORRECTABLE,
+ 0, 0, data_length, ACPI_CPER_SEV_RECOVERABLE);
+
+ /* Build this new generic error data entry header */
+ acpi_ghes_generic_error_data(block, uefi_cper_mem_sec,
+ ACPI_CPER_SEV_RECOVERABLE, 0, 0,
+ ACPI_GHES_MEM_CPER_LENGTH, fru_id, 0);
+
+ /* Build the memory section CPER for above new generic error data entry */
+ acpi_ghes_build_append_mem_cper(block, error_physical_addr);
+
+ /* Write the generic error data entry into guest memory */
+ cpu_physical_memory_write(error_block_address, block->data, block->len);
+
+ g_array_free(block, true);
+
+ return 0;
+}
+
+/*
+ * Build table for the hardware error fw_cfg blob.
+ * Initialize "etc/hardware_errors" and "etc/hardware_errors_addr" fw_cfg blobs.
+ * See docs/specs/acpi_hest_ghes.rst for blobs format.
+ */
+void build_ghes_error_table(GArray *hardware_errors, BIOSLinker *linker)
+{
+ int i, error_status_block_offset;
+
+ /* Build error_block_address */
+ for (i = 0; i < ACPI_GHES_ERROR_SOURCE_COUNT; i++) {
+ build_append_int_noprefix(hardware_errors, 0, sizeof(uint64_t));
+ }
+
+ /* Build read_ack_register */
+ for (i = 0; i < ACPI_GHES_ERROR_SOURCE_COUNT; i++) {
+ /*
+ * Initialize the value of read_ack_register to 1, so GHES can be
+ * writeable after (re)boot.
+ * ACPI 6.2: 18.3.2.8 Generic Hardware Error Source version 2
+ * (GHESv2 - Type 10)
+ */
+ build_append_int_noprefix(hardware_errors, 1, sizeof(uint64_t));
+ }
+
+ /* Generic Error Status Block offset in the hardware error fw_cfg blob */
+ error_status_block_offset = hardware_errors->len;
+
+ /* Reserve space for Error Status Data Block */
+ acpi_data_push(hardware_errors,
+ ACPI_GHES_MAX_RAW_DATA_LENGTH * ACPI_GHES_ERROR_SOURCE_COUNT);
+
+ /* Tell guest firmware to place hardware_errors blob into RAM */
+ bios_linker_loader_alloc(linker, ACPI_GHES_ERRORS_FW_CFG_FILE,
+ hardware_errors, sizeof(uint64_t), false);
+
+ for (i = 0; i < ACPI_GHES_ERROR_SOURCE_COUNT; i++) {
+ /*
+ * Tell firmware to patch error_block_address entries to point to
+ * corresponding "Generic Error Status Block"
+ */
+ bios_linker_loader_add_pointer(linker,
+ ACPI_GHES_ERRORS_FW_CFG_FILE, sizeof(uint64_t) * i,
+ sizeof(uint64_t), ACPI_GHES_ERRORS_FW_CFG_FILE,
+ error_status_block_offset + i * ACPI_GHES_MAX_RAW_DATA_LENGTH);
+ }
+
+ /*
+ * tell firmware to write hardware_errors GPA into
+ * hardware_errors_addr fw_cfg, once the former has been initialized.
+ */
+ bios_linker_loader_write_pointer(linker, ACPI_GHES_DATA_ADDR_FW_CFG_FILE,
+ 0, sizeof(uint64_t), ACPI_GHES_ERRORS_FW_CFG_FILE, 0);
+}
+
+/* Build Generic Hardware Error Source version 2 (GHESv2) */
+static void build_ghes_v2(GArray *table_data, int source_id, BIOSLinker *linker)
+{
+ uint64_t address_offset;
+ /*
+ * Type:
+ * Generic Hardware Error Source version 2(GHESv2 - Type 10)
+ */
+ build_append_int_noprefix(table_data, ACPI_GHES_SOURCE_GENERIC_ERROR_V2, 2);
+ /* Source Id */
+ build_append_int_noprefix(table_data, source_id, 2);
+ /* Related Source Id */
+ build_append_int_noprefix(table_data, 0xffff, 2);
+ /* Flags */
+ build_append_int_noprefix(table_data, 0, 1);
+ /* Enabled */
+ build_append_int_noprefix(table_data, 1, 1);
+
+ /* Number of Records To Pre-allocate */
+ build_append_int_noprefix(table_data, 1, 4);
+ /* Max Sections Per Record */
+ build_append_int_noprefix(table_data, 1, 4);
+ /* Max Raw Data Length */
+ build_append_int_noprefix(table_data, ACPI_GHES_MAX_RAW_DATA_LENGTH, 4);
+
+ address_offset = table_data->len;
+ /* Error Status Address */
+ build_append_gas(table_data, AML_AS_SYSTEM_MEMORY, 0x40, 0,
+ 4 /* QWord access */, 0);
+ bios_linker_loader_add_pointer(linker, ACPI_BUILD_TABLE_FILE,
+ address_offset + GAS_ADDR_OFFSET, sizeof(uint64_t),
+ ACPI_GHES_ERRORS_FW_CFG_FILE, source_id * sizeof(uint64_t));
+
+ switch (source_id) {
+ case ACPI_HEST_SRC_ID_SEA:
+ /*
+ * Notification Structure
+ * Now only enable ARMv8 SEA notification type
+ */
+ build_ghes_hw_error_notification(table_data, ACPI_GHES_NOTIFY_SEA);
+ break;
+ default:
+ error_report("Not support this error source");
+ abort();
+ }
+
+ /* Error Status Block Length */
+ build_append_int_noprefix(table_data, ACPI_GHES_MAX_RAW_DATA_LENGTH, 4);
+
+ /*
+ * Read Ack Register
+ * ACPI 6.1: 18.3.2.8 Generic Hardware Error Source
+ * version 2 (GHESv2 - Type 10)
+ */
+ address_offset = table_data->len;
+ build_append_gas(table_data, AML_AS_SYSTEM_MEMORY, 0x40, 0,
+ 4 /* QWord access */, 0);
+ bios_linker_loader_add_pointer(linker, ACPI_BUILD_TABLE_FILE,
+ address_offset + GAS_ADDR_OFFSET,
+ sizeof(uint64_t), ACPI_GHES_ERRORS_FW_CFG_FILE,
+ (ACPI_GHES_ERROR_SOURCE_COUNT + source_id) * sizeof(uint64_t));
+
+ /*
+ * Read Ack Preserve field
+ * We only provide the first bit in Read Ack Register to OSPM to write
+ * while the other bits are preserved.
+ */
+ build_append_int_noprefix(table_data, ~0x1ULL, 8);
+ /* Read Ack Write */
+ build_append_int_noprefix(table_data, 0x1, 8);
+}
+
+/* Build Hardware Error Source Table */
+void acpi_build_hest(GArray *table_data, BIOSLinker *linker)
+{
+ uint64_t hest_start = table_data->len;
+
+ /* Hardware Error Source Table header*/
+ acpi_data_push(table_data, sizeof(AcpiTableHeader));
+
+ /* Error Source Count */
+ build_append_int_noprefix(table_data, ACPI_GHES_ERROR_SOURCE_COUNT, 4);
+
+ build_ghes_v2(table_data, ACPI_HEST_SRC_ID_SEA, linker);
+
+ build_header(linker, table_data, (void *)(table_data->data + hest_start),
+ "HEST", table_data->len - hest_start, 1, NULL, NULL);
+}
+
+void acpi_ghes_add_fw_cfg(AcpiGhesState *ags, FWCfgState *s,
+ GArray *hardware_error)
+{
+ /* Create a read-only fw_cfg file for GHES */
+ fw_cfg_add_file(s, ACPI_GHES_ERRORS_FW_CFG_FILE, hardware_error->data,
+ hardware_error->len);
+
+ /* Create a read-write fw_cfg file for Address */
+ fw_cfg_add_file_callback(s, ACPI_GHES_DATA_ADDR_FW_CFG_FILE, NULL, NULL,
+ NULL, &(ags->ghes_addr_le), sizeof(ags->ghes_addr_le), false);
+}
+
+int acpi_ghes_record_errors(uint8_t source_id, uint64_t physical_address)
+{
+ uint64_t error_block_addr, read_ack_register_addr, read_ack_register = 0;
+ uint64_t start_addr;
+ bool ret = -1;
+ AcpiGedState *acpi_ged_state;
+ AcpiGhesState *ags;
+
+ assert(source_id < ACPI_HEST_SRC_ID_RESERVED);
+
+ acpi_ged_state = ACPI_GED(object_resolve_path_type("", TYPE_ACPI_GED,
+ NULL));
+ g_assert(acpi_ged_state);
+ ags = &acpi_ged_state->ghes_state;
+
+ start_addr = le64_to_cpu(ags->ghes_addr_le);
+
+ if (physical_address) {
+
+ if (source_id < ACPI_HEST_SRC_ID_RESERVED) {
+ start_addr += source_id * sizeof(uint64_t);
+ }
+
+ cpu_physical_memory_read(start_addr, &error_block_addr,
+ sizeof(error_block_addr));
+
+ error_block_addr = le64_to_cpu(error_block_addr);
+
+ read_ack_register_addr = start_addr +
+ ACPI_GHES_ERROR_SOURCE_COUNT * sizeof(uint64_t);
+
+ cpu_physical_memory_read(read_ack_register_addr,
+ &read_ack_register, sizeof(read_ack_register));
+
+ /* zero means OSPM does not acknowledge the error */
+ if (!read_ack_register) {
+ error_report("OSPM does not acknowledge previous error,"
+ " so can not record CPER for current error anymore");
+ } else if (error_block_addr) {
+ read_ack_register = cpu_to_le64(0);
+ /*
+ * Clear the Read Ack Register, OSPM will write it to 1 when
+ * it acknowledges this error.
+ */
+ cpu_physical_memory_write(read_ack_register_addr,
+ &read_ack_register, sizeof(uint64_t));
+
+ ret = acpi_ghes_record_mem_error(error_block_addr,
+ physical_address);
+ } else
+ error_report("can not find Generic Error Status Block");
+ }
+
+ return ret;
+}
diff --git a/hw/acpi/ich9.c b/hw/acpi/ich9.c
index 336cace..2d204ba 100644
--- a/hw/acpi/ich9.c
+++ b/hw/acpi/ich9.c
@@ -369,7 +369,7 @@
s->pm.enable_tco = value;
}
-void ich9_pm_add_properties(Object *obj, ICH9LPCPMRegs *pm, Error **errp)
+void ich9_pm_add_properties(Object *obj, ICH9LPCPMRegs *pm)
{
static const uint32_t gpe0_len = ICH9_PMIO_GPE0_LEN;
pm->acpi_memory_hotplug.is_enabled = true;
@@ -379,32 +379,27 @@
pm->s4_val = 2;
object_property_add_uint32_ptr(obj, ACPI_PM_PROP_PM_IO_BASE,
- &pm->pm_io_base, OBJ_PROP_FLAG_READ, errp);
+ &pm->pm_io_base, OBJ_PROP_FLAG_READ);
object_property_add(obj, ACPI_PM_PROP_GPE0_BLK, "uint32",
ich9_pm_get_gpe0_blk,
- NULL, NULL, pm, NULL);
+ NULL, NULL, pm);
object_property_add_uint32_ptr(obj, ACPI_PM_PROP_GPE0_BLK_LEN,
- &gpe0_len, OBJ_PROP_FLAG_READ, errp);
+ &gpe0_len, OBJ_PROP_FLAG_READ);
object_property_add_bool(obj, "memory-hotplug-support",
ich9_pm_get_memory_hotplug_support,
- ich9_pm_set_memory_hotplug_support,
- NULL);
+ ich9_pm_set_memory_hotplug_support);
object_property_add_bool(obj, "cpu-hotplug-legacy",
ich9_pm_get_cpu_hotplug_legacy,
- ich9_pm_set_cpu_hotplug_legacy,
- NULL);
+ ich9_pm_set_cpu_hotplug_legacy);
object_property_add_uint8_ptr(obj, ACPI_PM_PROP_S3_DISABLED,
- &pm->disable_s3, OBJ_PROP_FLAG_READWRITE,
- NULL);
+ &pm->disable_s3, OBJ_PROP_FLAG_READWRITE);
object_property_add_uint8_ptr(obj, ACPI_PM_PROP_S4_DISABLED,
- &pm->disable_s4, OBJ_PROP_FLAG_READWRITE,
- NULL);
+ &pm->disable_s4, OBJ_PROP_FLAG_READWRITE);
object_property_add_uint8_ptr(obj, ACPI_PM_PROP_S4_VAL,
- &pm->s4_val, OBJ_PROP_FLAG_READWRITE, NULL);
+ &pm->s4_val, OBJ_PROP_FLAG_READWRITE);
object_property_add_bool(obj, ACPI_PM_PROP_TCO_ENABLED,
ich9_pm_get_enable_tco,
- ich9_pm_set_enable_tco,
- NULL);
+ ich9_pm_set_enable_tco);
}
void ich9_pm_device_pre_plug_cb(HotplugHandler *hotplug_dev, DeviceState *dev,
diff --git a/hw/acpi/nvdimm.c b/hw/acpi/nvdimm.c
index fa7bf8b..9316d12 100644
--- a/hw/acpi/nvdimm.c
+++ b/hw/acpi/nvdimm.c
@@ -27,6 +27,7 @@
*/
#include "qemu/osdep.h"
+#include "qemu/uuid.h"
#include "hw/acpi/acpi.h"
#include "hw/acpi/aml-build.h"
#include "hw/acpi/bios-linker-loader.h"
@@ -34,18 +35,13 @@
#include "hw/mem/nvdimm.h"
#include "qemu/nvdimm-utils.h"
-#define NVDIMM_UUID_LE(a, b, c, d0, d1, d2, d3, d4, d5, d6, d7) \
- { (a) & 0xff, ((a) >> 8) & 0xff, ((a) >> 16) & 0xff, ((a) >> 24) & 0xff, \
- (b) & 0xff, ((b) >> 8) & 0xff, (c) & 0xff, ((c) >> 8) & 0xff, \
- (d0), (d1), (d2), (d3), (d4), (d5), (d6), (d7) }
-
/*
* define Byte Addressable Persistent Memory (PM) Region according to
* ACPI 6.0: 5.2.25.1 System Physical Address Range Structure.
*/
static const uint8_t nvdimm_nfit_spa_uuid[] =
- NVDIMM_UUID_LE(0x66f0d379, 0xb4f3, 0x4074, 0xac, 0x43, 0x0d, 0x33,
- 0x18, 0xb7, 0x8c, 0xdb);
+ UUID_LE(0x66f0d379, 0xb4f3, 0x4074, 0xac, 0x43, 0x0d, 0x33,
+ 0x18, 0xb7, 0x8c, 0xdb);
/*
* NVDIMM Firmware Interface Table
diff --git a/hw/acpi/pcihp.c b/hw/acpi/pcihp.c
index 0dc963e..d42906e 100644
--- a/hw/acpi/pcihp.c
+++ b/hw/acpi/pcihp.c
@@ -80,8 +80,7 @@
*bus_bsel = (*bsel_alloc)++;
object_property_add_uint32_ptr(OBJECT(bus), ACPI_PCIHP_PROP_BSEL,
- bus_bsel, OBJ_PROP_FLAG_READ,
- &error_abort);
+ bus_bsel, OBJ_PROP_FLAG_READ);
}
return bsel_alloc;
@@ -267,7 +266,7 @@
{
trace_acpi_pci_unplug(PCI_SLOT(PCI_DEVICE(dev)->devfn),
acpi_pcihp_get_bsel(pci_get_bus(PCI_DEVICE(dev))));
- object_property_set_bool(OBJECT(dev), false, "realized", NULL);
+ object_property_set_bool(OBJECT(dev), false, "realized", &error_abort);
}
void acpi_pcihp_device_unplug_request_cb(HotplugHandler *hotplug_dev,
@@ -374,9 +373,9 @@
memory_region_add_subregion(address_space_io, s->io_base, &s->io);
object_property_add_uint16_ptr(owner, ACPI_PCIHP_IO_BASE_PROP, &s->io_base,
- OBJ_PROP_FLAG_READ, &error_abort);
+ OBJ_PROP_FLAG_READ);
object_property_add_uint16_ptr(owner, ACPI_PCIHP_IO_LEN_PROP, &s->io_len,
- OBJ_PROP_FLAG_READ, &error_abort);
+ OBJ_PROP_FLAG_READ);
}
const VMStateDescription vmstate_acpi_pcihp_pci_status = {
diff --git a/hw/acpi/piix4.c b/hw/acpi/piix4.c
index 964d6f5..85c199b 100644
--- a/hw/acpi/piix4.c
+++ b/hw/acpi/piix4.c
@@ -444,17 +444,17 @@
static const uint16_t sci_int = 9;
object_property_add_uint8_ptr(OBJECT(s), ACPI_PM_PROP_ACPI_ENABLE_CMD,
- &acpi_enable_cmd, OBJ_PROP_FLAG_READ, NULL);
+ &acpi_enable_cmd, OBJ_PROP_FLAG_READ);
object_property_add_uint8_ptr(OBJECT(s), ACPI_PM_PROP_ACPI_DISABLE_CMD,
- &acpi_disable_cmd, OBJ_PROP_FLAG_READ, NULL);
+ &acpi_disable_cmd, OBJ_PROP_FLAG_READ);
object_property_add_uint32_ptr(OBJECT(s), ACPI_PM_PROP_GPE0_BLK,
- &gpe0_blk, OBJ_PROP_FLAG_READ, NULL);
+ &gpe0_blk, OBJ_PROP_FLAG_READ);
object_property_add_uint32_ptr(OBJECT(s), ACPI_PM_PROP_GPE0_BLK_LEN,
- &gpe0_blk_len, OBJ_PROP_FLAG_READ, NULL);
+ &gpe0_blk_len, OBJ_PROP_FLAG_READ);
object_property_add_uint16_ptr(OBJECT(s), ACPI_PM_PROP_SCI_INT,
- &sci_int, OBJ_PROP_FLAG_READ, NULL);
+ &sci_int, OBJ_PROP_FLAG_READ);
object_property_add_uint32_ptr(OBJECT(s), ACPI_PM_PROP_PM_IO_BASE,
- &s->io_base, OBJ_PROP_FLAG_READ, NULL);
+ &s->io_base, OBJ_PROP_FLAG_READ);
}
static void piix4_pm_realize(PCIDevice *dev, Error **errp)
@@ -598,8 +598,7 @@
s->cpu_hotplug_legacy = true;
object_property_add_bool(OBJECT(s), "cpu-hotplug-legacy",
piix4_get_cpu_hotplug_legacy,
- piix4_set_cpu_hotplug_legacy,
- NULL);
+ piix4_set_cpu_hotplug_legacy);
legacy_acpi_cpu_hotplug_init(parent, OBJECT(s), &s->gpe_cpu,
PIIX4_CPU_HOTPLUG_IO_BASE);
diff --git a/hw/arm/Kconfig b/hw/arm/Kconfig
index 5364172..9afa6ee 100644
--- a/hw/arm/Kconfig
+++ b/hw/arm/Kconfig
@@ -359,6 +359,7 @@
select IMX
select IMX_FEC
select IMX_I2C
+ select WDT_IMX2
select DS1338
config FSL_IMX31
@@ -366,6 +367,7 @@
select SERIAL
select IMX
select IMX_I2C
+ select WDT_IMX2
select LAN9118
config FSL_IMX6
@@ -375,6 +377,7 @@
select IMX_FEC
select IMX_I2C
select IMX_USBPHY
+ select WDT_IMX2
select SDHCI
config ASPEED_SOC
@@ -412,6 +415,7 @@
select IMX
select IMX_FEC
select IMX_I2C
+ select WDT_IMX2
select PCI_EXPRESS_DESIGNWARE
select SDHCI
select UNIMP
@@ -425,6 +429,7 @@
select IMX
select IMX_FEC
select IMX_I2C
+ select WDT_IMX2
select SDHCI
select UNIMP
diff --git a/hw/arm/allwinner-a10.c b/hw/arm/allwinner-a10.c
index 62a67a3..6e1329a 100644
--- a/hw/arm/allwinner-a10.c
+++ b/hw/arm/allwinner-a10.c
@@ -178,7 +178,7 @@
sysbus_mmio_map(SYS_BUS_DEVICE(&s->mmc0), 0, AW_A10_MMC0_BASE);
sysbus_connect_irq(SYS_BUS_DEVICE(&s->mmc0), 0, qdev_get_gpio_in(dev, 32));
object_property_add_alias(OBJECT(s), "sd-bus", OBJECT(&s->mmc0),
- "sd-bus", &error_abort);
+ "sd-bus");
/* RTC */
qdev_init_nofail(DEVICE(&s->rtc));
diff --git a/hw/arm/allwinner-h3.c b/hw/arm/allwinner-h3.c
index 9e4ce36..f10674d 100644
--- a/hw/arm/allwinner-h3.c
+++ b/hw/arm/allwinner-h3.c
@@ -205,9 +205,9 @@
sysbus_init_child_obj(obj, "timer", &s->timer, sizeof(s->timer),
TYPE_AW_A10_PIT);
object_property_add_alias(obj, "clk0-freq", OBJECT(&s->timer),
- "clk0-freq", &error_abort);
+ "clk0-freq");
object_property_add_alias(obj, "clk1-freq", OBJECT(&s->timer),
- "clk1-freq", &error_abort);
+ "clk1-freq");
sysbus_init_child_obj(obj, "ccu", &s->ccu, sizeof(s->ccu),
TYPE_AW_H3_CCU);
@@ -221,7 +221,7 @@
sysbus_init_child_obj(obj, "sid", &s->sid, sizeof(s->sid),
TYPE_AW_SID);
object_property_add_alias(obj, "identifier", OBJECT(&s->sid),
- "identifier", &error_abort);
+ "identifier");
sysbus_init_child_obj(obj, "mmc0", &s->mmc0, sizeof(s->mmc0),
TYPE_AW_SDHOST_SUN5I);
@@ -232,9 +232,9 @@
sysbus_init_child_obj(obj, "dramc", &s->dramc, sizeof(s->dramc),
TYPE_AW_H3_DRAMC);
object_property_add_alias(obj, "ram-addr", OBJECT(&s->dramc),
- "ram-addr", &error_abort);
+ "ram-addr");
object_property_add_alias(obj, "ram-size", OBJECT(&s->dramc),
- "ram-size", &error_abort);
+ "ram-size");
sysbus_init_child_obj(obj, "rtc", &s->rtc, sizeof(s->rtc),
TYPE_AW_RTC_SUN6I);
@@ -366,7 +366,7 @@
qdev_get_gpio_in(DEVICE(&s->gic), AW_H3_GIC_SPI_MMC0));
object_property_add_alias(OBJECT(s), "sd-bus", OBJECT(&s->mmc0),
- "sd-bus", &error_abort);
+ "sd-bus");
/* EMAC */
if (nd_table[0].used) {
diff --git a/hw/arm/armv7m.c b/hw/arm/armv7m.c
index 7531b97..7da57f5 100644
--- a/hw/arm/armv7m.c
+++ b/hw/arm/armv7m.c
@@ -138,7 +138,7 @@
sysbus_init_child_obj(obj, "nvnic", &s->nvic, sizeof(s->nvic), TYPE_NVIC);
object_property_add_alias(obj, "num-irq",
- OBJECT(&s->nvic), "num-irq", &error_abort);
+ OBJECT(&s->nvic), "num-irq");
for (i = 0; i < ARRAY_SIZE(s->bitband); i++) {
sysbus_init_child_obj(obj, "bitband[*]", &s->bitband[i],
diff --git a/hw/arm/aspeed.c b/hw/arm/aspeed.c
index 1eacb2f..2c23297 100644
--- a/hw/arm/aspeed.c
+++ b/hw/arm/aspeed.c
@@ -73,6 +73,21 @@
SCU_AST2500_HW_STRAP_ACPI_ENABLE | \
SCU_HW_STRAP_SPI_MODE(SCU_HW_STRAP_SPI_MASTER))
+/* Sonorapass hardware value: 0xF100D216 */
+#define SONORAPASS_BMC_HW_STRAP1 ( \
+ SCU_AST2500_HW_STRAP_SPI_AUTOFETCH_ENABLE | \
+ SCU_AST2500_HW_STRAP_GPIO_STRAP_ENABLE | \
+ SCU_AST2500_HW_STRAP_UART_DEBUG | \
+ SCU_AST2500_HW_STRAP_RESERVED28 | \
+ SCU_AST2500_HW_STRAP_DDR4_ENABLE | \
+ SCU_HW_STRAP_VGA_CLASS_CODE | \
+ SCU_HW_STRAP_LPC_RESET_PIN | \
+ SCU_HW_STRAP_SPI_MODE(SCU_HW_STRAP_SPI_MASTER) | \
+ SCU_AST2500_HW_STRAP_SET_AXI_AHB_RATIO(AXI_AHB_RATIO_2_1) | \
+ SCU_HW_STRAP_VGA_BIOS_ROM | \
+ SCU_HW_STRAP_VGA_SIZE_SET(VGA_16M_DRAM) | \
+ SCU_AST2500_HW_STRAP_RESERVED1)
+
/* Swift hardware value: 0xF11AD206 */
#define SWIFT_BMC_HW_STRAP1 ( \
AST2500_HW_STRAP1_DEFAULTS | \
@@ -437,6 +452,50 @@
i2c_create_slave(aspeed_i2c_get_bus(DEVICE(&soc->i2c), 12), "tmp105", 0x4a);
}
+static void sonorapass_bmc_i2c_init(AspeedBoardState *bmc)
+{
+ AspeedSoCState *soc = &bmc->soc;
+
+ /* bus 2 : */
+ i2c_create_slave(aspeed_i2c_get_bus(DEVICE(&soc->i2c), 2), "tmp105", 0x48);
+ i2c_create_slave(aspeed_i2c_get_bus(DEVICE(&soc->i2c), 2), "tmp105", 0x49);
+ /* bus 2 : pca9546 @ 0x73 */
+
+ /* bus 3 : pca9548 @ 0x70 */
+
+ /* bus 4 : */
+ uint8_t *eeprom4_54 = g_malloc0(8 * 1024);
+ smbus_eeprom_init_one(aspeed_i2c_get_bus(DEVICE(&soc->i2c), 4), 0x54,
+ eeprom4_54);
+ /* PCA9539 @ 0x76, but PCA9552 is compatible */
+ i2c_create_slave(aspeed_i2c_get_bus(DEVICE(&soc->i2c), 4), "pca9552", 0x76);
+ /* PCA9539 @ 0x77, but PCA9552 is compatible */
+ i2c_create_slave(aspeed_i2c_get_bus(DEVICE(&soc->i2c), 4), "pca9552", 0x77);
+
+ /* bus 6 : */
+ i2c_create_slave(aspeed_i2c_get_bus(DEVICE(&soc->i2c), 6), "tmp105", 0x48);
+ i2c_create_slave(aspeed_i2c_get_bus(DEVICE(&soc->i2c), 6), "tmp105", 0x49);
+ /* bus 6 : pca9546 @ 0x73 */
+
+ /* bus 8 : */
+ uint8_t *eeprom8_56 = g_malloc0(8 * 1024);
+ smbus_eeprom_init_one(aspeed_i2c_get_bus(DEVICE(&soc->i2c), 8), 0x56,
+ eeprom8_56);
+ i2c_create_slave(aspeed_i2c_get_bus(DEVICE(&soc->i2c), 8), "pca9552", 0x60);
+ i2c_create_slave(aspeed_i2c_get_bus(DEVICE(&soc->i2c), 8), "pca9552", 0x61);
+ /* bus 8 : adc128d818 @ 0x1d */
+ /* bus 8 : adc128d818 @ 0x1f */
+
+ /*
+ * bus 13 : pca9548 @ 0x71
+ * - channel 3:
+ * - tmm421 @ 0x4c
+ * - tmp421 @ 0x4e
+ * - tmp421 @ 0x4f
+ */
+
+}
+
static void witherspoon_bmc_i2c_init(AspeedBoardState *bmc)
{
AspeedSoCState *soc = &bmc->soc;
@@ -485,9 +544,9 @@
{
object_class_property_add_bool(oc, "execute-in-place",
aspeed_get_mmio_exec,
- aspeed_set_mmio_exec, &error_abort);
+ aspeed_set_mmio_exec);
object_class_property_set_description(oc, "execute-in-place",
- "boot directly from CE0 flash device", &error_abort);
+ "boot directly from CE0 flash device");
}
static void aspeed_machine_class_init(ObjectClass *oc, void *data)
@@ -549,6 +608,21 @@
mc->default_ram_size = 512 * MiB;
};
+static void aspeed_machine_sonorapass_class_init(ObjectClass *oc, void *data)
+{
+ MachineClass *mc = MACHINE_CLASS(oc);
+ AspeedMachineClass *amc = ASPEED_MACHINE_CLASS(oc);
+
+ mc->desc = "OCP SonoraPass BMC (ARM1176)";
+ amc->soc_name = "ast2500-a1";
+ amc->hw_strap1 = SONORAPASS_BMC_HW_STRAP1;
+ amc->fmc_model = "mx66l1g45g";
+ amc->spi_model = "mx66l1g45g";
+ amc->num_cs = 2;
+ amc->i2c_init = sonorapass_bmc_i2c_init;
+ mc->default_ram_size = 512 * MiB;
+};
+
static void aspeed_machine_swift_class_init(ObjectClass *oc, void *data)
{
MachineClass *mc = MACHINE_CLASS(oc);
@@ -629,6 +703,10 @@
.parent = TYPE_ASPEED_MACHINE,
.class_init = aspeed_machine_swift_class_init,
}, {
+ .name = MACHINE_TYPE_NAME("sonorapass-bmc"),
+ .parent = TYPE_ASPEED_MACHINE,
+ .class_init = aspeed_machine_sonorapass_class_init,
+ }, {
.name = MACHINE_TYPE_NAME("witherspoon-bmc"),
.parent = TYPE_ASPEED_MACHINE,
.class_init = aspeed_machine_witherspoon_class_init,
diff --git a/hw/arm/aspeed_ast2600.c b/hw/arm/aspeed_ast2600.c
index c6e0ab8..71a0acf 100644
--- a/hw/arm/aspeed_ast2600.c
+++ b/hw/arm/aspeed_ast2600.c
@@ -138,11 +138,11 @@
qdev_prop_set_uint32(DEVICE(&s->scu), "silicon-rev",
sc->silicon_rev);
object_property_add_alias(obj, "hw-strap1", OBJECT(&s->scu),
- "hw-strap1", &error_abort);
+ "hw-strap1");
object_property_add_alias(obj, "hw-strap2", OBJECT(&s->scu),
- "hw-strap2", &error_abort);
+ "hw-strap2");
object_property_add_alias(obj, "hw-prot-key", OBJECT(&s->scu),
- "hw-prot-key", &error_abort);
+ "hw-prot-key");
sysbus_init_child_obj(obj, "a7mpcore", &s->a7mpcore,
sizeof(s->a7mpcore), TYPE_A15MPCORE_PRIV);
@@ -161,8 +161,7 @@
snprintf(typename, sizeof(typename), "aspeed.fmc-%s", socname);
sysbus_init_child_obj(obj, "fmc", OBJECT(&s->fmc), sizeof(s->fmc),
typename);
- object_property_add_alias(obj, "num-cs", OBJECT(&s->fmc), "num-cs",
- &error_abort);
+ object_property_add_alias(obj, "num-cs", OBJECT(&s->fmc), "num-cs");
for (i = 0; i < sc->spis_num; i++) {
snprintf(typename, sizeof(typename), "aspeed.spi%d-%s", i + 1, socname);
@@ -179,9 +178,9 @@
sysbus_init_child_obj(obj, "sdmc", OBJECT(&s->sdmc), sizeof(s->sdmc),
typename);
object_property_add_alias(obj, "ram-size", OBJECT(&s->sdmc),
- "ram-size", &error_abort);
+ "ram-size");
object_property_add_alias(obj, "max-ram-size", OBJECT(&s->sdmc),
- "max-ram-size", &error_abort);
+ "max-ram-size");
for (i = 0; i < sc->wdts_num; i++) {
snprintf(typename, sizeof(typename), "aspeed.wdt-%s", socname);
diff --git a/hw/arm/aspeed_soc.c b/hw/arm/aspeed_soc.c
index 696c7fd..cf6b6dd 100644
--- a/hw/arm/aspeed_soc.c
+++ b/hw/arm/aspeed_soc.c
@@ -153,11 +153,11 @@
qdev_prop_set_uint32(DEVICE(&s->scu), "silicon-rev",
sc->silicon_rev);
object_property_add_alias(obj, "hw-strap1", OBJECT(&s->scu),
- "hw-strap1", &error_abort);
+ "hw-strap1");
object_property_add_alias(obj, "hw-strap2", OBJECT(&s->scu),
- "hw-strap2", &error_abort);
+ "hw-strap2");
object_property_add_alias(obj, "hw-prot-key", OBJECT(&s->scu),
- "hw-prot-key", &error_abort);
+ "hw-prot-key");
sysbus_init_child_obj(obj, "vic", OBJECT(&s->vic), sizeof(s->vic),
TYPE_ASPEED_VIC);
@@ -176,8 +176,7 @@
snprintf(typename, sizeof(typename), "aspeed.fmc-%s", socname);
sysbus_init_child_obj(obj, "fmc", OBJECT(&s->fmc), sizeof(s->fmc),
typename);
- object_property_add_alias(obj, "num-cs", OBJECT(&s->fmc), "num-cs",
- &error_abort);
+ object_property_add_alias(obj, "num-cs", OBJECT(&s->fmc), "num-cs");
for (i = 0; i < sc->spis_num; i++) {
snprintf(typename, sizeof(typename), "aspeed.spi%d-%s", i + 1, socname);
@@ -194,9 +193,9 @@
sysbus_init_child_obj(obj, "sdmc", OBJECT(&s->sdmc), sizeof(s->sdmc),
typename);
object_property_add_alias(obj, "ram-size", OBJECT(&s->sdmc),
- "ram-size", &error_abort);
+ "ram-size");
object_property_add_alias(obj, "max-ram-size", OBJECT(&s->sdmc),
- "max-ram-size", &error_abort);
+ "max-ram-size");
for (i = 0; i < sc->wdts_num; i++) {
snprintf(typename, sizeof(typename), "aspeed.wdt-%s", socname);
diff --git a/hw/arm/bcm2835_peripherals.c b/hw/arm/bcm2835_peripherals.c
index edcaa49..f1bcc14 100644
--- a/hw/arm/bcm2835_peripherals.c
+++ b/hw/arm/bcm2835_peripherals.c
@@ -43,12 +43,10 @@
/* Memory region for peripheral devices, which we export to our parent */
memory_region_init(&s->peri_mr, obj,"bcm2835-peripherals", 0x1000000);
- object_property_add_child(obj, "peripheral-io", OBJECT(&s->peri_mr), NULL);
sysbus_init_mmio(SYS_BUS_DEVICE(s), &s->peri_mr);
/* Internal memory region for peripheral bus addresses (not exported) */
memory_region_init(&s->gpu_bus_mr, obj, "bcm2835-gpu", (uint64_t)1 << 32);
- object_property_add_child(obj, "gpu-bus", OBJECT(&s->gpu_bus_mr), NULL);
/* Internal memory region for request/response communication with
* mailbox-addressable peripherals (not exported)
@@ -76,26 +74,25 @@
TYPE_BCM2835_MBOX);
object_property_add_const_link(OBJECT(&s->mboxes), "mbox-mr",
- OBJECT(&s->mbox_mr), &error_abort);
+ OBJECT(&s->mbox_mr));
/* Framebuffer */
sysbus_init_child_obj(obj, "fb", &s->fb, sizeof(s->fb), TYPE_BCM2835_FB);
- object_property_add_alias(obj, "vcram-size", OBJECT(&s->fb), "vcram-size",
- &error_abort);
+ object_property_add_alias(obj, "vcram-size", OBJECT(&s->fb), "vcram-size");
object_property_add_const_link(OBJECT(&s->fb), "dma-mr",
- OBJECT(&s->gpu_bus_mr), &error_abort);
+ OBJECT(&s->gpu_bus_mr));
/* Property channel */
sysbus_init_child_obj(obj, "property", &s->property, sizeof(s->property),
TYPE_BCM2835_PROPERTY);
object_property_add_alias(obj, "board-rev", OBJECT(&s->property),
- "board-rev", &error_abort);
+ "board-rev");
object_property_add_const_link(OBJECT(&s->property), "fb",
- OBJECT(&s->fb), &error_abort);
+ OBJECT(&s->fb));
object_property_add_const_link(OBJECT(&s->property), "dma-mr",
- OBJECT(&s->gpu_bus_mr), &error_abort);
+ OBJECT(&s->gpu_bus_mr));
/* Random Number Generator */
sysbus_init_child_obj(obj, "rng", &s->rng, sizeof(s->rng),
@@ -114,7 +111,7 @@
TYPE_BCM2835_DMA);
object_property_add_const_link(OBJECT(&s->dma), "dma-mr",
- OBJECT(&s->gpu_bus_mr), &error_abort);
+ OBJECT(&s->gpu_bus_mr));
/* Thermal */
sysbus_init_child_obj(obj, "thermal", &s->thermal, sizeof(s->thermal),
@@ -125,9 +122,9 @@
TYPE_BCM2835_GPIO);
object_property_add_const_link(OBJECT(&s->gpio), "sdbus-sdhci",
- OBJECT(&s->sdhci.sdbus), &error_abort);
+ OBJECT(&s->sdhci.sdbus));
object_property_add_const_link(OBJECT(&s->gpio), "sdbus-sdhost",
- OBJECT(&s->sdhost.sdbus), &error_abort);
+ OBJECT(&s->sdhost.sdbus));
}
static void bcm2835_peripherals_realize(DeviceState *dev, Error **errp)
@@ -361,12 +358,7 @@
memory_region_add_subregion(&s->peri_mr, GPIO_OFFSET,
sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->gpio), 0));
- object_property_add_alias(OBJECT(s), "sd-bus", OBJECT(&s->gpio), "sd-bus",
- &err);
- if (err) {
- error_propagate(errp, err);
- return;
- }
+ object_property_add_alias(OBJECT(s), "sd-bus", OBJECT(&s->gpio), "sd-bus");
create_unimp(s, &s->armtmr, "bcm2835-sp804", ARMCTRL_TIMER0_1_OFFSET, 0x40);
create_unimp(s, &s->cprman, "bcm2835-cprman", CPRMAN_OFFSET, 0x1000);
diff --git a/hw/arm/bcm2836.c b/hw/arm/bcm2836.c
index 43022b8..e51b4e0 100644
--- a/hw/arm/bcm2836.c
+++ b/hw/arm/bcm2836.c
@@ -63,9 +63,9 @@
sysbus_init_child_obj(obj, "peripherals", &s->peripherals,
sizeof(s->peripherals), TYPE_BCM2835_PERIPHERALS);
object_property_add_alias(obj, "board-rev", OBJECT(&s->peripherals),
- "board-rev", &error_abort);
+ "board-rev");
object_property_add_alias(obj, "vcram-size", OBJECT(&s->peripherals),
- "vcram-size", &error_abort);
+ "vcram-size");
}
static void bcm2836_realize(DeviceState *dev, Error **errp)
@@ -86,11 +86,7 @@
return;
}
- object_property_add_const_link(OBJECT(&s->peripherals), "ram", obj, &err);
- if (err) {
- error_propagate(errp, err);
- return;
- }
+ object_property_add_const_link(OBJECT(&s->peripherals), "ram", obj);
object_property_set_bool(OBJECT(&s->peripherals), true, "realized", &err);
if (err) {
@@ -99,11 +95,7 @@
}
object_property_add_alias(OBJECT(s), "sd-bus", OBJECT(&s->peripherals),
- "sd-bus", &err);
- if (err) {
- error_propagate(errp, err);
- return;
- }
+ "sd-bus");
sysbus_mmio_map_overlap(SYS_BUS_DEVICE(&s->peripherals), 0,
info->peri_base, 1);
diff --git a/hw/arm/cubieboard.c b/hw/arm/cubieboard.c
index 0b8ba44..cd1b6d3 100644
--- a/hw/arm/cubieboard.c
+++ b/hw/arm/cubieboard.c
@@ -59,8 +59,7 @@
}
a10 = AW_A10(object_new(TYPE_AW_A10));
- object_property_add_child(OBJECT(machine), "soc", OBJECT(a10),
- &error_abort);
+ object_property_add_child(OBJECT(machine), "soc", OBJECT(a10));
object_unref(OBJECT(a10));
object_property_set_int(OBJECT(&a10->emac), 1, "phy-addr", &err);
diff --git a/hw/arm/fsl-imx25.c b/hw/arm/fsl-imx25.c
index 6f1a82c..cdaa79c 100644
--- a/hw/arm/fsl-imx25.c
+++ b/hw/arm/fsl-imx25.c
@@ -87,6 +87,7 @@
TYPE_CHIPIDEA);
}
+ sysbus_init_child_obj(obj, "wdt", &s->wdt, sizeof(s->wdt), TYPE_IMX2_WDT);
}
static void fsl_imx25_realize(DeviceState *dev, Error **errp)
@@ -302,6 +303,15 @@
usb_table[i].irq));
}
+ /* Watchdog */
+ object_property_set_bool(OBJECT(&s->wdt), true, "pretimeout-support",
+ &error_abort);
+ object_property_set_bool(OBJECT(&s->wdt), true, "realized", &error_abort);
+ sysbus_mmio_map(SYS_BUS_DEVICE(&s->wdt), 0, FSL_IMX25_WDT_ADDR);
+ sysbus_connect_irq(SYS_BUS_DEVICE(&s->wdt), 0,
+ qdev_get_gpio_in(DEVICE(&s->avic),
+ FSL_IMX25_WDT_IRQ));
+
/* initialize 2 x 16 KB ROM */
memory_region_init_rom(&s->rom[0], OBJECT(dev), "imx25.rom0",
FSL_IMX25_ROM0_SIZE, &err);
diff --git a/hw/arm/fsl-imx31.c b/hw/arm/fsl-imx31.c
index 8472d2e..1e79598 100644
--- a/hw/arm/fsl-imx31.c
+++ b/hw/arm/fsl-imx31.c
@@ -63,6 +63,8 @@
sysbus_init_child_obj(obj, "gpio[*]", &s->gpio[i], sizeof(s->gpio[i]),
TYPE_IMX_GPIO);
}
+
+ sysbus_init_child_obj(obj, "wdt", &s->wdt, sizeof(s->wdt), TYPE_IMX2_WDT);
}
static void fsl_imx31_realize(DeviceState *dev, Error **errp)
@@ -205,6 +207,10 @@
gpio_table[i].irq));
}
+ /* Watchdog */
+ object_property_set_bool(OBJECT(&s->wdt), true, "realized", &error_abort);
+ sysbus_mmio_map(SYS_BUS_DEVICE(&s->wdt), 0, FSL_IMX31_WDT_ADDR);
+
/* On a real system, the first 16k is a `secure boot rom' */
memory_region_init_rom(&s->secure_rom, OBJECT(dev), "imx31.secure_rom",
FSL_IMX31_SECURE_ROM_SIZE, &err);
diff --git a/hw/arm/fsl-imx6.c b/hw/arm/fsl-imx6.c
index 13f1bf2..f58c85a 100644
--- a/hw/arm/fsl-imx6.c
+++ b/hw/arm/fsl-imx6.c
@@ -433,11 +433,20 @@
FSL_IMX6_WDOG1_ADDR,
FSL_IMX6_WDOG2_ADDR,
};
+ static const int FSL_IMX6_WDOGn_IRQ[FSL_IMX6_NUM_WDTS] = {
+ FSL_IMX6_WDOG1_IRQ,
+ FSL_IMX6_WDOG2_IRQ,
+ };
+ object_property_set_bool(OBJECT(&s->wdt[i]), true, "pretimeout-support",
+ &error_abort);
object_property_set_bool(OBJECT(&s->wdt[i]), true, "realized",
&error_abort);
sysbus_mmio_map(SYS_BUS_DEVICE(&s->wdt[i]), 0, FSL_IMX6_WDOGn_ADDR[i]);
+ sysbus_connect_irq(SYS_BUS_DEVICE(&s->wdt[i]), 0,
+ qdev_get_gpio_in(DEVICE(&s->a9mpcore),
+ FSL_IMX6_WDOGn_IRQ[i]));
}
/* ROM memory */
diff --git a/hw/arm/fsl-imx6ul.c b/hw/arm/fsl-imx6ul.c
index 56dfd7c..3ecb212 100644
--- a/hw/arm/fsl-imx6ul.c
+++ b/hw/arm/fsl-imx6ul.c
@@ -531,12 +531,22 @@
FSL_IMX6UL_WDOG2_ADDR,
FSL_IMX6UL_WDOG3_ADDR,
};
+ static const int FSL_IMX6UL_WDOGn_IRQ[FSL_IMX6UL_NUM_WDTS] = {
+ FSL_IMX6UL_WDOG1_IRQ,
+ FSL_IMX6UL_WDOG2_IRQ,
+ FSL_IMX6UL_WDOG3_IRQ,
+ };
+ object_property_set_bool(OBJECT(&s->wdt[i]), true, "pretimeout-support",
+ &error_abort);
object_property_set_bool(OBJECT(&s->wdt[i]), true, "realized",
&error_abort);
sysbus_mmio_map(SYS_BUS_DEVICE(&s->wdt[i]), 0,
FSL_IMX6UL_WDOGn_ADDR[i]);
+ sysbus_connect_irq(SYS_BUS_DEVICE(&s->wdt[i]), 0,
+ qdev_get_gpio_in(DEVICE(&s->a7mpcore),
+ FSL_IMX6UL_WDOGn_IRQ[i]));
}
/*
diff --git a/hw/arm/fsl-imx7.c b/hw/arm/fsl-imx7.c
index 119b281..89c3b64 100644
--- a/hw/arm/fsl-imx7.c
+++ b/hw/arm/fsl-imx7.c
@@ -447,11 +447,22 @@
FSL_IMX7_WDOG3_ADDR,
FSL_IMX7_WDOG4_ADDR,
};
+ static const int FSL_IMX7_WDOGn_IRQ[FSL_IMX7_NUM_WDTS] = {
+ FSL_IMX7_WDOG1_IRQ,
+ FSL_IMX7_WDOG2_IRQ,
+ FSL_IMX7_WDOG3_IRQ,
+ FSL_IMX7_WDOG4_IRQ,
+ };
+ object_property_set_bool(OBJECT(&s->wdt[i]), true, "pretimeout-support",
+ &error_abort);
object_property_set_bool(OBJECT(&s->wdt[i]), true, "realized",
&error_abort);
sysbus_mmio_map(SYS_BUS_DEVICE(&s->wdt[i]), 0, FSL_IMX7_WDOGn_ADDR[i]);
+ sysbus_connect_irq(SYS_BUS_DEVICE(&s->wdt[i]), 0,
+ qdev_get_gpio_in(DEVICE(&s->a7mpcore),
+ FSL_IMX7_WDOGn_IRQ[i]));
}
/*
@@ -459,6 +470,30 @@
*/
create_unimplemented_device("sdma", FSL_IMX7_SDMA_ADDR, FSL_IMX7_SDMA_SIZE);
+ /*
+ * CAAM
+ */
+ create_unimplemented_device("caam", FSL_IMX7_CAAM_ADDR, FSL_IMX7_CAAM_SIZE);
+
+ /*
+ * PWM
+ */
+ create_unimplemented_device("pwm1", FSL_IMX7_PWM1_ADDR, FSL_IMX7_PWMn_SIZE);
+ create_unimplemented_device("pwm2", FSL_IMX7_PWM2_ADDR, FSL_IMX7_PWMn_SIZE);
+ create_unimplemented_device("pwm3", FSL_IMX7_PWM3_ADDR, FSL_IMX7_PWMn_SIZE);
+ create_unimplemented_device("pwm4", FSL_IMX7_PWM4_ADDR, FSL_IMX7_PWMn_SIZE);
+
+ /*
+ * CAN
+ */
+ create_unimplemented_device("can1", FSL_IMX7_CAN1_ADDR, FSL_IMX7_CANn_SIZE);
+ create_unimplemented_device("can2", FSL_IMX7_CAN2_ADDR, FSL_IMX7_CANn_SIZE);
+
+ /*
+ * OCOTP
+ */
+ create_unimplemented_device("ocotp", FSL_IMX7_OCOTP_ADDR,
+ FSL_IMX7_OCOTP_SIZE);
object_property_set_bool(OBJECT(&s->gpr), true, "realized",
&error_abort);
diff --git a/hw/arm/integratorcp.c b/hw/arm/integratorcp.c
index 6d69010..5fb54e5 100644
--- a/hw/arm/integratorcp.c
+++ b/hw/arm/integratorcp.c
@@ -20,6 +20,7 @@
#include "exec/address-spaces.h"
#include "sysemu/runstate.h"
#include "sysemu/sysemu.h"
+#include "qemu/log.h"
#include "qemu/error-report.h"
#include "hw/char/pl011.h"
#include "hw/hw.h"
@@ -144,8 +145,9 @@
/* ??? Voltage control unimplemented. */
return 0;
default:
- hw_error("integratorcm_read: Unimplemented offset 0x%x\n",
- (int)offset);
+ qemu_log_mask(LOG_UNIMP,
+ "%s: Unimplemented offset 0x%" HWADDR_PRIX "\n",
+ __func__, offset);
return 0;
}
}
@@ -252,8 +254,9 @@
/* ??? Voltage control unimplemented. */
break;
default:
- hw_error("integratorcm_write: Unimplemented offset 0x%x\n",
- (int)offset);
+ qemu_log_mask(LOG_UNIMP,
+ "%s: Unimplemented offset 0x%" HWADDR_PRIX "\n",
+ __func__, offset);
break;
}
}
@@ -394,7 +397,8 @@
case 5: /* INT_SOFTCLR */
case 11: /* FRQ_ENABLECLR */
default:
- printf ("icp_pic_read: Bad register offset 0x%x\n", (int)offset);
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: Bad offset 0x%" HWADDR_PRIX "\n",
+ __func__, offset);
return 0;
}
}
@@ -430,7 +434,8 @@
case 8: /* FRQ_STATUS */
case 9: /* FRQ_RAWSTAT */
default:
- printf ("icp_pic_write: Bad register offset 0x%x\n", (int)offset);
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: Bad offset 0x%" HWADDR_PRIX "\n",
+ __func__, offset);
return;
}
icp_pic_update(s);
@@ -504,7 +509,8 @@
case 3: /* CP_DECODE */
return 0x11;
default:
- hw_error("icp_control_read: Bad offset %x\n", (int)offset);
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: Bad offset 0x%" HWADDR_PRIX "\n",
+ __func__, offset);
return 0;
}
}
@@ -524,7 +530,8 @@
/* Nothing interesting implemented yet. */
break;
default:
- hw_error("icp_control_write: Bad offset %x\n", (int)offset);
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: Bad offset 0x%" HWADDR_PRIX "\n",
+ __func__, offset);
}
}
diff --git a/hw/arm/mcimx6ul-evk.c b/hw/arm/mcimx6ul-evk.c
index 23a71ed..5b5f23a 100644
--- a/hw/arm/mcimx6ul-evk.c
+++ b/hw/arm/mcimx6ul-evk.c
@@ -39,7 +39,7 @@
};
s = FSL_IMX6UL(object_new(TYPE_FSL_IMX6UL));
- object_property_add_child(OBJECT(machine), "soc", OBJECT(s), &error_fatal);
+ object_property_add_child(OBJECT(machine), "soc", OBJECT(s));
object_property_set_bool(OBJECT(s), true, "realized", &error_fatal);
memory_region_add_subregion(get_system_memory(), FSL_IMX6UL_MMDC_ADDR,
diff --git a/hw/arm/mcimx7d-sabre.c b/hw/arm/mcimx7d-sabre.c
index de1e264..3851cd9 100644
--- a/hw/arm/mcimx7d-sabre.c
+++ b/hw/arm/mcimx7d-sabre.c
@@ -41,7 +41,7 @@
};
s = FSL_IMX7(object_new(TYPE_FSL_IMX7));
- object_property_add_child(OBJECT(machine), "soc", OBJECT(s), &error_fatal);
+ object_property_add_child(OBJECT(machine), "soc", OBJECT(s));
object_property_set_bool(OBJECT(s), true, "realized", &error_fatal);
memory_region_add_subregion(get_system_memory(), FSL_IMX7_MMDC_ADDR,
diff --git a/hw/arm/msf2-soc.c b/hw/arm/msf2-soc.c
index a455b88..f4579e5 100644
--- a/hw/arm/msf2-soc.c
+++ b/hw/arm/msf2-soc.c
@@ -197,8 +197,7 @@
/* Alias controller SPI bus to the SoC itself */
bus_name = g_strdup_printf("spi%d", i);
object_property_add_alias(OBJECT(s), bus_name,
- OBJECT(&s->spi[i]), "spi",
- &error_abort);
+ OBJECT(&s->spi[i]), "spi");
g_free(bus_name);
}
diff --git a/hw/arm/nrf51_soc.c b/hw/arm/nrf51_soc.c
index 71309e5..fe12658 100644
--- a/hw/arm/nrf51_soc.c
+++ b/hw/arm/nrf51_soc.c
@@ -197,8 +197,7 @@
sysbus_init_child_obj(obj, "uart", &s->uart, sizeof(s->uart),
TYPE_NRF51_UART);
- object_property_add_alias(obj, "serial0", OBJECT(&s->uart), "chardev",
- &error_abort);
+ object_property_add_alias(obj, "serial0", OBJECT(&s->uart), "chardev");
sysbus_init_child_obj(obj, "rng", &s->rng, sizeof(s->rng),
TYPE_NRF51_RNG);
diff --git a/hw/arm/orangepi.c b/hw/arm/orangepi.c
index a9f64c5..b291715 100644
--- a/hw/arm/orangepi.c
+++ b/hw/arm/orangepi.c
@@ -59,8 +59,7 @@
}
h3 = AW_H3(object_new(TYPE_AW_H3));
- object_property_add_child(OBJECT(machine), "soc", OBJECT(h3),
- &error_abort);
+ object_property_add_child(OBJECT(machine), "soc", OBJECT(h3));
object_unref(OBJECT(h3));
/* Setup timer properties */
diff --git a/hw/arm/pxa2xx_gpio.c b/hw/arm/pxa2xx_gpio.c
index f8df3cc..a01db54 100644
--- a/hw/arm/pxa2xx_gpio.c
+++ b/hw/arm/pxa2xx_gpio.c
@@ -9,7 +9,6 @@
#include "qemu/osdep.h"
#include "cpu.h"
-#include "hw/hw.h"
#include "hw/irq.h"
#include "hw/qdev-properties.h"
#include "hw/sysbus.h"
@@ -199,7 +198,8 @@
return s->status[bank];
default:
- hw_error("%s: Bad offset " REG_FMT "\n", __func__, offset);
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: Bad offset 0x%" HWADDR_PRIX "\n",
+ __func__, offset);
}
return 0;
@@ -252,7 +252,8 @@
break;
default:
- hw_error("%s: Bad offset " REG_FMT "\n", __func__, offset);
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: Bad offset 0x%" HWADDR_PRIX "\n",
+ __func__, offset);
}
}
diff --git a/hw/arm/raspi.c b/hw/arm/raspi.c
index fe3b9bc..a2efe0b 100644
--- a/hw/arm/raspi.c
+++ b/hw/arm/raspi.c
@@ -284,8 +284,7 @@
/* Setup the SOC */
object_initialize_child(OBJECT(machine), "soc", &s->soc, sizeof(s->soc),
board_soc_type(board_rev), &error_abort, NULL);
- object_property_add_const_link(OBJECT(&s->soc), "ram", OBJECT(machine->ram),
- &error_abort);
+ object_property_add_const_link(OBJECT(&s->soc), "ram", OBJECT(machine->ram));
object_property_set_int(OBJECT(&s->soc), board_rev, "board-rev",
&error_abort);
object_property_set_bool(OBJECT(&s->soc), true, "realized", &error_abort);
diff --git a/hw/arm/sabrelite.c b/hw/arm/sabrelite.c
index e31694b..96cb30a 100644
--- a/hw/arm/sabrelite.c
+++ b/hw/arm/sabrelite.c
@@ -41,7 +41,6 @@
static void sabrelite_init(MachineState *machine)
{
FslIMX6State *s;
- Error *err = NULL;
/* Check the amount of memory is compatible with the SOC */
if (machine->ram_size > FSL_IMX6_MMDC_SIZE) {
@@ -51,12 +50,8 @@
}
s = FSL_IMX6(object_new(TYPE_FSL_IMX6));
- object_property_add_child(OBJECT(machine), "soc", OBJECT(s), &error_fatal);
- object_property_set_bool(OBJECT(s), true, "realized", &err);
- if (err != NULL) {
- error_report("%s", error_get_pretty(err));
- exit(1);
- }
+ object_property_add_child(OBJECT(machine), "soc", OBJECT(s));
+ object_property_set_bool(OBJECT(s), true, "realized", &error_fatal);
memory_region_add_subregion(get_system_memory(), FSL_IMX6_MMDC_ADDR,
machine->ram);
diff --git a/hw/arm/sbsa-ref.c b/hw/arm/sbsa-ref.c
index 8409ba8..6a0221a 100644
--- a/hw/arm/sbsa-ref.c
+++ b/hw/arm/sbsa-ref.c
@@ -222,10 +222,9 @@
qdev_prop_set_uint16(dev, "id2", 0x00);
qdev_prop_set_uint16(dev, "id3", 0x00);
qdev_prop_set_string(dev, "name", name);
- object_property_add_child(OBJECT(sms), name, OBJECT(dev),
- &error_abort);
+ object_property_add_child(OBJECT(sms), name, OBJECT(dev));
object_property_add_alias(OBJECT(sms), alias_prop_name,
- OBJECT(dev), "drive", &error_abort);
+ OBJECT(dev), "drive");
return PFLASH_CFI01(dev);
}
@@ -241,7 +240,7 @@
{
DeviceState *dev = DEVICE(flash);
- assert(size % SBSA_FLASH_SECTOR_SIZE == 0);
+ assert(QEMU_IS_ALIGNED(size, SBSA_FLASH_SECTOR_SIZE));
assert(size / SBSA_FLASH_SECTOR_SIZE <= UINT32_MAX);
qdev_prop_set_uint32(dev, "num-blocks", size / SBSA_FLASH_SECTOR_SIZE);
qdev_init_nofail(dev);
diff --git a/hw/arm/vexpress.c b/hw/arm/vexpress.c
index ed683ee..69ee498 100644
--- a/hw/arm/vexpress.c
+++ b/hw/arm/vexpress.c
@@ -749,11 +749,10 @@
/* EL3 is enabled by default on vexpress */
vms->secure = true;
object_property_add_bool(obj, "secure", vexpress_get_secure,
- vexpress_set_secure, NULL);
+ vexpress_set_secure);
object_property_set_description(obj, "secure",
"Set on/off to enable/disable the ARM "
- "Security Extensions (TrustZone)",
- NULL);
+ "Security Extensions (TrustZone)");
}
static void vexpress_a15_instance_init(Object *obj)
@@ -766,12 +765,11 @@
*/
vms->virt = true;
object_property_add_bool(obj, "virtualization", vexpress_get_virt,
- vexpress_set_virt, NULL);
+ vexpress_set_virt);
object_property_set_description(obj, "virtualization",
"Set on/off to enable/disable the ARM "
"Virtualization Extensions "
- "(defaults to same as 'secure')",
- NULL);
+ "(defaults to same as 'secure')");
}
static void vexpress_a9_instance_init(Object *obj)
diff --git a/hw/arm/virt-acpi-build.c b/hw/arm/virt-acpi-build.c
index f22b1e6..1b0a584 100644
--- a/hw/arm/virt-acpi-build.c
+++ b/hw/arm/virt-acpi-build.c
@@ -49,6 +49,7 @@
#include "sysemu/reset.h"
#include "kvm_arm.h"
#include "migration/vmstate.h"
+#include "hw/acpi/ghes.h"
#define ARM_SPI_BASE 32
@@ -818,6 +819,12 @@
acpi_add_table(table_offsets, tables_blob);
build_spcr(tables_blob, tables->linker, vms);
+ if (vms->ras) {
+ build_ghes_error_table(tables->hardware_errors, tables->linker);
+ acpi_add_table(table_offsets, tables_blob);
+ acpi_build_hest(tables_blob, tables->linker);
+ }
+
if (ms->numa_state->num_nodes > 0) {
acpi_add_table(table_offsets, tables_blob);
build_srat(tables_blob, tables->linker, vms);
@@ -910,6 +917,7 @@
{
AcpiBuildTables tables;
AcpiBuildState *build_state;
+ AcpiGedState *acpi_ged_state;
if (!vms->fw_cfg) {
trace_virt_acpi_setup();
@@ -940,6 +948,13 @@
fw_cfg_add_file(vms->fw_cfg, ACPI_BUILD_TPMLOG_FILE, tables.tcpalog->data,
acpi_data_len(tables.tcpalog));
+ if (vms->ras) {
+ assert(vms->acpi_dev);
+ acpi_ged_state = ACPI_GED(vms->acpi_dev);
+ acpi_ghes_add_fw_cfg(&acpi_ged_state->ghes_state,
+ vms->fw_cfg, tables.hardware_errors);
+ }
+
build_state->rsdp_mr = acpi_add_rom_blob(virt_acpi_build_update,
build_state, tables.rsdp,
ACPI_BUILD_RSDP_FILE, 0);
diff --git a/hw/arm/virt.c b/hw/arm/virt.c
index 634db0c..37462a6 100644
--- a/hw/arm/virt.c
+++ b/hw/arm/virt.c
@@ -959,10 +959,9 @@
qdev_prop_set_uint16(dev, "id2", 0x00);
qdev_prop_set_uint16(dev, "id3", 0x00);
qdev_prop_set_string(dev, "name", name);
- object_property_add_child(OBJECT(vms), name, OBJECT(dev),
- &error_abort);
+ object_property_add_child(OBJECT(vms), name, OBJECT(dev));
object_property_add_alias(OBJECT(vms), alias_prop_name,
- OBJECT(dev), "drive", &error_abort);
+ OBJECT(dev), "drive");
return PFLASH_CFI01(dev);
}
@@ -978,7 +977,7 @@
{
DeviceState *dev = DEVICE(flash);
- assert(size % VIRT_FLASH_SECTOR_SIZE == 0);
+ assert(QEMU_IS_ALIGNED(size, VIRT_FLASH_SECTOR_SIZE));
assert(size / VIRT_FLASH_SECTOR_SIZE <= UINT32_MAX);
qdev_prop_set_uint32(dev, "num-blocks", size / VIRT_FLASH_SECTOR_SIZE);
qdev_init_nofail(dev);
@@ -1995,6 +1994,20 @@
visit_type_OnOffAuto(v, name, &vms->acpi, errp);
}
+static bool virt_get_ras(Object *obj, Error **errp)
+{
+ VirtMachineState *vms = VIRT_MACHINE(obj);
+
+ return vms->ras;
+}
+
+static void virt_set_ras(Object *obj, bool value, Error **errp)
+{
+ VirtMachineState *vms = VIRT_MACHINE(obj);
+
+ vms->ras = value;
+}
+
static char *virt_get_gic_version(Object *obj, Error **errp)
{
VirtMachineState *vms = VIRT_MACHINE(obj);
@@ -2256,9 +2269,9 @@
object_class_property_add(oc, "acpi", "OnOffAuto",
virt_get_acpi, virt_set_acpi,
- NULL, NULL, &error_abort);
+ NULL, NULL);
object_class_property_set_description(oc, "acpi",
- "Enable ACPI", &error_abort);
+ "Enable ACPI");
}
static void virt_instance_init(Object *obj)
@@ -2272,37 +2285,33 @@
*/
vms->secure = false;
object_property_add_bool(obj, "secure", virt_get_secure,
- virt_set_secure, NULL);
+ virt_set_secure);
object_property_set_description(obj, "secure",
"Set on/off to enable/disable the ARM "
- "Security Extensions (TrustZone)",
- NULL);
+ "Security Extensions (TrustZone)");
/* EL2 is also disabled by default, for similar reasons */
vms->virt = false;
object_property_add_bool(obj, "virtualization", virt_get_virt,
- virt_set_virt, NULL);
+ virt_set_virt);
object_property_set_description(obj, "virtualization",
"Set on/off to enable/disable emulating a "
"guest CPU which implements the ARM "
- "Virtualization Extensions",
- NULL);
+ "Virtualization Extensions");
/* High memory is enabled by default */
vms->highmem = true;
object_property_add_bool(obj, "highmem", virt_get_highmem,
- virt_set_highmem, NULL);
+ virt_set_highmem);
object_property_set_description(obj, "highmem",
"Set on/off to enable/disable using "
- "physical address space above 32 bits",
- NULL);
+ "physical address space above 32 bits");
vms->gic_version = VIRT_GIC_VERSION_NOSEL;
object_property_add_str(obj, "gic-version", virt_get_gic_version,
- virt_set_gic_version, NULL);
+ virt_set_gic_version);
object_property_set_description(obj, "gic-version",
"Set GIC version. "
- "Valid values are 2, 3, host and max",
- NULL);
+ "Valid values are 2, 3, host and max");
vms->highmem_ecam = !vmc->no_highmem_ecam;
@@ -2312,20 +2321,26 @@
/* Default allows ITS instantiation */
vms->its = true;
object_property_add_bool(obj, "its", virt_get_its,
- virt_set_its, NULL);
+ virt_set_its);
object_property_set_description(obj, "its",
"Set on/off to enable/disable "
- "ITS instantiation",
- NULL);
+ "ITS instantiation");
}
/* Default disallows iommu instantiation */
vms->iommu = VIRT_IOMMU_NONE;
- object_property_add_str(obj, "iommu", virt_get_iommu, virt_set_iommu, NULL);
+ object_property_add_str(obj, "iommu", virt_get_iommu, virt_set_iommu);
object_property_set_description(obj, "iommu",
"Set the IOMMU type. "
- "Valid values are none and smmuv3",
- NULL);
+ "Valid values are none and smmuv3");
+
+ /* Default disallows RAS instantiation */
+ vms->ras = false;
+ object_property_add_bool(obj, "ras", virt_get_ras,
+ virt_set_ras);
+ object_property_set_description(obj, "ras",
+ "Set on/off to enable/disable reporting host memory errors "
+ "to a KVM guest using ACPI and guest external abort exceptions");
vms->irqmap = a15irqmap;
diff --git a/hw/arm/xilinx_zynq.c b/hw/arm/xilinx_zynq.c
index 91b498d..cb933ef 100644
--- a/hw/arm/xilinx_zynq.c
+++ b/hw/arm/xilinx_zynq.c
@@ -229,7 +229,7 @@
/* Create the main clock source, and feed slcr with it */
zynq_machine->ps_clk = CLOCK(object_new(TYPE_CLOCK));
object_property_add_child(OBJECT(zynq_machine), "ps_clk",
- OBJECT(zynq_machine->ps_clk), &error_abort);
+ OBJECT(zynq_machine->ps_clk));
object_unref(OBJECT(zynq_machine->ps_clk));
clock_set_hz(zynq_machine->ps_clk, PS_CLK_FREQUENCY);
qdev_connect_clock_in(slcr, "ps_clk", zynq_machine->ps_clk);
diff --git a/hw/arm/xlnx-versal-virt.c b/hw/arm/xlnx-versal-virt.c
index 7e749e1..43a71e2 100644
--- a/hw/arm/xlnx-versal-virt.c
+++ b/hw/arm/xlnx-versal-virt.c
@@ -433,8 +433,7 @@
pic_irq = qdev_get_gpio_in(DEVICE(&s->soc.fpd.apu.gic), irq);
dev = qdev_create(NULL, "virtio-mmio");
- object_property_add_child(OBJECT(&s->soc), name, OBJECT(dev),
- &error_fatal);
+ object_property_add_child(OBJECT(&s->soc), name, OBJECT(dev));
qdev_init_nofail(dev);
sysbus_connect_irq(SYS_BUS_DEVICE(dev), 0, pic_irq);
mr = sysbus_mmio_get_region(SYS_BUS_DEVICE(dev), 0);
@@ -465,8 +464,7 @@
DeviceState *card;
card = qdev_create(qdev_get_child_bus(DEVICE(sd), "sd-bus"), TYPE_SD_CARD);
- object_property_add_child(OBJECT(sd), "card[*]", OBJECT(card),
- &error_fatal);
+ object_property_add_child(OBJECT(sd), "card[*]", OBJECT(card));
qdev_prop_set_drive(card, "drive", blk, &error_fatal);
object_property_set_bool(OBJECT(card), true, "realized", &error_fatal);
}
diff --git a/hw/arm/xlnx-versal.c b/hw/arm/xlnx-versal.c
index 321171b..809a313 100644
--- a/hw/arm/xlnx-versal.c
+++ b/hw/arm/xlnx-versal.c
@@ -309,7 +309,7 @@
qdev_prop_set_string(dev, "name", name);
qdev_prop_set_uint64(dev, "size", size);
- object_property_add_child(OBJECT(s), name, OBJECT(dev), &error_fatal);
+ object_property_add_child(OBJECT(s), name, OBJECT(dev));
qdev_init_nofail(dev);
mr_dev = sysbus_mmio_get_region(SYS_BUS_DEVICE(dev), 0);
diff --git a/hw/arm/xlnx-zcu102.c b/hw/arm/xlnx-zcu102.c
index a798e22..b01e575 100644
--- a/hw/arm/xlnx-zcu102.c
+++ b/hw/arm/xlnx-zcu102.c
@@ -209,21 +209,19 @@
/* Default to secure mode being disabled */
s->secure = false;
object_property_add_bool(obj, "secure", zcu102_get_secure,
- zcu102_set_secure, NULL);
+ zcu102_set_secure);
object_property_set_description(obj, "secure",
"Set on/off to enable/disable the ARM "
- "Security Extensions (TrustZone)",
- NULL);
+ "Security Extensions (TrustZone)");
/* Default to virt (EL2) being disabled */
s->virt = false;
object_property_add_bool(obj, "virtualization", zcu102_get_virt,
- zcu102_set_virt, NULL);
+ zcu102_set_virt);
object_property_set_description(obj, "virtualization",
"Set on/off to enable/disable emulating a "
"guest CPU which implements the ARM "
- "Virtualization Extensions",
- NULL);
+ "Virtualization Extensions");
}
static void xlnx_zcu102_machine_class_init(ObjectClass *oc, void *data)
diff --git a/hw/arm/xlnx-zynqmp.c b/hw/arm/xlnx-zynqmp.c
index b84d153..f08abf6 100644
--- a/hw/arm/xlnx-zynqmp.c
+++ b/hw/arm/xlnx-zynqmp.c
@@ -554,8 +554,7 @@
/* Alias controller SD bus to the SoC itself */
bus_name = g_strdup_printf("sd-bus%d", i);
- object_property_add_alias(OBJECT(s), bus_name, sdhci, "sd-bus",
- &error_abort);
+ object_property_add_alias(OBJECT(s), bus_name, sdhci, "sd-bus");
g_free(bus_name);
}
@@ -575,8 +574,7 @@
/* Alias controller SPI bus to the SoC itself */
bus_name = g_strdup_printf("spi%d", i);
object_property_add_alias(OBJECT(s), bus_name,
- OBJECT(&s->spi[i]), "spi0",
- &error_abort);
+ OBJECT(&s->spi[i]), "spi0");
g_free(bus_name);
}
@@ -597,8 +595,7 @@
bus_name = g_strdup_printf("qspi%d", i);
target_bus = g_strdup_printf("spi%d", i);
object_property_add_alias(OBJECT(s), bus_name,
- OBJECT(&s->qspi), target_bus,
- &error_abort);
+ OBJECT(&s->qspi), target_bus);
g_free(bus_name);
g_free(target_bus);
}
diff --git a/hw/audio/es1370.c b/hw/audio/es1370.c
index 89c4dab..5f8a83f 100644
--- a/hw/audio/es1370.c
+++ b/hw/audio/es1370.c
@@ -643,6 +643,9 @@
int csc_bytes = (csc + 1) << d->shift;
int cnt = d->frame_cnt >> 16;
int size = d->frame_cnt & 0xffff;
+ if (size < cnt) {
+ return;
+ }
int left = ((size - cnt + 1) << 2) + d->leftover;
int transferred = 0;
int temp = MIN (max, MIN (left, csc_bytes));
@@ -651,7 +654,7 @@
addr += (cnt << 2) + d->leftover;
if (index == ADC_CHANNEL) {
- while (temp) {
+ while (temp > 0) {
int acquired, to_copy;
to_copy = MIN ((size_t) temp, sizeof (tmpbuf));
@@ -669,7 +672,7 @@
else {
SWVoiceOut *voice = s->dac_voice[index];
- while (temp) {
+ while (temp > 0) {
int copied, to_copy;
to_copy = MIN ((size_t) temp, sizeof (tmpbuf));
diff --git a/hw/audio/gus.c b/hw/audio/gus.c
index eb4a803..c8df2bd 100644
--- a/hw/audio/gus.c
+++ b/hw/audio/gus.c
@@ -41,12 +41,6 @@
#define ldebug(...)
#endif
-#ifdef HOST_WORDS_BIGENDIAN
-#define GUS_ENDIANNESS 1
-#else
-#define GUS_ENDIANNESS 0
-#endif
-
#define TYPE_GUS "gus"
#define GUS(obj) OBJECT_CHECK (GUSState, (obj), TYPE_GUS)
@@ -256,7 +250,7 @@
as.freq = s->freq;
as.nchannels = 2;
as.fmt = AUDIO_FORMAT_S16;
- as.endianness = GUS_ENDIANNESS;
+ as.endianness = AUDIO_HOST_ENDIANNESS;
s->voice = AUD_open_out (
&s->card,
diff --git a/hw/audio/intel-hda.c b/hw/audio/intel-hda.c
index e8d18b7..4696ae0 100644
--- a/hw/audio/intel-hda.c
+++ b/hw/audio/intel-hda.c
@@ -74,7 +74,7 @@
}
}
-static void hda_codec_dev_unrealize(DeviceState *qdev, Error **errp)
+static void hda_codec_dev_unrealize(DeviceState *qdev)
{
HDACodecDevice *dev = HDA_CODEC_DEVICE(qdev);
HDACodecDeviceClass *cdc = HDA_CODEC_DEVICE_GET_CLASS(dev);
diff --git a/hw/audio/marvell_88w8618.c b/hw/audio/marvell_88w8618.c
index 883ef74..8dfacec 100644
--- a/hw/audio/marvell_88w8618.c
+++ b/hw/audio/marvell_88w8618.c
@@ -259,7 +259,7 @@
object_property_add_link(OBJECT(dev), "wm8750", TYPE_WM8750,
(Object **) &s->wm,
qdev_prop_allow_set_link_before_realize,
- 0, &error_abort);
+ 0);
}
static void mv88w8618_audio_realize(DeviceState *dev, Error **errp)
diff --git a/hw/audio/pcspk.c b/hw/audio/pcspk.c
index 29dc00b..c37a387 100644
--- a/hw/audio/pcspk.c
+++ b/hw/audio/pcspk.c
@@ -175,7 +175,7 @@
object_property_add_link(obj, "pit", TYPE_PIT_COMMON,
(Object **)&s->pit,
qdev_prop_allow_set_link_before_realize,
- 0, &error_abort);
+ 0);
}
static void pcspk_realizefn(DeviceState *dev, Error **errp)
diff --git a/hw/block/fdc.c b/hw/block/fdc.c
index 9628cc1..c5fb9d6 100644
--- a/hw/block/fdc.c
+++ b/hw/block/fdc.c
@@ -2813,10 +2813,10 @@
device_add_bootindex_property(obj, &isa->bootindexA,
"bootindexA", "/floppy@0",
- DEVICE(obj), NULL);
+ DEVICE(obj));
device_add_bootindex_property(obj, &isa->bootindexB,
"bootindexB", "/floppy@1",
- DEVICE(obj), NULL);
+ DEVICE(obj));
}
static const TypeInfo isa_fdc_info = {
diff --git a/hw/block/nvme.c b/hw/block/nvme.c
index 9b45342..2f3100e 100644
--- a/hw/block/nvme.c
+++ b/hw/block/nvme.c
@@ -1594,7 +1594,7 @@
device_add_bootindex_property(obj, &s->conf.bootindex,
"bootindex", "/namespace@1,0",
- DEVICE(obj), &error_abort);
+ DEVICE(obj));
}
static const TypeInfo nvme_info = {
diff --git a/hw/block/pflash_cfi01.c b/hw/block/pflash_cfi01.c
index 24f3bce..11922c0 100644
--- a/hw/block/pflash_cfi01.c
+++ b/hw/block/pflash_cfi01.c
@@ -42,7 +42,7 @@
#include "hw/qdev-properties.h"
#include "sysemu/block-backend.h"
#include "qapi/error.h"
-#include "qemu/timer.h"
+#include "qemu/error-report.h"
#include "qemu/bitops.h"
#include "qemu/error-report.h"
#include "qemu/host-utils.h"
@@ -91,7 +91,6 @@
uint8_t cfi_table[0x52];
uint64_t counter;
unsigned int writeblock_size;
- QEMUTimer *timer;
MemoryRegion mem;
char *name;
void *storage;
@@ -115,18 +114,6 @@
}
};
-static void pflash_timer (void *opaque)
-{
- PFlashCFI01 *pfl = opaque;
-
- trace_pflash_timer_expired(pfl->cmd);
- /* Reset flash */
- pfl->status ^= 0x80;
- memory_region_rom_device_set_romd(&pfl->mem, true);
- pfl->wcycle = 0;
- pfl->cmd = 0;
-}
-
/* Perform a CFI query based on the bank width of the flash.
* If this code is called we know we have a device_width set for
* this flash.
@@ -292,9 +279,13 @@
/* This should never happen : reset state & treat it as a read */
DPRINTF("%s: unknown command state: %x\n", __func__, pfl->cmd);
pfl->wcycle = 0;
- pfl->cmd = 0;
+ /*
+ * The command 0x00 is not assigned by the CFI open standard,
+ * but QEMU historically uses it for the READ_ARRAY command (0xff).
+ */
+ pfl->cmd = 0x00;
/* fall through to read code */
- case 0x00:
+ case 0x00: /* This model reset value for READ_ARRAY (not CFI compliant) */
/* Flash area read */
ret = pflash_data_read(pfl, offset, width, be);
break;
@@ -399,13 +390,18 @@
int size)
{
int offset_end;
+ int ret;
if (pfl->blk) {
offset_end = offset + size;
/* widen to sector boundaries */
offset = QEMU_ALIGN_DOWN(offset, BDRV_SECTOR_SIZE);
offset_end = QEMU_ALIGN_UP(offset_end, BDRV_SECTOR_SIZE);
- blk_pwrite(pfl->blk, offset, pfl->storage + offset,
+ ret = blk_pwrite(pfl->blk, offset, pfl->storage + offset,
offset_end - offset, 0);
+ if (ret < 0) {
+ /* TODO set error bit in status */
+ error_report("Could not update PFLASH: %s", strerror(-ret));
+ }
}
}
@@ -463,8 +459,8 @@
case 0:
/* read mode */
switch (cmd) {
- case 0x00: /* ??? */
- goto reset_flash;
+ case 0x00: /* This model reset value for READ_ARRAY (not CFI) */
+ goto mode_read_array;
case 0x10: /* Single Byte Program */
case 0x40: /* Single Byte Program */
DPRINTF("%s: Single Byte Program\n", __func__);
@@ -487,7 +483,7 @@
case 0x50: /* Clear status bits */
DPRINTF("%s: Clear status bits\n", __func__);
pfl->status = 0x0;
- goto reset_flash;
+ goto mode_read_array;
case 0x60: /* Block (un)lock */
DPRINTF("%s: Block unlock\n", __func__);
break;
@@ -512,10 +508,10 @@
break;
case 0xf0: /* Probe for AMD flash */
DPRINTF("%s: Probe for AMD flash\n", __func__);
- goto reset_flash;
- case 0xff: /* Read array mode */
+ goto mode_read_array;
+ case 0xff: /* Read Array */
DPRINTF("%s: Read array mode\n", __func__);
- goto reset_flash;
+ goto mode_read_array;
default:
goto error_flash;
}
@@ -541,8 +537,8 @@
if (cmd == 0xd0) { /* confirm */
pfl->wcycle = 0;
pfl->status |= 0x80;
- } else if (cmd == 0xff) { /* read array mode */
- goto reset_flash;
+ } else if (cmd == 0xff) { /* Read Array */
+ goto mode_read_array;
} else
goto error_flash;
@@ -568,16 +564,16 @@
} else if (cmd == 0x01) {
pfl->wcycle = 0;
pfl->status |= 0x80;
- } else if (cmd == 0xff) {
- goto reset_flash;
+ } else if (cmd == 0xff) { /* Read Array */
+ goto mode_read_array;
} else {
DPRINTF("%s: Unknown (un)locking command\n", __func__);
- goto reset_flash;
+ goto mode_read_array;
}
break;
case 0x98:
- if (cmd == 0xff) {
- goto reset_flash;
+ if (cmd == 0xff) { /* Read Array */
+ goto mode_read_array;
} else {
DPRINTF("%s: leaving query mode\n", __func__);
}
@@ -637,7 +633,7 @@
" the data is already written to storage!\n"
"Flash device reset into READ mode.\n",
__func__);
- goto reset_flash;
+ goto mode_read_array;
}
break;
default:
@@ -647,7 +643,7 @@
default:
/* Should never happen */
DPRINTF("%s: invalid write state\n", __func__);
- goto reset_flash;
+ goto mode_read_array;
}
return;
@@ -656,11 +652,11 @@
"(offset " TARGET_FMT_plx ", wcycle 0x%x cmd 0x%x value 0x%x)"
"\n", __func__, offset, pfl->wcycle, pfl->cmd, value);
- reset_flash:
+ mode_read_array:
trace_pflash_reset();
memory_region_rom_device_set_romd(&pfl->mem, true);
pfl->wcycle = 0;
- pfl->cmd = 0;
+ pfl->cmd = 0x00; /* This model reset value for READ_ARRAY (not CFI) */
}
@@ -775,9 +771,12 @@
pfl->max_device_width = pfl->device_width;
}
- pfl->timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, pflash_timer, pfl);
pfl->wcycle = 0;
- pfl->cmd = 0;
+ /*
+ * The command 0x00 is not assigned by the CFI open standard,
+ * but QEMU historically uses it for the READ_ARRAY command (0xff).
+ */
+ pfl->cmd = 0x00;
pfl->status = 0x80; /* WSM ready */
/* Hardcoded CFI table */
/* Standard "QRY" string */
@@ -965,7 +964,7 @@
if (blk) {
qdev_prop_set_drive(dev, "drive", blk, &error_abort);
}
- assert(size % sector_len == 0);
+ assert(QEMU_IS_ALIGNED(size, sector_len));
qdev_prop_set_uint32(dev, "num-blocks", size / sector_len);
qdev_prop_set_uint64(dev, "sector-length", sector_len);
qdev_prop_set_uint8(dev, "width", bank_width);
diff --git a/hw/block/pflash_cfi02.c b/hw/block/pflash_cfi02.c
index 12f18d4..ac7e34e 100644
--- a/hw/block/pflash_cfi02.c
+++ b/hw/block/pflash_cfi02.c
@@ -37,6 +37,7 @@
#include "hw/block/flash.h"
#include "hw/qdev-properties.h"
#include "qapi/error.h"
+#include "qemu/error-report.h"
#include "qemu/bitmap.h"
#include "qemu/timer.h"
#include "sysemu/block-backend.h"
@@ -393,13 +394,18 @@
static void pflash_update(PFlashCFI02 *pfl, int offset, int size)
{
int offset_end;
+ int ret;
if (pfl->blk) {
offset_end = offset + size;
/* widen to sector boundaries */
offset = QEMU_ALIGN_DOWN(offset, BDRV_SECTOR_SIZE);
offset_end = QEMU_ALIGN_UP(offset_end, BDRV_SECTOR_SIZE);
- blk_pwrite(pfl->blk, offset, pfl->storage + offset,
+ ret = blk_pwrite(pfl->blk, offset, pfl->storage + offset,
offset_end - offset, 0);
+ if (ret < 0) {
+ /* TODO set error bit in status */
+ error_report("Could not update PFLASH: %s", strerror(-ret));
+ }
}
}
@@ -949,7 +955,7 @@
DEFINE_PROP_END_OF_LIST(),
};
-static void pflash_cfi02_unrealize(DeviceState *dev, Error **errp)
+static void pflash_cfi02_unrealize(DeviceState *dev)
{
PFlashCFI02 *pfl = PFLASH_CFI02(dev);
timer_del(&pfl->timer);
@@ -997,7 +1003,7 @@
if (blk) {
qdev_prop_set_drive(dev, "drive", blk, &error_abort);
}
- assert(size % sector_len == 0);
+ assert(QEMU_IS_ALIGNED(size, sector_len));
qdev_prop_set_uint32(dev, "num-blocks", size / sector_len);
qdev_prop_set_uint32(dev, "sector-length", sector_len);
qdev_prop_set_uint8(dev, "width", width);
diff --git a/hw/block/vhost-user-blk.c b/hw/block/vhost-user-blk.c
index 6c485d1..9d8c0b3 100644
--- a/hw/block/vhost-user-blk.c
+++ b/hw/block/vhost-user-blk.c
@@ -452,7 +452,7 @@
vhost_user_cleanup(&s->vhost_user);
}
-static void vhost_user_blk_device_unrealize(DeviceState *dev, Error **errp)
+static void vhost_user_blk_device_unrealize(DeviceState *dev)
{
VirtIODevice *vdev = VIRTIO_DEVICE(dev);
VHostUserBlk *s = VHOST_USER_BLK(dev);
@@ -481,7 +481,7 @@
VHostUserBlk *s = VHOST_USER_BLK(obj);
device_add_bootindex_property(obj, &s->bootindex, "bootindex",
- "/disk@0,0", DEVICE(obj), NULL);
+ "/disk@0,0", DEVICE(obj));
}
static const VMStateDescription vmstate_vhost_user_blk = {
diff --git a/hw/block/virtio-blk.c b/hw/block/virtio-blk.c
index 97ba8a2..f5f6fc9 100644
--- a/hw/block/virtio-blk.c
+++ b/hw/block/virtio-blk.c
@@ -1223,7 +1223,7 @@
conf->conf.lsecs);
}
-static void virtio_blk_device_unrealize(DeviceState *dev, Error **errp)
+static void virtio_blk_device_unrealize(DeviceState *dev)
{
VirtIODevice *vdev = VIRTIO_DEVICE(dev);
VirtIOBlock *s = VIRTIO_BLK(dev);
@@ -1248,7 +1248,7 @@
device_add_bootindex_property(obj, &s->conf.conf.bootindex,
"bootindex", "/disk@0,0",
- DEVICE(obj), NULL);
+ DEVICE(obj));
}
static const VMStateDescription vmstate_virtio_blk = {
diff --git a/hw/block/xen-block.c b/hw/block/xen-block.c
index 99cb4c6..570489d 100644
--- a/hw/block/xen-block.c
+++ b/hw/block/xen-block.c
@@ -136,7 +136,7 @@
g_free(ring_ref);
}
-static void xen_block_unrealize(XenDevice *xendev, Error **errp)
+static void xen_block_unrealize(XenDevice *xendev)
{
XenBlockDevice *blockdev = XEN_BLOCK_DEVICE(xendev);
XenBlockDeviceClass *blockdev_class =
@@ -157,7 +157,7 @@
blockdev->dataplane = NULL;
if (blockdev_class->unrealize) {
- blockdev_class->unrealize(blockdev, errp);
+ blockdev_class->unrealize(blockdev);
}
}
@@ -567,7 +567,7 @@
.class_init = xen_block_class_init,
};
-static void xen_disk_unrealize(XenBlockDevice *blockdev, Error **errp)
+static void xen_disk_unrealize(XenBlockDevice *blockdev)
{
trace_xen_disk_unrealize();
}
@@ -606,7 +606,7 @@
.class_init = xen_disk_class_init,
};
-static void xen_cdrom_unrealize(XenBlockDevice *blockdev, Error **errp)
+static void xen_cdrom_unrealize(XenBlockDevice *blockdev)
{
trace_xen_cdrom_unrealize();
}
diff --git a/hw/char/serial-pci-multi.c b/hw/char/serial-pci-multi.c
index 1742cb7..5f9ccfc 100644
--- a/hw/char/serial-pci-multi.c
+++ b/hw/char/serial-pci-multi.c
@@ -56,7 +56,7 @@
for (i = 0; i < pci->ports; i++) {
s = pci->state + i;
- object_property_set_bool(OBJECT(s), false, "realized", NULL);
+ object_property_set_bool(OBJECT(s), false, "realized", &error_abort);
memory_region_del_subregion(&pci->iobar, &s->io);
g_free(pci->name[i]);
}
diff --git a/hw/char/serial-pci.c b/hw/char/serial-pci.c
index 743552c..37818db 100644
--- a/hw/char/serial-pci.c
+++ b/hw/char/serial-pci.c
@@ -68,7 +68,7 @@
PCISerialState *pci = DO_UPCAST(PCISerialState, dev, dev);
SerialState *s = &pci->state;
- object_property_set_bool(OBJECT(s), false, "realized", NULL);
+ object_property_set_bool(OBJECT(s), false, "realized", &error_abort);
qemu_free_irq(s->irq);
}
diff --git a/hw/char/serial.c b/hw/char/serial.c
index c822a9a..7d74694 100644
--- a/hw/char/serial.c
+++ b/hw/char/serial.c
@@ -950,7 +950,7 @@
serial_reset(s);
}
-static void serial_unrealize(DeviceState *dev, Error **errp)
+static void serial_unrealize(DeviceState *dev)
{
SerialState *s = SERIAL(dev);
diff --git a/hw/char/virtio-console.c b/hw/char/virtio-console.c
index b010c21..4f46753 100644
--- a/hw/char/virtio-console.c
+++ b/hw/char/virtio-console.c
@@ -249,7 +249,7 @@
}
}
-static void virtconsole_unrealize(DeviceState *dev, Error **errp)
+static void virtconsole_unrealize(DeviceState *dev)
{
VirtConsole *vcon = VIRTIO_CONSOLE(dev);
diff --git a/hw/char/virtio-serial-bus.c b/hw/char/virtio-serial-bus.c
index 99a65ba..262089c 100644
--- a/hw/char/virtio-serial-bus.c
+++ b/hw/char/virtio-serial-bus.c
@@ -1010,7 +1010,7 @@
virtio_notify_config(VIRTIO_DEVICE(hotplug_dev));
}
-static void virtser_port_device_unrealize(DeviceState *dev, Error **errp)
+static void virtser_port_device_unrealize(DeviceState *dev)
{
VirtIOSerialPort *port = VIRTIO_SERIAL_PORT(dev);
VirtIOSerialPortClass *vsc = VIRTIO_SERIAL_PORT_GET_CLASS(dev);
@@ -1022,7 +1022,7 @@
QTAILQ_REMOVE(&vser->ports, port, next);
if (vsc->unrealize) {
- vsc->unrealize(dev, errp);
+ vsc->unrealize(dev);
}
}
@@ -1122,7 +1122,7 @@
.class_init = virtio_serial_port_class_init,
};
-static void virtio_serial_device_unrealize(DeviceState *dev, Error **errp)
+static void virtio_serial_device_unrealize(DeviceState *dev)
{
VirtIODevice *vdev = VIRTIO_DEVICE(dev);
VirtIOSerial *vser = VIRTIO_SERIAL(dev);
@@ -1147,7 +1147,7 @@
g_free(vser->post_load);
}
- qbus_set_hotplug_handler(BUS(&vser->bus), NULL, errp);
+ qbus_set_hotplug_handler(BUS(&vser->bus), NULL, &error_abort);
virtio_cleanup(vdev);
}
diff --git a/hw/char/xilinx_uartlite.c b/hw/char/xilinx_uartlite.c
index c651228..ae4ccd0 100644
--- a/hw/char/xilinx_uartlite.c
+++ b/hw/char/xilinx_uartlite.c
@@ -23,7 +23,7 @@
*/
#include "qemu/osdep.h"
-#include "hw/hw.h"
+#include "qemu/log.h"
#include "hw/irq.h"
#include "hw/qdev-properties.h"
#include "hw/sysbus.h"
@@ -135,7 +135,8 @@
switch (addr)
{
case R_STATUS:
- hw_error("write to UART STATUS?\n");
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: write to UART STATUS\n",
+ __func__);
break;
case R_CTRL:
diff --git a/hw/core/bus.c b/hw/core/bus.c
index 3dc0a82..5092479 100644
--- a/hw/core/bus.c
+++ b/hw/core/bus.c
@@ -25,7 +25,7 @@
void qbus_set_hotplug_handler(BusState *bus, Object *handler, Error **errp)
{
- object_property_set_link(OBJECT(bus), OBJECT(handler),
+ object_property_set_link(OBJECT(bus), handler,
QDEV_HOTPLUG_HANDLER_PROPERTY, errp);
}
@@ -122,7 +122,7 @@
if (bus->parent) {
QLIST_INSERT_HEAD(&bus->parent->child_bus, bus, sibling);
bus->parent->num_child_bus++;
- object_property_add_child(OBJECT(bus->parent), bus->name, OBJECT(bus), NULL);
+ object_property_add_child(OBJECT(bus->parent), bus->name, OBJECT(bus));
object_unref(OBJECT(bus));
} else {
/* The only bus without a parent is the main system bus */
@@ -176,11 +176,10 @@
BusState *bus = BUS(obj);
BusClass *bc = BUS_GET_CLASS(bus);
BusChild *kid;
- Error *local_err = NULL;
if (value && !bus->realized) {
if (bc->realize) {
- bc->realize(bus, &local_err);
+ bc->realize(bus, errp);
}
/* TODO: recursive realization */
@@ -188,21 +187,13 @@
QTAILQ_FOREACH(kid, &bus->children, sibling) {
DeviceState *dev = kid->child;
object_property_set_bool(OBJECT(dev), false, "realized",
- &local_err);
- if (local_err != NULL) {
- break;
- }
+ &error_abort);
}
- if (bc->unrealize && local_err == NULL) {
- bc->unrealize(bus, &local_err);
+ if (bc->unrealize) {
+ bc->unrealize(bus);
}
}
- if (local_err != NULL) {
- error_propagate(errp, local_err);
- return;
- }
-
bus->realized = value;
}
@@ -215,10 +206,9 @@
TYPE_HOTPLUG_HANDLER,
(Object **)&bus->hotplug_handler,
object_property_allow_set_link,
- 0,
- NULL);
+ 0);
object_property_add_bool(obj, "realized",
- bus_get_realized, bus_set_realized, NULL);
+ bus_get_realized, bus_set_realized);
}
static char *default_bus_get_fw_dev_path(DeviceState *dev)
diff --git a/hw/core/cpu.c b/hw/core/cpu.c
index 786a1be..5284d38 100644
--- a/hw/core/cpu.c
+++ b/hw/core/cpu.c
@@ -345,7 +345,7 @@
trace_init_vcpu(cpu);
}
-static void cpu_common_unrealizefn(DeviceState *dev, Error **errp)
+static void cpu_common_unrealizefn(DeviceState *dev)
{
CPUState *cpu = CPU(dev);
/* NOTE: latest generic point before the cpu is fully unrealized */
diff --git a/hw/core/generic-loader.c b/hw/core/generic-loader.c
index b9aaa52..a242c07 100644
--- a/hw/core/generic-loader.c
+++ b/hw/core/generic-loader.c
@@ -173,7 +173,7 @@
}
}
-static void generic_loader_unrealize(DeviceState *dev, Error **errp)
+static void generic_loader_unrealize(DeviceState *dev)
{
qemu_unregister_reset(generic_loader_reset, dev);
}
diff --git a/hw/core/machine-qmp-cmds.c b/hw/core/machine-qmp-cmds.c
index eed5aeb..2c5da84 100644
--- a/hw/core/machine-qmp-cmds.c
+++ b/hw/core/machine-qmp-cmds.c
@@ -11,9 +11,13 @@
#include "cpu.h"
#include "hw/boards.h"
#include "qapi/error.h"
+#include "qapi/qapi-builtin-visit.h"
#include "qapi/qapi-commands-machine.h"
#include "qapi/qmp/qerror.h"
+#include "qapi/qmp/qobject.h"
+#include "qapi/qobject-input-visitor.h"
#include "qemu/main-loop.h"
+#include "qom/qom-qobject.h"
#include "sysemu/hostmem.h"
#include "sysemu/hw_accel.h"
#include "sysemu/numa.h"
@@ -303,6 +307,8 @@
{
MemdevList **list = opaque;
MemdevList *m = NULL;
+ QObject *host_nodes;
+ Visitor *v;
if (object_dynamic_cast(obj, TYPE_MEMORY_BACKEND)) {
m = g_malloc0(sizeof(*m));
@@ -325,9 +331,13 @@
"policy",
"HostMemPolicy",
&error_abort);
- object_property_get_uint16List(obj, "host-nodes",
- &m->value->host_nodes,
- &error_abort);
+ host_nodes = object_property_get_qobject(obj,
+ "host-nodes",
+ &error_abort);
+ v = qobject_input_visitor_new(host_nodes);
+ visit_type_uint16List(v, NULL, &m->value->host_nodes, &error_abort);
+ visit_free(v);
+ qobject_unref(host_nodes);
m->next = *list;
*list = m;
diff --git a/hw/core/machine.c b/hw/core/machine.c
index 7a50dd5..bb3a7b1 100644
--- a/hw/core/machine.c
+++ b/hw/core/machine.c
@@ -787,85 +787,80 @@
mc->numa_auto_assign_ram = numa_default_auto_assign_ram;
object_class_property_add_str(oc, "kernel",
- machine_get_kernel, machine_set_kernel, &error_abort);
+ machine_get_kernel, machine_set_kernel);
object_class_property_set_description(oc, "kernel",
- "Linux kernel image file", &error_abort);
+ "Linux kernel image file");
object_class_property_add_str(oc, "initrd",
- machine_get_initrd, machine_set_initrd, &error_abort);
+ machine_get_initrd, machine_set_initrd);
object_class_property_set_description(oc, "initrd",
- "Linux initial ramdisk file", &error_abort);
+ "Linux initial ramdisk file");
object_class_property_add_str(oc, "append",
- machine_get_append, machine_set_append, &error_abort);
+ machine_get_append, machine_set_append);
object_class_property_set_description(oc, "append",
- "Linux kernel command line", &error_abort);
+ "Linux kernel command line");
object_class_property_add_str(oc, "dtb",
- machine_get_dtb, machine_set_dtb, &error_abort);
+ machine_get_dtb, machine_set_dtb);
object_class_property_set_description(oc, "dtb",
- "Linux kernel device tree file", &error_abort);
+ "Linux kernel device tree file");
object_class_property_add_str(oc, "dumpdtb",
- machine_get_dumpdtb, machine_set_dumpdtb, &error_abort);
+ machine_get_dumpdtb, machine_set_dumpdtb);
object_class_property_set_description(oc, "dumpdtb",
- "Dump current dtb to a file and quit", &error_abort);
+ "Dump current dtb to a file and quit");
object_class_property_add(oc, "phandle-start", "int",
machine_get_phandle_start, machine_set_phandle_start,
- NULL, NULL, &error_abort);
+ NULL, NULL);
object_class_property_set_description(oc, "phandle-start",
- "The first phandle ID we may generate dynamically", &error_abort);
+ "The first phandle ID we may generate dynamically");
object_class_property_add_str(oc, "dt-compatible",
- machine_get_dt_compatible, machine_set_dt_compatible, &error_abort);
+ machine_get_dt_compatible, machine_set_dt_compatible);
object_class_property_set_description(oc, "dt-compatible",
- "Overrides the \"compatible\" property of the dt root node",
- &error_abort);
+ "Overrides the \"compatible\" property of the dt root node");
object_class_property_add_bool(oc, "dump-guest-core",
- machine_get_dump_guest_core, machine_set_dump_guest_core, &error_abort);
+ machine_get_dump_guest_core, machine_set_dump_guest_core);
object_class_property_set_description(oc, "dump-guest-core",
- "Include guest memory in a core dump", &error_abort);
+ "Include guest memory in a core dump");
object_class_property_add_bool(oc, "mem-merge",
- machine_get_mem_merge, machine_set_mem_merge, &error_abort);
+ machine_get_mem_merge, machine_set_mem_merge);
object_class_property_set_description(oc, "mem-merge",
- "Enable/disable memory merge support", &error_abort);
+ "Enable/disable memory merge support");
object_class_property_add_bool(oc, "usb",
- machine_get_usb, machine_set_usb, &error_abort);
+ machine_get_usb, machine_set_usb);
object_class_property_set_description(oc, "usb",
- "Set on/off to enable/disable usb", &error_abort);
+ "Set on/off to enable/disable usb");
object_class_property_add_bool(oc, "graphics",
- machine_get_graphics, machine_set_graphics, &error_abort);
+ machine_get_graphics, machine_set_graphics);
object_class_property_set_description(oc, "graphics",
- "Set on/off to enable/disable graphics emulation", &error_abort);
+ "Set on/off to enable/disable graphics emulation");
object_class_property_add_str(oc, "firmware",
- machine_get_firmware, machine_set_firmware,
- &error_abort);
+ machine_get_firmware, machine_set_firmware);
object_class_property_set_description(oc, "firmware",
- "Firmware image", &error_abort);
+ "Firmware image");
object_class_property_add_bool(oc, "suppress-vmdesc",
- machine_get_suppress_vmdesc, machine_set_suppress_vmdesc,
- &error_abort);
+ machine_get_suppress_vmdesc, machine_set_suppress_vmdesc);
object_class_property_set_description(oc, "suppress-vmdesc",
- "Set on to disable self-describing migration", &error_abort);
+ "Set on to disable self-describing migration");
object_class_property_add_bool(oc, "enforce-config-section",
- machine_get_enforce_config_section, machine_set_enforce_config_section,
- &error_abort);
+ machine_get_enforce_config_section, machine_set_enforce_config_section);
object_class_property_set_description(oc, "enforce-config-section",
- "Set on to enforce configuration section migration", &error_abort);
+ "Set on to enforce configuration section migration");
object_class_property_add_str(oc, "memory-encryption",
- machine_get_memory_encryption, machine_set_memory_encryption,
- &error_abort);
+ machine_get_memory_encryption, machine_set_memory_encryption);
object_class_property_set_description(oc, "memory-encryption",
- "Set memory encryption object to use", &error_abort);
+ "Set memory encryption object to use");
}
static void machine_class_base_init(ObjectClass *oc, void *data)
@@ -894,40 +889,34 @@
ms->nvdimms_state = g_new0(NVDIMMState, 1);
object_property_add_bool(obj, "nvdimm",
- machine_get_nvdimm, machine_set_nvdimm,
- &error_abort);
+ machine_get_nvdimm, machine_set_nvdimm);
object_property_set_description(obj, "nvdimm",
"Set on/off to enable/disable "
- "NVDIMM instantiation", NULL);
+ "NVDIMM instantiation");
object_property_add_str(obj, "nvdimm-persistence",
machine_get_nvdimm_persistence,
- machine_set_nvdimm_persistence,
- &error_abort);
+ machine_set_nvdimm_persistence);
object_property_set_description(obj, "nvdimm-persistence",
"Set NVDIMM persistence"
- "Valid values are cpu, mem-ctrl",
- NULL);
+ "Valid values are cpu, mem-ctrl");
}
if (mc->cpu_index_to_instance_props && mc->get_default_cpu_node_id) {
ms->numa_state = g_new0(NumaState, 1);
object_property_add_bool(obj, "hmat",
- machine_get_hmat, machine_set_hmat,
- &error_abort);
+ machine_get_hmat, machine_set_hmat);
object_property_set_description(obj, "hmat",
"Set on/off to enable/disable "
"ACPI Heterogeneous Memory Attribute "
- "Table (HMAT)", NULL);
+ "Table (HMAT)");
}
object_property_add_str(obj, "memory-backend",
- machine_get_memdev, machine_set_memdev,
- &error_abort);
+ machine_get_memdev, machine_set_memdev);
object_property_set_description(obj, "memory-backend",
"Set RAM backend"
- "Valid value is ID of hostmem based backend",
- &error_abort);
+ "Valid value is ID of hostmem based backend");
/* Register notifier when init is done for sysbus sanity checks */
ms->sysbus_notifier.notify = machine_init_notify;
diff --git a/hw/core/qdev-clock.c b/hw/core/qdev-clock.c
index a94cc44..5cc1e82 100644
--- a/hw/core/qdev-clock.c
+++ b/hw/core/qdev-clock.c
@@ -46,7 +46,7 @@
*/
if (clk == NULL) {
clk = CLOCK(object_new(TYPE_CLOCK));
- object_property_add_child(OBJECT(dev), name, OBJECT(clk), &error_abort);
+ object_property_add_child(OBJECT(dev), name, OBJECT(clk));
if (output) {
/*
* Remove object_new()'s initial reference.
@@ -59,7 +59,7 @@
object_property_add_link(OBJECT(dev), name,
object_get_typename(OBJECT(clk)),
(Object **) &ncl->clock,
- NULL, OBJ_PROP_LINK_STRONG, &error_abort);
+ NULL, OBJ_PROP_LINK_STRONG);
}
ncl->clock = clk;
diff --git a/hw/core/qdev-properties.c b/hw/core/qdev-properties.c
index 2047114..cc92481 100644
--- a/hw/core/qdev-properties.c
+++ b/hw/core/qdev-properties.c
@@ -1043,11 +1043,7 @@
arrayprop->prop.info->get,
arrayprop->prop.info->set,
array_element_release,
- arrayprop, &local_err);
- if (local_err) {
- error_propagate(errp, local_err);
- return;
- }
+ arrayprop);
}
}
@@ -1254,13 +1250,12 @@
/* --- object link property --- */
-static void create_link_property(ObjectClass *oc, Property *prop, Error **errp)
+static void create_link_property(ObjectClass *oc, Property *prop)
{
object_class_property_add_link(oc, prop->name, prop->link_type,
prop->offset,
qdev_prop_allow_set_link_before_realize,
- OBJ_PROP_LINK_STRONG,
- errp);
+ OBJ_PROP_LINK_STRONG);
}
const PropertyInfo qdev_prop_link = {
diff --git a/hw/core/qdev.c b/hw/core/qdev.c
index dd77a56..9e5538a 100644
--- a/hw/core/qdev.c
+++ b/hw/core/qdev.c
@@ -65,7 +65,7 @@
bus->num_children--;
/* This gives back ownership of kid->child back to us. */
- object_property_del(OBJECT(bus), name, NULL);
+ object_property_del(OBJECT(bus), name);
object_unref(OBJECT(kid->child));
g_free(kid);
return;
@@ -91,8 +91,7 @@
object_get_typename(OBJECT(child)),
(Object **)&kid->child,
NULL, /* read-only property */
- 0, /* return ownership on prop deletion */
- NULL);
+ 0);
}
void qdev_set_parent_bus(DeviceState *dev, BusState *bus)
@@ -393,7 +392,7 @@
void qdev_simple_device_unplug_cb(HotplugHandler *hotplug_dev,
DeviceState *dev, Error **errp)
{
- object_property_set_bool(OBJECT(dev), false, "realized", NULL);
+ object_property_set_bool(OBJECT(dev), false, "realized", &error_abort);
}
/*
@@ -481,7 +480,7 @@
gchar *propname = g_strdup_printf("%s[%u]", name, i);
object_property_add_child(OBJECT(dev), propname,
- OBJECT(gpio_list->in[i]), &error_abort);
+ OBJECT(gpio_list->in[i]));
g_free(propname);
}
@@ -512,8 +511,7 @@
object_property_add_link(OBJECT(dev), propname, TYPE_IRQ,
(Object **)&pins[i],
object_property_allow_set_link,
- OBJ_PROP_LINK_STRONG,
- &error_abort);
+ OBJ_PROP_LINK_STRONG);
g_free(propname);
}
gpio_list->num_out += n;
@@ -542,15 +540,11 @@
{
char *propname = g_strdup_printf("%s[%d]",
name ? name : "unnamed-gpio-out", n);
- if (pin) {
- /* We need a name for object_property_set_link to work. If the
- * object has a parent, object_property_add_child will come back
- * with an error without doing anything. If it has none, it will
- * never fail. So we can just call it with a NULL Error pointer.
- */
+ if (pin && !OBJECT(pin)->parent) {
+ /* We need a name for object_property_set_link to work */
object_property_add_child(container_get(qdev_get_machine(),
"/unattached"),
- "non-qdev-gpio[*]", OBJECT(pin), NULL);
+ "non-qdev-gpio[*]", OBJECT(pin));
}
object_property_set_link(OBJECT(dev), OBJECT(pin), propname, &error_abort);
g_free(propname);
@@ -608,8 +602,7 @@
char *propname = g_strdup_printf("%s[%d]", nm, i);
object_property_add_alias(OBJECT(container), propname,
- OBJECT(dev), propname,
- &error_abort);
+ OBJECT(dev), propname);
g_free(propname);
}
for (i = 0; i < ngl->num_out; i++) {
@@ -617,8 +610,7 @@
char *propname = g_strdup_printf("%s[%d]", nm, i);
object_property_add_alias(OBJECT(container), propname,
- OBJECT(dev), propname,
- &error_abort);
+ OBJECT(dev), propname);
g_free(propname);
}
QLIST_REMOVE(ngl, node);
@@ -759,7 +751,7 @@
name = g_strdup_printf("legacy-%s", prop->name);
object_class_property_add(OBJECT_CLASS(dc), name, "str",
prop->info->print ? qdev_get_legacy_property : prop->info->get,
- NULL, NULL, prop, &error_abort);
+ NULL, NULL, prop);
}
void qdev_property_add_static(DeviceState *dev, Property *prop)
@@ -772,11 +764,10 @@
op = object_property_add(obj, prop->name, prop->info->name,
prop->info->get, prop->info->set,
prop->info->release,
- prop, &error_abort);
+ prop);
object_property_set_description(obj, prop->name,
- prop->info->description,
- &error_abort);
+ prop->info->description);
if (prop->set_default) {
prop->info->set_default_value(op, prop);
@@ -791,7 +782,7 @@
ObjectClass *oc = OBJECT_CLASS(klass);
if (prop->info->create) {
- prop->info->create(oc, prop, &error_abort);
+ prop->info->create(oc, prop);
} else {
ObjectProperty *op;
@@ -799,14 +790,13 @@
prop->name, prop->info->name,
prop->info->get, prop->info->set,
prop->info->release,
- prop, &error_abort);
+ prop);
if (prop->set_default) {
prop->info->set_default_value(op, prop);
}
}
object_class_property_set_description(oc, prop->name,
- prop->info->description,
- &error_abort);
+ prop->info->description);
}
/* @qdev_alias_all_properties - Add alias properties to the source object for
@@ -823,8 +813,7 @@
for (prop = dc->props_; prop && prop->name; prop++) {
object_property_add_alias(source, prop->name,
- OBJECT(target), prop->name,
- &error_abort);
+ OBJECT(target), prop->name);
}
class = object_class_get_parent(class);
} while (class != object_class_by_name(TYPE_DEVICE));
@@ -876,7 +865,7 @@
object_property_add_child(container_get(qdev_get_machine(),
"/unattached"),
- name, obj, &error_abort);
+ name, obj);
unattached_parent = true;
g_free(name);
}
@@ -956,23 +945,18 @@
}
} else if (!value && dev->realized) {
- /* We want local_err to track only the first error */
QLIST_FOREACH(bus, &dev->child_bus, sibling) {
object_property_set_bool(OBJECT(bus), false, "realized",
- local_err ? NULL : &local_err);
+ &error_abort);
}
if (qdev_get_vmsd(dev)) {
vmstate_unregister(VMSTATE_IF(dev), qdev_get_vmsd(dev), dev);
}
if (dc->unrealize) {
- dc->unrealize(dev, local_err ? NULL : &local_err);
+ dc->unrealize(dev);
}
dev->pending_deleted_event = true;
DEVICE_LISTENER_CALL(unrealize, Reverse, dev);
-
- if (local_err != NULL) {
- goto fail;
- }
}
assert(local_err == NULL);
@@ -982,7 +966,7 @@
child_realize_fail:
QLIST_FOREACH(bus, &dev->child_bus, sibling) {
object_property_set_bool(OBJECT(bus), false, "realized",
- NULL);
+ &error_abort);
}
if (qdev_get_vmsd(dev)) {
@@ -993,7 +977,7 @@
g_free(dev->canonical_path);
dev->canonical_path = NULL;
if (dc->unrealize) {
- dc->unrealize(dev, NULL);
+ dc->unrealize(dev);
}
fail:
@@ -1094,7 +1078,7 @@
BusState *bus;
if (dev->realized) {
- object_property_set_bool(obj, false, "realized", NULL);
+ object_property_set_bool(obj, false, "realized", &error_abort);
}
while (dev->num_child_bus) {
bus = QLIST_FIRST(&dev->child_bus);
@@ -1203,17 +1187,13 @@
rc->get_transitional_function = device_get_transitional_reset;
object_class_property_add_bool(class, "realized",
- device_get_realized, device_set_realized,
- &error_abort);
+ device_get_realized, device_set_realized);
object_class_property_add_bool(class, "hotpluggable",
- device_get_hotpluggable, NULL,
- &error_abort);
+ device_get_hotpluggable, NULL);
object_class_property_add_bool(class, "hotplugged",
- device_get_hotplugged, NULL,
- &error_abort);
+ device_get_hotplugged, NULL);
object_class_property_add_link(class, "parent_bus", TYPE_BUS,
- offsetof(DeviceState, parent_bus), NULL, 0,
- &error_abort);
+ offsetof(DeviceState, parent_bus), NULL, 0);
}
void device_class_set_props(DeviceClass *dc, Property *props)
diff --git a/hw/core/stream.c b/hw/core/stream.c
index 39b1e59..a65ad12 100644
--- a/hw/core/stream.c
+++ b/hw/core/stream.c
@@ -3,11 +3,11 @@
#include "qemu/module.h"
size_t
-stream_push(StreamSlave *sink, uint8_t *buf, size_t len)
+stream_push(StreamSlave *sink, uint8_t *buf, size_t len, bool eop)
{
StreamSlaveClass *k = STREAM_SLAVE_GET_CLASS(sink);
- return k->push(sink, buf, len);
+ return k->push(sink, buf, len, eop);
}
bool
diff --git a/hw/cpu/core.c b/hw/cpu/core.c
index 9874c5c..a92ac59 100644
--- a/hw/cpu/core.c
+++ b/hw/cpu/core.c
@@ -76,9 +76,9 @@
CPUCore *core = CPU_CORE(obj);
object_property_add(obj, "core-id", "int", core_prop_get_core_id,
- core_prop_set_core_id, NULL, NULL, NULL);
+ core_prop_set_core_id, NULL, NULL);
object_property_add(obj, "nr-threads", "int", core_prop_get_nr_threads,
- core_prop_set_nr_threads, NULL, NULL, NULL);
+ core_prop_set_nr_threads, NULL, NULL);
core->nr_threads = ms->smp.threads;
}
diff --git a/hw/display/artist.c b/hw/display/artist.c
index 753dbb9..6261bfe 100644
--- a/hw/display/artist.c
+++ b/hw/display/artist.c
@@ -21,7 +21,7 @@
#include "migration/vmstate.h"
#include "ui/console.h"
#include "trace.h"
-#include "hw/display/framebuffer.h"
+#include "framebuffer.h"
#define TYPE_ARTIST "artist"
#define ARTIST(obj) OBJECT_CHECK(ARTISTState, (obj), TYPE_ARTIST)
@@ -1353,7 +1353,7 @@
s->cursor_height = 32;
s->cursor_width = 32;
- s->con = graphic_console_init(DEVICE(dev), 0, &artist_ops, s);
+ s->con = graphic_console_init(dev, 0, &artist_ops, s);
qemu_console_resize(s->con, s->width, s->height);
}
diff --git a/hw/display/ati.c b/hw/display/ati.c
index 58ec829..065f197 100644
--- a/hw/display/ati.c
+++ b/hw/display/ati.c
@@ -511,7 +511,7 @@
}
switch (addr) {
case MM_INDEX:
- s->regs.mm_index = data;
+ s->regs.mm_index = data & ~3;
break;
case MM_DATA ... MM_DATA + 3:
/* indexed access to regs or memory */
diff --git a/hw/display/bochs-display.c b/hw/display/bochs-display.c
index e763a0a..a8e8ab8 100644
--- a/hw/display/bochs-display.c
+++ b/hw/display/bochs-display.c
@@ -333,8 +333,7 @@
/* Expose framebuffer byteorder via QOM */
object_property_add_bool(obj, "big-endian-framebuffer",
bochs_display_get_big_endian_fb,
- bochs_display_set_big_endian_fb,
- NULL);
+ bochs_display_set_big_endian_fb);
dev->cap_present |= QEMU_PCI_CAP_EXPRESS;
}
diff --git a/hw/display/cg3.c b/hw/display/cg3.c
index a1ede10..7cbe6e5 100644
--- a/hw/display/cg3.c
+++ b/hw/display/cg3.c
@@ -35,6 +35,7 @@
#include "hw/qdev-properties.h"
#include "qemu/log.h"
#include "qemu/module.h"
+#include "trace.h"
/* Change to 1 to enable debugging */
#define DEBUG_CG3 0
@@ -63,12 +64,6 @@
#define CG3_VRAM_SIZE 0x100000
#define CG3_VRAM_OFFSET 0x800000
-#define DPRINTF(fmt, ...) do { \
- if (DEBUG_CG3) { \
- printf("CG3: " fmt , ## __VA_ARGS__); \
- } \
-} while (0)
-
#define TYPE_CG3 "cgthree"
#define CG3(obj) OBJECT_CHECK(CG3State, (obj), TYPE_CG3)
@@ -195,7 +190,8 @@
val = 0;
break;
}
- DPRINTF("read %02x from reg %" HWADDR_PRIx "\n", val, addr);
+ trace_cg3_read(addr, val, size);
+
return val;
}
@@ -206,9 +202,7 @@
uint8_t regval;
int i;
- DPRINTF("write %" PRIx64 " to reg %" HWADDR_PRIx " size %d\n",
- val, addr, size);
-
+ trace_cg3_write(addr, val, size);
switch (addr) {
case CG3_REG_BT458_ADDR:
s->dac_index = val;
@@ -321,7 +315,7 @@
sysbus_init_irq(sbd, &s->irq);
- s->con = graphic_console_init(DEVICE(dev), 0, &cg3_ops, s);
+ s->con = graphic_console_init(dev, 0, &cg3_ops, s);
qemu_console_resize(s->con, s->width, s->height);
}
diff --git a/hw/display/cirrus_vga.c b/hw/display/cirrus_vga.c
index 1f29731..92c197c 100644
--- a/hw/display/cirrus_vga.c
+++ b/hw/display/cirrus_vga.c
@@ -35,6 +35,7 @@
#include "qemu/osdep.h"
#include "qemu/module.h"
#include "qemu/units.h"
+#include "qemu/log.h"
#include "sysemu/reset.h"
#include "qapi/error.h"
#include "trace.h"
@@ -52,7 +53,6 @@
*/
//#define DEBUG_CIRRUS
-//#define DEBUG_BITBLT
/***************************************
*
@@ -905,9 +905,8 @@
static int cirrus_bitblt_videotocpu(CirrusVGAState * s)
{
/* XXX */
-#ifdef DEBUG_BITBLT
- printf("cirrus: bitblt (video to cpu) is not implemented yet\n");
-#endif
+ qemu_log_mask(LOG_UNIMP,
+ "cirrus: bitblt (video to cpu) is not implemented\n");
return 0;
}
@@ -950,19 +949,16 @@
s->cirrus_blt_dstaddr &= s->cirrus_addr_mask;
s->cirrus_blt_srcaddr &= s->cirrus_addr_mask;
-#ifdef DEBUG_BITBLT
- printf("rop=0x%02x mode=0x%02x modeext=0x%02x w=%d h=%d dpitch=%d spitch=%d daddr=0x%08x saddr=0x%08x writemask=0x%02x\n",
- blt_rop,
- s->cirrus_blt_mode,
- s->cirrus_blt_modeext,
- s->cirrus_blt_width,
- s->cirrus_blt_height,
- s->cirrus_blt_dstpitch,
- s->cirrus_blt_srcpitch,
- s->cirrus_blt_dstaddr,
- s->cirrus_blt_srcaddr,
- s->vga.gr[0x2f]);
-#endif
+ trace_vga_cirrus_bitblt_start(blt_rop,
+ s->cirrus_blt_mode,
+ s->cirrus_blt_modeext,
+ s->cirrus_blt_width,
+ s->cirrus_blt_height,
+ s->cirrus_blt_dstpitch,
+ s->cirrus_blt_srcpitch,
+ s->cirrus_blt_dstaddr,
+ s->cirrus_blt_srcaddr,
+ s->vga.gr[0x2f]);
switch (s->cirrus_blt_mode & CIRRUS_BLTMODE_PIXELWIDTHMASK) {
case CIRRUS_BLTMODE_PIXELWIDTH8:
@@ -978,9 +974,8 @@
s->cirrus_blt_pixelwidth = 4;
break;
default:
-#ifdef DEBUG_BITBLT
- printf("cirrus: bitblt - pixel width is unknown\n");
-#endif
+ qemu_log_mask(LOG_GUEST_ERROR,
+ "cirrus: bitblt - pixel width is unknown\n");
goto bitblt_ignore;
}
s->cirrus_blt_mode &= ~CIRRUS_BLTMODE_PIXELWIDTHMASK;
@@ -989,9 +984,8 @@
cirrus_blt_mode & (CIRRUS_BLTMODE_MEMSYSSRC |
CIRRUS_BLTMODE_MEMSYSDEST))
== (CIRRUS_BLTMODE_MEMSYSSRC | CIRRUS_BLTMODE_MEMSYSDEST)) {
-#ifdef DEBUG_BITBLT
- printf("cirrus: bitblt - memory-to-memory copy is requested\n");
-#endif
+ qemu_log_mask(LOG_UNIMP,
+ "cirrus: bitblt - memory-to-memory copy requested\n");
goto bitblt_ignore;
}
@@ -1038,7 +1032,9 @@
} else {
if (s->cirrus_blt_mode & CIRRUS_BLTMODE_TRANSPARENTCOMP) {
if (s->cirrus_blt_pixelwidth > 2) {
- printf("src transparent without colorexpand must be 8bpp or 16bpp\n");
+ qemu_log_mask(LOG_GUEST_ERROR,
+ "cirrus: src transparent without colorexpand "
+ "must be 8bpp or 16bpp\n");
goto bitblt_ignore;
}
if (s->cirrus_blt_mode & CIRRUS_BLTMODE_BACKWARDS) {
@@ -1136,10 +1132,9 @@
ret = 16;
break; /* XGA HiColor */
default:
-#ifdef DEBUG_CIRRUS
- printf("cirrus: invalid DAC value %x in 16bpp\n",
- (s->cirrus_hidden_dac_data & 0xf));
-#endif
+ qemu_log_mask(LOG_GUEST_ERROR,
+ "cirrus: invalid DAC value 0x%x in 16bpp\n",
+ (s->cirrus_hidden_dac_data & 0xf));
ret = 15; /* XXX */
break;
}
@@ -1308,11 +1303,9 @@
#endif
return s->vga.sr[s->vga.sr_index];
default:
-#ifdef DEBUG_CIRRUS
- printf("cirrus: inport sr_index %02x\n", s->vga.sr_index);
-#endif
+ qemu_log_mask(LOG_GUEST_ERROR,
+ "cirrus: inport sr_index 0x%02x\n", s->vga.sr_index);
return 0xff;
- break;
}
}
@@ -1401,10 +1394,9 @@
cirrus_update_memory_access(s);
break;
default:
-#ifdef DEBUG_CIRRUS
- printf("cirrus: outport sr_index %02x, sr_value %02x\n",
- s->vga.sr_index, val);
-#endif
+ qemu_log_mask(LOG_GUEST_ERROR,
+ "cirrus: outport sr_index 0x%02x, sr_value 0x%02x\n",
+ s->vga.sr_index, val);
break;
}
}
@@ -1502,9 +1494,8 @@
if (reg_index < 0x3a) {
return s->vga.gr[reg_index];
} else {
-#ifdef DEBUG_CIRRUS
- printf("cirrus: inport gr_index %02x\n", reg_index);
-#endif
+ qemu_log_mask(LOG_GUEST_ERROR,
+ "cirrus: inport gr_index 0x%02x\n", reg_index);
return 0xff;
}
}
@@ -1512,9 +1503,7 @@
static void
cirrus_vga_write_gr(CirrusVGAState * s, unsigned reg_index, int reg_value)
{
-#if defined(DEBUG_BITBLT) && 0
- printf("gr%02x: %02x\n", reg_index, reg_value);
-#endif
+ trace_vga_cirrus_write_gr(reg_index, reg_value);
switch (reg_index) {
case 0x00: // Standard VGA, BGCOLOR 0x000000ff
s->vga.gr[reg_index] = reg_value & gr_mask[reg_index];
@@ -1593,10 +1582,9 @@
cirrus_write_bitblt(s, reg_value);
break;
default:
-#ifdef DEBUG_CIRRUS
- printf("cirrus: outport gr_index %02x, gr_value %02x\n", reg_index,
- reg_value);
-#endif
+ qemu_log_mask(LOG_GUEST_ERROR,
+ "cirrus: outport gr_index 0x%02x, gr_value 0x%02x\n",
+ reg_index, reg_value);
break;
}
}
@@ -1651,9 +1639,8 @@
return s->vga.ar_index & 0x3f;
break;
default:
-#ifdef DEBUG_CIRRUS
- printf("cirrus: inport cr_index %02x\n", reg_index);
-#endif
+ qemu_log_mask(LOG_GUEST_ERROR,
+ "cirrus: inport cr_index 0x%02x\n", reg_index);
return 0xff;
}
}
@@ -1724,10 +1711,9 @@
break;
case 0x25: // Part Status
default:
-#ifdef DEBUG_CIRRUS
- printf("cirrus: outport cr_index %02x, cr_value %02x\n",
- s->vga.cr_index, reg_value);
-#endif
+ qemu_log_mask(LOG_GUEST_ERROR,
+ "cirrus: outport cr_index 0x%02x, cr_value 0x%02x\n",
+ s->vga.cr_index, reg_value);
break;
}
}
@@ -1837,9 +1823,8 @@
value = cirrus_vga_read_gr(s, 0x31);
break;
default:
-#ifdef DEBUG_CIRRUS
- printf("cirrus: mmio read - address 0x%04x\n", address);
-#endif
+ qemu_log_mask(LOG_GUEST_ERROR,
+ "cirrus: mmio read - address 0x%04x\n", address);
break;
}
@@ -1949,10 +1934,9 @@
cirrus_vga_write_gr(s, 0x31, value);
break;
default:
-#ifdef DEBUG_CIRRUS
- printf("cirrus: mmio write - addr 0x%04x val 0x%02x (ignored)\n",
- address, value);
-#endif
+ qemu_log_mask(LOG_GUEST_ERROR,
+ "cirrus: mmio write - addr 0x%04x val 0x%02x (ignored)\n",
+ address, value);
break;
}
}
@@ -2050,9 +2034,8 @@
}
} else {
val = 0xff;
-#ifdef DEBUG_CIRRUS
- printf("cirrus: mem_readb " TARGET_FMT_plx "\n", addr);
-#endif
+ qemu_log_mask(LOG_GUEST_ERROR,
+ "cirrus: mem_readb 0x" TARGET_FMT_plx "\n", addr);
}
return val;
}
@@ -2115,10 +2098,9 @@
cirrus_mmio_blt_write(s, addr & 0xff, mem_value);
}
} else {
-#ifdef DEBUG_CIRRUS
- printf("cirrus: mem_writeb " TARGET_FMT_plx " value 0x%02" PRIu64 "\n", addr,
- mem_value);
-#endif
+ qemu_log_mask(LOG_GUEST_ERROR,
+ "cirrus: mem_writeb 0x" TARGET_FMT_plx " "
+ "value 0x%02" PRIu64 "\n", addr, mem_value);
}
}
@@ -2414,6 +2396,9 @@
/* XXX handle bitblt */
(void)s;
+ qemu_log_mask(LOG_UNIMP,
+ "cirrus: linear bitblt is not implemented\n");
+
return 0xff;
}
diff --git a/hw/display/dpcd.c b/hw/display/dpcd.c
index 170545c..6446365 100644
--- a/hw/display/dpcd.c
+++ b/hw/display/dpcd.c
@@ -1,5 +1,5 @@
/*
- * dpcd.c
+ * Xilinx Display Port Control Data
*
* Copyright (C) 2015 : GreenSocs Ltd
* http://www.greensocs.com/ , email: info@greensocs.com
@@ -32,16 +32,7 @@
#include "hw/misc/auxbus.h"
#include "migration/vmstate.h"
#include "hw/display/dpcd.h"
-
-#ifndef DEBUG_DPCD
-#define DEBUG_DPCD 0
-#endif
-
-#define DPRINTF(fmt, ...) do { \
- if (DEBUG_DPCD) { \
- qemu_log("dpcd: " fmt, ## __VA_ARGS__); \
- } \
-} while (0)
+#include "trace.h"
#define DPCD_READABLE_AREA 0x600
@@ -70,8 +61,8 @@
offset);
ret = 0;
}
+ trace_dpcd_read(offset, ret);
- DPRINTF("read 0x%" PRIX8 " @0x%" HWADDR_PRIX "\n", ret, offset);
return ret;
}
@@ -80,8 +71,7 @@
{
DPCDState *e = DPCD(opaque);
- DPRINTF("write 0x%" PRIX8 " @0x%" HWADDR_PRIX "\n", (uint8_t)value, offset);
-
+ trace_dpcd_write(offset, value);
if (offset < DPCD_READABLE_AREA) {
e->dpcd_info[offset] = value;
} else {
@@ -137,7 +127,7 @@
{
DPCDState *s = DPCD(obj);
- memory_region_init_io(&s->iomem, obj, &aux_ops, s, TYPE_DPCD, 0x7FFFF);
+ memory_region_init_io(&s->iomem, obj, &aux_ops, s, TYPE_DPCD, 0x80000);
aux_init_mmio(AUX_SLAVE(obj), &s->iomem);
}
diff --git a/hw/display/exynos4210_fimd.c b/hw/display/exynos4210_fimd.c
index 1c0266c..4b7286b 100644
--- a/hw/display/exynos4210_fimd.c
+++ b/hw/display/exynos4210_fimd.c
@@ -31,6 +31,7 @@
#include "ui/pixel_ops.h"
#include "qemu/bswap.h"
#include "qemu/module.h"
+#include "qemu/log.h"
/* Debug messages configuration */
#define EXYNOS4210_FIMD_DEBUG 0
@@ -39,20 +40,15 @@
#if EXYNOS4210_FIMD_DEBUG == 0
#define DPRINT_L1(fmt, args...) do { } while (0)
#define DPRINT_L2(fmt, args...) do { } while (0)
- #define DPRINT_ERROR(fmt, args...) do { } while (0)
#elif EXYNOS4210_FIMD_DEBUG == 1
#define DPRINT_L1(fmt, args...) \
do {fprintf(stderr, "QEMU FIMD: "fmt, ## args); } while (0)
#define DPRINT_L2(fmt, args...) do { } while (0)
- #define DPRINT_ERROR(fmt, args...) \
- do {fprintf(stderr, "QEMU FIMD ERROR: "fmt, ## args); } while (0)
#else
#define DPRINT_L1(fmt, args...) \
do {fprintf(stderr, "QEMU FIMD: "fmt, ## args); } while (0)
#define DPRINT_L2(fmt, args...) \
do {fprintf(stderr, "QEMU FIMD: "fmt, ## args); } while (0)
- #define DPRINT_ERROR(fmt, args...) \
- do {fprintf(stderr, "QEMU FIMD ERROR: "fmt, ## args); } while (0)
#endif
#if EXYNOS4210_FIMD_MODE_TRACE == 0
@@ -1108,7 +1104,7 @@
case FIMD_WINCON_BUF2_STAT:
return 2;
default:
- DPRINT_ERROR("Non-existent buffer index\n");
+ qemu_log_mask(LOG_GUEST_ERROR, "FIMD: Non-existent buffer index\n");
return 0;
}
}
@@ -1160,20 +1156,24 @@
if (int128_get64(w->mem_section.size) != w->fb_len ||
!memory_region_is_ram(w->mem_section.mr)) {
- DPRINT_ERROR("Failed to find window %u framebuffer region\n", win);
+ qemu_log_mask(LOG_GUEST_ERROR,
+ "FIMD: Failed to find window %u framebuffer region\n",
+ win);
goto error_return;
}
w->host_fb_addr = cpu_physical_memory_map(fb_start_addr, &fb_mapped_len,
false);
if (!w->host_fb_addr) {
- DPRINT_ERROR("Failed to map window %u framebuffer\n", win);
+ qemu_log_mask(LOG_GUEST_ERROR,
+ "FIMD: Failed to map window %u framebuffer\n", win);
goto error_return;
}
if (fb_mapped_len != w->fb_len) {
- DPRINT_ERROR("Window %u mapped framebuffer length is less then "
- "expected\n", win);
+ qemu_log_mask(LOG_GUEST_ERROR,
+ "FIMD: Window %u mapped framebuffer length is less than "
+ "expected\n", win);
cpu_physical_memory_unmap(w->host_fb_addr, fb_mapped_len, 0, 0);
goto error_return;
}
@@ -1490,7 +1490,9 @@
break;
case 3:
if (w != 1 && w != 2) {
- DPRINT_ERROR("Bad write offset 0x%08x\n", offset);
+ qemu_log_mask(LOG_GUEST_ERROR,
+ "FIMD: Bad write offset 0x%08"HWADDR_PRIx"\n",
+ offset);
return;
}
s->window[w].osdsize = val;
@@ -1624,7 +1626,9 @@
break;
case FIMD_VIDW0ADD0_B2 ... FIMD_VIDW4ADD0_B2:
if (offset & 0x0004) {
- DPRINT_ERROR("bad write offset 0x%08x\n", offset);
+ qemu_log_mask(LOG_GUEST_ERROR,
+ "FIMD: bad write offset 0x%08"HWADDR_PRIx"\n",
+ offset);
break;
}
w = (offset - FIMD_VIDW0ADD0_B2) >> 3;
@@ -1638,14 +1642,18 @@
break;
case FIMD_SHD_ADD0_START ... FIMD_SHD_ADD0_END:
if (offset & 0x0004) {
- DPRINT_ERROR("bad write offset 0x%08x\n", offset);
+ qemu_log_mask(LOG_GUEST_ERROR,
+ "FIMD: bad write offset 0x%08"HWADDR_PRIx"\n",
+ offset);
break;
}
s->window[(offset - FIMD_SHD_ADD0_START) >> 3].shadow_buf_start = val;
break;
case FIMD_SHD_ADD1_START ... FIMD_SHD_ADD1_END:
if (offset & 0x0004) {
- DPRINT_ERROR("bad write offset 0x%08x\n", offset);
+ qemu_log_mask(LOG_GUEST_ERROR,
+ "FIMD: bad write offset 0x%08"HWADDR_PRIx"\n",
+ offset);
break;
}
s->window[(offset - FIMD_SHD_ADD1_START) >> 3].shadow_buf_end = val;
@@ -1665,7 +1673,8 @@
s->window[w].palette[i] = val;
break;
default:
- DPRINT_ERROR("bad write offset 0x%08x\n", offset);
+ qemu_log_mask(LOG_GUEST_ERROR,
+ "FIMD: bad write offset 0x%08"HWADDR_PRIx"\n", offset);
break;
}
}
@@ -1715,7 +1724,9 @@
break;
case 3:
if (w != 1 && w != 2) {
- DPRINT_ERROR("bad read offset 0x%08x\n", offset);
+ qemu_log_mask(LOG_GUEST_ERROR,
+ "FIMD: bad read offset 0x%08"HWADDR_PRIx"\n",
+ offset);
return 0xBAADBAAD;
}
ret = s->window[w].osdsize;
@@ -1809,7 +1820,8 @@
return s->window[w].palette[i];
}
- DPRINT_ERROR("bad read offset 0x%08x\n", offset);
+ qemu_log_mask(LOG_GUEST_ERROR,
+ "FIMD: bad read offset 0x%08"HWADDR_PRIx"\n", offset);
return 0xBAADBAAD;
}
diff --git a/hw/display/next-fb.c b/hw/display/next-fb.c
index 2b726a1..b0513a8 100644
--- a/hw/display/next-fb.c
+++ b/hw/display/next-fb.c
@@ -27,7 +27,7 @@
#include "hw/hw.h"
#include "hw/boards.h"
#include "hw/loader.h"
-#include "hw/display/framebuffer.h"
+#include "framebuffer.h"
#include "ui/pixel_ops.h"
#include "hw/m68k/next-cube.h"
diff --git a/hw/display/omap_dss.c b/hw/display/omap_dss.c
index 32dc0d6..21fde58 100644
--- a/hw/display/omap_dss.c
+++ b/hw/display/omap_dss.c
@@ -619,7 +619,7 @@
if (s->rfbi.control & (1 << 1)) { /* BYPASS */
/* TODO: in non-Bypass mode we probably need to just assert the
* DRQ and wait for DMA to write the pixels. */
- fprintf(stderr, "%s: Bypass mode unimplemented\n", __func__);
+ qemu_log_mask(LOG_UNIMP, "%s: Bypass mode unimplemented\n", __func__);
return;
}
diff --git a/hw/display/pxa2xx_lcd.c b/hw/display/pxa2xx_lcd.c
index 464e931..ff90104 100644
--- a/hw/display/pxa2xx_lcd.c
+++ b/hw/display/pxa2xx_lcd.c
@@ -11,7 +11,7 @@
*/
#include "qemu/osdep.h"
-#include "hw/hw.h"
+#include "qemu/log.h"
#include "hw/irq.h"
#include "migration/vmstate.h"
#include "ui/console.h"
@@ -407,7 +407,8 @@
default:
fail:
- hw_error("%s: Bad offset " REG_FMT "\n", __func__, offset);
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: Bad offset 0x%" HWADDR_PRIX "\n",
+ __func__, offset);
}
return 0;
@@ -425,9 +426,10 @@
if ((s->control[0] & LCCR0_ENB) && !(value & LCCR0_ENB))
s->status[0] |= LCSR0_QD;
- if (!(s->control[0] & LCCR0_LCDT) && (value & LCCR0_LCDT))
- printf("%s: internal frame buffer unsupported\n", __func__);
-
+ if (!(s->control[0] & LCCR0_LCDT) && (value & LCCR0_LCDT)) {
+ qemu_log_mask(LOG_UNIMP,
+ "%s: internal frame buffer unsupported\n", __func__);
+ }
if ((s->control[3] & LCCR3_API) &&
(value & LCCR0_ENB) && !(value & LCCR0_LCDT))
s->status[0] |= LCSR0_ABC;
@@ -461,9 +463,9 @@
break;
case OVL1C1:
- if (!(s->ovl1c[0] & OVLC1_EN) && (value & OVLC1_EN))
- printf("%s: Overlay 1 not supported\n", __func__);
-
+ if (!(s->ovl1c[0] & OVLC1_EN) && (value & OVLC1_EN)) {
+ qemu_log_mask(LOG_UNIMP, "%s: Overlay 1 not supported\n", __func__);
+ }
s->ovl1c[0] = value & 0x80ffffff;
s->dma_ch[1].up = (value & OVLC1_EN) || (s->control[0] & LCCR0_SDS);
break;
@@ -473,9 +475,9 @@
break;
case OVL2C1:
- if (!(s->ovl2c[0] & OVLC1_EN) && (value & OVLC1_EN))
- printf("%s: Overlay 2 not supported\n", __func__);
-
+ if (!(s->ovl2c[0] & OVLC1_EN) && (value & OVLC1_EN)) {
+ qemu_log_mask(LOG_UNIMP, "%s: Overlay 2 not supported\n", __func__);
+ }
s->ovl2c[0] = value & 0x80ffffff;
s->dma_ch[2].up = !!(value & OVLC1_EN);
s->dma_ch[3].up = !!(value & OVLC1_EN);
@@ -487,9 +489,10 @@
break;
case CCR:
- if (!(s->ccr & CCR_CEN) && (value & CCR_CEN))
- printf("%s: Hardware cursor unimplemented\n", __func__);
-
+ if (!(s->ccr & CCR_CEN) && (value & CCR_CEN)) {
+ qemu_log_mask(LOG_UNIMP,
+ "%s: Hardware cursor unimplemented\n", __func__);
+ }
s->ccr = value & 0x81ffffe7;
s->dma_ch[5].up = !!(value & CCR_CEN);
break;
@@ -562,7 +565,8 @@
default:
fail:
- hw_error("%s: Bad offset " REG_FMT "\n", __func__, offset);
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: Bad offset 0x%" HWADDR_PRIX "\n",
+ __func__, offset);
}
}
diff --git a/hw/display/ramfb-standalone.c b/hw/display/ramfb-standalone.c
index d76a9d0..b18db97 100644
--- a/hw/display/ramfb-standalone.c
+++ b/hw/display/ramfb-standalone.c
@@ -3,7 +3,6 @@
#include "qemu/module.h"
#include "hw/loader.h"
#include "hw/qdev-properties.h"
-#include "hw/isa/isa.h"
#include "hw/display/ramfb.h"
#include "ui/console.h"
@@ -13,8 +12,6 @@
SysBusDevice parent_obj;
QemuConsole *con;
RAMFBState *state;
- uint32_t xres;
- uint32_t yres;
} RAMFBStandaloneState;
static void display_update_wrapper(void *dev)
@@ -37,22 +34,15 @@
RAMFBStandaloneState *ramfb = RAMFB(dev);
ramfb->con = graphic_console_init(dev, 0, &wrapper_ops, dev);
- ramfb->state = ramfb_setup(dev, errp);
+ ramfb->state = ramfb_setup(errp);
}
-static Property ramfb_properties[] = {
- DEFINE_PROP_UINT32("xres", RAMFBStandaloneState, xres, 0),
- DEFINE_PROP_UINT32("yres", RAMFBStandaloneState, yres, 0),
- DEFINE_PROP_END_OF_LIST(),
-};
-
static void ramfb_class_initfn(ObjectClass *klass, void *data)
{
DeviceClass *dc = DEVICE_CLASS(klass);
set_bit(DEVICE_CATEGORY_DISPLAY, dc->categories);
dc->realize = ramfb_realizefn;
- device_class_set_props(dc, ramfb_properties);
dc->desc = "ram framebuffer standalone device";
dc->user_creatable = true;
}
diff --git a/hw/display/ramfb.c b/hw/display/ramfb.c
index 7ba07c8..79b9754 100644
--- a/hw/display/ramfb.c
+++ b/hw/display/ramfb.c
@@ -13,9 +13,9 @@
#include "qemu/osdep.h"
#include "qapi/error.h"
-#include "qemu/option.h"
#include "hw/loader.h"
#include "hw/display/ramfb.h"
+#include "hw/display/bochs-vbe.h" /* for limits */
#include "ui/console.h"
#include "sysemu/reset.h"
@@ -31,9 +31,7 @@
struct RAMFBState {
DisplaySurface *ds;
uint32_t width, height;
- uint32_t starting_width, starting_height;
struct RAMFBCfg cfg;
- bool locked;
};
static void ramfb_unmap_display_surface(pixman_image_t *image, void *unused)
@@ -46,25 +44,31 @@
static DisplaySurface *ramfb_create_display_surface(int width, int height,
pixman_format_code_t format,
- int linesize, uint64_t addr)
+ hwaddr stride, hwaddr addr)
{
DisplaySurface *surface;
- hwaddr size;
+ hwaddr size, mapsize, linesize;
void *data;
- if (linesize == 0) {
- linesize = width * PIXMAN_FORMAT_BPP(format) / 8;
+ if (width < 16 || width > VBE_DISPI_MAX_XRES ||
+ height < 16 || height > VBE_DISPI_MAX_YRES ||
+ format == 0 /* unknown format */)
+ return NULL;
+
+ linesize = width * PIXMAN_FORMAT_BPP(format) / 8;
+ if (stride == 0) {
+ stride = linesize;
}
- size = (hwaddr)linesize * height;
- data = cpu_physical_memory_map(addr, &size, false);
- if (size != (hwaddr)linesize * height) {
- cpu_physical_memory_unmap(data, size, 0, 0);
+ mapsize = size = stride * (height - 1) + linesize;
+ data = cpu_physical_memory_map(addr, &mapsize, false);
+ if (size != mapsize) {
+ cpu_physical_memory_unmap(data, mapsize, 0, 0);
return NULL;
}
surface = qemu_create_displaysurface_from(width, height,
- format, linesize, data);
+ format, stride, data);
pixman_image_set_destroy_function(surface->image,
ramfb_unmap_display_surface, NULL);
@@ -74,27 +78,26 @@
static void ramfb_fw_cfg_write(void *dev, off_t offset, size_t len)
{
RAMFBState *s = dev;
+ DisplaySurface *surface;
uint32_t fourcc, format, width, height;
hwaddr stride, addr;
- width = be32_to_cpu(s->cfg.width);
- height = be32_to_cpu(s->cfg.height);
- stride = be32_to_cpu(s->cfg.stride);
- fourcc = be32_to_cpu(s->cfg.fourcc);
- addr = be64_to_cpu(s->cfg.addr);
- format = qemu_drm_format_to_pixman(fourcc);
+ width = be32_to_cpu(s->cfg.width);
+ height = be32_to_cpu(s->cfg.height);
+ stride = be32_to_cpu(s->cfg.stride);
+ fourcc = be32_to_cpu(s->cfg.fourcc);
+ addr = be64_to_cpu(s->cfg.addr);
+ format = qemu_drm_format_to_pixman(fourcc);
- fprintf(stderr, "%s: %dx%d @ 0x%" PRIx64 "\n", __func__,
- width, height, addr);
- if (s->locked) {
- fprintf(stderr, "%s: resolution locked, change rejected\n", __func__);
+ surface = ramfb_create_display_surface(width, height,
+ format, stride, addr);
+ if (!surface) {
return;
}
- s->locked = true;
+
s->width = width;
s->height = height;
- s->ds = ramfb_create_display_surface(s->width, s->height,
- format, stride, addr);
+ s->ds = surface;
}
void ramfb_display_update(QemuConsole *con, RAMFBState *s)
@@ -112,16 +115,7 @@
dpy_gfx_update_full(con);
}
-static void ramfb_reset(void *opaque)
-{
- RAMFBState *s = (RAMFBState *)opaque;
- s->locked = false;
- memset(&s->cfg, 0, sizeof(s->cfg));
- s->cfg.width = s->starting_width;
- s->cfg.height = s->starting_height;
-}
-
-RAMFBState *ramfb_setup(DeviceState* dev, Error **errp)
+RAMFBState *ramfb_setup(Error **errp)
{
FWCfgState *fw_cfg = fw_cfg_find();
RAMFBState *s;
@@ -133,22 +127,9 @@
s = g_new0(RAMFBState, 1);
- const char *s_fb_width = qemu_opt_get(dev->opts, "xres");
- const char *s_fb_height = qemu_opt_get(dev->opts, "yres");
- if (s_fb_width) {
- s->cfg.width = atoi(s_fb_width);
- s->starting_width = s->cfg.width;
- }
- if (s_fb_height) {
- s->cfg.height = atoi(s_fb_height);
- s->starting_height = s->cfg.height;
- }
- s->locked = false;
-
rom_add_vga("vgabios-ramfb.bin");
fw_cfg_add_file_callback(fw_cfg, "etc/ramfb",
NULL, ramfb_fw_cfg_write, s,
&s->cfg, sizeof(s->cfg), false);
- qemu_register_reset(ramfb_reset, s);
return s;
}
diff --git a/hw/display/sm501.c b/hw/display/sm501.c
index de0ab9d..edd8d24 100644
--- a/hw/display/sm501.c
+++ b/hw/display/sm501.c
@@ -2,7 +2,7 @@
* QEMU SM501 Device
*
* Copyright (c) 2008 Shin-ichiro KAWASAKI
- * Copyright (c) 2016 BALATON Zoltan
+ * Copyright (c) 2016-2020 BALATON Zoltan
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -40,23 +40,6 @@
#include "ui/pixel_ops.h"
#include "qemu/bswap.h"
-/*
- * Status: 2010/05/07
- * - Minimum implementation for Linux console : mmio regs and CRT layer.
- * - 2D graphics acceleration partially supported : only fill rectangle.
- *
- * Status: 2016/12/04
- * - Misc fixes: endianness, hardware cursor
- * - Panel support
- *
- * TODO:
- * - Touch panel support
- * - USB support
- * - UART support
- * - More 2D graphics engine support
- * - Performance tuning
- */
-
/*#define DEBUG_SM501*/
/*#define DEBUG_BITBLT*/
@@ -699,139 +682,176 @@
static void sm501_2d_operation(SM501State *s)
{
- /* obtain operation parameters */
- int operation = (s->twoD_control >> 16) & 0x1f;
- int rtl = s->twoD_control & 0x8000000;
- int src_x = (s->twoD_source >> 16) & 0x01FFF;
- int src_y = s->twoD_source & 0xFFFF;
- int dst_x = (s->twoD_destination >> 16) & 0x01FFF;
- int dst_y = s->twoD_destination & 0xFFFF;
- int operation_width = (s->twoD_dimension >> 16) & 0x1FFF;
- int operation_height = s->twoD_dimension & 0xFFFF;
- uint32_t color = s->twoD_foreground;
- int format_flags = (s->twoD_stretch >> 20) & 0x3;
- int addressing = (s->twoD_stretch >> 16) & 0xF;
+ int cmd = (s->twoD_control >> 16) & 0x1F;
+ int rtl = s->twoD_control & BIT(27);
+ int format = (s->twoD_stretch >> 20) & 0x3;
int rop_mode = (s->twoD_control >> 15) & 0x1; /* 1 for rop2, else rop3 */
/* 1 if rop2 source is the pattern, otherwise the source is the bitmap */
int rop2_source_is_pattern = (s->twoD_control >> 14) & 0x1;
int rop = s->twoD_control & 0xFF;
- uint32_t src_base = s->twoD_source_base & 0x03FFFFFF;
+ unsigned int dst_x = (s->twoD_destination >> 16) & 0x01FFF;
+ unsigned int dst_y = s->twoD_destination & 0xFFFF;
+ unsigned int width = (s->twoD_dimension >> 16) & 0x1FFF;
+ unsigned int height = s->twoD_dimension & 0xFFFF;
uint32_t dst_base = s->twoD_destination_base & 0x03FFFFFF;
-
- /* get frame buffer info */
- uint8_t *src = s->local_mem + src_base;
- uint8_t *dst = s->local_mem + dst_base;
- int src_width = s->twoD_pitch & 0x1FFF;
- int dst_width = (s->twoD_pitch >> 16) & 0x1FFF;
+ unsigned int dst_pitch = (s->twoD_pitch >> 16) & 0x1FFF;
int crt = (s->dc_crt_control & SM501_DC_CRT_CONTROL_SEL) ? 1 : 0;
int fb_len = get_width(s, crt) * get_height(s, crt) * get_bpp(s, crt);
- if (addressing != 0x0) {
- printf("%s: only XY addressing is supported.\n", __func__);
- abort();
+ if ((s->twoD_stretch >> 16) & 0xF) {
+ qemu_log_mask(LOG_UNIMP, "sm501: only XY addressing is supported.\n");
+ return;
}
- if (rop_mode == 0) {
- if (rop != 0xcc) {
- /* Anything other than plain copies are not supported */
- qemu_log_mask(LOG_UNIMP, "sm501: rop3 mode with rop %x is not "
- "supported.\n", rop);
+ if (s->twoD_source_base & BIT(27) || s->twoD_destination_base & BIT(27)) {
+ qemu_log_mask(LOG_UNIMP, "sm501: only local memory is supported.\n");
+ return;
+ }
+
+ if (!dst_pitch) {
+ qemu_log_mask(LOG_GUEST_ERROR, "sm501: Zero dest pitch.\n");
+ return;
+ }
+
+ if (!width || !height) {
+ qemu_log_mask(LOG_GUEST_ERROR, "sm501: Zero size 2D op.\n");
+ return;
+ }
+
+ if (rtl) {
+ dst_x -= width - 1;
+ dst_y -= height - 1;
+ }
+
+ if (dst_base >= get_local_mem_size(s) || dst_base +
+ (dst_x + width + (dst_y + height) * (dst_pitch + width)) *
+ (1 << format) >= get_local_mem_size(s)) {
+ qemu_log_mask(LOG_GUEST_ERROR, "sm501: 2D op dest is outside vram.\n");
+ return;
+ }
+
+ switch (cmd) {
+ case 0: /* BitBlt */
+ {
+ static uint32_t tmp_buf[16384];
+ unsigned int src_x = (s->twoD_source >> 16) & 0x01FFF;
+ unsigned int src_y = s->twoD_source & 0xFFFF;
+ uint32_t src_base = s->twoD_source_base & 0x03FFFFFF;
+ unsigned int src_pitch = s->twoD_pitch & 0x1FFF;
+
+ if (!src_pitch) {
+ qemu_log_mask(LOG_GUEST_ERROR, "sm501: Zero src pitch.\n");
+ return;
}
- } else {
- if (rop2_source_is_pattern && rop != 0x5) {
- /* For pattern source, we support only inverse dest */
- qemu_log_mask(LOG_UNIMP, "sm501: rop2 source being the pattern and "
- "rop %x is not supported.\n", rop);
+
+ if (rtl) {
+ src_x -= width - 1;
+ src_y -= height - 1;
+ }
+
+ if (src_base >= get_local_mem_size(s) || src_base +
+ (src_x + width + (src_y + height) * (src_pitch + width)) *
+ (1 << format) >= get_local_mem_size(s)) {
+ qemu_log_mask(LOG_GUEST_ERROR,
+ "sm501: 2D op src is outside vram.\n");
+ return;
+ }
+
+ if ((rop_mode && rop == 0x5) || (!rop_mode && rop == 0x55)) {
+ /* Invert dest, is there a way to do this with pixman? */
+ unsigned int x, y, i;
+ uint8_t *d = s->local_mem + dst_base;
+
+ for (y = 0; y < height; y++) {
+ i = (dst_x + (dst_y + y) * dst_pitch) * (1 << format);
+ for (x = 0; x < width; x++, i += (1 << format)) {
+ switch (format) {
+ case 0:
+ d[i] = ~d[i];
+ break;
+ case 1:
+ *(uint16_t *)&d[i] = ~*(uint16_t *)&d[i];
+ break;
+ case 2:
+ *(uint32_t *)&d[i] = ~*(uint32_t *)&d[i];
+ break;
+ }
+ }
+ }
} else {
- if (rop != 0x5 && rop != 0xc) {
- /* Anything other than plain copies or inverse dest is not
- * supported */
- qemu_log_mask(LOG_UNIMP, "sm501: rop mode %x is not "
- "supported.\n", rop);
+ /* Do copy src for unimplemented ops, better than unpainted area */
+ if ((rop_mode && (rop != 0xc || rop2_source_is_pattern)) ||
+ (!rop_mode && rop != 0xcc)) {
+ qemu_log_mask(LOG_UNIMP,
+ "sm501: rop%d op %x%s not implemented\n",
+ (rop_mode ? 2 : 3), rop,
+ (rop2_source_is_pattern ?
+ " with pattern source" : ""));
+ }
+ /* Check for overlaps, this could be made more exact */
+ uint32_t sb, se, db, de;
+ sb = src_base + src_x + src_y * (width + src_pitch);
+ se = sb + width + height * (width + src_pitch);
+ db = dst_base + dst_x + dst_y * (width + dst_pitch);
+ de = db + width + height * (width + dst_pitch);
+ if (rtl && ((db >= sb && db <= se) || (de >= sb && de <= se))) {
+ /* regions may overlap: copy via temporary */
+ int free_buf = 0, llb = width * (1 << format);
+ int tmp_stride = DIV_ROUND_UP(llb, sizeof(uint32_t));
+ uint32_t *tmp = tmp_buf;
+
+ if (tmp_stride * sizeof(uint32_t) * height > sizeof(tmp_buf)) {
+ tmp = g_malloc(tmp_stride * sizeof(uint32_t) * height);
+ free_buf = 1;
+ }
+ pixman_blt((uint32_t *)&s->local_mem[src_base], tmp,
+ src_pitch * (1 << format) / sizeof(uint32_t),
+ tmp_stride, 8 * (1 << format), 8 * (1 << format),
+ src_x, src_y, 0, 0, width, height);
+ pixman_blt(tmp, (uint32_t *)&s->local_mem[dst_base],
+ tmp_stride,
+ dst_pitch * (1 << format) / sizeof(uint32_t),
+ 8 * (1 << format), 8 * (1 << format),
+ 0, 0, dst_x, dst_y, width, height);
+ if (free_buf) {
+ g_free(tmp);
+ }
+ } else {
+ pixman_blt((uint32_t *)&s->local_mem[src_base],
+ (uint32_t *)&s->local_mem[dst_base],
+ src_pitch * (1 << format) / sizeof(uint32_t),
+ dst_pitch * (1 << format) / sizeof(uint32_t),
+ 8 * (1 << format), 8 * (1 << format),
+ src_x, src_y, dst_x, dst_y, width, height);
}
}
- }
-
- if ((s->twoD_source_base & 0x08000000) ||
- (s->twoD_destination_base & 0x08000000)) {
- printf("%s: only local memory is supported.\n", __func__);
- abort();
- }
-
- switch (operation) {
- case 0x00: /* copy area */
-#define COPY_AREA(_bpp, _pixel_type, rtl) { \
- int y, x, index_d, index_s; \
- for (y = 0; y < operation_height; y++) { \
- for (x = 0; x < operation_width; x++) { \
- _pixel_type val; \
- \
- if (rtl) { \
- index_s = ((src_y - y) * src_width + src_x - x) * _bpp; \
- index_d = ((dst_y - y) * dst_width + dst_x - x) * _bpp; \
- } else { \
- index_s = ((src_y + y) * src_width + src_x + x) * _bpp; \
- index_d = ((dst_y + y) * dst_width + dst_x + x) * _bpp; \
- } \
- if (rop_mode == 1 && rop == 5) { \
- /* Invert dest */ \
- val = ~*(_pixel_type *)&dst[index_d]; \
- } else { \
- val = *(_pixel_type *)&src[index_s]; \
- } \
- *(_pixel_type *)&dst[index_d] = val; \
- } \
- } \
- }
- switch (format_flags) {
- case 0:
- COPY_AREA(1, uint8_t, rtl);
- break;
- case 1:
- COPY_AREA(2, uint16_t, rtl);
- break;
- case 2:
- COPY_AREA(4, uint32_t, rtl);
- break;
- }
break;
-
- case 0x01: /* fill rectangle */
-#define FILL_RECT(_bpp, _pixel_type) { \
- int y, x; \
- for (y = 0; y < operation_height; y++) { \
- for (x = 0; x < operation_width; x++) { \
- int index = ((dst_y + y) * dst_width + dst_x + x) * _bpp; \
- *(_pixel_type *)&dst[index] = (_pixel_type)color; \
- } \
- } \
}
+ case 1: /* Rectangle Fill */
+ {
+ uint32_t color = s->twoD_foreground;
- switch (format_flags) {
- case 0:
- FILL_RECT(1, uint8_t);
- break;
- case 1:
- color = cpu_to_le16(color);
- FILL_RECT(2, uint16_t);
- break;
- case 2:
+ if (format == 2) {
color = cpu_to_le32(color);
- FILL_RECT(4, uint32_t);
- break;
+ } else if (format == 1) {
+ color = cpu_to_le16(color);
}
- break;
- default:
- printf("non-implemented SM501 2D operation. %d\n", operation);
- abort();
+ pixman_fill((uint32_t *)&s->local_mem[dst_base],
+ dst_pitch * (1 << format) / sizeof(uint32_t),
+ 8 * (1 << format), dst_x, dst_y, width, height, color);
break;
}
+ default:
+ qemu_log_mask(LOG_UNIMP, "sm501: not implemented 2D operation: %d\n",
+ cmd);
+ return;
+ }
if (dst_base >= get_fb_addr(s, crt) &&
dst_base <= get_fb_addr(s, crt) + fb_len) {
- int dst_len = MIN(fb_len, ((dst_y + operation_height - 1) * dst_width +
- dst_x + operation_width) * (1 << format_flags));
+ int dst_len = MIN(fb_len, ((dst_y + height - 1) * dst_pitch +
+ dst_x + width) * (1 << format));
if (dst_len) {
memory_region_set_dirty(&s->local_mem_region, dst_base, dst_len);
}
@@ -892,9 +912,8 @@
break;
default:
- printf("sm501 system config : not implemented register read."
- " addr=%x\n", (int)addr);
- abort();
+ qemu_log_mask(LOG_UNIMP, "sm501: not implemented system config"
+ "register read. addr=%" HWADDR_PRIx "\n", addr);
}
return ret;
@@ -948,15 +967,15 @@
break;
case SM501_ENDIAN_CONTROL:
if (value & 0x00000001) {
- printf("sm501 system config : big endian mode not implemented.\n");
- abort();
+ qemu_log_mask(LOG_UNIMP, "sm501: system config big endian mode not"
+ " implemented.\n");
}
break;
default:
- printf("sm501 system config : not implemented register write."
- " addr=%x, val=%x\n", (int)addr, (uint32_t)value);
- abort();
+ qemu_log_mask(LOG_UNIMP, "sm501: not implemented system config"
+ "register write. addr=%" HWADDR_PRIx
+ ", val=%" PRIx64 "\n", addr, value);
}
}
@@ -1207,9 +1226,8 @@
break;
default:
- printf("sm501 disp ctrl : not implemented register read."
- " addr=%x\n", (int)addr);
- abort();
+ qemu_log_mask(LOG_UNIMP, "sm501: not implemented disp ctrl register "
+ "read. addr=%" HWADDR_PRIx "\n", addr);
}
return ret;
@@ -1345,9 +1363,9 @@
break;
default:
- printf("sm501 disp ctrl : not implemented register write."
- " addr=%x, val=%x\n", (int)addr, (unsigned)value);
- abort();
+ qemu_log_mask(LOG_UNIMP, "sm501: not implemented disp ctrl register "
+ "write. addr=%" HWADDR_PRIx
+ ", val=%" PRIx64 "\n", addr, value);
}
}
@@ -1433,9 +1451,8 @@
ret = 0; /* Should return interrupt status */
break;
default:
- printf("sm501 disp ctrl : not implemented register read."
- " addr=%x\n", (int)addr);
- abort();
+ qemu_log_mask(LOG_UNIMP, "sm501: not implemented disp ctrl register "
+ "read. addr=%" HWADDR_PRIx "\n", addr);
}
return ret;
@@ -1520,9 +1537,9 @@
/* ignored, writing 0 should clear interrupt status */
break;
default:
- printf("sm501 2d engine : not implemented register write."
- " addr=%x, val=%x\n", (int)addr, (unsigned)value);
- abort();
+ qemu_log_mask(LOG_UNIMP, "sm501: not implemented 2d engine register "
+ "write. addr=%" HWADDR_PRIx
+ ", val=%" PRIx64 "\n", addr, value);
}
}
@@ -1670,9 +1687,9 @@
draw_line = draw_line32_funcs[dst_depth_index];
break;
default:
- printf("sm501 update display : invalid control register value.\n");
- abort();
- break;
+ qemu_log_mask(LOG_GUEST_ERROR, "sm501: update display"
+ "invalid control register value.\n");
+ return;
}
/* set up to draw hardware cursor */
@@ -1839,7 +1856,7 @@
&s->twoD_engine_region);
/* create qemu graphic console */
- s->con = graphic_console_init(DEVICE(dev), 0, &sm501_ops, s);
+ s->con = graphic_console_init(dev, 0, &sm501_ops, s);
}
static const VMStateDescription vmstate_sm501_state = {
@@ -2011,7 +2028,7 @@
qdev_prop_set_uint8(DEVICE(smm), "endianness", DEVICE_LITTLE_ENDIAN);
object_property_add_alias(o, "chardev",
- OBJECT(smm), "chardev", &error_abort);
+ OBJECT(smm), "chardev");
}
static const TypeInfo sm501_sysbus_info = {
diff --git a/hw/display/tcx.c b/hw/display/tcx.c
index 76de16e..1fb45b1 100644
--- a/hw/display/tcx.c
+++ b/hw/display/tcx.c
@@ -868,9 +868,9 @@
sysbus_init_irq(sbd, &s->irq);
if (s->depth == 8) {
- s->con = graphic_console_init(DEVICE(dev), 0, &tcx_ops, s);
+ s->con = graphic_console_init(dev, 0, &tcx_ops, s);
} else {
- s->con = graphic_console_init(DEVICE(dev), 0, &tcx24_ops, s);
+ s->con = graphic_console_init(dev, 0, &tcx24_ops, s);
}
s->thcmisc = 0;
diff --git a/hw/display/trace-events b/hw/display/trace-events
index e6e22be..72d4c98 100644
--- a/hw/display/trace-events
+++ b/hw/display/trace-events
@@ -133,6 +133,8 @@
vga_cirrus_read_io(uint32_t addr, uint32_t val) "addr 0x%x, val 0x%x"
vga_cirrus_write_io(uint32_t addr, uint32_t val) "addr 0x%x, val 0x%x"
vga_cirrus_write_blt(uint32_t offset, uint32_t val) "offset 0x%x, val 0x%x"
+vga_cirrus_write_gr(uint8_t index, uint8_t val) "GR addr 0x%02x, val 0x%02x"
+vga_cirrus_bitblt_start(uint8_t blt_rop, uint8_t blt_mode, uint8_t blt_modeext, int blt_width, int blt_height, int blt_dstpitch, int blt_srcpitch, uint32_t blt_dstaddr, uint32_t blt_srcaddr, uint8_t gr_val) "rop=0x%02x mode=0x%02x modeext=0x%02x w=%d h=%d dpitch=%d spitch=%d daddr=0x%08"PRIx32" saddr=0x%08"PRIx32" writemask=0x%02x"
# sii9022.c
sii9022_read_reg(uint8_t addr, uint8_t val) "addr 0x%02x, val 0x%02x"
@@ -151,3 +153,11 @@
artist_fill_window(unsigned int start_x, unsigned int start_y, unsigned int width, unsigned int height, uint32_t op, uint32_t ctlpln) "start=%ux%u length=%ux%u op=0x%08x ctlpln=0x%08x"
artist_block_move(unsigned int start_x, unsigned int start_y, unsigned int dest_x, unsigned int dest_y, unsigned int width, unsigned int height) "source %ux%u -> dest %ux%u size %ux%u"
artist_draw_line(unsigned int start_x, unsigned int start_y, unsigned int end_x, unsigned int end_y) "%ux%u %ux%u"
+
+# cg3.c
+cg3_read(uint32_t addr, uint32_t val, unsigned size) "read addr:0x%06"PRIx32" val:0x%08"PRIx32" size:%u"
+cg3_write(uint32_t addr, uint32_t val, unsigned size) "write addr:0x%06"PRIx32" val:0x%08"PRIx32" size:%u"
+
+# dpcd.c
+dpcd_read(uint32_t addr, uint8_t val) "read addr:0x%"PRIx32" val:0x%02x"
+dpcd_write(uint32_t addr, uint8_t val) "write addr:0x%"PRIx32" val:0x%02x"
diff --git a/hw/display/vga-isa.c b/hw/display/vga-isa.c
index 0633ed3..3aaeeec 100644
--- a/hw/display/vga-isa.c
+++ b/hw/display/vga-isa.c
@@ -74,7 +74,7 @@
0x000a0000,
vga_io_memory, 1);
memory_region_set_coalescing(vga_io_memory);
- s->con = graphic_console_init(DEVICE(dev), 0, s->hw_ops, s);
+ s->con = graphic_console_init(dev, 0, s->hw_ops, s);
memory_region_add_subregion(isa_address_space(isadev),
VBE_DISPI_LFB_PHYSICAL_ADDRESS,
diff --git a/hw/display/vga-pci.c b/hw/display/vga-pci.c
index 6b9db86..a640fd8 100644
--- a/hw/display/vga-pci.c
+++ b/hw/display/vga-pci.c
@@ -270,7 +270,7 @@
{
/* Expose framebuffer byteorder via QOM */
object_property_add_bool(obj, "big-endian-framebuffer",
- vga_get_big_endian_fb, vga_set_big_endian_fb, NULL);
+ vga_get_big_endian_fb, vga_set_big_endian_fb);
}
static void pci_secondary_vga_realize(PCIDevice *dev, Error **errp)
@@ -321,7 +321,7 @@
{
/* Expose framebuffer byteorder via QOM */
object_property_add_bool(obj, "big-endian-framebuffer",
- vga_get_big_endian_fb, vga_set_big_endian_fb, NULL);
+ vga_get_big_endian_fb, vga_set_big_endian_fb);
}
static void pci_secondary_vga_reset(DeviceState *dev)
diff --git a/hw/display/vhost-user-gpu-pci.c b/hw/display/vhost-user-gpu-pci.c
index 7d9b1f5..23ce655 100644
--- a/hw/display/vhost-user-gpu-pci.c
+++ b/hw/display/vhost-user-gpu-pci.c
@@ -32,8 +32,7 @@
VIRTIO_GPU_PCI_BASE(obj)->vgpu = VIRTIO_GPU_BASE(&dev->vdev);
object_property_add_alias(obj, "chardev",
- OBJECT(&dev->vdev), "chardev",
- &error_abort);
+ OBJECT(&dev->vdev), "chardev");
}
static const VirtioPCIDeviceTypeInfo vhost_user_gpu_pci_info = {
diff --git a/hw/display/vhost-user-gpu.c b/hw/display/vhost-user-gpu.c
index f0c7c6f..4cdaee1 100644
--- a/hw/display/vhost-user-gpu.c
+++ b/hw/display/vhost-user-gpu.c
@@ -512,7 +512,7 @@
g->vhost = VHOST_USER_BACKEND(object_new(TYPE_VHOST_USER_BACKEND));
object_property_add_alias(obj, "chardev",
- OBJECT(g->vhost), "chardev", &error_abort);
+ OBJECT(g->vhost), "chardev");
}
static void
diff --git a/hw/display/vhost-user-vga.c b/hw/display/vhost-user-vga.c
index a719527..1690f6b 100644
--- a/hw/display/vhost-user-vga.c
+++ b/hw/display/vhost-user-vga.c
@@ -33,8 +33,7 @@
VIRTIO_VGA_BASE(dev)->vgpu = VIRTIO_GPU_BASE(&dev->vdev);
object_property_add_alias(obj, "chardev",
- OBJECT(&dev->vdev), "chardev",
- &error_abort);
+ OBJECT(&dev->vdev), "chardev");
}
static const VirtioPCIDeviceTypeInfo vhost_user_vga_info = {
diff --git a/hw/display/virtio-gpu-base.c b/hw/display/virtio-gpu-base.c
index 55e0799..c159351 100644
--- a/hw/display/virtio-gpu-base.c
+++ b/hw/display/virtio-gpu-base.c
@@ -203,7 +203,7 @@
}
static void
-virtio_gpu_base_device_unrealize(DeviceState *qdev, Error **errp)
+virtio_gpu_base_device_unrealize(DeviceState *qdev)
{
VirtIOGPUBase *g = VIRTIO_GPU_BASE(qdev);
diff --git a/hw/display/vmware_vga.c b/hw/display/vmware_vga.c
index 58ea82e..2579f6b 100644
--- a/hw/display/vmware_vga.c
+++ b/hw/display/vmware_vga.c
@@ -26,6 +26,7 @@
#include "qemu/module.h"
#include "qemu/units.h"
#include "qapi/error.h"
+#include "qemu/log.h"
#include "hw/loader.h"
#include "trace.h"
#include "ui/vnc.h"
@@ -953,7 +954,8 @@
ret = s->scratch[s->index - SVGA_SCRATCH_BASE];
break;
}
- printf("%s: Bad register %02x\n", __func__, s->index);
+ qemu_log_mask(LOG_GUEST_ERROR,
+ "%s: Bad register %02x\n", __func__, s->index);
ret = 0;
break;
}
@@ -1002,7 +1004,8 @@
s->new_width = value;
s->invalidated = 1;
} else {
- printf("%s: Bad width: %i\n", __func__, value);
+ qemu_log_mask(LOG_GUEST_ERROR,
+ "%s: Bad width: %i\n", __func__, value);
}
break;
@@ -1011,13 +1014,15 @@
s->new_height = value;
s->invalidated = 1;
} else {
- printf("%s: Bad height: %i\n", __func__, value);
+ qemu_log_mask(LOG_GUEST_ERROR,
+ "%s: Bad height: %i\n", __func__, value);
}
break;
case SVGA_REG_BITS_PER_PIXEL:
if (value != 32) {
- printf("%s: Bad bits per pixel: %i bits\n", __func__, value);
+ qemu_log_mask(LOG_GUEST_ERROR,
+ "%s: Bad bits per pixel: %i bits\n", __func__, value);
s->config = 0;
s->invalidated = 1;
}
@@ -1082,7 +1087,8 @@
s->scratch[s->index - SVGA_SCRATCH_BASE] = value;
break;
}
- printf("%s: Bad register %02x\n", __func__, s->index);
+ qemu_log_mask(LOG_GUEST_ERROR,
+ "%s: Bad register %02x\n", __func__, s->index);
}
}
@@ -1300,7 +1306,7 @@
dev->config[PCI_LATENCY_TIMER] = 0x40;
dev->config[PCI_INTERRUPT_LINE] = 0xff; /* End */
- memory_region_init_io(&s->io_bar, NULL, &vmsvga_io_ops, &s->chip,
+ memory_region_init_io(&s->io_bar, OBJECT(dev), &vmsvga_io_ops, &s->chip,
"vmsvga-io", 0x10);
memory_region_set_flush_coalesced(&s->io_bar);
pci_register_bar(dev, 0, PCI_BASE_ADDRESS_SPACE_IO, &s->io_bar);
diff --git a/hw/display/xlnx_dp.c b/hw/display/xlnx_dp.c
index 7058443..8d940cd 100644
--- a/hw/display/xlnx_dp.c
+++ b/hw/display/xlnx_dp.c
@@ -1,5 +1,5 @@
/*
- * xlnx_dp.c
+ * Xilinx Display Port
*
* Copyright (C) 2015 : GreenSocs Ltd
* http://www.greensocs.com/ , email: info@greensocs.com
@@ -24,6 +24,7 @@
#include "qemu/osdep.h"
#include "qapi/error.h"
+#include "qemu/error-report.h"
#include "qemu/log.h"
#include "qemu/module.h"
#include "hw/display/xlnx_dp.h"
@@ -465,7 +466,7 @@
uint8_t ret;
if (fifo8_is_empty(&s->tx_fifo)) {
- DPRINTF("tx_fifo underflow..\n");
+ error_report("%s: TX_FIFO underflow", __func__);
abort();
}
ret = fifo8_pop(&s->tx_fifo);
@@ -525,6 +526,7 @@
qemu_log_mask(LOG_UNIMP, "xlnx_dp: Write i2c status not implemented\n");
break;
default:
+ error_report("%s: invalid command: %u", __func__, cmd);
abort();
}
@@ -631,8 +633,8 @@
s->g_plane.format = PIXMAN_b8g8r8;
break;
default:
- DPRINTF("error: unsupported graphic format %u.\n",
- s->avbufm_registers[AV_BUF_FORMAT] & DP_GRAPHIC_MASK);
+ error_report("%s: unsupported graphic format %u", __func__,
+ s->avbufm_registers[AV_BUF_FORMAT] & DP_GRAPHIC_MASK);
abort();
}
@@ -647,8 +649,8 @@
s->v_plane.format = PIXMAN_x8b8g8r8;
break;
default:
- DPRINTF("error: unsupported video format %u.\n",
- s->avbufm_registers[AV_BUF_FORMAT] & DP_NL_VID_FMT_MASK);
+ error_report("%s: unsupported video format %u", __func__,
+ s->avbufm_registers[AV_BUF_FORMAT] & DP_NL_VID_FMT_MASK);
abort();
}
@@ -1237,8 +1239,7 @@
object_property_add_link(obj, "dpdma", TYPE_XLNX_DPDMA,
(Object **) &s->dpdma,
xlnx_dp_set_dpdma,
- OBJ_PROP_LINK_STRONG,
- &error_abort);
+ OBJ_PROP_LINK_STRONG);
/*
* Initialize AUX Bus.
@@ -1249,11 +1250,11 @@
* Initialize DPCD and EDID..
*/
s->dpcd = DPCD(aux_create_slave(s->aux_bus, "dpcd"));
- object_property_add_child(OBJECT(s), "dpcd", OBJECT(s->dpcd), NULL);
+ object_property_add_child(OBJECT(s), "dpcd", OBJECT(s->dpcd));
s->edid = I2CDDC(qdev_create(BUS(aux_get_i2c_bus(s->aux_bus)), "i2c-ddc"));
i2c_set_slave_address(I2C_SLAVE(s->edid), 0x50);
- object_property_add_child(OBJECT(s), "edid", OBJECT(s->edid), NULL);
+ object_property_add_child(OBJECT(s), "edid", OBJECT(s->edid));
fifo8_create(&s->rx_fifo, 16);
fifo8_create(&s->tx_fifo, 16);
diff --git a/hw/dma/pxa2xx_dma.c b/hw/dma/pxa2xx_dma.c
index 88ed4b6..8a2eeb3 100644
--- a/hw/dma/pxa2xx_dma.c
+++ b/hw/dma/pxa2xx_dma.c
@@ -9,6 +9,7 @@
*/
#include "qemu/osdep.h"
+#include "qemu/log.h"
#include "hw/hw.h"
#include "hw/irq.h"
#include "hw/qdev-properties.h"
@@ -268,7 +269,8 @@
unsigned int channel;
if (size != 4) {
- hw_error("%s: Bad access width\n", __func__);
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: Bad access width %u\n",
+ __func__, size);
return 5;
}
@@ -315,8 +317,8 @@
return s->chan[channel].cmd;
}
}
-
- hw_error("%s: Bad offset 0x" TARGET_FMT_plx "\n", __func__, offset);
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: Bad offset 0x%" HWADDR_PRIX "\n",
+ __func__, offset);
return 7;
}
@@ -327,7 +329,8 @@
unsigned int channel;
if (size != 4) {
- hw_error("%s: Bad access width\n", __func__);
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: Bad access width %u\n",
+ __func__, size);
return;
}
@@ -420,7 +423,8 @@
break;
}
fail:
- hw_error("%s: Bad offset " TARGET_FMT_plx "\n", __func__, offset);
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: Bad offset 0x%" HWADDR_PRIX "\n",
+ __func__, offset);
}
}
diff --git a/hw/dma/rc4030.c b/hw/dma/rc4030.c
index 7434d27..eefbabd 100644
--- a/hw/dma/rc4030.c
+++ b/hw/dma/rc4030.c
@@ -690,7 +690,7 @@
address_space_init(&s->dma_as, MEMORY_REGION(&s->dma_mr), "rc4030-dma");
}
-static void rc4030_unrealize(DeviceState *dev, Error **errp)
+static void rc4030_unrealize(DeviceState *dev)
{
rc4030State *s = RC4030(dev);
diff --git a/hw/dma/sparc32_dma.c b/hw/dma/sparc32_dma.c
index 3e4da0c..84b9c5d 100644
--- a/hw/dma/sparc32_dma.c
+++ b/hw/dma/sparc32_dma.c
@@ -264,7 +264,7 @@
object_property_add_link(OBJECT(dev), "iommu", TYPE_SUN4M_IOMMU,
(Object **) &s->iommu,
qdev_prop_allow_set_link_before_realize,
- 0, NULL);
+ 0);
qdev_init_gpio_in(dev, dma_set_irq, 1);
qdev_init_gpio_out(dev, s->gpio, 2);
@@ -302,7 +302,7 @@
ESPState *esp;
d = qdev_create(NULL, TYPE_ESP);
- object_property_add_child(OBJECT(dev), "esp", OBJECT(d), errp);
+ object_property_add_child(OBJECT(dev), "esp", OBJECT(d));
sysbus = ESP_STATE(d);
esp = &sysbus->esp;
esp->dma_memory_read = espdma_memory_read;
@@ -344,7 +344,7 @@
qemu_check_nic_model(nd, TYPE_LANCE);
d = qdev_create(NULL, TYPE_LANCE);
- object_property_add_child(OBJECT(dev), "lance", OBJECT(d), errp);
+ object_property_add_child(OBJECT(dev), "lance", OBJECT(d));
qdev_set_nic_properties(d, nd);
object_property_set_link(OBJECT(d), OBJECT(dev), "dma", errp);
qdev_init_nofail(d);
@@ -380,7 +380,7 @@
espdma = qdev_create(NULL, TYPE_SPARC32_ESPDMA_DEVICE);
object_property_set_link(OBJECT(espdma), iommu, "iommu", errp);
- object_property_add_child(OBJECT(s), "espdma", OBJECT(espdma), errp);
+ object_property_add_child(OBJECT(s), "espdma", OBJECT(espdma));
qdev_init_nofail(espdma);
esp = DEVICE(object_resolve_path_component(OBJECT(espdma), "esp"));
@@ -395,7 +395,7 @@
ledma = qdev_create(NULL, TYPE_SPARC32_LEDMA_DEVICE);
object_property_set_link(OBJECT(ledma), iommu, "iommu", errp);
- object_property_add_child(OBJECT(s), "ledma", OBJECT(ledma), errp);
+ object_property_add_child(OBJECT(s), "ledma", OBJECT(ledma));
qdev_init_nofail(ledma);
lance = DEVICE(object_resolve_path_component(OBJECT(ledma), "lance"));
diff --git a/hw/dma/xilinx_axidma.c b/hw/dma/xilinx_axidma.c
index 018f369..460102b 100644
--- a/hw/dma/xilinx_axidma.c
+++ b/hw/dma/xilinx_axidma.c
@@ -33,6 +33,7 @@
#include "qemu/log.h"
#include "qemu/module.h"
+#include "sysemu/dma.h"
#include "hw/stream.h"
#define D(x)
@@ -103,13 +104,14 @@
};
struct Stream {
+ struct XilinxAXIDMA *dma;
ptimer_state *ptimer;
qemu_irq irq;
int nr;
+ bool sof;
struct SDesc desc;
- int pos;
unsigned int complete_cnt;
uint32_t regs[R_MAX];
uint8_t app[20];
@@ -125,6 +127,9 @@
struct XilinxAXIDMA {
SysBusDevice busdev;
MemoryRegion iomem;
+ MemoryRegion *dma_mr;
+ AddressSpace as;
+
uint32_t freqhz;
StreamSlave *tx_data_dev;
StreamSlave *tx_control_dev;
@@ -170,6 +175,7 @@
{
s->regs[R_DMASR] = DMASR_HALTED; /* starts up halted. */
s->regs[R_DMACR] = 1 << 16; /* Starts with one in compl threshold. */
+ s->sof = true;
}
/* Map an offset addr into a channel index. */
@@ -186,7 +192,7 @@
{
struct SDesc *d = &s->desc;
- cpu_physical_memory_read(addr, d, sizeof *d);
+ address_space_read(&s->dma->as, addr, MEMTXATTRS_UNSPECIFIED, d, sizeof *d);
/* Convert from LE into host endianness. */
d->buffer_address = le64_to_cpu(d->buffer_address);
@@ -204,7 +210,8 @@
d->nxtdesc = cpu_to_le64(d->nxtdesc);
d->control = cpu_to_le32(d->control);
d->status = cpu_to_le32(d->status);
- cpu_physical_memory_write(addr, d, sizeof *d);
+ address_space_write(&s->dma->as, addr, MEMTXATTRS_UNSPECIFIED,
+ d, sizeof *d);
}
static void stream_update_irq(struct Stream *s)
@@ -261,7 +268,9 @@
StreamSlave *tx_control_dev)
{
uint32_t prev_d;
- unsigned int txlen;
+ uint32_t txlen;
+ uint64_t addr;
+ bool eop;
if (!stream_running(s) || stream_idle(s)) {
return;
@@ -276,23 +285,26 @@
}
if (stream_desc_sof(&s->desc)) {
- s->pos = 0;
- stream_push(tx_control_dev, s->desc.app, sizeof(s->desc.app));
+ stream_push(tx_control_dev, s->desc.app, sizeof(s->desc.app), true);
}
txlen = s->desc.control & SDESC_CTRL_LEN_MASK;
- if ((txlen + s->pos) > sizeof s->txbuf) {
- hw_error("%s: too small internal txbuf! %d\n", __func__,
- txlen + s->pos);
+
+ eop = stream_desc_eof(&s->desc);
+ addr = s->desc.buffer_address;
+ while (txlen) {
+ unsigned int len;
+
+ len = txlen > sizeof s->txbuf ? sizeof s->txbuf : txlen;
+ address_space_read(&s->dma->as, addr,
+ MEMTXATTRS_UNSPECIFIED,
+ s->txbuf, len);
+ stream_push(tx_data_dev, s->txbuf, len, eop && len == txlen);
+ txlen -= len;
+ addr += len;
}
- cpu_physical_memory_read(s->desc.buffer_address,
- s->txbuf + s->pos, txlen);
- s->pos += txlen;
-
- if (stream_desc_eof(&s->desc)) {
- stream_push(tx_data_dev, s->txbuf, s->pos);
- s->pos = 0;
+ if (eop) {
stream_complete(s);
}
@@ -311,12 +323,11 @@
}
static size_t stream_process_s2mem(struct Stream *s, unsigned char *buf,
- size_t len)
+ size_t len, bool eop)
{
uint32_t prev_d;
unsigned int rxlen;
size_t pos = 0;
- int sof = 1;
if (!stream_running(s) || stream_idle(s)) {
return 0;
@@ -336,21 +347,22 @@
rxlen = len;
}
- cpu_physical_memory_write(s->desc.buffer_address, buf + pos, rxlen);
+ address_space_write(&s->dma->as, s->desc.buffer_address,
+ MEMTXATTRS_UNSPECIFIED, buf + pos, rxlen);
len -= rxlen;
pos += rxlen;
/* Update the descriptor. */
- if (!len) {
+ if (eop) {
stream_complete(s);
memcpy(s->desc.app, s->app, sizeof(s->desc.app));
s->desc.status |= SDESC_STATUS_EOF;
}
- s->desc.status |= sof << SDESC_STATUS_SOF_BIT;
+ s->desc.status |= s->sof << SDESC_STATUS_SOF_BIT;
s->desc.status |= SDESC_STATUS_COMPLETE;
stream_desc_store(s, s->regs[R_CURDESC]);
- sof = 0;
+ s->sof = eop;
/* Advance. */
prev_d = s->regs[R_CURDESC];
@@ -376,7 +388,7 @@
static size_t
xilinx_axidma_control_stream_push(StreamSlave *obj, unsigned char *buf,
- size_t len)
+ size_t len, bool eop)
{
XilinxAXIDMAStreamSlave *cs = XILINX_AXI_DMA_CONTROL_STREAM(obj);
struct Stream *s = &cs->dma->streams[1];
@@ -408,13 +420,14 @@
}
static size_t
-xilinx_axidma_data_stream_push(StreamSlave *obj, unsigned char *buf, size_t len)
+xilinx_axidma_data_stream_push(StreamSlave *obj, unsigned char *buf, size_t len,
+ bool eop)
{
XilinxAXIDMAStreamSlave *ds = XILINX_AXI_DMA_DATA_STREAM(obj);
struct Stream *s = &ds->dma->streams[1];
size_t ret;
- ret = stream_process_s2mem(s, buf, len);
+ ret = stream_process_s2mem(s, buf, len, eop);
stream_update_irq(s);
return ret;
}
@@ -525,37 +538,35 @@
XilinxAXIDMAStreamSlave *cs = XILINX_AXI_DMA_CONTROL_STREAM(
&s->rx_control_dev);
Error *local_err = NULL;
+ int i;
object_property_add_link(OBJECT(ds), "dma", TYPE_XILINX_AXI_DMA,
(Object **)&ds->dma,
object_property_allow_set_link,
- OBJ_PROP_LINK_STRONG,
- &local_err);
+ OBJ_PROP_LINK_STRONG);
object_property_add_link(OBJECT(cs), "dma", TYPE_XILINX_AXI_DMA,
(Object **)&cs->dma,
object_property_allow_set_link,
- OBJ_PROP_LINK_STRONG,
- &local_err);
- if (local_err) {
- goto xilinx_axidma_realize_fail;
- }
+ OBJ_PROP_LINK_STRONG);
object_property_set_link(OBJECT(ds), OBJECT(s), "dma", &local_err);
object_property_set_link(OBJECT(cs), OBJECT(s), "dma", &local_err);
if (local_err) {
goto xilinx_axidma_realize_fail;
}
- int i;
-
for (i = 0; i < 2; i++) {
struct Stream *st = &s->streams[i];
+ st->dma = s;
st->nr = i;
st->ptimer = ptimer_init(timer_hit, st, PTIMER_POLICY_DEFAULT);
ptimer_transaction_begin(st->ptimer);
ptimer_set_freq(st->ptimer, s->freqhz);
ptimer_transaction_commit(st->ptimer);
}
+
+ address_space_init(&s->as,
+ s->dma_mr ? s->dma_mr : get_system_memory(), "dma");
return;
xilinx_axidma_realize_fail:
@@ -575,6 +586,10 @@
&s->rx_control_dev, sizeof(s->rx_control_dev),
TYPE_XILINX_AXI_DMA_CONTROL_STREAM, &error_abort,
NULL);
+ object_property_add_link(obj, "dma", TYPE_MEMORY_REGION,
+ (Object **)&s->dma_mr,
+ qdev_prop_allow_set_link_before_realize,
+ OBJ_PROP_LINK_STRONG);
sysbus_init_irq(sbd, &s->streams[0].irq);
sysbus_init_irq(sbd, &s->streams[1].irq);
diff --git a/hw/dma/xlnx-zdma.c b/hw/dma/xlnx-zdma.c
index 4121a1b..fa38a55 100644
--- a/hw/dma/xlnx-zdma.c
+++ b/hw/dma/xlnx-zdma.c
@@ -719,7 +719,7 @@
RegisterInfo *r = &s->regs_info[addr / 4];
if (!r->data) {
- gchar *path = object_get_canonical_path(OBJECT(s));
+ char *path = object_get_canonical_path(OBJECT(s));
qemu_log("%s: Decode error: read from %" HWADDR_PRIx "\n",
path,
addr);
@@ -738,7 +738,7 @@
RegisterInfo *r = &s->regs_info[addr / 4];
if (!r->data) {
- gchar *path = object_get_canonical_path(OBJECT(s));
+ char *path = object_get_canonical_path(OBJECT(s));
qemu_log("%s: Decode error: write to %" HWADDR_PRIx "=%" PRIx64 "\n",
path,
addr, value);
@@ -799,8 +799,7 @@
object_property_add_link(obj, "dma", TYPE_MEMORY_REGION,
(Object **)&s->dma_mr,
qdev_prop_allow_set_link_before_realize,
- OBJ_PROP_LINK_STRONG,
- &error_abort);
+ OBJ_PROP_LINK_STRONG);
}
static const VMStateDescription vmstate_zdma = {
diff --git a/hw/gpio/aspeed_gpio.c b/hw/gpio/aspeed_gpio.c
index 4c75b5c..dfa9db3 100644
--- a/hw/gpio/aspeed_gpio.c
+++ b/hw/gpio/aspeed_gpio.c
@@ -873,7 +873,7 @@
name = g_strdup_printf("gpio%s%d", props->group_label[group_idx],
pin_idx % GPIOS_PER_GROUP);
object_property_add(obj, name, "bool", aspeed_gpio_get_pin,
- aspeed_gpio_set_pin, NULL, NULL, NULL);
+ aspeed_gpio_set_pin, NULL, NULL);
g_free(name);
}
}
diff --git a/hw/gpio/pl061.c b/hw/gpio/pl061.c
index 2a82826..6d3c36b 100644
--- a/hw/gpio/pl061.c
+++ b/hw/gpio/pl061.c
@@ -36,6 +36,8 @@
#define TYPE_PL061 "pl061"
#define PL061(obj) OBJECT_CHECK(PL061State, (obj), TYPE_PL061)
+#define N_GPIOS 8
+
typedef struct PL061State {
SysBusDevice parent_obj;
@@ -62,7 +64,7 @@
uint32_t cr;
uint32_t amsel;
qemu_irq irq;
- qemu_irq out[8];
+ qemu_irq out[N_GPIOS];
const unsigned char *id;
uint32_t rsvd_start; /* reserved area: [rsvd_start, 0xfcc] */
} PL061State;
@@ -112,7 +114,7 @@
changed = s->old_out_data ^ out;
if (changed) {
s->old_out_data = out;
- for (i = 0; i < 8; i++) {
+ for (i = 0; i < N_GPIOS; i++) {
mask = 1 << i;
if (changed & mask) {
DPRINTF("Set output %d = %d\n", i, (out & mask) != 0);
@@ -125,7 +127,7 @@
changed = (s->old_in_data ^ s->data) & ~s->dir;
if (changed) {
s->old_in_data = s->data;
- for (i = 0; i < 8; i++) {
+ for (i = 0; i < N_GPIOS; i++) {
mask = 1 << i;
if (changed & mask) {
DPRINTF("Changed input %d = %d\n", i, (s->data & mask) != 0);
@@ -364,8 +366,8 @@
memory_region_init_io(&s->iomem, obj, &pl061_ops, s, "pl061", 0x1000);
sysbus_init_mmio(sbd, &s->iomem);
sysbus_init_irq(sbd, &s->irq);
- qdev_init_gpio_in(dev, pl061_set_irq, 8);
- qdev_init_gpio_out(dev, s->out, 8);
+ qdev_init_gpio_in(dev, pl061_set_irq, N_GPIOS);
+ qdev_init_gpio_out(dev, s->out, N_GPIOS);
}
static void pl061_class_init(ObjectClass *klass, void *data)
diff --git a/hw/hyperv/hyperv.c b/hw/hyperv/hyperv.c
index 4ddafe1..4b11f7a 100644
--- a/hw/hyperv/hyperv.c
+++ b/hw/hyperv/hyperv.c
@@ -131,7 +131,7 @@
obj = object_new(TYPE_SYNIC);
synic = SYNIC(obj);
synic->cs = cs;
- object_property_add_child(OBJECT(cs), "synic", obj, &error_abort);
+ object_property_add_child(OBJECT(cs), "synic", obj);
object_unref(obj);
object_property_set_bool(obj, true, "realized", &error_abort);
}
diff --git a/hw/i2c/imx_i2c.c b/hw/i2c/imx_i2c.c
index 30b9aea..2e02e1c 100644
--- a/hw/i2c/imx_i2c.c
+++ b/hw/i2c/imx_i2c.c
@@ -305,7 +305,7 @@
IMX_I2C_MEM_SIZE);
sysbus_init_mmio(SYS_BUS_DEVICE(dev), &s->iomem);
sysbus_init_irq(SYS_BUS_DEVICE(dev), &s->irq);
- s->bus = i2c_init_bus(DEVICE(dev), NULL);
+ s->bus = i2c_init_bus(dev, NULL);
}
static void imx_i2c_class_init(ObjectClass *klass, void *data)
diff --git a/hw/i2c/mpc_i2c.c b/hw/i2c/mpc_i2c.c
index 0aa1be3..9a724f3 100644
--- a/hw/i2c/mpc_i2c.c
+++ b/hw/i2c/mpc_i2c.c
@@ -332,7 +332,7 @@
memory_region_init_io(&i2c->iomem, OBJECT(i2c), &i2c_ops, i2c,
"mpc-i2c", 0x14);
sysbus_init_mmio(SYS_BUS_DEVICE(dev), &i2c->iomem);
- i2c->bus = i2c_init_bus(DEVICE(dev), "i2c");
+ i2c->bus = i2c_init_bus(dev, "i2c");
}
static void mpc_i2c_class_init(ObjectClass *klass, void *data)
diff --git a/hw/i386/kvm/apic.c b/hw/i386/kvm/apic.c
index 91fb622..4eb2d77 100644
--- a/hw/i386/kvm/apic.c
+++ b/hw/i386/kvm/apic.c
@@ -230,7 +230,7 @@
}
}
-static void kvm_apic_unrealize(DeviceState *dev, Error **errp)
+static void kvm_apic_unrealize(DeviceState *dev)
{
}
diff --git a/hw/i386/microvm.c b/hw/i386/microvm.c
index 38d8e51..937db10 100644
--- a/hw/i386/microvm.c
+++ b/hw/i386/microvm.c
@@ -510,47 +510,42 @@
object_class_property_add(oc, MICROVM_MACHINE_PIC, "OnOffAuto",
microvm_machine_get_pic,
microvm_machine_set_pic,
- NULL, NULL, &error_abort);
+ NULL, NULL);
object_class_property_set_description(oc, MICROVM_MACHINE_PIC,
- "Enable i8259 PIC", &error_abort);
+ "Enable i8259 PIC");
object_class_property_add(oc, MICROVM_MACHINE_PIT, "OnOffAuto",
microvm_machine_get_pit,
microvm_machine_set_pit,
- NULL, NULL, &error_abort);
+ NULL, NULL);
object_class_property_set_description(oc, MICROVM_MACHINE_PIT,
- "Enable i8254 PIT", &error_abort);
+ "Enable i8254 PIT");
object_class_property_add(oc, MICROVM_MACHINE_RTC, "OnOffAuto",
microvm_machine_get_rtc,
microvm_machine_set_rtc,
- NULL, NULL, &error_abort);
+ NULL, NULL);
object_class_property_set_description(oc, MICROVM_MACHINE_RTC,
- "Enable MC146818 RTC", &error_abort);
+ "Enable MC146818 RTC");
object_class_property_add_bool(oc, MICROVM_MACHINE_ISA_SERIAL,
microvm_machine_get_isa_serial,
- microvm_machine_set_isa_serial,
- &error_abort);
+ microvm_machine_set_isa_serial);
object_class_property_set_description(oc, MICROVM_MACHINE_ISA_SERIAL,
- "Set off to disable the instantiation an ISA serial port",
- &error_abort);
+ "Set off to disable the instantiation an ISA serial port");
object_class_property_add_bool(oc, MICROVM_MACHINE_OPTION_ROMS,
microvm_machine_get_option_roms,
- microvm_machine_set_option_roms,
- &error_abort);
+ microvm_machine_set_option_roms);
object_class_property_set_description(oc, MICROVM_MACHINE_OPTION_ROMS,
- "Set off to disable loading option ROMs", &error_abort);
+ "Set off to disable loading option ROMs");
object_class_property_add_bool(oc, MICROVM_MACHINE_AUTO_KERNEL_CMDLINE,
microvm_machine_get_auto_kernel_cmdline,
- microvm_machine_set_auto_kernel_cmdline,
- &error_abort);
+ microvm_machine_set_auto_kernel_cmdline);
object_class_property_set_description(oc,
MICROVM_MACHINE_AUTO_KERNEL_CMDLINE,
- "Set off to disable adding virtio-mmio devices to the kernel cmdline",
- &error_abort);
+ "Set off to disable adding virtio-mmio devices to the kernel cmdline");
}
static const TypeInfo microvm_machine_info = {
diff --git a/hw/i386/pc.c b/hw/i386/pc.c
index 97e345f..2128f3d 100644
--- a/hw/i386/pc.c
+++ b/hw/i386/pc.c
@@ -662,7 +662,7 @@
TYPE_ISA_DEVICE,
(Object **)&x86ms->rtc,
object_property_allow_set_link,
- OBJ_PROP_LINK_STRONG, &error_abort);
+ OBJ_PROP_LINK_STRONG);
object_property_set_link(OBJECT(pcms), OBJECT(s),
"rtc_state", &error_abort);
@@ -1385,7 +1385,7 @@
}
pc_dimm_unplug(PC_DIMM(dev), MACHINE(pcms));
- object_property_set_bool(OBJECT(dev), false, "realized", NULL);
+ object_property_set_bool(OBJECT(dev), false, "realized", &error_abort);
out:
error_propagate(errp, local_err);
}
@@ -1493,7 +1493,7 @@
found_cpu = pc_find_cpu_slot(MACHINE(pcms), cpu->apic_id, NULL);
found_cpu->cpu = NULL;
- object_property_set_bool(OBJECT(dev), false, "realized", NULL);
+ object_property_set_bool(OBJECT(dev), false, "realized", &error_abort);
/* decrement the number of CPUs */
x86ms->boot_cpus--;
@@ -1965,22 +1965,22 @@
object_class_property_add(oc, PC_MACHINE_DEVMEM_REGION_SIZE, "int",
pc_machine_get_device_memory_region_size, NULL,
- NULL, NULL, &error_abort);
+ NULL, NULL);
object_class_property_add(oc, PC_MACHINE_VMPORT, "OnOffAuto",
pc_machine_get_vmport, pc_machine_set_vmport,
- NULL, NULL, &error_abort);
+ NULL, NULL);
object_class_property_set_description(oc, PC_MACHINE_VMPORT,
- "Enable vmport (pc & q35)", &error_abort);
+ "Enable vmport (pc & q35)");
object_class_property_add_bool(oc, PC_MACHINE_SMBUS,
- pc_machine_get_smbus, pc_machine_set_smbus, &error_abort);
+ pc_machine_get_smbus, pc_machine_set_smbus);
object_class_property_add_bool(oc, PC_MACHINE_SATA,
- pc_machine_get_sata, pc_machine_set_sata, &error_abort);
+ pc_machine_get_sata, pc_machine_set_sata);
object_class_property_add_bool(oc, PC_MACHINE_PIT,
- pc_machine_get_pit, pc_machine_set_pit, &error_abort);
+ pc_machine_get_pit, pc_machine_set_pit);
}
static const TypeInfo pc_machine_info = {
diff --git a/hw/i386/pc_piix.c b/hw/i386/pc_piix.c
index 3862e51..f66e1d7 100644
--- a/hw/i386/pc_piix.c
+++ b/hw/i386/pc_piix.c
@@ -291,7 +291,7 @@
TYPE_HOTPLUG_HANDLER,
(Object **)&pcms->acpi_dev,
object_property_allow_set_link,
- OBJ_PROP_LINK_STRONG, &error_abort);
+ OBJ_PROP_LINK_STRONG);
object_property_set_link(OBJECT(machine), OBJECT(piix4_pm),
PC_MACHINE_ACPI_DEVICE_PROP, &error_abort);
}
diff --git a/hw/i386/pc_q35.c b/hw/i386/pc_q35.c
index 3349e38..4ba8ac8 100644
--- a/hw/i386/pc_q35.c
+++ b/hw/i386/pc_q35.c
@@ -214,7 +214,7 @@
/* create pci host bus */
q35_host = Q35_HOST_DEVICE(qdev_create(NULL, TYPE_Q35_HOST_DEVICE));
- object_property_add_child(qdev_get_machine(), "q35", OBJECT(q35_host), NULL);
+ object_property_add_child(qdev_get_machine(), "q35", OBJECT(q35_host));
object_property_set_link(OBJECT(q35_host), OBJECT(ram_memory),
MCH_HOST_PROP_RAM_MEM, NULL);
object_property_set_link(OBJECT(q35_host), OBJECT(pci_memory),
@@ -240,7 +240,7 @@
TYPE_HOTPLUG_HANDLER,
(Object **)&pcms->acpi_dev,
object_property_allow_set_link,
- OBJ_PROP_LINK_STRONG, &error_abort);
+ OBJ_PROP_LINK_STRONG);
object_property_set_link(OBJECT(machine), OBJECT(lpc),
PC_MACHINE_ACPI_DEVICE_PROP, &error_abort);
diff --git a/hw/i386/pc_sysfw.c b/hw/i386/pc_sysfw.c
index f5f3f46..b8d8ef5 100644
--- a/hw/i386/pc_sysfw.c
+++ b/hw/i386/pc_sysfw.c
@@ -90,10 +90,9 @@
qdev_prop_set_uint64(dev, "sector-length", FLASH_SECTOR_SIZE);
qdev_prop_set_uint8(dev, "width", 1);
qdev_prop_set_string(dev, "name", name);
- object_property_add_child(OBJECT(pcms), name, OBJECT(dev),
- &error_abort);
+ object_property_add_child(OBJECT(pcms), name, OBJECT(dev));
object_property_add_alias(OBJECT(pcms), alias_prop_name,
- OBJECT(dev), "drive", &error_abort);
+ OBJECT(dev), "drive");
return PFLASH_CFI01(dev);
}
@@ -121,7 +120,7 @@
dev_obj = OBJECT(pcms->flash[i]);
if (!object_property_get_bool(dev_obj, "realized", &error_abort)) {
prop_name = g_strdup_printf("pflash%d", i);
- object_property_del(OBJECT(pcms), prop_name, &error_abort);
+ object_property_del(OBJECT(pcms), prop_name);
g_free(prop_name);
object_unparent(dev_obj);
pcms->flash[i] = NULL;
@@ -168,7 +167,7 @@
blk_name(blk), strerror(-size));
exit(1);
}
- if (size == 0 || size % FLASH_SECTOR_SIZE != 0) {
+ if (size == 0 || !QEMU_IS_ALIGNED(size, FLASH_SECTOR_SIZE)) {
error_report("system firmware block device %s has invalid size "
"%" PRId64,
blk_name(blk), size);
diff --git a/hw/i386/x86.c b/hw/i386/x86.c
index b827700..7a3bc7a 100644
--- a/hw/i386/x86.c
+++ b/hw/i386/x86.c
@@ -350,7 +350,7 @@
dev = qdev_create(NULL, TYPE_IOAPIC);
}
object_property_add_child(object_resolve_path(parent_name, NULL),
- "ioapic", OBJECT(dev), NULL);
+ "ioapic", OBJECT(dev));
qdev_init_nofail(dev);
d = SYS_BUS_DEVICE(dev);
sysbus_mmio_map(d, 0, IO_APIC_DEFAULT_ADDRESS);
@@ -982,21 +982,21 @@
object_class_property_add(oc, X86_MACHINE_MAX_RAM_BELOW_4G, "size",
x86_machine_get_max_ram_below_4g, x86_machine_set_max_ram_below_4g,
- NULL, NULL, &error_abort);
+ NULL, NULL);
object_class_property_set_description(oc, X86_MACHINE_MAX_RAM_BELOW_4G,
- "Maximum ram below the 4G boundary (32bit boundary)", &error_abort);
+ "Maximum ram below the 4G boundary (32bit boundary)");
object_class_property_add(oc, X86_MACHINE_SMM, "OnOffAuto",
x86_machine_get_smm, x86_machine_set_smm,
- NULL, NULL, &error_abort);
+ NULL, NULL);
object_class_property_set_description(oc, X86_MACHINE_SMM,
- "Enable SMM", &error_abort);
+ "Enable SMM");
object_class_property_add(oc, X86_MACHINE_ACPI, "OnOffAuto",
x86_machine_get_acpi, x86_machine_set_acpi,
- NULL, NULL, &error_abort);
+ NULL, NULL);
object_class_property_set_description(oc, X86_MACHINE_ACPI,
- "Enable ACPI", &error_abort);
+ "Enable ACPI");
}
static const TypeInfo x86_machine_info = {
diff --git a/hw/ide/ahci-allwinner.c b/hw/ide/ahci-allwinner.c
index bb8393d..8536b9e 100644
--- a/hw/ide/ahci-allwinner.c
+++ b/hw/ide/ahci-allwinner.c
@@ -90,7 +90,7 @@
SysbusAHCIState *s = SYSBUS_AHCI(obj);
AllwinnerAHCIState *a = ALLWINNER_AHCI(obj);
- memory_region_init_io(&a->mmio, OBJECT(obj), &allwinner_ahci_mem_ops, a,
+ memory_region_init_io(&a->mmio, obj, &allwinner_ahci_mem_ops, a,
"allwinner-ahci", ALLWINNER_AHCI_MMIO_SIZE);
memory_region_add_subregion(&s->ahci.mem, ALLWINNER_AHCI_MMIO_OFF,
&a->mmio);
diff --git a/hw/ide/ahci.c b/hw/ide/ahci.c
index 13d91e1..fc82cbd 100644
--- a/hw/ide/ahci.c
+++ b/hw/ide/ahci.c
@@ -1509,6 +1509,7 @@
static void ahci_irq_set(void *opaque, int n, int level)
{
+ qemu_log_mask(LOG_UNIMP, "ahci: IRQ#%d level:%d\n", n, level);
}
static const IDEDMAOps ahci_dma_ops = {
diff --git a/hw/ide/macio.c b/hw/ide/macio.c
index a9f25e5..30af0e9 100644
--- a/hw/ide/macio.c
+++ b/hw/ide/macio.c
@@ -459,7 +459,7 @@
object_property_add_link(obj, "dbdma", TYPE_MAC_DBDMA,
(Object **) &s->dbdma,
- qdev_prop_allow_set_link_before_realize, 0, NULL);
+ qdev_prop_allow_set_link_before_realize, 0);
}
static Property macio_ide_properties[] = {
diff --git a/hw/ide/piix.c b/hw/ide/piix.c
index 3b2de4c..b402a93 100644
--- a/hw/ide/piix.c
+++ b/hw/ide/piix.c
@@ -193,7 +193,7 @@
blk_unref(blk);
}
}
- qdev_reset_all(DEVICE(dev));
+ qdev_reset_all(dev);
return 0;
}
diff --git a/hw/ide/qdev.c b/hw/ide/qdev.c
index c22afdb..06b1158 100644
--- a/hw/ide/qdev.c
+++ b/hw/ide/qdev.c
@@ -36,7 +36,7 @@
/* --------------------------------- */
static char *idebus_get_fw_dev_path(DeviceState *dev);
-static void idebus_unrealize(BusState *qdev, Error **errp);
+static void idebus_unrealize(BusState *qdev);
static Property ide_props[] = {
DEFINE_PROP_UINT32("unit", IDEDevice, unit, -1),
@@ -51,7 +51,7 @@
k->unrealize = idebus_unrealize;
}
-static void idebus_unrealize(BusState *bus, Error **errp)
+static void idebus_unrealize(BusState *bus)
{
IDEBus *ibus = IDE_BUS(bus);
@@ -266,7 +266,7 @@
{
object_property_add(obj, "bootindex", "int32",
ide_dev_get_bootindex,
- ide_dev_set_bootindex, NULL, NULL, NULL);
+ ide_dev_set_bootindex, NULL, NULL);
object_property_set_int(obj, -1, "bootindex", NULL);
}
diff --git a/hw/input/vhost-user-input.c b/hw/input/vhost-user-input.c
index 544452a..63984a8 100644
--- a/hw/input/vhost-user-input.c
+++ b/hw/input/vhost-user-input.c
@@ -101,7 +101,7 @@
vhi->vhost = VHOST_USER_BACKEND(object_new(TYPE_VHOST_USER_BACKEND));
object_property_add_alias(obj, "chardev",
- OBJECT(vhi->vhost), "chardev", &error_abort);
+ OBJECT(vhi->vhost), "chardev");
}
static void vhost_input_finalize(Object *obj)
diff --git a/hw/input/virtio-input-hid.c b/hw/input/virtio-input-hid.c
index e8ae6c1..09cf260 100644
--- a/hw/input/virtio-input-hid.c
+++ b/hw/input/virtio-input-hid.c
@@ -165,7 +165,7 @@
}
}
-static void virtio_input_hid_unrealize(DeviceState *dev, Error **errp)
+static void virtio_input_hid_unrealize(DeviceState *dev)
{
VirtIOInputHID *vhid = VIRTIO_INPUT_HID(dev);
qemu_input_handler_unregister(vhid->hs);
diff --git a/hw/input/virtio-input-host.c b/hw/input/virtio-input-host.c
index f2ab6df..85daf73 100644
--- a/hw/input/virtio-input-host.c
+++ b/hw/input/virtio-input-host.c
@@ -178,7 +178,7 @@
return;
}
-static void virtio_input_host_unrealize(DeviceState *dev, Error **errp)
+static void virtio_input_host_unrealize(DeviceState *dev)
{
VirtIOInputHost *vih = VIRTIO_INPUT_HOST(dev);
diff --git a/hw/input/virtio-input.c b/hw/input/virtio-input.c
index 4d49790..54bcb46 100644
--- a/hw/input/virtio-input.c
+++ b/hw/input/virtio-input.c
@@ -276,19 +276,14 @@
g_free(vinput->queue);
}
-static void virtio_input_device_unrealize(DeviceState *dev, Error **errp)
+static void virtio_input_device_unrealize(DeviceState *dev)
{
VirtIOInputClass *vic = VIRTIO_INPUT_GET_CLASS(dev);
VirtIODevice *vdev = VIRTIO_DEVICE(dev);
VirtIOInput *vinput = VIRTIO_INPUT(dev);
- Error *local_err = NULL;
if (vic->unrealize) {
- vic->unrealize(dev, &local_err);
- if (local_err) {
- error_propagate(errp, local_err);
- return;
- }
+ vic->unrealize(dev);
}
virtio_delete_queue(vinput->evt);
virtio_delete_queue(vinput->sts);
diff --git a/hw/intc/apic.c b/hw/intc/apic.c
index bd40467..6b46839 100644
--- a/hw/intc/apic.c
+++ b/hw/intc/apic.c
@@ -900,7 +900,7 @@
msi_nonbroken = true;
}
-static void apic_unrealize(DeviceState *dev, Error **errp)
+static void apic_unrealize(DeviceState *dev)
{
APICCommonState *s = APIC(dev);
diff --git a/hw/intc/apic_common.c b/hw/intc/apic_common.c
index 9ec0f2d..7da2862 100644
--- a/hw/intc/apic_common.c
+++ b/hw/intc/apic_common.c
@@ -293,13 +293,13 @@
s, -1, 0, NULL);
}
-static void apic_common_unrealize(DeviceState *dev, Error **errp)
+static void apic_common_unrealize(DeviceState *dev)
{
APICCommonState *s = APIC_COMMON(dev);
APICCommonClass *info = APIC_COMMON_GET_CLASS(s);
vmstate_unregister(NULL, &vmstate_apic_common, s);
- info->unrealize(dev, errp);
+ info->unrealize(dev);
if (apic_report_tpr_access && info->enable_tpr_reporting) {
info->enable_tpr_reporting(s, false);
@@ -445,7 +445,7 @@
s->id = s->initial_apic_id = -1;
object_property_add(obj, "id", "uint32",
apic_common_get_id,
- apic_common_set_id, NULL, NULL, NULL);
+ apic_common_set_id, NULL, NULL);
}
static void apic_common_class_init(ObjectClass *klass, void *data)
diff --git a/hw/intc/ioapic.c b/hw/intc/ioapic.c
index 15747fe..ffe30dc 100644
--- a/hw/intc/ioapic.c
+++ b/hw/intc/ioapic.c
@@ -451,7 +451,7 @@
qemu_add_machine_init_done_notifier(&s->machine_done);
}
-static void ioapic_unrealize(DeviceState *dev, Error **errp)
+static void ioapic_unrealize(DeviceState *dev)
{
IOAPICCommonState *s = IOAPIC_COMMON(dev);
diff --git a/hw/intc/s390_flic.c b/hw/intc/s390_flic.c
index 5f290f5..baca4d8 100644
--- a/hw/intc/s390_flic.c
+++ b/hw/intc/s390_flic.c
@@ -65,11 +65,11 @@
if (kvm_enabled()) {
dev = qdev_create(NULL, TYPE_KVM_S390_FLIC);
object_property_add_child(qdev_get_machine(), TYPE_KVM_S390_FLIC,
- OBJECT(dev), NULL);
+ OBJECT(dev));
} else {
dev = qdev_create(NULL, TYPE_QEMU_S390_FLIC);
object_property_add_child(qdev_get_machine(), TYPE_QEMU_S390_FLIC,
- OBJECT(dev), NULL);
+ OBJECT(dev));
}
qdev_init_nofail(dev);
}
diff --git a/hw/intc/xics.c b/hw/intc/xics.c
index c5d507e..d5032c8 100644
--- a/hw/intc/xics.c
+++ b/hw/intc/xics.c
@@ -338,7 +338,7 @@
vmstate_register(NULL, icp->cs->cpu_index, &vmstate_icp_server, icp);
}
-static void icp_unrealize(DeviceState *dev, Error **errp)
+static void icp_unrealize(DeviceState *dev)
{
ICPState *icp = ICP(dev);
@@ -380,7 +380,7 @@
Object *obj;
obj = object_new(type);
- object_property_add_child(cpu, type, obj, &error_abort);
+ object_property_add_child(cpu, type, obj);
object_unref(obj);
object_property_set_link(obj, OBJECT(xi), ICP_PROP_XICS, &error_abort);
object_property_set_link(obj, cpu, ICP_PROP_CPU, &error_abort);
diff --git a/hw/intc/xive.c b/hw/intc/xive.c
index d6183f8..8f2b405 100644
--- a/hw/intc/xive.c
+++ b/hw/intc/xive.c
@@ -761,7 +761,7 @@
Object *obj;
obj = object_new(TYPE_XIVE_TCTX);
- object_property_add_child(cpu, TYPE_XIVE_TCTX, obj, &error_abort);
+ object_property_add_child(cpu, TYPE_XIVE_TCTX, obj);
object_unref(obj);
object_property_set_link(obj, cpu, "cpu", &error_abort);
object_property_set_link(obj, OBJECT(xptr), "presenter", &error_abort);
diff --git a/hw/ipack/ipack.c b/hw/ipack/ipack.c
index 49787a1..f19ecae 100644
--- a/hw/ipack/ipack.c
+++ b/hw/ipack/ipack.c
@@ -60,15 +60,13 @@
k->realize(dev, errp);
}
-static void ipack_device_unrealize(DeviceState *dev, Error **errp)
+static void ipack_device_unrealize(DeviceState *dev)
{
IPackDevice *idev = IPACK_DEVICE(dev);
IPackDeviceClass *k = IPACK_DEVICE_GET_CLASS(dev);
- Error *err = NULL;
if (k->unrealize) {
- k->unrealize(dev, &err);
- error_propagate(errp, err);
+ k->unrealize(dev);
return;
}
diff --git a/hw/ipmi/ipmi.c b/hw/ipmi/ipmi.c
index 46c6a79..8d35c9f 100644
--- a/hw/ipmi/ipmi.c
+++ b/hw/ipmi/ipmi.c
@@ -105,8 +105,7 @@
{
object_property_add_link(obj, "bmc", TYPE_IPMI_BMC, bmc,
isa_ipmi_bmc_check,
- OBJ_PROP_LINK_STRONG,
- &error_abort);
+ OBJ_PROP_LINK_STRONG);
}
static Property ipmi_bmc_properties[] = {
diff --git a/hw/ipmi/smbus_ipmi.c b/hw/ipmi/smbus_ipmi.c
index 2a9470d..f1a0148 100644
--- a/hw/ipmi/smbus_ipmi.c
+++ b/hw/ipmi/smbus_ipmi.c
@@ -329,7 +329,7 @@
{
SMBusIPMIDevice *sid = SMBUS_IPMI(obj);
- ipmi_bmc_find_and_link(OBJECT(obj), (Object **) &sid->bmc);
+ ipmi_bmc_find_and_link(obj, (Object **) &sid->bmc);
}
static void smbus_ipmi_get_fwinfo(struct IPMIInterface *ii, IPMIFwInfo *info)
diff --git a/hw/isa/isa-superio.c b/hw/isa/isa-superio.c
index 180a8b9..3dcdc23 100644
--- a/hw/isa/isa-superio.c
+++ b/hw/isa/isa-superio.c
@@ -62,6 +62,7 @@
qdev_prop_set_uint32(d, "irq", k->parallel.get_irq(sio, i));
}
qdev_prop_set_chr(d, "chardev", chr);
+ object_property_add_child(OBJECT(dev), name, OBJECT(isa));
qdev_init_nofail(d);
sio->parallel[i] = isa;
trace_superio_create_parallel(i,
@@ -69,8 +70,6 @@
k->parallel.get_iobase(sio, i) : -1,
k->parallel.get_irq ?
k->parallel.get_irq(sio, i) : -1);
- object_property_add_child(OBJECT(dev), name,
- OBJECT(sio->parallel[i]), NULL);
g_free(name);
}
}
@@ -102,6 +101,7 @@
qdev_prop_set_uint32(d, "irq", k->serial.get_irq(sio, i));
}
qdev_prop_set_chr(d, "chardev", chr);
+ object_property_add_child(OBJECT(dev), name, OBJECT(isa));
qdev_init_nofail(d);
sio->serial[i] = isa;
trace_superio_create_serial(i,
@@ -109,8 +109,6 @@
k->serial.get_iobase(sio, i) : -1,
k->serial.get_irq ?
k->serial.get_irq(sio, i) : -1);
- object_property_add_child(OBJECT(dev), name,
- OBJECT(sio->serial[0]), NULL);
g_free(name);
}
}
@@ -137,6 +135,7 @@
qdev_prop_set_drive(d, "driveB", blk_by_legacy_dinfo(drive),
&error_fatal);
}
+ object_property_add_child(OBJECT(sio), "isa-fdc", OBJECT(isa));
qdev_init_nofail(d);
sio->floppy = isa;
trace_superio_create_floppy(0,
@@ -147,7 +146,10 @@
}
/* Keyboard, mouse */
- sio->kbc = isa_create_simple(bus, TYPE_I8042);
+ isa = isa_create(bus, TYPE_I8042);
+ object_property_add_child(OBJECT(sio), TYPE_I8042, OBJECT(isa));
+ qdev_init_nofail(DEVICE(isa));
+ sio->kbc = isa;
/* IDE */
if (k->ide.count && (!k->ide.is_enabled || k->ide.is_enabled(sio, 0))) {
@@ -163,6 +165,7 @@
qdev_prop_set_uint32(d, "irq", k->ide.get_irq(sio, 0));
}
qdev_init_nofail(d);
+ object_property_add_child(OBJECT(sio), "isa-ide", OBJECT(isa));
sio->ide = isa;
trace_superio_create_ide(0,
k->ide.get_iobase ?
diff --git a/hw/isa/lpc_ich9.c b/hw/isa/lpc_ich9.c
index fbc3165..cd6e169 100644
--- a/hw/isa/lpc_ich9.c
+++ b/hw/isa/lpc_ich9.c
@@ -633,13 +633,13 @@
static const uint8_t acpi_disable_cmd = ICH9_APM_ACPI_DISABLE;
object_property_add_uint8_ptr(obj, ACPI_PM_PROP_SCI_INT,
- &lpc->sci_gsi, OBJ_PROP_FLAG_READ, NULL);
+ &lpc->sci_gsi, OBJ_PROP_FLAG_READ);
object_property_add_uint8_ptr(OBJECT(lpc), ACPI_PM_PROP_ACPI_ENABLE_CMD,
- &acpi_enable_cmd, OBJ_PROP_FLAG_READ, NULL);
+ &acpi_enable_cmd, OBJ_PROP_FLAG_READ);
object_property_add_uint8_ptr(OBJECT(lpc), ACPI_PM_PROP_ACPI_DISABLE_CMD,
- &acpi_disable_cmd, OBJ_PROP_FLAG_READ, NULL);
+ &acpi_disable_cmd, OBJ_PROP_FLAG_READ);
- ich9_pm_add_properties(obj, &lpc->pm, NULL);
+ ich9_pm_add_properties(obj, &lpc->pm);
}
static void ich9_lpc_realize(PCIDevice *d, Error **errp)
diff --git a/hw/isa/vt82c686.c b/hw/isa/vt82c686.c
index d9b51fc..fac4e56 100644
--- a/hw/isa/vt82c686.c
+++ b/hw/isa/vt82c686.c
@@ -503,7 +503,7 @@
dc->vmsd = &vmstate_via;
/*
* Reason: part of VIA VT82C686 southbridge, needs to be wired up,
- * e.g. by mips_fulong2e_init()
+ * e.g. by mips_fuloong2e_init()
*/
dc->user_creatable = false;
}
diff --git a/hw/m68k/mcf5206.c b/hw/m68k/mcf5206.c
index b155dd8..a2fef04 100644
--- a/hw/m68k/mcf5206.c
+++ b/hw/m68k/mcf5206.c
@@ -8,6 +8,7 @@
#include "qemu/osdep.h"
#include "qemu/error-report.h"
+#include "qemu/log.h"
#include "cpu.h"
#include "hw/hw.h"
#include "hw/irq.h"
@@ -225,7 +226,8 @@
break;
default:
/* Unknown vector. */
- error_report("Unhandled vector for IRQ %d", irq);
+ qemu_log_mask(LOG_UNIMP, "%s: Unhandled vector for IRQ %d\n",
+ __func__, irq);
vector = 0xf;
break;
}
@@ -273,7 +275,7 @@
}
static uint64_t m5206_mbar_read(m5206_mbar_state *s,
- uint64_t offset, unsigned size)
+ uint16_t offset, unsigned size)
{
if (offset >= 0x100 && offset < 0x120) {
return m5206_timer_read(s->timer[0], offset - 0x100);
@@ -306,11 +308,12 @@
case 0x170: return s->uivr[0];
case 0x1b0: return s->uivr[1];
}
- hw_error("Bad MBAR read offset 0x%x", (int)offset);
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: Bad MBAR offset 0x%"PRIx16"\n",
+ __func__, offset);
return 0;
}
-static void m5206_mbar_write(m5206_mbar_state *s, uint32_t offset,
+static void m5206_mbar_write(m5206_mbar_state *s, uint16_t offset,
uint64_t value, unsigned size)
{
if (offset >= 0x100 && offset < 0x120) {
@@ -360,7 +363,8 @@
s->uivr[1] = value;
break;
default:
- hw_error("Bad MBAR write offset 0x%x", (int)offset);
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: Bad MBAR offset 0x%"PRIx16"\n",
+ __func__, offset);
break;
}
}
diff --git a/hw/m68k/mcf5208.c b/hw/m68k/mcf5208.c
index b84c152..2ab9701 100644
--- a/hw/m68k/mcf5208.c
+++ b/hw/m68k/mcf5208.c
@@ -9,10 +9,10 @@
#include "qemu/osdep.h"
#include "qemu/units.h"
#include "qemu/error-report.h"
+#include "qemu/log.h"
#include "qapi/error.h"
#include "qemu-common.h"
#include "cpu.h"
-#include "hw/hw.h"
#include "hw/irq.h"
#include "hw/m68k/mcf.h"
#include "hw/m68k/mcf_fec.h"
@@ -111,8 +111,9 @@
case 4:
break;
default:
- hw_error("m5208_timer_write: Bad offset 0x%x\n", (int)offset);
- break;
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: Bad offset 0x%" HWADDR_PRIX "\n",
+ __func__, offset);
+ return;
}
m5208_timer_update(s);
}
@@ -136,7 +137,8 @@
case 4:
return ptimer_get_count(s->timer);
default:
- hw_error("m5208_timer_read: Bad offset 0x%x\n", (int)addr);
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: Bad offset 0x%" HWADDR_PRIX "\n",
+ __func__, addr);
return 0;
}
}
@@ -164,7 +166,8 @@
return 0;
default:
- hw_error("m5208_sys_read: Bad offset 0x%x\n", (int)addr);
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: Bad offset 0x%" HWADDR_PRIX "\n",
+ __func__, addr);
return 0;
}
}
@@ -172,7 +175,8 @@
static void m5208_sys_write(void *opaque, hwaddr addr,
uint64_t value, unsigned size)
{
- hw_error("m5208_sys_write: Bad offset 0x%x\n", (int)addr);
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: Bad offset 0x%" HWADDR_PRIX "\n",
+ __func__, addr);
}
static const MemoryRegionOps m5208_sys_ops = {
diff --git a/hw/m68k/mcf_intc.c b/hw/m68k/mcf_intc.c
index d9e03a0..bc20742 100644
--- a/hw/m68k/mcf_intc.c
+++ b/hw/m68k/mcf_intc.c
@@ -8,6 +8,7 @@
#include "qemu/osdep.h"
#include "qemu/module.h"
+#include "qemu/log.h"
#include "cpu.h"
#include "hw/hw.h"
#include "hw/irq.h"
@@ -80,7 +81,9 @@
case 0xe1: case 0xe2: case 0xe3: case 0xe4:
case 0xe5: case 0xe6: case 0xe7:
/* LnIACK */
- hw_error("mcf_intc_read: LnIACK not implemented\n");
+ qemu_log_mask(LOG_UNIMP, "%s: LnIACK not implemented (offset 0x%02x)\n",
+ __func__, offset);
+ /* fallthru */
default:
return 0;
}
@@ -127,8 +130,9 @@
}
break;
default:
- hw_error("mcf_intc_write: Bad write offset %d\n", offset);
- break;
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: Bad offset 0x%02x\n",
+ __func__, offset);
+ return;
}
mcf_intc_update(s);
}
diff --git a/hw/mem/nvdimm.c b/hw/mem/nvdimm.c
index 8e426d2..76f66e0 100644
--- a/hw/mem/nvdimm.c
+++ b/hw/mem/nvdimm.c
@@ -97,7 +97,6 @@
if (qemu_uuid_parse(value, &nvdimm->uuid) != 0) {
error_setg(errp, "Property '%s.%s' has invalid value",
object_get_typename(obj), name);
- goto out;
}
g_free(value);
@@ -110,10 +109,10 @@
{
object_property_add(obj, NVDIMM_LABEL_SIZE_PROP, "int",
nvdimm_get_label_size, nvdimm_set_label_size, NULL,
- NULL, NULL);
+ NULL);
object_property_add(obj, NVDIMM_UUID_PROP, "QemuUUID", nvdimm_get_uuid,
- nvdimm_set_uuid, NULL, NULL, NULL);
+ nvdimm_set_uuid, NULL, NULL);
}
static void nvdimm_finalize(Object *obj)
diff --git a/hw/mem/pc-dimm.c b/hw/mem/pc-dimm.c
index 6d62588..f2a86ec 100644
--- a/hw/mem/pc-dimm.c
+++ b/hw/mem/pc-dimm.c
@@ -165,7 +165,7 @@
static void pc_dimm_init(Object *obj)
{
object_property_add(obj, PC_DIMM_SIZE_PROP, "uint64", pc_dimm_get_size,
- NULL, NULL, NULL, &error_abort);
+ NULL, NULL, NULL);
}
static void pc_dimm_realize(DeviceState *dev, Error **errp)
@@ -199,7 +199,7 @@
host_memory_backend_set_mapped(dimm->hostmem, true);
}
-static void pc_dimm_unrealize(DeviceState *dev, Error **errp)
+static void pc_dimm_unrealize(DeviceState *dev)
{
PCDIMMDevice *dimm = PC_DIMM(dev);
diff --git a/hw/microblaze/petalogix_ml605_mmu.c b/hw/microblaze/petalogix_ml605_mmu.c
index 0a2640c..05a5614 100644
--- a/hw/microblaze/petalogix_ml605_mmu.c
+++ b/hw/microblaze/petalogix_ml605_mmu.c
@@ -138,10 +138,8 @@
dma = qdev_create(NULL, "xlnx.axi-dma");
/* FIXME: attach to the sysbus instead */
- object_property_add_child(qdev_get_machine(), "xilinx-eth", OBJECT(eth0),
- NULL);
- object_property_add_child(qdev_get_machine(), "xilinx-dma", OBJECT(dma),
- NULL);
+ object_property_add_child(qdev_get_machine(), "xilinx-eth", OBJECT(eth0));
+ object_property_add_child(qdev_get_machine(), "xilinx-dma", OBJECT(dma));
ds = object_property_get_link(OBJECT(dma),
"axistream-connected-target", NULL);
@@ -150,9 +148,9 @@
qdev_set_nic_properties(eth0, &nd_table[0]);
qdev_prop_set_uint32(eth0, "rxmem", 0x1000);
qdev_prop_set_uint32(eth0, "txmem", 0x1000);
- object_property_set_link(OBJECT(eth0), OBJECT(ds),
+ object_property_set_link(OBJECT(eth0), ds,
"axistream-connected", &error_abort);
- object_property_set_link(OBJECT(eth0), OBJECT(cs),
+ object_property_set_link(OBJECT(eth0), cs,
"axistream-control-connected", &error_abort);
qdev_init_nofail(eth0);
sysbus_mmio_map(SYS_BUS_DEVICE(eth0), 0, AXIENET_BASEADDR);
@@ -163,9 +161,9 @@
cs = object_property_get_link(OBJECT(eth0),
"axistream-control-connected-target", NULL);
qdev_prop_set_uint32(dma, "freqhz", 100 * 1000000);
- object_property_set_link(OBJECT(dma), OBJECT(ds),
+ object_property_set_link(OBJECT(dma), ds,
"axistream-connected", &error_abort);
- object_property_set_link(OBJECT(dma), OBJECT(cs),
+ object_property_set_link(OBJECT(dma), cs,
"axistream-control-connected", &error_abort);
qdev_init_nofail(dma);
sysbus_mmio_map(SYS_BUS_DEVICE(dma), 0, AXIDMA_BASEADDR);
diff --git a/hw/mips/Kconfig b/hw/mips/Kconfig
index 2c2adbc..67d39c5 100644
--- a/hw/mips/Kconfig
+++ b/hw/mips/Kconfig
@@ -41,8 +41,9 @@
select DS1225Y
select JAZZ_LED
-config FULONG
+config FULOONG
bool
+ select PCI_BONITO
config MIPS_CPS
bool
diff --git a/hw/mips/Makefile.objs b/hw/mips/Makefile.objs
index 525809a..739e2b7 100644
--- a/hw/mips/Makefile.objs
+++ b/hw/mips/Makefile.objs
@@ -1,8 +1,8 @@
obj-y += addr.o mips_int.o
-obj-$(CONFIG_R4K) += mips_r4k.o
-obj-$(CONFIG_MALTA) += gt64xxx_pci.o mips_malta.o
-obj-$(CONFIG_MIPSSIM) += mips_mipssim.o
-obj-$(CONFIG_JAZZ) += mips_jazz.o
-obj-$(CONFIG_FULONG) += mips_fulong2e.o
+obj-$(CONFIG_R4K) += r4k.o
+obj-$(CONFIG_MALTA) += gt64xxx_pci.o malta.o
+obj-$(CONFIG_MIPSSIM) += mipssim.o
+obj-$(CONFIG_JAZZ) += jazz.o
+obj-$(CONFIG_FULOONG) += fuloong2e.o
obj-$(CONFIG_MIPS_CPS) += cps.o
obj-$(CONFIG_MIPS_BOSTON) += boston.o
diff --git a/hw/mips/boston.c b/hw/mips/boston.c
index 98ecd25..a896056 100644
--- a/hw/mips/boston.c
+++ b/hw/mips/boston.c
@@ -426,7 +426,6 @@
{
DeviceState *dev;
BostonState *s;
- Error *err = NULL;
MemoryRegion *flash, *ddr_low_alias, *lcd, *platreg;
MemoryRegion *sys_mem = get_system_memory();
XilinxPCIEHost *pcie2;
@@ -458,19 +457,17 @@
sysbus_init_child_obj(OBJECT(machine), "cps", OBJECT(&s->cps),
sizeof(s->cps), TYPE_MIPS_CPS);
object_property_set_str(OBJECT(&s->cps), machine->cpu_type, "cpu-type",
- &err);
- object_property_set_int(OBJECT(&s->cps), machine->smp.cpus, "num-vp", &err);
- object_property_set_bool(OBJECT(&s->cps), true, "realized", &err);
-
- if (err != NULL) {
- error_report("%s", error_get_pretty(err));
- exit(1);
- }
+ &error_fatal);
+ object_property_set_int(OBJECT(&s->cps), machine->smp.cpus, "num-vp",
+ &error_fatal);
+ object_property_set_bool(OBJECT(&s->cps), true, "realized",
+ &error_fatal);
sysbus_mmio_map_overlap(SYS_BUS_DEVICE(&s->cps), 0, 0, 1);
flash = g_new(MemoryRegion, 1);
- memory_region_init_rom(flash, NULL, "boston.flash", 128 * MiB, &err);
+ memory_region_init_rom(flash, NULL, "boston.flash", 128 * MiB,
+ &error_fatal);
memory_region_add_subregion_overlap(sys_mem, 0x18000000, flash, 0);
memory_region_add_subregion_overlap(sys_mem, 0x80000000, machine->ram, 0);
diff --git a/hw/mips/mips_fulong2e.c b/hw/mips/fuloong2e.c
similarity index 91%
rename from hw/mips/mips_fulong2e.c
rename to hw/mips/fuloong2e.c
index ef02d54..7a65166 100644
--- a/hw/mips/mips_fulong2e.c
+++ b/hw/mips/fuloong2e.c
@@ -1,5 +1,5 @@
/*
- * QEMU fulong 2e mini pc support
+ * QEMU fuloong 2e mini pc support
*
* Copyright (c) 2008 yajin (yajin@vm-kernel.org)
* Copyright (c) 2009 chenming (chenming@rdc.faw.com.cn)
@@ -11,8 +11,8 @@
*/
/*
- * Fulong 2e mini pc is based on ICT/ST Loongson 2e CPU (MIPS III like, 800MHz)
- * http://www.linux-mips.org/wiki/Fulong
+ * Fuloong 2e mini pc is based on ICT/ST Loongson 2e CPU (MIPS III like, 800MHz)
+ * https://www.linux-mips.org/wiki/Fuloong_2E
*
* Loongson 2e user manual:
* http://www.loongsondeveloper.com/doc/Loongson2EUserGuide.pdf
@@ -33,7 +33,6 @@
#include "hw/mips/mips.h"
#include "hw/mips/cpudevs.h"
#include "hw/pci/pci.h"
-#include "audio/audio.h"
#include "qemu/log.h"
#include "hw/loader.h"
#include "hw/ide/pci.h"
@@ -46,13 +45,13 @@
#include "sysemu/reset.h"
#include "qemu/error-report.h"
-#define DEBUG_FULONG2E_INIT
+#define DEBUG_FULOONG2E_INIT
#define ENVP_ADDR 0x80002000l
#define ENVP_NB_ENTRIES 16
#define ENVP_ENTRY_SIZE 256
-/* fulong 2e has a 512k flash: Winbond W39L040AP70Z */
+/* Fuloong 2e has a 512k flash: Winbond W39L040AP70Z */
#define BIOS_SIZE (512 * KiB)
#define MAX_IDE_BUS 2
@@ -69,12 +68,12 @@
* 2, use "Bonito2edev" to replace "dir_corresponding_to_your_target_hardware"
* in the "Compile Guide".
*/
-#define FULONG_BIOSNAME "pmon_fulong2e.bin"
+#define FULOONG_BIOSNAME "pmon_2e.bin"
-/* PCI SLOT in fulong 2e */
-#define FULONG2E_VIA_SLOT 5
-#define FULONG2E_ATI_SLOT 6
-#define FULONG2E_RTL8139_SLOT 7
+/* PCI SLOT in Fuloong 2e */
+#define FULOONG2E_VIA_SLOT 5
+#define FULOONG2E_ATI_SLOT 6
+#define FULOONG2E_RTL8139_SLOT 7
static struct _loaderparams {
int ram_size;
@@ -279,7 +278,7 @@
const char *default_devaddr = NULL;
if (i == 0 && (!nd->model || strcmp(nd->model, "rtl8139") == 0)) {
- /* The fulong board has a RTL8139 card using PCI SLOT 7 */
+ /* The Fuloong board has a RTL8139 card using PCI SLOT 7 */
default_devaddr = "07";
}
@@ -287,7 +286,7 @@
}
}
-static void mips_fulong2e_init(MachineState *machine)
+static void mips_fuloong2e_init(MachineState *machine)
{
const char *kernel_filename = machine->kernel_filename;
const char *kernel_cmdline = machine->kernel_cmdline;
@@ -316,12 +315,11 @@
error_report("Invalid RAM size, should be 256MB");
exit(EXIT_FAILURE);
}
-
- /* allocate RAM */
- memory_region_init_rom(bios, NULL, "fulong2e.bios", BIOS_SIZE,
- &error_fatal);
-
memory_region_add_subregion(address_space_mem, 0, machine->ram);
+
+ /* Boot ROM */
+ memory_region_init_rom(bios, NULL, "fuloong2e.bios", BIOS_SIZE,
+ &error_fatal);
memory_region_add_subregion(address_space_mem, 0x1fc00000LL, bios);
/*
@@ -338,7 +336,7 @@
write_bootloader(env, memory_region_get_ram_ptr(bios), kernel_entry);
} else {
if (bios_name == NULL) {
- bios_name = FULONG_BIOSNAME;
+ bios_name = FULOONG_BIOSNAME;
}
filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name);
if (filename) {
@@ -364,7 +362,7 @@
pci_bus = bonito_init((qemu_irq *)&(env->irq[2]));
/* South bridge -> IP5 */
- vt82c686b_southbridge_init(pci_bus, FULONG2E_VIA_SLOT, env->irq[5],
+ vt82c686b_southbridge_init(pci_bus, FULOONG2E_VIA_SLOT, env->irq[5],
&smbus, &isa_bus);
/* GPU */
@@ -385,14 +383,16 @@
network_init(pci_bus);
}
-static void mips_fulong2e_machine_init(MachineClass *mc)
+static void mips_fuloong2e_machine_init(MachineClass *mc)
{
- mc->desc = "Fulong 2e mini pc";
- mc->init = mips_fulong2e_init;
+ mc->desc = "Fuloong 2e mini pc";
+ mc->alias = "fulong2e"; /* Incorrect name used up to QEMU 4.2 */
+ mc->init = mips_fuloong2e_init;
mc->block_default_type = IF_IDE;
mc->default_cpu_type = MIPS_CPU_TYPE_NAME("Loongson-2E");
mc->default_ram_size = 256 * MiB;
- mc->default_ram_id = "fulong2e.ram";
+ mc->default_ram_id = "fuloong2e.ram";
+ mc->minimum_page_bits = 14;
}
-DEFINE_MACHINE("fulong2e", mips_fulong2e_machine_init)
+DEFINE_MACHINE("fuloong2e", mips_fuloong2e_machine_init)
diff --git a/hw/mips/mips_jazz.c b/hw/mips/jazz.c
similarity index 100%
rename from hw/mips/mips_jazz.c
rename to hw/mips/jazz.c
diff --git a/hw/mips/mips_malta.c b/hw/mips/malta.c
similarity index 98%
rename from hw/mips/mips_malta.c
rename to hw/mips/malta.c
index e4c4de1..636c95d 100644
--- a/hw/mips/mips_malta.c
+++ b/hw/mips/malta.c
@@ -427,10 +427,9 @@
break;
default:
-#if 0
- printf("malta_fpga_read: Bad register offset 0x" TARGET_FMT_lx "\n",
- addr);
-#endif
+ qemu_log_mask(LOG_GUEST_ERROR,
+ "malta_fpga_read: Bad register addr 0x%"HWADDR_PRIX"\n",
+ addr);
break;
}
return val;
@@ -515,10 +514,9 @@
break;
default:
-#if 0
- printf("malta_fpga_write: Bad register offset 0x" TARGET_FMT_lx "\n",
- addr);
-#endif
+ qemu_log_mask(LOG_GUEST_ERROR,
+ "malta_fpga_write: Bad register addr 0x%"HWADDR_PRIX"\n",
+ addr);
break;
}
}
@@ -1185,17 +1183,14 @@
static void create_cps(MachineState *ms, MaltaState *s,
qemu_irq *cbus_irq, qemu_irq *i8259_irq)
{
- Error *err = NULL;
-
sysbus_init_child_obj(OBJECT(s), "cps", OBJECT(&s->cps), sizeof(s->cps),
TYPE_MIPS_CPS);
- object_property_set_str(OBJECT(&s->cps), ms->cpu_type, "cpu-type", &err);
- object_property_set_int(OBJECT(&s->cps), ms->smp.cpus, "num-vp", &err);
- object_property_set_bool(OBJECT(&s->cps), true, "realized", &err);
- if (err != NULL) {
- error_report("%s", error_get_pretty(err));
- exit(1);
- }
+ object_property_set_str(OBJECT(&s->cps), ms->cpu_type, "cpu-type",
+ &error_fatal);
+ object_property_set_int(OBJECT(&s->cps), ms->smp.cpus, "num-vp",
+ &error_fatal);
+ object_property_set_bool(OBJECT(&s->cps), true, "realized",
+ &error_fatal);
sysbus_mmio_map_overlap(SYS_BUS_DEVICE(&s->cps), 0, 0, 1);
diff --git a/hw/mips/mips_int.c b/hw/mips/mips_int.c
index 796730b..0f9c6f0 100644
--- a/hw/mips/mips_int.c
+++ b/hw/mips/mips_int.c
@@ -47,17 +47,12 @@
if (level) {
env->CP0_Cause |= 1 << (irq + CP0Ca_IP);
-
- if (kvm_enabled() && irq == 2) {
- kvm_mips_set_interrupt(cpu, irq, level);
- }
-
} else {
env->CP0_Cause &= ~(1 << (irq + CP0Ca_IP));
+ }
- if (kvm_enabled() && irq == 2) {
- kvm_mips_set_interrupt(cpu, irq, level);
- }
+ if (kvm_enabled() && (irq == 2 || irq == 3)) {
+ kvm_mips_set_interrupt(cpu, irq, level);
}
if (env->CP0_Cause & CP0Ca_IP_mask) {
diff --git a/hw/mips/mips_mipssim.c b/hw/mips/mipssim.c
similarity index 100%
rename from hw/mips/mips_mipssim.c
rename to hw/mips/mipssim.c
diff --git a/hw/mips/mips_r4k.c b/hw/mips/r4k.c
similarity index 100%
rename from hw/mips/mips_r4k.c
rename to hw/mips/r4k.c
diff --git a/hw/misc/Makefile.objs b/hw/misc/Makefile.objs
index 68aae2e..b25181b 100644
--- a/hw/misc/Makefile.objs
+++ b/hw/misc/Makefile.objs
@@ -44,7 +44,6 @@
common-obj-$(CONFIG_IMX) += imx6ul_ccm.o
obj-$(CONFIG_IMX) += imx6_src.o
common-obj-$(CONFIG_IMX) += imx7_ccm.o
-common-obj-$(CONFIG_IMX) += imx2_wdt.o
common-obj-$(CONFIG_IMX) += imx7_snvs.o
common-obj-$(CONFIG_IMX) += imx7_gpr.o
common-obj-$(CONFIG_IMX) += imx_rngc.o
diff --git a/hw/misc/aspeed_sdmc.c b/hw/misc/aspeed_sdmc.c
index 14db9cf..25e1e58 100644
--- a/hw/misc/aspeed_sdmc.c
+++ b/hw/misc/aspeed_sdmc.c
@@ -250,7 +250,7 @@
{
object_property_add(obj, "ram-size", "int",
aspeed_sdmc_get_ram_size, aspeed_sdmc_set_ram_size,
- NULL, NULL, NULL);
+ NULL, NULL);
}
static void aspeed_sdmc_realize(DeviceState *dev, Error **errp)
diff --git a/hw/misc/edu.c b/hw/misc/edu.c
index ff10f5b..ec617e6 100644
--- a/hw/misc/edu.c
+++ b/hw/misc/edu.c
@@ -402,8 +402,7 @@
edu->dma_mask = (1UL << 28) - 1;
object_property_add_uint64_ptr(obj, "dma_mask",
- &edu->dma_mask, OBJ_PROP_FLAG_READWRITE,
- NULL);
+ &edu->dma_mask, OBJ_PROP_FLAG_READWRITE);
}
static void edu_class_init(ObjectClass *class, void *data)
diff --git a/hw/misc/imx2_wdt.c b/hw/misc/imx2_wdt.c
deleted file mode 100644
index 2aedfe8..0000000
--- a/hw/misc/imx2_wdt.c
+++ /dev/null
@@ -1,90 +0,0 @@
-/*
- * Copyright (c) 2018, Impinj, Inc.
- *
- * i.MX2 Watchdog IP block
- *
- * Author: Andrey Smirnov <andrew.smirnov@gmail.com>
- *
- * This work is licensed under the terms of the GNU GPL, version 2 or later.
- * See the COPYING file in the top-level directory.
- */
-
-#include "qemu/osdep.h"
-#include "qemu/bitops.h"
-#include "qemu/module.h"
-#include "sysemu/watchdog.h"
-
-#include "hw/misc/imx2_wdt.h"
-
-#define IMX2_WDT_WCR_WDA BIT(5) /* -> External Reset WDOG_B */
-#define IMX2_WDT_WCR_SRS BIT(4) /* -> Software Reset Signal */
-
-static uint64_t imx2_wdt_read(void *opaque, hwaddr addr,
- unsigned int size)
-{
- return 0;
-}
-
-static void imx2_wdt_write(void *opaque, hwaddr addr,
- uint64_t value, unsigned int size)
-{
- if (addr == IMX2_WDT_WCR &&
- (~value & (IMX2_WDT_WCR_WDA | IMX2_WDT_WCR_SRS))) {
- watchdog_perform_action();
- }
-}
-
-static const MemoryRegionOps imx2_wdt_ops = {
- .read = imx2_wdt_read,
- .write = imx2_wdt_write,
- .endianness = DEVICE_NATIVE_ENDIAN,
- .impl = {
- /*
- * Our device would not work correctly if the guest was doing
- * unaligned access. This might not be a limitation on the
- * real device but in practice there is no reason for a guest
- * to access this device unaligned.
- */
- .min_access_size = 4,
- .max_access_size = 4,
- .unaligned = false,
- },
-};
-
-static void imx2_wdt_realize(DeviceState *dev, Error **errp)
-{
- IMX2WdtState *s = IMX2_WDT(dev);
-
- memory_region_init_io(&s->mmio, OBJECT(dev),
- &imx2_wdt_ops, s,
- TYPE_IMX2_WDT".mmio",
- IMX2_WDT_REG_NUM * sizeof(uint16_t));
- sysbus_init_mmio(SYS_BUS_DEVICE(dev), &s->mmio);
-}
-
-static void imx2_wdt_class_init(ObjectClass *klass, void *data)
-{
- DeviceClass *dc = DEVICE_CLASS(klass);
-
- dc->realize = imx2_wdt_realize;
- set_bit(DEVICE_CATEGORY_MISC, dc->categories);
-}
-
-static const TypeInfo imx2_wdt_info = {
- .name = TYPE_IMX2_WDT,
- .parent = TYPE_SYS_BUS_DEVICE,
- .instance_size = sizeof(IMX2WdtState),
- .class_init = imx2_wdt_class_init,
-};
-
-static WatchdogTimerModel model = {
- .wdt_name = "imx2-watchdog",
- .wdt_description = "i.MX2 Watchdog",
-};
-
-static void imx2_wdt_register_type(void)
-{
- watchdog_add_model(&model);
- type_register_static(&imx2_wdt_info);
-}
-type_init(imx2_wdt_register_type)
diff --git a/hw/misc/mac_via.c b/hw/misc/mac_via.c
index 8134330..e05623d 100644
--- a/hw/misc/mac_via.c
+++ b/hw/misc/mac_via.c
@@ -885,10 +885,10 @@
/* Pass through mos6522 output IRQs */
ms = MOS6522(&m->mos6522_via1);
object_property_add_alias(OBJECT(dev), "irq[0]", OBJECT(ms),
- SYSBUS_DEVICE_GPIO_IRQ "[0]", &error_abort);
+ SYSBUS_DEVICE_GPIO_IRQ "[0]");
ms = MOS6522(&m->mos6522_via2);
object_property_add_alias(OBJECT(dev), "irq[1]", OBJECT(ms),
- SYSBUS_DEVICE_GPIO_IRQ "[0]", &error_abort);
+ SYSBUS_DEVICE_GPIO_IRQ "[0]");
/* Pass through mos6522 input IRQs */
qdev_pass_gpios(DEVICE(&m->mos6522_via1), dev, "via1-irq");
diff --git a/hw/misc/macio/gpio.c b/hw/misc/macio/gpio.c
index 6cca6b2..0fef8fb 100644
--- a/hw/misc/macio/gpio.c
+++ b/hw/misc/macio/gpio.c
@@ -170,7 +170,7 @@
object_property_add_link(obj, "pic", TYPE_OPENPIC,
(Object **) &s->pic,
qdev_prop_allow_set_link_before_realize,
- 0, NULL);
+ 0);
memory_region_init_io(&s->gpiomem, OBJECT(s), &macio_gpio_ops, obj,
"gpio", 0x30);
diff --git a/hw/misc/macio/macio.c b/hw/misc/macio/macio.c
index 7922219..3779865 100644
--- a/hw/misc/macio/macio.c
+++ b/hw/misc/macio/macio.c
@@ -241,7 +241,7 @@
object_property_add_link(obj, "pic", TYPE_HEATHROW,
(Object **) &os->pic,
qdev_prop_allow_set_link_before_realize,
- 0, NULL);
+ 0);
macio_init_child_obj(s, "cuda", &s->cuda, sizeof(s->cuda), TYPE_CUDA);
@@ -397,7 +397,7 @@
object_property_add_link(obj, "pic", TYPE_OPENPIC,
(Object **) &ns->pic,
qdev_prop_allow_set_link_before_realize,
- 0, NULL);
+ 0);
macio_init_child_obj(s, "gpio", &ns->gpio, sizeof(ns->gpio),
TYPE_MACIO_GPIO);
diff --git a/hw/misc/macio/pmu.c b/hw/misc/macio/pmu.c
index b8466a4..9a9cd42 100644
--- a/hw/misc/macio/pmu.c
+++ b/hw/misc/macio/pmu.c
@@ -758,7 +758,7 @@
if (s->has_adb) {
qbus_create_inplace(&s->adb_bus, sizeof(s->adb_bus), TYPE_ADB_BUS,
- DEVICE(dev), "adb.0");
+ dev, "adb.0");
s->adb_poll_timer = timer_new_ms(QEMU_CLOCK_VIRTUAL, pmu_adb_poll, s);
s->adb_poll_mask = 0xffff;
s->autopoll_rate_ms = 20;
@@ -773,7 +773,7 @@
object_property_add_link(obj, "gpio", TYPE_MACIO_GPIO,
(Object **) &s->gpio,
qdev_prop_allow_set_link_before_realize,
- 0, NULL);
+ 0);
sysbus_init_child_obj(obj, "mos6522-pmu", &s->mos6522_pmu,
sizeof(s->mos6522_pmu), TYPE_MOS6522_PMU);
diff --git a/hw/misc/pca9552.c b/hw/misc/pca9552.c
index efd961e..cac729e 100644
--- a/hw/misc/pca9552.c
+++ b/hw/misc/pca9552.c
@@ -298,7 +298,7 @@
name = g_strdup_printf("led%d", led);
object_property_add(obj, name, "bool", pca9552_get_led, pca9552_set_led,
- NULL, NULL, NULL);
+ NULL, NULL);
g_free(name);
}
}
diff --git a/hw/misc/tmp105.c b/hw/misc/tmp105.c
index 75ddad3..58dbebc 100644
--- a/hw/misc/tmp105.c
+++ b/hw/misc/tmp105.c
@@ -245,7 +245,7 @@
{
object_property_add(obj, "temperature", "int",
tmp105_get_temperature,
- tmp105_set_temperature, NULL, NULL, NULL);
+ tmp105_set_temperature, NULL, NULL);
}
static void tmp105_class_init(ObjectClass *klass, void *data)
diff --git a/hw/misc/tmp421.c b/hw/misc/tmp421.c
index c0bc150..74864cd 100644
--- a/hw/misc/tmp421.c
+++ b/hw/misc/tmp421.c
@@ -347,16 +347,16 @@
{
object_property_add(obj, "temperature0", "int",
tmp421_get_temperature,
- tmp421_set_temperature, NULL, NULL, NULL);
+ tmp421_set_temperature, NULL, NULL);
object_property_add(obj, "temperature1", "int",
tmp421_get_temperature,
- tmp421_set_temperature, NULL, NULL, NULL);
+ tmp421_set_temperature, NULL, NULL);
object_property_add(obj, "temperature2", "int",
tmp421_get_temperature,
- tmp421_set_temperature, NULL, NULL, NULL);
+ tmp421_set_temperature, NULL, NULL);
object_property_add(obj, "temperature3", "int",
tmp421_get_temperature,
- tmp421_set_temperature, NULL, NULL, NULL);
+ tmp421_set_temperature, NULL, NULL);
}
static void tmp421_class_init(ObjectClass *klass, void *data)
diff --git a/hw/net/cadence_gem.c b/hw/net/cadence_gem.c
index 22a0b1b..e8f9cc7 100644
--- a/hw/net/cadence_gem.c
+++ b/hw/net/cadence_gem.c
@@ -1600,8 +1600,7 @@
object_property_add_link(obj, "dma", TYPE_MEMORY_REGION,
(Object **)&s->dma_mr,
qdev_prop_allow_set_link_before_realize,
- OBJ_PROP_LINK_STRONG,
- &error_abort);
+ OBJ_PROP_LINK_STRONG);
}
static const VMStateDescription vmstate_cadence_gem = {
diff --git a/hw/net/can/can_kvaser_pci.c b/hw/net/can/can_kvaser_pci.c
index 16861b8..4b94137 100644
--- a/hw/net/can/can_kvaser_pci.c
+++ b/hw/net/can/can_kvaser_pci.c
@@ -282,7 +282,7 @@
object_property_add_link(obj, "canbus", TYPE_CAN_BUS,
(Object **)&d->canbus,
qdev_prop_allow_set_link_before_realize,
- 0, &error_abort);
+ 0);
}
static void kvaser_pci_class_init(ObjectClass *klass, void *data)
diff --git a/hw/net/can/can_mioe3680_pci.c b/hw/net/can/can_mioe3680_pci.c
index 965e252..695e762 100644
--- a/hw/net/can/can_mioe3680_pci.c
+++ b/hw/net/can/can_mioe3680_pci.c
@@ -219,11 +219,11 @@
object_property_add_link(obj, "canbus0", TYPE_CAN_BUS,
(Object **)&d->canbus[0],
qdev_prop_allow_set_link_before_realize,
- 0, &error_abort);
+ 0);
object_property_add_link(obj, "canbus1", TYPE_CAN_BUS,
(Object **)&d->canbus[1],
qdev_prop_allow_set_link_before_realize,
- 0, &error_abort);
+ 0);
}
static void mioe3680_pci_class_init(ObjectClass *klass, void *data)
diff --git a/hw/net/can/can_pcm3680_pci.c b/hw/net/can/can_pcm3680_pci.c
index 51b6540..4218e63 100644
--- a/hw/net/can/can_pcm3680_pci.c
+++ b/hw/net/can/can_pcm3680_pci.c
@@ -220,11 +220,11 @@
object_property_add_link(obj, "canbus0", TYPE_CAN_BUS,
(Object **)&d->canbus[0],
qdev_prop_allow_set_link_before_realize,
- 0, &error_abort);
+ 0);
object_property_add_link(obj, "canbus1", TYPE_CAN_BUS,
(Object **)&d->canbus[1],
qdev_prop_allow_set_link_before_realize,
- 0, &error_abort);
+ 0);
}
static void pcm3680i_pci_class_init(ObjectClass *klass, void *data)
diff --git a/hw/net/e1000.c b/hw/net/e1000.c
index 2a69eee..a18f80e 100644
--- a/hw/net/e1000.c
+++ b/hw/net/e1000.c
@@ -1774,7 +1774,7 @@
E1000State *n = E1000(obj);
device_add_bootindex_property(obj, &n->conf.bootindex,
"bootindex", "/ethernet-phy@0",
- DEVICE(n), NULL);
+ DEVICE(n));
}
static const TypeInfo e1000_base_info = {
@@ -1824,7 +1824,6 @@
type_info.parent = TYPE_E1000_BASE;
type_info.class_data = (void *)info;
type_info.class_init = e1000_class_init;
- type_info.instance_init = e1000_instance_init;
type_register(&type_info);
}
diff --git a/hw/net/e1000e.c b/hw/net/e1000e.c
index 79ba158..fda3451 100644
--- a/hw/net/e1000e.c
+++ b/hw/net/e1000e.c
@@ -705,7 +705,7 @@
E1000EState *s = E1000E(obj);
device_add_bootindex_property(obj, &s->conf.bootindex,
"bootindex", "/ethernet-phy@0",
- DEVICE(obj), NULL);
+ DEVICE(obj));
}
static const TypeInfo e1000e_info = {
diff --git a/hw/net/eepro100.c b/hw/net/eepro100.c
index f6474f0..16e95ef 100644
--- a/hw/net/eepro100.c
+++ b/hw/net/eepro100.c
@@ -1883,7 +1883,7 @@
EEPRO100State *s = DO_UPCAST(EEPRO100State, dev, PCI_DEVICE(obj));
device_add_bootindex_property(obj, &s->conf.bootindex,
"bootindex", "/ethernet-phy@0",
- DEVICE(s), NULL);
+ DEVICE(s));
}
static E100PCIDeviceInfo e100_devices[] = {
diff --git a/hw/net/ftgmac100.c b/hw/net/ftgmac100.c
index 041ed21..25ebee7 100644
--- a/hw/net/ftgmac100.c
+++ b/hw/net/ftgmac100.c
@@ -1035,8 +1035,7 @@
qemu_macaddr_default_if_unset(&s->conf.macaddr);
s->nic = qemu_new_nic(&net_ftgmac100_info, &s->conf,
- object_get_typename(OBJECT(dev)), DEVICE(dev)->id,
- s);
+ object_get_typename(OBJECT(dev)), dev->id, s);
qemu_format_nic_info_str(qemu_get_queue(s->nic), s->conf.macaddr.a);
}
diff --git a/hw/net/imx_fec.c b/hw/net/imx_fec.c
index a35c336..7adcc9d 100644
--- a/hw/net/imx_fec.c
+++ b/hw/net/imx_fec.c
@@ -1323,7 +1323,7 @@
s->nic = qemu_new_nic(&imx_eth_net_info, &s->conf,
object_get_typename(OBJECT(dev)),
- DEVICE(dev)->id, s);
+ dev->id, s);
qemu_format_nic_info_str(qemu_get_queue(s->nic), s->conf.macaddr.a);
}
diff --git a/hw/net/lance.c b/hw/net/lance.c
index 688724d..4c5f01b 100644
--- a/hw/net/lance.c
+++ b/hw/net/lance.c
@@ -134,7 +134,7 @@
device_add_bootindex_property(obj, &s->conf.bootindex,
"bootindex", "/ethernet-phy@0",
- DEVICE(obj), NULL);
+ DEVICE(obj));
}
static Property lance_properties[] = {
diff --git a/hw/net/lasi_i82596.c b/hw/net/lasi_i82596.c
index 52637a5..5e0fd69 100644
--- a/hw/net/lasi_i82596.c
+++ b/hw/net/lasi_i82596.c
@@ -152,7 +152,7 @@
device_add_bootindex_property(obj, &s->conf.bootindex,
"bootindex", "/ethernet-phy@0",
- DEVICE(obj), NULL);
+ DEVICE(obj));
}
static Property lasi_82596_properties[] = {
diff --git a/hw/net/mcf_fec.c b/hw/net/mcf_fec.c
index 9327ac8..2813458 100644
--- a/hw/net/mcf_fec.c
+++ b/hw/net/mcf_fec.c
@@ -7,7 +7,7 @@
*/
#include "qemu/osdep.h"
-#include "hw/hw.h"
+#include "qemu/log.h"
#include "hw/irq.h"
#include "net/net.h"
#include "qemu/module.h"
@@ -392,7 +392,8 @@
case 0x188: return s->emrbr;
case 0x200 ... 0x2e0: return s->mib[(addr & 0x1ff) / 4];
default:
- hw_error("mcf_fec_read: Bad address 0x%x\n", (int)addr);
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: Bad address 0x%" HWADDR_PRIX "\n",
+ __func__, addr);
return 0;
}
}
@@ -492,7 +493,9 @@
s->mib[(addr & 0x1ff) / 4] = value;
break;
default:
- hw_error("mcf_fec_write Bad address 0x%x\n", (int)addr);
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: Bad address 0x%" HWADDR_PRIX "\n",
+ __func__, addr);
+ return;
}
mcf_fec_update(s);
}
diff --git a/hw/net/ne2000-isa.c b/hw/net/ne2000-isa.c
index e744eff..fdf8faa 100644
--- a/hw/net/ne2000-isa.c
+++ b/hw/net/ne2000-isa.c
@@ -133,7 +133,7 @@
{
object_property_add(obj, "bootindex", "int32",
isa_ne2000_get_bootindex,
- isa_ne2000_set_bootindex, NULL, NULL, NULL);
+ isa_ne2000_set_bootindex, NULL, NULL);
object_property_set_int(obj, -1, "bootindex", NULL);
}
static const TypeInfo ne2000_isa_info = {
diff --git a/hw/net/ne2000-pci.c b/hw/net/ne2000-pci.c
index e11d67b..9e5d108 100644
--- a/hw/net/ne2000-pci.c
+++ b/hw/net/ne2000-pci.c
@@ -92,7 +92,7 @@
device_add_bootindex_property(obj, &s->c.bootindex,
"bootindex", "/ethernet-phy@0",
- &pci_dev->qdev, NULL);
+ &pci_dev->qdev);
}
static Property ne2000_properties[] = {
diff --git a/hw/net/pcnet-pci.c b/hw/net/pcnet-pci.c
index d1f31e0..49d3e42 100644
--- a/hw/net/pcnet-pci.c
+++ b/hw/net/pcnet-pci.c
@@ -250,7 +250,7 @@
device_add_bootindex_property(obj, &s->conf.bootindex,
"bootindex", "/ethernet-phy@0",
- DEVICE(obj), NULL);
+ DEVICE(obj));
}
static Property pcnet_properties[] = {
diff --git a/hw/net/rtl8139.c b/hw/net/rtl8139.c
index 70aca7e..ab93d78 100644
--- a/hw/net/rtl8139.c
+++ b/hw/net/rtl8139.c
@@ -3415,7 +3415,7 @@
device_add_bootindex_property(obj, &s->conf.bootindex,
"bootindex", "/ethernet-phy@0",
- DEVICE(obj), NULL);
+ DEVICE(obj));
}
static Property rtl8139_properties[] = {
diff --git a/hw/net/spapr_llan.c b/hw/net/spapr_llan.c
index a237702..968a1ce 100644
--- a/hw/net/spapr_llan.c
+++ b/hw/net/spapr_llan.c
@@ -340,7 +340,7 @@
device_add_bootindex_property(obj, &dev->nicconf.bootindex,
"bootindex", "",
- DEVICE(dev), NULL);
+ DEVICE(dev));
if (dev->compat_flags & SPAPRVLAN_FLAG_RX_BUF_POOLS) {
for (i = 0; i < RX_MAX_POOLS; i++) {
diff --git a/hw/net/sungem.c b/hw/net/sungem.c
index b01197d..e4b7b57 100644
--- a/hw/net/sungem.c
+++ b/hw/net/sungem.c
@@ -1378,7 +1378,7 @@
device_add_bootindex_property(obj, &s->conf.bootindex,
"bootindex", "/ethernet-phy@0",
- DEVICE(obj), NULL);
+ DEVICE(obj));
}
static Property sungem_properties[] = {
diff --git a/hw/net/sunhme.c b/hw/net/sunhme.c
index 9c38583..bc48d46 100644
--- a/hw/net/sunhme.c
+++ b/hw/net/sunhme.c
@@ -901,7 +901,7 @@
device_add_bootindex_property(obj, &s->conf.bootindex,
"bootindex", "/ethernet-phy@0",
- DEVICE(obj), NULL);
+ DEVICE(obj));
}
static void sunhme_reset(DeviceState *ds)
diff --git a/hw/net/tulip.c b/hw/net/tulip.c
index 1295f51..6cefc0a 100644
--- a/hw/net/tulip.c
+++ b/hw/net/tulip.c
@@ -1001,7 +1001,7 @@
device_add_bootindex_property(obj, &d->c.bootindex,
"bootindex", "/ethernet-phy@0",
- &pci_dev->qdev, NULL);
+ &pci_dev->qdev);
}
static Property tulip_properties[] = {
diff --git a/hw/net/virtio-net.c b/hw/net/virtio-net.c
index 3301869..b7f3d1b 100644
--- a/hw/net/virtio-net.c
+++ b/hw/net/virtio-net.c
@@ -399,7 +399,7 @@
VirtIONet *n = qemu_get_nic_opaque(nc);
if (nc->rxfilter_notify_enabled) {
- gchar *path = object_get_canonical_path(OBJECT(n->qdev));
+ char *path = object_get_canonical_path(OBJECT(n->qdev));
qapi_event_send_nic_rx_filter_changed(!!n->netclient_name,
n->netclient_name, path);
g_free(path);
@@ -3077,7 +3077,7 @@
n->qdev = dev;
}
-static void virtio_net_device_unrealize(DeviceState *dev, Error **errp)
+static void virtio_net_device_unrealize(DeviceState *dev)
{
VirtIODevice *vdev = VIRTIO_DEVICE(dev);
VirtIONet *n = VIRTIO_NET(dev);
@@ -3125,7 +3125,7 @@
n->config_size = sizeof(struct virtio_net_config);
device_add_bootindex_property(obj, &n->nic_conf.bootindex,
"bootindex", "/ethernet-phy@0",
- DEVICE(n), NULL);
+ DEVICE(n));
}
static int virtio_net_pre_save(void *opaque)
diff --git a/hw/net/vmxnet3.c b/hw/net/vmxnet3.c
index 6d91cd8..7a6ca4e 100644
--- a/hw/net/vmxnet3.c
+++ b/hw/net/vmxnet3.c
@@ -2237,7 +2237,7 @@
VMXNET3State *s = VMXNET3(obj);
device_add_bootindex_property(obj, &s->conf.bootindex,
"bootindex", "/ethernet-phy@0",
- DEVICE(obj), NULL);
+ DEVICE(obj));
}
static void vmxnet3_pci_uninit(PCIDevice *pci_dev)
diff --git a/hw/net/xilinx_axienet.c b/hw/net/xilinx_axienet.c
index 7047888..44fe04d 100644
--- a/hw/net/xilinx_axienet.c
+++ b/hw/net/xilinx_axienet.c
@@ -149,8 +149,8 @@
break;
}
- /* Unconditionally clear regs[BMCR][BMCR_RESET] */
- phy->regs[0] &= ~0x8000;
+ /* Unconditionally clear regs[BMCR][BMCR_RESET] and auto-neg */
+ phy->regs[0] &= ~0x8200;
}
static void
@@ -402,6 +402,9 @@
uint32_t hdr[CONTROL_PAYLOAD_WORDS];
+ uint8_t *txmem;
+ uint32_t txpos;
+
uint8_t *rxmem;
uint32_t rxsize;
uint32_t rxpos;
@@ -421,6 +424,7 @@
static void axienet_tx_reset(XilinxAXIEnet *s)
{
s->tc = TC_JUM | TC_TX | TC_VLAN;
+ s->txpos = 0;
}
static inline int axienet_rx_resetting(XilinxAXIEnet *s)
@@ -697,14 +701,14 @@
axienet_eth_rx_notify, s)) {
size_t ret = stream_push(s->tx_control_dev,
(void *)s->rxapp + CONTROL_PAYLOAD_SIZE
- - s->rxappsize, s->rxappsize);
+ - s->rxappsize, s->rxappsize, true);
s->rxappsize -= ret;
}
while (s->rxsize && stream_can_push(s->tx_data_dev,
axienet_eth_rx_notify, s)) {
size_t ret = stream_push(s->tx_data_dev, (void *)s->rxmem + s->rxpos,
- s->rxsize);
+ s->rxsize, true);
s->rxsize -= ret;
s->rxpos += ret;
if (!s->rxsize) {
@@ -874,12 +878,14 @@
}
static size_t
-xilinx_axienet_control_stream_push(StreamSlave *obj, uint8_t *buf, size_t len)
+xilinx_axienet_control_stream_push(StreamSlave *obj, uint8_t *buf, size_t len,
+ bool eop)
{
int i;
XilinxAXIEnetStreamSlave *cs = XILINX_AXI_ENET_CONTROL_STREAM(obj);
XilinxAXIEnet *s = cs->enet;
+ assert(eop);
if (len != CONTROL_PAYLOAD_SIZE) {
hw_error("AXI Enet requires %d byte control stream payload\n",
(int)CONTROL_PAYLOAD_SIZE);
@@ -894,7 +900,8 @@
}
static size_t
-xilinx_axienet_data_stream_push(StreamSlave *obj, uint8_t *buf, size_t size)
+xilinx_axienet_data_stream_push(StreamSlave *obj, uint8_t *buf, size_t size,
+ bool eop)
{
XilinxAXIEnetStreamSlave *ds = XILINX_AXI_ENET_DATA_STREAM(obj);
XilinxAXIEnet *s = ds->enet;
@@ -904,9 +911,30 @@
return size;
}
+ if (s->txpos + size > s->c_txmem) {
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: Packet larger than txmem\n",
+ TYPE_XILINX_AXI_ENET);
+ s->txpos = 0;
+ return size;
+ }
+
+ if (s->txpos == 0 && eop) {
+ /* Fast path single fragment. */
+ s->txpos = size;
+ } else {
+ memcpy(s->txmem + s->txpos, buf, size);
+ buf = s->txmem;
+ s->txpos += size;
+
+ if (!eop) {
+ return size;
+ }
+ }
+
/* Jumbo or vlan sizes ? */
if (!(s->tc & TC_JUM)) {
- if (size > 1518 && size <= 1522 && !(s->tc & TC_VLAN)) {
+ if (s->txpos > 1518 && s->txpos <= 1522 && !(s->tc & TC_VLAN)) {
+ s->txpos = 0;
return size;
}
}
@@ -917,8 +945,8 @@
uint32_t tmp_csum;
uint16_t csum;
- tmp_csum = net_checksum_add(size - start_off,
- (uint8_t *)buf + start_off);
+ tmp_csum = net_checksum_add(s->txpos - start_off,
+ buf + start_off);
/* Accumulate the seed. */
tmp_csum += s->hdr[2] & 0xffff;
@@ -930,12 +958,13 @@
buf[write_off + 1] = csum & 0xff;
}
- qemu_send_packet(qemu_get_queue(s->nic), buf, size);
+ qemu_send_packet(qemu_get_queue(s->nic), buf, s->txpos);
- s->stats.tx_bytes += size;
+ s->stats.tx_bytes += s->txpos;
s->regs[R_IS] |= IS_TX_COMPLETE;
enet_update_irq(s);
+ s->txpos = 0;
return size;
}
@@ -956,16 +985,11 @@
object_property_add_link(OBJECT(ds), "enet", "xlnx.axi-ethernet",
(Object **) &ds->enet,
object_property_allow_set_link,
- OBJ_PROP_LINK_STRONG,
- &local_err);
+ OBJ_PROP_LINK_STRONG);
object_property_add_link(OBJECT(cs), "enet", "xlnx.axi-ethernet",
(Object **) &cs->enet,
object_property_allow_set_link,
- OBJ_PROP_LINK_STRONG,
- &local_err);
- if (local_err) {
- goto xilinx_enet_realize_fail;
- }
+ OBJ_PROP_LINK_STRONG);
object_property_set_link(OBJECT(ds), OBJECT(s), "enet", &local_err);
object_property_set_link(OBJECT(cs), OBJECT(s), "enet", &local_err);
if (local_err) {
@@ -983,6 +1007,7 @@
s->TEMAC.parent = s;
s->rxmem = g_malloc(s->c_rxmem);
+ s->txmem = g_malloc(s->c_txmem);
return;
xilinx_enet_realize_fail:
@@ -1029,11 +1054,19 @@
dc->reset = xilinx_axienet_reset;
}
-static void xilinx_enet_stream_class_init(ObjectClass *klass, void *data)
+static void xilinx_enet_control_stream_class_init(ObjectClass *klass,
+ void *data)
{
StreamSlaveClass *ssc = STREAM_SLAVE_CLASS(klass);
- ssc->push = data;
+ ssc->push = xilinx_axienet_control_stream_push;
+}
+
+static void xilinx_enet_data_stream_class_init(ObjectClass *klass, void *data)
+{
+ StreamSlaveClass *ssc = STREAM_SLAVE_CLASS(klass);
+
+ ssc->push = xilinx_axienet_data_stream_push;
}
static const TypeInfo xilinx_enet_info = {
@@ -1048,8 +1081,7 @@
.name = TYPE_XILINX_AXI_ENET_DATA_STREAM,
.parent = TYPE_OBJECT,
.instance_size = sizeof(struct XilinxAXIEnetStreamSlave),
- .class_init = xilinx_enet_stream_class_init,
- .class_data = xilinx_axienet_data_stream_push,
+ .class_init = xilinx_enet_data_stream_class_init,
.interfaces = (InterfaceInfo[]) {
{ TYPE_STREAM_SLAVE },
{ }
@@ -1060,8 +1092,7 @@
.name = TYPE_XILINX_AXI_ENET_CONTROL_STREAM,
.parent = TYPE_OBJECT,
.instance_size = sizeof(struct XilinxAXIEnetStreamSlave),
- .class_init = xilinx_enet_stream_class_init,
- .class_data = xilinx_axienet_control_stream_push,
+ .class_init = xilinx_enet_control_stream_class_init,
.interfaces = (InterfaceInfo[]) {
{ TYPE_STREAM_SLAVE },
{ }
diff --git a/hw/nios2/10m50_devboard.c b/hw/nios2/10m50_devboard.c
index 33dc2bf..4c60a27 100644
--- a/hw/nios2/10m50_devboard.c
+++ b/hw/nios2/10m50_devboard.c
@@ -81,8 +81,7 @@
/* Register: Internal Interrupt Controller (IIC) */
dev = qdev_create(NULL, "altera,iic");
- object_property_add_const_link(OBJECT(dev), "cpu", OBJECT(cpu),
- &error_abort);
+ object_property_add_const_link(OBJECT(dev), "cpu", OBJECT(cpu));
qdev_init_nofail(dev);
sysbus_connect_irq(SYS_BUS_DEVICE(dev), 0, cpu_irq[0]);
for (i = 0; i < 32; i++) {
diff --git a/hw/nubus/nubus-device.c b/hw/nubus/nubus-device.c
index 01ccad9..ffe78a8 100644
--- a/hw/nubus/nubus-device.c
+++ b/hw/nubus/nubus-device.c
@@ -156,7 +156,7 @@
static void nubus_device_realize(DeviceState *dev, Error **errp)
{
- NubusBus *nubus = NUBUS_BUS(qdev_get_parent_bus(DEVICE(dev)));
+ NubusBus *nubus = NUBUS_BUS(qdev_get_parent_bus(dev));
NubusDevice *nd = NUBUS_DEVICE(dev);
char *name;
hwaddr slot_offset;
diff --git a/hw/nvram/fw_cfg.c b/hw/nvram/fw_cfg.c
index 4be6c9d..8dd50c2 100644
--- a/hw/nvram/fw_cfg.c
+++ b/hw/nvram/fw_cfg.c
@@ -1105,7 +1105,7 @@
}
object_property_add_child(OBJECT(qdev_get_machine()), TYPE_FW_CFG,
- OBJECT(dev), NULL);
+ OBJECT(dev));
qdev_init_nofail(dev);
sbd = SYS_BUS_DEVICE(dev);
@@ -1145,7 +1145,7 @@
}
object_property_add_child(OBJECT(qdev_get_machine()), TYPE_FW_CFG,
- OBJECT(dev), NULL);
+ OBJECT(dev));
qdev_init_nofail(dev);
sbd = SYS_BUS_DEVICE(dev);
diff --git a/hw/nvram/mac_nvram.c b/hw/nvram/mac_nvram.c
index 2e8a1e3..beec1c4 100644
--- a/hw/nvram/mac_nvram.c
+++ b/hw/nvram/mac_nvram.c
@@ -30,18 +30,9 @@
#include "migration/vmstate.h"
#include "qemu/cutils.h"
#include "qemu/module.h"
+#include "trace.h"
#include <zlib.h>
-/* debug NVR */
-//#define DEBUG_NVR
-
-#ifdef DEBUG_NVR
-#define NVR_DPRINTF(fmt, ...) \
- do { printf("NVR: " fmt , ## __VA_ARGS__); } while (0)
-#else
-#define NVR_DPRINTF(fmt, ...)
-#endif
-
#define DEF_SYSTEM_SIZE 0xc10
/* macio style NVRAM device */
@@ -51,9 +42,8 @@
MacIONVRAMState *s = opaque;
addr = (addr >> s->it_shift) & (s->size - 1);
+ trace_macio_nvram_write(addr, value);
s->data[addr] = value;
- NVR_DPRINTF("writeb addr %04" HWADDR_PRIx " val %" PRIx64 "\n",
- addr, value);
}
static uint64_t macio_nvram_readb(void *opaque, hwaddr addr,
@@ -64,8 +54,7 @@
addr = (addr >> s->it_shift) & (s->size - 1);
value = s->data[addr];
- NVR_DPRINTF("readb addr %04" HWADDR_PRIx " val %" PRIx32 "\n",
- addr, value);
+ trace_macio_nvram_read(addr, value);
return value;
}
@@ -107,7 +96,7 @@
sysbus_init_mmio(d, &s->mem);
}
-static void macio_nvram_unrealizefn(DeviceState *dev, Error **errp)
+static void macio_nvram_unrealizefn(DeviceState *dev)
{
MacIONVRAMState *s = MACIO_NVRAM(dev);
diff --git a/hw/nvram/trace-events b/hw/nvram/trace-events
index 0dea926..e023193 100644
--- a/hw/nvram/trace-events
+++ b/hw/nvram/trace-events
@@ -13,3 +13,7 @@
fw_cfg_add_i16(uint16_t key_value, const char *key_name, uint16_t value) "key 0x%04" PRIx16 " '%s', value 0x%" PRIx16
fw_cfg_add_i32(uint16_t key_value, const char *key_name, uint32_t value) "key 0x%04" PRIx16 " '%s', value 0x%" PRIx32
fw_cfg_add_i64(uint16_t key_value, const char *key_name, uint64_t value) "key 0x%04" PRIx16 " '%s', value 0x%" PRIx64
+
+# mac_nvram.c
+macio_nvram_read(uint32_t addr, uint8_t val) "read addr=0x%04"PRIx32" val=0x%02x"
+macio_nvram_write(uint32_t addr, uint8_t val) "write addr=0x%04"PRIx32" val=0x%02x"
diff --git a/hw/pci-bridge/dec.c b/hw/pci-bridge/dec.c
index 3ae2f78..952bc71 100644
--- a/hw/pci-bridge/dec.c
+++ b/hw/pci-bridge/dec.c
@@ -32,16 +32,6 @@
#include "hw/pci/pci_bridge.h"
#include "hw/pci/pci_bus.h"
-/* debug DEC */
-//#define DEBUG_DEC
-
-#ifdef DEBUG_DEC
-#define DEC_DPRINTF(fmt, ...) \
- do { printf("DEC: " fmt , ## __VA_ARGS__); } while (0)
-#else
-#define DEC_DPRINTF(fmt, ...)
-#endif
-
#define DEC_21154(obj) OBJECT_CHECK(DECState, (obj), TYPE_DEC_21154)
typedef struct DECState {
diff --git a/hw/pci-host/Kconfig b/hw/pci-host/Kconfig
index 9642c77..036a618 100644
--- a/hw/pci-host/Kconfig
+++ b/hw/pci-host/Kconfig
@@ -55,3 +55,8 @@
bool
select PCI_EXPRESS
select MSI_NONBROKEN
+
+config PCI_BONITO
+ select PCI
+ select UNIMP
+ bool
diff --git a/hw/pci-host/Makefile.objs b/hw/pci-host/Makefile.objs
index 8c87e84..e422e0a 100644
--- a/hw/pci-host/Makefile.objs
+++ b/hw/pci-host/Makefile.objs
@@ -12,7 +12,7 @@
common-obj-$(CONFIG_VERSATILE_PCI) += versatile.o
common-obj-$(CONFIG_PCI_SABRE) += sabre.o
-common-obj-$(CONFIG_FULONG) += bonito.o
+common-obj-$(CONFIG_PCI_BONITO) += bonito.o
common-obj-$(CONFIG_PCI_I440FX) += i440fx.o
common-obj-$(CONFIG_XEN_IGD_PASSTHROUGH) += xen_igd_pt.o
common-obj-$(CONFIG_PCI_EXPRESS_Q35) += q35.o
diff --git a/hw/pci-host/bonito.c b/hw/pci-host/bonito.c
index cc6545c..f9697dc 100644
--- a/hw/pci-host/bonito.c
+++ b/hw/pci-host/bonito.c
@@ -11,7 +11,7 @@
*/
/*
- * fulong 2e mini pc has a bonito north bridge.
+ * fuloong 2e mini pc has a bonito north bridge.
*/
/*
@@ -39,6 +39,7 @@
*/
#include "qemu/osdep.h"
+#include "qemu/units.h"
#include "qemu/error-report.h"
#include "hw/pci/pci.h"
#include "hw/irq.h"
@@ -48,6 +49,8 @@
#include "sysemu/reset.h"
#include "sysemu/runstate.h"
#include "exec/address-spaces.h"
+#include "hw/misc/unimp.h"
+#include "hw/registerfields.h"
/* #define DEBUG_BONITO */
@@ -81,7 +84,7 @@
#define BONITO_PCILO1_BASE 0x14000000
#define BONITO_PCILO2_BASE 0x18000000
#define BONITO_PCIHI_BASE 0x20000000
-#define BONITO_PCIHI_SIZE 0x20000000
+#define BONITO_PCIHI_SIZE 0x60000000
#define BONITO_PCIHI_TOP (BONITO_PCIHI_BASE + BONITO_PCIHI_SIZE - 1)
#define BONITO_PCIIO_BASE 0x1fd00000
#define BONITO_PCIIO_BASE_VA 0xbfd00000
@@ -110,8 +113,19 @@
/* Power on register */
#define BONITO_BONPONCFG (0x00 >> 2) /* 0x100 */
+
+/* PCI configuration register */
#define BONITO_BONGENCFG_OFFSET 0x4
#define BONITO_BONGENCFG (BONITO_BONGENCFG_OFFSET >> 2) /*0x104 */
+REG32(BONGENCFG, 0x104)
+FIELD(BONGENCFG, DEBUGMODE, 0, 1)
+FIELD(BONGENCFG, SNOOP, 1, 1)
+FIELD(BONGENCFG, CPUSELFRESET, 2, 1)
+FIELD(BONGENCFG, BYTESWAP, 6, 1)
+FIELD(BONGENCFG, UNCACHED, 7, 1)
+FIELD(BONGENCFG, PREFETCH, 8, 1)
+FIELD(BONGENCFG, WRITEBEHIND, 9, 1)
+FIELD(BONGENCFG, PCIQUEUE, 12, 1)
/* 2. IO & IDE configuration */
#define BONITO_IODEVCFG (0x08 >> 2) /* 0x108 */
@@ -239,7 +253,7 @@
saddr = addr >> 2;
- DPRINTF("bonito_writel "TARGET_FMT_plx" val %x saddr %x\n",
+ DPRINTF("bonito_writel "TARGET_FMT_plx" val %lx saddr %x\n",
addr, val, saddr);
switch (saddr) {
case BONITO_BONPONCFG:
@@ -327,7 +341,7 @@
PCIBonitoState *s = opaque;
PCIDevice *d = PCI_DEVICE(s);
- DPRINTF("bonito_pciconf_writel "TARGET_FMT_plx" val %x\n", addr, val);
+ DPRINTF("bonito_pciconf_writel "TARGET_FMT_plx" val %lx\n", addr, val);
d->config_write(d, addr, val, 4);
}
@@ -474,7 +488,7 @@
uint32_t pciaddr;
uint16_t status;
- DPRINTF("bonito_spciconf_write "TARGET_FMT_plx" size %d val %x\n",
+ DPRINTF("bonito_spciconf_write "TARGET_FMT_plx" size %d val %lx\n",
addr, size, val);
pciaddr = bonito_sbridge_pciaddr(s, addr);
@@ -559,11 +573,11 @@
slot = (pci_dev->devfn >> 3);
switch (slot) {
- case 5: /* FULONG2E_VIA_SLOT, SouthBridge, IDE, USB, ACPI, AC97, MC97 */
+ case 5: /* FULOONG2E_VIA_SLOT, SouthBridge, IDE, USB, ACPI, AC97, MC97 */
return irq_num % 4 + BONITO_IRQ_BASE;
- case 6: /* FULONG2E_ATI_SLOT, VGA */
+ case 6: /* FULOONG2E_ATI_SLOT, VGA */
return 4 + BONITO_IRQ_BASE;
- case 7: /* FULONG2E_RTL_SLOT, RTL8139 */
+ case 7: /* FULOONG2E_RTL_SLOT, RTL8139 */
return 5 + BONITO_IRQ_BASE;
case 8 ... 12: /* PCI slot 1 to 4 */
return (slot - 8 + irq_num) + 6 + BONITO_IRQ_BASE;
@@ -575,11 +589,18 @@
static void bonito_reset(void *opaque)
{
PCIBonitoState *s = opaque;
+ uint32_t val = 0;
/* set the default value of north bridge registers */
s->regs[BONITO_BONPONCFG] = 0xc40;
- s->regs[BONITO_BONGENCFG] = 0x1384;
+ val = FIELD_DP32(val, BONGENCFG, PCIQUEUE, 1);
+ val = FIELD_DP32(val, BONGENCFG, WRITEBEHIND, 1);
+ val = FIELD_DP32(val, BONGENCFG, PREFETCH, 1);
+ val = FIELD_DP32(val, BONGENCFG, UNCACHED, 1);
+ val = FIELD_DP32(val, BONGENCFG, CPUSELFRESET, 1);
+ s->regs[BONITO_BONGENCFG] = val;
+
s->regs[BONITO_IODEVCFG] = 0x2bff8010;
s->regs[BONITO_SDCFG] = 0x255e0091;
@@ -604,14 +625,26 @@
{
PCIHostState *phb = PCI_HOST_BRIDGE(dev);
BonitoState *bs = BONITO_PCI_HOST_BRIDGE(dev);
+ MemoryRegion *pcimem_lo_alias = g_new(MemoryRegion, 3);
- memory_region_init(&bs->pci_mem, OBJECT(dev), "pci.mem", BONITO_PCILO_SIZE);
- phb->bus = pci_register_root_bus(DEVICE(dev), "pci",
+ memory_region_init(&bs->pci_mem, OBJECT(dev), "pci.mem", BONITO_PCIHI_SIZE);
+ phb->bus = pci_register_root_bus(dev, "pci",
pci_bonito_set_irq, pci_bonito_map_irq,
dev, &bs->pci_mem, get_system_io(),
0x28, 32, TYPE_PCI_BUS);
- memory_region_add_subregion(get_system_memory(), BONITO_PCILO_BASE,
- &bs->pci_mem);
+
+ for (size_t i = 0; i < 3; i++) {
+ char *name = g_strdup_printf("pci.lomem%zu", i);
+
+ memory_region_init_alias(&pcimem_lo_alias[i], NULL, name,
+ &bs->pci_mem, i * 64 * MiB, 64 * MiB);
+ memory_region_add_subregion(get_system_memory(),
+ BONITO_PCILO_BASE + i * 64 * MiB,
+ &pcimem_lo_alias[i]);
+ g_free(name);
+ }
+
+ create_unimplemented_device("pci.io", BONITO_PCIIO_BASE, 1 * MiB);
}
static void bonito_realize(PCIDevice *dev, Error **errp)
@@ -619,6 +652,8 @@
PCIBonitoState *s = PCI_BONITO(dev);
SysBusDevice *sysbus = SYS_BUS_DEVICE(s->pcihost);
PCIHostState *phb = PCI_HOST_BRIDGE(s->pcihost);
+ BonitoState *bs = BONITO_PCI_HOST_BRIDGE(s->pcihost);
+ MemoryRegion *pcimem_alias = g_new(MemoryRegion, 1);
/*
* Bonito North Bridge, built on FPGA,
@@ -644,15 +679,20 @@
sysbus_init_mmio(sysbus, &phb->data_mem);
sysbus_mmio_map(sysbus, 2, BONITO_SPCICONFIG_BASE);
+ create_unimplemented_device("bonito", BONITO_REG_BASE, BONITO_REG_SIZE);
+
memory_region_init_io(&s->iomem_ldma, OBJECT(s), &bonito_ldma_ops, s,
"ldma", 0x100);
sysbus_init_mmio(sysbus, &s->iomem_ldma);
- sysbus_mmio_map(sysbus, 3, 0xbfe00200);
+ sysbus_mmio_map(sysbus, 3, 0x1fe00200);
+ /* PCI copier */
memory_region_init_io(&s->iomem_cop, OBJECT(s), &bonito_cop_ops, s,
"cop", 0x100);
sysbus_init_mmio(sysbus, &s->iomem_cop);
- sysbus_mmio_map(sysbus, 4, 0xbfe00300);
+ sysbus_mmio_map(sysbus, 4, 0x1fe00300);
+
+ create_unimplemented_device("ROMCS", BONITO_FLASH_BASE, 60 * MiB);
/* Map PCI IO Space 0x1fd0 0000 - 0x1fd1 0000 */
memory_region_init_alias(&s->bonito_pciio, OBJECT(s), "isa_mmio",
@@ -661,10 +701,25 @@
sysbus_mmio_map(sysbus, 5, BONITO_PCIIO_BASE);
/* add pci local io mapping */
- memory_region_init_alias(&s->bonito_localio, OBJECT(s), "isa_mmio",
- get_system_io(), 0, BONITO_DEV_SIZE);
+
+ memory_region_init_alias(&s->bonito_localio, OBJECT(s), "IOCS[0]",
+ get_system_io(), 0, 256 * KiB);
sysbus_init_mmio(sysbus, &s->bonito_localio);
sysbus_mmio_map(sysbus, 6, BONITO_DEV_BASE);
+ create_unimplemented_device("IOCS[1]", BONITO_DEV_BASE + 1 * 256 * KiB,
+ 256 * KiB);
+ create_unimplemented_device("IOCS[2]", BONITO_DEV_BASE + 2 * 256 * KiB,
+ 256 * KiB);
+ create_unimplemented_device("IOCS[3]", BONITO_DEV_BASE + 3 * 256 * KiB,
+ 256 * KiB);
+
+ memory_region_init_alias(pcimem_alias, NULL, "pci.mem.alias",
+ &bs->pci_mem, 0, BONITO_PCIHI_SIZE);
+ memory_region_add_subregion(get_system_memory(),
+ BONITO_PCIHI_BASE, pcimem_alias);
+ create_unimplemented_device("PCI_2",
+ (hwaddr)BONITO_PCIHI_BASE + BONITO_PCIHI_SIZE,
+ 2 * GiB);
/* set the default value of north bridge pci config */
pci_set_word(dev->config + PCI_COMMAND, 0x0000);
diff --git a/hw/pci-host/grackle.c b/hw/pci-host/grackle.c
index 24ccdf6..4b3af0c 100644
--- a/hw/pci-host/grackle.c
+++ b/hw/pci-host/grackle.c
@@ -109,7 +109,7 @@
object_property_add_link(obj, "pic", TYPE_HEATHROW,
(Object **) &s->pic,
qdev_prop_allow_set_link_before_realize,
- 0, NULL);
+ 0);
sysbus_init_mmio(sbd, &phb->conf_mem);
sysbus_init_mmio(sbd, &phb->data_mem);
diff --git a/hw/pci-host/i440fx.c b/hw/pci-host/i440fx.c
index d980c97..0adbd77 100644
--- a/hw/pci-host/i440fx.c
+++ b/hw/pci-host/i440fx.c
@@ -212,19 +212,19 @@
object_property_add(obj, PCI_HOST_PROP_PCI_HOLE_START, "uint32",
i440fx_pcihost_get_pci_hole_start,
- NULL, NULL, NULL, NULL);
+ NULL, NULL, NULL);
object_property_add(obj, PCI_HOST_PROP_PCI_HOLE_END, "uint32",
i440fx_pcihost_get_pci_hole_end,
- NULL, NULL, NULL, NULL);
+ NULL, NULL, NULL);
object_property_add(obj, PCI_HOST_PROP_PCI_HOLE64_START, "uint64",
i440fx_pcihost_get_pci_hole64_start,
- NULL, NULL, NULL, NULL);
+ NULL, NULL, NULL);
object_property_add(obj, PCI_HOST_PROP_PCI_HOLE64_END, "uint64",
i440fx_pcihost_get_pci_hole64_end,
- NULL, NULL, NULL, NULL);
+ NULL, NULL, NULL);
}
static void i440fx_pcihost_realize(DeviceState *dev, Error **errp)
@@ -275,7 +275,7 @@
b = pci_root_bus_new(dev, NULL, pci_address_space,
address_space_io, 0, TYPE_PCI_BUS);
s->bus = b;
- object_property_add_child(qdev_get_machine(), "i440fx", OBJECT(dev), NULL);
+ object_property_add_child(qdev_get_machine(), "i440fx", OBJECT(dev));
qdev_init_nofail(dev);
d = pci_create_simple(b, 0, pci_type);
@@ -308,7 +308,7 @@
memory_region_set_enabled(&f->low_smram, true);
memory_region_add_subregion(&f->smram, 0xa0000, &f->low_smram);
object_property_add_const_link(qdev_get_machine(), "smram",
- OBJECT(&f->smram), &error_abort);
+ OBJECT(&f->smram));
init_pam(dev, f->ram_memory, f->system_memory, f->pci_address_space,
&f->pam_regions[0], PAM_BIOS_BASE, PAM_BIOS_SIZE);
diff --git a/hw/pci-host/pnv_phb3_msi.c b/hw/pci-host/pnv_phb3_msi.c
index d645468..099d209 100644
--- a/hw/pci-host/pnv_phb3_msi.c
+++ b/hw/pci-host/pnv_phb3_msi.c
@@ -282,8 +282,7 @@
object_property_add_link(obj, "phb", TYPE_PNV_PHB3,
(Object **)&msi->phb,
object_property_allow_set_link,
- OBJ_PROP_LINK_STRONG,
- &error_abort);
+ OBJ_PROP_LINK_STRONG);
/* Will be overriden later */
ics->offset = 0;
diff --git a/hw/pci-host/pnv_phb3_pbcq.c b/hw/pci-host/pnv_phb3_pbcq.c
index 7b9a121..a0526aa 100644
--- a/hw/pci-host/pnv_phb3_pbcq.c
+++ b/hw/pci-host/pnv_phb3_pbcq.c
@@ -324,8 +324,7 @@
object_property_add_link(obj, "phb", TYPE_PNV_PHB3,
(Object **)&pbcq->phb,
object_property_allow_set_link,
- OBJ_PROP_LINK_STRONG,
- &error_abort);
+ OBJ_PROP_LINK_STRONG);
}
static void pnv_pbcq_class_init(ObjectClass *klass, void *data)
diff --git a/hw/pci-host/q35.c b/hw/pci-host/q35.c
index 2bbc90b..352aeec 100644
--- a/hw/pci-host/q35.c
+++ b/hw/pci-host/q35.c
@@ -222,38 +222,38 @@
Q35_PCI_HOST_HOLE64_SIZE_DEFAULT);
object_property_add(obj, PCI_HOST_PROP_PCI_HOLE_START, "uint32",
q35_host_get_pci_hole_start,
- NULL, NULL, NULL, NULL);
+ NULL, NULL, NULL);
object_property_add(obj, PCI_HOST_PROP_PCI_HOLE_END, "uint32",
q35_host_get_pci_hole_end,
- NULL, NULL, NULL, NULL);
+ NULL, NULL, NULL);
object_property_add(obj, PCI_HOST_PROP_PCI_HOLE64_START, "uint64",
q35_host_get_pci_hole64_start,
- NULL, NULL, NULL, NULL);
+ NULL, NULL, NULL);
object_property_add(obj, PCI_HOST_PROP_PCI_HOLE64_END, "uint64",
q35_host_get_pci_hole64_end,
- NULL, NULL, NULL, NULL);
+ NULL, NULL, NULL);
object_property_add_uint64_ptr(obj, PCIE_HOST_MCFG_SIZE,
- &pehb->size, OBJ_PROP_FLAG_READ, NULL);
+ &pehb->size, OBJ_PROP_FLAG_READ);
object_property_add_link(obj, MCH_HOST_PROP_RAM_MEM, TYPE_MEMORY_REGION,
(Object **) &s->mch.ram_memory,
- qdev_prop_allow_set_link_before_realize, 0, NULL);
+ qdev_prop_allow_set_link_before_realize, 0);
object_property_add_link(obj, MCH_HOST_PROP_PCI_MEM, TYPE_MEMORY_REGION,
(Object **) &s->mch.pci_address_space,
- qdev_prop_allow_set_link_before_realize, 0, NULL);
+ qdev_prop_allow_set_link_before_realize, 0);
object_property_add_link(obj, MCH_HOST_PROP_SYSTEM_MEM, TYPE_MEMORY_REGION,
(Object **) &s->mch.system_memory,
- qdev_prop_allow_set_link_before_realize, 0, NULL);
+ qdev_prop_allow_set_link_before_realize, 0);
object_property_add_link(obj, MCH_HOST_PROP_IO_MEM, TYPE_MEMORY_REGION,
(Object **) &s->mch.address_space_io,
- qdev_prop_allow_set_link_before_realize, 0, NULL);
+ qdev_prop_allow_set_link_before_realize, 0);
}
static const TypeInfo q35_host_info = {
@@ -638,7 +638,7 @@
&mch->smbase_window);
object_property_add_const_link(qdev_get_machine(), "smram",
- OBJECT(&mch->smram), &error_abort);
+ OBJECT(&mch->smram));
init_pam(DEVICE(mch), mch->ram_memory, mch->system_memory,
mch->pci_address_space, &mch->pam_regions[0],
diff --git a/hw/pci-host/sabre.c b/hw/pci-host/sabre.c
index 2b8503b..475bcb0 100644
--- a/hw/pci-host/sabre.c
+++ b/hw/pci-host/sabre.c
@@ -442,7 +442,7 @@
object_property_add_link(obj, "iommu", TYPE_SUN4U_IOMMU,
(Object **) &s->iommu,
qdev_prop_allow_set_link_before_realize,
- 0, NULL);
+ 0);
/* sabre_config */
memory_region_init_io(&s->sabre_config, OBJECT(s), &sabre_config_ops, s,
diff --git a/hw/pci-host/uninorth.c b/hw/pci-host/uninorth.c
index cf70b76..1ed1072 100644
--- a/hw/pci-host/uninorth.c
+++ b/hw/pci-host/uninorth.c
@@ -175,7 +175,7 @@
object_property_add_link(obj, "pic", TYPE_OPENPIC,
(Object **) &s->pic,
qdev_prop_allow_set_link_before_realize,
- 0, NULL);
+ 0);
sysbus_init_mmio(sbd, &h->conf_mem);
sysbus_init_mmio(sbd, &h->data_mem);
@@ -223,7 +223,7 @@
object_property_add_link(obj, "pic", TYPE_OPENPIC,
(Object **) &s->pic,
qdev_prop_allow_set_link_before_realize,
- 0, NULL);
+ 0);
sysbus_init_mmio(sbd, &h->conf_mem);
sysbus_init_mmio(sbd, &h->data_mem);
@@ -262,7 +262,7 @@
object_property_add_link(obj, "pic", TYPE_OPENPIC,
(Object **) &s->pic,
qdev_prop_allow_set_link_before_realize,
- 0, NULL);
+ 0);
sysbus_init_mmio(sbd, &h->conf_mem);
sysbus_init_mmio(sbd, &h->data_mem);
@@ -299,7 +299,7 @@
object_property_add_link(obj, "pic", TYPE_OPENPIC,
(Object **) &s->pic,
qdev_prop_allow_set_link_before_realize,
- 0, NULL);
+ 0);
sysbus_init_mmio(sbd, &h->conf_mem);
sysbus_init_mmio(sbd, &h->data_mem);
diff --git a/hw/pci/pci.c b/hw/pci/pci.c
index b5bc842..70c6696 100644
--- a/hw/pci/pci.c
+++ b/hw/pci/pci.c
@@ -146,7 +146,7 @@
}
}
-static void pci_bus_unrealize(BusState *qbus, Error **errp)
+static void pci_bus_unrealize(BusState *qbus)
{
PCIBus *bus = PCI_BUS(qbus);
@@ -456,7 +456,7 @@
{
pci_bus_uninit(bus);
/* the caller of the unplug hotplug handler will delete this device */
- object_property_set_bool(OBJECT(bus), false, "realized", NULL);
+ object_property_set_bool(OBJECT(bus), false, "realized", &error_abort);
}
void pci_bus_irqs(PCIBus *bus, pci_set_irq_fn set_irq, pci_map_irq_fn map_irq,
@@ -1118,7 +1118,7 @@
pci_unregister_vga(pci_dev);
}
-static void pci_qdev_unrealize(DeviceState *dev, Error **errp)
+static void pci_qdev_unrealize(DeviceState *dev)
{
PCIDevice *pci_dev = PCI_DEVICE(dev);
PCIDeviceClass *pc = PCI_DEVICE_GET_CLASS(pci_dev);
@@ -2108,7 +2108,7 @@
error_setg(errp, "failover primary device must be on "
"PCIExpress bus");
error_propagate(errp, local_err);
- pci_qdev_unrealize(DEVICE(pci_dev), NULL);
+ pci_qdev_unrealize(DEVICE(pci_dev));
return;
}
class_id = pci_get_word(pci_dev->config + PCI_CLASS_DEVICE);
@@ -2116,7 +2116,7 @@
error_setg(errp, "failover primary device is not an "
"Ethernet device");
error_propagate(errp, local_err);
- pci_qdev_unrealize(DEVICE(pci_dev), NULL);
+ pci_qdev_unrealize(DEVICE(pci_dev));
return;
}
if (!(pci_dev->cap_present & QEMU_PCI_CAP_MULTIFUNCTION)
@@ -2126,7 +2126,7 @@
error_setg(errp, "failover: primary device must be in its own "
"PCI slot");
error_propagate(errp, local_err);
- pci_qdev_unrealize(DEVICE(pci_dev), NULL);
+ pci_qdev_unrealize(DEVICE(pci_dev));
return;
}
qdev->allow_unplug_during_migration = true;
@@ -2142,7 +2142,7 @@
pci_add_option_rom(pci_dev, is_default_rom, &local_err);
if (local_err) {
error_propagate(errp, local_err);
- pci_qdev_unrealize(DEVICE(pci_dev), NULL);
+ pci_qdev_unrealize(DEVICE(pci_dev));
return;
}
}
diff --git a/hw/pci/pcie.c b/hw/pci/pcie.c
index abc99b6..f50e10b 100644
--- a/hw/pci/pcie.c
+++ b/hw/pci/pcie.c
@@ -457,7 +457,7 @@
void pcie_cap_slot_unplug_cb(HotplugHandler *hotplug_dev, DeviceState *dev,
Error **errp)
{
- object_property_set_bool(OBJECT(dev), false, "realized", NULL);
+ object_property_set_bool(OBJECT(dev), false, "realized", &error_abort);
}
static void pcie_unplug_device(PCIBus *bus, PCIDevice *dev, void *opaque)
diff --git a/hw/pci/shpc.c b/hw/pci/shpc.c
index 7f0aa28..b76d3d2 100644
--- a/hw/pci/shpc.c
+++ b/hw/pci/shpc.c
@@ -547,7 +547,7 @@
void shpc_device_unplug_cb(HotplugHandler *hotplug_dev, DeviceState *dev,
Error **errp)
{
- object_property_set_bool(OBJECT(dev), false, "realized", NULL);
+ object_property_set_bool(OBJECT(dev), false, "realized", &error_abort);
}
void shpc_device_unplug_request_cb(HotplugHandler *hotplug_dev,
diff --git a/hw/pcmcia/pxa2xx.c b/hw/pcmcia/pxa2xx.c
index 14e4dfe..8667244 100644
--- a/hw/pcmcia/pxa2xx.c
+++ b/hw/pcmcia/pxa2xx.c
@@ -189,7 +189,7 @@
object_property_add_link(obj, "card", TYPE_PCMCIA_CARD,
(Object **)&s->card,
NULL, /* read-only property */
- 0, NULL);
+ 0);
}
/* Insert a new card into a slot */
diff --git a/hw/ppc/e500.c b/hw/ppc/e500.c
index 0d1f411..2a0b66a 100644
--- a/hw/ppc/e500.c
+++ b/hw/ppc/e500.c
@@ -744,8 +744,7 @@
const PPCE500MachineClass *pmc = PPCE500_MACHINE_GET_CLASS(pms);
dev = qdev_create(NULL, TYPE_OPENPIC);
- object_property_add_child(OBJECT(machine), "pic", OBJECT(dev),
- &error_fatal);
+ object_property_add_child(OBJECT(machine), "pic", OBJECT(dev));
qdev_prop_set_uint32(dev, "model", pmc->mpic_version);
qdev_prop_set_uint32(dev, "nb_cpus", smp_cpus);
@@ -916,7 +915,7 @@
dev = qdev_create(NULL, "e500-ccsr");
object_property_add_child(qdev_get_machine(), "e500-ccsr",
- OBJECT(dev), NULL);
+ OBJECT(dev));
qdev_init_nofail(dev);
ccsr = CCSR(dev);
ccsr_addr_space = &ccsr->ccsr_space;
@@ -957,8 +956,7 @@
/* PCI */
dev = qdev_create(NULL, "e500-pcihost");
- object_property_add_child(qdev_get_machine(), "pci-host", OBJECT(dev),
- &error_abort);
+ object_property_add_child(qdev_get_machine(), "pci-host", OBJECT(dev));
qdev_prop_set_uint32(dev, "first_slot", pmc->pci_first_slot);
qdev_prop_set_uint32(dev, "first_pin_irq", pci_irq_nrs[0]);
qdev_init_nofail(dev);
diff --git a/hw/ppc/mac_newworld.c b/hw/ppc/mac_newworld.c
index 428cf63..3507f26 100644
--- a/hw/ppc/mac_newworld.c
+++ b/hw/ppc/mac_newworld.c
@@ -455,7 +455,7 @@
qdev_prop_set_uint32(dev, "data_width", 1);
qdev_prop_set_bit(dev, "dma_enabled", false);
object_property_add_child(OBJECT(qdev_get_machine()), TYPE_FW_CFG,
- OBJECT(fw_cfg), NULL);
+ OBJECT(fw_cfg));
qdev_init_nofail(dev);
s = SYS_BUS_DEVICE(dev);
sysbus_mmio_map(s, 0, CFG_ADDR);
@@ -628,11 +628,10 @@
/* Default via_config is CORE99_VIA_CONFIG_CUDA */
cms->via_config = CORE99_VIA_CONFIG_CUDA;
object_property_add_str(obj, "via", core99_get_via_config,
- core99_set_via_config, NULL);
+ core99_set_via_config);
object_property_set_description(obj, "via",
"Set VIA configuration. "
- "Valid values are cuda, pmu and pmu-adb",
- NULL);
+ "Valid values are cuda, pmu and pmu-adb");
return;
}
diff --git a/hw/ppc/mac_oldworld.c b/hw/ppc/mac_oldworld.c
index 101bdc5..0b4c1c6 100644
--- a/hw/ppc/mac_oldworld.c
+++ b/hw/ppc/mac_oldworld.c
@@ -314,7 +314,7 @@
qdev_prop_set_uint32(dev, "data_width", 1);
qdev_prop_set_bit(dev, "dma_enabled", false);
object_property_add_child(OBJECT(qdev_get_machine()), TYPE_FW_CFG,
- OBJECT(fw_cfg), NULL);
+ OBJECT(fw_cfg));
qdev_init_nofail(dev);
s = SYS_BUS_DEVICE(dev);
sysbus_mmio_map(s, 0, CFG_ADDR);
diff --git a/hw/ppc/pnv.c b/hw/ppc/pnv.c
index a3b7a8d..806a5d9 100644
--- a/hw/ppc/pnv.c
+++ b/hw/ppc/pnv.c
@@ -832,7 +832,7 @@
}
snprintf(chip_name, sizeof(chip_name), "chip[%d]", PNV_CHIP_HWID(i));
- object_property_add_child(OBJECT(pnv), chip_name, chip, &error_fatal);
+ object_property_add_child(OBJECT(pnv), chip_name, chip);
object_property_set_int(chip, PNV_CHIP_HWID(i), "chip-id",
&error_fatal);
object_property_set_int(chip, machine->smp.cores,
@@ -1060,8 +1060,7 @@
object_property_add_link(obj, "xics", TYPE_XICS_FABRIC,
(Object **)&chip8->xics,
object_property_allow_set_link,
- OBJ_PROP_LINK_STRONG,
- &error_abort);
+ OBJ_PROP_LINK_STRONG);
object_initialize_child(obj, "psi", &chip8->psi, sizeof(chip8->psi),
TYPE_PNV8_PSI, &error_abort, NULL);
@@ -1321,7 +1320,7 @@
object_initialize_child(obj, "xive", &chip9->xive, sizeof(chip9->xive),
TYPE_PNV_XIVE, &error_abort, NULL);
object_property_add_alias(obj, "xive-fabric", OBJECT(&chip9->xive),
- "xive-fabric", &error_abort);
+ "xive-fabric");
object_initialize_child(obj, "psi", &chip9->psi, sizeof(chip9->psi),
TYPE_PNV9_PSI, &error_abort, NULL);
@@ -1739,8 +1738,7 @@
pnv_core = PNV_CORE(object_new(typename));
snprintf(core_name, sizeof(core_name), "core[%d]", core_hwid);
- object_property_add_child(OBJECT(chip), core_name, OBJECT(pnv_core),
- &error_abort);
+ object_property_add_child(OBJECT(chip), core_name, OBJECT(pnv_core));
chip->cores[i] = pnv_core;
object_property_set_int(OBJECT(pnv_core), chip->nr_threads,
"nr-threads", &error_fatal);
@@ -1986,12 +1984,26 @@
cpu_synchronize_state(cs);
ppc_cpu_do_system_reset(cs);
- /*
- * SRR1[42:45] is set to 0100 which the ISA defines as implementation
- * dependent. POWER processors use this for xscom triggered interrupts,
- * which come from the BMC or NMI IPIs.
- */
- env->spr[SPR_SRR1] |= PPC_BIT(43);
+ if (env->spr[SPR_SRR1] & SRR1_WAKESTATE) {
+ /*
+ * Power-save wakeups, as indicated by non-zero SRR1[46:47] put the
+ * wakeup reason in SRR1[42:45], system reset is indicated with 0b0100
+ * (PPC_BIT(43)).
+ */
+ if (!(env->spr[SPR_SRR1] & SRR1_WAKERESET)) {
+ warn_report("ppc_cpu_do_system_reset does not set system reset wakeup reason");
+ env->spr[SPR_SRR1] |= SRR1_WAKERESET;
+ }
+ } else {
+ /*
+ * For non-powersave system resets, SRR1[42:45] are defined to be
+ * implementation-dependent. The POWER9 User Manual specifies that
+ * an external (SCOM driven, which may come from a BMC nmi command or
+ * another CPU requesting a NMI IPI) system reset exception should be
+ * 0b0010 (PPC_BIT(44)).
+ */
+ env->spr[SPR_SRR1] |= SRR1_WAKESCOM;
+ }
}
static void pnv_nmi(NMIState *n, int cpu_index, Error **errp)
@@ -2027,11 +2039,9 @@
nc->nmi_monitor_handler = pnv_nmi;
object_class_property_add_bool(oc, "hb-mode",
- pnv_machine_get_hb, pnv_machine_set_hb,
- &error_abort);
+ pnv_machine_get_hb, pnv_machine_set_hb);
object_class_property_set_description(oc, "hb-mode",
- "Use a hostboot like boot loader",
- NULL);
+ "Use a hostboot like boot loader");
}
#define DEFINE_PNV8_CHIP_TYPE(type, class_initfn) \
diff --git a/hw/ppc/pnv_bmc.c b/hw/ppc/pnv_bmc.c
index 4e018b8..5f86453 100644
--- a/hw/ppc/pnv_bmc.c
+++ b/hw/ppc/pnv_bmc.c
@@ -217,8 +217,7 @@
void pnv_bmc_set_pnor(IPMIBmc *bmc, PnvPnor *pnor)
{
object_ref(OBJECT(pnor));
- object_property_add_const_link(OBJECT(bmc), "pnor", OBJECT(pnor),
- &error_abort);
+ object_property_add_const_link(OBJECT(bmc), "pnor", OBJECT(pnor));
/* Install the HIOMAP protocol handlers to access the PNOR */
ipmi_sim_register_netfn(IPMI_BMC_SIMULATOR(bmc), IPMI_NETFN_OEM,
@@ -235,7 +234,7 @@
obj = object_new(TYPE_IPMI_BMC_SIMULATOR);
object_ref(OBJECT(pnor));
- object_property_add_const_link(obj, "pnor", OBJECT(pnor), &error_abort);
+ object_property_add_const_link(obj, "pnor", OBJECT(pnor));
object_property_set_bool(obj, true, "realized", &error_fatal);
/* Install the HIOMAP protocol handlers to access the PNOR */
diff --git a/hw/ppc/pnv_core.c b/hw/ppc/pnv_core.c
index 2345620..96a446f 100644
--- a/hw/ppc/pnv_core.c
+++ b/hw/ppc/pnv_core.c
@@ -232,7 +232,7 @@
pc->threads[i] = POWERPC_CPU(obj);
snprintf(name, sizeof(name), "thread[%d]", i);
- object_property_add_child(OBJECT(pc), name, obj, &error_abort);
+ object_property_add_child(OBJECT(pc), name, obj);
cpu->machine_data = g_new0(PnvCPUState, 1);
@@ -275,7 +275,7 @@
object_unparent(OBJECT(cpu));
}
-static void pnv_core_unrealize(DeviceState *dev, Error **errp)
+static void pnv_core_unrealize(DeviceState *dev)
{
PnvCore *pc = PNV_CORE(dev);
CPUCore *cc = CPU_CORE(dev);
diff --git a/hw/ppc/pnv_psi.c b/hw/ppc/pnv_psi.c
index c34a49b..cfd5b7b 100644
--- a/hw/ppc/pnv_psi.c
+++ b/hw/ppc/pnv_psi.c
@@ -486,7 +486,7 @@
object_initialize_child(obj, "ics-psi", &psi8->ics, sizeof(psi8->ics),
TYPE_ICS, &error_abort, NULL);
object_property_add_alias(obj, ICS_PROP_XICS, OBJECT(&psi8->ics),
- ICS_PROP_XICS, &error_abort);
+ ICS_PROP_XICS);
}
static const uint8_t irq_to_xivr[] = {
diff --git a/hw/ppc/prep.c b/hw/ppc/prep.c
index 44be9d2..9266453 100644
--- a/hw/ppc/prep.c
+++ b/hw/ppc/prep.c
@@ -229,7 +229,7 @@
rtc_set_memory(rtc, 0x3f, checksum >> 8);
object_property_add_alias(qdev_get_machine(), "rtc-time", OBJECT(rtc),
- "date", NULL);
+ "date");
}
return 0;
}
@@ -275,7 +275,7 @@
qdev_prop_set_string(dev, "bios-name", bios_name);
qdev_prop_set_uint32(dev, "elf-machine", PPC_ELF_MACHINE);
pcihost = SYS_BUS_DEVICE(dev);
- object_property_add_child(qdev_get_machine(), "raven", OBJECT(dev), NULL);
+ object_property_add_child(qdev_get_machine(), "raven", OBJECT(dev));
qdev_init_nofail(dev);
pci_bus = PCI_BUS(qdev_get_child_bus(dev, "pci.0"));
if (!pci_bus) {
@@ -343,7 +343,7 @@
qdev_prop_set_uint32(dev, "data_width", 1);
qdev_prop_set_bit(dev, "dma_enabled", false);
object_property_add_child(OBJECT(qdev_get_machine()), TYPE_FW_CFG,
- OBJECT(fw_cfg), NULL);
+ OBJECT(fw_cfg));
qdev_init_nofail(dev);
s = SYS_BUS_DEVICE(dev);
sysbus_mmio_map(s, 0, CFG_ADDR);
diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c
index c18eab0..3b1a5ed 100644
--- a/hw/ppc/spapr.c
+++ b/hw/ppc/spapr.c
@@ -445,7 +445,8 @@
g_assert(drc);
elem = spapr_get_drconf_cell(size / lmb_size, addr,
spapr_drc_index(drc), node,
- SPAPR_LMB_FLAGS_ASSIGNED);
+ (SPAPR_LMB_FLAGS_ASSIGNED |
+ SPAPR_LMB_FLAGS_HOTREMOVABLE));
QSIMPLEQ_INSERT_TAIL(&drconf_queue, elem, entry);
nr_entries++;
cur_addr = addr + size;
@@ -1732,7 +1733,7 @@
object_property_set_bool(OBJECT(&spapr->rtc), true, "realized",
&error_fatal);
object_property_add_alias(OBJECT(spapr), "rtc-time", OBJECT(&spapr->rtc),
- "date", &error_fatal);
+ "date");
}
/* Returns whether we want to use VGA or not */
@@ -3305,64 +3306,53 @@
spapr->htab_fd = -1;
spapr->use_hotplug_event_source = true;
object_property_add_str(obj, "kvm-type",
- spapr_get_kvm_type, spapr_set_kvm_type, NULL);
+ spapr_get_kvm_type, spapr_set_kvm_type);
object_property_set_description(obj, "kvm-type",
- "Specifies the KVM virtualization mode (HV, PR)",
- NULL);
+ "Specifies the KVM virtualization mode (HV, PR)");
object_property_add_bool(obj, "modern-hotplug-events",
spapr_get_modern_hotplug_events,
- spapr_set_modern_hotplug_events,
- NULL);
+ spapr_set_modern_hotplug_events);
object_property_set_description(obj, "modern-hotplug-events",
"Use dedicated hotplug event mechanism in"
" place of standard EPOW events when possible"
- " (required for memory hot-unplug support)",
- NULL);
+ " (required for memory hot-unplug support)");
ppc_compat_add_property(obj, "max-cpu-compat", &spapr->max_compat_pvr,
- "Maximum permitted CPU compatibility mode",
- &error_fatal);
+ "Maximum permitted CPU compatibility mode");
object_property_add_str(obj, "resize-hpt",
- spapr_get_resize_hpt, spapr_set_resize_hpt, NULL);
+ spapr_get_resize_hpt, spapr_set_resize_hpt);
object_property_set_description(obj, "resize-hpt",
- "Resizing of the Hash Page Table (enabled, disabled, required)",
- NULL);
+ "Resizing of the Hash Page Table (enabled, disabled, required)");
object_property_add_uint32_ptr(obj, "vsmt",
- &spapr->vsmt, OBJ_PROP_FLAG_READWRITE,
- &error_abort);
+ &spapr->vsmt, OBJ_PROP_FLAG_READWRITE);
object_property_set_description(obj, "vsmt",
"Virtual SMT: KVM behaves as if this were"
- " the host's SMT mode", &error_abort);
+ " the host's SMT mode");
object_property_add_bool(obj, "vfio-no-msix-emulation",
- spapr_get_msix_emulation, NULL, NULL);
+ spapr_get_msix_emulation, NULL);
object_property_add_uint64_ptr(obj, "kernel-addr",
- &spapr->kernel_addr, OBJ_PROP_FLAG_READWRITE,
- &error_abort);
+ &spapr->kernel_addr, OBJ_PROP_FLAG_READWRITE);
object_property_set_description(obj, "kernel-addr",
stringify(KERNEL_LOAD_ADDR)
- " for -kernel is the default",
- NULL);
+ " for -kernel is the default");
spapr->kernel_addr = KERNEL_LOAD_ADDR;
/* The machine class defines the default interrupt controller mode */
spapr->irq = smc->irq;
object_property_add_str(obj, "ic-mode", spapr_get_ic_mode,
- spapr_set_ic_mode, NULL);
+ spapr_set_ic_mode);
object_property_set_description(obj, "ic-mode",
- "Specifies the interrupt controller mode (xics, xive, dual)",
- NULL);
+ "Specifies the interrupt controller mode (xics, xive, dual)");
object_property_add_str(obj, "host-model",
- spapr_get_host_model, spapr_set_host_model,
- &error_abort);
+ spapr_get_host_model, spapr_set_host_model);
object_property_set_description(obj, "host-model",
- "Host model to advertise in guest device tree", &error_abort);
+ "Host model to advertise in guest device tree");
object_property_add_str(obj, "host-serial",
- spapr_get_host_serial, spapr_set_host_serial,
- &error_abort);
+ spapr_get_host_serial, spapr_set_host_serial);
object_property_set_description(obj, "host-serial",
- "Host serial number to advertise in guest device tree", &error_abort);
+ "Host serial number to advertise in guest device tree");
}
static void spapr_machine_finalizefn(Object *obj)
@@ -3681,7 +3671,7 @@
SpaprDimmState *ds = spapr_pending_dimm_unplugs_find(spapr, PC_DIMM(dev));
pc_dimm_unplug(PC_DIMM(dev), MACHINE(hotplug_dev));
- object_property_set_bool(OBJECT(dev), false, "realized", NULL);
+ object_property_set_bool(OBJECT(dev), false, "realized", &error_abort);
spapr_pending_dimm_unplugs_remove(spapr, ds);
}
@@ -3774,7 +3764,7 @@
assert(core_slot);
core_slot->cpu = NULL;
- object_property_set_bool(OBJECT(dev), false, "realized", NULL);
+ object_property_set_bool(OBJECT(dev), false, "realized", &error_abort);
}
static
@@ -4024,7 +4014,7 @@
/* hotplug hooks should check it's enabled before getting this far */
assert(drc);
- spapr_drc_attach(drc, DEVICE(dev), &local_err);
+ spapr_drc_attach(drc, dev, &local_err);
if (local_err) {
error_propagate(errp, local_err);
return;
@@ -4047,7 +4037,7 @@
static void spapr_phb_unplug(HotplugHandler *hotplug_dev, DeviceState *dev)
{
- object_property_set_bool(OBJECT(dev), false, "realized", NULL);
+ object_property_set_bool(OBJECT(dev), false, "realized", &error_abort);
}
static void spapr_phb_unplug_request(HotplugHandler *hotplug_dev,
@@ -4083,7 +4073,7 @@
{
SpaprMachineState *spapr = SPAPR_MACHINE(OBJECT(hotplug_dev));
- object_property_set_bool(OBJECT(dev), false, "realized", NULL);
+ object_property_set_bool(OBJECT(dev), false, "realized", &error_abort);
object_unparent(OBJECT(dev));
spapr->tpm_proxy = NULL;
}
@@ -4535,7 +4525,7 @@
smc->default_caps.caps[SPAPR_CAP_LARGE_DECREMENTER] = SPAPR_CAP_ON;
smc->default_caps.caps[SPAPR_CAP_CCF_ASSIST] = SPAPR_CAP_ON;
smc->default_caps.caps[SPAPR_CAP_FWNMI] = SPAPR_CAP_ON;
- spapr_caps_add_properties(smc, &error_abort);
+ spapr_caps_add_properties(smc);
smc->irq = &spapr_irq_dual;
smc->dr_phb_enabled = true;
smc->linux_pci_probe = true;
diff --git a/hw/ppc/spapr_caps.c b/hw/ppc/spapr_caps.c
index eb54f94..efdc0db 100644
--- a/hw/ppc/spapr_caps.c
+++ b/hw/ppc/spapr_caps.c
@@ -824,9 +824,8 @@
}
}
-void spapr_caps_add_properties(SpaprMachineClass *smc, Error **errp)
+void spapr_caps_add_properties(SpaprMachineClass *smc)
{
- Error *local_err = NULL;
ObjectClass *klass = OBJECT_CLASS(smc);
int i;
@@ -837,20 +836,11 @@
object_class_property_add(klass, name, cap->type,
cap->get, cap->set,
- NULL, cap, &local_err);
- if (local_err) {
- error_propagate(errp, local_err);
- g_free(name);
- return;
- }
+ NULL, cap);
desc = g_strdup_printf("%s", cap->description);
- object_class_property_set_description(klass, name, desc, &local_err);
+ object_class_property_set_description(klass, name, desc);
g_free(name);
g_free(desc);
- if (local_err) {
- error_propagate(errp, local_err);
- return;
- }
}
}
diff --git a/hw/ppc/spapr_cpu_core.c b/hw/ppc/spapr_cpu_core.c
index ac1c109..9c8c1b1 100644
--- a/hw/ppc/spapr_cpu_core.c
+++ b/hw/ppc/spapr_cpu_core.c
@@ -218,7 +218,7 @@
spapr_cpu_core_reset(opaque);
}
-static void spapr_cpu_core_unrealize(DeviceState *dev, Error **errp)
+static void spapr_cpu_core_unrealize(DeviceState *dev)
{
SpaprCpuCore *sc = SPAPR_CPU_CORE(OBJECT(dev));
CPUCore *cc = CPU_CORE(dev);
@@ -290,11 +290,8 @@
cpu->node_id = sc->node_id;
id = g_strdup_printf("thread[%d]", i);
- object_property_add_child(OBJECT(sc), id, obj, &local_err);
+ object_property_add_child(OBJECT(sc), id, obj);
g_free(id);
- if (local_err) {
- goto err;
- }
cpu->machine_data = g_new0(SpaprCpuState, 1);
@@ -410,6 +407,7 @@
DEFINE_SPAPR_CPU_CORE_TYPE("power8nvl_v1.0"),
DEFINE_SPAPR_CPU_CORE_TYPE("power9_v1.0"),
DEFINE_SPAPR_CPU_CORE_TYPE("power9_v2.0"),
+ DEFINE_SPAPR_CPU_CORE_TYPE("power10_v1.0"),
#ifdef CONFIG_KVM
DEFINE_SPAPR_CPU_CORE_TYPE("host"),
#endif
diff --git a/hw/ppc/spapr_drc.c b/hw/ppc/spapr_drc.c
index 47e6bb1..b958f8a 100644
--- a/hw/ppc/spapr_drc.c
+++ b/hw/ppc/spapr_drc.c
@@ -392,7 +392,7 @@
object_property_add_link(OBJECT(drc), "device",
object_get_typename(OBJECT(drc->dev)),
(Object **)(&drc->dev),
- NULL, 0, NULL);
+ NULL, 0);
}
static void spapr_drc_release(SpaprDrc *drc)
@@ -405,7 +405,7 @@
g_free(drc->fdt);
drc->fdt = NULL;
drc->fdt_start_offset = 0;
- object_property_del(OBJECT(drc), "device", &error_abort);
+ object_property_del(OBJECT(drc), "device");
drc->dev = NULL;
}
@@ -518,8 +518,7 @@
SpaprDrc *drc = SPAPR_DR_CONNECTOR(d);
Object *root_container;
gchar *link_name;
- gchar *child_name;
- Error *err = NULL;
+ char *child_name;
trace_spapr_drc_realize(spapr_drc_index(drc));
/* NOTE: we do this as part of realize/unrealize due to the fact
@@ -534,19 +533,15 @@
child_name = object_get_canonical_path_component(OBJECT(drc));
trace_spapr_drc_realize_child(spapr_drc_index(drc), child_name);
object_property_add_alias(root_container, link_name,
- drc->owner, child_name, &err);
+ drc->owner, child_name);
g_free(child_name);
g_free(link_name);
- if (err) {
- error_propagate(errp, err);
- return;
- }
vmstate_register(VMSTATE_IF(drc), spapr_drc_index(drc), &vmstate_spapr_drc,
drc);
trace_spapr_drc_realize_complete(spapr_drc_index(drc));
}
-static void unrealize(DeviceState *d, Error **errp)
+static void unrealize(DeviceState *d)
{
SpaprDrc *drc = SPAPR_DR_CONNECTOR(d);
Object *root_container;
@@ -556,7 +551,7 @@
vmstate_unregister(VMSTATE_IF(drc), &vmstate_spapr_drc, drc);
root_container = container_get(object_get_root(), DRC_CONTAINER_PATH);
name = g_strdup_printf("%x", spapr_drc_index(drc));
- object_property_del(root_container, name, errp);
+ object_property_del(root_container, name);
g_free(name);
}
@@ -570,7 +565,7 @@
drc->owner = owner;
prop_name = g_strdup_printf("dr-connector[%"PRIu32"]",
spapr_drc_index(drc));
- object_property_add_child(owner, prop_name, OBJECT(drc), &error_abort);
+ object_property_add_child(owner, prop_name, OBJECT(drc));
object_unref(OBJECT(drc));
object_property_set_bool(OBJECT(drc), true, "realized", NULL);
g_free(prop_name);
@@ -583,12 +578,11 @@
SpaprDrc *drc = SPAPR_DR_CONNECTOR(obj);
SpaprDrcClass *drck = SPAPR_DR_CONNECTOR_GET_CLASS(drc);
- object_property_add_uint32_ptr(obj, "id", &drc->id, OBJ_PROP_FLAG_READ,
- NULL);
+ object_property_add_uint32_ptr(obj, "id", &drc->id, OBJ_PROP_FLAG_READ);
object_property_add(obj, "index", "uint32", prop_get_index,
- NULL, NULL, NULL, NULL);
+ NULL, NULL, NULL);
object_property_add(obj, "fdt", "struct", prop_get_fdt,
- NULL, NULL, NULL, NULL);
+ NULL, NULL, NULL);
drc->state = drck->empty_state;
}
@@ -656,17 +650,11 @@
qemu_register_reset(drc_physical_reset, drcp);
}
-static void unrealize_physical(DeviceState *d, Error **errp)
+static void unrealize_physical(DeviceState *d)
{
SpaprDrcPhysical *drcp = SPAPR_DRC_PHYSICAL(d);
- Error *local_err = NULL;
- unrealize(d, &local_err);
- if (local_err) {
- error_propagate(errp, local_err);
- return;
- }
-
+ unrealize(d);
vmstate_unregister(VMSTATE_IF(drcp), &vmstate_spapr_drc_physical, drcp);
qemu_unregister_reset(drc_physical_reset, drcp);
}
diff --git a/hw/ppc/spapr_iommu.c b/hw/ppc/spapr_iommu.c
index 5704fe6..7e1d6d5 100644
--- a/hw/ppc/spapr_iommu.c
+++ b/hw/ppc/spapr_iommu.c
@@ -365,7 +365,7 @@
tcet->liobn = liobn;
tmp = g_strdup_printf("tce-table-%x", liobn);
- object_property_add_child(OBJECT(owner), tmp, OBJECT(tcet), NULL);
+ object_property_add_child(OBJECT(owner), tmp, OBJECT(tcet));
g_free(tmp);
object_unref(OBJECT(tcet));
@@ -416,7 +416,7 @@
tcet->nb_table = 0;
}
-static void spapr_tce_table_unrealize(DeviceState *dev, Error **errp)
+static void spapr_tce_table_unrealize(DeviceState *dev)
{
SpaprTceTable *tcet = SPAPR_TCE_TABLE(dev);
diff --git a/hw/ppc/spapr_irq.c b/hw/ppc/spapr_irq.c
index 1f630f2..0c594aa 100644
--- a/hw/ppc/spapr_irq.c
+++ b/hw/ppc/spapr_irq.c
@@ -307,7 +307,7 @@
obj = object_new(TYPE_ICS_SPAPR);
- object_property_add_child(OBJECT(spapr), "ics", obj, &error_abort);
+ object_property_add_child(OBJECT(spapr), "ics", obj);
object_property_set_link(obj, OBJECT(spapr), ICS_PROP_XICS,
&error_abort);
object_property_set_int(obj, smc->nr_xirqs, "nr-irqs", &error_abort);
diff --git a/hw/ppc/spapr_pci.c b/hw/ppc/spapr_pci.c
index 61b84a3..83f1453 100644
--- a/hw/ppc/spapr_pci.c
+++ b/hw/ppc/spapr_pci.c
@@ -1203,46 +1203,36 @@
drc_id_from_devfn(phb, chassis, devfn));
}
-static uint8_t chassis_from_bus(PCIBus *bus, Error **errp)
+static uint8_t chassis_from_bus(PCIBus *bus)
{
if (pci_bus_is_root(bus)) {
return 0;
} else {
PCIDevice *bridge = pci_bridge_get_device(bus);
- return object_property_get_uint(OBJECT(bridge), "chassis_nr", errp);
+ return object_property_get_uint(OBJECT(bridge), "chassis_nr",
+ &error_abort);
}
}
static SpaprDrc *drc_from_dev(SpaprPhbState *phb, PCIDevice *dev)
{
- Error *local_err = NULL;
- uint8_t chassis = chassis_from_bus(pci_get_bus(dev), &local_err);
-
- if (local_err) {
- error_report_err(local_err);
- return NULL;
- }
+ uint8_t chassis = chassis_from_bus(pci_get_bus(dev));
return drc_from_devfn(phb, chassis, dev->devfn);
}
-static void add_drcs(SpaprPhbState *phb, PCIBus *bus, Error **errp)
+static void add_drcs(SpaprPhbState *phb, PCIBus *bus)
{
Object *owner;
int i;
uint8_t chassis;
- Error *local_err = NULL;
if (!phb->dr_enabled) {
return;
}
- chassis = chassis_from_bus(bus, &local_err);
- if (local_err) {
- error_propagate(errp, local_err);
- return;
- }
+ chassis = chassis_from_bus(bus);
if (pci_bus_is_root(bus)) {
owner = OBJECT(phb);
@@ -1256,21 +1246,16 @@
}
}
-static void remove_drcs(SpaprPhbState *phb, PCIBus *bus, Error **errp)
+static void remove_drcs(SpaprPhbState *phb, PCIBus *bus)
{
int i;
uint8_t chassis;
- Error *local_err = NULL;
if (!phb->dr_enabled) {
return;
}
- chassis = chassis_from_bus(bus, &local_err);
- if (local_err) {
- error_propagate(errp, local_err);
- return;
- }
+ chassis = chassis_from_bus(bus);
for (i = PCI_SLOT_MAX * PCI_FUNC_MAX - 1; i >= 0; i--) {
SpaprDrc *drc = drc_from_devfn(phb, chassis, i);
@@ -1488,17 +1473,11 @@
}
static void spapr_pci_bridge_plug(SpaprPhbState *phb,
- PCIBridge *bridge,
- Error **errp)
+ PCIBridge *bridge)
{
- Error *local_err = NULL;
PCIBus *bus = pci_bridge_get_sec_bus(bridge);
- add_drcs(phb, bus, &local_err);
- if (local_err) {
- error_propagate(errp, local_err);
- return;
- }
+ add_drcs(phb, bus);
}
static void spapr_pci_plug(HotplugHandler *plug_handler,
@@ -1529,11 +1508,7 @@
g_assert(drc);
if (pc->is_bridge) {
- spapr_pci_bridge_plug(phb, PCI_BRIDGE(plugged_dev), &local_err);
- if (local_err) {
- error_propagate(errp, local_err);
- return;
- }
+ spapr_pci_bridge_plug(phb, PCI_BRIDGE(plugged_dev));
}
/* Following the QEMU convention used for PCIe multifunction
@@ -1560,12 +1535,7 @@
spapr_drc_reset(drc);
} else if (PCI_FUNC(pdev->devfn) == 0) {
int i;
- uint8_t chassis = chassis_from_bus(pci_get_bus(pdev), &local_err);
-
- if (local_err) {
- error_propagate(errp, local_err);
- return;
- }
+ uint8_t chassis = chassis_from_bus(pci_get_bus(pdev));
for (i = 0; i < 8; i++) {
SpaprDrc *func_drc;
@@ -1587,17 +1557,11 @@
}
static void spapr_pci_bridge_unplug(SpaprPhbState *phb,
- PCIBridge *bridge,
- Error **errp)
+ PCIBridge *bridge)
{
- Error *local_err = NULL;
PCIBus *bus = pci_bridge_get_sec_bus(bridge);
- remove_drcs(phb, bus, &local_err);
- if (local_err) {
- error_propagate(errp, local_err);
- return;
- }
+ remove_drcs(phb, bus);
}
static void spapr_pci_unplug(HotplugHandler *plug_handler,
@@ -1619,15 +1583,12 @@
pci_device_reset(PCI_DEVICE(plugged_dev));
if (pc->is_bridge) {
- Error *local_err = NULL;
- spapr_pci_bridge_unplug(phb, PCI_BRIDGE(plugged_dev), &local_err);
- if (local_err) {
- error_propagate(errp, local_err);
- }
+ spapr_pci_bridge_unplug(phb, PCI_BRIDGE(plugged_dev));
return;
}
- object_property_set_bool(OBJECT(plugged_dev), false, "realized", NULL);
+ object_property_set_bool(OBJECT(plugged_dev), false, "realized",
+ &error_abort);
}
static void spapr_pci_unplug_request(HotplugHandler *plug_handler,
@@ -1653,13 +1614,7 @@
SpaprDrcClass *func_drck;
SpaprDREntitySense state;
int i;
- Error *local_err = NULL;
- uint8_t chassis = chassis_from_bus(pci_get_bus(pdev), &local_err);
-
- if (local_err) {
- error_propagate(errp, local_err);
- return;
- }
+ uint8_t chassis = chassis_from_bus(pci_get_bus(pdev));
if (pc->is_bridge) {
error_setg(errp, "PCI: Hot unplug of PCI bridges not supported");
@@ -1715,7 +1670,7 @@
sphb->dtbusname = NULL;
}
-static void spapr_phb_unrealize(DeviceState *dev, Error **errp)
+static void spapr_phb_unrealize(DeviceState *dev)
{
SpaprMachineState *spapr = SPAPR_MACHINE(qdev_get_machine());
SysBusDevice *s = SYS_BUS_DEVICE(dev);
@@ -1724,7 +1679,6 @@
SpaprTceTable *tcet;
int i;
const unsigned windows_supported = spapr_phb_windows_supported(sphb);
- Error *local_err = NULL;
spapr_phb_nvgpu_free(sphb);
@@ -1745,11 +1699,7 @@
}
}
- remove_drcs(sphb, phb->bus, &local_err);
- if (local_err) {
- error_propagate(errp, local_err);
- return;
- }
+ remove_drcs(sphb, phb->bus);
for (i = PCI_NUM_PINS - 1; i >= 0; i--) {
if (sphb->lsi_table[i].irq) {
@@ -1988,11 +1938,7 @@
}
/* allocate connectors for child PCI devices */
- add_drcs(sphb, phb->bus, &local_err);
- if (local_err) {
- error_propagate(errp, local_err);
- goto unrealize;
- }
+ add_drcs(sphb, phb->bus);
/* DMA setup */
for (i = 0; i < windows_supported; ++i) {
@@ -2011,7 +1957,7 @@
return;
unrealize:
- spapr_phb_unrealize(dev, NULL);
+ spapr_phb_unrealize(dev);
}
static int spapr_phb_children_reset(Object *child, void *opaque)
diff --git a/hw/ppc/spapr_rng.c b/hw/ppc/spapr_rng.c
index e8e8d65..85bf64d 100644
--- a/hw/ppc/spapr_rng.c
+++ b/hw/ppc/spapr_rng.c
@@ -103,8 +103,7 @@
}
object_property_set_description(obj, "rng",
- "ID of the random number generator backend",
- NULL);
+ "ID of the random number generator backend");
}
static void spapr_rng_realize(DeviceState *dev, Error **errp)
diff --git a/hw/ppc/spapr_rtc.c b/hw/ppc/spapr_rtc.c
index 42ff72c..68cfc57 100644
--- a/hw/ppc/spapr_rtc.c
+++ b/hw/ppc/spapr_rtc.c
@@ -149,7 +149,7 @@
rtc_ns = qemu_clock_get_ns(rtc_clock);
rtc->ns_offset = host_s * NANOSECONDS_PER_SECOND - rtc_ns;
- object_property_add_tm(OBJECT(rtc), "date", spapr_rtc_qom_date, NULL);
+ object_property_add_tm(OBJECT(rtc), "date", spapr_rtc_qom_date);
}
static const VMStateDescription vmstate_spapr_rtc = {
diff --git a/hw/ppc/spapr_tpm_proxy.c b/hw/ppc/spapr_tpm_proxy.c
index 991615d..a01f81f 100644
--- a/hw/ppc/spapr_tpm_proxy.c
+++ b/hw/ppc/spapr_tpm_proxy.c
@@ -140,7 +140,7 @@
qemu_register_reset(spapr_tpm_proxy_reset, tpm_proxy);
}
-static void spapr_tpm_proxy_unrealize(DeviceState *d, Error **errp)
+static void spapr_tpm_proxy_unrealize(DeviceState *d)
{
SpaprTpmProxy *tpm_proxy = SPAPR_TPM_PROXY(d);
diff --git a/hw/riscv/sifive_u.c b/hw/riscv/sifive_u.c
index bed10fc..4299bdf 100644
--- a/hw/riscv/sifive_u.c
+++ b/hw/riscv/sifive_u.c
@@ -441,17 +441,18 @@
SiFiveUState *s = RISCV_U_MACHINE(obj);
s->start_in_flash = false;
- object_property_add_bool(obj, "start-in-flash", sifive_u_machine_get_start_in_flash,
- sifive_u_machine_set_start_in_flash, NULL);
+ object_property_add_bool(obj, "start-in-flash",
+ sifive_u_machine_get_start_in_flash,
+ sifive_u_machine_set_start_in_flash);
object_property_set_description(obj, "start-in-flash",
"Set on to tell QEMU's ROM to jump to "
- "flash. Otherwise QEMU will jump to DRAM",
- NULL);
+ "flash. Otherwise QEMU will jump to DRAM");
s->serial = OTP_SERIAL;
- object_property_add(obj, "serial", "uint32", sifive_u_machine_get_serial,
- sifive_u_machine_set_serial, NULL, &s->serial, NULL);
- object_property_set_description(obj, "serial", "Board serial number", NULL);
+ object_property_add(obj, "serial", "uint32",
+ sifive_u_machine_get_serial,
+ sifive_u_machine_set_serial, NULL, &s->serial);
+ object_property_set_description(obj, "serial", "Board serial number");
}
static void sifive_u_machine_class_init(ObjectClass *oc, void *data)
diff --git a/hw/riscv/virt.c b/hw/riscv/virt.c
index daae3eb..7ce2889 100644
--- a/hw/riscv/virt.c
+++ b/hw/riscv/virt.c
@@ -92,10 +92,9 @@
qdev_prop_set_uint16(dev, "id3", 0x00);
qdev_prop_set_string(dev, "name", name);
- object_property_add_child(OBJECT(s), name, OBJECT(dev),
- &error_abort);
+ object_property_add_child(OBJECT(s), name, OBJECT(dev));
object_property_add_alias(OBJECT(s), alias_prop_name,
- OBJECT(dev), "drive", &error_abort);
+ OBJECT(dev), "drive");
return PFLASH_CFI01(dev);
}
@@ -112,7 +111,7 @@
{
DeviceState *dev = DEVICE(flash);
- assert(size % VIRT_FLASH_SECTOR_SIZE == 0);
+ assert(QEMU_IS_ALIGNED(size, VIRT_FLASH_SECTOR_SIZE));
assert(size / VIRT_FLASH_SECTOR_SIZE <= UINT32_MAX);
qdev_prop_set_uint32(dev, "num-blocks", size / VIRT_FLASH_SECTOR_SIZE);
qdev_init_nofail(dev);
diff --git a/hw/rtc/mc146818rtc.c b/hw/rtc/mc146818rtc.c
index d18c099..9c30cbd 100644
--- a/hw/rtc/mc146818rtc.c
+++ b/hw/rtc/mc146818rtc.c
@@ -962,7 +962,7 @@
qdev_set_legacy_instance_id(dev, RTC_ISA_BASE, 3);
qemu_register_reset(rtc_reset, s);
- object_property_add_tm(OBJECT(s), "date", rtc_get_date, NULL);
+ object_property_add_tm(OBJECT(s), "date", rtc_get_date);
qdev_init_gpio_out(dev, &s->irq, 1);
QLIST_INSERT_HEAD(&rtc_devices, s, link);
@@ -984,7 +984,7 @@
}
object_property_add_alias(qdev_get_machine(), "rtc-time", OBJECT(isadev),
- "date", NULL);
+ "date");
return isadev;
}
diff --git a/hw/s390x/ap-bridge.c b/hw/s390x/ap-bridge.c
index 9284de4..d0dbd0f 100644
--- a/hw/s390x/ap-bridge.c
+++ b/hw/s390x/ap-bridge.c
@@ -51,7 +51,7 @@
/* Create bridge device */
dev = qdev_create(NULL, TYPE_AP_BRIDGE);
object_property_add_child(qdev_get_machine(), TYPE_AP_BRIDGE,
- OBJECT(dev), NULL);
+ OBJECT(dev));
qdev_init_nofail(dev);
/* Create bus on bridge device */
diff --git a/hw/s390x/css-bridge.c b/hw/s390x/css-bridge.c
index a306a78..3f6aec6 100644
--- a/hw/s390x/css-bridge.c
+++ b/hw/s390x/css-bridge.c
@@ -54,7 +54,7 @@
css_generate_sch_crws(sch->cssid, sch->ssid, sch->schid, 1, 0);
- object_property_set_bool(OBJECT(dev), false, "realized", NULL);
+ object_property_set_bool(OBJECT(dev), false, "realized", &error_abort);
}
static void virtual_css_bus_reset(BusState *qbus)
@@ -103,7 +103,7 @@
/* Create bridge device */
dev = qdev_create(NULL, TYPE_VIRTUAL_CSS_BRIDGE);
object_property_add_child(qdev_get_machine(), TYPE_VIRTUAL_CSS_BRIDGE,
- OBJECT(dev), NULL);
+ OBJECT(dev));
qdev_init_nofail(dev);
/* Create bus on bridge device */
@@ -141,11 +141,10 @@
set_bit(DEVICE_CATEGORY_BRIDGE, dc->categories);
device_class_set_props(dc, virtual_css_bridge_properties);
object_class_property_add_bool(klass, "cssid-unrestricted",
- prop_get_true, NULL, NULL);
+ prop_get_true, NULL);
object_class_property_set_description(klass, "cssid-unrestricted",
"A css device can use any cssid, regardless whether virtual"
- " or not (read only, always true)",
- NULL);
+ " or not (read only, always true)");
}
static const TypeInfo virtual_css_bridge_info = {
diff --git a/hw/s390x/event-facility.c b/hw/s390x/event-facility.c
index 9d6972a..97a4f0b 100644
--- a/hw/s390x/event-facility.c
+++ b/hw/s390x/event-facility.c
@@ -449,18 +449,18 @@
event_facility->allow_all_mask_sizes = true;
object_property_add_bool(obj, "allow_all_mask_sizes",
sclp_event_get_allow_all_mask_sizes,
- sclp_event_set_allow_all_mask_sizes, NULL);
+ sclp_event_set_allow_all_mask_sizes);
/* Spawn a new bus for SCLP events */
qbus_create_inplace(&event_facility->sbus, sizeof(event_facility->sbus),
TYPE_SCLP_EVENTS_BUS, sdev, NULL);
new = object_new(TYPE_SCLP_QUIESCE);
- object_property_add_child(obj, TYPE_SCLP_QUIESCE, new, NULL);
+ object_property_add_child(obj, TYPE_SCLP_QUIESCE, new);
object_unref(new);
qdev_set_parent_bus(DEVICE(new), BUS(&event_facility->sbus));
new = object_new(TYPE_SCLP_CPU_HOTPLUG);
- object_property_add_child(obj, TYPE_SCLP_CPU_HOTPLUG, new, NULL);
+ object_property_add_child(obj, TYPE_SCLP_CPU_HOTPLUG, new);
object_unref(new);
qdev_set_parent_bus(DEVICE(new), BUS(&event_facility->sbus));
/* the facility will automatically realize the devices via the bus */
diff --git a/hw/s390x/s390-ccw.c b/hw/s390x/s390-ccw.c
index 0c5a5b6..c48510f 100644
--- a/hw/s390x/s390-ccw.c
+++ b/hw/s390x/s390-ccw.c
@@ -132,7 +132,7 @@
error_propagate(errp, err);
}
-static void s390_ccw_unrealize(S390CCWDevice *cdev, Error **errp)
+static void s390_ccw_unrealize(S390CCWDevice *cdev)
{
CcwDevice *ccw_dev = CCW_DEVICE(cdev);
SubchDev *sch = ccw_dev->sch;
@@ -151,7 +151,7 @@
S390CCWDevice *dev = S390_CCW_DEVICE(obj);
device_add_bootindex_property(obj, &dev->bootindex, "bootindex",
- "/disk@0,0", DEVICE(obj), NULL);
+ "/disk@0,0", DEVICE(obj));
}
static void s390_ccw_class_init(ObjectClass *klass, void *data)
diff --git a/hw/s390x/s390-pci-bus.c b/hw/s390x/s390-pci-bus.c
index ed8be12..c4a4259 100644
--- a/hw/s390x/s390-pci-bus.c
+++ b/hw/s390x/s390-pci-bus.c
@@ -1003,7 +1003,7 @@
pbdev->fh, pbdev->fid);
bus = pci_get_bus(pci_dev);
devfn = pci_dev->devfn;
- object_property_set_bool(OBJECT(dev), false, "realized", NULL);
+ object_property_set_bool(OBJECT(dev), false, "realized", &error_abort);
s390_pci_msix_free(pbdev);
s390_pci_iommu_free(s, bus, devfn);
@@ -1014,7 +1014,7 @@
pbdev->fid = 0;
QTAILQ_REMOVE(&s->zpci_devs, pbdev, link);
g_hash_table_remove(s->zpci_table, &pbdev->idx);
- object_property_set_bool(OBJECT(dev), false, "realized", NULL);
+ object_property_set_bool(OBJECT(dev), false, "realized", &error_abort);
}
}
diff --git a/hw/s390x/s390-skeys.c b/hw/s390x/s390-skeys.c
index a9a4ae7..d304b85 100644
--- a/hw/s390x/s390-skeys.c
+++ b/hw/s390x/s390-skeys.c
@@ -45,7 +45,7 @@
obj = object_new(TYPE_QEMU_S390_SKEYS);
}
object_property_add_child(qdev_get_machine(), TYPE_S390_SKEYS,
- obj, NULL);
+ obj);
object_unref(obj);
qdev_init_nofail(DEVICE(obj));
@@ -400,7 +400,7 @@
{
object_property_add_bool(obj, "migration-enabled",
s390_skeys_get_migration_enabled,
- s390_skeys_set_migration_enabled, NULL);
+ s390_skeys_set_migration_enabled);
object_property_set_bool(obj, true, "migration-enabled", NULL);
}
diff --git a/hw/s390x/s390-stattrib.c b/hw/s390x/s390-stattrib.c
index 58121b9..6d1e587 100644
--- a/hw/s390x/s390-stattrib.c
+++ b/hw/s390x/s390-stattrib.c
@@ -47,7 +47,7 @@
}
object_property_add_child(qdev_get_machine(), TYPE_S390_STATTRIB,
- obj, NULL);
+ obj);
object_unref(obj);
qdev_init_nofail(DEVICE(obj));
@@ -387,7 +387,7 @@
object_property_add_bool(obj, "migration-enabled",
s390_stattrib_get_migration_enabled,
- s390_stattrib_set_migration_enabled, NULL);
+ s390_stattrib_set_migration_enabled);
object_property_set_bool(obj, true, "migration-enabled", NULL);
sas->migration_cur_gfn = 0;
}
diff --git a/hw/s390x/s390-virtio-ccw.c b/hw/s390x/s390-virtio-ccw.c
index f660070..67ae2e0 100644
--- a/hw/s390x/s390-virtio-ccw.c
+++ b/hw/s390x/s390-virtio-ccw.c
@@ -208,7 +208,7 @@
}
g_free(netboot_fw_prop);
object_property_add_child(qdev_get_machine(), TYPE_S390_IPL,
- new, NULL);
+ new);
object_unref(new);
qdev_init_nofail(dev);
}
@@ -271,7 +271,7 @@
dev = qdev_create(NULL, TYPE_S390_PCI_HOST_BRIDGE);
object_property_add_child(qdev_get_machine(), TYPE_S390_PCI_HOST_BRIDGE,
- OBJECT(dev), NULL);
+ OBJECT(dev));
qdev_init_nofail(dev);
/* register hypercalls */
@@ -729,26 +729,23 @@
{
object_property_add_bool(obj, "aes-key-wrap",
machine_get_aes_key_wrap,
- machine_set_aes_key_wrap, NULL);
+ machine_set_aes_key_wrap);
object_property_set_description(obj, "aes-key-wrap",
- "enable/disable AES key wrapping using the CPACF wrapping key",
- NULL);
+ "enable/disable AES key wrapping using the CPACF wrapping key");
object_property_set_bool(obj, true, "aes-key-wrap", NULL);
object_property_add_bool(obj, "dea-key-wrap",
machine_get_dea_key_wrap,
- machine_set_dea_key_wrap, NULL);
+ machine_set_dea_key_wrap);
object_property_set_description(obj, "dea-key-wrap",
- "enable/disable DEA key wrapping using the CPACF wrapping key",
- NULL);
+ "enable/disable DEA key wrapping using the CPACF wrapping key");
object_property_set_bool(obj, true, "dea-key-wrap", NULL);
object_property_add_str(obj, "loadparm",
- machine_get_loadparm, machine_set_loadparm, NULL);
+ machine_get_loadparm, machine_set_loadparm);
object_property_set_description(obj, "loadparm",
"Up to 8 chars in set of [A-Za-z0-9. ] (lower case chars converted"
" to upper case) to pass to machine loader, boot manager,"
- " and guest kernel",
- NULL);
+ " and guest kernel");
}
static const TypeInfo ccw_machine_info = {
diff --git a/hw/s390x/sclp.c b/hw/s390x/sclp.c
index ede056b..20aca30 100644
--- a/hw/s390x/sclp.c
+++ b/hw/s390x/sclp.c
@@ -320,9 +320,8 @@
{
Object *new = object_new(TYPE_SCLP);
- object_property_add_child(qdev_get_machine(), TYPE_SCLP, new,
- NULL);
- object_unref(OBJECT(new));
+ object_property_add_child(qdev_get_machine(), TYPE_SCLP, new);
+ object_unref(new);
qdev_init_nofail(DEVICE(new));
}
@@ -383,7 +382,7 @@
Object *new;
new = object_new(TYPE_SCLP_EVENT_FACILITY);
- object_property_add_child(obj, TYPE_SCLP_EVENT_FACILITY, new, NULL);
+ object_property_add_child(obj, TYPE_SCLP_EVENT_FACILITY, new);
object_unref(new);
sclp->event_facility = EVENT_FACILITY(new);
diff --git a/hw/s390x/tod.c b/hw/s390x/tod.c
index 2499d6f..7324e37 100644
--- a/hw/s390x/tod.c
+++ b/hw/s390x/tod.c
@@ -26,7 +26,7 @@
} else {
obj = object_new(TYPE_QEMU_S390_TOD);
}
- object_property_add_child(qdev_get_machine(), TYPE_S390_TOD, obj, NULL);
+ object_property_add_child(qdev_get_machine(), TYPE_S390_TOD, obj);
object_unref(obj);
qdev_init_nofail(DEVICE(obj));
diff --git a/hw/s390x/virtio-ccw-balloon.c b/hw/s390x/virtio-ccw-balloon.c
index 5d28e72..ef3308e 100644
--- a/hw/s390x/virtio-ccw-balloon.c
+++ b/hw/s390x/virtio-ccw-balloon.c
@@ -32,10 +32,10 @@
virtio_instance_init_common(obj, &dev->vdev, sizeof(dev->vdev),
TYPE_VIRTIO_BALLOON);
object_property_add_alias(obj, "guest-stats", OBJECT(&dev->vdev),
- "guest-stats", &error_abort);
+ "guest-stats");
object_property_add_alias(obj, "guest-stats-polling-interval",
OBJECT(&dev->vdev),
- "guest-stats-polling-interval", &error_abort);
+ "guest-stats-polling-interval");
}
static Property virtio_ccw_balloon_properties[] = {
diff --git a/hw/s390x/virtio-ccw-blk.c b/hw/s390x/virtio-ccw-blk.c
index bf8520e..7287932 100644
--- a/hw/s390x/virtio-ccw-blk.c
+++ b/hw/s390x/virtio-ccw-blk.c
@@ -32,7 +32,7 @@
virtio_instance_init_common(obj, &dev->vdev, sizeof(dev->vdev),
TYPE_VIRTIO_BLK);
object_property_add_alias(obj, "bootindex", OBJECT(&dev->vdev),
- "bootindex", &error_abort);
+ "bootindex");
}
static Property virtio_ccw_blk_properties[] = {
diff --git a/hw/s390x/virtio-ccw-net.c b/hw/s390x/virtio-ccw-net.c
index cd02699..26c4d87 100644
--- a/hw/s390x/virtio-ccw-net.c
+++ b/hw/s390x/virtio-ccw-net.c
@@ -35,7 +35,7 @@
virtio_instance_init_common(obj, &dev->vdev, sizeof(dev->vdev),
TYPE_VIRTIO_NET);
object_property_add_alias(obj, "bootindex", OBJECT(&dev->vdev),
- "bootindex", &error_abort);
+ "bootindex");
}
static Property virtio_ccw_net_properties[] = {
diff --git a/hw/s390x/virtio-ccw.c b/hw/s390x/virtio-ccw.c
index 64f928f..c1f4bb1 100644
--- a/hw/s390x/virtio-ccw.c
+++ b/hw/s390x/virtio-ccw.c
@@ -752,14 +752,14 @@
g_free(sch);
}
-static void virtio_ccw_device_unrealize(VirtioCcwDevice *dev, Error **errp)
+static void virtio_ccw_device_unrealize(VirtioCcwDevice *dev)
{
VirtIOCCWDeviceClass *dc = VIRTIO_CCW_DEVICE_GET_CLASS(dev);
CcwDevice *ccw_dev = CCW_DEVICE(dev);
SubchDev *sch = ccw_dev->sch;
if (dc->unrealize) {
- dc->unrealize(dev, errp);
+ dc->unrealize(dev);
}
if (sch) {
@@ -1155,11 +1155,11 @@
virtio_ccw_device_realize(_dev, errp);
}
-static void virtio_ccw_busdev_unrealize(DeviceState *dev, Error **errp)
+static void virtio_ccw_busdev_unrealize(DeviceState *dev)
{
VirtioCcwDevice *_dev = (VirtioCcwDevice *)dev;
- virtio_ccw_device_unrealize(_dev, errp);
+ virtio_ccw_device_unrealize(_dev);
}
static void virtio_ccw_busdev_unplug(HotplugHandler *hotplug_dev,
diff --git a/hw/s390x/virtio-ccw.h b/hw/s390x/virtio-ccw.h
index 3453aa1..c0e3355 100644
--- a/hw/s390x/virtio-ccw.h
+++ b/hw/s390x/virtio-ccw.h
@@ -76,7 +76,7 @@
typedef struct VirtIOCCWDeviceClass {
CCWDeviceClass parent_class;
void (*realize)(VirtioCcwDevice *dev, Error **errp);
- void (*unrealize)(VirtioCcwDevice *dev, Error **errp);
+ void (*unrealize)(VirtioCcwDevice *dev);
void (*parent_reset)(DeviceState *dev);
} VirtIOCCWDeviceClass;
diff --git a/hw/scsi/lsi53c895a.c b/hw/scsi/lsi53c895a.c
index ec53b14..63ff418 100644
--- a/hw/scsi/lsi53c895a.c
+++ b/hw/scsi/lsi53c895a.c
@@ -2312,7 +2312,7 @@
scsi_bus_new(&s->bus, sizeof(s->bus), d, &lsi_scsi_info, NULL);
}
-static void lsi_scsi_unrealize(DeviceState *dev, Error **errp)
+static void lsi_scsi_unrealize(DeviceState *dev)
{
LSIState *s = LSI53C895A(dev);
diff --git a/hw/scsi/scsi-bus.c b/hw/scsi/scsi-bus.c
index 1c980ca..2836f80 100644
--- a/hw/scsi/scsi-bus.c
+++ b/hw/scsi/scsi-bus.c
@@ -59,11 +59,11 @@
}
}
-static void scsi_device_unrealize(SCSIDevice *s, Error **errp)
+static void scsi_device_unrealize(SCSIDevice *s)
{
SCSIDeviceClass *sc = SCSI_DEVICE_GET_CLASS(s);
if (sc->unrealize) {
- sc->unrealize(s, errp);
+ sc->unrealize(s);
}
}
@@ -222,10 +222,9 @@
scsi_dma_restart_cb, dev);
}
-static void scsi_qdev_unrealize(DeviceState *qdev, Error **errp)
+static void scsi_qdev_unrealize(DeviceState *qdev)
{
SCSIDevice *dev = SCSI_DEVICE(qdev);
- Error *local_err = NULL;
if (dev->vmsentry) {
qemu_del_vm_change_state_handler(dev->vmsentry);
@@ -233,11 +232,7 @@
scsi_device_purge_requests(dev, SENSE_CODE(NO_SENSE));
- scsi_device_unrealize(dev, &local_err);
- if (local_err) {
- error_propagate(errp, local_err);
- return;
- }
+ scsi_device_unrealize(dev);
blockdev_mark_auto_del(dev->conf.blk);
}
@@ -268,7 +263,7 @@
}
dev = qdev_create(&bus->qbus, driver);
name = g_strdup_printf("legacy[%d]", unit);
- object_property_add_child(OBJECT(bus), name, OBJECT(dev), NULL);
+ object_property_add_child(OBJECT(bus), name, OBJECT(dev));
g_free(name);
qdev_prop_set_uint32(dev, "scsi-id", unit);
@@ -1738,7 +1733,7 @@
device_add_bootindex_property(obj, &s->conf.bootindex,
"bootindex", NULL,
- &s->qdev, NULL);
+ &s->qdev);
}
static const TypeInfo scsi_device_type_info = {
diff --git a/hw/scsi/scsi-disk.c b/hw/scsi/scsi-disk.c
index e5bcd0b..387503e 100644
--- a/hw/scsi/scsi-disk.c
+++ b/hw/scsi/scsi-disk.c
@@ -2421,7 +2421,7 @@
dev->conf.lsecs);
}
-static void scsi_unrealize(SCSIDevice *dev, Error **errp)
+static void scsi_unrealize(SCSIDevice *dev)
{
del_boot_device_lchs(&dev->qdev, NULL);
}
diff --git a/hw/scsi/vhost-scsi.c b/hw/scsi/vhost-scsi.c
index f052377..c1b012a 100644
--- a/hw/scsi/vhost-scsi.c
+++ b/hw/scsi/vhost-scsi.c
@@ -248,7 +248,7 @@
return;
}
-static void vhost_scsi_unrealize(DeviceState *dev, Error **errp)
+static void vhost_scsi_unrealize(DeviceState *dev)
{
VirtIODevice *vdev = VIRTIO_DEVICE(dev);
VHostSCSICommon *vsc = VHOST_SCSI_COMMON(dev);
@@ -311,7 +311,7 @@
vsc->feature_bits = kernel_feature_bits;
device_add_bootindex_property(obj, &vsc->bootindex, "bootindex", NULL,
- DEVICE(vsc), NULL);
+ DEVICE(vsc));
}
static const TypeInfo vhost_scsi_info = {
diff --git a/hw/scsi/vhost-user-scsi.c b/hw/scsi/vhost-user-scsi.c
index a01bf63..cbb5d97 100644
--- a/hw/scsi/vhost-user-scsi.c
+++ b/hw/scsi/vhost-user-scsi.c
@@ -143,7 +143,7 @@
virtio_scsi_common_unrealize(dev);
}
-static void vhost_user_scsi_unrealize(DeviceState *dev, Error **errp)
+static void vhost_user_scsi_unrealize(DeviceState *dev)
{
VirtIODevice *vdev = VIRTIO_DEVICE(dev);
VHostUserSCSI *s = VHOST_USER_SCSI(dev);
@@ -217,7 +217,7 @@
/* Add the bootindex property for this object */
device_add_bootindex_property(obj, &vsc->bootindex, "bootindex", NULL,
- DEVICE(vsc), NULL);
+ DEVICE(vsc));
}
static const TypeInfo vhost_user_scsi_info = {
diff --git a/hw/scsi/virtio-scsi.c b/hw/scsi/virtio-scsi.c
index 472bbd2..9b72094 100644
--- a/hw/scsi/virtio-scsi.c
+++ b/hw/scsi/virtio-scsi.c
@@ -954,7 +954,7 @@
virtio_cleanup(vdev);
}
-static void virtio_scsi_device_unrealize(DeviceState *dev, Error **errp)
+static void virtio_scsi_device_unrealize(DeviceState *dev)
{
VirtIOSCSI *s = VIRTIO_SCSI(dev);
diff --git a/hw/sd/pxa2xx_mmci.c b/hw/sd/pxa2xx_mmci.c
index 8f9ab0e..f9c50dd 100644
--- a/hw/sd/pxa2xx_mmci.c
+++ b/hw/sd/pxa2xx_mmci.c
@@ -497,12 +497,12 @@
carddev = qdev_create(qdev_get_child_bus(dev, "sd-bus"), TYPE_SD_CARD);
qdev_prop_set_drive(carddev, "drive", blk, &err);
if (err) {
- error_report("failed to init SD card: %s", error_get_pretty(err));
+ error_reportf_err(err, "failed to init SD card: ");
return NULL;
}
object_property_set_bool(OBJECT(carddev), true, "realized", &err);
if (err) {
- error_report("failed to init SD card: %s", error_get_pretty(err));
+ error_reportf_err(err, "failed to init SD card: ");
return NULL;
}
diff --git a/hw/sd/sd.c b/hw/sd/sd.c
index 71a9af0..3c06a0a 100644
--- a/hw/sd/sd.c
+++ b/hw/sd/sd.c
@@ -703,13 +703,13 @@
dev = DEVICE(obj);
qdev_prop_set_drive(dev, "drive", blk, &err);
if (err) {
- error_report("sd_init failed: %s", error_get_pretty(err));
+ error_reportf_err(err, "sd_init failed: ");
return NULL;
}
qdev_prop_set_bit(dev, "spi", is_spi);
object_property_set_bool(obj, true, "realized", &err);
if (err) {
- error_report("sd_init failed: %s", error_get_pretty(err));
+ error_reportf_err(err, "sd_init failed: ");
return NULL;
}
diff --git a/hw/sd/sdhci-internal.h b/hw/sd/sdhci-internal.h
index 3414140..e7c8a52 100644
--- a/hw/sd/sdhci-internal.h
+++ b/hw/sd/sdhci-internal.h
@@ -335,7 +335,7 @@
void sdhci_initfn(SDHCIState *s);
void sdhci_uninitfn(SDHCIState *s);
void sdhci_common_realize(SDHCIState *s, Error **errp);
-void sdhci_common_unrealize(SDHCIState *s, Error **errp);
+void sdhci_common_unrealize(SDHCIState *s);
void sdhci_common_class_init(ObjectClass *klass, void *data);
#endif
diff --git a/hw/sd/sdhci-pci.c b/hw/sd/sdhci-pci.c
index 19fa8bd..4f5977d 100644
--- a/hw/sd/sdhci-pci.c
+++ b/hw/sd/sdhci-pci.c
@@ -50,7 +50,7 @@
{
SDHCIState *s = PCI_SDHCI(dev);
- sdhci_common_unrealize(s, &error_abort);
+ sdhci_common_unrealize(s);
sdhci_uninitfn(s);
}
diff --git a/hw/sd/sdhci.c b/hw/sd/sdhci.c
index 70531ad..1b75d7b 100644
--- a/hw/sd/sdhci.c
+++ b/hw/sd/sdhci.c
@@ -1346,7 +1346,7 @@
SDHC_REGISTERS_MAP_SIZE);
}
-void sdhci_common_unrealize(SDHCIState *s, Error **errp)
+void sdhci_common_unrealize(SDHCIState *s)
{
/* This function is expected to be called only once for each class:
* - SysBus: via DeviceClass->unrealize(),
@@ -1479,11 +1479,11 @@
sysbus_init_mmio(sbd, &s->iomem);
}
-static void sdhci_sysbus_unrealize(DeviceState *dev, Error **errp)
+static void sdhci_sysbus_unrealize(DeviceState *dev)
{
SDHCIState *s = SYSBUS_SDHCI(dev);
- sdhci_common_unrealize(s, &error_abort);
+ sdhci_common_unrealize(s);
if (s->dma_mr) {
address_space_destroy(s->dma_as);
diff --git a/hw/sh4/sh_pci.c b/hw/sh4/sh_pci.c
index 08f2fc1..0a3e86f 100644
--- a/hw/sh4/sh_pci.c
+++ b/hw/sh4/sh_pci.c
@@ -129,7 +129,7 @@
for (i = 0; i < 4; i++) {
sysbus_init_irq(sbd, &s->irq[i]);
}
- phb->bus = pci_register_root_bus(DEVICE(dev), "pci",
+ phb->bus = pci_register_root_bus(dev, "pci",
sh_pci_set_irq, sh_pci_map_irq,
s->irq,
get_system_memory(),
diff --git a/hw/sparc/sun4m.c b/hw/sparc/sun4m.c
index 36ee1a0..8dda3f7 100644
--- a/hw/sparc/sun4m.c
+++ b/hw/sparc/sun4m.c
@@ -795,10 +795,9 @@
object_property_add_link(obj, "memdev", TYPE_MEMORY_BACKEND,
(Object **)&d->memdev,
object_property_allow_set_link,
- OBJ_PROP_LINK_STRONG, &error_abort);
+ OBJ_PROP_LINK_STRONG);
object_property_set_description(obj, "memdev", "Set RAM backend"
- "Valid value is ID of a hostmem backend",
- &error_abort);
+ "Valid value is ID of a hostmem backend");
}
static void ram_class_init(ObjectClass *klass, void *data)
@@ -1061,7 +1060,7 @@
qdev_prop_set_uint32(dev, "data_width", 1);
qdev_prop_set_bit(dev, "dma_enabled", false);
object_property_add_child(OBJECT(qdev_get_machine()), TYPE_FW_CFG,
- OBJECT(fw_cfg), NULL);
+ OBJECT(fw_cfg));
qdev_init_nofail(dev);
s = SYS_BUS_DEVICE(dev);
sysbus_mmio_map(s, 0, CFG_ADDR);
diff --git a/hw/sparc64/sun4u.c b/hw/sparc64/sun4u.c
index 6abfcb3..3a757ec 100644
--- a/hw/sparc64/sun4u.c
+++ b/hw/sparc64/sun4u.c
@@ -691,7 +691,7 @@
dev = qdev_create(NULL, TYPE_FW_CFG_IO);
qdev_prop_set_bit(dev, "dma_enabled", false);
- object_property_add_child(OBJECT(ebus), TYPE_FW_CFG, OBJECT(dev), NULL);
+ object_property_add_child(OBJECT(ebus), TYPE_FW_CFG, OBJECT(dev));
qdev_init_nofail(dev);
memory_region_add_subregion(pci_address_space_io(ebus), BIOS_CFG_IOPORT,
&FW_CFG_IO(dev)->comb_iomem);
diff --git a/hw/ssi/xilinx_spips.c b/hw/ssi/xilinx_spips.c
index c57850a..e76cf29 100644
--- a/hw/ssi/xilinx_spips.c
+++ b/hw/ssi/xilinx_spips.c
@@ -868,7 +868,7 @@
memcpy(rq->dma_buf, rxd, num);
- ret = stream_push(rq->dma, rq->dma_buf, num);
+ ret = stream_push(rq->dma, rq->dma_buf, num, false);
assert(ret == num);
xlnx_zynqmp_qspips_check_flush(rq);
}
@@ -1360,8 +1360,7 @@
object_property_add_link(obj, "stream-connected-dma", TYPE_STREAM_SLAVE,
(Object **)&rq->dma,
object_property_allow_set_link,
- OBJ_PROP_LINK_STRONG,
- NULL);
+ OBJ_PROP_LINK_STRONG);
}
static int xilinx_spips_post_load(void *opaque, int version_id)
diff --git a/hw/timer/exynos4210_mct.c b/hw/timer/exynos4210_mct.c
index 570cf70..29a4b10 100644
--- a/hw/timer/exynos4210_mct.c
+++ b/hw/timer/exynos4210_mct.c
@@ -54,7 +54,6 @@
#include "qemu/osdep.h"
#include "qemu/log.h"
-#include "hw/hw.h"
#include "hw/sysbus.h"
#include "migration/vmstate.h"
#include "qemu/timer.h"
@@ -62,7 +61,6 @@
#include "hw/ptimer.h"
#include "hw/arm/exynos4210.h"
-#include "hw/hw.h"
#include "hw/irq.h"
//#define DEBUG_MCT
@@ -1062,7 +1060,7 @@
int index;
int shift;
uint64_t count;
- uint32_t value;
+ uint32_t value = 0;
int lt_i;
switch (offset) {
@@ -1158,8 +1156,8 @@
break;
default:
- hw_error("exynos4210.mct: bad read offset "
- TARGET_FMT_plx "\n", offset);
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: Bad offset 0x%" HWADDR_PRIX "\n",
+ __func__, offset);
break;
}
return value;
@@ -1484,8 +1482,8 @@
break;
default:
- hw_error("exynos4210.mct: bad write offset "
- TARGET_FMT_plx "\n", offset);
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: Bad offset 0x%" HWADDR_PRIX "\n",
+ __func__, offset);
break;
}
}
diff --git a/hw/tpm/tpm_tis_common.c b/hw/tpm/tpm_tis_common.c
index 9ce64d4..1af4bce 100644
--- a/hw/tpm/tpm_tis_common.c
+++ b/hw/tpm/tpm_tis_common.c
@@ -536,7 +536,7 @@
while ((TPM_TIS_IS_VALID_LOCTY(s->active_locty) &&
locty > s->active_locty) ||
!TPM_TIS_IS_VALID_LOCTY(s->active_locty)) {
- bool higher_seize = FALSE;
+ bool higher_seize = false;
/* already a pending SEIZE ? */
if ((s->loc[locty].access & TPM_TIS_ACCESS_SEIZE)) {
@@ -546,7 +546,7 @@
/* check for ongoing seize by a higher locality */
for (l = locty + 1; l < TPM_TIS_NUM_LOCALITIES; l++) {
if ((s->loc[l].access & TPM_TIS_ACCESS_SEIZE)) {
- higher_seize = TRUE;
+ higher_seize = true;
break;
}
}
diff --git a/hw/usb/bus.c b/hw/usb/bus.c
index c9a3900..fa07df9 100644
--- a/hw/usb/bus.c
+++ b/hw/usb/bus.c
@@ -14,7 +14,7 @@
static char *usb_get_dev_path(DeviceState *dev);
static char *usb_get_fw_dev_path(DeviceState *qdev);
-static void usb_qdev_unrealize(DeviceState *qdev, Error **errp);
+static void usb_qdev_unrealize(DeviceState *qdev);
static Property usb_props[] = {
DEFINE_PROP_STRING("port", USBDevice, port_path),
@@ -130,12 +130,12 @@
return NULL;
}
-static void usb_device_unrealize(USBDevice *dev, Error **errp)
+static void usb_device_unrealize(USBDevice *dev)
{
USBDeviceClass *klass = USB_DEVICE_GET_CLASS(dev);
if (klass->unrealize) {
- klass->unrealize(dev, errp);
+ klass->unrealize(dev);
}
}
@@ -265,14 +265,14 @@
if (dev->auto_attach) {
usb_device_attach(dev, &local_err);
if (local_err) {
- usb_qdev_unrealize(qdev, NULL);
+ usb_qdev_unrealize(qdev);
error_propagate(errp, local_err);
return;
}
}
}
-static void usb_qdev_unrealize(DeviceState *qdev, Error **errp)
+static void usb_qdev_unrealize(DeviceState *qdev)
{
USBDevice *dev = USB_DEVICE(qdev);
USBDescString *s, *next;
@@ -286,7 +286,7 @@
if (dev->attached) {
usb_device_detach(dev);
}
- usb_device_unrealize(dev, errp);
+ usb_device_unrealize(dev);
if (dev->port) {
usb_release_port(dev);
}
@@ -753,12 +753,10 @@
if (klass->attached_settable) {
object_property_add_bool(obj, "attached",
- usb_get_attached, usb_set_attached,
- NULL);
+ usb_get_attached, usb_set_attached);
} else {
object_property_add_bool(obj, "attached",
- usb_get_attached, NULL,
- NULL);
+ usb_get_attached, NULL);
}
}
diff --git a/hw/usb/ccid-card-emulated.c b/hw/usb/ccid-card-emulated.c
index 3083124..7d6105e 100644
--- a/hw/usb/ccid-card-emulated.c
+++ b/hw/usb/ccid-card-emulated.c
@@ -562,7 +562,7 @@
qemu_mutex_destroy(&card->event_list_mutex);
}
-static void emulated_unrealize(CCIDCardState *base, Error **errp)
+static void emulated_unrealize(CCIDCardState *base)
{
EmulatedState *card = EMULATED_CCID_CARD(base);
VEvent *vevent = vevent_new(VEVENT_LAST, NULL, NULL);
diff --git a/hw/usb/ccid.h b/hw/usb/ccid.h
index bb2fdbf..531bf28 100644
--- a/hw/usb/ccid.h
+++ b/hw/usb/ccid.h
@@ -36,7 +36,7 @@
const uint8_t *apdu,
uint32_t len);
void (*realize)(CCIDCardState *card, Error **errp);
- void (*unrealize)(CCIDCardState *card, Error **errp);
+ void (*unrealize)(CCIDCardState *card);
} CCIDCardClass;
/*
diff --git a/hw/usb/dev-audio.c b/hw/usb/dev-audio.c
index 6fa213f..1371c44 100644
--- a/hw/usb/dev-audio.c
+++ b/hw/usb/dev-audio.c
@@ -923,7 +923,7 @@
}
}
-static void usb_audio_unrealize(USBDevice *dev, Error **errp)
+static void usb_audio_unrealize(USBDevice *dev)
{
USBAudioState *s = USB_AUDIO(dev);
diff --git a/hw/usb/dev-hid.c b/hw/usb/dev-hid.c
index 67ec8b6..89f63b6 100644
--- a/hw/usb/dev-hid.c
+++ b/hw/usb/dev-hid.c
@@ -699,7 +699,7 @@
}
}
-static void usb_hid_unrealize(USBDevice *dev, Error **errp)
+static void usb_hid_unrealize(USBDevice *dev)
{
USBHIDState *us = USB_HID(dev);
diff --git a/hw/usb/dev-hub.c b/hw/usb/dev-hub.c
index 49a573b..5f19dd9 100644
--- a/hw/usb/dev-hub.c
+++ b/hw/usb/dev-hub.c
@@ -565,7 +565,7 @@
}
}
-static void usb_hub_unrealize(USBDevice *dev, Error **errp)
+static void usb_hub_unrealize(USBDevice *dev)
{
USBHubState *s = (USBHubState *)dev;
int i;
diff --git a/hw/usb/dev-mtp.c b/hw/usb/dev-mtp.c
index 20717f0..1684281 100644
--- a/hw/usb/dev-mtp.c
+++ b/hw/usb/dev-mtp.c
@@ -631,8 +631,9 @@
int64_t id = qemu_file_monitor_add_watch(s->file_monitor, o->path, NULL,
file_monitor_event, s, &err);
if (id == -1) {
- error_report("usb-mtp: failed to add watch for %s: %s", o->path,
- error_get_pretty(err));
+ error_reportf_err(err,
+ "usb-mtp: failed to add watch for %s: ",
+ o->path);
error_free(err);
} else {
trace_usb_mtp_file_monitor_event(s->dev.addr, o->path,
@@ -1276,8 +1277,8 @@
s->file_monitor = qemu_file_monitor_new(&err);
if (err) {
- error_report("usb-mtp: file monitoring init failed: %s",
- error_get_pretty(err));
+ error_reportf_err(err,
+ "usb-mtp: file monitoring init failed: ");
error_free(err);
} else {
QTAILQ_INIT(&s->events);
diff --git a/hw/usb/dev-network.c b/hw/usb/dev-network.c
index 6210427..c697567 100644
--- a/hw/usb/dev-network.c
+++ b/hw/usb/dev-network.c
@@ -1326,7 +1326,7 @@
s->nic = NULL;
}
-static void usb_net_unrealize(USBDevice *dev, Error **errp)
+static void usb_net_unrealize(USBDevice *dev)
{
USBNetState *s = (USBNetState *) dev;
@@ -1381,7 +1381,7 @@
device_add_bootindex_property(obj, &s->conf.bootindex,
"bootindex", "/ethernet-phy@0",
- &dev->qdev, NULL);
+ &dev->qdev);
}
static const VMStateDescription vmstate_usb_net = {
diff --git a/hw/usb/dev-smartcard-reader.c b/hw/usb/dev-smartcard-reader.c
index ef72738..ada18c1 100644
--- a/hw/usb/dev-smartcard-reader.c
+++ b/hw/usb/dev-smartcard-reader.c
@@ -1146,7 +1146,7 @@
}
}
-static void ccid_unrealize(USBDevice *dev, Error **errp)
+static void ccid_unrealize(USBDevice *dev)
{
USBCCIDState *s = USB_CCID_DEV(dev);
@@ -1269,23 +1269,18 @@
ccid_on_slot_change(s, true);
}
-static void ccid_card_unrealize(DeviceState *qdev, Error **errp)
+static void ccid_card_unrealize(DeviceState *qdev)
{
CCIDCardState *card = CCID_CARD(qdev);
CCIDCardClass *cc = CCID_CARD_GET_CLASS(card);
USBDevice *dev = USB_DEVICE(qdev->parent_bus->parent);
USBCCIDState *s = USB_CCID_DEV(dev);
- Error *local_err = NULL;
if (ccid_card_inserted(s)) {
ccid_card_card_removed(card);
}
if (cc->unrealize) {
- cc->unrealize(card, &local_err);
- if (local_err != NULL) {
- error_propagate(errp, local_err);
- return;
- }
+ cc->unrealize(card);
}
s->card = NULL;
}
diff --git a/hw/usb/dev-storage.c b/hw/usb/dev-storage.c
index 5c4b57b..4eba475 100644
--- a/hw/usb/dev-storage.c
+++ b/hw/usb/dev-storage.c
@@ -753,7 +753,7 @@
{
object_property_add(obj, "bootindex", "int32",
usb_msd_get_bootindex,
- usb_msd_set_bootindex, NULL, NULL, NULL);
+ usb_msd_set_bootindex, NULL, NULL);
object_property_set_int(obj, -1, "bootindex", NULL);
}
diff --git a/hw/usb/dev-uas.c b/hw/usb/dev-uas.c
index 11a8684..a3a4d41 100644
--- a/hw/usb/dev-uas.c
+++ b/hw/usb/dev-uas.c
@@ -894,7 +894,7 @@
}
}
-static void usb_uas_unrealize(USBDevice *dev, Error **errp)
+static void usb_uas_unrealize(USBDevice *dev)
{
UASDevice *uas = USB_UAS(dev);
diff --git a/hw/usb/dev-wacom.c b/hw/usb/dev-wacom.c
index 8ed57b3..8aba44b 100644
--- a/hw/usb/dev-wacom.c
+++ b/hw/usb/dev-wacom.c
@@ -331,7 +331,7 @@
}
}
-static void usb_wacom_unrealize(USBDevice *dev, Error **errp)
+static void usb_wacom_unrealize(USBDevice *dev)
{
USBWacomState *s = (USBWacomState *) dev;
diff --git a/hw/usb/hcd-ehci-pci.c b/hw/usb/hcd-ehci-pci.c
index fc73a05..4c37c8e 100644
--- a/hw/usb/hcd-ehci-pci.c
+++ b/hw/usb/hcd-ehci-pci.c
@@ -105,7 +105,7 @@
EHCIPCIState *i = PCI_EHCI(dev);
EHCIState *s = &i->ehci;
- usb_ehci_unrealize(s, DEVICE(dev), NULL);
+ usb_ehci_unrealize(s, DEVICE(dev));
g_free(s->irq);
s->irq = NULL;
diff --git a/hw/usb/hcd-ehci.c b/hw/usb/hcd-ehci.c
index 29d49c2..1495e8f 100644
--- a/hw/usb/hcd-ehci.c
+++ b/hw/usb/hcd-ehci.c
@@ -2522,7 +2522,7 @@
s->vmstate = qemu_add_vm_change_state_handler(usb_ehci_vm_state_change, s);
}
-void usb_ehci_unrealize(EHCIState *s, DeviceState *dev, Error **errp)
+void usb_ehci_unrealize(EHCIState *s, DeviceState *dev)
{
trace_usb_ehci_unrealize();
diff --git a/hw/usb/hcd-ehci.h b/hw/usb/hcd-ehci.h
index edb5931..57b38cf 100644
--- a/hw/usb/hcd-ehci.h
+++ b/hw/usb/hcd-ehci.h
@@ -324,7 +324,7 @@
void usb_ehci_init(EHCIState *s, DeviceState *dev);
void usb_ehci_finalize(EHCIState *s);
void usb_ehci_realize(EHCIState *s, DeviceState *dev, Error **errp);
-void usb_ehci_unrealize(EHCIState *s, DeviceState *dev, Error **errp);
+void usb_ehci_unrealize(EHCIState *s, DeviceState *dev);
void ehci_reset(void *opaque);
#define TYPE_PCI_EHCI "pci-ehci-usb"
diff --git a/hw/usb/host-libusb.c b/hw/usb/host-libusb.c
index 2ac7a93..e284413 100644
--- a/hw/usb/host-libusb.c
+++ b/hw/usb/host-libusb.c
@@ -1101,10 +1101,10 @@
device_add_bootindex_property(obj, &s->bootindex,
"bootindex", NULL,
- &udev->qdev, NULL);
+ &udev->qdev);
}
-static void usb_host_unrealize(USBDevice *udev, Error **errp)
+static void usb_host_unrealize(USBDevice *udev)
{
USBHostDevice *s = USB_HOST_DEVICE(udev);
diff --git a/hw/usb/redirect.c b/hw/usb/redirect.c
index 45d8b76..417a60a 100644
--- a/hw/usb/redirect.c
+++ b/hw/usb/redirect.c
@@ -1468,7 +1468,7 @@
}
}
-static void usbredir_unrealize(USBDevice *udev, Error **errp)
+static void usbredir_unrealize(USBDevice *udev)
{
USBRedirDevice *dev = USB_REDIRECT(udev);
@@ -2595,7 +2595,7 @@
device_add_bootindex_property(obj, &dev->bootindex,
"bootindex", NULL,
- &udev->qdev, NULL);
+ &udev->qdev);
}
static const TypeInfo usbredir_dev_info = {
diff --git a/hw/usb/xen-usb.c b/hw/usb/xen-usb.c
index 961190d..4d266d7 100644
--- a/hw/usb/xen-usb.c
+++ b/hw/usb/xen-usb.c
@@ -30,6 +30,7 @@
#include "hw/usb.h"
#include "hw/xen/xen-legacy-backend.h"
#include "monitor/qdev.h"
+#include "qapi/error.h"
#include "qapi/qmp/qdict.h"
#include "qapi/qmp/qstring.h"
@@ -755,13 +756,16 @@
qdict_put_int(qdict, "port", port);
qdict_put_int(qdict, "hostbus", atoi(busid));
qdict_put_str(qdict, "hostport", portname);
- opts = qemu_opts_from_qdict(qemu_find_opts("device"), qdict, &local_err);
- if (local_err) {
- goto err;
- }
+ opts = qemu_opts_from_qdict(qemu_find_opts("device"), qdict,
+ &error_abort);
usbif->ports[port - 1].dev = USB_DEVICE(qdev_device_add(opts, &local_err));
if (!usbif->ports[port - 1].dev) {
- goto err;
+ qobject_unref(qdict);
+ xen_pv_printf(&usbif->xendev, 0,
+ "device %s could not be opened: %s\n",
+ busid, error_get_pretty(local_err));
+ error_free(local_err);
+ return;
}
qobject_unref(qdict);
speed = usbif->ports[port - 1].dev->speed;
@@ -793,11 +797,6 @@
usbback_hotplug_enq(usbif, port);
TR_BUS(&usbif->xendev, "port %d attached\n", port);
- return;
-
-err:
- qobject_unref(qdict);
- xen_pv_printf(&usbif->xendev, 0, "device %s could not be opened\n", busid);
}
static void usbback_process_port(struct usbback_info *usbif, unsigned port)
diff --git a/hw/vfio/ap.c b/hw/vfio/ap.c
index 8649ac1..95564c1 100644
--- a/hw/vfio/ap.c
+++ b/hw/vfio/ap.c
@@ -124,7 +124,7 @@
vfio_put_group(vfio_group);
}
-static void vfio_ap_unrealize(DeviceState *dev, Error **errp)
+static void vfio_ap_unrealize(DeviceState *dev)
{
APDevice *apdev = AP_DEVICE(dev);
VFIOAPDevice *vapdev = VFIO_AP_DEVICE(apdev);
diff --git a/hw/vfio/ccw.c b/hw/vfio/ccw.c
index 50cc2ec..c862494 100644
--- a/hw/vfio/ccw.c
+++ b/hw/vfio/ccw.c
@@ -521,13 +521,13 @@
vfio_put_group(group);
out_group_err:
if (cdc->unrealize) {
- cdc->unrealize(cdev, NULL);
+ cdc->unrealize(cdev);
}
out_err_propagate:
error_propagate(errp, err);
}
-static void vfio_ccw_unrealize(DeviceState *dev, Error **errp)
+static void vfio_ccw_unrealize(DeviceState *dev)
{
CcwDevice *ccw_dev = DO_UPCAST(CcwDevice, parent_obj, dev);
S390CCWDevice *cdev = DO_UPCAST(S390CCWDevice, parent_obj, ccw_dev);
@@ -541,7 +541,7 @@
vfio_put_group(group);
if (cdc->unrealize) {
- cdc->unrealize(cdev, errp);
+ cdc->unrealize(cdev);
}
}
diff --git a/hw/vfio/display.c b/hw/vfio/display.c
index f4977c6..a57a226 100644
--- a/hw/vfio/display.c
+++ b/hw/vfio/display.c
@@ -353,7 +353,7 @@
&vfio_display_dmabuf_ops,
vdev);
if (vdev->enable_ramfb) {
- vdev->dpy->ramfb = ramfb_setup(DEVICE(vdev), errp);
+ vdev->dpy->ramfb = ramfb_setup(errp);
}
vfio_display_edid_init(vdev);
return 0;
@@ -479,7 +479,7 @@
&vfio_display_region_ops,
vdev);
if (vdev->enable_ramfb) {
- vdev->dpy->ramfb = ramfb_setup(DEVICE(vdev), errp);
+ vdev->dpy->ramfb = ramfb_setup(errp);
}
return 0;
}
diff --git a/hw/vfio/pci-quirks.c b/hw/vfio/pci-quirks.c
index 2d348f8..f2155dd 100644
--- a/hw/vfio/pci-quirks.c
+++ b/hw/vfio/pci-quirks.c
@@ -1620,7 +1620,7 @@
}
cap = (void *) hdr;
- p = mmap(NULL, nv2reg->size, PROT_READ | PROT_WRITE | PROT_EXEC,
+ p = mmap(NULL, nv2reg->size, PROT_READ | PROT_WRITE,
MAP_SHARED, vdev->vbasedev.fd, nv2reg->offset);
if (p == MAP_FAILED) {
ret = -errno;
@@ -1634,7 +1634,7 @@
object_property_add(OBJECT(vdev), "nvlink2-tgt", "uint64",
vfio_pci_nvlink2_get_tgt, NULL, NULL,
- (void *) (uintptr_t) cap->tgt, NULL);
+ (void *) (uintptr_t) cap->tgt);
trace_vfio_pci_nvidia_gpu_setup_quirk(vdev->vbasedev.name, cap->tgt,
nv2reg->size);
free_exit:
@@ -1680,7 +1680,7 @@
/* Some NVLink bridges may not have assigned ATSD */
if (atsdreg->size) {
- p = mmap(NULL, atsdreg->size, PROT_READ | PROT_WRITE | PROT_EXEC,
+ p = mmap(NULL, atsdreg->size, PROT_READ | PROT_WRITE,
MAP_SHARED, vdev->vbasedev.fd, atsdreg->offset);
if (p == MAP_FAILED) {
ret = -errno;
@@ -1695,13 +1695,13 @@
object_property_add(OBJECT(vdev), "nvlink2-tgt", "uint64",
vfio_pci_nvlink2_get_tgt, NULL, NULL,
- (void *) (uintptr_t) captgt->tgt, NULL);
+ (void *) (uintptr_t) captgt->tgt);
trace_vfio_pci_nvlink2_setup_quirk_ssatgt(vdev->vbasedev.name, captgt->tgt,
atsdreg->size);
object_property_add(OBJECT(vdev), "nvlink2-link-speed", "uint32",
vfio_pci_nvlink2_get_link_speed, NULL, NULL,
- (void *) (uintptr_t) capspeed->link_speed, NULL);
+ (void *) (uintptr_t) capspeed->link_speed);
trace_vfio_pci_nvlink2_setup_quirk_lnkspd(vdev->vbasedev.name,
capspeed->link_speed);
free_exit:
diff --git a/hw/vfio/pci.c b/hw/vfio/pci.c
index 5e75a95..342dd6b 100644
--- a/hw/vfio/pci.c
+++ b/hw/vfio/pci.c
@@ -3133,7 +3133,7 @@
device_add_bootindex_property(obj, &vdev->bootindex,
"bootindex", NULL,
- &pci_dev->qdev, NULL);
+ &pci_dev->qdev);
vdev->host.domain = ~0U;
vdev->host.bus = ~0U;
vdev->host.slot = ~0U;
diff --git a/hw/virtio/vhost-scsi-pci.c b/hw/virtio/vhost-scsi-pci.c
index 5dce640..5da6bb6 100644
--- a/hw/virtio/vhost-scsi-pci.c
+++ b/hw/virtio/vhost-scsi-pci.c
@@ -78,7 +78,7 @@
virtio_instance_init_common(obj, &dev->vdev, sizeof(dev->vdev),
TYPE_VHOST_SCSI);
object_property_add_alias(obj, "bootindex", OBJECT(&dev->vdev),
- "bootindex", &error_abort);
+ "bootindex");
}
static const VirtioPCIDeviceTypeInfo vhost_scsi_pci_info = {
diff --git a/hw/virtio/vhost-user-blk-pci.c b/hw/virtio/vhost-user-blk-pci.c
index 8d3d766..58d7c31 100644
--- a/hw/virtio/vhost-user-blk-pci.c
+++ b/hw/virtio/vhost-user-blk-pci.c
@@ -84,7 +84,7 @@
virtio_instance_init_common(obj, &dev->vdev, sizeof(dev->vdev),
TYPE_VHOST_USER_BLK);
object_property_add_alias(obj, "bootindex", OBJECT(&dev->vdev),
- "bootindex", &error_abort);
+ "bootindex");
}
static const VirtioPCIDeviceTypeInfo vhost_user_blk_pci_info = {
diff --git a/hw/virtio/vhost-user-fs.c b/hw/virtio/vhost-user-fs.c
index 6136768..1bc5d03 100644
--- a/hw/virtio/vhost-user-fs.c
+++ b/hw/virtio/vhost-user-fs.c
@@ -241,7 +241,7 @@
return;
}
-static void vuf_device_unrealize(DeviceState *dev, Error **errp)
+static void vuf_device_unrealize(DeviceState *dev)
{
VirtIODevice *vdev = VIRTIO_DEVICE(dev);
VHostUserFS *fs = VHOST_USER_FS(dev);
diff --git a/hw/virtio/vhost-user-input-pci.c b/hw/virtio/vhost-user-input-pci.c
index ae9cff9..0a50015 100644
--- a/hw/virtio/vhost-user-input-pci.c
+++ b/hw/virtio/vhost-user-input-pci.c
@@ -31,8 +31,7 @@
TYPE_VHOST_USER_INPUT);
object_property_add_alias(obj, "chardev",
- OBJECT(&dev->vhi), "chardev",
- &error_abort);
+ OBJECT(&dev->vhi), "chardev");
}
static const VirtioPCIDeviceTypeInfo vhost_user_input_pci_info = {
diff --git a/hw/virtio/vhost-user-scsi-pci.c b/hw/virtio/vhost-user-scsi-pci.c
index 32febb2..6f3375f 100644
--- a/hw/virtio/vhost-user-scsi-pci.c
+++ b/hw/virtio/vhost-user-scsi-pci.c
@@ -84,7 +84,7 @@
virtio_instance_init_common(obj, &dev->vdev, sizeof(dev->vdev),
TYPE_VHOST_USER_SCSI);
object_property_add_alias(obj, "bootindex", OBJECT(&dev->vdev),
- "bootindex", &error_abort);
+ "bootindex");
}
static const VirtioPCIDeviceTypeInfo vhost_user_scsi_pci_info = {
diff --git a/hw/virtio/vhost-vsock.c b/hw/virtio/vhost-vsock.c
index 09b6b07..4a228f5 100644
--- a/hw/virtio/vhost-vsock.c
+++ b/hw/virtio/vhost-vsock.c
@@ -377,7 +377,7 @@
return;
}
-static void vhost_vsock_device_unrealize(DeviceState *dev, Error **errp)
+static void vhost_vsock_device_unrealize(DeviceState *dev)
{
VirtIODevice *vdev = VIRTIO_DEVICE(dev);
VHostVSock *vsock = VHOST_VSOCK(dev);
diff --git a/hw/virtio/virtio-balloon-pci.c b/hw/virtio/virtio-balloon-pci.c
index 56962ae..cc25df0 100644
--- a/hw/virtio/virtio-balloon-pci.c
+++ b/hw/virtio/virtio-balloon-pci.c
@@ -73,10 +73,10 @@
virtio_instance_init_common(obj, &dev->vdev, sizeof(dev->vdev),
TYPE_VIRTIO_BALLOON);
object_property_add_alias(obj, "guest-stats", OBJECT(&dev->vdev),
- "guest-stats", &error_abort);
+ "guest-stats");
object_property_add_alias(obj, "guest-stats-polling-interval",
OBJECT(&dev->vdev),
- "guest-stats-polling-interval", &error_abort);
+ "guest-stats-polling-interval");
}
static const VirtioPCIDeviceTypeInfo virtio_balloon_pci_info = {
diff --git a/hw/virtio/virtio-balloon.c b/hw/virtio/virtio-balloon.c
index a4729f7..065cd45 100644
--- a/hw/virtio/virtio-balloon.c
+++ b/hw/virtio/virtio-balloon.c
@@ -819,7 +819,7 @@
reset_stats(s);
}
-static void virtio_balloon_device_unrealize(DeviceState *dev, Error **errp)
+static void virtio_balloon_device_unrealize(DeviceState *dev)
{
VirtIODevice *vdev = VIRTIO_DEVICE(dev);
VirtIOBalloon *s = VIRTIO_BALLOON(dev);
@@ -893,12 +893,12 @@
VirtIOBalloon *s = VIRTIO_BALLOON(obj);
object_property_add(obj, "guest-stats", "guest statistics",
- balloon_stats_get_all, NULL, NULL, s, NULL);
+ balloon_stats_get_all, NULL, NULL, s);
object_property_add(obj, "guest-stats-polling-interval", "int",
balloon_stats_get_poll_interval,
balloon_stats_set_poll_interval,
- NULL, s, NULL);
+ NULL, s);
}
static const VMStateDescription vmstate_virtio_balloon = {
diff --git a/hw/virtio/virtio-blk-pci.c b/hw/virtio/virtio-blk-pci.c
index efb2c22..28838fa 100644
--- a/hw/virtio/virtio-blk-pci.c
+++ b/hw/virtio/virtio-blk-pci.c
@@ -81,7 +81,7 @@
virtio_instance_init_common(obj, &dev->vdev, sizeof(dev->vdev),
TYPE_VIRTIO_BLK);
object_property_add_alias(obj, "bootindex", OBJECT(&dev->vdev),
- "bootindex", &error_abort);
+ "bootindex");
}
static const VirtioPCIDeviceTypeInfo virtio_blk_pci_info = {
diff --git a/hw/virtio/virtio-crypto.c b/hw/virtio/virtio-crypto.c
index 4c65114..bd9165c 100644
--- a/hw/virtio/virtio-crypto.c
+++ b/hw/virtio/virtio-crypto.c
@@ -822,7 +822,7 @@
cryptodev_backend_set_used(vcrypto->cryptodev, true);
}
-static void virtio_crypto_device_unrealize(DeviceState *dev, Error **errp)
+static void virtio_crypto_device_unrealize(DeviceState *dev)
{
VirtIODevice *vdev = VIRTIO_DEVICE(dev);
VirtIOCrypto *vcrypto = VIRTIO_CRYPTO(dev);
diff --git a/hw/virtio/virtio-iommu.c b/hw/virtio/virtio-iommu.c
index 22ba884..483883e 100644
--- a/hw/virtio/virtio-iommu.c
+++ b/hw/virtio/virtio-iommu.c
@@ -688,7 +688,7 @@
}
}
-static void virtio_iommu_device_unrealize(DeviceState *dev, Error **errp)
+static void virtio_iommu_device_unrealize(DeviceState *dev)
{
VirtIODevice *vdev = VIRTIO_DEVICE(dev);
VirtIOIOMMU *s = VIRTIO_IOMMU(dev);
diff --git a/hw/virtio/virtio-net-pci.c b/hw/virtio/virtio-net-pci.c
index 5ca71d4..ea43040 100644
--- a/hw/virtio/virtio-net-pci.c
+++ b/hw/virtio/virtio-net-pci.c
@@ -79,7 +79,7 @@
virtio_instance_init_common(obj, &dev->vdev, sizeof(dev->vdev),
TYPE_VIRTIO_NET);
object_property_add_alias(obj, "bootindex", OBJECT(&dev->vdev),
- "bootindex", &error_abort);
+ "bootindex");
}
static const VirtioPCIDeviceTypeInfo virtio_net_pci_info = {
diff --git a/hw/virtio/virtio-pmem.c b/hw/virtio/virtio-pmem.c
index 4339952..c3374b2 100644
--- a/hw/virtio/virtio-pmem.c
+++ b/hw/virtio/virtio-pmem.c
@@ -124,7 +124,7 @@
pmem->rq_vq = virtio_add_queue(vdev, 128, virtio_pmem_flush);
}
-static void virtio_pmem_unrealize(DeviceState *dev, Error **errp)
+static void virtio_pmem_unrealize(DeviceState *dev)
{
VirtIODevice *vdev = VIRTIO_DEVICE(dev);
VirtIOPMEM *pmem = VIRTIO_PMEM(dev);
diff --git a/hw/virtio/virtio-rng.c b/hw/virtio/virtio-rng.c
index 1e363ad..a8df41b 100644
--- a/hw/virtio/virtio-rng.c
+++ b/hw/virtio/virtio-rng.c
@@ -203,7 +203,7 @@
}
object_property_add_child(OBJECT(dev), "default-backend",
- default_backend, &error_abort);
+ default_backend);
/* The child property took a reference, we can safely drop ours now */
object_unref(default_backend);
@@ -230,7 +230,7 @@
vrng);
}
-static void virtio_rng_device_unrealize(DeviceState *dev, Error **errp)
+static void virtio_rng_device_unrealize(DeviceState *dev)
{
VirtIODevice *vdev = VIRTIO_DEVICE(dev);
VirtIORNG *vrng = VIRTIO_RNG(dev);
diff --git a/hw/virtio/virtio.c b/hw/virtio/virtio.c
index b6c8ef5..850fcce 100644
--- a/hw/virtio/virtio.c
+++ b/hw/virtio/virtio.c
@@ -3622,7 +3622,7 @@
virtio_bus_device_plugged(vdev, &err);
if (err != NULL) {
error_propagate(errp, err);
- vdc->unrealize(dev, NULL);
+ vdc->unrealize(dev);
return;
}
@@ -3630,20 +3630,15 @@
memory_listener_register(&vdev->listener, vdev->dma_as);
}
-static void virtio_device_unrealize(DeviceState *dev, Error **errp)
+static void virtio_device_unrealize(DeviceState *dev)
{
VirtIODevice *vdev = VIRTIO_DEVICE(dev);
VirtioDeviceClass *vdc = VIRTIO_DEVICE_GET_CLASS(dev);
- Error *err = NULL;
virtio_bus_device_unplugged(vdev);
if (vdc->unrealize != NULL) {
- vdc->unrealize(dev, &err);
- if (err != NULL) {
- error_propagate(errp, err);
- return;
- }
+ vdc->unrealize(dev);
}
g_free(vdev->bus_name);
diff --git a/hw/watchdog/Kconfig b/hw/watchdog/Kconfig
index 2118d89..293209b 100644
--- a/hw/watchdog/Kconfig
+++ b/hw/watchdog/Kconfig
@@ -14,3 +14,6 @@
config WDT_DIAG288
bool
+
+config WDT_IMX2
+ bool
diff --git a/hw/watchdog/Makefile.objs b/hw/watchdog/Makefile.objs
index 3f536d1..631b711 100644
--- a/hw/watchdog/Makefile.objs
+++ b/hw/watchdog/Makefile.objs
@@ -4,3 +4,4 @@
common-obj-$(CONFIG_WDT_IB700) += wdt_ib700.o
common-obj-$(CONFIG_WDT_DIAG288) += wdt_diag288.o
common-obj-$(CONFIG_ASPEED_SOC) += wdt_aspeed.o
+common-obj-$(CONFIG_WDT_IMX2) += wdt_imx2.o
diff --git a/hw/watchdog/wdt_diag288.c b/hw/watchdog/wdt_diag288.c
index 5b6eb2b..71a945f 100644
--- a/hw/watchdog/wdt_diag288.c
+++ b/hw/watchdog/wdt_diag288.c
@@ -108,7 +108,7 @@
dev);
}
-static void wdt_diag288_unrealize(DeviceState *dev, Error **errp)
+static void wdt_diag288_unrealize(DeviceState *dev)
{
DIAG288State *diag288 = DIAG288(dev);
diff --git a/hw/watchdog/wdt_imx2.c b/hw/watchdog/wdt_imx2.c
new file mode 100644
index 0000000..a5fb763
--- /dev/null
+++ b/hw/watchdog/wdt_imx2.c
@@ -0,0 +1,304 @@
+/*
+ * Copyright (c) 2018, Impinj, Inc.
+ *
+ * i.MX2 Watchdog IP block
+ *
+ * Author: Andrey Smirnov <andrew.smirnov@gmail.com>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ */
+
+#include "qemu/osdep.h"
+#include "qemu/bitops.h"
+#include "qemu/module.h"
+#include "sysemu/watchdog.h"
+#include "migration/vmstate.h"
+#include "hw/qdev-properties.h"
+
+#include "hw/watchdog/wdt_imx2.h"
+
+static void imx2_wdt_interrupt(void *opaque)
+{
+ IMX2WdtState *s = IMX2_WDT(opaque);
+
+ s->wicr |= IMX2_WDT_WICR_WTIS;
+ qemu_set_irq(s->irq, 1);
+}
+
+static void imx2_wdt_expired(void *opaque)
+{
+ IMX2WdtState *s = IMX2_WDT(opaque);
+
+ s->wrsr = IMX2_WDT_WRSR_TOUT;
+
+ /* Perform watchdog action if watchdog is enabled */
+ if (s->wcr & IMX2_WDT_WCR_WDE) {
+ s->wrsr = IMX2_WDT_WRSR_TOUT;
+ watchdog_perform_action();
+ }
+}
+
+static void imx2_wdt_reset(DeviceState *dev)
+{
+ IMX2WdtState *s = IMX2_WDT(dev);
+
+ ptimer_transaction_begin(s->timer);
+ ptimer_stop(s->timer);
+ ptimer_transaction_commit(s->timer);
+
+ if (s->pretimeout_support) {
+ ptimer_transaction_begin(s->itimer);
+ ptimer_stop(s->itimer);
+ ptimer_transaction_commit(s->itimer);
+ }
+
+ s->wicr_locked = false;
+ s->wcr_locked = false;
+ s->wcr_wde_locked = false;
+
+ s->wcr = IMX2_WDT_WCR_WDA | IMX2_WDT_WCR_SRS;
+ s->wsr = 0;
+ s->wrsr &= ~(IMX2_WDT_WRSR_TOUT | IMX2_WDT_WRSR_SFTW);
+ s->wicr = IMX2_WDT_WICR_WICT_DEF;
+ s->wmcr = IMX2_WDT_WMCR_PDE;
+}
+
+static uint64_t imx2_wdt_read(void *opaque, hwaddr addr, unsigned int size)
+{
+ IMX2WdtState *s = IMX2_WDT(opaque);
+
+ switch (addr) {
+ case IMX2_WDT_WCR:
+ return s->wcr;
+ case IMX2_WDT_WSR:
+ return s->wsr;
+ case IMX2_WDT_WRSR:
+ return s->wrsr;
+ case IMX2_WDT_WICR:
+ return s->wicr;
+ case IMX2_WDT_WMCR:
+ return s->wmcr;
+ }
+ return 0;
+}
+
+static void imx_wdt2_update_itimer(IMX2WdtState *s, bool start)
+{
+ bool running = (s->wcr & IMX2_WDT_WCR_WDE) && (s->wcr & IMX2_WDT_WCR_WT);
+ bool enabled = s->wicr & IMX2_WDT_WICR_WIE;
+
+ ptimer_transaction_begin(s->itimer);
+ if (start || !enabled) {
+ ptimer_stop(s->itimer);
+ }
+ if (running && enabled) {
+ int count = ptimer_get_count(s->timer);
+ int pretimeout = s->wicr & IMX2_WDT_WICR_WICT;
+
+ /*
+ * Only (re-)start pretimeout timer if its counter value is larger
+ * than 0. Otherwise it will fire right away and we'll get an
+ * interrupt loop.
+ */
+ if (count > pretimeout) {
+ ptimer_set_count(s->itimer, count - pretimeout);
+ if (start) {
+ ptimer_run(s->itimer, 1);
+ }
+ }
+ }
+ ptimer_transaction_commit(s->itimer);
+}
+
+static void imx_wdt2_update_timer(IMX2WdtState *s, bool start)
+{
+ ptimer_transaction_begin(s->timer);
+ if (start) {
+ ptimer_stop(s->timer);
+ }
+ if ((s->wcr & IMX2_WDT_WCR_WDE) && (s->wcr & IMX2_WDT_WCR_WT)) {
+ int count = (s->wcr & IMX2_WDT_WCR_WT) >> 8;
+
+ /* A value of 0 reflects one period (0.5s). */
+ ptimer_set_count(s->timer, count + 1);
+ if (start) {
+ ptimer_run(s->timer, 1);
+ }
+ }
+ ptimer_transaction_commit(s->timer);
+ if (s->pretimeout_support) {
+ imx_wdt2_update_itimer(s, start);
+ }
+}
+
+static void imx2_wdt_write(void *opaque, hwaddr addr,
+ uint64_t value, unsigned int size)
+{
+ IMX2WdtState *s = IMX2_WDT(opaque);
+
+ switch (addr) {
+ case IMX2_WDT_WCR:
+ if (s->wcr_locked) {
+ value &= ~IMX2_WDT_WCR_LOCK_MASK;
+ value |= (s->wicr & IMX2_WDT_WCR_LOCK_MASK);
+ }
+ s->wcr_locked = true;
+ if (s->wcr_wde_locked) {
+ value &= ~IMX2_WDT_WCR_WDE;
+ value |= (s->wicr & ~IMX2_WDT_WCR_WDE);
+ } else if (value & IMX2_WDT_WCR_WDE) {
+ s->wcr_wde_locked = true;
+ }
+ if (s->wcr_wdt_locked) {
+ value &= ~IMX2_WDT_WCR_WDT;
+ value |= (s->wicr & ~IMX2_WDT_WCR_WDT);
+ } else if (value & IMX2_WDT_WCR_WDT) {
+ s->wcr_wdt_locked = true;
+ }
+
+ s->wcr = value;
+ if (!(value & IMX2_WDT_WCR_SRS)) {
+ s->wrsr = IMX2_WDT_WRSR_SFTW;
+ }
+ if (!(value & (IMX2_WDT_WCR_WDA | IMX2_WDT_WCR_SRS)) ||
+ (!(value & IMX2_WDT_WCR_WT) && (value & IMX2_WDT_WCR_WDE))) {
+ watchdog_perform_action();
+ }
+ s->wcr |= IMX2_WDT_WCR_SRS;
+ imx_wdt2_update_timer(s, true);
+ break;
+ case IMX2_WDT_WSR:
+ if (s->wsr == IMX2_WDT_SEQ1 && value == IMX2_WDT_SEQ2) {
+ imx_wdt2_update_timer(s, false);
+ }
+ s->wsr = value;
+ break;
+ case IMX2_WDT_WRSR:
+ break;
+ case IMX2_WDT_WICR:
+ if (!s->pretimeout_support) {
+ return;
+ }
+ value &= IMX2_WDT_WICR_LOCK_MASK | IMX2_WDT_WICR_WTIS;
+ if (s->wicr_locked) {
+ value &= IMX2_WDT_WICR_WTIS;
+ value |= (s->wicr & IMX2_WDT_WICR_LOCK_MASK);
+ }
+ s->wicr = value | (s->wicr & IMX2_WDT_WICR_WTIS);
+ if (value & IMX2_WDT_WICR_WTIS) {
+ s->wicr &= ~IMX2_WDT_WICR_WTIS;
+ qemu_set_irq(s->irq, 0);
+ }
+ imx_wdt2_update_itimer(s, true);
+ s->wicr_locked = true;
+ break;
+ case IMX2_WDT_WMCR:
+ s->wmcr = value & IMX2_WDT_WMCR_PDE;
+ break;
+ }
+}
+
+static const MemoryRegionOps imx2_wdt_ops = {
+ .read = imx2_wdt_read,
+ .write = imx2_wdt_write,
+ .endianness = DEVICE_NATIVE_ENDIAN,
+ .impl = {
+ /*
+ * Our device would not work correctly if the guest was doing
+ * unaligned access. This might not be a limitation on the
+ * real device but in practice there is no reason for a guest
+ * to access this device unaligned.
+ */
+ .min_access_size = 2,
+ .max_access_size = 2,
+ .unaligned = false,
+ },
+};
+
+static const VMStateDescription vmstate_imx2_wdt = {
+ .name = "imx2.wdt",
+ .fields = (VMStateField[]) {
+ VMSTATE_PTIMER(timer, IMX2WdtState),
+ VMSTATE_PTIMER(itimer, IMX2WdtState),
+ VMSTATE_BOOL(wicr_locked, IMX2WdtState),
+ VMSTATE_BOOL(wcr_locked, IMX2WdtState),
+ VMSTATE_BOOL(wcr_wde_locked, IMX2WdtState),
+ VMSTATE_BOOL(wcr_wdt_locked, IMX2WdtState),
+ VMSTATE_UINT16(wcr, IMX2WdtState),
+ VMSTATE_UINT16(wsr, IMX2WdtState),
+ VMSTATE_UINT16(wrsr, IMX2WdtState),
+ VMSTATE_UINT16(wmcr, IMX2WdtState),
+ VMSTATE_UINT16(wicr, IMX2WdtState),
+ VMSTATE_END_OF_LIST()
+ }
+};
+
+static void imx2_wdt_realize(DeviceState *dev, Error **errp)
+{
+ IMX2WdtState *s = IMX2_WDT(dev);
+ SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
+
+ memory_region_init_io(&s->mmio, OBJECT(dev),
+ &imx2_wdt_ops, s,
+ TYPE_IMX2_WDT,
+ IMX2_WDT_MMIO_SIZE);
+ sysbus_init_mmio(sbd, &s->mmio);
+ sysbus_init_irq(sbd, &s->irq);
+
+ s->timer = ptimer_init(imx2_wdt_expired, s,
+ PTIMER_POLICY_NO_IMMEDIATE_TRIGGER |
+ PTIMER_POLICY_NO_IMMEDIATE_RELOAD |
+ PTIMER_POLICY_NO_COUNTER_ROUND_DOWN);
+ ptimer_transaction_begin(s->timer);
+ ptimer_set_freq(s->timer, 2);
+ ptimer_set_limit(s->timer, 0xff, 1);
+ ptimer_transaction_commit(s->timer);
+ if (s->pretimeout_support) {
+ s->itimer = ptimer_init(imx2_wdt_interrupt, s,
+ PTIMER_POLICY_NO_IMMEDIATE_TRIGGER |
+ PTIMER_POLICY_NO_IMMEDIATE_RELOAD |
+ PTIMER_POLICY_NO_COUNTER_ROUND_DOWN);
+ ptimer_transaction_begin(s->itimer);
+ ptimer_set_freq(s->itimer, 2);
+ ptimer_set_limit(s->itimer, 0xff, 1);
+ ptimer_transaction_commit(s->itimer);
+ }
+}
+
+static Property imx2_wdt_properties[] = {
+ DEFINE_PROP_BOOL("pretimeout-support", IMX2WdtState, pretimeout_support,
+ false),
+ DEFINE_PROP_END_OF_LIST()
+};
+
+static void imx2_wdt_class_init(ObjectClass *klass, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(klass);
+
+ device_class_set_props(dc, imx2_wdt_properties);
+ dc->realize = imx2_wdt_realize;
+ dc->reset = imx2_wdt_reset;
+ dc->vmsd = &vmstate_imx2_wdt;
+ dc->desc = "i.MX watchdog timer";
+ set_bit(DEVICE_CATEGORY_MISC, dc->categories);
+}
+
+static const TypeInfo imx2_wdt_info = {
+ .name = TYPE_IMX2_WDT,
+ .parent = TYPE_SYS_BUS_DEVICE,
+ .instance_size = sizeof(IMX2WdtState),
+ .class_init = imx2_wdt_class_init,
+};
+
+static WatchdogTimerModel model = {
+ .wdt_name = "imx2-watchdog",
+ .wdt_description = "i.MX2 Watchdog",
+};
+
+static void imx2_wdt_register_type(void)
+{
+ watchdog_add_model(&model);
+ type_register_static(&imx2_wdt_info);
+}
+type_init(imx2_wdt_register_type)
diff --git a/hw/xen/xen-bus.c b/hw/xen/xen-bus.c
index 18237b3..32dd446 100644
--- a/hw/xen/xen-bus.c
+++ b/hw/xen/xen-bus.c
@@ -428,7 +428,7 @@
xen_bus_cleanup(xenbus);
}
-static void xen_bus_unrealize(BusState *bus, Error **errp)
+static void xen_bus_unrealize(BusState *bus)
{
XenBus *xenbus = XEN_BUS(bus);
@@ -486,7 +486,7 @@
return;
fail:
- xen_bus_unrealize(bus, &error_abort);
+ xen_bus_unrealize(bus);
}
static void xen_bus_unplug_request(HotplugHandler *hotplug,
@@ -1189,7 +1189,7 @@
g_free(channel);
}
-static void xen_device_unrealize(DeviceState *dev, Error **errp)
+static void xen_device_unrealize(DeviceState *dev)
{
XenDevice *xendev = XEN_DEVICE(dev);
XenDeviceClass *xendev_class = XEN_DEVICE_GET_CLASS(xendev);
@@ -1208,7 +1208,7 @@
}
if (xendev_class->unrealize) {
- xendev_class->unrealize(xendev, errp);
+ xendev_class->unrealize(xendev);
}
/* Make sure all event channels are cleaned up */
@@ -1242,7 +1242,7 @@
{
XenDevice *xendev = container_of(n, XenDevice, exit);
- xen_device_unrealize(DEVICE(xendev), &error_abort);
+ xen_device_unrealize(DEVICE(xendev));
}
static void xen_device_realize(DeviceState *dev, Error **errp)
@@ -1336,7 +1336,7 @@
return;
unrealize:
- xen_device_unrealize(dev, &error_abort);
+ xen_device_unrealize(dev);
}
static Property xen_device_props[] = {
diff --git a/hw/xen/xen-common.c b/hw/xen/xen-common.c
index a15070f..70564cc 100644
--- a/hw/xen/xen-common.c
+++ b/hw/xen/xen-common.c
@@ -198,10 +198,9 @@
compat_props_add(ac->compat_props, compat, G_N_ELEMENTS(compat));
object_class_property_add_bool(oc, "igd-passthru",
- xen_get_igd_gfx_passthru, xen_set_igd_gfx_passthru,
- &error_abort);
+ xen_get_igd_gfx_passthru, xen_set_igd_gfx_passthru);
object_class_property_set_description(oc, "igd-passthru",
- "Set on/off to enable/disable igd passthrou", &error_abort);
+ "Set on/off to enable/disable igd passthrou");
}
#define TYPE_XEN_ACCEL ACCEL_CLASS_NAME("xen")
diff --git a/hw/xen/xen-legacy-backend.c b/hw/xen/xen-legacy-backend.c
index 4a373b2..f9d0138 100644
--- a/hw/xen/xen-legacy-backend.c
+++ b/hw/xen/xen-legacy-backend.c
@@ -705,7 +705,7 @@
xen_sysdev = qdev_create(NULL, TYPE_XENSYSDEV);
qdev_init_nofail(xen_sysdev);
- xen_sysbus = qbus_create(TYPE_XENSYSBUS, DEVICE(xen_sysdev), "xen-sysbus");
+ xen_sysbus = qbus_create(TYPE_XENSYSBUS, xen_sysdev, "xen-sysbus");
qbus_set_bus_hotplug_handler(xen_sysbus, &error_abort);
return 0;
diff --git a/include/block/aio.h b/include/block/aio.h
index 62ed954..b2f703f 100644
--- a/include/block/aio.h
+++ b/include/block/aio.h
@@ -701,6 +701,9 @@
*/
void aio_context_destroy(AioContext *ctx);
+/* Used internally, do not call outside AioContext code */
+void aio_context_use_g_source(AioContext *ctx);
+
/**
* aio_context_set_poll_params:
* @ctx: the aio context
diff --git a/include/block/block.h b/include/block/block.h
index 4de8d8f..25e2996 100644
--- a/include/block/block.h
+++ b/include/block/block.h
@@ -13,7 +13,7 @@
/* block.c */
typedef struct BlockDriver BlockDriver;
typedef struct BdrvChild BdrvChild;
-typedef struct BdrvChildRole BdrvChildRole;
+typedef struct BdrvChildClass BdrvChildClass;
typedef struct BlockDriverInfo {
/* in bytes, 0 if irrelevant */
@@ -268,6 +268,62 @@
DEFAULT_PERM_UNCHANGED = BLK_PERM_ALL & ~DEFAULT_PERM_PASSTHROUGH,
};
+/*
+ * Flags that parent nodes assign to child nodes to specify what kind of
+ * role(s) they take.
+ *
+ * At least one of DATA, METADATA, FILTERED, or COW must be set for
+ * every child.
+ */
+enum BdrvChildRoleBits {
+ /*
+ * This child stores data.
+ * Any node may have an arbitrary number of such children.
+ */
+ BDRV_CHILD_DATA = (1 << 0),
+
+ /*
+ * This child stores metadata.
+ * Any node may have an arbitrary number of metadata-storing
+ * children.
+ */
+ BDRV_CHILD_METADATA = (1 << 1),
+
+ /*
+ * A child that always presents exactly the same visible data as
+ * the parent, e.g. by virtue of the parent forwarding all reads
+ * and writes.
+ * This flag is mutually exclusive with DATA, METADATA, and COW.
+ * Any node may have at most one filtered child at a time.
+ */
+ BDRV_CHILD_FILTERED = (1 << 2),
+
+ /*
+ * Child from which to read all data that isn’t allocated in the
+ * parent (i.e., the backing child); such data is copied to the
+ * parent through COW (and optionally COR).
+ * This field is mutually exclusive with DATA, METADATA, and
+ * FILTERED.
+ * Any node may have at most one such backing child at a time.
+ */
+ BDRV_CHILD_COW = (1 << 3),
+
+ /*
+ * The primary child. For most drivers, this is the child whose
+ * filename applies best to the parent node.
+ * Any node may have at most one primary child at a time.
+ */
+ BDRV_CHILD_PRIMARY = (1 << 4),
+
+ /* Useful combination of flags */
+ BDRV_CHILD_IMAGE = BDRV_CHILD_DATA
+ | BDRV_CHILD_METADATA
+ | BDRV_CHILD_PRIMARY,
+};
+
+/* Mask of BdrvChildRoleBits values */
+typedef unsigned int BdrvChildRole;
+
char *bdrv_perm_names(uint64_t perm);
uint64_t bdrv_qapi_perm_to_blk_perm(BlockPermission qapi_perm);
@@ -296,7 +352,8 @@
BdrvChild *bdrv_open_child(const char *filename,
QDict *options, const char *bdref_key,
BlockDriverState* parent,
- const BdrvChildRole *child_role,
+ const BdrvChildClass *child_class,
+ BdrvChildRole child_role,
bool allow_none, Error **errp);
BlockDriverState *bdrv_open_blockdev_ref(BlockdevRef *ref, Error **errp);
void bdrv_set_backing_hd(BlockDriverState *bs, BlockDriverState *backing_hd,
@@ -352,6 +409,7 @@
void bdrv_get_geometry(BlockDriverState *bs, uint64_t *nb_sectors_ptr);
void bdrv_refresh_limits(BlockDriverState *bs, Error **errp);
int bdrv_commit(BlockDriverState *bs);
+int bdrv_make_empty(BdrvChild *c, Error **errp);
int bdrv_change_backing_file(BlockDriverState *bs,
const char *backing_file, const char *backing_fmt);
void bdrv_register(BlockDriver *bdrv);
@@ -540,7 +598,8 @@
BdrvChild *bdrv_attach_child(BlockDriverState *parent_bs,
BlockDriverState *child_bs,
const char *child_name,
- const BdrvChildRole *child_role,
+ const BdrvChildClass *child_class,
+ BdrvChildRole child_role,
Error **errp);
bool bdrv_op_is_blocked(BlockDriverState *bs, BlockOpType op, Error **errp);
diff --git a/include/block/block_int.h b/include/block/block_int.h
index df6d027..791de6a 100644
--- a/include/block/block_int.h
+++ b/include/block/block_int.h
@@ -57,6 +57,7 @@
#define BLOCK_OPT_REFCOUNT_BITS "refcount_bits"
#define BLOCK_OPT_DATA_FILE "data_file"
#define BLOCK_OPT_DATA_FILE_RAW "data_file_raw"
+#define BLOCK_OPT_COMPRESSION_TYPE "compression_type"
#define BLOCK_PROBE_BUF_SIZE 512
@@ -95,6 +96,13 @@
*/
bool is_filter;
/*
+ * Set to true if the BlockDriver is a format driver. Format nodes
+ * generally do not expect their children to be other format nodes
+ * (except for backing files), and so format probing is disabled
+ * on those children.
+ */
+ bool is_format;
+ /*
* Return true if @to_replace can be replaced by a BDS with the
* same data as @bs without it affecting @bs's behavior (that is,
* without it being visible to @bs's parents).
@@ -548,18 +556,19 @@
* the parents in @parent_perm and @parent_shared.
*
* If @c is NULL, return the permissions for attaching a new child for the
- * given @role.
+ * given @child_class and @role.
*
* If @reopen_queue is non-NULL, don't return the currently needed
* permissions, but those that will be needed after applying the
* @reopen_queue.
*/
void (*bdrv_child_perm)(BlockDriverState *bs, BdrvChild *c,
- const BdrvChildRole *role,
+ BdrvChildRole role,
BlockReopenQueue *reopen_queue,
uint64_t parent_perm, uint64_t parent_shared,
uint64_t *nperm, uint64_t *nshared);
+ bool (*bdrv_supports_persistent_dirty_bitmap)(BlockDriverState *bs);
bool (*bdrv_co_can_store_new_dirty_bitmap)(BlockDriverState *bs,
const char *name,
uint32_t granularity,
@@ -657,7 +666,7 @@
QLIST_ENTRY(BdrvAioNotifier) list;
} BdrvAioNotifier;
-struct BdrvChildRole {
+struct BdrvChildClass {
/* If true, bdrv_replace_node() doesn't change the node this BdrvChild
* points to. */
bool stay_at_node;
@@ -668,7 +677,8 @@
* non-BDS parents. */
bool parent_is_bds;
- void (*inherit_options)(int *child_flags, QDict *child_options,
+ void (*inherit_options)(BdrvChildRole role, bool parent_is_format,
+ int *child_flags, QDict *child_options,
int parent_flags, QDict *parent_options);
void (*change_media)(BdrvChild *child, bool load);
@@ -730,14 +740,13 @@
void (*set_aio_ctx)(BdrvChild *child, AioContext *ctx, GSList **ignore);
};
-extern const BdrvChildRole child_file;
-extern const BdrvChildRole child_format;
-extern const BdrvChildRole child_backing;
+extern const BdrvChildClass child_of_bds;
struct BdrvChild {
BlockDriverState *bs;
char *name;
- const BdrvChildRole *role;
+ const BdrvChildClass *klass;
+ BdrvChildRole role;
void *opaque;
/**
@@ -764,7 +773,7 @@
/*
* How many times the parent of this child has been drained
- * (through role->drained_*).
+ * (through klass->drained_*).
* Usually, this is equal to bs->quiesce_counter (potentially
* reduced by bdrv_drain_all_count). It may differ while the
* child is entering or leaving a drained section.
@@ -1224,7 +1233,8 @@
BdrvChild *bdrv_root_attach_child(BlockDriverState *child_bs,
const char *child_name,
- const BdrvChildRole *child_role,
+ const BdrvChildClass *child_class,
+ BdrvChildRole child_role,
AioContext *ctx,
uint64_t perm, uint64_t shared_perm,
void *opaque, Error **errp);
@@ -1251,29 +1261,20 @@
*/
int bdrv_child_refresh_perms(BlockDriverState *bs, BdrvChild *c, Error **errp);
-/* Default implementation for BlockDriver.bdrv_child_perm() that can be used by
- * block filters: Forward CONSISTENT_READ, WRITE, WRITE_UNCHANGED and RESIZE to
- * all children */
-void bdrv_filter_default_perms(BlockDriverState *bs, BdrvChild *c,
- const BdrvChildRole *role,
- BlockReopenQueue *reopen_queue,
- uint64_t perm, uint64_t shared,
- uint64_t *nperm, uint64_t *nshared);
-
-/* Default implementation for BlockDriver.bdrv_child_perm() that can be used by
- * (non-raw) image formats: Like above for bs->backing, but for bs->file it
- * requires WRITE | RESIZE for read-write images, always requires
- * CONSISTENT_READ and doesn't share WRITE. */
-void bdrv_format_default_perms(BlockDriverState *bs, BdrvChild *c,
- const BdrvChildRole *role,
- BlockReopenQueue *reopen_queue,
- uint64_t perm, uint64_t shared,
- uint64_t *nperm, uint64_t *nshared);
-
bool bdrv_recurse_can_replace(BlockDriverState *bs,
BlockDriverState *to_replace);
/*
+ * Default implementation for BlockDriver.bdrv_child_perm() that can
+ * be used by block filters and image formats, as long as they use the
+ * child_of_bds child class and set an appropriate BdrvChildRole.
+ */
+void bdrv_default_perms(BlockDriverState *bs, BdrvChild *c,
+ BdrvChildRole role, BlockReopenQueue *reopen_queue,
+ uint64_t perm, uint64_t shared,
+ uint64_t *nperm, uint64_t *nshared);
+
+/*
* Default implementation for drivers to pass bdrv_co_block_status() to
* their file.
*/
@@ -1343,4 +1344,16 @@
Error **errp);
extern QemuOptsList bdrv_create_opts_simple;
+BdrvDirtyBitmap *block_dirty_bitmap_lookup(const char *node,
+ const char *name,
+ BlockDriverState **pbs,
+ Error **errp);
+BdrvDirtyBitmap *block_dirty_bitmap_merge(const char *node, const char *target,
+ BlockDirtyBitmapMergeSourceList *bms,
+ HBitmap **backup, Error **errp);
+BdrvDirtyBitmap *block_dirty_bitmap_remove(const char *node, const char *name,
+ bool release,
+ BlockDriverState **bitmap_bs,
+ Error **errp);
+
#endif /* BLOCK_INT_H */
diff --git a/include/block/dirty-bitmap.h b/include/block/dirty-bitmap.h
index 8a10029..36e8da4 100644
--- a/include/block/dirty-bitmap.h
+++ b/include/block/dirty-bitmap.h
@@ -16,6 +16,7 @@
#define BDRV_BITMAP_MAX_NAME_SIZE 1023
+bool bdrv_supports_persistent_dirty_bitmap(BlockDriverState *bs);
BdrvDirtyBitmap *bdrv_create_dirty_bitmap(BlockDriverState *bs,
uint32_t granularity,
const char *name,
@@ -94,6 +95,7 @@
void bdrv_dirty_bitmap_truncate(BlockDriverState *bs, int64_t bytes);
bool bdrv_dirty_bitmap_readonly(const BdrvDirtyBitmap *bitmap);
bool bdrv_has_readonly_bitmaps(BlockDriverState *bs);
+bool bdrv_has_named_bitmaps(BlockDriverState *bs);
bool bdrv_dirty_bitmap_get_autoload(const BdrvDirtyBitmap *bitmap);
bool bdrv_dirty_bitmap_get_persistence(BdrvDirtyBitmap *bitmap);
bool bdrv_dirty_bitmap_inconsistent(const BdrvDirtyBitmap *bitmap);
diff --git a/include/disas/disas.h b/include/disas/disas.h
index 36c33f6..1b6e035 100644
--- a/include/disas/disas.h
+++ b/include/disas/disas.h
@@ -7,7 +7,7 @@
#include "cpu.h"
/* Disassemble this for me please... (debugging). */
-void disas(FILE *out, void *code, unsigned long size);
+void disas(FILE *out, void *code, unsigned long size, const char *note);
void target_disas(FILE *out, CPUState *cpu, target_ulong code,
target_ulong size);
diff --git a/include/exec/cpu-all.h b/include/exec/cpu-all.h
index 43ddcf0..d14374b 100644
--- a/include/exec/cpu-all.h
+++ b/include/exec/cpu-all.h
@@ -159,15 +159,30 @@
* This allows the guest address space to be offset to a convenient location.
*/
extern unsigned long guest_base;
-extern int have_guest_base;
+extern bool have_guest_base;
extern unsigned long reserved_va;
-#if HOST_LONG_BITS <= TARGET_VIRT_ADDR_SPACE_BITS
-#define GUEST_ADDR_MAX (~0ul)
+/*
+ * Limit the guest addresses as best we can.
+ *
+ * When not using -R reserved_va, we cannot really limit the guest
+ * to less address space than the host. For 32-bit guests, this
+ * acts as a sanity check that we're not giving the guest an address
+ * that it cannot even represent. For 64-bit guests... the address
+ * might not be what the real kernel would give, but it is at least
+ * representable in the guest.
+ *
+ * TODO: Improve address allocation to avoid this problem, and to
+ * avoid setting bits at the top of guest addresses that might need
+ * to be used for tags.
+ */
+#if MIN(TARGET_VIRT_ADDR_SPACE_BITS, TARGET_ABI_BITS) <= 32
+# define GUEST_ADDR_MAX_ UINT32_MAX
#else
-#define GUEST_ADDR_MAX (reserved_va ? reserved_va - 1 : \
- (1ul << TARGET_VIRT_ADDR_SPACE_BITS) - 1)
+# define GUEST_ADDR_MAX_ (~0ul)
#endif
+#define GUEST_ADDR_MAX (reserved_va ? reserved_va - 1 : GUEST_ADDR_MAX_)
+
#else
#include "exec/hwaddr.h"
diff --git a/include/exec/log.h b/include/exec/log.h
index fcc7b9e..3ed797c 100644
--- a/include/exec/log.h
+++ b/include/exec/log.h
@@ -56,13 +56,13 @@
rcu_read_unlock();
}
-static inline void log_disas(void *code, unsigned long size)
+static inline void log_disas(void *code, unsigned long size, const char *note)
{
QemuLogFile *logfile;
rcu_read_lock();
logfile = atomic_rcu_read(&qemu_logfile);
if (logfile) {
- disas(logfile->fd, code, size);
+ disas(logfile->fd, code, size, note);
}
rcu_read_unlock();
}
diff --git a/include/fpu/softfloat-helpers.h b/include/fpu/softfloat-helpers.h
index e0baf24c..735ed6b 100644
--- a/include/fpu/softfloat-helpers.h
+++ b/include/fpu/softfloat-helpers.h
@@ -53,12 +53,13 @@
#include "fpu/softfloat-types.h"
-static inline void set_float_detect_tininess(int val, float_status *status)
+static inline void set_float_detect_tininess(bool val, float_status *status)
{
- status->float_detect_tininess = val;
+ status->tininess_before_rounding = val;
}
-static inline void set_float_rounding_mode(int val, float_status *status)
+static inline void set_float_rounding_mode(FloatRoundMode val,
+ float_status *status)
{
status->float_rounding_mode = val;
}
@@ -74,32 +75,32 @@
status->floatx80_rounding_precision = val;
}
-static inline void set_flush_to_zero(flag val, float_status *status)
+static inline void set_flush_to_zero(bool val, float_status *status)
{
status->flush_to_zero = val;
}
-static inline void set_flush_inputs_to_zero(flag val, float_status *status)
+static inline void set_flush_inputs_to_zero(bool val, float_status *status)
{
status->flush_inputs_to_zero = val;
}
-static inline void set_default_nan_mode(flag val, float_status *status)
+static inline void set_default_nan_mode(bool val, float_status *status)
{
status->default_nan_mode = val;
}
-static inline void set_snan_bit_is_one(flag val, float_status *status)
+static inline void set_snan_bit_is_one(bool val, float_status *status)
{
status->snan_bit_is_one = val;
}
-static inline int get_float_detect_tininess(float_status *status)
+static inline bool get_float_detect_tininess(float_status *status)
{
- return status->float_detect_tininess;
+ return status->tininess_before_rounding;
}
-static inline int get_float_rounding_mode(float_status *status)
+static inline FloatRoundMode get_float_rounding_mode(float_status *status)
{
return status->float_rounding_mode;
}
@@ -114,17 +115,17 @@
return status->floatx80_rounding_precision;
}
-static inline flag get_flush_to_zero(float_status *status)
+static inline bool get_flush_to_zero(float_status *status)
{
return status->flush_to_zero;
}
-static inline flag get_flush_inputs_to_zero(float_status *status)
+static inline bool get_flush_inputs_to_zero(float_status *status)
{
return status->flush_inputs_to_zero;
}
-static inline flag get_default_nan_mode(float_status *status)
+static inline bool get_default_nan_mode(float_status *status)
{
return status->default_nan_mode;
}
diff --git a/include/fpu/softfloat-macros.h b/include/fpu/softfloat-macros.h
index 605c4f4..a35ec28 100644
--- a/include/fpu/softfloat-macros.h
+++ b/include/fpu/softfloat-macros.h
@@ -756,11 +756,9 @@
| Otherwise, returns 0.
*----------------------------------------------------------------------------*/
-static inline flag eq128( uint64_t a0, uint64_t a1, uint64_t b0, uint64_t b1 )
+static inline bool eq128(uint64_t a0, uint64_t a1, uint64_t b0, uint64_t b1)
{
-
- return ( a0 == b0 ) && ( a1 == b1 );
-
+ return a0 == b0 && a1 == b1;
}
/*----------------------------------------------------------------------------
@@ -769,11 +767,9 @@
| Otherwise, returns 0.
*----------------------------------------------------------------------------*/
-static inline flag le128( uint64_t a0, uint64_t a1, uint64_t b0, uint64_t b1 )
+static inline bool le128(uint64_t a0, uint64_t a1, uint64_t b0, uint64_t b1)
{
-
- return ( a0 < b0 ) || ( ( a0 == b0 ) && ( a1 <= b1 ) );
-
+ return a0 < b0 || (a0 == b0 && a1 <= b1);
}
/*----------------------------------------------------------------------------
@@ -782,11 +778,9 @@
| returns 0.
*----------------------------------------------------------------------------*/
-static inline flag lt128( uint64_t a0, uint64_t a1, uint64_t b0, uint64_t b1 )
+static inline bool lt128(uint64_t a0, uint64_t a1, uint64_t b0, uint64_t b1)
{
-
- return ( a0 < b0 ) || ( ( a0 == b0 ) && ( a1 < b1 ) );
-
+ return a0 < b0 || (a0 == b0 && a1 < b1);
}
/*----------------------------------------------------------------------------
@@ -795,11 +789,9 @@
| Otherwise, returns 0.
*----------------------------------------------------------------------------*/
-static inline flag ne128( uint64_t a0, uint64_t a1, uint64_t b0, uint64_t b1 )
+static inline bool ne128(uint64_t a0, uint64_t a1, uint64_t b0, uint64_t b1)
{
-
- return ( a0 != b0 ) || ( a1 != b1 );
-
+ return a0 != b0 || a1 != b1;
}
#endif
diff --git a/include/fpu/softfloat-types.h b/include/fpu/softfloat-types.h
index 2aae6a8..7680193 100644
--- a/include/fpu/softfloat-types.h
+++ b/include/fpu/softfloat-types.h
@@ -80,12 +80,6 @@
#ifndef SOFTFLOAT_TYPES_H
#define SOFTFLOAT_TYPES_H
-/* This 'flag' type must be able to hold at least 0 and 1. It should
- * probably be replaced with 'bool' but the uses would need to be audited
- * to check that they weren't accidentally relying on it being a larger type.
- */
-typedef uint8_t flag;
-
/*
* Software IEC/IEEE floating-point types.
*/
@@ -122,16 +116,14 @@
* Software IEC/IEEE floating-point underflow tininess-detection mode.
*/
-enum {
- float_tininess_after_rounding = 0,
- float_tininess_before_rounding = 1
-};
+#define float_tininess_after_rounding false
+#define float_tininess_before_rounding true
/*
*Software IEC/IEEE floating-point rounding mode.
*/
-enum {
+typedef enum __attribute__((__packed__)) {
float_round_nearest_even = 0,
float_round_down = 1,
float_round_up = 2,
@@ -139,7 +131,7 @@
float_round_ties_away = 4,
/* Not an IEEE rounding mode: round to the closest odd mantissa value */
float_round_to_odd = 5,
-};
+} FloatRoundMode;
/*
* Software IEC/IEEE floating-point exception flags.
@@ -164,17 +156,17 @@
*/
typedef struct float_status {
- signed char float_detect_tininess;
- signed char float_rounding_mode;
+ FloatRoundMode float_rounding_mode;
uint8_t float_exception_flags;
signed char floatx80_rounding_precision;
+ bool tininess_before_rounding;
/* should denormalised results go to zero and set the inexact flag? */
- flag flush_to_zero;
+ bool flush_to_zero;
/* should denormalised inputs go to zero and set the input_denormal flag? */
- flag flush_inputs_to_zero;
- flag default_nan_mode;
+ bool flush_inputs_to_zero;
+ bool default_nan_mode;
/* not always used -- see snan_bit_is_one() in softfloat-specialize.h */
- flag snan_bit_is_one;
+ bool snan_bit_is_one;
} float_status;
#endif /* SOFTFLOAT_TYPES_H */
diff --git a/include/fpu/softfloat.h b/include/fpu/softfloat.h
index ecb8ba0..16ca697 100644
--- a/include/fpu/softfloat.h
+++ b/include/fpu/softfloat.h
@@ -85,12 +85,13 @@
/*----------------------------------------------------------------------------
| Software IEC/IEEE floating-point ordering relations
*----------------------------------------------------------------------------*/
-enum {
+
+typedef enum {
float_relation_less = -1,
float_relation_equal = 0,
float_relation_greater = 1,
float_relation_unordered = 2
-};
+} FloatRelation;
#include "fpu/softfloat-types.h"
#include "fpu/softfloat-helpers.h"
@@ -186,9 +187,9 @@
float16 float64_to_float16(float64 a, bool ieee, float_status *status);
float64 float16_to_float64(float16 a, bool ieee, float_status *status);
-int16_t float16_to_int16_scalbn(float16, int, int, float_status *status);
-int32_t float16_to_int32_scalbn(float16, int, int, float_status *status);
-int64_t float16_to_int64_scalbn(float16, int, int, float_status *status);
+int16_t float16_to_int16_scalbn(float16, FloatRoundMode, int, float_status *);
+int32_t float16_to_int32_scalbn(float16, FloatRoundMode, int, float_status *);
+int64_t float16_to_int64_scalbn(float16, FloatRoundMode, int, float_status *);
int16_t float16_to_int16(float16, float_status *status);
int32_t float16_to_int32(float16, float_status *status);
@@ -198,9 +199,12 @@
int32_t float16_to_int32_round_to_zero(float16, float_status *status);
int64_t float16_to_int64_round_to_zero(float16, float_status *status);
-uint16_t float16_to_uint16_scalbn(float16 a, int, int, float_status *status);
-uint32_t float16_to_uint32_scalbn(float16 a, int, int, float_status *status);
-uint64_t float16_to_uint64_scalbn(float16 a, int, int, float_status *status);
+uint16_t float16_to_uint16_scalbn(float16 a, FloatRoundMode,
+ int, float_status *status);
+uint32_t float16_to_uint32_scalbn(float16 a, FloatRoundMode,
+ int, float_status *status);
+uint64_t float16_to_uint64_scalbn(float16 a, FloatRoundMode,
+ int, float_status *status);
uint16_t float16_to_uint16(float16 a, float_status *status);
uint32_t float16_to_uint32(float16 a, float_status *status);
@@ -228,34 +232,34 @@
float16 float16_minnummag(float16, float16, float_status *status);
float16 float16_maxnummag(float16, float16, float_status *status);
float16 float16_sqrt(float16, float_status *status);
-int float16_compare(float16, float16, float_status *status);
-int float16_compare_quiet(float16, float16, float_status *status);
+FloatRelation float16_compare(float16, float16, float_status *status);
+FloatRelation float16_compare_quiet(float16, float16, float_status *status);
-int float16_is_quiet_nan(float16, float_status *status);
-int float16_is_signaling_nan(float16, float_status *status);
+bool float16_is_quiet_nan(float16, float_status *status);
+bool float16_is_signaling_nan(float16, float_status *status);
float16 float16_silence_nan(float16, float_status *status);
-static inline int float16_is_any_nan(float16 a)
+static inline bool float16_is_any_nan(float16 a)
{
return ((float16_val(a) & ~0x8000) > 0x7c00);
}
-static inline int float16_is_neg(float16 a)
+static inline bool float16_is_neg(float16 a)
{
return float16_val(a) >> 15;
}
-static inline int float16_is_infinity(float16 a)
+static inline bool float16_is_infinity(float16 a)
{
return (float16_val(a) & 0x7fff) == 0x7c00;
}
-static inline int float16_is_zero(float16 a)
+static inline bool float16_is_zero(float16 a)
{
return (float16_val(a) & 0x7fff) == 0;
}
-static inline int float16_is_zero_or_denormal(float16 a)
+static inline bool float16_is_zero_or_denormal(float16 a)
{
return (float16_val(a) & 0x7c00) == 0;
}
@@ -298,9 +302,9 @@
| Software IEC/IEEE single-precision conversion routines.
*----------------------------------------------------------------------------*/
-int16_t float32_to_int16_scalbn(float32, int, int, float_status *status);
-int32_t float32_to_int32_scalbn(float32, int, int, float_status *status);
-int64_t float32_to_int64_scalbn(float32, int, int, float_status *status);
+int16_t float32_to_int16_scalbn(float32, FloatRoundMode, int, float_status *);
+int32_t float32_to_int32_scalbn(float32, FloatRoundMode, int, float_status *);
+int64_t float32_to_int64_scalbn(float32, FloatRoundMode, int, float_status *);
int16_t float32_to_int16(float32, float_status *status);
int32_t float32_to_int32(float32, float_status *status);
@@ -310,9 +314,9 @@
int32_t float32_to_int32_round_to_zero(float32, float_status *status);
int64_t float32_to_int64_round_to_zero(float32, float_status *status);
-uint16_t float32_to_uint16_scalbn(float32, int, int, float_status *status);
-uint32_t float32_to_uint32_scalbn(float32, int, int, float_status *status);
-uint64_t float32_to_uint64_scalbn(float32, int, int, float_status *status);
+uint16_t float32_to_uint16_scalbn(float32, FloatRoundMode, int, float_status *);
+uint32_t float32_to_uint32_scalbn(float32, FloatRoundMode, int, float_status *);
+uint64_t float32_to_uint64_scalbn(float32, FloatRoundMode, int, float_status *);
uint16_t float32_to_uint16(float32, float_status *status);
uint32_t float32_to_uint32(float32, float_status *status);
@@ -339,24 +343,16 @@
float32 float32_sqrt(float32, float_status *status);
float32 float32_exp2(float32, float_status *status);
float32 float32_log2(float32, float_status *status);
-int float32_eq(float32, float32, float_status *status);
-int float32_le(float32, float32, float_status *status);
-int float32_lt(float32, float32, float_status *status);
-int float32_unordered(float32, float32, float_status *status);
-int float32_eq_quiet(float32, float32, float_status *status);
-int float32_le_quiet(float32, float32, float_status *status);
-int float32_lt_quiet(float32, float32, float_status *status);
-int float32_unordered_quiet(float32, float32, float_status *status);
-int float32_compare(float32, float32, float_status *status);
-int float32_compare_quiet(float32, float32, float_status *status);
+FloatRelation float32_compare(float32, float32, float_status *status);
+FloatRelation float32_compare_quiet(float32, float32, float_status *status);
float32 float32_min(float32, float32, float_status *status);
float32 float32_max(float32, float32, float_status *status);
float32 float32_minnum(float32, float32, float_status *status);
float32 float32_maxnum(float32, float32, float_status *status);
float32 float32_minnummag(float32, float32, float_status *status);
float32 float32_maxnummag(float32, float32, float_status *status);
-int float32_is_quiet_nan(float32, float_status *status);
-int float32_is_signaling_nan(float32, float_status *status);
+bool float32_is_quiet_nan(float32, float_status *status);
+bool float32_is_signaling_nan(float32, float_status *status);
float32 float32_silence_nan(float32, float_status *status);
float32 float32_scalbn(float32, int, float_status *status);
@@ -376,27 +372,27 @@
return make_float32(float32_val(a) ^ 0x80000000);
}
-static inline int float32_is_infinity(float32 a)
+static inline bool float32_is_infinity(float32 a)
{
return (float32_val(a) & 0x7fffffff) == 0x7f800000;
}
-static inline int float32_is_neg(float32 a)
+static inline bool float32_is_neg(float32 a)
{
return float32_val(a) >> 31;
}
-static inline int float32_is_zero(float32 a)
+static inline bool float32_is_zero(float32 a)
{
return (float32_val(a) & 0x7fffffff) == 0;
}
-static inline int float32_is_any_nan(float32 a)
+static inline bool float32_is_any_nan(float32 a)
{
return ((float32_val(a) & ~(1 << 31)) > 0x7f800000UL);
}
-static inline int float32_is_zero_or_denormal(float32 a)
+static inline bool float32_is_zero_or_denormal(float32 a)
{
return (float32_val(a) & 0x7f800000) == 0;
}
@@ -421,6 +417,47 @@
return make_float32((float32_val(a) & 0x7fffffff) | (sign << 31));
}
+static inline bool float32_eq(float32 a, float32 b, float_status *s)
+{
+ return float32_compare(a, b, s) == float_relation_equal;
+}
+
+static inline bool float32_le(float32 a, float32 b, float_status *s)
+{
+ return float32_compare(a, b, s) <= float_relation_equal;
+}
+
+static inline bool float32_lt(float32 a, float32 b, float_status *s)
+{
+ return float32_compare(a, b, s) < float_relation_equal;
+}
+
+static inline bool float32_unordered(float32 a, float32 b, float_status *s)
+{
+ return float32_compare(a, b, s) == float_relation_unordered;
+}
+
+static inline bool float32_eq_quiet(float32 a, float32 b, float_status *s)
+{
+ return float32_compare_quiet(a, b, s) == float_relation_equal;
+}
+
+static inline bool float32_le_quiet(float32 a, float32 b, float_status *s)
+{
+ return float32_compare_quiet(a, b, s) <= float_relation_equal;
+}
+
+static inline bool float32_lt_quiet(float32 a, float32 b, float_status *s)
+{
+ return float32_compare_quiet(a, b, s) < float_relation_equal;
+}
+
+static inline bool float32_unordered_quiet(float32 a, float32 b,
+ float_status *s)
+{
+ return float32_compare_quiet(a, b, s) == float_relation_unordered;
+}
+
#define float32_zero make_float32(0)
#define float32_half make_float32(0x3f000000)
#define float32_one make_float32(0x3f800000)
@@ -440,7 +477,7 @@
| significand.
*----------------------------------------------------------------------------*/
-static inline float32 packFloat32(flag zSign, int zExp, uint32_t zSig)
+static inline float32 packFloat32(bool zSign, int zExp, uint32_t zSig)
{
return make_float32(
(((uint32_t)zSign) << 31) + (((uint32_t)zExp) << 23) + zSig);
@@ -455,9 +492,9 @@
| Software IEC/IEEE double-precision conversion routines.
*----------------------------------------------------------------------------*/
-int16_t float64_to_int16_scalbn(float64, int, int, float_status *status);
-int32_t float64_to_int32_scalbn(float64, int, int, float_status *status);
-int64_t float64_to_int64_scalbn(float64, int, int, float_status *status);
+int16_t float64_to_int16_scalbn(float64, FloatRoundMode, int, float_status *);
+int32_t float64_to_int32_scalbn(float64, FloatRoundMode, int, float_status *);
+int64_t float64_to_int64_scalbn(float64, FloatRoundMode, int, float_status *);
int16_t float64_to_int16(float64, float_status *status);
int32_t float64_to_int32(float64, float_status *status);
@@ -467,9 +504,9 @@
int32_t float64_to_int32_round_to_zero(float64, float_status *status);
int64_t float64_to_int64_round_to_zero(float64, float_status *status);
-uint16_t float64_to_uint16_scalbn(float64, int, int, float_status *status);
-uint32_t float64_to_uint32_scalbn(float64, int, int, float_status *status);
-uint64_t float64_to_uint64_scalbn(float64, int, int, float_status *status);
+uint16_t float64_to_uint16_scalbn(float64, FloatRoundMode, int, float_status *);
+uint32_t float64_to_uint32_scalbn(float64, FloatRoundMode, int, float_status *);
+uint64_t float64_to_uint64_scalbn(float64, FloatRoundMode, int, float_status *);
uint16_t float64_to_uint16(float64, float_status *status);
uint32_t float64_to_uint32(float64, float_status *status);
@@ -495,24 +532,16 @@
float64 float64_muladd(float64, float64, float64, int, float_status *status);
float64 float64_sqrt(float64, float_status *status);
float64 float64_log2(float64, float_status *status);
-int float64_eq(float64, float64, float_status *status);
-int float64_le(float64, float64, float_status *status);
-int float64_lt(float64, float64, float_status *status);
-int float64_unordered(float64, float64, float_status *status);
-int float64_eq_quiet(float64, float64, float_status *status);
-int float64_le_quiet(float64, float64, float_status *status);
-int float64_lt_quiet(float64, float64, float_status *status);
-int float64_unordered_quiet(float64, float64, float_status *status);
-int float64_compare(float64, float64, float_status *status);
-int float64_compare_quiet(float64, float64, float_status *status);
+FloatRelation float64_compare(float64, float64, float_status *status);
+FloatRelation float64_compare_quiet(float64, float64, float_status *status);
float64 float64_min(float64, float64, float_status *status);
float64 float64_max(float64, float64, float_status *status);
float64 float64_minnum(float64, float64, float_status *status);
float64 float64_maxnum(float64, float64, float_status *status);
float64 float64_minnummag(float64, float64, float_status *status);
float64 float64_maxnummag(float64, float64, float_status *status);
-int float64_is_quiet_nan(float64 a, float_status *status);
-int float64_is_signaling_nan(float64, float_status *status);
+bool float64_is_quiet_nan(float64 a, float_status *status);
+bool float64_is_signaling_nan(float64, float_status *status);
float64 float64_silence_nan(float64, float_status *status);
float64 float64_scalbn(float64, int, float_status *status);
@@ -532,27 +561,27 @@
return make_float64(float64_val(a) ^ 0x8000000000000000LL);
}
-static inline int float64_is_infinity(float64 a)
+static inline bool float64_is_infinity(float64 a)
{
return (float64_val(a) & 0x7fffffffffffffffLL ) == 0x7ff0000000000000LL;
}
-static inline int float64_is_neg(float64 a)
+static inline bool float64_is_neg(float64 a)
{
return float64_val(a) >> 63;
}
-static inline int float64_is_zero(float64 a)
+static inline bool float64_is_zero(float64 a)
{
return (float64_val(a) & 0x7fffffffffffffffLL) == 0;
}
-static inline int float64_is_any_nan(float64 a)
+static inline bool float64_is_any_nan(float64 a)
{
return ((float64_val(a) & ~(1ULL << 63)) > 0x7ff0000000000000ULL);
}
-static inline int float64_is_zero_or_denormal(float64 a)
+static inline bool float64_is_zero_or_denormal(float64 a)
{
return (float64_val(a) & 0x7ff0000000000000LL) == 0;
}
@@ -578,6 +607,47 @@
| ((int64_t)sign << 63));
}
+static inline bool float64_eq(float64 a, float64 b, float_status *s)
+{
+ return float64_compare(a, b, s) == float_relation_equal;
+}
+
+static inline bool float64_le(float64 a, float64 b, float_status *s)
+{
+ return float64_compare(a, b, s) <= float_relation_equal;
+}
+
+static inline bool float64_lt(float64 a, float64 b, float_status *s)
+{
+ return float64_compare(a, b, s) < float_relation_equal;
+}
+
+static inline bool float64_unordered(float64 a, float64 b, float_status *s)
+{
+ return float64_compare(a, b, s) == float_relation_unordered;
+}
+
+static inline bool float64_eq_quiet(float64 a, float64 b, float_status *s)
+{
+ return float64_compare_quiet(a, b, s) == float_relation_equal;
+}
+
+static inline bool float64_le_quiet(float64 a, float64 b, float_status *s)
+{
+ return float64_compare_quiet(a, b, s) <= float_relation_equal;
+}
+
+static inline bool float64_lt_quiet(float64 a, float64 b, float_status *s)
+{
+ return float64_compare_quiet(a, b, s) < float_relation_equal;
+}
+
+static inline bool float64_unordered_quiet(float64 a, float64 b,
+ float_status *s)
+{
+ return float64_compare_quiet(a, b, s) == float_relation_unordered;
+}
+
#define float64_zero make_float64(0)
#define float64_half make_float64(0x3fe0000000000000LL)
#define float64_one make_float64(0x3ff0000000000000LL)
@@ -619,16 +689,8 @@
floatx80 floatx80_div(floatx80, floatx80, float_status *status);
floatx80 floatx80_rem(floatx80, floatx80, float_status *status);
floatx80 floatx80_sqrt(floatx80, float_status *status);
-int floatx80_eq(floatx80, floatx80, float_status *status);
-int floatx80_le(floatx80, floatx80, float_status *status);
-int floatx80_lt(floatx80, floatx80, float_status *status);
-int floatx80_unordered(floatx80, floatx80, float_status *status);
-int floatx80_eq_quiet(floatx80, floatx80, float_status *status);
-int floatx80_le_quiet(floatx80, floatx80, float_status *status);
-int floatx80_lt_quiet(floatx80, floatx80, float_status *status);
-int floatx80_unordered_quiet(floatx80, floatx80, float_status *status);
-int floatx80_compare(floatx80, floatx80, float_status *status);
-int floatx80_compare_quiet(floatx80, floatx80, float_status *status);
+FloatRelation floatx80_compare(floatx80, floatx80, float_status *status);
+FloatRelation floatx80_compare_quiet(floatx80, floatx80, float_status *status);
int floatx80_is_quiet_nan(floatx80, float_status *status);
int floatx80_is_signaling_nan(floatx80, float_status *status);
floatx80 floatx80_silence_nan(floatx80, float_status *status);
@@ -646,7 +708,7 @@
return a;
}
-static inline int floatx80_is_infinity(floatx80 a)
+static inline bool floatx80_is_infinity(floatx80 a)
{
#if defined(TARGET_M68K)
return (a.high & 0x7fff) == floatx80_infinity.high && !(a.low << 1);
@@ -656,26 +718,67 @@
#endif
}
-static inline int floatx80_is_neg(floatx80 a)
+static inline bool floatx80_is_neg(floatx80 a)
{
return a.high >> 15;
}
-static inline int floatx80_is_zero(floatx80 a)
+static inline bool floatx80_is_zero(floatx80 a)
{
return (a.high & 0x7fff) == 0 && a.low == 0;
}
-static inline int floatx80_is_zero_or_denormal(floatx80 a)
+static inline bool floatx80_is_zero_or_denormal(floatx80 a)
{
return (a.high & 0x7fff) == 0;
}
-static inline int floatx80_is_any_nan(floatx80 a)
+static inline bool floatx80_is_any_nan(floatx80 a)
{
return ((a.high & 0x7fff) == 0x7fff) && (a.low<<1);
}
+static inline bool floatx80_eq(floatx80 a, floatx80 b, float_status *s)
+{
+ return floatx80_compare(a, b, s) == float_relation_equal;
+}
+
+static inline bool floatx80_le(floatx80 a, floatx80 b, float_status *s)
+{
+ return floatx80_compare(a, b, s) <= float_relation_equal;
+}
+
+static inline bool floatx80_lt(floatx80 a, floatx80 b, float_status *s)
+{
+ return floatx80_compare(a, b, s) < float_relation_equal;
+}
+
+static inline bool floatx80_unordered(floatx80 a, floatx80 b, float_status *s)
+{
+ return floatx80_compare(a, b, s) == float_relation_unordered;
+}
+
+static inline bool floatx80_eq_quiet(floatx80 a, floatx80 b, float_status *s)
+{
+ return floatx80_compare_quiet(a, b, s) == float_relation_equal;
+}
+
+static inline bool floatx80_le_quiet(floatx80 a, floatx80 b, float_status *s)
+{
+ return floatx80_compare_quiet(a, b, s) <= float_relation_equal;
+}
+
+static inline bool floatx80_lt_quiet(floatx80 a, floatx80 b, float_status *s)
+{
+ return floatx80_compare_quiet(a, b, s) < float_relation_equal;
+}
+
+static inline bool floatx80_unordered_quiet(floatx80 a, floatx80 b,
+ float_status *s)
+{
+ return floatx80_compare_quiet(a, b, s) == float_relation_unordered;
+}
+
/*----------------------------------------------------------------------------
| Return whether the given value is an invalid floatx80 encoding.
| Invalid floatx80 encodings arise when the integer bit is not set, but
@@ -722,7 +825,7 @@
| `a'.
*----------------------------------------------------------------------------*/
-static inline flag extractFloatx80Sign(floatx80 a)
+static inline bool extractFloatx80Sign(floatx80 a)
{
return a.high >> 15;
}
@@ -732,7 +835,7 @@
| extended double-precision floating-point value, returning the result.
*----------------------------------------------------------------------------*/
-static inline floatx80 packFloatx80(flag zSign, int32_t zExp, uint64_t zSig)
+static inline floatx80 packFloatx80(bool zSign, int32_t zExp, uint64_t zSig)
{
floatx80 z;
@@ -783,7 +886,7 @@
| Floating-Point Arithmetic.
*----------------------------------------------------------------------------*/
-floatx80 roundAndPackFloatx80(int8_t roundingPrecision, flag zSign,
+floatx80 roundAndPackFloatx80(int8_t roundingPrecision, bool zSign,
int32_t zExp, uint64_t zSig0, uint64_t zSig1,
float_status *status);
@@ -797,7 +900,7 @@
*----------------------------------------------------------------------------*/
floatx80 normalizeRoundAndPackFloatx80(int8_t roundingPrecision,
- flag zSign, int32_t zExp,
+ bool zSign, int32_t zExp,
uint64_t zSig0, uint64_t zSig1,
float_status *status);
@@ -831,18 +934,10 @@
float128 float128_div(float128, float128, float_status *status);
float128 float128_rem(float128, float128, float_status *status);
float128 float128_sqrt(float128, float_status *status);
-int float128_eq(float128, float128, float_status *status);
-int float128_le(float128, float128, float_status *status);
-int float128_lt(float128, float128, float_status *status);
-int float128_unordered(float128, float128, float_status *status);
-int float128_eq_quiet(float128, float128, float_status *status);
-int float128_le_quiet(float128, float128, float_status *status);
-int float128_lt_quiet(float128, float128, float_status *status);
-int float128_unordered_quiet(float128, float128, float_status *status);
-int float128_compare(float128, float128, float_status *status);
-int float128_compare_quiet(float128, float128, float_status *status);
-int float128_is_quiet_nan(float128, float_status *status);
-int float128_is_signaling_nan(float128, float_status *status);
+FloatRelation float128_compare(float128, float128, float_status *status);
+FloatRelation float128_compare_quiet(float128, float128, float_status *status);
+bool float128_is_quiet_nan(float128, float_status *status);
+bool float128_is_signaling_nan(float128, float_status *status);
float128 float128_silence_nan(float128, float_status *status);
float128 float128_scalbn(float128, int, float_status *status);
@@ -858,22 +953,22 @@
return a;
}
-static inline int float128_is_infinity(float128 a)
+static inline bool float128_is_infinity(float128 a)
{
return (a.high & 0x7fffffffffffffffLL) == 0x7fff000000000000LL && a.low == 0;
}
-static inline int float128_is_neg(float128 a)
+static inline bool float128_is_neg(float128 a)
{
return a.high >> 63;
}
-static inline int float128_is_zero(float128 a)
+static inline bool float128_is_zero(float128 a)
{
return (a.high & 0x7fffffffffffffffLL) == 0 && a.low == 0;
}
-static inline int float128_is_zero_or_denormal(float128 a)
+static inline bool float128_is_zero_or_denormal(float128 a)
{
return (a.high & 0x7fff000000000000LL) == 0;
}
@@ -888,12 +983,53 @@
return float128_is_zero_or_denormal(a) && !float128_is_zero(a);
}
-static inline int float128_is_any_nan(float128 a)
+static inline bool float128_is_any_nan(float128 a)
{
return ((a.high >> 48) & 0x7fff) == 0x7fff &&
((a.low != 0) || ((a.high & 0xffffffffffffLL) != 0));
}
+static inline bool float128_eq(float128 a, float128 b, float_status *s)
+{
+ return float128_compare(a, b, s) == float_relation_equal;
+}
+
+static inline bool float128_le(float128 a, float128 b, float_status *s)
+{
+ return float128_compare(a, b, s) <= float_relation_equal;
+}
+
+static inline bool float128_lt(float128 a, float128 b, float_status *s)
+{
+ return float128_compare(a, b, s) < float_relation_equal;
+}
+
+static inline bool float128_unordered(float128 a, float128 b, float_status *s)
+{
+ return float128_compare(a, b, s) == float_relation_unordered;
+}
+
+static inline bool float128_eq_quiet(float128 a, float128 b, float_status *s)
+{
+ return float128_compare_quiet(a, b, s) == float_relation_equal;
+}
+
+static inline bool float128_le_quiet(float128 a, float128 b, float_status *s)
+{
+ return float128_compare_quiet(a, b, s) <= float_relation_equal;
+}
+
+static inline bool float128_lt_quiet(float128 a, float128 b, float_status *s)
+{
+ return float128_compare_quiet(a, b, s) < float_relation_equal;
+}
+
+static inline bool float128_unordered_quiet(float128 a, float128 b,
+ float_status *s)
+{
+ return float128_compare_quiet(a, b, s) == float_relation_unordered;
+}
+
#define float128_zero make_float128(0, 0)
/*----------------------------------------------------------------------------
diff --git a/include/hw/acpi/aml-build.h b/include/hw/acpi/aml-build.h
index 1539fe0..ed7c893 100644
--- a/include/hw/acpi/aml-build.h
+++ b/include/hw/acpi/aml-build.h
@@ -220,6 +220,7 @@
GArray *rsdp;
GArray *tcpalog;
GArray *vmgenid;
+ GArray *hardware_errors;
BIOSLinker *linker;
} AcpiBuildTables;
diff --git a/include/hw/acpi/generic_event_device.h b/include/hw/acpi/generic_event_device.h
index 9eb86ca..83917de 100644
--- a/include/hw/acpi/generic_event_device.h
+++ b/include/hw/acpi/generic_event_device.h
@@ -61,6 +61,7 @@
#include "hw/sysbus.h"
#include "hw/acpi/memory_hotplug.h"
+#include "hw/acpi/ghes.h"
#define ACPI_POWER_BUTTON_DEVICE "PWRB"
@@ -96,6 +97,7 @@
GEDState ged_state;
uint32_t ged_event_bitmap;
qemu_irq irq;
+ AcpiGhesState ghes_state;
} AcpiGedState;
void build_ged_aml(Aml *table, const char* name, HotplugHandler *hotplug_dev,
diff --git a/include/hw/acpi/ghes.h b/include/hw/acpi/ghes.h
new file mode 100644
index 0000000..4ad025e
--- /dev/null
+++ b/include/hw/acpi/ghes.h
@@ -0,0 +1,74 @@
+/*
+ * Support for generating APEI tables and recording CPER for Guests
+ *
+ * Copyright (c) 2020 HUAWEI TECHNOLOGIES CO., LTD.
+ *
+ * Author: Dongjiu Geng <gengdongjiu@huawei.com>
+ *
+ * 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/>.
+ */
+
+#ifndef ACPI_GHES_H
+#define ACPI_GHES_H
+
+#include "hw/acpi/bios-linker-loader.h"
+
+/*
+ * Values for Hardware Error Notification Type field
+ */
+enum AcpiGhesNotifyType {
+ /* Polled */
+ ACPI_GHES_NOTIFY_POLLED = 0,
+ /* External Interrupt */
+ ACPI_GHES_NOTIFY_EXTERNAL = 1,
+ /* Local Interrupt */
+ ACPI_GHES_NOTIFY_LOCAL = 2,
+ /* SCI */
+ ACPI_GHES_NOTIFY_SCI = 3,
+ /* NMI */
+ ACPI_GHES_NOTIFY_NMI = 4,
+ /* CMCI, ACPI 5.0: 18.3.2.7, Table 18-290 */
+ ACPI_GHES_NOTIFY_CMCI = 5,
+ /* MCE, ACPI 5.0: 18.3.2.7, Table 18-290 */
+ ACPI_GHES_NOTIFY_MCE = 6,
+ /* GPIO-Signal, ACPI 6.0: 18.3.2.7, Table 18-332 */
+ ACPI_GHES_NOTIFY_GPIO = 7,
+ /* ARMv8 SEA, ACPI 6.1: 18.3.2.9, Table 18-345 */
+ ACPI_GHES_NOTIFY_SEA = 8,
+ /* ARMv8 SEI, ACPI 6.1: 18.3.2.9, Table 18-345 */
+ ACPI_GHES_NOTIFY_SEI = 9,
+ /* External Interrupt - GSIV, ACPI 6.1: 18.3.2.9, Table 18-345 */
+ ACPI_GHES_NOTIFY_GSIV = 10,
+ /* Software Delegated Exception, ACPI 6.2: 18.3.2.9, Table 18-383 */
+ ACPI_GHES_NOTIFY_SDEI = 11,
+ /* 12 and greater are reserved */
+ ACPI_GHES_NOTIFY_RESERVED = 12
+};
+
+enum {
+ ACPI_HEST_SRC_ID_SEA = 0,
+ /* future ids go here */
+ ACPI_HEST_SRC_ID_RESERVED,
+};
+
+typedef struct AcpiGhesState {
+ uint64_t ghes_addr_le;
+} AcpiGhesState;
+
+void build_ghes_error_table(GArray *hardware_errors, BIOSLinker *linker);
+void acpi_build_hest(GArray *table_data, BIOSLinker *linker);
+void acpi_ghes_add_fw_cfg(AcpiGhesState *vms, FWCfgState *s,
+ GArray *hardware_errors);
+int acpi_ghes_record_errors(uint8_t notify, uint64_t error_physical_addr);
+#endif
diff --git a/include/hw/acpi/ich9.h b/include/hw/acpi/ich9.h
index 41568d1..28a5318 100644
--- a/include/hw/acpi/ich9.h
+++ b/include/hw/acpi/ich9.h
@@ -72,7 +72,7 @@
void ich9_pm_iospace_update(ICH9LPCPMRegs *pm, uint32_t pm_io_base);
extern const VMStateDescription vmstate_ich9_pm;
-void ich9_pm_add_properties(Object *obj, ICH9LPCPMRegs *pm, Error **errp);
+void ich9_pm_add_properties(Object *obj, ICH9LPCPMRegs *pm);
void ich9_pm_device_pre_plug_cb(HotplugHandler *hotplug_dev, DeviceState *dev,
Error **errp);
diff --git a/include/hw/arm/fsl-imx25.h b/include/hw/arm/fsl-imx25.h
index 5e196bb..9e228da 100644
--- a/include/hw/arm/fsl-imx25.h
+++ b/include/hw/arm/fsl-imx25.h
@@ -29,6 +29,7 @@
#include "hw/gpio/imx_gpio.h"
#include "hw/sd/sdhci.h"
#include "hw/usb/chipidea.h"
+#include "hw/watchdog/wdt_imx2.h"
#include "exec/memory.h"
#include "target/arm/cpu.h"
@@ -60,6 +61,7 @@
IMXGPIOState gpio[FSL_IMX25_NUM_GPIOS];
SDHCIState esdhc[FSL_IMX25_NUM_ESDHCS];
ChipideaState usb[FSL_IMX25_NUM_USBS];
+ IMX2WdtState wdt;
MemoryRegion rom[2];
MemoryRegion iram;
MemoryRegion iram_alias;
@@ -229,6 +231,8 @@
#define FSL_IMX25_GPIO1_SIZE 0x4000
#define FSL_IMX25_GPIO2_ADDR 0x53FD0000
#define FSL_IMX25_GPIO2_SIZE 0x4000
+#define FSL_IMX25_WDT_ADDR 0x53FDC000
+#define FSL_IMX25_WDT_SIZE 0x4000
#define FSL_IMX25_USB1_ADDR 0x53FF4000
#define FSL_IMX25_USB1_SIZE 0x0200
#define FSL_IMX25_USB2_ADDR 0x53FF4400
@@ -268,5 +272,6 @@
#define FSL_IMX25_ESDHC2_IRQ 8
#define FSL_IMX25_USB1_IRQ 37
#define FSL_IMX25_USB2_IRQ 35
+#define FSL_IMX25_WDT_IRQ 55
#endif /* FSL_IMX25_H */
diff --git a/include/hw/arm/fsl-imx31.h b/include/hw/arm/fsl-imx31.h
index ac5ca98..dd8561b 100644
--- a/include/hw/arm/fsl-imx31.h
+++ b/include/hw/arm/fsl-imx31.h
@@ -25,6 +25,7 @@
#include "hw/timer/imx_epit.h"
#include "hw/i2c/imx_i2c.h"
#include "hw/gpio/imx_gpio.h"
+#include "hw/watchdog/wdt_imx2.h"
#include "exec/memory.h"
#include "target/arm/cpu.h"
@@ -49,6 +50,7 @@
IMXEPITState epit[FSL_IMX31_NUM_EPITS];
IMXI2CState i2c[FSL_IMX31_NUM_I2CS];
IMXGPIOState gpio[FSL_IMX31_NUM_GPIOS];
+ IMX2WdtState wdt;
MemoryRegion secure_rom;
MemoryRegion rom;
MemoryRegion iram;
@@ -87,6 +89,8 @@
#define FSL_IMX31_GPIO1_SIZE 0x4000
#define FSL_IMX31_GPIO2_ADDR 0x53FD0000
#define FSL_IMX31_GPIO2_SIZE 0x4000
+#define FSL_IMX31_WDT_ADDR 0x53FDC000
+#define FSL_IMX31_WDT_SIZE 0x4000
#define FSL_IMX31_AVIC_ADDR 0x68000000
#define FSL_IMX31_AVIC_SIZE 0x100
#define FSL_IMX31_SDRAM0_ADDR 0x80000000
diff --git a/include/hw/arm/fsl-imx6.h b/include/hw/arm/fsl-imx6.h
index 973bcb7..1ebd751 100644
--- a/include/hw/arm/fsl-imx6.h
+++ b/include/hw/arm/fsl-imx6.h
@@ -21,7 +21,7 @@
#include "hw/cpu/a9mpcore.h"
#include "hw/misc/imx6_ccm.h"
#include "hw/misc/imx6_src.h"
-#include "hw/misc/imx2_wdt.h"
+#include "hw/watchdog/wdt_imx2.h"
#include "hw/char/imx_serial.h"
#include "hw/timer/imx_gpt.h"
#include "hw/timer/imx_epit.h"
diff --git a/include/hw/arm/fsl-imx6ul.h b/include/hw/arm/fsl-imx6ul.h
index 1a0bab8..37c89cc 100644
--- a/include/hw/arm/fsl-imx6ul.h
+++ b/include/hw/arm/fsl-imx6ul.h
@@ -24,7 +24,7 @@
#include "hw/misc/imx7_snvs.h"
#include "hw/misc/imx7_gpr.h"
#include "hw/intc/imx_gpcv2.h"
-#include "hw/misc/imx2_wdt.h"
+#include "hw/watchdog/wdt_imx2.h"
#include "hw/gpio/imx_gpio.h"
#include "hw/char/imx_serial.h"
#include "hw/timer/imx_gpt.h"
diff --git a/include/hw/arm/fsl-imx7.h b/include/hw/arm/fsl-imx7.h
index 706aef2..da977f9 100644
--- a/include/hw/arm/fsl-imx7.h
+++ b/include/hw/arm/fsl-imx7.h
@@ -26,7 +26,7 @@
#include "hw/misc/imx7_snvs.h"
#include "hw/misc/imx7_gpr.h"
#include "hw/misc/imx6_src.h"
-#include "hw/misc/imx2_wdt.h"
+#include "hw/watchdog/wdt_imx2.h"
#include "hw/gpio/imx_gpio.h"
#include "hw/char/imx_serial.h"
#include "hw/timer/imx_gpt.h"
@@ -113,6 +113,9 @@
FSL_IMX7_IOMUXC_GPR_ADDR = 0x30340000,
FSL_IMX7_IOMUXCn_SIZE = 0x1000,
+ FSL_IMX7_OCOTP_ADDR = 0x30350000,
+ FSL_IMX7_OCOTP_SIZE = 0x10000,
+
FSL_IMX7_ANALOG_ADDR = 0x30360000,
FSL_IMX7_SNVS_ADDR = 0x30370000,
FSL_IMX7_CCM_ADDR = 0x30380000,
@@ -124,11 +127,24 @@
FSL_IMX7_ADC2_ADDR = 0x30620000,
FSL_IMX7_ADCn_SIZE = 0x1000,
+ FSL_IMX7_PWM1_ADDR = 0x30660000,
+ FSL_IMX7_PWM2_ADDR = 0x30670000,
+ FSL_IMX7_PWM3_ADDR = 0x30680000,
+ FSL_IMX7_PWM4_ADDR = 0x30690000,
+ FSL_IMX7_PWMn_SIZE = 0x10000,
+
FSL_IMX7_PCIE_PHY_ADDR = 0x306D0000,
FSL_IMX7_PCIE_PHY_SIZE = 0x10000,
FSL_IMX7_GPC_ADDR = 0x303A0000,
+ FSL_IMX7_CAAM_ADDR = 0x30900000,
+ FSL_IMX7_CAAM_SIZE = 0x40000,
+
+ FSL_IMX7_CAN1_ADDR = 0x30A00000,
+ FSL_IMX7_CAN2_ADDR = 0x30A10000,
+ FSL_IMX7_CANn_SIZE = 0x10000,
+
FSL_IMX7_I2C1_ADDR = 0x30A20000,
FSL_IMX7_I2C2_ADDR = 0x30A30000,
FSL_IMX7_I2C3_ADDR = 0x30A40000,
@@ -212,6 +228,11 @@
FSL_IMX7_USB2_IRQ = 42,
FSL_IMX7_USB3_IRQ = 40,
+ FSL_IMX7_WDOG1_IRQ = 78,
+ FSL_IMX7_WDOG2_IRQ = 79,
+ FSL_IMX7_WDOG3_IRQ = 10,
+ FSL_IMX7_WDOG4_IRQ = 109,
+
FSL_IMX7_PCI_INTA_IRQ = 125,
FSL_IMX7_PCI_INTB_IRQ = 124,
FSL_IMX7_PCI_INTC_IRQ = 123,
diff --git a/include/hw/arm/virt.h b/include/hw/arm/virt.h
index 6d67ace..31878dd 100644
--- a/include/hw/arm/virt.h
+++ b/include/hw/arm/virt.h
@@ -132,6 +132,7 @@
bool highmem_ecam;
bool its;
bool virt;
+ bool ras;
OnOffAuto acpi;
VirtGICType gic_version;
VirtIOMMUType iommu;
diff --git a/include/hw/display/edid.h b/include/hw/display/edid.h
index ff99dc0..23371ee 100644
--- a/include/hw/display/edid.h
+++ b/include/hw/display/edid.h
@@ -2,6 +2,7 @@
#define EDID_H
#include "qom/object.h"
+#include "hw/qdev-properties.h"
typedef struct qemu_edid_info {
const char *vendor; /* http://www.uefi.org/pnp_id_list */
diff --git a/include/hw/display/ramfb.h b/include/hw/display/ramfb.h
index f6c2de9..b33a2c4 100644
--- a/include/hw/display/ramfb.h
+++ b/include/hw/display/ramfb.h
@@ -4,7 +4,7 @@
/* ramfb.c */
typedef struct RAMFBState RAMFBState;
void ramfb_display_update(QemuConsole *con, RAMFBState *s);
-RAMFBState *ramfb_setup(DeviceState *dev, Error **errp);
+RAMFBState *ramfb_setup(Error **errp);
/* ramfb-standalone.c */
#define TYPE_RAMFB_DEVICE "ramfb"
diff --git a/include/hw/misc/imx2_wdt.h b/include/hw/misc/imx2_wdt.h
deleted file mode 100644
index b91b002..0000000
--- a/include/hw/misc/imx2_wdt.h
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * Copyright (c) 2017, Impinj, Inc.
- *
- * i.MX2 Watchdog IP block
- *
- * Author: Andrey Smirnov <andrew.smirnov@gmail.com>
- *
- * This work is licensed under the terms of the GNU GPL, version 2 or later.
- * See the COPYING file in the top-level directory.
- */
-
-#ifndef IMX2_WDT_H
-#define IMX2_WDT_H
-
-#include "hw/sysbus.h"
-
-#define TYPE_IMX2_WDT "imx2.wdt"
-#define IMX2_WDT(obj) OBJECT_CHECK(IMX2WdtState, (obj), TYPE_IMX2_WDT)
-
-enum IMX2WdtRegisters {
- IMX2_WDT_WCR = 0x0000,
- IMX2_WDT_REG_NUM = 0x0008 / sizeof(uint16_t) + 1,
-};
-
-
-typedef struct IMX2WdtState {
- /* <private> */
- SysBusDevice parent_obj;
-
- MemoryRegion mmio;
-} IMX2WdtState;
-
-#endif /* IMX2_WDT_H */
diff --git a/include/hw/ppc/spapr.h b/include/hw/ppc/spapr.h
index e579eaf..c421410 100644
--- a/include/hw/ppc/spapr.h
+++ b/include/hw/ppc/spapr.h
@@ -886,6 +886,7 @@
#define SPAPR_LMB_FLAGS_ASSIGNED 0x00000008
#define SPAPR_LMB_FLAGS_DRC_INVALID 0x00000020
#define SPAPR_LMB_FLAGS_RESERVED 0x00000080
+#define SPAPR_LMB_FLAGS_HOTREMOVABLE 0x00000100
void spapr_do_system_reset_on_cpu(CPUState *cs, run_on_cpu_data arg);
@@ -921,7 +922,7 @@
void spapr_caps_init(SpaprMachineState *spapr);
void spapr_caps_apply(SpaprMachineState *spapr);
void spapr_caps_cpu_apply(SpaprMachineState *spapr, PowerPCCPU *cpu);
-void spapr_caps_add_properties(SpaprMachineClass *smc, Error **errp);
+void spapr_caps_add_properties(SpaprMachineClass *smc);
int spapr_caps_post_migration(SpaprMachineState *spapr);
void spapr_check_pagesize(SpaprMachineState *spapr, hwaddr pagesize,
diff --git a/include/hw/qdev-core.h b/include/hw/qdev-core.h
index d87d989..b870b27 100644
--- a/include/hw/qdev-core.h
+++ b/include/hw/qdev-core.h
@@ -30,10 +30,10 @@
} DeviceCategory;
typedef void (*DeviceRealize)(DeviceState *dev, Error **errp);
-typedef void (*DeviceUnrealize)(DeviceState *dev, Error **errp);
+typedef void (*DeviceUnrealize)(DeviceState *dev);
typedef void (*DeviceReset)(DeviceState *dev);
typedef void (*BusRealize)(BusState *bus, Error **errp);
-typedef void (*BusUnrealize)(BusState *bus, Error **errp);
+typedef void (*BusUnrealize)(BusState *bus);
/**
* DeviceClass:
@@ -286,7 +286,7 @@
const QEnumLookup *enum_table;
int (*print)(DeviceState *dev, Property *prop, char *dest, size_t len);
void (*set_default_value)(ObjectProperty *op, const Property *prop);
- void (*create)(ObjectClass *oc, Property *prop, Error **errp);
+ void (*create)(ObjectClass *oc, Property *prop);
ObjectPropertyAccessor *get;
ObjectPropertyAccessor *set;
ObjectPropertyRelease *release;
diff --git a/include/hw/registerfields.h b/include/hw/registerfields.h
index 0407edb..93fa4a8 100644
--- a/include/hw/registerfields.h
+++ b/include/hw/registerfields.h
@@ -66,35 +66,35 @@
#define FIELD_DP8(storage, reg, field, val) ({ \
struct { \
unsigned int v:R_ ## reg ## _ ## field ## _LENGTH; \
- } v = { .v = val }; \
- uint8_t d; \
- d = deposit32((storage), R_ ## reg ## _ ## field ## _SHIFT, \
- R_ ## reg ## _ ## field ## _LENGTH, v.v); \
- d; })
+ } _v = { .v = val }; \
+ uint8_t _d; \
+ _d = deposit32((storage), R_ ## reg ## _ ## field ## _SHIFT, \
+ R_ ## reg ## _ ## field ## _LENGTH, _v.v); \
+ _d; })
#define FIELD_DP16(storage, reg, field, val) ({ \
struct { \
unsigned int v:R_ ## reg ## _ ## field ## _LENGTH; \
- } v = { .v = val }; \
- uint16_t d; \
- d = deposit32((storage), R_ ## reg ## _ ## field ## _SHIFT, \
- R_ ## reg ## _ ## field ## _LENGTH, v.v); \
- d; })
+ } _v = { .v = val }; \
+ uint16_t _d; \
+ _d = deposit32((storage), R_ ## reg ## _ ## field ## _SHIFT, \
+ R_ ## reg ## _ ## field ## _LENGTH, _v.v); \
+ _d; })
#define FIELD_DP32(storage, reg, field, val) ({ \
struct { \
unsigned int v:R_ ## reg ## _ ## field ## _LENGTH; \
- } v = { .v = val }; \
- uint32_t d; \
- d = deposit32((storage), R_ ## reg ## _ ## field ## _SHIFT, \
- R_ ## reg ## _ ## field ## _LENGTH, v.v); \
- d; })
+ } _v = { .v = val }; \
+ uint32_t _d; \
+ _d = deposit32((storage), R_ ## reg ## _ ## field ## _SHIFT, \
+ R_ ## reg ## _ ## field ## _LENGTH, _v.v); \
+ _d; })
#define FIELD_DP64(storage, reg, field, val) ({ \
struct { \
unsigned int v:R_ ## reg ## _ ## field ## _LENGTH; \
- } v = { .v = val }; \
- uint64_t d; \
- d = deposit64((storage), R_ ## reg ## _ ## field ## _SHIFT, \
- R_ ## reg ## _ ## field ## _LENGTH, v.v); \
- d; })
+ } _v = { .v = val }; \
+ uint64_t _d; \
+ _d = deposit64((storage), R_ ## reg ## _ ## field ## _SHIFT, \
+ R_ ## reg ## _ ## field ## _LENGTH, _v.v); \
+ _d; })
/* Deposit a field to array of registers. */
#define ARRAY_FIELD_DP32(regs, reg, field, val) \
diff --git a/include/hw/s390x/s390-ccw.h b/include/hw/s390x/s390-ccw.h
index fffb545..7f27bc2 100644
--- a/include/hw/s390x/s390-ccw.h
+++ b/include/hw/s390x/s390-ccw.h
@@ -33,7 +33,7 @@
typedef struct S390CCWDeviceClass {
CCWDeviceClass parent_class;
void (*realize)(S390CCWDevice *dev, char *sysfsdev, Error **errp);
- void (*unrealize)(S390CCWDevice *dev, Error **errp);
+ void (*unrealize)(S390CCWDevice *dev);
IOInstEnding (*handle_request) (SubchDev *sch);
int (*handle_halt) (SubchDev *sch);
int (*handle_clear) (SubchDev *sch);
diff --git a/include/hw/scsi/scsi.h b/include/hw/scsi/scsi.h
index 332ef60..2fc23e4 100644
--- a/include/hw/scsi/scsi.h
+++ b/include/hw/scsi/scsi.h
@@ -59,7 +59,7 @@
typedef struct SCSIDeviceClass {
DeviceClass parent_class;
void (*realize)(SCSIDevice *dev, Error **errp);
- void (*unrealize)(SCSIDevice *dev, Error **errp);
+ void (*unrealize)(SCSIDevice *dev);
int (*parse_cdb)(SCSIDevice *dev, SCSICommand *cmd, uint8_t *buf,
void *hba_private);
SCSIRequest *(*alloc_req)(SCSIDevice *s, uint32_t tag, uint32_t lun,
diff --git a/include/hw/stream.h b/include/hw/stream.h
index d02f62c..ed09e83 100644
--- a/include/hw/stream.h
+++ b/include/hw/stream.h
@@ -39,12 +39,13 @@
* @obj: Stream slave to push to
* @buf: Data to write
* @len: Maximum number of bytes to write
+ * @eop: End of packet flag
*/
- size_t (*push)(StreamSlave *obj, unsigned char *buf, size_t len);
+ size_t (*push)(StreamSlave *obj, unsigned char *buf, size_t len, bool eop);
} StreamSlaveClass;
size_t
-stream_push(StreamSlave *sink, uint8_t *buf, size_t len);
+stream_push(StreamSlave *sink, uint8_t *buf, size_t len, bool eop);
bool
stream_can_push(StreamSlave *sink, StreamCanPushNotifyFn notify,
diff --git a/include/hw/usb.h b/include/hw/usb.h
index c24d968..1cf1cd9 100644
--- a/include/hw/usb.h
+++ b/include/hw/usb.h
@@ -272,7 +272,7 @@
OBJECT_GET_CLASS(USBDeviceClass, (obj), TYPE_USB_DEVICE)
typedef void (*USBDeviceRealize)(USBDevice *dev, Error **errp);
-typedef void (*USBDeviceUnrealize)(USBDevice *dev, Error **errp);
+typedef void (*USBDeviceUnrealize)(USBDevice *dev);
typedef struct USBDeviceClass {
DeviceClass parent_class;
diff --git a/include/hw/watchdog/wdt_imx2.h b/include/hw/watchdog/wdt_imx2.h
new file mode 100644
index 0000000..f9af6be
--- /dev/null
+++ b/include/hw/watchdog/wdt_imx2.h
@@ -0,0 +1,90 @@
+/*
+ * Copyright (c) 2017, Impinj, Inc.
+ *
+ * i.MX2 Watchdog IP block
+ *
+ * Author: Andrey Smirnov <andrew.smirnov@gmail.com>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ */
+
+#ifndef IMX2_WDT_H
+#define IMX2_WDT_H
+
+#include "qemu/bitops.h"
+#include "hw/sysbus.h"
+#include "hw/irq.h"
+#include "hw/ptimer.h"
+
+#define TYPE_IMX2_WDT "imx2.wdt"
+#define IMX2_WDT(obj) OBJECT_CHECK(IMX2WdtState, (obj), TYPE_IMX2_WDT)
+
+enum IMX2WdtRegisters {
+ IMX2_WDT_WCR = 0x0000, /* Control Register */
+ IMX2_WDT_WSR = 0x0002, /* Service Register */
+ IMX2_WDT_WRSR = 0x0004, /* Reset Status Register */
+ IMX2_WDT_WICR = 0x0006, /* Interrupt Control Register */
+ IMX2_WDT_WMCR = 0x0008, /* Misc Register */
+};
+
+#define IMX2_WDT_MMIO_SIZE 0x000a
+
+/* Control Register definitions */
+#define IMX2_WDT_WCR_WT (0xFF << 8) /* Watchdog Timeout Field */
+#define IMX2_WDT_WCR_WDW BIT(7) /* WDOG Disable for Wait */
+#define IMX2_WDT_WCR_WDA BIT(5) /* WDOG Assertion */
+#define IMX2_WDT_WCR_SRS BIT(4) /* Software Reset Signal */
+#define IMX2_WDT_WCR_WDT BIT(3) /* WDOG Timeout Assertion */
+#define IMX2_WDT_WCR_WDE BIT(2) /* Watchdog Enable */
+#define IMX2_WDT_WCR_WDBG BIT(1) /* Watchdog Debug Enable */
+#define IMX2_WDT_WCR_WDZST BIT(0) /* Watchdog Timer Suspend */
+
+#define IMX2_WDT_WCR_LOCK_MASK (IMX2_WDT_WCR_WDZST | IMX2_WDT_WCR_WDBG \
+ | IMX2_WDT_WCR_WDW)
+
+/* Service Register definitions */
+#define IMX2_WDT_SEQ1 0x5555 /* service sequence 1 */
+#define IMX2_WDT_SEQ2 0xAAAA /* service sequence 2 */
+
+/* Reset Status Register definitions */
+#define IMX2_WDT_WRSR_TOUT BIT(1) /* Reset due to Timeout */
+#define IMX2_WDT_WRSR_SFTW BIT(0) /* Reset due to software reset */
+
+/* Interrupt Control Register definitions */
+#define IMX2_WDT_WICR_WIE BIT(15) /* Interrupt Enable */
+#define IMX2_WDT_WICR_WTIS BIT(14) /* Interrupt Status */
+#define IMX2_WDT_WICR_WICT 0xff /* Interrupt Timeout */
+#define IMX2_WDT_WICR_WICT_DEF 0x04 /* Default interrupt timeout (2s) */
+
+#define IMX2_WDT_WICR_LOCK_MASK (IMX2_WDT_WICR_WIE | IMX2_WDT_WICR_WICT)
+
+/* Misc Control Register definitions */
+#define IMX2_WDT_WMCR_PDE BIT(0) /* Power-Down Enable */
+
+typedef struct IMX2WdtState {
+ /* <private> */
+ SysBusDevice parent_obj;
+
+ /*< public >*/
+ MemoryRegion mmio;
+ qemu_irq irq;
+
+ struct ptimer_state *timer;
+ struct ptimer_state *itimer;
+
+ bool pretimeout_support;
+ bool wicr_locked;
+
+ uint16_t wcr;
+ uint16_t wsr;
+ uint16_t wrsr;
+ uint16_t wicr;
+ uint16_t wmcr;
+
+ bool wcr_locked; /* affects WDZST, WDBG, and WDW */
+ bool wcr_wde_locked; /* affects WDE */
+ bool wcr_wdt_locked; /* affects WDT (never cleared) */
+} IMX2WdtState;
+
+#endif /* IMX2_WDT_H */
diff --git a/include/hw/xen/xen-block.h b/include/hw/xen/xen-block.h
index 11d351b..2cd2fc2 100644
--- a/include/hw/xen/xen-block.h
+++ b/include/hw/xen/xen-block.h
@@ -57,7 +57,7 @@
} XenBlockDevice;
typedef void (*XenBlockDeviceRealize)(XenBlockDevice *blockdev, Error **errp);
-typedef void (*XenBlockDeviceUnrealize)(XenBlockDevice *blockdev, Error **errp);
+typedef void (*XenBlockDeviceUnrealize)(XenBlockDevice *blockdev);
typedef struct XenBlockDeviceClass {
/*< private >*/
diff --git a/include/hw/xen/xen-bus.h b/include/hw/xen/xen-bus.h
index c18c137..4ec0bb0 100644
--- a/include/hw/xen/xen-bus.h
+++ b/include/hw/xen/xen-bus.h
@@ -42,7 +42,7 @@
typedef void (*XenDeviceFrontendChanged)(XenDevice *xendev,
enum xenbus_state frontend_state,
Error **errp);
-typedef void (*XenDeviceUnrealize)(XenDevice *xendev, Error **errp);
+typedef void (*XenDeviceUnrealize)(XenDevice *xendev);
typedef struct XenDeviceClass {
/*< private >*/
diff --git a/include/migration/vmstate.h b/include/migration/vmstate.h
index 3066763..eafa39f 100644
--- a/include/migration/vmstate.h
+++ b/include/migration/vmstate.h
@@ -1199,7 +1199,6 @@
void vmstate_unregister(VMStateIf *obj, const VMStateDescription *vmsd,
void *opaque);
-struct MemoryRegion;
void vmstate_register_ram(struct MemoryRegion *memory, DeviceState *dev);
void vmstate_unregister_ram(struct MemoryRegion *memory, DeviceState *dev);
void vmstate_register_ram_global(struct MemoryRegion *memory);
diff --git a/include/monitor/hmp.h b/include/monitor/hmp.h
index e33ca5a..c986cfd 100644
--- a/include/monitor/hmp.h
+++ b/include/monitor/hmp.h
@@ -96,6 +96,7 @@
void hmp_info_numa(Monitor *mon, const QDict *qdict);
void hmp_info_memory_devices(Monitor *mon, const QDict *qdict);
void hmp_qom_list(Monitor *mon, const QDict *qdict);
+void hmp_qom_get(Monitor *mon, const QDict *qdict);
void hmp_qom_set(Monitor *mon, const QDict *qdict);
void hmp_info_qom_tree(Monitor *mon, const QDict *dict);
void object_add_completion(ReadLineState *rs, int nb_args, const char *str);
diff --git a/include/qemu/plugin.h b/include/qemu/plugin.h
index 11687e8..ab790ad 100644
--- a/include/qemu/plugin.h
+++ b/include/qemu/plugin.h
@@ -14,6 +14,22 @@
#include "qemu/option.h"
/*
+ * Events that plugins can subscribe to.
+ */
+enum qemu_plugin_event {
+ QEMU_PLUGIN_EV_VCPU_INIT,
+ QEMU_PLUGIN_EV_VCPU_EXIT,
+ QEMU_PLUGIN_EV_VCPU_TB_TRANS,
+ QEMU_PLUGIN_EV_VCPU_IDLE,
+ QEMU_PLUGIN_EV_VCPU_RESUME,
+ QEMU_PLUGIN_EV_VCPU_SYSCALL,
+ QEMU_PLUGIN_EV_VCPU_SYSCALL_RET,
+ QEMU_PLUGIN_EV_FLUSH,
+ QEMU_PLUGIN_EV_ATEXIT,
+ QEMU_PLUGIN_EV_MAX, /* total number of plugin events we support */
+};
+
+/*
* Option parsing/processing.
* Note that we can load an arbitrary number of plugins.
*/
@@ -30,38 +46,6 @@
void qemu_plugin_opt_parse(const char *optarg, QemuPluginList *head);
int qemu_plugin_load_list(QemuPluginList *head);
-#else /* !CONFIG_PLUGIN */
-static inline void qemu_plugin_add_opts(void)
-{ }
-
-static inline void qemu_plugin_opt_parse(const char *optarg,
- QemuPluginList *head)
-{
- error_report("plugin interface not enabled in this build");
- exit(1);
-}
-
-static inline int qemu_plugin_load_list(QemuPluginList *head)
-{
- return 0;
-}
-#endif /* !CONFIG_PLUGIN */
-
-/*
- * Events that plugins can subscribe to.
- */
-enum qemu_plugin_event {
- QEMU_PLUGIN_EV_VCPU_INIT,
- QEMU_PLUGIN_EV_VCPU_EXIT,
- QEMU_PLUGIN_EV_VCPU_TB_TRANS,
- QEMU_PLUGIN_EV_VCPU_IDLE,
- QEMU_PLUGIN_EV_VCPU_RESUME,
- QEMU_PLUGIN_EV_VCPU_SYSCALL,
- QEMU_PLUGIN_EV_VCPU_SYSCALL_RET,
- QEMU_PLUGIN_EV_FLUSH,
- QEMU_PLUGIN_EV_ATEXIT,
- QEMU_PLUGIN_EV_MAX, /* total number of plugin events we support */
-};
union qemu_plugin_cb_sig {
qemu_plugin_simple_cb_t simple;
@@ -182,8 +166,6 @@
return insn;
}
-#ifdef CONFIG_PLUGIN
-
void qemu_plugin_vcpu_init_hook(CPUState *cpu);
void qemu_plugin_vcpu_exit_hook(CPUState *cpu);
void qemu_plugin_tb_trans_cb(CPUState *cpu, struct qemu_plugin_tb *tb);
@@ -207,6 +189,21 @@
#else /* !CONFIG_PLUGIN */
+static inline void qemu_plugin_add_opts(void)
+{ }
+
+static inline void qemu_plugin_opt_parse(const char *optarg,
+ QemuPluginList *head)
+{
+ error_report("plugin interface not enabled in this build");
+ exit(1);
+}
+
+static inline int qemu_plugin_load_list(QemuPluginList *head)
+{
+ return 0;
+}
+
static inline void qemu_plugin_vcpu_init_hook(CPUState *cpu)
{ }
diff --git a/include/qemu/qemu-plugin.h b/include/qemu/qemu-plugin.h
index 5502e11..89ed579 100644
--- a/include/qemu/qemu-plugin.h
+++ b/include/qemu/qemu-plugin.h
@@ -331,7 +331,7 @@
* to return information about it. For non-IO accesses the device
* offset will be into the appropriate block of RAM.
*/
-bool qemu_plugin_hwaddr_is_io(struct qemu_plugin_hwaddr *hwaddr);
+bool qemu_plugin_hwaddr_is_io(const struct qemu_plugin_hwaddr *haddr);
uint64_t qemu_plugin_hwaddr_device_offset(const struct qemu_plugin_hwaddr *haddr);
typedef void
diff --git a/include/qemu/uuid.h b/include/qemu/uuid.h
index 129c45f..9925feb 100644
--- a/include/qemu/uuid.h
+++ b/include/qemu/uuid.h
@@ -34,6 +34,33 @@
};
} QemuUUID;
+/**
+ * UUID_LE - converts the fields of UUID to little-endian array,
+ * each of parameters is the filed of UUID.
+ *
+ * @time_low: The low field of the timestamp
+ * @time_mid: The middle field of the timestamp
+ * @time_hi_and_version: The high field of the timestamp
+ * multiplexed with the version number
+ * @clock_seq_hi_and_reserved: The high field of the clock
+ * sequence multiplexed with the variant
+ * @clock_seq_low: The low field of the clock sequence
+ * @node0: The spatially unique node0 identifier
+ * @node1: The spatially unique node1 identifier
+ * @node2: The spatially unique node2 identifier
+ * @node3: The spatially unique node3 identifier
+ * @node4: The spatially unique node4 identifier
+ * @node5: The spatially unique node5 identifier
+ */
+#define UUID_LE(time_low, time_mid, time_hi_and_version, \
+ clock_seq_hi_and_reserved, clock_seq_low, node0, node1, node2, \
+ node3, node4, node5) \
+ { (time_low) & 0xff, ((time_low) >> 8) & 0xff, ((time_low) >> 16) & 0xff, \
+ ((time_low) >> 24) & 0xff, (time_mid) & 0xff, ((time_mid) >> 8) & 0xff, \
+ (time_hi_and_version) & 0xff, ((time_hi_and_version) >> 8) & 0xff, \
+ (clock_seq_hi_and_reserved), (clock_seq_low), (node0), (node1), (node2),\
+ (node3), (node4), (node5) }
+
#define UUID_FMT "%02hhx%02hhx%02hhx%02hhx-" \
"%02hhx%02hhx-%02hhx%02hhx-" \
"%02hhx%02hhx-" \
diff --git a/include/qom/object.h b/include/qom/object.h
index 784c97c..fd453dc 100644
--- a/include/qom/object.h
+++ b/include/qom/object.h
@@ -369,9 +369,9 @@
struct ObjectProperty
{
- gchar *name;
- gchar *type;
- gchar *description;
+ char *name;
+ char *type;
+ char *description;
ObjectPropertyAccessor *get;
ObjectPropertyAccessor *set;
ObjectPropertyResolve *resolve;
@@ -1036,7 +1036,6 @@
* meant to allow a property to free its opaque upon object
* destruction. This may be NULL.
* @opaque: an opaque pointer to pass to the callbacks for the property
- * @errp: returns an error if this function fails
*
* Returns: The #ObjectProperty; this can be used to set the @resolve
* callback for child and link properties.
@@ -1046,16 +1045,16 @@
ObjectPropertyAccessor *get,
ObjectPropertyAccessor *set,
ObjectPropertyRelease *release,
- void *opaque, Error **errp);
+ void *opaque);
-void object_property_del(Object *obj, const char *name, Error **errp);
+void object_property_del(Object *obj, const char *name);
ObjectProperty *object_class_property_add(ObjectClass *klass, const char *name,
const char *type,
ObjectPropertyAccessor *get,
ObjectPropertyAccessor *set,
ObjectPropertyRelease *release,
- void *opaque, Error **errp);
+ void *opaque);
/**
* object_property_set_default_bool:
@@ -1321,20 +1320,6 @@
const char *typename, Error **errp);
/**
- * object_property_get_uint16List:
- * @obj: the object
- * @name: the name of the property
- * @list: the returned int list
- * @errp: returns an error if this function fails
- *
- * Returns: the value of the property, converted to integers, or
- * undefined if an error occurs (including when the property value is not
- * an list of integers).
- */
-void object_property_get_uint16List(Object *obj, const char *name,
- uint16List **list, Error **errp);
-
-/**
* object_property_set:
* @obj: the object
* @v: the visitor that will be used to write the property value. This should
@@ -1421,7 +1406,7 @@
* path is the path within the composition tree starting from the root.
* %NULL if the object doesn't have a parent (and thus a canonical path).
*/
-gchar *object_get_canonical_path_component(Object *obj);
+char *object_get_canonical_path_component(Object *obj);
/**
* object_get_canonical_path:
@@ -1429,7 +1414,7 @@
* Returns: The canonical path for a object. This is the path within the
* composition tree starting from the root.
*/
-gchar *object_get_canonical_path(Object *obj);
+char *object_get_canonical_path(Object *obj);
/**
* object_resolve_path:
@@ -1487,14 +1472,13 @@
*
* Returns: The resolved object or NULL on path lookup failure.
*/
-Object *object_resolve_path_component(Object *parent, const gchar *part);
+Object *object_resolve_path_component(Object *parent, const char *part);
/**
* object_property_add_child:
* @obj: the object to add a property to
* @name: the name of the property
* @child: the child object
- * @errp: if an error occurs, a pointer to an area to store the error
*
* Child properties form the composition tree. All objects need to be a child
* of another object. Objects can only be a child of one object.
@@ -1505,9 +1489,11 @@
* The value of a child property as a C string will be the child object's
* canonical path. It can be retrieved using object_property_get_str().
* The child object itself can be retrieved using object_property_get_link().
+ *
+ * Returns: The newly added property on success, or %NULL on failure.
*/
-void object_property_add_child(Object *obj, const char *name,
- Object *child, Error **errp);
+ObjectProperty *object_property_add_child(Object *obj, const char *name,
+ Object *child);
typedef enum {
/* Unref the link pointer when the property is deleted */
@@ -1536,7 +1522,6 @@
* @targetp: a pointer to where the link object reference is stored
* @check: callback to veto setting or NULL if the property is read-only
* @flags: additional options for the link
- * @errp: if an error occurs, a pointer to an area to store the error
*
* Links establish relationships between objects. Links are unidirectional
* although two links can be combined to form a bidirectional relationship
@@ -1556,21 +1541,21 @@
* <code>@flags</code> <code>OBJ_PROP_LINK_STRONG</code> bit is set,
* the reference count is decremented when the property is deleted or
* modified.
+ *
+ * Returns: The newly added property on success, or %NULL on failure.
*/
-void object_property_add_link(Object *obj, const char *name,
+ObjectProperty *object_property_add_link(Object *obj, const char *name,
const char *type, Object **targetp,
void (*check)(const Object *obj, const char *name,
Object *val, Error **errp),
- ObjectPropertyLinkFlags flags,
- Error **errp);
+ ObjectPropertyLinkFlags flags);
ObjectProperty *object_class_property_add_link(ObjectClass *oc,
const char *name,
const char *type, ptrdiff_t offset,
void (*check)(const Object *obj, const char *name,
Object *val, Error **errp),
- ObjectPropertyLinkFlags flags,
- Error **errp);
+ ObjectPropertyLinkFlags flags);
/**
* object_property_add_str:
@@ -1579,22 +1564,21 @@
* @get: the getter or NULL if the property is write-only. This function must
* return a string to be freed by g_free().
* @set: the setter or NULL if the property is read-only
- * @errp: if an error occurs, a pointer to an area to store the error
*
* Add a string property using getters/setters. This function will add a
* property of type 'string'.
+ *
+ * Returns: The newly added property on success, or %NULL on failure.
*/
-void object_property_add_str(Object *obj, const char *name,
+ObjectProperty *object_property_add_str(Object *obj, const char *name,
char *(*get)(Object *, Error **),
- void (*set)(Object *, const char *, Error **),
- Error **errp);
+ void (*set)(Object *, const char *, Error **));
ObjectProperty *object_class_property_add_str(ObjectClass *klass,
const char *name,
char *(*get)(Object *, Error **),
void (*set)(Object *, const char *,
- Error **),
- Error **errp);
+ Error **));
/**
* object_property_add_bool:
@@ -1602,21 +1586,20 @@
* @name: the name of the property
* @get: the getter or NULL if the property is write-only.
* @set: the setter or NULL if the property is read-only
- * @errp: if an error occurs, a pointer to an area to store the error
*
* Add a bool property using getters/setters. This function will add a
* property of type 'bool'.
+ *
+ * Returns: The newly added property on success, or %NULL on failure.
*/
-void object_property_add_bool(Object *obj, const char *name,
+ObjectProperty *object_property_add_bool(Object *obj, const char *name,
bool (*get)(Object *, Error **),
- void (*set)(Object *, bool, Error **),
- Error **errp);
+ void (*set)(Object *, bool, Error **));
ObjectProperty *object_class_property_add_bool(ObjectClass *klass,
const char *name,
bool (*get)(Object *, Error **),
- void (*set)(Object *, bool, Error **),
- Error **errp);
+ void (*set)(Object *, bool, Error **));
/**
* object_property_add_enum:
@@ -1625,44 +1608,42 @@
* @typename: the name of the enum data type
* @get: the getter or %NULL if the property is write-only.
* @set: the setter or %NULL if the property is read-only
- * @errp: if an error occurs, a pointer to an area to store the error
*
* Add an enum property using getters/setters. This function will add a
* property of type '@typename'.
+ *
+ * Returns: The newly added property on success, or %NULL on failure.
*/
-void object_property_add_enum(Object *obj, const char *name,
+ObjectProperty *object_property_add_enum(Object *obj, const char *name,
const char *typename,
const QEnumLookup *lookup,
int (*get)(Object *, Error **),
- void (*set)(Object *, int, Error **),
- Error **errp);
+ void (*set)(Object *, int, Error **));
ObjectProperty *object_class_property_add_enum(ObjectClass *klass,
const char *name,
const char *typename,
const QEnumLookup *lookup,
int (*get)(Object *, Error **),
- void (*set)(Object *, int, Error **),
- Error **errp);
+ void (*set)(Object *, int, Error **));
/**
* object_property_add_tm:
* @obj: the object to add a property to
* @name: the name of the property
* @get: the getter or NULL if the property is write-only.
- * @errp: if an error occurs, a pointer to an area to store the error
*
* Add a read-only struct tm valued property using a getter function.
* This function will add a property of type 'struct tm'.
+ *
+ * Returns: The newly added property on success, or %NULL on failure.
*/
-void object_property_add_tm(Object *obj, const char *name,
- void (*get)(Object *, struct tm *, Error **),
- Error **errp);
+ObjectProperty *object_property_add_tm(Object *obj, const char *name,
+ void (*get)(Object *, struct tm *, Error **));
ObjectProperty *object_class_property_add_tm(ObjectClass *klass,
- const char *name,
- void (*get)(Object *, struct tm *, Error **),
- Error **errp);
+ const char *name,
+ void (*get)(Object *, struct tm *, Error **));
typedef enum {
/* Automatically add a getter to the property */
@@ -1679,20 +1660,20 @@
* @name: the name of the property
* @v: pointer to value
* @flags: bitwise-or'd ObjectPropertyFlags
- * @errp: if an error occurs, a pointer to an area to store the error
*
* Add an integer property in memory. This function will add a
* property of type 'uint8'.
+ *
+ * Returns: The newly added property on success, or %NULL on failure.
*/
-void object_property_add_uint8_ptr(Object *obj, const char *name,
- const uint8_t *v, ObjectPropertyFlags flags,
- Error **errp);
+ObjectProperty *object_property_add_uint8_ptr(Object *obj, const char *name,
+ const uint8_t *v,
+ ObjectPropertyFlags flags);
ObjectProperty *object_class_property_add_uint8_ptr(ObjectClass *klass,
const char *name,
const uint8_t *v,
- ObjectPropertyFlags flags,
- Error **errp);
+ ObjectPropertyFlags flags);
/**
* object_property_add_uint16_ptr:
@@ -1700,21 +1681,20 @@
* @name: the name of the property
* @v: pointer to value
* @flags: bitwise-or'd ObjectPropertyFlags
- * @errp: if an error occurs, a pointer to an area to store the error
*
* Add an integer property in memory. This function will add a
* property of type 'uint16'.
+ *
+ * Returns: The newly added property on success, or %NULL on failure.
*/
-void object_property_add_uint16_ptr(Object *obj, const char *name,
+ObjectProperty *object_property_add_uint16_ptr(Object *obj, const char *name,
const uint16_t *v,
- ObjectPropertyFlags flags,
- Error **errp);
+ ObjectPropertyFlags flags);
ObjectProperty *object_class_property_add_uint16_ptr(ObjectClass *klass,
const char *name,
const uint16_t *v,
- ObjectPropertyFlags flags,
- Error **errp);
+ ObjectPropertyFlags flags);
/**
* object_property_add_uint32_ptr:
@@ -1722,21 +1702,20 @@
* @name: the name of the property
* @v: pointer to value
* @flags: bitwise-or'd ObjectPropertyFlags
- * @errp: if an error occurs, a pointer to an area to store the error
*
* Add an integer property in memory. This function will add a
* property of type 'uint32'.
+ *
+ * Returns: The newly added property on success, or %NULL on failure.
*/
-void object_property_add_uint32_ptr(Object *obj, const char *name,
+ObjectProperty *object_property_add_uint32_ptr(Object *obj, const char *name,
const uint32_t *v,
- ObjectPropertyFlags flags,
- Error **errp);
+ ObjectPropertyFlags flags);
ObjectProperty *object_class_property_add_uint32_ptr(ObjectClass *klass,
const char *name,
const uint32_t *v,
- ObjectPropertyFlags flags,
- Error **errp);
+ ObjectPropertyFlags flags);
/**
* object_property_add_uint64_ptr:
@@ -1744,21 +1723,20 @@
* @name: the name of the property
* @v: pointer to value
* @flags: bitwise-or'd ObjectPropertyFlags
- * @errp: if an error occurs, a pointer to an area to store the error
*
* Add an integer property in memory. This function will add a
* property of type 'uint64'.
+ *
+ * Returns: The newly added property on success, or %NULL on failure.
*/
-void object_property_add_uint64_ptr(Object *obj, const char *name,
+ObjectProperty *object_property_add_uint64_ptr(Object *obj, const char *name,
const uint64_t *v,
- ObjectPropertyFlags flags,
- Error **Errp);
+ ObjectPropertyFlags flags);
ObjectProperty *object_class_property_add_uint64_ptr(ObjectClass *klass,
const char *name,
const uint64_t *v,
- ObjectPropertyFlags flags,
- Error **Errp);
+ ObjectPropertyFlags flags);
/**
* object_property_add_alias:
@@ -1766,7 +1744,6 @@
* @name: the name of the property
* @target_obj: the object to forward property access to
* @target_name: the name of the property on the forwarded object
- * @errp: if an error occurs, a pointer to an area to store the error
*
* Add an alias for a property on an object. This function will add a property
* of the same type as the forwarded property.
@@ -1775,17 +1752,17 @@
* this property exists. In the case of a child object or an alias on the same
* object this will be the case. For aliases to other objects the caller is
* responsible for taking a reference.
+ *
+ * Returns: The newly added property on success, or %NULL on failure.
*/
-void object_property_add_alias(Object *obj, const char *name,
- Object *target_obj, const char *target_name,
- Error **errp);
+ObjectProperty *object_property_add_alias(Object *obj, const char *name,
+ Object *target_obj, const char *target_name);
/**
* object_property_add_const_link:
* @obj: the object to add a property to
* @name: the name of the property
* @target: the object to be referred by the link
- * @errp: if an error occurs, a pointer to an area to store the error
*
* Add an unmodifiable link for a property on an object. This function will
* add a property of type link<TYPE> where TYPE is the type of @target.
@@ -1794,25 +1771,25 @@
* this property exists. In the case @target is a child of @obj,
* this will be the case. Otherwise, the caller is responsible for
* taking a reference.
+ *
+ * Returns: The newly added property on success, or %NULL on failure.
*/
-void object_property_add_const_link(Object *obj, const char *name,
- Object *target, Error **errp);
+ObjectProperty *object_property_add_const_link(Object *obj, const char *name,
+ Object *target);
/**
* object_property_set_description:
* @obj: the object owning the property
* @name: the name of the property
* @description: the description of the property on the object
- * @errp: if an error occurs, a pointer to an area to store the error
*
* Set an object property's description.
*
*/
void object_property_set_description(Object *obj, const char *name,
- const char *description, Error **errp);
+ const char *description);
void object_class_property_set_description(ObjectClass *klass, const char *name,
- const char *description,
- Error **errp);
+ const char *description);
/**
* object_child_foreach:
diff --git a/include/sysemu/block-backend.h b/include/sysemu/block-backend.h
index 0917663..8203d7f 100644
--- a/include/sysemu/block-backend.h
+++ b/include/sysemu/block-backend.h
@@ -266,4 +266,6 @@
const BdrvChild *blk_root(BlockBackend *blk);
+int blk_make_empty(BlockBackend *blk, Error **errp);
+
#endif
diff --git a/include/sysemu/kvm.h b/include/sysemu/kvm.h
index 141342d..3b22504 100644
--- a/include/sysemu/kvm.h
+++ b/include/sysemu/kvm.h
@@ -379,8 +379,7 @@
/* Returns VCPU ID to be used on KVM_CREATE_VCPU ioctl() */
unsigned long kvm_arch_vcpu_id(CPUState *cpu);
-#ifdef TARGET_I386
-#define KVM_HAVE_MCE_INJECTION 1
+#ifdef KVM_HAVE_MCE_INJECTION
void kvm_arch_on_sigbus_vcpu(CPUState *cpu, int code, void *addr);
#endif
diff --git a/include/sysemu/kvm_int.h b/include/sysemu/kvm_int.h
index ac2d1f8..c660a70 100644
--- a/include/sysemu/kvm_int.h
+++ b/include/sysemu/kvm_int.h
@@ -42,4 +42,16 @@
AddressSpace *as, int as_id);
void kvm_set_max_memslot_size(hwaddr max_slot_size);
+
+/**
+ * kvm_hwpoison_page_add:
+ *
+ * Parameters:
+ * @ram_addr: the address in the RAM for the poisoned page
+ *
+ * Add a poisoned page to the list
+ *
+ * Return: None.
+ */
+void kvm_hwpoison_page_add(ram_addr_t ram_addr);
#endif
diff --git a/include/sysemu/sysemu.h b/include/sysemu/sysemu.h
index ef81302..26c0c80 100644
--- a/include/sysemu/sysemu.h
+++ b/include/sysemu/sysemu.h
@@ -92,7 +92,7 @@
void del_boot_device_path(DeviceState *dev, const char *suffix);
void device_add_bootindex_property(Object *obj, int32_t *bootindex,
const char *name, const char *suffix,
- DeviceState *dev, Error **errp);
+ DeviceState *dev);
void restore_boot_order(void *opaque);
void validate_bootdevices(const char *devices, Error **errp);
void add_boot_device_lchs(DeviceState *dev, const char *suffix,
diff --git a/include/ui/win32-kbd-hook.h b/include/ui/win32-kbd-hook.h
new file mode 100644
index 0000000..4bd9f00
--- /dev/null
+++ b/include/ui/win32-kbd-hook.h
@@ -0,0 +1,14 @@
+/*
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ */
+
+#ifndef UI_WIN32_KBD_HOOK_H
+#define UI_WIN32_KBD_HOOK_H
+
+void win32_kbd_set_window(void *hwnd);
+void win32_kbd_set_grab(bool grab);
+
+#endif
diff --git a/iothread.c b/iothread.c
index 7130be5..cb082b9 100644
--- a/iothread.c
+++ b/iothread.c
@@ -276,15 +276,15 @@
object_class_property_add(klass, "poll-max-ns", "int",
iothread_get_poll_param,
iothread_set_poll_param,
- NULL, &poll_max_ns_info, &error_abort);
+ NULL, &poll_max_ns_info);
object_class_property_add(klass, "poll-grow", "int",
iothread_get_poll_param,
iothread_set_poll_param,
- NULL, &poll_grow_info, &error_abort);
+ NULL, &poll_grow_info);
object_class_property_add(klass, "poll-shrink", "int",
iothread_get_poll_param,
iothread_set_poll_param,
- NULL, &poll_shrink_info, &error_abort);
+ NULL, &poll_shrink_info);
}
static const TypeInfo iothread_info = {
diff --git a/linux-user/arm/cpu_loop.c b/linux-user/arm/cpu_loop.c
index cf618da..13629ee 100644
--- a/linux-user/arm/cpu_loop.c
+++ b/linux-user/arm/cpu_loop.c
@@ -295,84 +295,100 @@
}
break;
case EXCP_SWI:
- case EXCP_BKPT:
{
env->eabi = 1;
/* system call */
- if (trapnr == EXCP_BKPT) {
- if (env->thumb) {
- /* FIXME - what to do if get_user() fails? */
- get_user_code_u16(insn, env->regs[15], env);
- n = insn & 0xff;
- env->regs[15] += 2;
- } else {
- /* FIXME - what to do if get_user() fails? */
- get_user_code_u32(insn, env->regs[15], env);
- n = (insn & 0xf) | ((insn >> 4) & 0xff0);
- env->regs[15] += 4;
- }
+ if (env->thumb) {
+ /* Thumb is always EABI style with syscall number in r7 */
+ n = env->regs[7];
} else {
- if (env->thumb) {
- /* FIXME - what to do if get_user() fails? */
- get_user_code_u16(insn, env->regs[15] - 2, env);
- n = insn & 0xff;
+ /*
+ * Equivalent of kernel CONFIG_OABI_COMPAT: read the
+ * Arm SVC insn to extract the immediate, which is the
+ * syscall number in OABI.
+ */
+ /* FIXME - what to do if get_user() fails? */
+ get_user_code_u32(insn, env->regs[15] - 4, env);
+ n = insn & 0xffffff;
+ if (n == 0) {
+ /* zero immediate: EABI, syscall number in r7 */
+ n = env->regs[7];
} else {
- /* FIXME - what to do if get_user() fails? */
- get_user_code_u32(insn, env->regs[15] - 4, env);
- n = insn & 0xffffff;
+ /*
+ * This XOR matches the kernel code: an immediate
+ * in the valid range (0x900000 .. 0x9fffff) is
+ * converted into the correct EABI-style syscall
+ * number; invalid immediates end up as values
+ * > 0xfffff and are handled below as out-of-range.
+ */
+ n ^= ARM_SYSCALL_BASE;
+ env->eabi = 0;
}
}
- if (n == ARM_NR_cacheflush) {
- /* nop */
- } else if (n == 0 || n >= ARM_SYSCALL_BASE || env->thumb) {
- /* linux syscall */
- if (env->thumb || n == 0) {
- n = env->regs[7];
- } else {
- n -= ARM_SYSCALL_BASE;
- env->eabi = 0;
- }
- if ( n > ARM_NR_BASE) {
- switch (n) {
- case ARM_NR_cacheflush:
- /* nop */
- break;
- case ARM_NR_set_tls:
- cpu_set_tls(env, env->regs[0]);
- env->regs[0] = 0;
- break;
- case ARM_NR_breakpoint:
- env->regs[15] -= env->thumb ? 2 : 4;
- goto excp_debug;
- case ARM_NR_get_tls:
- env->regs[0] = cpu_get_tls(env);
- break;
- default:
+ if (n > ARM_NR_BASE) {
+ switch (n) {
+ case ARM_NR_cacheflush:
+ /* nop */
+ break;
+ case ARM_NR_set_tls:
+ cpu_set_tls(env, env->regs[0]);
+ env->regs[0] = 0;
+ break;
+ case ARM_NR_breakpoint:
+ env->regs[15] -= env->thumb ? 2 : 4;
+ goto excp_debug;
+ case ARM_NR_get_tls:
+ env->regs[0] = cpu_get_tls(env);
+ break;
+ default:
+ if (n < 0xf0800) {
+ /*
+ * Syscalls 0xf0000..0xf07ff (or 0x9f0000..
+ * 0x9f07ff in OABI numbering) are defined
+ * to return -ENOSYS rather than raising
+ * SIGILL. Note that we have already
+ * removed the 0x900000 prefix.
+ */
qemu_log_mask(LOG_UNIMP,
- "qemu: Unsupported ARM syscall: 0x%x\n",
+ "qemu: Unsupported ARM syscall: 0x%x\n",
n);
env->regs[0] = -TARGET_ENOSYS;
- break;
+ } else {
+ /*
+ * Otherwise SIGILL. This includes any SWI with
+ * immediate not originally 0x9fxxxx, because
+ * of the earlier XOR.
+ */
+ info.si_signo = TARGET_SIGILL;
+ info.si_errno = 0;
+ info.si_code = TARGET_ILL_ILLTRP;
+ info._sifields._sigfault._addr = env->regs[15];
+ if (env->thumb) {
+ info._sifields._sigfault._addr -= 2;
+ } else {
+ info._sifields._sigfault._addr -= 4;
+ }
+ queue_signal(env, info.si_signo,
+ QEMU_SI_FAULT, &info);
}
- } else {
- ret = do_syscall(env,
- n,
- env->regs[0],
- env->regs[1],
- env->regs[2],
- env->regs[3],
- env->regs[4],
- env->regs[5],
- 0, 0);
- if (ret == -TARGET_ERESTARTSYS) {
- env->regs[15] -= env->thumb ? 2 : 4;
- } else if (ret != -TARGET_QEMU_ESIGRETURN) {
- env->regs[0] = ret;
- }
+ break;
}
} else {
- goto error;
+ ret = do_syscall(env,
+ n,
+ env->regs[0],
+ env->regs[1],
+ env->regs[2],
+ env->regs[3],
+ env->regs[4],
+ env->regs[5],
+ 0, 0);
+ if (ret == -TARGET_ERESTARTSYS) {
+ env->regs[15] -= env->thumb ? 2 : 4;
+ } else if (ret != -TARGET_QEMU_ESIGRETURN) {
+ env->regs[0] = ret;
+ }
}
}
break;
@@ -396,6 +412,7 @@
}
break;
case EXCP_DEBUG:
+ case EXCP_BKPT:
excp_debug:
info.si_signo = TARGET_SIGTRAP;
info.si_errno = 0;
diff --git a/linux-user/arm/signal.c b/linux-user/arm/signal.c
index d96fc27..f21d153 100644
--- a/linux-user/arm/signal.c
+++ b/linux-user/arm/signal.c
@@ -126,8 +126,6 @@
abi_ulong retcode[4];
};
-#define TARGET_CONFIG_CPU_32 1
-
/*
* For ARM syscalls, we encode the syscall number into the instruction.
*/
@@ -187,9 +185,7 @@
__put_user(env->regs[13], &sc->arm_sp);
__put_user(env->regs[14], &sc->arm_lr);
__put_user(env->regs[15], &sc->arm_pc);
-#ifdef TARGET_CONFIG_CPU_32
__put_user(cpsr_read(env), &sc->arm_cpsr);
-#endif
__put_user(/* current->thread.trap_no */ 0, &sc->trap_no);
__put_user(/* current->thread.error_code */ 0, &sc->error_code);
@@ -244,6 +240,11 @@
} else {
cpsr &= ~CPSR_T;
}
+ if (env->cp15.sctlr_el[1] & SCTLR_E0E) {
+ cpsr |= CPSR_E;
+ } else {
+ cpsr &= ~CPSR_E;
+ }
if (ka->sa_flags & TARGET_SA_RESTORER) {
if (is_fdpic) {
@@ -287,7 +288,8 @@
env->regs[13] = frame_addr;
env->regs[14] = retcode;
env->regs[15] = handler & (thumb ? ~1 : ~3);
- cpsr_write(env, cpsr, CPSR_IT | CPSR_T, CPSRWriteByInstr);
+ cpsr_write(env, cpsr, CPSR_IT | CPSR_T | CPSR_E, CPSRWriteByInstr);
+ arm_rebuild_hflags(env);
return 0;
}
@@ -543,10 +545,9 @@
__get_user(env->regs[13], &sc->arm_sp);
__get_user(env->regs[14], &sc->arm_lr);
__get_user(env->regs[15], &sc->arm_pc);
-#ifdef TARGET_CONFIG_CPU_32
__get_user(cpsr, &sc->arm_cpsr);
cpsr_write(env, cpsr, CPSR_USER | CPSR_EXEC, CPSRWriteByInstr);
-#endif
+ arm_rebuild_hflags(env);
err |= !valid_user_regs(env);
diff --git a/linux-user/elfload.c b/linux-user/elfload.c
index 619c054..ebc663e 100644
--- a/linux-user/elfload.c
+++ b/linux-user/elfload.c
@@ -11,6 +11,7 @@
#include "qemu/queue.h"
#include "qemu/guest-random.h"
#include "qemu/units.h"
+#include "qemu/selfmap.h"
#ifdef _ARCH_PPC64
#undef ARCH_DLINFO
@@ -382,68 +383,30 @@
/* The commpage only exists for 32 bit kernels */
-/* Return 1 if the proposed guest space is suitable for the guest.
- * Return 0 if the proposed guest space isn't suitable, but another
- * address space should be tried.
- * Return -1 if there is no way the proposed guest space can be
- * valid regardless of the base.
- * The guest code may leave a page mapped and populate it if the
- * address is suitable.
- */
-static int init_guest_commpage(unsigned long guest_base,
- unsigned long guest_size)
+#define ARM_COMMPAGE (intptr_t)0xffff0f00u
+
+static bool init_guest_commpage(void)
{
- unsigned long real_start, test_page_addr;
+ void *want = g2h(ARM_COMMPAGE & -qemu_host_page_size);
+ void *addr = mmap(want, qemu_host_page_size, PROT_READ | PROT_WRITE,
+ MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
- /* We need to check that we can force a fault on access to the
- * commpage at 0xffff0fxx
- */
- test_page_addr = guest_base + (0xffff0f00 & qemu_host_page_mask);
-
- /* If the commpage lies within the already allocated guest space,
- * then there is no way we can allocate it.
- *
- * You may be thinking that that this check is redundant because
- * we already validated the guest size against MAX_RESERVED_VA;
- * but if qemu_host_page_mask is unusually large, then
- * test_page_addr may be lower.
- */
- if (test_page_addr >= guest_base
- && test_page_addr < (guest_base + guest_size)) {
- return -1;
+ if (addr == MAP_FAILED) {
+ perror("Allocating guest commpage");
+ exit(EXIT_FAILURE);
+ }
+ if (addr != want) {
+ return false;
}
- /* Note it needs to be writeable to let us initialise it */
- real_start = (unsigned long)
- mmap((void *)test_page_addr, qemu_host_page_size,
- PROT_READ | PROT_WRITE,
- MAP_ANONYMOUS | MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
+ /* Set kernel helper versions; rest of page is 0. */
+ __put_user(5, (uint32_t *)g2h(0xffff0ffcu));
- /* If we can't map it then try another address */
- if (real_start == -1ul) {
- return 0;
- }
-
- if (real_start != test_page_addr) {
- /* OS didn't put the page where we asked - unmap and reject */
- munmap((void *)real_start, qemu_host_page_size);
- return 0;
- }
-
- /* Leave the page mapped
- * Populate it (mmap should have left it all 0'd)
- */
-
- /* Kernel helper versions */
- __put_user(5, (uint32_t *)g2h(0xffff0ffcul));
-
- /* Now it's populated make it RO */
- if (mprotect((void *)test_page_addr, qemu_host_page_size, PROT_READ)) {
+ if (mprotect(addr, qemu_host_page_size, PROT_READ)) {
perror("Protecting guest commpage");
- exit(-1);
+ exit(EXIT_FAILURE);
}
-
- return 1; /* All good */
+ return true;
}
#define ELF_HWCAP get_elf_hwcap()
@@ -2075,240 +2038,270 @@
return sp;
}
-unsigned long init_guest_space(unsigned long host_start,
- unsigned long host_size,
- unsigned long guest_start,
- bool fixed)
+#ifndef ARM_COMMPAGE
+#define ARM_COMMPAGE 0
+#define init_guest_commpage() true
+#endif
+
+static void pgb_fail_in_use(const char *image_name)
+{
+ error_report("%s: requires virtual address space that is in use "
+ "(omit the -B option or choose a different value)",
+ image_name);
+ exit(EXIT_FAILURE);
+}
+
+static void pgb_have_guest_base(const char *image_name, abi_ulong guest_loaddr,
+ abi_ulong guest_hiaddr, long align)
+{
+ const int flags = MAP_ANONYMOUS | MAP_PRIVATE | MAP_NORESERVE;
+ void *addr, *test;
+
+ if (!QEMU_IS_ALIGNED(guest_base, align)) {
+ fprintf(stderr, "Requested guest base 0x%lx does not satisfy "
+ "host minimum alignment (0x%lx)\n",
+ guest_base, align);
+ exit(EXIT_FAILURE);
+ }
+
+ /* Sanity check the guest binary. */
+ if (reserved_va) {
+ if (guest_hiaddr > reserved_va) {
+ error_report("%s: requires more than reserved virtual "
+ "address space (0x%" PRIx64 " > 0x%lx)",
+ image_name, (uint64_t)guest_hiaddr, reserved_va);
+ exit(EXIT_FAILURE);
+ }
+ } else {
+#if HOST_LONG_BITS < TARGET_ABI_BITS
+ if ((guest_hiaddr - guest_base) > ~(uintptr_t)0) {
+ error_report("%s: requires more virtual address space "
+ "than the host can provide (0x%" PRIx64 ")",
+ image_name, (uint64_t)guest_hiaddr - guest_base);
+ exit(EXIT_FAILURE);
+ }
+#endif
+ }
+
+ /*
+ * Expand the allocation to the entire reserved_va.
+ * Exclude the mmap_min_addr hole.
+ */
+ if (reserved_va) {
+ guest_loaddr = (guest_base >= mmap_min_addr ? 0
+ : mmap_min_addr - guest_base);
+ guest_hiaddr = reserved_va;
+ }
+
+ /* Reserve the address space for the binary, or reserved_va. */
+ test = g2h(guest_loaddr);
+ addr = mmap(test, guest_hiaddr - guest_loaddr, PROT_NONE, flags, -1, 0);
+ if (test != addr) {
+ pgb_fail_in_use(image_name);
+ }
+}
+
+/* Return value for guest_base, or -1 if no hole found. */
+static uintptr_t pgb_find_hole(uintptr_t guest_loaddr, uintptr_t guest_size,
+ long align)
+{
+ GSList *maps, *iter;
+ uintptr_t this_start, this_end, next_start, brk;
+ intptr_t ret = -1;
+
+ assert(QEMU_IS_ALIGNED(guest_loaddr, align));
+
+ maps = read_self_maps();
+
+ /* Read brk after we've read the maps, which will malloc. */
+ brk = (uintptr_t)sbrk(0);
+
+ /* The first hole is before the first map entry. */
+ this_start = mmap_min_addr;
+
+ for (iter = maps; iter;
+ this_start = next_start, iter = g_slist_next(iter)) {
+ uintptr_t align_start, hole_size;
+
+ this_end = ((MapInfo *)iter->data)->start;
+ next_start = ((MapInfo *)iter->data)->end;
+ align_start = ROUND_UP(this_start, align);
+
+ /* Skip holes that are too small. */
+ if (align_start >= this_end) {
+ continue;
+ }
+ hole_size = this_end - align_start;
+ if (hole_size < guest_size) {
+ continue;
+ }
+
+ /* If this hole contains brk, give ourselves some room to grow. */
+ if (this_start <= brk && brk < this_end) {
+ hole_size -= guest_size;
+ if (sizeof(uintptr_t) == 8 && hole_size >= 1 * GiB) {
+ align_start += 1 * GiB;
+ } else if (hole_size >= 16 * MiB) {
+ align_start += 16 * MiB;
+ } else {
+ align_start = (this_end - guest_size) & -align;
+ if (align_start < this_start) {
+ continue;
+ }
+ }
+ }
+
+ /* Record the lowest successful match. */
+ if (ret < 0) {
+ ret = align_start - guest_loaddr;
+ }
+ /* If this hole contains the identity map, select it. */
+ if (align_start <= guest_loaddr &&
+ guest_loaddr + guest_size <= this_end) {
+ ret = 0;
+ }
+ /* If this hole ends above the identity map, stop looking. */
+ if (this_end >= guest_loaddr) {
+ break;
+ }
+ }
+ free_self_maps(maps);
+
+ return ret;
+}
+
+static void pgb_static(const char *image_name, abi_ulong orig_loaddr,
+ abi_ulong orig_hiaddr, long align)
+{
+ uintptr_t loaddr = orig_loaddr;
+ uintptr_t hiaddr = orig_hiaddr;
+ uintptr_t addr;
+
+ if (hiaddr != orig_hiaddr) {
+ error_report("%s: requires virtual address space that the "
+ "host cannot provide (0x%" PRIx64 ")",
+ image_name, (uint64_t)orig_hiaddr);
+ exit(EXIT_FAILURE);
+ }
+
+ loaddr &= -align;
+ if (ARM_COMMPAGE) {
+ /*
+ * Extend the allocation to include the commpage.
+ * For a 64-bit host, this is just 4GiB; for a 32-bit host,
+ * the address arithmetic will wrap around, but the difference
+ * will produce the correct allocation size.
+ */
+ if (sizeof(uintptr_t) == 8 || loaddr >= 0x80000000u) {
+ hiaddr = (uintptr_t)4 << 30;
+ } else {
+ loaddr = ARM_COMMPAGE & -align;
+ }
+ }
+
+ addr = pgb_find_hole(loaddr, hiaddr - loaddr, align);
+ if (addr == -1) {
+ /*
+ * If ARM_COMMPAGE, there *might* be a non-consecutive allocation
+ * that can satisfy both. But as the normal arm32 link base address
+ * is ~32k, and we extend down to include the commpage, making the
+ * overhead only ~96k, this is unlikely.
+ */
+ error_report("%s: Unable to allocate %#zx bytes of "
+ "virtual address space", image_name,
+ (size_t)(hiaddr - loaddr));
+ exit(EXIT_FAILURE);
+ }
+
+ guest_base = addr;
+}
+
+static void pgb_dynamic(const char *image_name, long align)
+{
+ /*
+ * The executable is dynamic and does not require a fixed address.
+ * All we need is a commpage that satisfies align.
+ * If we do not need a commpage, leave guest_base == 0.
+ */
+ if (ARM_COMMPAGE) {
+ uintptr_t addr, commpage;
+
+ /* 64-bit hosts should have used reserved_va. */
+ assert(sizeof(uintptr_t) == 4);
+
+ /*
+ * By putting the commpage at the first hole, that puts guest_base
+ * just above that, and maximises the positive guest addresses.
+ */
+ commpage = ARM_COMMPAGE & -align;
+ addr = pgb_find_hole(commpage, -commpage, align);
+ assert(addr != -1);
+ guest_base = addr;
+ }
+}
+
+static void pgb_reserved_va(const char *image_name, abi_ulong guest_loaddr,
+ abi_ulong guest_hiaddr, long align)
+{
+ const int flags = MAP_ANONYMOUS | MAP_PRIVATE | MAP_NORESERVE;
+ void *addr, *test;
+
+ if (guest_hiaddr > reserved_va) {
+ error_report("%s: requires more than reserved virtual "
+ "address space (0x%" PRIx64 " > 0x%lx)",
+ image_name, (uint64_t)guest_hiaddr, reserved_va);
+ exit(EXIT_FAILURE);
+ }
+
+ /* Widen the "image" to the entire reserved address space. */
+ pgb_static(image_name, 0, reserved_va, align);
+
+ /* Reserve the memory on the host. */
+ assert(guest_base != 0);
+ test = g2h(0);
+ addr = mmap(test, reserved_va, PROT_NONE, flags, -1, 0);
+ if (addr == MAP_FAILED) {
+ error_report("Unable to reserve 0x%lx bytes of virtual address "
+ "space for use as guest address space (check your "
+ "virtual memory ulimit setting or reserve less "
+ "using -R option)", reserved_va);
+ exit(EXIT_FAILURE);
+ }
+ assert(addr == test);
+}
+
+void probe_guest_base(const char *image_name, abi_ulong guest_loaddr,
+ abi_ulong guest_hiaddr)
{
/* In order to use host shmat, we must be able to honor SHMLBA. */
- unsigned long align = MAX(SHMLBA, qemu_host_page_size);
- unsigned long current_start, aligned_start;
- int flags;
+ uintptr_t align = MAX(SHMLBA, qemu_host_page_size);
- assert(host_start || host_size);
-
- /* If just a starting address is given, then just verify that
- * address. */
- if (host_start && !host_size) {
-#if defined(TARGET_ARM) && !defined(TARGET_AARCH64)
- if (init_guest_commpage(host_start, host_size) != 1) {
- return (unsigned long)-1;
- }
-#endif
- return host_start;
+ if (have_guest_base) {
+ pgb_have_guest_base(image_name, guest_loaddr, guest_hiaddr, align);
+ } else if (reserved_va) {
+ pgb_reserved_va(image_name, guest_loaddr, guest_hiaddr, align);
+ } else if (guest_loaddr) {
+ pgb_static(image_name, guest_loaddr, guest_hiaddr, align);
+ } else {
+ pgb_dynamic(image_name, align);
}
- /* Setup the initial flags and start address. */
- current_start = host_start & -align;
- flags = MAP_ANONYMOUS | MAP_PRIVATE | MAP_NORESERVE;
- if (fixed) {
- flags |= MAP_FIXED;
- }
-
- /* Otherwise, a non-zero size region of memory needs to be mapped
- * and validated. */
-
-#if defined(TARGET_ARM) && !defined(TARGET_AARCH64)
- /* On 32-bit ARM, we need to map not just the usable memory, but
- * also the commpage. Try to find a suitable place by allocating
- * a big chunk for all of it. If host_start, then the naive
- * strategy probably does good enough.
- */
- if (!host_start) {
- unsigned long guest_full_size, host_full_size, real_start;
-
- guest_full_size =
- (0xffff0f00 & qemu_host_page_mask) + qemu_host_page_size;
- host_full_size = guest_full_size - guest_start;
- real_start = (unsigned long)
- mmap(NULL, host_full_size, PROT_NONE, flags, -1, 0);
- if (real_start == (unsigned long)-1) {
- if (host_size < host_full_size - qemu_host_page_size) {
- /* We failed to map a continous segment, but we're
- * allowed to have a gap between the usable memory and
- * the commpage where other things can be mapped.
- * This sparseness gives us more flexibility to find
- * an address range.
- */
- goto naive;
- }
- return (unsigned long)-1;
- }
- munmap((void *)real_start, host_full_size);
- if (real_start & (align - 1)) {
- /* The same thing again, but with extra
- * so that we can shift around alignment.
- */
- unsigned long real_size = host_full_size + qemu_host_page_size;
- real_start = (unsigned long)
- mmap(NULL, real_size, PROT_NONE, flags, -1, 0);
- if (real_start == (unsigned long)-1) {
- if (host_size < host_full_size - qemu_host_page_size) {
- goto naive;
- }
- return (unsigned long)-1;
- }
- munmap((void *)real_start, real_size);
- real_start = ROUND_UP(real_start, align);
- }
- current_start = real_start;
- }
- naive:
-#endif
-
- while (1) {
- unsigned long real_start, real_size, aligned_size;
- aligned_size = real_size = host_size;
-
- /* Do not use mmap_find_vma here because that is limited to the
- * guest address space. We are going to make the
- * guest address space fit whatever we're given.
+ /* Reserve and initialize the commpage. */
+ if (!init_guest_commpage()) {
+ /*
+ * With have_guest_base, the user has selected the address and
+ * we are trying to work with that. Otherwise, we have selected
+ * free space and init_guest_commpage must succeeded.
*/
- real_start = (unsigned long)
- mmap((void *)current_start, host_size, PROT_NONE, flags, -1, 0);
- if (real_start == (unsigned long)-1) {
- return (unsigned long)-1;
- }
-
- /* Check to see if the address is valid. */
- if (host_start && real_start != current_start) {
- qemu_log_mask(CPU_LOG_PAGE, "invalid %lx && %lx != %lx\n",
- host_start, real_start, current_start);
- goto try_again;
- }
-
- /* Ensure the address is properly aligned. */
- if (real_start & (align - 1)) {
- /* Ideally, we adjust like
- *
- * pages: [ ][ ][ ][ ][ ]
- * old: [ real ]
- * [ aligned ]
- * new: [ real ]
- * [ aligned ]
- *
- * But if there is something else mapped right after it,
- * then obviously it won't have room to grow, and the
- * kernel will put the new larger real someplace else with
- * unknown alignment (if we made it to here, then
- * fixed=false). Which is why we grow real by a full page
- * size, instead of by part of one; so that even if we get
- * moved, we can still guarantee alignment. But this does
- * mean that there is a padding of < 1 page both before
- * and after the aligned range; the "after" could could
- * cause problems for ARM emulation where it could butt in
- * to where we need to put the commpage.
- */
- munmap((void *)real_start, host_size);
- real_size = aligned_size + align;
- real_start = (unsigned long)
- mmap((void *)real_start, real_size, PROT_NONE, flags, -1, 0);
- if (real_start == (unsigned long)-1) {
- return (unsigned long)-1;
- }
- aligned_start = ROUND_UP(real_start, align);
- } else {
- aligned_start = real_start;
- }
-
-#if defined(TARGET_ARM) && !defined(TARGET_AARCH64)
- /* On 32-bit ARM, we need to also be able to map the commpage. */
- int valid = init_guest_commpage(aligned_start - guest_start,
- aligned_size + guest_start);
- if (valid == -1) {
- munmap((void *)real_start, real_size);
- return (unsigned long)-1;
- } else if (valid == 0) {
- goto try_again;
- }
-#endif
-
- /* If nothing has said `return -1` or `goto try_again` yet,
- * then the address we have is good.
- */
- break;
-
- try_again:
- /* That address didn't work. Unmap and try a different one.
- * The address the host picked because is typically right at
- * the top of the host address space and leaves the guest with
- * no usable address space. Resort to a linear search. We
- * already compensated for mmap_min_addr, so this should not
- * happen often. Probably means we got unlucky and host
- * address space randomization put a shared library somewhere
- * inconvenient.
- *
- * This is probably a good strategy if host_start, but is
- * probably a bad strategy if not, which means we got here
- * because of trouble with ARM commpage setup.
- */
- if (munmap((void *)real_start, real_size) != 0) {
- error_report("%s: failed to unmap %lx:%lx (%s)", __func__,
- real_start, real_size, strerror(errno));
- abort();
- }
- current_start += align;
- if (host_start == current_start) {
- /* Theoretically possible if host doesn't have any suitably
- * aligned areas. Normally the first mmap will fail.
- */
- return (unsigned long)-1;
- }
+ assert(have_guest_base);
+ pgb_fail_in_use(image_name);
}
- qemu_log_mask(CPU_LOG_PAGE, "Reserved 0x%lx bytes of guest address space\n", host_size);
-
- return aligned_start;
+ assert(QEMU_IS_ALIGNED(guest_base, align));
+ qemu_log_mask(CPU_LOG_PAGE, "Locating guest address space "
+ "@ 0x%" PRIx64 "\n", (uint64_t)guest_base);
}
-static void probe_guest_base(const char *image_name,
- abi_ulong loaddr, abi_ulong hiaddr)
-{
- /* Probe for a suitable guest base address, if the user has not set
- * it explicitly, and set guest_base appropriately.
- * In case of error we will print a suitable message and exit.
- */
- const char *errmsg;
- if (!have_guest_base && !reserved_va) {
- unsigned long host_start, real_start, host_size;
-
- /* Round addresses to page boundaries. */
- loaddr &= qemu_host_page_mask;
- hiaddr = HOST_PAGE_ALIGN(hiaddr);
-
- if (loaddr < mmap_min_addr) {
- host_start = HOST_PAGE_ALIGN(mmap_min_addr);
- } else {
- host_start = loaddr;
- if (host_start != loaddr) {
- errmsg = "Address overflow loading ELF binary";
- goto exit_errmsg;
- }
- }
- host_size = hiaddr - loaddr;
-
- /* Setup the initial guest memory space with ranges gleaned from
- * the ELF image that is being loaded.
- */
- real_start = init_guest_space(host_start, host_size, loaddr, false);
- if (real_start == (unsigned long)-1) {
- errmsg = "Unable to find space for application";
- goto exit_errmsg;
- }
- guest_base = real_start - loaddr;
-
- qemu_log_mask(CPU_LOG_PAGE, "Relocating guest address space from 0x"
- TARGET_ABI_FMT_lx " to 0x%lx\n",
- loaddr, real_start);
- }
- return;
-
-exit_errmsg:
- fprintf(stderr, "%s: %s\n", image_name, errmsg);
- exit(-1);
-}
-
-
/* Load an ELF image into the address space.
IMAGE_NAME is the filename of the image, to use in error messages.
@@ -2399,6 +2392,12 @@
* MMAP_MIN_ADDR or the QEMU application itself.
*/
probe_guest_base(image_name, loaddr, hiaddr);
+ } else {
+ /*
+ * The binary is dynamic, but we still need to
+ * select guest_base. In this case we pass a size.
+ */
+ probe_guest_base(image_name, 0, hiaddr - loaddr);
}
}
diff --git a/linux-user/flatload.c b/linux-user/flatload.c
index 66901f3..8fb448f 100644
--- a/linux-user/flatload.c
+++ b/linux-user/flatload.c
@@ -442,6 +442,12 @@
indx_len = (indx_len + 15) & ~(abi_ulong)15;
/*
+ * Alloate the address space.
+ */
+ probe_guest_base(bprm->filename, 0,
+ text_len + data_len + extra + indx_len);
+
+ /*
* there are a couple of cases here, the separate code/data
* case, and then the fully copied to RAM case which lumps
* it all together.
diff --git a/linux-user/main.c b/linux-user/main.c
index 2cd4432..3597e99 100644
--- a/linux-user/main.c
+++ b/linux-user/main.c
@@ -24,6 +24,7 @@
#include "qemu-version.h"
#include <sys/syscall.h>
#include <sys/resource.h>
+#include <sys/shm.h>
#include "qapi/error.h"
#include "qemu.h"
@@ -58,7 +59,7 @@
static const char *seed_optarg;
unsigned long mmap_min_addr;
unsigned long guest_base;
-int have_guest_base;
+bool have_guest_base;
/*
* Used to implement backwards-compatibility for the `-strace`, and
@@ -333,7 +334,7 @@
static void handle_arg_guest_base(const char *arg)
{
guest_base = strtol(arg, NULL, 0);
- have_guest_base = 1;
+ have_guest_base = true;
}
static void handle_arg_reserved_va(const char *arg)
@@ -748,28 +749,6 @@
envlist_free(envlist);
/*
- * Now that page sizes are configured in tcg_exec_init() we can do
- * proper page alignment for guest_base.
- */
- guest_base = HOST_PAGE_ALIGN(guest_base);
-
- if (reserved_va || have_guest_base) {
- guest_base = init_guest_space(guest_base, reserved_va, 0,
- have_guest_base);
- if (guest_base == (unsigned long)-1) {
- fprintf(stderr, "Unable to reserve 0x%lx bytes of virtual address "
- "space for use as guest address space (check your virtual "
- "memory ulimit setting or reserve less using -R option)\n",
- reserved_va);
- exit(EXIT_FAILURE);
- }
-
- if (reserved_va) {
- mmap_next_start = reserved_va;
- }
- }
-
- /*
* Read in mmap_min_addr kernel parameter. This value is used
* When loading the ELF image to determine whether guest_base
* is needed. It is also used in mmap_find_vma.
diff --git a/linux-user/ppc/cpu_loop.c b/linux-user/ppc/cpu_loop.c
index 5b27f86..df71e15 100644
--- a/linux-user/ppc/cpu_loop.c
+++ b/linux-user/ppc/cpu_loop.c
@@ -267,6 +267,7 @@
queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info);
break;
case POWERPC_EXCP_SYSCALL: /* System call exception */
+ case POWERPC_EXCP_SYSCALL_VECTORED:
cpu_abort(cs, "Syscall exception while in user mode. "
"Aborting\n");
break;
diff --git a/linux-user/qemu.h b/linux-user/qemu.h
index 792c742..ce902f5 100644
--- a/linux-user/qemu.h
+++ b/linux-user/qemu.h
@@ -219,18 +219,27 @@
void fork_start(void);
void fork_end(int child);
-/* Creates the initial guest address space in the host memory space using
- * the given host start address hint and size. The guest_start parameter
- * specifies the start address of the guest space. guest_base will be the
- * difference between the host start address computed by this function and
- * guest_start. If fixed is specified, then the mapped address space must
- * start at host_start. The real start address of the mapped memory space is
- * returned or -1 if there was an error.
+/**
+ * probe_guest_base:
+ * @image_name: the executable being loaded
+ * @loaddr: the lowest fixed address in the executable
+ * @hiaddr: the highest fixed address in the executable
+ *
+ * Creates the initial guest address space in the host memory space.
+ *
+ * If @loaddr == 0, then no address in the executable is fixed,
+ * i.e. it is fully relocatable. In that case @hiaddr is the size
+ * of the executable.
+ *
+ * This function will not return if a valid value for guest_base
+ * cannot be chosen. On return, the executable loader can expect
+ *
+ * target_mmap(loaddr, hiaddr - loaddr, ...)
+ *
+ * to succeed.
*/
-unsigned long init_guest_space(unsigned long host_start,
- unsigned long host_size,
- unsigned long guest_start,
- bool fixed);
+void probe_guest_base(const char *image_name,
+ abi_ulong loaddr, abi_ulong hiaddr);
#include "qemu/log.h"
diff --git a/linux-user/syscall.c b/linux-user/syscall.c
index 05f0391..7f6700c 100644
--- a/linux-user/syscall.c
+++ b/linux-user/syscall.c
@@ -7635,30 +7635,33 @@
return -TARGET_ERESTARTSYS;
}
- cpu_list_lock();
+ pthread_mutex_lock(&clone_lock);
if (CPU_NEXT(first_cpu)) {
- TaskState *ts;
+ TaskState *ts = cpu->opaque;
- /* Remove the CPU from the list. */
- QTAILQ_REMOVE_RCU(&cpus, cpu, node);
+ object_property_set_bool(OBJECT(cpu), false, "realized", NULL);
+ object_unref(OBJECT(cpu));
+ /*
+ * At this point the CPU should be unrealized and removed
+ * from cpu lists. We can clean-up the rest of the thread
+ * data without the lock held.
+ */
- cpu_list_unlock();
+ pthread_mutex_unlock(&clone_lock);
- ts = cpu->opaque;
if (ts->child_tidptr) {
put_user_u32(0, ts->child_tidptr);
do_sys_futex(g2h(ts->child_tidptr), FUTEX_WAKE, INT_MAX,
NULL, NULL, 0);
}
thread_cpu = NULL;
- object_unref(OBJECT(cpu));
g_free(ts);
rcu_unregister_thread();
pthread_exit(NULL);
}
- cpu_list_unlock();
+ pthread_mutex_unlock(&clone_lock);
preexit_cleanup(cpu_env, arg1);
_exit(arg1);
return 0; /* avoid warning */
diff --git a/memory.c b/memory.c
index 601b749..fd6f3d6 100644
--- a/memory.c
+++ b/memory.c
@@ -1154,7 +1154,7 @@
owner = container_get(qdev_get_machine(), "/unattached");
}
- object_property_add_child(owner, name_array, OBJECT(mr), &error_abort);
+ object_property_add_child(owner, name_array, OBJECT(mr));
object_unref(OBJECT(mr));
g_free(name_array);
g_free(escaped_name);
@@ -1175,7 +1175,7 @@
Error **errp)
{
MemoryRegion *mr = MEMORY_REGION(obj);
- gchar *path = (gchar *)"";
+ char *path = (char *)"";
if (mr->container) {
path = object_get_canonical_path(OBJECT(mr->container));
@@ -1230,19 +1230,19 @@
"link<" TYPE_MEMORY_REGION ">",
memory_region_get_container,
NULL, /* memory_region_set_container */
- NULL, NULL, &error_abort);
+ NULL, NULL);
op->resolve = memory_region_resolve_container;
object_property_add_uint64_ptr(OBJECT(mr), "addr",
- &mr->addr, OBJ_PROP_FLAG_READ, &error_abort);
+ &mr->addr, OBJ_PROP_FLAG_READ);
object_property_add(OBJECT(mr), "priority", "uint32",
memory_region_get_priority,
NULL, /* memory_region_set_priority */
- NULL, NULL, &error_abort);
+ NULL, NULL);
object_property_add(OBJECT(mr), "size", "uint64",
memory_region_get_size,
NULL, /* memory_region_set_size, */
- NULL, NULL, &error_abort);
+ NULL, NULL);
}
static void iommu_memory_region_initfn(Object *obj)
@@ -2845,7 +2845,7 @@
if (dev && dev->id) {
qemu_printf(" id=%s", dev->id);
} else {
- gchar *canonical_path = object_get_canonical_path(obj);
+ char *canonical_path = object_get_canonical_path(obj);
if (canonical_path) {
qemu_printf(" path=%s", canonical_path);
g_free(canonical_path);
diff --git a/migration/block-dirty-bitmap.c b/migration/block-dirty-bitmap.c
index 7eaffac..47bc0f6 100644
--- a/migration/block-dirty-bitmap.c
+++ b/migration/block-dirty-bitmap.c
@@ -268,57 +268,118 @@
}
/* Called with iothread lock taken. */
-static int init_dirty_bitmap_migration(void)
+static int add_bitmaps_to_list(BlockDriverState *bs, const char *bs_name)
{
- BlockDriverState *bs;
BdrvDirtyBitmap *bitmap;
DirtyBitmapMigBitmapState *dbms;
Error *local_err = NULL;
+ bitmap = bdrv_dirty_bitmap_first(bs);
+ if (!bitmap) {
+ return 0;
+ }
+
+ if (!bs_name || strcmp(bs_name, "") == 0) {
+ error_report("Bitmap '%s' in unnamed node can't be migrated",
+ bdrv_dirty_bitmap_name(bitmap));
+ return -1;
+ }
+
+ if (bs_name[0] == '#') {
+ error_report("Bitmap '%s' in a node with auto-generated "
+ "name '%s' can't be migrated",
+ bdrv_dirty_bitmap_name(bitmap), bs_name);
+ return -1;
+ }
+
+ FOR_EACH_DIRTY_BITMAP(bs, bitmap) {
+ if (!bdrv_dirty_bitmap_name(bitmap)) {
+ continue;
+ }
+
+ if (bdrv_dirty_bitmap_check(bitmap, BDRV_BITMAP_DEFAULT, &local_err)) {
+ error_report_err(local_err);
+ return -1;
+ }
+
+ bdrv_ref(bs);
+ bdrv_dirty_bitmap_set_busy(bitmap, true);
+
+ dbms = g_new0(DirtyBitmapMigBitmapState, 1);
+ dbms->bs = bs;
+ dbms->node_name = bs_name;
+ dbms->bitmap = bitmap;
+ dbms->total_sectors = bdrv_nb_sectors(bs);
+ dbms->sectors_per_chunk = CHUNK_SIZE * 8 *
+ bdrv_dirty_bitmap_granularity(bitmap) >> BDRV_SECTOR_BITS;
+ if (bdrv_dirty_bitmap_enabled(bitmap)) {
+ dbms->flags |= DIRTY_BITMAP_MIG_START_FLAG_ENABLED;
+ }
+ if (bdrv_dirty_bitmap_get_persistence(bitmap)) {
+ dbms->flags |= DIRTY_BITMAP_MIG_START_FLAG_PERSISTENT;
+ }
+
+ QSIMPLEQ_INSERT_TAIL(&dirty_bitmap_mig_state.dbms_list,
+ dbms, entry);
+ }
+
+ return 0;
+}
+
+/* Called with iothread lock taken. */
+static int init_dirty_bitmap_migration(void)
+{
+ BlockDriverState *bs;
+ DirtyBitmapMigBitmapState *dbms;
+ GHashTable *handled_by_blk = g_hash_table_new(NULL, NULL);
+ BlockBackend *blk;
+
dirty_bitmap_mig_state.bulk_completed = false;
dirty_bitmap_mig_state.prev_bs = NULL;
dirty_bitmap_mig_state.prev_bitmap = NULL;
dirty_bitmap_mig_state.no_bitmaps = false;
+ /*
+ * Use blockdevice name for direct (or filtered) children of named block
+ * backends.
+ */
+ for (blk = blk_next(NULL); blk; blk = blk_next(blk)) {
+ const char *name = blk_name(blk);
+
+ if (!name || strcmp(name, "") == 0) {
+ continue;
+ }
+
+ bs = blk_bs(blk);
+
+ /* Skip filters without bitmaps */
+ while (bs && bs->drv && bs->drv->is_filter &&
+ !bdrv_has_named_bitmaps(bs))
+ {
+ if (bs->backing) {
+ bs = bs->backing->bs;
+ } else if (bs->file) {
+ bs = bs->file->bs;
+ } else {
+ bs = NULL;
+ }
+ }
+
+ if (bs && bs->drv && !bs->drv->is_filter) {
+ if (add_bitmaps_to_list(bs, name)) {
+ goto fail;
+ }
+ g_hash_table_add(handled_by_blk, bs);
+ }
+ }
+
for (bs = bdrv_next_all_states(NULL); bs; bs = bdrv_next_all_states(bs)) {
- const char *name = bdrv_get_device_or_node_name(bs);
+ if (g_hash_table_contains(handled_by_blk, bs)) {
+ continue;
+ }
- FOR_EACH_DIRTY_BITMAP(bs, bitmap) {
- if (!bdrv_dirty_bitmap_name(bitmap)) {
- continue;
- }
-
- if (!name || strcmp(name, "") == 0) {
- error_report("Found bitmap '%s' in unnamed node %p. It can't "
- "be migrated", bdrv_dirty_bitmap_name(bitmap), bs);
- goto fail;
- }
-
- if (bdrv_dirty_bitmap_check(bitmap, BDRV_BITMAP_DEFAULT,
- &local_err)) {
- error_report_err(local_err);
- goto fail;
- }
-
- bdrv_ref(bs);
- bdrv_dirty_bitmap_set_busy(bitmap, true);
-
- dbms = g_new0(DirtyBitmapMigBitmapState, 1);
- dbms->bs = bs;
- dbms->node_name = name;
- dbms->bitmap = bitmap;
- dbms->total_sectors = bdrv_nb_sectors(bs);
- dbms->sectors_per_chunk = CHUNK_SIZE * 8 *
- bdrv_dirty_bitmap_granularity(bitmap) >> BDRV_SECTOR_BITS;
- if (bdrv_dirty_bitmap_enabled(bitmap)) {
- dbms->flags |= DIRTY_BITMAP_MIG_START_FLAG_ENABLED;
- }
- if (bdrv_dirty_bitmap_get_persistence(bitmap)) {
- dbms->flags |= DIRTY_BITMAP_MIG_START_FLAG_PERSISTENT;
- }
-
- QSIMPLEQ_INSERT_TAIL(&dirty_bitmap_mig_state.dbms_list,
- dbms, entry);
+ if (add_bitmaps_to_list(bs, bdrv_get_node_name(bs))) {
+ goto fail;
}
}
@@ -331,9 +392,12 @@
dirty_bitmap_mig_state.no_bitmaps = true;
}
+ g_hash_table_destroy(handled_by_blk);
+
return 0;
fail:
+ g_hash_table_destroy(handled_by_blk);
dirty_bitmap_mig_cleanup();
return -1;
diff --git a/migration/colo.c b/migration/colo.c
index d015d4f..ea7d1e9 100644
--- a/migration/colo.c
+++ b/migration/colo.c
@@ -436,11 +436,6 @@
goto out;
}
- colo_notify_compares_event(NULL, COLO_EVENT_CHECKPOINT, &local_err);
- if (local_err) {
- goto out;
- }
-
/* Disable block migration */
migrate_set_block_enabled(false, &local_err);
if (local_err) {
@@ -502,6 +497,12 @@
goto out;
}
+ qemu_event_reset(&s->colo_checkpoint_event);
+ colo_notify_compares_event(NULL, COLO_EVENT_CHECKPOINT, &local_err);
+ if (local_err) {
+ goto out;
+ }
+
colo_receive_check_message(s->rp_state.from_dst_file,
COLO_MESSAGE_VMSTATE_LOADED, &local_err);
if (local_err) {
@@ -589,7 +590,7 @@
goto out;
}
- qemu_sem_wait(&s->colo_checkpoint_sem);
+ qemu_event_wait(&s->colo_checkpoint_event);
if (s->state != MIGRATION_STATUS_COLO) {
goto out;
@@ -637,7 +638,7 @@
colo_compare_unregister_notifier(&packets_compare_notifier);
timer_del(s->colo_delay_timer);
timer_free(s->colo_delay_timer);
- qemu_sem_destroy(&s->colo_checkpoint_sem);
+ qemu_event_destroy(&s->colo_checkpoint_event);
/*
* Must be called after failover BH is completed,
@@ -654,7 +655,7 @@
MigrationState *s = opaque;
int64_t next_notify_time;
- qemu_sem_post(&s->colo_checkpoint_sem);
+ qemu_event_set(&s->colo_checkpoint_event);
s->colo_checkpoint_time = qemu_clock_get_ms(QEMU_CLOCK_HOST);
next_notify_time = s->colo_checkpoint_time +
s->parameters.x_checkpoint_delay;
@@ -664,7 +665,7 @@
void migrate_start_colo_process(MigrationState *s)
{
qemu_mutex_unlock_iothread();
- qemu_sem_init(&s->colo_checkpoint_sem, 0);
+ qemu_event_init(&s->colo_checkpoint_event, false);
s->colo_delay_timer = timer_new_ms(QEMU_CLOCK_HOST,
colo_checkpoint_notify, s);
@@ -704,7 +705,7 @@
}
qemu_mutex_lock_iothread();
- cpu_synchronize_all_pre_loadvm();
+ cpu_synchronize_all_states();
ret = qemu_loadvm_state_main(mis->from_src_file, mis);
qemu_mutex_unlock_iothread();
@@ -747,9 +748,11 @@
qemu_mutex_lock_iothread();
vmstate_loading = true;
+ colo_flush_ram_cache();
ret = qemu_load_device_state(fb);
if (ret < 0) {
error_setg(errp, "COLO: load device state failed");
+ vmstate_loading = false;
qemu_mutex_unlock_iothread();
return;
}
@@ -758,6 +761,7 @@
replication_get_error_all(&local_err);
if (local_err) {
error_propagate(errp, local_err);
+ vmstate_loading = false;
qemu_mutex_unlock_iothread();
return;
}
@@ -766,6 +770,7 @@
replication_do_checkpoint_all(&local_err);
if (local_err) {
error_propagate(errp, local_err);
+ vmstate_loading = false;
qemu_mutex_unlock_iothread();
return;
}
@@ -777,6 +782,7 @@
if (local_err) {
error_propagate(errp, local_err);
+ vmstate_loading = false;
qemu_mutex_unlock_iothread();
return;
}
@@ -787,9 +793,6 @@
qemu_mutex_unlock_iothread();
if (failover_get_state() == FAILOVER_STATUS_RELAUNCH) {
- failover_set_state(FAILOVER_STATUS_RELAUNCH,
- FAILOVER_STATUS_NONE);
- failover_request_active(NULL);
return;
}
@@ -888,6 +891,14 @@
error_report_err(local_err);
break;
}
+
+ if (failover_get_state() == FAILOVER_STATUS_RELAUNCH) {
+ failover_set_state(FAILOVER_STATUS_RELAUNCH,
+ FAILOVER_STATUS_NONE);
+ failover_request_active(NULL);
+ break;
+ }
+
if (failover_get_state() != FAILOVER_STATUS_NONE) {
error_report("failover request");
break;
@@ -895,8 +906,6 @@
}
out:
- vmstate_loading = false;
-
/*
* There are only two reasons we can get here, some error happened
* or the user triggered failover.
diff --git a/migration/migration.c b/migration/migration.c
index 0bb042a..b63ad91 100644
--- a/migration/migration.c
+++ b/migration/migration.c
@@ -3361,6 +3361,10 @@
bool urgent = false;
migration_update_counters(s, now);
if (qemu_file_rate_limit(s->to_dst_file)) {
+
+ if (qemu_file_get_error(s->to_dst_file)) {
+ return false;
+ }
/*
* Wait for a delay to do rate limiting OR
* something urgent to post the semaphore.
diff --git a/migration/migration.h b/migration/migration.h
index 507284e..f617960 100644
--- a/migration/migration.h
+++ b/migration/migration.h
@@ -215,8 +215,8 @@
/* The semaphore is used to notify COLO thread that failover is finished */
QemuSemaphore colo_exit_sem;
- /* The semaphore is used to notify COLO thread to do checkpoint */
- QemuSemaphore colo_checkpoint_sem;
+ /* The event is used to notify COLO thread to do checkpoint */
+ QemuEvent colo_checkpoint_event;
int64_t colo_checkpoint_time;
QEMUTimer *colo_delay_timer;
diff --git a/migration/ram.c b/migration/ram.c
index 859f835..41cc530 100644
--- a/migration/ram.c
+++ b/migration/ram.c
@@ -3360,7 +3360,7 @@
* Flush content of RAM cache into SVM's memory.
* Only flush the pages that be dirtied by PVM or SVM or both.
*/
-static void colo_flush_ram_cache(void)
+void colo_flush_ram_cache(void)
{
RAMBlock *block = NULL;
void *dst_host;
@@ -3632,9 +3632,6 @@
}
trace_ram_load_complete(ret, seq_iter);
- if (!ret && migration_incoming_in_colo_state()) {
- colo_flush_ram_cache();
- }
return ret;
}
diff --git a/migration/ram.h b/migration/ram.h
index 5ceaff7..2eeaacf 100644
--- a/migration/ram.h
+++ b/migration/ram.h
@@ -65,6 +65,7 @@
/* ram cache */
int colo_init_ram_cache(void);
+void colo_flush_ram_cache(void);
void colo_release_ram_cache(void);
void colo_incoming_start_dirty_log(void);
diff --git a/migration/rdma.c b/migration/rdma.c
index 967fda5..ec45d33 100644
--- a/migration/rdma.c
+++ b/migration/rdma.c
@@ -4056,7 +4056,9 @@
return;
err:
error_propagate(errp, local_err);
- g_free(rdma->host);
+ if (rdma) {
+ g_free(rdma->host);
+ }
g_free(rdma);
g_free(rdma_return_path);
}
@@ -4092,20 +4094,20 @@
rdma_return_path = qemu_rdma_data_init(host_port, errp);
if (rdma_return_path == NULL) {
- goto err;
+ goto return_path_err;
}
ret = qemu_rdma_source_init(rdma_return_path,
s->enabled_capabilities[MIGRATION_CAPABILITY_RDMA_PIN_ALL], errp);
if (ret) {
- goto err;
+ goto return_path_err;
}
ret = qemu_rdma_connect(rdma_return_path, errp);
if (ret) {
- goto err;
+ goto return_path_err;
}
rdma->return_path = rdma_return_path;
@@ -4118,6 +4120,8 @@
s->to_dst_file = qemu_fopen_rdma(rdma, "wb");
migrate_fd_connect(s, NULL);
return;
+return_path_err:
+ qemu_rdma_cleanup(rdma);
err:
g_free(rdma);
g_free(rdma_return_path);
diff --git a/monitor/misc.c b/monitor/misc.c
index 9723b46..f5207cd 100644
--- a/monitor/misc.c
+++ b/monitor/misc.c
@@ -1837,8 +1837,7 @@
static int qdev_add_hotpluggable_device(Object *obj, void *opaque)
{
GSList **list = opaque;
- DeviceState *dev = (DeviceState *)object_dynamic_cast(OBJECT(obj),
- TYPE_DEVICE);
+ DeviceState *dev = (DeviceState *)object_dynamic_cast(obj, TYPE_DEVICE);
if (dev == NULL) {
return 0;
diff --git a/monitor/monitor-internal.h b/monitor/monitor-internal.h
index 8f60ccc..b39e03b 100644
--- a/monitor/monitor-internal.h
+++ b/monitor/monitor-internal.h
@@ -91,7 +91,7 @@
bool skip_flush;
bool use_io_thread;
- gchar *mon_cpu_path;
+ char *mon_cpu_path;
QTAILQ_ENTRY(Monitor) entry;
/*
diff --git a/net/can/can_host.c b/net/can/can_host.c
index 1dfaf0c..be4547d 100644
--- a/net/can/can_host.c
+++ b/net/can/can_host.c
@@ -79,8 +79,7 @@
object_property_add_link(obj, "canbus", TYPE_CAN_BUS,
(Object **)&ch->bus,
object_property_allow_set_link,
- OBJ_PROP_LINK_STRONG,
- &error_abort);
+ OBJ_PROP_LINK_STRONG);
}
static void can_host_class_init(ObjectClass *klass,
diff --git a/net/can/can_socketcan.c b/net/can/can_socketcan.c
index 807f31f..b7ef63e 100644
--- a/net/can/can_socketcan.c
+++ b/net/can/can_socketcan.c
@@ -266,8 +266,7 @@
object_class_property_add_str(klass, "if",
can_host_socketcan_get_if,
- can_host_socketcan_set_if,
- &error_abort);
+ can_host_socketcan_set_if);
chc->connect = can_host_socketcan_connect;
chc->disconnect = can_host_socketcan_disconnect;
}
diff --git a/net/colo-compare.c b/net/colo-compare.c
index 10c0239..c07e7c1 100644
--- a/net/colo-compare.c
+++ b/net/colo-compare.c
@@ -1245,34 +1245,30 @@
CompareState *s = COLO_COMPARE(obj);
object_property_add_str(obj, "primary_in",
- compare_get_pri_indev, compare_set_pri_indev,
- NULL);
+ compare_get_pri_indev, compare_set_pri_indev);
object_property_add_str(obj, "secondary_in",
- compare_get_sec_indev, compare_set_sec_indev,
- NULL);
+ compare_get_sec_indev, compare_set_sec_indev);
object_property_add_str(obj, "outdev",
- compare_get_outdev, compare_set_outdev,
- NULL);
+ compare_get_outdev, compare_set_outdev);
object_property_add_link(obj, "iothread", TYPE_IOTHREAD,
(Object **)&s->iothread,
object_property_allow_set_link,
- OBJ_PROP_LINK_STRONG, NULL);
+ OBJ_PROP_LINK_STRONG);
/* This parameter just for Xen COLO */
object_property_add_str(obj, "notify_dev",
- compare_get_notify_dev, compare_set_notify_dev,
- NULL);
+ compare_get_notify_dev, compare_set_notify_dev);
object_property_add(obj, "compare_timeout", "uint32",
compare_get_timeout,
- compare_set_timeout, NULL, NULL, NULL);
+ compare_set_timeout, NULL, NULL);
object_property_add(obj, "expired_scan_cycle", "uint32",
compare_get_expired_scan_cycle,
- compare_set_expired_scan_cycle, NULL, NULL, NULL);
+ compare_set_expired_scan_cycle, NULL, NULL);
s->vnet_hdr = false;
object_property_add_bool(obj, "vnet_hdr_support", compare_get_vnet_hdr,
- compare_set_vnet_hdr, NULL);
+ compare_set_vnet_hdr);
}
static void colo_compare_finalize(Object *obj)
diff --git a/net/dump.c b/net/dump.c
index 23b3628..61389e7 100644
--- a/net/dump.c
+++ b/net/dump.c
@@ -232,9 +232,9 @@
nfds->maxlen = 65536;
object_property_add(obj, "maxlen", "uint32", filter_dump_get_maxlen,
- filter_dump_set_maxlen, NULL, NULL, NULL);
+ filter_dump_set_maxlen, NULL, NULL);
object_property_add_str(obj, "file", file_dump_get_filename,
- file_dump_set_filename, NULL);
+ file_dump_set_filename);
}
static void filter_dump_instance_finalize(Object *obj)
diff --git a/net/filter-buffer.c b/net/filter-buffer.c
index 12e0254..93050f8 100644
--- a/net/filter-buffer.c
+++ b/net/filter-buffer.c
@@ -192,7 +192,7 @@
{
object_property_add(obj, "interval", "uint32",
filter_buffer_get_interval,
- filter_buffer_set_interval, NULL, NULL, NULL);
+ filter_buffer_set_interval, NULL, NULL);
}
static const TypeInfo filter_buffer_info = {
diff --git a/net/filter-mirror.c b/net/filter-mirror.c
index d83e815..e9379ce 100644
--- a/net/filter-mirror.c
+++ b/net/filter-mirror.c
@@ -392,12 +392,12 @@
MirrorState *s = FILTER_MIRROR(obj);
object_property_add_str(obj, "outdev", filter_mirror_get_outdev,
- filter_mirror_set_outdev, NULL);
+ filter_mirror_set_outdev);
s->vnet_hdr = false;
object_property_add_bool(obj, "vnet_hdr_support",
filter_mirror_get_vnet_hdr,
- filter_mirror_set_vnet_hdr, NULL);
+ filter_mirror_set_vnet_hdr);
}
static void filter_redirector_init(Object *obj)
@@ -405,14 +405,14 @@
MirrorState *s = FILTER_REDIRECTOR(obj);
object_property_add_str(obj, "indev", filter_redirector_get_indev,
- filter_redirector_set_indev, NULL);
+ filter_redirector_set_indev);
object_property_add_str(obj, "outdev", filter_redirector_get_outdev,
- filter_redirector_set_outdev, NULL);
+ filter_redirector_set_outdev);
s->vnet_hdr = false;
object_property_add_bool(obj, "vnet_hdr_support",
filter_redirector_get_vnet_hdr,
- filter_redirector_set_vnet_hdr, NULL);
+ filter_redirector_set_vnet_hdr);
}
static void filter_mirror_fini(Object *obj)
diff --git a/net/filter-rewriter.c b/net/filter-rewriter.c
index 31da08a..1aaad10 100644
--- a/net/filter-rewriter.c
+++ b/net/filter-rewriter.c
@@ -413,7 +413,7 @@
s->failover_mode = FAILOVER_MODE_OFF;
object_property_add_bool(obj, "vnet_hdr_support",
filter_rewriter_get_vnet_hdr,
- filter_rewriter_set_vnet_hdr, NULL);
+ filter_rewriter_set_vnet_hdr);
}
static void colo_rewriter_class_init(ObjectClass *oc, void *data)
diff --git a/net/filter.c b/net/filter.c
index 8221666..caf6443 100644
--- a/net/filter.c
+++ b/net/filter.c
@@ -214,21 +214,16 @@
nf->position = g_strdup("tail");
object_property_add_str(obj, "netdev",
- netfilter_get_netdev_id, netfilter_set_netdev_id,
- NULL);
+ netfilter_get_netdev_id, netfilter_set_netdev_id);
object_property_add_enum(obj, "queue", "NetFilterDirection",
&NetFilterDirection_lookup,
- netfilter_get_direction, netfilter_set_direction,
- NULL);
+ netfilter_get_direction, netfilter_set_direction);
object_property_add_str(obj, "status",
- netfilter_get_status, netfilter_set_status,
- NULL);
+ netfilter_get_status, netfilter_set_status);
object_property_add_str(obj, "position",
- netfilter_get_position, netfilter_set_position,
- NULL);
+ netfilter_get_position, netfilter_set_position);
object_property_add_str(obj, "insert",
- netfilter_get_insert, netfilter_set_insert,
- NULL);
+ netfilter_get_insert, netfilter_set_insert);
}
static void netfilter_complete(UserCreatable *uc, Error **errp)
diff --git a/pc-bios/openbios-ppc b/pc-bios/openbios-ppc
index 1c9ab09..5da9363 100644
--- a/pc-bios/openbios-ppc
+++ b/pc-bios/openbios-ppc
Binary files differ
diff --git a/pc-bios/openbios-sparc32 b/pc-bios/openbios-sparc32
index 2ba8660..d68b5e5 100644
--- a/pc-bios/openbios-sparc32
+++ b/pc-bios/openbios-sparc32
Binary files differ
diff --git a/pc-bios/openbios-sparc64 b/pc-bios/openbios-sparc64
index 99420eb..26d631e 100644
--- a/pc-bios/openbios-sparc64
+++ b/pc-bios/openbios-sparc64
Binary files differ
diff --git a/plugins/api.c b/plugins/api.c
index 53c8a73..bbdc5a4 100644
--- a/plugins/api.c
+++ b/plugins/api.c
@@ -275,10 +275,10 @@
}
#endif
-bool qemu_plugin_hwaddr_is_io(struct qemu_plugin_hwaddr *hwaddr)
+bool qemu_plugin_hwaddr_is_io(const struct qemu_plugin_hwaddr *haddr)
{
#ifdef CONFIG_SOFTMMU
- return hwaddr->is_io;
+ return haddr->is_io;
#else
return false;
#endif
diff --git a/python/qemu/.flake8 b/python/qemu/.flake8
new file mode 100644
index 0000000..45d8146
--- /dev/null
+++ b/python/qemu/.flake8
@@ -0,0 +1,2 @@
+[flake8]
+extend-ignore = E722 # Pylint handles this, but smarter.
\ No newline at end of file
diff --git a/python/qemu/accel.py b/python/qemu/accel.py
index 36ae857..7fabe62 100644
--- a/python/qemu/accel.py
+++ b/python/qemu/accel.py
@@ -23,11 +23,12 @@
# Mapping host architecture to any additional architectures it can
# support which often includes its 32 bit cousin.
ADDITIONAL_ARCHES = {
- "x86_64" : "i386",
- "aarch64" : "armhf",
- "ppc64le" : "ppc64",
+ "x86_64": "i386",
+ "aarch64": "armhf",
+ "ppc64le": "ppc64",
}
+
def list_accel(qemu_bin):
"""
List accelerators enabled in the QEMU binary.
@@ -47,6 +48,7 @@
# Skip the first line which is the header.
return [acc.strip() for acc in out.splitlines()[1:]]
+
def kvm_available(target_arch=None, qemu_bin=None):
"""
Check if KVM is available using the following heuristic:
@@ -69,6 +71,7 @@
return False
return True
+
def tcg_available(qemu_bin):
"""
Check if TCG is available.
diff --git a/python/qemu/machine.py b/python/qemu/machine.py
index b9a98e2..041c615 100644
--- a/python/qemu/machine.py
+++ b/python/qemu/machine.py
@@ -24,11 +24,14 @@
import shutil
import socket
import tempfile
+from typing import Optional, Type
+from types import TracebackType
from . import qmp
LOG = logging.getLogger(__name__)
+
class QEMUMachineError(Exception):
"""
Exception called when an error in QEMUMachine happens.
@@ -54,15 +57,16 @@
desc = reply["error"]["desc"]
except KeyError:
desc = reply
- super(MonitorResponseError, self).__init__(desc)
+ super().__init__(desc)
self.reply = reply
-class QEMUMachine(object):
+class QEMUMachine:
"""
A QEMU VM
- Use this object as a context manager to ensure the QEMU process terminates::
+ Use this object as a context manager to ensure
+ the QEMU process terminates::
with VM(binary) as vm:
...
@@ -119,15 +123,14 @@
self._console_socket = None
self._remove_files = []
- # just in case logging wasn't configured by the main script:
- logging.basicConfig()
-
def __enter__(self):
return self
- def __exit__(self, exc_type, exc_val, exc_tb):
+ def __exit__(self,
+ exc_type: Optional[Type[BaseException]],
+ exc_val: Optional[BaseException],
+ exc_tb: Optional[TracebackType]) -> None:
self.shutdown()
- return False
def add_monitor_null(self):
"""
@@ -188,8 +191,10 @@
fd_param.append(str(fd))
devnull = open(os.path.devnull, 'rb')
- proc = subprocess.Popen(fd_param, stdin=devnull, stdout=subprocess.PIPE,
- stderr=subprocess.STDOUT, close_fds=False)
+ proc = subprocess.Popen(
+ fd_param, stdin=devnull, stdout=subprocess.PIPE,
+ stderr=subprocess.STDOUT, close_fds=False
+ )
output = proc.communicate()[0]
if output:
LOG.debug(output)
@@ -242,7 +247,7 @@
'chardev=mon,mode=control'])
if self._machine is not None:
args.extend(['-machine', self._machine])
- for i in range(self._console_index):
+ for _ in range(self._console_index):
args.extend(['-serial', 'null'])
if self._console_set:
self._console_address = os.path.join(self._sock_dir,
@@ -342,7 +347,7 @@
self._load_io_log()
self._post_shutdown()
- def shutdown(self, has_quit=False):
+ def shutdown(self, has_quit=False, hard=False):
"""
Terminate the VM and clean up
"""
@@ -354,7 +359,9 @@
self._console_socket = None
if self.is_running():
- if self._qmp:
+ if hard:
+ self._popen.kill()
+ elif self._qmp:
try:
if not has_quit:
self._qmp.cmd('quit')
@@ -368,16 +375,20 @@
self._post_shutdown()
exitcode = self.exitcode()
- if exitcode is not None and exitcode < 0:
+ if exitcode is not None and exitcode < 0 and \
+ not (exitcode == -9 and hard):
msg = 'qemu received signal %i: %s'
if self._qemu_full_args:
command = ' '.join(self._qemu_full_args)
else:
command = ''
- LOG.warning(msg, -exitcode, command)
+ LOG.warning(msg, -int(exitcode), command)
self._launched = False
+ def kill(self):
+ self.shutdown(hard=True)
+
def set_qmp_monitor(self, enabled=True):
"""
Set the QMP monitor.
@@ -482,7 +493,8 @@
def events_wait(self, events, timeout=60.0):
"""
- events_wait waits for and returns a named event from QMP with a timeout.
+ events_wait waits for and returns a named event
+ from QMP with a timeout.
events: a sequence of (name, match_criteria) tuples.
The match criteria are optional and may be None.
diff --git a/python/qemu/pylintrc b/python/qemu/pylintrc
new file mode 100644
index 0000000..5d6ae73
--- /dev/null
+++ b/python/qemu/pylintrc
@@ -0,0 +1,58 @@
+[MASTER]
+
+[MESSAGES CONTROL]
+
+# Disable the message, report, category or checker with the given id(s). You
+# can either give multiple identifiers separated by comma (,) or put this
+# option multiple times (only on the command line, not in the configuration
+# file where it should appear only once). You can also use "--disable=all" to
+# disable everything first and then reenable specific checks. For example, if
+# you want to run only the similarities checker, you can use "--disable=all
+# --enable=similarities". If you want to run only the classes checker, but have
+# no Warning level messages displayed, use "--disable=all --enable=classes
+# --disable=W".
+disable=too-many-arguments,
+ too-many-instance-attributes,
+ too-many-public-methods,
+
+[REPORTS]
+
+[REFACTORING]
+
+[MISCELLANEOUS]
+
+[LOGGING]
+
+[BASIC]
+
+# Good variable names which should always be accepted, separated by a comma.
+good-names=i,
+ j,
+ k,
+ ex,
+ Run,
+ _,
+ fd,
+
+[VARIABLES]
+
+[STRING]
+
+[SPELLING]
+
+[FORMAT]
+
+[SIMILARITIES]
+
+# Ignore imports when computing similarities.
+ignore-imports=yes
+
+[TYPECHECK]
+
+[CLASSES]
+
+[IMPORTS]
+
+[DESIGN]
+
+[EXCEPTIONS]
diff --git a/python/qemu/qmp.py b/python/qemu/qmp.py
index d6c9b2f..e64b6b5 100644
--- a/python/qemu/qmp.py
+++ b/python/qemu/qmp.py
@@ -11,6 +11,12 @@
import errno
import socket
import logging
+from typing import (
+ Optional,
+ TextIO,
+ Type,
+)
+from types import TracebackType
class QMPError(Exception):
@@ -61,7 +67,7 @@
self.__events = []
self.__address = address
self.__sock = self.__get_sock()
- self.__sockfile = None
+ self.__sockfile: Optional[TextIO] = None
self._nickname = nickname
if self._nickname:
self.logger = logging.getLogger('QMP').getChild(self._nickname)
@@ -88,6 +94,7 @@
raise QMPCapabilitiesError
def __json_read(self, only_event=False):
+ assert self.__sockfile is not None
while True:
data = self.__sockfile.readline()
if not data:
@@ -114,14 +121,14 @@
"""
# Check for new events regardless and pull them into the cache:
- self.__sock.setblocking(0)
+ self.__sock.setblocking(False)
try:
self.__json_read()
except OSError as err:
if err.errno == errno.EAGAIN:
# No data available
pass
- self.__sock.setblocking(1)
+ self.__sock.setblocking(True)
# Wait for new events, if needed.
# if wait is 0.0, this means "no wait" and is also implicitly false.
@@ -142,10 +149,14 @@
# Implement context manager enter function.
return self
- def __exit__(self, exc_type, exc_value, exc_traceback):
+ def __exit__(self,
+ # pylint: disable=duplicate-code
+ # see https://github.com/PyCQA/pylint/issues/3619
+ exc_type: Optional[Type[BaseException]],
+ exc_val: Optional[BaseException],
+ exc_tb: Optional[TracebackType]) -> None:
# Implement context manager exit function.
self.close()
- return False
def connect(self, negotiate=True):
"""
@@ -157,7 +168,7 @@
@raise QMPCapabilitiesError if fails to negotiate capabilities
"""
self.__sock.connect(self.__address)
- self.__sockfile = self.__sock.makefile()
+ self.__sockfile = self.__sock.makefile(mode='r')
if negotiate:
return self.__negotiate_capabilities()
return None
@@ -168,8 +179,8 @@
@param timeout: timeout in seconds (nonnegative float number, or
None). The value passed will set the behavior of the
- underneath QMP socket as described in [1]. Default value
- is set to 15.0.
+ underneath QMP socket as described in [1].
+ Default value is set to 15.0.
@return QMP greeting dict
@raise OSError on socket connection errors
@raise QMPConnectError if the greeting is not received
@@ -180,7 +191,7 @@
"""
self.__sock.settimeout(timeout)
self.__sock, _ = self.__sock.accept()
- self.__sockfile = self.__sock.makefile()
+ self.__sockfile = self.__sock.makefile(mode='r')
return self.__negotiate_capabilities()
def cmd_obj(self, qmp_cmd):
diff --git a/python/qemu/qtest.py b/python/qemu/qtest.py
index d24ad04..888c8bd 100644
--- a/python/qemu/qtest.py
+++ b/python/qemu/qtest.py
@@ -1,5 +1,11 @@
-# QEMU qtest library
-#
+"""
+QEMU qtest library
+
+qtest offers the QEMUQtestProtocol and QEMUQTestMachine classes, which
+offer a connection to QEMU's qtest protocol socket, and a qtest-enabled
+subclass of QEMUMachine, respectively.
+"""
+
# Copyright (C) 2015 Red Hat Inc.
#
# Authors:
@@ -13,26 +19,29 @@
import socket
import os
+from typing import Optional, TextIO
from .machine import QEMUMachine
-class QEMUQtestProtocol(object):
- def __init__(self, address, server=False):
- """
- Create a QEMUQtestProtocol object.
+class QEMUQtestProtocol:
+ """
+ QEMUQtestProtocol implements a connection to a qtest socket.
- @param address: QEMU address, can be either a unix socket path (string)
- or a tuple in the form ( address, port ) for a TCP
- connection
- @param server: server mode, listens on the socket (bool)
- @raise socket.error on socket connection errors
- @note No connection is established, this is done by the connect() or
- accept() methods
- """
+ :param address: QEMU address, can be either a unix socket path (string)
+ or a tuple in the form ( address, port ) for a TCP
+ connection
+ :param server: server mode, listens on the socket (bool)
+ :raise socket.error: on socket connection errors
+
+ .. note::
+ No conection is estabalished by __init__(), this is done
+ by the connect() or accept() methods.
+ """
+ def __init__(self, address, server=False):
self._address = address
self._sock = self._get_sock()
- self._sockfile = None
+ self._sockfile: Optional[TextIO] = None
if server:
self._sock.bind(self._address)
self._sock.listen(1)
@@ -51,7 +60,7 @@
@raise socket.error on socket connection errors
"""
self._sock.connect(self._address)
- self._sockfile = self._sock.makefile()
+ self._sockfile = self._sock.makefile(mode='r')
def accept(self):
"""
@@ -60,7 +69,7 @@
@raise socket.error on socket connection errors
"""
self._sock, _ = self._sock.accept()
- self._sockfile = self._sock.makefile()
+ self._sockfile = self._sock.makefile(mode='r')
def cmd(self, qtest_cmd):
"""
@@ -68,20 +77,27 @@
@param qtest_cmd: qtest command text to be sent
"""
+ assert self._sockfile is not None
self._sock.sendall((qtest_cmd + "\n").encode('utf-8'))
resp = self._sockfile.readline()
return resp
def close(self):
+ """Close this socket."""
self._sock.close()
- self._sockfile.close()
+ if self._sockfile:
+ self._sockfile.close()
+ self._sockfile = None
def settimeout(self, timeout):
+ """Set a timeout, in seconds."""
self._sock.settimeout(timeout)
class QEMUQtestMachine(QEMUMachine):
- '''A QEMU VM'''
+ """
+ A QEMU VM, with a qtest socket available.
+ """
def __init__(self, binary, args=None, name=None, test_dir="/var/tmp",
socket_scm_helper=None, sock_dir=None):
@@ -89,31 +105,38 @@
name = "qemu-%d" % os.getpid()
if sock_dir is None:
sock_dir = test_dir
- super(QEMUQtestMachine,
- self).__init__(binary, args, name=name, test_dir=test_dir,
- socket_scm_helper=socket_scm_helper,
- sock_dir=sock_dir)
+ super().__init__(binary, args, name=name, test_dir=test_dir,
+ socket_scm_helper=socket_scm_helper,
+ sock_dir=sock_dir)
self._qtest = None
self._qtest_path = os.path.join(sock_dir, name + "-qtest.sock")
def _base_args(self):
- args = super(QEMUQtestMachine, self)._base_args()
+ args = super()._base_args()
args.extend(['-qtest', 'unix:path=' + self._qtest_path,
'-accel', 'qtest'])
return args
def _pre_launch(self):
- super(QEMUQtestMachine, self)._pre_launch()
+ super()._pre_launch()
self._qtest = QEMUQtestProtocol(self._qtest_path, server=True)
- def _post_launch(self):
- super(QEMUQtestMachine, self)._post_launch()
+ def _post_launch(self) -> None:
+ assert self._qtest is not None
+ super()._post_launch()
self._qtest.accept()
def _post_shutdown(self):
- super(QEMUQtestMachine, self)._post_shutdown()
+ super()._post_shutdown()
self._remove_if_exists(self._qtest_path)
- def qtest(self, cmd):
- '''Send a qtest command to guest'''
+ def qtest(self, cmd: str) -> str:
+ """
+ Send a qtest command to the guest.
+
+ :param cmd: qtest command to send
+ :return: qtest server response
+ """
+ if self._qtest is None:
+ raise RuntimeError("qtest socket not available")
return self._qtest.cmd(cmd)
diff --git a/qapi/audio.json b/qapi/audio.json
index c31251f..f62bd0d 100644
--- a/qapi/audio.json
+++ b/qapi/audio.json
@@ -153,6 +153,55 @@
'*latency': 'uint32' } }
##
+# @AudiodevJackPerDirectionOptions:
+#
+# Options of the JACK backend that are used for both playback and
+# recording.
+#
+# @server-name: select from among several possible concurrent server instances
+# (default: environment variable $JACK_DEFAULT_SERVER if set, else "default")
+#
+# @client-name: the client name to use. The server will modify this name to
+# create a unique variant, if needed unless @exact-name is true (default: the
+# guest's name)
+#
+# @connect-ports: if set, a regular expression of JACK client port name(s) to
+# monitor for and automatically connect to
+#
+# @start-server: start a jack server process if one is not already present
+# (default: false)
+#
+# @exact-name: use the exact name requested otherwise JACK automatically
+# generates a unique one, if needed (default: false)
+#
+# Since: 5.1
+##
+{ 'struct': 'AudiodevJackPerDirectionOptions',
+ 'base': 'AudiodevPerDirectionOptions',
+ 'data': {
+ '*server-name': 'str',
+ '*client-name': 'str',
+ '*connect-ports': 'str',
+ '*start-server': 'bool',
+ '*exact-name': 'bool' } }
+
+##
+# @AudiodevJackOptions:
+#
+# Options of the JACK audio backend.
+#
+# @in: options of the capture stream
+#
+# @out: options of the playback stream
+#
+# Since: 5.1
+##
+{ 'struct': 'AudiodevJackOptions',
+ 'data': {
+ '*in': 'AudiodevJackPerDirectionOptions',
+ '*out': 'AudiodevJackPerDirectionOptions' } }
+
+##
# @AudiodevOssPerDirectionOptions:
#
# Options of the OSS backend that are used for both playback and
@@ -297,11 +346,13 @@
#
# An enumeration of possible audio backend drivers.
#
+# @jack: JACK audio backend (since 5.1)
+#
# Since: 4.0
##
{ 'enum': 'AudiodevDriver',
- 'data': [ 'none', 'alsa', 'coreaudio', 'dsound', 'oss', 'pa', 'sdl',
- 'spice', 'wav' ] }
+ 'data': [ 'none', 'alsa', 'coreaudio', 'dsound', 'jack', 'oss', 'pa',
+ 'sdl', 'spice', 'wav' ] }
##
# @Audiodev:
@@ -327,6 +378,7 @@
'alsa': 'AudiodevAlsaOptions',
'coreaudio': 'AudiodevCoreaudioOptions',
'dsound': 'AudiodevDsoundOptions',
+ 'jack': 'AudiodevJackOptions',
'oss': 'AudiodevOssOptions',
'pa': 'AudiodevPaOptions',
'sdl': 'AudiodevGenericOptions',
diff --git a/qapi/block-core.json b/qapi/block-core.json
index 943df19..0e1c6a5 100644
--- a/qapi/block-core.json
+++ b/qapi/block-core.json
@@ -78,6 +78,8 @@
#
# @bitmaps: A list of qcow2 bitmap details (since 4.0)
#
+# @compression-type: the image cluster compression method (since 5.1)
+#
# Since: 1.7
##
{ 'struct': 'ImageInfoSpecificQCow2',
@@ -89,7 +91,8 @@
'*corrupt': 'bool',
'refcount-bits': 'int',
'*encrypt': 'ImageInfoSpecificQCow2Encryption',
- '*bitmaps': ['Qcow2BitmapInfo']
+ '*bitmaps': ['Qcow2BitmapInfo'],
+ 'compression-type': 'Qcow2CompressionType'
} }
##
@@ -633,18 +636,24 @@
# efficiently so file size may be smaller than virtual disk size.
#
# The values are upper bounds that are guaranteed to fit the new image file.
-# Subsequent modification, such as internal snapshot or bitmap creation, may
-# require additional space and is not covered here.
+# Subsequent modification, such as internal snapshot or further bitmap
+# creation, may require additional space and is not covered here.
#
-# @required: Size required for a new image file, in bytes.
+# @required: Size required for a new image file, in bytes, when copying just
+# allocated guest-visible contents.
#
# @fully-allocated: Image file size, in bytes, once data has been written
-# to all sectors.
+# to all sectors, when copying just guest-visible contents.
+#
+# @bitmaps: Additional size required if all the top-level bitmap metadata
+# in the source image were to be copied to the destination,
+# present only when source and destination both support
+# persistent bitmaps. (since 5.1)
#
# Since: 2.10
##
{ 'struct': 'BlockMeasureInfo',
- 'data': {'required': 'int', 'fully-allocated': 'int'} }
+ 'data': {'required': 'int', 'fully-allocated': 'int', '*bitmaps': 'int'} }
##
# @query-block:
@@ -4285,6 +4294,19 @@
##
+# @Qcow2CompressionType:
+#
+# Compression type used in qcow2 image file
+#
+# @zlib: zlib compression, see <http://zlib.net/>
+# @zstd: zstd compression, see <http://github.com/facebook/zstd>
+#
+# Since: 5.1
+##
+{ 'enum': 'Qcow2CompressionType',
+ 'data': [ 'zlib', { 'name': 'zstd', 'if': 'defined(CONFIG_ZSTD)' } ] }
+
+##
# @BlockdevCreateOptionsQcow2:
#
# Driver specific image creation options for qcow2.
@@ -4307,6 +4329,8 @@
# allowed values: off, falloc, full, metadata)
# @lazy-refcounts: True if refcounts may be updated lazily (default: off)
# @refcount-bits: Width of reference counts in bits (default: 16)
+# @compression-type: The image cluster compression method
+# (default: zlib, since 5.1)
#
# Since: 2.12
##
@@ -4322,7 +4346,8 @@
'*cluster-size': 'size',
'*preallocation': 'PreallocMode',
'*lazy-refcounts': 'bool',
- '*refcount-bits': 'int' } }
+ '*refcount-bits': 'int',
+ '*compression-type':'Qcow2CompressionType' } }
##
# @BlockdevCreateOptionsQed:
diff --git a/qapi/sockets.json b/qapi/sockets.json
index ea933ed..cbd6ef3 100644
--- a/qapi/sockets.json
+++ b/qapi/sockets.json
@@ -73,12 +73,18 @@
# Captures a socket address in the local ("Unix socket") namespace.
#
# @path: filesystem path to use
+# @tight: pass a socket address length confined to the minimum length of the
+# abstract string, rather than the full sockaddr_un record length
+# (only matters for abstract sockets, default true). (Since 5.1)
+# @abstract: whether this is an abstract address, default false. (Since 5.1)
#
# Since: 1.3
##
{ 'struct': 'UnixSocketAddress',
'data': {
- 'path': 'str' } }
+ 'path': 'str',
+ '*tight': 'bool',
+ '*abstract': 'bool' } }
##
# @VsockSocketAddress:
diff --git a/qdev-monitor.c b/qdev-monitor.c
index 56cee14..a4735d3 100644
--- a/qdev-monitor.c
+++ b/qdev-monitor.c
@@ -562,12 +562,12 @@
if (dev->id) {
object_property_add_child(qdev_get_peripheral(), dev->id,
- OBJECT(dev), NULL);
+ OBJECT(dev));
} else {
static int anon_count;
gchar *name = g_strdup_printf("device[%d]", anon_count++);
object_property_add_child(qdev_get_peripheral_anon(), name,
- OBJECT(dev), NULL);
+ OBJECT(dev));
g_free(name);
}
}
diff --git a/qemu-img-cmds.hx b/qemu-img-cmds.hx
index c9c54de..10b910b 100644
--- a/qemu-img-cmds.hx
+++ b/qemu-img-cmds.hx
@@ -7,7 +7,7 @@
HXCOMM HXCOMM can be used for comments, discarded from both rST and C
HXCOMM When amending the rST sections, please remember to copy the usage
-HXCOMM over to the per-command sections in qemu-img.texi.
+HXCOMM over to the per-command sections in docs/tools/qemu-img.rst.
DEF("amend", img_amend,
"amend [--object objectdef] [--image-opts] [-p] [-q] [-f fmt] [-t cache] -o options filename")
@@ -20,6 +20,13 @@
SRST
.. option:: bench [-c COUNT] [-d DEPTH] [-f FMT] [--flush-interval=FLUSH_INTERVAL] [-i AIO] [-n] [--no-drain] [-o OFFSET] [--pattern=PATTERN] [-q] [-s BUFFER_SIZE] [-S STEP_SIZE] [-t CACHE] [-w] [-U] FILENAME
ERST
+
+DEF("bitmap", img_bitmap,
+ "bitmap (--merge SOURCE | --add | --remove | --clear | --enable | --disable)... [-b source_file [-F source_fmt]] [-g granularity] [--object objectdef] [--image-opts | -f fmt] filename bitmap")
+SRST
+.. option:: bitmap (--merge SOURCE | --add | --remove | --clear | --enable | --disable)... [-b SOURCE_FILE [-F SOURCE_FMT]] [-g GRANULARITY] [--object OBJECTDEF] [--image-opts | -f FMT] FILENAME BITMAP
+ERST
+
DEF("check", img_check,
"check [--object objectdef] [--image-opts] [-q] [-f fmt] [--output=ofmt] [-r [leaks | all]] [-T src_cache] [-U] filename")
SRST
@@ -39,9 +46,9 @@
ERST
DEF("convert", img_convert,
- "convert [--object objectdef] [--image-opts] [--target-image-opts] [--target-is-zero] [-U] [-C] [-c] [-p] [-q] [-n] [-f fmt] [-t cache] [-T src_cache] [-O output_fmt] [-B backing_file] [-o options] [-l snapshot_param] [-S sparse_size] [-m num_coroutines] [-W] [--salvage] filename [filename2 [...]] output_filename")
+ "convert [--object objectdef] [--image-opts] [--target-image-opts] [--target-is-zero] [--bitmaps] [-U] [-C] [-c] [-p] [-q] [-n] [-f fmt] [-t cache] [-T src_cache] [-O output_fmt] [-B backing_file] [-o options] [-l snapshot_param] [-S sparse_size] [-m num_coroutines] [-W] [--salvage] filename [filename2 [...]] output_filename")
SRST
-.. option:: convert [--object OBJECTDEF] [--image-opts] [--target-image-opts] [--target-is-zero] [-U] [-C] [-c] [-p] [-q] [-n] [-f FMT] [-t CACHE] [-T SRC_CACHE] [-O OUTPUT_FMT] [-B BACKING_FILE] [-o OPTIONS] [-l SNAPSHOT_PARAM] [-S SPARSE_SIZE] [-m NUM_COROUTINES] [-W] [--salvage] FILENAME [FILENAME2 [...]] OUTPUT_FILENAME
+.. option:: convert [--object OBJECTDEF] [--image-opts] [--target-image-opts] [--target-is-zero] [--bitmaps] [-U] [-C] [-c] [-p] [-q] [-n] [-f FMT] [-t CACHE] [-T SRC_CACHE] [-O OUTPUT_FMT] [-B BACKING_FILE] [-o OPTIONS] [-l SNAPSHOT_PARAM] [-S SPARSE_SIZE] [-m NUM_COROUTINES] [-W] [--salvage] FILENAME [FILENAME2 [...]] OUTPUT_FILENAME
ERST
DEF("create", img_create,
@@ -63,9 +70,9 @@
ERST
DEF("map", img_map,
- "map [--object objectdef] [--image-opts] [-f fmt] [--output=ofmt] [-U] filename")
+ "map [--object objectdef] [--image-opts] [-f fmt] [--start-offset=offset] [--max-length=len] [--output=ofmt] [-U] filename")
SRST
-.. option:: map [--object OBJECTDEF] [--image-opts] [-f FMT] [--output=OFMT] [-U] FILENAME
+.. option:: map [--object OBJECTDEF] [--image-opts] [-f FMT] [--start-offset=OFFSET] [--max-length=LEN] [--output=OFMT] [-U] FILENAME
ERST
DEF("measure", img_measure,
diff --git a/qemu-img.c b/qemu-img.c
index 6a4327a..d7e846e 100644
--- a/qemu-img.c
+++ b/qemu-img.c
@@ -28,6 +28,7 @@
#include "qemu-common.h"
#include "qemu-version.h"
#include "qapi/error.h"
+#include "qapi/qapi-commands-block-core.h"
#include "qapi/qapi-visit-block-core.h"
#include "qapi/qobject-output-visitor.h"
#include "qapi/qmp/qjson.h"
@@ -71,6 +72,13 @@
OPTION_SHRINK = 266,
OPTION_SALVAGE = 267,
OPTION_TARGET_IS_ZERO = 268,
+ OPTION_ADD = 269,
+ OPTION_REMOVE = 270,
+ OPTION_CLEAR = 271,
+ OPTION_ENABLE = 272,
+ OPTION_DISABLE = 273,
+ OPTION_MERGE = 274,
+ OPTION_BITMAPS = 275,
};
typedef enum OutputFormat {
@@ -108,7 +116,7 @@
error_exit("unrecognized option '%s'", option);
}
-/* Please keep in synch with qemu-img.texi */
+/* Please keep in synch with docs/tools/qemu-img.rst */
static void QEMU_NORETURN help(void)
{
const char *help_msg =
@@ -169,6 +177,14 @@
" '-n' skips the target volume creation (useful if the volume is created\n"
" prior to running qemu-img)\n"
"\n"
+ "Parameters to bitmap subcommand:\n"
+ " 'bitmap' is the name of the bitmap to manipulate, through one or more\n"
+ " actions from '--add', '--remove', '--clear', '--enable', '--disable',\n"
+ " or '--merge source'\n"
+ " '-g granularity' sets the granularity for '--add' actions\n"
+ " '-b source' and '-F src_fmt' tell '--merge' actions to find the source\n"
+ " bitmaps from an alternative file\n"
+ "\n"
"Parameters to check subcommand:\n"
" '-r' tries to repair any inconsistencies that are found during the check.\n"
" '-r leaks' repairs only cluster leaks, whereas '-r all' fixes all\n"
@@ -176,6 +192,7 @@
" hiding corruption that has already occurred.\n"
"\n"
"Parameters to convert subcommand:\n"
+ " '--bitmaps' copies all top-level persistent bitmaps to destination\n"
" '-m' specifies how many coroutines work in parallel during the convert\n"
" process (defaults to 8)\n"
" '-W' allow to write to the target out of order rather than sequential\n"
@@ -470,19 +487,31 @@
return 0;
}
-static int64_t cvtnum(const char *s)
+static int64_t cvtnum_full(const char *name, const char *value, int64_t min,
+ int64_t max)
{
int err;
- uint64_t value;
+ uint64_t res;
- err = qemu_strtosz(s, NULL, &value);
- if (err < 0) {
+ err = qemu_strtosz(value, NULL, &res);
+ if (err < 0 && err != -ERANGE) {
+ error_report("Invalid %s specified. You may use "
+ "k, M, G, T, P or E suffixes for", name);
+ error_report("kilobytes, megabytes, gigabytes, terabytes, "
+ "petabytes and exabytes.");
return err;
}
- if (value > INT64_MAX) {
+ if (err == -ERANGE || res > max || res < min) {
+ error_report("Invalid %s specified. Must be between %" PRId64
+ " and %" PRId64 ".", name, min, max);
return -ERANGE;
}
- return value;
+ return res;
+}
+
+static int64_t cvtnum(const char *name, const char *value)
+{
+ return cvtnum_full(name, value, 0, INT64_MAX);
}
static int img_create(int argc, char **argv)
@@ -572,16 +601,8 @@
if (optind < argc) {
int64_t sval;
- sval = cvtnum(argv[optind++]);
+ sval = cvtnum("image size", argv[optind++]);
if (sval < 0) {
- if (sval == -ERANGE) {
- error_report("Image size must be less than 8 EiB!");
- } else {
- error_report("Invalid image size specified! You may use k, M, "
- "G, T, P or E suffixes for ");
- error_report("kilobytes, megabytes, gigabytes, terabytes, "
- "petabytes and exabytes.");
- }
goto fail;
}
img_size = (uint64_t)sval;
@@ -1104,11 +1125,20 @@
goto unref_backing;
}
- if (!drop && bs->drv->bdrv_make_empty) {
- ret = bs->drv->bdrv_make_empty(bs);
- if (ret) {
- error_setg_errno(&local_err, -ret, "Could not empty %s",
- filename);
+ if (!drop) {
+ BlockBackend *old_backing_blk;
+
+ old_backing_blk = blk_new_with_bs(bs, BLK_PERM_WRITE, BLK_PERM_ALL,
+ &local_err);
+ if (!old_backing_blk) {
+ goto unref_backing;
+ }
+ ret = blk_make_empty(old_backing_blk, &local_err);
+ blk_unref(old_backing_blk);
+ if (ret == -ENOTSUP) {
+ error_free(local_err);
+ local_err = NULL;
+ } else if (ret < 0) {
goto unref_backing;
}
}
@@ -1610,6 +1640,24 @@
return ret;
}
+/* Convenience wrapper around qmp_block_dirty_bitmap_merge */
+static void do_dirty_bitmap_merge(const char *dst_node, const char *dst_name,
+ const char *src_node, const char *src_name,
+ Error **errp)
+{
+ BlockDirtyBitmapMergeSource *merge_src;
+ BlockDirtyBitmapMergeSourceList *list;
+
+ merge_src = g_new0(BlockDirtyBitmapMergeSource, 1);
+ merge_src->type = QTYPE_QDICT;
+ merge_src->u.external.node = g_strdup(src_node);
+ merge_src->u.external.name = g_strdup(src_name);
+ list = g_new0(BlockDirtyBitmapMergeSourceList, 1);
+ list->value = merge_src;
+ qmp_block_dirty_bitmap_merge(dst_node, dst_name, list, errp);
+ qapi_free_BlockDirtyBitmapMergeSourceList(list);
+}
+
enum ImgConvertBlockStatus {
BLK_DATA,
BLK_ZERO,
@@ -2093,6 +2141,39 @@
return s->ret;
}
+static int convert_copy_bitmaps(BlockDriverState *src, BlockDriverState *dst)
+{
+ BdrvDirtyBitmap *bm;
+ Error *err = NULL;
+
+ FOR_EACH_DIRTY_BITMAP(src, bm) {
+ const char *name;
+
+ if (!bdrv_dirty_bitmap_get_persistence(bm)) {
+ continue;
+ }
+ name = bdrv_dirty_bitmap_name(bm);
+ qmp_block_dirty_bitmap_add(dst->node_name, name,
+ true, bdrv_dirty_bitmap_granularity(bm),
+ true, true,
+ true, !bdrv_dirty_bitmap_enabled(bm),
+ &err);
+ if (err) {
+ error_reportf_err(err, "Failed to create bitmap %s: ", name);
+ return -1;
+ }
+
+ do_dirty_bitmap_merge(dst->node_name, name, src->node_name, name,
+ &err);
+ if (err) {
+ error_reportf_err(err, "Failed to populate bitmap %s: ", name);
+ return -1;
+ }
+ }
+
+ return 0;
+}
+
#define MAX_BUF_SECTORS 32768
static int img_convert(int argc, char **argv)
@@ -2114,6 +2195,7 @@
int64_t ret = -EINVAL;
bool force_share = false;
bool explict_min_sparse = false;
+ bool bitmaps = false;
ImgConvertState s = (ImgConvertState) {
/* Need at least 4k of zeros for sparse detection */
@@ -2133,6 +2215,7 @@
{"target-image-opts", no_argument, 0, OPTION_TARGET_IMAGE_OPTS},
{"salvage", no_argument, 0, OPTION_SALVAGE},
{"target-is-zero", no_argument, 0, OPTION_TARGET_IS_ZERO},
+ {"bitmaps", no_argument, 0, OPTION_BITMAPS},
{0, 0, 0, 0}
};
c = getopt_long(argc, argv, ":hf:O:B:Cco:l:S:pt:T:qnm:WU",
@@ -2187,8 +2270,10 @@
{
int64_t sval;
- sval = cvtnum(optarg);
- if (sval < 0 || !QEMU_IS_ALIGNED(sval, BDRV_SECTOR_SIZE) ||
+ sval = cvtnum("buffer size for sparse output", optarg);
+ if (sval < 0) {
+ goto fail_getopt;
+ } else if (!QEMU_IS_ALIGNED(sval, BDRV_SECTOR_SIZE) ||
sval / BDRV_SECTOR_SIZE > MAX_BUF_SECTORS) {
error_report("Invalid buffer size for sparse output specified. "
"Valid sizes are multiples of %llu up to %llu. Select "
@@ -2256,6 +2341,9 @@
*/
s.has_zero_init = true;
break;
+ case OPTION_BITMAPS:
+ bitmaps = true;
+ break;
}
}
@@ -2317,7 +2405,6 @@
goto fail_getopt;
}
-
/* ret is still -EINVAL until here */
ret = bdrv_parse_cache_mode(src_cache, &src_flags, &src_writethrough);
if (ret < 0) {
@@ -2477,6 +2564,20 @@
}
}
+ /* Determine if bitmaps need copying */
+ if (bitmaps) {
+ if (s.src_num > 1) {
+ error_report("Copying bitmaps only possible with single source");
+ ret = -1;
+ goto out;
+ }
+ if (!bdrv_supports_persistent_dirty_bitmap(blk_bs(s.src[0]))) {
+ error_report("Source lacks bitmap support");
+ ret = -1;
+ goto out;
+ }
+ }
+
/*
* The later open call will need any decryption secrets, and
* bdrv_create() will purge "opts", so extract them now before
@@ -2485,9 +2586,7 @@
if (!skip_create) {
open_opts = qdict_new();
qemu_opt_foreach(opts, img_add_key_secrets, open_opts, &error_abort);
- }
- if (!skip_create) {
/* Create the new image */
ret = bdrv_create(drv, out_filename, opts, &local_err);
if (ret < 0) {
@@ -2525,6 +2624,13 @@
}
out_bs = blk_bs(s.target);
+ if (bitmaps && !bdrv_supports_persistent_dirty_bitmap(out_bs)) {
+ error_report("Format driver '%s' does not support bitmaps",
+ out_bs->drv->format_name);
+ ret = -1;
+ goto out;
+ }
+
if (s.compressed && !block_driver_can_compress(out_bs->drv)) {
error_report("Compression not supported for this file format");
ret = -1;
@@ -2584,6 +2690,12 @@
}
ret = convert_do_copy(&s);
+
+ /* Now copy the bitmaps */
+ if (bitmaps && ret == 0) {
+ ret = convert_copy_bitmaps(blk_bs(s.src[0]), out_bs);
+ }
+
out:
if (!ret) {
qemu_progress_print(100, 0);
@@ -2896,9 +3008,8 @@
}
break;
case OFORMAT_JSON:
- printf("%s{ \"start\": %"PRId64", \"length\": %"PRId64","
+ printf("{ \"start\": %"PRId64", \"length\": %"PRId64","
" \"depth\": %"PRId64", \"zero\": %s, \"data\": %s",
- (e->start == 0 ? "[" : ",\n"),
e->start, e->length, e->depth,
e->zero ? "true" : "false",
e->data ? "true" : "false");
@@ -2907,8 +3018,8 @@
}
putchar('}');
- if (!next) {
- printf("]\n");
+ if (next) {
+ puts(",");
}
break;
}
@@ -3004,6 +3115,8 @@
int ret = 0;
bool image_opts = false;
bool force_share = false;
+ int64_t start_offset = 0;
+ int64_t max_length = -1;
fmt = NULL;
output = NULL;
@@ -3016,9 +3129,11 @@
{"object", required_argument, 0, OPTION_OBJECT},
{"image-opts", no_argument, 0, OPTION_IMAGE_OPTS},
{"force-share", no_argument, 0, 'U'},
+ {"start-offset", required_argument, 0, 's'},
+ {"max-length", required_argument, 0, 'l'},
{0, 0, 0, 0}
};
- c = getopt_long(argc, argv, ":f:hU",
+ c = getopt_long(argc, argv, ":f:s:l:hU",
long_options, &option_index);
if (c == -1) {
break;
@@ -3042,6 +3157,18 @@
case OPTION_OUTPUT:
output = optarg;
break;
+ case 's':
+ start_offset = cvtnum("start offset", optarg);
+ if (start_offset < 0) {
+ return 1;
+ }
+ break;
+ case 'l':
+ max_length = cvtnum("max length", optarg);
+ if (max_length < 0) {
+ return 1;
+ }
+ break;
case OPTION_OBJECT: {
QemuOpts *opts;
opts = qemu_opts_parse_noisily(&qemu_object_opts,
@@ -3083,9 +3210,20 @@
if (output_format == OFORMAT_HUMAN) {
printf("%-16s%-16s%-16s%s\n", "Offset", "Length", "Mapped to", "File");
+ } else if (output_format == OFORMAT_JSON) {
+ putchar('[');
}
length = blk_getlength(blk);
+ if (length < 0) {
+ error_report("Failed to get size for '%s'", filename);
+ return 1;
+ }
+ if (max_length != -1) {
+ length = MIN(start_offset + max_length, length);
+ }
+
+ curr.start = start_offset;
while (curr.start + curr.length < length) {
int64_t offset = curr.start + curr.length;
int64_t n;
@@ -3114,6 +3252,9 @@
}
ret = dump_map_entry(output_format, &curr, NULL);
+ if (output_format == OFORMAT_JSON) {
+ puts("]");
+ }
out:
blk_unref(blk);
@@ -4291,9 +4432,8 @@
break;
case 'o':
{
- offset = cvtnum(optarg);
+ offset = cvtnum("offset", optarg);
if (offset < 0) {
- error_report("Invalid offset specified");
return 1;
}
break;
@@ -4306,9 +4446,8 @@
{
int64_t sval;
- sval = cvtnum(optarg);
- if (sval < 0 || sval > INT_MAX) {
- error_report("Invalid buffer size specified");
+ sval = cvtnum_full("buffer size", optarg, 0, INT_MAX);
+ if (sval < 0) {
return 1;
}
@@ -4319,9 +4458,8 @@
{
int64_t sval;
- sval = cvtnum(optarg);
- if (sval < 0 || sval > INT_MAX) {
- error_report("Invalid step size specified");
+ sval = cvtnum_full("step_size", optarg, 0, INT_MAX);
+ if (sval < 0) {
return 1;
}
@@ -4461,6 +4599,229 @@
return 0;
}
+enum ImgBitmapAct {
+ BITMAP_ADD,
+ BITMAP_REMOVE,
+ BITMAP_CLEAR,
+ BITMAP_ENABLE,
+ BITMAP_DISABLE,
+ BITMAP_MERGE,
+};
+typedef struct ImgBitmapAction {
+ enum ImgBitmapAct act;
+ const char *src; /* only used for merge */
+ QSIMPLEQ_ENTRY(ImgBitmapAction) next;
+} ImgBitmapAction;
+
+static int img_bitmap(int argc, char **argv)
+{
+ Error *err = NULL;
+ int c, ret = 1;
+ QemuOpts *opts = NULL;
+ const char *fmt = NULL, *src_fmt = NULL, *src_filename = NULL;
+ const char *filename, *bitmap;
+ BlockBackend *blk = NULL, *src = NULL;
+ BlockDriverState *bs = NULL, *src_bs = NULL;
+ bool image_opts = false;
+ int64_t granularity = 0;
+ bool add = false, merge = false;
+ QSIMPLEQ_HEAD(, ImgBitmapAction) actions;
+ ImgBitmapAction *act, *act_next;
+ const char *op;
+
+ QSIMPLEQ_INIT(&actions);
+
+ for (;;) {
+ static const struct option long_options[] = {
+ {"help", no_argument, 0, 'h'},
+ {"object", required_argument, 0, OPTION_OBJECT},
+ {"image-opts", no_argument, 0, OPTION_IMAGE_OPTS},
+ {"add", no_argument, 0, OPTION_ADD},
+ {"remove", no_argument, 0, OPTION_REMOVE},
+ {"clear", no_argument, 0, OPTION_CLEAR},
+ {"enable", no_argument, 0, OPTION_ENABLE},
+ {"disable", no_argument, 0, OPTION_DISABLE},
+ {"merge", required_argument, 0, OPTION_MERGE},
+ {"granularity", required_argument, 0, 'g'},
+ {"source-file", required_argument, 0, 'b'},
+ {"source-format", required_argument, 0, 'F'},
+ {0, 0, 0, 0}
+ };
+ c = getopt_long(argc, argv, ":b:f:F:g:h", long_options, NULL);
+ if (c == -1) {
+ break;
+ }
+
+ switch (c) {
+ case ':':
+ missing_argument(argv[optind - 1]);
+ break;
+ case '?':
+ unrecognized_option(argv[optind - 1]);
+ break;
+ case 'h':
+ help();
+ break;
+ case 'b':
+ src_filename = optarg;
+ break;
+ case 'f':
+ fmt = optarg;
+ break;
+ case 'F':
+ src_fmt = optarg;
+ break;
+ case 'g':
+ granularity = cvtnum("granularity", optarg);
+ if (granularity < 0) {
+ return 1;
+ }
+ break;
+ case OPTION_ADD:
+ act = g_new0(ImgBitmapAction, 1);
+ act->act = BITMAP_ADD;
+ QSIMPLEQ_INSERT_TAIL(&actions, act, next);
+ add = true;
+ break;
+ case OPTION_REMOVE:
+ act = g_new0(ImgBitmapAction, 1);
+ act->act = BITMAP_REMOVE;
+ QSIMPLEQ_INSERT_TAIL(&actions, act, next);
+ break;
+ case OPTION_CLEAR:
+ act = g_new0(ImgBitmapAction, 1);
+ act->act = BITMAP_CLEAR;
+ QSIMPLEQ_INSERT_TAIL(&actions, act, next);
+ break;
+ case OPTION_ENABLE:
+ act = g_new0(ImgBitmapAction, 1);
+ act->act = BITMAP_ENABLE;
+ QSIMPLEQ_INSERT_TAIL(&actions, act, next);
+ break;
+ case OPTION_DISABLE:
+ act = g_new0(ImgBitmapAction, 1);
+ act->act = BITMAP_DISABLE;
+ QSIMPLEQ_INSERT_TAIL(&actions, act, next);
+ break;
+ case OPTION_MERGE:
+ act = g_new0(ImgBitmapAction, 1);
+ act->act = BITMAP_MERGE;
+ act->src = optarg;
+ QSIMPLEQ_INSERT_TAIL(&actions, act, next);
+ merge = true;
+ break;
+ case OPTION_OBJECT:
+ opts = qemu_opts_parse_noisily(&qemu_object_opts, optarg, true);
+ if (!opts) {
+ goto out;
+ }
+ break;
+ case OPTION_IMAGE_OPTS:
+ image_opts = true;
+ break;
+ }
+ }
+
+ if (qemu_opts_foreach(&qemu_object_opts,
+ user_creatable_add_opts_foreach,
+ qemu_img_object_print_help, &error_fatal)) {
+ goto out;
+ }
+
+ if (QSIMPLEQ_EMPTY(&actions)) {
+ error_report("Need at least one of --add, --remove, --clear, "
+ "--enable, --disable, or --merge");
+ goto out;
+ }
+
+ if (granularity && !add) {
+ error_report("granularity only supported with --add");
+ goto out;
+ }
+ if (src_fmt && !src_filename) {
+ error_report("-F only supported with -b");
+ goto out;
+ }
+ if (src_filename && !merge) {
+ error_report("Merge bitmap source file only supported with "
+ "--merge");
+ goto out;
+ }
+
+ if (optind != argc - 2) {
+ error_report("Expecting filename and bitmap name");
+ goto out;
+ }
+
+ filename = argv[optind];
+ bitmap = argv[optind + 1];
+
+ blk = img_open(image_opts, filename, fmt, BDRV_O_RDWR, false, false,
+ false);
+ if (!blk) {
+ goto out;
+ }
+ bs = blk_bs(blk);
+ if (src_filename) {
+ src = img_open(false, src_filename, src_fmt, 0, false, false, false);
+ if (!src) {
+ goto out;
+ }
+ src_bs = blk_bs(src);
+ } else {
+ src_bs = bs;
+ }
+
+ QSIMPLEQ_FOREACH_SAFE(act, &actions, next, act_next) {
+ switch (act->act) {
+ case BITMAP_ADD:
+ qmp_block_dirty_bitmap_add(bs->node_name, bitmap,
+ !!granularity, granularity, true, true,
+ false, false, &err);
+ op = "add";
+ break;
+ case BITMAP_REMOVE:
+ qmp_block_dirty_bitmap_remove(bs->node_name, bitmap, &err);
+ op = "remove";
+ break;
+ case BITMAP_CLEAR:
+ qmp_block_dirty_bitmap_clear(bs->node_name, bitmap, &err);
+ op = "clear";
+ break;
+ case BITMAP_ENABLE:
+ qmp_block_dirty_bitmap_enable(bs->node_name, bitmap, &err);
+ op = "enable";
+ break;
+ case BITMAP_DISABLE:
+ qmp_block_dirty_bitmap_disable(bs->node_name, bitmap, &err);
+ op = "disable";
+ break;
+ case BITMAP_MERGE:
+ do_dirty_bitmap_merge(bs->node_name, bitmap, src_bs->node_name,
+ act->src, &err);
+ op = "merge";
+ break;
+ default:
+ g_assert_not_reached();
+ }
+
+ if (err) {
+ error_reportf_err(err, "Operation %s on bitmap %s failed: ",
+ op, bitmap);
+ goto out;
+ }
+ g_free(act);
+ }
+
+ ret = 0;
+
+ out:
+ blk_unref(src);
+ blk_unref(blk);
+ qemu_opts_del(opts);
+ return ret;
+}
+
#define C_BS 01
#define C_COUNT 02
#define C_IF 04
@@ -4491,10 +4852,9 @@
{
int64_t res;
- res = cvtnum(arg);
+ res = cvtnum_full("bs", arg, 1, INT_MAX);
- if (res <= 0 || res > INT_MAX) {
- error_report("invalid number: '%s'", arg);
+ if (res < 0) {
return 1;
}
in->bsz = out->bsz = res;
@@ -4506,10 +4866,9 @@
struct DdIo *in, struct DdIo *out,
struct DdInfo *dd)
{
- dd->count = cvtnum(arg);
+ dd->count = cvtnum("count", arg);
if (dd->count < 0) {
- error_report("invalid number: '%s'", arg);
return 1;
}
@@ -4538,10 +4897,9 @@
struct DdIo *in, struct DdIo *out,
struct DdInfo *dd)
{
- in->offset = cvtnum(arg);
+ in->offset = cvtnum("skip", arg);
if (in->offset < 0) {
- error_report("invalid number: '%s'", arg);
return 1;
}
@@ -4923,16 +5281,8 @@
{
int64_t sval;
- sval = cvtnum(optarg);
+ sval = cvtnum("image size", optarg);
if (sval < 0) {
- if (sval == -ERANGE) {
- error_report("Image size must be less than 8 EiB!");
- } else {
- error_report("Invalid image size specified! You may use "
- "k, M, G, T, P or E suffixes for ");
- error_report("kilobytes, megabytes, gigabytes, terabytes, "
- "petabytes and exabytes.");
- }
goto out;
}
img_size = (uint64_t)sval;
@@ -5024,6 +5374,9 @@
if (output_format == OFORMAT_HUMAN) {
printf("required size: %" PRIu64 "\n", info->required);
printf("fully allocated size: %" PRIu64 "\n", info->fully_allocated);
+ if (info->has_bitmaps) {
+ printf("bitmaps size: %" PRIu64 "\n", info->bitmaps);
+ }
} else {
dump_json_block_measure_info(info);
}
diff --git a/qemu-nbd.c b/qemu-nbd.c
index 4aa0050..d2657b8 100644
--- a/qemu-nbd.c
+++ b/qemu-nbd.c
@@ -856,8 +856,7 @@
}
tlscreds = nbd_get_tls_creds(tlscredsid, list, &local_err);
if (local_err) {
- error_report("Failed to get TLS creds %s",
- error_get_pretty(local_err));
+ error_reportf_err(local_err, "Failed to get TLS creds: ");
exit(EXIT_FAILURE);
}
} else {
@@ -916,7 +915,11 @@
} else if (pid == 0) {
close(stderr_fd[0]);
- old_stderr = dup(STDERR_FILENO);
+ /* Remember parent's stderr if we will be restoring it. */
+ if (fork_process) {
+ old_stderr = dup(STDERR_FILENO);
+ }
+
ret = qemu_daemon(1, 0);
/* Temporarily redirect stderr to the parent's pipe... */
@@ -979,8 +982,8 @@
&local_err);
if (sioc == NULL) {
object_unref(OBJECT(server));
- error_report("Failed to use socket activation: %s",
- error_get_pretty(local_err));
+ error_reportf_err(local_err,
+ "Failed to use socket activation: ");
exit(EXIT_FAILURE);
}
qio_net_listener_add(server, sioc);
diff --git a/qemu-options.hx b/qemu-options.hx
index 292d4e7..93bde2b 100644
--- a/qemu-options.hx
+++ b/qemu-options.hx
@@ -1542,9 +1542,17 @@
``-virtfs proxy,sock_fd=sock_fd,mount_tag=mount_tag [,writeout=writeout][,readonly]``
\
``-virtfs synth,mount_tag=mount_tag``
- Define a new filesystem device and expose it to the guest using a
- virtio-9p-device. The general form of a Virtual File system
- pass-through options are:
+ Define a new virtual filesystem device and expose it to the guest using
+ a virtio-9p-device (a.k.a. 9pfs), which essentially means that a certain
+ directory on host is made directly accessible by guest as a pass-through
+ file system by using the 9P network protocol for communication between
+ host and guests, if desired even accessible, shared by several guests
+ simultaniously.
+
+ Note that ``-virtfs`` is actually just a convenience shortcut for its
+ generalized form ``-fsdev -device virtio-9p-pci``.
+
+ The general form of pass-through file system options are:
``local``
Accesses to the filesystem are done by QEMU.
@@ -2930,7 +2938,7 @@
" [,server][,nowait][,telnet][,websocket][,reconnect=seconds][,mux=on|off]\n"
" [,logfile=PATH][,logappend=on|off][,tls-creds=ID][,tls-authz=ID] (tcp)\n"
"-chardev socket,id=id,path=path[,server][,nowait][,telnet][,websocket][,reconnect=seconds]\n"
- " [,mux=on|off][,logfile=PATH][,logappend=on|off] (unix)\n"
+ " [,mux=on|off][,logfile=PATH][,logappend=on|off][,abstract=on|off][,tight=on|off] (unix)\n"
"-chardev udp,id=id[,host=host],port=port[,localaddr=localaddr]\n"
" [,localport=localport][,ipv4][,ipv6][,mux=on|off]\n"
" [,logfile=PATH][,logappend=on|off]\n"
@@ -3097,9 +3105,13 @@
``nodelay`` disables the Nagle algorithm.
- ``unix options: path=path``
+ ``unix options: path=path[,abstract=on|off][,tight=on|off]``
``path`` specifies the local path of the unix socket. ``path``
is required.
+ ``abstract`` specifies the use of the abstract socket namespace,
+ rather than the filesystem. Optional, defaults to false.
+ ``tight`` sets the socket length of abstract sockets to their minimum,
+ rather than the full sun_path length. Optional, defaults to true.
``-chardev udp,id=id[,host=host],port=port[,localaddr=localaddr][,localport=localport][,ipv4][,ipv6]``
Sends all traffic from the guest to a remote host over UDP.
diff --git a/qom/container.c b/qom/container.c
index f6ccaf7..14e7ae4 100644
--- a/qom/container.c
+++ b/qom/container.c
@@ -28,7 +28,7 @@
Object *container_get(Object *root, const char *path)
{
Object *obj, *child;
- gchar **parts;
+ char **parts;
int i;
parts = g_strsplit(path, "/", 0);
@@ -39,7 +39,7 @@
child = object_resolve_path_component(obj, parts[i]);
if (!child) {
child = object_new("container");
- object_property_add_child(obj, parts[i], child, NULL);
+ object_property_add_child(obj, parts[i], child);
object_unref(child);
}
}
diff --git a/qom/object.c b/qom/object.c
index be700e8..d0be42c 100644
--- a/qom/object.c
+++ b/qom/object.c
@@ -557,10 +557,7 @@
goto out;
}
- object_property_add_child(parentobj, propname, obj, &local_err);
- if (local_err) {
- goto out;
- }
+ object_property_add_child(parentobj, propname, obj);
uc = (UserCreatable *)object_dynamic_cast(obj, TYPE_USER_CREATABLE);
if (uc) {
@@ -571,18 +568,18 @@
}
}
+out:
/*
- * Since object_property_add_child added a reference to the child object,
- * we can drop the reference added by object_initialize(), so the child
- * property will own the only reference to the object.
+ * We want @obj's reference to be 1 on success, 0 on failure.
+ * On success, it's 2: one taken by object_initialize(), and one
+ * by object_property_add_child().
+ * On failure in object_initialize() or earlier, it's 1.
+ * On failure afterwards, it's also 1: object_unparent() releases
+ * the reference taken by object_property_add_child().
*/
object_unref(obj);
-out:
- if (local_err) {
- error_propagate(errp, local_err);
- object_unref(obj);
- }
+ error_propagate(errp, local_err);
}
static inline bool object_property_is_child(ObjectProperty *prop)
@@ -614,7 +611,7 @@
g_hash_table_unref(obj->properties);
}
-static void object_property_del_child(Object *obj, Object *child, Error **errp)
+static void object_property_del_child(Object *obj, Object *child)
{
ObjectProperty *prop;
GHashTableIter iter;
@@ -644,7 +641,7 @@
void object_unparent(Object *obj)
{
if (obj->parent) {
- object_property_del_child(obj->parent, obj, NULL);
+ object_property_del_child(obj->parent, obj);
}
}
@@ -745,10 +742,7 @@
}
if (id != NULL) {
- object_property_add_child(parent, id, obj, &local_err);
- if (local_err) {
- goto error;
- }
+ object_property_add_child(parent, id, obj);
}
uc = (UserCreatable *)object_dynamic_cast(obj, TYPE_USER_CREATABLE);
@@ -762,7 +756,7 @@
}
}
- object_unref(OBJECT(obj));
+ object_unref(obj);
return obj;
error:
@@ -1129,12 +1123,12 @@
}
}
-ObjectProperty *
-object_property_add(Object *obj, const char *name, const char *type,
- ObjectPropertyAccessor *get,
- ObjectPropertyAccessor *set,
- ObjectPropertyRelease *release,
- void *opaque, Error **errp)
+static ObjectProperty *
+object_property_try_add(Object *obj, const char *name, const char *type,
+ ObjectPropertyAccessor *get,
+ ObjectPropertyAccessor *set,
+ ObjectPropertyRelease *release,
+ void *opaque, Error **errp)
{
ObjectProperty *prop;
size_t name_len = strlen(name);
@@ -1148,8 +1142,8 @@
for (i = 0; ; ++i) {
char *full_name = g_strdup_printf("%s[%d]", name_no_array, i);
- ret = object_property_add(obj, full_name, type, get, set,
- release, opaque, NULL);
+ ret = object_property_try_add(obj, full_name, type, get, set,
+ release, opaque, NULL);
g_free(full_name);
if (ret) {
break;
@@ -1180,22 +1174,28 @@
}
ObjectProperty *
+object_property_add(Object *obj, const char *name, const char *type,
+ ObjectPropertyAccessor *get,
+ ObjectPropertyAccessor *set,
+ ObjectPropertyRelease *release,
+ void *opaque)
+{
+ return object_property_try_add(obj, name, type, get, set, release,
+ opaque, &error_abort);
+}
+
+ObjectProperty *
object_class_property_add(ObjectClass *klass,
const char *name,
const char *type,
ObjectPropertyAccessor *get,
ObjectPropertyAccessor *set,
ObjectPropertyRelease *release,
- void *opaque,
- Error **errp)
+ void *opaque)
{
ObjectProperty *prop;
- if (object_class_property_find(klass, name, NULL) != NULL) {
- error_setg(errp, "attempt to add duplicate property '%s' to class (type '%s')",
- name, object_class_get_name(klass));
- return NULL;
- }
+ assert(!object_class_property_find(klass, name, NULL));
prop = g_malloc0(sizeof(*prop));
@@ -1280,15 +1280,10 @@
return prop;
}
-void object_property_del(Object *obj, const char *name, Error **errp)
+void object_property_del(Object *obj, const char *name)
{
ObjectProperty *prop = g_hash_table_lookup(obj->properties, name);
- if (!prop) {
- error_setg(errp, "Property '.%s' not found", name);
- return;
- }
-
if (prop->release) {
prop->release(obj, name, prop->opaque);
}
@@ -1357,7 +1352,7 @@
const char *name, Error **errp)
{
if (value) {
- gchar *path = object_get_canonical_path(value);
+ char *path = object_get_canonical_path(value);
object_property_set_str(obj, path, name, errp);
g_free(path);
} else {
@@ -1521,8 +1516,6 @@
int object_property_get_enum(Object *obj, const char *name,
const char *typename, Error **errp)
{
- Error *err = NULL;
- Visitor *v;
char *str;
int ret;
ObjectProperty *prop = object_property_find(obj, name, errp);
@@ -1541,15 +1534,10 @@
enumprop = prop->opaque;
- v = string_output_visitor_new(false, &str);
- object_property_get(obj, v, name, &err);
- if (err) {
- error_propagate(errp, err);
- visit_free(v);
+ str = object_property_get_str(obj, name, errp);
+ if (!str) {
return 0;
}
- visit_complete(v, &str);
- visit_free(v);
ret = qapi_enum_parse(enumprop->lookup, str, -1, errp);
g_free(str);
@@ -1557,29 +1545,6 @@
return ret;
}
-void object_property_get_uint16List(Object *obj, const char *name,
- uint16List **list, Error **errp)
-{
- Error *err = NULL;
- Visitor *v;
- char *str;
-
- v = string_output_visitor_new(false, &str);
- object_property_get(obj, v, name, &err);
- if (err) {
- error_propagate(errp, err);
- goto out;
- }
- visit_complete(v, &str);
- visit_free(v);
- v = string_input_visitor_new(str);
- visit_type_uint16List(v, NULL, list, errp);
-
- g_free(str);
-out:
- visit_free(v);
-}
-
void object_property_parse(Object *obj, const char *string,
const char *name, Error **errp)
{
@@ -1651,14 +1616,15 @@
Error **errp)
{
Object *child = opaque;
- gchar *path;
+ char *path;
path = object_get_canonical_path(child);
visit_type_str(v, name, &path, errp);
g_free(path);
}
-static Object *object_resolve_child_property(Object *parent, void *opaque, const gchar *part)
+static Object *object_resolve_child_property(Object *parent, void *opaque,
+ const char *part)
{
return opaque;
}
@@ -1675,33 +1641,23 @@
object_unref(child);
}
-void object_property_add_child(Object *obj, const char *name,
- Object *child, Error **errp)
+ObjectProperty *
+object_property_add_child(Object *obj, const char *name,
+ Object *child)
{
- Error *local_err = NULL;
- gchar *type;
+ g_autofree char *type = NULL;
ObjectProperty *op;
- if (child->parent != NULL) {
- error_setg(errp, "child object is already parented");
- return;
- }
+ assert(!child->parent);
- type = g_strdup_printf("child<%s>", object_get_typename(OBJECT(child)));
+ type = g_strdup_printf("child<%s>", object_get_typename(child));
op = object_property_add(obj, name, type, object_get_child_property, NULL,
- object_finalize_child_property, child, &local_err);
- if (local_err) {
- error_propagate(errp, local_err);
- goto out;
- }
-
+ object_finalize_child_property, child);
op->resolve = object_resolve_child_property;
object_ref(child);
child->parent = obj;
-
-out:
- g_free(type);
+ return op;
}
void object_property_allow_set_link(const Object *obj, const char *name,
@@ -1738,14 +1694,14 @@
{
LinkProperty *lprop = opaque;
Object **targetp = object_link_get_targetp(obj, lprop);
- gchar *path;
+ char *path;
if (*targetp) {
path = object_get_canonical_path(*targetp);
visit_type_str(v, name, &path, errp);
g_free(path);
} else {
- path = (gchar *)"";
+ path = (char *)"";
visit_type_str(v, name, &path, errp);
}
}
@@ -1763,7 +1719,7 @@
const char *path, Error **errp)
{
const char *type;
- gchar *target_type;
+ char *target_type;
bool ambiguous = false;
Object *target;
@@ -1826,7 +1782,8 @@
}
}
-static Object *object_resolve_link_property(Object *parent, void *opaque, const gchar *part)
+static Object *object_resolve_link_property(Object *parent, void *opaque,
+ const char *part)
{
LinkProperty *lprop = opaque;
@@ -1847,16 +1804,15 @@
}
}
-static void object_add_link_prop(Object *obj, const char *name,
- const char *type, void *ptr,
- void (*check)(const Object *, const char *,
- Object *, Error **),
- ObjectPropertyLinkFlags flags,
- Error **errp)
+static ObjectProperty *
+object_add_link_prop(Object *obj, const char *name,
+ const char *type, void *ptr,
+ void (*check)(const Object *, const char *,
+ Object *, Error **),
+ ObjectPropertyLinkFlags flags)
{
- Error *local_err = NULL;
LinkProperty *prop = g_malloc(sizeof(*prop));
- gchar *full_type;
+ g_autofree char *full_type = NULL;
ObjectProperty *op;
if (flags & OBJ_PROP_LINK_DIRECT) {
@@ -1873,28 +1829,19 @@
object_get_link_property,
check ? object_set_link_property : NULL,
object_release_link_property,
- prop,
- &local_err);
- if (local_err) {
- error_propagate(errp, local_err);
- g_free(prop);
- goto out;
- }
-
+ prop);
op->resolve = object_resolve_link_property;
-
-out:
- g_free(full_type);
+ return op;
}
-void object_property_add_link(Object *obj, const char *name,
- const char *type, Object **targetp,
- void (*check)(const Object *, const char *,
- Object *, Error **),
- ObjectPropertyLinkFlags flags,
- Error **errp)
+ObjectProperty *
+object_property_add_link(Object *obj, const char *name,
+ const char *type, Object **targetp,
+ void (*check)(const Object *, const char *,
+ Object *, Error **),
+ ObjectPropertyLinkFlags flags)
{
- object_add_link_prop(obj, name, type, targetp, check, flags, errp);
+ return object_add_link_prop(obj, name, type, targetp, check, flags);
}
ObjectProperty *
@@ -1903,12 +1850,10 @@
const char *type, ptrdiff_t offset,
void (*check)(const Object *obj, const char *name,
Object *val, Error **errp),
- ObjectPropertyLinkFlags flags,
- Error **errp)
+ ObjectPropertyLinkFlags flags)
{
- Error *local_err = NULL;
LinkProperty *prop = g_new0(LinkProperty, 1);
- gchar *full_type;
+ char *full_type;
ObjectProperty *op;
prop->offset = offset;
@@ -1921,29 +1866,24 @@
object_get_link_property,
check ? object_set_link_property : NULL,
object_release_link_property,
- prop,
- &local_err);
- if (local_err) {
- error_propagate(errp, local_err);
- g_free(prop);
- goto out;
- }
+ prop);
op->resolve = object_resolve_link_property;
-out:
g_free(full_type);
return op;
}
-void object_property_add_const_link(Object *obj, const char *name,
- Object *target, Error **errp)
+ObjectProperty *
+object_property_add_const_link(Object *obj, const char *name,
+ Object *target)
{
- object_add_link_prop(obj, name, object_get_typename(target), target,
- NULL, OBJ_PROP_LINK_DIRECT, errp);
+ return object_add_link_prop(obj, name,
+ object_get_typename(target), target,
+ NULL, OBJ_PROP_LINK_DIRECT);
}
-gchar *object_get_canonical_path_component(Object *obj)
+char *object_get_canonical_path_component(Object *obj)
{
ObjectProperty *prop = NULL;
GHashTableIter iter;
@@ -1968,7 +1908,7 @@
return NULL;
}
-gchar *object_get_canonical_path(Object *obj)
+char *object_get_canonical_path(Object *obj)
{
Object *root = object_get_root();
char *newpath, *path = NULL;
@@ -1998,7 +1938,7 @@
return path;
}
-Object *object_resolve_path_component(Object *parent, const gchar *part)
+Object *object_resolve_path_component(Object *parent, const char *part)
{
ObjectProperty *prop = object_property_find(parent, part, NULL);
if (prop == NULL) {
@@ -2013,9 +1953,9 @@
}
static Object *object_resolve_abs_path(Object *parent,
- gchar **parts,
- const char *typename,
- int index)
+ char **parts,
+ const char *typename,
+ int index)
{
Object *child;
@@ -2036,9 +1976,9 @@
}
static Object *object_resolve_partial_path(Object *parent,
- gchar **parts,
- const char *typename,
- bool *ambiguous)
+ char **parts,
+ const char *typename,
+ bool *ambiguous)
{
Object *obj;
GHashTableIter iter;
@@ -2076,7 +2016,7 @@
bool *ambiguousp)
{
Object *obj;
- gchar **parts;
+ char **parts;
parts = g_strsplit(path, "/", 0);
assert(parts);
@@ -2149,53 +2089,39 @@
g_free(prop);
}
-void object_property_add_str(Object *obj, const char *name,
- char *(*get)(Object *, Error **),
- void (*set)(Object *, const char *, Error **),
- Error **errp)
+ObjectProperty *
+object_property_add_str(Object *obj, const char *name,
+ char *(*get)(Object *, Error **),
+ void (*set)(Object *, const char *, Error **))
{
- Error *local_err = NULL;
StringProperty *prop = g_malloc0(sizeof(*prop));
prop->get = get;
prop->set = set;
- object_property_add(obj, name, "string",
- get ? property_get_str : NULL,
- set ? property_set_str : NULL,
- property_release_str,
- prop, &local_err);
- if (local_err) {
- error_propagate(errp, local_err);
- g_free(prop);
- }
+ return object_property_add(obj, name, "string",
+ get ? property_get_str : NULL,
+ set ? property_set_str : NULL,
+ property_release_str,
+ prop);
}
ObjectProperty *
object_class_property_add_str(ObjectClass *klass, const char *name,
char *(*get)(Object *, Error **),
void (*set)(Object *, const char *,
- Error **),
- Error **errp)
+ Error **))
{
- Error *local_err = NULL;
StringProperty *prop = g_malloc0(sizeof(*prop));
- ObjectProperty *rv;
prop->get = get;
prop->set = set;
- rv = object_class_property_add(klass, name, "string",
- get ? property_get_str : NULL,
- set ? property_set_str : NULL,
- NULL,
- prop, &local_err);
- if (local_err) {
- error_propagate(errp, local_err);
- g_free(prop);
- }
-
- return rv;
+ return object_class_property_add(klass, name, "string",
+ get ? property_get_str : NULL,
+ set ? property_set_str : NULL,
+ NULL,
+ prop);
}
typedef struct BoolProperty
@@ -2243,52 +2169,38 @@
g_free(prop);
}
-void object_property_add_bool(Object *obj, const char *name,
- bool (*get)(Object *, Error **),
- void (*set)(Object *, bool, Error **),
- Error **errp)
+ObjectProperty *
+object_property_add_bool(Object *obj, const char *name,
+ bool (*get)(Object *, Error **),
+ void (*set)(Object *, bool, Error **))
{
- Error *local_err = NULL;
BoolProperty *prop = g_malloc0(sizeof(*prop));
prop->get = get;
prop->set = set;
- object_property_add(obj, name, "bool",
- get ? property_get_bool : NULL,
- set ? property_set_bool : NULL,
- property_release_bool,
- prop, &local_err);
- if (local_err) {
- error_propagate(errp, local_err);
- g_free(prop);
- }
+ return object_property_add(obj, name, "bool",
+ get ? property_get_bool : NULL,
+ set ? property_set_bool : NULL,
+ property_release_bool,
+ prop);
}
ObjectProperty *
object_class_property_add_bool(ObjectClass *klass, const char *name,
bool (*get)(Object *, Error **),
- void (*set)(Object *, bool, Error **),
- Error **errp)
+ void (*set)(Object *, bool, Error **))
{
- Error *local_err = NULL;
BoolProperty *prop = g_malloc0(sizeof(*prop));
- ObjectProperty *rv;
prop->get = get;
prop->set = set;
- rv = object_class_property_add(klass, name, "bool",
- get ? property_get_bool : NULL,
- set ? property_set_bool : NULL,
- NULL,
- prop, &local_err);
- if (local_err) {
- error_propagate(errp, local_err);
- g_free(prop);
- }
-
- return rv;
+ return object_class_property_add(klass, name, "bool",
+ get ? property_get_bool : NULL,
+ set ? property_set_bool : NULL,
+ NULL,
+ prop);
}
static void property_get_enum(Object *obj, Visitor *v, const char *name,
@@ -2329,29 +2241,24 @@
g_free(prop);
}
-void object_property_add_enum(Object *obj, const char *name,
- const char *typename,
- const QEnumLookup *lookup,
- int (*get)(Object *, Error **),
- void (*set)(Object *, int, Error **),
- Error **errp)
+ObjectProperty *
+object_property_add_enum(Object *obj, const char *name,
+ const char *typename,
+ const QEnumLookup *lookup,
+ int (*get)(Object *, Error **),
+ void (*set)(Object *, int, Error **))
{
- Error *local_err = NULL;
EnumProperty *prop = g_malloc(sizeof(*prop));
prop->lookup = lookup;
prop->get = get;
prop->set = set;
- object_property_add(obj, name, typename,
- get ? property_get_enum : NULL,
- set ? property_set_enum : NULL,
- property_release_enum,
- prop, &local_err);
- if (local_err) {
- error_propagate(errp, local_err);
- g_free(prop);
- }
+ return object_property_add(obj, name, typename,
+ get ? property_get_enum : NULL,
+ set ? property_set_enum : NULL,
+ property_release_enum,
+ prop);
}
ObjectProperty *
@@ -2359,28 +2266,19 @@
const char *typename,
const QEnumLookup *lookup,
int (*get)(Object *, Error **),
- void (*set)(Object *, int, Error **),
- Error **errp)
+ void (*set)(Object *, int, Error **))
{
- Error *local_err = NULL;
EnumProperty *prop = g_malloc(sizeof(*prop));
- ObjectProperty *rv;
prop->lookup = lookup;
prop->get = get;
prop->set = set;
- rv = object_class_property_add(klass, name, typename,
- get ? property_get_enum : NULL,
- set ? property_set_enum : NULL,
- NULL,
- prop, &local_err);
- if (local_err) {
- error_propagate(errp, local_err);
- g_free(prop);
- }
-
- return rv;
+ return object_class_property_add(klass, name, typename,
+ get ? property_get_enum : NULL,
+ set ? property_set_enum : NULL,
+ NULL,
+ prop);
}
typedef struct TMProperty {
@@ -2442,46 +2340,31 @@
g_free(prop);
}
-void object_property_add_tm(Object *obj, const char *name,
- void (*get)(Object *, struct tm *, Error **),
- Error **errp)
+ObjectProperty *
+object_property_add_tm(Object *obj, const char *name,
+ void (*get)(Object *, struct tm *, Error **))
{
- Error *local_err = NULL;
TMProperty *prop = g_malloc0(sizeof(*prop));
prop->get = get;
- object_property_add(obj, name, "struct tm",
- get ? property_get_tm : NULL, NULL,
- property_release_tm,
- prop, &local_err);
- if (local_err) {
- error_propagate(errp, local_err);
- g_free(prop);
- }
+ return object_property_add(obj, name, "struct tm",
+ get ? property_get_tm : NULL, NULL,
+ property_release_tm,
+ prop);
}
ObjectProperty *
object_class_property_add_tm(ObjectClass *klass, const char *name,
- void (*get)(Object *, struct tm *, Error **),
- Error **errp)
+ void (*get)(Object *, struct tm *, Error **))
{
- Error *local_err = NULL;
TMProperty *prop = g_malloc0(sizeof(*prop));
- ObjectProperty *rv;
prop->get = get;
- rv = object_class_property_add(klass, name, "struct tm",
- get ? property_get_tm : NULL, NULL,
- NULL,
- prop, &local_err);
- if (local_err) {
- error_propagate(errp, local_err);
- g_free(prop);
- }
-
- return rv;
+ return object_class_property_add(klass, name, "struct tm",
+ get ? property_get_tm : NULL,
+ NULL, NULL, prop);
}
static char *qdev_get_type(Object *obj, Error **errp)
@@ -2581,10 +2464,10 @@
*field = value;
}
-void object_property_add_uint8_ptr(Object *obj, const char *name,
- const uint8_t *v,
- ObjectPropertyFlags flags,
- Error **errp)
+ObjectProperty *
+object_property_add_uint8_ptr(Object *obj, const char *name,
+ const uint8_t *v,
+ ObjectPropertyFlags flags)
{
ObjectPropertyAccessor *getter = NULL;
ObjectPropertyAccessor *setter = NULL;
@@ -2597,15 +2480,14 @@
setter = property_set_uint8_ptr;
}
- object_property_add(obj, name, "uint8",
- getter, setter, NULL, (void *)v, errp);
+ return object_property_add(obj, name, "uint8",
+ getter, setter, NULL, (void *)v);
}
ObjectProperty *
object_class_property_add_uint8_ptr(ObjectClass *klass, const char *name,
const uint8_t *v,
- ObjectPropertyFlags flags,
- Error **errp)
+ ObjectPropertyFlags flags)
{
ObjectPropertyAccessor *getter = NULL;
ObjectPropertyAccessor *setter = NULL;
@@ -2619,13 +2501,13 @@
}
return object_class_property_add(klass, name, "uint8",
- getter, setter, NULL, (void *)v, errp);
+ getter, setter, NULL, (void *)v);
}
-void object_property_add_uint16_ptr(Object *obj, const char *name,
- const uint16_t *v,
- ObjectPropertyFlags flags,
- Error **errp)
+ObjectProperty *
+object_property_add_uint16_ptr(Object *obj, const char *name,
+ const uint16_t *v,
+ ObjectPropertyFlags flags)
{
ObjectPropertyAccessor *getter = NULL;
ObjectPropertyAccessor *setter = NULL;
@@ -2638,15 +2520,14 @@
setter = property_set_uint16_ptr;
}
- object_property_add(obj, name, "uint16",
- getter, setter, NULL, (void *)v, errp);
+ return object_property_add(obj, name, "uint16",
+ getter, setter, NULL, (void *)v);
}
ObjectProperty *
object_class_property_add_uint16_ptr(ObjectClass *klass, const char *name,
const uint16_t *v,
- ObjectPropertyFlags flags,
- Error **errp)
+ ObjectPropertyFlags flags)
{
ObjectPropertyAccessor *getter = NULL;
ObjectPropertyAccessor *setter = NULL;
@@ -2660,13 +2541,13 @@
}
return object_class_property_add(klass, name, "uint16",
- getter, setter, NULL, (void *)v, errp);
+ getter, setter, NULL, (void *)v);
}
-void object_property_add_uint32_ptr(Object *obj, const char *name,
- const uint32_t *v,
- ObjectPropertyFlags flags,
- Error **errp)
+ObjectProperty *
+object_property_add_uint32_ptr(Object *obj, const char *name,
+ const uint32_t *v,
+ ObjectPropertyFlags flags)
{
ObjectPropertyAccessor *getter = NULL;
ObjectPropertyAccessor *setter = NULL;
@@ -2679,15 +2560,14 @@
setter = property_set_uint32_ptr;
}
- object_property_add(obj, name, "uint32",
- getter, setter, NULL, (void *)v, errp);
+ return object_property_add(obj, name, "uint32",
+ getter, setter, NULL, (void *)v);
}
ObjectProperty *
object_class_property_add_uint32_ptr(ObjectClass *klass, const char *name,
const uint32_t *v,
- ObjectPropertyFlags flags,
- Error **errp)
+ ObjectPropertyFlags flags)
{
ObjectPropertyAccessor *getter = NULL;
ObjectPropertyAccessor *setter = NULL;
@@ -2701,13 +2581,13 @@
}
return object_class_property_add(klass, name, "uint32",
- getter, setter, NULL, (void *)v, errp);
+ getter, setter, NULL, (void *)v);
}
-void object_property_add_uint64_ptr(Object *obj, const char *name,
- const uint64_t *v,
- ObjectPropertyFlags flags,
- Error **errp)
+ObjectProperty *
+object_property_add_uint64_ptr(Object *obj, const char *name,
+ const uint64_t *v,
+ ObjectPropertyFlags flags)
{
ObjectPropertyAccessor *getter = NULL;
ObjectPropertyAccessor *setter = NULL;
@@ -2720,15 +2600,14 @@
setter = property_set_uint64_ptr;
}
- object_property_add(obj, name, "uint64",
- getter, setter, NULL, (void *)v, errp);
+ return object_property_add(obj, name, "uint64",
+ getter, setter, NULL, (void *)v);
}
ObjectProperty *
object_class_property_add_uint64_ptr(ObjectClass *klass, const char *name,
const uint64_t *v,
- ObjectPropertyFlags flags,
- Error **errp)
+ ObjectPropertyFlags flags)
{
ObjectPropertyAccessor *getter = NULL;
ObjectPropertyAccessor *setter = NULL;
@@ -2742,7 +2621,7 @@
}
return object_class_property_add(klass, name, "uint64",
- getter, setter, NULL, (void *)v, errp);
+ getter, setter, NULL, (void *)v);
}
typedef struct {
@@ -2767,7 +2646,7 @@
}
static Object *property_resolve_alias(Object *obj, void *opaque,
- const gchar *part)
+ const char *part)
{
AliasProperty *prop = opaque;
@@ -2782,20 +2661,17 @@
g_free(prop);
}
-void object_property_add_alias(Object *obj, const char *name,
- Object *target_obj, const char *target_name,
- Error **errp)
+ObjectProperty *
+object_property_add_alias(Object *obj, const char *name,
+ Object *target_obj, const char *target_name)
{
AliasProperty *prop;
ObjectProperty *op;
ObjectProperty *target_prop;
- gchar *prop_type;
- Error *local_err = NULL;
+ g_autofree char *prop_type = NULL;
- target_prop = object_property_find(target_obj, target_name, errp);
- if (!target_prop) {
- return;
- }
+ target_prop = object_property_find(target_obj, target_name,
+ &error_abort);
if (object_property_is_child(target_prop)) {
prop_type = g_strdup_printf("link%s",
@@ -2812,52 +2688,34 @@
property_get_alias,
property_set_alias,
property_release_alias,
- prop, &local_err);
- if (local_err) {
- error_propagate(errp, local_err);
- g_free(prop);
- goto out;
- }
+ prop);
op->resolve = property_resolve_alias;
if (target_prop->defval) {
op->defval = qobject_ref(target_prop->defval);
}
object_property_set_description(obj, op->name,
- target_prop->description,
- &error_abort);
-
-out:
- g_free(prop_type);
+ target_prop->description);
+ return op;
}
void object_property_set_description(Object *obj, const char *name,
- const char *description, Error **errp)
+ const char *description)
{
ObjectProperty *op;
- op = object_property_find(obj, name, errp);
- if (!op) {
- return;
- }
-
+ op = object_property_find(obj, name, &error_abort);
g_free(op->description);
op->description = g_strdup(description);
}
void object_class_property_set_description(ObjectClass *klass,
const char *name,
- const char *description,
- Error **errp)
+ const char *description)
{
ObjectProperty *op;
op = g_hash_table_lookup(klass->properties, name);
- if (!op) {
- error_setg(errp, "Property '.%s' not found", name);
- return;
- }
-
g_free(op->description);
op->description = g_strdup(description);
}
@@ -2865,7 +2723,7 @@
static void object_class_init(ObjectClass *klass, void *data)
{
object_class_property_add_str(klass, "type", qdev_get_type,
- NULL, &error_abort);
+ NULL);
}
static void register_types(void)
diff --git a/qom/object_interfaces.c b/qom/object_interfaces.c
index bc36f96..7e26f86 100644
--- a/qom/object_interfaces.c
+++ b/qom/object_interfaces.c
@@ -83,17 +83,13 @@
if (id != NULL) {
object_property_add_child(object_get_objects_root(),
- id, obj, &local_err);
- if (local_err) {
- goto out;
- }
+ id, obj);
}
user_creatable_complete(USER_CREATABLE(obj), &local_err);
if (local_err) {
if (id != NULL) {
- object_property_del(object_get_objects_root(),
- id, &error_abort);
+ object_property_del(object_get_objects_root(), id);
}
goto out;
}
diff --git a/qom/qom-hmp-cmds.c b/qom/qom-hmp-cmds.c
index cd08233..f704b69 100644
--- a/qom/qom-hmp-cmds.c
+++ b/qom/qom-hmp-cmds.c
@@ -12,6 +12,8 @@
#include "qapi/error.h"
#include "qapi/qapi-commands-qom.h"
#include "qapi/qmp/qdict.h"
+#include "qapi/qmp/qjson.h"
+#include "qapi/qmp/qstring.h"
#include "qom/object.h"
void hmp_qom_list(Monitor *mon, const QDict *qdict)
@@ -46,19 +48,29 @@
const char *property = qdict_get_str(qdict, "property");
const char *value = qdict_get_str(qdict, "value");
Error *err = NULL;
- bool ambiguous = false;
- Object *obj;
+ QObject *obj;
- obj = object_resolve_path(path, &ambiguous);
- if (obj == NULL) {
- error_set(&err, ERROR_CLASS_DEVICE_NOT_FOUND,
- "Device '%s' not found", path);
- } else {
- if (ambiguous) {
- monitor_printf(mon, "Warning: Path '%s' is ambiguous\n", path);
- }
- object_property_parse(obj, value, property, &err);
+ obj = qobject_from_json(value, &err);
+ if (err == NULL) {
+ qmp_qom_set(path, property, obj, &err);
}
+
+ hmp_handle_error(mon, err);
+}
+
+void hmp_qom_get(Monitor *mon, const QDict *qdict)
+{
+ const char *path = qdict_get_str(qdict, "path");
+ const char *property = qdict_get_str(qdict, "property");
+ Error *err = NULL;
+ QObject *obj = qmp_qom_get(path, property, &err);
+
+ if (err == NULL) {
+ QString *str = qobject_to_json_pretty(obj);
+ monitor_printf(mon, "%s\n", qstring_get_str(str));
+ qobject_unref(str);
+ }
+
hmp_handle_error(mon, err);
}
diff --git a/roms/openbios b/roms/openbios
index 7e5b89e..4704d9e 160000
--- a/roms/openbios
+++ b/roms/openbios
@@ -1 +1 @@
-Subproject commit 7e5b89e4295063d8eba55b9c8ce8bc681c2d129a
+Subproject commit 4704d9eba6d8017dc694c077ca4205ffd8becad8
diff --git a/scripts/analyze-migration.py b/scripts/analyze-migration.py
index 96a31d3..95838cb 100755
--- a/scripts/analyze-migration.py
+++ b/scripts/analyze-migration.py
@@ -25,11 +25,6 @@
import sys
-MIN_PYTHON = (3, 2)
-if sys.version_info < MIN_PYTHON:
- sys.exit("Python %s.%s or later is required.\n" % MIN_PYTHON)
-
-
def mkdir_p(path):
try:
os.makedirs(path)
diff --git a/scripts/decodetree.py b/scripts/decodetree.py
index 46ab917..f9d204a 100755
--- a/scripts/decodetree.py
+++ b/scripts/decodetree.py
@@ -75,13 +75,6 @@
output_fd.write(a)
-if sys.version_info >= (3, 4):
- re_fullmatch = re.fullmatch
-else:
- def re_fullmatch(pat, str):
- return re.match('^' + pat + '$', str)
-
-
def output_autogen():
output('/* This file is autogenerated by scripts/decodetree.py. */\n\n')
@@ -428,18 +421,18 @@
width = 0
func = None
for t in toks:
- if re_fullmatch('!function=' + re_ident, t):
+ if re.fullmatch('!function=' + re_ident, t):
if func:
error(lineno, 'duplicate function')
func = t.split('=')
func = func[1]
continue
- if re_fullmatch('[0-9]+:s[0-9]+', t):
+ if re.fullmatch('[0-9]+:s[0-9]+', t):
# Signed field extract
subtoks = t.split(':s')
sign = True
- elif re_fullmatch('[0-9]+:[0-9]+', t):
+ elif re.fullmatch('[0-9]+:[0-9]+', t):
# Unsigned field extract
subtoks = t.split(':')
sign = False
@@ -488,11 +481,11 @@
flds = []
extern = False
for t in toks:
- if re_fullmatch('!extern', t):
+ if re.fullmatch('!extern', t):
extern = True
anyextern = True
continue
- if not re_fullmatch(re_ident, t):
+ if not re.fullmatch(re_ident, t):
error(lineno, 'invalid argument set token "{0}"'.format(t))
if t in flds:
error(lineno, 'duplicate argument "{0}"'.format(t))
@@ -621,13 +614,13 @@
continue
# 'Foo=%Bar' imports a field with a different name.
- if re_fullmatch(re_ident + '=%' + re_ident, t):
+ if re.fullmatch(re_ident + '=%' + re_ident, t):
(fname, iname) = t.split('=%')
flds = add_field_byname(lineno, flds, fname, iname)
continue
# 'Foo=number' sets an argument field to a constant value
- if re_fullmatch(re_ident + '=[+-]?[0-9]+', t):
+ if re.fullmatch(re_ident + '=[+-]?[0-9]+', t):
(fname, value) = t.split('=')
value = int(value)
flds = add_field(lineno, flds, fname, ConstField(value))
@@ -635,7 +628,7 @@
# Pattern of 0s, 1s, dots and dashes indicate required zeros,
# required ones, or dont-cares.
- if re_fullmatch('[01.-]+', t):
+ if re.fullmatch('[01.-]+', t):
shift = len(t)
fms = t.replace('0', '1')
fms = fms.replace('.', '0')
@@ -652,7 +645,7 @@
fixedmask = (fixedmask << shift) | fms
undefmask = (undefmask << shift) | ubm
# Otherwise, fieldname:fieldwidth
- elif re_fullmatch(re_ident + ':s?[0-9]+', t):
+ elif re.fullmatch(re_ident + ':s?[0-9]+', t):
(fname, flen) = t.split(':')
sign = False
if flen[0] == 's':
diff --git a/scripts/kvm/vmxcap b/scripts/kvm/vmxcap
index 971ed0e..6fe66d5 100755
--- a/scripts/kvm/vmxcap
+++ b/scripts/kvm/vmxcap
@@ -1,4 +1,4 @@
-#!/usr/bin/python
+#!/usr/bin/env python3
#
# tool for querying VMX capabilities
#
@@ -275,5 +275,6 @@
),
]
-for c in controls:
- c.show()
+if __name__ == '__main__':
+ for c in controls:
+ c.show()
diff --git a/scripts/modules/module_block.py b/scripts/modules/module_block.py
index f23191f..1109df8 100644
--- a/scripts/modules/module_block.py
+++ b/scripts/modules/module_block.py
@@ -1,4 +1,4 @@
-#!/usr/bin/python
+#!/usr/bin/env python3
#
# Module information generator
#
@@ -80,19 +80,20 @@
#endif
''')
-# First argument: output file
-# All other arguments: modules source files (.c)
-output_file = sys.argv[1]
-with open(output_file, 'w') as fheader:
- print_top(fheader)
+if __name__ == '__main__':
+ # First argument: output file
+ # All other arguments: modules source files (.c)
+ output_file = sys.argv[1]
+ with open(output_file, 'w') as fheader:
+ print_top(fheader)
- for filename in sys.argv[2:]:
- if os.path.isfile(filename):
- process_file(fheader, filename)
- else:
- print("File " + filename + " does not exist.", file=sys.stderr)
- sys.exit(1)
+ for filename in sys.argv[2:]:
+ if os.path.isfile(filename):
+ process_file(fheader, filename)
+ else:
+ print("File " + filename + " does not exist.", file=sys.stderr)
+ sys.exit(1)
- print_bottom(fheader)
+ print_bottom(fheader)
-sys.exit(0)
+ sys.exit(0)
diff --git a/scripts/qemu-gdb.py b/scripts/qemu-gdb.py
index f2a305c..e0bfa7b 100644
--- a/scripts/qemu-gdb.py
+++ b/scripts/qemu-gdb.py
@@ -1,5 +1,5 @@
-#!/usr/bin/python
-
+#!/usr/bin/env python3
+#
# GDB debugging support
#
# Copyright 2012 Red Hat, Inc. and/or its affiliates
diff --git a/scripts/qemugdb/__init__.py b/scripts/qemugdb/__init__.py
index 969f552..da8ff61 100644
--- a/scripts/qemugdb/__init__.py
+++ b/scripts/qemugdb/__init__.py
@@ -1,5 +1,4 @@
-#!/usr/bin/python
-
+#
# GDB debugging support
#
# Copyright (c) 2015 Linaro Ltd
diff --git a/scripts/qemugdb/aio.py b/scripts/qemugdb/aio.py
index 2ba00c4..d7c1ba0 100644
--- a/scripts/qemugdb/aio.py
+++ b/scripts/qemugdb/aio.py
@@ -1,5 +1,4 @@
-#!/usr/bin/python
-
+#
# GDB debugging support: aio/iohandler debug
#
# Copyright (c) 2015 Red Hat, Inc.
diff --git a/scripts/qemugdb/coroutine.py b/scripts/qemugdb/coroutine.py
index 41e079d..db61389 100644
--- a/scripts/qemugdb/coroutine.py
+++ b/scripts/qemugdb/coroutine.py
@@ -1,5 +1,4 @@
-#!/usr/bin/python
-
+#
# GDB debugging support
#
# Copyright 2012 Red Hat, Inc. and/or its affiliates
diff --git a/scripts/qemugdb/mtree.py b/scripts/qemugdb/mtree.py
index 3030a60..8fe42c3 100644
--- a/scripts/qemugdb/mtree.py
+++ b/scripts/qemugdb/mtree.py
@@ -1,5 +1,4 @@
-#!/usr/bin/python
-
+#
# GDB debugging support
#
# Copyright 2012 Red Hat, Inc. and/or its affiliates
@@ -84,4 +83,3 @@
while not isnull(subregion):
self.print_item(subregion, addr, level)
subregion = subregion['subregions_link']['tqe_next']
-
diff --git a/scripts/qemugdb/tcg.py b/scripts/qemugdb/tcg.py
index 18880fc..16c03c0 100644
--- a/scripts/qemugdb/tcg.py
+++ b/scripts/qemugdb/tcg.py
@@ -1,4 +1,3 @@
-#!/usr/bin/python
# -*- coding: utf-8 -*-
#
# GDB debugging support, TCG status
diff --git a/scripts/qemugdb/timers.py b/scripts/qemugdb/timers.py
index f0e132d..46537b2 100644
--- a/scripts/qemugdb/timers.py
+++ b/scripts/qemugdb/timers.py
@@ -1,4 +1,3 @@
-#!/usr/bin/python
# -*- coding: utf-8 -*-
# GDB debugging support
#
diff --git a/scripts/qmp/qmp b/scripts/qmp/qmp
index 0625fc2..8e52e4a 100755
--- a/scripts/qmp/qmp
+++ b/scripts/qmp/qmp
@@ -11,7 +11,9 @@
# See the COPYING file in the top-level directory.
import sys, os
-from qmp import QEMUMonitorProtocol
+
+sys.path.append(os.path.join(os.path.dirname(__file__), '..', '..', 'python'))
+from qemu.qmp import QEMUMonitorProtocol
def print_response(rsp, prefix=[]):
if type(rsp) == list:
diff --git a/scripts/qmp/qmp-shell b/scripts/qmp/qmp-shell
index a01d31d..c5eef06 100755
--- a/scripts/qmp/qmp-shell
+++ b/scripts/qmp/qmp-shell
@@ -77,9 +77,6 @@
sys.path.append(os.path.join(os.path.dirname(__file__), '..', '..', 'python'))
from qemu import qmp
-if sys.version_info[0] == 2:
- input = raw_input
-
class QMPCompleter(list):
def complete(self, text, state):
for cmd in self:
diff --git a/scripts/qmp/qom-fuse b/scripts/qmp/qom-fuse
index 6bada2c..5fa6b3b 100755
--- a/scripts/qmp/qom-fuse
+++ b/scripts/qmp/qom-fuse
@@ -15,7 +15,9 @@
from fuse import Fuse
import os, posix
from errno import *
-from qmp import QEMUMonitorProtocol
+
+sys.path.append(os.path.join(os.path.dirname(__file__), '..', '..', 'python'))
+from qemu.qmp import QEMUMonitorProtocol
fuse.fuse_python_api = (0, 2)
diff --git a/scripts/qmp/qom-get b/scripts/qmp/qom-get
index 007b4cd..666df71 100755
--- a/scripts/qmp/qom-get
+++ b/scripts/qmp/qom-get
@@ -1,4 +1,4 @@
-#!/usr/bin/python
+#!/usr/bin/env python3
##
# QEMU Object Model test tools
#
@@ -13,7 +13,9 @@
import sys
import os
-from qmp import QEMUMonitorProtocol
+
+sys.path.append(os.path.join(os.path.dirname(__file__), '..', '..', 'python'))
+from qemu.qmp import QEMUMonitorProtocol
cmd, args = sys.argv[0], sys.argv[1:]
socket_path = None
diff --git a/scripts/qmp/qom-list b/scripts/qmp/qom-list
index 03bda34..5074fd9 100755
--- a/scripts/qmp/qom-list
+++ b/scripts/qmp/qom-list
@@ -1,4 +1,4 @@
-#!/usr/bin/python
+#!/usr/bin/env python3
##
# QEMU Object Model test tools
#
@@ -13,7 +13,9 @@
import sys
import os
-from qmp import QEMUMonitorProtocol
+
+sys.path.append(os.path.join(os.path.dirname(__file__), '..', '..', 'python'))
+from qemu.qmp import QEMUMonitorProtocol
cmd, args = sys.argv[0], sys.argv[1:]
socket_path = None
diff --git a/scripts/qmp/qom-set b/scripts/qmp/qom-set
index c37fe78..240a781 100755
--- a/scripts/qmp/qom-set
+++ b/scripts/qmp/qom-set
@@ -1,4 +1,4 @@
-#!/usr/bin/python
+#!/usr/bin/env python3
##
# QEMU Object Model test tools
#
@@ -13,7 +13,9 @@
import sys
import os
-from qmp import QEMUMonitorProtocol
+
+sys.path.append(os.path.join(os.path.dirname(__file__), '..', '..', 'python'))
+from qemu.qmp import QEMUMonitorProtocol
cmd, args = sys.argv[0], sys.argv[1:]
socket_path = None
diff --git a/scripts/qmp/qom-tree b/scripts/qmp/qom-tree
index 1c8acf6..25b0781 100755
--- a/scripts/qmp/qom-tree
+++ b/scripts/qmp/qom-tree
@@ -1,4 +1,4 @@
-#!/usr/bin/python
+#!/usr/bin/env python3
##
# QEMU Object Model test tools
#
@@ -15,7 +15,9 @@
import sys
import os
-from qmp import QEMUMonitorProtocol
+
+sys.path.append(os.path.join(os.path.dirname(__file__), '..', '..', 'python'))
+from qemu.qmp import QEMUMonitorProtocol
cmd, args = sys.argv[0], sys.argv[1:]
socket_path = None
diff --git a/scsi/pr-manager-helper.c b/scsi/pr-manager-helper.c
index ca27c93..bf62cbe 100644
--- a/scsi/pr-manager-helper.c
+++ b/scsi/pr-manager-helper.c
@@ -307,8 +307,7 @@
PRManagerClass *prmgr_klass = PR_MANAGER_CLASS(klass);
UserCreatableClass *uc_klass = USER_CREATABLE_CLASS(klass);
- object_class_property_add_str(klass, "path", get_path, set_path,
- &error_abort);
+ object_class_property_add_str(klass, "path", get_path, set_path);
uc_klass->complete = pr_manager_helper_complete;
prmgr_klass->run = pr_manager_helper_run;
prmgr_klass->is_connected = pr_manager_helper_is_connected;
diff --git a/scsi/qemu-pr-helper.c b/scsi/qemu-pr-helper.c
index 181ed4a..57ad830 100644
--- a/scsi/qemu-pr-helper.c
+++ b/scsi/qemu-pr-helper.c
@@ -1030,8 +1030,8 @@
server_ioc = qio_channel_socket_new_fd(FIRST_SOCKET_ACTIVATION_FD,
&local_err);
if (server_ioc == NULL) {
- error_report("Failed to use socket activation: %s",
- error_get_pretty(local_err));
+ error_reportf_err(local_err,
+ "Failed to use socket activation: ");
exit(EXIT_FAILURE);
}
}
diff --git a/softmmu/vl.c b/softmmu/vl.c
index afd2615..ae5451b 100644
--- a/softmmu/vl.c
+++ b/softmmu/vl.c
@@ -2802,7 +2802,7 @@
}
object_property_set_int(obj, ms->ram_size, "size", &error_fatal);
object_property_add_child(object_get_objects_root(), mc->default_ram_id,
- obj, &error_fatal);
+ obj);
/* Ensure backend's memory region name is equal to mc->default_ram_id */
object_property_set_bool(obj, false, "x-use-canonical-path-for-ramblock-id",
&error_fatal);
@@ -3531,8 +3531,10 @@
no_shutdown = 1;
break;
case QEMU_OPTION_show_cursor:
- warn_report("The -show-cursor option is deprecated, "
- "use -display {sdl,gtk},show-cursor=on instead");
+ warn_report("The -show-cursor option is deprecated. Please "
+ "add show-cursor=on to your -display options.");
+ warn_report("When using the default display you can use "
+ "-display default,show-cursor=on");
dpy.has_show_cursor = true;
dpy.show_cursor = true;
break;
@@ -3878,11 +3880,10 @@
exit(0);
}
object_property_add_child(object_get_root(), "machine",
- OBJECT(current_machine), &error_abort);
+ OBJECT(current_machine));
object_property_add_child(container_get(OBJECT(current_machine),
"/unattached"),
- "sysbus", OBJECT(sysbus_get_default()),
- NULL);
+ "sysbus", OBJECT(sysbus_get_default()));
if (machine_class->minimum_page_bits) {
if (!set_preferred_target_page_bits(machine_class->minimum_page_bits)) {
diff --git a/stubs/Makefile.objs b/stubs/Makefile.objs
index 45be5dc..6a9e313 100644
--- a/stubs/Makefile.objs
+++ b/stubs/Makefile.objs
@@ -32,6 +32,7 @@
stub-obj-y += uuid.o
stub-obj-y += vm-stop.o
stub-obj-y += vmstate.o
+stub-obj-y += win32-kbd-hook.o
stub-obj-y += fd-register.o
stub-obj-y += qmp_memory_device.o
stub-obj-y += target-monitor-defs.o
diff --git a/stubs/ramfb.c b/stubs/ramfb.c
index 0799093..48143f3 100644
--- a/stubs/ramfb.c
+++ b/stubs/ramfb.c
@@ -6,7 +6,7 @@
{
}
-RAMFBState *ramfb_setup(DeviceState* dev, Error **errp)
+RAMFBState *ramfb_setup(Error **errp)
{
error_setg(errp, "ramfb support not available");
return NULL;
diff --git a/stubs/win32-kbd-hook.c b/stubs/win32-kbd-hook.c
new file mode 100644
index 0000000..1a084b0
--- /dev/null
+++ b/stubs/win32-kbd-hook.c
@@ -0,0 +1,18 @@
+/*
+ * Win32 keyboard hook stubs
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or
+ * (at your option) any later version. See the COPYING file in the
+ * top-level directory.
+ */
+
+#include "qemu/osdep.h"
+#include "ui/win32-kbd-hook.h"
+
+void win32_kbd_set_window(void *hwnd)
+{
+}
+
+void win32_kbd_set_grab(bool grab)
+{
+}
diff --git a/target/alpha/cpu-param.h b/target/alpha/cpu-param.h
index 692aee2..1153992 100644
--- a/target/alpha/cpu-param.h
+++ b/target/alpha/cpu-param.h
@@ -10,22 +10,11 @@
#define TARGET_LONG_BITS 64
#define TARGET_PAGE_BITS 13
-#ifdef CONFIG_USER_ONLY
-/*
- * ??? The kernel likes to give addresses in high memory. If the host has
- * more virtual address space than the guest, this can lead to impossible
- * allocations. Honor the long-standing assumption that only kernel addrs
- * are negative, but otherwise allow allocations anywhere. This could lead
- * to tricky emulation problems for programs doing tagged addressing, but
- * that's far fewer than encounter the impossible allocation problem.
- */
-#define TARGET_PHYS_ADDR_SPACE_BITS 63
-#define TARGET_VIRT_ADDR_SPACE_BITS 63
-#else
+
/* ??? EV4 has 34 phys addr bits, EV5 has 40, EV6 has 44. */
#define TARGET_PHYS_ADDR_SPACE_BITS 44
#define TARGET_VIRT_ADDR_SPACE_BITS (30 + TARGET_PAGE_BITS)
-#endif
+
#define NB_MMU_MODES 3
#endif
diff --git a/target/arm/cpu.c b/target/arm/cpu.c
index 3794f0d..32bec15 100644
--- a/target/arm/cpu.c
+++ b/target/arm/cpu.c
@@ -1179,8 +1179,7 @@
TYPE_MEMORY_REGION,
(Object **)&cpu->secure_memory,
qdev_prop_allow_set_link_before_realize,
- OBJ_PROP_LINK_STRONG,
- &error_abort);
+ OBJ_PROP_LINK_STRONG);
}
if (arm_feature(&cpu->env, ARM_FEATURE_EL2)) {
@@ -1190,8 +1189,7 @@
if (arm_feature(&cpu->env, ARM_FEATURE_PMU)) {
cpu->has_pmu = true;
- object_property_add_bool(obj, "pmu", arm_get_pmu, arm_set_pmu,
- &error_abort);
+ object_property_add_bool(obj, "pmu", arm_get_pmu, arm_set_pmu);
}
/*
@@ -1231,8 +1229,7 @@
if (arm_feature(&cpu->env, ARM_FEATURE_M_SECURITY)) {
object_property_add_link(obj, "idau", TYPE_IDAU_INTERFACE, &cpu->idau,
qdev_prop_allow_set_link_before_realize,
- OBJ_PROP_LINK_STRONG,
- &error_abort);
+ OBJ_PROP_LINK_STRONG);
/*
* M profile: initial value of the Secure VTOR. We can't just use
* a simple DEFINE_PROP_UINT32 for this because we want to permit
@@ -1240,7 +1237,7 @@
*/
object_property_add_uint32_ptr(obj, "init-svtor",
&cpu->init_svtor,
- OBJ_PROP_FLAG_READWRITE, &error_abort);
+ OBJ_PROP_FLAG_READWRITE);
}
qdev_property_add_static(DEVICE(obj), &arm_cpu_cfgend_property);
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
index 676f216..677584e 100644
--- a/target/arm/cpu.h
+++ b/target/arm/cpu.h
@@ -28,6 +28,10 @@
/* ARM processors have a weak memory model */
#define TCG_GUEST_DEFAULT_MO (0)
+#ifdef TARGET_AARCH64
+#define KVM_HAVE_MCE_INJECTION 1
+#endif
+
#define EXCP_UDEF 1 /* undefined instruction */
#define EXCP_SWI 2 /* software interrupt */
#define EXCP_PREFETCH_ABORT 3
@@ -1226,7 +1230,7 @@
#define CACHED_CPSR_BITS (CPSR_T | CPSR_AIF | CPSR_GE | CPSR_IT | CPSR_Q \
| CPSR_NZCV)
/* Bits writable in user mode. */
-#define CPSR_USER (CPSR_NZCV | CPSR_Q | CPSR_GE)
+#define CPSR_USER (CPSR_NZCV | CPSR_Q | CPSR_GE | CPSR_E)
/* Execution state bits. MRS read as zero, MSR writes ignored. */
#define CPSR_EXEC (CPSR_T | CPSR_IT | CPSR_J | CPSR_IL)
diff --git a/target/arm/cpu64.c b/target/arm/cpu64.c
index f5c49ee..cbc5c38 100644
--- a/target/arm/cpu64.c
+++ b/target/arm/cpu64.c
@@ -571,13 +571,13 @@
uint32_t vq;
object_property_add(obj, "sve", "bool", cpu_arm_get_sve,
- cpu_arm_set_sve, NULL, NULL, &error_fatal);
+ cpu_arm_set_sve, NULL, NULL);
for (vq = 1; vq <= ARM_MAX_VQ; ++vq) {
char name[8];
sprintf(name, "sve%d", vq * 128);
object_property_add(obj, name, "bool", cpu_arm_get_sve_vq,
- cpu_arm_set_sve_vq, NULL, NULL, &error_fatal);
+ cpu_arm_set_sve_vq, NULL, NULL);
}
}
@@ -726,7 +726,7 @@
aarch64_add_sve_properties(obj);
object_property_add(obj, "sve-max-vq", "uint32", cpu_max_get_sve_max_vq,
- cpu_max_set_sve_max_vq, NULL, NULL, &error_fatal);
+ cpu_max_set_sve_max_vq, NULL, NULL);
}
static const ARMCPUInfo aarch64_cpus[] = {
@@ -767,11 +767,10 @@
static void aarch64_cpu_initfn(Object *obj)
{
object_property_add_bool(obj, "aarch64", aarch64_cpu_get_aarch64,
- aarch64_cpu_set_aarch64, NULL);
+ aarch64_cpu_set_aarch64);
object_property_set_description(obj, "aarch64",
"Set on/off to enable/disable aarch64 "
- "execution state ",
- NULL);
+ "execution state ");
}
static void aarch64_cpu_finalizefn(Object *obj)
diff --git a/target/arm/cpu_tcg.c b/target/arm/cpu_tcg.c
index 591baef..00b0e08 100644
--- a/target/arm/cpu_tcg.c
+++ b/target/arm/cpu_tcg.c
@@ -605,6 +605,7 @@
#endif
cc->cpu_exec_interrupt = arm_v7m_cpu_exec_interrupt;
+ cc->gdb_core_xml_file = "arm-m-profile.xml";
}
static const ARMCPUInfo arm_tcg_cpus[] = {
diff --git a/target/arm/gdbstub.c b/target/arm/gdbstub.c
index 063551d..ecfa88f 100644
--- a/target/arm/gdbstub.c
+++ b/target/arm/gdbstub.c
@@ -57,8 +57,12 @@
}
return gdb_get_reg32(mem_buf, 0);
case 25:
- /* CPSR */
- return gdb_get_reg32(mem_buf, cpsr_read(env));
+ /* CPSR, or XPSR for M-profile */
+ if (arm_feature(env, ARM_FEATURE_M)) {
+ return gdb_get_reg32(mem_buf, xpsr_read(env));
+ } else {
+ return gdb_get_reg32(mem_buf, cpsr_read(env));
+ }
}
/* Unknown register. */
return 0;
@@ -98,8 +102,18 @@
}
return 4;
case 25:
- /* CPSR */
- cpsr_write(env, tmp, 0xffffffff, CPSRWriteByGDBStub);
+ /* CPSR, or XPSR for M-profile */
+ if (arm_feature(env, ARM_FEATURE_M)) {
+ /*
+ * Don't allow writing to XPSR.Exception as it can cause
+ * a transition into or out of handler mode (it's not
+ * writeable via the MSR insn so this is a reasonable
+ * restriction). Other fields are safe to update.
+ */
+ xpsr_write(env, tmp, ~XPSR_EXCP);
+ } else {
+ cpsr_write(env, tmp, 0xffffffff, CPSRWriteByGDBStub);
+ }
return 4;
}
/* Unknown register. */
diff --git a/target/arm/helper.c b/target/arm/helper.c
index b88d278..a92ae55 100644
--- a/target/arm/helper.c
+++ b/target/arm/helper.c
@@ -3465,7 +3465,7 @@
* Report exception with ESR indicating a fault due to a
* translation table walk for a cache maintenance instruction.
*/
- syn = syn_data_abort_no_iss(current_el == target_el,
+ syn = syn_data_abort_no_iss(current_el == target_el, 0,
fi.ea, 1, fi.s1ptw, 1, fsc);
env->exception.vaddress = value;
env->exception.fsr = fsr;
diff --git a/target/arm/helper.h b/target/arm/helper.h
index 5817626..49336dc 100644
--- a/target/arm/helper.h
+++ b/target/arm/helper.h
@@ -203,16 +203,16 @@
DEF_HELPER_4(vfp_muladdd, f64, f64, f64, f64, ptr)
DEF_HELPER_4(vfp_muladds, f32, f32, f32, f32, ptr)
-DEF_HELPER_3(recps_f32, f32, f32, f32, env)
-DEF_HELPER_3(rsqrts_f32, f32, f32, f32, env)
+DEF_HELPER_3(recps_f32, f32, env, f32, f32)
+DEF_HELPER_3(rsqrts_f32, f32, env, f32, f32)
DEF_HELPER_FLAGS_2(recpe_f16, TCG_CALL_NO_RWG, f16, f16, ptr)
DEF_HELPER_FLAGS_2(recpe_f32, TCG_CALL_NO_RWG, f32, f32, ptr)
DEF_HELPER_FLAGS_2(recpe_f64, TCG_CALL_NO_RWG, f64, f64, ptr)
DEF_HELPER_FLAGS_2(rsqrte_f16, TCG_CALL_NO_RWG, f16, f16, ptr)
DEF_HELPER_FLAGS_2(rsqrte_f32, TCG_CALL_NO_RWG, f32, f32, ptr)
DEF_HELPER_FLAGS_2(rsqrte_f64, TCG_CALL_NO_RWG, f64, f64, ptr)
-DEF_HELPER_2(recpe_u32, i32, i32, ptr)
-DEF_HELPER_FLAGS_2(rsqrte_u32, TCG_CALL_NO_RWG, i32, i32, ptr)
+DEF_HELPER_FLAGS_1(recpe_u32, TCG_CALL_NO_RWG, i32, i32)
+DEF_HELPER_FLAGS_1(rsqrte_u32, TCG_CALL_NO_RWG, i32, i32)
DEF_HELPER_FLAGS_4(neon_tbl, TCG_CALL_NO_RWG, i32, i32, i32, ptr, i32)
DEF_HELPER_3(shl_cc, i32, env, i32, i32)
@@ -284,13 +284,6 @@
DEF_HELPER_2(neon_pmax_u16, i32, i32, i32)
DEF_HELPER_2(neon_pmax_s16, i32, i32, i32)
-DEF_HELPER_2(neon_abd_u8, i32, i32, i32)
-DEF_HELPER_2(neon_abd_s8, i32, i32, i32)
-DEF_HELPER_2(neon_abd_u16, i32, i32, i32)
-DEF_HELPER_2(neon_abd_s16, i32, i32, i32)
-DEF_HELPER_2(neon_abd_u32, i32, i32, i32)
-DEF_HELPER_2(neon_abd_s32, i32, i32, i32)
-
DEF_HELPER_2(neon_shl_u16, i32, i32, i32)
DEF_HELPER_2(neon_shl_s16, i32, i32, i32)
DEF_HELPER_2(neon_rshl_u8, i32, i32, i32)
@@ -403,7 +396,6 @@
DEF_HELPER_FLAGS_2(neon_qneg_s32, TCG_CALL_NO_RWG, i32, env, i32)
DEF_HELPER_FLAGS_2(neon_qneg_s64, TCG_CALL_NO_RWG, i64, env, i64)
-DEF_HELPER_3(neon_abd_f32, i32, i32, i32, ptr)
DEF_HELPER_3(neon_ceq_f32, i32, i32, i32, ptr)
DEF_HELPER_3(neon_cge_f32, i32, i32, i32, ptr)
DEF_HELPER_3(neon_cgt_f32, i32, i32, i32, ptr)
@@ -602,6 +594,8 @@
DEF_HELPER_FLAGS_5(gvec_fmul_s, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, ptr, i32)
DEF_HELPER_FLAGS_5(gvec_fmul_d, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, ptr, i32)
+DEF_HELPER_FLAGS_5(gvec_fabd_s, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, ptr, i32)
+
DEF_HELPER_FLAGS_5(gvec_ftsmul_h, TCG_CALL_NO_RWG,
void, ptr, ptr, ptr, ptr, i32)
DEF_HELPER_FLAGS_5(gvec_ftsmul_s, TCG_CALL_NO_RWG,
@@ -691,6 +685,66 @@
DEF_HELPER_FLAGS_4(neon_pmull_h, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
+DEF_HELPER_FLAGS_3(gvec_ssra_b, TCG_CALL_NO_RWG, void, ptr, ptr, i32)
+DEF_HELPER_FLAGS_3(gvec_ssra_h, TCG_CALL_NO_RWG, void, ptr, ptr, i32)
+DEF_HELPER_FLAGS_3(gvec_ssra_s, TCG_CALL_NO_RWG, void, ptr, ptr, i32)
+DEF_HELPER_FLAGS_3(gvec_ssra_d, TCG_CALL_NO_RWG, void, ptr, ptr, i32)
+
+DEF_HELPER_FLAGS_3(gvec_usra_b, TCG_CALL_NO_RWG, void, ptr, ptr, i32)
+DEF_HELPER_FLAGS_3(gvec_usra_h, TCG_CALL_NO_RWG, void, ptr, ptr, i32)
+DEF_HELPER_FLAGS_3(gvec_usra_s, TCG_CALL_NO_RWG, void, ptr, ptr, i32)
+DEF_HELPER_FLAGS_3(gvec_usra_d, TCG_CALL_NO_RWG, void, ptr, ptr, i32)
+
+DEF_HELPER_FLAGS_3(gvec_srshr_b, TCG_CALL_NO_RWG, void, ptr, ptr, i32)
+DEF_HELPER_FLAGS_3(gvec_srshr_h, TCG_CALL_NO_RWG, void, ptr, ptr, i32)
+DEF_HELPER_FLAGS_3(gvec_srshr_s, TCG_CALL_NO_RWG, void, ptr, ptr, i32)
+DEF_HELPER_FLAGS_3(gvec_srshr_d, TCG_CALL_NO_RWG, void, ptr, ptr, i32)
+
+DEF_HELPER_FLAGS_3(gvec_urshr_b, TCG_CALL_NO_RWG, void, ptr, ptr, i32)
+DEF_HELPER_FLAGS_3(gvec_urshr_h, TCG_CALL_NO_RWG, void, ptr, ptr, i32)
+DEF_HELPER_FLAGS_3(gvec_urshr_s, TCG_CALL_NO_RWG, void, ptr, ptr, i32)
+DEF_HELPER_FLAGS_3(gvec_urshr_d, TCG_CALL_NO_RWG, void, ptr, ptr, i32)
+
+DEF_HELPER_FLAGS_3(gvec_srsra_b, TCG_CALL_NO_RWG, void, ptr, ptr, i32)
+DEF_HELPER_FLAGS_3(gvec_srsra_h, TCG_CALL_NO_RWG, void, ptr, ptr, i32)
+DEF_HELPER_FLAGS_3(gvec_srsra_s, TCG_CALL_NO_RWG, void, ptr, ptr, i32)
+DEF_HELPER_FLAGS_3(gvec_srsra_d, TCG_CALL_NO_RWG, void, ptr, ptr, i32)
+
+DEF_HELPER_FLAGS_3(gvec_ursra_b, TCG_CALL_NO_RWG, void, ptr, ptr, i32)
+DEF_HELPER_FLAGS_3(gvec_ursra_h, TCG_CALL_NO_RWG, void, ptr, ptr, i32)
+DEF_HELPER_FLAGS_3(gvec_ursra_s, TCG_CALL_NO_RWG, void, ptr, ptr, i32)
+DEF_HELPER_FLAGS_3(gvec_ursra_d, TCG_CALL_NO_RWG, void, ptr, ptr, i32)
+
+DEF_HELPER_FLAGS_3(gvec_sri_b, TCG_CALL_NO_RWG, void, ptr, ptr, i32)
+DEF_HELPER_FLAGS_3(gvec_sri_h, TCG_CALL_NO_RWG, void, ptr, ptr, i32)
+DEF_HELPER_FLAGS_3(gvec_sri_s, TCG_CALL_NO_RWG, void, ptr, ptr, i32)
+DEF_HELPER_FLAGS_3(gvec_sri_d, TCG_CALL_NO_RWG, void, ptr, ptr, i32)
+
+DEF_HELPER_FLAGS_3(gvec_sli_b, TCG_CALL_NO_RWG, void, ptr, ptr, i32)
+DEF_HELPER_FLAGS_3(gvec_sli_h, TCG_CALL_NO_RWG, void, ptr, ptr, i32)
+DEF_HELPER_FLAGS_3(gvec_sli_s, TCG_CALL_NO_RWG, void, ptr, ptr, i32)
+DEF_HELPER_FLAGS_3(gvec_sli_d, TCG_CALL_NO_RWG, void, ptr, ptr, i32)
+
+DEF_HELPER_FLAGS_4(gvec_sabd_b, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
+DEF_HELPER_FLAGS_4(gvec_sabd_h, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
+DEF_HELPER_FLAGS_4(gvec_sabd_s, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
+DEF_HELPER_FLAGS_4(gvec_sabd_d, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
+
+DEF_HELPER_FLAGS_4(gvec_uabd_b, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
+DEF_HELPER_FLAGS_4(gvec_uabd_h, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
+DEF_HELPER_FLAGS_4(gvec_uabd_s, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
+DEF_HELPER_FLAGS_4(gvec_uabd_d, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
+
+DEF_HELPER_FLAGS_4(gvec_saba_b, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
+DEF_HELPER_FLAGS_4(gvec_saba_h, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
+DEF_HELPER_FLAGS_4(gvec_saba_s, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
+DEF_HELPER_FLAGS_4(gvec_saba_d, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
+
+DEF_HELPER_FLAGS_4(gvec_uaba_b, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
+DEF_HELPER_FLAGS_4(gvec_uaba_h, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
+DEF_HELPER_FLAGS_4(gvec_uaba_s, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
+DEF_HELPER_FLAGS_4(gvec_uaba_d, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
+
#ifdef TARGET_AARCH64
#include "helper-a64.h"
#include "helper-sve.h"
diff --git a/target/arm/internals.h b/target/arm/internals.h
index a833e39..4bdbc3a 100644
--- a/target/arm/internals.h
+++ b/target/arm/internals.h
@@ -451,13 +451,14 @@
| ARM_EL_IL | (ea << 9) | (s1ptw << 7) | fsc;
}
-static inline uint32_t syn_data_abort_no_iss(int same_el,
+static inline uint32_t syn_data_abort_no_iss(int same_el, int fnv,
int ea, int cm, int s1ptw,
int wnr, int fsc)
{
return (EC_DATAABORT << ARM_EL_EC_SHIFT) | (same_el << ARM_EL_EC_SHIFT)
| ARM_EL_IL
- | (ea << 9) | (cm << 8) | (s1ptw << 7) | (wnr << 6) | fsc;
+ | (fnv << 10) | (ea << 9) | (cm << 8) | (s1ptw << 7)
+ | (wnr << 6) | fsc;
}
static inline uint32_t syn_data_abort_with_iss(int same_el,
diff --git a/target/arm/kvm.c b/target/arm/kvm.c
index 390077c..4bdbe6d 100644
--- a/target/arm/kvm.c
+++ b/target/arm/kvm.c
@@ -200,11 +200,11 @@
ARM_CPU(obj)->kvm_adjvtime = true;
object_property_add_bool(obj, "kvm-no-adjvtime", kvm_no_adjvtime_get,
- kvm_no_adjvtime_set, &error_abort);
+ kvm_no_adjvtime_set);
object_property_set_description(obj, "kvm-no-adjvtime",
"Set on to disable the adjustment of "
"the virtual counter. VM stopped time "
- "will be counted.", &error_abort);
+ "will be counted.");
}
bool kvm_arm_pmu_supported(CPUState *cpu)
diff --git a/target/arm/kvm64.c b/target/arm/kvm64.c
index cd8ab6b..f09ed9f 100644
--- a/target/arm/kvm64.c
+++ b/target/arm/kvm64.c
@@ -28,6 +28,9 @@
#include "sysemu/kvm_int.h"
#include "kvm_arm.h"
#include "internals.h"
+#include "hw/acpi/acpi.h"
+#include "hw/acpi/ghes.h"
+#include "hw/arm/virt.h"
static bool have_guest_debug;
@@ -883,6 +886,30 @@
return KVM_PUT_RUNTIME_STATE;
}
+/* Callers must hold the iothread mutex lock */
+static void kvm_inject_arm_sea(CPUState *c)
+{
+ ARMCPU *cpu = ARM_CPU(c);
+ CPUARMState *env = &cpu->env;
+ CPUClass *cc = CPU_GET_CLASS(c);
+ uint32_t esr;
+ bool same_el;
+
+ c->exception_index = EXCP_DATA_ABORT;
+ env->exception.target_el = 1;
+
+ /*
+ * Set the DFSC to synchronous external abort and set FnV to not valid,
+ * this will tell guest the FAR_ELx is UNKNOWN for this abort.
+ */
+ same_el = arm_current_el(env) == env->exception.target_el;
+ esr = syn_data_abort_no_iss(same_el, 1, 0, 0, 0, 0, 0x10);
+
+ env->exception.syndrome = esr;
+
+ cc->do_interrupt(c);
+}
+
#define AARCH64_CORE_REG(x) (KVM_REG_ARM64 | KVM_REG_SIZE_U64 | \
KVM_REG_ARM_CORE | KVM_REG_ARM_CORE_REG(x))
@@ -1316,6 +1343,56 @@
return ret;
}
+void kvm_arch_on_sigbus_vcpu(CPUState *c, int code, void *addr)
+{
+ ram_addr_t ram_addr;
+ hwaddr paddr;
+ Object *obj = qdev_get_machine();
+ VirtMachineState *vms = VIRT_MACHINE(obj);
+ bool acpi_enabled = virt_is_acpi_enabled(vms);
+
+ assert(code == BUS_MCEERR_AR || code == BUS_MCEERR_AO);
+
+ if (acpi_enabled && addr &&
+ object_property_get_bool(obj, "ras", NULL)) {
+ ram_addr = qemu_ram_addr_from_host(addr);
+ if (ram_addr != RAM_ADDR_INVALID &&
+ kvm_physical_memory_addr_from_host(c->kvm_state, addr, &paddr)) {
+ kvm_hwpoison_page_add(ram_addr);
+ /*
+ * If this is a BUS_MCEERR_AR, we know we have been called
+ * synchronously from the vCPU thread, so we can easily
+ * synchronize the state and inject an error.
+ *
+ * TODO: we currently don't tell the guest at all about
+ * BUS_MCEERR_AO. In that case we might either be being
+ * called synchronously from the vCPU thread, or a bit
+ * later from the main thread, so doing the injection of
+ * the error would be more complicated.
+ */
+ if (code == BUS_MCEERR_AR) {
+ kvm_cpu_synchronize_state(c);
+ if (!acpi_ghes_record_errors(ACPI_HEST_SRC_ID_SEA, paddr)) {
+ kvm_inject_arm_sea(c);
+ } else {
+ error_report("failed to record the error");
+ abort();
+ }
+ }
+ return;
+ }
+ if (code == BUS_MCEERR_AO) {
+ error_report("Hardware memory error at addr %p for memory used by "
+ "QEMU itself instead of guest system!", addr);
+ }
+ }
+
+ if (code == BUS_MCEERR_AR) {
+ error_report("Hardware memory error!");
+ exit(1);
+ }
+}
+
/* C6.6.29 BRK instruction */
static const uint32_t brk_insn = 0xd4200000;
diff --git a/target/arm/neon-dp.decode b/target/arm/neon-dp.decode
index ec3a92f..8beb1db 100644
--- a/target/arm/neon-dp.decode
+++ b/target/arm/neon-dp.decode
@@ -42,9 +42,23 @@
@3same .... ... . . . size:2 .... .... .... . q:1 . . .... \
&3same vm=%vm_dp vn=%vn_dp vd=%vd_dp
+@3same_q0 .... ... . . . size:2 .... .... .... . 0 . . .... \
+ &3same vm=%vm_dp vn=%vn_dp vd=%vd_dp q=0
+
+# For FP insns the high bit of 'size' is used as part of opcode decode
+@3same_fp .... ... . . . . size:1 .... .... .... . q:1 . . .... \
+ &3same vm=%vm_dp vn=%vn_dp vd=%vd_dp
+@3same_fp_q0 .... ... . . . . size:1 .... .... .... . 0 . . .... \
+ &3same vm=%vm_dp vn=%vn_dp vd=%vd_dp q=0
+
+VHADD_S_3s 1111 001 0 0 . .. .... .... 0000 . . . 0 .... @3same
+VHADD_U_3s 1111 001 1 0 . .. .... .... 0000 . . . 0 .... @3same
VQADD_S_3s 1111 001 0 0 . .. .... .... 0000 . . . 1 .... @3same
VQADD_U_3s 1111 001 1 0 . .. .... .... 0000 . . . 1 .... @3same
+VRHADD_S_3s 1111 001 0 0 . .. .... .... 0001 . . . 0 .... @3same
+VRHADD_U_3s 1111 001 1 0 . .. .... .... 0001 . . . 0 .... @3same
+
@3same_logic .... ... . . . .. .... .... .... . q:1 .. .... \
&3same vm=%vm_dp vn=%vn_dp vd=%vd_dp size=0
@@ -57,6 +71,9 @@
VBIT_3s 1111 001 1 0 . 10 .... .... 0001 ... 1 .... @3same_logic
VBIF_3s 1111 001 1 0 . 11 .... .... 0001 ... 1 .... @3same_logic
+VHSUB_S_3s 1111 001 0 0 . .. .... .... 0010 . . . 0 .... @3same
+VHSUB_U_3s 1111 001 1 0 . .. .... .... 0010 . . . 0 .... @3same
+
VQSUB_S_3s 1111 001 0 0 . .. .... .... 0010 . . . 1 .... @3same
VQSUB_U_3s 1111 001 1 0 . .. .... .... 0010 . . . 1 .... @3same
@@ -65,14 +82,64 @@
VCGE_S_3s 1111 001 0 0 . .. .... .... 0011 . . . 1 .... @3same
VCGE_U_3s 1111 001 1 0 . .. .... .... 0011 . . . 1 .... @3same
-VSHL_S_3s 1111 001 0 0 . .. .... .... 0100 . . . 0 .... @3same
-VSHL_U_3s 1111 001 1 0 . .. .... .... 0100 . . . 0 .... @3same
+# The _rev suffix indicates that Vn and Vm are reversed. This is
+# the case for shifts. In the Arm ARM these insns are documented
+# with the Vm and Vn fields in their usual places, but in the
+# assembly the operands are listed "backwards", ie in the order
+# Dd, Dm, Dn where other insns use Dd, Dn, Dm. For QEMU we choose
+# to consider Vm and Vn as being in different fields in the insn,
+# which allows us to avoid special-casing shifts in the trans_
+# function code. We would otherwise need to manually swap the operands
+# over to call Neon helper functions that are shared with AArch64,
+# which does not have this odd reversed-operand situation.
+@3same_rev .... ... . . . size:2 .... .... .... . q:1 . . .... \
+ &3same vn=%vm_dp vm=%vn_dp vd=%vd_dp
+
+VSHL_S_3s 1111 001 0 0 . .. .... .... 0100 . . . 0 .... @3same_rev
+VSHL_U_3s 1111 001 1 0 . .. .... .... 0100 . . . 0 .... @3same_rev
+
+# Insns operating on 64-bit elements (size!=0b11 handled elsewhere)
+# The _rev suffix indicates that Vn and Vm are reversed (as explained
+# by the comment for the @3same_rev format).
+@3same_64_rev .... ... . . . 11 .... .... .... . q:1 . . .... \
+ &3same vm=%vn_dp vn=%vm_dp vd=%vd_dp size=3
+
+{
+ VQSHL_S64_3s 1111 001 0 0 . .. .... .... 0100 . . . 1 .... @3same_64_rev
+ VQSHL_S_3s 1111 001 0 0 . .. .... .... 0100 . . . 1 .... @3same_rev
+}
+{
+ VQSHL_U64_3s 1111 001 1 0 . .. .... .... 0100 . . . 1 .... @3same_64_rev
+ VQSHL_U_3s 1111 001 1 0 . .. .... .... 0100 . . . 1 .... @3same_rev
+}
+{
+ VRSHL_S64_3s 1111 001 0 0 . .. .... .... 0101 . . . 0 .... @3same_64_rev
+ VRSHL_S_3s 1111 001 0 0 . .. .... .... 0101 . . . 0 .... @3same_rev
+}
+{
+ VRSHL_U64_3s 1111 001 1 0 . .. .... .... 0101 . . . 0 .... @3same_64_rev
+ VRSHL_U_3s 1111 001 1 0 . .. .... .... 0101 . . . 0 .... @3same_rev
+}
+{
+ VQRSHL_S64_3s 1111 001 0 0 . .. .... .... 0101 . . . 1 .... @3same_64_rev
+ VQRSHL_S_3s 1111 001 0 0 . .. .... .... 0101 . . . 1 .... @3same_rev
+}
+{
+ VQRSHL_U64_3s 1111 001 1 0 . .. .... .... 0101 . . . 1 .... @3same_64_rev
+ VQRSHL_U_3s 1111 001 1 0 . .. .... .... 0101 . . . 1 .... @3same_rev
+}
VMAX_S_3s 1111 001 0 0 . .. .... .... 0110 . . . 0 .... @3same
VMAX_U_3s 1111 001 1 0 . .. .... .... 0110 . . . 0 .... @3same
VMIN_S_3s 1111 001 0 0 . .. .... .... 0110 . . . 1 .... @3same
VMIN_U_3s 1111 001 1 0 . .. .... .... 0110 . . . 1 .... @3same
+VABD_S_3s 1111 001 0 0 . .. .... .... 0111 . . . 0 .... @3same
+VABD_U_3s 1111 001 1 0 . .. .... .... 0111 . . . 0 .... @3same
+
+VABA_S_3s 1111 001 0 0 . .. .... .... 0111 . . . 1 .... @3same
+VABA_U_3s 1111 001 1 0 . .. .... .... 0111 . . . 1 .... @3same
+
VADD_3s 1111 001 0 0 . .. .... .... 1000 . . . 0 .... @3same
VSUB_3s 1111 001 1 0 . .. .... .... 1000 . . . 0 .... @3same
@@ -84,3 +151,51 @@
VMUL_3s 1111 001 0 0 . .. .... .... 1001 . . . 1 .... @3same
VMUL_p_3s 1111 001 1 0 . .. .... .... 1001 . . . 1 .... @3same
+
+VPMAX_S_3s 1111 001 0 0 . .. .... .... 1010 . . . 0 .... @3same_q0
+VPMAX_U_3s 1111 001 1 0 . .. .... .... 1010 . . . 0 .... @3same_q0
+
+VPMIN_S_3s 1111 001 0 0 . .. .... .... 1010 . . . 1 .... @3same_q0
+VPMIN_U_3s 1111 001 1 0 . .. .... .... 1010 . . . 1 .... @3same_q0
+
+VQDMULH_3s 1111 001 0 0 . .. .... .... 1011 . . . 0 .... @3same
+VQRDMULH_3s 1111 001 1 0 . .. .... .... 1011 . . . 0 .... @3same
+
+VPADD_3s 1111 001 0 0 . .. .... .... 1011 . . . 1 .... @3same_q0
+
+VQRDMLAH_3s 1111 001 1 0 . .. .... .... 1011 ... 1 .... @3same
+
+SHA1_3s 1111 001 0 0 . optype:2 .... .... 1100 . 1 . 0 .... \
+ vm=%vm_dp vn=%vn_dp vd=%vd_dp
+SHA256H_3s 1111 001 1 0 . 00 .... .... 1100 . 1 . 0 .... \
+ vm=%vm_dp vn=%vn_dp vd=%vd_dp
+SHA256H2_3s 1111 001 1 0 . 01 .... .... 1100 . 1 . 0 .... \
+ vm=%vm_dp vn=%vn_dp vd=%vd_dp
+SHA256SU1_3s 1111 001 1 0 . 10 .... .... 1100 . 1 . 0 .... \
+ vm=%vm_dp vn=%vn_dp vd=%vd_dp
+
+VFMA_fp_3s 1111 001 0 0 . 0 . .... .... 1100 ... 1 .... @3same_fp
+VFMS_fp_3s 1111 001 0 0 . 1 . .... .... 1100 ... 1 .... @3same_fp
+
+VQRDMLSH_3s 1111 001 1 0 . .. .... .... 1100 ... 1 .... @3same
+
+VADD_fp_3s 1111 001 0 0 . 0 . .... .... 1101 ... 0 .... @3same_fp
+VSUB_fp_3s 1111 001 0 0 . 1 . .... .... 1101 ... 0 .... @3same_fp
+VPADD_fp_3s 1111 001 1 0 . 0 . .... .... 1101 ... 0 .... @3same_fp_q0
+VABD_fp_3s 1111 001 1 0 . 1 . .... .... 1101 ... 0 .... @3same_fp
+VMLA_fp_3s 1111 001 0 0 . 0 . .... .... 1101 ... 1 .... @3same_fp
+VMLS_fp_3s 1111 001 0 0 . 1 . .... .... 1101 ... 1 .... @3same_fp
+VMUL_fp_3s 1111 001 1 0 . 0 . .... .... 1101 ... 1 .... @3same_fp
+VCEQ_fp_3s 1111 001 0 0 . 0 . .... .... 1110 ... 0 .... @3same_fp
+VCGE_fp_3s 1111 001 1 0 . 0 . .... .... 1110 ... 0 .... @3same_fp
+VACGE_fp_3s 1111 001 1 0 . 0 . .... .... 1110 ... 1 .... @3same_fp
+VCGT_fp_3s 1111 001 1 0 . 1 . .... .... 1110 ... 0 .... @3same_fp
+VACGT_fp_3s 1111 001 1 0 . 1 . .... .... 1110 ... 1 .... @3same_fp
+VMAX_fp_3s 1111 001 0 0 . 0 . .... .... 1111 ... 0 .... @3same_fp
+VMIN_fp_3s 1111 001 0 0 . 1 . .... .... 1111 ... 0 .... @3same_fp
+VPMAX_fp_3s 1111 001 1 0 . 0 . .... .... 1111 ... 0 .... @3same_fp_q0
+VPMIN_fp_3s 1111 001 1 0 . 1 . .... .... 1111 ... 0 .... @3same_fp_q0
+VRECPS_fp_3s 1111 001 0 0 . 0 . .... .... 1111 ... 1 .... @3same_fp
+VRSQRTS_fp_3s 1111 001 0 0 . 1 . .... .... 1111 ... 1 .... @3same_fp
+VMAXNM_fp_3s 1111 001 1 0 . 0 . .... .... 1111 ... 1 .... @3same_fp
+VMINNM_fp_3s 1111 001 1 0 . 1 . .... .... 1111 ... 1 .... @3same_fp
diff --git a/target/arm/neon_helper.c b/target/arm/neon_helper.c
index 448be93..b637265 100644
--- a/target/arm/neon_helper.c
+++ b/target/arm/neon_helper.c
@@ -576,16 +576,6 @@
NEON_POP(pmax_u16, neon_u16, 2)
#undef NEON_FN
-#define NEON_FN(dest, src1, src2) \
- dest = (src1 > src2) ? (src1 - src2) : (src2 - src1)
-NEON_VOP(abd_s8, neon_s8, 4)
-NEON_VOP(abd_u8, neon_u8, 4)
-NEON_VOP(abd_s16, neon_s16, 2)
-NEON_VOP(abd_u16, neon_u16, 2)
-NEON_VOP(abd_s32, neon_s32, 1)
-NEON_VOP(abd_u32, neon_u32, 1)
-#undef NEON_FN
-
#define NEON_FN(dest, src1, src2) do { \
int8_t tmp; \
tmp = (int8_t)src2; \
@@ -1835,13 +1825,6 @@
}
/* NEON Float helpers. */
-uint32_t HELPER(neon_abd_f32)(uint32_t a, uint32_t b, void *fpstp)
-{
- float_status *fpst = fpstp;
- float32 f0 = make_float32(a);
- float32 f1 = make_float32(b);
- return float32_val(float32_abs(float32_sub(f0, f1, fpst)));
-}
/* Floating point comparisons produce an integer result.
* Note that EQ doesn't signal InvalidOp for QNaNs but GE and GT do.
diff --git a/target/arm/sve_helper.c b/target/arm/sve_helper.c
index 0da254d..e590db6 100644
--- a/target/arm/sve_helper.c
+++ b/target/arm/sve_helper.c
@@ -3201,7 +3201,7 @@
*/
static inline float32 sve_f16_to_f32(float16 f, float_status *fpst)
{
- flag save = get_flush_inputs_to_zero(fpst);
+ bool save = get_flush_inputs_to_zero(fpst);
float32 ret;
set_flush_inputs_to_zero(false, fpst);
@@ -3212,7 +3212,7 @@
static inline float64 sve_f16_to_f64(float16 f, float_status *fpst)
{
- flag save = get_flush_inputs_to_zero(fpst);
+ bool save = get_flush_inputs_to_zero(fpst);
float64 ret;
set_flush_inputs_to_zero(false, fpst);
@@ -3223,7 +3223,7 @@
static inline float16 sve_f32_to_f16(float32 f, float_status *fpst)
{
- flag save = get_flush_to_zero(fpst);
+ bool save = get_flush_to_zero(fpst);
float16 ret;
set_flush_to_zero(false, fpst);
@@ -3234,7 +3234,7 @@
static inline float16 sve_f64_to_f16(float64 f, float_status *fpst)
{
- flag save = get_flush_to_zero(fpst);
+ bool save = get_flush_to_zero(fpst);
float16 ret;
set_flush_to_zero(false, fpst);
diff --git a/target/arm/tlb_helper.c b/target/arm/tlb_helper.c
index e63f8bd..7388494 100644
--- a/target/arm/tlb_helper.c
+++ b/target/arm/tlb_helper.c
@@ -33,7 +33,7 @@
* ISV field.
*/
if (!(template_syn & ARM_EL_ISV) || target_el != 2 || s1ptw) {
- syn = syn_data_abort_no_iss(same_el,
+ syn = syn_data_abort_no_iss(same_el, 0,
ea, 0, s1ptw, is_write, fsc);
} else {
/*
diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
index 62e5729..874f3eb 100644
--- a/target/arm/translate-a64.c
+++ b/target/arm/translate-a64.c
@@ -496,14 +496,8 @@
unsigned ofs = fp_reg_offset(s, rd, MO_64);
unsigned vsz = vec_full_reg_size(s);
- if (!is_q) {
- TCGv_i64 tcg_zero = tcg_const_i64(0);
- tcg_gen_st_i64(tcg_zero, cpu_env, ofs + 8);
- tcg_temp_free_i64(tcg_zero);
- }
- if (vsz > 16) {
- tcg_gen_gvec_dup_imm(MO_64, ofs + 16, vsz - 16, vsz - 16, 0);
- }
+ /* Nop move, with side effect of clearing the tail. */
+ tcg_gen_gvec_mov(MO_64, ofs, ofs, is_q ? 16 : 8, vsz);
}
void write_fp_dreg(DisasContext *s, int reg, TCGv_i64 v)
@@ -577,33 +571,6 @@
is_q ? 16 : 8, vec_full_reg_size(s));
}
-/* Expand a 2-operand AdvSIMD vector operation using an op descriptor. */
-static void gen_gvec_op2(DisasContext *s, bool is_q, int rd,
- int rn, const GVecGen2 *gvec_op)
-{
- tcg_gen_gvec_2(vec_full_reg_offset(s, rd), vec_full_reg_offset(s, rn),
- is_q ? 16 : 8, vec_full_reg_size(s), gvec_op);
-}
-
-/* Expand a 2-operand + immediate AdvSIMD vector operation using
- * an op descriptor.
- */
-static void gen_gvec_op2i(DisasContext *s, bool is_q, int rd,
- int rn, int64_t imm, const GVecGen2i *gvec_op)
-{
- tcg_gen_gvec_2i(vec_full_reg_offset(s, rd), vec_full_reg_offset(s, rn),
- is_q ? 16 : 8, vec_full_reg_size(s), imm, gvec_op);
-}
-
-/* Expand a 3-operand AdvSIMD vector operation using an op descriptor. */
-static void gen_gvec_op3(DisasContext *s, bool is_q, int rd,
- int rn, int rm, const GVecGen3 *gvec_op)
-{
- tcg_gen_gvec_3(vec_full_reg_offset(s, rd), vec_full_reg_offset(s, rn),
- vec_full_reg_offset(s, rm), is_q ? 16 : 8,
- vec_full_reg_size(s), gvec_op);
-}
-
/* Expand a 3-operand operation using an out-of-line helper. */
static void gen_gvec_op3_ool(DisasContext *s, bool is_q, int rd,
int rn, int rm, int data, gen_helper_gvec_3 *fn)
@@ -614,18 +581,6 @@
is_q ? 16 : 8, vec_full_reg_size(s), data, fn);
}
-/* Expand a 3-operand + env pointer operation using
- * an out-of-line helper.
- */
-static void gen_gvec_op3_env(DisasContext *s, bool is_q, int rd,
- int rn, int rm, gen_helper_gvec_3_ptr *fn)
-{
- tcg_gen_gvec_3_ptr(vec_full_reg_offset(s, rd),
- vec_full_reg_offset(s, rn),
- vec_full_reg_offset(s, rm), cpu_env,
- is_q ? 16 : 8, vec_full_reg_size(s), 0, fn);
-}
-
/* Expand a 3-operand + fpstatus pointer + simd data value operation using
* an out-of-line helper.
*/
@@ -945,11 +900,10 @@
{
/* This always zero-extends and writes to a full 128 bit wide vector */
TCGv_i64 tmplo = tcg_temp_new_i64();
- TCGv_i64 tmphi;
+ TCGv_i64 tmphi = NULL;
if (size < 4) {
MemOp memop = s->be_data + size;
- tmphi = tcg_const_i64(0);
tcg_gen_qemu_ld_i64(tmplo, tcg_addr, get_mem_index(s), memop);
} else {
bool be = s->be_data == MO_BE;
@@ -967,12 +921,13 @@
}
tcg_gen_st_i64(tmplo, cpu_env, fp_reg_offset(s, destidx, MO_64));
- tcg_gen_st_i64(tmphi, cpu_env, fp_reg_hi_offset(s, destidx));
-
tcg_temp_free_i64(tmplo);
- tcg_temp_free_i64(tmphi);
- clear_vec_high(s, true, destidx);
+ if (tmphi) {
+ tcg_gen_st_i64(tmphi, cpu_env, fp_reg_hi_offset(s, destidx));
+ tcg_temp_free_i64(tmphi);
+ }
+ clear_vec_high(s, tmphi != NULL, destidx);
}
/*
@@ -6979,7 +6934,6 @@
read_vec_element(s, tcg_resh, rm, 0, MO_64);
do_ext64(s, tcg_resh, tcg_resl, pos);
}
- tcg_gen_movi_i64(tcg_resh, 0);
} else {
TCGv_i64 tcg_hh;
typedef struct {
@@ -7009,9 +6963,11 @@
write_vec_element(s, tcg_resl, rd, 0, MO_64);
tcg_temp_free_i64(tcg_resl);
- write_vec_element(s, tcg_resh, rd, 1, MO_64);
+ if (is_q) {
+ write_vec_element(s, tcg_resh, rd, 1, MO_64);
+ }
tcg_temp_free_i64(tcg_resh);
- clear_vec_high(s, true, rd);
+ clear_vec_high(s, is_q, rd);
}
/* TBL/TBX
@@ -7048,17 +7004,21 @@
* the input.
*/
tcg_resl = tcg_temp_new_i64();
- tcg_resh = tcg_temp_new_i64();
+ tcg_resh = NULL;
if (is_tblx) {
read_vec_element(s, tcg_resl, rd, 0, MO_64);
} else {
tcg_gen_movi_i64(tcg_resl, 0);
}
- if (is_tblx && is_q) {
- read_vec_element(s, tcg_resh, rd, 1, MO_64);
- } else {
- tcg_gen_movi_i64(tcg_resh, 0);
+
+ if (is_q) {
+ tcg_resh = tcg_temp_new_i64();
+ if (is_tblx) {
+ read_vec_element(s, tcg_resh, rd, 1, MO_64);
+ } else {
+ tcg_gen_movi_i64(tcg_resh, 0);
+ }
}
tcg_idx = tcg_temp_new_i64();
@@ -7078,9 +7038,12 @@
write_vec_element(s, tcg_resl, rd, 0, MO_64);
tcg_temp_free_i64(tcg_resl);
- write_vec_element(s, tcg_resh, rd, 1, MO_64);
- tcg_temp_free_i64(tcg_resh);
- clear_vec_high(s, true, rd);
+
+ if (is_q) {
+ write_vec_element(s, tcg_resh, rd, 1, MO_64);
+ tcg_temp_free_i64(tcg_resh);
+ }
+ clear_vec_high(s, is_q, rd);
}
/* ZIP/UZP/TRN
@@ -7117,7 +7080,7 @@
}
tcg_resl = tcg_const_i64(0);
- tcg_resh = tcg_const_i64(0);
+ tcg_resh = is_q ? tcg_const_i64(0) : NULL;
tcg_res = tcg_temp_new_i64();
for (i = 0; i < elements; i++) {
@@ -7168,9 +7131,12 @@
write_vec_element(s, tcg_resl, rd, 0, MO_64);
tcg_temp_free_i64(tcg_resl);
- write_vec_element(s, tcg_resh, rd, 1, MO_64);
- tcg_temp_free_i64(tcg_resh);
- clear_vec_high(s, true, rd);
+
+ if (is_q) {
+ write_vec_element(s, tcg_resh, rd, 1, MO_64);
+ tcg_temp_free_i64(tcg_resh);
+ }
+ clear_vec_high(s, is_q, rd);
}
/*
@@ -9726,7 +9692,7 @@
switch (opcode) {
case 0x3c: /* URECPE */
- gen_helper_recpe_u32(tcg_res, tcg_op, fpst);
+ gen_helper_recpe_u32(tcg_res, tcg_op);
break;
case 0x3d: /* FRECPE */
gen_helper_recpe_f32(tcg_res, tcg_op, fpst);
@@ -10165,16 +10131,7 @@
int size = 32 - clz32(immh) - 1;
int immhb = immh << 3 | immb;
int shift = 2 * (8 << size) - immhb;
- bool accumulate = false;
- int dsize = is_q ? 128 : 64;
- int esize = 8 << size;
- int elements = dsize/esize;
- MemOp memop = size | (is_u ? 0 : MO_SIGN);
- TCGv_i64 tcg_rn = new_tmp_a64(s);
- TCGv_i64 tcg_rd = new_tmp_a64(s);
- TCGv_i64 tcg_round;
- uint64_t round_const;
- int i;
+ GVecGen2iFn *gvec_fn;
if (extract32(immh, 3, 1) && !is_q) {
unallocated_encoding(s);
@@ -10188,27 +10145,12 @@
switch (opcode) {
case 0x02: /* SSRA / USRA (accumulate) */
- if (is_u) {
- /* Shift count same as element size produces zero to add. */
- if (shift == 8 << size) {
- goto done;
- }
- gen_gvec_op2i(s, is_q, rd, rn, shift, &usra_op[size]);
- } else {
- /* Shift count same as element size produces all sign to add. */
- if (shift == 8 << size) {
- shift -= 1;
- }
- gen_gvec_op2i(s, is_q, rd, rn, shift, &ssra_op[size]);
- }
- return;
+ gvec_fn = is_u ? gen_gvec_usra : gen_gvec_ssra;
+ break;
+
case 0x08: /* SRI */
- /* Shift count same as element size is valid but does nothing. */
- if (shift == 8 << size) {
- goto done;
- }
- gen_gvec_op2i(s, is_q, rd, rn, shift, &sri_op[size]);
- return;
+ gvec_fn = gen_gvec_sri;
+ break;
case 0x00: /* SSHR / USHR */
if (is_u) {
@@ -10216,45 +10158,31 @@
/* Shift count the same size as element size produces zero. */
tcg_gen_gvec_dup_imm(size, vec_full_reg_offset(s, rd),
is_q ? 16 : 8, vec_full_reg_size(s), 0);
- } else {
- gen_gvec_fn2i(s, is_q, rd, rn, shift, tcg_gen_gvec_shri, size);
+ return;
}
+ gvec_fn = tcg_gen_gvec_shri;
} else {
/* Shift count the same size as element size produces all sign. */
if (shift == 8 << size) {
shift -= 1;
}
- gen_gvec_fn2i(s, is_q, rd, rn, shift, tcg_gen_gvec_sari, size);
+ gvec_fn = tcg_gen_gvec_sari;
}
- return;
+ break;
case 0x04: /* SRSHR / URSHR (rounding) */
+ gvec_fn = is_u ? gen_gvec_urshr : gen_gvec_srshr;
break;
+
case 0x06: /* SRSRA / URSRA (accum + rounding) */
- accumulate = true;
+ gvec_fn = is_u ? gen_gvec_ursra : gen_gvec_srsra;
break;
+
default:
g_assert_not_reached();
}
- round_const = 1ULL << (shift - 1);
- tcg_round = tcg_const_i64(round_const);
-
- for (i = 0; i < elements; i++) {
- read_vec_element(s, tcg_rn, rn, i, memop);
- if (accumulate) {
- read_vec_element(s, tcg_rd, rd, i, memop);
- }
-
- handle_shri_with_rndacc(tcg_rd, tcg_rn, tcg_round,
- accumulate, is_u, size, shift);
-
- write_vec_element(s, tcg_rd, rd, i, size);
- }
- tcg_temp_free_i64(tcg_round);
-
- done:
- clear_vec_high(s, is_q, rd);
+ gen_gvec_fn2i(s, is_q, rd, rn, shift, gvec_fn, size);
}
/* SHL/SLI - Vector shift left */
@@ -10278,7 +10206,7 @@
}
if (insert) {
- gen_gvec_op2i(s, is_q, rd, rn, shift, &sli_op[size]);
+ gen_gvec_fn2i(s, is_q, rd, rn, shift, gen_gvec_sli, size);
} else {
gen_gvec_fn2i(s, is_q, rd, rn, shift, tcg_gen_gvec_shli, size);
}
@@ -11233,24 +11161,25 @@
switch (opcode) {
case 0x01: /* SQADD, UQADD */
- tcg_gen_gvec_4(vec_full_reg_offset(s, rd),
- offsetof(CPUARMState, vfp.qc),
- vec_full_reg_offset(s, rn),
- vec_full_reg_offset(s, rm),
- is_q ? 16 : 8, vec_full_reg_size(s),
- (u ? uqadd_op : sqadd_op) + size);
+ if (u) {
+ gen_gvec_fn3(s, is_q, rd, rn, rm, gen_gvec_uqadd_qc, size);
+ } else {
+ gen_gvec_fn3(s, is_q, rd, rn, rm, gen_gvec_sqadd_qc, size);
+ }
return;
case 0x05: /* SQSUB, UQSUB */
- tcg_gen_gvec_4(vec_full_reg_offset(s, rd),
- offsetof(CPUARMState, vfp.qc),
- vec_full_reg_offset(s, rn),
- vec_full_reg_offset(s, rm),
- is_q ? 16 : 8, vec_full_reg_size(s),
- (u ? uqsub_op : sqsub_op) + size);
+ if (u) {
+ gen_gvec_fn3(s, is_q, rd, rn, rm, gen_gvec_uqsub_qc, size);
+ } else {
+ gen_gvec_fn3(s, is_q, rd, rn, rm, gen_gvec_sqsub_qc, size);
+ }
return;
case 0x08: /* SSHL, USHL */
- gen_gvec_op3(s, is_q, rd, rn, rm,
- u ? &ushl_op[size] : &sshl_op[size]);
+ if (u) {
+ gen_gvec_fn3(s, is_q, rd, rn, rm, gen_gvec_ushl, size);
+ } else {
+ gen_gvec_fn3(s, is_q, rd, rn, rm, gen_gvec_sshl, size);
+ }
return;
case 0x0c: /* SMAX, UMAX */
if (u) {
@@ -11266,6 +11195,20 @@
gen_gvec_fn3(s, is_q, rd, rn, rm, tcg_gen_gvec_smin, size);
}
return;
+ case 0xe: /* SABD, UABD */
+ if (u) {
+ gen_gvec_fn3(s, is_q, rd, rn, rm, gen_gvec_uabd, size);
+ } else {
+ gen_gvec_fn3(s, is_q, rd, rn, rm, gen_gvec_sabd, size);
+ }
+ return;
+ case 0xf: /* SABA, UABA */
+ if (u) {
+ gen_gvec_fn3(s, is_q, rd, rn, rm, gen_gvec_uaba, size);
+ } else {
+ gen_gvec_fn3(s, is_q, rd, rn, rm, gen_gvec_saba, size);
+ }
+ return;
case 0x10: /* ADD, SUB */
if (u) {
gen_gvec_fn3(s, is_q, rd, rn, rm, tcg_gen_gvec_sub, size);
@@ -11282,14 +11225,14 @@
return;
case 0x12: /* MLA, MLS */
if (u) {
- gen_gvec_op3(s, is_q, rd, rn, rm, &mls_op[size]);
+ gen_gvec_fn3(s, is_q, rd, rn, rm, gen_gvec_mls, size);
} else {
- gen_gvec_op3(s, is_q, rd, rn, rm, &mla_op[size]);
+ gen_gvec_fn3(s, is_q, rd, rn, rm, gen_gvec_mla, size);
}
return;
case 0x11:
if (!u) { /* CMTST */
- gen_gvec_op3(s, is_q, rd, rn, rm, &cmtst_op[size]);
+ gen_gvec_fn3(s, is_q, rd, rn, rm, gen_gvec_cmtst, size);
return;
}
/* else CMEQ */
@@ -11398,17 +11341,6 @@
genenvfn = fns[size][u];
break;
}
- case 0xe: /* SABD, UABD */
- case 0xf: /* SABA, UABA */
- {
- static NeonGenTwoOpFn * const fns[3][2] = {
- { gen_helper_neon_abd_s8, gen_helper_neon_abd_u8 },
- { gen_helper_neon_abd_s16, gen_helper_neon_abd_u16 },
- { gen_helper_neon_abd_s32, gen_helper_neon_abd_u32 },
- };
- genfn = fns[size][u];
- break;
- }
case 0x16: /* SQDMULH, SQRDMULH */
{
static NeonGenTwoOpEnvFn * const fns[2][2] = {
@@ -11757,29 +11689,11 @@
switch (opcode) {
case 0x0: /* SQRDMLAH (vector) */
- switch (size) {
- case 1:
- gen_gvec_op3_env(s, is_q, rd, rn, rm, gen_helper_gvec_qrdmlah_s16);
- break;
- case 2:
- gen_gvec_op3_env(s, is_q, rd, rn, rm, gen_helper_gvec_qrdmlah_s32);
- break;
- default:
- g_assert_not_reached();
- }
+ gen_gvec_fn3(s, is_q, rd, rn, rm, gen_gvec_sqrdmlah_qc, size);
return;
case 0x1: /* SQRDMLSH (vector) */
- switch (size) {
- case 1:
- gen_gvec_op3_env(s, is_q, rd, rn, rm, gen_helper_gvec_qrdmlsh_s16);
- break;
- case 2:
- gen_gvec_op3_env(s, is_q, rd, rn, rm, gen_helper_gvec_qrdmlsh_s32);
- break;
- default:
- g_assert_not_reached();
- }
+ gen_gvec_fn3(s, is_q, rd, rn, rm, gen_gvec_sqrdmlsh_qc, size);
return;
case 0x2: /* SDOT / UDOT */
@@ -12308,7 +12222,6 @@
unallocated_encoding(s);
return;
}
- need_fpstatus = true;
break;
case 0x1e: /* FRINT32Z */
case 0x1f: /* FRINT64Z */
@@ -12358,13 +12271,21 @@
}
break;
case 0x8: /* CMGT, CMGE */
- gen_gvec_op2(s, is_q, rd, rn, u ? &cge0_op[size] : &cgt0_op[size]);
+ if (u) {
+ gen_gvec_fn2(s, is_q, rd, rn, gen_gvec_cge0, size);
+ } else {
+ gen_gvec_fn2(s, is_q, rd, rn, gen_gvec_cgt0, size);
+ }
return;
case 0x9: /* CMEQ, CMLE */
- gen_gvec_op2(s, is_q, rd, rn, u ? &cle0_op[size] : &ceq0_op[size]);
+ if (u) {
+ gen_gvec_fn2(s, is_q, rd, rn, gen_gvec_cle0, size);
+ } else {
+ gen_gvec_fn2(s, is_q, rd, rn, gen_gvec_ceq0, size);
+ }
return;
case 0xa: /* CMLT */
- gen_gvec_op2(s, is_q, rd, rn, &clt0_op[size]);
+ gen_gvec_fn2(s, is_q, rd, rn, gen_gvec_clt0, size);
return;
case 0xb:
if (u) { /* ABS, NEG */
@@ -12468,7 +12389,7 @@
gen_helper_rints_exact(tcg_res, tcg_op, tcg_fpstatus);
break;
case 0x7c: /* URSQRTE */
- gen_helper_rsqrte_u32(tcg_res, tcg_op, tcg_fpstatus);
+ gen_helper_rsqrte_u32(tcg_res, tcg_op);
break;
case 0x1e: /* FRINT32Z */
case 0x5e: /* FRINT32X */
diff --git a/target/arm/translate-neon.inc.c b/target/arm/translate-neon.inc.c
index 50b77b6..3fe65a0 100644
--- a/target/arm/translate-neon.inc.c
+++ b/target/arm/translate-neon.inc.c
@@ -603,6 +603,12 @@
DO_3SAME(VORR, tcg_gen_gvec_or)
DO_3SAME(VORN, tcg_gen_gvec_orc)
DO_3SAME(VEOR, tcg_gen_gvec_xor)
+DO_3SAME(VSHL_S, gen_gvec_sshl)
+DO_3SAME(VSHL_U, gen_gvec_ushl)
+DO_3SAME(VQADD_S, gen_gvec_sqadd_qc)
+DO_3SAME(VQADD_U, gen_gvec_uqadd_qc)
+DO_3SAME(VQSUB_S, gen_gvec_sqsub_qc)
+DO_3SAME(VQSUB_U, gen_gvec_uqsub_qc)
/* These insns are all gvec_bitsel but with the inputs in various orders. */
#define DO_3SAME_BITSEL(INSN, O1, O2, O3) \
@@ -632,6 +638,13 @@
DO_3SAME_NO_SZ_3(VMIN_S, tcg_gen_gvec_smin)
DO_3SAME_NO_SZ_3(VMIN_U, tcg_gen_gvec_umin)
DO_3SAME_NO_SZ_3(VMUL, tcg_gen_gvec_mul)
+DO_3SAME_NO_SZ_3(VMLA, gen_gvec_mla)
+DO_3SAME_NO_SZ_3(VMLS, gen_gvec_mls)
+DO_3SAME_NO_SZ_3(VTST, gen_gvec_cmtst)
+DO_3SAME_NO_SZ_3(VABD_S, gen_gvec_sabd)
+DO_3SAME_NO_SZ_3(VABA_S, gen_gvec_saba)
+DO_3SAME_NO_SZ_3(VABD_U, gen_gvec_uabd)
+DO_3SAME_NO_SZ_3(VABA_U, gen_gvec_uaba)
#define DO_3SAME_CMP(INSN, COND) \
static void gen_##INSN##_3s(unsigned vece, uint32_t rd_ofs, \
@@ -648,28 +661,6 @@
DO_3SAME_CMP(VCGE_U, TCG_COND_GEU)
DO_3SAME_CMP(VCEQ, TCG_COND_EQ)
-static void gen_VTST_3s(unsigned vece, uint32_t rd_ofs, uint32_t rn_ofs,
- uint32_t rm_ofs, uint32_t oprsz, uint32_t maxsz)
-{
- tcg_gen_gvec_3(rd_ofs, rn_ofs, rm_ofs, oprsz, maxsz, &cmtst_op[vece]);
-}
-DO_3SAME_NO_SZ_3(VTST, gen_VTST_3s)
-
-#define DO_3SAME_GVEC4(INSN, OPARRAY) \
- static void gen_##INSN##_3s(unsigned vece, uint32_t rd_ofs, \
- uint32_t rn_ofs, uint32_t rm_ofs, \
- uint32_t oprsz, uint32_t maxsz) \
- { \
- tcg_gen_gvec_4(rd_ofs, offsetof(CPUARMState, vfp.qc), \
- rn_ofs, rm_ofs, oprsz, maxsz, &OPARRAY[vece]); \
- } \
- DO_3SAME(INSN, gen_##INSN##_3s)
-
-DO_3SAME_GVEC4(VQADD_S, sqadd_op)
-DO_3SAME_GVEC4(VQADD_U, uqadd_op)
-DO_3SAME_GVEC4(VQSUB_S, sqsub_op)
-DO_3SAME_GVEC4(VQSUB_U, uqsub_op)
-
static void gen_VMUL_p_3s(unsigned vece, uint32_t rd_ofs, uint32_t rn_ofs,
uint32_t rm_ofs, uint32_t oprsz, uint32_t maxsz)
{
@@ -685,30 +676,637 @@
return do_3same(s, a, gen_VMUL_p_3s);
}
-#define DO_3SAME_GVEC3_NO_SZ_3(INSN, OPARRAY) \
+#define DO_VQRDMLAH(INSN, FUNC) \
+ static bool trans_##INSN##_3s(DisasContext *s, arg_3same *a) \
+ { \
+ if (!dc_isar_feature(aa32_rdm, s)) { \
+ return false; \
+ } \
+ if (a->size != 1 && a->size != 2) { \
+ return false; \
+ } \
+ return do_3same(s, a, FUNC); \
+ }
+
+DO_VQRDMLAH(VQRDMLAH, gen_gvec_sqrdmlah_qc)
+DO_VQRDMLAH(VQRDMLSH, gen_gvec_sqrdmlsh_qc)
+
+static bool trans_SHA1_3s(DisasContext *s, arg_SHA1_3s *a)
+{
+ TCGv_ptr ptr1, ptr2, ptr3;
+ TCGv_i32 tmp;
+
+ if (!arm_dc_feature(s, ARM_FEATURE_NEON) ||
+ !dc_isar_feature(aa32_sha1, s)) {
+ return false;
+ }
+
+ /* UNDEF accesses to D16-D31 if they don't exist. */
+ if (!dc_isar_feature(aa32_simd_r32, s) &&
+ ((a->vd | a->vn | a->vm) & 0x10)) {
+ return false;
+ }
+
+ if ((a->vn | a->vm | a->vd) & 1) {
+ return false;
+ }
+
+ if (!vfp_access_check(s)) {
+ return true;
+ }
+
+ ptr1 = vfp_reg_ptr(true, a->vd);
+ ptr2 = vfp_reg_ptr(true, a->vn);
+ ptr3 = vfp_reg_ptr(true, a->vm);
+ tmp = tcg_const_i32(a->optype);
+ gen_helper_crypto_sha1_3reg(ptr1, ptr2, ptr3, tmp);
+ tcg_temp_free_i32(tmp);
+ tcg_temp_free_ptr(ptr1);
+ tcg_temp_free_ptr(ptr2);
+ tcg_temp_free_ptr(ptr3);
+
+ return true;
+}
+
+static bool trans_SHA256H_3s(DisasContext *s, arg_SHA256H_3s *a)
+{
+ TCGv_ptr ptr1, ptr2, ptr3;
+
+ if (!arm_dc_feature(s, ARM_FEATURE_NEON) ||
+ !dc_isar_feature(aa32_sha2, s)) {
+ return false;
+ }
+
+ /* UNDEF accesses to D16-D31 if they don't exist. */
+ if (!dc_isar_feature(aa32_simd_r32, s) &&
+ ((a->vd | a->vn | a->vm) & 0x10)) {
+ return false;
+ }
+
+ if ((a->vn | a->vm | a->vd) & 1) {
+ return false;
+ }
+
+ if (!vfp_access_check(s)) {
+ return true;
+ }
+
+ ptr1 = vfp_reg_ptr(true, a->vd);
+ ptr2 = vfp_reg_ptr(true, a->vn);
+ ptr3 = vfp_reg_ptr(true, a->vm);
+ gen_helper_crypto_sha256h(ptr1, ptr2, ptr3);
+ tcg_temp_free_ptr(ptr1);
+ tcg_temp_free_ptr(ptr2);
+ tcg_temp_free_ptr(ptr3);
+
+ return true;
+}
+
+static bool trans_SHA256H2_3s(DisasContext *s, arg_SHA256H2_3s *a)
+{
+ TCGv_ptr ptr1, ptr2, ptr3;
+
+ if (!arm_dc_feature(s, ARM_FEATURE_NEON) ||
+ !dc_isar_feature(aa32_sha2, s)) {
+ return false;
+ }
+
+ /* UNDEF accesses to D16-D31 if they don't exist. */
+ if (!dc_isar_feature(aa32_simd_r32, s) &&
+ ((a->vd | a->vn | a->vm) & 0x10)) {
+ return false;
+ }
+
+ if ((a->vn | a->vm | a->vd) & 1) {
+ return false;
+ }
+
+ if (!vfp_access_check(s)) {
+ return true;
+ }
+
+ ptr1 = vfp_reg_ptr(true, a->vd);
+ ptr2 = vfp_reg_ptr(true, a->vn);
+ ptr3 = vfp_reg_ptr(true, a->vm);
+ gen_helper_crypto_sha256h2(ptr1, ptr2, ptr3);
+ tcg_temp_free_ptr(ptr1);
+ tcg_temp_free_ptr(ptr2);
+ tcg_temp_free_ptr(ptr3);
+
+ return true;
+}
+
+static bool trans_SHA256SU1_3s(DisasContext *s, arg_SHA256SU1_3s *a)
+{
+ TCGv_ptr ptr1, ptr2, ptr3;
+
+ if (!arm_dc_feature(s, ARM_FEATURE_NEON) ||
+ !dc_isar_feature(aa32_sha2, s)) {
+ return false;
+ }
+
+ /* UNDEF accesses to D16-D31 if they don't exist. */
+ if (!dc_isar_feature(aa32_simd_r32, s) &&
+ ((a->vd | a->vn | a->vm) & 0x10)) {
+ return false;
+ }
+
+ if ((a->vn | a->vm | a->vd) & 1) {
+ return false;
+ }
+
+ if (!vfp_access_check(s)) {
+ return true;
+ }
+
+ ptr1 = vfp_reg_ptr(true, a->vd);
+ ptr2 = vfp_reg_ptr(true, a->vn);
+ ptr3 = vfp_reg_ptr(true, a->vm);
+ gen_helper_crypto_sha256su1(ptr1, ptr2, ptr3);
+ tcg_temp_free_ptr(ptr1);
+ tcg_temp_free_ptr(ptr2);
+ tcg_temp_free_ptr(ptr3);
+
+ return true;
+}
+
+#define DO_3SAME_64(INSN, FUNC) \
static void gen_##INSN##_3s(unsigned vece, uint32_t rd_ofs, \
uint32_t rn_ofs, uint32_t rm_ofs, \
uint32_t oprsz, uint32_t maxsz) \
{ \
- tcg_gen_gvec_3(rd_ofs, rn_ofs, rm_ofs, \
- oprsz, maxsz, &OPARRAY[vece]); \
- } \
- DO_3SAME_NO_SZ_3(INSN, gen_##INSN##_3s)
-
-
-DO_3SAME_GVEC3_NO_SZ_3(VMLA, mla_op)
-DO_3SAME_GVEC3_NO_SZ_3(VMLS, mls_op)
-
-#define DO_3SAME_GVEC3_SHIFT(INSN, OPARRAY) \
- static void gen_##INSN##_3s(unsigned vece, uint32_t rd_ofs, \
- uint32_t rn_ofs, uint32_t rm_ofs, \
- uint32_t oprsz, uint32_t maxsz) \
- { \
- /* Note the operation is vshl vd,vm,vn */ \
- tcg_gen_gvec_3(rd_ofs, rm_ofs, rn_ofs, \
- oprsz, maxsz, &OPARRAY[vece]); \
+ static const GVecGen3 op = { .fni8 = FUNC }; \
+ tcg_gen_gvec_3(rd_ofs, rn_ofs, rm_ofs, oprsz, maxsz, &op); \
} \
DO_3SAME(INSN, gen_##INSN##_3s)
-DO_3SAME_GVEC3_SHIFT(VSHL_S, sshl_op)
-DO_3SAME_GVEC3_SHIFT(VSHL_U, ushl_op)
+#define DO_3SAME_64_ENV(INSN, FUNC) \
+ static void gen_##INSN##_elt(TCGv_i64 d, TCGv_i64 n, TCGv_i64 m) \
+ { \
+ FUNC(d, cpu_env, n, m); \
+ } \
+ DO_3SAME_64(INSN, gen_##INSN##_elt)
+
+DO_3SAME_64(VRSHL_S64, gen_helper_neon_rshl_s64)
+DO_3SAME_64(VRSHL_U64, gen_helper_neon_rshl_u64)
+DO_3SAME_64_ENV(VQSHL_S64, gen_helper_neon_qshl_s64)
+DO_3SAME_64_ENV(VQSHL_U64, gen_helper_neon_qshl_u64)
+DO_3SAME_64_ENV(VQRSHL_S64, gen_helper_neon_qrshl_s64)
+DO_3SAME_64_ENV(VQRSHL_U64, gen_helper_neon_qrshl_u64)
+
+#define DO_3SAME_32(INSN, FUNC) \
+ static void gen_##INSN##_3s(unsigned vece, uint32_t rd_ofs, \
+ uint32_t rn_ofs, uint32_t rm_ofs, \
+ uint32_t oprsz, uint32_t maxsz) \
+ { \
+ static const GVecGen3 ops[4] = { \
+ { .fni4 = gen_helper_neon_##FUNC##8 }, \
+ { .fni4 = gen_helper_neon_##FUNC##16 }, \
+ { .fni4 = gen_helper_neon_##FUNC##32 }, \
+ { 0 }, \
+ }; \
+ tcg_gen_gvec_3(rd_ofs, rn_ofs, rm_ofs, oprsz, maxsz, &ops[vece]); \
+ } \
+ static bool trans_##INSN##_3s(DisasContext *s, arg_3same *a) \
+ { \
+ if (a->size > 2) { \
+ return false; \
+ } \
+ return do_3same(s, a, gen_##INSN##_3s); \
+ }
+
+/*
+ * Some helper functions need to be passed the cpu_env. In order
+ * to use those with the gvec APIs like tcg_gen_gvec_3() we need
+ * to create wrapper functions whose prototype is a NeonGenTwoOpFn()
+ * and which call a NeonGenTwoOpEnvFn().
+ */
+#define WRAP_ENV_FN(WRAPNAME, FUNC) \
+ static void WRAPNAME(TCGv_i32 d, TCGv_i32 n, TCGv_i32 m) \
+ { \
+ FUNC(d, cpu_env, n, m); \
+ }
+
+#define DO_3SAME_32_ENV(INSN, FUNC) \
+ WRAP_ENV_FN(gen_##INSN##_tramp8, gen_helper_neon_##FUNC##8); \
+ WRAP_ENV_FN(gen_##INSN##_tramp16, gen_helper_neon_##FUNC##16); \
+ WRAP_ENV_FN(gen_##INSN##_tramp32, gen_helper_neon_##FUNC##32); \
+ static void gen_##INSN##_3s(unsigned vece, uint32_t rd_ofs, \
+ uint32_t rn_ofs, uint32_t rm_ofs, \
+ uint32_t oprsz, uint32_t maxsz) \
+ { \
+ static const GVecGen3 ops[4] = { \
+ { .fni4 = gen_##INSN##_tramp8 }, \
+ { .fni4 = gen_##INSN##_tramp16 }, \
+ { .fni4 = gen_##INSN##_tramp32 }, \
+ { 0 }, \
+ }; \
+ tcg_gen_gvec_3(rd_ofs, rn_ofs, rm_ofs, oprsz, maxsz, &ops[vece]); \
+ } \
+ static bool trans_##INSN##_3s(DisasContext *s, arg_3same *a) \
+ { \
+ if (a->size > 2) { \
+ return false; \
+ } \
+ return do_3same(s, a, gen_##INSN##_3s); \
+ }
+
+DO_3SAME_32(VHADD_S, hadd_s)
+DO_3SAME_32(VHADD_U, hadd_u)
+DO_3SAME_32(VHSUB_S, hsub_s)
+DO_3SAME_32(VHSUB_U, hsub_u)
+DO_3SAME_32(VRHADD_S, rhadd_s)
+DO_3SAME_32(VRHADD_U, rhadd_u)
+DO_3SAME_32(VRSHL_S, rshl_s)
+DO_3SAME_32(VRSHL_U, rshl_u)
+
+DO_3SAME_32_ENV(VQSHL_S, qshl_s)
+DO_3SAME_32_ENV(VQSHL_U, qshl_u)
+DO_3SAME_32_ENV(VQRSHL_S, qrshl_s)
+DO_3SAME_32_ENV(VQRSHL_U, qrshl_u)
+
+static bool do_3same_pair(DisasContext *s, arg_3same *a, NeonGenTwoOpFn *fn)
+{
+ /* Operations handled pairwise 32 bits at a time */
+ TCGv_i32 tmp, tmp2, tmp3;
+
+ if (!arm_dc_feature(s, ARM_FEATURE_NEON)) {
+ return false;
+ }
+
+ /* UNDEF accesses to D16-D31 if they don't exist. */
+ if (!dc_isar_feature(aa32_simd_r32, s) &&
+ ((a->vd | a->vn | a->vm) & 0x10)) {
+ return false;
+ }
+
+ if (a->size == 3) {
+ return false;
+ }
+
+ if (!vfp_access_check(s)) {
+ return true;
+ }
+
+ assert(a->q == 0); /* enforced by decode patterns */
+
+ /*
+ * Note that we have to be careful not to clobber the source operands
+ * in the "vm == vd" case by storing the result of the first pass too
+ * early. Since Q is 0 there are always just two passes, so instead
+ * of a complicated loop over each pass we just unroll.
+ */
+ tmp = neon_load_reg(a->vn, 0);
+ tmp2 = neon_load_reg(a->vn, 1);
+ fn(tmp, tmp, tmp2);
+ tcg_temp_free_i32(tmp2);
+
+ tmp3 = neon_load_reg(a->vm, 0);
+ tmp2 = neon_load_reg(a->vm, 1);
+ fn(tmp3, tmp3, tmp2);
+ tcg_temp_free_i32(tmp2);
+
+ neon_store_reg(a->vd, 0, tmp);
+ neon_store_reg(a->vd, 1, tmp3);
+ return true;
+}
+
+#define DO_3SAME_PAIR(INSN, func) \
+ static bool trans_##INSN##_3s(DisasContext *s, arg_3same *a) \
+ { \
+ static NeonGenTwoOpFn * const fns[] = { \
+ gen_helper_neon_##func##8, \
+ gen_helper_neon_##func##16, \
+ gen_helper_neon_##func##32, \
+ }; \
+ if (a->size > 2) { \
+ return false; \
+ } \
+ return do_3same_pair(s, a, fns[a->size]); \
+ }
+
+/* 32-bit pairwise ops end up the same as the elementwise versions. */
+#define gen_helper_neon_pmax_s32 tcg_gen_smax_i32
+#define gen_helper_neon_pmax_u32 tcg_gen_umax_i32
+#define gen_helper_neon_pmin_s32 tcg_gen_smin_i32
+#define gen_helper_neon_pmin_u32 tcg_gen_umin_i32
+#define gen_helper_neon_padd_u32 tcg_gen_add_i32
+
+DO_3SAME_PAIR(VPMAX_S, pmax_s)
+DO_3SAME_PAIR(VPMIN_S, pmin_s)
+DO_3SAME_PAIR(VPMAX_U, pmax_u)
+DO_3SAME_PAIR(VPMIN_U, pmin_u)
+DO_3SAME_PAIR(VPADD, padd_u)
+
+#define DO_3SAME_VQDMULH(INSN, FUNC) \
+ WRAP_ENV_FN(gen_##INSN##_tramp16, gen_helper_neon_##FUNC##_s16); \
+ WRAP_ENV_FN(gen_##INSN##_tramp32, gen_helper_neon_##FUNC##_s32); \
+ static void gen_##INSN##_3s(unsigned vece, uint32_t rd_ofs, \
+ uint32_t rn_ofs, uint32_t rm_ofs, \
+ uint32_t oprsz, uint32_t maxsz) \
+ { \
+ static const GVecGen3 ops[2] = { \
+ { .fni4 = gen_##INSN##_tramp16 }, \
+ { .fni4 = gen_##INSN##_tramp32 }, \
+ }; \
+ tcg_gen_gvec_3(rd_ofs, rn_ofs, rm_ofs, oprsz, maxsz, &ops[vece - 1]); \
+ } \
+ static bool trans_##INSN##_3s(DisasContext *s, arg_3same *a) \
+ { \
+ if (a->size != 1 && a->size != 2) { \
+ return false; \
+ } \
+ return do_3same(s, a, gen_##INSN##_3s); \
+ }
+
+DO_3SAME_VQDMULH(VQDMULH, qdmulh)
+DO_3SAME_VQDMULH(VQRDMULH, qrdmulh)
+
+static bool do_3same_fp(DisasContext *s, arg_3same *a, VFPGen3OpSPFn *fn,
+ bool reads_vd)
+{
+ /*
+ * FP operations handled elementwise 32 bits at a time.
+ * If reads_vd is true then the old value of Vd will be
+ * loaded before calling the callback function. This is
+ * used for multiply-accumulate type operations.
+ */
+ TCGv_i32 tmp, tmp2;
+ int pass;
+
+ if (!arm_dc_feature(s, ARM_FEATURE_NEON)) {
+ return false;
+ }
+
+ /* UNDEF accesses to D16-D31 if they don't exist. */
+ if (!dc_isar_feature(aa32_simd_r32, s) &&
+ ((a->vd | a->vn | a->vm) & 0x10)) {
+ return false;
+ }
+
+ if ((a->vn | a->vm | a->vd) & a->q) {
+ return false;
+ }
+
+ if (!vfp_access_check(s)) {
+ return true;
+ }
+
+ TCGv_ptr fpstatus = get_fpstatus_ptr(1);
+ for (pass = 0; pass < (a->q ? 4 : 2); pass++) {
+ tmp = neon_load_reg(a->vn, pass);
+ tmp2 = neon_load_reg(a->vm, pass);
+ if (reads_vd) {
+ TCGv_i32 tmp_rd = neon_load_reg(a->vd, pass);
+ fn(tmp_rd, tmp, tmp2, fpstatus);
+ neon_store_reg(a->vd, pass, tmp_rd);
+ tcg_temp_free_i32(tmp);
+ } else {
+ fn(tmp, tmp, tmp2, fpstatus);
+ neon_store_reg(a->vd, pass, tmp);
+ }
+ tcg_temp_free_i32(tmp2);
+ }
+ tcg_temp_free_ptr(fpstatus);
+ return true;
+}
+
+/*
+ * For all the functions using this macro, size == 1 means fp16,
+ * which is an architecture extension we don't implement yet.
+ */
+#define DO_3S_FP_GVEC(INSN,FUNC) \
+ static void gen_##INSN##_3s(unsigned vece, uint32_t rd_ofs, \
+ uint32_t rn_ofs, uint32_t rm_ofs, \
+ uint32_t oprsz, uint32_t maxsz) \
+ { \
+ TCGv_ptr fpst = get_fpstatus_ptr(1); \
+ tcg_gen_gvec_3_ptr(rd_ofs, rn_ofs, rm_ofs, fpst, \
+ oprsz, maxsz, 0, FUNC); \
+ tcg_temp_free_ptr(fpst); \
+ } \
+ static bool trans_##INSN##_fp_3s(DisasContext *s, arg_3same *a) \
+ { \
+ if (a->size != 0) { \
+ /* TODO fp16 support */ \
+ return false; \
+ } \
+ return do_3same(s, a, gen_##INSN##_3s); \
+ }
+
+
+DO_3S_FP_GVEC(VADD, gen_helper_gvec_fadd_s)
+DO_3S_FP_GVEC(VSUB, gen_helper_gvec_fsub_s)
+DO_3S_FP_GVEC(VABD, gen_helper_gvec_fabd_s)
+DO_3S_FP_GVEC(VMUL, gen_helper_gvec_fmul_s)
+
+/*
+ * For all the functions using this macro, size == 1 means fp16,
+ * which is an architecture extension we don't implement yet.
+ */
+#define DO_3S_FP(INSN,FUNC,READS_VD) \
+ static bool trans_##INSN##_fp_3s(DisasContext *s, arg_3same *a) \
+ { \
+ if (a->size != 0) { \
+ /* TODO fp16 support */ \
+ return false; \
+ } \
+ return do_3same_fp(s, a, FUNC, READS_VD); \
+ }
+
+DO_3S_FP(VCEQ, gen_helper_neon_ceq_f32, false)
+DO_3S_FP(VCGE, gen_helper_neon_cge_f32, false)
+DO_3S_FP(VCGT, gen_helper_neon_cgt_f32, false)
+DO_3S_FP(VACGE, gen_helper_neon_acge_f32, false)
+DO_3S_FP(VACGT, gen_helper_neon_acgt_f32, false)
+DO_3S_FP(VMAX, gen_helper_vfp_maxs, false)
+DO_3S_FP(VMIN, gen_helper_vfp_mins, false)
+
+static void gen_VMLA_fp_3s(TCGv_i32 vd, TCGv_i32 vn, TCGv_i32 vm,
+ TCGv_ptr fpstatus)
+{
+ gen_helper_vfp_muls(vn, vn, vm, fpstatus);
+ gen_helper_vfp_adds(vd, vd, vn, fpstatus);
+}
+
+static void gen_VMLS_fp_3s(TCGv_i32 vd, TCGv_i32 vn, TCGv_i32 vm,
+ TCGv_ptr fpstatus)
+{
+ gen_helper_vfp_muls(vn, vn, vm, fpstatus);
+ gen_helper_vfp_subs(vd, vd, vn, fpstatus);
+}
+
+DO_3S_FP(VMLA, gen_VMLA_fp_3s, true)
+DO_3S_FP(VMLS, gen_VMLS_fp_3s, true)
+
+static bool trans_VMAXNM_fp_3s(DisasContext *s, arg_3same *a)
+{
+ if (!arm_dc_feature(s, ARM_FEATURE_V8)) {
+ return false;
+ }
+
+ if (a->size != 0) {
+ /* TODO fp16 support */
+ return false;
+ }
+
+ return do_3same_fp(s, a, gen_helper_vfp_maxnums, false);
+}
+
+static bool trans_VMINNM_fp_3s(DisasContext *s, arg_3same *a)
+{
+ if (!arm_dc_feature(s, ARM_FEATURE_V8)) {
+ return false;
+ }
+
+ if (a->size != 0) {
+ /* TODO fp16 support */
+ return false;
+ }
+
+ return do_3same_fp(s, a, gen_helper_vfp_minnums, false);
+}
+
+WRAP_ENV_FN(gen_VRECPS_tramp, gen_helper_recps_f32)
+
+static void gen_VRECPS_fp_3s(unsigned vece, uint32_t rd_ofs,
+ uint32_t rn_ofs, uint32_t rm_ofs,
+ uint32_t oprsz, uint32_t maxsz)
+{
+ static const GVecGen3 ops = { .fni4 = gen_VRECPS_tramp };
+ tcg_gen_gvec_3(rd_ofs, rn_ofs, rm_ofs, oprsz, maxsz, &ops);
+}
+
+static bool trans_VRECPS_fp_3s(DisasContext *s, arg_3same *a)
+{
+ if (a->size != 0) {
+ /* TODO fp16 support */
+ return false;
+ }
+
+ return do_3same(s, a, gen_VRECPS_fp_3s);
+}
+
+WRAP_ENV_FN(gen_VRSQRTS_tramp, gen_helper_rsqrts_f32)
+
+static void gen_VRSQRTS_fp_3s(unsigned vece, uint32_t rd_ofs,
+ uint32_t rn_ofs, uint32_t rm_ofs,
+ uint32_t oprsz, uint32_t maxsz)
+{
+ static const GVecGen3 ops = { .fni4 = gen_VRSQRTS_tramp };
+ tcg_gen_gvec_3(rd_ofs, rn_ofs, rm_ofs, oprsz, maxsz, &ops);
+}
+
+static bool trans_VRSQRTS_fp_3s(DisasContext *s, arg_3same *a)
+{
+ if (a->size != 0) {
+ /* TODO fp16 support */
+ return false;
+ }
+
+ return do_3same(s, a, gen_VRSQRTS_fp_3s);
+}
+
+static void gen_VFMA_fp_3s(TCGv_i32 vd, TCGv_i32 vn, TCGv_i32 vm,
+ TCGv_ptr fpstatus)
+{
+ gen_helper_vfp_muladds(vd, vn, vm, vd, fpstatus);
+}
+
+static bool trans_VFMA_fp_3s(DisasContext *s, arg_3same *a)
+{
+ if (!dc_isar_feature(aa32_simdfmac, s)) {
+ return false;
+ }
+
+ if (a->size != 0) {
+ /* TODO fp16 support */
+ return false;
+ }
+
+ return do_3same_fp(s, a, gen_VFMA_fp_3s, true);
+}
+
+static void gen_VFMS_fp_3s(TCGv_i32 vd, TCGv_i32 vn, TCGv_i32 vm,
+ TCGv_ptr fpstatus)
+{
+ gen_helper_vfp_negs(vn, vn);
+ gen_helper_vfp_muladds(vd, vn, vm, vd, fpstatus);
+}
+
+static bool trans_VFMS_fp_3s(DisasContext *s, arg_3same *a)
+{
+ if (!dc_isar_feature(aa32_simdfmac, s)) {
+ return false;
+ }
+
+ if (a->size != 0) {
+ /* TODO fp16 support */
+ return false;
+ }
+
+ return do_3same_fp(s, a, gen_VFMS_fp_3s, true);
+}
+
+static bool do_3same_fp_pair(DisasContext *s, arg_3same *a, VFPGen3OpSPFn *fn)
+{
+ /* FP operations handled pairwise 32 bits at a time */
+ TCGv_i32 tmp, tmp2, tmp3;
+ TCGv_ptr fpstatus;
+
+ if (!arm_dc_feature(s, ARM_FEATURE_NEON)) {
+ return false;
+ }
+
+ /* UNDEF accesses to D16-D31 if they don't exist. */
+ if (!dc_isar_feature(aa32_simd_r32, s) &&
+ ((a->vd | a->vn | a->vm) & 0x10)) {
+ return false;
+ }
+
+ if (!vfp_access_check(s)) {
+ return true;
+ }
+
+ assert(a->q == 0); /* enforced by decode patterns */
+
+ /*
+ * Note that we have to be careful not to clobber the source operands
+ * in the "vm == vd" case by storing the result of the first pass too
+ * early. Since Q is 0 there are always just two passes, so instead
+ * of a complicated loop over each pass we just unroll.
+ */
+ fpstatus = get_fpstatus_ptr(1);
+ tmp = neon_load_reg(a->vn, 0);
+ tmp2 = neon_load_reg(a->vn, 1);
+ fn(tmp, tmp, tmp2, fpstatus);
+ tcg_temp_free_i32(tmp2);
+
+ tmp3 = neon_load_reg(a->vm, 0);
+ tmp2 = neon_load_reg(a->vm, 1);
+ fn(tmp3, tmp3, tmp2, fpstatus);
+ tcg_temp_free_i32(tmp2);
+ tcg_temp_free_ptr(fpstatus);
+
+ neon_store_reg(a->vd, 0, tmp);
+ neon_store_reg(a->vd, 1, tmp3);
+ return true;
+}
+
+/*
+ * For all the functions using this macro, size == 1 means fp16,
+ * which is an architecture extension we don't implement yet.
+ */
+#define DO_3S_FP_PAIR(INSN,FUNC) \
+ static bool trans_##INSN##_fp_3s(DisasContext *s, arg_3same *a) \
+ { \
+ if (a->size != 0) { \
+ /* TODO fp16 support */ \
+ return false; \
+ } \
+ return do_3same_fp_pair(s, a, FUNC); \
+ }
+
+DO_3S_FP_PAIR(VPADD, gen_helper_vfp_adds)
+DO_3S_FP_PAIR(VPMAX, gen_helper_vfp_maxs)
+DO_3S_FP_PAIR(VPMIN, gen_helper_vfp_mins)
diff --git a/target/arm/translate.c b/target/arm/translate.c
index 74fac1d..c829611 100644
--- a/target/arm/translate.c
+++ b/target/arm/translate.c
@@ -3011,12 +3011,6 @@
}
}
-/* 32-bit pairwise ops end up the same as the elementwise versions. */
-#define gen_helper_neon_pmax_s32 tcg_gen_smax_i32
-#define gen_helper_neon_pmax_u32 tcg_gen_umax_i32
-#define gen_helper_neon_pmin_s32 tcg_gen_smin_i32
-#define gen_helper_neon_pmin_u32 tcg_gen_umin_i32
-
#define GEN_NEON_INTEGER_OP_ENV(name) do { \
switch ((size << 1) | u) { \
case 0: \
@@ -3040,29 +3034,6 @@
default: return 1; \
}} while (0)
-#define GEN_NEON_INTEGER_OP(name) do { \
- switch ((size << 1) | u) { \
- case 0: \
- gen_helper_neon_##name##_s8(tmp, tmp, tmp2); \
- break; \
- case 1: \
- gen_helper_neon_##name##_u8(tmp, tmp, tmp2); \
- break; \
- case 2: \
- gen_helper_neon_##name##_s16(tmp, tmp, tmp2); \
- break; \
- case 3: \
- gen_helper_neon_##name##_u16(tmp, tmp, tmp2); \
- break; \
- case 4: \
- gen_helper_neon_##name##_s32(tmp, tmp, tmp2); \
- break; \
- case 5: \
- gen_helper_neon_##name##_u32(tmp, tmp, tmp2); \
- break; \
- default: return 1; \
- }} while (0)
-
static TCGv_i32 neon_load_scratch(int scratch)
{
TCGv_i32 tmp = tcg_temp_new_i32();
@@ -3397,78 +3368,6 @@
}
}
-/* Symbolic constants for op fields for Neon 3-register same-length.
- * The values correspond to bits [11:8,4]; see the ARM ARM DDI0406B
- * table A7-9.
- */
-#define NEON_3R_VHADD 0
-#define NEON_3R_VQADD 1
-#define NEON_3R_VRHADD 2
-#define NEON_3R_LOGIC 3 /* VAND,VBIC,VORR,VMOV,VORN,VEOR,VBIF,VBIT,VBSL */
-#define NEON_3R_VHSUB 4
-#define NEON_3R_VQSUB 5
-#define NEON_3R_VCGT 6
-#define NEON_3R_VCGE 7
-#define NEON_3R_VSHL 8
-#define NEON_3R_VQSHL 9
-#define NEON_3R_VRSHL 10
-#define NEON_3R_VQRSHL 11
-#define NEON_3R_VMAX 12
-#define NEON_3R_VMIN 13
-#define NEON_3R_VABD 14
-#define NEON_3R_VABA 15
-#define NEON_3R_VADD_VSUB 16
-#define NEON_3R_VTST_VCEQ 17
-#define NEON_3R_VML 18 /* VMLA, VMLS */
-#define NEON_3R_VMUL 19
-#define NEON_3R_VPMAX 20
-#define NEON_3R_VPMIN 21
-#define NEON_3R_VQDMULH_VQRDMULH 22
-#define NEON_3R_VPADD_VQRDMLAH 23
-#define NEON_3R_SHA 24 /* SHA1C,SHA1P,SHA1M,SHA1SU0,SHA256H{2},SHA256SU1 */
-#define NEON_3R_VFM_VQRDMLSH 25 /* VFMA, VFMS, VQRDMLSH */
-#define NEON_3R_FLOAT_ARITH 26 /* float VADD, VSUB, VPADD, VABD */
-#define NEON_3R_FLOAT_MULTIPLY 27 /* float VMLA, VMLS, VMUL */
-#define NEON_3R_FLOAT_CMP 28 /* float VCEQ, VCGE, VCGT */
-#define NEON_3R_FLOAT_ACMP 29 /* float VACGE, VACGT, VACLE, VACLT */
-#define NEON_3R_FLOAT_MINMAX 30 /* float VMIN, VMAX */
-#define NEON_3R_FLOAT_MISC 31 /* float VRECPS, VRSQRTS, VMAXNM/MINNM */
-
-static const uint8_t neon_3r_sizes[] = {
- [NEON_3R_VHADD] = 0x7,
- [NEON_3R_VQADD] = 0xf,
- [NEON_3R_VRHADD] = 0x7,
- [NEON_3R_LOGIC] = 0xf, /* size field encodes op type */
- [NEON_3R_VHSUB] = 0x7,
- [NEON_3R_VQSUB] = 0xf,
- [NEON_3R_VCGT] = 0x7,
- [NEON_3R_VCGE] = 0x7,
- [NEON_3R_VSHL] = 0xf,
- [NEON_3R_VQSHL] = 0xf,
- [NEON_3R_VRSHL] = 0xf,
- [NEON_3R_VQRSHL] = 0xf,
- [NEON_3R_VMAX] = 0x7,
- [NEON_3R_VMIN] = 0x7,
- [NEON_3R_VABD] = 0x7,
- [NEON_3R_VABA] = 0x7,
- [NEON_3R_VADD_VSUB] = 0xf,
- [NEON_3R_VTST_VCEQ] = 0x7,
- [NEON_3R_VML] = 0x7,
- [NEON_3R_VMUL] = 0x7,
- [NEON_3R_VPMAX] = 0x7,
- [NEON_3R_VPMIN] = 0x7,
- [NEON_3R_VQDMULH_VQRDMULH] = 0x6,
- [NEON_3R_VPADD_VQRDMLAH] = 0x7,
- [NEON_3R_SHA] = 0xf, /* size field encodes op type */
- [NEON_3R_VFM_VQRDMLSH] = 0x7, /* For VFM, size bit 1 encodes op */
- [NEON_3R_FLOAT_ARITH] = 0x5, /* size bit 1 encodes op */
- [NEON_3R_FLOAT_MULTIPLY] = 0x5, /* size bit 1 encodes op */
- [NEON_3R_FLOAT_CMP] = 0x5, /* size bit 1 encodes op */
- [NEON_3R_FLOAT_ACMP] = 0x5, /* size bit 1 encodes op */
- [NEON_3R_FLOAT_MINMAX] = 0x5, /* size bit 1 encodes op */
- [NEON_3R_FLOAT_MISC] = 0x5, /* size bit 1 encodes op */
-};
-
/* Symbolic constants for op fields for Neon 2-register miscellaneous.
* The values correspond to bits [17:16,10:7]; see the ARM ARM DDI0406B
* table A7-13.
@@ -3629,220 +3528,91 @@
[NEON_2RM_VCVT_UF] = 0x4,
};
-
-/* Expand v8.1 simd helper. */
-static int do_v81_helper(DisasContext *s, gen_helper_gvec_3_ptr *fn,
- int q, int rd, int rn, int rm)
+static void gen_gvec_fn3_qc(uint32_t rd_ofs, uint32_t rn_ofs, uint32_t rm_ofs,
+ uint32_t opr_sz, uint32_t max_sz,
+ gen_helper_gvec_3_ptr *fn)
{
- if (dc_isar_feature(aa32_rdm, s)) {
- int opr_sz = (1 + q) * 8;
- tcg_gen_gvec_3_ptr(vfp_reg_offset(1, rd),
- vfp_reg_offset(1, rn),
- vfp_reg_offset(1, rm), cpu_env,
- opr_sz, opr_sz, 0, fn);
- return 0;
+ TCGv_ptr qc_ptr = tcg_temp_new_ptr();
+
+ tcg_gen_addi_ptr(qc_ptr, cpu_env, offsetof(CPUARMState, vfp.qc));
+ tcg_gen_gvec_3_ptr(rd_ofs, rn_ofs, rm_ofs, qc_ptr,
+ opr_sz, max_sz, 0, fn);
+ tcg_temp_free_ptr(qc_ptr);
+}
+
+void gen_gvec_sqrdmlah_qc(unsigned vece, uint32_t rd_ofs, uint32_t rn_ofs,
+ uint32_t rm_ofs, uint32_t opr_sz, uint32_t max_sz)
+{
+ static gen_helper_gvec_3_ptr * const fns[2] = {
+ gen_helper_gvec_qrdmlah_s16, gen_helper_gvec_qrdmlah_s32
+ };
+ tcg_debug_assert(vece >= 1 && vece <= 2);
+ gen_gvec_fn3_qc(rd_ofs, rn_ofs, rm_ofs, opr_sz, max_sz, fns[vece - 1]);
+}
+
+void gen_gvec_sqrdmlsh_qc(unsigned vece, uint32_t rd_ofs, uint32_t rn_ofs,
+ uint32_t rm_ofs, uint32_t opr_sz, uint32_t max_sz)
+{
+ static gen_helper_gvec_3_ptr * const fns[2] = {
+ gen_helper_gvec_qrdmlsh_s16, gen_helper_gvec_qrdmlsh_s32
+ };
+ tcg_debug_assert(vece >= 1 && vece <= 2);
+ gen_gvec_fn3_qc(rd_ofs, rn_ofs, rm_ofs, opr_sz, max_sz, fns[vece - 1]);
+}
+
+#define GEN_CMP0(NAME, COND) \
+ static void gen_##NAME##0_i32(TCGv_i32 d, TCGv_i32 a) \
+ { \
+ tcg_gen_setcondi_i32(COND, d, a, 0); \
+ tcg_gen_neg_i32(d, d); \
+ } \
+ static void gen_##NAME##0_i64(TCGv_i64 d, TCGv_i64 a) \
+ { \
+ tcg_gen_setcondi_i64(COND, d, a, 0); \
+ tcg_gen_neg_i64(d, d); \
+ } \
+ static void gen_##NAME##0_vec(unsigned vece, TCGv_vec d, TCGv_vec a) \
+ { \
+ TCGv_vec zero = tcg_const_zeros_vec_matching(d); \
+ tcg_gen_cmp_vec(COND, vece, d, a, zero); \
+ tcg_temp_free_vec(zero); \
+ } \
+ void gen_gvec_##NAME##0(unsigned vece, uint32_t d, uint32_t m, \
+ uint32_t opr_sz, uint32_t max_sz) \
+ { \
+ const GVecGen2 op[4] = { \
+ { .fno = gen_helper_gvec_##NAME##0_b, \
+ .fniv = gen_##NAME##0_vec, \
+ .opt_opc = vecop_list_cmp, \
+ .vece = MO_8 }, \
+ { .fno = gen_helper_gvec_##NAME##0_h, \
+ .fniv = gen_##NAME##0_vec, \
+ .opt_opc = vecop_list_cmp, \
+ .vece = MO_16 }, \
+ { .fni4 = gen_##NAME##0_i32, \
+ .fniv = gen_##NAME##0_vec, \
+ .opt_opc = vecop_list_cmp, \
+ .vece = MO_32 }, \
+ { .fni8 = gen_##NAME##0_i64, \
+ .fniv = gen_##NAME##0_vec, \
+ .opt_opc = vecop_list_cmp, \
+ .prefer_i64 = TCG_TARGET_REG_BITS == 64, \
+ .vece = MO_64 }, \
+ }; \
+ tcg_gen_gvec_2(d, m, opr_sz, max_sz, &op[vece]); \
}
- return 1;
-}
-
-static void gen_ceq0_i32(TCGv_i32 d, TCGv_i32 a)
-{
- tcg_gen_setcondi_i32(TCG_COND_EQ, d, a, 0);
- tcg_gen_neg_i32(d, d);
-}
-
-static void gen_ceq0_i64(TCGv_i64 d, TCGv_i64 a)
-{
- tcg_gen_setcondi_i64(TCG_COND_EQ, d, a, 0);
- tcg_gen_neg_i64(d, d);
-}
-
-static void gen_ceq0_vec(unsigned vece, TCGv_vec d, TCGv_vec a)
-{
- TCGv_vec zero = tcg_const_zeros_vec_matching(d);
- tcg_gen_cmp_vec(TCG_COND_EQ, vece, d, a, zero);
- tcg_temp_free_vec(zero);
-}
static const TCGOpcode vecop_list_cmp[] = {
INDEX_op_cmp_vec, 0
};
-const GVecGen2 ceq0_op[4] = {
- { .fno = gen_helper_gvec_ceq0_b,
- .fniv = gen_ceq0_vec,
- .opt_opc = vecop_list_cmp,
- .vece = MO_8 },
- { .fno = gen_helper_gvec_ceq0_h,
- .fniv = gen_ceq0_vec,
- .opt_opc = vecop_list_cmp,
- .vece = MO_16 },
- { .fni4 = gen_ceq0_i32,
- .fniv = gen_ceq0_vec,
- .opt_opc = vecop_list_cmp,
- .vece = MO_32 },
- { .fni8 = gen_ceq0_i64,
- .fniv = gen_ceq0_vec,
- .opt_opc = vecop_list_cmp,
- .prefer_i64 = TCG_TARGET_REG_BITS == 64,
- .vece = MO_64 },
-};
+GEN_CMP0(ceq, TCG_COND_EQ)
+GEN_CMP0(cle, TCG_COND_LE)
+GEN_CMP0(cge, TCG_COND_GE)
+GEN_CMP0(clt, TCG_COND_LT)
+GEN_CMP0(cgt, TCG_COND_GT)
-static void gen_cle0_i32(TCGv_i32 d, TCGv_i32 a)
-{
- tcg_gen_setcondi_i32(TCG_COND_LE, d, a, 0);
- tcg_gen_neg_i32(d, d);
-}
-
-static void gen_cle0_i64(TCGv_i64 d, TCGv_i64 a)
-{
- tcg_gen_setcondi_i64(TCG_COND_LE, d, a, 0);
- tcg_gen_neg_i64(d, d);
-}
-
-static void gen_cle0_vec(unsigned vece, TCGv_vec d, TCGv_vec a)
-{
- TCGv_vec zero = tcg_const_zeros_vec_matching(d);
- tcg_gen_cmp_vec(TCG_COND_LE, vece, d, a, zero);
- tcg_temp_free_vec(zero);
-}
-
-const GVecGen2 cle0_op[4] = {
- { .fno = gen_helper_gvec_cle0_b,
- .fniv = gen_cle0_vec,
- .opt_opc = vecop_list_cmp,
- .vece = MO_8 },
- { .fno = gen_helper_gvec_cle0_h,
- .fniv = gen_cle0_vec,
- .opt_opc = vecop_list_cmp,
- .vece = MO_16 },
- { .fni4 = gen_cle0_i32,
- .fniv = gen_cle0_vec,
- .opt_opc = vecop_list_cmp,
- .vece = MO_32 },
- { .fni8 = gen_cle0_i64,
- .fniv = gen_cle0_vec,
- .opt_opc = vecop_list_cmp,
- .prefer_i64 = TCG_TARGET_REG_BITS == 64,
- .vece = MO_64 },
-};
-
-static void gen_cge0_i32(TCGv_i32 d, TCGv_i32 a)
-{
- tcg_gen_setcondi_i32(TCG_COND_GE, d, a, 0);
- tcg_gen_neg_i32(d, d);
-}
-
-static void gen_cge0_i64(TCGv_i64 d, TCGv_i64 a)
-{
- tcg_gen_setcondi_i64(TCG_COND_GE, d, a, 0);
- tcg_gen_neg_i64(d, d);
-}
-
-static void gen_cge0_vec(unsigned vece, TCGv_vec d, TCGv_vec a)
-{
- TCGv_vec zero = tcg_const_zeros_vec_matching(d);
- tcg_gen_cmp_vec(TCG_COND_GE, vece, d, a, zero);
- tcg_temp_free_vec(zero);
-}
-
-const GVecGen2 cge0_op[4] = {
- { .fno = gen_helper_gvec_cge0_b,
- .fniv = gen_cge0_vec,
- .opt_opc = vecop_list_cmp,
- .vece = MO_8 },
- { .fno = gen_helper_gvec_cge0_h,
- .fniv = gen_cge0_vec,
- .opt_opc = vecop_list_cmp,
- .vece = MO_16 },
- { .fni4 = gen_cge0_i32,
- .fniv = gen_cge0_vec,
- .opt_opc = vecop_list_cmp,
- .vece = MO_32 },
- { .fni8 = gen_cge0_i64,
- .fniv = gen_cge0_vec,
- .opt_opc = vecop_list_cmp,
- .prefer_i64 = TCG_TARGET_REG_BITS == 64,
- .vece = MO_64 },
-};
-
-static void gen_clt0_i32(TCGv_i32 d, TCGv_i32 a)
-{
- tcg_gen_setcondi_i32(TCG_COND_LT, d, a, 0);
- tcg_gen_neg_i32(d, d);
-}
-
-static void gen_clt0_i64(TCGv_i64 d, TCGv_i64 a)
-{
- tcg_gen_setcondi_i64(TCG_COND_LT, d, a, 0);
- tcg_gen_neg_i64(d, d);
-}
-
-static void gen_clt0_vec(unsigned vece, TCGv_vec d, TCGv_vec a)
-{
- TCGv_vec zero = tcg_const_zeros_vec_matching(d);
- tcg_gen_cmp_vec(TCG_COND_LT, vece, d, a, zero);
- tcg_temp_free_vec(zero);
-}
-
-const GVecGen2 clt0_op[4] = {
- { .fno = gen_helper_gvec_clt0_b,
- .fniv = gen_clt0_vec,
- .opt_opc = vecop_list_cmp,
- .vece = MO_8 },
- { .fno = gen_helper_gvec_clt0_h,
- .fniv = gen_clt0_vec,
- .opt_opc = vecop_list_cmp,
- .vece = MO_16 },
- { .fni4 = gen_clt0_i32,
- .fniv = gen_clt0_vec,
- .opt_opc = vecop_list_cmp,
- .vece = MO_32 },
- { .fni8 = gen_clt0_i64,
- .fniv = gen_clt0_vec,
- .opt_opc = vecop_list_cmp,
- .prefer_i64 = TCG_TARGET_REG_BITS == 64,
- .vece = MO_64 },
-};
-
-static void gen_cgt0_i32(TCGv_i32 d, TCGv_i32 a)
-{
- tcg_gen_setcondi_i32(TCG_COND_GT, d, a, 0);
- tcg_gen_neg_i32(d, d);
-}
-
-static void gen_cgt0_i64(TCGv_i64 d, TCGv_i64 a)
-{
- tcg_gen_setcondi_i64(TCG_COND_GT, d, a, 0);
- tcg_gen_neg_i64(d, d);
-}
-
-static void gen_cgt0_vec(unsigned vece, TCGv_vec d, TCGv_vec a)
-{
- TCGv_vec zero = tcg_const_zeros_vec_matching(d);
- tcg_gen_cmp_vec(TCG_COND_GT, vece, d, a, zero);
- tcg_temp_free_vec(zero);
-}
-
-const GVecGen2 cgt0_op[4] = {
- { .fno = gen_helper_gvec_cgt0_b,
- .fniv = gen_cgt0_vec,
- .opt_opc = vecop_list_cmp,
- .vece = MO_8 },
- { .fno = gen_helper_gvec_cgt0_h,
- .fniv = gen_cgt0_vec,
- .opt_opc = vecop_list_cmp,
- .vece = MO_16 },
- { .fni4 = gen_cgt0_i32,
- .fniv = gen_cgt0_vec,
- .opt_opc = vecop_list_cmp,
- .vece = MO_32 },
- { .fni8 = gen_cgt0_i64,
- .fniv = gen_cgt0_vec,
- .opt_opc = vecop_list_cmp,
- .prefer_i64 = TCG_TARGET_REG_BITS == 64,
- .vece = MO_64 },
-};
+#undef GEN_CMP0
static void gen_ssra8_i64(TCGv_i64 d, TCGv_i64 a, int64_t shift)
{
@@ -3874,33 +3644,51 @@
tcg_gen_add_vec(vece, d, d, a);
}
-static const TCGOpcode vecop_list_ssra[] = {
- INDEX_op_sari_vec, INDEX_op_add_vec, 0
-};
+void gen_gvec_ssra(unsigned vece, uint32_t rd_ofs, uint32_t rm_ofs,
+ int64_t shift, uint32_t opr_sz, uint32_t max_sz)
+{
+ static const TCGOpcode vecop_list[] = {
+ INDEX_op_sari_vec, INDEX_op_add_vec, 0
+ };
+ static const GVecGen2i ops[4] = {
+ { .fni8 = gen_ssra8_i64,
+ .fniv = gen_ssra_vec,
+ .fno = gen_helper_gvec_ssra_b,
+ .load_dest = true,
+ .opt_opc = vecop_list,
+ .vece = MO_8 },
+ { .fni8 = gen_ssra16_i64,
+ .fniv = gen_ssra_vec,
+ .fno = gen_helper_gvec_ssra_h,
+ .load_dest = true,
+ .opt_opc = vecop_list,
+ .vece = MO_16 },
+ { .fni4 = gen_ssra32_i32,
+ .fniv = gen_ssra_vec,
+ .fno = gen_helper_gvec_ssra_s,
+ .load_dest = true,
+ .opt_opc = vecop_list,
+ .vece = MO_32 },
+ { .fni8 = gen_ssra64_i64,
+ .fniv = gen_ssra_vec,
+ .fno = gen_helper_gvec_ssra_b,
+ .prefer_i64 = TCG_TARGET_REG_BITS == 64,
+ .opt_opc = vecop_list,
+ .load_dest = true,
+ .vece = MO_64 },
+ };
-const GVecGen2i ssra_op[4] = {
- { .fni8 = gen_ssra8_i64,
- .fniv = gen_ssra_vec,
- .load_dest = true,
- .opt_opc = vecop_list_ssra,
- .vece = MO_8 },
- { .fni8 = gen_ssra16_i64,
- .fniv = gen_ssra_vec,
- .load_dest = true,
- .opt_opc = vecop_list_ssra,
- .vece = MO_16 },
- { .fni4 = gen_ssra32_i32,
- .fniv = gen_ssra_vec,
- .load_dest = true,
- .opt_opc = vecop_list_ssra,
- .vece = MO_32 },
- { .fni8 = gen_ssra64_i64,
- .fniv = gen_ssra_vec,
- .prefer_i64 = TCG_TARGET_REG_BITS == 64,
- .opt_opc = vecop_list_ssra,
- .load_dest = true,
- .vece = MO_64 },
-};
+ /* tszimm encoding produces immediates in the range [1..esize]. */
+ tcg_debug_assert(shift > 0);
+ tcg_debug_assert(shift <= (8 << vece));
+
+ /*
+ * Shifts larger than the element size are architecturally valid.
+ * Signed results in all sign bits.
+ */
+ shift = MIN(shift, (8 << vece) - 1);
+ tcg_gen_gvec_2i(rd_ofs, rm_ofs, opr_sz, max_sz, shift, &ops[vece]);
+}
static void gen_usra8_i64(TCGv_i64 d, TCGv_i64 a, int64_t shift)
{
@@ -3932,33 +3720,471 @@
tcg_gen_add_vec(vece, d, d, a);
}
-static const TCGOpcode vecop_list_usra[] = {
- INDEX_op_shri_vec, INDEX_op_add_vec, 0
-};
+void gen_gvec_usra(unsigned vece, uint32_t rd_ofs, uint32_t rm_ofs,
+ int64_t shift, uint32_t opr_sz, uint32_t max_sz)
+{
+ static const TCGOpcode vecop_list[] = {
+ INDEX_op_shri_vec, INDEX_op_add_vec, 0
+ };
+ static const GVecGen2i ops[4] = {
+ { .fni8 = gen_usra8_i64,
+ .fniv = gen_usra_vec,
+ .fno = gen_helper_gvec_usra_b,
+ .load_dest = true,
+ .opt_opc = vecop_list,
+ .vece = MO_8, },
+ { .fni8 = gen_usra16_i64,
+ .fniv = gen_usra_vec,
+ .fno = gen_helper_gvec_usra_h,
+ .load_dest = true,
+ .opt_opc = vecop_list,
+ .vece = MO_16, },
+ { .fni4 = gen_usra32_i32,
+ .fniv = gen_usra_vec,
+ .fno = gen_helper_gvec_usra_s,
+ .load_dest = true,
+ .opt_opc = vecop_list,
+ .vece = MO_32, },
+ { .fni8 = gen_usra64_i64,
+ .fniv = gen_usra_vec,
+ .fno = gen_helper_gvec_usra_d,
+ .prefer_i64 = TCG_TARGET_REG_BITS == 64,
+ .load_dest = true,
+ .opt_opc = vecop_list,
+ .vece = MO_64, },
+ };
-const GVecGen2i usra_op[4] = {
- { .fni8 = gen_usra8_i64,
- .fniv = gen_usra_vec,
- .load_dest = true,
- .opt_opc = vecop_list_usra,
- .vece = MO_8, },
- { .fni8 = gen_usra16_i64,
- .fniv = gen_usra_vec,
- .load_dest = true,
- .opt_opc = vecop_list_usra,
- .vece = MO_16, },
- { .fni4 = gen_usra32_i32,
- .fniv = gen_usra_vec,
- .load_dest = true,
- .opt_opc = vecop_list_usra,
- .vece = MO_32, },
- { .fni8 = gen_usra64_i64,
- .fniv = gen_usra_vec,
- .prefer_i64 = TCG_TARGET_REG_BITS == 64,
- .load_dest = true,
- .opt_opc = vecop_list_usra,
- .vece = MO_64, },
-};
+ /* tszimm encoding produces immediates in the range [1..esize]. */
+ tcg_debug_assert(shift > 0);
+ tcg_debug_assert(shift <= (8 << vece));
+
+ /*
+ * Shifts larger than the element size are architecturally valid.
+ * Unsigned results in all zeros as input to accumulate: nop.
+ */
+ if (shift < (8 << vece)) {
+ tcg_gen_gvec_2i(rd_ofs, rm_ofs, opr_sz, max_sz, shift, &ops[vece]);
+ } else {
+ /* Nop, but we do need to clear the tail. */
+ tcg_gen_gvec_mov(vece, rd_ofs, rd_ofs, opr_sz, max_sz);
+ }
+}
+
+/*
+ * Shift one less than the requested amount, and the low bit is
+ * the rounding bit. For the 8 and 16-bit operations, because we
+ * mask the low bit, we can perform a normal integer shift instead
+ * of a vector shift.
+ */
+static void gen_srshr8_i64(TCGv_i64 d, TCGv_i64 a, int64_t sh)
+{
+ TCGv_i64 t = tcg_temp_new_i64();
+
+ tcg_gen_shri_i64(t, a, sh - 1);
+ tcg_gen_andi_i64(t, t, dup_const(MO_8, 1));
+ tcg_gen_vec_sar8i_i64(d, a, sh);
+ tcg_gen_vec_add8_i64(d, d, t);
+ tcg_temp_free_i64(t);
+}
+
+static void gen_srshr16_i64(TCGv_i64 d, TCGv_i64 a, int64_t sh)
+{
+ TCGv_i64 t = tcg_temp_new_i64();
+
+ tcg_gen_shri_i64(t, a, sh - 1);
+ tcg_gen_andi_i64(t, t, dup_const(MO_16, 1));
+ tcg_gen_vec_sar16i_i64(d, a, sh);
+ tcg_gen_vec_add16_i64(d, d, t);
+ tcg_temp_free_i64(t);
+}
+
+static void gen_srshr32_i32(TCGv_i32 d, TCGv_i32 a, int32_t sh)
+{
+ TCGv_i32 t = tcg_temp_new_i32();
+
+ tcg_gen_extract_i32(t, a, sh - 1, 1);
+ tcg_gen_sari_i32(d, a, sh);
+ tcg_gen_add_i32(d, d, t);
+ tcg_temp_free_i32(t);
+}
+
+static void gen_srshr64_i64(TCGv_i64 d, TCGv_i64 a, int64_t sh)
+{
+ TCGv_i64 t = tcg_temp_new_i64();
+
+ tcg_gen_extract_i64(t, a, sh - 1, 1);
+ tcg_gen_sari_i64(d, a, sh);
+ tcg_gen_add_i64(d, d, t);
+ tcg_temp_free_i64(t);
+}
+
+static void gen_srshr_vec(unsigned vece, TCGv_vec d, TCGv_vec a, int64_t sh)
+{
+ TCGv_vec t = tcg_temp_new_vec_matching(d);
+ TCGv_vec ones = tcg_temp_new_vec_matching(d);
+
+ tcg_gen_shri_vec(vece, t, a, sh - 1);
+ tcg_gen_dupi_vec(vece, ones, 1);
+ tcg_gen_and_vec(vece, t, t, ones);
+ tcg_gen_sari_vec(vece, d, a, sh);
+ tcg_gen_add_vec(vece, d, d, t);
+
+ tcg_temp_free_vec(t);
+ tcg_temp_free_vec(ones);
+}
+
+void gen_gvec_srshr(unsigned vece, uint32_t rd_ofs, uint32_t rm_ofs,
+ int64_t shift, uint32_t opr_sz, uint32_t max_sz)
+{
+ static const TCGOpcode vecop_list[] = {
+ INDEX_op_shri_vec, INDEX_op_sari_vec, INDEX_op_add_vec, 0
+ };
+ static const GVecGen2i ops[4] = {
+ { .fni8 = gen_srshr8_i64,
+ .fniv = gen_srshr_vec,
+ .fno = gen_helper_gvec_srshr_b,
+ .opt_opc = vecop_list,
+ .vece = MO_8 },
+ { .fni8 = gen_srshr16_i64,
+ .fniv = gen_srshr_vec,
+ .fno = gen_helper_gvec_srshr_h,
+ .opt_opc = vecop_list,
+ .vece = MO_16 },
+ { .fni4 = gen_srshr32_i32,
+ .fniv = gen_srshr_vec,
+ .fno = gen_helper_gvec_srshr_s,
+ .opt_opc = vecop_list,
+ .vece = MO_32 },
+ { .fni8 = gen_srshr64_i64,
+ .fniv = gen_srshr_vec,
+ .fno = gen_helper_gvec_srshr_d,
+ .prefer_i64 = TCG_TARGET_REG_BITS == 64,
+ .opt_opc = vecop_list,
+ .vece = MO_64 },
+ };
+
+ /* tszimm encoding produces immediates in the range [1..esize] */
+ tcg_debug_assert(shift > 0);
+ tcg_debug_assert(shift <= (8 << vece));
+
+ if (shift == (8 << vece)) {
+ /*
+ * Shifts larger than the element size are architecturally valid.
+ * Signed results in all sign bits. With rounding, this produces
+ * (-1 + 1) >> 1 == 0, or (0 + 1) >> 1 == 0.
+ * I.e. always zero.
+ */
+ tcg_gen_gvec_dup_imm(vece, rd_ofs, opr_sz, max_sz, 0);
+ } else {
+ tcg_gen_gvec_2i(rd_ofs, rm_ofs, opr_sz, max_sz, shift, &ops[vece]);
+ }
+}
+
+static void gen_srsra8_i64(TCGv_i64 d, TCGv_i64 a, int64_t sh)
+{
+ TCGv_i64 t = tcg_temp_new_i64();
+
+ gen_srshr8_i64(t, a, sh);
+ tcg_gen_vec_add8_i64(d, d, t);
+ tcg_temp_free_i64(t);
+}
+
+static void gen_srsra16_i64(TCGv_i64 d, TCGv_i64 a, int64_t sh)
+{
+ TCGv_i64 t = tcg_temp_new_i64();
+
+ gen_srshr16_i64(t, a, sh);
+ tcg_gen_vec_add16_i64(d, d, t);
+ tcg_temp_free_i64(t);
+}
+
+static void gen_srsra32_i32(TCGv_i32 d, TCGv_i32 a, int32_t sh)
+{
+ TCGv_i32 t = tcg_temp_new_i32();
+
+ gen_srshr32_i32(t, a, sh);
+ tcg_gen_add_i32(d, d, t);
+ tcg_temp_free_i32(t);
+}
+
+static void gen_srsra64_i64(TCGv_i64 d, TCGv_i64 a, int64_t sh)
+{
+ TCGv_i64 t = tcg_temp_new_i64();
+
+ gen_srshr64_i64(t, a, sh);
+ tcg_gen_add_i64(d, d, t);
+ tcg_temp_free_i64(t);
+}
+
+static void gen_srsra_vec(unsigned vece, TCGv_vec d, TCGv_vec a, int64_t sh)
+{
+ TCGv_vec t = tcg_temp_new_vec_matching(d);
+
+ gen_srshr_vec(vece, t, a, sh);
+ tcg_gen_add_vec(vece, d, d, t);
+ tcg_temp_free_vec(t);
+}
+
+void gen_gvec_srsra(unsigned vece, uint32_t rd_ofs, uint32_t rm_ofs,
+ int64_t shift, uint32_t opr_sz, uint32_t max_sz)
+{
+ static const TCGOpcode vecop_list[] = {
+ INDEX_op_shri_vec, INDEX_op_sari_vec, INDEX_op_add_vec, 0
+ };
+ static const GVecGen2i ops[4] = {
+ { .fni8 = gen_srsra8_i64,
+ .fniv = gen_srsra_vec,
+ .fno = gen_helper_gvec_srsra_b,
+ .opt_opc = vecop_list,
+ .load_dest = true,
+ .vece = MO_8 },
+ { .fni8 = gen_srsra16_i64,
+ .fniv = gen_srsra_vec,
+ .fno = gen_helper_gvec_srsra_h,
+ .opt_opc = vecop_list,
+ .load_dest = true,
+ .vece = MO_16 },
+ { .fni4 = gen_srsra32_i32,
+ .fniv = gen_srsra_vec,
+ .fno = gen_helper_gvec_srsra_s,
+ .opt_opc = vecop_list,
+ .load_dest = true,
+ .vece = MO_32 },
+ { .fni8 = gen_srsra64_i64,
+ .fniv = gen_srsra_vec,
+ .fno = gen_helper_gvec_srsra_d,
+ .prefer_i64 = TCG_TARGET_REG_BITS == 64,
+ .opt_opc = vecop_list,
+ .load_dest = true,
+ .vece = MO_64 },
+ };
+
+ /* tszimm encoding produces immediates in the range [1..esize] */
+ tcg_debug_assert(shift > 0);
+ tcg_debug_assert(shift <= (8 << vece));
+
+ /*
+ * Shifts larger than the element size are architecturally valid.
+ * Signed results in all sign bits. With rounding, this produces
+ * (-1 + 1) >> 1 == 0, or (0 + 1) >> 1 == 0.
+ * I.e. always zero. With accumulation, this leaves D unchanged.
+ */
+ if (shift == (8 << vece)) {
+ /* Nop, but we do need to clear the tail. */
+ tcg_gen_gvec_mov(vece, rd_ofs, rd_ofs, opr_sz, max_sz);
+ } else {
+ tcg_gen_gvec_2i(rd_ofs, rm_ofs, opr_sz, max_sz, shift, &ops[vece]);
+ }
+}
+
+static void gen_urshr8_i64(TCGv_i64 d, TCGv_i64 a, int64_t sh)
+{
+ TCGv_i64 t = tcg_temp_new_i64();
+
+ tcg_gen_shri_i64(t, a, sh - 1);
+ tcg_gen_andi_i64(t, t, dup_const(MO_8, 1));
+ tcg_gen_vec_shr8i_i64(d, a, sh);
+ tcg_gen_vec_add8_i64(d, d, t);
+ tcg_temp_free_i64(t);
+}
+
+static void gen_urshr16_i64(TCGv_i64 d, TCGv_i64 a, int64_t sh)
+{
+ TCGv_i64 t = tcg_temp_new_i64();
+
+ tcg_gen_shri_i64(t, a, sh - 1);
+ tcg_gen_andi_i64(t, t, dup_const(MO_16, 1));
+ tcg_gen_vec_shr16i_i64(d, a, sh);
+ tcg_gen_vec_add16_i64(d, d, t);
+ tcg_temp_free_i64(t);
+}
+
+static void gen_urshr32_i32(TCGv_i32 d, TCGv_i32 a, int32_t sh)
+{
+ TCGv_i32 t = tcg_temp_new_i32();
+
+ tcg_gen_extract_i32(t, a, sh - 1, 1);
+ tcg_gen_shri_i32(d, a, sh);
+ tcg_gen_add_i32(d, d, t);
+ tcg_temp_free_i32(t);
+}
+
+static void gen_urshr64_i64(TCGv_i64 d, TCGv_i64 a, int64_t sh)
+{
+ TCGv_i64 t = tcg_temp_new_i64();
+
+ tcg_gen_extract_i64(t, a, sh - 1, 1);
+ tcg_gen_shri_i64(d, a, sh);
+ tcg_gen_add_i64(d, d, t);
+ tcg_temp_free_i64(t);
+}
+
+static void gen_urshr_vec(unsigned vece, TCGv_vec d, TCGv_vec a, int64_t shift)
+{
+ TCGv_vec t = tcg_temp_new_vec_matching(d);
+ TCGv_vec ones = tcg_temp_new_vec_matching(d);
+
+ tcg_gen_shri_vec(vece, t, a, shift - 1);
+ tcg_gen_dupi_vec(vece, ones, 1);
+ tcg_gen_and_vec(vece, t, t, ones);
+ tcg_gen_shri_vec(vece, d, a, shift);
+ tcg_gen_add_vec(vece, d, d, t);
+
+ tcg_temp_free_vec(t);
+ tcg_temp_free_vec(ones);
+}
+
+void gen_gvec_urshr(unsigned vece, uint32_t rd_ofs, uint32_t rm_ofs,
+ int64_t shift, uint32_t opr_sz, uint32_t max_sz)
+{
+ static const TCGOpcode vecop_list[] = {
+ INDEX_op_shri_vec, INDEX_op_add_vec, 0
+ };
+ static const GVecGen2i ops[4] = {
+ { .fni8 = gen_urshr8_i64,
+ .fniv = gen_urshr_vec,
+ .fno = gen_helper_gvec_urshr_b,
+ .opt_opc = vecop_list,
+ .vece = MO_8 },
+ { .fni8 = gen_urshr16_i64,
+ .fniv = gen_urshr_vec,
+ .fno = gen_helper_gvec_urshr_h,
+ .opt_opc = vecop_list,
+ .vece = MO_16 },
+ { .fni4 = gen_urshr32_i32,
+ .fniv = gen_urshr_vec,
+ .fno = gen_helper_gvec_urshr_s,
+ .opt_opc = vecop_list,
+ .vece = MO_32 },
+ { .fni8 = gen_urshr64_i64,
+ .fniv = gen_urshr_vec,
+ .fno = gen_helper_gvec_urshr_d,
+ .prefer_i64 = TCG_TARGET_REG_BITS == 64,
+ .opt_opc = vecop_list,
+ .vece = MO_64 },
+ };
+
+ /* tszimm encoding produces immediates in the range [1..esize] */
+ tcg_debug_assert(shift > 0);
+ tcg_debug_assert(shift <= (8 << vece));
+
+ if (shift == (8 << vece)) {
+ /*
+ * Shifts larger than the element size are architecturally valid.
+ * Unsigned results in zero. With rounding, this produces a
+ * copy of the most significant bit.
+ */
+ tcg_gen_gvec_shri(vece, rd_ofs, rm_ofs, shift - 1, opr_sz, max_sz);
+ } else {
+ tcg_gen_gvec_2i(rd_ofs, rm_ofs, opr_sz, max_sz, shift, &ops[vece]);
+ }
+}
+
+static void gen_ursra8_i64(TCGv_i64 d, TCGv_i64 a, int64_t sh)
+{
+ TCGv_i64 t = tcg_temp_new_i64();
+
+ if (sh == 8) {
+ tcg_gen_vec_shr8i_i64(t, a, 7);
+ } else {
+ gen_urshr8_i64(t, a, sh);
+ }
+ tcg_gen_vec_add8_i64(d, d, t);
+ tcg_temp_free_i64(t);
+}
+
+static void gen_ursra16_i64(TCGv_i64 d, TCGv_i64 a, int64_t sh)
+{
+ TCGv_i64 t = tcg_temp_new_i64();
+
+ if (sh == 16) {
+ tcg_gen_vec_shr16i_i64(t, a, 15);
+ } else {
+ gen_urshr16_i64(t, a, sh);
+ }
+ tcg_gen_vec_add16_i64(d, d, t);
+ tcg_temp_free_i64(t);
+}
+
+static void gen_ursra32_i32(TCGv_i32 d, TCGv_i32 a, int32_t sh)
+{
+ TCGv_i32 t = tcg_temp_new_i32();
+
+ if (sh == 32) {
+ tcg_gen_shri_i32(t, a, 31);
+ } else {
+ gen_urshr32_i32(t, a, sh);
+ }
+ tcg_gen_add_i32(d, d, t);
+ tcg_temp_free_i32(t);
+}
+
+static void gen_ursra64_i64(TCGv_i64 d, TCGv_i64 a, int64_t sh)
+{
+ TCGv_i64 t = tcg_temp_new_i64();
+
+ if (sh == 64) {
+ tcg_gen_shri_i64(t, a, 63);
+ } else {
+ gen_urshr64_i64(t, a, sh);
+ }
+ tcg_gen_add_i64(d, d, t);
+ tcg_temp_free_i64(t);
+}
+
+static void gen_ursra_vec(unsigned vece, TCGv_vec d, TCGv_vec a, int64_t sh)
+{
+ TCGv_vec t = tcg_temp_new_vec_matching(d);
+
+ if (sh == (8 << vece)) {
+ tcg_gen_shri_vec(vece, t, a, sh - 1);
+ } else {
+ gen_urshr_vec(vece, t, a, sh);
+ }
+ tcg_gen_add_vec(vece, d, d, t);
+ tcg_temp_free_vec(t);
+}
+
+void gen_gvec_ursra(unsigned vece, uint32_t rd_ofs, uint32_t rm_ofs,
+ int64_t shift, uint32_t opr_sz, uint32_t max_sz)
+{
+ static const TCGOpcode vecop_list[] = {
+ INDEX_op_shri_vec, INDEX_op_add_vec, 0
+ };
+ static const GVecGen2i ops[4] = {
+ { .fni8 = gen_ursra8_i64,
+ .fniv = gen_ursra_vec,
+ .fno = gen_helper_gvec_ursra_b,
+ .opt_opc = vecop_list,
+ .load_dest = true,
+ .vece = MO_8 },
+ { .fni8 = gen_ursra16_i64,
+ .fniv = gen_ursra_vec,
+ .fno = gen_helper_gvec_ursra_h,
+ .opt_opc = vecop_list,
+ .load_dest = true,
+ .vece = MO_16 },
+ { .fni4 = gen_ursra32_i32,
+ .fniv = gen_ursra_vec,
+ .fno = gen_helper_gvec_ursra_s,
+ .opt_opc = vecop_list,
+ .load_dest = true,
+ .vece = MO_32 },
+ { .fni8 = gen_ursra64_i64,
+ .fniv = gen_ursra_vec,
+ .fno = gen_helper_gvec_ursra_d,
+ .prefer_i64 = TCG_TARGET_REG_BITS == 64,
+ .opt_opc = vecop_list,
+ .load_dest = true,
+ .vece = MO_64 },
+ };
+
+ /* tszimm encoding produces immediates in the range [1..esize] */
+ tcg_debug_assert(shift > 0);
+ tcg_debug_assert(shift <= (8 << vece));
+
+ tcg_gen_gvec_2i(rd_ofs, rm_ofs, opr_sz, max_sz, shift, &ops[vece]);
+}
static void gen_shr8_ins_i64(TCGv_i64 d, TCGv_i64 a, int64_t shift)
{
@@ -3998,47 +4224,62 @@
static void gen_shr_ins_vec(unsigned vece, TCGv_vec d, TCGv_vec a, int64_t sh)
{
- if (sh == 0) {
- tcg_gen_mov_vec(d, a);
- } else {
- TCGv_vec t = tcg_temp_new_vec_matching(d);
- TCGv_vec m = tcg_temp_new_vec_matching(d);
+ TCGv_vec t = tcg_temp_new_vec_matching(d);
+ TCGv_vec m = tcg_temp_new_vec_matching(d);
- tcg_gen_dupi_vec(vece, m, MAKE_64BIT_MASK((8 << vece) - sh, sh));
- tcg_gen_shri_vec(vece, t, a, sh);
- tcg_gen_and_vec(vece, d, d, m);
- tcg_gen_or_vec(vece, d, d, t);
+ tcg_gen_dupi_vec(vece, m, MAKE_64BIT_MASK((8 << vece) - sh, sh));
+ tcg_gen_shri_vec(vece, t, a, sh);
+ tcg_gen_and_vec(vece, d, d, m);
+ tcg_gen_or_vec(vece, d, d, t);
- tcg_temp_free_vec(t);
- tcg_temp_free_vec(m);
- }
+ tcg_temp_free_vec(t);
+ tcg_temp_free_vec(m);
}
-static const TCGOpcode vecop_list_sri[] = { INDEX_op_shri_vec, 0 };
+void gen_gvec_sri(unsigned vece, uint32_t rd_ofs, uint32_t rm_ofs,
+ int64_t shift, uint32_t opr_sz, uint32_t max_sz)
+{
+ static const TCGOpcode vecop_list[] = { INDEX_op_shri_vec, 0 };
+ const GVecGen2i ops[4] = {
+ { .fni8 = gen_shr8_ins_i64,
+ .fniv = gen_shr_ins_vec,
+ .fno = gen_helper_gvec_sri_b,
+ .load_dest = true,
+ .opt_opc = vecop_list,
+ .vece = MO_8 },
+ { .fni8 = gen_shr16_ins_i64,
+ .fniv = gen_shr_ins_vec,
+ .fno = gen_helper_gvec_sri_h,
+ .load_dest = true,
+ .opt_opc = vecop_list,
+ .vece = MO_16 },
+ { .fni4 = gen_shr32_ins_i32,
+ .fniv = gen_shr_ins_vec,
+ .fno = gen_helper_gvec_sri_s,
+ .load_dest = true,
+ .opt_opc = vecop_list,
+ .vece = MO_32 },
+ { .fni8 = gen_shr64_ins_i64,
+ .fniv = gen_shr_ins_vec,
+ .fno = gen_helper_gvec_sri_d,
+ .prefer_i64 = TCG_TARGET_REG_BITS == 64,
+ .load_dest = true,
+ .opt_opc = vecop_list,
+ .vece = MO_64 },
+ };
-const GVecGen2i sri_op[4] = {
- { .fni8 = gen_shr8_ins_i64,
- .fniv = gen_shr_ins_vec,
- .load_dest = true,
- .opt_opc = vecop_list_sri,
- .vece = MO_8 },
- { .fni8 = gen_shr16_ins_i64,
- .fniv = gen_shr_ins_vec,
- .load_dest = true,
- .opt_opc = vecop_list_sri,
- .vece = MO_16 },
- { .fni4 = gen_shr32_ins_i32,
- .fniv = gen_shr_ins_vec,
- .load_dest = true,
- .opt_opc = vecop_list_sri,
- .vece = MO_32 },
- { .fni8 = gen_shr64_ins_i64,
- .fniv = gen_shr_ins_vec,
- .prefer_i64 = TCG_TARGET_REG_BITS == 64,
- .load_dest = true,
- .opt_opc = vecop_list_sri,
- .vece = MO_64 },
-};
+ /* tszimm encoding produces immediates in the range [1..esize]. */
+ tcg_debug_assert(shift > 0);
+ tcg_debug_assert(shift <= (8 << vece));
+
+ /* Shift of esize leaves destination unchanged. */
+ if (shift < (8 << vece)) {
+ tcg_gen_gvec_2i(rd_ofs, rm_ofs, opr_sz, max_sz, shift, &ops[vece]);
+ } else {
+ /* Nop, but we do need to clear the tail. */
+ tcg_gen_gvec_mov(vece, rd_ofs, rd_ofs, opr_sz, max_sz);
+ }
+}
static void gen_shl8_ins_i64(TCGv_i64 d, TCGv_i64 a, int64_t shift)
{
@@ -4076,47 +4317,60 @@
static void gen_shl_ins_vec(unsigned vece, TCGv_vec d, TCGv_vec a, int64_t sh)
{
- if (sh == 0) {
- tcg_gen_mov_vec(d, a);
- } else {
- TCGv_vec t = tcg_temp_new_vec_matching(d);
- TCGv_vec m = tcg_temp_new_vec_matching(d);
+ TCGv_vec t = tcg_temp_new_vec_matching(d);
+ TCGv_vec m = tcg_temp_new_vec_matching(d);
- tcg_gen_dupi_vec(vece, m, MAKE_64BIT_MASK(0, sh));
- tcg_gen_shli_vec(vece, t, a, sh);
- tcg_gen_and_vec(vece, d, d, m);
- tcg_gen_or_vec(vece, d, d, t);
+ tcg_gen_shli_vec(vece, t, a, sh);
+ tcg_gen_dupi_vec(vece, m, MAKE_64BIT_MASK(0, sh));
+ tcg_gen_and_vec(vece, d, d, m);
+ tcg_gen_or_vec(vece, d, d, t);
- tcg_temp_free_vec(t);
- tcg_temp_free_vec(m);
- }
+ tcg_temp_free_vec(t);
+ tcg_temp_free_vec(m);
}
-static const TCGOpcode vecop_list_sli[] = { INDEX_op_shli_vec, 0 };
+void gen_gvec_sli(unsigned vece, uint32_t rd_ofs, uint32_t rm_ofs,
+ int64_t shift, uint32_t opr_sz, uint32_t max_sz)
+{
+ static const TCGOpcode vecop_list[] = { INDEX_op_shli_vec, 0 };
+ const GVecGen2i ops[4] = {
+ { .fni8 = gen_shl8_ins_i64,
+ .fniv = gen_shl_ins_vec,
+ .fno = gen_helper_gvec_sli_b,
+ .load_dest = true,
+ .opt_opc = vecop_list,
+ .vece = MO_8 },
+ { .fni8 = gen_shl16_ins_i64,
+ .fniv = gen_shl_ins_vec,
+ .fno = gen_helper_gvec_sli_h,
+ .load_dest = true,
+ .opt_opc = vecop_list,
+ .vece = MO_16 },
+ { .fni4 = gen_shl32_ins_i32,
+ .fniv = gen_shl_ins_vec,
+ .fno = gen_helper_gvec_sli_s,
+ .load_dest = true,
+ .opt_opc = vecop_list,
+ .vece = MO_32 },
+ { .fni8 = gen_shl64_ins_i64,
+ .fniv = gen_shl_ins_vec,
+ .fno = gen_helper_gvec_sli_d,
+ .prefer_i64 = TCG_TARGET_REG_BITS == 64,
+ .load_dest = true,
+ .opt_opc = vecop_list,
+ .vece = MO_64 },
+ };
-const GVecGen2i sli_op[4] = {
- { .fni8 = gen_shl8_ins_i64,
- .fniv = gen_shl_ins_vec,
- .load_dest = true,
- .opt_opc = vecop_list_sli,
- .vece = MO_8 },
- { .fni8 = gen_shl16_ins_i64,
- .fniv = gen_shl_ins_vec,
- .load_dest = true,
- .opt_opc = vecop_list_sli,
- .vece = MO_16 },
- { .fni4 = gen_shl32_ins_i32,
- .fniv = gen_shl_ins_vec,
- .load_dest = true,
- .opt_opc = vecop_list_sli,
- .vece = MO_32 },
- { .fni8 = gen_shl64_ins_i64,
- .fniv = gen_shl_ins_vec,
- .prefer_i64 = TCG_TARGET_REG_BITS == 64,
- .load_dest = true,
- .opt_opc = vecop_list_sli,
- .vece = MO_64 },
-};
+ /* tszimm encoding produces immediates in the range [0..esize-1]. */
+ tcg_debug_assert(shift >= 0);
+ tcg_debug_assert(shift < (8 << vece));
+
+ if (shift == 0) {
+ tcg_gen_gvec_mov(vece, rd_ofs, rm_ofs, opr_sz, max_sz);
+ } else {
+ tcg_gen_gvec_2i(rd_ofs, rm_ofs, opr_sz, max_sz, shift, &ops[vece]);
+ }
+}
static void gen_mla8_i32(TCGv_i32 d, TCGv_i32 a, TCGv_i32 b)
{
@@ -4181,62 +4435,69 @@
/* Note that while NEON does not support VMLA and VMLS as 64-bit ops,
* these tables are shared with AArch64 which does support them.
*/
+void gen_gvec_mla(unsigned vece, uint32_t rd_ofs, uint32_t rn_ofs,
+ uint32_t rm_ofs, uint32_t opr_sz, uint32_t max_sz)
+{
+ static const TCGOpcode vecop_list[] = {
+ INDEX_op_mul_vec, INDEX_op_add_vec, 0
+ };
+ static const GVecGen3 ops[4] = {
+ { .fni4 = gen_mla8_i32,
+ .fniv = gen_mla_vec,
+ .load_dest = true,
+ .opt_opc = vecop_list,
+ .vece = MO_8 },
+ { .fni4 = gen_mla16_i32,
+ .fniv = gen_mla_vec,
+ .load_dest = true,
+ .opt_opc = vecop_list,
+ .vece = MO_16 },
+ { .fni4 = gen_mla32_i32,
+ .fniv = gen_mla_vec,
+ .load_dest = true,
+ .opt_opc = vecop_list,
+ .vece = MO_32 },
+ { .fni8 = gen_mla64_i64,
+ .fniv = gen_mla_vec,
+ .prefer_i64 = TCG_TARGET_REG_BITS == 64,
+ .load_dest = true,
+ .opt_opc = vecop_list,
+ .vece = MO_64 },
+ };
+ tcg_gen_gvec_3(rd_ofs, rn_ofs, rm_ofs, opr_sz, max_sz, &ops[vece]);
+}
-static const TCGOpcode vecop_list_mla[] = {
- INDEX_op_mul_vec, INDEX_op_add_vec, 0
-};
-
-static const TCGOpcode vecop_list_mls[] = {
- INDEX_op_mul_vec, INDEX_op_sub_vec, 0
-};
-
-const GVecGen3 mla_op[4] = {
- { .fni4 = gen_mla8_i32,
- .fniv = gen_mla_vec,
- .load_dest = true,
- .opt_opc = vecop_list_mla,
- .vece = MO_8 },
- { .fni4 = gen_mla16_i32,
- .fniv = gen_mla_vec,
- .load_dest = true,
- .opt_opc = vecop_list_mla,
- .vece = MO_16 },
- { .fni4 = gen_mla32_i32,
- .fniv = gen_mla_vec,
- .load_dest = true,
- .opt_opc = vecop_list_mla,
- .vece = MO_32 },
- { .fni8 = gen_mla64_i64,
- .fniv = gen_mla_vec,
- .prefer_i64 = TCG_TARGET_REG_BITS == 64,
- .load_dest = true,
- .opt_opc = vecop_list_mla,
- .vece = MO_64 },
-};
-
-const GVecGen3 mls_op[4] = {
- { .fni4 = gen_mls8_i32,
- .fniv = gen_mls_vec,
- .load_dest = true,
- .opt_opc = vecop_list_mls,
- .vece = MO_8 },
- { .fni4 = gen_mls16_i32,
- .fniv = gen_mls_vec,
- .load_dest = true,
- .opt_opc = vecop_list_mls,
- .vece = MO_16 },
- { .fni4 = gen_mls32_i32,
- .fniv = gen_mls_vec,
- .load_dest = true,
- .opt_opc = vecop_list_mls,
- .vece = MO_32 },
- { .fni8 = gen_mls64_i64,
- .fniv = gen_mls_vec,
- .prefer_i64 = TCG_TARGET_REG_BITS == 64,
- .load_dest = true,
- .opt_opc = vecop_list_mls,
- .vece = MO_64 },
-};
+void gen_gvec_mls(unsigned vece, uint32_t rd_ofs, uint32_t rn_ofs,
+ uint32_t rm_ofs, uint32_t opr_sz, uint32_t max_sz)
+{
+ static const TCGOpcode vecop_list[] = {
+ INDEX_op_mul_vec, INDEX_op_sub_vec, 0
+ };
+ static const GVecGen3 ops[4] = {
+ { .fni4 = gen_mls8_i32,
+ .fniv = gen_mls_vec,
+ .load_dest = true,
+ .opt_opc = vecop_list,
+ .vece = MO_8 },
+ { .fni4 = gen_mls16_i32,
+ .fniv = gen_mls_vec,
+ .load_dest = true,
+ .opt_opc = vecop_list,
+ .vece = MO_16 },
+ { .fni4 = gen_mls32_i32,
+ .fniv = gen_mls_vec,
+ .load_dest = true,
+ .opt_opc = vecop_list,
+ .vece = MO_32 },
+ { .fni8 = gen_mls64_i64,
+ .fniv = gen_mls_vec,
+ .prefer_i64 = TCG_TARGET_REG_BITS == 64,
+ .load_dest = true,
+ .opt_opc = vecop_list,
+ .vece = MO_64 },
+ };
+ tcg_gen_gvec_3(rd_ofs, rn_ofs, rm_ofs, opr_sz, max_sz, &ops[vece]);
+}
/* CMTST : test is "if (X & Y != 0)". */
static void gen_cmtst_i32(TCGv_i32 d, TCGv_i32 a, TCGv_i32 b)
@@ -4260,27 +4521,31 @@
tcg_gen_cmp_vec(TCG_COND_NE, vece, d, d, a);
}
-static const TCGOpcode vecop_list_cmtst[] = { INDEX_op_cmp_vec, 0 };
-
-const GVecGen3 cmtst_op[4] = {
- { .fni4 = gen_helper_neon_tst_u8,
- .fniv = gen_cmtst_vec,
- .opt_opc = vecop_list_cmtst,
- .vece = MO_8 },
- { .fni4 = gen_helper_neon_tst_u16,
- .fniv = gen_cmtst_vec,
- .opt_opc = vecop_list_cmtst,
- .vece = MO_16 },
- { .fni4 = gen_cmtst_i32,
- .fniv = gen_cmtst_vec,
- .opt_opc = vecop_list_cmtst,
- .vece = MO_32 },
- { .fni8 = gen_cmtst_i64,
- .fniv = gen_cmtst_vec,
- .prefer_i64 = TCG_TARGET_REG_BITS == 64,
- .opt_opc = vecop_list_cmtst,
- .vece = MO_64 },
-};
+void gen_gvec_cmtst(unsigned vece, uint32_t rd_ofs, uint32_t rn_ofs,
+ uint32_t rm_ofs, uint32_t opr_sz, uint32_t max_sz)
+{
+ static const TCGOpcode vecop_list[] = { INDEX_op_cmp_vec, 0 };
+ static const GVecGen3 ops[4] = {
+ { .fni4 = gen_helper_neon_tst_u8,
+ .fniv = gen_cmtst_vec,
+ .opt_opc = vecop_list,
+ .vece = MO_8 },
+ { .fni4 = gen_helper_neon_tst_u16,
+ .fniv = gen_cmtst_vec,
+ .opt_opc = vecop_list,
+ .vece = MO_16 },
+ { .fni4 = gen_cmtst_i32,
+ .fniv = gen_cmtst_vec,
+ .opt_opc = vecop_list,
+ .vece = MO_32 },
+ { .fni8 = gen_cmtst_i64,
+ .fniv = gen_cmtst_vec,
+ .prefer_i64 = TCG_TARGET_REG_BITS == 64,
+ .opt_opc = vecop_list,
+ .vece = MO_64 },
+ };
+ tcg_gen_gvec_3(rd_ofs, rn_ofs, rm_ofs, opr_sz, max_sz, &ops[vece]);
+}
void gen_ushl_i32(TCGv_i32 dst, TCGv_i32 src, TCGv_i32 shift)
{
@@ -4398,29 +4663,33 @@
tcg_temp_free_vec(rsh);
}
-static const TCGOpcode ushl_list[] = {
- INDEX_op_neg_vec, INDEX_op_shlv_vec,
- INDEX_op_shrv_vec, INDEX_op_cmp_vec, 0
-};
-
-const GVecGen3 ushl_op[4] = {
- { .fniv = gen_ushl_vec,
- .fno = gen_helper_gvec_ushl_b,
- .opt_opc = ushl_list,
- .vece = MO_8 },
- { .fniv = gen_ushl_vec,
- .fno = gen_helper_gvec_ushl_h,
- .opt_opc = ushl_list,
- .vece = MO_16 },
- { .fni4 = gen_ushl_i32,
- .fniv = gen_ushl_vec,
- .opt_opc = ushl_list,
- .vece = MO_32 },
- { .fni8 = gen_ushl_i64,
- .fniv = gen_ushl_vec,
- .opt_opc = ushl_list,
- .vece = MO_64 },
-};
+void gen_gvec_ushl(unsigned vece, uint32_t rd_ofs, uint32_t rn_ofs,
+ uint32_t rm_ofs, uint32_t opr_sz, uint32_t max_sz)
+{
+ static const TCGOpcode vecop_list[] = {
+ INDEX_op_neg_vec, INDEX_op_shlv_vec,
+ INDEX_op_shrv_vec, INDEX_op_cmp_vec, 0
+ };
+ static const GVecGen3 ops[4] = {
+ { .fniv = gen_ushl_vec,
+ .fno = gen_helper_gvec_ushl_b,
+ .opt_opc = vecop_list,
+ .vece = MO_8 },
+ { .fniv = gen_ushl_vec,
+ .fno = gen_helper_gvec_ushl_h,
+ .opt_opc = vecop_list,
+ .vece = MO_16 },
+ { .fni4 = gen_ushl_i32,
+ .fniv = gen_ushl_vec,
+ .opt_opc = vecop_list,
+ .vece = MO_32 },
+ { .fni8 = gen_ushl_i64,
+ .fniv = gen_ushl_vec,
+ .opt_opc = vecop_list,
+ .vece = MO_64 },
+ };
+ tcg_gen_gvec_3(rd_ofs, rn_ofs, rm_ofs, opr_sz, max_sz, &ops[vece]);
+}
void gen_sshl_i32(TCGv_i32 dst, TCGv_i32 src, TCGv_i32 shift)
{
@@ -4532,29 +4801,33 @@
tcg_temp_free_vec(tmp);
}
-static const TCGOpcode sshl_list[] = {
- INDEX_op_neg_vec, INDEX_op_umin_vec, INDEX_op_shlv_vec,
- INDEX_op_sarv_vec, INDEX_op_cmp_vec, INDEX_op_cmpsel_vec, 0
-};
-
-const GVecGen3 sshl_op[4] = {
- { .fniv = gen_sshl_vec,
- .fno = gen_helper_gvec_sshl_b,
- .opt_opc = sshl_list,
- .vece = MO_8 },
- { .fniv = gen_sshl_vec,
- .fno = gen_helper_gvec_sshl_h,
- .opt_opc = sshl_list,
- .vece = MO_16 },
- { .fni4 = gen_sshl_i32,
- .fniv = gen_sshl_vec,
- .opt_opc = sshl_list,
- .vece = MO_32 },
- { .fni8 = gen_sshl_i64,
- .fniv = gen_sshl_vec,
- .opt_opc = sshl_list,
- .vece = MO_64 },
-};
+void gen_gvec_sshl(unsigned vece, uint32_t rd_ofs, uint32_t rn_ofs,
+ uint32_t rm_ofs, uint32_t opr_sz, uint32_t max_sz)
+{
+ static const TCGOpcode vecop_list[] = {
+ INDEX_op_neg_vec, INDEX_op_umin_vec, INDEX_op_shlv_vec,
+ INDEX_op_sarv_vec, INDEX_op_cmp_vec, INDEX_op_cmpsel_vec, 0
+ };
+ static const GVecGen3 ops[4] = {
+ { .fniv = gen_sshl_vec,
+ .fno = gen_helper_gvec_sshl_b,
+ .opt_opc = vecop_list,
+ .vece = MO_8 },
+ { .fniv = gen_sshl_vec,
+ .fno = gen_helper_gvec_sshl_h,
+ .opt_opc = vecop_list,
+ .vece = MO_16 },
+ { .fni4 = gen_sshl_i32,
+ .fniv = gen_sshl_vec,
+ .opt_opc = vecop_list,
+ .vece = MO_32 },
+ { .fni8 = gen_sshl_i64,
+ .fniv = gen_sshl_vec,
+ .opt_opc = vecop_list,
+ .vece = MO_64 },
+ };
+ tcg_gen_gvec_3(rd_ofs, rn_ofs, rm_ofs, opr_sz, max_sz, &ops[vece]);
+}
static void gen_uqadd_vec(unsigned vece, TCGv_vec t, TCGv_vec sat,
TCGv_vec a, TCGv_vec b)
@@ -4567,32 +4840,37 @@
tcg_temp_free_vec(x);
}
-static const TCGOpcode vecop_list_uqadd[] = {
- INDEX_op_usadd_vec, INDEX_op_cmp_vec, INDEX_op_add_vec, 0
-};
-
-const GVecGen4 uqadd_op[4] = {
- { .fniv = gen_uqadd_vec,
- .fno = gen_helper_gvec_uqadd_b,
- .write_aofs = true,
- .opt_opc = vecop_list_uqadd,
- .vece = MO_8 },
- { .fniv = gen_uqadd_vec,
- .fno = gen_helper_gvec_uqadd_h,
- .write_aofs = true,
- .opt_opc = vecop_list_uqadd,
- .vece = MO_16 },
- { .fniv = gen_uqadd_vec,
- .fno = gen_helper_gvec_uqadd_s,
- .write_aofs = true,
- .opt_opc = vecop_list_uqadd,
- .vece = MO_32 },
- { .fniv = gen_uqadd_vec,
- .fno = gen_helper_gvec_uqadd_d,
- .write_aofs = true,
- .opt_opc = vecop_list_uqadd,
- .vece = MO_64 },
-};
+void gen_gvec_uqadd_qc(unsigned vece, uint32_t rd_ofs, uint32_t rn_ofs,
+ uint32_t rm_ofs, uint32_t opr_sz, uint32_t max_sz)
+{
+ static const TCGOpcode vecop_list[] = {
+ INDEX_op_usadd_vec, INDEX_op_cmp_vec, INDEX_op_add_vec, 0
+ };
+ static const GVecGen4 ops[4] = {
+ { .fniv = gen_uqadd_vec,
+ .fno = gen_helper_gvec_uqadd_b,
+ .write_aofs = true,
+ .opt_opc = vecop_list,
+ .vece = MO_8 },
+ { .fniv = gen_uqadd_vec,
+ .fno = gen_helper_gvec_uqadd_h,
+ .write_aofs = true,
+ .opt_opc = vecop_list,
+ .vece = MO_16 },
+ { .fniv = gen_uqadd_vec,
+ .fno = gen_helper_gvec_uqadd_s,
+ .write_aofs = true,
+ .opt_opc = vecop_list,
+ .vece = MO_32 },
+ { .fniv = gen_uqadd_vec,
+ .fno = gen_helper_gvec_uqadd_d,
+ .write_aofs = true,
+ .opt_opc = vecop_list,
+ .vece = MO_64 },
+ };
+ tcg_gen_gvec_4(rd_ofs, offsetof(CPUARMState, vfp.qc),
+ rn_ofs, rm_ofs, opr_sz, max_sz, &ops[vece]);
+}
static void gen_sqadd_vec(unsigned vece, TCGv_vec t, TCGv_vec sat,
TCGv_vec a, TCGv_vec b)
@@ -4605,32 +4883,37 @@
tcg_temp_free_vec(x);
}
-static const TCGOpcode vecop_list_sqadd[] = {
- INDEX_op_ssadd_vec, INDEX_op_cmp_vec, INDEX_op_add_vec, 0
-};
-
-const GVecGen4 sqadd_op[4] = {
- { .fniv = gen_sqadd_vec,
- .fno = gen_helper_gvec_sqadd_b,
- .opt_opc = vecop_list_sqadd,
- .write_aofs = true,
- .vece = MO_8 },
- { .fniv = gen_sqadd_vec,
- .fno = gen_helper_gvec_sqadd_h,
- .opt_opc = vecop_list_sqadd,
- .write_aofs = true,
- .vece = MO_16 },
- { .fniv = gen_sqadd_vec,
- .fno = gen_helper_gvec_sqadd_s,
- .opt_opc = vecop_list_sqadd,
- .write_aofs = true,
- .vece = MO_32 },
- { .fniv = gen_sqadd_vec,
- .fno = gen_helper_gvec_sqadd_d,
- .opt_opc = vecop_list_sqadd,
- .write_aofs = true,
- .vece = MO_64 },
-};
+void gen_gvec_sqadd_qc(unsigned vece, uint32_t rd_ofs, uint32_t rn_ofs,
+ uint32_t rm_ofs, uint32_t opr_sz, uint32_t max_sz)
+{
+ static const TCGOpcode vecop_list[] = {
+ INDEX_op_ssadd_vec, INDEX_op_cmp_vec, INDEX_op_add_vec, 0
+ };
+ static const GVecGen4 ops[4] = {
+ { .fniv = gen_sqadd_vec,
+ .fno = gen_helper_gvec_sqadd_b,
+ .opt_opc = vecop_list,
+ .write_aofs = true,
+ .vece = MO_8 },
+ { .fniv = gen_sqadd_vec,
+ .fno = gen_helper_gvec_sqadd_h,
+ .opt_opc = vecop_list,
+ .write_aofs = true,
+ .vece = MO_16 },
+ { .fniv = gen_sqadd_vec,
+ .fno = gen_helper_gvec_sqadd_s,
+ .opt_opc = vecop_list,
+ .write_aofs = true,
+ .vece = MO_32 },
+ { .fniv = gen_sqadd_vec,
+ .fno = gen_helper_gvec_sqadd_d,
+ .opt_opc = vecop_list,
+ .write_aofs = true,
+ .vece = MO_64 },
+ };
+ tcg_gen_gvec_4(rd_ofs, offsetof(CPUARMState, vfp.qc),
+ rn_ofs, rm_ofs, opr_sz, max_sz, &ops[vece]);
+}
static void gen_uqsub_vec(unsigned vece, TCGv_vec t, TCGv_vec sat,
TCGv_vec a, TCGv_vec b)
@@ -4643,32 +4926,37 @@
tcg_temp_free_vec(x);
}
-static const TCGOpcode vecop_list_uqsub[] = {
- INDEX_op_ussub_vec, INDEX_op_cmp_vec, INDEX_op_sub_vec, 0
-};
-
-const GVecGen4 uqsub_op[4] = {
- { .fniv = gen_uqsub_vec,
- .fno = gen_helper_gvec_uqsub_b,
- .opt_opc = vecop_list_uqsub,
- .write_aofs = true,
- .vece = MO_8 },
- { .fniv = gen_uqsub_vec,
- .fno = gen_helper_gvec_uqsub_h,
- .opt_opc = vecop_list_uqsub,
- .write_aofs = true,
- .vece = MO_16 },
- { .fniv = gen_uqsub_vec,
- .fno = gen_helper_gvec_uqsub_s,
- .opt_opc = vecop_list_uqsub,
- .write_aofs = true,
- .vece = MO_32 },
- { .fniv = gen_uqsub_vec,
- .fno = gen_helper_gvec_uqsub_d,
- .opt_opc = vecop_list_uqsub,
- .write_aofs = true,
- .vece = MO_64 },
-};
+void gen_gvec_uqsub_qc(unsigned vece, uint32_t rd_ofs, uint32_t rn_ofs,
+ uint32_t rm_ofs, uint32_t opr_sz, uint32_t max_sz)
+{
+ static const TCGOpcode vecop_list[] = {
+ INDEX_op_ussub_vec, INDEX_op_cmp_vec, INDEX_op_sub_vec, 0
+ };
+ static const GVecGen4 ops[4] = {
+ { .fniv = gen_uqsub_vec,
+ .fno = gen_helper_gvec_uqsub_b,
+ .opt_opc = vecop_list,
+ .write_aofs = true,
+ .vece = MO_8 },
+ { .fniv = gen_uqsub_vec,
+ .fno = gen_helper_gvec_uqsub_h,
+ .opt_opc = vecop_list,
+ .write_aofs = true,
+ .vece = MO_16 },
+ { .fniv = gen_uqsub_vec,
+ .fno = gen_helper_gvec_uqsub_s,
+ .opt_opc = vecop_list,
+ .write_aofs = true,
+ .vece = MO_32 },
+ { .fniv = gen_uqsub_vec,
+ .fno = gen_helper_gvec_uqsub_d,
+ .opt_opc = vecop_list,
+ .write_aofs = true,
+ .vece = MO_64 },
+ };
+ tcg_gen_gvec_4(rd_ofs, offsetof(CPUARMState, vfp.qc),
+ rn_ofs, rm_ofs, opr_sz, max_sz, &ops[vece]);
+}
static void gen_sqsub_vec(unsigned vece, TCGv_vec t, TCGv_vec sat,
TCGv_vec a, TCGv_vec b)
@@ -4681,32 +4969,275 @@
tcg_temp_free_vec(x);
}
-static const TCGOpcode vecop_list_sqsub[] = {
- INDEX_op_sssub_vec, INDEX_op_cmp_vec, INDEX_op_sub_vec, 0
-};
+void gen_gvec_sqsub_qc(unsigned vece, uint32_t rd_ofs, uint32_t rn_ofs,
+ uint32_t rm_ofs, uint32_t opr_sz, uint32_t max_sz)
+{
+ static const TCGOpcode vecop_list[] = {
+ INDEX_op_sssub_vec, INDEX_op_cmp_vec, INDEX_op_sub_vec, 0
+ };
+ static const GVecGen4 ops[4] = {
+ { .fniv = gen_sqsub_vec,
+ .fno = gen_helper_gvec_sqsub_b,
+ .opt_opc = vecop_list,
+ .write_aofs = true,
+ .vece = MO_8 },
+ { .fniv = gen_sqsub_vec,
+ .fno = gen_helper_gvec_sqsub_h,
+ .opt_opc = vecop_list,
+ .write_aofs = true,
+ .vece = MO_16 },
+ { .fniv = gen_sqsub_vec,
+ .fno = gen_helper_gvec_sqsub_s,
+ .opt_opc = vecop_list,
+ .write_aofs = true,
+ .vece = MO_32 },
+ { .fniv = gen_sqsub_vec,
+ .fno = gen_helper_gvec_sqsub_d,
+ .opt_opc = vecop_list,
+ .write_aofs = true,
+ .vece = MO_64 },
+ };
+ tcg_gen_gvec_4(rd_ofs, offsetof(CPUARMState, vfp.qc),
+ rn_ofs, rm_ofs, opr_sz, max_sz, &ops[vece]);
+}
-const GVecGen4 sqsub_op[4] = {
- { .fniv = gen_sqsub_vec,
- .fno = gen_helper_gvec_sqsub_b,
- .opt_opc = vecop_list_sqsub,
- .write_aofs = true,
- .vece = MO_8 },
- { .fniv = gen_sqsub_vec,
- .fno = gen_helper_gvec_sqsub_h,
- .opt_opc = vecop_list_sqsub,
- .write_aofs = true,
- .vece = MO_16 },
- { .fniv = gen_sqsub_vec,
- .fno = gen_helper_gvec_sqsub_s,
- .opt_opc = vecop_list_sqsub,
- .write_aofs = true,
- .vece = MO_32 },
- { .fniv = gen_sqsub_vec,
- .fno = gen_helper_gvec_sqsub_d,
- .opt_opc = vecop_list_sqsub,
- .write_aofs = true,
- .vece = MO_64 },
-};
+static void gen_sabd_i32(TCGv_i32 d, TCGv_i32 a, TCGv_i32 b)
+{
+ TCGv_i32 t = tcg_temp_new_i32();
+
+ tcg_gen_sub_i32(t, a, b);
+ tcg_gen_sub_i32(d, b, a);
+ tcg_gen_movcond_i32(TCG_COND_LT, d, a, b, d, t);
+ tcg_temp_free_i32(t);
+}
+
+static void gen_sabd_i64(TCGv_i64 d, TCGv_i64 a, TCGv_i64 b)
+{
+ TCGv_i64 t = tcg_temp_new_i64();
+
+ tcg_gen_sub_i64(t, a, b);
+ tcg_gen_sub_i64(d, b, a);
+ tcg_gen_movcond_i64(TCG_COND_LT, d, a, b, d, t);
+ tcg_temp_free_i64(t);
+}
+
+static void gen_sabd_vec(unsigned vece, TCGv_vec d, TCGv_vec a, TCGv_vec b)
+{
+ TCGv_vec t = tcg_temp_new_vec_matching(d);
+
+ tcg_gen_smin_vec(vece, t, a, b);
+ tcg_gen_smax_vec(vece, d, a, b);
+ tcg_gen_sub_vec(vece, d, d, t);
+ tcg_temp_free_vec(t);
+}
+
+void gen_gvec_sabd(unsigned vece, uint32_t rd_ofs, uint32_t rn_ofs,
+ uint32_t rm_ofs, uint32_t opr_sz, uint32_t max_sz)
+{
+ static const TCGOpcode vecop_list[] = {
+ INDEX_op_sub_vec, INDEX_op_smin_vec, INDEX_op_smax_vec, 0
+ };
+ static const GVecGen3 ops[4] = {
+ { .fniv = gen_sabd_vec,
+ .fno = gen_helper_gvec_sabd_b,
+ .opt_opc = vecop_list,
+ .vece = MO_8 },
+ { .fniv = gen_sabd_vec,
+ .fno = gen_helper_gvec_sabd_h,
+ .opt_opc = vecop_list,
+ .vece = MO_16 },
+ { .fni4 = gen_sabd_i32,
+ .fniv = gen_sabd_vec,
+ .fno = gen_helper_gvec_sabd_s,
+ .opt_opc = vecop_list,
+ .vece = MO_32 },
+ { .fni8 = gen_sabd_i64,
+ .fniv = gen_sabd_vec,
+ .fno = gen_helper_gvec_sabd_d,
+ .prefer_i64 = TCG_TARGET_REG_BITS == 64,
+ .opt_opc = vecop_list,
+ .vece = MO_64 },
+ };
+ tcg_gen_gvec_3(rd_ofs, rn_ofs, rm_ofs, opr_sz, max_sz, &ops[vece]);
+}
+
+static void gen_uabd_i32(TCGv_i32 d, TCGv_i32 a, TCGv_i32 b)
+{
+ TCGv_i32 t = tcg_temp_new_i32();
+
+ tcg_gen_sub_i32(t, a, b);
+ tcg_gen_sub_i32(d, b, a);
+ tcg_gen_movcond_i32(TCG_COND_LTU, d, a, b, d, t);
+ tcg_temp_free_i32(t);
+}
+
+static void gen_uabd_i64(TCGv_i64 d, TCGv_i64 a, TCGv_i64 b)
+{
+ TCGv_i64 t = tcg_temp_new_i64();
+
+ tcg_gen_sub_i64(t, a, b);
+ tcg_gen_sub_i64(d, b, a);
+ tcg_gen_movcond_i64(TCG_COND_LTU, d, a, b, d, t);
+ tcg_temp_free_i64(t);
+}
+
+static void gen_uabd_vec(unsigned vece, TCGv_vec d, TCGv_vec a, TCGv_vec b)
+{
+ TCGv_vec t = tcg_temp_new_vec_matching(d);
+
+ tcg_gen_umin_vec(vece, t, a, b);
+ tcg_gen_umax_vec(vece, d, a, b);
+ tcg_gen_sub_vec(vece, d, d, t);
+ tcg_temp_free_vec(t);
+}
+
+void gen_gvec_uabd(unsigned vece, uint32_t rd_ofs, uint32_t rn_ofs,
+ uint32_t rm_ofs, uint32_t opr_sz, uint32_t max_sz)
+{
+ static const TCGOpcode vecop_list[] = {
+ INDEX_op_sub_vec, INDEX_op_umin_vec, INDEX_op_umax_vec, 0
+ };
+ static const GVecGen3 ops[4] = {
+ { .fniv = gen_uabd_vec,
+ .fno = gen_helper_gvec_uabd_b,
+ .opt_opc = vecop_list,
+ .vece = MO_8 },
+ { .fniv = gen_uabd_vec,
+ .fno = gen_helper_gvec_uabd_h,
+ .opt_opc = vecop_list,
+ .vece = MO_16 },
+ { .fni4 = gen_uabd_i32,
+ .fniv = gen_uabd_vec,
+ .fno = gen_helper_gvec_uabd_s,
+ .opt_opc = vecop_list,
+ .vece = MO_32 },
+ { .fni8 = gen_uabd_i64,
+ .fniv = gen_uabd_vec,
+ .fno = gen_helper_gvec_uabd_d,
+ .prefer_i64 = TCG_TARGET_REG_BITS == 64,
+ .opt_opc = vecop_list,
+ .vece = MO_64 },
+ };
+ tcg_gen_gvec_3(rd_ofs, rn_ofs, rm_ofs, opr_sz, max_sz, &ops[vece]);
+}
+
+static void gen_saba_i32(TCGv_i32 d, TCGv_i32 a, TCGv_i32 b)
+{
+ TCGv_i32 t = tcg_temp_new_i32();
+ gen_sabd_i32(t, a, b);
+ tcg_gen_add_i32(d, d, t);
+ tcg_temp_free_i32(t);
+}
+
+static void gen_saba_i64(TCGv_i64 d, TCGv_i64 a, TCGv_i64 b)
+{
+ TCGv_i64 t = tcg_temp_new_i64();
+ gen_sabd_i64(t, a, b);
+ tcg_gen_add_i64(d, d, t);
+ tcg_temp_free_i64(t);
+}
+
+static void gen_saba_vec(unsigned vece, TCGv_vec d, TCGv_vec a, TCGv_vec b)
+{
+ TCGv_vec t = tcg_temp_new_vec_matching(d);
+ gen_sabd_vec(vece, t, a, b);
+ tcg_gen_add_vec(vece, d, d, t);
+ tcg_temp_free_vec(t);
+}
+
+void gen_gvec_saba(unsigned vece, uint32_t rd_ofs, uint32_t rn_ofs,
+ uint32_t rm_ofs, uint32_t opr_sz, uint32_t max_sz)
+{
+ static const TCGOpcode vecop_list[] = {
+ INDEX_op_sub_vec, INDEX_op_add_vec,
+ INDEX_op_smin_vec, INDEX_op_smax_vec, 0
+ };
+ static const GVecGen3 ops[4] = {
+ { .fniv = gen_saba_vec,
+ .fno = gen_helper_gvec_saba_b,
+ .opt_opc = vecop_list,
+ .load_dest = true,
+ .vece = MO_8 },
+ { .fniv = gen_saba_vec,
+ .fno = gen_helper_gvec_saba_h,
+ .opt_opc = vecop_list,
+ .load_dest = true,
+ .vece = MO_16 },
+ { .fni4 = gen_saba_i32,
+ .fniv = gen_saba_vec,
+ .fno = gen_helper_gvec_saba_s,
+ .opt_opc = vecop_list,
+ .load_dest = true,
+ .vece = MO_32 },
+ { .fni8 = gen_saba_i64,
+ .fniv = gen_saba_vec,
+ .fno = gen_helper_gvec_saba_d,
+ .prefer_i64 = TCG_TARGET_REG_BITS == 64,
+ .opt_opc = vecop_list,
+ .load_dest = true,
+ .vece = MO_64 },
+ };
+ tcg_gen_gvec_3(rd_ofs, rn_ofs, rm_ofs, opr_sz, max_sz, &ops[vece]);
+}
+
+static void gen_uaba_i32(TCGv_i32 d, TCGv_i32 a, TCGv_i32 b)
+{
+ TCGv_i32 t = tcg_temp_new_i32();
+ gen_uabd_i32(t, a, b);
+ tcg_gen_add_i32(d, d, t);
+ tcg_temp_free_i32(t);
+}
+
+static void gen_uaba_i64(TCGv_i64 d, TCGv_i64 a, TCGv_i64 b)
+{
+ TCGv_i64 t = tcg_temp_new_i64();
+ gen_uabd_i64(t, a, b);
+ tcg_gen_add_i64(d, d, t);
+ tcg_temp_free_i64(t);
+}
+
+static void gen_uaba_vec(unsigned vece, TCGv_vec d, TCGv_vec a, TCGv_vec b)
+{
+ TCGv_vec t = tcg_temp_new_vec_matching(d);
+ gen_uabd_vec(vece, t, a, b);
+ tcg_gen_add_vec(vece, d, d, t);
+ tcg_temp_free_vec(t);
+}
+
+void gen_gvec_uaba(unsigned vece, uint32_t rd_ofs, uint32_t rn_ofs,
+ uint32_t rm_ofs, uint32_t opr_sz, uint32_t max_sz)
+{
+ static const TCGOpcode vecop_list[] = {
+ INDEX_op_sub_vec, INDEX_op_add_vec,
+ INDEX_op_umin_vec, INDEX_op_umax_vec, 0
+ };
+ static const GVecGen3 ops[4] = {
+ { .fniv = gen_uaba_vec,
+ .fno = gen_helper_gvec_uaba_b,
+ .opt_opc = vecop_list,
+ .load_dest = true,
+ .vece = MO_8 },
+ { .fniv = gen_uaba_vec,
+ .fno = gen_helper_gvec_uaba_h,
+ .opt_opc = vecop_list,
+ .load_dest = true,
+ .vece = MO_16 },
+ { .fni4 = gen_uaba_i32,
+ .fniv = gen_uaba_vec,
+ .fno = gen_helper_gvec_uaba_s,
+ .opt_opc = vecop_list,
+ .load_dest = true,
+ .vece = MO_32 },
+ { .fni8 = gen_uaba_i64,
+ .fniv = gen_uaba_vec,
+ .fno = gen_helper_gvec_uaba_d,
+ .prefer_i64 = TCG_TARGET_REG_BITS == 64,
+ .opt_opc = vecop_list,
+ .load_dest = true,
+ .vece = MO_64 },
+ };
+ tcg_gen_gvec_3(rd_ofs, rn_ofs, rm_ofs, opr_sz, max_sz, &ops[vece]);
+}
/* Translate a NEON data processing instruction. Return nonzero if the
instruction is invalid.
@@ -4722,12 +5253,11 @@
int shift;
int pass;
int count;
- int pairwise;
int u;
int vec_size;
uint32_t imm;
TCGv_i32 tmp, tmp2, tmp3, tmp4, tmp5;
- TCGv_ptr ptr1, ptr2, ptr3;
+ TCGv_ptr ptr1, ptr2;
TCGv_i64 tmp64;
if (!arm_dc_feature(s, ARM_FEATURE_NEON)) {
@@ -4758,413 +5288,8 @@
rm_ofs = neon_reg_offset(rm, 0);
if ((insn & (1 << 23)) == 0) {
- /* Three register same length. */
- op = ((insn >> 7) & 0x1e) | ((insn >> 4) & 1);
- /* Catch invalid op and bad size combinations: UNDEF */
- if ((neon_3r_sizes[op] & (1 << size)) == 0) {
- return 1;
- }
- /* All insns of this form UNDEF for either this condition or the
- * superset of cases "Q==1"; we catch the latter later.
- */
- if (q && ((rd | rn | rm) & 1)) {
- return 1;
- }
- switch (op) {
- case NEON_3R_SHA:
- /* The SHA-1/SHA-256 3-register instructions require special
- * treatment here, as their size field is overloaded as an
- * op type selector, and they all consume their input in a
- * single pass.
- */
- if (!q) {
- return 1;
- }
- if (!u) { /* SHA-1 */
- if (!dc_isar_feature(aa32_sha1, s)) {
- return 1;
- }
- ptr1 = vfp_reg_ptr(true, rd);
- ptr2 = vfp_reg_ptr(true, rn);
- ptr3 = vfp_reg_ptr(true, rm);
- tmp4 = tcg_const_i32(size);
- gen_helper_crypto_sha1_3reg(ptr1, ptr2, ptr3, tmp4);
- tcg_temp_free_i32(tmp4);
- } else { /* SHA-256 */
- if (!dc_isar_feature(aa32_sha2, s) || size == 3) {
- return 1;
- }
- ptr1 = vfp_reg_ptr(true, rd);
- ptr2 = vfp_reg_ptr(true, rn);
- ptr3 = vfp_reg_ptr(true, rm);
- switch (size) {
- case 0:
- gen_helper_crypto_sha256h(ptr1, ptr2, ptr3);
- break;
- case 1:
- gen_helper_crypto_sha256h2(ptr1, ptr2, ptr3);
- break;
- case 2:
- gen_helper_crypto_sha256su1(ptr1, ptr2, ptr3);
- break;
- }
- }
- tcg_temp_free_ptr(ptr1);
- tcg_temp_free_ptr(ptr2);
- tcg_temp_free_ptr(ptr3);
- return 0;
-
- case NEON_3R_VPADD_VQRDMLAH:
- if (!u) {
- break; /* VPADD */
- }
- /* VQRDMLAH */
- switch (size) {
- case 1:
- return do_v81_helper(s, gen_helper_gvec_qrdmlah_s16,
- q, rd, rn, rm);
- case 2:
- return do_v81_helper(s, gen_helper_gvec_qrdmlah_s32,
- q, rd, rn, rm);
- }
- return 1;
-
- case NEON_3R_VFM_VQRDMLSH:
- if (!u) {
- /* VFM, VFMS */
- if (size == 1) {
- return 1;
- }
- break;
- }
- /* VQRDMLSH */
- switch (size) {
- case 1:
- return do_v81_helper(s, gen_helper_gvec_qrdmlsh_s16,
- q, rd, rn, rm);
- case 2:
- return do_v81_helper(s, gen_helper_gvec_qrdmlsh_s32,
- q, rd, rn, rm);
- }
- return 1;
-
- case NEON_3R_VADD_VSUB:
- case NEON_3R_LOGIC:
- case NEON_3R_VMAX:
- case NEON_3R_VMIN:
- case NEON_3R_VTST_VCEQ:
- case NEON_3R_VCGT:
- case NEON_3R_VCGE:
- case NEON_3R_VQADD:
- case NEON_3R_VQSUB:
- case NEON_3R_VMUL:
- case NEON_3R_VML:
- case NEON_3R_VSHL:
- /* Already handled by decodetree */
- return 1;
- }
-
- if (size == 3) {
- /* 64-bit element instructions. */
- for (pass = 0; pass < (q ? 2 : 1); pass++) {
- neon_load_reg64(cpu_V0, rn + pass);
- neon_load_reg64(cpu_V1, rm + pass);
- switch (op) {
- case NEON_3R_VQSHL:
- if (u) {
- gen_helper_neon_qshl_u64(cpu_V0, cpu_env,
- cpu_V1, cpu_V0);
- } else {
- gen_helper_neon_qshl_s64(cpu_V0, cpu_env,
- cpu_V1, cpu_V0);
- }
- break;
- case NEON_3R_VRSHL:
- if (u) {
- gen_helper_neon_rshl_u64(cpu_V0, cpu_V1, cpu_V0);
- } else {
- gen_helper_neon_rshl_s64(cpu_V0, cpu_V1, cpu_V0);
- }
- break;
- case NEON_3R_VQRSHL:
- if (u) {
- gen_helper_neon_qrshl_u64(cpu_V0, cpu_env,
- cpu_V1, cpu_V0);
- } else {
- gen_helper_neon_qrshl_s64(cpu_V0, cpu_env,
- cpu_V1, cpu_V0);
- }
- break;
- default:
- abort();
- }
- neon_store_reg64(cpu_V0, rd + pass);
- }
- return 0;
- }
- pairwise = 0;
- switch (op) {
- case NEON_3R_VQSHL:
- case NEON_3R_VRSHL:
- case NEON_3R_VQRSHL:
- {
- int rtmp;
- /* Shift instruction operands are reversed. */
- rtmp = rn;
- rn = rm;
- rm = rtmp;
- }
- break;
- case NEON_3R_VPADD_VQRDMLAH:
- case NEON_3R_VPMAX:
- case NEON_3R_VPMIN:
- pairwise = 1;
- break;
- case NEON_3R_FLOAT_ARITH:
- pairwise = (u && size < 2); /* if VPADD (float) */
- break;
- case NEON_3R_FLOAT_MINMAX:
- pairwise = u; /* if VPMIN/VPMAX (float) */
- break;
- case NEON_3R_FLOAT_CMP:
- if (!u && size) {
- /* no encoding for U=0 C=1x */
- return 1;
- }
- break;
- case NEON_3R_FLOAT_ACMP:
- if (!u) {
- return 1;
- }
- break;
- case NEON_3R_FLOAT_MISC:
- /* VMAXNM/VMINNM in ARMv8 */
- if (u && !arm_dc_feature(s, ARM_FEATURE_V8)) {
- return 1;
- }
- break;
- case NEON_3R_VFM_VQRDMLSH:
- if (!dc_isar_feature(aa32_simdfmac, s)) {
- return 1;
- }
- break;
- default:
- break;
- }
-
- if (pairwise && q) {
- /* All the pairwise insns UNDEF if Q is set */
- return 1;
- }
-
- for (pass = 0; pass < (q ? 4 : 2); pass++) {
-
- if (pairwise) {
- /* Pairwise. */
- if (pass < 1) {
- tmp = neon_load_reg(rn, 0);
- tmp2 = neon_load_reg(rn, 1);
- } else {
- tmp = neon_load_reg(rm, 0);
- tmp2 = neon_load_reg(rm, 1);
- }
- } else {
- /* Elementwise. */
- tmp = neon_load_reg(rn, pass);
- tmp2 = neon_load_reg(rm, pass);
- }
- switch (op) {
- case NEON_3R_VHADD:
- GEN_NEON_INTEGER_OP(hadd);
- break;
- case NEON_3R_VRHADD:
- GEN_NEON_INTEGER_OP(rhadd);
- break;
- case NEON_3R_VHSUB:
- GEN_NEON_INTEGER_OP(hsub);
- break;
- case NEON_3R_VQSHL:
- GEN_NEON_INTEGER_OP_ENV(qshl);
- break;
- case NEON_3R_VRSHL:
- GEN_NEON_INTEGER_OP(rshl);
- break;
- case NEON_3R_VQRSHL:
- GEN_NEON_INTEGER_OP_ENV(qrshl);
- break;
- case NEON_3R_VABD:
- GEN_NEON_INTEGER_OP(abd);
- break;
- case NEON_3R_VABA:
- GEN_NEON_INTEGER_OP(abd);
- tcg_temp_free_i32(tmp2);
- tmp2 = neon_load_reg(rd, pass);
- gen_neon_add(size, tmp, tmp2);
- break;
- case NEON_3R_VPMAX:
- GEN_NEON_INTEGER_OP(pmax);
- break;
- case NEON_3R_VPMIN:
- GEN_NEON_INTEGER_OP(pmin);
- break;
- case NEON_3R_VQDMULH_VQRDMULH: /* Multiply high. */
- if (!u) { /* VQDMULH */
- switch (size) {
- case 1:
- gen_helper_neon_qdmulh_s16(tmp, cpu_env, tmp, tmp2);
- break;
- case 2:
- gen_helper_neon_qdmulh_s32(tmp, cpu_env, tmp, tmp2);
- break;
- default: abort();
- }
- } else { /* VQRDMULH */
- switch (size) {
- case 1:
- gen_helper_neon_qrdmulh_s16(tmp, cpu_env, tmp, tmp2);
- break;
- case 2:
- gen_helper_neon_qrdmulh_s32(tmp, cpu_env, tmp, tmp2);
- break;
- default: abort();
- }
- }
- break;
- case NEON_3R_VPADD_VQRDMLAH:
- switch (size) {
- case 0: gen_helper_neon_padd_u8(tmp, tmp, tmp2); break;
- case 1: gen_helper_neon_padd_u16(tmp, tmp, tmp2); break;
- case 2: tcg_gen_add_i32(tmp, tmp, tmp2); break;
- default: abort();
- }
- break;
- case NEON_3R_FLOAT_ARITH: /* Floating point arithmetic. */
- {
- TCGv_ptr fpstatus = get_fpstatus_ptr(1);
- switch ((u << 2) | size) {
- case 0: /* VADD */
- case 4: /* VPADD */
- gen_helper_vfp_adds(tmp, tmp, tmp2, fpstatus);
- break;
- case 2: /* VSUB */
- gen_helper_vfp_subs(tmp, tmp, tmp2, fpstatus);
- break;
- case 6: /* VABD */
- gen_helper_neon_abd_f32(tmp, tmp, tmp2, fpstatus);
- break;
- default:
- abort();
- }
- tcg_temp_free_ptr(fpstatus);
- break;
- }
- case NEON_3R_FLOAT_MULTIPLY:
- {
- TCGv_ptr fpstatus = get_fpstatus_ptr(1);
- gen_helper_vfp_muls(tmp, tmp, tmp2, fpstatus);
- if (!u) {
- tcg_temp_free_i32(tmp2);
- tmp2 = neon_load_reg(rd, pass);
- if (size == 0) {
- gen_helper_vfp_adds(tmp, tmp, tmp2, fpstatus);
- } else {
- gen_helper_vfp_subs(tmp, tmp2, tmp, fpstatus);
- }
- }
- tcg_temp_free_ptr(fpstatus);
- break;
- }
- case NEON_3R_FLOAT_CMP:
- {
- TCGv_ptr fpstatus = get_fpstatus_ptr(1);
- if (!u) {
- gen_helper_neon_ceq_f32(tmp, tmp, tmp2, fpstatus);
- } else {
- if (size == 0) {
- gen_helper_neon_cge_f32(tmp, tmp, tmp2, fpstatus);
- } else {
- gen_helper_neon_cgt_f32(tmp, tmp, tmp2, fpstatus);
- }
- }
- tcg_temp_free_ptr(fpstatus);
- break;
- }
- case NEON_3R_FLOAT_ACMP:
- {
- TCGv_ptr fpstatus = get_fpstatus_ptr(1);
- if (size == 0) {
- gen_helper_neon_acge_f32(tmp, tmp, tmp2, fpstatus);
- } else {
- gen_helper_neon_acgt_f32(tmp, tmp, tmp2, fpstatus);
- }
- tcg_temp_free_ptr(fpstatus);
- break;
- }
- case NEON_3R_FLOAT_MINMAX:
- {
- TCGv_ptr fpstatus = get_fpstatus_ptr(1);
- if (size == 0) {
- gen_helper_vfp_maxs(tmp, tmp, tmp2, fpstatus);
- } else {
- gen_helper_vfp_mins(tmp, tmp, tmp2, fpstatus);
- }
- tcg_temp_free_ptr(fpstatus);
- break;
- }
- case NEON_3R_FLOAT_MISC:
- if (u) {
- /* VMAXNM/VMINNM */
- TCGv_ptr fpstatus = get_fpstatus_ptr(1);
- if (size == 0) {
- gen_helper_vfp_maxnums(tmp, tmp, tmp2, fpstatus);
- } else {
- gen_helper_vfp_minnums(tmp, tmp, tmp2, fpstatus);
- }
- tcg_temp_free_ptr(fpstatus);
- } else {
- if (size == 0) {
- gen_helper_recps_f32(tmp, tmp, tmp2, cpu_env);
- } else {
- gen_helper_rsqrts_f32(tmp, tmp, tmp2, cpu_env);
- }
- }
- break;
- case NEON_3R_VFM_VQRDMLSH:
- {
- /* VFMA, VFMS: fused multiply-add */
- TCGv_ptr fpstatus = get_fpstatus_ptr(1);
- TCGv_i32 tmp3 = neon_load_reg(rd, pass);
- if (size) {
- /* VFMS */
- gen_helper_vfp_negs(tmp, tmp);
- }
- gen_helper_vfp_muladds(tmp, tmp, tmp2, tmp3, fpstatus);
- tcg_temp_free_i32(tmp3);
- tcg_temp_free_ptr(fpstatus);
- break;
- }
- default:
- abort();
- }
- tcg_temp_free_i32(tmp2);
-
- /* Save the result. For elementwise operations we can put it
- straight into the destination register. For pairwise operations
- we have to be careful to avoid clobbering the source operands. */
- if (pairwise && rd == rm) {
- neon_store_scratch(pass, tmp);
- } else {
- neon_store_reg(rd, pass, tmp);
- }
-
- } /* for pass */
- if (pairwise && rd == rm) {
- for (pass = 0; pass < (q ? 4 : 2); pass++) {
- tmp = neon_load_scratch(pass);
- neon_store_reg(rd, pass, tmp);
- }
- }
- /* End of 3 register same size operations. */
+ /* Three register same length: handled by decodetree */
+ return 1;
} else if (insn & (1 << 4)) {
if ((insn & 0x00380080) != 0) {
/* Two registers and shift. */
@@ -5220,19 +5345,36 @@
case 1: /* VSRA */
/* Right shift comes here negative. */
shift = -shift;
- /* Shifts larger than the element size are architecturally
- * valid. Unsigned results in all zeros; signed results
- * in all sign bits.
- */
- if (!u) {
- tcg_gen_gvec_2i(rd_ofs, rm_ofs, vec_size, vec_size,
- MIN(shift, (8 << size) - 1),
- &ssra_op[size]);
- } else if (shift >= 8 << size) {
- /* rd += 0 */
+ if (u) {
+ gen_gvec_usra(size, rd_ofs, rm_ofs, shift,
+ vec_size, vec_size);
} else {
- tcg_gen_gvec_2i(rd_ofs, rm_ofs, vec_size, vec_size,
- shift, &usra_op[size]);
+ gen_gvec_ssra(size, rd_ofs, rm_ofs, shift,
+ vec_size, vec_size);
+ }
+ return 0;
+
+ case 2: /* VRSHR */
+ /* Right shift comes here negative. */
+ shift = -shift;
+ if (u) {
+ gen_gvec_urshr(size, rd_ofs, rm_ofs, shift,
+ vec_size, vec_size);
+ } else {
+ gen_gvec_srshr(size, rd_ofs, rm_ofs, shift,
+ vec_size, vec_size);
+ }
+ return 0;
+
+ case 3: /* VRSRA */
+ /* Right shift comes here negative. */
+ shift = -shift;
+ if (u) {
+ gen_gvec_ursra(size, rd_ofs, rm_ofs, shift,
+ vec_size, vec_size);
+ } else {
+ gen_gvec_srsra(size, rd_ofs, rm_ofs, shift,
+ vec_size, vec_size);
}
return 0;
@@ -5242,31 +5384,17 @@
}
/* Right shift comes here negative. */
shift = -shift;
- /* Shift out of range leaves destination unchanged. */
- if (shift < 8 << size) {
- tcg_gen_gvec_2i(rd_ofs, rm_ofs, vec_size, vec_size,
- shift, &sri_op[size]);
- }
+ gen_gvec_sri(size, rd_ofs, rm_ofs, shift,
+ vec_size, vec_size);
return 0;
case 5: /* VSHL, VSLI */
if (u) { /* VSLI */
- /* Shift out of range leaves destination unchanged. */
- if (shift < 8 << size) {
- tcg_gen_gvec_2i(rd_ofs, rm_ofs, vec_size,
- vec_size, shift, &sli_op[size]);
- }
+ gen_gvec_sli(size, rd_ofs, rm_ofs, shift,
+ vec_size, vec_size);
} else { /* VSHL */
- /* Shifts larger than the element size are
- * architecturally valid and results in zero.
- */
- if (shift >= 8 << size) {
- tcg_gen_gvec_dup_imm(size, rd_ofs,
- vec_size, vec_size, 0);
- } else {
- tcg_gen_gvec_shli(size, rd_ofs, rm_ofs, shift,
- vec_size, vec_size);
- }
+ tcg_gen_gvec_shli(size, rd_ofs, rm_ofs, shift,
+ vec_size, vec_size);
}
return 0;
}
@@ -5287,13 +5415,6 @@
neon_load_reg64(cpu_V0, rm + pass);
tcg_gen_movi_i64(cpu_V1, imm);
switch (op) {
- case 2: /* VRSHR */
- case 3: /* VRSRA */
- if (u)
- gen_helper_neon_rshl_u64(cpu_V0, cpu_V0, cpu_V1);
- else
- gen_helper_neon_rshl_s64(cpu_V0, cpu_V0, cpu_V1);
- break;
case 6: /* VQSHLU */
gen_helper_neon_qshlu_s64(cpu_V0, cpu_env,
cpu_V0, cpu_V1);
@@ -5310,11 +5431,6 @@
default:
g_assert_not_reached();
}
- if (op == 3) {
- /* Accumulate. */
- neon_load_reg64(cpu_V1, rd + pass);
- tcg_gen_add_i64(cpu_V0, cpu_V0, cpu_V1);
- }
neon_store_reg64(cpu_V0, rd + pass);
} else { /* size < 3 */
/* Operands in T0 and T1. */
@@ -5322,10 +5438,6 @@
tmp2 = tcg_temp_new_i32();
tcg_gen_movi_i32(tmp2, imm);
switch (op) {
- case 2: /* VRSHR */
- case 3: /* VRSRA */
- GEN_NEON_INTEGER_OP(rshl);
- break;
case 6: /* VQSHLU */
switch (size) {
case 0:
@@ -5351,13 +5463,6 @@
g_assert_not_reached();
}
tcg_temp_free_i32(tmp2);
-
- if (op == 3) {
- /* Accumulate. */
- tmp2 = neon_load_reg(rd, pass);
- gen_neon_add(size, tmp, tmp2);
- tcg_temp_free_i32(tmp2);
- }
neon_store_reg(rd, pass, tmp);
}
} /* for pass */
@@ -6308,24 +6413,19 @@
break;
case NEON_2RM_VCEQ0:
- tcg_gen_gvec_2(rd_ofs, rm_ofs, vec_size,
- vec_size, &ceq0_op[size]);
+ gen_gvec_ceq0(size, rd_ofs, rm_ofs, vec_size, vec_size);
break;
case NEON_2RM_VCGT0:
- tcg_gen_gvec_2(rd_ofs, rm_ofs, vec_size,
- vec_size, &cgt0_op[size]);
+ gen_gvec_cgt0(size, rd_ofs, rm_ofs, vec_size, vec_size);
break;
case NEON_2RM_VCLE0:
- tcg_gen_gvec_2(rd_ofs, rm_ofs, vec_size,
- vec_size, &cle0_op[size]);
+ gen_gvec_cle0(size, rd_ofs, rm_ofs, vec_size, vec_size);
break;
case NEON_2RM_VCGE0:
- tcg_gen_gvec_2(rd_ofs, rm_ofs, vec_size,
- vec_size, &cge0_op[size]);
+ gen_gvec_cge0(size, rd_ofs, rm_ofs, vec_size, vec_size);
break;
case NEON_2RM_VCLT0:
- tcg_gen_gvec_2(rd_ofs, rm_ofs, vec_size,
- vec_size, &clt0_op[size]);
+ gen_gvec_clt0(size, rd_ofs, rm_ofs, vec_size, vec_size);
break;
default:
@@ -6522,19 +6622,11 @@
break;
}
case NEON_2RM_VRECPE:
- {
- TCGv_ptr fpstatus = get_fpstatus_ptr(1);
- gen_helper_recpe_u32(tmp, tmp, fpstatus);
- tcg_temp_free_ptr(fpstatus);
+ gen_helper_recpe_u32(tmp, tmp);
break;
- }
case NEON_2RM_VRSQRTE:
- {
- TCGv_ptr fpstatus = get_fpstatus_ptr(1);
- gen_helper_rsqrte_u32(tmp, tmp, fpstatus);
- tcg_temp_free_ptr(fpstatus);
+ gen_helper_rsqrte_u32(tmp, tmp);
break;
- }
case NEON_2RM_VRECPE_F:
{
TCGv_ptr fpstatus = get_fpstatus_ptr(1);
diff --git a/target/arm/translate.h b/target/arm/translate.h
index cb7925e..c937dfe 100644
--- a/target/arm/translate.h
+++ b/target/arm/translate.h
@@ -275,30 +275,78 @@
uint64_t vfp_expand_imm(int size, uint8_t imm8);
/* Vector operations shared between ARM and AArch64. */
-extern const GVecGen2 ceq0_op[4];
-extern const GVecGen2 clt0_op[4];
-extern const GVecGen2 cgt0_op[4];
-extern const GVecGen2 cle0_op[4];
-extern const GVecGen2 cge0_op[4];
-extern const GVecGen3 mla_op[4];
-extern const GVecGen3 mls_op[4];
-extern const GVecGen3 cmtst_op[4];
-extern const GVecGen3 sshl_op[4];
-extern const GVecGen3 ushl_op[4];
-extern const GVecGen2i ssra_op[4];
-extern const GVecGen2i usra_op[4];
-extern const GVecGen2i sri_op[4];
-extern const GVecGen2i sli_op[4];
-extern const GVecGen4 uqadd_op[4];
-extern const GVecGen4 sqadd_op[4];
-extern const GVecGen4 uqsub_op[4];
-extern const GVecGen4 sqsub_op[4];
+void gen_gvec_ceq0(unsigned vece, uint32_t rd_ofs, uint32_t rm_ofs,
+ uint32_t opr_sz, uint32_t max_sz);
+void gen_gvec_clt0(unsigned vece, uint32_t rd_ofs, uint32_t rm_ofs,
+ uint32_t opr_sz, uint32_t max_sz);
+void gen_gvec_cgt0(unsigned vece, uint32_t rd_ofs, uint32_t rm_ofs,
+ uint32_t opr_sz, uint32_t max_sz);
+void gen_gvec_cle0(unsigned vece, uint32_t rd_ofs, uint32_t rm_ofs,
+ uint32_t opr_sz, uint32_t max_sz);
+void gen_gvec_cge0(unsigned vece, uint32_t rd_ofs, uint32_t rm_ofs,
+ uint32_t opr_sz, uint32_t max_sz);
+
+void gen_gvec_mla(unsigned vece, uint32_t rd_ofs, uint32_t rn_ofs,
+ uint32_t rm_ofs, uint32_t opr_sz, uint32_t max_sz);
+void gen_gvec_mls(unsigned vece, uint32_t rd_ofs, uint32_t rn_ofs,
+ uint32_t rm_ofs, uint32_t opr_sz, uint32_t max_sz);
+
+void gen_gvec_cmtst(unsigned vece, uint32_t rd_ofs, uint32_t rn_ofs,
+ uint32_t rm_ofs, uint32_t opr_sz, uint32_t max_sz);
+void gen_gvec_sshl(unsigned vece, uint32_t rd_ofs, uint32_t rn_ofs,
+ uint32_t rm_ofs, uint32_t opr_sz, uint32_t max_sz);
+void gen_gvec_ushl(unsigned vece, uint32_t rd_ofs, uint32_t rn_ofs,
+ uint32_t rm_ofs, uint32_t opr_sz, uint32_t max_sz);
+
void gen_cmtst_i64(TCGv_i64 d, TCGv_i64 a, TCGv_i64 b);
void gen_ushl_i32(TCGv_i32 d, TCGv_i32 a, TCGv_i32 b);
void gen_sshl_i32(TCGv_i32 d, TCGv_i32 a, TCGv_i32 b);
void gen_ushl_i64(TCGv_i64 d, TCGv_i64 a, TCGv_i64 b);
void gen_sshl_i64(TCGv_i64 d, TCGv_i64 a, TCGv_i64 b);
+void gen_gvec_uqadd_qc(unsigned vece, uint32_t rd_ofs, uint32_t rn_ofs,
+ uint32_t rm_ofs, uint32_t opr_sz, uint32_t max_sz);
+void gen_gvec_sqadd_qc(unsigned vece, uint32_t rd_ofs, uint32_t rn_ofs,
+ uint32_t rm_ofs, uint32_t opr_sz, uint32_t max_sz);
+void gen_gvec_uqsub_qc(unsigned vece, uint32_t rd_ofs, uint32_t rn_ofs,
+ uint32_t rm_ofs, uint32_t opr_sz, uint32_t max_sz);
+void gen_gvec_sqsub_qc(unsigned vece, uint32_t rd_ofs, uint32_t rn_ofs,
+ uint32_t rm_ofs, uint32_t opr_sz, uint32_t max_sz);
+
+void gen_gvec_ssra(unsigned vece, uint32_t rd_ofs, uint32_t rm_ofs,
+ int64_t shift, uint32_t opr_sz, uint32_t max_sz);
+void gen_gvec_usra(unsigned vece, uint32_t rd_ofs, uint32_t rm_ofs,
+ int64_t shift, uint32_t opr_sz, uint32_t max_sz);
+
+void gen_gvec_srshr(unsigned vece, uint32_t rd_ofs, uint32_t rm_ofs,
+ int64_t shift, uint32_t opr_sz, uint32_t max_sz);
+void gen_gvec_urshr(unsigned vece, uint32_t rd_ofs, uint32_t rm_ofs,
+ int64_t shift, uint32_t opr_sz, uint32_t max_sz);
+void gen_gvec_srsra(unsigned vece, uint32_t rd_ofs, uint32_t rm_ofs,
+ int64_t shift, uint32_t opr_sz, uint32_t max_sz);
+void gen_gvec_ursra(unsigned vece, uint32_t rd_ofs, uint32_t rm_ofs,
+ int64_t shift, uint32_t opr_sz, uint32_t max_sz);
+
+void gen_gvec_sri(unsigned vece, uint32_t rd_ofs, uint32_t rm_ofs,
+ int64_t shift, uint32_t opr_sz, uint32_t max_sz);
+void gen_gvec_sli(unsigned vece, uint32_t rd_ofs, uint32_t rm_ofs,
+ int64_t shift, uint32_t opr_sz, uint32_t max_sz);
+
+void gen_gvec_sqrdmlah_qc(unsigned vece, uint32_t rd_ofs, uint32_t rn_ofs,
+ uint32_t rm_ofs, uint32_t opr_sz, uint32_t max_sz);
+void gen_gvec_sqrdmlsh_qc(unsigned vece, uint32_t rd_ofs, uint32_t rn_ofs,
+ uint32_t rm_ofs, uint32_t opr_sz, uint32_t max_sz);
+
+void gen_gvec_sabd(unsigned vece, uint32_t rd_ofs, uint32_t rn_ofs,
+ uint32_t rm_ofs, uint32_t opr_sz, uint32_t max_sz);
+void gen_gvec_uabd(unsigned vece, uint32_t rd_ofs, uint32_t rn_ofs,
+ uint32_t rm_ofs, uint32_t opr_sz, uint32_t max_sz);
+
+void gen_gvec_saba(unsigned vece, uint32_t rd_ofs, uint32_t rn_ofs,
+ uint32_t rm_ofs, uint32_t opr_sz, uint32_t max_sz);
+void gen_gvec_uaba(unsigned vece, uint32_t rd_ofs, uint32_t rn_ofs,
+ uint32_t rm_ofs, uint32_t opr_sz, uint32_t max_sz);
+
/*
* Forward to the isar_feature_* tests given a DisasContext pointer.
*/
diff --git a/target/arm/vec_helper.c b/target/arm/vec_helper.c
index 3d53418..50a4992 100644
--- a/target/arm/vec_helper.c
+++ b/target/arm/vec_helper.c
@@ -36,8 +36,6 @@
#define H4(x) (x)
#endif
-#define SET_QC() env->vfp.qc[0] = 1
-
static void clear_tail(void *vd, uintptr_t opr_sz, uintptr_t max_sz)
{
uint64_t *d = vd + opr_sz;
@@ -49,8 +47,8 @@
}
/* Signed saturating rounding doubling multiply-accumulate high half, 16-bit */
-static uint16_t inl_qrdmlah_s16(CPUARMState *env, int16_t src1,
- int16_t src2, int16_t src3)
+static int16_t inl_qrdmlah_s16(int16_t src1, int16_t src2,
+ int16_t src3, uint32_t *sat)
{
/* Simplify:
* = ((a3 << 16) + ((e1 * e2) << 1) + (1 << 15)) >> 16
@@ -60,7 +58,7 @@
ret = ((int32_t)src3 << 15) + ret + (1 << 14);
ret >>= 15;
if (ret != (int16_t)ret) {
- SET_QC();
+ *sat = 1;
ret = (ret < 0 ? -0x8000 : 0x7fff);
}
return ret;
@@ -69,30 +67,30 @@
uint32_t HELPER(neon_qrdmlah_s16)(CPUARMState *env, uint32_t src1,
uint32_t src2, uint32_t src3)
{
- uint16_t e1 = inl_qrdmlah_s16(env, src1, src2, src3);
- uint16_t e2 = inl_qrdmlah_s16(env, src1 >> 16, src2 >> 16, src3 >> 16);
+ uint32_t *sat = &env->vfp.qc[0];
+ uint16_t e1 = inl_qrdmlah_s16(src1, src2, src3, sat);
+ uint16_t e2 = inl_qrdmlah_s16(src1 >> 16, src2 >> 16, src3 >> 16, sat);
return deposit32(e1, 16, 16, e2);
}
void HELPER(gvec_qrdmlah_s16)(void *vd, void *vn, void *vm,
- void *ve, uint32_t desc)
+ void *vq, uint32_t desc)
{
uintptr_t opr_sz = simd_oprsz(desc);
int16_t *d = vd;
int16_t *n = vn;
int16_t *m = vm;
- CPUARMState *env = ve;
uintptr_t i;
for (i = 0; i < opr_sz / 2; ++i) {
- d[i] = inl_qrdmlah_s16(env, n[i], m[i], d[i]);
+ d[i] = inl_qrdmlah_s16(n[i], m[i], d[i], vq);
}
clear_tail(d, opr_sz, simd_maxsz(desc));
}
/* Signed saturating rounding doubling multiply-subtract high half, 16-bit */
-static uint16_t inl_qrdmlsh_s16(CPUARMState *env, int16_t src1,
- int16_t src2, int16_t src3)
+static int16_t inl_qrdmlsh_s16(int16_t src1, int16_t src2,
+ int16_t src3, uint32_t *sat)
{
/* Similarly, using subtraction:
* = ((a3 << 16) - ((e1 * e2) << 1) + (1 << 15)) >> 16
@@ -102,7 +100,7 @@
ret = ((int32_t)src3 << 15) - ret + (1 << 14);
ret >>= 15;
if (ret != (int16_t)ret) {
- SET_QC();
+ *sat = 1;
ret = (ret < 0 ? -0x8000 : 0x7fff);
}
return ret;
@@ -111,85 +109,97 @@
uint32_t HELPER(neon_qrdmlsh_s16)(CPUARMState *env, uint32_t src1,
uint32_t src2, uint32_t src3)
{
- uint16_t e1 = inl_qrdmlsh_s16(env, src1, src2, src3);
- uint16_t e2 = inl_qrdmlsh_s16(env, src1 >> 16, src2 >> 16, src3 >> 16);
+ uint32_t *sat = &env->vfp.qc[0];
+ uint16_t e1 = inl_qrdmlsh_s16(src1, src2, src3, sat);
+ uint16_t e2 = inl_qrdmlsh_s16(src1 >> 16, src2 >> 16, src3 >> 16, sat);
return deposit32(e1, 16, 16, e2);
}
void HELPER(gvec_qrdmlsh_s16)(void *vd, void *vn, void *vm,
- void *ve, uint32_t desc)
+ void *vq, uint32_t desc)
{
uintptr_t opr_sz = simd_oprsz(desc);
int16_t *d = vd;
int16_t *n = vn;
int16_t *m = vm;
- CPUARMState *env = ve;
uintptr_t i;
for (i = 0; i < opr_sz / 2; ++i) {
- d[i] = inl_qrdmlsh_s16(env, n[i], m[i], d[i]);
+ d[i] = inl_qrdmlsh_s16(n[i], m[i], d[i], vq);
}
clear_tail(d, opr_sz, simd_maxsz(desc));
}
/* Signed saturating rounding doubling multiply-accumulate high half, 32-bit */
-uint32_t HELPER(neon_qrdmlah_s32)(CPUARMState *env, int32_t src1,
- int32_t src2, int32_t src3)
+static int32_t inl_qrdmlah_s32(int32_t src1, int32_t src2,
+ int32_t src3, uint32_t *sat)
{
/* Simplify similarly to int_qrdmlah_s16 above. */
int64_t ret = (int64_t)src1 * src2;
ret = ((int64_t)src3 << 31) + ret + (1 << 30);
ret >>= 31;
if (ret != (int32_t)ret) {
- SET_QC();
+ *sat = 1;
ret = (ret < 0 ? INT32_MIN : INT32_MAX);
}
return ret;
}
+uint32_t HELPER(neon_qrdmlah_s32)(CPUARMState *env, int32_t src1,
+ int32_t src2, int32_t src3)
+{
+ uint32_t *sat = &env->vfp.qc[0];
+ return inl_qrdmlah_s32(src1, src2, src3, sat);
+}
+
void HELPER(gvec_qrdmlah_s32)(void *vd, void *vn, void *vm,
- void *ve, uint32_t desc)
+ void *vq, uint32_t desc)
{
uintptr_t opr_sz = simd_oprsz(desc);
int32_t *d = vd;
int32_t *n = vn;
int32_t *m = vm;
- CPUARMState *env = ve;
uintptr_t i;
for (i = 0; i < opr_sz / 4; ++i) {
- d[i] = helper_neon_qrdmlah_s32(env, n[i], m[i], d[i]);
+ d[i] = inl_qrdmlah_s32(n[i], m[i], d[i], vq);
}
clear_tail(d, opr_sz, simd_maxsz(desc));
}
/* Signed saturating rounding doubling multiply-subtract high half, 32-bit */
-uint32_t HELPER(neon_qrdmlsh_s32)(CPUARMState *env, int32_t src1,
- int32_t src2, int32_t src3)
+static int32_t inl_qrdmlsh_s32(int32_t src1, int32_t src2,
+ int32_t src3, uint32_t *sat)
{
/* Simplify similarly to int_qrdmlsh_s16 above. */
int64_t ret = (int64_t)src1 * src2;
ret = ((int64_t)src3 << 31) - ret + (1 << 30);
ret >>= 31;
if (ret != (int32_t)ret) {
- SET_QC();
+ *sat = 1;
ret = (ret < 0 ? INT32_MIN : INT32_MAX);
}
return ret;
}
+uint32_t HELPER(neon_qrdmlsh_s32)(CPUARMState *env, int32_t src1,
+ int32_t src2, int32_t src3)
+{
+ uint32_t *sat = &env->vfp.qc[0];
+ return inl_qrdmlsh_s32(src1, src2, src3, sat);
+}
+
void HELPER(gvec_qrdmlsh_s32)(void *vd, void *vn, void *vm,
- void *ve, uint32_t desc)
+ void *vq, uint32_t desc)
{
uintptr_t opr_sz = simd_oprsz(desc);
int32_t *d = vd;
int32_t *n = vn;
int32_t *m = vm;
- CPUARMState *env = ve;
uintptr_t i;
for (i = 0; i < opr_sz / 4; ++i) {
- d[i] = helper_neon_qrdmlsh_s32(env, n[i], m[i], d[i]);
+ d[i] = inl_qrdmlsh_s32(n[i], m[i], d[i], vq);
}
clear_tail(d, opr_sz, simd_maxsz(desc));
}
@@ -681,6 +691,11 @@
return result;
}
+static float32 float32_abd(float32 op1, float32 op2, float_status *stat)
+{
+ return float32_abs(float32_sub(op1, op2, stat));
+}
+
#define DO_3OP(NAME, FUNC, TYPE) \
void HELPER(NAME)(void *vd, void *vn, void *vm, void *stat, uint32_t desc) \
{ \
@@ -708,6 +723,8 @@
DO_3OP(gvec_ftsmul_s, float32_ftsmul, float32)
DO_3OP(gvec_ftsmul_d, float64_ftsmul, float64)
+DO_3OP(gvec_fabd_s, float32_abd, float32)
+
#ifdef TARGET_AARCH64
DO_3OP(gvec_recps_h, helper_recpsf_f16, float16)
@@ -737,6 +754,7 @@
d[i + j] = TYPE##_mul(n[i + j], mm, stat); \
} \
} \
+ clear_tail(d, oprsz, simd_maxsz(desc)); \
}
DO_MUL_IDX(gvec_fmul_idx_h, float16, H2)
@@ -761,6 +779,7 @@
mm, a[i + j], 0, stat); \
} \
} \
+ clear_tail(d, oprsz, simd_maxsz(desc)); \
}
DO_FMLA_IDX(gvec_fmla_idx_h, float16, H2)
@@ -899,6 +918,119 @@
clear_tail(d, oprsz, simd_maxsz(desc));
}
+
+#define DO_SRA(NAME, TYPE) \
+void HELPER(NAME)(void *vd, void *vn, uint32_t desc) \
+{ \
+ intptr_t i, oprsz = simd_oprsz(desc); \
+ int shift = simd_data(desc); \
+ TYPE *d = vd, *n = vn; \
+ for (i = 0; i < oprsz / sizeof(TYPE); i++) { \
+ d[i] += n[i] >> shift; \
+ } \
+ clear_tail(d, oprsz, simd_maxsz(desc)); \
+}
+
+DO_SRA(gvec_ssra_b, int8_t)
+DO_SRA(gvec_ssra_h, int16_t)
+DO_SRA(gvec_ssra_s, int32_t)
+DO_SRA(gvec_ssra_d, int64_t)
+
+DO_SRA(gvec_usra_b, uint8_t)
+DO_SRA(gvec_usra_h, uint16_t)
+DO_SRA(gvec_usra_s, uint32_t)
+DO_SRA(gvec_usra_d, uint64_t)
+
+#undef DO_SRA
+
+#define DO_RSHR(NAME, TYPE) \
+void HELPER(NAME)(void *vd, void *vn, uint32_t desc) \
+{ \
+ intptr_t i, oprsz = simd_oprsz(desc); \
+ int shift = simd_data(desc); \
+ TYPE *d = vd, *n = vn; \
+ for (i = 0; i < oprsz / sizeof(TYPE); i++) { \
+ TYPE tmp = n[i] >> (shift - 1); \
+ d[i] = (tmp >> 1) + (tmp & 1); \
+ } \
+ clear_tail(d, oprsz, simd_maxsz(desc)); \
+}
+
+DO_RSHR(gvec_srshr_b, int8_t)
+DO_RSHR(gvec_srshr_h, int16_t)
+DO_RSHR(gvec_srshr_s, int32_t)
+DO_RSHR(gvec_srshr_d, int64_t)
+
+DO_RSHR(gvec_urshr_b, uint8_t)
+DO_RSHR(gvec_urshr_h, uint16_t)
+DO_RSHR(gvec_urshr_s, uint32_t)
+DO_RSHR(gvec_urshr_d, uint64_t)
+
+#undef DO_RSHR
+
+#define DO_RSRA(NAME, TYPE) \
+void HELPER(NAME)(void *vd, void *vn, uint32_t desc) \
+{ \
+ intptr_t i, oprsz = simd_oprsz(desc); \
+ int shift = simd_data(desc); \
+ TYPE *d = vd, *n = vn; \
+ for (i = 0; i < oprsz / sizeof(TYPE); i++) { \
+ TYPE tmp = n[i] >> (shift - 1); \
+ d[i] += (tmp >> 1) + (tmp & 1); \
+ } \
+ clear_tail(d, oprsz, simd_maxsz(desc)); \
+}
+
+DO_RSRA(gvec_srsra_b, int8_t)
+DO_RSRA(gvec_srsra_h, int16_t)
+DO_RSRA(gvec_srsra_s, int32_t)
+DO_RSRA(gvec_srsra_d, int64_t)
+
+DO_RSRA(gvec_ursra_b, uint8_t)
+DO_RSRA(gvec_ursra_h, uint16_t)
+DO_RSRA(gvec_ursra_s, uint32_t)
+DO_RSRA(gvec_ursra_d, uint64_t)
+
+#undef DO_RSRA
+
+#define DO_SRI(NAME, TYPE) \
+void HELPER(NAME)(void *vd, void *vn, uint32_t desc) \
+{ \
+ intptr_t i, oprsz = simd_oprsz(desc); \
+ int shift = simd_data(desc); \
+ TYPE *d = vd, *n = vn; \
+ for (i = 0; i < oprsz / sizeof(TYPE); i++) { \
+ d[i] = deposit64(d[i], 0, sizeof(TYPE) * 8 - shift, n[i] >> shift); \
+ } \
+ clear_tail(d, oprsz, simd_maxsz(desc)); \
+}
+
+DO_SRI(gvec_sri_b, uint8_t)
+DO_SRI(gvec_sri_h, uint16_t)
+DO_SRI(gvec_sri_s, uint32_t)
+DO_SRI(gvec_sri_d, uint64_t)
+
+#undef DO_SRI
+
+#define DO_SLI(NAME, TYPE) \
+void HELPER(NAME)(void *vd, void *vn, uint32_t desc) \
+{ \
+ intptr_t i, oprsz = simd_oprsz(desc); \
+ int shift = simd_data(desc); \
+ TYPE *d = vd, *n = vn; \
+ for (i = 0; i < oprsz / sizeof(TYPE); i++) { \
+ d[i] = deposit64(d[i], shift, sizeof(TYPE) * 8 - shift, n[i]); \
+ } \
+ clear_tail(d, oprsz, simd_maxsz(desc)); \
+}
+
+DO_SLI(gvec_sli_b, uint8_t)
+DO_SLI(gvec_sli_h, uint16_t)
+DO_SLI(gvec_sli_s, uint32_t)
+DO_SLI(gvec_sli_d, uint64_t)
+
+#undef DO_SLI
+
/*
* Convert float16 to float32, raising no exceptions and
* preserving exceptional values, including SNaN.
@@ -1282,3 +1414,51 @@
DO_CMP0(gvec_cge0_h, int16_t, >=)
#undef DO_CMP0
+
+#define DO_ABD(NAME, TYPE) \
+void HELPER(NAME)(void *vd, void *vn, void *vm, uint32_t desc) \
+{ \
+ intptr_t i, opr_sz = simd_oprsz(desc); \
+ TYPE *d = vd, *n = vn, *m = vm; \
+ \
+ for (i = 0; i < opr_sz / sizeof(TYPE); ++i) { \
+ d[i] = n[i] < m[i] ? m[i] - n[i] : n[i] - m[i]; \
+ } \
+ clear_tail(d, opr_sz, simd_maxsz(desc)); \
+}
+
+DO_ABD(gvec_sabd_b, int8_t)
+DO_ABD(gvec_sabd_h, int16_t)
+DO_ABD(gvec_sabd_s, int32_t)
+DO_ABD(gvec_sabd_d, int64_t)
+
+DO_ABD(gvec_uabd_b, uint8_t)
+DO_ABD(gvec_uabd_h, uint16_t)
+DO_ABD(gvec_uabd_s, uint32_t)
+DO_ABD(gvec_uabd_d, uint64_t)
+
+#undef DO_ABD
+
+#define DO_ABA(NAME, TYPE) \
+void HELPER(NAME)(void *vd, void *vn, void *vm, uint32_t desc) \
+{ \
+ intptr_t i, opr_sz = simd_oprsz(desc); \
+ TYPE *d = vd, *n = vn, *m = vm; \
+ \
+ for (i = 0; i < opr_sz / sizeof(TYPE); ++i) { \
+ d[i] += n[i] < m[i] ? m[i] - n[i] : n[i] - m[i]; \
+ } \
+ clear_tail(d, opr_sz, simd_maxsz(desc)); \
+}
+
+DO_ABA(gvec_saba_b, int8_t)
+DO_ABA(gvec_saba_h, int16_t)
+DO_ABA(gvec_saba_s, int32_t)
+DO_ABA(gvec_saba_d, int64_t)
+
+DO_ABA(gvec_uaba_b, uint8_t)
+DO_ABA(gvec_uaba_h, uint16_t)
+DO_ABA(gvec_uaba_s, uint32_t)
+DO_ABA(gvec_uaba_d, uint64_t)
+
+#undef DO_ABA
diff --git a/target/arm/vfp_helper.c b/target/arm/vfp_helper.c
index 930d6e7..60dcd4b 100644
--- a/target/arm/vfp_helper.c
+++ b/target/arm/vfp_helper.c
@@ -281,7 +281,7 @@
return float64_sqrt(a, &env->vfp.fp_status);
}
-static void softfloat_to_vfp_compare(CPUARMState *env, int cmp)
+static void softfloat_to_vfp_compare(CPUARMState *env, FloatRelation cmp)
{
uint32_t flags;
switch (cmp) {
@@ -531,7 +531,7 @@
* it would affect flushing input denormals.
*/
float_status *fpst = fpstp;
- flag save = get_flush_inputs_to_zero(fpst);
+ bool save = get_flush_inputs_to_zero(fpst);
set_flush_inputs_to_zero(false, fpst);
float32 r = float16_to_float32(a, !ahp_mode, fpst);
set_flush_inputs_to_zero(save, fpst);
@@ -544,7 +544,7 @@
* it would affect flushing output denormals.
*/
float_status *fpst = fpstp;
- flag save = get_flush_to_zero(fpst);
+ bool save = get_flush_to_zero(fpst);
set_flush_to_zero(false, fpst);
float16 r = float32_to_float16(a, !ahp_mode, fpst);
set_flush_to_zero(save, fpst);
@@ -557,7 +557,7 @@
* it would affect flushing input denormals.
*/
float_status *fpst = fpstp;
- flag save = get_flush_inputs_to_zero(fpst);
+ bool save = get_flush_inputs_to_zero(fpst);
set_flush_inputs_to_zero(false, fpst);
float64 r = float16_to_float64(a, !ahp_mode, fpst);
set_flush_inputs_to_zero(save, fpst);
@@ -570,7 +570,7 @@
* it would affect flushing output denormals.
*/
float_status *fpst = fpstp;
- flag save = get_flush_to_zero(fpst);
+ bool save = get_flush_to_zero(fpst);
set_flush_to_zero(false, fpst);
float16 r = float64_to_float16(a, !ahp_mode, fpst);
set_flush_to_zero(save, fpst);
@@ -581,7 +581,7 @@
#define float32_three make_float32(0x40400000)
#define float32_one_point_five make_float32(0x3fc00000)
-float32 HELPER(recps_f32)(float32 a, float32 b, CPUARMState *env)
+float32 HELPER(recps_f32)(CPUARMState *env, float32 a, float32 b)
{
float_status *s = &env->vfp.standard_fp_status;
if ((float32_is_infinity(a) && float32_is_zero_or_denormal(b)) ||
@@ -594,7 +594,7 @@
return float32_sub(float32_two, float32_mul(a, b, s), s);
}
-float32 HELPER(rsqrts_f32)(float32 a, float32 b, CPUARMState *env)
+float32 HELPER(rsqrts_f32)(CPUARMState *env, float32 a, float32 b)
{
float_status *s = &env->vfp.standard_fp_status;
float32 product;
@@ -697,9 +697,9 @@
return sign_bit;
case float_round_to_zero: /* Round to Zero */
return false;
+ default:
+ g_assert_not_reached();
}
-
- g_assert_not_reached();
}
uint32_t HELPER(recpe_f16)(uint32_t input, void *fpstp)
@@ -1023,9 +1023,8 @@
return make_float64(val);
}
-uint32_t HELPER(recpe_u32)(uint32_t a, void *fpstp)
+uint32_t HELPER(recpe_u32)(uint32_t a)
{
- /* float_status *s = fpstp; */
int input, estimate;
if ((a & 0x80000000) == 0) {
@@ -1038,7 +1037,7 @@
return deposit32(0, (32 - 9), 9, estimate);
}
-uint32_t HELPER(rsqrte_u32)(uint32_t a, void *fpstp)
+uint32_t HELPER(rsqrte_u32)(uint32_t a)
{
int estimate;
diff --git a/target/hppa/op_helper.c b/target/hppa/op_helper.c
index 7823706..5685e30 100644
--- a/target/hppa/op_helper.c
+++ b/target/hppa/op_helper.c
@@ -523,7 +523,8 @@
return ret;
}
-static void update_fr0_cmp(CPUHPPAState *env, uint32_t y, uint32_t c, int r)
+static void update_fr0_cmp(CPUHPPAState *env, uint32_t y,
+ uint32_t c, FloatRelation r)
{
uint32_t shadow = env->fr0_shadow;
@@ -565,7 +566,7 @@
void HELPER(fcmp_s)(CPUHPPAState *env, float32 a, float32 b,
uint32_t y, uint32_t c)
{
- int r;
+ FloatRelation r;
if (c & 1) {
r = float32_compare(a, b, &env->fp_status);
} else {
@@ -578,7 +579,7 @@
void HELPER(fcmp_d)(CPUHPPAState *env, float64 a, float64 b,
uint32_t y, uint32_t c)
{
- int r;
+ FloatRelation r;
if (c & 1) {
r = float64_compare(a, b, &env->fp_status);
} else {
diff --git a/target/i386/cpu.c b/target/i386/cpu.c
index 9c256ab..3733d9a 100644
--- a/target/i386/cpu.c
+++ b/target/i386/cpu.c
@@ -5078,7 +5078,7 @@
/* Load data from X86CPUDefinition into a X86CPU object
*/
-static void x86_cpu_load_model(X86CPU *cpu, X86CPUModel *model, Error **errp)
+static void x86_cpu_load_model(X86CPU *cpu, X86CPUModel *model)
{
X86CPUDefinition *def = model->cpudef;
CPUX86State *env = &cpu->env;
@@ -5092,13 +5092,19 @@
*/
/* CPU models only set _minimum_ values for level/xlevel: */
- object_property_set_uint(OBJECT(cpu), def->level, "min-level", errp);
- object_property_set_uint(OBJECT(cpu), def->xlevel, "min-xlevel", errp);
+ object_property_set_uint(OBJECT(cpu), def->level, "min-level",
+ &error_abort);
+ object_property_set_uint(OBJECT(cpu), def->xlevel, "min-xlevel",
+ &error_abort);
- object_property_set_int(OBJECT(cpu), def->family, "family", errp);
- object_property_set_int(OBJECT(cpu), def->model, "model", errp);
- object_property_set_int(OBJECT(cpu), def->stepping, "stepping", errp);
- object_property_set_str(OBJECT(cpu), def->model_id, "model-id", errp);
+ object_property_set_int(OBJECT(cpu), def->family, "family",
+ &error_abort);
+ object_property_set_int(OBJECT(cpu), def->model, "model",
+ &error_abort);
+ object_property_set_int(OBJECT(cpu), def->stepping, "stepping",
+ &error_abort);
+ object_property_set_str(OBJECT(cpu), def->model_id, "model-id",
+ &error_abort);
for (w = 0; w < FEATURE_WORDS; w++) {
env->features[w] = def->features[w];
}
@@ -5135,7 +5141,8 @@
vendor = host_vendor;
}
- object_property_set_str(OBJECT(cpu), vendor, "vendor", errp);
+ object_property_set_str(OBJECT(cpu), vendor, "vendor",
+ &error_abort);
x86_cpu_apply_version_props(cpu, model);
}
@@ -6110,7 +6117,7 @@
cpu->apic_state = DEVICE(object_new_with_class(apic_class));
object_property_add_child(OBJECT(cpu), "lapic",
- OBJECT(cpu->apic_state), &error_abort);
+ OBJECT(cpu->apic_state));
object_unref(OBJECT(cpu->apic_state));
qdev_prop_set_uint32(cpu->apic_state, "id", cpu->apic_id);
@@ -6722,11 +6729,10 @@
}
}
-static void x86_cpu_unrealizefn(DeviceState *dev, Error **errp)
+static void x86_cpu_unrealizefn(DeviceState *dev)
{
X86CPU *cpu = X86_CPU(dev);
X86CPUClass *xcc = X86_CPU_GET_CLASS(dev);
- Error *local_err = NULL;
#ifndef CONFIG_USER_ONLY
cpu_remove_sync(CPU(dev));
@@ -6738,11 +6744,7 @@
cpu->apic_state = NULL;
}
- xcc->parent_unrealize(dev, &local_err);
- if (local_err != NULL) {
- error_propagate(errp, local_err);
- return;
- }
+ xcc->parent_unrealize(dev);
}
typedef struct BitProperty {
@@ -6822,7 +6824,7 @@
object_property_add(OBJECT(cpu), prop_name, "bool",
x86_cpu_get_bit_prop,
x86_cpu_set_bit_prop,
- x86_cpu_release_bit_prop, fp, &error_abort);
+ x86_cpu_release_bit_prop, fp);
}
}
@@ -6905,28 +6907,28 @@
object_property_add(obj, "family", "int",
x86_cpuid_version_get_family,
- x86_cpuid_version_set_family, NULL, NULL, NULL);
+ x86_cpuid_version_set_family, NULL, NULL);
object_property_add(obj, "model", "int",
x86_cpuid_version_get_model,
- x86_cpuid_version_set_model, NULL, NULL, NULL);
+ x86_cpuid_version_set_model, NULL, NULL);
object_property_add(obj, "stepping", "int",
x86_cpuid_version_get_stepping,
- x86_cpuid_version_set_stepping, NULL, NULL, NULL);
+ x86_cpuid_version_set_stepping, NULL, NULL);
object_property_add_str(obj, "vendor",
x86_cpuid_get_vendor,
- x86_cpuid_set_vendor, NULL);
+ x86_cpuid_set_vendor);
object_property_add_str(obj, "model-id",
x86_cpuid_get_model_id,
- x86_cpuid_set_model_id, NULL);
+ x86_cpuid_set_model_id);
object_property_add(obj, "tsc-frequency", "int",
x86_cpuid_get_tsc_freq,
- x86_cpuid_set_tsc_freq, NULL, NULL, NULL);
+ x86_cpuid_set_tsc_freq, NULL, NULL);
object_property_add(obj, "feature-words", "X86CPUFeatureWordInfo",
x86_cpu_get_feature_words,
- NULL, NULL, (void *)env->features, NULL);
+ NULL, NULL, (void *)env->features);
object_property_add(obj, "filtered-features", "X86CPUFeatureWordInfo",
x86_cpu_get_feature_words,
- NULL, NULL, (void *)cpu->filtered_features, NULL);
+ NULL, NULL, (void *)cpu->filtered_features);
/*
* The "unavailable-features" property has the same semantics as
* CpuDefinitionInfo.unavailable-features on the "query-cpu-definitions"
@@ -6935,10 +6937,10 @@
*/
object_property_add(obj, "unavailable-features", "strList",
x86_cpu_get_unavailable_features,
- NULL, NULL, NULL, &error_abort);
+ NULL, NULL, NULL);
object_property_add(obj, "crash-information", "GuestPanicInformation",
- x86_cpu_get_crash_info_qom, NULL, NULL, NULL, NULL);
+ x86_cpu_get_crash_info_qom, NULL, NULL, NULL);
for (w = 0; w < FEATURE_WORDS; w++) {
int bitnr;
@@ -6948,40 +6950,39 @@
}
}
- object_property_add_alias(obj, "sse3", obj, "pni", &error_abort);
- object_property_add_alias(obj, "pclmuldq", obj, "pclmulqdq", &error_abort);
- object_property_add_alias(obj, "sse4-1", obj, "sse4.1", &error_abort);
- object_property_add_alias(obj, "sse4-2", obj, "sse4.2", &error_abort);
- object_property_add_alias(obj, "xd", obj, "nx", &error_abort);
- object_property_add_alias(obj, "ffxsr", obj, "fxsr-opt", &error_abort);
- object_property_add_alias(obj, "i64", obj, "lm", &error_abort);
+ object_property_add_alias(obj, "sse3", obj, "pni");
+ object_property_add_alias(obj, "pclmuldq", obj, "pclmulqdq");
+ object_property_add_alias(obj, "sse4-1", obj, "sse4.1");
+ object_property_add_alias(obj, "sse4-2", obj, "sse4.2");
+ object_property_add_alias(obj, "xd", obj, "nx");
+ object_property_add_alias(obj, "ffxsr", obj, "fxsr-opt");
+ object_property_add_alias(obj, "i64", obj, "lm");
- object_property_add_alias(obj, "ds_cpl", obj, "ds-cpl", &error_abort);
- object_property_add_alias(obj, "tsc_adjust", obj, "tsc-adjust", &error_abort);
- object_property_add_alias(obj, "fxsr_opt", obj, "fxsr-opt", &error_abort);
- object_property_add_alias(obj, "lahf_lm", obj, "lahf-lm", &error_abort);
- object_property_add_alias(obj, "cmp_legacy", obj, "cmp-legacy", &error_abort);
- object_property_add_alias(obj, "nodeid_msr", obj, "nodeid-msr", &error_abort);
- object_property_add_alias(obj, "perfctr_core", obj, "perfctr-core", &error_abort);
- object_property_add_alias(obj, "perfctr_nb", obj, "perfctr-nb", &error_abort);
- object_property_add_alias(obj, "kvm_nopiodelay", obj, "kvm-nopiodelay", &error_abort);
- object_property_add_alias(obj, "kvm_mmu", obj, "kvm-mmu", &error_abort);
- object_property_add_alias(obj, "kvm_asyncpf", obj, "kvm-asyncpf", &error_abort);
- object_property_add_alias(obj, "kvm_steal_time", obj, "kvm-steal-time", &error_abort);
- object_property_add_alias(obj, "kvm_pv_eoi", obj, "kvm-pv-eoi", &error_abort);
- object_property_add_alias(obj, "kvm_pv_unhalt", obj, "kvm-pv-unhalt", &error_abort);
- object_property_add_alias(obj, "kvm_poll_control", obj, "kvm-poll-control",
- &error_abort);
- object_property_add_alias(obj, "svm_lock", obj, "svm-lock", &error_abort);
- object_property_add_alias(obj, "nrip_save", obj, "nrip-save", &error_abort);
- object_property_add_alias(obj, "tsc_scale", obj, "tsc-scale", &error_abort);
- object_property_add_alias(obj, "vmcb_clean", obj, "vmcb-clean", &error_abort);
- object_property_add_alias(obj, "pause_filter", obj, "pause-filter", &error_abort);
- object_property_add_alias(obj, "sse4_1", obj, "sse4.1", &error_abort);
- object_property_add_alias(obj, "sse4_2", obj, "sse4.2", &error_abort);
+ object_property_add_alias(obj, "ds_cpl", obj, "ds-cpl");
+ object_property_add_alias(obj, "tsc_adjust", obj, "tsc-adjust");
+ object_property_add_alias(obj, "fxsr_opt", obj, "fxsr-opt");
+ object_property_add_alias(obj, "lahf_lm", obj, "lahf-lm");
+ object_property_add_alias(obj, "cmp_legacy", obj, "cmp-legacy");
+ object_property_add_alias(obj, "nodeid_msr", obj, "nodeid-msr");
+ object_property_add_alias(obj, "perfctr_core", obj, "perfctr-core");
+ object_property_add_alias(obj, "perfctr_nb", obj, "perfctr-nb");
+ object_property_add_alias(obj, "kvm_nopiodelay", obj, "kvm-nopiodelay");
+ object_property_add_alias(obj, "kvm_mmu", obj, "kvm-mmu");
+ object_property_add_alias(obj, "kvm_asyncpf", obj, "kvm-asyncpf");
+ object_property_add_alias(obj, "kvm_steal_time", obj, "kvm-steal-time");
+ object_property_add_alias(obj, "kvm_pv_eoi", obj, "kvm-pv-eoi");
+ object_property_add_alias(obj, "kvm_pv_unhalt", obj, "kvm-pv-unhalt");
+ object_property_add_alias(obj, "kvm_poll_control", obj, "kvm-poll-control");
+ object_property_add_alias(obj, "svm_lock", obj, "svm-lock");
+ object_property_add_alias(obj, "nrip_save", obj, "nrip-save");
+ object_property_add_alias(obj, "tsc_scale", obj, "tsc-scale");
+ object_property_add_alias(obj, "vmcb_clean", obj, "vmcb-clean");
+ object_property_add_alias(obj, "pause_filter", obj, "pause-filter");
+ object_property_add_alias(obj, "sse4_1", obj, "sse4.1");
+ object_property_add_alias(obj, "sse4_2", obj, "sse4.2");
if (xcc->model) {
- x86_cpu_load_model(cpu, xcc->model, &error_abort);
+ x86_cpu_load_model(cpu, xcc->model);
}
}
diff --git a/target/i386/cpu.h b/target/i386/cpu.h
index e818fc7..408392d 100644
--- a/target/i386/cpu.h
+++ b/target/i386/cpu.h
@@ -29,6 +29,8 @@
/* The x86 has a strong memory model with some store-after-load re-ordering */
#define TCG_GUEST_DEFAULT_MO (TCG_MO_ALL & ~TCG_MO_ST_LD)
+#define KVM_HAVE_MCE_INJECTION 1
+
/* Maximum instruction code size */
#define TARGET_MAX_INSN_SIZE 16
diff --git a/target/i386/fpu_helper.c b/target/i386/fpu_helper.c
index 792a128..b34fa78 100644
--- a/target/i386/fpu_helper.c
+++ b/target/i386/fpu_helper.c
@@ -420,7 +420,7 @@
void helper_fcom_ST0_FT0(CPUX86State *env)
{
- int ret;
+ FloatRelation ret;
ret = floatx80_compare(ST0, FT0, &env->fp_status);
env->fpus = (env->fpus & ~0x4500) | fcom_ccval[ret + 1];
@@ -428,7 +428,7 @@
void helper_fucom_ST0_FT0(CPUX86State *env)
{
- int ret;
+ FloatRelation ret;
ret = floatx80_compare_quiet(ST0, FT0, &env->fp_status);
env->fpus = (env->fpus & ~0x4500) | fcom_ccval[ret + 1];
@@ -439,7 +439,7 @@
void helper_fcomi_ST0_FT0(CPUX86State *env)
{
int eflags;
- int ret;
+ FloatRelation ret;
ret = floatx80_compare(ST0, FT0, &env->fp_status);
eflags = cpu_cc_compute_all(env, CC_OP);
@@ -450,7 +450,7 @@
void helper_fucomi_ST0_FT0(CPUX86State *env)
{
int eflags;
- int ret;
+ FloatRelation ret;
ret = floatx80_compare_quiet(ST0, FT0, &env->fp_status);
eflags = cpu_cc_compute_all(env, CC_OP);
diff --git a/target/i386/kvm.c b/target/i386/kvm.c
index 4901c6d..34f8387 100644
--- a/target/i386/kvm.c
+++ b/target/i386/kvm.c
@@ -24,7 +24,6 @@
#include "sysemu/sysemu.h"
#include "sysemu/hw_accel.h"
#include "sysemu/kvm_int.h"
-#include "sysemu/reset.h"
#include "sysemu/runstate.h"
#include "kvm_i386.h"
#include "hyperv.h"
@@ -533,40 +532,6 @@
}
}
-
-typedef struct HWPoisonPage {
- ram_addr_t ram_addr;
- QLIST_ENTRY(HWPoisonPage) list;
-} HWPoisonPage;
-
-static QLIST_HEAD(, HWPoisonPage) hwpoison_page_list =
- QLIST_HEAD_INITIALIZER(hwpoison_page_list);
-
-static void kvm_unpoison_all(void *param)
-{
- HWPoisonPage *page, *next_page;
-
- QLIST_FOREACH_SAFE(page, &hwpoison_page_list, list, next_page) {
- QLIST_REMOVE(page, list);
- qemu_ram_remap(page->ram_addr, TARGET_PAGE_SIZE);
- g_free(page);
- }
-}
-
-static void kvm_hwpoison_page_add(ram_addr_t ram_addr)
-{
- HWPoisonPage *page;
-
- QLIST_FOREACH(page, &hwpoison_page_list, list) {
- if (page->ram_addr == ram_addr) {
- return;
- }
- }
- page = g_new(HWPoisonPage, 1);
- page->ram_addr = ram_addr;
- QLIST_INSERT_HEAD(&hwpoison_page_list, page, list);
-}
-
static int kvm_get_mce_cap_supported(KVMState *s, uint64_t *mce_cap,
int *max_banks)
{
@@ -2180,7 +2145,6 @@
fprintf(stderr, "e820_add_entry() table is full\n");
return ret;
}
- qemu_register_reset(kvm_unpoison_all, NULL);
shadow_mem = object_property_get_int(OBJECT(s), "kvm-shadow-mem", &error_abort);
if (shadow_mem != -1) {
diff --git a/target/i386/ops_sse.h b/target/i386/ops_sse.h
index ec1ec74..4658768 100644
--- a/target/i386/ops_sse.h
+++ b/target/i386/ops_sse.h
@@ -1031,7 +1031,7 @@
void helper_ucomiss(CPUX86State *env, Reg *d, Reg *s)
{
- int ret;
+ FloatRelation ret;
float32 s0, s1;
s0 = d->ZMM_S(0);
@@ -1042,7 +1042,7 @@
void helper_comiss(CPUX86State *env, Reg *d, Reg *s)
{
- int ret;
+ FloatRelation ret;
float32 s0, s1;
s0 = d->ZMM_S(0);
@@ -1053,7 +1053,7 @@
void helper_ucomisd(CPUX86State *env, Reg *d, Reg *s)
{
- int ret;
+ FloatRelation ret;
float64 d0, d1;
d0 = d->ZMM_D(0);
@@ -1064,7 +1064,7 @@
void helper_comisd(CPUX86State *env, Reg *d, Reg *s)
{
- int ret;
+ FloatRelation ret;
float64 d0, d1;
d0 = d->ZMM_D(0);
diff --git a/target/i386/sev.c b/target/i386/sev.c
index 846018a..51cdbe5 100644
--- a/target/i386/sev.c
+++ b/target/i386/sev.c
@@ -248,22 +248,19 @@
{
object_class_property_add_str(oc, "sev-device",
qsev_guest_get_sev_device,
- qsev_guest_set_sev_device,
- NULL);
+ qsev_guest_set_sev_device);
object_class_property_set_description(oc, "sev-device",
- "SEV device to use", NULL);
+ "SEV device to use");
object_class_property_add_str(oc, "dh-cert-file",
qsev_guest_get_dh_cert_file,
- qsev_guest_set_dh_cert_file,
- NULL);
+ qsev_guest_set_dh_cert_file);
object_class_property_set_description(oc, "dh-cert-file",
- "guest owners DH certificate (encoded with base64)", NULL);
+ "guest owners DH certificate (encoded with base64)");
object_class_property_add_str(oc, "session-file",
qsev_guest_get_session_file,
- qsev_guest_set_session_file,
- NULL);
+ qsev_guest_set_session_file);
object_class_property_set_description(oc, "session-file",
- "guest owners session parameters (encoded with base64)", NULL);
+ "guest owners session parameters (encoded with base64)");
}
static void
@@ -274,14 +271,14 @@
sev->sev_device = g_strdup(DEFAULT_SEV_DEVICE);
sev->policy = DEFAULT_GUEST_POLICY;
object_property_add_uint32_ptr(obj, "policy", &sev->policy,
- OBJ_PROP_FLAG_READWRITE, NULL);
+ OBJ_PROP_FLAG_READWRITE);
object_property_add_uint32_ptr(obj, "handle", &sev->handle,
- OBJ_PROP_FLAG_READWRITE, NULL);
+ OBJ_PROP_FLAG_READWRITE);
object_property_add_uint32_ptr(obj, "cbitpos", &sev->cbitpos,
- OBJ_PROP_FLAG_READWRITE, NULL);
+ OBJ_PROP_FLAG_READWRITE);
object_property_add_uint32_ptr(obj, "reduced-phys-bits",
&sev->reduced_phys_bits,
- OBJ_PROP_FLAG_READWRITE, NULL);
+ OBJ_PROP_FLAG_READWRITE);
}
/* sev guest info */
diff --git a/target/m68k/fpu_helper.c b/target/m68k/fpu_helper.c
index 4137542..36e6c70 100644
--- a/target/m68k/fpu_helper.c
+++ b/target/m68k/fpu_helper.c
@@ -149,7 +149,7 @@
void HELPER(fitrunc)(CPUM68KState *env, FPReg *res, FPReg *val)
{
- int rounding_mode = get_float_rounding_mode(&env->fp_status);
+ FloatRoundMode rounding_mode = get_float_rounding_mode(&env->fp_status);
set_float_rounding_mode(float_round_to_zero, &env->fp_status);
res->d = floatx80_round_to_int(val->d, &env->fp_status);
set_float_rounding_mode(rounding_mode, &env->fp_status);
@@ -300,7 +300,7 @@
void HELPER(fsglmul)(CPUM68KState *env, FPReg *res, FPReg *val0, FPReg *val1)
{
- int rounding_mode = get_float_rounding_mode(&env->fp_status);
+ FloatRoundMode rounding_mode = get_float_rounding_mode(&env->fp_status);
floatx80 a, b;
PREC_BEGIN(32);
@@ -333,7 +333,7 @@
void HELPER(fsgldiv)(CPUM68KState *env, FPReg *res, FPReg *val0, FPReg *val1)
{
- int rounding_mode = get_float_rounding_mode(&env->fp_status);
+ FloatRoundMode rounding_mode = get_float_rounding_mode(&env->fp_status);
floatx80 a, b;
PREC_BEGIN(32);
diff --git a/target/m68k/softfloat.c b/target/m68k/softfloat.c
index 24c313e..9f120cf 100644
--- a/target/m68k/softfloat.c
+++ b/target/m68k/softfloat.c
@@ -49,7 +49,7 @@
floatx80 floatx80_mod(floatx80 a, floatx80 b, float_status *status)
{
- flag aSign, zSign;
+ bool aSign, zSign;
int32_t aExp, bExp, expDiff;
uint64_t aSig0, aSig1, bSig;
uint64_t qTemp, term0, term1;
@@ -132,7 +132,7 @@
floatx80 floatx80_getman(floatx80 a, float_status *status)
{
- flag aSign;
+ bool aSign;
int32_t aExp;
uint64_t aSig;
@@ -166,7 +166,7 @@
floatx80 floatx80_getexp(floatx80 a, float_status *status)
{
- flag aSign;
+ bool aSign;
int32_t aExp;
uint64_t aSig;
@@ -202,7 +202,7 @@
floatx80 floatx80_scale(floatx80 a, floatx80 b, float_status *status)
{
- flag aSign, bSign;
+ bool aSign, bSign;
int32_t aExp, bExp, shiftCount;
uint64_t aSig, bSig;
@@ -258,7 +258,7 @@
floatx80 floatx80_move(floatx80 a, float_status *status)
{
- flag aSign;
+ bool aSign;
int32_t aExp;
uint64_t aSig;
@@ -306,7 +306,7 @@
floatx80 floatx80_lognp1(floatx80 a, float_status *status)
{
- flag aSign;
+ bool aSign;
int32_t aExp;
uint64_t aSig, fSig;
@@ -505,7 +505,7 @@
floatx80 floatx80_logn(floatx80 a, float_status *status)
{
- flag aSign;
+ bool aSign;
int32_t aExp;
uint64_t aSig, fSig;
@@ -673,7 +673,7 @@
floatx80 floatx80_log10(floatx80 a, float_status *status)
{
- flag aSign;
+ bool aSign;
int32_t aExp;
uint64_t aSig;
@@ -730,7 +730,7 @@
floatx80 floatx80_log2(floatx80 a, float_status *status)
{
- flag aSign;
+ bool aSign;
int32_t aExp;
uint64_t aSig;
@@ -797,7 +797,7 @@
floatx80 floatx80_etox(floatx80 a, float_status *status)
{
- flag aSign;
+ bool aSign;
int32_t aExp;
uint64_t aSig;
@@ -805,7 +805,7 @@
int32_t compact, n, j, k, m, m1;
floatx80 fp0, fp1, fp2, fp3, l2, scale, adjscale;
- flag adjflag;
+ bool adjflag;
aSig = extractFloatx80Frac(a);
aExp = extractFloatx80Exp(a);
@@ -981,7 +981,7 @@
floatx80 floatx80_twotox(floatx80 a, float_status *status)
{
- flag aSign;
+ bool aSign;
int32_t aExp;
uint64_t aSig;
@@ -1131,7 +1131,7 @@
floatx80 floatx80_tentox(floatx80 a, float_status *status)
{
- flag aSign;
+ bool aSign;
int32_t aExp;
uint64_t aSig;
@@ -1286,7 +1286,7 @@
floatx80 floatx80_tan(floatx80 a, float_status *status)
{
- flag aSign, xSign;
+ bool aSign, xSign;
int32_t aExp, xExp;
uint64_t aSig, xSig;
@@ -1295,7 +1295,7 @@
int32_t compact, l, n, j;
floatx80 fp0, fp1, fp2, fp3, fp4, fp5, invtwopi, twopi1, twopi2;
float32 twoto63;
- flag endflag;
+ bool endflag;
aSig = extractFloatx80Frac(a);
aExp = extractFloatx80Exp(a);
@@ -1344,10 +1344,10 @@
xExp -= 0x3FFF;
if (xExp <= 28) {
l = 0;
- endflag = 1;
+ endflag = true;
} else {
l = xExp - 27;
- endflag = 0;
+ endflag = false;
}
invtwopi = packFloatx80(0, 0x3FFE - l,
UINT64_C(0xA2F9836E4E44152A)); /* INVTWOPI */
@@ -1372,7 +1372,7 @@
fp1 = floatx80_sub(fp1, fp4, status); /* FP1 is a := r - p */
fp0 = floatx80_add(fp0, fp1, status); /* FP0 is R := A+a */
- if (endflag > 0) {
+ if (endflag) {
n = floatx80_to_int32(fp2, status);
goto tancont;
}
@@ -1496,7 +1496,7 @@
floatx80 floatx80_sin(floatx80 a, float_status *status)
{
- flag aSign, xSign;
+ bool aSign, xSign;
int32_t aExp, xExp;
uint64_t aSig, xSig;
@@ -1505,7 +1505,7 @@
int32_t compact, l, n, j;
floatx80 fp0, fp1, fp2, fp3, fp4, fp5, x, invtwopi, twopi1, twopi2;
float32 posneg1, twoto63;
- flag endflag;
+ bool endflag;
aSig = extractFloatx80Frac(a);
aExp = extractFloatx80Exp(a);
@@ -1554,10 +1554,10 @@
xExp -= 0x3FFF;
if (xExp <= 28) {
l = 0;
- endflag = 1;
+ endflag = true;
} else {
l = xExp - 27;
- endflag = 0;
+ endflag = false;
}
invtwopi = packFloatx80(0, 0x3FFE - l,
UINT64_C(0xA2F9836E4E44152A)); /* INVTWOPI */
@@ -1582,7 +1582,7 @@
fp1 = floatx80_sub(fp1, fp4, status); /* FP1 is a := r - p */
fp0 = floatx80_add(fp0, fp1, status); /* FP0 is R := A+a */
- if (endflag > 0) {
+ if (endflag) {
n = floatx80_to_int32(fp2, status);
goto sincont;
}
@@ -1735,7 +1735,7 @@
floatx80 floatx80_cos(floatx80 a, float_status *status)
{
- flag aSign, xSign;
+ bool aSign, xSign;
int32_t aExp, xExp;
uint64_t aSig, xSig;
@@ -1744,7 +1744,7 @@
int32_t compact, l, n, j;
floatx80 fp0, fp1, fp2, fp3, fp4, fp5, x, invtwopi, twopi1, twopi2;
float32 posneg1, twoto63;
- flag endflag;
+ bool endflag;
aSig = extractFloatx80Frac(a);
aExp = extractFloatx80Exp(a);
@@ -1793,10 +1793,10 @@
xExp -= 0x3FFF;
if (xExp <= 28) {
l = 0;
- endflag = 1;
+ endflag = true;
} else {
l = xExp - 27;
- endflag = 0;
+ endflag = false;
}
invtwopi = packFloatx80(0, 0x3FFE - l,
UINT64_C(0xA2F9836E4E44152A)); /* INVTWOPI */
@@ -1821,7 +1821,7 @@
fp1 = floatx80_sub(fp1, fp4, status); /* FP1 is a := r - p */
fp0 = floatx80_add(fp0, fp1, status); /* FP0 is R := A+a */
- if (endflag > 0) {
+ if (endflag) {
n = floatx80_to_int32(fp2, status);
goto sincont;
}
@@ -1972,7 +1972,7 @@
floatx80 floatx80_atan(floatx80 a, float_status *status)
{
- flag aSign;
+ bool aSign;
int32_t aExp;
uint64_t aSig;
@@ -2169,7 +2169,7 @@
floatx80 floatx80_asin(floatx80 a, float_status *status)
{
- flag aSign;
+ bool aSign;
int32_t aExp;
uint64_t aSig;
@@ -2234,7 +2234,7 @@
floatx80 floatx80_acos(floatx80 a, float_status *status)
{
- flag aSign;
+ bool aSign;
int32_t aExp;
uint64_t aSig;
@@ -2303,7 +2303,7 @@
floatx80 floatx80_atanh(floatx80 a, float_status *status)
{
- flag aSign;
+ bool aSign;
int32_t aExp;
uint64_t aSig;
@@ -2368,7 +2368,7 @@
floatx80 floatx80_etoxm1(floatx80 a, float_status *status)
{
- flag aSign;
+ bool aSign;
int32_t aExp;
uint64_t aSig;
@@ -2620,7 +2620,7 @@
floatx80 floatx80_tanh(floatx80 a, float_status *status)
{
- flag aSign, vSign;
+ bool aSign, vSign;
int32_t aExp, vExp;
uint64_t aSig, vSig;
@@ -2735,7 +2735,7 @@
floatx80 floatx80_sinh(floatx80 a, float_status *status)
{
- flag aSign;
+ bool aSign;
int32_t aExp;
uint64_t aSig;
diff --git a/target/microblaze/cpu.c b/target/microblaze/cpu.c
index aa99830..51e5c85 100644
--- a/target/microblaze/cpu.c
+++ b/target/microblaze/cpu.c
@@ -329,7 +329,7 @@
#endif
dc->vmsd = &vmstate_mb_cpu;
device_class_set_props(dc, mb_properties);
- cc->gdb_num_core_regs = 32 + 5;
+ cc->gdb_num_core_regs = 32 + 27;
cc->disas_set_info = mb_disas_set_info;
cc->tcg_initialize = mb_tcg_init;
diff --git a/target/microblaze/gdbstub.c b/target/microblaze/gdbstub.c
index f41ebf1..73e8973 100644
--- a/target/microblaze/gdbstub.c
+++ b/target/microblaze/gdbstub.c
@@ -25,13 +25,54 @@
{
MicroBlazeCPU *cpu = MICROBLAZE_CPU(cs);
CPUMBState *env = &cpu->env;
+ /*
+ * GDB expects SREGs in the following order:
+ * PC, MSR, EAR, ESR, FSR, BTR, EDR, PID, ZPR, TLBX, TLBSX, TLBLO, TLBHI.
+ * They aren't stored in this order, so make a map.
+ * PID, ZPR, TLBx, TLBsx, TLBLO, and TLBHI aren't modeled, so we don't
+ * map them to anything and return a value of 0 instead.
+ */
+ static const uint8_t sreg_map[6] = {
+ SR_PC,
+ SR_MSR,
+ SR_EAR,
+ SR_ESR,
+ SR_FSR,
+ SR_BTR
+ };
+ /*
+ * GDB expects registers to be reported in this order:
+ * R0-R31
+ * PC-BTR
+ * PVR0-PVR11
+ * EDR-TLBHI
+ * SLR-SHR
+ */
if (n < 32) {
return gdb_get_reg32(mem_buf, env->regs[n]);
} else {
- return gdb_get_reg32(mem_buf, env->sregs[n - 32]);
+ n -= 32;
+ switch (n) {
+ case 0 ... 5:
+ return gdb_get_reg32(mem_buf, env->sregs[sreg_map[n]]);
+ /* PVR12 is intentionally skipped */
+ case 6 ... 17:
+ n -= 6;
+ return gdb_get_reg32(mem_buf, env->pvr.regs[n]);
+ case 18:
+ return gdb_get_reg32(mem_buf, env->sregs[SR_EDR]);
+ /* Other SRegs aren't modeled, so report a value of 0 */
+ case 19 ... 24:
+ return gdb_get_reg32(mem_buf, 0);
+ case 25:
+ return gdb_get_reg32(mem_buf, env->slr);
+ case 26:
+ return gdb_get_reg32(mem_buf, env->shr);
+ default:
+ return 0;
+ }
}
- return 0;
}
int mb_cpu_gdb_write_register(CPUState *cs, uint8_t *mem_buf, int n)
@@ -41,16 +82,60 @@
CPUMBState *env = &cpu->env;
uint32_t tmp;
+ /*
+ * GDB expects SREGs in the following order:
+ * PC, MSR, EAR, ESR, FSR, BTR, EDR, PID, ZPR, TLBX, TLBSX, TLBLO, TLBHI.
+ * They aren't stored in this order, so make a map.
+ * PID, ZPR, TLBx, TLBsx, TLBLO, and TLBHI aren't modeled, so we don't
+ * map them to anything.
+ */
+ static const uint8_t sreg_map[6] = {
+ SR_PC,
+ SR_MSR,
+ SR_EAR,
+ SR_ESR,
+ SR_FSR,
+ SR_BTR
+ };
+
if (n > cc->gdb_num_core_regs) {
return 0;
}
tmp = ldl_p(mem_buf);
+ /*
+ * GDB expects registers to be reported in this order:
+ * R0-R31
+ * PC-BTR
+ * PVR0-PVR11
+ * EDR-TLBHI
+ * SLR-SHR
+ */
if (n < 32) {
env->regs[n] = tmp;
} else {
- env->sregs[n - 32] = tmp;
+ n -= 32;
+ switch (n) {
+ case 0 ... 5:
+ env->sregs[sreg_map[n]] = tmp;
+ break;
+ /* PVR12 is intentionally skipped */
+ case 6 ... 17:
+ n -= 6;
+ env->pvr.regs[n] = tmp;
+ break;
+ /* Only EDR is modeled in these indeces, so ignore the rest */
+ case 18:
+ env->sregs[SR_EDR] = tmp;
+ break;
+ case 25:
+ env->slr = tmp;
+ break;
+ case 26:
+ env->shr = tmp;
+ break;
+ }
}
return 4;
}
diff --git a/target/microblaze/translate.c b/target/microblaze/translate.c
index 20b7427..f6ff259 100644
--- a/target/microblaze/translate.c
+++ b/target/microblaze/translate.c
@@ -581,6 +581,7 @@
case SR_ESR:
case SR_FSR:
case SR_BTR:
+ case SR_EDR:
tcg_gen_extrl_i64_i32(cpu_R[dc->rd], cpu_SR[sr]);
break;
case 0x800:
@@ -1391,7 +1392,7 @@
tcg_gen_movi_i64(cpu_SR[SR_ESR], ESR_EC_FPU);
t_gen_raise_exception(dc, EXCP_HW_EXCP);
}
- return (dc->cpu->cfg.use_fpu == 2) ? 0 : PVR2_USE_FPU2_MASK;
+ return (dc->cpu->cfg.use_fpu == 2) ? PVR2_USE_FPU2_MASK : 0;
}
static void dec_fpu(DisasContext *dc)
@@ -1788,9 +1789,11 @@
qemu_fprintf(f, "IN: PC=%" PRIx64 " %s\n",
env->sregs[SR_PC], lookup_symbol(env->sregs[SR_PC]));
qemu_fprintf(f, "rmsr=%" PRIx64 " resr=%" PRIx64 " rear=%" PRIx64 " "
- "debug=%x imm=%x iflags=%x fsr=%" PRIx64 "\n",
+ "debug=%x imm=%x iflags=%x fsr=%" PRIx64 " "
+ "rbtr=%" PRIx64 "\n",
env->sregs[SR_MSR], env->sregs[SR_ESR], env->sregs[SR_EAR],
- env->debug, env->imm, env->iflags, env->sregs[SR_FSR]);
+ env->debug, env->imm, env->iflags, env->sregs[SR_FSR],
+ env->sregs[SR_BTR]);
qemu_fprintf(f, "btaken=%d btarget=%" PRIx64 " mode=%s(saved=%s) "
"eip=%d ie=%d\n",
env->btaken, env->btarget,
@@ -1798,7 +1801,17 @@
(env->sregs[SR_MSR] & MSR_UMS) ? "user" : "kernel",
(bool)(env->sregs[SR_MSR] & MSR_EIP),
(bool)(env->sregs[SR_MSR] & MSR_IE));
+ for (i = 0; i < 12; i++) {
+ qemu_fprintf(f, "rpvr%2.2d=%8.8x ", i, env->pvr.regs[i]);
+ if ((i + 1) % 4 == 0) {
+ qemu_fprintf(f, "\n");
+ }
+ }
+ /* Registers that aren't modeled are reported as 0 */
+ qemu_fprintf(f, "redr=%" PRIx64 " rpid=0 rzpr=0 rtlbx=0 rtlbsx=0 "
+ "rtlblo=0 rtlbhi=0\n", env->sregs[SR_EDR]);
+ qemu_fprintf(f, "slr=%x shr=%x\n", env->slr, env->shr);
for (i = 0; i < 32; i++) {
qemu_fprintf(f, "r%2.2d=%8.8x ", i, env->regs[i]);
if ((i + 1) % 4 == 0)
diff --git a/target/mips/cpu-param.h b/target/mips/cpu-param.h
index 308660d..9c4a6ea 100644
--- a/target/mips/cpu-param.h
+++ b/target/mips/cpu-param.h
@@ -23,7 +23,12 @@
# define TARGET_VIRT_ADDR_SPACE_BITS 32
#endif
#endif
+#ifdef CONFIG_USER_ONLY
#define TARGET_PAGE_BITS 12
+#else
+#define TARGET_PAGE_BITS_VARY
+#define TARGET_PAGE_BITS_MIN 12
+#endif
#define NB_MMU_MODES 4
#endif
diff --git a/target/mips/kvm.c b/target/mips/kvm.c
index de3e26e..96cfa10 100644
--- a/target/mips/kvm.c
+++ b/target/mips/kvm.c
@@ -245,10 +245,16 @@
(KVM_REG_MIPS_CP0 | KVM_REG_SIZE_U64 | (8 * (_R) + (_S)))
#define KVM_REG_MIPS_CP0_INDEX MIPS_CP0_32(0, 0)
+#define KVM_REG_MIPS_CP0_RANDOM MIPS_CP0_32(1, 0)
#define KVM_REG_MIPS_CP0_CONTEXT MIPS_CP0_64(4, 0)
#define KVM_REG_MIPS_CP0_USERLOCAL MIPS_CP0_64(4, 2)
#define KVM_REG_MIPS_CP0_PAGEMASK MIPS_CP0_32(5, 0)
+#define KVM_REG_MIPS_CP0_PAGEGRAIN MIPS_CP0_32(5, 1)
+#define KVM_REG_MIPS_CP0_PWBASE MIPS_CP0_64(5, 5)
+#define KVM_REG_MIPS_CP0_PWFIELD MIPS_CP0_64(5, 6)
+#define KVM_REG_MIPS_CP0_PWSIZE MIPS_CP0_64(5, 7)
#define KVM_REG_MIPS_CP0_WIRED MIPS_CP0_32(6, 0)
+#define KVM_REG_MIPS_CP0_PWCTL MIPS_CP0_32(6, 6)
#define KVM_REG_MIPS_CP0_HWRENA MIPS_CP0_32(7, 0)
#define KVM_REG_MIPS_CP0_BADVADDR MIPS_CP0_64(8, 0)
#define KVM_REG_MIPS_CP0_COUNT MIPS_CP0_32(9, 0)
@@ -258,13 +264,22 @@
#define KVM_REG_MIPS_CP0_CAUSE MIPS_CP0_32(13, 0)
#define KVM_REG_MIPS_CP0_EPC MIPS_CP0_64(14, 0)
#define KVM_REG_MIPS_CP0_PRID MIPS_CP0_32(15, 0)
+#define KVM_REG_MIPS_CP0_EBASE MIPS_CP0_64(15, 1)
#define KVM_REG_MIPS_CP0_CONFIG MIPS_CP0_32(16, 0)
#define KVM_REG_MIPS_CP0_CONFIG1 MIPS_CP0_32(16, 1)
#define KVM_REG_MIPS_CP0_CONFIG2 MIPS_CP0_32(16, 2)
#define KVM_REG_MIPS_CP0_CONFIG3 MIPS_CP0_32(16, 3)
#define KVM_REG_MIPS_CP0_CONFIG4 MIPS_CP0_32(16, 4)
#define KVM_REG_MIPS_CP0_CONFIG5 MIPS_CP0_32(16, 5)
+#define KVM_REG_MIPS_CP0_CONFIG6 MIPS_CP0_32(16, 6)
+#define KVM_REG_MIPS_CP0_XCONTEXT MIPS_CP0_64(20, 0)
#define KVM_REG_MIPS_CP0_ERROREPC MIPS_CP0_64(30, 0)
+#define KVM_REG_MIPS_CP0_KSCRATCH1 MIPS_CP0_64(31, 2)
+#define KVM_REG_MIPS_CP0_KSCRATCH2 MIPS_CP0_64(31, 3)
+#define KVM_REG_MIPS_CP0_KSCRATCH3 MIPS_CP0_64(31, 4)
+#define KVM_REG_MIPS_CP0_KSCRATCH4 MIPS_CP0_64(31, 5)
+#define KVM_REG_MIPS_CP0_KSCRATCH5 MIPS_CP0_64(31, 6)
+#define KVM_REG_MIPS_CP0_KSCRATCH6 MIPS_CP0_64(31, 7)
static inline int kvm_mips_put_one_reg(CPUState *cs, uint64_t reg_id,
int32_t *addr)
@@ -394,6 +409,29 @@
(1U << CP0C5_UFE) | \
(1U << CP0C5_FRE) | \
(1U << CP0C5_UFR))
+#define KVM_REG_MIPS_CP0_CONFIG6_MASK ((1U << CP0C6_BPPASS) | \
+ (0x3fU << CP0C6_KPOS) | \
+ (1U << CP0C6_KE) | \
+ (1U << CP0C6_VTLBONLY) | \
+ (1U << CP0C6_LASX) | \
+ (1U << CP0C6_SSEN) | \
+ (1U << CP0C6_DISDRTIME) | \
+ (1U << CP0C6_PIXNUEN) | \
+ (1U << CP0C6_SCRAND) | \
+ (1U << CP0C6_LLEXCEN) | \
+ (1U << CP0C6_DISVC) | \
+ (1U << CP0C6_VCLRU) | \
+ (1U << CP0C6_DCLRU) | \
+ (1U << CP0C6_PIXUEN) | \
+ (1U << CP0C6_DISBLKLYEN) | \
+ (1U << CP0C6_UMEMUALEN) | \
+ (1U << CP0C6_SFBEN) | \
+ (1U << CP0C6_FLTINT) | \
+ (1U << CP0C6_VLTINT) | \
+ (1U << CP0C6_DISBTB) | \
+ (3U << CP0C6_STPREFCTL) | \
+ (1U << CP0C6_INSTPREF) | \
+ (1U << CP0C6_DATAPREF))
static inline int kvm_mips_change_one_reg(CPUState *cs, uint64_t reg_id,
int32_t *addr, int32_t mask)
@@ -729,6 +767,11 @@
DPRINTF("%s: Failed to put CP0_INDEX (%d)\n", __func__, err);
ret = err;
}
+ err = kvm_mips_put_one_reg(cs, KVM_REG_MIPS_CP0_RANDOM, &env->CP0_Random);
+ if (err < 0) {
+ DPRINTF("%s: Failed to put CP0_RANDOM (%d)\n", __func__, err);
+ ret = err;
+ }
err = kvm_mips_put_one_ulreg(cs, KVM_REG_MIPS_CP0_CONTEXT,
&env->CP0_Context);
if (err < 0) {
@@ -747,11 +790,40 @@
DPRINTF("%s: Failed to put CP0_PAGEMASK (%d)\n", __func__, err);
ret = err;
}
+ err = kvm_mips_put_one_reg(cs, KVM_REG_MIPS_CP0_PAGEGRAIN,
+ &env->CP0_PageGrain);
+ if (err < 0) {
+ DPRINTF("%s: Failed to put CP0_PAGEGRAIN (%d)\n", __func__, err);
+ ret = err;
+ }
+ err = kvm_mips_put_one_ulreg(cs, KVM_REG_MIPS_CP0_PWBASE,
+ &env->CP0_PWBase);
+ if (err < 0) {
+ DPRINTF("%s: Failed to put CP0_PWBASE (%d)\n", __func__, err);
+ ret = err;
+ }
+ err = kvm_mips_put_one_ulreg(cs, KVM_REG_MIPS_CP0_PWFIELD,
+ &env->CP0_PWField);
+ if (err < 0) {
+ DPRINTF("%s: Failed to put CP0_PWField (%d)\n", __func__, err);
+ ret = err;
+ }
+ err = kvm_mips_put_one_ulreg(cs, KVM_REG_MIPS_CP0_PWSIZE,
+ &env->CP0_PWSize);
+ if (err < 0) {
+ DPRINTF("%s: Failed to put CP0_PWSIZE (%d)\n", __func__, err);
+ ret = err;
+ }
err = kvm_mips_put_one_reg(cs, KVM_REG_MIPS_CP0_WIRED, &env->CP0_Wired);
if (err < 0) {
DPRINTF("%s: Failed to put CP0_WIRED (%d)\n", __func__, err);
ret = err;
}
+ err = kvm_mips_put_one_reg(cs, KVM_REG_MIPS_CP0_PWCTL, &env->CP0_PWCtl);
+ if (err < 0) {
+ DPRINTF("%s: Failed to put CP0_PWCTL (%d)\n", __func__, err);
+ ret = err;
+ }
err = kvm_mips_put_one_reg(cs, KVM_REG_MIPS_CP0_HWRENA, &env->CP0_HWREna);
if (err < 0) {
DPRINTF("%s: Failed to put CP0_HWRENA (%d)\n", __func__, err);
@@ -799,6 +871,11 @@
DPRINTF("%s: Failed to put CP0_PRID (%d)\n", __func__, err);
ret = err;
}
+ err = kvm_mips_put_one_ulreg(cs, KVM_REG_MIPS_CP0_EBASE, &env->CP0_EBase);
+ if (err < 0) {
+ DPRINTF("%s: Failed to put CP0_EBASE (%d)\n", __func__, err);
+ ret = err;
+ }
err = kvm_mips_change_one_reg(cs, KVM_REG_MIPS_CP0_CONFIG,
&env->CP0_Config0,
KVM_REG_MIPS_CP0_CONFIG_MASK);
@@ -841,12 +918,61 @@
DPRINTF("%s: Failed to change CP0_CONFIG5 (%d)\n", __func__, err);
ret = err;
}
+ err = kvm_mips_change_one_reg(cs, KVM_REG_MIPS_CP0_CONFIG6,
+ &env->CP0_Config6,
+ KVM_REG_MIPS_CP0_CONFIG6_MASK);
+ if (err < 0) {
+ DPRINTF("%s: Failed to change CP0_CONFIG6 (%d)\n", __func__, err);
+ ret = err;
+ }
+ err = kvm_mips_put_one_ulreg(cs, KVM_REG_MIPS_CP0_XCONTEXT,
+ &env->CP0_XContext);
+ if (err < 0) {
+ DPRINTF("%s: Failed to put CP0_XCONTEXT (%d)\n", __func__, err);
+ ret = err;
+ }
err = kvm_mips_put_one_ulreg(cs, KVM_REG_MIPS_CP0_ERROREPC,
&env->CP0_ErrorEPC);
if (err < 0) {
DPRINTF("%s: Failed to put CP0_ERROREPC (%d)\n", __func__, err);
ret = err;
}
+ err = kvm_mips_put_one_ulreg(cs, KVM_REG_MIPS_CP0_KSCRATCH1,
+ &env->CP0_KScratch[0]);
+ if (err < 0) {
+ DPRINTF("%s: Failed to put CP0_KSCRATCH1 (%d)\n", __func__, err);
+ ret = err;
+ }
+ err = kvm_mips_put_one_ulreg(cs, KVM_REG_MIPS_CP0_KSCRATCH2,
+ &env->CP0_KScratch[1]);
+ if (err < 0) {
+ DPRINTF("%s: Failed to put CP0_KSCRATCH2 (%d)\n", __func__, err);
+ ret = err;
+ }
+ err = kvm_mips_put_one_ulreg(cs, KVM_REG_MIPS_CP0_KSCRATCH3,
+ &env->CP0_KScratch[2]);
+ if (err < 0) {
+ DPRINTF("%s: Failed to put CP0_KSCRATCH3 (%d)\n", __func__, err);
+ ret = err;
+ }
+ err = kvm_mips_put_one_ulreg(cs, KVM_REG_MIPS_CP0_KSCRATCH4,
+ &env->CP0_KScratch[3]);
+ if (err < 0) {
+ DPRINTF("%s: Failed to put CP0_KSCRATCH4 (%d)\n", __func__, err);
+ ret = err;
+ }
+ err = kvm_mips_put_one_ulreg(cs, KVM_REG_MIPS_CP0_KSCRATCH5,
+ &env->CP0_KScratch[4]);
+ if (err < 0) {
+ DPRINTF("%s: Failed to put CP0_KSCRATCH5 (%d)\n", __func__, err);
+ ret = err;
+ }
+ err = kvm_mips_put_one_ulreg(cs, KVM_REG_MIPS_CP0_KSCRATCH6,
+ &env->CP0_KScratch[5]);
+ if (err < 0) {
+ DPRINTF("%s: Failed to put CP0_KSCRATCH6 (%d)\n", __func__, err);
+ ret = err;
+ }
return ret;
}
@@ -862,6 +988,11 @@
DPRINTF("%s: Failed to get CP0_INDEX (%d)\n", __func__, err);
ret = err;
}
+ err = kvm_mips_get_one_reg(cs, KVM_REG_MIPS_CP0_RANDOM, &env->CP0_Random);
+ if (err < 0) {
+ DPRINTF("%s: Failed to get CP0_RANDOM (%d)\n", __func__, err);
+ ret = err;
+ }
err = kvm_mips_get_one_ulreg(cs, KVM_REG_MIPS_CP0_CONTEXT,
&env->CP0_Context);
if (err < 0) {
@@ -880,11 +1011,40 @@
DPRINTF("%s: Failed to get CP0_PAGEMASK (%d)\n", __func__, err);
ret = err;
}
+ err = kvm_mips_get_one_reg(cs, KVM_REG_MIPS_CP0_PAGEGRAIN,
+ &env->CP0_PageGrain);
+ if (err < 0) {
+ DPRINTF("%s: Failed to get CP0_PAGEGRAIN (%d)\n", __func__, err);
+ ret = err;
+ }
+ err = kvm_mips_get_one_ulreg(cs, KVM_REG_MIPS_CP0_PWBASE,
+ &env->CP0_PWBase);
+ if (err < 0) {
+ DPRINTF("%s: Failed to get CP0_PWBASE (%d)\n", __func__, err);
+ ret = err;
+ }
+ err = kvm_mips_get_one_ulreg(cs, KVM_REG_MIPS_CP0_PWFIELD,
+ &env->CP0_PWField);
+ if (err < 0) {
+ DPRINTF("%s: Failed to get CP0_PWFIELD (%d)\n", __func__, err);
+ ret = err;
+ }
+ err = kvm_mips_get_one_ulreg(cs, KVM_REG_MIPS_CP0_PWSIZE,
+ &env->CP0_PWSize);
+ if (err < 0) {
+ DPRINTF("%s: Failed to get CP0_PWSIZE (%d)\n", __func__, err);
+ ret = err;
+ }
err = kvm_mips_get_one_reg(cs, KVM_REG_MIPS_CP0_WIRED, &env->CP0_Wired);
if (err < 0) {
DPRINTF("%s: Failed to get CP0_WIRED (%d)\n", __func__, err);
ret = err;
}
+ err = kvm_mips_get_one_reg(cs, KVM_REG_MIPS_CP0_PWCTL, &env->CP0_PWCtl);
+ if (err < 0) {
+ DPRINTF("%s: Failed to get CP0_PWCtl (%d)\n", __func__, err);
+ ret = err;
+ }
err = kvm_mips_get_one_reg(cs, KVM_REG_MIPS_CP0_HWRENA, &env->CP0_HWREna);
if (err < 0) {
DPRINTF("%s: Failed to get CP0_HWRENA (%d)\n", __func__, err);
@@ -932,6 +1092,11 @@
DPRINTF("%s: Failed to get CP0_PRID (%d)\n", __func__, err);
ret = err;
}
+ err = kvm_mips_get_one_ulreg(cs, KVM_REG_MIPS_CP0_EBASE, &env->CP0_EBase);
+ if (err < 0) {
+ DPRINTF("%s: Failed to get CP0_EBASE (%d)\n", __func__, err);
+ ret = err;
+ }
err = kvm_mips_get_one_reg(cs, KVM_REG_MIPS_CP0_CONFIG, &env->CP0_Config0);
if (err < 0) {
DPRINTF("%s: Failed to get CP0_CONFIG (%d)\n", __func__, err);
@@ -962,12 +1127,59 @@
DPRINTF("%s: Failed to get CP0_CONFIG5 (%d)\n", __func__, err);
ret = err;
}
+ err = kvm_mips_get_one_reg(cs, KVM_REG_MIPS_CP0_CONFIG6, &env->CP0_Config6);
+ if (err < 0) {
+ DPRINTF("%s: Failed to get CP0_CONFIG6 (%d)\n", __func__, err);
+ ret = err;
+ }
+ err = kvm_mips_get_one_ulreg(cs, KVM_REG_MIPS_CP0_XCONTEXT,
+ &env->CP0_XContext);
+ if (err < 0) {
+ DPRINTF("%s: Failed to get CP0_XCONTEXT (%d)\n", __func__, err);
+ ret = err;
+ }
err = kvm_mips_get_one_ulreg(cs, KVM_REG_MIPS_CP0_ERROREPC,
&env->CP0_ErrorEPC);
if (err < 0) {
DPRINTF("%s: Failed to get CP0_ERROREPC (%d)\n", __func__, err);
ret = err;
}
+ err = kvm_mips_get_one_ulreg(cs, KVM_REG_MIPS_CP0_KSCRATCH1,
+ &env->CP0_KScratch[0]);
+ if (err < 0) {
+ DPRINTF("%s: Failed to get CP0_KSCRATCH1 (%d)\n", __func__, err);
+ ret = err;
+ }
+ err = kvm_mips_get_one_ulreg(cs, KVM_REG_MIPS_CP0_KSCRATCH2,
+ &env->CP0_KScratch[1]);
+ if (err < 0) {
+ DPRINTF("%s: Failed to get CP0_KSCRATCH2 (%d)\n", __func__, err);
+ ret = err;
+ }
+ err = kvm_mips_get_one_ulreg(cs, KVM_REG_MIPS_CP0_KSCRATCH3,
+ &env->CP0_KScratch[2]);
+ if (err < 0) {
+ DPRINTF("%s: Failed to get CP0_KSCRATCH3 (%d)\n", __func__, err);
+ ret = err;
+ }
+ err = kvm_mips_get_one_ulreg(cs, KVM_REG_MIPS_CP0_KSCRATCH4,
+ &env->CP0_KScratch[3]);
+ if (err < 0) {
+ DPRINTF("%s: Failed to get CP0_KSCRATCH4 (%d)\n", __func__, err);
+ ret = err;
+ }
+ err = kvm_mips_get_one_ulreg(cs, KVM_REG_MIPS_CP0_KSCRATCH5,
+ &env->CP0_KScratch[4]);
+ if (err < 0) {
+ DPRINTF("%s: Failed to get CP0_KSCRATCH5 (%d)\n", __func__, err);
+ ret = err;
+ }
+ err = kvm_mips_get_one_ulreg(cs, KVM_REG_MIPS_CP0_KSCRATCH6,
+ &env->CP0_KScratch[5]);
+ if (err < 0) {
+ DPRINTF("%s: Failed to get CP0_KSCRATCH6 (%d)\n", __func__, err);
+ ret = err;
+ }
return ret;
}
diff --git a/target/mips/machine.c b/target/mips/machine.c
index 8d5b18b..5b23e3e 100644
--- a/target/mips/machine.c
+++ b/target/mips/machine.c
@@ -212,8 +212,8 @@
const VMStateDescription vmstate_mips_cpu = {
.name = "cpu",
- .version_id = 19,
- .minimum_version_id = 19,
+ .version_id = 20,
+ .minimum_version_id = 20,
.post_load = cpu_post_load,
.fields = (VMStateField[]) {
/* Active TC */
@@ -289,6 +289,8 @@
VMSTATE_INT32(env.CP0_Config1, MIPSCPU),
VMSTATE_INT32(env.CP0_Config2, MIPSCPU),
VMSTATE_INT32(env.CP0_Config3, MIPSCPU),
+ VMSTATE_INT32(env.CP0_Config4, MIPSCPU),
+ VMSTATE_INT32(env.CP0_Config5, MIPSCPU),
VMSTATE_INT32(env.CP0_Config6, MIPSCPU),
VMSTATE_INT32(env.CP0_Config7, MIPSCPU),
VMSTATE_UINT64(env.CP0_LLAddr, MIPSCPU),
diff --git a/target/mips/msa_helper.c b/target/mips/msa_helper.c
index 4065cfe..3c7012c 100644
--- a/target/mips/msa_helper.c
+++ b/target/mips/msa_helper.c
@@ -5508,7 +5508,7 @@
return c & enable;
}
-static inline float16 float16_from_float32(int32_t a, flag ieee,
+static inline float16 float16_from_float32(int32_t a, bool ieee,
float_status *status)
{
float16 f_val;
@@ -5527,7 +5527,7 @@
return a < 0 ? (f_val | (1 << 31)) : f_val;
}
-static inline float32 float32_from_float16(int16_t a, flag ieee,
+static inline float32 float32_from_float16(int16_t a, bool ieee,
float_status *status)
{
float32 f_val;
@@ -6564,7 +6564,7 @@
* IEEE and "ARM" format. The latter gains extra exponent
* range by omitting the NaN/Inf encodings.
*/
- flag ieee = 1;
+ bool ieee = true;
MSA_FLOAT_BINOP(Lh(pwx, i), from_float32, pws->w[i], ieee, 16);
MSA_FLOAT_BINOP(Rh(pwx, i), from_float32, pwt->w[i], ieee, 16);
@@ -7178,7 +7178,7 @@
* IEEE and "ARM" format. The latter gains extra exponent
* range by omitting the NaN/Inf encodings.
*/
- flag ieee = 1;
+ bool ieee = true;
MSA_FLOAT_BINOP(pwx->w[i], from_float16, Lh(pws, i), ieee, 32);
}
@@ -7214,7 +7214,7 @@
* IEEE and "ARM" format. The latter gains extra exponent
* range by omitting the NaN/Inf encodings.
*/
- flag ieee = 1;
+ bool ieee = true;
MSA_FLOAT_BINOP(pwx->w[i], from_float16, Rh(pws, i), ieee, 32);
}
diff --git a/target/openrisc/fpu_helper.c b/target/openrisc/fpu_helper.c
index 6f75ea0..f9e34fa 100644
--- a/target/openrisc/fpu_helper.c
+++ b/target/openrisc/fpu_helper.c
@@ -155,13 +155,13 @@
target_ulong helper_float_ ## name ## _d(CPUOpenRISCState *env, \
uint64_t fdt0, uint64_t fdt1) \
{ \
- int r = float64_compare_quiet(fdt0, fdt1, &env->fp_status); \
+ FloatRelation r = float64_compare_quiet(fdt0, fdt1, &env->fp_status); \
return expr; \
} \
target_ulong helper_float_ ## name ## _s(CPUOpenRISCState *env, \
uint32_t fdt0, uint32_t fdt1) \
{ \
- int r = float32_compare_quiet(fdt0, fdt1, &env->fp_status); \
+ FloatRelation r = float32_compare_quiet(fdt0, fdt1, &env->fp_status); \
return expr; \
}
diff --git a/target/ppc/compat.c b/target/ppc/compat.c
index f48df25..fda0dfe 100644
--- a/target/ppc/compat.c
+++ b/target/ppc/compat.c
@@ -298,20 +298,15 @@
}
void ppc_compat_add_property(Object *obj, const char *name,
- uint32_t *compat_pvr, const char *basedesc,
- Error **errp)
+ uint32_t *compat_pvr, const char *basedesc)
{
- Error *local_err = NULL;
gchar *namesv[ARRAY_SIZE(compat_table) + 1];
gchar *names, *desc;
int i;
object_property_add(obj, name, "string",
ppc_compat_prop_get, ppc_compat_prop_set, NULL,
- compat_pvr, &local_err);
- if (local_err) {
- goto out;
- }
+ compat_pvr);
for (i = 0; i < ARRAY_SIZE(compat_table); i++) {
/*
@@ -324,11 +319,8 @@
names = g_strjoinv(", ", namesv);
desc = g_strdup_printf("%s. Valid values are %s.", basedesc, names);
- object_property_set_description(obj, name, desc, &local_err);
+ object_property_set_description(obj, name, desc);
g_free(names);
g_free(desc);
-
-out:
- error_propagate(errp, local_err);
}
diff --git a/target/ppc/cpu.h b/target/ppc/cpu.h
index 6b6dd7e..1988b43 100644
--- a/target/ppc/cpu.h
+++ b/target/ppc/cpu.h
@@ -127,8 +127,9 @@
POWERPC_EXCP_SDOOR_HV = 100,
/* ISA 3.00 additions */
POWERPC_EXCP_HVIRT = 101,
+ POWERPC_EXCP_SYSCALL_VECTORED = 102, /* scv exception */
/* EOL */
- POWERPC_EXCP_NB = 102,
+ POWERPC_EXCP_NB = 103,
/* QEMU exceptions: used internally during code translation */
POWERPC_EXCP_STOP = 0x200, /* stop translation */
POWERPC_EXCP_BRANCH = 0x201, /* branch instruction */
@@ -475,9 +476,31 @@
#define SRR1_PROTFAULT DSISR_PROTFAULT
#define SRR1_IAMR DSISR_AMR
+/* SRR1[42:45] wakeup fields for System Reset Interrupt */
+
+#define SRR1_WAKEMASK 0x003c0000 /* reason for wakeup */
+
+#define SRR1_WAKEHMI 0x00280000 /* Hypervisor maintenance */
+#define SRR1_WAKEHVI 0x00240000 /* Hypervisor Virt. Interrupt (P9) */
+#define SRR1_WAKEEE 0x00200000 /* External interrupt */
+#define SRR1_WAKEDEC 0x00180000 /* Decrementer interrupt */
+#define SRR1_WAKEDBELL 0x00140000 /* Privileged doorbell */
+#define SRR1_WAKERESET 0x00100000 /* System reset */
+#define SRR1_WAKEHDBELL 0x000c0000 /* Hypervisor doorbell */
+#define SRR1_WAKESCOM 0x00080000 /* SCOM not in power-saving mode */
+
+/* SRR1[46:47] power-saving exit mode */
+
+#define SRR1_WAKESTATE 0x00030000 /* Powersave exit mask */
+
+#define SRR1_WS_HVLOSS 0x00030000 /* HV resources not maintained */
+#define SRR1_WS_GPRLOSS 0x00020000 /* GPRs not maintained */
+#define SRR1_WS_NOLOSS 0x00010000 /* All resources maintained */
+
/* Facility Status and Control (FSCR) bits */
#define FSCR_EBB (63 - 56) /* Event-Based Branch Facility */
#define FSCR_TAR (63 - 55) /* Target Address Register */
+#define FSCR_SCV (63 - 51) /* System call vectored */
/* Interrupt cause mask and position in FSCR. HFSCR has the same format */
#define FSCR_IC_MASK (0xFFULL)
#define FSCR_IC_POS (63 - 7)
@@ -487,6 +510,7 @@
#define FSCR_IC_TM 5
#define FSCR_IC_EBB 7
#define FSCR_IC_TAR 8
+#define FSCR_IC_SCV 12
/* Exception state register bits definition */
#define ESR_PIL PPC_BIT(36) /* Illegal Instruction */
@@ -554,6 +578,8 @@
POWERPC_FLAG_VSX = 0x00080000,
/* Has Transaction Memory (ISA 2.07) */
POWERPC_FLAG_TM = 0x00100000,
+ /* Has SCV (ISA 3.00) */
+ POWERPC_FLAG_SCV = 0x00200000,
};
/*****************************************************************************/
@@ -1338,8 +1364,7 @@
#endif
int ppc_compat_max_vthreads(PowerPCCPU *cpu);
void ppc_compat_add_property(Object *obj, const char *name,
- uint32_t *compat_pvr, const char *basedesc,
- Error **errp);
+ uint32_t *compat_pvr, const char *basedesc);
#endif /* defined(TARGET_PPC64) */
typedef CPUPPCState CPUArchState;
diff --git a/target/ppc/excp_helper.c b/target/ppc/excp_helper.c
index f052979..a988ba1 100644
--- a/target/ppc/excp_helper.c
+++ b/target/ppc/excp_helper.c
@@ -67,19 +67,31 @@
ppc_dump_gpr(env, 8), env->nip);
}
+static inline void dump_syscall_vectored(CPUPPCState *env)
+{
+ qemu_log_mask(CPU_LOG_INT, "syscall r0=%016" PRIx64
+ " r3=%016" PRIx64 " r4=%016" PRIx64 " r5=%016" PRIx64
+ " r6=%016" PRIx64 " r7=%016" PRIx64 " r8=%016" PRIx64
+ " nip=" TARGET_FMT_lx "\n",
+ ppc_dump_gpr(env, 0), ppc_dump_gpr(env, 3),
+ ppc_dump_gpr(env, 4), ppc_dump_gpr(env, 5),
+ ppc_dump_gpr(env, 6), ppc_dump_gpr(env, 7),
+ ppc_dump_gpr(env, 8), env->nip);
+}
+
static inline void dump_hcall(CPUPPCState *env)
{
qemu_log_mask(CPU_LOG_INT, "hypercall r3=%016" PRIx64
- " r4=%016" PRIx64 " r5=%016" PRIx64 " r6=%016" PRIx64
- " r7=%016" PRIx64 " r8=%016" PRIx64 " r9=%016" PRIx64
- " r10=%016" PRIx64 " r11=%016" PRIx64 " r12=%016" PRIx64
+ " r4=%016" PRIx64 " r5=%016" PRIx64 " r6=%016" PRIx64
+ " r7=%016" PRIx64 " r8=%016" PRIx64 " r9=%016" PRIx64
+ " r10=%016" PRIx64 " r11=%016" PRIx64 " r12=%016" PRIx64
" nip=" TARGET_FMT_lx "\n",
ppc_dump_gpr(env, 3), ppc_dump_gpr(env, 4),
- ppc_dump_gpr(env, 5), ppc_dump_gpr(env, 6),
- ppc_dump_gpr(env, 7), ppc_dump_gpr(env, 8),
- ppc_dump_gpr(env, 9), ppc_dump_gpr(env, 10),
- ppc_dump_gpr(env, 11), ppc_dump_gpr(env, 12),
- env->nip);
+ ppc_dump_gpr(env, 5), ppc_dump_gpr(env, 6),
+ ppc_dump_gpr(env, 7), ppc_dump_gpr(env, 8),
+ ppc_dump_gpr(env, 9), ppc_dump_gpr(env, 10),
+ ppc_dump_gpr(env, 11), ppc_dump_gpr(env, 12),
+ env->nip);
}
static int powerpc_reset_wakeup(CPUState *cs, CPUPPCState *env, int excp,
@@ -89,7 +101,7 @@
env->resume_as_sreset = false;
/* Pretend to be returning from doze always as we don't lose state */
- *msr |= (0x1ull << (63 - 47));
+ *msr |= SRR1_WS_NOLOSS;
/* Machine checks are sent normally */
if (excp == POWERPC_EXCP_MCHECK) {
@@ -97,25 +109,25 @@
}
switch (excp) {
case POWERPC_EXCP_RESET:
- *msr |= 0x4ull << (63 - 45);
+ *msr |= SRR1_WAKERESET;
break;
case POWERPC_EXCP_EXTERNAL:
- *msr |= 0x8ull << (63 - 45);
+ *msr |= SRR1_WAKEEE;
break;
case POWERPC_EXCP_DECR:
- *msr |= 0x6ull << (63 - 45);
+ *msr |= SRR1_WAKEDEC;
break;
case POWERPC_EXCP_SDOOR:
- *msr |= 0x5ull << (63 - 45);
+ *msr |= SRR1_WAKEDBELL;
break;
case POWERPC_EXCP_SDOOR_HV:
- *msr |= 0x3ull << (63 - 45);
+ *msr |= SRR1_WAKEHDBELL;
break;
case POWERPC_EXCP_HV_MAINT:
- *msr |= 0xaull << (63 - 45);
+ *msr |= SRR1_WAKEHMI;
break;
case POWERPC_EXCP_HVIRT:
- *msr |= 0x9ull << (63 - 45);
+ *msr |= SRR1_WAKEHVI;
break;
default:
cpu_abort(cs, "Unsupported exception %d in Power Save mode\n",
@@ -185,7 +197,7 @@
CPUState *cs = CPU(cpu);
CPUPPCState *env = &cpu->env;
target_ulong msr, new_msr, vector;
- int srr0, srr1, asrr0, asrr1, lev, ail;
+ int srr0, srr1, asrr0, asrr1, lev = -1, ail;
bool lpes0;
qemu_log_mask(CPU_LOG_INT, "Raise exception at " TARGET_FMT_lx
@@ -421,6 +433,13 @@
new_msr |= (target_ulong)MSR_HVB;
}
break;
+ case POWERPC_EXCP_SYSCALL_VECTORED: /* scv exception */
+ lev = env->error_code;
+ dump_syscall_vectored(env);
+ env->nip += 4;
+ new_msr |= env->msr & ((target_ulong)1 << MSR_EE);
+ new_msr |= env->msr & ((target_ulong)1 << MSR_RI);
+ break;
case POWERPC_EXCP_FPU: /* Floating-point unavailable exception */
case POWERPC_EXCP_APU: /* Auxiliary processor unavailable */
case POWERPC_EXCP_DECR: /* Decrementer exception */
@@ -724,12 +743,6 @@
break;
}
- /* Save PC */
- env->spr[srr0] = env->nip;
-
- /* Save MSR */
- env->spr[srr1] = msr;
-
/* Sanity check */
if (!(env->msr_mask & MSR_HVB)) {
if (new_msr & MSR_HVB) {
@@ -742,14 +755,6 @@
}
}
- /* If any alternate SRR register are defined, duplicate saved values */
- if (asrr0 != -1) {
- env->spr[asrr0] = env->spr[srr0];
- }
- if (asrr1 != -1) {
- env->spr[asrr1] = env->spr[srr1];
- }
-
/*
* Sort out endianness of interrupt, this differs depending on the
* CPU, the HV mode, etc...
@@ -784,14 +789,6 @@
}
#endif
- /* Jump to handler */
- vector = env->excp_vectors[excp];
- if (vector == (target_ulong)-1ULL) {
- cpu_abort(cs, "Raised an exception without defined vector %d\n",
- excp);
- }
- vector |= env->excp_prefix;
-
/*
* AIL only works if there is no HV transition and we are running
* with translations enabled
@@ -800,10 +797,21 @@
((new_msr & MSR_HVB) && !(msr & MSR_HVB))) {
ail = 0;
}
- /* Handle AIL */
- if (ail) {
- new_msr |= (1 << MSR_IR) | (1 << MSR_DR);
- vector |= ppc_excp_vector_offset(cs, ail);
+
+ vector = env->excp_vectors[excp];
+ if (vector == (target_ulong)-1ULL) {
+ cpu_abort(cs, "Raised an exception without defined vector %d\n",
+ excp);
+ }
+
+ vector |= env->excp_prefix;
+
+ /* If any alternate SRR register are defined, duplicate saved values */
+ if (asrr0 != -1) {
+ env->spr[asrr0] = env->nip;
+ }
+ if (asrr1 != -1) {
+ env->spr[asrr1] = msr;
}
#if defined(TARGET_PPC64)
@@ -823,6 +831,37 @@
}
#endif
+ if (excp != POWERPC_EXCP_SYSCALL_VECTORED) {
+ /* Save PC */
+ env->spr[srr0] = env->nip;
+
+ /* Save MSR */
+ env->spr[srr1] = msr;
+
+ /* Handle AIL */
+ if (ail) {
+ new_msr |= (1 << MSR_IR) | (1 << MSR_DR);
+ vector |= ppc_excp_vector_offset(cs, ail);
+ }
+
+#if defined(TARGET_PPC64)
+ } else {
+ /* scv AIL is a little different */
+ if (ail) {
+ new_msr |= (1 << MSR_IR) | (1 << MSR_DR);
+ }
+ if (ail == AIL_C000_0000_0000_4000) {
+ vector |= 0xc000000000003000ull;
+ } else {
+ vector |= 0x0000000000017000ull;
+ }
+ vector += lev * 0x20;
+
+ env->lr = env->nip;
+ env->ctr = msr;
+#endif
+ }
+
powerpc_set_excp_state(cpu, vector, new_msr);
}
@@ -1160,6 +1199,11 @@
do_rfi(env, env->spr[SPR_SRR0], env->spr[SPR_SRR1]);
}
+void helper_rfscv(CPUPPCState *env)
+{
+ do_rfi(env, env->lr, env->ctr);
+}
+
void helper_hrfid(CPUPPCState *env)
{
do_rfi(env, env->spr[SPR_HSRR0], env->spr[SPR_HSRR1]);
diff --git a/target/ppc/helper.h b/target/ppc/helper.h
index a95c010..2dfa1c6 100644
--- a/target/ppc/helper.h
+++ b/target/ppc/helper.h
@@ -15,6 +15,7 @@
#if defined(TARGET_PPC64)
DEF_HELPER_2(pminsn, void, env, i32)
DEF_HELPER_1(rfid, void, env)
+DEF_HELPER_1(rfscv, void, env)
DEF_HELPER_1(hrfid, void, env)
DEF_HELPER_2(store_lpcr, void, env, tl)
DEF_HELPER_2(store_pcr, void, env, tl)
diff --git a/target/ppc/int_helper.c b/target/ppc/int_helper.c
index 6d238b9..be53cd6 100644
--- a/target/ppc/int_helper.c
+++ b/target/ppc/int_helper.c
@@ -770,8 +770,9 @@
\
for (i = 0; i < ARRAY_SIZE(r->f32); i++) { \
uint32_t result; \
- int rel = float32_compare_quiet(a->f32[i], b->f32[i], \
- &env->vec_status); \
+ FloatRelation rel = \
+ float32_compare_quiet(a->f32[i], b->f32[i], \
+ &env->vec_status); \
if (rel == float_relation_unordered) { \
result = 0; \
} else if (rel compare order) { \
@@ -803,15 +804,15 @@
int all_in = 0;
for (i = 0; i < ARRAY_SIZE(r->f32); i++) {
- int le_rel = float32_compare_quiet(a->f32[i], b->f32[i],
- &env->vec_status);
+ FloatRelation le_rel = float32_compare_quiet(a->f32[i], b->f32[i],
+ &env->vec_status);
if (le_rel == float_relation_unordered) {
r->u32[i] = 0xc0000000;
all_in = 1;
} else {
float32 bneg = float32_chs(b->f32[i]);
- int ge_rel = float32_compare_quiet(a->f32[i], bneg,
- &env->vec_status);
+ FloatRelation ge_rel = float32_compare_quiet(a->f32[i], bneg,
+ &env->vec_status);
int le = le_rel != float_relation_greater;
int ge = ge_rel != float_relation_less;
diff --git a/target/ppc/mmu-radix64.c b/target/ppc/mmu-radix64.c
index 1404e53..c60bf31 100644
--- a/target/ppc/mmu-radix64.c
+++ b/target/ppc/mmu-radix64.c
@@ -28,7 +28,8 @@
#include "mmu-radix64.h"
#include "mmu-book3s-v3.h"
-static bool ppc_radix64_get_fully_qualified_addr(CPUPPCState *env, vaddr eaddr,
+static bool ppc_radix64_get_fully_qualified_addr(const CPUPPCState *env,
+ vaddr eaddr,
uint64_t *lpid, uint64_t *pid)
{
if (msr_hv) { /* MSR[HV] -> Hypervisor/bare metal */
@@ -49,6 +50,8 @@
*lpid = 0;
*pid = 0;
break;
+ default:
+ g_assert_not_reached();
}
} else { /* !MSR[HV] -> Guest */
switch (eaddr & R_EADDR_QUADRANT) {
@@ -63,6 +66,8 @@
*lpid = env->spr[SPR_LPIDR];
*pid = 0; /* pid set to 0 -> addresses guest operating system */
break;
+ default:
+ g_assert_not_reached();
}
}
@@ -269,7 +274,7 @@
ppc_v3_pate_t pate,
hwaddr *h_raddr, int *h_prot,
int *h_page_size, bool pde_addr,
- bool cause_excp)
+ bool guest_visible)
{
int fault_cause = 0;
hwaddr pte_addr;
@@ -281,16 +286,18 @@
pate.dw0 & PRTBE_R_RPDS, h_raddr, h_page_size,
&pte, &fault_cause, &pte_addr) ||
ppc_radix64_check_prot(cpu, rwx, pte, &fault_cause, h_prot, true)) {
- if (pde_addr) /* address being translated was that of a guest pde */
+ if (pde_addr) { /* address being translated was that of a guest pde */
fault_cause |= DSISR_PRTABLE_FAULT;
- if (cause_excp) {
+ }
+ if (guest_visible) {
ppc_radix64_raise_hsi(cpu, rwx, eaddr, g_raddr, fault_cause);
}
return 1;
}
- /* Update Reference and Change Bits */
- ppc_radix64_set_rc(cpu, rwx, pte, pte_addr, h_prot);
+ if (guest_visible) {
+ ppc_radix64_set_rc(cpu, rwx, pte, pte_addr, h_prot);
+ }
return 0;
}
@@ -299,7 +306,7 @@
vaddr eaddr, uint64_t pid,
ppc_v3_pate_t pate, hwaddr *g_raddr,
int *g_prot, int *g_page_size,
- bool cause_excp)
+ bool guest_visible)
{
CPUState *cs = CPU(cpu);
CPUPPCState *env = &cpu->env;
@@ -313,7 +320,7 @@
size = 1ULL << ((pate.dw1 & PATE1_R_PRTS) + 12);
if (offset >= size) {
/* offset exceeds size of the process table */
- if (cause_excp) {
+ if (guest_visible) {
ppc_radix64_raise_si(cpu, rwx, eaddr, DSISR_NOPTE);
}
return 1;
@@ -333,7 +340,8 @@
*/
ret = ppc_radix64_partition_scoped_xlate(cpu, 0, eaddr, prtbe_addr,
pate, &h_raddr, &h_prot,
- &h_page_size, 1, 1);
+ &h_page_size, true,
+ guest_visible);
if (ret) {
return ret;
}
@@ -353,7 +361,7 @@
&fault_cause, &pte_addr);
if (ret) {
/* No valid PTE */
- if (cause_excp) {
+ if (guest_visible) {
ppc_radix64_raise_si(cpu, rwx, eaddr, fault_cause);
}
return ret;
@@ -372,7 +380,8 @@
do {
ret = ppc_radix64_partition_scoped_xlate(cpu, 0, eaddr, pte_addr,
pate, &h_raddr, &h_prot,
- &h_page_size, 1, 1);
+ &h_page_size, true,
+ guest_visible);
if (ret) {
return ret;
}
@@ -381,7 +390,7 @@
&nls, g_page_size, &pte, &fault_cause);
if (ret) {
/* No valid pte */
- if (cause_excp) {
+ if (guest_visible) {
ppc_radix64_raise_si(cpu, rwx, eaddr, fault_cause);
}
return ret;
@@ -398,13 +407,15 @@
if (ppc_radix64_check_prot(cpu, rwx, pte, &fault_cause, g_prot, false)) {
/* Access denied due to protection */
- if (cause_excp) {
+ if (guest_visible) {
ppc_radix64_raise_si(cpu, rwx, eaddr, fault_cause);
}
return 1;
}
- ppc_radix64_set_rc(cpu, rwx, pte, pte_addr, g_prot);
+ if (guest_visible) {
+ ppc_radix64_set_rc(cpu, rwx, pte, pte_addr, g_prot);
+ }
return 0;
}
@@ -429,17 +440,17 @@
static int ppc_radix64_xlate(PowerPCCPU *cpu, vaddr eaddr, int rwx,
bool relocation,
hwaddr *raddr, int *psizep, int *protp,
- bool cause_excp)
+ bool guest_visible)
{
CPUPPCState *env = &cpu->env;
- uint64_t lpid = 0, pid = 0;
+ uint64_t lpid, pid;
ppc_v3_pate_t pate;
int psize, prot;
hwaddr g_raddr;
/* Virtual Mode Access - get the fully qualified address */
if (!ppc_radix64_get_fully_qualified_addr(&cpu->env, eaddr, &lpid, &pid)) {
- if (cause_excp) {
+ if (guest_visible) {
ppc_radix64_raise_segi(cpu, rwx, eaddr);
}
return 1;
@@ -452,13 +463,13 @@
vhc->get_pate(cpu->vhyp, &pate);
} else {
if (!ppc64_v3_get_pate(cpu, lpid, &pate)) {
- if (cause_excp) {
+ if (guest_visible) {
ppc_radix64_raise_si(cpu, rwx, eaddr, DSISR_NOPTE);
}
return 1;
}
if (!validate_pate(cpu, lpid, &pate)) {
- if (cause_excp) {
+ if (guest_visible) {
ppc_radix64_raise_si(cpu, rwx, eaddr, DSISR_R_BADCONFIG);
}
return 1;
@@ -479,7 +490,7 @@
if (relocation) {
int ret = ppc_radix64_process_scoped_xlate(cpu, rwx, eaddr, pid,
pate, &g_raddr, &prot,
- &psize, cause_excp);
+ &psize, guest_visible);
if (ret) {
return ret;
}
@@ -502,7 +513,7 @@
ret = ppc_radix64_partition_scoped_xlate(cpu, rwx, eaddr, g_raddr,
pate, raddr, &prot, &psize,
- 0, cause_excp);
+ false, guest_visible);
if (ret) {
return ret;
}
diff --git a/target/ppc/mmu-radix64.h b/target/ppc/mmu-radix64.h
index 9622854..f28c579 100644
--- a/target/ppc/mmu-radix64.h
+++ b/target/ppc/mmu-radix64.h
@@ -55,9 +55,9 @@
(pte & R_PTE_EAA_X ? PAGE_EXEC : 0);
}
-static inline int ppc_radix64_get_prot_amr(PowerPCCPU *cpu)
+static inline int ppc_radix64_get_prot_amr(const PowerPCCPU *cpu)
{
- CPUPPCState *env = &cpu->env;
+ const CPUPPCState *env = &cpu->env;
int amr = env->spr[SPR_AMR] >> 62; /* We only care about key0 AMR63:62 */
int iamr = env->spr[SPR_IAMR] >> 62; /* We only care about key0 IAMR63:62 */
diff --git a/target/ppc/mmu_helper.c b/target/ppc/mmu_helper.c
index 86c667b..8972714 100644
--- a/target/ppc/mmu_helper.c
+++ b/target/ppc/mmu_helper.c
@@ -1820,7 +1820,7 @@
if (((end - base) >> TARGET_PAGE_BITS) > 1024) {
/* Flushing 1024 4K pages is slower than a complete flush */
LOG_BATS("Flush all BATs\n");
- tlb_flush(CPU(cs));
+ tlb_flush(cs);
LOG_BATS("Flush done\n");
return;
}
diff --git a/target/ppc/translate.c b/target/ppc/translate.c
index 3385298..4ce3d66 100644
--- a/target/ppc/translate.c
+++ b/target/ppc/translate.c
@@ -173,6 +173,7 @@
bool vsx_enabled;
bool spe_enabled;
bool tm_enabled;
+ bool scv_enabled;
bool gtse;
ppc_spr_t *spr_cb; /* Needed to check rights for mfspr/mtspr */
int singlestep_enabled;
@@ -4030,6 +4031,24 @@
#endif
}
+#if !defined(CONFIG_USER_ONLY)
+static void gen_rfscv(DisasContext *ctx)
+{
+#if defined(CONFIG_USER_ONLY)
+ GEN_PRIV;
+#else
+ /* Restore CPU state */
+ CHK_SV;
+ if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
+ gen_io_start();
+ }
+ gen_update_cfar(ctx, ctx->base.pc_next - 4);
+ gen_helper_rfscv(cpu_env);
+ gen_sync_exception(ctx);
+#endif
+}
+#endif
+
static void gen_hrfid(DisasContext *ctx)
{
#if defined(CONFIG_USER_ONLY)
@@ -4048,6 +4067,7 @@
#define POWERPC_SYSCALL POWERPC_EXCP_SYSCALL_USER
#else
#define POWERPC_SYSCALL POWERPC_EXCP_SYSCALL
+#define POWERPC_SYSCALL_VECTORED POWERPC_EXCP_SYSCALL_VECTORED
#endif
static void gen_sc(DisasContext *ctx)
{
@@ -4057,6 +4077,23 @@
gen_exception_err(ctx, POWERPC_SYSCALL, lev);
}
+#if defined(TARGET_PPC64)
+#if !defined(CONFIG_USER_ONLY)
+static void gen_scv(DisasContext *ctx)
+{
+ uint32_t lev;
+
+ if (unlikely(!ctx->scv_enabled)) {
+ gen_exception_err(ctx, POWERPC_EXCP_FU, FSCR_IC_SCV);
+ return;
+ }
+
+ lev = (ctx->opcode >> 5) & 0x7F;
+ gen_exception_err(ctx, POWERPC_SYSCALL_VECTORED, lev);
+}
+#endif
+#endif
+
/*** Trap ***/
/* Check for unconditional traps (always or never) */
@@ -7049,6 +7086,12 @@
GEN_HANDLER(rfi, 0x13, 0x12, 0x01, 0x03FF8001, PPC_FLOW),
#if defined(TARGET_PPC64)
GEN_HANDLER(rfid, 0x13, 0x12, 0x00, 0x03FF8001, PPC_64B),
+#if !defined(CONFIG_USER_ONLY)
+/* Top bit of opc2 corresponds with low bit of LEV, so use two handlers */
+GEN_HANDLER_E(scv, 0x11, 0x10, 0xFF, 0x03FFF01E, PPC_NONE, PPC2_ISA300),
+GEN_HANDLER_E(scv, 0x11, 0x00, 0xFF, 0x03FFF01E, PPC_NONE, PPC2_ISA300),
+GEN_HANDLER_E(rfscv, 0x13, 0x12, 0x02, 0x03FF8001, PPC_NONE, PPC2_ISA300),
+#endif
GEN_HANDLER_E(stop, 0x13, 0x12, 0x0b, 0x03FFF801, PPC_NONE, PPC2_ISA300),
GEN_HANDLER_E(doze, 0x13, 0x12, 0x0c, 0x03FFF801, PPC_NONE, PPC2_PM_ISA206),
GEN_HANDLER_E(nap, 0x13, 0x12, 0x0d, 0x03FFF801, PPC_NONE, PPC2_PM_ISA206),
@@ -7056,7 +7099,9 @@
GEN_HANDLER_E(rvwinkle, 0x13, 0x12, 0x0f, 0x03FFF801, PPC_NONE, PPC2_PM_ISA206),
GEN_HANDLER(hrfid, 0x13, 0x12, 0x08, 0x03FF8001, PPC_64H),
#endif
-GEN_HANDLER(sc, 0x11, 0xFF, 0xFF, 0x03FFF01D, PPC_FLOW),
+/* Top bit of opc2 corresponds with low bit of LEV, so use two handlers */
+GEN_HANDLER(sc, 0x11, 0x11, 0xFF, 0x03FFF01D, PPC_FLOW),
+GEN_HANDLER(sc, 0x11, 0x01, 0xFF, 0x03FFF01D, PPC_FLOW),
GEN_HANDLER(tw, 0x1F, 0x04, 0x00, 0x00000001, PPC_FLOW),
GEN_HANDLER(twi, 0x03, 0xFF, 0xFF, 0x00000000, PPC_FLOW),
#if defined(TARGET_PPC64)
@@ -7835,6 +7880,12 @@
} else {
ctx->vsx_enabled = false;
}
+ if ((env->flags & POWERPC_FLAG_SCV)
+ && (env->spr[SPR_FSCR] & (1ull << FSCR_SCV))) {
+ ctx->scv_enabled = true;
+ } else {
+ ctx->scv_enabled = false;
+ }
#if defined(TARGET_PPC64)
if ((env->flags & POWERPC_FLAG_TM) && msr_tm) {
ctx->tm_enabled = !!msr_tm;
diff --git a/target/ppc/translate_init.inc.c b/target/ppc/translate_init.inc.c
index 2b6e832..38cb773 100644
--- a/target/ppc/translate_init.inc.c
+++ b/target/ppc/translate_init.inc.c
@@ -3382,6 +3382,7 @@
#if !defined(CONFIG_USER_ONLY)
env->excp_vectors[POWERPC_EXCP_HVIRT] = 0x00000EA0;
+ env->excp_vectors[POWERPC_EXCP_SYSCALL_VECTORED] = 0x00000000;
#endif
}
@@ -9030,7 +9031,7 @@
pcc->flags = POWERPC_FLAG_VRE | POWERPC_FLAG_SE |
POWERPC_FLAG_BE | POWERPC_FLAG_PMM |
POWERPC_FLAG_BUS_CLK | POWERPC_FLAG_CFAR |
- POWERPC_FLAG_VSX | POWERPC_FLAG_TM;
+ POWERPC_FLAG_VSX | POWERPC_FLAG_TM | POWERPC_FLAG_SCV;
pcc->l1_dcache_size = 0x8000;
pcc->l1_icache_size = 0x8000;
pcc->interrupts_big_endian = ppc_cpu_interrupts_big_endian_lpcr;
@@ -10293,19 +10294,14 @@
cpu_exec_unrealizefn(cs);
}
-static void ppc_cpu_unrealize(DeviceState *dev, Error **errp)
+static void ppc_cpu_unrealize(DeviceState *dev)
{
PowerPCCPU *cpu = POWERPC_CPU(dev);
PowerPCCPUClass *pcc = POWERPC_CPU_GET_CLASS(cpu);
- Error *local_err = NULL;
opc_handler_t **table, **table_2;
int i, j, k;
- pcc->parent_unrealize(dev, &local_err);
- if (local_err != NULL) {
- error_propagate(errp, local_err);
- return;
- }
+ pcc->parent_unrealize(dev);
for (i = 0; i < PPC_CPU_OPCODES_LEN; i++) {
if (cpu->opcodes[i] == &invalid_handler) {
diff --git a/target/s390x/cpu.c b/target/s390x/cpu.c
index f2ccf0a..ca50b70 100644
--- a/target/s390x/cpu.c
+++ b/target/s390x/cpu.c
@@ -296,7 +296,7 @@
cs->halted = 1;
cs->exception_index = EXCP_HLT;
object_property_add(obj, "crash-information", "GuestPanicInformation",
- s390_cpu_get_crash_info_qom, NULL, NULL, NULL, NULL);
+ s390_cpu_get_crash_info_qom, NULL, NULL, NULL);
s390_cpu_model_register_props(obj);
#if !defined(CONFIG_USER_ONLY)
cpu->env.tod_timer =
diff --git a/target/s390x/cpu_features_def.inc.h b/target/s390x/cpu_features_def.inc.h
index 60db283..5942f81 100644
--- a/target/s390x/cpu_features_def.inc.h
+++ b/target/s390x/cpu_features_def.inc.h
@@ -311,7 +311,7 @@
DEF_FEAT(PCC_CMAC_TDEA, "pcc-cmac-etdea-192", PCC, 11, "PCC Compute-Last-Block-CMAC-Using-EncryptedTDEA-192")
DEF_FEAT(PCC_CMAC_AES_128, "pcc-cmac-aes-128", PCC, 18, "PCC Compute-Last-Block-CMAC-Using-AES-128")
DEF_FEAT(PCC_CMAC_AES_192, "pcc-cmac-aes-192", PCC, 19, "PCC Compute-Last-Block-CMAC-Using-AES-192")
-DEF_FEAT(PCC_CMAC_AES_256, "pcc-cmac-eaes-256", PCC, 20, "PCC Compute-Last-Block-CMAC-Using-AES-256")
+DEF_FEAT(PCC_CMAC_AES_256, "pcc-cmac-aes-256", PCC, 20, "PCC Compute-Last-Block-CMAC-Using-AES-256")
DEF_FEAT(PCC_CMAC_EAES_128, "pcc-cmac-eaes-128", PCC, 26, "PCC Compute-Last-Block-CMAC-Using-Encrypted-AES-128")
DEF_FEAT(PCC_CMAC_EAES_192, "pcc-cmac-eaes-192", PCC, 27, "PCC Compute-Last-Block-CMAC-Using-Encrypted-AES-192")
DEF_FEAT(PCC_CMAC_EAES_256, "pcc-cmac-eaes-256", PCC, 28, "PCC Compute-Last-Block-CMAC-Using-Encrypted-AES-256")
diff --git a/target/s390x/cpu_models.c b/target/s390x/cpu_models.c
index 7c32180..2fa609b 100644
--- a/target/s390x/cpu_models.c
+++ b/target/s390x/cpu_models.c
@@ -524,7 +524,7 @@
}
}
if (!err) {
- visit_check_struct(visitor, errp);
+ visit_check_struct(visitor, &err);
}
visit_end_struct(visitor, NULL);
visit_free(visitor);
@@ -1106,14 +1106,14 @@
for (feat = 0; feat < S390_FEAT_MAX; feat++) {
const S390FeatDef *def = s390_feat_def(feat);
object_property_add(obj, def->name, "bool", get_feature,
- set_feature, NULL, (void *) feat, NULL);
- object_property_set_description(obj, def->name, def->desc , NULL);
+ set_feature, NULL, (void *) feat);
+ object_property_set_description(obj, def->name, def->desc);
}
for (group = 0; group < S390_FEAT_GROUP_MAX; group++) {
const S390FeatGroupDef *def = s390_feat_group_def(group);
object_property_add(obj, def->name, "bool", get_feature_group,
- set_feature_group, NULL, (void *) group, NULL);
- object_property_set_description(obj, def->name, def->desc , NULL);
+ set_feature_group, NULL, (void *) group);
+ object_property_set_description(obj, def->name, def->desc);
}
}
@@ -1225,11 +1225,10 @@
void s390_cpu_model_class_register_props(ObjectClass *oc)
{
object_class_property_add_bool(oc, "migration-safe", get_is_migration_safe,
- NULL, NULL);
+ NULL);
object_class_property_add_bool(oc, "static", get_is_static,
- NULL, NULL);
- object_class_property_add_str(oc, "description", get_description, NULL,
- NULL);
+ NULL);
+ object_class_property_add_str(oc, "description", get_description, NULL);
}
#ifdef CONFIG_KVM
diff --git a/target/s390x/fpu_helper.c b/target/s390x/fpu_helper.c
index 8bb9f54..f155bc0 100644
--- a/target/s390x/fpu_helper.c
+++ b/target/s390x/fpu_helper.c
@@ -112,7 +112,7 @@
}
}
-int float_comp_to_cc(CPUS390XState *env, int float_compare)
+int float_comp_to_cc(CPUS390XState *env, FloatRelation float_compare)
{
switch (float_compare) {
case float_relation_equal:
@@ -368,7 +368,7 @@
/* 32-bit FP compare */
uint32_t HELPER(ceb)(CPUS390XState *env, uint64_t f1, uint64_t f2)
{
- int cmp = float32_compare_quiet(f1, f2, &env->fpu_status);
+ FloatRelation cmp = float32_compare_quiet(f1, f2, &env->fpu_status);
handle_exceptions(env, false, GETPC());
return float_comp_to_cc(env, cmp);
}
@@ -376,7 +376,7 @@
/* 64-bit FP compare */
uint32_t HELPER(cdb)(CPUS390XState *env, uint64_t f1, uint64_t f2)
{
- int cmp = float64_compare_quiet(f1, f2, &env->fpu_status);
+ FloatRelation cmp = float64_compare_quiet(f1, f2, &env->fpu_status);
handle_exceptions(env, false, GETPC());
return float_comp_to_cc(env, cmp);
}
@@ -385,9 +385,9 @@
uint32_t HELPER(cxb)(CPUS390XState *env, uint64_t ah, uint64_t al,
uint64_t bh, uint64_t bl)
{
- int cmp = float128_compare_quiet(make_float128(ah, al),
- make_float128(bh, bl),
- &env->fpu_status);
+ FloatRelation cmp = float128_compare_quiet(make_float128(ah, al),
+ make_float128(bh, bl),
+ &env->fpu_status);
handle_exceptions(env, false, GETPC());
return float_comp_to_cc(env, cmp);
}
@@ -675,7 +675,7 @@
/* 32-bit FP compare and signal */
uint32_t HELPER(keb)(CPUS390XState *env, uint64_t f1, uint64_t f2)
{
- int cmp = float32_compare(f1, f2, &env->fpu_status);
+ FloatRelation cmp = float32_compare(f1, f2, &env->fpu_status);
handle_exceptions(env, false, GETPC());
return float_comp_to_cc(env, cmp);
}
@@ -683,7 +683,7 @@
/* 64-bit FP compare and signal */
uint32_t HELPER(kdb)(CPUS390XState *env, uint64_t f1, uint64_t f2)
{
- int cmp = float64_compare(f1, f2, &env->fpu_status);
+ FloatRelation cmp = float64_compare(f1, f2, &env->fpu_status);
handle_exceptions(env, false, GETPC());
return float_comp_to_cc(env, cmp);
}
@@ -692,9 +692,9 @@
uint32_t HELPER(kxb)(CPUS390XState *env, uint64_t ah, uint64_t al,
uint64_t bh, uint64_t bl)
{
- int cmp = float128_compare(make_float128(ah, al),
- make_float128(bh, bl),
- &env->fpu_status);
+ FloatRelation cmp = float128_compare(make_float128(ah, al),
+ make_float128(bh, bl),
+ &env->fpu_status);
handle_exceptions(env, false, GETPC());
return float_comp_to_cc(env, cmp);
}
diff --git a/target/s390x/vec_fpu_helper.c b/target/s390x/vec_fpu_helper.c
index a48bd70..c1564e8 100644
--- a/target/s390x/vec_fpu_helper.c
+++ b/target/s390x/vec_fpu_helper.c
@@ -174,7 +174,7 @@
env->cc_op = wfc64(v1, v2, env, true, GETPC());
}
-typedef int (*vfc64_fn)(float64 a, float64 b, float_status *status);
+typedef bool (*vfc64_fn)(float64 a, float64 b, float_status *status);
static int vfc64(S390Vector *v1, const S390Vector *v2, const S390Vector *v3,
CPUS390XState *env, bool s, vfc64_fn fn, uintptr_t retaddr)
{
diff --git a/target/sparc/fop_helper.c b/target/sparc/fop_helper.c
index 9eb9b75..e6dd3fc 100644
--- a/target/sparc/fop_helper.c
+++ b/target/sparc/fop_helper.c
@@ -264,7 +264,7 @@
#define GEN_FCMP(name, size, reg1, reg2, FS, E) \
target_ulong glue(helper_, name) (CPUSPARCState *env) \
{ \
- int ret; \
+ FloatRelation ret; \
target_ulong fsr; \
if (E) { \
ret = glue(size, _compare)(reg1, reg2, &env->fp_status); \
@@ -295,7 +295,7 @@
#define GEN_FCMP_T(name, size, FS, E) \
target_ulong glue(helper_, name)(CPUSPARCState *env, size src1, size src2)\
{ \
- int ret; \
+ FloatRelation ret; \
target_ulong fsr; \
if (E) { \
ret = glue(size, _compare)(src1, src2, &env->fp_status); \
diff --git a/target/tricore/Makefile.objs b/target/tricore/Makefile.objs
index 7a05670..281b55f 100644
--- a/target/tricore/Makefile.objs
+++ b/target/tricore/Makefile.objs
@@ -1 +1 @@
-obj-y += translate.o helper.o cpu.o op_helper.o fpu_helper.o
+obj-y += translate.o helper.o cpu.o op_helper.o fpu_helper.o gdbstub.o
diff --git a/target/tricore/cpu.c b/target/tricore/cpu.c
index 743b404..2f2e5b0 100644
--- a/target/tricore/cpu.c
+++ b/target/tricore/cpu.c
@@ -23,19 +23,16 @@
#include "exec/exec-all.h"
#include "qemu/error-report.h"
-static hwaddr tricore_cpu_get_phys_page_attrs_debug(CPUState *cpu, vaddr addr,
- MemTxAttrs *attrs)
-{
- error_report("function cpu_get_phys_page_attrs_debug not "
- "implemented, aborting");
- return -1;
-}
-
static inline void set_feature(CPUTriCoreState *env, int feature)
{
env->features |= 1ULL << feature;
}
+static gchar *tricore_gdb_arch_name(CPUState *cs)
+{
+ return g_strdup("tricore");
+}
+
static void tricore_cpu_set_pc(CPUState *cs, vaddr value)
{
TriCoreCPU *cpu = TRICORE_CPU(cs);
@@ -158,10 +155,15 @@
cc->class_by_name = tricore_cpu_class_by_name;
cc->has_work = tricore_cpu_has_work;
+ cc->gdb_read_register = tricore_cpu_gdb_read_register;
+ cc->gdb_write_register = tricore_cpu_gdb_write_register;
+ cc->gdb_num_core_regs = 44;
+ cc->gdb_arch_name = tricore_gdb_arch_name;
+
cc->dump_state = tricore_cpu_dump_state;
cc->set_pc = tricore_cpu_set_pc;
cc->synchronize_from_tb = tricore_cpu_synchronize_from_tb;
- cc->get_phys_page_attrs_debug = tricore_cpu_get_phys_page_attrs_debug;
+ cc->get_phys_page_debug = tricore_cpu_get_phys_page_debug;
cc->tcg_initialize = tricore_tcg_init;
cc->tlb_fill = tricore_cpu_tlb_fill;
}
diff --git a/target/tricore/cpu.h b/target/tricore/cpu.h
index 8c014fa..b82349d 100644
--- a/target/tricore/cpu.h
+++ b/target/tricore/cpu.h
@@ -353,6 +353,8 @@
uint32_t psw_read(CPUTriCoreState *env);
void psw_write(CPUTriCoreState *env, uint32_t val);
+int tricore_cpu_gdb_read_register(CPUState *cs, GByteArray *mem_buf, int n);
+int tricore_cpu_gdb_write_register(CPUState *cs, uint8_t *mem_buf, int n);
void fpu_set_state(CPUTriCoreState *env);
diff --git a/target/tricore/gdbstub.c b/target/tricore/gdbstub.c
new file mode 100644
index 0000000..0f4e612
--- /dev/null
+++ b/target/tricore/gdbstub.c
@@ -0,0 +1,139 @@
+/*
+ * TriCore gdb server stub
+ *
+ * Copyright (c) 2019 Bastian Koppelmann, Paderborn University
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "qemu/osdep.h"
+#include "qemu-common.h"
+#include "exec/gdbstub.h"
+
+
+#define LCX_REGNUM 32
+#define FCX_REGNUM 33
+#define PCXI_REGNUM 34
+#define TRICORE_PSW_REGNUM 35
+#define TRICORE_PC_REGNUM 36
+#define ICR_REGNUM 37
+#define ISP_REGNUM 38
+#define BTV_REGNUM 39
+#define BIV_REGNUM 40
+#define SYSCON_REGNUM 41
+#define PMUCON0_REGNUM 42
+#define DMUCON_REGNUM 43
+
+static uint32_t tricore_cpu_gdb_read_csfr(CPUTriCoreState *env, int n)
+{
+ switch (n) {
+ case LCX_REGNUM:
+ return env->LCX;
+ case FCX_REGNUM:
+ return env->FCX;
+ case PCXI_REGNUM:
+ return env->PCXI;
+ case TRICORE_PSW_REGNUM:
+ return psw_read(env);
+ case TRICORE_PC_REGNUM:
+ return env->PC;
+ case ICR_REGNUM:
+ return env->ICR;
+ case ISP_REGNUM:
+ return env->ISP;
+ case BTV_REGNUM:
+ return env->BTV;
+ case BIV_REGNUM:
+ return env->BIV;
+ case SYSCON_REGNUM:
+ return env->SYSCON;
+ case PMUCON0_REGNUM:
+ return 0; /* PMUCON0 */
+ case DMUCON_REGNUM:
+ return 0; /* DMUCON0 */
+ default:
+ return 0;
+ }
+}
+
+static void tricore_cpu_gdb_write_csfr(CPUTriCoreState *env, int n,
+ uint32_t val)
+{
+ switch (n) {
+ case LCX_REGNUM:
+ env->LCX = val;
+ break;
+ case FCX_REGNUM:
+ env->FCX = val;
+ break;
+ case PCXI_REGNUM:
+ env->PCXI = val;
+ break;
+ case TRICORE_PSW_REGNUM:
+ psw_write(env, val);
+ break;
+ case TRICORE_PC_REGNUM:
+ env->PC = val;
+ break;
+ case ICR_REGNUM:
+ env->ICR = val;
+ break;
+ case ISP_REGNUM:
+ env->ISP = val;
+ break;
+ case BTV_REGNUM:
+ env->BTV = val;
+ break;
+ case BIV_REGNUM:
+ env->BIV = val;
+ break;
+ case SYSCON_REGNUM:
+ env->SYSCON = val;
+ break;
+ }
+}
+
+
+int tricore_cpu_gdb_read_register(CPUState *cs, GByteArray *mem_buf, int n)
+{
+ TriCoreCPU *cpu = TRICORE_CPU(cs);
+ CPUTriCoreState *env = &cpu->env;
+
+ if (n < 16) { /* data registers */
+ return gdb_get_reg32(mem_buf, env->gpr_d[n]);
+ } else if (n < 32) { /* address registers */
+ return gdb_get_reg32(mem_buf, env->gpr_a[n - 16]);
+ } else { /* csfr */
+ return gdb_get_reg32(mem_buf, tricore_cpu_gdb_read_csfr(env, n));
+ }
+ return 0;
+}
+
+int tricore_cpu_gdb_write_register(CPUState *cs, uint8_t *mem_buf, int n)
+{
+ TriCoreCPU *cpu = TRICORE_CPU(cs);
+ CPUTriCoreState *env = &cpu->env;
+ uint32_t tmp;
+
+ tmp = ldl_p(mem_buf);
+
+ if (n < 16) { /* data registers */
+ env->gpr_d[n] = tmp;
+ } else if (n < 32) { /* address registers */
+ env->gpr_d[n - 16] = tmp;
+ } else {
+ tricore_cpu_gdb_write_csfr(env, n, tmp);
+ }
+ return 4;
+}
diff --git a/target/tricore/helper.c b/target/tricore/helper.c
index d5db7b2..7715293 100644
--- a/target/tricore/helper.c
+++ b/target/tricore/helper.c
@@ -42,6 +42,19 @@
return ret;
}
+
+hwaddr tricore_cpu_get_phys_page_debug(CPUState *cs, vaddr addr)
+{
+ TriCoreCPU *cpu = TRICORE_CPU(cs);
+ hwaddr phys_addr;
+ int prot;
+ int mmu_idx = cpu_mmu_index(&cpu->env, false);
+
+ if (get_physical_address(&cpu->env, &phys_addr, &prot, addr, 0, mmu_idx)) {
+ return -1;
+ }
+ return phys_addr;
+}
#endif
/* TODO: Add exeption support*/
diff --git a/target/tricore/translate.c b/target/tricore/translate.c
index 609d75a..7752630 100644
--- a/target/tricore/translate.c
+++ b/target/tricore/translate.c
@@ -66,14 +66,19 @@
typedef struct DisasContext {
DisasContextBase base;
- CPUTriCoreState *env;
target_ulong pc_succ_insn;
uint32_t opcode;
/* Routine used to access memory */
int mem_idx;
uint32_t hflags, saved_hflags;
+ uint64_t features;
} DisasContext;
+static int has_feature(DisasContext *ctx, int feature)
+{
+ return (ctx->features & (1ULL << feature)) != 0;
+}
+
enum {
MODE_LL = 0,
MODE_LU = 1,
@@ -370,7 +375,7 @@
These makros also specify in which ISA version the csfr was introduced. */
#define R(ADDRESS, REG, FEATURE) \
case ADDRESS: \
- if (tricore_feature(ctx->env, FEATURE)) { \
+ if (has_feature(ctx, FEATURE)) { \
tcg_gen_ld_tl(ret, cpu_env, offsetof(CPUTriCoreState, REG)); \
} \
break;
@@ -395,7 +400,7 @@
since no execption occurs */
#define A(ADDRESS, REG, FEATURE) R(ADDRESS, REG, FEATURE) \
case ADDRESS: \
- if (tricore_feature(ctx->env, FEATURE)) { \
+ if (has_feature(ctx, FEATURE)) { \
tcg_gen_st_tl(r1, cpu_env, offsetof(CPUTriCoreState, REG)); \
} \
break;
@@ -3158,7 +3163,7 @@
{
TCGv_i64 ret = tcg_temp_new_i64();
- if (!tricore_feature(ctx->env, TRICORE_FEATURE_131)) {
+ if (!has_feature(ctx, TRICORE_FEATURE_131)) {
gen_helper_dvinit_b_13(ret, cpu_env, r1, r2);
} else {
gen_helper_dvinit_b_131(ret, cpu_env, r1, r2);
@@ -3173,7 +3178,7 @@
{
TCGv_i64 ret = tcg_temp_new_i64();
- if (!tricore_feature(ctx->env, TRICORE_FEATURE_131)) {
+ if (!has_feature(ctx, TRICORE_FEATURE_131)) {
gen_helper_dvinit_h_13(ret, cpu_env, r1, r2);
} else {
gen_helper_dvinit_h_131(ret, cpu_env, r1, r2);
@@ -3233,6 +3238,14 @@
#endif
}
+static void generate_qemu_excp(DisasContext *ctx, int excp)
+{
+ TCGv_i32 tmp = tcg_const_i32(excp);
+ gen_helper_qemu_excp(cpu_env, tmp);
+ ctx->base.is_jmp = DISAS_NORETURN;
+ tcg_temp_free(tmp);
+}
+
static inline void gen_goto_tb(DisasContext *ctx, int n, target_ulong dest)
{
if (use_goto_tb(ctx, dest)) {
@@ -3242,7 +3255,7 @@
} else {
gen_save_pc(dest);
if (ctx->base.singlestep_enabled) {
- /* raise exception debug */
+ generate_qemu_excp(ctx, EXCP_DEBUG);
}
tcg_gen_exit_tb(NULL, 0);
}
@@ -3261,15 +3274,6 @@
tcg_temp_free(tintemp);
}
-static void generate_qemu_excp(DisasContext *ctx, int excp)
-{
- TCGv_i32 tmp = tcg_const_i32(excp);
- gen_save_pc(ctx->base.pc_next);
- gen_helper_qemu_excp(cpu_env, tmp);
- ctx->base.is_jmp = DISAS_NORETURN;
- tcg_temp_free(tmp);
-}
-
static inline void gen_branch_cond(DisasContext *ctx, TCGCond cond, TCGv r1,
TCGv r2, int16_t address)
{
@@ -3656,7 +3660,7 @@
tcg_gen_movi_tl(cpu_gpr_a[r1], const4);
break;
case OPC1_16_SRC_MOV_E:
- if (tricore_feature(ctx->env, TRICORE_FEATURE_16)) {
+ if (has_feature(ctx, TRICORE_FEATURE_16)) {
tcg_gen_movi_tl(cpu_gpr_d[r1], const4);
tcg_gen_sari_tl(cpu_gpr_d[r1+1], cpu_gpr_d[r1], 31);
} else {
@@ -4107,7 +4111,7 @@
break;
case OPC1_16_SBC_JEQ2:
case OPC1_16_SBC_JNE2:
- if (tricore_feature(ctx->env, TRICORE_FEATURE_16)) {
+ if (has_feature(ctx, TRICORE_FEATURE_16)) {
address = MASK_OP_SBC_DISP4(ctx->opcode);
const16 = MASK_OP_SBC_CONST4_SEXT(ctx->opcode);
gen_compute_branch(ctx, op1, 0, 0, const16, address);
@@ -4125,7 +4129,7 @@
/* SBR-format */
case OPC1_16_SBR_JEQ2:
case OPC1_16_SBR_JNE2:
- if (tricore_feature(ctx->env, TRICORE_FEATURE_16)) {
+ if (has_feature(ctx, TRICORE_FEATURE_16)) {
r1 = MASK_OP_SBR_S2(ctx->opcode);
address = MASK_OP_SBR_DISP4(ctx->opcode);
gen_compute_branch(ctx, op1, r1, 0, 0, address);
@@ -4705,13 +4709,13 @@
break;
case OPC2_32_BO_CACHEI_WI_SHORTOFF:
case OPC2_32_BO_CACHEI_W_SHORTOFF:
- if (!tricore_feature(ctx->env, TRICORE_FEATURE_131)) {
+ if (!has_feature(ctx, TRICORE_FEATURE_131)) {
generate_trap(ctx, TRAPC_INSN_ERR, TIN2_IOPC);
}
break;
case OPC2_32_BO_CACHEI_W_POSTINC:
case OPC2_32_BO_CACHEI_WI_POSTINC:
- if (tricore_feature(ctx->env, TRICORE_FEATURE_131)) {
+ if (has_feature(ctx, TRICORE_FEATURE_131)) {
tcg_gen_addi_tl(cpu_gpr_a[r2], cpu_gpr_a[r2], off10);
} else {
generate_trap(ctx, TRAPC_INSN_ERR, TIN2_IOPC);
@@ -4719,7 +4723,7 @@
break;
case OPC2_32_BO_CACHEI_W_PREINC:
case OPC2_32_BO_CACHEI_WI_PREINC:
- if (tricore_feature(ctx->env, TRICORE_FEATURE_131)) {
+ if (has_feature(ctx, TRICORE_FEATURE_131)) {
tcg_gen_addi_tl(cpu_gpr_a[r2], cpu_gpr_a[r2], off10);
} else {
generate_trap(ctx, TRAPC_INSN_ERR, TIN2_IOPC);
@@ -5373,7 +5377,7 @@
tcg_gen_addi_tl(cpu_gpr_a[r1], cpu_gpr_a[r2], address);
break;
case OPC1_32_BOL_ST_A_LONGOFF:
- if (tricore_feature(ctx->env, TRICORE_FEATURE_16)) {
+ if (has_feature(ctx, TRICORE_FEATURE_16)) {
gen_offset_st(ctx, cpu_gpr_a[r1], cpu_gpr_a[r2], address, MO_LEUL);
} else {
generate_trap(ctx, TRAPC_INSN_ERR, TIN2_IOPC);
@@ -5383,42 +5387,42 @@
gen_offset_st(ctx, cpu_gpr_d[r1], cpu_gpr_a[r2], address, MO_LEUL);
break;
case OPC1_32_BOL_LD_B_LONGOFF:
- if (tricore_feature(ctx->env, TRICORE_FEATURE_16)) {
+ if (has_feature(ctx, TRICORE_FEATURE_16)) {
gen_offset_ld(ctx, cpu_gpr_d[r1], cpu_gpr_a[r2], address, MO_SB);
} else {
generate_trap(ctx, TRAPC_INSN_ERR, TIN2_IOPC);
}
break;
case OPC1_32_BOL_LD_BU_LONGOFF:
- if (tricore_feature(ctx->env, TRICORE_FEATURE_16)) {
+ if (has_feature(ctx, TRICORE_FEATURE_16)) {
gen_offset_ld(ctx, cpu_gpr_d[r1], cpu_gpr_a[r2], address, MO_UB);
} else {
generate_trap(ctx, TRAPC_INSN_ERR, TIN2_IOPC);
}
break;
case OPC1_32_BOL_LD_H_LONGOFF:
- if (tricore_feature(ctx->env, TRICORE_FEATURE_16)) {
+ if (has_feature(ctx, TRICORE_FEATURE_16)) {
gen_offset_ld(ctx, cpu_gpr_d[r1], cpu_gpr_a[r2], address, MO_LESW);
} else {
generate_trap(ctx, TRAPC_INSN_ERR, TIN2_IOPC);
}
break;
case OPC1_32_BOL_LD_HU_LONGOFF:
- if (tricore_feature(ctx->env, TRICORE_FEATURE_16)) {
+ if (has_feature(ctx, TRICORE_FEATURE_16)) {
gen_offset_ld(ctx, cpu_gpr_d[r1], cpu_gpr_a[r2], address, MO_LEUW);
} else {
generate_trap(ctx, TRAPC_INSN_ERR, TIN2_IOPC);
}
break;
case OPC1_32_BOL_ST_B_LONGOFF:
- if (tricore_feature(ctx->env, TRICORE_FEATURE_16)) {
+ if (has_feature(ctx, TRICORE_FEATURE_16)) {
gen_offset_st(ctx, cpu_gpr_d[r1], cpu_gpr_a[r2], address, MO_SB);
} else {
generate_trap(ctx, TRAPC_INSN_ERR, TIN2_IOPC);
}
break;
case OPC1_32_BOL_ST_H_LONGOFF:
- if (tricore_feature(ctx->env, TRICORE_FEATURE_16)) {
+ if (has_feature(ctx, TRICORE_FEATURE_16)) {
gen_offset_st(ctx, cpu_gpr_d[r1], cpu_gpr_a[r2], address, MO_LESW);
} else {
generate_trap(ctx, TRAPC_INSN_ERR, TIN2_IOPC);
@@ -6023,7 +6027,7 @@
tcg_gen_movi_tl(cpu_gpr_d[r2], const16);
break;
case OPC1_32_RLC_MOV_64:
- if (tricore_feature(ctx->env, TRICORE_FEATURE_16)) {
+ if (has_feature(ctx, TRICORE_FEATURE_16)) {
CHECK_REG_PAIR(r2);
tcg_gen_movi_tl(cpu_gpr_d[r2], const16);
tcg_gen_movi_tl(cpu_gpr_d[r2+1], const16 >> 15);
@@ -6249,7 +6253,7 @@
tcg_gen_mov_tl(cpu_gpr_d[r3], cpu_gpr_d[r2]);
break;
case OPC2_32_RR_MOV_64:
- if (tricore_feature(ctx->env, TRICORE_FEATURE_16)) {
+ if (has_feature(ctx, TRICORE_FEATURE_16)) {
temp = tcg_temp_new();
CHECK_REG_PAIR(r3);
@@ -6263,7 +6267,7 @@
}
break;
case OPC2_32_RR_MOVS_64:
- if (tricore_feature(ctx->env, TRICORE_FEATURE_16)) {
+ if (has_feature(ctx, TRICORE_FEATURE_16)) {
CHECK_REG_PAIR(r3);
tcg_gen_mov_tl(cpu_gpr_d[r3], cpu_gpr_d[r2]);
tcg_gen_sari_tl(cpu_gpr_d[r3 + 1], cpu_gpr_d[r2], 31);
@@ -6603,7 +6607,7 @@
tcg_gen_shri_tl(temp3, cpu_gpr_d[r1], 8);
/* reset av */
tcg_gen_movi_tl(cpu_PSW_AV, 0);
- if (!tricore_feature(ctx->env, TRICORE_FEATURE_131)) {
+ if (!has_feature(ctx, TRICORE_FEATURE_131)) {
/* overflow = (abs(D[r3+1]) >= abs(D[r2])) */
tcg_gen_abs_tl(temp, temp3);
tcg_gen_abs_tl(temp2, cpu_gpr_d[r2]);
@@ -6636,7 +6640,7 @@
tcg_gen_shri_tl(temp3, cpu_gpr_d[r1], 16);
/* reset av */
tcg_gen_movi_tl(cpu_PSW_AV, 0);
- if (!tricore_feature(ctx->env, TRICORE_FEATURE_131)) {
+ if (!has_feature(ctx, TRICORE_FEATURE_131)) {
/* overflow = (abs(D[r3+1]) >= abs(D[r2])) */
tcg_gen_abs_tl(temp, temp3);
tcg_gen_abs_tl(temp2, cpu_gpr_d[r2]);
@@ -6699,14 +6703,14 @@
gen_unpack(cpu_gpr_d[r3], cpu_gpr_d[r3+1], cpu_gpr_d[r1]);
break;
case OPC2_32_RR_CRC32:
- if (tricore_feature(ctx->env, TRICORE_FEATURE_161)) {
+ if (has_feature(ctx, TRICORE_FEATURE_161)) {
gen_helper_crc32(cpu_gpr_d[r3], cpu_gpr_d[r1], cpu_gpr_d[r2]);
} else {
generate_trap(ctx, TRAPC_INSN_ERR, TIN2_IOPC);
}
break;
case OPC2_32_RR_DIV:
- if (tricore_feature(ctx->env, TRICORE_FEATURE_16)) {
+ if (has_feature(ctx, TRICORE_FEATURE_16)) {
GEN_HELPER_RR(divide, cpu_gpr_d[r3], cpu_gpr_d[r3+1], cpu_gpr_d[r1],
cpu_gpr_d[r2]);
} else {
@@ -6714,7 +6718,7 @@
}
break;
case OPC2_32_RR_DIV_U:
- if (tricore_feature(ctx->env, TRICORE_FEATURE_16)) {
+ if (has_feature(ctx, TRICORE_FEATURE_16)) {
GEN_HELPER_RR(divide_u, cpu_gpr_d[r3], cpu_gpr_d[r3+1],
cpu_gpr_d[r1], cpu_gpr_d[r2]);
} else {
@@ -8412,7 +8416,7 @@
gen_helper_svlcx(cpu_env);
break;
case OPC2_32_SYS_RESTORE:
- if (tricore_feature(ctx->env, TRICORE_FEATURE_16)) {
+ if (has_feature(ctx, TRICORE_FEATURE_16)) {
if ((ctx->hflags & TRICORE_HFLAG_KUU) == TRICORE_HFLAG_SM ||
(ctx->hflags & TRICORE_HFLAG_KUU) == TRICORE_HFLAG_UM1) {
tcg_gen_deposit_tl(cpu_ICR, cpu_ICR, cpu_gpr_d[r1], 8, 1);
@@ -8793,6 +8797,7 @@
CPUTriCoreState *env = cs->env_ptr;
ctx->mem_idx = cpu_mmu_index(env, false);
ctx->hflags = (uint32_t)ctx->base.tb->flags;
+ ctx->features = env->features;
}
static void tricore_tr_tb_start(DisasContextBase *db, CPUState *cpu)
diff --git a/target/unicore32/ucf64_helper.c b/target/unicore32/ucf64_helper.c
index e078e84..12a9190 100644
--- a/target/unicore32/ucf64_helper.c
+++ b/target/unicore32/ucf64_helper.c
@@ -174,8 +174,7 @@
void HELPER(ucf64_cmps)(float32 a, float32 b, uint32_t c,
CPUUniCore32State *env)
{
- int flag;
- flag = float32_compare_quiet(a, b, &env->ucf64.fp_status);
+ FloatRelation flag = float32_compare_quiet(a, b, &env->ucf64.fp_status);
env->CF = 0;
switch (c & 0x7) {
case 0: /* F */
@@ -223,8 +222,7 @@
void HELPER(ucf64_cmpd)(float64 a, float64 b, uint32_t c,
CPUUniCore32State *env)
{
- int flag;
- flag = float64_compare_quiet(a, b, &env->ucf64.fp_status);
+ FloatRelation flag = float64_compare_quiet(a, b, &env->ucf64.fp_status);
env->CF = 0;
switch (c & 0x7) {
case 0: /* F */
diff --git a/target/xtensa/fpu_helper.c b/target/xtensa/fpu_helper.c
index f8bbb6c..8748729 100644
--- a/target/xtensa/fpu_helper.c
+++ b/target/xtensa/fpu_helper.c
@@ -139,7 +139,7 @@
void HELPER(ueq_s)(CPUXtensaState *env, uint32_t br, float32 a, float32 b)
{
- int v = float32_compare_quiet(a, b, &env->fp_status);
+ FloatRelation v = float32_compare_quiet(a, b, &env->fp_status);
set_br(env, v == float_relation_equal || v == float_relation_unordered, br);
}
@@ -150,7 +150,7 @@
void HELPER(ult_s)(CPUXtensaState *env, uint32_t br, float32 a, float32 b)
{
- int v = float32_compare_quiet(a, b, &env->fp_status);
+ FloatRelation v = float32_compare_quiet(a, b, &env->fp_status);
set_br(env, v == float_relation_less || v == float_relation_unordered, br);
}
@@ -161,6 +161,6 @@
void HELPER(ule_s)(CPUXtensaState *env, uint32_t br, float32 a, float32 b)
{
- int v = float32_compare_quiet(a, b, &env->fp_status);
+ FloatRelation v = float32_compare_quiet(a, b, &env->fp_status);
set_br(env, v != float_relation_greater, br);
}
diff --git a/tcg/tcg.c b/tcg/tcg.c
index dd4b3d7..a2268d9 100644
--- a/tcg/tcg.c
+++ b/tcg/tcg.c
@@ -1092,7 +1092,7 @@
size_t data_size = prologue_size - code_size;
size_t i;
- log_disas(buf0, code_size);
+ log_disas(buf0, code_size, NULL);
for (i = 0; i < data_size; i += sizeof(tcg_target_ulong)) {
if (sizeof(tcg_target_ulong) == 8) {
@@ -1106,7 +1106,7 @@
}
}
} else {
- log_disas(buf0, prologue_size);
+ log_disas(buf0, prologue_size, NULL);
}
qemu_log("\n");
qemu_log_flush();
diff --git a/tests/Makefile.include b/tests/Makefile.include
index 03a74b6..6e3d637 100644
--- a/tests/Makefile.include
+++ b/tests/Makefile.include
@@ -4,7 +4,7 @@
check-help:
@echo "Regression testing targets:"
@echo
- @echo " $(MAKE) check Run unit, qapi-schema, qtest and decodetree"
+ @echo " $(MAKE) check Run block, qapi-schema, unit, softfloat, qtest and decodetree tests"
@echo
@echo " $(MAKE) check-qtest-TARGET Run qtest tests for given target"
@echo " $(MAKE) check-qtest Run qtest tests"
@@ -687,11 +687,26 @@
(cat $2.out && exit 1;), \
"FLOAT TEST", $2)
-# Conversion Routines:
+# Conversion Routines: Float to Float
+# FIXME: f32_to_f128 (broken), f64_to_f128 (broken)
+# FIXME: f128_to_f32(broken), f128_to_f64 (broken)
+# FIXME: f128_to_extF80 (broken)
+check-softfloat-conv-f2f: $(FP_TEST_BIN)
+ $(call test-softfloat, \
+ f16_to_f32 f16_to_f64 \
+ f16_to_extF80 f16_to_f128 \
+ f32_to_f16 f32_to_f64 \
+ f32_to_extF80 \
+ f64_to_f16 f64_to_f32 \
+ extF80_to_f16 extF80_to_f32 \
+ extF80_to_f64 extF80_to_f128 \
+ f128_to_f16, \
+ float-to-float)
+
+# Conversion Routines: Int and Uint to Float
# FIXME: i32_to_extF80 (broken), i64_to_extF80 (broken)
-# ui32_to_f128 (not implemented), extF80_roundToInt (broken)
-#
-check-softfloat-conv: $(FP_TEST_BIN)
+# ui32_to_f128 (not implemented)
+check-softfloat-conv-to-float: $(FP_TEST_BIN)
$(call test-softfloat, \
i32_to_f16 i64_to_f16 \
i32_to_f32 i64_to_f32 \
@@ -701,7 +716,12 @@
ui32_to_f16 ui64_to_f16 \
ui32_to_f32 ui64_to_f32 \
ui32_to_f64 ui64_to_f64 \
+ ui32_to_extF80 ui64_to_extF80 \
ui64_to_f128, uint-to-float)
+
+# Conversion Routines: Float to integers
+# FIXME: extF80_roundToInt (broken)
+check-softfloat-conv-to-int: $(FP_TEST_BIN)
$(call test-softfloat, \
f16_to_i32 f16_to_i32_r_minMag \
f32_to_i32 f32_to_i32_r_minMag \
@@ -718,10 +738,12 @@
f16_to_ui32 f16_to_ui32_r_minMag \
f32_to_ui32 f32_to_ui32_r_minMag \
f64_to_ui32 f64_to_ui32_r_minMag \
+ extF80_to_ui32 extF80_to_ui32_r_minMag \
f128_to_ui32 f128_to_ui32_r_minMag \
f16_to_ui64 f16_to_ui64_r_minMag \
f32_to_ui64 f32_to_ui64_r_minMag \
f64_to_ui64 f64_to_ui64_r_minMag \
+ extF80_to_ui64 extF80_to_ui64_r_minMag \
f128_to_ui64 f128_to_ui64_r_minMag, \
float-to-uint)
$(call test-softfloat, \
@@ -729,9 +751,14 @@
f64_roundToInt f128_roundToInt, \
round-to-integer)
+.PHONY: check-softfloat-conv
+check-softfloat-conv: check-softfloat-conv-f2f
+check-softfloat-conv: check-softfloat-conv-to-float
+check-softfloat-conv: check-softfloat-conv-to-int
+
# Generic rule for all float operations
#
-# Some patterns are overidden due to broken or missing tests.
+# Some patterns are overridden due to broken or missing tests.
# Hopefully these can be removed over time.
check-softfloat-%: $(FP_TEST_BIN)
@@ -741,13 +768,6 @@
SF_COMPARE_OPS=eq eq_signaling le le_quiet lt_quiet
SF_COMPARE_RULES=$(patsubst %,check-softfloat-%, $(SF_COMPARE_OPS))
-# FIXME: extF80_le_quiet (broken)
-check-softfloat-le_quiet: $(FP_TEST_BIN)
- $(call test-softfloat, \
- f16_le_quiet f32_le_quiet f64_le_quiet \
- f128_le_quiet, \
- le_quiet)
-
# FIXME: extF80_lt_quiet (broken)
check-softfloat-lt_quiet: $(FP_TEST_BIN)
$(call test-softfloat, \
diff --git a/tests/acceptance/avocado_qemu/__init__.py b/tests/acceptance/avocado_qemu/__init__.py
index 59e7b4f..77d1c1d 100644
--- a/tests/acceptance/avocado_qemu/__init__.py
+++ b/tests/acceptance/avocado_qemu/__init__.py
@@ -69,13 +69,15 @@
def _console_interaction(test, success_message, failure_message,
- send_string, keep_sending=False):
+ send_string, keep_sending=False, vm=None):
assert not keep_sending or send_string
- console = test.vm.console_socket.makefile()
+ if vm is None:
+ vm = test.vm
+ console = vm.console_socket.makefile()
console_logger = logging.getLogger('console')
while True:
if send_string:
- test.vm.console_socket.sendall(send_string.encode())
+ vm.console_socket.sendall(send_string.encode())
if not keep_sending:
send_string = None # send only once
msg = console.readline().strip()
@@ -115,7 +117,8 @@
_console_interaction(test, success_message, failure_message,
interrupt_string, True)
-def wait_for_console_pattern(test, success_message, failure_message=None):
+def wait_for_console_pattern(test, success_message, failure_message=None,
+ vm=None):
"""
Waits for messages to appear on the console, while logging the content
@@ -125,7 +128,7 @@
:param success_message: if this message appears, test succeeds
:param failure_message: if this message appears, test fails
"""
- _console_interaction(test, success_message, failure_message, None)
+ _console_interaction(test, success_message, failure_message, None, vm=vm)
def exec_command_and_wait_for_pattern(test, command,
success_message, failure_message=None):
diff --git a/tests/acceptance/boot_linux.py b/tests/acceptance/boot_linux.py
index 075a386..3aa57e8 100644
--- a/tests/acceptance/boot_linux.py
+++ b/tests/acceptance/boot_linux.py
@@ -26,22 +26,8 @@
TCG_NOT_AVAILABLE = ACCEL_NOT_AVAILABLE_FMT % "TCG"
-class BootLinux(Test):
- """
- Boots a Linux system, checking for a successful initialization
- """
-
- timeout = 900
- chksum = None
-
- def setUp(self):
- super(BootLinux, self).setUp()
- self.vm.add_args('-smp', '2')
- self.vm.add_args('-m', '1024')
- self.prepare_boot()
- self.prepare_cloudinit()
-
- def prepare_boot(self):
+class BootLinuxBase(Test):
+ def download_boot(self):
self.log.debug('Looking for and selecting a qemu-img binary to be '
'used to create the bootable snapshot image')
# If qemu-img has been built, use it, otherwise the system wide one
@@ -60,17 +46,17 @@
if image_arch == 'ppc64':
image_arch = 'ppc64le'
try:
- self.boot = vmimage.get(
+ boot = vmimage.get(
'fedora', arch=image_arch, version='31',
checksum=self.chksum,
algorithm='sha256',
cache_dir=self.cache_dirs[0],
snapshot_dir=self.workdir)
- self.vm.add_args('-drive', 'file=%s' % self.boot.path)
except:
self.cancel('Failed to download/prepare boot image')
+ return boot.path
- def prepare_cloudinit(self):
+ def download_cloudinit(self):
self.log.info('Preparing cloudinit image')
try:
cloudinit_iso = os.path.join(self.workdir, 'cloudinit.iso')
@@ -81,9 +67,32 @@
# QEMU's hard coded usermode router address
phone_home_host='10.0.2.2',
phone_home_port=self.phone_home_port)
- self.vm.add_args('-drive', 'file=%s,format=raw' % cloudinit_iso)
except Exception:
self.cancel('Failed to prepared cloudinit image')
+ return cloudinit_iso
+
+class BootLinux(BootLinuxBase):
+ """
+ Boots a Linux system, checking for a successful initialization
+ """
+
+ timeout = 900
+ chksum = None
+
+ def setUp(self):
+ super(BootLinux, self).setUp()
+ self.vm.add_args('-smp', '2')
+ self.vm.add_args('-m', '1024')
+ self.prepare_boot()
+ self.prepare_cloudinit()
+
+ def prepare_boot(self):
+ path = self.download_boot()
+ self.vm.add_args('-drive', 'file=%s' % path)
+
+ def prepare_cloudinit(self):
+ cloudinit_iso = self.download_cloudinit()
+ self.vm.add_args('-drive', 'file=%s,format=raw' % cloudinit_iso)
def launch_and_wait(self):
self.vm.set_console()
diff --git a/tests/acceptance/boot_linux_console.py b/tests/acceptance/boot_linux_console.py
index c6b06a1..12725d4 100644
--- a/tests/acceptance/boot_linux_console.py
+++ b/tests/acceptance/boot_linux_console.py
@@ -28,19 +28,13 @@
except CmdNotFoundError:
P7ZIP_AVAILABLE = False
-class BootLinuxConsole(Test):
- """
- Boots a Linux kernel and checks that the console is operational and the
- kernel command line is properly passed from QEMU to the kernel
- """
-
- timeout = 90
-
+class LinuxKernelTest(Test):
KERNEL_COMMON_COMMAND_LINE = 'printk.time=0 '
- def wait_for_console_pattern(self, success_message):
+ def wait_for_console_pattern(self, success_message, vm=None):
wait_for_console_pattern(self, success_message,
- failure_message='Kernel panic - not syncing')
+ failure_message='Kernel panic - not syncing',
+ vm=vm)
def extract_from_deb(self, deb, path):
"""
@@ -79,6 +73,13 @@
os.chdir(cwd)
return os.path.normpath(os.path.join(self.workdir, path))
+class BootLinuxConsole(LinuxKernelTest):
+ """
+ Boots a Linux kernel and checks that the console is operational and the
+ kernel command line is properly passed from QEMU to the kernel
+ """
+ timeout = 90
+
def test_x86_64_pc(self):
"""
:avocado: tags=arch:x86_64
diff --git a/tests/acceptance/machine_arm_canona1100.py b/tests/acceptance/machine_arm_canona1100.py
new file mode 100644
index 0000000..0e5c43d
--- /dev/null
+++ b/tests/acceptance/machine_arm_canona1100.py
@@ -0,0 +1,35 @@
+# Functional test that boots the canon-a1100 machine with firmware
+#
+# Copyright (c) 2020 Red Hat, Inc.
+#
+# Author:
+# Thomas Huth <thuth@redhat.com>
+#
+# This work is licensed under the terms of the GNU GPL, version 2 or
+# later. See the COPYING file in the top-level directory.
+
+from avocado_qemu import Test
+from avocado_qemu import wait_for_console_pattern
+from avocado.utils import archive
+
+class CanonA1100Machine(Test):
+ """Boots the barebox firmware and checks that the console is operational"""
+
+ timeout = 90
+
+ def test_arm_canona1100(self):
+ """
+ :avocado: tags=arch:arm
+ :avocado: tags=machine:canon-a1100
+ :avocado: tags=device:pflash_cfi02
+ """
+ tar_url = ('https://www.qemu-advent-calendar.org'
+ '/2018/download/day18.tar.xz')
+ tar_hash = '068b5fc4242b29381acee94713509f8a876e9db6'
+ file_path = self.fetch_asset(tar_url, asset_hash=tar_hash)
+ archive.extract(file_path, self.workdir)
+ self.vm.set_console()
+ self.vm.add_args('-bios',
+ self.workdir + '/day18/barebox.canon-a1100.bin')
+ self.vm.launch()
+ wait_for_console_pattern(self, 'running /env/bin/init')
diff --git a/tests/acceptance/migration.py b/tests/acceptance/migration.py
index 0365289..792639c 100644
--- a/tests/acceptance/migration.py
+++ b/tests/acceptance/migration.py
@@ -35,6 +35,10 @@
timeout=self.timeout,
step=0.1,
args=(src_vm,))
+ wait.wait_for(self.migration_finished,
+ timeout=self.timeout,
+ step=0.1,
+ args=(dst_vm,))
self.assertEqual(src_vm.command('query-migrate')['status'], 'completed')
self.assertEqual(dst_vm.command('query-migrate')['status'], 'completed')
self.assertEqual(dst_vm.command('query-status')['status'], 'running')
diff --git a/tests/check-qom-proplist.c b/tests/check-qom-proplist.c
index a8b2958..13a824c 100644
--- a/tests/check-qom-proplist.c
+++ b/tests/check-qom-proplist.c
@@ -125,32 +125,22 @@
static void dummy_init(Object *obj)
{
- Error *err = NULL;
-
object_property_add_bool(obj, "bv",
dummy_get_bv,
- dummy_set_bv,
- &err);
- error_free_or_abort(&err);
+ dummy_set_bv);
}
static void dummy_class_init(ObjectClass *cls, void *data)
{
- object_class_property_add_bool(cls, "bv",
- dummy_get_bv,
- dummy_set_bv,
- NULL);
object_class_property_add_str(cls, "sv",
dummy_get_sv,
- dummy_set_sv,
- NULL);
+ dummy_set_sv);
object_class_property_add_enum(cls, "av",
"DummyAnimal",
&dummy_animal_map,
dummy_get_av,
- dummy_set_av,
- NULL);
+ dummy_set_av);
}
@@ -255,13 +245,13 @@
DummyBus *bus = DUMMY_BUS(object_new(TYPE_DUMMY_BUS));
DummyBackend *backend = DUMMY_BACKEND(object_new(TYPE_DUMMY_BACKEND));
- object_property_add_child(obj, "bus", OBJECT(bus), NULL);
+ object_property_add_child(obj, "bus", OBJECT(bus));
dev->bus = bus;
- object_property_add_child(OBJECT(bus), "backend", OBJECT(backend), NULL);
+ object_property_add_child(OBJECT(bus), "backend", OBJECT(backend));
bus->backend = backend;
object_property_add_link(obj, "backend", TYPE_DUMMY_BACKEND,
- (Object **)&bus->backend, NULL, 0, NULL);
+ (Object **)&bus->backend, NULL, 0);
}
static void dummy_dev_unparent(Object *obj)
@@ -290,7 +280,7 @@
static void dummy_bus_unparent(Object *obj)
{
DummyBus *bus = DUMMY_BUS(obj);
- object_property_del(obj->parent, "backend", NULL);
+ object_property_del(obj->parent, "backend");
object_unparent(OBJECT(bus->backend));
}
@@ -520,34 +510,33 @@
}
-static void test_dummy_prop_iterator(ObjectPropertyIterator *iter)
+static void test_dummy_prop_iterator(ObjectPropertyIterator *iter,
+ const char *expected[], int n)
{
- bool seenbv = false, seensv = false, seenav = false, seentype = false;
ObjectProperty *prop;
+ int i;
while ((prop = object_property_iter_next(iter))) {
- if (!seenbv && g_str_equal(prop->name, "bv")) {
- seenbv = true;
- } else if (!seensv && g_str_equal(prop->name, "sv")) {
- seensv = true;
- } else if (!seenav && g_str_equal(prop->name, "av")) {
- seenav = true;
- } else if (!seentype && g_str_equal(prop->name, "type")) {
- /* This prop comes from the base Object class */
- seentype = true;
- } else {
- g_printerr("Found prop '%s'\n", prop->name);
- g_assert_not_reached();
+ for (i = 0; i < n; i++) {
+ if (!g_strcmp0(prop->name, expected[i])) {
+ break;
+ }
}
+ g_assert(i < n);
+ expected[i] = NULL;
}
- g_assert(seenbv);
- g_assert(seenav);
- g_assert(seensv);
- g_assert(seentype);
+
+ for (i = 0; i < n; i++) {
+ g_assert(!expected[i]);
+ }
}
static void test_dummy_iterator(void)
{
+ const char *expected[] = {
+ "type", /* inherited from TYPE_OBJECT */
+ "sv", "av", /* class properties */
+ "bv"}; /* instance property */
Object *parent = object_get_objects_root();
DummyObject *dobj = DUMMY_OBJECT(
object_new_with_props(TYPE_DUMMY,
@@ -561,17 +550,18 @@
ObjectPropertyIterator iter;
object_property_iter_init(&iter, OBJECT(dobj));
- test_dummy_prop_iterator(&iter);
+ test_dummy_prop_iterator(&iter, expected, ARRAY_SIZE(expected));
object_unparent(OBJECT(dobj));
}
static void test_dummy_class_iterator(void)
{
+ const char *expected[] = { "type", "av", "sv" };
ObjectPropertyIterator iter;
ObjectClass *klass = object_class_by_name(TYPE_DUMMY);
object_class_property_iter_init(&iter, klass);
- test_dummy_prop_iterator(&iter);
+ test_dummy_prop_iterator(&iter, expected, ARRAY_SIZE(expected));
}
static void test_dummy_delchild(void)
@@ -602,11 +592,11 @@
* /cont1/obj2 (obj2a)
* /obj2 (obj2b)
*/
- object_property_add_child(cont1, "obj1", obj1, &error_abort);
+ object_property_add_child(cont1, "obj1", obj1);
object_unref(obj1);
- object_property_add_child(cont1, "obj2", obj2a, &error_abort);
+ object_property_add_child(cont1, "obj2", obj2a);
object_unref(obj2a);
- object_property_add_child(root, "obj2", obj2b, &error_abort);
+ object_property_add_child(root, "obj2", obj2b);
object_unref(obj2b);
ambiguous = false;
diff --git a/tests/docker/Makefile.include b/tests/docker/Makefile.include
index 43a8678..ed46bd9 100644
--- a/tests/docker/Makefile.include
+++ b/tests/docker/Makefile.include
@@ -7,7 +7,7 @@
DOCKER_SUFFIX := .docker
DOCKER_FILES_DIR := $(SRC_PATH)/tests/docker/dockerfiles
# we don't run tests on intermediate images (used as base by another image)
-DOCKER_PARTIAL_IMAGES := debian9 debian10
+DOCKER_PARTIAL_IMAGES := debian9 debian10 debian11
DOCKER_PARTIAL_IMAGES += debian9-mxe debian-bootstrap
DOCKER_IMAGES := $(sort $(notdir $(basename $(wildcard $(DOCKER_FILES_DIR)/*.docker))))
DOCKER_TARGETS := $(patsubst %,docker-image-%,$(DOCKER_IMAGES))
@@ -131,9 +131,11 @@
# Specialist build images, sometimes very limited tools
docker-image-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
DOCKER_PARTIAL_IMAGES += debian-alpha-cross
+DOCKER_PARTIAL_IMAGES += debian-arm64-test-cross
DOCKER_PARTIAL_IMAGES += debian-hppa-cross
DOCKER_PARTIAL_IMAGES += debian-m68k-cross debian-mips64-cross
DOCKER_PARTIAL_IMAGES += debian-powerpc-cross debian-ppc64-cross
diff --git a/tests/docker/docker.py b/tests/docker/docker.py
index d8268c1..5a9735d 100755
--- a/tests/docker/docker.py
+++ b/tests/docker/docker.py
@@ -258,12 +258,13 @@
return self._do_kill_instances(True)
def _output(self, cmd, **kwargs):
- if sys.version_info[1] >= 6:
+ try:
return subprocess.check_output(self._command + cmd,
stderr=subprocess.STDOUT,
encoding='utf-8',
**kwargs)
- else:
+ except TypeError:
+ # 'encoding' argument was added in 3.6+
return subprocess.check_output(self._command + cmd,
stderr=subprocess.STDOUT,
**kwargs).decode('utf-8')
diff --git a/tests/docker/dockerfiles/debian-arm64-test-cross.docker b/tests/docker/dockerfiles/debian-arm64-test-cross.docker
new file mode 100644
index 0000000..a44e76d
--- /dev/null
+++ b/tests/docker/dockerfiles/debian-arm64-test-cross.docker
@@ -0,0 +1,13 @@
+#
+# Docker arm64 cross-compiler target (tests only)
+#
+# This docker target builds on the debian Bullseye base image.
+#
+FROM qemu:debian11
+
+# Add the foreign architecture we want and install dependencies
+RUN dpkg --add-architecture arm64
+RUN apt update && \
+ DEBIAN_FRONTEND=noninteractive eatmydata \
+ apt install -y --no-install-recommends \
+ crossbuild-essential-arm64 gcc-10-aarch64-linux-gnu
diff --git a/tests/docker/dockerfiles/debian11.docker b/tests/docker/dockerfiles/debian11.docker
new file mode 100644
index 0000000..5adfd62
--- /dev/null
+++ b/tests/docker/dockerfiles/debian11.docker
@@ -0,0 +1,18 @@
+#
+# Docker multiarch cross-compiler target
+#
+# This docker target uses the current development version of Debian as
+# a base for cross compilers for building test binaries. We won't
+# attempt to build QEMU on it yet given it is still in development.
+#
+# On its own you can't build much but the docker-foo-cross targets
+# build on top of the base debian image.
+#
+FROM debian:bullseye-slim
+
+# Duplicate deb line as deb-src
+RUN cat /etc/apt/sources.list | sed "s/^deb\ /deb-src /" >> /etc/apt/sources.list
+
+# Install common build utilities
+RUN apt update && \
+ DEBIAN_FRONTEND=noninteractive apt install -yy eatmydata
diff --git a/tests/fp/fp-test.c b/tests/fp/fp-test.c
index 7d0faf2..43ef962 100644
--- a/tests/fp/fp-test.c
+++ b/tests/fp/fp-test.c
@@ -989,7 +989,7 @@
verCases_tininessCode = 0;
slowfloat_detectTininess = tmode;
- qsf.float_detect_tininess = sf_tininess_to_qemu(tmode);
+ qsf.tininess_before_rounding = sf_tininess_to_qemu(tmode);
if (attrs & FUNC_EFF_TININESSMODE ||
((attrs & FUNC_EFF_TININESSMODE_REDUCEDPREC) &&
diff --git a/tests/guest-debug/run-test.py b/tests/guest-debug/run-test.py
index d9af957..71c5569 100755
--- a/tests/guest-debug/run-test.py
+++ b/tests/guest-debug/run-test.py
@@ -80,4 +80,10 @@
print("GDB crashed? SKIPPING")
exit(0)
+ try:
+ inferior.wait(2)
+ except subprocess.TimeoutExpired:
+ print("GDB never connected? Killed guest")
+ inferior.kill()
+
exit(result)
diff --git a/tests/migration/guestperf-batch.py b/tests/migration/guestperf-batch.py
index cb150ce..f1e9009 100755
--- a/tests/migration/guestperf-batch.py
+++ b/tests/migration/guestperf-batch.py
@@ -1,4 +1,4 @@
-#!/usr/bin/python
+#!/usr/bin/env python3
#
# Migration test batch comparison invokation
#
diff --git a/tests/migration/guestperf-plot.py b/tests/migration/guestperf-plot.py
index d70bb7a..9071510 100755
--- a/tests/migration/guestperf-plot.py
+++ b/tests/migration/guestperf-plot.py
@@ -1,4 +1,4 @@
-#!/usr/bin/python
+#!/usr/bin/env python3
#
# Migration test graph plotting command
#
diff --git a/tests/migration/guestperf.py b/tests/migration/guestperf.py
index 99b027e..ba1c4bc 100755
--- a/tests/migration/guestperf.py
+++ b/tests/migration/guestperf.py
@@ -1,4 +1,4 @@
-#!/usr/bin/python
+#!/usr/bin/env python3
#
# Migration test direct invokation command
#
diff --git a/tests/qemu-iotests/030 b/tests/qemu-iotests/030
index 104e3ce..1cdd7e2 100755
--- a/tests/qemu-iotests/030
+++ b/tests/qemu-iotests/030
@@ -354,14 +354,14 @@
self.assert_qmp(result, 'error/desc',
"Node 'node5' is busy: block device is in use by block job: commit")
+ result = self.vm.qmp('block-job-set-speed', device='commit-drive0', speed=0)
+ self.assert_qmp(result, 'return', {})
+
event = self.vm.event_wait(name='BLOCK_JOB_READY')
self.assert_qmp(event, 'data/device', 'commit-drive0')
self.assert_qmp(event, 'data/type', 'commit')
self.assert_qmp_absent(event, 'data/error')
- result = self.vm.qmp('block-job-set-speed', device='commit-drive0', speed=0)
- self.assert_qmp(result, 'return', {})
-
result = self.vm.qmp('block-job-complete', device='commit-drive0')
self.assert_qmp(result, 'return', {})
diff --git a/tests/qemu-iotests/031.out b/tests/qemu-iotests/031.out
index 46f97c5..5a4beda 100644
--- a/tests/qemu-iotests/031.out
+++ b/tests/qemu-iotests/031.out
@@ -113,11 +113,11 @@
compatible_features []
autoclear_features []
refcount_order 4
-header_length 104
+header_length 112
Header extension:
magic 0x6803f857
-length 288
+length 336
data <binary>
Header extension:
@@ -146,11 +146,11 @@
compatible_features []
autoclear_features []
refcount_order 4
-header_length 104
+header_length 112
Header extension:
magic 0x6803f857
-length 288
+length 336
data <binary>
Header extension:
@@ -164,7 +164,7 @@
magic 0x514649fb
version 3
-backing_file_offset 0x1d8
+backing_file_offset 0x210
backing_file_size 0x17
cluster_bits 16
size 67108864
@@ -179,7 +179,7 @@
compatible_features []
autoclear_features []
refcount_order 4
-header_length 104
+header_length 112
Header extension:
magic 0xe2792aca
@@ -188,7 +188,7 @@
Header extension:
magic 0x6803f857
-length 288
+length 336
data <binary>
Header extension:
diff --git a/tests/qemu-iotests/036.out b/tests/qemu-iotests/036.out
index 23b699c..e409acf 100644
--- a/tests/qemu-iotests/036.out
+++ b/tests/qemu-iotests/036.out
@@ -26,7 +26,7 @@
autoclear_features [63]
Header extension:
magic 0x6803f857
-length 288
+length 336
data <binary>
@@ -38,7 +38,7 @@
autoclear_features []
Header extension:
magic 0x6803f857
-length 288
+length 336
data <binary>
*** done
diff --git a/tests/qemu-iotests/041 b/tests/qemu-iotests/041
index 1812dd8..601c756 100755
--- a/tests/qemu-iotests/041
+++ b/tests/qemu-iotests/041
@@ -240,6 +240,49 @@
target=self.qmp_target)
self.assert_qmp(result, 'error/class', 'GenericError')
+ def do_test_resize(self, device, node):
+ def pre_finalize():
+ if device:
+ result = self.vm.qmp('block_resize', device=device, size=65536)
+ self.assert_qmp(result, 'error/class', 'GenericError')
+
+ result = self.vm.qmp('block_resize', node_name=node, size=65536)
+ self.assert_qmp(result, 'error/class', 'GenericError')
+
+ result = self.vm.qmp(self.qmp_cmd, job_id='job0', device='drive0',
+ sync='full', target=self.qmp_target,
+ auto_finalize=False, auto_dismiss=False)
+ self.assert_qmp(result, 'return', {})
+
+ result = self.vm.run_job('job0', auto_finalize=False,
+ pre_finalize=pre_finalize)
+ self.assertEqual(result, None)
+
+ def test_source_resize(self):
+ self.do_test_resize('drive0', 'top')
+
+ def test_target_resize(self):
+ self.do_test_resize(None, self.qmp_target)
+
+ def do_test_target_size(self, size):
+ result = self.vm.qmp('block_resize', node_name=self.qmp_target,
+ size=size)
+ self.assert_qmp(result, 'return', {})
+
+ result = self.vm.qmp(self.qmp_cmd, job_id='job0',
+ device='drive0', sync='full', auto_dismiss=False,
+ target=self.qmp_target)
+ self.assert_qmp(result, 'return', {})
+
+ result = self.vm.run_job('job0')
+ self.assertEqual(result, 'Source and target image have different sizes')
+
+ def test_small_target(self):
+ self.do_test_target_size(self.image_len // 2)
+
+ def test_large_target(self):
+ self.do_test_target_size(self.image_len * 2)
+
test_large_cluster = None
test_image_not_found = None
test_small_buffer2 = None
@@ -251,6 +294,8 @@
class TestSingleBlockdevZeroLength(TestSingleBlockdev):
image_len = 0
+ test_small_target = None
+ test_large_target = None
class TestSingleDriveUnalignedLength(TestSingleDrive):
image_len = 1025 * 1024
diff --git a/tests/qemu-iotests/041.out b/tests/qemu-iotests/041.out
index 877b76f..53abe11 100644
--- a/tests/qemu-iotests/041.out
+++ b/tests/qemu-iotests/041.out
@@ -1,5 +1,5 @@
-..............................................................................................
+........................................................................................................
----------------------------------------------------------------------
-Ran 94 tests
+Ran 104 tests
OK
diff --git a/tests/qemu-iotests/049.out b/tests/qemu-iotests/049.out
index affa55b..c54ae21 100644
--- a/tests/qemu-iotests/049.out
+++ b/tests/qemu-iotests/049.out
@@ -4,107 +4,107 @@
== 1. Traditional size parameter ==
qemu-img create -f qcow2 TEST_DIR/t.qcow2 1024
-Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=1024 cluster_size=65536 lazy_refcounts=off refcount_bits=16
+Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=1024 cluster_size=65536 lazy_refcounts=off refcount_bits=16 compression_type=zlib
qemu-img create -f qcow2 TEST_DIR/t.qcow2 1024b
-Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=1024 cluster_size=65536 lazy_refcounts=off refcount_bits=16
+Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=1024 cluster_size=65536 lazy_refcounts=off refcount_bits=16 compression_type=zlib
qemu-img create -f qcow2 TEST_DIR/t.qcow2 1k
-Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=1024 cluster_size=65536 lazy_refcounts=off refcount_bits=16
+Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=1024 cluster_size=65536 lazy_refcounts=off refcount_bits=16 compression_type=zlib
qemu-img create -f qcow2 TEST_DIR/t.qcow2 1K
-Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=1024 cluster_size=65536 lazy_refcounts=off refcount_bits=16
+Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=1024 cluster_size=65536 lazy_refcounts=off refcount_bits=16 compression_type=zlib
qemu-img create -f qcow2 TEST_DIR/t.qcow2 1M
-Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=1048576 cluster_size=65536 lazy_refcounts=off refcount_bits=16
+Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=1048576 cluster_size=65536 lazy_refcounts=off refcount_bits=16 compression_type=zlib
qemu-img create -f qcow2 TEST_DIR/t.qcow2 1G
-Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=1073741824 cluster_size=65536 lazy_refcounts=off refcount_bits=16
+Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=1073741824 cluster_size=65536 lazy_refcounts=off refcount_bits=16 compression_type=zlib
qemu-img create -f qcow2 TEST_DIR/t.qcow2 1T
-Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=1099511627776 cluster_size=65536 lazy_refcounts=off refcount_bits=16
+Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=1099511627776 cluster_size=65536 lazy_refcounts=off refcount_bits=16 compression_type=zlib
qemu-img create -f qcow2 TEST_DIR/t.qcow2 1024.0
-Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=1024 cluster_size=65536 lazy_refcounts=off refcount_bits=16
+Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=1024 cluster_size=65536 lazy_refcounts=off refcount_bits=16 compression_type=zlib
qemu-img create -f qcow2 TEST_DIR/t.qcow2 1024.0b
-Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=1024 cluster_size=65536 lazy_refcounts=off refcount_bits=16
+Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=1024 cluster_size=65536 lazy_refcounts=off refcount_bits=16 compression_type=zlib
qemu-img create -f qcow2 TEST_DIR/t.qcow2 1.5k
-Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=1536 cluster_size=65536 lazy_refcounts=off refcount_bits=16
+Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=1536 cluster_size=65536 lazy_refcounts=off refcount_bits=16 compression_type=zlib
qemu-img create -f qcow2 TEST_DIR/t.qcow2 1.5K
-Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=1536 cluster_size=65536 lazy_refcounts=off refcount_bits=16
+Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=1536 cluster_size=65536 lazy_refcounts=off refcount_bits=16 compression_type=zlib
qemu-img create -f qcow2 TEST_DIR/t.qcow2 1.5M
-Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=1572864 cluster_size=65536 lazy_refcounts=off refcount_bits=16
+Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=1572864 cluster_size=65536 lazy_refcounts=off refcount_bits=16 compression_type=zlib
qemu-img create -f qcow2 TEST_DIR/t.qcow2 1.5G
-Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=1610612736 cluster_size=65536 lazy_refcounts=off refcount_bits=16
+Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=1610612736 cluster_size=65536 lazy_refcounts=off refcount_bits=16 compression_type=zlib
qemu-img create -f qcow2 TEST_DIR/t.qcow2 1.5T
-Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=1649267441664 cluster_size=65536 lazy_refcounts=off refcount_bits=16
+Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=1649267441664 cluster_size=65536 lazy_refcounts=off refcount_bits=16 compression_type=zlib
== 2. Specifying size via -o ==
qemu-img create -f qcow2 -o size=1024 TEST_DIR/t.qcow2
-Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=1024 cluster_size=65536 lazy_refcounts=off refcount_bits=16
+Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=1024 cluster_size=65536 lazy_refcounts=off refcount_bits=16 compression_type=zlib
qemu-img create -f qcow2 -o size=1024b TEST_DIR/t.qcow2
-Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=1024 cluster_size=65536 lazy_refcounts=off refcount_bits=16
+Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=1024 cluster_size=65536 lazy_refcounts=off refcount_bits=16 compression_type=zlib
qemu-img create -f qcow2 -o size=1k TEST_DIR/t.qcow2
-Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=1024 cluster_size=65536 lazy_refcounts=off refcount_bits=16
+Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=1024 cluster_size=65536 lazy_refcounts=off refcount_bits=16 compression_type=zlib
qemu-img create -f qcow2 -o size=1K TEST_DIR/t.qcow2
-Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=1024 cluster_size=65536 lazy_refcounts=off refcount_bits=16
+Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=1024 cluster_size=65536 lazy_refcounts=off refcount_bits=16 compression_type=zlib
qemu-img create -f qcow2 -o size=1M TEST_DIR/t.qcow2
-Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=1048576 cluster_size=65536 lazy_refcounts=off refcount_bits=16
+Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=1048576 cluster_size=65536 lazy_refcounts=off refcount_bits=16 compression_type=zlib
qemu-img create -f qcow2 -o size=1G TEST_DIR/t.qcow2
-Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=1073741824 cluster_size=65536 lazy_refcounts=off refcount_bits=16
+Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=1073741824 cluster_size=65536 lazy_refcounts=off refcount_bits=16 compression_type=zlib
qemu-img create -f qcow2 -o size=1T TEST_DIR/t.qcow2
-Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=1099511627776 cluster_size=65536 lazy_refcounts=off refcount_bits=16
+Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=1099511627776 cluster_size=65536 lazy_refcounts=off refcount_bits=16 compression_type=zlib
qemu-img create -f qcow2 -o size=1024.0 TEST_DIR/t.qcow2
-Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=1024 cluster_size=65536 lazy_refcounts=off refcount_bits=16
+Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=1024 cluster_size=65536 lazy_refcounts=off refcount_bits=16 compression_type=zlib
qemu-img create -f qcow2 -o size=1024.0b TEST_DIR/t.qcow2
-Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=1024 cluster_size=65536 lazy_refcounts=off refcount_bits=16
+Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=1024 cluster_size=65536 lazy_refcounts=off refcount_bits=16 compression_type=zlib
qemu-img create -f qcow2 -o size=1.5k TEST_DIR/t.qcow2
-Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=1536 cluster_size=65536 lazy_refcounts=off refcount_bits=16
+Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=1536 cluster_size=65536 lazy_refcounts=off refcount_bits=16 compression_type=zlib
qemu-img create -f qcow2 -o size=1.5K TEST_DIR/t.qcow2
-Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=1536 cluster_size=65536 lazy_refcounts=off refcount_bits=16
+Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=1536 cluster_size=65536 lazy_refcounts=off refcount_bits=16 compression_type=zlib
qemu-img create -f qcow2 -o size=1.5M TEST_DIR/t.qcow2
-Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=1572864 cluster_size=65536 lazy_refcounts=off refcount_bits=16
+Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=1572864 cluster_size=65536 lazy_refcounts=off refcount_bits=16 compression_type=zlib
qemu-img create -f qcow2 -o size=1.5G TEST_DIR/t.qcow2
-Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=1610612736 cluster_size=65536 lazy_refcounts=off refcount_bits=16
+Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=1610612736 cluster_size=65536 lazy_refcounts=off refcount_bits=16 compression_type=zlib
qemu-img create -f qcow2 -o size=1.5T TEST_DIR/t.qcow2
-Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=1649267441664 cluster_size=65536 lazy_refcounts=off refcount_bits=16
+Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=1649267441664 cluster_size=65536 lazy_refcounts=off refcount_bits=16 compression_type=zlib
== 3. Invalid sizes ==
qemu-img create -f qcow2 TEST_DIR/t.qcow2 -- -1024
-qemu-img: Image size must be less than 8 EiB!
+qemu-img: Invalid image size specified. Must be between 0 and 9223372036854775807.
qemu-img create -f qcow2 -o size=-1024 TEST_DIR/t.qcow2
qemu-img: TEST_DIR/t.qcow2: Value '-1024' is out of range for parameter 'size'
qemu-img create -f qcow2 TEST_DIR/t.qcow2 -- -1k
-qemu-img: Image size must be less than 8 EiB!
+qemu-img: Invalid image size specified. Must be between 0 and 9223372036854775807.
qemu-img create -f qcow2 -o size=-1k TEST_DIR/t.qcow2
qemu-img: TEST_DIR/t.qcow2: Value '-1k' is out of range for parameter 'size'
qemu-img create -f qcow2 TEST_DIR/t.qcow2 -- 1kilobyte
-qemu-img: Invalid image size specified! You may use k, M, G, T, P or E suffixes for
+qemu-img: Invalid image size specified. You may use k, M, G, T, P or E suffixes for
qemu-img: kilobytes, megabytes, gigabytes, terabytes, petabytes and exabytes.
qemu-img create -f qcow2 -o size=1kilobyte TEST_DIR/t.qcow2
@@ -113,7 +113,7 @@
and exabytes, respectively.
qemu-img create -f qcow2 TEST_DIR/t.qcow2 -- foobar
-qemu-img: Invalid image size specified! You may use k, M, G, T, P or E suffixes for
+qemu-img: Invalid image size specified. You may use k, M, G, T, P or E suffixes for
qemu-img: kilobytes, megabytes, gigabytes, terabytes, petabytes and exabytes.
qemu-img create -f qcow2 -o size=foobar TEST_DIR/t.qcow2
@@ -129,84 +129,84 @@
== Check correct interpretation of suffixes for cluster size ==
qemu-img create -f qcow2 -o cluster_size=1024 TEST_DIR/t.qcow2 64M
-Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=67108864 cluster_size=1024 lazy_refcounts=off refcount_bits=16
+Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=67108864 cluster_size=1024 lazy_refcounts=off refcount_bits=16 compression_type=zlib
qemu-img create -f qcow2 -o cluster_size=1024b TEST_DIR/t.qcow2 64M
-Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=67108864 cluster_size=1024 lazy_refcounts=off refcount_bits=16
+Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=67108864 cluster_size=1024 lazy_refcounts=off refcount_bits=16 compression_type=zlib
qemu-img create -f qcow2 -o cluster_size=1k TEST_DIR/t.qcow2 64M
-Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=67108864 cluster_size=1024 lazy_refcounts=off refcount_bits=16
+Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=67108864 cluster_size=1024 lazy_refcounts=off refcount_bits=16 compression_type=zlib
qemu-img create -f qcow2 -o cluster_size=1K TEST_DIR/t.qcow2 64M
-Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=67108864 cluster_size=1024 lazy_refcounts=off refcount_bits=16
+Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=67108864 cluster_size=1024 lazy_refcounts=off refcount_bits=16 compression_type=zlib
qemu-img create -f qcow2 -o cluster_size=1M TEST_DIR/t.qcow2 64M
-Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=67108864 cluster_size=1048576 lazy_refcounts=off refcount_bits=16
+Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=67108864 cluster_size=1048576 lazy_refcounts=off refcount_bits=16 compression_type=zlib
qemu-img create -f qcow2 -o cluster_size=1024.0 TEST_DIR/t.qcow2 64M
-Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=67108864 cluster_size=1024 lazy_refcounts=off refcount_bits=16
+Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=67108864 cluster_size=1024 lazy_refcounts=off refcount_bits=16 compression_type=zlib
qemu-img create -f qcow2 -o cluster_size=1024.0b TEST_DIR/t.qcow2 64M
-Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=67108864 cluster_size=1024 lazy_refcounts=off refcount_bits=16
+Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=67108864 cluster_size=1024 lazy_refcounts=off refcount_bits=16 compression_type=zlib
qemu-img create -f qcow2 -o cluster_size=0.5k TEST_DIR/t.qcow2 64M
-Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=67108864 cluster_size=512 lazy_refcounts=off refcount_bits=16
+Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=67108864 cluster_size=512 lazy_refcounts=off refcount_bits=16 compression_type=zlib
qemu-img create -f qcow2 -o cluster_size=0.5K TEST_DIR/t.qcow2 64M
-Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=67108864 cluster_size=512 lazy_refcounts=off refcount_bits=16
+Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=67108864 cluster_size=512 lazy_refcounts=off refcount_bits=16 compression_type=zlib
qemu-img create -f qcow2 -o cluster_size=0.5M TEST_DIR/t.qcow2 64M
-Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=67108864 cluster_size=524288 lazy_refcounts=off refcount_bits=16
+Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=67108864 cluster_size=524288 lazy_refcounts=off refcount_bits=16 compression_type=zlib
== Check compat level option ==
qemu-img create -f qcow2 -o compat=0.10 TEST_DIR/t.qcow2 64M
-Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=67108864 compat=0.10 cluster_size=65536 lazy_refcounts=off refcount_bits=16
+Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=67108864 compat=0.10 cluster_size=65536 lazy_refcounts=off refcount_bits=16 compression_type=zlib
qemu-img create -f qcow2 -o compat=1.1 TEST_DIR/t.qcow2 64M
-Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=67108864 compat=1.1 cluster_size=65536 lazy_refcounts=off refcount_bits=16
+Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=67108864 compat=1.1 cluster_size=65536 lazy_refcounts=off refcount_bits=16 compression_type=zlib
qemu-img create -f qcow2 -o compat=0.42 TEST_DIR/t.qcow2 64M
qemu-img: TEST_DIR/t.qcow2: Invalid parameter '0.42'
-Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=67108864 compat=0.42 cluster_size=65536 lazy_refcounts=off refcount_bits=16
+Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=67108864 compat=0.42 cluster_size=65536 lazy_refcounts=off refcount_bits=16 compression_type=zlib
qemu-img create -f qcow2 -o compat=foobar TEST_DIR/t.qcow2 64M
qemu-img: TEST_DIR/t.qcow2: Invalid parameter 'foobar'
-Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=67108864 compat=foobar cluster_size=65536 lazy_refcounts=off refcount_bits=16
+Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=67108864 compat=foobar cluster_size=65536 lazy_refcounts=off refcount_bits=16 compression_type=zlib
== Check preallocation option ==
qemu-img create -f qcow2 -o preallocation=off TEST_DIR/t.qcow2 64M
-Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=67108864 cluster_size=65536 preallocation=off lazy_refcounts=off refcount_bits=16
+Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=67108864 cluster_size=65536 preallocation=off lazy_refcounts=off refcount_bits=16 compression_type=zlib
qemu-img create -f qcow2 -o preallocation=metadata TEST_DIR/t.qcow2 64M
-Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=67108864 cluster_size=65536 preallocation=metadata lazy_refcounts=off refcount_bits=16
+Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=67108864 cluster_size=65536 preallocation=metadata lazy_refcounts=off refcount_bits=16 compression_type=zlib
qemu-img create -f qcow2 -o preallocation=1234 TEST_DIR/t.qcow2 64M
qemu-img: TEST_DIR/t.qcow2: Invalid parameter '1234'
-Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=67108864 cluster_size=65536 preallocation=1234 lazy_refcounts=off refcount_bits=16
+Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=67108864 cluster_size=65536 preallocation=1234 lazy_refcounts=off refcount_bits=16 compression_type=zlib
== Check encryption option ==
qemu-img create -f qcow2 -o encryption=off TEST_DIR/t.qcow2 64M
-Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=67108864 encryption=off cluster_size=65536 lazy_refcounts=off refcount_bits=16
+Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=67108864 encryption=off cluster_size=65536 lazy_refcounts=off refcount_bits=16 compression_type=zlib
qemu-img create -f qcow2 --object secret,id=sec0,data=123456 -o encryption=on,encrypt.key-secret=sec0 TEST_DIR/t.qcow2 64M
-Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=67108864 encryption=on encrypt.key-secret=sec0 cluster_size=65536 lazy_refcounts=off refcount_bits=16
+Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=67108864 encryption=on encrypt.key-secret=sec0 cluster_size=65536 lazy_refcounts=off refcount_bits=16 compression_type=zlib
== Check lazy_refcounts option (only with v3) ==
qemu-img create -f qcow2 -o compat=1.1,lazy_refcounts=off TEST_DIR/t.qcow2 64M
-Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=67108864 compat=1.1 cluster_size=65536 lazy_refcounts=off refcount_bits=16
+Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=67108864 compat=1.1 cluster_size=65536 lazy_refcounts=off refcount_bits=16 compression_type=zlib
qemu-img create -f qcow2 -o compat=1.1,lazy_refcounts=on TEST_DIR/t.qcow2 64M
-Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=67108864 compat=1.1 cluster_size=65536 lazy_refcounts=on refcount_bits=16
+Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=67108864 compat=1.1 cluster_size=65536 lazy_refcounts=on refcount_bits=16 compression_type=zlib
qemu-img create -f qcow2 -o compat=0.10,lazy_refcounts=off TEST_DIR/t.qcow2 64M
-Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=67108864 compat=0.10 cluster_size=65536 lazy_refcounts=off refcount_bits=16
+Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=67108864 compat=0.10 cluster_size=65536 lazy_refcounts=off refcount_bits=16 compression_type=zlib
qemu-img create -f qcow2 -o compat=0.10,lazy_refcounts=on TEST_DIR/t.qcow2 64M
qemu-img: TEST_DIR/t.qcow2: Lazy refcounts only supported with compatibility level 1.1 and above (use version=v3 or greater)
-Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=67108864 compat=0.10 cluster_size=65536 lazy_refcounts=on refcount_bits=16
+Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=67108864 compat=0.10 cluster_size=65536 lazy_refcounts=on refcount_bits=16 compression_type=zlib
*** done
diff --git a/tests/qemu-iotests/060.out b/tests/qemu-iotests/060.out
index 09caaea..be5f870 100644
--- a/tests/qemu-iotests/060.out
+++ b/tests/qemu-iotests/060.out
@@ -17,6 +17,7 @@
cluster_size: 65536
Format specific information:
compat: 1.1
+ compression type: zlib
lazy refcounts: false
refcount bits: 16
corrupt: true
diff --git a/tests/qemu-iotests/061.out b/tests/qemu-iotests/061.out
index 5a8d36d..a51ad1b 100644
--- a/tests/qemu-iotests/061.out
+++ b/tests/qemu-iotests/061.out
Binary files differ
diff --git a/tests/qemu-iotests/065 b/tests/qemu-iotests/065
index 6426474..18dc488 100755
--- a/tests/qemu-iotests/065
+++ b/tests/qemu-iotests/065
@@ -88,24 +88,30 @@
class TestQCow2(TestQemuImgInfo):
'''Testing a qcow2 version 2 image'''
img_options = 'compat=0.10'
- json_compare = { 'compat': '0.10', 'refcount-bits': 16 }
- human_compare = [ 'compat: 0.10', 'refcount bits: 16' ]
+ json_compare = { 'compat': '0.10', 'refcount-bits': 16,
+ 'compression-type': 'zlib' }
+ human_compare = [ 'compat: 0.10', 'compression type: zlib',
+ 'refcount bits: 16' ]
class TestQCow3NotLazy(TestQemuImgInfo):
'''Testing a qcow2 version 3 image with lazy refcounts disabled'''
img_options = 'compat=1.1,lazy_refcounts=off'
json_compare = { 'compat': '1.1', 'lazy-refcounts': False,
- 'refcount-bits': 16, 'corrupt': False }
- human_compare = [ 'compat: 1.1', 'lazy refcounts: false',
- 'refcount bits: 16', 'corrupt: false' ]
+ 'refcount-bits': 16, 'corrupt': False,
+ 'compression-type': 'zlib' }
+ human_compare = [ 'compat: 1.1', 'compression type: zlib',
+ 'lazy refcounts: false', 'refcount bits: 16',
+ 'corrupt: false' ]
class TestQCow3Lazy(TestQemuImgInfo):
'''Testing a qcow2 version 3 image with lazy refcounts enabled'''
img_options = 'compat=1.1,lazy_refcounts=on'
json_compare = { 'compat': '1.1', 'lazy-refcounts': True,
- 'refcount-bits': 16, 'corrupt': False }
- human_compare = [ 'compat: 1.1', 'lazy refcounts: true',
- 'refcount bits: 16', 'corrupt: false' ]
+ 'refcount-bits': 16, 'corrupt': False,
+ 'compression-type': 'zlib' }
+ human_compare = [ 'compat: 1.1', 'compression type: zlib',
+ 'lazy refcounts: true', 'refcount bits: 16',
+ 'corrupt: false' ]
class TestQCow3NotLazyQMP(TestQMP):
'''Testing a qcow2 version 3 image with lazy refcounts disabled, opening
@@ -113,7 +119,8 @@
img_options = 'compat=1.1,lazy_refcounts=off'
qemu_options = 'lazy-refcounts=on'
compare = { 'compat': '1.1', 'lazy-refcounts': False,
- 'refcount-bits': 16, 'corrupt': False }
+ 'refcount-bits': 16, 'corrupt': False,
+ 'compression-type': 'zlib' }
class TestQCow3LazyQMP(TestQMP):
@@ -122,7 +129,8 @@
img_options = 'compat=1.1,lazy_refcounts=on'
qemu_options = 'lazy-refcounts=off'
compare = { 'compat': '1.1', 'lazy-refcounts': True,
- 'refcount-bits': 16, 'corrupt': False }
+ 'refcount-bits': 16, 'corrupt': False,
+ 'compression-type': 'zlib' }
TestImageInfoSpecific = None
TestQemuImgInfo = None
diff --git a/tests/qemu-iotests/080 b/tests/qemu-iotests/080
index a3d13c4..7588c63 100755
--- a/tests/qemu-iotests/080
+++ b/tests/qemu-iotests/080
@@ -45,7 +45,7 @@
# - This is generally a test for compat=1.1 images
_unsupported_imgopts 'refcount_bits=1[^0-9]' data_file 'compat=0.10'
-header_size=104
+header_size=112
offset_backing_file_offset=8
offset_backing_file_size=16
diff --git a/tests/qemu-iotests/082.out b/tests/qemu-iotests/082.out
index 9d4ed4d..529a121 100644
--- a/tests/qemu-iotests/082.out
+++ b/tests/qemu-iotests/082.out
@@ -3,38 +3,40 @@
=== create: Options specified more than once ===
Testing: create -f foo -f qcow2 TEST_DIR/t.qcow2 128M
-Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=134217728 cluster_size=65536 lazy_refcounts=off refcount_bits=16
+Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=134217728 cluster_size=65536 lazy_refcounts=off refcount_bits=16 compression_type=zlib
image: TEST_DIR/t.IMGFMT
file format: IMGFMT
virtual size: 128 MiB (134217728 bytes)
cluster_size: 65536
Testing: create -f qcow2 -o cluster_size=4k -o lazy_refcounts=on TEST_DIR/t.qcow2 128M
-Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=134217728 cluster_size=4096 lazy_refcounts=on refcount_bits=16
+Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=134217728 cluster_size=4096 lazy_refcounts=on refcount_bits=16 compression_type=zlib
image: TEST_DIR/t.IMGFMT
file format: IMGFMT
virtual size: 128 MiB (134217728 bytes)
cluster_size: 4096
Format specific information:
compat: 1.1
+ compression type: zlib
lazy refcounts: true
refcount bits: 16
corrupt: false
Testing: create -f qcow2 -o cluster_size=4k -o lazy_refcounts=on -o cluster_size=8k TEST_DIR/t.qcow2 128M
-Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=134217728 cluster_size=8192 lazy_refcounts=on refcount_bits=16
+Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=134217728 cluster_size=8192 lazy_refcounts=on refcount_bits=16 compression_type=zlib
image: TEST_DIR/t.IMGFMT
file format: IMGFMT
virtual size: 128 MiB (134217728 bytes)
cluster_size: 8192
Format specific information:
compat: 1.1
+ compression type: zlib
lazy refcounts: true
refcount bits: 16
corrupt: false
Testing: create -f qcow2 -o cluster_size=4k,cluster_size=8k TEST_DIR/t.qcow2 128M
-Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=134217728 cluster_size=8192 lazy_refcounts=off refcount_bits=16
+Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=134217728 cluster_size=8192 lazy_refcounts=off refcount_bits=16 compression_type=zlib
image: TEST_DIR/t.IMGFMT
file format: IMGFMT
virtual size: 128 MiB (134217728 bytes)
@@ -48,6 +50,7 @@
backing_fmt=<str> - Image format of the base image
cluster_size=<size> - qcow2 cluster size
compat=<str> - Compatibility level (v2 [0.10] or v3 [1.1])
+ compression_type=<str> - Compression method used for image cluster compression
data_file=<str> - File name of an external data file
data_file_raw=<bool (on/off)> - The external data file must stay valid as a raw image
encrypt.cipher-alg=<str> - Name of encryption cipher algorithm
@@ -71,6 +74,7 @@
backing_fmt=<str> - Image format of the base image
cluster_size=<size> - qcow2 cluster size
compat=<str> - Compatibility level (v2 [0.10] or v3 [1.1])
+ compression_type=<str> - Compression method used for image cluster compression
data_file=<str> - File name of an external data file
data_file_raw=<bool (on/off)> - The external data file must stay valid as a raw image
encrypt.cipher-alg=<str> - Name of encryption cipher algorithm
@@ -94,6 +98,7 @@
backing_fmt=<str> - Image format of the base image
cluster_size=<size> - qcow2 cluster size
compat=<str> - Compatibility level (v2 [0.10] or v3 [1.1])
+ compression_type=<str> - Compression method used for image cluster compression
data_file=<str> - File name of an external data file
data_file_raw=<bool (on/off)> - The external data file must stay valid as a raw image
encrypt.cipher-alg=<str> - Name of encryption cipher algorithm
@@ -117,6 +122,7 @@
backing_fmt=<str> - Image format of the base image
cluster_size=<size> - qcow2 cluster size
compat=<str> - Compatibility level (v2 [0.10] or v3 [1.1])
+ compression_type=<str> - Compression method used for image cluster compression
data_file=<str> - File name of an external data file
data_file_raw=<bool (on/off)> - The external data file must stay valid as a raw image
encrypt.cipher-alg=<str> - Name of encryption cipher algorithm
@@ -140,6 +146,7 @@
backing_fmt=<str> - Image format of the base image
cluster_size=<size> - qcow2 cluster size
compat=<str> - Compatibility level (v2 [0.10] or v3 [1.1])
+ compression_type=<str> - Compression method used for image cluster compression
data_file=<str> - File name of an external data file
data_file_raw=<bool (on/off)> - The external data file must stay valid as a raw image
encrypt.cipher-alg=<str> - Name of encryption cipher algorithm
@@ -163,6 +170,7 @@
backing_fmt=<str> - Image format of the base image
cluster_size=<size> - qcow2 cluster size
compat=<str> - Compatibility level (v2 [0.10] or v3 [1.1])
+ compression_type=<str> - Compression method used for image cluster compression
data_file=<str> - File name of an external data file
data_file_raw=<bool (on/off)> - The external data file must stay valid as a raw image
encrypt.cipher-alg=<str> - Name of encryption cipher algorithm
@@ -186,6 +194,7 @@
backing_fmt=<str> - Image format of the base image
cluster_size=<size> - qcow2 cluster size
compat=<str> - Compatibility level (v2 [0.10] or v3 [1.1])
+ compression_type=<str> - Compression method used for image cluster compression
data_file=<str> - File name of an external data file
data_file_raw=<bool (on/off)> - The external data file must stay valid as a raw image
encrypt.cipher-alg=<str> - Name of encryption cipher algorithm
@@ -209,6 +218,7 @@
backing_fmt=<str> - Image format of the base image
cluster_size=<size> - qcow2 cluster size
compat=<str> - Compatibility level (v2 [0.10] or v3 [1.1])
+ compression_type=<str> - Compression method used for image cluster compression
data_file=<str> - File name of an external data file
data_file_raw=<bool (on/off)> - The external data file must stay valid as a raw image
encrypt.cipher-alg=<str> - Name of encryption cipher algorithm
@@ -227,10 +237,10 @@
size=<size> - Virtual disk size
Testing: create -f qcow2 -u -o backing_file=TEST_DIR/t.qcow2,,help TEST_DIR/t.qcow2 128M
-Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=134217728 backing_file=TEST_DIR/t.qcow2,,help cluster_size=65536 lazy_refcounts=off refcount_bits=16
+Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=134217728 backing_file=TEST_DIR/t.qcow2,,help cluster_size=65536 lazy_refcounts=off refcount_bits=16 compression_type=zlib
Testing: create -f qcow2 -u -o backing_file=TEST_DIR/t.qcow2,,? TEST_DIR/t.qcow2 128M
-Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=134217728 backing_file=TEST_DIR/t.qcow2,,? cluster_size=65536 lazy_refcounts=off refcount_bits=16
+Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=134217728 backing_file=TEST_DIR/t.qcow2,,? cluster_size=65536 lazy_refcounts=off refcount_bits=16 compression_type=zlib
Testing: create -f qcow2 -o backing_file=TEST_DIR/t.qcow2, -o help TEST_DIR/t.qcow2 128M
qemu-img: Invalid option list: backing_file=TEST_DIR/t.qcow2,
@@ -247,6 +257,7 @@
backing_fmt=<str> - Image format of the base image
cluster_size=<size> - qcow2 cluster size
compat=<str> - Compatibility level (v2 [0.10] or v3 [1.1])
+ compression_type=<str> - Compression method used for image cluster compression
data_file=<str> - File name of an external data file
data_file_raw=<bool (on/off)> - The external data file must stay valid as a raw image
encrypt.cipher-alg=<str> - Name of encryption cipher algorithm
@@ -279,7 +290,7 @@
=== convert: Options specified more than once ===
Testing: create -f qcow2 TEST_DIR/t.qcow2 128M
-Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=134217728 cluster_size=65536 lazy_refcounts=off refcount_bits=16
+Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=134217728 cluster_size=65536 lazy_refcounts=off refcount_bits=16 compression_type=zlib
Testing: convert -f foo -f qcow2 TEST_DIR/t.qcow2 TEST_DIR/t.qcow2.base
image: TEST_DIR/t.IMGFMT.base
@@ -299,6 +310,7 @@
cluster_size: 4096
Format specific information:
compat: 1.1
+ compression type: zlib
lazy refcounts: true
refcount bits: 16
corrupt: false
@@ -310,6 +322,7 @@
cluster_size: 8192
Format specific information:
compat: 1.1
+ compression type: zlib
lazy refcounts: true
refcount bits: 16
corrupt: false
@@ -328,6 +341,7 @@
backing_fmt=<str> - Image format of the base image
cluster_size=<size> - qcow2 cluster size
compat=<str> - Compatibility level (v2 [0.10] or v3 [1.1])
+ compression_type=<str> - Compression method used for image cluster compression
data_file=<str> - File name of an external data file
data_file_raw=<bool (on/off)> - The external data file must stay valid as a raw image
encrypt.cipher-alg=<str> - Name of encryption cipher algorithm
@@ -351,6 +365,7 @@
backing_fmt=<str> - Image format of the base image
cluster_size=<size> - qcow2 cluster size
compat=<str> - Compatibility level (v2 [0.10] or v3 [1.1])
+ compression_type=<str> - Compression method used for image cluster compression
data_file=<str> - File name of an external data file
data_file_raw=<bool (on/off)> - The external data file must stay valid as a raw image
encrypt.cipher-alg=<str> - Name of encryption cipher algorithm
@@ -374,6 +389,7 @@
backing_fmt=<str> - Image format of the base image
cluster_size=<size> - qcow2 cluster size
compat=<str> - Compatibility level (v2 [0.10] or v3 [1.1])
+ compression_type=<str> - Compression method used for image cluster compression
data_file=<str> - File name of an external data file
data_file_raw=<bool (on/off)> - The external data file must stay valid as a raw image
encrypt.cipher-alg=<str> - Name of encryption cipher algorithm
@@ -397,6 +413,7 @@
backing_fmt=<str> - Image format of the base image
cluster_size=<size> - qcow2 cluster size
compat=<str> - Compatibility level (v2 [0.10] or v3 [1.1])
+ compression_type=<str> - Compression method used for image cluster compression
data_file=<str> - File name of an external data file
data_file_raw=<bool (on/off)> - The external data file must stay valid as a raw image
encrypt.cipher-alg=<str> - Name of encryption cipher algorithm
@@ -420,6 +437,7 @@
backing_fmt=<str> - Image format of the base image
cluster_size=<size> - qcow2 cluster size
compat=<str> - Compatibility level (v2 [0.10] or v3 [1.1])
+ compression_type=<str> - Compression method used for image cluster compression
data_file=<str> - File name of an external data file
data_file_raw=<bool (on/off)> - The external data file must stay valid as a raw image
encrypt.cipher-alg=<str> - Name of encryption cipher algorithm
@@ -443,6 +461,7 @@
backing_fmt=<str> - Image format of the base image
cluster_size=<size> - qcow2 cluster size
compat=<str> - Compatibility level (v2 [0.10] or v3 [1.1])
+ compression_type=<str> - Compression method used for image cluster compression
data_file=<str> - File name of an external data file
data_file_raw=<bool (on/off)> - The external data file must stay valid as a raw image
encrypt.cipher-alg=<str> - Name of encryption cipher algorithm
@@ -466,6 +485,7 @@
backing_fmt=<str> - Image format of the base image
cluster_size=<size> - qcow2 cluster size
compat=<str> - Compatibility level (v2 [0.10] or v3 [1.1])
+ compression_type=<str> - Compression method used for image cluster compression
data_file=<str> - File name of an external data file
data_file_raw=<bool (on/off)> - The external data file must stay valid as a raw image
encrypt.cipher-alg=<str> - Name of encryption cipher algorithm
@@ -489,6 +509,7 @@
backing_fmt=<str> - Image format of the base image
cluster_size=<size> - qcow2 cluster size
compat=<str> - Compatibility level (v2 [0.10] or v3 [1.1])
+ compression_type=<str> - Compression method used for image cluster compression
data_file=<str> - File name of an external data file
data_file_raw=<bool (on/off)> - The external data file must stay valid as a raw image
encrypt.cipher-alg=<str> - Name of encryption cipher algorithm
@@ -527,6 +548,7 @@
backing_fmt=<str> - Image format of the base image
cluster_size=<size> - qcow2 cluster size
compat=<str> - Compatibility level (v2 [0.10] or v3 [1.1])
+ compression_type=<str> - Compression method used for image cluster compression
data_file=<str> - File name of an external data file
data_file_raw=<bool (on/off)> - The external data file must stay valid as a raw image
encrypt.cipher-alg=<str> - Name of encryption cipher algorithm
@@ -579,6 +601,7 @@
cluster_size: 65536
Format specific information:
compat: 1.1
+ compression type: zlib
lazy refcounts: true
refcount bits: 16
corrupt: false
@@ -590,6 +613,7 @@
cluster_size: 65536
Format specific information:
compat: 1.1
+ compression type: zlib
lazy refcounts: false
refcount bits: 16
corrupt: false
@@ -601,6 +625,7 @@
cluster_size: 65536
Format specific information:
compat: 1.1
+ compression type: zlib
lazy refcounts: true
refcount bits: 16
corrupt: false
@@ -619,6 +644,7 @@
backing_fmt=<str> - Image format of the base image
cluster_size=<size> - qcow2 cluster size
compat=<str> - Compatibility level (v2 [0.10] or v3 [1.1])
+ compression_type=<str> - Compression method used for image cluster compression
data_file=<str> - File name of an external data file
data_file_raw=<bool (on/off)> - The external data file must stay valid as a raw image
encrypt.cipher-alg=<str> - Name of encryption cipher algorithm
@@ -643,6 +669,7 @@
backing_fmt=<str> - Image format of the base image
cluster_size=<size> - qcow2 cluster size
compat=<str> - Compatibility level (v2 [0.10] or v3 [1.1])
+ compression_type=<str> - Compression method used for image cluster compression
data_file=<str> - File name of an external data file
data_file_raw=<bool (on/off)> - The external data file must stay valid as a raw image
encrypt.cipher-alg=<str> - Name of encryption cipher algorithm
@@ -667,6 +694,7 @@
backing_fmt=<str> - Image format of the base image
cluster_size=<size> - qcow2 cluster size
compat=<str> - Compatibility level (v2 [0.10] or v3 [1.1])
+ compression_type=<str> - Compression method used for image cluster compression
data_file=<str> - File name of an external data file
data_file_raw=<bool (on/off)> - The external data file must stay valid as a raw image
encrypt.cipher-alg=<str> - Name of encryption cipher algorithm
@@ -691,6 +719,7 @@
backing_fmt=<str> - Image format of the base image
cluster_size=<size> - qcow2 cluster size
compat=<str> - Compatibility level (v2 [0.10] or v3 [1.1])
+ compression_type=<str> - Compression method used for image cluster compression
data_file=<str> - File name of an external data file
data_file_raw=<bool (on/off)> - The external data file must stay valid as a raw image
encrypt.cipher-alg=<str> - Name of encryption cipher algorithm
@@ -715,6 +744,7 @@
backing_fmt=<str> - Image format of the base image
cluster_size=<size> - qcow2 cluster size
compat=<str> - Compatibility level (v2 [0.10] or v3 [1.1])
+ compression_type=<str> - Compression method used for image cluster compression
data_file=<str> - File name of an external data file
data_file_raw=<bool (on/off)> - The external data file must stay valid as a raw image
encrypt.cipher-alg=<str> - Name of encryption cipher algorithm
@@ -739,6 +769,7 @@
backing_fmt=<str> - Image format of the base image
cluster_size=<size> - qcow2 cluster size
compat=<str> - Compatibility level (v2 [0.10] or v3 [1.1])
+ compression_type=<str> - Compression method used for image cluster compression
data_file=<str> - File name of an external data file
data_file_raw=<bool (on/off)> - The external data file must stay valid as a raw image
encrypt.cipher-alg=<str> - Name of encryption cipher algorithm
@@ -763,6 +794,7 @@
backing_fmt=<str> - Image format of the base image
cluster_size=<size> - qcow2 cluster size
compat=<str> - Compatibility level (v2 [0.10] or v3 [1.1])
+ compression_type=<str> - Compression method used for image cluster compression
data_file=<str> - File name of an external data file
data_file_raw=<bool (on/off)> - The external data file must stay valid as a raw image
encrypt.cipher-alg=<str> - Name of encryption cipher algorithm
@@ -787,6 +819,7 @@
backing_fmt=<str> - Image format of the base image
cluster_size=<size> - qcow2 cluster size
compat=<str> - Compatibility level (v2 [0.10] or v3 [1.1])
+ compression_type=<str> - Compression method used for image cluster compression
data_file=<str> - File name of an external data file
data_file_raw=<bool (on/off)> - The external data file must stay valid as a raw image
encrypt.cipher-alg=<str> - Name of encryption cipher algorithm
@@ -828,6 +861,7 @@
backing_fmt=<str> - Image format of the base image
cluster_size=<size> - qcow2 cluster size
compat=<str> - Compatibility level (v2 [0.10] or v3 [1.1])
+ compression_type=<str> - Compression method used for image cluster compression
data_file=<str> - File name of an external data file
data_file_raw=<bool (on/off)> - The external data file must stay valid as a raw image
encrypt.cipher-alg=<str> - Name of encryption cipher algorithm
diff --git a/tests/qemu-iotests/085.out b/tests/qemu-iotests/085.out
index fd11aae..a822ff4 100644
--- a/tests/qemu-iotests/085.out
+++ b/tests/qemu-iotests/085.out
@@ -13,7 +13,7 @@
=== Create a single snapshot on virtio0 ===
{ 'execute': 'blockdev-snapshot-sync', 'arguments': { 'device': 'virtio0', 'snapshot-file':'TEST_DIR/1-snapshot-v0.IMGFMT', 'format': 'IMGFMT' } }
-Formatting 'TEST_DIR/1-snapshot-v0.qcow2', fmt=qcow2 size=134217728 backing_file=TEST_DIR/t.qcow2.1 backing_fmt=qcow2 cluster_size=65536 lazy_refcounts=off refcount_bits=16
+Formatting 'TEST_DIR/1-snapshot-v0.qcow2', fmt=qcow2 size=134217728 backing_file=TEST_DIR/t.qcow2.1 backing_fmt=qcow2 cluster_size=65536 lazy_refcounts=off refcount_bits=16 compression_type=zlib
{"return": {}}
=== Invalid command - missing device and nodename ===
@@ -30,40 +30,40 @@
=== Create several transactional group snapshots ===
{ 'execute': 'transaction', 'arguments': {'actions': [ { 'type': 'blockdev-snapshot-sync', 'data' : { 'device': 'virtio0', 'snapshot-file': 'TEST_DIR/2-snapshot-v0.IMGFMT' } }, { 'type': 'blockdev-snapshot-sync', 'data' : { 'device': 'virtio1', 'snapshot-file': 'TEST_DIR/2-snapshot-v1.IMGFMT' } } ] } }
-Formatting 'TEST_DIR/2-snapshot-v0.qcow2', fmt=qcow2 size=134217728 backing_file=TEST_DIR/1-snapshot-v0.qcow2 backing_fmt=qcow2 cluster_size=65536 lazy_refcounts=off refcount_bits=16
-Formatting 'TEST_DIR/2-snapshot-v1.qcow2', fmt=qcow2 size=134217728 backing_file=TEST_DIR/t.qcow2.2 backing_fmt=qcow2 cluster_size=65536 lazy_refcounts=off refcount_bits=16
+Formatting 'TEST_DIR/2-snapshot-v0.qcow2', fmt=qcow2 size=134217728 backing_file=TEST_DIR/1-snapshot-v0.qcow2 backing_fmt=qcow2 cluster_size=65536 lazy_refcounts=off refcount_bits=16 compression_type=zlib
+Formatting 'TEST_DIR/2-snapshot-v1.qcow2', fmt=qcow2 size=134217728 backing_file=TEST_DIR/t.qcow2.2 backing_fmt=qcow2 cluster_size=65536 lazy_refcounts=off refcount_bits=16 compression_type=zlib
{"return": {}}
{ 'execute': 'transaction', 'arguments': {'actions': [ { 'type': 'blockdev-snapshot-sync', 'data' : { 'device': 'virtio0', 'snapshot-file': 'TEST_DIR/3-snapshot-v0.IMGFMT' } }, { 'type': 'blockdev-snapshot-sync', 'data' : { 'device': 'virtio1', 'snapshot-file': 'TEST_DIR/3-snapshot-v1.IMGFMT' } } ] } }
-Formatting 'TEST_DIR/3-snapshot-v0.qcow2', fmt=qcow2 size=134217728 backing_file=TEST_DIR/2-snapshot-v0.qcow2 backing_fmt=qcow2 cluster_size=65536 lazy_refcounts=off refcount_bits=16
-Formatting 'TEST_DIR/3-snapshot-v1.qcow2', fmt=qcow2 size=134217728 backing_file=TEST_DIR/2-snapshot-v1.qcow2 backing_fmt=qcow2 cluster_size=65536 lazy_refcounts=off refcount_bits=16
+Formatting 'TEST_DIR/3-snapshot-v0.qcow2', fmt=qcow2 size=134217728 backing_file=TEST_DIR/2-snapshot-v0.qcow2 backing_fmt=qcow2 cluster_size=65536 lazy_refcounts=off refcount_bits=16 compression_type=zlib
+Formatting 'TEST_DIR/3-snapshot-v1.qcow2', fmt=qcow2 size=134217728 backing_file=TEST_DIR/2-snapshot-v1.qcow2 backing_fmt=qcow2 cluster_size=65536 lazy_refcounts=off refcount_bits=16 compression_type=zlib
{"return": {}}
{ 'execute': 'transaction', 'arguments': {'actions': [ { 'type': 'blockdev-snapshot-sync', 'data' : { 'device': 'virtio0', 'snapshot-file': 'TEST_DIR/4-snapshot-v0.IMGFMT' } }, { 'type': 'blockdev-snapshot-sync', 'data' : { 'device': 'virtio1', 'snapshot-file': 'TEST_DIR/4-snapshot-v1.IMGFMT' } } ] } }
-Formatting 'TEST_DIR/4-snapshot-v0.qcow2', fmt=qcow2 size=134217728 backing_file=TEST_DIR/3-snapshot-v0.qcow2 backing_fmt=qcow2 cluster_size=65536 lazy_refcounts=off refcount_bits=16
-Formatting 'TEST_DIR/4-snapshot-v1.qcow2', fmt=qcow2 size=134217728 backing_file=TEST_DIR/3-snapshot-v1.qcow2 backing_fmt=qcow2 cluster_size=65536 lazy_refcounts=off refcount_bits=16
+Formatting 'TEST_DIR/4-snapshot-v0.qcow2', fmt=qcow2 size=134217728 backing_file=TEST_DIR/3-snapshot-v0.qcow2 backing_fmt=qcow2 cluster_size=65536 lazy_refcounts=off refcount_bits=16 compression_type=zlib
+Formatting 'TEST_DIR/4-snapshot-v1.qcow2', fmt=qcow2 size=134217728 backing_file=TEST_DIR/3-snapshot-v1.qcow2 backing_fmt=qcow2 cluster_size=65536 lazy_refcounts=off refcount_bits=16 compression_type=zlib
{"return": {}}
{ 'execute': 'transaction', 'arguments': {'actions': [ { 'type': 'blockdev-snapshot-sync', 'data' : { 'device': 'virtio0', 'snapshot-file': 'TEST_DIR/5-snapshot-v0.IMGFMT' } }, { 'type': 'blockdev-snapshot-sync', 'data' : { 'device': 'virtio1', 'snapshot-file': 'TEST_DIR/5-snapshot-v1.IMGFMT' } } ] } }
-Formatting 'TEST_DIR/5-snapshot-v0.qcow2', fmt=qcow2 size=134217728 backing_file=TEST_DIR/4-snapshot-v0.qcow2 backing_fmt=qcow2 cluster_size=65536 lazy_refcounts=off refcount_bits=16
-Formatting 'TEST_DIR/5-snapshot-v1.qcow2', fmt=qcow2 size=134217728 backing_file=TEST_DIR/4-snapshot-v1.qcow2 backing_fmt=qcow2 cluster_size=65536 lazy_refcounts=off refcount_bits=16
+Formatting 'TEST_DIR/5-snapshot-v0.qcow2', fmt=qcow2 size=134217728 backing_file=TEST_DIR/4-snapshot-v0.qcow2 backing_fmt=qcow2 cluster_size=65536 lazy_refcounts=off refcount_bits=16 compression_type=zlib
+Formatting 'TEST_DIR/5-snapshot-v1.qcow2', fmt=qcow2 size=134217728 backing_file=TEST_DIR/4-snapshot-v1.qcow2 backing_fmt=qcow2 cluster_size=65536 lazy_refcounts=off refcount_bits=16 compression_type=zlib
{"return": {}}
{ 'execute': 'transaction', 'arguments': {'actions': [ { 'type': 'blockdev-snapshot-sync', 'data' : { 'device': 'virtio0', 'snapshot-file': 'TEST_DIR/6-snapshot-v0.IMGFMT' } }, { 'type': 'blockdev-snapshot-sync', 'data' : { 'device': 'virtio1', 'snapshot-file': 'TEST_DIR/6-snapshot-v1.IMGFMT' } } ] } }
-Formatting 'TEST_DIR/6-snapshot-v0.qcow2', fmt=qcow2 size=134217728 backing_file=TEST_DIR/5-snapshot-v0.qcow2 backing_fmt=qcow2 cluster_size=65536 lazy_refcounts=off refcount_bits=16
-Formatting 'TEST_DIR/6-snapshot-v1.qcow2', fmt=qcow2 size=134217728 backing_file=TEST_DIR/5-snapshot-v1.qcow2 backing_fmt=qcow2 cluster_size=65536 lazy_refcounts=off refcount_bits=16
+Formatting 'TEST_DIR/6-snapshot-v0.qcow2', fmt=qcow2 size=134217728 backing_file=TEST_DIR/5-snapshot-v0.qcow2 backing_fmt=qcow2 cluster_size=65536 lazy_refcounts=off refcount_bits=16 compression_type=zlib
+Formatting 'TEST_DIR/6-snapshot-v1.qcow2', fmt=qcow2 size=134217728 backing_file=TEST_DIR/5-snapshot-v1.qcow2 backing_fmt=qcow2 cluster_size=65536 lazy_refcounts=off refcount_bits=16 compression_type=zlib
{"return": {}}
{ 'execute': 'transaction', 'arguments': {'actions': [ { 'type': 'blockdev-snapshot-sync', 'data' : { 'device': 'virtio0', 'snapshot-file': 'TEST_DIR/7-snapshot-v0.IMGFMT' } }, { 'type': 'blockdev-snapshot-sync', 'data' : { 'device': 'virtio1', 'snapshot-file': 'TEST_DIR/7-snapshot-v1.IMGFMT' } } ] } }
-Formatting 'TEST_DIR/7-snapshot-v0.qcow2', fmt=qcow2 size=134217728 backing_file=TEST_DIR/6-snapshot-v0.qcow2 backing_fmt=qcow2 cluster_size=65536 lazy_refcounts=off refcount_bits=16
-Formatting 'TEST_DIR/7-snapshot-v1.qcow2', fmt=qcow2 size=134217728 backing_file=TEST_DIR/6-snapshot-v1.qcow2 backing_fmt=qcow2 cluster_size=65536 lazy_refcounts=off refcount_bits=16
+Formatting 'TEST_DIR/7-snapshot-v0.qcow2', fmt=qcow2 size=134217728 backing_file=TEST_DIR/6-snapshot-v0.qcow2 backing_fmt=qcow2 cluster_size=65536 lazy_refcounts=off refcount_bits=16 compression_type=zlib
+Formatting 'TEST_DIR/7-snapshot-v1.qcow2', fmt=qcow2 size=134217728 backing_file=TEST_DIR/6-snapshot-v1.qcow2 backing_fmt=qcow2 cluster_size=65536 lazy_refcounts=off refcount_bits=16 compression_type=zlib
{"return": {}}
{ 'execute': 'transaction', 'arguments': {'actions': [ { 'type': 'blockdev-snapshot-sync', 'data' : { 'device': 'virtio0', 'snapshot-file': 'TEST_DIR/8-snapshot-v0.IMGFMT' } }, { 'type': 'blockdev-snapshot-sync', 'data' : { 'device': 'virtio1', 'snapshot-file': 'TEST_DIR/8-snapshot-v1.IMGFMT' } } ] } }
-Formatting 'TEST_DIR/8-snapshot-v0.qcow2', fmt=qcow2 size=134217728 backing_file=TEST_DIR/7-snapshot-v0.qcow2 backing_fmt=qcow2 cluster_size=65536 lazy_refcounts=off refcount_bits=16
-Formatting 'TEST_DIR/8-snapshot-v1.qcow2', fmt=qcow2 size=134217728 backing_file=TEST_DIR/7-snapshot-v1.qcow2 backing_fmt=qcow2 cluster_size=65536 lazy_refcounts=off refcount_bits=16
+Formatting 'TEST_DIR/8-snapshot-v0.qcow2', fmt=qcow2 size=134217728 backing_file=TEST_DIR/7-snapshot-v0.qcow2 backing_fmt=qcow2 cluster_size=65536 lazy_refcounts=off refcount_bits=16 compression_type=zlib
+Formatting 'TEST_DIR/8-snapshot-v1.qcow2', fmt=qcow2 size=134217728 backing_file=TEST_DIR/7-snapshot-v1.qcow2 backing_fmt=qcow2 cluster_size=65536 lazy_refcounts=off refcount_bits=16 compression_type=zlib
{"return": {}}
{ 'execute': 'transaction', 'arguments': {'actions': [ { 'type': 'blockdev-snapshot-sync', 'data' : { 'device': 'virtio0', 'snapshot-file': 'TEST_DIR/9-snapshot-v0.IMGFMT' } }, { 'type': 'blockdev-snapshot-sync', 'data' : { 'device': 'virtio1', 'snapshot-file': 'TEST_DIR/9-snapshot-v1.IMGFMT' } } ] } }
-Formatting 'TEST_DIR/9-snapshot-v0.qcow2', fmt=qcow2 size=134217728 backing_file=TEST_DIR/8-snapshot-v0.qcow2 backing_fmt=qcow2 cluster_size=65536 lazy_refcounts=off refcount_bits=16
-Formatting 'TEST_DIR/9-snapshot-v1.qcow2', fmt=qcow2 size=134217728 backing_file=TEST_DIR/8-snapshot-v1.qcow2 backing_fmt=qcow2 cluster_size=65536 lazy_refcounts=off refcount_bits=16
+Formatting 'TEST_DIR/9-snapshot-v0.qcow2', fmt=qcow2 size=134217728 backing_file=TEST_DIR/8-snapshot-v0.qcow2 backing_fmt=qcow2 cluster_size=65536 lazy_refcounts=off refcount_bits=16 compression_type=zlib
+Formatting 'TEST_DIR/9-snapshot-v1.qcow2', fmt=qcow2 size=134217728 backing_file=TEST_DIR/8-snapshot-v1.qcow2 backing_fmt=qcow2 cluster_size=65536 lazy_refcounts=off refcount_bits=16 compression_type=zlib
{"return": {}}
{ 'execute': 'transaction', 'arguments': {'actions': [ { 'type': 'blockdev-snapshot-sync', 'data' : { 'device': 'virtio0', 'snapshot-file': 'TEST_DIR/10-snapshot-v0.IMGFMT' } }, { 'type': 'blockdev-snapshot-sync', 'data' : { 'device': 'virtio1', 'snapshot-file': 'TEST_DIR/10-snapshot-v1.IMGFMT' } } ] } }
-Formatting 'TEST_DIR/10-snapshot-v0.qcow2', fmt=qcow2 size=134217728 backing_file=TEST_DIR/9-snapshot-v0.qcow2 backing_fmt=qcow2 cluster_size=65536 lazy_refcounts=off refcount_bits=16
-Formatting 'TEST_DIR/10-snapshot-v1.qcow2', fmt=qcow2 size=134217728 backing_file=TEST_DIR/9-snapshot-v1.qcow2 backing_fmt=qcow2 cluster_size=65536 lazy_refcounts=off refcount_bits=16
+Formatting 'TEST_DIR/10-snapshot-v0.qcow2', fmt=qcow2 size=134217728 backing_file=TEST_DIR/9-snapshot-v0.qcow2 backing_fmt=qcow2 cluster_size=65536 lazy_refcounts=off refcount_bits=16 compression_type=zlib
+Formatting 'TEST_DIR/10-snapshot-v1.qcow2', fmt=qcow2 size=134217728 backing_file=TEST_DIR/9-snapshot-v1.qcow2 backing_fmt=qcow2 cluster_size=65536 lazy_refcounts=off refcount_bits=16 compression_type=zlib
{"return": {}}
=== Create a couple of snapshots using blockdev-snapshot ===
diff --git a/tests/qemu-iotests/098.out b/tests/qemu-iotests/098.out
index 7634d0e..23cf371 100644
--- a/tests/qemu-iotests/098.out
+++ b/tests/qemu-iotests/098.out
@@ -6,7 +6,7 @@
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 backing_file=TEST_DIR/t.IMGFMT.base
wrote 65536/65536 bytes at offset 0
64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
-qemu-img: Could not empty blkdebug:TEST_DIR/blkdebug.conf:TEST_DIR/t.IMGFMT: Input/output error
+qemu-img: Failed to empty blkdebug:TEST_DIR/blkdebug.conf:TEST_DIR/t.IMGFMT: Input/output error
No errors were found on the image.
=== empty_image_prepare ===
@@ -15,7 +15,7 @@
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 backing_file=TEST_DIR/t.IMGFMT.base
wrote 65536/65536 bytes at offset 0
64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
-qemu-img: Could not empty blkdebug:TEST_DIR/blkdebug.conf:TEST_DIR/t.IMGFMT: Input/output error
+qemu-img: Failed to empty blkdebug:TEST_DIR/blkdebug.conf:TEST_DIR/t.IMGFMT: Input/output error
Leaked cluster 4 refcount=1 reference=0
Leaked cluster 5 refcount=1 reference=0
Repairing cluster 4 refcount=1 reference=0
@@ -28,7 +28,7 @@
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 backing_file=TEST_DIR/t.IMGFMT.base
wrote 65536/65536 bytes at offset 0
64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
-qemu-img: Could not empty blkdebug:TEST_DIR/blkdebug.conf:TEST_DIR/t.IMGFMT: Input/output error
+qemu-img: Failed to empty blkdebug:TEST_DIR/blkdebug.conf:TEST_DIR/t.IMGFMT: Input/output error
ERROR cluster 0 refcount=0 reference=1
ERROR cluster 1 refcount=0 reference=1
ERROR cluster 3 refcount=0 reference=1
@@ -42,7 +42,7 @@
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 backing_file=TEST_DIR/t.IMGFMT.base
wrote 65536/65536 bytes at offset 0
64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
-qemu-img: Could not empty blkdebug:TEST_DIR/blkdebug.conf:TEST_DIR/t.IMGFMT: Input/output error
+qemu-img: Failed to empty blkdebug:TEST_DIR/blkdebug.conf:TEST_DIR/t.IMGFMT: Input/output error
ERROR cluster 0 refcount=0 reference=1
ERROR cluster 1 refcount=0 reference=1
ERROR cluster 3 refcount=0 reference=1
diff --git a/tests/qemu-iotests/109 b/tests/qemu-iotests/109
index 5bc2e9b..3ffeaf3 100755
--- a/tests/qemu-iotests/109
+++ b/tests/qemu-iotests/109
@@ -77,14 +77,14 @@
echo "=== Writing a $fmt header into raw ==="
echo
- _make_test_img 64M
TEST_IMG="$TEST_IMG.src" IMGFMT=$fmt _make_test_img 64M
+ _make_test_img $(du -b "$TEST_IMG.src" | cut -f1) | _filter_img_create_size
# This first test should fail: The image format was probed, we may not
# write an image header at the start of the image
run_qemu "$TEST_IMG" "$TEST_IMG.src" "" "BLOCK_JOB_ERROR" |
_filter_block_job_len
- $QEMU_IO -c 'read -P 0 0 64k' "$TEST_IMG" | _filter_qemu_io
+ $QEMU_IO -c 'read -P 0 0 512' "$TEST_IMG" | _filter_qemu_io
# When raw was explicitly specified, the same must succeed
@@ -103,12 +103,12 @@
# Can't use _use_sample_img because that isn't designed to be used multiple
# times and it overwrites $TEST_IMG (both breaks cleanup)
- _make_test_img 64M
bzcat "$SAMPLE_IMG_DIR/$sample_img.bz2" > "$TEST_IMG.src"
+ _make_test_img $(du -b "$TEST_IMG.src" | cut -f1) | _filter_img_create_size
run_qemu "$TEST_IMG" "$TEST_IMG.src" "" "BLOCK_JOB_ERROR" |
_filter_block_job_offset | _filter_block_job_len
- $QEMU_IO -c 'read -P 0 0 64k' "$TEST_IMG" | _filter_qemu_io
+ $QEMU_IO -c 'read -P 0 0 512' "$TEST_IMG" | _filter_qemu_io
run_qemu "$TEST_IMG" "$TEST_IMG.src" "'format': 'raw'," "BLOCK_JOB_READY"
$QEMU_IMG compare -f raw -F raw "$TEST_IMG" "$TEST_IMG.src"
@@ -119,8 +119,8 @@
echo
for sample_img in grub_mbr.raw; do
- _make_test_img 64M
bzcat "$SAMPLE_IMG_DIR/$sample_img.bz2" > "$TEST_IMG.src"
+ _make_test_img $(du -b "$TEST_IMG.src" | cut -f1) | _filter_img_create_size
run_qemu "$TEST_IMG" "$TEST_IMG.src" "" "BLOCK_JOB_READY"
$QEMU_IMG compare -f raw -F raw "$TEST_IMG" "$TEST_IMG.src"
diff --git a/tests/qemu-iotests/109.out b/tests/qemu-iotests/109.out
index 884f65f..ad739df 100644
--- a/tests/qemu-iotests/109.out
+++ b/tests/qemu-iotests/109.out
@@ -2,8 +2,8 @@
=== Writing a qcow header into raw ===
-Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864
Formatting 'TEST_DIR/t.raw.src', fmt=IMGFMT size=67108864
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=SIZE
{ 'execute': 'qmp_capabilities' }
{"return": {}}
{'execute':'drive-mirror', 'arguments':{ 'device': 'src', 'target': 'TEST_DIR/t.IMGFMT', 'mode': 'existing', 'sync': 'full'}}
@@ -23,8 +23,8 @@
{"execute":"quit"}
{"return": {}}
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false, "reason": "host-qmp-quit"}}
-read 65536/65536 bytes at offset 0
-64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 0
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
{ 'execute': 'qmp_capabilities' }
{"return": {}}
{'execute':'drive-mirror', 'arguments':{ 'device': 'src', 'target': 'TEST_DIR/t.IMGFMT', 'format': 'IMGFMT', 'mode': 'existing', 'sync': 'full'}}
@@ -43,13 +43,12 @@
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_COMPLETED", "data": {"device": "src", "len": 1024, "offset": 1024, "speed": 0, "type": "mirror"}}
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "concluded", "id": "src"}}
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "null", "id": "src"}}
-Warning: Image size mismatch!
Images are identical.
=== Writing a qcow2 header into raw ===
-Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864
Formatting 'TEST_DIR/t.raw.src', fmt=IMGFMT size=67108864
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=SIZE
{ 'execute': 'qmp_capabilities' }
{"return": {}}
{'execute':'drive-mirror', 'arguments':{ 'device': 'src', 'target': 'TEST_DIR/t.IMGFMT', 'mode': 'existing', 'sync': 'full'}}
@@ -69,8 +68,8 @@
{"execute":"quit"}
{"return": {}}
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false, "reason": "host-qmp-quit"}}
-read 65536/65536 bytes at offset 0
-64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 0
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
{ 'execute': 'qmp_capabilities' }
{"return": {}}
{'execute':'drive-mirror', 'arguments':{ 'device': 'src', 'target': 'TEST_DIR/t.IMGFMT', 'format': 'IMGFMT', 'mode': 'existing', 'sync': 'full'}}
@@ -89,13 +88,12 @@
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_COMPLETED", "data": {"device": "src", "len": 197120, "offset": 197120, "speed": 0, "type": "mirror"}}
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "concluded", "id": "src"}}
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "null", "id": "src"}}
-Warning: Image size mismatch!
Images are identical.
=== Writing a qed header into raw ===
-Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864
Formatting 'TEST_DIR/t.raw.src', fmt=IMGFMT size=67108864
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=SIZE
{ 'execute': 'qmp_capabilities' }
{"return": {}}
{'execute':'drive-mirror', 'arguments':{ 'device': 'src', 'target': 'TEST_DIR/t.IMGFMT', 'mode': 'existing', 'sync': 'full'}}
@@ -115,8 +113,8 @@
{"execute":"quit"}
{"return": {}}
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false, "reason": "host-qmp-quit"}}
-read 65536/65536 bytes at offset 0
-64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 0
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
{ 'execute': 'qmp_capabilities' }
{"return": {}}
{'execute':'drive-mirror', 'arguments':{ 'device': 'src', 'target': 'TEST_DIR/t.IMGFMT', 'format': 'IMGFMT', 'mode': 'existing', 'sync': 'full'}}
@@ -135,13 +133,12 @@
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_COMPLETED", "data": {"device": "src", "len": 327680, "offset": 327680, "speed": 0, "type": "mirror"}}
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "concluded", "id": "src"}}
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "null", "id": "src"}}
-Warning: Image size mismatch!
Images are identical.
=== Writing a vdi header into raw ===
-Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864
Formatting 'TEST_DIR/t.raw.src', fmt=IMGFMT size=67108864
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=SIZE
{ 'execute': 'qmp_capabilities' }
{"return": {}}
{'execute':'drive-mirror', 'arguments':{ 'device': 'src', 'target': 'TEST_DIR/t.IMGFMT', 'mode': 'existing', 'sync': 'full'}}
@@ -161,8 +158,8 @@
{"execute":"quit"}
{"return": {}}
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false, "reason": "host-qmp-quit"}}
-read 65536/65536 bytes at offset 0
-64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 0
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
{ 'execute': 'qmp_capabilities' }
{"return": {}}
{'execute':'drive-mirror', 'arguments':{ 'device': 'src', 'target': 'TEST_DIR/t.IMGFMT', 'format': 'IMGFMT', 'mode': 'existing', 'sync': 'full'}}
@@ -181,13 +178,12 @@
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_COMPLETED", "data": {"device": "src", "len": 1024, "offset": 1024, "speed": 0, "type": "mirror"}}
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "concluded", "id": "src"}}
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "null", "id": "src"}}
-Warning: Image size mismatch!
Images are identical.
=== Writing a vmdk header into raw ===
-Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864
Formatting 'TEST_DIR/t.raw.src', fmt=IMGFMT size=67108864
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=SIZE
{ 'execute': 'qmp_capabilities' }
{"return": {}}
{'execute':'drive-mirror', 'arguments':{ 'device': 'src', 'target': 'TEST_DIR/t.IMGFMT', 'mode': 'existing', 'sync': 'full'}}
@@ -207,8 +203,8 @@
{"execute":"quit"}
{"return": {}}
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false, "reason": "host-qmp-quit"}}
-read 65536/65536 bytes at offset 0
-64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 0
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
{ 'execute': 'qmp_capabilities' }
{"return": {}}
{'execute':'drive-mirror', 'arguments':{ 'device': 'src', 'target': 'TEST_DIR/t.IMGFMT', 'format': 'IMGFMT', 'mode': 'existing', 'sync': 'full'}}
@@ -227,13 +223,12 @@
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_COMPLETED", "data": {"device": "src", "len": 65536, "offset": 65536, "speed": 0, "type": "mirror"}}
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "concluded", "id": "src"}}
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "null", "id": "src"}}
-Warning: Image size mismatch!
Images are identical.
=== Writing a vpc header into raw ===
-Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864
Formatting 'TEST_DIR/t.raw.src', fmt=IMGFMT size=67108864
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=SIZE
{ 'execute': 'qmp_capabilities' }
{"return": {}}
{'execute':'drive-mirror', 'arguments':{ 'device': 'src', 'target': 'TEST_DIR/t.IMGFMT', 'mode': 'existing', 'sync': 'full'}}
@@ -253,8 +248,8 @@
{"execute":"quit"}
{"return": {}}
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false, "reason": "host-qmp-quit"}}
-read 65536/65536 bytes at offset 0
-64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 0
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
{ 'execute': 'qmp_capabilities' }
{"return": {}}
{'execute':'drive-mirror', 'arguments':{ 'device': 'src', 'target': 'TEST_DIR/t.IMGFMT', 'format': 'IMGFMT', 'mode': 'existing', 'sync': 'full'}}
@@ -273,12 +268,11 @@
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_COMPLETED", "data": {"device": "src", "len": 2560, "offset": 2560, "speed": 0, "type": "mirror"}}
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "concluded", "id": "src"}}
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "null", "id": "src"}}
-Warning: Image size mismatch!
Images are identical.
=== Copying sample image empty.bochs into raw ===
-Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=SIZE
{ 'execute': 'qmp_capabilities' }
{"return": {}}
{'execute':'drive-mirror', 'arguments':{ 'device': 'src', 'target': 'TEST_DIR/t.IMGFMT', 'mode': 'existing', 'sync': 'full'}}
@@ -298,8 +292,8 @@
{"execute":"quit"}
{"return": {}}
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false, "reason": "host-qmp-quit"}}
-read 65536/65536 bytes at offset 0
-64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 0
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
{ 'execute': 'qmp_capabilities' }
{"return": {}}
{'execute':'drive-mirror', 'arguments':{ 'device': 'src', 'target': 'TEST_DIR/t.IMGFMT', 'format': 'IMGFMT', 'mode': 'existing', 'sync': 'full'}}
@@ -318,12 +312,11 @@
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_COMPLETED", "data": {"device": "src", "len": 2560, "offset": 2560, "speed": 0, "type": "mirror"}}
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "concluded", "id": "src"}}
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "null", "id": "src"}}
-Warning: Image size mismatch!
Images are identical.
=== Copying sample image iotest-dirtylog-10G-4M.vhdx into raw ===
-Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=SIZE
{ 'execute': 'qmp_capabilities' }
{"return": {}}
{'execute':'drive-mirror', 'arguments':{ 'device': 'src', 'target': 'TEST_DIR/t.IMGFMT', 'mode': 'existing', 'sync': 'full'}}
@@ -343,8 +336,8 @@
{"execute":"quit"}
{"return": {}}
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false, "reason": "host-qmp-quit"}}
-read 65536/65536 bytes at offset 0
-64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 0
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
{ 'execute': 'qmp_capabilities' }
{"return": {}}
{'execute':'drive-mirror', 'arguments':{ 'device': 'src', 'target': 'TEST_DIR/t.IMGFMT', 'format': 'IMGFMT', 'mode': 'existing', 'sync': 'full'}}
@@ -363,12 +356,11 @@
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_COMPLETED", "data": {"device": "src", "len": 31457280, "offset": 31457280, "speed": 0, "type": "mirror"}}
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "concluded", "id": "src"}}
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "null", "id": "src"}}
-Warning: Image size mismatch!
Images are identical.
=== Copying sample image parallels-v1 into raw ===
-Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=SIZE
{ 'execute': 'qmp_capabilities' }
{"return": {}}
{'execute':'drive-mirror', 'arguments':{ 'device': 'src', 'target': 'TEST_DIR/t.IMGFMT', 'mode': 'existing', 'sync': 'full'}}
@@ -388,8 +380,8 @@
{"execute":"quit"}
{"return": {}}
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false, "reason": "host-qmp-quit"}}
-read 65536/65536 bytes at offset 0
-64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 0
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
{ 'execute': 'qmp_capabilities' }
{"return": {}}
{'execute':'drive-mirror', 'arguments':{ 'device': 'src', 'target': 'TEST_DIR/t.IMGFMT', 'format': 'IMGFMT', 'mode': 'existing', 'sync': 'full'}}
@@ -408,12 +400,11 @@
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_COMPLETED", "data": {"device": "src", "len": 327680, "offset": 327680, "speed": 0, "type": "mirror"}}
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "concluded", "id": "src"}}
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "null", "id": "src"}}
-Warning: Image size mismatch!
Images are identical.
=== Copying sample image simple-pattern.cloop into raw ===
-Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=SIZE
{ 'execute': 'qmp_capabilities' }
{"return": {}}
{'execute':'drive-mirror', 'arguments':{ 'device': 'src', 'target': 'TEST_DIR/t.IMGFMT', 'mode': 'existing', 'sync': 'full'}}
@@ -433,8 +424,8 @@
{"execute":"quit"}
{"return": {}}
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false, "reason": "host-qmp-quit"}}
-read 65536/65536 bytes at offset 0
-64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 0
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
{ 'execute': 'qmp_capabilities' }
{"return": {}}
{'execute':'drive-mirror', 'arguments':{ 'device': 'src', 'target': 'TEST_DIR/t.IMGFMT', 'format': 'IMGFMT', 'mode': 'existing', 'sync': 'full'}}
@@ -453,12 +444,11 @@
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_COMPLETED", "data": {"device": "src", "len": 2048, "offset": 2048, "speed": 0, "type": "mirror"}}
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "concluded", "id": "src"}}
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "null", "id": "src"}}
-Warning: Image size mismatch!
Images are identical.
=== Write legitimate MBR into raw ===
-Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=SIZE
{ 'execute': 'qmp_capabilities' }
{"return": {}}
{'execute':'drive-mirror', 'arguments':{ 'device': 'src', 'target': 'TEST_DIR/t.IMGFMT', 'mode': 'existing', 'sync': 'full'}}
@@ -480,7 +470,6 @@
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_COMPLETED", "data": {"device": "src", "len": 512, "offset": 512, "speed": 0, "type": "mirror"}}
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "concluded", "id": "src"}}
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "null", "id": "src"}}
-Warning: Image size mismatch!
Images are identical.
{ 'execute': 'qmp_capabilities' }
{"return": {}}
@@ -500,6 +489,5 @@
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_COMPLETED", "data": {"device": "src", "len": 512, "offset": 512, "speed": 0, "type": "mirror"}}
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "concluded", "id": "src"}}
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "null", "id": "src"}}
-Warning: Image size mismatch!
Images are identical.
*** done
diff --git a/tests/qemu-iotests/144.out b/tests/qemu-iotests/144.out
index c7aa2e4..885a887 100644
--- a/tests/qemu-iotests/144.out
+++ b/tests/qemu-iotests/144.out
@@ -9,7 +9,7 @@
{ 'execute': 'qmp_capabilities' }
{"return": {}}
{ 'execute': 'blockdev-snapshot-sync', 'arguments': { 'device': 'virtio0', 'snapshot-file':'TEST_DIR/tmp.IMGFMT', 'format': 'IMGFMT' } }
-Formatting 'TEST_DIR/tmp.qcow2', fmt=qcow2 size=536870912 backing_file=TEST_DIR/t.qcow2 backing_fmt=qcow2 cluster_size=65536 lazy_refcounts=off refcount_bits=16
+Formatting 'TEST_DIR/tmp.qcow2', fmt=qcow2 size=536870912 backing_file=TEST_DIR/t.qcow2 backing_fmt=qcow2 cluster_size=65536 lazy_refcounts=off refcount_bits=16 compression_type=zlib
{"return": {}}
=== Performing block-commit on active layer ===
@@ -31,6 +31,6 @@
=== Performing Live Snapshot 2 ===
{ 'execute': 'blockdev-snapshot-sync', 'arguments': { 'device': 'virtio0', 'snapshot-file':'TEST_DIR/tmp2.IMGFMT', 'format': 'IMGFMT' } }
-Formatting 'TEST_DIR/tmp2.qcow2', fmt=qcow2 size=536870912 backing_file=TEST_DIR/t.qcow2 backing_fmt=qcow2 cluster_size=65536 lazy_refcounts=off refcount_bits=16
+Formatting 'TEST_DIR/tmp2.qcow2', fmt=qcow2 size=536870912 backing_file=TEST_DIR/t.qcow2 backing_fmt=qcow2 cluster_size=65536 lazy_refcounts=off refcount_bits=16 compression_type=zlib
{"return": {}}
*** done
diff --git a/tests/qemu-iotests/178.out.qcow2 b/tests/qemu-iotests/178.out.qcow2
index f59bf4b..c799776 100644
--- a/tests/qemu-iotests/178.out.qcow2
+++ b/tests/qemu-iotests/178.out.qcow2
@@ -13,7 +13,7 @@
qemu-img: Invalid parameter 'snapshot.foo'
qemu-img: Failed in parsing snapshot param 'snapshot.foo'
qemu-img: --output must be used with human or json as argument.
-qemu-img: Image size must be less than 8 EiB!
+qemu-img: Invalid image size specified. Must be between 0 and 9223372036854775807.
qemu-img: Unknown file format 'foo'
== Size calculation for a new file (human) ==
@@ -37,6 +37,7 @@
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=0
required size: 196608
fully allocated size: 196608
+bitmaps size: 0
converted image file size in bytes: 196608
@@ -45,6 +46,7 @@
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824
required size: 393216
fully allocated size: 1074135040
+bitmaps size: 0
wrote 512/512 bytes at offset 512
512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
wrote 65536/65536 bytes at offset 65536
@@ -53,6 +55,7 @@
63 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
required size: 589824
fully allocated size: 1074135040
+bitmaps size: 0
converted image file size in bytes: 524288
@@ -60,6 +63,7 @@
required size: 524288
fully allocated size: 1074135040
+bitmaps size: 0
converted image file size in bytes: 458752
@@ -67,16 +71,19 @@
required size: 1074135040
fully allocated size: 1074135040
+bitmaps size: 0
== qcow2 input image and LUKS encryption ==
required size: 2686976
fully allocated size: 1076232192
+bitmaps size: 0
== qcow2 input image and preallocation (human) ==
required size: 1074135040
fully allocated size: 1074135040
+bitmaps size: 0
converted image file size in bytes: 1074135040
@@ -87,6 +94,7 @@
8 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
required size: 8716288
fully allocated size: 8716288
+bitmaps size: 0
converted image file size in bytes: 8716288
@@ -173,6 +181,7 @@
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=0
{
+ "bitmaps": 0,
"required": 196608,
"fully-allocated": 196608
}
@@ -183,6 +192,7 @@
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824
{
+ "bitmaps": 0,
"required": 393216,
"fully-allocated": 1074135040
}
@@ -193,6 +203,7 @@
wrote 64512/64512 bytes at offset 134217728
63 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
{
+ "bitmaps": 0,
"required": 589824,
"fully-allocated": 1074135040
}
@@ -202,6 +213,7 @@
== qcow2 input image with internal snapshot (json) ==
{
+ "bitmaps": 0,
"required": 524288,
"fully-allocated": 1074135040
}
@@ -211,6 +223,7 @@
== qcow2 input image and a backing file (json) ==
{
+ "bitmaps": 0,
"required": 1074135040,
"fully-allocated": 1074135040
}
@@ -218,6 +231,7 @@
== qcow2 input image and LUKS encryption ==
{
+ "bitmaps": 0,
"required": 2686976,
"fully-allocated": 1076232192
}
@@ -225,6 +239,7 @@
== qcow2 input image and preallocation (json) ==
{
+ "bitmaps": 0,
"required": 1074135040,
"fully-allocated": 1074135040
}
@@ -237,6 +252,7 @@
wrote 8388608/8388608 bytes at offset 0
8 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
{
+ "bitmaps": 0,
"required": 8716288,
"fully-allocated": 8716288
}
diff --git a/tests/qemu-iotests/178.out.raw b/tests/qemu-iotests/178.out.raw
index 404ca90..20e17da 100644
--- a/tests/qemu-iotests/178.out.raw
+++ b/tests/qemu-iotests/178.out.raw
@@ -13,7 +13,7 @@
qemu-img: Invalid parameter 'snapshot.foo'
qemu-img: Failed in parsing snapshot param 'snapshot.foo'
qemu-img: --output must be used with human or json as argument.
-qemu-img: Image size must be less than 8 EiB!
+qemu-img: Invalid image size specified. Must be between 0 and 9223372036854775807.
qemu-img: Unknown file format 'foo'
== Size calculation for a new file (human) ==
diff --git a/tests/qemu-iotests/182.out b/tests/qemu-iotests/182.out
index a8eea16..ae43654 100644
--- a/tests/qemu-iotests/182.out
+++ b/tests/qemu-iotests/182.out
@@ -13,7 +13,7 @@
{'execute': 'blockdev-add', 'arguments': { 'node-name': 'node0', 'driver': 'file', 'filename': 'TEST_DIR/t.IMGFMT', 'locking': 'on' } }
{"return": {}}
{'execute': 'blockdev-snapshot-sync', 'arguments': { 'node-name': 'node0', 'snapshot-file': 'TEST_DIR/t.IMGFMT.overlay', 'snapshot-node-name': 'node1' } }
-Formatting 'TEST_DIR/t.qcow2.overlay', fmt=qcow2 size=197120 backing_file=TEST_DIR/t.qcow2 backing_fmt=file cluster_size=65536 lazy_refcounts=off refcount_bits=16
+Formatting 'TEST_DIR/t.qcow2.overlay', fmt=qcow2 size=197120 backing_file=TEST_DIR/t.qcow2 backing_fmt=file cluster_size=65536 lazy_refcounts=off refcount_bits=16 compression_type=zlib
{"return": {}}
{'execute': 'blockdev-add', 'arguments': { 'node-name': 'node1', 'driver': 'file', 'filename': 'TEST_DIR/t.IMGFMT', 'locking': 'on' } }
{"return": {}}
diff --git a/tests/qemu-iotests/185.out b/tests/qemu-iotests/185.out
index 9a3b657..ac5ab16 100644
--- a/tests/qemu-iotests/185.out
+++ b/tests/qemu-iotests/185.out
@@ -9,14 +9,14 @@
=== Creating backing chain ===
{ 'execute': 'blockdev-snapshot-sync', 'arguments': { 'device': 'disk', 'snapshot-file': 'TEST_DIR/t.IMGFMT.mid', 'format': 'IMGFMT', 'mode': 'absolute-paths' } }
-Formatting 'TEST_DIR/t.qcow2.mid', fmt=qcow2 size=67108864 backing_file=TEST_DIR/t.qcow2.base backing_fmt=qcow2 cluster_size=65536 lazy_refcounts=off refcount_bits=16
+Formatting 'TEST_DIR/t.qcow2.mid', fmt=qcow2 size=67108864 backing_file=TEST_DIR/t.qcow2.base backing_fmt=qcow2 cluster_size=65536 lazy_refcounts=off refcount_bits=16 compression_type=zlib
{"return": {}}
{ 'execute': 'human-monitor-command', 'arguments': { 'command-line': 'qemu-io disk "write 0 4M"' } }
wrote 4194304/4194304 bytes at offset 0
4 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
{"return": ""}
{ 'execute': 'blockdev-snapshot-sync', 'arguments': { 'device': 'disk', 'snapshot-file': 'TEST_DIR/t.IMGFMT', 'format': 'IMGFMT', 'mode': 'absolute-paths' } }
-Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=67108864 backing_file=TEST_DIR/t.qcow2.mid backing_fmt=qcow2 cluster_size=65536 lazy_refcounts=off refcount_bits=16
+Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=67108864 backing_file=TEST_DIR/t.qcow2.mid backing_fmt=qcow2 cluster_size=65536 lazy_refcounts=off refcount_bits=16 compression_type=zlib
{"return": {}}
=== Start commit job and exit qemu ===
@@ -48,7 +48,7 @@
{ 'execute': 'qmp_capabilities' }
{"return": {}}
{ 'execute': 'drive-mirror', 'arguments': { 'device': 'disk', 'target': 'TEST_DIR/t.IMGFMT.copy', 'format': 'IMGFMT', 'sync': 'full', 'speed': 65536 } }
-Formatting 'TEST_DIR/t.qcow2.copy', fmt=qcow2 size=67108864 cluster_size=65536 lazy_refcounts=off refcount_bits=16
+Formatting 'TEST_DIR/t.qcow2.copy', fmt=qcow2 size=67108864 cluster_size=65536 lazy_refcounts=off refcount_bits=16 compression_type=zlib
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "created", "id": "disk"}}
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "running", "id": "disk"}}
{"return": {}}
@@ -62,7 +62,7 @@
{ 'execute': 'qmp_capabilities' }
{"return": {}}
{ 'execute': 'drive-backup', 'arguments': { 'device': 'disk', 'target': 'TEST_DIR/t.IMGFMT.copy', 'format': 'IMGFMT', 'sync': 'full', 'speed': 65536 } }
-Formatting 'TEST_DIR/t.qcow2.copy', fmt=qcow2 size=67108864 cluster_size=65536 lazy_refcounts=off refcount_bits=16
+Formatting 'TEST_DIR/t.qcow2.copy', fmt=qcow2 size=67108864 cluster_size=65536 lazy_refcounts=off refcount_bits=16 compression_type=zlib
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "created", "id": "disk"}}
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "running", "id": "disk"}}
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "paused", "id": "disk"}}
diff --git a/tests/qemu-iotests/190 b/tests/qemu-iotests/190
index 6d416504..fe63091 100755
--- a/tests/qemu-iotests/190
+++ b/tests/qemu-iotests/190
@@ -2,7 +2,7 @@
#
# qemu-img measure sub-command tests on huge qcow2 files
#
-# Copyright (C) 2017 Red Hat, Inc.
+# Copyright (C) 2017-2020 Red Hat, Inc.
#
# 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
@@ -42,7 +42,7 @@
_supported_fmt qcow2
_supported_proto file
-echo "== Huge file =="
+echo "== Huge file without bitmaps =="
echo
_make_test_img -o 'cluster_size=2M' 2T
@@ -51,6 +51,49 @@
$QEMU_IMG measure -O qcow2 -o cluster_size=64k -f qcow2 "$TEST_IMG"
$QEMU_IMG measure -O qcow2 -o cluster_size=2M -f qcow2 "$TEST_IMG"
+echo
+echo "== Huge file with bitmaps =="
+echo
+
+$QEMU_IMG bitmap --add --granularity 512 -f qcow2 "$TEST_IMG" b1
+$QEMU_IMG bitmap --add -g 2M -f qcow2 "$TEST_IMG" b2
+
+# No bitmap without a source
+$QEMU_IMG measure -O qcow2 --size 10M
+# No bitmap output, since raw does not support it
+$QEMU_IMG measure -O raw -f qcow2 "$TEST_IMG"
+# No bitmap output, since no bitmaps on raw source. Munge required size, as
+# some filesystems store the qcow2 file with less sparseness than others
+$QEMU_IMG measure -O qcow2 -f raw "$TEST_IMG" |
+ sed '/^required size:/ s/[0-9][0-9]*/SIZE/'
+# No bitmap output, since v2 does not support it
+$QEMU_IMG measure -O qcow2 -o compat=0.10 -f qcow2 "$TEST_IMG"
+
+# Compute expected output: bitmap clusters + bitmap tables + bitmaps directory
+echo
+val2T=$((2*1024*1024*1024*1024))
+cluster=$((64*1024))
+b1clusters=$(( (val2T/512/8 + cluster - 1) / cluster ))
+b2clusters=$(( (val2T/2/1024/1024/8 + cluster - 1) / cluster ))
+echo expected bitmap $((b1clusters * cluster +
+ (b1clusters * 8 + cluster - 1) / cluster * cluster +
+ b2clusters * cluster +
+ (b2clusters * 8 + cluster - 1) / cluster * cluster +
+ cluster))
+$QEMU_IMG measure -O qcow2 -o cluster_size=64k -f qcow2 "$TEST_IMG"
+
+# Compute expected output: bitmap clusters + bitmap tables + bitmaps directory
+echo
+cluster=$((2*1024*1024))
+b1clusters=$(( (val2T/512/8 + cluster - 1) / cluster ))
+b2clusters=$(( (val2T/2/1024/1024/8 + cluster - 1) / cluster ))
+echo expected bitmap $((b1clusters * cluster +
+ (b1clusters * 8 + cluster - 1) / cluster * cluster +
+ b2clusters * cluster +
+ (b2clusters * 8 + cluster - 1) / cluster * cluster +
+ cluster))
+$QEMU_IMG measure --output=json -O qcow2 -o cluster_size=2M -f qcow2 "$TEST_IMG"
+
# success, all done
echo "*** done"
rm -f $seq.full
diff --git a/tests/qemu-iotests/190.out b/tests/qemu-iotests/190.out
index d001942..ed9d821 100644
--- a/tests/qemu-iotests/190.out
+++ b/tests/qemu-iotests/190.out
@@ -1,11 +1,36 @@
QA output created by 190
-== Huge file ==
+== Huge file without bitmaps ==
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2199023255552
required size: 2199023255552
fully allocated size: 2199023255552
required size: 335806464
fully allocated size: 2199359062016
+bitmaps size: 0
required size: 18874368
fully allocated size: 2199042129920
+bitmaps size: 0
+
+== Huge file with bitmaps ==
+
+required size: 327680
+fully allocated size: 10813440
+required size: 2199023255552
+fully allocated size: 2199023255552
+required size: SIZE
+fully allocated size: 17170432
+required size: 335806464
+fully allocated size: 2199359062016
+
+expected bitmap 537198592
+required size: 335806464
+fully allocated size: 2199359062016
+bitmaps size: 537198592
+
+expected bitmap 545259520
+{
+ "bitmaps": 545259520,
+ "required": 18874368,
+ "fully-allocated": 2199042129920
+}
*** done
diff --git a/tests/qemu-iotests/194 b/tests/qemu-iotests/194
index 8b1f720..3fad7c6 100755
--- a/tests/qemu-iotests/194
+++ b/tests/qemu-iotests/194
@@ -42,6 +42,8 @@
.add_incoming('unix:{0}'.format(migration_sock_path))
.launch())
+ source_vm.qmp_log('block-dirty-bitmap-add', node='drive0', name='bitmap0')
+
iotests.log('Launching NBD server on destination...')
iotests.log(dest_vm.qmp('nbd-server-start', addr={'type': 'unix', 'data': {'path': nbd_sock_path}}))
iotests.log(dest_vm.qmp('nbd-server-add', device='drive0', writable=True))
@@ -61,12 +63,14 @@
filters=[iotests.filter_qmp_event])
iotests.log('Starting migration...')
- source_vm.qmp('migrate-set-capabilities',
- capabilities=[{'capability': 'events', 'state': True}])
- dest_vm.qmp('migrate-set-capabilities',
- capabilities=[{'capability': 'events', 'state': True}])
+ capabilities = [{'capability': 'events', 'state': True},
+ {'capability': 'dirty-bitmaps', 'state': True}]
+ source_vm.qmp('migrate-set-capabilities', capabilities=capabilities)
+ dest_vm.qmp('migrate-set-capabilities', capabilities=capabilities)
iotests.log(source_vm.qmp('migrate', uri='unix:{0}'.format(migration_sock_path)))
+ source_vm.qmp_log('migrate-start-postcopy')
+
while True:
event1 = source_vm.event_wait('MIGRATION')
iotests.log(event1, filters=[iotests.filter_qmp_event])
@@ -82,3 +86,5 @@
iotests.log('Stopping the NBD server on destination...')
iotests.log(dest_vm.qmp('nbd-server-stop'))
break
+
+ iotests.log(source_vm.qmp('query-block')['return'][0]['dirty-bitmaps'])
diff --git a/tests/qemu-iotests/194.out b/tests/qemu-iotests/194.out
index 7185785..dd60dcc 100644
--- a/tests/qemu-iotests/194.out
+++ b/tests/qemu-iotests/194.out
@@ -1,4 +1,6 @@
Launching VMs...
+{"execute": "block-dirty-bitmap-add", "arguments": {"name": "bitmap0", "node": "drive0"}}
+{"return": {}}
Launching NBD server on destination...
{"return": {}}
{"return": {}}
@@ -8,11 +10,15 @@
{"data": {"device": "mirror-job0", "len": 1073741824, "offset": 1073741824, "speed": 0, "type": "mirror"}, "event": "BLOCK_JOB_READY", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}}
Starting migration...
{"return": {}}
+{"execute": "migrate-start-postcopy", "arguments": {}}
+{"return": {}}
{"data": {"status": "setup"}, "event": "MIGRATION", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}}
{"data": {"status": "active"}, "event": "MIGRATION", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}}
+{"data": {"status": "postcopy-active"}, "event": "MIGRATION", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}}
{"data": {"status": "completed"}, "event": "MIGRATION", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}}
Gracefully ending the `drive-mirror` job on source...
{"return": {}}
{"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": {}}
+[{"busy": false, "count": 0, "granularity": 65536, "name": "bitmap0", "persistent": false, "recording": true, "status": "active"}]
diff --git a/tests/qemu-iotests/198.out b/tests/qemu-iotests/198.out
index 831ce3a..6280ae6 100644
--- a/tests/qemu-iotests/198.out
+++ b/tests/qemu-iotests/198.out
@@ -36,6 +36,7 @@
file format: IMGFMT
virtual size: 16 MiB (16777216 bytes)
Format specific information:
+ compression type: zlib
encrypt:
ivgen alg: plain64
hash alg: sha256
@@ -79,6 +80,7 @@
virtual size: 16 MiB (16777216 bytes)
backing file: TEST_DIR/t.IMGFMT.base
Format specific information:
+ compression type: zlib
encrypt:
ivgen alg: plain64
hash alg: sha256
diff --git a/tests/qemu-iotests/206.out b/tests/qemu-iotests/206.out
index 61e7241..1a14255 100644
--- a/tests/qemu-iotests/206.out
+++ b/tests/qemu-iotests/206.out
@@ -18,6 +18,7 @@
cluster_size: 65536
Format specific information:
compat: 1.1
+ compression type: zlib
lazy refcounts: false
refcount bits: 16
corrupt: false
@@ -40,6 +41,7 @@
cluster_size: 65536
Format specific information:
compat: 1.1
+ compression type: zlib
lazy refcounts: false
refcount bits: 16
corrupt: false
@@ -62,6 +64,7 @@
cluster_size: 2097152
Format specific information:
compat: 1.1
+ compression type: zlib
lazy refcounts: true
refcount bits: 1
corrupt: false
@@ -86,6 +89,7 @@
backing file format: IMGFMT
Format specific information:
compat: 0.10
+ compression type: zlib
refcount bits: 16
=== Successful image creation (encrypted) ===
@@ -102,6 +106,7 @@
cluster_size: 65536
Format specific information:
compat: 1.1
+ compression type: zlib
lazy refcounts: false
refcount bits: 16
encrypt:
diff --git a/tests/qemu-iotests/223 b/tests/qemu-iotests/223
index 56fbc5f..d68bc3c 100755
--- a/tests/qemu-iotests/223
+++ b/tests/qemu-iotests/223
@@ -2,7 +2,7 @@
#
# Test reading dirty bitmap over NBD
#
-# Copyright (C) 2018-2019 Red Hat, Inc.
+# Copyright (C) 2018-2020 Red Hat, Inc.
#
# 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
@@ -206,7 +206,9 @@
nbd_server_start_unix_socket -f $IMGFMT -B b2 "$TEST_IMG"
IMG="driver=nbd,server.type=unix,server.path=$nbd_unix_socket"
-$QEMU_IMG map --output=json --image-opts \
+$QEMU_IMG map --output=json --image-opts --max-length=12345 \
+ "$IMG,x-dirty-bitmap=qemu:dirty-bitmap:b2" | _filter_qemu_img_map
+$QEMU_IMG map --output=json --image-opts --start-offset=12345 \
"$IMG,x-dirty-bitmap=qemu:dirty-bitmap:b2" | _filter_qemu_img_map
# success, all done
diff --git a/tests/qemu-iotests/223.out b/tests/qemu-iotests/223.out
index 80c0cf6..e1eaaed 100644
--- a/tests/qemu-iotests/223.out
+++ b/tests/qemu-iotests/223.out
@@ -201,6 +201,7 @@
{ "start": 2097152, "length": 2097152, "depth": 0, "zero": false, "data": false}]
[{ "start": 0, "length": 512, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
{ "start": 512, "length": 512, "depth": 0, "zero": false, "data": false},
-{ "start": 1024, "length": 2096128, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
+{ "start": 1024, "length": 11321, "depth": 0, "zero": false, "data": true, "offset": OFFSET}]
+[{ "start": 12345, "length": 2084807, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
{ "start": 2097152, "length": 2097152, "depth": 0, "zero": false, "data": false}]
*** done
diff --git a/tests/qemu-iotests/229 b/tests/qemu-iotests/229
index 866168b..99acb55 100755
--- a/tests/qemu-iotests/229
+++ b/tests/qemu-iotests/229
@@ -33,6 +33,7 @@
_cleanup_test_img
_rm_test_img "$TEST_IMG"
_rm_test_img "$DEST_IMG"
+ rm -f "$TEST_DIR/blkdebug.conf"
}
trap "_cleanup; exit \$status" 0 1 2 3 15
@@ -49,11 +50,10 @@
DEST_IMG="$TEST_DIR/d.$IMGFMT"
TEST_IMG="$TEST_DIR/b.$IMGFMT"
+BLKDEBUG_CONF="$TEST_DIR/blkdebug.conf"
_make_test_img 2M
-
-# destination for mirror will be too small, causing error
-TEST_IMG=$DEST_IMG _make_test_img 1M
+TEST_IMG=$DEST_IMG _make_test_img 2M
$QEMU_IO -c 'write 0 2M' "$TEST_IMG" | _filter_qemu_io
@@ -67,11 +67,18 @@
echo '=== Starting drive-mirror, causing error & stop ==='
echo
+cat > "$BLKDEBUG_CONF" <<EOF
+[inject-error]
+event = "write_aio"
+errno = "5"
+once = "on"
+EOF
+
_send_qemu_cmd $QEMU_HANDLE \
"{'execute': 'drive-mirror',
'arguments': {'device': 'testdisk',
'format': '$IMGFMT',
- 'target': '$DEST_IMG',
+ 'target': 'blkdebug:$BLKDEBUG_CONF:$DEST_IMG',
'sync': 'full',
'mode': 'existing',
'on-source-error': 'stop',
@@ -90,7 +97,8 @@
'arguments': { 'device': 'testdisk',
'force': true}}" \
"BLOCK_JOB_CANCELLED" "Assertion" \
- | grep -v '"BLOCK_JOB_ERROR"'
+ | grep -v '"BLOCK_JOB_ERROR"' \
+ | _filter_block_job_offset
# success, all done
echo "*** done"
diff --git a/tests/qemu-iotests/229.out b/tests/qemu-iotests/229.out
index 22350d7..4de6dfa 100644
--- a/tests/qemu-iotests/229.out
+++ b/tests/qemu-iotests/229.out
@@ -1,6 +1,6 @@
QA output created by 229
Formatting 'TEST_DIR/b.IMGFMT', fmt=IMGFMT size=2097152
-Formatting 'TEST_DIR/d.IMGFMT', fmt=IMGFMT size=1048576
+Formatting 'TEST_DIR/d.IMGFMT', fmt=IMGFMT size=2097152
wrote 2097152/2097152 bytes at offset 0
2 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
{'execute': 'qmp_capabilities'}
@@ -8,7 +8,7 @@
=== Starting drive-mirror, causing error & stop ===
-{'execute': 'drive-mirror', 'arguments': {'device': 'testdisk', 'format': 'IMGFMT', 'target': 'TEST_DIR/d.IMGFMT', 'sync': 'full', 'mode': 'existing', 'on-source-error': 'stop', 'on-target-error': 'stop' }}
+{'execute': 'drive-mirror', 'arguments': {'device': 'testdisk', 'format': 'IMGFMT', 'target': 'blkdebug:TEST_DIR/blkdebug.conf:TEST_DIR/d.IMGFMT', 'sync': 'full', 'mode': 'existing', 'on-source-error': 'stop', 'on-target-error': 'stop' }}
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "created", "id": "testdisk"}}
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "running", "id": "testdisk"}}
{"return": {}}
@@ -21,5 +21,5 @@
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "running", "id": "testdisk"}}
{"return": {}}
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "aborting", "id": "testdisk"}}
-{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_CANCELLED", "data": {"device": "testdisk", "len": 2097152, "offset": 1048576, "speed": 0, "type": "mirror"}}
+{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_CANCELLED", "data": {"device": "testdisk", "len": 2097152, "offset": OFFSET, "speed": 0, "type": "mirror"}}
*** done
diff --git a/tests/qemu-iotests/242.out b/tests/qemu-iotests/242.out
index 7ac8404..091b912 100644
--- a/tests/qemu-iotests/242.out
+++ b/tests/qemu-iotests/242.out
@@ -12,6 +12,7 @@
cluster_size: 65536
Format specific information:
compat: 1.1
+ compression type: zlib
lazy refcounts: false
refcount bits: 16
corrupt: false
@@ -32,6 +33,7 @@
cluster_size: 65536
Format specific information:
compat: 1.1
+ compression type: zlib
lazy refcounts: false
bitmaps:
[0]:
@@ -64,6 +66,7 @@
cluster_size: 65536
Format specific information:
compat: 1.1
+ compression type: zlib
lazy refcounts: false
bitmaps:
[0]:
@@ -104,6 +107,7 @@
cluster_size: 65536
Format specific information:
compat: 1.1
+ compression type: zlib
lazy refcounts: false
bitmaps:
[0]:
@@ -153,6 +157,7 @@
cluster_size: 65536
Format specific information:
compat: 1.1
+ compression type: zlib
lazy refcounts: false
bitmaps:
[0]:
diff --git a/tests/qemu-iotests/255.out b/tests/qemu-iotests/255.out
index 348909f..a3c99fd 100644
--- a/tests/qemu-iotests/255.out
+++ b/tests/qemu-iotests/255.out
@@ -3,9 +3,9 @@
=== Create backing chain and start VM ===
-Formatting 'TEST_DIR/PID-t.qcow2.mid', fmt=qcow2 size=134217728 cluster_size=65536 lazy_refcounts=off refcount_bits=16
+Formatting 'TEST_DIR/PID-t.qcow2.mid', fmt=qcow2 size=134217728 cluster_size=65536 lazy_refcounts=off refcount_bits=16 compression_type=zlib
-Formatting 'TEST_DIR/PID-t.qcow2', fmt=qcow2 size=134217728 cluster_size=65536 lazy_refcounts=off refcount_bits=16
+Formatting 'TEST_DIR/PID-t.qcow2', fmt=qcow2 size=134217728 cluster_size=65536 lazy_refcounts=off refcount_bits=16 compression_type=zlib
=== Start background read requests ===
@@ -23,9 +23,9 @@
=== Create images and start VM ===
-Formatting 'TEST_DIR/PID-src.qcow2', fmt=qcow2 size=134217728 cluster_size=65536 lazy_refcounts=off refcount_bits=16
+Formatting 'TEST_DIR/PID-src.qcow2', fmt=qcow2 size=134217728 cluster_size=65536 lazy_refcounts=off refcount_bits=16 compression_type=zlib
-Formatting 'TEST_DIR/PID-dst.qcow2', fmt=qcow2 size=134217728 cluster_size=65536 lazy_refcounts=off refcount_bits=16
+Formatting 'TEST_DIR/PID-dst.qcow2', fmt=qcow2 size=134217728 cluster_size=65536 lazy_refcounts=off refcount_bits=16 compression_type=zlib
wrote 1048576/1048576 bytes at offset 0
1 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
diff --git a/tests/qemu-iotests/274.out b/tests/qemu-iotests/274.out
index 9d6fdeb..d24ff68 100644
--- a/tests/qemu-iotests/274.out
+++ b/tests/qemu-iotests/274.out
@@ -1,9 +1,9 @@
== Commit tests ==
-Formatting 'TEST_DIR/PID-base', fmt=qcow2 size=2097152 cluster_size=65536 lazy_refcounts=off refcount_bits=16
+Formatting 'TEST_DIR/PID-base', fmt=qcow2 size=2097152 cluster_size=65536 lazy_refcounts=off refcount_bits=16 compression_type=zlib
-Formatting 'TEST_DIR/PID-mid', fmt=qcow2 size=1048576 backing_file=TEST_DIR/PID-base cluster_size=65536 lazy_refcounts=off refcount_bits=16
+Formatting 'TEST_DIR/PID-mid', fmt=qcow2 size=1048576 backing_file=TEST_DIR/PID-base cluster_size=65536 lazy_refcounts=off refcount_bits=16 compression_type=zlib
-Formatting 'TEST_DIR/PID-top', fmt=qcow2 size=2097152 backing_file=TEST_DIR/PID-mid cluster_size=65536 lazy_refcounts=off refcount_bits=16
+Formatting 'TEST_DIR/PID-top', fmt=qcow2 size=2097152 backing_file=TEST_DIR/PID-mid cluster_size=65536 lazy_refcounts=off refcount_bits=16 compression_type=zlib
wrote 2097152/2097152 bytes at offset 0
2 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
@@ -52,6 +52,7 @@
backing file: TEST_DIR/PID-base
Format specific information:
compat: 1.1
+ compression type: zlib
lazy refcounts: false
refcount bits: 16
corrupt: false
@@ -63,11 +64,11 @@
1 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
=== Testing HMP commit (top -> mid) ===
-Formatting 'TEST_DIR/PID-base', fmt=qcow2 size=2097152 cluster_size=65536 lazy_refcounts=off refcount_bits=16
+Formatting 'TEST_DIR/PID-base', fmt=qcow2 size=2097152 cluster_size=65536 lazy_refcounts=off refcount_bits=16 compression_type=zlib
-Formatting 'TEST_DIR/PID-mid', fmt=qcow2 size=1048576 backing_file=TEST_DIR/PID-base cluster_size=65536 lazy_refcounts=off refcount_bits=16
+Formatting 'TEST_DIR/PID-mid', fmt=qcow2 size=1048576 backing_file=TEST_DIR/PID-base cluster_size=65536 lazy_refcounts=off refcount_bits=16 compression_type=zlib
-Formatting 'TEST_DIR/PID-top', fmt=qcow2 size=2097152 backing_file=TEST_DIR/PID-mid cluster_size=65536 lazy_refcounts=off refcount_bits=16
+Formatting 'TEST_DIR/PID-top', fmt=qcow2 size=2097152 backing_file=TEST_DIR/PID-mid cluster_size=65536 lazy_refcounts=off refcount_bits=16 compression_type=zlib
wrote 2097152/2097152 bytes at offset 0
2 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
@@ -81,6 +82,7 @@
backing file: TEST_DIR/PID-base
Format specific information:
compat: 1.1
+ compression type: zlib
lazy refcounts: false
refcount bits: 16
corrupt: false
@@ -92,11 +94,11 @@
1 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
=== Testing QMP active commit (top -> mid) ===
-Formatting 'TEST_DIR/PID-base', fmt=qcow2 size=2097152 cluster_size=65536 lazy_refcounts=off refcount_bits=16
+Formatting 'TEST_DIR/PID-base', fmt=qcow2 size=2097152 cluster_size=65536 lazy_refcounts=off refcount_bits=16 compression_type=zlib
-Formatting 'TEST_DIR/PID-mid', fmt=qcow2 size=1048576 backing_file=TEST_DIR/PID-base cluster_size=65536 lazy_refcounts=off refcount_bits=16
+Formatting 'TEST_DIR/PID-mid', fmt=qcow2 size=1048576 backing_file=TEST_DIR/PID-base cluster_size=65536 lazy_refcounts=off refcount_bits=16 compression_type=zlib
-Formatting 'TEST_DIR/PID-top', fmt=qcow2 size=2097152 backing_file=TEST_DIR/PID-mid cluster_size=65536 lazy_refcounts=off refcount_bits=16
+Formatting 'TEST_DIR/PID-top', fmt=qcow2 size=2097152 backing_file=TEST_DIR/PID-mid cluster_size=65536 lazy_refcounts=off refcount_bits=16 compression_type=zlib
wrote 2097152/2097152 bytes at offset 0
2 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
@@ -116,6 +118,7 @@
backing file: TEST_DIR/PID-base
Format specific information:
compat: 1.1
+ compression type: zlib
lazy refcounts: false
refcount bits: 16
corrupt: false
@@ -128,9 +131,9 @@
== Resize tests ==
=== preallocation=off ===
-Formatting 'TEST_DIR/PID-base', fmt=qcow2 size=6442450944 cluster_size=65536 lazy_refcounts=off refcount_bits=16
+Formatting 'TEST_DIR/PID-base', fmt=qcow2 size=6442450944 cluster_size=65536 lazy_refcounts=off refcount_bits=16 compression_type=zlib
-Formatting 'TEST_DIR/PID-top', fmt=qcow2 size=1073741824 backing_file=TEST_DIR/PID-base cluster_size=65536 lazy_refcounts=off refcount_bits=16
+Formatting 'TEST_DIR/PID-top', fmt=qcow2 size=1073741824 backing_file=TEST_DIR/PID-base cluster_size=65536 lazy_refcounts=off refcount_bits=16 compression_type=zlib
wrote 65536/65536 bytes at offset 5368709120
64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
@@ -147,9 +150,9 @@
{ "start": 1073741824, "length": 7516192768, "depth": 0, "zero": true, "data": false}]
=== preallocation=metadata ===
-Formatting 'TEST_DIR/PID-base', fmt=qcow2 size=34359738368 cluster_size=65536 lazy_refcounts=off refcount_bits=16
+Formatting 'TEST_DIR/PID-base', fmt=qcow2 size=34359738368 cluster_size=65536 lazy_refcounts=off refcount_bits=16 compression_type=zlib
-Formatting 'TEST_DIR/PID-top', fmt=qcow2 size=32212254720 backing_file=TEST_DIR/PID-base cluster_size=65536 lazy_refcounts=off refcount_bits=16
+Formatting 'TEST_DIR/PID-top', fmt=qcow2 size=32212254720 backing_file=TEST_DIR/PID-base cluster_size=65536 lazy_refcounts=off refcount_bits=16 compression_type=zlib
wrote 65536/65536 bytes at offset 33285996544
64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
@@ -171,9 +174,9 @@
{ "start": 34896609280, "length": 536870912, "depth": 0, "zero": true, "data": false, "offset": 2685075456}]
=== preallocation=falloc ===
-Formatting 'TEST_DIR/PID-base', fmt=qcow2 size=10485760 cluster_size=65536 lazy_refcounts=off refcount_bits=16
+Formatting 'TEST_DIR/PID-base', fmt=qcow2 size=10485760 cluster_size=65536 lazy_refcounts=off refcount_bits=16 compression_type=zlib
-Formatting 'TEST_DIR/PID-top', fmt=qcow2 size=5242880 backing_file=TEST_DIR/PID-base cluster_size=65536 lazy_refcounts=off refcount_bits=16
+Formatting 'TEST_DIR/PID-top', fmt=qcow2 size=5242880 backing_file=TEST_DIR/PID-base cluster_size=65536 lazy_refcounts=off refcount_bits=16 compression_type=zlib
wrote 65536/65536 bytes at offset 9437184
64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
@@ -190,9 +193,9 @@
{ "start": 5242880, "length": 10485760, "depth": 0, "zero": false, "data": true, "offset": 327680}]
=== preallocation=full ===
-Formatting 'TEST_DIR/PID-base', fmt=qcow2 size=16777216 cluster_size=65536 lazy_refcounts=off refcount_bits=16
+Formatting 'TEST_DIR/PID-base', fmt=qcow2 size=16777216 cluster_size=65536 lazy_refcounts=off refcount_bits=16 compression_type=zlib
-Formatting 'TEST_DIR/PID-top', fmt=qcow2 size=8388608 backing_file=TEST_DIR/PID-base cluster_size=65536 lazy_refcounts=off refcount_bits=16
+Formatting 'TEST_DIR/PID-top', fmt=qcow2 size=8388608 backing_file=TEST_DIR/PID-base cluster_size=65536 lazy_refcounts=off refcount_bits=16 compression_type=zlib
wrote 65536/65536 bytes at offset 11534336
64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
@@ -209,9 +212,9 @@
{ "start": 8388608, "length": 4194304, "depth": 0, "zero": false, "data": true, "offset": 327680}]
=== preallocation=off ===
-Formatting 'TEST_DIR/PID-base', fmt=qcow2 size=393216 cluster_size=65536 lazy_refcounts=off refcount_bits=16
+Formatting 'TEST_DIR/PID-base', fmt=qcow2 size=393216 cluster_size=65536 lazy_refcounts=off refcount_bits=16 compression_type=zlib
-Formatting 'TEST_DIR/PID-top', fmt=qcow2 size=259072 backing_file=TEST_DIR/PID-base cluster_size=65536 lazy_refcounts=off refcount_bits=16
+Formatting 'TEST_DIR/PID-top', fmt=qcow2 size=259072 backing_file=TEST_DIR/PID-base cluster_size=65536 lazy_refcounts=off refcount_bits=16 compression_type=zlib
wrote 65536/65536 bytes at offset 259072
64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
@@ -229,9 +232,9 @@
{ "start": 262144, "length": 262144, "depth": 0, "zero": true, "data": false}]
=== preallocation=off ===
-Formatting 'TEST_DIR/PID-base', fmt=qcow2 size=409600 cluster_size=65536 lazy_refcounts=off refcount_bits=16
+Formatting 'TEST_DIR/PID-base', fmt=qcow2 size=409600 cluster_size=65536 lazy_refcounts=off refcount_bits=16 compression_type=zlib
-Formatting 'TEST_DIR/PID-top', fmt=qcow2 size=262144 backing_file=TEST_DIR/PID-base cluster_size=65536 lazy_refcounts=off refcount_bits=16
+Formatting 'TEST_DIR/PID-top', fmt=qcow2 size=262144 backing_file=TEST_DIR/PID-base cluster_size=65536 lazy_refcounts=off refcount_bits=16 compression_type=zlib
wrote 65536/65536 bytes at offset 344064
64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
@@ -248,9 +251,9 @@
{ "start": 262144, "length": 262144, "depth": 0, "zero": true, "data": false}]
=== preallocation=off ===
-Formatting 'TEST_DIR/PID-base', fmt=qcow2 size=524288 cluster_size=65536 lazy_refcounts=off refcount_bits=16
+Formatting 'TEST_DIR/PID-base', fmt=qcow2 size=524288 cluster_size=65536 lazy_refcounts=off refcount_bits=16 compression_type=zlib
-Formatting 'TEST_DIR/PID-top', fmt=qcow2 size=262144 backing_file=TEST_DIR/PID-base cluster_size=65536 lazy_refcounts=off refcount_bits=16
+Formatting 'TEST_DIR/PID-top', fmt=qcow2 size=262144 backing_file=TEST_DIR/PID-base cluster_size=65536 lazy_refcounts=off refcount_bits=16 compression_type=zlib
wrote 65536/65536 bytes at offset 446464
64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
diff --git a/tests/qemu-iotests/280.out b/tests/qemu-iotests/280.out
index 5d382fa..92e4d14 100644
--- a/tests/qemu-iotests/280.out
+++ b/tests/qemu-iotests/280.out
@@ -1,4 +1,4 @@
-Formatting 'TEST_DIR/PID-base', fmt=qcow2 size=67108864 cluster_size=65536 lazy_refcounts=off refcount_bits=16
+Formatting 'TEST_DIR/PID-base', fmt=qcow2 size=67108864 cluster_size=65536 lazy_refcounts=off refcount_bits=16 compression_type=zlib
=== Launch VM ===
Enabling migration QMP events on VM...
diff --git a/tests/qemu-iotests/287 b/tests/qemu-iotests/287
new file mode 100755
index 0000000..f98a4ca
--- /dev/null
+++ b/tests/qemu-iotests/287
@@ -0,0 +1,152 @@
+#!/usr/bin/env bash
+#
+# Test case for an image using zstd compression
+#
+# 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/>.
+#
+
+# creator
+owner=dplotnikov@virtuozzo.com
+
+seq="$(basename $0)"
+echo "QA output created by $seq"
+
+status=1 # failure is the default!
+
+# standard environment
+. ./common.rc
+. ./common.filter
+
+# This tests qocw2-specific low-level functionality
+_supported_fmt qcow2
+_supported_proto file
+_supported_os Linux
+_unsupported_imgopts 'compat=0.10' data_file
+
+COMPR_IMG="$TEST_IMG.compressed"
+RAND_FILE="$TEST_DIR/rand_data"
+
+_cleanup()
+{
+ _cleanup_test_img
+ _rm_test_img "$COMPR_IMG"
+ rm -f "$RAND_FILE"
+}
+trap "_cleanup; exit \$status" 0 1 2 3 15
+
+# for all the cases
+CLUSTER_SIZE=65536
+
+# Check if we can run this test.
+if IMGOPTS='compression_type=zstd' _make_test_img 64M |
+ grep "Invalid parameter 'zstd'"; then
+ _notrun "ZSTD is disabled"
+fi
+
+echo
+echo "=== Testing compression type incompatible bit setting for zlib ==="
+echo
+_make_test_img -o compression_type=zlib 64M
+$PYTHON qcow2.py "$TEST_IMG" dump-header | grep incompatible_features
+
+echo
+echo "=== Testing compression type incompatible bit setting for zstd ==="
+echo
+_make_test_img -o compression_type=zstd 64M
+$PYTHON qcow2.py "$TEST_IMG" dump-header | grep incompatible_features
+
+echo
+echo "=== Testing zlib with incompatible bit set ==="
+echo
+_make_test_img -o compression_type=zlib 64M
+$PYTHON qcow2.py "$TEST_IMG" set-feature-bit incompatible 3
+# to make sure the bit was actually set
+$PYTHON qcow2.py "$TEST_IMG" dump-header | grep incompatible_features
+
+if $QEMU_IMG info "$TEST_IMG" >/dev/null 2>&1 ; then
+ echo "Error: The image opened successfully. The image must not be opened."
+fi
+
+echo
+echo "=== Testing zstd with incompatible bit unset ==="
+echo
+_make_test_img -o compression_type=zstd 64M
+$PYTHON qcow2.py "$TEST_IMG" set-header incompatible_features 0
+# to make sure the bit was actually unset
+$PYTHON qcow2.py "$TEST_IMG" dump-header | grep incompatible_features
+
+if $QEMU_IMG info "$TEST_IMG" >/dev/null 2>&1 ; then
+ echo "Error: The image opened successfully. The image must not be opened."
+fi
+
+echo
+echo "=== Testing compression type values ==="
+echo
+# zlib=0
+_make_test_img -o compression_type=zlib 64M
+peek_file_be "$TEST_IMG" 104 1
+echo
+
+# zstd=1
+_make_test_img -o compression_type=zstd 64M
+peek_file_be "$TEST_IMG" 104 1
+echo
+
+echo
+echo "=== Testing simple reading and writing with zstd ==="
+echo
+_make_test_img -o compression_type=zstd 64M
+$QEMU_IO -c "write -c -P 0xAC 64K 64K " "$TEST_IMG" | _filter_qemu_io
+$QEMU_IO -c "read -P 0xAC 64K 64K " "$TEST_IMG" | _filter_qemu_io
+# read on the cluster boundaries
+$QEMU_IO -c "read -v 131070 8 " "$TEST_IMG" | _filter_qemu_io
+$QEMU_IO -c "read -v 65534 8" "$TEST_IMG" | _filter_qemu_io
+
+echo
+echo "=== Testing adjacent clusters reading and writing with zstd ==="
+echo
+_make_test_img -o compression_type=zstd 64M
+$QEMU_IO -c "write -c -P 0xAB 0 64K " "$TEST_IMG" | _filter_qemu_io
+$QEMU_IO -c "write -c -P 0xAC 64K 64K " "$TEST_IMG" | _filter_qemu_io
+$QEMU_IO -c "write -c -P 0xAD 128K 64K " "$TEST_IMG" | _filter_qemu_io
+
+$QEMU_IO -c "read -P 0xAB 0 64k " "$TEST_IMG" | _filter_qemu_io
+$QEMU_IO -c "read -P 0xAC 64K 64k " "$TEST_IMG" | _filter_qemu_io
+$QEMU_IO -c "read -P 0xAD 128K 64k " "$TEST_IMG" | _filter_qemu_io
+
+echo
+echo "=== Testing incompressible cluster processing with zstd ==="
+echo
+# create a 2M image and fill it with 1M likely incompressible data
+# and 1M compressible data
+dd if=/dev/urandom of="$RAND_FILE" bs=1M count=1 seek=1
+QEMU_IO_OPTIONS="$QEMU_IO_OPTIONS_NO_FMT" \
+$QEMU_IO -f raw -c "write -P 0xFA 0 1M" "$RAND_FILE" | _filter_qemu_io
+
+$QEMU_IMG convert -f raw -O $IMGFMT -c \
+-o "$(_optstr_add "$IMGOPTS" "compression_type=zlib")" "$RAND_FILE" \
+"$TEST_IMG" | _filter_qemu_io
+
+$QEMU_IMG convert -O $IMGFMT -c \
+-o "$(_optstr_add "$IMGOPTS" "compression_type=zstd")" "$TEST_IMG" \
+"$COMPR_IMG" | _filter_qemu_io
+
+$QEMU_IMG compare "$TEST_IMG" "$COMPR_IMG"
+
+# success, all done
+echo "*** done"
+rm -f $seq.full
+status=0
diff --git a/tests/qemu-iotests/287.out b/tests/qemu-iotests/287.out
new file mode 100644
index 0000000..6b9dfb4
--- /dev/null
+++ b/tests/qemu-iotests/287.out
@@ -0,0 +1,67 @@
+QA output created by 287
+
+=== Testing compression type incompatible bit setting for zlib ===
+
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864
+incompatible_features []
+
+=== Testing compression type incompatible bit setting for zstd ===
+
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864
+incompatible_features [3]
+
+=== Testing zlib with incompatible bit set ===
+
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864
+incompatible_features [3]
+
+=== Testing zstd with incompatible bit unset ===
+
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864
+incompatible_features []
+
+=== Testing compression type values ===
+
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864
+ 0
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864
+ 1
+
+=== Testing simple reading and writing with zstd ===
+
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864
+wrote 65536/65536 bytes at offset 65536
+64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 65536/65536 bytes at offset 65536
+64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+0001fffe: ac ac 00 00 00 00 00 00 ........
+read 8/8 bytes at offset 131070
+8 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+0000fffe: 00 00 ac ac ac ac ac ac ........
+read 8/8 bytes at offset 65534
+8 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
+=== Testing adjacent clusters reading and writing with zstd ===
+
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864
+wrote 65536/65536 bytes at offset 0
+64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 65536/65536 bytes at offset 65536
+64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 65536/65536 bytes at offset 131072
+64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 65536/65536 bytes at offset 0
+64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 65536/65536 bytes at offset 65536
+64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 65536/65536 bytes at offset 131072
+64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
+=== Testing incompressible cluster processing with zstd ===
+
+1+0 records in
+1+0 records out
+wrote 1048576/1048576 bytes at offset 0
+1 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+Images are identical.
+*** done
diff --git a/tests/qemu-iotests/291 b/tests/qemu-iotests/291
new file mode 100755
index 0000000..3ca83b9
--- /dev/null
+++ b/tests/qemu-iotests/291
@@ -0,0 +1,112 @@
+#!/usr/bin/env bash
+#
+# Test qemu-img bitmap handling
+#
+# Copyright (C) 2018-2020 Red Hat, Inc.
+#
+# 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/>.
+#
+
+seq="$(basename $0)"
+echo "QA output created by $seq"
+
+status=1 # failure is the default!
+
+_cleanup()
+{
+ _cleanup_test_img
+ nbd_server_stop
+}
+trap "_cleanup; exit \$status" 0 1 2 3 15
+
+# get standard environment, filters and checks
+. ./common.rc
+. ./common.filter
+. ./common.nbd
+
+_supported_fmt qcow2
+_supported_proto file
+_supported_os Linux
+_require_command QEMU_NBD
+
+echo
+echo "=== Initial image setup ==="
+echo
+
+# Create backing image with one bitmap
+TEST_IMG="$TEST_IMG.base" _make_test_img 10M
+$QEMU_IMG bitmap --add -f $IMGFMT "$TEST_IMG.base" b0
+$QEMU_IO -c 'w 3M 1M' -f $IMGFMT "$TEST_IMG.base" | _filter_qemu_io
+
+# Create initial image and populate two bitmaps: one active, one inactive.
+ORIG_IMG=$TEST_IMG
+TEST_IMG=$TEST_IMG.orig
+_make_test_img -b "$ORIG_IMG.base" -F $IMGFMT 10M
+$QEMU_IO -c 'w 0 1M' -f $IMGFMT "$TEST_IMG" | _filter_qemu_io
+$QEMU_IMG bitmap --add -g 512k -f $IMGFMT "$TEST_IMG" b1
+$QEMU_IMG bitmap --add --disable -f $IMGFMT "$TEST_IMG" b2
+$QEMU_IO -c 'w 3M 1M' -f $IMGFMT "$TEST_IMG" | _filter_qemu_io
+$QEMU_IMG bitmap --clear -f $IMGFMT "$TEST_IMG" b1
+$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
+echo "=== Bitmap preservation not possible to non-qcow2 ==="
+echo
+
+TEST_IMG=$ORIG_IMG
+$QEMU_IMG convert --bitmaps -O raw "$TEST_IMG.orig" "$TEST_IMG" &&
+ echo "unexpected success"
+
+echo
+echo "=== Convert with bitmap preservation ==="
+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
+# 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
+$QEMU_IMG bitmap --add --disable -f $IMGFMT "$TEST_IMG" b0
+$QEMU_IMG bitmap --add --merge b0 -b "$TEST_IMG.base" -F $IMGFMT \
+ -f $IMGFMT "$TEST_IMG" tmp
+$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
+
+echo
+echo "=== Check bitmap contents ==="
+echo
+
+# x-dirty-bitmap is a hack for reading bitmaps; it abuses block status to
+# report "data":false for portions of the bitmap which are set
+IMG="driver=nbd,server.type=unix,server.path=$nbd_unix_socket"
+nbd_server_start_unix_socket -r -f qcow2 -B b0 "$TEST_IMG"
+$QEMU_IMG map --output=json --image-opts \
+ "$IMG,x-dirty-bitmap=qemu:dirty-bitmap:b0" | _filter_qemu_img_map
+nbd_server_start_unix_socket -r -f qcow2 -B b1 "$TEST_IMG"
+$QEMU_IMG map --output=json --image-opts \
+ "$IMG,x-dirty-bitmap=qemu:dirty-bitmap:b1" | _filter_qemu_img_map
+nbd_server_start_unix_socket -r -f qcow2 -B b2 "$TEST_IMG"
+$QEMU_IMG map --output=json --image-opts \
+ "$IMG,x-dirty-bitmap=qemu:dirty-bitmap:b2" | _filter_qemu_img_map
+
+# success, all done
+echo '*** done'
+rm -f $seq.full
+status=0
diff --git a/tests/qemu-iotests/291.out b/tests/qemu-iotests/291.out
new file mode 100644
index 0000000..8c62017
--- /dev/null
+++ b/tests/qemu-iotests/291.out
@@ -0,0 +1,80 @@
+QA output created by 291
+
+=== Initial image setup ===
+
+Formatting 'TEST_DIR/t.IMGFMT.base', fmt=IMGFMT size=10485760
+wrote 1048576/1048576 bytes at offset 3145728
+1 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+Formatting 'TEST_DIR/t.IMGFMT.orig', fmt=IMGFMT size=10485760 backing_file=TEST_DIR/t.IMGFMT.base backing_fmt=IMGFMT
+wrote 1048576/1048576 bytes at offset 0
+1 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 1048576/1048576 bytes at offset 3145728
+1 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+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)
+
+=== Bitmap preservation not possible to non-qcow2 ===
+
+qemu-img: Format driver 'raw' does not support bitmaps
+
+=== Convert with bitmap preservation ===
+
+image: TEST_DIR/t.IMGFMT
+file format: IMGFMT
+virtual size: 10 MiB (10485760 bytes)
+disk size: 4.39 MiB
+Format specific information:
+ compat: 1.1
+ compression type: zlib
+ lazy refcounts: false
+ bitmaps:
+ [0]:
+ flags:
+ name: b1
+ granularity: 524288
+ [1]:
+ flags:
+ [0]: auto
+ name: b2
+ granularity: 65536
+ refcount bits: 16
+ corrupt: false
+image: TEST_DIR/t.IMGFMT
+file format: IMGFMT
+virtual size: 10 MiB (10485760 bytes)
+disk size: 4.48 MiB
+Format specific information:
+ compat: 1.1
+ compression type: zlib
+ lazy refcounts: false
+ bitmaps:
+ [0]:
+ flags:
+ name: b1
+ granularity: 524288
+ [1]:
+ flags:
+ [0]: auto
+ name: b2
+ granularity: 65536
+ [2]:
+ flags:
+ name: b0
+ granularity: 65536
+ refcount bits: 16
+ corrupt: false
+
+=== Check bitmap contents ===
+
+[{ "start": 0, "length": 3145728, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
+{ "start": 3145728, "length": 1048576, "depth": 0, "zero": false, "data": false},
+{ "start": 4194304, "length": 6291456, "depth": 0, "zero": false, "data": true, "offset": OFFSET}]
+[{ "start": 0, "length": 1048576, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
+{ "start": 1048576, "length": 1048576, "depth": 0, "zero": false, "data": false},
+{ "start": 2097152, "length": 8388608, "depth": 0, "zero": false, "data": true, "offset": OFFSET}]
+[{ "start": 0, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
+{ "start": 2097152, "length": 1048576, "depth": 0, "zero": false, "data": false},
+{ "start": 3145728, "length": 7340032, "depth": 0, "zero": false, "data": true, "offset": OFFSET}]
+*** done
diff --git a/tests/qemu-iotests/297 b/tests/qemu-iotests/297
new file mode 100755
index 0000000..5c54207
--- /dev/null
+++ b/tests/qemu-iotests/297
@@ -0,0 +1,44 @@
+#!/usr/bin/env bash
+#
+# Copyright (C) 2020 Red Hat, Inc.
+#
+# 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/>.
+
+seq=$(basename $0)
+echo "QA output created by $seq"
+
+status=1 # failure is the default!
+
+# get standard environment
+. ./common.rc
+
+if ! type -p "pylint-3" > /dev/null; then
+ _notrun "pylint-3 not found"
+fi
+if ! type -p "mypy" > /dev/null; then
+ _notrun "mypy not found"
+fi
+
+pylint-3 --score=n iotests.py
+
+MYPYPATH=../../python/ mypy --warn-unused-configs --disallow-subclassing-any \
+ --disallow-any-generics --disallow-incomplete-defs \
+ --disallow-untyped-decorators --no-implicit-optional \
+ --warn-redundant-casts --warn-unused-ignores \
+ --no-implicit-reexport iotests.py
+
+# success, all done
+echo "*** done"
+rm -f $seq.full
+status=0
diff --git a/tests/qemu-iotests/297.out b/tests/qemu-iotests/297.out
new file mode 100644
index 0000000..6acc843
--- /dev/null
+++ b/tests/qemu-iotests/297.out
@@ -0,0 +1,3 @@
+QA output created by 297
+Success: no issues found in 1 source file
+*** done
diff --git a/tests/qemu-iotests/common.filter b/tests/qemu-iotests/common.filter
index 3f8ee3e..03e4f71 100644
--- a/tests/qemu-iotests/common.filter
+++ b/tests/qemu-iotests/common.filter
@@ -152,7 +152,13 @@
-e "s# refcount_bits=[0-9]\\+##g" \
-e "s# key-secret=[a-zA-Z0-9]\\+##g" \
-e "s# iter-time=[0-9]\\+##g" \
- -e "s# force_size=\\(on\\|off\\)##g"
+ -e "s# force_size=\\(on\\|off\\)##g" \
+ -e "s# compression_type=[a-zA-Z0-9]\\+##g"
+}
+
+_filter_img_create_size()
+{
+ $SED -e "s# size=[0-9]\\+# size=SIZE#g"
}
_filter_img_info()
diff --git a/tests/qemu-iotests/group b/tests/qemu-iotests/group
index fe649c5..d886fa0 100644
--- a/tests/qemu-iotests/group
+++ b/tests/qemu-iotests/group
@@ -295,7 +295,10 @@
283 auto quick
284 rw
286 rw quick
+287 auto quick
288 quick
289 rw quick
290 rw auto quick
+291 rw quick
292 rw auto quick
+297 meta
diff --git a/tests/qemu-iotests/iotests.py b/tests/qemu-iotests/iotests.py
index 6c0e781..f20d90f 100644
--- a/tests/qemu-iotests/iotests.py
+++ b/tests/qemu-iotests/iotests.py
@@ -1040,7 +1040,7 @@
if supported_cache_modes and (cachemode not in supported_cache_modes):
notrun('not suitable for this cache mode: %s' % cachemode)
-def _verify_aio_mode(supported_aio_modes: Sequence[str] = ()):
+def _verify_aio_mode(supported_aio_modes: Sequence[str] = ()) -> None:
if supported_aio_modes and (aiomode not in supported_aio_modes):
notrun('not suitable for this aio mode: %s' % aiomode)
@@ -1087,7 +1087,8 @@
'''Skip Test Decorator
Runs the test if all the required formats are whitelisted'''
def skip_test_decorator(func):
- def func_wrapper(test_case: QMPTestCase, *args, **kwargs):
+ def func_wrapper(test_case: QMPTestCase, *args: List[Any],
+ **kwargs: Dict[str, Any]) -> None:
if callable(required_formats):
fmts = required_formats(test_case)
else:
@@ -1097,9 +1098,8 @@
if usf_list:
msg = f'{test_case}: formats {usf_list} are not whitelisted'
test_case.case_skip(msg)
- return None
else:
- return func(test_case, *args, **kwargs)
+ func(test_case, *args, **kwargs)
return func_wrapper
return skip_test_decorator
@@ -1168,18 +1168,17 @@
sys.stderr.write('Please run this test via the "check" script\n')
sys.exit(os.EX_USAGE)
+ debug = '-d' in sys.argv
+ if debug:
+ sys.argv.remove('-d')
+ logging.basicConfig(level=(logging.DEBUG if debug else logging.WARN))
+
_verify_image_format(supported_fmts, unsupported_fmts)
_verify_protocol(supported_protocols, unsupported_protocols)
_verify_platform(supported=supported_platforms)
_verify_cache_mode(supported_cache_modes)
_verify_aio_mode(supported_aio_modes)
- debug = '-d' in sys.argv
- if debug:
- sys.argv.remove('-d')
- logging.basicConfig(level=(logging.DEBUG if debug else logging.WARN))
- logger.debug("iotests debugging messages active")
-
return debug
def execute_test(*args, test_function=None, **kwargs):
diff --git a/tests/qemu-iotests/nbd-fault-injector.py b/tests/qemu-iotests/nbd-fault-injector.py
index 588d62a..78f42c4 100755
--- a/tests/qemu-iotests/nbd-fault-injector.py
+++ b/tests/qemu-iotests/nbd-fault-injector.py
@@ -47,10 +47,7 @@
import socket
import struct
import collections
-if sys.version_info.major >= 3:
- import configparser
-else:
- import ConfigParser as configparser
+import configparser
FAKE_DISK_SIZE = 8 * 1024 * 1024 * 1024 # 8 GB
diff --git a/tests/qtest/endianness-test.c b/tests/qtest/endianness-test.c
index 2798802..cc088ac 100644
--- a/tests/qtest/endianness-test.c
+++ b/tests/qtest/endianness-test.c
@@ -33,7 +33,7 @@
{ "mips64", "pica61", 0x90000000, .bswap = true },
{ "mips64", "mips", 0x14000000, .bswap = true },
{ "mips64", "malta", 0x10000000, .bswap = true },
- { "mips64el", "fulong2e", 0x1fd00000 },
+ { "mips64el", "fuloong2e", 0x1fd00000 },
{ "ppc", "g3beige", 0xfe000000, .bswap = true, .superio = "i82378" },
{ "ppc", "40p", 0x80000000, .bswap = true },
{ "ppc", "bamboo", 0xe8000000, .bswap = true, .superio = "i82378" },
diff --git a/tests/qtest/fuzz/Makefile.include b/tests/qtest/fuzz/Makefile.include
index cde3e96..f259d86 100644
--- a/tests/qtest/fuzz/Makefile.include
+++ b/tests/qtest/fuzz/Makefile.include
@@ -7,9 +7,9 @@
fuzz-obj-y += tests/qtest/fuzz/qos_fuzz.o
# Targets
-fuzz-obj-y += tests/qtest/fuzz/i440fx_fuzz.o
-fuzz-obj-y += tests/qtest/fuzz/virtio_net_fuzz.o
-fuzz-obj-y += tests/qtest/fuzz/virtio_scsi_fuzz.o
+fuzz-obj-$(CONFIG_PCI_I440FX) += tests/qtest/fuzz/i440fx_fuzz.o
+fuzz-obj-$(CONFIG_VIRTIO_NET) += tests/qtest/fuzz/virtio_net_fuzz.o
+fuzz-obj-$(CONFIG_SCSI) += tests/qtest/fuzz/virtio_scsi_fuzz.o
FUZZ_CFLAGS += -I$(SRC_PATH)/tests -I$(SRC_PATH)/tests/qtest
diff --git a/tests/qtest/fuzz/i440fx_fuzz.c b/tests/qtest/fuzz/i440fx_fuzz.c
index ab5f112..bcd6769 100644
--- a/tests/qtest/fuzz/i440fx_fuzz.c
+++ b/tests/qtest/fuzz/i440fx_fuzz.c
@@ -39,18 +39,17 @@
ACTION_MAX
};
-static void i440fx_fuzz_qtest(QTestState *s,
+static void ioport_fuzz_qtest(QTestState *s,
const unsigned char *Data, size_t Size) {
/*
* loop over the Data, breaking it up into actions. each action has an
* opcode, address offset and value
*/
- typedef struct QTestFuzzAction {
+ struct {
uint8_t opcode;
uint8_t addr;
uint32_t value;
- } QTestFuzzAction;
- QTestFuzzAction a;
+ } a;
while (Size >= sizeof(a)) {
/* make a copy of the action so we can normalize the values in-place */
@@ -85,25 +84,26 @@
flush_events(s);
}
-static void i440fx_fuzz_qos(QTestState *s,
+static void i440fx_fuzz_qtest(QTestState *s,
+ const unsigned char *Data,
+ size_t Size)
+{
+ ioport_fuzz_qtest(s, Data, Size);
+}
+
+static void pciconfig_fuzz_qos(QTestState *s, QPCIBus *bus,
const unsigned char *Data, size_t Size) {
/*
- * Same as i440fx_fuzz_qtest, but using QOS. devfn is incorporated into the
+ * Same as ioport_fuzz_qtest, but using QOS. devfn is incorporated into the
* value written over Port IO
*/
- typedef struct QOSFuzzAction {
+ struct {
uint8_t opcode;
uint8_t offset;
int devfn;
uint32_t value;
- } QOSFuzzAction;
+ } a;
- static QPCIBus *bus;
- if (!bus) {
- bus = qpci_new_pc(s, fuzz_qos_alloc);
- }
-
- QOSFuzzAction a;
while (Size >= sizeof(a)) {
memcpy(&a, Data, sizeof(a));
switch (a.opcode % ACTION_MAX) {
@@ -132,6 +132,19 @@
flush_events(s);
}
+static void i440fx_fuzz_qos(QTestState *s,
+ const unsigned char *Data,
+ size_t Size)
+{
+ static QPCIBus *bus;
+
+ if (!bus) {
+ bus = qpci_new_pc(s, fuzz_qos_alloc);
+ }
+
+ pciconfig_fuzz_qos(s, bus, Data, Size);
+}
+
static void i440fx_fuzz_qos_fork(QTestState *s,
const unsigned char *Data, size_t Size) {
if (fork() == 0) {
@@ -159,7 +172,7 @@
/* Uses simple qtest commands and reboots to reset state */
fuzz_add_target(&(FuzzTarget){
.name = "i440fx-qtest-reboot-fuzz",
- .description = "Fuzz the i440fx using raw qtest commands and"
+ .description = "Fuzz the i440fx using raw qtest commands and "
"rebooting after each run",
.get_init_cmdline = i440fx_argv,
.fuzz = i440fx_fuzz_qtest});
@@ -167,7 +180,7 @@
/* Uses libqos and forks to prevent state leakage */
fuzz_add_qos_target(&(FuzzTarget){
.name = "i440fx-qos-fork-fuzz",
- .description = "Fuzz the i440fx using raw qtest commands and"
+ .description = "Fuzz the i440fx using raw qtest commands and "
"rebooting after each run",
.pre_vm_init = &fork_init,
.fuzz = i440fx_fuzz_qos_fork,},
@@ -182,7 +195,7 @@
*/
fuzz_add_qos_target(&(FuzzTarget){
.name = "i440fx-qos-noreset-fuzz",
- .description = "Fuzz the i440fx using raw qtest commands and"
+ .description = "Fuzz the i440fx using raw qtest commands and "
"rebooting after each run",
.fuzz = i440fx_fuzz_qos,},
"i440FX-pcihost",
diff --git a/tests/qtest/migration-test.c b/tests/qtest/migration-test.c
index 2568c95..dc3490c 100644
--- a/tests/qtest/migration-test.c
+++ b/tests/qtest/migration-test.c
@@ -13,6 +13,7 @@
#include "qemu/osdep.h"
#include "libqtest.h"
+#include "qapi/error.h"
#include "qapi/qmp/qdict.h"
#include "qemu/module.h"
#include "qemu/option.h"
@@ -301,7 +302,6 @@
{
QDict *rsp;
char *result;
- Error *local_err = NULL;
SocketAddressList *addrs;
Visitor *iv = NULL;
QObject *object;
@@ -310,7 +310,7 @@
object = qdict_get(rsp, parameter);
iv = qobject_input_visitor_new(object);
- visit_type_SocketAddressList(iv, NULL, &addrs, &local_err);
+ visit_type_SocketAddressList(iv, NULL, &addrs, &error_abort);
visit_free(iv);
/* we are only using a single address */
diff --git a/tests/qtest/test-hmp.c b/tests/qtest/test-hmp.c
index f8aa5f9..b8b1271 100644
--- a/tests/qtest/test-hmp.c
+++ b/tests/qtest/test-hmp.c
@@ -61,6 +61,7 @@
"p $pc + 8",
"qom-list /",
"qom-set /machine initrd test",
+ "qom-get /machine initrd",
"screendump /dev/null",
"sendkey x",
"singlestep on",
diff --git a/tests/tcg/aarch64/Makefile.softmmu-target b/tests/tcg/aarch64/Makefile.softmmu-target
index 71f72cf..1057a8a 100644
--- a/tests/tcg/aarch64/Makefile.softmmu-target
+++ b/tests/tcg/aarch64/Makefile.softmmu-target
@@ -61,7 +61,7 @@
$(QEMU_OPTS) memory, \
"$< on $(TARGET_NAME)")
-EXTRA_TESTS+=memory-record memory-replay
+EXTRA_RUNS+=run-memory-replay
ifneq ($(DOCKER_IMAGE)$(CROSS_CC_HAS_ARMV8_3),)
pauth-3: CFLAGS += -march=armv8.3-a
diff --git a/tests/tcg/configure.sh b/tests/tcg/configure.sh
index eaaaff6..2326f97 100755
--- a/tests/tcg/configure.sh
+++ b/tests/tcg/configure.sh
@@ -97,8 +97,8 @@
case $target in
aarch64-*)
# We don't have any bigendian build tools so we only use this for AArch64
- container_image=debian-arm64-cross
- container_cross_cc=aarch64-linux-gnu-gcc
+ container_image=debian-arm64-test-cross
+ container_cross_cc=aarch64-linux-gnu-gcc-10
;;
alpha-*)
container_image=debian-alpha-cross
diff --git a/tests/tcg/i386/test-i386-pseudo-denormal.c b/tests/tcg/i386/test-i386-pseudo-denormal.c
new file mode 100644
index 0000000..00d510c
--- /dev/null
+++ b/tests/tcg/i386/test-i386-pseudo-denormal.c
@@ -0,0 +1,38 @@
+/* Test pseudo-denormal operations. */
+
+#include <stdint.h>
+#include <stdio.h>
+
+union u {
+ struct { uint64_t sig; uint16_t sign_exp; } s;
+ long double ld;
+};
+
+volatile union u ld_pseudo_m16382 = { .s = { UINT64_C(1) << 63, 0 } };
+
+volatile long double ld_res;
+
+int main(void)
+{
+ short cw;
+ int ret = 0;
+ ld_res = ld_pseudo_m16382.ld + ld_pseudo_m16382.ld;
+ if (ld_res != 0x1p-16381L) {
+ printf("FAIL: pseudo-denormal add\n");
+ ret = 1;
+ }
+ if (ld_pseudo_m16382.ld != 0x1p-16382L) {
+ printf("FAIL: pseudo-denormal compare\n");
+ ret = 1;
+ }
+ /* Set round-upward. */
+ __asm__ volatile ("fnstcw %0" : "=m" (cw));
+ cw = (cw & ~0xc00) | 0x800;
+ __asm__ volatile ("fldcw %0" : : "m" (cw));
+ __asm__ ("frndint" : "=t" (ld_res) : "0" (ld_pseudo_m16382.ld));
+ if (ld_res != 1.0L) {
+ printf("FAIL: pseudo-denormal round-to-integer\n");
+ ret = 1;
+ }
+ return ret;
+}
diff --git a/tests/tcg/i386/test-i386-snan-convert.c b/tests/tcg/i386/test-i386-snan-convert.c
new file mode 100644
index 0000000..ed6d535
--- /dev/null
+++ b/tests/tcg/i386/test-i386-snan-convert.c
@@ -0,0 +1,63 @@
+/* Test conversions of signaling NaNs to and from long double. */
+
+#include <stdint.h>
+#include <stdio.h>
+
+volatile float f_res;
+volatile double d_res;
+volatile long double ld_res;
+
+volatile float f_snan = __builtin_nansf("");
+volatile double d_snan = __builtin_nans("");
+volatile long double ld_snan = __builtin_nansl("");
+
+int issignaling_f(float x)
+{
+ union { float f; uint32_t u; } u = { .f = x };
+ return (u.u & 0x7fffffff) > 0x7f800000 && (u.u & 0x400000) == 0;
+}
+
+int issignaling_d(double x)
+{
+ union { double d; uint64_t u; } u = { .d = x };
+ return (((u.u & UINT64_C(0x7fffffffffffffff)) >
+ UINT64_C(0x7ff0000000000000)) &&
+ (u.u & UINT64_C(0x8000000000000)) == 0);
+}
+
+int issignaling_ld(long double x)
+{
+ union {
+ long double ld;
+ struct { uint64_t sig; uint16_t sign_exp; } s;
+ } u = { .ld = x };
+ return ((u.s.sign_exp & 0x7fff) == 0x7fff &&
+ (u.s.sig >> 63) != 0 &&
+ (u.s.sig & UINT64_C(0x4000000000000000)) == 0);
+}
+
+int main(void)
+{
+ int ret = 0;
+ ld_res = f_snan;
+ if (issignaling_ld(ld_res)) {
+ printf("FAIL: float -> long double\n");
+ ret = 1;
+ }
+ ld_res = d_snan;
+ if (issignaling_ld(ld_res)) {
+ printf("FAIL: double -> long double\n");
+ ret = 1;
+ }
+ f_res = ld_snan;
+ if (issignaling_d(f_res)) {
+ printf("FAIL: long double -> float\n");
+ ret = 1;
+ }
+ d_res = ld_snan;
+ if (issignaling_d(d_res)) {
+ printf("FAIL: long double -> double\n");
+ ret = 1;
+ }
+ return ret;
+}
diff --git a/tests/tcg/multiarch/Makefile.target b/tests/tcg/multiarch/Makefile.target
index 51fb75e..cb49cc9 100644
--- a/tests/tcg/multiarch/Makefile.target
+++ b/tests/tcg/multiarch/Makefile.target
@@ -28,6 +28,8 @@
testthread: LDFLAGS+=-lpthread
+threadcount: LDFLAGS+=-lpthread
+
# We define the runner for test-mmap after the individual
# architectures have defined their supported pages sizes. If no
# additional page sizes are defined we only run the default test.
diff --git a/tests/tcg/multiarch/gdbstub/sha1.py b/tests/tcg/multiarch/gdbstub/sha1.py
index 734553b..2bfde49 100644
--- a/tests/tcg/multiarch/gdbstub/sha1.py
+++ b/tests/tcg/multiarch/gdbstub/sha1.py
@@ -65,6 +65,10 @@
print("SKIPPING (not connected)", file=sys.stderr)
exit(0)
+if gdb.parse_and_eval('$pc') == 0:
+ print("SKIP: PC not set")
+ exit(0)
+
try:
# These are not very useful in scripts
gdb.execute("set pagination off")
diff --git a/tests/tcg/multiarch/threadcount.c b/tests/tcg/multiarch/threadcount.c
new file mode 100644
index 0000000..545a1c8
--- /dev/null
+++ b/tests/tcg/multiarch/threadcount.c
@@ -0,0 +1,64 @@
+/*
+ * Thread Exerciser
+ *
+ * Unlike testthread which is mainly concerned about testing thread
+ * semantics this test is used to exercise the thread creation and
+ * accounting. A version of this test found a problem with clashing
+ * cpu_indexes which caused a break in plugin handling.
+ *
+ * Based on the original test case by Nikolay Igotti.
+ *
+ * Copyright (c) 2020 Linaro Ltd
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <pthread.h>
+
+int max_threads = 10;
+
+typedef struct {
+ int delay;
+} ThreadArg;
+
+static void *thread_fn(void* varg)
+{
+ ThreadArg *arg = varg;
+ usleep(arg->delay);
+ free(arg);
+ return NULL;
+}
+
+int main(int argc, char **argv)
+{
+ int i;
+ pthread_t *threads;
+
+ if (argc > 1) {
+ max_threads = atoi(argv[1]);
+ }
+ threads = calloc(sizeof(pthread_t), max_threads);
+
+ for (i = 0; i < max_threads; i++) {
+ ThreadArg *arg = calloc(sizeof(ThreadArg), 1);
+ arg->delay = i * 100;
+ pthread_create(threads + i, NULL, thread_fn, arg);
+ }
+
+ printf("Created %d threads\n", max_threads);
+
+ /* sleep until roughly half the threads have "finished" */
+ usleep(max_threads * 50);
+
+ for (i = 0; i < max_threads; i++) {
+ pthread_join(threads[i], NULL);
+ }
+
+ printf("Done\n");
+
+ return 0;
+}
diff --git a/tests/test-bdrv-drain.c b/tests/test-bdrv-drain.c
index fa0e6a6..1107271 100644
--- a/tests/test-bdrv-drain.c
+++ b/tests/test-bdrv-drain.c
@@ -85,22 +85,6 @@
return 0;
}
-static void bdrv_test_child_perm(BlockDriverState *bs, BdrvChild *c,
- const BdrvChildRole *role,
- BlockReopenQueue *reopen_queue,
- uint64_t perm, uint64_t shared,
- uint64_t *nperm, uint64_t *nshared)
-{
- /* bdrv_format_default_perms() accepts only these two, so disguise
- * detach_by_driver_cb_role as one of them. */
- if (role != &child_file && role != &child_backing) {
- role = &child_file;
- }
-
- bdrv_format_default_perms(bs, c, role, reopen_queue, perm, shared,
- nperm, nshared);
-}
-
static int bdrv_test_change_backing_file(BlockDriverState *bs,
const char *backing_file,
const char *backing_fmt)
@@ -118,7 +102,7 @@
.bdrv_co_drain_begin = bdrv_test_co_drain_begin,
.bdrv_co_drain_end = bdrv_test_co_drain_end,
- .bdrv_child_perm = bdrv_test_child_perm,
+ .bdrv_child_perm = bdrv_default_perms,
.bdrv_change_backing_file = bdrv_test_change_backing_file,
};
@@ -1134,7 +1118,7 @@
.bdrv_close = bdrv_test_top_close,
.bdrv_co_preadv = bdrv_test_top_co_preadv,
- .bdrv_child_perm = bdrv_format_default_perms,
+ .bdrv_child_perm = bdrv_default_perms,
};
typedef struct TestCoDeleteByDrainData {
@@ -1200,7 +1184,8 @@
null_bs = bdrv_open("null-co://", NULL, NULL, BDRV_O_RDWR | BDRV_O_PROTOCOL,
&error_abort);
- bdrv_attach_child(bs, null_bs, "null-child", &child_file, &error_abort);
+ bdrv_attach_child(bs, null_bs, "null-child", &child_of_bds,
+ BDRV_CHILD_DATA, &error_abort);
/* This child will be the one to pass to requests through to, and
* it will stall until a drain occurs */
@@ -1208,14 +1193,17 @@
&error_abort);
child_bs->total_sectors = 65536 >> BDRV_SECTOR_BITS;
/* Takes our reference to child_bs */
- tts->wait_child = bdrv_attach_child(bs, child_bs, "wait-child", &child_file,
+ tts->wait_child = bdrv_attach_child(bs, child_bs, "wait-child",
+ &child_of_bds,
+ BDRV_CHILD_DATA | BDRV_CHILD_PRIMARY,
&error_abort);
/* 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_attach_child(bs, null_bs, "null-child", &child_file, &error_abort);
+ bdrv_attach_child(bs, null_bs, "null-child", &child_of_bds, BDRV_CHILD_DATA,
+ &error_abort);
blk = blk_new(qemu_get_aio_context(), BLK_PERM_ALL, BLK_PERM_ALL);
blk_insert_bs(blk, bs, &error_abort);
@@ -1312,7 +1300,8 @@
bdrv_ref(data->c);
data->child_c = bdrv_attach_child(data->parent_b, data->c, "PB-C",
- &child_file, &error_abort);
+ &child_of_bds, BDRV_CHILD_DATA,
+ &error_abort);
}
static void detach_by_parent_aio_cb(void *opaque, int ret)
@@ -1329,10 +1318,10 @@
{
aio_bh_schedule_oneshot(qemu_get_current_aio_context(),
detach_indirect_bh, &detach_by_parent_data);
- child_file.drained_begin(child);
+ child_of_bds.drained_begin(child);
}
-static BdrvChildRole detach_by_driver_cb_role;
+static BdrvChildClass detach_by_driver_cb_class;
/*
* Initial graph:
@@ -1349,7 +1338,7 @@
*
* by_parent_cb == false: Test that bdrv_drain_invoke() doesn't poll
*
- * PA's BdrvChildRole has a .drained_begin callback that schedules a BH
+ * PA's BdrvChildClass has a .drained_begin callback that schedules a BH
* that does the same graph change. If bdrv_drain_invoke() calls it, the
* state is messed up, but if it is only polled in the single
* BDRV_POLL_WHILE() at the end of the drain, this should work fine.
@@ -1364,8 +1353,8 @@
QEMUIOVector qiov = QEMU_IOVEC_INIT_BUF(qiov, NULL, 0);
if (!by_parent_cb) {
- detach_by_driver_cb_role = child_file;
- detach_by_driver_cb_role.drained_begin =
+ detach_by_driver_cb_class = child_of_bds;
+ detach_by_driver_cb_class.drained_begin =
detach_by_driver_cb_drained_begin;
}
@@ -1394,13 +1383,15 @@
/* Set child relationships */
bdrv_ref(b);
bdrv_ref(a);
- child_b = bdrv_attach_child(parent_b, b, "PB-B", &child_file, &error_abort);
- child_a = bdrv_attach_child(parent_b, a, "PB-A", &child_backing, &error_abort);
+ child_b = bdrv_attach_child(parent_b, b, "PB-B", &child_of_bds,
+ BDRV_CHILD_DATA, &error_abort);
+ child_a = bdrv_attach_child(parent_b, a, "PB-A", &child_of_bds,
+ BDRV_CHILD_COW, &error_abort);
bdrv_ref(a);
bdrv_attach_child(parent_a, a, "PA-A",
- by_parent_cb ? &child_file : &detach_by_driver_cb_role,
- &error_abort);
+ by_parent_cb ? &child_of_bds : &detach_by_driver_cb_class,
+ BDRV_CHILD_DATA, &error_abort);
g_assert_cmpint(parent_a->refcnt, ==, 1);
g_assert_cmpint(parent_b->refcnt, ==, 1);
@@ -1735,7 +1726,7 @@
/**
* Test a poll in the midst of bdrv_drop_intermediate().
*
- * bdrv_drop_intermediate() calls BdrvChildRole.update_filename(),
+ * bdrv_drop_intermediate() calls BdrvChildClass.update_filename(),
* which can yield or poll. This may lead to graph changes, unless
* the whole subtree in question is drained.
*
@@ -1772,7 +1763,7 @@
*
* The solution is for bdrv_drop_intermediate() to drain top's
* subtree. This prevents graph changes from happening just because
- * BdrvChildRole.update_filename() yields or polls. Thus, the block
+ * BdrvChildClass.update_filename() yields or polls. Thus, the block
* job is paused during that drained section and must finish before or
* after.
*
@@ -1780,7 +1771,7 @@
*/
static void test_drop_intermediate_poll(void)
{
- static BdrvChildRole chain_child_role;
+ static BdrvChildClass chain_child_class;
BlockDriverState *chain[3];
TestSimpleBlockJob *job;
BlockDriverState *job_node;
@@ -1788,8 +1779,8 @@
int i;
int ret;
- chain_child_role = child_backing;
- chain_child_role.update_filename = drop_intermediate_poll_update_filename;
+ chain_child_class = child_of_bds;
+ chain_child_class.update_filename = drop_intermediate_poll_update_filename;
for (i = 0; i < 3; i++) {
char name[32];
@@ -1810,8 +1801,8 @@
if (i) {
/* Takes the reference to chain[i - 1] */
chain[i]->backing = bdrv_attach_child(chain[i], chain[i - 1],
- "chain", &chain_child_role,
- &error_abort);
+ "chain", &chain_child_class,
+ BDRV_CHILD_COW, &error_abort);
}
}
@@ -1956,7 +1947,7 @@
.bdrv_co_drain_begin = bdrv_replace_test_co_drain_begin,
.bdrv_co_drain_end = bdrv_replace_test_co_drain_end,
- .bdrv_child_perm = bdrv_format_default_perms,
+ .bdrv_child_perm = bdrv_default_perms,
};
static void coroutine_fn test_replace_child_mid_drain_read_co(void *opaque)
@@ -2029,7 +2020,8 @@
bdrv_ref(old_child_bs);
parent_bs->backing = bdrv_attach_child(parent_bs, old_child_bs, "child",
- &child_backing, &error_abort);
+ &child_of_bds, BDRV_CHILD_COW,
+ &error_abort);
for (i = 0; i < old_drain_count; i++) {
bdrv_drained_begin(old_child_bs);
diff --git a/tests/test-bdrv-graph-mod.c b/tests/test-bdrv-graph-mod.c
index a007754..f93f316 100644
--- a/tests/test-bdrv-graph-mod.c
+++ b/tests/test-bdrv-graph-mod.c
@@ -26,11 +26,11 @@
static BlockDriver bdrv_pass_through = {
.format_name = "pass-through",
- .bdrv_child_perm = bdrv_filter_default_perms,
+ .bdrv_child_perm = bdrv_default_perms,
};
static void no_perm_default_perms(BlockDriverState *bs, BdrvChild *c,
- const BdrvChildRole *role,
+ BdrvChildRole role,
BlockReopenQueue *reopen_queue,
uint64_t perm, uint64_t shared,
uint64_t *nperm, uint64_t *nshared)
@@ -111,7 +111,8 @@
blk_insert_bs(root, bs, &error_abort);
- bdrv_attach_child(filter, bs, "child", &child_file, &error_abort);
+ bdrv_attach_child(filter, bs, "child", &child_of_bds,
+ BDRV_CHILD_FILTERED | BDRV_CHILD_PRIMARY, &error_abort);
bdrv_append(filter, bs, &local_err);
@@ -177,7 +178,8 @@
bdrv_set_backing_hd(target, bs, &error_abort);
g_assert(target->backing->bs == bs);
- bdrv_attach_child(filter, target, "target", &child_file, &error_abort);
+ bdrv_attach_child(filter, target, "target", &child_of_bds,
+ BDRV_CHILD_DATA, &error_abort);
bdrv_append(filter, bs, &error_abort);
g_assert(target->backing->bs == bs);
diff --git a/tests/test-block-iothread.c b/tests/test-block-iothread.c
index 71e9bce..a953794 100644
--- a/tests/test-block-iothread.c
+++ b/tests/test-block-iothread.c
@@ -482,8 +482,13 @@
BlockDriverState *bs_a, *bs_b, *bs_verify;
QDict *options;
- /* Create bs_a and its BlockBackend */
- blk = blk_new(qemu_get_aio_context(), BLK_PERM_ALL, BLK_PERM_ALL);
+ /*
+ * Create bs_a and its BlockBackend. We cannot take the RESIZE
+ * permission because blkverify will not share it on the test
+ * image.
+ */
+ blk = blk_new(qemu_get_aio_context(), BLK_PERM_ALL & ~BLK_PERM_RESIZE,
+ BLK_PERM_ALL);
bs_a = bdrv_new_open_driver(&bdrv_test, "bs_a", BDRV_O_RDWR, &error_abort);
blk_insert_bs(blk, bs_a, &error_abort);
@@ -566,7 +571,13 @@
qdict_put_str(options, "raw", "bs_c");
bs_verify = bdrv_open(NULL, NULL, options, BDRV_O_RDWR, &error_abort);
- blk = blk_new(qemu_get_aio_context(), BLK_PERM_ALL, BLK_PERM_ALL);
+ /*
+ * Do not take the RESIZE permission: This would require the same
+ * from bs_c and thus from bs_a; however, blkverify will not share
+ * it on bs_b, and thus it will not be available for bs_a.
+ */
+ blk = blk_new(qemu_get_aio_context(), BLK_PERM_ALL & ~BLK_PERM_RESIZE,
+ BLK_PERM_ALL);
blk_insert_bs(blk, bs_verify, &error_abort);
/* Switch the AioContext */
diff --git a/tests/test-qdev-global-props.c b/tests/test-qdev-global-props.c
index 270c690..42d3dd7 100644
--- a/tests/test-qdev-global-props.c
+++ b/tests/test-qdev-global-props.c
@@ -151,9 +151,9 @@
static void dynamic_instance_init(Object *obj)
{
object_property_add(obj, "prop1", "uint32", prop1_accessor, prop1_accessor,
- NULL, NULL, NULL);
+ NULL, NULL);
object_property_add(obj, "prop2", "uint32", prop2_accessor, prop2_accessor,
- NULL, NULL, NULL);
+ NULL, NULL);
}
static void dynamic_class_init(ObjectClass *oc, void *data)
diff --git a/tests/test-util-sockets.c b/tests/test-util-sockets.c
index 5fd947c..2ca1e99 100644
--- a/tests/test-util-sockets.c
+++ b/tests/test-util-sockets.c
@@ -227,6 +227,93 @@
g_free(addr.u.fd.str);
}
+#ifdef __linux__
+static gchar *abstract_sock_name;
+
+static gpointer unix_server_thread_func(gpointer user_data)
+{
+ SocketAddress addr;
+ Error *err = NULL;
+ int fd = -1;
+ int connfd = -1;
+ struct sockaddr_un un;
+ socklen_t len = sizeof(un);
+
+ addr.type = SOCKET_ADDRESS_TYPE_UNIX;
+ addr.u.q_unix.path = abstract_sock_name;
+ addr.u.q_unix.tight = user_data != NULL;
+ addr.u.q_unix.abstract = true;
+
+ fd = socket_listen(&addr, 1, &err);
+ g_assert_cmpint(fd, >=, 0);
+ g_assert(fd_is_socket(fd));
+
+ connfd = accept(fd, (struct sockaddr *)&un, &len);
+ g_assert_cmpint(connfd, !=, -1);
+
+ close(fd);
+
+ return NULL;
+}
+
+static gpointer unix_client_thread_func(gpointer user_data)
+{
+ SocketAddress addr;
+ Error *err = NULL;
+ int fd = -1;
+
+ addr.type = SOCKET_ADDRESS_TYPE_UNIX;
+ addr.u.q_unix.path = abstract_sock_name;
+ addr.u.q_unix.tight = user_data != NULL;
+ addr.u.q_unix.abstract = true;
+
+ fd = socket_connect(&addr, &err);
+
+ g_assert_cmpint(fd, >=, 0);
+
+ close(fd);
+
+ return NULL;
+}
+
+static void test_socket_unix_abstract_good(void)
+{
+ GRand *r = g_rand_new();
+
+ abstract_sock_name = g_strdup_printf("unix-%d-%d", getpid(),
+ g_rand_int_range(r, 100, 1000));
+
+ /* non tight socklen serv and cli */
+ GThread *serv = g_thread_new("abstract_unix_server",
+ unix_server_thread_func,
+ NULL);
+
+ sleep(1);
+
+ GThread *cli = g_thread_new("abstract_unix_client",
+ unix_client_thread_func,
+ NULL);
+
+ g_thread_join(cli);
+ g_thread_join(serv);
+
+ /* tight socklen serv and cli */
+ serv = g_thread_new("abstract_unix_server",
+ unix_server_thread_func,
+ (gpointer)1);
+
+ sleep(1);
+
+ cli = g_thread_new("abstract_unix_client",
+ unix_client_thread_func,
+ (gpointer)1);
+
+ g_thread_join(cli);
+ g_thread_join(serv);
+
+ g_free(abstract_sock_name);
+}
+#endif
int main(int argc, char **argv)
{
@@ -265,6 +352,11 @@
test_socket_fd_pass_num_nocli);
}
+#ifdef __linux__
+ g_test_add_func("/util/socket/unix-abstract/good",
+ test_socket_unix_abstract_good);
+#endif
+
end:
return g_test_run();
}
diff --git a/tests/vm/Makefile.include b/tests/vm/Makefile.include
index 1bf9693..a253aba 100644
--- a/tests/vm/Makefile.include
+++ b/tests/vm/Makefile.include
@@ -41,6 +41,7 @@
@echo " J=[0..9]* - Override the -jN parameter for make commands"
@echo " DEBUG=1 - Enable verbose output on host and interactive debugging"
@echo " V=1 - Enable verbose ouput on host and guest commands"
+ @echo " QEMU_LOCAL=1 - Use QEMU binary local to this build."
@echo " QEMU=/path/to/qemu - Change path to QEMU binary"
@echo " QEMU_IMG=/path/to/qemu-img - Change path to qemu-img tool"
@@ -56,6 +57,8 @@
$(call quiet-command, \
$(PYTHON) $< \
$(if $(V)$(DEBUG), --debug) \
+ $(if $(GENISOIMAGE),--genisoimage $(GENISOIMAGE)) \
+ $(if $(QEMU_LOCAL),--build-path $(BUILD_DIR)) \
--image "$@" \
--force \
--build-image $@, \
@@ -70,6 +73,7 @@
$(if $(DEBUG), --interactive) \
$(if $(J),--jobs $(J)) \
$(if $(V),--verbose) \
+ $(if $(QEMU_LOCAL),--build-path $(BUILD_DIR)) \
--image "$<" \
$(if $(BUILD_TARGET),--build-target $(BUILD_TARGET)) \
--snapshot \
@@ -90,6 +94,8 @@
$(call quiet-command, \
$(PYTHON) $(SRC_PATH)/tests/vm/$* \
$(if $(J),--jobs $(J)) \
+ $(if $(V)$(DEBUG), --debug) \
+ $(if $(QEMU_LOCAL),--build-path $(BUILD_DIR)) \
--image "$<" \
--interactive \
false, \
diff --git a/tests/vm/basevm.py b/tests/vm/basevm.py
index 756ccf7..a80b616 100644
--- a/tests/vm/basevm.py
+++ b/tests/vm/basevm.py
@@ -61,8 +61,11 @@
# 4 is arbitrary, but greater than 2,
# since we found we need to wait more than twice as long.
tcg_ssh_timeout_multiplier = 4
- def __init__(self, debug=False, vcpus=None):
+ def __init__(self, debug=False, vcpus=None, genisoimage=None,
+ build_path=None):
self._guest = None
+ self._genisoimage = genisoimage
+ self._build_path = build_path
self._tmpdir = os.path.realpath(tempfile.mkdtemp(prefix="vm-test-",
suffix=".tmp",
dir="."))
@@ -183,15 +186,15 @@
"-device", "virtio-blk,drive=drive0,bootindex=0"]
args += self._data_args + extra_args
logging.debug("QEMU args: %s", " ".join(args))
- qemu_bin = os.environ.get("QEMU", "qemu-system-" + self.arch)
- guest = QEMUMachine(binary=qemu_bin, args=args)
+ qemu_path = get_qemu_path(self.arch, self._build_path)
+ guest = QEMUMachine(binary=qemu_path, args=args)
guest.set_machine('pc')
guest.set_console()
try:
guest.launch()
except:
logging.error("Failed to launch QEMU, command line:")
- logging.error(" ".join([qemu_bin] + args))
+ logging.error(" ".join([qemu_path] + args))
logging.error("Log:")
logging.error(guest.get_log())
logging.error("QEMU version >= 2.10 is required")
@@ -317,24 +320,24 @@
def print_step(self, text):
sys.stderr.write("### %s ...\n" % text)
- def wait_ssh(self, wait_root=False, seconds=300):
+ def wait_ssh(self, wait_root=False, seconds=300, cmd="exit 0"):
# Allow more time for VM to boot under TCG.
if not kvm_available(self.arch):
seconds *= self.tcg_ssh_timeout_multiplier
starttime = datetime.datetime.now()
endtime = starttime + datetime.timedelta(seconds=seconds)
- guest_up = False
+ cmd_success = False
while datetime.datetime.now() < endtime:
- if wait_root and self.ssh_root("exit 0") == 0:
- guest_up = True
+ if wait_root and self.ssh_root(cmd) == 0:
+ cmd_success = True
break
- elif self.ssh("exit 0") == 0:
- guest_up = True
+ elif self.ssh(cmd) == 0:
+ cmd_success = True
break
seconds = (endtime - datetime.datetime.now()).total_seconds()
logging.debug("%ds before timeout", seconds)
time.sleep(1)
- if not guest_up:
+ if not cmd_success:
raise Exception("Timeout while waiting for guest ssh")
def shutdown(self):
@@ -381,15 +384,28 @@
udata.writelines(["apt:\n",
" proxy: %s" % proxy])
udata.close()
- subprocess.check_call(["genisoimage", "-output", "cloud-init.iso",
+ subprocess.check_call([self._genisoimage, "-output", "cloud-init.iso",
"-volid", "cidata", "-joliet", "-rock",
"user-data", "meta-data"],
- cwd=cidir,
- stdin=self._devnull, stdout=self._stdout,
- stderr=self._stdout)
+ cwd=cidir,
+ stdin=self._devnull, stdout=self._stdout,
+ stderr=self._stdout)
return os.path.join(cidir, "cloud-init.iso")
+def get_qemu_path(arch, build_path=None):
+ """Fetch the path to the qemu binary."""
+ # If QEMU environment variable set, it takes precedence
+ if "QEMU" in os.environ:
+ qemu_path = os.environ["QEMU"]
+ elif build_path:
+ qemu_path = os.path.join(build_path, arch + "-softmmu")
+ qemu_path = os.path.join(qemu_path, "qemu-system-" + arch)
+ else:
+ # Default is to use system path for qemu.
+ qemu_path = "qemu-system-" + arch
+ return qemu_path
+
def parse_args(vmcls):
def get_default_jobs():
@@ -420,10 +436,15 @@
help="build QEMU from source in guest")
parser.add_option("--build-target",
help="QEMU build target", default="check")
+ parser.add_option("--build-path", default=None,
+ help="Path of build directory, "\
+ "for using build tree QEMU binary. ")
parser.add_option("--interactive", "-I", action="store_true",
help="Interactively run command")
parser.add_option("--snapshot", "-s", action="store_true",
help="run tests with a snapshot")
+ parser.add_option("--genisoimage", default="genisoimage",
+ help="iso imaging tool")
parser.disable_interspersed_args()
return parser.parse_args()
@@ -435,7 +456,8 @@
return 1
logging.basicConfig(level=(logging.DEBUG if args.debug
else logging.WARN))
- vm = vmcls(debug=args.debug, vcpus=args.jobs)
+ vm = vmcls(debug=args.debug, vcpus=args.jobs,
+ genisoimage=args.genisoimage, build_path=args.build_path)
if args.build_image:
if os.path.exists(args.image) and not args.force:
sys.stderr.writelines(["Image file exists: %s\n" % args.image,
diff --git a/tools/virtiofsd/passthrough_ll.c b/tools/virtiofsd/passthrough_ll.c
index 3ba1d90..2ce7c96 100644
--- a/tools/virtiofsd/passthrough_ll.c
+++ b/tools/virtiofsd/passthrough_ll.c
@@ -140,7 +140,6 @@
struct lo_data {
pthread_mutex_t mutex;
int debug;
- int norace;
int writeback;
int flock;
int posix_lock;
@@ -176,7 +175,6 @@
{ "cache=none", offsetof(struct lo_data, cache), CACHE_NONE },
{ "cache=auto", offsetof(struct lo_data, cache), CACHE_AUTO },
{ "cache=always", offsetof(struct lo_data, cache), CACHE_ALWAYS },
- { "norace", offsetof(struct lo_data, norace), 1 },
{ "readdirplus", offsetof(struct lo_data, readdirplus_set), 1 },
{ "no_readdirplus", offsetof(struct lo_data, readdirplus_clear), 1 },
FUSE_OPT_END
@@ -592,136 +590,6 @@
fuse_reply_attr(req, &buf, lo->timeout);
}
-/*
- * Increments parent->nlookup and caller must release refcount using
- * lo_inode_put(&parent).
- */
-static int lo_parent_and_name(struct lo_data *lo, struct lo_inode *inode,
- char path[PATH_MAX], struct lo_inode **parent)
-{
- char procname[64];
- char *last;
- struct stat stat;
- struct lo_inode *p;
- int retries = 2;
- int res;
-
-retry:
- sprintf(procname, "%i", inode->fd);
-
- res = readlinkat(lo->proc_self_fd, procname, path, PATH_MAX);
- if (res < 0) {
- fuse_log(FUSE_LOG_WARNING, "%s: readlink failed: %m\n", __func__);
- goto fail_noretry;
- }
-
- if (res >= PATH_MAX) {
- fuse_log(FUSE_LOG_WARNING, "%s: readlink overflowed\n", __func__);
- goto fail_noretry;
- }
- path[res] = '\0';
-
- last = strrchr(path, '/');
- if (last == NULL) {
- /* Shouldn't happen */
- fuse_log(
- FUSE_LOG_WARNING,
- "%s: INTERNAL ERROR: bad path read from proc\n", __func__);
- goto fail_noretry;
- }
- if (last == path) {
- p = &lo->root;
- pthread_mutex_lock(&lo->mutex);
- p->nlookup++;
- g_atomic_int_inc(&p->refcount);
- pthread_mutex_unlock(&lo->mutex);
- } else {
- *last = '\0';
- res = fstatat(AT_FDCWD, last == path ? "/" : path, &stat, 0);
- if (res == -1) {
- if (!retries) {
- fuse_log(FUSE_LOG_WARNING,
- "%s: failed to stat parent: %m\n", __func__);
- }
- goto fail;
- }
- p = lo_find(lo, &stat);
- if (p == NULL) {
- if (!retries) {
- fuse_log(FUSE_LOG_WARNING,
- "%s: failed to find parent\n", __func__);
- }
- goto fail;
- }
- }
- last++;
- res = fstatat(p->fd, last, &stat, AT_SYMLINK_NOFOLLOW);
- if (res == -1) {
- if (!retries) {
- fuse_log(FUSE_LOG_WARNING,
- "%s: failed to stat last\n", __func__);
- }
- goto fail_unref;
- }
- if (stat.st_dev != inode->key.dev || stat.st_ino != inode->key.ino) {
- if (!retries) {
- fuse_log(FUSE_LOG_WARNING,
- "%s: failed to match last\n", __func__);
- }
- goto fail_unref;
- }
- *parent = p;
- memmove(path, last, strlen(last) + 1);
-
- return 0;
-
-fail_unref:
- unref_inode_lolocked(lo, p, 1);
- lo_inode_put(lo, &p);
-fail:
- if (retries) {
- retries--;
- goto retry;
- }
-fail_noretry:
- errno = EIO;
- return -1;
-}
-
-static int utimensat_empty(struct lo_data *lo, struct lo_inode *inode,
- const struct timespec *tv)
-{
- int res;
- struct lo_inode *parent;
- char path[PATH_MAX];
-
- if (S_ISLNK(inode->filetype)) {
- res = utimensat(inode->fd, "", tv, AT_EMPTY_PATH);
- if (res == -1 && errno == EINVAL) {
- /* Sorry, no race free way to set times on symlink. */
- if (lo->norace) {
- errno = EPERM;
- } else {
- goto fallback;
- }
- }
- return res;
- }
- sprintf(path, "%i", inode->fd);
-
- return utimensat(lo->proc_self_fd, path, tv, 0);
-
-fallback:
- res = lo_parent_and_name(lo, inode, path, &parent);
- if (res != -1) {
- res = utimensat(parent->fd, path, tv, AT_SYMLINK_NOFOLLOW);
- unref_inode_lolocked(lo, parent, 1);
- lo_inode_put(lo, &parent);
- }
-
- return res;
-}
-
static int lo_fi_fd(fuse_req_t req, struct fuse_file_info *fi)
{
struct lo_data *lo = lo_data(req);
@@ -828,7 +696,8 @@
if (fi) {
res = futimens(fd, tv);
} else {
- res = utimensat_empty(lo, inode, tv);
+ sprintf(procname, "%i", inode->fd);
+ res = utimensat(lo->proc_self_fd, procname, tv, 0);
}
if (res == -1) {
goto out_err;
@@ -1129,41 +998,6 @@
lo_mknod_symlink(req, parent, name, S_IFLNK, 0, link);
}
-static int linkat_empty_nofollow(struct lo_data *lo, struct lo_inode *inode,
- int dfd, const char *name)
-{
- int res;
- struct lo_inode *parent;
- char path[PATH_MAX];
-
- if (S_ISLNK(inode->filetype)) {
- res = linkat(inode->fd, "", dfd, name, AT_EMPTY_PATH);
- if (res == -1 && (errno == ENOENT || errno == EINVAL)) {
- /* Sorry, no race free way to hard-link a symlink. */
- if (lo->norace) {
- errno = EPERM;
- } else {
- goto fallback;
- }
- }
- return res;
- }
-
- sprintf(path, "%i", inode->fd);
-
- return linkat(lo->proc_self_fd, path, dfd, name, AT_SYMLINK_FOLLOW);
-
-fallback:
- res = lo_parent_and_name(lo, inode, path, &parent);
- if (res != -1) {
- res = linkat(parent->fd, path, dfd, name, 0);
- unref_inode_lolocked(lo, parent, 1);
- lo_inode_put(lo, &parent);
- }
-
- return res;
-}
-
static void lo_link(fuse_req_t req, fuse_ino_t ino, fuse_ino_t parent,
const char *name)
{
@@ -1172,6 +1006,7 @@
struct lo_inode *parent_inode;
struct lo_inode *inode;
struct fuse_entry_param e;
+ char procname[64];
int saverr;
if (!is_safe_path_component(name)) {
@@ -1190,7 +1025,9 @@
e.attr_timeout = lo->timeout;
e.entry_timeout = lo->timeout;
- res = linkat_empty_nofollow(lo, inode, parent_inode->fd, name);
+ sprintf(procname, "%i", inode->fd);
+ res = linkat(lo->proc_self_fd, procname, parent_inode->fd, name,
+ AT_SYMLINK_FOLLOW);
if (res == -1) {
goto out_err;
}
diff --git a/ui/Makefile.objs b/ui/Makefile.objs
index e6da6ff..504b196 100644
--- a/ui/Makefile.objs
+++ b/ui/Makefile.objs
@@ -15,6 +15,9 @@
common-obj-$(CONFIG_COCOA) += cocoa.o
common-obj-$(CONFIG_VNC) += $(vnc-obj-y)
common-obj-$(call lnot,$(CONFIG_VNC)) += vnc-stubs.o
+ifneq (,$(findstring m,$(CONFIG_SDL)$(CONFIG_GTK)))
+common-obj-$(CONFIG_WIN32) += win32-kbd-hook.o
+endif
# ui-sdl module
common-obj-$(CONFIG_SDL) += sdl.mo
diff --git a/ui/console.c b/ui/console.c
index 184e173..865fa32 100644
--- a/ui/console.c
+++ b/ui/console.c
@@ -1297,10 +1297,9 @@
object_property_add_link(obj, "device", TYPE_DEVICE,
(Object **)&s->device,
object_property_allow_set_link,
- OBJ_PROP_LINK_STRONG,
- &error_abort);
+ OBJ_PROP_LINK_STRONG);
object_property_add_uint32_ptr(obj, "head", &s->head,
- OBJ_PROP_FLAG_READ, &error_abort);
+ OBJ_PROP_FLAG_READ);
if (!active_console || ((active_console->console_type != GRAPHIC_CONSOLE) &&
(console_type == GRAPHIC_CONSOLE))) {
@@ -1868,7 +1867,7 @@
* doesn't change any more */
name = g_strdup_printf("console[%d]", con->index);
object_property_add_child(container_get(object_get_root(), "/backend"),
- name, OBJECT(con), &error_abort);
+ name, OBJECT(con));
g_free(name);
}
diff --git a/ui/gtk.c b/ui/gtk.c
index 83f2f5d..d4b49bd 100644
--- a/ui/gtk.c
+++ b/ui/gtk.c
@@ -38,6 +38,10 @@
#include "ui/console.h"
#include "ui/gtk.h"
+#ifdef G_OS_WIN32
+#include <gdk/gdkwin32.h>
+#endif
+#include "ui/win32-kbd-hook.h"
#include <glib/gi18n.h>
#include <locale.h>
@@ -108,15 +112,6 @@
# define VTE_CHECK_VERSION(a, b, c) 0
#endif
-/* Some older mingw versions lack this constant or have
- * it conditionally defined */
-#ifdef _WIN32
-# ifndef MAPVK_VK_TO_VSC
-# define MAPVK_VK_TO_VSC 0
-# endif
-#endif
-
-
#define HOTKEY_MODIFIERS (GDK_CONTROL_MASK | GDK_MOD1_MASK)
static const guint16 *keycode_map;
@@ -173,8 +168,6 @@
bool external_pause_update;
- bool ignore_keys;
-
DisplayOptions *opts;
};
@@ -428,6 +421,16 @@
g_object_unref(G_OBJECT(widget));
}
+static void *gd_win32_get_hwnd(VirtualConsole *vc)
+{
+#ifdef G_OS_WIN32
+ return gdk_win32_window_get_impl_hwnd(
+ gtk_widget_get_window(vc->window ? vc->window : vc->s->window));
+#else
+ return NULL;
+#endif
+}
+
/** DisplayState Callbacks **/
static void gd_update(DisplayChangeListener *dcl,
@@ -487,12 +490,7 @@
static GdkDevice *gd_get_pointer(GdkDisplay *dpy)
{
-#if GTK_CHECK_VERSION(3, 20, 0)
return gdk_seat_get_pointer(gdk_display_get_default_seat(dpy));
-#else
- return gdk_device_manager_get_client_pointer(
- gdk_display_get_device_manager(dpy));
-#endif
}
static void gd_mouse_set(DisplayChangeListener *dcl,
@@ -874,27 +872,18 @@
if (!qemu_input_is_absolute() && s->ptr_owner == vc) {
GdkScreen *screen = gtk_widget_get_screen(vc->gfx.drawing_area);
+ GdkDisplay *dpy = gtk_widget_get_display(widget);
+ GdkWindow *win = gtk_widget_get_window(widget);
+ GdkMonitor *monitor = gdk_display_get_monitor_at_window(dpy, win);
+ GdkRectangle geometry;
int screen_width, screen_height;
int x = (int)motion->x_root;
int y = (int)motion->y_root;
-#if GTK_CHECK_VERSION(3, 22, 0)
- {
- GdkDisplay *dpy = gtk_widget_get_display(widget);
- GdkWindow *win = gtk_widget_get_window(widget);
- GdkMonitor *monitor = gdk_display_get_monitor_at_window(dpy, win);
- GdkRectangle geometry;
- gdk_monitor_get_geometry(monitor, &geometry);
- screen_width = geometry.width;
- screen_height = geometry.height;
- }
-#else
- {
- screen_width = gdk_screen_get_width(screen);
- screen_height = gdk_screen_get_height(screen);
- }
-#endif
+ gdk_monitor_get_geometry(monitor, &geometry);
+ screen_width = geometry.width;
+ screen_height = geometry.height;
/* In relative mode check to see if client pointer hit
* one of the screen edges, and if so move it back by
@@ -1023,8 +1012,8 @@
#ifdef GDK_WINDOWING_WIN32
if (GDK_IS_WIN32_DISPLAY(dpy)) {
trace_gd_keymap_windowing("win32");
- *maplen = qemu_input_map_win32_to_qcode_len;
- return qemu_input_map_win32_to_qcode;
+ *maplen = qemu_input_map_atset1_to_qcode_len;
+ return qemu_input_map_atset1_to_qcode;
}
#endif
@@ -1070,6 +1059,25 @@
return keycode_map[scancode];
}
+static int gd_get_keycode(GdkEventKey *key)
+{
+#ifdef G_OS_WIN32
+ int scancode = gdk_event_get_scancode((GdkEvent *)key);
+
+ /* translate Windows native scancodes to atset1 keycodes */
+ switch (scancode & (KF_EXTENDED | 0xff)) {
+ case 0x145: /* NUMLOCK */
+ return scancode & 0xff;
+ }
+
+ return scancode & KF_EXTENDED ?
+ 0xe000 | (scancode & 0xff) : scancode & 0xff;
+
+#else
+ return key->hardware_keycode;
+#endif
+}
+
static gboolean gd_text_key_down(GtkWidget *widget,
GdkEventKey *key, void *opaque)
{
@@ -1081,7 +1089,7 @@
} else if (key->length) {
kbd_put_string_console(con, key->string, key->length);
} else {
- int qcode = gd_map_keycode(key->hardware_keycode);
+ int qcode = gd_map_keycode(gd_get_keycode(key));
kbd_put_qcode_console(con, qcode, false);
}
return TRUE;
@@ -1090,18 +1098,19 @@
static gboolean gd_key_event(GtkWidget *widget, GdkEventKey *key, void *opaque)
{
VirtualConsole *vc = opaque;
- GtkDisplayState *s = vc->s;
- int qcode;
+ int keycode, qcode;
- if (s->ignore_keys) {
- s->ignore_keys = (key->type == GDK_KEY_PRESS);
- return TRUE;
- }
-
-#ifdef WIN32
+#ifdef G_OS_WIN32
/* on windows, we ought to ignore the reserved key event? */
if (key->hardware_keycode == 0xff)
return false;
+
+ if (!vc->s->kbd_owner) {
+ if (key->hardware_keycode == VK_LWIN ||
+ key->hardware_keycode == VK_RWIN) {
+ return FALSE;
+ }
+ }
#endif
if (key->keyval == GDK_KEY_Pause
@@ -1117,9 +1126,10 @@
return TRUE;
}
- qcode = gd_map_keycode(key->hardware_keycode);
+ keycode = gd_get_keycode(key);
+ qcode = gd_map_keycode(keycode);
- trace_gd_key_event(vc->label, key->hardware_keycode, qcode,
+ trace_gd_key_event(vc->label, keycode, qcode,
(key->type == GDK_KEY_PRESS) ? "down" : "up");
qkbd_state_key_event(vc->gfx.kbd, qcode,
@@ -1128,6 +1138,25 @@
return TRUE;
}
+static gboolean gd_grab_broken_event(GtkWidget *widget,
+ GdkEventGrabBroken *event, void *opaque)
+{
+#ifdef CONFIG_WIN32
+ /*
+ * On Windows the Ctrl-Alt-Del key combination can't be grabbed. This
+ * key combination leaves all three keys in a stuck condition. We use
+ * the grab-broken-event to release all keys.
+ */
+ if (event->keyboard) {
+ VirtualConsole *vc = opaque;
+ GtkDisplayState *s = vc->s;
+
+ gtk_release_modifiers(s);
+ }
+#endif
+ return TRUE;
+}
+
static gboolean gd_event(GtkWidget *widget, GdkEvent *event, void *opaque)
{
if (event->type == GDK_MOTION_NOTIFY) {
@@ -1180,7 +1209,6 @@
gtk_notebook_set_current_page(nb, page);
gtk_widget_grab_focus(vc->focus);
}
- s->ignore_keys = false;
}
static void gd_accel_switch_vc(void *opaque)
@@ -1390,7 +1418,6 @@
gd_update_full_redraw(vc);
}
-#if GTK_CHECK_VERSION(3, 20, 0)
static void gd_grab_update(VirtualConsole *vc, bool kbd, bool ptr)
{
GdkDisplay *display = gtk_widget_get_display(vc->gfx.drawing_area);
@@ -1414,32 +1441,6 @@
gdk_seat_ungrab(seat);
}
}
-#else
-static void gd_grab_devices(VirtualConsole *vc, bool grab,
- GdkInputSource source, GdkEventMask mask,
- GdkCursor *cursor)
-{
- GdkDisplay *display = gtk_widget_get_display(vc->gfx.drawing_area);
- GdkDeviceManager *mgr = gdk_display_get_device_manager(display);
- GList *devs = gdk_device_manager_list_devices(mgr, GDK_DEVICE_TYPE_MASTER);
- GList *tmp = devs;
-
- for (tmp = devs; tmp; tmp = tmp->next) {
- GdkDevice *dev = tmp->data;
- if (gdk_device_get_source(dev) != source) {
- continue;
- }
- if (grab) {
- GdkWindow *win = gtk_widget_get_window(vc->gfx.drawing_area);
- gdk_device_grab(dev, win, GDK_OWNERSHIP_NONE, FALSE,
- mask, cursor, GDK_CURRENT_TIME);
- } else {
- gdk_device_ungrab(dev, GDK_CURRENT_TIME);
- }
- }
- g_list_free(devs);
-}
-#endif
static void gd_grab_keyboard(VirtualConsole *vc, const char *reason)
{
@@ -1451,13 +1452,8 @@
}
}
-#if GTK_CHECK_VERSION(3, 20, 0)
+ win32_kbd_set_grab(true);
gd_grab_update(vc, true, vc->s->ptr_owner == vc);
-#else
- gd_grab_devices(vc, true, GDK_SOURCE_KEYBOARD,
- GDK_KEY_PRESS_MASK | GDK_KEY_RELEASE_MASK,
- NULL);
-#endif
vc->s->kbd_owner = vc;
gd_update_caption(vc->s);
trace_gd_grab(vc->label, "kbd", reason);
@@ -1472,11 +1468,8 @@
}
s->kbd_owner = NULL;
-#if GTK_CHECK_VERSION(3, 20, 0)
+ win32_kbd_set_grab(false);
gd_grab_update(vc, false, vc->s->ptr_owner == vc);
-#else
- gd_grab_devices(vc, false, GDK_SOURCE_KEYBOARD, 0, NULL);
-#endif
gd_update_caption(s);
trace_gd_ungrab(vc->label, "kbd");
}
@@ -1493,21 +1486,9 @@
}
}
-#if GTK_CHECK_VERSION(3, 20, 0)
gd_grab_update(vc, vc->s->kbd_owner == vc, true);
gdk_device_get_position(gd_get_pointer(display),
NULL, &vc->s->grab_x_root, &vc->s->grab_y_root);
-#else
- gd_grab_devices(vc, true, GDK_SOURCE_MOUSE,
- GDK_POINTER_MOTION_MASK |
- GDK_BUTTON_PRESS_MASK |
- GDK_BUTTON_RELEASE_MASK |
- GDK_BUTTON_MOTION_MASK |
- GDK_SCROLL_MASK,
- vc->s->null_cursor);
- gdk_device_get_position(gd_get_pointer(display),
- NULL, &vc->s->grab_x_root, &vc->s->grab_y_root);
-#endif
vc->s->ptr_owner = vc;
gd_update_caption(vc->s);
trace_gd_grab(vc->label, "ptr", reason);
@@ -1524,17 +1505,10 @@
s->ptr_owner = NULL;
display = gtk_widget_get_display(vc->gfx.drawing_area);
-#if GTK_CHECK_VERSION(3, 20, 0)
gd_grab_update(vc, vc->s->kbd_owner == vc, false);
gdk_device_warp(gd_get_pointer(display),
gtk_widget_get_screen(vc->gfx.drawing_area),
vc->s->grab_x_root, vc->s->grab_y_root);
-#else
- gd_grab_devices(vc, false, GDK_SOURCE_MOUSE, 0, NULL);
- gdk_device_warp(gd_get_pointer(display),
- gtk_widget_get_screen(vc->gfx.drawing_area),
- vc->s->grab_x_root, vc->s->grab_y_root);
-#endif
gd_update_caption(s);
trace_gd_ungrab(vc->label, "ptr");
}
@@ -1614,12 +1588,22 @@
return TRUE;
}
+static gboolean gd_focus_in_event(GtkWidget *widget,
+ GdkEventFocus *event, gpointer opaque)
+{
+ VirtualConsole *vc = opaque;
+
+ win32_kbd_set_window(gd_win32_get_hwnd(vc));
+ return TRUE;
+}
+
static gboolean gd_focus_out_event(GtkWidget *widget,
- GdkEventCrossing *crossing, gpointer opaque)
+ GdkEventFocus *event, gpointer opaque)
{
VirtualConsole *vc = opaque;
GtkDisplayState *s = vc->s;
+ win32_kbd_set_window(NULL);
gtk_release_modifiers(s);
return TRUE;
}
@@ -1878,10 +1862,14 @@
G_CALLBACK(gd_enter_event), vc);
g_signal_connect(vc->gfx.drawing_area, "leave-notify-event",
G_CALLBACK(gd_leave_event), vc);
+ g_signal_connect(vc->gfx.drawing_area, "focus-in-event",
+ G_CALLBACK(gd_focus_in_event), vc);
g_signal_connect(vc->gfx.drawing_area, "focus-out-event",
G_CALLBACK(gd_focus_out_event), vc);
g_signal_connect(vc->gfx.drawing_area, "configure-event",
G_CALLBACK(gd_configure), vc);
+ g_signal_connect(vc->gfx.drawing_area, "grab-broken-event",
+ G_CALLBACK(gd_grab_broken_event), vc);
} else {
g_signal_connect(vc->gfx.drawing_area, "key-press-event",
G_CALLBACK(gd_text_key_down), vc);
diff --git a/ui/input-barrier.c b/ui/input-barrier.c
index 527c75e..1cdf0c5 100644
--- a/ui/input-barrier.c
+++ b/ui/input-barrier.c
@@ -700,25 +700,25 @@
object_property_add_str(obj, "name",
input_barrier_get_name,
- input_barrier_set_name, NULL);
+ input_barrier_set_name);
object_property_add_str(obj, "server",
input_barrier_get_server,
- input_barrier_set_server, NULL);
+ input_barrier_set_server);
object_property_add_str(obj, "port",
input_barrier_get_port,
- input_barrier_set_port, NULL);
+ input_barrier_set_port);
object_property_add_str(obj, "x-origin",
input_barrier_get_x_origin,
- input_barrier_set_x_origin, NULL);
+ input_barrier_set_x_origin);
object_property_add_str(obj, "y-origin",
input_barrier_get_y_origin,
- input_barrier_set_y_origin, NULL);
+ input_barrier_set_y_origin);
object_property_add_str(obj, "width",
input_barrier_get_width,
- input_barrier_set_width, NULL);
+ input_barrier_set_width);
object_property_add_str(obj, "height",
input_barrier_get_height,
- input_barrier_set_height, NULL);
+ input_barrier_set_height);
}
static void input_barrier_class_init(ObjectClass *oc, void *data)
diff --git a/ui/input-linux.c b/ui/input-linux.c
index ef37b14..4925ce1 100644
--- a/ui/input-linux.c
+++ b/ui/input-linux.c
@@ -499,17 +499,17 @@
{
object_property_add_str(obj, "evdev",
input_linux_get_evdev,
- input_linux_set_evdev, NULL);
+ input_linux_set_evdev);
object_property_add_bool(obj, "grab_all",
input_linux_get_grab_all,
- input_linux_set_grab_all, NULL);
+ input_linux_set_grab_all);
object_property_add_bool(obj, "repeat",
input_linux_get_repeat,
- input_linux_set_repeat, NULL);
+ input_linux_set_repeat);
object_property_add_enum(obj, "grab-toggle", "GrabToggleKeys",
&GrabToggleKeys_lookup,
input_linux_get_grab_toggle,
- input_linux_set_grab_toggle, NULL);
+ input_linux_set_grab_toggle);
}
static void input_linux_class_init(ObjectClass *oc, void *data)
diff --git a/ui/sdl2-input.c b/ui/sdl2-input.c
index 1f9fe83..f068382 100644
--- a/ui/sdl2-input.c
+++ b/ui/sdl2-input.c
@@ -27,6 +27,7 @@
#include "ui/console.h"
#include "ui/input.h"
#include "ui/sdl2.h"
+#include "trace.h"
void sdl2_process_key(struct sdl2_console *scon,
SDL_KeyboardEvent *ev)
@@ -38,6 +39,8 @@
return;
}
qcode = qemu_input_map_usb_to_qcode[ev->keysym.scancode];
+ trace_sdl2_process_key(ev->keysym.scancode, qcode,
+ ev->type == SDL_KEYDOWN ? "down" : "up");
qkbd_state_key_event(scon->kbd, qcode, ev->type == SDL_KEYDOWN);
if (!qemu_console_is_graphic(con)) {
diff --git a/ui/sdl2.c b/ui/sdl2.c
index 3c9424e..b23a8f0 100644
--- a/ui/sdl2.c
+++ b/ui/sdl2.c
@@ -30,6 +30,7 @@
#include "ui/sdl2.h"
#include "sysemu/runstate.h"
#include "sysemu/sysemu.h"
+#include "ui/win32-kbd-hook.h"
static int sdl2_num_outputs;
static struct sdl2_console *sdl2_console;
@@ -220,6 +221,7 @@
}
SDL_SetWindowGrab(scon->real_window, SDL_TRUE);
gui_grab = 1;
+ win32_kbd_set_grab(true);
sdl_update_caption(scon);
}
@@ -227,6 +229,7 @@
{
SDL_SetWindowGrab(scon->real_window, SDL_FALSE);
gui_grab = 0;
+ win32_kbd_set_grab(false);
sdl_show_cursor(scon);
sdl_update_caption(scon);
}
@@ -325,6 +328,19 @@
}
}
+static void *sdl2_win32_get_hwnd(struct sdl2_console *scon)
+{
+#ifdef CONFIG_WIN32
+ SDL_SysWMinfo info;
+
+ SDL_VERSION(&info.version);
+ if (SDL_GetWindowWMInfo(scon->real_window, &info)) {
+ return info.info.win.window;
+ }
+#endif
+ return NULL;
+}
+
static void handle_keydown(SDL_Event *ev)
{
int win;
@@ -332,6 +348,10 @@
int gui_key_modifier_pressed = get_mod_state();
int gui_keysym = 0;
+ if (!scon) {
+ return;
+ }
+
if (!scon->ignore_hotkeys && gui_key_modifier_pressed && !ev->key.repeat) {
switch (ev->key.keysym.scancode) {
case SDL_SCANCODE_2:
@@ -412,6 +432,10 @@
{
struct sdl2_console *scon = get_scon_from_window(ev->key.windowID);
+ if (!scon) {
+ return;
+ }
+
scon->ignore_hotkeys = false;
sdl2_process_key(scon, &ev->key);
}
@@ -421,6 +445,10 @@
struct sdl2_console *scon = get_scon_from_window(ev->text.windowID);
QemuConsole *con = scon ? scon->dcl.con : NULL;
+ if (!con) {
+ return;
+ }
+
if (qemu_console_is_graphic(con)) {
return;
}
@@ -532,6 +560,11 @@
sdl2_redraw(scon);
break;
case SDL_WINDOWEVENT_FOCUS_GAINED:
+ win32_kbd_set_grab(gui_grab);
+ if (qemu_console_is_graphic(scon->dcl.con)) {
+ win32_kbd_set_window(sdl2_win32_get_hwnd(scon));
+ }
+ /* fall through */
case SDL_WINDOWEVENT_ENTER:
if (!gui_grab && (qemu_input_is_absolute() || absolute_enabled)) {
absolute_mouse_grab(scon);
@@ -546,6 +579,9 @@
scon->ignore_hotkeys = get_mod_state();
break;
case SDL_WINDOWEVENT_FOCUS_LOST:
+ if (qemu_console_is_graphic(scon->dcl.con)) {
+ win32_kbd_set_window(NULL);
+ }
if (gui_grab && !gui_fullscreen) {
sdl_grab_end(scon);
}
@@ -845,17 +881,16 @@
SDL_SetWindowIcon(sdl2_console[0].real_window, icon);
}
- gui_grab = 0;
- if (gui_fullscreen) {
- sdl_grab_start(0);
- }
-
mouse_mode_notifier.notify = sdl_mouse_mode_change;
qemu_add_mouse_mode_change_notifier(&mouse_mode_notifier);
sdl_cursor_hidden = SDL_CreateCursor(&data, &data, 8, 1, 0, 0);
sdl_cursor_normal = SDL_GetCursor();
+ if (gui_fullscreen) {
+ sdl_grab_start(&sdl2_console[0]);
+ }
+
atexit(sdl_cleanup);
}
diff --git a/ui/trace-events b/ui/trace-events
index 0dcda39..5367fd3 100644
--- a/ui/trace-events
+++ b/ui/trace-events
@@ -75,6 +75,9 @@
input_event_sync(void) ""
input_mouse_mode(int absolute) "absolute %d"
+# sdl2-input.c
+sdl2_process_key(int sdl_scancode, int qcode, const char *action) "translated SDL scancode %d to QKeyCode %d (%s)"
+
# spice-display.c
qemu_spice_add_memslot(int qid, uint32_t slot_id, unsigned long virt_start, unsigned long virt_end, int async) "%d %u: host virt 0x%lx - 0x%lx async=%d"
qemu_spice_del_memslot(int qid, uint32_t gid, uint32_t slot_id) "%d gid=%u sid=%u"
diff --git a/ui/vnc.c b/ui/vnc.c
index 1d7138a..12a1271 100644
--- a/ui/vnc.c
+++ b/ui/vnc.c
@@ -1177,7 +1177,7 @@
{
}
-static void audio_capture(void *opaque, void *buf, int size)
+static void audio_capture(void *opaque, const void *buf, int size)
{
VncState *vs = opaque;
diff --git a/ui/win32-kbd-hook.c b/ui/win32-kbd-hook.c
new file mode 100644
index 0000000..1ac237d
--- /dev/null
+++ b/ui/win32-kbd-hook.c
@@ -0,0 +1,102 @@
+/*
+ * This work is licensed under the terms of the GNU GPL, version 2 or
+ * (at your option) any later version. See the COPYING file in the
+ * top-level directory.
+ *
+ * The win32 keyboard hooking code was imported from project spice-gtk.
+ */
+
+#include "qemu/osdep.h"
+#include "sysemu/sysemu.h"
+#include "ui/win32-kbd-hook.h"
+
+static Notifier win32_unhook_notifier;
+static HHOOK win32_keyboard_hook;
+static HWND win32_window;
+static DWORD win32_grab;
+
+static LRESULT CALLBACK keyboard_hook_cb(int code, WPARAM wparam, LPARAM lparam)
+{
+ if (win32_window && code == HC_ACTION && win32_window == GetFocus()) {
+ KBDLLHOOKSTRUCT *hooked = (KBDLLHOOKSTRUCT *)lparam;
+
+ if (wparam != WM_KEYUP) {
+ DWORD dwmsg = (hooked->flags << 24) |
+ ((hooked->scanCode & 0xff) << 16) | 1;
+
+ switch (hooked->vkCode) {
+ case VK_CAPITAL:
+ /* fall through */
+ case VK_SCROLL:
+ /* fall through */
+ case VK_NUMLOCK:
+ /* fall through */
+ case VK_LSHIFT:
+ /* fall through */
+ case VK_RSHIFT:
+ /* fall through */
+ case VK_RCONTROL:
+ /* fall through */
+ case VK_LMENU:
+ /* fall through */
+ case VK_RMENU:
+ break;
+
+ case VK_LCONTROL:
+ /*
+ * When pressing AltGr, an extra VK_LCONTROL with a special
+ * scancode with bit 9 set is sent. Let's ignore the extra
+ * VK_LCONTROL, as that will make AltGr misbehave.
+ */
+ if (hooked->scanCode & 0x200) {
+ return 1;
+ }
+ break;
+
+ default:
+ if (win32_grab) {
+ SendMessage(win32_window, wparam, hooked->vkCode, dwmsg);
+ return 1;
+ }
+ break;
+ }
+
+ } else {
+ switch (hooked->vkCode) {
+ case VK_LCONTROL:
+ if (hooked->scanCode & 0x200) {
+ return 1;
+ }
+ break;
+ }
+ }
+ }
+
+ return CallNextHookEx(NULL, code, wparam, lparam);
+}
+
+static void keyboard_hook_unhook(Notifier *n, void *data)
+{
+ UnhookWindowsHookEx(win32_keyboard_hook);
+ win32_keyboard_hook = NULL;
+}
+
+void win32_kbd_set_window(void *hwnd)
+{
+ if (hwnd && !win32_keyboard_hook) {
+ /* note: the installing thread must have a message loop */
+ win32_keyboard_hook = SetWindowsHookEx(WH_KEYBOARD_LL, keyboard_hook_cb,
+ GetModuleHandle(NULL), 0);
+ if (win32_keyboard_hook) {
+ win32_unhook_notifier.notify = keyboard_hook_unhook;
+ qemu_add_exit_notifier(&win32_unhook_notifier);
+ }
+ }
+
+ win32_window = hwnd;
+}
+
+void win32_kbd_set_grab(bool grab)
+{
+ win32_grab = grab;
+}
diff --git a/util/aio-posix.c b/util/aio-posix.c
index c3613d2..1b2a3af 100644
--- a/util/aio-posix.c
+++ b/util/aio-posix.c
@@ -679,6 +679,19 @@
{
fdmon_io_uring_destroy(ctx);
fdmon_epoll_disable(ctx);
+ aio_free_deleted_handlers(ctx);
+}
+
+void aio_context_use_g_source(AioContext *ctx)
+{
+ /*
+ * Disable io_uring when the glib main loop is used because it doesn't
+ * support mixed glib/aio_poll() usage. It relies on aio_poll() being
+ * called regularly so that changes to the monitored file descriptors are
+ * submitted, otherwise a list of pending fd handlers builds up.
+ */
+ fdmon_io_uring_destroy(ctx);
+ aio_free_deleted_handlers(ctx);
}
void aio_context_set_poll_params(AioContext *ctx, int64_t max_ns,
diff --git a/util/aio-win32.c b/util/aio-win32.c
index 729d533..953c56a 100644
--- a/util/aio-win32.c
+++ b/util/aio-win32.c
@@ -414,6 +414,10 @@
{
}
+void aio_context_use_g_source(AioContext *ctx)
+{
+}
+
void aio_context_set_poll_params(AioContext *ctx, int64_t max_ns,
int64_t grow, int64_t shrink, Error **errp)
{
diff --git a/util/async.c b/util/async.c
index 3165a28..1319eee 100644
--- a/util/async.c
+++ b/util/async.c
@@ -362,6 +362,7 @@
GSource *aio_get_g_source(AioContext *ctx)
{
+ aio_context_use_g_source(ctx);
g_source_ref(&ctx->source);
return &ctx->source;
}
diff --git a/util/fdmon-io_uring.c b/util/fdmon-io_uring.c
index d5a80ed..1d14177 100644
--- a/util/fdmon-io_uring.c
+++ b/util/fdmon-io_uring.c
@@ -342,11 +342,18 @@
io_uring_queue_exit(&ctx->fdmon_io_uring);
- /* No need to submit these anymore, just free them. */
+ /* Move handlers due to be removed onto the deleted list */
while ((node = QSLIST_FIRST_RCU(&ctx->submit_list))) {
+ unsigned flags = atomic_fetch_and(&node->flags,
+ ~(FDMON_IO_URING_PENDING |
+ FDMON_IO_URING_ADD |
+ FDMON_IO_URING_REMOVE));
+
+ if (flags & FDMON_IO_URING_REMOVE) {
+ QLIST_INSERT_HEAD_RCU(&ctx->deleted_aio_handlers, node, node_deleted);
+ }
+
QSLIST_REMOVE_HEAD_RCU(&ctx->submit_list, node_submitted);
- QLIST_REMOVE(node, node);
- g_free(node);
}
ctx->fdmon_ops = &fdmon_poll_ops;
diff --git a/util/qemu-sockets.c b/util/qemu-sockets.c
index 86c48b9..b37d288 100644
--- a/util/qemu-sockets.c
+++ b/util/qemu-sockets.c
@@ -863,6 +863,7 @@
char *pathbuf = NULL;
const char *path;
size_t pathlen;
+ size_t addrlen;
sock = qemu_socket(PF_UNIX, SOCK_STREAM, 0);
if (sock < 0) {
@@ -879,9 +880,11 @@
}
pathlen = strlen(path);
- if (pathlen > sizeof(un.sun_path)) {
+ if (pathlen > sizeof(un.sun_path) ||
+ (saddr->abstract && pathlen > (sizeof(un.sun_path) - 1))) {
error_setg(errp, "UNIX socket path '%s' is too long", path);
error_append_hint(errp, "Path must be less than %zu bytes\n",
+ saddr->abstract ? sizeof(un.sun_path) - 1 :
sizeof(un.sun_path));
goto err;
}
@@ -903,7 +906,7 @@
close(fd);
}
- if (unlink(path) < 0 && errno != ENOENT) {
+ if (!saddr->abstract && unlink(path) < 0 && errno != ENOENT) {
error_setg_errno(errp, errno,
"Failed to unlink socket %s", path);
goto err;
@@ -911,9 +914,19 @@
memset(&un, 0, sizeof(un));
un.sun_family = AF_UNIX;
- memcpy(un.sun_path, path, pathlen);
+ addrlen = sizeof(un);
- if (bind(sock, (struct sockaddr*) &un, sizeof(un)) < 0) {
+ if (saddr->abstract) {
+ un.sun_path[0] = '\0';
+ memcpy(&un.sun_path[1], path, pathlen);
+ if (saddr->tight) {
+ addrlen = offsetof(struct sockaddr_un, sun_path) + 1 + pathlen;
+ }
+ } else {
+ memcpy(un.sun_path, path, pathlen);
+ }
+
+ if (bind(sock, (struct sockaddr *) &un, addrlen) < 0) {
error_setg_errno(errp, errno, "Failed to bind socket to %s", path);
goto err;
}
@@ -936,6 +949,7 @@
struct sockaddr_un un;
int sock, rc;
size_t pathlen;
+ size_t addrlen;
if (saddr->path == NULL) {
error_setg(errp, "unix connect: no path specified");
@@ -949,21 +963,32 @@
}
pathlen = strlen(saddr->path);
- if (pathlen > sizeof(un.sun_path)) {
+ if (pathlen > sizeof(un.sun_path) ||
+ (saddr->abstract && pathlen > (sizeof(un.sun_path) - 1))) {
error_setg(errp, "UNIX socket path '%s' is too long", saddr->path);
error_append_hint(errp, "Path must be less than %zu bytes\n",
+ saddr->abstract ? sizeof(un.sun_path) - 1 :
sizeof(un.sun_path));
goto err;
}
memset(&un, 0, sizeof(un));
un.sun_family = AF_UNIX;
- memcpy(un.sun_path, saddr->path, pathlen);
+ addrlen = sizeof(un);
+ if (saddr->abstract) {
+ un.sun_path[0] = '\0';
+ memcpy(&un.sun_path[1], saddr->path, pathlen);
+ if (saddr->tight) {
+ addrlen = offsetof(struct sockaddr_un, sun_path) + 1 + pathlen;
+ }
+ } else {
+ memcpy(un.sun_path, saddr->path, pathlen);
+ }
/* connect to peer */
do {
rc = 0;
- if (connect(sock, (struct sockaddr *) &un, sizeof(un)) < 0) {
+ if (connect(sock, (struct sockaddr *) &un, addrlen) < 0) {
rc = -errno;
}
} while (rc == -EINTR);