Version in base suite: 10.0.3+ds-0+deb13u1 Base version: qemu_10.0.3+ds-0+deb13u1 Target version: qemu_10.0.6+ds-0+deb13u1 Base file: /srv/ftp-master.debian.org/ftp/pool/main/q/qemu/qemu_10.0.3+ds-0+deb13u1.dsc Target file: /srv/ftp-master.debian.org/policy/pool/main/q/qemu/qemu_10.0.6+ds-0+deb13u1.dsc .gitlab-ci.d/buildtest.yml | 2 .gitlab-ci.d/container-cross.yml | 3 .gitlab-ci.d/crossbuilds.yml | 5 .gitmodules | 4 VERSION | 2 accel/tcg/tb-maint.c | 8 block/curl.c | 17 block/rbd.c | 104 +++-- contrib/elf2dmp/download.c | 4 debian/changelog | 191 ++++++++++ debian/control.mk | 2 debian/patches/hw-display-qxl-render.c-fix-qxl_unpack_chunks-chunk-.patch | 51 -- debian/patches/pcie_sriov-Fix-configuration-and-state-synchronizati.patch | 122 ------ debian/patches/series | 3 debian/patches/system-physmem-fix-use-after-free-with-dispatch.patch | 126 ------ docs/devel/uefi-vars.rst | 4 docs/interop/firmware.json | 4 docs/pcie_sriov.txt | 5 docs/user/index.rst | 5 host/include/aarch64/host/atomic128-cas.h | 45 -- host/include/aarch64/host/atomic128-cas.h.inc | 45 ++ hw/arm/stm32f205_soc.c | 10 hw/char/sifive_uart.c | 24 - hw/core/cpu-common.c | 1 hw/display/qxl-render.c | 11 hw/gpio/pca9554.c | 2 hw/i386/amd_iommu.c | 6 hw/i386/intel_iommu.c | 15 hw/input/hid.c | 1 hw/intc/apic.c | 2 hw/intc/arm_gicv3_kvm.c | 17 hw/intc/pnv_xive2.c | 29 + hw/intc/riscv_aplic.c | 6 hw/intc/trace-events | 6 hw/intc/xics.c | 2 hw/intc/xive.c | 11 hw/intc/xive2.c | 38 + hw/net/cadence_gem.c | 2 hw/net/e1000e_core.c | 5 hw/net/igbvf.c | 6 hw/net/virtio-net.c | 7 hw/nvme/ctrl.c | 51 +- hw/pci-host/astro.c | 27 - hw/pci-host/dino.c | 74 +-- hw/pci/pci.c | 42 +- hw/pci/pcie_sriov.c | 81 +--- hw/ppc/pnv.c | 86 ++++ hw/ppc/spapr.c | 11 hw/riscv/riscv-iommu.c | 154 +++++++- hw/sd/ssi-sd.c | 4 hw/ssi/aspeed_smc.c | 3 hw/uefi/var-service-core.c | 4 hw/uefi/var-service-json.c | 2 hw/uefi/var-service-vars.c | 5 hw/usb/dev-network.c | 2 hw/usb/hcd-uhci.c | 10 hw/virtio/vhost.c | 6 hw/virtio/virtio.c | 22 - include/elf.h | 7 include/exec/cpu-common.h | 10 include/exec/memory.h | 24 + include/hw/arm/stm32f205_soc.h | 2 include/hw/core/cpu.h | 1 include/hw/intc/arm_gicv3_common.h | 3 include/hw/pci/pcie_sriov.h | 4 include/hw/ppc/xive2_regs.h | 1 include/qemu/compiler.h | 13 include/qemu/host-utils.h | 2 linux-user/aarch64/signal.c | 48 ++ linux-user/microblaze/target_elf.h | 3 linux-user/mips/target_elf.h | 6 linux-user/strace.c | 2 linux-user/strace.list | 6 migration/migration.c | 5 pc-bios/optionrom/multiboot.S | 2 python/qemu/machine/qtest.py | 2 python/qemu/qmp/legacy.py | 42 +- python/qemu/qmp/protocol.py | 48 +- python/qemu/qmp/qmp_shell.py | 2 python/qemu/qmp/qmp_tui.py | 30 + python/qemu/qmp/util.py | 134 +------ python/scripts/mkvenv.py | 68 +++ python/tests/protocol.py | 10 qapi/block-core.json | 9 qga/commands-linux.c | 14 qga/commands.c | 6 qga/installer/qemu-ga.wxs | 23 + qga/vss-win32/requester.cpp | 5 roms/Makefile | 8 rust/hw/timer/hpet/src/hpet.rs | 2 scripts/kernel-doc | 9 scripts/make-release | 20 - scsi/pr-manager-helper.c | 9 stubs/cpu-destroy-address-spaces.c | 15 stubs/meson.build | 1 subprojects/libvduse/include/compiler.h | 13 subprojects/libvhost-user/include/compiler.h | 13 system/memory.c | 20 - system/physmem.c | 52 -- target/arm/gdbstub64.c | 35 + target/arm/helper.c | 66 ++- target/hppa/insns.decode | 8 target/i386/cpu.c | 19 target/i386/cpu.h | 5 target/i386/helper.c | 4 target/i386/kvm/kvm-cpu.c | 10 target/i386/kvm/kvm.c | 30 + target/i386/kvm/vmsr_energy.c | 6 target/i386/tcg/decode-new.c.inc | 6 target/i386/tcg/system/excp_helper.c | 3 target/i386/tcg/system/seg_helper.c | 1 target/i386/tcg/system/smm_helper.c | 10 target/i386/tcg/system/svm_helper.c | 2 target/i386/tcg/system/tcg-cpu.c | 4 target/loongarch/cpu.c | 4 target/loongarch/cpu.h | 2 target/loongarch/cpu_helper.c | 4 target/loongarch/tcg/insn_trans/trans_atomic.c.inc | 36 - target/loongarch/tcg/insn_trans/trans_extra.c.inc | 20 - target/loongarch/tcg/insn_trans/trans_farith.c.inc | 8 target/loongarch/tcg/insn_trans/trans_fcnv.c.inc | 4 target/loongarch/tcg/insn_trans/trans_fmemory.c.inc | 16 target/loongarch/tcg/insn_trans/trans_privileged.c.inc | 4 target/loongarch/tcg/insn_trans/trans_shift.c.inc | 4 target/loongarch/tcg/insn_trans/trans_vec.c.inc | 6 target/loongarch/translate.h | 5 target/mips/tcg/system/cp0_helper.c | 32 - target/mips/tcg/system/tlb_helper.c | 2 target/ppc/cpu.h | 4 target/ppc/misc_helper.c | 59 --- target/riscv/cpu.c | 2 target/riscv/cpu.h | 2 target/riscv/csr.c | 20 - target/riscv/helper.h | 21 - target/riscv/insn_trans/trans_rvv.c.inc | 50 ++ target/riscv/insn_trans/trans_rvzce.c.inc | 6 target/riscv/insn_trans/trans_rvzicfiss.c.inc | 9 target/riscv/machine.c | 3 target/riscv/op_helper.c | 64 +++ target/riscv/pmp.c | 7 target/riscv/tcg/tcg-cpu.c | 21 - target/riscv/translate.c | 3 target/riscv/vector_helper.c | 20 - target/sparc/insns.decode | 83 ++-- target/sparc/translate.c | 77 ++-- tcg/optimize.c | 3 tests/Makefile.include | 3 tests/docker/dockerfiles/python.docker | 2 tests/functional/test_aarch64_sbsaref_freebsd.py | 8 tests/functional/test_ppc_bamboo.py | 34 - tests/qemu-iotests/039.out | 10 tests/qemu-iotests/061.out | 4 tests/qemu-iotests/137.out | 2 tests/qemu-iotests/147 | 1 tests/qemu-iotests/151 | 5 tests/qemu-iotests/check | 4 tests/qemu-iotests/common.filter | 2 tests/qemu-iotests/testenv.py | 7 tests/qemu-iotests/testrunner.py | 9 tests/qtest/qos-test.c | 5 tests/qtest/vhost-user-test.c | 27 - tests/tcg/multiarch/Makefile.target | 2 tests/tcg/multiarch/tb-link.c | 67 +++ ui/curses.c | 10 ui/gtk.c | 29 + ui/icons/qemu.svg | 21 + ui/input-barrier.c | 5 ui/spice-core.c | 6 ui/vnc.c | 18 util/async.c | 11 170 files changed, 2006 insertions(+), 1327 deletions(-) diff -Nru qemu-10.0.3+ds/.gitlab-ci.d/buildtest.yml qemu-10.0.6+ds/.gitlab-ci.d/buildtest.yml --- qemu-10.0.3+ds/.gitlab-ci.d/buildtest.yml 2025-07-23 21:05:28.000000000 +0000 +++ qemu-10.0.6+ds/.gitlab-ci.d/buildtest.yml 2025-10-20 18:13:45.000000000 +0000 @@ -751,7 +751,7 @@ - make gtags # 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 + - CI_COMMIT_MESSAGE= CI_COMMIT_TAG_MESSAGE= CI_COMMIT_DESCRIPTION= htags -anT --tree-view=filetree -m qemu_init -t "Welcome to the QEMU sourcecode" - mv HTML public/src diff -Nru qemu-10.0.3+ds/.gitlab-ci.d/container-cross.yml qemu-10.0.6+ds/.gitlab-ci.d/container-cross.yml --- qemu-10.0.3+ds/.gitlab-ci.d/container-cross.yml 2025-07-23 21:05:28.000000000 +0000 +++ qemu-10.0.6+ds/.gitlab-ci.d/container-cross.yml 2025-10-20 18:13:45.000000000 +0000 @@ -67,11 +67,8 @@ riscv64-debian-cross-container: extends: .container_job_template stage: containers - # as we are currently based on 'sid/unstable' we may break so... - allow_failure: true variables: NAME: debian-riscv64-cross - QEMU_JOB_OPTIONAL: 1 s390x-debian-cross-container: extends: .container_job_template diff -Nru qemu-10.0.3+ds/.gitlab-ci.d/crossbuilds.yml qemu-10.0.6+ds/.gitlab-ci.d/crossbuilds.yml --- qemu-10.0.3+ds/.gitlab-ci.d/crossbuilds.yml 2025-07-23 21:05:28.000000000 +0000 +++ qemu-10.0.6+ds/.gitlab-ci.d/crossbuilds.yml 2025-10-20 18:13:45.000000000 +0000 @@ -118,12 +118,8 @@ IMAGE: debian-ppc64el-cross EXTRA_CONFIGURE_OPTS: --disable-tcg --without-default-devices -# The riscv64 cross-builds currently use a 'sid' container to get -# compilers and libraries. Until something more stable is found we -# allow_failure so as not to block CI. cross-riscv64-system: extends: .cross_system_build_job - allow_failure: true needs: job: riscv64-debian-cross-container variables: @@ -131,7 +127,6 @@ cross-riscv64-user: extends: .cross_user_build_job - allow_failure: true needs: job: riscv64-debian-cross-container variables: diff -Nru qemu-10.0.3+ds/.gitmodules qemu-10.0.6+ds/.gitmodules --- qemu-10.0.3+ds/.gitmodules 2025-07-23 21:05:28.000000000 +0000 +++ qemu-10.0.6+ds/.gitmodules 2025-10-20 18:13:45.000000000 +0000 @@ -15,7 +15,7 @@ url = https://gitlab.com/qemu-project/qemu-palcode.git [submodule "roms/u-boot"] path = roms/u-boot - url = https://gitlab.com/qemu-project/u-boot.git + url = https://gitlab.com/qemu-project-mirrors/u-boot.git [submodule "roms/skiboot"] path = roms/skiboot url = https://gitlab.com/qemu-project/skiboot.git @@ -27,7 +27,7 @@ url = https://gitlab.com/qemu-project/seabios-hppa.git [submodule "roms/u-boot-sam460ex"] path = roms/u-boot-sam460ex - url = https://gitlab.com/qemu-project/u-boot-sam460ex.git + url = https://gitlab.com/qemu-project-mirrors/u-boot-sam460ex.git [submodule "roms/edk2"] path = roms/edk2 url = https://gitlab.com/qemu-project/edk2.git diff -Nru qemu-10.0.3+ds/VERSION qemu-10.0.6+ds/VERSION --- qemu-10.0.3+ds/VERSION 2025-07-23 21:05:28.000000000 +0000 +++ qemu-10.0.6+ds/VERSION 2025-10-20 18:13:45.000000000 +0000 @@ -1 +1 @@ -10.0.3 +10.0.6 diff -Nru qemu-10.0.3+ds/accel/tcg/tb-maint.c qemu-10.0.6+ds/accel/tcg/tb-maint.c --- qemu-10.0.3+ds/accel/tcg/tb-maint.c 2025-07-23 21:05:28.000000000 +0000 +++ qemu-10.0.6+ds/accel/tcg/tb-maint.c 2025-10-20 18:13:45.000000000 +0000 @@ -839,6 +839,14 @@ * We first acquired the lock, and since the destination pointer matches, * we know for sure that @orig is in the jmp list. */ + if (dest == orig) { + /* + * In the case of a TB that links to itself, removing the entry + * from the list means that it won't be present later during + * tb_jmp_unlink -- unlink now. + */ + tb_reset_jump(orig, n_orig); + } pprev = &dest->jmp_list_head; TB_FOR_EACH_JMP(dest, tb, n) { if (tb == orig && n == n_orig) { diff -Nru qemu-10.0.3+ds/block/curl.c qemu-10.0.6+ds/block/curl.c --- qemu-10.0.3+ds/block/curl.c 2025-07-23 21:05:28.000000000 +0000 +++ qemu-10.0.6+ds/block/curl.c 2025-10-20 18:13:45.000000000 +0000 @@ -162,13 +162,9 @@ static int curl_sock_cb(CURL *curl, curl_socket_t fd, int action, void *userp, void *sp) { - BDRVCURLState *s; - CURLState *state = NULL; + BDRVCURLState *s = userp; CURLSocket *socket; - curl_easy_getinfo(curl, CURLINFO_PRIVATE, (char **)&state); - s = state->s; - socket = g_hash_table_lookup(s->sockets, GINT_TO_POINTER(fd)); if (!socket) { socket = g_new0(CURLSocket, 1); @@ -475,11 +471,11 @@ (void *)curl_read_cb) || curl_easy_setopt(state->curl, CURLOPT_WRITEDATA, (void *)state) || curl_easy_setopt(state->curl, CURLOPT_PRIVATE, (void *)state) || - curl_easy_setopt(state->curl, CURLOPT_AUTOREFERER, 1) || - curl_easy_setopt(state->curl, CURLOPT_FOLLOWLOCATION, 1) || - curl_easy_setopt(state->curl, CURLOPT_NOSIGNAL, 1) || + curl_easy_setopt(state->curl, CURLOPT_AUTOREFERER, 1L) || + curl_easy_setopt(state->curl, CURLOPT_FOLLOWLOCATION, 1L) || + curl_easy_setopt(state->curl, CURLOPT_NOSIGNAL, 1L) || curl_easy_setopt(state->curl, CURLOPT_ERRORBUFFER, state->errmsg) || - curl_easy_setopt(state->curl, CURLOPT_FAILONERROR, 1)) { + curl_easy_setopt(state->curl, CURLOPT_FAILONERROR, 1L)) { goto err; } if (s->username) { @@ -605,6 +601,7 @@ assert(!s->multi); s->multi = curl_multi_init(); s->aio_context = new_context; + curl_multi_setopt(s->multi, CURLMOPT_SOCKETDATA, s); curl_multi_setopt(s->multi, CURLMOPT_SOCKETFUNCTION, curl_sock_cb); curl_multi_setopt(s->multi, CURLMOPT_TIMERDATA, s); curl_multi_setopt(s->multi, CURLMOPT_TIMERFUNCTION, curl_timer_cb); @@ -803,7 +800,7 @@ } s->accept_range = false; - if (curl_easy_setopt(state->curl, CURLOPT_NOBODY, 1) || + if (curl_easy_setopt(state->curl, CURLOPT_NOBODY, 1L) || curl_easy_setopt(state->curl, CURLOPT_HEADERFUNCTION, curl_header_cb) || curl_easy_setopt(state->curl, CURLOPT_HEADERDATA, s)) { pstrcpy(state->errmsg, CURL_ERROR_SIZE, diff -Nru qemu-10.0.3+ds/block/rbd.c qemu-10.0.6+ds/block/rbd.c --- qemu-10.0.3+ds/block/rbd.c 2025-07-23 21:05:28.000000000 +0000 +++ qemu-10.0.6+ds/block/rbd.c 2025-10-20 18:13:45.000000000 +0000 @@ -99,6 +99,14 @@ char *namespace; uint64_t image_size; uint64_t object_size; + + /* + * If @bs->encrypted is true, this is the encryption format actually loaded + * at the librbd level. If it is false, it is the result of probing. + * RBD_IMAGE_ENCRYPTION_FORMAT__MAX means that encryption is not enabled and + * probing didn't find any known encryption header either. + */ + RbdImageEncryptionFormat encryption_format; } BDRVRBDState; typedef struct RBDTask { @@ -471,10 +479,12 @@ return 0; } -static int qemu_rbd_encryption_load(rbd_image_t image, +static int qemu_rbd_encryption_load(BlockDriverState *bs, + rbd_image_t image, RbdEncryptionOptions *encrypt, Error **errp) { + BDRVRBDState *s = bs->opaque; int r = 0; g_autofree char *passphrase = NULL; rbd_encryption_luks1_format_options_t luks_opts; @@ -545,15 +555,19 @@ error_setg_errno(errp, -r, "encryption load fail"); return r; } + bs->encrypted = true; + s->encryption_format = encrypt->format; return 0; } #ifdef LIBRBD_SUPPORTS_ENCRYPTION_LOAD2 -static int qemu_rbd_encryption_load2(rbd_image_t image, +static int qemu_rbd_encryption_load2(BlockDriverState *bs, + rbd_image_t image, RbdEncryptionOptions *encrypt, Error **errp) { + BDRVRBDState *s = bs->opaque; int r = 0; int encrypt_count = 1; int i; @@ -639,6 +653,8 @@ error_setg_errno(errp, -r, "layered encryption load fail"); goto exit; } + bs->encrypted = true; + s->encryption_format = encrypt->format; exit: for (i = 0; i < encrypt_count; ++i) { @@ -672,6 +688,45 @@ #endif #endif +/* + * For an image without encryption enabled on the rbd layer, probe the start of + * the image if it could be opened as an encrypted image so that we can display + * it when the user queries the node (most importantly in qemu-img). + * + * If the guest writes an encryption header to its disk after this probing, this + * won't be reflected when queried, but that's okay. There is no reason why the + * user should want to apply encryption at the rbd level while the image is + * still in use. This is just guest data. + */ +static void qemu_rbd_encryption_probe(BlockDriverState *bs) +{ + BDRVRBDState *s = bs->opaque; + char buf[RBD_ENCRYPTION_LUKS_HEADER_VERIFICATION_LEN] = {0}; + int r; + + assert(s->encryption_format == RBD_IMAGE_ENCRYPTION_FORMAT__MAX); + + r = rbd_read(s->image, 0, + RBD_ENCRYPTION_LUKS_HEADER_VERIFICATION_LEN, buf); + if (r < RBD_ENCRYPTION_LUKS_HEADER_VERIFICATION_LEN) { + return; + } + + if (memcmp(buf, rbd_luks_header_verification, + RBD_ENCRYPTION_LUKS_HEADER_VERIFICATION_LEN) == 0) { + s->encryption_format = RBD_IMAGE_ENCRYPTION_FORMAT_LUKS; + } else if (memcmp(buf, rbd_luks2_header_verification, + RBD_ENCRYPTION_LUKS_HEADER_VERIFICATION_LEN) == 0) { + s->encryption_format = RBD_IMAGE_ENCRYPTION_FORMAT_LUKS2; + } else if (memcmp(buf, rbd_layered_luks_header_verification, + RBD_ENCRYPTION_LUKS_HEADER_VERIFICATION_LEN) == 0) { + s->encryption_format = RBD_IMAGE_ENCRYPTION_FORMAT_LUKS; + } else if (memcmp(buf, rbd_layered_luks2_header_verification, + RBD_ENCRYPTION_LUKS_HEADER_VERIFICATION_LEN) == 0) { + s->encryption_format = RBD_IMAGE_ENCRYPTION_FORMAT_LUKS2; + } +} + /* FIXME Deprecate and remove keypairs or make it available in QMP. */ static int qemu_rbd_do_create(BlockdevCreateOptions *options, const char *keypairs, const char *password_secret, @@ -1134,17 +1189,18 @@ goto failed_open; } + s->encryption_format = RBD_IMAGE_ENCRYPTION_FORMAT__MAX; if (opts->encrypt) { #ifdef LIBRBD_SUPPORTS_ENCRYPTION if (opts->encrypt->parent) { #ifdef LIBRBD_SUPPORTS_ENCRYPTION_LOAD2 - r = qemu_rbd_encryption_load2(s->image, opts->encrypt, errp); + r = qemu_rbd_encryption_load2(bs, s->image, opts->encrypt, errp); #else r = -ENOTSUP; error_setg(errp, "RBD library does not support layered encryption"); #endif } else { - r = qemu_rbd_encryption_load(s->image, opts->encrypt, errp); + r = qemu_rbd_encryption_load(bs, s->image, opts->encrypt, errp); } if (r < 0) { goto failed_post_open; @@ -1154,6 +1210,8 @@ error_setg(errp, "RBD library does not support image encryption"); goto failed_post_open; #endif + } else { + qemu_rbd_encryption_probe(bs); } r = rbd_stat(s->image, &info, sizeof(info)); @@ -1413,17 +1471,6 @@ { BDRVRBDState *s = bs->opaque; ImageInfoSpecific *spec_info; - char buf[RBD_ENCRYPTION_LUKS_HEADER_VERIFICATION_LEN] = {0}; - int r; - - if (s->image_size >= RBD_ENCRYPTION_LUKS_HEADER_VERIFICATION_LEN) { - r = rbd_read(s->image, 0, - RBD_ENCRYPTION_LUKS_HEADER_VERIFICATION_LEN, buf); - if (r < 0) { - error_setg_errno(errp, -r, "cannot read image start for probe"); - return NULL; - } - } spec_info = g_new(ImageInfoSpecific, 1); *spec_info = (ImageInfoSpecific){ @@ -1431,28 +1478,13 @@ .u.rbd.data = g_new0(ImageInfoSpecificRbd, 1), }; - if (memcmp(buf, rbd_luks_header_verification, - RBD_ENCRYPTION_LUKS_HEADER_VERIFICATION_LEN) == 0) { - spec_info->u.rbd.data->encryption_format = - RBD_IMAGE_ENCRYPTION_FORMAT_LUKS; - spec_info->u.rbd.data->has_encryption_format = true; - } else if (memcmp(buf, rbd_luks2_header_verification, - RBD_ENCRYPTION_LUKS_HEADER_VERIFICATION_LEN) == 0) { - spec_info->u.rbd.data->encryption_format = - RBD_IMAGE_ENCRYPTION_FORMAT_LUKS2; - spec_info->u.rbd.data->has_encryption_format = true; - } else if (memcmp(buf, rbd_layered_luks_header_verification, - RBD_ENCRYPTION_LUKS_HEADER_VERIFICATION_LEN) == 0) { - spec_info->u.rbd.data->encryption_format = - RBD_IMAGE_ENCRYPTION_FORMAT_LUKS; - spec_info->u.rbd.data->has_encryption_format = true; - } else if (memcmp(buf, rbd_layered_luks2_header_verification, - RBD_ENCRYPTION_LUKS_HEADER_VERIFICATION_LEN) == 0) { - spec_info->u.rbd.data->encryption_format = - RBD_IMAGE_ENCRYPTION_FORMAT_LUKS2; - spec_info->u.rbd.data->has_encryption_format = true; + if (s->encryption_format == RBD_IMAGE_ENCRYPTION_FORMAT__MAX) { + assert(!bs->encrypted); } else { - spec_info->u.rbd.data->has_encryption_format = false; + ImageInfoSpecificRbd *rbd_info = spec_info->u.rbd.data; + + rbd_info->has_encryption_format = true; + rbd_info->encryption_format = s->encryption_format; } return spec_info; diff -Nru qemu-10.0.3+ds/contrib/elf2dmp/download.c qemu-10.0.6+ds/contrib/elf2dmp/download.c --- qemu-10.0.3+ds/contrib/elf2dmp/download.c 2025-07-23 21:05:28.000000000 +0000 +++ qemu-10.0.6+ds/contrib/elf2dmp/download.c 2025-10-20 18:13:45.000000000 +0000 @@ -27,8 +27,8 @@ if (curl_easy_setopt(curl, CURLOPT_URL, url) != CURLE_OK || curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, NULL) != CURLE_OK || curl_easy_setopt(curl, CURLOPT_WRITEDATA, file) != CURLE_OK - || curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1) != CURLE_OK - || curl_easy_setopt(curl, CURLOPT_NOPROGRESS, 0) != CURLE_OK + || curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L) != CURLE_OK + || curl_easy_setopt(curl, CURLOPT_NOPROGRESS, 0L) != CURLE_OK || curl_easy_perform(curl) != CURLE_OK) { unlink(name); fclose(file); diff -Nru qemu-10.0.3+ds/debian/changelog qemu-10.0.6+ds/debian/changelog --- qemu-10.0.3+ds/debian/changelog 2025-08-21 15:23:38.000000000 +0000 +++ qemu-10.0.6+ds/debian/changelog 2025-09-10 06:50:46.000000000 +0000 @@ -1,3 +1,194 @@ +qemu (1:10.0.6+ds-0+deb13u1) trixie; urgency=medium + + * new upstream stable/bugfix release: + - Update version for 10.0.6 release + - linux-user/microblaze: Fix little-endianness binary + - target/hppa: correct size bit parity for fmpyadd + - target/i386: user: do not set up a valid LDT on reset + - async: access bottom half flags with qatomic_read + - target/i386: fix x86_64 pushw op + - i386/tcg/smm_helper: Properly apply DR values on SMM entry / exit + - i386/cpu: Prevent delivering SIPI during SMM in TCG mode + - i386/kvm: Expose ARCH_CAP_FB_CLEAR when invulnerable to MDS + - target/i386: Fix CR2 handling for non-canonical addresses + - block/curl.c: Use explicit long constants in curl_easy_setopt calls + - pcie_sriov: Fix broken MMIO accesses from SR-IOV VFs + - target/riscv: rvv: Fix vslide1[up|down].vx unexpected result + when XLEN=32 and SEW=64 + - target/riscv: Fix ssamoswap error handling + - target/riscv: Fix SSP CSR error handling in VU/VS mode + - target/riscv: Fix the mepc when sspopchk triggers the exception + - target/arm: Don't set HCR.RW for AArch32 only CPUs + - pcie_sriov: make pcie_sriov_pf_exit() safe on non-SR-IOV devices + - docs/devel: Correct uefi-vars-x64 device name + - hid: fix incorrect return value for hid + - ui/gtk: Fix callback function signature + - ui/gtk: Consider scaling when propagating ui info + - Revert "i386/cpu: Move adjustment of CPUID_EXT_PDCM + before feature_dependencies[] check" + - Revert "target/i386: do not expose ARCH_CAPABILITIES on AMD CPU" + * new upstream stable/bugfix release: + - Update version for 10.0.5 release + - tests/functional/test_aarch64_sbsaref_freebsd: + Fix the URL of the ISO image + - tests/functional/test_ppc_bamboo: Replace broken link with working assets + - physmem: Destroy all CPU AddressSpaces on unrealize + - memory: New AS helper to serialize destroy+free + - include/system/memory.h: Clarify address_space_destroy() behaviour + - migration: Fix state transition in postcopy_start() error handling + - target/riscv: rvv: Modify minimum VLEN according to enabled + vector extensions + - target/riscv: rvv: Replace checking V by checking Zve32x + - target/riscv: Fix endianness swap on compressed instructions + - hw/riscv/riscv-iommu: Fixup PDT Nested Walk + - target/riscv: do not use translator_ldl in opcode_at + - target/riscv: use riscv_csrr in riscv_csr_read + - hw/char: sifive_uart: Raise IRQ according to the Tx/Rx + watermark thresholds + - docs/interop/firmware: Add riscv64 to FirmwareArchitecture + - hw/riscv/riscv-iommu: Fix MSI table size limit + - ui/icons/qemu.svg: Add metadata information (author, license) to the logo + - ui/spice: Fix abort on macOS + - ppc/spapr: init lrdr-capapcity phys with ram size if maxmem not provided + - hw/intc/xics: Add missing call to register vmstate_icp_server + - hw/usb/hcd-uhci: don't assert for SETUP to non-0 endpoint + Closes: #1082377 (CVE-2024-8354) + - tests/tcg/multiarch: Add tb-link test + - accel/tcg: Properly unlink a TB linked to itself + - tests: Fix "make check-functional" for targets without thorough tests + - .gitlab-ci.d/buildtest.yml: Unset CI_COMMIT_DESCRIPTION for htags + - tcg/optimize: Fix folding of vector bitsel + - hw/pci-host/astro: Don't call pci_regsiter_root_bus() in init + - hw/pci-host/dino: Don't call pci_register_root_bus() in init + - target/sparc: Relax decode of rs2_or_imm for v7 + - target/sparc: Loosen decode of RDTBR for v7 + - target/sparc: Loosen decode of RDWIM for v7 + - target/sparc: Loosen decode of RDPSR for v7 + - target/sparc: Loosen decode of RDY for v7 + - target/sparc: Loosen decode of STBAR for v8 + - target/sparc: Allow TRANS macro with no extra arguments + - linux-user: avoid -Werror=int-in-bool-context + - multiboot: Fix the split lock + - target/i386: Define enum X86ASIdx for x86's address spaces + - i386/cpu: Enable SMM cpu address space under KVM + - hw/usb/network: Remove hardcoded 0x40 prefix in STRING_ETHADDR response + - rust: hpet: fix new warning + - ci: run RISC-V cross jobs by default + - tests/docker/dockerfiles/python.docker: pull fedora:40 image + instead of fedora:latest + - .gitmodules: move u-boot mirrors to qemu-project-mirrors + - iotests/check: always enable all python warnings + - iotests/151: ensure subprocesses are cleaned up + - iotests/147: ensure temporary sockets are closed before exiting + - python: ensure QEMUQtestProtocol closes its socket + - iotests: drop compat for old version context manager + - python: backport 'avoid creating additional event loops per thread' + - python: backport 'Remove deprecated get_event_loop calls' + - python: backport 'qmp-tui: Do not crash if optional dependencies + are not met' + - python: backport 'qmp-shell-wrap: handle missing binary gracefully' + - python: backport 'Use @asynciocontextmanager' + - python: backport 'drop Python3.6 workarounds' + - python: backport 'kick event queue on legacy event_pull()' + - ui/vnc: Fix crash when specifying [vnc] without id in the config file + - target/loongarch: Guard 64-bit-only insn translation with TRANS64 macro + - target/loongarch: Add CRC feature flag and use it to gate CRC instructions + * new upstream stable/bugfix release: + - Update version for 10.0.4 release + - block/curl: fix curl internal handles handling + (Closes: #1111809) + - hw/gpio/pca9554: Avoid leak in pca9554_set_pin() + - hw/ppc: Fix build error with CONFIG_POWERNV disabled + - target/mips: fix TLB huge page check to use 64-bit shift + - linux-user/mips: Select M14Kc CPU to run microMIPS binaries + - linux-user/mips: Select 74Kf CPU to run MIPS16e binaries + - elf: Add EF_MIPS_ARCH_ASE definitions + - e1000e: Prevent crash from legacy interrupt firing after MSI-X enable + - Revert "tests/qtest: use qos_printf instead of g_test_message" + - vfio scsi ui: Error-check qio_channel_socket_connect_sync() the same way + - i386/kvm/vmsr_energy: Plug memory leak on failure to connect socket + - qga: Fix truncated output handling in guest-exec status reporting + - qga-vss: Write hex value of error in log + - qga/installer: Remove QGA VSS if QGA installation failed + - hw/arm/stm32f205_soc: Don't leak TYPE_OR_IRQ objects + - qemu/atomic: Finish renaming atomic128-cas.h headers + - scripts/kernel-doc: Avoid new Perl precedence warning + - target/arm: Trap PMCR when MDCR_EL2.TPMCR is set + - hw/intc/arm_gicv3_kvm: preserve pending interrupts during cpr + - linux-user: Add strace for rseq + - i386/tcg/svm: fix incorrect canonicalization + - python: mkvenv: fix messages printed by mkvenv + - hw/uefi: open json file in binary mode + - hw/uefi: check access for first variable + - hw/uefi: return success for notifications + - hw/uefi: clear uefi-vars buffer in uefi_vars_write callback + - mkvenv: Support pip 25.2 + - hw/sd/ssi-sd: Return noise (dummy byte) when no card connected + - qemu-iotests: Ignore indentation in Killed messages + - rbd: Fix .bdrv_get_specific_info implementation + - hw/nvme: cap MDTS value for internal limitation + - hw/nvme: revert CMIC behavior + - hw/nvme: fix namespace attachment + - target/loongarch: Fix [X]VLDI raising exception incorrectly + - ui/curses: Fix infinite loop on windows + - ppc/xive2: Fix treatment of PIPR in CPPR update + - ppc/xive2: Fix irq preempted by lower priority group irq + - ppc/xive2: Reset Generation Flipped bit on END Cache Watch + - ppc/xive: Fix PHYS NSR ring matching + - ppc/xive2: fix context push calculation of IPB priority + - ppc/xive2: Remote VSDs need to match on forwarding address + - ppc/xive2: Fix calculation of END queue sizes + - ppc/xive: Report access size in XIVE TM operation error logs + - ppc/xive: Fix xive trace event output + - target/i386/cpu: Move addressable ID encoding out of compat property + in CPUID[0x1] + - i386/cpu: Fix cpu number overflow in CPUID.01H.EBX[23:16] + - i386/cpu: Fix number of addressable IDs field for CPUID.01H.EBX[23:16] + - i386/cpu: Move adjustment of CPUID_EXT_PDCM before feature_dependencies[] + check + - Revert "i386/cpu: Fix cpu number overflow in CPUID.01H.EBX[23:16]" + (The 5 changes above Closes: #1095935 in 10.0.x) + - qga: correctly write to /sys/power/state on linux + (Closes: #1108387) + - scripts/make-release: Go back to cloning all the EDK2 submodules + - target/arm: add support for 64-bit PMCCNTR in AArch32 mode + - hw/ssi/aspeed_smc: Fix incorrect FMC_WDT2 register read on AST1030 + - target/arm: Fix handling of setting SVE registers from gdb + - target/arm: Fix big-endian handling of NEON gdb remote debugging + - hw/intc/arm_gicv3_kvm: Write all 1's to clear enable/active + - hw/i386/amd_iommu: Move IOAPIC memory region initialization to the end + - intel_iommu: Allow both Status Write and Interrupt Flag in QI wait + - pcie_sriov: Fix configuration and state synchronization + - virtio-net: Fix VLAN filter table reset timing + - vhost: Do not abort on log-stop error + - vhost: Do not abort on log-start error + - virtio: fix off-by-one and invalid access in virtqueue_ordered_fill + - target/loongarch: Fix valid virtual address checking + - target/riscv: Restrict midelegh access to S-mode harts + - target/riscv: Restrict mideleg/medeleg/medelegh access to S-mode harts + - intc/riscv_aplic: Fix target register read when source is inactive + - target/riscv: Fix pmp range wraparound on zero + - target/riscv: Fix exception type when VU accesses supervisor CSRs + - target/riscv: do not call GETPC() in check_ret_from_m_mode() + - linux-user/strace.list: add riscv_hwprobe entry + - roms/Makefile: fix npcmNxx_bootrom build rules + - system/physmem: fix use-after-free with dispatch + - hw/net/cadence_gem: fix register mask initialization + - target/mips: Only update MVPControl.EVP bit if executed by master VPE + - docs/user: clarify user-mode expects the same OS + - linux-user/aarch64: Support TPIDR2_MAGIC signal frame record + - linux-user/aarch64: Clear TPIDR2_EL0 when delivering signals + - target/i386: fix width of third operand of VINSERTx128 + - hw/display/qxl-render.c: fix qxl_unpack_chunks() chunk size calculation + - host-utils: Drop workaround for buggy Apple Clang __builtin_subcll() + * drop patches included upstream: + - hw-display-qxl-render.c-fix-qxl_unpack_chunks-chunk-.patch + - pcie_sriov-Fix-configuration-and-state-synchronizati.patch + - system-physmem-fix-use-after-free-with-dispatch.patch + * d/control.mk: 10.0.6+ds + + -- Michael Tokarev Wed, 10 Sep 2025 09:50:46 +0300 + qemu (1:10.0.3+ds-0+deb13u1) trixie; urgency=medium * new upstream stable/bugfix release: diff -Nru qemu-10.0.3+ds/debian/control.mk qemu-10.0.6+ds/debian/control.mk --- qemu-10.0.3+ds/debian/control.mk 2025-08-21 15:23:38.000000000 +0000 +++ qemu-10.0.6+ds/debian/control.mk 2025-09-10 06:50:46.000000000 +0000 @@ -9,7 +9,7 @@ # since some files and/or lists differ from version to version, # ensure we have the expected qemu version, or else scream loudly -checked-version := 10.0.3+ds +checked-version := 10.0.6+ds # version of last vdso change for d/control Depends field: vdso-version := 1:9.2.0~rc3+ds-1~ diff -Nru qemu-10.0.3+ds/debian/patches/hw-display-qxl-render.c-fix-qxl_unpack_chunks-chunk-.patch qemu-10.0.6+ds/debian/patches/hw-display-qxl-render.c-fix-qxl_unpack_chunks-chunk-.patch --- qemu-10.0.3+ds/debian/patches/hw-display-qxl-render.c-fix-qxl_unpack_chunks-chunk-.patch 2025-08-21 15:23:38.000000000 +0000 +++ qemu-10.0.6+ds/debian/patches/hw-display-qxl-render.c-fix-qxl_unpack_chunks-chunk-.patch 1970-01-01 00:00:00.000000000 +0000 @@ -1,51 +0,0 @@ -From: Michael Tokarev -Date: Fri, 21 Feb 2025 16:34:52 +0300 -Subject: hw/display/qxl-render.c: fix qxl_unpack_chunks() chunk size calculation -Forwarded: https://lore.kernel.org/qemu-devel/20250221134856.478806-1-mjt@tls.msk.ru/T/#u -Bug: https://gitlab.com/qemu-project/qemu/-/issues/1628 - -In case of multiple chunks, code in qxl_unpack_chunks() takes size of the -wrong (next in the chain) chunk, instead of using current chunk size. -This leads to wrong number of bytes being copied, and to crashes if next -chunk size is larger than the current one. - -Based on the code by Gao Yong. - -Resolves: https://gitlab.com/qemu-project/qemu/-/issues/1628 -Signed-off-by: Michael Tokarev ---- - hw/display/qxl-render.c | 11 ++++++++++- - 1 file changed, 10 insertions(+), 1 deletion(-) - -diff --git a/hw/display/qxl-render.c b/hw/display/qxl-render.c -index eda6d3de37..c6a9ac1da1 100644 ---- a/hw/display/qxl-render.c -+++ b/hw/display/qxl-render.c -@@ -222,6 +222,7 @@ static void qxl_unpack_chunks(void *dest, size_t size, PCIQXLDevice *qxl, - uint32_t max_chunks = 32; - size_t offset = 0; - size_t bytes; -+ QXLPHYSICAL next_chunk_phys = 0; - - for (;;) { - bytes = MIN(size - offset, chunk->data_size); -@@ -230,7 +231,15 @@ static void qxl_unpack_chunks(void *dest, size_t size, PCIQXLDevice *qxl, - if (offset == size) { - return; - } -- chunk = qxl_phys2virt(qxl, chunk->next_chunk, group_id, -+ next_chunk_phys = chunk->next_chunk; -+ /* fist time, only get the next chunk's data size */ -+ chunk = qxl_phys2virt(qxl, next_chunk_phys, group_id, -+ sizeof(QXLDataChunk)); -+ if (!chunk) { -+ return; -+ } -+ /* second time, check data size and get data */ -+ chunk = qxl_phys2virt(qxl, next_chunk_phys, group_id, - sizeof(QXLDataChunk) + chunk->data_size); - if (!chunk) { - return; --- -2.39.5 - diff -Nru qemu-10.0.3+ds/debian/patches/pcie_sriov-Fix-configuration-and-state-synchronizati.patch qemu-10.0.6+ds/debian/patches/pcie_sriov-Fix-configuration-and-state-synchronizati.patch --- qemu-10.0.3+ds/debian/patches/pcie_sriov-Fix-configuration-and-state-synchronizati.patch 2025-08-21 15:23:38.000000000 +0000 +++ qemu-10.0.6+ds/debian/patches/pcie_sriov-Fix-configuration-and-state-synchronizati.patch 1970-01-01 00:00:00.000000000 +0000 @@ -1,122 +0,0 @@ -From: Akihiko Odaki -Date: Sun, 27 Jul 2025 15:50:08 +0900 -Subject: pcie_sriov: Fix configuration and state synchronization -Origin: upstream, https://gitlab.com/qemu-project/qemu/-/commit/cad9aa6fbdccd95e56e10cfa57c354a20a333717 -Forwarded: not-needed -Bug-Debian: https://bugs.debian.org/1109989 - -Fix issues in PCIe SR-IOV configuration register handling that caused -inconsistent internal state due to improper write mask handling and -incorrect migration behavior. - -Two main problems were identified: - -1. VF Enable bit write mask handling: - pcie_sriov_config_write() incorrectly assumed that its val parameter - was already masked, causing it to ignore the actual write mask. - This led to the VF Enable bit being processed even when masked, - resulting in incorrect VF registration/unregistration. It is - identified as CVE-2025-54567. - -2. Migration state inconsistency: - pcie_sriov_pf_post_load() unconditionally called register_vfs() - regardless of the VF Enable bit state, creating inconsistent - internal state when VFs should not be enabled. Additionally, - it failed to properly update the NumVFs write mask based on - the current configuration. It is identified as CVE-2025-54566. - -Root cause analysis revealed that both functions relied on incorrect -special-case assumptions instead of properly reading and consuming -the actual configuration values. This change introduces a unified -consume_config() function that reads actual configuration values and -synchronize the internal state without special-case assumptions. - -The solution only adds register read overhead in non-hot-path code -while ensuring correct SR-IOV state management across configuration -writes and migration scenarios. - -Fixes: 5e7dd17e4348 ("pcie_sriov: Remove num_vfs from PCIESriovPF") -Fixes: f9efcd47110d ("pcie_sriov: Register VFs after migration") -Fixes: CVE-2025-54566 -Fixes: CVE-2025-54567 -Cc: qemu-stable@nongnu.org -Reported-by: Corentin BAYET -Signed-off-by: Akihiko Odaki -Message-Id: <20250727-wmask-v2-1-394910b1c0b6@rsg.ci.i.u-tokyo.ac.jp> -Reviewed-by: Michael S. Tsirkin -Signed-off-by: Michael S. Tsirkin -(cherry picked from commit cad9aa6fbdccd95e56e10cfa57c354a20a333717) -(Mjt: context fix) -Signed-off-by: Michael Tokarev ---- - hw/pci/pcie_sriov.c | 42 +++++++++++++++++++++++------------------- - 1 file changed, 23 insertions(+), 19 deletions(-) - -diff --git a/hw/pci/pcie_sriov.c b/hw/pci/pcie_sriov.c -index 1eb4358256..dd4fbaea46 100644 ---- a/hw/pci/pcie_sriov.c -+++ b/hw/pci/pcie_sriov.c -@@ -211,6 +211,27 @@ static void unregister_vfs(PCIDevice *dev) - pci_set_word(dev->wmask + dev->exp.sriov_cap + PCI_SRIOV_NUM_VF, 0xffff); - } - -+static void consume_config(PCIDevice *dev) -+{ -+ uint8_t *cfg = dev->config + dev->exp.sriov_cap; -+ -+ if (pci_get_word(cfg + PCI_SRIOV_CTRL) & PCI_SRIOV_CTRL_VFE) { -+ register_vfs(dev); -+ } else { -+ uint8_t *wmask = dev->wmask + dev->exp.sriov_cap; -+ uint16_t num_vfs = pci_get_word(cfg + PCI_SRIOV_NUM_VF); -+ uint16_t wmask_val = PCI_SRIOV_CTRL_MSE | PCI_SRIOV_CTRL_ARI; -+ -+ unregister_vfs(dev); -+ -+ if (num_vfs <= pci_get_word(cfg + PCI_SRIOV_TOTAL_VF)) { -+ wmask_val |= PCI_SRIOV_CTRL_VFE; -+ } -+ -+ pci_set_word(wmask + PCI_SRIOV_CTRL, wmask_val); -+ } -+} -+ - void pcie_sriov_config_write(PCIDevice *dev, uint32_t address, - uint32_t val, int len) - { -@@ -228,30 +249,13 @@ void pcie_sriov_config_write(PCIDevice *dev, uint32_t address, - trace_sriov_config_write(dev->name, PCI_SLOT(dev->devfn), - PCI_FUNC(dev->devfn), off, val, len); - -- if (range_covers_byte(off, len, PCI_SRIOV_CTRL)) { -- if (val & PCI_SRIOV_CTRL_VFE) { -- register_vfs(dev); -- } else { -- unregister_vfs(dev); -- } -- } else if (range_covers_byte(off, len, PCI_SRIOV_NUM_VF)) { -- uint8_t *cfg = dev->config + sriov_cap; -- uint8_t *wmask = dev->wmask + sriov_cap; -- uint16_t num_vfs = pci_get_word(cfg + PCI_SRIOV_NUM_VF); -- uint16_t wmask_val = PCI_SRIOV_CTRL_MSE | PCI_SRIOV_CTRL_ARI; -- -- if (num_vfs <= pci_get_word(cfg + PCI_SRIOV_TOTAL_VF)) { -- wmask_val |= PCI_SRIOV_CTRL_VFE; -- } -- -- pci_set_word(wmask + PCI_SRIOV_CTRL, wmask_val); -- } -+ consume_config(dev); - } - - void pcie_sriov_pf_post_load(PCIDevice *dev) - { - if (dev->exp.sriov_cap) { -- register_vfs(dev); -+ consume_config(dev); - } - } - --- -2.47.2 - diff -Nru qemu-10.0.3+ds/debian/patches/series qemu-10.0.6+ds/debian/patches/series --- qemu-10.0.3+ds/debian/patches/series 2025-08-21 15:23:38.000000000 +0000 +++ qemu-10.0.6+ds/debian/patches/series 2025-09-10 06:50:46.000000000 +0000 @@ -15,6 +15,3 @@ slof-ensure-ld-is-called-with-C-locale.patch qemu-img-options.patch disable-pycotap.patch -hw-display-qxl-render.c-fix-qxl_unpack_chunks-chunk-.patch -system-physmem-fix-use-after-free-with-dispatch.patch -pcie_sriov-Fix-configuration-and-state-synchronizati.patch diff -Nru qemu-10.0.3+ds/debian/patches/system-physmem-fix-use-after-free-with-dispatch.patch qemu-10.0.6+ds/debian/patches/system-physmem-fix-use-after-free-with-dispatch.patch --- qemu-10.0.3+ds/debian/patches/system-physmem-fix-use-after-free-with-dispatch.patch 2025-08-21 15:23:38.000000000 +0000 +++ qemu-10.0.6+ds/debian/patches/system-physmem-fix-use-after-free-with-dispatch.patch 1970-01-01 00:00:00.000000000 +0000 @@ -1,126 +0,0 @@ -From: Pierrick Bouvier -Subject: system/physmem: fix use-after-free with dispatch -Date: Thu, 24 Jul 2025 09:11:42 -0700 -Message-ID: <20250724161142.2803091-1-pierrick.bouvier@linaro.org> -MIME-Version: 1.0 -Content-Transfer-Encoding: 8bit -Bug-Debian: https://bugs.debian.org/1106792 -Origin: upstream, https://lore.kernel.org/qemu-devel/afddf3fc-5561-40b4-b61c-1301b079b0b8@tls.msk.ru/T/#t -Forwarded: not-needed - -A use-after-free bug was reported when booting a Linux kernel during the -pci setup phase. It's quite hard to reproduce (needs smp, and favored by -having several pci devices with BAR and specific Linux config, which -is Debian default one in this case). - -After investigation (see the associated bug ticket), it appears that, -under specific conditions, we might access a cached AddressSpaceDispatch -that was reclaimed by RCU thread meanwhile. -In the Linux boot scenario, during the pci phase, memory region are -destroyed/recreated, resulting in exposition of the bug. - -The core of the issue is that we cache the dispatch associated to -current cpu in cpu->cpu_ases[asidx].memory_dispatch. It is updated with -tcg_commit, which runs asynchronously on a given cpu. -At some point, we leave the rcu critial section, and the RCU thread -starts reclaiming it, but tcg_commit is not yet invoked, resulting in -the use-after-free. - -It's not the first problem around this area, and this patch [1] already -tried to address it. It did a good job, but it seems that we found a -specific situation where it's not enough. - -This patch takes a simple approach: remove the cached value creating the -issue, and make sure we always get the current mapping for address -space, using address_space_to_dispatch(cpu->cpu_ases[asidx].as). -It's equivalent to qatomic_rcu_read(&as->current_map)->dispatch; -This is not really costly, we just need two dereferences, -including one atomic (rcu) read, which is negligible considering we are -already on mmu slow path anyway. - -Note that tcg_commit is still needed, as it's taking care of flushing -TLB, removing previously mapped entries. - -Another solution would be to cache directly values under the dispatch -(dispatch themselves are not ref counted), keep an active reference on -associated memory section, and release it when appropriate (tricky). -Given the time already spent debugging this area now and previously, I -strongly prefer eliminating the root of the issue, instead of adding -more complexity for a hypothetical performance gain. RCU is precisely -used to ensure good performance when reading data, so caching is not as -beneficial as it might seem IMHO. - -[1] https://gitlab.com/qemu-project/qemu/-/commit/0d58c660689f6da1e3feff8a997014003d928b3b - -Resolves: https://gitlab.com/qemu-project/qemu/-/issues/3040 -Signed-off-by: Pierrick Bouvier -Reviewed-by: Richard Henderson -Reviewed-by: Michael Tokarev -Tested-by: Michael Tokarev ---- - system/physmem.c | 15 +++------------ - 1 file changed, 3 insertions(+), 12 deletions(-) - -diff --git a/system/physmem.c b/system/physmem.c -index 130c148ffb5..e5dd760e0bc 100644 ---- a/system/physmem.c -+++ b/system/physmem.c -@@ -165,13 +165,11 @@ static bool ram_is_cpr_compatible(RAMBlock *rb); - * CPUAddressSpace: all the information a CPU needs about an AddressSpace - * @cpu: the CPU whose AddressSpace this is - * @as: the AddressSpace itself -- * @memory_dispatch: its dispatch pointer (cached, RCU protected) - * @tcg_as_listener: listener for tracking changes to the AddressSpace - */ - typedef struct CPUAddressSpace { - CPUState *cpu; - AddressSpace *as; -- struct AddressSpaceDispatch *memory_dispatch; - MemoryListener tcg_as_listener; - } CPUAddressSpace; - -@@ -692,7 +690,7 @@ address_space_translate_for_iotlb(CPUState *cpu, int asidx, hwaddr orig_addr, - IOMMUTLBEntry iotlb; - int iommu_idx; - hwaddr addr = orig_addr; -- AddressSpaceDispatch *d = cpu->cpu_ases[asidx].memory_dispatch; -+ AddressSpaceDispatch *d = address_space_to_dispatch(cpu->cpu_ases[asidx].as); - - for (;;) { - section = address_space_translate_internal(d, addr, &addr, plen, false); -@@ -753,7 +751,7 @@ MemoryRegionSection *iotlb_to_section(CPUState *cpu, - { - int asidx = cpu_asidx_from_attrs(cpu, attrs); - CPUAddressSpace *cpuas = &cpu->cpu_ases[asidx]; -- AddressSpaceDispatch *d = cpuas->memory_dispatch; -+ AddressSpaceDispatch *d = address_space_to_dispatch(cpuas->as); - int section_index = index & ~TARGET_PAGE_MASK; - MemoryRegionSection *ret; - -@@ -2780,9 +2778,6 @@ static void tcg_log_global_after_sync(MemoryListener *listener) - - static void tcg_commit_cpu(CPUState *cpu, run_on_cpu_data data) - { -- CPUAddressSpace *cpuas = data.host_ptr; -- -- cpuas->memory_dispatch = address_space_to_dispatch(cpuas->as); - tlb_flush(cpu); - } - -@@ -2798,11 +2793,7 @@ static void tcg_commit(MemoryListener *listener) - cpu = cpuas->cpu; - - /* -- * Defer changes to as->memory_dispatch until the cpu is quiescent. -- * Otherwise we race between (1) other cpu threads and (2) ongoing -- * i/o for the current cpu thread, with data cached by mmu_lookup(). -- * -- * In addition, queueing the work function will kick the cpu back to -+ * Queueing the work function will kick the cpu back to - * the main loop, which will end the RCU critical section and reclaim - * the memory data structures. - * --- -2.47.2 - - diff -Nru qemu-10.0.3+ds/docs/devel/uefi-vars.rst qemu-10.0.6+ds/docs/devel/uefi-vars.rst --- qemu-10.0.3+ds/docs/devel/uefi-vars.rst 2025-07-23 21:05:28.000000000 +0000 +++ qemu-10.0.6+ds/docs/devel/uefi-vars.rst 2025-10-20 18:13:45.000000000 +0000 @@ -34,7 +34,7 @@ to process the requests. The ``uefi-vars`` device implements the UEFI virtual device. It comes -in ``uefi-vars-x86`` and ``uefi-vars-sysbus`` flavours. The device +in ``uefi-vars-x64`` and ``uefi-vars-sysbus`` flavours. The device reimplements the handlers needed, specifically ``EfiSmmVariableProtocol`` and ``VarCheckPolicyLibMmiHandler``. It also consumes events (``EfiEndOfDxeEventGroup``, @@ -57,7 +57,7 @@ .. code:: qemu-system-x86_64 \ - -device uefi-vars-x86,jsonfile=/path/to/vars.json + -device uefi-vars-x64,jsonfile=/path/to/vars.json usage on aarch64 ---------------- diff -Nru qemu-10.0.3+ds/docs/interop/firmware.json qemu-10.0.6+ds/docs/interop/firmware.json --- qemu-10.0.3+ds/docs/interop/firmware.json 2025-07-23 21:05:28.000000000 +0000 +++ qemu-10.0.6+ds/docs/interop/firmware.json 2025-10-20 18:13:45.000000000 +0000 @@ -76,12 +76,14 @@ # # @loongarch64: 64-bit LoongArch. (since: 7.1) # +# @riscv64: 64-bit RISC-V. +# # @x86_64: 64-bit x86. # # Since: 3.0 ## { 'enum' : 'FirmwareArchitecture', - 'data' : [ 'aarch64', 'arm', 'i386', 'loongarch64', 'x86_64' ] } + 'data' : [ 'aarch64', 'arm', 'i386', 'loongarch64', 'riscv64', 'x86_64' ] } ## # @FirmwareTarget: diff -Nru qemu-10.0.3+ds/docs/pcie_sriov.txt qemu-10.0.6+ds/docs/pcie_sriov.txt --- qemu-10.0.3+ds/docs/pcie_sriov.txt 2025-07-23 21:05:28.000000000 +0000 +++ qemu-10.0.6+ds/docs/pcie_sriov.txt 2025-10-20 18:13:45.000000000 +0000 @@ -72,8 +72,7 @@ 2) Similarly in the implementation of the virtual function, you need to make it a PCI Express device and add a similar set of capabilities except for the SR/IOV capability. Then you need to set up the VF BARs as - subregions of the PFs SR/IOV VF BARs by calling - pcie_sriov_vf_register_bar() instead of the normal pci_register_bar() call: + subregions of the PFs SR/IOV VF BARs by calling pci_register_bar(): pci_your_vf_dev_realize( ... ) { @@ -83,7 +82,7 @@ pcie_ari_init(d, 0x100); ... memory_region_init(mr, ... ) - pcie_sriov_vf_register_bar(d, bar_nr, mr); + pci_register_bar(d, bar_nr, bar_type, mr); ... } diff -Nru qemu-10.0.3+ds/docs/user/index.rst qemu-10.0.6+ds/docs/user/index.rst --- qemu-10.0.3+ds/docs/user/index.rst 2025-07-23 21:05:28.000000000 +0000 +++ qemu-10.0.6+ds/docs/user/index.rst 2025-10-20 18:13:45.000000000 +0000 @@ -5,8 +5,9 @@ ------------------- This section of the manual is the overall guide for users using QEMU -for user-mode emulation. In this mode, QEMU can launch -processes compiled for one CPU on another CPU. +for user-mode emulation. In this mode, QEMU can launch programs +compiled for one CPU architecture on the same Operating System (OS) +but running on a different CPU architecture. .. toctree:: :maxdepth: 2 diff -Nru qemu-10.0.3+ds/host/include/aarch64/host/atomic128-cas.h qemu-10.0.6+ds/host/include/aarch64/host/atomic128-cas.h --- qemu-10.0.3+ds/host/include/aarch64/host/atomic128-cas.h 2025-07-23 21:05:28.000000000 +0000 +++ qemu-10.0.6+ds/host/include/aarch64/host/atomic128-cas.h 1970-01-01 00:00:00.000000000 +0000 @@ -1,45 +0,0 @@ -/* - * SPDX-License-Identifier: GPL-2.0-or-later - * Compare-and-swap for 128-bit atomic operations, AArch64 version. - * - * Copyright (C) 2018, 2023 Linaro, Ltd. - * - * See docs/devel/atomics.rst for discussion about the guarantees each - * atomic primitive is meant to provide. - */ - -#ifndef AARCH64_ATOMIC128_CAS_H -#define AARCH64_ATOMIC128_CAS_H - -/* Through gcc 10, aarch64 has no support for 128-bit atomics. */ -#if defined(CONFIG_ATOMIC128) || defined(CONFIG_CMPXCHG128) -#include "host/include/generic/host/atomic128-cas.h.inc" -#else -static inline Int128 atomic16_cmpxchg(Int128 *ptr, Int128 cmp, Int128 new) -{ - uint64_t cmpl = int128_getlo(cmp), cmph = int128_gethi(cmp); - uint64_t newl = int128_getlo(new), newh = int128_gethi(new); - uint64_t oldl, oldh; - uint32_t tmp; - - asm("0: ldaxp %[oldl], %[oldh], %[mem]\n\t" - "cmp %[oldl], %[cmpl]\n\t" - "ccmp %[oldh], %[cmph], #0, eq\n\t" - "b.ne 1f\n\t" - "stlxp %w[tmp], %[newl], %[newh], %[mem]\n\t" - "cbnz %w[tmp], 0b\n" - "1:" - : [mem] "+m"(*ptr), [tmp] "=&r"(tmp), - [oldl] "=&r"(oldl), [oldh] "=&r"(oldh) - : [cmpl] "r"(cmpl), [cmph] "r"(cmph), - [newl] "r"(newl), [newh] "r"(newh) - : "memory", "cc"); - - return int128_make128(oldl, oldh); -} - -# define CONFIG_CMPXCHG128 1 -# define HAVE_CMPXCHG128 1 -#endif - -#endif /* AARCH64_ATOMIC128_CAS_H */ diff -Nru qemu-10.0.3+ds/host/include/aarch64/host/atomic128-cas.h.inc qemu-10.0.6+ds/host/include/aarch64/host/atomic128-cas.h.inc --- qemu-10.0.3+ds/host/include/aarch64/host/atomic128-cas.h.inc 1970-01-01 00:00:00.000000000 +0000 +++ qemu-10.0.6+ds/host/include/aarch64/host/atomic128-cas.h.inc 2025-10-20 18:13:45.000000000 +0000 @@ -0,0 +1,45 @@ +/* + * SPDX-License-Identifier: GPL-2.0-or-later + * Compare-and-swap for 128-bit atomic operations, AArch64 version. + * + * Copyright (C) 2018, 2023 Linaro, Ltd. + * + * See docs/devel/atomics.rst for discussion about the guarantees each + * atomic primitive is meant to provide. + */ + +#ifndef AARCH64_ATOMIC128_CAS_H +#define AARCH64_ATOMIC128_CAS_H + +/* Through gcc 10, aarch64 has no support for 128-bit atomics. */ +#if defined(CONFIG_ATOMIC128) || defined(CONFIG_CMPXCHG128) +#include "host/include/generic/host/atomic128-cas.h.inc" +#else +static inline Int128 atomic16_cmpxchg(Int128 *ptr, Int128 cmp, Int128 new) +{ + uint64_t cmpl = int128_getlo(cmp), cmph = int128_gethi(cmp); + uint64_t newl = int128_getlo(new), newh = int128_gethi(new); + uint64_t oldl, oldh; + uint32_t tmp; + + asm("0: ldaxp %[oldl], %[oldh], %[mem]\n\t" + "cmp %[oldl], %[cmpl]\n\t" + "ccmp %[oldh], %[cmph], #0, eq\n\t" + "b.ne 1f\n\t" + "stlxp %w[tmp], %[newl], %[newh], %[mem]\n\t" + "cbnz %w[tmp], 0b\n" + "1:" + : [mem] "+m"(*ptr), [tmp] "=&r"(tmp), + [oldl] "=&r"(oldl), [oldh] "=&r"(oldh) + : [cmpl] "r"(cmpl), [cmph] "r"(cmph), + [newl] "r"(newl), [newh] "r"(newh) + : "memory", "cc"); + + return int128_make128(oldl, oldh); +} + +# define CONFIG_CMPXCHG128 1 +# define HAVE_CMPXCHG128 1 +#endif + +#endif /* AARCH64_ATOMIC128_CAS_H */ diff -Nru qemu-10.0.3+ds/hw/arm/stm32f205_soc.c qemu-10.0.6+ds/hw/arm/stm32f205_soc.c --- qemu-10.0.3+ds/hw/arm/stm32f205_soc.c 2025-07-23 21:05:28.000000000 +0000 +++ qemu-10.0.6+ds/hw/arm/stm32f205_soc.c 2025-10-20 18:13:45.000000000 +0000 @@ -66,7 +66,7 @@ TYPE_STM32F2XX_TIMER); } - s->adc_irqs = OR_IRQ(object_new(TYPE_OR_IRQ)); + object_initialize_child(obj, "adc-irq-orgate", &s->adc_irqs, TYPE_OR_IRQ); for (i = 0; i < STM_NUM_ADCS; i++) { object_initialize_child(obj, "adc[*]", &s->adc[i], TYPE_STM32F2XX_ADC); @@ -171,12 +171,12 @@ } /* ADC 1 to 3 */ - object_property_set_int(OBJECT(s->adc_irqs), "num-lines", STM_NUM_ADCS, + object_property_set_int(OBJECT(&s->adc_irqs), "num-lines", STM_NUM_ADCS, &error_abort); - if (!qdev_realize(DEVICE(s->adc_irqs), NULL, errp)) { + if (!qdev_realize(DEVICE(&s->adc_irqs), NULL, errp)) { return; } - qdev_connect_gpio_out(DEVICE(s->adc_irqs), 0, + qdev_connect_gpio_out(DEVICE(&s->adc_irqs), 0, qdev_get_gpio_in(armv7m, ADC_IRQ)); for (i = 0; i < STM_NUM_ADCS; i++) { @@ -187,7 +187,7 @@ busdev = SYS_BUS_DEVICE(dev); sysbus_mmio_map(busdev, 0, adc_addr[i]); sysbus_connect_irq(busdev, 0, - qdev_get_gpio_in(DEVICE(s->adc_irqs), i)); + qdev_get_gpio_in(DEVICE(&s->adc_irqs), i)); } /* SPI 1 and 2 */ diff -Nru qemu-10.0.3+ds/hw/char/sifive_uart.c qemu-10.0.6+ds/hw/char/sifive_uart.c --- qemu-10.0.3+ds/hw/char/sifive_uart.c 2025-07-23 21:05:28.000000000 +0000 +++ qemu-10.0.6+ds/hw/char/sifive_uart.c 2025-10-20 18:13:45.000000000 +0000 @@ -35,16 +35,17 @@ */ /* Returns the state of the IP (interrupt pending) register */ -static uint64_t sifive_uart_ip(SiFiveUARTState *s) +static uint32_t sifive_uart_ip(SiFiveUARTState *s) { - uint64_t ret = 0; + uint32_t ret = 0; - uint64_t txcnt = SIFIVE_UART_GET_TXCNT(s->txctrl); - uint64_t rxcnt = SIFIVE_UART_GET_RXCNT(s->rxctrl); + uint32_t txcnt = SIFIVE_UART_GET_TXCNT(s->txctrl); + uint32_t rxcnt = SIFIVE_UART_GET_RXCNT(s->rxctrl); - if (txcnt != 0) { + if (fifo8_num_used(&s->tx_fifo) < txcnt) { ret |= SIFIVE_UART_IP_TXWM; } + if (s->rx_fifo_len > rxcnt) { ret |= SIFIVE_UART_IP_RXWM; } @@ -55,15 +56,14 @@ static void sifive_uart_update_irq(SiFiveUARTState *s) { int cond = 0; - if ((s->ie & SIFIVE_UART_IE_TXWM) || - ((s->ie & SIFIVE_UART_IE_RXWM) && s->rx_fifo_len)) { + uint32_t ip = sifive_uart_ip(s); + + if (((ip & SIFIVE_UART_IP_TXWM) && (s->ie & SIFIVE_UART_IE_TXWM)) || + ((ip & SIFIVE_UART_IP_RXWM) && (s->ie & SIFIVE_UART_IE_RXWM))) { cond = 1; } - if (cond) { - qemu_irq_raise(s->irq); - } else { - qemu_irq_lower(s->irq); - } + + qemu_set_irq(s->irq, cond); } static gboolean sifive_uart_xmit(void *do_not_use, GIOCondition cond, diff -Nru qemu-10.0.3+ds/hw/core/cpu-common.c qemu-10.0.6+ds/hw/core/cpu-common.c --- qemu-10.0.3+ds/hw/core/cpu-common.c 2025-07-23 21:05:28.000000000 +0000 +++ qemu-10.0.6+ds/hw/core/cpu-common.c 2025-10-20 18:13:45.000000000 +0000 @@ -248,6 +248,7 @@ * accel_cpu_common_unrealize, which may free fields using call_rcu. */ accel_cpu_common_unrealize(cpu); + cpu_destroy_address_spaces(cpu); } static void cpu_common_initfn(Object *obj) diff -Nru qemu-10.0.3+ds/hw/display/qxl-render.c qemu-10.0.6+ds/hw/display/qxl-render.c --- qemu-10.0.3+ds/hw/display/qxl-render.c 2025-07-23 21:05:28.000000000 +0000 +++ qemu-10.0.6+ds/hw/display/qxl-render.c 2025-10-20 18:13:45.000000000 +0000 @@ -222,6 +222,7 @@ uint32_t max_chunks = 32; size_t offset = 0; size_t bytes; + QXLPHYSICAL next_chunk_phys = 0; for (;;) { bytes = MIN(size - offset, chunk->data_size); @@ -230,7 +231,15 @@ if (offset == size) { return; } - chunk = qxl_phys2virt(qxl, chunk->next_chunk, group_id, + next_chunk_phys = chunk->next_chunk; + /* fist time, only get the next chunk's data size */ + chunk = qxl_phys2virt(qxl, next_chunk_phys, group_id, + sizeof(QXLDataChunk)); + if (!chunk) { + return; + } + /* second time, check data size and get data */ + chunk = qxl_phys2virt(qxl, next_chunk_phys, group_id, sizeof(QXLDataChunk) + chunk->data_size); if (!chunk) { return; diff -Nru qemu-10.0.3+ds/hw/gpio/pca9554.c qemu-10.0.6+ds/hw/gpio/pca9554.c --- qemu-10.0.3+ds/hw/gpio/pca9554.c 2025-07-23 21:05:28.000000000 +0000 +++ qemu-10.0.6+ds/hw/gpio/pca9554.c 2025-10-20 18:13:45.000000000 +0000 @@ -177,7 +177,7 @@ PCA9554State *s = PCA9554(obj); int pin, rc, val; uint8_t state, mask; - char *state_str; + g_autofree char *state_str = NULL; if (!visit_type_str(v, name, &state_str, errp)) { return; diff -Nru qemu-10.0.3+ds/hw/i386/amd_iommu.c qemu-10.0.6+ds/hw/i386/amd_iommu.c --- qemu-10.0.3+ds/hw/i386/amd_iommu.c 2025-07-23 21:05:28.000000000 +0000 +++ qemu-10.0.6+ds/hw/i386/amd_iommu.c 2025-10-20 18:13:45.000000000 +0000 @@ -1620,9 +1620,6 @@ return; } - /* Pseudo address space under root PCI bus. */ - x86ms->ioapic_as = amdvi_host_dma_iommu(bus, s, AMDVI_IOAPIC_SB_DEVID); - /* set up MMIO */ memory_region_init_io(&s->mr_mmio, OBJECT(s), &mmio_mem_ops, s, "amdvi-mmio", AMDVI_MMIO_SIZE); @@ -1645,6 +1642,9 @@ memory_region_add_subregion_overlap(&s->mr_sys, AMDVI_INT_ADDR_FIRST, &s->mr_ir, 1); + /* Pseudo address space under root PCI bus. */ + x86ms->ioapic_as = amdvi_host_dma_iommu(bus, s, AMDVI_IOAPIC_SB_DEVID); + if (kvm_enabled() && x86ms->apic_id_limit > 255 && !s->xtsup) { error_report("AMD IOMMU with x2APIC configuration requires xtsup=on"); exit(EXIT_FAILURE); diff -Nru qemu-10.0.3+ds/hw/i386/intel_iommu.c qemu-10.0.6+ds/hw/i386/intel_iommu.c --- qemu-10.0.3+ds/hw/i386/intel_iommu.c 2025-07-23 21:05:28.000000000 +0000 +++ qemu-10.0.6+ds/hw/i386/intel_iommu.c 2025-10-20 18:13:45.000000000 +0000 @@ -2830,6 +2830,7 @@ { uint64_t mask[4] = {VTD_INV_DESC_WAIT_RSVD_LO, VTD_INV_DESC_WAIT_RSVD_HI, VTD_INV_DESC_ALL_ONE, VTD_INV_DESC_ALL_ONE}; + bool ret = true; if (!vtd_inv_desc_reserved_check(s, inv_desc, mask, false, __func__, "wait")) { @@ -2841,8 +2842,6 @@ uint32_t status_data = (uint32_t)(inv_desc->lo >> VTD_INV_DESC_WAIT_DATA_SHIFT); - assert(!(inv_desc->lo & VTD_INV_DESC_WAIT_IF)); - /* FIXME: need to be masked with HAW? */ dma_addr_t status_addr = inv_desc->hi; trace_vtd_inv_desc_wait_sw(status_addr, status_data); @@ -2851,18 +2850,22 @@ &status_data, sizeof(status_data), MEMTXATTRS_UNSPECIFIED)) { trace_vtd_inv_desc_wait_write_fail(inv_desc->hi, inv_desc->lo); - return false; + ret = false; } - } else if (inv_desc->lo & VTD_INV_DESC_WAIT_IF) { + } + + if (inv_desc->lo & VTD_INV_DESC_WAIT_IF) { /* Interrupt flag */ vtd_generate_completion_event(s); - } else { + } + + if (!(inv_desc->lo & (VTD_INV_DESC_WAIT_IF | VTD_INV_DESC_WAIT_SW))) { error_report_once("%s: invalid wait desc: hi=%"PRIx64", lo=%"PRIx64 " (unknown type)", __func__, inv_desc->hi, inv_desc->lo); return false; } - return true; + return ret; } static bool vtd_process_context_cache_desc(IntelIOMMUState *s, diff -Nru qemu-10.0.3+ds/hw/input/hid.c qemu-10.0.6+ds/hw/input/hid.c --- qemu-10.0.3+ds/hw/input/hid.c 2025-07-23 21:05:28.000000000 +0000 +++ qemu-10.0.6+ds/hw/input/hid.c 2025-10-20 18:13:45.000000000 +0000 @@ -478,6 +478,7 @@ ledstate |= QEMU_CAPS_LOCK_LED; } kbd_put_ledstate(ledstate); + return 1; } return 0; } diff -Nru qemu-10.0.3+ds/hw/intc/apic.c qemu-10.0.6+ds/hw/intc/apic.c --- qemu-10.0.3+ds/hw/intc/apic.c 2025-07-23 21:05:28.000000000 +0000 +++ qemu-10.0.6+ds/hw/intc/apic.c 2025-10-20 18:13:45.000000000 +0000 @@ -645,8 +645,6 @@ { APICCommonState *s = APIC(dev); - cpu_reset_interrupt(CPU(s->cpu), CPU_INTERRUPT_SIPI); - if (!s->wait_for_sipi) return; cpu_x86_load_seg_cache_sipi(s->cpu, s->sipi_vector); diff -Nru qemu-10.0.3+ds/hw/intc/arm_gicv3_kvm.c qemu-10.0.6+ds/hw/intc/arm_gicv3_kvm.c --- qemu-10.0.3+ds/hw/intc/arm_gicv3_kvm.c 2025-07-23 21:05:28.000000000 +0000 +++ qemu-10.0.6+ds/hw/intc/arm_gicv3_kvm.c 2025-10-20 18:13:45.000000000 +0000 @@ -30,6 +30,7 @@ #include "gicv3_internal.h" #include "vgic_common.h" #include "migration/blocker.h" +#include "migration/misc.h" #include "qom/object.h" #include "target/arm/cpregs.h" @@ -294,7 +295,7 @@ * the 1 bits. */ if (clroffset != 0) { - reg = 0; + reg = ~0; kvm_gicd_access(s, clroffset, ®, true); clroffset += 4; } @@ -777,6 +778,17 @@ } } +static int kvm_arm_gicv3_notifier(NotifierWithReturn *notifier, + MigrationEvent *e, Error **errp) +{ + if (e->type == MIG_EVENT_PRECOPY_DONE) { + GICv3State *s = container_of(notifier, GICv3State, cpr_notifier); + return kvm_device_access(s->dev_fd, KVM_DEV_ARM_VGIC_GRP_CTRL, + KVM_DEV_ARM_VGIC_SAVE_PENDING_TABLES, + NULL, true, errp); + } + return 0; +} static void kvm_arm_gicv3_realize(DeviceState *dev, Error **errp) { @@ -890,6 +902,9 @@ if (kvm_device_check_attr(s->dev_fd, KVM_DEV_ARM_VGIC_GRP_CTRL, KVM_DEV_ARM_VGIC_SAVE_PENDING_TABLES)) { qemu_add_vm_change_state_handler(vm_change_state_handler, s); + migration_add_notifier_mode(&s->cpr_notifier, + kvm_arm_gicv3_notifier, + MIG_MODE_CPR_TRANSFER); } } diff -Nru qemu-10.0.3+ds/hw/intc/pnv_xive2.c qemu-10.0.6+ds/hw/intc/pnv_xive2.c --- qemu-10.0.3+ds/hw/intc/pnv_xive2.c 2025-07-23 21:05:28.000000000 +0000 +++ qemu-10.0.6+ds/hw/intc/pnv_xive2.c 2025-10-20 18:13:45.000000000 +0000 @@ -101,12 +101,10 @@ } /* - * Remote access to controllers. HW uses MMIOs. For now, a simple scan - * of the chips is good enough. - * - * TODO: Block scope support + * Remote access to INT controllers. HW uses MMIOs(?). For now, a simple + * scan of all the chips INT controller is good enough. */ -static PnvXive2 *pnv_xive2_get_remote(uint8_t blk) +static PnvXive2 *pnv_xive2_get_remote(uint32_t vsd_type, hwaddr fwd_addr) { PnvMachineState *pnv = PNV_MACHINE(qdev_get_machine()); int i; @@ -115,10 +113,23 @@ Pnv10Chip *chip10 = PNV10_CHIP(pnv->chips[i]); PnvXive2 *xive = &chip10->xive; - if (pnv_xive2_block_id(xive) == blk) { + /* + * Is this the XIVE matching the forwarded VSD address is for this + * VSD type + */ + if ((vsd_type == VST_ESB && fwd_addr == xive->esb_base) || + (vsd_type == VST_END && fwd_addr == xive->end_base) || + ((vsd_type == VST_NVP || + vsd_type == VST_NVG) && fwd_addr == xive->nvpg_base) || + (vsd_type == VST_NVC && fwd_addr == xive->nvc_base)) { return xive; } } + + qemu_log_mask(LOG_GUEST_ERROR, + "XIVE: >>>>> %s vsd_type %u fwd_addr 0x%"HWADDR_PRIx + " NOT FOUND\n", + __func__, vsd_type, fwd_addr); return NULL; } @@ -251,8 +262,7 @@ /* Remote VST access */ if (GETFIELD(VSD_MODE, vsd) == VSD_MODE_FORWARD) { - xive = pnv_xive2_get_remote(blk); - + xive = pnv_xive2_get_remote(type, (vsd & VSD_ADDRESS_MASK)); return xive ? pnv_xive2_vst_addr(xive, type, blk, idx) : 0; } @@ -1315,10 +1325,11 @@ case VC_ENDC_WATCH3_DATA0: /* * Load DATA registers from cache with data requested by the - * SPEC register + * SPEC register. Clear gen_flipped bit in word 1. */ watch_engine = (offset - VC_ENDC_WATCH0_DATA0) >> 6; pnv_xive2_end_cache_load(xive, watch_engine); + xive->vc_regs[reg] &= ~(uint64_t)END2_W1_GEN_FLIPPED; val = xive->vc_regs[reg]; break; diff -Nru qemu-10.0.3+ds/hw/intc/riscv_aplic.c qemu-10.0.6+ds/hw/intc/riscv_aplic.c --- qemu-10.0.3+ds/hw/intc/riscv_aplic.c 2025-07-23 21:05:28.000000000 +0000 +++ qemu-10.0.6+ds/hw/intc/riscv_aplic.c 2025-10-20 18:13:45.000000000 +0000 @@ -628,7 +628,7 @@ static uint64_t riscv_aplic_read(void *opaque, hwaddr addr, unsigned size) { - uint32_t irq, word, idc; + uint32_t irq, word, idc, sm; RISCVAPLICState *aplic = opaque; /* Reads must be 4 byte words */ @@ -696,6 +696,10 @@ } else if ((APLIC_TARGET_BASE <= addr) && (addr < (APLIC_TARGET_BASE + (aplic->num_irqs - 1) * 4))) { irq = ((addr - APLIC_TARGET_BASE) >> 2) + 1; + sm = aplic->sourcecfg[irq] & APLIC_SOURCECFG_SM_MASK; + if (sm == APLIC_SOURCECFG_SM_INACTIVE) { + return 0; + } return aplic->target[irq]; } else if (!aplic->msimode && (APLIC_IDC_BASE <= addr) && (addr < (APLIC_IDC_BASE + aplic->num_harts * APLIC_IDC_SIZE))) { diff -Nru qemu-10.0.3+ds/hw/intc/trace-events qemu-10.0.6+ds/hw/intc/trace-events --- qemu-10.0.3+ds/hw/intc/trace-events 2025-07-23 21:05:28.000000000 +0000 +++ qemu-10.0.6+ds/hw/intc/trace-events 2025-10-20 18:13:45.000000000 +0000 @@ -274,9 +274,9 @@ kvm_xive_source_reset(uint32_t srcno) "IRQ 0x%x" # xive.c -xive_tctx_accept(uint32_t index, uint8_t ring, uint8_t ipb, uint8_t pipr, uint8_t cppr, uint8_t nsr) "target=%d ring=0x%x IBP=0x%02x PIPR=0x%02x CPPR=0x%02x NSR=0x%02x ACK" -xive_tctx_notify(uint32_t index, uint8_t ring, uint8_t ipb, uint8_t pipr, uint8_t cppr, uint8_t nsr) "target=%d ring=0x%x IBP=0x%02x PIPR=0x%02x CPPR=0x%02x NSR=0x%02x raise !" -xive_tctx_set_cppr(uint32_t index, uint8_t ring, uint8_t ipb, uint8_t pipr, uint8_t cppr, uint8_t nsr) "target=%d ring=0x%x IBP=0x%02x PIPR=0x%02x new CPPR=0x%02x NSR=0x%02x" +xive_tctx_accept(uint32_t index, uint8_t ring, uint8_t ipb, uint8_t pipr, uint8_t cppr, uint8_t nsr) "target=%d ring=0x%x IPB=0x%02x PIPR=0x%02x CPPR=0x%02x NSR=0x%02x ACK" +xive_tctx_notify(uint32_t index, uint8_t ring, uint8_t ipb, uint8_t pipr, uint8_t cppr, uint8_t nsr) "target=%d ring=0x%x IPB=0x%02x PIPR=0x%02x CPPR=0x%02x NSR=0x%02x raise !" +xive_tctx_set_cppr(uint32_t index, uint8_t ring, uint8_t ipb, uint8_t pipr, uint8_t cppr, uint8_t nsr) "target=%d ring=0x%x IPB=0x%02x PIPR=0x%02x new CPPR=0x%02x NSR=0x%02x" xive_source_esb_read(uint64_t addr, uint32_t srcno, uint64_t value) "@0x%"PRIx64" IRQ 0x%x val=0x%"PRIx64 xive_source_esb_write(uint64_t addr, uint32_t srcno, uint64_t value) "@0x%"PRIx64" IRQ 0x%x val=0x%"PRIx64 xive_router_end_notify(uint8_t end_blk, uint32_t end_idx, uint32_t end_data) "END 0x%02x/0x%04x -> enqueue 0x%08x" diff -Nru qemu-10.0.3+ds/hw/intc/xics.c qemu-10.0.6+ds/hw/intc/xics.c --- qemu-10.0.3+ds/hw/intc/xics.c 2025-07-23 21:05:28.000000000 +0000 +++ qemu-10.0.6+ds/hw/intc/xics.c 2025-10-20 18:13:45.000000000 +0000 @@ -335,6 +335,8 @@ return; } } + + vmstate_register(NULL, icp->cs->cpu_index, &vmstate_icp_server, icp); } static void icp_unrealize(DeviceState *dev) diff -Nru qemu-10.0.3+ds/hw/intc/xive.c qemu-10.0.6+ds/hw/intc/xive.c --- qemu-10.0.3+ds/hw/intc/xive.c 2025-07-23 21:05:28.000000000 +0000 +++ qemu-10.0.6+ds/hw/intc/xive.c 2025-10-20 18:13:45.000000000 +0000 @@ -54,7 +54,8 @@ uint8_t *alt_regs; /* POOL interrupt uses IPB in QW2, POOL ring */ - if ((ring == TM_QW3_HV_PHYS) && (nsr & (TM_QW3_NSR_HE_POOL << 6))) { + if ((ring == TM_QW3_HV_PHYS) && + ((nsr & TM_QW3_NSR_HE) == (TM_QW3_NSR_HE_POOL << 6))) { alt_ring = TM_QW2_HV_POOL; } else { alt_ring = ring; @@ -326,7 +327,7 @@ */ if (size < 4 || !mask || ring_offset == TM_QW0_USER) { qemu_log_mask(LOG_GUEST_ERROR, "XIVE: invalid write access at TIMA @%" - HWADDR_PRIx"\n", offset); + HWADDR_PRIx" size %d\n", offset, size); return; } @@ -357,7 +358,7 @@ */ if (size < 4 || !mask || ring_offset == TM_QW0_USER) { qemu_log_mask(LOG_GUEST_ERROR, "XIVE: invalid read access at TIMA @%" - HWADDR_PRIx"\n", offset); + HWADDR_PRIx" size %d\n", offset, size); return -1; } @@ -688,7 +689,7 @@ xto = xive_tm_find_op(tctx->xptr, offset, size, true); if (!xto) { qemu_log_mask(LOG_GUEST_ERROR, "XIVE: invalid write access at TIMA " - "@%"HWADDR_PRIx"\n", offset); + "@%"HWADDR_PRIx" size %d\n", offset, size); } else { xto->write_handler(xptr, tctx, offset, value, size); } @@ -727,7 +728,7 @@ xto = xive_tm_find_op(tctx->xptr, offset, size, false); if (!xto) { qemu_log_mask(LOG_GUEST_ERROR, "XIVE: invalid read access to TIMA" - "@%"HWADDR_PRIx"\n", offset); + "@%"HWADDR_PRIx" size %d\n", offset, size); return -1; } ret = xto->read_handler(xptr, tctx, offset, size); diff -Nru qemu-10.0.3+ds/hw/intc/xive2.c qemu-10.0.6+ds/hw/intc/xive2.c --- qemu-10.0.3+ds/hw/intc/xive2.c 2025-07-23 21:05:28.000000000 +0000 +++ qemu-10.0.6+ds/hw/intc/xive2.c 2025-10-20 18:13:45.000000000 +0000 @@ -188,12 +188,27 @@ (uint32_t) xive_get_field64(EAS2_END_DATA, eas->w)); } +#define XIVE2_QSIZE_CHUNK_CL 128 +#define XIVE2_QSIZE_CHUNK_4k 4096 +/* Calculate max number of queue entries for an END */ +static uint32_t xive2_end_get_qentries(Xive2End *end) +{ + uint32_t w3 = end->w3; + uint32_t qsize = xive_get_field32(END2_W3_QSIZE, w3); + if (xive_get_field32(END2_W3_CL, w3)) { + g_assert(qsize <= 4); + return (XIVE2_QSIZE_CHUNK_CL << qsize) / sizeof(uint32_t); + } else { + g_assert(qsize <= 12); + return (XIVE2_QSIZE_CHUNK_4k << qsize) / sizeof(uint32_t); + } +} + void xive2_end_queue_pic_print_info(Xive2End *end, uint32_t width, GString *buf) { uint64_t qaddr_base = xive2_end_qaddr(end); - uint32_t qsize = xive_get_field32(END2_W3_QSIZE, end->w3); uint32_t qindex = xive_get_field32(END2_W1_PAGE_OFF, end->w1); - uint32_t qentries = 1 << (qsize + 10); + uint32_t qentries = xive2_end_get_qentries(end); int i; /* @@ -223,8 +238,7 @@ uint64_t qaddr_base = xive2_end_qaddr(end); uint32_t qindex = xive_get_field32(END2_W1_PAGE_OFF, end->w1); uint32_t qgen = xive_get_field32(END2_W1_GENERATION, end->w1); - uint32_t qsize = xive_get_field32(END2_W3_QSIZE, end->w3); - uint32_t qentries = 1 << (qsize + 10); + uint32_t qentries = xive2_end_get_qentries(end); uint32_t nvx_blk = xive_get_field32(END2_W6_VP_BLOCK, end->w6); uint32_t nvx_idx = xive_get_field32(END2_W6_VP_OFFSET, end->w6); @@ -341,13 +355,12 @@ static void xive2_end_enqueue(Xive2End *end, uint32_t data) { uint64_t qaddr_base = xive2_end_qaddr(end); - uint32_t qsize = xive_get_field32(END2_W3_QSIZE, end->w3); uint32_t qindex = xive_get_field32(END2_W1_PAGE_OFF, end->w1); uint32_t qgen = xive_get_field32(END2_W1_GENERATION, end->w1); uint64_t qaddr = qaddr_base + (qindex << 2); uint32_t qdata = cpu_to_be32((qgen << 31) | (data & 0x7fffffff)); - uint32_t qentries = 1 << (qsize + 10); + uint32_t qentries = xive2_end_get_qentries(end); if (dma_memory_write(&address_space_memory, qaddr, &qdata, sizeof(qdata), MEMTXATTRS_UNSPECIFIED)) { @@ -361,8 +374,8 @@ qgen ^= 1; end->w1 = xive_set_field32(END2_W1_GENERATION, end->w1, qgen); - /* TODO(PowerNV): reset GF bit on a cache watch operation */ - end->w1 = xive_set_field32(END2_W1_GEN_FLIPPED, end->w1, qgen); + /* Set gen flipped to 1, it gets reset on a cache watch operation */ + end->w1 = xive_set_field32(END2_W1_GEN_FLIPPED, end->w1, 1); } end->w1 = xive_set_field32(END2_W1_PAGE_OFF, end->w1, qindex); } @@ -822,8 +835,9 @@ nvp.w2 = xive_set_field32(NVP2_W2_IPB, nvp.w2, 0); xive2_router_write_nvp(xrtr, nvp_blk, nvp_idx, &nvp, 2); } + /* IPB bits in the backlog are merged with the TIMA IPB bits */ regs[TM_IPB] |= ipb; - backlog_prio = xive_ipb_to_pipr(ipb); + backlog_prio = xive_ipb_to_pipr(regs[TM_IPB]); backlog_level = 0; first_group = xive_get_field32(NVP2_W0_PGOFIRST, nvp.w0); @@ -981,7 +995,9 @@ } } } - regs[TM_PIPR] = pipr_min; + + /* PIPR should not be set to a value greater than CPPR */ + regs[TM_PIPR] = (pipr_min > cppr) ? cppr : pipr_min; rc = xive2_tctx_get_nvp_indexes(tctx, ring_min, &nvp_blk, &nvp_idx); if (rc) { @@ -1269,7 +1285,7 @@ * priority to know if the thread can take the interrupt now or if * it is precluded. */ - if (priority < alt_regs[TM_CPPR]) { + if (priority < alt_regs[TM_PIPR]) { return false; } return true; diff -Nru qemu-10.0.3+ds/hw/net/cadence_gem.c qemu-10.0.6+ds/hw/net/cadence_gem.c --- qemu-10.0.3+ds/hw/net/cadence_gem.c 2025-07-23 21:05:28.000000000 +0000 +++ qemu-10.0.6+ds/hw/net/cadence_gem.c 2025-10-20 18:13:45.000000000 +0000 @@ -1756,6 +1756,7 @@ sysbus_init_irq(SYS_BUS_DEVICE(dev), &s->irq[i]); } + gem_init_register_masks(s); qemu_macaddr_default_if_unset(&s->conf.macaddr); s->nic = qemu_new_nic(&net_gem_info, &s->conf, @@ -1776,7 +1777,6 @@ DB_PRINT("\n"); - gem_init_register_masks(s); memory_region_init_io(&s->iomem, OBJECT(s), &gem_ops, s, "enet", sizeof(s->regs)); diff -Nru qemu-10.0.3+ds/hw/net/e1000e_core.c qemu-10.0.6+ds/hw/net/e1000e_core.c --- qemu-10.0.3+ds/hw/net/e1000e_core.c 2025-07-23 21:05:28.000000000 +0000 +++ qemu-10.0.6+ds/hw/net/e1000e_core.c 2025-10-20 18:13:45.000000000 +0000 @@ -341,11 +341,6 @@ { uint32_t res; - if (msix_enabled(core->owner)) { - assert(core->delayed_causes == 0); - return 0; - } - res = core->delayed_causes; core->delayed_causes = 0; diff -Nru qemu-10.0.3+ds/hw/net/igbvf.c qemu-10.0.6+ds/hw/net/igbvf.c --- qemu-10.0.3+ds/hw/net/igbvf.c 2025-07-23 21:05:28.000000000 +0000 +++ qemu-10.0.6+ds/hw/net/igbvf.c 2025-10-20 18:13:45.000000000 +0000 @@ -251,10 +251,12 @@ memory_region_init_io(&s->mmio, OBJECT(dev), &mmio_ops, s, "igbvf-mmio", IGBVF_MMIO_SIZE); - pcie_sriov_vf_register_bar(dev, IGBVF_MMIO_BAR_IDX, &s->mmio); + pci_register_bar(dev, IGBVF_MMIO_BAR_IDX, PCI_BASE_ADDRESS_MEM_TYPE_64 | + PCI_BASE_ADDRESS_MEM_PREFETCH, &s->mmio); memory_region_init(&s->msix, OBJECT(dev), "igbvf-msix", IGBVF_MSIX_SIZE); - pcie_sriov_vf_register_bar(dev, IGBVF_MSIX_BAR_IDX, &s->msix); + pci_register_bar(dev, IGBVF_MSIX_BAR_IDX, PCI_BASE_ADDRESS_MEM_TYPE_64 | + PCI_BASE_ADDRESS_MEM_PREFETCH, &s->msix); ret = msix_init(dev, IGBVF_MSIX_VEC_NUM, &s->msix, IGBVF_MSIX_BAR_IDX, 0, &s->msix, IGBVF_MSIX_BAR_IDX, 0x2000, 0x70, errp); diff -Nru qemu-10.0.3+ds/hw/net/virtio-net.c qemu-10.0.6+ds/hw/net/virtio-net.c --- qemu-10.0.3+ds/hw/net/virtio-net.c 2025-07-23 21:05:28.000000000 +0000 +++ qemu-10.0.6+ds/hw/net/virtio-net.c 2025-10-20 18:13:45.000000000 +0000 @@ -997,8 +997,9 @@ vhost_net_save_acked_features(nc->peer); } - if (!virtio_has_feature(features, VIRTIO_NET_F_CTRL_VLAN)) { - memset(n->vlans, 0xff, MAX_VLAN >> 3); + if (virtio_has_feature(vdev->guest_features ^ features, VIRTIO_NET_F_CTRL_VLAN)) { + bool vlan = virtio_has_feature(features, VIRTIO_NET_F_CTRL_VLAN); + memset(n->vlans, vlan ? 0 : 0xff, MAX_VLAN >> 3); } if (virtio_has_feature(features, VIRTIO_NET_F_STANDBY)) { @@ -3896,6 +3897,7 @@ n->mac_table.macs = g_malloc0(MAC_TABLE_ENTRIES * ETH_ALEN); n->vlans = g_malloc0(MAX_VLAN >> 3); + memset(n->vlans, 0xff, MAX_VLAN >> 3); nc = qemu_get_queue(n->nic); nc->rxfilter_notify_enabled = 1; @@ -3986,7 +3988,6 @@ memset(n->mac_table.macs, 0, MAC_TABLE_ENTRIES * ETH_ALEN); memcpy(&n->mac[0], &n->nic->conf->macaddr, sizeof(n->mac)); qemu_format_nic_info_str(qemu_get_queue(n->nic), n->mac); - memset(n->vlans, 0, MAX_VLAN >> 3); /* Flush any async TX */ for (i = 0; i < n->max_queue_pairs; i++) { diff -Nru qemu-10.0.3+ds/hw/nvme/ctrl.c qemu-10.0.6+ds/hw/nvme/ctrl.c --- qemu-10.0.3+ds/hw/nvme/ctrl.c 2025-07-23 21:05:28.000000000 +0000 +++ qemu-10.0.6+ds/hw/nvme/ctrl.c 2025-10-20 18:13:45.000000000 +0000 @@ -6816,7 +6816,7 @@ switch (sel) { case NVME_NS_ATTACHMENT_ATTACH: - if (nvme_ns(n, nsid)) { + if (nvme_ns(ctrl, nsid)) { return NVME_NS_ALREADY_ATTACHED | NVME_DNR; } @@ -6824,7 +6824,7 @@ return NVME_NS_PRIVATE | NVME_DNR; } - if (!nvme_csi_supported(n, ns->csi)) { + if (!nvme_csi_supported(ctrl, ns->csi)) { return NVME_IOCS_NOT_SUPPORTED | NVME_DNR; } @@ -6834,6 +6834,10 @@ break; case NVME_NS_ATTACHMENT_DETACH: + if (!nvme_ns(ctrl, nsid)) { + return NVME_NS_NOT_ATTACHED | NVME_DNR; + } + nvme_detach_ns(ctrl, ns); nvme_update_dsm_limits(ctrl, NULL); @@ -8335,6 +8339,11 @@ host_memory_backend_set_mapped(n->pmr.dev, true); } + if (!n->params.mdts || ((1 << n->params.mdts) + 1) > IOV_MAX) { + error_setg(errp, "mdts exceeds IOV_MAX"); + return false; + } + if (n->params.zasl > n->params.mdts) { error_setg(errp, "zoned.zasl (Zone Append Size Limit) must be less " "than or equal to mdts (Maximum Data Transfer Size)"); @@ -8699,12 +8708,8 @@ msix_table_offset); memory_region_add_subregion(&n->bar0, 0, &n->iomem); - if (pci_is_vf(pci_dev)) { - pcie_sriov_vf_register_bar(pci_dev, 0, &n->bar0); - } else { - pci_register_bar(pci_dev, 0, PCI_BASE_ADDRESS_SPACE_MEMORY | - PCI_BASE_ADDRESS_MEM_TYPE_64, &n->bar0); - } + pci_register_bar(pci_dev, 0, PCI_BASE_ADDRESS_SPACE_MEMORY | + PCI_BASE_ADDRESS_MEM_TYPE_64, &n->bar0); ret = msix_init(pci_dev, nr_vectors, &n->bar0, 0, msix_table_offset, @@ -8776,7 +8781,7 @@ uint8_t *pci_conf = pci_dev->config; uint64_t cap = ldq_le_p(&n->bar.cap); NvmeSecCtrlEntry *sctrl = nvme_sctrl(n); - uint32_t ctratt; + uint32_t ctratt = le32_to_cpu(id->ctratt); uint16_t oacs; memcpy(n->cse.acs, nvme_cse_acs_default, sizeof(n->cse.acs)); @@ -8794,10 +8799,11 @@ id->oaes = cpu_to_le32(NVME_OAES_NS_ATTR); - ctratt = NVME_CTRATT_ELBAS; + ctratt |= NVME_CTRATT_ELBAS; if (n->params.ctratt.mem) { ctratt |= NVME_CTRATT_MEM; } + id->ctratt = cpu_to_le32(ctratt); id->rab = 6; @@ -8880,17 +8886,6 @@ id->psd[0].enlat = cpu_to_le32(0x10); id->psd[0].exlat = cpu_to_le32(0x4); - id->cmic |= NVME_CMIC_MULTI_CTRL; - ctratt |= NVME_CTRATT_ENDGRPS; - - id->endgidmax = cpu_to_le16(0x1); - - if (n->subsys->endgrp.fdp.enabled) { - ctratt |= NVME_CTRATT_FDPS; - } - - id->ctratt = cpu_to_le32(ctratt); - NVME_CAP_SET_MQES(cap, n->params.mqes); NVME_CAP_SET_CQR(cap, 1); NVME_CAP_SET_TO(cap, 0xf); @@ -8923,6 +8918,20 @@ } n->subsys = NVME_SUBSYS(dev); + } else { + NvmeIdCtrl *id = &n->id_ctrl; + uint32_t ctratt = le32_to_cpu(id->ctratt); + + id->cmic |= NVME_CMIC_MULTI_CTRL; + ctratt |= NVME_CTRATT_ENDGRPS; + + id->endgidmax = cpu_to_le16(0x1); + + if (n->subsys->endgrp.fdp.enabled) { + ctratt |= NVME_CTRATT_FDPS; + } + + id->ctratt = cpu_to_le32(ctratt); } cntlid = nvme_subsys_register_ctrl(n, errp); diff -Nru qemu-10.0.3+ds/hw/pci/pci.c qemu-10.0.6+ds/hw/pci/pci.c --- qemu-10.0.3+ds/hw/pci/pci.c 2025-07-23 21:05:28.000000000 +0000 +++ qemu-10.0.6+ds/hw/pci/pci.c 2025-10-20 18:13:45.000000000 +0000 @@ -1470,7 +1470,6 @@ pcibus_t size = memory_region_size(memory); uint8_t hdr_type; - assert(!pci_is_vf(pci_dev)); /* VFs must use pcie_sriov_vf_register_bar */ assert(region_num >= 0); assert(region_num < PCI_NUM_REGIONS); assert(is_power_of_2(size)); @@ -1482,7 +1481,6 @@ r = &pci_dev->io_regions[region_num]; assert(!r->size); - r->addr = PCI_BAR_UNMAPPED; r->size = size; r->type = type; r->memory = memory; @@ -1490,22 +1488,32 @@ ? pci_get_bus(pci_dev)->address_space_io : pci_get_bus(pci_dev)->address_space_mem; - wmask = ~(size - 1); - if (region_num == PCI_ROM_SLOT) { - /* ROM enable bit is writable */ - wmask |= PCI_ROM_ADDRESS_ENABLE; - } - - addr = pci_bar(pci_dev, region_num); - pci_set_long(pci_dev->config + addr, type); - - if (!(r->type & PCI_BASE_ADDRESS_SPACE_IO) && - r->type & PCI_BASE_ADDRESS_MEM_TYPE_64) { - pci_set_quad(pci_dev->wmask + addr, wmask); - pci_set_quad(pci_dev->cmask + addr, ~0ULL); + if (pci_is_vf(pci_dev)) { + r->addr = pci_bar_address(pci_dev, region_num, r->type, r->size); + if (r->addr != PCI_BAR_UNMAPPED) { + memory_region_add_subregion_overlap(r->address_space, + r->addr, r->memory, 1); + } } else { - pci_set_long(pci_dev->wmask + addr, wmask & 0xffffffff); - pci_set_long(pci_dev->cmask + addr, 0xffffffff); + r->addr = PCI_BAR_UNMAPPED; + + wmask = ~(size - 1); + if (region_num == PCI_ROM_SLOT) { + /* ROM enable bit is writable */ + wmask |= PCI_ROM_ADDRESS_ENABLE; + } + + addr = pci_bar(pci_dev, region_num); + pci_set_long(pci_dev->config + addr, type); + + if (!(r->type & PCI_BASE_ADDRESS_SPACE_IO) && + r->type & PCI_BASE_ADDRESS_MEM_TYPE_64) { + pci_set_quad(pci_dev->wmask + addr, wmask); + pci_set_quad(pci_dev->cmask + addr, ~0ULL); + } else { + pci_set_long(pci_dev->wmask + addr, wmask & 0xffffffff); + pci_set_long(pci_dev->cmask + addr, 0xffffffff); + } } } diff -Nru qemu-10.0.3+ds/hw/pci/pcie_sriov.c qemu-10.0.6+ds/hw/pci/pcie_sriov.c --- qemu-10.0.3+ds/hw/pci/pcie_sriov.c 2025-07-23 21:05:28.000000000 +0000 +++ qemu-10.0.6+ds/hw/pci/pcie_sriov.c 2025-10-20 18:13:45.000000000 +0000 @@ -112,6 +112,9 @@ void pcie_sriov_pf_exit(PCIDevice *dev) { uint8_t *cfg = dev->config + dev->exp.sriov_cap; + if (dev->exp.sriov_cap == 0) { + return; + } unparent_vfs(dev, pci_get_word(cfg + PCI_SRIOV_TOTAL_VF)); } @@ -143,42 +146,6 @@ dev->exp.sriov_pf.vf_bar_type[region_num] = type; } -void pcie_sriov_vf_register_bar(PCIDevice *dev, int region_num, - MemoryRegion *memory) -{ - PCIIORegion *r; - PCIBus *bus = pci_get_bus(dev); - uint8_t type; - pcibus_t size = memory_region_size(memory); - - assert(pci_is_vf(dev)); /* PFs must use pci_register_bar */ - assert(region_num >= 0); - assert(region_num < PCI_NUM_REGIONS); - type = dev->exp.sriov_vf.pf->exp.sriov_pf.vf_bar_type[region_num]; - - if (!is_power_of_2(size)) { - error_report("%s: PCI region size must be a power" - " of two - type=0x%x, size=0x%"FMT_PCIBUS, - __func__, type, size); - exit(1); - } - - r = &dev->io_regions[region_num]; - r->memory = memory; - r->address_space = - type & PCI_BASE_ADDRESS_SPACE_IO - ? bus->address_space_io - : bus->address_space_mem; - r->size = size; - r->type = type; - - r->addr = pci_bar_address(dev, region_num, r->type, r->size); - if (r->addr != PCI_BAR_UNMAPPED) { - memory_region_add_subregion_overlap(r->address_space, - r->addr, r->memory, 1); - } -} - static void register_vfs(PCIDevice *dev) { uint16_t num_vfs; @@ -211,6 +178,27 @@ pci_set_word(dev->wmask + dev->exp.sriov_cap + PCI_SRIOV_NUM_VF, 0xffff); } +static void consume_config(PCIDevice *dev) +{ + uint8_t *cfg = dev->config + dev->exp.sriov_cap; + + if (pci_get_word(cfg + PCI_SRIOV_CTRL) & PCI_SRIOV_CTRL_VFE) { + register_vfs(dev); + } else { + uint8_t *wmask = dev->wmask + dev->exp.sriov_cap; + uint16_t num_vfs = pci_get_word(cfg + PCI_SRIOV_NUM_VF); + uint16_t wmask_val = PCI_SRIOV_CTRL_MSE | PCI_SRIOV_CTRL_ARI; + + unregister_vfs(dev); + + if (num_vfs <= pci_get_word(cfg + PCI_SRIOV_TOTAL_VF)) { + wmask_val |= PCI_SRIOV_CTRL_VFE; + } + + pci_set_word(wmask + PCI_SRIOV_CTRL, wmask_val); + } +} + void pcie_sriov_config_write(PCIDevice *dev, uint32_t address, uint32_t val, int len) { @@ -228,30 +216,13 @@ trace_sriov_config_write(dev->name, PCI_SLOT(dev->devfn), PCI_FUNC(dev->devfn), off, val, len); - if (range_covers_byte(off, len, PCI_SRIOV_CTRL)) { - if (val & PCI_SRIOV_CTRL_VFE) { - register_vfs(dev); - } else { - unregister_vfs(dev); - } - } else if (range_covers_byte(off, len, PCI_SRIOV_NUM_VF)) { - uint8_t *cfg = dev->config + sriov_cap; - uint8_t *wmask = dev->wmask + sriov_cap; - uint16_t num_vfs = pci_get_word(cfg + PCI_SRIOV_NUM_VF); - uint16_t wmask_val = PCI_SRIOV_CTRL_MSE | PCI_SRIOV_CTRL_ARI; - - if (num_vfs <= pci_get_word(cfg + PCI_SRIOV_TOTAL_VF)) { - wmask_val |= PCI_SRIOV_CTRL_VFE; - } - - pci_set_word(wmask + PCI_SRIOV_CTRL, wmask_val); - } + consume_config(dev); } void pcie_sriov_pf_post_load(PCIDevice *dev) { if (dev->exp.sriov_cap) { - register_vfs(dev); + consume_config(dev); } } diff -Nru qemu-10.0.3+ds/hw/pci-host/astro.c qemu-10.0.6+ds/hw/pci-host/astro.c --- qemu-10.0.3+ds/hw/pci-host/astro.c 2025-07-23 21:05:28.000000000 +0000 +++ qemu-10.0.6+ds/hw/pci-host/astro.c 2025-10-20 18:13:45.000000000 +0000 @@ -423,22 +423,23 @@ } } -static void elroy_pcihost_init(Object *obj) +static void elroy_pcihost_realize(DeviceState *dev, Error **errp) { - ElroyState *s = ELROY_PCI_HOST_BRIDGE(obj); - PCIHostState *phb = PCI_HOST_BRIDGE(obj); - SysBusDevice *sbd = SYS_BUS_DEVICE(obj); + ElroyState *s = ELROY_PCI_HOST_BRIDGE(dev); + PCIHostState *phb = PCI_HOST_BRIDGE(dev); + SysBusDevice *sbd = SYS_BUS_DEVICE(dev); + Object *obj = OBJECT(s); /* Elroy config access from CPU. */ - memory_region_init_io(&s->this_mem, OBJECT(s), &elroy_chip_ops, + memory_region_init_io(&s->this_mem, obj, &elroy_chip_ops, s, "elroy", 0x2000); /* Elroy PCI config. */ - memory_region_init_io(&phb->conf_mem, OBJECT(phb), - &elroy_config_addr_ops, DEVICE(s), + memory_region_init_io(&phb->conf_mem, obj, + &elroy_config_addr_ops, dev, "pci-conf-idx", 8); - memory_region_init_io(&phb->data_mem, OBJECT(phb), - &elroy_config_data_ops, DEVICE(s), + memory_region_init_io(&phb->data_mem, obj, + &elroy_config_data_ops, dev, "pci-conf-data", 8); memory_region_add_subregion(&s->this_mem, 0x40, &phb->conf_mem); @@ -446,8 +447,8 @@ &phb->data_mem); /* Elroy PCI bus memory. */ - memory_region_init(&s->pci_mmio, OBJECT(s), "pci-mmio", UINT64_MAX); - memory_region_init_io(&s->pci_io, OBJECT(s), &unassigned_io_ops, obj, + memory_region_init(&s->pci_mmio, obj, "pci-mmio", UINT64_MAX); + memory_region_init_io(&s->pci_io, obj, &unassigned_io_ops, obj, "pci-isa-mmio", ((uint32_t) IOS_DIST_BASE_SIZE) / ROPES_PER_IOC); @@ -458,7 +459,7 @@ sysbus_init_mmio(sbd, &s->this_mem); - qdev_init_gpio_in(DEVICE(obj), elroy_set_irq, ELROY_IRQS); + qdev_init_gpio_in(dev, elroy_set_irq, ELROY_IRQS); } static const VMStateDescription vmstate_elroy = { @@ -486,6 +487,7 @@ DeviceClass *dc = DEVICE_CLASS(klass); device_class_set_legacy_reset(dc, elroy_reset); + dc->realize = elroy_pcihost_realize; dc->vmsd = &vmstate_elroy; dc->user_creatable = false; } @@ -493,7 +495,6 @@ static const TypeInfo elroy_pcihost_info = { .name = TYPE_ELROY_PCI_HOST_BRIDGE, .parent = TYPE_PCI_HOST_BRIDGE, - .instance_init = elroy_pcihost_init, .instance_size = sizeof(ElroyState), .class_init = elroy_pcihost_class_init, }; diff -Nru qemu-10.0.3+ds/hw/pci-host/dino.c qemu-10.0.6+ds/hw/pci-host/dino.c --- qemu-10.0.3+ds/hw/pci-host/dino.c 2025-07-23 21:05:28.000000000 +0000 +++ qemu-10.0.6+ds/hw/pci-host/dino.c 2025-10-20 18:13:45.000000000 +0000 @@ -413,43 +413,7 @@ static void dino_pcihost_realize(DeviceState *dev, Error **errp) { DinoState *s = DINO_PCI_HOST_BRIDGE(dev); - - /* Set up PCI view of memory: Bus master address space. */ - memory_region_init(&s->bm, OBJECT(s), "bm-dino", 4 * GiB); - memory_region_init_alias(&s->bm_ram_alias, OBJECT(s), - "bm-system", s->memory_as, 0, - 0xf0000000 + DINO_MEM_CHUNK_SIZE); - memory_region_init_alias(&s->bm_pci_alias, OBJECT(s), - "bm-pci", &s->pci_mem, - 0xf0000000 + DINO_MEM_CHUNK_SIZE, - 30 * DINO_MEM_CHUNK_SIZE); - memory_region_init_alias(&s->bm_cpu_alias, OBJECT(s), - "bm-cpu", s->memory_as, 0xfff00000, - 0xfffff); - memory_region_add_subregion(&s->bm, 0, - &s->bm_ram_alias); - memory_region_add_subregion(&s->bm, - 0xf0000000 + DINO_MEM_CHUNK_SIZE, - &s->bm_pci_alias); - memory_region_add_subregion(&s->bm, 0xfff00000, - &s->bm_cpu_alias); - - address_space_init(&s->bm_as, &s->bm, "pci-bm"); -} - -static void dino_pcihost_unrealize(DeviceState *dev) -{ - DinoState *s = DINO_PCI_HOST_BRIDGE(dev); - - address_space_destroy(&s->bm_as); -} - -static void dino_pcihost_init(Object *obj) -{ - DinoState *s = DINO_PCI_HOST_BRIDGE(obj); - PCIHostState *phb = PCI_HOST_BRIDGE(obj); - SysBusDevice *sbd = SYS_BUS_DEVICE(obj); - int i; + PCIHostState *phb = PCI_HOST_BRIDGE(dev); /* Dino PCI access from main memory. */ memory_region_init_io(&s->this_mem, OBJECT(s), &dino_chip_ops, @@ -476,7 +440,7 @@ PCI_DEVFN(0, 0), 32, TYPE_PCI_BUS); /* Set up windows into PCI bus memory. */ - for (i = 1; i < 31; i++) { + for (int i = 1; i < 31; i++) { uint32_t addr = 0xf0000000 + i * DINO_MEM_CHUNK_SIZE; char *name = g_strdup_printf("PCI Outbound Window %d", i); memory_region_init_alias(&s->pci_mem_alias[i], OBJECT(s), @@ -487,9 +451,38 @@ pci_setup_iommu(phb->bus, &dino_iommu_ops, s); - sysbus_init_mmio(sbd, &s->this_mem); + sysbus_init_mmio(SYS_BUS_DEVICE(dev), &s->this_mem); + + qdev_init_gpio_in(dev, dino_set_irq, DINO_IRQS); + + /* Set up PCI view of memory: Bus master address space. */ + memory_region_init(&s->bm, OBJECT(s), "bm-dino", 4 * GiB); + memory_region_init_alias(&s->bm_ram_alias, OBJECT(s), + "bm-system", s->memory_as, 0, + 0xf0000000 + DINO_MEM_CHUNK_SIZE); + memory_region_init_alias(&s->bm_pci_alias, OBJECT(s), + "bm-pci", &s->pci_mem, + 0xf0000000 + DINO_MEM_CHUNK_SIZE, + 30 * DINO_MEM_CHUNK_SIZE); + memory_region_init_alias(&s->bm_cpu_alias, OBJECT(s), + "bm-cpu", s->memory_as, 0xfff00000, + 0xfffff); + memory_region_add_subregion(&s->bm, 0, + &s->bm_ram_alias); + memory_region_add_subregion(&s->bm, + 0xf0000000 + DINO_MEM_CHUNK_SIZE, + &s->bm_pci_alias); + memory_region_add_subregion(&s->bm, 0xfff00000, + &s->bm_cpu_alias); + + address_space_init(&s->bm_as, &s->bm, "pci-bm"); +} - qdev_init_gpio_in(DEVICE(obj), dino_set_irq, DINO_IRQS); +static void dino_pcihost_unrealize(DeviceState *dev) +{ + DinoState *s = DINO_PCI_HOST_BRIDGE(dev); + + address_space_destroy(&s->bm_as); } static const Property dino_pcihost_properties[] = { @@ -511,7 +504,6 @@ static const TypeInfo dino_pcihost_info = { .name = TYPE_DINO_PCI_HOST_BRIDGE, .parent = TYPE_PCI_HOST_BRIDGE, - .instance_init = dino_pcihost_init, .instance_size = sizeof(DinoState), .class_init = dino_pcihost_class_init, }; diff -Nru qemu-10.0.3+ds/hw/ppc/pnv.c qemu-10.0.6+ds/hw/ppc/pnv.c --- qemu-10.0.3+ds/hw/ppc/pnv.c 2025-07-23 21:05:28.000000000 +0000 +++ qemu-10.0.6+ds/hw/ppc/pnv.c 2025-10-20 18:13:45.000000000 +0000 @@ -21,6 +21,7 @@ #include "qemu/osdep.h" #include "qemu/datadir.h" +#include "qemu/log.h" #include "qemu/units.h" #include "qemu/cutils.h" #include "qapi/error.h" @@ -1794,12 +1795,83 @@ } } +static uint64_t pnv_handle_sprd_load(CPUPPCState *env) +{ + PowerPCCPU *cpu = env_archcpu(env); + PnvCore *pc = pnv_cpu_state(cpu)->pnv_core; + uint64_t sprc = env->spr[SPR_POWER_SPRC]; + + if (pc->big_core) { + pc = pnv_chip_find_core(pc->chip, CPU_CORE(pc)->core_id & ~0x1); + } + + switch (sprc & 0x3e0) { + case 0: /* SCRATCH0-3 */ + case 1: /* SCRATCH4-7 */ + return pc->scratch[(sprc >> 3) & 0x7]; + + case 0x1e0: /* core thread state */ + if (env->excp_model == POWERPC_EXCP_POWER9) { + /* + * Only implement for POWER9 because skiboot uses it to check + * big-core mode. Other bits are unimplemented so we would + * prefer to get unimplemented message on POWER10 if it were + * used anywhere. + */ + if (pc->big_core) { + return PPC_BIT(63); + } else { + return 0; + } + } + /* fallthru */ + + default: + qemu_log_mask(LOG_UNIMP, "mfSPRD: Unimplemented SPRC:0x" + TARGET_FMT_lx"\n", sprc); + break; + } + return 0; +} + +static void pnv_handle_sprd_store(CPUPPCState *env, uint64_t val) +{ + PowerPCCPU *cpu = env_archcpu(env); + uint64_t sprc = env->spr[SPR_POWER_SPRC]; + PnvCore *pc = pnv_cpu_state(cpu)->pnv_core; + int nr; + + if (pc->big_core) { + pc = pnv_chip_find_core(pc->chip, CPU_CORE(pc)->core_id & ~0x1); + } + + switch (sprc & 0x3e0) { + case 0: /* SCRATCH0-3 */ + case 1: /* SCRATCH4-7 */ + /* + * Log stores to SCRATCH, because some firmware uses these for + * debugging and logging, but they would normally be read by the BMC, + * which is not implemented in QEMU yet. This gives a way to get at the + * information. Could also dump these upon checkstop. + */ + nr = (sprc >> 3) & 0x7; + pc->scratch[nr] = val; + break; + default: + qemu_log_mask(LOG_UNIMP, "mtSPRD: Unimplemented SPRC:0x" + TARGET_FMT_lx"\n", sprc); + break; + } +} + static void pnv_chip_power9_realize(DeviceState *dev, Error **errp) { PnvChipClass *pcc = PNV_CHIP_GET_CLASS(dev); Pnv9Chip *chip9 = PNV9_CHIP(dev); PnvChip *chip = PNV_CHIP(dev); Pnv9Psi *psi9 = &chip9->psi; + PowerPCCPU *cpu; + PowerPCCPUClass *cpu_class; Error *local_err = NULL; int i; @@ -1827,6 +1899,12 @@ return; } + /* Set handlers for Special registers, such as SPRD */ + cpu = chip->cores[0]->threads[0]; + cpu_class = POWERPC_CPU_GET_CLASS(cpu); + cpu_class->load_sprd = pnv_handle_sprd_load; + cpu_class->store_sprd = pnv_handle_sprd_store; + /* XIVE interrupt controller (POWER9) */ object_property_set_int(OBJECT(&chip9->xive), "ic-bar", PNV9_XIVE_IC_BASE(chip), &error_fatal); @@ -2078,6 +2156,8 @@ PnvChipClass *pcc = PNV_CHIP_GET_CLASS(dev); PnvChip *chip = PNV_CHIP(dev); Pnv10Chip *chip10 = PNV10_CHIP(dev); + PowerPCCPU *cpu; + PowerPCCPUClass *cpu_class; Error *local_err = NULL; int i; @@ -2105,6 +2185,12 @@ return; } + /* Set handlers for Special registers, such as SPRD */ + cpu = chip->cores[0]->threads[0]; + cpu_class = POWERPC_CPU_GET_CLASS(cpu); + cpu_class->load_sprd = pnv_handle_sprd_load; + cpu_class->store_sprd = pnv_handle_sprd_store; + /* XIVE2 interrupt controller (POWER10) */ object_property_set_int(OBJECT(&chip10->xive), "ic-bar", PNV10_XIVE2_IC_BASE(chip), &error_fatal); diff -Nru qemu-10.0.3+ds/hw/ppc/spapr.c qemu-10.0.6+ds/hw/ppc/spapr.c --- qemu-10.0.3+ds/hw/ppc/spapr.c 2025-07-23 21:05:28.000000000 +0000 +++ qemu-10.0.6+ds/hw/ppc/spapr.c 2025-10-20 18:13:45.000000000 +0000 @@ -907,6 +907,7 @@ int rtas; GString *hypertas = g_string_sized_new(256); GString *qemu_hypertas = g_string_sized_new(256); + uint64_t max_device_addr = 0; uint32_t lrdr_capacity[] = { 0, 0, @@ -917,13 +918,15 @@ /* Do we have device memory? */ if (MACHINE(spapr)->device_memory) { - uint64_t max_device_addr = MACHINE(spapr)->device_memory->base + + max_device_addr = MACHINE(spapr)->device_memory->base + memory_region_size(&MACHINE(spapr)->device_memory->mr); - - lrdr_capacity[0] = cpu_to_be32(max_device_addr >> 32); - lrdr_capacity[1] = cpu_to_be32(max_device_addr & 0xffffffff); + } else if (ms->ram_size == ms->maxram_size) { + max_device_addr = ms->ram_size; } + lrdr_capacity[0] = cpu_to_be32(max_device_addr >> 32); + lrdr_capacity[1] = cpu_to_be32(max_device_addr & 0xffffffff); + _FDT(rtas = fdt_add_subnode(fdt, 0, "rtas")); /* hypertas */ diff -Nru qemu-10.0.3+ds/hw/riscv/riscv-iommu.c qemu-10.0.6+ds/hw/riscv/riscv-iommu.c --- qemu-10.0.3+ds/hw/riscv/riscv-iommu.c 2025-07-23 21:05:28.000000000 +0000 +++ qemu-10.0.6+ds/hw/riscv/riscv-iommu.c 2025-10-20 18:13:45.000000000 +0000 @@ -557,6 +557,7 @@ MemTxResult res; dma_addr_t addr; uint64_t intn; + size_t offset; uint32_t n190; uint64_t pte[2]; int fault_type = RISCV_IOMMU_FQ_TTYPE_UADDR_WR; @@ -564,16 +565,18 @@ /* Interrupt File Number */ intn = riscv_iommu_pext_u64(PPN_DOWN(gpa), ctx->msi_addr_mask); - if (intn >= 256) { + offset = intn * sizeof(pte); + + /* fetch MSI PTE */ + addr = PPN_PHYS(get_field(ctx->msiptp, RISCV_IOMMU_DC_MSIPTP_PPN)); + if (addr & offset) { /* Interrupt file number out of range */ res = MEMTX_ACCESS_ERROR; cause = RISCV_IOMMU_FQ_CAUSE_MSI_LOAD_FAULT; goto err; } - /* fetch MSI PTE */ - addr = PPN_PHYS(get_field(ctx->msiptp, RISCV_IOMMU_DC_MSIPTP_PPN)); - addr = addr | (intn * sizeof(pte)); + addr |= offset; res = dma_memory_read(s->target_as, addr, &pte, sizeof(pte), MEMTXATTRS_UNSPECIFIED); if (res != MEMTX_OK) { @@ -865,6 +868,145 @@ return true; } +/** + * pdt_memory_read: PDT wrapper of dma_memory_read. + * + * @s: IOMMU Device State + * @ctx: Device Translation Context with devid and pasid set + * @addr: address within that address space + * @buf: buffer with the data transferred + * @len: length of the data transferred + * @attrs: memory transaction attributes + */ +static MemTxResult pdt_memory_read(RISCVIOMMUState *s, + RISCVIOMMUContext *ctx, + dma_addr_t addr, + void *buf, dma_addr_t len, + MemTxAttrs attrs) +{ + uint64_t gatp_mode, pte; + struct { + unsigned char step; + unsigned char levels; + unsigned char ptidxbits; + unsigned char ptesize; + } sc; + MemTxResult ret; + dma_addr_t base = addr; + + /* G stages translation mode */ + gatp_mode = get_field(ctx->gatp, RISCV_IOMMU_ATP_MODE_FIELD); + if (gatp_mode == RISCV_IOMMU_DC_IOHGATP_MODE_BARE) { + goto out; + } + + /* G stages translation tables root pointer */ + base = PPN_PHYS(get_field(ctx->gatp, RISCV_IOMMU_ATP_PPN_FIELD)); + + /* Start at step 0 */ + sc.step = 0; + + if (s->fctl & RISCV_IOMMU_FCTL_GXL) { + /* 32bit mode for GXL == 1 */ + switch (gatp_mode) { + case RISCV_IOMMU_DC_IOHGATP_MODE_SV32X4: + if (!(s->cap & RISCV_IOMMU_CAP_SV32X4)) { + return MEMTX_ACCESS_ERROR; + } + sc.levels = 2; + sc.ptidxbits = 10; + sc.ptesize = 4; + break; + default: + return MEMTX_ACCESS_ERROR; + } + } else { + /* 64bit mode for GXL == 0 */ + switch (gatp_mode) { + case RISCV_IOMMU_DC_IOHGATP_MODE_SV39X4: + if (!(s->cap & RISCV_IOMMU_CAP_SV39X4)) { + return MEMTX_ACCESS_ERROR; + } + sc.levels = 3; + sc.ptidxbits = 9; + sc.ptesize = 8; + break; + case RISCV_IOMMU_DC_IOHGATP_MODE_SV48X4: + if (!(s->cap & RISCV_IOMMU_CAP_SV48X4)) { + return MEMTX_ACCESS_ERROR; + } + sc.levels = 4; + sc.ptidxbits = 9; + sc.ptesize = 8; + break; + case RISCV_IOMMU_DC_IOHGATP_MODE_SV57X4: + if (!(s->cap & RISCV_IOMMU_CAP_SV57X4)) { + return MEMTX_ACCESS_ERROR; + } + sc.levels = 5; + sc.ptidxbits = 9; + sc.ptesize = 8; + break; + default: + return MEMTX_ACCESS_ERROR; + } + } + + do { + const unsigned va_bits = (sc.step ? 0 : 2) + sc.ptidxbits; + const unsigned va_skip = TARGET_PAGE_BITS + sc.ptidxbits * + (sc.levels - 1 - sc.step); + const unsigned idx = (addr >> va_skip) & ((1 << va_bits) - 1); + const dma_addr_t pte_addr = base + idx * sc.ptesize; + + /* Address range check before first level lookup */ + if (!sc.step) { + const uint64_t va_mask = (1ULL << (va_skip + va_bits)) - 1; + if ((addr & va_mask) != addr) { + return MEMTX_ACCESS_ERROR; + } + } + + /* Read page table entry */ + if (sc.ptesize == 4) { + uint32_t pte32 = 0; + ret = ldl_le_dma(s->target_as, pte_addr, &pte32, attrs); + pte = pte32; + } else { + ret = ldq_le_dma(s->target_as, pte_addr, &pte, attrs); + } + if (ret != MEMTX_OK) { + return ret; + } + + sc.step++; + hwaddr ppn = pte >> PTE_PPN_SHIFT; + + if (!(pte & PTE_V)) { + return MEMTX_ACCESS_ERROR; /* Invalid PTE */ + } else if (!(pte & (PTE_R | PTE_W | PTE_X))) { + base = PPN_PHYS(ppn); /* Inner PTE, continue walking */ + } else if ((pte & (PTE_R | PTE_W | PTE_X)) == PTE_W) { + return MEMTX_ACCESS_ERROR; /* Reserved leaf PTE flags: PTE_W */ + } else if ((pte & (PTE_R | PTE_W | PTE_X)) == (PTE_W | PTE_X)) { + return MEMTX_ACCESS_ERROR; /* Reserved leaf PTE flags: PTE_W + PTE_X */ + } else if (ppn & ((1ULL << (va_skip - TARGET_PAGE_BITS)) - 1)) { + return MEMTX_ACCESS_ERROR; /* Misaligned PPN */ + } else { + /* Leaf PTE, translation completed. */ + base = PPN_PHYS(ppn) | (addr & ((1ULL << va_skip) - 1)); + break; + } + + if (sc.step == sc.levels) { + return MEMTX_ACCESS_ERROR; /* Can't find leaf PTE */ + } + } while (1); + +out: + return dma_memory_read(s->target_as, base, buf, len, attrs); +} + /* * RISC-V IOMMU Device Context Loopkup - Device Directory Tree Walk * @@ -1037,7 +1179,7 @@ */ const int split = depth * 9 + 8; addr |= ((ctx->process_id >> split) << 3) & ~TARGET_PAGE_MASK; - if (dma_memory_read(s->target_as, addr, &de, sizeof(de), + if (pdt_memory_read(s, ctx, addr, &de, sizeof(de), MEMTXATTRS_UNSPECIFIED) != MEMTX_OK) { return RISCV_IOMMU_FQ_CAUSE_PDT_LOAD_FAULT; } @@ -1052,7 +1194,7 @@ /* Leaf entry in PDT */ addr |= (ctx->process_id << 4) & ~TARGET_PAGE_MASK; - if (dma_memory_read(s->target_as, addr, &dc.ta, sizeof(uint64_t) * 2, + if (pdt_memory_read(s, ctx, addr, &dc.ta, sizeof(uint64_t) * 2, MEMTXATTRS_UNSPECIFIED) != MEMTX_OK) { return RISCV_IOMMU_FQ_CAUSE_PDT_LOAD_FAULT; } diff -Nru qemu-10.0.3+ds/hw/sd/ssi-sd.c qemu-10.0.6+ds/hw/sd/ssi-sd.c --- qemu-10.0.3+ds/hw/sd/ssi-sd.c 2025-07-23 21:05:28.000000000 +0000 +++ qemu-10.0.6+ds/hw/sd/ssi-sd.c 2025-10-20 18:13:45.000000000 +0000 @@ -106,6 +106,10 @@ SDRequest request; uint8_t longresp[16]; + if (!sdbus_get_inserted(&s->sdbus)) { + return SSI_DUMMY; + } + /* * Special case: allow CMD12 (STOP TRANSMISSION) while reading data. * diff -Nru qemu-10.0.3+ds/hw/ssi/aspeed_smc.c qemu-10.0.6+ds/hw/ssi/aspeed_smc.c --- qemu-10.0.3+ds/hw/ssi/aspeed_smc.c 2025-07-23 21:05:28.000000000 +0000 +++ qemu-10.0.6+ds/hw/ssi/aspeed_smc.c 2025-10-20 18:13:45.000000000 +0000 @@ -1857,7 +1857,8 @@ asc->resets = aspeed_1030_fmc_resets; asc->flash_window_base = 0x80000000; asc->flash_window_size = 0x10000000; - asc->features = ASPEED_SMC_FEATURE_DMA; + asc->features = ASPEED_SMC_FEATURE_DMA | + ASPEED_SMC_FEATURE_WDT_CONTROL; asc->dma_flash_mask = 0x0FFFFFFC; asc->dma_dram_mask = 0x000BFFFC; asc->dma_start_length = 1; diff -Nru qemu-10.0.3+ds/hw/uefi/var-service-core.c qemu-10.0.6+ds/hw/uefi/var-service-core.c --- qemu-10.0.3+ds/hw/uefi/var-service-core.c 2025-07-23 21:05:28.000000000 +0000 +++ qemu-10.0.6+ds/hw/uefi/var-service-core.c 2025-10-20 18:13:45.000000000 +0000 @@ -259,8 +259,8 @@ uv->buf_size = val; g_free(uv->buffer); g_free(uv->pio_xfer_buffer); - uv->buffer = g_malloc(uv->buf_size); - uv->pio_xfer_buffer = g_malloc(uv->buf_size); + uv->buffer = g_malloc0(uv->buf_size); + uv->pio_xfer_buffer = g_malloc0(uv->buf_size); break; case UEFI_VARS_REG_DMA_BUFFER_ADDR_LO: uv->buf_addr_lo = val; diff -Nru qemu-10.0.3+ds/hw/uefi/var-service-json.c qemu-10.0.6+ds/hw/uefi/var-service-json.c --- qemu-10.0.3+ds/hw/uefi/var-service-json.c 2025-07-23 21:05:28.000000000 +0000 +++ qemu-10.0.6+ds/hw/uefi/var-service-json.c 2025-10-20 18:13:45.000000000 +0000 @@ -172,7 +172,7 @@ void uefi_vars_json_init(uefi_vars_state *uv, Error **errp) { if (uv->jsonfile) { - uv->jsonfd = qemu_create(uv->jsonfile, O_RDWR, 0666, errp); + uv->jsonfd = qemu_create(uv->jsonfile, O_RDWR | O_BINARY, 0666, errp); } } diff -Nru qemu-10.0.3+ds/hw/uefi/var-service-vars.c qemu-10.0.6+ds/hw/uefi/var-service-vars.c --- qemu-10.0.3+ds/hw/uefi/var-service-vars.c 2025-07-23 21:05:28.000000000 +0000 +++ qemu-10.0.6+ds/hw/uefi/var-service-vars.c 2025-10-20 18:13:45.000000000 +0000 @@ -357,6 +357,9 @@ if (uefi_strlen(name, nv->name_size) == 0) { /* empty string -> first */ var = QTAILQ_FIRST(&uv->variables); + while (var && !check_access(uv, var)) { + var = QTAILQ_NEXT(var, next); + } if (!var) { return uefi_vars_mm_error(mhdr, mvar, EFI_NOT_FOUND); } @@ -702,12 +705,14 @@ case SMM_VARIABLE_FUNCTION_READY_TO_BOOT: trace_uefi_event("ready-to-boot"); uv->ready_to_boot = true; + mvar->status = EFI_SUCCESS; length = 0; break; case SMM_VARIABLE_FUNCTION_EXIT_BOOT_SERVICE: trace_uefi_event("exit-boot-service"); uv->exit_boot_service = true; + mvar->status = EFI_SUCCESS; length = 0; break; diff -Nru qemu-10.0.3+ds/hw/usb/dev-network.c qemu-10.0.6+ds/hw/usb/dev-network.c --- qemu-10.0.3+ds/hw/usb/dev-network.c 2025-07-23 21:05:28.000000000 +0000 +++ qemu-10.0.6+ds/hw/usb/dev-network.c 2025-10-20 18:13:45.000000000 +0000 @@ -1383,7 +1383,7 @@ 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", - 0x40, + s->conf.macaddr.a[0], s->conf.macaddr.a[1], s->conf.macaddr.a[2], s->conf.macaddr.a[3], diff -Nru qemu-10.0.3+ds/hw/usb/hcd-uhci.c qemu-10.0.6+ds/hw/usb/hcd-uhci.c --- qemu-10.0.3+ds/hw/usb/hcd-uhci.c 2025-07-23 21:05:28.000000000 +0000 +++ qemu-10.0.6+ds/hw/usb/hcd-uhci.c 2025-10-20 18:13:45.000000000 +0000 @@ -735,6 +735,7 @@ bool spd; bool queuing = (q != NULL); uint8_t pid = td->token & 0xff; + uint8_t ep_id = (td->token >> 15) & 0xf; UHCIAsync *async; async = uhci_async_find_td(s, td_addr); @@ -778,9 +779,14 @@ switch (pid) { case USB_TOKEN_OUT: - case USB_TOKEN_SETUP: case USB_TOKEN_IN: break; + case USB_TOKEN_SETUP: + /* SETUP is only valid to endpoint 0 */ + if (ep_id == 0) { + break; + } + /* fallthrough */ default: /* invalid pid : frame interrupted */ s->status |= UHCI_STS_HCPERR; @@ -829,7 +835,7 @@ return uhci_handle_td_error(s, td, td_addr, USB_RET_NODEV, int_mask); } - ep = usb_ep_get(dev, pid, (td->token >> 15) & 0xf); + ep = usb_ep_get(dev, pid, ep_id); q = uhci_queue_new(s, qh_addr, td, ep); } async = uhci_async_alloc(q, td_addr); diff -Nru qemu-10.0.3+ds/hw/virtio/vhost.c qemu-10.0.6+ds/hw/virtio/vhost.c --- qemu-10.0.3+ds/hw/virtio/vhost.c 2025-07-23 21:05:28.000000000 +0000 +++ qemu-10.0.6+ds/hw/virtio/vhost.c 2025-10-20 18:13:45.000000000 +0000 @@ -1111,7 +1111,8 @@ r = vhost_migration_log(listener, true); if (r < 0) { - abort(); + error_setg_errno(errp, -r, "vhost: Failed to start logging"); + return false; } return true; } @@ -1122,7 +1123,8 @@ r = vhost_migration_log(listener, false); if (r < 0) { - abort(); + /* Not fatal, so report it, but take no further action */ + warn_report("vhost: Failed to stop logging"); } } diff -Nru qemu-10.0.3+ds/hw/virtio/virtio.c qemu-10.0.6+ds/hw/virtio/virtio.c --- qemu-10.0.3+ds/hw/virtio/virtio.c 2025-07-23 21:05:28.000000000 +0000 +++ qemu-10.0.6+ds/hw/virtio/virtio.c 2025-10-20 18:13:45.000000000 +0000 @@ -929,18 +929,18 @@ static void virtqueue_ordered_fill(VirtQueue *vq, const VirtQueueElement *elem, unsigned int len) { - unsigned int i, steps, max_steps; + unsigned int i, steps, max_steps, ndescs; i = vq->used_idx % vq->vring.num; steps = 0; /* - * We shouldn't need to increase 'i' by more than the distance - * between used_idx and last_avail_idx. + * We shouldn't need to increase 'i' by more than or equal to + * the distance between used_idx and last_avail_idx (max_steps). */ max_steps = (vq->last_avail_idx - vq->used_idx) % vq->vring.num; /* Search for element in vq->used_elems */ - while (steps <= max_steps) { + while (steps < max_steps) { /* Found element, set length and mark as filled */ if (vq->used_elems[i].index == elem->index) { vq->used_elems[i].len = len; @@ -948,8 +948,18 @@ break; } - i += vq->used_elems[i].ndescs; - steps += vq->used_elems[i].ndescs; + ndescs = vq->used_elems[i].ndescs; + + /* Defensive sanity check */ + if (unlikely(ndescs == 0 || ndescs > vq->vring.num)) { + qemu_log_mask(LOG_GUEST_ERROR, + "%s: %s invalid ndescs %u at position %u\n", + __func__, vq->vdev->name, ndescs, i); + return; + } + + i += ndescs; + steps += ndescs; if (i >= vq->vring.num) { i -= vq->vring.num; diff -Nru qemu-10.0.3+ds/include/elf.h qemu-10.0.6+ds/include/elf.h --- qemu-10.0.3+ds/include/elf.h 2025-07-23 21:05:28.000000000 +0000 +++ qemu-10.0.6+ds/include/elf.h 2025-10-20 18:13:46.000000000 +0000 @@ -56,6 +56,13 @@ #define EF_MIPS_ARCH_32R6 0x90000000 /* MIPS32r6 code. */ #define EF_MIPS_ARCH_64R6 0xa0000000 /* MIPS64r6 code. */ +/* MIPS Architectural Extensions. */ +#define EF_MIPS_ARCH_ASE 0x0f000000 + +#define EF_MIPS_ARCH_ASE_MICROMIPS 0x02000000 +#define EF_MIPS_ARCH_ASE_M16 0x04000000 +#define EF_MIPS_ARCH_ASE_MDMX 0x08000000 + /* The ABI of a file. */ #define EF_MIPS_ABI_O32 0x00001000 /* O32 ABI. */ #define EF_MIPS_ABI_O64 0x00002000 /* O32 extended for 64 bit. */ diff -Nru qemu-10.0.3+ds/include/exec/cpu-common.h qemu-10.0.6+ds/include/exec/cpu-common.h --- qemu-10.0.3+ds/include/exec/cpu-common.h 2025-07-23 21:05:28.000000000 +0000 +++ qemu-10.0.6+ds/include/exec/cpu-common.h 2025-10-20 18:13:46.000000000 +0000 @@ -132,13 +132,13 @@ void cpu_address_space_init(CPUState *cpu, int asidx, const char *prefix, MemoryRegion *mr); /** - * cpu_address_space_destroy: - * @cpu: CPU for which address space needs to be destroyed - * @asidx: integer index of this address space + * cpu_destroy_address_spaces: + * @cpu: CPU for which address spaces need to be destroyed * - * Note that with KVM only one address space is supported. + * Destroy all address spaces associated with this CPU; this + * is called as part of unrealizing the CPU. */ -void cpu_address_space_destroy(CPUState *cpu, int asidx); +void cpu_destroy_address_spaces(CPUState *cpu); void cpu_physical_memory_rw(hwaddr addr, void *buf, hwaddr len, bool is_write); diff -Nru qemu-10.0.3+ds/include/exec/memory.h qemu-10.0.6+ds/include/exec/memory.h --- qemu-10.0.3+ds/include/exec/memory.h 2025-07-23 21:05:28.000000000 +0000 +++ qemu-10.0.6+ds/include/exec/memory.h 2025-10-20 18:13:46.000000000 +0000 @@ -2627,15 +2627,33 @@ /** * address_space_destroy: destroy an address space * - * Releases all resources associated with an address space. After an address space - * is destroyed, its root memory region (given by address_space_init()) may be destroyed - * as well. + * Releases all resources associated with an address space. After an + * address space is destroyed, the reference the AddressSpace had to + * its root memory region is dropped, which may result in the + * destruction of that memory region as well. + * + * Note that destruction of the AddressSpace is done via RCU; + * it is therefore not valid to free the memory the AddressSpace + * struct is in until after that RCU callback has completed. + * If you want to g_free() the AddressSpace after destruction you + * can do that with address_space_destroy_free(). * * @as: address space to be destroyed */ void address_space_destroy(AddressSpace *as); /** + * address_space_destroy_free: destroy an address space and free it + * + * This does the same thing as address_space_destroy(), and then also + * frees (via g_free()) the AddressSpace itself once the destruction + * is complete. + * + * @as: address space to be destroyed + */ +void address_space_destroy_free(AddressSpace *as); + +/** * address_space_remove_listeners: unregister all listeners of an address space * * Removes all callbacks previously registered with memory_listener_register() diff -Nru qemu-10.0.3+ds/include/hw/arm/stm32f205_soc.h qemu-10.0.6+ds/include/hw/arm/stm32f205_soc.h --- qemu-10.0.3+ds/include/hw/arm/stm32f205_soc.h 2025-07-23 21:05:28.000000000 +0000 +++ qemu-10.0.6+ds/include/hw/arm/stm32f205_soc.h 2025-10-20 18:13:46.000000000 +0000 @@ -59,7 +59,7 @@ STM32F2XXADCState adc[STM_NUM_ADCS]; STM32F2XXSPIState spi[STM_NUM_SPIS]; - OrIRQState *adc_irqs; + OrIRQState adc_irqs; MemoryRegion sram; MemoryRegion flash; diff -Nru qemu-10.0.3+ds/include/hw/core/cpu.h qemu-10.0.6+ds/include/hw/core/cpu.h --- qemu-10.0.3+ds/include/hw/core/cpu.h 2025-07-23 21:05:28.000000000 +0000 +++ qemu-10.0.6+ds/include/hw/core/cpu.h 2025-10-20 18:13:46.000000000 +0000 @@ -500,7 +500,6 @@ QSIMPLEQ_HEAD(, qemu_work_item) work_list; struct CPUAddressSpace *cpu_ases; - int cpu_ases_count; int num_ases; AddressSpace *as; MemoryRegion *memory; diff -Nru qemu-10.0.3+ds/include/hw/intc/arm_gicv3_common.h qemu-10.0.6+ds/include/hw/intc/arm_gicv3_common.h --- qemu-10.0.3+ds/include/hw/intc/arm_gicv3_common.h 2025-07-23 21:05:28.000000000 +0000 +++ qemu-10.0.6+ds/include/hw/intc/arm_gicv3_common.h 2025-10-20 18:13:46.000000000 +0000 @@ -27,6 +27,7 @@ #include "hw/sysbus.h" #include "hw/intc/arm_gic_common.h" #include "qom/object.h" +#include "qemu/notify.h" /* * Maximum number of possible interrupts, determined by the GIC architecture. @@ -270,6 +271,8 @@ GICv3CPUState *cpu; /* List of all ITSes connected to this GIC */ GPtrArray *itslist; + + NotifierWithReturn cpr_notifier; }; #define GICV3_BITMAP_ACCESSORS(BMP) \ diff -Nru qemu-10.0.3+ds/include/hw/pci/pcie_sriov.h qemu-10.0.6+ds/include/hw/pci/pcie_sriov.h --- qemu-10.0.3+ds/include/hw/pci/pcie_sriov.h 2025-07-23 21:05:28.000000000 +0000 +++ qemu-10.0.6+ds/include/hw/pci/pcie_sriov.h 2025-10-20 18:13:46.000000000 +0000 @@ -36,10 +36,6 @@ void pcie_sriov_pf_init_vf_bar(PCIDevice *dev, int region_num, uint8_t type, dma_addr_t size); -/* Instantiate a bar for a VF */ -void pcie_sriov_vf_register_bar(PCIDevice *dev, int region_num, - MemoryRegion *memory); - /* * Default (minimal) page size support values * as required by the SR/IOV standard: diff -Nru qemu-10.0.3+ds/include/hw/ppc/xive2_regs.h qemu-10.0.6+ds/include/hw/ppc/xive2_regs.h --- qemu-10.0.3+ds/include/hw/ppc/xive2_regs.h 2025-07-23 21:05:28.000000000 +0000 +++ qemu-10.0.6+ds/include/hw/ppc/xive2_regs.h 2025-10-20 18:13:46.000000000 +0000 @@ -87,6 +87,7 @@ #define END2_W2_EQ_ADDR_HI PPC_BITMASK32(8, 31) uint32_t w3; #define END2_W3_EQ_ADDR_LO PPC_BITMASK32(0, 24) +#define END2_W3_CL PPC_BIT32(27) #define END2_W3_QSIZE PPC_BITMASK32(28, 31) uint32_t w4; #define END2_W4_END_BLOCK PPC_BITMASK32(4, 7) diff -Nru qemu-10.0.3+ds/include/qemu/compiler.h qemu-10.0.6+ds/include/qemu/compiler.h --- qemu-10.0.3+ds/include/qemu/compiler.h 2025-07-23 21:05:28.000000000 +0000 +++ qemu-10.0.6+ds/include/qemu/compiler.h 2025-10-20 18:13:46.000000000 +0000 @@ -182,19 +182,6 @@ #define QEMU_DISABLE_CFI #endif -/* - * Apple clang version 14 has a bug in its __builtin_subcll(); define - * BUILTIN_SUBCLL_BROKEN for the offending versions so we can avoid it. - * When a version of Apple clang which has this bug fixed is released - * we can add an upper bound to this check. - * See https://gitlab.com/qemu-project/qemu/-/issues/1631 - * and https://gitlab.com/qemu-project/qemu/-/issues/1659 for details. - * The bug never made it into any upstream LLVM releases, only Apple ones. - */ -#if defined(__apple_build_version__) && __clang_major__ >= 14 -#define BUILTIN_SUBCLL_BROKEN -#endif - #if __has_attribute(annotate) #define QEMU_ANNOTATE(x) __attribute__((annotate(x))) #else diff -Nru qemu-10.0.3+ds/include/qemu/host-utils.h qemu-10.0.6+ds/include/qemu/host-utils.h --- qemu-10.0.3+ds/include/qemu/host-utils.h 2025-07-23 21:05:28.000000000 +0000 +++ qemu-10.0.6+ds/include/qemu/host-utils.h 2025-10-20 18:13:46.000000000 +0000 @@ -677,7 +677,7 @@ */ static inline uint64_t usub64_borrow(uint64_t x, uint64_t y, bool *pborrow) { -#if __has_builtin(__builtin_subcll) && !defined(BUILTIN_SUBCLL_BROKEN) +#if __has_builtin(__builtin_subcll) unsigned long long b = *pborrow; x = __builtin_subcll(x, y, b, &b); *pborrow = b & 1; diff -Nru qemu-10.0.3+ds/linux-user/aarch64/signal.c qemu-10.0.6+ds/linux-user/aarch64/signal.c --- qemu-10.0.3+ds/linux-user/aarch64/signal.c 2025-07-23 21:05:28.000000000 +0000 +++ qemu-10.0.6+ds/linux-user/aarch64/signal.c 2025-10-20 18:13:46.000000000 +0000 @@ -121,6 +121,13 @@ #define TARGET_ZA_SIG_CONTEXT_SIZE(VQ) \ TARGET_ZA_SIG_ZAV_OFFSET(VQ, VQ * TARGET_SVE_VQ_BYTES) +#define TARGET_TPIDR2_MAGIC 0x54504902 + +struct target_tpidr2_context { + struct target_aarch64_ctx head; + uint64_t tpidr2; +}; + struct target_rt_sigframe { struct target_siginfo info; struct target_ucontext uc; @@ -253,6 +260,14 @@ } } +static void target_setup_tpidr2_record(struct target_tpidr2_context *tpidr2, + CPUARMState *env) +{ + __put_user(TARGET_TPIDR2_MAGIC, &tpidr2->head.magic); + __put_user(sizeof(struct target_tpidr2_context), &tpidr2->head.size); + __put_user(env->cp15.tpidr2_el0, &tpidr2->tpidr2); +} + static void target_restore_general_frame(CPUARMState *env, struct target_rt_sigframe *sf) { @@ -403,6 +418,12 @@ return true; } +static void target_restore_tpidr2_record(CPUARMState *env, + struct target_tpidr2_context *tpidr2) +{ + __get_user(env->cp15.tpidr2_el0, &tpidr2->tpidr2); +} + static int target_restore_sigframe(CPUARMState *env, struct target_rt_sigframe *sf) { @@ -410,6 +431,7 @@ struct target_fpsimd_context *fpsimd = NULL; struct target_sve_context *sve = NULL; struct target_za_context *za = NULL; + struct target_tpidr2_context *tpidr2 = NULL; uint64_t extra_datap = 0; bool used_extra = false; int sve_size = 0; @@ -460,6 +482,14 @@ za_size = size; break; + case TARGET_TPIDR2_MAGIC: + if (tpidr2 || size != sizeof(struct target_tpidr2_context) || + !cpu_isar_feature(aa64_sme, env_archcpu(env))) { + goto err; + } + tpidr2 = (struct target_tpidr2_context *)ctx; + break; + case TARGET_EXTRA_MAGIC: if (extra || size != sizeof(struct target_extra_context)) { goto err; @@ -497,6 +527,9 @@ if (za && !target_restore_za_record(env, za, za_size, &svcr)) { goto err; } + if (tpidr2) { + target_restore_tpidr2_record(env, tpidr2); + } if (env->svcr != svcr) { env->svcr = svcr; arm_rebuild_hflags(env); @@ -568,8 +601,8 @@ .total_size = offsetof(struct target_rt_sigframe, uc.tuc_mcontext.__reserved), }; - int fpsimd_ofs, fr_ofs, sve_ofs = 0, za_ofs = 0; - int sve_size = 0, za_size = 0; + int fpsimd_ofs, fr_ofs, sve_ofs = 0, za_ofs = 0, tpidr2_ofs = 0; + int sve_size = 0, za_size = 0, tpidr2_size = 0; struct target_rt_sigframe *frame; struct target_rt_frame_record *fr; abi_ulong frame_addr, return_addr; @@ -585,6 +618,8 @@ sve_ofs = alloc_sigframe_space(sve_size, &layout); } if (cpu_isar_feature(aa64_sme, env_archcpu(env))) { + tpidr2_size = sizeof(struct target_tpidr2_context); + tpidr2_ofs = alloc_sigframe_space(tpidr2_size, &layout); /* ZA state needs saving only if it is enabled. */ if (FIELD_EX64(env->svcr, SVCR, ZA)) { za_size = TARGET_ZA_SIG_CONTEXT_SIZE(sme_vq(env)); @@ -644,6 +679,9 @@ if (za_ofs) { target_setup_za_record((void *)frame + za_ofs, env, za_size); } + if (tpidr2_ofs) { + target_setup_tpidr2_record((void *)frame + tpidr2_ofs, env); + } /* Set up the stack frame for unwinding. */ fr = (void *)frame + fr_ofs; @@ -666,8 +704,12 @@ env->btype = 2; } - /* Invoke the signal handler with both SM and ZA disabled. */ + /* + * Invoke the signal handler with a clean SME state: both SM and ZA + * disabled and TPIDR2_EL0 cleared. + */ aarch64_set_svcr(env, 0, R_SVCR_SM_MASK | R_SVCR_ZA_MASK); + env->cp15.tpidr2_el0 = 0; if (info) { frame->info = *info; diff -Nru qemu-10.0.3+ds/linux-user/microblaze/target_elf.h qemu-10.0.6+ds/linux-user/microblaze/target_elf.h --- qemu-10.0.3+ds/linux-user/microblaze/target_elf.h 2025-07-23 21:05:28.000000000 +0000 +++ qemu-10.0.6+ds/linux-user/microblaze/target_elf.h 2025-10-20 18:13:46.000000000 +0000 @@ -9,6 +9,7 @@ #define MICROBLAZE_TARGET_ELF_H static inline const char *cpu_get_model(uint32_t eflags) { - return "any"; + return TARGET_BIG_ENDIAN ? "any,little-endian=off" + : "any,little-endian=on"; } #endif diff -Nru qemu-10.0.3+ds/linux-user/mips/target_elf.h qemu-10.0.6+ds/linux-user/mips/target_elf.h --- qemu-10.0.3+ds/linux-user/mips/target_elf.h 2025-07-23 21:05:28.000000000 +0000 +++ qemu-10.0.6+ds/linux-user/mips/target_elf.h 2025-10-20 18:13:46.000000000 +0000 @@ -12,6 +12,12 @@ if ((eflags & EF_MIPS_ARCH) == EF_MIPS_ARCH_32R6) { return "mips32r6-generic"; } + if ((eflags & EF_MIPS_ARCH_ASE) == EF_MIPS_ARCH_ASE_MICROMIPS) { + return "M14Kc"; + } + if ((eflags & EF_MIPS_ARCH_ASE) == EF_MIPS_ARCH_ASE_M16) { + return "74Kf"; + } if (eflags & EF_MIPS_NAN2008) { return "P5600"; } diff -Nru qemu-10.0.3+ds/linux-user/strace.c qemu-10.0.6+ds/linux-user/strace.c --- qemu-10.0.3+ds/linux-user/strace.c 2025-07-23 21:05:28.000000000 +0000 +++ qemu-10.0.6+ds/linux-user/strace.c 2025-10-20 18:13:46.000000000 +0000 @@ -54,7 +54,7 @@ }; /* No 'struct flags' element should have a zero mask. */ -#define FLAG_BASIC(V, M, N) { V, M | QEMU_BUILD_BUG_ON_ZERO(!(M)), N } +#define FLAG_BASIC(V, M, N) { V, M | QEMU_BUILD_BUG_ON_ZERO((M) == 0), N } /* common flags for all architectures */ #define FLAG_GENERIC_MASK(V, M) FLAG_BASIC(V, M, #V) diff -Nru qemu-10.0.3+ds/linux-user/strace.list qemu-10.0.6+ds/linux-user/strace.list --- qemu-10.0.3+ds/linux-user/strace.list 2025-07-23 21:05:28.000000000 +0000 +++ qemu-10.0.6+ds/linux-user/strace.list 2025-10-20 18:13:46.000000000 +0000 @@ -1716,3 +1716,9 @@ { TARGET_NR_clock_gettime64, "clock_gettime64" , NULL, print_clock_gettime64, print_syscall_ret_clock_gettime64 }, #endif +#ifdef TARGET_NR_riscv_hwprobe +{ TARGET_NR_riscv_hwprobe, "riscv_hwprobe" , "%s(%p,%d,%d,%d,%d,%d)", NULL, NULL }, +#endif +#ifdef TARGET_NR_rseq +{ TARGET_NR_rseq, "rseq" , "%s(%p,%u,%d,%#x)", NULL, NULL }, +#endif diff -Nru qemu-10.0.3+ds/migration/migration.c qemu-10.0.6+ds/migration/migration.c --- qemu-10.0.3+ds/migration/migration.c 2025-07-23 21:05:28.000000000 +0000 +++ qemu-10.0.6+ds/migration/migration.c 2025-10-20 18:13:46.000000000 +0000 @@ -2843,8 +2843,9 @@ fail_closefb: qemu_fclose(fb); fail: - migrate_set_state(&ms->state, MIGRATION_STATUS_POSTCOPY_ACTIVE, - MIGRATION_STATUS_FAILED); + if (ms->state != MIGRATION_STATUS_CANCELLING) { + migrate_set_state(&ms->state, ms->state, MIGRATION_STATUS_FAILED); + } migration_block_activate(NULL); migration_call_notifiers(ms, MIG_EVENT_PRECOPY_FAILED, NULL); bql_unlock(); diff -Nru qemu-10.0.3+ds/pc-bios/optionrom/multiboot.S qemu-10.0.6+ds/pc-bios/optionrom/multiboot.S --- qemu-10.0.3+ds/pc-bios/optionrom/multiboot.S 2025-07-23 21:05:28.000000000 +0000 +++ qemu-10.0.6+ds/pc-bios/optionrom/multiboot.S 2025-10-20 18:13:46.000000000 +0000 @@ -208,7 +208,7 @@ prot_jump: .long prot_mode .short 8 -.align 4, 0 +.align 8, 0 gdt: /* 0x00 */ .byte 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 diff -Nru qemu-10.0.3+ds/python/qemu/machine/qtest.py qemu-10.0.6+ds/python/qemu/machine/qtest.py --- qemu-10.0.3+ds/python/qemu/machine/qtest.py 2025-07-23 21:05:28.000000000 +0000 +++ qemu-10.0.6+ds/python/qemu/machine/qtest.py 2025-10-20 18:13:46.000000000 +0000 @@ -177,6 +177,8 @@ self._qtest_sock_pair[0].close() self._qtest_sock_pair[1].close() self._qtest_sock_pair = None + if self._qtest is not None: + self._qtest.close() super()._post_shutdown() def qtest(self, cmd: str) -> str: diff -Nru qemu-10.0.3+ds/python/qemu/qmp/legacy.py qemu-10.0.6+ds/python/qemu/qmp/legacy.py --- qemu-10.0.3+ds/python/qemu/qmp/legacy.py 2025-07-23 21:05:28.000000000 +0000 +++ qemu-10.0.6+ds/python/qemu/qmp/legacy.py 2025-10-20 18:13:46.000000000 +0000 @@ -38,6 +38,7 @@ from .error import QMPError from .protocol import Runstate, SocketAddrT from .qmp_client import QMPClient +from .util import get_or_create_event_loop #: QMPMessage is an entire QMP message of any kind. @@ -86,10 +87,13 @@ "server argument should be False when passing a socket") self._qmp = QMPClient(nickname) - self._aloop = asyncio.get_event_loop() self._address = address self._timeout: Optional[float] = None + # This is a sync shim intended for use in fully synchronous + # programs. Create and set an event loop if necessary. + self._aloop = get_or_create_event_loop() + if server: assert not isinstance(self._address, socket.socket) self._sync(self._qmp.start_server(self._address)) @@ -231,6 +235,9 @@ :return: The first available QMP event, or None. """ + # Kick the event loop to allow events to accumulate + self._sync(asyncio.sleep(0)) + if not wait: # wait is False/0: "do not wait, do not except." if self._qmp.events.empty(): @@ -303,17 +310,30 @@ self._qmp.send_fd_scm(fd) def __del__(self) -> None: - if self._qmp.runstate == Runstate.IDLE: - return + if self._qmp.runstate != Runstate.IDLE: + self._qmp.logger.warning( + "QEMUMonitorProtocol object garbage collected without a prior " + "call to close()" + ) if not self._aloop.is_running(): - self.close() - else: - # Garbage collection ran while the event loop was running. - # Nothing we can do about it now, but if we don't raise our - # own error, the user will be treated to a lot of traceback - # they might not understand. + if self._qmp.runstate != Runstate.IDLE: + # If the user neglected to close the QMP session and we + # are not currently running in an asyncio context, we + # have the opportunity to close the QMP session. If we + # do not do this, the error messages presented over + # dangling async resources may not make any sense to the + # user. + self.close() + + if self._qmp.runstate != Runstate.IDLE: + # If QMP is still not quiesced, it means that the garbage + # collector ran from a context within the event loop and we + # are simply too late to take any corrective action. Raise + # our own error to give meaningful feedback to the user in + # order to prevent pages of asyncio stacktrace jargon. raise QMPError( - "QEMUMonitorProtocol.close()" - " was not called before object was garbage collected" + "QEMUMonitorProtocol.close() was not called before object was " + "garbage collected, and could not be closed due to GC running " + "in the event loop" ) diff -Nru qemu-10.0.3+ds/python/qemu/qmp/protocol.py qemu-10.0.6+ds/python/qemu/qmp/protocol.py --- qemu-10.0.3+ds/python/qemu/qmp/protocol.py 2025-07-23 21:05:28.000000000 +0000 +++ qemu-10.0.6+ds/python/qemu/qmp/protocol.py 2025-10-20 18:13:46.000000000 +0000 @@ -15,6 +15,7 @@ import asyncio from asyncio import StreamReader, StreamWriter +from contextlib import asynccontextmanager from enum import Enum from functools import wraps import logging @@ -22,6 +23,7 @@ from ssl import SSLContext from typing import ( Any, + AsyncGenerator, Awaitable, Callable, Generic, @@ -36,13 +38,10 @@ from .error import QMPError from .util import ( bottom_half, - create_task, exception_summary, flush, - is_closing, pretty_traceback, upper_half, - wait_closed, ) @@ -321,9 +320,8 @@ This exception will wrap a more concrete one. In most cases, the wrapped exception will be `OSError`. """ - await self._session_guard( - self._do_start_server(address, ssl), - 'Failed to establish connection') + async with self._session_guard('Failed to establish connection'): + await self._do_start_server(address, ssl) assert self.runstate == Runstate.CONNECTING @upper_half @@ -346,12 +344,10 @@ """ if self._accepted is None: raise QMPError("Cannot call accept() before start_server().") - await self._session_guard( - self._do_accept(), - 'Failed to establish connection') - await self._session_guard( - self._establish_session(), - 'Failed to establish session') + async with self._session_guard('Failed to establish connection'): + await self._do_accept() + async with self._session_guard('Failed to establish session'): + await self._establish_session() assert self.runstate == Runstate.RUNNING @upper_half @@ -376,12 +372,10 @@ protocol-level failure occurs while establishing a new session, the wrapped error may also be an `QMPError`. """ - await self._session_guard( - self._do_connect(address, ssl), - 'Failed to establish connection') - await self._session_guard( - self._establish_session(), - 'Failed to establish session') + async with self._session_guard('Failed to establish connection'): + await self._do_connect(address, ssl) + async with self._session_guard('Failed to establish session'): + await self._establish_session() assert self.runstate == Runstate.RUNNING @upper_half @@ -402,7 +396,8 @@ # Section: Session machinery # -------------------------- - async def _session_guard(self, coro: Awaitable[None], emsg: str) -> None: + @asynccontextmanager + async def _session_guard(self, emsg: str) -> AsyncGenerator[None, None]: """ Async guard function used to roll back to `IDLE` on any error. @@ -419,10 +414,9 @@ :raise ConnectError: When any other error is encountered in the guarded block. """ - # Note: After Python 3.6 support is removed, this should be an - # @asynccontextmanager instead of accepting a callback. try: - await coro + # Caller's code runs here. + yield except BaseException as err: self.logger.error("%s: %s", emsg, exception_summary(err)) self.logger.debug("%s:\n%s\n", emsg, pretty_traceback()) @@ -663,8 +657,8 @@ reader_coro = self._bh_loop_forever(self._bh_recv_message, 'Reader') writer_coro = self._bh_loop_forever(self._bh_send_message, 'Writer') - self._reader_task = create_task(reader_coro) - self._writer_task = create_task(writer_coro) + self._reader_task = asyncio.create_task(reader_coro) + self._writer_task = asyncio.create_task(writer_coro) self._bh_tasks = asyncio.gather( self._reader_task, @@ -689,7 +683,7 @@ if not self._dc_task: self._set_state(Runstate.DISCONNECTING) self.logger.debug("Scheduling disconnect.") - self._dc_task = create_task(self._bh_disconnect()) + self._dc_task = asyncio.create_task(self._bh_disconnect()) @upper_half async def _wait_disconnect(self) -> None: @@ -825,13 +819,13 @@ if not self._writer: return - if not is_closing(self._writer): + if not self._writer.is_closing(): self.logger.debug("Closing StreamWriter.") self._writer.close() self.logger.debug("Waiting for StreamWriter to close ...") try: - await wait_closed(self._writer) + await self._writer.wait_closed() except Exception: # pylint: disable=broad-except # It's hard to tell if the Stream is already closed or # not. Even if one of the tasks has failed, it may have diff -Nru qemu-10.0.3+ds/python/qemu/qmp/qmp_shell.py qemu-10.0.6+ds/python/qemu/qmp/qmp_shell.py --- qemu-10.0.3+ds/python/qemu/qmp/qmp_shell.py 2025-07-23 21:05:28.000000000 +0000 +++ qemu-10.0.6+ds/python/qemu/qmp/qmp_shell.py 2025-10-20 18:13:46.000000000 +0000 @@ -610,6 +610,8 @@ for _ in qemu.repl(): pass + except FileNotFoundError: + sys.stderr.write(f"ERROR: QEMU executable '{cmd[0]}' not found.\n") finally: os.unlink(sockpath) diff -Nru qemu-10.0.3+ds/python/qemu/qmp/qmp_tui.py qemu-10.0.6+ds/python/qemu/qmp/qmp_tui.py --- qemu-10.0.3+ds/python/qemu/qmp/qmp_tui.py 2025-07-23 21:05:28.000000000 +0000 +++ qemu-10.0.6+ds/python/qemu/qmp/qmp_tui.py 2025-10-20 18:13:46.000000000 +0000 @@ -21,6 +21,7 @@ import logging from logging import Handler, LogRecord import signal +import sys from typing import ( List, Optional, @@ -30,17 +31,27 @@ cast, ) -from pygments import lexers -from pygments import token as Token -import urwid -import urwid_readline + +try: + from pygments import lexers + from pygments import token as Token + import urwid + import urwid_readline +except ModuleNotFoundError as exc: + print( + f"Module '{exc.name}' not found.", + "You need the optional 'tui' group: pip install qemu.qmp[tui]", + sep='\n', + file=sys.stderr, + ) + sys.exit(1) from .error import ProtocolError from .legacy import QEMUMonitorProtocol, QMPBadPortError from .message import DeserializationError, Message, UnexpectedTypeError from .protocol import ConnectError, Runstate from .qmp_client import ExecInterruptedError, QMPClient -from .util import create_task, pretty_traceback +from .util import get_or_create_event_loop, pretty_traceback # The name of the signal that is used to update the history list @@ -225,7 +236,7 @@ """ try: msg = Message(bytes(raw_msg, encoding='utf-8')) - create_task(self._send_to_server(msg)) + asyncio.create_task(self._send_to_server(msg)) except (DeserializationError, UnexpectedTypeError) as err: raw_msg = format_json(raw_msg) logging.info('Invalid message: %s', err.error_message) @@ -246,7 +257,7 @@ Initiates killing of app. A bridge between asynchronous and synchronous code. """ - create_task(self._kill_app()) + asyncio.create_task(self._kill_app()) async def _kill_app(self) -> None: """ @@ -376,8 +387,7 @@ """ screen = urwid.raw_display.Screen() screen.set_terminal_properties(256) - - self.aloop = asyncio.get_event_loop() + self.aloop = get_or_create_event_loop() self.aloop.set_debug(debug) # Gracefully handle SIGTERM and SIGINT signals @@ -393,7 +403,7 @@ handle_mouse=True, event_loop=event_loop) - create_task(self.manage_connection(), self.aloop) + self.aloop.create_task(self.manage_connection()) try: main_loop.run() except Exception as err: diff -Nru qemu-10.0.3+ds/python/qemu/qmp/util.py qemu-10.0.6+ds/python/qemu/qmp/util.py --- qemu-10.0.3+ds/python/qemu/qmp/util.py 2025-07-23 21:05:28.000000000 +0000 +++ qemu-10.0.6+ds/python/qemu/qmp/util.py 2025-10-20 18:13:46.000000000 +0000 @@ -1,25 +1,16 @@ """ Miscellaneous Utilities -This module provides asyncio utilities and compatibility wrappers for -Python 3.6 to provide some features that otherwise become available in -Python 3.7+. - -Various logging and debugging utilities are also provided, such as -`exception_summary()` and `pretty_traceback()`, used primarily for -adding information into the logging stream. +This module provides asyncio and various logging and debugging +utilities, such as `exception_summary()` and `pretty_traceback()`, used +primarily for adding information into the logging stream. """ import asyncio import sys import traceback -from typing import ( - Any, - Coroutine, - Optional, - TypeVar, - cast, -) +from typing import TypeVar, cast +import warnings T = TypeVar('T') @@ -30,6 +21,32 @@ # -------------------------- +def get_or_create_event_loop() -> asyncio.AbstractEventLoop: + """ + Return this thread's current event loop, or create a new one. + + This function behaves similarly to asyncio.get_event_loop() in + Python<=3.13, where if there is no event loop currently associated + with the current context, it will create and register one. It should + generally not be used in any asyncio-native applications. + """ + try: + with warnings.catch_warnings(): + # Python <= 3.13 will trigger deprecation warnings if no + # event loop is set, but will create and set a new loop. + warnings.simplefilter("ignore") + loop = asyncio.get_event_loop() + except RuntimeError: + # Python 3.14+: No event loop set for this thread, + # create and set one. + loop = asyncio.new_event_loop() + # Set this loop as the current thread's loop, to be returned + # by calls to get_event_loop() in the future. + asyncio.set_event_loop(loop) + + return loop + + async def flush(writer: asyncio.StreamWriter) -> None: """ Utility function to ensure a StreamWriter is *fully* drained. @@ -79,95 +96,6 @@ return func -# ------------------------------- -# Section: Compatibility Wrappers -# ------------------------------- - - -def create_task(coro: Coroutine[Any, Any, T], - loop: Optional[asyncio.AbstractEventLoop] = None - ) -> 'asyncio.Future[T]': - """ - Python 3.6-compatible `asyncio.create_task` wrapper. - - :param coro: The coroutine to execute in a task. - :param loop: Optionally, the loop to create the task in. - - :return: An `asyncio.Future` object. - """ - if sys.version_info >= (3, 7): - if loop is not None: - return loop.create_task(coro) - return asyncio.create_task(coro) # pylint: disable=no-member - - # Python 3.6: - return asyncio.ensure_future(coro, loop=loop) - - -def is_closing(writer: asyncio.StreamWriter) -> bool: - """ - Python 3.6-compatible `asyncio.StreamWriter.is_closing` wrapper. - - :param writer: The `asyncio.StreamWriter` object. - :return: `True` if the writer is closing, or closed. - """ - if sys.version_info >= (3, 7): - return writer.is_closing() - - # Python 3.6: - transport = writer.transport - assert isinstance(transport, asyncio.WriteTransport) - return transport.is_closing() - - -async def wait_closed(writer: asyncio.StreamWriter) -> None: - """ - Python 3.6-compatible `asyncio.StreamWriter.wait_closed` wrapper. - - :param writer: The `asyncio.StreamWriter` to wait on. - """ - if sys.version_info >= (3, 7): - await writer.wait_closed() - return - - # Python 3.6 - transport = writer.transport - assert isinstance(transport, asyncio.WriteTransport) - - while not transport.is_closing(): - await asyncio.sleep(0) - - # This is an ugly workaround, but it's the best I can come up with. - sock = transport.get_extra_info('socket') - - if sock is None: - # Our transport doesn't have a socket? ... - # Nothing we can reasonably do. - return - - while sock.fileno() != -1: - await asyncio.sleep(0) - - -def asyncio_run(coro: Coroutine[Any, Any, T], *, debug: bool = False) -> T: - """ - Python 3.6-compatible `asyncio.run` wrapper. - - :param coro: A coroutine to execute now. - :return: The return value from the coroutine. - """ - if sys.version_info >= (3, 7): - return asyncio.run(coro, debug=debug) - - # Python 3.6 - loop = asyncio.get_event_loop() - loop.set_debug(debug) - ret = loop.run_until_complete(coro) - loop.close() - - return ret - - # ---------------------------- # Section: Logging & Debugging # ---------------------------- diff -Nru qemu-10.0.3+ds/python/scripts/mkvenv.py qemu-10.0.6+ds/python/scripts/mkvenv.py --- qemu-10.0.3+ds/python/scripts/mkvenv.py 2025-07-23 21:05:28.000000000 +0000 +++ qemu-10.0.6+ds/python/scripts/mkvenv.py 2025-10-20 18:13:46.000000000 +0000 @@ -84,6 +84,7 @@ Sequence, Tuple, Union, + cast, ) import venv @@ -94,17 +95,39 @@ HAVE_DISTLIB = True try: import distlib.scripts - import distlib.version except ImportError: try: # Reach into pip's cookie jar. pylint and flake8 don't understand # that these imports will be used via distlib.xxx. from pip._vendor import distlib import pip._vendor.distlib.scripts # noqa, pylint: disable=unused-import - import pip._vendor.distlib.version # noqa, pylint: disable=unused-import except ImportError: HAVE_DISTLIB = False +# pip 25.2 does not vendor distlib.version, but it uses vendored +# packaging.version +HAVE_DISTLIB_VERSION = True +try: + import distlib.version # pylint: disable=ungrouped-imports +except ImportError: + try: + # pylint: disable=unused-import,ungrouped-imports + import pip._vendor.distlib.version # noqa + except ImportError: + HAVE_DISTLIB_VERSION = False + +HAVE_PACKAGING_VERSION = True +try: + # Do not bother importing non-vendored packaging, because it is not + # in stdlib. + from pip._vendor import packaging + # pylint: disable=unused-import + import pip._vendor.packaging.requirements # noqa + import pip._vendor.packaging.version # noqa +except ImportError: + HAVE_PACKAGING_VERSION = False + + # Try to load tomllib, with a fallback to tomli. # HAVE_TOMLLIB is checked below, just-in-time, so that mkvenv does not fail # outside the venv or before a potential call to ensurepip in checkpip(). @@ -133,6 +156,43 @@ """An Exception class we can't confuse with a builtin.""" +class Matcher: + """Compatibility appliance for version/requirement string parsing.""" + def __init__(self, name_and_constraint: str): + """Create a matcher from a requirement-like string.""" + if HAVE_DISTLIB_VERSION: + self._m = distlib.version.LegacyMatcher(name_and_constraint) + elif HAVE_PACKAGING_VERSION: + self._m = packaging.requirements.Requirement(name_and_constraint) + else: + raise Ouch("found neither distlib.version nor packaging.version") + self.name = self._m.name + + def match(self, version_str: str) -> bool: + """Return True if `version` satisfies the stored constraint.""" + if HAVE_DISTLIB_VERSION: + return cast( + bool, + self._m.match(distlib.version.LegacyVersion(version_str)) + ) + + assert HAVE_PACKAGING_VERSION + return cast( + bool, + self._m.specifier.contains( + packaging.version.Version(version_str), prereleases=True + ) + ) + + def __str__(self) -> str: + """String representation delegated to the backend.""" + return str(self._m) + + def __repr__(self) -> str: + """Stable debug representation delegated to the backend.""" + return repr(self._m) + + class QemuEnvBuilder(venv.EnvBuilder): """ An extension of venv.EnvBuilder for building QEMU's configure-time venv. @@ -669,7 +729,7 @@ canary = None for name, info in group.items(): constraint = _make_version_constraint(info, False) - matcher = distlib.version.LegacyMatcher(name + constraint) + matcher = Matcher(name + constraint) print(f"mkvenv: checking for {matcher}", file=sys.stderr) dist: Optional[Distribution] = None @@ -683,7 +743,7 @@ # Always pass installed package to pip, so that they can be # updated if the requested version changes or not _is_system_package(dist) - or not matcher.match(distlib.version.LegacyVersion(dist.version)) + or not matcher.match(dist.version) ): absent.append(name + _make_version_constraint(info, True)) if len(absent) == 1: diff -Nru qemu-10.0.3+ds/python/tests/protocol.py qemu-10.0.6+ds/python/tests/protocol.py --- qemu-10.0.3+ds/python/tests/protocol.py 2025-07-23 21:05:28.000000000 +0000 +++ qemu-10.0.6+ds/python/tests/protocol.py 2025-10-20 18:13:46.000000000 +0000 @@ -8,7 +8,6 @@ from qemu.qmp import ConnectError, Runstate from qemu.qmp.protocol import AsyncProtocol, StateError -from qemu.qmp.util import asyncio_run, create_task class NullProtocol(AsyncProtocol[None]): @@ -124,7 +123,7 @@ if allow_cancellation: return raise - return create_task(_runner()) + return asyncio.create_task(_runner()) @contextmanager @@ -228,7 +227,7 @@ Decorator; adds SetUp and TearDown to async tests. """ async def _wrapper(self, *args, **kwargs): - loop = asyncio.get_event_loop() + loop = asyncio.get_running_loop() loop.set_debug(True) await self._asyncSetUp() @@ -271,7 +270,7 @@ msg=f"Expected state '{state.name}'", ) - self.runstate_watcher = create_task(_watcher()) + self.runstate_watcher = asyncio.create_task(_watcher()) # Kick the loop and force the task to block on the event. await asyncio.sleep(0) @@ -589,7 +588,8 @@ async def testSmoke(self): with TemporaryDirectory(suffix='.qmp') as tmpdir: sock = os.path.join(tmpdir, type(self.proto).__name__ + ".sock") - server_task = create_task(self.server.start_server_and_accept(sock)) + server_task = asyncio.create_task( + self.server.start_server_and_accept(sock)) # give the server a chance to start listening [...] await asyncio.sleep(0) diff -Nru qemu-10.0.3+ds/qapi/block-core.json qemu-10.0.6+ds/qapi/block-core.json --- qemu-10.0.3+ds/qapi/block-core.json 2025-07-23 21:05:28.000000000 +0000 +++ qemu-10.0.6+ds/qapi/block-core.json 2025-10-20 18:13:46.000000000 +0000 @@ -158,7 +158,14 @@ ## # @ImageInfoSpecificRbd: # -# @encryption-format: Image encryption format +# @encryption-format: Image encryption format. If encryption is enabled for the +# image (see encrypted in BlockNodeInfo), this is the actual format in which the +# image is accessed. If encryption is not enabled, this is the result of +# probing when the image was opened, to give a suggestion which encryption +# format could be enabled. Note that probing results can be changed by the +# guest by writing a (possibly partial) encryption format header to the +# image, so don't treat this information as trusted if the guest is not +# trusted. # # Since: 6.1 ## diff -Nru qemu-10.0.3+ds/qga/commands-linux.c qemu-10.0.6+ds/qga/commands-linux.c --- qemu-10.0.3+ds/qga/commands-linux.c 2025-07-23 21:05:28.000000000 +0000 +++ qemu-10.0.6+ds/qga/commands-linux.c 2025-10-20 18:13:46.000000000 +0000 @@ -1400,20 +1400,22 @@ static void linux_sys_state_suspend(SuspendMode mode, Error **errp) { - g_autoptr(GError) local_gerr = NULL; const char *sysfile_strs[3] = {"disk", "mem", NULL}; const char *sysfile_str = sysfile_strs[mode]; + int fd; if (!sysfile_str) { error_setg(errp, "unknown guest suspend mode"); return; } - if (!g_file_set_contents(LINUX_SYS_STATE_FILE, sysfile_str, - -1, &local_gerr)) { - error_setg(errp, "suspend: cannot write to '%s': %s", - LINUX_SYS_STATE_FILE, local_gerr->message); - return; + fd = open(LINUX_SYS_STATE_FILE, O_WRONLY); + if (fd < 0 || write(fd, sysfile_str, strlen(sysfile_str)) < 0) { + error_setg(errp, "suspend: cannot write to '%s': %m", + LINUX_SYS_STATE_FILE); + } + if (fd >= 0) { + close(fd); } } diff -Nru qemu-10.0.3+ds/qga/commands.c qemu-10.0.6+ds/qga/commands.c --- qemu-10.0.3+ds/qga/commands.c 2025-07-23 21:05:28.000000000 +0000 +++ qemu-10.0.6+ds/qga/commands.c 2025-10-20 18:13:46.000000000 +0000 @@ -205,13 +205,15 @@ #endif if (gei->out.length > 0) { ges->out_data = g_base64_encode(gei->out.data, gei->out.length); - ges->has_out_truncated = gei->out.truncated; + ges->has_out_truncated = true; + ges->out_truncated = gei->out.truncated; } g_free(gei->out.data); if (gei->err.length > 0) { ges->err_data = g_base64_encode(gei->err.data, gei->err.length); - ges->has_err_truncated = gei->err.truncated; + ges->has_err_truncated = true; + ges->err_truncated = gei->err.truncated; } g_free(gei->err.data); diff -Nru qemu-10.0.3+ds/qga/installer/qemu-ga.wxs qemu-10.0.6+ds/qga/installer/qemu-ga.wxs --- qemu-10.0.3+ds/qga/installer/qemu-ga.wxs 2025-07-23 21:05:28.000000000 +0000 +++ qemu-10.0.6+ds/qga/installer/qemu-ga.wxs 2025-10-20 18:13:46.000000000 +0000 @@ -151,6 +151,14 @@ Return="check" > + + @@ -174,8 +182,19 @@ - Installed - NOT REMOVE + + + + + + + NOT REMOVE + + + NOT REMOVE + + + Installed diff -Nru qemu-10.0.3+ds/qga/vss-win32/requester.cpp qemu-10.0.6+ds/qga/vss-win32/requester.cpp --- qemu-10.0.3+ds/qga/vss-win32/requester.cpp 2025-07-23 21:05:28.000000000 +0000 +++ qemu-10.0.6+ds/qga/vss-win32/requester.cpp 2025-10-20 18:13:46.000000000 +0000 @@ -28,8 +28,9 @@ #define err_set(e, err, fmt, ...) { \ (e)->error_setg_win32_wrapper((e)->errp, __FILE__, __LINE__, __func__, \ - err, fmt, ## __VA_ARGS__); \ - qga_debug(fmt, ## __VA_ARGS__); \ + err, fmt ": Windows error 0x%lx", \ + ## __VA_ARGS__, err); \ + qga_debug(fmt ": Windows error 0x%lx", ## __VA_ARGS__, err); \ } /* Bad idea, works only when (e)->errp != NULL: */ #define err_is_set(e) ((e)->errp && *(e)->errp) diff -Nru qemu-10.0.3+ds/roms/Makefile qemu-10.0.6+ds/roms/Makefile --- qemu-10.0.3+ds/roms/Makefile 2025-07-23 21:05:28.000000000 +0000 +++ qemu-10.0.6+ds/roms/Makefile 2025-10-20 18:13:46.000000000 +0000 @@ -193,12 +193,12 @@ cp qboot/build/bios.bin ../pc-bios/qboot.rom npcm7xx_bootrom: - $(MAKE) -C vbootrom CROSS_COMPILE=$(arm_cross_prefix) - cp vbootrom/npcm7xx_bootrom.bin ../pc-bios/npcm7xx_bootrom.bin + $(MAKE) -C vbootrom/npcm7xx CROSS_COMPILE=$(arm_cross_prefix) + cp vbootrom/npcm7xx/npcm7xx_bootrom.bin ../pc-bios/npcm7xx_bootrom.bin npcm8xx_bootrom: - $(MAKE) -C vbootrom CROSS_COMPILE=$(aarch64_cross_prefix) - cp vbootrom/npcm8xx_bootrom.bin ../pc-bios/npcm8xx_bootrom.bin + $(MAKE) -C vbootrom/npcm8xx CROSS_COMPILE=$(aarch64_cross_prefix) + cp vbootrom/npcm8xx/npcm8xx_bootrom.bin ../pc-bios/npcm8xx_bootrom.bin hppa-firmware: $(MAKE) -C seabios-hppa parisc diff -Nru qemu-10.0.3+ds/rust/hw/timer/hpet/src/hpet.rs qemu-10.0.6+ds/rust/hw/timer/hpet/src/hpet.rs --- qemu-10.0.3+ds/rust/hw/timer/hpet/src/hpet.rs 2025-07-23 21:05:28.000000000 +0000 +++ qemu-10.0.6+ds/rust/hw/timer/hpet/src/hpet.rs 2025-10-20 18:13:46.000000000 +0000 @@ -765,7 +765,7 @@ self.rtc_irq_level.set(0); } - fn decode(&self, mut addr: hwaddr, size: u32) -> HPETAddrDecode { + fn decode(&self, mut addr: hwaddr, size: u32) -> HPETAddrDecode<'_> { let shift = ((addr & 4) * 8) as u32; let len = std::cmp::min(size * 8, 64 - shift); diff -Nru qemu-10.0.3+ds/scripts/kernel-doc qemu-10.0.6+ds/scripts/kernel-doc --- qemu-10.0.3+ds/scripts/kernel-doc 2025-07-23 21:05:28.000000000 +0000 +++ qemu-10.0.6+ds/scripts/kernel-doc 2025-10-20 18:13:46.000000000 +0000 @@ -1594,13 +1594,12 @@ if ($type eq "" && $param =~ /\.\.\.$/) { - if (!$param =~ /\w\.\.\.$/) { - # handles unnamed variable parameters - $param = "..."; - } - elsif ($param =~ /\w\.\.\.$/) { + if ($param =~ /\w\.\.\.$/) { # for named variable parameters of the form `x...`, remove the dots $param =~ s/\.\.\.$//; + } else { + # handles unnamed variable parameters + $param = "..."; } if (!defined $parameterdescs{$param} || $parameterdescs{$param} eq "") { $parameterdescs{$param} = "variable arguments"; diff -Nru qemu-10.0.3+ds/scripts/make-release qemu-10.0.6+ds/scripts/make-release --- qemu-10.0.3+ds/scripts/make-release 2025-07-23 21:05:28.000000000 +0000 +++ qemu-10.0.6+ds/scripts/make-release 2025-10-20 18:13:46.000000000 +0000 @@ -61,17 +61,15 @@ (cd roms/skiboot && ./make_version.sh > .version) # Fetch edk2 submodule's submodules, since it won't have access to them via # the tarball later. -# -# A more uniform way to handle this sort of situation would be nice, but we -# don't necessarily have much control over how a submodule handles its -# submodule dependencies, so we continue to handle these on a case-by-case -# basis for now. -(cd roms/edk2 && \ - git submodule update --init --depth 1 -- \ - ArmPkg/Library/ArmSoftFloatLib/berkeley-softfloat-3 \ - BaseTools/Source/C/BrotliCompress/brotli \ - CryptoPkg/Library/OpensslLib/openssl \ - MdeModulePkg/Library/BrotliCustomDecompressLib/brotli) + +# As recommended by the EDK2 readme, we don't use --recursive here. +# EDK2 won't use any code or feature from a submodule of a submodule, +# so we don't need to add them to the tarball. +# Although we don't necessarily need all of the submodules that EDK2 +# has, we clone them all, to avoid running into problems where EDK2 +# adds a new submodule or changes its use of an existing one and +# the sources we ship in the tarball then fail to build. +(cd roms/edk2 && git submodule update --init --depth 1) popd exclude=(--exclude=.git) diff -Nru qemu-10.0.3+ds/scsi/pr-manager-helper.c qemu-10.0.6+ds/scsi/pr-manager-helper.c --- qemu-10.0.3+ds/scsi/pr-manager-helper.c 2025-07-23 21:05:28.000000000 +0000 +++ qemu-10.0.6+ds/scsi/pr-manager-helper.c 2025-10-20 18:13:46.000000000 +0000 @@ -105,20 +105,15 @@ .u.q_unix.path = path }; QIOChannelSocket *sioc = qio_channel_socket_new(); - Error *local_err = NULL; - uint32_t flags; int r; assert(!pr_mgr->ioc); qio_channel_set_name(QIO_CHANNEL(sioc), "pr-manager-helper"); - qio_channel_socket_connect_sync(sioc, - &saddr, - &local_err); + r = qio_channel_socket_connect_sync(sioc, &saddr, errp); g_free(path); - if (local_err) { + if (r < 0) { object_unref(OBJECT(sioc)); - error_propagate(errp, local_err); return -ENOTCONN; } diff -Nru qemu-10.0.3+ds/stubs/cpu-destroy-address-spaces.c qemu-10.0.6+ds/stubs/cpu-destroy-address-spaces.c --- qemu-10.0.3+ds/stubs/cpu-destroy-address-spaces.c 1970-01-01 00:00:00.000000000 +0000 +++ qemu-10.0.6+ds/stubs/cpu-destroy-address-spaces.c 2025-10-20 18:13:46.000000000 +0000 @@ -0,0 +1,15 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ + +#include "qemu/osdep.h" +#include "exec/cpu-common.h" + +/* + * user-mode CPUs never create address spaces with + * cpu_address_space_init(), so the cleanup function doesn't + * need to do anything. We need this stub because cpu-common.c + * is built-once so it can't #ifndef CONFIG_USER around the + * call; the real function is in physmem.c which is system-only. + */ +void cpu_destroy_address_spaces(CPUState *cpu) +{ +} diff -Nru qemu-10.0.3+ds/stubs/meson.build qemu-10.0.6+ds/stubs/meson.build --- qemu-10.0.3+ds/stubs/meson.build 2025-07-23 21:05:28.000000000 +0000 +++ qemu-10.0.6+ds/stubs/meson.build 2025-10-20 18:13:46.000000000 +0000 @@ -55,6 +55,7 @@ if have_user # Symbols that are used by hw/core. stub_ss.add(files('cpu-synchronize-state.c')) + stub_ss.add(files('cpu-destroy-address-spaces.c')) # Stubs for QAPI events. Those can always be included in the build, but # they are not built at all for --disable-system builds. diff -Nru qemu-10.0.3+ds/subprojects/libvduse/include/compiler.h qemu-10.0.6+ds/subprojects/libvduse/include/compiler.h --- qemu-10.0.3+ds/subprojects/libvduse/include/compiler.h 2025-07-23 21:05:28.000000000 +0000 +++ qemu-10.0.6+ds/subprojects/libvduse/include/compiler.h 2025-10-20 18:13:46.000000000 +0000 @@ -182,19 +182,6 @@ #define QEMU_DISABLE_CFI #endif -/* - * Apple clang version 14 has a bug in its __builtin_subcll(); define - * BUILTIN_SUBCLL_BROKEN for the offending versions so we can avoid it. - * When a version of Apple clang which has this bug fixed is released - * we can add an upper bound to this check. - * See https://gitlab.com/qemu-project/qemu/-/issues/1631 - * and https://gitlab.com/qemu-project/qemu/-/issues/1659 for details. - * The bug never made it into any upstream LLVM releases, only Apple ones. - */ -#if defined(__apple_build_version__) && __clang_major__ >= 14 -#define BUILTIN_SUBCLL_BROKEN -#endif - #if __has_attribute(annotate) #define QEMU_ANNOTATE(x) __attribute__((annotate(x))) #else diff -Nru qemu-10.0.3+ds/subprojects/libvhost-user/include/compiler.h qemu-10.0.6+ds/subprojects/libvhost-user/include/compiler.h --- qemu-10.0.3+ds/subprojects/libvhost-user/include/compiler.h 2025-07-23 21:05:28.000000000 +0000 +++ qemu-10.0.6+ds/subprojects/libvhost-user/include/compiler.h 2025-10-20 18:13:46.000000000 +0000 @@ -182,19 +182,6 @@ #define QEMU_DISABLE_CFI #endif -/* - * Apple clang version 14 has a bug in its __builtin_subcll(); define - * BUILTIN_SUBCLL_BROKEN for the offending versions so we can avoid it. - * When a version of Apple clang which has this bug fixed is released - * we can add an upper bound to this check. - * See https://gitlab.com/qemu-project/qemu/-/issues/1631 - * and https://gitlab.com/qemu-project/qemu/-/issues/1659 for details. - * The bug never made it into any upstream LLVM releases, only Apple ones. - */ -#if defined(__apple_build_version__) && __clang_major__ >= 14 -#define BUILTIN_SUBCLL_BROKEN -#endif - #if __has_attribute(annotate) #define QEMU_ANNOTATE(x) __attribute__((annotate(x))) #else diff -Nru qemu-10.0.3+ds/system/memory.c qemu-10.0.6+ds/system/memory.c --- qemu-10.0.3+ds/system/memory.c 2025-07-23 21:05:28.000000000 +0000 +++ qemu-10.0.6+ds/system/memory.c 2025-10-20 18:13:46.000000000 +0000 @@ -3254,7 +3254,14 @@ memory_region_unref(as->root); } -void address_space_destroy(AddressSpace *as) +static void do_address_space_destroy_free(AddressSpace *as) +{ + do_address_space_destroy(as); + g_free(as); +} + +/* Detach address space from global view, notify all listeners */ +static void address_space_detach(AddressSpace *as) { MemoryRegion *root = as->root; @@ -3269,9 +3276,20 @@ * values to expire before freeing the data. */ as->root = root; +} + +void address_space_destroy(AddressSpace *as) +{ + address_space_detach(as); call_rcu(as, do_address_space_destroy, rcu); } +void address_space_destroy_free(AddressSpace *as) +{ + address_space_detach(as); + call_rcu(as, do_address_space_destroy_free, rcu); +} + static const char *memory_region_type(MemoryRegion *mr) { if (mr->alias) { diff -Nru qemu-10.0.3+ds/system/physmem.c qemu-10.0.6+ds/system/physmem.c --- qemu-10.0.3+ds/system/physmem.c 2025-07-23 21:05:28.000000000 +0000 +++ qemu-10.0.6+ds/system/physmem.c 2025-10-20 18:13:46.000000000 +0000 @@ -164,13 +164,11 @@ * CPUAddressSpace: all the information a CPU needs about an AddressSpace * @cpu: the CPU whose AddressSpace this is * @as: the AddressSpace itself - * @memory_dispatch: its dispatch pointer (cached, RCU protected) * @tcg_as_listener: listener for tracking changes to the AddressSpace */ typedef struct CPUAddressSpace { CPUState *cpu; AddressSpace *as; - struct AddressSpaceDispatch *memory_dispatch; MemoryListener tcg_as_listener; } CPUAddressSpace; @@ -689,7 +687,7 @@ IOMMUTLBEntry iotlb; int iommu_idx; hwaddr addr = orig_addr; - AddressSpaceDispatch *d = cpu->cpu_ases[asidx].memory_dispatch; + AddressSpaceDispatch *d = address_space_to_dispatch(cpu->cpu_ases[asidx].as); for (;;) { section = address_space_translate_internal(d, addr, &addr, plen, false); @@ -765,12 +763,8 @@ cpu->as = as; } - /* KVM cannot currently support multiple address spaces. */ - assert(asidx == 0 || !kvm_enabled()); - if (!cpu->cpu_ases) { cpu->cpu_ases = g_new0(CPUAddressSpace, cpu->num_ases); - cpu->cpu_ases_count = cpu->num_ases; } newas = &cpu->cpu_ases[asidx]; @@ -784,32 +778,29 @@ } } -void cpu_address_space_destroy(CPUState *cpu, int asidx) +void cpu_destroy_address_spaces(CPUState *cpu) { CPUAddressSpace *cpuas; + int asidx; assert(cpu->cpu_ases); - assert(asidx >= 0 && asidx < cpu->num_ases); - /* KVM cannot currently support multiple address spaces. */ - assert(asidx == 0 || !kvm_enabled()); - - cpuas = &cpu->cpu_ases[asidx]; - if (tcg_enabled()) { - memory_listener_unregister(&cpuas->tcg_as_listener); - } - address_space_destroy(cpuas->as); - g_free_rcu(cpuas->as, rcu); + /* convenience alias just points to some cpu_ases[n] */ + cpu->as = NULL; - if (asidx == 0) { - /* reset the convenience alias for address space 0 */ - cpu->as = NULL; + for (asidx = 0; asidx < cpu->num_ases; asidx++) { + cpuas = &cpu->cpu_ases[asidx]; + if (!cpuas->as) { + /* This index was never initialized; no deinit needed */ + continue; + } + if (tcg_enabled()) { + memory_listener_unregister(&cpuas->tcg_as_listener); + } + g_clear_pointer(&cpuas->as, address_space_destroy_free); } - if (--cpu->cpu_ases_count == 0) { - g_free(cpu->cpu_ases); - cpu->cpu_ases = NULL; - } + g_clear_pointer(&cpu->cpu_ases, g_free); } AddressSpace *cpu_get_address_space(CPUState *cpu, int asidx) @@ -2673,7 +2664,7 @@ { int asidx = cpu_asidx_from_attrs(cpu, attrs); CPUAddressSpace *cpuas = &cpu->cpu_ases[asidx]; - AddressSpaceDispatch *d = cpuas->memory_dispatch; + AddressSpaceDispatch *d = address_space_to_dispatch(cpuas->as); int section_index = index & ~TARGET_PAGE_MASK; MemoryRegionSection *ret; @@ -2750,9 +2741,6 @@ static void tcg_commit_cpu(CPUState *cpu, run_on_cpu_data data) { - CPUAddressSpace *cpuas = data.host_ptr; - - cpuas->memory_dispatch = address_space_to_dispatch(cpuas->as); tlb_flush(cpu); } @@ -2768,11 +2756,7 @@ cpu = cpuas->cpu; /* - * Defer changes to as->memory_dispatch until the cpu is quiescent. - * Otherwise we race between (1) other cpu threads and (2) ongoing - * i/o for the current cpu thread, with data cached by mmu_lookup(). - * - * In addition, queueing the work function will kick the cpu back to + * Queueing the work function will kick the cpu back to * the main loop, which will end the RCU critical section and reclaim * the memory data structures. * diff -Nru qemu-10.0.3+ds/target/arm/gdbstub64.c qemu-10.0.6+ds/target/arm/gdbstub64.c --- qemu-10.0.3+ds/target/arm/gdbstub64.c 2025-07-23 21:05:28.000000000 +0000 +++ qemu-10.0.6+ds/target/arm/gdbstub64.c 2025-10-20 18:13:46.000000000 +0000 @@ -111,8 +111,22 @@ /* 128 bit FP register */ { uint64_t *q = aa64_vfp_qreg(env, reg); - q[0] = ldq_le_p(buf); - q[1] = ldq_le_p(buf + 8); + + /* + * On the wire these are target-endian 128 bit values. + * In the CPU state these are host-order uint64_t values + * with the least-significant one first. This means they're + * the other way around for target_words_bigendian() (which is + * only true for us for aarch64_be-linux-user). + */ + if (target_words_bigendian()) { + q[1] = ldq_p(buf); + q[0] = ldq_p(buf + 8); + } else{ + q[0] = ldq_p(buf); + q[1] = ldq_p(buf + 8); + } + return 16; } case 32: @@ -188,10 +202,17 @@ case 0 ... 31: { int vq, len = 0; - uint64_t *p = (uint64_t *) buf; for (vq = 0; vq < cpu->sve_max_vq; vq++) { - env->vfp.zregs[reg].d[vq * 2 + 1] = *p++; - env->vfp.zregs[reg].d[vq * 2] = *p++; + if (target_words_bigendian()) { + env->vfp.zregs[reg].d[vq * 2 + 1] = ldq_p(buf); + buf += 8; + env->vfp.zregs[reg].d[vq * 2] = ldq_p(buf); + } else{ + env->vfp.zregs[reg].d[vq * 2] = ldq_p(buf); + buf += 8; + env->vfp.zregs[reg].d[vq * 2 + 1] = ldq_p(buf); + } + buf += 8; len += 16; } return len; @@ -206,9 +227,9 @@ { int preg = reg - 34; int vq, len = 0; - uint64_t *p = (uint64_t *) buf; for (vq = 0; vq < cpu->sve_max_vq; vq = vq + 4) { - env->vfp.pregs[preg].p[vq / 4] = *p++; + env->vfp.pregs[preg].p[vq / 4] = ldq_p(buf); + buf += 8; len += 8; } return len; diff -Nru qemu-10.0.3+ds/target/arm/helper.c qemu-10.0.6+ds/target/arm/helper.c --- qemu-10.0.3+ds/target/arm/helper.c 2025-07-23 21:05:28.000000000 +0000 +++ qemu-10.0.6+ds/target/arm/helper.c 2025-10-20 18:13:46.000000000 +0000 @@ -870,22 +870,27 @@ return supported_event_map[number] != UNSUPPORTED_EVENT; } -static CPAccessResult pmreg_access(CPUARMState *env, const ARMCPRegInfo *ri, - bool isread) +static CPAccessResult do_pmreg_access(CPUARMState *env, bool is_pmcr) { /* * Performance monitor registers user accessibility is controlled - * by PMUSERENR. MDCR_EL2.TPM and MDCR_EL3.TPM allow configurable + * by PMUSERENR. MDCR_EL2.TPM/TPMCR and MDCR_EL3.TPM allow configurable * trapping to EL2 or EL3 for other accesses. */ int el = arm_current_el(env); - uint64_t mdcr_el2 = arm_mdcr_el2_eff(env); if (el == 0 && !(env->cp15.c9_pmuserenr & 1)) { return CP_ACCESS_TRAP_EL1; } - if (el < 2 && (mdcr_el2 & MDCR_TPM)) { - return CP_ACCESS_TRAP_EL2; + if (el < 2) { + uint64_t mdcr_el2 = arm_mdcr_el2_eff(env); + + if (mdcr_el2 & MDCR_TPM) { + return CP_ACCESS_TRAP_EL2; + } + if (is_pmcr && (mdcr_el2 & MDCR_TPMCR)) { + return CP_ACCESS_TRAP_EL2; + } } if (el < 3 && (env->cp15.mdcr_el3 & MDCR_TPM)) { return CP_ACCESS_TRAP_EL3; @@ -894,6 +899,19 @@ return CP_ACCESS_OK; } +static CPAccessResult pmreg_access(CPUARMState *env, const ARMCPRegInfo *ri, + bool isread) +{ + return do_pmreg_access(env, false); +} + +static CPAccessResult pmreg_access_pmcr(CPUARMState *env, + const ARMCPRegInfo *ri, + bool isread) +{ + return do_pmreg_access(env, true); +} + static CPAccessResult pmreg_access_xevcntr(CPUARMState *env, const ARMCPRegInfo *ri, bool isread) @@ -1946,11 +1964,6 @@ .fgt = FGT_PMSELR_EL0, .fieldoffset = offsetof(CPUARMState, cp15.c9_pmselr), .writefn = pmselr_write, .raw_writefn = raw_write, }, - { .name = "PMCCNTR", .cp = 15, .crn = 9, .crm = 13, .opc1 = 0, .opc2 = 0, - .access = PL0_RW, .resetvalue = 0, .type = ARM_CP_ALIAS | ARM_CP_IO, - .fgt = FGT_PMCCNTR_EL0, - .readfn = pmccntr_read, .writefn = pmccntr_write32, - .accessfn = pmreg_access_ccntr }, { .name = "PMCCNTR_EL0", .state = ARM_CP_STATE_AA64, .opc0 = 3, .opc1 = 3, .crn = 9, .crm = 13, .opc2 = 0, .access = PL0_RW, .accessfn = pmreg_access_ccntr, @@ -5327,7 +5340,8 @@ value &= valid_mask; /* RW is RAO/WI if EL1 is AArch64 only */ - if (!cpu_isar_feature(aa64_aa32_el1, cpu)) { + if (arm_feature(env, ARM_FEATURE_AARCH64) && + !cpu_isar_feature(aa64_aa32_el1, cpu)) { value |= HCR_RW; } @@ -6834,14 +6848,14 @@ .fgt = FGT_PMCR_EL0, .type = ARM_CP_IO | ARM_CP_ALIAS, .fieldoffset = offsetoflow32(CPUARMState, cp15.c9_pmcr), - .accessfn = pmreg_access, + .accessfn = pmreg_access_pmcr, .readfn = pmcr_read, .raw_readfn = raw_read, .writefn = pmcr_write, .raw_writefn = raw_write, }; ARMCPRegInfo pmcr64 = { .name = "PMCR_EL0", .state = ARM_CP_STATE_AA64, .opc0 = 3, .opc1 = 3, .crn = 9, .crm = 12, .opc2 = 0, - .access = PL0_RW, .accessfn = pmreg_access, + .access = PL0_RW, .accessfn = pmreg_access_pmcr, .fgt = FGT_PMCR_EL0, .type = ARM_CP_IO, .fieldoffset = offsetof(CPUARMState, cp15.c9_pmcr), @@ -6849,9 +6863,26 @@ .readfn = pmcr_read, .raw_readfn = raw_read, .writefn = pmcr_write, .raw_writefn = raw_write, }; + /* + * 32-bit AArch32 PMCCNTR. We don't expose this to GDB if the + * new-in-v8 PMUv3 64-bit AArch32 PMCCNTR register is implemented + * (as that will provide the GDB user's view of "PMCCNTR"). + */ + ARMCPRegInfo pmccntr = { + .name = "PMCCNTR", + .cp = 15, .crn = 9, .crm = 13, .opc1 = 0, .opc2 = 0, + .access = PL0_RW, .accessfn = pmreg_access_ccntr, + .resetvalue = 0, .type = ARM_CP_ALIAS | ARM_CP_IO, + .fgt = FGT_PMCCNTR_EL0, + .readfn = pmccntr_read, .writefn = pmccntr_write32, + }; + if (arm_feature(&cpu->env, ARM_FEATURE_V8)) { + pmccntr.type |= ARM_CP_NO_GDB; + } define_one_arm_cp_reg(cpu, &pmcr); define_one_arm_cp_reg(cpu, &pmcr64); + define_one_arm_cp_reg(cpu, &pmccntr); for (i = 0; i < pmcrn; i++) { char *pmevcntr_name = g_strdup_printf("PMEVCNTR%d", i); char *pmevcntr_el0_name = g_strdup_printf("PMEVCNTR%d_EL0", i); @@ -8162,6 +8193,13 @@ .access = PL0_R, .accessfn = pmreg_access, .type = ARM_CP_CONST, .fgt = FGT_PMCEIDN_EL0, .resetvalue = cpu->pmceid1 }, + /* AArch32 64-bit PMCCNTR view: added in PMUv3 with Armv8 */ + { .name = "PMCCNTR", .state = ARM_CP_STATE_AA32, + .cp = 15, .crm = 9, .opc1 = 0, + .access = PL0_RW, .accessfn = pmreg_access_ccntr, .resetvalue = 0, + .type = ARM_CP_ALIAS | ARM_CP_IO | ARM_CP_64BIT, + .fgt = FGT_PMCCNTR_EL0, .readfn = pmccntr_read, + .writefn = pmccntr_write, }, }; #ifdef CONFIG_USER_ONLY static const ARMCPRegUserSpaceInfo v8_user_idregs[] = { diff -Nru qemu-10.0.3+ds/target/hppa/insns.decode qemu-10.0.6+ds/target/hppa/insns.decode --- qemu-10.0.3+ds/target/hppa/insns.decode 2025-07-23 21:05:28.000000000 +0000 +++ qemu-10.0.6+ds/target/hppa/insns.decode 2025-10-20 18:13:46.000000000 +0000 @@ -365,10 +365,10 @@ &mpyadd rm1 rm2 ta ra tm @mpyadd ...... rm1:5 rm2:5 ta:5 ra:5 . tm:5 &mpyadd -fmpyadd_f 000110 ..... ..... ..... ..... 0 ..... @mpyadd -fmpyadd_d 000110 ..... ..... ..... ..... 1 ..... @mpyadd -fmpysub_f 100110 ..... ..... ..... ..... 0 ..... @mpyadd -fmpysub_d 100110 ..... ..... ..... ..... 1 ..... @mpyadd +fmpyadd_f 000110 ..... ..... ..... ..... 1 ..... @mpyadd +fmpyadd_d 000110 ..... ..... ..... ..... 0 ..... @mpyadd +fmpysub_f 100110 ..... ..... ..... ..... 1 ..... @mpyadd +fmpysub_d 100110 ..... ..... ..... ..... 0 ..... @mpyadd #### # Conditional Branches diff -Nru qemu-10.0.3+ds/target/i386/cpu.c qemu-10.0.6+ds/target/i386/cpu.c --- qemu-10.0.3+ds/target/i386/cpu.c 2025-07-23 21:05:28.000000000 +0000 +++ qemu-10.0.6+ds/target/i386/cpu.c 2025-10-20 18:13:46.000000000 +0000 @@ -6835,8 +6835,21 @@ } *edx = env->features[FEAT_1_EDX]; if (threads_per_pkg > 1) { + uint32_t num; + + /* + * For CPUID.01H.EBX[Bits 23-16], AMD requires logical processor + * count, but Intel needs maximum number of addressable IDs for + * logical processors per package. + */ + if ((IS_INTEL_CPU(env) || IS_ZHAOXIN_CPU(env))) { + num = 1 << apicid_pkg_offset(topo_info); + } else { + num = threads_per_pkg; + } + /* Fixup overflow: max value for bits 23-16 is 255. */ - *ebx |= MIN(threads_per_pkg, 255) << 16; + *ebx |= MIN(num, 255) << 16; } if (!cpu->enable_pmu) { *ecx &= ~CPUID_EXT_PDCM; @@ -7500,7 +7513,11 @@ env->idt.limit = 0xffff; env->gdt.limit = 0xffff; +#if defined(CONFIG_USER_ONLY) + env->ldt.limit = 0; +#else env->ldt.limit = 0xffff; +#endif env->ldt.flags = DESC_P_MASK | (2 << DESC_TYPE_SHIFT); env->tr.limit = 0xffff; env->tr.flags = DESC_P_MASK | (11 << DESC_TYPE_SHIFT); diff -Nru qemu-10.0.3+ds/target/i386/cpu.h qemu-10.0.6+ds/target/i386/cpu.h --- qemu-10.0.3+ds/target/i386/cpu.h 2025-07-23 21:05:28.000000000 +0000 +++ qemu-10.0.6+ds/target/i386/cpu.h 2025-10-20 18:13:46.000000000 +0000 @@ -2517,6 +2517,11 @@ void x86_cpu_set_a20(X86CPU *cpu, int a20_state); void cpu_sync_avx_hflag(CPUX86State *env); +typedef enum X86ASIdx { + X86ASIdx_MEM = 0, + X86ASIdx_SMM = 1, +} X86ASIdx; + #ifndef CONFIG_USER_ONLY static inline int x86_asidx_from_attrs(CPUState *cs, MemTxAttrs attrs) { diff -Nru qemu-10.0.3+ds/target/i386/helper.c qemu-10.0.6+ds/target/i386/helper.c --- qemu-10.0.3+ds/target/i386/helper.c 2025-07-23 21:05:28.000000000 +0000 +++ qemu-10.0.6+ds/target/i386/helper.c 2025-10-20 18:13:46.000000000 +0000 @@ -617,6 +617,10 @@ void do_cpu_sipi(X86CPU *cpu) { + CPUX86State *env = &cpu->env; + if (env->hflags & HF_SMM_MASK) { + return; + } apic_sipi(cpu->apic_state); } diff -Nru qemu-10.0.3+ds/target/i386/kvm/kvm-cpu.c qemu-10.0.6+ds/target/i386/kvm/kvm-cpu.c --- qemu-10.0.3+ds/target/i386/kvm/kvm-cpu.c 2025-07-23 21:05:28.000000000 +0000 +++ qemu-10.0.6+ds/target/i386/kvm/kvm-cpu.c 2025-10-20 18:13:46.000000000 +0000 @@ -13,6 +13,7 @@ #include "qapi/error.h" #include "system/system.h" #include "hw/boards.h" +#include "hw/i386/x86.h" #include "kvm_i386.h" #include "accel/accel-cpu-target.h" @@ -90,6 +91,15 @@ kvm_set_guest_phys_bits(cs); } + /* + * When SMM is enabled, there is 2 address spaces. Otherwise only 1. + * + * Only initialize address space 0 here, the second one for SMM is + * initialized at register_smram_listener() after machine init done. + */ + cs->num_ases = x86_machine_is_smm_enabled(X86_MACHINE(current_machine)) ? 2 : 1; + cpu_address_space_init(cs, X86ASIdx_MEM, "cpu-memory", cs->memory); + return true; } diff -Nru qemu-10.0.3+ds/target/i386/kvm/kvm.c qemu-10.0.6+ds/target/i386/kvm/kvm.c --- qemu-10.0.3+ds/target/i386/kvm/kvm.c 2025-07-23 21:05:28.000000000 +0000 +++ qemu-10.0.6+ds/target/i386/kvm/kvm.c 2025-10-20 18:13:46.000000000 +0000 @@ -500,12 +500,8 @@ * Linux v4.17-v4.20 incorrectly return ARCH_CAPABILITIES on SVM hosts. * We can detect the bug by checking if MSR_IA32_ARCH_CAPABILITIES is * returned by KVM_GET_MSR_INDEX_LIST. - * - * But also, because Windows does not like ARCH_CAPABILITIES on AMD - * mcahines at all, do not show the fake ARCH_CAPABILITIES MSR that - * KVM sets up. */ - if (!has_msr_arch_capabs || !(edx & CPUID_7_0_EDX_ARCH_CAPABILITIES)) { + if (!has_msr_arch_capabs) { ret &= ~CPUID_7_0_EDX_ARCH_CAPABILITIES; } } else if (function == 7 && index == 1 && reg == R_EAX) { @@ -654,6 +650,23 @@ must_be_one = (uint32_t)value; can_be_one = (uint32_t)(value >> 32); return can_be_one & ~must_be_one; + case MSR_IA32_ARCH_CAPABILITIES: + /* + * Special handling for fb-clear bit in ARCH_CAPABILITIES MSR. + * KVM will only report the bit if it is enabled in the host, + * but, for live migration capability purposes, we want to + * expose the bit to the guest even if it is disabled in the + * host, as long as the host itself is not vulnerable to + * the issue that the fb-clear bit is meant to mitigate. + */ + if ((value & MSR_ARCH_CAP_MDS_NO) && + (value & MSR_ARCH_CAP_TAA_NO) && + (value & MSR_ARCH_CAP_SBDR_SSDP_NO) && + (value & MSR_ARCH_CAP_FBSDP_NO) && + (value & MSR_ARCH_CAP_PSDP_NO)) { + value |= MSR_ARCH_CAP_FB_CLEAR; + } + return value; default: return value; @@ -2678,6 +2691,7 @@ static void register_smram_listener(Notifier *n, void *unused) { + CPUState *cpu; MemoryRegion *smram = (MemoryRegion *) object_resolve_path("/machine/smram", NULL); @@ -2701,7 +2715,11 @@ address_space_init(&smram_address_space, &smram_as_root, "KVM-SMRAM"); kvm_memory_listener_register(kvm_state, &smram_listener, - &smram_address_space, 1, "kvm-smram"); + &smram_address_space, X86ASIdx_SMM, "kvm-smram"); + + CPU_FOREACH(cpu) { + cpu_address_space_init(cpu, X86ASIdx_SMM, "cpu-smm", &smram_as_root); + } } static void *kvm_msr_energy_thread(void *data) diff -Nru qemu-10.0.3+ds/target/i386/kvm/vmsr_energy.c qemu-10.0.6+ds/target/i386/kvm/vmsr_energy.c --- qemu-10.0.3+ds/target/i386/kvm/vmsr_energy.c 2025-07-23 21:05:28.000000000 +0000 +++ qemu-10.0.6+ds/target/i386/kvm/vmsr_energy.c 2025-10-20 18:13:46.000000000 +0000 @@ -67,13 +67,9 @@ }; QIOChannelSocket *sioc = qio_channel_socket_new(); - Error *local_err = NULL; qio_channel_set_name(QIO_CHANNEL(sioc), "vmsr-helper"); - qio_channel_socket_connect_sync(sioc, - &saddr, - &local_err); - if (local_err) { + if (qio_channel_socket_connect_sync(sioc, &saddr, NULL) < 0) { /* Close socket. */ qio_channel_close(QIO_CHANNEL(sioc), NULL); object_unref(OBJECT(sioc)); diff -Nru qemu-10.0.3+ds/target/i386/tcg/decode-new.c.inc qemu-10.0.6+ds/target/i386/tcg/decode-new.c.inc --- qemu-10.0.3+ds/target/i386/tcg/decode-new.c.inc 2025-07-23 21:05:28.000000000 +0000 +++ qemu-10.0.6+ds/target/i386/tcg/decode-new.c.inc 2025-10-20 18:13:46.000000000 +0000 @@ -878,10 +878,10 @@ [0x0e] = X86_OP_ENTRY4(VPBLENDW, V,x, H,x, W,x, vex4 cpuid(SSE41) avx2_256 p_66), [0x0f] = X86_OP_ENTRY4(PALIGNR, V,x, H,x, W,x, vex4 cpuid(SSSE3) mmx avx2_256 p_00_66), - [0x18] = X86_OP_ENTRY4(VINSERTx128, V,qq, H,qq, W,qq, vex6 chk(W0) cpuid(AVX) p_66), + [0x18] = X86_OP_ENTRY4(VINSERTx128, V,qq, H,qq, W,dq, vex6 chk(W0) cpuid(AVX) p_66), [0x19] = X86_OP_ENTRY3(VEXTRACTx128, W,dq, V,qq, I,b, vex6 chk(W0) cpuid(AVX) p_66), - [0x38] = X86_OP_ENTRY4(VINSERTx128, V,qq, H,qq, W,qq, vex6 chk(W0) cpuid(AVX2) p_66), + [0x38] = X86_OP_ENTRY4(VINSERTx128, V,qq, H,qq, W,dq, vex6 chk(W0) cpuid(AVX2) p_66), [0x39] = X86_OP_ENTRY3(VEXTRACTx128, W,dq, V,qq, I,b, vex6 chk(W0) cpuid(AVX2) p_66), /* Listed incorrectly as type 4 */ @@ -1541,7 +1541,7 @@ [0x0b] = X86_OP_ENTRYr(CALLF_m, M,p), [0x0c] = X86_OP_ENTRYr(JMP_m, E,f64, zextT0), [0x0d] = X86_OP_ENTRYr(JMPF_m, M,p), - [0x0e] = X86_OP_ENTRYr(PUSH, E,f64), + [0x0e] = X86_OP_ENTRYr(PUSH, E,d64), }; int w = (*b & 1); diff -Nru qemu-10.0.3+ds/target/i386/tcg/system/excp_helper.c qemu-10.0.6+ds/target/i386/tcg/system/excp_helper.c --- qemu-10.0.3+ds/target/i386/tcg/system/excp_helper.c 2025-07-23 21:05:28.000000000 +0000 +++ qemu-10.0.6+ds/target/i386/tcg/system/excp_helper.c 2025-10-20 18:13:46.000000000 +0000 @@ -589,7 +589,8 @@ if (sext != 0 && sext != -1) { *err = (TranslateFault){ .exception_index = EXCP0D_GPF, - .cr2 = addr, + /* non-canonical #GP doesn't change CR2 */ + .cr2 = env->cr[2], }; return false; } diff -Nru qemu-10.0.3+ds/target/i386/tcg/system/seg_helper.c qemu-10.0.6+ds/target/i386/tcg/system/seg_helper.c --- qemu-10.0.3+ds/target/i386/tcg/system/seg_helper.c 2025-07-23 21:05:28.000000000 +0000 +++ qemu-10.0.6+ds/target/i386/tcg/system/seg_helper.c 2025-10-20 18:13:46.000000000 +0000 @@ -182,6 +182,7 @@ apic_poll_irq(cpu->apic_state); break; case CPU_INTERRUPT_SIPI: + cpu_reset_interrupt(cs, CPU_INTERRUPT_SIPI); do_cpu_sipi(cpu); break; case CPU_INTERRUPT_SMI: diff -Nru qemu-10.0.3+ds/target/i386/tcg/system/smm_helper.c qemu-10.0.6+ds/target/i386/tcg/system/smm_helper.c --- qemu-10.0.3+ds/target/i386/tcg/system/smm_helper.c 2025-07-23 21:05:28.000000000 +0000 +++ qemu-10.0.6+ds/target/i386/tcg/system/smm_helper.c 2025-10-20 18:13:46.000000000 +0000 @@ -168,7 +168,7 @@ env->cr[0] & ~(CR0_PE_MASK | CR0_EM_MASK | CR0_TS_MASK | CR0_PG_MASK)); cpu_x86_update_cr4(env, 0); - env->dr[7] = 0x00000400; + helper_set_dr(env, 7, 0x00000400); cpu_x86_load_seg_cache(env, R_CS, (env->smbase >> 4) & 0xffff, env->smbase, 0xffffffff, @@ -233,8 +233,8 @@ env->eip = x86_ldq_phys(cs, sm_state + 0x7f78); cpu_load_eflags(env, x86_ldl_phys(cs, sm_state + 0x7f70), ~(CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C | DF_MASK)); - env->dr[6] = x86_ldl_phys(cs, sm_state + 0x7f68); - env->dr[7] = x86_ldl_phys(cs, sm_state + 0x7f60); + helper_set_dr(env, 6, x86_ldl_phys(cs, sm_state + 0x7f68)); + helper_set_dr(env, 7, x86_ldl_phys(cs, sm_state + 0x7f60)); cpu_x86_update_cr4(env, x86_ldl_phys(cs, sm_state + 0x7f48)); cpu_x86_update_cr3(env, x86_ldq_phys(cs, sm_state + 0x7f50)); @@ -268,8 +268,8 @@ env->regs[R_EDX] = x86_ldl_phys(cs, sm_state + 0x7fd8); env->regs[R_ECX] = x86_ldl_phys(cs, sm_state + 0x7fd4); env->regs[R_EAX] = x86_ldl_phys(cs, sm_state + 0x7fd0); - env->dr[6] = x86_ldl_phys(cs, sm_state + 0x7fcc); - env->dr[7] = x86_ldl_phys(cs, sm_state + 0x7fc8); + helper_set_dr(env, 6, x86_ldl_phys(cs, sm_state + 0x7fcc)); + helper_set_dr(env, 7, x86_ldl_phys(cs, sm_state + 0x7fc8)); env->tr.selector = x86_ldl_phys(cs, sm_state + 0x7fc4) & 0xffff; env->tr.base = x86_ldl_phys(cs, sm_state + 0x7f64); diff -Nru qemu-10.0.3+ds/target/i386/tcg/system/svm_helper.c qemu-10.0.6+ds/target/i386/tcg/system/svm_helper.c --- qemu-10.0.3+ds/target/i386/tcg/system/svm_helper.c 2025-07-23 21:05:28.000000000 +0000 +++ qemu-10.0.6+ds/target/i386/tcg/system/svm_helper.c 2025-10-20 18:13:46.000000000 +0000 @@ -49,7 +49,7 @@ static inline void svm_canonicalization(CPUX86State *env, target_ulong *seg_base) { uint16_t shift_amt = 64 - cpu_x86_virtual_addr_width(env); - *seg_base = ((((long) *seg_base) << shift_amt) >> shift_amt); + *seg_base = (((int64_t) *seg_base) << shift_amt) >> shift_amt; } static void svm_load_seg(CPUX86State *env, int mmu_idx, hwaddr addr, diff -Nru qemu-10.0.3+ds/target/i386/tcg/system/tcg-cpu.c qemu-10.0.6+ds/target/i386/tcg/system/tcg-cpu.c --- qemu-10.0.3+ds/target/i386/tcg/system/tcg-cpu.c 2025-07-23 21:05:28.000000000 +0000 +++ qemu-10.0.6+ds/target/i386/tcg/system/tcg-cpu.c 2025-10-20 18:13:46.000000000 +0000 @@ -73,8 +73,8 @@ memory_region_set_enabled(cpu->cpu_as_mem, true); cs->num_ases = 2; - cpu_address_space_init(cs, 0, "cpu-memory", cs->memory); - cpu_address_space_init(cs, 1, "cpu-smm", cpu->cpu_as_root); + cpu_address_space_init(cs, X86ASIdx_MEM, "cpu-memory", cs->memory); + cpu_address_space_init(cs, X86ASIdx_SMM, "cpu-smm", cpu->cpu_as_root); /* ... SMRAM with higher priority, linked from /machine/smram. */ cpu->machine_done.notify = tcg_cpu_machine_done; diff -Nru qemu-10.0.3+ds/target/loongarch/cpu.c qemu-10.0.6+ds/target/loongarch/cpu.c --- qemu-10.0.3+ds/target/loongarch/cpu.c 2025-07-23 21:05:28.000000000 +0000 +++ qemu-10.0.6+ds/target/loongarch/cpu.c 2025-10-20 18:13:46.000000000 +0000 @@ -431,7 +431,7 @@ data = FIELD_DP32(data, CPUCFG1, EP, 1); data = FIELD_DP32(data, CPUCFG1, RPLV, 1); data = FIELD_DP32(data, CPUCFG1, HP, 1); - data = FIELD_DP32(data, CPUCFG1, IOCSR_BRD, 1); + data = FIELD_DP32(data, CPUCFG1, CRC, 1); env->cpucfg[1] = data; data = 0; @@ -530,7 +530,7 @@ data = FIELD_DP32(data, CPUCFG1, EP, 0); data = FIELD_DP32(data, CPUCFG1, RPLV, 0); data = FIELD_DP32(data, CPUCFG1, HP, 1); - data = FIELD_DP32(data, CPUCFG1, IOCSR_BRD, 1); + data = FIELD_DP32(data, CPUCFG1, CRC, 1); env->cpucfg[1] = data; } diff -Nru qemu-10.0.3+ds/target/loongarch/cpu.h qemu-10.0.6+ds/target/loongarch/cpu.h --- qemu-10.0.3+ds/target/loongarch/cpu.h 2025-07-23 21:05:28.000000000 +0000 +++ qemu-10.0.6+ds/target/loongarch/cpu.h 2025-10-20 18:13:46.000000000 +0000 @@ -129,7 +129,7 @@ FIELD(CPUCFG1, EP, 22, 1) FIELD(CPUCFG1, RPLV, 23, 1) FIELD(CPUCFG1, HP, 24, 1) -FIELD(CPUCFG1, IOCSR_BRD, 25, 1) +FIELD(CPUCFG1, CRC, 25, 1) FIELD(CPUCFG1, MSG_INT, 26, 1) /* cpucfg[1].arch */ diff -Nru qemu-10.0.3+ds/target/loongarch/cpu_helper.c qemu-10.0.6+ds/target/loongarch/cpu_helper.c --- qemu-10.0.3+ds/target/loongarch/cpu_helper.c 2025-07-23 21:05:28.000000000 +0000 +++ qemu-10.0.6+ds/target/loongarch/cpu_helper.c 2025-10-20 18:13:46.000000000 +0000 @@ -299,8 +299,8 @@ } /* Check valid extension */ - addr_high = sextract64(address, TARGET_VIRT_ADDR_SPACE_BITS, 16); - if (!(addr_high == 0 || addr_high == -1)) { + addr_high = (int64_t)address >> (TARGET_VIRT_ADDR_SPACE_BITS - 1); + if (!(addr_high == 0 || addr_high == -1ULL)) { return TLBRET_BADADDR; } diff -Nru qemu-10.0.3+ds/target/loongarch/tcg/insn_trans/trans_atomic.c.inc qemu-10.0.6+ds/target/loongarch/tcg/insn_trans/trans_atomic.c.inc --- qemu-10.0.3+ds/target/loongarch/tcg/insn_trans/trans_atomic.c.inc 2025-07-23 21:05:28.000000000 +0000 +++ qemu-10.0.6+ds/target/loongarch/tcg/insn_trans/trans_atomic.c.inc 2025-10-20 18:13:46.000000000 +0000 @@ -74,38 +74,38 @@ TRANS(ll_d, 64, gen_ll, MO_TEUQ) TRANS(sc_d, 64, gen_sc, MO_TEUQ) TRANS(amswap_w, LAM, gen_am, tcg_gen_atomic_xchg_tl, MO_TESL) -TRANS(amswap_d, LAM, gen_am, tcg_gen_atomic_xchg_tl, MO_TEUQ) +TRANS64(amswap_d, LAM, gen_am, tcg_gen_atomic_xchg_tl, MO_TEUQ) TRANS(amadd_w, LAM, gen_am, tcg_gen_atomic_fetch_add_tl, MO_TESL) -TRANS(amadd_d, LAM, gen_am, tcg_gen_atomic_fetch_add_tl, MO_TEUQ) +TRANS64(amadd_d, LAM, gen_am, tcg_gen_atomic_fetch_add_tl, MO_TEUQ) TRANS(amand_w, LAM, gen_am, tcg_gen_atomic_fetch_and_tl, MO_TESL) -TRANS(amand_d, LAM, gen_am, tcg_gen_atomic_fetch_and_tl, MO_TEUQ) +TRANS64(amand_d, LAM, gen_am, tcg_gen_atomic_fetch_and_tl, MO_TEUQ) TRANS(amor_w, LAM, gen_am, tcg_gen_atomic_fetch_or_tl, MO_TESL) -TRANS(amor_d, LAM, gen_am, tcg_gen_atomic_fetch_or_tl, MO_TEUQ) +TRANS64(amor_d, LAM, gen_am, tcg_gen_atomic_fetch_or_tl, MO_TEUQ) TRANS(amxor_w, LAM, gen_am, tcg_gen_atomic_fetch_xor_tl, MO_TESL) -TRANS(amxor_d, LAM, gen_am, tcg_gen_atomic_fetch_xor_tl, MO_TEUQ) +TRANS64(amxor_d, LAM, gen_am, tcg_gen_atomic_fetch_xor_tl, MO_TEUQ) TRANS(ammax_w, LAM, gen_am, tcg_gen_atomic_fetch_smax_tl, MO_TESL) -TRANS(ammax_d, LAM, gen_am, tcg_gen_atomic_fetch_smax_tl, MO_TEUQ) +TRANS64(ammax_d, LAM, gen_am, tcg_gen_atomic_fetch_smax_tl, MO_TEUQ) TRANS(ammin_w, LAM, gen_am, tcg_gen_atomic_fetch_smin_tl, MO_TESL) -TRANS(ammin_d, LAM, gen_am, tcg_gen_atomic_fetch_smin_tl, MO_TEUQ) +TRANS64(ammin_d, LAM, gen_am, tcg_gen_atomic_fetch_smin_tl, MO_TEUQ) TRANS(ammax_wu, LAM, gen_am, tcg_gen_atomic_fetch_umax_tl, MO_TESL) -TRANS(ammax_du, LAM, gen_am, tcg_gen_atomic_fetch_umax_tl, MO_TEUQ) +TRANS64(ammax_du, LAM, gen_am, tcg_gen_atomic_fetch_umax_tl, MO_TEUQ) TRANS(ammin_wu, LAM, gen_am, tcg_gen_atomic_fetch_umin_tl, MO_TESL) -TRANS(ammin_du, LAM, gen_am, tcg_gen_atomic_fetch_umin_tl, MO_TEUQ) +TRANS64(ammin_du, LAM, gen_am, tcg_gen_atomic_fetch_umin_tl, MO_TEUQ) TRANS(amswap_db_w, LAM, gen_am, tcg_gen_atomic_xchg_tl, MO_TESL) -TRANS(amswap_db_d, LAM, gen_am, tcg_gen_atomic_xchg_tl, MO_TEUQ) +TRANS64(amswap_db_d, LAM, gen_am, tcg_gen_atomic_xchg_tl, MO_TEUQ) TRANS(amadd_db_w, LAM, gen_am, tcg_gen_atomic_fetch_add_tl, MO_TESL) -TRANS(amadd_db_d, LAM, gen_am, tcg_gen_atomic_fetch_add_tl, MO_TEUQ) +TRANS64(amadd_db_d, LAM, gen_am, tcg_gen_atomic_fetch_add_tl, MO_TEUQ) TRANS(amand_db_w, LAM, gen_am, tcg_gen_atomic_fetch_and_tl, MO_TESL) -TRANS(amand_db_d, LAM, gen_am, tcg_gen_atomic_fetch_and_tl, MO_TEUQ) +TRANS64(amand_db_d, LAM, gen_am, tcg_gen_atomic_fetch_and_tl, MO_TEUQ) TRANS(amor_db_w, LAM, gen_am, tcg_gen_atomic_fetch_or_tl, MO_TESL) -TRANS(amor_db_d, LAM, gen_am, tcg_gen_atomic_fetch_or_tl, MO_TEUQ) +TRANS64(amor_db_d, LAM, gen_am, tcg_gen_atomic_fetch_or_tl, MO_TEUQ) TRANS(amxor_db_w, LAM, gen_am, tcg_gen_atomic_fetch_xor_tl, MO_TESL) -TRANS(amxor_db_d, LAM, gen_am, tcg_gen_atomic_fetch_xor_tl, MO_TEUQ) +TRANS64(amxor_db_d, LAM, gen_am, tcg_gen_atomic_fetch_xor_tl, MO_TEUQ) TRANS(ammax_db_w, LAM, gen_am, tcg_gen_atomic_fetch_smax_tl, MO_TESL) -TRANS(ammax_db_d, LAM, gen_am, tcg_gen_atomic_fetch_smax_tl, MO_TEUQ) +TRANS64(ammax_db_d, LAM, gen_am, tcg_gen_atomic_fetch_smax_tl, MO_TEUQ) TRANS(ammin_db_w, LAM, gen_am, tcg_gen_atomic_fetch_smin_tl, MO_TESL) -TRANS(ammin_db_d, LAM, gen_am, tcg_gen_atomic_fetch_smin_tl, MO_TEUQ) +TRANS64(ammin_db_d, LAM, gen_am, tcg_gen_atomic_fetch_smin_tl, MO_TEUQ) TRANS(ammax_db_wu, LAM, gen_am, tcg_gen_atomic_fetch_umax_tl, MO_TESL) -TRANS(ammax_db_du, LAM, gen_am, tcg_gen_atomic_fetch_umax_tl, MO_TEUQ) +TRANS64(ammax_db_du, LAM, gen_am, tcg_gen_atomic_fetch_umax_tl, MO_TEUQ) TRANS(ammin_db_wu, LAM, gen_am, tcg_gen_atomic_fetch_umin_tl, MO_TESL) -TRANS(ammin_db_du, LAM, gen_am, tcg_gen_atomic_fetch_umin_tl, MO_TEUQ) +TRANS64(ammin_db_du, LAM, gen_am, tcg_gen_atomic_fetch_umin_tl, MO_TEUQ) diff -Nru qemu-10.0.3+ds/target/loongarch/tcg/insn_trans/trans_extra.c.inc qemu-10.0.6+ds/target/loongarch/tcg/insn_trans/trans_extra.c.inc --- qemu-10.0.3+ds/target/loongarch/tcg/insn_trans/trans_extra.c.inc 2025-07-23 21:05:28.000000000 +0000 +++ qemu-10.0.6+ds/target/loongarch/tcg/insn_trans/trans_extra.c.inc 2025-10-20 18:13:46.000000000 +0000 @@ -69,6 +69,10 @@ static bool trans_rdtime_d(DisasContext *ctx, arg_rdtime_d *a) { + if (!avail_64(ctx)) { + return false; + } + return gen_rdtime(ctx, a, 0, 0); } @@ -97,11 +101,11 @@ return true; } -TRANS(crc_w_b_w, 64, gen_crc, gen_helper_crc32, tcg_constant_tl(1)) -TRANS(crc_w_h_w, 64, gen_crc, gen_helper_crc32, tcg_constant_tl(2)) -TRANS(crc_w_w_w, 64, gen_crc, gen_helper_crc32, tcg_constant_tl(4)) -TRANS(crc_w_d_w, 64, gen_crc, gen_helper_crc32, tcg_constant_tl(8)) -TRANS(crcc_w_b_w, 64, gen_crc, gen_helper_crc32c, tcg_constant_tl(1)) -TRANS(crcc_w_h_w, 64, gen_crc, gen_helper_crc32c, tcg_constant_tl(2)) -TRANS(crcc_w_w_w, 64, gen_crc, gen_helper_crc32c, tcg_constant_tl(4)) -TRANS(crcc_w_d_w, 64, gen_crc, gen_helper_crc32c, tcg_constant_tl(8)) +TRANS(crc_w_b_w, CRC, gen_crc, gen_helper_crc32, tcg_constant_tl(1)) +TRANS(crc_w_h_w, CRC, gen_crc, gen_helper_crc32, tcg_constant_tl(2)) +TRANS(crc_w_w_w, CRC, gen_crc, gen_helper_crc32, tcg_constant_tl(4)) +TRANS64(crc_w_d_w, CRC, gen_crc, gen_helper_crc32, tcg_constant_tl(8)) +TRANS(crcc_w_b_w, CRC, gen_crc, gen_helper_crc32c, tcg_constant_tl(1)) +TRANS(crcc_w_h_w, CRC, gen_crc, gen_helper_crc32c, tcg_constant_tl(2)) +TRANS(crcc_w_w_w, CRC, gen_crc, gen_helper_crc32c, tcg_constant_tl(4)) +TRANS64(crcc_w_d_w, CRC, gen_crc, gen_helper_crc32c, tcg_constant_tl(8)) diff -Nru qemu-10.0.3+ds/target/loongarch/tcg/insn_trans/trans_farith.c.inc qemu-10.0.6+ds/target/loongarch/tcg/insn_trans/trans_farith.c.inc --- qemu-10.0.3+ds/target/loongarch/tcg/insn_trans/trans_farith.c.inc 2025-07-23 21:05:28.000000000 +0000 +++ qemu-10.0.6+ds/target/loongarch/tcg/insn_trans/trans_farith.c.inc 2025-10-20 18:13:46.000000000 +0000 @@ -183,16 +183,16 @@ TRANS(fmaxa_d, FP_DP, gen_fff, gen_helper_fmaxa_d) TRANS(fmina_s, FP_SP, gen_fff, gen_helper_fmina_s) TRANS(fmina_d, FP_DP, gen_fff, gen_helper_fmina_d) -TRANS(fscaleb_s, FP_SP, gen_fff, gen_helper_fscaleb_s) -TRANS(fscaleb_d, FP_DP, gen_fff, gen_helper_fscaleb_d) +TRANS64(fscaleb_s, FP_SP, gen_fff, gen_helper_fscaleb_s) +TRANS64(fscaleb_d, FP_DP, gen_fff, gen_helper_fscaleb_d) TRANS(fsqrt_s, FP_SP, gen_ff, gen_helper_fsqrt_s) TRANS(fsqrt_d, FP_DP, gen_ff, gen_helper_fsqrt_d) TRANS(frecip_s, FP_SP, gen_ff, gen_helper_frecip_s) TRANS(frecip_d, FP_DP, gen_ff, gen_helper_frecip_d) TRANS(frsqrt_s, FP_SP, gen_ff, gen_helper_frsqrt_s) TRANS(frsqrt_d, FP_DP, gen_ff, gen_helper_frsqrt_d) -TRANS(flogb_s, FP_SP, gen_ff, gen_helper_flogb_s) -TRANS(flogb_d, FP_DP, gen_ff, gen_helper_flogb_d) +TRANS64(flogb_s, FP_SP, gen_ff, gen_helper_flogb_s) +TRANS64(flogb_d, FP_DP, gen_ff, gen_helper_flogb_d) TRANS(fclass_s, FP_SP, gen_ff, gen_helper_fclass_s) TRANS(fclass_d, FP_DP, gen_ff, gen_helper_fclass_d) TRANS(fmadd_s, FP_SP, gen_muladd, gen_helper_fmuladd_s, 0) diff -Nru qemu-10.0.3+ds/target/loongarch/tcg/insn_trans/trans_fcnv.c.inc qemu-10.0.6+ds/target/loongarch/tcg/insn_trans/trans_fcnv.c.inc --- qemu-10.0.3+ds/target/loongarch/tcg/insn_trans/trans_fcnv.c.inc 2025-07-23 21:05:28.000000000 +0000 +++ qemu-10.0.6+ds/target/loongarch/tcg/insn_trans/trans_fcnv.c.inc 2025-10-20 18:13:46.000000000 +0000 @@ -29,5 +29,5 @@ TRANS(ffint_s_l, FP_SP, gen_ff, gen_helper_ffint_s_l) TRANS(ffint_d_w, FP_DP, gen_ff, gen_helper_ffint_d_w) TRANS(ffint_d_l, FP_DP, gen_ff, gen_helper_ffint_d_l) -TRANS(frint_s, FP_SP, gen_ff, gen_helper_frint_s) -TRANS(frint_d, FP_DP, gen_ff, gen_helper_frint_d) +TRANS64(frint_s, FP_SP, gen_ff, gen_helper_frint_s) +TRANS64(frint_d, FP_DP, gen_ff, gen_helper_frint_d) diff -Nru qemu-10.0.3+ds/target/loongarch/tcg/insn_trans/trans_fmemory.c.inc qemu-10.0.6+ds/target/loongarch/tcg/insn_trans/trans_fmemory.c.inc --- qemu-10.0.3+ds/target/loongarch/tcg/insn_trans/trans_fmemory.c.inc 2025-07-23 21:05:28.000000000 +0000 +++ qemu-10.0.6+ds/target/loongarch/tcg/insn_trans/trans_fmemory.c.inc 2025-10-20 18:13:46.000000000 +0000 @@ -148,11 +148,11 @@ TRANS(fldx_d, FP_DP, gen_floadx, MO_TEUQ) TRANS(fstx_s, FP_SP, gen_fstorex, MO_TEUL) TRANS(fstx_d, FP_DP, gen_fstorex, MO_TEUQ) -TRANS(fldgt_s, FP_SP, gen_fload_gt, MO_TEUL) -TRANS(fldgt_d, FP_DP, gen_fload_gt, MO_TEUQ) -TRANS(fldle_s, FP_SP, gen_fload_le, MO_TEUL) -TRANS(fldle_d, FP_DP, gen_fload_le, MO_TEUQ) -TRANS(fstgt_s, FP_SP, gen_fstore_gt, MO_TEUL) -TRANS(fstgt_d, FP_DP, gen_fstore_gt, MO_TEUQ) -TRANS(fstle_s, FP_SP, gen_fstore_le, MO_TEUL) -TRANS(fstle_d, FP_DP, gen_fstore_le, MO_TEUQ) +TRANS64(fldgt_s, FP_SP, gen_fload_gt, MO_TEUL) +TRANS64(fldgt_d, FP_DP, gen_fload_gt, MO_TEUQ) +TRANS64(fldle_s, FP_SP, gen_fload_le, MO_TEUL) +TRANS64(fldle_d, FP_DP, gen_fload_le, MO_TEUQ) +TRANS64(fstgt_s, FP_SP, gen_fstore_gt, MO_TEUL) +TRANS64(fstgt_d, FP_DP, gen_fstore_gt, MO_TEUQ) +TRANS64(fstle_s, FP_SP, gen_fstore_le, MO_TEUL) +TRANS64(fstle_d, FP_DP, gen_fstore_le, MO_TEUQ) diff -Nru qemu-10.0.3+ds/target/loongarch/tcg/insn_trans/trans_privileged.c.inc qemu-10.0.6+ds/target/loongarch/tcg/insn_trans/trans_privileged.c.inc --- qemu-10.0.3+ds/target/loongarch/tcg/insn_trans/trans_privileged.c.inc 2025-07-23 21:05:28.000000000 +0000 +++ qemu-10.0.6+ds/target/loongarch/tcg/insn_trans/trans_privileged.c.inc 2025-10-20 18:13:46.000000000 +0000 @@ -233,11 +233,11 @@ TRANS(iocsrrd_b, IOCSR, gen_iocsrrd, gen_helper_iocsrrd_b) TRANS(iocsrrd_h, IOCSR, gen_iocsrrd, gen_helper_iocsrrd_h) TRANS(iocsrrd_w, IOCSR, gen_iocsrrd, gen_helper_iocsrrd_w) -TRANS(iocsrrd_d, IOCSR, gen_iocsrrd, gen_helper_iocsrrd_d) +TRANS64(iocsrrd_d, IOCSR, gen_iocsrrd, gen_helper_iocsrrd_d) TRANS(iocsrwr_b, IOCSR, gen_iocsrwr, gen_helper_iocsrwr_b) TRANS(iocsrwr_h, IOCSR, gen_iocsrwr, gen_helper_iocsrwr_h) TRANS(iocsrwr_w, IOCSR, gen_iocsrwr, gen_helper_iocsrwr_w) -TRANS(iocsrwr_d, IOCSR, gen_iocsrwr, gen_helper_iocsrwr_d) +TRANS64(iocsrwr_d, IOCSR, gen_iocsrwr, gen_helper_iocsrwr_d) static void check_mmu_idx(DisasContext *ctx) { diff -Nru qemu-10.0.3+ds/target/loongarch/tcg/insn_trans/trans_shift.c.inc qemu-10.0.6+ds/target/loongarch/tcg/insn_trans/trans_shift.c.inc --- qemu-10.0.3+ds/target/loongarch/tcg/insn_trans/trans_shift.c.inc 2025-07-23 21:05:28.000000000 +0000 +++ qemu-10.0.6+ds/target/loongarch/tcg/insn_trans/trans_shift.c.inc 2025-10-20 18:13:46.000000000 +0000 @@ -78,7 +78,7 @@ TRANS(sll_d, 64, gen_rrr, EXT_NONE, EXT_NONE, EXT_NONE, gen_sll_d) TRANS(srl_d, 64, gen_rrr, EXT_NONE, EXT_NONE, EXT_NONE, gen_srl_d) TRANS(sra_d, 64, gen_rrr, EXT_NONE, EXT_NONE, EXT_NONE, gen_sra_d) -TRANS(rotr_w, 64, gen_rrr, EXT_ZERO, EXT_NONE, EXT_SIGN, gen_rotr_w) +TRANS(rotr_w, ALL, gen_rrr, EXT_ZERO, EXT_NONE, EXT_SIGN, gen_rotr_w) TRANS(rotr_d, 64, gen_rrr, EXT_NONE, EXT_NONE, EXT_NONE, gen_rotr_d) TRANS(slli_w, ALL, gen_rri_c, EXT_NONE, EXT_SIGN, tcg_gen_shli_tl) TRANS(slli_d, 64, gen_rri_c, EXT_NONE, EXT_NONE, tcg_gen_shli_tl) @@ -86,5 +86,5 @@ TRANS(srli_d, 64, gen_rri_c, EXT_NONE, EXT_NONE, tcg_gen_shri_tl) TRANS(srai_w, ALL, gen_rri_c, EXT_NONE, EXT_NONE, gen_sari_w) TRANS(srai_d, 64, gen_rri_c, EXT_NONE, EXT_NONE, tcg_gen_sari_tl) -TRANS(rotri_w, 64, gen_rri_v, EXT_NONE, EXT_NONE, gen_rotr_w) +TRANS(rotri_w, ALL, gen_rri_v, EXT_NONE, EXT_NONE, gen_rotr_w) TRANS(rotri_d, 64, gen_rri_c, EXT_NONE, EXT_NONE, tcg_gen_rotri_tl) diff -Nru qemu-10.0.3+ds/target/loongarch/tcg/insn_trans/trans_vec.c.inc qemu-10.0.6+ds/target/loongarch/tcg/insn_trans/trans_vec.c.inc --- qemu-10.0.3+ds/target/loongarch/tcg/insn_trans/trans_vec.c.inc 2025-07-23 21:05:28.000000000 +0000 +++ qemu-10.0.6+ds/target/loongarch/tcg/insn_trans/trans_vec.c.inc 2025-10-20 18:13:46.000000000 +0000 @@ -3585,7 +3585,9 @@ int sel, vece; uint64_t value; - if (!check_valid_vldi_mode(a)) { + sel = (a->imm >> 12) & 0x1; + + if (sel && !check_valid_vldi_mode(a)) { generate_exception(ctx, EXCCODE_INE); return true; } @@ -3594,8 +3596,6 @@ return true; } - sel = (a->imm >> 12) & 0x1; - if (sel) { value = vldi_get_value(ctx, a->imm); vece = MO_64; diff -Nru qemu-10.0.3+ds/target/loongarch/translate.h qemu-10.0.6+ds/target/loongarch/translate.h --- qemu-10.0.3+ds/target/loongarch/translate.h 2025-07-23 21:05:28.000000000 +0000 +++ qemu-10.0.6+ds/target/loongarch/translate.h 2025-10-20 18:13:46.000000000 +0000 @@ -14,6 +14,10 @@ static bool trans_##NAME(DisasContext *ctx, arg_##NAME * a) \ { return avail_##AVAIL(ctx) && FUNC(ctx, a, __VA_ARGS__); } +#define TRANS64(NAME, AVAIL, FUNC, ...) \ + static bool trans_##NAME(DisasContext *ctx, arg_##NAME * a) \ + { return avail_64(ctx) && avail_##AVAIL(ctx) && FUNC(ctx, a, __VA_ARGS__); } + #define avail_ALL(C) true #define avail_64(C) (FIELD_EX32((C)->cpucfg1, CPUCFG1, ARCH) == \ CPUCFG1_ARCH_LA64) @@ -25,6 +29,7 @@ #define avail_LSX(C) (FIELD_EX32((C)->cpucfg2, CPUCFG2, LSX)) #define avail_LASX(C) (FIELD_EX32((C)->cpucfg2, CPUCFG2, LASX)) #define avail_IOCSR(C) (FIELD_EX32((C)->cpucfg1, CPUCFG1, IOCSR)) +#define avail_CRC(C) (FIELD_EX32((C)->cpucfg1, CPUCFG1, CRC)) /* * If an operation is being performed on less than TARGET_LONG_BITS, diff -Nru qemu-10.0.3+ds/target/mips/tcg/system/cp0_helper.c qemu-10.0.6+ds/target/mips/tcg/system/cp0_helper.c --- qemu-10.0.3+ds/target/mips/tcg/system/cp0_helper.c 2025-07-23 21:05:28.000000000 +0000 +++ qemu-10.0.6+ds/target/mips/tcg/system/cp0_helper.c 2025-10-20 18:13:46.000000000 +0000 @@ -1561,12 +1561,14 @@ CPUState *other_cs = first_cpu; target_ulong prev = env->mvp->CP0_MVPControl; - CPU_FOREACH(other_cs) { - MIPSCPU *other_cpu = MIPS_CPU(other_cs); - /* Turn off all VPEs except the one executing the dvpe. */ - if (&other_cpu->env != env) { - other_cpu->env.mvp->CP0_MVPControl &= ~(1 << CP0MVPCo_EVP); - mips_vpe_sleep(other_cpu); + if (env->CP0_VPEConf0 & (1 << CP0VPEC0_MVP)) { + CPU_FOREACH(other_cs) { + MIPSCPU *other_cpu = MIPS_CPU(other_cs); + /* Turn off all VPEs except the one executing the dvpe. */ + if (&other_cpu->env != env) { + other_cpu->env.mvp->CP0_MVPControl &= ~(1 << CP0MVPCo_EVP); + mips_vpe_sleep(other_cpu); + } } } return prev; @@ -1577,15 +1579,17 @@ CPUState *other_cs = first_cpu; target_ulong prev = env->mvp->CP0_MVPControl; - CPU_FOREACH(other_cs) { - MIPSCPU *other_cpu = MIPS_CPU(other_cs); + if (env->CP0_VPEConf0 & (1 << CP0VPEC0_MVP)) { + CPU_FOREACH(other_cs) { + MIPSCPU *other_cpu = MIPS_CPU(other_cs); - if (&other_cpu->env != env - /* If the VPE is WFI, don't disturb its sleep. */ - && !mips_vpe_is_wfi(other_cpu)) { - /* Enable the VPE. */ - other_cpu->env.mvp->CP0_MVPControl |= (1 << CP0MVPCo_EVP); - mips_vpe_wake(other_cpu); /* And wake it up. */ + if (&other_cpu->env != env + /* If the VPE is WFI, don't disturb its sleep. */ + && !mips_vpe_is_wfi(other_cpu)) { + /* Enable the VPE. */ + other_cpu->env.mvp->CP0_MVPControl |= (1 << CP0MVPCo_EVP); + mips_vpe_wake(other_cpu); /* And wake it up. */ + } } } return prev; diff -Nru qemu-10.0.3+ds/target/mips/tcg/system/tlb_helper.c qemu-10.0.6+ds/target/mips/tcg/system/tlb_helper.c --- qemu-10.0.3+ds/target/mips/tcg/system/tlb_helper.c 2025-07-23 21:05:28.000000000 +0000 +++ qemu-10.0.6+ds/target/mips/tcg/system/tlb_helper.c 2025-10-20 18:13:46.000000000 +0000 @@ -652,7 +652,7 @@ return 0; } - if ((entry & (1 << psn)) && hugepg) { + if (extract64(entry, psn, 1) && hugepg) { *huge_page = true; *hgpg_directory_hit = true; entry = get_tlb_entry_layout(env, entry, leaf_mop, pf_ptew); diff -Nru qemu-10.0.3+ds/target/ppc/cpu.h qemu-10.0.6+ds/target/ppc/cpu.h --- qemu-10.0.3+ds/target/ppc/cpu.h 2025-07-23 21:05:28.000000000 +0000 +++ qemu-10.0.6+ds/target/ppc/cpu.h 2025-10-20 18:13:46.000000000 +0000 @@ -1520,6 +1520,10 @@ void (*init_proc)(CPUPPCState *env); int (*check_pow)(CPUPPCState *env); int (*check_attn)(CPUPPCState *env); + + /* Handlers to be set by the machine initialising the chips */ + uint64_t (*load_sprd)(CPUPPCState *env); + void (*store_sprd)(CPUPPCState *env, uint64_t val); }; static inline bool ppc_cpu_core_single_threaded(CPUState *cs) diff -Nru qemu-10.0.3+ds/target/ppc/misc_helper.c qemu-10.0.6+ds/target/ppc/misc_helper.c --- qemu-10.0.3+ds/target/ppc/misc_helper.c 2025-07-23 21:05:28.000000000 +0000 +++ qemu-10.0.6+ds/target/ppc/misc_helper.c 2025-10-20 18:13:46.000000000 +0000 @@ -329,69 +329,22 @@ * accessed by powernv machines. */ PowerPCCPU *cpu = env_archcpu(env); - PnvCore *pc = pnv_cpu_state(cpu)->pnv_core; - target_ulong sprc = env->spr[SPR_POWER_SPRC]; + PowerPCCPUClass *pcc = POWERPC_CPU_GET_CLASS(cpu); - if (pc->big_core) { - pc = pnv_chip_find_core(pc->chip, CPU_CORE(pc)->core_id & ~0x1); + if (pcc->load_sprd) { + return pcc->load_sprd(env); } - switch (sprc & 0x3e0) { - case 0: /* SCRATCH0-3 */ - case 1: /* SCRATCH4-7 */ - return pc->scratch[(sprc >> 3) & 0x7]; - - case 0x1e0: /* core thread state */ - if (env->excp_model == POWERPC_EXCP_POWER9) { - /* - * Only implement for POWER9 because skiboot uses it to check - * big-core mode. Other bits are unimplemented so we would - * prefer to get unimplemented message on POWER10 if it were - * used anywhere. - */ - if (pc->big_core) { - return PPC_BIT(63); - } else { - return 0; - } - } - /* fallthru */ - - default: - qemu_log_mask(LOG_UNIMP, "mfSPRD: Unimplemented SPRC:0x" - TARGET_FMT_lx"\n", sprc); - break; - } return 0; } void helper_store_sprd(CPUPPCState *env, target_ulong val) { - target_ulong sprc = env->spr[SPR_POWER_SPRC]; PowerPCCPU *cpu = env_archcpu(env); - PnvCore *pc = pnv_cpu_state(cpu)->pnv_core; - int nr; - - if (pc->big_core) { - pc = pnv_chip_find_core(pc->chip, CPU_CORE(pc)->core_id & ~0x1); - } + PowerPCCPUClass *pcc = POWERPC_CPU_GET_CLASS(cpu); - switch (sprc & 0x3e0) { - case 0: /* SCRATCH0-3 */ - case 1: /* SCRATCH4-7 */ - /* - * Log stores to SCRATCH, because some firmware uses these for - * debugging and logging, but they would normally be read by the BMC, - * which is not implemented in QEMU yet. This gives a way to get at the - * information. Could also dump these upon checkstop. - */ - nr = (sprc >> 3) & 0x7; - pc->scratch[nr] = val; - break; - default: - qemu_log_mask(LOG_UNIMP, "mtSPRD: Unimplemented SPRC:0x" - TARGET_FMT_lx"\n", sprc); - break; + if (pcc->store_sprd) { + return pcc->store_sprd(env, val); } } diff -Nru qemu-10.0.3+ds/target/riscv/cpu.c qemu-10.0.6+ds/target/riscv/cpu.c --- qemu-10.0.3+ds/target/riscv/cpu.c 2025-07-23 21:05:28.000000000 +0000 +++ qemu-10.0.6+ds/target/riscv/cpu.c 2025-10-20 18:13:46.000000000 +0000 @@ -945,7 +945,7 @@ } } } - if (riscv_has_ext(env, RVV) && (flags & CPU_DUMP_VPU)) { + if (riscv_cpu_cfg(env)->ext_zve32x && (flags & CPU_DUMP_VPU)) { static const int dump_rvv_csrs[] = { CSR_VSTART, CSR_VXSAT, diff -Nru qemu-10.0.3+ds/target/riscv/cpu.h qemu-10.0.6+ds/target/riscv/cpu.h --- qemu-10.0.3+ds/target/riscv/cpu.h 2025-07-23 21:05:28.000000000 +0000 +++ qemu-10.0.6+ds/target/riscv/cpu.h 2025-10-20 18:13:46.000000000 +0000 @@ -839,7 +839,7 @@ static inline target_ulong riscv_csr_read(CPURISCVState *env, int csrno) { target_ulong val = 0; - riscv_csrrw(env, csrno, &val, 0, 0); + riscv_csrr(env, csrno, &val); return val; } diff -Nru qemu-10.0.3+ds/target/riscv/csr.c qemu-10.0.6+ds/target/riscv/csr.c --- qemu-10.0.3+ds/target/riscv/csr.c 2025-07-23 21:05:28.000000000 +0000 +++ qemu-10.0.6+ds/target/riscv/csr.c 2025-10-20 18:13:46.000000000 +0000 @@ -202,6 +202,8 @@ #if !defined(CONFIG_USER_ONLY) if (env->debugger) { return RISCV_EXCP_NONE; + } else if (env->virt_enabled) { + return RISCV_EXCP_VIRT_INSTRUCTION_FAULT; } #endif return RISCV_EXCP_ILLEGAL_INST; @@ -372,8 +374,11 @@ static RISCVException aia_smode32(CPURISCVState *env, int csrno) { int ret; + int csr_priv = get_field(csrno, 0x300); - if (!riscv_cpu_cfg(env)->ext_ssaia) { + if (csr_priv == PRV_M && !riscv_cpu_cfg(env)->ext_smaia) { + return RISCV_EXCP_ILLEGAL_INST; + } else if (!riscv_cpu_cfg(env)->ext_ssaia) { return RISCV_EXCP_ILLEGAL_INST; } @@ -1987,7 +1992,8 @@ if (riscv_has_ext(env, RVF)) { mask |= MSTATUS_FS; } - if (riscv_has_ext(env, RVV)) { + + if (riscv_cpu_cfg(env)->ext_zve32x) { mask |= MSTATUS_VS; } @@ -5498,7 +5504,7 @@ csr_priv = get_field(csrno, 0x300); if (!env->debugger && (effective_priv < csr_priv)) { - if (csr_priv == (PRV_S + 1) && env->virt_enabled) { + if (csr_priv <= (PRV_S + 1) && env->virt_enabled) { return RISCV_EXCP_VIRT_INSTRUCTION_FAULT; } return RISCV_EXCP_ILLEGAL_INST; @@ -5783,8 +5789,8 @@ NULL, read_mstatus_i128 }, [CSR_MISA] = { "misa", any, read_misa, write_misa, NULL, read_misa_i128 }, - [CSR_MIDELEG] = { "mideleg", any, NULL, NULL, rmw_mideleg }, - [CSR_MEDELEG] = { "medeleg", any, read_medeleg, write_medeleg }, + [CSR_MIDELEG] = { "mideleg", smode, NULL, NULL, rmw_mideleg }, + [CSR_MEDELEG] = { "medeleg", smode, read_medeleg, write_medeleg }, [CSR_MIE] = { "mie", any, NULL, NULL, rmw_mie }, [CSR_MTVEC] = { "mtvec", any, read_mtvec, write_mtvec }, [CSR_MCOUNTEREN] = { "mcounteren", umode, read_mcounteren, @@ -5792,7 +5798,7 @@ [CSR_MSTATUSH] = { "mstatush", any32, read_mstatush, write_mstatush }, - [CSR_MEDELEGH] = { "medelegh", any32, read_zero, write_ignore, + [CSR_MEDELEGH] = { "medelegh", smode32, read_zero, write_ignore, .min_priv_ver = PRIV_VERSION_1_13_0 }, [CSR_HEDELEGH] = { "hedelegh", hmode32, read_hedelegh, write_hedelegh, .min_priv_ver = PRIV_VERSION_1_13_0 }, @@ -5832,7 +5838,7 @@ [CSR_MVIP] = { "mvip", aia_any, NULL, NULL, rmw_mvip }, /* Machine-Level High-Half CSRs (AIA) */ - [CSR_MIDELEGH] = { "midelegh", aia_any32, NULL, NULL, rmw_midelegh }, + [CSR_MIDELEGH] = { "midelegh", aia_smode32, NULL, NULL, rmw_midelegh }, [CSR_MIEH] = { "mieh", aia_any32, NULL, NULL, rmw_mieh }, [CSR_MVIENH] = { "mvienh", aia_any32, NULL, NULL, rmw_mvienh }, [CSR_MVIPH] = { "mviph", aia_any32, NULL, NULL, rmw_mviph }, diff -Nru qemu-10.0.3+ds/target/riscv/helper.h qemu-10.0.6+ds/target/riscv/helper.h --- qemu-10.0.3+ds/target/riscv/helper.h 2025-07-23 21:05:28.000000000 +0000 +++ qemu-10.0.6+ds/target/riscv/helper.h 2025-10-20 18:13:46.000000000 +0000 @@ -1101,14 +1101,14 @@ DEF_HELPER_6(vslidedown_vx_h, void, ptr, ptr, tl, ptr, env, i32) DEF_HELPER_6(vslidedown_vx_w, void, ptr, ptr, tl, ptr, env, i32) DEF_HELPER_6(vslidedown_vx_d, void, ptr, ptr, tl, ptr, env, i32) -DEF_HELPER_6(vslide1up_vx_b, void, ptr, ptr, tl, ptr, env, i32) -DEF_HELPER_6(vslide1up_vx_h, void, ptr, ptr, tl, ptr, env, i32) -DEF_HELPER_6(vslide1up_vx_w, void, ptr, ptr, tl, ptr, env, i32) -DEF_HELPER_6(vslide1up_vx_d, void, ptr, ptr, tl, ptr, env, i32) -DEF_HELPER_6(vslide1down_vx_b, void, ptr, ptr, tl, ptr, env, i32) -DEF_HELPER_6(vslide1down_vx_h, void, ptr, ptr, tl, ptr, env, i32) -DEF_HELPER_6(vslide1down_vx_w, void, ptr, ptr, tl, ptr, env, i32) -DEF_HELPER_6(vslide1down_vx_d, void, ptr, ptr, tl, ptr, env, i32) +DEF_HELPER_6(vslide1up_vx_b, void, ptr, ptr, i64, ptr, env, i32) +DEF_HELPER_6(vslide1up_vx_h, void, ptr, ptr, i64, ptr, env, i32) +DEF_HELPER_6(vslide1up_vx_w, void, ptr, ptr, i64, ptr, env, i32) +DEF_HELPER_6(vslide1up_vx_d, void, ptr, ptr, i64, ptr, env, i32) +DEF_HELPER_6(vslide1down_vx_b, void, ptr, ptr, i64, ptr, env, i32) +DEF_HELPER_6(vslide1down_vx_h, void, ptr, ptr, i64, ptr, env, i32) +DEF_HELPER_6(vslide1down_vx_w, void, ptr, ptr, i64, ptr, env, i32) +DEF_HELPER_6(vslide1down_vx_d, void, ptr, ptr, i64, ptr, env, i32) DEF_HELPER_6(vfslide1up_vf_h, void, ptr, ptr, i64, ptr, env, i32) DEF_HELPER_6(vfslide1up_vf_w, void, ptr, ptr, i64, ptr, env, i32) @@ -1284,3 +1284,8 @@ DEF_HELPER_5(vsm4k_vi, void, ptr, ptr, i32, env, i32) DEF_HELPER_4(vsm4r_vv, void, ptr, ptr, env, i32) DEF_HELPER_4(vsm4r_vs, void, ptr, ptr, env, i32) + +/* CFI (zicfiss) helpers */ +#ifndef CONFIG_USER_ONLY +DEF_HELPER_1(ssamoswap_disabled, void, env) +#endif diff -Nru qemu-10.0.3+ds/target/riscv/insn_trans/trans_rvv.c.inc qemu-10.0.6+ds/target/riscv/insn_trans/trans_rvv.c.inc --- qemu-10.0.3+ds/target/riscv/insn_trans/trans_rvv.c.inc 2025-07-23 21:05:28.000000000 +0000 +++ qemu-10.0.6+ds/target/riscv/insn_trans/trans_rvv.c.inc 2025-10-20 18:13:46.000000000 +0000 @@ -3494,7 +3494,6 @@ } GEN_OPIVX_TRANS(vslideup_vx, slideup_check) -GEN_OPIVX_TRANS(vslide1up_vx, slideup_check) GEN_OPIVI_TRANS(vslideup_vi, IMM_ZX, vslideup_vx, slideup_check) static bool slidedown_check(DisasContext *s, arg_rmrr *a) @@ -3505,9 +3504,56 @@ } GEN_OPIVX_TRANS(vslidedown_vx, slidedown_check) -GEN_OPIVX_TRANS(vslide1down_vx, slidedown_check) GEN_OPIVI_TRANS(vslidedown_vi, IMM_ZX, vslidedown_vx, slidedown_check) +typedef void gen_helper_vslide1_vx(TCGv_ptr, TCGv_ptr, TCGv_i64, TCGv_ptr, + TCGv_env, TCGv_i32); + +#define GEN_OPIVX_VSLIDE1_TRANS(NAME, CHECK) \ +static bool trans_##NAME(DisasContext *s, arg_rmrr *a) \ +{ \ + if (CHECK(s, a)) { \ + static gen_helper_vslide1_vx * const fns[4] = { \ + gen_helper_##NAME##_b, gen_helper_##NAME##_h, \ + gen_helper_##NAME##_w, gen_helper_##NAME##_d, \ + }; \ + \ + TCGv_ptr dest, src2, mask; \ + TCGv_i64 src1; \ + TCGv_i32 desc; \ + uint32_t data = 0; \ + \ + dest = tcg_temp_new_ptr(); \ + mask = tcg_temp_new_ptr(); \ + src2 = tcg_temp_new_ptr(); \ + src1 = tcg_temp_new_i64(); \ + \ + data = FIELD_DP32(data, VDATA, VM, a->vm); \ + data = FIELD_DP32(data, VDATA, LMUL, s->lmul); \ + data = FIELD_DP32(data, VDATA, VTA, s->vta); \ + data = FIELD_DP32(data, VDATA, VTA_ALL_1S, s->cfg_vta_all_1s); \ + data = FIELD_DP32(data, VDATA, VMA, s->vma); \ + desc = tcg_constant_i32(simd_desc(s->cfg_ptr->vlenb, \ + s->cfg_ptr->vlenb, data)); \ + \ + tcg_gen_addi_ptr(dest, tcg_env, vreg_ofs(s, a->rd)); \ + tcg_gen_addi_ptr(src2, tcg_env, vreg_ofs(s, a->rs2)); \ + tcg_gen_addi_ptr(mask, tcg_env, vreg_ofs(s, 0)); \ + tcg_gen_ext_tl_i64(src1, get_gpr(s, a->rs1, EXT_SIGN)); \ + \ + fns[s->sew](dest, mask, src1, src2, tcg_env, desc); \ + \ + tcg_gen_movi_tl(cpu_vstart, 0); \ + finalize_rvv_inst(s); \ + \ + return true; \ + } \ + return false; \ +} + +GEN_OPIVX_VSLIDE1_TRANS(vslide1up_vx, slideup_check) +GEN_OPIVX_VSLIDE1_TRANS(vslide1down_vx, slidedown_check) + /* Vector Floating-Point Slide Instructions */ static bool fslideup_check(DisasContext *s, arg_rmrr *a) { diff -Nru qemu-10.0.3+ds/target/riscv/insn_trans/trans_rvzce.c.inc qemu-10.0.6+ds/target/riscv/insn_trans/trans_rvzce.c.inc --- qemu-10.0.3+ds/target/riscv/insn_trans/trans_rvzce.c.inc 2025-07-23 21:05:28.000000000 +0000 +++ qemu-10.0.6+ds/target/riscv/insn_trans/trans_rvzce.c.inc 2025-10-20 18:13:46.000000000 +0000 @@ -88,13 +88,13 @@ static bool trans_c_lhu(DisasContext *ctx, arg_c_lhu *a) { REQUIRE_ZCB(ctx); - return gen_load(ctx, a, MO_UW); + return gen_load(ctx, a, MO_TEUW); } static bool trans_c_lh(DisasContext *ctx, arg_c_lh *a) { REQUIRE_ZCB(ctx); - return gen_load(ctx, a, MO_SW); + return gen_load(ctx, a, MO_TESW); } static bool trans_c_sb(DisasContext *ctx, arg_c_sb *a) @@ -106,7 +106,7 @@ static bool trans_c_sh(DisasContext *ctx, arg_c_sh *a) { REQUIRE_ZCB(ctx); - return gen_store(ctx, a, MO_UW); + return gen_store(ctx, a, MO_TEUW); } #define X_S0 8 diff -Nru qemu-10.0.3+ds/target/riscv/insn_trans/trans_rvzicfiss.c.inc qemu-10.0.6+ds/target/riscv/insn_trans/trans_rvzicfiss.c.inc --- qemu-10.0.3+ds/target/riscv/insn_trans/trans_rvzicfiss.c.inc 2025-07-23 21:05:28.000000000 +0000 +++ qemu-10.0.6+ds/target/riscv/insn_trans/trans_rvzicfiss.c.inc 2025-10-20 18:13:46.000000000 +0000 @@ -40,6 +40,7 @@ tcg_gen_brcond_tl(TCG_COND_EQ, data, rs1, skip); tcg_gen_st_tl(tcg_constant_tl(RISCV_EXCP_SW_CHECK_BCFI_TVAL), tcg_env, offsetof(CPURISCVState, sw_check_code)); + gen_update_pc(ctx, 0); gen_helper_raise_exception(tcg_env, tcg_constant_i32(RISCV_EXCP_SW_CHECK)); gen_set_label(skip); @@ -90,7 +91,11 @@ } if (!ctx->bcfi_enabled) { +#ifndef CONFIG_USER_ONLY + gen_helper_ssamoswap_disabled(tcg_env); +#else return false; +#endif } TCGv dest = dest_gpr(ctx, a->rd); @@ -115,7 +120,11 @@ } if (!ctx->bcfi_enabled) { +#ifndef CONFIG_USER_ONLY + gen_helper_ssamoswap_disabled(tcg_env); +#else return false; +#endif } TCGv dest = dest_gpr(ctx, a->rd); diff -Nru qemu-10.0.3+ds/target/riscv/machine.c qemu-10.0.6+ds/target/riscv/machine.c --- qemu-10.0.3+ds/target/riscv/machine.c 2025-07-23 21:05:28.000000000 +0000 +++ qemu-10.0.6+ds/target/riscv/machine.c 2025-10-20 18:13:46.000000000 +0000 @@ -130,7 +130,8 @@ RISCVCPU *cpu = opaque; CPURISCVState *env = &cpu->env; - return riscv_has_ext(env, RVV); + return kvm_enabled() ? riscv_has_ext(env, RVV) : + riscv_cpu_cfg(env)->ext_zve32x; } static const VMStateDescription vmstate_vector = { diff -Nru qemu-10.0.3+ds/target/riscv/op_helper.c qemu-10.0.6+ds/target/riscv/op_helper.c --- qemu-10.0.3+ds/target/riscv/op_helper.c 2025-07-23 21:05:28.000000000 +0000 +++ qemu-10.0.6+ds/target/riscv/op_helper.c 2025-10-20 18:13:46.000000000 +0000 @@ -353,21 +353,22 @@ } static void check_ret_from_m_mode(CPURISCVState *env, target_ulong retpc, - target_ulong prev_priv) + target_ulong prev_priv, + uintptr_t ra) { if (!(env->priv >= PRV_M)) { - riscv_raise_exception(env, RISCV_EXCP_ILLEGAL_INST, GETPC()); + riscv_raise_exception(env, RISCV_EXCP_ILLEGAL_INST, ra); } if (!riscv_cpu_allow_16bit_insn(&env_archcpu(env)->cfg, env->priv_ver, env->misa_ext) && (retpc & 0x3)) { - riscv_raise_exception(env, RISCV_EXCP_INST_ADDR_MIS, GETPC()); + riscv_raise_exception(env, RISCV_EXCP_INST_ADDR_MIS, ra); } if (riscv_cpu_cfg(env)->pmp && !pmp_get_num_rules(env) && (prev_priv != PRV_M)) { - riscv_raise_exception(env, RISCV_EXCP_INST_ACCESS_FAULT, GETPC()); + riscv_raise_exception(env, RISCV_EXCP_INST_ACCESS_FAULT, ra); } } static target_ulong ssdbltrp_mxret(CPURISCVState *env, target_ulong mstatus, @@ -392,8 +393,9 @@ target_ulong retpc = env->mepc; uint64_t mstatus = env->mstatus; target_ulong prev_priv = get_field(mstatus, MSTATUS_MPP); + uintptr_t ra = GETPC(); - check_ret_from_m_mode(env, retpc, prev_priv); + check_ret_from_m_mode(env, retpc, prev_priv, ra); target_ulong prev_virt = get_field(env->mstatus, MSTATUS_MPV) && (prev_priv != PRV_M); @@ -441,8 +443,9 @@ target_ulong retpc = env->mnepc; target_ulong prev_priv = get_field(env->mnstatus, MNSTATUS_MNPP); target_ulong prev_virt; + uintptr_t ra = GETPC(); - check_ret_from_m_mode(env, retpc, prev_priv); + check_ret_from_m_mode(env, retpc, prev_priv, ra); prev_virt = get_field(env->mnstatus, MNSTATUS_MNPV) && (prev_priv != PRV_M); @@ -712,4 +715,53 @@ return cpu_ldl_code_mmu(env, addr, oi, ra); } +void helper_ssamoswap_disabled(CPURISCVState *env) +{ + int exception = RISCV_EXCP_ILLEGAL_INST; + + /* + * Here we follow the RISC-V CFI spec [1] to implement the exception type + * of ssamoswap* instruction. + * + * [1] RISC-V CFI spec v1.0, ch2.7 Atomic Swap from a Shadow Stack Location + * + * Note: We have already checked some conditions in trans_* functions: + * 1. The effective priv mode is not M-mode. + * 2. The xSSE specific to the effictive priv mode is disabled. + */ + if (!get_field(env->menvcfg, MENVCFG_SSE)) { + /* + * Disabled M-mode SSE always trigger illegal instruction when + * current priv mode is not M-mode. + */ + exception = RISCV_EXCP_ILLEGAL_INST; + goto done; + } + + if (!riscv_has_ext(env, RVS)) { + /* S-mode is not implemented */ + exception = RISCV_EXCP_ILLEGAL_INST; + goto done; + } else if (env->virt_enabled) { + /* + * VU/VS-mode with disabled xSSE will trigger the virtual instruction + * exception. + */ + exception = RISCV_EXCP_VIRT_INSTRUCTION_FAULT; + goto done; + } else { + /* + * U-mode with disabled S-mode SSE will trigger the illegal instruction + * exception. + * + * Note: S-mode is already handled in the disabled M-mode SSE case. + */ + exception = RISCV_EXCP_ILLEGAL_INST; + goto done; + } + +done: + riscv_raise_exception(env, exception, GETPC()); +} + #endif /* !CONFIG_USER_ONLY */ diff -Nru qemu-10.0.3+ds/target/riscv/pmp.c qemu-10.0.6+ds/target/riscv/pmp.c --- qemu-10.0.3+ds/target/riscv/pmp.c 2025-07-23 21:05:28.000000000 +0000 +++ qemu-10.0.6+ds/target/riscv/pmp.c 2025-10-20 18:13:46.000000000 +0000 @@ -206,11 +206,12 @@ break; case PMP_AMATCH_TOR: - sa = prev_addr << 2; /* shift up from [xx:0] to [xx+2:2] */ - ea = (this_addr << 2) - 1u; - if (sa > ea) { + if (prev_addr >= this_addr) { sa = ea = 0u; + break; } + sa = prev_addr << 2; /* shift up from [xx:0] to [xx+2:2] */ + ea = (this_addr << 2) - 1u; break; case PMP_AMATCH_NA4: diff -Nru qemu-10.0.3+ds/target/riscv/tcg/tcg-cpu.c qemu-10.0.6+ds/target/riscv/tcg/tcg-cpu.c --- qemu-10.0.3+ds/target/riscv/tcg/tcg-cpu.c 2025-07-23 21:05:28.000000000 +0000 +++ qemu-10.0.6+ds/target/riscv/tcg/tcg-cpu.c 2025-10-20 18:13:46.000000000 +0000 @@ -280,12 +280,21 @@ static void riscv_cpu_validate_v(CPURISCVState *env, RISCVCPUConfig *cfg, Error **errp) { + uint32_t min_vlen; uint32_t vlen = cfg->vlenb << 3; - if (vlen > RV_VLEN_MAX || vlen < 128) { + if (riscv_has_ext(env, RVV)) { + min_vlen = 128; + } else if (cfg->ext_zve64x) { + min_vlen = 64; + } else if (cfg->ext_zve32x) { + min_vlen = 32; + } + + if (vlen > RV_VLEN_MAX || vlen < min_vlen) { error_setg(errp, "Vector extension implementation only supports VLEN " - "in the range [128, %d]", RV_VLEN_MAX); + "in the range [%d, %d]", min_vlen, RV_VLEN_MAX); return; } @@ -295,6 +304,12 @@ "in the range [8, 64]"); return; } + + if (vlen < cfg->elen) { + error_setg(errp, "Vector extension implementation requires VLEN " + "to be greater than or equal to ELEN"); + return; + } } static void riscv_cpu_disable_priv_spec_isa_exts(RISCVCPU *cpu) @@ -515,7 +530,7 @@ return; } - if (riscv_has_ext(env, RVV)) { + if (cpu->cfg.ext_zve32x) { riscv_cpu_validate_v(env, &cpu->cfg, &local_err); if (local_err != NULL) { error_propagate(errp, local_err); diff -Nru qemu-10.0.3+ds/target/riscv/translate.c qemu-10.0.6+ds/target/riscv/translate.c --- qemu-10.0.3+ds/target/riscv/translate.c 2025-07-23 21:05:28.000000000 +0000 +++ qemu-10.0.6+ds/target/riscv/translate.c 2025-10-20 18:13:46.000000000 +0000 @@ -25,6 +25,7 @@ #include "exec/helper-gen.h" #include "exec/translator.h" +#include "exec/cpu_ldst.h" #include "exec/translation-block.h" #include "exec/log.h" #include "semihosting/semihost.h" @@ -1167,7 +1168,7 @@ CPUState *cpu = ctx->cs; CPURISCVState *env = cpu_env(cpu); - return translator_ldl(env, &ctx->base, pc); + return cpu_ldl_code(env, pc); } #define SS_MMU_INDEX(ctx) (ctx->mem_idx | MMU_IDX_SS_WRITE) diff -Nru qemu-10.0.3+ds/target/riscv/vector_helper.c qemu-10.0.6+ds/target/riscv/vector_helper.c --- qemu-10.0.3+ds/target/riscv/vector_helper.c 2025-07-23 21:05:28.000000000 +0000 +++ qemu-10.0.6+ds/target/riscv/vector_helper.c 2025-10-20 18:13:46.000000000 +0000 @@ -5169,11 +5169,11 @@ GEN_VEXT_VSLIE1UP(32, H4) GEN_VEXT_VSLIE1UP(64, H8) -#define GEN_VEXT_VSLIDE1UP_VX(NAME, BITWIDTH) \ -void HELPER(NAME)(void *vd, void *v0, target_ulong s1, void *vs2, \ - CPURISCVState *env, uint32_t desc) \ -{ \ - vslide1up_##BITWIDTH(vd, v0, s1, vs2, env, desc); \ +#define GEN_VEXT_VSLIDE1UP_VX(NAME, BITWIDTH) \ +void HELPER(NAME)(void *vd, void *v0, uint64_t s1, void *vs2, \ + CPURISCVState *env, uint32_t desc) \ +{ \ + vslide1up_##BITWIDTH(vd, v0, s1, vs2, env, desc); \ } /* vslide1up.vx vd, vs2, rs1, vm # vd[0]=x[rs1], vd[i+1] = vs2[i] */ @@ -5220,11 +5220,11 @@ GEN_VEXT_VSLIDE1DOWN(32, H4) GEN_VEXT_VSLIDE1DOWN(64, H8) -#define GEN_VEXT_VSLIDE1DOWN_VX(NAME, BITWIDTH) \ -void HELPER(NAME)(void *vd, void *v0, target_ulong s1, void *vs2, \ - CPURISCVState *env, uint32_t desc) \ -{ \ - vslide1down_##BITWIDTH(vd, v0, s1, vs2, env, desc); \ +#define GEN_VEXT_VSLIDE1DOWN_VX(NAME, BITWIDTH) \ +void HELPER(NAME)(void *vd, void *v0, uint64_t s1, void *vs2, \ + CPURISCVState *env, uint32_t desc) \ +{ \ + vslide1down_##BITWIDTH(vd, v0, s1, vs2, env, desc); \ } /* vslide1down.vx vd, vs2, rs1, vm # vd[i] = vs2[i+1], vd[vl-1]=x[rs1] */ diff -Nru qemu-10.0.3+ds/target/sparc/insns.decode qemu-10.0.6+ds/target/sparc/insns.decode --- qemu-10.0.3+ds/target/sparc/insns.decode 2025-07-23 21:05:28.000000000 +0000 +++ qemu-10.0.6+ds/target/sparc/insns.decode 2025-10-20 18:13:46.000000000 +0000 @@ -88,9 +88,10 @@ { [ - STBAR 10 00000 101000 01111 0 0000000000000 + STBAR_v9 10 00000 101000 01111 0 0000000000000 MEMBAR 10 00000 101000 01111 1 000000 cmask:3 mmask:4 + RDY_v9 10 rd:5 101000 00000 0 0000000000000 RDCCR 10 rd:5 101000 00010 0 0000000000000 RDASI 10 rd:5 101000 00011 0 0000000000000 RDTICK 10 rd:5 101000 00100 0 0000000000000 @@ -107,8 +108,26 @@ RDSTICK_CMPR 10 rd:5 101000 11001 0 0000000000000 RDSTRAND_STATUS 10 rd:5 101000 11010 0 0000000000000 ] - # Before v8, all rs1 accepted; otherwise rs1==0. - RDY 10 rd:5 101000 rs1:5 0 0000000000000 + + # The v8 manual, section B.30 STBAR instruction, says + # bits [12:0] are ignored, but bit 13 must be 0. + # However, section B.28 Read State Register Instruction has a + # comment that RDASR with rs1 = 15, rd = 0 is STBAR. Here, + # bit 13 is also ignored and rd != 0 is merely reserved. + # + # Solaris 8 executes v9 MEMBAR instruction 0x8143e008 during boot. + # This confirms that bit 13 is ignored, as 0x8143c000 is STBAR. + STBAR_v8 10 ----- 101000 01111 - ------------- + + # For v7, bits [18:0] are ignored. + # For v8, bits [18:14], aka rs1, are repurposed and rs1 = 0 is RDY, + # and other values are RDASR. However, the v8 manual explicitly + # says that rs1 in 1..14 yield undefined results and do not cause + # an illegal instruction trap, and rs1 in 16..31 are available for + # implementation specific usage. + # Implement not causing an illegal instruction trap for v8 by + # continuing to interpret unused values per v7, i.e. as RDY. + RDY_v7 10 rd:5 101000 ----- - ------------- } { @@ -139,14 +158,16 @@ } { - RDPSR 10 rd:5 101001 00000 0 0000000000000 - RDHPR_hpstate 10 rd:5 101001 00000 0 0000000000000 + [ + RDHPR_hpstate 10 rd:5 101001 00000 0 0000000000000 + RDHPR_htstate 10 rd:5 101001 00001 0 0000000000000 + RDHPR_hintp 10 rd:5 101001 00011 0 0000000000000 + RDHPR_htba 10 rd:5 101001 00101 0 0000000000000 + RDHPR_hver 10 rd:5 101001 00110 0 0000000000000 + RDHPR_hstick_cmpr 10 rd:5 101001 11111 0 0000000000000 + ] + RDPSR 10 rd:5 101001 ----- - ------------- } -RDHPR_htstate 10 rd:5 101001 00001 0 0000000000000 -RDHPR_hintp 10 rd:5 101001 00011 0 0000000000000 -RDHPR_htba 10 rd:5 101001 00101 0 0000000000000 -RDHPR_hver 10 rd:5 101001 00110 0 0000000000000 -RDHPR_hstick_cmpr 10 rd:5 101001 11111 0 0000000000000 { WRPSR 10 00000 110001 ..... . ............. @n_r_ri @@ -159,26 +180,28 @@ # UA2005 INVALW { - RDWIM 10 rd:5 101010 00000 0 0000000000000 - RDPR_tpc 10 rd:5 101010 00000 0 0000000000000 + [ + RDPR_tpc 10 rd:5 101010 00000 0 0000000000000 + RDPR_tnpc 10 rd:5 101010 00001 0 0000000000000 + RDPR_tstate 10 rd:5 101010 00010 0 0000000000000 + RDPR_tt 10 rd:5 101010 00011 0 0000000000000 + RDPR_tick 10 rd:5 101010 00100 0 0000000000000 + RDPR_tba 10 rd:5 101010 00101 0 0000000000000 + RDPR_pstate 10 rd:5 101010 00110 0 0000000000000 + RDPR_tl 10 rd:5 101010 00111 0 0000000000000 + RDPR_pil 10 rd:5 101010 01000 0 0000000000000 + RDPR_cwp 10 rd:5 101010 01001 0 0000000000000 + RDPR_cansave 10 rd:5 101010 01010 0 0000000000000 + RDPR_canrestore 10 rd:5 101010 01011 0 0000000000000 + RDPR_cleanwin 10 rd:5 101010 01100 0 0000000000000 + RDPR_otherwin 10 rd:5 101010 01101 0 0000000000000 + RDPR_wstate 10 rd:5 101010 01110 0 0000000000000 + RDPR_gl 10 rd:5 101010 10000 0 0000000000000 + RDPR_strand_status 10 rd:5 101010 11010 0 0000000000000 + RDPR_ver 10 rd:5 101010 11111 0 0000000000000 + ] + RDWIM 10 rd:5 101010 ----- - ------------- } -RDPR_tnpc 10 rd:5 101010 00001 0 0000000000000 -RDPR_tstate 10 rd:5 101010 00010 0 0000000000000 -RDPR_tt 10 rd:5 101010 00011 0 0000000000000 -RDPR_tick 10 rd:5 101010 00100 0 0000000000000 -RDPR_tba 10 rd:5 101010 00101 0 0000000000000 -RDPR_pstate 10 rd:5 101010 00110 0 0000000000000 -RDPR_tl 10 rd:5 101010 00111 0 0000000000000 -RDPR_pil 10 rd:5 101010 01000 0 0000000000000 -RDPR_cwp 10 rd:5 101010 01001 0 0000000000000 -RDPR_cansave 10 rd:5 101010 01010 0 0000000000000 -RDPR_canrestore 10 rd:5 101010 01011 0 0000000000000 -RDPR_cleanwin 10 rd:5 101010 01100 0 0000000000000 -RDPR_otherwin 10 rd:5 101010 01101 0 0000000000000 -RDPR_wstate 10 rd:5 101010 01110 0 0000000000000 -RDPR_gl 10 rd:5 101010 10000 0 0000000000000 -RDPR_strand_status 10 rd:5 101010 11010 0 0000000000000 -RDPR_ver 10 rd:5 101010 11111 0 0000000000000 { WRWIM 10 00000 110010 ..... . ............. @n_r_ri @@ -203,7 +226,7 @@ { FLUSHW 10 00000 101011 00000 0 0000000000000 - RDTBR 10 rd:5 101011 00000 0 0000000000000 + RDTBR 10 rd:5 101011 ----- - ------------- } { diff -Nru qemu-10.0.3+ds/target/sparc/translate.c qemu-10.0.6+ds/target/sparc/translate.c --- qemu-10.0.3+ds/target/sparc/translate.c 2025-07-23 21:05:28.000000000 +0000 +++ qemu-10.0.6+ds/target/sparc/translate.c 2025-10-20 18:13:46.000000000 +0000 @@ -2488,7 +2488,7 @@ #define TRANS(NAME, AVAIL, FUNC, ...) \ static bool trans_##NAME(DisasContext *dc, arg_##NAME *a) \ - { return avail_##AVAIL(dc) && FUNC(dc, __VA_ARGS__); } + { return avail_##AVAIL(dc) && FUNC(dc, ## __VA_ARGS__); } #define avail_ALL(C) true #ifdef TARGET_SPARC64 @@ -2527,6 +2527,32 @@ # define avail_VIS4(C) false #endif +/* + * We decoded bit 13 as imm, and bits [12:0] as rs2_or_imm. + * For v9, if !imm, then the unused bits [12:5] must be zero. + * For v7 and v8, the unused bits are ignored; clear them here. + */ +static bool check_rs2(DisasContext *dc, int *rs2) +{ + if (unlikely(*rs2 & ~0x1f)) { + if (avail_64(dc)) { + return false; + } + *rs2 &= 0x1f; + } + return true; +} + +static bool check_r_r_ri(DisasContext *dc, arg_r_r_ri *a) +{ + return a->imm || check_rs2(dc, &a->rs2_or_imm); +} + +static bool check_r_r_ri_cc(DisasContext *dc, arg_r_r_ri_cc *a) +{ + return a->imm || check_rs2(dc, &a->rs2_or_imm); +} + /* Default case for non jump instructions. */ static bool advance_pc(DisasContext *dc) { @@ -2824,12 +2850,15 @@ return do_tcc(dc, a->cond, a->cc, a->rs1, true, a->i); } -static bool trans_STBAR(DisasContext *dc, arg_STBAR *a) +static bool do_stbar(DisasContext *dc) { tcg_gen_mb(TCG_MO_ST_ST | TCG_BAR_SC); return advance_pc(dc); } +TRANS(STBAR_v8, 32, do_stbar) +TRANS(STBAR_v9, 64, do_stbar) + static bool trans_MEMBAR(DisasContext *dc, arg_MEMBAR *a) { if (avail_32(dc)) { @@ -2861,18 +2890,8 @@ return cpu_y; } -static bool trans_RDY(DisasContext *dc, arg_RDY *a) -{ - /* - * TODO: Need a feature bit for sparcv8. In the meantime, treat all - * 32-bit cpus like sparcv7, which ignores the rs1 field. - * This matches after all other ASR, so Leon3 Asr17 is handled first. - */ - if (avail_64(dc) && a->rs1 != 0) { - return false; - } - return do_rd_special(dc, true, a->rd, do_rdy); -} +TRANS(RDY_v7, 32, do_rd_special, true, a->rd, do_rdy) +TRANS(RDY_v9, 64, do_rd_special, true, a->rd, do_rdy) static TCGv do_rd_leon3_config(DisasContext *dc, TCGv dst) { @@ -3257,8 +3276,7 @@ { TCGv src; - /* For simplicity, we under-decoded the rs2 form. */ - if (!a->imm && (a->rs2_or_imm & ~0x1f)) { + if (!check_r_r_ri(dc, a)) { return false; } if (!priv) { @@ -3701,8 +3719,7 @@ { TCGv dst, src1; - /* For simplicity, we under-decoded the rs2 form. */ - if (!a->imm && a->rs2_or_imm & ~0x1f) { + if (!check_r_r_ri_cc(dc, a)) { return false; } @@ -3786,11 +3803,11 @@ { /* OR with %g0 is the canonical alias for MOV. */ if (!a->cc && a->rs1 == 0) { + if (!check_r_r_ri_cc(dc, a)) { + return false; + } if (a->imm || a->rs2_or_imm == 0) { gen_store_gpr(dc, a->rd, tcg_constant_tl(a->rs2_or_imm)); - } else if (a->rs2_or_imm & ~0x1f) { - /* For simplicity, we under-decoded the rs2 form. */ - return false; } else { gen_store_gpr(dc, a->rd, cpu_regs[a->rs2_or_imm]); } @@ -3807,8 +3824,7 @@ if (!avail_DIV(dc)) { return false; } - /* For simplicity, we under-decoded the rs2 form. */ - if (!a->imm && a->rs2_or_imm & ~0x1f) { + if (!check_r_r_ri(dc, a)) { return false; } @@ -3859,8 +3875,7 @@ if (!avail_64(dc)) { return false; } - /* For simplicity, we under-decoded the rs2 form. */ - if (!a->imm && a->rs2_or_imm & ~0x1f) { + if (!check_r_r_ri(dc, a)) { return false; } @@ -3897,8 +3912,7 @@ if (!avail_64(dc)) { return false; } - /* For simplicity, we under-decoded the rs2 form. */ - if (!a->imm && a->rs2_or_imm & ~0x1f) { + if (!check_r_r_ri(dc, a)) { return false; } @@ -4194,8 +4208,7 @@ static TCGv gen_rs2_or_imm(DisasContext *dc, bool imm, int rs2_or_imm) { - /* For simplicity, we under-decoded the rs2 form. */ - if (!imm && rs2_or_imm & ~0x1f) { + if (!imm && !check_rs2(dc, &rs2_or_imm)) { return NULL; } if (imm || rs2_or_imm == 0) { @@ -4258,8 +4271,7 @@ { TCGv src1, sum; - /* For simplicity, we under-decoded the rs2 form. */ - if (!a->imm && a->rs2_or_imm & ~0x1f) { + if (!check_r_r_ri(dc, a)) { return false; } @@ -4377,8 +4389,7 @@ { TCGv addr, tmp = NULL; - /* For simplicity, we under-decoded the rs2 form. */ - if (!imm && rs2_or_imm & ~0x1f) { + if (!imm && !check_rs2(dc, &rs2_or_imm)) { return NULL; } diff -Nru qemu-10.0.3+ds/tcg/optimize.c qemu-10.0.6+ds/tcg/optimize.c --- qemu-10.0.3+ds/tcg/optimize.c 2025-07-23 21:05:28.000000000 +0000 +++ qemu-10.0.6+ds/tcg/optimize.c 2025-10-20 18:13:46.000000000 +0000 @@ -1410,9 +1410,10 @@ return fold_and(ctx, op); } if (fv == -1 && TCG_TARGET_HAS_orc_vec) { + TCGArg ta = op->args[2]; op->opc = INDEX_op_orc_vec; op->args[2] = op->args[1]; - op->args[1] = op->args[3]; + op->args[1] = ta; return fold_orc(ctx, op); } } diff -Nru qemu-10.0.3+ds/tests/Makefile.include qemu-10.0.6+ds/tests/Makefile.include --- qemu-10.0.3+ds/tests/Makefile.include 2025-07-23 21:05:28.000000000 +0000 +++ qemu-10.0.6+ds/tests/Makefile.include 2025-10-20 18:13:46.000000000 +0000 @@ -164,6 +164,9 @@ @$(NINJA) precache-functional @QEMU_TEST_NO_DOWNLOAD=1 $(MAKE) SPEED=thorough check-func check-func-quick +.PHONY: check-func check-func-quick +check-func check-func-quick: + # Consolidated targets .PHONY: check check-clean get-vm-images diff -Nru qemu-10.0.3+ds/tests/docker/dockerfiles/python.docker qemu-10.0.6+ds/tests/docker/dockerfiles/python.docker --- qemu-10.0.3+ds/tests/docker/dockerfiles/python.docker 2025-07-23 21:05:28.000000000 +0000 +++ qemu-10.0.6+ds/tests/docker/dockerfiles/python.docker 2025-10-20 18:13:46.000000000 +0000 @@ -1,6 +1,6 @@ # Python library testing environment -FROM fedora:latest +FROM fedora:40 MAINTAINER John Snow # Please keep this list sorted alphabetically diff -Nru qemu-10.0.3+ds/tests/functional/test_aarch64_sbsaref_freebsd.py qemu-10.0.6+ds/tests/functional/test_aarch64_sbsaref_freebsd.py --- qemu-10.0.3+ds/tests/functional/test_aarch64_sbsaref_freebsd.py 2025-07-23 21:05:28.000000000 +0000 +++ qemu-10.0.6+ds/tests/functional/test_aarch64_sbsaref_freebsd.py 2025-10-20 18:13:46.000000000 +0000 @@ -20,9 +20,9 @@ class Aarch64SbsarefFreeBSD(QemuSystemTest): ASSET_FREEBSD_ISO = Asset( - ('https://download.freebsd.org/releases/arm64/aarch64/ISO-IMAGES/' - '14.1/FreeBSD-14.1-RELEASE-arm64-aarch64-bootonly.iso'), - '44cdbae275ef1bb6dab1d5fbb59473d4f741e1c8ea8a80fd9e906b531d6ad461') + ('http://ftp-archive.freebsd.org/pub/FreeBSD-Archive/old-releases/arm64' + '/aarch64/ISO-IMAGES/14.1/FreeBSD-14.1-RELEASE-arm64-aarch64-bootonly.iso.xz'), + '7313a4495ffd71ab77b49b1e83f571521c32756e1d75bf48bd890e0ab0f75827') # This tests the whole boot chain from EFI to Userspace # We only boot a whole OS for the current top level CPU and GIC @@ -30,7 +30,7 @@ def boot_freebsd14(self, cpu=None): fetch_firmware(self) - img_path = self.ASSET_FREEBSD_ISO.fetch() + img_path = self.uncompress(self.ASSET_FREEBSD_ISO) self.vm.set_console() self.vm.add_args( diff -Nru qemu-10.0.3+ds/tests/functional/test_ppc_bamboo.py qemu-10.0.6+ds/tests/functional/test_ppc_bamboo.py --- qemu-10.0.3+ds/tests/functional/test_ppc_bamboo.py 2025-07-23 21:05:28.000000000 +0000 +++ qemu-10.0.6+ds/tests/functional/test_ppc_bamboo.py 2025-10-20 18:13:46.000000000 +0000 @@ -16,28 +16,32 @@ timeout = 90 - ASSET_IMAGE = Asset( - ('http://landley.net/aboriginal/downloads/binaries/' - 'system-image-powerpc-440fp.tar.gz'), - 'c12b58f841c775a0e6df4832a55afe6b74814d1565d08ddeafc1fb949a075c5e') + ASSET_KERNEL = Asset( + ('https://github.com/legoater/qemu-ppc-boot/raw/refs/heads/main/' + 'buildroot/qemu_ppc_bamboo-2023.11-8-gdcd9f0f6eb-20240105/vmlinux'), + 'a2e12eb45b73491ac62fc0bbeb68dead0dc5c0f22cf83146558389209b420ad1') + ASSET_INITRD = Asset( + ('https://github.com/legoater/qemu-ppc-boot/raw/refs/heads/main/' + 'buildroot/qemu_ppc_bamboo-2023.11-8-gdcd9f0f6eb-20240105/rootfs.cpio'), + 'd2a36bdb8763b389765dc8c29d4904cec2bd001c587f92e85ab9eb10d5ddda54') def test_ppc_bamboo(self): self.set_machine('bamboo') self.require_accelerator("tcg") self.require_netdev('user') - self.archive_extract(self.ASSET_IMAGE) + + kernel = self.ASSET_KERNEL.fetch() + initrd = self.ASSET_INITRD.fetch() + self.vm.set_console() - self.vm.add_args('-kernel', - self.scratch_file('system-image-powerpc-440fp', - 'linux'), - '-initrd', - self.scratch_file('system-image-powerpc-440fp', - 'rootfs.cpio.gz'), - '-nic', 'user,model=rtl8139,restrict=on') + self.vm.add_args('-kernel', kernel, + '-initrd', initrd, + '-nic', 'user,model=virtio-net-pci,restrict=on') self.vm.launch() - wait_for_console_pattern(self, 'Type exit when done') - exec_command_and_wait_for_pattern(self, 'ping 10.0.2.2', - '10.0.2.2 is alive!') + wait_for_console_pattern(self, 'buildroot login:') + exec_command_and_wait_for_pattern(self, 'root', '#') + exec_command_and_wait_for_pattern(self, 'ping -c1 10.0.2.2', + '1 packets transmitted, 1 packets received, 0% packet loss') exec_command_and_wait_for_pattern(self, 'halt', 'System Halted') if __name__ == '__main__': diff -Nru qemu-10.0.3+ds/tests/qemu-iotests/039.out qemu-10.0.6+ds/tests/qemu-iotests/039.out --- qemu-10.0.3+ds/tests/qemu-iotests/039.out 2025-07-23 21:05:28.000000000 +0000 +++ qemu-10.0.6+ds/tests/qemu-iotests/039.out 2025-10-20 18:13:46.000000000 +0000 @@ -11,7 +11,7 @@ Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728 wrote 512/512 bytes at offset 0 512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) -./common.rc: Killed ( VALGRIND_QEMU="${VALGRIND_QEMU_IO}" _qemu_proc_exec "${VALGRIND_LOGFILE}" "$QEMU_IO_PROG" $QEMU_IO_ARGS "$@" ) +./common.rc: Killed ( VALGRIND_QEMU="${VALGRIND_QEMU_IO}" _qemu_proc_exec "${VALGRIND_LOGFILE}" "$QEMU_IO_PROG" $QEMU_IO_ARGS "$@" ) incompatible_features [0] ERROR cluster 5 refcount=0 reference=1 ERROR OFLAG_COPIED data cluster: l2_entry=8000000000050000 refcount=0 @@ -46,7 +46,7 @@ Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728 wrote 512/512 bytes at offset 0 512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) -./common.rc: Killed ( VALGRIND_QEMU="${VALGRIND_QEMU_IO}" _qemu_proc_exec "${VALGRIND_LOGFILE}" "$QEMU_IO_PROG" $QEMU_IO_ARGS "$@" ) +./common.rc: Killed ( VALGRIND_QEMU="${VALGRIND_QEMU_IO}" _qemu_proc_exec "${VALGRIND_LOGFILE}" "$QEMU_IO_PROG" $QEMU_IO_ARGS "$@" ) incompatible_features [0] ERROR cluster 5 refcount=0 reference=1 Rebuilding refcount structure @@ -60,7 +60,7 @@ Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728 wrote 512/512 bytes at offset 0 512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) -./common.rc: Killed ( VALGRIND_QEMU="${VALGRIND_QEMU_IO}" _qemu_proc_exec "${VALGRIND_LOGFILE}" "$QEMU_IO_PROG" $QEMU_IO_ARGS "$@" ) +./common.rc: Killed ( VALGRIND_QEMU="${VALGRIND_QEMU_IO}" _qemu_proc_exec "${VALGRIND_LOGFILE}" "$QEMU_IO_PROG" $QEMU_IO_ARGS "$@" ) incompatible_features [] No errors were found on the image. @@ -79,7 +79,7 @@ Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728 wrote 512/512 bytes at offset 0 512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) -./common.rc: Killed ( VALGRIND_QEMU="${VALGRIND_QEMU_IO}" _qemu_proc_exec "${VALGRIND_LOGFILE}" "$QEMU_IO_PROG" $QEMU_IO_ARGS "$@" ) +./common.rc: Killed ( VALGRIND_QEMU="${VALGRIND_QEMU_IO}" _qemu_proc_exec "${VALGRIND_LOGFILE}" "$QEMU_IO_PROG" $QEMU_IO_ARGS "$@" ) incompatible_features [0] ERROR cluster 5 refcount=0 reference=1 ERROR OFLAG_COPIED data cluster: l2_entry=8000000000050000 refcount=0 @@ -89,7 +89,7 @@ Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728 wrote 512/512 bytes at offset 0 512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) -./common.rc: Killed ( VALGRIND_QEMU="${VALGRIND_QEMU_IO}" _qemu_proc_exec "${VALGRIND_LOGFILE}" "$QEMU_IO_PROG" $QEMU_IO_ARGS "$@" ) +./common.rc: Killed ( VALGRIND_QEMU="${VALGRIND_QEMU_IO}" _qemu_proc_exec "${VALGRIND_LOGFILE}" "$QEMU_IO_PROG" $QEMU_IO_ARGS "$@" ) incompatible_features [] No errors were found on the image. *** done diff -Nru qemu-10.0.3+ds/tests/qemu-iotests/061.out qemu-10.0.6+ds/tests/qemu-iotests/061.out --- qemu-10.0.3+ds/tests/qemu-iotests/061.out 2025-07-23 21:05:28.000000000 +0000 +++ qemu-10.0.6+ds/tests/qemu-iotests/061.out 2025-10-20 18:13:46.000000000 +0000 @@ -118,7 +118,7 @@ Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 wrote 131072/131072 bytes at offset 0 128 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) -./common.rc: Killed ( VALGRIND_QEMU="${VALGRIND_QEMU_IO}" _qemu_proc_exec "${VALGRIND_LOGFILE}" "$QEMU_IO_PROG" $QEMU_IO_ARGS "$@" ) +./common.rc: Killed ( VALGRIND_QEMU="${VALGRIND_QEMU_IO}" _qemu_proc_exec "${VALGRIND_LOGFILE}" "$QEMU_IO_PROG" $QEMU_IO_ARGS "$@" ) magic 0x514649fb version 3 backing_file_offset 0x0 @@ -304,7 +304,7 @@ Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 wrote 131072/131072 bytes at offset 0 128 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) -./common.rc: Killed ( VALGRIND_QEMU="${VALGRIND_QEMU_IO}" _qemu_proc_exec "${VALGRIND_LOGFILE}" "$QEMU_IO_PROG" $QEMU_IO_ARGS "$@" ) +./common.rc: Killed ( VALGRIND_QEMU="${VALGRIND_QEMU_IO}" _qemu_proc_exec "${VALGRIND_LOGFILE}" "$QEMU_IO_PROG" $QEMU_IO_ARGS "$@" ) magic 0x514649fb version 3 backing_file_offset 0x0 diff -Nru qemu-10.0.3+ds/tests/qemu-iotests/137.out qemu-10.0.6+ds/tests/qemu-iotests/137.out --- qemu-10.0.3+ds/tests/qemu-iotests/137.out 2025-07-23 21:05:28.000000000 +0000 +++ qemu-10.0.6+ds/tests/qemu-iotests/137.out 2025-10-20 18:13:46.000000000 +0000 @@ -35,7 +35,7 @@ qemu-io: Unsupported value 'blubb' for qcow2 option 'overlap-check'. Allowed are any of the following: none, constant, cached, all wrote 512/512 bytes at offset 0 512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) -./common.rc: Killed ( VALGRIND_QEMU="${VALGRIND_QEMU_IO}" _qemu_proc_exec "${VALGRIND_LOGFILE}" "$QEMU_IO_PROG" $QEMU_IO_ARGS "$@" ) +./common.rc: Killed ( VALGRIND_QEMU="${VALGRIND_QEMU_IO}" _qemu_proc_exec "${VALGRIND_LOGFILE}" "$QEMU_IO_PROG" $QEMU_IO_ARGS "$@" ) OK: Dirty bit not set Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 qemu-io: Parameter 'lazy-refcounts' expects 'on' or 'off' diff -Nru qemu-10.0.3+ds/tests/qemu-iotests/147 qemu-10.0.6+ds/tests/qemu-iotests/147 --- qemu-10.0.3+ds/tests/qemu-iotests/147 2025-07-23 21:05:28.000000000 +0000 +++ qemu-10.0.6+ds/tests/qemu-iotests/147 2025-10-20 18:13:46.000000000 +0000 @@ -277,6 +277,7 @@ } } self.client_test(filename, flatten_sock_addr(address), 'nbd-export') + sockfd.close() self._server_down() diff -Nru qemu-10.0.3+ds/tests/qemu-iotests/151 qemu-10.0.6+ds/tests/qemu-iotests/151 --- qemu-10.0.3+ds/tests/qemu-iotests/151 2025-07-23 21:05:28.000000000 +0000 +++ qemu-10.0.6+ds/tests/qemu-iotests/151 2025-10-20 18:13:46.000000000 +0000 @@ -263,6 +263,11 @@ break except subprocess.TimeoutExpired: self.vm.qtest(f'clock_step {1 * 1000 * 1000 * 1000}') + try: + p.kill() + p.stdout.close() + except: + pass except IndexError: pass diff -Nru qemu-10.0.3+ds/tests/qemu-iotests/check qemu-10.0.6+ds/tests/qemu-iotests/check --- qemu-10.0.3+ds/tests/qemu-iotests/check 2025-07-23 21:05:29.000000000 +0000 +++ qemu-10.0.6+ds/tests/qemu-iotests/check 2025-10-20 18:13:46.000000000 +0000 @@ -21,6 +21,7 @@ import argparse import shutil from pathlib import Path +import warnings from findtests import TestFinder from testenv import TestEnv @@ -137,6 +138,9 @@ if __name__ == '__main__': + warnings.simplefilter("default") + os.environ["PYTHONWARNINGS"] = "default" + args = make_argparser().parse_args() env = TestEnv(source_dir=args.source_dir, diff -Nru qemu-10.0.3+ds/tests/qemu-iotests/common.filter qemu-10.0.6+ds/tests/qemu-iotests/common.filter --- qemu-10.0.3+ds/tests/qemu-iotests/common.filter 2025-07-23 21:05:29.000000000 +0000 +++ qemu-10.0.6+ds/tests/qemu-iotests/common.filter 2025-10-20 18:13:46.000000000 +0000 @@ -74,7 +74,7 @@ { _filter_win32 | \ gsed -e "s/[0-9]* ops\; [0-9/:. sec]* ([0-9/.inf]* [EPTGMKiBbytes]*\/sec and [0-9/.inf]* ops\/sec)/X ops\; XX:XX:XX.X (XXX YYY\/sec and XXX ops\/sec)/" \ - -e "s/: line [0-9][0-9]*: *[0-9][0-9]*\( Aborted\| Killed\)/:\1/" \ + -e "s/: line [0-9][0-9]*: *[0-9][0-9]*\( Aborted\| Killed\) \{2,\}/:\1 /" \ -e "s/qemu-io> //g" } diff -Nru qemu-10.0.3+ds/tests/qemu-iotests/testenv.py qemu-10.0.6+ds/tests/qemu-iotests/testenv.py --- qemu-10.0.3+ds/tests/qemu-iotests/testenv.py 2025-07-23 21:05:29.000000000 +0000 +++ qemu-10.0.6+ds/tests/qemu-iotests/testenv.py 2025-10-20 18:13:46.000000000 +0000 @@ -22,15 +22,12 @@ from pathlib import Path import shutil import collections +import contextlib import random import subprocess import glob from typing import List, Dict, Any, Optional -if sys.version_info >= (3, 9): - from contextlib import AbstractContextManager as ContextManager -else: - from typing import ContextManager DEF_GDB_OPTIONS = 'localhost:12345' @@ -58,7 +55,7 @@ return default_machine -class TestEnv(ContextManager['TestEnv']): +class TestEnv(contextlib.AbstractContextManager['TestEnv']): """ Manage system environment for running tests diff -Nru qemu-10.0.3+ds/tests/qemu-iotests/testrunner.py qemu-10.0.6+ds/tests/qemu-iotests/testrunner.py --- qemu-10.0.3+ds/tests/qemu-iotests/testrunner.py 2025-07-23 21:05:29.000000000 +0000 +++ qemu-10.0.6+ds/tests/qemu-iotests/testrunner.py 2025-10-20 18:13:46.000000000 +0000 @@ -30,11 +30,6 @@ from typing import List, Optional, Any, Sequence, Dict from testenv import TestEnv -if sys.version_info >= (3, 9): - from contextlib import AbstractContextManager as ContextManager -else: - from typing import ContextManager - def silent_unlink(path: Path) -> None: try: @@ -57,7 +52,7 @@ return res -class LastElapsedTime(ContextManager['LastElapsedTime']): +class LastElapsedTime(contextlib.AbstractContextManager['LastElapsedTime']): """ Cache for elapsed time for tests, to show it during new test run It is safe to use get() at any time. To use update(), you must either @@ -112,7 +107,7 @@ self.interrupted = interrupted -class TestRunner(ContextManager['TestRunner']): +class TestRunner(contextlib.AbstractContextManager['TestRunner']): shared_self = None @staticmethod diff -Nru qemu-10.0.3+ds/tests/qtest/qos-test.c qemu-10.0.6+ds/tests/qtest/qos-test.c --- qemu-10.0.3+ds/tests/qtest/qos-test.c 2025-07-23 21:05:29.000000000 +0000 +++ qemu-10.0.6+ds/tests/qtest/qos-test.c 2025-10-20 18:13:46.000000000 +0000 @@ -328,11 +328,6 @@ int main(int argc, char **argv, char** envp) { g_test_init(&argc, &argv, NULL); - - if (g_test_subprocess()) { - qos_printf("qos_test running single test in subprocess\n"); - } - if (g_test_verbose()) { qos_printf("ENVIRONMENT VARIABLES: {\n"); for (char **env = envp; *env != 0; env++) { diff -Nru qemu-10.0.3+ds/tests/qtest/vhost-user-test.c qemu-10.0.6+ds/tests/qtest/vhost-user-test.c --- qemu-10.0.3+ds/tests/qtest/vhost-user-test.c 2025-07-23 21:05:29.000000000 +0000 +++ qemu-10.0.6+ds/tests/qtest/vhost-user-test.c 2025-10-20 18:13:46.000000000 +0000 @@ -26,7 +26,6 @@ #include "libqos/virtio-pci.h" #include "libqos/malloc-pc.h" -#include "libqos/qgraph_internal.h" #include "hw/virtio/virtio-net.h" #include "standard-headers/linux/vhost_types.h" @@ -345,7 +344,7 @@ } if (size != VHOST_USER_HDR_SIZE) { - qos_printf("%s: Wrong message size received %d\n", __func__, size); + g_test_message("Wrong message size received %d", size); return; } @@ -356,8 +355,8 @@ p += VHOST_USER_HDR_SIZE; size = qemu_chr_fe_read_all(chr, p, msg.size); if (size != msg.size) { - qos_printf("%s: Wrong message size received %d != %d\n", - __func__, size, msg.size); + g_test_message("Wrong message size received %d != %d", + size, msg.size); goto out; } } @@ -393,7 +392,7 @@ * We don't need to do anything here, the remote is just * letting us know it is in charge. Just log it. */ - qos_printf("set_owner: start of session\n"); + g_test_message("set_owner: start of session\n"); break; case VHOST_USER_GET_PROTOCOL_FEATURES: @@ -419,7 +418,7 @@ * the remote end to send this. There is no handshake reply so * just log the details for debugging. */ - qos_printf("set_protocol_features: 0x%"PRIx64 "\n", msg.payload.u64); + g_test_message("set_protocol_features: 0x%"PRIx64 "\n", msg.payload.u64); break; /* @@ -427,11 +426,11 @@ * address of the vrings but we can simply report them. */ case VHOST_USER_SET_VRING_NUM: - qos_printf("set_vring_num: %d/%d\n", + g_test_message("set_vring_num: %d/%d\n", msg.payload.state.index, msg.payload.state.num); break; case VHOST_USER_SET_VRING_ADDR: - qos_printf("set_vring_addr: 0x%"PRIx64"/0x%"PRIx64"/0x%"PRIx64"\n", + g_test_message("set_vring_addr: 0x%"PRIx64"/0x%"PRIx64"/0x%"PRIx64"\n", msg.payload.addr.avail_user_addr, msg.payload.addr.desc_user_addr, msg.payload.addr.used_user_addr); @@ -464,7 +463,7 @@ case VHOST_USER_SET_VRING_CALL: /* consume the fd */ if (!qemu_chr_fe_get_msgfds(chr, &fd, 1) && fd < 0) { - qos_printf("call fd: %d, do not set non-blocking\n", fd); + g_test_message("call fd: %d, do not set non-blocking\n", fd); break; } /* @@ -510,12 +509,12 @@ * fully functioning vhost-user we would enable/disable the * vring monitoring. */ - qos_printf("set_vring(%d)=%s\n", msg.payload.state.index, + g_test_message("set_vring(%d)=%s\n", msg.payload.state.index, msg.payload.state.num ? "enabled" : "disabled"); break; default: - qos_printf("vhost-user: un-handled message: %d\n", msg.request); + g_test_message("vhost-user: un-handled message: %d\n", msg.request); break; } @@ -539,7 +538,7 @@ } if (access(path, R_OK | W_OK | X_OK)) { - qos_printf("access on path (%s): %s", path, strerror(errno)); + g_test_message("access on path (%s): %s", path, strerror(errno)); g_test_fail(); return NULL; } @@ -549,13 +548,13 @@ } while (ret != 0 && errno == EINTR); if (ret != 0) { - qos_printf("statfs on path (%s): %s", path, strerror(errno)); + g_test_message("statfs on path (%s): %s", path, strerror(errno)); g_test_fail(); return NULL; } if (fs.f_type != HUGETLBFS_MAGIC) { - qos_printf("Warning: path not on HugeTLBFS: %s", path); + g_test_message("Warning: path not on HugeTLBFS: %s", path); g_test_fail(); return NULL; } diff -Nru qemu-10.0.3+ds/tests/tcg/multiarch/Makefile.target qemu-10.0.6+ds/tests/tcg/multiarch/Makefile.target --- qemu-10.0.3+ds/tests/tcg/multiarch/Makefile.target 2025-07-23 21:05:29.000000000 +0000 +++ qemu-10.0.6+ds/tests/tcg/multiarch/Makefile.target 2025-10-20 18:13:46.000000000 +0000 @@ -45,6 +45,8 @@ sigreturn-sigmask: CFLAGS+=-pthread sigreturn-sigmask: LDFLAGS+=-pthread +tb-link: LDFLAGS+=-lpthread + # GCC versions 12/13/14/15 at least incorrectly complain about # "'SHA1Transform' reading 64 bytes from a region of size 0"; see the gcc bug # https://gcc.gnu.org/bugzilla/show_bug.cgi?id=106709 diff -Nru qemu-10.0.3+ds/tests/tcg/multiarch/tb-link.c qemu-10.0.6+ds/tests/tcg/multiarch/tb-link.c --- qemu-10.0.3+ds/tests/tcg/multiarch/tb-link.c 1970-01-01 00:00:00.000000000 +0000 +++ qemu-10.0.6+ds/tests/tcg/multiarch/tb-link.c 2025-10-20 18:13:46.000000000 +0000 @@ -0,0 +1,67 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ +/* + * Verify that a single TB spin-loop is properly invalidated, + * releasing the thread from the spin-loop. + */ + +#include +#include +#include +#include +#include +#include +#include + + +#ifdef __x86_64__ +#define READY 0x000047c6 /* movb $0,0(%rdi) */ +#define LOOP 0xfceb9090 /* 1: nop*2; jmp 1b */ +#define RETURN 0x909090c3 /* ret; nop*3 */ +#define NOP 0x90909090 /* nop*4 */ +#elif defined(__aarch64__) +#define READY 0x3900001f /* strb wzr,[x0] */ +#define LOOP 0x14000000 /* b . */ +#define RETURN 0xd65f03c0 /* ret */ +#define NOP 0xd503201f /* nop */ +#elif defined(__riscv) +#define READY 0x00050023 /* sb zero, (a0) */ +#define LOOP 0x0000006f /* jal zero, #0 */ +#define RETURN 0x00008067 /* jalr zero, ra, 0 */ +#define NOP 0x00000013 /* nop */ +#endif + + +int main() +{ +#ifdef READY + int tmp; + pthread_t thread_id; + bool hold = true; + uint32_t *buf; + + buf = mmap(NULL, 3 * sizeof(uint32_t), + PROT_READ | PROT_WRITE | PROT_EXEC, + MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); + assert(buf != MAP_FAILED); + + buf[0] = READY; + buf[1] = LOOP; + buf[2] = RETURN; + + alarm(2); + + tmp = pthread_create(&thread_id, NULL, (void *(*)(void *))buf, &hold); + assert(tmp == 0); + + while (hold) { + sched_yield(); + } + + buf[1] = NOP; + __builtin___clear_cache(&buf[1], &buf[2]); + + tmp = pthread_join(thread_id, NULL); + assert(tmp == 0); +#endif + return 0; +} diff -Nru qemu-10.0.3+ds/ui/curses.c qemu-10.0.6+ds/ui/curses.c --- qemu-10.0.3+ds/ui/curses.c 2025-07-23 21:05:29.000000000 +0000 +++ qemu-10.0.6+ds/ui/curses.c 2025-10-20 18:13:46.000000000 +0000 @@ -265,7 +265,8 @@ static void curses_refresh(DisplayChangeListener *dcl) { - int chr, keysym, keycode, keycode_alt; + wint_t chr = 0; + int keysym, keycode, keycode_alt; enum maybe_keycode maybe_keycode = CURSES_KEYCODE; curses_winch_check(); @@ -284,8 +285,9 @@ /* while there are any pending key strokes to process */ chr = console_getch(&maybe_keycode); - if (chr == -1) + if (chr == WEOF) { break; + } #ifdef KEY_RESIZE /* this shouldn't occur when we use a custom SIGWINCH handler */ @@ -304,9 +306,9 @@ /* alt or esc key */ if (keycode == 1) { enum maybe_keycode next_maybe_keycode = CURSES_KEYCODE; - int nextchr = console_getch(&next_maybe_keycode); + wint_t nextchr = console_getch(&next_maybe_keycode); - if (nextchr != -1) { + if (nextchr != WEOF) { chr = nextchr; maybe_keycode = next_maybe_keycode; keycode_alt = ALT; diff -Nru qemu-10.0.3+ds/ui/gtk.c qemu-10.0.6+ds/ui/gtk.c --- qemu-10.0.3+ds/ui/gtk.c 2025-07-23 21:05:29.000000000 +0000 +++ qemu-10.0.6+ds/ui/gtk.c 2025-10-20 18:13:46.000000000 +0000 @@ -769,11 +769,24 @@ } static void gd_resize_event(GtkGLArea *area, - gint width, gint height, gpointer *opaque) + gint width, gint height, gpointer opaque) { - VirtualConsole *vc = (void *)opaque; + VirtualConsole *vc = opaque; + double pw = width, ph = height; + double sx = vc->gfx.scale_x, sy = vc->gfx.scale_y; + GdkWindow *window = gtk_widget_get_window(GTK_WIDGET(area)); + const int gs = gdk_window_get_scale_factor(window); + + if (!vc->s->free_scale && !vc->s->full_screen) { + pw /= sx; + ph /= sy; + } - gd_set_ui_size(vc, width, height); + /** + * width and height here are in pixel coordinate, so we must divide it + * by global window scale (gs) + */ + gd_set_ui_size(vc, pw / gs, ph / gs); } #endif @@ -1836,8 +1849,16 @@ GdkEventConfigure *cfg, gpointer opaque) { VirtualConsole *vc = opaque; + const double sx = vc->gfx.scale_x, sy = vc->gfx.scale_y; + double width = cfg->width, height = cfg->height; + + if (!vc->s->free_scale && !vc->s->full_screen) { + width /= sx; + height /= sy; + } + + gd_set_ui_size(vc, width, height); - gd_set_ui_size(vc, cfg->width, cfg->height); return FALSE; } diff -Nru qemu-10.0.3+ds/ui/icons/qemu.svg qemu-10.0.6+ds/ui/icons/qemu.svg --- qemu-10.0.3+ds/ui/icons/qemu.svg 2025-07-23 21:05:29.000000000 +0000 +++ qemu-10.0.6+ds/ui/icons/qemu.svg 2025-10-20 18:13:46.000000000 +0000 @@ -918,7 +918,26 @@ image/svg+xml - + Kew the Angry Emu + + + BenoĆ®t Canet + + + + + CC BY 3.0 + + + + + QEMU Community + + + 2012-02-15 + + https://lists.gnu.org/archive/html/qemu-devel/2012-02/msg02865.html diff -Nru qemu-10.0.3+ds/ui/input-barrier.c qemu-10.0.6+ds/ui/input-barrier.c --- qemu-10.0.3+ds/ui/input-barrier.c 2025-07-23 21:05:29.000000000 +0000 +++ qemu-10.0.6+ds/ui/input-barrier.c 2025-10-20 18:13:46.000000000 +0000 @@ -490,7 +490,6 @@ static void input_barrier_complete(UserCreatable *uc, Error **errp) { InputBarrier *ib = INPUT_BARRIER(uc); - Error *local_err = NULL; if (!ib->name) { error_setg(errp, QERR_MISSING_PARAMETER, "name"); @@ -506,9 +505,7 @@ ib->sioc = qio_channel_socket_new(); qio_channel_set_name(QIO_CHANNEL(ib->sioc), "barrier-client"); - qio_channel_socket_connect_sync(ib->sioc, &ib->saddr, &local_err); - if (local_err) { - error_propagate(errp, local_err); + if (qio_channel_socket_connect_sync(ib->sioc, &ib->saddr, errp) < 0) { return; } diff -Nru qemu-10.0.3+ds/ui/spice-core.c qemu-10.0.6+ds/ui/spice-core.c --- qemu-10.0.3+ds/ui/spice-core.c 2025-07-23 21:05:29.000000000 +0000 +++ qemu-10.0.6+ds/ui/spice-core.c 2025-10-20 18:13:46.000000000 +0000 @@ -50,8 +50,6 @@ static int spice_display_is_running; static int spice_have_target_host; -static QemuThread me; - struct SpiceTimer { QEMUTimer *timer; }; @@ -220,7 +218,7 @@ * thread and grab the BQL if so before calling qemu * functions. */ - bool need_lock = !qemu_thread_is_self(&me); + bool need_lock = !bql_locked(); if (need_lock) { bql_lock(); } @@ -667,8 +665,6 @@ spice_wan_compression_t wan_compr; bool seamless_migration; - qemu_thread_get_self(&me); - if (!opts) { return; } diff -Nru qemu-10.0.3+ds/ui/vnc.c qemu-10.0.6+ds/ui/vnc.c --- qemu-10.0.3+ds/ui/vnc.c 2025-07-23 21:05:29.000000000 +0000 +++ qemu-10.0.6+ds/ui/vnc.c 2025-10-20 18:13:46.000000000 +0000 @@ -4265,8 +4265,9 @@ } } -static void vnc_auto_assign_id(QemuOptsList *olist, QemuOpts *opts) +static char *vnc_auto_assign_id(QemuOpts *opts) { + QemuOptsList *olist = qemu_find_opts("vnc"); int i = 2; char *id; @@ -4276,23 +4277,18 @@ id = g_strdup_printf("vnc%d", i++); } qemu_opts_set_id(opts, id); + + return id; } void vnc_parse(const char *str) { QemuOptsList *olist = qemu_find_opts("vnc"); QemuOpts *opts = qemu_opts_parse_noisily(olist, str, !is_help_option(str)); - const char *id; if (!opts) { exit(1); } - - id = qemu_opts_id(opts); - if (!id) { - /* auto-assign id if not present */ - vnc_auto_assign_id(olist, opts); - } } int vnc_init_func(void *opaque, QemuOpts *opts, Error **errp) @@ -4300,7 +4296,11 @@ Error *local_err = NULL; char *id = (char *)qemu_opts_id(opts); - assert(id); + if (!id) { + /* auto-assign id if not present */ + id = vnc_auto_assign_id(opts); + } + vnc_display_init(id, &local_err); if (local_err) { error_propagate(errp, local_err); diff -Nru qemu-10.0.3+ds/util/async.c qemu-10.0.6+ds/util/async.c --- qemu-10.0.3+ds/util/async.c 2025-07-23 21:05:29.000000000 +0000 +++ qemu-10.0.6+ds/util/async.c 2025-10-20 18:13:46.000000000 +0000 @@ -256,8 +256,9 @@ QEMUBH *bh; QSLIST_FOREACH_RCU(bh, head, next) { - if ((bh->flags & (BH_SCHEDULED | BH_DELETED)) == BH_SCHEDULED) { - if (bh->flags & BH_IDLE) { + int flags = qatomic_load_acquire(&bh->flags); + if ((flags & (BH_SCHEDULED | BH_DELETED)) == BH_SCHEDULED) { + if (flags & BH_IDLE) { /* idle bottom halves will be polled at least * every 10ms */ timeout = 10000000; @@ -335,14 +336,16 @@ aio_notify_accept(ctx); QSLIST_FOREACH_RCU(bh, &ctx->bh_list, next) { - if ((bh->flags & (BH_SCHEDULED | BH_DELETED)) == BH_SCHEDULED) { + int flags = qatomic_load_acquire(&bh->flags); + if ((flags & (BH_SCHEDULED | BH_DELETED)) == BH_SCHEDULED) { return true; } } QSIMPLEQ_FOREACH(s, &ctx->bh_slice_list, next) { QSLIST_FOREACH_RCU(bh, &s->bh_list, next) { - if ((bh->flags & (BH_SCHEDULED | BH_DELETED)) == BH_SCHEDULED) { + int flags = qatomic_load_acquire(&bh->flags); + if ((flags & (BH_SCHEDULED | BH_DELETED)) == BH_SCHEDULED) { return true; } }