aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gitlab-ci.d/buildtest-template.yml81
-rw-r--r--.gitlab-ci.d/buildtest.yml730
-rw-r--r--.gitlab-ci.d/container-core.yml17
-rw-r--r--.gitlab-ci.d/container-cross.yml192
-rw-r--r--.gitlab-ci.d/container-template.yml21
-rw-r--r--.gitlab-ci.d/containers.yml232
-rw-r--r--.gitlab-ci.d/crossbuild-template.yml41
-rw-r--r--.gitlab-ci.d/crossbuilds.yml60
-rw-r--r--.gitlab-ci.d/qemu-project.yml11
-rw-r--r--.gitlab-ci.d/stages.yml8
-rw-r--r--.gitlab-ci.d/static_checks.yml26
-rw-r--r--.gitlab-ci.yml885
-rw-r--r--MAINTAINERS1
-rw-r--r--Makefile2
-rw-r--r--accel/kvm/kvm-all.c615
-rw-r--r--accel/kvm/trace-events7
-rw-r--r--accel/tcg/cpu-exec.c5
-rw-r--r--accel/tcg/cputlb.c2
-rw-r--r--accel/tcg/tb-context.h (renamed from include/exec/tb-context.h)0
-rw-r--r--accel/tcg/tb-hash.h (renamed from include/exec/tb-hash.h)0
-rw-r--r--accel/tcg/tb-lookup.h (renamed from include/exec/tb-lookup.h)2
-rw-r--r--accel/tcg/tcg-runtime.c2
-rw-r--r--accel/tcg/translate-all.c3
-rw-r--r--block/replication.c2
-rwxr-xr-xconfigure79
-rw-r--r--cpu.c18
-rw-r--r--default-configs/devices/ppc64-softmmu.mak1
-rw-r--r--hmp-commands.hx2
-rw-r--r--hw/arm/Kconfig1
-rw-r--r--hw/core/cpu-common.c (renamed from hw/core/cpu.c)116
-rw-r--r--hw/core/cpu-sysemu.c145
-rw-r--r--hw/core/meson.build3
-rw-r--r--hw/i386/Kconfig1
-rw-r--r--hw/mem/Kconfig2
-rw-r--r--hw/mips/jazz.c35
-rw-r--r--hw/net/imx_fec.c8
-rw-r--r--hw/net/trace-events2
-rw-r--r--hw/net/virtio-net.c1
-rw-r--r--hw/ppc/Kconfig1
-rw-r--r--hw/scsi/scsi-disk.c12
-rw-r--r--hw/virtio/virtio.c4
-rw-r--r--include/block/replication.h (renamed from replication.h)4
-rw-r--r--include/exec/exec-all.h1
-rw-r--r--include/exec/memory.h14
-rw-r--r--include/exec/memory_ldst.h.inc16
-rw-r--r--include/exec/memory_ldst_cached.h.inc42
-rw-r--r--include/exec/memory_ldst_phys.h.inc72
-rw-r--r--include/hw/core/cpu.h101
-rw-r--r--include/hw/core/sysemu-cpu-ops.h92
-rw-r--r--include/migration/vmstate.h2
-rw-r--r--include/qemu/config-file.h2
-rw-r--r--include/qemu/qemu-options.h (renamed from qemu-options.h)9
-rw-r--r--include/sysemu/kvm_int.h7
-rw-r--r--include/tcg/tcg.h1
-rw-r--r--memory_ldst.c.inc20
-rw-r--r--meson.build1
-rw-r--r--migration/colo.c2
-rw-r--r--migration/rdma.c83
-rw-r--r--monitor/hmp-cmds.c2
-rw-r--r--net/tap-bsd.c8
-rw-r--r--os-posix.c2
-rw-r--r--os-win32.c1
-rw-r--r--plugins/plugin.h1
-rw-r--r--qapi/qom.json23
-rw-r--r--qemu-options-wrapper.h40
-rw-r--r--qemu-options.hx23
-rw-r--r--replication.c2
-rw-r--r--softmmu/memory.c33
-rw-r--r--softmmu/physmem.c10
-rw-r--r--softmmu/qtest.c185
-rw-r--r--softmmu/vl.c52
-rw-r--r--stubs/meson.build1
-rw-r--r--stubs/module-opts.c6
-rw-r--r--stubs/vmstate.c2
-rw-r--r--target/alpha/cpu.c12
-rw-r--r--target/arm/cpu.c22
-rw-r--r--target/arm/cpu_tcg.c2
-rw-r--r--target/avr/cpu.c12
-rw-r--r--target/avr/machine.c4
-rw-r--r--target/cris/cpu.c14
-rw-r--r--target/hexagon/cpu.c2
-rw-r--r--target/hppa/cpu.c12
-rw-r--r--target/i386/cpu.c34
-rw-r--r--target/i386/cpu.h2
-rw-r--r--target/i386/tcg/tcg-cpu.c2
-rw-r--r--target/m68k/cpu.c12
-rw-r--r--target/m68k/cpu.h8
-rw-r--r--target/m68k/translate.c51
-rw-r--r--target/microblaze/cpu.c12
-rw-r--r--target/mips/cpu-qom.h3
-rw-r--r--target/mips/cpu.c14
-rw-r--r--target/mips/tcg/op_helper.c3
-rw-r--r--target/nios2/cpu.c12
-rw-r--r--target/openrisc/cpu.c12
-rw-r--r--target/ppc/cpu_init.c24
-rw-r--r--target/riscv/cpu.c19
-rw-r--r--target/rx/cpu.c14
-rw-r--r--target/s390x/cpu.c18
-rw-r--r--target/sh4/cpu.c15
-rw-r--r--target/sparc/cpu.c14
-rw-r--r--target/tricore/cpu.c10
-rw-r--r--target/xtensa/cpu.c14
-rw-r--r--tcg/aarch64/tcg-target.c.inc5
-rw-r--r--tests/qtest/fuzz/fuzz.c1
-rw-r--r--tests/unit/test-replication.c2
-rw-r--r--tools/virtiofsd/buffer.c4
-rw-r--r--tools/virtiofsd/fuse_opt.c4
-rw-r--r--tools/virtiofsd/fuse_virtio.c81
-rw-r--r--util/qemu-config.c1
109 files changed, 2855 insertions, 1852 deletions
diff --git a/.gitlab-ci.d/buildtest-template.yml b/.gitlab-ci.d/buildtest-template.yml
new file mode 100644
index 0000000000..3e3e19d96b
--- /dev/null
+++ b/.gitlab-ci.d/buildtest-template.yml
@@ -0,0 +1,81 @@
+.native_build_job_template:
+ stage: build
+ image: $CI_REGISTRY_IMAGE/qemu/$IMAGE:latest
+ before_script:
+ - JOBS=$(expr $(nproc) + 1)
+ script:
+ - if test -n "$LD_JOBS";
+ then
+ scripts/git-submodule.sh update meson ;
+ fi
+ - mkdir build
+ - cd build
+ - if test -n "$TARGETS";
+ then
+ ../configure --enable-werror --disable-docs ${LD_JOBS:+--meson=git} $CONFIGURE_ARGS --target-list="$TARGETS" ;
+ else
+ ../configure --enable-werror --disable-docs ${LD_JOBS:+--meson=git} $CONFIGURE_ARGS ;
+ fi || { cat config.log meson-logs/meson-log.txt && exit 1; }
+ - if test -n "$LD_JOBS";
+ then
+ ../meson/meson.py configure . -Dbackend_max_links="$LD_JOBS" ;
+ fi || exit 1;
+ - make -j"$JOBS"
+ - if test -n "$MAKE_CHECK_ARGS";
+ then
+ make -j"$JOBS" $MAKE_CHECK_ARGS ;
+ fi
+
+.native_test_job_template:
+ stage: test
+ image: $CI_REGISTRY_IMAGE/qemu/$IMAGE:latest
+ script:
+ - scripts/git-submodule.sh update
+ $(sed -n '/GIT_SUBMODULES=/ s/.*=// p' build/config-host.mak)
+ - cd build
+ - find . -type f -exec touch {} +
+ # Avoid recompiling by hiding ninja with NINJA=":"
+ - make NINJA=":" $MAKE_CHECK_ARGS
+
+.acceptance_test_job_template:
+ extends: .native_test_job_template
+ cache:
+ key: "${CI_JOB_NAME}-cache"
+ paths:
+ - ${CI_PROJECT_DIR}/avocado-cache
+ policy: pull-push
+ artifacts:
+ name: "$CI_JOB_NAME-$CI_COMMIT_REF_SLUG"
+ when: on_failure
+ expire_in: 7 days
+ paths:
+ - build/tests/results/latest/results.xml
+ - build/tests/results/latest/test-results
+ reports:
+ junit: build/tests/results/latest/results.xml
+ before_script:
+ - mkdir -p ~/.config/avocado
+ - echo "[datadir.paths]" > ~/.config/avocado/avocado.conf
+ - echo "cache_dirs = ['${CI_PROJECT_DIR}/avocado-cache']"
+ >> ~/.config/avocado/avocado.conf
+ - echo -e '[job.output.testlogs]\nstatuses = ["FAIL", "INTERRUPT"]'
+ >> ~/.config/avocado/avocado.conf
+ - if [ -d ${CI_PROJECT_DIR}/avocado-cache ]; then
+ du -chs ${CI_PROJECT_DIR}/avocado-cache ;
+ fi
+ - export AVOCADO_ALLOW_UNTRUSTED_CODE=1
+ after_script:
+ - cd build
+ - du -chs ${CI_PROJECT_DIR}/avocado-cache
+ rules:
+ # Only run these jobs if running on the mainstream namespace,
+ # or if the user set the QEMU_CI_AVOCADO_TESTING variable (either
+ # in its namespace setting or via git-push option, see documentation
+ # in /.gitlab-ci.yml of this repository).
+ - if: '$CI_PROJECT_NAMESPACE == "qemu-project"'
+ when: always
+ - if: '$QEMU_CI_AVOCADO_TESTING'
+ when: always
+ # Otherwise, set to manual (the jobs are created but not run).
+ - when: manual
+ allow_failure: true
diff --git a/.gitlab-ci.d/buildtest.yml b/.gitlab-ci.d/buildtest.yml
new file mode 100644
index 0000000000..807040c1c7
--- /dev/null
+++ b/.gitlab-ci.d/buildtest.yml
@@ -0,0 +1,730 @@
+include:
+ - local: '/.gitlab-ci.d/buildtest-template.yml'
+
+build-system-alpine:
+ extends: .native_build_job_template
+ needs:
+ - job: amd64-alpine-container
+ variables:
+ IMAGE: alpine
+ TARGETS: aarch64-softmmu alpha-softmmu cris-softmmu hppa-softmmu
+ microblazeel-softmmu mips64el-softmmu
+ MAKE_CHECK_ARGS: check-build
+ CONFIGURE_ARGS: --enable-docs --enable-trace-backends=log,simple,syslog
+ artifacts:
+ expire_in: 2 days
+ paths:
+ - .git-submodule-status
+ - build
+
+check-system-alpine:
+ extends: .native_test_job_template
+ needs:
+ - job: build-system-alpine
+ artifacts: true
+ variables:
+ IMAGE: alpine
+ MAKE_CHECK_ARGS: check
+
+acceptance-system-alpine:
+ extends: .acceptance_test_job_template
+ needs:
+ - job: build-system-alpine
+ artifacts: true
+ variables:
+ IMAGE: alpine
+ MAKE_CHECK_ARGS: check-acceptance
+
+build-system-ubuntu:
+ extends: .native_build_job_template
+ needs:
+ job: amd64-ubuntu2004-container
+ variables:
+ IMAGE: ubuntu2004
+ CONFIGURE_ARGS: --enable-docs --enable-fdt=system --enable-slirp=system
+ TARGETS: aarch64-softmmu alpha-softmmu cris-softmmu hppa-softmmu
+ microblazeel-softmmu mips64el-softmmu
+ MAKE_CHECK_ARGS: check-build
+ artifacts:
+ expire_in: 2 days
+ paths:
+ - build
+
+check-system-ubuntu:
+ extends: .native_test_job_template
+ needs:
+ - job: build-system-ubuntu
+ artifacts: true
+ variables:
+ IMAGE: ubuntu2004
+ MAKE_CHECK_ARGS: check
+
+acceptance-system-ubuntu:
+ extends: .acceptance_test_job_template
+ needs:
+ - job: build-system-ubuntu
+ artifacts: true
+ variables:
+ IMAGE: ubuntu2004
+ MAKE_CHECK_ARGS: check-acceptance
+
+build-system-debian:
+ extends: .native_build_job_template
+ needs:
+ job: amd64-debian-container
+ variables:
+ IMAGE: debian-amd64
+ CONFIGURE_ARGS: --enable-fdt=system
+ TARGETS: arm-softmmu avr-softmmu i386-softmmu mipsel-softmmu
+ riscv64-softmmu sh4eb-softmmu sparc-softmmu xtensaeb-softmmu
+ MAKE_CHECK_ARGS: check-build
+ artifacts:
+ expire_in: 2 days
+ paths:
+ - build
+
+check-system-debian:
+ extends: .native_test_job_template
+ needs:
+ - job: build-system-debian
+ artifacts: true
+ variables:
+ IMAGE: debian-amd64
+ MAKE_CHECK_ARGS: check
+
+acceptance-system-debian:
+ extends: .acceptance_test_job_template
+ needs:
+ - job: build-system-debian
+ artifacts: true
+ variables:
+ IMAGE: debian-amd64
+ MAKE_CHECK_ARGS: check-acceptance
+
+build-system-fedora:
+ extends: .native_build_job_template
+ needs:
+ job: amd64-fedora-container
+ variables:
+ IMAGE: fedora
+ CONFIGURE_ARGS: --disable-gcrypt --enable-nettle --enable-docs
+ --enable-fdt=system --enable-slirp=system --enable-capstone=system
+ TARGETS: tricore-softmmu microblaze-softmmu mips-softmmu
+ xtensa-softmmu m68k-softmmu riscv32-softmmu ppc-softmmu sparc64-softmmu
+ MAKE_CHECK_ARGS: check-build
+ artifacts:
+ expire_in: 2 days
+ paths:
+ - build
+
+check-system-fedora:
+ extends: .native_test_job_template
+ needs:
+ - job: build-system-fedora
+ artifacts: true
+ variables:
+ IMAGE: fedora
+ MAKE_CHECK_ARGS: check
+
+acceptance-system-fedora:
+ extends: .acceptance_test_job_template
+ needs:
+ - job: build-system-fedora
+ artifacts: true
+ variables:
+ IMAGE: fedora
+ MAKE_CHECK_ARGS: check-acceptance
+
+build-system-centos:
+ extends: .native_build_job_template
+ needs:
+ job: amd64-centos8-container
+ variables:
+ IMAGE: centos8
+ CONFIGURE_ARGS: --disable-nettle --enable-gcrypt --enable-fdt=system
+ --enable-modules --enable-trace-backends=dtrace
+ TARGETS: ppc64-softmmu or1k-softmmu s390x-softmmu
+ x86_64-softmmu rx-softmmu sh4-softmmu nios2-softmmu
+ MAKE_CHECK_ARGS: check-build
+ artifacts:
+ expire_in: 2 days
+ paths:
+ - build
+
+check-system-centos:
+ extends: .native_test_job_template
+ needs:
+ - job: build-system-centos
+ artifacts: true
+ variables:
+ IMAGE: centos8
+ MAKE_CHECK_ARGS: check
+
+acceptance-system-centos:
+ extends: .acceptance_test_job_template
+ needs:
+ - job: build-system-centos
+ artifacts: true
+ variables:
+ IMAGE: centos8
+ MAKE_CHECK_ARGS: check-acceptance
+
+build-system-opensuse:
+ extends: .native_build_job_template
+ needs:
+ job: amd64-opensuse-leap-container
+ variables:
+ IMAGE: opensuse-leap
+ CONFIGURE_ARGS: --enable-fdt=system
+ TARGETS: s390x-softmmu x86_64-softmmu aarch64-softmmu
+ MAKE_CHECK_ARGS: check-build
+ artifacts:
+ expire_in: 2 days
+ paths:
+ - build
+
+check-system-opensuse:
+ extends: .native_test_job_template
+ needs:
+ - job: build-system-opensuse
+ artifacts: true
+ variables:
+ IMAGE: opensuse-leap
+ MAKE_CHECK_ARGS: check
+
+acceptance-system-opensuse:
+ extends: .acceptance_test_job_template
+ needs:
+ - job: build-system-opensuse
+ artifacts: true
+ variables:
+ IMAGE: opensuse-leap
+ MAKE_CHECK_ARGS: check-acceptance
+
+
+build-disabled:
+ extends: .native_build_job_template
+ needs:
+ job: amd64-fedora-container
+ variables:
+ IMAGE: fedora
+ CONFIGURE_ARGS:
+ --disable-attr
+ --disable-auth-pam
+ --disable-avx2
+ --disable-bochs
+ --disable-brlapi
+ --disable-bzip2
+ --disable-cap-ng
+ --disable-capstone
+ --disable-cloop
+ --disable-coroutine-pool
+ --disable-curl
+ --disable-curses
+ --disable-dmg
+ --disable-docs
+ --disable-gcrypt
+ --disable-glusterfs
+ --disable-gnutls
+ --disable-gtk
+ --disable-guest-agent
+ --disable-iconv
+ --disable-keyring
+ --disable-kvm
+ --disable-libiscsi
+ --disable-libpmem
+ --disable-libssh
+ --disable-libudev
+ --disable-libusb
+ --disable-libxml2
+ --disable-linux-aio
+ --disable-live-block-migration
+ --disable-lzo
+ --disable-malloc-trim
+ --disable-mpath
+ --disable-nettle
+ --disable-numa
+ --disable-opengl
+ --disable-parallels
+ --disable-pie
+ --disable-qcow1
+ --disable-qed
+ --disable-qom-cast-debug
+ --disable-rbd
+ --disable-rdma
+ --disable-replication
+ --disable-sdl
+ --disable-seccomp
+ --disable-slirp
+ --disable-smartcard
+ --disable-snappy
+ --disable-sparse
+ --disable-spice
+ --disable-strip
+ --disable-tpm
+ --disable-usb-redir
+ --disable-vdi
+ --disable-vhost-crypto
+ --disable-vhost-net
+ --disable-vhost-scsi
+ --disable-vhost-kernel
+ --disable-vhost-user
+ --disable-vhost-vdpa
+ --disable-vhost-vsock
+ --disable-virglrenderer
+ --disable-vnc
+ --disable-vte
+ --disable-vvfat
+ --disable-xen
+ --disable-zstd
+ TARGETS: arm-softmmu i386-softmmu ppc64-softmmu mips64-softmmu
+ s390x-softmmu i386-linux-user
+ MAKE_CHECK_ARGS: check-qtest SPEED=slow
+
+# This jobs explicitly disable TCG (--disable-tcg), KVM is detected by
+# the configure script. The container doesn't contain Xen headers so
+# Xen accelerator is not detected / selected. As result it build the
+# i386-softmmu and x86_64-softmmu with KVM being the single accelerator
+# available.
+# Also use a different coroutine implementation (which is only really of
+# interest to KVM users, i.e. with TCG disabled)
+build-tcg-disabled:
+ extends: .native_build_job_template
+ needs:
+ job: amd64-centos8-container
+ variables:
+ IMAGE: centos8
+ script:
+ - mkdir build
+ - cd build
+ - ../configure --disable-tcg --audio-drv-list="" --with-coroutine=ucontext
+ || { cat config.log meson-logs/meson-log.txt && exit 1; }
+ - make -j"$JOBS"
+ - make check-unit
+ - make check-qapi-schema
+ - cd tests/qemu-iotests/
+ - ./check -raw 001 002 003 004 005 008 009 010 011 012 021 025 032 033 048
+ 052 063 077 086 101 104 106 113 148 150 151 152 157 159 160 163
+ 170 171 183 184 192 194 197 208 215 221 222 226 227 236 253 277
+ - ./check -qcow2 028 051 056 057 058 065 068 082 085 091 095 096 102 122
+ 124 132 139 142 144 145 151 152 155 157 165 194 196 197 200 202
+ 208 209 215 216 218 222 227 234 246 247 248 250 254 255 257 258
+ 260 261 262 263 264 270 272 273 277 279
+
+build-user:
+ extends: .native_build_job_template
+ needs:
+ job: amd64-debian-user-cross-container
+ variables:
+ IMAGE: debian-all-test-cross
+ CONFIGURE_ARGS: --disable-tools --disable-system
+ MAKE_CHECK_ARGS: check-tcg
+
+build-user-static:
+ extends: .native_build_job_template
+ needs:
+ job: amd64-debian-user-cross-container
+ variables:
+ IMAGE: debian-all-test-cross
+ CONFIGURE_ARGS: --disable-tools --disable-system --static
+ MAKE_CHECK_ARGS: check-tcg
+
+# Because the hexagon cross-compiler takes so long to build we don't rely
+# on the CI system to build it and hence this job has an optional dependency
+# declared. The image is manually uploaded.
+build-user-hexagon:
+ extends: .native_build_job_template
+ needs:
+ job: hexagon-cross-container
+ optional: true
+ variables:
+ IMAGE: debian-hexagon-cross
+ TARGETS: hexagon-linux-user
+ CONFIGURE_ARGS: --disable-tools --disable-docs --enable-debug-tcg
+ MAKE_CHECK_ARGS: check-tcg
+
+# Only build the softmmu targets we have check-tcg tests for
+build-some-softmmu:
+ extends: .native_build_job_template
+ needs:
+ job: amd64-debian-user-cross-container
+ variables:
+ IMAGE: debian-all-test-cross
+ CONFIGURE_ARGS: --disable-tools --enable-debug
+ TARGETS: xtensa-softmmu arm-softmmu aarch64-softmmu alpha-softmmu
+ MAKE_CHECK_ARGS: check-tcg
+
+# Run check-tcg against linux-user (with plugins)
+# we skip sparc64-linux-user until it has been fixed somewhat
+# we skip cris-linux-user as it doesn't use the common run loop
+build-user-plugins:
+ extends: .native_build_job_template
+ needs:
+ job: amd64-debian-user-cross-container
+ variables:
+ IMAGE: debian-all-test-cross
+ CONFIGURE_ARGS: --disable-tools --disable-system --enable-plugins --enable-debug-tcg --target-list-exclude=sparc64-linux-user,cris-linux-user
+ MAKE_CHECK_ARGS: check-tcg
+ timeout: 1h 30m
+
+build-some-softmmu-plugins:
+ extends: .native_build_job_template
+ needs:
+ job: amd64-debian-user-cross-container
+ variables:
+ IMAGE: debian-all-test-cross
+ CONFIGURE_ARGS: --disable-tools --disable-user --enable-plugins --enable-debug-tcg
+ TARGETS: xtensa-softmmu arm-softmmu aarch64-softmmu alpha-softmmu
+ MAKE_CHECK_ARGS: check-tcg
+
+clang-system:
+ extends: .native_build_job_template
+ needs:
+ job: amd64-fedora-container
+ variables:
+ IMAGE: fedora
+ CONFIGURE_ARGS: --cc=clang --cxx=clang++
+ --extra-cflags=-fsanitize=undefined --extra-cflags=-fno-sanitize-recover=undefined
+ TARGETS: alpha-softmmu arm-softmmu m68k-softmmu mips64-softmmu
+ ppc-softmmu s390x-softmmu
+ MAKE_CHECK_ARGS: check-qtest check-tcg
+
+clang-user:
+ extends: .native_build_job_template
+ needs:
+ job: amd64-debian-user-cross-container
+ variables:
+ IMAGE: debian-all-test-cross
+ CONFIGURE_ARGS: --cc=clang --cxx=clang++ --disable-system
+ --target-list-exclude=microblazeel-linux-user,aarch64_be-linux-user,i386-linux-user,m68k-linux-user,mipsn32el-linux-user,xtensaeb-linux-user
+ --extra-cflags=-fsanitize=undefined --extra-cflags=-fno-sanitize-recover=undefined
+ MAKE_CHECK_ARGS: check-unit check-tcg
+
+# Set LD_JOBS=1 because this requires LTO and ld consumes a large amount of memory.
+# On gitlab runners, default value sometimes end up calling 2 lds concurrently and
+# triggers an Out-Of-Memory error
+#
+# Since slirp callbacks are used in QEMU Timers, slirp needs to be compiled together
+# with QEMU and linked as a static library to avoid false positives in CFI checks.
+# This can be accomplished by using -enable-slirp=git, which avoids the use of
+# a system-wide version of the library
+#
+# Split in three sets of build/check/acceptance to limit the execution time of each
+# job
+build-cfi-aarch64:
+ extends: .native_build_job_template
+ needs:
+ - job: amd64-fedora-container
+ variables:
+ LD_JOBS: 1
+ AR: llvm-ar
+ IMAGE: fedora
+ CONFIGURE_ARGS: --cc=clang --cxx=clang++ --enable-cfi --enable-cfi-debug
+ --enable-safe-stack --enable-slirp=git
+ TARGETS: aarch64-softmmu
+ MAKE_CHECK_ARGS: check-build
+ timeout: 70m
+ artifacts:
+ expire_in: 2 days
+ paths:
+ - build
+
+check-cfi-aarch64:
+ extends: .native_test_job_template
+ needs:
+ - job: build-cfi-aarch64
+ artifacts: true
+ variables:
+ IMAGE: fedora
+ MAKE_CHECK_ARGS: check
+
+acceptance-cfi-aarch64:
+ extends: .acceptance_test_job_template
+ needs:
+ - job: build-cfi-aarch64
+ artifacts: true
+ variables:
+ IMAGE: fedora
+ MAKE_CHECK_ARGS: check-acceptance
+
+build-cfi-ppc64-s390x:
+ extends: .native_build_job_template
+ needs:
+ - job: amd64-fedora-container
+ variables:
+ LD_JOBS: 1
+ AR: llvm-ar
+ IMAGE: fedora
+ CONFIGURE_ARGS: --cc=clang --cxx=clang++ --enable-cfi --enable-cfi-debug
+ --enable-safe-stack --enable-slirp=git
+ TARGETS: ppc64-softmmu s390x-softmmu
+ MAKE_CHECK_ARGS: check-build
+ timeout: 70m
+ artifacts:
+ expire_in: 2 days
+ paths:
+ - build
+
+check-cfi-ppc64-s390x:
+ extends: .native_test_job_template
+ needs:
+ - job: build-cfi-ppc64-s390x
+ artifacts: true
+ variables:
+ IMAGE: fedora
+ MAKE_CHECK_ARGS: check
+
+acceptance-cfi-ppc64-s390x:
+ extends: .acceptance_test_job_template
+ needs:
+ - job: build-cfi-ppc64-s390x
+ artifacts: true
+ variables:
+ IMAGE: fedora
+ MAKE_CHECK_ARGS: check-acceptance
+
+build-cfi-x86_64:
+ extends: .native_build_job_template
+ needs:
+ - job: amd64-fedora-container
+ variables:
+ LD_JOBS: 1
+ AR: llvm-ar
+ IMAGE: fedora
+ CONFIGURE_ARGS: --cc=clang --cxx=clang++ --enable-cfi --enable-cfi-debug
+ --enable-safe-stack --enable-slirp=git
+ TARGETS: x86_64-softmmu
+ MAKE_CHECK_ARGS: check-build
+ timeout: 70m
+ artifacts:
+ expire_in: 2 days
+ paths:
+ - build
+
+check-cfi-x86_64:
+ extends: .native_test_job_template
+ needs:
+ - job: build-cfi-x86_64
+ artifacts: true
+ variables:
+ IMAGE: fedora
+ MAKE_CHECK_ARGS: check
+
+acceptance-cfi-x86_64:
+ extends: .acceptance_test_job_template
+ needs:
+ - job: build-cfi-x86_64
+ artifacts: true
+ variables:
+ IMAGE: fedora
+ MAKE_CHECK_ARGS: check-acceptance
+
+tsan-build:
+ extends: .native_build_job_template
+ needs:
+ job: amd64-ubuntu2004-container
+ variables:
+ IMAGE: ubuntu2004
+ CONFIGURE_ARGS: --enable-tsan --cc=clang-10 --cxx=clang++-10
+ --enable-trace-backends=ust --enable-fdt=system --enable-slirp=system
+ TARGETS: x86_64-softmmu ppc64-softmmu riscv64-softmmu x86_64-linux-user
+ MAKE_CHECK_ARGS: bench V=1
+
+# These targets are on the way out
+build-deprecated:
+ extends: .native_build_job_template
+ needs:
+ job: amd64-debian-user-cross-container
+ variables:
+ IMAGE: debian-all-test-cross
+ CONFIGURE_ARGS: --disable-tools
+ MAKE_CHECK_ARGS: build-tcg
+ TARGETS: ppc64abi32-linux-user
+ artifacts:
+ expire_in: 2 days
+ paths:
+ - build
+
+# We split the check-tcg step as test failures are expected but we still
+# want to catch the build breaking.
+check-deprecated:
+ extends: .native_test_job_template
+ needs:
+ - job: build-deprecated
+ artifacts: true
+ variables:
+ IMAGE: debian-all-test-cross
+ MAKE_CHECK_ARGS: check-tcg
+ allow_failure: true
+
+# gprof/gcov are GCC features
+gprof-gcov:
+ extends: .native_build_job_template
+ needs:
+ job: amd64-ubuntu2004-container
+ variables:
+ IMAGE: ubuntu2004
+ CONFIGURE_ARGS: --enable-gprof --enable-gcov
+ MAKE_CHECK_ARGS: check
+ TARGETS: aarch64-softmmu ppc64-softmmu s390x-softmmu x86_64-softmmu
+ timeout: 70m
+ after_script:
+ - ${CI_PROJECT_DIR}/scripts/ci/coverage-summary.sh
+
+build-oss-fuzz:
+ extends: .native_build_job_template
+ needs:
+ job: amd64-fedora-container
+ variables:
+ IMAGE: fedora
+ script:
+ - mkdir build-oss-fuzz
+ - CC="clang" CXX="clang++" CFLAGS="-fsanitize=address"
+ ./scripts/oss-fuzz/build.sh
+ - export ASAN_OPTIONS="fast_unwind_on_malloc=0"
+ - for fuzzer in $(find ./build-oss-fuzz/DEST_DIR/ -executable -type f
+ | grep -v slirp); do
+ grep "LLVMFuzzerTestOneInput" ${fuzzer} > /dev/null 2>&1 || continue ;
+ echo Testing ${fuzzer} ... ;
+ "${fuzzer}" -runs=1 -seed=1 || exit 1 ;
+ done
+ # Unrelated to fuzzer: run some tests with -fsanitize=address
+ - cd build-oss-fuzz && make check-qtest-i386 check-unit
+
+build-tci:
+ extends: .native_build_job_template
+ needs:
+ job: amd64-debian-user-cross-container
+ variables:
+ IMAGE: debian-all-test-cross
+ script:
+ - TARGETS="aarch64 alpha arm hppa m68k microblaze ppc64 s390x x86_64"
+ - mkdir build
+ - cd build
+ - ../configure --enable-tcg-interpreter
+ --target-list="$(for tg in $TARGETS; do echo -n ${tg}'-softmmu '; done)" || { cat config.log meson-logs/meson-log.txt && exit 1; }
+ - make -j"$JOBS"
+ - make tests/qtest/boot-serial-test tests/qtest/cdrom-test tests/qtest/pxe-test
+ - for tg in $TARGETS ; do
+ export QTEST_QEMU_BINARY="./qemu-system-${tg}" ;
+ ./tests/qtest/boot-serial-test || exit 1 ;
+ ./tests/qtest/cdrom-test || exit 1 ;
+ done
+ - QTEST_QEMU_BINARY="./qemu-system-x86_64" ./tests/qtest/pxe-test
+ - QTEST_QEMU_BINARY="./qemu-system-s390x" ./tests/qtest/pxe-test -m slow
+ - make check-tcg
+
+# Alternate coroutines implementations are only really of interest to KVM users
+# However we can't test against KVM on Gitlab-CI so we can only run unit tests
+build-coroutine-sigaltstack:
+ extends: .native_build_job_template
+ needs:
+ job: amd64-ubuntu2004-container
+ variables:
+ IMAGE: ubuntu2004
+ CONFIGURE_ARGS: --with-coroutine=sigaltstack --disable-tcg
+ --enable-trace-backends=ftrace
+ MAKE_CHECK_ARGS: check-unit
+
+# Most jobs test latest gcrypt or nettle builds
+#
+# These jobs test old gcrypt and nettle from RHEL7
+# which had some API differences.
+crypto-old-nettle:
+ extends: .native_build_job_template
+ needs:
+ job: amd64-centos7-container
+ variables:
+ IMAGE: centos7
+ TARGETS: x86_64-softmmu x86_64-linux-user
+ CONFIGURE_ARGS: --disable-gcrypt --enable-nettle
+ MAKE_CHECK_ARGS: check
+
+crypto-old-gcrypt:
+ extends: .native_build_job_template
+ needs:
+ job: amd64-centos7-container
+ variables:
+ IMAGE: centos7
+ TARGETS: x86_64-softmmu x86_64-linux-user
+ CONFIGURE_ARGS: --disable-nettle --enable-gcrypt
+ MAKE_CHECK_ARGS: check
+
+crypto-only-gnutls:
+ extends: .native_build_job_template
+ needs:
+ job: amd64-centos7-container
+ variables:
+ IMAGE: centos7
+ TARGETS: x86_64-softmmu x86_64-linux-user
+ CONFIGURE_ARGS: --disable-nettle --disable-gcrypt --enable-gnutls
+ MAKE_CHECK_ARGS: check
+
+
+# Check our reduced build configurations
+build-without-default-devices:
+ extends: .native_build_job_template
+ needs:
+ job: amd64-centos8-container
+ variables:
+ IMAGE: centos8
+ CONFIGURE_ARGS: --without-default-devices --disable-user
+
+build-without-default-features:
+ extends: .native_build_job_template
+ needs:
+ job: amd64-debian-container
+ variables:
+ IMAGE: debian-amd64
+ CONFIGURE_ARGS: --without-default-features --disable-user
+ --target-list-exclude=arm-softmmu,i386-softmmu,mipsel-softmmu,mips64-softmmu,ppc-softmmu
+ MAKE_CHECK_ARGS: check-unit
+
+build-libvhost-user:
+ stage: build
+ image: $CI_REGISTRY_IMAGE/qemu/fedora:latest
+ needs:
+ job: amd64-fedora-container
+ before_script:
+ - dnf install -y meson ninja-build
+ script:
+ - mkdir subprojects/libvhost-user/build
+ - cd subprojects/libvhost-user/build
+ - meson
+ - ninja
+
+# No targets are built here, just tools, docs, and unit tests. This
+# also feeds into the eventual documentation deployment steps later
+build-tools-and-docs-debian:
+ extends: .native_build_job_template
+ needs:
+ job: amd64-debian-container
+ variables:
+ IMAGE: debian-amd64
+ MAKE_CHECK_ARGS: check-unit check-softfloat ctags TAGS cscope
+ CONFIGURE_ARGS: --disable-system --disable-user --enable-docs --enable-tools
+ artifacts:
+ expire_in: 2 days
+ paths:
+ - build
+
+# Prepare for GitLab pages deployment. Anything copied into the
+# "public" directory will be deployed to $USER.gitlab.io/$PROJECT
+pages:
+ image: $CI_REGISTRY_IMAGE/qemu/debian-amd64:latest
+ stage: test
+ needs:
+ - job: build-tools-and-docs-debian
+ script:
+ - mkdir -p public
+ # HTML-ised source tree
+ - make gtags
+ - htags -anT --tree-view=filetree -m qemu_init
+ -t "Welcome to the QEMU sourcecode"
+ - mv HTML public/src
+ # Project documentation
+ - make -C build install DESTDIR=$(pwd)/temp-install
+ - mv temp-install/usr/local/share/doc/qemu/* public/
+ artifacts:
+ paths:
+ - public
diff --git a/.gitlab-ci.d/container-core.yml b/.gitlab-ci.d/container-core.yml
new file mode 100644
index 0000000000..e8dd1f476a
--- /dev/null
+++ b/.gitlab-ci.d/container-core.yml
@@ -0,0 +1,17 @@
+include:
+ - local: '/.gitlab-ci.d/container-template.yml'
+
+amd64-centos8-container:
+ extends: .container_job_template
+ variables:
+ NAME: centos8
+
+amd64-fedora-container:
+ extends: .container_job_template
+ variables:
+ NAME: fedora
+
+amd64-debian10-container:
+ extends: .container_job_template
+ variables:
+ NAME: debian10
diff --git a/.gitlab-ci.d/container-cross.yml b/.gitlab-ci.d/container-cross.yml
new file mode 100644
index 0000000000..0fcebe363a
--- /dev/null
+++ b/.gitlab-ci.d/container-cross.yml
@@ -0,0 +1,192 @@
+alpha-debian-cross-container:
+ extends: .container_job_template
+ stage: containers-layer2
+ needs: ['amd64-debian10-container']
+ variables:
+ NAME: debian-alpha-cross
+
+amd64-debian-cross-container:
+ extends: .container_job_template
+ stage: containers-layer2
+ needs: ['amd64-debian10-container']
+ variables:
+ NAME: debian-amd64-cross
+
+amd64-debian-user-cross-container:
+ extends: .container_job_template
+ stage: containers-layer2
+ needs: ['amd64-debian10-container']
+ variables:
+ NAME: debian-all-test-cross
+
+arm64-debian-cross-container:
+ extends: .container_job_template
+ stage: containers-layer2
+ needs: ['amd64-debian10-container']
+ variables:
+ NAME: debian-arm64-cross
+
+arm64-test-debian-cross-container:
+ extends: .container_job_template
+ stage: containers-layer2
+ needs: ['amd64-debian11-container']
+ variables:
+ NAME: debian-arm64-test-cross
+
+armel-debian-cross-container:
+ extends: .container_job_template
+ stage: containers-layer2
+ needs: ['amd64-debian10-container']
+ variables:
+ NAME: debian-armel-cross
+
+armhf-debian-cross-container:
+ extends: .container_job_template
+ stage: containers-layer2
+ needs: ['amd64-debian10-container']
+ variables:
+ NAME: debian-armhf-cross
+
+# We never want to build hexagon in the CI system and by default we
+# always want to refer to the master registry where it lives.
+hexagon-cross-container:
+ image: docker:stable
+ stage: containers
+ rules:
+ - if: '$CI_PROJECT_NAMESPACE == "qemu-project"'
+ when: never
+ - when: always
+ variables:
+ NAME: debian-hexagon-cross
+ GIT_DEPTH: 1
+ services:
+ - docker:dind
+ before_script:
+ - export TAG="$CI_REGISTRY_IMAGE/qemu/$NAME:latest"
+ - export COMMON_TAG="$CI_REGISTRY/qemu-project/qemu/qemu/$NAME:latest"
+ - docker info
+ - docker login $CI_REGISTRY -u "$CI_REGISTRY_USER" -p "$CI_REGISTRY_PASSWORD"
+ script:
+ - echo "TAG:$TAG"
+ - echo "COMMON_TAG:$COMMON_TAG"
+ - docker pull $COMMON_TAG
+ - docker tag $COMMON_TAG $TAG
+ - docker push "$TAG"
+ after_script:
+ - docker logout
+
+hppa-debian-cross-container:
+ extends: .container_job_template
+ stage: containers-layer2
+ needs: ['amd64-debian10-container']
+ variables:
+ NAME: debian-hppa-cross
+
+m68k-debian-cross-container:
+ extends: .container_job_template
+ stage: containers-layer2
+ needs: ['amd64-debian10-container']
+ variables:
+ NAME: debian-m68k-cross
+
+mips64-debian-cross-container:
+ extends: .container_job_template
+ stage: containers-layer2
+ needs: ['amd64-debian10-container']
+ variables:
+ NAME: debian-mips64-cross
+
+mips64el-debian-cross-container:
+ extends: .container_job_template
+ stage: containers-layer2
+ needs: ['amd64-debian10-container']
+ variables:
+ NAME: debian-mips64el-cross
+
+mips-debian-cross-container:
+ extends: .container_job_template
+ stage: containers-layer2
+ needs: ['amd64-debian10-container']
+ variables:
+ NAME: debian-mips-cross
+
+mipsel-debian-cross-container:
+ extends: .container_job_template
+ stage: containers-layer2
+ needs: ['amd64-debian10-container']
+ variables:
+ NAME: debian-mipsel-cross
+
+powerpc-test-cross-container:
+ extends: .container_job_template
+ stage: containers-layer2
+ needs: ['amd64-debian11-container']
+ variables:
+ NAME: debian-powerpc-test-cross
+
+ppc64el-debian-cross-container:
+ extends: .container_job_template
+ stage: containers-layer2
+ needs: ['amd64-debian10-container']
+ variables:
+ NAME: debian-ppc64el-cross
+
+riscv64-debian-cross-container:
+ extends: .container_job_template
+ stage: containers-layer2
+ needs: ['amd64-debian10-container']
+ variables:
+ NAME: debian-riscv64-cross
+
+s390x-debian-cross-container:
+ extends: .container_job_template
+ stage: containers-layer2
+ needs: ['amd64-debian10-container']
+ variables:
+ NAME: debian-s390x-cross
+
+sh4-debian-cross-container:
+ extends: .container_job_template
+ stage: containers-layer2
+ needs: ['amd64-debian10-container']
+ variables:
+ NAME: debian-sh4-cross
+
+sparc64-debian-cross-container:
+ extends: .container_job_template
+ stage: containers-layer2
+ needs: ['amd64-debian10-container']
+ variables:
+ NAME: debian-sparc64-cross
+
+tricore-debian-cross-container:
+ extends: .container_job_template
+ stage: containers-layer2
+ needs: ['amd64-debian10-container']
+ variables:
+ NAME: debian-tricore-cross
+
+xtensa-debian-cross-container:
+ extends: .container_job_template
+ variables:
+ NAME: debian-xtensa-cross
+
+cris-fedora-cross-container:
+ extends: .container_job_template
+ variables:
+ NAME: fedora-cris-cross
+
+i386-fedora-cross-container:
+ extends: .container_job_template
+ variables:
+ NAME: fedora-i386-cross
+
+win32-fedora-cross-container:
+ extends: .container_job_template
+ variables:
+ NAME: fedora-win32-cross
+
+win64-fedora-cross-container:
+ extends: .container_job_template
+ variables:
+ NAME: fedora-win64-cross
diff --git a/.gitlab-ci.d/container-template.yml b/.gitlab-ci.d/container-template.yml
new file mode 100644
index 0000000000..1baecd9460
--- /dev/null
+++ b/.gitlab-ci.d/container-template.yml
@@ -0,0 +1,21 @@
+.container_job_template:
+ image: docker:stable
+ stage: containers
+ services:
+ - docker:dind
+ before_script:
+ - export TAG="$CI_REGISTRY_IMAGE/qemu/$NAME:latest"
+ - export COMMON_TAG="$CI_REGISTRY/qemu-project/qemu/$NAME:latest"
+ - apk add python3
+ - docker info
+ - docker login $CI_REGISTRY -u "$CI_REGISTRY_USER" -p "$CI_REGISTRY_PASSWORD"
+ script:
+ - echo "TAG:$TAG"
+ - echo "COMMON_TAG:$COMMON_TAG"
+ - ./tests/docker/docker.py --engine docker build
+ -t "qemu/$NAME" -f "tests/docker/dockerfiles/$NAME.docker"
+ -r $CI_REGISTRY/qemu-project/qemu
+ - docker tag "qemu/$NAME" "$TAG"
+ - docker push "$TAG"
+ after_script:
+ - docker logout
diff --git a/.gitlab-ci.d/containers.yml b/.gitlab-ci.d/containers.yml
index 7b7ca3790d..bd01ae8f80 100644
--- a/.gitlab-ci.d/containers.yml
+++ b/.gitlab-ci.d/containers.yml
@@ -1,24 +1,6 @@
-.container_job_template:
- image: docker:stable
- stage: containers
- services:
- - docker:dind
- before_script:
- - export TAG="$CI_REGISTRY_IMAGE/qemu/$NAME:latest"
- - export COMMON_TAG="$CI_REGISTRY/qemu-project/qemu/$NAME:latest"
- - apk add python3
- - docker info
- - docker login $CI_REGISTRY -u "$CI_REGISTRY_USER" -p "$CI_REGISTRY_PASSWORD"
- script:
- - echo "TAG:$TAG"
- - echo "COMMON_TAG:$COMMON_TAG"
- - ./tests/docker/docker.py --engine docker build
- -t "qemu/$NAME" -f "tests/docker/dockerfiles/$NAME.docker"
- -r $CI_REGISTRY/qemu-project/qemu
- - docker tag "qemu/$NAME" "$TAG"
- - docker push "$TAG"
- after_script:
- - docker logout
+include:
+ - local: '/.gitlab-ci.d/container-core.yml'
+ - local: '/.gitlab-ci.d/container-cross.yml'
amd64-alpine-container:
extends: .container_job_template
@@ -30,42 +12,11 @@ amd64-centos7-container:
variables:
NAME: centos7
-amd64-centos8-container:
- extends: .container_job_template
- variables:
- NAME: centos8
-
-amd64-debian10-container:
- extends: .container_job_template
- variables:
- NAME: debian10
-
amd64-debian11-container:
extends: .container_job_template
variables:
NAME: debian11
-alpha-debian-cross-container:
- extends: .container_job_template
- stage: containers-layer2
- needs: ['amd64-debian10-container']
- variables:
- NAME: debian-alpha-cross
-
-amd64-debian-cross-container:
- extends: .container_job_template
- stage: containers-layer2
- needs: ['amd64-debian10-container']
- variables:
- NAME: debian-amd64-cross
-
-amd64-debian-user-cross-container:
- extends: .container_job_template
- stage: containers-layer2
- needs: ['amd64-debian10-container']
- variables:
- NAME: debian-all-test-cross
-
amd64-debian-container:
extends: .container_job_template
stage: containers-layer2
@@ -73,183 +24,6 @@ amd64-debian-container:
variables:
NAME: debian-amd64
-arm64-debian-cross-container:
- extends: .container_job_template
- stage: containers-layer2
- needs: ['amd64-debian10-container']
- variables:
- NAME: debian-arm64-cross
-
-arm64-test-debian-cross-container:
- extends: .container_job_template
- stage: containers-layer2
- needs: ['amd64-debian11-container']
- variables:
- NAME: debian-arm64-test-cross
-
-armel-debian-cross-container:
- extends: .container_job_template
- stage: containers-layer2
- needs: ['amd64-debian10-container']
- variables:
- NAME: debian-armel-cross
-
-armhf-debian-cross-container:
- extends: .container_job_template
- stage: containers-layer2
- needs: ['amd64-debian10-container']
- variables:
- NAME: debian-armhf-cross
-
-# We never want to build hexagon in the CI system and by default we
-# always want to refer to the master registry where it lives.
-hexagon-cross-container:
- image: docker:stable
- stage: containers
- rules:
- - if: '$CI_PROJECT_NAMESPACE == "qemu-project"'
- when: never
- - when: always
- variables:
- NAME: debian-hexagon-cross
- GIT_DEPTH: 1
- services:
- - docker:dind
- before_script:
- - export TAG="$CI_REGISTRY_IMAGE/qemu/$NAME:latest"
- - export COMMON_TAG="$CI_REGISTRY/qemu-project/qemu/qemu/$NAME:latest"
- - docker info
- - docker login $CI_REGISTRY -u "$CI_REGISTRY_USER" -p "$CI_REGISTRY_PASSWORD"
- script:
- - echo "TAG:$TAG"
- - echo "COMMON_TAG:$COMMON_TAG"
- - docker pull $COMMON_TAG
- - docker tag $COMMON_TAG $TAG
- - docker push "$TAG"
- after_script:
- - docker logout
-
-hppa-debian-cross-container:
- extends: .container_job_template
- stage: containers-layer2
- needs: ['amd64-debian10-container']
- variables:
- NAME: debian-hppa-cross
-
-m68k-debian-cross-container:
- extends: .container_job_template
- stage: containers-layer2
- needs: ['amd64-debian10-container']
- variables:
- NAME: debian-m68k-cross
-
-mips64-debian-cross-container:
- extends: .container_job_template
- stage: containers-layer2
- needs: ['amd64-debian10-container']
- variables:
- NAME: debian-mips64-cross
-
-mips64el-debian-cross-container:
- extends: .container_job_template
- stage: containers-layer2
- needs: ['amd64-debian10-container']
- variables:
- NAME: debian-mips64el-cross
-
-mips-debian-cross-container:
- extends: .container_job_template
- stage: containers-layer2
- needs: ['amd64-debian10-container']
- variables:
- NAME: debian-mips-cross
-
-mipsel-debian-cross-container:
- extends: .container_job_template
- stage: containers-layer2
- needs: ['amd64-debian10-container']
- variables:
- NAME: debian-mipsel-cross
-
-powerpc-test-cross-container:
- extends: .container_job_template
- stage: containers-layer2
- needs: ['amd64-debian11-container']
- variables:
- NAME: debian-powerpc-test-cross
-
-ppc64el-debian-cross-container:
- extends: .container_job_template
- stage: containers-layer2
- needs: ['amd64-debian10-container']
- variables:
- NAME: debian-ppc64el-cross
-
-riscv64-debian-cross-container:
- extends: .container_job_template
- stage: containers-layer2
- needs: ['amd64-debian10-container']
- variables:
- NAME: debian-riscv64-cross
-
-s390x-debian-cross-container:
- extends: .container_job_template
- stage: containers-layer2
- needs: ['amd64-debian10-container']
- variables:
- NAME: debian-s390x-cross
-
-sh4-debian-cross-container:
- extends: .container_job_template
- stage: containers-layer2
- needs: ['amd64-debian10-container']
- variables:
- NAME: debian-sh4-cross
-
-sparc64-debian-cross-container:
- extends: .container_job_template
- stage: containers-layer2
- needs: ['amd64-debian10-container']
- variables:
- NAME: debian-sparc64-cross
-
-tricore-debian-cross-container:
- extends: .container_job_template
- stage: containers-layer2
- needs: ['amd64-debian10-container']
- variables:
- NAME: debian-tricore-cross
-
-xtensa-debian-cross-container:
- extends: .container_job_template
- variables:
- NAME: debian-xtensa-cross
-
-cris-fedora-cross-container:
- extends: .container_job_template
- variables:
- NAME: fedora-cris-cross
-
-amd64-fedora-container:
- extends: .container_job_template
- variables:
- NAME: fedora
-
-i386-fedora-cross-container:
- extends: .container_job_template
- variables:
- NAME: fedora-i386-cross
-
-win32-fedora-cross-container:
- extends: .container_job_template
- variables:
- NAME: fedora-win32-cross
-
-win64-fedora-cross-container:
- extends: .container_job_template
- variables:
- NAME: fedora-win64-cross
-
amd64-ubuntu1804-container:
extends: .container_job_template
variables:
diff --git a/.gitlab-ci.d/crossbuild-template.yml b/.gitlab-ci.d/crossbuild-template.yml
new file mode 100644
index 0000000000..1be541174c
--- /dev/null
+++ b/.gitlab-ci.d/crossbuild-template.yml
@@ -0,0 +1,41 @@
+.cross_system_build_job:
+ stage: build
+ image: $CI_REGISTRY_IMAGE/qemu/$IMAGE:latest
+ timeout: 80m
+ script:
+ - mkdir build
+ - cd build
+ - PKG_CONFIG_PATH=$PKG_CONFIG_PATH
+ ../configure --enable-werror --disable-docs $QEMU_CONFIGURE_OPTS
+ --disable-user --target-list-exclude="arm-softmmu cris-softmmu
+ i386-softmmu microblaze-softmmu mips-softmmu mipsel-softmmu
+ mips64-softmmu ppc-softmmu sh4-softmmu xtensa-softmmu"
+ - make -j$(expr $(nproc) + 1) all check-build $MAKE_CHECK_ARGS
+
+# Job to cross-build specific accelerators.
+#
+# Set the $ACCEL variable to select the specific accelerator (default to
+# KVM), and set extra options (such disabling other accelerators) via the
+# $EXTRA_CONFIGURE_OPTS variable.
+.cross_accel_build_job:
+ stage: build
+ image: $CI_REGISTRY_IMAGE/qemu/$IMAGE:latest
+ timeout: 30m
+ script:
+ - mkdir build
+ - cd build
+ - PKG_CONFIG_PATH=$PKG_CONFIG_PATH
+ ../configure --enable-werror --disable-docs $QEMU_CONFIGURE_OPTS
+ --disable-tools --enable-${ACCEL:-kvm} $EXTRA_CONFIGURE_OPTS
+ - make -j$(expr $(nproc) + 1) all check-build $MAKE_CHECK_ARGS
+
+.cross_user_build_job:
+ stage: build
+ image: $CI_REGISTRY_IMAGE/qemu/$IMAGE:latest
+ script:
+ - mkdir build
+ - cd build
+ - PKG_CONFIG_PATH=$PKG_CONFIG_PATH
+ ../configure --enable-werror --disable-docs $QEMU_CONFIGURE_OPTS
+ --disable-system
+ - make -j$(expr $(nproc) + 1) all check-build $MAKE_CHECK_ARGS
diff --git a/.gitlab-ci.d/crossbuilds.yml b/.gitlab-ci.d/crossbuilds.yml
index e44e4b49a2..6b3865c9e8 100644
--- a/.gitlab-ci.d/crossbuilds.yml
+++ b/.gitlab-ci.d/crossbuilds.yml
@@ -1,44 +1,5 @@
-.cross_system_build_job:
- stage: build
- image: $CI_REGISTRY_IMAGE/qemu/$IMAGE:latest
- timeout: 80m
- script:
- - mkdir build
- - cd build
- - PKG_CONFIG_PATH=$PKG_CONFIG_PATH
- ../configure --enable-werror --disable-docs $QEMU_CONFIGURE_OPTS
- --disable-user --target-list-exclude="arm-softmmu cris-softmmu
- i386-softmmu microblaze-softmmu mips-softmmu mipsel-softmmu
- mips64-softmmu ppc-softmmu sh4-softmmu xtensa-softmmu"
- - make -j$(expr $(nproc) + 1) all check-build $MAKE_CHECK_ARGS
-
-# Job to cross-build specific accelerators.
-#
-# Set the $ACCEL variable to select the specific accelerator (default to
-# KVM), and set extra options (such disabling other accelerators) via the
-# $ACCEL_CONFIGURE_OPTS variable.
-.cross_accel_build_job:
- stage: build
- image: $CI_REGISTRY_IMAGE/qemu/$IMAGE:latest
- timeout: 30m
- script:
- - mkdir build
- - cd build
- - PKG_CONFIG_PATH=$PKG_CONFIG_PATH
- ../configure --enable-werror --disable-docs $QEMU_CONFIGURE_OPTS
- --disable-tools --enable-${ACCEL:-kvm} $ACCEL_CONFIGURE_OPTS
- - make -j$(expr $(nproc) + 1) all check-build
-
-.cross_user_build_job:
- stage: build
- image: $CI_REGISTRY_IMAGE/qemu/$IMAGE:latest
- script:
- - mkdir build
- - cd build
- - PKG_CONFIG_PATH=$PKG_CONFIG_PATH
- ../configure --enable-werror --disable-docs $QEMU_CONFIGURE_OPTS
- --disable-system
- - make -j$(expr $(nproc) + 1) all check-build $MAKE_CHECK_ARGS
+include:
+ - local: '/.gitlab-ci.d/crossbuild-template.yml'
cross-armel-system:
extends: .cross_system_build_job
@@ -98,6 +59,15 @@ cross-i386-user:
IMAGE: fedora-i386-cross
MAKE_CHECK_ARGS: check
+cross-i386-tci:
+ extends: .cross_accel_build_job
+ timeout: 60m
+ variables:
+ IMAGE: fedora-i386-cross
+ ACCEL: tcg-interpreter
+ EXTRA_CONFIGURE_OPTS: --target-list=i386-softmmu,i386-linux-user,aarch64-softmmu,aarch64-linux-user,ppc-softmmu,ppc-linux-user
+ MAKE_CHECK_ARGS: check check-tcg
+
cross-mips-system:
extends: .cross_system_build_job
needs:
@@ -174,7 +144,7 @@ cross-s390x-kvm-only:
job: s390x-debian-cross-container
variables:
IMAGE: debian-s390x-cross
- ACCEL_CONFIGURE_OPTS: --disable-tcg
+ EXTRA_CONFIGURE_OPTS: --disable-tcg
cross-mips64el-kvm-only:
extends: .cross_accel_build_job
@@ -182,7 +152,7 @@ cross-mips64el-kvm-only:
job: mips64el-debian-cross-container
variables:
IMAGE: debian-mips64el-cross
- ACCEL_CONFIGURE_OPTS: --disable-tcg --target-list=mips64el-softmmu
+ EXTRA_CONFIGURE_OPTS: --disable-tcg --target-list=mips64el-softmmu
cross-win32-system:
extends: .cross_system_build_job
@@ -205,7 +175,7 @@ cross-amd64-xen-only:
variables:
IMAGE: debian-amd64-cross
ACCEL: xen
- ACCEL_CONFIGURE_OPTS: --disable-tcg --disable-kvm
+ EXTRA_CONFIGURE_OPTS: --disable-tcg --disable-kvm
cross-arm64-xen-only:
extends: .cross_accel_build_job
@@ -214,4 +184,4 @@ cross-arm64-xen-only:
variables:
IMAGE: debian-arm64-cross
ACCEL: xen
- ACCEL_CONFIGURE_OPTS: --disable-tcg --disable-kvm
+ EXTRA_CONFIGURE_OPTS: --disable-tcg --disable-kvm
diff --git a/.gitlab-ci.d/qemu-project.yml b/.gitlab-ci.d/qemu-project.yml
new file mode 100644
index 0000000000..64cb2ba1da
--- /dev/null
+++ b/.gitlab-ci.d/qemu-project.yml
@@ -0,0 +1,11 @@
+# This file contains the set of jobs run by the QEMU project:
+# https://gitlab.com/qemu-project/qemu/-/pipelines
+
+include:
+ - local: '/.gitlab-ci.d/stages.yml'
+ - local: '/.gitlab-ci.d/edk2.yml'
+ - local: '/.gitlab-ci.d/opensbi.yml'
+ - local: '/.gitlab-ci.d/containers.yml'
+ - local: '/.gitlab-ci.d/crossbuilds.yml'
+ - local: '/.gitlab-ci.d/buildtest.yml'
+ - local: '/.gitlab-ci.d/static_checks.yml'
diff --git a/.gitlab-ci.d/stages.yml b/.gitlab-ci.d/stages.yml
new file mode 100644
index 0000000000..f50826018d
--- /dev/null
+++ b/.gitlab-ci.d/stages.yml
@@ -0,0 +1,8 @@
+# Currently we have two build stages after our containers are built:
+# - build (for traditional build and test or first stage build)
+# - test (for test stages, using build artefacts from a build stage)
+stages:
+ - containers
+ - containers-layer2
+ - build
+ - test
diff --git a/.gitlab-ci.d/static_checks.yml b/.gitlab-ci.d/static_checks.yml
new file mode 100644
index 0000000000..91247a6f67
--- /dev/null
+++ b/.gitlab-ci.d/static_checks.yml
@@ -0,0 +1,26 @@
+check-patch:
+ stage: build
+ image: $CI_REGISTRY_IMAGE/qemu/centos8:latest
+ needs:
+ job: amd64-centos8-container
+ script: .gitlab-ci.d/check-patch.py
+ variables:
+ GIT_DEPTH: 1000
+ rules:
+ - if: '$CI_PROJECT_NAMESPACE == "qemu-project" && $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH'
+ when: never
+ - when: on_success
+ allow_failure: true
+
+check-dco:
+ stage: build
+ image: $CI_REGISTRY_IMAGE/qemu/centos8:latest
+ needs:
+ job: amd64-centos8-container
+ script: .gitlab-ci.d/check-dco.py
+ variables:
+ GIT_DEPTH: 1000
+ rules:
+ - if: '$CI_PROJECT_NAMESPACE == "qemu-project" && $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH'
+ when: never
+ - when: on_success
diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index 6a0d311cf4..6dc5385e69 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -1,854 +1,39 @@
-# Currently we have two build stages after our containers are built:
-# - build (for traditional build and test or first stage build)
-# - test (for test stages, using build artefacts from a build stage)
-stages:
- - containers
- - containers-layer2
- - build
- - test
-
-include:
- - local: '/.gitlab-ci.d/edk2.yml'
- - local: '/.gitlab-ci.d/opensbi.yml'
- - local: '/.gitlab-ci.d/containers.yml'
- - local: '/.gitlab-ci.d/crossbuilds.yml'
-
-.native_build_job_template:
- stage: build
- image: $CI_REGISTRY_IMAGE/qemu/$IMAGE:latest
- before_script:
- - JOBS=$(expr $(nproc) + 1)
- script:
- - if test -n "$LD_JOBS";
- then
- scripts/git-submodule.sh update meson ;
- fi
- - mkdir build
- - cd build
- - if test -n "$TARGETS";
- then
- ../configure --enable-werror --disable-docs ${LD_JOBS:+--meson=internal} $CONFIGURE_ARGS --target-list="$TARGETS" ;
- else
- ../configure --enable-werror --disable-docs ${LD_JOBS:+--meson=internal} $CONFIGURE_ARGS ;
- fi || { cat config.log meson-logs/meson-log.txt && exit 1; }
- - if test -n "$LD_JOBS";
- then
- ../meson/meson.py configure . -Dbackend_max_links="$LD_JOBS" ;
- fi || exit 1;
- - make -j"$JOBS"
- - if test -n "$MAKE_CHECK_ARGS";
- then
- make -j"$JOBS" $MAKE_CHECK_ARGS ;
- fi
-
-.native_test_job_template:
- stage: test
- image: $CI_REGISTRY_IMAGE/qemu/$IMAGE:latest
- script:
- - scripts/git-submodule.sh update
- $(sed -n '/GIT_SUBMODULES=/ s/.*=// p' build/config-host.mak)
- - cd build
- - find . -type f -exec touch {} +
- # Avoid recompiling by hiding ninja with NINJA=":"
- - make NINJA=":" $MAKE_CHECK_ARGS
-
-.acceptance_template: &acceptance_definition
- cache:
- key: "${CI_JOB_NAME}-cache"
- paths:
- - ${CI_PROJECT_DIR}/avocado-cache
- policy: pull-push
- artifacts:
- name: "$CI_JOB_NAME-$CI_COMMIT_REF_SLUG"
- when: always
- expire_in: 2 days
- paths:
- - build/tests/results/latest/results.xml
- - build/tests/results/latest/test-results
- reports:
- junit: build/tests/results/latest/results.xml
- before_script:
- - mkdir -p ~/.config/avocado
- - echo "[datadir.paths]" > ~/.config/avocado/avocado.conf
- - echo "cache_dirs = ['${CI_PROJECT_DIR}/avocado-cache']"
- >> ~/.config/avocado/avocado.conf
- - echo -e '[job.output.testlogs]\nstatuses = ["FAIL", "INTERRUPT"]'
- >> ~/.config/avocado/avocado.conf
- - if [ -d ${CI_PROJECT_DIR}/avocado-cache ]; then
- du -chs ${CI_PROJECT_DIR}/avocado-cache ;
- fi
- - export AVOCADO_ALLOW_UNTRUSTED_CODE=1
- after_script:
- - cd build
- - du -chs ${CI_PROJECT_DIR}/avocado-cache
-
-build-system-alpine:
- extends: .native_build_job_template
- needs:
- - job: amd64-alpine-container
- variables:
- IMAGE: alpine
- TARGETS: aarch64-softmmu alpha-softmmu cris-softmmu hppa-softmmu
- microblazeel-softmmu mips64el-softmmu
- MAKE_CHECK_ARGS: check-build
- CONFIGURE_ARGS: --enable-docs --enable-trace-backends=log,simple,syslog
- artifacts:
- expire_in: 2 days
- paths:
- - .git-submodule-status
- - build
-
-check-system-alpine:
- extends: .native_test_job_template
- needs:
- - job: build-system-alpine
- artifacts: true
- variables:
- IMAGE: alpine
- MAKE_CHECK_ARGS: check
-
-acceptance-system-alpine:
- extends: .native_test_job_template
- needs:
- - job: build-system-alpine
- artifacts: true
- variables:
- IMAGE: alpine
- MAKE_CHECK_ARGS: check-acceptance
- <<: *acceptance_definition
-
-build-system-ubuntu:
- extends: .native_build_job_template
- needs:
- job: amd64-ubuntu2004-container
- variables:
- IMAGE: ubuntu2004
- CONFIGURE_ARGS: --enable-docs --enable-fdt=system --enable-slirp=system
- TARGETS: aarch64-softmmu alpha-softmmu cris-softmmu hppa-softmmu
- microblazeel-softmmu mips64el-softmmu
- MAKE_CHECK_ARGS: check-build
- artifacts:
- expire_in: 2 days
- paths:
- - build
-
-check-system-ubuntu:
- extends: .native_test_job_template
- needs:
- - job: build-system-ubuntu
- artifacts: true
- variables:
- IMAGE: ubuntu2004
- MAKE_CHECK_ARGS: check
-
-acceptance-system-ubuntu:
- extends: .native_test_job_template
- needs:
- - job: build-system-ubuntu
- artifacts: true
- variables:
- IMAGE: ubuntu2004
- MAKE_CHECK_ARGS: check-acceptance
- <<: *acceptance_definition
-
-build-system-debian:
- extends: .native_build_job_template
- needs:
- job: amd64-debian-container
- variables:
- IMAGE: debian-amd64
- CONFIGURE_ARGS: --enable-fdt=system
- TARGETS: arm-softmmu avr-softmmu i386-softmmu mipsel-softmmu
- riscv64-softmmu sh4eb-softmmu sparc-softmmu xtensaeb-softmmu
- MAKE_CHECK_ARGS: check-build
- artifacts:
- expire_in: 2 days
- paths:
- - build
-
-check-system-debian:
- extends: .native_test_job_template
- needs:
- - job: build-system-debian
- artifacts: true
- variables:
- IMAGE: debian-amd64
- MAKE_CHECK_ARGS: check
-
-acceptance-system-debian:
- extends: .native_test_job_template
- needs:
- - job: build-system-debian
- artifacts: true
- variables:
- IMAGE: debian-amd64
- MAKE_CHECK_ARGS: check-acceptance
- <<: *acceptance_definition
-
-build-system-fedora:
- extends: .native_build_job_template
- needs:
- job: amd64-fedora-container
- variables:
- IMAGE: fedora
- CONFIGURE_ARGS: --disable-gcrypt --enable-nettle --enable-docs
- --enable-fdt=system --enable-slirp=system --enable-capstone=system
- TARGETS: tricore-softmmu microblaze-softmmu mips-softmmu
- xtensa-softmmu m68k-softmmu riscv32-softmmu ppc-softmmu sparc64-softmmu
- MAKE_CHECK_ARGS: check-build
- artifacts:
- expire_in: 2 days
- paths:
- - build
-
-check-system-fedora:
- extends: .native_test_job_template
- needs:
- - job: build-system-fedora
- artifacts: true
- variables:
- IMAGE: fedora
- MAKE_CHECK_ARGS: check
-
-acceptance-system-fedora:
- extends: .native_test_job_template
- needs:
- - job: build-system-fedora
- artifacts: true
- variables:
- IMAGE: fedora
- MAKE_CHECK_ARGS: check-acceptance
- <<: *acceptance_definition
-
-build-system-centos:
- extends: .native_build_job_template
- needs:
- job: amd64-centos8-container
- variables:
- IMAGE: centos8
- CONFIGURE_ARGS: --disable-nettle --enable-gcrypt --enable-fdt=system
- --enable-modules --enable-trace-backends=dtrace
- TARGETS: ppc64-softmmu or1k-softmmu s390x-softmmu
- x86_64-softmmu rx-softmmu sh4-softmmu nios2-softmmu
- MAKE_CHECK_ARGS: check-build
- artifacts:
- expire_in: 2 days
- paths:
- - build
-
-check-system-centos:
- extends: .native_test_job_template
- needs:
- - job: build-system-centos
- artifacts: true
- variables:
- IMAGE: centos8
- MAKE_CHECK_ARGS: check
-
-acceptance-system-centos:
- extends: .native_test_job_template
- needs:
- - job: build-system-centos
- artifacts: true
- variables:
- IMAGE: centos8
- MAKE_CHECK_ARGS: check-acceptance
- <<: *acceptance_definition
-
-build-system-opensuse:
- extends: .native_build_job_template
- needs:
- job: amd64-opensuse-leap-container
- variables:
- IMAGE: opensuse-leap
- CONFIGURE_ARGS: --enable-fdt=system
- TARGETS: s390x-softmmu x86_64-softmmu aarch64-softmmu
- MAKE_CHECK_ARGS: check-build
- artifacts:
- expire_in: 2 days
- paths:
- - build
-
-check-system-opensuse:
- extends: .native_test_job_template
- needs:
- - job: build-system-opensuse
- artifacts: true
- variables:
- IMAGE: opensuse-leap
- MAKE_CHECK_ARGS: check
-
-acceptance-system-opensuse:
- extends: .native_test_job_template
- needs:
- - job: build-system-opensuse
- artifacts: true
- variables:
- IMAGE: opensuse-leap
- MAKE_CHECK_ARGS: check-acceptance
- <<: *acceptance_definition
-
-
-build-disabled:
- extends: .native_build_job_template
- needs:
- job: amd64-fedora-container
- variables:
- IMAGE: fedora
- CONFIGURE_ARGS:
- --disable-attr
- --disable-auth-pam
- --disable-avx2
- --disable-bochs
- --disable-brlapi
- --disable-bzip2
- --disable-cap-ng
- --disable-capstone
- --disable-cloop
- --disable-coroutine-pool
- --disable-curl
- --disable-curses
- --disable-dmg
- --disable-docs
- --disable-gcrypt
- --disable-glusterfs
- --disable-gnutls
- --disable-gtk
- --disable-guest-agent
- --disable-iconv
- --disable-keyring
- --disable-kvm
- --disable-libiscsi
- --disable-libpmem
- --disable-libssh
- --disable-libudev
- --disable-libusb
- --disable-libxml2
- --disable-linux-aio
- --disable-live-block-migration
- --disable-lzo
- --disable-malloc-trim
- --disable-mpath
- --disable-nettle
- --disable-numa
- --disable-opengl
- --disable-parallels
- --disable-pie
- --disable-qcow1
- --disable-qed
- --disable-qom-cast-debug
- --disable-rbd
- --disable-rdma
- --disable-replication
- --disable-sdl
- --disable-seccomp
- --disable-slirp
- --disable-smartcard
- --disable-snappy
- --disable-sparse
- --disable-spice
- --disable-strip
- --disable-tpm
- --disable-usb-redir
- --disable-vdi
- --disable-vhost-crypto
- --disable-vhost-net
- --disable-vhost-scsi
- --disable-vhost-kernel
- --disable-vhost-user
- --disable-vhost-vdpa
- --disable-vhost-vsock
- --disable-virglrenderer
- --disable-vnc
- --disable-vte
- --disable-vvfat
- --disable-xen
- --disable-zstd
- TARGETS: arm-softmmu i386-softmmu ppc64-softmmu mips64-softmmu
- s390x-softmmu i386-linux-user
- MAKE_CHECK_ARGS: check-qtest SPEED=slow
-
-# This jobs explicitly disable TCG (--disable-tcg), KVM is detected by
-# the configure script. The container doesn't contain Xen headers so
-# Xen accelerator is not detected / selected. As result it build the
-# i386-softmmu and x86_64-softmmu with KVM being the single accelerator
-# available.
-# Also use a different coroutine implementation (which is only really of
-# interest to KVM users, i.e. with TCG disabled)
-build-tcg-disabled:
- extends: .native_build_job_template
- needs:
- job: amd64-centos8-container
- variables:
- IMAGE: centos8
- script:
- - mkdir build
- - cd build
- - ../configure --disable-tcg --audio-drv-list="" --with-coroutine=ucontext
- || { cat config.log meson-logs/meson-log.txt && exit 1; }
- - make -j"$JOBS"
- - make check-unit
- - make check-qapi-schema
- - cd tests/qemu-iotests/
- - ./check -raw 001 002 003 004 005 008 009 010 011 012 021 025 032 033 048
- 052 063 077 086 101 104 106 113 148 150 151 152 157 159 160 163
- 170 171 183 184 192 194 197 208 215 221 222 226 227 236 253 277
- - ./check -qcow2 028 051 056 057 058 065 068 082 085 091 095 096 102 122
- 124 132 139 142 144 145 151 152 155 157 165 194 196 197 200 202
- 208 209 215 216 218 222 227 234 246 247 248 250 254 255 257 258
- 260 261 262 263 264 270 272 273 277 279
-
-build-user:
- extends: .native_build_job_template
- needs:
- job: amd64-debian-user-cross-container
- variables:
- IMAGE: debian-all-test-cross
- CONFIGURE_ARGS: --disable-tools --disable-system
- MAKE_CHECK_ARGS: check-tcg
-
-build-user-static:
- extends: .native_build_job_template
- needs:
- job: amd64-debian-user-cross-container
- variables:
- IMAGE: debian-all-test-cross
- CONFIGURE_ARGS: --disable-tools --disable-system --static
- MAKE_CHECK_ARGS: check-tcg
-
-# Because the hexagon cross-compiler takes so long to build we don't rely
-# on the CI system to build it and hence this job has an optional dependency
-# declared. The image is manually uploaded.
-build-user-hexagon:
- extends: .native_build_job_template
- needs:
- job: hexagon-cross-container
- optional: true
- variables:
- IMAGE: debian-hexagon-cross
- TARGETS: hexagon-linux-user
- CONFIGURE_ARGS: --disable-tools --disable-docs --enable-debug-tcg
- MAKE_CHECK_ARGS: check-tcg
-
-# Only build the softmmu targets we have check-tcg tests for
-build-some-softmmu:
- extends: .native_build_job_template
- needs:
- job: amd64-debian-user-cross-container
- variables:
- IMAGE: debian-all-test-cross
- CONFIGURE_ARGS: --disable-tools --enable-debug
- TARGETS: xtensa-softmmu arm-softmmu aarch64-softmmu alpha-softmmu
- MAKE_CHECK_ARGS: check-tcg
-
-# Run check-tcg against linux-user (with plugins)
-# we skip sparc64-linux-user until it has been fixed somewhat
-# we skip cris-linux-user as it doesn't use the common run loop
-build-user-plugins:
- extends: .native_build_job_template
- needs:
- job: amd64-debian-user-cross-container
- variables:
- IMAGE: debian-all-test-cross
- CONFIGURE_ARGS: --disable-tools --disable-system --enable-plugins --enable-debug-tcg --target-list-exclude=sparc64-linux-user,cris-linux-user
- MAKE_CHECK_ARGS: check-tcg
- timeout: 1h 30m
-
-build-user-centos7:
- extends: .native_build_job_template
- needs:
- job: amd64-centos7-container
- variables:
- IMAGE: centos7
- CONFIGURE_ARGS: --disable-system --disable-tools --disable-docs
- MAKE_CHECK_ARGS: check-tcg
-
-build-some-softmmu-plugins:
- extends: .native_build_job_template
- needs:
- job: amd64-debian-user-cross-container
- variables:
- IMAGE: debian-all-test-cross
- CONFIGURE_ARGS: --disable-tools --disable-user --enable-plugins --enable-debug-tcg
- TARGETS: xtensa-softmmu arm-softmmu aarch64-softmmu alpha-softmmu
- MAKE_CHECK_ARGS: check-tcg
-
-clang-system:
- extends: .native_build_job_template
- needs:
- job: amd64-fedora-container
- variables:
- IMAGE: fedora
- CONFIGURE_ARGS: --cc=clang --cxx=clang++
- --extra-cflags=-fsanitize=undefined --extra-cflags=-fno-sanitize-recover=undefined
- TARGETS: alpha-softmmu arm-softmmu m68k-softmmu mips64-softmmu
- ppc-softmmu s390x-softmmu
- MAKE_CHECK_ARGS: check-qtest check-tcg
-
-clang-user:
- extends: .native_build_job_template
- needs:
- job: amd64-debian-user-cross-container
- variables:
- IMAGE: debian-all-test-cross
- CONFIGURE_ARGS: --cc=clang --cxx=clang++ --disable-system
- --target-list-exclude=microblazeel-linux-user,aarch64_be-linux-user,i386-linux-user,m68k-linux-user,mipsn32el-linux-user,xtensaeb-linux-user
- --extra-cflags=-fsanitize=undefined --extra-cflags=-fno-sanitize-recover=undefined
- MAKE_CHECK_ARGS: check-unit check-tcg
-
-# Set LD_JOBS=1 because this requires LTO and ld consumes a large amount of memory.
-# On gitlab runners, default value sometimes end up calling 2 lds concurrently and
-# triggers an Out-Of-Memory error
#
-# Since slirp callbacks are used in QEMU Timers, slirp needs to be compiled together
-# with QEMU and linked as a static library to avoid false positives in CFI checks.
-# This can be accomplished by using -enable-slirp=git, which avoids the use of
-# a system-wide version of the library
+# This is the GitLab CI configuration file for the mainstream QEMU
+# project: https://gitlab.com/qemu-project/qemu/-/pipelines
#
-# Split in three sets of build/check/acceptance to limit the execution time of each
-# job
-build-cfi-aarch64:
- extends: .native_build_job_template
- needs:
- - job: amd64-fedora-container
- variables:
- LD_JOBS: 1
- AR: llvm-ar
- IMAGE: fedora
- CONFIGURE_ARGS: --cc=clang --cxx=clang++ --enable-cfi --enable-cfi-debug
- --enable-safe-stack --enable-slirp=git
- TARGETS: aarch64-softmmu
- MAKE_CHECK_ARGS: check-build
- timeout: 70m
- artifacts:
- expire_in: 2 days
- paths:
- - build
-
-check-cfi-aarch64:
- extends: .native_test_job_template
- needs:
- - job: build-cfi-aarch64
- artifacts: true
- variables:
- IMAGE: fedora
- MAKE_CHECK_ARGS: check
-
-acceptance-cfi-aarch64:
- extends: .native_test_job_template
- needs:
- - job: build-cfi-aarch64
- artifacts: true
- variables:
- IMAGE: fedora
- MAKE_CHECK_ARGS: check-acceptance
- <<: *acceptance_definition
-
-build-cfi-ppc64-s390x:
- extends: .native_build_job_template
- needs:
- - job: amd64-fedora-container
- variables:
- LD_JOBS: 1
- AR: llvm-ar
- IMAGE: fedora
- CONFIGURE_ARGS: --cc=clang --cxx=clang++ --enable-cfi --enable-cfi-debug
- --enable-safe-stack --enable-slirp=git
- TARGETS: ppc64-softmmu s390x-softmmu
- MAKE_CHECK_ARGS: check-build
- timeout: 70m
- artifacts:
- expire_in: 2 days
- paths:
- - build
-
-check-cfi-ppc64-s390x:
- extends: .native_test_job_template
- needs:
- - job: build-cfi-ppc64-s390x
- artifacts: true
- variables:
- IMAGE: fedora
- MAKE_CHECK_ARGS: check
-
-acceptance-cfi-ppc64-s390x:
- extends: .native_test_job_template
- needs:
- - job: build-cfi-ppc64-s390x
- artifacts: true
- variables:
- IMAGE: fedora
- MAKE_CHECK_ARGS: check-acceptance
- <<: *acceptance_definition
-
-build-cfi-x86_64:
- extends: .native_build_job_template
- needs:
- - job: amd64-fedora-container
- variables:
- LD_JOBS: 1
- AR: llvm-ar
- IMAGE: fedora
- CONFIGURE_ARGS: --cc=clang --cxx=clang++ --enable-cfi --enable-cfi-debug
- --enable-safe-stack --enable-slirp=git
- TARGETS: x86_64-softmmu
- MAKE_CHECK_ARGS: check-build
- timeout: 70m
- artifacts:
- expire_in: 2 days
- paths:
- - build
-
-check-cfi-x86_64:
- extends: .native_test_job_template
- needs:
- - job: build-cfi-x86_64
- artifacts: true
- variables:
- IMAGE: fedora
- MAKE_CHECK_ARGS: check
-
-acceptance-cfi-x86_64:
- extends: .native_test_job_template
- needs:
- - job: build-cfi-x86_64
- artifacts: true
- variables:
- IMAGE: fedora
- MAKE_CHECK_ARGS: check-acceptance
- <<: *acceptance_definition
-
-tsan-build:
- extends: .native_build_job_template
- needs:
- job: amd64-ubuntu2004-container
- variables:
- IMAGE: ubuntu2004
- CONFIGURE_ARGS: --enable-tsan --cc=clang-10 --cxx=clang++-10
- --enable-trace-backends=ust --enable-fdt=system --enable-slirp=system
- TARGETS: x86_64-softmmu ppc64-softmmu riscv64-softmmu x86_64-linux-user
- MAKE_CHECK_ARGS: bench V=1
-
-# These targets are on the way out
-build-deprecated:
- extends: .native_build_job_template
- needs:
- job: amd64-debian-user-cross-container
- variables:
- IMAGE: debian-all-test-cross
- CONFIGURE_ARGS: --disable-tools
- MAKE_CHECK_ARGS: build-tcg
- TARGETS: ppc64abi32-linux-user
- artifacts:
- expire_in: 2 days
- paths:
- - build
-
-# We split the check-tcg step as test failures are expected but we still
-# want to catch the build breaking.
-check-deprecated:
- extends: .native_test_job_template
- needs:
- - job: build-deprecated
- artifacts: true
- variables:
- IMAGE: debian-all-test-cross
- MAKE_CHECK_ARGS: check-tcg
- allow_failure: true
-
-# gprof/gcov are GCC features
-gprof-gcov:
- extends: .native_build_job_template
- needs:
- job: amd64-ubuntu2004-container
- variables:
- IMAGE: ubuntu2004
- CONFIGURE_ARGS: --enable-gprof --enable-gcov
- MAKE_CHECK_ARGS: check
- TARGETS: aarch64-softmmu ppc64-softmmu s390x-softmmu x86_64-softmmu
- timeout: 70m
- after_script:
- - ${CI_PROJECT_DIR}/scripts/ci/coverage-summary.sh
-
-build-oss-fuzz:
- extends: .native_build_job_template
- needs:
- job: amd64-fedora-container
- variables:
- IMAGE: fedora
- script:
- - mkdir build-oss-fuzz
- - CC="clang" CXX="clang++" CFLAGS="-fsanitize=address"
- ./scripts/oss-fuzz/build.sh
- - export ASAN_OPTIONS="fast_unwind_on_malloc=0"
- - for fuzzer in $(find ./build-oss-fuzz/DEST_DIR/ -executable -type f
- | grep -v slirp); do
- grep "LLVMFuzzerTestOneInput" ${fuzzer} > /dev/null 2>&1 || continue ;
- echo Testing ${fuzzer} ... ;
- "${fuzzer}" -runs=1 -seed=1 || exit 1 ;
- done
- # Unrelated to fuzzer: run some tests with -fsanitize=address
- - cd build-oss-fuzz && make check-qtest-i386 check-unit
-
-build-tci:
- extends: .native_build_job_template
- needs:
- job: amd64-debian-user-cross-container
- variables:
- IMAGE: debian-all-test-cross
- script:
- - TARGETS="aarch64 alpha arm hppa m68k microblaze ppc64 s390x x86_64"
- - mkdir build
- - cd build
- - ../configure --enable-tcg-interpreter
- --target-list="$(for tg in $TARGETS; do echo -n ${tg}'-softmmu '; done)" || { cat config.log meson-logs/meson-log.txt && exit 1; }
- - make -j"$JOBS"
- - make tests/qtest/boot-serial-test tests/qtest/cdrom-test tests/qtest/pxe-test
- - for tg in $TARGETS ; do
- export QTEST_QEMU_BINARY="./qemu-system-${tg}" ;
- ./tests/qtest/boot-serial-test || exit 1 ;
- ./tests/qtest/cdrom-test || exit 1 ;
- done
- - QTEST_QEMU_BINARY="./qemu-system-x86_64" ./tests/qtest/pxe-test
- - QTEST_QEMU_BINARY="./qemu-system-s390x" ./tests/qtest/pxe-test -m slow
- - make check-tcg
-
-# Alternate coroutines implementations are only really of interest to KVM users
-# However we can't test against KVM on Gitlab-CI so we can only run unit tests
-build-coroutine-sigaltstack:
- extends: .native_build_job_template
- needs:
- job: amd64-ubuntu2004-container
- variables:
- IMAGE: ubuntu2004
- CONFIGURE_ARGS: --with-coroutine=sigaltstack --disable-tcg
- --enable-trace-backends=ftrace
- MAKE_CHECK_ARGS: check-unit
-
-# Most jobs test latest gcrypt or nettle builds
+# !!! DO NOT ADD ANY NEW CONFIGURATION TO THIS FILE !!!
#
-# These jobs test old gcrypt and nettle from RHEL7
-# which had some API differences.
-crypto-old-nettle:
- extends: .native_build_job_template
- needs:
- job: amd64-centos7-container
- variables:
- IMAGE: centos7
- TARGETS: x86_64-softmmu x86_64-linux-user
- CONFIGURE_ARGS: --disable-gcrypt --enable-nettle
- MAKE_CHECK_ARGS: check
-
-crypto-old-gcrypt:
- extends: .native_build_job_template
- needs:
- job: amd64-centos7-container
- variables:
- IMAGE: centos7
- TARGETS: x86_64-softmmu x86_64-linux-user
- CONFIGURE_ARGS: --disable-nettle --enable-gcrypt
- MAKE_CHECK_ARGS: check
-
-crypto-only-gnutls:
- extends: .native_build_job_template
- needs:
- job: amd64-centos7-container
- variables:
- IMAGE: centos7
- TARGETS: x86_64-softmmu x86_64-linux-user
- CONFIGURE_ARGS: --disable-nettle --disable-gcrypt --enable-gnutls
- MAKE_CHECK_ARGS: check
-
-
-# Check our reduced build configurations
-build-without-default-devices:
- extends: .native_build_job_template
- needs:
- job: amd64-centos8-container
- variables:
- IMAGE: centos8
- CONFIGURE_ARGS: --without-default-devices --disable-user
-
-build-without-default-features:
- extends: .native_build_job_template
- needs:
- job: amd64-debian-container
- variables:
- IMAGE: debian-amd64
- CONFIGURE_ARGS: --without-default-features --disable-user
- --target-list-exclude=arm-softmmu,i386-softmmu,mipsel-softmmu,mips64-softmmu,ppc-softmmu
- MAKE_CHECK_ARGS: check-unit
-
-check-patch:
- stage: build
- image: $CI_REGISTRY_IMAGE/qemu/centos8:latest
- needs:
- job: amd64-centos8-container
- script: .gitlab-ci.d/check-patch.py
- except:
- variables:
- - $CI_PROJECT_NAMESPACE == 'qemu-project' && $CI_COMMIT_BRANCH == 'master'
- variables:
- GIT_DEPTH: 1000
- allow_failure: true
-
-check-dco:
- stage: build
- image: $CI_REGISTRY_IMAGE/qemu/centos8:latest
- needs:
- job: amd64-centos8-container
- script: .gitlab-ci.d/check-dco.py
- except:
- variables:
- - $CI_PROJECT_NAMESPACE == 'qemu-project' && $CI_COMMIT_BRANCH == 'master'
- variables:
- GIT_DEPTH: 1000
-
-build-libvhost-user:
- stage: build
- image: $CI_REGISTRY_IMAGE/qemu/fedora:latest
- needs:
- job: amd64-fedora-container
- before_script:
- - dnf install -y meson ninja-build
- script:
- - mkdir subprojects/libvhost-user/build
- - cd subprojects/libvhost-user/build
- - meson
- - ninja
-
-# No targets are built here, just tools, docs, and unit tests. This
-# also feeds into the eventual documentation deployment steps later
-build-tools-and-docs-debian:
- extends: .native_build_job_template
- needs:
- job: amd64-debian-container
- variables:
- IMAGE: debian-amd64
- MAKE_CHECK_ARGS: check-unit check-softfloat ctags TAGS cscope
- CONFIGURE_ARGS: --disable-system --disable-user --enable-docs --enable-tools
- artifacts:
- expire_in: 2 days
- paths:
- - build
+# Only documentation or comments is accepted.
+#
+# To use a different set of jobs than the mainstream QEMU project,
+# you need to set the location of your custom yml file at "custom CI/CD
+# configuration path", on your GitLab CI namespace:
+# https://docs.gitlab.com/ee/ci/pipelines/settings.html#custom-cicd-configuration-path
+#
+# ----------------------------------------------------------------------
+#
+# QEMU CI jobs are based on templates. Some templates provide
+# user-configurable options, modifiable via configuration variables.
+#
+# These variables can be set globally in the user's CI namespace
+# setting:
+# https://docs.gitlab.com/ee/ci/variables/#create-a-custom-variable-in-the-ui
+# or set manually each time a branch/tag is pushed, as a git-push
+# command line argument:
+# https://docs.gitlab.com/ee/user/project/push_options.html#push-options-for-gitlab-cicd
+#
+# Example setting the QEMU_CI_EXAMPLE_VAR variable:
+#
+# git push -o ci.variable="QEMU_CI_EXAMPLE_VAR=value" myrepo mybranch
+#
+# ----------------------------------------------------------------------
+#
+# List of environment variables that can be use to modify the set
+# of jobs selected:
+#
+# - QEMU_CI_AVOCADO_TESTING
+# If set, tests using the Avocado framework will be run
-# Prepare for GitLab pages deployment. Anything copied into the
-# "public" directory will be deployed to $USER.gitlab.io/$PROJECT
-pages:
- image: $CI_REGISTRY_IMAGE/qemu/debian-amd64:latest
- stage: test
- needs:
- - job: build-tools-and-docs-debian
- script:
- - mkdir -p public
- # HTML-ised source tree
- - make gtags
- - htags -anT --tree-view=filetree -m qemu_init
- -t "Welcome to the QEMU sourcecode"
- - mv HTML public/src
- # Project documentation
- - make -C build install DESTDIR=$(pwd)/temp-install
- - mv temp-install/usr/local/share/doc/qemu/* public/
- artifacts:
- paths:
- - public
+include:
+ - local: '/.gitlab-ci.d/qemu-project.yml'
diff --git a/MAINTAINERS b/MAINTAINERS
index a77f246569..5f55404f2f 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -128,7 +128,6 @@ F: docs/devel/decodetree.rst
F: include/exec/cpu*.h
F: include/exec/exec-all.h
F: include/exec/helper*.h
-F: include/exec/tb-hash.h
F: include/sysemu/cpus.h
F: include/sysemu/tcg.h
F: include/hw/core/tcg-cpu-ops.h
diff --git a/Makefile b/Makefile
index 4cab10a2a4..30f19d33bb 100644
--- a/Makefile
+++ b/Makefile
@@ -48,9 +48,11 @@ Makefile: .git-submodule-status
.PHONY: git-submodule-update
git-submodule-update:
+ifneq ($(GIT_SUBMODULES_ACTION),ignore)
$(call quiet-command, \
(GIT="$(GIT)" "$(SRC_PATH)/scripts/git-submodule.sh" $(GIT_SUBMODULES_ACTION) $(GIT_SUBMODULES)), \
"GIT","$(GIT_SUBMODULES)")
+endif
# 0. ensure the build tree is okay
diff --git a/accel/kvm/kvm-all.c b/accel/kvm/kvm-all.c
index 4e0168e88b..c7ec538850 100644
--- a/accel/kvm/kvm-all.c
+++ b/accel/kvm/kvm-all.c
@@ -15,6 +15,7 @@
#include "qemu/osdep.h"
#include <sys/ioctl.h>
+#include <poll.h>
#include <linux/kvm.h>
@@ -78,6 +79,25 @@ struct KVMParkedVcpu {
QLIST_ENTRY(KVMParkedVcpu) node;
};
+enum KVMDirtyRingReaperState {
+ KVM_DIRTY_RING_REAPER_NONE = 0,
+ /* The reaper is sleeping */
+ KVM_DIRTY_RING_REAPER_WAIT,
+ /* The reaper is reaping for dirty pages */
+ KVM_DIRTY_RING_REAPER_REAPING,
+};
+
+/*
+ * KVM reaper instance, responsible for collecting the KVM dirty bits
+ * via the dirty ring.
+ */
+struct KVMDirtyRingReaper {
+ /* The reaper thread */
+ QemuThread reaper_thr;
+ volatile uint64_t reaper_iteration; /* iteration number of reaper thr */
+ volatile enum KVMDirtyRingReaperState reaper_state; /* reap thr state */
+};
+
struct KVMState
{
AccelState parent_obj;
@@ -126,6 +146,9 @@ struct KVMState
KVMMemoryListener *ml;
AddressSpace *as;
} *as;
+ uint64_t kvm_dirty_ring_bytes; /* Size of the per-vcpu dirty ring */
+ uint32_t kvm_dirty_ring_size; /* Number of dirty GFNs per ring */
+ struct KVMDirtyRingReaper reaper;
};
KVMState *kvm_state;
@@ -172,8 +195,12 @@ typedef struct KVMResampleFd KVMResampleFd;
static QLIST_HEAD(, KVMResampleFd) kvm_resample_fd_list =
QLIST_HEAD_INITIALIZER(kvm_resample_fd_list);
-#define kvm_slots_lock(kml) qemu_mutex_lock(&(kml)->slots_lock)
-#define kvm_slots_unlock(kml) qemu_mutex_unlock(&(kml)->slots_lock)
+static QemuMutex kml_slots_lock;
+
+#define kvm_slots_lock() qemu_mutex_lock(&kml_slots_lock)
+#define kvm_slots_unlock() qemu_mutex_unlock(&kml_slots_lock)
+
+static void kvm_slot_init_dirty_bitmap(KVMSlot *mem);
static inline void kvm_resample_fd_remove(int gsi)
{
@@ -239,9 +266,9 @@ bool kvm_has_free_slot(MachineState *ms)
bool result;
KVMMemoryListener *kml = &s->memory_listener;
- kvm_slots_lock(kml);
+ kvm_slots_lock();
result = !!kvm_get_free_slot(kml);
- kvm_slots_unlock(kml);
+ kvm_slots_unlock();
return result;
}
@@ -307,7 +334,7 @@ int kvm_physical_memory_addr_from_host(KVMState *s, void *ram,
KVMMemoryListener *kml = &s->memory_listener;
int i, ret = 0;
- kvm_slots_lock(kml);
+ kvm_slots_lock();
for (i = 0; i < s->nr_slots; i++) {
KVMSlot *mem = &kml->slots[i];
@@ -317,7 +344,7 @@ int kvm_physical_memory_addr_from_host(KVMState *s, void *ram,
break;
}
}
- kvm_slots_unlock(kml);
+ kvm_slots_unlock();
return ret;
}
@@ -383,6 +410,13 @@ static int do_kvm_destroy_vcpu(CPUState *cpu)
goto err;
}
+ if (cpu->kvm_dirty_gfns) {
+ ret = munmap(cpu->kvm_dirty_gfns, s->kvm_dirty_ring_size);
+ if (ret < 0) {
+ goto err;
+ }
+ }
+
vcpu = g_malloc0(sizeof(*vcpu));
vcpu->vcpu_id = kvm_arch_vcpu_id(cpu);
vcpu->kvm_fd = cpu->kvm_fd;
@@ -459,6 +493,19 @@ int kvm_init_vcpu(CPUState *cpu, Error **errp)
(void *)cpu->kvm_run + s->coalesced_mmio * PAGE_SIZE;
}
+ if (s->kvm_dirty_ring_size) {
+ /* Use MAP_SHARED to share pages with the kernel */
+ cpu->kvm_dirty_gfns = mmap(NULL, s->kvm_dirty_ring_size,
+ PROT_READ | PROT_WRITE, MAP_SHARED,
+ cpu->kvm_fd,
+ PAGE_SIZE * KVM_DIRTY_LOG_PAGE_OFFSET);
+ if (cpu->kvm_dirty_gfns == MAP_FAILED) {
+ ret = -errno;
+ DPRINTF("mmap'ing vcpu dirty gfns failed: %d\n", ret);
+ goto err;
+ }
+ }
+
ret = kvm_arch_init_vcpu(cpu);
if (ret < 0) {
error_setg_errno(errp, -ret,
@@ -498,6 +545,7 @@ static int kvm_slot_update_flags(KVMMemoryListener *kml, KVMSlot *mem,
return 0;
}
+ kvm_slot_init_dirty_bitmap(mem);
return kvm_set_user_memory_region(kml, mem, false);
}
@@ -513,7 +561,7 @@ static int kvm_section_update_flags(KVMMemoryListener *kml,
return 0;
}
- kvm_slots_lock(kml);
+ kvm_slots_lock();
while (size && !ret) {
slot_size = MIN(kvm_max_slot_size, size);
@@ -529,7 +577,7 @@ static int kvm_section_update_flags(KVMMemoryListener *kml,
}
out:
- kvm_slots_unlock(kml);
+ kvm_slots_unlock();
return ret;
}
@@ -568,22 +616,28 @@ static void kvm_log_stop(MemoryListener *listener,
}
/* get kvm's dirty pages bitmap and update qemu's */
-static int kvm_get_dirty_pages_log_range(MemoryRegionSection *section,
- unsigned long *bitmap)
+static void kvm_slot_sync_dirty_pages(KVMSlot *slot)
{
- ram_addr_t start = section->offset_within_region +
- memory_region_get_ram_addr(section->mr);
- ram_addr_t pages = int128_get64(section->size) / qemu_real_host_page_size;
+ ram_addr_t start = slot->ram_start_offset;
+ ram_addr_t pages = slot->memory_size / qemu_real_host_page_size;
- cpu_physical_memory_set_dirty_lebitmap(bitmap, start, pages);
- return 0;
+ cpu_physical_memory_set_dirty_lebitmap(slot->dirty_bmap, start, pages);
+}
+
+static void kvm_slot_reset_dirty_pages(KVMSlot *slot)
+{
+ memset(slot->dirty_bmap, 0, slot->dirty_bmap_size);
}
#define ALIGN(x, y) (((x)+(y)-1) & ~((y)-1))
/* Allocate the dirty bitmap for a slot */
-static void kvm_memslot_init_dirty_bitmap(KVMSlot *mem)
+static void kvm_slot_init_dirty_bitmap(KVMSlot *mem)
{
+ if (!(mem->flags & KVM_MEM_LOG_DIRTY_PAGES) || mem->dirty_bmap) {
+ return;
+ }
+
/*
* XXX bad kernel interface alert
* For dirty bitmap, kernel allocates array of size aligned to
@@ -604,6 +658,196 @@ static void kvm_memslot_init_dirty_bitmap(KVMSlot *mem)
hwaddr bitmap_size = ALIGN(mem->memory_size / qemu_real_host_page_size,
/*HOST_LONG_BITS*/ 64) / 8;
mem->dirty_bmap = g_malloc0(bitmap_size);
+ mem->dirty_bmap_size = bitmap_size;
+}
+
+/*
+ * Sync dirty bitmap from kernel to KVMSlot.dirty_bmap, return true if
+ * succeeded, false otherwise
+ */
+static bool kvm_slot_get_dirty_log(KVMState *s, KVMSlot *slot)
+{
+ struct kvm_dirty_log d = {};
+ int ret;
+
+ d.dirty_bitmap = slot->dirty_bmap;
+ d.slot = slot->slot | (slot->as_id << 16);
+ ret = kvm_vm_ioctl(s, KVM_GET_DIRTY_LOG, &d);
+
+ if (ret == -ENOENT) {
+ /* kernel does not have dirty bitmap in this slot */
+ ret = 0;
+ }
+ if (ret) {
+ error_report_once("%s: KVM_GET_DIRTY_LOG failed with %d",
+ __func__, ret);
+ }
+ return ret == 0;
+}
+
+/* Should be with all slots_lock held for the address spaces. */
+static void kvm_dirty_ring_mark_page(KVMState *s, uint32_t as_id,
+ uint32_t slot_id, uint64_t offset)
+{
+ KVMMemoryListener *kml;
+ KVMSlot *mem;
+
+ if (as_id >= s->nr_as) {
+ return;
+ }
+
+ kml = s->as[as_id].ml;
+ mem = &kml->slots[slot_id];
+
+ if (!mem->memory_size || offset >=
+ (mem->memory_size / qemu_real_host_page_size)) {
+ return;
+ }
+
+ set_bit(offset, mem->dirty_bmap);
+}
+
+static bool dirty_gfn_is_dirtied(struct kvm_dirty_gfn *gfn)
+{
+ return gfn->flags == KVM_DIRTY_GFN_F_DIRTY;
+}
+
+static void dirty_gfn_set_collected(struct kvm_dirty_gfn *gfn)
+{
+ gfn->flags = KVM_DIRTY_GFN_F_RESET;
+}
+
+/*
+ * Should be with all slots_lock held for the address spaces. It returns the
+ * dirty page we've collected on this dirty ring.
+ */
+static uint32_t kvm_dirty_ring_reap_one(KVMState *s, CPUState *cpu)
+{
+ struct kvm_dirty_gfn *dirty_gfns = cpu->kvm_dirty_gfns, *cur;
+ uint32_t ring_size = s->kvm_dirty_ring_size;
+ uint32_t count = 0, fetch = cpu->kvm_fetch_index;
+
+ assert(dirty_gfns && ring_size);
+ trace_kvm_dirty_ring_reap_vcpu(cpu->cpu_index);
+
+ while (true) {
+ cur = &dirty_gfns[fetch % ring_size];
+ if (!dirty_gfn_is_dirtied(cur)) {
+ break;
+ }
+ kvm_dirty_ring_mark_page(s, cur->slot >> 16, cur->slot & 0xffff,
+ cur->offset);
+ dirty_gfn_set_collected(cur);
+ trace_kvm_dirty_ring_page(cpu->cpu_index, fetch, cur->offset);
+ fetch++;
+ count++;
+ }
+ cpu->kvm_fetch_index = fetch;
+
+ return count;
+}
+
+/* Must be with slots_lock held */
+static uint64_t kvm_dirty_ring_reap_locked(KVMState *s)
+{
+ int ret;
+ CPUState *cpu;
+ uint64_t total = 0;
+ int64_t stamp;
+
+ stamp = get_clock();
+
+ CPU_FOREACH(cpu) {
+ total += kvm_dirty_ring_reap_one(s, cpu);
+ }
+
+ if (total) {
+ ret = kvm_vm_ioctl(s, KVM_RESET_DIRTY_RINGS);
+ assert(ret == total);
+ }
+
+ stamp = get_clock() - stamp;
+
+ if (total) {
+ trace_kvm_dirty_ring_reap(total, stamp / 1000);
+ }
+
+ return total;
+}
+
+/*
+ * Currently for simplicity, we must hold BQL before calling this. We can
+ * consider to drop the BQL if we're clear with all the race conditions.
+ */
+static uint64_t kvm_dirty_ring_reap(KVMState *s)
+{
+ uint64_t total;
+
+ /*
+ * We need to lock all kvm slots for all address spaces here,
+ * because:
+ *
+ * (1) We need to mark dirty for dirty bitmaps in multiple slots
+ * and for tons of pages, so it's better to take the lock here
+ * once rather than once per page. And more importantly,
+ *
+ * (2) We must _NOT_ publish dirty bits to the other threads
+ * (e.g., the migration thread) via the kvm memory slot dirty
+ * bitmaps before correctly re-protect those dirtied pages.
+ * Otherwise we can have potential risk of data corruption if
+ * the page data is read in the other thread before we do
+ * reset below.
+ */
+ kvm_slots_lock();
+ total = kvm_dirty_ring_reap_locked(s);
+ kvm_slots_unlock();
+
+ return total;
+}
+
+static void do_kvm_cpu_synchronize_kick(CPUState *cpu, run_on_cpu_data arg)
+{
+ /* No need to do anything */
+}
+
+/*
+ * Kick all vcpus out in a synchronized way. When returned, we
+ * guarantee that every vcpu has been kicked and at least returned to
+ * userspace once.
+ */
+static void kvm_cpu_synchronize_kick_all(void)
+{
+ CPUState *cpu;
+
+ CPU_FOREACH(cpu) {
+ run_on_cpu(cpu, do_kvm_cpu_synchronize_kick, RUN_ON_CPU_NULL);
+ }
+}
+
+/*
+ * Flush all the existing dirty pages to the KVM slot buffers. When
+ * this call returns, we guarantee that all the touched dirty pages
+ * before calling this function have been put into the per-kvmslot
+ * dirty bitmap.
+ *
+ * This function must be called with BQL held.
+ */
+static void kvm_dirty_ring_flush(void)
+{
+ trace_kvm_dirty_ring_flush(0);
+ /*
+ * The function needs to be serialized. Since this function
+ * should always be with BQL held, serialization is guaranteed.
+ * However, let's be sure of it.
+ */
+ assert(qemu_mutex_iothread_locked());
+ /*
+ * First make sure to flush the hardware buffers by kicking all
+ * vcpus out in a synchronous way.
+ */
+ kvm_cpu_synchronize_kick_all();
+ kvm_dirty_ring_reap(kvm_state);
+ trace_kvm_dirty_ring_flush(1);
}
/**
@@ -617,53 +861,28 @@ static void kvm_memslot_init_dirty_bitmap(KVMSlot *mem)
* @kml: the KVM memory listener object
* @section: the memory section to sync the dirty bitmap with
*/
-static int kvm_physical_sync_dirty_bitmap(KVMMemoryListener *kml,
- MemoryRegionSection *section)
+static void kvm_physical_sync_dirty_bitmap(KVMMemoryListener *kml,
+ MemoryRegionSection *section)
{
KVMState *s = kvm_state;
- struct kvm_dirty_log d = {};
KVMSlot *mem;
hwaddr start_addr, size;
- hwaddr slot_size, slot_offset = 0;
- int ret = 0;
+ hwaddr slot_size;
size = kvm_align_section(section, &start_addr);
while (size) {
- MemoryRegionSection subsection = *section;
-
slot_size = MIN(kvm_max_slot_size, size);
mem = kvm_lookup_matching_slot(kml, start_addr, slot_size);
if (!mem) {
/* We don't have a slot if we want to trap every access. */
- goto out;
- }
-
- if (!mem->dirty_bmap) {
- /* Allocate on the first log_sync, once and for all */
- kvm_memslot_init_dirty_bitmap(mem);
+ return;
}
-
- d.dirty_bitmap = mem->dirty_bmap;
- d.slot = mem->slot | (kml->as_id << 16);
- ret = kvm_vm_ioctl(s, KVM_GET_DIRTY_LOG, &d);
- if (ret == -ENOENT) {
- /* kernel does not have dirty bitmap in this slot */
- ret = 0;
- } else if (ret < 0) {
- error_report("ioctl KVM_GET_DIRTY_LOG failed: %d", errno);
- goto out;
- } else {
- subsection.offset_within_region += slot_offset;
- subsection.size = int128_make64(slot_size);
- kvm_get_dirty_pages_log_range(&subsection, d.dirty_bitmap);
+ if (kvm_slot_get_dirty_log(s, mem)) {
+ kvm_slot_sync_dirty_pages(mem);
}
-
- slot_offset += slot_size;
start_addr += slot_size;
size -= slot_size;
}
-out:
- return ret;
}
/* Alignment requirement for KVM_CLEAR_DIRTY_LOG - 64 pages */
@@ -810,7 +1029,7 @@ static int kvm_physical_log_clear(KVMMemoryListener *kml,
return ret;
}
- kvm_slots_lock(kml);
+ kvm_slots_lock();
for (i = 0; i < s->nr_slots; i++) {
mem = &kml->slots[i];
@@ -836,7 +1055,7 @@ static int kvm_physical_log_clear(KVMMemoryListener *kml,
}
}
- kvm_slots_unlock(kml);
+ kvm_slots_unlock();
return ret;
}
@@ -1119,7 +1338,8 @@ static void kvm_set_phys_mem(KVMMemoryListener *kml,
int err;
MemoryRegion *mr = section->mr;
bool writeable = !mr->readonly && !mr->rom_device;
- hwaddr start_addr, size, slot_size;
+ hwaddr start_addr, size, slot_size, mr_offset;
+ ram_addr_t ram_start_offset;
void *ram;
if (!memory_region_is_ram(mr)) {
@@ -1137,11 +1357,15 @@ static void kvm_set_phys_mem(KVMMemoryListener *kml,
return;
}
- /* use aligned delta to align the ram address */
- ram = memory_region_get_ram_ptr(mr) + section->offset_within_region +
- (start_addr - section->offset_within_address_space);
+ /* The offset of the kvmslot within the memory region */
+ mr_offset = section->offset_within_region + start_addr -
+ section->offset_within_address_space;
- kvm_slots_lock(kml);
+ /* use aligned delta to align the ram address and offset */
+ ram = memory_region_get_ram_ptr(mr) + mr_offset;
+ ram_start_offset = memory_region_get_ram_addr(mr) + mr_offset;
+
+ kvm_slots_lock();
if (!add) {
do {
@@ -1151,7 +1375,25 @@ static void kvm_set_phys_mem(KVMMemoryListener *kml,
goto out;
}
if (mem->flags & KVM_MEM_LOG_DIRTY_PAGES) {
- kvm_physical_sync_dirty_bitmap(kml, section);
+ /*
+ * NOTE: We should be aware of the fact that here we're only
+ * doing a best effort to sync dirty bits. No matter whether
+ * we're using dirty log or dirty ring, we ignored two facts:
+ *
+ * (1) dirty bits can reside in hardware buffers (PML)
+ *
+ * (2) after we collected dirty bits here, pages can be dirtied
+ * again before we do the final KVM_SET_USER_MEMORY_REGION to
+ * remove the slot.
+ *
+ * Not easy. Let's cross the fingers until it's fixed.
+ */
+ if (kvm_state->kvm_dirty_ring_size) {
+ kvm_dirty_ring_reap_locked(kvm_state);
+ } else {
+ kvm_slot_get_dirty_log(kvm_state, mem);
+ }
+ kvm_slot_sync_dirty_pages(mem);
}
/* unregister the slot */
@@ -1175,18 +1417,13 @@ static void kvm_set_phys_mem(KVMMemoryListener *kml,
do {
slot_size = MIN(kvm_max_slot_size, size);
mem = kvm_alloc_slot(kml);
+ mem->as_id = kml->as_id;
mem->memory_size = slot_size;
mem->start_addr = start_addr;
+ mem->ram_start_offset = ram_start_offset;
mem->ram = ram;
mem->flags = kvm_mem_flags(mr);
-
- if (mem->flags & KVM_MEM_LOG_DIRTY_PAGES) {
- /*
- * Reallocate the bmap; it means it doesn't disappear in
- * middle of a migrate.
- */
- kvm_memslot_init_dirty_bitmap(mem);
- }
+ kvm_slot_init_dirty_bitmap(mem);
err = kvm_set_user_memory_region(kml, mem, true);
if (err) {
fprintf(stderr, "%s: error registering slot: %s\n", __func__,
@@ -1194,12 +1431,58 @@ static void kvm_set_phys_mem(KVMMemoryListener *kml,
abort();
}
start_addr += slot_size;
+ ram_start_offset += slot_size;
ram += slot_size;
size -= slot_size;
} while (size);
out:
- kvm_slots_unlock(kml);
+ kvm_slots_unlock();
+}
+
+static void *kvm_dirty_ring_reaper_thread(void *data)
+{
+ KVMState *s = data;
+ struct KVMDirtyRingReaper *r = &s->reaper;
+
+ rcu_register_thread();
+
+ trace_kvm_dirty_ring_reaper("init");
+
+ while (true) {
+ r->reaper_state = KVM_DIRTY_RING_REAPER_WAIT;
+ trace_kvm_dirty_ring_reaper("wait");
+ /*
+ * TODO: provide a smarter timeout rather than a constant?
+ */
+ sleep(1);
+
+ trace_kvm_dirty_ring_reaper("wakeup");
+ r->reaper_state = KVM_DIRTY_RING_REAPER_REAPING;
+
+ qemu_mutex_lock_iothread();
+ kvm_dirty_ring_reap(s);
+ qemu_mutex_unlock_iothread();
+
+ r->reaper_iteration++;
+ }
+
+ trace_kvm_dirty_ring_reaper("exit");
+
+ rcu_unregister_thread();
+
+ return NULL;
+}
+
+static int kvm_dirty_ring_reaper_init(KVMState *s)
+{
+ struct KVMDirtyRingReaper *r = &s->reaper;
+
+ qemu_thread_create(&r->reaper_thr, "kvm-reaper",
+ kvm_dirty_ring_reaper_thread,
+ s, QEMU_THREAD_JOINABLE);
+
+ return 0;
}
static void kvm_region_add(MemoryListener *listener,
@@ -1224,14 +1507,40 @@ static void kvm_log_sync(MemoryListener *listener,
MemoryRegionSection *section)
{
KVMMemoryListener *kml = container_of(listener, KVMMemoryListener, listener);
- int r;
- kvm_slots_lock(kml);
- r = kvm_physical_sync_dirty_bitmap(kml, section);
- kvm_slots_unlock(kml);
- if (r < 0) {
- abort();
+ kvm_slots_lock();
+ kvm_physical_sync_dirty_bitmap(kml, section);
+ kvm_slots_unlock();
+}
+
+static void kvm_log_sync_global(MemoryListener *l)
+{
+ KVMMemoryListener *kml = container_of(l, KVMMemoryListener, listener);
+ KVMState *s = kvm_state;
+ KVMSlot *mem;
+ int i;
+
+ /* Flush all kernel dirty addresses into KVMSlot dirty bitmap */
+ kvm_dirty_ring_flush();
+
+ /*
+ * TODO: make this faster when nr_slots is big while there are
+ * only a few used slots (small VMs).
+ */
+ kvm_slots_lock();
+ for (i = 0; i < s->nr_slots; i++) {
+ mem = &kml->slots[i];
+ if (mem->memory_size && mem->flags & KVM_MEM_LOG_DIRTY_PAGES) {
+ kvm_slot_sync_dirty_pages(mem);
+ /*
+ * This is not needed by KVM_GET_DIRTY_LOG because the
+ * ioctl will unconditionally overwrite the whole region.
+ * However kvm dirty ring has no such side effect.
+ */
+ kvm_slot_reset_dirty_pages(mem);
+ }
}
+ kvm_slots_unlock();
}
static void kvm_log_clear(MemoryListener *listener,
@@ -1328,7 +1637,6 @@ void kvm_memory_listener_register(KVMState *s, KVMMemoryListener *kml,
{
int i;
- qemu_mutex_init(&kml->slots_lock);
kml->slots = g_malloc0(s->nr_slots * sizeof(KVMSlot));
kml->as_id = as_id;
@@ -1340,10 +1648,15 @@ void kvm_memory_listener_register(KVMState *s, KVMMemoryListener *kml,
kml->listener.region_del = kvm_region_del;
kml->listener.log_start = kvm_log_start;
kml->listener.log_stop = kvm_log_stop;
- kml->listener.log_sync = kvm_log_sync;
- kml->listener.log_clear = kvm_log_clear;
kml->listener.priority = 10;
+ if (s->kvm_dirty_ring_size) {
+ kml->listener.log_sync_global = kvm_log_sync_global;
+ } else {
+ kml->listener.log_sync = kvm_log_sync;
+ kml->listener.log_clear = kvm_log_clear;
+ }
+
memory_listener_register(&kml->listener, as);
for (i = 0; i < s->nr_as; ++i) {
@@ -2001,6 +2314,8 @@ static int kvm_init(MachineState *ms)
int type = 0;
uint64_t dirty_log_manual_caps;
+ qemu_mutex_init(&kml_slots_lock);
+
s = KVM_STATE(ms->accelerator);
/*
@@ -2017,7 +2332,6 @@ static int kvm_init(MachineState *ms)
QTAILQ_INIT(&s->kvm_sw_breakpoints);
#endif
QLIST_INIT(&s->kvm_parked_vcpus);
- s->vmfd = -1;
s->fd = qemu_open_old("/dev/kvm", O_RDWR);
if (s->fd == -1) {
fprintf(stderr, "Could not access KVM kernel module: %m\n");
@@ -2125,20 +2439,70 @@ static int kvm_init(MachineState *ms)
s->coalesced_pio = s->coalesced_mmio &&
kvm_check_extension(s, KVM_CAP_COALESCED_PIO);
- dirty_log_manual_caps =
- kvm_check_extension(s, KVM_CAP_MANUAL_DIRTY_LOG_PROTECT2);
- dirty_log_manual_caps &= (KVM_DIRTY_LOG_MANUAL_PROTECT_ENABLE |
- KVM_DIRTY_LOG_INITIALLY_SET);
- s->manual_dirty_log_protect = dirty_log_manual_caps;
- if (dirty_log_manual_caps) {
- ret = kvm_vm_enable_cap(s, KVM_CAP_MANUAL_DIRTY_LOG_PROTECT2, 0,
- dirty_log_manual_caps);
- if (ret) {
- warn_report("Trying to enable capability %"PRIu64" of "
- "KVM_CAP_MANUAL_DIRTY_LOG_PROTECT2 but failed. "
- "Falling back to the legacy mode. ",
- dirty_log_manual_caps);
- s->manual_dirty_log_protect = 0;
+ /*
+ * Enable KVM dirty ring if supported, otherwise fall back to
+ * dirty logging mode
+ */
+ if (s->kvm_dirty_ring_size > 0) {
+ uint64_t ring_bytes;
+
+ ring_bytes = s->kvm_dirty_ring_size * sizeof(struct kvm_dirty_gfn);
+
+ /* Read the max supported pages */
+ ret = kvm_vm_check_extension(s, KVM_CAP_DIRTY_LOG_RING);
+ if (ret > 0) {
+ if (ring_bytes > ret) {
+ error_report("KVM dirty ring size %" PRIu32 " too big "
+ "(maximum is %ld). Please use a smaller value.",
+ s->kvm_dirty_ring_size,
+ (long)ret / sizeof(struct kvm_dirty_gfn));
+ ret = -EINVAL;
+ goto err;
+ }
+
+ ret = kvm_vm_enable_cap(s, KVM_CAP_DIRTY_LOG_RING, 0, ring_bytes);
+ if (ret) {
+ error_report("Enabling of KVM dirty ring failed: %s. "
+ "Suggested mininum value is 1024.", strerror(-ret));
+ goto err;
+ }
+
+ s->kvm_dirty_ring_bytes = ring_bytes;
+ } else {
+ warn_report("KVM dirty ring not available, using bitmap method");
+ s->kvm_dirty_ring_size = 0;
+ }
+ }
+
+ /*
+ * KVM_CAP_MANUAL_DIRTY_LOG_PROTECT2 is not needed when dirty ring is
+ * enabled. More importantly, KVM_DIRTY_LOG_INITIALLY_SET will assume no
+ * page is wr-protected initially, which is against how kvm dirty ring is
+ * usage - kvm dirty ring requires all pages are wr-protected at the very
+ * beginning. Enabling this feature for dirty ring causes data corruption.
+ *
+ * TODO: Without KVM_CAP_MANUAL_DIRTY_LOG_PROTECT2 and kvm clear dirty log,
+ * we may expect a higher stall time when starting the migration. In the
+ * future we can enable KVM_CLEAR_DIRTY_LOG to work with dirty ring too:
+ * instead of clearing dirty bit, it can be a way to explicitly wr-protect
+ * guest pages.
+ */
+ if (!s->kvm_dirty_ring_size) {
+ dirty_log_manual_caps =
+ kvm_check_extension(s, KVM_CAP_MANUAL_DIRTY_LOG_PROTECT2);
+ dirty_log_manual_caps &= (KVM_DIRTY_LOG_MANUAL_PROTECT_ENABLE |
+ KVM_DIRTY_LOG_INITIALLY_SET);
+ s->manual_dirty_log_protect = dirty_log_manual_caps;
+ if (dirty_log_manual_caps) {
+ ret = kvm_vm_enable_cap(s, KVM_CAP_MANUAL_DIRTY_LOG_PROTECT2, 0,
+ dirty_log_manual_caps);
+ if (ret) {
+ warn_report("Trying to enable capability %"PRIu64" of "
+ "KVM_CAP_MANUAL_DIRTY_LOG_PROTECT2 but failed. "
+ "Falling back to the legacy mode. ",
+ dirty_log_manual_caps);
+ s->manual_dirty_log_protect = 0;
+ }
}
}
@@ -2224,6 +2588,14 @@ static int kvm_init(MachineState *ms)
ret = ram_block_discard_disable(true);
assert(!ret);
}
+
+ if (s->kvm_dirty_ring_size) {
+ ret = kvm_dirty_ring_reaper_init(s);
+ if (ret) {
+ goto err;
+ }
+ }
+
return 0;
err:
@@ -2536,6 +2908,17 @@ int kvm_cpu_exec(CPUState *cpu)
case KVM_EXIT_INTERNAL_ERROR:
ret = kvm_handle_internal_error(cpu, run);
break;
+ case KVM_EXIT_DIRTY_RING_FULL:
+ /*
+ * We shouldn't continue if the dirty ring of this vcpu is
+ * still full. Got kicked by KVM_RESET_DIRTY_RINGS.
+ */
+ trace_kvm_dirty_ring_full(cpu->cpu_index);
+ qemu_mutex_lock_iothread();
+ kvm_dirty_ring_reap(kvm_state);
+ qemu_mutex_unlock_iothread();
+ ret = 0;
+ break;
case KVM_EXIT_SYSTEM_EVENT:
switch (run->system_event.type) {
case KVM_SYSTEM_EVENT_SHUTDOWN:
@@ -3112,6 +3495,11 @@ static void kvm_set_kvm_shadow_mem(Object *obj, Visitor *v,
KVMState *s = KVM_STATE(obj);
int64_t value;
+ if (s->fd != -1) {
+ error_setg(errp, "Cannot set properties after the accelerator has been initialized");
+ return;
+ }
+
if (!visit_type_int(v, name, &value, errp)) {
return;
}
@@ -3126,6 +3514,11 @@ static void kvm_set_kernel_irqchip(Object *obj, Visitor *v,
KVMState *s = KVM_STATE(obj);
OnOffSplit mode;
+ if (s->fd != -1) {
+ error_setg(errp, "Cannot set properties after the accelerator has been initialized");
+ return;
+ }
+
if (!visit_type_OnOffSplit(v, name, &mode, errp)) {
return;
}
@@ -3168,13 +3561,53 @@ bool kvm_kernel_irqchip_split(void)
return kvm_state->kernel_irqchip_split == ON_OFF_AUTO_ON;
}
+static void kvm_get_dirty_ring_size(Object *obj, Visitor *v,
+ const char *name, void *opaque,
+ Error **errp)
+{
+ KVMState *s = KVM_STATE(obj);
+ uint32_t value = s->kvm_dirty_ring_size;
+
+ visit_type_uint32(v, name, &value, errp);
+}
+
+static void kvm_set_dirty_ring_size(Object *obj, Visitor *v,
+ const char *name, void *opaque,
+ Error **errp)
+{
+ KVMState *s = KVM_STATE(obj);
+ Error *error = NULL;
+ uint32_t value;
+
+ if (s->fd != -1) {
+ error_setg(errp, "Cannot set properties after the accelerator has been initialized");
+ return;
+ }
+
+ visit_type_uint32(v, name, &value, &error);
+ if (error) {
+ error_propagate(errp, error);
+ return;
+ }
+ if (value & (value - 1)) {
+ error_setg(errp, "dirty-ring-size must be a power of two.");
+ return;
+ }
+
+ s->kvm_dirty_ring_size = value;
+}
+
static void kvm_accel_instance_init(Object *obj)
{
KVMState *s = KVM_STATE(obj);
+ s->fd = -1;
+ s->vmfd = -1;
s->kvm_shadow_mem = -1;
s->kernel_irqchip_allowed = true;
s->kernel_irqchip_split = ON_OFF_AUTO_AUTO;
+ /* KVM dirty ring is by default off */
+ s->kvm_dirty_ring_size = 0;
}
static void kvm_accel_class_init(ObjectClass *oc, void *data)
@@ -3196,6 +3629,12 @@ static void kvm_accel_class_init(ObjectClass *oc, void *data)
NULL, NULL);
object_class_property_set_description(oc, "kvm-shadow-mem",
"KVM shadow MMU size");
+
+ object_class_property_add(oc, "dirty-ring-size", "uint32",
+ kvm_get_dirty_ring_size, kvm_set_dirty_ring_size,
+ NULL, NULL);
+ object_class_property_set_description(oc, "dirty-ring-size",
+ "Size of KVM dirty page ring buffer (default: 0, i.e. use bitmap)");
}
static const TypeInfo kvm_accel_type = {
diff --git a/accel/kvm/trace-events b/accel/kvm/trace-events
index e15ae8980d..72a01320a1 100644
--- a/accel/kvm/trace-events
+++ b/accel/kvm/trace-events
@@ -18,4 +18,11 @@ kvm_set_ioeventfd_pio(int fd, uint16_t addr, uint32_t val, bool assign, uint32_t
kvm_set_user_memory(uint32_t slot, uint32_t flags, uint64_t guest_phys_addr, uint64_t memory_size, uint64_t userspace_addr, int ret) "Slot#%d flags=0x%x gpa=0x%"PRIx64 " size=0x%"PRIx64 " ua=0x%"PRIx64 " ret=%d"
kvm_clear_dirty_log(uint32_t slot, uint64_t start, uint32_t size) "slot#%"PRId32" start 0x%"PRIx64" size 0x%"PRIx32
kvm_resample_fd_notify(int gsi) "gsi %d"
+kvm_dirty_ring_full(int id) "vcpu %d"
+kvm_dirty_ring_reap_vcpu(int id) "vcpu %d"
+kvm_dirty_ring_page(int vcpu, uint32_t slot, uint64_t offset) "vcpu %d fetch %"PRIu32" offset 0x%"PRIx64
+kvm_dirty_ring_reaper(const char *s) "%s"
+kvm_dirty_ring_reap(uint64_t count, int64_t t) "reaped %"PRIu64" pages (took %"PRIi64" us)"
+kvm_dirty_ring_reaper_kick(const char *reason) "%s"
+kvm_dirty_ring_flush(int finished) "%d"
diff --git a/accel/tcg/cpu-exec.c b/accel/tcg/cpu-exec.c
index 0dc5271715..ad1279d2ed 100644
--- a/accel/tcg/cpu-exec.c
+++ b/accel/tcg/cpu-exec.c
@@ -29,8 +29,6 @@
#include "qemu/compiler.h"
#include "qemu/timer.h"
#include "qemu/rcu.h"
-#include "exec/tb-hash.h"
-#include "exec/tb-lookup.h"
#include "exec/log.h"
#include "qemu/main-loop.h"
#if defined(TARGET_I386) && !defined(CONFIG_USER_ONLY)
@@ -40,6 +38,9 @@
#include "exec/cpu-all.h"
#include "sysemu/cpu-timers.h"
#include "sysemu/replay.h"
+#include "tb-hash.h"
+#include "tb-lookup.h"
+#include "tb-context.h"
#include "internal.h"
/* -icount align implementation. */
diff --git a/accel/tcg/cputlb.c b/accel/tcg/cputlb.c
index 2f7088614a..f24348e979 100644
--- a/accel/tcg/cputlb.c
+++ b/accel/tcg/cputlb.c
@@ -24,7 +24,6 @@
#include "exec/memory.h"
#include "exec/cpu_ldst.h"
#include "exec/cputlb.h"
-#include "exec/tb-hash.h"
#include "exec/memory-internal.h"
#include "exec/ram_addr.h"
#include "tcg/tcg.h"
@@ -36,6 +35,7 @@
#include "exec/translate-all.h"
#include "trace/trace-root.h"
#include "trace/mem.h"
+#include "tb-hash.h"
#include "internal.h"
#ifdef CONFIG_PLUGIN
#include "qemu/plugin-memory.h"
diff --git a/include/exec/tb-context.h b/accel/tcg/tb-context.h
index cc33979113..cc33979113 100644
--- a/include/exec/tb-context.h
+++ b/accel/tcg/tb-context.h
diff --git a/include/exec/tb-hash.h b/accel/tcg/tb-hash.h
index 0a273d9605..0a273d9605 100644
--- a/include/exec/tb-hash.h
+++ b/accel/tcg/tb-hash.h
diff --git a/include/exec/tb-lookup.h b/accel/tcg/tb-lookup.h
index 29d61ceb34..9c9e0079da 100644
--- a/include/exec/tb-lookup.h
+++ b/accel/tcg/tb-lookup.h
@@ -14,7 +14,7 @@
#endif
#include "exec/exec-all.h"
-#include "exec/tb-hash.h"
+#include "tb-hash.h"
/* Might cause an exception, so have a longjmp destination ready */
static inline TranslationBlock *tb_lookup(CPUState *cpu, target_ulong pc,
diff --git a/accel/tcg/tcg-runtime.c b/accel/tcg/tcg-runtime.c
index 49f5de37e8..66ac830e2f 100644
--- a/accel/tcg/tcg-runtime.c
+++ b/accel/tcg/tcg-runtime.c
@@ -30,7 +30,7 @@
#include "disas/disas.h"
#include "exec/log.h"
#include "tcg/tcg.h"
-#include "exec/tb-lookup.h"
+#include "tb-lookup.h"
/* 32-bit helpers */
diff --git a/accel/tcg/translate-all.c b/accel/tcg/translate-all.c
index 640ff6e3e7..1eefe6ea8d 100644
--- a/accel/tcg/translate-all.c
+++ b/accel/tcg/translate-all.c
@@ -47,7 +47,6 @@
#endif
#include "exec/cputlb.h"
-#include "exec/tb-hash.h"
#include "exec/translate-all.h"
#include "qemu/bitmap.h"
#include "qemu/error-report.h"
@@ -60,6 +59,8 @@
#include "sysemu/tcg.h"
#include "qapi/error.h"
#include "hw/core/tcg-cpu-ops.h"
+#include "tb-hash.h"
+#include "tb-context.h"
#include "internal.h"
/* #define DEBUG_TB_INVALIDATE */
diff --git a/block/replication.c b/block/replication.c
index 97be7ef4de..52163f2d1f 100644
--- a/block/replication.c
+++ b/block/replication.c
@@ -22,7 +22,7 @@
#include "sysemu/block-backend.h"
#include "qapi/error.h"
#include "qapi/qmp/qdict.h"
-#include "replication.h"
+#include "block/replication.h"
typedef enum {
BLOCK_REPLICATION_NONE, /* block replication is not started */
diff --git a/configure b/configure
index 676239c697..90c0807347 100755
--- a/configure
+++ b/configure
@@ -256,31 +256,11 @@ gdb_bin=$(command -v "gdb-multiarch" || command -v "gdb")
if test -e "$source_path/.git"
then
git_submodules_action="update"
- git_submodules="ui/keycodemapdb"
- git_submodules="$git_submodules tests/fp/berkeley-testfloat-3"
- git_submodules="$git_submodules tests/fp/berkeley-softfloat-3"
else
git_submodules_action="ignore"
- git_submodules=""
-
- if ! test -f "$source_path/ui/keycodemapdb/README"
- then
- echo
- echo "ERROR: missing file $source_path/ui/keycodemapdb/README"
- echo
- echo "This is not a GIT checkout but module content appears to"
- echo "be missing. Do not use 'git archive' or GitHub download links"
- echo "to acquire QEMU source archives. Non-GIT builds are only"
- echo "supported with source archives linked from:"
- echo
- echo " https://www.qemu.org/download/#source"
- echo
- echo "Developers working with GIT can use scripts/archive-source.sh"
- echo "if they need to create valid source archives."
- echo
- exit 1
- fi
fi
+
+git_submodules="ui/keycodemapdb"
git="git"
# Don't accept a target_list environment variable.
@@ -1593,6 +1573,28 @@ case $git_submodules_action in
fi
;;
ignore)
+ if ! test -f "$source_path/ui/keycodemapdb/README"
+ then
+ echo
+ echo "ERROR: missing GIT submodules"
+ echo
+ if test -e "$source_path/.git"; then
+ echo "--with-git-submodules=ignore specified but submodules were not"
+ echo "checked out. Please initialize and update submodules."
+ else
+ echo "This is not a GIT checkout but module content appears to"
+ echo "be missing. Do not use 'git archive' or GitHub download links"
+ echo "to acquire QEMU source archives. Non-GIT builds are only"
+ echo "supported with source archives linked from:"
+ echo
+ echo " https://www.qemu.org/download/#source"
+ echo
+ echo "Developers working with GIT can use scripts/archive-source.sh"
+ echo "if they need to create valid source archives."
+ fi
+ echo
+ exit 1
+ fi
;;
*)
echo "ERROR: invalid --with-git-submodules= value '$git_submodules_action'"
@@ -2281,6 +2283,11 @@ if test "$solaris" = "yes" ; then
fi
fi
+if test "$tcg" = "enabled"; then
+ git_submodules="$git_submodules tests/fp/berkeley-testfloat-3"
+ git_submodules="$git_submodules tests/fp/berkeley-softfloat-3"
+fi
+
if test -z "${target_list+xxx}" ; then
default_targets=yes
for target in $default_target_list; do
@@ -3620,9 +3627,7 @@ fi
case "$fdt" in
auto | enabled | internal)
# Simpler to always update submodule, even if not needed.
- if test "$git_submodules_action" != "ignore"; then
- git_submodules="${git_submodules} dtc"
- fi
+ git_submodules="${git_submodules} dtc"
;;
esac
@@ -4344,9 +4349,7 @@ fi
case "$capstone" in
auto | enabled | internal)
# Simpler to always update submodule, even if not needed.
- if test "$git_submodules_action" != "ignore"; then
- git_submodules="${git_submodules} capstone"
- fi
+ git_submodules="${git_submodules} capstone"
;;
esac
@@ -5276,9 +5279,7 @@ fi
case "$slirp" in
auto | enabled | internal)
# Simpler to always update submodule, even if not needed.
- if test "$git_submodules_action" != "ignore"; then
- git_submodules="${git_submodules} slirp"
- fi
+ git_submodules="${git_submodules} slirp"
;;
esac
@@ -5470,9 +5471,7 @@ if test "$cpu" = "s390x" ; then
roms="$roms s390-ccw"
# SLOF is required for building the s390-ccw firmware on s390x,
# since it is using the libnet code from SLOF for network booting.
- if test "$git_submodules_action" != "ignore"; then
- git_submodules="${git_submodules} roms/SLOF"
- fi
+ git_submodules="${git_submodules} roms/SLOF"
fi
fi
@@ -6504,10 +6503,14 @@ fi
# Create list of config switches that should be poisoned in common code...
# but filter out CONFIG_TCG and CONFIG_USER_ONLY which are special.
-sed -n -e '/CONFIG_TCG/d' -e '/CONFIG_USER_ONLY/d' \
- -e '/^#define / { s///; s/ .*//; s/^/#pragma GCC poison /p; }' \
- *-config-devices.h *-config-target.h | \
- sort -u > config-poison.h
+target_configs_h=$(ls *-config-devices.h *-config-target.h 2>/dev/null)
+if test -n "$target_configs_h" ; then
+ sed -n -e '/CONFIG_TCG/d' -e '/CONFIG_USER_ONLY/d' \
+ -e '/^#define / { s///; s/ .*//; s/^/#pragma GCC poison /p; }' \
+ $target_configs_h | sort -u > config-poison.h
+else
+ :> config-poison.h
+fi
# Save the configure command line for later reuse.
cat <<EOD >config.status
diff --git a/cpu.c b/cpu.c
index 34a0484bf4..164fefeaa3 100644
--- a/cpu.c
+++ b/cpu.c
@@ -29,6 +29,7 @@
#ifdef CONFIG_USER_ONLY
#include "qemu.h"
#else
+#include "hw/core/sysemu-cpu-ops.h"
#include "exec/address-spaces.h"
#endif
#include "sysemu/tcg.h"
@@ -127,7 +128,9 @@ const VMStateDescription vmstate_cpu_common = {
void cpu_exec_realizefn(CPUState *cpu, Error **errp)
{
+#ifndef CONFIG_USER_ONLY
CPUClass *cc = CPU_GET_CLASS(cpu);
+#endif
cpu_list_add(cpu);
if (!accel_cpu_realizefn(cpu, errp)) {
@@ -141,26 +144,25 @@ void cpu_exec_realizefn(CPUState *cpu, Error **errp)
#endif /* CONFIG_TCG */
#ifdef CONFIG_USER_ONLY
- assert(cc->vmsd == NULL);
+ assert(qdev_get_vmsd(DEVICE(cpu)) == NULL ||
+ qdev_get_vmsd(DEVICE(cpu))->unmigratable);
#else
if (qdev_get_vmsd(DEVICE(cpu)) == NULL) {
vmstate_register(NULL, cpu->cpu_index, &vmstate_cpu_common, cpu);
}
- if (cc->vmsd != NULL) {
- vmstate_register(NULL, cpu->cpu_index, cc->vmsd, cpu);
+ if (cc->sysemu_ops->legacy_vmsd != NULL) {
+ vmstate_register(NULL, cpu->cpu_index, cc->sysemu_ops->legacy_vmsd, cpu);
}
#endif /* CONFIG_USER_ONLY */
}
void cpu_exec_unrealizefn(CPUState *cpu)
{
+#ifndef CONFIG_USER_ONLY
CPUClass *cc = CPU_GET_CLASS(cpu);
-#ifdef CONFIG_USER_ONLY
- assert(cc->vmsd == NULL);
-#else
- if (cc->vmsd != NULL) {
- vmstate_unregister(NULL, cc->vmsd, cpu);
+ if (cc->sysemu_ops->legacy_vmsd != NULL) {
+ vmstate_unregister(NULL, cc->sysemu_ops->legacy_vmsd, cpu);
}
if (qdev_get_vmsd(DEVICE(cpu)) == NULL) {
vmstate_unregister(NULL, &vmstate_cpu_common, cpu);
diff --git a/default-configs/devices/ppc64-softmmu.mak b/default-configs/devices/ppc64-softmmu.mak
index ae0841fa3a..cca52665d9 100644
--- a/default-configs/devices/ppc64-softmmu.mak
+++ b/default-configs/devices/ppc64-softmmu.mak
@@ -8,4 +8,3 @@ CONFIG_POWERNV=y
# For pSeries
CONFIG_PSERIES=y
-CONFIG_NVDIMM=y
diff --git a/hmp-commands.hx b/hmp-commands.hx
index 5ee9cfd520..2d21fe5ad4 100644
--- a/hmp-commands.hx
+++ b/hmp-commands.hx
@@ -1297,6 +1297,7 @@ ERST
.help = "create QOM object",
.cmd = hmp_object_add,
.command_completion = object_add_completion,
+ .flags = "p",
},
SRST
@@ -1311,6 +1312,7 @@ ERST
.help = "destroy QOM object",
.cmd = hmp_object_del,
.command_completion = object_del_completion,
+ .flags = "p",
},
SRST
diff --git a/hw/arm/Kconfig b/hw/arm/Kconfig
index b887f6a5b1..67723d9ea6 100644
--- a/hw/arm/Kconfig
+++ b/hw/arm/Kconfig
@@ -6,6 +6,7 @@ config ARM_VIRT
imply VFIO_PLATFORM
imply VFIO_XGMAC
imply TPM_TIS_SYSBUS
+ imply NVDIMM
select ARM_GIC
select ACPI
select ARM_SMMUV3
diff --git a/hw/core/cpu.c b/hw/core/cpu-common.c
index 00330ba07d..9530e266ec 100644
--- a/hw/core/cpu.c
+++ b/hw/core/cpu-common.c
@@ -34,7 +34,6 @@
#include "hw/qdev-properties.h"
#include "trace/trace-root.h"
#include "qemu/plugin.h"
-#include "sysemu/hw_accel.h"
CPUState *cpu_by_arch_id(int64_t id)
{
@@ -67,33 +66,6 @@ CPUState *cpu_create(const char *typename)
return cpu;
}
-bool cpu_paging_enabled(const CPUState *cpu)
-{
- CPUClass *cc = CPU_GET_CLASS(cpu);
-
- return cc->get_paging_enabled(cpu);
-}
-
-static bool cpu_common_get_paging_enabled(const CPUState *cpu)
-{
- return false;
-}
-
-void cpu_get_memory_mapping(CPUState *cpu, MemoryMappingList *list,
- Error **errp)
-{
- CPUClass *cc = CPU_GET_CLASS(cpu);
-
- cc->get_memory_mapping(cpu, list, errp);
-}
-
-static void cpu_common_get_memory_mapping(CPUState *cpu,
- MemoryMappingList *list,
- Error **errp)
-{
- error_setg(errp, "Obtaining memory mappings is unsupported on this CPU.");
-}
-
/* Resetting the IRQ comes from across the code base so we take the
* BQL here if we need to. cpu_interrupt assumes it is held.*/
void cpu_reset_interrupt(CPUState *cpu, int mask)
@@ -117,65 +89,6 @@ void cpu_exit(CPUState *cpu)
qatomic_set(&cpu->icount_decr_ptr->u16.high, -1);
}
-int cpu_write_elf32_qemunote(WriteCoreDumpFunction f, CPUState *cpu,
- void *opaque)
-{
- CPUClass *cc = CPU_GET_CLASS(cpu);
-
- return (*cc->write_elf32_qemunote)(f, cpu, opaque);
-}
-
-static int cpu_common_write_elf32_qemunote(WriteCoreDumpFunction f,
- CPUState *cpu, void *opaque)
-{
- return 0;
-}
-
-int cpu_write_elf32_note(WriteCoreDumpFunction f, CPUState *cpu,
- int cpuid, void *opaque)
-{
- CPUClass *cc = CPU_GET_CLASS(cpu);
-
- return (*cc->write_elf32_note)(f, cpu, cpuid, opaque);
-}
-
-static int cpu_common_write_elf32_note(WriteCoreDumpFunction f,
- CPUState *cpu, int cpuid,
- void *opaque)
-{
- return -1;
-}
-
-int cpu_write_elf64_qemunote(WriteCoreDumpFunction f, CPUState *cpu,
- void *opaque)
-{
- CPUClass *cc = CPU_GET_CLASS(cpu);
-
- return (*cc->write_elf64_qemunote)(f, cpu, opaque);
-}
-
-static int cpu_common_write_elf64_qemunote(WriteCoreDumpFunction f,
- CPUState *cpu, void *opaque)
-{
- return 0;
-}
-
-int cpu_write_elf64_note(WriteCoreDumpFunction f, CPUState *cpu,
- int cpuid, void *opaque)
-{
- CPUClass *cc = CPU_GET_CLASS(cpu);
-
- return (*cc->write_elf64_note)(f, cpu, cpuid, opaque);
-}
-
-static int cpu_common_write_elf64_note(WriteCoreDumpFunction f,
- CPUState *cpu, int cpuid,
- void *opaque)
-{
- return -1;
-}
-
-
static int cpu_common_gdb_read_register(CPUState *cpu, GByteArray *buf, int reg)
{
return 0;
@@ -186,28 +99,6 @@ static int cpu_common_gdb_write_register(CPUState *cpu, uint8_t *buf, int reg)
return 0;
}
-static bool cpu_common_virtio_is_big_endian(CPUState *cpu)
-{
- return target_words_bigendian();
-}
-
-/*
- * XXX the following #if is always true because this is a common_ss
- * module, so target CONFIG_* is never defined.
- */
-#if !defined(CONFIG_USER_ONLY)
-GuestPanicInformation *cpu_get_crash_info(CPUState *cpu)
-{
- CPUClass *cc = CPU_GET_CLASS(cpu);
- GuestPanicInformation *res = NULL;
-
- if (cc->get_crash_info) {
- res = cc->get_crash_info(cpu);
- }
- return res;
-}
-#endif
-
void cpu_dump_state(CPUState *cpu, FILE *f, int flags)
{
CPUClass *cc = CPU_GET_CLASS(cpu);
@@ -398,15 +289,8 @@ static void cpu_class_init(ObjectClass *klass, void *data)
k->parse_features = cpu_common_parse_features;
k->get_arch_id = cpu_common_get_arch_id;
k->has_work = cpu_common_has_work;
- k->get_paging_enabled = cpu_common_get_paging_enabled;
- k->get_memory_mapping = cpu_common_get_memory_mapping;
- k->write_elf32_qemunote = cpu_common_write_elf32_qemunote;
- k->write_elf32_note = cpu_common_write_elf32_note;
- k->write_elf64_qemunote = cpu_common_write_elf64_qemunote;
- k->write_elf64_note = cpu_common_write_elf64_note;
k->gdb_read_register = cpu_common_gdb_read_register;
k->gdb_write_register = cpu_common_gdb_write_register;
- k->virtio_is_big_endian = cpu_common_virtio_is_big_endian;
set_bit(DEVICE_CATEGORY_CPU, dc->categories);
dc->realize = cpu_common_realizefn;
dc->unrealize = cpu_common_unrealizefn;
diff --git a/hw/core/cpu-sysemu.c b/hw/core/cpu-sysemu.c
new file mode 100644
index 0000000000..00253f8929
--- /dev/null
+++ b/hw/core/cpu-sysemu.c
@@ -0,0 +1,145 @@
+/*
+ * QEMU CPU model (system emulation specific)
+ *
+ * Copyright (c) 2012-2014 SUSE LINUX Products 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/gpl-2.0.html>
+ */
+
+#include "qemu/osdep.h"
+#include "qapi/error.h"
+#include "hw/core/cpu.h"
+#include "hw/core/sysemu-cpu-ops.h"
+
+bool cpu_paging_enabled(const CPUState *cpu)
+{
+ CPUClass *cc = CPU_GET_CLASS(cpu);
+
+ if (cc->sysemu_ops->get_paging_enabled) {
+ return cc->sysemu_ops->get_paging_enabled(cpu);
+ }
+
+ return false;
+}
+
+void cpu_get_memory_mapping(CPUState *cpu, MemoryMappingList *list,
+ Error **errp)
+{
+ CPUClass *cc = CPU_GET_CLASS(cpu);
+
+ if (cc->sysemu_ops->get_memory_mapping) {
+ cc->sysemu_ops->get_memory_mapping(cpu, list, errp);
+ return;
+ }
+
+ error_setg(errp, "Obtaining memory mappings is unsupported on this CPU.");
+}
+
+hwaddr cpu_get_phys_page_attrs_debug(CPUState *cpu, vaddr addr,
+ MemTxAttrs *attrs)
+{
+ CPUClass *cc = CPU_GET_CLASS(cpu);
+
+ if (cc->sysemu_ops->get_phys_page_attrs_debug) {
+ return cc->sysemu_ops->get_phys_page_attrs_debug(cpu, addr, attrs);
+ }
+ /* Fallback for CPUs which don't implement the _attrs_ hook */
+ *attrs = MEMTXATTRS_UNSPECIFIED;
+ return cc->sysemu_ops->get_phys_page_debug(cpu, addr);
+}
+
+hwaddr cpu_get_phys_page_debug(CPUState *cpu, vaddr addr)
+{
+ MemTxAttrs attrs = {};
+
+ return cpu_get_phys_page_attrs_debug(cpu, addr, &attrs);
+}
+
+int cpu_asidx_from_attrs(CPUState *cpu, MemTxAttrs attrs)
+{
+ CPUClass *cc = CPU_GET_CLASS(cpu);
+ int ret = 0;
+
+ if (cc->sysemu_ops->asidx_from_attrs) {
+ ret = cc->sysemu_ops->asidx_from_attrs(cpu, attrs);
+ assert(ret < cpu->num_ases && ret >= 0);
+ }
+ return ret;
+}
+
+int cpu_write_elf32_qemunote(WriteCoreDumpFunction f, CPUState *cpu,
+ void *opaque)
+{
+ CPUClass *cc = CPU_GET_CLASS(cpu);
+
+ if (!cc->sysemu_ops->write_elf32_qemunote) {
+ return 0;
+ }
+ return (*cc->sysemu_ops->write_elf32_qemunote)(f, cpu, opaque);
+}
+
+int cpu_write_elf32_note(WriteCoreDumpFunction f, CPUState *cpu,
+ int cpuid, void *opaque)
+{
+ CPUClass *cc = CPU_GET_CLASS(cpu);
+
+ if (!cc->sysemu_ops->write_elf32_note) {
+ return -1;
+ }
+ return (*cc->sysemu_ops->write_elf32_note)(f, cpu, cpuid, opaque);
+}
+
+int cpu_write_elf64_qemunote(WriteCoreDumpFunction f, CPUState *cpu,
+ void *opaque)
+{
+ CPUClass *cc = CPU_GET_CLASS(cpu);
+
+ if (!cc->sysemu_ops->write_elf64_qemunote) {
+ return 0;
+ }
+ return (*cc->sysemu_ops->write_elf64_qemunote)(f, cpu, opaque);
+}
+
+int cpu_write_elf64_note(WriteCoreDumpFunction f, CPUState *cpu,
+ int cpuid, void *opaque)
+{
+ CPUClass *cc = CPU_GET_CLASS(cpu);
+
+ if (!cc->sysemu_ops->write_elf64_note) {
+ return -1;
+ }
+ return (*cc->sysemu_ops->write_elf64_note)(f, cpu, cpuid, opaque);
+}
+
+bool cpu_virtio_is_big_endian(CPUState *cpu)
+{
+ CPUClass *cc = CPU_GET_CLASS(cpu);
+
+ if (cc->sysemu_ops->virtio_is_big_endian) {
+ return cc->sysemu_ops->virtio_is_big_endian(cpu);
+ }
+ return target_words_bigendian();
+}
+
+GuestPanicInformation *cpu_get_crash_info(CPUState *cpu)
+{
+ CPUClass *cc = CPU_GET_CLASS(cpu);
+ GuestPanicInformation *res = NULL;
+
+ if (cc->sysemu_ops->get_crash_info) {
+ res = cc->sysemu_ops->get_crash_info(cpu);
+ }
+ return res;
+}
diff --git a/hw/core/meson.build b/hw/core/meson.build
index 59f1605bb0..18f44fb7c2 100644
--- a/hw/core/meson.build
+++ b/hw/core/meson.build
@@ -13,7 +13,7 @@ hwcore_files = files(
'qdev-clock.c',
)
-common_ss.add(files('cpu.c'))
+common_ss.add(files('cpu-common.c'))
common_ss.add(when: 'CONFIG_FITLOADER', if_true: files('loader-fit.c'))
common_ss.add(when: 'CONFIG_GENERIC_LOADER', if_true: files('generic-loader.c'))
common_ss.add(when: ['CONFIG_GUEST_LOADER', fdt], if_true: files('guest-loader.c'))
@@ -25,6 +25,7 @@ common_ss.add(when: 'CONFIG_SPLIT_IRQ', if_true: files('split-irq.c'))
common_ss.add(when: 'CONFIG_XILINX_AXI', if_true: files('stream.c'))
softmmu_ss.add(files(
+ 'cpu-sysemu.c',
'fw-path-provider.c',
'loader.c',
'machine-hmp-cmds.c',
diff --git a/hw/i386/Kconfig b/hw/i386/Kconfig
index 7f91f30877..66838fa397 100644
--- a/hw/i386/Kconfig
+++ b/hw/i386/Kconfig
@@ -23,6 +23,7 @@ config PC
imply TPM_TIS_ISA
imply VGA_PCI
imply VIRTIO_VGA
+ imply NVDIMM
select FDC
select I8259
select I8254
diff --git a/hw/mem/Kconfig b/hw/mem/Kconfig
index a0ef2cf648..8b19fdc49f 100644
--- a/hw/mem/Kconfig
+++ b/hw/mem/Kconfig
@@ -7,6 +7,4 @@ config MEM_DEVICE
config NVDIMM
bool
- default y
- depends on (PC || PSERIES || ARM_VIRT)
select MEM_DEVICE
diff --git a/hw/mips/jazz.c b/hw/mips/jazz.c
index dba2088ed1..1e1cf8154e 100644
--- a/hw/mips/jazz.c
+++ b/hw/mips/jazz.c
@@ -119,30 +119,6 @@ static const MemoryRegionOps dma_dummy_ops = {
#define MAGNUM_BIOS_SIZE \
(BIOS_SIZE < MAGNUM_BIOS_SIZE_MAX ? BIOS_SIZE : MAGNUM_BIOS_SIZE_MAX)
-#if defined(CONFIG_TCG) && !defined(CONFIG_USER_ONLY)
-static void (*real_do_transaction_failed)(CPUState *cpu, hwaddr physaddr,
- vaddr addr, unsigned size,
- MMUAccessType access_type,
- int mmu_idx, MemTxAttrs attrs,
- MemTxResult response,
- uintptr_t retaddr);
-
-static void mips_jazz_do_transaction_failed(CPUState *cs, hwaddr physaddr,
- vaddr addr, unsigned size,
- MMUAccessType access_type,
- int mmu_idx, MemTxAttrs attrs,
- MemTxResult response,
- uintptr_t retaddr)
-{
- if (access_type != MMU_INST_FETCH) {
- /* ignore invalid access (ie do not raise exception) */
- return;
- }
- (*real_do_transaction_failed)(cs, physaddr, addr, size, access_type,
- mmu_idx, attrs, response, retaddr);
-}
-#endif /* CONFIG_TCG && !CONFIG_USER_ONLY */
-
static void mips_jazz_init(MachineState *machine,
enum jazz_model_e jazz_model)
{
@@ -151,7 +127,7 @@ static void mips_jazz_init(MachineState *machine,
int bios_size, n;
Clock *cpuclk;
MIPSCPU *cpu;
- CPUClass *cc;
+ MIPSCPUClass *mcc;
CPUMIPSState *env;
qemu_irq *i8259;
rc4030_dma *dmas;
@@ -198,8 +174,6 @@ static void mips_jazz_init(MachineState *machine,
* However, we can't simply add a global memory region to catch
* everything, as this would make all accesses including instruction
* accesses be ignored and not raise exceptions.
- * So instead we hijack the do_transaction_failed method on the CPU, and
- * do not raise exceptions for data access.
*
* NOTE: this behaviour of raising exceptions for bad instruction
* fetches but not bad data accesses was added in commit 54e755588cf1e9
@@ -209,11 +183,8 @@ static void mips_jazz_init(MachineState *machine,
* we could replace this hijacking of CPU methods with a simple global
* memory region that catches all memory accesses, as we do on Malta.
*/
- cc = CPU_GET_CLASS(cpu);
-#if defined(CONFIG_TCG) && !defined(CONFIG_USER_ONLY)
- real_do_transaction_failed = cc->tcg_ops->do_transaction_failed;
- cc->tcg_ops->do_transaction_failed = mips_jazz_do_transaction_failed;
-#endif /* CONFIG_TCG && !CONFIG_USER_ONLY */
+ mcc = MIPS_CPU_GET_CLASS(cpu);
+ mcc->no_data_aborts = true;
/* allocate RAM */
memory_region_add_subregion(address_space, 0, machine->ram);
diff --git a/hw/net/imx_fec.c b/hw/net/imx_fec.c
index f03450c028..9c7035bc94 100644
--- a/hw/net/imx_fec.c
+++ b/hw/net/imx_fec.c
@@ -283,9 +283,8 @@ static uint32_t imx_phy_read(IMXFECState *s, int reg)
uint32_t phy = reg / 32;
if (phy != s->phy_num) {
- qemu_log_mask(LOG_GUEST_ERROR, "[%s.phy]%s: Bad phy num %u\n",
- TYPE_IMX_FEC, __func__, phy);
- return 0;
+ trace_imx_phy_read_num(phy, s->phy_num);
+ return 0xffff;
}
reg %= 32;
@@ -345,8 +344,7 @@ static void imx_phy_write(IMXFECState *s, int reg, uint32_t val)
uint32_t phy = reg / 32;
if (phy != s->phy_num) {
- qemu_log_mask(LOG_GUEST_ERROR, "[%s.phy]%s: Bad phy num %u\n",
- TYPE_IMX_FEC, __func__, phy);
+ trace_imx_phy_write_num(phy, s->phy_num);
return;
}
diff --git a/hw/net/trace-events b/hw/net/trace-events
index 314e21fa99..1704bb0664 100644
--- a/hw/net/trace-events
+++ b/hw/net/trace-events
@@ -402,7 +402,9 @@ i82596_channel_attention(void *s) "%p: Received CHANNEL ATTENTION"
# imx_fec.c
imx_phy_read(uint32_t val, int phy, int reg) "0x%04"PRIx32" <= phy[%d].reg[%d]"
+imx_phy_read_num(int phy, int configured) "read request from unconfigured phy %d (configured %d)"
imx_phy_write(uint32_t val, int phy, int reg) "0x%04"PRIx32" => phy[%d].reg[%d]"
+imx_phy_write_num(int phy, int configured) "write request to unconfigured phy %d (configured %d)"
imx_phy_update_link(const char *s) "%s"
imx_phy_reset(void) ""
imx_fec_read_bd(uint64_t addr, int flags, int len, int data) "tx_bd 0x%"PRIx64" flags 0x%04x len %d data 0x%08x"
diff --git a/hw/net/virtio-net.c b/hw/net/virtio-net.c
index 6b7e8dd04e..05bd50d3f6 100644
--- a/hw/net/virtio-net.c
+++ b/hw/net/virtio-net.c
@@ -3373,6 +3373,7 @@ static void virtio_net_device_unrealize(DeviceState *dev)
if (n->failover) {
device_listener_unregister(&n->primary_listener);
+ remove_migration_state_change_notifier(&n->migration_state);
}
max_queues = n->multiqueue ? n->max_queues : 1;
diff --git a/hw/ppc/Kconfig b/hw/ppc/Kconfig
index e51e0e5e5a..66e0b15d9e 100644
--- a/hw/ppc/Kconfig
+++ b/hw/ppc/Kconfig
@@ -3,6 +3,7 @@ config PSERIES
imply PCI_DEVICES
imply TEST_DEVICES
imply VIRTIO_VGA
+ imply NVDIMM
select DIMM
select PCI
select SPAPR_VSCSI
diff --git a/hw/scsi/scsi-disk.c b/hw/scsi/scsi-disk.c
index 3580e7ee61..e8a547dbb7 100644
--- a/hw/scsi/scsi-disk.c
+++ b/hw/scsi/scsi-disk.c
@@ -1582,6 +1582,7 @@ invalid_field:
scsi_check_condition(r, SENSE_CODE(INVALID_FIELD));
}
+/* sector_num and nb_sectors expected to be in qdev blocksize */
static inline bool check_lba_range(SCSIDiskState *s,
uint64_t sector_num, uint32_t nb_sectors)
{
@@ -1614,11 +1615,12 @@ static void scsi_unmap_complete_noio(UnmapCBData *data, int ret)
assert(r->req.aiocb == NULL);
if (data->count > 0) {
- r->sector = ldq_be_p(&data->inbuf[0])
- * (s->qdev.blocksize / BDRV_SECTOR_SIZE);
- r->sector_count = (ldl_be_p(&data->inbuf[8]) & 0xffffffffULL)
- * (s->qdev.blocksize / BDRV_SECTOR_SIZE);
- if (!check_lba_range(s, r->sector, r->sector_count)) {
+ uint64_t sector_num = ldq_be_p(&data->inbuf[0]);
+ uint32_t nb_sectors = ldl_be_p(&data->inbuf[8]) & 0xffffffffULL;
+ r->sector = sector_num * (s->qdev.blocksize / BDRV_SECTOR_SIZE);
+ r->sector_count = nb_sectors * (s->qdev.blocksize / BDRV_SECTOR_SIZE);
+
+ if (!check_lba_range(s, sector_num, nb_sectors)) {
block_acct_invalid(blk_get_stats(s->qdev.conf.blk),
BLOCK_ACCT_UNMAP);
scsi_check_condition(r, SENSE_CODE(LBA_OUT_OF_RANGE));
diff --git a/hw/virtio/virtio.c b/hw/virtio/virtio.c
index e02544b2df..ab516ac614 100644
--- a/hw/virtio/virtio.c
+++ b/hw/virtio/virtio.c
@@ -1972,9 +1972,7 @@ static enum virtio_device_endian virtio_default_endian(void)
static enum virtio_device_endian virtio_current_cpu_endian(void)
{
- CPUClass *cc = CPU_GET_CLASS(current_cpu);
-
- if (cc->virtio_is_big_endian(current_cpu)) {
+ if (cpu_virtio_is_big_endian(current_cpu)) {
return VIRTIO_DEVICE_ENDIAN_BIG;
} else {
return VIRTIO_DEVICE_ENDIAN_LITTLE;
diff --git a/replication.h b/include/block/replication.h
index d49fc22cb9..21931b4f0c 100644
--- a/replication.h
+++ b/include/block/replication.h
@@ -23,7 +23,7 @@ typedef struct ReplicationOps ReplicationOps;
typedef struct ReplicationState ReplicationState;
/**
- * SECTION:replication.h
+ * SECTION:block/replication.h
* @title:Base Replication System
* @short_description: interfaces for handling replication
*
@@ -32,7 +32,7 @@ typedef struct ReplicationState ReplicationState;
* <example>
* <title>How to use replication interfaces</title>
* <programlisting>
- * #include "replication.h"
+ * #include "block/replication.h"
*
* typedef struct BDRVReplicationState {
* ReplicationState *rs;
diff --git a/include/exec/exec-all.h b/include/exec/exec-all.h
index 8021adf38f..754f4130c9 100644
--- a/include/exec/exec-all.h
+++ b/include/exec/exec-all.h
@@ -21,7 +21,6 @@
#define EXEC_ALL_H
#include "cpu.h"
-#include "exec/tb-context.h"
#ifdef CONFIG_TCG
#include "exec/cpu_ldst.h"
#endif
diff --git a/include/exec/memory.h b/include/exec/memory.h
index c8b9088924..c158fd7084 100644
--- a/include/exec/memory.h
+++ b/include/exec/memory.h
@@ -617,6 +617,18 @@ struct MemoryListener {
void (*log_sync)(MemoryListener *listener, MemoryRegionSection *section);
/**
+ * @log_sync_global:
+ *
+ * This is the global version of @log_sync when the listener does
+ * not have a way to synchronize the log with finer granularity.
+ * When the listener registers with @log_sync_global defined, then
+ * its @log_sync must be NULL. Vice versa.
+ *
+ * @listener: The #MemoryListener.
+ */
+ void (*log_sync_global)(MemoryListener *listener);
+
+ /**
* @log_clear:
*
* Called before reading the dirty memory bitmap for a
@@ -2305,7 +2317,7 @@ static inline uint8_t address_space_ldub_cached(MemoryRegionCache *cache,
}
static inline void address_space_stb_cached(MemoryRegionCache *cache,
- hwaddr addr, uint32_t val, MemTxAttrs attrs, MemTxResult *result)
+ hwaddr addr, uint8_t val, MemTxAttrs attrs, MemTxResult *result)
{
assert(addr < cache->len);
if (likely(cache->ptr)) {
diff --git a/include/exec/memory_ldst.h.inc b/include/exec/memory_ldst.h.inc
index 46e6c220d3..7c3a641f7e 100644
--- a/include/exec/memory_ldst.h.inc
+++ b/include/exec/memory_ldst.h.inc
@@ -20,7 +20,7 @@
*/
#ifdef TARGET_ENDIANNESS
-extern uint32_t glue(address_space_lduw, SUFFIX)(ARG1_DECL,
+extern uint16_t glue(address_space_lduw, SUFFIX)(ARG1_DECL,
hwaddr addr, MemTxAttrs attrs, MemTxResult *result);
extern uint32_t glue(address_space_ldl, SUFFIX)(ARG1_DECL,
hwaddr addr, MemTxAttrs attrs, MemTxResult *result);
@@ -29,17 +29,17 @@ extern uint64_t glue(address_space_ldq, SUFFIX)(ARG1_DECL,
extern void glue(address_space_stl_notdirty, SUFFIX)(ARG1_DECL,
hwaddr addr, uint32_t val, MemTxAttrs attrs, MemTxResult *result);
extern void glue(address_space_stw, SUFFIX)(ARG1_DECL,
- hwaddr addr, uint32_t val, MemTxAttrs attrs, MemTxResult *result);
+ hwaddr addr, uint16_t val, MemTxAttrs attrs, MemTxResult *result);
extern void glue(address_space_stl, SUFFIX)(ARG1_DECL,
hwaddr addr, uint32_t val, MemTxAttrs attrs, MemTxResult *result);
extern void glue(address_space_stq, SUFFIX)(ARG1_DECL,
hwaddr addr, uint64_t val, MemTxAttrs attrs, MemTxResult *result);
#else
-extern uint32_t glue(address_space_ldub, SUFFIX)(ARG1_DECL,
+extern uint8_t glue(address_space_ldub, SUFFIX)(ARG1_DECL,
hwaddr addr, MemTxAttrs attrs, MemTxResult *result);
-extern uint32_t glue(address_space_lduw_le, SUFFIX)(ARG1_DECL,
+extern uint16_t glue(address_space_lduw_le, SUFFIX)(ARG1_DECL,
hwaddr addr, MemTxAttrs attrs, MemTxResult *result);
-extern uint32_t glue(address_space_lduw_be, SUFFIX)(ARG1_DECL,
+extern uint16_t glue(address_space_lduw_be, SUFFIX)(ARG1_DECL,
hwaddr addr, MemTxAttrs attrs, MemTxResult *result);
extern uint32_t glue(address_space_ldl_le, SUFFIX)(ARG1_DECL,
hwaddr addr, MemTxAttrs attrs, MemTxResult *result);
@@ -50,11 +50,11 @@ extern uint64_t glue(address_space_ldq_le, SUFFIX)(ARG1_DECL,
extern uint64_t glue(address_space_ldq_be, SUFFIX)(ARG1_DECL,
hwaddr addr, MemTxAttrs attrs, MemTxResult *result);
extern void glue(address_space_stb, SUFFIX)(ARG1_DECL,
- hwaddr addr, uint32_t val, MemTxAttrs attrs, MemTxResult *result);
+ hwaddr addr, uint8_t val, MemTxAttrs attrs, MemTxResult *result);
extern void glue(address_space_stw_le, SUFFIX)(ARG1_DECL,
- hwaddr addr, uint32_t val, MemTxAttrs attrs, MemTxResult *result);
+ hwaddr addr, uint16_t val, MemTxAttrs attrs, MemTxResult *result);
extern void glue(address_space_stw_be, SUFFIX)(ARG1_DECL,
- hwaddr addr, uint32_t val, MemTxAttrs attrs, MemTxResult *result);
+ hwaddr addr, uint16_t val, MemTxAttrs attrs, MemTxResult *result);
extern void glue(address_space_stl_le, SUFFIX)(ARG1_DECL,
hwaddr addr, uint32_t val, MemTxAttrs attrs, MemTxResult *result);
extern void glue(address_space_stl_be, SUFFIX)(ARG1_DECL,
diff --git a/include/exec/memory_ldst_cached.h.inc b/include/exec/memory_ldst_cached.h.inc
index 7bc8790d34..d7834f852c 100644
--- a/include/exec/memory_ldst_cached.h.inc
+++ b/include/exec/memory_ldst_cached.h.inc
@@ -24,6 +24,18 @@
#define LD_P(size) \
glue(glue(ld, size), glue(ENDIANNESS, _p))
+static inline uint16_t ADDRESS_SPACE_LD_CACHED(uw)(MemoryRegionCache *cache,
+ hwaddr addr, MemTxAttrs attrs, MemTxResult *result)
+{
+ assert(addr < cache->len && 2 <= cache->len - addr);
+ fuzz_dma_read_cb(cache->xlat + addr, 2, cache->mrs.mr);
+ if (likely(cache->ptr)) {
+ return LD_P(uw)(cache->ptr + addr);
+ } else {
+ return ADDRESS_SPACE_LD_CACHED_SLOW(uw)(cache, addr, attrs, result);
+ }
+}
+
static inline uint32_t ADDRESS_SPACE_LD_CACHED(l)(MemoryRegionCache *cache,
hwaddr addr, MemTxAttrs attrs, MemTxResult *result)
{
@@ -48,18 +60,6 @@ static inline uint64_t ADDRESS_SPACE_LD_CACHED(q)(MemoryRegionCache *cache,
}
}
-static inline uint32_t ADDRESS_SPACE_LD_CACHED(uw)(MemoryRegionCache *cache,
- hwaddr addr, MemTxAttrs attrs, MemTxResult *result)
-{
- assert(addr < cache->len && 2 <= cache->len - addr);
- fuzz_dma_read_cb(cache->xlat + addr, 2, cache->mrs.mr);
- if (likely(cache->ptr)) {
- return LD_P(uw)(cache->ptr + addr);
- } else {
- return ADDRESS_SPACE_LD_CACHED_SLOW(uw)(cache, addr, attrs, result);
- }
-}
-
#undef ADDRESS_SPACE_LD_CACHED
#undef ADDRESS_SPACE_LD_CACHED_SLOW
#undef LD_P
@@ -71,25 +71,25 @@ static inline uint32_t ADDRESS_SPACE_LD_CACHED(uw)(MemoryRegionCache *cache,
#define ST_P(size) \
glue(glue(st, size), glue(ENDIANNESS, _p))
-static inline void ADDRESS_SPACE_ST_CACHED(l)(MemoryRegionCache *cache,
- hwaddr addr, uint32_t val, MemTxAttrs attrs, MemTxResult *result)
+static inline void ADDRESS_SPACE_ST_CACHED(w)(MemoryRegionCache *cache,
+ hwaddr addr, uint16_t val, MemTxAttrs attrs, MemTxResult *result)
{
- assert(addr < cache->len && 4 <= cache->len - addr);
+ assert(addr < cache->len && 2 <= cache->len - addr);
if (likely(cache->ptr)) {
- ST_P(l)(cache->ptr + addr, val);
+ ST_P(w)(cache->ptr + addr, val);
} else {
- ADDRESS_SPACE_ST_CACHED_SLOW(l)(cache, addr, val, attrs, result);
+ ADDRESS_SPACE_ST_CACHED_SLOW(w)(cache, addr, val, attrs, result);
}
}
-static inline void ADDRESS_SPACE_ST_CACHED(w)(MemoryRegionCache *cache,
+static inline void ADDRESS_SPACE_ST_CACHED(l)(MemoryRegionCache *cache,
hwaddr addr, uint32_t val, MemTxAttrs attrs, MemTxResult *result)
{
- assert(addr < cache->len && 2 <= cache->len - addr);
+ assert(addr < cache->len && 4 <= cache->len - addr);
if (likely(cache->ptr)) {
- ST_P(w)(cache->ptr + addr, val);
+ ST_P(l)(cache->ptr + addr, val);
} else {
- ADDRESS_SPACE_ST_CACHED_SLOW(w)(cache, addr, val, attrs, result);
+ ADDRESS_SPACE_ST_CACHED_SLOW(l)(cache, addr, val, attrs, result);
}
}
diff --git a/include/exec/memory_ldst_phys.h.inc b/include/exec/memory_ldst_phys.h.inc
index b9dd53c389..ecd678610d 100644
--- a/include/exec/memory_ldst_phys.h.inc
+++ b/include/exec/memory_ldst_phys.h.inc
@@ -20,6 +20,12 @@
*/
#ifdef TARGET_ENDIANNESS
+static inline uint16_t glue(lduw_phys, SUFFIX)(ARG1_DECL, hwaddr addr)
+{
+ return glue(address_space_lduw, SUFFIX)(ARG1, addr,
+ MEMTXATTRS_UNSPECIFIED, NULL);
+}
+
static inline uint32_t glue(ldl_phys, SUFFIX)(ARG1_DECL, hwaddr addr)
{
return glue(address_space_ldl, SUFFIX)(ARG1, addr,
@@ -32,10 +38,10 @@ static inline uint64_t glue(ldq_phys, SUFFIX)(ARG1_DECL, hwaddr addr)
MEMTXATTRS_UNSPECIFIED, NULL);
}
-static inline uint32_t glue(lduw_phys, SUFFIX)(ARG1_DECL, hwaddr addr)
+static inline void glue(stw_phys, SUFFIX)(ARG1_DECL, hwaddr addr, uint16_t val)
{
- return glue(address_space_lduw, SUFFIX)(ARG1, addr,
- MEMTXATTRS_UNSPECIFIED, NULL);
+ glue(address_space_stw, SUFFIX)(ARG1, addr, val,
+ MEMTXATTRS_UNSPECIFIED, NULL);
}
static inline void glue(stl_phys, SUFFIX)(ARG1_DECL, hwaddr addr, uint32_t val)
@@ -44,18 +50,30 @@ static inline void glue(stl_phys, SUFFIX)(ARG1_DECL, hwaddr addr, uint32_t val)
MEMTXATTRS_UNSPECIFIED, NULL);
}
-static inline void glue(stw_phys, SUFFIX)(ARG1_DECL, hwaddr addr, uint32_t val)
-{
- glue(address_space_stw, SUFFIX)(ARG1, addr, val,
- MEMTXATTRS_UNSPECIFIED, NULL);
-}
-
static inline void glue(stq_phys, SUFFIX)(ARG1_DECL, hwaddr addr, uint64_t val)
{
glue(address_space_stq, SUFFIX)(ARG1, addr, val,
MEMTXATTRS_UNSPECIFIED, NULL);
}
#else
+static inline uint8_t glue(ldub_phys, SUFFIX)(ARG1_DECL, hwaddr addr)
+{
+ return glue(address_space_ldub, SUFFIX)(ARG1, addr,
+ MEMTXATTRS_UNSPECIFIED, NULL);
+}
+
+static inline uint16_t glue(lduw_le_phys, SUFFIX)(ARG1_DECL, hwaddr addr)
+{
+ return glue(address_space_lduw_le, SUFFIX)(ARG1, addr,
+ MEMTXATTRS_UNSPECIFIED, NULL);
+}
+
+static inline uint16_t glue(lduw_be_phys, SUFFIX)(ARG1_DECL, hwaddr addr)
+{
+ return glue(address_space_lduw_be, SUFFIX)(ARG1, addr,
+ MEMTXATTRS_UNSPECIFIED, NULL);
+}
+
static inline uint32_t glue(ldl_le_phys, SUFFIX)(ARG1_DECL, hwaddr addr)
{
return glue(address_space_ldl_le, SUFFIX)(ARG1, addr,
@@ -80,22 +98,22 @@ static inline uint64_t glue(ldq_be_phys, SUFFIX)(ARG1_DECL, hwaddr addr)
MEMTXATTRS_UNSPECIFIED, NULL);
}
-static inline uint32_t glue(ldub_phys, SUFFIX)(ARG1_DECL, hwaddr addr)
+static inline void glue(stb_phys, SUFFIX)(ARG1_DECL, hwaddr addr, uint8_t val)
{
- return glue(address_space_ldub, SUFFIX)(ARG1, addr,
- MEMTXATTRS_UNSPECIFIED, NULL);
+ glue(address_space_stb, SUFFIX)(ARG1, addr, val,
+ MEMTXATTRS_UNSPECIFIED, NULL);
}
-static inline uint32_t glue(lduw_le_phys, SUFFIX)(ARG1_DECL, hwaddr addr)
+static inline void glue(stw_le_phys, SUFFIX)(ARG1_DECL, hwaddr addr, uint16_t val)
{
- return glue(address_space_lduw_le, SUFFIX)(ARG1, addr,
- MEMTXATTRS_UNSPECIFIED, NULL);
+ glue(address_space_stw_le, SUFFIX)(ARG1, addr, val,
+ MEMTXATTRS_UNSPECIFIED, NULL);
}
-static inline uint32_t glue(lduw_be_phys, SUFFIX)(ARG1_DECL, hwaddr addr)
+static inline void glue(stw_be_phys, SUFFIX)(ARG1_DECL, hwaddr addr, uint16_t val)
{
- return glue(address_space_lduw_be, SUFFIX)(ARG1, addr,
- MEMTXATTRS_UNSPECIFIED, NULL);
+ glue(address_space_stw_be, SUFFIX)(ARG1, addr, val,
+ MEMTXATTRS_UNSPECIFIED, NULL);
}
static inline void glue(stl_le_phys, SUFFIX)(ARG1_DECL, hwaddr addr, uint32_t val)
@@ -110,24 +128,6 @@ static inline void glue(stl_be_phys, SUFFIX)(ARG1_DECL, hwaddr addr, uint32_t va
MEMTXATTRS_UNSPECIFIED, NULL);
}
-static inline void glue(stb_phys, SUFFIX)(ARG1_DECL, hwaddr addr, uint32_t val)
-{
- glue(address_space_stb, SUFFIX)(ARG1, addr, val,
- MEMTXATTRS_UNSPECIFIED, NULL);
-}
-
-static inline void glue(stw_le_phys, SUFFIX)(ARG1_DECL, hwaddr addr, uint32_t val)
-{
- glue(address_space_stw_le, SUFFIX)(ARG1, addr, val,
- MEMTXATTRS_UNSPECIFIED, NULL);
-}
-
-static inline void glue(stw_be_phys, SUFFIX)(ARG1_DECL, hwaddr addr, uint32_t val)
-{
- glue(address_space_stw_be, SUFFIX)(ARG1, addr, val,
- MEMTXATTRS_UNSPECIFIED, NULL);
-}
-
static inline void glue(stq_le_phys, SUFFIX)(ARG1_DECL, hwaddr addr, uint64_t val)
{
glue(address_space_stq_le, SUFFIX)(ARG1, addr, val,
diff --git a/include/hw/core/cpu.h b/include/hw/core/cpu.h
index d45f78290e..044f668a6e 100644
--- a/include/hw/core/cpu.h
+++ b/include/hw/core/cpu.h
@@ -80,6 +80,9 @@ struct TCGCPUOps;
/* see accel-cpu.h */
struct AccelCPUClass;
+/* see sysemu-cpu-ops.h */
+struct SysemuCPUOps;
+
/**
* CPUClass:
* @class_by_name: Callback to map -cpu command line model name to an
@@ -87,16 +90,10 @@ struct AccelCPUClass;
* @parse_features: Callback to parse command line arguments.
* @reset_dump_flags: #CPUDumpFlags to use for reset logging.
* @has_work: Callback for checking if there is work to do.
- * @virtio_is_big_endian: Callback to return %true if a CPU which supports
- * runtime configurable endianness is currently big-endian. Non-configurable
- * CPUs can use the default implementation of this method. This method should
- * not be used by any callers other than the pre-1.0 virtio devices.
* @memory_rw_debug: Callback for GDB memory access.
* @dump_state: Callback for dumping state.
* @dump_statistics: Callback for dumping statistics.
* @get_arch_id: Callback for getting architecture-dependent CPU ID.
- * @get_paging_enabled: Callback for inquiring whether paging is enabled.
- * @get_memory_mapping: Callback for obtaining the memory mappings.
* @set_pc: Callback for setting the Program Counter register. This
* should have the semantics used by the target architecture when
* setting the PC from a source such as an ELF file entry point;
@@ -105,24 +102,8 @@ struct AccelCPUClass;
* If the target behaviour here is anything other than "set
* the PC register to the value passed in" then the target must
* also implement the synchronize_from_tb hook.
- * @get_phys_page_debug: Callback for obtaining a physical address.
- * @get_phys_page_attrs_debug: Callback for obtaining a physical address and the
- * associated memory transaction attributes to use for the access.
- * CPUs which use memory transaction attributes should implement this
- * instead of get_phys_page_debug.
- * @asidx_from_attrs: Callback to return the CPU AddressSpace to use for
- * a memory access with the specified memory transaction attributes.
* @gdb_read_register: Callback for letting GDB read a register.
* @gdb_write_register: Callback for letting GDB write a register.
- * @write_elf64_note: Callback for writing a CPU-specific ELF note to a
- * 64-bit VM coredump.
- * @write_elf32_qemunote: Callback for writing a CPU- and QEMU-specific ELF
- * note to a 32-bit VM coredump.
- * @write_elf32_note: Callback for writing a CPU-specific ELF note to a
- * 32-bit VM coredump.
- * @write_elf32_qemunote: Callback for writing a CPU- and QEMU-specific ELF
- * note to a 32-bit VM coredump.
- * @vmsd: State description for migration.
* @gdb_num_core_regs: Number of core registers accessible to GDB.
* @gdb_core_xml_file: File name for core registers GDB XML description.
* @gdb_stop_before_watchpoint: Indicates whether GDB expects the CPU to stop
@@ -150,34 +131,15 @@ struct CPUClass {
int reset_dump_flags;
bool (*has_work)(CPUState *cpu);
- bool (*virtio_is_big_endian)(CPUState *cpu);
int (*memory_rw_debug)(CPUState *cpu, vaddr addr,
uint8_t *buf, int len, bool is_write);
void (*dump_state)(CPUState *cpu, FILE *, int flags);
- GuestPanicInformation* (*get_crash_info)(CPUState *cpu);
void (*dump_statistics)(CPUState *cpu, int flags);
int64_t (*get_arch_id)(CPUState *cpu);
- bool (*get_paging_enabled)(const CPUState *cpu);
- void (*get_memory_mapping)(CPUState *cpu, MemoryMappingList *list,
- Error **errp);
void (*set_pc)(CPUState *cpu, vaddr value);
- hwaddr (*get_phys_page_debug)(CPUState *cpu, vaddr addr);
- hwaddr (*get_phys_page_attrs_debug)(CPUState *cpu, vaddr addr,
- MemTxAttrs *attrs);
- int (*asidx_from_attrs)(CPUState *cpu, MemTxAttrs attrs);
int (*gdb_read_register)(CPUState *cpu, GByteArray *buf, int reg);
int (*gdb_write_register)(CPUState *cpu, uint8_t *buf, int reg);
- int (*write_elf64_note)(WriteCoreDumpFunction f, CPUState *cpu,
- int cpuid, void *opaque);
- int (*write_elf64_qemunote)(WriteCoreDumpFunction f, CPUState *cpu,
- void *opaque);
- int (*write_elf32_note)(WriteCoreDumpFunction f, CPUState *cpu,
- int cpuid, void *opaque);
- int (*write_elf32_qemunote)(WriteCoreDumpFunction f, CPUState *cpu,
- void *opaque);
-
- const VMStateDescription *vmsd;
const char *gdb_core_xml_file;
gchar * (*gdb_arch_name)(CPUState *cpu);
const char * (*gdb_get_dynamic_xml)(CPUState *cpu, const char *xmlname);
@@ -190,8 +152,11 @@ struct CPUClass {
bool gdb_stop_before_watchpoint;
struct AccelCPUClass *accel_cpu;
+ /* when system emulation is not available, this pointer is NULL */
+ const struct SysemuCPUOps *sysemu_ops;
+
/* when TCG is not available, this pointer is NULL */
- struct TCGCPUOps *tcg_ops;
+ const struct TCGCPUOps *tcg_ops;
/*
* if not NULL, this is called in order for the CPUClass to initialize
@@ -329,6 +294,10 @@ struct qemu_work_item;
* @ignore_memory_transaction_failures: Cached copy of the MachineState
* flag of the same name: allows the board to suppress calling of the
* CPU do_transaction_failed hook function.
+ * @kvm_dirty_gfns: Points to the KVM dirty ring for this CPU when KVM dirty
+ * ring is enabled.
+ * @kvm_fetch_index: Keeps the index that we last fetched from the per-vCPU
+ * dirty ring structure.
*
* State of one CPU core or thread.
*/
@@ -400,9 +369,12 @@ struct CPUState {
*/
uintptr_t mem_io_pc;
+ /* Only used in KVM */
int kvm_fd;
struct KVMState *kvm_state;
struct kvm_run *kvm_run;
+ struct kvm_dirty_gfn *kvm_dirty_gfns;
+ uint32_t kvm_fetch_index;
/* Used for events with 'vcpu' and *without* the 'disabled' properties */
DECLARE_BITMAP(trace_dstate_delayed, CPU_TRACE_DSTATE_MAX_EVENTS);
@@ -586,18 +558,8 @@ void cpu_dump_statistics(CPUState *cpu, int flags);
*
* Returns: Corresponding physical page address or -1 if no page found.
*/
-static inline hwaddr cpu_get_phys_page_attrs_debug(CPUState *cpu, vaddr addr,
- MemTxAttrs *attrs)
-{
- CPUClass *cc = CPU_GET_CLASS(cpu);
-
- if (cc->get_phys_page_attrs_debug) {
- return cc->get_phys_page_attrs_debug(cpu, addr, attrs);
- }
- /* Fallback for CPUs which don't implement the _attrs_ hook */
- *attrs = MEMTXATTRS_UNSPECIFIED;
- return cc->get_phys_page_debug(cpu, addr);
-}
+hwaddr cpu_get_phys_page_attrs_debug(CPUState *cpu, vaddr addr,
+ MemTxAttrs *attrs);
/**
* cpu_get_phys_page_debug:
@@ -609,12 +571,7 @@ static inline hwaddr cpu_get_phys_page_attrs_debug(CPUState *cpu, vaddr addr,
*
* Returns: Corresponding physical page address or -1 if no page found.
*/
-static inline hwaddr cpu_get_phys_page_debug(CPUState *cpu, vaddr addr)
-{
- MemTxAttrs attrs = {};
-
- return cpu_get_phys_page_attrs_debug(cpu, addr, &attrs);
-}
+hwaddr cpu_get_phys_page_debug(CPUState *cpu, vaddr addr);
/** cpu_asidx_from_attrs:
* @cpu: CPU
@@ -623,17 +580,16 @@ static inline hwaddr cpu_get_phys_page_debug(CPUState *cpu, vaddr addr)
* Returns the address space index specifying the CPU AddressSpace
* to use for a memory access with the given transaction attributes.
*/
-static inline int cpu_asidx_from_attrs(CPUState *cpu, MemTxAttrs attrs)
-{
- CPUClass *cc = CPU_GET_CLASS(cpu);
- int ret = 0;
+int cpu_asidx_from_attrs(CPUState *cpu, MemTxAttrs attrs);
- if (cc->asidx_from_attrs) {
- ret = cc->asidx_from_attrs(cpu, attrs);
- assert(ret < cpu->num_ases && ret >= 0);
- }
- return ret;
-}
+/**
+ * cpu_virtio_is_big_endian:
+ * @cpu: CPU
+
+ * Returns %true if a CPU which supports runtime configurable endianness
+ * is currently big-endian.
+ */
+bool cpu_virtio_is_big_endian(CPUState *cpu);
#endif /* CONFIG_USER_ONLY */
@@ -1074,10 +1030,8 @@ bool target_words_bigendian(void);
#ifdef NEED_CPU_H
#ifdef CONFIG_SOFTMMU
+
extern const VMStateDescription vmstate_cpu_common;
-#else
-#define vmstate_cpu_common vmstate_dummy
-#endif
#define VMSTATE_CPU() { \
.name = "parent_obj", \
@@ -1086,6 +1040,7 @@ extern const VMStateDescription vmstate_cpu_common;
.flags = VMS_STRUCT, \
.offset = 0, \
}
+#endif /* CONFIG_SOFTMMU */
#endif /* NEED_CPU_H */
diff --git a/include/hw/core/sysemu-cpu-ops.h b/include/hw/core/sysemu-cpu-ops.h
new file mode 100644
index 0000000000..a9ba39e5f2
--- /dev/null
+++ b/include/hw/core/sysemu-cpu-ops.h
@@ -0,0 +1,92 @@
+/*
+ * CPU operations specific to system emulation
+ *
+ * Copyright (c) 2012 SUSE LINUX Products GmbH
+ *
+ * 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 SYSEMU_CPU_OPS_H
+#define SYSEMU_CPU_OPS_H
+
+#include "hw/core/cpu.h"
+
+/*
+ * struct SysemuCPUOps: System operations specific to a CPU class
+ */
+typedef struct SysemuCPUOps {
+ /**
+ * @get_memory_mapping: Callback for obtaining the memory mappings.
+ */
+ void (*get_memory_mapping)(CPUState *cpu, MemoryMappingList *list,
+ Error **errp);
+ /**
+ * @get_paging_enabled: Callback for inquiring whether paging is enabled.
+ */
+ bool (*get_paging_enabled)(const CPUState *cpu);
+ /**
+ * @get_phys_page_debug: Callback for obtaining a physical address.
+ */
+ hwaddr (*get_phys_page_debug)(CPUState *cpu, vaddr addr);
+ /**
+ * @get_phys_page_attrs_debug: Callback for obtaining a physical address
+ * and the associated memory transaction attributes to use for the
+ * access.
+ * CPUs which use memory transaction attributes should implement this
+ * instead of get_phys_page_debug.
+ */
+ hwaddr (*get_phys_page_attrs_debug)(CPUState *cpu, vaddr addr,
+ MemTxAttrs *attrs);
+ /**
+ * @asidx_from_attrs: Callback to return the CPU AddressSpace to use for
+ * a memory access with the specified memory transaction attributes.
+ */
+ int (*asidx_from_attrs)(CPUState *cpu, MemTxAttrs attrs);
+ /**
+ * @get_crash_info: Callback for reporting guest crash information in
+ * GUEST_PANICKED events.
+ */
+ GuestPanicInformation* (*get_crash_info)(CPUState *cpu);
+ /**
+ * @write_elf32_note: Callback for writing a CPU-specific ELF note to a
+ * 32-bit VM coredump.
+ */
+ int (*write_elf32_note)(WriteCoreDumpFunction f, CPUState *cpu,
+ int cpuid, void *opaque);
+ /**
+ * @write_elf64_note: Callback for writing a CPU-specific ELF note to a
+ * 64-bit VM coredump.
+ */
+ int (*write_elf64_note)(WriteCoreDumpFunction f, CPUState *cpu,
+ int cpuid, void *opaque);
+ /**
+ * @write_elf32_qemunote: Callback for writing a CPU- and QEMU-specific ELF
+ * note to a 32-bit VM coredump.
+ */
+ int (*write_elf32_qemunote)(WriteCoreDumpFunction f, CPUState *cpu,
+ void *opaque);
+ /**
+ * @write_elf64_qemunote: Callback for writing a CPU- and QEMU-specific ELF
+ * note to a 64-bit VM coredump.
+ */
+ int (*write_elf64_qemunote)(WriteCoreDumpFunction f, CPUState *cpu,
+ void *opaque);
+ /**
+ * @virtio_is_big_endian: Callback to return %true if a CPU which supports
+ * runtime configurable endianness is currently big-endian.
+ * Non-configurable CPUs can use the default implementation of this method.
+ * This method should not be used by any callers other than the pre-1.0
+ * virtio devices.
+ */
+ bool (*virtio_is_big_endian)(CPUState *cpu);
+
+ /**
+ * @legacy_vmsd: Legacy state for migration.
+ * Do not use in new targets, use #DeviceClass::vmsd instead.
+ */
+ const VMStateDescription *legacy_vmsd;
+
+} SysemuCPUOps;
+
+#endif /* SYSEMU_CPU_OPS_H */
diff --git a/include/migration/vmstate.h b/include/migration/vmstate.h
index 075ee80096..8df7b69f38 100644
--- a/include/migration/vmstate.h
+++ b/include/migration/vmstate.h
@@ -194,8 +194,6 @@ struct VMStateDescription {
const VMStateDescription **subsections;
};
-extern const VMStateDescription vmstate_dummy;
-
extern const VMStateInfo vmstate_info_bool;
extern const VMStateInfo vmstate_info_int8;
diff --git a/include/qemu/config-file.h b/include/qemu/config-file.h
index 8d3e53ae4d..0500b3668d 100644
--- a/include/qemu/config-file.h
+++ b/include/qemu/config-file.h
@@ -1,7 +1,7 @@
#ifndef QEMU_CONFIG_FILE_H
#define QEMU_CONFIG_FILE_H
-
+void qemu_load_module_for_opts(const char *group);
QemuOptsList *qemu_find_opts(const char *group);
QemuOptsList *qemu_find_opts_err(const char *group, Error **errp);
QemuOpts *qemu_find_opts_singleton(const char *group);
diff --git a/qemu-options.h b/include/qemu/qemu-options.h
index b4ee63cd60..4a62c83c45 100644
--- a/qemu-options.h
+++ b/include/qemu/qemu-options.h
@@ -29,8 +29,13 @@
#define QEMU_OPTIONS_H
enum {
-#define QEMU_OPTIONS_GENERATE_ENUM
-#include "qemu-options-wrapper.h"
+
+#define DEF(option, opt_arg, opt_enum, opt_help, arch_mask) \
+ opt_enum,
+#define DEFHEADING(text)
+#define ARCHHEADING(text, arch_mask)
+
+#include "qemu-options.def"
};
#endif
diff --git a/include/sysemu/kvm_int.h b/include/sysemu/kvm_int.h
index ccb8869f01..c788452cd9 100644
--- a/include/sysemu/kvm_int.h
+++ b/include/sysemu/kvm_int.h
@@ -23,12 +23,15 @@ typedef struct KVMSlot
int old_flags;
/* Dirty bitmap cache for the slot */
unsigned long *dirty_bmap;
+ unsigned long dirty_bmap_size;
+ /* Cache of the address space ID */
+ int as_id;
+ /* Cache of the offset in ram address space */
+ ram_addr_t ram_start_offset;
} KVMSlot;
typedef struct KVMMemoryListener {
MemoryListener listener;
- /* Protects the slots and all inside them */
- QemuMutex slots_lock;
KVMSlot *slots;
int as_id;
} KVMMemoryListener;
diff --git a/include/tcg/tcg.h b/include/tcg/tcg.h
index 0f0695e90d..74cb345308 100644
--- a/include/tcg/tcg.h
+++ b/include/tcg/tcg.h
@@ -27,7 +27,6 @@
#include "cpu.h"
#include "exec/memop.h"
-#include "exec/tb-context.h"
#include "qemu/bitops.h"
#include "qemu/plugin.h"
#include "qemu/queue.h"
diff --git a/memory_ldst.c.inc b/memory_ldst.c.inc
index b56e961967..84b868f294 100644
--- a/memory_ldst.c.inc
+++ b/memory_ldst.c.inc
@@ -157,7 +157,7 @@ uint64_t glue(address_space_ldq_be, SUFFIX)(ARG1_DECL,
DEVICE_BIG_ENDIAN);
}
-uint32_t glue(address_space_ldub, SUFFIX)(ARG1_DECL,
+uint8_t glue(address_space_ldub, SUFFIX)(ARG1_DECL,
hwaddr addr, MemTxAttrs attrs, MemTxResult *result)
{
uint8_t *ptr;
@@ -193,7 +193,7 @@ uint32_t glue(address_space_ldub, SUFFIX)(ARG1_DECL,
}
/* warning: addr must be aligned */
-static inline uint32_t glue(address_space_lduw_internal, SUFFIX)(ARG1_DECL,
+static inline uint16_t glue(address_space_lduw_internal, SUFFIX)(ARG1_DECL,
hwaddr addr, MemTxAttrs attrs, MemTxResult *result,
enum device_endian endian)
{
@@ -240,21 +240,21 @@ static inline uint32_t glue(address_space_lduw_internal, SUFFIX)(ARG1_DECL,
return val;
}
-uint32_t glue(address_space_lduw, SUFFIX)(ARG1_DECL,
+uint16_t glue(address_space_lduw, SUFFIX)(ARG1_DECL,
hwaddr addr, MemTxAttrs attrs, MemTxResult *result)
{
return glue(address_space_lduw_internal, SUFFIX)(ARG1, addr, attrs, result,
DEVICE_NATIVE_ENDIAN);
}
-uint32_t glue(address_space_lduw_le, SUFFIX)(ARG1_DECL,
+uint16_t glue(address_space_lduw_le, SUFFIX)(ARG1_DECL,
hwaddr addr, MemTxAttrs attrs, MemTxResult *result)
{
return glue(address_space_lduw_internal, SUFFIX)(ARG1, addr, attrs, result,
DEVICE_LITTLE_ENDIAN);
}
-uint32_t glue(address_space_lduw_be, SUFFIX)(ARG1_DECL,
+uint16_t glue(address_space_lduw_be, SUFFIX)(ARG1_DECL,
hwaddr addr, MemTxAttrs attrs, MemTxResult *result)
{
return glue(address_space_lduw_internal, SUFFIX)(ARG1, addr, attrs, result,
@@ -366,7 +366,7 @@ void glue(address_space_stl_be, SUFFIX)(ARG1_DECL,
}
void glue(address_space_stb, SUFFIX)(ARG1_DECL,
- hwaddr addr, uint32_t val, MemTxAttrs attrs, MemTxResult *result)
+ hwaddr addr, uint8_t val, MemTxAttrs attrs, MemTxResult *result)
{
uint8_t *ptr;
MemoryRegion *mr;
@@ -398,7 +398,7 @@ void glue(address_space_stb, SUFFIX)(ARG1_DECL,
/* warning: addr must be aligned */
static inline void glue(address_space_stw_internal, SUFFIX)(ARG1_DECL,
- hwaddr addr, uint32_t val, MemTxAttrs attrs,
+ hwaddr addr, uint16_t val, MemTxAttrs attrs,
MemTxResult *result, enum device_endian endian)
{
uint8_t *ptr;
@@ -441,21 +441,21 @@ static inline void glue(address_space_stw_internal, SUFFIX)(ARG1_DECL,
}
void glue(address_space_stw, SUFFIX)(ARG1_DECL,
- hwaddr addr, uint32_t val, MemTxAttrs attrs, MemTxResult *result)
+ hwaddr addr, uint16_t val, MemTxAttrs attrs, MemTxResult *result)
{
glue(address_space_stw_internal, SUFFIX)(ARG1, addr, val, attrs, result,
DEVICE_NATIVE_ENDIAN);
}
void glue(address_space_stw_le, SUFFIX)(ARG1_DECL,
- hwaddr addr, uint32_t val, MemTxAttrs attrs, MemTxResult *result)
+ hwaddr addr, uint16_t val, MemTxAttrs attrs, MemTxResult *result)
{
glue(address_space_stw_internal, SUFFIX)(ARG1, addr, val, attrs, result,
DEVICE_LITTLE_ENDIAN);
}
void glue(address_space_stw_be, SUFFIX)(ARG1_DECL,
- hwaddr addr, uint32_t val, MemTxAttrs attrs, MemTxResult *result)
+ hwaddr addr, uint16_t val, MemTxAttrs attrs, MemTxResult *result)
{
glue(address_space_stw_internal, SUFFIX)(ARG1, addr, val, attrs, result,
DEVICE_BIG_ENDIAN);
diff --git a/meson.build b/meson.build
index 9b6d93b8bb..a45f1a844f 100644
--- a/meson.build
+++ b/meson.build
@@ -2145,6 +2145,7 @@ common_all = common_ss.apply(config_all, strict: false)
common_all = static_library('common',
build_by_default: false,
sources: common_all.sources() + genh,
+ implicit_include_directories: false,
dependencies: common_all.dependencies(),
name_suffix: 'fa')
diff --git a/migration/colo.c b/migration/colo.c
index de27662cab..e498fdb125 100644
--- a/migration/colo.c
+++ b/migration/colo.c
@@ -28,7 +28,7 @@
#include "migration/failover.h"
#include "migration/ram.h"
#ifdef CONFIG_REPLICATION
-#include "replication.h"
+#include "block/replication.h"
#endif
#include "net/colo-compare.h"
#include "net/colo.h"
diff --git a/migration/rdma.c b/migration/rdma.c
index 00eac34232..1cdb4561f3 100644
--- a/migration/rdma.c
+++ b/migration/rdma.c
@@ -36,6 +36,7 @@
#include <rdma/rdma_cma.h>
#include "trace.h"
#include "qom/object.h"
+#include <poll.h>
/*
* Print and error on both the Monitor and the Log file.
@@ -316,6 +317,7 @@ typedef struct RDMALocalBlocks {
typedef struct RDMAContext {
char *host;
int port;
+ char *host_port;
RDMAWorkRequestData wr_data[RDMA_WRID_MAX];
@@ -987,10 +989,12 @@ static int qemu_rdma_resolve_host(RDMAContext *rdma, Error **errp)
}
}
+ rdma_freeaddrinfo(res);
ERROR(errp, "could not resolve address %s", rdma->host);
goto err_resolve_get_addr;
route:
+ rdma_freeaddrinfo(res);
qemu_rdma_dump_gid("source_resolve_addr", rdma->cm_id);
ret = rdma_get_cm_event(rdma->channel, &cm_event);
@@ -2390,7 +2394,9 @@ static void qemu_rdma_cleanup(RDMAContext *rdma)
rdma->channel = NULL;
}
g_free(rdma->host);
+ g_free(rdma->host_port);
rdma->host = NULL;
+ rdma->host_port = NULL;
}
@@ -2455,7 +2461,36 @@ err_rdma_source_init:
return -1;
}
-static int qemu_rdma_connect(RDMAContext *rdma, Error **errp)
+static int qemu_get_cm_event_timeout(RDMAContext *rdma,
+ struct rdma_cm_event **cm_event,
+ long msec, Error **errp)
+{
+ int ret;
+ struct pollfd poll_fd = {
+ .fd = rdma->channel->fd,
+ .events = POLLIN,
+ .revents = 0
+ };
+
+ do {
+ ret = poll(&poll_fd, 1, msec);
+ } while (ret < 0 && errno == EINTR);
+
+ if (ret == 0) {
+ ERROR(errp, "poll cm event timeout");
+ return -1;
+ } else if (ret < 0) {
+ ERROR(errp, "failed to poll cm event, errno=%i", errno);
+ return -1;
+ } else if (poll_fd.revents & POLLIN) {
+ return rdma_get_cm_event(rdma->channel, cm_event);
+ } else {
+ ERROR(errp, "no POLLIN event, revent=%x", poll_fd.revents);
+ return -1;
+ }
+}
+
+static int qemu_rdma_connect(RDMAContext *rdma, Error **errp, bool return_path)
{
RDMACapabilities cap = {
.version = RDMA_CONTROL_VERSION_CURRENT,
@@ -2493,11 +2528,14 @@ static int qemu_rdma_connect(RDMAContext *rdma, Error **errp)
goto err_rdma_source_connect;
}
- ret = rdma_get_cm_event(rdma->channel, &cm_event);
+ if (return_path) {
+ ret = qemu_get_cm_event_timeout(rdma, &cm_event, 5000, errp);
+ } else {
+ ret = rdma_get_cm_event(rdma->channel, &cm_event);
+ }
if (ret) {
perror("rdma_get_cm_event after rdma_connect");
ERROR(errp, "connecting to destination!");
- rdma_ack_cm_event(cm_event);
goto err_rdma_source_connect;
}
@@ -2594,6 +2632,7 @@ static int qemu_rdma_dest_init(RDMAContext *rdma, Error **errp)
break;
}
+ rdma_freeaddrinfo(res);
if (!e) {
ERROR(errp, "Error: could not rdma_bind_addr!");
goto err_dest_init_bind_addr;
@@ -2646,6 +2685,7 @@ static void *qemu_rdma_data_init(const char *host_port, Error **errp)
if (!inet_parse(addr, host_port, NULL)) {
rdma->port = atoi(addr->port);
rdma->host = g_strdup(addr->host);
+ rdma->host_port = g_strdup(host_port);
} else {
ERROR(errp, "bad RDMA migration address '%s'", host_port);
g_free(rdma);
@@ -3274,6 +3314,7 @@ static int qemu_rdma_accept(RDMAContext *rdma)
.private_data = &cap,
.private_data_len = sizeof(cap),
};
+ RDMAContext *rdma_return_path = NULL;
struct rdma_cm_event *cm_event;
struct ibv_context *verbs;
int ret = -EINVAL;
@@ -3289,6 +3330,20 @@ static int qemu_rdma_accept(RDMAContext *rdma)
goto err_rdma_dest_wait;
}
+ /*
+ * initialize the RDMAContext for return path for postcopy after first
+ * connection request reached.
+ */
+ if (migrate_postcopy() && !rdma->is_return_path) {
+ rdma_return_path = qemu_rdma_data_init(rdma->host_port, NULL);
+ if (rdma_return_path == NULL) {
+ rdma_ack_cm_event(cm_event);
+ goto err_rdma_dest_wait;
+ }
+
+ qemu_rdma_return_path_dest_init(rdma_return_path, rdma);
+ }
+
memcpy(&cap, cm_event->param.conn.private_data, sizeof(cap));
network_to_caps(&cap);
@@ -3404,6 +3459,7 @@ static int qemu_rdma_accept(RDMAContext *rdma)
err_rdma_dest_wait:
rdma->error_state = ret;
qemu_rdma_cleanup(rdma);
+ g_free(rdma_return_path);
return ret;
}
@@ -4041,29 +4097,22 @@ void rdma_start_incoming_migration(const char *host_port, Error **errp)
if (ret) {
ERROR(errp, "listening on socket!");
- goto err;
+ goto cleanup_rdma;
}
trace_rdma_start_incoming_migration_after_rdma_listen();
- /* initialize the RDMAContext for return path */
- if (migrate_postcopy()) {
- rdma_return_path = qemu_rdma_data_init(host_port, &local_err);
-
- if (rdma_return_path == NULL) {
- goto err;
- }
-
- qemu_rdma_return_path_dest_init(rdma_return_path, rdma);
- }
-
qemu_set_fd_handler(rdma->channel->fd, rdma_accept_incoming_migration,
NULL, (void *)(intptr_t)rdma);
return;
+
+cleanup_rdma:
+ qemu_rdma_cleanup(rdma);
err:
error_propagate(errp, local_err);
if (rdma) {
g_free(rdma->host);
+ g_free(rdma->host_port);
}
g_free(rdma);
g_free(rdma_return_path);
@@ -4096,7 +4145,7 @@ void rdma_start_outgoing_migration(void *opaque,
}
trace_rdma_start_outgoing_migration_after_rdma_source_init();
- ret = qemu_rdma_connect(rdma, errp);
+ ret = qemu_rdma_connect(rdma, errp, false);
if (ret) {
goto err;
@@ -4117,7 +4166,7 @@ void rdma_start_outgoing_migration(void *opaque,
goto return_path_err;
}
- ret = qemu_rdma_connect(rdma_return_path, errp);
+ ret = qemu_rdma_connect(rdma_return_path, errp, true);
if (ret) {
goto return_path_err;
diff --git a/monitor/hmp-cmds.c b/monitor/hmp-cmds.c
index d9bef63373..d10ee14110 100644
--- a/monitor/hmp-cmds.c
+++ b/monitor/hmp-cmds.c
@@ -1133,7 +1133,7 @@ void hmp_loadvm(Monitor *mon, const QDict *qdict)
vm_stop(RUN_STATE_RESTORE_VM);
- if (!load_snapshot(name, NULL, false, NULL, &err) && saved_vm_running) {
+ if (load_snapshot(name, NULL, false, NULL, &err) && saved_vm_running) {
vm_start();
}
hmp_handle_error(mon, err);
diff --git a/net/tap-bsd.c b/net/tap-bsd.c
index 77aaf674b1..59dfcdfae0 100644
--- a/net/tap-bsd.c
+++ b/net/tap-bsd.c
@@ -35,10 +35,6 @@
#include <net/if_tap.h>
#endif
-#if defined(__OpenBSD__)
-#include <sys/param.h>
-#endif
-
#ifndef __FreeBSD__
int tap_open(char *ifname, int ifname_size, int *vnet_hdr,
int vnet_hdr_required, int mq_required, Error **errp)
@@ -59,11 +55,7 @@ int tap_open(char *ifname, int ifname_size, int *vnet_hdr,
if (*ifname) {
snprintf(dname, sizeof dname, "/dev/%s", ifname);
} else {
-#if defined(__OpenBSD__) && OpenBSD < 201605
- snprintf(dname, sizeof dname, "/dev/tun%d", i);
-#else
snprintf(dname, sizeof dname, "/dev/tap%d", i);
-#endif
}
TFR(fd = open(dname, O_RDWR));
if (fd >= 0) {
diff --git a/os-posix.c b/os-posix.c
index a6846f51c1..ae6c9f2a5e 100644
--- a/os-posix.c
+++ b/os-posix.c
@@ -32,7 +32,7 @@
#include "qemu-common.h"
/* Needed early for CONFIG_BSD etc. */
#include "net/slirp.h"
-#include "qemu-options.h"
+#include "qemu/qemu-options.h"
#include "qemu/error-report.h"
#include "qemu/log.h"
#include "sysemu/runstate.h"
diff --git a/os-win32.c b/os-win32.c
index fd1137bab1..e31c921983 100644
--- a/os-win32.c
+++ b/os-win32.c
@@ -27,7 +27,6 @@
#include <windows.h>
#include <mmsystem.h>
#include "qemu-common.h"
-#include "qemu-options.h"
#include "sysemu/runstate.h"
static BOOL WINAPI qemu_ctrl_handler(DWORD type)
diff --git a/plugins/plugin.h b/plugins/plugin.h
index 1aa29dcadd..55017e3581 100644
--- a/plugins/plugin.h
+++ b/plugins/plugin.h
@@ -13,6 +13,7 @@
#define _PLUGIN_INTERNAL_H_
#include <gmodule.h>
+#include "qemu/qht.h"
#define QEMU_PLUGIN_MIN_VERSION 0
diff --git a/qapi/qom.json b/qapi/qom.json
index 40d70c434a..f7ef30f940 100644
--- a/qapi/qom.json
+++ b/qapi/qom.json
@@ -645,6 +645,21 @@
'data': { 'path': 'str' } }
##
+# @QtestProperties:
+#
+# Properties for qtest objects.
+#
+# @chardev: the chardev to be used to receive qtest commands on.
+#
+# @log: the path to a log file
+#
+# Since: 6.0
+##
+{ 'struct': 'QtestProperties',
+ 'data': { 'chardev': 'str',
+ '*log': 'str' } }
+
+##
# @RemoteObjectProperties:
#
# Properties for x-remote-object objects.
@@ -769,6 +784,7 @@
'memory-backend-ram',
'pef-guest',
'pr-manager-helper',
+ 'qtest',
'rng-builtin',
'rng-egd',
'rng-random',
@@ -825,6 +841,7 @@
'if': 'defined(CONFIG_LINUX)' },
'memory-backend-ram': 'MemoryBackendProperties',
'pr-manager-helper': 'PrManagerHelperProperties',
+ 'qtest': 'QtestProperties',
'rng-builtin': 'RngProperties',
'rng-egd': 'RngEgdProperties',
'rng-random': 'RngRandomProperties',
@@ -857,7 +874,8 @@
# <- { "return": {} }
#
##
-{ 'command': 'object-add', 'data': 'ObjectOptions', 'boxed': true }
+{ 'command': 'object-add', 'data': 'ObjectOptions', 'boxed': true,
+ 'allow-preconfig': true }
##
# @object-del:
@@ -877,4 +895,5 @@
# <- { "return": {} }
#
##
-{ 'command': 'object-del', 'data': {'id': 'str'} }
+{ 'command': 'object-del', 'data': {'id': 'str'},
+ 'allow-preconfig': true }
diff --git a/qemu-options-wrapper.h b/qemu-options-wrapper.h
deleted file mode 100644
index 6f548e3922..0000000000
--- a/qemu-options-wrapper.h
+++ /dev/null
@@ -1,40 +0,0 @@
-
-#if defined(QEMU_OPTIONS_GENERATE_ENUM)
-
-#define DEF(option, opt_arg, opt_enum, opt_help, arch_mask) \
- opt_enum,
-#define DEFHEADING(text)
-#define ARCHHEADING(text, arch_mask)
-
-#elif defined(QEMU_OPTIONS_GENERATE_HELP)
-
-#define DEF(option, opt_arg, opt_enum, opt_help, arch_mask) \
- if ((arch_mask) & arch_type) \
- fputs(opt_help, stdout);
-
-#define ARCHHEADING(text, arch_mask) \
- if ((arch_mask) & arch_type) \
- puts(stringify(text));
-
-#define DEFHEADING(text) ARCHHEADING(text, QEMU_ARCH_ALL)
-
-#elif defined(QEMU_OPTIONS_GENERATE_OPTIONS)
-
-#define DEF(option, opt_arg, opt_enum, opt_help, arch_mask) \
- { option, opt_arg, opt_enum, arch_mask },
-#define DEFHEADING(text)
-#define ARCHHEADING(text, arch_mask)
-
-#else
-#error "qemu-options-wrapper.h included with no option defined"
-#endif
-
-#include "qemu-options.def"
-
-#undef DEF
-#undef DEFHEADING
-#undef ARCHHEADING
-
-#undef QEMU_OPTIONS_GENERATE_ENUM
-#undef QEMU_OPTIONS_GENERATE_HELP
-#undef QEMU_OPTIONS_GENERATE_OPTIONS
diff --git a/qemu-options.hx b/qemu-options.hx
index e22fb94d99..14258784b3 100644
--- a/qemu-options.hx
+++ b/qemu-options.hx
@@ -141,6 +141,7 @@ DEF("accel", HAS_ARG, QEMU_OPTION_accel,
" kvm-shadow-mem=size of KVM shadow MMU in bytes\n"
" split-wx=on|off (enable TCG split w^x mapping)\n"
" tb-size=n (TCG translation block cache size)\n"
+ " dirty-ring-size=n (KVM dirty ring GFN count, default 0)\n"
" thread=single|multi (enable multi-threaded TCG)\n", QEMU_ARCH_ALL)
SRST
``-accel name[,prop=value[,...]]``
@@ -181,6 +182,17 @@ SRST
where both the back-end and front-ends support it and no
incompatible TCG features have been enabled (e.g.
icount/replay).
+
+ ``dirty-ring-size=n``
+ When the KVM accelerator is used, it controls the size of the per-vCPU
+ dirty page ring buffer (number of entries for each vCPU). It should
+ be a value that is power of two, and it should be 1024 or bigger (but
+ still less than the maximum value that the kernel supports). 4096
+ could be a good initial value if you have no idea which is the best.
+ Set this value to 0 to disable the feature. By default, this feature
+ is disabled (dirty-ring-size=0). When enabled, KVM will instead
+ record dirty pages in a bitmap.
+
ERST
DEF("smp", HAS_ARG, QEMU_OPTION_smp,
@@ -3787,8 +3799,11 @@ DEF("mon", HAS_ARG, QEMU_OPTION_mon, \
"-mon [chardev=]name[,mode=readline|control][,pretty[=on|off]]\n", QEMU_ARCH_ALL)
SRST
``-mon [chardev=]name[,mode=readline|control][,pretty[=on|off]]``
- Setup monitor on chardev name. ``pretty`` is only valid when
- ``mode=control``, turning on JSON pretty printing to ease
+ Setup monitor on chardev name. ``mode=control`` configures
+ a QMP monitor (a JSON RPC-style protocol) and it is not the
+ same as HMP, the human monitor that has a "(qemu)" prompt.
+ ``pretty`` is only valid when ``mode=control``,
+ turning on JSON pretty printing to ease
human reading and debugging.
ERST
@@ -5264,3 +5279,7 @@ ERST
HXCOMM This is the last statement. Insert new options before this line!
+
+#undef DEF
+#undef DEFHEADING
+#undef ARCHHEADING
diff --git a/replication.c b/replication.c
index be3a42f9c9..4acd3f8004 100644
--- a/replication.c
+++ b/replication.c
@@ -14,7 +14,7 @@
#include "qemu/osdep.h"
#include "qapi/error.h"
-#include "replication.h"
+#include "block/replication.h"
static QLIST_HEAD(, ReplicationState) replication_states;
diff --git a/softmmu/memory.c b/softmmu/memory.c
index 3bb533c0bc..c19b0be6b1 100644
--- a/softmmu/memory.c
+++ b/softmmu/memory.c
@@ -2055,6 +2055,10 @@ void memory_region_set_dirty(MemoryRegion *mr, hwaddr addr,
memory_region_get_dirty_log_mask(mr));
}
+/*
+ * If memory region `mr' is NULL, do global sync. Otherwise, sync
+ * dirty bitmap for the specified memory region.
+ */
static void memory_region_sync_dirty_bitmap(MemoryRegion *mr)
{
MemoryListener *listener;
@@ -2068,18 +2072,24 @@ static void memory_region_sync_dirty_bitmap(MemoryRegion *mr)
* address space once.
*/
QTAILQ_FOREACH(listener, &memory_listeners, link) {
- if (!listener->log_sync) {
- continue;
- }
- as = listener->address_space;
- view = address_space_get_flatview(as);
- FOR_EACH_FLAT_RANGE(fr, view) {
- if (fr->dirty_log_mask && (!mr || fr->mr == mr)) {
- MemoryRegionSection mrs = section_from_flat_range(fr, view);
- listener->log_sync(listener, &mrs);
+ if (listener->log_sync) {
+ as = listener->address_space;
+ view = address_space_get_flatview(as);
+ FOR_EACH_FLAT_RANGE(fr, view) {
+ if (fr->dirty_log_mask && (!mr || fr->mr == mr)) {
+ MemoryRegionSection mrs = section_from_flat_range(fr, view);
+ listener->log_sync(listener, &mrs);
+ }
}
+ flatview_unref(view);
+ } else if (listener->log_sync_global) {
+ /*
+ * No matter whether MR is specified, what we can do here
+ * is to do a global sync, because we are not capable to
+ * sync in a finer granularity.
+ */
+ listener->log_sync_global(listener);
}
- flatview_unref(view);
}
}
@@ -2767,6 +2777,9 @@ void memory_listener_register(MemoryListener *listener, AddressSpace *as)
{
MemoryListener *other = NULL;
+ /* Only one of them can be defined for a listener */
+ assert(!(listener->log_sync && listener->log_sync_global));
+
listener->address_space = as;
if (QTAILQ_EMPTY(&memory_listeners)
|| listener->priority >= QTAILQ_LAST(&memory_listeners)->priority) {
diff --git a/softmmu/physmem.c b/softmmu/physmem.c
index e1da81ed2f..1c8717684a 100644
--- a/softmmu/physmem.c
+++ b/softmmu/physmem.c
@@ -905,6 +905,16 @@ void cpu_check_watchpoint(CPUState *cpu, vaddr addr, vaddr len,
&& (wp->flags & flags)) {
if (replay_running_debug()) {
/*
+ * replay_breakpoint reads icount.
+ * Force recompile to succeed, because icount may
+ * be read only at the end of the block.
+ */
+ if (!cpu->can_do_io) {
+ /* Force execution of one insn next time. */
+ cpu->cflags_next_tb = 1 | CF_LAST_IO | curr_cflags(cpu);
+ cpu_loop_exit_restore(cpu, ra);
+ }
+ /*
* Don't process the watchpoints when we are
* in a reverse debugging operation.
*/
diff --git a/softmmu/qtest.c b/softmmu/qtest.c
index 130c366615..72751e1fd8 100644
--- a/softmmu/qtest.c
+++ b/softmmu/qtest.c
@@ -27,6 +27,8 @@
#include "qemu/error-report.h"
#include "qemu/module.h"
#include "qemu/cutils.h"
+#include "qapi/qmp/qerror.h"
+#include "qom/object_interfaces.h"
#include CONFIG_DEVICES
#ifdef CONFIG_PSERIES
#include "hw/ppc/spapr_rtas.h"
@@ -34,11 +36,25 @@
#define MAX_IRQ 256
+#define TYPE_QTEST "qtest"
+
+OBJECT_DECLARE_SIMPLE_TYPE(QTest, QTEST)
+
+struct QTest {
+ Object parent;
+
+ bool has_machine_link;
+ char *chr_name;
+ Chardev *chr;
+ CharBackend qtest_chr;
+ char *log;
+};
+
bool qtest_allowed;
static DeviceState *irq_intercept_dev;
static FILE *qtest_log_fp;
-static CharBackend qtest_chr;
+static QTest *qtest;
static GString *inbuf;
static int irq_levels[MAX_IRQ];
static qemu_timeval start_time;
@@ -320,7 +336,7 @@ static void qtest_irq_handler(void *opaque, int n, int level)
qemu_set_irq(old_irq, level);
if (irq_levels[n] != level) {
- CharBackend *chr = &qtest_chr;
+ CharBackend *chr = &qtest->qtest_chr;
irq_levels[n] = level;
qtest_send_prefix(chr);
qtest_sendf(chr, "IRQ %s %d\n",
@@ -849,18 +865,39 @@ static void qtest_event(void *opaque, QEMUChrEvent event)
break;
}
}
+
void qtest_server_init(const char *qtest_chrdev, const char *qtest_log, Error **errp)
{
+ ERRP_GUARD();
Chardev *chr;
+ Object *qtest;
chr = qemu_chr_new("qtest", qtest_chrdev, NULL);
-
if (chr == NULL) {
error_setg(errp, "Failed to initialize device for qtest: \"%s\"",
qtest_chrdev);
return;
}
+ qtest = object_new(TYPE_QTEST);
+ object_property_set_str(qtest, "chardev", "qtest", &error_abort);
+ if (qtest_log) {
+ object_property_set_str(qtest, "log", qtest_log, &error_abort);
+ }
+ object_property_add_child(qdev_get_machine(), "qtest", qtest);
+ user_creatable_complete(USER_CREATABLE(qtest), errp);
+ if (*errp) {
+ object_unparent(qtest);
+ }
+ object_unref(OBJECT(chr));
+ object_unref(qtest);
+}
+
+static bool qtest_server_start(QTest *q, Error **errp)
+{
+ Chardev *chr = q->chr;
+ const char *qtest_log = q->log;
+
if (qtest_log) {
if (strcmp(qtest_log, "none") != 0) {
qtest_log_fp = fopen(qtest_log, "w+");
@@ -869,16 +906,20 @@ void qtest_server_init(const char *qtest_chrdev, const char *qtest_log, Error **
qtest_log_fp = stderr;
}
- qemu_chr_fe_init(&qtest_chr, chr, errp);
- qemu_chr_fe_set_handlers(&qtest_chr, qtest_can_read, qtest_read,
- qtest_event, NULL, &qtest_chr, NULL, true);
- qemu_chr_fe_set_echo(&qtest_chr, true);
+ if (!qemu_chr_fe_init(&q->qtest_chr, chr, errp)) {
+ return false;
+ }
+ qemu_chr_fe_set_handlers(&q->qtest_chr, qtest_can_read, qtest_read,
+ qtest_event, NULL, &q->qtest_chr, NULL, true);
+ qemu_chr_fe_set_echo(&q->qtest_chr, true);
inbuf = g_string_new("");
if (!qtest_server_send) {
- qtest_server_set_send_handler(qtest_server_char_be_send, &qtest_chr);
+ qtest_server_set_send_handler(qtest_server_char_be_send, &q->qtest_chr);
}
+ qtest = q;
+ return true;
}
void qtest_server_set_send_handler(void (*send)(void*, const char*),
@@ -890,7 +931,7 @@ void qtest_server_set_send_handler(void (*send)(void*, const char*),
bool qtest_driver(void)
{
- return qtest_chr.chr != NULL;
+ return qtest && qtest->qtest_chr.chr != NULL;
}
void qtest_server_inproc_recv(void *dummy, const char *buf)
@@ -905,3 +946,129 @@ void qtest_server_inproc_recv(void *dummy, const char *buf)
g_string_truncate(gstr, 0);
}
}
+
+static void qtest_complete(UserCreatable *uc, Error **errp)
+{
+ QTest *q = QTEST(uc);
+ if (qtest) {
+ error_setg(errp, "Only one instance of qtest can be created");
+ return;
+ }
+ if (!q->chr_name) {
+ error_setg(errp, "No backend specified");
+ return;
+ }
+
+ if (OBJECT(uc)->parent != qdev_get_machine()) {
+ q->has_machine_link = true;
+ object_property_add_const_link(qdev_get_machine(), "qtest", OBJECT(uc));
+ } else {
+ /* -qtest was used. */
+ }
+
+ qtest_server_start(q, errp);
+}
+
+static void qtest_unparent(Object *obj)
+{
+ QTest *q = QTEST(obj);
+
+ if (qtest == q) {
+ qemu_chr_fe_disconnect(&q->qtest_chr);
+ assert(!qtest_opened);
+ qemu_chr_fe_deinit(&q->qtest_chr, false);
+ if (qtest_log_fp) {
+ fclose(qtest_log_fp);
+ qtest_log_fp = NULL;
+ }
+ qtest = NULL;
+ }
+
+ if (q->has_machine_link) {
+ object_property_del(qdev_get_machine(), "qtest");
+ q->has_machine_link = false;
+ }
+}
+
+static void qtest_set_log(Object *obj, const char *value, Error **errp)
+{
+ QTest *q = QTEST(obj);
+
+ if (qtest == q) {
+ error_setg(errp, QERR_PERMISSION_DENIED);
+ } else {
+ g_free(q->log);
+ q->log = g_strdup(value);
+ }
+}
+
+static char *qtest_get_log(Object *obj, Error **errp)
+{
+ QTest *q = QTEST(obj);
+
+ return g_strdup(q->log);
+}
+
+static void qtest_set_chardev(Object *obj, const char *value, Error **errp)
+{
+ QTest *q = QTEST(obj);
+ Chardev *chr;
+
+ if (qtest == q) {
+ error_setg(errp, QERR_PERMISSION_DENIED);
+ return;
+ }
+
+ chr = qemu_chr_find(value);
+ if (!chr) {
+ error_setg(errp, "Cannot find character device '%s'", value);
+ return;
+ }
+
+ g_free(q->chr_name);
+ q->chr_name = g_strdup(value);
+
+ if (q->chr) {
+ object_unref(q->chr);
+ }
+ q->chr = chr;
+ object_ref(chr);
+}
+
+static char *qtest_get_chardev(Object *obj, Error **errp)
+{
+ QTest *q = QTEST(obj);
+
+ return g_strdup(q->chr_name);
+}
+
+static void qtest_class_init(ObjectClass *oc, void *data)
+{
+ UserCreatableClass *ucc = USER_CREATABLE_CLASS(oc);
+
+ oc->unparent = qtest_unparent;
+ ucc->complete = qtest_complete;
+
+ object_class_property_add_str(oc, "chardev",
+ qtest_get_chardev, qtest_set_chardev);
+ object_class_property_add_str(oc, "log",
+ qtest_get_log, qtest_set_log);
+}
+
+static const TypeInfo qtest_info = {
+ .name = TYPE_QTEST,
+ .parent = TYPE_OBJECT,
+ .class_init = qtest_class_init,
+ .instance_size = sizeof(QTest),
+ .interfaces = (InterfaceInfo[]) {
+ { TYPE_USER_CREATABLE },
+ { }
+ }
+};
+
+static void register_types(void)
+{
+ type_register_static(&qtest_info);
+}
+
+type_init(register_types);
diff --git a/softmmu/vl.c b/softmmu/vl.c
index 93e78469bc..6054f6f0b9 100644
--- a/softmmu/vl.c
+++ b/softmmu/vl.c
@@ -88,7 +88,7 @@
#include "qapi/qobject-input-visitor.h"
#include "qemu/option.h"
#include "qemu/config-file.h"
-#include "qemu-options.h"
+#include "qemu/qemu-options.h"
#include "qemu/main-loop.h"
#ifdef CONFIG_VIRTFS
#include "fsdev/qemu-fsdev.h"
@@ -854,8 +854,17 @@ static void help(int exitcode)
"'disk_image' is a raw hard disk image for IDE hard disk 0\n\n",
error_get_progname());
-#define QEMU_OPTIONS_GENERATE_HELP
-#include "qemu-options-wrapper.h"
+#define DEF(option, opt_arg, opt_enum, opt_help, arch_mask) \
+ if ((arch_mask) & arch_type) \
+ fputs(opt_help, stdout);
+
+#define ARCHHEADING(text, arch_mask) \
+ if ((arch_mask) & arch_type) \
+ puts(stringify(text));
+
+#define DEFHEADING(text) ARCHHEADING(text, QEMU_ARCH_ALL)
+
+#include "qemu-options.def"
printf("\nDuring emulation, the following keys are useful:\n"
"ctrl-alt-f toggle full screen\n"
@@ -880,8 +889,13 @@ typedef struct QEMUOption {
static const QEMUOption qemu_options[] = {
{ "h", 0, QEMU_OPTION_h, QEMU_ARCH_ALL },
-#define QEMU_OPTIONS_GENERATE_OPTIONS
-#include "qemu-options-wrapper.h"
+
+#define DEF(option, opt_arg, opt_enum, opt_help, arch_mask) \
+ { option, opt_arg, opt_enum, arch_mask },
+#define DEFHEADING(text)
+#define ARCHHEADING(text, arch_mask)
+
+#include "qemu-options.def"
{ NULL },
};
@@ -1758,8 +1772,9 @@ static bool object_create_early(const char *type)
* add one, state the reason in a comment!
*/
- /* Reason: rng-egd property "chardev" */
- if (g_str_equal(type, "rng-egd")) {
+ /* Reason: property "chardev" */
+ if (g_str_equal(type, "rng-egd") ||
+ g_str_equal(type, "qtest")) {
return false;
}
@@ -2024,8 +2039,6 @@ static void set_memory_options(MachineClass *mc)
exit(EXIT_FAILURE);
}
- /* store value for the future use */
- qemu_opt_set_number(opts, "size", ram_size, &error_abort);
maxram_size = ram_size;
if (qemu_opt_get(opts, "maxmem")) {
@@ -2614,6 +2627,23 @@ void qmp_x_exit_preconfig(Error **errp)
}
}
+#ifdef CONFIG_MODULES
+void qemu_load_module_for_opts(const char *group)
+{
+ static bool spice_tried;
+ if (g_str_equal(group, "spice") && !spice_tried) {
+ ui_module_load_one("spice-core");
+ spice_tried = true;
+ }
+
+ static bool iscsi_tried;
+ if (g_str_equal(group, "iscsi") && !iscsi_tried) {
+ block_module_load_one("iscsi");
+ iscsi_tried = true;
+ }
+}
+#endif
+
void qemu_init(int argc, char **argv, char **envp)
{
QemuOpts *opts;
@@ -3374,10 +3404,6 @@ void qemu_init(int argc, char **argv, char **envp)
case QEMU_OPTION_spice:
olist = qemu_find_opts_err("spice", NULL);
if (!olist) {
- ui_module_load_one("spice-core");
- olist = qemu_find_opts("spice");
- }
- if (!olist) {
error_report("spice support is disabled");
exit(1);
}
diff --git a/stubs/meson.build b/stubs/meson.build
index c32d182585..65c22c0568 100644
--- a/stubs/meson.build
+++ b/stubs/meson.build
@@ -22,6 +22,7 @@ stub_ss.add(files('isa-bus.c'))
stub_ss.add(files('is-daemonized.c'))
stub_ss.add(when: 'CONFIG_LINUX_AIO', if_true: files('linux-aio.c'))
stub_ss.add(files('migr-blocker.c'))
+stub_ss.add(files('module-opts.c'))
stub_ss.add(files('monitor.c'))
stub_ss.add(files('monitor-core.c'))
stub_ss.add(files('pci-bus.c'))
diff --git a/stubs/module-opts.c b/stubs/module-opts.c
new file mode 100644
index 0000000000..a7d0e4ad6e
--- /dev/null
+++ b/stubs/module-opts.c
@@ -0,0 +1,6 @@
+#include "qemu/osdep.h"
+#include "qemu/config-file.h"
+
+void qemu_load_module_for_opts(const char *group)
+{
+}
diff --git a/stubs/vmstate.c b/stubs/vmstate.c
index cc4fe41dfc..8513d9204e 100644
--- a/stubs/vmstate.c
+++ b/stubs/vmstate.c
@@ -1,8 +1,6 @@
#include "qemu/osdep.h"
#include "migration/vmstate.h"
-const VMStateDescription vmstate_dummy = {};
-
int vmstate_register_with_alias_id(VMStateIf *obj,
uint32_t instance_id,
const VMStateDescription *vmsd,
diff --git a/target/alpha/cpu.c b/target/alpha/cpu.c
index 27192b62e2..4871ad0c0a 100644
--- a/target/alpha/cpu.c
+++ b/target/alpha/cpu.c
@@ -206,9 +206,17 @@ static void alpha_cpu_initfn(Object *obj)
#endif
}
+#ifndef CONFIG_USER_ONLY
+#include "hw/core/sysemu-cpu-ops.h"
+
+static const struct SysemuCPUOps alpha_sysemu_ops = {
+ .get_phys_page_debug = alpha_cpu_get_phys_page_debug,
+};
+#endif
+
#include "hw/core/tcg-cpu-ops.h"
-static struct TCGCPUOps alpha_tcg_ops = {
+static const struct TCGCPUOps alpha_tcg_ops = {
.initialize = alpha_translate_init,
.cpu_exec_interrupt = alpha_cpu_exec_interrupt,
.tlb_fill = alpha_cpu_tlb_fill,
@@ -236,8 +244,8 @@ static void alpha_cpu_class_init(ObjectClass *oc, void *data)
cc->gdb_read_register = alpha_cpu_gdb_read_register;
cc->gdb_write_register = alpha_cpu_gdb_write_register;
#ifndef CONFIG_USER_ONLY
- cc->get_phys_page_debug = alpha_cpu_get_phys_page_debug;
dc->vmsd = &vmstate_alpha_cpu;
+ cc->sysemu_ops = &alpha_sysemu_ops;
#endif
cc->disas_set_info = alpha_cpu_disas_set_info;
diff --git a/target/arm/cpu.c b/target/arm/cpu.c
index 7aeb4b1381..ad65b60b04 100644
--- a/target/arm/cpu.c
+++ b/target/arm/cpu.c
@@ -1944,8 +1944,21 @@ static gchar *arm_gdb_arch_name(CPUState *cs)
return g_strdup("arm");
}
+#ifndef CONFIG_USER_ONLY
+#include "hw/core/sysemu-cpu-ops.h"
+
+static const struct SysemuCPUOps arm_sysemu_ops = {
+ .get_phys_page_attrs_debug = arm_cpu_get_phys_page_attrs_debug,
+ .asidx_from_attrs = arm_asidx_from_attrs,
+ .write_elf32_note = arm_cpu_write_elf32_note,
+ .write_elf64_note = arm_cpu_write_elf64_note,
+ .virtio_is_big_endian = arm_cpu_virtio_is_big_endian,
+ .legacy_vmsd = &vmstate_arm_cpu,
+};
+#endif
+
#ifdef CONFIG_TCG
-static struct TCGCPUOps arm_tcg_ops = {
+static const struct TCGCPUOps arm_tcg_ops = {
.initialize = arm_translate_init,
.synchronize_from_tb = arm_cpu_synchronize_from_tb,
.cpu_exec_interrupt = arm_cpu_exec_interrupt,
@@ -1981,12 +1994,7 @@ static void arm_cpu_class_init(ObjectClass *oc, void *data)
cc->gdb_read_register = arm_cpu_gdb_read_register;
cc->gdb_write_register = arm_cpu_gdb_write_register;
#ifndef CONFIG_USER_ONLY
- cc->get_phys_page_attrs_debug = arm_cpu_get_phys_page_attrs_debug;
- cc->asidx_from_attrs = arm_asidx_from_attrs;
- cc->vmsd = &vmstate_arm_cpu;
- cc->virtio_is_big_endian = arm_cpu_virtio_is_big_endian;
- cc->write_elf64_note = arm_cpu_write_elf64_note;
- cc->write_elf32_note = arm_cpu_write_elf32_note;
+ cc->sysemu_ops = &arm_sysemu_ops;
#endif
cc->gdb_num_core_regs = 26;
cc->gdb_core_xml_file = "arm-core.xml";
diff --git a/target/arm/cpu_tcg.c b/target/arm/cpu_tcg.c
index d3458335ed..2e0e508f0e 100644
--- a/target/arm/cpu_tcg.c
+++ b/target/arm/cpu_tcg.c
@@ -898,7 +898,7 @@ static void pxa270c5_initfn(Object *obj)
}
#ifdef CONFIG_TCG
-static struct TCGCPUOps arm_v7m_tcg_ops = {
+static const struct TCGCPUOps arm_v7m_tcg_ops = {
.initialize = arm_translate_init,
.synchronize_from_tb = arm_cpu_synchronize_from_tb,
.cpu_exec_interrupt = arm_v7m_cpu_exec_interrupt,
diff --git a/target/avr/cpu.c b/target/avr/cpu.c
index 0f4596932b..57e3fab4a0 100644
--- a/target/avr/cpu.c
+++ b/target/avr/cpu.c
@@ -184,9 +184,15 @@ static void avr_cpu_dump_state(CPUState *cs, FILE *f, int flags)
qemu_fprintf(f, "\n");
}
+#include "hw/core/sysemu-cpu-ops.h"
+
+static const struct SysemuCPUOps avr_sysemu_ops = {
+ .get_phys_page_debug = avr_cpu_get_phys_page_debug,
+};
+
#include "hw/core/tcg-cpu-ops.h"
-static struct TCGCPUOps avr_tcg_ops = {
+static const struct TCGCPUOps avr_tcg_ops = {
.initialize = avr_cpu_tcg_init,
.synchronize_from_tb = avr_cpu_synchronize_from_tb,
.cpu_exec_interrupt = avr_cpu_exec_interrupt,
@@ -212,8 +218,8 @@ static void avr_cpu_class_init(ObjectClass *oc, void *data)
cc->dump_state = avr_cpu_dump_state;
cc->set_pc = avr_cpu_set_pc;
cc->memory_rw_debug = avr_cpu_memory_rw_debug;
- cc->get_phys_page_debug = avr_cpu_get_phys_page_debug;
- cc->vmsd = &vms_avr_cpu;
+ dc->vmsd = &vms_avr_cpu;
+ cc->sysemu_ops = &avr_sysemu_ops;
cc->disas_set_info = avr_cpu_disas_set_info;
cc->gdb_read_register = avr_cpu_gdb_read_register;
cc->gdb_write_register = avr_cpu_gdb_write_register;
diff --git a/target/avr/machine.c b/target/avr/machine.c
index de264f57c3..16f7a3e031 100644
--- a/target/avr/machine.c
+++ b/target/avr/machine.c
@@ -98,8 +98,8 @@ static const VMStateInfo vms_eind = {
const VMStateDescription vms_avr_cpu = {
.name = "cpu",
- .version_id = 0,
- .minimum_version_id = 0,
+ .version_id = 1,
+ .minimum_version_id = 1,
.fields = (VMStateField[]) {
VMSTATE_UINT32(env.pc_w, AVRCPU),
VMSTATE_UINT32(env.sp, AVRCPU),
diff --git a/target/cris/cpu.c b/target/cris/cpu.c
index ed983380fc..70932b1f8c 100644
--- a/target/cris/cpu.c
+++ b/target/cris/cpu.c
@@ -193,9 +193,17 @@ static void cris_cpu_initfn(Object *obj)
#endif
}
+#ifndef CONFIG_USER_ONLY
+#include "hw/core/sysemu-cpu-ops.h"
+
+static const struct SysemuCPUOps cris_sysemu_ops = {
+ .get_phys_page_debug = cris_cpu_get_phys_page_debug,
+};
+#endif
+
#include "hw/core/tcg-cpu-ops.h"
-static struct TCGCPUOps crisv10_tcg_ops = {
+static const struct TCGCPUOps crisv10_tcg_ops = {
.initialize = cris_initialize_crisv10_tcg,
.cpu_exec_interrupt = cris_cpu_exec_interrupt,
.tlb_fill = cris_cpu_tlb_fill,
@@ -205,7 +213,7 @@ static struct TCGCPUOps crisv10_tcg_ops = {
#endif /* !CONFIG_USER_ONLY */
};
-static struct TCGCPUOps crisv32_tcg_ops = {
+static const struct TCGCPUOps crisv32_tcg_ops = {
.initialize = cris_initialize_tcg,
.cpu_exec_interrupt = cris_cpu_exec_interrupt,
.tlb_fill = cris_cpu_tlb_fill,
@@ -292,8 +300,8 @@ static void cris_cpu_class_init(ObjectClass *oc, void *data)
cc->gdb_read_register = cris_cpu_gdb_read_register;
cc->gdb_write_register = cris_cpu_gdb_write_register;
#ifndef CONFIG_USER_ONLY
- cc->get_phys_page_debug = cris_cpu_get_phys_page_debug;
dc->vmsd = &vmstate_cris_cpu;
+ cc->sysemu_ops = &cris_sysemu_ops;
#endif
cc->gdb_num_core_regs = 49;
diff --git a/target/hexagon/cpu.c b/target/hexagon/cpu.c
index ebe60a6e15..3338365c16 100644
--- a/target/hexagon/cpu.c
+++ b/target/hexagon/cpu.c
@@ -269,7 +269,7 @@ static bool hexagon_tlb_fill(CPUState *cs, vaddr address, int size,
#include "hw/core/tcg-cpu-ops.h"
-static struct TCGCPUOps hexagon_tcg_ops = {
+static const struct TCGCPUOps hexagon_tcg_ops = {
.initialize = hexagon_translate_init,
.synchronize_from_tb = hexagon_cpu_synchronize_from_tb,
.tlb_fill = hexagon_tlb_fill,
diff --git a/target/hppa/cpu.c b/target/hppa/cpu.c
index d8fad52d1f..2eace4ee12 100644
--- a/target/hppa/cpu.c
+++ b/target/hppa/cpu.c
@@ -131,9 +131,17 @@ static ObjectClass *hppa_cpu_class_by_name(const char *cpu_model)
return object_class_by_name(TYPE_HPPA_CPU);
}
+#ifndef CONFIG_USER_ONLY
+#include "hw/core/sysemu-cpu-ops.h"
+
+static const struct SysemuCPUOps hppa_sysemu_ops = {
+ .get_phys_page_debug = hppa_cpu_get_phys_page_debug,
+};
+#endif
+
#include "hw/core/tcg-cpu-ops.h"
-static struct TCGCPUOps hppa_tcg_ops = {
+static const struct TCGCPUOps hppa_tcg_ops = {
.initialize = hppa_translate_init,
.synchronize_from_tb = hppa_cpu_synchronize_from_tb,
.cpu_exec_interrupt = hppa_cpu_exec_interrupt,
@@ -161,8 +169,8 @@ static void hppa_cpu_class_init(ObjectClass *oc, void *data)
cc->gdb_read_register = hppa_cpu_gdb_read_register;
cc->gdb_write_register = hppa_cpu_gdb_write_register;
#ifndef CONFIG_USER_ONLY
- cc->get_phys_page_debug = hppa_cpu_get_phys_page_debug;
dc->vmsd = &vmstate_hppa_cpu;
+ cc->sysemu_ops = &hppa_sysemu_ops;
#endif
cc->disas_set_info = hppa_cpu_disas_set_info;
cc->gdb_num_core_regs = 128;
diff --git a/target/i386/cpu.c b/target/i386/cpu.c
index c496bfa1c2..b4349119f8 100644
--- a/target/i386/cpu.c
+++ b/target/i386/cpu.c
@@ -940,7 +940,7 @@ FeatureWordInfo feature_word_info[FEATURE_WORDS] = {
.type = CPUID_FEATURE_WORD,
.feat_names = {
NULL, NULL, NULL, NULL,
- NULL, "avx512-bf16", NULL, NULL,
+ "avx-vnni", "avx512-bf16", NULL, NULL,
NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL,
@@ -3194,7 +3194,7 @@ static X86CPUDefinition builtin_x86_defs[] = {
MSR_ARCH_CAP_SKIP_L1DFL_VMENTRY | MSR_ARCH_CAP_MDS_NO |
MSR_ARCH_CAP_PSCHANGE_MC_NO | MSR_ARCH_CAP_TAA_NO,
.features[FEAT_7_1_EAX] =
- CPUID_7_1_EAX_AVX512_BF16,
+ CPUID_7_1_EAX_AVX_VNNI | CPUID_7_1_EAX_AVX512_BF16,
/*
* Missing: XSAVES (not supported by some Linux versions,
* including v4.1 to v4.12).
@@ -6485,12 +6485,14 @@ static int64_t x86_cpu_get_arch_id(CPUState *cs)
return cpu->apic_id;
}
+#if !defined(CONFIG_USER_ONLY)
static bool x86_cpu_get_paging_enabled(const CPUState *cs)
{
X86CPU *cpu = X86_CPU(cs);
return cpu->env.cr[0] & CR0_PG_MASK;
}
+#endif /* !CONFIG_USER_ONLY */
static void x86_cpu_set_pc(CPUState *cs, vaddr value)
{
@@ -6714,6 +6716,23 @@ static Property x86_cpu_properties[] = {
DEFINE_PROP_END_OF_LIST()
};
+#ifndef CONFIG_USER_ONLY
+#include "hw/core/sysemu-cpu-ops.h"
+
+static const struct SysemuCPUOps i386_sysemu_ops = {
+ .get_memory_mapping = x86_cpu_get_memory_mapping,
+ .get_paging_enabled = x86_cpu_get_paging_enabled,
+ .get_phys_page_attrs_debug = x86_cpu_get_phys_page_attrs_debug,
+ .asidx_from_attrs = x86_asidx_from_attrs,
+ .get_crash_info = x86_cpu_get_crash_info,
+ .write_elf32_note = x86_cpu_write_elf32_note,
+ .write_elf64_note = x86_cpu_write_elf64_note,
+ .write_elf32_qemunote = x86_cpu_write_elf32_qemunote,
+ .write_elf64_qemunote = x86_cpu_write_elf64_qemunote,
+ .legacy_vmsd = &vmstate_x86_cpu,
+};
+#endif
+
static void x86_cpu_common_class_init(ObjectClass *oc, void *data)
{
X86CPUClass *xcc = X86_CPU_CLASS(oc);
@@ -6738,18 +6757,9 @@ static void x86_cpu_common_class_init(ObjectClass *oc, void *data)
cc->gdb_read_register = x86_cpu_gdb_read_register;
cc->gdb_write_register = x86_cpu_gdb_write_register;
cc->get_arch_id = x86_cpu_get_arch_id;
- cc->get_paging_enabled = x86_cpu_get_paging_enabled;
#ifndef CONFIG_USER_ONLY
- cc->asidx_from_attrs = x86_asidx_from_attrs;
- cc->get_memory_mapping = x86_cpu_get_memory_mapping;
- cc->get_phys_page_attrs_debug = x86_cpu_get_phys_page_attrs_debug;
- cc->get_crash_info = x86_cpu_get_crash_info;
- cc->write_elf64_note = x86_cpu_write_elf64_note;
- cc->write_elf64_qemunote = x86_cpu_write_elf64_qemunote;
- cc->write_elf32_note = x86_cpu_write_elf32_note;
- cc->write_elf32_qemunote = x86_cpu_write_elf32_qemunote;
- cc->vmsd = &vmstate_x86_cpu;
+ cc->sysemu_ops = &i386_sysemu_ops;
#endif /* !CONFIG_USER_ONLY */
cc->gdb_arch_name = x86_gdb_arch_name;
diff --git a/target/i386/cpu.h b/target/i386/cpu.h
index e6836393f7..da72aa5228 100644
--- a/target/i386/cpu.h
+++ b/target/i386/cpu.h
@@ -817,6 +817,8 @@ typedef uint64_t FeatureWordArray[FEATURE_WORDS];
/* Speculative Store Bypass Disable */
#define CPUID_7_0_EDX_SPEC_CTRL_SSBD (1U << 31)
+/* AVX VNNI Instruction */
+#define CPUID_7_1_EAX_AVX_VNNI (1U << 4)
/* AVX512 BFloat16 Instruction */
#define CPUID_7_1_EAX_AVX512_BF16 (1U << 5)
diff --git a/target/i386/tcg/tcg-cpu.c b/target/i386/tcg/tcg-cpu.c
index ba39531aa5..014ebea2f6 100644
--- a/target/i386/tcg/tcg-cpu.c
+++ b/target/i386/tcg/tcg-cpu.c
@@ -56,7 +56,7 @@ static void x86_cpu_synchronize_from_tb(CPUState *cs,
#include "hw/core/tcg-cpu-ops.h"
-static struct TCGCPUOps x86_tcg_ops = {
+static const struct TCGCPUOps x86_tcg_ops = {
.initialize = tcg_x86_init,
.synchronize_from_tb = x86_cpu_synchronize_from_tb,
.cpu_exec_enter = x86_cpu_exec_enter,
diff --git a/target/m68k/cpu.c b/target/m68k/cpu.c
index a14874b4da..72de6e9726 100644
--- a/target/m68k/cpu.c
+++ b/target/m68k/cpu.c
@@ -503,9 +503,17 @@ static const VMStateDescription vmstate_m68k_cpu = {
};
#endif
+#ifndef CONFIG_USER_ONLY
+#include "hw/core/sysemu-cpu-ops.h"
+
+static const struct SysemuCPUOps m68k_sysemu_ops = {
+ .get_phys_page_debug = m68k_cpu_get_phys_page_debug,
+};
+#endif
+
#include "hw/core/tcg-cpu-ops.h"
-static struct TCGCPUOps m68k_tcg_ops = {
+static const struct TCGCPUOps m68k_tcg_ops = {
.initialize = m68k_tcg_init,
.cpu_exec_interrupt = m68k_cpu_exec_interrupt,
.tlb_fill = m68k_cpu_tlb_fill,
@@ -533,8 +541,8 @@ static void m68k_cpu_class_init(ObjectClass *c, void *data)
cc->gdb_read_register = m68k_cpu_gdb_read_register;
cc->gdb_write_register = m68k_cpu_gdb_write_register;
#if defined(CONFIG_SOFTMMU)
- cc->get_phys_page_debug = m68k_cpu_get_phys_page_debug;
dc->vmsd = &vmstate_m68k_cpu;
+ cc->sysemu_ops = &m68k_sysemu_ops;
#endif
cc->disas_set_info = m68k_cpu_disas_set_info;
diff --git a/target/m68k/cpu.h b/target/m68k/cpu.h
index 402c86c876..997d588911 100644
--- a/target/m68k/cpu.h
+++ b/target/m68k/cpu.h
@@ -230,6 +230,9 @@ typedef enum {
#define SR_T_SHIFT 14
#define SR_T 0xc000
+#define M68K_SR_TRACE(sr) ((sr & SR_T) >> SR_T_SHIFT)
+#define M68K_SR_TRACE_ANY_INS 0x2
+
#define M68K_SSP 0
#define M68K_USP 1
#define M68K_ISP 2
@@ -590,6 +593,8 @@ typedef M68kCPU ArchCPU;
#define TB_FLAGS_SFC_S (1 << TB_FLAGS_SFC_S_BIT)
#define TB_FLAGS_DFC_S_BIT 15
#define TB_FLAGS_DFC_S (1 << TB_FLAGS_DFC_S_BIT)
+#define TB_FLAGS_TRACE 16
+#define TB_FLAGS_TRACE_BIT (1 << TB_FLAGS_TRACE)
static inline void cpu_get_tb_cpu_state(CPUM68KState *env, target_ulong *pc,
target_ulong *cs_base, uint32_t *flags)
@@ -602,6 +607,9 @@ static inline void cpu_get_tb_cpu_state(CPUM68KState *env, target_ulong *pc,
*flags |= (env->sfc << (TB_FLAGS_SFC_S_BIT - 2)) & TB_FLAGS_SFC_S;
*flags |= (env->dfc << (TB_FLAGS_DFC_S_BIT - 2)) & TB_FLAGS_DFC_S;
}
+ if (M68K_SR_TRACE(env->sr) == M68K_SR_TRACE_ANY_INS) {
+ *flags |= TB_FLAGS_TRACE;
+ }
}
void dump_mmu(CPUM68KState *env);
diff --git a/target/m68k/translate.c b/target/m68k/translate.c
index 200018ae6a..f0c5bf9154 100644
--- a/target/m68k/translate.c
+++ b/target/m68k/translate.c
@@ -124,6 +124,7 @@ typedef struct DisasContext {
#define MAX_TO_RELEASE 8
int release_count;
TCGv release[MAX_TO_RELEASE];
+ bool ss_active;
} DisasContext;
static void init_release_array(DisasContext *s)
@@ -194,6 +195,18 @@ static void do_writebacks(DisasContext *s)
}
}
+static bool is_singlestepping(DisasContext *s)
+{
+ /*
+ * Return true if we are singlestepping either because of
+ * architectural singlestep or QEMU gdbstub singlestep. This does
+ * not include the command line '-singlestep' mode which is rather
+ * misnamed as it only means "one instruction per TB" and doesn't
+ * affect the code we generate.
+ */
+ return s->base.singlestep_enabled || s->ss_active;
+}
+
/* is_jmp field values */
#define DISAS_JUMP DISAS_TARGET_0 /* only pc was modified dynamically */
#define DISAS_EXIT DISAS_TARGET_1 /* cpu state was modified dynamically */
@@ -308,6 +321,20 @@ static void gen_exception(DisasContext *s, uint32_t dest, int nr)
s->base.is_jmp = DISAS_NORETURN;
}
+static void gen_singlestep_exception(DisasContext *s)
+{
+ /*
+ * Generate the right kind of exception for singlestep, which is
+ * either the architectural singlestep or EXCP_DEBUG for QEMU's
+ * gdb singlestepping.
+ */
+ if (s->ss_active) {
+ gen_raise_exception(EXCP_TRACE);
+ } else {
+ gen_raise_exception(EXCP_DEBUG);
+ }
+}
+
static inline void gen_addr_fault(DisasContext *s)
{
gen_exception(s, s->base.pc_next, EXCP_ADDRESS);
@@ -1506,8 +1533,10 @@ static inline bool use_goto_tb(DisasContext *s, uint32_t dest)
/* Generate a jump to an immediate address. */
static void gen_jmp_tb(DisasContext *s, int n, uint32_t dest)
{
- if (unlikely(s->base.singlestep_enabled)) {
- gen_exception(s, dest, EXCP_DEBUG);
+ if (unlikely(is_singlestepping(s))) {
+ update_cc_op(s);
+ tcg_gen_movi_i32(QREG_PC, dest);
+ gen_singlestep_exception(s);
} else if (use_goto_tb(s, dest)) {
tcg_gen_goto_tb(n);
tcg_gen_movi_i32(QREG_PC, dest);
@@ -6172,6 +6201,12 @@ static void m68k_tr_init_disas_context(DisasContextBase *dcbase, CPUState *cpu)
dc->done_mac = 0;
dc->writeback_mask = 0;
init_release_array(dc);
+
+ dc->ss_active = (M68K_SR_TRACE(env->sr) == M68K_SR_TRACE_ANY_INS);
+ /* If architectural single step active, limit to 1 */
+ if (is_singlestepping(dc)) {
+ dc->base.max_insns = 1;
+ }
}
static void m68k_tr_tb_start(DisasContextBase *dcbase, CPUState *cpu)
@@ -6245,17 +6280,17 @@ static void m68k_tr_tb_stop(DisasContextBase *dcbase, CPUState *cpu)
break;
case DISAS_TOO_MANY:
update_cc_op(dc);
- if (dc->base.singlestep_enabled) {
+ if (is_singlestepping(dc)) {
tcg_gen_movi_i32(QREG_PC, dc->pc);
- gen_raise_exception(EXCP_DEBUG);
+ gen_singlestep_exception(dc);
} else {
gen_jmp_tb(dc, 0, dc->pc);
}
break;
case DISAS_JUMP:
/* We updated CC_OP and PC in gen_jmp/gen_jmp_im. */
- if (dc->base.singlestep_enabled) {
- gen_raise_exception(EXCP_DEBUG);
+ if (is_singlestepping(dc)) {
+ gen_singlestep_exception(dc);
} else {
tcg_gen_lookup_and_goto_ptr();
}
@@ -6265,8 +6300,8 @@ static void m68k_tr_tb_stop(DisasContextBase *dcbase, CPUState *cpu)
* We updated CC_OP and PC in gen_exit_tb, but also modified
* other state that may require returning to the main loop.
*/
- if (dc->base.singlestep_enabled) {
- gen_raise_exception(EXCP_DEBUG);
+ if (is_singlestepping(dc)) {
+ gen_singlestep_exception(dc);
} else {
tcg_gen_exit_tb(NULL, 0);
}
diff --git a/target/microblaze/cpu.c b/target/microblaze/cpu.c
index 433ba20203..72d8f2a0da 100644
--- a/target/microblaze/cpu.c
+++ b/target/microblaze/cpu.c
@@ -352,9 +352,17 @@ static ObjectClass *mb_cpu_class_by_name(const char *cpu_model)
return object_class_by_name(TYPE_MICROBLAZE_CPU);
}
+#ifndef CONFIG_USER_ONLY
+#include "hw/core/sysemu-cpu-ops.h"
+
+static const struct SysemuCPUOps mb_sysemu_ops = {
+ .get_phys_page_attrs_debug = mb_cpu_get_phys_page_attrs_debug,
+};
+#endif
+
#include "hw/core/tcg-cpu-ops.h"
-static struct TCGCPUOps mb_tcg_ops = {
+static const struct TCGCPUOps mb_tcg_ops = {
.initialize = mb_tcg_init,
.synchronize_from_tb = mb_cpu_synchronize_from_tb,
.cpu_exec_interrupt = mb_cpu_exec_interrupt,
@@ -386,8 +394,8 @@ static void mb_cpu_class_init(ObjectClass *oc, void *data)
cc->gdb_write_register = mb_cpu_gdb_write_register;
#ifndef CONFIG_USER_ONLY
- cc->get_phys_page_attrs_debug = mb_cpu_get_phys_page_attrs_debug;
dc->vmsd = &vmstate_mb_cpu;
+ cc->sysemu_ops = &mb_sysemu_ops;
#endif
device_class_set_props(dc, mb_properties);
cc->gdb_num_core_regs = 32 + 27;
diff --git a/target/mips/cpu-qom.h b/target/mips/cpu-qom.h
index 826ab13019..dda0c911fa 100644
--- a/target/mips/cpu-qom.h
+++ b/target/mips/cpu-qom.h
@@ -47,6 +47,9 @@ struct MIPSCPUClass {
DeviceRealize parent_realize;
DeviceReset parent_reset;
const struct mips_def_t *cpu_def;
+
+ /* Used for the jazz board to modify mips_cpu_do_transaction_failed. */
+ bool no_data_aborts;
};
diff --git a/target/mips/cpu.c b/target/mips/cpu.c
index 1ad2fe4aa3..96236abc00 100644
--- a/target/mips/cpu.c
+++ b/target/mips/cpu.c
@@ -521,13 +521,22 @@ static Property mips_cpu_properties[] = {
DEFINE_PROP_END_OF_LIST()
};
+#ifndef CONFIG_USER_ONLY
+#include "hw/core/sysemu-cpu-ops.h"
+
+static const struct SysemuCPUOps mips_sysemu_ops = {
+ .get_phys_page_debug = mips_cpu_get_phys_page_debug,
+ .legacy_vmsd = &vmstate_mips_cpu,
+};
+#endif
+
#ifdef CONFIG_TCG
#include "hw/core/tcg-cpu-ops.h"
/*
* NB: cannot be const, as some elements are changed for specific
* mips hardware (see hw/mips/jazz.c).
*/
-static struct TCGCPUOps mips_tcg_ops = {
+static const struct TCGCPUOps mips_tcg_ops = {
.initialize = mips_tcg_init,
.synchronize_from_tb = mips_cpu_synchronize_from_tb,
.cpu_exec_interrupt = mips_cpu_exec_interrupt,
@@ -560,8 +569,7 @@ static void mips_cpu_class_init(ObjectClass *c, void *data)
cc->gdb_read_register = mips_cpu_gdb_read_register;
cc->gdb_write_register = mips_cpu_gdb_write_register;
#ifndef CONFIG_USER_ONLY
- cc->get_phys_page_debug = mips_cpu_get_phys_page_debug;
- cc->vmsd = &vmstate_mips_cpu;
+ cc->sysemu_ops = &mips_sysemu_ops;
#endif
cc->disas_set_info = mips_cpu_disas_set_info;
cc->gdb_num_core_regs = 73;
diff --git a/target/mips/tcg/op_helper.c b/target/mips/tcg/op_helper.c
index ce1549c985..fafbf1faca 100644
--- a/target/mips/tcg/op_helper.c
+++ b/target/mips/tcg/op_helper.c
@@ -409,11 +409,12 @@ void mips_cpu_do_transaction_failed(CPUState *cs, hwaddr physaddr,
MemTxResult response, uintptr_t retaddr)
{
MIPSCPU *cpu = MIPS_CPU(cs);
+ MIPSCPUClass *mcc = MIPS_CPU_GET_CLASS(cpu);
CPUMIPSState *env = &cpu->env;
if (access_type == MMU_INST_FETCH) {
do_raise_exception(env, EXCP_IBE, retaddr);
- } else {
+ } else if (!mcc->no_data_aborts) {
do_raise_exception(env, EXCP_DBE, retaddr);
}
}
diff --git a/target/nios2/cpu.c b/target/nios2/cpu.c
index e9c9fc3a38..5e37defef8 100644
--- a/target/nios2/cpu.c
+++ b/target/nios2/cpu.c
@@ -207,9 +207,17 @@ static Property nios2_properties[] = {
DEFINE_PROP_END_OF_LIST(),
};
+#ifndef CONFIG_USER_ONLY
+#include "hw/core/sysemu-cpu-ops.h"
+
+static const struct SysemuCPUOps nios2_sysemu_ops = {
+ .get_phys_page_debug = nios2_cpu_get_phys_page_debug,
+};
+#endif
+
#include "hw/core/tcg-cpu-ops.h"
-static struct TCGCPUOps nios2_tcg_ops = {
+static const struct TCGCPUOps nios2_tcg_ops = {
.initialize = nios2_tcg_init,
.cpu_exec_interrupt = nios2_cpu_exec_interrupt,
.tlb_fill = nios2_cpu_tlb_fill,
@@ -237,7 +245,7 @@ static void nios2_cpu_class_init(ObjectClass *oc, void *data)
cc->set_pc = nios2_cpu_set_pc;
cc->disas_set_info = nios2_cpu_disas_set_info;
#ifndef CONFIG_USER_ONLY
- cc->get_phys_page_debug = nios2_cpu_get_phys_page_debug;
+ cc->sysemu_ops = &nios2_sysemu_ops;
#endif
cc->gdb_read_register = nios2_cpu_gdb_read_register;
cc->gdb_write_register = nios2_cpu_gdb_write_register;
diff --git a/target/openrisc/cpu.c b/target/openrisc/cpu.c
index 2c64842f46..bd34e429ec 100644
--- a/target/openrisc/cpu.c
+++ b/target/openrisc/cpu.c
@@ -174,9 +174,17 @@ static void openrisc_any_initfn(Object *obj)
| (IMMUCFGR_NTS & (ctz32(TLB_SIZE) << 2));
}
+#ifndef CONFIG_USER_ONLY
+#include "hw/core/sysemu-cpu-ops.h"
+
+static const struct SysemuCPUOps openrisc_sysemu_ops = {
+ .get_phys_page_debug = openrisc_cpu_get_phys_page_debug,
+};
+#endif
+
#include "hw/core/tcg-cpu-ops.h"
-static struct TCGCPUOps openrisc_tcg_ops = {
+static const struct TCGCPUOps openrisc_tcg_ops = {
.initialize = openrisc_translate_init,
.cpu_exec_interrupt = openrisc_cpu_exec_interrupt,
.tlb_fill = openrisc_cpu_tlb_fill,
@@ -203,8 +211,8 @@ static void openrisc_cpu_class_init(ObjectClass *oc, void *data)
cc->gdb_read_register = openrisc_cpu_gdb_read_register;
cc->gdb_write_register = openrisc_cpu_gdb_write_register;
#ifndef CONFIG_USER_ONLY
- cc->get_phys_page_debug = openrisc_cpu_get_phys_page_debug;
dc->vmsd = &vmstate_openrisc_cpu;
+ cc->sysemu_ops = &openrisc_sysemu_ops;
#endif
cc->gdb_num_core_regs = 32 + 3;
cc->disas_set_info = openrisc_disas_set_info;
diff --git a/target/ppc/cpu_init.c b/target/ppc/cpu_init.c
index 22ecbccad8..7bdb443114 100644
--- a/target/ppc/cpu_init.c
+++ b/target/ppc/cpu_init.c
@@ -9263,10 +9263,22 @@ static Property ppc_cpu_properties[] = {
DEFINE_PROP_END_OF_LIST(),
};
+#ifndef CONFIG_USER_ONLY
+#include "hw/core/sysemu-cpu-ops.h"
+
+static const struct SysemuCPUOps ppc_sysemu_ops = {
+ .get_phys_page_debug = ppc_cpu_get_phys_page_debug,
+ .write_elf32_note = ppc32_cpu_write_elf32_note,
+ .write_elf64_note = ppc64_cpu_write_elf64_note,
+ .virtio_is_big_endian = ppc_cpu_is_big_endian,
+ .legacy_vmsd = &vmstate_ppc_cpu,
+};
+#endif
+
#ifdef CONFIG_TCG
#include "hw/core/tcg-cpu-ops.h"
-static struct TCGCPUOps ppc_tcg_ops = {
+static const struct TCGCPUOps ppc_tcg_ops = {
.initialize = ppc_translate_init,
.cpu_exec_interrupt = ppc_cpu_exec_interrupt,
.tlb_fill = ppc_cpu_tlb_fill,
@@ -9304,12 +9316,7 @@ static void ppc_cpu_class_init(ObjectClass *oc, void *data)
cc->gdb_read_register = ppc_cpu_gdb_read_register;
cc->gdb_write_register = ppc_cpu_gdb_write_register;
#ifndef CONFIG_USER_ONLY
- cc->get_phys_page_debug = ppc_cpu_get_phys_page_debug;
- cc->vmsd = &vmstate_ppc_cpu;
-#endif
-#if defined(CONFIG_SOFTMMU)
- cc->write_elf64_note = ppc64_cpu_write_elf64_note;
- cc->write_elf32_note = ppc32_cpu_write_elf32_note;
+ cc->sysemu_ops = &ppc_sysemu_ops;
#endif
cc->gdb_num_core_regs = 71;
@@ -9328,9 +9335,6 @@ static void ppc_cpu_class_init(ObjectClass *oc, void *data)
#else
cc->gdb_core_xml_file = "power-core.xml";
#endif
-#ifndef CONFIG_USER_ONLY
- cc->virtio_is_big_endian = ppc_cpu_is_big_endian;
-#endif
cc->disas_set_info = ppc_disas_set_info;
dc->fw_name = "PowerPC,UNKNOWN";
diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
index 3191fd0082..1f1cef1d6a 100644
--- a/target/riscv/cpu.c
+++ b/target/riscv/cpu.c
@@ -596,9 +596,20 @@ static const char *riscv_gdb_get_dynamic_xml(CPUState *cs, const char *xmlname)
return NULL;
}
+#ifndef CONFIG_USER_ONLY
+#include "hw/core/sysemu-cpu-ops.h"
+
+static const struct SysemuCPUOps riscv_sysemu_ops = {
+ .get_phys_page_debug = riscv_cpu_get_phys_page_debug,
+ .write_elf64_note = riscv_cpu_write_elf64_note,
+ .write_elf32_note = riscv_cpu_write_elf32_note,
+ .legacy_vmsd = &vmstate_riscv_cpu,
+};
+#endif
+
#include "hw/core/tcg-cpu-ops.h"
-static struct TCGCPUOps riscv_tcg_ops = {
+static const struct TCGCPUOps riscv_tcg_ops = {
.initialize = riscv_translate_init,
.synchronize_from_tb = riscv_cpu_synchronize_from_tb,
.cpu_exec_interrupt = riscv_cpu_exec_interrupt,
@@ -637,11 +648,7 @@ static void riscv_cpu_class_init(ObjectClass *c, void *data)
cc->gdb_stop_before_watchpoint = true;
cc->disas_set_info = riscv_cpu_disas_set_info;
#ifndef CONFIG_USER_ONLY
- cc->get_phys_page_debug = riscv_cpu_get_phys_page_debug;
- /* For now, mark unmigratable: */
- cc->vmsd = &vmstate_riscv_cpu;
- cc->write_elf64_note = riscv_cpu_write_elf64_note;
- cc->write_elf32_note = riscv_cpu_write_elf32_note;
+ cc->sysemu_ops = &riscv_sysemu_ops;
#endif
cc->gdb_arch_name = riscv_gdb_arch_name;
cc->gdb_get_dynamic_xml = riscv_gdb_get_dynamic_xml;
diff --git a/target/rx/cpu.c b/target/rx/cpu.c
index 7ac6618b26..96cc96e514 100644
--- a/target/rx/cpu.c
+++ b/target/rx/cpu.c
@@ -173,9 +173,17 @@ static void rx_cpu_init(Object *obj)
qdev_init_gpio_in(DEVICE(cpu), rx_cpu_set_irq, 2);
}
+#ifndef CONFIG_USER_ONLY
+#include "hw/core/sysemu-cpu-ops.h"
+
+static const struct SysemuCPUOps rx_sysemu_ops = {
+ .get_phys_page_debug = rx_cpu_get_phys_page_debug,
+};
+#endif
+
#include "hw/core/tcg-cpu-ops.h"
-static struct TCGCPUOps rx_tcg_ops = {
+static const struct TCGCPUOps rx_tcg_ops = {
.initialize = rx_translate_init,
.synchronize_from_tb = rx_cpu_synchronize_from_tb,
.cpu_exec_interrupt = rx_cpu_exec_interrupt,
@@ -202,9 +210,11 @@ static void rx_cpu_class_init(ObjectClass *klass, void *data)
cc->dump_state = rx_cpu_dump_state;
cc->set_pc = rx_cpu_set_pc;
+#ifndef CONFIG_USER_ONLY
+ cc->sysemu_ops = &rx_sysemu_ops;
+#endif
cc->gdb_read_register = rx_cpu_gdb_read_register;
cc->gdb_write_register = rx_cpu_gdb_write_register;
- cc->get_phys_page_debug = rx_cpu_get_phys_page_debug;
cc->disas_set_info = rx_cpu_disas_set_info;
cc->gdb_num_core_regs = 26;
diff --git a/target/s390x/cpu.c b/target/s390x/cpu.c
index 64455cf309..890f382a36 100644
--- a/target/s390x/cpu.c
+++ b/target/s390x/cpu.c
@@ -476,10 +476,21 @@ static void s390_cpu_reset_full(DeviceState *dev)
return s390_cpu_reset(s, S390_CPU_RESET_CLEAR);
}
+#ifndef CONFIG_USER_ONLY
+#include "hw/core/sysemu-cpu-ops.h"
+
+static const struct SysemuCPUOps s390_sysemu_ops = {
+ .get_phys_page_debug = s390_cpu_get_phys_page_debug,
+ .get_crash_info = s390_cpu_get_crash_info,
+ .write_elf64_note = s390_cpu_write_elf64_note,
+ .legacy_vmsd = &vmstate_s390_cpu,
+};
+#endif
+
#ifdef CONFIG_TCG
#include "hw/core/tcg-cpu-ops.h"
-static struct TCGCPUOps s390_tcg_ops = {
+static const struct TCGCPUOps s390_tcg_ops = {
.initialize = s390x_translate_init,
.tlb_fill = s390_cpu_tlb_fill,
@@ -515,10 +526,7 @@ static void s390_cpu_class_init(ObjectClass *oc, void *data)
cc->gdb_read_register = s390_cpu_gdb_read_register;
cc->gdb_write_register = s390_cpu_gdb_write_register;
#ifndef CONFIG_USER_ONLY
- cc->get_phys_page_debug = s390_cpu_get_phys_page_debug;
- cc->vmsd = &vmstate_s390_cpu;
- cc->get_crash_info = s390_cpu_get_crash_info;
- cc->write_elf64_note = s390_cpu_write_elf64_note;
+ cc->sysemu_ops = &s390_sysemu_ops;
#endif
cc->disas_set_info = s390_cpu_disas_set_info;
cc->gdb_num_core_regs = S390_NUM_CORE_REGS;
diff --git a/target/sh4/cpu.c b/target/sh4/cpu.c
index ac65c88f1f..8326922942 100644
--- a/target/sh4/cpu.c
+++ b/target/sh4/cpu.c
@@ -218,14 +218,22 @@ static void superh_cpu_initfn(Object *obj)
env->movcal_backup_tail = &(env->movcal_backup);
}
+#ifndef CONFIG_USER_ONLY
static const VMStateDescription vmstate_sh_cpu = {
.name = "cpu",
.unmigratable = 1,
};
+#include "hw/core/sysemu-cpu-ops.h"
+
+static const struct SysemuCPUOps sh4_sysemu_ops = {
+ .get_phys_page_debug = superh_cpu_get_phys_page_debug,
+};
+#endif
+
#include "hw/core/tcg-cpu-ops.h"
-static struct TCGCPUOps superh_tcg_ops = {
+static const struct TCGCPUOps superh_tcg_ops = {
.initialize = sh4_translate_init,
.synchronize_from_tb = superh_cpu_synchronize_from_tb,
.cpu_exec_interrupt = superh_cpu_exec_interrupt,
@@ -256,13 +264,12 @@ static void superh_cpu_class_init(ObjectClass *oc, void *data)
cc->gdb_read_register = superh_cpu_gdb_read_register;
cc->gdb_write_register = superh_cpu_gdb_write_register;
#ifndef CONFIG_USER_ONLY
- cc->get_phys_page_debug = superh_cpu_get_phys_page_debug;
+ cc->sysemu_ops = &sh4_sysemu_ops;
+ dc->vmsd = &vmstate_sh_cpu;
#endif
cc->disas_set_info = superh_cpu_disas_set_info;
cc->gdb_num_core_regs = 59;
-
- dc->vmsd = &vmstate_sh_cpu;
cc->tcg_ops = &superh_tcg_ops;
}
diff --git a/target/sparc/cpu.c b/target/sparc/cpu.c
index aece2c7dc8..da6b30ec74 100644
--- a/target/sparc/cpu.c
+++ b/target/sparc/cpu.c
@@ -848,10 +848,19 @@ static Property sparc_cpu_properties[] = {
DEFINE_PROP_END_OF_LIST()
};
+#ifndef CONFIG_USER_ONLY
+#include "hw/core/sysemu-cpu-ops.h"
+
+static const struct SysemuCPUOps sparc_sysemu_ops = {
+ .get_phys_page_debug = sparc_cpu_get_phys_page_debug,
+ .legacy_vmsd = &vmstate_sparc_cpu,
+};
+#endif
+
#ifdef CONFIG_TCG
#include "hw/core/tcg-cpu-ops.h"
-static struct TCGCPUOps sparc_tcg_ops = {
+static const struct TCGCPUOps sparc_tcg_ops = {
.initialize = sparc_tcg_init,
.synchronize_from_tb = sparc_cpu_synchronize_from_tb,
.cpu_exec_interrupt = sparc_cpu_exec_interrupt,
@@ -888,8 +897,7 @@ static void sparc_cpu_class_init(ObjectClass *oc, void *data)
cc->gdb_read_register = sparc_cpu_gdb_read_register;
cc->gdb_write_register = sparc_cpu_gdb_write_register;
#ifndef CONFIG_USER_ONLY
- cc->get_phys_page_debug = sparc_cpu_get_phys_page_debug;
- cc->vmsd = &vmstate_sparc_cpu;
+ cc->sysemu_ops = &sparc_sysemu_ops;
#endif
cc->disas_set_info = cpu_sparc_disas_set_info;
diff --git a/target/tricore/cpu.c b/target/tricore/cpu.c
index 0b1e139bcb..b95682b7f0 100644
--- a/target/tricore/cpu.c
+++ b/target/tricore/cpu.c
@@ -142,9 +142,15 @@ static void tc27x_initfn(Object *obj)
set_feature(&cpu->env, TRICORE_FEATURE_161);
}
+#include "hw/core/sysemu-cpu-ops.h"
+
+static const struct SysemuCPUOps tricore_sysemu_ops = {
+ .get_phys_page_debug = tricore_cpu_get_phys_page_debug,
+};
+
#include "hw/core/tcg-cpu-ops.h"
-static struct TCGCPUOps tricore_tcg_ops = {
+static const struct TCGCPUOps tricore_tcg_ops = {
.initialize = tricore_tcg_init,
.synchronize_from_tb = tricore_cpu_synchronize_from_tb,
.tlb_fill = tricore_cpu_tlb_fill,
@@ -170,7 +176,7 @@ static void tricore_cpu_class_init(ObjectClass *c, void *data)
cc->dump_state = tricore_cpu_dump_state;
cc->set_pc = tricore_cpu_set_pc;
- cc->get_phys_page_debug = tricore_cpu_get_phys_page_debug;
+ cc->sysemu_ops = &tricore_sysemu_ops;
cc->tcg_ops = &tricore_tcg_ops;
}
diff --git a/target/xtensa/cpu.c b/target/xtensa/cpu.c
index 210ef80092..58ec3a0862 100644
--- a/target/xtensa/cpu.c
+++ b/target/xtensa/cpu.c
@@ -175,14 +175,22 @@ static void xtensa_cpu_initfn(Object *obj)
#endif
}
+#ifndef CONFIG_USER_ONLY
static const VMStateDescription vmstate_xtensa_cpu = {
.name = "cpu",
.unmigratable = 1,
};
+#include "hw/core/sysemu-cpu-ops.h"
+
+static const struct SysemuCPUOps xtensa_sysemu_ops = {
+ .get_phys_page_debug = xtensa_cpu_get_phys_page_debug,
+};
+#endif
+
#include "hw/core/tcg-cpu-ops.h"
-static struct TCGCPUOps xtensa_tcg_ops = {
+static const struct TCGCPUOps xtensa_tcg_ops = {
.initialize = xtensa_translate_init,
.cpu_exec_interrupt = xtensa_cpu_exec_interrupt,
.tlb_fill = xtensa_cpu_tlb_fill,
@@ -214,10 +222,10 @@ static void xtensa_cpu_class_init(ObjectClass *oc, void *data)
cc->gdb_write_register = xtensa_cpu_gdb_write_register;
cc->gdb_stop_before_watchpoint = true;
#ifndef CONFIG_USER_ONLY
- cc->get_phys_page_debug = xtensa_cpu_get_phys_page_debug;
+ cc->sysemu_ops = &xtensa_sysemu_ops;
+ dc->vmsd = &vmstate_xtensa_cpu;
#endif
cc->disas_set_info = xtensa_cpu_disas_set_info;
- dc->vmsd = &vmstate_xtensa_cpu;
cc->tcg_ops = &xtensa_tcg_ops;
}
diff --git a/tcg/aarch64/tcg-target.c.inc b/tcg/aarch64/tcg-target.c.inc
index f07ba98aa4..5bd366f2d4 100644
--- a/tcg/aarch64/tcg-target.c.inc
+++ b/tcg/aarch64/tcg-target.c.inc
@@ -1291,9 +1291,8 @@ static inline void tcg_out_rotr(TCGContext *s, TCGType ext,
static inline void tcg_out_rotl(TCGContext *s, TCGType ext,
TCGReg rd, TCGReg rn, unsigned int m)
{
- int bits = ext ? 64 : 32;
- int max = bits - 1;
- tcg_out_extr(s, ext, rd, rn, rn, bits - (m & max));
+ int max = ext ? 63 : 31;
+ tcg_out_extr(s, ext, rd, rn, rn, -m & max);
}
static inline void tcg_out_dep(TCGContext *s, TCGType ext, TCGReg rd,
diff --git a/tests/qtest/fuzz/fuzz.c b/tests/qtest/fuzz/fuzz.c
index 04b70e114b..5f77c84983 100644
--- a/tests/qtest/fuzz/fuzz.c
+++ b/tests/qtest/fuzz/fuzz.c
@@ -16,6 +16,7 @@
#include <wordexp.h>
#include "qemu/datadir.h"
+#include "sysemu/sysemu.h"
#include "sysemu/qtest.h"
#include "sysemu/runstate.h"
#include "qemu/main-loop.h"
diff --git a/tests/unit/test-replication.c b/tests/unit/test-replication.c
index b067240add..afff908d77 100644
--- a/tests/unit/test-replication.c
+++ b/tests/unit/test-replication.c
@@ -14,7 +14,7 @@
#include "qapi/qmp/qdict.h"
#include "qemu/option.h"
#include "qemu/main-loop.h"
-#include "replication.h"
+#include "block/replication.h"
#include "block/block_int.h"
#include "block/qdict.h"
#include "sysemu/block-backend.h"
diff --git a/tools/virtiofsd/buffer.c b/tools/virtiofsd/buffer.c
index 874f01c488..b5f04be356 100644
--- a/tools/virtiofsd/buffer.c
+++ b/tools/virtiofsd/buffer.c
@@ -37,7 +37,7 @@ static ssize_t fuse_buf_writev(struct fuse_buf *out_buf,
struct iovec *iov;
int fd = out_buf->fd;
- iov = calloc(iovcnt, sizeof(struct iovec));
+ iov = g_try_new0(struct iovec, iovcnt);
if (!iov) {
return -ENOMEM;
}
@@ -61,7 +61,7 @@ static ssize_t fuse_buf_writev(struct fuse_buf *out_buf,
res = -errno;
}
- free(iov);
+ g_free(iov);
return res;
}
diff --git a/tools/virtiofsd/fuse_opt.c b/tools/virtiofsd/fuse_opt.c
index f0ab8d22f4..9d371448e9 100644
--- a/tools/virtiofsd/fuse_opt.c
+++ b/tools/virtiofsd/fuse_opt.c
@@ -272,7 +272,7 @@ static int process_opt_sep_arg(struct fuse_opt_context *ctx,
}
param = ctx->argv[ctx->argctr];
- newarg = malloc(sep + strlen(param) + 1);
+ newarg = g_try_malloc(sep + strlen(param) + 1);
if (!newarg) {
return alloc_failed();
}
@@ -280,7 +280,7 @@ static int process_opt_sep_arg(struct fuse_opt_context *ctx,
memcpy(newarg, arg, sep);
strcpy(newarg + sep, param);
res = process_opt(ctx, opt, sep, newarg, iso);
- free(newarg);
+ g_free(newarg);
return res;
}
diff --git a/tools/virtiofsd/fuse_virtio.c b/tools/virtiofsd/fuse_virtio.c
index 9efdbd8ffd..fa4aff9b0e 100644
--- a/tools/virtiofsd/fuse_virtio.c
+++ b/tools/virtiofsd/fuse_virtio.c
@@ -366,14 +366,12 @@ int virtio_send_data_iov(struct fuse_session *se, struct fuse_chan *ch,
if (in_len < sizeof(struct fuse_out_header)) {
fuse_log(FUSE_LOG_ERR, "%s: elem %d too short for out_header\n",
__func__, elem->index);
- ret = E2BIG;
- goto err;
+ return E2BIG;
}
if (in_len < tosend_len) {
fuse_log(FUSE_LOG_ERR, "%s: elem %d too small for data len %zd\n",
__func__, elem->index, tosend_len);
- ret = E2BIG;
- goto err;
+ return E2BIG;
}
/* TODO: Limit to 'len' */
@@ -389,68 +387,46 @@ int virtio_send_data_iov(struct fuse_session *se, struct fuse_chan *ch,
memcpy(in_sg_cpy, in_sg, sizeof(struct iovec) * in_num);
/* These get updated as we skip */
struct iovec *in_sg_ptr = in_sg_cpy;
- int in_sg_cpy_count = in_num;
+ unsigned int in_sg_cpy_count = in_num;
/* skip over parts of in_sg that contained the header iov */
- size_t skip_size = iov_len;
+ iov_discard_front(&in_sg_ptr, &in_sg_cpy_count, iov_len);
- size_t in_sg_left = 0;
do {
- while (skip_size != 0 && in_sg_cpy_count) {
- if (skip_size >= in_sg_ptr[0].iov_len) {
- skip_size -= in_sg_ptr[0].iov_len;
- in_sg_ptr++;
- in_sg_cpy_count--;
- } else {
- in_sg_ptr[0].iov_len -= skip_size;
- in_sg_ptr[0].iov_base += skip_size;
- break;
- }
- }
+ fuse_log(FUSE_LOG_DEBUG, "%s: in_sg_cpy_count=%d len remaining=%zd\n",
+ __func__, in_sg_cpy_count, len);
- int i;
- for (i = 0, in_sg_left = 0; i < in_sg_cpy_count; i++) {
- in_sg_left += in_sg_ptr[i].iov_len;
- }
- fuse_log(FUSE_LOG_DEBUG,
- "%s: after skip skip_size=%zd in_sg_cpy_count=%d "
- "in_sg_left=%zd\n",
- __func__, skip_size, in_sg_cpy_count, in_sg_left);
ret = preadv(buf->buf[0].fd, in_sg_ptr, in_sg_cpy_count,
buf->buf[0].pos);
if (ret == -1) {
ret = errno;
+ if (ret == EINTR) {
+ continue;
+ }
fuse_log(FUSE_LOG_DEBUG, "%s: preadv failed (%m) len=%zd\n",
__func__, len);
- goto err;
+ return ret;
}
- fuse_log(FUSE_LOG_DEBUG, "%s: preadv ret=%d len=%zd\n", __func__,
- ret, len);
- if (ret < len && ret) {
- fuse_log(FUSE_LOG_DEBUG, "%s: ret < len\n", __func__);
- /* Skip over this much next time around */
- skip_size = ret;
- buf->buf[0].pos += ret;
- len -= ret;
- /* Lets do another read */
- continue;
- }
if (!ret) {
/* EOF case? */
- fuse_log(FUSE_LOG_DEBUG, "%s: !ret in_sg_left=%zd\n", __func__,
- in_sg_left);
+ fuse_log(FUSE_LOG_DEBUG, "%s: !ret len remaining=%zd\n", __func__,
+ len);
break;
}
- if (ret != len) {
- fuse_log(FUSE_LOG_DEBUG, "%s: ret!=len\n", __func__);
- ret = EIO;
- goto err;
- }
- in_sg_left -= ret;
+ fuse_log(FUSE_LOG_DEBUG, "%s: preadv ret=%d len=%zd\n", __func__,
+ ret, len);
+
len -= ret;
- } while (in_sg_left);
+ /* Short read. Retry reading remaining bytes */
+ if (len) {
+ fuse_log(FUSE_LOG_DEBUG, "%s: ret < len\n", __func__);
+ /* Skip over this much next time around */
+ iov_discard_front(&in_sg_ptr, &in_sg_cpy_count, ret);
+ buf->buf[0].pos += ret;
+ }
+ } while (len);
/* Need to fix out->len on EOF */
if (len) {
@@ -460,21 +436,14 @@ int virtio_send_data_iov(struct fuse_session *se, struct fuse_chan *ch,
out_sg->len = tosend_len;
}
- ret = 0;
-
vu_dispatch_rdlock(qi->virtio_dev);
pthread_mutex_lock(&qi->vq_lock);
vu_queue_push(dev, q, elem, tosend_len);
vu_queue_notify(dev, q);
pthread_mutex_unlock(&qi->vq_lock);
vu_dispatch_unlock(qi->virtio_dev);
-
-err:
- if (ret == 0) {
- req->reply_sent = true;
- }
-
- return ret;
+ req->reply_sent = true;
+ return 0;
}
static __thread bool clone_fs_called;
diff --git a/util/qemu-config.c b/util/qemu-config.c
index 670bd6ebca..34974c4b47 100644
--- a/util/qemu-config.c
+++ b/util/qemu-config.c
@@ -16,6 +16,7 @@ static QemuOptsList *find_list(QemuOptsList **lists, const char *group,
{
int i;
+ qemu_load_module_for_opts(group);
for (i = 0; lists[i] != NULL; i++) {
if (strcmp(lists[i]->name, group) == 0)
break;