Bug#1115486: trixie-pu: package qemu/1:10.0.4+ds-0+deb13u1
Control: retitle -1 trixie-pu: package qemu/1:10.0.6+ds-0+deb13u1
[ Reason ]
Here's an update to the already reviewed (but not uploaded)
10.0.4+ds-0+deb13u1 version.
There's a prob in this (upstream) version, - two bugfixes applied
to 10.0.4 caused migration regression (it regressed in the upstream
master branch too, and in subsequent 10.1.0 upstream version), so 10.0.6
is here which fixes the issues by reverting the two problematic bug
fixes. Unfortunately it makes the two bugs reappear in 10.0.x series,
but again, it's not possible to fix them without introducing migration
regression (for which it's necessary to change machine type definition),
and qemu never changed released machine types.
The bugs in question are:
https://gitlab.com/qemu-project/qemu/-/issues/3001
https://gitlab.com/qemu-project/qemu/-/issues/3061
In addition to the above migration fix, the new upstream stable/bugfix
release, again, includes a long list of fixes everywhere, for issues
found so far.
[ Tests ]
This release works fine on/with a pile of my test virtual machines
(including several versions of windows and debian). Additionally,
it is now used on our site in production.
[ Risks ]
Usually qemu stable series are rather low risk. It is still
possible to break things, - however, the changes are focused,
and most of them are rather obvious or at least understandable.
Additionally, all changes were picked up from the upstream
master branch where they've tested in different contexts and
environments too.
We had 2 migration regressions in qemu stable series recently.
This upstream release corrects one of them before it entered
debian, so everything's good here. There's another in 7.2
(oldstable) which is fixed in subsequent upstream stable release
but not yet uploaded to debian.
[ Checklist ]
[x] *all* changes are documented in the d/changelog
[x] I reviewed all changes and I approve them
[x] attach debdiff against the package in (old)stable
[x] the issue is verified as fixed in unstable
[ Changes ]
The debian/changelog is below, in the debdiff (first in there).
[ Other info ]
Instead of the finall difference, it might be easier to review the
upstream changes as individual git commits, which are available at
https://salsa.debian.org/qemu-team/qemu/-/commits/upstream/10.0.6+ds
(up to v10.0.4 tag, which has already been reviewed during handling
of this bug report).
The debdiff between version which has already been reviewed, and the
proposed version, is attached below.
Unfortunately, I uploaded the proposed version already, forgetting it
should be reviewed first. Hopefully it's not a big issue.
Thanks,
/mjt
diff -Nru qemu-10.0.4+ds/debian/changelog qemu-10.0.6+ds/debian/changelog
--- qemu-10.0.4+ds/debian/changelog 2025-09-10 09:50:46.000000000 +0300
+++ qemu-10.0.6+ds/debian/changelog 2025-09-10 09:50:46.000000000 +0300
@@ -1,6 +1,99 @@
-qemu (1:10.0.4+ds-0+deb13u1) trixie; urgency=medium
+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)
@@ -92,6 +185,7 @@
- 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 <mjt@tls.msk.ru> Wed, 10 Sep 2025 09:50:46 +0300
diff -Nru qemu-10.0.4+ds/debian/control.mk qemu-10.0.6+ds/debian/control.mk
--- qemu-10.0.4+ds/debian/control.mk 2025-09-10 09:50:46.000000000 +0300
+++ qemu-10.0.6+ds/debian/control.mk 2025-09-10 09:50:46.000000000 +0300
@@ -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.4+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.4+ds/.gitlab-ci.d/buildtest.yml qemu-10.0.6+ds/.gitlab-ci.d/buildtest.yml
--- qemu-10.0.4+ds/.gitlab-ci.d/buildtest.yml 2025-09-09 19:21:41.000000000 +0300
+++ qemu-10.0.6+ds/.gitlab-ci.d/buildtest.yml 2025-10-20 21:13:45.000000000 +0300
@@ -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.4+ds/.gitlab-ci.d/container-cross.yml qemu-10.0.6+ds/.gitlab-ci.d/container-cross.yml
--- qemu-10.0.4+ds/.gitlab-ci.d/container-cross.yml 2025-09-09 19:21:41.000000000 +0300
+++ qemu-10.0.6+ds/.gitlab-ci.d/container-cross.yml 2025-10-20 21:13:45.000000000 +0300
@@ -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.4+ds/.gitlab-ci.d/crossbuilds.yml qemu-10.0.6+ds/.gitlab-ci.d/crossbuilds.yml
--- qemu-10.0.4+ds/.gitlab-ci.d/crossbuilds.yml 2025-09-09 19:21:41.000000000 +0300
+++ qemu-10.0.6+ds/.gitlab-ci.d/crossbuilds.yml 2025-10-20 21:13:45.000000000 +0300
@@ -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.4+ds/.gitmodules qemu-10.0.6+ds/.gitmodules
--- qemu-10.0.4+ds/.gitmodules 2025-09-09 19:21:41.000000000 +0300
+++ qemu-10.0.6+ds/.gitmodules 2025-10-20 21:13:45.000000000 +0300
@@ -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.4+ds/VERSION qemu-10.0.6+ds/VERSION
--- qemu-10.0.4+ds/VERSION 2025-09-09 19:21:41.000000000 +0300
+++ qemu-10.0.6+ds/VERSION 2025-10-20 21:13:45.000000000 +0300
@@ -1 +1 @@
-10.0.4
+10.0.6
diff -Nru qemu-10.0.4+ds/accel/tcg/tb-maint.c qemu-10.0.6+ds/accel/tcg/tb-maint.c
--- qemu-10.0.4+ds/accel/tcg/tb-maint.c 2025-09-09 19:21:41.000000000 +0300
+++ qemu-10.0.6+ds/accel/tcg/tb-maint.c 2025-10-20 21:13:45.000000000 +0300
@@ -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.4+ds/block/curl.c qemu-10.0.6+ds/block/curl.c
--- qemu-10.0.4+ds/block/curl.c 2025-09-09 19:21:41.000000000 +0300
+++ qemu-10.0.6+ds/block/curl.c 2025-10-20 21:13:45.000000000 +0300
@@ -471,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) {
@@ -800,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.4+ds/contrib/elf2dmp/download.c qemu-10.0.6+ds/contrib/elf2dmp/download.c
--- qemu-10.0.4+ds/contrib/elf2dmp/download.c 2025-09-09 19:21:41.000000000 +0300
+++ qemu-10.0.6+ds/contrib/elf2dmp/download.c 2025-10-20 21:13:45.000000000 +0300
@@ -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.4+ds/docs/devel/uefi-vars.rst qemu-10.0.6+ds/docs/devel/uefi-vars.rst
--- qemu-10.0.4+ds/docs/devel/uefi-vars.rst 2025-09-09 19:21:41.000000000 +0300
+++ qemu-10.0.6+ds/docs/devel/uefi-vars.rst 2025-10-20 21:13:45.000000000 +0300
@@ -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.4+ds/docs/interop/firmware.json qemu-10.0.6+ds/docs/interop/firmware.json
--- qemu-10.0.4+ds/docs/interop/firmware.json 2025-09-09 19:21:41.000000000 +0300
+++ qemu-10.0.6+ds/docs/interop/firmware.json 2025-10-20 21:13:45.000000000 +0300
@@ -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.4+ds/docs/pcie_sriov.txt qemu-10.0.6+ds/docs/pcie_sriov.txt
--- qemu-10.0.4+ds/docs/pcie_sriov.txt 2025-09-09 19:21:41.000000000 +0300
+++ qemu-10.0.6+ds/docs/pcie_sriov.txt 2025-10-20 21:13:45.000000000 +0300
@@ -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.4+ds/hw/char/sifive_uart.c qemu-10.0.6+ds/hw/char/sifive_uart.c
--- qemu-10.0.4+ds/hw/char/sifive_uart.c 2025-09-09 19:21:41.000000000 +0300
+++ qemu-10.0.6+ds/hw/char/sifive_uart.c 2025-10-20 21:13:45.000000000 +0300
@@ -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.4+ds/hw/core/cpu-common.c qemu-10.0.6+ds/hw/core/cpu-common.c
--- qemu-10.0.4+ds/hw/core/cpu-common.c 2025-09-09 19:21:41.000000000 +0300
+++ qemu-10.0.6+ds/hw/core/cpu-common.c 2025-10-20 21:13:45.000000000 +0300
@@ -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.4+ds/hw/input/hid.c qemu-10.0.6+ds/hw/input/hid.c
--- qemu-10.0.4+ds/hw/input/hid.c 2025-09-09 19:21:41.000000000 +0300
+++ qemu-10.0.6+ds/hw/input/hid.c 2025-10-20 21:13:45.000000000 +0300
@@ -478,6 +478,7 @@
ledstate |= QEMU_CAPS_LOCK_LED;
}
kbd_put_ledstate(ledstate);
+ return 1;
}
return 0;
}
diff -Nru qemu-10.0.4+ds/hw/intc/apic.c qemu-10.0.6+ds/hw/intc/apic.c
--- qemu-10.0.4+ds/hw/intc/apic.c 2025-09-09 19:21:41.000000000 +0300
+++ qemu-10.0.6+ds/hw/intc/apic.c 2025-10-20 21:13:45.000000000 +0300
@@ -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.4+ds/hw/intc/xics.c qemu-10.0.6+ds/hw/intc/xics.c
--- qemu-10.0.4+ds/hw/intc/xics.c 2025-09-09 19:21:41.000000000 +0300
+++ qemu-10.0.6+ds/hw/intc/xics.c 2025-10-20 21:13:45.000000000 +0300
@@ -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.4+ds/hw/net/igbvf.c qemu-10.0.6+ds/hw/net/igbvf.c
--- qemu-10.0.4+ds/hw/net/igbvf.c 2025-09-09 19:21:41.000000000 +0300
+++ qemu-10.0.6+ds/hw/net/igbvf.c 2025-10-20 21:13:45.000000000 +0300
@@ -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.4+ds/hw/nvme/ctrl.c qemu-10.0.6+ds/hw/nvme/ctrl.c
--- qemu-10.0.4+ds/hw/nvme/ctrl.c 2025-09-09 19:21:41.000000000 +0300
+++ qemu-10.0.6+ds/hw/nvme/ctrl.c 2025-10-20 21:13:45.000000000 +0300
@@ -8708,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,
diff -Nru qemu-10.0.4+ds/hw/pci/pci.c qemu-10.0.6+ds/hw/pci/pci.c
--- qemu-10.0.4+ds/hw/pci/pci.c 2025-09-09 19:21:41.000000000 +0300
+++ qemu-10.0.6+ds/hw/pci/pci.c 2025-10-20 21:13:45.000000000 +0300
@@ -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.4+ds/hw/pci/pcie_sriov.c qemu-10.0.6+ds/hw/pci/pcie_sriov.c
--- qemu-10.0.4+ds/hw/pci/pcie_sriov.c 2025-09-09 19:21:41.000000000 +0300
+++ qemu-10.0.6+ds/hw/pci/pcie_sriov.c 2025-10-20 21:13:45.000000000 +0300
@@ -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;
diff -Nru qemu-10.0.4+ds/hw/pci-host/astro.c qemu-10.0.6+ds/hw/pci-host/astro.c
--- qemu-10.0.4+ds/hw/pci-host/astro.c 2025-09-09 19:21:41.000000000 +0300
+++ qemu-10.0.6+ds/hw/pci-host/astro.c 2025-10-20 21:13:45.000000000 +0300
@@ -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.4+ds/hw/pci-host/dino.c qemu-10.0.6+ds/hw/pci-host/dino.c
--- qemu-10.0.4+ds/hw/pci-host/dino.c 2025-09-09 19:21:41.000000000 +0300
+++ qemu-10.0.6+ds/hw/pci-host/dino.c 2025-10-20 21:13:45.000000000 +0300
@@ -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.4+ds/hw/ppc/spapr.c qemu-10.0.6+ds/hw/ppc/spapr.c
--- qemu-10.0.4+ds/hw/ppc/spapr.c 2025-09-09 19:21:41.000000000 +0300
+++ qemu-10.0.6+ds/hw/ppc/spapr.c 2025-10-20 21:13:45.000000000 +0300
@@ -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.4+ds/hw/riscv/riscv-iommu.c qemu-10.0.6+ds/hw/riscv/riscv-iommu.c
--- qemu-10.0.4+ds/hw/riscv/riscv-iommu.c 2025-09-09 19:21:41.000000000 +0300
+++ qemu-10.0.6+ds/hw/riscv/riscv-iommu.c 2025-10-20 21:13:45.000000000 +0300
@@ -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.4+ds/hw/usb/dev-network.c qemu-10.0.6+ds/hw/usb/dev-network.c
--- qemu-10.0.4+ds/hw/usb/dev-network.c 2025-09-09 19:21:41.000000000 +0300
+++ qemu-10.0.6+ds/hw/usb/dev-network.c 2025-10-20 21:13:45.000000000 +0300
@@ -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.4+ds/hw/usb/hcd-uhci.c qemu-10.0.6+ds/hw/usb/hcd-uhci.c
--- qemu-10.0.4+ds/hw/usb/hcd-uhci.c 2025-09-09 19:21:41.000000000 +0300
+++ qemu-10.0.6+ds/hw/usb/hcd-uhci.c 2025-10-20 21:13:45.000000000 +0300
@@ -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.4+ds/include/exec/cpu-common.h qemu-10.0.6+ds/include/exec/cpu-common.h
--- qemu-10.0.4+ds/include/exec/cpu-common.h 2025-09-09 19:21:41.000000000 +0300
+++ qemu-10.0.6+ds/include/exec/cpu-common.h 2025-10-20 21:13:46.000000000 +0300
@@ -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.4+ds/include/exec/memory.h qemu-10.0.6+ds/include/exec/memory.h
--- qemu-10.0.4+ds/include/exec/memory.h 2025-09-09 19:21:41.000000000 +0300
+++ qemu-10.0.6+ds/include/exec/memory.h 2025-10-20 21:13:46.000000000 +0300
@@ -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.4+ds/include/hw/core/cpu.h qemu-10.0.6+ds/include/hw/core/cpu.h
--- qemu-10.0.4+ds/include/hw/core/cpu.h 2025-09-09 19:21:41.000000000 +0300
+++ qemu-10.0.6+ds/include/hw/core/cpu.h 2025-10-20 21:13:46.000000000 +0300
@@ -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.4+ds/include/hw/pci/pcie_sriov.h qemu-10.0.6+ds/include/hw/pci/pcie_sriov.h
--- qemu-10.0.4+ds/include/hw/pci/pcie_sriov.h 2025-09-09 19:21:41.000000000 +0300
+++ qemu-10.0.6+ds/include/hw/pci/pcie_sriov.h 2025-10-20 21:13:46.000000000 +0300
@@ -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.4+ds/linux-user/microblaze/target_elf.h qemu-10.0.6+ds/linux-user/microblaze/target_elf.h
--- qemu-10.0.4+ds/linux-user/microblaze/target_elf.h 2025-09-09 19:21:41.000000000 +0300
+++ qemu-10.0.6+ds/linux-user/microblaze/target_elf.h 2025-10-20 21:13:46.000000000 +0300
@@ -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.4+ds/linux-user/strace.c qemu-10.0.6+ds/linux-user/strace.c
--- qemu-10.0.4+ds/linux-user/strace.c 2025-09-09 19:21:41.000000000 +0300
+++ qemu-10.0.6+ds/linux-user/strace.c 2025-10-20 21:13:46.000000000 +0300
@@ -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.4+ds/migration/migration.c qemu-10.0.6+ds/migration/migration.c
--- qemu-10.0.4+ds/migration/migration.c 2025-09-09 19:21:41.000000000 +0300
+++ qemu-10.0.6+ds/migration/migration.c 2025-10-20 21:13:46.000000000 +0300
@@ -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.4+ds/pc-bios/optionrom/multiboot.S qemu-10.0.6+ds/pc-bios/optionrom/multiboot.S
--- qemu-10.0.4+ds/pc-bios/optionrom/multiboot.S 2025-09-09 19:21:41.000000000 +0300
+++ qemu-10.0.6+ds/pc-bios/optionrom/multiboot.S 2025-10-20 21:13:46.000000000 +0300
@@ -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.4+ds/python/qemu/machine/qtest.py qemu-10.0.6+ds/python/qemu/machine/qtest.py
--- qemu-10.0.4+ds/python/qemu/machine/qtest.py 2025-09-09 19:21:41.000000000 +0300
+++ qemu-10.0.6+ds/python/qemu/machine/qtest.py 2025-10-20 21:13:46.000000000 +0300
@@ -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.4+ds/python/qemu/qmp/legacy.py qemu-10.0.6+ds/python/qemu/qmp/legacy.py
--- qemu-10.0.4+ds/python/qemu/qmp/legacy.py 2025-09-09 19:21:41.000000000 +0300
+++ qemu-10.0.6+ds/python/qemu/qmp/legacy.py 2025-10-20 21:13:46.000000000 +0300
@@ -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.4+ds/python/qemu/qmp/protocol.py qemu-10.0.6+ds/python/qemu/qmp/protocol.py
--- qemu-10.0.4+ds/python/qemu/qmp/protocol.py 2025-09-09 19:21:41.000000000 +0300
+++ qemu-10.0.6+ds/python/qemu/qmp/protocol.py 2025-10-20 21:13:46.000000000 +0300
@@ -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.4+ds/python/qemu/qmp/qmp_shell.py qemu-10.0.6+ds/python/qemu/qmp/qmp_shell.py
--- qemu-10.0.4+ds/python/qemu/qmp/qmp_shell.py 2025-09-09 19:21:41.000000000 +0300
+++ qemu-10.0.6+ds/python/qemu/qmp/qmp_shell.py 2025-10-20 21:13:46.000000000 +0300
@@ -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.4+ds/python/qemu/qmp/qmp_tui.py qemu-10.0.6+ds/python/qemu/qmp/qmp_tui.py
--- qemu-10.0.4+ds/python/qemu/qmp/qmp_tui.py 2025-09-09 19:21:41.000000000 +0300
+++ qemu-10.0.6+ds/python/qemu/qmp/qmp_tui.py 2025-10-20 21:13:46.000000000 +0300
@@ -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.4+ds/python/qemu/qmp/util.py qemu-10.0.6+ds/python/qemu/qmp/util.py
--- qemu-10.0.4+ds/python/qemu/qmp/util.py 2025-09-09 19:21:41.000000000 +0300
+++ qemu-10.0.6+ds/python/qemu/qmp/util.py 2025-10-20 21:13:46.000000000 +0300
@@ -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.4+ds/python/tests/protocol.py qemu-10.0.6+ds/python/tests/protocol.py
--- qemu-10.0.4+ds/python/tests/protocol.py 2025-09-09 19:21:41.000000000 +0300
+++ qemu-10.0.6+ds/python/tests/protocol.py 2025-10-20 21:13:46.000000000 +0300
@@ -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.4+ds/rust/hw/timer/hpet/src/hpet.rs qemu-10.0.6+ds/rust/hw/timer/hpet/src/hpet.rs
--- qemu-10.0.4+ds/rust/hw/timer/hpet/src/hpet.rs 2025-09-09 19:21:41.000000000 +0300
+++ qemu-10.0.6+ds/rust/hw/timer/hpet/src/hpet.rs 2025-10-20 21:13:46.000000000 +0300
@@ -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.4+ds/stubs/cpu-destroy-address-spaces.c qemu-10.0.6+ds/stubs/cpu-destroy-address-spaces.c
--- qemu-10.0.4+ds/stubs/cpu-destroy-address-spaces.c 1970-01-01 03:00:00.000000000 +0300
+++ qemu-10.0.6+ds/stubs/cpu-destroy-address-spaces.c 2025-10-20 21:13:46.000000000 +0300
@@ -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.4+ds/stubs/meson.build qemu-10.0.6+ds/stubs/meson.build
--- qemu-10.0.4+ds/stubs/meson.build 2025-09-09 19:21:41.000000000 +0300
+++ qemu-10.0.6+ds/stubs/meson.build 2025-10-20 21:13:46.000000000 +0300
@@ -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.4+ds/system/memory.c qemu-10.0.6+ds/system/memory.c
--- qemu-10.0.4+ds/system/memory.c 2025-09-09 19:21:41.000000000 +0300
+++ qemu-10.0.6+ds/system/memory.c 2025-10-20 21:13:46.000000000 +0300
@@ -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.4+ds/system/physmem.c qemu-10.0.6+ds/system/physmem.c
--- qemu-10.0.4+ds/system/physmem.c 2025-09-09 19:21:41.000000000 +0300
+++ qemu-10.0.6+ds/system/physmem.c 2025-10-20 21:13:46.000000000 +0300
@@ -763,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];
@@ -782,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);
- }
+ /* convenience alias just points to some cpu_ases[n] */
+ cpu->as = NULL;
- address_space_destroy(cpuas->as);
- g_free_rcu(cpuas->as, rcu);
-
- 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)
diff -Nru qemu-10.0.4+ds/target/arm/helper.c qemu-10.0.6+ds/target/arm/helper.c
--- qemu-10.0.4+ds/target/arm/helper.c 2025-09-09 19:21:41.000000000 +0300
+++ qemu-10.0.6+ds/target/arm/helper.c 2025-10-20 21:13:46.000000000 +0300
@@ -5340,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;
}
diff -Nru qemu-10.0.4+ds/target/hppa/insns.decode qemu-10.0.6+ds/target/hppa/insns.decode
--- qemu-10.0.4+ds/target/hppa/insns.decode 2025-09-09 19:21:41.000000000 +0300
+++ qemu-10.0.6+ds/target/hppa/insns.decode 2025-10-20 21:13:46.000000000 +0300
@@ -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.4+ds/target/i386/cpu.c qemu-10.0.6+ds/target/i386/cpu.c
--- qemu-10.0.4+ds/target/i386/cpu.c 2025-09-09 19:21:41.000000000 +0300
+++ qemu-10.0.6+ds/target/i386/cpu.c 2025-10-20 21:13:46.000000000 +0300
@@ -6851,6 +6851,9 @@
/* Fixup overflow: max value for bits 23-16 is 255. */
*ebx |= MIN(num, 255) << 16;
}
+ if (!cpu->enable_pmu) {
+ *ecx &= ~CPUID_EXT_PDCM;
+ }
break;
case 2:
/* cache info: needed for Pentium Pro compatibility */
@@ -7510,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);
@@ -7840,10 +7847,6 @@
}
}
- if (!cpu->enable_pmu) {
- env->features[FEAT_1_ECX] &= ~CPUID_EXT_PDCM;
- }
-
for (i = 0; i < ARRAY_SIZE(feature_dependencies); i++) {
FeatureDep *d = &feature_dependencies[i];
if (!(env->features[d->from.index] & d->from.mask)) {
diff -Nru qemu-10.0.4+ds/target/i386/cpu.h qemu-10.0.6+ds/target/i386/cpu.h
--- qemu-10.0.4+ds/target/i386/cpu.h 2025-09-09 19:21:41.000000000 +0300
+++ qemu-10.0.6+ds/target/i386/cpu.h 2025-10-20 21:13:46.000000000 +0300
@@ -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.4+ds/target/i386/helper.c qemu-10.0.6+ds/target/i386/helper.c
--- qemu-10.0.4+ds/target/i386/helper.c 2025-09-09 19:21:41.000000000 +0300
+++ qemu-10.0.6+ds/target/i386/helper.c 2025-10-20 21:13:46.000000000 +0300
@@ -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.4+ds/target/i386/kvm/kvm-cpu.c qemu-10.0.6+ds/target/i386/kvm/kvm-cpu.c
--- qemu-10.0.4+ds/target/i386/kvm/kvm-cpu.c 2025-09-09 19:21:41.000000000 +0300
+++ qemu-10.0.6+ds/target/i386/kvm/kvm-cpu.c 2025-10-20 21:13:46.000000000 +0300
@@ -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.4+ds/target/i386/kvm/kvm.c qemu-10.0.6+ds/target/i386/kvm/kvm.c
--- qemu-10.0.4+ds/target/i386/kvm/kvm.c 2025-09-09 19:21:41.000000000 +0300
+++ qemu-10.0.6+ds/target/i386/kvm/kvm.c 2025-10-20 21:13:46.000000000 +0300
@@ -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.4+ds/target/i386/tcg/decode-new.c.inc qemu-10.0.6+ds/target/i386/tcg/decode-new.c.inc
--- qemu-10.0.4+ds/target/i386/tcg/decode-new.c.inc 2025-09-09 19:21:41.000000000 +0300
+++ qemu-10.0.6+ds/target/i386/tcg/decode-new.c.inc 2025-10-20 21:13:46.000000000 +0300
@@ -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.4+ds/target/i386/tcg/system/excp_helper.c qemu-10.0.6+ds/target/i386/tcg/system/excp_helper.c
--- qemu-10.0.4+ds/target/i386/tcg/system/excp_helper.c 2025-09-09 19:21:41.000000000 +0300
+++ qemu-10.0.6+ds/target/i386/tcg/system/excp_helper.c 2025-10-20 21:13:46.000000000 +0300
@@ -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.4+ds/target/i386/tcg/system/seg_helper.c qemu-10.0.6+ds/target/i386/tcg/system/seg_helper.c
--- qemu-10.0.4+ds/target/i386/tcg/system/seg_helper.c 2025-09-09 19:21:41.000000000 +0300
+++ qemu-10.0.6+ds/target/i386/tcg/system/seg_helper.c 2025-10-20 21:13:46.000000000 +0300
@@ -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.4+ds/target/i386/tcg/system/smm_helper.c qemu-10.0.6+ds/target/i386/tcg/system/smm_helper.c
--- qemu-10.0.4+ds/target/i386/tcg/system/smm_helper.c 2025-09-09 19:21:41.000000000 +0300
+++ qemu-10.0.6+ds/target/i386/tcg/system/smm_helper.c 2025-10-20 21:13:46.000000000 +0300
@@ -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.4+ds/target/i386/tcg/system/tcg-cpu.c qemu-10.0.6+ds/target/i386/tcg/system/tcg-cpu.c
--- qemu-10.0.4+ds/target/i386/tcg/system/tcg-cpu.c 2025-09-09 19:21:41.000000000 +0300
+++ qemu-10.0.6+ds/target/i386/tcg/system/tcg-cpu.c 2025-10-20 21:13:46.000000000 +0300
@@ -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.4+ds/target/loongarch/cpu.c qemu-10.0.6+ds/target/loongarch/cpu.c
--- qemu-10.0.4+ds/target/loongarch/cpu.c 2025-09-09 19:21:41.000000000 +0300
+++ qemu-10.0.6+ds/target/loongarch/cpu.c 2025-10-20 21:13:46.000000000 +0300
@@ -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.4+ds/target/loongarch/cpu.h qemu-10.0.6+ds/target/loongarch/cpu.h
--- qemu-10.0.4+ds/target/loongarch/cpu.h 2025-09-09 19:21:41.000000000 +0300
+++ qemu-10.0.6+ds/target/loongarch/cpu.h 2025-10-20 21:13:46.000000000 +0300
@@ -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.4+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.4+ds/target/loongarch/tcg/insn_trans/trans_atomic.c.inc 2025-09-09 19:21:41.000000000 +0300
+++ qemu-10.0.6+ds/target/loongarch/tcg/insn_trans/trans_atomic.c.inc 2025-10-20 21:13:46.000000000 +0300
@@ -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.4+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.4+ds/target/loongarch/tcg/insn_trans/trans_extra.c.inc 2025-09-09 19:21:41.000000000 +0300
+++ qemu-10.0.6+ds/target/loongarch/tcg/insn_trans/trans_extra.c.inc 2025-10-20 21:13:46.000000000 +0300
@@ -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.4+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.4+ds/target/loongarch/tcg/insn_trans/trans_farith.c.inc 2025-09-09 19:21:41.000000000 +0300
+++ qemu-10.0.6+ds/target/loongarch/tcg/insn_trans/trans_farith.c.inc 2025-10-20 21:13:46.000000000 +0300
@@ -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.4+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.4+ds/target/loongarch/tcg/insn_trans/trans_fcnv.c.inc 2025-09-09 19:21:41.000000000 +0300
+++ qemu-10.0.6+ds/target/loongarch/tcg/insn_trans/trans_fcnv.c.inc 2025-10-20 21:13:46.000000000 +0300
@@ -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.4+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.4+ds/target/loongarch/tcg/insn_trans/trans_fmemory.c.inc 2025-09-09 19:21:41.000000000 +0300
+++ qemu-10.0.6+ds/target/loongarch/tcg/insn_trans/trans_fmemory.c.inc 2025-10-20 21:13:46.000000000 +0300
@@ -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.4+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.4+ds/target/loongarch/tcg/insn_trans/trans_privileged.c.inc 2025-09-09 19:21:41.000000000 +0300
+++ qemu-10.0.6+ds/target/loongarch/tcg/insn_trans/trans_privileged.c.inc 2025-10-20 21:13:46.000000000 +0300
@@ -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.4+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.4+ds/target/loongarch/tcg/insn_trans/trans_shift.c.inc 2025-09-09 19:21:41.000000000 +0300
+++ qemu-10.0.6+ds/target/loongarch/tcg/insn_trans/trans_shift.c.inc 2025-10-20 21:13:46.000000000 +0300
@@ -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.4+ds/target/loongarch/translate.h qemu-10.0.6+ds/target/loongarch/translate.h
--- qemu-10.0.4+ds/target/loongarch/translate.h 2025-09-09 19:21:41.000000000 +0300
+++ qemu-10.0.6+ds/target/loongarch/translate.h 2025-10-20 21:13:46.000000000 +0300
@@ -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.4+ds/target/riscv/cpu.c qemu-10.0.6+ds/target/riscv/cpu.c
--- qemu-10.0.4+ds/target/riscv/cpu.c 2025-09-09 19:21:41.000000000 +0300
+++ qemu-10.0.6+ds/target/riscv/cpu.c 2025-10-20 21:13:46.000000000 +0300
@@ -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.4+ds/target/riscv/cpu.h qemu-10.0.6+ds/target/riscv/cpu.h
--- qemu-10.0.4+ds/target/riscv/cpu.h 2025-09-09 19:21:41.000000000 +0300
+++ qemu-10.0.6+ds/target/riscv/cpu.h 2025-10-20 21:13:46.000000000 +0300
@@ -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.4+ds/target/riscv/csr.c qemu-10.0.6+ds/target/riscv/csr.c
--- qemu-10.0.4+ds/target/riscv/csr.c 2025-09-09 19:21:41.000000000 +0300
+++ qemu-10.0.6+ds/target/riscv/csr.c 2025-10-20 21:13:46.000000000 +0300
@@ -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;
@@ -1990,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;
}
diff -Nru qemu-10.0.4+ds/target/riscv/helper.h qemu-10.0.6+ds/target/riscv/helper.h
--- qemu-10.0.4+ds/target/riscv/helper.h 2025-09-09 19:21:41.000000000 +0300
+++ qemu-10.0.6+ds/target/riscv/helper.h 2025-10-20 21:13:46.000000000 +0300
@@ -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.4+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.4+ds/target/riscv/insn_trans/trans_rvv.c.inc 2025-09-09 19:21:41.000000000 +0300
+++ qemu-10.0.6+ds/target/riscv/insn_trans/trans_rvv.c.inc 2025-10-20 21:13:46.000000000 +0300
@@ -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.4+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.4+ds/target/riscv/insn_trans/trans_rvzce.c.inc 2025-09-09 19:21:41.000000000 +0300
+++ qemu-10.0.6+ds/target/riscv/insn_trans/trans_rvzce.c.inc 2025-10-20 21:13:46.000000000 +0300
@@ -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.4+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.4+ds/target/riscv/insn_trans/trans_rvzicfiss.c.inc 2025-09-09 19:21:41.000000000 +0300
+++ qemu-10.0.6+ds/target/riscv/insn_trans/trans_rvzicfiss.c.inc 2025-10-20 21:13:46.000000000 +0300
@@ -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.4+ds/target/riscv/machine.c qemu-10.0.6+ds/target/riscv/machine.c
--- qemu-10.0.4+ds/target/riscv/machine.c 2025-09-09 19:21:41.000000000 +0300
+++ qemu-10.0.6+ds/target/riscv/machine.c 2025-10-20 21:13:46.000000000 +0300
@@ -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.4+ds/target/riscv/op_helper.c qemu-10.0.6+ds/target/riscv/op_helper.c
--- qemu-10.0.4+ds/target/riscv/op_helper.c 2025-09-09 19:21:41.000000000 +0300
+++ qemu-10.0.6+ds/target/riscv/op_helper.c 2025-10-20 21:13:46.000000000 +0300
@@ -715,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.4+ds/target/riscv/tcg/tcg-cpu.c qemu-10.0.6+ds/target/riscv/tcg/tcg-cpu.c
--- qemu-10.0.4+ds/target/riscv/tcg/tcg-cpu.c 2025-09-09 19:21:41.000000000 +0300
+++ qemu-10.0.6+ds/target/riscv/tcg/tcg-cpu.c 2025-10-20 21:13:46.000000000 +0300
@@ -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.4+ds/target/riscv/translate.c qemu-10.0.6+ds/target/riscv/translate.c
--- qemu-10.0.4+ds/target/riscv/translate.c 2025-09-09 19:21:41.000000000 +0300
+++ qemu-10.0.6+ds/target/riscv/translate.c 2025-10-20 21:13:46.000000000 +0300
@@ -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.4+ds/target/riscv/vector_helper.c qemu-10.0.6+ds/target/riscv/vector_helper.c
--- qemu-10.0.4+ds/target/riscv/vector_helper.c 2025-09-09 19:21:41.000000000 +0300
+++ qemu-10.0.6+ds/target/riscv/vector_helper.c 2025-10-20 21:13:46.000000000 +0300
@@ -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.4+ds/target/sparc/insns.decode qemu-10.0.6+ds/target/sparc/insns.decode
--- qemu-10.0.4+ds/target/sparc/insns.decode 2025-09-09 19:21:41.000000000 +0300
+++ qemu-10.0.6+ds/target/sparc/insns.decode 2025-10-20 21:13:46.000000000 +0300
@@ -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.4+ds/target/sparc/translate.c qemu-10.0.6+ds/target/sparc/translate.c
--- qemu-10.0.4+ds/target/sparc/translate.c 2025-09-09 19:21:41.000000000 +0300
+++ qemu-10.0.6+ds/target/sparc/translate.c 2025-10-20 21:13:46.000000000 +0300
@@ -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.4+ds/tcg/optimize.c qemu-10.0.6+ds/tcg/optimize.c
--- qemu-10.0.4+ds/tcg/optimize.c 2025-09-09 19:21:41.000000000 +0300
+++ qemu-10.0.6+ds/tcg/optimize.c 2025-10-20 21:13:46.000000000 +0300
@@ -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.4+ds/tests/Makefile.include qemu-10.0.6+ds/tests/Makefile.include
--- qemu-10.0.4+ds/tests/Makefile.include 2025-09-09 19:21:41.000000000 +0300
+++ qemu-10.0.6+ds/tests/Makefile.include 2025-10-20 21:13:46.000000000 +0300
@@ -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.4+ds/tests/docker/dockerfiles/python.docker qemu-10.0.6+ds/tests/docker/dockerfiles/python.docker
--- qemu-10.0.4+ds/tests/docker/dockerfiles/python.docker 2025-09-09 19:21:41.000000000 +0300
+++ qemu-10.0.6+ds/tests/docker/dockerfiles/python.docker 2025-10-20 21:13:46.000000000 +0300
@@ -1,6 +1,6 @@
# Python library testing environment
-FROM fedora:latest
+FROM fedora:40
MAINTAINER John Snow <jsnow@redhat.com>
# Please keep this list sorted alphabetically
diff -Nru qemu-10.0.4+ds/tests/functional/test_aarch64_sbsaref_freebsd.py qemu-10.0.6+ds/tests/functional/test_aarch64_sbsaref_freebsd.py
--- qemu-10.0.4+ds/tests/functional/test_aarch64_sbsaref_freebsd.py 2025-09-09 19:21:41.000000000 +0300
+++ qemu-10.0.6+ds/tests/functional/test_aarch64_sbsaref_freebsd.py 2025-10-20 21:13:46.000000000 +0300
@@ -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.4+ds/tests/functional/test_ppc_bamboo.py qemu-10.0.6+ds/tests/functional/test_ppc_bamboo.py
--- qemu-10.0.4+ds/tests/functional/test_ppc_bamboo.py 2025-09-09 19:21:41.000000000 +0300
+++ qemu-10.0.6+ds/tests/functional/test_ppc_bamboo.py 2025-10-20 21:13:46.000000000 +0300
@@ -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.4+ds/tests/qemu-iotests/147 qemu-10.0.6+ds/tests/qemu-iotests/147
--- qemu-10.0.4+ds/tests/qemu-iotests/147 2025-09-09 19:21:41.000000000 +0300
+++ qemu-10.0.6+ds/tests/qemu-iotests/147 2025-10-20 21:13:46.000000000 +0300
@@ -277,6 +277,7 @@
} }
self.client_test(filename, flatten_sock_addr(address), 'nbd-export')
+ sockfd.close()
self._server_down()
diff -Nru qemu-10.0.4+ds/tests/qemu-iotests/151 qemu-10.0.6+ds/tests/qemu-iotests/151
--- qemu-10.0.4+ds/tests/qemu-iotests/151 2025-09-09 19:21:41.000000000 +0300
+++ qemu-10.0.6+ds/tests/qemu-iotests/151 2025-10-20 21:13:46.000000000 +0300
@@ -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.4+ds/tests/qemu-iotests/check qemu-10.0.6+ds/tests/qemu-iotests/check
--- qemu-10.0.4+ds/tests/qemu-iotests/check 2025-09-09 19:21:41.000000000 +0300
+++ qemu-10.0.6+ds/tests/qemu-iotests/check 2025-10-20 21:13:46.000000000 +0300
@@ -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.4+ds/tests/qemu-iotests/testenv.py qemu-10.0.6+ds/tests/qemu-iotests/testenv.py
--- qemu-10.0.4+ds/tests/qemu-iotests/testenv.py 2025-09-09 19:21:41.000000000 +0300
+++ qemu-10.0.6+ds/tests/qemu-iotests/testenv.py 2025-10-20 21:13:46.000000000 +0300
@@ -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.4+ds/tests/qemu-iotests/testrunner.py qemu-10.0.6+ds/tests/qemu-iotests/testrunner.py
--- qemu-10.0.4+ds/tests/qemu-iotests/testrunner.py 2025-09-09 19:21:41.000000000 +0300
+++ qemu-10.0.6+ds/tests/qemu-iotests/testrunner.py 2025-10-20 21:13:46.000000000 +0300
@@ -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.4+ds/tests/tcg/multiarch/Makefile.target qemu-10.0.6+ds/tests/tcg/multiarch/Makefile.target
--- qemu-10.0.4+ds/tests/tcg/multiarch/Makefile.target 2025-09-09 19:21:42.000000000 +0300
+++ qemu-10.0.6+ds/tests/tcg/multiarch/Makefile.target 2025-10-20 21:13:46.000000000 +0300
@@ -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.4+ds/tests/tcg/multiarch/tb-link.c qemu-10.0.6+ds/tests/tcg/multiarch/tb-link.c
--- qemu-10.0.4+ds/tests/tcg/multiarch/tb-link.c 1970-01-01 03:00:00.000000000 +0300
+++ qemu-10.0.6+ds/tests/tcg/multiarch/tb-link.c 2025-10-20 21:13:46.000000000 +0300
@@ -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 <assert.h>
+#include <sys/mman.h>
+#include <pthread.h>
+#include <stdint.h>
+#include <stdbool.h>
+#include <unistd.h>
+#include <sched.h>
+
+
+#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.4+ds/ui/gtk.c qemu-10.0.6+ds/ui/gtk.c
--- qemu-10.0.4+ds/ui/gtk.c 2025-09-09 19:21:42.000000000 +0300
+++ qemu-10.0.6+ds/ui/gtk.c 2025-10-20 21:13:46.000000000 +0300
@@ -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.4+ds/ui/icons/qemu.svg qemu-10.0.6+ds/ui/icons/qemu.svg
--- qemu-10.0.4+ds/ui/icons/qemu.svg 2025-09-09 19:21:42.000000000 +0300
+++ qemu-10.0.6+ds/ui/icons/qemu.svg 2025-10-20 21:13:46.000000000 +0300
@@ -918,7 +918,26 @@
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
- <dc:title />
+ <dc:title>Kew the Angry Emu</dc:title>
+ <dc:creator>
+ <cc:Agent>
+ <dc:title>Benoît Canet</dc:title>
+ </cc:Agent>
+ </dc:creator>
+ <dc:rights>
+ <cc:Agent>
+ <dc:title>CC BY 3.0</dc:title>
+ </cc:Agent>
+ </dc:rights>
+ <dc:publisher>
+ <cc:Agent>
+ <dc:title>QEMU Community</dc:title>
+ </cc:Agent>
+ </dc:publisher>
+ <dc:date>2012-02-15</dc:date>
+ <cc:license
+ rdf:resource="http://creativecommons.org/licenses/by/3.0/" />
+ <dc:source>https://lists.gnu.org/archive/html/qemu-devel/2012-02/msg02865.html</dc:source>
</cc:Work>
</rdf:RDF>
</metadata>
diff -Nru qemu-10.0.4+ds/ui/spice-core.c qemu-10.0.6+ds/ui/spice-core.c
--- qemu-10.0.4+ds/ui/spice-core.c 2025-09-09 19:21:42.000000000 +0300
+++ qemu-10.0.6+ds/ui/spice-core.c 2025-10-20 21:13:46.000000000 +0300
@@ -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.4+ds/ui/vnc.c qemu-10.0.6+ds/ui/vnc.c
--- qemu-10.0.4+ds/ui/vnc.c 2025-09-09 19:21:42.000000000 +0300
+++ qemu-10.0.6+ds/ui/vnc.c 2025-10-20 21:13:46.000000000 +0300
@@ -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.4+ds/util/async.c qemu-10.0.6+ds/util/async.c
--- qemu-10.0.4+ds/util/async.c 2025-09-09 19:21:42.000000000 +0300
+++ qemu-10.0.6+ds/util/async.c 2025-10-20 21:13:46.000000000 +0300
@@ -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;
}
}
Reply to: