diff --git a/.gitlab-ci.d/buildtest.yml b/.gitlab-ci.d/buildtest.yml index da72f7c690..0a01746cea 100644 --- a/.gitlab-ci.d/buildtest.yml +++ b/.gitlab-ci.d/buildtest.yml @@ -41,7 +41,7 @@ build-system-ubuntu: variables: IMAGE: ubuntu2204 CONFIGURE_ARGS: --enable-docs - TARGETS: alpha-softmmu microblazeel-softmmu mips64el-softmmu + TARGETS: alpha-softmmu microblaze-softmmu mips64el-softmmu MAKE_CHECK_ARGS: check-build check-system-ubuntu: @@ -70,7 +70,7 @@ build-system-debian: needs: job: amd64-debian-container variables: - IMAGE: debian-amd64 + IMAGE: debian CONFIGURE_ARGS: --with-coroutine=sigaltstack TARGETS: arm-softmmu i386-softmmu riscv64-softmmu sh4eb-softmmu sparc-softmmu xtensa-softmmu @@ -82,7 +82,7 @@ check-system-debian: - job: build-system-debian artifacts: true variables: - IMAGE: debian-amd64 + IMAGE: debian MAKE_CHECK_ARGS: check avocado-system-debian: @@ -91,7 +91,7 @@ avocado-system-debian: - job: build-system-debian artifacts: true variables: - IMAGE: debian-amd64 + IMAGE: debian MAKE_CHECK_ARGS: check-avocado AVOCADO_TAGS: arch:arm arch:i386 arch:riscv64 arch:sh4 arch:sparc arch:xtensa @@ -101,7 +101,7 @@ crash-test-debian: - job: build-system-debian artifacts: true variables: - IMAGE: debian-amd64 + IMAGE: debian script: - cd build - make NINJA=":" check-venv @@ -217,6 +217,36 @@ avocado-system-opensuse: MAKE_CHECK_ARGS: check-avocado AVOCADO_TAGS: arch:s390x arch:x86_64 arch:aarch64 +# +# Flaky tests. We don't run these by default and they are allow fail +# but often the CI system is the only way to trigger the failures. +# + +build-system-flaky: + extends: + - .native_build_job_template + - .native_build_artifact_template + needs: + job: amd64-debian-container + variables: + IMAGE: debian + QEMU_JOB_OPTIONAL: 1 + TARGETS: aarch64-softmmu arm-softmmu mips64el-softmmu + ppc64-softmmu rx-softmmu s390x-softmmu sh4-softmmu x86_64-softmmu + MAKE_CHECK_ARGS: check-build + +avocado-system-flaky: + extends: .avocado_test_job_template + needs: + - job: build-system-flaky + artifacts: true + allow_failure: true + variables: + IMAGE: debian + MAKE_CHECK_ARGS: check-avocado + QEMU_JOB_OPTIONAL: 1 + QEMU_TEST_FLAKY_TESTS: 1 + AVOCADO_TAGS: flaky # This jobs explicitly disable TCG (--disable-tcg), KVM is detected by # the configure script. The container doesn't contain Xen headers so @@ -589,7 +619,7 @@ build-tools-and-docs-debian: # when running on 'master' we use pre-existing container optional: true variables: - IMAGE: debian-amd64 + IMAGE: debian MAKE_CHECK_ARGS: check-unit ctags TAGS cscope CONFIGURE_ARGS: --disable-system --disable-user --enable-docs --enable-tools QEMU_JOB_PUBLISH: 1 @@ -609,7 +639,7 @@ build-tools-and-docs-debian: # of what topic branch they're currently using pages: extends: .base_job_template - image: $CI_REGISTRY_IMAGE/qemu/debian-amd64:$QEMU_CI_CONTAINER_TAG + image: $CI_REGISTRY_IMAGE/qemu/debian:$QEMU_CI_CONTAINER_TAG stage: test needs: - job: build-tools-and-docs-debian @@ -617,7 +647,10 @@ pages: - mkdir -p public # HTML-ised source tree - make gtags - - htags -anT --tree-view=filetree -m qemu_init + # We unset variables to work around a bug in some htags versions + # which causes it to fail when the environment is large + - CI_COMMIT_MESSAGE= CI_COMMIT_TAG_MESSAGE= htags + -anT --tree-view=filetree -m qemu_init -t "Welcome to the QEMU sourcecode" - mv HTML public/src # Project documentation diff --git a/.gitlab-ci.d/cirrus.yml b/.gitlab-ci.d/cirrus.yml index e7f1f83c2c..64f2e25afa 100644 --- a/.gitlab-ci.d/cirrus.yml +++ b/.gitlab-ci.d/cirrus.yml @@ -59,13 +59,13 @@ x64-freebsd-13-build: INSTALL_COMMAND: pkg install -y TEST_TARGETS: check -aarch64-macos-12-base-build: +aarch64-macos-13-base-build: extends: .cirrus_build_job variables: - NAME: macos-12 + NAME: macos-13 CIRRUS_VM_INSTANCE_TYPE: macos_instance CIRRUS_VM_IMAGE_SELECTOR: image - CIRRUS_VM_IMAGE_NAME: ghcr.io/cirruslabs/macos-monterey-base:latest + CIRRUS_VM_IMAGE_NAME: ghcr.io/cirruslabs/macos-ventura-base:latest CIRRUS_VM_CPUS: 12 CIRRUS_VM_RAM: 24G UPDATE_COMMAND: brew update @@ -74,6 +74,22 @@ aarch64-macos-12-base-build: PKG_CONFIG_PATH: /opt/homebrew/curl/lib/pkgconfig:/opt/homebrew/ncurses/lib/pkgconfig:/opt/homebrew/readline/lib/pkgconfig TEST_TARGETS: check-unit check-block check-qapi-schema check-softfloat check-qtest-x86_64 +aarch64-macos-14-base-build: + extends: .cirrus_build_job + variables: + NAME: macos-14 + CIRRUS_VM_INSTANCE_TYPE: macos_instance + CIRRUS_VM_IMAGE_SELECTOR: image + CIRRUS_VM_IMAGE_NAME: ghcr.io/cirruslabs/macos-sonoma-base:latest + CIRRUS_VM_CPUS: 12 + CIRRUS_VM_RAM: 24G + UPDATE_COMMAND: brew update + INSTALL_COMMAND: brew install + PATH_EXTRA: /opt/homebrew/ccache/libexec:/opt/homebrew/gettext/bin + PKG_CONFIG_PATH: /opt/homebrew/curl/lib/pkgconfig:/opt/homebrew/ncurses/lib/pkgconfig:/opt/homebrew/readline/lib/pkgconfig + TEST_TARGETS: check-unit check-block check-qapi-schema check-softfloat check-qtest-x86_64 + QEMU_JOB_OPTIONAL: 1 + # The following jobs run VM-based tests via KVM on a Linux-based Cirrus-CI job .cirrus_kvm_job: diff --git a/.gitlab-ci.d/cirrus/macos-12.vars b/.gitlab-ci.d/cirrus/macos-13.vars similarity index 95% rename from .gitlab-ci.d/cirrus/macos-12.vars rename to .gitlab-ci.d/cirrus/macos-13.vars index 5f3fb346d1..534f029956 100644 --- a/.gitlab-ci.d/cirrus/macos-12.vars +++ b/.gitlab-ci.d/cirrus/macos-13.vars @@ -1,6 +1,6 @@ # THIS FILE WAS AUTO-GENERATED # -# $ lcitool variables macos-12 qemu +# $ lcitool variables macos-13 qemu # # https://gitlab.com/libvirt/libvirt-ci diff --git a/.gitlab-ci.d/cirrus/macos-14.vars b/.gitlab-ci.d/cirrus/macos-14.vars new file mode 100644 index 0000000000..43070f4a26 --- /dev/null +++ b/.gitlab-ci.d/cirrus/macos-14.vars @@ -0,0 +1,16 @@ +# THIS FILE WAS AUTO-GENERATED +# +# $ lcitool variables macos-14 qemu +# +# https://gitlab.com/libvirt/libvirt-ci + +CCACHE='/opt/homebrew/bin/ccache' +CPAN_PKGS='' +CROSS_PKGS='' +MAKE='/opt/homebrew/bin/gmake' +NINJA='/opt/homebrew/bin/ninja' +PACKAGING_COMMAND='brew' +PIP3='/opt/homebrew/bin/pip3' +PKGS='bash bc bison bzip2 capstone ccache cmocka ctags curl dbus diffutils dtc flex gcovr gettext git glib gnu-sed gnutls gtk+3 jemalloc jpeg-turbo json-c libepoxy libffi libgcrypt libiscsi libnfs libpng libslirp libssh libtasn1 libusb llvm lzo make meson mtools ncurses nettle ninja pixman pkg-config python3 rpm2cpio sdl2 sdl2_image snappy socat sparse spice-protocol swtpm tesseract usbredir vde vte3 xorriso zlib zstd' +PYPI_PKGS='PyYAML numpy pillow sphinx sphinx-rtd-theme tomli' +PYTHON='/opt/homebrew/bin/python3' diff --git a/.gitlab-ci.d/container-cross.yml b/.gitlab-ci.d/container-cross.yml index 463ac493ad..8d235cbea0 100644 --- a/.gitlab-ci.d/container-cross.yml +++ b/.gitlab-ci.d/container-cross.yml @@ -46,6 +46,12 @@ loongarch-debian-cross-container: variables: NAME: debian-loongarch-cross +i686-debian-cross-container: + extends: .container_job_template + stage: containers + variables: + NAME: debian-i686-cross + mips64el-debian-cross-container: extends: .container_job_template stage: containers @@ -95,11 +101,6 @@ cris-fedora-cross-container: 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: diff --git a/.gitlab-ci.d/containers.yml b/.gitlab-ci.d/containers.yml index 8637a13d86..ae79d4c58b 100644 --- a/.gitlab-ci.d/containers.yml +++ b/.gitlab-ci.d/containers.yml @@ -11,7 +11,7 @@ amd64-debian-container: extends: .container_job_template stage: containers variables: - NAME: debian-amd64 + NAME: debian amd64-ubuntu2204-container: extends: .container_job_template diff --git a/.gitlab-ci.d/crossbuilds.yml b/.gitlab-ci.d/crossbuilds.yml index ac71a2abd3..d19d98cde0 100644 --- a/.gitlab-ci.d/crossbuilds.yml +++ b/.gitlab-ci.d/crossbuilds.yml @@ -37,25 +37,25 @@ cross-arm64-kvm-only: IMAGE: debian-arm64-cross EXTRA_CONFIGURE_OPTS: --disable-tcg --without-default-features -cross-i386-user: +cross-i686-user: extends: - .cross_user_build_job - .cross_test_artifacts needs: - job: i386-fedora-cross-container + job: i686-debian-cross-container variables: - IMAGE: fedora-i386-cross + IMAGE: debian-i686-cross MAKE_CHECK_ARGS: check -cross-i386-tci: +cross-i686-tci: extends: - .cross_accel_build_job - .cross_test_artifacts timeout: 60m needs: - job: i386-fedora-cross-container + job: i686-debian-cross-container variables: - IMAGE: fedora-i386-cross + IMAGE: debian-i686-cross ACCEL: tcg-interpreter EXTRA_CONFIGURE_OPTS: --target-list=i386-softmmu,i386-linux-user,aarch64-softmmu,aarch64-linux-user,ppc-softmmu,ppc-linux-user --disable-plugins MAKE_CHECK_ARGS: check check-tcg @@ -165,7 +165,7 @@ cross-win32-system: job: win32-fedora-cross-container variables: IMAGE: fedora-win32-cross - EXTRA_CONFIGURE_OPTS: --enable-fdt=internal --disable-plugins + EXTRA_CONFIGURE_OPTS: --enable-fdt=internal CROSS_SKIP_TARGETS: alpha-softmmu avr-softmmu hppa-softmmu m68k-softmmu microblazeel-softmmu mips64el-softmmu nios2-softmmu artifacts: diff --git a/.readthedocs.yml b/.readthedocs.yml index 7fb7b8dd61..0b262469ce 100644 --- a/.readthedocs.yml +++ b/.readthedocs.yml @@ -5,16 +5,21 @@ # Required version: 2 +# Set the version of Python and other tools you might need +build: + os: ubuntu-22.04 + tools: + python: "3.11" + # Build documentation in the docs/ directory with Sphinx sphinx: configuration: docs/conf.py +# We recommend specifying your dependencies to enable reproducible builds: +# https://docs.readthedocs.io/en/stable/guides/reproducible-builds.html +python: + install: + - requirements: docs/requirements.txt + # We want all the document formats formats: all - -# For consistency, we require that QEMU's Sphinx extensions -# run with at least the same minimum version of Python that -# we require for other Python in our codebase (our conf.py -# enforces this, and some code needs it.) -python: - version: 3.6 diff --git a/MAINTAINERS b/MAINTAINERS index ff1238bb98..695e0bd34f 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -174,6 +174,7 @@ F: include/hw/core/tcg-cpu-ops.h F: host/include/*/host/cpuinfo.h F: util/cpuinfo-*.c F: include/tcg/ +F: tests/decode/ FPU emulation M: Aurelien Jarno diff --git a/VERSION b/VERSION index eea587b882..2b0aa21219 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -8.1.90 +8.2.1 diff --git a/accel/tcg/cpu-exec.c b/accel/tcg/cpu-exec.c index d3cb3940b8..b34cd9e524 100644 --- a/accel/tcg/cpu-exec.c +++ b/accel/tcg/cpu-exec.c @@ -183,7 +183,7 @@ static bool tb_lookup_cmp(const void *p, const void *d) const TranslationBlock *tb = p; const struct tb_desc *desc = d; - if ((tb_cflags(tb) & CF_PCREL || tb->pc == desc->pc) && + if (tb->pc == desc->pc && tb_page_addr0(tb) == desc->page_addr0 && tb->cs_base == desc->cs_base && tb->flags == desc->flags && @@ -233,7 +233,7 @@ static TranslationBlock *tb_htable_lookup(CPUState *cpu, vaddr pc, return NULL; } desc.page_addr0 = phys_pc; - h = tb_hash_func(phys_pc, (cflags & CF_PCREL ? 0 : pc), + h = tb_hash_func(phys_pc, pc, flags, cs_base, cflags); return qht_lookup_custom(&tb_ctx.htable, &desc, h, tb_lookup_cmp); } diff --git a/accel/tcg/tb-maint.c b/accel/tcg/tb-maint.c index 3d2a896220..0d069a081e 100644 --- a/accel/tcg/tb-maint.c +++ b/accel/tcg/tb-maint.c @@ -47,7 +47,7 @@ static bool tb_cmp(const void *ap, const void *bp) const TranslationBlock *a = ap; const TranslationBlock *b = bp; - return ((tb_cflags(a) & CF_PCREL || a->pc == b->pc) && + return (a->pc == b->pc && a->cs_base == b->cs_base && a->flags == b->flags && (tb_cflags(a) & ~CF_INVALID) == (tb_cflags(b) & ~CF_INVALID) && @@ -916,7 +916,7 @@ static void do_tb_phys_invalidate(TranslationBlock *tb, bool rm_from_page_list) /* remove the TB from the hash list */ phys_pc = tb_page_addr0(tb); - h = tb_hash_func(phys_pc, (orig_cflags & CF_PCREL ? 0 : tb->pc), + h = tb_hash_func(phys_pc, tb->pc, tb->flags, tb->cs_base, orig_cflags); if (!qht_remove(&tb_ctx.htable, tb, h)) { return; @@ -983,7 +983,7 @@ TranslationBlock *tb_link_page(TranslationBlock *tb) tb_record(tb); /* add in the hash table */ - h = tb_hash_func(tb_page_addr0(tb), (tb->cflags & CF_PCREL ? 0 : tb->pc), + h = tb_hash_func(tb_page_addr0(tb), tb->pc, tb->flags, tb->cs_base, tb->cflags); qht_insert(&tb_ctx.htable, tb, h, &existing_tb); diff --git a/accel/tcg/translate-all.c b/accel/tcg/translate-all.c index b9f81e1606..a4d85fa612 100644 --- a/accel/tcg/translate-all.c +++ b/accel/tcg/translate-all.c @@ -303,7 +303,7 @@ static int setjmp_gen_code(CPUArchState *env, TranslationBlock *tb, } hook = hook->next; } - + //// --- End LibAFL code --- gen_intermediate_code(env_cpu(env), tb, max_insns, pc, host_pc); @@ -320,11 +320,11 @@ static target_ulong reverse_bits(target_ulong num) { unsigned int count = sizeof(num) * 8 - 1; target_ulong reverse_num = num; - - num >>= 1; + + num >>= 1; while(num) { - reverse_num <<= 1; + reverse_num <<= 1; reverse_num |= num & 1; num >>= 1; count--; @@ -358,7 +358,7 @@ TranslationBlock *libafl_gen_edge(CPUState *cpu, target_ulong src_block, (void)existing_tb; assert_memory_lock(); - + struct libafl_edge_hook* hook = libafl_edge_hooks; int no_exec_hook = 1; while (hook) { diff --git a/audio/audio.c b/audio/audio.c index f91e05b72c..7ac74f9e16 100644 --- a/audio/audio.c +++ b/audio/audio.c @@ -1744,7 +1744,7 @@ static AudioState *audio_init(Audiodev *dev, Error **errp) if (driver) { done = !audio_driver_init(s, driver, dev, errp); } else { - error_setg(errp, "Unknown audio driver `%s'\n", drvname); + error_setg(errp, "Unknown audio driver `%s'", drvname); } if (!done) { goto out; @@ -1758,12 +1758,15 @@ static AudioState *audio_init(Audiodev *dev, Error **errp) goto out; } s->dev = dev = e->dev; + QSIMPLEQ_REMOVE_HEAD(&default_audiodevs, next); + g_free(e); drvname = AudiodevDriver_str(dev->driver); driver = audio_driver_lookup(drvname); if (!audio_driver_init(s, driver, dev, NULL)) { break; } - QSIMPLEQ_REMOVE_HEAD(&default_audiodevs, next); + qapi_free_Audiodev(dev); + s->dev = NULL; } } diff --git a/backends/cryptodev.c b/backends/cryptodev.c index e5006bd215..fff89fd62a 100644 --- a/backends/cryptodev.c +++ b/backends/cryptodev.c @@ -398,6 +398,7 @@ static void cryptodev_backend_set_ops(Object *obj, Visitor *v, static void cryptodev_backend_complete(UserCreatable *uc, Error **errp) { + ERRP_GUARD(); CryptoDevBackend *backend = CRYPTODEV_BACKEND(uc); CryptoDevBackendClass *bc = CRYPTODEV_BACKEND_GET_CLASS(uc); uint32_t services; @@ -406,11 +407,20 @@ cryptodev_backend_complete(UserCreatable *uc, Error **errp) QTAILQ_INIT(&backend->opinfos); value = backend->tc.buckets[THROTTLE_OPS_TOTAL].avg; cryptodev_backend_set_throttle(backend, THROTTLE_OPS_TOTAL, value, errp); + if (*errp) { + return; + } value = backend->tc.buckets[THROTTLE_BPS_TOTAL].avg; cryptodev_backend_set_throttle(backend, THROTTLE_BPS_TOTAL, value, errp); + if (*errp) { + return; + } if (bc->init) { bc->init(backend, errp); + if (*errp) { + return; + } } services = backend->conf.crypto_services; diff --git a/block.c b/block.c index eac105a504..bfb0861ec6 100644 --- a/block.c +++ b/block.c @@ -1713,7 +1713,7 @@ open_failed: bdrv_unref_child(bs, bs->file); assert(!bs->file); } - bdrv_graph_wrunlock(); + bdrv_graph_wrunlock(NULL); g_free(bs->opaque); bs->opaque = NULL; @@ -3577,7 +3577,7 @@ int bdrv_set_backing_hd(BlockDriverState *bs, BlockDriverState *backing_hd, bdrv_drained_begin(drain_bs); bdrv_graph_wrlock(backing_hd); ret = bdrv_set_backing_hd_drained(bs, backing_hd, errp); - bdrv_graph_wrunlock(); + bdrv_graph_wrunlock(backing_hd); bdrv_drained_end(drain_bs); bdrv_unref(drain_bs); @@ -3796,7 +3796,7 @@ BdrvChild *bdrv_open_child(const char *filename, child = bdrv_attach_child(parent, bs, bdref_key, child_class, child_role, errp); aio_context_release(ctx); - bdrv_graph_wrunlock(); + bdrv_graph_wrunlock(NULL); return child; } @@ -4652,7 +4652,7 @@ int bdrv_reopen_multiple(BlockReopenQueue *bs_queue, Error **errp) bdrv_graph_wrlock(NULL); tran_commit(tran); - bdrv_graph_wrunlock(); + bdrv_graph_wrunlock(NULL); QTAILQ_FOREACH_REVERSE(bs_entry, bs_queue, entry) { BlockDriverState *bs = bs_entry->state.bs; @@ -4671,7 +4671,7 @@ int bdrv_reopen_multiple(BlockReopenQueue *bs_queue, Error **errp) abort: bdrv_graph_wrlock(NULL); tran_abort(tran); - bdrv_graph_wrunlock(); + bdrv_graph_wrunlock(NULL); QTAILQ_FOREACH_SAFE(bs_entry, bs_queue, entry, next) { if (bs_entry->prepared) { @@ -4857,7 +4857,7 @@ bdrv_reopen_parse_file_or_backing(BDRVReopenState *reopen_state, ret = bdrv_set_file_or_backing_noperm(bs, new_child_bs, is_backing, tran, errp); - bdrv_graph_wrunlock(); + bdrv_graph_wrunlock_ctx(ctx); if (old_ctx != ctx) { aio_context_release(ctx); @@ -5216,7 +5216,7 @@ static void bdrv_close(BlockDriverState *bs) assert(!bs->backing); assert(!bs->file); - bdrv_graph_wrunlock(); + bdrv_graph_wrunlock(bs); g_free(bs->opaque); bs->opaque = NULL; @@ -5511,7 +5511,7 @@ int bdrv_drop_filter(BlockDriverState *bs, Error **errp) bdrv_drained_begin(child_bs); bdrv_graph_wrlock(bs); ret = bdrv_replace_node_common(bs, child_bs, true, true, errp); - bdrv_graph_wrunlock(); + bdrv_graph_wrunlock(bs); bdrv_drained_end(child_bs); return ret; @@ -5593,7 +5593,7 @@ out: tran_finalize(tran, ret); bdrv_refresh_limits(bs_top, NULL, NULL); - bdrv_graph_wrunlock(); + bdrv_graph_wrunlock(bs_top); bdrv_drained_end(bs_top); bdrv_drained_end(bs_new); @@ -5631,7 +5631,7 @@ int bdrv_replace_child_bs(BdrvChild *child, BlockDriverState *new_bs, tran_finalize(tran, ret); - bdrv_graph_wrunlock(); + bdrv_graph_wrunlock(new_bs); bdrv_drained_end(old_bs); bdrv_drained_end(new_bs); bdrv_unref(old_bs); @@ -5720,7 +5720,7 @@ BlockDriverState *bdrv_insert_node(BlockDriverState *bs, QDict *options, bdrv_drained_begin(new_node_bs); bdrv_graph_wrlock(new_node_bs); ret = bdrv_replace_node(bs, new_node_bs, errp); - bdrv_graph_wrunlock(); + bdrv_graph_wrunlock(new_node_bs); bdrv_drained_end(new_node_bs); bdrv_drained_end(bs); bdrv_unref(bs); @@ -6015,7 +6015,7 @@ int bdrv_drop_intermediate(BlockDriverState *top, BlockDriverState *base, * That's a FIXME. */ bdrv_replace_node_common(top, base, false, false, &local_err); - bdrv_graph_wrunlock(); + bdrv_graph_wrunlock(base); if (local_err) { error_report_err(local_err); @@ -6052,7 +6052,7 @@ int bdrv_drop_intermediate(BlockDriverState *top, BlockDriverState *base, goto exit; exit_wrlock: - bdrv_graph_wrunlock(); + bdrv_graph_wrunlock(base); exit: bdrv_drained_end(base); bdrv_unref(top); @@ -7254,6 +7254,16 @@ void bdrv_unref(BlockDriverState *bs) } } +static void bdrv_schedule_unref_bh(void *opaque) +{ + BlockDriverState *bs = opaque; + AioContext *ctx = bdrv_get_aio_context(bs); + + aio_context_acquire(ctx); + bdrv_unref(bs); + aio_context_release(ctx); +} + /* * Release a BlockDriverState reference while holding the graph write lock. * @@ -7267,8 +7277,7 @@ void bdrv_schedule_unref(BlockDriverState *bs) if (!bs) { return; } - aio_bh_schedule_oneshot(qemu_get_aio_context(), - (QEMUBHFunc *) bdrv_unref, bs); + aio_bh_schedule_oneshot(qemu_get_aio_context(), bdrv_schedule_unref_bh, bs); } struct BdrvOpBlocker { diff --git a/block/backup.c b/block/backup.c index 5bad7d116f..8aae5836d7 100644 --- a/block/backup.c +++ b/block/backup.c @@ -499,7 +499,7 @@ BlockJob *backup_job_create(const char *job_id, BlockDriverState *bs, bdrv_graph_wrlock(target); block_job_add_bdrv(&job->common, "target", target, 0, BLK_PERM_ALL, &error_abort); - bdrv_graph_wrunlock(); + bdrv_graph_wrunlock(target); return &job->common; diff --git a/block/blklogwrites.c b/block/blklogwrites.c index a0d70729bb..84e03f309f 100644 --- a/block/blklogwrites.c +++ b/block/blklogwrites.c @@ -253,7 +253,7 @@ fail_log: if (ret < 0) { bdrv_graph_wrlock(NULL); bdrv_unref_child(bs, s->log_file); - bdrv_graph_wrunlock(); + bdrv_graph_wrunlock(NULL); s->log_file = NULL; } fail: @@ -268,7 +268,7 @@ static void blk_log_writes_close(BlockDriverState *bs) bdrv_graph_wrlock(NULL); bdrv_unref_child(bs, s->log_file); s->log_file = NULL; - bdrv_graph_wrunlock(); + bdrv_graph_wrunlock(NULL); } static int64_t coroutine_fn GRAPH_RDLOCK @@ -328,22 +328,39 @@ static void coroutine_fn GRAPH_RDLOCK blk_log_writes_co_do_log(BlkLogWritesLogReq *lr) { BDRVBlkLogWritesState *s = lr->bs->opaque; - uint64_t cur_log_offset = s->cur_log_sector << s->sectorbits; + + /* + * Determine the offsets and sizes of different parts of the entry, and + * update the state of the driver. + * + * This needs to be done in one go, before any actual I/O is done, as the + * log entry may have to be written in two parts, and the state of the + * driver may be modified by other driver operations while waiting for the + * I/O to complete. + */ + const uint64_t entry_start_sector = s->cur_log_sector; + const uint64_t entry_offset = entry_start_sector << s->sectorbits; + const uint64_t qiov_aligned_size = ROUND_UP(lr->qiov->size, s->sectorsize); + const uint64_t entry_aligned_size = qiov_aligned_size + + ROUND_UP(lr->zero_size, s->sectorsize); + const uint64_t entry_nr_sectors = entry_aligned_size >> s->sectorbits; s->nr_entries++; - s->cur_log_sector += - ROUND_UP(lr->qiov->size, s->sectorsize) >> s->sectorbits; + s->cur_log_sector += entry_nr_sectors; - lr->log_ret = bdrv_co_pwritev(s->log_file, cur_log_offset, lr->qiov->size, + /* + * Write the log entry. Note that if this is a "write zeroes" operation, + * only the entry header is written here, with the zeroing being done + * separately below. + */ + lr->log_ret = bdrv_co_pwritev(s->log_file, entry_offset, lr->qiov->size, lr->qiov, 0); /* Logging for the "write zeroes" operation */ if (lr->log_ret == 0 && lr->zero_size) { - cur_log_offset = s->cur_log_sector << s->sectorbits; - s->cur_log_sector += - ROUND_UP(lr->zero_size, s->sectorsize) >> s->sectorbits; + const uint64_t zeroes_offset = entry_offset + qiov_aligned_size; - lr->log_ret = bdrv_co_pwrite_zeroes(s->log_file, cur_log_offset, + lr->log_ret = bdrv_co_pwrite_zeroes(s->log_file, zeroes_offset, lr->zero_size, 0); } diff --git a/block/blkverify.c b/block/blkverify.c index a96905db35..9b17c46644 100644 --- a/block/blkverify.c +++ b/block/blkverify.c @@ -154,7 +154,7 @@ static void blkverify_close(BlockDriverState *bs) bdrv_graph_wrlock(NULL); bdrv_unref_child(bs, s->test_file); s->test_file = NULL; - bdrv_graph_wrunlock(); + bdrv_graph_wrunlock(NULL); } static int64_t coroutine_fn GRAPH_RDLOCK diff --git a/block/block-backend.c b/block/block-backend.c index 27615e4b10..19978a9cf2 100644 --- a/block/block-backend.c +++ b/block/block-backend.c @@ -924,11 +924,14 @@ BlockBackend *blk_by_public(BlockBackendPublic *public) /* * Disassociates the currently associated BlockDriverState from @blk. + * + * The caller must hold the AioContext lock for the BlockBackend. */ void blk_remove_bs(BlockBackend *blk) { ThrottleGroupMember *tgm = &blk->public.throttle_group_member; BdrvChild *root; + AioContext *ctx; GLOBAL_STATE_CODE(); @@ -958,9 +961,10 @@ void blk_remove_bs(BlockBackend *blk) root = blk->root; blk->root = NULL; - bdrv_graph_wrlock(NULL); + ctx = bdrv_get_aio_context(root->bs); + bdrv_graph_wrlock(root->bs); bdrv_root_unref_child(root); - bdrv_graph_wrunlock(); + bdrv_graph_wrunlock_ctx(ctx); } /* @@ -971,6 +975,8 @@ void blk_remove_bs(BlockBackend *blk) int blk_insert_bs(BlockBackend *blk, BlockDriverState *bs, Error **errp) { ThrottleGroupMember *tgm = &blk->public.throttle_group_member; + AioContext *ctx = bdrv_get_aio_context(bs); + GLOBAL_STATE_CODE(); bdrv_ref(bs); bdrv_graph_wrlock(bs); @@ -978,7 +984,7 @@ int blk_insert_bs(BlockBackend *blk, BlockDriverState *bs, Error **errp) BDRV_CHILD_FILTERED | BDRV_CHILD_PRIMARY, blk->perm, blk->shared_perm, blk, errp); - bdrv_graph_wrunlock(); + bdrv_graph_wrunlock_ctx(ctx); if (blk->root == NULL) { return -EPERM; } diff --git a/block/commit.c b/block/commit.c index eb3dc01f45..69cc75be0c 100644 --- a/block/commit.c +++ b/block/commit.c @@ -102,7 +102,7 @@ static void commit_abort(Job *job) bdrv_drained_begin(commit_top_backing_bs); bdrv_graph_wrlock(commit_top_backing_bs); bdrv_replace_node(s->commit_top_bs, commit_top_backing_bs, &error_abort); - bdrv_graph_wrunlock(); + bdrv_graph_wrunlock(commit_top_backing_bs); bdrv_drained_end(commit_top_backing_bs); bdrv_unref(s->commit_top_bs); @@ -370,19 +370,19 @@ void commit_start(const char *job_id, BlockDriverState *bs, ret = block_job_add_bdrv(&s->common, "intermediate node", iter, 0, iter_shared_perms, errp); if (ret < 0) { - bdrv_graph_wrunlock(); + bdrv_graph_wrunlock(top); goto fail; } } if (bdrv_freeze_backing_chain(commit_top_bs, base, errp) < 0) { - bdrv_graph_wrunlock(); + bdrv_graph_wrunlock(top); goto fail; } s->chain_frozen = true; ret = block_job_add_bdrv(&s->common, "base", base, 0, BLK_PERM_ALL, errp); - bdrv_graph_wrunlock(); + bdrv_graph_wrunlock(top); if (ret < 0) { goto fail; @@ -436,7 +436,7 @@ fail: bdrv_drained_begin(top); bdrv_graph_wrlock(top); bdrv_replace_node(commit_top_bs, top, &error_abort); - bdrv_graph_wrunlock(); + bdrv_graph_wrunlock(top); bdrv_drained_end(top); } } diff --git a/block/export/vhost-user-blk-server.c b/block/export/vhost-user-blk-server.c index fe2cee3a78..16f48388d3 100644 --- a/block/export/vhost-user-blk-server.c +++ b/block/export/vhost-user-blk-server.c @@ -283,6 +283,7 @@ static void vu_blk_drained_begin(void *opaque) { VuBlkExport *vexp = opaque; + vexp->vu_server.quiescing = true; vhost_user_server_detach_aio_context(&vexp->vu_server); } @@ -291,19 +292,23 @@ static void vu_blk_drained_end(void *opaque) { VuBlkExport *vexp = opaque; + vexp->vu_server.quiescing = false; vhost_user_server_attach_aio_context(&vexp->vu_server, vexp->export.ctx); } /* - * Ensures that bdrv_drained_begin() waits until in-flight requests complete. + * Ensures that bdrv_drained_begin() waits until in-flight requests complete + * and the server->co_trip coroutine has terminated. It will be restarted in + * vhost_user_server_attach_aio_context(). * * Called with vexp->export.ctx acquired. */ static bool vu_blk_drained_poll(void *opaque) { VuBlkExport *vexp = opaque; + VuServer *server = &vexp->vu_server; - return vhost_user_server_has_in_flight(&vexp->vu_server); + return server->co_trip || vhost_user_server_has_in_flight(server); } static const BlockDevOps vu_blk_dev_ops = { diff --git a/block/graph-lock.c b/block/graph-lock.c index e5525ee2db..079e878d9b 100644 --- a/block/graph-lock.c +++ b/block/graph-lock.c @@ -161,11 +161,21 @@ void no_coroutine_fn bdrv_graph_wrlock(BlockDriverState *bs) } } -void bdrv_graph_wrunlock(void) +void no_coroutine_fn bdrv_graph_wrunlock_ctx(AioContext *ctx) { GLOBAL_STATE_CODE(); assert(qatomic_read(&has_writer)); + /* + * Release only non-mainloop AioContext. The mainloop often relies on the + * BQL and doesn't lock the main AioContext before doing things. + */ + if (ctx && ctx != qemu_get_aio_context()) { + aio_context_release(ctx); + } else { + ctx = NULL; + } + WITH_QEMU_LOCK_GUARD(&aio_context_list_lock) { /* * No need for memory barriers, this works in pair with @@ -187,6 +197,17 @@ void bdrv_graph_wrunlock(void) * progress. */ aio_bh_poll(qemu_get_aio_context()); + + if (ctx) { + aio_context_acquire(ctx); + } +} + +void no_coroutine_fn bdrv_graph_wrunlock(BlockDriverState *bs) +{ + AioContext *ctx = bs ? bdrv_get_aio_context(bs) : NULL; + + bdrv_graph_wrunlock_ctx(ctx); } void coroutine_fn bdrv_graph_co_rdlock(void) diff --git a/block/io.c b/block/io.c index 7e62fabbf5..d202987770 100644 --- a/block/io.c +++ b/block/io.c @@ -2619,6 +2619,16 @@ bdrv_co_do_block_status(BlockDriverState *bs, bool want_zero, ret |= (ret2 & BDRV_BLOCK_ZERO); } } + + /* + * Now that the recursive search was done, clear the flag. Otherwise, + * with more complicated block graphs like snapshot-access -> + * copy-before-write -> qcow2, where the return value will be propagated + * further up to a parent bdrv_co_do_block_status() call, both the + * BDRV_BLOCK_RECURSE and BDRV_BLOCK_ZERO flags would be set, which is + * not allowed. + */ + ret &= ~BDRV_BLOCK_RECURSE; } out: diff --git a/block/mirror.c b/block/mirror.c index 2096fade90..cd9d3ad4a8 100644 --- a/block/mirror.c +++ b/block/mirror.c @@ -773,7 +773,7 @@ static int mirror_exit_common(Job *job) "would not lead to an abrupt change of visible data", to_replace->node_name, target_bs->node_name); } - bdrv_graph_wrunlock(); + bdrv_graph_wrunlock(target_bs); bdrv_drained_end(to_replace); if (local_err) { error_report_err(local_err); @@ -798,7 +798,7 @@ static int mirror_exit_common(Job *job) block_job_remove_all_bdrv(bjob); bdrv_graph_wrlock(mirror_top_bs); bdrv_replace_node(mirror_top_bs, mirror_top_bs->backing->bs, &error_abort); - bdrv_graph_wrunlock(); + bdrv_graph_wrunlock(mirror_top_bs); bdrv_drained_end(target_bs); bdrv_unref(target_bs); @@ -1920,7 +1920,7 @@ static BlockJob *mirror_start_job( BLK_PERM_CONSISTENT_READ, errp); if (ret < 0) { - bdrv_graph_wrunlock(); + bdrv_graph_wrunlock(bs); goto fail; } @@ -1965,17 +1965,17 @@ static BlockJob *mirror_start_job( ret = block_job_add_bdrv(&s->common, "intermediate node", iter, 0, iter_shared_perms, errp); if (ret < 0) { - bdrv_graph_wrunlock(); + bdrv_graph_wrunlock(bs); goto fail; } } if (bdrv_freeze_backing_chain(mirror_top_bs, target, errp) < 0) { - bdrv_graph_wrunlock(); + bdrv_graph_wrunlock(bs); goto fail; } } - bdrv_graph_wrunlock(); + bdrv_graph_wrunlock(bs); QTAILQ_INIT(&s->ops_in_flight); @@ -2006,7 +2006,7 @@ fail: bdrv_child_refresh_perms(mirror_top_bs, mirror_top_bs->backing, &error_abort); bdrv_replace_node(mirror_top_bs, bs, &error_abort); - bdrv_graph_wrunlock(); + bdrv_graph_wrunlock(bs); bdrv_drained_end(bs); bdrv_unref(mirror_top_bs); diff --git a/block/qcow2.c b/block/qcow2.c index cf2468858f..13e032bd5e 100644 --- a/block/qcow2.c +++ b/block/qcow2.c @@ -2809,7 +2809,7 @@ qcow2_do_close(BlockDriverState *bs, bool close_data_file) bdrv_graph_rdunlock_main_loop(); bdrv_graph_wrlock(NULL); bdrv_unref_child(bs, s->data_file); - bdrv_graph_wrunlock(); + bdrv_graph_wrunlock(NULL); s->data_file = NULL; bdrv_graph_rdlock_main_loop(); } diff --git a/block/quorum.c b/block/quorum.c index d3ffc2ee33..505b8b3e18 100644 --- a/block/quorum.c +++ b/block/quorum.c @@ -1044,7 +1044,7 @@ close_exit: } bdrv_unref_child(bs, s->children[i]); } - bdrv_graph_wrunlock(); + bdrv_graph_wrunlock(NULL); g_free(s->children); g_free(opened); exit: @@ -1061,7 +1061,7 @@ static void quorum_close(BlockDriverState *bs) for (i = 0; i < s->num_children; i++) { bdrv_unref_child(bs, s->children[i]); } - bdrv_graph_wrunlock(); + bdrv_graph_wrunlock(NULL); g_free(s->children); } diff --git a/block/replication.c b/block/replication.c index 43e259444b..5ded5f1ca9 100644 --- a/block/replication.c +++ b/block/replication.c @@ -568,7 +568,7 @@ static void replication_start(ReplicationState *rs, ReplicationMode mode, &local_err); if (local_err) { error_propagate(errp, local_err); - bdrv_graph_wrunlock(); + bdrv_graph_wrunlock(bs); aio_context_release(aio_context); return; } @@ -579,7 +579,7 @@ static void replication_start(ReplicationState *rs, ReplicationMode mode, BDRV_CHILD_DATA, &local_err); if (local_err) { error_propagate(errp, local_err); - bdrv_graph_wrunlock(); + bdrv_graph_wrunlock(bs); aio_context_release(aio_context); return; } @@ -592,7 +592,7 @@ static void replication_start(ReplicationState *rs, ReplicationMode mode, if (!top_bs || !bdrv_is_root_node(top_bs) || !check_top_bs(top_bs, bs)) { error_setg(errp, "No top_bs or it is invalid"); - bdrv_graph_wrunlock(); + bdrv_graph_wrunlock(bs); reopen_backing_file(bs, false, NULL); aio_context_release(aio_context); return; @@ -600,7 +600,7 @@ static void replication_start(ReplicationState *rs, ReplicationMode mode, bdrv_op_block_all(top_bs, s->blocker); bdrv_op_unblock(top_bs, BLOCK_OP_TYPE_DATAPLANE, s->blocker); - bdrv_graph_wrunlock(); + bdrv_graph_wrunlock(bs); s->backup_job = backup_job_create( NULL, s->secondary_disk->bs, s->hidden_disk->bs, @@ -696,7 +696,7 @@ static void replication_done(void *opaque, int ret) s->secondary_disk = NULL; bdrv_unref_child(bs, s->hidden_disk); s->hidden_disk = NULL; - bdrv_graph_wrunlock(); + bdrv_graph_wrunlock(NULL); s->error = 0; } else { diff --git a/block/snapshot.c b/block/snapshot.c index 55974273ae..c4d40e80dd 100644 --- a/block/snapshot.c +++ b/block/snapshot.c @@ -196,8 +196,10 @@ bdrv_snapshot_fallback(BlockDriverState *bs) int bdrv_can_snapshot(BlockDriverState *bs) { BlockDriver *drv = bs->drv; + GLOBAL_STATE_CODE(); - if (!drv || !bdrv_is_inserted(bs) || bdrv_is_read_only(bs)) { + + if (!drv || !bdrv_is_inserted(bs) || !bdrv_is_writable(bs)) { return 0; } @@ -292,7 +294,7 @@ int bdrv_snapshot_goto(BlockDriverState *bs, /* .bdrv_open() will re-attach it */ bdrv_graph_wrlock(NULL); bdrv_unref_child(bs, fallback); - bdrv_graph_wrunlock(); + bdrv_graph_wrunlock(NULL); ret = bdrv_snapshot_goto(fallback_bs, snapshot_id, errp); open_ret = drv->bdrv_open(bs, options, bs->open_flags, &local_err); diff --git a/block/stream.c b/block/stream.c index 0b92410c00..01fe7c0f16 100644 --- a/block/stream.c +++ b/block/stream.c @@ -99,9 +99,9 @@ static int stream_prepare(Job *job) } } - bdrv_graph_wrlock(base); + bdrv_graph_wrlock(s->target_bs); bdrv_set_backing_hd_drained(unfiltered_bs, base, &local_err); - bdrv_graph_wrunlock(); + bdrv_graph_wrunlock(s->target_bs); /* * This call will do I/O, so the graph can change again from here on. @@ -369,7 +369,7 @@ void stream_start(const char *job_id, BlockDriverState *bs, bdrv_graph_wrlock(bs); if (block_job_add_bdrv(&s->common, "active node", bs, 0, basic_flags | BLK_PERM_WRITE, errp)) { - bdrv_graph_wrunlock(); + bdrv_graph_wrunlock(bs); goto fail; } @@ -389,11 +389,11 @@ void stream_start(const char *job_id, BlockDriverState *bs, ret = block_job_add_bdrv(&s->common, "intermediate node", iter, 0, basic_flags, errp); if (ret < 0) { - bdrv_graph_wrunlock(); + bdrv_graph_wrunlock(bs); goto fail; } } - bdrv_graph_wrunlock(); + bdrv_graph_wrunlock(bs); s->base_overlay = base_overlay; s->above_base = above_base; diff --git a/block/vmdk.c b/block/vmdk.c index dda783f06b..d6971c7067 100644 --- a/block/vmdk.c +++ b/block/vmdk.c @@ -283,7 +283,7 @@ static void vmdk_free_extents(BlockDriverState *bs) bdrv_unref_child(bs, e->file); } } - bdrv_graph_wrunlock(); + bdrv_graph_wrunlock(NULL); g_free(s->extents); } @@ -351,29 +351,41 @@ vmdk_write_cid(BlockDriverState *bs, uint32_t cid) BDRVVmdkState *s = bs->opaque; int ret = 0; - desc = g_malloc0(DESC_SIZE); - tmp_desc = g_malloc0(DESC_SIZE); - ret = bdrv_co_pread(bs->file, s->desc_offset, DESC_SIZE, desc, 0); + size_t desc_buf_size; + + if (s->desc_offset == 0) { + desc_buf_size = bdrv_getlength(bs->file->bs); + if (desc_buf_size > 16ULL << 20) { + error_report("VMDK description file too big"); + return -EFBIG; + } + } else { + desc_buf_size = DESC_SIZE; + } + + desc = g_malloc0(desc_buf_size); + tmp_desc = g_malloc0(desc_buf_size); + ret = bdrv_co_pread(bs->file, s->desc_offset, desc_buf_size, desc, 0); if (ret < 0) { goto out; } - desc[DESC_SIZE - 1] = '\0'; + desc[desc_buf_size - 1] = '\0'; tmp_str = strstr(desc, "parentCID"); if (tmp_str == NULL) { ret = -EINVAL; goto out; } - pstrcpy(tmp_desc, DESC_SIZE, tmp_str); + pstrcpy(tmp_desc, desc_buf_size, tmp_str); p_name = strstr(desc, "CID"); if (p_name != NULL) { p_name += sizeof("CID"); - snprintf(p_name, DESC_SIZE - (p_name - desc), "%" PRIx32 "\n", cid); - pstrcat(desc, DESC_SIZE, tmp_desc); + snprintf(p_name, desc_buf_size - (p_name - desc), "%" PRIx32 "\n", cid); + pstrcat(desc, desc_buf_size, tmp_desc); } - ret = bdrv_co_pwrite_sync(bs->file, s->desc_offset, DESC_SIZE, desc, 0); + ret = bdrv_co_pwrite_sync(bs->file, s->desc_offset, desc_buf_size, desc, 0); out: g_free(desc); @@ -1237,7 +1249,7 @@ vmdk_parse_extents(const char *desc, BlockDriverState *bs, QDict *options, bdrv_graph_rdunlock_main_loop(); bdrv_graph_wrlock(NULL); bdrv_unref_child(bs, extent_file); - bdrv_graph_wrunlock(); + bdrv_graph_wrunlock(NULL); bdrv_graph_rdlock_main_loop(); goto out; } @@ -1256,7 +1268,7 @@ vmdk_parse_extents(const char *desc, BlockDriverState *bs, QDict *options, bdrv_graph_rdunlock_main_loop(); bdrv_graph_wrlock(NULL); bdrv_unref_child(bs, extent_file); - bdrv_graph_wrunlock(); + bdrv_graph_wrunlock(NULL); bdrv_graph_rdlock_main_loop(); goto out; } @@ -1267,7 +1279,7 @@ vmdk_parse_extents(const char *desc, BlockDriverState *bs, QDict *options, bdrv_graph_rdunlock_main_loop(); bdrv_graph_wrlock(NULL); bdrv_unref_child(bs, extent_file); - bdrv_graph_wrunlock(); + bdrv_graph_wrunlock(NULL); bdrv_graph_rdlock_main_loop(); goto out; } @@ -1277,7 +1289,7 @@ vmdk_parse_extents(const char *desc, BlockDriverState *bs, QDict *options, bdrv_graph_rdunlock_main_loop(); bdrv_graph_wrlock(NULL); bdrv_unref_child(bs, extent_file); - bdrv_graph_wrunlock(); + bdrv_graph_wrunlock(NULL); bdrv_graph_rdlock_main_loop(); ret = -ENOTSUP; goto out; diff --git a/blockdev.c b/blockdev.c index 5bc921236c..c91f49e7b6 100644 --- a/blockdev.c +++ b/blockdev.c @@ -1613,7 +1613,7 @@ static void external_snapshot_abort(void *opaque) bdrv_drained_begin(state->new_bs); bdrv_graph_wrlock(state->old_bs); bdrv_replace_node(state->new_bs, state->old_bs, &error_abort); - bdrv_graph_wrunlock(); + bdrv_graph_wrunlock(state->old_bs); bdrv_drained_end(state->new_bs); bdrv_unref(state->old_bs); /* bdrv_replace_node() ref'ed old_bs */ @@ -2400,8 +2400,9 @@ void coroutine_fn qmp_block_resize(const char *device, const char *node_name, bdrv_co_lock(bs); bdrv_drained_end(bs); - blk_co_unref(blk); bdrv_co_unlock(bs); + + blk_co_unref(blk); } void qmp_block_stream(const char *job_id, const char *device, @@ -3692,7 +3693,7 @@ void qmp_x_blockdev_change(const char *parent, const char *child, } out: - bdrv_graph_wrunlock(); + bdrv_graph_wrunlock(NULL); } BlockJobInfoList *qmp_query_block_jobs(Error **errp) diff --git a/blockjob.c b/blockjob.c index af44322cbe..b7a29052b9 100644 --- a/blockjob.c +++ b/blockjob.c @@ -212,7 +212,7 @@ void block_job_remove_all_bdrv(BlockJob *job) g_slist_free_1(l); } - bdrv_graph_wrunlock(); + bdrv_graph_wrunlock_ctx(job->job.aio_context); } bool block_job_has_bdrv(BlockJob *job, BlockDriverState *bs) @@ -523,7 +523,7 @@ void *block_job_create(const char *job_id, const BlockJobDriver *driver, job = job_create(job_id, &driver->job_driver, txn, bdrv_get_aio_context(bs), flags, cb, opaque, errp); if (job == NULL) { - bdrv_graph_wrunlock(); + bdrv_graph_wrunlock(bs); return NULL; } @@ -563,11 +563,11 @@ void *block_job_create(const char *job_id, const BlockJobDriver *driver, goto fail; } - bdrv_graph_wrunlock(); + bdrv_graph_wrunlock(bs); return job; fail: - bdrv_graph_wrunlock(); + bdrv_graph_wrunlock(bs); job_early_fail(&job->job); return NULL; } diff --git a/bsd-user/bsd-mem.h b/bsd-user/bsd-mem.h index c3e72e3b86..21d9bab889 100644 --- a/bsd-user/bsd-mem.h +++ b/bsd-user/bsd-mem.h @@ -235,7 +235,7 @@ static inline abi_long do_obreak(abi_ulong brk_val) return target_brk; } - /* Release heap if necesary */ + /* Release heap if necessary */ if (new_brk < old_brk) { target_munmap(new_brk, old_brk - new_brk); diff --git a/bsd-user/freebsd/os-proc.c b/bsd-user/freebsd/os-proc.c index 4e67ae4d56..e0203e259b 100644 --- a/bsd-user/freebsd/os-proc.c +++ b/bsd-user/freebsd/os-proc.c @@ -115,7 +115,7 @@ abi_long freebsd_exec_common(abi_ulong path_or_fd, abi_ulong guest_argp, } qarg0 = argp = g_new0(char *, argc + 9); - /* save the first agrument for the emulator */ + /* save the first argument for the emulator */ *argp++ = (char *)getprogname(); qargp = argp; *argp++ = (char *)getprogname(); diff --git a/bsd-user/freebsd/os-stat.h b/bsd-user/freebsd/os-stat.h index b20e270774..3bdc66aa98 100644 --- a/bsd-user/freebsd/os-stat.h +++ b/bsd-user/freebsd/os-stat.h @@ -146,7 +146,7 @@ static inline abi_long do_freebsd_fstatat(abi_long arg1, abi_long arg2, return ret; } -/* undocummented nstat(char *path, struct nstat *ub) syscall */ +/* undocumented nstat(char *path, struct nstat *ub) syscall */ static abi_long do_freebsd11_nstat(abi_long arg1, abi_long arg2) { abi_long ret; @@ -162,7 +162,7 @@ static abi_long do_freebsd11_nstat(abi_long arg1, abi_long arg2) return ret; } -/* undocummented nfstat(int fd, struct nstat *sb) syscall */ +/* undocumented nfstat(int fd, struct nstat *sb) syscall */ static abi_long do_freebsd11_nfstat(abi_long arg1, abi_long arg2) { abi_long ret; @@ -175,7 +175,7 @@ static abi_long do_freebsd11_nfstat(abi_long arg1, abi_long arg2) return ret; } -/* undocummented nlstat(char *path, struct nstat *ub) syscall */ +/* undocumented nlstat(char *path, struct nstat *ub) syscall */ static abi_long do_freebsd11_nlstat(abi_long arg1, abi_long arg2) { abi_long ret; diff --git a/chardev/char.c b/chardev/char.c index 996a024c7a..119b548784 100644 --- a/chardev/char.c +++ b/chardev/char.c @@ -518,7 +518,7 @@ static const ChardevClass *char_get_class(const char *driver, Error **errp) if (object_class_is_abstract(oc)) { error_setg(errp, QERR_INVALID_PARAMETER_VALUE, "driver", - "an abstract device type"); + "a non-abstract device type"); return NULL; } diff --git a/configure b/configure index f90c274570..798f94d85f 100755 --- a/configure +++ b/configure @@ -41,12 +41,7 @@ then # This file is auto-generated by configure to support in-source tree # 'make' command invocation -ifeq ($(MAKECMDGOALS),) -recurse: all -endif - -.NOTPARALLEL: % -%: force +build: @echo 'changing dir to build for $(MAKE) "$(MAKECMDGOALS)"...' @$(MAKE) -C build -f Makefile $(MAKECMDGOALS) @if test "$(MAKECMDGOALS)" = "distclean" && \ @@ -54,8 +49,9 @@ endif then \ rm -rf build GNUmakefile ; \ fi -force: ; -.PHONY: force +%: build + @ +.PHONY: build GNUmakefile: ; EOF @@ -981,14 +977,14 @@ meson="$(cd pyvenv/bin; pwd)/meson" # Conditionally ensure Sphinx is installed. -mkvenv_flags="" -if test "$download" = "enabled" -a "$docs" = "enabled" ; then - mkvenv_flags="--online" +mkvenv_online_flag="" +if test "$download" = "enabled" ; then + mkvenv_online_flag=" --online" fi if test "$docs" != "disabled" ; then if ! $mkvenv ensuregroup \ - $mkvenv_flags \ + $(test "$docs" = "enabled" && echo "$mkvenv_online_flag") \ ${source_path}/pythondeps.toml docs; then if test "$docs" = "enabled" ; then @@ -1320,8 +1316,8 @@ probe_target_compiler() { container_cross_cc=${container_cross_prefix}gcc ;; i386) - container_image=fedora-i386-cross - container_cross_prefix= + container_image=debian-i686-cross + container_cross_prefix=i686-linux-gnu- ;; loongarch64) container_image=debian-loongarch-cross @@ -1404,16 +1400,19 @@ probe_target_compiler() { done try=cross - case "$target_arch:$cpu" in - aarch64_be:aarch64 | \ - armeb:arm | \ - i386:x86_64 | \ - mips*:mips64 | \ - ppc*:ppc64 | \ - sparc:sparc64 | \ - "$cpu:$cpu") - try='native cross' ;; - esac + # For softmmu/roms also look for a bi-endian or multilib-enabled host compiler + if [ "${1%softmmu}" != "$1" ] || test "$target_arch" = "$cpu"; then + case "$target_arch:$cpu" in + aarch64_be:aarch64 | \ + armeb:arm | \ + i386:x86_64 | \ + mips*:mips64 | \ + ppc*:ppc64 | \ + sparc:sparc64 | \ + "$cpu:$cpu") + try='native cross' ;; + esac + fi eval "target_cflags=\${cross_cc_cflags_$target_arch}" for thistry in $try; do case $thistry in @@ -1645,6 +1644,7 @@ fi echo "SUBDIRS=$subdirs" >> $config_host_mak echo "PYTHON=$python" >> $config_host_mak +echo "MKVENV_ENSUREGROUP=$mkvenv ensuregroup $mkvenv_online_flag" >> $config_host_mak echo "GENISOIMAGE=$genisoimage" >> $config_host_mak echo "MESON=$meson" >> $config_host_mak echo "NINJA=$ninja" >> $config_host_mak diff --git a/contrib/plugins/Makefile b/contrib/plugins/Makefile index 1783750cf6..0b64d2c1e3 100644 --- a/contrib/plugins/Makefile +++ b/contrib/plugins/Makefile @@ -49,7 +49,7 @@ all: $(SONAMES) $(CC) $(CFLAGS) $(PLUGIN_CFLAGS) -c -o $@ $< ifeq ($(CONFIG_WIN32),y) -lib%$(SO_SUFFIX): %.o win32_linker.o ../../plugins/qemu_plugin_api.lib +lib%$(SO_SUFFIX): %.o win32_linker.o ../../plugins/libqemu_plugin_api.a $(CC) -shared -o $@ $^ $(LDLIBS) else ifeq ($(CONFIG_DARWIN),y) lib%$(SO_SUFFIX): %.o diff --git a/contrib/vhost-user-gpu/virgl.c b/contrib/vhost-user-gpu/virgl.c index 1da6cc1588..d1ccdf7d06 100644 --- a/contrib/vhost-user-gpu/virgl.c +++ b/contrib/vhost-user-gpu/virgl.c @@ -401,7 +401,7 @@ virgl_cmd_set_scanout(VuGpu *g, if (g->use_modifiers) { /* - * The mesage uses all the fields set in dmabuf_scanout plus + * The message uses all the fields set in dmabuf_scanout plus * modifiers which is appended after VhostUserGpuDMABUFScanout. */ msg.request = VHOST_USER_GPU_DMABUF_SCANOUT2; diff --git a/disas/cris.c b/disas/cris.c index 0b0a3fb916..409a224c5d 100644 --- a/disas/cris.c +++ b/disas/cris.c @@ -1731,10 +1731,10 @@ format_hex (unsigned long number, unsigned (== 0). */ static char * -format_dec (long number, char *outbuffer, int signedp) +format_dec (long number, char *outbuffer, size_t outsize, int signedp) { last_immediate = number; - sprintf (outbuffer, signedp ? "%ld" : "%lu", number); + snprintf (outbuffer, outsize, signedp ? "%ld" : "%lu", number); return outbuffer + strlen (outbuffer); } @@ -1876,6 +1876,12 @@ print_flags (struct cris_disasm_data *disdata, unsigned int insn, char *cp) return cp; } +#define FORMAT_DEC(number, tp, signedp) \ + format_dec (number, tp, ({ \ + assert(tp >= temp && tp <= temp + sizeof(temp)); \ + temp + sizeof(temp) - tp; \ + }), signedp) + /* Print out an insn with its operands, and update the info->insn_type fields. The prefix_opcodep and the rest hold a prefix insn that is supposed to be output as an address mode. */ @@ -2105,7 +2111,7 @@ print_with_operands (const struct cris_opcode *opcodep, if ((*cs == 'z' && (insn & 0x20)) || (opcodep->match == BDAP_QUICK_OPCODE && (nbytes <= 2 || buffer[1 + nbytes] == 0))) - tp = format_dec (number, tp, signedp); + tp = FORMAT_DEC (number, tp, signedp); else { unsigned int highbyte = (number >> 24) & 0xff; @@ -2241,7 +2247,7 @@ print_with_operands (const struct cris_opcode *opcodep, with_reg_prefix); if (number >= 0) *tp++ = '+'; - tp = format_dec (number, tp, 1); + tp = FORMAT_DEC (number, tp, 1); info->flags |= CRIS_DIS_FLAG_MEM_TARGET_IS_REG; info->target = (prefix_insn >> 12) & 15; @@ -2340,7 +2346,7 @@ print_with_operands (const struct cris_opcode *opcodep, { if (number >= 0) *tp++ = '+'; - tp = format_dec (number, tp, 1); + tp = FORMAT_DEC (number, tp, 1); } } else @@ -2397,7 +2403,7 @@ print_with_operands (const struct cris_opcode *opcodep, break; case 'I': - tp = format_dec (insn & 63, tp, 0); + tp = FORMAT_DEC (insn & 63, tp, 0); break; case 'b': @@ -2426,11 +2432,11 @@ print_with_operands (const struct cris_opcode *opcodep, break; case 'c': - tp = format_dec (insn & 31, tp, 0); + tp = FORMAT_DEC (insn & 31, tp, 0); break; case 'C': - tp = format_dec (insn & 15, tp, 0); + tp = FORMAT_DEC (insn & 15, tp, 0); break; case 'o': @@ -2463,7 +2469,7 @@ print_with_operands (const struct cris_opcode *opcodep, if (number > 127) number = number - 256; - tp = format_dec (number, tp, 1); + tp = FORMAT_DEC (number, tp, 1); *tp++ = ','; tp = format_reg (disdata, (insn >> 12) & 15, tp, with_reg_prefix); } @@ -2474,7 +2480,7 @@ print_with_operands (const struct cris_opcode *opcodep, break; case 'i': - tp = format_dec ((insn & 32) ? (insn & 31) | ~31L : insn & 31, tp, 1); + tp = FORMAT_DEC ((insn & 32) ? (insn & 31) | ~31L : insn & 31, tp, 1); break; case 'P': diff --git a/disas/hppa.c b/disas/hppa.c index dcf9a47f34..cce4f4aa37 100644 --- a/disas/hppa.c +++ b/disas/hppa.c @@ -1968,6 +1968,10 @@ print_insn_hppa (bfd_vma memaddr, disassemble_info *info) insn = bfd_getb32 (buffer); + info->fprintf_func(info->stream, " %02x %02x %02x %02x ", + (insn >> 24) & 0xff, (insn >> 16) & 0xff, + (insn >> 8) & 0xff, insn & 0xff); + for (i = 0; i < NUMOPCODES; ++i) { const struct pa_opcode *opcode = &pa_opcodes[i]; @@ -2826,6 +2830,6 @@ print_insn_hppa (bfd_vma memaddr, disassemble_info *info) return sizeof (insn); } } - (*info->fprintf_func) (info->stream, "#%8x", insn); + info->fprintf_func(info->stream, ""); return sizeof (insn); } diff --git a/docs/about/deprecated.rst b/docs/about/deprecated.rst index 78550c07bf..2e15040246 100644 --- a/docs/about/deprecated.rst +++ b/docs/about/deprecated.rst @@ -236,6 +236,16 @@ it. Since all recent x86 hardware from the past >10 years is capable of the 64-bit x86 extensions, a corresponding 64-bit OS should be used instead. +System emulator CPUs +-------------------- + +Nios II CPU (since 8.2) +''''''''''''''''''''''' + +The Nios II architecture is orphan. The ``nios2`` guest CPU support is +deprecated and will be removed in a future version of QEMU. + + System emulator machines ------------------------ @@ -254,6 +264,11 @@ These old machine types are quite neglected nowadays and thus might have various pitfalls with regards to live migration. Use a newer machine type instead. +Nios II ``10m50-ghrd`` and ``nios2-generic-nommu`` machines (since 8.2) +''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' + +The Nios II architecture is orphan. + Backend options --------------- @@ -514,5 +529,5 @@ old compression method (since 8.2) Compression method fails too much. Too many races. We are going to remove it if nobody fixes it. For starters, migration-test -compression tests are disabled becase they fail randomly. If you need +compression tests are disabled because they fail randomly. If you need compression, use multifd compression methods. diff --git a/docs/about/emulation.rst b/docs/about/emulation.rst index 0ad0b86f0d..a2eefe3f3f 100644 --- a/docs/about/emulation.rst +++ b/docs/about/emulation.rst @@ -129,8 +129,9 @@ causing most hypervisors to trap and fault on them. .. warning:: Semihosting inherently bypasses any isolation there may be between the guest and the host. As a result a program using semihosting can - happily trash your host system. You should only ever run trusted - code with semihosting enabled. + happily trash your host system. Some semihosting calls (e.g. + ``SYS_READC``) can block execution indefinitely. You should only + ever run trusted code with semihosting enabled. Redirection ~~~~~~~~~~~ diff --git a/docs/devel/build-system.rst b/docs/devel/build-system.rst index 21f78da7d1..43d6005881 100644 --- a/docs/devel/build-system.rst +++ b/docs/devel/build-system.rst @@ -122,10 +122,78 @@ functioning. These are performed using a few more helper functions: indicated by $TMPC. -Python virtual environments and the QEMU build system ------------------------------------------------------ +Python virtual environments and the build process +------------------------------------------------- + +An important step in ``configure`` is to create a Python virtual +environment (venv) during the configuration phase. The Python interpreter +comes from the ``--python`` command line option, the ``$PYTHON`` variable +from the environment, or the system PATH, in this order. The venv resides +in the ``pyvenv`` directory in the build tree, and provides consistency +in how the build process runs Python code. + +At this stage, ``configure`` also queries the chosen Python interpreter +about QEMU's build dependencies. Note that the build process does *not* +look for ``meson``, ``sphinx-build`` or ``avocado`` binaries in the PATH; +likewise, there are no options such as ``--meson`` or ``--sphinx-build``. +This avoids a potential mismatch, where Meson and Sphinx binaries on the +PATH might operate in a different Python environment than the one chosen +by the user during the build process. On the other hand, it introduces +a potential source of confusion where the user installs a dependency but +``configure`` is not able to find it. When this happens, the dependency +was installed in the ``site-packages`` directory of another interpreter, +or with the wrong ``pip`` program. + +If a package is available for the chosen interpreter, ``configure`` +prepares a small script that invokes it from the venv itself[#distlib]_. +If not, ``configure`` can also optionally install dependencies in the +virtual environment with ``pip``, either from wheels in ``python/wheels`` +or by downloading the package with PyPI. Downloading can be disabled with +``--disable-download``; and anyway, it only happens when a ``configure`` +option (currently, only ``--enable-docs``) is explicitly enabled but +the dependencies are not present[#pip]_. + +.. [#distlib] The scripts are created based on the package's metadata, + specifically the ``console_script`` entry points. This is the + same mechanism that ``pip`` uses when installing a package. + Currently, in all cases it would be possible to use ``python -m`` + instead of an entry point script, which makes this approach a + bit overkill. On the other hand, creating the scripts is + future proof and it makes the contents of the ``pyvenv/bin`` + directory more informative. Portability is also not an issue, + because the Python Packaging Authority provides a package + ``distlib.scripts`` to perform this task. + +.. [#pip] ``pip`` might also be used when running ``make check-avocado`` + if downloading is enabled, to ensure that Avocado is + available. + +The required versions of the packages are stored in a configuration file +``pythondeps.toml``. The format is custom to QEMU, but it is documented +at the top of the file itself and it should be easy to understand. The +requirements should make it possible to use the version that is packaged +that is provided by supported distros. + +When dependencies are downloaded, instead, ``configure`` uses a "known +good" version that is also listed in ``pythondeps.toml``. In this +scenario, ``pythondeps.toml`` behaves like the "lock file" used by +``cargo``, ``poetry`` or other dependency management systems. + + +Bundled Python packages +----------------------- + +Python packages that are **mandatory** dependencies to build QEMU, +but are not available in all supported distros, are bundled with the +QEMU sources. Currently this includes Meson (outdated in CentOS 8 +and derivatives, Ubuntu 20.04 and 22.04, and openSUSE Leap) and tomli +(absent in Ubuntu 20.04). + +If you need to update these, please do so by modifying and rerunning +``python/scripts/vendor.py``. This script embeds the sha256 hash of +package sources and checks it. The pypi.org web site provides an easy +way to retrieve the sha256 hash of the sources. -TBD Stage 2: Meson ============== @@ -376,6 +444,15 @@ This is needed to obey the --python= option passed to the configure script, which may point to something other than the first python3 binary on the path. +By the time Meson runs, Python dependencies are available in the virtual +environment and should be invoked through the scripts that ``configure`` +places under ``pyvenv``. One way to do so is as follows, using Meson's +``find_program`` function:: + + sphinx_build = find_program( + fs.parent(python.full_path()) / 'sphinx-build', + required: get_option('docs')) + Stage 3: Make ============= @@ -434,6 +511,11 @@ number of dynamically created files listed later. executables. Build rules for various subdirectories are included in other meson.build files spread throughout the QEMU source tree. +``python/scripts/mkvenv.py`` + A wrapper for the Python ``venv`` and ``distlib.scripts`` packages. + It handles creating the virtual environment, creating scripts in + ``pyvenv/bin``, and calling ``pip`` to install dependencies. + ``tests/Makefile.include`` Rules for external test harnesses. These include the TCG tests and the Avocado-based integration tests. diff --git a/docs/devel/migration.rst b/docs/devel/migration.rst index 5adf4f12f7..ec55089b25 100644 --- a/docs/devel/migration.rst +++ b/docs/devel/migration.rst @@ -1061,7 +1061,7 @@ QEMU version, in this case pc-5.1. 4 - qemu-5.1 -M pc-5.2 -> migrates to -> qemu-5.1 -M pc-5.2 - This combination is not possible as the qemu-5.1 doen't understand + This combination is not possible as the qemu-5.1 doesn't understand pc-5.2 machine type. So nothing to worry here. Now it comes the interesting ones, when both QEMU processes are @@ -1214,8 +1214,8 @@ machine types to have the right value:: ... }; -A device with diferent features on both sides ---------------------------------------------- +A device with different features on both sides +---------------------------------------------- Let's assume that we are using the same QEMU binary on both sides, just to make the things easier. But we have a device that has @@ -1294,12 +1294,12 @@ Host B: $ qemu-system-x86_64 -cpu host,taa-no=off -And you would be able to migrate between them. It is responsability +And you would be able to migrate between them. It is responsibility of the management application or of the user to make sure that the configuration is correct. QEMU doesn't know how to look at this kind of features in general. -Notice that we don't recomend to use -cpu host for migration. It is +Notice that we don't recommend to use -cpu host for migration. It is used in this example because it makes the example simpler. Other devices have worse control about individual features. If they diff --git a/docs/devel/s390-cpu-topology.rst b/docs/devel/s390-cpu-topology.rst index 9eab28d5e5..48313b92d4 100644 --- a/docs/devel/s390-cpu-topology.rst +++ b/docs/devel/s390-cpu-topology.rst @@ -15,7 +15,7 @@ have default values: -smp 1,drawers=3,books=3,sockets=2,cores=2,maxcpus=36 \ -device z14-s390x-cpu,core-id=19,entitlement=high \ -device z14-s390x-cpu,core-id=11,entitlement=low \ - -device z14-s390x-cpu,core-id=112,entitlement=high \ + -device z14-s390x-cpu,core-id=12,entitlement=high \ ... Additions to query-cpus-fast @@ -78,7 +78,7 @@ modifiers for all configured vCPUs. "dedicated": true, "thread-id": 537005, "props": { - "core-id": 112, + "core-id": 12, "socket-id": 0, "drawer-id": 3, "book-id": 2 @@ -86,7 +86,7 @@ modifiers for all configured vCPUs. "cpu-state": "operating", "entitlement": "high", "qom-path": "/machine/peripheral-anon/device[2]", - "cpu-index": 112, + "cpu-index": 12, "target": "s390x" } ] diff --git a/docs/devel/testing.rst b/docs/devel/testing.rst index fef64accc1..bd132306c1 100644 --- a/docs/devel/testing.rst +++ b/docs/devel/testing.rst @@ -1016,7 +1016,7 @@ class. Here's a simple usage example: self.vm.launch() res = self.vm.cmd('human-monitor-command', command_line='info version') - self.assertRegexpMatches(res, r'^(\d+\.\d+\.\d)') + self.assertRegex(res, r'^(\d+\.\d+\.\d)') To execute your test, run: @@ -1077,7 +1077,7 @@ and hypothetical example follows: 'human-monitor-command', command_line='info version') - self.assertEquals(first_res, second_res, third_res) + self.assertEqual(first_res, second_res, third_res) At test "tear down", ``avocado_qemu.Test`` handles all the QEMUMachines shutdown. @@ -1371,23 +1371,33 @@ conditions. For example, tests that take longer to execute when QEMU is compiled with debug flags. Therefore, the ``AVOCADO_TIMEOUT_EXPECTED`` variable has been used to determine whether those tests should run or not. -GITLAB_CI -^^^^^^^^^ -A number of tests are flagged to not run on the GitLab CI. Usually because -they proved to the flaky or there are constraints on the CI environment which -would make them fail. If you encounter a similar situation then use that -variable as shown on the code snippet below to skip the test: - -.. code:: - - @skipIf(os.getenv('GITLAB_CI'), 'Running on GitLab') - def test(self): - do_something() - QEMU_TEST_FLAKY_TESTS ^^^^^^^^^^^^^^^^^^^^^ Some tests are not working reliably and thus are disabled by default. -Set this environment variable to enable them. +This includes tests that don't run reliably on GitLab's CI which +usually expose real issues that are rarely seen on developer machines +due to the constraints of the CI environment. If you encounter a +similar situation then raise a bug and then mark the test as shown on +the code snippet below: + +.. code:: + + # See https://gitlab.com/qemu-project/qemu/-/issues/nnnn + @skipUnless(os.getenv('QEMU_TEST_FLAKY_TESTS'), 'Test is unstable on GitLab') + def test(self): + do_something() + +You can also add ``:avocado: tags=flaky`` to the test meta-data so +only the flaky tests can be run as a group: + +.. code:: + + env QEMU_TEST_FLAKY_TESTS=1 ./pyvenv/bin/avocado \ + run tests/avocado -filter-by-tags=flaky + +Tests should not live in this state forever and should either be fixed +or eventually removed. + Uninstalling Avocado ~~~~~~~~~~~~~~~~~~~~ diff --git a/docs/requirements.txt b/docs/requirements.txt new file mode 100644 index 0000000000..691e5218ec --- /dev/null +++ b/docs/requirements.txt @@ -0,0 +1,2 @@ +sphinx==5.3.0 +sphinx_rtd_theme==1.1.1 diff --git a/docs/specs/tpm.rst b/docs/specs/tpm.rst index efe124a148..c96776a369 100644 --- a/docs/specs/tpm.rst +++ b/docs/specs/tpm.rst @@ -1,3 +1,5 @@ +.. _tpm-device: + =============== QEMU TPM Device =============== diff --git a/docs/system/arm/emulation.rst b/docs/system/arm/emulation.rst index 47fd648035..0b604f9005 100644 --- a/docs/system/arm/emulation.rst +++ b/docs/system/arm/emulation.rst @@ -70,7 +70,7 @@ the following architecture extensions: - FEAT_PAN2 (AT S1E1R and AT S1E1W instruction variants affected by PSTATE.PAN) - FEAT_PAN3 (Support for SCTLR_ELx.EPAN) - FEAT_PAuth (Pointer authentication) -- FEAT_PAuth2 (Enhacements to pointer authentication) +- FEAT_PAuth2 (Enhancements to pointer authentication) - FEAT_PMULL (PMULL, PMULL2 instructions) - FEAT_PMUv3p1 (PMU Extensions v3.1) - FEAT_PMUv3p4 (PMU Extensions v3.4) diff --git a/docs/system/arm/xenpvh.rst b/docs/system/arm/xenpvh.rst index e1655c7ab8..430ac2c02e 100644 --- a/docs/system/arm/xenpvh.rst +++ b/docs/system/arm/xenpvh.rst @@ -1,34 +1,39 @@ -XENPVH (``xenpvh``) +Xen Device Emulation Backend (``xenpvh``) ========================================= -This machine creates a IOREQ server to register/connect with Xen Hypervisor. -When TPM is enabled, this machine also creates a tpm-tis-device at a user input -tpm base address, adds a TPM emulator and connects to a swtpm application -running on host machine via chardev socket. This enables xenpvh to support TPM -functionalities for a guest domain. +This machine is a little unusual compared to others as QEMU just acts +as an IOREQ server to register/connect with Xen Hypervisor. Control of +the VMs themselves is left to the Xen tooling. -More information about TPM use and installing swtpm linux application can be -found at: docs/specs/tpm.rst. +When TPM is enabled, this machine also creates a tpm-tis-device at a +user input tpm base address, adds a TPM emulator and connects to a +swtpm application running on host machine via chardev socket. This +enables xenpvh to support TPM functionalities for a guest domain. + +More information about TPM use and installing swtpm linux application +can be found in the :ref:`tpm-device` section. Example for starting swtpm on host machine: + .. code-block:: console mkdir /tmp/vtpm2 swtpm socket --tpmstate dir=/tmp/vtpm2 \ - --ctrl type=unixio,path=/tmp/vtpm2/swtpm-sock & + --ctrl type=unixio,path=/tmp/vtpm2/swtpm-sock & Sample QEMU xenpvh commands for running and connecting with Xen: + .. code-block:: console qemu-system-aarch64 -xen-domid 1 \ - -chardev socket,id=libxl-cmd,path=qmp-libxl-1,server=on,wait=off \ - -mon chardev=libxl-cmd,mode=control \ - -chardev socket,id=libxenstat-cmd,path=qmp-libxenstat-1,server=on,wait=off \ - -mon chardev=libxenstat-cmd,mode=control \ - -xen-attach -name guest0 -vnc none -display none -nographic \ - -machine xenpvh -m 1301 \ - -chardev socket,id=chrtpm,path=tmp/vtpm2/swtpm-sock \ - -tpmdev emulator,id=tpm0,chardev=chrtpm -machine tpm-base-addr=0x0C000000 + -chardev socket,id=libxl-cmd,path=qmp-libxl-1,server=on,wait=off \ + -mon chardev=libxl-cmd,mode=control \ + -chardev socket,id=libxenstat-cmd,path=qmp-libxenstat-1,server=on,wait=off \ + -mon chardev=libxenstat-cmd,mode=control \ + -xen-attach -name guest0 -vnc none -display none -nographic \ + -machine xenpvh -m 1301 \ + -chardev socket,id=chrtpm,path=tmp/vtpm2/swtpm-sock \ + -tpmdev emulator,id=tpm0,chardev=chrtpm -machine tpm-base-addr=0x0C000000 In above QEMU command, last two lines are for connecting xenpvh QEMU to swtpm via chardev socket. diff --git a/docs/system/gdb.rst b/docs/system/gdb.rst index 9906991b84..4228cb56bb 100644 --- a/docs/system/gdb.rst +++ b/docs/system/gdb.rst @@ -60,7 +60,7 @@ As TCG cannot track all memory accesses in user-mode there is no support for watchpoints. Relocating code ---------------- +=============== On modern kernels confusion can be caused by code being relocated by features such as address space layout randomisation. To avoid @@ -68,6 +68,17 @@ confusion when debugging such things you either need to update gdb's view of where things are in memory or perhaps more trivially disable ASLR when booting the system. +Debugging user-space in system emulation +======================================== + +While it is technically possible to debug a user-space program running +inside a system image, it does present challenges. Kernel preemption +and execution mode changes between kernel and user mode can make it +hard to follow what's going on. Unless you are specifically trying to +debug some interaction between kernel and user-space you are better +off running your guest program with gdb either in the guest or using +a gdbserver exposed via a port to the outside world. + Debugging multicore machines ============================ diff --git a/gdbstub/gdbstub.c b/gdbstub/gdbstub.c index 01363a525b..a0baf68f4e 100644 --- a/gdbstub/gdbstub.c +++ b/gdbstub/gdbstub.c @@ -692,7 +692,7 @@ static int gdb_handle_vcont(const char *p) /* * target_count and last_target keep track of how many CPUs we are going to * step or resume, and a pointer to the state structure of one of them, - * respectivelly + * respectively */ int target_count = 0; CPUState *last_target = NULL; diff --git a/gdbstub/internals.h b/gdbstub/internals.h index e5e822a9a4..cf02a83ddd 100644 --- a/gdbstub/internals.h +++ b/gdbstub/internals.h @@ -24,6 +24,7 @@ enum { GDB_SIGNAL_TRAP = 5, GDB_SIGNAL_ABRT = 6, GDB_SIGNAL_ALRM = 14, + GDB_SIGNAL_STOP = 17, GDB_SIGNAL_IO = 23, GDB_SIGNAL_XCPU = 24, GDB_SIGNAL_UNKNOWN = 143 diff --git a/gdbstub/system.c b/gdbstub/system.c index 0f0bd920cf..f6abead908 100644 --- a/gdbstub/system.c +++ b/gdbstub/system.c @@ -183,7 +183,7 @@ static void gdb_vm_state_change(void *opaque, bool running, RunState state) break; case RUN_STATE_IO_ERROR: trace_gdbstub_hit_io_error(); - ret = GDB_SIGNAL_IO; + ret = GDB_SIGNAL_STOP; break; case RUN_STATE_WATCHDOG: trace_gdbstub_hit_watchdog(); diff --git a/hw/acpi/erst.c b/hw/acpi/erst.c index 35007d8017..ba751dc60e 100644 --- a/hw/acpi/erst.c +++ b/hw/acpi/erst.c @@ -947,6 +947,7 @@ static const VMStateDescription erst_vmstate = { static void erst_realizefn(PCIDevice *pci_dev, Error **errp) { + ERRP_GUARD(); ERSTDeviceState *s = ACPIERST(pci_dev); trace_acpi_erst_realizefn_in(); @@ -964,9 +965,15 @@ static void erst_realizefn(PCIDevice *pci_dev, Error **errp) /* HostMemoryBackend size will be multiple of PAGE_SIZE */ s->storage_size = object_property_get_int(OBJECT(s->hostmem), "size", errp); + if (*errp) { + return; + } /* Initialize backend storage and record_count */ check_erst_backend_storage(s, errp); + if (*errp) { + return; + } /* BAR 0: Programming registers */ memory_region_init_io(&s->iomem_mr, OBJECT(pci_dev), &erst_reg_ops, s, @@ -977,6 +984,9 @@ static void erst_realizefn(PCIDevice *pci_dev, Error **errp) memory_region_init_ram(&s->exchange_mr, OBJECT(pci_dev), "erst.exchange", le32_to_cpu(s->header->record_size), errp); + if (*errp) { + return; + } pci_register_bar(pci_dev, 1, PCI_BASE_ADDRESS_SPACE_MEMORY, &s->exchange_mr); diff --git a/hw/arm/fsl-imx25.c b/hw/arm/fsl-imx25.c index 24c4374590..9aabbf7f58 100644 --- a/hw/arm/fsl-imx25.c +++ b/hw/arm/fsl-imx25.c @@ -169,7 +169,8 @@ static void fsl_imx25_realize(DeviceState *dev, Error **errp) epit_table[i].irq)); } - object_property_set_uint(OBJECT(&s->fec), "phy-num", s->phy_num, &err); + object_property_set_uint(OBJECT(&s->fec), "phy-num", s->phy_num, + &error_abort); qdev_set_nic_properties(DEVICE(&s->fec), &nd_table[0]); if (!sysbus_realize(SYS_BUS_DEVICE(&s->fec), errp)) { diff --git a/hw/arm/fsl-imx6.c b/hw/arm/fsl-imx6.c index 4fa7f0b95e..7dc42cbfe6 100644 --- a/hw/arm/fsl-imx6.c +++ b/hw/arm/fsl-imx6.c @@ -379,7 +379,8 @@ static void fsl_imx6_realize(DeviceState *dev, Error **errp) spi_table[i].irq)); } - object_property_set_uint(OBJECT(&s->eth), "phy-num", s->phy_num, &err); + object_property_set_uint(OBJECT(&s->eth), "phy-num", s->phy_num, + &error_abort); qdev_set_nic_properties(DEVICE(&s->eth), &nd_table[0]); if (!sysbus_realize(SYS_BUS_DEVICE(&s->eth), errp)) { return; diff --git a/hw/arm/netduino2.c b/hw/arm/netduino2.c index 83753d53a3..501f63a77f 100644 --- a/hw/arm/netduino2.c +++ b/hw/arm/netduino2.c @@ -44,7 +44,6 @@ static void netduino2_init(MachineState *machine) clock_set_hz(sysclk, SYSCLK_FRQ); dev = qdev_new(TYPE_STM32F205_SOC); - qdev_prop_set_string(dev, "cpu-type", ARM_CPU_TYPE_NAME("cortex-m3")); qdev_connect_clock_in(dev, "sysclk", sysclk); sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal); @@ -54,8 +53,14 @@ static void netduino2_init(MachineState *machine) static void netduino2_machine_init(MachineClass *mc) { + static const char * const valid_cpu_types[] = { + ARM_CPU_TYPE_NAME("cortex-m3"), + NULL + }; + mc->desc = "Netduino 2 Machine (Cortex-M3)"; mc->init = netduino2_init; + mc->valid_cpu_types = valid_cpu_types; mc->ignore_memory_transaction_failures = true; } diff --git a/hw/arm/netduinoplus2.c b/hw/arm/netduinoplus2.c index 515c081605..2e58984947 100644 --- a/hw/arm/netduinoplus2.c +++ b/hw/arm/netduinoplus2.c @@ -44,7 +44,6 @@ static void netduinoplus2_init(MachineState *machine) clock_set_hz(sysclk, SYSCLK_FRQ); dev = qdev_new(TYPE_STM32F405_SOC); - qdev_prop_set_string(dev, "cpu-type", ARM_CPU_TYPE_NAME("cortex-m4")); qdev_connect_clock_in(dev, "sysclk", sysclk); sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal); @@ -55,8 +54,14 @@ static void netduinoplus2_init(MachineState *machine) static void netduinoplus2_machine_init(MachineClass *mc) { + static const char * const valid_cpu_types[] = { + ARM_CPU_TYPE_NAME("cortex-m4"), + NULL + }; + mc->desc = "Netduino Plus 2 Machine (Cortex-M4)"; mc->init = netduinoplus2_init; + mc->valid_cpu_types = valid_cpu_types; } DEFINE_MACHINE("netduinoplus2", netduinoplus2_machine_init) diff --git a/hw/arm/olimex-stm32-h405.c b/hw/arm/olimex-stm32-h405.c index 3aa61c91b7..d793de7c97 100644 --- a/hw/arm/olimex-stm32-h405.c +++ b/hw/arm/olimex-stm32-h405.c @@ -47,7 +47,6 @@ static void olimex_stm32_h405_init(MachineState *machine) clock_set_hz(sysclk, SYSCLK_FRQ); dev = qdev_new(TYPE_STM32F405_SOC); - qdev_prop_set_string(dev, "cpu-type", ARM_CPU_TYPE_NAME("cortex-m4")); qdev_connect_clock_in(dev, "sysclk", sysclk); sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal); @@ -58,9 +57,14 @@ static void olimex_stm32_h405_init(MachineState *machine) static void olimex_stm32_h405_machine_init(MachineClass *mc) { + static const char * const valid_cpu_types[] = { + ARM_CPU_TYPE_NAME("cortex-m4"), + NULL + }; + mc->desc = "Olimex STM32-H405 (Cortex-M4)"; mc->init = olimex_stm32_h405_init; - mc->default_cpu_type = ARM_CPU_TYPE_NAME("cortex-m4"); + mc->valid_cpu_types = valid_cpu_types; /* SRAM pre-allocated as part of the SoC instantiation */ mc->default_ram_size = 0; diff --git a/hw/arm/stm32f100_soc.c b/hw/arm/stm32f100_soc.c index f7b344ba9f..b90d440d7a 100644 --- a/hw/arm/stm32f100_soc.c +++ b/hw/arm/stm32f100_soc.c @@ -115,7 +115,7 @@ static void stm32f100_soc_realize(DeviceState *dev_soc, Error **errp) /* Init ARMv7m */ armv7m = DEVICE(&s->armv7m); qdev_prop_set_uint32(armv7m, "num-irq", 61); - qdev_prop_set_string(armv7m, "cpu-type", s->cpu_type); + qdev_prop_set_string(armv7m, "cpu-type", ARM_CPU_TYPE_NAME("cortex-m3")); qdev_prop_set_bit(armv7m, "enable-bitband", true); qdev_connect_clock_in(armv7m, "cpuclk", s->sysclk); qdev_connect_clock_in(armv7m, "refclk", s->refclk); @@ -180,17 +180,12 @@ static void stm32f100_soc_realize(DeviceState *dev_soc, Error **errp) create_unimplemented_device("CRC", 0x40023000, 0x400); } -static Property stm32f100_soc_properties[] = { - DEFINE_PROP_STRING("cpu-type", STM32F100State, cpu_type), - DEFINE_PROP_END_OF_LIST(), -}; - static void stm32f100_soc_class_init(ObjectClass *klass, void *data) { DeviceClass *dc = DEVICE_CLASS(klass); dc->realize = stm32f100_soc_realize; - device_class_set_props(dc, stm32f100_soc_properties); + /* No vmstate or reset required: device has no internal state */ } static const TypeInfo stm32f100_soc_info = { diff --git a/hw/arm/stm32f205_soc.c b/hw/arm/stm32f205_soc.c index c6b75a381d..1a548646f6 100644 --- a/hw/arm/stm32f205_soc.c +++ b/hw/arm/stm32f205_soc.c @@ -127,7 +127,7 @@ static void stm32f205_soc_realize(DeviceState *dev_soc, Error **errp) armv7m = DEVICE(&s->armv7m); qdev_prop_set_uint32(armv7m, "num-irq", 96); - qdev_prop_set_string(armv7m, "cpu-type", s->cpu_type); + qdev_prop_set_string(armv7m, "cpu-type", ARM_CPU_TYPE_NAME("cortex-m3")); qdev_prop_set_bit(armv7m, "enable-bitband", true); qdev_connect_clock_in(armv7m, "cpuclk", s->sysclk); qdev_connect_clock_in(armv7m, "refclk", s->refclk); @@ -201,17 +201,12 @@ static void stm32f205_soc_realize(DeviceState *dev_soc, Error **errp) } } -static Property stm32f205_soc_properties[] = { - DEFINE_PROP_STRING("cpu-type", STM32F205State, cpu_type), - DEFINE_PROP_END_OF_LIST(), -}; - static void stm32f205_soc_class_init(ObjectClass *klass, void *data) { DeviceClass *dc = DEVICE_CLASS(klass); dc->realize = stm32f205_soc_realize; - device_class_set_props(dc, stm32f205_soc_properties); + /* No vmstate or reset required: device has no internal state */ } static const TypeInfo stm32f205_soc_info = { diff --git a/hw/arm/stm32f405_soc.c b/hw/arm/stm32f405_soc.c index cef23d7ee4..a65bbe298d 100644 --- a/hw/arm/stm32f405_soc.c +++ b/hw/arm/stm32f405_soc.c @@ -149,7 +149,7 @@ static void stm32f405_soc_realize(DeviceState *dev_soc, Error **errp) armv7m = DEVICE(&s->armv7m); qdev_prop_set_uint32(armv7m, "num-irq", 96); - qdev_prop_set_string(armv7m, "cpu-type", s->cpu_type); + qdev_prop_set_string(armv7m, "cpu-type", ARM_CPU_TYPE_NAME("cortex-m4")); qdev_prop_set_bit(armv7m, "enable-bitband", true); qdev_connect_clock_in(armv7m, "cpuclk", s->sysclk); qdev_connect_clock_in(armv7m, "refclk", s->refclk); @@ -287,17 +287,11 @@ static void stm32f405_soc_realize(DeviceState *dev_soc, Error **errp) create_unimplemented_device("RNG", 0x50060800, 0x400); } -static Property stm32f405_soc_properties[] = { - DEFINE_PROP_STRING("cpu-type", STM32F405State, cpu_type), - DEFINE_PROP_END_OF_LIST(), -}; - static void stm32f405_soc_class_init(ObjectClass *klass, void *data) { DeviceClass *dc = DEVICE_CLASS(klass); dc->realize = stm32f405_soc_realize; - device_class_set_props(dc, stm32f405_soc_properties); /* No vmstate or reset required: device has no internal state */ } diff --git a/hw/arm/stm32vldiscovery.c b/hw/arm/stm32vldiscovery.c index 67675e952f..190db6118b 100644 --- a/hw/arm/stm32vldiscovery.c +++ b/hw/arm/stm32vldiscovery.c @@ -47,7 +47,6 @@ static void stm32vldiscovery_init(MachineState *machine) clock_set_hz(sysclk, SYSCLK_FRQ); dev = qdev_new(TYPE_STM32F100_SOC); - qdev_prop_set_string(dev, "cpu-type", ARM_CPU_TYPE_NAME("cortex-m3")); qdev_connect_clock_in(dev, "sysclk", sysclk); sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal); @@ -58,8 +57,14 @@ static void stm32vldiscovery_init(MachineState *machine) static void stm32vldiscovery_machine_init(MachineClass *mc) { + static const char * const valid_cpu_types[] = { + ARM_CPU_TYPE_NAME("cortex-m3"), + NULL + }; + mc->desc = "ST STM32VLDISCOVERY (Cortex-M3)"; mc->init = stm32vldiscovery_init; + mc->valid_cpu_types = valid_cpu_types; } DEFINE_MACHINE("stm32vldiscovery", stm32vldiscovery_machine_init) diff --git a/hw/audio/hda-codec.c b/hw/audio/hda-codec.c index b9ad1f4c39..0bc20d49f6 100644 --- a/hw/audio/hda-codec.c +++ b/hw/audio/hda-codec.c @@ -22,6 +22,7 @@ #include "hw/qdev-properties.h" #include "intel-hda.h" #include "migration/vmstate.h" +#include "qemu/host-utils.h" #include "qemu/module.h" #include "intel-hda-defs.h" #include "audio/audio.h" @@ -189,9 +190,9 @@ struct HDAAudioState { bool use_timer; }; -static inline int64_t hda_bytes_per_second(HDAAudioStream *st) +static inline uint32_t hda_bytes_per_second(HDAAudioStream *st) { - return 2LL * st->as.nchannels * st->as.freq; + return 2 * (uint32_t)st->as.nchannels * (uint32_t)st->as.freq; } static inline void hda_timer_sync_adjust(HDAAudioStream *st, int64_t target_pos) @@ -222,12 +223,18 @@ static void hda_audio_input_timer(void *opaque) int64_t now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL); - int64_t buft_start = st->buft_start; + int64_t uptime = now - st->buft_start; int64_t wpos = st->wpos; int64_t rpos = st->rpos; + int64_t wanted_rpos; - int64_t wanted_rpos = hda_bytes_per_second(st) * (now - buft_start) - / NANOSECONDS_PER_SECOND; + if (uptime <= 0) { + /* wanted_rpos <= 0 */ + goto out_timer; + } + + wanted_rpos = muldiv64(uptime, hda_bytes_per_second(st), + NANOSECONDS_PER_SECOND); wanted_rpos &= -4; /* IMPORTANT! clip to frames */ if (wanted_rpos <= rpos) { @@ -286,12 +293,18 @@ static void hda_audio_output_timer(void *opaque) int64_t now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL); - int64_t buft_start = st->buft_start; + int64_t uptime = now - st->buft_start; int64_t wpos = st->wpos; int64_t rpos = st->rpos; + int64_t wanted_wpos; - int64_t wanted_wpos = hda_bytes_per_second(st) * (now - buft_start) - / NANOSECONDS_PER_SECOND; + if (uptime <= 0) { + /* wanted_wpos <= 0 */ + goto out_timer; + } + + wanted_wpos = muldiv64(uptime, hda_bytes_per_second(st), + NANOSECONDS_PER_SECOND); wanted_wpos &= -4; /* IMPORTANT! clip to frames */ if (wanted_wpos <= wpos) { @@ -855,10 +868,10 @@ static Property hda_audio_properties[] = { static void hda_audio_init_output(HDACodecDevice *hda, Error **errp) { HDAAudioState *a = HDA_AUDIO(hda); - const struct desc_codec *desc = &output_nomixemu; + const struct desc_codec *desc = &output_mixemu; if (!a->mixer) { - desc = &output_mixemu; + desc = &output_nomixemu; } hda_audio_init(hda, desc, errp); @@ -867,10 +880,10 @@ static void hda_audio_init_output(HDACodecDevice *hda, Error **errp) static void hda_audio_init_duplex(HDACodecDevice *hda, Error **errp) { HDAAudioState *a = HDA_AUDIO(hda); - const struct desc_codec *desc = &duplex_nomixemu; + const struct desc_codec *desc = &duplex_mixemu; if (!a->mixer) { - desc = &duplex_mixemu; + desc = &duplex_nomixemu; } hda_audio_init(hda, desc, errp); @@ -879,10 +892,10 @@ static void hda_audio_init_duplex(HDACodecDevice *hda, Error **errp) static void hda_audio_init_micro(HDACodecDevice *hda, Error **errp) { HDAAudioState *a = HDA_AUDIO(hda); - const struct desc_codec *desc = µ_nomixemu; + const struct desc_codec *desc = µ_mixemu; if (!a->mixer) { - desc = µ_mixemu; + desc = µ_nomixemu; } hda_audio_init(hda, desc, errp); diff --git a/hw/audio/via-ac97.c b/hw/audio/via-ac97.c index 30095a4c7a..4c127a1def 100644 --- a/hw/audio/via-ac97.c +++ b/hw/audio/via-ac97.c @@ -211,14 +211,14 @@ static void out_cb(void *opaque, int avail) AUD_set_active_out(s->vo, 0); } if (c->type & STAT_EOL) { - pci_set_irq(&s->dev, 1); + via_isa_set_irq(&s->dev, 0, 1); } } if (CLEN_IS_FLAG(c)) { c->stat |= STAT_FLAG; c->stat |= STAT_PAUSED; if (c->type & STAT_FLAG) { - pci_set_irq(&s->dev, 1); + via_isa_set_irq(&s->dev, 0, 1); } } if (CLEN_IS_STOP(c)) { @@ -305,13 +305,13 @@ static void sgd_write(void *opaque, hwaddr addr, uint64_t val, unsigned size) if (val & STAT_EOL) { s->aur.stat &= ~(STAT_EOL | STAT_PAUSED); if (s->aur.type & STAT_EOL) { - pci_set_irq(&s->dev, 0); + via_isa_set_irq(&s->dev, 0, 0); } } if (val & STAT_FLAG) { s->aur.stat &= ~(STAT_FLAG | STAT_PAUSED); if (s->aur.type & STAT_FLAG) { - pci_set_irq(&s->dev, 0); + via_isa_set_irq(&s->dev, 0, 0); } } break; diff --git a/hw/audio/virtio-snd-pci.c b/hw/audio/virtio-snd-pci.c index 0f92e0752b..ab58c6410e 100644 --- a/hw/audio/virtio-snd-pci.c +++ b/hw/audio/virtio-snd-pci.c @@ -47,12 +47,14 @@ static void virtio_snd_pci_class_init(ObjectClass *klass, void *data) { DeviceClass *dc = DEVICE_CLASS(klass); VirtioPCIClass *vpciklass = VIRTIO_PCI_CLASS(klass); + PCIDeviceClass *pcidevklass = PCI_DEVICE_CLASS(klass); device_class_set_props(dc, virtio_snd_pci_properties); dc->desc = "Virtio Sound"; set_bit(DEVICE_CATEGORY_SOUND, dc->categories); vpciklass->realize = virtio_snd_pci_realize; + pcidevklass->class_id = PCI_CLASS_MULTIMEDIA_AUDIO; } static void virtio_snd_pci_instance_init(Object *obj) diff --git a/hw/audio/virtio-snd.c b/hw/audio/virtio-snd.c index a18a9949a7..137fa77a01 100644 --- a/hw/audio/virtio-snd.c +++ b/hw/audio/virtio-snd.c @@ -36,6 +36,7 @@ static void virtio_snd_pcm_out_cb(void *data, int available); static void virtio_snd_process_cmdq(VirtIOSound *s); static void virtio_snd_pcm_flush(VirtIOSoundPCMStream *stream); static void virtio_snd_pcm_in_cb(void *data, int available); +static void virtio_snd_unrealize(DeviceState *dev); static uint32_t supported_formats = BIT(VIRTIO_SND_PCM_FMT_S8) | BIT(VIRTIO_SND_PCM_FMT_U8) @@ -68,6 +69,7 @@ static const VMStateDescription vmstate_virtio_snd_device = { static const VMStateDescription vmstate_virtio_snd = { .name = TYPE_VIRTIO_SND, + .unmigratable = 1, .minimum_version_id = VIRTIO_SOUND_VM_VERSION, .version_id = VIRTIO_SOUND_VM_VERSION, .fields = (VMStateField[]) { @@ -1065,23 +1067,9 @@ static void virtio_snd_realize(DeviceState *dev, Error **errp) virtio_snd_pcm_set_params default_params = { 0 }; uint32_t status; - vsnd->pcm = NULL; - vsnd->vmstate = - qemu_add_vm_change_state_handler(virtio_snd_vm_state_change, vsnd); - trace_virtio_snd_realize(vsnd); - vsnd->pcm = g_new0(VirtIOSoundPCM, 1); - vsnd->pcm->snd = vsnd; - vsnd->pcm->streams = - g_new0(VirtIOSoundPCMStream *, vsnd->snd_conf.streams); - vsnd->pcm->pcm_params = - g_new0(virtio_snd_pcm_set_params, vsnd->snd_conf.streams); - - virtio_init(vdev, VIRTIO_ID_SOUND, sizeof(virtio_snd_config)); - virtio_add_feature(&vsnd->features, VIRTIO_F_VERSION_1); - - /* set number of jacks and streams */ + /* check number of jacks and streams */ if (vsnd->snd_conf.jacks > 8) { error_setg(errp, "Invalid number of jacks: %"PRIu32, @@ -1102,7 +1090,22 @@ static void virtio_snd_realize(DeviceState *dev, Error **errp) return; } - AUD_register_card("virtio-sound", &vsnd->card, errp); + if (!AUD_register_card("virtio-sound", &vsnd->card, errp)) { + return; + } + + vsnd->vmstate = + qemu_add_vm_change_state_handler(virtio_snd_vm_state_change, vsnd); + + vsnd->pcm = g_new0(VirtIOSoundPCM, 1); + vsnd->pcm->snd = vsnd; + vsnd->pcm->streams = + g_new0(VirtIOSoundPCMStream *, vsnd->snd_conf.streams); + vsnd->pcm->pcm_params = + g_new0(virtio_snd_pcm_set_params, vsnd->snd_conf.streams); + + virtio_init(vdev, VIRTIO_ID_SOUND, sizeof(virtio_snd_config)); + virtio_add_feature(&vsnd->features, VIRTIO_F_VERSION_1); /* set default params for all streams */ default_params.features = 0; @@ -1126,18 +1129,23 @@ static void virtio_snd_realize(DeviceState *dev, Error **errp) status = virtio_snd_set_pcm_params(vsnd, i, &default_params); if (status != cpu_to_le32(VIRTIO_SND_S_OK)) { error_setg(errp, - "Can't initalize stream params, device responded with %s.", + "Can't initialize stream params, device responded with %s.", print_code(status)); - return; + goto error_cleanup; } status = virtio_snd_pcm_prepare(vsnd, i); if (status != cpu_to_le32(VIRTIO_SND_S_OK)) { error_setg(errp, "Can't prepare streams, device responded with %s.", print_code(status)); - return; + goto error_cleanup; } } + + return; + +error_cleanup: + virtio_snd_unrealize(dev); } static inline void return_tx_buffer(VirtIOSoundPCMStream *stream, diff --git a/hw/avr/atmega.c b/hw/avr/atmega.c index a34803e642..31c8992d75 100644 --- a/hw/avr/atmega.c +++ b/hw/avr/atmega.c @@ -233,6 +233,10 @@ static void atmega_realize(DeviceState *dev, Error **errp) /* CPU */ object_initialize_child(OBJECT(dev), "cpu", &s->cpu, mc->cpu_type); + + object_property_set_uint(OBJECT(&s->cpu), "init-sp", + mc->io_size + mc->sram_size - 1, &error_abort); + qdev_realize(DEVICE(&s->cpu), NULL, &error_abort); cpudev = DEVICE(&s->cpu); diff --git a/hw/block/pflash_cfi01.c b/hw/block/pflash_cfi01.c index 62056b1d74..5e848a9b4c 100644 --- a/hw/block/pflash_cfi01.c +++ b/hw/block/pflash_cfi01.c @@ -80,16 +80,39 @@ struct PFlashCFI01 { uint16_t ident3; uint8_t cfi_table[0x52]; uint64_t counter; - unsigned int writeblock_size; + uint32_t writeblock_size; MemoryRegion mem; char *name; void *storage; VMChangeStateEntry *vmstate; bool old_multiple_chip_handling; + + /* block update buffer */ + unsigned char *blk_bytes; + uint32_t blk_offset; }; static int pflash_post_load(void *opaque, int version_id); +static bool pflash_blk_write_state_needed(void *opaque) +{ + PFlashCFI01 *pfl = opaque; + + return (pfl->blk_offset != -1); +} + +static const VMStateDescription vmstate_pflash_blk_write = { + .name = "pflash_cfi01_blk_write", + .version_id = 1, + .minimum_version_id = 1, + .needed = pflash_blk_write_state_needed, + .fields = (const VMStateField[]) { + VMSTATE_VBUFFER_UINT32(blk_bytes, PFlashCFI01, 0, NULL, writeblock_size), + VMSTATE_UINT32(blk_offset, PFlashCFI01), + VMSTATE_END_OF_LIST() + } +}; + static const VMStateDescription vmstate_pflash = { .name = "pflash_cfi01", .version_id = 1, @@ -101,6 +124,10 @@ static const VMStateDescription vmstate_pflash = { VMSTATE_UINT8(status, PFlashCFI01), VMSTATE_UINT64(counter, PFlashCFI01), VMSTATE_END_OF_LIST() + }, + .subsections = (const VMStateDescription * []) { + &vmstate_pflash_blk_write, + NULL } }; @@ -225,34 +252,10 @@ static uint32_t pflash_data_read(PFlashCFI01 *pfl, hwaddr offset, uint32_t ret; p = pfl->storage; - switch (width) { - case 1: - ret = p[offset]; - break; - case 2: - if (be) { - ret = p[offset] << 8; - ret |= p[offset + 1]; - } else { - ret = p[offset]; - ret |= p[offset + 1] << 8; - } - break; - case 4: - if (be) { - ret = p[offset] << 24; - ret |= p[offset + 1] << 16; - ret |= p[offset + 2] << 8; - ret |= p[offset + 3]; - } else { - ret = p[offset]; - ret |= p[offset + 1] << 8; - ret |= p[offset + 2] << 16; - ret |= p[offset + 3] << 24; - } - break; - default: - abort(); + if (be) { + ret = ldn_be_p(p + offset, width); + } else { + ret = ldn_le_p(p + offset, width); } trace_pflash_data_read(pfl->name, offset, width, ret); return ret; @@ -400,40 +403,61 @@ static void pflash_update(PFlashCFI01 *pfl, int offset, } } +/* copy current flash content to block update buffer */ +static void pflash_blk_write_start(PFlashCFI01 *pfl, hwaddr offset) +{ + hwaddr mask = ~(pfl->writeblock_size - 1); + + trace_pflash_write_block_start(pfl->name, pfl->counter); + pfl->blk_offset = offset & mask; + memcpy(pfl->blk_bytes, pfl->storage + pfl->blk_offset, + pfl->writeblock_size); +} + +/* commit block update buffer changes */ +static void pflash_blk_write_flush(PFlashCFI01 *pfl) +{ + g_assert(pfl->blk_offset != -1); + trace_pflash_write_block_flush(pfl->name); + memcpy(pfl->storage + pfl->blk_offset, pfl->blk_bytes, + pfl->writeblock_size); + pflash_update(pfl, pfl->blk_offset, pfl->writeblock_size); + pfl->blk_offset = -1; +} + +/* discard block update buffer changes */ +static void pflash_blk_write_abort(PFlashCFI01 *pfl) +{ + trace_pflash_write_block_abort(pfl->name); + pfl->blk_offset = -1; +} + static inline void pflash_data_write(PFlashCFI01 *pfl, hwaddr offset, uint32_t value, int width, int be) { - uint8_t *p = pfl->storage; + uint8_t *p; - trace_pflash_data_write(pfl->name, offset, width, value, pfl->counter); - switch (width) { - case 1: - p[offset] = value; - break; - case 2: - if (be) { - p[offset] = value >> 8; - p[offset + 1] = value; - } else { - p[offset] = value; - p[offset + 1] = value >> 8; + if (pfl->blk_offset != -1) { + /* block write: redirect writes to block update buffer */ + if ((offset < pfl->blk_offset) || + (offset + width > pfl->blk_offset + pfl->writeblock_size)) { + pfl->status |= 0x10; /* Programming error */ + return; } - break; - case 4: - if (be) { - p[offset] = value >> 24; - p[offset + 1] = value >> 16; - p[offset + 2] = value >> 8; - p[offset + 3] = value; - } else { - p[offset] = value; - p[offset + 1] = value >> 8; - p[offset + 2] = value >> 16; - p[offset + 3] = value >> 24; - } - break; + trace_pflash_data_write_block(pfl->name, offset, width, value, + pfl->counter); + p = pfl->blk_bytes + (offset - pfl->blk_offset); + } else { + /* write directly to storage */ + trace_pflash_data_write(pfl->name, offset, width, value); + p = pfl->storage + offset; } + if (be) { + stn_be_p(p, width, value); + } else { + stn_le_p(p, width, value); + } } static void pflash_write(PFlashCFI01 *pfl, hwaddr offset, @@ -548,9 +572,9 @@ static void pflash_write(PFlashCFI01 *pfl, hwaddr offset, } else { value = extract32(value, 0, pfl->bank_width * 8); } - trace_pflash_write_block(pfl->name, value); pfl->counter = value; pfl->wcycle++; + pflash_blk_write_start(pfl, offset); break; case 0x60: if (cmd == 0xd0) { @@ -581,12 +605,7 @@ static void pflash_write(PFlashCFI01 *pfl, hwaddr offset, switch (pfl->cmd) { case 0xe8: /* Block write */ /* FIXME check @offset, @width */ - if (!pfl->ro) { - /* - * FIXME writing straight to memory is *wrong*. We - * should write to a buffer, and flush it to memory - * only on confirm command (see below). - */ + if (!pfl->ro && (pfl->blk_offset != -1)) { pflash_data_write(pfl, offset, value, width, be); } else { pfl->status |= 0x10; /* Programming error */ @@ -595,18 +614,8 @@ static void pflash_write(PFlashCFI01 *pfl, hwaddr offset, pfl->status |= 0x80; if (!pfl->counter) { - hwaddr mask = pfl->writeblock_size - 1; - mask = ~mask; - trace_pflash_write(pfl->name, "block write finished"); pfl->wcycle++; - if (!pfl->ro) { - /* Flush the entire write buffer onto backing storage. */ - /* FIXME premature! */ - pflash_update(pfl, offset & mask, pfl->writeblock_size); - } else { - pfl->status |= 0x10; /* Programming error */ - } } pfl->counter--; @@ -618,20 +627,17 @@ static void pflash_write(PFlashCFI01 *pfl, hwaddr offset, case 3: /* Confirm mode */ switch (pfl->cmd) { case 0xe8: /* Block write */ - if (cmd == 0xd0) { - /* FIXME this is where we should write out the buffer */ + if ((cmd == 0xd0) && !(pfl->status & 0x10)) { + pflash_blk_write_flush(pfl); pfl->wcycle = 0; pfl->status |= 0x80; } else { - qemu_log_mask(LOG_UNIMP, - "%s: Aborting write to buffer not implemented," - " the data is already written to storage!\n" - "Flash device reset into READ mode.\n", - __func__); + pflash_blk_write_abort(pfl); goto mode_read_array; } break; default: + pflash_blk_write_abort(pfl); goto error_flash; } break; @@ -865,6 +871,9 @@ static void pflash_cfi01_realize(DeviceState *dev, Error **errp) pfl->cmd = 0x00; pfl->status = 0x80; /* WSM ready */ pflash_cfi01_fill_cfi_table(pfl); + + pfl->blk_bytes = g_malloc(pfl->writeblock_size); + pfl->blk_offset = -1; } static void pflash_cfi01_system_reset(DeviceState *dev) @@ -884,6 +893,8 @@ static void pflash_cfi01_system_reset(DeviceState *dev) * This model deliberately ignores this delay. */ pfl->status = 0x80; + + pfl->blk_offset = -1; } static Property pflash_cfi01_properties[] = { diff --git a/hw/block/pflash_cfi02.c b/hw/block/pflash_cfi02.c index 2a99b286b0..6fa56f14c0 100644 --- a/hw/block/pflash_cfi02.c +++ b/hw/block/pflash_cfi02.c @@ -546,7 +546,7 @@ static void pflash_write(void *opaque, hwaddr offset, uint64_t value, } goto reset_flash; } - trace_pflash_data_write(pfl->name, offset, width, value, 0); + trace_pflash_data_write(pfl->name, offset, width, value); if (!pfl->ro) { p = (uint8_t *)pfl->storage + offset; if (pfl->be) { diff --git a/hw/block/trace-events b/hw/block/trace-events index bab21d3a1c..cc9a9f2460 100644 --- a/hw/block/trace-events +++ b/hw/block/trace-events @@ -12,7 +12,8 @@ fdctrl_tc_pulse(int level) "TC pulse: %u" pflash_chip_erase_invalid(const char *name, uint64_t offset) "%s: chip erase: invalid address 0x%" PRIx64 pflash_chip_erase_start(const char *name) "%s: start chip erase" pflash_data_read(const char *name, uint64_t offset, unsigned size, uint32_t value) "%s: data offset:0x%04"PRIx64" size:%u value:0x%04x" -pflash_data_write(const char *name, uint64_t offset, unsigned size, uint32_t value, uint64_t counter) "%s: data offset:0x%04"PRIx64" size:%u value:0x%04x counter:0x%016"PRIx64 +pflash_data_write(const char *name, uint64_t offset, unsigned size, uint32_t value) "%s: data offset:0x%04"PRIx64" size:%u value:0x%04x" +pflash_data_write_block(const char *name, uint64_t offset, unsigned size, uint32_t value, uint64_t counter) "%s: data offset:0x%04"PRIx64" size:%u value:0x%04x counter:0x%016"PRIx64 pflash_device_id(const char *name, uint16_t id) "%s: read device ID: 0x%04x" pflash_device_info(const char *name, uint64_t offset) "%s: read device information offset:0x%04" PRIx64 pflash_erase_complete(const char *name) "%s: sector erase complete" @@ -32,7 +33,9 @@ pflash_unlock0_failed(const char *name, uint64_t offset, uint8_t cmd, uint16_t a pflash_unlock1_failed(const char *name, uint64_t offset, uint8_t cmd) "%s: unlock0 failed 0x%" PRIx64 " 0x%02x" pflash_unsupported_device_configuration(const char *name, uint8_t width, uint8_t max) "%s: unsupported device configuration: device_width:%d max_device_width:%d" pflash_write(const char *name, const char *str) "%s: %s" -pflash_write_block(const char *name, uint32_t value) "%s: block write: bytes:0x%x" +pflash_write_block_start(const char *name, uint32_t value) "%s: block write start: bytes:0x%x" +pflash_write_block_flush(const char *name) "%s: block write flush" +pflash_write_block_abort(const char *name) "%s: block write abort" pflash_write_block_erase(const char *name, uint64_t offset, uint64_t len) "%s: block erase offset:0x%" PRIx64 " bytes:0x%" PRIx64 pflash_write_failed(const char *name, uint64_t offset, uint8_t cmd) "%s: command failed 0x%" PRIx64 " 0x%02x" pflash_write_invalid(const char *name, uint8_t cmd) "%s: invalid write for command 0x%02x" diff --git a/hw/block/vhost-user-blk.c b/hw/block/vhost-user-blk.c index 818b833108..2863d80d15 100644 --- a/hw/block/vhost-user-blk.c +++ b/hw/block/vhost-user-blk.c @@ -326,7 +326,6 @@ static int vhost_user_blk_connect(DeviceState *dev, Error **errp) if (s->connected) { return 0; } - s->connected = true; s->dev.num_queues = s->num_queues; s->dev.nvqs = s->num_queues; @@ -343,15 +342,14 @@ static int vhost_user_blk_connect(DeviceState *dev, Error **errp) return ret; } + s->connected = true; + /* restore vhost state */ if (virtio_device_started(vdev, vdev->status)) { ret = vhost_user_blk_start(vdev, errp); - if (ret < 0) { - return ret; - } } - return 0; + return ret; } static void vhost_user_blk_disconnect(DeviceState *dev) diff --git a/hw/block/xen-block.c b/hw/block/xen-block.c index 6d64ede94f..aed1d5c330 100644 --- a/hw/block/xen-block.c +++ b/hw/block/xen-block.c @@ -91,9 +91,27 @@ static bool xen_block_find_free_vdev(XenBlockDevice *blockdev, Error **errp) existing_frontends = qemu_xen_xs_directory(xenbus->xsh, XBT_NULL, fe_path, &nr_existing); - if (!existing_frontends && errno != ENOENT) { - error_setg_errno(errp, errno, "cannot read %s", fe_path); - return false; + if (!existing_frontends) { + if (errno == ENOENT) { + /* + * If the frontend directory doesn't exist because there are + * no existing vbd devices, that's fine. Just ensure that we + * don't dereference the NULL existing_frontends pointer, by + * checking that nr_existing is zero so the loop below is not + * entered. + * + * In fact this is redundant since nr_existing is initialized + * to zero, but setting it again here makes it abundantly clear + * to Coverity, and to the human reader who doesn't know the + * semantics of qemu_xen_xs_directory() off the top of their + * head. + */ + nr_existing = 0; + } else { + /* All other errors accessing the frontend directory are fatal. */ + error_setg_errno(errp, errno, "cannot read %s", fe_path); + return false; + } } memset(used_devs, 0, sizeof(used_devs)); diff --git a/hw/core/loader.c b/hw/core/loader.c index 3c79283777..e7a9b3775b 100644 --- a/hw/core/loader.c +++ b/hw/core/loader.c @@ -505,7 +505,7 @@ ssize_t load_elf_ram_sym(const char *filename, clear_lsb, data_swab, as, load_rom, sym_cb); } - if (ret != ELF_LOAD_FAILED) { + if (ret > 0) { debuginfo_report_elf(filename, fd, 0); } diff --git a/hw/core/qdev-properties.c b/hw/core/qdev-properties.c index 91632f7be9..840006e953 100644 --- a/hw/core/qdev-properties.c +++ b/hw/core/qdev-properties.c @@ -689,23 +689,36 @@ static void get_prop_array(Object *obj, Visitor *v, const char *name, Property *prop = opaque; uint32_t *alenptr = object_field_prop_ptr(obj, prop); void **arrayptr = (void *)obj + prop->arrayoffset; - char *elem = *arrayptr; - GenericList *list; - const size_t list_elem_size = sizeof(*list) + prop->arrayfieldsize; + char *elemptr = *arrayptr; + ArrayElementList *list = NULL, *elem; + ArrayElementList **tail = &list; + const size_t size = sizeof(*list); int i; bool ok; - if (!visit_start_list(v, name, &list, list_elem_size, errp)) { + /* At least the string output visitor needs a real list */ + for (i = 0; i < *alenptr; i++) { + elem = g_new0(ArrayElementList, 1); + elem->value = elemptr; + elemptr += prop->arrayfieldsize; + + *tail = elem; + tail = &elem->next; + } + + if (!visit_start_list(v, name, (GenericList **) &list, size, errp)) { return; } - for (i = 0; i < *alenptr; i++) { - Property elem_prop = array_elem_prop(obj, prop, name, elem); + elem = list; + while (elem) { + Property elem_prop = array_elem_prop(obj, prop, name, elem->value); prop->arrayinfo->get(obj, v, NULL, &elem_prop, errp); if (*errp) { goto out_obj; } - elem += prop->arrayfieldsize; + elem = (ArrayElementList *) visit_next_list(v, (GenericList*) elem, + size); } /* visit_check_list() can only fail for input visitors */ @@ -714,6 +727,12 @@ static void get_prop_array(Object *obj, Visitor *v, const char *name, out_obj: visit_end_list(v, (void**) &list); + + while (list) { + elem = list; + list = elem->next; + g_free(elem); + } } static void default_prop_array(ObjectProperty *op, const Property *prop) diff --git a/hw/cxl/cxl-component-utils.c b/hw/cxl/cxl-component-utils.c index d0245cc55d..29d477492b 100644 --- a/hw/cxl/cxl-component-utils.c +++ b/hw/cxl/cxl-component-utils.c @@ -81,7 +81,7 @@ static uint64_t cxl_cache_mem_read_reg(void *opaque, hwaddr offset, return 0; default: /* - * In line with specifiction limitaions on access sizes, this + * In line with specification limitaions on access sizes, this * routine is not called with other sizes. */ g_assert_not_reached(); @@ -152,7 +152,7 @@ static void cxl_cache_mem_write_reg(void *opaque, hwaddr offset, uint64_t value, return; default: /* - * In line with specifiction limitaions on access sizes, this + * In line with specification limitaions on access sizes, this * routine is not called with other sizes. */ g_assert_not_reached(); diff --git a/hw/cxl/cxl-mailbox-utils.c b/hw/cxl/cxl-mailbox-utils.c index b365575097..6eff56fb1b 100644 --- a/hw/cxl/cxl-mailbox-utils.c +++ b/hw/cxl/cxl-mailbox-utils.c @@ -431,7 +431,7 @@ static CXLRetCode cmd_identify_switch_device(const struct cxl_cmd *cmd, out = (struct cxl_fmapi_ident_switch_dev_resp_pl *)payload_out; *out = (struct cxl_fmapi_ident_switch_dev_resp_pl) { .num_physical_ports = num_phys_ports + 1, /* 1 USP */ - .num_vcss = 1, /* Not yet support multiple VCS - potentialy tricky */ + .num_vcss = 1, /* Not yet support multiple VCS - potentially tricky */ .active_vcs_bitmask[0] = 0x1, .total_vppbs = num_phys_ports + 1, .bound_vppbs = num_phys_ports + 1, diff --git a/hw/dma/xlnx_csu_dma.c b/hw/dma/xlnx_csu_dma.c index e89089821a..bc1505aade 100644 --- a/hw/dma/xlnx_csu_dma.c +++ b/hw/dma/xlnx_csu_dma.c @@ -33,13 +33,13 @@ /* * Ref: UG1087 (v1.7) February 8, 2019 - * https://www.xilinx.com/html_docs/registers/ug1087/ug1087-zynq-ultrascale-registers.html + * https://www.xilinx.com/html_docs/registers/ug1087/ug1087-zynq-ultrascale-registers * CSUDMA Module section */ REG32(ADDR, 0x0) FIELD(ADDR, ADDR, 2, 30) /* wo */ REG32(SIZE, 0x4) - FIELD(SIZE, SIZE, 2, 27) /* wo */ + FIELD(SIZE, SIZE, 2, 27) FIELD(SIZE, LAST_WORD, 0, 1) /* rw, only exists in SRC */ REG32(STATUS, 0x8) FIELD(STATUS, DONE_CNT, 13, 3) /* wtc */ @@ -335,10 +335,14 @@ static uint64_t addr_pre_write(RegisterInfo *reg, uint64_t val) static uint64_t size_pre_write(RegisterInfo *reg, uint64_t val) { XlnxCSUDMA *s = XLNX_CSU_DMA(reg->opaque); + uint64_t size = val & R_SIZE_SIZE_MASK; if (s->regs[R_SIZE] != 0) { - qemu_log_mask(LOG_GUEST_ERROR, - "%s: Starting DMA while already running.\n", __func__); + if (size || s->is_dst) { + qemu_log_mask(LOG_GUEST_ERROR, + "%s: Starting DMA while already running.\n", + __func__); + } } if (!s->is_dst) { @@ -346,7 +350,7 @@ static uint64_t size_pre_write(RegisterInfo *reg, uint64_t val) } /* Size is word aligned */ - return val & R_SIZE_SIZE_MASK; + return size; } static uint64_t size_post_read(RegisterInfo *reg, uint64_t val) diff --git a/hw/hppa/machine.c b/hw/hppa/machine.c index 9d08f39490..9e611620cc 100644 --- a/hw/hppa/machine.c +++ b/hw/hppa/machine.c @@ -36,8 +36,8 @@ #define MIN_SEABIOS_HPPA_VERSION 12 /* require at least this fw version */ -/* Power button address at &PAGE0->pad[4] */ -#define HPA_POWER_BUTTON (0x40 + 4 * sizeof(uint32_t)) +#define HPA_POWER_BUTTON (FIRMWARE_END - 0x10) +static hwaddr soft_power_reg; #define enable_lasi_lan() 0 @@ -45,7 +45,6 @@ static DeviceState *lasi_dev; static void hppa_powerdown_req(Notifier *n, void *opaque) { - hwaddr soft_power_reg = HPA_POWER_BUTTON; uint32_t val; val = ldl_be_phys(&address_space_memory, soft_power_reg); @@ -221,7 +220,7 @@ static FWCfgState *create_fw_cfg(MachineState *ms, PCIBus *pci_bus, fw_cfg_add_file(fw_cfg, "/etc/hppa/machine", g_memdup(mc->name, len), len); - val = cpu_to_le64(HPA_POWER_BUTTON); + val = cpu_to_le64(soft_power_reg); fw_cfg_add_file(fw_cfg, "/etc/hppa/power-button-addr", g_memdup(&val, sizeof(val)), sizeof(val)); @@ -276,6 +275,7 @@ static TranslateFn *machine_HP_common_init_cpus(MachineState *machine) unsigned int smp_cpus = machine->smp.cpus; TranslateFn *translate; MemoryRegion *cpu_region; + uint64_t ram_max; /* Create CPUs. */ for (unsigned int i = 0; i < smp_cpus; i++) { @@ -288,10 +288,14 @@ static TranslateFn *machine_HP_common_init_cpus(MachineState *machine) */ if (hppa_is_pa20(&cpu[0]->env)) { translate = translate_pa20; + ram_max = 0xf0000000; /* 3.75 GB (limited by 32-bit firmware) */ } else { translate = translate_pa10; + ram_max = 0xf0000000; /* 3.75 GB (32-bit CPU) */ } + soft_power_reg = translate(NULL, HPA_POWER_BUTTON); + for (unsigned int i = 0; i < smp_cpus; i++) { g_autofree char *name = g_strdup_printf("cpu%u-io-eir", i); @@ -311,9 +315,9 @@ static TranslateFn *machine_HP_common_init_cpus(MachineState *machine) cpu_region); /* Main memory region. */ - if (machine->ram_size > 3 * GiB) { - error_report("RAM size is currently restricted to 3GB"); - exit(EXIT_FAILURE); + if (machine->ram_size > ram_max) { + info_report("Max RAM size limited to %" PRIu64 " MB", ram_max / MiB); + machine->ram_size = ram_max; } memory_region_add_subregion_overlap(addr_space, 0, machine->ram, -1); @@ -343,8 +347,10 @@ static void machine_HP_common_init_tail(MachineState *machine, PCIBus *pci_bus, SysBusDevice *s; /* SCSI disk setup. */ - dev = DEVICE(pci_create_simple(pci_bus, -1, "lsi53c895a")); - lsi53c8xx_handle_legacy_cmdline(dev); + if (drive_get_max_bus(IF_SCSI) >= 0) { + dev = DEVICE(pci_create_simple(pci_bus, -1, "lsi53c895a")); + lsi53c8xx_handle_legacy_cmdline(dev); + } /* Graphics setup. */ if (machine->enable_graphics && vga_interface_type != VGA_NONE) { @@ -357,7 +363,7 @@ static void machine_HP_common_init_tail(MachineState *machine, PCIBus *pci_bus, } /* Network setup. */ - if (enable_lasi_lan()) { + if (nd_table[0].used && enable_lasi_lan()) { lasi_82596_init(addr_space, translate(NULL, LASI_LAN_HPA), qdev_get_gpio_in(lasi_dev, LASI_IRQ_LAN_HPA)); } @@ -382,7 +388,7 @@ static void machine_HP_common_init_tail(MachineState *machine, PCIBus *pci_bus, pci_set_word(&pci_dev->config[PCI_SUBSYSTEM_ID], 0x1227); /* Powerbar */ /* create a second serial PCI card when running Astro */ - if (!lasi_dev) { + if (serial_hd(1) && !lasi_dev) { pci_dev = pci_new(-1, "pci-serial-4x"); qdev_prop_set_chr(DEVICE(pci_dev), "chardev1", serial_hd(1)); qdev_prop_set_chr(DEVICE(pci_dev), "chardev2", serial_hd(2)); @@ -672,19 +678,18 @@ static void hppa_nmi(NMIState *n, int cpu_index, Error **errp) } } -static const char *HP_B160L_machine_valid_cpu_types[] = { - TYPE_HPPA_CPU, - NULL -}; - static void HP_B160L_machine_init_class_init(ObjectClass *oc, void *data) { + static const char * const valid_cpu_types[] = { + TYPE_HPPA_CPU, + NULL + }; MachineClass *mc = MACHINE_CLASS(oc); NMIClass *nc = NMI_CLASS(oc); mc->desc = "HP B160L workstation"; mc->default_cpu_type = TYPE_HPPA_CPU; - mc->valid_cpu_types = HP_B160L_machine_valid_cpu_types; + mc->valid_cpu_types = valid_cpu_types; mc->init = machine_HP_B160L_init; mc->reset = hppa_machine_reset; mc->block_default_type = IF_SCSI; @@ -709,19 +714,18 @@ static const TypeInfo HP_B160L_machine_init_typeinfo = { }, }; -static const char *HP_C3700_machine_valid_cpu_types[] = { - TYPE_HPPA64_CPU, - NULL -}; - static void HP_C3700_machine_init_class_init(ObjectClass *oc, void *data) { + static const char * const valid_cpu_types[] = { + TYPE_HPPA64_CPU, + NULL + }; MachineClass *mc = MACHINE_CLASS(oc); NMIClass *nc = NMI_CLASS(oc); mc->desc = "HP C3700 workstation"; mc->default_cpu_type = TYPE_HPPA64_CPU; - mc->valid_cpu_types = HP_C3700_machine_valid_cpu_types; + mc->valid_cpu_types = valid_cpu_types; mc->init = machine_HP_C3700_init; mc->reset = hppa_machine_reset; mc->block_default_type = IF_SCSI; diff --git a/hw/i386/sgx-stub.c b/hw/i386/sgx-stub.c index 26833eb233..16b1dfd90b 100644 --- a/hw/i386/sgx-stub.c +++ b/hw/i386/sgx-stub.c @@ -34,5 +34,5 @@ void pc_machine_init_sgx_epc(PCMachineState *pcms) bool sgx_epc_get_section(int section_nr, uint64_t *addr, uint64_t *size) { - g_assert_not_reached(); + return true; } diff --git a/hw/i386/x86.c b/hw/i386/x86.c index b3d054889b..2b6291ad8d 100644 --- a/hw/i386/x86.c +++ b/hw/i386/x86.c @@ -131,8 +131,12 @@ void x86_cpus_init(X86MachineState *x86ms, int default_cpu_version) /* * Can we support APIC ID 255 or higher? With KVM, that requires * both in-kernel lapic and X2APIC userspace API. + * + * kvm_enabled() must go first to ensure that kvm_* references are + * not emitted for the linker to consume (kvm_enabled() is + * a literal `0` in configurations where kvm_* aren't defined) */ - if (x86ms->apic_id_limit > 255 && kvm_enabled() && + if (kvm_enabled() && x86ms->apic_id_limit > 255 && (!kvm_irqchip_in_kernel() || !kvm_enable_x2apic())) { error_report("current -smp configuration requires kernel " "irqchip and X2APIC API support."); @@ -418,8 +422,13 @@ void x86_cpu_pre_plug(HotplugHandler *hotplug_dev, } cpu->thread_id = topo_ids.smt_id; - if (hyperv_feat_enabled(cpu, HYPERV_FEAT_VPINDEX) && - kvm_enabled() && !kvm_hv_vpindex_settable()) { + /* + * kvm_enabled() must go first to ensure that kvm_* references are + * not emitted for the linker to consume (kvm_enabled() is + * a literal `0` in configurations where kvm_* aren't defined) + */ + if (kvm_enabled() && hyperv_feat_enabled(cpu, HYPERV_FEAT_VPINDEX) && + !kvm_hv_vpindex_settable()) { error_setg(errp, "kernel doesn't allow setting HyperV VP_INDEX"); return; } diff --git a/hw/ide/ahci.c b/hw/ide/ahci.c index 7676e2d871..afdc44b8e0 100644 --- a/hw/ide/ahci.c +++ b/hw/ide/ahci.c @@ -623,9 +623,13 @@ static void ahci_init_d2h(AHCIDevice *ad) return; } + /* + * For simplicity, do not call ahci_clear_cmd_issue() for this + * ahci_write_fis_d2h(). (The reset value for PxCI is 0.) + */ if (ahci_write_fis_d2h(ad, true)) { ad->init_d2h_sent = true; - /* We're emulating receiving the first Reg H2D Fis from the device; + /* We're emulating receiving the first Reg D2H FIS from the device; * Update the SIG register, but otherwise proceed as normal. */ pr->sig = ((uint32_t)ide_state->hcyl << 24) | (ide_state->lcyl << 16) | @@ -663,6 +667,7 @@ static void ahci_reset_port(AHCIState *s, int port) pr->scr_act = 0; pr->tfdata = 0x7F; pr->sig = 0xFFFFFFFF; + pr->cmd_issue = 0; d->busy_slot = -1; d->init_d2h_sent = false; @@ -1242,10 +1247,30 @@ static void handle_reg_h2d_fis(AHCIState *s, int port, case STATE_RUN: if (cmd_fis[15] & ATA_SRST) { s->dev[port].port_state = STATE_RESET; + /* + * When setting SRST in the first H2D FIS in the reset sequence, + * the device does not send a D2H FIS. Host software thus has to + * set the "Clear Busy upon R_OK" bit such that PxCI (and BUSY) + * gets cleared. See AHCI 1.3.1, section 10.4.1 Software Reset. + */ + if (opts & AHCI_CMD_CLR_BUSY) { + ahci_clear_cmd_issue(ad, slot); + } } break; case STATE_RESET: if (!(cmd_fis[15] & ATA_SRST)) { + /* + * When clearing SRST in the second H2D FIS in the reset + * sequence, the device will execute diagnostics. When this is + * done, the device will send a D2H FIS with the good status. + * See SATA 3.5a Gold, section 11.4 Software reset protocol. + * + * This D2H FIS is the first D2H FIS received from the device, + * and is received regardless if the reset was performed by a + * COMRESET or by setting and clearing the SRST bit. Therefore, + * the logic for this is found in ahci_init_d2h() and not here. + */ ahci_reset_port(s, port); } break; diff --git a/hw/ide/core.c b/hw/ide/core.c index 63ba665f3d..8a0579bff4 100644 --- a/hw/ide/core.c +++ b/hw/ide/core.c @@ -81,6 +81,18 @@ static const char *IDE_DMA_CMD_str(enum ide_dma_cmd enval) static void ide_dummy_transfer_stop(IDEState *s); +const MemoryRegionPortio ide_portio_list[] = { + { 0, 8, 1, .read = ide_ioport_read, .write = ide_ioport_write }, + { 0, 1, 2, .read = ide_data_readw, .write = ide_data_writew }, + { 0, 1, 4, .read = ide_data_readl, .write = ide_data_writel }, + PORTIO_END_OF_LIST(), +}; + +const MemoryRegionPortio ide_portio2_list[] = { + { 0, 1, 1, .read = ide_status_read, .write = ide_ctrl_write }, + PORTIO_END_OF_LIST(), +}; + static void padstr(char *str, const char *src, int len) { int i, v; diff --git a/hw/ide/ioport.c b/hw/ide/ioport.c index e2ecc6230c..0b283ac783 100644 --- a/hw/ide/ioport.c +++ b/hw/ide/ioport.c @@ -28,18 +28,6 @@ #include "hw/ide/internal.h" #include "trace.h" -static const MemoryRegionPortio ide_portio_list[] = { - { 0, 8, 1, .read = ide_ioport_read, .write = ide_ioport_write }, - { 0, 1, 2, .read = ide_data_readw, .write = ide_data_writew }, - { 0, 1, 4, .read = ide_data_readl, .write = ide_data_writel }, - PORTIO_END_OF_LIST(), -}; - -static const MemoryRegionPortio ide_portio2_list[] = { - { 0, 1, 1, .read = ide_status_read, .write = ide_ctrl_write }, - PORTIO_END_OF_LIST(), -}; - int ide_init_ioport(IDEBus *bus, ISADevice *dev, int iobase, int iobase2) { int ret; diff --git a/hw/ide/pci.c b/hw/ide/pci.c index a25b352537..810c6b6d98 100644 --- a/hw/ide/pci.c +++ b/hw/ide/pci.c @@ -104,6 +104,90 @@ const MemoryRegionOps pci_ide_data_le_ops = { .endianness = DEVICE_LITTLE_ENDIAN, }; +void pci_ide_update_mode(PCIIDEState *s) +{ + PCIDevice *d = PCI_DEVICE(s); + uint8_t mode = d->config[PCI_CLASS_PROG]; + + /* + * This function only configures the BARs/ioports for now: PCI IDE + * controllers must manage their own IRQ routing + */ + + switch (mode & 0xf) { + case 0xa: + /* Both channels legacy mode */ + + /* + * TODO: according to the PCI IDE specification the BARs should + * be completely disabled, however Linux for the pegasos2 + * machine stil accesses the BAR addresses after switching to legacy + * mode. Hence we leave them active for now. + */ + + /* Clear interrupt pin */ + pci_config_set_interrupt_pin(d->config, 0); + + /* Add legacy IDE ports */ + if (!s->bus[0].portio_list.owner) { + portio_list_init(&s->bus[0].portio_list, OBJECT(d), + ide_portio_list, &s->bus[0], "ide"); + portio_list_add(&s->bus[0].portio_list, + pci_address_space_io(d), 0x1f0); + } + + if (!s->bus[0].portio2_list.owner) { + portio_list_init(&s->bus[0].portio2_list, OBJECT(d), + ide_portio2_list, &s->bus[0], "ide"); + portio_list_add(&s->bus[0].portio2_list, + pci_address_space_io(d), 0x3f6); + } + + if (!s->bus[1].portio_list.owner) { + portio_list_init(&s->bus[1].portio_list, OBJECT(d), + ide_portio_list, &s->bus[1], "ide"); + portio_list_add(&s->bus[1].portio_list, + pci_address_space_io(d), 0x170); + } + + if (!s->bus[1].portio2_list.owner) { + portio_list_init(&s->bus[1].portio2_list, OBJECT(d), + ide_portio2_list, &s->bus[1], "ide"); + portio_list_add(&s->bus[1].portio2_list, + pci_address_space_io(d), 0x376); + } + break; + + case 0xf: + /* Both channels native mode */ + + /* Set interrupt pin */ + pci_config_set_interrupt_pin(d->config, 1); + + /* Remove legacy IDE ports */ + if (s->bus[0].portio_list.owner) { + portio_list_del(&s->bus[0].portio_list); + portio_list_destroy(&s->bus[0].portio_list); + } + + if (s->bus[0].portio2_list.owner) { + portio_list_del(&s->bus[0].portio2_list); + portio_list_destroy(&s->bus[0].portio2_list); + } + + if (s->bus[1].portio_list.owner) { + portio_list_del(&s->bus[1].portio_list); + portio_list_destroy(&s->bus[1].portio_list); + } + + if (s->bus[1].portio2_list.owner) { + portio_list_del(&s->bus[1].portio2_list); + portio_list_destroy(&s->bus[1].portio2_list); + } + break; + } +} + static IDEState *bmdma_active_if(BMDMAState *bmdma) { assert(bmdma->bus->retry_unit != (uint8_t)-1); diff --git a/hw/ide/via.c b/hw/ide/via.c index fff23803a6..3f3c484253 100644 --- a/hw/ide/via.c +++ b/hw/ide/via.c @@ -28,6 +28,7 @@ #include "hw/pci/pci.h" #include "migration/vmstate.h" #include "qemu/module.h" +#include "qemu/range.h" #include "sysemu/dma.h" #include "hw/isa/vt82c686.h" #include "hw/ide/pci.h" @@ -128,16 +129,14 @@ static void via_ide_reset(DeviceState *dev) ide_bus_reset(&d->bus[i]); } + pci_config_set_prog_interface(pci_conf, 0x8a); /* legacy mode */ + pci_ide_update_mode(d); + pci_set_word(pci_conf + PCI_COMMAND, PCI_COMMAND_IO | PCI_COMMAND_WAIT); pci_set_word(pci_conf + PCI_STATUS, PCI_STATUS_FAST_BACK | PCI_STATUS_DEVSEL_MEDIUM); - pci_set_long(pci_conf + PCI_BASE_ADDRESS_0, 0x000001f0); - pci_set_long(pci_conf + PCI_BASE_ADDRESS_1, 0x000003f4); - pci_set_long(pci_conf + PCI_BASE_ADDRESS_2, 0x00000170); - pci_set_long(pci_conf + PCI_BASE_ADDRESS_3, 0x00000374); - pci_set_long(pci_conf + PCI_BASE_ADDRESS_4, 0x0000cc01); /* BMIBA: 20-23h */ - pci_set_long(pci_conf + PCI_INTERRUPT_LINE, 0x0000010e); + pci_set_byte(pci_conf + PCI_INTERRUPT_LINE, 0xe); /* IDE chip enable, IDE configuration 1/2, IDE FIFO Configuration*/ pci_set_long(pci_conf + 0x40, 0x0a090600); @@ -159,6 +158,41 @@ static void via_ide_reset(DeviceState *dev) pci_set_long(pci_conf + 0xc0, 0x00020001); } +static uint32_t via_ide_cfg_read(PCIDevice *pd, uint32_t addr, int len) +{ + uint32_t val = pci_default_read_config(pd, addr, len); + uint8_t mode = pd->config[PCI_CLASS_PROG]; + + if ((mode & 0xf) == 0xa) { + if (ranges_overlap(addr, len, PCI_BASE_ADDRESS_0, 16)) { + /* BARs 0-3 always read back zero in legacy mode */ + for (int i = addr; i < addr + len; i++) { + if (i >= PCI_BASE_ADDRESS_0 && i < PCI_BASE_ADDRESS_0 + 16) { + val &= ~(0xffULL << ((i - addr) << 3)); + } + } + } + if (addr == PCI_BASE_ADDRESS_4 && val == PCI_BASE_ADDRESS_SPACE_IO) { + /* BAR4 default value if unset */ + val = 0xcc00 | PCI_BASE_ADDRESS_SPACE_IO; + } + } + + return val; +} + +static void via_ide_cfg_write(PCIDevice *pd, uint32_t addr, + uint32_t val, int len) +{ + PCIIDEState *d = PCI_IDE(pd); + + pci_default_write_config(pd, addr, val, len); + + if (range_covers_byte(addr, len, PCI_CLASS_PROG)) { + pci_ide_update_mode(d); + } +} + static void via_ide_realize(PCIDevice *dev, Error **errp) { PCIIDEState *d = PCI_IDE(dev); @@ -166,7 +200,6 @@ static void via_ide_realize(PCIDevice *dev, Error **errp) uint8_t *pci_conf = dev->config; int i; - pci_config_set_prog_interface(pci_conf, 0x8a); /* legacy mode */ pci_set_long(pci_conf + PCI_CAPABILITY_LIST, 0x000000c0); dev->wmask[PCI_INTERRUPT_LINE] = 0; dev->wmask[PCI_CLASS_PROG] = 5; @@ -221,6 +254,8 @@ static void via_ide_class_init(ObjectClass *klass, void *data) /* Reason: only works as function of VIA southbridge */ dc->user_creatable = false; + k->config_read = via_ide_cfg_read; + k->config_write = via_ide_cfg_write; k->realize = via_ide_realize; k->exit = via_ide_exitfn; k->vendor_id = PCI_VENDOR_ID_VIA; diff --git a/hw/input/stellaris_gamepad.c b/hw/input/stellaris_gamepad.c index 06a0c0ce83..9dfa620e29 100644 --- a/hw/input/stellaris_gamepad.c +++ b/hw/input/stellaris_gamepad.c @@ -63,6 +63,13 @@ static void stellaris_gamepad_realize(DeviceState *dev, Error **errp) qemu_input_handler_register(dev, &stellaris_gamepad_handler); } +static void stellaris_gamepad_finalize(Object *obj) +{ + StellarisGamepad *s = STELLARIS_GAMEPAD(obj); + + g_free(s->keycodes); +} + static void stellaris_gamepad_reset_enter(Object *obj, ResetType type) { StellarisGamepad *s = STELLARIS_GAMEPAD(obj); @@ -92,6 +99,7 @@ static const TypeInfo stellaris_gamepad_info[] = { .name = TYPE_STELLARIS_GAMEPAD, .parent = TYPE_SYS_BUS_DEVICE, .instance_size = sizeof(StellarisGamepad), + .instance_finalize = stellaris_gamepad_finalize, .class_init = stellaris_gamepad_class_init, }, }; diff --git a/hw/intc/arm_gicv3_cpuif.c b/hw/intc/arm_gicv3_cpuif.c index d07b13eb27..258dee1b80 100644 --- a/hw/intc/arm_gicv3_cpuif.c +++ b/hw/intc/arm_gicv3_cpuif.c @@ -146,7 +146,7 @@ static uint32_t icv_fullprio_mask(GICv3CPUState *cs) * with the group priority, whose mask depends on the value of VBPR * for the interrupt group.) */ - return ~0U << (8 - cs->vpribits); + return (~0U << (8 - cs->vpribits)) & 0xff; } static int ich_highest_active_virt_prio(GICv3CPUState *cs) @@ -803,7 +803,7 @@ static uint32_t icc_fullprio_mask(GICv3CPUState *cs) * with the group priority, whose mask depends on the value of BPR * for the interrupt group.) */ - return ~0U << (8 - cs->pribits); + return (~0U << (8 - cs->pribits)) & 0xff; } static inline int icc_min_bpr(GICv3CPUState *cs) @@ -1434,16 +1434,25 @@ static void icv_eoir_write(CPUARMState *env, const ARMCPRegInfo *ri, idx = icv_find_active(cs, irq); if (idx < 0) { - /* No valid list register corresponding to EOI ID */ - icv_increment_eoicount(cs); + /* + * No valid list register corresponding to EOI ID; if this is a vLPI + * not in the list regs then do nothing; otherwise increment EOI count + */ + if (irq < GICV3_LPI_INTID_START) { + icv_increment_eoicount(cs); + } } else { uint64_t lr = cs->ich_lr_el2[idx]; int thisgrp = (lr & ICH_LR_EL2_GROUP) ? GICV3_G1NS : GICV3_G0; int lr_gprio = ich_lr_prio(lr) & icv_gprio_mask(cs, grp); if (thisgrp == grp && lr_gprio == dropprio) { - if (!icv_eoi_split(env, cs)) { - /* Priority drop and deactivate not split: deactivate irq now */ + if (!icv_eoi_split(env, cs) || irq >= GICV3_LPI_INTID_START) { + /* + * Priority drop and deactivate not split: deactivate irq now. + * LPIs always get their active state cleared immediately + * because no separate deactivate is expected. + */ icv_deactivate_irq(cs, idx); } } diff --git a/hw/isa/vt82c686.c b/hw/isa/vt82c686.c index 57bdfb4e78..9c2333a277 100644 --- a/hw/isa/vt82c686.c +++ b/hw/isa/vt82c686.c @@ -549,6 +549,7 @@ struct ViaISAState { PCIDevice dev; qemu_irq cpu_intr; qemu_irq *isa_irqs_in; + uint16_t irq_state[ISA_NUM_IRQS]; ViaSuperIOState via_sio; MC146818RtcState rtc; PCIIDEState ide; @@ -592,15 +593,9 @@ static const TypeInfo via_isa_info = { }, }; -static void via_isa_request_i8259_irq(void *opaque, int irq, int level) +static int via_isa_get_pci_irq(const ViaISAState *s, int pin) { - ViaISAState *s = opaque; - qemu_set_irq(s->cpu_intr, level); -} - -static int via_isa_get_pci_irq(const ViaISAState *s, int irq_num) -{ - switch (irq_num) { + switch (pin) { case 0: return s->dev.config[0x55] >> 4; case 1: @@ -613,29 +608,60 @@ static int via_isa_get_pci_irq(const ViaISAState *s, int irq_num) return 0; } -static void via_isa_set_pci_irq(void *opaque, int irq_num, int level) +void via_isa_set_irq(PCIDevice *d, int pin, int level) { - ViaISAState *s = opaque; - PCIBus *bus = pci_get_bus(&s->dev); - int i, pic_level, pic_irq = via_isa_get_pci_irq(s, irq_num); + ViaISAState *s = VIA_ISA(pci_get_function_0(d)); + uint8_t irq = d->config[PCI_INTERRUPT_LINE], max_irq = 15; + int f = PCI_FUNC(d->devfn); + uint16_t mask = BIT(f); - /* IRQ 0: disabled, IRQ 2,8,13: reserved */ - if (!pic_irq) { + switch (f) { + case 0: /* PIRQ/PINT inputs */ + irq = via_isa_get_pci_irq(s, pin); + f = 8 + pin; /* Use function 8-11 for PCI interrupt inputs */ + break; + case 2: /* USB ports 0-1 */ + case 3: /* USB ports 2-3 */ + case 5: /* AC97 audio */ + max_irq = 14; + break; + } + + /* Keep track of the state of all sources */ + if (level) { + s->irq_state[0] |= mask; + } else { + s->irq_state[0] &= ~mask; + } + if (irq == 0 || irq == 0xff) { + return; /* disabled */ + } + if (unlikely(irq > max_irq || irq == 2)) { + qemu_log_mask(LOG_GUEST_ERROR, "Invalid ISA IRQ routing %d for %d", + irq, f); return; } - if (unlikely(pic_irq == 2 || pic_irq == 8 || pic_irq == 13)) { - qemu_log_mask(LOG_GUEST_ERROR, "Invalid ISA IRQ routing"); + /* Record source state at mapped IRQ */ + if (level) { + s->irq_state[irq] |= mask; + } else { + s->irq_state[irq] &= ~mask; } + /* Make sure there are no stuck bits if mapping has changed */ + s->irq_state[irq] &= s->irq_state[0]; + /* ISA IRQ level is the OR of all sources routed to it */ + qemu_set_irq(s->isa_irqs_in[irq], !!s->irq_state[irq]); +} - /* The pic level is the logical OR of all the PCI irqs mapped to it. */ - pic_level = 0; - for (i = 0; i < PCI_NUM_PINS; i++) { - if (pic_irq == via_isa_get_pci_irq(s, i)) { - pic_level |= pci_bus_get_irq_level(bus, i); - } - } - /* Now we change the pic irq level according to the via irq mappings. */ - qemu_set_irq(s->isa_irqs_in[pic_irq], pic_level); +static void via_isa_pirq(void *opaque, int pin, int level) +{ + via_isa_set_irq(opaque, pin, level); +} + +static void via_isa_request_i8259_irq(void *opaque, int irq, int level) +{ + ViaISAState *s = opaque; + qemu_set_irq(s->cpu_intr, level); } static void via_isa_realize(PCIDevice *d, Error **errp) @@ -648,6 +674,7 @@ static void via_isa_realize(PCIDevice *d, Error **errp) int i; qdev_init_gpio_out(dev, &s->cpu_intr, 1); + qdev_init_gpio_in_named(dev, via_isa_pirq, "pirq", PCI_NUM_PINS); isa_irq = qemu_allocate_irqs(via_isa_request_i8259_irq, s, 1); isa_bus = isa_bus_new(dev, pci_address_space(d), pci_address_space_io(d), errp); @@ -661,8 +688,6 @@ static void via_isa_realize(PCIDevice *d, Error **errp) i8254_pit_init(isa_bus, 0x40, 0, NULL); i8257_dma_init(isa_bus, 0); - qdev_init_gpio_in_named(dev, via_isa_set_pci_irq, "pirq", PCI_NUM_PINS); - /* RTC */ qdev_prop_set_int32(DEVICE(&s->rtc), "base_year", 2000); if (!qdev_realize(DEVICE(&s->rtc), BUS(isa_bus), errp)) { diff --git a/hw/m68k/q800.c b/hw/m68k/q800.c index 1d7cd5ff1c..83d1571d02 100644 --- a/hw/m68k/q800.c +++ b/hw/m68k/q800.c @@ -726,19 +726,18 @@ static GlobalProperty hw_compat_q800[] = { }; static const size_t hw_compat_q800_len = G_N_ELEMENTS(hw_compat_q800); -static const char *q800_machine_valid_cpu_types[] = { - M68K_CPU_TYPE_NAME("m68040"), - NULL -}; - static void q800_machine_class_init(ObjectClass *oc, void *data) { + static const char * const valid_cpu_types[] = { + M68K_CPU_TYPE_NAME("m68040"), + NULL + }; MachineClass *mc = MACHINE_CLASS(oc); mc->desc = "Macintosh Quadra 800"; mc->init = q800_machine_init; mc->default_cpu_type = M68K_CPU_TYPE_NAME("m68040"); - mc->valid_cpu_types = q800_machine_valid_cpu_types; + mc->valid_cpu_types = valid_cpu_types; mc->max_cpus = 1; mc->block_default_type = IF_SCSI; mc->default_ram_id = "m68k_mac.ram"; diff --git a/hw/mem/memory-device.c b/hw/mem/memory-device.c index e0704b8dc3..a1b1af26bc 100644 --- a/hw/mem/memory-device.c +++ b/hw/mem/memory-device.c @@ -29,7 +29,7 @@ static bool memory_device_is_empty(const MemoryDeviceState *md) /* dropping const here is fine as we don't touch the memory region */ mr = mdc->get_memory_region((MemoryDeviceState *)md, &local_err); if (local_err) { - /* Not empty, we'll report errors later when ontaining the MR again. */ + /* Not empty, we'll report errors later when containing the MR again. */ error_free(local_err); return false; } diff --git a/hw/misc/edu.c b/hw/misc/edu.c index a1f8bc77e7..e64a246d3f 100644 --- a/hw/misc/edu.c +++ b/hw/misc/edu.c @@ -115,7 +115,7 @@ static void edu_check_range(uint64_t addr, uint64_t size1, uint64_t start, uint64_t end2 = start + size2; if (within(addr, start, end2) && - end1 > addr && within(end1, start, end2)) { + end1 > addr && end1 <= end2) { return; } diff --git a/hw/misc/mps2-scc.c b/hw/misc/mps2-scc.c index b3b42a792c..fe5034db14 100644 --- a/hw/misc/mps2-scc.c +++ b/hw/misc/mps2-scc.c @@ -329,6 +329,13 @@ static void mps2_scc_realize(DeviceState *dev, Error **errp) s->oscclk = g_new0(uint32_t, s->num_oscclk); } +static void mps2_scc_finalize(Object *obj) +{ + MPS2SCC *s = MPS2_SCC(obj); + + g_free(s->oscclk_reset); +} + static const VMStateDescription mps2_scc_vmstate = { .name = "mps2-scc", .version_id = 3, @@ -385,6 +392,7 @@ static const TypeInfo mps2_scc_info = { .parent = TYPE_SYS_BUS_DEVICE, .instance_size = sizeof(MPS2SCC), .instance_init = mps2_scc_init, + .instance_finalize = mps2_scc_finalize, .class_init = mps2_scc_class_init, }; diff --git a/hw/net/allwinner-sun8i-emac.c b/hw/net/allwinner-sun8i-emac.c index fac4405f45..cc350d40e5 100644 --- a/hw/net/allwinner-sun8i-emac.c +++ b/hw/net/allwinner-sun8i-emac.c @@ -824,7 +824,8 @@ static void allwinner_sun8i_emac_realize(DeviceState *dev, Error **errp) qemu_macaddr_default_if_unset(&s->conf.macaddr); s->nic = qemu_new_nic(&net_allwinner_sun8i_emac_info, &s->conf, - object_get_typename(OBJECT(dev)), dev->id, s); + object_get_typename(OBJECT(dev)), dev->id, + &dev->mem_reentrancy_guard, s); qemu_format_nic_info_str(qemu_get_queue(s->nic), s->conf.macaddr.a); } diff --git a/hw/net/allwinner_emac.c b/hw/net/allwinner_emac.c index 372e5b66da..e10965de14 100644 --- a/hw/net/allwinner_emac.c +++ b/hw/net/allwinner_emac.c @@ -453,7 +453,8 @@ static void aw_emac_realize(DeviceState *dev, Error **errp) qemu_macaddr_default_if_unset(&s->conf.macaddr); s->nic = qemu_new_nic(&net_aw_emac_info, &s->conf, - object_get_typename(OBJECT(dev)), dev->id, s); + object_get_typename(OBJECT(dev)), dev->id, + &dev->mem_reentrancy_guard, s); qemu_format_nic_info_str(qemu_get_queue(s->nic), s->conf.macaddr.a); fifo8_create(&s->rx_fifo, RX_FIFO_SIZE); diff --git a/hw/net/cadence_gem.c b/hw/net/cadence_gem.c index 5b989f5b52..472ce9c8cf 100644 --- a/hw/net/cadence_gem.c +++ b/hw/net/cadence_gem.c @@ -199,8 +199,8 @@ REG32(PHYMNTNC, 0x34) /* Phy Maintenance reg */ FIELD(PHYMNTNC, PHY_ADDR, 23, 5) FIELD(PHYMNTNC, OP, 28, 2) FIELD(PHYMNTNC, ST, 30, 2) -#define MDIO_OP_READ 0x3 -#define MDIO_OP_WRITE 0x2 +#define MDIO_OP_READ 0x2 +#define MDIO_OP_WRITE 0x1 REG32(RXPAUSE, 0x38) /* RX Pause Time reg */ REG32(TXPAUSE, 0x3c) /* TX Pause Time reg */ @@ -225,8 +225,8 @@ REG32(WOLAN, 0xb8) /* Wake on LAN reg */ REG32(IPGSTRETCH, 0xbc) /* IPG Stretch reg */ REG32(SVLAN, 0xc0) /* Stacked VLAN reg */ REG32(MODID, 0xfc) /* Module ID reg */ -REG32(OCTTXLO, 0x100) /* Octects transmitted Low reg */ -REG32(OCTTXHI, 0x104) /* Octects transmitted High reg */ +REG32(OCTTXLO, 0x100) /* Octets transmitted Low reg */ +REG32(OCTTXHI, 0x104) /* Octets transmitted High reg */ REG32(TXCNT, 0x108) /* Error-free Frames transmitted */ REG32(TXBCNT, 0x10c) /* Error-free Broadcast Frames */ REG32(TXMCNT, 0x110) /* Error-free Multicast Frame */ @@ -245,8 +245,8 @@ REG32(EXCESSCOLLCNT, 0x140) /* Excessive Collision Frames */ REG32(LATECOLLCNT, 0x144) /* Late Collision Frames */ REG32(DEFERTXCNT, 0x148) /* Deferred Transmission Frames */ REG32(CSENSECNT, 0x14c) /* Carrier Sense Error Counter */ -REG32(OCTRXLO, 0x150) /* Octects Received register Low */ -REG32(OCTRXHI, 0x154) /* Octects Received register High */ +REG32(OCTRXLO, 0x150) /* Octets Received register Low */ +REG32(OCTRXHI, 0x154) /* Octets Received register High */ REG32(RXCNT, 0x158) /* Error-free Frames Received */ REG32(RXBROADCNT, 0x15c) /* Error-free Broadcast Frames RX */ REG32(RXMULTICNT, 0x160) /* Error-free Multicast Frames RX */ @@ -1743,7 +1743,8 @@ static void gem_realize(DeviceState *dev, Error **errp) qemu_macaddr_default_if_unset(&s->conf.macaddr); s->nic = qemu_new_nic(&net_gem_info, &s->conf, - object_get_typename(OBJECT(dev)), dev->id, s); + object_get_typename(OBJECT(dev)), dev->id, + &dev->mem_reentrancy_guard, s); if (s->jumbo_max_len > MAX_FRAME_SIZE) { error_setg(errp, "jumbo-max-len is greater than %d", diff --git a/hw/net/can/can_sja1000.c b/hw/net/can/can_sja1000.c index 73201f9139..575df7d2f8 100644 --- a/hw/net/can/can_sja1000.c +++ b/hw/net/can/can_sja1000.c @@ -108,7 +108,7 @@ void can_sja_single_filter(struct qemu_can_filter *filter, } filter->can_mask = (uint32_t)amr[0] << 3; - filter->can_mask |= (uint32_t)amr[1] << 5; + filter->can_mask |= (uint32_t)amr[1] >> 5; filter->can_mask = ~filter->can_mask & QEMU_CAN_SFF_MASK; if (!(amr[1] & 0x10)) { filter->can_mask |= QEMU_CAN_RTR_FLAG; diff --git a/hw/net/can/xlnx-zynqmp-can.c b/hw/net/can/xlnx-zynqmp-can.c index e93e6c5e19..f60e480c3a 100644 --- a/hw/net/can/xlnx-zynqmp-can.c +++ b/hw/net/can/xlnx-zynqmp-can.c @@ -434,6 +434,52 @@ static bool tx_ready_check(XlnxZynqMPCANState *s) return true; } +static void read_tx_frame(XlnxZynqMPCANState *s, Fifo32 *fifo, uint32_t *data) +{ + unsigned used = fifo32_num_used(fifo); + bool is_txhpb = fifo == &s->txhpb_fifo; + + assert(used > 0); + used %= CAN_FRAME_SIZE; + + /* + * Frame Message Format + * + * Each frame includes four words (16 bytes). Software must read and write + * all four words regardless of the actual number of data bytes and valid + * fields in the message. + * If software misbehave (not writing all four words), we use the previous + * registers content to initialize each missing word. + * + * If used is 1 then ID, DLC and DATA1 are missing. + * if used is 2 then ID and DLC are missing. + * if used is 3 then only ID is missing. + */ + if (used > 0) { + data[0] = s->regs[is_txhpb ? R_TXHPB_ID : R_TXFIFO_ID]; + } else { + data[0] = fifo32_pop(fifo); + } + if (used == 1 || used == 2) { + data[1] = s->regs[is_txhpb ? R_TXHPB_DLC : R_TXFIFO_DLC]; + } else { + data[1] = fifo32_pop(fifo); + } + if (used == 1) { + data[2] = s->regs[is_txhpb ? R_TXHPB_DATA1 : R_TXFIFO_DATA1]; + } else { + data[2] = fifo32_pop(fifo); + } + /* DATA2 triggered the transfer thus is always available */ + data[3] = fifo32_pop(fifo); + + if (used) { + qemu_log_mask(LOG_GUEST_ERROR, + "%s: Incomplete CAN frame (only %u/%u slots used)\n", + TYPE_XLNX_ZYNQMP_CAN, used, CAN_FRAME_SIZE); + } +} + static void transfer_fifo(XlnxZynqMPCANState *s, Fifo32 *fifo) { qemu_can_frame frame; @@ -451,9 +497,7 @@ static void transfer_fifo(XlnxZynqMPCANState *s, Fifo32 *fifo) } while (!fifo32_is_empty(fifo)) { - for (i = 0; i < CAN_FRAME_SIZE; i++) { - data[i] = fifo32_pop(fifo); - } + read_tx_frame(s, fifo, data); if (ARRAY_FIELD_EX32(s->regs, STATUS_REGISTER, LBACK)) { /* @@ -734,14 +778,18 @@ static void update_rx_fifo(XlnxZynqMPCANState *s, const qemu_can_frame *frame) } } -static uint64_t can_rxfifo_pre_read(RegisterInfo *reg, uint64_t val) +static uint64_t can_rxfifo_post_read_id(RegisterInfo *reg, uint64_t val) { XlnxZynqMPCANState *s = XLNX_ZYNQMP_CAN(reg->opaque); + unsigned used = fifo32_num_used(&s->rx_fifo); - if (!fifo32_is_empty(&s->rx_fifo)) { - val = fifo32_pop(&s->rx_fifo); - } else { + if (used < CAN_FRAME_SIZE) { ARRAY_FIELD_DP32(s->regs, INTERRUPT_STATUS_REGISTER, RXUFLW, 1); + } else { + val = s->regs[R_RXFIFO_ID] = fifo32_pop(&s->rx_fifo); + s->regs[R_RXFIFO_DLC] = fifo32_pop(&s->rx_fifo); + s->regs[R_RXFIFO_DATA1] = fifo32_pop(&s->rx_fifo); + s->regs[R_RXFIFO_DATA2] = fifo32_pop(&s->rx_fifo); } can_update_irq(s); @@ -902,14 +950,11 @@ static const RegisterAccessInfo can_regs_info[] = { .post_write = can_tx_post_write, },{ .name = "RXFIFO_ID", .addr = A_RXFIFO_ID, .ro = 0xffffffff, - .post_read = can_rxfifo_pre_read, + .post_read = can_rxfifo_post_read_id, },{ .name = "RXFIFO_DLC", .addr = A_RXFIFO_DLC, .rsvd = 0xfff0000, - .post_read = can_rxfifo_pre_read, },{ .name = "RXFIFO_DATA1", .addr = A_RXFIFO_DATA1, - .post_read = can_rxfifo_pre_read, },{ .name = "RXFIFO_DATA2", .addr = A_RXFIFO_DATA2, - .post_read = can_rxfifo_pre_read, },{ .name = "AFR", .addr = A_AFR, .rsvd = 0xfffffff0, .post_write = can_filter_enable_post_write, diff --git a/hw/net/dp8393x.c b/hw/net/dp8393x.c index c6f5fb7dce..b16b18b3c3 100644 --- a/hw/net/dp8393x.c +++ b/hw/net/dp8393x.c @@ -913,7 +913,8 @@ static void dp8393x_realize(DeviceState *dev, Error **errp) "dp8393x-regs", SONIC_REG_COUNT << s->it_shift); s->nic = qemu_new_nic(&net_dp83932_info, &s->conf, - object_get_typename(OBJECT(dev)), dev->id, s); + object_get_typename(OBJECT(dev)), dev->id, + &dev->mem_reentrancy_guard, s); qemu_format_nic_info_str(qemu_get_queue(s->nic), s->conf.macaddr.a); s->watchdog = timer_new_ns(QEMU_CLOCK_VIRTUAL, dp8393x_watchdog, s); diff --git a/hw/net/e1000.c b/hw/net/e1000.c index 548bcabcbb..8ffe1077f1 100644 --- a/hw/net/e1000.c +++ b/hw/net/e1000.c @@ -1666,7 +1666,8 @@ static void pci_e1000_realize(PCIDevice *pci_dev, Error **errp) macaddr); d->nic = qemu_new_nic(&net_e1000_info, &d->conf, - object_get_typename(OBJECT(d)), dev->id, d); + object_get_typename(OBJECT(d)), dev->id, + &dev->mem_reentrancy_guard, d); qemu_format_nic_info_str(qemu_get_queue(d->nic), macaddr); diff --git a/hw/net/e1000e.c b/hw/net/e1000e.c index c3848797b8..e41a6c1038 100644 --- a/hw/net/e1000e.c +++ b/hw/net/e1000e.c @@ -320,7 +320,7 @@ e1000e_init_net_peer(E1000EState *s, PCIDevice *pci_dev, uint8_t *macaddr) int i; s->nic = qemu_new_nic(&net_e1000e_info, &s->conf, - object_get_typename(OBJECT(s)), dev->id, s); + object_get_typename(OBJECT(s)), dev->id, &dev->mem_reentrancy_guard, s); s->core.max_queue_num = s->conf.peers.queues ? s->conf.peers.queues - 1 : 0; diff --git a/hw/net/eepro100.c b/hw/net/eepro100.c index 94ce9e18ff..69e1c4bb89 100644 --- a/hw/net/eepro100.c +++ b/hw/net/eepro100.c @@ -1874,7 +1874,9 @@ static void e100_nic_realize(PCIDevice *pci_dev, Error **errp) nic_reset(s); s->nic = qemu_new_nic(&net_eepro100_info, &s->conf, - object_get_typename(OBJECT(pci_dev)), pci_dev->qdev.id, s); + object_get_typename(OBJECT(pci_dev)), + pci_dev->qdev.id, + &pci_dev->qdev.mem_reentrancy_guard, s); qemu_format_nic_info_str(qemu_get_queue(s->nic), s->conf.macaddr.a); TRACE(OTHER, logout("%s\n", qemu_get_queue(s->nic)->info_str)); diff --git a/hw/net/etraxfs_eth.c b/hw/net/etraxfs_eth.c index 1b82aec794..ba57a978d1 100644 --- a/hw/net/etraxfs_eth.c +++ b/hw/net/etraxfs_eth.c @@ -618,7 +618,8 @@ static void etraxfs_eth_realize(DeviceState *dev, Error **errp) qemu_macaddr_default_if_unset(&s->conf.macaddr); s->nic = qemu_new_nic(&net_etraxfs_info, &s->conf, - object_get_typename(OBJECT(s)), dev->id, s); + object_get_typename(OBJECT(s)), dev->id, + &dev->mem_reentrancy_guard, s); qemu_format_nic_info_str(qemu_get_queue(s->nic), s->conf.macaddr.a); s->phy.read = tdk_read; diff --git a/hw/net/fsl_etsec/etsec.c b/hw/net/fsl_etsec/etsec.c index 798ea33d08..00315f305d 100644 --- a/hw/net/fsl_etsec/etsec.c +++ b/hw/net/fsl_etsec/etsec.c @@ -391,7 +391,8 @@ static void etsec_realize(DeviceState *dev, Error **errp) eTSEC *etsec = ETSEC_COMMON(dev); etsec->nic = qemu_new_nic(&net_etsec_info, &etsec->conf, - object_get_typename(OBJECT(dev)), dev->id, etsec); + object_get_typename(OBJECT(dev)), dev->id, + &dev->mem_reentrancy_guard, etsec); qemu_format_nic_info_str(qemu_get_queue(etsec->nic), etsec->conf.macaddr.a); etsec->ptimer = ptimer_init(etsec_timer_hit, etsec, PTIMER_POLICY_LEGACY); diff --git a/hw/net/ftgmac100.c b/hw/net/ftgmac100.c index 702b001be2..78e594afa4 100644 --- a/hw/net/ftgmac100.c +++ b/hw/net/ftgmac100.c @@ -1110,7 +1110,8 @@ static void ftgmac100_realize(DeviceState *dev, Error **errp) qemu_macaddr_default_if_unset(&s->conf.macaddr); s->nic = qemu_new_nic(&net_ftgmac100_info, &s->conf, - object_get_typename(OBJECT(dev)), dev->id, s); + object_get_typename(OBJECT(dev)), dev->id, + &dev->mem_reentrancy_guard, s); qemu_format_nic_info_str(qemu_get_queue(s->nic), s->conf.macaddr.a); } diff --git a/hw/net/i82596.c b/hw/net/i82596.c index 6defa9d3a1..a907f0df8c 100644 --- a/hw/net/i82596.c +++ b/hw/net/i82596.c @@ -726,7 +726,7 @@ void i82596_common_init(DeviceState *dev, I82596State *s, NetClientInfo *info) qemu_macaddr_default_if_unset(&s->conf.macaddr); } s->nic = qemu_new_nic(info, &s->conf, object_get_typename(OBJECT(dev)), - dev->id, s); + dev->id, &dev->mem_reentrancy_guard, s); qemu_format_nic_info_str(qemu_get_queue(s->nic), s->conf.macaddr.a); if (USE_TIMER) { diff --git a/hw/net/igb.c b/hw/net/igb.c index dfb722b695..8089acfea4 100644 --- a/hw/net/igb.c +++ b/hw/net/igb.c @@ -325,7 +325,7 @@ igb_init_net_peer(IGBState *s, PCIDevice *pci_dev, uint8_t *macaddr) int i; s->nic = qemu_new_nic(&net_igb_info, &s->conf, - object_get_typename(OBJECT(s)), dev->id, s); + object_get_typename(OBJECT(s)), dev->id, &dev->mem_reentrancy_guard, s); s->core.max_queue_num = s->conf.peers.queues ? s->conf.peers.queues - 1 : 0; diff --git a/hw/net/imx_fec.c b/hw/net/imx_fec.c index 5d1f1f104c..6881e3e4f0 100644 --- a/hw/net/imx_fec.c +++ b/hw/net/imx_fec.c @@ -1334,7 +1334,7 @@ static void imx_eth_realize(DeviceState *dev, Error **errp) s->nic = qemu_new_nic(&imx_eth_net_info, &s->conf, object_get_typename(OBJECT(dev)), - dev->id, s); + dev->id, &dev->mem_reentrancy_guard, s); qemu_format_nic_info_str(qemu_get_queue(s->nic), s->conf.macaddr.a); } diff --git a/hw/net/lan9118.c b/hw/net/lan9118.c index e5c4af182d..cf7b8c897a 100644 --- a/hw/net/lan9118.c +++ b/hw/net/lan9118.c @@ -1361,7 +1361,8 @@ static void lan9118_realize(DeviceState *dev, Error **errp) qemu_macaddr_default_if_unset(&s->conf.macaddr); s->nic = qemu_new_nic(&net_lan9118_info, &s->conf, - object_get_typename(OBJECT(dev)), dev->id, s); + object_get_typename(OBJECT(dev)), dev->id, + &dev->mem_reentrancy_guard, s); qemu_format_nic_info_str(qemu_get_queue(s->nic), s->conf.macaddr.a); s->eeprom[0] = 0xa5; for (i = 0; i < 6; i++) { diff --git a/hw/net/mcf_fec.c b/hw/net/mcf_fec.c index ec3ddf520a..e6902716bd 100644 --- a/hw/net/mcf_fec.c +++ b/hw/net/mcf_fec.c @@ -643,7 +643,8 @@ static void mcf_fec_realize(DeviceState *dev, Error **errp) mcf_fec_state *s = MCF_FEC_NET(dev); s->nic = qemu_new_nic(&net_mcf_fec_info, &s->conf, - object_get_typename(OBJECT(dev)), dev->id, s); + object_get_typename(OBJECT(dev)), dev->id, + &dev->mem_reentrancy_guard, s); qemu_format_nic_info_str(qemu_get_queue(s->nic), s->conf.macaddr.a); } diff --git a/hw/net/mipsnet.c b/hw/net/mipsnet.c index 2ade72dea0..8e925de867 100644 --- a/hw/net/mipsnet.c +++ b/hw/net/mipsnet.c @@ -255,7 +255,8 @@ static void mipsnet_realize(DeviceState *dev, Error **errp) sysbus_init_irq(sbd, &s->irq); s->nic = qemu_new_nic(&net_mipsnet_info, &s->conf, - object_get_typename(OBJECT(dev)), dev->id, s); + object_get_typename(OBJECT(dev)), dev->id, + &dev->mem_reentrancy_guard, s); qemu_format_nic_info_str(qemu_get_queue(s->nic), s->conf.macaddr.a); } diff --git a/hw/net/msf2-emac.c b/hw/net/msf2-emac.c index db3a04deb1..145a5e46ab 100644 --- a/hw/net/msf2-emac.c +++ b/hw/net/msf2-emac.c @@ -530,7 +530,8 @@ static void msf2_emac_realize(DeviceState *dev, Error **errp) qemu_macaddr_default_if_unset(&s->conf.macaddr); s->nic = qemu_new_nic(&net_msf2_emac_info, &s->conf, - object_get_typename(OBJECT(dev)), dev->id, s); + object_get_typename(OBJECT(dev)), dev->id, + &dev->mem_reentrancy_guard, s); qemu_format_nic_info_str(qemu_get_queue(s->nic), s->conf.macaddr.a); } diff --git a/hw/net/mv88w8618_eth.c b/hw/net/mv88w8618_eth.c index ef30b0d4a6..2185f1131a 100644 --- a/hw/net/mv88w8618_eth.c +++ b/hw/net/mv88w8618_eth.c @@ -350,7 +350,8 @@ static void mv88w8618_eth_realize(DeviceState *dev, Error **errp) address_space_init(&s->dma_as, s->dma_mr, "emac-dma"); s->nic = qemu_new_nic(&net_mv88w8618_info, &s->conf, - object_get_typename(OBJECT(dev)), dev->id, s); + object_get_typename(OBJECT(dev)), dev->id, + &dev->mem_reentrancy_guard, s); } static const VMStateDescription mv88w8618_eth_vmsd = { diff --git a/hw/net/ne2000-isa.c b/hw/net/ne2000-isa.c index 6ced6775ff..a79f7fad1f 100644 --- a/hw/net/ne2000-isa.c +++ b/hw/net/ne2000-isa.c @@ -74,7 +74,8 @@ static void isa_ne2000_realizefn(DeviceState *dev, Error **errp) ne2000_reset(s); s->nic = qemu_new_nic(&net_ne2000_isa_info, &s->c, - object_get_typename(OBJECT(dev)), dev->id, s); + object_get_typename(OBJECT(dev)), dev->id, + &dev->mem_reentrancy_guard, s); qemu_format_nic_info_str(qemu_get_queue(s->nic), s->c.macaddr.a); } diff --git a/hw/net/ne2000-pci.c b/hw/net/ne2000-pci.c index edc6689d33..fee93c6ec0 100644 --- a/hw/net/ne2000-pci.c +++ b/hw/net/ne2000-pci.c @@ -71,7 +71,8 @@ static void pci_ne2000_realize(PCIDevice *pci_dev, Error **errp) s->nic = qemu_new_nic(&net_ne2000_info, &s->c, object_get_typename(OBJECT(pci_dev)), - pci_dev->qdev.id, s); + pci_dev->qdev.id, + &pci_dev->qdev.mem_reentrancy_guard, s); qemu_format_nic_info_str(qemu_get_queue(s->nic), s->c.macaddr.a); } diff --git a/hw/net/npcm7xx_emc.c b/hw/net/npcm7xx_emc.c index 8156f701b0..1d4e8f59f3 100644 --- a/hw/net/npcm7xx_emc.c +++ b/hw/net/npcm7xx_emc.c @@ -821,7 +821,8 @@ static void npcm7xx_emc_realize(DeviceState *dev, Error **errp) qemu_macaddr_default_if_unset(&emc->conf.macaddr); emc->nic = qemu_new_nic(&net_npcm7xx_emc_info, &emc->conf, - object_get_typename(OBJECT(dev)), dev->id, emc); + object_get_typename(OBJECT(dev)), dev->id, + &dev->mem_reentrancy_guard, emc); qemu_format_nic_info_str(qemu_get_queue(emc->nic), emc->conf.macaddr.a); } diff --git a/hw/net/opencores_eth.c b/hw/net/opencores_eth.c index 0b3dc3146e..f96d6ea2cc 100644 --- a/hw/net/opencores_eth.c +++ b/hw/net/opencores_eth.c @@ -732,7 +732,8 @@ static void sysbus_open_eth_realize(DeviceState *dev, Error **errp) sysbus_init_irq(sbd, &s->irq); s->nic = qemu_new_nic(&net_open_eth_info, &s->conf, - object_get_typename(OBJECT(s)), dev->id, s); + object_get_typename(OBJECT(s)), dev->id, + &dev->mem_reentrancy_guard, s); } static void qdev_open_eth_reset(DeviceState *dev) diff --git a/hw/net/pcnet.c b/hw/net/pcnet.c index 02828ae716..a7e123e60d 100644 --- a/hw/net/pcnet.c +++ b/hw/net/pcnet.c @@ -1709,7 +1709,8 @@ void pcnet_common_init(DeviceState *dev, PCNetState *s, NetClientInfo *info) s->poll_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, pcnet_poll_timer, s); qemu_macaddr_default_if_unset(&s->conf.macaddr); - s->nic = qemu_new_nic(info, &s->conf, object_get_typename(OBJECT(dev)), dev->id, s); + s->nic = qemu_new_nic(info, &s->conf, object_get_typename(OBJECT(dev)), + dev->id, &dev->mem_reentrancy_guard, s); qemu_format_nic_info_str(qemu_get_queue(s->nic), s->conf.macaddr.a); /* Initialize the PROM */ diff --git a/hw/net/rocker/rocker_fp.c b/hw/net/rocker/rocker_fp.c index 9afd0c5e3f..cb87ff752a 100644 --- a/hw/net/rocker/rocker_fp.c +++ b/hw/net/rocker/rocker_fp.c @@ -241,8 +241,8 @@ FpPort *fp_port_alloc(Rocker *r, char *sw_name, port->conf.bootindex = -1; port->conf.peers = *peers; - port->nic = qemu_new_nic(&fp_port_info, &port->conf, - sw_name, NULL, port); + port->nic = qemu_new_nic(&fp_port_info, &port->conf, sw_name, NULL, + &DEVICE(r)->mem_reentrancy_guard, port); qemu_format_nic_info_str(qemu_get_queue(port->nic), port->conf.macaddr.a); diff --git a/hw/net/rtl8139.c b/hw/net/rtl8139.c index 4525fda383..4af8c66266 100644 --- a/hw/net/rtl8139.c +++ b/hw/net/rtl8139.c @@ -3388,7 +3388,8 @@ static void pci_rtl8139_realize(PCIDevice *dev, Error **errp) s->eeprom.contents[9] = s->conf.macaddr.a[4] | s->conf.macaddr.a[5] << 8; s->nic = qemu_new_nic(&net_rtl8139_info, &s->conf, - object_get_typename(OBJECT(dev)), d->id, s); + object_get_typename(OBJECT(dev)), d->id, + &d->mem_reentrancy_guard, s); qemu_format_nic_info_str(qemu_get_queue(s->nic), s->conf.macaddr.a); s->cplus_txbuffer = NULL; diff --git a/hw/net/smc91c111.c b/hw/net/smc91c111.c index ddbceda967..876a78456a 100644 --- a/hw/net/smc91c111.c +++ b/hw/net/smc91c111.c @@ -783,7 +783,8 @@ static void smc91c111_realize(DeviceState *dev, Error **errp) sysbus_init_irq(sbd, &s->irq); qemu_macaddr_default_if_unset(&s->conf.macaddr); s->nic = qemu_new_nic(&net_smc91c111_info, &s->conf, - object_get_typename(OBJECT(dev)), dev->id, s); + object_get_typename(OBJECT(dev)), dev->id, + &dev->mem_reentrancy_guard, s); qemu_format_nic_info_str(qemu_get_queue(s->nic), s->conf.macaddr.a); /* ??? Save/restore. */ } diff --git a/hw/net/spapr_llan.c b/hw/net/spapr_llan.c index a6876a936d..475d5f3a34 100644 --- a/hw/net/spapr_llan.c +++ b/hw/net/spapr_llan.c @@ -325,7 +325,8 @@ static void spapr_vlan_realize(SpaprVioDevice *sdev, Error **errp) memcpy(&dev->perm_mac.a, &dev->nicconf.macaddr.a, sizeof(dev->perm_mac.a)); dev->nic = qemu_new_nic(&net_spapr_vlan_info, &dev->nicconf, - object_get_typename(OBJECT(sdev)), sdev->qdev.id, dev); + object_get_typename(OBJECT(sdev)), sdev->qdev.id, + &sdev->qdev.mem_reentrancy_guard, dev); qemu_format_nic_info_str(qemu_get_queue(dev->nic), dev->nicconf.macaddr.a); dev->rxp_timer = timer_new_us(QEMU_CLOCK_VIRTUAL, spapr_vlan_flush_rx_queue, diff --git a/hw/net/stellaris_enet.c b/hw/net/stellaris_enet.c index 8dd60783d8..6768a6912f 100644 --- a/hw/net/stellaris_enet.c +++ b/hw/net/stellaris_enet.c @@ -492,7 +492,8 @@ static void stellaris_enet_realize(DeviceState *dev, Error **errp) qemu_macaddr_default_if_unset(&s->conf.macaddr); s->nic = qemu_new_nic(&net_stellaris_enet_info, &s->conf, - object_get_typename(OBJECT(dev)), dev->id, s); + object_get_typename(OBJECT(dev)), dev->id, + &dev->mem_reentrancy_guard, s); qemu_format_nic_info_str(qemu_get_queue(s->nic), s->conf.macaddr.a); } diff --git a/hw/net/sungem.c b/hw/net/sungem.c index c2e2c90668..013cfc2736 100644 --- a/hw/net/sungem.c +++ b/hw/net/sungem.c @@ -1399,7 +1399,7 @@ static void sungem_realize(PCIDevice *pci_dev, Error **errp) qemu_macaddr_default_if_unset(&s->conf.macaddr); s->nic = qemu_new_nic(&net_sungem_info, &s->conf, object_get_typename(OBJECT(dev)), - dev->id, s); + dev->id, &dev->mem_reentrancy_guard, s); qemu_format_nic_info_str(qemu_get_queue(s->nic), s->conf.macaddr.a); } diff --git a/hw/net/sunhme.c b/hw/net/sunhme.c index 64d4ea5850..ddc83a64bd 100644 --- a/hw/net/sunhme.c +++ b/hw/net/sunhme.c @@ -881,7 +881,8 @@ static void sunhme_realize(PCIDevice *pci_dev, Error **errp) qemu_macaddr_default_if_unset(&s->conf.macaddr); s->nic = qemu_new_nic(&net_sunhme_info, &s->conf, - object_get_typename(OBJECT(d)), d->id, s); + object_get_typename(OBJECT(d)), d->id, + &d->mem_reentrancy_guard, s); qemu_format_nic_info_str(qemu_get_queue(s->nic), s->conf.macaddr.a); } diff --git a/hw/net/tulip.c b/hw/net/tulip.c index 11d866e431..962086aae4 100644 --- a/hw/net/tulip.c +++ b/hw/net/tulip.c @@ -983,7 +983,8 @@ static void pci_tulip_realize(PCIDevice *pci_dev, Error **errp) s->nic = qemu_new_nic(&net_tulip_info, &s->c, object_get_typename(OBJECT(pci_dev)), - pci_dev->qdev.id, s); + pci_dev->qdev.id, + &pci_dev->qdev.mem_reentrancy_guard, s); qemu_format_nic_info_str(qemu_get_queue(s->nic), s->c.macaddr.a); } diff --git a/hw/net/virtio-net.c b/hw/net/virtio-net.c index b85c7946a7..73024babd4 100644 --- a/hw/net/virtio-net.c +++ b/hw/net/virtio-net.c @@ -674,6 +674,11 @@ static void virtio_net_set_mrg_rx_bufs(VirtIONet *n, int mergeable_rx_bufs, n->mergeable_rx_bufs = mergeable_rx_bufs; + /* + * Note: when extending the vnet header, please make sure to + * change the vnet header copying logic in virtio_net_flush_tx() + * as well. + */ if (version_1) { n->guest_hdr_len = hash_report ? sizeof(struct virtio_net_hdr_v1_hash) : @@ -2693,7 +2698,7 @@ static int32_t virtio_net_flush_tx(VirtIONetQueue *q) ssize_t ret; unsigned int out_num; struct iovec sg[VIRTQUEUE_MAX_SIZE], sg2[VIRTQUEUE_MAX_SIZE + 1], *out_sg; - struct virtio_net_hdr_mrg_rxbuf mhdr; + struct virtio_net_hdr_v1_hash vhdr; elem = virtqueue_pop(q->tx_vq, sizeof(VirtQueueElement)); if (!elem) { @@ -2710,7 +2715,7 @@ static int32_t virtio_net_flush_tx(VirtIONetQueue *q) } if (n->has_vnet_hdr) { - if (iov_to_buf(out_sg, out_num, 0, &mhdr, n->guest_hdr_len) < + if (iov_to_buf(out_sg, out_num, 0, &vhdr, n->guest_hdr_len) < n->guest_hdr_len) { virtio_error(vdev, "virtio-net header incorrect"); virtqueue_detach_element(q->tx_vq, elem, 0); @@ -2718,8 +2723,8 @@ static int32_t virtio_net_flush_tx(VirtIONetQueue *q) return -EINVAL; } if (n->needs_vnet_hdr_swap) { - virtio_net_hdr_swap(vdev, (void *) &mhdr); - sg2[0].iov_base = &mhdr; + virtio_net_hdr_swap(vdev, (void *) &vhdr); + sg2[0].iov_base = &vhdr; sg2[0].iov_len = n->guest_hdr_len; out_num = iov_copy(&sg2[1], ARRAY_SIZE(sg2) - 1, out_sg, out_num, @@ -3714,10 +3719,12 @@ static void virtio_net_device_realize(DeviceState *dev, Error **errp) * Happen when virtio_net_set_netclient_name has been called. */ n->nic = qemu_new_nic(&net_virtio_info, &n->nic_conf, - n->netclient_type, n->netclient_name, n); + n->netclient_type, n->netclient_name, + &dev->mem_reentrancy_guard, n); } else { n->nic = qemu_new_nic(&net_virtio_info, &n->nic_conf, - object_get_typename(OBJECT(dev)), dev->id, n); + object_get_typename(OBJECT(dev)), dev->id, + &dev->mem_reentrancy_guard, n); } for (i = 0; i < n->max_queue_pairs; i++) { diff --git a/hw/net/vmxnet3.c b/hw/net/vmxnet3.c index 1b48d7743e..6fb4102d03 100644 --- a/hw/net/vmxnet3.c +++ b/hw/net/vmxnet3.c @@ -2078,7 +2078,7 @@ static void vmxnet3_net_init(VMXNET3State *s) s->nic = qemu_new_nic(&net_vmxnet3_info, &s->conf, object_get_typename(OBJECT(s)), - d->id, s); + d->id, &d->mem_reentrancy_guard, s); s->peer_has_vhdr = vmxnet3_peer_has_vnet_hdr(s); s->tx_sop = true; diff --git a/hw/net/xen_nic.c b/hw/net/xen_nic.c index af4ba3f1e6..1e2b3baeb1 100644 --- a/hw/net/xen_nic.c +++ b/hw/net/xen_nic.c @@ -325,7 +325,8 @@ static void xen_netdev_realize(XenDevice *xendev, Error **errp) netdev->nic = qemu_new_nic(&net_xen_info, &netdev->conf, object_get_typename(OBJECT(xendev)), - DEVICE(xendev)->id, netdev); + DEVICE(xendev)->id, + &xendev->qdev.mem_reentrancy_guard, netdev); nc = qemu_get_queue(netdev->nic); qemu_format_nic_info_str(nc, netdev->conf.macaddr.a); diff --git a/hw/net/xgmac.c b/hw/net/xgmac.c index 0ab6ae91aa..1f4f277d84 100644 --- a/hw/net/xgmac.c +++ b/hw/net/xgmac.c @@ -402,7 +402,8 @@ static void xgmac_enet_realize(DeviceState *dev, Error **errp) qemu_macaddr_default_if_unset(&s->conf.macaddr); s->nic = qemu_new_nic(&net_xgmac_enet_info, &s->conf, - object_get_typename(OBJECT(dev)), dev->id, s); + object_get_typename(OBJECT(dev)), dev->id, + &dev->mem_reentrancy_guard, s); qemu_format_nic_info_str(qemu_get_queue(s->nic), s->conf.macaddr.a); s->regs[XGMAC_ADDR_HIGH(0)] = (s->conf.macaddr.a[5] << 8) | diff --git a/hw/net/xilinx_axienet.c b/hw/net/xilinx_axienet.c index 5b19a01eaa..7d1fd37b4a 100644 --- a/hw/net/xilinx_axienet.c +++ b/hw/net/xilinx_axienet.c @@ -967,7 +967,8 @@ static void xilinx_enet_realize(DeviceState *dev, Error **errp) qemu_macaddr_default_if_unset(&s->conf.macaddr); s->nic = qemu_new_nic(&net_xilinx_enet_info, &s->conf, - object_get_typename(OBJECT(dev)), dev->id, s); + object_get_typename(OBJECT(dev)), dev->id, + &dev->mem_reentrancy_guard, s); qemu_format_nic_info_str(qemu_get_queue(s->nic), s->conf.macaddr.a); tdk_init(&s->TEMAC.phy); diff --git a/hw/net/xilinx_ethlite.c b/hw/net/xilinx_ethlite.c index 89f4f3b254..989afaf037 100644 --- a/hw/net/xilinx_ethlite.c +++ b/hw/net/xilinx_ethlite.c @@ -235,7 +235,8 @@ static void xilinx_ethlite_realize(DeviceState *dev, Error **errp) qemu_macaddr_default_if_unset(&s->conf.macaddr); s->nic = qemu_new_nic(&net_xilinx_ethlite_info, &s->conf, - object_get_typename(OBJECT(dev)), dev->id, s); + object_get_typename(OBJECT(dev)), dev->id, + &dev->mem_reentrancy_guard, s); qemu_format_nic_info_str(qemu_get_queue(s->nic), s->conf.macaddr.a); } diff --git a/hw/nios2/10m50_devboard.c b/hw/nios2/10m50_devboard.c index 952a0dc33e..6cb32f777b 100644 --- a/hw/nios2/10m50_devboard.c +++ b/hw/nios2/10m50_devboard.c @@ -160,6 +160,7 @@ static void nios2_10m50_ghrd_class_init(ObjectClass *oc, void *data) mc->desc = "Altera 10M50 GHRD Nios II design"; mc->init = nios2_10m50_ghrd_init; mc->is_default = true; + mc->deprecation_reason = "Nios II architecture is deprecated"; object_class_property_add_bool(oc, "vic", get_vic, set_vic); object_class_property_set_description(oc, "vic", diff --git a/hw/nios2/generic_nommu.c b/hw/nios2/generic_nommu.c index 48edb3ae37..defa16953f 100644 --- a/hw/nios2/generic_nommu.c +++ b/hw/nios2/generic_nommu.c @@ -95,6 +95,7 @@ static void nios2_generic_nommu_machine_init(struct MachineClass *mc) { mc->desc = "Generic NOMMU Nios II design"; mc->init = nios2_generic_nommu_init; + mc->deprecation_reason = "Nios II architecture is deprecated"; } DEFINE_MACHINE("nios2-generic-nommu", nios2_generic_nommu_machine_init); diff --git a/hw/nvram/xlnx-efuse.c b/hw/nvram/xlnx-efuse.c index 655c40b8d1..f7b849f7de 100644 --- a/hw/nvram/xlnx-efuse.c +++ b/hw/nvram/xlnx-efuse.c @@ -224,6 +224,13 @@ static void efuse_realize(DeviceState *dev, Error **errp) } } +static void efuse_finalize(Object *obj) +{ + XlnxEFuse *s = XLNX_EFUSE(obj); + + g_free(s->ro_bits); +} + static void efuse_prop_set_drive(Object *obj, Visitor *v, const char *name, void *opaque, Error **errp) { @@ -280,6 +287,7 @@ static const TypeInfo efuse_info = { .name = TYPE_XLNX_EFUSE, .parent = TYPE_DEVICE, .instance_size = sizeof(XlnxEFuse), + .instance_finalize = efuse_finalize, .class_init = efuse_class_init, }; diff --git a/hw/nvram/xlnx-versal-efuse-ctrl.c b/hw/nvram/xlnx-versal-efuse-ctrl.c index beb5661c35..2480af35e1 100644 --- a/hw/nvram/xlnx-versal-efuse-ctrl.c +++ b/hw/nvram/xlnx-versal-efuse-ctrl.c @@ -726,6 +726,13 @@ static void efuse_ctrl_init(Object *obj) sysbus_init_irq(sbd, &s->irq_efuse_imr); } +static void efuse_ctrl_finalize(Object *obj) +{ + XlnxVersalEFuseCtrl *s = XLNX_VERSAL_EFUSE_CTRL(obj); + + g_free(s->extra_pg0_lock_spec); +} + static const VMStateDescription vmstate_efuse_ctrl = { .name = TYPE_XLNX_VERSAL_EFUSE_CTRL, .version_id = 1, @@ -764,6 +771,7 @@ static const TypeInfo efuse_ctrl_info = { .instance_size = sizeof(XlnxVersalEFuseCtrl), .class_init = efuse_ctrl_class_init, .instance_init = efuse_ctrl_init, + .instance_finalize = efuse_ctrl_finalize, }; static void efuse_ctrl_register_types(void) diff --git a/hw/pci-host/astro.c b/hw/pci-host/astro.c index 7d68ccee7e..cb2c8a828d 100644 --- a/hw/pci-host/astro.c +++ b/hw/pci-host/astro.c @@ -166,6 +166,8 @@ static MemTxResult elroy_chip_write_with_attrs(void *opaque, hwaddr addr, trace_elroy_write(addr, size, val); switch ((addr >> 3) << 3) { + case 0x000: /* PCI_ID & PCI_COMMAND_STATUS_REG */ + break; case 0x080: put_val_in_int64(&s->arb_mask, addr, size, val); break; @@ -175,6 +177,9 @@ static MemTxResult elroy_chip_write_with_attrs(void *opaque, hwaddr addr, case 0x200 ... 0x250 - 1: /* LMMIO, GMMIO, WLMMIO, WGMMIO, ... */ put_val_in_arrary(s->mmio_base, 0x200, addr, size, val); break; + case 0x300: /* ibase */ + case 0x308: /* imask */ + break; case 0x0680: put_val_in_int64(&s->error_config, addr, size, val); break; @@ -538,6 +543,9 @@ static MemTxResult astro_chip_read_with_attrs(void *opaque, hwaddr addr, case 0x0030: /* HP-UX 10.20 and 11.11 reads it. No idea. */ val = -1; break; + case 0x0078: /* NetBSD reads 0x78 ? */ + val = -1; + break; case 0x0300 ... 0x03d8: /* LMMIO_DIRECT0_BASE... */ index = (addr - 0x300) / 8; val = s->ioc_ranges[index]; @@ -624,31 +632,43 @@ static MemTxResult astro_chip_write_with_attrs(void *opaque, hwaddr addr, case 0x10220: case 0x10230: /* HP-UX 11.11 reads it. No idea. */ break; - case 0x22108: /* IOC STATUS_CONTROL */ - put_val_in_int64(&s->ioc_status_ctrl, addr, size, val); - break; case 0x20200 ... 0x20240 - 1: /* IOC Rope0_Control ... */ put_val_in_arrary(s->ioc_rope_control, 0x20200, addr, size, val); break; case 0x20040: /* IOC Rope config */ + case 0x22040: put_val_in_int64(&s->ioc_rope_config, addr, size, val); break; case 0x20300: + case 0x22300: put_val_in_int64(&s->tlb_ibase, addr, size, val); break; case 0x20308: + case 0x22308: put_val_in_int64(&s->tlb_imask, addr, size, val); break; case 0x20310: + case 0x22310: put_val_in_int64(&s->tlb_pcom, addr, size, val); /* TODO: flush iommu */ break; case 0x20318: + case 0x22318: put_val_in_int64(&s->tlb_tcnfg, addr, size, val); break; case 0x20320: + case 0x22320: put_val_in_int64(&s->tlb_pdir_base, addr, size, val); break; + case 0x22000: /* func_id */ + break; + case 0x22008: /* func_class */ + break; + case 0x22050: /* rope_debug */ + break; + case 0x22108: /* IOC STATUS_CONTROL */ + put_val_in_int64(&s->ioc_status_ctrl, addr, size, val); + break; /* * empty placeholders for non-existent elroys, e.g. * func_class, pci config & data diff --git a/hw/pci/msix.c b/hw/pci/msix.c index ab8869d9d0..cd817f4ca8 100644 --- a/hw/pci/msix.c +++ b/hw/pci/msix.c @@ -648,6 +648,7 @@ undo: } dev->msix_vector_use_notifier = NULL; dev->msix_vector_release_notifier = NULL; + dev->msix_vector_poll_notifier = NULL; return ret; } diff --git a/hw/pci/pcie_sriov.c b/hw/pci/pcie_sriov.c index 5ef8950940..a1fe65f5d8 100644 --- a/hw/pci/pcie_sriov.c +++ b/hw/pci/pcie_sriov.c @@ -178,7 +178,6 @@ static void register_vfs(PCIDevice *dev) num_vfs = pci_get_word(dev->config + sriov_cap + PCI_SRIOV_NUM_VF); dev->exp.sriov_pf.vf = g_new(PCIDevice *, num_vfs); - assert(dev->exp.sriov_pf.vf); trace_sriov_register_vfs(dev->name, PCI_SLOT(dev->devfn), PCI_FUNC(dev->devfn), num_vfs); diff --git a/hw/ppc/amigaone.c b/hw/ppc/amigaone.c index 992a55e632..ddfa09457a 100644 --- a/hw/ppc/amigaone.c +++ b/hw/ppc/amigaone.c @@ -36,10 +36,19 @@ * -device VGA,romfile=VGABIOS-lgpl-latest.bin * from http://www.nongnu.org/vgabios/ instead. */ -#define PROM_FILENAME "u-boot-amigaone.bin" #define PROM_ADDR 0xfff00000 #define PROM_SIZE (512 * KiB) +/* AmigaOS calls this routine from ROM, use this if no firmware loaded */ +static const char dummy_fw[] = { + 0x38, 0x00, 0x00, 0x08, /* li r0,8 */ + 0x7c, 0x09, 0x03, 0xa6, /* mtctr r0 */ + 0x54, 0x63, 0xf8, 0x7e, /* srwi r3,r3,1 */ + 0x42, 0x00, 0xff, 0xfc, /* bdnz 0x8 */ + 0x7c, 0x63, 0x18, 0xf8, /* not r3,r3 */ + 0x4e, 0x80, 0x00, 0x20, /* blr */ +}; + static void amigaone_cpu_reset(void *opaque) { PowerPCCPU *cpu = opaque; @@ -60,8 +69,6 @@ static void amigaone_init(MachineState *machine) PowerPCCPU *cpu; CPUPPCState *env; MemoryRegion *rom, *pci_mem, *mr; - const char *fwname = machine->firmware ?: PROM_FILENAME; - char *filename; ssize_t sz; PCIBus *pci_bus; Object *via; @@ -94,20 +101,24 @@ static void amigaone_init(MachineState *machine) } /* allocate and load firmware */ - filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, fwname); - if (filename) { - rom = g_new(MemoryRegion, 1); - memory_region_init_rom(rom, NULL, "rom", PROM_SIZE, &error_fatal); - memory_region_add_subregion(get_system_memory(), PROM_ADDR, rom); + rom = g_new(MemoryRegion, 1); + memory_region_init_rom(rom, NULL, "rom", PROM_SIZE, &error_fatal); + memory_region_add_subregion(get_system_memory(), PROM_ADDR, rom); + if (!machine->firmware) { + rom_add_blob_fixed("dummy-fw", dummy_fw, sizeof(dummy_fw), + PROM_ADDR + PROM_SIZE - 0x80); + } else { + g_autofree char *filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, + machine->firmware); + if (!filename) { + error_report("Could not find firmware '%s'", machine->firmware); + exit(1); + } sz = load_image_targphys(filename, PROM_ADDR, PROM_SIZE); if (sz <= 0 || sz > PROM_SIZE) { error_report("Could not load firmware '%s'", filename); exit(1); } - g_free(filename); - } else if (!qtest_enabled()) { - error_report("Could not find firmware '%s'", fwname); - exit(1); } /* Articia S */ diff --git a/hw/ppc/pnv.c b/hw/ppc/pnv.c index 9c29727337..0297871bdd 100644 --- a/hw/ppc/pnv.c +++ b/hw/ppc/pnv.c @@ -1623,7 +1623,8 @@ static void pnv_chip_power9_realize(DeviceState *dev, Error **errp) return; } pnv_xscom_add_subregion(chip, PNV9_XSCOM_I2CM_BASE + - chip9->i2c[i].engine * PNV9_XSCOM_I2CM_SIZE, + (chip9->i2c[i].engine - 1) * + PNV9_XSCOM_I2CM_SIZE, &chip9->i2c[i].xscom_regs); qdev_connect_gpio_out(DEVICE(&chip9->i2c[i]), 0, qdev_get_gpio_in(DEVICE(&chip9->psi), @@ -1871,7 +1872,8 @@ static void pnv_chip_power10_realize(DeviceState *dev, Error **errp) return; } pnv_xscom_add_subregion(chip, PNV10_XSCOM_I2CM_BASE + - chip10->i2c[i].engine * PNV10_XSCOM_I2CM_SIZE, + (chip10->i2c[i].engine - 1) * + PNV10_XSCOM_I2CM_SIZE, &chip10->i2c[i].xscom_regs); qdev_connect_gpio_out(DEVICE(&chip10->i2c[i]), 0, qdev_get_gpio_in(DEVICE(&chip10->psi), diff --git a/hw/ppc/pnv_i2c.c b/hw/ppc/pnv_i2c.c index f75e59e709..656a48eebe 100644 --- a/hw/ppc/pnv_i2c.c +++ b/hw/ppc/pnv_i2c.c @@ -151,6 +151,7 @@ #define I2C_RESET_S_SDA_REG 0x11 #define PNV_I2C_FIFO_SIZE 8 +#define PNV_I2C_MAX_BUSSES 64 static I2CBus *pnv_i2c_get_bus(PnvI2C *i2c) { @@ -437,7 +438,7 @@ static uint64_t pnv_i2c_xscom_read(void *opaque, hwaddr addr, case I2C_PORT_BUSY_REG: /* compute busy bit for each port */ val = 0; for (i = 0; i < i2c->num_busses; i++) { - val |= i2c_bus_busy(i2c->busses[i]) << i; + val |= (uint64_t)i2c_bus_busy(i2c->busses[i]) << i; } break; @@ -462,6 +463,23 @@ static uint64_t pnv_i2c_xscom_read(void *opaque, hwaddr addr, return val; } +static void pnv_i2c_reset(void *dev) +{ + PnvI2C *i2c = PNV_I2C(dev); + + memset(i2c->regs, 0, sizeof(i2c->regs)); + + i2c->regs[I2C_STAT_REG] = + SETFIELD(I2C_STAT_UPPER_THRS, 0ull, i2c->num_busses - 1) | + I2C_STAT_CMD_COMP | I2C_STAT_SCL_INPUT_LEVEL | + I2C_STAT_SDA_INPUT_LEVEL; + i2c->regs[I2C_EXTD_STAT_REG] = + SETFIELD(I2C_EXTD_STAT_FIFO_SIZE, 0ull, PNV_I2C_FIFO_SIZE) | + SETFIELD(I2C_EXTD_STAT_I2C_VERSION, 0ull, 23); /* last version */ + + fifo8_reset(&i2c->fifo); +} + static void pnv_i2c_xscom_write(void *opaque, hwaddr addr, uint64_t val, unsigned size) { @@ -499,16 +517,7 @@ static void pnv_i2c_xscom_write(void *opaque, hwaddr addr, break; case I2C_RESET_I2C_REG: - i2c->regs[I2C_MODE_REG] = 0; - i2c->regs[I2C_CMD_REG] = 0; - i2c->regs[I2C_WATERMARK_REG] = 0; - i2c->regs[I2C_INTR_MASK_REG] = 0; - i2c->regs[I2C_INTR_COND_REG] = 0; - i2c->regs[I2C_INTR_RAW_COND_REG] = 0; - i2c->regs[I2C_STAT_REG] = 0; - i2c->regs[I2C_RESIDUAL_LEN_REG] = 0; - i2c->regs[I2C_EXTD_STAT_REG] &= - (I2C_EXTD_STAT_FIFO_SIZE | I2C_EXTD_STAT_I2C_VERSION); + pnv_i2c_reset(i2c); break; case I2C_RESET_ERRORS: @@ -593,7 +602,7 @@ static int pnv_i2c_dt_xscom(PnvXScomInterface *dev, void *fdt, int i2c_offset; const char i2c_compat[] = "ibm,power8-i2cm\0ibm,power9-i2cm"; uint32_t i2c_pcba = PNV9_XSCOM_I2CM_BASE + - i2c->engine * PNV9_XSCOM_I2CM_SIZE; + (i2c->engine - 1) * PNV9_XSCOM_I2CM_SIZE; uint32_t reg[2] = { cpu_to_be32(i2c_pcba), cpu_to_be32(PNV9_XSCOM_I2CM_SIZE) @@ -620,20 +629,6 @@ static int pnv_i2c_dt_xscom(PnvXScomInterface *dev, void *fdt, return 0; } -static void pnv_i2c_reset(void *dev) -{ - PnvI2C *i2c = PNV_I2C(dev); - - memset(i2c->regs, 0, sizeof(i2c->regs)); - - i2c->regs[I2C_STAT_REG] = I2C_STAT_CMD_COMP; - i2c->regs[I2C_EXTD_STAT_REG] = - SETFIELD(I2C_EXTD_STAT_FIFO_SIZE, 0ull, PNV_I2C_FIFO_SIZE) | - SETFIELD(I2C_EXTD_STAT_I2C_VERSION, 0ull, 23); /* last version */ - - fifo8_reset(&i2c->fifo); -} - static void pnv_i2c_realize(DeviceState *dev, Error **errp) { PnvI2C *i2c = PNV_I2C(dev); @@ -641,6 +636,11 @@ static void pnv_i2c_realize(DeviceState *dev, Error **errp) assert(i2c->chip); + if (i2c->num_busses > PNV_I2C_MAX_BUSSES) { + error_setg(errp, "Invalid number of busses: %u", i2c->num_busses); + return; + } + pnv_xscom_region_init(&i2c->xscom_regs, OBJECT(i2c), &pnv_i2c_xscom_ops, i2c, "xscom-i2c", PNV9_XSCOM_I2CM_SIZE); diff --git a/hw/ppc/spapr_pci.c b/hw/ppc/spapr_pci.c index a27024e45a..6760823e13 100644 --- a/hw/ppc/spapr_pci.c +++ b/hw/ppc/spapr_pci.c @@ -1555,7 +1555,7 @@ static void spapr_pci_pre_plug(HotplugHandler *plug_handler, */ if (plugged_dev->hotplugged) { error_setg(errp, QERR_BUS_NO_HOTPLUG, - object_get_typename(OBJECT(phb))); + phb->parent_obj.bus->qbus.name); return; } } @@ -1676,7 +1676,7 @@ static void spapr_pci_unplug_request(HotplugHandler *plug_handler, if (!phb->dr_enabled) { error_setg(errp, QERR_BUS_NO_HOTPLUG, - object_get_typename(OBJECT(phb))); + phb->parent_obj.bus->qbus.name); return; } diff --git a/hw/riscv/sifive_e.c b/hw/riscv/sifive_e.c index 0d37adc542..87d9602383 100644 --- a/hw/riscv/sifive_e.c +++ b/hw/riscv/sifive_e.c @@ -225,7 +225,7 @@ static void sifive_e_soc_realize(DeviceState *dev, Error **errp) RISCV_ACLINT_SWI_SIZE, RISCV_ACLINT_DEFAULT_MTIMER_SIZE, 0, ms->smp.cpus, RISCV_ACLINT_DEFAULT_MTIMECMP, RISCV_ACLINT_DEFAULT_MTIME, - RISCV_ACLINT_DEFAULT_TIMEBASE_FREQ, false); + SIFIVE_E_LFCLK_DEFAULT_FREQ, false); sifive_e_prci_create(memmap[SIFIVE_E_DEV_PRCI].base); /* AON */ diff --git a/hw/riscv/virt.c b/hw/riscv/virt.c index c7fc97e273..d2eac24156 100644 --- a/hw/riscv/virt.c +++ b/hw/riscv/virt.c @@ -962,7 +962,6 @@ static void create_fdt_uart(RISCVVirtState *s, const MemMapEntry *memmap, qemu_fdt_setprop_cells(ms->fdt, name, "interrupts", UART0_IRQ, 0x4); } - qemu_fdt_add_subnode(ms->fdt, "/chosen"); qemu_fdt_setprop_string(ms->fdt, "/chosen", "stdout-path", name); g_free(name); } @@ -1023,11 +1022,29 @@ static void create_fdt_fw_cfg(RISCVVirtState *s, const MemMapEntry *memmap) g_free(nodename); } +static void finalize_fdt(RISCVVirtState *s) +{ + uint32_t phandle = 1, irq_mmio_phandle = 1, msi_pcie_phandle = 1; + uint32_t irq_pcie_phandle = 1, irq_virtio_phandle = 1; + + create_fdt_sockets(s, virt_memmap, &phandle, &irq_mmio_phandle, + &irq_pcie_phandle, &irq_virtio_phandle, + &msi_pcie_phandle); + + create_fdt_virtio(s, virt_memmap, irq_virtio_phandle); + + create_fdt_pcie(s, virt_memmap, irq_pcie_phandle, msi_pcie_phandle); + + create_fdt_reset(s, virt_memmap, &phandle); + + create_fdt_uart(s, virt_memmap, irq_mmio_phandle); + + create_fdt_rtc(s, virt_memmap, irq_mmio_phandle); +} + static void create_fdt(RISCVVirtState *s, const MemMapEntry *memmap) { MachineState *ms = MACHINE(s); - uint32_t phandle = 1, irq_mmio_phandle = 1, msi_pcie_phandle = 1; - uint32_t irq_pcie_phandle = 1, irq_virtio_phandle = 1; uint8_t rng_seed[32]; ms->fdt = create_device_tree(&s->fdt_size); @@ -1047,28 +1064,16 @@ static void create_fdt(RISCVVirtState *s, const MemMapEntry *memmap) qemu_fdt_setprop_cell(ms->fdt, "/soc", "#size-cells", 0x2); qemu_fdt_setprop_cell(ms->fdt, "/soc", "#address-cells", 0x2); - create_fdt_sockets(s, memmap, &phandle, &irq_mmio_phandle, - &irq_pcie_phandle, &irq_virtio_phandle, - &msi_pcie_phandle); - - create_fdt_virtio(s, memmap, irq_virtio_phandle); - - create_fdt_pcie(s, memmap, irq_pcie_phandle, msi_pcie_phandle); - - create_fdt_reset(s, memmap, &phandle); - - create_fdt_uart(s, memmap, irq_mmio_phandle); - - create_fdt_rtc(s, memmap, irq_mmio_phandle); - - create_fdt_flash(s, memmap); - create_fdt_fw_cfg(s, memmap); - create_fdt_pmu(s); + qemu_fdt_add_subnode(ms->fdt, "/chosen"); /* Pass seed to RNG */ qemu_guest_getrandom_nofail(rng_seed, sizeof(rng_seed)); qemu_fdt_setprop(ms->fdt, "/chosen", "rng-seed", rng_seed, sizeof(rng_seed)); + + create_fdt_flash(s, memmap); + create_fdt_fw_cfg(s, memmap); + create_fdt_pmu(s); } static inline DeviceState *gpex_pcie_init(MemoryRegion *sys_mem, @@ -1257,15 +1262,12 @@ static void virt_machine_done(Notifier *notifier, void *data) uint64_t kernel_entry = 0; BlockBackend *pflash_blk0; - /* load/create device tree */ - if (machine->dtb) { - machine->fdt = load_device_tree(machine->dtb, &s->fdt_size); - if (!machine->fdt) { - error_report("load_device_tree() failed"); - exit(1); - } - } else { - create_fdt(s, memmap); + /* + * An user provided dtb must include everything, including + * dynamic sysbus devices. Our FDT needs to be finalized. + */ + if (machine->dtb == NULL) { + finalize_fdt(s); } /* @@ -1541,6 +1543,17 @@ static void virt_machine_init(MachineState *machine) } virt_flash_map(s, system_memory); + /* load/create device tree */ + if (machine->dtb) { + machine->fdt = load_device_tree(machine->dtb, &s->fdt_size); + if (!machine->fdt) { + error_report("load_device_tree() failed"); + exit(1); + } + } else { + create_fdt(s, memmap); + } + s->machine_done.notify = virt_machine_done; qemu_add_machine_init_done_notifier(&s->machine_done); } diff --git a/hw/s390x/s390-pci-bus.c b/hw/s390x/s390-pci-bus.c index 347580ebac..3e57d5faca 100644 --- a/hw/s390x/s390-pci-bus.c +++ b/hw/s390x/s390-pci-bus.c @@ -151,20 +151,12 @@ static void s390_pci_shutdown_notifier(Notifier *n, void *opaque) pci_device_reset(pbdev->pdev); } -static void s390_pci_reset_cb(void *opaque) -{ - S390PCIBusDevice *pbdev = opaque; - - pci_device_reset(pbdev->pdev); -} - static void s390_pci_perform_unplug(S390PCIBusDevice *pbdev) { HotplugHandler *hotplug_ctrl; if (pbdev->pft == ZPCI_PFT_ISM) { notifier_remove(&pbdev->shutdown_notifier); - qemu_unregister_reset(s390_pci_reset_cb, pbdev); } /* Unplug the PCI device */ @@ -1132,7 +1124,6 @@ static void s390_pcihost_plug(HotplugHandler *hotplug_dev, DeviceState *dev, if (pbdev->pft == ZPCI_PFT_ISM) { pbdev->shutdown_notifier.notify = s390_pci_shutdown_notifier; qemu_register_shutdown_notifier(&pbdev->shutdown_notifier); - qemu_register_reset(s390_pci_reset_cb, pbdev); } } else { pbdev->fh |= FH_SHM_EMUL; @@ -1279,6 +1270,23 @@ static void s390_pci_enumerate_bridge(PCIBus *bus, PCIDevice *pdev, pci_default_write_config(pdev, PCI_SUBORDINATE_BUS, s->bus_no, 1); } +void s390_pci_ism_reset(void) +{ + S390pciState *s = s390_get_phb(); + + S390PCIBusDevice *pbdev, *next; + + /* Trigger reset event for each passthrough ISM device currently in-use */ + QTAILQ_FOREACH_SAFE(pbdev, &s->zpci_devs, link, next) { + if (pbdev->interp && pbdev->pft == ZPCI_PFT_ISM && + pbdev->fh & FH_MASK_ENABLE) { + s390_pci_kvm_aif_disable(pbdev); + + pci_device_reset(pbdev->pdev); + } + } +} + static void s390_pcihost_reset(DeviceState *dev) { S390pciState *s = S390_PCI_HOST_BRIDGE(dev); diff --git a/hw/s390x/s390-pci-kvm.c b/hw/s390x/s390-pci-kvm.c index ff41e4106d..9eef4fc3ec 100644 --- a/hw/s390x/s390-pci-kvm.c +++ b/hw/s390x/s390-pci-kvm.c @@ -18,6 +18,7 @@ #include "hw/s390x/s390-pci-bus.h" #include "hw/s390x/s390-pci-kvm.h" #include "hw/s390x/s390-pci-inst.h" +#include "hw/s390x/s390-pci-vfio.h" #include "cpu_models.h" bool s390_pci_kvm_interp_allowed(void) @@ -27,6 +28,7 @@ bool s390_pci_kvm_interp_allowed(void) int s390_pci_kvm_aif_enable(S390PCIBusDevice *pbdev, ZpciFib *fib, bool assist) { + int rc; struct kvm_s390_zpci_op args = { .fh = pbdev->fh, .op = KVM_S390_ZPCIOP_REG_AEN, @@ -38,15 +40,43 @@ int s390_pci_kvm_aif_enable(S390PCIBusDevice *pbdev, ZpciFib *fib, bool assist) .u.reg_aen.flags = (assist) ? 0 : KVM_S390_ZPCIOP_REGAEN_HOST }; - return kvm_vm_ioctl(kvm_state, KVM_S390_ZPCI_OP, &args); + if (pbdev->aif) { + return -EINVAL; + } + + rc = kvm_vm_ioctl(kvm_state, KVM_S390_ZPCI_OP, &args); + if (rc == 0) { + pbdev->aif = true; + } + + return rc; } int s390_pci_kvm_aif_disable(S390PCIBusDevice *pbdev) { + int rc; + struct kvm_s390_zpci_op args = { .fh = pbdev->fh, .op = KVM_S390_ZPCIOP_DEREG_AEN }; - return kvm_vm_ioctl(kvm_state, KVM_S390_ZPCI_OP, &args); + if (!pbdev->aif) { + return -EINVAL; + } + + /* + * The device may have already been reset but we still want to relinquish + * the guest ISC, so always be sure to use an up-to-date host fh. + */ + if (!s390_pci_get_host_fh(pbdev, &args.fh)) { + return -EPERM; + } + + rc = kvm_vm_ioctl(kvm_state, KVM_S390_ZPCI_OP, &args); + if (rc == 0) { + pbdev->aif = false; + } + + return rc; } diff --git a/hw/s390x/s390-virtio-ccw.c b/hw/s390x/s390-virtio-ccw.c index 7262725d2e..2d6b86624f 100644 --- a/hw/s390x/s390-virtio-ccw.c +++ b/hw/s390x/s390-virtio-ccw.c @@ -118,6 +118,14 @@ static void subsystem_reset(void) DeviceState *dev; int i; + /* + * ISM firmware is sensitive to unexpected changes to the IOMMU, which can + * occur during reset of the vfio-pci device (unmap of entire aperture). + * Ensure any passthrough ISM devices are reset now, while CPUs are paused + * but before vfio-pci cleanup occurs. + */ + s390_pci_ism_reset(); + for (i = 0; i < ARRAY_SIZE(reset_dev_types); i++) { dev = DEVICE(object_resolve_path_type("", reset_dev_types[i], NULL)); if (dev) { diff --git a/hw/scsi/esp-pci.c b/hw/scsi/esp-pci.c index 4e890db0e2..51f0157934 100644 --- a/hw/scsi/esp-pci.c +++ b/hw/scsi/esp-pci.c @@ -77,6 +77,41 @@ struct PCIESPState { ESPState esp; }; +static void esp_pci_update_irq(PCIESPState *pci) +{ + int scsi_level = !!(pci->dma_regs[DMA_STAT] & DMA_STAT_SCSIINT); + int dma_level = (pci->dma_regs[DMA_CMD] & DMA_CMD_INTE_D) ? + !!(pci->dma_regs[DMA_STAT] & DMA_STAT_DONE) : 0; + int level = scsi_level || dma_level; + + pci_set_irq(PCI_DEVICE(pci), level); +} + +static void esp_irq_handler(void *opaque, int irq_num, int level) +{ + PCIESPState *pci = PCI_ESP(opaque); + + if (level) { + pci->dma_regs[DMA_STAT] |= DMA_STAT_SCSIINT; + + /* + * If raising the ESP IRQ to indicate end of DMA transfer, set + * DMA_STAT_DONE at the same time. In theory this should be done in + * esp_pci_dma_memory_rw(), however there is a delay between setting + * DMA_STAT_DONE and the ESP IRQ arriving which is visible to the + * guest that can cause confusion e.g. Linux + */ + if ((pci->dma_regs[DMA_CMD] & DMA_CMD_MASK) == 0x3 && + pci->dma_regs[DMA_WBC] == 0) { + pci->dma_regs[DMA_STAT] |= DMA_STAT_DONE; + } + } else { + pci->dma_regs[DMA_STAT] &= ~DMA_STAT_SCSIINT; + } + + esp_pci_update_irq(pci); +} + static void esp_pci_handle_idle(PCIESPState *pci, uint32_t val) { ESPState *s = &pci->esp; @@ -89,6 +124,7 @@ static void esp_pci_handle_blast(PCIESPState *pci, uint32_t val) { trace_esp_pci_dma_blast(val); qemu_log_mask(LOG_UNIMP, "am53c974: cmd BLAST not implemented\n"); + pci->dma_regs[DMA_STAT] |= DMA_STAT_BCMBLT; } static void esp_pci_handle_abort(PCIESPState *pci, uint32_t val) @@ -151,6 +187,7 @@ static void esp_pci_dma_write(PCIESPState *pci, uint32_t saddr, uint32_t val) /* clear some bits on write */ uint32_t mask = DMA_STAT_ERROR | DMA_STAT_ABORT | DMA_STAT_DONE; pci->dma_regs[DMA_STAT] &= ~(val & mask); + esp_pci_update_irq(pci); } break; default: @@ -161,17 +198,14 @@ static void esp_pci_dma_write(PCIESPState *pci, uint32_t saddr, uint32_t val) static uint32_t esp_pci_dma_read(PCIESPState *pci, uint32_t saddr) { - ESPState *s = &pci->esp; uint32_t val; val = pci->dma_regs[saddr]; if (saddr == DMA_STAT) { - if (s->rregs[ESP_RSTAT] & STAT_INT) { - val |= DMA_STAT_SCSIINT; - } if (!(pci->sbac & SBAC_STATUS)) { pci->dma_regs[DMA_STAT] &= ~(DMA_STAT_ERROR | DMA_STAT_ABORT | DMA_STAT_DONE); + esp_pci_update_irq(pci); } } @@ -275,7 +309,7 @@ static void esp_pci_dma_memory_rw(PCIESPState *pci, uint8_t *buf, int len, qemu_log_mask(LOG_UNIMP, "am53c974: MDL transfer not implemented\n"); } - addr = pci->dma_regs[DMA_SPA]; + addr = pci->dma_regs[DMA_WAC]; if (pci->dma_regs[DMA_WBC] < len) { len = pci->dma_regs[DMA_WBC]; } @@ -285,9 +319,6 @@ static void esp_pci_dma_memory_rw(PCIESPState *pci, uint8_t *buf, int len, /* update status registers */ pci->dma_regs[DMA_WBC] -= len; pci->dma_regs[DMA_WAC] += len; - if (pci->dma_regs[DMA_WBC] == 0) { - pci->dma_regs[DMA_STAT] |= DMA_STAT_DONE; - } } static void esp_pci_dma_memory_read(void *opaque, uint8_t *buf, int len) @@ -342,23 +373,13 @@ static const VMStateDescription vmstate_esp_pci_scsi = { } }; -static void esp_pci_command_complete(SCSIRequest *req, size_t resid) -{ - ESPState *s = req->hba_private; - PCIESPState *pci = container_of(s, PCIESPState, esp); - - esp_command_complete(req, resid); - pci->dma_regs[DMA_WBC] = 0; - pci->dma_regs[DMA_STAT] |= DMA_STAT_DONE; -} - static const struct SCSIBusInfo esp_pci_scsi_info = { .tcq = false, .max_target = ESP_MAX_DEVS, .max_lun = 7, .transfer_data = esp_transfer_data, - .complete = esp_pci_command_complete, + .complete = esp_command_complete, .cancel = esp_request_cancelled, }; @@ -386,7 +407,7 @@ static void esp_pci_scsi_realize(PCIDevice *dev, Error **errp) "esp-io", 0x80); pci_register_bar(dev, 0, PCI_BASE_ADDRESS_SPACE_IO, &pci->io); - s->irq = pci_allocate_irq(dev); + s->irq = qemu_allocate_irq(esp_irq_handler, pci, 0); scsi_bus_init(&s->bus, sizeof(s->bus), d, &esp_pci_scsi_info); } diff --git a/hw/scsi/vhost-user-scsi.c b/hw/scsi/vhost-user-scsi.c index 4486500cac..780f10559d 100644 --- a/hw/scsi/vhost-user-scsi.c +++ b/hw/scsi/vhost-user-scsi.c @@ -147,7 +147,6 @@ static int vhost_user_scsi_connect(DeviceState *dev, Error **errp) if (s->connected) { return 0; } - s->connected = true; vsc->dev.num_queues = vs->conf.num_queues; vsc->dev.nvqs = VIRTIO_SCSI_VQ_NUM_FIXED + vs->conf.num_queues; @@ -161,6 +160,8 @@ static int vhost_user_scsi_connect(DeviceState *dev, Error **errp) return ret; } + s->connected = true; + /* restore vhost state */ if (virtio_device_started(vdev, vdev->status)) { ret = vhost_user_scsi_start(s, errp); @@ -359,6 +360,20 @@ static Property vhost_user_scsi_properties[] = { DEFINE_PROP_END_OF_LIST(), }; +static void vhost_user_scsi_reset(VirtIODevice *vdev) +{ + VHostUserSCSI *s = VHOST_USER_SCSI(vdev); + VHostSCSICommon *vsc = VHOST_SCSI_COMMON(s); + + vhost_dev_free_inflight(vsc->inflight); +} + +static struct vhost_dev *vhost_user_scsi_get_vhost(VirtIODevice *vdev) +{ + VHostSCSICommon *vsc = VHOST_SCSI_COMMON(vdev); + return &vsc->dev; +} + static const VMStateDescription vmstate_vhost_scsi = { .name = "virtio-scsi", .minimum_version_id = 1, @@ -384,6 +399,8 @@ static void vhost_user_scsi_class_init(ObjectClass *klass, void *data) vdc->set_config = vhost_scsi_common_set_config; vdc->set_status = vhost_user_scsi_set_status; fwc->get_dev_path = vhost_scsi_common_get_fw_dev_path; + vdc->reset = vhost_user_scsi_reset; + vdc->get_vhost = vhost_user_scsi_get_vhost; } static void vhost_user_scsi_instance_init(Object *obj) diff --git a/hw/ssi/xilinx_spips.c b/hw/ssi/xilinx_spips.c index a3955c6c50..0bdfad7e2e 100644 --- a/hw/ssi/xilinx_spips.c +++ b/hw/ssi/xilinx_spips.c @@ -973,6 +973,8 @@ static void xilinx_spips_write(void *opaque, hwaddr addr, DB_PRINT_L(0, "addr=" HWADDR_FMT_plx " = %x\n", addr, (unsigned)value); addr >>= 2; + assert(addr < XLNX_SPIPS_R_MAX); + switch (addr) { case R_CONFIG: mask = ~(R_CONFIG_RSVD | MAN_START_COM); @@ -1299,7 +1301,7 @@ static void xilinx_spips_realize(DeviceState *dev, Error **errp) } memory_region_init_io(&s->iomem, OBJECT(s), xsc->reg_ops, s, - "spi", XLNX_ZYNQMP_SPIPS_R_MAX * 4); + "spi", xsc->reg_size); sysbus_init_mmio(sbd, &s->iomem); s->irqline = -1; @@ -1435,6 +1437,7 @@ static void xilinx_qspips_class_init(ObjectClass *klass, void * data) dc->realize = xilinx_qspips_realize; xsc->reg_ops = &qspips_ops; + xsc->reg_size = XLNX_SPIPS_R_MAX * 4; xsc->rx_fifo_size = RXFF_A_Q; xsc->tx_fifo_size = TXFF_A_Q; } @@ -1450,6 +1453,7 @@ static void xilinx_spips_class_init(ObjectClass *klass, void *data) dc->vmsd = &vmstate_xilinx_spips; xsc->reg_ops = &spips_ops; + xsc->reg_size = XLNX_SPIPS_R_MAX * 4; xsc->rx_fifo_size = RXFF_A; xsc->tx_fifo_size = TXFF_A; } @@ -1464,6 +1468,7 @@ static void xlnx_zynqmp_qspips_class_init(ObjectClass *klass, void * data) dc->vmsd = &vmstate_xlnx_zynqmp_qspips; device_class_set_props(dc, xilinx_zynqmp_qspips_properties); xsc->reg_ops = &xlnx_zynqmp_qspips_ops; + xsc->reg_size = XLNX_ZYNQMP_SPIPS_R_MAX * 4; xsc->rx_fifo_size = RXFF_A_Q; xsc->tx_fifo_size = TXFF_A_Q; } diff --git a/hw/ufs/ufs.c b/hw/ufs/ufs.c index 68c5f1f6c9..eccdb852a0 100644 --- a/hw/ufs/ufs.c +++ b/hw/ufs/ufs.c @@ -1323,9 +1323,17 @@ static bool ufs_bus_check_address(BusState *qbus, DeviceState *qdev, return true; } +static char *ufs_bus_get_dev_path(DeviceState *dev) +{ + BusState *bus = qdev_get_parent_bus(dev); + + return qdev_get_dev_path(bus->parent); +} + static void ufs_bus_class_init(ObjectClass *class, void *data) { BusClass *bc = BUS_CLASS(class); + bc->get_dev_path = ufs_bus_get_dev_path; bc->check_address = ufs_bus_check_address; } diff --git a/hw/usb/dev-network.c b/hw/usb/dev-network.c index 5fff487ee5..2c33e36cad 100644 --- a/hw/usb/dev-network.c +++ b/hw/usb/dev-network.c @@ -1386,7 +1386,8 @@ static void usb_net_realize(USBDevice *dev, Error **errp) qemu_macaddr_default_if_unset(&s->conf.macaddr); s->nic = qemu_new_nic(&net_usbnet_info, &s->conf, - object_get_typename(OBJECT(s)), s->dev.qdev.id, s); + object_get_typename(OBJECT(s)), s->dev.qdev.id, + &s->dev.qdev.mem_reentrancy_guard, s); qemu_format_nic_info_str(qemu_get_queue(s->nic), s->conf.macaddr.a); snprintf(s->usbstring_mac, sizeof(s->usbstring_mac), "%02x%02x%02x%02x%02x%02x", diff --git a/hw/usb/vt82c686-uhci-pci.c b/hw/usb/vt82c686-uhci-pci.c index b4884c9011..6162806172 100644 --- a/hw/usb/vt82c686-uhci-pci.c +++ b/hw/usb/vt82c686-uhci-pci.c @@ -1,7 +1,14 @@ #include "qemu/osdep.h" +#include "hw/irq.h" #include "hw/isa/vt82c686.h" #include "hcd-uhci.h" +static void uhci_isa_set_irq(void *opaque, int irq_num, int level) +{ + UHCIState *s = opaque; + via_isa_set_irq(&s->dev, 0, level); +} + static void usb_uhci_vt82c686b_realize(PCIDevice *dev, Error **errp) { UHCIState *s = UHCI(dev); @@ -15,6 +22,8 @@ static void usb_uhci_vt82c686b_realize(PCIDevice *dev, Error **errp) pci_set_long(pci_conf + 0xc0, 0x00002000); usb_uhci_common_realize(dev, errp); + object_unref(s->irq); + s->irq = qemu_allocate_irq(uhci_isa_set_irq, s, 0); } static UHCIInfo uhci_info[] = { diff --git a/hw/vfio/common.c b/hw/vfio/common.c index e70fdf5e0c..a5dfc2d27e 100644 --- a/hw/vfio/common.c +++ b/hw/vfio/common.c @@ -73,7 +73,7 @@ bool vfio_mig_active(void) return false; } - QLIST_FOREACH(vbasedev, &vfio_device_list, next) { + QLIST_FOREACH(vbasedev, &vfio_device_list, global_next) { if (vbasedev->migration_blocker) { return false; } @@ -94,7 +94,7 @@ static bool vfio_multiple_devices_migration_is_supported(void) unsigned int device_num = 0; bool all_support_p2p = true; - QLIST_FOREACH(vbasedev, &vfio_device_list, next) { + QLIST_FOREACH(vbasedev, &vfio_device_list, global_next) { if (vbasedev->migration) { device_num++; @@ -1352,13 +1352,13 @@ void vfio_reset_handler(void *opaque) { VFIODevice *vbasedev; - QLIST_FOREACH(vbasedev, &vfio_device_list, next) { + QLIST_FOREACH(vbasedev, &vfio_device_list, global_next) { if (vbasedev->dev->realized) { vbasedev->ops->vfio_compute_needs_reset(vbasedev); } } - QLIST_FOREACH(vbasedev, &vfio_device_list, next) { + QLIST_FOREACH(vbasedev, &vfio_device_list, global_next) { if (vbasedev->dev->realized && vbasedev->needs_reset) { vbasedev->ops->vfio_hot_reset_multi(vbasedev); } diff --git a/hw/vfio/container.c b/hw/vfio/container.c index 242010036a..adc3005beb 100644 --- a/hw/vfio/container.c +++ b/hw/vfio/container.c @@ -848,7 +848,8 @@ static void vfio_put_base_device(VFIODevice *vbasedev) static int vfio_device_groupid(VFIODevice *vbasedev, Error **errp) { - char *tmp, group_path[PATH_MAX], *group_name; + char *tmp, group_path[PATH_MAX]; + g_autofree char *group_name = NULL; int ret, groupid; ssize_t len; @@ -864,7 +865,7 @@ static int vfio_device_groupid(VFIODevice *vbasedev, Error **errp) group_path[len] = 0; - group_name = basename(group_path); + group_name = g_path_get_basename(group_path); if (sscanf(group_name, "%d", &groupid) != 1) { error_setg_errno(errp, errno, "failed to read %s", group_path); return -errno; diff --git a/hw/virtio/vhost-user-gpio.c b/hw/virtio/vhost-user-gpio.c index aff2d7eff6..a83437a5da 100644 --- a/hw/virtio/vhost-user-gpio.c +++ b/hw/virtio/vhost-user-gpio.c @@ -229,7 +229,6 @@ static int vu_gpio_connect(DeviceState *dev, Error **errp) if (gpio->connected) { return 0; } - gpio->connected = true; vhost_dev_set_config_notifier(vhost_dev, &gpio_ops); gpio->vhost_user.supports_config = true; @@ -243,6 +242,8 @@ static int vu_gpio_connect(DeviceState *dev, Error **errp) return ret; } + gpio->connected = true; + /* restore vhost state */ if (virtio_device_started(vdev, vdev->status)) { vu_gpio_start(vdev); diff --git a/hw/virtio/virtio-iommu-pci.c b/hw/virtio/virtio-iommu-pci.c index 9459fbf6ed..cbdfe4c591 100644 --- a/hw/virtio/virtio-iommu-pci.c +++ b/hw/virtio/virtio-iommu-pci.c @@ -95,10 +95,18 @@ static void virtio_iommu_pci_instance_init(Object *obj) TYPE_VIRTIO_IOMMU); } +static void virtio_iommu_pci_instance_finalize(Object *obj) +{ + VirtIOIOMMUPCI *dev = VIRTIO_IOMMU_PCI(obj); + + g_free(dev->vdev.prop_resv_regions); +} + static const VirtioPCIDeviceTypeInfo virtio_iommu_pci_info = { .generic_name = TYPE_VIRTIO_IOMMU_PCI, .instance_size = sizeof(VirtIOIOMMUPCI), .instance_init = virtio_iommu_pci_instance_init, + .instance_finalize = virtio_iommu_pci_instance_finalize, .class_init = virtio_iommu_pci_class_init, }; diff --git a/hw/virtio/virtio-iommu.c b/hw/virtio/virtio-iommu.c index 89fb5767d1..9d463efc52 100644 --- a/hw/virtio/virtio-iommu.c +++ b/hw/virtio/virtio-iommu.c @@ -698,9 +698,6 @@ static int virtio_iommu_probe(VirtIOIOMMU *s, } sdev = container_of(iommu_mr, IOMMUDevice, iommu_mr); - if (!sdev) { - return -EINVAL; - } count = virtio_iommu_fill_resv_mem_prop(sdev, ep_id, buf, free); if (count < 0) { diff --git a/hw/virtio/virtio-pci.c b/hw/virtio/virtio-pci.c index 205dbf24fb..e433879542 100644 --- a/hw/virtio/virtio-pci.c +++ b/hw/virtio/virtio-pci.c @@ -2391,6 +2391,7 @@ void virtio_pci_types_register(const VirtioPCIDeviceTypeInfo *t) .parent = t->parent ? t->parent : TYPE_VIRTIO_PCI, .instance_size = t->instance_size, .instance_init = t->instance_init, + .instance_finalize = t->instance_finalize, .class_size = t->class_size, .abstract = true, .interfaces = t->interfaces, diff --git a/hw/virtio/virtio.c b/hw/virtio/virtio.c index e5105571cf..3a160f86ed 100644 --- a/hw/virtio/virtio.c +++ b/hw/virtio/virtio.c @@ -2137,7 +2137,7 @@ void virtio_reset(void *opaque) vdev->device_endian = virtio_default_endian(); } - if (vdev->vhost_started) { + if (vdev->vhost_started && k->get_vhost) { vhost_reset_device(k->get_vhost(vdev)); } diff --git a/hw/watchdog/wdt_aspeed.c b/hw/watchdog/wdt_aspeed.c index d267aa185c..273a49d360 100644 --- a/hw/watchdog/wdt_aspeed.c +++ b/hw/watchdog/wdt_aspeed.c @@ -14,7 +14,6 @@ #include "qemu/module.h" #include "qemu/timer.h" #include "sysemu/watchdog.h" -#include "hw/misc/aspeed_scu.h" #include "hw/qdev-properties.h" #include "hw/sysbus.h" #include "hw/watchdog/wdt_aspeed.h" diff --git a/include/block/graph-lock.h b/include/block/graph-lock.h index 6f1cd12745..22b5db1ed9 100644 --- a/include/block/graph-lock.h +++ b/include/block/graph-lock.h @@ -123,8 +123,21 @@ bdrv_graph_wrlock(BlockDriverState *bs); * bdrv_graph_wrunlock: * Write finished, reset global has_writer to 0 and restart * all readers that are waiting. + * + * If @bs is non-NULL, its AioContext is temporarily released. */ -void bdrv_graph_wrunlock(void) TSA_RELEASE(graph_lock) TSA_NO_TSA; +void no_coroutine_fn TSA_RELEASE(graph_lock) TSA_NO_TSA +bdrv_graph_wrunlock(BlockDriverState *bs); + +/* + * bdrv_graph_wrunlock_ctx: + * Write finished, reset global has_writer to 0 and restart + * all readers that are waiting. + * + * If @ctx is non-NULL, its lock is temporarily released. + */ +void no_coroutine_fn TSA_RELEASE(graph_lock) TSA_NO_TSA +bdrv_graph_wrunlock_ctx(AioContext *ctx); /* * bdrv_graph_co_rdlock: diff --git a/include/block/ufs.h b/include/block/ufs.h index 0b6ec0814d..d61598b8f3 100644 --- a/include/block/ufs.h +++ b/include/block/ufs.h @@ -657,7 +657,7 @@ typedef struct QEMU_PACKED UtpTaskReqDesc { #define UFS_UPIU_MAX_WB_LUN_ID 8 /* - * WriteBooster buffer lifetime has a limit setted by vendor. + * WriteBooster buffer lifetime has a limit set by vendor. * If it is over the limit, WriteBooster feature will be disabled. */ #define UFS_WB_EXCEED_LIFETIME 0x0B diff --git a/include/hw/arm/stm32f100_soc.h b/include/hw/arm/stm32f100_soc.h index 40cd415b28..a74d7b369c 100644 --- a/include/hw/arm/stm32f100_soc.h +++ b/include/hw/arm/stm32f100_soc.h @@ -43,12 +43,8 @@ OBJECT_DECLARE_SIMPLE_TYPE(STM32F100State, STM32F100_SOC) #define SRAM_SIZE (8 * 1024) struct STM32F100State { - /*< private >*/ SysBusDevice parent_obj; - /*< public >*/ - char *cpu_type; - ARMv7MState armv7m; STM32F2XXUsartState usart[STM_NUM_USARTS]; diff --git a/include/hw/arm/stm32f205_soc.h b/include/hw/arm/stm32f205_soc.h index 5a4f776264..4f4c8bbebc 100644 --- a/include/hw/arm/stm32f205_soc.h +++ b/include/hw/arm/stm32f205_soc.h @@ -49,11 +49,7 @@ OBJECT_DECLARE_SIMPLE_TYPE(STM32F205State, STM32F205_SOC) #define SRAM_SIZE (128 * 1024) struct STM32F205State { - /*< private >*/ SysBusDevice parent_obj; - /*< public >*/ - - char *cpu_type; ARMv7MState armv7m; diff --git a/include/hw/arm/stm32f405_soc.h b/include/hw/arm/stm32f405_soc.h index c968ce3ab2..d15c03c4b5 100644 --- a/include/hw/arm/stm32f405_soc.h +++ b/include/hw/arm/stm32f405_soc.h @@ -51,11 +51,7 @@ OBJECT_DECLARE_SIMPLE_TYPE(STM32F405State, STM32F405_SOC) #define CCM_SIZE (64 * 1024) struct STM32F405State { - /*< private >*/ SysBusDevice parent_obj; - /*< public >*/ - - char *cpu_type; ARMv7MState armv7m; diff --git a/include/hw/boards.h b/include/hw/boards.h index a735999298..da85f86efb 100644 --- a/include/hw/boards.h +++ b/include/hw/boards.h @@ -273,7 +273,7 @@ struct MachineClass { bool has_hotpluggable_cpus; bool ignore_memory_transaction_failures; int numa_mem_align_shift; - const char **valid_cpu_types; + const char * const *valid_cpu_types; strList *allowed_dynamic_sysbus_devices; bool auto_enable_numa_with_memhp; bool auto_enable_numa_with_memdev; diff --git a/include/hw/cxl/cxl_device.h b/include/hw/cxl/cxl_device.h index 61b7f897f7..befb5f884b 100644 --- a/include/hw/cxl/cxl_device.h +++ b/include/hw/cxl/cxl_device.h @@ -403,7 +403,7 @@ struct CXLType3Dev { CXLComponentState cxl_cstate; CXLDeviceState cxl_dstate; CXLCCI cci; /* Primary PCI mailbox CCI */ - /* Always intialized as no way to know if a VDM might show up */ + /* Always initialized as no way to know if a VDM might show up */ CXLCCI vdm_fm_owned_ld_mctp_cci; CXLCCI ld0_cci; diff --git a/include/hw/elf_ops.h b/include/hw/elf_ops.h index 0a5c258fe6..9c35d1b9da 100644 --- a/include/hw/elf_ops.h +++ b/include/hw/elf_ops.h @@ -500,7 +500,7 @@ static ssize_t glue(load_elf, SZ)(const char *name, int fd, } if (data_swab) { - int j; + elf_word j; for (j = 0; j < file_size; j += (1 << data_swab)) { uint8_t *dp = data + j; switch (data_swab) { diff --git a/include/hw/hyperv/dynmem-proto.h b/include/hw/hyperv/dynmem-proto.h index d0f9090ac4..a657786a94 100644 --- a/include/hw/hyperv/dynmem-proto.h +++ b/include/hw/hyperv/dynmem-proto.h @@ -232,7 +232,7 @@ struct dm_capabilities_resp_msg { * num_committed: Committed memory in pages. * page_file_size: The accumulated size of all page files * in the system in pages. - * zero_free: The nunber of zero and free pages. + * zero_free: The number of zero and free pages. * page_file_writes: The writes to the page file in pages. * io_diff: An indicator of file cache efficiency or page file activity, * calculated as File Cache Page Fault Count - Page Read Count. @@ -275,7 +275,7 @@ struct dm_balloon { * * reservedz: Reserved; must be set to zero. * more_pages: If FALSE, this is the last message of the transaction. - * if TRUE there will atleast one more message from the guest. + * if TRUE there will be at least one more message from the guest. * * range_count: The number of ranges in the range array. * @@ -296,7 +296,7 @@ struct dm_balloon_response { * to the guest to give guest more memory. * * more_pages: If FALSE, this is the last message of the transaction. - * if TRUE there will atleast one more message from the guest. + * if TRUE there will be at least one more message from the guest. * * reservedz: Reserved; must be set to zero. * diff --git a/include/hw/ide/internal.h b/include/hw/ide/internal.h index 2bfa7533d6..3bdcc75597 100644 --- a/include/hw/ide/internal.h +++ b/include/hw/ide/internal.h @@ -354,6 +354,9 @@ enum ide_dma_cmd { extern const char *IDE_DMA_CMD_lookup[IDE_DMA__COUNT]; +extern const MemoryRegionPortio ide_portio_list[]; +extern const MemoryRegionPortio ide_portio2_list[]; + #define ide_cmd_is_read(s) \ ((s)->dma_cmd == IDE_DMA_READ) diff --git a/include/hw/ide/pci.h b/include/hw/ide/pci.h index 1ff469de87..a814a0a7c3 100644 --- a/include/hw/ide/pci.h +++ b/include/hw/ide/pci.h @@ -61,6 +61,7 @@ void bmdma_cmd_writeb(BMDMAState *bm, uint32_t val); void bmdma_status_writeb(BMDMAState *bm, uint32_t val); extern MemoryRegionOps bmdma_addr_ioport_ops; void pci_ide_create_devs(PCIDevice *dev); +void pci_ide_update_mode(PCIIDEState *s); extern const VMStateDescription vmstate_ide_pci; extern const MemoryRegionOps pci_ide_cmd_le_ops; diff --git a/include/hw/isa/vt82c686.h b/include/hw/isa/vt82c686.h index b6e95b2851..da1722daf2 100644 --- a/include/hw/isa/vt82c686.h +++ b/include/hw/isa/vt82c686.h @@ -34,4 +34,6 @@ struct ViaAC97State { uint32_t ac97_cmd; }; +void via_isa_set_irq(PCIDevice *d, int n, int level); + #endif diff --git a/include/hw/misc/xlnx-versal-cframe-reg.h b/include/hw/misc/xlnx-versal-cframe-reg.h index a14fbd7fe4..0091505246 100644 --- a/include/hw/misc/xlnx-versal-cframe-reg.h +++ b/include/hw/misc/xlnx-versal-cframe-reg.h @@ -12,7 +12,7 @@ * https://www.xilinx.com/support/documentation/architecture-manuals/am011-versal-acap-trm.pdf * * [2] Versal ACAP Register Reference, - * https://www.xilinx.com/htmldocs/registers/am012/am012-versal-register-reference.html + * https://docs.xilinx.com/r/en-US/am012-versal-register-reference/CFRAME_REG-Module */ #ifndef HW_MISC_XLNX_VERSAL_CFRAME_REG_H #define HW_MISC_XLNX_VERSAL_CFRAME_REG_H diff --git a/include/hw/misc/xlnx-versal-cfu.h b/include/hw/misc/xlnx-versal-cfu.h index 86fb841053..be62bab8c8 100644 --- a/include/hw/misc/xlnx-versal-cfu.h +++ b/include/hw/misc/xlnx-versal-cfu.h @@ -12,7 +12,7 @@ * https://www.xilinx.com/support/documentation/architecture-manuals/am011-versal-acap-trm.pdf * * [2] Versal ACAP Register Reference, - * https://www.xilinx.com/htmldocs/registers/am012/am012-versal-register-reference.html + * https://docs.xilinx.com/r/en-US/am012-versal-register-reference/CFU_CSR-Module */ #ifndef HW_MISC_XLNX_VERSAL_CFU_APB_H #define HW_MISC_XLNX_VERSAL_CFU_APB_H diff --git a/include/hw/misc/xlnx-versal-pmc-iou-slcr.h b/include/hw/misc/xlnx-versal-pmc-iou-slcr.h index f7d24c93c4..0c4a4fd66d 100644 --- a/include/hw/misc/xlnx-versal-pmc-iou-slcr.h +++ b/include/hw/misc/xlnx-versal-pmc-iou-slcr.h @@ -34,7 +34,7 @@ * https://www.xilinx.com/support/documentation/architecture-manuals/am011-versal-acap-trm.pdf * * [2] Versal ACAP Register Reference, - * https://www.xilinx.com/html_docs/registers/am012/am012-versal-register-reference.html#mod___pmc_iop_slcr.html + * https://docs.xilinx.com/r/en-US/am012-versal-register-reference/PMC_IOP_SLCR-Module * * QEMU interface: * + sysbus MMIO region 0: MemoryRegion for the device's registers diff --git a/include/hw/s390x/s390-pci-bus.h b/include/hw/s390x/s390-pci-bus.h index b1bdbeaeb5..2c43ea123f 100644 --- a/include/hw/s390x/s390-pci-bus.h +++ b/include/hw/s390x/s390-pci-bus.h @@ -361,6 +361,7 @@ struct S390PCIBusDevice { bool unplug_requested; bool interp; bool forwarding_assist; + bool aif; QTAILQ_ENTRY(S390PCIBusDevice) link; }; @@ -400,5 +401,6 @@ S390PCIBusDevice *s390_pci_find_dev_by_target(S390pciState *s, const char *target); S390PCIBusDevice *s390_pci_find_next_avail_dev(S390pciState *s, S390PCIBusDevice *pbdev); +void s390_pci_ism_reset(void); #endif diff --git a/include/hw/ssi/xilinx_spips.h b/include/hw/ssi/xilinx_spips.h index 1386d5ac8f..7a754bf67a 100644 --- a/include/hw/ssi/xilinx_spips.h +++ b/include/hw/ssi/xilinx_spips.h @@ -33,7 +33,9 @@ typedef struct XilinxSPIPS XilinxSPIPS; +/* For SPIPS, QSPIPS. */ #define XLNX_SPIPS_R_MAX (0x100 / 4) +/* For ZYNQMP_QSPIPS. */ #define XLNX_ZYNQMP_SPIPS_R_MAX (0x200 / 4) /* Bite off 4k chunks at a time */ @@ -125,6 +127,7 @@ struct XilinxSPIPSClass { SysBusDeviceClass parent_class; const MemoryRegionOps *reg_ops; + uint64_t reg_size; uint32_t rx_fifo_size; uint32_t tx_fifo_size; diff --git a/include/hw/ssi/xlnx-versal-ospi.h b/include/hw/ssi/xlnx-versal-ospi.h index 5d131d351d..4ac975aa2f 100644 --- a/include/hw/ssi/xlnx-versal-ospi.h +++ b/include/hw/ssi/xlnx-versal-ospi.h @@ -34,7 +34,7 @@ * https://www.xilinx.com/support/documentation/architecture-manuals/am011-versal-acap-trm.pdf * * [2] Versal ACAP Register Reference, - * https://www.xilinx.com/html_docs/registers/am012/am012-versal-register-reference.html#mod___ospi.html + * https://docs.xilinx.com/r/en-US/am012-versal-register-reference/OSPI-Module * * * QEMU interface: diff --git a/include/hw/virtio/vhost.h b/include/hw/virtio/vhost.h index 05d7204a08..02477788df 100644 --- a/include/hw/virtio/vhost.h +++ b/include/hw/virtio/vhost.h @@ -456,7 +456,7 @@ int vhost_save_backend_state(struct vhost_dev *dev, QEMUFile *f, Error **errp); * Must only be called while the device and all its vrings are stopped * (`VHOST_TRANSFER_STATE_PHASE_STOPPED`). * - * @dev: The vhost device to which to send the sate + * @dev: The vhost device to which to send the state * @f: Migration stream from which to load the state * @errp: Potential error message * diff --git a/include/hw/virtio/virtio-pci.h b/include/hw/virtio/virtio-pci.h index 5a3f182f99..59d88018c1 100644 --- a/include/hw/virtio/virtio-pci.h +++ b/include/hw/virtio/virtio-pci.h @@ -246,6 +246,7 @@ typedef struct VirtioPCIDeviceTypeInfo { size_t instance_size; size_t class_size; void (*instance_init)(Object *obj); + void (*instance_finalize)(Object *obj); void (*class_init)(ObjectClass *klass, void *data); InterfaceInfo *interfaces; } VirtioPCIDeviceTypeInfo; diff --git a/include/hw/xen/xen_native.h b/include/hw/xen/xen_native.h index 6f09c48823..1a5ad693a4 100644 --- a/include/hw/xen/xen_native.h +++ b/include/hw/xen/xen_native.h @@ -532,7 +532,7 @@ static inline int xendevicemodel_set_irq_level(xendevicemodel_handle *dmod, } #endif -#if CONFIG_XEN_CTRL_INTERFACE_VERSION <= 41700 +#if CONFIG_XEN_CTRL_INTERFACE_VERSION < 41700 #define GUEST_VIRTIO_MMIO_BASE xen_mk_ullong(0x02000000) #define GUEST_VIRTIO_MMIO_SIZE xen_mk_ullong(0x00100000) #define GUEST_VIRTIO_MMIO_SPI_FIRST 33 diff --git a/include/net/net.h b/include/net/net.h index 2fb1c9181c..ffbd2c8d56 100644 --- a/include/net/net.h +++ b/include/net/net.h @@ -126,6 +126,7 @@ typedef QTAILQ_HEAD(NetClientStateList, NetClientState) NetClientStateList; typedef struct NICState { NetClientState *ncs; NICConf *conf; + MemReentrancyGuard *reentrancy_guard; void *opaque; bool peer_deleted; } NICState; @@ -159,6 +160,7 @@ NICState *qemu_new_nic(NetClientInfo *info, NICConf *conf, const char *model, const char *name, + MemReentrancyGuard *reentrancy_guard, void *opaque); void qemu_del_nic(NICState *nic); NetClientState *qemu_get_subqueue(NICState *nic, int queue_index); diff --git a/include/qemu/osdep.h b/include/qemu/osdep.h index 7a0912a1af..9f3c7b29f9 100644 --- a/include/qemu/osdep.h +++ b/include/qemu/osdep.h @@ -779,6 +779,16 @@ static inline int platform_does_not_support_system(const char *command) } #endif /* !HAVE_SYSTEM_FUNCTION */ +/** + * If the load average was unobtainable, -1 is returned + */ +#ifndef HAVE_GETLOADAVG_FUNCTION +static inline int getloadavg(double loadavg[], int nelem) +{ + return -1; +} +#endif /* !HAVE_GETLOADAVG_FUNCTION */ + #ifdef __cplusplus } #endif diff --git a/include/qemu/vhost-user-server.h b/include/qemu/vhost-user-server.h index 64ad701015..0417ec0533 100644 --- a/include/qemu/vhost-user-server.h +++ b/include/qemu/vhost-user-server.h @@ -45,6 +45,7 @@ typedef struct { /* Protected by ctx lock */ bool in_qio_channel_yield; bool wait_idle; + bool quiescing; VuDev vu_dev; QIOChannel *ioc; /* The I/O channel with the client */ QIOChannelSocket *sioc; /* The underlying data channel with the client */ diff --git a/include/ui/pixman-minimal.h b/include/ui/pixman-minimal.h index efcf570c9e..6dd7de1c7e 100644 --- a/include/ui/pixman-minimal.h +++ b/include/ui/pixman-minimal.h @@ -113,6 +113,45 @@ typedef struct pixman_color { uint16_t alpha; } pixman_color_t; +static inline uint32_t *create_bits(pixman_format_code_t format, + int width, + int height, + int *rowstride_bytes) +{ + int stride = 0; + size_t buf_size = 0; + int bpp = PIXMAN_FORMAT_BPP(format); + + /* + * Calculate the following while checking for overflow truncation: + * stride = ((width * bpp + 0x1f) >> 5) * sizeof(uint32_t); + */ + + if (unlikely(__builtin_mul_overflow(width, bpp, &stride))) { + return NULL; + } + + if (unlikely(__builtin_add_overflow(stride, 0x1f, &stride))) { + return NULL; + } + + stride >>= 5; + + stride *= sizeof(uint32_t); + + if (unlikely(__builtin_mul_overflow((size_t) height, + (size_t) stride, + &buf_size))) { + return NULL; + } + + if (rowstride_bytes) { + *rowstride_bytes = stride; + } + + return g_malloc0(buf_size); +} + static inline pixman_image_t *pixman_image_create_bits(pixman_format_code_t format, int width, int height, @@ -123,13 +162,18 @@ static inline pixman_image_t *pixman_image_create_bits(pixman_format_code_t form i->width = width; i->height = height; - i->stride = rowstride_bytes ?: width * DIV_ROUND_UP(PIXMAN_FORMAT_BPP(format), 8); i->format = format; if (bits) { i->data = bits; } else { - i->free_me = i->data = g_malloc0(rowstride_bytes * height); + i->free_me = i->data = + create_bits(format, width, height, &rowstride_bytes); + if (width && height) { + assert(i->data); + } } + i->stride = rowstride_bytes ? rowstride_bytes : + width * DIV_ROUND_UP(PIXMAN_FORMAT_BPP(format), 8); i->ref_count = 1; return i; diff --git a/include/ui/rect.h b/include/ui/rect.h index 94898f92d0..68f05d78a8 100644 --- a/include/ui/rect.h +++ b/include/ui/rect.h @@ -19,7 +19,7 @@ static inline void qemu_rect_init(QemuRect *rect, uint16_t width, uint16_t height) { rect->x = x; - rect->y = x; + rect->y = y; rect->width = width; rect->height = height; } diff --git a/linux-user/elfload.c b/linux-user/elfload.c index f50c6bf904..1121e5eaea 100644 --- a/linux-user/elfload.c +++ b/linux-user/elfload.c @@ -3308,7 +3308,7 @@ static void load_elf_image(const char *image_name, const ImageSource *src, for (i = 0; i < ehdr->e_phnum; ++i) { struct elf_phdr *eppnt = phdr + i; if (eppnt->p_type == PT_LOAD) { - abi_ulong a = eppnt->p_vaddr - eppnt->p_offset; + abi_ulong a = eppnt->p_vaddr & TARGET_PAGE_MASK; if (a < loaddr) { loaddr = a; } diff --git a/linux-user/ppc/vdso.S b/linux-user/ppc/vdso.S index 689010db13..2e79ea9808 100644 --- a/linux-user/ppc/vdso.S +++ b/linux-user/ppc/vdso.S @@ -227,7 +227,7 @@ endf __kernel_sigtramp_rt #ifndef _ARCH_PPC64 /* * The non-rt sigreturn has the same layout at a different offset. - * Move the CFA and leave all othe other descriptions the same. + * Move the CFA and leave all the other descriptions the same. */ .cfi_def_cfa 1, SIGNAL_FRAMESIZE + offsetof_sigframe_mcontext nop diff --git a/linux-user/riscv/vdso-32.so b/linux-user/riscv/vdso-32.so index 1ad1e5cbbb..c2ce2a4757 100755 Binary files a/linux-user/riscv/vdso-32.so and b/linux-user/riscv/vdso-32.so differ diff --git a/linux-user/riscv/vdso-64.so b/linux-user/riscv/vdso-64.so index 83992bebe6..ae49f5b043 100755 Binary files a/linux-user/riscv/vdso-64.so and b/linux-user/riscv/vdso-64.so differ diff --git a/linux-user/riscv/vdso.S b/linux-user/riscv/vdso.S index a86d8fc488..c37275233a 100644 --- a/linux-user/riscv/vdso.S +++ b/linux-user/riscv/vdso.S @@ -101,12 +101,12 @@ endf __vdso_flush_icache .cfi_startproc simple .cfi_signal_frame -#define sizeof_reg (__riscv_xlen / 4) +#define sizeof_reg (__riscv_xlen / 8) #define sizeof_freg 8 -#define B_GR (offsetof_uc_mcontext - sizeof_rt_sigframe) -#define B_FR (offsetof_uc_mcontext - sizeof_rt_sigframe + offsetof_freg0) +#define B_GR 0 +#define B_FR offsetof_freg0 - .cfi_def_cfa 2, sizeof_rt_sigframe + .cfi_def_cfa 2, offsetof_uc_mcontext /* Return address */ .cfi_return_column 64 diff --git a/linux-user/sh4/termbits.h b/linux-user/sh4/termbits.h index eeabd2d7a9..28e79f2c9a 100644 --- a/linux-user/sh4/termbits.h +++ b/linux-user/sh4/termbits.h @@ -39,86 +39,86 @@ struct target_termios { #define TARGET_VEOL2 16 /* c_iflag bits */ -#define TARGET_IGNBRK 0000001 -#define TARGET_BRKINT 0000002 -#define TARGET_IGNPAR 0000004 -#define TARGET_PARMRK 0000010 -#define TARGET_INPCK 0000020 -#define TARGET_ISTRIP 0000040 -#define TARGET_INLCR 0000100 -#define TARGET_IGNCR 0000200 -#define TARGET_ICRNL 0000400 -#define TARGET_IUCLC 0001000 -#define TARGET_IXON 0002000 -#define TARGET_IXANY 0004000 -#define TARGET_IXOFF 0010000 -#define TARGET_IMAXBEL 0020000 -#define TARGET_IUTF8 0040000 +#define TARGET_IGNBRK 0000001 +#define TARGET_BRKINT 0000002 +#define TARGET_IGNPAR 0000004 +#define TARGET_PARMRK 0000010 +#define TARGET_INPCK 0000020 +#define TARGET_ISTRIP 0000040 +#define TARGET_INLCR 0000100 +#define TARGET_IGNCR 0000200 +#define TARGET_ICRNL 0000400 +#define TARGET_IUCLC 0001000 +#define TARGET_IXON 0002000 +#define TARGET_IXANY 0004000 +#define TARGET_IXOFF 0010000 +#define TARGET_IMAXBEL 0020000 +#define TARGET_IUTF8 0040000 /* c_oflag bits */ -#define TARGET_OPOST 0000001 -#define TARGET_OLCUC 0000002 -#define TARGET_ONLCR 0000004 -#define TARGET_OCRNL 0000010 -#define TARGET_ONOCR 0000020 -#define TARGET_ONLRET 0000040 -#define TARGET_OFILL 0000100 -#define TARGET_OFDEL 0000200 -#define TARGET_NLDLY 0000400 -#define TARGET_NL0 0000000 -#define TARGET_NL1 0000400 -#define TARGET_CRDLY 0003000 -#define TARGET_CR0 0000000 -#define TARGET_CR1 0001000 -#define TARGET_CR2 0002000 -#define TARGET_CR3 0003000 -#define TARGET_TABDLY 0014000 -#define TARGET_TAB0 0000000 -#define TARGET_TAB1 0004000 -#define TARGET_TAB2 0010000 -#define TARGET_TAB3 0014000 -#define TARGET_XTABS 0014000 -#define TARGET_BSDLY 0020000 -#define TARGET_BS0 0000000 -#define TARGET_BS1 0020000 -#define TARGET_VTDLY 0040000 -#define TARGET_VT0 0000000 -#define TARGET_VT1 0040000 -#define TARGET_FFDLY 0100000 -#define TARGET_FF0 0000000 -#define TARGET_FF1 0100000 +#define TARGET_OPOST 0000001 +#define TARGET_OLCUC 0000002 +#define TARGET_ONLCR 0000004 +#define TARGET_OCRNL 0000010 +#define TARGET_ONOCR 0000020 +#define TARGET_ONLRET 0000040 +#define TARGET_OFILL 0000100 +#define TARGET_OFDEL 0000200 +#define TARGET_NLDLY 0000400 +#define TARGET_NL0 0000000 +#define TARGET_NL1 0000400 +#define TARGET_CRDLY 0003000 +#define TARGET_CR0 0000000 +#define TARGET_CR1 0001000 +#define TARGET_CR2 0002000 +#define TARGET_CR3 0003000 +#define TARGET_TABDLY 0014000 +#define TARGET_TAB0 0000000 +#define TARGET_TAB1 0004000 +#define TARGET_TAB2 0010000 +#define TARGET_TAB3 0014000 +#define TARGET_XTABS 0014000 +#define TARGET_BSDLY 0020000 +#define TARGET_BS0 0000000 +#define TARGET_BS1 0020000 +#define TARGET_VTDLY 0040000 +#define TARGET_VT0 0000000 +#define TARGET_VT1 0040000 +#define TARGET_FFDLY 0100000 +#define TARGET_FF0 0000000 +#define TARGET_FF1 0100000 /* c_cflag bit meaning */ -#define TARGET_CBAUD 0010017 -#define TARGET_B0 0000000 /* hang up */ -#define TARGET_B50 0000001 -#define TARGET_B75 0000002 -#define TARGET_B110 0000003 -#define TARGET_B134 0000004 -#define TARGET_B150 0000005 -#define TARGET_B200 0000006 -#define TARGET_B300 0000007 -#define TARGET_B600 0000010 -#define TARGET_B1200 0000011 -#define TARGET_B1800 0000012 -#define TARGET_B2400 0000013 -#define TARGET_B4800 0000014 -#define TARGET_B9600 0000015 -#define TARGET_B19200 0000016 -#define TARGET_B38400 0000017 +#define TARGET_CBAUD 0010017 +#define TARGET_B0 0000000 /* hang up */ +#define TARGET_B50 0000001 +#define TARGET_B75 0000002 +#define TARGET_B110 0000003 +#define TARGET_B134 0000004 +#define TARGET_B150 0000005 +#define TARGET_B200 0000006 +#define TARGET_B300 0000007 +#define TARGET_B600 0000010 +#define TARGET_B1200 0000011 +#define TARGET_B1800 0000012 +#define TARGET_B2400 0000013 +#define TARGET_B4800 0000014 +#define TARGET_B9600 0000015 +#define TARGET_B19200 0000016 +#define TARGET_B38400 0000017 #define TARGET_EXTA B19200 #define TARGET_EXTB B38400 -#define TARGET_CSIZE 0000060 -#define TARGET_CS5 0000000 -#define TARGET_CS6 0000020 -#define TARGET_CS7 0000040 -#define TARGET_CS8 0000060 -#define TARGET_CSTOPB 0000100 -#define TARGET_CREAD 0000200 -#define TARGET_PARENB 0000400 -#define TARGET_PARODD 0001000 -#define TARGET_HUPCL 0002000 -#define TARGET_CLOCAL 0004000 +#define TARGET_CSIZE 0000060 +#define TARGET_CS5 0000000 +#define TARGET_CS6 0000020 +#define TARGET_CS7 0000040 +#define TARGET_CS8 0000060 +#define TARGET_CSTOPB 0000100 +#define TARGET_CREAD 0000200 +#define TARGET_PARENB 0000400 +#define TARGET_PARODD 0001000 +#define TARGET_HUPCL 0002000 +#define TARGET_CLOCAL 0004000 #define TARGET_CBAUDEX 0010000 #define TARGET_B57600 0010001 #define TARGET_B115200 0010002 @@ -135,44 +135,44 @@ struct target_termios { #define TARGET_B3000000 0010015 #define TARGET_B3500000 0010016 #define TARGET_B4000000 0010017 -#define TARGET_CIBAUD 002003600000 /* input baud rate (not used) */ -#define TARGET_CMSPAR 010000000000 /* mark or space (stick) parity */ -#define TARGET_CRTSCTS 020000000000 /* flow control */ +#define TARGET_CIBAUD 002003600000 /* input baud rate (not used) */ +#define TARGET_CMSPAR 010000000000 /* mark or space (stick) parity */ +#define TARGET_CRTSCTS 020000000000 /* flow control */ /* c_lflag bits */ -#define TARGET_ISIG 0000001 -#define TARGET_ICANON 0000002 -#define TARGET_XCASE 0000004 -#define TARGET_ECHO 0000010 -#define TARGET_ECHOE 0000020 -#define TARGET_ECHOK 0000040 -#define TARGET_ECHONL 0000100 -#define TARGET_NOFLSH 0000200 -#define TARGET_TOSTOP 0000400 -#define TARGET_ECHOCTL 0001000 -#define TARGET_ECHOPRT 0002000 -#define TARGET_ECHOKE 0004000 -#define TARGET_FLUSHO 0010000 -#define TARGET_PENDIN 0040000 -#define TARGET_IEXTEN 0100000 +#define TARGET_ISIG 0000001 +#define TARGET_ICANON 0000002 +#define TARGET_XCASE 0000004 +#define TARGET_ECHO 0000010 +#define TARGET_ECHOE 0000020 +#define TARGET_ECHOK 0000040 +#define TARGET_ECHONL 0000100 +#define TARGET_NOFLSH 0000200 +#define TARGET_TOSTOP 0000400 +#define TARGET_ECHOCTL 0001000 +#define TARGET_ECHOPRT 0002000 +#define TARGET_ECHOKE 0004000 +#define TARGET_FLUSHO 0010000 +#define TARGET_PENDIN 0040000 +#define TARGET_IEXTEN 0100000 #define TARGET_EXTPROC 0200000 /* tcflow() and TCXONC use these */ -#define TARGET_TCOOFF 0 -#define TARGET_TCOON 1 -#define TARGET_TCIOFF 2 -#define TARGET_TCION 3 +#define TARGET_TCOOFF 0 +#define TARGET_TCOON 1 +#define TARGET_TCIOFF 2 +#define TARGET_TCION 3 /* tcflush() and TCFLSH use these */ -#define TARGET_TCIFLUSH 0 -#define TARGET_TCOFLUSH 1 -#define TARGET_TCIOFLUSH 2 +#define TARGET_TCIFLUSH 0 +#define TARGET_TCOFLUSH 1 +#define TARGET_TCIOFLUSH 2 /* tcsetattr uses these */ -#define TARGET_TCSANOW 0 -#define TARGET_TCSADRAIN 1 -#define TARGET_TARGET_TCSAFLUSH 2 +#define TARGET_TCSANOW 0 +#define TARGET_TCSADRAIN 1 +#define TARGET_TARGET_TCSAFLUSH 2 /* ioctl */ #define TARGET_FIOCLEX TARGET_IO('f', 1) diff --git a/linux-user/signal.c b/linux-user/signal.c index 450157731b..046f960d32 100644 --- a/linux-user/signal.c +++ b/linux-user/signal.c @@ -947,7 +947,7 @@ static void host_sigsegv_handler(CPUState *cpu, siginfo_t *info, cpu_loop_exit_sigsegv(cpu, guest_addr, access_type, maperr, pc); } -static void host_sigbus_handler(CPUState *cpu, siginfo_t *info, +static uintptr_t host_sigbus_handler(CPUState *cpu, siginfo_t *info, host_sigcontext *uc) { uintptr_t pc = host_signal_pc(uc); @@ -969,6 +969,7 @@ static void host_sigbus_handler(CPUState *cpu, siginfo_t *info, sigprocmask(SIG_SETMASK, host_signal_mask(uc), NULL); cpu_loop_exit_sigbus(cpu, guest_addr, access_type, pc); } + return pc; } //// --- Begin LibAFL code --- @@ -1027,7 +1028,7 @@ static void host_signal_handler(int host_sig, siginfo_t *info, void *puc) host_sigsegv_handler(cpu, info, uc); return; case SIGBUS: - host_sigbus_handler(cpu, info, uc); + pc = host_sigbus_handler(cpu, info, uc); sync_sig = true; break; case SIGILL: diff --git a/linux-user/syscall.c b/linux-user/syscall.c index c74c4adbd2..bc81470a90 100644 --- a/linux-user/syscall.c +++ b/linux-user/syscall.c @@ -848,7 +848,7 @@ abi_long do_brk(abi_ulong brk_val) return target_brk; } - /* Release heap if necesary */ + /* Release heap if necessary */ if (new_brk < old_brk) { target_munmap(new_brk, old_brk - new_brk); @@ -8852,6 +8852,8 @@ static int do_getdents64(abi_long dirfd, abi_long arg2, abi_long count) #define RISCV_HWPROBE_MISALIGNED_UNSUPPORTED (4 << 0) #define RISCV_HWPROBE_MISALIGNED_MASK (7 << 0) +#define RISCV_HWPROBE_KEY_ZICBOZ_BLOCK_SIZE 6 + struct riscv_hwprobe { abi_llong key; abi_ullong value; @@ -8904,6 +8906,10 @@ static void risc_hwprobe_fill_pairs(CPURISCVState *env, case RISCV_HWPROBE_KEY_CPUPERF_0: __put_user(RISCV_HWPROBE_MISALIGNED_FAST, &pair->value); break; + case RISCV_HWPROBE_KEY_ZICBOZ_BLOCK_SIZE: + value = cfg->ext_zicboz ? cfg->cboz_blocksize : 0; + __put_user(value, &pair->value); + break; default: __put_user(-1, &pair->key); break; diff --git a/linux-user/xtensa/signal.c b/linux-user/xtensa/signal.c index f5fb8b5cbe..32dcfa5229 100644 --- a/linux-user/xtensa/signal.c +++ b/linux-user/xtensa/signal.c @@ -157,6 +157,9 @@ void setup_rt_frame(int sig, struct target_sigaction *ka, { abi_ulong frame_addr; struct target_rt_sigframe *frame; + int is_fdpic = info_is_fdpic(((TaskState *)thread_cpu->opaque)->info); + abi_ulong handler = 0; + abi_ulong handler_fdpic_GOT = 0; uint32_t ra; bool abi_call0; unsigned base; @@ -165,6 +168,17 @@ void setup_rt_frame(int sig, struct target_sigaction *ka, frame_addr = get_sigframe(ka, env, sizeof(*frame)); trace_user_setup_rt_frame(env, frame_addr); + if (is_fdpic) { + abi_ulong funcdesc_ptr = ka->_sa_handler; + + if (get_user_ual(handler, funcdesc_ptr) + || get_user_ual(handler_fdpic_GOT, funcdesc_ptr + 4)) { + goto give_sigsegv; + } + } else { + handler = ka->_sa_handler; + } + if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) { goto give_sigsegv; } @@ -185,14 +199,21 @@ void setup_rt_frame(int sig, struct target_sigaction *ka, } if (ka->sa_flags & TARGET_SA_RESTORER) { - ra = ka->sa_restorer; + if (is_fdpic) { + if (get_user_ual(ra, ka->sa_restorer)) { + unlock_user_struct(frame, frame_addr, 0); + goto give_sigsegv; + } + } else { + ra = ka->sa_restorer; + } } else { /* Not used, but retain for ABI compatibility. */ install_sigtramp(frame->retcode); ra = default_rt_sigreturn; } memset(env->regs, 0, sizeof(env->regs)); - env->pc = ka->_sa_handler; + env->pc = handler; env->regs[1] = frame_addr; env->sregs[WINDOW_BASE] = 0; env->sregs[WINDOW_START] = 1; @@ -212,6 +233,9 @@ void setup_rt_frame(int sig, struct target_sigaction *ka, env->regs[base + 3] = frame_addr + offsetof(struct target_rt_sigframe, info); env->regs[base + 4] = frame_addr + offsetof(struct target_rt_sigframe, uc); + if (is_fdpic) { + env->regs[base + 11] = handler_fdpic_GOT; + } unlock_user_struct(frame, frame_addr, 1); return; diff --git a/meson.build b/meson.build index 0a068ead86..8c53950d83 100644 --- a/meson.build +++ b/meson.build @@ -123,21 +123,24 @@ if get_option('kvm').allowed() and targetos == 'linux' kvm_targets_c = '"' + '" ,"'.join(kvm_targets) + '"' endif config_host_data.set('CONFIG_KVM_TARGETS', kvm_targets_c) - accelerator_targets = { 'CONFIG_KVM': kvm_targets } +if cpu in ['x86', 'x86_64'] + xen_targets = ['i386-softmmu', 'x86_64-softmmu'] +elif cpu in ['arm', 'aarch64'] + # i386 emulator provides xenpv machine type for multiple architectures + xen_targets = ['i386-softmmu', 'x86_64-softmmu', 'aarch64-softmmu'] +else + xen_targets = [] +endif +accelerator_targets += { 'CONFIG_XEN': xen_targets } + if cpu in ['aarch64'] accelerator_targets += { 'CONFIG_HVF': ['aarch64-softmmu'] } endif -if cpu in ['x86', 'x86_64', 'arm', 'aarch64'] - # i386 emulator provides xenpv machine type for multiple architectures - accelerator_targets += { - 'CONFIG_XEN': ['i386-softmmu', 'x86_64-softmmu', 'aarch64-softmmu'], - } -endif if cpu in ['x86', 'x86_64'] accelerator_targets += { 'CONFIG_HVF': ['x86_64-softmmu'], @@ -2293,6 +2296,7 @@ config_host_data.set('HAVE_GLIB_WITH_SLICE_ALLOCATOR', glib_has_gslice) config_host_data.set('HAVE_OPENPTY', cc.has_function('openpty', dependencies: util)) config_host_data.set('HAVE_STRCHRNUL', cc.has_function('strchrnul')) config_host_data.set('HAVE_SYSTEM_FUNCTION', cc.has_function('system', prefix: '#include ')) +config_host_data.set('HAVE_GETLOADAVG_FUNCTION', cc.has_function('getloadavg', prefix: '#include ')) if rbd.found() config_host_data.set('HAVE_RBD_NAMESPACE_EXISTS', cc.has_function('rbd_namespace_exists', diff --git a/migration/migration.c b/migration/migration.c index 28a34c9068..3ce04b2aaf 100644 --- a/migration/migration.c +++ b/migration/migration.c @@ -462,7 +462,6 @@ bool migrate_uri_parse(const char *uri, MigrationChannel **channel, { g_autoptr(MigrationChannel) val = g_new0(MigrationChannel, 1); g_autoptr(MigrationAddress) addr = g_new0(MigrationAddress, 1); - SocketAddress *saddr = NULL; InetSocketAddress *isock = &addr->u.rdma; strList **tail = &addr->u.exec.args; @@ -487,12 +486,14 @@ bool migrate_uri_parse(const char *uri, MigrationChannel **channel, strstart(uri, "vsock:", NULL) || strstart(uri, "fd:", NULL)) { addr->transport = MIGRATION_ADDRESS_TYPE_SOCKET; - saddr = socket_parse(uri, errp); + SocketAddress *saddr = socket_parse(uri, errp); if (!saddr) { return false; } addr->u.socket.type = saddr->type; addr->u.socket.u = saddr->u; + /* Don't free the objects inside; their ownership moved to "addr" */ + g_free(saddr); } else if (strstart(uri, "file:", NULL)) { addr->transport = MIGRATION_ADDRESS_TYPE_FILE; addr->u.file.filename = g_strdup(uri + strlen("file:")); @@ -515,7 +516,7 @@ static void qemu_start_incoming_migration(const char *uri, bool has_channels, MigrationChannelList *channels, Error **errp) { - MigrationChannel *channel = NULL; + g_autoptr(MigrationChannel) channel = NULL; MigrationAddress *addr = NULL; MigrationIncomingState *mis = migration_incoming_get_current(); @@ -533,18 +534,18 @@ static void qemu_start_incoming_migration(const char *uri, bool has_channels, error_setg(errp, "Channel list has more than one entries"); return; } - channel = channels->value; + addr = channels->value->addr; } else if (uri) { /* caller uses the old URI syntax */ if (!migrate_uri_parse(uri, &channel, errp)) { return; } + addr = channel->addr; } else { error_setg(errp, "neither 'uri' or 'channels' argument are " "specified in 'migrate-incoming' qmp command "); return; } - addr = channel->addr; /* transport mechanism not suitable for migration? */ if (!migration_channels_and_transport_compatible(addr, errp)) { @@ -1932,7 +1933,7 @@ void qmp_migrate(const char *uri, bool has_channels, bool resume_requested; Error *local_err = NULL; MigrationState *s = migrate_get_current(); - MigrationChannel *channel = NULL; + g_autoptr(MigrationChannel) channel = NULL; MigrationAddress *addr = NULL; /* @@ -1949,18 +1950,18 @@ void qmp_migrate(const char *uri, bool has_channels, error_setg(errp, "Channel list has more than one entries"); return; } - channel = channels->value; + addr = channels->value->addr; } else if (uri) { /* caller uses the old URI syntax */ if (!migrate_uri_parse(uri, &channel, errp)) { return; } + addr = channel->addr; } else { error_setg(errp, "neither 'uri' or 'channels' argument are " "specified in 'migrate' qmp command "); return; } - addr = channel->addr; /* transport mechanism not suitable for migration? */ if (!migration_channels_and_transport_compatible(addr, errp)) { diff --git a/migration/multifd.c b/migration/multifd.c index ec58c58082..409460684f 100644 --- a/migration/multifd.c +++ b/migration/multifd.c @@ -883,8 +883,7 @@ static void multifd_new_send_channel_async(QIOTask *task, gpointer opaque) trace_multifd_new_send_channel_async(p->id); if (!qio_task_propagate_error(task, &local_err)) { - p->c = ioc; - qio_channel_set_delay(p->c, false); + qio_channel_set_delay(ioc, false); p->running = true; if (multifd_channel_connect(p, ioc, &local_err)) { return; diff --git a/migration/rdma.c b/migration/rdma.c index 6a29e53daf..4141c0bd25 100644 --- a/migration/rdma.c +++ b/migration/rdma.c @@ -238,6 +238,7 @@ static const char *control_desc(unsigned int rdma_control) return strs[rdma_control]; } +#if !defined(htonll) static uint64_t htonll(uint64_t v) { union { uint32_t lv[2]; uint64_t llv; } u; @@ -245,13 +246,16 @@ static uint64_t htonll(uint64_t v) u.lv[1] = htonl(v & 0xFFFFFFFFULL); return u.llv; } +#endif +#if !defined(ntohll) static uint64_t ntohll(uint64_t v) { union { uint32_t lv[2]; uint64_t llv; } u; u.llv = v; return ((uint64_t)ntohl(u.lv[0]) << 32) | (uint64_t) ntohl(u.lv[1]); } +#endif static void dest_block_to_network(RDMADestBlock *db) { @@ -2204,7 +2208,7 @@ retry: stat64_add(&mig_stats.normal_pages, sge.length / qemu_target_page_size()); /* * We are adding to transferred the amount of data written, but no - * overhead at all. I will asume that RDMA is magicaly and don't + * overhead at all. I will assume that RDMA is magicaly and don't * need to transfer (at least) the addresses where it wants to * write the pages. Here it looks like it should be something * like: diff --git a/monitor/hmp-cmds.c b/monitor/hmp-cmds.c index 6c559b48c8..871898ac46 100644 --- a/monitor/hmp-cmds.c +++ b/monitor/hmp-cmds.c @@ -24,7 +24,6 @@ #include "qapi/qapi-commands-control.h" #include "qapi/qapi-commands-misc.h" #include "qapi/qmp/qdict.h" -#include "qapi/qmp/qerror.h" #include "qemu/cutils.h" #include "hw/intc/intc.h" #include "qemu/log.h" @@ -138,7 +137,8 @@ void hmp_sync_profile(Monitor *mon, const QDict *qdict) } else { Error *err = NULL; - error_setg(&err, QERR_INVALID_PARAMETER, op); + error_setg(&err, "invalid parameter '%s'," + " expecting 'on', 'off', or 'reset'", op); hmp_handle_error(mon, err); } } diff --git a/monitor/qmp.c b/monitor/qmp.c index 6eee450fe4..a239945e8d 100644 --- a/monitor/qmp.c +++ b/monitor/qmp.c @@ -321,14 +321,6 @@ void coroutine_fn monitor_qmp_dispatcher_co(void *data) qemu_coroutine_yield(); } - /* - * Move the coroutine from iohandler_ctx to qemu_aio_context for - * executing the command handler so that it can make progress if it - * involves an AIO_WAIT_WHILE(). - */ - aio_co_schedule(qemu_get_aio_context(), qmp_dispatcher_co); - qemu_coroutine_yield(); - /* Process request */ if (req_obj->req) { if (trace_event_get_state(TRACE_MONITOR_QMP_CMD_IN_BAND)) { @@ -355,15 +347,6 @@ void coroutine_fn monitor_qmp_dispatcher_co(void *data) } qmp_request_free(req_obj); - - /* - * Yield and reschedule so the main loop stays responsive. - * - * Move back to iohandler_ctx so that nested event loops for - * qemu_aio_context don't start new monitor commands. - */ - aio_co_schedule(iohandler_get_aio_context(), qmp_dispatcher_co); - qemu_coroutine_yield(); } qatomic_set(&qmp_dispatcher_co, NULL); } diff --git a/net/net.c b/net/net.c index c0c0cbe99e..0520bc1681 100644 --- a/net/net.c +++ b/net/net.c @@ -319,6 +319,7 @@ NICState *qemu_new_nic(NetClientInfo *info, NICConf *conf, const char *model, const char *name, + MemReentrancyGuard *reentrancy_guard, void *opaque) { NetClientState **peers = conf->peers.ncs; @@ -331,6 +332,7 @@ NICState *qemu_new_nic(NetClientInfo *info, nic = g_malloc0(info->size + sizeof(NetClientState) * queues); nic->ncs = (void *)nic + info->size; nic->conf = conf; + nic->reentrancy_guard = reentrancy_guard, nic->opaque = opaque; for (i = 0; i < queues; i++) { @@ -813,6 +815,7 @@ static ssize_t qemu_deliver_packet_iov(NetClientState *sender, int iovcnt, void *opaque) { + MemReentrancyGuard *owned_reentrancy_guard; NetClientState *nc = opaque; int ret; @@ -825,12 +828,24 @@ static ssize_t qemu_deliver_packet_iov(NetClientState *sender, return 0; } + if (nc->info->type != NET_CLIENT_DRIVER_NIC || + qemu_get_nic(nc)->reentrancy_guard->engaged_in_io) { + owned_reentrancy_guard = NULL; + } else { + owned_reentrancy_guard = qemu_get_nic(nc)->reentrancy_guard; + owned_reentrancy_guard->engaged_in_io = true; + } + if (nc->info->receive_iov && !(flags & QEMU_NET_PACKET_FLAG_RAW)) { ret = nc->info->receive_iov(nc, iov, iovcnt); } else { ret = nc_sendv_compat(nc, iov, iovcnt, flags); } + if (owned_reentrancy_guard) { + owned_reentrancy_guard->engaged_in_io = false; + } + if (ret == 0) { nc->receive_disabled = 1; } @@ -1227,7 +1242,7 @@ static int net_client_init(QemuOpts *opts, bool is_netdev, Error **errp) int ret = -1; Visitor *v = opts_visitor_new(opts); - /* Parse convenience option format ip6-net=fec0::0[/64] */ + /* Parse convenience option format ipv6-net=fec0::0[/64] */ const char *ip6_net = qemu_opt_get(opts, "ipv6-net"); if (ip6_net) { @@ -1247,8 +1262,8 @@ static int net_client_init(QemuOpts *opts, bool is_netdev, Error **errp) if (substrings[1] && qemu_strtoul(substrings[1], NULL, 10, &prefix_len)) { - error_setg(errp, QERR_INVALID_PARAMETER_VALUE, - "ipv6-prefixlen", "a number"); + error_setg(errp, + "parameter 'ipv6-net' expects a number after '/'"); goto out; } @@ -1499,18 +1514,34 @@ static void net_vm_change_state_handler(void *opaque, bool running, void net_cleanup(void) { - NetClientState *nc; + NetClientState *nc, **p = &QTAILQ_FIRST(&net_clients); /*cleanup colo compare module for COLO*/ colo_compare_cleanup(); - /* We may del multiple entries during qemu_del_net_client(), - * so QTAILQ_FOREACH_SAFE() is also not safe here. + /* + * Walk the net_clients list and remove the netdevs but *not* any + * NET_CLIENT_DRIVER_NIC entries. The latter are owned by the device + * model which created them, and in some cases (e.g. xen-net-device) + * the device itself may do cleanup at exit and will be upset if we + * just delete its NIC from underneath it. + * + * Since qemu_del_net_client() may delete multiple entries, using + * QTAILQ_FOREACH_SAFE() is not safe here. The only safe pointer + * to keep as a bookmark is a NET_CLIENT_DRIVER_NIC entry, so keep + * 'p' pointing to either the head of the list, or the 'next' field + * of the latest NET_CLIENT_DRIVER_NIC, and operate on *p as we walk + * the list. + * + * The 'nc' variable isn't part of the list traversal; it's purely + * for convenience as too much '(*p)->' has a tendency to make the + * readers' eyes bleed. */ - while (!QTAILQ_EMPTY(&net_clients)) { - nc = QTAILQ_FIRST(&net_clients); + while (*p) { + nc = *p; if (nc->info->type == NET_CLIENT_DRIVER_NIC) { - qemu_del_nic(qemu_get_nic(nc)); + /* Skip NET_CLIENT_DRIVER_NIC entries */ + p = &QTAILQ_NEXT(nc, next); } else { qemu_del_net_client(nc); } diff --git a/pc-bios/README b/pc-bios/README index c555dd324e..4189bb28cc 100644 --- a/pc-bios/README +++ b/pc-bios/README @@ -14,7 +14,7 @@ - SLOF (Slimline Open Firmware) is a free IEEE 1275 Open Firmware implementation for certain IBM POWER hardware. The sources are at https://github.com/aik/SLOF, and the image currently in qemu is - built from git tag qemu-slof-20220719. + built from git tag qemu-slof-20230918. - VOF (Virtual Open Firmware) is a minimalistic firmware to work with -machine pseries,x-vof=on. When enabled, the firmware acts as a slim shim and diff --git a/pc-bios/bios-256k.bin b/pc-bios/bios-256k.bin index 8d1dc0dff3..48c3707d55 100644 Binary files a/pc-bios/bios-256k.bin and b/pc-bios/bios-256k.bin differ diff --git a/pc-bios/bios-microvm.bin b/pc-bios/bios-microvm.bin index 1a96d55862..c98351e734 100644 Binary files a/pc-bios/bios-microvm.bin and b/pc-bios/bios-microvm.bin differ diff --git a/pc-bios/bios.bin b/pc-bios/bios.bin index a4e7fef336..7e2d062af6 100644 Binary files a/pc-bios/bios.bin and b/pc-bios/bios.bin differ diff --git a/pc-bios/edk2-aarch64-code.fd.bz2 b/pc-bios/edk2-aarch64-code.fd.bz2 index 985e69a66a..fdcf89022a 100644 Binary files a/pc-bios/edk2-aarch64-code.fd.bz2 and b/pc-bios/edk2-aarch64-code.fd.bz2 differ diff --git a/pc-bios/edk2-arm-code.fd.bz2 b/pc-bios/edk2-arm-code.fd.bz2 index ae797a8c8e..9d829f4f08 100644 Binary files a/pc-bios/edk2-arm-code.fd.bz2 and b/pc-bios/edk2-arm-code.fd.bz2 differ diff --git a/pc-bios/edk2-i386-code.fd.bz2 b/pc-bios/edk2-i386-code.fd.bz2 index e703c2f954..1a9d392574 100644 Binary files a/pc-bios/edk2-i386-code.fd.bz2 and b/pc-bios/edk2-i386-code.fd.bz2 differ diff --git a/pc-bios/edk2-i386-secure-code.fd.bz2 b/pc-bios/edk2-i386-secure-code.fd.bz2 index 7230d44615..fab0a77b30 100644 Binary files a/pc-bios/edk2-i386-secure-code.fd.bz2 and b/pc-bios/edk2-i386-secure-code.fd.bz2 differ diff --git a/pc-bios/edk2-riscv-code.fd.bz2 b/pc-bios/edk2-riscv-code.fd.bz2 index c1cc08561d..6394fbfff3 100644 Binary files a/pc-bios/edk2-riscv-code.fd.bz2 and b/pc-bios/edk2-riscv-code.fd.bz2 differ diff --git a/pc-bios/edk2-x86_64-code.fd.bz2 b/pc-bios/edk2-x86_64-code.fd.bz2 index 9b7767a3ac..0d325bd483 100644 Binary files a/pc-bios/edk2-x86_64-code.fd.bz2 and b/pc-bios/edk2-x86_64-code.fd.bz2 differ diff --git a/pc-bios/edk2-x86_64-microvm.fd.bz2 b/pc-bios/edk2-x86_64-microvm.fd.bz2 index 17460dd380..829429082b 100644 Binary files a/pc-bios/edk2-x86_64-microvm.fd.bz2 and b/pc-bios/edk2-x86_64-microvm.fd.bz2 differ diff --git a/pc-bios/edk2-x86_64-secure-code.fd.bz2 b/pc-bios/edk2-x86_64-secure-code.fd.bz2 index fd0efeacbf..c6b039819c 100644 Binary files a/pc-bios/edk2-x86_64-secure-code.fd.bz2 and b/pc-bios/edk2-x86_64-secure-code.fd.bz2 differ diff --git a/pc-bios/hppa-firmware.img b/pc-bios/hppa-firmware.img index 9a2d54f26b..1b3a841825 100644 Binary files a/pc-bios/hppa-firmware.img and b/pc-bios/hppa-firmware.img differ diff --git a/pc-bios/slof.bin b/pc-bios/slof.bin index ef9b81d628..27fed09f49 100644 Binary files a/pc-bios/slof.bin and b/pc-bios/slof.bin differ diff --git a/pc-bios/vgabios-ati.bin b/pc-bios/vgabios-ati.bin index 27b785e3f8..e10cd263b8 100644 Binary files a/pc-bios/vgabios-ati.bin and b/pc-bios/vgabios-ati.bin differ diff --git a/pc-bios/vgabios-bochs-display.bin b/pc-bios/vgabios-bochs-display.bin index 598a3db4f2..416036d986 100644 Binary files a/pc-bios/vgabios-bochs-display.bin and b/pc-bios/vgabios-bochs-display.bin differ diff --git a/pc-bios/vgabios-cirrus.bin b/pc-bios/vgabios-cirrus.bin index 2b0202928f..4ffaa43d6f 100644 Binary files a/pc-bios/vgabios-cirrus.bin and b/pc-bios/vgabios-cirrus.bin differ diff --git a/pc-bios/vgabios-qxl.bin b/pc-bios/vgabios-qxl.bin index ebd6abe498..1b7a3831ef 100644 Binary files a/pc-bios/vgabios-qxl.bin and b/pc-bios/vgabios-qxl.bin differ diff --git a/pc-bios/vgabios-ramfb.bin b/pc-bios/vgabios-ramfb.bin index ab2f20d87b..dba6cb8e32 100644 Binary files a/pc-bios/vgabios-ramfb.bin and b/pc-bios/vgabios-ramfb.bin differ diff --git a/pc-bios/vgabios-stdvga.bin b/pc-bios/vgabios-stdvga.bin index 84588dd25d..0d541c5530 100644 Binary files a/pc-bios/vgabios-stdvga.bin and b/pc-bios/vgabios-stdvga.bin differ diff --git a/pc-bios/vgabios-virtio.bin b/pc-bios/vgabios-virtio.bin index 41308e0caf..2ce3557624 100644 Binary files a/pc-bios/vgabios-virtio.bin and b/pc-bios/vgabios-virtio.bin differ diff --git a/pc-bios/vgabios-vmware.bin b/pc-bios/vgabios-vmware.bin index d382d0af94..b7cab15593 100644 Binary files a/pc-bios/vgabios-vmware.bin and b/pc-bios/vgabios-vmware.bin differ diff --git a/pc-bios/vgabios.bin b/pc-bios/vgabios.bin index 62799d0113..ee748f6599 100644 Binary files a/pc-bios/vgabios.bin and b/pc-bios/vgabios.bin differ diff --git a/plugins/meson.build b/plugins/meson.build index 40d24529c0..6b2d7a9292 100644 --- a/plugins/meson.build +++ b/plugins/meson.build @@ -28,7 +28,7 @@ if get_option('plugins') # then use dlltool to assemble a delaylib. win32_qemu_plugin_api_lib = configure_file( input: win32_plugin_def, - output: 'qemu_plugin_api.lib', + output: 'libqemu_plugin_api.a', command: [dlltool, '--input-def', '@INPUT@', '--output-delaylib', '@OUTPUT@', '--dllname', 'qemu.exe'] ) diff --git a/python/scripts/vendor.py b/python/scripts/vendor.py index 7627487117..1038b14ae0 100755 --- a/python/scripts/vendor.py +++ b/python/scripts/vendor.py @@ -41,8 +41,8 @@ def main() -> int: parser.parse_args() packages = { - "meson==0.63.3": - "d677b809c4895dcbaac9bf6c43703fcb3609a4b24c6057c78f828590049cf43a", + "meson==1.2.3": + "4533a43c34548edd1f63a276a42690fce15bde9409bcf20c4b8fa3d7e4d7cac1", "tomli==2.0.1": "939de3e7a6161af0c887ef91b7d41a53e7c5a1ca976325f429cb46ea9bc30ecc", diff --git a/python/wheels/meson-0.63.3-py3-none-any.whl b/python/wheels/meson-0.63.3-py3-none-any.whl deleted file mode 100644 index 8a191e3a20..0000000000 Binary files a/python/wheels/meson-0.63.3-py3-none-any.whl and /dev/null differ diff --git a/python/wheels/meson-1.2.3-py3-none-any.whl b/python/wheels/meson-1.2.3-py3-none-any.whl new file mode 100644 index 0000000000..a8b84e5f11 Binary files /dev/null and b/python/wheels/meson-1.2.3-py3-none-any.whl differ diff --git a/pythondeps.toml b/pythondeps.toml index 0a35ebcf9f..0e88415999 100644 --- a/pythondeps.toml +++ b/pythondeps.toml @@ -10,7 +10,8 @@ # - accepted: accepted versions when using a system package # - installed: fixed version to install in the virtual environment # if a system package is not found; if not specified, -# the minimum and maximum +# defaults to the same as "accepted" or, if also missing, +# to the newest version available on PyPI. # - canary: if specified, use this program name to present more # precise error diagnostics to the user. For example, # 'sphinx-build' can be used as a bellwether for the @@ -18,7 +19,7 @@ [meson] # The install key should match the version in python/wheels/ -meson = { accepted = ">=0.63.0", installed = "0.63.3", canary = "meson" } +meson = { accepted = ">=0.63.0", installed = "1.2.3", canary = "meson" } [docs] sphinx = { accepted = ">=1.6", installed = "5.3.0", canary = "sphinx-build" } diff --git a/qapi/migration.json b/qapi/migration.json index 975761eebd..eb2f883513 100644 --- a/qapi/migration.json +++ b/qapi/migration.json @@ -1658,7 +1658,7 @@ # # Migration stream channel parameters. # -# @channel-type: Channel type for transfering packet information. +# @channel-type: Channel type for transferring packet information. # # @addr: Migration endpoint configuration on destination interface. # diff --git a/qapi/pragma.json b/qapi/pragma.json index 7f810b0e97..0aa4eeddd3 100644 --- a/qapi/pragma.json +++ b/qapi/pragma.json @@ -3,8 +3,8 @@ { 'pragma': { 'doc-required': true } } -# Whitelists to permit QAPI rule violations; think twice before you -# add to them! +# Entries in these lists are allowed to violate the QAPI rules (for +# historical reasons); think twice before you add to them! { 'pragma': { # Command names containing '_' 'command-name-exceptions': [ diff --git a/qapi/qmp-dispatch.c b/qapi/qmp-dispatch.c index 555528b6bb..176b549473 100644 --- a/qapi/qmp-dispatch.c +++ b/qapi/qmp-dispatch.c @@ -206,9 +206,31 @@ QDict *coroutine_mixed_fn qmp_dispatch(const QmpCommandList *cmds, QObject *requ assert(!(oob && qemu_in_coroutine())); assert(monitor_cur() == NULL); if (!!(cmd->options & QCO_COROUTINE) == qemu_in_coroutine()) { + if (qemu_in_coroutine()) { + /* + * Move the coroutine from iohandler_ctx to qemu_aio_context for + * executing the command handler so that it can make progress if it + * involves an AIO_WAIT_WHILE(). + */ + aio_co_schedule(qemu_get_aio_context(), qemu_coroutine_self()); + qemu_coroutine_yield(); + } + monitor_set_cur(qemu_coroutine_self(), cur_mon); cmd->fn(args, &ret, &err); monitor_set_cur(qemu_coroutine_self(), NULL); + + if (qemu_in_coroutine()) { + /* + * Yield and reschedule so the main loop stays responsive. + * + * Move back to iohandler_ctx so that nested event loops for + * qemu_aio_context don't start new monitor commands. + */ + aio_co_schedule(iohandler_get_aio_context(), + qemu_coroutine_self()); + qemu_coroutine_yield(); + } } else { /* * Actual context doesn't match the one the command needs. @@ -232,7 +254,7 @@ QDict *coroutine_mixed_fn qmp_dispatch(const QmpCommandList *cmds, QObject *requ .errp = &err, .co = qemu_coroutine_self(), }; - aio_bh_schedule_oneshot(qemu_get_aio_context(), do_qmp_dispatch_bh, + aio_bh_schedule_oneshot(iohandler_get_aio_context(), do_qmp_dispatch_bh, &data); qemu_coroutine_yield(); } diff --git a/qapi/string-output-visitor.c b/qapi/string-output-visitor.c index 71ddc92b7b..c0cb72dbe4 100644 --- a/qapi/string-output-visitor.c +++ b/qapi/string-output-visitor.c @@ -74,11 +74,27 @@ static StringOutputVisitor *to_sov(Visitor *v) static void string_output_set(StringOutputVisitor *sov, char *string) { - if (sov->string) { - g_string_free(sov->string, true); + switch (sov->list_mode) { + case LM_STARTED: + sov->list_mode = LM_IN_PROGRESS; + /* fall through */ + case LM_NONE: + if (sov->string) { + g_string_free(sov->string, true); + } + sov->string = g_string_new(string); + g_free(string); + break; + + case LM_IN_PROGRESS: + case LM_END: + g_string_append(sov->string, ", "); + g_string_append(sov->string, string); + break; + + default: + abort(); } - sov->string = g_string_new(string); - g_free(string); } static void string_output_append(StringOutputVisitor *sov, int64_t a) diff --git a/qga/commands.c b/qga/commands.c index ce172edd2d..88c1c99fe5 100644 --- a/qga/commands.c +++ b/qga/commands.c @@ -154,7 +154,7 @@ GuestExecStatus *qmp_guest_exec_status(int64_t pid, Error **errp) gei = guest_exec_info_find(pid); if (gei == NULL) { - error_setg(errp, QERR_INVALID_PARAMETER, "pid"); + error_setg(errp, "PID " PRId64 " does not exist"); return NULL; } diff --git a/qga/meson.build b/qga/meson.build index 940a51d55d..ff7a8496e4 100644 --- a/qga/meson.build +++ b/qga/meson.build @@ -146,7 +146,7 @@ if targetos == 'windows' libpcre = 'libpcre2' endif qga_msi_version = get_option('qemu_ga_version') == '' \ - ? project.version() \ + ? meson.project_version() \ : get_option('qemu_ga_version') qga_msi = custom_target('QGA MSI', input: files('installer/qemu-ga.wxs'), diff --git a/roms/SLOF b/roms/SLOF index 6b6c16b4b4..3a259df244 160000 --- a/roms/SLOF +++ b/roms/SLOF @@ -1 +1 @@ -Subproject commit 6b6c16b4b40763507cf1f518096f3c3883c5cf2d +Subproject commit 3a259df2449fc4a4e43ab5f33f0b2c66484b4bc3 diff --git a/roms/edk2 b/roms/edk2 index 819cfc6b42..b8a3eec88c 160000 --- a/roms/edk2 +++ b/roms/edk2 @@ -1 +1 @@ -Subproject commit 819cfc6b42a68790a23509e4fcc58ceb70e1965e +Subproject commit b8a3eec88cc74bbfe7fb389d026cc7d1d8a989c8 diff --git a/roms/edk2-build.config b/roms/edk2-build.config index bab6a9caeb..0d367dbdb7 100644 --- a/roms/edk2-build.config +++ b/roms/edk2-build.config @@ -22,9 +22,15 @@ SMM_REQUIRE = TRUE [opts.armvirt.silent] DEBUG_PRINT_ERROR_LEVEL = 0x80000000 -[pcds.nx.broken.grub] +[pcds.nx.strict] +PcdDxeNxMemoryProtectionPolicy = 0xC000000000007FD5 +PcdUninstallMemAttrProtocol = FALSE + +[pcds.nx.broken.shim.grub] # grub.efi uses EfiLoaderData for code PcdDxeNxMemoryProtectionPolicy = 0xC000000000007FD1 +# shim.efi has broken MemAttr code +PcdUninstallMemAttrProtocol = TRUE [pcds.workaround.202308] PcdFirstTimeWakeUpAPsBySipi = FALSE @@ -95,7 +101,7 @@ conf = ArmVirtPkg/ArmVirtQemu.dsc arch = ARM opts = common armvirt.silent -pcds = nx.broken.grub +pcds = nx.broken.shim.grub plat = ArmVirtQemu-ARM dest = ../pc-bios cpy1 = FV/QEMU_EFI.fd edk2-arm-code.fd @@ -112,7 +118,7 @@ conf = ArmVirtPkg/ArmVirtQemu.dsc arch = AARCH64 opts = common armvirt.silent -pcds = nx.broken.grub +pcds = nx.broken.shim.grub plat = ArmVirtQemu-AARCH64 dest = ../pc-bios cpy1 = FV/QEMU_EFI.fd edk2-aarch64-code.fd diff --git a/roms/seabios b/roms/seabios index 1e1da7a963..a6ed6b701f 160000 --- a/roms/seabios +++ b/roms/seabios @@ -1 +1 @@ -Subproject commit 1e1da7a963007d03a4e0e9a9e0ff17990bb1608d +Subproject commit a6ed6b701f0a57db0569ab98b0661c12a6ec3ff8 diff --git a/roms/seabios-hppa b/roms/seabios-hppa index 2a23dd388f..e4eac85880 160000 --- a/roms/seabios-hppa +++ b/roms/seabios-hppa @@ -1 +1 @@ -Subproject commit 2a23dd388fcc1068f9c4a3077e0662803743e1c8 +Subproject commit e4eac85880e8677f96d8b9e94de9f2eec9c0751f diff --git a/scripts/block-coroutine-wrapper.py b/scripts/block-coroutine-wrapper.py index a601c3c672..a38e5833fb 100644 --- a/scripts/block-coroutine-wrapper.py +++ b/scripts/block-coroutine-wrapper.py @@ -262,7 +262,7 @@ def gen_no_co_wrapper(func: FuncDecl) -> str: graph_unlock=' bdrv_graph_rdunlock_main_loop();' elif func.graph_wrlock: graph_lock=' bdrv_graph_wrlock(NULL);' - graph_unlock=' bdrv_graph_wrunlock();' + graph_unlock=' bdrv_graph_wrunlock(NULL);' return f"""\ /* diff --git a/scripts/coverity-scan/model.c b/scripts/coverity-scan/model.c index 686d1a3008..a064d84084 100644 --- a/scripts/coverity-scan/model.c +++ b/scripts/coverity-scan/model.c @@ -42,94 +42,6 @@ typedef _Bool bool; typedef struct va_list_str *va_list; -/* exec.c */ - -typedef struct AddressSpace AddressSpace; -typedef struct MemoryRegionCache MemoryRegionCache; -typedef uint64_t hwaddr; -typedef uint32_t MemTxResult; -typedef struct MemTxAttrs {} MemTxAttrs; - -static void __bufwrite(uint8_t *buf, ssize_t len) -{ - int first, last; - __coverity_negative_sink__(len); - if (len == 0) return; - buf[0] = first; - buf[len-1] = last; - __coverity_writeall__(buf); -} - -static void __bufread(uint8_t *buf, ssize_t len) -{ - __coverity_negative_sink__(len); - if (len == 0) return; - int first = buf[0]; - int last = buf[len-1]; -} - -MemTxResult address_space_read_cached(MemoryRegionCache *cache, hwaddr addr, - MemTxAttrs attrs, - void *buf, int len) -{ - MemTxResult result; - // TODO: investigate impact of treating reads as producing - // tainted data, with __coverity_tainted_data_argument__(buf). - __bufwrite(buf, len); - return result; -} - -MemTxResult address_space_write_cached(MemoryRegionCache *cache, hwaddr addr, - MemTxAttrs attrs, - const void *buf, int len) -{ - MemTxResult result; - __bufread(buf, len); - return result; -} - -MemTxResult address_space_rw_cached(MemoryRegionCache *cache, hwaddr addr, - MemTxAttrs attrs, - void *buf, int len, bool is_write) -{ - if (is_write) { - return address_space_write_cached(cache, addr, attrs, buf, len); - } else { - return address_space_read_cached(cache, addr, attrs, buf, len); - } -} - -MemTxResult address_space_read(AddressSpace *as, hwaddr addr, - MemTxAttrs attrs, - void *buf, int len) -{ - MemTxResult result; - // TODO: investigate impact of treating reads as producing - // tainted data, with __coverity_tainted_data_argument__(buf). - __bufwrite(buf, len); - return result; -} - -MemTxResult address_space_write(AddressSpace *as, hwaddr addr, - MemTxAttrs attrs, - const void *buf, int len) -{ - MemTxResult result; - __bufread(buf, len); - return result; -} - -MemTxResult address_space_rw(AddressSpace *as, hwaddr addr, - MemTxAttrs attrs, - void *buf, int len, bool is_write) -{ - if (is_write) { - return address_space_write(as, addr, attrs, buf, len); - } else { - return address_space_read(as, addr, attrs, buf, len); - } -} - /* Tainting */ typedef struct {} name2keysym_t; diff --git a/scripts/coverity-scan/run-coverity-scan b/scripts/coverity-scan/run-coverity-scan index 129672c86f..d56c9b6677 100755 --- a/scripts/coverity-scan/run-coverity-scan +++ b/scripts/coverity-scan/run-coverity-scan @@ -116,14 +116,14 @@ update_coverity_tools () { cd "$COVERITY_TOOL_BASE" echo "Checking for new version of coverity build tools..." - wget https://scan.coverity.com/download/linux64 --post-data "token=$COVERITY_TOKEN&project=$PROJNAME&md5=1" -O coverity_tool.md5.new + wget https://scan.coverity.com/download/cxx/linux64 --post-data "token=$COVERITY_TOKEN&project=$PROJNAME&md5=1" -O coverity_tool.md5.new if ! cmp -s coverity_tool.md5 coverity_tool.md5.new; then # out of date md5 or no md5: download new build tool # blow away the old build tool echo "Downloading coverity build tools..." rm -rf coverity_tool coverity_tool.tgz - wget https://scan.coverity.com/download/linux64 --post-data "token=$COVERITY_TOKEN&project=$PROJNAME" -O coverity_tool.tgz + wget https://scan.coverity.com/download/cxx/linux64 --post-data "token=$COVERITY_TOKEN&project=$PROJNAME" -O coverity_tool.tgz if ! (cat coverity_tool.md5.new; echo " coverity_tool.tgz") | md5sum -c --status; then echo "Downloaded tarball didn't match md5sum!" exit 1 diff --git a/system/balloon.c b/system/balloon.c index e0e8969a4b..fda7af832e 100644 --- a/system/balloon.c +++ b/system/balloon.c @@ -90,17 +90,17 @@ BalloonInfo *qmp_query_balloon(Error **errp) return info; } -void qmp_balloon(int64_t target, Error **errp) +void qmp_balloon(int64_t value, Error **errp) { if (!have_balloon(errp)) { return; } - if (target <= 0) { - error_setg(errp, QERR_INVALID_PARAMETER_VALUE, "target", "a size"); + if (value <= 0) { + error_setg(errp, QERR_INVALID_PARAMETER_VALUE, "value", "a size"); return; } - trace_balloon_event(balloon_opaque, target); - balloon_event_fn(balloon_opaque, target); + trace_balloon_event(balloon_opaque, value); + balloon_event_fn(balloon_opaque, value); } diff --git a/system/memory.c b/system/memory.c index 304fa843ea..798b6c0a17 100644 --- a/system/memory.c +++ b/system/memory.c @@ -1339,22 +1339,7 @@ static uint64_t memory_region_ram_device_read(void *opaque, hwaddr addr, unsigned size) { MemoryRegion *mr = opaque; - uint64_t data = (uint64_t)~0; - - switch (size) { - case 1: - data = *(uint8_t *)(mr->ram_block->host + addr); - break; - case 2: - data = *(uint16_t *)(mr->ram_block->host + addr); - break; - case 4: - data = *(uint32_t *)(mr->ram_block->host + addr); - break; - case 8: - data = *(uint64_t *)(mr->ram_block->host + addr); - break; - } + uint64_t data = ldn_he_p(mr->ram_block->host + addr, size); trace_memory_region_ram_device_read(get_cpu_index(), mr, addr, data, size); @@ -1368,20 +1353,7 @@ static void memory_region_ram_device_write(void *opaque, hwaddr addr, trace_memory_region_ram_device_write(get_cpu_index(), mr, addr, data, size); - switch (size) { - case 1: - *(uint8_t *)(mr->ram_block->host + addr) = (uint8_t)data; - break; - case 2: - *(uint16_t *)(mr->ram_block->host + addr) = (uint16_t)data; - break; - case 4: - *(uint32_t *)(mr->ram_block->host + addr) = (uint32_t)data; - break; - case 8: - *(uint64_t *)(mr->ram_block->host + addr) = data; - break; - } + stn_he_p(mr->ram_block->host + addr, size, data); } static const MemoryRegionOps ram_device_mem_ops = { @@ -1692,7 +1664,7 @@ void memory_region_init_ram_ptr(MemoryRegion *mr, /* qemu_ram_alloc_from_ptr cannot fail with ptr != NULL. */ assert(ptr != NULL); - mr->ram_block = qemu_ram_alloc_from_ptr(size, ptr, mr, &error_fatal); + mr->ram_block = qemu_ram_alloc_from_ptr(size, ptr, mr, &error_abort); } void memory_region_init_ram_device_ptr(MemoryRegion *mr, @@ -1711,7 +1683,7 @@ void memory_region_init_ram_device_ptr(MemoryRegion *mr, /* qemu_ram_alloc_from_ptr cannot fail with ptr != NULL. */ assert(ptr != NULL); - mr->ram_block = qemu_ram_alloc_from_ptr(size, ptr, mr, &error_fatal); + mr->ram_block = qemu_ram_alloc_from_ptr(size, ptr, mr, &error_abort); } void memory_region_init_alias(MemoryRegion *mr, diff --git a/system/physmem.c b/system/physmem.c index 211b19872d..f605737d16 100644 --- a/system/physmem.c +++ b/system/physmem.c @@ -2704,6 +2704,17 @@ static MemTxResult flatview_write_continue(FlatView *fv, hwaddr addr, l = memory_access_size(mr, l, addr1); /* XXX: could force current_cpu to NULL to avoid potential bugs */ + + /* + * Assure Coverity (and ourselves) that we are not going to OVERRUN + * the buffer by following ldn_he_p(). + */ +#ifdef QEMU_STATIC_ANALYSIS + assert((l == 1 && len >= 1) || + (l == 2 && len >= 2) || + (l == 4 && len >= 4) || + (l == 8 && len >= 8)); +#endif val = ldn_he_p(buf, l); result |= memory_region_dispatch_write(mr, addr1, val, size_memop(l), attrs); @@ -2774,6 +2785,17 @@ MemTxResult flatview_read_continue(FlatView *fv, hwaddr addr, l = memory_access_size(mr, l, addr1); result |= memory_region_dispatch_read(mr, addr1, &val, size_memop(l), attrs); + + /* + * Assure Coverity (and ourselves) that we are not going to OVERRUN + * the buffer by following stn_he_p(). + */ +#ifdef QEMU_STATIC_ANALYSIS + assert((l == 1 && len >= 1) || + (l == 2 && len >= 2) || + (l == 4 && len >= 4) || + (l == 8 && len >= 8)); +#endif stn_he_p(buf, l, val); } else { /* RAM case */ diff --git a/system/vl.c b/system/vl.c index 5af7ced2a1..6b87bfa32c 100644 --- a/system/vl.c +++ b/system/vl.c @@ -198,6 +198,7 @@ static const struct { const char *driver; int *flag; } default_list[] = { + { .driver = "xen-console", .flag = &default_serial }, { .driver = "isa-serial", .flag = &default_serial }, { .driver = "isa-parallel", .flag = &default_parallel }, { .driver = "isa-fdc", .flag = &default_floppy }, @@ -1110,6 +1111,7 @@ static void parse_display(const char *p) */ if (*opts == '=') { vnc_parse(opts + 1); + display_remote++; } else { error_report("VNC requires a display argument vnc="); exit(1); @@ -1359,6 +1361,7 @@ static void qemu_setup_display(void) dpy.type = DISPLAY_TYPE_NONE; #if defined(CONFIG_VNC) vnc_parse("localhost:0,to=99,id=default"); + display_remote++; #endif } } @@ -1391,7 +1394,7 @@ static void qemu_create_default_devices(void) } } - if (nographic || (!vc && !is_daemonized() && isatty(STDOUT_FILENO))) { + if (nographic) { if (default_parallel) { add_device_config(DEV_PARALLEL, "null"); } @@ -2423,6 +2426,10 @@ static void qemu_validate_options(const QDict *machine_opts) } } + if (loadvm && incoming) { + error_report("'incoming' and 'loadvm' options are mutually exclusive"); + exit(EXIT_FAILURE); + } if (loadvm && preconfig_requested) { error_report("'preconfig' and 'loadvm' options are " "mutually exclusive"); diff --git a/target/arm/cpu-features.h b/target/arm/cpu-features.h index 954d358268..165a497f7b 100644 --- a/target/arm/cpu-features.h +++ b/target/arm/cpu-features.h @@ -771,7 +771,7 @@ static inline bool isar_feature_aa64_hcx(const ARMISARegisters *id) static inline bool isar_feature_aa64_tidcp1(const ARMISARegisters *id) { - return FIELD_EX64(id->id_aa64mmfr2, ID_AA64MMFR1, TIDCP1) != 0; + return FIELD_EX64(id->id_aa64mmfr1, ID_AA64MMFR1, TIDCP1) != 0; } static inline bool isar_feature_aa64_hafs(const ARMISARegisters *id) diff --git a/target/arm/cpu.c b/target/arm/cpu.c index 25e9d2ae7b..efb22a87f9 100644 --- a/target/arm/cpu.c +++ b/target/arm/cpu.c @@ -1743,6 +1743,16 @@ void arm_cpu_finalize_features(ARMCPU *cpu, Error **errp) return; } + /* + * FEAT_SME is not architecturally dependent on FEAT_SVE (unless + * FEAT_SME_FA64 is present). However our implementation currently + * assumes it, so if the user asked for sve=off then turn off SME also. + * (KVM doesn't currently support SME at all.) + */ + if (cpu_isar_feature(aa64_sme, cpu) && !cpu_isar_feature(aa64_sve, cpu)) { + object_property_set_bool(OBJECT(cpu), "sme", false, &error_abort); + } + arm_cpu_sme_finalize(cpu, &local_err); if (local_err != NULL) { error_propagate(errp, local_err); diff --git a/target/arm/helper.c b/target/arm/helper.c index dc4f21e0bf..2e7be278b4 100644 --- a/target/arm/helper.c +++ b/target/arm/helper.c @@ -2646,11 +2646,28 @@ static void gt_recalc_timer(ARMCPU *cpu, int timeridx) gt->ctl = deposit32(gt->ctl, 2, 1, istatus); if (istatus) { - /* Next transition is when count rolls back over to zero */ - nexttick = UINT64_MAX; + /* + * Next transition is when (count - offset) rolls back over to 0. + * If offset > count then this is when count == offset; + * if offset <= count then this is when count == offset + 2^64 + * For the latter case we set nexttick to an "as far in future + * as possible" value and let the code below handle it. + */ + if (offset > count) { + nexttick = offset; + } else { + nexttick = UINT64_MAX; + } } else { - /* Next transition is when we hit cval */ - nexttick = gt->cval + offset; + /* + * Next transition is when (count - offset) == cval, i.e. + * when count == (cval + offset). + * If that would overflow, then again we set up the next interrupt + * for "as far in the future as possible" for the code below. + */ + if (uadd64_overflow(gt->cval, offset, &nexttick)) { + nexttick = UINT64_MAX; + } } /* * Note that the desired next expiry time might be beyond the diff --git a/target/arm/syndrome.h b/target/arm/syndrome.h index 5d34755508..95454b5b3b 100644 --- a/target/arm/syndrome.h +++ b/target/arm/syndrome.h @@ -216,7 +216,7 @@ static inline uint32_t syn_simd_access_trap(int cv, int cond, bool is_16bit) static inline uint32_t syn_sve_access_trap(void) { - return EC_SVEACCESSTRAP << ARM_EL_EC_SHIFT; + return (EC_SVEACCESSTRAP << ARM_EL_EC_SHIFT) | ARM_EL_IL; } /* @@ -242,12 +242,12 @@ static inline uint32_t syn_pacfail(bool data, int keynumber) static inline uint32_t syn_pactrap(void) { - return EC_PACTRAP << ARM_EL_EC_SHIFT; + return (EC_PACTRAP << ARM_EL_EC_SHIFT) | ARM_EL_IL; } static inline uint32_t syn_btitrap(int btype) { - return (EC_BTITRAP << ARM_EL_EC_SHIFT) | btype; + return (EC_BTITRAP << ARM_EL_EC_SHIFT) | ARM_EL_IL | btype; } static inline uint32_t syn_bxjtrap(int cv, int cond, int rm) diff --git a/target/arm/tcg/cpu64.c b/target/arm/tcg/cpu64.c index 08db1dbcc7..fcda99e158 100644 --- a/target/arm/tcg/cpu64.c +++ b/target/arm/tcg/cpu64.c @@ -1018,7 +1018,7 @@ static void aarch64_neoverse_n2_initfn(Object *obj) cpu->isar.id_aa64dfr1 = 0; cpu->id_aa64afr0 = 0; cpu->id_aa64afr1 = 0; - cpu->isar.id_aa64isar0 = 0x0221111110212120ull; /* with Crypto */ + cpu->isar.id_aa64isar0 = 0x1221111110212120ull; /* with Crypto and FEAT_RNG */ cpu->isar.id_aa64isar1 = 0x0011111101211052ull; cpu->isar.id_aa64mmfr0 = 0x0000022200101125ull; cpu->isar.id_aa64mmfr1 = 0x0000000010212122ull; diff --git a/target/arm/tcg/helper-a64.c b/target/arm/tcg/helper-a64.c index ce4800b8d1..8ad84623d3 100644 --- a/target/arm/tcg/helper-a64.c +++ b/target/arm/tcg/helper-a64.c @@ -1414,7 +1414,7 @@ void HELPER(setge)(CPUARMState *env, uint32_t syndrome, uint32_t mtedesc) /* * Perform part of a memory copy from the guest memory at fromaddr * and extending for copysize bytes, to the guest memory at - * toaddr. Both addreses are dirty. + * toaddr. Both addresses are dirty. * * Returns the number of bytes actually set, which might be less than * copysize; the caller should loop until the whole copy has been done. diff --git a/target/arm/tcg/hflags.c b/target/arm/tcg/hflags.c index 3d7fdce5c3..a6ebd7571a 100644 --- a/target/arm/tcg/hflags.c +++ b/target/arm/tcg/hflags.c @@ -327,7 +327,7 @@ static CPUARMTBFlags rebuild_hflags_a64(CPUARMState *env, int el, int fp_el, DP_TBFLAG_A64(flags, MTE0_ACTIVE, 1); } /* - * For unpriv tag-setting accesses we alse need ATA0. Again, in + * For unpriv tag-setting accesses we also need ATA0. Again, in * contexts where unpriv and normal insns are the same we * duplicate the ATA bit to save effort for translate-a64.c. */ diff --git a/target/arm/tcg/sme_helper.c b/target/arm/tcg/sme_helper.c index 296826ffe6..1ee2690ceb 100644 --- a/target/arm/tcg/sme_helper.c +++ b/target/arm/tcg/sme_helper.c @@ -1037,10 +1037,9 @@ void HELPER(sme_fmopa_h)(void *vza, void *vzn, void *vzm, void *vpn, m = f16mop_adj_pair(m, pcol, 0); *a = f16_dotadd(*a, n, m, &fpst_std, &fpst_odd); - - col += 4; - pcol >>= 4; } + col += 4; + pcol >>= 4; } while (col & 15); } row += 4; @@ -1073,10 +1072,9 @@ void HELPER(sme_bfmopa)(void *vza, void *vzn, void *vzm, void *vpn, m = f16mop_adj_pair(m, pcol, 0); *a = bfdotadd(*a, n, m); - - col += 4; - pcol >>= 4; } + col += 4; + pcol >>= 4; } while (col & 15); } row += 4; diff --git a/target/arm/tcg/translate-a64.c b/target/arm/tcg/translate-a64.c index 0b8cb4f285..2d229af8d6 100644 --- a/target/arm/tcg/translate-a64.c +++ b/target/arm/tcg/translate-a64.c @@ -8254,7 +8254,7 @@ static void handle_vec_simd_sqshrn(DisasContext *s, bool is_scalar, bool is_q, narrowfn(tcg_rd_narrowed, tcg_env, tcg_rd); tcg_gen_extu_i32_i64(tcg_rd, tcg_rd_narrowed); if (i == 0) { - tcg_gen_mov_i64(tcg_final, tcg_rd); + tcg_gen_extract_i64(tcg_final, tcg_rd, 0, esize); } else { tcg_gen_deposit_i64(tcg_final, tcg_final, tcg_rd, esize * i, esize); } diff --git a/target/avr/cpu.c b/target/avr/cpu.c index 44de1e18d1..999c010ded 100644 --- a/target/avr/cpu.c +++ b/target/avr/cpu.c @@ -25,6 +25,7 @@ #include "cpu.h" #include "disas/dis-asm.h" #include "tcg/debug-assert.h" +#include "hw/qdev-properties.h" static void avr_cpu_set_pc(CPUState *cs, vaddr value) { @@ -95,7 +96,7 @@ static void avr_cpu_reset_hold(Object *obj) env->rampY = 0; env->rampZ = 0; env->eind = 0; - env->sp = 0; + env->sp = cpu->init_sp; env->skip = 0; @@ -152,6 +153,11 @@ static void avr_cpu_initfn(Object *obj) sizeof(cpu->env.intsrc) * 8); } +static Property avr_cpu_properties[] = { + DEFINE_PROP_UINT32("init-sp", AVRCPU, init_sp, 0), + DEFINE_PROP_END_OF_LIST() +}; + static ObjectClass *avr_cpu_class_by_name(const char *cpu_model) { ObjectClass *oc; @@ -228,6 +234,8 @@ static void avr_cpu_class_init(ObjectClass *oc, void *data) device_class_set_parent_realize(dc, avr_cpu_realizefn, &mcc->parent_realize); + device_class_set_props(dc, avr_cpu_properties); + resettable_class_set_parent_phases(rc, NULL, avr_cpu_reset_hold, NULL, &mcc->parent_phases); diff --git a/target/avr/cpu.h b/target/avr/cpu.h index 8a17862737..7960c5c57a 100644 --- a/target/avr/cpu.h +++ b/target/avr/cpu.h @@ -145,6 +145,9 @@ struct ArchCPU { CPUState parent_obj; CPUAVRState env; + + /* Initial value of stack pointer */ + uint32_t init_sp; }; /** diff --git a/target/hexagon/idef-parser/prepare b/target/hexagon/idef-parser/prepare index 72d6fcbd21..cb3622d4f8 100755 --- a/target/hexagon/idef-parser/prepare +++ b/target/hexagon/idef-parser/prepare @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash # # Copyright(c) 2019-2021 rev.ng Labs Srl. All Rights Reserved. diff --git a/target/hppa/cpu.c b/target/hppa/cpu.c index 04de1689d7..fda32d7f59 100644 --- a/target/hppa/cpu.c +++ b/target/hppa/cpu.c @@ -110,11 +110,7 @@ void hppa_cpu_do_unaligned_access(CPUState *cs, vaddr addr, CPUHPPAState *env = &cpu->env; cs->exception_index = EXCP_UNALIGN; - if (env->psw & PSW_Q) { - /* ??? Needs tweaking for hppa64. */ - env->cr[CR_IOR] = addr; - env->cr[CR_ISR] = addr >> 32; - } + hppa_set_ior_and_isr(env, addr, MMU_IDX_MMU_DISABLED(mmu_idx)); cpu_loop_exit_restore(cs, retaddr); } diff --git a/target/hppa/cpu.h b/target/hppa/cpu.h index bcfed04f7c..9556e95fab 100644 --- a/target/hppa/cpu.h +++ b/target/hppa/cpu.h @@ -56,7 +56,7 @@ 1 << MMU_PL2_IDX | 1 << MMU_PL2_P_IDX | \ 1 << MMU_USER_IDX | 1 << MMU_USER_P_IDX) -/* Indicies to flush for access_id changes. */ +/* Indices to flush for access_id changes. */ #define HPPA_MMU_FLUSH_P_MASK \ (1 << MMU_KERNEL_P_IDX | 1 << MMU_PL1_P_IDX | \ 1 << MMU_PL2_P_IDX | 1 << MMU_USER_P_IDX) @@ -385,6 +385,7 @@ void hppa_cpu_dump_state(CPUState *cs, FILE *f, int); #ifndef CONFIG_USER_ONLY void hppa_ptlbe(CPUHPPAState *env); hwaddr hppa_cpu_get_phys_page_debug(CPUState *cs, vaddr addr); +void hppa_set_ior_and_isr(CPUHPPAState *env, vaddr addr, bool mmu_disabled); bool hppa_cpu_tlb_fill(CPUState *cs, vaddr address, int size, MMUAccessType access_type, int mmu_idx, bool probe, uintptr_t retaddr); diff --git a/target/hppa/machine.c b/target/hppa/machine.c index 2f8e8cc5a1..15cbc5e6d0 100644 --- a/target/hppa/machine.c +++ b/target/hppa/machine.c @@ -129,7 +129,7 @@ static int tlb_post_load(void *opaque, int version_id) /* * Re-create the interval tree from the valid entries. - * Truely invalid entries should have start == end == 0. + * Truly invalid entries should have start == end == 0. * Otherwise it should be the in-flight tlb_partial entry. */ for (uint32_t i = 0; i < ARRAY_SIZE(env->tlb); ++i) { diff --git a/target/hppa/mem_helper.c b/target/hppa/mem_helper.c index 08abd1a9f9..4fcc612754 100644 --- a/target/hppa/mem_helper.c +++ b/target/hppa/mem_helper.c @@ -55,8 +55,14 @@ hwaddr hppa_abs_to_phys_pa2_w0(vaddr addr) /* I/O address space */ addr = (int32_t)addr; } else { - /* PDC address space */ - addr &= MAKE_64BIT_MASK(0, 24); + /* + * PDC address space: + * Figures H-10 and H-11 of the parisc2.0 spec do not specify + * where to map into the 64-bit PDC address space. + * We map with an offset which equals the 32-bit address, which + * is what can be seen on physical machines too. + */ + addr = (uint32_t)addr; addr |= -1ull << (TARGET_PHYS_ADDR_SPACE_BITS - 4); } return addr; @@ -299,14 +305,8 @@ hwaddr hppa_cpu_get_phys_page_debug(CPUState *cs, vaddr addr) return excp == EXCP_DTLB_MISS ? -1 : phys; } -G_NORETURN static void -raise_exception_with_ior(CPUHPPAState *env, int excp, uintptr_t retaddr, - vaddr addr, bool mmu_disabled) +void hppa_set_ior_and_isr(CPUHPPAState *env, vaddr addr, bool mmu_disabled) { - CPUState *cs = env_cpu(env); - - cs->exception_index = excp; - if (env->psw & PSW_Q) { /* * For pa1.x, the offset and space never overlap, and so we @@ -333,16 +333,23 @@ raise_exception_with_ior(CPUHPPAState *env, int excp, uintptr_t retaddr, */ uint64_t b; - cpu_restore_state(cs, retaddr); - - b = env->gr[env->unwind_breg]; + b = env->unwind_breg ? env->gr[env->unwind_breg] : 0; b >>= (env->psw & PSW_W ? 62 : 30); env->cr[CR_IOR] |= b << 62; - - cpu_loop_exit(cs); } } } +} + +G_NORETURN static void +raise_exception_with_ior(CPUHPPAState *env, int excp, uintptr_t retaddr, + vaddr addr, bool mmu_disabled) +{ + CPUState *cs = env_cpu(env); + + cs->exception_index = excp; + hppa_set_ior_and_isr(env, addr, mmu_disabled); + cpu_loop_exit_restore(cs, retaddr); } diff --git a/target/hppa/op_helper.c b/target/hppa/op_helper.c index 7f607c3afd..ce15469465 100644 --- a/target/hppa/op_helper.c +++ b/target/hppa/op_helper.c @@ -351,11 +351,7 @@ target_ulong HELPER(probe)(CPUHPPAState *env, target_ulong addr, excp = hppa_get_physical_address(env, addr, mmu_idx, 0, &phys, &prot, NULL); if (excp >= 0) { - if (env->psw & PSW_Q) { - /* ??? Needs tweaking for hppa64. */ - env->cr[CR_IOR] = addr; - env->cr[CR_ISR] = addr >> 32; - } + hppa_set_ior_and_isr(env, addr, MMU_IDX_MMU_DISABLED(mmu_idx)); if (excp == EXCP_DTLB_MISS) { excp = EXCP_NA_DTLB_MISS; } diff --git a/target/hppa/translate.c b/target/hppa/translate.c index 4a4830c3e3..3ef39b1bd7 100644 --- a/target/hppa/translate.c +++ b/target/hppa/translate.c @@ -3438,9 +3438,9 @@ static bool trans_shrp_sar(DisasContext *ctx, arg_shrp_sar *a) TCGv_i64 n = tcg_temp_new_i64(); tcg_gen_xori_i64(n, cpu_sar, 63); - tcg_gen_shl_i64(t, src2, n); + tcg_gen_shl_i64(t, src1, n); tcg_gen_shli_i64(t, t, 1); - tcg_gen_shr_i64(dest, src1, cpu_sar); + tcg_gen_shr_i64(dest, src2, cpu_sar); tcg_gen_or_i64(dest, dest, t); } else { TCGv_i64 t = tcg_temp_new_i64(); diff --git a/target/i386/cpu.c b/target/i386/cpu.c index 499771053c..85cfd0eb51 100644 --- a/target/i386/cpu.c +++ b/target/i386/cpu.c @@ -5192,7 +5192,8 @@ static void x86_cpuid_set_vendor(Object *obj, const char *value, int i; if (strlen(value) != CPUID_VENDOR_SZ) { - error_setg(errp, QERR_PROPERTY_VALUE_BAD, "", "vendor", value); + error_setg(errp, "value of property 'vendor' must consist of" + " exactly " stringify(CPUID_VENDOR_SZ) " characters"); return; } diff --git a/target/i386/cpu.h b/target/i386/cpu.h index deebf1a9ad..d01c1b016c 100644 --- a/target/i386/cpu.h +++ b/target/i386/cpu.h @@ -2330,10 +2330,15 @@ static inline int cpu_mmu_index_kernel(CPUX86State *env) static inline void cpu_get_tb_cpu_state(CPUX86State *env, vaddr *pc, uint64_t *cs_base, uint32_t *flags) { - *cs_base = env->segs[R_CS].base; - *pc = *cs_base + env->eip; *flags = env->hflags | (env->eflags & (IOPL_MASK | TF_MASK | RF_MASK | VM_MASK | AC_MASK)); + if (env->hflags & HF_CS64_MASK) { + *cs_base = 0; + *pc = env->eip; + } else { + *cs_base = env->segs[R_CS].base; + *pc = (uint32_t)(*cs_base + env->eip); + } } void do_cpu_init(X86CPU *cpu); diff --git a/target/i386/kvm/kvm.c b/target/i386/kvm/kvm.c index 11b8177eff..4ce80555b4 100644 --- a/target/i386/kvm/kvm.c +++ b/target/i386/kvm/kvm.c @@ -3643,6 +3643,10 @@ static int kvm_get_sregs(X86CPU *cpu) env->cr[4] = sregs.cr4; env->efer = sregs.efer; + if (sev_es_enabled() && env->efer & MSR_EFER_LME && + env->cr[0] & CR0_PG_MASK) { + env->efer |= MSR_EFER_LMA; + } /* changes to apic base and cr8/tpr are read back via kvm_arch_post_run */ x86_update_hflags(env); @@ -3682,6 +3686,10 @@ static int kvm_get_sregs2(X86CPU *cpu) env->cr[4] = sregs.cr4; env->efer = sregs.efer; + if (sev_es_enabled() && env->efer & MSR_EFER_LME && + env->cr[0] & CR0_PG_MASK) { + env->efer |= MSR_EFER_LMA; + } env->pdptrs_valid = sregs.flags & KVM_SREGS2_FLAGS_PDPTRS_VALID; diff --git a/target/i386/tcg/tcg-cpu.c b/target/i386/tcg/tcg-cpu.c index 2c6a12c835..1d54164bdf 100644 --- a/target/i386/tcg/tcg-cpu.c +++ b/target/i386/tcg/tcg-cpu.c @@ -52,7 +52,12 @@ static void x86_cpu_synchronize_from_tb(CPUState *cs, /* The instruction pointer is always up to date with CF_PCREL. */ if (!(tb_cflags(tb) & CF_PCREL)) { CPUX86State *env = cpu_env(cs); - env->eip = tb->pc - tb->cs_base; + + if (tb->flags & HF_CS64_MASK) { + env->eip = tb->pc; + } else { + env->eip = (uint32_t)(tb->pc - tb->cs_base); + } } } @@ -63,12 +68,26 @@ static void x86_restore_state_to_opc(CPUState *cs, X86CPU *cpu = X86_CPU(cs); CPUX86State *env = &cpu->env; int cc_op = data[1]; + uint64_t new_pc; if (tb_cflags(tb) & CF_PCREL) { - env->eip = (env->eip & TARGET_PAGE_MASK) | data[0]; + /* + * data[0] in PC-relative TBs is also a linear address, i.e. an address with + * the CS base added, because it is not guaranteed that EIP bits 12 and higher + * stay the same across the translation block. Add the CS base back before + * replacing the low bits, and subtract it below just like for !CF_PCREL. + */ + uint64_t pc = env->eip + tb->cs_base; + new_pc = (pc & TARGET_PAGE_MASK) | data[0]; } else { - env->eip = data[0] - tb->cs_base; + new_pc = data[0]; } + if (tb->flags & HF_CS64_MASK) { + env->eip = new_pc; + } else { + env->eip = (uint32_t)(new_pc - tb->cs_base); + } + if (cc_op != CC_OP_DYNAMIC) { env->cc_op = cc_op; } diff --git a/target/i386/tcg/translate.c b/target/i386/tcg/translate.c index 8ea77e0d8b..17c9b79cab 100644 --- a/target/i386/tcg/translate.c +++ b/target/i386/tcg/translate.c @@ -557,8 +557,10 @@ static void gen_update_eip_cur(DisasContext *s) assert(s->pc_save != -1); if (tb_cflags(s->base.tb) & CF_PCREL) { tcg_gen_addi_tl(cpu_eip, cpu_eip, s->base.pc_next - s->pc_save); + } else if (CODE64(s)) { + tcg_gen_movi_tl(cpu_eip, s->base.pc_next); } else { - tcg_gen_movi_tl(cpu_eip, s->base.pc_next - s->cs_base); + tcg_gen_movi_tl(cpu_eip, (uint32_t)(s->base.pc_next - s->cs_base)); } s->pc_save = s->base.pc_next; } @@ -568,8 +570,10 @@ static void gen_update_eip_next(DisasContext *s) assert(s->pc_save != -1); if (tb_cflags(s->base.tb) & CF_PCREL) { tcg_gen_addi_tl(cpu_eip, cpu_eip, s->pc - s->pc_save); + } else if (CODE64(s)) { + tcg_gen_movi_tl(cpu_eip, s->pc); } else { - tcg_gen_movi_tl(cpu_eip, s->pc - s->cs_base); + tcg_gen_movi_tl(cpu_eip, (uint32_t)(s->pc - s->cs_base)); } s->pc_save = s->pc; } @@ -615,8 +619,10 @@ static TCGv eip_next_tl(DisasContext *s) TCGv ret = tcg_temp_new(); tcg_gen_addi_tl(ret, cpu_eip, s->pc - s->pc_save); return ret; + } else if (CODE64(s)) { + return tcg_constant_tl(s->pc); } else { - return tcg_constant_tl(s->pc - s->cs_base); + return tcg_constant_tl((uint32_t)(s->pc - s->cs_base)); } } @@ -627,8 +633,10 @@ static TCGv eip_cur_tl(DisasContext *s) TCGv ret = tcg_temp_new(); tcg_gen_addi_tl(ret, cpu_eip, s->base.pc_next - s->pc_save); return ret; + } else if (CODE64(s)) { + return tcg_constant_tl(s->base.pc_next); } else { - return tcg_constant_tl(s->base.pc_next - s->cs_base); + return tcg_constant_tl((uint32_t)(s->base.pc_next - s->cs_base)); } } @@ -2871,10 +2879,11 @@ static void gen_jmp_rel(DisasContext *s, MemOp ot, int diff, int tb_num) tcg_gen_andi_tl(cpu_eip, cpu_eip, mask); use_goto_tb = false; } + } else if (!CODE64(s)) { + new_pc = (uint32_t)(new_eip + s->cs_base); } - if (use_goto_tb && - translator_use_goto_tb(&s->base, new_eip + s->cs_base)) { + if (use_goto_tb && translator_use_goto_tb(&s->base, new_pc)) { /* jump to same page: we can use a direct jump */ tcg_gen_goto_tb(tb_num); if (!(tb_cflags(s->base.tb) & CF_PCREL)) { @@ -6982,7 +6991,6 @@ static void i386_tr_insn_start(DisasContextBase *dcbase, CPUState *cpu) dc->prev_insn_end = tcg_last_op(); if (tb_cflags(dcbase->tb) & CF_PCREL) { - pc_arg -= dc->cs_base; pc_arg &= ~TARGET_PAGE_MASK; } tcg_gen_insn_start(pc_arg, dc->cc_op); diff --git a/target/ppc/fpu_helper.c b/target/ppc/fpu_helper.c index 03150a0f10..4b3dcad5d1 100644 --- a/target/ppc/fpu_helper.c +++ b/target/ppc/fpu_helper.c @@ -2880,20 +2880,22 @@ uint64_t helper_XSCVSPDPN(uint64_t xb) #define VSX_CVT_FP_TO_INT(op, nels, stp, ttp, sfld, tfld, sfi, rnan) \ void helper_##op(CPUPPCState *env, ppc_vsr_t *xt, ppc_vsr_t *xb) \ { \ + int all_flags = 0; \ ppc_vsr_t t = { }; \ int i, flags; \ \ - helper_reset_fpstatus(env); \ - \ for (i = 0; i < nels; i++) { \ + helper_reset_fpstatus(env); \ t.tfld = stp##_to_##ttp##_round_to_zero(xb->sfld, &env->fp_status); \ flags = env->fp_status.float_exception_flags; \ + all_flags |= flags; \ if (unlikely(flags & float_flag_invalid)) { \ t.tfld = float_invalid_cvt(env, flags, t.tfld, rnan, 0, GETPC());\ } \ } \ \ *xt = t; \ + env->fp_status.float_exception_flags = all_flags; \ do_float_check_status(env, sfi, GETPC()); \ } @@ -2945,15 +2947,16 @@ VSX_CVT_FP_TO_INT128(XSCVQPSQZ, int128, 0x8000000000000000ULL); #define VSX_CVT_FP_TO_INT2(op, nels, stp, ttp, sfi, rnan) \ void helper_##op(CPUPPCState *env, ppc_vsr_t *xt, ppc_vsr_t *xb) \ { \ + int all_flags = 0; \ ppc_vsr_t t = { }; \ int i, flags; \ \ - helper_reset_fpstatus(env); \ - \ for (i = 0; i < nels; i++) { \ + helper_reset_fpstatus(env); \ t.VsrW(2 * i) = stp##_to_##ttp##_round_to_zero(xb->VsrD(i), \ &env->fp_status); \ flags = env->fp_status.float_exception_flags; \ + all_flags |= flags; \ if (unlikely(flags & float_flag_invalid)) { \ t.VsrW(2 * i) = float_invalid_cvt(env, flags, t.VsrW(2 * i), \ rnan, 0, GETPC()); \ @@ -2962,6 +2965,7 @@ void helper_##op(CPUPPCState *env, ppc_vsr_t *xt, ppc_vsr_t *xb) \ } \ \ *xt = t; \ + env->fp_status.float_exception_flags = all_flags; \ do_float_check_status(env, sfi, GETPC()); \ } diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h index bf58b0f0b5..d74b361be6 100644 --- a/target/riscv/cpu.h +++ b/target/riscv/cpu.h @@ -214,13 +214,13 @@ struct CPUArchState { /* * When mideleg[i]=0 and mvien[i]=1, sie[i] is no more - * alias of mie[i] and needs to be maintained separatly. + * alias of mie[i] and needs to be maintained separately. */ uint64_t sie; /* * When hideleg[i]=0 and hvien[i]=1, vsie[i] is no more - * alias of sie[i] (mie[i]) and needs to be maintained separatly. + * alias of sie[i] (mie[i]) and needs to be maintained separately. */ uint64_t vsie; diff --git a/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c index b7af69de53..e7e23b34f4 100644 --- a/target/riscv/cpu_helper.c +++ b/target/riscv/cpu_helper.c @@ -1032,13 +1032,29 @@ restart: prot |= PAGE_WRITE; } if (pte & PTE_X) { - bool mxr; + bool mxr = false; - if (first_stage == true) { + /* + * Use mstatus for first stage or for the second stage without + * virt_enabled (MPRV+MPV) + */ + if (first_stage || !env->virt_enabled) { mxr = get_field(env->mstatus, MSTATUS_MXR); - } else { - mxr = get_field(env->vsstatus, MSTATUS_MXR); } + + /* MPRV+MPV case, check VSSTATUS */ + if (first_stage && two_stage && !env->virt_enabled) { + mxr |= get_field(env->vsstatus, MSTATUS_MXR); + } + + /* + * Setting MXR at HS-level overrides both VS-stage and G-stage + * execute-only permissions + */ + if (env->virt_enabled) { + mxr |= get_field(env->mstatus_hs, MSTATUS_MXR); + } + if (mxr) { prot |= PAGE_READ; } @@ -1143,47 +1159,31 @@ static void raise_mmu_exception(CPURISCVState *env, target_ulong address, bool two_stage_indirect) { CPUState *cs = env_cpu(env); - int page_fault_exceptions, vm; - uint64_t stap_mode; - - if (riscv_cpu_mxl(env) == MXL_RV32) { - stap_mode = SATP32_MODE; - } else { - stap_mode = SATP64_MODE; - } - - if (first_stage) { - vm = get_field(env->satp, stap_mode); - } else { - vm = get_field(env->hgatp, stap_mode); - } - - page_fault_exceptions = vm != VM_1_10_MBARE && !pmp_violation; switch (access_type) { case MMU_INST_FETCH: if (env->virt_enabled && !first_stage) { cs->exception_index = RISCV_EXCP_INST_GUEST_PAGE_FAULT; } else { - cs->exception_index = page_fault_exceptions ? - RISCV_EXCP_INST_PAGE_FAULT : RISCV_EXCP_INST_ACCESS_FAULT; + cs->exception_index = pmp_violation ? + RISCV_EXCP_INST_ACCESS_FAULT : RISCV_EXCP_INST_PAGE_FAULT; } break; case MMU_DATA_LOAD: if (two_stage && !first_stage) { cs->exception_index = RISCV_EXCP_LOAD_GUEST_ACCESS_FAULT; } else { - cs->exception_index = page_fault_exceptions ? - RISCV_EXCP_LOAD_PAGE_FAULT : RISCV_EXCP_LOAD_ACCESS_FAULT; + cs->exception_index = pmp_violation ? + RISCV_EXCP_LOAD_ACCESS_FAULT : RISCV_EXCP_LOAD_PAGE_FAULT; } break; case MMU_DATA_STORE: if (two_stage && !first_stage) { cs->exception_index = RISCV_EXCP_STORE_GUEST_AMO_ACCESS_FAULT; } else { - cs->exception_index = page_fault_exceptions ? - RISCV_EXCP_STORE_PAGE_FAULT : - RISCV_EXCP_STORE_AMO_ACCESS_FAULT; + cs->exception_index = pmp_violation ? + RISCV_EXCP_STORE_AMO_ACCESS_FAULT : + RISCV_EXCP_STORE_PAGE_FAULT; } break; default: diff --git a/target/riscv/csr.c b/target/riscv/csr.c index fde7ce1a53..c50a33397c 100644 --- a/target/riscv/csr.c +++ b/target/riscv/csr.c @@ -907,11 +907,11 @@ static int write_mhpmcounterh(CPURISCVState *env, int csrno, target_ulong val) static RISCVException riscv_pmu_read_ctr(CPURISCVState *env, target_ulong *val, bool upper_half, uint32_t ctr_idx) { - PMUCTRState counter = env->pmu_ctrs[ctr_idx]; - target_ulong ctr_prev = upper_half ? counter.mhpmcounterh_prev : - counter.mhpmcounter_prev; - target_ulong ctr_val = upper_half ? counter.mhpmcounterh_val : - counter.mhpmcounter_val; + PMUCTRState *counter = &env->pmu_ctrs[ctr_idx]; + target_ulong ctr_prev = upper_half ? counter->mhpmcounterh_prev : + counter->mhpmcounter_prev; + target_ulong ctr_val = upper_half ? counter->mhpmcounterh_val : + counter->mhpmcounter_val; if (get_field(env->mcountinhibit, BIT(ctr_idx))) { /* @@ -919,12 +919,12 @@ static RISCVException riscv_pmu_read_ctr(CPURISCVState *env, target_ulong *val, * stop the icount counting. Just return the counter value written by * the supervisor to indicate that counter was not incremented. */ - if (!counter.started) { + if (!counter->started) { *val = ctr_val; return RISCV_EXCP_NONE; } else { /* Mark that the counter has been stopped */ - counter.started = false; + counter->started = false; } } diff --git a/target/riscv/kvm/kvm-cpu.c b/target/riscv/kvm/kvm-cpu.c index 78fa1fa162..117e33cf90 100644 --- a/target/riscv/kvm/kvm-cpu.c +++ b/target/riscv/kvm/kvm-cpu.c @@ -87,17 +87,17 @@ static uint64_t kvm_riscv_reg_id(CPURISCVState *env, uint64_t type, #define KVM_RISCV_GET_CSR(cs, env, csr, reg) \ do { \ - int ret = kvm_get_one_reg(cs, RISCV_CSR_REG(env, csr), ®); \ - if (ret) { \ - return ret; \ + int _ret = kvm_get_one_reg(cs, RISCV_CSR_REG(env, csr), ®); \ + if (_ret) { \ + return _ret; \ } \ } while (0) #define KVM_RISCV_SET_CSR(cs, env, csr, reg) \ do { \ - int ret = kvm_set_one_reg(cs, RISCV_CSR_REG(env, csr), ®); \ - if (ret) { \ - return ret; \ + int _ret = kvm_set_one_reg(cs, RISCV_CSR_REG(env, csr), ®); \ + if (_ret) { \ + return _ret; \ } \ } while (0) @@ -533,7 +533,6 @@ static int kvm_riscv_put_regs_core(CPUState *cs) static int kvm_riscv_get_regs_csr(CPUState *cs) { - int ret = 0; CPURISCVState *env = &RISCV_CPU(cs)->env; KVM_RISCV_GET_CSR(cs, env, sstatus, env->mstatus); @@ -545,12 +544,12 @@ static int kvm_riscv_get_regs_csr(CPUState *cs) KVM_RISCV_GET_CSR(cs, env, stval, env->stval); KVM_RISCV_GET_CSR(cs, env, sip, env->mip); KVM_RISCV_GET_CSR(cs, env, satp, env->satp); - return ret; + + return 0; } static int kvm_riscv_put_regs_csr(CPUState *cs) { - int ret = 0; CPURISCVState *env = &RISCV_CPU(cs)->env; KVM_RISCV_SET_CSR(cs, env, sstatus, env->mstatus); @@ -563,7 +562,7 @@ static int kvm_riscv_put_regs_csr(CPUState *cs) KVM_RISCV_SET_CSR(cs, env, sip, env->mip); KVM_RISCV_SET_CSR(cs, env, satp, env->satp); - return ret; + return 0; } static int kvm_riscv_get_regs_fp(CPUState *cs) @@ -833,9 +832,8 @@ static void kvm_riscv_read_multiext_legacy(RISCVCPU *cpu, multi_ext_cfg->supported = false; val = false; } else { - error_report("Unable to read ISA_EXT KVM register %s, " - "error code: %s", multi_ext_cfg->name, - strerrorname_np(errno)); + error_report("Unable to read ISA_EXT KVM register %s: %s", + multi_ext_cfg->name, strerror(errno)); exit(EXIT_FAILURE); } } else { @@ -896,8 +894,8 @@ static void kvm_riscv_init_multiext_cfg(RISCVCPU *cpu, KVMScratchCPU *kvmcpu) * * Error out if we get any other errno. */ - error_report("Error when accessing get-reg-list, code: %s", - strerrorname_np(errno)); + error_report("Error when accessing get-reg-list: %s", + strerror(errno)); exit(EXIT_FAILURE); } @@ -906,8 +904,8 @@ static void kvm_riscv_init_multiext_cfg(RISCVCPU *cpu, KVMScratchCPU *kvmcpu) reglist->n = rl_struct.n; ret = ioctl(kvmcpu->cpufd, KVM_GET_REG_LIST, reglist); if (ret) { - error_report("Error when reading KVM_GET_REG_LIST, code %s ", - strerrorname_np(errno)); + error_report("Error when reading KVM_GET_REG_LIST: %s", + strerror(errno)); exit(EXIT_FAILURE); } @@ -928,9 +926,8 @@ static void kvm_riscv_init_multiext_cfg(RISCVCPU *cpu, KVMScratchCPU *kvmcpu) reg.addr = (uint64_t)&val; ret = ioctl(kvmcpu->cpufd, KVM_GET_ONE_REG, ®); if (ret != 0) { - error_report("Unable to read ISA_EXT KVM register %s, " - "error code: %s", multi_ext_cfg->name, - strerrorname_np(errno)); + error_report("Unable to read ISA_EXT KVM register %s: %s", + multi_ext_cfg->name, strerror(errno)); exit(EXIT_FAILURE); } diff --git a/target/riscv/tcg/tcg-cpu.c b/target/riscv/tcg/tcg-cpu.c index 08adad304d..8a35683a34 100644 --- a/target/riscv/tcg/tcg-cpu.c +++ b/target/riscv/tcg/tcg-cpu.c @@ -250,6 +250,15 @@ static void riscv_cpu_disable_priv_spec_isa_exts(RISCVCPU *cpu) for (edata = isa_edata_arr; edata && edata->name; edata++) { if (isa_ext_is_enabled(cpu, edata->ext_enable_offset) && (env->priv_ver < edata->min_version)) { + /* + * These two extensions are always enabled as they were supported + * by QEMU before they were added as extensions in the ISA. + */ + if (!strcmp(edata->name, "zicntr") || + !strcmp(edata->name, "zihpm")) { + continue; + } + isa_ext_update_enabled(cpu, edata->ext_enable_offset, false); #ifndef CONFIG_USER_ONLY warn_report("disabling %s extension for hart 0x" TARGET_FMT_lx diff --git a/target/s390x/tcg/translate.c b/target/s390x/tcg/translate.c index 62ab2be8b1..8df00b7df9 100644 --- a/target/s390x/tcg/translate.c +++ b/target/s390x/tcg/translate.c @@ -3221,6 +3221,7 @@ static DisasJumpType op_mov2e(DisasContext *s, DisasOps *o) { int b2 = get_field(s, b2); TCGv ar1 = tcg_temp_new_i64(); + int r1 = get_field(s, r1); o->out = o->in2; o->in2 = NULL; @@ -3244,7 +3245,7 @@ static DisasJumpType op_mov2e(DisasContext *s, DisasOps *o) break; } - tcg_gen_st32_i64(ar1, tcg_env, offsetof(CPUS390XState, aregs[1])); + tcg_gen_st32_i64(ar1, tcg_env, offsetof(CPUS390XState, aregs[r1])); return DISAS_NEXT; } diff --git a/target/sh4/cpu.h b/target/sh4/cpu.h index 360eac1fbe..031dc0b457 100644 --- a/target/sh4/cpu.h +++ b/target/sh4/cpu.h @@ -107,19 +107,19 @@ TB_FLAG_GUSA_MASK) typedef struct tlb_t { - uint32_t vpn; /* virtual page number */ - uint32_t ppn; /* physical page number */ - uint32_t size; /* mapped page size in bytes */ - uint8_t asid; /* address space identifier */ - uint8_t v:1; /* validity */ - uint8_t sz:2; /* page size */ - uint8_t sh:1; /* share status */ - uint8_t c:1; /* cacheability */ - uint8_t pr:2; /* protection key */ - uint8_t d:1; /* dirty */ - uint8_t wt:1; /* write through */ - uint8_t sa:3; /* space attribute (PCMCIA) */ - uint8_t tc:1; /* timing control */ + uint32_t vpn; /* virtual page number */ + uint32_t ppn; /* physical page number */ + uint32_t size; /* mapped page size in bytes */ + uint8_t asid; /* address space identifier */ + uint8_t v:1; /* validity */ + uint8_t sz:2; /* page size */ + uint8_t sh:1; /* share status */ + uint8_t c:1; /* cacheability */ + uint8_t pr:2; /* protection key */ + uint8_t d:1; /* dirty */ + uint8_t wt:1; /* write through */ + uint8_t sa:3; /* space attribute (PCMCIA) */ + uint8_t tc:1; /* timing control */ } tlb_t; #define UTLB_SIZE 64 @@ -139,44 +139,44 @@ typedef struct memory_content { } memory_content; typedef struct CPUArchState { - uint32_t flags; /* general execution flags */ - uint32_t gregs[24]; /* general registers */ - float32 fregs[32]; /* floating point registers */ + uint32_t flags; /* general execution flags */ + uint32_t gregs[24]; /* general registers */ + float32 fregs[32]; /* floating point registers */ uint32_t sr; /* status register (with T split out) */ uint32_t sr_m; /* M bit of status register */ uint32_t sr_q; /* Q bit of status register */ uint32_t sr_t; /* T bit of status register */ - uint32_t ssr; /* saved status register */ - uint32_t spc; /* saved program counter */ - uint32_t gbr; /* global base register */ - uint32_t vbr; /* vector base register */ - uint32_t sgr; /* saved global register 15 */ - uint32_t dbr; /* debug base register */ - uint32_t pc; /* program counter */ + uint32_t ssr; /* saved status register */ + uint32_t spc; /* saved program counter */ + uint32_t gbr; /* global base register */ + uint32_t vbr; /* vector base register */ + uint32_t sgr; /* saved global register 15 */ + uint32_t dbr; /* debug base register */ + uint32_t pc; /* program counter */ uint32_t delayed_pc; /* target of delayed branch */ uint32_t delayed_cond; /* condition of delayed branch */ - uint32_t mach; /* multiply and accumulate high */ - uint32_t macl; /* multiply and accumulate low */ - uint32_t pr; /* procedure register */ - uint32_t fpscr; /* floating point status/control register */ - uint32_t fpul; /* floating point communication register */ + uint32_t mach; /* multiply and accumulate high */ + uint32_t macl; /* multiply and accumulate low */ + uint32_t pr; /* procedure register */ + uint32_t fpscr; /* floating point status/control register */ + uint32_t fpul; /* floating point communication register */ /* float point status register */ float_status fp_status; /* Those belong to the specific unit (SH7750) but are handled here */ - uint32_t mmucr; /* MMU control register */ - uint32_t pteh; /* page table entry high register */ - uint32_t ptel; /* page table entry low register */ - uint32_t ptea; /* page table entry assistance register */ + uint32_t mmucr; /* MMU control register */ + uint32_t pteh; /* page table entry high register */ + uint32_t ptel; /* page table entry low register */ + uint32_t ptea; /* page table entry assistance register */ uint32_t ttb; /* translation table base register */ - uint32_t tea; /* TLB exception address register */ - uint32_t tra; /* TRAPA exception register */ - uint32_t expevt; /* exception event register */ - uint32_t intevt; /* interrupt event register */ + uint32_t tea; /* TLB exception address register */ + uint32_t tra; /* TRAPA exception register */ + uint32_t expevt; /* exception event register */ + uint32_t intevt; /* interrupt event register */ - tlb_t itlb[ITLB_SIZE]; /* instruction translation table */ - tlb_t utlb[UTLB_SIZE]; /* unified translation table */ + tlb_t itlb[ITLB_SIZE]; /* instruction translation table */ + tlb_t utlb[UTLB_SIZE]; /* unified translation table */ /* LDST = LOCK_ADDR != -1. */ uint32_t lock_addr; @@ -186,13 +186,13 @@ typedef struct CPUArchState { struct {} end_reset_fields; /* Fields from here on are preserved over CPU reset. */ - int id; /* CPU model */ + int id; /* CPU model */ /* The features that we should emulate. See sh_features above. */ uint32_t features; void *intc_handle; - int in_sleep; /* SR_BL ignored during sleep */ + int in_sleep; /* SR_BL ignored during sleep */ memory_content *movcal_backup; memory_content **movcal_backup_tail; } CPUSH4State; diff --git a/target/sh4/helper.c b/target/sh4/helper.c index e02e7af607..5a6f653c12 100644 --- a/target/sh4/helper.c +++ b/target/sh4/helper.c @@ -84,60 +84,60 @@ void superh_cpu_do_interrupt(CPUState *cs) if (do_irq) { irq_vector = sh_intc_get_pending_vector(env->intc_handle, - (env->sr >> 4) & 0xf); + (env->sr >> 4) & 0xf); if (irq_vector == -1) { return; /* masked */ - } + } } if (qemu_loglevel_mask(CPU_LOG_INT)) { - const char *expname; + const char *expname; switch (cs->exception_index) { - case 0x0e0: - expname = "addr_error"; - break; - case 0x040: - expname = "tlb_miss"; - break; - case 0x0a0: - expname = "tlb_violation"; - break; - case 0x180: - expname = "illegal_instruction"; - break; - case 0x1a0: - expname = "slot_illegal_instruction"; - break; - case 0x800: - expname = "fpu_disable"; - break; - case 0x820: - expname = "slot_fpu"; - break; - case 0x100: - expname = "data_write"; - break; - case 0x060: - expname = "dtlb_miss_write"; - break; - case 0x0c0: - expname = "dtlb_violation_write"; - break; - case 0x120: - expname = "fpu_exception"; - break; - case 0x080: - expname = "initial_page_write"; - break; - case 0x160: - expname = "trapa"; - break; - default: + case 0x0e0: + expname = "addr_error"; + break; + case 0x040: + expname = "tlb_miss"; + break; + case 0x0a0: + expname = "tlb_violation"; + break; + case 0x180: + expname = "illegal_instruction"; + break; + case 0x1a0: + expname = "slot_illegal_instruction"; + break; + case 0x800: + expname = "fpu_disable"; + break; + case 0x820: + expname = "slot_fpu"; + break; + case 0x100: + expname = "data_write"; + break; + case 0x060: + expname = "dtlb_miss_write"; + break; + case 0x0c0: + expname = "dtlb_violation_write"; + break; + case 0x120: + expname = "fpu_exception"; + break; + case 0x080: + expname = "initial_page_write"; + break; + case 0x160: + expname = "trapa"; + break; + default: expname = do_irq ? "interrupt" : "???"; break; - } - qemu_log("exception 0x%03x [%s] raised\n", - irq_vector, expname); + } + qemu_log("exception 0x%03x [%s] raised\n", + irq_vector, expname); log_cpu_state(cs, 0); } @@ -149,8 +149,8 @@ void superh_cpu_do_interrupt(CPUState *cs) if (env->flags & TB_FLAG_DELAY_SLOT_MASK) { /* Branch instruction should be executed again before delay slot. */ - env->spc -= 2; - /* Clear flags for exception/interrupt routine. */ + env->spc -= 2; + /* Clear flags for exception/interrupt routine. */ env->flags &= ~TB_FLAG_DELAY_SLOT_MASK; } @@ -191,19 +191,19 @@ static void update_itlb_use(CPUSH4State * env, int itlbnb) switch (itlbnb) { case 0: - and_mask = 0x1f; - break; + and_mask = 0x1f; + break; case 1: - and_mask = 0xe7; - or_mask = 0x80; - break; + and_mask = 0xe7; + or_mask = 0x80; + break; case 2: - and_mask = 0xfb; - or_mask = 0x50; - break; + and_mask = 0xfb; + or_mask = 0x50; + break; case 3: - or_mask = 0x2c; - break; + or_mask = 0x2c; + break; } env->mmucr &= (and_mask << 24) | 0x00ffffff; @@ -213,16 +213,16 @@ static void update_itlb_use(CPUSH4State * env, int itlbnb) static int itlb_replacement(CPUSH4State * env) { if ((env->mmucr & 0xe0000000) == 0xe0000000) { - return 0; + return 0; } if ((env->mmucr & 0x98000000) == 0x18000000) { - return 1; + return 1; } if ((env->mmucr & 0x54000000) == 0x04000000) { - return 2; + return 2; } if ((env->mmucr & 0x2c000000) == 0x00000000) { - return 3; + return 3; } cpu_abort(env_cpu(env), "Unhandled itlb_replacement"); } @@ -231,7 +231,7 @@ static int itlb_replacement(CPUSH4State * env) Return entry, MMU_DTLB_MISS or MMU_DTLB_MULTIPLE */ static int find_tlb_entry(CPUSH4State * env, target_ulong address, - tlb_t * entries, uint8_t nbtlb, int use_asid) + tlb_t * entries, uint8_t nbtlb, int use_asid) { int match = MMU_DTLB_MISS; uint32_t start, end; @@ -241,17 +241,17 @@ static int find_tlb_entry(CPUSH4State * env, target_ulong address, asid = env->pteh & 0xff; for (i = 0; i < nbtlb; i++) { - if (!entries[i].v) - continue; /* Invalid entry */ - if (!entries[i].sh && use_asid && entries[i].asid != asid) - continue; /* Bad ASID */ - start = (entries[i].vpn << 10) & ~(entries[i].size - 1); - end = start + entries[i].size - 1; - if (address >= start && address <= end) { /* Match */ - if (match != MMU_DTLB_MISS) - return MMU_DTLB_MULTIPLE; /* Multiple match */ - match = i; - } + if (!entries[i].v) + continue; /* Invalid entry */ + if (!entries[i].sh && use_asid && entries[i].asid != asid) + continue; /* Bad ASID */ + start = (entries[i].vpn << 10) & ~(entries[i].size - 1); + end = start + entries[i].size - 1; + if (address >= start && address <= end) { /* Match */ + if (match != MMU_DTLB_MISS) + return MMU_DTLB_MULTIPLE; /* Multiple match */ + match = i; + } } return match; } @@ -265,7 +265,7 @@ static void increment_urc(CPUSH4State * env) urc = ((env->mmucr) >> 10) & 0x3f; urc++; if ((urb > 0 && urc > urb) || urc > (UTLB_SIZE - 1)) - urc = 0; + urc = 0; env->mmucr = (env->mmucr & 0xffff03ff) | (urc << 10); } @@ -297,11 +297,11 @@ static int find_itlb_entry(CPUSH4State * env, target_ulong address, e = find_tlb_entry(env, address, env->itlb, ITLB_SIZE, use_asid); if (e == MMU_DTLB_MULTIPLE) { - e = MMU_ITLB_MULTIPLE; + e = MMU_ITLB_MULTIPLE; } else if (e == MMU_DTLB_MISS) { - e = MMU_ITLB_MISS; + e = MMU_ITLB_MISS; } else if (e >= 0) { - update_itlb_use(env, e); + update_itlb_use(env, e); } return e; } @@ -518,7 +518,7 @@ uint32_t cpu_sh4_read_mmaped_itlb_addr(CPUSH4State *s, } void cpu_sh4_write_mmaped_itlb_addr(CPUSH4State *s, hwaddr addr, - uint32_t mem_value) + uint32_t mem_value) { uint32_t vpn = (mem_value & 0xfffffc00) >> 10; uint8_t v = (uint8_t)((mem_value & 0x00000100) >> 8); @@ -601,7 +601,7 @@ uint32_t cpu_sh4_read_mmaped_utlb_addr(CPUSH4State *s, } void cpu_sh4_write_mmaped_utlb_addr(CPUSH4State *s, hwaddr addr, - uint32_t mem_value) + uint32_t mem_value) { int associate = addr & 0x0000080; uint32_t vpn = (mem_value & 0xfffffc00) >> 10; @@ -612,48 +612,48 @@ void cpu_sh4_write_mmaped_utlb_addr(CPUSH4State *s, hwaddr addr, if (associate) { int i; - tlb_t * utlb_match_entry = NULL; - int needs_tlb_flush = 0; + tlb_t * utlb_match_entry = NULL; + int needs_tlb_flush = 0; - /* search UTLB */ - for (i = 0; i < UTLB_SIZE; i++) { + /* search UTLB */ + for (i = 0; i < UTLB_SIZE; i++) { tlb_t * entry = &s->utlb[i]; if (!entry->v) - continue; + continue; if (entry->vpn == vpn && (!use_asid || entry->asid == asid || entry->sh)) { - if (utlb_match_entry) { + if (utlb_match_entry) { CPUState *cs = env_cpu(s); - /* Multiple TLB Exception */ + /* Multiple TLB Exception */ cs->exception_index = 0x140; - s->tea = addr; - break; - } - if (entry->v && !v) - needs_tlb_flush = 1; - entry->v = v; - entry->d = d; - utlb_match_entry = entry; - } - increment_urc(s); /* per utlb access */ - } + s->tea = addr; + break; + } + if (entry->v && !v) + needs_tlb_flush = 1; + entry->v = v; + entry->d = d; + utlb_match_entry = entry; + } + increment_urc(s); /* per utlb access */ + } - /* search ITLB */ - for (i = 0; i < ITLB_SIZE; i++) { + /* search ITLB */ + for (i = 0; i < ITLB_SIZE; i++) { tlb_t * entry = &s->itlb[i]; if (entry->vpn == vpn && (!use_asid || entry->asid == asid || entry->sh)) { - if (entry->v && !v) - needs_tlb_flush = 1; - if (utlb_match_entry) - *entry = *utlb_match_entry; - else - entry->v = v; - break; - } - } + if (entry->v && !v) + needs_tlb_flush = 1; + if (utlb_match_entry) + *entry = *utlb_match_entry; + else + entry->v = v; + break; + } + } if (needs_tlb_flush) { tlb_flush_page(env_cpu(s), vpn << 10); @@ -661,18 +661,18 @@ void cpu_sh4_write_mmaped_utlb_addr(CPUSH4State *s, hwaddr addr, } else { int index = (addr & 0x00003f00) >> 8; tlb_t * entry = &s->utlb[index]; - if (entry->v) { + if (entry->v) { CPUState *cs = env_cpu(s); - /* Overwriting valid entry in utlb. */ + /* Overwriting valid entry in utlb. */ target_ulong address = entry->vpn << 10; tlb_flush_page(cs, address); - } - entry->asid = asid; - entry->vpn = vpn; - entry->d = d; - entry->v = v; - increment_urc(s); + } + entry->asid = asid; + entry->vpn = vpn; + entry->d = d; + entry->v = v; + increment_urc(s); } } diff --git a/target/sh4/op_helper.c b/target/sh4/op_helper.c index ada41ba0a2..54d390fe1f 100644 --- a/target/sh4/op_helper.c +++ b/target/sh4/op_helper.c @@ -114,12 +114,12 @@ void helper_movcal(CPUSH4State *env, uint32_t address, uint32_t value) { memory_content *r = g_new(memory_content, 1); - r->address = address; - r->value = value; - r->next = NULL; + r->address = address; + r->value = value; + r->next = NULL; - *(env->movcal_backup_tail) = r; - env->movcal_backup_tail = &(r->next); + *(env->movcal_backup_tail) = r; + env->movcal_backup_tail = &(r->next); } } @@ -129,12 +129,12 @@ void helper_discard_movcal_backup(CPUSH4State *env) while(current) { - memory_content *next = current->next; + memory_content *next = current->next; g_free(current); - env->movcal_backup = current = next; - if (current == NULL) - env->movcal_backup_tail = &(env->movcal_backup); - } + env->movcal_backup = current = next; + if (current == NULL) + env->movcal_backup_tail = &(env->movcal_backup); + } } void helper_ocbi(CPUSH4State *env, uint32_t address) @@ -142,21 +142,21 @@ void helper_ocbi(CPUSH4State *env, uint32_t address) memory_content **current = &(env->movcal_backup); while (*current) { - uint32_t a = (*current)->address; - if ((a & ~0x1F) == (address & ~0x1F)) - { - memory_content *next = (*current)->next; + uint32_t a = (*current)->address; + if ((a & ~0x1F) == (address & ~0x1F)) + { + memory_content *next = (*current)->next; cpu_stl_data(env, a, (*current)->value); - - if (next == NULL) - { - env->movcal_backup_tail = current; - } + + if (next == NULL) + { + env->movcal_backup_tail = current; + } g_free(*current); - *current = next; - break; - } + *current = next; + break; + } } } @@ -169,10 +169,10 @@ void helper_macl(CPUSH4State *env, uint32_t arg0, uint32_t arg1) env->mach = (res >> 32) & 0xffffffff; env->macl = res & 0xffffffff; if (env->sr & (1u << SR_S)) { - if (res < 0) - env->mach |= 0xffff0000; - else - env->mach &= 0x00007fff; + if (res < 0) + env->mach |= 0xffff0000; + else + env->mach &= 0x00007fff; } } @@ -185,13 +185,13 @@ void helper_macw(CPUSH4State *env, uint32_t arg0, uint32_t arg1) env->mach = (res >> 32) & 0xffffffff; env->macl = res & 0xffffffff; if (env->sr & (1u << SR_S)) { - if (res < -0x80000000) { - env->mach = 1; - env->macl = 0x80000000; - } else if (res > 0x000000007fffffff) { - env->mach = 1; - env->macl = 0x7fffffff; - } + if (res < -0x80000000) { + env->mach = 1; + env->macl = 0x80000000; + } else if (res > 0x000000007fffffff) { + env->mach = 1; + env->macl = 0x7fffffff; + } } } @@ -199,9 +199,9 @@ void helper_ld_fpscr(CPUSH4State *env, uint32_t val) { env->fpscr = val & FPSCR_MASK; if ((val & FPSCR_RM_MASK) == FPSCR_RM_ZERO) { - set_float_rounding_mode(float_round_to_zero, &env->fp_status); + set_float_rounding_mode(float_round_to_zero, &env->fp_status); } else { - set_float_rounding_mode(float_round_nearest_even, &env->fp_status); + set_float_rounding_mode(float_round_nearest_even, &env->fp_status); } set_flush_to_zero((val & FPSCR_DN) != 0, &env->fp_status); } diff --git a/target/sh4/translate.c b/target/sh4/translate.c index 220a06bdce..81f825f125 100644 --- a/target/sh4/translate.c +++ b/target/sh4/translate.c @@ -136,10 +136,10 @@ void sh4_translate_init(void) offsetof(CPUSH4State, fpul), "FPUL"); cpu_flags = tcg_global_mem_new_i32(tcg_env, - offsetof(CPUSH4State, flags), "_flags_"); + offsetof(CPUSH4State, flags), "_flags_"); cpu_delayed_pc = tcg_global_mem_new_i32(tcg_env, - offsetof(CPUSH4State, delayed_pc), - "_delayed_pc_"); + offsetof(CPUSH4State, delayed_pc), + "_delayed_pc_"); cpu_delayed_cond = tcg_global_mem_new_i32(tcg_env, offsetof(CPUSH4State, delayed_cond), @@ -252,9 +252,9 @@ static void gen_goto_tb(DisasContext *ctx, int n, target_ulong dest) static void gen_jump(DisasContext * ctx) { if (ctx->delayed_pc == -1) { - /* Target is not statically known, it comes necessarily from a - delayed jump as immediate jump are conditinal jumps */ - tcg_gen_mov_i32(cpu_pc, cpu_delayed_pc); + /* Target is not statically known, it comes necessarily from a + delayed jump as immediate jump are conditinal jumps */ + tcg_gen_mov_i32(cpu_pc, cpu_delayed_pc); tcg_gen_discard_i32(cpu_delayed_pc); if (use_exit_tb(ctx)) { tcg_gen_exit_tb(NULL, 0); @@ -263,7 +263,7 @@ static void gen_jump(DisasContext * ctx) } ctx->base.is_jmp = DISAS_NORETURN; } else { - gen_goto_tb(ctx, 0, ctx->delayed_pc); + gen_goto_tb(ctx, 0, ctx->delayed_pc); } } @@ -411,103 +411,103 @@ static void _decode_opc(DisasContext * ctx) TB, or if we already saw movca.l in this TB and did not flush stores yet. */ if (ctx->has_movcal) - { - int opcode = ctx->opcode & 0xf0ff; - if (opcode != 0x0093 /* ocbi */ - && opcode != 0x00c3 /* movca.l */) - { - gen_helper_discard_movcal_backup(tcg_env); - ctx->has_movcal = 0; - } - } + { + int opcode = ctx->opcode & 0xf0ff; + if (opcode != 0x0093 /* ocbi */ + && opcode != 0x00c3 /* movca.l */) + { + gen_helper_discard_movcal_backup(tcg_env); + ctx->has_movcal = 0; + } + } #if 0 fprintf(stderr, "Translating opcode 0x%04x\n", ctx->opcode); #endif switch (ctx->opcode) { - case 0x0019: /* div0u */ + case 0x0019: /* div0u */ tcg_gen_movi_i32(cpu_sr_m, 0); tcg_gen_movi_i32(cpu_sr_q, 0); tcg_gen_movi_i32(cpu_sr_t, 0); - return; - case 0x000b: /* rts */ - CHECK_NOT_DELAY_SLOT - tcg_gen_mov_i32(cpu_delayed_pc, cpu_pr); + return; + case 0x000b: /* rts */ + CHECK_NOT_DELAY_SLOT + tcg_gen_mov_i32(cpu_delayed_pc, cpu_pr); ctx->envflags |= TB_FLAG_DELAY_SLOT; - ctx->delayed_pc = (uint32_t) - 1; - return; - case 0x0028: /* clrmac */ - tcg_gen_movi_i32(cpu_mach, 0); - tcg_gen_movi_i32(cpu_macl, 0); - return; - case 0x0048: /* clrs */ + ctx->delayed_pc = (uint32_t) - 1; + return; + case 0x0028: /* clrmac */ + tcg_gen_movi_i32(cpu_mach, 0); + tcg_gen_movi_i32(cpu_macl, 0); + return; + case 0x0048: /* clrs */ tcg_gen_andi_i32(cpu_sr, cpu_sr, ~(1u << SR_S)); - return; - case 0x0008: /* clrt */ + return; + case 0x0008: /* clrt */ tcg_gen_movi_i32(cpu_sr_t, 0); - return; - case 0x0038: /* ldtlb */ - CHECK_PRIVILEGED + return; + case 0x0038: /* ldtlb */ + CHECK_PRIVILEGED gen_helper_ldtlb(tcg_env); - return; - case 0x002b: /* rte */ - CHECK_PRIVILEGED - CHECK_NOT_DELAY_SLOT + return; + case 0x002b: /* rte */ + CHECK_PRIVILEGED + CHECK_NOT_DELAY_SLOT gen_write_sr(cpu_ssr); - tcg_gen_mov_i32(cpu_delayed_pc, cpu_spc); + tcg_gen_mov_i32(cpu_delayed_pc, cpu_spc); ctx->envflags |= TB_FLAG_DELAY_SLOT_RTE; - ctx->delayed_pc = (uint32_t) - 1; + ctx->delayed_pc = (uint32_t) - 1; ctx->base.is_jmp = DISAS_STOP; - return; - case 0x0058: /* sets */ + return; + case 0x0058: /* sets */ tcg_gen_ori_i32(cpu_sr, cpu_sr, (1u << SR_S)); - return; - case 0x0018: /* sett */ + return; + case 0x0018: /* sett */ tcg_gen_movi_i32(cpu_sr_t, 1); - return; - case 0xfbfd: /* frchg */ + return; + case 0xfbfd: /* frchg */ CHECK_FPSCR_PR_0 - tcg_gen_xori_i32(cpu_fpscr, cpu_fpscr, FPSCR_FR); + tcg_gen_xori_i32(cpu_fpscr, cpu_fpscr, FPSCR_FR); ctx->base.is_jmp = DISAS_STOP; - return; - case 0xf3fd: /* fschg */ + return; + case 0xf3fd: /* fschg */ CHECK_FPSCR_PR_0 tcg_gen_xori_i32(cpu_fpscr, cpu_fpscr, FPSCR_SZ); ctx->base.is_jmp = DISAS_STOP; - return; - case 0xf7fd: /* fpchg */ + return; + case 0xf7fd: /* fpchg */ CHECK_SH4A tcg_gen_xori_i32(cpu_fpscr, cpu_fpscr, FPSCR_PR); ctx->base.is_jmp = DISAS_STOP; return; - case 0x0009: /* nop */ - return; - case 0x001b: /* sleep */ - CHECK_PRIVILEGED + case 0x0009: /* nop */ + return; + case 0x001b: /* sleep */ + CHECK_PRIVILEGED tcg_gen_movi_i32(cpu_pc, ctx->base.pc_next + 2); gen_helper_sleep(tcg_env); - return; + return; } switch (ctx->opcode & 0xf000) { - case 0x1000: /* mov.l Rm,@(disp,Rn) */ - { - TCGv addr = tcg_temp_new(); - tcg_gen_addi_i32(addr, REG(B11_8), B3_0 * 4); + case 0x1000: /* mov.l Rm,@(disp,Rn) */ + { + TCGv addr = tcg_temp_new(); + tcg_gen_addi_i32(addr, REG(B11_8), B3_0 * 4); tcg_gen_qemu_st_i32(REG(B7_4), addr, ctx->memidx, MO_TEUL | UNALIGN(ctx)); - } - return; - case 0x5000: /* mov.l @(disp,Rm),Rn */ - { - TCGv addr = tcg_temp_new(); - tcg_gen_addi_i32(addr, REG(B7_4), B3_0 * 4); + } + return; + case 0x5000: /* mov.l @(disp,Rm),Rn */ + { + TCGv addr = tcg_temp_new(); + tcg_gen_addi_i32(addr, REG(B7_4), B3_0 * 4); tcg_gen_qemu_ld_i32(REG(B11_8), addr, ctx->memidx, MO_TESL | UNALIGN(ctx)); - } - return; - case 0xe000: /* mov #imm,Rn */ + } + return; + case 0xe000: /* mov #imm,Rn */ #ifdef CONFIG_USER_ONLY /* * Detect the start of a gUSA region (mov #-n, r15). @@ -521,178 +521,178 @@ static void _decode_opc(DisasContext * ctx) ctx->base.is_jmp = DISAS_STOP; } #endif - tcg_gen_movi_i32(REG(B11_8), B7_0s); - return; - case 0x9000: /* mov.w @(disp,PC),Rn */ - { + tcg_gen_movi_i32(REG(B11_8), B7_0s); + return; + case 0x9000: /* mov.w @(disp,PC),Rn */ + { TCGv addr = tcg_constant_i32(ctx->base.pc_next + 4 + B7_0 * 2); tcg_gen_qemu_ld_i32(REG(B11_8), addr, ctx->memidx, MO_TESW | MO_ALIGN); - } - return; - case 0xd000: /* mov.l @(disp,PC),Rn */ - { + } + return; + case 0xd000: /* mov.l @(disp,PC),Rn */ + { TCGv addr = tcg_constant_i32((ctx->base.pc_next + 4 + B7_0 * 4) & ~3); tcg_gen_qemu_ld_i32(REG(B11_8), addr, ctx->memidx, MO_TESL | MO_ALIGN); - } - return; - case 0x7000: /* add #imm,Rn */ - tcg_gen_addi_i32(REG(B11_8), REG(B11_8), B7_0s); - return; - case 0xa000: /* bra disp */ - CHECK_NOT_DELAY_SLOT + } + return; + case 0x7000: /* add #imm,Rn */ + tcg_gen_addi_i32(REG(B11_8), REG(B11_8), B7_0s); + return; + case 0xa000: /* bra disp */ + CHECK_NOT_DELAY_SLOT ctx->delayed_pc = ctx->base.pc_next + 4 + B11_0s * 2; ctx->envflags |= TB_FLAG_DELAY_SLOT; - return; - case 0xb000: /* bsr disp */ - CHECK_NOT_DELAY_SLOT + return; + case 0xb000: /* bsr disp */ + CHECK_NOT_DELAY_SLOT tcg_gen_movi_i32(cpu_pr, ctx->base.pc_next + 4); ctx->delayed_pc = ctx->base.pc_next + 4 + B11_0s * 2; ctx->envflags |= TB_FLAG_DELAY_SLOT; - return; + return; } switch (ctx->opcode & 0xf00f) { - case 0x6003: /* mov Rm,Rn */ - tcg_gen_mov_i32(REG(B11_8), REG(B7_4)); - return; - case 0x2000: /* mov.b Rm,@Rn */ + case 0x6003: /* mov Rm,Rn */ + tcg_gen_mov_i32(REG(B11_8), REG(B7_4)); + return; + case 0x2000: /* mov.b Rm,@Rn */ tcg_gen_qemu_st_i32(REG(B7_4), REG(B11_8), ctx->memidx, MO_UB); - return; - case 0x2001: /* mov.w Rm,@Rn */ + return; + case 0x2001: /* mov.w Rm,@Rn */ tcg_gen_qemu_st_i32(REG(B7_4), REG(B11_8), ctx->memidx, MO_TEUW | UNALIGN(ctx)); - return; - case 0x2002: /* mov.l Rm,@Rn */ + return; + case 0x2002: /* mov.l Rm,@Rn */ tcg_gen_qemu_st_i32(REG(B7_4), REG(B11_8), ctx->memidx, MO_TEUL | UNALIGN(ctx)); - return; - case 0x6000: /* mov.b @Rm,Rn */ + return; + case 0x6000: /* mov.b @Rm,Rn */ tcg_gen_qemu_ld_i32(REG(B11_8), REG(B7_4), ctx->memidx, MO_SB); - return; - case 0x6001: /* mov.w @Rm,Rn */ + return; + case 0x6001: /* mov.w @Rm,Rn */ tcg_gen_qemu_ld_i32(REG(B11_8), REG(B7_4), ctx->memidx, MO_TESW | UNALIGN(ctx)); - return; - case 0x6002: /* mov.l @Rm,Rn */ + return; + case 0x6002: /* mov.l @Rm,Rn */ tcg_gen_qemu_ld_i32(REG(B11_8), REG(B7_4), ctx->memidx, MO_TESL | UNALIGN(ctx)); - return; - case 0x2004: /* mov.b Rm,@-Rn */ - { - TCGv addr = tcg_temp_new(); - tcg_gen_subi_i32(addr, REG(B11_8), 1); + return; + case 0x2004: /* mov.b Rm,@-Rn */ + { + TCGv addr = tcg_temp_new(); + tcg_gen_subi_i32(addr, REG(B11_8), 1); /* might cause re-execution */ tcg_gen_qemu_st_i32(REG(B7_4), addr, ctx->memidx, MO_UB); - tcg_gen_mov_i32(REG(B11_8), addr); /* modify register status */ - } - return; - case 0x2005: /* mov.w Rm,@-Rn */ - { - TCGv addr = tcg_temp_new(); - tcg_gen_subi_i32(addr, REG(B11_8), 2); + tcg_gen_mov_i32(REG(B11_8), addr); /* modify register status */ + } + return; + case 0x2005: /* mov.w Rm,@-Rn */ + { + TCGv addr = tcg_temp_new(); + tcg_gen_subi_i32(addr, REG(B11_8), 2); tcg_gen_qemu_st_i32(REG(B7_4), addr, ctx->memidx, MO_TEUW | UNALIGN(ctx)); - tcg_gen_mov_i32(REG(B11_8), addr); - } - return; - case 0x2006: /* mov.l Rm,@-Rn */ - { - TCGv addr = tcg_temp_new(); - tcg_gen_subi_i32(addr, REG(B11_8), 4); + tcg_gen_mov_i32(REG(B11_8), addr); + } + return; + case 0x2006: /* mov.l Rm,@-Rn */ + { + TCGv addr = tcg_temp_new(); + tcg_gen_subi_i32(addr, REG(B11_8), 4); tcg_gen_qemu_st_i32(REG(B7_4), addr, ctx->memidx, MO_TEUL | UNALIGN(ctx)); - tcg_gen_mov_i32(REG(B11_8), addr); - } - return; - case 0x6004: /* mov.b @Rm+,Rn */ + tcg_gen_mov_i32(REG(B11_8), addr); + } + return; + case 0x6004: /* mov.b @Rm+,Rn */ tcg_gen_qemu_ld_i32(REG(B11_8), REG(B7_4), ctx->memidx, MO_SB); - if ( B11_8 != B7_4 ) - tcg_gen_addi_i32(REG(B7_4), REG(B7_4), 1); - return; - case 0x6005: /* mov.w @Rm+,Rn */ + if ( B11_8 != B7_4 ) + tcg_gen_addi_i32(REG(B7_4), REG(B7_4), 1); + return; + case 0x6005: /* mov.w @Rm+,Rn */ tcg_gen_qemu_ld_i32(REG(B11_8), REG(B7_4), ctx->memidx, MO_TESW | UNALIGN(ctx)); - if ( B11_8 != B7_4 ) - tcg_gen_addi_i32(REG(B7_4), REG(B7_4), 2); - return; - case 0x6006: /* mov.l @Rm+,Rn */ + if ( B11_8 != B7_4 ) + tcg_gen_addi_i32(REG(B7_4), REG(B7_4), 2); + return; + case 0x6006: /* mov.l @Rm+,Rn */ tcg_gen_qemu_ld_i32(REG(B11_8), REG(B7_4), ctx->memidx, MO_TESL | UNALIGN(ctx)); - if ( B11_8 != B7_4 ) - tcg_gen_addi_i32(REG(B7_4), REG(B7_4), 4); - return; - case 0x0004: /* mov.b Rm,@(R0,Rn) */ - { - TCGv addr = tcg_temp_new(); - tcg_gen_add_i32(addr, REG(B11_8), REG(0)); + if ( B11_8 != B7_4 ) + tcg_gen_addi_i32(REG(B7_4), REG(B7_4), 4); + return; + case 0x0004: /* mov.b Rm,@(R0,Rn) */ + { + TCGv addr = tcg_temp_new(); + tcg_gen_add_i32(addr, REG(B11_8), REG(0)); tcg_gen_qemu_st_i32(REG(B7_4), addr, ctx->memidx, MO_UB); - } - return; - case 0x0005: /* mov.w Rm,@(R0,Rn) */ - { - TCGv addr = tcg_temp_new(); - tcg_gen_add_i32(addr, REG(B11_8), REG(0)); + } + return; + case 0x0005: /* mov.w Rm,@(R0,Rn) */ + { + TCGv addr = tcg_temp_new(); + tcg_gen_add_i32(addr, REG(B11_8), REG(0)); tcg_gen_qemu_st_i32(REG(B7_4), addr, ctx->memidx, MO_TEUW | UNALIGN(ctx)); - } - return; - case 0x0006: /* mov.l Rm,@(R0,Rn) */ - { - TCGv addr = tcg_temp_new(); - tcg_gen_add_i32(addr, REG(B11_8), REG(0)); + } + return; + case 0x0006: /* mov.l Rm,@(R0,Rn) */ + { + TCGv addr = tcg_temp_new(); + tcg_gen_add_i32(addr, REG(B11_8), REG(0)); tcg_gen_qemu_st_i32(REG(B7_4), addr, ctx->memidx, MO_TEUL | UNALIGN(ctx)); - } - return; - case 0x000c: /* mov.b @(R0,Rm),Rn */ - { - TCGv addr = tcg_temp_new(); - tcg_gen_add_i32(addr, REG(B7_4), REG(0)); + } + return; + case 0x000c: /* mov.b @(R0,Rm),Rn */ + { + TCGv addr = tcg_temp_new(); + tcg_gen_add_i32(addr, REG(B7_4), REG(0)); tcg_gen_qemu_ld_i32(REG(B11_8), addr, ctx->memidx, MO_SB); - } - return; - case 0x000d: /* mov.w @(R0,Rm),Rn */ - { - TCGv addr = tcg_temp_new(); - tcg_gen_add_i32(addr, REG(B7_4), REG(0)); + } + return; + case 0x000d: /* mov.w @(R0,Rm),Rn */ + { + TCGv addr = tcg_temp_new(); + tcg_gen_add_i32(addr, REG(B7_4), REG(0)); tcg_gen_qemu_ld_i32(REG(B11_8), addr, ctx->memidx, MO_TESW | UNALIGN(ctx)); - } - return; - case 0x000e: /* mov.l @(R0,Rm),Rn */ - { - TCGv addr = tcg_temp_new(); - tcg_gen_add_i32(addr, REG(B7_4), REG(0)); + } + return; + case 0x000e: /* mov.l @(R0,Rm),Rn */ + { + TCGv addr = tcg_temp_new(); + tcg_gen_add_i32(addr, REG(B7_4), REG(0)); tcg_gen_qemu_ld_i32(REG(B11_8), addr, ctx->memidx, MO_TESL | UNALIGN(ctx)); - } - return; - case 0x6008: /* swap.b Rm,Rn */ - { + } + return; + case 0x6008: /* swap.b Rm,Rn */ + { TCGv low = tcg_temp_new(); tcg_gen_bswap16_i32(low, REG(B7_4), 0); tcg_gen_deposit_i32(REG(B11_8), REG(B7_4), low, 0, 16); - } - return; - case 0x6009: /* swap.w Rm,Rn */ + } + return; + case 0x6009: /* swap.w Rm,Rn */ tcg_gen_rotli_i32(REG(B11_8), REG(B7_4), 16); - return; - case 0x200d: /* xtrct Rm,Rn */ - { - TCGv high, low; - high = tcg_temp_new(); - tcg_gen_shli_i32(high, REG(B7_4), 16); - low = tcg_temp_new(); - tcg_gen_shri_i32(low, REG(B11_8), 16); - tcg_gen_or_i32(REG(B11_8), high, low); - } - return; - case 0x300c: /* add Rm,Rn */ - tcg_gen_add_i32(REG(B11_8), REG(B11_8), REG(B7_4)); - return; - case 0x300e: /* addc Rm,Rn */ + return; + case 0x200d: /* xtrct Rm,Rn */ + { + TCGv high, low; + high = tcg_temp_new(); + tcg_gen_shli_i32(high, REG(B7_4), 16); + low = tcg_temp_new(); + tcg_gen_shri_i32(low, REG(B11_8), 16); + tcg_gen_or_i32(REG(B11_8), high, low); + } + return; + case 0x300c: /* add Rm,Rn */ + tcg_gen_add_i32(REG(B11_8), REG(B11_8), REG(B7_4)); + return; + case 0x300e: /* addc Rm,Rn */ { TCGv t0, t1; t0 = tcg_constant_tl(0); @@ -701,8 +701,8 @@ static void _decode_opc(DisasContext * ctx) tcg_gen_add2_i32(REG(B11_8), cpu_sr_t, REG(B11_8), t0, t1, cpu_sr_t); } - return; - case 0x300f: /* addv Rm,Rn */ + return; + case 0x300f: /* addv Rm,Rn */ { TCGv t0, t1, t2; t0 = tcg_temp_new(); @@ -715,42 +715,42 @@ static void _decode_opc(DisasContext * ctx) tcg_gen_shri_i32(cpu_sr_t, cpu_sr_t, 31); tcg_gen_mov_i32(REG(B7_4), t0); } - return; - case 0x2009: /* and Rm,Rn */ - tcg_gen_and_i32(REG(B11_8), REG(B11_8), REG(B7_4)); - return; - case 0x3000: /* cmp/eq Rm,Rn */ + return; + case 0x2009: /* and Rm,Rn */ + tcg_gen_and_i32(REG(B11_8), REG(B11_8), REG(B7_4)); + return; + case 0x3000: /* cmp/eq Rm,Rn */ tcg_gen_setcond_i32(TCG_COND_EQ, cpu_sr_t, REG(B11_8), REG(B7_4)); - return; - case 0x3003: /* cmp/ge Rm,Rn */ + return; + case 0x3003: /* cmp/ge Rm,Rn */ tcg_gen_setcond_i32(TCG_COND_GE, cpu_sr_t, REG(B11_8), REG(B7_4)); - return; - case 0x3007: /* cmp/gt Rm,Rn */ + return; + case 0x3007: /* cmp/gt Rm,Rn */ tcg_gen_setcond_i32(TCG_COND_GT, cpu_sr_t, REG(B11_8), REG(B7_4)); - return; - case 0x3006: /* cmp/hi Rm,Rn */ + return; + case 0x3006: /* cmp/hi Rm,Rn */ tcg_gen_setcond_i32(TCG_COND_GTU, cpu_sr_t, REG(B11_8), REG(B7_4)); - return; - case 0x3002: /* cmp/hs Rm,Rn */ + return; + case 0x3002: /* cmp/hs Rm,Rn */ tcg_gen_setcond_i32(TCG_COND_GEU, cpu_sr_t, REG(B11_8), REG(B7_4)); - return; - case 0x200c: /* cmp/str Rm,Rn */ - { - TCGv cmp1 = tcg_temp_new(); - TCGv cmp2 = tcg_temp_new(); + return; + case 0x200c: /* cmp/str Rm,Rn */ + { + TCGv cmp1 = tcg_temp_new(); + TCGv cmp2 = tcg_temp_new(); tcg_gen_xor_i32(cmp2, REG(B7_4), REG(B11_8)); tcg_gen_subi_i32(cmp1, cmp2, 0x01010101); tcg_gen_andc_i32(cmp1, cmp1, cmp2); tcg_gen_andi_i32(cmp1, cmp1, 0x80808080); tcg_gen_setcondi_i32(TCG_COND_NE, cpu_sr_t, cmp1, 0); - } - return; - case 0x2007: /* div0s Rm,Rn */ + } + return; + case 0x2007: /* div0s Rm,Rn */ tcg_gen_shri_i32(cpu_sr_q, REG(B11_8), 31); /* SR_Q */ tcg_gen_shri_i32(cpu_sr_m, REG(B7_4), 31); /* SR_M */ tcg_gen_xor_i32(cpu_sr_t, cpu_sr_q, cpu_sr_m); /* SR_T */ - return; - case 0x3004: /* div1 Rm,Rn */ + return; + case 0x3004: /* div1 Rm,Rn */ { TCGv t0 = tcg_temp_new(); TCGv t1 = tcg_temp_new(); @@ -779,80 +779,80 @@ static void _decode_opc(DisasContext * ctx) tcg_gen_xori_i32(cpu_sr_t, t1, 1); tcg_gen_xor_i32(cpu_sr_q, cpu_sr_m, t1); } - return; - case 0x300d: /* dmuls.l Rm,Rn */ + return; + case 0x300d: /* dmuls.l Rm,Rn */ tcg_gen_muls2_i32(cpu_macl, cpu_mach, REG(B7_4), REG(B11_8)); - return; - case 0x3005: /* dmulu.l Rm,Rn */ + return; + case 0x3005: /* dmulu.l Rm,Rn */ tcg_gen_mulu2_i32(cpu_macl, cpu_mach, REG(B7_4), REG(B11_8)); - return; - case 0x600e: /* exts.b Rm,Rn */ - tcg_gen_ext8s_i32(REG(B11_8), REG(B7_4)); - return; - case 0x600f: /* exts.w Rm,Rn */ - tcg_gen_ext16s_i32(REG(B11_8), REG(B7_4)); - return; - case 0x600c: /* extu.b Rm,Rn */ - tcg_gen_ext8u_i32(REG(B11_8), REG(B7_4)); - return; - case 0x600d: /* extu.w Rm,Rn */ - tcg_gen_ext16u_i32(REG(B11_8), REG(B7_4)); - return; - case 0x000f: /* mac.l @Rm+,@Rn+ */ - { - TCGv arg0, arg1; - arg0 = tcg_temp_new(); + return; + case 0x600e: /* exts.b Rm,Rn */ + tcg_gen_ext8s_i32(REG(B11_8), REG(B7_4)); + return; + case 0x600f: /* exts.w Rm,Rn */ + tcg_gen_ext16s_i32(REG(B11_8), REG(B7_4)); + return; + case 0x600c: /* extu.b Rm,Rn */ + tcg_gen_ext8u_i32(REG(B11_8), REG(B7_4)); + return; + case 0x600d: /* extu.w Rm,Rn */ + tcg_gen_ext16u_i32(REG(B11_8), REG(B7_4)); + return; + case 0x000f: /* mac.l @Rm+,@Rn+ */ + { + TCGv arg0, arg1; + arg0 = tcg_temp_new(); tcg_gen_qemu_ld_i32(arg0, REG(B7_4), ctx->memidx, MO_TESL | MO_ALIGN); - arg1 = tcg_temp_new(); + arg1 = tcg_temp_new(); tcg_gen_qemu_ld_i32(arg1, REG(B11_8), ctx->memidx, MO_TESL | MO_ALIGN); gen_helper_macl(tcg_env, arg0, arg1); - tcg_gen_addi_i32(REG(B7_4), REG(B7_4), 4); - tcg_gen_addi_i32(REG(B11_8), REG(B11_8), 4); - } - return; - case 0x400f: /* mac.w @Rm+,@Rn+ */ - { - TCGv arg0, arg1; - arg0 = tcg_temp_new(); + tcg_gen_addi_i32(REG(B7_4), REG(B7_4), 4); + tcg_gen_addi_i32(REG(B11_8), REG(B11_8), 4); + } + return; + case 0x400f: /* mac.w @Rm+,@Rn+ */ + { + TCGv arg0, arg1; + arg0 = tcg_temp_new(); tcg_gen_qemu_ld_i32(arg0, REG(B7_4), ctx->memidx, MO_TESL | MO_ALIGN); - arg1 = tcg_temp_new(); + arg1 = tcg_temp_new(); tcg_gen_qemu_ld_i32(arg1, REG(B11_8), ctx->memidx, MO_TESL | MO_ALIGN); gen_helper_macw(tcg_env, arg0, arg1); - tcg_gen_addi_i32(REG(B11_8), REG(B11_8), 2); - tcg_gen_addi_i32(REG(B7_4), REG(B7_4), 2); - } - return; - case 0x0007: /* mul.l Rm,Rn */ - tcg_gen_mul_i32(cpu_macl, REG(B7_4), REG(B11_8)); - return; - case 0x200f: /* muls.w Rm,Rn */ - { - TCGv arg0, arg1; - arg0 = tcg_temp_new(); - tcg_gen_ext16s_i32(arg0, REG(B7_4)); - arg1 = tcg_temp_new(); - tcg_gen_ext16s_i32(arg1, REG(B11_8)); - tcg_gen_mul_i32(cpu_macl, arg0, arg1); - } - return; - case 0x200e: /* mulu.w Rm,Rn */ - { - TCGv arg0, arg1; - arg0 = tcg_temp_new(); - tcg_gen_ext16u_i32(arg0, REG(B7_4)); - arg1 = tcg_temp_new(); - tcg_gen_ext16u_i32(arg1, REG(B11_8)); - tcg_gen_mul_i32(cpu_macl, arg0, arg1); - } - return; - case 0x600b: /* neg Rm,Rn */ - tcg_gen_neg_i32(REG(B11_8), REG(B7_4)); - return; - case 0x600a: /* negc Rm,Rn */ + tcg_gen_addi_i32(REG(B11_8), REG(B11_8), 2); + tcg_gen_addi_i32(REG(B7_4), REG(B7_4), 2); + } + return; + case 0x0007: /* mul.l Rm,Rn */ + tcg_gen_mul_i32(cpu_macl, REG(B7_4), REG(B11_8)); + return; + case 0x200f: /* muls.w Rm,Rn */ + { + TCGv arg0, arg1; + arg0 = tcg_temp_new(); + tcg_gen_ext16s_i32(arg0, REG(B7_4)); + arg1 = tcg_temp_new(); + tcg_gen_ext16s_i32(arg1, REG(B11_8)); + tcg_gen_mul_i32(cpu_macl, arg0, arg1); + } + return; + case 0x200e: /* mulu.w Rm,Rn */ + { + TCGv arg0, arg1; + arg0 = tcg_temp_new(); + tcg_gen_ext16u_i32(arg0, REG(B7_4)); + arg1 = tcg_temp_new(); + tcg_gen_ext16u_i32(arg1, REG(B11_8)); + tcg_gen_mul_i32(cpu_macl, arg0, arg1); + } + return; + case 0x600b: /* neg Rm,Rn */ + tcg_gen_neg_i32(REG(B11_8), REG(B7_4)); + return; + case 0x600a: /* negc Rm,Rn */ { TCGv t0 = tcg_constant_i32(0); tcg_gen_add2_i32(REG(B11_8), cpu_sr_t, @@ -861,15 +861,15 @@ static void _decode_opc(DisasContext * ctx) t0, t0, REG(B11_8), cpu_sr_t); tcg_gen_andi_i32(cpu_sr_t, cpu_sr_t, 1); } - return; - case 0x6007: /* not Rm,Rn */ - tcg_gen_not_i32(REG(B11_8), REG(B7_4)); - return; - case 0x200b: /* or Rm,Rn */ - tcg_gen_or_i32(REG(B11_8), REG(B11_8), REG(B7_4)); - return; - case 0x400c: /* shad Rm,Rn */ - { + return; + case 0x6007: /* not Rm,Rn */ + tcg_gen_not_i32(REG(B11_8), REG(B7_4)); + return; + case 0x200b: /* or Rm,Rn */ + tcg_gen_or_i32(REG(B11_8), REG(B11_8), REG(B7_4)); + return; + case 0x400c: /* shad Rm,Rn */ + { TCGv t0 = tcg_temp_new(); TCGv t1 = tcg_temp_new(); TCGv t2 = tcg_temp_new(); @@ -888,10 +888,10 @@ static void _decode_opc(DisasContext * ctx) /* select between the two cases */ tcg_gen_movi_i32(t0, 0); tcg_gen_movcond_i32(TCG_COND_GE, REG(B11_8), REG(B7_4), t0, t1, t2); - } - return; - case 0x400d: /* shld Rm,Rn */ - { + } + return; + case 0x400d: /* shld Rm,Rn */ + { TCGv t0 = tcg_temp_new(); TCGv t1 = tcg_temp_new(); TCGv t2 = tcg_temp_new(); @@ -910,12 +910,12 @@ static void _decode_opc(DisasContext * ctx) /* select between the two cases */ tcg_gen_movi_i32(t0, 0); tcg_gen_movcond_i32(TCG_COND_GE, REG(B11_8), REG(B7_4), t0, t1, t2); - } - return; - case 0x3008: /* sub Rm,Rn */ - tcg_gen_sub_i32(REG(B11_8), REG(B11_8), REG(B7_4)); - return; - case 0x300a: /* subc Rm,Rn */ + } + return; + case 0x3008: /* sub Rm,Rn */ + tcg_gen_sub_i32(REG(B11_8), REG(B11_8), REG(B7_4)); + return; + case 0x300a: /* subc Rm,Rn */ { TCGv t0, t1; t0 = tcg_constant_tl(0); @@ -925,8 +925,8 @@ static void _decode_opc(DisasContext * ctx) REG(B11_8), t0, t1, cpu_sr_t); tcg_gen_andi_i32(cpu_sr_t, cpu_sr_t, 1); } - return; - case 0x300b: /* subv Rm,Rn */ + return; + case 0x300b: /* subv Rm,Rn */ { TCGv t0, t1, t2; t0 = tcg_temp_new(); @@ -939,68 +939,68 @@ static void _decode_opc(DisasContext * ctx) tcg_gen_shri_i32(cpu_sr_t, t1, 31); tcg_gen_mov_i32(REG(B11_8), t0); } - return; - case 0x2008: /* tst Rm,Rn */ - { - TCGv val = tcg_temp_new(); - tcg_gen_and_i32(val, REG(B7_4), REG(B11_8)); + return; + case 0x2008: /* tst Rm,Rn */ + { + TCGv val = tcg_temp_new(); + tcg_gen_and_i32(val, REG(B7_4), REG(B11_8)); tcg_gen_setcondi_i32(TCG_COND_EQ, cpu_sr_t, val, 0); - } - return; - case 0x200a: /* xor Rm,Rn */ - tcg_gen_xor_i32(REG(B11_8), REG(B11_8), REG(B7_4)); - return; + } + return; + case 0x200a: /* xor Rm,Rn */ + tcg_gen_xor_i32(REG(B11_8), REG(B11_8), REG(B7_4)); + return; case 0xf00c: /* fmov {F,D,X}Rm,{F,D,X}Rn - FPSCR: Nothing */ - CHECK_FPU_ENABLED + CHECK_FPU_ENABLED if (ctx->tbflags & FPSCR_SZ) { int xsrc = XHACK(B7_4); int xdst = XHACK(B11_8); tcg_gen_mov_i32(FREG(xdst), FREG(xsrc)); tcg_gen_mov_i32(FREG(xdst + 1), FREG(xsrc + 1)); - } else { + } else { tcg_gen_mov_i32(FREG(B11_8), FREG(B7_4)); - } - return; + } + return; case 0xf00a: /* fmov {F,D,X}Rm,@Rn - FPSCR: Nothing */ - CHECK_FPU_ENABLED + CHECK_FPU_ENABLED if (ctx->tbflags & FPSCR_SZ) { TCGv_i64 fp = tcg_temp_new_i64(); gen_load_fpr64(ctx, fp, XHACK(B7_4)); tcg_gen_qemu_st_i64(fp, REG(B11_8), ctx->memidx, MO_TEUQ | MO_ALIGN); - } else { + } else { tcg_gen_qemu_st_i32(FREG(B7_4), REG(B11_8), ctx->memidx, MO_TEUL | MO_ALIGN); - } - return; + } + return; case 0xf008: /* fmov @Rm,{F,D,X}Rn - FPSCR: Nothing */ - CHECK_FPU_ENABLED + CHECK_FPU_ENABLED if (ctx->tbflags & FPSCR_SZ) { TCGv_i64 fp = tcg_temp_new_i64(); tcg_gen_qemu_ld_i64(fp, REG(B7_4), ctx->memidx, MO_TEUQ | MO_ALIGN); gen_store_fpr64(ctx, fp, XHACK(B11_8)); - } else { + } else { tcg_gen_qemu_ld_i32(FREG(B11_8), REG(B7_4), ctx->memidx, MO_TEUL | MO_ALIGN); - } - return; + } + return; case 0xf009: /* fmov @Rm+,{F,D,X}Rn - FPSCR: Nothing */ - CHECK_FPU_ENABLED + CHECK_FPU_ENABLED if (ctx->tbflags & FPSCR_SZ) { TCGv_i64 fp = tcg_temp_new_i64(); tcg_gen_qemu_ld_i64(fp, REG(B7_4), ctx->memidx, MO_TEUQ | MO_ALIGN); gen_store_fpr64(ctx, fp, XHACK(B11_8)); tcg_gen_addi_i32(REG(B7_4), REG(B7_4), 8); - } else { + } else { tcg_gen_qemu_ld_i32(FREG(B11_8), REG(B7_4), ctx->memidx, MO_TEUL | MO_ALIGN); - tcg_gen_addi_i32(REG(B7_4), REG(B7_4), 4); - } - return; + tcg_gen_addi_i32(REG(B7_4), REG(B7_4), 4); + } + return; case 0xf00b: /* fmov {F,D,X}Rm,@-Rn - FPSCR: Nothing */ - CHECK_FPU_ENABLED + CHECK_FPU_ENABLED { TCGv addr = tcg_temp_new_i32(); if (ctx->tbflags & FPSCR_SZ) { @@ -1016,108 +1016,108 @@ static void _decode_opc(DisasContext * ctx) } tcg_gen_mov_i32(REG(B11_8), addr); } - return; + return; case 0xf006: /* fmov @(R0,Rm),{F,D,X}Rm - FPSCR: Nothing */ - CHECK_FPU_ENABLED - { - TCGv addr = tcg_temp_new_i32(); - tcg_gen_add_i32(addr, REG(B7_4), REG(0)); + CHECK_FPU_ENABLED + { + TCGv addr = tcg_temp_new_i32(); + tcg_gen_add_i32(addr, REG(B7_4), REG(0)); if (ctx->tbflags & FPSCR_SZ) { TCGv_i64 fp = tcg_temp_new_i64(); tcg_gen_qemu_ld_i64(fp, addr, ctx->memidx, MO_TEUQ | MO_ALIGN); gen_store_fpr64(ctx, fp, XHACK(B11_8)); - } else { + } else { tcg_gen_qemu_ld_i32(FREG(B11_8), addr, ctx->memidx, MO_TEUL | MO_ALIGN); - } - } - return; + } + } + return; case 0xf007: /* fmov {F,D,X}Rn,@(R0,Rn) - FPSCR: Nothing */ - CHECK_FPU_ENABLED - { - TCGv addr = tcg_temp_new(); - tcg_gen_add_i32(addr, REG(B11_8), REG(0)); + CHECK_FPU_ENABLED + { + TCGv addr = tcg_temp_new(); + tcg_gen_add_i32(addr, REG(B11_8), REG(0)); if (ctx->tbflags & FPSCR_SZ) { TCGv_i64 fp = tcg_temp_new_i64(); gen_load_fpr64(ctx, fp, XHACK(B7_4)); tcg_gen_qemu_st_i64(fp, addr, ctx->memidx, MO_TEUQ | MO_ALIGN); - } else { + } else { tcg_gen_qemu_st_i32(FREG(B7_4), addr, ctx->memidx, MO_TEUL | MO_ALIGN); - } - } - return; + } + } + return; case 0xf000: /* fadd Rm,Rn - FPSCR: R[PR,Enable.O/U/I]/W[Cause,Flag] */ case 0xf001: /* fsub Rm,Rn - FPSCR: R[PR,Enable.O/U/I]/W[Cause,Flag] */ case 0xf002: /* fmul Rm,Rn - FPSCR: R[PR,Enable.O/U/I]/W[Cause,Flag] */ case 0xf003: /* fdiv Rm,Rn - FPSCR: R[PR,Enable.O/U/I]/W[Cause,Flag] */ case 0xf004: /* fcmp/eq Rm,Rn - FPSCR: R[PR,Enable.V]/W[Cause,Flag] */ case 0xf005: /* fcmp/gt Rm,Rn - FPSCR: R[PR,Enable.V]/W[Cause,Flag] */ - { - CHECK_FPU_ENABLED + { + CHECK_FPU_ENABLED if (ctx->tbflags & FPSCR_PR) { TCGv_i64 fp0, fp1; if (ctx->opcode & 0x0110) { goto do_illegal; } - fp0 = tcg_temp_new_i64(); - fp1 = tcg_temp_new_i64(); + fp0 = tcg_temp_new_i64(); + fp1 = tcg_temp_new_i64(); gen_load_fpr64(ctx, fp0, B11_8); gen_load_fpr64(ctx, fp1, B7_4); switch (ctx->opcode & 0xf00f) { - case 0xf000: /* fadd Rm,Rn */ + case 0xf000: /* fadd Rm,Rn */ gen_helper_fadd_DT(fp0, tcg_env, fp0, fp1); break; - case 0xf001: /* fsub Rm,Rn */ + case 0xf001: /* fsub Rm,Rn */ gen_helper_fsub_DT(fp0, tcg_env, fp0, fp1); break; - case 0xf002: /* fmul Rm,Rn */ + case 0xf002: /* fmul Rm,Rn */ gen_helper_fmul_DT(fp0, tcg_env, fp0, fp1); break; - case 0xf003: /* fdiv Rm,Rn */ + case 0xf003: /* fdiv Rm,Rn */ gen_helper_fdiv_DT(fp0, tcg_env, fp0, fp1); break; - case 0xf004: /* fcmp/eq Rm,Rn */ + case 0xf004: /* fcmp/eq Rm,Rn */ gen_helper_fcmp_eq_DT(cpu_sr_t, tcg_env, fp0, fp1); return; - case 0xf005: /* fcmp/gt Rm,Rn */ + case 0xf005: /* fcmp/gt Rm,Rn */ gen_helper_fcmp_gt_DT(cpu_sr_t, tcg_env, fp0, fp1); return; } gen_store_fpr64(ctx, fp0, B11_8); - } else { + } else { switch (ctx->opcode & 0xf00f) { - case 0xf000: /* fadd Rm,Rn */ + case 0xf000: /* fadd Rm,Rn */ gen_helper_fadd_FT(FREG(B11_8), tcg_env, FREG(B11_8), FREG(B7_4)); break; - case 0xf001: /* fsub Rm,Rn */ + case 0xf001: /* fsub Rm,Rn */ gen_helper_fsub_FT(FREG(B11_8), tcg_env, FREG(B11_8), FREG(B7_4)); break; - case 0xf002: /* fmul Rm,Rn */ + case 0xf002: /* fmul Rm,Rn */ gen_helper_fmul_FT(FREG(B11_8), tcg_env, FREG(B11_8), FREG(B7_4)); break; - case 0xf003: /* fdiv Rm,Rn */ + case 0xf003: /* fdiv Rm,Rn */ gen_helper_fdiv_FT(FREG(B11_8), tcg_env, FREG(B11_8), FREG(B7_4)); break; - case 0xf004: /* fcmp/eq Rm,Rn */ + case 0xf004: /* fcmp/eq Rm,Rn */ gen_helper_fcmp_eq_FT(cpu_sr_t, tcg_env, FREG(B11_8), FREG(B7_4)); return; - case 0xf005: /* fcmp/gt Rm,Rn */ + case 0xf005: /* fcmp/gt Rm,Rn */ gen_helper_fcmp_gt_FT(cpu_sr_t, tcg_env, FREG(B11_8), FREG(B7_4)); return; } - } - } - return; + } + } + return; case 0xf00e: /* fmac FR0,RM,Rn */ CHECK_FPU_ENABLED CHECK_FPSCR_PR_0 @@ -1127,348 +1127,348 @@ static void _decode_opc(DisasContext * ctx) } switch (ctx->opcode & 0xff00) { - case 0xc900: /* and #imm,R0 */ - tcg_gen_andi_i32(REG(0), REG(0), B7_0); - return; - case 0xcd00: /* and.b #imm,@(R0,GBR) */ - { - TCGv addr, val; - addr = tcg_temp_new(); - tcg_gen_add_i32(addr, REG(0), cpu_gbr); - val = tcg_temp_new(); + case 0xc900: /* and #imm,R0 */ + tcg_gen_andi_i32(REG(0), REG(0), B7_0); + return; + case 0xcd00: /* and.b #imm,@(R0,GBR) */ + { + TCGv addr, val; + addr = tcg_temp_new(); + tcg_gen_add_i32(addr, REG(0), cpu_gbr); + val = tcg_temp_new(); tcg_gen_qemu_ld_i32(val, addr, ctx->memidx, MO_UB); - tcg_gen_andi_i32(val, val, B7_0); + tcg_gen_andi_i32(val, val, B7_0); tcg_gen_qemu_st_i32(val, addr, ctx->memidx, MO_UB); - } - return; - case 0x8b00: /* bf label */ - CHECK_NOT_DELAY_SLOT + } + return; + case 0x8b00: /* bf label */ + CHECK_NOT_DELAY_SLOT gen_conditional_jump(ctx, ctx->base.pc_next + 4 + B7_0s * 2, false); - return; - case 0x8f00: /* bf/s label */ - CHECK_NOT_DELAY_SLOT + return; + case 0x8f00: /* bf/s label */ + CHECK_NOT_DELAY_SLOT tcg_gen_xori_i32(cpu_delayed_cond, cpu_sr_t, 1); ctx->delayed_pc = ctx->base.pc_next + 4 + B7_0s * 2; ctx->envflags |= TB_FLAG_DELAY_SLOT_COND; - return; - case 0x8900: /* bt label */ - CHECK_NOT_DELAY_SLOT + return; + case 0x8900: /* bt label */ + CHECK_NOT_DELAY_SLOT gen_conditional_jump(ctx, ctx->base.pc_next + 4 + B7_0s * 2, true); - return; - case 0x8d00: /* bt/s label */ - CHECK_NOT_DELAY_SLOT + return; + case 0x8d00: /* bt/s label */ + CHECK_NOT_DELAY_SLOT tcg_gen_mov_i32(cpu_delayed_cond, cpu_sr_t); ctx->delayed_pc = ctx->base.pc_next + 4 + B7_0s * 2; ctx->envflags |= TB_FLAG_DELAY_SLOT_COND; - return; - case 0x8800: /* cmp/eq #imm,R0 */ + return; + case 0x8800: /* cmp/eq #imm,R0 */ tcg_gen_setcondi_i32(TCG_COND_EQ, cpu_sr_t, REG(0), B7_0s); - return; - case 0xc400: /* mov.b @(disp,GBR),R0 */ - { - TCGv addr = tcg_temp_new(); - tcg_gen_addi_i32(addr, cpu_gbr, B7_0); + return; + case 0xc400: /* mov.b @(disp,GBR),R0 */ + { + TCGv addr = tcg_temp_new(); + tcg_gen_addi_i32(addr, cpu_gbr, B7_0); tcg_gen_qemu_ld_i32(REG(0), addr, ctx->memidx, MO_SB); - } - return; - case 0xc500: /* mov.w @(disp,GBR),R0 */ - { - TCGv addr = tcg_temp_new(); - tcg_gen_addi_i32(addr, cpu_gbr, B7_0 * 2); + } + return; + case 0xc500: /* mov.w @(disp,GBR),R0 */ + { + TCGv addr = tcg_temp_new(); + tcg_gen_addi_i32(addr, cpu_gbr, B7_0 * 2); tcg_gen_qemu_ld_i32(REG(0), addr, ctx->memidx, MO_TESW | MO_ALIGN); - } - return; - case 0xc600: /* mov.l @(disp,GBR),R0 */ - { - TCGv addr = tcg_temp_new(); - tcg_gen_addi_i32(addr, cpu_gbr, B7_0 * 4); + } + return; + case 0xc600: /* mov.l @(disp,GBR),R0 */ + { + TCGv addr = tcg_temp_new(); + tcg_gen_addi_i32(addr, cpu_gbr, B7_0 * 4); tcg_gen_qemu_ld_i32(REG(0), addr, ctx->memidx, MO_TESL | MO_ALIGN); - } - return; - case 0xc000: /* mov.b R0,@(disp,GBR) */ - { - TCGv addr = tcg_temp_new(); - tcg_gen_addi_i32(addr, cpu_gbr, B7_0); + } + return; + case 0xc000: /* mov.b R0,@(disp,GBR) */ + { + TCGv addr = tcg_temp_new(); + tcg_gen_addi_i32(addr, cpu_gbr, B7_0); tcg_gen_qemu_st_i32(REG(0), addr, ctx->memidx, MO_UB); - } - return; - case 0xc100: /* mov.w R0,@(disp,GBR) */ - { - TCGv addr = tcg_temp_new(); - tcg_gen_addi_i32(addr, cpu_gbr, B7_0 * 2); + } + return; + case 0xc100: /* mov.w R0,@(disp,GBR) */ + { + TCGv addr = tcg_temp_new(); + tcg_gen_addi_i32(addr, cpu_gbr, B7_0 * 2); tcg_gen_qemu_st_i32(REG(0), addr, ctx->memidx, MO_TEUW | MO_ALIGN); - } - return; - case 0xc200: /* mov.l R0,@(disp,GBR) */ - { - TCGv addr = tcg_temp_new(); - tcg_gen_addi_i32(addr, cpu_gbr, B7_0 * 4); + } + return; + case 0xc200: /* mov.l R0,@(disp,GBR) */ + { + TCGv addr = tcg_temp_new(); + tcg_gen_addi_i32(addr, cpu_gbr, B7_0 * 4); tcg_gen_qemu_st_i32(REG(0), addr, ctx->memidx, MO_TEUL | MO_ALIGN); - } - return; - case 0x8000: /* mov.b R0,@(disp,Rn) */ - { - TCGv addr = tcg_temp_new(); - tcg_gen_addi_i32(addr, REG(B7_4), B3_0); + } + return; + case 0x8000: /* mov.b R0,@(disp,Rn) */ + { + TCGv addr = tcg_temp_new(); + tcg_gen_addi_i32(addr, REG(B7_4), B3_0); tcg_gen_qemu_st_i32(REG(0), addr, ctx->memidx, MO_UB); - } - return; - case 0x8100: /* mov.w R0,@(disp,Rn) */ - { - TCGv addr = tcg_temp_new(); - tcg_gen_addi_i32(addr, REG(B7_4), B3_0 * 2); + } + return; + case 0x8100: /* mov.w R0,@(disp,Rn) */ + { + TCGv addr = tcg_temp_new(); + tcg_gen_addi_i32(addr, REG(B7_4), B3_0 * 2); tcg_gen_qemu_st_i32(REG(0), addr, ctx->memidx, MO_TEUW | UNALIGN(ctx)); - } - return; - case 0x8400: /* mov.b @(disp,Rn),R0 */ - { - TCGv addr = tcg_temp_new(); - tcg_gen_addi_i32(addr, REG(B7_4), B3_0); + } + return; + case 0x8400: /* mov.b @(disp,Rn),R0 */ + { + TCGv addr = tcg_temp_new(); + tcg_gen_addi_i32(addr, REG(B7_4), B3_0); tcg_gen_qemu_ld_i32(REG(0), addr, ctx->memidx, MO_SB); - } - return; - case 0x8500: /* mov.w @(disp,Rn),R0 */ - { - TCGv addr = tcg_temp_new(); - tcg_gen_addi_i32(addr, REG(B7_4), B3_0 * 2); + } + return; + case 0x8500: /* mov.w @(disp,Rn),R0 */ + { + TCGv addr = tcg_temp_new(); + tcg_gen_addi_i32(addr, REG(B7_4), B3_0 * 2); tcg_gen_qemu_ld_i32(REG(0), addr, ctx->memidx, MO_TESW | UNALIGN(ctx)); - } - return; - case 0xc700: /* mova @(disp,PC),R0 */ + } + return; + case 0xc700: /* mova @(disp,PC),R0 */ tcg_gen_movi_i32(REG(0), ((ctx->base.pc_next & 0xfffffffc) + 4 + B7_0 * 4) & ~3); - return; - case 0xcb00: /* or #imm,R0 */ - tcg_gen_ori_i32(REG(0), REG(0), B7_0); - return; - case 0xcf00: /* or.b #imm,@(R0,GBR) */ - { - TCGv addr, val; - addr = tcg_temp_new(); - tcg_gen_add_i32(addr, REG(0), cpu_gbr); - val = tcg_temp_new(); + return; + case 0xcb00: /* or #imm,R0 */ + tcg_gen_ori_i32(REG(0), REG(0), B7_0); + return; + case 0xcf00: /* or.b #imm,@(R0,GBR) */ + { + TCGv addr, val; + addr = tcg_temp_new(); + tcg_gen_add_i32(addr, REG(0), cpu_gbr); + val = tcg_temp_new(); tcg_gen_qemu_ld_i32(val, addr, ctx->memidx, MO_UB); - tcg_gen_ori_i32(val, val, B7_0); + tcg_gen_ori_i32(val, val, B7_0); tcg_gen_qemu_st_i32(val, addr, ctx->memidx, MO_UB); - } - return; - case 0xc300: /* trapa #imm */ - { - TCGv imm; - CHECK_NOT_DELAY_SLOT + } + return; + case 0xc300: /* trapa #imm */ + { + TCGv imm; + CHECK_NOT_DELAY_SLOT gen_save_cpu_state(ctx, true); - imm = tcg_constant_i32(B7_0); + imm = tcg_constant_i32(B7_0); gen_helper_trapa(tcg_env, imm); ctx->base.is_jmp = DISAS_NORETURN; - } - return; - case 0xc800: /* tst #imm,R0 */ - { - TCGv val = tcg_temp_new(); - tcg_gen_andi_i32(val, REG(0), B7_0); + } + return; + case 0xc800: /* tst #imm,R0 */ + { + TCGv val = tcg_temp_new(); + tcg_gen_andi_i32(val, REG(0), B7_0); tcg_gen_setcondi_i32(TCG_COND_EQ, cpu_sr_t, val, 0); - } - return; - case 0xcc00: /* tst.b #imm,@(R0,GBR) */ - { - TCGv val = tcg_temp_new(); - tcg_gen_add_i32(val, REG(0), cpu_gbr); + } + return; + case 0xcc00: /* tst.b #imm,@(R0,GBR) */ + { + TCGv val = tcg_temp_new(); + tcg_gen_add_i32(val, REG(0), cpu_gbr); tcg_gen_qemu_ld_i32(val, val, ctx->memidx, MO_UB); - tcg_gen_andi_i32(val, val, B7_0); + tcg_gen_andi_i32(val, val, B7_0); tcg_gen_setcondi_i32(TCG_COND_EQ, cpu_sr_t, val, 0); - } - return; - case 0xca00: /* xor #imm,R0 */ - tcg_gen_xori_i32(REG(0), REG(0), B7_0); - return; - case 0xce00: /* xor.b #imm,@(R0,GBR) */ - { - TCGv addr, val; - addr = tcg_temp_new(); - tcg_gen_add_i32(addr, REG(0), cpu_gbr); - val = tcg_temp_new(); + } + return; + case 0xca00: /* xor #imm,R0 */ + tcg_gen_xori_i32(REG(0), REG(0), B7_0); + return; + case 0xce00: /* xor.b #imm,@(R0,GBR) */ + { + TCGv addr, val; + addr = tcg_temp_new(); + tcg_gen_add_i32(addr, REG(0), cpu_gbr); + val = tcg_temp_new(); tcg_gen_qemu_ld_i32(val, addr, ctx->memidx, MO_UB); - tcg_gen_xori_i32(val, val, B7_0); + tcg_gen_xori_i32(val, val, B7_0); tcg_gen_qemu_st_i32(val, addr, ctx->memidx, MO_UB); - } - return; + } + return; } switch (ctx->opcode & 0xf08f) { - case 0x408e: /* ldc Rm,Rn_BANK */ - CHECK_PRIVILEGED - tcg_gen_mov_i32(ALTREG(B6_4), REG(B11_8)); - return; - case 0x4087: /* ldc.l @Rm+,Rn_BANK */ - CHECK_PRIVILEGED + case 0x408e: /* ldc Rm,Rn_BANK */ + CHECK_PRIVILEGED + tcg_gen_mov_i32(ALTREG(B6_4), REG(B11_8)); + return; + case 0x4087: /* ldc.l @Rm+,Rn_BANK */ + CHECK_PRIVILEGED tcg_gen_qemu_ld_i32(ALTREG(B6_4), REG(B11_8), ctx->memidx, MO_TESL | MO_ALIGN); - tcg_gen_addi_i32(REG(B11_8), REG(B11_8), 4); - return; - case 0x0082: /* stc Rm_BANK,Rn */ - CHECK_PRIVILEGED - tcg_gen_mov_i32(REG(B11_8), ALTREG(B6_4)); - return; - case 0x4083: /* stc.l Rm_BANK,@-Rn */ - CHECK_PRIVILEGED - { - TCGv addr = tcg_temp_new(); - tcg_gen_subi_i32(addr, REG(B11_8), 4); + tcg_gen_addi_i32(REG(B11_8), REG(B11_8), 4); + return; + case 0x0082: /* stc Rm_BANK,Rn */ + CHECK_PRIVILEGED + tcg_gen_mov_i32(REG(B11_8), ALTREG(B6_4)); + return; + case 0x4083: /* stc.l Rm_BANK,@-Rn */ + CHECK_PRIVILEGED + { + TCGv addr = tcg_temp_new(); + tcg_gen_subi_i32(addr, REG(B11_8), 4); tcg_gen_qemu_st_i32(ALTREG(B6_4), addr, ctx->memidx, MO_TEUL | MO_ALIGN); - tcg_gen_mov_i32(REG(B11_8), addr); - } - return; + tcg_gen_mov_i32(REG(B11_8), addr); + } + return; } switch (ctx->opcode & 0xf0ff) { - case 0x0023: /* braf Rn */ - CHECK_NOT_DELAY_SLOT + case 0x0023: /* braf Rn */ + CHECK_NOT_DELAY_SLOT tcg_gen_addi_i32(cpu_delayed_pc, REG(B11_8), ctx->base.pc_next + 4); ctx->envflags |= TB_FLAG_DELAY_SLOT; - ctx->delayed_pc = (uint32_t) - 1; - return; - case 0x0003: /* bsrf Rn */ - CHECK_NOT_DELAY_SLOT + ctx->delayed_pc = (uint32_t) - 1; + return; + case 0x0003: /* bsrf Rn */ + CHECK_NOT_DELAY_SLOT tcg_gen_movi_i32(cpu_pr, ctx->base.pc_next + 4); - tcg_gen_add_i32(cpu_delayed_pc, REG(B11_8), cpu_pr); + tcg_gen_add_i32(cpu_delayed_pc, REG(B11_8), cpu_pr); ctx->envflags |= TB_FLAG_DELAY_SLOT; - ctx->delayed_pc = (uint32_t) - 1; - return; - case 0x4015: /* cmp/pl Rn */ + ctx->delayed_pc = (uint32_t) - 1; + return; + case 0x4015: /* cmp/pl Rn */ tcg_gen_setcondi_i32(TCG_COND_GT, cpu_sr_t, REG(B11_8), 0); - return; - case 0x4011: /* cmp/pz Rn */ + return; + case 0x4011: /* cmp/pz Rn */ tcg_gen_setcondi_i32(TCG_COND_GE, cpu_sr_t, REG(B11_8), 0); - return; - case 0x4010: /* dt Rn */ - tcg_gen_subi_i32(REG(B11_8), REG(B11_8), 1); + return; + case 0x4010: /* dt Rn */ + tcg_gen_subi_i32(REG(B11_8), REG(B11_8), 1); tcg_gen_setcondi_i32(TCG_COND_EQ, cpu_sr_t, REG(B11_8), 0); - return; - case 0x402b: /* jmp @Rn */ - CHECK_NOT_DELAY_SLOT - tcg_gen_mov_i32(cpu_delayed_pc, REG(B11_8)); + return; + case 0x402b: /* jmp @Rn */ + CHECK_NOT_DELAY_SLOT + tcg_gen_mov_i32(cpu_delayed_pc, REG(B11_8)); ctx->envflags |= TB_FLAG_DELAY_SLOT; - ctx->delayed_pc = (uint32_t) - 1; - return; - case 0x400b: /* jsr @Rn */ - CHECK_NOT_DELAY_SLOT + ctx->delayed_pc = (uint32_t) - 1; + return; + case 0x400b: /* jsr @Rn */ + CHECK_NOT_DELAY_SLOT tcg_gen_movi_i32(cpu_pr, ctx->base.pc_next + 4); - tcg_gen_mov_i32(cpu_delayed_pc, REG(B11_8)); + tcg_gen_mov_i32(cpu_delayed_pc, REG(B11_8)); ctx->envflags |= TB_FLAG_DELAY_SLOT; - ctx->delayed_pc = (uint32_t) - 1; - return; - case 0x400e: /* ldc Rm,SR */ - CHECK_PRIVILEGED + ctx->delayed_pc = (uint32_t) - 1; + return; + case 0x400e: /* ldc Rm,SR */ + CHECK_PRIVILEGED { TCGv val = tcg_temp_new(); tcg_gen_andi_i32(val, REG(B11_8), 0x700083f3); gen_write_sr(val); ctx->base.is_jmp = DISAS_STOP; } - return; - case 0x4007: /* ldc.l @Rm+,SR */ - CHECK_PRIVILEGED - { - TCGv val = tcg_temp_new(); + return; + case 0x4007: /* ldc.l @Rm+,SR */ + CHECK_PRIVILEGED + { + TCGv val = tcg_temp_new(); tcg_gen_qemu_ld_i32(val, REG(B11_8), ctx->memidx, MO_TESL | MO_ALIGN); tcg_gen_andi_i32(val, val, 0x700083f3); gen_write_sr(val); - tcg_gen_addi_i32(REG(B11_8), REG(B11_8), 4); + tcg_gen_addi_i32(REG(B11_8), REG(B11_8), 4); ctx->base.is_jmp = DISAS_STOP; - } - return; - case 0x0002: /* stc SR,Rn */ - CHECK_PRIVILEGED + } + return; + case 0x0002: /* stc SR,Rn */ + CHECK_PRIVILEGED gen_read_sr(REG(B11_8)); - return; - case 0x4003: /* stc SR,@-Rn */ - CHECK_PRIVILEGED - { - TCGv addr = tcg_temp_new(); + return; + case 0x4003: /* stc SR,@-Rn */ + CHECK_PRIVILEGED + { + TCGv addr = tcg_temp_new(); TCGv val = tcg_temp_new(); - tcg_gen_subi_i32(addr, REG(B11_8), 4); + tcg_gen_subi_i32(addr, REG(B11_8), 4); gen_read_sr(val); tcg_gen_qemu_st_i32(val, addr, ctx->memidx, MO_TEUL | MO_ALIGN); - tcg_gen_mov_i32(REG(B11_8), addr); - } - return; -#define LD(reg,ldnum,ldpnum,prechk) \ - case ldnum: \ - prechk \ - tcg_gen_mov_i32 (cpu_##reg, REG(B11_8)); \ - return; \ - case ldpnum: \ - prechk \ - tcg_gen_qemu_ld_i32(cpu_##reg, REG(B11_8), ctx->memidx, \ - MO_TESL | MO_ALIGN); \ - tcg_gen_addi_i32(REG(B11_8), REG(B11_8), 4); \ + tcg_gen_mov_i32(REG(B11_8), addr); + } + return; +#define LD(reg,ldnum,ldpnum,prechk) \ + case ldnum: \ + prechk \ + tcg_gen_mov_i32 (cpu_##reg, REG(B11_8)); \ + return; \ + case ldpnum: \ + prechk \ + tcg_gen_qemu_ld_i32(cpu_##reg, REG(B11_8), ctx->memidx, \ + MO_TESL | MO_ALIGN); \ + tcg_gen_addi_i32(REG(B11_8), REG(B11_8), 4); \ return; -#define ST(reg,stnum,stpnum,prechk) \ - case stnum: \ - prechk \ - tcg_gen_mov_i32 (REG(B11_8), cpu_##reg); \ - return; \ - case stpnum: \ - prechk \ - { \ - TCGv addr = tcg_temp_new(); \ - tcg_gen_subi_i32(addr, REG(B11_8), 4); \ - tcg_gen_qemu_st_i32(cpu_##reg, addr, ctx->memidx, \ - MO_TEUL | MO_ALIGN); \ - tcg_gen_mov_i32(REG(B11_8), addr); \ - } \ +#define ST(reg,stnum,stpnum,prechk) \ + case stnum: \ + prechk \ + tcg_gen_mov_i32 (REG(B11_8), cpu_##reg); \ + return; \ + case stpnum: \ + prechk \ + { \ + TCGv addr = tcg_temp_new(); \ + tcg_gen_subi_i32(addr, REG(B11_8), 4); \ + tcg_gen_qemu_st_i32(cpu_##reg, addr, ctx->memidx, \ + MO_TEUL | MO_ALIGN); \ + tcg_gen_mov_i32(REG(B11_8), addr); \ + } \ return; -#define LDST(reg,ldnum,ldpnum,stnum,stpnum,prechk) \ - LD(reg,ldnum,ldpnum,prechk) \ - ST(reg,stnum,stpnum,prechk) - LDST(gbr, 0x401e, 0x4017, 0x0012, 0x4013, {}) - LDST(vbr, 0x402e, 0x4027, 0x0022, 0x4023, CHECK_PRIVILEGED) - LDST(ssr, 0x403e, 0x4037, 0x0032, 0x4033, CHECK_PRIVILEGED) - LDST(spc, 0x404e, 0x4047, 0x0042, 0x4043, CHECK_PRIVILEGED) - ST(sgr, 0x003a, 0x4032, CHECK_PRIVILEGED) +#define LDST(reg,ldnum,ldpnum,stnum,stpnum,prechk) \ + LD(reg,ldnum,ldpnum,prechk) \ + ST(reg,stnum,stpnum,prechk) + LDST(gbr, 0x401e, 0x4017, 0x0012, 0x4013, {}) + LDST(vbr, 0x402e, 0x4027, 0x0022, 0x4023, CHECK_PRIVILEGED) + LDST(ssr, 0x403e, 0x4037, 0x0032, 0x4033, CHECK_PRIVILEGED) + LDST(spc, 0x404e, 0x4047, 0x0042, 0x4043, CHECK_PRIVILEGED) + ST(sgr, 0x003a, 0x4032, CHECK_PRIVILEGED) LD(sgr, 0x403a, 0x4036, CHECK_PRIVILEGED CHECK_SH4A) - LDST(dbr, 0x40fa, 0x40f6, 0x00fa, 0x40f2, CHECK_PRIVILEGED) - LDST(mach, 0x400a, 0x4006, 0x000a, 0x4002, {}) - LDST(macl, 0x401a, 0x4016, 0x001a, 0x4012, {}) - LDST(pr, 0x402a, 0x4026, 0x002a, 0x4022, {}) - LDST(fpul, 0x405a, 0x4056, 0x005a, 0x4052, {CHECK_FPU_ENABLED}) - case 0x406a: /* lds Rm,FPSCR */ - CHECK_FPU_ENABLED + LDST(dbr, 0x40fa, 0x40f6, 0x00fa, 0x40f2, CHECK_PRIVILEGED) + LDST(mach, 0x400a, 0x4006, 0x000a, 0x4002, {}) + LDST(macl, 0x401a, 0x4016, 0x001a, 0x4012, {}) + LDST(pr, 0x402a, 0x4026, 0x002a, 0x4022, {}) + LDST(fpul, 0x405a, 0x4056, 0x005a, 0x4052, {CHECK_FPU_ENABLED}) + case 0x406a: /* lds Rm,FPSCR */ + CHECK_FPU_ENABLED gen_helper_ld_fpscr(tcg_env, REG(B11_8)); ctx->base.is_jmp = DISAS_STOP; - return; - case 0x4066: /* lds.l @Rm+,FPSCR */ - CHECK_FPU_ENABLED - { - TCGv addr = tcg_temp_new(); + return; + case 0x4066: /* lds.l @Rm+,FPSCR */ + CHECK_FPU_ENABLED + { + TCGv addr = tcg_temp_new(); tcg_gen_qemu_ld_i32(addr, REG(B11_8), ctx->memidx, MO_TESL | MO_ALIGN); - tcg_gen_addi_i32(REG(B11_8), REG(B11_8), 4); + tcg_gen_addi_i32(REG(B11_8), REG(B11_8), 4); gen_helper_ld_fpscr(tcg_env, addr); ctx->base.is_jmp = DISAS_STOP; - } - return; - case 0x006a: /* sts FPSCR,Rn */ - CHECK_FPU_ENABLED - tcg_gen_andi_i32(REG(B11_8), cpu_fpscr, 0x003fffff); - return; - case 0x4062: /* sts FPSCR,@-Rn */ - CHECK_FPU_ENABLED - { - TCGv addr, val; - val = tcg_temp_new(); - tcg_gen_andi_i32(val, cpu_fpscr, 0x003fffff); - addr = tcg_temp_new(); - tcg_gen_subi_i32(addr, REG(B11_8), 4); + } + return; + case 0x006a: /* sts FPSCR,Rn */ + CHECK_FPU_ENABLED + tcg_gen_andi_i32(REG(B11_8), cpu_fpscr, 0x003fffff); + return; + case 0x4062: /* sts FPSCR,@-Rn */ + CHECK_FPU_ENABLED + { + TCGv addr, val; + val = tcg_temp_new(); + tcg_gen_andi_i32(val, cpu_fpscr, 0x003fffff); + addr = tcg_temp_new(); + tcg_gen_subi_i32(addr, REG(B11_8), 4); tcg_gen_qemu_st_i32(val, addr, ctx->memidx, MO_TEUL | MO_ALIGN); - tcg_gen_mov_i32(REG(B11_8), addr); - } - return; - case 0x00c3: /* movca.l R0,@Rm */ + tcg_gen_mov_i32(REG(B11_8), addr); + } + return; + case 0x00c3: /* movca.l R0,@Rm */ { TCGv val = tcg_temp_new(); tcg_gen_qemu_ld_i32(val, REG(B11_8), ctx->memidx, @@ -1478,23 +1478,23 @@ static void _decode_opc(DisasContext * ctx) MO_TEUL | MO_ALIGN); } ctx->has_movcal = 1; - return; - case 0x40a9: /* movua.l @Rm,R0 */ + return; + case 0x40a9: /* movua.l @Rm,R0 */ CHECK_SH4A /* Load non-boundary-aligned data */ tcg_gen_qemu_ld_i32(REG(0), REG(B11_8), ctx->memidx, MO_TEUL | MO_UNALN); return; - case 0x40e9: /* movua.l @Rm+,R0 */ + case 0x40e9: /* movua.l @Rm+,R0 */ CHECK_SH4A /* Load non-boundary-aligned data */ tcg_gen_qemu_ld_i32(REG(0), REG(B11_8), ctx->memidx, MO_TEUL | MO_UNALN); tcg_gen_addi_i32(REG(B11_8), REG(B11_8), 4); return; - case 0x0029: /* movt Rn */ + case 0x0029: /* movt Rn */ tcg_gen_mov_i32(REG(B11_8), cpu_sr_t); - return; + return; case 0x0073: /* MOVCO.L * LDST -> T @@ -1558,182 +1558,182 @@ static void _decode_opc(DisasContext * ctx) tcg_gen_movi_i32(cpu_lock_addr, 0); } return; - case 0x0093: /* ocbi @Rn */ - { + case 0x0093: /* ocbi @Rn */ + { gen_helper_ocbi(tcg_env, REG(B11_8)); - } - return; - case 0x00a3: /* ocbp @Rn */ - case 0x00b3: /* ocbwb @Rn */ + } + return; + case 0x00a3: /* ocbp @Rn */ + case 0x00b3: /* ocbwb @Rn */ /* These instructions are supposed to do nothing in case of a cache miss. Given that we only partially emulate caches it is safe to simply ignore them. */ - return; - case 0x0083: /* pref @Rn */ - return; - case 0x00d3: /* prefi @Rn */ + return; + case 0x0083: /* pref @Rn */ + return; + case 0x00d3: /* prefi @Rn */ CHECK_SH4A return; - case 0x00e3: /* icbi @Rn */ + case 0x00e3: /* icbi @Rn */ CHECK_SH4A return; - case 0x00ab: /* synco */ + case 0x00ab: /* synco */ CHECK_SH4A tcg_gen_mb(TCG_MO_ALL | TCG_BAR_SC); return; - case 0x4024: /* rotcl Rn */ - { - TCGv tmp = tcg_temp_new(); + case 0x4024: /* rotcl Rn */ + { + TCGv tmp = tcg_temp_new(); tcg_gen_mov_i32(tmp, cpu_sr_t); tcg_gen_shri_i32(cpu_sr_t, REG(B11_8), 31); - tcg_gen_shli_i32(REG(B11_8), REG(B11_8), 1); + tcg_gen_shli_i32(REG(B11_8), REG(B11_8), 1); tcg_gen_or_i32(REG(B11_8), REG(B11_8), tmp); - } - return; - case 0x4025: /* rotcr Rn */ - { - TCGv tmp = tcg_temp_new(); + } + return; + case 0x4025: /* rotcr Rn */ + { + TCGv tmp = tcg_temp_new(); tcg_gen_shli_i32(tmp, cpu_sr_t, 31); tcg_gen_andi_i32(cpu_sr_t, REG(B11_8), 1); - tcg_gen_shri_i32(REG(B11_8), REG(B11_8), 1); + tcg_gen_shri_i32(REG(B11_8), REG(B11_8), 1); tcg_gen_or_i32(REG(B11_8), REG(B11_8), tmp); - } - return; - case 0x4004: /* rotl Rn */ - tcg_gen_rotli_i32(REG(B11_8), REG(B11_8), 1); + } + return; + case 0x4004: /* rotl Rn */ + tcg_gen_rotli_i32(REG(B11_8), REG(B11_8), 1); tcg_gen_andi_i32(cpu_sr_t, REG(B11_8), 0); - return; - case 0x4005: /* rotr Rn */ + return; + case 0x4005: /* rotr Rn */ tcg_gen_andi_i32(cpu_sr_t, REG(B11_8), 0); - tcg_gen_rotri_i32(REG(B11_8), REG(B11_8), 1); - return; - case 0x4000: /* shll Rn */ - case 0x4020: /* shal Rn */ + tcg_gen_rotri_i32(REG(B11_8), REG(B11_8), 1); + return; + case 0x4000: /* shll Rn */ + case 0x4020: /* shal Rn */ tcg_gen_shri_i32(cpu_sr_t, REG(B11_8), 31); - tcg_gen_shli_i32(REG(B11_8), REG(B11_8), 1); - return; - case 0x4021: /* shar Rn */ + tcg_gen_shli_i32(REG(B11_8), REG(B11_8), 1); + return; + case 0x4021: /* shar Rn */ tcg_gen_andi_i32(cpu_sr_t, REG(B11_8), 1); - tcg_gen_sari_i32(REG(B11_8), REG(B11_8), 1); - return; - case 0x4001: /* shlr Rn */ + tcg_gen_sari_i32(REG(B11_8), REG(B11_8), 1); + return; + case 0x4001: /* shlr Rn */ tcg_gen_andi_i32(cpu_sr_t, REG(B11_8), 1); - tcg_gen_shri_i32(REG(B11_8), REG(B11_8), 1); - return; - case 0x4008: /* shll2 Rn */ - tcg_gen_shli_i32(REG(B11_8), REG(B11_8), 2); - return; - case 0x4018: /* shll8 Rn */ - tcg_gen_shli_i32(REG(B11_8), REG(B11_8), 8); - return; - case 0x4028: /* shll16 Rn */ - tcg_gen_shli_i32(REG(B11_8), REG(B11_8), 16); - return; - case 0x4009: /* shlr2 Rn */ - tcg_gen_shri_i32(REG(B11_8), REG(B11_8), 2); - return; - case 0x4019: /* shlr8 Rn */ - tcg_gen_shri_i32(REG(B11_8), REG(B11_8), 8); - return; - case 0x4029: /* shlr16 Rn */ - tcg_gen_shri_i32(REG(B11_8), REG(B11_8), 16); - return; - case 0x401b: /* tas.b @Rn */ + tcg_gen_shri_i32(REG(B11_8), REG(B11_8), 1); + return; + case 0x4008: /* shll2 Rn */ + tcg_gen_shli_i32(REG(B11_8), REG(B11_8), 2); + return; + case 0x4018: /* shll8 Rn */ + tcg_gen_shli_i32(REG(B11_8), REG(B11_8), 8); + return; + case 0x4028: /* shll16 Rn */ + tcg_gen_shli_i32(REG(B11_8), REG(B11_8), 16); + return; + case 0x4009: /* shlr2 Rn */ + tcg_gen_shri_i32(REG(B11_8), REG(B11_8), 2); + return; + case 0x4019: /* shlr8 Rn */ + tcg_gen_shri_i32(REG(B11_8), REG(B11_8), 8); + return; + case 0x4029: /* shlr16 Rn */ + tcg_gen_shri_i32(REG(B11_8), REG(B11_8), 16); + return; + case 0x401b: /* tas.b @Rn */ tcg_gen_atomic_fetch_or_i32(cpu_sr_t, REG(B11_8), tcg_constant_i32(0x80), ctx->memidx, MO_UB); tcg_gen_setcondi_i32(TCG_COND_EQ, cpu_sr_t, cpu_sr_t, 0); return; case 0xf00d: /* fsts FPUL,FRn - FPSCR: Nothing */ - CHECK_FPU_ENABLED + CHECK_FPU_ENABLED tcg_gen_mov_i32(FREG(B11_8), cpu_fpul); - return; + return; case 0xf01d: /* flds FRm,FPUL - FPSCR: Nothing */ - CHECK_FPU_ENABLED + CHECK_FPU_ENABLED tcg_gen_mov_i32(cpu_fpul, FREG(B11_8)); - return; + return; case 0xf02d: /* float FPUL,FRn/DRn - FPSCR: R[PR,Enable.I]/W[Cause,Flag] */ - CHECK_FPU_ENABLED + CHECK_FPU_ENABLED if (ctx->tbflags & FPSCR_PR) { - TCGv_i64 fp; + TCGv_i64 fp; if (ctx->opcode & 0x0100) { goto do_illegal; } - fp = tcg_temp_new_i64(); + fp = tcg_temp_new_i64(); gen_helper_float_DT(fp, tcg_env, cpu_fpul); gen_store_fpr64(ctx, fp, B11_8); - } - else { + } + else { gen_helper_float_FT(FREG(B11_8), tcg_env, cpu_fpul); - } - return; + } + return; case 0xf03d: /* ftrc FRm/DRm,FPUL - FPSCR: R[PR,Enable.V]/W[Cause,Flag] */ - CHECK_FPU_ENABLED + CHECK_FPU_ENABLED if (ctx->tbflags & FPSCR_PR) { - TCGv_i64 fp; + TCGv_i64 fp; if (ctx->opcode & 0x0100) { goto do_illegal; } - fp = tcg_temp_new_i64(); + fp = tcg_temp_new_i64(); gen_load_fpr64(ctx, fp, B11_8); gen_helper_ftrc_DT(cpu_fpul, tcg_env, fp); - } - else { + } + else { gen_helper_ftrc_FT(cpu_fpul, tcg_env, FREG(B11_8)); - } - return; + } + return; case 0xf04d: /* fneg FRn/DRn - FPSCR: Nothing */ - CHECK_FPU_ENABLED + CHECK_FPU_ENABLED tcg_gen_xori_i32(FREG(B11_8), FREG(B11_8), 0x80000000); - return; + return; case 0xf05d: /* fabs FRn/DRn - FPCSR: Nothing */ - CHECK_FPU_ENABLED + CHECK_FPU_ENABLED tcg_gen_andi_i32(FREG(B11_8), FREG(B11_8), 0x7fffffff); - return; + return; case 0xf06d: /* fsqrt FRn */ - CHECK_FPU_ENABLED + CHECK_FPU_ENABLED if (ctx->tbflags & FPSCR_PR) { if (ctx->opcode & 0x0100) { goto do_illegal; } - TCGv_i64 fp = tcg_temp_new_i64(); + TCGv_i64 fp = tcg_temp_new_i64(); gen_load_fpr64(ctx, fp, B11_8); gen_helper_fsqrt_DT(fp, tcg_env, fp); gen_store_fpr64(ctx, fp, B11_8); - } else { + } else { gen_helper_fsqrt_FT(FREG(B11_8), tcg_env, FREG(B11_8)); - } - return; + } + return; case 0xf07d: /* fsrra FRn */ - CHECK_FPU_ENABLED + CHECK_FPU_ENABLED CHECK_FPSCR_PR_0 gen_helper_fsrra_FT(FREG(B11_8), tcg_env, FREG(B11_8)); - break; + break; case 0xf08d: /* fldi0 FRn - FPSCR: R[PR] */ - CHECK_FPU_ENABLED + CHECK_FPU_ENABLED CHECK_FPSCR_PR_0 tcg_gen_movi_i32(FREG(B11_8), 0); return; case 0xf09d: /* fldi1 FRn - FPSCR: R[PR] */ - CHECK_FPU_ENABLED + CHECK_FPU_ENABLED CHECK_FPSCR_PR_0 tcg_gen_movi_i32(FREG(B11_8), 0x3f800000); return; case 0xf0ad: /* fcnvsd FPUL,DRn */ - CHECK_FPU_ENABLED - { - TCGv_i64 fp = tcg_temp_new_i64(); + CHECK_FPU_ENABLED + { + TCGv_i64 fp = tcg_temp_new_i64(); gen_helper_fcnvsd_FT_DT(fp, tcg_env, cpu_fpul); gen_store_fpr64(ctx, fp, B11_8); - } - return; + } + return; case 0xf0bd: /* fcnvds DRn,FPUL */ - CHECK_FPU_ENABLED - { - TCGv_i64 fp = tcg_temp_new_i64(); + CHECK_FPU_ENABLED + { + TCGv_i64 fp = tcg_temp_new_i64(); gen_load_fpr64(ctx, fp, B11_8); gen_helper_fcnvds_DT_FT(cpu_fpul, tcg_env, fp); - } - return; + } + return; case 0xf0ed: /* fipr FVm,FVn */ CHECK_FPU_ENABLED CHECK_FPSCR_PR_1 @@ -1808,10 +1808,10 @@ static void decode_opc(DisasContext * ctx) tcg_gen_movi_i32(cpu_flags, ctx->envflags); if (old_flags & TB_FLAG_DELAY_SLOT_COND) { - gen_delayed_conditional_jump(ctx); + gen_delayed_conditional_jump(ctx); } else { gen_jump(ctx); - } + } } } diff --git a/target/xtensa/mmu_helper.c b/target/xtensa/mmu_helper.c index 12552a3347..2fda4e887c 100644 --- a/target/xtensa/mmu_helper.c +++ b/target/xtensa/mmu_helper.c @@ -224,22 +224,31 @@ static void split_tlb_entry_spec_way(const CPUXtensaState *env, uint32_t v, * Split TLB address into TLB way, entry index and VPN (with index). * See ISA, 4.6.5.5 - 4.6.5.8 for the TLB addressing format */ -static void split_tlb_entry_spec(CPUXtensaState *env, uint32_t v, bool dtlb, - uint32_t *vpn, uint32_t *wi, uint32_t *ei) +static bool split_tlb_entry_spec(CPUXtensaState *env, uint32_t v, bool dtlb, + uint32_t *vpn, uint32_t *wi, uint32_t *ei) { if (xtensa_option_enabled(env->config, XTENSA_OPTION_MMU)) { *wi = v & (dtlb ? 0xf : 0x7); - split_tlb_entry_spec_way(env, v, dtlb, vpn, *wi, ei); + if (*wi < (dtlb ? env->config->dtlb.nways : env->config->itlb.nways)) { + split_tlb_entry_spec_way(env, v, dtlb, vpn, *wi, ei); + return true; + } else { + return false; + } } else { *vpn = v & REGION_PAGE_MASK; *wi = 0; *ei = (v >> 29) & 0x7; + return true; } } static xtensa_tlb_entry *xtensa_tlb_get_entry(CPUXtensaState *env, bool dtlb, unsigned wi, unsigned ei) { + const xtensa_tlb *tlb = dtlb ? &env->config->dtlb : &env->config->itlb; + + assert(wi < tlb->nways && ei < tlb->way_size[wi]); return dtlb ? env->dtlb[wi] + ei : env->itlb[wi] + ei; @@ -252,11 +261,14 @@ static xtensa_tlb_entry *get_tlb_entry(CPUXtensaState *env, uint32_t wi; uint32_t ei; - split_tlb_entry_spec(env, v, dtlb, &vpn, &wi, &ei); - if (pwi) { - *pwi = wi; + if (split_tlb_entry_spec(env, v, dtlb, &vpn, &wi, &ei)) { + if (pwi) { + *pwi = wi; + } + return xtensa_tlb_get_entry(env, dtlb, wi, ei); + } else { + return NULL; } - return xtensa_tlb_get_entry(env, dtlb, wi, ei); } static void xtensa_tlb_set_entry_mmu(const CPUXtensaState *env, @@ -482,7 +494,12 @@ uint32_t HELPER(rtlb0)(CPUXtensaState *env, uint32_t v, uint32_t dtlb) if (xtensa_option_enabled(env->config, XTENSA_OPTION_MMU)) { uint32_t wi; const xtensa_tlb_entry *entry = get_tlb_entry(env, v, dtlb, &wi); - return (entry->vaddr & get_vpn_mask(env, dtlb, wi)) | entry->asid; + + if (entry) { + return (entry->vaddr & get_vpn_mask(env, dtlb, wi)) | entry->asid; + } else { + return 0; + } } else { return v & REGION_PAGE_MASK; } @@ -491,7 +508,12 @@ uint32_t HELPER(rtlb0)(CPUXtensaState *env, uint32_t v, uint32_t dtlb) uint32_t HELPER(rtlb1)(CPUXtensaState *env, uint32_t v, uint32_t dtlb) { const xtensa_tlb_entry *entry = get_tlb_entry(env, v, dtlb, NULL); - return entry->paddr | entry->attr; + + if (entry) { + return entry->paddr | entry->attr; + } else { + return 0; + } } void HELPER(itlb)(CPUXtensaState *env, uint32_t v, uint32_t dtlb) @@ -499,7 +521,7 @@ void HELPER(itlb)(CPUXtensaState *env, uint32_t v, uint32_t dtlb) if (xtensa_option_enabled(env->config, XTENSA_OPTION_MMU)) { uint32_t wi; xtensa_tlb_entry *entry = get_tlb_entry(env, v, dtlb, &wi); - if (entry->variable && entry->asid) { + if (entry && entry->variable && entry->asid) { tlb_flush_page(env_cpu(env), entry->vaddr); entry->asid = 0; } @@ -537,8 +559,9 @@ void HELPER(wtlb)(CPUXtensaState *env, uint32_t p, uint32_t v, uint32_t dtlb) uint32_t vpn; uint32_t wi; uint32_t ei; - split_tlb_entry_spec(env, v, dtlb, &vpn, &wi, &ei); - xtensa_tlb_set_entry(env, dtlb, wi, ei, vpn, p); + if (split_tlb_entry_spec(env, v, dtlb, &vpn, &wi, &ei)) { + xtensa_tlb_set_entry(env, dtlb, wi, ei, vpn, p); + } } /*! diff --git a/tcg/arm/tcg-target.c.inc b/tcg/arm/tcg-target.c.inc index fc78566494..a9aa8aa91c 100644 --- a/tcg/arm/tcg-target.c.inc +++ b/tcg/arm/tcg-target.c.inc @@ -1662,6 +1662,9 @@ static void tcg_out_qemu_st_direct(TCGContext *s, MemOp opc, TCGReg datalo, } else { tcg_out_strd_r(s, h.cond, datalo, h.base, h.index); } + } else if (h.index < 0) { + tcg_out_st32_12(s, h.cond, datalo, h.base, 0); + tcg_out_st32_12(s, h.cond, datahi, h.base, 4); } else if (h.index_scratch) { tcg_out_st32_rwb(s, h.cond, datalo, h.index, h.base); tcg_out_st32_12(s, h.cond, datahi, h.index, 4); diff --git a/tcg/loongarch64/tcg-target.c.inc b/tcg/loongarch64/tcg-target.c.inc index a588fb3085..bab0a173a3 100644 --- a/tcg/loongarch64/tcg-target.c.inc +++ b/tcg/loongarch64/tcg-target.c.inc @@ -308,6 +308,9 @@ static bool tcg_out_mov(TCGContext *s, TCGType type, TCGReg ret, TCGReg arg) */ tcg_out_opc_or(s, ret, arg, TCG_REG_ZERO); break; + case TCG_TYPE_V128: + tcg_out_opc_vori_b(s, ret, arg, 0); + break; default: g_assert_not_reached(); } diff --git a/tcg/ppc/tcg-target-con-set.h b/tcg/ppc/tcg-target-con-set.h index bbd7b21247..cb47b29452 100644 --- a/tcg/ppc/tcg-target-con-set.h +++ b/tcg/ppc/tcg-target-con-set.h @@ -35,7 +35,7 @@ C_O1_I3(v, v, v, v) C_O1_I4(r, r, ri, rZ, rZ) C_O1_I4(r, r, r, ri, ri) C_O2_I1(r, r, r) -C_O2_I1(o, m, r) +C_N1O1_I1(o, m, r) C_O2_I2(r, r, r, r) C_O2_I4(r, r, rI, rZM, r, r) C_O2_I4(r, r, r, r, rI, rZM) diff --git a/tcg/ppc/tcg-target.c.inc b/tcg/ppc/tcg-target.c.inc index 856c3b18f5..54816967bc 100644 --- a/tcg/ppc/tcg-target.c.inc +++ b/tcg/ppc/tcg-target.c.inc @@ -2595,6 +2595,7 @@ static void tcg_out_qemu_ldst_i128(TCGContext *s, TCGReg datalo, TCGReg datahi, tcg_debug_assert(!need_bswap); tcg_debug_assert(datalo & 1); tcg_debug_assert(datahi == datalo - 1); + tcg_debug_assert(!is_ld || datahi != index); insn = is_ld ? LQ : STQ; tcg_out32(s, insn | TAI(datahi, index, 0)); } else { @@ -4071,7 +4072,7 @@ static TCGConstraintSetIndex tcg_target_op_def(TCGOpcode op) case INDEX_op_qemu_ld_a32_i128: case INDEX_op_qemu_ld_a64_i128: - return C_O2_I1(o, m, r); + return C_N1O1_I1(o, m, r); case INDEX_op_qemu_st_a32_i128: case INDEX_op_qemu_st_a64_i128: return C_O0_I3(o, m, r); diff --git a/tcg/s390x/tcg-target.c.inc b/tcg/s390x/tcg-target.c.inc index fbee43d3b0..7f6b84aa2c 100644 --- a/tcg/s390x/tcg-target.c.inc +++ b/tcg/s390x/tcg-target.c.inc @@ -683,7 +683,7 @@ static void tcg_out_insn_VRIc(TCGContext *s, S390Opcode op, tcg_debug_assert(is_vector_reg(v3)); tcg_out16(s, (op & 0xff00) | ((v1 & 0xf) << 4) | (v3 & 0xf)); tcg_out16(s, i2); - tcg_out16(s, (op & 0x00ff) | RXB(v1, 0, v3, 0) | (m4 << 12)); + tcg_out16(s, (op & 0x00ff) | RXB(v1, v3, 0, 0) | (m4 << 12)); } static void tcg_out_insn_VRRa(TCGContext *s, S390Opcode op, @@ -738,7 +738,7 @@ static void tcg_out_insn_VRSa(TCGContext *s, S390Opcode op, TCGReg v1, tcg_debug_assert(is_vector_reg(v3)); tcg_out16(s, (op & 0xff00) | ((v1 & 0xf) << 4) | (v3 & 0xf)); tcg_out16(s, b2 << 12 | d2); - tcg_out16(s, (op & 0x00ff) | RXB(v1, 0, v3, 0) | (m4 << 12)); + tcg_out16(s, (op & 0x00ff) | RXB(v1, v3, 0, 0) | (m4 << 12)); } static void tcg_out_insn_VRSb(TCGContext *s, S390Opcode op, TCGReg v1, @@ -762,7 +762,7 @@ static void tcg_out_insn_VRSc(TCGContext *s, S390Opcode op, TCGReg r1, tcg_debug_assert(is_vector_reg(v3)); tcg_out16(s, (op & 0xff00) | (r1 << 4) | (v3 & 0xf)); tcg_out16(s, b2 << 12 | d2); - tcg_out16(s, (op & 0x00ff) | RXB(0, 0, v3, 0) | (m4 << 12)); + tcg_out16(s, (op & 0x00ff) | RXB(0, v3, 0, 0) | (m4 << 12)); } static void tcg_out_insn_VRX(TCGContext *s, S390Opcode op, TCGReg v1, diff --git a/tcg/tcg-op-ldst.c b/tcg/tcg-op-ldst.c index 9b39055396..4e94c064bf 100644 --- a/tcg/tcg-op-ldst.c +++ b/tcg/tcg-op-ldst.c @@ -77,6 +77,13 @@ static MemOp tcg_canonicalize_memop(MemOp op, bool is64, bool st) if (st) { op &= ~MO_SIGN; } + + /* In serial mode, reduce atomicity. */ + if (!(tcg_ctx->gen_tb->cflags & CF_PARALLEL)) { + op &= ~MO_ATOM_MASK; + op |= MO_ATOM_NONE; + } + return op; } @@ -459,8 +466,7 @@ static bool use_two_i64_for_i128(MemOp mop) case MO_ATOM_SUBALIGN: case MO_ATOM_WITHIN16: case MO_ATOM_WITHIN16_PAIR: - /* In a serialized context, no atomicity is required. */ - return !(tcg_ctx->gen_tb->cflags & CF_PARALLEL); + return false; default: g_assert_not_reached(); } @@ -530,13 +536,20 @@ static void maybe_free_addr64(TCGv_i64 a64) static void tcg_gen_qemu_ld_i128_int(TCGv_i128 val, TCGTemp *addr, TCGArg idx, MemOp memop) { - const MemOpIdx orig_oi = make_memop_idx(memop, idx); + MemOpIdx orig_oi; TCGv_i64 ext_addr = NULL; TCGOpcode opc; check_max_alignment(get_alignment_bits(memop)); tcg_gen_req_mo(TCG_MO_LD_LD | TCG_MO_ST_LD); + /* In serial mode, reduce atomicity. */ + if (!(tcg_ctx->gen_tb->cflags & CF_PARALLEL)) { + memop &= ~MO_ATOM_MASK; + memop |= MO_ATOM_NONE; + } + orig_oi = make_memop_idx(memop, idx); + /* TODO: For now, force 32-bit hosts to use the helper. */ if (TCG_TARGET_HAS_qemu_ldst_i128 && TCG_TARGET_REG_BITS == 64) { TCGv_i64 lo, hi; @@ -639,13 +652,20 @@ void tcg_gen_qemu_ld_i128_chk(TCGv_i128 val, TCGTemp *addr, TCGArg idx, static void tcg_gen_qemu_st_i128_int(TCGv_i128 val, TCGTemp *addr, TCGArg idx, MemOp memop) { - const MemOpIdx orig_oi = make_memop_idx(memop, idx); + MemOpIdx orig_oi; TCGv_i64 ext_addr = NULL; TCGOpcode opc; check_max_alignment(get_alignment_bits(memop)); tcg_gen_req_mo(TCG_MO_ST_LD | TCG_MO_ST_ST); + /* In serial mode, reduce atomicity. */ + if (!(tcg_ctx->gen_tb->cflags & CF_PARALLEL)) { + memop &= ~MO_ATOM_MASK; + memop |= MO_ATOM_NONE; + } + orig_oi = make_memop_idx(memop, idx); + /* TODO: For now, force 32-bit hosts to use the helper. */ if (TCG_TARGET_HAS_qemu_ldst_i128 && TCG_TARGET_REG_BITS == 64) { diff --git a/tcg/tcg.c b/tcg/tcg.c index 564e2fc148..5329350f0f 100644 --- a/tcg/tcg.c +++ b/tcg/tcg.c @@ -653,6 +653,7 @@ static void tcg_out_movext3(TCGContext *s, const TCGMovExtend *i1, #define C_O1_I4(O1, I1, I2, I3, I4) C_PFX5(c_o1_i4_, O1, I1, I2, I3, I4), #define C_N1_I2(O1, I1, I2) C_PFX3(c_n1_i2_, O1, I1, I2), +#define C_N1O1_I1(O1, O2, I1) C_PFX3(c_n1o1_i1_, O1, O2, I1), #define C_N2_I1(O1, O2, I1) C_PFX3(c_n2_i1_, O1, O2, I1), #define C_O2_I1(O1, O2, I1) C_PFX3(c_o2_i1_, O1, O2, I1), @@ -676,6 +677,7 @@ static TCGConstraintSetIndex tcg_target_op_def(TCGOpcode); #undef C_O1_I3 #undef C_O1_I4 #undef C_N1_I2 +#undef C_N1O1_I1 #undef C_N2_I1 #undef C_O2_I1 #undef C_O2_I2 @@ -696,6 +698,7 @@ static TCGConstraintSetIndex tcg_target_op_def(TCGOpcode); #define C_O1_I4(O1, I1, I2, I3, I4) { .args_ct_str = { #O1, #I1, #I2, #I3, #I4 } }, #define C_N1_I2(O1, I1, I2) { .args_ct_str = { "&" #O1, #I1, #I2 } }, +#define C_N1O1_I1(O1, O2, I1) { .args_ct_str = { "&" #O1, #O2, #I1 } }, #define C_N2_I1(O1, O2, I1) { .args_ct_str = { "&" #O1, "&" #O2, #I1 } }, #define C_O2_I1(O1, O2, I1) { .args_ct_str = { #O1, #O2, #I1 } }, @@ -718,6 +721,7 @@ static const TCGTargetOpDef constraint_sets[] = { #undef C_O1_I3 #undef C_O1_I4 #undef C_N1_I2 +#undef C_N1O1_I1 #undef C_N2_I1 #undef C_O2_I1 #undef C_O2_I2 @@ -738,6 +742,7 @@ static const TCGTargetOpDef constraint_sets[] = { #define C_O1_I4(O1, I1, I2, I3, I4) C_PFX5(c_o1_i4_, O1, I1, I2, I3, I4) #define C_N1_I2(O1, I1, I2) C_PFX3(c_n1_i2_, O1, I1, I2) +#define C_N1O1_I1(O1, O2, I1) C_PFX3(c_n1o1_i1_, O1, O2, I1) #define C_N2_I1(O1, O2, I1) C_PFX3(c_n2_i1_, O1, O2, I1) #define C_O2_I1(O1, O2, I1) C_PFX3(c_o2_i1_, O1, O2, I1) @@ -2994,6 +2999,7 @@ static void process_op_defs(TCGContext *s) .pair = 2, .pair_index = o, .regs = def->args_ct[o].regs << 1, + .newreg = def->args_ct[o].newreg, }; def->args_ct[o].pair = 1; def->args_ct[o].pair_index = i; @@ -3010,6 +3016,7 @@ static void process_op_defs(TCGContext *s) .pair = 1, .pair_index = o, .regs = def->args_ct[o].regs >> 1, + .newreg = def->args_ct[o].newreg, }; def->args_ct[o].pair = 2; def->args_ct[o].pair_index = i; @@ -5042,17 +5049,21 @@ static void tcg_reg_alloc_op(TCGContext *s, const TCGOp *op) break; case 1: /* first of pair */ - tcg_debug_assert(!arg_ct->newreg); if (arg_ct->oalias) { reg = new_args[arg_ct->alias_index]; - break; + } else if (arg_ct->newreg) { + reg = tcg_reg_alloc_pair(s, arg_ct->regs, + i_allocated_regs | o_allocated_regs, + output_pref(op, k), + ts->indirect_base); + } else { + reg = tcg_reg_alloc_pair(s, arg_ct->regs, o_allocated_regs, + output_pref(op, k), + ts->indirect_base); } - reg = tcg_reg_alloc_pair(s, arg_ct->regs, o_allocated_regs, - output_pref(op, k), ts->indirect_base); break; case 2: /* second of pair */ - tcg_debug_assert(!arg_ct->newreg); if (arg_ct->oalias) { reg = new_args[arg_ct->alias_index]; } else { @@ -5446,15 +5457,8 @@ static TCGAtomAlign atom_and_align_for_opc(TCGContext *s, MemOp opc, MemOp align = get_alignment_bits(opc); MemOp size = opc & MO_SIZE; MemOp half = size ? size - 1 : 0; + MemOp atom = opc & MO_ATOM_MASK; MemOp atmax; - MemOp atom; - - /* When serialized, no further atomicity required. */ - if (s->gen_tb->cflags & CF_PARALLEL) { - atom = opc & MO_ATOM_MASK; - } else { - atom = MO_ATOM_NONE; - } switch (atom) { case MO_ATOM_NONE: diff --git a/tests/Makefile.include b/tests/Makefile.include index dab1989a07..c9d1674bd0 100644 --- a/tests/Makefile.include +++ b/tests/Makefile.include @@ -111,7 +111,7 @@ quiet-venv-pip = $(quiet-@)$(call quiet-command-run, \ $(TESTS_VENV_TOKEN): $(SRC_PATH)/pythondeps.toml $(call quiet-venv-pip,install -e "$(SRC_PATH)/python/") - $(PYTHON) python/scripts/mkvenv.py ensuregroup --online $< avocado + $(MKVENV_ENSUREGROUP) $< avocado $(call quiet-command, touch $@) $(TESTS_RESULTS_DIR): diff --git a/tests/avocado/acpi-bits.py b/tests/avocado/acpi-bits.py index 68b9e98d4e..efe4f52ee0 100644 --- a/tests/avocado/acpi-bits.py +++ b/tests/avocado/acpi-bits.py @@ -54,6 +54,8 @@ from avocado_qemu import QemuBaseTest deps = ["xorriso", "mformat"] # dependent tools needed in the test setup/box. supported_platforms = ['x86_64'] # supported test platforms. +# default timeout of 120 secs is sometimes not enough for bits test. +BITS_TIMEOUT = 200 def which(tool): """ looks up the full path for @tool, returns None if not found @@ -133,7 +135,7 @@ class AcpiBitsTest(QemuBaseTest): #pylint: disable=too-many-instance-attributes """ # in slower systems the test can take as long as 3 minutes to complete. - timeout = 200 + timeout = BITS_TIMEOUT def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) @@ -400,7 +402,8 @@ class AcpiBitsTest(QemuBaseTest): #pylint: disable=too-many-instance-attributes # biosbits has been configured to run all the specified test suites # in batch mode and then automatically initiate a vm shutdown. - # Rely on avocado's unit test timeout. - self._vm.event_wait('SHUTDOWN') + # Set timeout to BITS_TIMEOUT for SHUTDOWN event from bits VM at par + # with the avocado test timeout. + self._vm.event_wait('SHUTDOWN', timeout=BITS_TIMEOUT) self._vm.wait(timeout=None) self.parse_log() diff --git a/tests/avocado/avocado_qemu/__init__.py b/tests/avocado/avocado_qemu/__init__.py index d71e989db6..304c428168 100644 --- a/tests/avocado/avocado_qemu/__init__.py +++ b/tests/avocado/avocado_qemu/__init__.py @@ -254,7 +254,7 @@ class QemuBaseTest(avocado.Test): self.cancel("No QEMU binary defined or found in the build tree") def fetch_asset(self, name, - asset_hash=None, algorithm=None, + asset_hash, algorithm=None, locations=None, expire=None, find_only=False, cancel_on_missing=True): return super().fetch_asset(name, diff --git a/tests/avocado/boot_linux.py b/tests/avocado/boot_linux.py index be30dcbd58..7c4769904e 100644 --- a/tests/avocado/boot_linux.py +++ b/tests/avocado/boot_linux.py @@ -12,7 +12,7 @@ import os from avocado_qemu import LinuxTest, BUILD_DIR -from avocado import skipIf +from avocado import skipUnless class BootLinuxX8664(LinuxTest): @@ -93,11 +93,13 @@ class BootLinuxPPC64(LinuxTest): timeout = 360 - @skipIf(os.getenv('GITLAB_CI'), 'Running on GitLab') + @skipUnless(os.getenv('QEMU_TEST_FLAKY_TESTS'), 'Test is unstable on GitLab') + def test_pseries_tcg(self): """ :avocado: tags=machine:pseries :avocado: tags=accel:tcg + :avocado: tags=flaky """ self.require_accelerator("tcg") self.vm.add_args("-accel", "tcg") @@ -111,11 +113,13 @@ class BootLinuxS390X(LinuxTest): timeout = 240 - @skipIf(os.getenv('GITLAB_CI'), 'Running on GitLab') + @skipUnless(os.getenv('QEMU_TEST_FLAKY_TESTS'), 'Test is unstable on GitLab') + def test_s390_ccw_virtio_tcg(self): """ :avocado: tags=machine:s390-ccw-virtio :avocado: tags=accel:tcg + :avocado: tags=flaky """ self.require_accelerator("tcg") self.vm.add_args("-accel", "tcg") diff --git a/tests/avocado/boot_linux_console.py b/tests/avocado/boot_linux_console.py index 6eab515718..3f0180e1f8 100644 --- a/tests/avocado/boot_linux_console.py +++ b/tests/avocado/boot_linux_console.py @@ -15,7 +15,7 @@ import shutil from avocado import skip from avocado import skipUnless -from avocado import skipIf +from avocado import skipUnless from avocado_qemu import QemuSystemTest from avocado_qemu import exec_command from avocado_qemu import exec_command_and_wait_for_pattern @@ -1419,11 +1419,13 @@ class BootLinuxConsole(LinuxKernelTest): # This test has a 6-10% failure rate on various hosts that look # like issues with a buggy kernel. As a result we don't want it # gating releases on Gitlab. - @skipIf(os.getenv('GITLAB_CI'), 'Running on GitLab') + @skipUnless(os.getenv('QEMU_TEST_FLAKY_TESTS'), 'Test is unstable on GitLab') + def test_sh4_r2d(self): """ :avocado: tags=arch:sh4 :avocado: tags=machine:r2d + :avocado: tags=flaky """ tar_hash = 'fe06a4fd8ccbf2e27928d64472939d47829d4c7e' self.vm.add_args('-append', 'console=ttySC1') diff --git a/tests/avocado/cpu_queries.py b/tests/avocado/cpu_queries.py index 86c2d5c92d..d3faa14720 100644 --- a/tests/avocado/cpu_queries.py +++ b/tests/avocado/cpu_queries.py @@ -32,4 +32,4 @@ class QueryCPUModelExpansion(QemuSystemTest): model = {'name': c['name']} e = self.vm.cmd('query-cpu-model-expansion', model=model, type='full') - self.assertEquals(e['model']['name'], c['name']) + self.assertEqual(e['model']['name'], c['name']) diff --git a/tests/avocado/empty_cpu_model.py b/tests/avocado/empty_cpu_model.py index 22f504418d..d906ef3d3c 100644 --- a/tests/avocado/empty_cpu_model.py +++ b/tests/avocado/empty_cpu_model.py @@ -15,5 +15,5 @@ class EmptyCPUModel(QemuSystemTest): self.vm.set_qmp_monitor(enabled=False) self.vm.launch() self.vm.wait() - self.assertEquals(self.vm.exitcode(), 1, "QEMU exit code should be 1") + self.assertEqual(self.vm.exitcode(), 1, "QEMU exit code should be 1") self.assertRegex(self.vm.get_log(), r'-cpu option cannot be empty') diff --git a/tests/avocado/intel_iommu.py b/tests/avocado/intel_iommu.py index 474d62f6bf..f04ee1cf9d 100644 --- a/tests/avocado/intel_iommu.py +++ b/tests/avocado/intel_iommu.py @@ -9,10 +9,11 @@ # later. See the COPYING file in the top-level directory. import os -from avocado import skipIf +from avocado import skipUnless from avocado_qemu import LinuxTest -@skipIf(os.getenv('GITLAB_CI'), 'Running on GitLab') +@skipUnless(os.getenv('QEMU_TEST_FLAKY_TESTS'), 'Test is unstable on GitLab') + class IntelIOMMU(LinuxTest): """ :avocado: tags=arch:x86_64 @@ -21,6 +22,7 @@ class IntelIOMMU(LinuxTest): :avocado: tags=machine:q35 :avocado: tags=accel:kvm :avocado: tags=intel_iommu + :avocado: tags=flaky """ IOMMU_ADDON = ',iommu_platform=on,disable-modern=off,disable-legacy=on' @@ -54,9 +56,11 @@ class IntelIOMMU(LinuxTest): return kernel_url = self.distro.pxeboot_url + 'vmlinuz' + kernel_hash = '5b6f6876e1b5bda314f93893271da0d5777b1f3c' initrd_url = self.distro.pxeboot_url + 'initrd.img' - self.kernel_path = self.fetch_asset(kernel_url) - self.initrd_path = self.fetch_asset(initrd_url) + initrd_hash = 'dd0340a1b39bd28f88532babd4581c67649ec5b1' + self.kernel_path = self.fetch_asset(kernel_url, asset_hash=kernel_hash) + self.initrd_path = self.fetch_asset(initrd_url, asset_hash=initrd_hash) def run_and_check(self): if self.kernel_path: diff --git a/tests/avocado/linux_initrd.py b/tests/avocado/linux_initrd.py index ba02e5a563..aad5b19bd9 100644 --- a/tests/avocado/linux_initrd.py +++ b/tests/avocado/linux_initrd.py @@ -13,7 +13,7 @@ import logging import tempfile from avocado_qemu import QemuSystemTest -from avocado import skipIf +from avocado import skipUnless class LinuxInitrd(QemuSystemTest): @@ -53,9 +53,12 @@ class LinuxInitrd(QemuSystemTest): max_size + 1) self.assertRegex(self.vm.get_log(), expected_msg) - @skipIf(os.getenv('GITLAB_CI'), 'Running on GitLab') + @skipUnless(os.getenv('QEMU_TEST_FLAKY_TESTS'), 'Test is unstable on GitLab') + def test_with_2gib_file_should_work_with_linux_v4_16(self): """ + :avocado: tags=flaky + QEMU has supported up to 4 GiB initrd for recent kernel Expect guest can reach 'Unpacking initramfs...' """ diff --git a/tests/avocado/machine_aarch64_sbsaref.py b/tests/avocado/machine_aarch64_sbsaref.py index bdd1efc768..528c7d2934 100644 --- a/tests/avocado/machine_aarch64_sbsaref.py +++ b/tests/avocado/machine_aarch64_sbsaref.py @@ -20,6 +20,10 @@ class Aarch64SbsarefMachine(QemuSystemTest): """ :avocado: tags=arch:aarch64 :avocado: tags=machine:sbsa-ref + :avocado: tags=accel:tcg + + As firmware runs at a higher privilege level than the hypervisor we + can only run these tests under TCG emulation. """ timeout = 180 diff --git a/tests/avocado/machine_aspeed.py b/tests/avocado/machine_aspeed.py index df31b2a8a8..6fa5459a07 100644 --- a/tests/avocado/machine_aspeed.py +++ b/tests/avocado/machine_aspeed.py @@ -18,7 +18,7 @@ from avocado_qemu import exec_command_and_wait_for_pattern from avocado_qemu import interrupt_interactive_console_until_pattern from avocado_qemu import has_cmd from avocado.utils import archive -from avocado import skipIf +from avocado import skipUnless from avocado import skipUnless @@ -311,11 +311,13 @@ class AST2x00MachineSDK(QemuSystemTest, LinuxSSHMixIn): self, 'boot', '## Loading kernel from FIT Image') self.wait_for_console_pattern('Starting kernel ...') - @skipIf(os.getenv('GITLAB_CI'), 'Running on GitLab') + @skipUnless(os.getenv('QEMU_TEST_FLAKY_TESTS'), 'Test is unstable on GitLab') + def test_arm_ast2500_evb_sdk(self): """ :avocado: tags=arch:arm :avocado: tags=machine:ast2500-evb + :avocado: tags=flaky """ image_url = ('https://github.com/AspeedTech-BMC/openbmc/releases/' @@ -329,11 +331,13 @@ class AST2x00MachineSDK(QemuSystemTest, LinuxSSHMixIn): self.workdir + '/ast2500-default/image-bmc') self.wait_for_console_pattern('nodistro.0 ast2500-default ttyS4') - @skipIf(os.getenv('GITLAB_CI'), 'Running on GitLab') + @skipUnless(os.getenv('QEMU_TEST_FLAKY_TESTS'), 'Test is unstable on GitLab') + def test_arm_ast2600_evb_sdk(self): """ :avocado: tags=arch:arm :avocado: tags=machine:ast2600-evb + :avocado: tags=flaky """ image_url = ('https://github.com/AspeedTech-BMC/openbmc/releases/' diff --git a/tests/avocado/machine_mips_malta.py b/tests/avocado/machine_mips_malta.py index 9bd54518bf..8cf84bd805 100644 --- a/tests/avocado/machine_mips_malta.py +++ b/tests/avocado/machine_mips_malta.py @@ -11,7 +11,7 @@ import os import gzip import logging -from avocado import skipIf +from avocado import skipUnless from avocado import skipUnless from avocado.utils import archive from avocado_qemu import QemuSystemTest @@ -101,31 +101,36 @@ class MaltaMachineFramebuffer(QemuSystemTest): """ self.do_test_i6400_framebuffer_logo(1) - @skipIf(os.getenv('GITLAB_CI'), 'Running on GitLab') + @skipUnless(os.getenv('QEMU_TEST_FLAKY_TESTS'), 'Test is unstable on GitLab') + def test_mips_malta_i6400_framebuffer_logo_7cores(self): """ :avocado: tags=arch:mips64el :avocado: tags=machine:malta :avocado: tags=cpu:I6400 :avocado: tags=mips:smp + :avocado: tags=flaky """ self.do_test_i6400_framebuffer_logo(7) - @skipIf(os.getenv('GITLAB_CI'), 'Running on GitLab') + @skipUnless(os.getenv('QEMU_TEST_FLAKY_TESTS'), 'Test is unstable on GitLab') + def test_mips_malta_i6400_framebuffer_logo_8cores(self): """ :avocado: tags=arch:mips64el :avocado: tags=machine:malta :avocado: tags=cpu:I6400 :avocado: tags=mips:smp + :avocado: tags=flaky """ self.do_test_i6400_framebuffer_logo(8) class MaltaMachine(QemuSystemTest): def do_test_yamon(self): - rom_url = ('http://www.imgtec.com/tools/mips-tools/downloads/' - 'yamon/yamon-bin-02.22.zip') + rom_url = ('https://s3-eu-west-1.amazonaws.com/' + 'downloads-mips/mips-downloads/' + 'YAMON/yamon-bin-02.22.zip') rom_hash = '8da7ecddbc5312704b8b324341ee238189bde480' zip_path = self.fetch_asset(rom_url, asset_hash=rom_hash) diff --git a/tests/avocado/machine_rx_gdbsim.py b/tests/avocado/machine_rx_gdbsim.py index 6cd8704b01..412a7a5089 100644 --- a/tests/avocado/machine_rx_gdbsim.py +++ b/tests/avocado/machine_rx_gdbsim.py @@ -10,7 +10,7 @@ import os -from avocado import skipIf +from avocado import skipUnless from avocado_qemu import QemuSystemTest from avocado_qemu import exec_command_and_wait_for_pattern from avocado_qemu import wait_for_console_pattern @@ -22,7 +22,8 @@ class RxGdbSimMachine(QemuSystemTest): timeout = 30 KERNEL_COMMON_COMMAND_LINE = 'printk.time=0 ' - @skipIf(os.getenv('GITLAB_CI'), 'Running on GitLab') + @skipUnless(os.getenv('QEMU_TEST_FLAKY_TESTS'), 'Test is unstable on GitLab') + def test_uboot(self): """ U-Boot and checks that the console is operational. @@ -30,6 +31,7 @@ class RxGdbSimMachine(QemuSystemTest): :avocado: tags=arch:rx :avocado: tags=machine:gdbsim-r5f562n8 :avocado: tags=endian:little + :avocado: tags=flaky """ uboot_url = ('https://acc.dl.osdn.jp/users/23/23888/u-boot.bin.gz') uboot_hash = '9b78dbd43b40b2526848c0b1ce9de02c24f4dcdb' @@ -46,7 +48,8 @@ class RxGdbSimMachine(QemuSystemTest): # FIXME limit baudrate on chardev, else we type too fast #exec_command_and_wait_for_pattern(self, 'version', gcc_version) - @skipIf(os.getenv('GITLAB_CI'), 'Running on GitLab') + @skipUnless(os.getenv('QEMU_TEST_FLAKY_TESTS'), 'Test is unstable on GitLab') + def test_linux_sash(self): """ Boots a Linux kernel and checks that the console is operational. @@ -54,6 +57,7 @@ class RxGdbSimMachine(QemuSystemTest): :avocado: tags=arch:rx :avocado: tags=machine:gdbsim-r5f562n7 :avocado: tags=endian:little + :avocado: tags=flaky """ dtb_url = ('https://acc.dl.osdn.jp/users/23/23887/rx-virt.dtb') dtb_hash = '7b4e4e2c71905da44e86ce47adee2210b026ac18' diff --git a/tests/avocado/machine_s390_ccw_virtio.py b/tests/avocado/machine_s390_ccw_virtio.py index ffd914ded9..26e938c9e9 100644 --- a/tests/avocado/machine_s390_ccw_virtio.py +++ b/tests/avocado/machine_s390_ccw_virtio.py @@ -12,7 +12,7 @@ import os import tempfile -from avocado import skipIf +from avocado import skipUnless from avocado_qemu import QemuSystemTest from avocado_qemu import exec_command_and_wait_for_pattern from avocado_qemu import wait_for_console_pattern @@ -167,6 +167,7 @@ class S390CCWVirtioMachine(QemuSystemTest): :avocado: tags=device:virtio-gpu :avocado: tags=device:virtio-crypto :avocado: tags=device:virtio-net + :avocado: tags=flaky """ kernel_url = ('https://archives.fedoraproject.org/pub/archive' diff --git a/tests/avocado/mem-addr-space-check.py b/tests/avocado/mem-addr-space-check.py index be949222a4..363c3f12a6 100644 --- a/tests/avocado/mem-addr-space-check.py +++ b/tests/avocado/mem-addr-space-check.py @@ -49,7 +49,7 @@ class MemAddrCheck(QemuSystemTest): self.vm.set_qmp_monitor(enabled=False) self.vm.launch() self.vm.wait() - self.assertEquals(self.vm.exitcode(), 1, "QEMU exit code should be 1") + self.assertEqual(self.vm.exitcode(), 1, "QEMU exit code should be 1") self.assertRegex(self.vm.get_log(), r'phys-bits too low') def test_phybits_low_pae(self): @@ -69,7 +69,7 @@ class MemAddrCheck(QemuSystemTest): self.vm.set_qmp_monitor(enabled=False) self.vm.launch() self.vm.wait() - self.assertEquals(self.vm.exitcode(), 1, "QEMU exit code should be 1") + self.assertEqual(self.vm.exitcode(), 1, "QEMU exit code should be 1") self.assertRegex(self.vm.get_log(), r'phys-bits too low') def test_phybits_ok_pentium_pse36(self): @@ -149,7 +149,7 @@ class MemAddrCheck(QemuSystemTest): self.vm.set_qmp_monitor(enabled=False) self.vm.launch() self.vm.wait() - self.assertEquals(self.vm.exitcode(), 1, "QEMU exit code should be 1") + self.assertEqual(self.vm.exitcode(), 1, "QEMU exit code should be 1") self.assertRegex(self.vm.get_log(), r'phys-bits too low') # now lets test some 64-bit CPU cases. @@ -179,7 +179,7 @@ class MemAddrCheck(QemuSystemTest): self.vm.set_qmp_monitor(enabled=False) self.vm.launch() self.vm.wait() - self.assertEquals(self.vm.exitcode(), 1, "QEMU exit code should be 1") + self.assertEqual(self.vm.exitcode(), 1, "QEMU exit code should be 1") self.assertRegex(self.vm.get_log(), r'phys-bits too low') def test_phybits_low_tcg_q35_71_amd(self): @@ -202,7 +202,7 @@ class MemAddrCheck(QemuSystemTest): self.vm.set_qmp_monitor(enabled=False) self.vm.launch() self.vm.wait() - self.assertEquals(self.vm.exitcode(), 1, "QEMU exit code should be 1") + self.assertEqual(self.vm.exitcode(), 1, "QEMU exit code should be 1") self.assertRegex(self.vm.get_log(), r'phys-bits too low') def test_phybits_ok_tcg_q35_70_amd(self): @@ -288,7 +288,7 @@ class MemAddrCheck(QemuSystemTest): self.vm.set_qmp_monitor(enabled=False) self.vm.launch() self.vm.wait() - self.assertEquals(self.vm.exitcode(), 1, "QEMU exit code should be 1") + self.assertEqual(self.vm.exitcode(), 1, "QEMU exit code should be 1") self.assertRegex(self.vm.get_log(), r'phys-bits too low') def test_phybits_ok_tcg_q35_71_amd_41bits(self): @@ -332,7 +332,7 @@ class MemAddrCheck(QemuSystemTest): self.vm.set_qmp_monitor(enabled=False) self.vm.launch() self.vm.wait() - self.assertEquals(self.vm.exitcode(), 1, "QEMU exit code should be 1") + self.assertEqual(self.vm.exitcode(), 1, "QEMU exit code should be 1") self.assertRegex(self.vm.get_log(), r'phys-bits too low') def test_phybits_ok_tcg_q35_intel_cxl(self): diff --git a/tests/avocado/multiprocess.py b/tests/avocado/multiprocess.py index 9112a4cacc..ee7490ae08 100644 --- a/tests/avocado/multiprocess.py +++ b/tests/avocado/multiprocess.py @@ -18,8 +18,8 @@ class Multiprocess(QemuSystemTest): """ KERNEL_COMMON_COMMAND_LINE = 'printk.time=0 ' - def do_test(self, kernel_url, initrd_url, kernel_command_line, - machine_type): + def do_test(self, kernel_url, kernel_hash, initrd_url, initrd_hash, + kernel_command_line, machine_type): """Main test method""" self.require_accelerator('kvm') self.require_multiprocess() @@ -30,8 +30,8 @@ class Multiprocess(QemuSystemTest): os.set_inheritable(proxy_sock.fileno(), True) os.set_inheritable(remote_sock.fileno(), True) - kernel_path = self.fetch_asset(kernel_url) - initrd_path = self.fetch_asset(initrd_url) + kernel_path = self.fetch_asset(kernel_url, asset_hash=kernel_hash) + initrd_path = self.fetch_asset(initrd_url, asset_hash=initrd_hash) # Create remote process remote_vm = self.get_vm() @@ -72,13 +72,16 @@ class Multiprocess(QemuSystemTest): kernel_url = ('https://archives.fedoraproject.org/pub/archive/fedora' '/linux/releases/31/Everything/x86_64/os/images' '/pxeboot/vmlinuz') + kernel_hash = '5b6f6876e1b5bda314f93893271da0d5777b1f3c' initrd_url = ('https://archives.fedoraproject.org/pub/archive/fedora' '/linux/releases/31/Everything/x86_64/os/images' '/pxeboot/initrd.img') + initrd_hash = 'dd0340a1b39bd28f88532babd4581c67649ec5b1' kernel_command_line = (self.KERNEL_COMMON_COMMAND_LINE + 'console=ttyS0 rdinit=/bin/bash') machine_type = 'pc' - self.do_test(kernel_url, initrd_url, kernel_command_line, machine_type) + self.do_test(kernel_url, kernel_hash, initrd_url, initrd_hash, + kernel_command_line, machine_type) def test_multiprocess_aarch64(self): """ @@ -87,10 +90,13 @@ class Multiprocess(QemuSystemTest): kernel_url = ('https://archives.fedoraproject.org/pub/archive/fedora' '/linux/releases/31/Everything/aarch64/os/images' '/pxeboot/vmlinuz') + kernel_hash = '3505f2751e2833c681de78cee8dda1e49cabd2e8' initrd_url = ('https://archives.fedoraproject.org/pub/archive/fedora' '/linux/releases/31/Everything/aarch64/os/images' '/pxeboot/initrd.img') + initrd_hash = '519a1962daf17d67fc3a9c89d45affcb399607db' kernel_command_line = (self.KERNEL_COMMON_COMMAND_LINE + 'rdinit=/bin/bash console=ttyAMA0') machine_type = 'virt,gic-version=3' - self.do_test(kernel_url, initrd_url, kernel_command_line, machine_type) + self.do_test(kernel_url, kernel_hash, initrd_url, initrd_hash, + kernel_command_line, machine_type) diff --git a/tests/avocado/pc_cpu_hotplug_props.py b/tests/avocado/pc_cpu_hotplug_props.py index b56f51d02a..4bd3e02665 100644 --- a/tests/avocado/pc_cpu_hotplug_props.py +++ b/tests/avocado/pc_cpu_hotplug_props.py @@ -32,4 +32,4 @@ class OmittedCPUProps(QemuSystemTest): self.vm.add_args('-smp', '1,sockets=2,cores=2,threads=2,maxcpus=8') self.vm.add_args('-device', 'qemu64-x86_64-cpu,socket-id=1,core-id=0,thread-id=0') self.vm.launch() - self.assertEquals(len(self.vm.cmd('query-cpus-fast')), 2) + self.assertEqual(len(self.vm.cmd('query-cpus-fast')), 2) diff --git a/tests/avocado/replay_kernel.py b/tests/avocado/replay_kernel.py index a18610542e..c37afa662c 100644 --- a/tests/avocado/replay_kernel.py +++ b/tests/avocado/replay_kernel.py @@ -15,7 +15,7 @@ import logging import time from avocado import skip -from avocado import skipIf +from avocado import skipUnless from avocado import skipUnless from avocado_qemu import wait_for_console_pattern from avocado.utils import archive @@ -81,11 +81,14 @@ class ReplayKernelBase(LinuxKernelTest): logger.info('replay overhead {:.2%}'.format(t2 / t1 - 1)) class ReplayKernelNormal(ReplayKernelBase): - @skipIf(os.getenv('GITLAB_CI'), 'Running on GitLab') + + # See https://gitlab.com/qemu-project/qemu/-/issues/2010 + @skipUnless(os.getenv('QEMU_TEST_FLAKY_TESTS'), 'Test sometimes gets stuck') def test_x86_64_pc(self): """ :avocado: tags=arch:x86_64 :avocado: tags=machine:pc + :avocado: tags=flaky """ kernel_url = ('https://archives.fedoraproject.org/pub/archive/fedora' '/linux/releases/29/Everything/x86_64/os/images/pxeboot' @@ -116,6 +119,8 @@ class ReplayKernelNormal(ReplayKernelBase): self.run_rr(kernel_path, kernel_command_line, console_pattern, shift=5) + # See https://gitlab.com/qemu-project/qemu/-/issues/2013 + @skipUnless(os.getenv('QEMU_TEST_FLAKY_TESTS'), 'Test is unstable on GitLab') def test_mips64el_malta(self): """ This test requires the ar tool to extract "data.tar.gz" from @@ -131,6 +136,7 @@ class ReplayKernelNormal(ReplayKernelBase): :avocado: tags=arch:mips64el :avocado: tags=machine:malta + :avocado: tags=flaky """ deb_url = ('http://snapshot.debian.org/archive/debian/' '20130217T032700Z/pool/main/l/linux-2.6/' @@ -178,11 +184,13 @@ class ReplayKernelNormal(ReplayKernelBase): self.run_rr(kernel_path, kernel_command_line, console_pattern, shift=1) - @skipIf(os.getenv('GITLAB_CI'), 'Running on GitLab') + @skipUnless(os.getenv('QEMU_TEST_FLAKY_TESTS'), 'Test is unstable on GitLab') + def test_arm_cubieboard_initrd(self): """ :avocado: tags=arch:arm :avocado: tags=machine:cubieboard + :avocado: tags=flaky """ deb_url = ('https://apt.armbian.com/pool/main/l/' 'linux-5.10.16-sunxi/linux-image-current-sunxi_21.02.2_armhf.deb') diff --git a/tests/avocado/reverse_debugging.py b/tests/avocado/reverse_debugging.py index fc47874eda..4cce5a5598 100644 --- a/tests/avocado/reverse_debugging.py +++ b/tests/avocado/reverse_debugging.py @@ -10,8 +10,9 @@ import os import logging -from avocado import skipIf +from avocado import skipUnless from avocado_qemu import BUILD_DIR +from avocado.utils import datadrainer from avocado.utils import gdb from avocado.utils import process from avocado.utils.network.ports import find_free_port @@ -52,6 +53,10 @@ class ReverseDebugging(LinuxKernelTest): if args: vm.add_args(*args) vm.launch() + console_drainer = datadrainer.LineLogger(vm.console_socket.fileno(), + logger=self.log.getChild('console'), + stop_check=(lambda : not vm.is_running())) + console_drainer.start() return vm @staticmethod @@ -201,7 +206,8 @@ class ReverseDebugging_X86_64(ReverseDebugging): + self.get_reg_le(g, self.REG_CS) * 0x10 # unidentified gitlab timeout problem - @skipIf(os.getenv('GITLAB_CI'), 'Running on GitLab') + @skipUnless(os.getenv('QEMU_TEST_FLAKY_TESTS'), 'Test is unstable on GitLab') + def test_x86_64_pc(self): """ :avocado: tags=arch:x86_64 @@ -218,7 +224,8 @@ class ReverseDebugging_AArch64(ReverseDebugging): REG_PC = 32 # unidentified gitlab timeout problem - @skipIf(os.getenv('GITLAB_CI'), 'Running on GitLab') + @skipUnless(os.getenv('QEMU_TEST_FLAKY_TESTS'), 'Test is unstable on GitLab') + def test_aarch64_virt(self): """ :avocado: tags=arch:aarch64 @@ -242,11 +249,13 @@ class ReverseDebugging_ppc64(ReverseDebugging): REG_PC = 0x40 # unidentified gitlab timeout problem - @skipIf(os.getenv('GITLAB_CI'), 'Running on GitLab') + @skipUnless(os.getenv('QEMU_TEST_FLAKY_TESTS'), 'Test is unstable on GitLab') + def test_ppc64_pseries(self): """ :avocado: tags=arch:ppc64 :avocado: tags=machine:pseries + :avocado: tags=flaky """ # SLOF branches back to its entry point, which causes this test # to take the 'hit a breakpoint again' path. That's not a problem, @@ -254,11 +263,14 @@ class ReverseDebugging_ppc64(ReverseDebugging): self.endian_is_le = False self.reverse_debugging() - @skipIf(os.getenv('GITLAB_CI'), 'Running on GitLab') + # See https://gitlab.com/qemu-project/qemu/-/issues/1992 + @skipUnless(os.getenv('QEMU_TEST_FLAKY_TESTS'), 'Test is unstable on GitLab') + def test_ppc64_powernv(self): """ :avocado: tags=arch:ppc64 :avocado: tags=machine:powernv + :avocado: tags=flaky """ self.endian_is_le = False self.reverse_debugging() diff --git a/tests/avocado/smmu.py b/tests/avocado/smmu.py index b3c4de6bf4..21ff030ca7 100644 --- a/tests/avocado/smmu.py +++ b/tests/avocado/smmu.py @@ -9,10 +9,11 @@ # later. See the COPYING file in the top-level directory. import os -from avocado import skipIf +from avocado import skipUnless from avocado_qemu import LinuxTest, BUILD_DIR -@skipIf(os.getenv('GITLAB_CI'), 'Running on GitLab') +@skipUnless(os.getenv('QEMU_TEST_FLAKY_TESTS'), 'Test is unstable on GitLab') + class SMMU(LinuxTest): """ :avocado: tags=accel:kvm @@ -21,6 +22,7 @@ class SMMU(LinuxTest): :avocado: tags=machine:virt :avocado: tags=distro:fedora :avocado: tags=smmu + :avocado: tags=flaky """ IOMMU_ADDON = ',iommu_platform=on,disable-modern=off,disable-legacy=on' diff --git a/tests/avocado/tuxrun_baselines.py b/tests/avocado/tuxrun_baselines.py index c99bea6c0b..a936a3b780 100644 --- a/tests/avocado/tuxrun_baselines.py +++ b/tests/avocado/tuxrun_baselines.py @@ -13,7 +13,7 @@ import os import time import tempfile -from avocado import skip, skipIf +from avocado import skip, skipUnless from avocado_qemu import QemuSystemTest from avocado_qemu import exec_command, exec_command_and_wait_for_pattern from avocado_qemu import wait_for_console_pattern @@ -551,7 +551,7 @@ class TuxRunBaselineTest(QemuSystemTest): haltmsg="Requesting system halt") # Note: some segfaults caused by unaligned userspace access - @skipIf(os.getenv('GITLAB_CI'), 'Skipping unstable test on GitLab') + @skipUnless(os.getenv('QEMU_TEST_FLAKY_TESTS'), 'Test is unstable on GitLab') def test_sh4(self): """ :avocado: tags=arch:sh4 @@ -561,6 +561,7 @@ class TuxRunBaselineTest(QemuSystemTest): :avocado: tags=image:zImage :avocado: tags=root:sda :avocado: tags=console:ttySC1 + :avocado: tags=flaky """ sums = { "rootfs.ext4.zst" : "3592a7a3d5a641e8b9821449e77bc43c9904a56c30d45da0694349cfd86743fd", diff --git a/tests/avocado/version.py b/tests/avocado/version.py index 93ffdf3d97..c6139568a1 100644 --- a/tests/avocado/version.py +++ b/tests/avocado/version.py @@ -22,4 +22,4 @@ class Version(QemuSystemTest): self.vm.launch() res = self.vm.cmd('human-monitor-command', command_line='info version') - self.assertRegexpMatches(res, r'^(\d+\.\d+\.\d)') + self.assertRegex(res, r'^(\d+\.\d+\.\d)') diff --git a/tests/avocado/virtio-gpu.py b/tests/avocado/virtio-gpu.py index 89bfecc715..6091f614a4 100644 --- a/tests/avocado/virtio-gpu.py +++ b/tests/avocado/virtio-gpu.py @@ -149,10 +149,8 @@ class VirtioGPUx86(QemuSystemTest): # TODO: probably fails because we are missing the VirGL features self.cancel("VirGL not enabled?") self.wait_for_console_pattern("as init process") - exec_command_and_wait_for_pattern( - self, "/usr/sbin/modprobe virtio_gpu", "" - ) - self.wait_for_console_pattern("features: +virgl -edid") + exec_command_and_wait_for_pattern(self, "/usr/sbin/modprobe virtio_gpu", + "features: +virgl +edid") self.vm.shutdown() qemu_sock.close() vugp.terminate() diff --git a/tests/avocado/x86_cpu_model_versions.py b/tests/avocado/x86_cpu_model_versions.py index 9e07b8a55d..11101e02b9 100644 --- a/tests/avocado/x86_cpu_model_versions.py +++ b/tests/avocado/x86_cpu_model_versions.py @@ -121,94 +121,95 @@ class X86CPUModelAliases(avocado_qemu.QemuSystemTest): self.assertFalse(cpus['Cascadelake-Server']['static'], 'unversioned Cascadelake-Server CPU model must not be static') - self.assertEquals(cpus['Cascadelake-Server'].get('alias-of'), 'Cascadelake-Server-v1', - 'Cascadelake-Server must be an alias of Cascadelake-Server-v1') + self.assertEqual(cpus['Cascadelake-Server'].get('alias-of'), + 'Cascadelake-Server-v1', + 'Cascadelake-Server must be an alias of Cascadelake-Server-v1') self.assertNotIn('alias-of', cpus['Cascadelake-Server-v1'], 'Cascadelake-Server-v1 must not be an alias') self.assertFalse(cpus['qemu64']['static'], 'unversioned qemu64 CPU model must not be static') - self.assertEquals(cpus['qemu64'].get('alias-of'), 'qemu64-v1', - 'qemu64 must be an alias of qemu64-v1') + self.assertEqual(cpus['qemu64'].get('alias-of'), 'qemu64-v1', + 'qemu64 must be an alias of qemu64-v1') self.assertNotIn('alias-of', cpus['qemu64-v1'], 'qemu64-v1 must not be an alias') self.validate_variant_aliases(cpus) # On pc-*-4.1, -noTSX and -IBRS models should be aliases: - self.assertEquals(cpus["Haswell"].get('alias-of'), - "Haswell-v1", + self.assertEqual(cpus["Haswell"].get('alias-of'), + "Haswell-v1", "Haswell must be an alias") - self.assertEquals(cpus["Haswell-noTSX"].get('alias-of'), - "Haswell-v2", + self.assertEqual(cpus["Haswell-noTSX"].get('alias-of'), + "Haswell-v2", "Haswell-noTSX must be an alias") - self.assertEquals(cpus["Haswell-IBRS"].get('alias-of'), - "Haswell-v3", + self.assertEqual(cpus["Haswell-IBRS"].get('alias-of'), + "Haswell-v3", "Haswell-IBRS must be an alias") - self.assertEquals(cpus["Haswell-noTSX-IBRS"].get('alias-of'), - "Haswell-v4", + self.assertEqual(cpus["Haswell-noTSX-IBRS"].get('alias-of'), + "Haswell-v4", "Haswell-noTSX-IBRS must be an alias") - self.assertEquals(cpus["Broadwell"].get('alias-of'), - "Broadwell-v1", + self.assertEqual(cpus["Broadwell"].get('alias-of'), + "Broadwell-v1", "Broadwell must be an alias") - self.assertEquals(cpus["Broadwell-noTSX"].get('alias-of'), - "Broadwell-v2", + self.assertEqual(cpus["Broadwell-noTSX"].get('alias-of'), + "Broadwell-v2", "Broadwell-noTSX must be an alias") - self.assertEquals(cpus["Broadwell-IBRS"].get('alias-of'), - "Broadwell-v3", + self.assertEqual(cpus["Broadwell-IBRS"].get('alias-of'), + "Broadwell-v3", "Broadwell-IBRS must be an alias") - self.assertEquals(cpus["Broadwell-noTSX-IBRS"].get('alias-of'), - "Broadwell-v4", + self.assertEqual(cpus["Broadwell-noTSX-IBRS"].get('alias-of'), + "Broadwell-v4", "Broadwell-noTSX-IBRS must be an alias") - self.assertEquals(cpus["Nehalem"].get('alias-of'), - "Nehalem-v1", + self.assertEqual(cpus["Nehalem"].get('alias-of'), + "Nehalem-v1", "Nehalem must be an alias") - self.assertEquals(cpus["Nehalem-IBRS"].get('alias-of'), - "Nehalem-v2", + self.assertEqual(cpus["Nehalem-IBRS"].get('alias-of'), + "Nehalem-v2", "Nehalem-IBRS must be an alias") - self.assertEquals(cpus["Westmere"].get('alias-of'), - "Westmere-v1", + self.assertEqual(cpus["Westmere"].get('alias-of'), + "Westmere-v1", "Westmere must be an alias") - self.assertEquals(cpus["Westmere-IBRS"].get('alias-of'), - "Westmere-v2", + self.assertEqual(cpus["Westmere-IBRS"].get('alias-of'), + "Westmere-v2", "Westmere-IBRS must be an alias") - self.assertEquals(cpus["SandyBridge"].get('alias-of'), - "SandyBridge-v1", + self.assertEqual(cpus["SandyBridge"].get('alias-of'), + "SandyBridge-v1", "SandyBridge must be an alias") - self.assertEquals(cpus["SandyBridge-IBRS"].get('alias-of'), - "SandyBridge-v2", + self.assertEqual(cpus["SandyBridge-IBRS"].get('alias-of'), + "SandyBridge-v2", "SandyBridge-IBRS must be an alias") - self.assertEquals(cpus["IvyBridge"].get('alias-of'), - "IvyBridge-v1", + self.assertEqual(cpus["IvyBridge"].get('alias-of'), + "IvyBridge-v1", "IvyBridge must be an alias") - self.assertEquals(cpus["IvyBridge-IBRS"].get('alias-of'), - "IvyBridge-v2", + self.assertEqual(cpus["IvyBridge-IBRS"].get('alias-of'), + "IvyBridge-v2", "IvyBridge-IBRS must be an alias") - self.assertEquals(cpus["Skylake-Client"].get('alias-of'), - "Skylake-Client-v1", + self.assertEqual(cpus["Skylake-Client"].get('alias-of'), + "Skylake-Client-v1", "Skylake-Client must be an alias") - self.assertEquals(cpus["Skylake-Client-IBRS"].get('alias-of'), - "Skylake-Client-v2", + self.assertEqual(cpus["Skylake-Client-IBRS"].get('alias-of'), + "Skylake-Client-v2", "Skylake-Client-IBRS must be an alias") - self.assertEquals(cpus["Skylake-Server"].get('alias-of'), - "Skylake-Server-v1", + self.assertEqual(cpus["Skylake-Server"].get('alias-of'), + "Skylake-Server-v1", "Skylake-Server must be an alias") - self.assertEquals(cpus["Skylake-Server-IBRS"].get('alias-of'), - "Skylake-Server-v2", + self.assertEqual(cpus["Skylake-Server-IBRS"].get('alias-of'), + "Skylake-Server-v2", "Skylake-Server-IBRS must be an alias") - self.assertEquals(cpus["EPYC"].get('alias-of'), - "EPYC-v1", + self.assertEqual(cpus["EPYC"].get('alias-of'), + "EPYC-v1", "EPYC must be an alias") - self.assertEquals(cpus["EPYC-IBPB"].get('alias-of'), - "EPYC-v2", + self.assertEqual(cpus["EPYC-IBPB"].get('alias-of'), + "EPYC-v2", "EPYC-IBPB must be an alias") self.validate_aliases(cpus) diff --git a/tests/data/acpi/virt/SSDT.memhp b/tests/data/acpi/virt/SSDT.memhp index 31ff6ac469..fb3dcde5a1 100644 Binary files a/tests/data/acpi/virt/SSDT.memhp and b/tests/data/acpi/virt/SSDT.memhp differ diff --git a/tests/data/qobject/qdict.txt b/tests/data/qobject/qdict.txt index 122fda4524..e2edc88161 100644 --- a/tests/data/qobject/qdict.txt +++ b/tests/data/qobject/qdict.txt @@ -1866,10 +1866,6 @@ blackfin: 4096 blackfin.c: 7552 blackfin.h: 1089 blackfin_sram.h: 1207 -blacklist.c: 8658 -blacklist.h: 108 -blackstamp.c: 9838 -BlackStamp_defconfig: 27434 blinken.h: 617 blizzard.c: 41338 blizzard.h: 249 diff --git a/tests/docker/Makefile.include b/tests/docker/Makefile.include index cd4688bf07..5ba5b50ab9 100644 --- a/tests/docker/Makefile.include +++ b/tests/docker/Makefile.include @@ -88,9 +88,6 @@ DOCKER_PARTIAL_IMAGES += debian-s390x-cross DOCKER_PARTIAL_IMAGES += fedora endif -# The native build should never use the registry -docker-image-debian-native: DOCKER_REGISTRY= - # alpine has no adduser docker-image-alpine: NOUSER=1 diff --git a/tests/docker/dockerfiles/debian-i686-cross.docker b/tests/docker/dockerfiles/debian-i686-cross.docker new file mode 100644 index 0000000000..3fc4e15acd --- /dev/null +++ b/tests/docker/dockerfiles/debian-i686-cross.docker @@ -0,0 +1,182 @@ +# THIS FILE WAS AUTO-GENERATED +# +# $ lcitool dockerfile --layers all --cross-arch i686 debian-11 qemu +# +# https://gitlab.com/libvirt/libvirt-ci + +FROM docker.io/library/debian:11-slim + +RUN export DEBIAN_FRONTEND=noninteractive && \ + apt-get update && \ + apt-get install -y eatmydata && \ + eatmydata apt-get dist-upgrade -y && \ + eatmydata apt-get install --no-install-recommends -y \ + bash \ + bc \ + bison \ + bsdextrautils \ + bzip2 \ + ca-certificates \ + ccache \ + dbus \ + debianutils \ + diffutils \ + exuberant-ctags \ + findutils \ + flex \ + gcc \ + gcovr \ + gettext \ + git \ + hostname \ + libglib2.0-dev \ + libpcre2-dev \ + libsndio-dev \ + libspice-protocol-dev \ + llvm \ + locales \ + make \ + meson \ + mtools \ + ncat \ + ninja-build \ + openssh-client \ + pkgconf \ + python3 \ + python3-numpy \ + python3-opencv \ + python3-pillow \ + python3-pip \ + python3-setuptools \ + python3-sphinx \ + python3-sphinx-rtd-theme \ + python3-venv \ + python3-wheel \ + python3-yaml \ + rpm2cpio \ + sed \ + socat \ + sparse \ + tar \ + tesseract-ocr \ + tesseract-ocr-eng \ + xorriso \ + zstd && \ + eatmydata apt-get autoremove -y && \ + eatmydata apt-get autoclean -y && \ + sed -Ei 's,^# (en_US\.UTF-8 .*)$,\1,' /etc/locale.gen && \ + dpkg-reconfigure locales + +RUN /usr/bin/pip3 install tomli + +ENV CCACHE_WRAPPERSDIR "/usr/libexec/ccache-wrappers" +ENV LANG "en_US.UTF-8" +ENV MAKE "/usr/bin/make" +ENV NINJA "/usr/bin/ninja" +ENV PYTHON "/usr/bin/python3" + +RUN export DEBIAN_FRONTEND=noninteractive && \ + dpkg --add-architecture i386 && \ + eatmydata apt-get update && \ + eatmydata apt-get dist-upgrade -y && \ + eatmydata apt-get install --no-install-recommends -y dpkg-dev && \ + eatmydata apt-get install --no-install-recommends -y \ + g++-i686-linux-gnu \ + gcc-i686-linux-gnu \ + libaio-dev:i386 \ + libasan6:i386 \ + libasound2-dev:i386 \ + libattr1-dev:i386 \ + libbpf-dev:i386 \ + libbrlapi-dev:i386 \ + libbz2-dev:i386 \ + libc6-dev:i386 \ + libcacard-dev:i386 \ + libcap-ng-dev:i386 \ + libcapstone-dev:i386 \ + libcmocka-dev:i386 \ + libcurl4-gnutls-dev:i386 \ + libdaxctl-dev:i386 \ + libdrm-dev:i386 \ + libepoxy-dev:i386 \ + libfdt-dev:i386 \ + libffi-dev:i386 \ + libfuse3-dev:i386 \ + libgbm-dev:i386 \ + libgcrypt20-dev:i386 \ + libglib2.0-dev:i386 \ + libglusterfs-dev:i386 \ + libgnutls28-dev:i386 \ + libgtk-3-dev:i386 \ + libibumad-dev:i386 \ + libibverbs-dev:i386 \ + libiscsi-dev:i386 \ + libjemalloc-dev:i386 \ + libjpeg62-turbo-dev:i386 \ + libjson-c-dev:i386 \ + liblttng-ust-dev:i386 \ + liblzo2-dev:i386 \ + libncursesw5-dev:i386 \ + libnfs-dev:i386 \ + libnuma-dev:i386 \ + libpam0g-dev:i386 \ + libpipewire-0.3-dev:i386 \ + libpixman-1-dev:i386 \ + libpng-dev:i386 \ + libpulse-dev:i386 \ + librbd-dev:i386 \ + librdmacm-dev:i386 \ + libsasl2-dev:i386 \ + libsdl2-dev:i386 \ + libsdl2-image-dev:i386 \ + libseccomp-dev:i386 \ + libselinux1-dev:i386 \ + libslirp-dev:i386 \ + libsnappy-dev:i386 \ + libspice-server-dev:i386 \ + libssh-gcrypt-dev:i386 \ + libsystemd-dev:i386 \ + libtasn1-6-dev:i386 \ + libubsan1:i386 \ + libudev-dev:i386 \ + liburing-dev:i386 \ + libusb-1.0-0-dev:i386 \ + libusbredirhost-dev:i386 \ + libvdeplug-dev:i386 \ + libvirglrenderer-dev:i386 \ + libvte-2.91-dev:i386 \ + libzstd-dev:i386 \ + nettle-dev:i386 \ + systemtap-sdt-dev:i386 \ + xfslibs-dev:i386 \ + zlib1g-dev:i386 && \ + eatmydata apt-get autoremove -y && \ + eatmydata apt-get autoclean -y && \ + mkdir -p /usr/local/share/meson/cross && \ + printf "[binaries]\n\ +c = '/usr/bin/i686-linux-gnu-gcc'\n\ +ar = '/usr/bin/i686-linux-gnu-gcc-ar'\n\ +strip = '/usr/bin/i686-linux-gnu-strip'\n\ +pkgconfig = '/usr/bin/i686-linux-gnu-pkg-config'\n\ +\n\ +[host_machine]\n\ +system = 'linux'\n\ +cpu_family = 'x86'\n\ +cpu = 'i686'\n\ +endian = 'little'\n" > /usr/local/share/meson/cross/i686-linux-gnu && \ + dpkg-query --showformat '${Package}_${Version}_${Architecture}\n' --show > /packages.txt && \ + mkdir -p /usr/libexec/ccache-wrappers && \ + ln -s /usr/bin/ccache /usr/libexec/ccache-wrappers/i686-linux-gnu-c++ && \ + ln -s /usr/bin/ccache /usr/libexec/ccache-wrappers/i686-linux-gnu-cc && \ + ln -s /usr/bin/ccache /usr/libexec/ccache-wrappers/i686-linux-gnu-g++ && \ + ln -s /usr/bin/ccache /usr/libexec/ccache-wrappers/i686-linux-gnu-gcc + +ENV ABI "i686-linux-gnu" +ENV MESON_OPTS "--cross-file=i686-linux-gnu" +ENV QEMU_CONFIGURE_OPTS --cross-prefix=x86_64-linux-gnu- +ENV DEF_TARGET_LIST x86_64-softmmu,x86_64-linux-user,i386-softmmu,i386-linux-user +# As a final step configure the user (if env is defined) +ARG USER +ARG UID +RUN if [ "${USER}" ]; then \ + id ${USER} 2>/dev/null || useradd -u ${UID} -U ${USER}; fi diff --git a/tests/docker/dockerfiles/debian-native.docker b/tests/docker/dockerfiles/debian-native.docker deleted file mode 100644 index abac7d7cd7..0000000000 --- a/tests/docker/dockerfiles/debian-native.docker +++ /dev/null @@ -1,54 +0,0 @@ -# -# Docker Debian Native -# -# This is intended to build QEMU on native host systems. Debian is -# chosen due to the broadest range on supported host systems for QEMU. -# -# This docker target is based on the docker.io Debian Bullseye base -# image rather than QEMU's base because we would otherwise confuse the -# build grabbing stuff from the registry built for other -# architectures. -# -FROM docker.io/library/debian:bullseye-slim -MAINTAINER Alex Bennée - -# Duplicate deb line as deb-src -RUN cat /etc/apt/sources.list | sed "s/^deb\ /deb-src /" >> /etc/apt/sources.list - -# Install common build utilities -RUN apt update && \ - DEBIAN_FRONTEND=noninteractive apt install -yy eatmydata - -RUN apt update && \ - DEBIAN_FRONTEND=noninteractive eatmydata \ - apt build-dep -yy --arch-only qemu - -RUN apt update && \ - DEBIAN_FRONTEND=noninteractive eatmydata \ - apt install -y --no-install-recommends \ - cscope \ - genisoimage \ - exuberant-ctags \ - global \ - libbz2-dev \ - liblzo2-dev \ - libgcrypt20-dev \ - libfdt-dev \ - librdmacm-dev \ - libsasl2-dev \ - libsnappy-dev \ - libvte-dev \ - netcat-openbsd \ - ninja-build \ - openssh-client \ - python3-numpy \ - python3-opencv \ - python3-venv - -ENV QEMU_CONFIGURE_OPTS $QEMU_CONFIGURE_OPTS -ENV DEF_TARGET_LIST "none" -# As a final step configure the user (if env is defined) -ARG USER -ARG UID -RUN if [ "${USER}" ]; then \ - id ${USER} 2>/dev/null || useradd -u ${UID} -U ${USER}; fi diff --git a/tests/docker/dockerfiles/debian-amd64.docker b/tests/docker/dockerfiles/debian.docker similarity index 96% rename from tests/docker/dockerfiles/debian-amd64.docker rename to tests/docker/dockerfiles/debian.docker index 9b50fb2f63..b5e642d5b6 100644 --- a/tests/docker/dockerfiles/debian-amd64.docker +++ b/tests/docker/dockerfiles/debian.docker @@ -155,10 +155,13 @@ RUN DEBIAN_FRONTEND=noninteractive eatmydata \ apt install -y --no-install-recommends \ cscope\ global\ - linux-headers-amd64 + linux-headers-generic RUN git clone https://github.com/luigirizzo/netmap.git /usr/src/netmap RUN cd /usr/src/netmap && git checkout v11.3 -RUN cd /usr/src/netmap/LINUX && ./configure --no-drivers --no-apps --kernel-dir=$(ls -d /usr/src/linux-headers-*-amd64) && make install +RUN cd /usr/src/netmap/LINUX && \ + ./configure --no-drivers --no-apps \ + --kernel-dir=$(ls -d /usr/src/linux-headers-*-$(dpkg --print-architecture)) \ + && make install ENV QEMU_CONFIGURE_OPTS --enable-netmap # As a final step configure the user (if env is defined) ARG USER diff --git a/tests/docker/dockerfiles/fedora-i386-cross.docker b/tests/docker/dockerfiles/fedora-i386-cross.docker deleted file mode 100644 index b59a9115c4..0000000000 --- a/tests/docker/dockerfiles/fedora-i386-cross.docker +++ /dev/null @@ -1,40 +0,0 @@ -FROM registry.fedoraproject.org/fedora:34 - -ENV PACKAGES \ - bison \ - bzip2 \ - ccache \ - diffutils \ - flex \ - findutils \ - gcc \ - git \ - libfdt-devel.i686 \ - libffi-devel.i686 \ - libselinux-devel.i686 \ - libtasn1-devel.i686 \ - libzstd-devel.i686 \ - make \ - meson \ - ninja-build \ - glib2-devel.i686 \ - glibc-devel.i686 \ - glibc-static.i686 \ - gnutls-devel.i686 \ - nettle-devel.i686 \ - pcre-devel.i686 \ - pixman-devel.i686 \ - python3-tomli \ - sysprof-capture-devel.i686 \ - zlib-devel.i686 - -ENV QEMU_CONFIGURE_OPTS --cpu=i386 --disable-vhost-user -ENV PKG_CONFIG_LIBDIR /usr/lib/pkgconfig - -RUN dnf update -y && dnf install -y $PACKAGES -RUN rpm -q $PACKAGES | sort > /packages.txt -# As a final step configure the user (if env is defined) -ARG USER -ARG UID -RUN if [ "${USER}" ]; then \ - id ${USER} 2>/dev/null || useradd -u ${UID} -U ${USER}; fi diff --git a/tests/lcitool/libvirt-ci b/tests/lcitool/libvirt-ci index 36bc517161..77c800186f 160000 --- a/tests/lcitool/libvirt-ci +++ b/tests/lcitool/libvirt-ci @@ -1 +1 @@ -Subproject commit 36bc517161c45ead20224d47f2dc4fa428af6724 +Subproject commit 77c800186f34b21be7660750577cc5582a914deb diff --git a/tests/lcitool/refresh b/tests/lcitool/refresh index 92e7d30982..0c93557ad6 100755 --- a/tests/lcitool/refresh +++ b/tests/lcitool/refresh @@ -99,10 +99,13 @@ debian12_extras = [ " apt install -y --no-install-recommends \\\n", " cscope\\\n", " global\\\n", - " linux-headers-amd64\n", + " linux-headers-generic\n", "RUN git clone https://github.com/luigirizzo/netmap.git /usr/src/netmap\n", "RUN cd /usr/src/netmap && git checkout v11.3\n", - "RUN cd /usr/src/netmap/LINUX && ./configure --no-drivers --no-apps --kernel-dir=$(ls -d /usr/src/linux-headers-*-amd64) && make install\n", + "RUN cd /usr/src/netmap/LINUX && \\\n", + " ./configure --no-drivers --no-apps \\\n", + " --kernel-dir=$(ls -d /usr/src/linux-headers-*-$(dpkg --print-architecture)) \\\n", + " && make install\n", "ENV QEMU_CONFIGURE_OPTS --enable-netmap\n" ] @@ -123,7 +126,7 @@ try: # generate_dockerfile("alpine", "alpine-318") generate_dockerfile("centos8", "centos-stream-8") - generate_dockerfile("debian-amd64", "debian-12", + generate_dockerfile("debian", "debian-12", trailer="".join(debian12_extras)) generate_dockerfile("fedora", "fedora-38") generate_dockerfile("opensuse-leap", "opensuse-leap-15") @@ -156,6 +159,13 @@ try: trailer=cross_build("arm-linux-gnueabihf-", "arm-softmmu,arm-linux-user")) + generate_dockerfile("debian-i686-cross", "debian-11", + cross="i686", + trailer=cross_build("x86_64-linux-gnu-", + "x86_64-softmmu," + "x86_64-linux-user," + "i386-softmmu,i386-linux-user")) + generate_dockerfile("debian-mips64el-cross", "debian-11", cross="mips64el", trailer=cross_build("mips64el-linux-gnuabi64-", @@ -196,7 +206,8 @@ try: # Cirrus packages lists for GitLab # generate_cirrus("freebsd-13") - generate_cirrus("macos-12") + generate_cirrus("macos-13") + generate_cirrus("macos-14") # # VM packages lists diff --git a/tests/plugin/meson.build b/tests/plugin/meson.build index 528bb9d86c..28a929dbcc 100644 --- a/tests/plugin/meson.build +++ b/tests/plugin/meson.build @@ -4,7 +4,8 @@ if get_option('plugins') if targetos == 'windows' t += shared_module(i, files(i + '.c') + '../../contrib/plugins/win32_linker.c', include_directories: '../../include/qemu', - objects: [win32_qemu_plugin_api_lib], + link_depends: [win32_qemu_plugin_api_lib], + link_args: ['-Lplugins', '-lqemu_plugin_api'], dependencies: glib) else diff --git a/tests/qemu-iotests/059 b/tests/qemu-iotests/059 index 2bcb1f7f9c..0634c7bd92 100755 --- a/tests/qemu-iotests/059 +++ b/tests/qemu-iotests/059 @@ -84,6 +84,8 @@ echo echo "=== Testing big twoGbMaxExtentFlat ===" _make_test_img -o "subformat=twoGbMaxExtentFlat" 1000G _img_info --format-specific | _filter_img_info --format-specific +$QEMU_IO -c "write 990G 512 -P 89" "$TEST_IMG" | _filter_qemu_io +$QEMU_IO -c "read 990G 512 -P 89" "$TEST_IMG" | _filter_qemu_io _cleanup_test_img echo diff --git a/tests/qemu-iotests/059.out b/tests/qemu-iotests/059.out index 2b83c0c8b6..275ee7c778 100644 --- a/tests/qemu-iotests/059.out +++ b/tests/qemu-iotests/059.out @@ -2032,6 +2032,10 @@ Format specific information: virtual size: 2147483648 filename: TEST_DIR/t-f500.IMGFMT format: FLAT +wrote 512/512 bytes at offset 1063004405760 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 1063004405760 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) === Testing malformed VMFS extent description line === qemu-img: Could not open 'TEST_DIR/t.IMGFMT': Invalid extent line: RW 12582912 VMFS "dummy.IMGFMT" 1 diff --git a/tests/qemu-iotests/060.out b/tests/qemu-iotests/060.out index 329977d9b9..a37bf446e9 100644 --- a/tests/qemu-iotests/060.out +++ b/tests/qemu-iotests/060.out @@ -421,8 +421,8 @@ QMP_VERSION {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_IMAGE_CORRUPTED", "data": {"device": "none0", "msg": "Preventing invalid write on metadata (overlaps with refcount table)", "offset": 65536, "node-name": "drive", "fatal": true, "size": 65536}} write failed: Input/output error {"return": ""} -{"return": {}} {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false, "reason": "host-qmp-quit"}} +{"return": {}} === Testing incoming inactive corrupted image === @@ -432,8 +432,8 @@ QMP_VERSION qcow2: Image is corrupt: L2 table offset 0x2a2a2a00 unaligned (L1 index: 0); further non-fatal corruption events will be suppressed {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_IMAGE_CORRUPTED", "data": {"device": "", "msg": "L2 table offset 0x2a2a2a00 unaligned (L1 index: 0)", "node-name": "drive", "fatal": false}} {"return": ""} -{"return": {}} {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false, "reason": "host-qmp-quit"}} +{"return": {}} corrupt: false *** done diff --git a/tests/qemu-iotests/071.out b/tests/qemu-iotests/071.out index bca0c02f5c..a2923b05c2 100644 --- a/tests/qemu-iotests/071.out +++ b/tests/qemu-iotests/071.out @@ -45,8 +45,8 @@ QMP_VERSION {"return": {}} read failed: Input/output error {"return": ""} -{"return": {}} {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false, "reason": "host-qmp-quit"}} +{"return": {}} === Testing blkverify on existing block device === @@ -84,9 +84,9 @@ wrote 512/512 bytes at offset 0 {"return": ""} read failed: Input/output error {"return": ""} -{"return": {}} {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false, "reason": "host-qmp-quit"}} QEMU_PROG: Failed to flush the L2 table cache: Input/output error QEMU_PROG: Failed to flush the refcount block cache: Input/output error +{"return": {}} *** done diff --git a/tests/qemu-iotests/081.out b/tests/qemu-iotests/081.out index 615c083549..aba85ea564 100644 --- a/tests/qemu-iotests/081.out +++ b/tests/qemu-iotests/081.out @@ -35,8 +35,8 @@ QMP_VERSION read 10485760/10485760 bytes at offset 0 10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) {"return": ""} -{"return": {}} {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false, "reason": "host-qmp-quit"}} +{"return": {}} == using quorum rewrite corrupted mode == @@ -67,8 +67,8 @@ QMP_VERSION read 10485760/10485760 bytes at offset 0 10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) {"return": ""} -{"return": {}} {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false, "reason": "host-qmp-quit"}} +{"return": {}} -- checking that the image has been corrected -- read 10485760/10485760 bytes at offset 0 @@ -106,8 +106,8 @@ QMP_VERSION {"return": {}} {"return": {}} {"return": {}} -{"return": {}} {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false, "reason": "host-qmp-quit"}} +{"return": {}} Testing: QMP_VERSION @@ -115,8 +115,8 @@ QMP_VERSION {"return": {}} {"return": {}} {"error": {"class": "GenericError", "desc": "Cannot add a child to a quorum in blkverify mode"}} -{"return": {}} {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false, "reason": "host-qmp-quit"}} +{"return": {}} == dynamically removing a child from a quorum == @@ -125,31 +125,31 @@ QMP_VERSION {"return": {}} {"return": {}} {"return": {}} -{"return": {}} {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false, "reason": "host-qmp-quit"}} +{"return": {}} Testing: QMP_VERSION {"return": {}} {"return": {}} {"error": {"class": "GenericError", "desc": "The number of children cannot be lower than the vote threshold 2"}} -{"return": {}} {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false, "reason": "host-qmp-quit"}} +{"return": {}} Testing: QMP_VERSION {"return": {}} {"error": {"class": "GenericError", "desc": "blkverify=on can only be set if there are exactly two files and vote-threshold is 2"}} {"error": {"class": "GenericError", "desc": "Cannot find device='drive0-quorum' nor node-name='drive0-quorum'"}} -{"return": {}} {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false, "reason": "host-qmp-quit"}} +{"return": {}} Testing: QMP_VERSION {"return": {}} {"return": {}} {"error": {"class": "GenericError", "desc": "The number of children cannot be lower than the vote threshold 2"}} -{"return": {}} {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false, "reason": "host-qmp-quit"}} +{"return": {}} *** done diff --git a/tests/qemu-iotests/087.out b/tests/qemu-iotests/087.out index e1c23a6983..97b6d8036d 100644 --- a/tests/qemu-iotests/087.out +++ b/tests/qemu-iotests/087.out @@ -7,8 +7,8 @@ Testing: QMP_VERSION {"return": {}} {"error": {"class": "GenericError", "desc": "'node-name' must be specified for the root node"}} -{"return": {}} {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false, "reason": "host-qmp-quit"}} +{"return": {}} === Duplicate ID === @@ -18,8 +18,8 @@ QMP_VERSION {"return": {}} {"error": {"class": "GenericError", "desc": "node-name=disk is conflicting with a device id"}} {"error": {"class": "GenericError", "desc": "Duplicate nodes with node-name='test-node'"}} -{"return": {}} {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false, "reason": "host-qmp-quit"}} +{"return": {}} === aio=native without O_DIRECT === @@ -28,8 +28,8 @@ Testing: QMP_VERSION {"return": {}} {"error": {"class": "GenericError", "desc": "aio=native was specified, but it requires cache.direct=on, which was not specified."}} -{"return": {}} {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false, "reason": "host-qmp-quit"}} +{"return": {}} === Encrypted image QCow === @@ -40,8 +40,8 @@ QMP_VERSION {"return": {}} {"return": {}} {"error": {"class": "GenericError", "desc": "Use of AES-CBC encrypted IMGFMT images is no longer supported in system emulators"}} -{"return": {}} {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false, "reason": "host-qmp-quit"}} +{"return": {}} === Encrypted image LUKS === @@ -52,8 +52,8 @@ QMP_VERSION {"return": {}} {"return": {}} {"return": {}} -{"return": {}} {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false, "reason": "host-qmp-quit"}} +{"return": {}} === Missing driver === @@ -63,7 +63,7 @@ Testing: -S QMP_VERSION {"return": {}} {"error": {"class": "GenericError", "desc": "Parameter 'driver' is missing"}} -{"return": {}} {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false, "reason": "host-qmp-quit"}} +{"return": {}} *** done diff --git a/tests/qemu-iotests/108.out b/tests/qemu-iotests/108.out index b5401d788d..b9c876b394 100644 --- a/tests/qemu-iotests/108.out +++ b/tests/qemu-iotests/108.out @@ -173,8 +173,8 @@ OK: Reftable is where we expect it {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "null", "id": "create"}} {"return": {}} { "execute": "quit" } -{"return": {}} {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false, "reason": "host-qmp-quit"}} +{"return": {}} wrote 65536/65536 bytes at offset 0 64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) diff --git a/tests/qemu-iotests/109 b/tests/qemu-iotests/109 index e207a555f3..0fb580f9a5 100755 --- a/tests/qemu-iotests/109 +++ b/tests/qemu-iotests/109 @@ -57,13 +57,13 @@ run_qemu() _launch_qemu -drive file="${source_img}",format=raw,cache=${CACHEMODE},aio=${AIOMODE},id=src _send_qemu_cmd $QEMU_HANDLE "{ 'execute': 'qmp_capabilities' }" "return" - _send_qemu_cmd $QEMU_HANDLE \ + capture_events="$qmp_event" _send_qemu_cmd $QEMU_HANDLE \ "{'execute':'drive-mirror', 'arguments':{ 'device': 'src', 'target': '$raw_img', $qmp_format 'mode': 'existing', 'sync': 'full'}}" \ "return" - _send_qemu_cmd $QEMU_HANDLE '' "$qmp_event" + capture_events="$qmp_event JOB_STATUS_CHANGE" _wait_event $QEMU_HANDLE "$qmp_event" if test "$qmp_event" = BLOCK_JOB_ERROR; then _send_qemu_cmd $QEMU_HANDLE '' '"status": "null"' fi diff --git a/tests/qemu-iotests/109.out b/tests/qemu-iotests/109.out index 965c9a6a0a..3ae8552ff7 100644 --- a/tests/qemu-iotests/109.out +++ b/tests/qemu-iotests/109.out @@ -7,7 +7,7 @@ Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=SIZE { 'execute': 'qmp_capabilities' } {"return": {}} {'execute':'drive-mirror', 'arguments':{ - 'device': 'src', 'target': 'TEST_DIR/t.IMGFMT', + 'device': 'src', 'target': 'TEST_DIR/t.IMGFMT', 'mode': 'existing', 'sync': 'full'}} WARNING: Image format was not specified for 'TEST_DIR/t.raw' and probing guessed raw. Automatically detecting the format is dangerous for raw images, write operations on block 0 will be restricted. @@ -23,8 +23,8 @@ WARNING: Image format was not specified for 'TEST_DIR/t.raw' and probing guessed {"execute":"query-block-jobs"} {"return": []} {"execute":"quit"} -{"return": {}} {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false, "reason": "host-qmp-quit"}} +{"return": {}} read 512/512 bytes at offset 0 512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) { 'execute': 'qmp_capabilities' } @@ -35,12 +35,10 @@ read 512/512 bytes at offset 0 {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "created", "id": "src"}} {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "running", "id": "src"}} {"return": {}} -{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "ready", "id": "src"}} {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_READY", "data": {"device": "src", "len": 1024, "offset": 1024, "speed": 0, "type": "mirror"}} {"execute":"query-block-jobs"} {"return": [{"auto-finalize": true, "io-status": "ok", "device": "src", "auto-dismiss": true, "busy": false, "len": 1024, "offset": 1024, "status": "ready", "paused": false, "speed": 0, "ready": true, "type": "mirror", "actively-synced": false}]} {"execute":"quit"} -{"return": {}} {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false, "reason": "host-qmp-quit"}} {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "standby", "id": "src"}} {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "ready", "id": "src"}} @@ -50,6 +48,7 @@ read 512/512 bytes at offset 0 {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_CANCELLED", "data": {"device": "src", "len": 1024, "offset": 1024, "speed": 0, "type": "mirror"}} {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "concluded", "id": "src"}} {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "null", "id": "src"}} +{"return": {}} Images are identical. === Writing a qcow2 header into raw === @@ -59,7 +58,7 @@ Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=SIZE { 'execute': 'qmp_capabilities' } {"return": {}} {'execute':'drive-mirror', 'arguments':{ - 'device': 'src', 'target': 'TEST_DIR/t.IMGFMT', + 'device': 'src', 'target': 'TEST_DIR/t.IMGFMT', 'mode': 'existing', 'sync': 'full'}} WARNING: Image format was not specified for 'TEST_DIR/t.raw' and probing guessed raw. Automatically detecting the format is dangerous for raw images, write operations on block 0 will be restricted. @@ -75,8 +74,8 @@ WARNING: Image format was not specified for 'TEST_DIR/t.raw' and probing guessed {"execute":"query-block-jobs"} {"return": []} {"execute":"quit"} -{"return": {}} {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false, "reason": "host-qmp-quit"}} +{"return": {}} read 512/512 bytes at offset 0 512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) { 'execute': 'qmp_capabilities' } @@ -87,12 +86,10 @@ read 512/512 bytes at offset 0 {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "created", "id": "src"}} {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "running", "id": "src"}} {"return": {}} -{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "ready", "id": "src"}} {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_READY", "data": {"device": "src", "len": 197120, "offset": 197120, "speed": 0, "type": "mirror"}} {"execute":"query-block-jobs"} {"return": [{"auto-finalize": true, "io-status": "ok", "device": "src", "auto-dismiss": true, "busy": false, "len": 197120, "offset": 197120, "status": "ready", "paused": false, "speed": 0, "ready": true, "type": "mirror", "actively-synced": false}]} {"execute":"quit"} -{"return": {}} {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false, "reason": "host-qmp-quit"}} {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "standby", "id": "src"}} {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "ready", "id": "src"}} @@ -102,6 +99,7 @@ read 512/512 bytes at offset 0 {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_CANCELLED", "data": {"device": "src", "len": 197120, "offset": 197120, "speed": 0, "type": "mirror"}} {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "concluded", "id": "src"}} {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "null", "id": "src"}} +{"return": {}} Images are identical. === Writing a qed header into raw === @@ -111,7 +109,7 @@ Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=SIZE { 'execute': 'qmp_capabilities' } {"return": {}} {'execute':'drive-mirror', 'arguments':{ - 'device': 'src', 'target': 'TEST_DIR/t.IMGFMT', + 'device': 'src', 'target': 'TEST_DIR/t.IMGFMT', 'mode': 'existing', 'sync': 'full'}} WARNING: Image format was not specified for 'TEST_DIR/t.raw' and probing guessed raw. Automatically detecting the format is dangerous for raw images, write operations on block 0 will be restricted. @@ -127,8 +125,8 @@ WARNING: Image format was not specified for 'TEST_DIR/t.raw' and probing guessed {"execute":"query-block-jobs"} {"return": []} {"execute":"quit"} -{"return": {}} {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false, "reason": "host-qmp-quit"}} +{"return": {}} read 512/512 bytes at offset 0 512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) { 'execute': 'qmp_capabilities' } @@ -139,12 +137,10 @@ read 512/512 bytes at offset 0 {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "created", "id": "src"}} {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "running", "id": "src"}} {"return": {}} -{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "ready", "id": "src"}} {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_READY", "data": {"device": "src", "len": 327680, "offset": 327680, "speed": 0, "type": "mirror"}} {"execute":"query-block-jobs"} {"return": [{"auto-finalize": true, "io-status": "ok", "device": "src", "auto-dismiss": true, "busy": false, "len": 327680, "offset": 327680, "status": "ready", "paused": false, "speed": 0, "ready": true, "type": "mirror", "actively-synced": false}]} {"execute":"quit"} -{"return": {}} {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false, "reason": "host-qmp-quit"}} {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "standby", "id": "src"}} {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "ready", "id": "src"}} @@ -154,6 +150,7 @@ read 512/512 bytes at offset 0 {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_CANCELLED", "data": {"device": "src", "len": 327680, "offset": 327680, "speed": 0, "type": "mirror"}} {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "concluded", "id": "src"}} {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "null", "id": "src"}} +{"return": {}} Images are identical. === Writing a vdi header into raw === @@ -163,7 +160,7 @@ Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=SIZE { 'execute': 'qmp_capabilities' } {"return": {}} {'execute':'drive-mirror', 'arguments':{ - 'device': 'src', 'target': 'TEST_DIR/t.IMGFMT', + 'device': 'src', 'target': 'TEST_DIR/t.IMGFMT', 'mode': 'existing', 'sync': 'full'}} WARNING: Image format was not specified for 'TEST_DIR/t.raw' and probing guessed raw. Automatically detecting the format is dangerous for raw images, write operations on block 0 will be restricted. @@ -179,8 +176,8 @@ WARNING: Image format was not specified for 'TEST_DIR/t.raw' and probing guessed {"execute":"query-block-jobs"} {"return": []} {"execute":"quit"} -{"return": {}} {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false, "reason": "host-qmp-quit"}} +{"return": {}} read 512/512 bytes at offset 0 512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) { 'execute': 'qmp_capabilities' } @@ -191,12 +188,10 @@ read 512/512 bytes at offset 0 {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "created", "id": "src"}} {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "running", "id": "src"}} {"return": {}} -{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "ready", "id": "src"}} {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_READY", "data": {"device": "src", "len": 1024, "offset": 1024, "speed": 0, "type": "mirror"}} {"execute":"query-block-jobs"} {"return": [{"auto-finalize": true, "io-status": "ok", "device": "src", "auto-dismiss": true, "busy": false, "len": 1024, "offset": 1024, "status": "ready", "paused": false, "speed": 0, "ready": true, "type": "mirror", "actively-synced": false}]} {"execute":"quit"} -{"return": {}} {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false, "reason": "host-qmp-quit"}} {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "standby", "id": "src"}} {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "ready", "id": "src"}} @@ -206,6 +201,7 @@ read 512/512 bytes at offset 0 {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_CANCELLED", "data": {"device": "src", "len": 1024, "offset": 1024, "speed": 0, "type": "mirror"}} {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "concluded", "id": "src"}} {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "null", "id": "src"}} +{"return": {}} Images are identical. === Writing a vmdk header into raw === @@ -215,7 +211,7 @@ Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=SIZE { 'execute': 'qmp_capabilities' } {"return": {}} {'execute':'drive-mirror', 'arguments':{ - 'device': 'src', 'target': 'TEST_DIR/t.IMGFMT', + 'device': 'src', 'target': 'TEST_DIR/t.IMGFMT', 'mode': 'existing', 'sync': 'full'}} WARNING: Image format was not specified for 'TEST_DIR/t.raw' and probing guessed raw. Automatically detecting the format is dangerous for raw images, write operations on block 0 will be restricted. @@ -231,8 +227,8 @@ WARNING: Image format was not specified for 'TEST_DIR/t.raw' and probing guessed {"execute":"query-block-jobs"} {"return": []} {"execute":"quit"} -{"return": {}} {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false, "reason": "host-qmp-quit"}} +{"return": {}} read 512/512 bytes at offset 0 512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) { 'execute': 'qmp_capabilities' } @@ -243,12 +239,10 @@ read 512/512 bytes at offset 0 {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "created", "id": "src"}} {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "running", "id": "src"}} {"return": {}} -{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "ready", "id": "src"}} {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_READY", "data": {"device": "src", "len": 65536, "offset": 65536, "speed": 0, "type": "mirror"}} {"execute":"query-block-jobs"} {"return": [{"auto-finalize": true, "io-status": "ok", "device": "src", "auto-dismiss": true, "busy": false, "len": 65536, "offset": 65536, "status": "ready", "paused": false, "speed": 0, "ready": true, "type": "mirror", "actively-synced": false}]} {"execute":"quit"} -{"return": {}} {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false, "reason": "host-qmp-quit"}} {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "standby", "id": "src"}} {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "ready", "id": "src"}} @@ -258,6 +252,7 @@ read 512/512 bytes at offset 0 {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_CANCELLED", "data": {"device": "src", "len": 65536, "offset": 65536, "speed": 0, "type": "mirror"}} {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "concluded", "id": "src"}} {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "null", "id": "src"}} +{"return": {}} Images are identical. === Writing a vpc header into raw === @@ -267,7 +262,7 @@ Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=SIZE { 'execute': 'qmp_capabilities' } {"return": {}} {'execute':'drive-mirror', 'arguments':{ - 'device': 'src', 'target': 'TEST_DIR/t.IMGFMT', + 'device': 'src', 'target': 'TEST_DIR/t.IMGFMT', 'mode': 'existing', 'sync': 'full'}} WARNING: Image format was not specified for 'TEST_DIR/t.raw' and probing guessed raw. Automatically detecting the format is dangerous for raw images, write operations on block 0 will be restricted. @@ -283,8 +278,8 @@ WARNING: Image format was not specified for 'TEST_DIR/t.raw' and probing guessed {"execute":"query-block-jobs"} {"return": []} {"execute":"quit"} -{"return": {}} {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false, "reason": "host-qmp-quit"}} +{"return": {}} read 512/512 bytes at offset 0 512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) { 'execute': 'qmp_capabilities' } @@ -295,12 +290,10 @@ read 512/512 bytes at offset 0 {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "created", "id": "src"}} {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "running", "id": "src"}} {"return": {}} -{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "ready", "id": "src"}} {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_READY", "data": {"device": "src", "len": 2560, "offset": 2560, "speed": 0, "type": "mirror"}} {"execute":"query-block-jobs"} {"return": [{"auto-finalize": true, "io-status": "ok", "device": "src", "auto-dismiss": true, "busy": false, "len": 2560, "offset": 2560, "status": "ready", "paused": false, "speed": 0, "ready": true, "type": "mirror", "actively-synced": false}]} {"execute":"quit"} -{"return": {}} {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false, "reason": "host-qmp-quit"}} {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "standby", "id": "src"}} {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "ready", "id": "src"}} @@ -310,6 +303,7 @@ read 512/512 bytes at offset 0 {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_CANCELLED", "data": {"device": "src", "len": 2560, "offset": 2560, "speed": 0, "type": "mirror"}} {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "concluded", "id": "src"}} {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "null", "id": "src"}} +{"return": {}} Images are identical. === Copying sample image empty.bochs into raw === @@ -318,7 +312,7 @@ Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=SIZE { 'execute': 'qmp_capabilities' } {"return": {}} {'execute':'drive-mirror', 'arguments':{ - 'device': 'src', 'target': 'TEST_DIR/t.IMGFMT', + 'device': 'src', 'target': 'TEST_DIR/t.IMGFMT', 'mode': 'existing', 'sync': 'full'}} WARNING: Image format was not specified for 'TEST_DIR/t.raw' and probing guessed raw. Automatically detecting the format is dangerous for raw images, write operations on block 0 will be restricted. @@ -334,8 +328,8 @@ WARNING: Image format was not specified for 'TEST_DIR/t.raw' and probing guessed {"execute":"query-block-jobs"} {"return": []} {"execute":"quit"} -{"return": {}} {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false, "reason": "host-qmp-quit"}} +{"return": {}} read 512/512 bytes at offset 0 512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) { 'execute': 'qmp_capabilities' } @@ -346,12 +340,10 @@ read 512/512 bytes at offset 0 {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "created", "id": "src"}} {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "running", "id": "src"}} {"return": {}} -{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "ready", "id": "src"}} {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_READY", "data": {"device": "src", "len": 2560, "offset": 2560, "speed": 0, "type": "mirror"}} {"execute":"query-block-jobs"} {"return": [{"auto-finalize": true, "io-status": "ok", "device": "src", "auto-dismiss": true, "busy": false, "len": 2560, "offset": 2560, "status": "ready", "paused": false, "speed": 0, "ready": true, "type": "mirror", "actively-synced": false}]} {"execute":"quit"} -{"return": {}} {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false, "reason": "host-qmp-quit"}} {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "standby", "id": "src"}} {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "ready", "id": "src"}} @@ -361,6 +353,7 @@ read 512/512 bytes at offset 0 {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_CANCELLED", "data": {"device": "src", "len": 2560, "offset": 2560, "speed": 0, "type": "mirror"}} {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "concluded", "id": "src"}} {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "null", "id": "src"}} +{"return": {}} Images are identical. === Copying sample image iotest-dirtylog-10G-4M.vhdx into raw === @@ -369,7 +362,7 @@ Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=SIZE { 'execute': 'qmp_capabilities' } {"return": {}} {'execute':'drive-mirror', 'arguments':{ - 'device': 'src', 'target': 'TEST_DIR/t.IMGFMT', + 'device': 'src', 'target': 'TEST_DIR/t.IMGFMT', 'mode': 'existing', 'sync': 'full'}} WARNING: Image format was not specified for 'TEST_DIR/t.raw' and probing guessed raw. Automatically detecting the format is dangerous for raw images, write operations on block 0 will be restricted. @@ -385,8 +378,8 @@ WARNING: Image format was not specified for 'TEST_DIR/t.raw' and probing guessed {"execute":"query-block-jobs"} {"return": []} {"execute":"quit"} -{"return": {}} {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false, "reason": "host-qmp-quit"}} +{"return": {}} read 512/512 bytes at offset 0 512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) { 'execute': 'qmp_capabilities' } @@ -397,12 +390,10 @@ read 512/512 bytes at offset 0 {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "created", "id": "src"}} {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "running", "id": "src"}} {"return": {}} -{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "ready", "id": "src"}} {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_READY", "data": {"device": "src", "len": 31457280, "offset": 31457280, "speed": 0, "type": "mirror"}} {"execute":"query-block-jobs"} {"return": [{"auto-finalize": true, "io-status": "ok", "device": "src", "auto-dismiss": true, "busy": false, "len": 31457280, "offset": 31457280, "status": "ready", "paused": false, "speed": 0, "ready": true, "type": "mirror", "actively-synced": false}]} {"execute":"quit"} -{"return": {}} {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false, "reason": "host-qmp-quit"}} {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "standby", "id": "src"}} {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "ready", "id": "src"}} @@ -412,6 +403,7 @@ read 512/512 bytes at offset 0 {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_CANCELLED", "data": {"device": "src", "len": 31457280, "offset": 31457280, "speed": 0, "type": "mirror"}} {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "concluded", "id": "src"}} {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "null", "id": "src"}} +{"return": {}} Images are identical. === Copying sample image parallels-v1 into raw === @@ -420,7 +412,7 @@ Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=SIZE { 'execute': 'qmp_capabilities' } {"return": {}} {'execute':'drive-mirror', 'arguments':{ - 'device': 'src', 'target': 'TEST_DIR/t.IMGFMT', + 'device': 'src', 'target': 'TEST_DIR/t.IMGFMT', 'mode': 'existing', 'sync': 'full'}} WARNING: Image format was not specified for 'TEST_DIR/t.raw' and probing guessed raw. Automatically detecting the format is dangerous for raw images, write operations on block 0 will be restricted. @@ -436,8 +428,8 @@ WARNING: Image format was not specified for 'TEST_DIR/t.raw' and probing guessed {"execute":"query-block-jobs"} {"return": []} {"execute":"quit"} -{"return": {}} {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false, "reason": "host-qmp-quit"}} +{"return": {}} read 512/512 bytes at offset 0 512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) { 'execute': 'qmp_capabilities' } @@ -448,12 +440,10 @@ read 512/512 bytes at offset 0 {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "created", "id": "src"}} {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "running", "id": "src"}} {"return": {}} -{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "ready", "id": "src"}} {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_READY", "data": {"device": "src", "len": 327680, "offset": 327680, "speed": 0, "type": "mirror"}} {"execute":"query-block-jobs"} {"return": [{"auto-finalize": true, "io-status": "ok", "device": "src", "auto-dismiss": true, "busy": false, "len": 327680, "offset": 327680, "status": "ready", "paused": false, "speed": 0, "ready": true, "type": "mirror", "actively-synced": false}]} {"execute":"quit"} -{"return": {}} {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false, "reason": "host-qmp-quit"}} {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "standby", "id": "src"}} {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "ready", "id": "src"}} @@ -463,6 +453,7 @@ read 512/512 bytes at offset 0 {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_CANCELLED", "data": {"device": "src", "len": 327680, "offset": 327680, "speed": 0, "type": "mirror"}} {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "concluded", "id": "src"}} {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "null", "id": "src"}} +{"return": {}} Images are identical. === Copying sample image simple-pattern.cloop into raw === @@ -471,7 +462,7 @@ Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=SIZE { 'execute': 'qmp_capabilities' } {"return": {}} {'execute':'drive-mirror', 'arguments':{ - 'device': 'src', 'target': 'TEST_DIR/t.IMGFMT', + 'device': 'src', 'target': 'TEST_DIR/t.IMGFMT', 'mode': 'existing', 'sync': 'full'}} WARNING: Image format was not specified for 'TEST_DIR/t.raw' and probing guessed raw. Automatically detecting the format is dangerous for raw images, write operations on block 0 will be restricted. @@ -487,8 +478,8 @@ WARNING: Image format was not specified for 'TEST_DIR/t.raw' and probing guessed {"execute":"query-block-jobs"} {"return": []} {"execute":"quit"} -{"return": {}} {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false, "reason": "host-qmp-quit"}} +{"return": {}} read 512/512 bytes at offset 0 512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) { 'execute': 'qmp_capabilities' } @@ -499,12 +490,10 @@ read 512/512 bytes at offset 0 {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "created", "id": "src"}} {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "running", "id": "src"}} {"return": {}} -{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "ready", "id": "src"}} {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_READY", "data": {"device": "src", "len": 2048, "offset": 2048, "speed": 0, "type": "mirror"}} {"execute":"query-block-jobs"} {"return": [{"auto-finalize": true, "io-status": "ok", "device": "src", "auto-dismiss": true, "busy": false, "len": 2048, "offset": 2048, "status": "ready", "paused": false, "speed": 0, "ready": true, "type": "mirror", "actively-synced": false}]} {"execute":"quit"} -{"return": {}} {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false, "reason": "host-qmp-quit"}} {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "standby", "id": "src"}} {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "ready", "id": "src"}} @@ -514,6 +503,7 @@ read 512/512 bytes at offset 0 {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_CANCELLED", "data": {"device": "src", "len": 2048, "offset": 2048, "speed": 0, "type": "mirror"}} {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "concluded", "id": "src"}} {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "null", "id": "src"}} +{"return": {}} Images are identical. === Write legitimate MBR into raw === @@ -522,7 +512,7 @@ Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=SIZE { 'execute': 'qmp_capabilities' } {"return": {}} {'execute':'drive-mirror', 'arguments':{ - 'device': 'src', 'target': 'TEST_DIR/t.IMGFMT', + 'device': 'src', 'target': 'TEST_DIR/t.IMGFMT', 'mode': 'existing', 'sync': 'full'}} WARNING: Image format was not specified for 'TEST_DIR/t.raw' and probing guessed raw. Automatically detecting the format is dangerous for raw images, write operations on block 0 will be restricted. @@ -530,12 +520,10 @@ WARNING: Image format was not specified for 'TEST_DIR/t.raw' and probing guessed {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "created", "id": "src"}} {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "running", "id": "src"}} {"return": {}} -{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "ready", "id": "src"}} {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_READY", "data": {"device": "src", "len": 512, "offset": 512, "speed": 0, "type": "mirror"}} {"execute":"query-block-jobs"} {"return": [{"auto-finalize": true, "io-status": "ok", "device": "src", "auto-dismiss": true, "busy": false, "len": 512, "offset": 512, "status": "ready", "paused": false, "speed": 0, "ready": true, "type": "mirror", "actively-synced": false}]} {"execute":"quit"} -{"return": {}} {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false, "reason": "host-qmp-quit"}} {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "standby", "id": "src"}} {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "ready", "id": "src"}} @@ -545,6 +533,7 @@ WARNING: Image format was not specified for 'TEST_DIR/t.raw' and probing guessed {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_CANCELLED", "data": {"device": "src", "len": 512, "offset": 512, "speed": 0, "type": "mirror"}} {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "concluded", "id": "src"}} {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "null", "id": "src"}} +{"return": {}} Images are identical. { 'execute': 'qmp_capabilities' } {"return": {}} @@ -554,12 +543,10 @@ Images are identical. {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "created", "id": "src"}} {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "running", "id": "src"}} {"return": {}} -{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "ready", "id": "src"}} {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_READY", "data": {"device": "src", "len": 512, "offset": 512, "speed": 0, "type": "mirror"}} {"execute":"query-block-jobs"} {"return": [{"auto-finalize": true, "io-status": "ok", "device": "src", "auto-dismiss": true, "busy": false, "len": 512, "offset": 512, "status": "ready", "paused": false, "speed": 0, "ready": true, "type": "mirror", "actively-synced": false}]} {"execute":"quit"} -{"return": {}} {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false, "reason": "host-qmp-quit"}} {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "standby", "id": "src"}} {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "ready", "id": "src"}} @@ -569,5 +556,6 @@ Images are identical. {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_CANCELLED", "data": {"device": "src", "len": 512, "offset": 512, "speed": 0, "type": "mirror"}} {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "concluded", "id": "src"}} {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "null", "id": "src"}} +{"return": {}} Images are identical. *** done diff --git a/tests/qemu-iotests/117.out b/tests/qemu-iotests/117.out index 735ffd25c6..1cea9e0217 100644 --- a/tests/qemu-iotests/117.out +++ b/tests/qemu-iotests/117.out @@ -18,8 +18,8 @@ wrote 65536/65536 bytes at offset 0 64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) {"return": ""} { 'execute': 'quit' } -{"return": {}} {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false, "reason": "host-qmp-quit"}} +{"return": {}} No errors were found on the image. read 65536/65536 bytes at offset 0 64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) diff --git a/tests/qemu-iotests/120.out b/tests/qemu-iotests/120.out index 0744c1f136..35d84a5bc5 100644 --- a/tests/qemu-iotests/120.out +++ b/tests/qemu-iotests/120.out @@ -5,8 +5,8 @@ QMP_VERSION wrote 65536/65536 bytes at offset 0 64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) {"return": ""} -{"return": {}} {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false, "reason": "host-qmp-quit"}} +{"return": {}} read 65536/65536 bytes at offset 0 64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) read 65536/65536 bytes at offset 0 diff --git a/tests/qemu-iotests/127.out b/tests/qemu-iotests/127.out index 1685c4850a..dd8c4a8aa9 100644 --- a/tests/qemu-iotests/127.out +++ b/tests/qemu-iotests/127.out @@ -28,6 +28,6 @@ wrote 42/42 bytes at offset 0 { 'execute': 'quit' } {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "concluded", "id": "mirror"}} {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "null", "id": "mirror"}} -{"return": {}} {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false, "reason": "host-qmp-quit"}} +{"return": {}} *** done diff --git a/tests/qemu-iotests/140.out b/tests/qemu-iotests/140.out index 312f76d5da..32866440ae 100644 --- a/tests/qemu-iotests/140.out +++ b/tests/qemu-iotests/140.out @@ -19,6 +19,6 @@ read 65536/65536 bytes at offset 0 qemu-io: can't open device nbd+unix:///drv?socket=SOCK_DIR/nbd: Requested export not available server reported: export 'drv' not present { 'execute': 'quit' } -{"return": {}} {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false, "reason": "host-qmp-quit"}} +{"return": {}} *** done diff --git a/tests/qemu-iotests/141 b/tests/qemu-iotests/141 index a37030ee17..a7d3985a02 100755 --- a/tests/qemu-iotests/141 +++ b/tests/qemu-iotests/141 @@ -1,9 +1,12 @@ -#!/usr/bin/env bash +#!/usr/bin/env python3 # group: rw auto quick # # Test case for ejecting BDSs with block jobs still running on them # -# Copyright (C) 2016 Red Hat, Inc. +# Originally written in bash by Hanna Czenczek, ported to Python by Stefan +# Hajnoczi. +# +# Copyright Red Hat # # 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 @@ -19,177 +22,129 @@ # along with this program. If not, see . # -# creator -owner=hreitz@redhat.com +import iotests -seq="$(basename $0)" -echo "QA output created by $seq" - -status=1 # failure is the default! - -_cleanup() -{ - _cleanup_qemu - _cleanup_test_img - for img in "$TEST_DIR"/{b,m,o}.$IMGFMT; do - _rm_test_img "$img" - done -} -trap "_cleanup; exit \$status" 0 1 2 3 15 - -# get standard environment, filters and checks -. ./common.rc -. ./common.filter -. ./common.qemu - -# Needs backing file and backing format support -_supported_fmt qcow2 qed -_supported_proto file -_supported_os Linux +# Common filters to mask values that vary in the test output +QMP_FILTERS = [iotests.filter_qmp_testfiles, \ + iotests.filter_qmp_imgfmt] -test_blockjob() -{ - _send_qemu_cmd $QEMU_HANDLE \ - "{'execute': 'blockdev-add', - 'arguments': { - 'node-name': 'drv0', - 'driver': '$IMGFMT', - 'file': { - 'driver': 'file', - 'filename': '$TEST_IMG' - }}}" \ - 'return' +class TestCase: + def __init__(self, name, vm, image_path, cancel_event): + self.name = name + self.vm = vm + self.image_path = image_path + self.cancel_event = cancel_event - # If "$2" is an event, we may or may not see it before the - # {"return": {}}. Therefore, filter the {"return": {}} out both - # here and in the next command. (Naturally, if we do not see it - # here, we will see it before the next command can be executed, - # so it will appear in the next _send_qemu_cmd's output.) - _send_qemu_cmd $QEMU_HANDLE \ - "$1" \ - "$2" \ - | _filter_img_create | _filter_qmp_empty_return + def __enter__(self): + iotests.log(f'=== Testing {self.name} ===') + self.vm.qmp_log('blockdev-add', \ + node_name='drv0', \ + driver=iotests.imgfmt, \ + file={'driver': 'file', 'filename': self.image_path}, \ + filters=QMP_FILTERS) - # We want this to return an error because the block job is still running - _send_qemu_cmd $QEMU_HANDLE \ - "{'execute': 'blockdev-del', - 'arguments': {'node-name': 'drv0'}}" \ - 'error' | _filter_generated_node_ids | _filter_qmp_empty_return + def __exit__(self, *exc_details): + # This is expected to fail because the job still exists + self.vm.qmp_log('blockdev-del', node_name='drv0', \ + filters=[iotests.filter_qmp_generated_node_ids]) - _send_qemu_cmd $QEMU_HANDLE \ - "{'execute': 'block-job-cancel', - 'arguments': {'device': 'job0'}}" \ - "$3" + self.vm.qmp_log('block-job-cancel', device='job0') + event = self.vm.event_wait(self.cancel_event) + iotests.log(event, filters=[iotests.filter_qmp_event]) - _send_qemu_cmd $QEMU_HANDLE \ - "{'execute': 'blockdev-del', - 'arguments': {'node-name': 'drv0'}}" \ - 'return' -} + # This time it succeeds + self.vm.qmp_log('blockdev-del', node_name='drv0') + + # Separate test cases in output + iotests.log('') -TEST_IMG="$TEST_DIR/b.$IMGFMT" _make_test_img 1M -TEST_IMG="$TEST_DIR/m.$IMGFMT" _make_test_img -b "$TEST_DIR/b.$IMGFMT" -F $IMGFMT 1M -_make_test_img -b "$TEST_DIR/m.$IMGFMT" 1M -F $IMGFMT +def main() -> None: + with iotests.FilePath('bottom', 'middle', 'top', 'target') as \ + (bottom_path, middle_path, top_path, target_path), \ + iotests.VM() as vm: -_launch_qemu -nodefaults + iotests.log('Creating bottom <- middle <- top backing file chain...') + IMAGE_SIZE='1M' + iotests.qemu_img_create('-f', iotests.imgfmt, bottom_path, IMAGE_SIZE) + iotests.qemu_img_create('-f', iotests.imgfmt, \ + '-F', iotests.imgfmt, \ + '-b', bottom_path, \ + middle_path, \ + IMAGE_SIZE) + iotests.qemu_img_create('-f', iotests.imgfmt, \ + '-F', iotests.imgfmt, \ + '-b', middle_path, \ + top_path, \ + IMAGE_SIZE) -_send_qemu_cmd $QEMU_HANDLE \ - "{'execute': 'qmp_capabilities'}" \ - 'return' + iotests.log('Starting VM...') + vm.add_args('-nodefaults') + vm.launch() -echo -echo '=== Testing drive-backup ===' -echo + # drive-backup will not send BLOCK_JOB_READY by itself, and cancelling + # the job will consequently result in BLOCK_JOB_CANCELLED being + # emitted. + with TestCase('drive-backup', vm, top_path, 'BLOCK_JOB_CANCELLED'): + vm.qmp_log('drive-backup', \ + job_id='job0', \ + device='drv0', \ + target=target_path, \ + format=iotests.imgfmt, \ + sync='none', \ + filters=QMP_FILTERS) -# drive-backup will not send BLOCK_JOB_READY by itself, and cancelling the job -# will consequently result in BLOCK_JOB_CANCELLED being emitted. + # drive-mirror will send BLOCK_JOB_READY basically immediately, and + # cancelling the job will consequently result in BLOCK_JOB_COMPLETED + # being emitted. + with TestCase('drive-mirror', vm, top_path, 'BLOCK_JOB_COMPLETED'): + vm.qmp_log('drive-mirror', \ + job_id='job0', \ + device='drv0', \ + target=target_path, \ + format=iotests.imgfmt, \ + sync='none', \ + filters=QMP_FILTERS) + event = vm.event_wait('BLOCK_JOB_READY') + assert event is not None # silence mypy + iotests.log(event, filters=[iotests.filter_qmp_event]) -test_blockjob \ - "{'execute': 'drive-backup', - 'arguments': {'job-id': 'job0', - 'device': 'drv0', - 'target': '$TEST_DIR/o.$IMGFMT', - 'format': '$IMGFMT', - 'sync': 'none'}}" \ - 'return' \ - '"status": "null"' + # An active block-commit will send BLOCK_JOB_READY basically + # immediately, and cancelling the job will consequently result in + # BLOCK_JOB_COMPLETED being emitted. + with TestCase('active block-commit', vm, top_path, \ + 'BLOCK_JOB_COMPLETED'): + vm.qmp_log('block-commit', \ + job_id='job0', \ + device='drv0') + event = vm.event_wait('BLOCK_JOB_READY') + assert event is not None # silence mypy + iotests.log(event, filters=[iotests.filter_qmp_event]) -echo -echo '=== Testing drive-mirror ===' -echo + # Give block-commit something to work on, otherwise it would be done + # immediately, send a BLOCK_JOB_COMPLETED and ejecting the BDS would + # work just fine without the block job still running. + iotests.qemu_io(middle_path, '-c', f'write 0 {IMAGE_SIZE}') + with TestCase('non-active block-commit', vm, top_path, \ + 'BLOCK_JOB_CANCELLED'): + vm.qmp_log('block-commit', \ + job_id='job0', \ + device='drv0', \ + top=middle_path, \ + speed=1, \ + filters=[iotests.filter_qmp_testfiles]) -# drive-mirror will send BLOCK_JOB_READY basically immediately, and cancelling -# the job will consequently result in BLOCK_JOB_COMPLETED being emitted. + # Give block-stream something to work on, otherwise it would be done + # immediately, send a BLOCK_JOB_COMPLETED and ejecting the BDS would + # work just fine without the block job still running. + iotests.qemu_io(bottom_path, '-c', f'write 0 {IMAGE_SIZE}') + with TestCase('block-stream', vm, top_path, 'BLOCK_JOB_CANCELLED'): + vm.qmp_log('block-stream', \ + job_id='job0', \ + device='drv0', \ + speed=1) -test_blockjob \ - "{'execute': 'drive-mirror', - 'arguments': {'job-id': 'job0', - 'device': 'drv0', - 'target': '$TEST_DIR/o.$IMGFMT', - 'format': '$IMGFMT', - 'sync': 'none'}}" \ - 'BLOCK_JOB_READY' \ - '"status": "null"' - -echo -echo '=== Testing active block-commit ===' -echo - -# An active block-commit will send BLOCK_JOB_READY basically immediately, and -# cancelling the job will consequently result in BLOCK_JOB_COMPLETED being -# emitted. - -test_blockjob \ - "{'execute': 'block-commit', - 'arguments': {'job-id': 'job0', 'device': 'drv0'}}" \ - 'BLOCK_JOB_READY' \ - '"status": "null"' - -echo -echo '=== Testing non-active block-commit ===' -echo - -# Give block-commit something to work on, otherwise it would be done -# immediately, send a BLOCK_JOB_COMPLETED and ejecting the BDS would work just -# fine without the block job still running. - -$QEMU_IO -c 'write 0 1M' "$TEST_DIR/m.$IMGFMT" | _filter_qemu_io - -test_blockjob \ - "{'execute': 'block-commit', - 'arguments': {'job-id': 'job0', - 'device': 'drv0', - 'top': '$TEST_DIR/m.$IMGFMT', - 'speed': 1}}" \ - 'return' \ - '"status": "null"' - -echo -echo '=== Testing block-stream ===' -echo - -# Give block-stream something to work on, otherwise it would be done -# immediately, send a BLOCK_JOB_COMPLETED and ejecting the BDS would work just -# fine without the block job still running. - -$QEMU_IO -c 'write 0 1M' "$TEST_DIR/b.$IMGFMT" | _filter_qemu_io - -# With some data to stream (and @speed set to 1), block-stream will not complete -# until we send the block-job-cancel command. - -test_blockjob \ - "{'execute': 'block-stream', - 'arguments': {'job-id': 'job0', - 'device': 'drv0', - 'speed': 1}}" \ - 'return' \ - '"status": "null"' - -_cleanup_qemu - -# success, all done -echo "*** done" -rm -f $seq.full -status=0 +if __name__ == '__main__': + iotests.script_main(main, supported_fmts=['qcow2', 'qed'], + supported_protocols=['file']) diff --git a/tests/qemu-iotests/141.out b/tests/qemu-iotests/141.out index 63203d9944..91b7ba50af 100644 --- a/tests/qemu-iotests/141.out +++ b/tests/qemu-iotests/141.out @@ -1,179 +1,69 @@ -QA output created by 141 -Formatting 'TEST_DIR/b.IMGFMT', fmt=IMGFMT size=1048576 -Formatting 'TEST_DIR/m.IMGFMT', fmt=IMGFMT size=1048576 backing_file=TEST_DIR/b.IMGFMT backing_fmt=IMGFMT -Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1048576 backing_file=TEST_DIR/m.IMGFMT backing_fmt=IMGFMT -{'execute': 'qmp_capabilities'} -{"return": {}} - +Creating bottom <- middle <- top backing file chain... +Starting VM... === Testing drive-backup === - -{'execute': 'blockdev-add', - 'arguments': { - 'node-name': 'drv0', - 'driver': 'IMGFMT', - 'file': { - 'driver': 'file', - 'filename': 'TEST_DIR/t.IMGFMT' - }}} +{"execute": "blockdev-add", "arguments": {"driver": "IMGFMT", "file": {"driver": "file", "filename": "TEST_DIR/PID-top"}, "node-name": "drv0"}} {"return": {}} -{'execute': 'drive-backup', -'arguments': {'job-id': 'job0', -'device': 'drv0', -'target': 'TEST_DIR/o.IMGFMT', -'format': 'IMGFMT', -'sync': 'none'}} -Formatting 'TEST_DIR/o.IMGFMT', fmt=IMGFMT size=1048576 backing_file=TEST_DIR/t.IMGFMT backing_fmt=IMGFMT -{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "created", "id": "job0"}} -{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "running", "id": "job0"}} -{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "paused", "id": "job0"}} -{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "running", "id": "job0"}} -{'execute': 'blockdev-del', - 'arguments': {'node-name': 'drv0'}} +{"execute": "drive-backup", "arguments": {"device": "drv0", "format": "IMGFMT", "job-id": "job0", "sync": "none", "target": "TEST_DIR/PID-target"}} +{"return": {}} +{"execute": "blockdev-del", "arguments": {"node-name": "drv0"}} {"error": {"class": "GenericError", "desc": "Node 'drv0' is busy: node is used as backing hd of 'NODE_NAME'"}} -{'execute': 'block-job-cancel', - 'arguments': {'device': 'job0'}} +{"execute": "block-job-cancel", "arguments": {"device": "job0"}} {"return": {}} -{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "aborting", "id": "job0"}} -{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_CANCELLED", "data": {"device": "job0", "len": 1048576, "offset": 0, "speed": 0, "type": "backup"}} -{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "concluded", "id": "job0"}} -{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "null", "id": "job0"}} -{'execute': 'blockdev-del', - 'arguments': {'node-name': 'drv0'}} +{"data": {"device": "job0", "len": 1048576, "offset": 0, "speed": 0, "type": "backup"}, "event": "BLOCK_JOB_CANCELLED", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}} +{"execute": "blockdev-del", "arguments": {"node-name": "drv0"}} {"return": {}} === Testing drive-mirror === - -{'execute': 'blockdev-add', - 'arguments': { - 'node-name': 'drv0', - 'driver': 'IMGFMT', - 'file': { - 'driver': 'file', - 'filename': 'TEST_DIR/t.IMGFMT' - }}} +{"execute": "blockdev-add", "arguments": {"driver": "IMGFMT", "file": {"driver": "file", "filename": "TEST_DIR/PID-top"}, "node-name": "drv0"}} {"return": {}} -{'execute': 'drive-mirror', -'arguments': {'job-id': 'job0', -'device': 'drv0', -'target': 'TEST_DIR/o.IMGFMT', -'format': 'IMGFMT', -'sync': 'none'}} -Formatting 'TEST_DIR/o.IMGFMT', fmt=IMGFMT size=1048576 backing_file=TEST_DIR/t.IMGFMT backing_fmt=IMGFMT -{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "created", "id": "job0"}} -{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "running", "id": "job0"}} -{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "ready", "id": "job0"}} -{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_READY", "data": {"device": "job0", "len": 0, "offset": 0, "speed": 0, "type": "mirror"}} -{'execute': 'blockdev-del', - 'arguments': {'node-name': 'drv0'}} +{"execute": "drive-mirror", "arguments": {"device": "drv0", "format": "IMGFMT", "job-id": "job0", "sync": "none", "target": "TEST_DIR/PID-target"}} +{"return": {}} +{"data": {"device": "job0", "len": 0, "offset": 0, "speed": 0, "type": "mirror"}, "event": "BLOCK_JOB_READY", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}} +{"execute": "blockdev-del", "arguments": {"node-name": "drv0"}} {"error": {"class": "GenericError", "desc": "Node 'drv0' is busy: block device is in use by block job: mirror"}} -{'execute': 'block-job-cancel', - 'arguments': {'device': 'job0'}} +{"execute": "block-job-cancel", "arguments": {"device": "job0"}} {"return": {}} -{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "waiting", "id": "job0"}} -{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "pending", "id": "job0"}} -{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_COMPLETED", "data": {"device": "job0", "len": 0, "offset": 0, "speed": 0, "type": "mirror"}} -{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "concluded", "id": "job0"}} -{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "null", "id": "job0"}} -{'execute': 'blockdev-del', - 'arguments': {'node-name': 'drv0'}} +{"data": {"device": "job0", "len": 0, "offset": 0, "speed": 0, "type": "mirror"}, "event": "BLOCK_JOB_COMPLETED", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}} +{"execute": "blockdev-del", "arguments": {"node-name": "drv0"}} {"return": {}} === Testing active block-commit === - -{'execute': 'blockdev-add', - 'arguments': { - 'node-name': 'drv0', - 'driver': 'IMGFMT', - 'file': { - 'driver': 'file', - 'filename': 'TEST_DIR/t.IMGFMT' - }}} +{"execute": "blockdev-add", "arguments": {"driver": "IMGFMT", "file": {"driver": "file", "filename": "TEST_DIR/PID-top"}, "node-name": "drv0"}} {"return": {}} -{'execute': 'block-commit', -'arguments': {'job-id': 'job0', 'device': 'drv0'}} -{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "created", "id": "job0"}} -{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "running", "id": "job0"}} -{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "ready", "id": "job0"}} -{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_READY", "data": {"device": "job0", "len": 0, "offset": 0, "speed": 0, "type": "commit"}} -{'execute': 'blockdev-del', - 'arguments': {'node-name': 'drv0'}} +{"execute": "block-commit", "arguments": {"device": "drv0", "job-id": "job0"}} +{"return": {}} +{"data": {"device": "job0", "len": 0, "offset": 0, "speed": 0, "type": "commit"}, "event": "BLOCK_JOB_READY", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}} +{"execute": "blockdev-del", "arguments": {"node-name": "drv0"}} {"error": {"class": "GenericError", "desc": "Node 'drv0' is busy: block device is in use by block job: commit"}} -{'execute': 'block-job-cancel', - 'arguments': {'device': 'job0'}} +{"execute": "block-job-cancel", "arguments": {"device": "job0"}} {"return": {}} -{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "waiting", "id": "job0"}} -{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "pending", "id": "job0"}} -{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_COMPLETED", "data": {"device": "job0", "len": 0, "offset": 0, "speed": 0, "type": "commit"}} -{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "concluded", "id": "job0"}} -{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "null", "id": "job0"}} -{'execute': 'blockdev-del', - 'arguments': {'node-name': 'drv0'}} +{"data": {"device": "job0", "len": 0, "offset": 0, "speed": 0, "type": "commit"}, "event": "BLOCK_JOB_COMPLETED", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}} +{"execute": "blockdev-del", "arguments": {"node-name": "drv0"}} {"return": {}} === Testing non-active block-commit === - -wrote 1048576/1048576 bytes at offset 0 -1 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) -{'execute': 'blockdev-add', - 'arguments': { - 'node-name': 'drv0', - 'driver': 'IMGFMT', - 'file': { - 'driver': 'file', - 'filename': 'TEST_DIR/t.IMGFMT' - }}} +{"execute": "blockdev-add", "arguments": {"driver": "IMGFMT", "file": {"driver": "file", "filename": "TEST_DIR/PID-top"}, "node-name": "drv0"}} {"return": {}} -{'execute': 'block-commit', -'arguments': {'job-id': 'job0', -'device': 'drv0', -'top': 'TEST_DIR/m.IMGFMT', -'speed': 1}} -{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "created", "id": "job0"}} -{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "running", "id": "job0"}} -{'execute': 'blockdev-del', - 'arguments': {'node-name': 'drv0'}} +{"execute": "block-commit", "arguments": {"device": "drv0", "job-id": "job0", "speed": 1, "top": "TEST_DIR/PID-middle"}} +{"return": {}} +{"execute": "blockdev-del", "arguments": {"node-name": "drv0"}} {"error": {"class": "GenericError", "desc": "Node 'drv0' is busy: block device is in use by block job: commit"}} -{'execute': 'block-job-cancel', - 'arguments': {'device': 'job0'}} +{"execute": "block-job-cancel", "arguments": {"device": "job0"}} {"return": {}} -{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "aborting", "id": "job0"}} -{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_CANCELLED", "data": {"device": "job0", "len": 1048576, "offset": 524288, "speed": 1, "type": "commit"}} -{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "concluded", "id": "job0"}} -{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "null", "id": "job0"}} -{'execute': 'blockdev-del', - 'arguments': {'node-name': 'drv0'}} +{"data": {"device": "job0", "len": 1048576, "offset": 524288, "speed": 1, "type": "commit"}, "event": "BLOCK_JOB_CANCELLED", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}} +{"execute": "blockdev-del", "arguments": {"node-name": "drv0"}} {"return": {}} === Testing block-stream === - -wrote 1048576/1048576 bytes at offset 0 -1 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) -{'execute': 'blockdev-add', - 'arguments': { - 'node-name': 'drv0', - 'driver': 'IMGFMT', - 'file': { - 'driver': 'file', - 'filename': 'TEST_DIR/t.IMGFMT' - }}} +{"execute": "blockdev-add", "arguments": {"driver": "IMGFMT", "file": {"driver": "file", "filename": "TEST_DIR/PID-top"}, "node-name": "drv0"}} {"return": {}} -{'execute': 'block-stream', -'arguments': {'job-id': 'job0', -'device': 'drv0', -'speed': 1}} -{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "created", "id": "job0"}} -{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "running", "id": "job0"}} -{'execute': 'blockdev-del', - 'arguments': {'node-name': 'drv0'}} +{"execute": "block-stream", "arguments": {"device": "drv0", "job-id": "job0", "speed": 1}} +{"return": {}} +{"execute": "blockdev-del", "arguments": {"node-name": "drv0"}} {"error": {"class": "GenericError", "desc": "Node 'drv0' is busy: block device is in use by block job: stream"}} -{'execute': 'block-job-cancel', - 'arguments': {'device': 'job0'}} +{"execute": "block-job-cancel", "arguments": {"device": "job0"}} {"return": {}} -{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "aborting", "id": "job0"}} -{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_CANCELLED", "data": {"device": "job0", "len": 1048576, "offset": 524288, "speed": 1, "type": "stream"}} -{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "concluded", "id": "job0"}} -{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "null", "id": "job0"}} -{'execute': 'blockdev-del', - 'arguments': {'node-name': 'drv0'}} +{"data": {"device": "job0", "len": 1048576, "offset": 524288, "speed": 1, "type": "stream"}, "event": "BLOCK_JOB_CANCELLED", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}} +{"execute": "blockdev-del", "arguments": {"node-name": "drv0"}} {"return": {}} -*** done + diff --git a/tests/qemu-iotests/143.out b/tests/qemu-iotests/143.out index 9ec5888e0e..d6afa32abc 100644 --- a/tests/qemu-iotests/143.out +++ b/tests/qemu-iotests/143.out @@ -10,6 +10,6 @@ server reported: export 'no_such_export' not present qemu-io: can't open device nbd+unix:///aa--aa1?socket=SOCK_DIR/nbd: Requested export not available server reported: export 'aa--aa...' not present { 'execute': 'quit' } -{"return": {}} {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false, "reason": "host-qmp-quit"}} +{"return": {}} *** done diff --git a/tests/qemu-iotests/149 b/tests/qemu-iotests/149 index 2ae318f16f..c13343d7ef 100755 --- a/tests/qemu-iotests/149 +++ b/tests/qemu-iotests/149 @@ -518,7 +518,7 @@ configs = [ ] -blacklist = [ +unsupported_configs = [ # We don't have a cast-6 cipher impl for QEMU yet "cast6-256-xts-plain64-sha1", "cast6-128-xts-plain64-sha1", @@ -528,17 +528,19 @@ blacklist = [ "twofish-192-xts-plain64-sha1", ] -whitelist = [] +# Optionally test only the configurations in the LUKS_CONFIG +# environment variable +tested_configs = None if "LUKS_CONFIG" in os.environ: - whitelist = os.environ["LUKS_CONFIG"].split(",") + tested_configs = os.environ["LUKS_CONFIG"].split(",") for config in configs: - if config.name in blacklist: - iotests.log("Skipping %s in blacklist" % config.name) + if config.name in unsupported_configs: + iotests.log("Skipping %s (config not supported)" % config.name) continue - if len(whitelist) > 0 and config.name not in whitelist: - iotests.log("Skipping %s not in whitelist" % config.name) + if tested_configs is not None and config.name not in tested_configs: + iotests.log("Skipping %s (by user request)" % config.name) continue test_once(config, qemu_img=False) diff --git a/tests/qemu-iotests/149.out b/tests/qemu-iotests/149.out index 2cc5b82f7c..72ca847159 100644 --- a/tests/qemu-iotests/149.out +++ b/tests/qemu-iotests/149.out @@ -470,7 +470,7 @@ sudo cryptsetup -q -v luksClose qiotest-145-cast5-128-cbc-plain64-sha1 # Delete image unlink TEST_DIR/luks-cast5-128-cbc-plain64-sha1.img -Skipping cast6-256-xts-plain64-sha1 in blacklist +Skipping cast6-256-xts-plain64-sha1 (config not supported) # ================= dm-crypt aes-256-cbc-plain-sha1 ================= # Create image truncate TEST_DIR/luks-aes-256-cbc-plain-sha1.img --size 4194304MB @@ -1297,7 +1297,7 @@ sudo cryptsetup -q -v luksClose qiotest-145-twofish-128-xts-plain64-sha1 # Delete image unlink TEST_DIR/luks-twofish-128-xts-plain64-sha1.img -Skipping twofish-192-xts-plain64-sha1 in blacklist +Skipping twofish-192-xts-plain64-sha1 (config not supported) # ================= dm-crypt serpent-128-xts-plain64-sha1 ================= # Create image truncate TEST_DIR/luks-serpent-128-xts-plain64-sha1.img --size 4194304MB @@ -1534,8 +1534,8 @@ sudo cryptsetup -q -v luksClose qiotest-145-serpent-192-xts-plain64-sha1 # Delete image unlink TEST_DIR/luks-serpent-192-xts-plain64-sha1.img -Skipping cast6-128-xts-plain64-sha1 in blacklist -Skipping cast6-192-xts-plain64-sha1 in blacklist +Skipping cast6-128-xts-plain64-sha1 (config not supported) +Skipping cast6-192-xts-plain64-sha1 (config not supported) # ================= dm-crypt aes-256-xts-plain64-sha224 ================= # Create image truncate TEST_DIR/luks-aes-256-xts-plain64-sha224.img --size 4194304MB diff --git a/tests/qemu-iotests/156.out b/tests/qemu-iotests/156.out index 4a22f0c41a..07e5e83f5d 100644 --- a/tests/qemu-iotests/156.out +++ b/tests/qemu-iotests/156.out @@ -72,8 +72,8 @@ read 65536/65536 bytes at offset 196608 {"return": ""} { 'execute': 'quit' } -{"return": {}} {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false, "reason": "host-qmp-quit"}} +{"return": {}} read 65536/65536 bytes at offset 0 64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) diff --git a/tests/qemu-iotests/176.out b/tests/qemu-iotests/176.out index 9d09b60452..45e9153ef3 100644 --- a/tests/qemu-iotests/176.out +++ b/tests/qemu-iotests/176.out @@ -169,8 +169,8 @@ QMP_VERSION {"return": {}} {"return": {}} {"return": {}} -{"return": {}} {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false, "reason": "host-qmp-quit"}} +{"return": {}} wrote 196608/196608 bytes at offset 2147287040 192 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) wrote 131072/131072 bytes at offset 2147352576 @@ -206,8 +206,8 @@ QMP_VERSION {"return": {}} {"return": {}} {"return": {"sha256": HASH}} -{"return": {}} {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false, "reason": "host-qmp-quit"}} +{"return": {}} === Test pass bitmap.1 === @@ -218,8 +218,8 @@ QMP_VERSION {"return": {}} {"return": {}} {"return": {}} -{"return": {}} {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false, "reason": "host-qmp-quit"}} +{"return": {}} wrote 196608/196608 bytes at offset 2147287040 192 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) wrote 131072/131072 bytes at offset 2147352576 @@ -256,8 +256,8 @@ QMP_VERSION {"return": {}} {"return": {}} {"return": {"sha256": HASH}} -{"return": {}} {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false, "reason": "host-qmp-quit"}} +{"return": {}} === Test pass bitmap.2 === @@ -268,8 +268,8 @@ QMP_VERSION {"return": {}} {"return": {}} {"return": {}} -{"return": {}} {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false, "reason": "host-qmp-quit"}} +{"return": {}} wrote 196608/196608 bytes at offset 2147287040 192 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) wrote 131072/131072 bytes at offset 2147352576 @@ -306,8 +306,8 @@ QMP_VERSION {"return": {}} {"return": {}} {"return": {"sha256": HASH}} -{"return": {}} {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false, "reason": "host-qmp-quit"}} +{"return": {}} === Test pass bitmap.3 === @@ -318,8 +318,8 @@ QMP_VERSION {"return": {}} {"return": {}} {"return": {}} -{"return": {}} {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false, "reason": "host-qmp-quit"}} +{"return": {}} wrote 196608/196608 bytes at offset 2147287040 192 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) wrote 131072/131072 bytes at offset 2147352576 @@ -353,6 +353,6 @@ QMP_VERSION {"return": {}} {"return": {}} {"return": {"sha256": HASH}} -{"return": {}} {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false, "reason": "host-qmp-quit"}} +{"return": {}} *** done diff --git a/tests/qemu-iotests/182.out b/tests/qemu-iotests/182.out index 57f7265458..83fc1a4797 100644 --- a/tests/qemu-iotests/182.out +++ b/tests/qemu-iotests/182.out @@ -53,6 +53,6 @@ Formatting 'TEST_DIR/t.qcow2.overlay', fmt=qcow2 cluster_size=65536 extended_l2= {'execute': 'qmp_capabilities'} {"return": {}} {'execute': 'quit'} -{"return": {}} {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false, "reason": "host-qmp-quit"}} +{"return": {}} *** done diff --git a/tests/qemu-iotests/183.out b/tests/qemu-iotests/183.out index fd9c2e52a5..51aa41c888 100644 --- a/tests/qemu-iotests/183.out +++ b/tests/qemu-iotests/183.out @@ -53,11 +53,11 @@ wrote 65536/65536 bytes at offset 1048576 === Shut down and check image === {"execute":"quit"} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false, "reason": "host-qmp-quit"}} {"return": {}} {"execute":"quit"} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false, "reason": "host-qmp-quit"}} {"return": {}} -{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false, "reason": "host-qmp-quit"}} -{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false, "reason": "host-qmp-quit"}} No errors were found on the image. No errors were found on the image. wrote 65536/65536 bytes at offset 1048576 diff --git a/tests/qemu-iotests/184.out b/tests/qemu-iotests/184.out index 77e5489d65..e8f631f853 100644 --- a/tests/qemu-iotests/184.out +++ b/tests/qemu-iotests/184.out @@ -89,10 +89,6 @@ Testing: "return": [ ] } -{ - "return": { - } -} { "timestamp": { "seconds": TIMESTAMP, @@ -104,6 +100,10 @@ Testing: "reason": "host-qmp-quit" } } +{ + "return": { + } +} == property changes in ThrottleGroup == @@ -169,10 +169,6 @@ Testing: "iops-total-max": 0 } } -{ - "return": { - } -} { "timestamp": { "seconds": TIMESTAMP, @@ -184,6 +180,10 @@ Testing: "reason": "host-qmp-quit" } } +{ + "return": { + } +} == object creation/set errors == @@ -211,10 +211,6 @@ Testing: "desc": "bps/iops/max total values and read/write values cannot be used at the same time" } } -{ - "return": { - } -} { "timestamp": { "seconds": TIMESTAMP, @@ -226,6 +222,10 @@ Testing: "reason": "host-qmp-quit" } } +{ + "return": { + } +} == don't specify group == @@ -247,10 +247,6 @@ Testing: "desc": "Parameter 'throttle-group' is missing" } } -{ - "return": { - } -} { "timestamp": { "seconds": TIMESTAMP, @@ -262,6 +258,10 @@ Testing: "reason": "host-qmp-quit" } } +{ + "return": { + } +} *** done diff --git a/tests/qemu-iotests/185 b/tests/qemu-iotests/185 index 2ae0a85bbf..17489fb91c 100755 --- a/tests/qemu-iotests/185 +++ b/tests/qemu-iotests/185 @@ -344,14 +344,14 @@ wait_for_job_and_quit() { sleep 1 + # List of expected events + capture_events='BLOCK_JOB_CANCELLED JOB_STATUS_CHANGE SHUTDOWN' + _send_qemu_cmd $h \ '{"execute": "quit"}' \ 'return' - # List of expected events - capture_events='BLOCK_JOB_CANCELLED JOB_STATUS_CHANGE SHUTDOWN' _wait_event $h 'SHUTDOWN' - QEMU_EVENTS= # Ignore all JOB_STATUS_CHANGE events that came before SHUTDOWN _wait_event $h 'JOB_STATUS_CHANGE' # standby _wait_event $h 'JOB_STATUS_CHANGE' # ready _wait_event $h 'JOB_STATUS_CHANGE' # standby diff --git a/tests/qemu-iotests/185.out b/tests/qemu-iotests/185.out index 7292c26bae..6af0953c4d 100644 --- a/tests/qemu-iotests/185.out +++ b/tests/qemu-iotests/185.out @@ -40,9 +40,16 @@ Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=65536 extended_l2=off comp {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "running", "id": "disk"}} {"return": {}} { 'execute': 'quit' } -{"return": {}} {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false, "reason": "host-qmp-quit"}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "paused", "id": "disk"}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "running", "id": "disk"}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "paused", "id": "disk"}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "running", "id": "disk"}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "aborting", "id": "disk"}} {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_CANCELLED", "data": {"device": "disk", "len": 67108864, "offset": 524288, "speed": 65536, "type": "commit"}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "concluded", "id": "disk"}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "null", "id": "disk"}} +{"return": {}} === Start active commit job and exit qemu === @@ -56,9 +63,16 @@ Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=65536 extended_l2=off comp {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "running", "id": "disk"}} {"return": {}} { 'execute': 'quit' } -{"return": {}} {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false, "reason": "host-qmp-quit"}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "paused", "id": "disk"}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "running", "id": "disk"}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "paused", "id": "disk"}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "running", "id": "disk"}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "aborting", "id": "disk"}} {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_CANCELLED", "data": {"device": "disk", "len": 4194304, "offset": 4194304, "speed": 65536, "type": "commit"}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "concluded", "id": "disk"}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "null", "id": "disk"}} +{"return": {}} === Start mirror job and exit qemu === @@ -75,9 +89,16 @@ Formatting 'TEST_DIR/t.qcow2.copy', fmt=qcow2 cluster_size=65536 extended_l2=off {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "running", "id": "disk"}} {"return": {}} { 'execute': 'quit' } -{"return": {}} {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false, "reason": "host-qmp-quit"}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "paused", "id": "disk"}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "running", "id": "disk"}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "paused", "id": "disk"}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "running", "id": "disk"}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "aborting", "id": "disk"}} {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_CANCELLED", "data": {"device": "disk", "len": 4194304, "offset": 4194304, "speed": 65536, "type": "mirror"}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "concluded", "id": "disk"}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "null", "id": "disk"}} +{"return": {}} === Start backup job and exit qemu === @@ -97,9 +118,16 @@ Formatting 'TEST_DIR/t.qcow2.copy', fmt=qcow2 cluster_size=65536 extended_l2=off {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "running", "id": "disk"}} {"return": {}} { 'execute': 'quit' } -{"return": {}} {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false, "reason": "host-qmp-quit"}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "paused", "id": "disk"}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "running", "id": "disk"}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "paused", "id": "disk"}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "running", "id": "disk"}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "aborting", "id": "disk"}} {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_CANCELLED", "data": {"device": "disk", "len": 67108864, "offset": 65536, "speed": 65536, "type": "backup"}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "concluded", "id": "disk"}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "null", "id": "disk"}} +{"return": {}} === Start streaming job and exit qemu === @@ -112,9 +140,16 @@ Formatting 'TEST_DIR/t.qcow2.copy', fmt=qcow2 cluster_size=65536 extended_l2=off {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "running", "id": "disk"}} {"return": {}} { 'execute': 'quit' } -{"return": {}} {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false, "reason": "host-qmp-quit"}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "paused", "id": "disk"}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "running", "id": "disk"}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "paused", "id": "disk"}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "running", "id": "disk"}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "aborting", "id": "disk"}} {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_CANCELLED", "data": {"device": "disk", "len": 67108864, "offset": 524288, "speed": 65536, "type": "stream"}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "concluded", "id": "disk"}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "null", "id": "disk"}} +{"return": {}} No errors were found on the image. === Start mirror to throttled QSD and exit qemu === diff --git a/tests/qemu-iotests/191.out b/tests/qemu-iotests/191.out index ea88777374..c3309e4bc6 100644 --- a/tests/qemu-iotests/191.out +++ b/tests/qemu-iotests/191.out @@ -378,10 +378,6 @@ wrote 65536/65536 bytes at offset 1048576 ] } { 'execute': 'quit' } -{ - "return": { - } -} { "timestamp": { "seconds": TIMESTAMP, @@ -393,6 +389,10 @@ wrote 65536/65536 bytes at offset 1048576 "reason": "host-qmp-quit" } } +{ + "return": { + } +} image: TEST_DIR/t.IMGFMT file format: IMGFMT virtual size: 64 MiB (67108864 bytes) @@ -796,10 +796,6 @@ wrote 65536/65536 bytes at offset 1048576 ] } { 'execute': 'quit' } -{ - "return": { - } -} { "timestamp": { "seconds": TIMESTAMP, @@ -811,6 +807,10 @@ wrote 65536/65536 bytes at offset 1048576 "reason": "host-qmp-quit" } } +{ + "return": { + } +} image: TEST_DIR/t.IMGFMT file format: IMGFMT virtual size: 64 MiB (67108864 bytes) diff --git a/tests/qemu-iotests/195.out b/tests/qemu-iotests/195.out index ec84df5012..91717d302e 100644 --- a/tests/qemu-iotests/195.out +++ b/tests/qemu-iotests/195.out @@ -17,10 +17,6 @@ Testing: -drive if=none,file=TEST_DIR/t.IMGFMT,backing.node-name=mid "return": { } } -{ - "return": { - } -} { "timestamp": { "seconds": TIMESTAMP, @@ -32,6 +28,10 @@ Testing: -drive if=none,file=TEST_DIR/t.IMGFMT,backing.node-name=mid "reason": "host-qmp-quit" } } +{ + "return": { + } +} image: TEST_DIR/t.IMGFMT.mid file format: IMGFMT @@ -55,10 +55,6 @@ Testing: -drive if=none,file=TEST_DIR/t.IMGFMT,node-name=top "return": { } } -{ - "return": { - } -} { "timestamp": { "seconds": TIMESTAMP, @@ -70,6 +66,10 @@ Testing: -drive if=none,file=TEST_DIR/t.IMGFMT,node-name=top "reason": "host-qmp-quit" } } +{ + "return": { + } +} image: TEST_DIR/t.IMGFMT file format: IMGFMT diff --git a/tests/qemu-iotests/223.out b/tests/qemu-iotests/223.out index e5e7f42caa..5f5b42e2dc 100644 --- a/tests/qemu-iotests/223.out +++ b/tests/qemu-iotests/223.out @@ -11,8 +11,8 @@ QMP_VERSION {"return": {}} {"return": {}} {"return": {}} -{"return": {}} {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false, "reason": "host-qmp-quit"}} +{"return": {}} === Write part of the file under active bitmap === @@ -145,14 +145,14 @@ read 2097152/2097152 bytes at offset 2097152 {"execute":"nbd-server-remove", "arguments":{"name":"n"}} -{"return": {}} -{"execute":"nbd-server-remove", - "arguments":{"name":"n2"}} {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_EXPORT_DELETED", "data": {"id": "n"}} {"return": {}} {"execute":"nbd-server-remove", "arguments":{"name":"n2"}} {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_EXPORT_DELETED", "data": {"id": "n2"}} +{"return": {}} +{"execute":"nbd-server-remove", + "arguments":{"name":"n2"}} {"error": {"class": "GenericError", "desc": "Export 'n2' is not found"}} {"execute":"nbd-server-stop"} {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_EXPORT_DELETED", "data": {"id": "n3"}} @@ -267,14 +267,14 @@ read 2097152/2097152 bytes at offset 2097152 {"execute":"nbd-server-remove", "arguments":{"name":"n"}} -{"return": {}} -{"execute":"nbd-server-remove", - "arguments":{"name":"n2"}} {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_EXPORT_DELETED", "data": {"id": "n"}} {"return": {}} {"execute":"nbd-server-remove", "arguments":{"name":"n2"}} {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_EXPORT_DELETED", "data": {"id": "n2"}} +{"return": {}} +{"execute":"nbd-server-remove", + "arguments":{"name":"n2"}} {"error": {"class": "GenericError", "desc": "Export 'n2' is not found"}} {"execute":"nbd-server-stop"} {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_EXPORT_DELETED", "data": {"id": "n3"}} @@ -282,8 +282,8 @@ read 2097152/2097152 bytes at offset 2097152 {"execute":"nbd-server-stop"} {"error": {"class": "GenericError", "desc": "NBD server not running"}} {"execute":"quit"} -{"return": {}} {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false, "reason": "host-qmp-quit"}} +{"return": {}} === Use qemu-nbd as server === diff --git a/tests/qemu-iotests/227.out b/tests/qemu-iotests/227.out index a947b1a87d..d6a1d4ecb6 100644 --- a/tests/qemu-iotests/227.out +++ b/tests/qemu-iotests/227.out @@ -54,10 +54,6 @@ Testing: -drive driver=null-co,read-zeroes=on,if=virtio } ] } -{ - "return": { - } -} { "timestamp": { "seconds": TIMESTAMP, @@ -69,6 +65,10 @@ Testing: -drive driver=null-co,read-zeroes=on,if=virtio "reason": "host-qmp-quit" } } +{ + "return": { + } +} === blockstats with -drive if=none === @@ -124,10 +124,6 @@ Testing: -drive driver=null-co,if=none } ] } -{ - "return": { - } -} { "timestamp": { "seconds": TIMESTAMP, @@ -139,6 +135,10 @@ Testing: -drive driver=null-co,if=none "reason": "host-qmp-quit" } } +{ + "return": { + } +} === blockstats with -blockdev === @@ -155,10 +155,6 @@ Testing: -blockdev driver=null-co,node-name=null "return": [ ] } -{ - "return": { - } -} { "timestamp": { "seconds": TIMESTAMP, @@ -170,6 +166,10 @@ Testing: -blockdev driver=null-co,node-name=null "reason": "host-qmp-quit" } } +{ + "return": { + } +} === blockstats with -blockdev and -device === @@ -226,10 +226,6 @@ Testing: -blockdev driver=null-co,read-zeroes=on,node-name=null -device virtio-b } ] } -{ - "return": { - } -} { "timestamp": { "seconds": TIMESTAMP, @@ -241,5 +237,9 @@ Testing: -blockdev driver=null-co,read-zeroes=on,node-name=null -device virtio-b "reason": "host-qmp-quit" } } +{ + "return": { + } +} *** done diff --git a/tests/qemu-iotests/247.out b/tests/qemu-iotests/247.out index e909e83994..7d252e7fe4 100644 --- a/tests/qemu-iotests/247.out +++ b/tests/qemu-iotests/247.out @@ -17,6 +17,6 @@ QMP_VERSION {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_COMPLETED", "data": {"device": "job0", "len": 134217728, "offset": 134217728, "speed": 0, "type": "commit"}} {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "concluded", "id": "job0"}} {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "null", "id": "job0"}} -{"return": {}} {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false, "reason": "host-qmp-quit"}} +{"return": {}} *** done diff --git a/tests/qemu-iotests/273.out b/tests/qemu-iotests/273.out index 6a74a8138b..71843f02de 100644 --- a/tests/qemu-iotests/273.out +++ b/tests/qemu-iotests/273.out @@ -282,10 +282,6 @@ Testing: -blockdev file,node-name=base,filename=TEST_DIR/t.IMGFMT.base -blockdev ] } } -{ - "return": { - } -} { "timestamp": { "seconds": TIMESTAMP, @@ -297,5 +293,9 @@ Testing: -blockdev file,node-name=base,filename=TEST_DIR/t.IMGFMT.base -blockdev "reason": "host-qmp-quit" } } +{ + "return": { + } +} *** done diff --git a/tests/qemu-iotests/308 b/tests/qemu-iotests/308 index de12b2b1b9..ea81dc496a 100755 --- a/tests/qemu-iotests/308 +++ b/tests/qemu-iotests/308 @@ -77,6 +77,7 @@ fuse_export_add() # $1: Export ID fuse_export_del() { + capture_events="BLOCK_EXPORT_DELETED" \ _send_qemu_cmd $QEMU_HANDLE \ "{'execute': 'block-export-del', 'arguments': { @@ -84,8 +85,7 @@ fuse_export_del() } }" \ 'return' - _send_qemu_cmd $QEMU_HANDLE \ - '' \ + _wait_event $QEMU_HANDLE \ 'BLOCK_EXPORT_DELETED' } diff --git a/tests/qemu-iotests/308.out b/tests/qemu-iotests/308.out index d5767133b1..e5e233691d 100644 --- a/tests/qemu-iotests/308.out +++ b/tests/qemu-iotests/308.out @@ -165,9 +165,9 @@ OK: Post-truncate image size is as expected === Tear down === {'execute': 'quit'} -{"return": {}} {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false, "reason": "host-qmp-quit"}} {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_EXPORT_DELETED", "data": {"id": "export-mp"}} +{"return": {}} === Compare copy with original === Images are identical. @@ -201,9 +201,9 @@ wrote 67108864/67108864 bytes at offset 0 read 67108864/67108864 bytes at offset 0 64 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) {'execute': 'quit'} -{"return": {}} {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false, "reason": "host-qmp-quit"}} {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_EXPORT_DELETED", "data": {"id": "export"}} +{"return": {}} read 67108864/67108864 bytes at offset 0 64 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) *** done diff --git a/tests/qemu-iotests/iotests.py b/tests/qemu-iotests/iotests.py index e5c5798c71..ea48af4a7b 100644 --- a/tests/qemu-iotests/iotests.py +++ b/tests/qemu-iotests/iotests.py @@ -651,6 +651,13 @@ def filter_qmp_virtio_scsi(qmsg): def filter_generated_node_ids(msg): return re.sub("#block[0-9]+", "NODE_NAME", msg) +def filter_qmp_generated_node_ids(qmsg): + def _filter(_key, value): + if is_str(value): + return filter_generated_node_ids(value) + return value + return filter_qmp(qmsg, _filter) + def filter_img_info(output: str, filename: str, drop_child_info: bool = True) -> str: lines = [] diff --git a/tests/qemu-iotests/testenv.py b/tests/qemu-iotests/testenv.py index e67ebd254b..3ff38f2661 100644 --- a/tests/qemu-iotests/testenv.py +++ b/tests/qemu-iotests/testenv.py @@ -40,7 +40,7 @@ def get_default_machine(qemu_prog: str) -> str: machines = outp.split('\n') try: - default_machine = next(m for m in machines if m.endswith(' (default)')) + default_machine = next(m for m in machines if ' (default)' in m) except StopIteration: return '' default_machine = default_machine.split(' ', 1)[0] diff --git a/tests/qemu-iotests/tests/file-io-error b/tests/qemu-iotests/tests/file-io-error index 88ee5f670c..fb8db73b31 100755 --- a/tests/qemu-iotests/tests/file-io-error +++ b/tests/qemu-iotests/tests/file-io-error @@ -99,13 +99,12 @@ echo $QEMU_IO -f file -c 'write 0 64M' "$TEST_DIR/fuse-export" | _filter_qemu_io echo -_send_qemu_cmd $QEMU_HANDLE \ +capture_events=BLOCK_EXPORT_DELETED _send_qemu_cmd $QEMU_HANDLE \ "{'execute': 'block-export-del', 'arguments': {'id': 'exp0'}}" \ 'return' -_send_qemu_cmd $QEMU_HANDLE \ - '' \ +_wait_event $QEMU_HANDLE \ 'BLOCK_EXPORT_DELETED' _send_qemu_cmd $QEMU_HANDLE \ diff --git a/tests/qemu-iotests/tests/iothreads-resize.out b/tests/qemu-iotests/tests/iothreads-resize.out index 2ca5a9d964..2967ac8f0d 100644 --- a/tests/qemu-iotests/tests/iothreads-resize.out +++ b/tests/qemu-iotests/tests/iothreads-resize.out @@ -3,8 +3,8 @@ Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 QMP_VERSION {"return": {}} {"return": {}} -{"return": {}} {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false, "reason": "host-qmp-quit"}} +{"return": {}} image: TEST_DIR/t.IMGFMT file format: IMGFMT virtual size: 128 MiB (134217728 bytes) diff --git a/tests/qemu-iotests/tests/iothreads-stream b/tests/qemu-iotests/tests/iothreads-stream new file mode 100755 index 0000000000..503f221f16 --- /dev/null +++ b/tests/qemu-iotests/tests/iothreads-stream @@ -0,0 +1,74 @@ +#!/usr/bin/env python3 +# group: rw quick auto +# +# Copyright (C) 2023 Red Hat, Inc. +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +# +# Creator/Owner: Kevin Wolf + +import iotests + +iotests.script_initialize(supported_fmts=['qcow2'], + supported_platforms=['linux']) +iotests.verify_virtio_scsi_pci_or_ccw() + +with iotests.FilePath('disk1.img') as base1_path, \ + iotests.FilePath('disk1-snap.img') as snap1_path, \ + iotests.FilePath('disk2.img') as base2_path, \ + iotests.FilePath('disk2-snap.img') as snap2_path, \ + iotests.VM() as vm: + + img_size = '10M' + + # Only one iothread for both disks + vm.add_object('iothread,id=iothread0') + vm.add_device('virtio-scsi,iothread=iothread0') + + iotests.log('Preparing disks...') + for i, base_path, snap_path in ((0, base1_path, snap1_path), + (1, base2_path, snap2_path)): + iotests.qemu_img_create('-f', iotests.imgfmt, base_path, img_size) + iotests.qemu_img_create('-f', iotests.imgfmt, '-b', base_path, + '-F', iotests.imgfmt, snap_path) + + iotests.qemu_io_log('-c', f'write 0 {img_size}', base_path) + + vm.add_blockdev(f'file,node-name=disk{i}-base-file,' + f'filename={base_path}') + vm.add_blockdev(f'qcow2,node-name=disk{i}-base,file=disk{i}-base-file') + vm.add_blockdev(f'file,node-name=disk{i}-file,filename={snap_path}') + vm.add_blockdev(f'qcow2,node-name=disk{i},file=disk{i}-file,' + f'backing=disk{i}-base') + vm.add_device(f'scsi-hd,drive=disk{i}') + + iotests.log('Launching VM...') + vm.launch() + + iotests.log('Starting stream jobs...') + iotests.log(vm.qmp('block-stream', device='disk0', job_id='job0')) + iotests.log(vm.qmp('block-stream', device='disk1', job_id='job1')) + + finished = 0 + while True: + try: + ev = vm.event_wait('JOB_STATUS_CHANGE', timeout=0.1) + if ev is not None and ev['data']['status'] == 'null': + finished += 1 + # The test is done once both jobs are gone + if finished == 2: + break + except TimeoutError: + pass + vm.cmd('query-jobs') diff --git a/tests/qemu-iotests/tests/iothreads-stream.out b/tests/qemu-iotests/tests/iothreads-stream.out new file mode 100644 index 0000000000..ef134165e5 --- /dev/null +++ b/tests/qemu-iotests/tests/iothreads-stream.out @@ -0,0 +1,11 @@ +Preparing disks... +wrote 10485760/10485760 bytes at offset 0 +10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) + +wrote 10485760/10485760 bytes at offset 0 +10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) + +Launching VM... +Starting stream jobs... +{"return": {}} +{"return": {}} diff --git a/tests/qemu-iotests/tests/qcow2-internal-snapshots b/tests/qemu-iotests/tests/qcow2-internal-snapshots new file mode 100755 index 0000000000..36523aba06 --- /dev/null +++ b/tests/qemu-iotests/tests/qcow2-internal-snapshots @@ -0,0 +1,170 @@ +#!/usr/bin/env bash +# group: rw quick +# +# Test case for internal snapshots in qcow2 +# +# Copyright (C) 2023 Red Hat, Inc. +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +# + +# creator +owner=kwolf@redhat.com + +seq="$(basename $0)" +echo "QA output created by $seq" + +status=1 # failure is the default! + +_cleanup() +{ + _cleanup_test_img +} +trap "_cleanup; exit \$status" 0 1 2 3 15 + +# get standard environment, filters and checks +. ../common.rc +. ../common.filter + +# This tests qcow2-specific low-level functionality +_supported_fmt qcow2 +_supported_proto generic +# Internal snapshots are (currently) impossible with refcount_bits=1, +# and generally impossible with external data files +_unsupported_imgopts 'compat=0.10' 'refcount_bits=1[^0-9]' data_file + +IMG_SIZE=64M + +_qemu() +{ + $QEMU -no-shutdown -nographic -monitor stdio -serial none \ + -blockdev file,filename="$TEST_IMG",node-name=disk0-file \ + -blockdev "$IMGFMT",file=disk0-file,node-name=disk0 \ + -object iothread,id=iothread0 \ + -device virtio-scsi,iothread=iothread0 \ + -device scsi-hd,drive=disk0,share-rw=on \ + "$@" 2>&1 |\ + _filter_qemu | _filter_hmp | _filter_qemu_io +} + +_make_test_img $IMG_SIZE + +echo +echo "=== Write some data, take a snapshot and overwrite part of it ===" +echo + +{ + echo 'qemu-io disk0 "write -P0x11 0 1M"' + # Give qemu some time to boot before saving the VM state + sleep 0.5 + echo "savevm snap0" + echo 'qemu-io disk0 "write -P0x22 0 512k"' + echo "quit" +} | _qemu + +echo +$QEMU_IMG snapshot -l "$TEST_IMG" | _filter_date | _filter_vmstate_size +_check_test_img + +echo +echo "=== Verify that loading the snapshot reverts to the old content ===" +echo + +{ + # -loadvm reverted the write from the previous QEMU instance + echo 'qemu-io disk0 "read -P0x11 0 1M"' + + # Verify that it works without restarting QEMU, too + echo 'qemu-io disk0 "write -P0x33 512k 512k"' + echo "loadvm snap0" + echo 'qemu-io disk0 "read -P0x11 0 1M"' + + # Verify COW by writing a partial cluster + echo 'qemu-io disk0 "write -P0x33 63k 2k"' + echo 'qemu-io disk0 "read -P0x11 0 63k"' + echo 'qemu-io disk0 "read -P0x33 63k 2k"' + echo 'qemu-io disk0 "read -P0x11 65k 63k"' + + # Take a second snapshot + echo "savevm snap1" + + echo "quit" +} | _qemu -loadvm snap0 + +echo +$QEMU_IMG snapshot -l "$TEST_IMG" | _filter_date | _filter_vmstate_size +_check_test_img + +echo +echo "=== qemu-img snapshot can revert to snapshots ===" +echo + +$QEMU_IMG snapshot -a snap0 "$TEST_IMG" +$QEMU_IO -c "read -P0x11 0 1M" "$TEST_IMG" | _filter_qemu_io +$QEMU_IMG snapshot -a snap1 "$TEST_IMG" +$QEMU_IO \ + -c "read -P0x11 0 63k" \ + -c "read -P0x33 63k 2k" \ + -c "read -P0x11 65k 63k" \ + "$TEST_IMG" | _filter_qemu_io + +echo +echo "=== Deleting snapshots ===" +echo +{ + # The active layer stays unaffected by deleting the snapshot + echo "delvm snap1" + echo 'qemu-io disk0 "read -P0x11 0 63k"' + echo 'qemu-io disk0 "read -P0x33 63k 2k"' + echo 'qemu-io disk0 "read -P0x11 65k 63k"' + + echo "quit" +} | _qemu + + +echo +$QEMU_IMG snapshot -l "$TEST_IMG" | _filter_date | _filter_vmstate_size +_check_test_img + +echo +echo "=== Error cases ===" +echo + +# snap1 should not exist any more +_qemu -loadvm snap1 + +echo +{ + echo "loadvm snap1" + echo "quit" +} | _qemu + +# Snapshot operations and inactive images are incompatible +echo +_qemu -loadvm snap0 -incoming defer +{ + echo "loadvm snap0" + echo "delvm snap0" + echo "savevm snap1" + echo "quit" +} | _qemu -incoming defer + +# -loadvm and -preconfig are incompatible +echo +_qemu -loadvm snap0 -preconfig + +# success, all done +echo "*** done" +rm -f $seq.full +status=0 diff --git a/tests/qemu-iotests/tests/qcow2-internal-snapshots.out b/tests/qemu-iotests/tests/qcow2-internal-snapshots.out new file mode 100644 index 0000000000..438f535e6a --- /dev/null +++ b/tests/qemu-iotests/tests/qcow2-internal-snapshots.out @@ -0,0 +1,107 @@ +QA output created by qcow2-internal-snapshots +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 + +=== Write some data, take a snapshot and overwrite part of it === + +QEMU X.Y.Z monitor - type 'help' for more information +(qemu) qemu-io disk0 "write -P0x11 0 1M" +wrote 1048576/1048576 bytes at offset 0 +1 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +(qemu) savevm snap0 +(qemu) qemu-io disk0 "write -P0x22 0 512k" +wrote 524288/524288 bytes at offset 0 +512 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +(qemu) quit + +Snapshot list: +ID TAG VM SIZE DATE VM CLOCK ICOUNT +1 snap0 SIZE yyyy-mm-dd hh:mm:ss 00:00:00.000 +No errors were found on the image. + +=== Verify that loading the snapshot reverts to the old content === + +QEMU X.Y.Z monitor - type 'help' for more information +(qemu) qemu-io disk0 "read -P0x11 0 1M" +read 1048576/1048576 bytes at offset 0 +1 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +(qemu) qemu-io disk0 "write -P0x33 512k 512k" +wrote 524288/524288 bytes at offset 524288 +512 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +(qemu) loadvm snap0 +(qemu) qemu-io disk0 "read -P0x11 0 1M" +read 1048576/1048576 bytes at offset 0 +1 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +(qemu) qemu-io disk0 "write -P0x33 63k 2k" +wrote 2048/2048 bytes at offset 64512 +2 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +(qemu) qemu-io disk0 "read -P0x11 0 63k" +read 64512/64512 bytes at offset 0 +63 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +(qemu) qemu-io disk0 "read -P0x33 63k 2k" +read 2048/2048 bytes at offset 64512 +2 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +(qemu) qemu-io disk0 "read -P0x11 65k 63k" +read 64512/64512 bytes at offset 66560 +63 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +(qemu) savevm snap1 +(qemu) quit + +Snapshot list: +ID TAG VM SIZE DATE VM CLOCK ICOUNT +1 snap0 SIZE yyyy-mm-dd hh:mm:ss 00:00:00.000 +2 snap1 SIZE yyyy-mm-dd hh:mm:ss 00:00:00.000 +No errors were found on the image. + +=== qemu-img snapshot can revert to snapshots === + +read 1048576/1048576 bytes at offset 0 +1 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 64512/64512 bytes at offset 0 +63 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 2048/2048 bytes at offset 64512 +2 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 64512/64512 bytes at offset 66560 +63 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) + +=== Deleting snapshots === + +QEMU X.Y.Z monitor - type 'help' for more information +(qemu) delvm snap1 +(qemu) qemu-io disk0 "read -P0x11 0 63k" +read 64512/64512 bytes at offset 0 +63 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +(qemu) qemu-io disk0 "read -P0x33 63k 2k" +read 2048/2048 bytes at offset 64512 +2 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +(qemu) qemu-io disk0 "read -P0x11 65k 63k" +read 64512/64512 bytes at offset 66560 +63 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +(qemu) quit + +Snapshot list: +ID TAG VM SIZE DATE VM CLOCK ICOUNT +1 snap0 SIZE yyyy-mm-dd hh:mm:ss 00:00:00.000 +No errors were found on the image. + +=== Error cases === + +QEMU X.Y.Z monitor - type 'help' for more information +(qemu) QEMU_PROG: Snapshot 'snap1' does not exist in one or more devices + +QEMU X.Y.Z monitor - type 'help' for more information +(qemu) loadvm snap1 +Error: Snapshot 'snap1' does not exist in one or more devices +(qemu) quit + +QEMU_PROG: 'incoming' and 'loadvm' options are mutually exclusive +QEMU X.Y.Z monitor - type 'help' for more information +(qemu) loadvm snap0 +Error: Device 'disk0' is writable but does not support snapshots +(qemu) delvm snap0 +Error: Device 'disk0' is writable but does not support snapshots +(qemu) savevm snap1 +Error: Device 'disk0' is writable but does not support snapshots +(qemu) quit + +QEMU_PROG: 'preconfig' and 'loadvm' options are mutually exclusive +*** done diff --git a/tests/qemu-iotests/tests/qsd-jobs.out b/tests/qemu-iotests/tests/qsd-jobs.out index c1bc9b8356..aa6b6d1aef 100644 --- a/tests/qemu-iotests/tests/qsd-jobs.out +++ b/tests/qemu-iotests/tests/qsd-jobs.out @@ -7,8 +7,8 @@ Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728 backing_file=TEST_DIR/ QMP_VERSION {"return": {}} {"return": {}} -{"return": {}} {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_CANCELLED", "data": {"device": "job0", "len": 0, "offset": 0, "speed": 0, "type": "commit"}} +{"return": {}} === Streaming can't get permission on base node === @@ -17,6 +17,6 @@ QMP_VERSION {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "created", "id": "job0"}} {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "null", "id": "job0"}} {"error": {"class": "GenericError", "desc": "Permission conflict on node 'fmt_base': permissions 'write' are both required by an unnamed block device (uses node 'fmt_base' as 'root' child) and unshared by stream job 'job0' (uses node 'fmt_base' as 'intermediate node' child)."}} -{"return": {}} {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_EXPORT_DELETED", "data": {"id": "export1"}} +{"return": {}} *** done diff --git a/tests/qtest/bios-tables-test.c b/tests/qtest/bios-tables-test.c index 71af5cf69f..fe6a9a8563 100644 --- a/tests/qtest/bios-tables-test.c +++ b/tests/qtest/bios-tables-test.c @@ -112,6 +112,7 @@ static const char *iasl; #endif static int verbosity_level; +static GArray *load_expected_aml(test_data *data); static bool compare_signature(const AcpiSdtTable *sdt, const char *signature) { @@ -244,21 +245,32 @@ static void test_acpi_fadt_table(test_data *data) static void dump_aml_files(test_data *data, bool rebuild) { - AcpiSdtTable *sdt; + AcpiSdtTable *sdt, *exp_sdt; GError *error = NULL; gchar *aml_file = NULL; + test_data exp_data = {}; gint fd; ssize_t ret; int i; + exp_data.tables = load_expected_aml(data); for (i = 0; i < data->tables->len; ++i) { const char *ext = data->variant ? data->variant : ""; sdt = &g_array_index(data->tables, AcpiSdtTable, i); + exp_sdt = &g_array_index(exp_data.tables, AcpiSdtTable, i); g_assert(sdt->aml); + g_assert(exp_sdt->aml); if (rebuild) { aml_file = g_strdup_printf("%s/%s/%.4s%s", data_dir, data->machine, sdt->aml, ext); + if (!g_file_test(aml_file, G_FILE_TEST_EXISTS) && + sdt->aml_len == exp_sdt->aml_len && + !memcmp(sdt->aml, exp_sdt->aml, sdt->aml_len)) { + /* identical tables, no need to write new files */ + g_free(aml_file); + continue; + } fd = g_open(aml_file, O_WRONLY|O_TRUNC|O_CREAT, S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH); if (fd < 0) { diff --git a/tests/qtest/meson.build b/tests/qtest/meson.build index 47dabf91d0..fc14ae95a3 100644 --- a/tests/qtest/meson.build +++ b/tests/qtest/meson.build @@ -1,5 +1,6 @@ slow_qtests = { 'ahci-test' : 60, + 'aspeed_smc-test': 360, 'bios-tables-test' : 120, 'boot-serial-test' : 60, 'migration-test' : 150, diff --git a/tests/qtest/migration-test.c b/tests/qtest/migration-test.c index 5752412b64..0fbaa6a90f 100644 --- a/tests/qtest/migration-test.c +++ b/tests/qtest/migration-test.c @@ -3138,7 +3138,7 @@ static void test_migrate_dirty_limit(void) uint64_t throttle_us_per_full; /* * We want the test to be stable and as fast as possible. - * E.g., with 1Gb/s bandwith migration may pass without dirty limit, + * E.g., with 1Gb/s bandwidth migration may pass without dirty limit, * so we need to decrease a bandwidth. */ const int64_t dirtylimit_period = 1000, dirtylimit_value = 50; diff --git a/tests/qtest/netdev-socket.c b/tests/qtest/netdev-socket.c index 7ba1eff120..bb99d08b5e 100644 --- a/tests/qtest/netdev-socket.c +++ b/tests/qtest/netdev-socket.c @@ -18,6 +18,32 @@ #define CONNECTION_TIMEOUT 120 +static double connection_timeout(void) +{ + double load; + int ret = getloadavg(&load, 1); + + /* + * If we can't get load data, or load is low because we just started + * running, assume load of 1 (we are alone in this system). + */ + if (ret < 1 || load < 1.0) { + load = 1.0; + } + /* + * No one wants to wait more than 10 minutes for this test. Higher load? + * Too bad. + */ + if (load > 10.0) { + fprintf(stderr, "Warning: load %f higher than 10 - test might timeout\n", + load); + load = 10.0; + } + + /* if load is high increase timeout as we might not get a chance to run */ + return load * CONNECTION_TIMEOUT; +} + #define EXPECT_STATE(q, e, t) \ do { \ char *resp = NULL; \ @@ -31,7 +57,7 @@ do { \ if (g_str_equal(resp, e)) { \ break; \ } \ - } while (g_test_timer_elapsed() < CONNECTION_TIMEOUT); \ + } while (g_test_timer_elapsed() < connection_timeout()); \ g_assert_cmpstr(resp, ==, e); \ g_free(resp); \ } while (0) diff --git a/tests/qtest/test-filter-mirror.c b/tests/qtest/test-filter-mirror.c index adeada3eb8..f3865f7519 100644 --- a/tests/qtest/test-filter-mirror.c +++ b/tests/qtest/test-filter-mirror.c @@ -61,6 +61,7 @@ static void test_mirror(void) g_assert_cmpint(len, ==, sizeof(send_buf)); recv_buf = g_malloc(len); ret = recv(recv_sock[0], recv_buf, len, 0); + g_assert_cmpint(ret, ==, len); g_assert_cmpstr(recv_buf, ==, send_buf); g_free(recv_buf); diff --git a/tests/qtest/test-filter-redirector.c b/tests/qtest/test-filter-redirector.c index e72e3b7873..a77d5fd8ec 100644 --- a/tests/qtest/test-filter-redirector.c +++ b/tests/qtest/test-filter-redirector.c @@ -118,6 +118,7 @@ static void test_redirector_tx(void) g_assert_cmpint(len, ==, sizeof(send_buf)); recv_buf = g_malloc(len); ret = recv(recv_sock, recv_buf, len, 0); + g_assert_cmpint(ret, ==, len); g_assert_cmpstr(recv_buf, ==, send_buf); g_free(recv_buf); @@ -185,6 +186,7 @@ static void test_redirector_rx(void) g_assert_cmpint(len, ==, sizeof(send_buf)); recv_buf = g_malloc(len); ret = recv(backend_sock[0], recv_buf, len, 0); + g_assert_cmpint(ret, ==, len); g_assert_cmpstr(recv_buf, ==, send_buf); close(send_sock); diff --git a/tests/qtest/ufs-test.c b/tests/qtest/ufs-test.c index 5daf8c9c49..95e82f9472 100644 --- a/tests/qtest/ufs-test.c +++ b/tests/qtest/ufs-test.c @@ -319,7 +319,7 @@ static void ufs_init(QUfs *ufs, QGuestAllocator *alloc) ufs_wreg(ufs, A_IE, ie); ufs_wreg(ufs, A_UTRIACR, 0); - /* Enable tranfer request and task management request */ + /* Enable transfer request and task management request */ cap = ufs_rreg(ufs, A_CAP); nutrs = FIELD_EX32(cap, CAP, NUTRS) + 1; nutmrs = FIELD_EX32(cap, CAP, NUTMRS) + 1; diff --git a/tests/qtest/virtio-ccw-test.c b/tests/qtest/virtio-ccw-test.c index f4f5858b84..7a5357c212 100644 --- a/tests/qtest/virtio-ccw-test.c +++ b/tests/qtest/virtio-ccw-test.c @@ -85,7 +85,7 @@ int main(int argc, char **argv) if (qtest_has_device("virtio-rng-ccw")) { qtest_add_func("/virtio/rng/nop", virtio_rng_nop); } - if (qtest_has_device("virtio-rng-ccw")) { + if (qtest_has_device("virtio-scsi-ccw")) { qtest_add_func("/virtio/scsi/nop", virtio_scsi_nop); qtest_add_func("/virtio/scsi/hotplug", virtio_scsi_hotplug); } diff --git a/tests/qtest/virtio-net-test.c b/tests/qtest/virtio-net-test.c index fab5dd8b05..2df75c9780 100644 --- a/tests/qtest/virtio-net-test.c +++ b/tests/qtest/virtio-net-test.c @@ -91,6 +91,7 @@ static void tx_test(QVirtioDevice *dev, len = ntohl(len); ret = recv(socket, buffer, len, 0); + g_assert_cmpint(ret, ==, len); g_assert_cmpstr(buffer, ==, "TEST"); } diff --git a/tests/tcg/aarch64/Makefile.softmmu-target b/tests/tcg/aarch64/Makefile.softmmu-target index b74a2534e3..4b03ef602e 100644 --- a/tests/tcg/aarch64/Makefile.softmmu-target +++ b/tests/tcg/aarch64/Makefile.softmmu-target @@ -45,16 +45,22 @@ TESTS+=memory-sve # Running QEMU_BASE_MACHINE=-M virt -cpu max -display none -QEMU_OPTS+=$(QEMU_BASE_MACHINE) -semihosting-config enable=on,target=native,chardev=output -kernel +QEMU_BASE_ARGS=-semihosting-config enable=on,target=native,chardev=output +QEMU_OPTS+=$(QEMU_BASE_MACHINE) $(QEMU_BASE_ARGS) -kernel # console test is manual only -QEMU_SEMIHOST=-chardev stdio,mux=on,id=stdio0 -semihosting-config enable=on,chardev=stdio0 -mon chardev=stdio0,mode=readline -run-semiconsole: QEMU_OPTS=$(QEMU_BASE_MACHINE) $(QEMU_SEMIHOST) -kernel +QEMU_SEMIHOST=-serial none -chardev stdio,mux=on,id=stdio0 -semihosting-config enable=on,chardev=stdio0 -mon chardev=stdio0,mode=readline +run-semiconsole: QEMU_OPTS=$(QEMU_BASE_MACHINE) $(QEMU_SEMIHOST) -kernel run-semiconsole: semiconsole $(call skip-test, $<, "MANUAL ONLY") + $(if $(V),@printf " %-7s %s %s\n" "TO RUN" $(notdir $(QEMU)) "$(QEMU_OPTS) $<") run-plugin-semiconsole-with-%: semiconsole $(call skip-test, $<, "MANUAL ONLY") +# vtimer test needs EL2 +QEMU_EL2_MACHINE=-machine virt,virtualization=on,gic-version=2 -cpu cortex-a57 -smp 4 +run-vtimer: QEMU_OPTS=$(QEMU_EL2_MACHINE) $(QEMU_BASE_ARGS) -kernel + # Simple Record/Replay Test .PHONY: memory-record run-memory-record: memory-record memory diff --git a/tests/tcg/aarch64/system/vtimer.c b/tests/tcg/aarch64/system/vtimer.c new file mode 100644 index 0000000000..42f2f7796c --- /dev/null +++ b/tests/tcg/aarch64/system/vtimer.c @@ -0,0 +1,48 @@ +/* + * Simple Virtual Timer Test + * + * Copyright (c) 2020 Linaro Ltd + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +#include +#include + +/* grabbed from Linux */ +#define __stringify_1(x...) #x +#define __stringify(x...) __stringify_1(x) + +#define read_sysreg(r) ({ \ + uint64_t __val; \ + asm volatile("mrs %0, " __stringify(r) : "=r" (__val)); \ + __val; \ +}) + +#define write_sysreg(r, v) do { \ + uint64_t __val = (uint64_t)(v); \ + asm volatile("msr " __stringify(r) ", %x0" \ + : : "rZ" (__val)); \ +} while (0) + +int main(void) +{ + int i; + + ml_printf("VTimer Test\n"); + + write_sysreg(cntvoff_el2, 1); + write_sysreg(cntv_cval_el0, -1); + write_sysreg(cntv_ctl_el0, 1); + + ml_printf("cntvoff_el2=%lx\n", read_sysreg(cntvoff_el2)); + ml_printf("cntv_cval_el0=%lx\n", read_sysreg(cntv_cval_el0)); + ml_printf("cntv_ctl_el0=%lx\n", read_sysreg(cntv_ctl_el0)); + + /* Now read cval a few times */ + for (i = 0; i < 10; i++) { + ml_printf("%d: cntv_cval_el0=%lx\n", i, read_sysreg(cntv_cval_el0)); + } + + return 0; +} diff --git a/tests/tcg/arm/Makefile.softmmu-target b/tests/tcg/arm/Makefile.softmmu-target index 8b546e2aa3..4c9264057f 100644 --- a/tests/tcg/arm/Makefile.softmmu-target +++ b/tests/tcg/arm/Makefile.softmmu-target @@ -3,26 +3,78 @@ # ARM SoftMMU tests - included from tests/tcg/Makefile # -ARM_SRC=$(SRC_PATH)/tests/tcg/arm +ARM_SRC=$(SRC_PATH)/tests/tcg/arm/system # Set search path for all sources VPATH += $(ARM_SRC) -ARM_TESTS=test-armv6m-undef - -TESTS += $(ARM_TESTS) - -CFLAGS+=-Wl,--build-id=none -x assembler-with-cpp -LDFLAGS+=-nostdlib -N -static - -%: %.S %.ld - $(CC) $(CFLAGS) $(ASFLAGS) $(EXTRA_CFLAGS) $< -o $@ $(LDFLAGS) -T $(ARM_SRC)/$@.ld - # Specific Test Rules -test-armv6m-undef: EXTRA_CFLAGS+=-mcpu=cortex-m0 -mfloat-abi=soft +test-armv6m-undef: test-armv6m-undef.S + $(CC) -mcpu=cortex-m0 -mfloat-abi=soft \ + -Wl,--build-id=none -x assembler-with-cpp \ + $< -o $@ -nostdlib -N -static \ + -T $(ARM_SRC)/$@.ld run-test-armv6m-undef: QEMU_OPTS+=-semihosting -M microbit -kernel -# We don't currently support the multiarch system tests -undefine MULTIARCH_TESTS +ARM_TESTS+=test-armv6m-undef + +# These objects provide the basic boot code and helper functions for all tests +CRT_OBJS=boot.o + +ARM_TEST_SRCS=$(wildcard $(ARM_SRC)/*.c) +ARM_TESTS+=$(patsubst $(ARM_SRC)/%.c, %, $(ARM_TEST_SRCS)) + +CRT_PATH=$(ARM_SRC) +LINK_SCRIPT=$(ARM_SRC)/kernel.ld +LDFLAGS=-Wl,-T$(LINK_SCRIPT) +CFLAGS+=-nostdlib -ggdb -O0 $(MINILIB_INC) +LDFLAGS+=-static -nostdlib -N $(CRT_OBJS) $(MINILIB_OBJS) -lgcc + +# building head blobs +.PRECIOUS: $(CRT_OBJS) + +%.o: $(ARM_SRC)/%.S + $(CC) $(CFLAGS) $(EXTRA_CFLAGS) -x assembler-with-cpp -c $< -o $@ + +# Build and link the tests +%: %.c $(LINK_SCRIPT) $(CRT_OBJS) $(MINILIB_OBJS) + $(CC) $(CFLAGS) $(EXTRA_CFLAGS) $< -o $@ $(LDFLAGS) + +memory: CFLAGS+=-DCHECK_UNALIGNED=0 + +# Running +QEMU_BASE_MACHINE=-M virt -cpu max -display none +QEMU_OPTS+=$(QEMU_BASE_MACHINE) -semihosting-config enable=on,target=native,chardev=output -kernel + +# console test is manual only +QEMU_SEMIHOST=-serial none -chardev stdio,mux=on,id=stdio0 -semihosting-config enable=on,chardev=stdio0 -mon chardev=stdio0,mode=readline +run-semiconsole: QEMU_OPTS=$(QEMU_BASE_MACHINE) $(QEMU_SEMIHOST) -kernel +run-semiconsole: semiconsole + $(call skip-test, $<, "MANUAL ONLY") + $(if $(V),@printf " %-7s %s %s\n" "TO RUN" $(notdir $(QEMU)) "$(QEMU_OPTS) $<") +run-plugin-semiconsole-with-%: semiconsole + $(call skip-test, $<, "MANUAL ONLY") + +# Simple Record/Replay Test +.PHONY: memory-record +run-memory-record: memory-record memory + $(call run-test, $<, \ + $(QEMU) -monitor none -display none \ + -chardev file$(COMMA)path=$<.out$(COMMA)id=output \ + -icount shift=5$(COMMA)rr=record$(COMMA)rrfile=record.bin \ + $(QEMU_OPTS) memory) + +.PHONY: memory-replay +run-memory-replay: memory-replay run-memory-record + $(call run-test, $<, \ + $(QEMU) -monitor none -display none \ + -chardev file$(COMMA)path=$<.out$(COMMA)id=output \ + -icount shift=5$(COMMA)rr=replay$(COMMA)rrfile=record.bin \ + $(QEMU_OPTS) memory) + +EXTRA_RUNS+=run-memory-replay + +TESTS += $(ARM_TESTS) $(MULTIARCH_TESTS) +EXTRA_RUNS+=$(MULTIARCH_RUNS) diff --git a/tests/tcg/arm/system/boot.S b/tests/tcg/arm/system/boot.S new file mode 100644 index 0000000000..7d43372c66 --- /dev/null +++ b/tests/tcg/arm/system/boot.S @@ -0,0 +1,319 @@ +/* + * Minimal ArmV7 system boot code. + * + * Using semihosting for serial output and exit functions. + */ + +/* + * Semihosting interface on ARM AArch32 + * R0 - semihosting call number + * R1 - semihosting parameter + */ +#define semihosting_call svc 0x123456 +#define SYS_WRITEC 0x03 /* character to debug channel */ +#define SYS_WRITE0 0x04 /* string to debug channel */ +#define SYS_EXIT 0x18 + +#define ADP_Stopped_ApplicationExit 0x20026 +#define ADP_Stopped_InternalError 0x20024 + +/* + * Helper macro for annotating functions with elf type and size. + */ +.macro endf name + .global \name + .type \name, %function + .size \name, . - \name +.endm + + .section .interrupt_vector, "ax" + .align 5 + +vector_table: + b reset /* reset vector */ + b undef_instr /* undefined instruction vector */ + b software_intr /* software interrupt vector */ + b prefetch_abort /* prefetch abort vector */ + b data_abort /* data abort vector */ + nop /* reserved */ + b IRQ_handler /* IRQ vector */ + b FIQ_handler /* FIQ vector */ + +endf vector_table + + .text +__start: + ldr r0, =vector_table + mcr p15, 0, r0, c12, c0, 0 /* Set up VBAR */ + + ldr sp, =stack_end /* Set up the stack */ + bl mmu_setup /* Set up the MMU */ + bl main /* Jump to main */ + +endf __start + +_exit: + cmp r0, #0 + ite EQ // if-then-else. "EQ" is for if equal, else otherwise + ldreq r1, =ADP_Stopped_ApplicationExit // if r0 == 0 + ldrne r1, =ADP_Stopped_InternalError // else + mov r0, #SYS_EXIT + semihosting_call + +endf _exit + +/* + * Helper Functions + */ + +mmu_setup: + /* + * The MMU setup for this is very simple using two stage one + * translations. The first 1Mb section points to the text + * section and the second points to the data and rss. + * Currently the fattest test only needs ~50k for that so we + * have plenty of space. + * + * The short descriptor Section format is as follows: + * + * PA[31:20] - Section Base Address + * NS[19] - Non-secure bit + * 0[18] - Section (1 for Super Section) + * nG[17] - Not global bit + * S[16] - Shareable + * TEX[14:12] - Memory Region Attributes + * AP[15, 11:10] - Access Permission Bits + * IMPDEF[9] + * Domain[8:5] + * XN[4] - Execute never bit + * C[3] - Memory Region Attributes + * B[2] - Memory Region Attributes + * 1[1] + * PXN[0] - Privileged Execute Never + * + * r0 - point at the table + * r1 - address + * r2 - entry + * r3 - common section bits + * r4 - scratch + */ + + /* + * Memory Region Bits + * + * TEX[14:12] = 000 + * C[3] = 1 + * B[2] = 1 + * + * Outer and Inner WB, no write allocate + */ + mov r3, #0 + ldr r4, =(3 << 2) + orr r3, r4, r4 + + /* Section bit */ + orr r3, r3, #2 + + /* Page table setup (identity mapping). */ + ldr r0, =ttb + + /* First block: .text/RO/execute enabled */ + ldr r1, =.text + ldr r2, =0xFFF00000 /* 1MB block alignment */ + and r2, r1, r2 + orr r2, r2, r3 /* common bits */ + orr r2, r2, #(1 << 15) /* AP[2] = 1 */ + orr r2, r2, #(1 << 10) /* AP[0] = 1 => RO @ PL1 */ + + lsr r4, r2, #(20 - 2) + str r2, [r0, r4, lsl #0] /* write entry */ + + /* Second block: .data/RW/no execute */ + ldr r1, =.data + ldr r2, =0xFFF00000 /* 1MB block alignment */ + and r2, r1, r2 + orr r2, r2, r3 /* common bits */ + orr r2, r2, #(1 << 10) /* AP[0] = 1 => RW @ PL1 */ + orr r2, r2, #(1 << 4) /* XN[4] => no execute */ + + lsr r4, r2, #(20 - 2) + str r2, [r0, r4, lsl #0] /* write entry */ + + /* + * DACR - Domain Control + * + * Enable client mode for domain 0 (we don't use any others) + */ + ldr r0, =0x1 + mcr p15, 0, r0, c3, c0, 0 + + /* + * TTCBR - Translation Table Base Control Register + * + * EAE[31] = 0, 32-bit translation, short descriptor format + * N[2:0] = 5 ( TTBRO uses 31:14-5 => 9 bit lookup stage ) + */ + ldr r0, =0x5 + mcr p15, 0, r0, c1, c0, 2 + + /* + * TTBR0 -Translation Table Base Register 0 + * + * [31:9] = Base address of table + * + * QEMU doesn't really care about the cache sharing + * attributes so we don't need to either. + */ + ldr r0, =ttb + mcr p15, 0, r0, c2, c0, 0 + + /* + * SCTLR- System Control Register + * + * TE[30] = 0, exceptions to A32 state + * AFE[29] = 0, AP[0] is the access permissions bit + * EE[25] = 0, Little-endian + * WXN[19] = 0 = no effect, Write does not imply XN (execute never) + * I[12] = Instruction cachability control + * C[2] = Data cachability control + * M[0] = 1, enable stage 1 address translation for EL0/1 + * + * At this point virtual memory is enabled. + */ + ldr r0, =0x1005 + mcr p15, 0, r0, c1, c0, 0 + + isb + + mov pc, lr /* done, return to caller */ + +endf mmu_setup + +/* Output a single character to serial port */ +__sys_outc: + STMFD sp!, {r0-r1} // push r0, r1 onto stack + mov r1, sp + mov r0, #SYS_WRITEC + semihosting_call + LDMFD sp!, {r0-r1} // pop r0, r1 from stack + bx lr + +endf __sys_outc + +reset: + ldr r1, =reset_error + b exception_handler + +endf reset + +undef_instr: + ldr r1, =undef_intr_error + b exception_handler + +endf undef_instr + +software_intr: + ldr r1, =software_intr_error + b exception_handler + +endf software_intr + +prefetch_abort: + ldr r1, =prefetch_abort_error + b exception_handler + +endf prefetch_abort + +data_abort: + ldr r1, =data_abort_error + b exception_handler + +endf data_abort + +IRQ_handler: + ldr r1, =irq_error + b exception_handler + +endf IRQ_handler + +FIQ_handler: + ldr r1, =fiq_error + b exception_handler + +endf FIQ_handler + +/* + * Initiate a exit semihosting call whenever there is any exception + * r1 already holds the string. + */ +exception_handler: + mov r0, #SYS_WRITE0 + semihosting_call + mov r0, #SYS_EXIT + mov r1, #1 + semihosting_call + +endf exception_handler + +/* + * We implement a stub raise() function which errors out as tests + * shouldn't trigger maths errors. + */ + .global raise +raise: + mov r0, #SYS_WRITE0 + ldr r1, =maths_error + semihosting_call + mov r0, #SYS_EXIT + ldr r1, =ADP_Stopped_InternalError + semihosting_call + +endf raise + + .data + +.data + +reset_error: + .ascii "Reset exception occurred.\n\0" + +undef_intr_error: + .ascii "Undefined Instruction Exception Occurred.\n\0" + +software_intr_error: + .ascii "Software Interrupt Occurred.\n\0" + +prefetch_abort_error: + .ascii "Prefetch Abort Occurred.\n\0" + +data_abort_error: + .ascii "Data Abort Occurred.\n\0" + +irq_error: + .ascii "IRQ exception occurred.\n\0" + +fiq_error: + .ascii "FIQ exception occurred.\n\0" + +maths_error: + .ascii "Software maths exception.\n\0" + + + /* + * 1st Stage Translation table + * 4096 entries, indexed by [31:20] + * each entry covers 1Mb of address space + * aligned on 16kb + */ + .align 15 +ttb: + .space (4096 * 4), 0 + + .align 12 + + /* Space for stack */ + .align 5 + .section .bss +stack: + .space 65536, 0 +stack_end: diff --git a/tests/tcg/arm/system/kernel.ld b/tests/tcg/arm/system/kernel.ld new file mode 100644 index 0000000000..7b3a76dcbf --- /dev/null +++ b/tests/tcg/arm/system/kernel.ld @@ -0,0 +1,24 @@ +ENTRY(__start) + +SECTIONS +{ + /* virt machine, RAM starts at 1gb */ + . = (1 << 30); + .text : { + *(.text) + } + .rodata : { + *(.rodata) + } + /* align r/w section to next 2mb */ + . = ALIGN(1 << 21); + .data : { + *(.data) + } + .bss : { + *(.bss) + } + /DISCARD/ : { + *(.ARM.attributes) + } +} diff --git a/tests/tcg/arm/system/semiconsole.c b/tests/tcg/arm/system/semiconsole.c new file mode 100644 index 0000000000..206dd60eed --- /dev/null +++ b/tests/tcg/arm/system/semiconsole.c @@ -0,0 +1,42 @@ +/* + * Semihosting Console Test + * + * Copyright (c) 2019 Linaro Ltd + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +#include +#include + +#define SYS_READC 0x7 + +uintptr_t __semi_call(uintptr_t type, uintptr_t arg0) +{ + register uintptr_t t asm("r0") = type; + register uintptr_t a0 asm("r1") = arg0; +#ifdef __thumb__ +# define SVC "svc 0xab" +#else +# define SVC "svc 0x123456" +#endif + asm(SVC : "=r" (t) + : "r" (t), "r" (a0)); + + return t; +} + +int main(void) +{ + char c; + + ml_printf("Semihosting Console Test\n"); + ml_printf("hit X to exit:"); + + do { + c = __semi_call(SYS_READC, 0); + __sys_outc(c); + } while (c != 'X'); + + return 0; +} diff --git a/tests/tcg/arm/test-armv6m-undef.S b/tests/tcg/arm/system/test-armv6m-undef.S similarity index 100% rename from tests/tcg/arm/test-armv6m-undef.S rename to tests/tcg/arm/system/test-armv6m-undef.S diff --git a/tests/tcg/arm/test-armv6m-undef.ld b/tests/tcg/arm/system/test-armv6m-undef.ld similarity index 100% rename from tests/tcg/arm/test-armv6m-undef.ld rename to tests/tcg/arm/system/test-armv6m-undef.ld diff --git a/tests/tcg/multiarch/gdbstub/registers.py b/tests/tcg/multiarch/gdbstub/registers.py index ff6076b09e..688c061107 100644 --- a/tests/tcg/multiarch/gdbstub/registers.py +++ b/tests/tcg/multiarch/gdbstub/registers.py @@ -44,7 +44,6 @@ def fetch_xml_regmap(): total_regs = 0 reg_map = {} - frame = gdb.selected_frame() tree = ET.fromstring(xml) for f in tree.findall("feature"): @@ -61,12 +60,8 @@ def fetch_xml_regmap(): for r in regs: name = r.attrib["name"] regnum = int(r.attrib["regnum"]) - try: - value = frame.read_register(name) - except ValueError: - report(False, f"failed to read reg: {name}") - entry = { "name": name, "initial": value, "regnum": regnum } + entry = { "name": name, "regnum": regnum } if name in reg_map: report(False, f"duplicate register {entry} vs {reg_map[name]}") @@ -80,6 +75,15 @@ def fetch_xml_regmap(): return reg_map +def get_register_by_regnum(reg_map, regnum): + """ + Helper to find a register from the map via its XML regnum + """ + for regname, entry in reg_map.items(): + if entry['regnum'] == regnum: + return entry + return None + def crosscheck_remote_xml(reg_map): """ Cross-check the list of remote-registers with the XML info. @@ -90,8 +94,11 @@ def crosscheck_remote_xml(reg_map): total_regs = len(reg_map.keys()) total_r_regs = 0 + total_r_elided_regs = 0 for r in r_regs: + r = r.replace("long long", "long_long") + r = r.replace("long double", "long_double") fields = r.split() # Some of the registers reported here are "pseudo" registers that # gdb invents based on actual registers so we need to filter them @@ -100,6 +107,15 @@ def crosscheck_remote_xml(reg_map): r_name = fields[0] r_regnum = int(fields[6]) + # Some registers are "hidden" so don't have a name + # although they still should have a register number + if r_name == "''": + total_r_elided_regs += 1 + x_reg = get_register_by_regnum(reg_map, r_regnum) + if x_reg is not None: + x_reg["hidden"] = True + continue + # check in the XML try: x_reg = reg_map[r_name] @@ -114,17 +130,42 @@ def crosscheck_remote_xml(reg_map): else: total_r_regs += 1 - # Just print a mismatch in totals as gdb will filter out 64 bit - # registers on a 32 bit machine. Also print what is missing to - # help with debug. - if total_regs != total_r_regs: - print(f"xml-tdesc has ({total_regs}) registers") - print(f"remote-registers has ({total_r_regs}) registers") + report(total_regs == total_r_regs + total_r_elided_regs, + "All XML Registers accounted for") + + print(f"xml-tdesc has {total_regs} registers") + print(f"remote-registers has {total_r_regs} registers") + print(f"of which {total_r_elided_regs} are hidden") + + for x_key in reg_map.keys(): + x_reg = reg_map[x_key] + if "hidden" in x_reg: + print(f"{x_reg} elided by gdb") + elif "seen" not in x_reg: + print(f"{x_reg} wasn't seen in remote-registers") + +def initial_register_read(reg_map): + """ + Do an initial read of all registers that we know gdb cares about + (so ignore the elided ones). + """ + frame = gdb.selected_frame() + + for e in reg_map.values(): + name = e["name"] + regnum = e["regnum"] + + try: + if "hidden" in e: + value = frame.read_register(regnum) + e["initial"] = value + elif "seen" in e: + value = frame.read_register(name) + e["initial"] = value + + except ValueError: + report(False, f"failed to read reg: {name}") - for x_key in reg_map.keys(): - x_reg = reg_map[x_key] - if "seen" not in x_reg: - print(f"{x_reg} wasn't seen in remote-registers") def complete_and_diff(reg_map): """ @@ -144,18 +185,19 @@ def complete_and_diff(reg_map): changed = 0 for e in reg_map.values(): - name = e["name"] - old_val = e["initial"] + if "initial" in e and "hidden" not in e: + name = e["name"] + old_val = e["initial"] - try: - new_val = frame.read_register(name) - except: - report(False, f"failed to read {name} at end of run") - continue + try: + new_val = frame.read_register(name) + except ValueError: + report(False, f"failed to read {name} at end of run") + continue - if new_val != old_val: - print(f"{name} changes from {old_val} to {new_val}") - changed += 1 + if new_val != old_val: + print(f"{name} changes from {old_val} to {new_val}") + changed += 1 # as long as something changed we can be confident its working report(changed > 0, f"{changed} registers were changed") @@ -168,6 +210,7 @@ def run_test(): if reg_map is not None: crosscheck_remote_xml(reg_map) + initial_register_read(reg_map) complete_and_diff(reg_map) diff --git a/tests/tcg/ppc64/Makefile.target b/tests/tcg/ppc64/Makefile.target index 1d08076756..8c3e4e4038 100644 --- a/tests/tcg/ppc64/Makefile.target +++ b/tests/tcg/ppc64/Makefile.target @@ -16,6 +16,11 @@ PPC64_TESTS=bcdsub non_signalling_xscv endif $(PPC64_TESTS): CFLAGS += -mpower8-vector +ifneq ($(CROSS_CC_HAS_POWER8_VECTOR),) +PPC64_TESTS += vsx_f2i_nan +endif +vsx_f2i_nan: CFLAGS += -mpower8-vector -I$(SRC_PATH)/include + PPC64_TESTS += mtfsf PPC64_TESTS += mffsce @@ -38,11 +43,4 @@ PPC64_TESTS += signal_save_restore_xer PPC64_TESTS += xxspltw PPC64_TESTS += test-aes -ifneq ($(GDB),) -# Skip for now until vsx registers sorted out -run-gdbstub-registers: - $(call skip-test, $<, "BROKEN reading VSX registers") -endif - - TESTS += $(PPC64_TESTS) diff --git a/tests/tcg/ppc64/vsx_f2i_nan.c b/tests/tcg/ppc64/vsx_f2i_nan.c new file mode 100644 index 0000000000..94b1a4eb02 --- /dev/null +++ b/tests/tcg/ppc64/vsx_f2i_nan.c @@ -0,0 +1,300 @@ +#include +#include "qemu/compiler.h" + +typedef vector float vsx_float32_vec_t; +typedef vector double vsx_float64_vec_t; +typedef vector signed int vsx_int32_vec_t; +typedef vector unsigned int vsx_uint32_vec_t; +typedef vector signed long long vsx_int64_vec_t; +typedef vector unsigned long long vsx_uint64_vec_t; + +#define DEFINE_VSX_F2I_FUNC(SRC_T, DEST_T, INSN) \ +static inline vsx_##DEST_T##_vec_t \ + vsx_convert_##SRC_T##_vec_to_##DEST_T##_vec(vsx_##SRC_T##_vec_t v) \ +{ \ + vsx_##DEST_T##_vec_t result; \ + asm(#INSN " %x0, %x1" : "=wa" (result) : "wa" (v)); \ + return result; \ +} + +DEFINE_VSX_F2I_FUNC(float32, int32, xvcvspsxws) +DEFINE_VSX_F2I_FUNC(float32, uint32, xvcvspuxws) +DEFINE_VSX_F2I_FUNC(float32, int64, xvcvspsxds) +DEFINE_VSX_F2I_FUNC(float32, uint64, xvcvspuxds) +DEFINE_VSX_F2I_FUNC(float64, int32, xvcvdpsxws) +DEFINE_VSX_F2I_FUNC(float64, uint32, xvcvdpuxws) +DEFINE_VSX_F2I_FUNC(float64, int64, xvcvdpsxds) +DEFINE_VSX_F2I_FUNC(float64, uint64, xvcvdpuxds) + +static inline vsx_float32_vec_t vsx_float32_is_nan(vsx_float32_vec_t v) +{ + vsx_float32_vec_t abs_v; + vsx_float32_vec_t result_mask; + const vsx_uint32_vec_t f32_pos_inf_bits = {0x7F800000U, 0x7F800000U, + 0x7F800000U, 0x7F800000U}; + + asm("xvabssp %x0, %x1" : "=wa" (abs_v) : "wa" (v)); + asm("vcmpgtuw %0, %1, %2" + : "=v" (result_mask) + : "v" (abs_v), "v" (f32_pos_inf_bits)); + return result_mask; +} + +static inline vsx_float64_vec_t vsx_float64_is_nan(vsx_float64_vec_t v) +{ + vsx_float64_vec_t abs_v; + vsx_float64_vec_t result_mask; + const vsx_uint64_vec_t f64_pos_inf_bits = {0x7FF0000000000000ULL, + 0x7FF0000000000000ULL}; + + asm("xvabsdp %x0, %x1" : "=wa" (abs_v) : "wa" (v)); + asm("vcmpgtud %0, %1, %2" + : "=v" (result_mask) + : "v" (abs_v), "v" (f64_pos_inf_bits)); + return result_mask; +} + +#define DEFINE_VSX_BINARY_LOGICAL_OP_INSN(LANE_TYPE, OP_NAME, OP_INSN) \ +static inline vsx_##LANE_TYPE##_vec_t vsx_##LANE_TYPE##_##OP_NAME( \ + vsx_##LANE_TYPE##_vec_t a, vsx_##LANE_TYPE##_vec_t b) \ +{ \ + vsx_##LANE_TYPE##_vec_t result; \ + asm(#OP_INSN " %x0, %x1, %x2" : "=wa" (result) : "wa" (a), "wa" (b)); \ + return result; \ +} + +DEFINE_VSX_BINARY_LOGICAL_OP_INSN(float32, logical_and, xxland) +DEFINE_VSX_BINARY_LOGICAL_OP_INSN(float64, logical_and, xxland) +DEFINE_VSX_BINARY_LOGICAL_OP_INSN(int32, logical_and, xxland) +DEFINE_VSX_BINARY_LOGICAL_OP_INSN(uint32, logical_and, xxland) +DEFINE_VSX_BINARY_LOGICAL_OP_INSN(int64, logical_and, xxland) +DEFINE_VSX_BINARY_LOGICAL_OP_INSN(uint64, logical_and, xxland) + +DEFINE_VSX_BINARY_LOGICAL_OP_INSN(float32, logical_andc, xxlandc) +DEFINE_VSX_BINARY_LOGICAL_OP_INSN(float64, logical_andc, xxlandc) + +DEFINE_VSX_BINARY_LOGICAL_OP_INSN(float32, logical_or, xxlor) +DEFINE_VSX_BINARY_LOGICAL_OP_INSN(float64, logical_or, xxlor) +DEFINE_VSX_BINARY_LOGICAL_OP_INSN(int32, logical_or, xxlor) +DEFINE_VSX_BINARY_LOGICAL_OP_INSN(uint32, logical_or, xxlor) +DEFINE_VSX_BINARY_LOGICAL_OP_INSN(int64, logical_or, xxlor) +DEFINE_VSX_BINARY_LOGICAL_OP_INSN(uint64, logical_or, xxlor) + +static inline vsx_int32_vec_t vsx_mask_out_float32_vec_to_int32_vec( + vsx_int32_vec_t v) +{ + return v; +} +static inline vsx_uint32_vec_t vsx_mask_out_float32_vec_to_uint32_vec( + vsx_uint32_vec_t v) +{ + return v; +} +static inline vsx_int64_vec_t vsx_mask_out_float32_vec_to_int64_vec( + vsx_int64_vec_t v) +{ + return v; +} +static inline vsx_uint64_vec_t vsx_mask_out_float32_vec_to_uint64_vec( + vsx_uint64_vec_t v) +{ + return v; +} + +static inline vsx_int32_vec_t vsx_mask_out_float64_vec_to_int32_vec( + vsx_int32_vec_t v) +{ +#if HOST_BIG_ENDIAN + const vsx_int32_vec_t valid_lanes_mask = {-1, 0, -1, 0}; +#else + const vsx_int32_vec_t valid_lanes_mask = {0, -1, 0, -1}; +#endif + + return vsx_int32_logical_and(v, valid_lanes_mask); +} + +static inline vsx_uint32_vec_t vsx_mask_out_float64_vec_to_uint32_vec( + vsx_uint32_vec_t v) +{ + return (vsx_uint32_vec_t)vsx_mask_out_float64_vec_to_int32_vec( + (vsx_int32_vec_t)v); +} + +static inline vsx_int64_vec_t vsx_mask_out_float64_vec_to_int64_vec( + vsx_int64_vec_t v) +{ + return v; +} +static inline vsx_uint64_vec_t vsx_mask_out_float64_vec_to_uint64_vec( + vsx_uint64_vec_t v) +{ + return v; +} + +static inline void print_vsx_float32_vec_elements(FILE *stream, + vsx_float32_vec_t vec) +{ + fprintf(stream, "%g, %g, %g, %g", (double)vec[0], (double)vec[1], + (double)vec[2], (double)vec[3]); +} + +static inline void print_vsx_float64_vec_elements(FILE *stream, + vsx_float64_vec_t vec) +{ + fprintf(stream, "%.17g, %.17g", vec[0], vec[1]); +} + +static inline void print_vsx_int32_vec_elements(FILE *stream, + vsx_int32_vec_t vec) +{ + fprintf(stream, "%d, %d, %d, %d", vec[0], vec[1], vec[2], vec[3]); +} + +static inline void print_vsx_uint32_vec_elements(FILE *stream, + vsx_uint32_vec_t vec) +{ + fprintf(stream, "%u, %u, %u, %u", vec[0], vec[1], vec[2], vec[3]); +} + +static inline void print_vsx_int64_vec_elements(FILE *stream, + vsx_int64_vec_t vec) +{ + fprintf(stream, "%lld, %lld", vec[0], vec[1]); +} + +static inline void print_vsx_uint64_vec_elements(FILE *stream, + vsx_uint64_vec_t vec) +{ + fprintf(stream, "%llu, %llu", vec[0], vec[1]); +} + +#define DEFINE_VSX_ALL_EQ_FUNC(LANE_TYPE, CMP_INSN) \ +static inline int vsx_##LANE_TYPE##_all_eq(vsx_##LANE_TYPE##_vec_t a, \ + vsx_##LANE_TYPE##_vec_t b) \ +{ \ + unsigned result; \ + vsx_##LANE_TYPE##_vec_t is_eq_mask_vec; \ + asm(#CMP_INSN ". %0, %2, %3\n\t" \ + "mfocrf %1, 2" \ + : "=v" (is_eq_mask_vec), "=r" (result) \ + : "v" (a), "v" (b) \ + : "cr6"); \ + return (int)((result >> 7) & 1u); \ +} + +DEFINE_VSX_ALL_EQ_FUNC(int32, vcmpequw) +DEFINE_VSX_ALL_EQ_FUNC(uint32, vcmpequw) +DEFINE_VSX_ALL_EQ_FUNC(int64, vcmpequd) +DEFINE_VSX_ALL_EQ_FUNC(uint64, vcmpequd) + +#define DEFINE_VSX_F2I_TEST_FUNC(SRC_T, DEST_T) \ +static inline int test_vsx_conv_##SRC_T##_vec_to_##DEST_T##_vec( \ + vsx_##SRC_T##_vec_t src_v) \ +{ \ + const vsx_##SRC_T##_vec_t is_nan_mask = vsx_##SRC_T##_is_nan(src_v); \ + const vsx_##SRC_T##_vec_t nan_src_v = \ + vsx_##SRC_T##_logical_and(src_v, is_nan_mask); \ + const vsx_##SRC_T##_vec_t non_nan_src_v = \ + vsx_##SRC_T##_logical_andc(src_v, is_nan_mask); \ + \ + const vsx_##DEST_T##_vec_t expected_result = \ + vsx_mask_out_##SRC_T##_vec_to_##DEST_T##_vec( \ + vsx_##DEST_T##_logical_or( \ + vsx_convert_##SRC_T##_vec_to_##DEST_T##_vec(nan_src_v), \ + vsx_convert_##SRC_T##_vec_to_##DEST_T##_vec( \ + non_nan_src_v))); \ + const vsx_##DEST_T##_vec_t actual_result = \ + vsx_mask_out_##SRC_T##_vec_to_##DEST_T##_vec( \ + vsx_convert_##SRC_T##_vec_to_##DEST_T##_vec(src_v)); \ + const int test_result = \ + vsx_##DEST_T##_all_eq(expected_result, actual_result); \ + \ + if (unlikely(test_result == 0)) { \ + fputs("FAIL: Conversion of " #SRC_T " vector to " #DEST_T \ + " vector failed\n", stdout); \ + fputs("Source values: ", stdout); \ + print_vsx_##SRC_T##_vec_elements(stdout, src_v); \ + fputs("\nExpected result: ", stdout); \ + print_vsx_##DEST_T##_vec_elements(stdout, expected_result); \ + fputs("\nActual result: ", stdout); \ + print_vsx_##DEST_T##_vec_elements(stdout, actual_result); \ + fputs("\n\n", stdout); \ + } \ + \ + return test_result; \ +} + + +DEFINE_VSX_F2I_TEST_FUNC(float32, int32) +DEFINE_VSX_F2I_TEST_FUNC(float32, uint32) +DEFINE_VSX_F2I_TEST_FUNC(float32, int64) +DEFINE_VSX_F2I_TEST_FUNC(float32, uint64) +DEFINE_VSX_F2I_TEST_FUNC(float64, int32) +DEFINE_VSX_F2I_TEST_FUNC(float64, uint32) +DEFINE_VSX_F2I_TEST_FUNC(float64, int64) +DEFINE_VSX_F2I_TEST_FUNC(float64, uint64) + +static inline vsx_int32_vec_t vsx_int32_vec_from_mask(int mask) +{ + const vsx_int32_vec_t bits_to_test = {1, 2, 4, 8}; + const vsx_int32_vec_t vec_mask = {mask, mask, mask, mask}; + vsx_int32_vec_t result; + + asm("vcmpequw %0, %1, %2" + : "=v" (result) + : "v" (vsx_int32_logical_and(vec_mask, bits_to_test)), + "v" (bits_to_test)); + return result; +} + +static inline vsx_int64_vec_t vsx_int64_vec_from_mask(int mask) +{ + const vsx_int64_vec_t bits_to_test = {1, 2}; + const vsx_int64_vec_t vec_mask = {mask, mask}; + vsx_int64_vec_t result; + + asm("vcmpequd %0, %1, %2" + : "=v" (result) + : "v" (vsx_int64_logical_and(vec_mask, bits_to_test)), + "v" (bits_to_test)); + return result; +} + +int main(void) +{ + const vsx_float32_vec_t f32_iota1 = {1.0f, 2.0f, 3.0f, 4.0f}; + const vsx_float64_vec_t f64_iota1 = {1.0, 2.0}; + + int num_of_tests_failed = 0; + + for (int i = 0; i < 16; i++) { + const vsx_int32_vec_t nan_mask = vsx_int32_vec_from_mask(i); + const vsx_float32_vec_t f32_v = + vsx_float32_logical_or(f32_iota1, (vsx_float32_vec_t)nan_mask); + num_of_tests_failed += + (int)(!test_vsx_conv_float32_vec_to_int32_vec(f32_v)); + num_of_tests_failed += + (int)(!test_vsx_conv_float32_vec_to_int64_vec(f32_v)); + num_of_tests_failed += + (int)(!test_vsx_conv_float32_vec_to_uint32_vec(f32_v)); + num_of_tests_failed += + (int)(!test_vsx_conv_float32_vec_to_uint64_vec(f32_v)); + } + + for (int i = 0; i < 4; i++) { + const vsx_int64_vec_t nan_mask = vsx_int64_vec_from_mask(i); + const vsx_float64_vec_t f64_v = + vsx_float64_logical_or(f64_iota1, (vsx_float64_vec_t)nan_mask); + num_of_tests_failed += + (int)(!test_vsx_conv_float64_vec_to_int32_vec(f64_v)); + num_of_tests_failed += + (int)(!test_vsx_conv_float64_vec_to_int64_vec(f64_v)); + num_of_tests_failed += + (int)(!test_vsx_conv_float64_vec_to_uint32_vec(f64_v)); + num_of_tests_failed += + (int)(!test_vsx_conv_float64_vec_to_uint64_vec(f64_v)); + } + + printf("%d tests failed\n", num_of_tests_failed); + return (int)(num_of_tests_failed != 0); +} diff --git a/tests/tcg/s390x/Makefile.target b/tests/tcg/s390x/Makefile.target index 46544fecd4..0e670f3f8b 100644 --- a/tests/tcg/s390x/Makefile.target +++ b/tests/tcg/s390x/Makefile.target @@ -103,10 +103,6 @@ run-gdbstub-svc: hello-s390x-asm --bin $< --test $(S390X_SRC)/gdbstub/test-svc.py, \ single-stepping svc) -# Skip for now until vx registers sorted out -run-gdbstub-registers: - $(call skip-test, $<, "BROKEN reading VX registers") - EXTRA_RUNS += run-gdbstub-signals-s390x run-gdbstub-svc endif diff --git a/tests/unit/test-bdrv-drain.c b/tests/unit/test-bdrv-drain.c index 8d05538bf6..704d1a3f36 100644 --- a/tests/unit/test-bdrv-drain.c +++ b/tests/unit/test-bdrv-drain.c @@ -809,7 +809,7 @@ static void test_blockjob_common_drain_node(enum drain_type drain_type, bdrv_graph_wrlock(target); block_job_add_bdrv(job, "target", target, 0, BLK_PERM_ALL, &error_abort); - bdrv_graph_wrunlock(); + bdrv_graph_wrunlock(target); switch (result) { case TEST_JOB_SUCCESS: @@ -995,7 +995,7 @@ static void bdrv_test_top_close(BlockDriverState *bs) QLIST_FOREACH_SAFE(c, &bs->children, next, next_c) { bdrv_unref_child(bs, c); } - bdrv_graph_wrunlock(); + bdrv_graph_wrunlock(NULL); } static int coroutine_fn GRAPH_RDLOCK @@ -1088,7 +1088,7 @@ static void do_test_delete_by_drain(bool detach_instead_of_delete, bdrv_graph_wrlock(NULL); bdrv_attach_child(bs, null_bs, "null-child", &child_of_bds, BDRV_CHILD_DATA, &error_abort); - bdrv_graph_wrunlock(); + bdrv_graph_wrunlock(NULL); /* This child will be the one to pass to requests through to, and * it will stall until a drain occurs */ @@ -1101,7 +1101,7 @@ static void do_test_delete_by_drain(bool detach_instead_of_delete, &child_of_bds, BDRV_CHILD_DATA | BDRV_CHILD_PRIMARY, &error_abort); - bdrv_graph_wrunlock(); + bdrv_graph_wrunlock(NULL); /* This child is just there to be deleted * (for detach_instead_of_delete == true) */ @@ -1110,7 +1110,7 @@ static void do_test_delete_by_drain(bool detach_instead_of_delete, bdrv_graph_wrlock(NULL); bdrv_attach_child(bs, null_bs, "null-child", &child_of_bds, BDRV_CHILD_DATA, &error_abort); - bdrv_graph_wrunlock(); + bdrv_graph_wrunlock(NULL); blk = blk_new(qemu_get_aio_context(), BLK_PERM_ALL, BLK_PERM_ALL); blk_insert_bs(blk, bs, &error_abort); @@ -1200,7 +1200,7 @@ static void no_coroutine_fn detach_indirect_bh(void *opaque) data->child_c = bdrv_attach_child(data->parent_b, data->c, "PB-C", &child_of_bds, BDRV_CHILD_DATA, &error_abort); - bdrv_graph_wrunlock(); + bdrv_graph_wrunlock(NULL); } static void coroutine_mixed_fn detach_by_parent_aio_cb(void *opaque, int ret) @@ -1308,7 +1308,7 @@ static void TSA_NO_TSA test_detach_indirect(bool by_parent_cb) bdrv_attach_child(parent_a, a, "PA-A", by_parent_cb ? &child_of_bds : &detach_by_driver_cb_class, BDRV_CHILD_DATA, &error_abort); - bdrv_graph_wrunlock(); + bdrv_graph_wrunlock(NULL); g_assert_cmpint(parent_a->refcnt, ==, 1); g_assert_cmpint(parent_b->refcnt, ==, 1); @@ -1735,7 +1735,7 @@ static void test_drop_intermediate_poll(void) &chain_child_class, BDRV_CHILD_COW, &error_abort); } } - bdrv_graph_wrunlock(); + bdrv_graph_wrunlock(NULL); job = block_job_create("job", &test_simple_job_driver, NULL, job_node, 0, BLK_PERM_ALL, 0, 0, NULL, NULL, &error_abort); @@ -1985,7 +1985,7 @@ static void do_test_replace_child_mid_drain(int old_drain_count, bdrv_graph_wrlock(NULL); bdrv_attach_child(parent_bs, old_child_bs, "child", &child_of_bds, BDRV_CHILD_COW, &error_abort); - bdrv_graph_wrunlock(); + bdrv_graph_wrunlock(NULL); parent_s->setup_completed = true; for (i = 0; i < old_drain_count; i++) { @@ -2018,7 +2018,7 @@ static void do_test_replace_child_mid_drain(int old_drain_count, bdrv_drained_begin(new_child_bs); bdrv_graph_wrlock(NULL); bdrv_replace_node(old_child_bs, new_child_bs, &error_abort); - bdrv_graph_wrunlock(); + bdrv_graph_wrunlock(NULL); bdrv_drained_end(new_child_bs); bdrv_drained_end(old_child_bs); g_assert(parent_bs->quiesce_counter == new_drain_count); diff --git a/tests/unit/test-bdrv-graph-mod.c b/tests/unit/test-bdrv-graph-mod.c index 878544dbd5..074adcbb93 100644 --- a/tests/unit/test-bdrv-graph-mod.c +++ b/tests/unit/test-bdrv-graph-mod.c @@ -140,7 +140,7 @@ static void test_update_perm_tree(void) bdrv_graph_wrlock(NULL); bdrv_attach_child(filter, bs, "child", &child_of_bds, BDRV_CHILD_DATA, &error_abort); - bdrv_graph_wrunlock(); + bdrv_graph_wrunlock(NULL); aio_context_acquire(qemu_get_aio_context()); ret = bdrv_append(filter, bs, NULL); @@ -210,7 +210,7 @@ static void test_should_update_child(void) g_assert(target->backing->bs == bs); bdrv_attach_child(filter, target, "target", &child_of_bds, BDRV_CHILD_DATA, &error_abort); - bdrv_graph_wrunlock(); + bdrv_graph_wrunlock(NULL); aio_context_acquire(qemu_get_aio_context()); bdrv_append(filter, bs, &error_abort); aio_context_release(qemu_get_aio_context()); @@ -260,7 +260,7 @@ static void test_parallel_exclusive_write(void) &error_abort); bdrv_replace_node(fl1, fl2, &error_abort); - bdrv_graph_wrunlock(); + bdrv_graph_wrunlock(NULL); bdrv_drained_end(fl2); bdrv_drained_end(fl1); @@ -380,7 +380,7 @@ static void test_parallel_perm_update(void) bdrv_attach_child(fl2, base, "backing", &child_of_bds, BDRV_CHILD_FILTERED | BDRV_CHILD_PRIMARY, &error_abort); - bdrv_graph_wrunlock(); + bdrv_graph_wrunlock(NULL); /* Select fl1 as first child to be active */ s->selected = c_fl1; @@ -438,7 +438,7 @@ static void test_append_greedy_filter(void) bdrv_attach_child(top, base, "backing", &child_of_bds, BDRV_CHILD_FILTERED | BDRV_CHILD_PRIMARY, &error_abort); - bdrv_graph_wrunlock(); + bdrv_graph_wrunlock(NULL); aio_context_acquire(qemu_get_aio_context()); bdrv_append(fl, base, &error_abort); diff --git a/ui/console.c b/ui/console.c index 8e688d3569..7db921e3b7 100644 --- a/ui/console.c +++ b/ui/console.c @@ -1679,19 +1679,17 @@ void qemu_display_init(DisplayState *ds, DisplayOptions *opts) const char *qemu_display_get_vc(DisplayOptions *opts) { - assert(opts->type < DISPLAY_TYPE__MAX); - if (opts->type == DISPLAY_TYPE_NONE) { - return NULL; - } - assert(dpys[opts->type] != NULL); - if (dpys[opts->type]->vc) { - return dpys[opts->type]->vc; - } else { #ifdef CONFIG_PIXMAN - return "vc:80Cx24C"; + const char *vc = "vc:80Cx24C"; +#else + const char *vc = NULL; #endif + + assert(opts->type < DISPLAY_TYPE__MAX); + if (dpys[opts->type] && dpys[opts->type]->vc) { + vc = dpys[opts->type]->vc; } - return NULL; + return vc; } void qemu_display_help(void) diff --git a/ui/dbus.c b/ui/dbus.c index 866467ad2e..e08b5de064 100644 --- a/ui/dbus.c +++ b/ui/dbus.c @@ -518,6 +518,7 @@ static QemuDisplay qemu_display_dbus = { .type = DISPLAY_TYPE_DBUS, .early_init = early_dbus_init, .init = dbus_init, + .vc = "vc", }; static void register_dbus(void) diff --git a/ui/gtk-egl.c b/ui/gtk-egl.c index cd2f176502..3af5ac5bcf 100644 --- a/ui/gtk-egl.c +++ b/ui/gtk-egl.c @@ -249,14 +249,14 @@ void gd_egl_scanout_texture(DisplayChangeListener *dcl, if (!vc->gfx.esurface) { return; } - - eglMakeCurrent(qemu_egl_display, vc->gfx.esurface, - vc->gfx.esurface, vc->gfx.ectx); - - gtk_egl_set_scanout_mode(vc, true); - egl_fb_setup_for_tex(&vc->gfx.guest_fb, backing_width, backing_height, - backing_id, false); } + + eglMakeCurrent(qemu_egl_display, vc->gfx.esurface, + vc->gfx.esurface, vc->gfx.ectx); + + gtk_egl_set_scanout_mode(vc, true); + egl_fb_setup_for_tex(&vc->gfx.guest_fb, backing_width, backing_height, + backing_id, false); } void gd_egl_scanout_dmabuf(DisplayChangeListener *dcl, diff --git a/ui/gtk.c b/ui/gtk.c index be047a41ad..810d7fc796 100644 --- a/ui/gtk.c +++ b/ui/gtk.c @@ -2534,6 +2534,7 @@ static QemuDisplay qemu_display_gtk = { .type = DISPLAY_TYPE_GTK, .early_init = early_gtk_display_init, .init = gtk_display_init, + .vc = "vc", }; static void register_gtk(void) diff --git a/ui/spice-app.c b/ui/spice-app.c index 405fb7f9f5..a10b4a58fe 100644 --- a/ui/spice-app.c +++ b/ui/spice-app.c @@ -220,6 +220,7 @@ static QemuDisplay qemu_display_spice_app = { .type = DISPLAY_TYPE_SPICE_APP, .early_init = spice_app_display_early_init, .init = spice_app_display_init, + .vc = "vc", }; static void register_spice_app(void) diff --git a/ui/ui-qmp-cmds.c b/ui/ui-qmp-cmds.c index d772e1cb7f..74fa6c6ec5 100644 --- a/ui/ui-qmp-cmds.c +++ b/ui/ui-qmp-cmds.c @@ -44,7 +44,8 @@ void qmp_set_password(SetPasswordOptions *opts, Error **errp) assert(opts->protocol == DISPLAY_PROTOCOL_VNC); if (opts->connected != SET_PASSWORD_ACTION_KEEP) { /* vnc supports "connected=keep" only */ - error_setg(errp, QERR_INVALID_PARAMETER, "connected"); + error_setg(errp, "parameter 'connected' must be 'keep'" + " when 'protocol' is 'vnc'"); return; } /* @@ -195,7 +196,7 @@ void qmp_client_migrate_info(const char *protocol, const char *hostname, } if (!has_port && !has_tls_port) { - error_setg(errp, QERR_MISSING_PARAMETER, "port/tls-port"); + error_setg(errp, "parameter 'port' or 'tls-port' is required"); return; } diff --git a/ui/vnc-clipboard.c b/ui/vnc-clipboard.c index c759be3438..124b6fbd9c 100644 --- a/ui/vnc-clipboard.c +++ b/ui/vnc-clipboard.c @@ -69,6 +69,11 @@ static uint8_t *inflate_buffer(uint8_t *in, uint32_t in_len, uint32_t *size) } } + *size = stream.total_out; + inflateEnd(&stream); + + return out; + err_end: inflateEnd(&stream); err: diff --git a/util/coroutine-ucontext.c b/util/coroutine-ucontext.c index 7b304c79d9..8ef603d081 100644 --- a/util/coroutine-ucontext.c +++ b/util/coroutine-ucontext.c @@ -119,13 +119,11 @@ void finish_switch_fiber(void *fake_stack_save) /* always_inline is required to avoid TSan runtime fatal errors. */ static inline __attribute__((always_inline)) -void start_switch_fiber_asan(CoroutineAction action, void **fake_stack_save, +void start_switch_fiber_asan(void **fake_stack_save, const void *bottom, size_t size) { #ifdef CONFIG_ASAN - __sanitizer_start_switch_fiber( - action == COROUTINE_TERMINATE ? NULL : fake_stack_save, - bottom, size); + __sanitizer_start_switch_fiber(fake_stack_save, bottom, size); #endif } @@ -165,7 +163,7 @@ static void coroutine_trampoline(int i0, int i1) if (!sigsetjmp(self->env, 0)) { CoroutineUContext *leaderp = get_ptr_leader(); - start_switch_fiber_asan(COROUTINE_YIELD, &fake_stack_save, + start_switch_fiber_asan(&fake_stack_save, leaderp->stack, leaderp->stack_size); start_switch_fiber_tsan(&fake_stack_save, self, true); /* true=caller */ siglongjmp(*(sigjmp_buf *)co->entry_arg, 1); @@ -226,8 +224,7 @@ Coroutine *qemu_coroutine_new(void) /* swapcontext() in, siglongjmp() back out */ if (!sigsetjmp(old_env, 0)) { - start_switch_fiber_asan(COROUTINE_YIELD, &fake_stack_save, co->stack, - co->stack_size); + start_switch_fiber_asan(&fake_stack_save, co->stack, co->stack_size); start_switch_fiber_tsan(&fake_stack_save, co, false); /* false=not caller */ @@ -269,10 +266,28 @@ static inline void valgrind_stack_deregister(CoroutineUContext *co) #endif #endif +#if defined(CONFIG_ASAN) && defined(CONFIG_COROUTINE_POOL) +static void coroutine_fn terminate_asan(void *opaque) +{ + CoroutineUContext *to = DO_UPCAST(CoroutineUContext, base, opaque); + + set_current(opaque); + start_switch_fiber_asan(NULL, to->stack, to->stack_size); + G_STATIC_ASSERT(!IS_ENABLED(CONFIG_TSAN)); + siglongjmp(to->env, COROUTINE_ENTER); +} +#endif + void qemu_coroutine_delete(Coroutine *co_) { CoroutineUContext *co = DO_UPCAST(CoroutineUContext, base, co_); +#if defined(CONFIG_ASAN) && defined(CONFIG_COROUTINE_POOL) + co_->entry_arg = qemu_coroutine_self(); + co_->entry = terminate_asan; + qemu_coroutine_switch(co_->entry_arg, co_, COROUTINE_ENTER); +#endif + #ifdef CONFIG_VALGRIND_H valgrind_stack_deregister(co); #endif @@ -305,8 +320,10 @@ qemu_coroutine_switch(Coroutine *from_, Coroutine *to_, ret = sigsetjmp(from->env, 0); if (ret == 0) { - start_switch_fiber_asan(action, &fake_stack_save, to->stack, - to->stack_size); + start_switch_fiber_asan(IS_ENABLED(CONFIG_COROUTINE_POOL) || + action != COROUTINE_TERMINATE ? + &fake_stack_save : NULL, + to->stack, to->stack_size); start_switch_fiber_tsan(&fake_stack_save, to, false); /* false=not caller */ siglongjmp(to->env, action); diff --git a/util/cpuinfo-ppc.c b/util/cpuinfo-ppc.c index 1ea3db0ac8..b2d8893a06 100644 --- a/util/cpuinfo-ppc.c +++ b/util/cpuinfo-ppc.c @@ -6,10 +6,10 @@ #include "qemu/osdep.h" #include "host/cpuinfo.h" +#include #ifdef CONFIG_GETAUXVAL # include #else -# include # include "elf.h" #endif @@ -40,7 +40,7 @@ unsigned __attribute__((constructor)) cpuinfo_init(void) info |= CPUINFO_V2_06; } - if (hwcap2 & PPC_FEATURE2_HAS_ISEL) { + if (hwcap2 & PPC_FEATURE2_ISEL) { info |= CPUINFO_ISEL; } if (hwcap & PPC_FEATURE_HAS_ALTIVEC) { @@ -53,7 +53,7 @@ unsigned __attribute__((constructor)) cpuinfo_init(void) * always have both anyway, since VSX came with Power7 * and crypto came with Power8. */ - if (hwcap2 & PPC_FEATURE2_HAS_VEC_CRYPTO) { + if (hwcap2 & PPC_FEATURE2_VEC_CRYPTO) { info |= CPUINFO_CRYPTO; } } diff --git a/util/filemonitor-inotify.c b/util/filemonitor-inotify.c index 2121111f38..7352b9fe53 100644 --- a/util/filemonitor-inotify.c +++ b/util/filemonitor-inotify.c @@ -89,7 +89,7 @@ static void qemu_file_monitor_watch(void *arg) struct inotify_event *ev = (struct inotify_event *)(buf + used); /* - * We trust the kenel to provide valid buffer with complete event + * We trust the kernel to provide valid buffer with complete event * records. */ assert(len - used >= sizeof(struct inotify_event)); diff --git a/util/range.c b/util/range.c index 9605ccfcbe..f3f40098d5 100644 --- a/util/range.c +++ b/util/range.c @@ -98,7 +98,7 @@ void range_inverse_array(GList *in, GList **rev, out = append_new_range(out, low, MIN(range_lob(r) - 1, high)); } - /* insert a range inbetween each original range until we reach high */ + /* insert a range in between each original range until we reach high */ for (; l->next; l = l->next) { r = (Range *)l->data; rn = (Range *)l->next->data; diff --git a/util/vhost-user-server.c b/util/vhost-user-server.c index 5ccc6d24a0..a9a48fffb8 100644 --- a/util/vhost-user-server.c +++ b/util/vhost-user-server.c @@ -132,8 +132,7 @@ vu_message_read(VuDev *vu_dev, int conn_fd, VhostUserMsg *vmsg) qio_channel_yield(ioc, G_IO_IN); server->in_qio_channel_yield = false; } else { - /* Wait until attached to an AioContext again */ - qemu_coroutine_yield(); + return false; } continue; } else { @@ -201,8 +200,16 @@ static coroutine_fn void vu_client_trip(void *opaque) VuServer *server = opaque; VuDev *vu_dev = &server->vu_dev; - while (!vu_dev->broken && vu_dispatch(vu_dev)) { - /* Keep running */ + while (!vu_dev->broken) { + if (server->quiescing) { + server->co_trip = NULL; + aio_wait_kick(); + return; + } + /* vu_dispatch() returns false if server->ctx went away */ + if (!vu_dispatch(vu_dev) && server->ctx) { + break; + } } if (vhost_user_server_has_in_flight(server)) { @@ -353,8 +360,7 @@ static void vu_accept(QIONetListener *listener, QIOChannelSocket *sioc, qio_channel_set_follow_coroutine_ctx(server->ioc, true); - server->co_trip = qemu_coroutine_create(vu_client_trip, server); - + /* Attaching the AioContext starts the vu_client_trip coroutine */ aio_context_acquire(server->ctx); vhost_user_server_attach_aio_context(server, server->ctx); aio_context_release(server->ctx); @@ -413,8 +419,25 @@ void vhost_user_server_attach_aio_context(VuServer *server, AioContext *ctx) NULL, NULL, vu_fd_watch); } - assert(!server->in_qio_channel_yield); - aio_co_schedule(ctx, server->co_trip); + if (server->co_trip) { + /* + * The caller didn't fully shut down co_trip (this can happen on + * non-polling drains like in bdrv_graph_wrlock()). This is okay as long + * as it no longer tries to shut it down and we're guaranteed to still + * be in the same AioContext as before. + * + * co_ctx can still be NULL if we get multiple calls and only just + * scheduled a new coroutine in the else branch. + */ + AioContext *co_ctx = qemu_coroutine_get_aio_context(server->co_trip); + + assert(!server->quiescing); + assert(!co_ctx || co_ctx == ctx); + } else { + server->co_trip = qemu_coroutine_create(vu_client_trip, server); + assert(!server->in_qio_channel_yield); + aio_co_schedule(ctx, server->co_trip); + } } /* Called with server->ctx acquired */