Misc HW patches for 2025-07-29
The following changes since commit c017386f28c03a03b8f14444f8671d3d8f7180fe:
Merge tag 'pull-target-arm-20250725' of https://gitlab.com/pm215/qemu into staging (2025-07-25 08:24:52 -0400)
are available in the Git repository at:
https://github.com/philmd/qemu.git tags/hw-misc-20250729
for you to fetch changes up to 67e4808403471427b73c8d2c3f4273d64908f480:
hw/display/sm501: fix missing error-report.h (2025-07-29 13:56:39 +0200)
----------------------------------------------------------------
Misc HW patches
- Fix MIPS MVPControl.EVP update
- Fix qxl_unpack_chunks() chunk size calculation
- Fix Cadence GEM register mask initialization
- Fix AddressSpaceDispatch use after free
- Fix building npcm7xx/npcm8xx bootroms
- Include missing headers
----------------------------------------------------------------
Adam Williamson (1):
hw/xen/passthrough: add missing error-report include
Clément Chigot (1):
hw/display/sm501: fix missing error-report.h
Luc Michel (1):
hw/net/cadence_gem: fix register mask initialization
Michael Tokarev (2):
hw/display/qxl-render: fix qxl_unpack_chunks() chunk size calculation roms/Makefile: fix npcmNxx_bootrom build rules
Philippe Mathieu-Daudé (2):
target/mips: Only update MVPControl.EVP bit if executed by master VPE hw/vfio/vfio-migration: Remove unnecessary 'qemu/typedefs.h' include
Pierrick Bouvier (2):
migration: rename target.c to vfio.c system/physmem: fix use-after-free with dispatch
hw/vfio/vfio-migration-internal.h | 1 -
hw/display/qxl-render.c | 11 +++++++++-
hw/display/sm501.c | 1 +
hw/net/cadence_gem.c | 2 +-
hw/xen/xen_pt.c | 1 +
migration/{target.c => vfio.c} | 2 +-
system/physmem.c | 15 +++-----------
target/mips/tcg/system/cp0_helper.c | 32 ++++++++++++++++-------------
migration/meson.build | 2 +-
roms/Makefile | 8 ++++----
10 files changed, 40 insertions(+), 35 deletions(-)
rename migration/{target.c => vfio.c} (90%)Signature · 1 line
2.49.0
[PULL 6/9] hw/xen/passthrough: add missing error-report include
From: Adam Williamson <[email protected]>
In commit cfcacbab38e ("xen/passthrough: use gsi to map pirq when dom0 is PVH") an error_report was added to this file, but the corresponding include of qemu/error-report.h was missed. This only becomes apparent when building against Xen 4.20+ with trace backend log disabled.
Message-ID: <[email protected]>
--- hw/xen/xen_pt.c | 1 + 1 file changed, 1 insertion(+)
hw/xen/xen_pt.c +1 -0
@@ -54,6 +54,7 @@#include "qemu/osdep.h" #include "qapi/error.h" +#include "qemu/error-report.h" #include <sys/ioctl.h> #include "hw/pci/pci.h"
Signature · 1 line
2.49.0
[PULL 2/9] hw/display/qxl-render: fix qxl_unpack_chunks() chunk size calculation
In reply to Philippe Mathieu-DaudéFrom: Michael Tokarev <[email protected]>
In case of multiple chunks, code in qxl_unpack_chunks() takes size of the wrong (next in the chain) chunk, instead of using current chunk size. This leads to wrong number of bytes being copied, and to crashes if next chunk size is larger than the current one.
Based on the code by Gao Yong.
Resolves: https://gitlab.com/qemu-project/qemu/-/issues/1628
Message-ID: <[email protected]>
--- hw/display/qxl-render.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-)
hw/display/qxl-render.c +10 -1
@@ -222,6 +222,7 @@ static void qxl_unpack_chunks(void *dest, size_t size, PCIQXLDevice *qxl,uint32_t max_chunks =32 ;size_t offset =0 ;size_t bytes; +QXLPHYSICAL next_chunk_phys =0 ;for (;;) { bytes =MIN (size - offset, chunk->data_size);
@@ -230,7 +231,15 @@ static void qxl_unpack_chunks(void *dest, size_t size, PCIQXLDevice *qxl,if (offset == size) {return ; } - chunk =qxl_phys2virt (qxl, chunk->next_chunk, group_id, + next_chunk_phys = chunk->next_chunk; +/* fist time, only get the next chunk's data size */ + chunk =qxl_phys2virt (qxl, next_chunk_phys, group_id, +sizeof (QXLDataChunk)); +if (!chunk) { +return ; + } +/* second time, check data size and get data */ + chunk =qxl_phys2virt (qxl, next_chunk_phys, group_id,sizeof (QXLDataChunk) + chunk->data_size);if (!chunk) {return ;
Signature · 1 line
2.49.0
[PULL 5/9] hw/net/cadence_gem: fix register mask initialization
In reply to Philippe Mathieu-DaudéFrom: Luc Michel <[email protected]>
The gem_init_register_masks function was called at init time but it relies on the num-priority-queues property. Call it at realize time instead.
Message-ID: <[email protected]>
--- hw/net/cadence_gem.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
hw/net/cadence_gem.c +1 -1
@@ -1756,6 +1756,7 @@ static void gem_realize(DeviceState *dev, Error **errp)sysbus_init_irq (SYS_BUS_DEVICE (dev), &s->irq[i]); } +gem_init_register_masks (s);qemu_macaddr_default_if_unset (&s->conf.macaddr); s->nic = qemu_new_nic(&net_gem_info, &s->conf,
@@ -1776,7 +1777,6 @@ static void gem_init(Object *obj)DB_PRINT ("\n" ); -gem_init_register_masks (s);memory_region_init_io (&s->iomem,OBJECT (s), &gem_ops, s,"enet" ,sizeof (s->regs));
Signature · 1 line
2.49.0
[PULL 9/9] hw/display/sm501: fix missing error-report.h
In reply to Philippe Mathieu-DaudéFrom: Clément Chigot <[email protected]>
"qemu/error-report.h" was previously implicitly included. This is no longer the case following 012842c075520dbe1bd96a2fdcf4e218874ba443.
However, the issue predates this change as error-report.h should have been included when the warn_report call was introduced.
Message-ID: <[email protected]>
--- hw/display/sm501.c | 1 + 1 file changed, 1 insertion(+)
hw/display/sm501.c +1 -0
@@ -26,6 +26,7 @@#include "qemu/osdep.h" #include "qemu/units.h" #include "qapi/error.h" +#include "qemu/error-report.h" #include "qemu/log.h" #include "qemu/module.h" #include "hw/usb/hcd-ohci.h"
Signature · 1 line
2.49.0
[PULL 1/9] target/mips: Only update MVPControl.EVP bit if executed by master VPE
In reply to Philippe Mathieu-DaudéFrom: Philippe Mathieu-Daudé <[email protected]>
According to the 'MIPS MT Application-Specific Extension' manual:
If the VPE executing the instruction is not a Master VPE, with the MVP bit of the VPEConf0 register set, the EVP bit is unchanged by the instruction.
Modify the DVPE/EVPE opcodes to only update the MVPControl.EVP bit if executed on a master VPE.
Message-ID: <[email protected]>
--- target/mips/tcg/system/cp0_helper.c | 32 ++++++++++++++++------------- 1 file changed, 18 insertions(+), 14 deletions(-)
target/mips/tcg/system/cp0_helper.c +18 -14
@@ -1562,12 +1562,14 @@ target_ulong helper_dvpe(CPUMIPSState *env)CPUState *other_cs = first_cpu;target_ulong prev = env->mvp->CP0_MVPControl; -CPU_FOREACH (other_cs) { -MIPSCPU *other_cpu =MIPS_CPU (other_cs); -/* Turn off all VPEs except the one executing the dvpe. */ -if (&other_cpu->env != env) { - other_cpu->env.mvp->CP0_MVPControl &= ~(1 << CP0MVPCo_EVP); -mips_vpe_sleep (other_cpu); +if (env->CP0_VPEConf0 & (1 <<CP0VPEC0_MVP )) { +CPU_FOREACH (other_cs) { +MIPSCPU *other_cpu =MIPS_CPU (other_cs); +/* Turn off all VPEs except the one executing the dvpe. */ +if (&other_cpu->env != env) { + other_cpu->env.mvp->CP0_MVPControl &= ~(1 << CP0MVPCo_EVP); +mips_vpe_sleep (other_cpu); + } } }return prev;
@@ -1578,15 +1580,17 @@ target_ulong helper_evpe(CPUMIPSState *env)CPUState *other_cs = first_cpu;target_ulong prev = env->mvp->CP0_MVPControl; -CPU_FOREACH (other_cs) { -MIPSCPU *other_cpu =MIPS_CPU (other_cs); +if (env->CP0_VPEConf0 & (1 <<CP0VPEC0_MVP )) { +CPU_FOREACH (other_cs) { +MIPSCPU *other_cpu =MIPS_CPU (other_cs); -if (&other_cpu->env != env -/* If the VPE is WFI, don't disturb its sleep. */ - && !mips_vpe_is_wfi (other_cpu)) { -/* Enable the VPE. */ - other_cpu->env.mvp->CP0_MVPControl |= (1 << CP0MVPCo_EVP); -mips_vpe_wake (other_cpu);/* And wake it up. */ +if (&other_cpu->env != env +/* If the VPE is WFI, don't disturb its sleep. */ + && !mips_vpe_is_wfi (other_cpu)) { +/* Enable the VPE. */ + other_cpu->env.mvp->CP0_MVPControl |= (1 << CP0MVPCo_EVP); +mips_vpe_wake (other_cpu);/* And wake it up. */ + } } }return prev;
Signature · 1 line
2.49.0
[PULL 7/9] system/physmem: fix use-after-free with dispatch
In reply to Philippe Mathieu-DaudéFrom: Pierrick Bouvier <[email protected]>
A use-after-free bug was reported when booting a Linux kernel during the pci setup phase. It's quite hard to reproduce (needs smp, and favored by having several pci devices with BAR and specific Linux config, which is Debian default one in this case).
After investigation (see the associated bug ticket), it appears that, under specific conditions, we might access a cached AddressSpaceDispatch that was reclaimed by RCU thread meanwhile.
In the Linux boot scenario, during the pci phase, memory region are destroyed/recreated, resulting in exposition of the bug.
The core of the issue is that we cache the dispatch associated to current cpu in cpu->cpu_ases[asidx].memory_dispatch. It is updated with tcg_commit, which runs asynchronously on a given cpu.
At some point, we leave the rcu critial section, and the RCU thread starts reclaiming it, but tcg_commit is not yet invoked, resulting in the use-after-free.
It's not the first problem around this area, and commit 0d58c660689 [1] ("softmmu: Use async_run_on_cpu in tcg_commit") already tried to address it. It did a good job, but it seems that we found a specific situation where it's not enough.
This patch takes a simple approach: remove the cached value creating the issue, and make sure we always get the current mapping for address space, using address_space_to_dispatch(cpu->cpu_ases[asidx].as). It's equivalent to qatomic_rcu_read(&as->current_map)->dispatch; This is not really costly, we just need two dereferences, including one atomic (rcu) read, which is negligible considering we are already on mmu slow path anyway.
Note that tcg_commit is still needed, as it's taking care of flushing TLB, removing previously mapped entries.
Another solution would be to cache directly values under the dispatch (dispatch themselves are not ref counted), keep an active reference on associated memory section, and release it when appropriate (tricky). Given the time already spent debugging this area now and previously, I strongly prefer eliminating the root of the issue, instead of adding more complexity for a hypothetical performance gain. RCU is precisely used to ensure good performance when reading data, so caching is not as beneficial as it might seem IMHO.
[1] https://gitlab.com/qemu-project/qemu/-/commit/0d58c660689f6da1e3feff8a997014003d928b3b
Cc: [email protected]
Resolves: https://gitlab.com/qemu-project/qemu/-/issues/3040
Message-ID: <[email protected]>
--- system/physmem.c | 15 +++------------ 1 file changed, 3 insertions(+), 12 deletions(-)
system/physmem.c +3 -12
@@ -165,13 +165,11 @@ static bool ram_is_cpr_compatible(RAMBlock *rb);* CPUAddressSpace: all the information a CPU needs about an AddressSpace * @cpu: the CPU whose AddressSpace this is * @as: the AddressSpace itself -* @memory_dispatch: its dispatch pointer (cached, RCU protected) * @tcg_as_listener: listener for tracking changes to the AddressSpace */ typedef struct CPUAddressSpace {CPUState *cpu;AddressSpace *as; -struct AddressSpaceDispatch *memory_dispatch;MemoryListener tcg_as_listener; }CPUAddressSpace ;
@@ -692,7 +690,7 @@ address_space_translate_for_iotlb(CPUState *cpu, int asidx, hwaddr orig_addr,IOMMUTLBEntry iotlb;int iommu_idx;hwaddr addr = orig_addr; -AddressSpaceDispatch *d = cpu->cpu_ases[asidx].memory_dispatch; +AddressSpaceDispatch *d =address_space_to_dispatch (cpu->cpu_ases[asidx].as);for (;;) { section =address_space_translate_internal (d, addr, &addr, plen, false);
@@ -753,7 +751,7 @@ MemoryRegionSection *iotlb_to_section(CPUState *cpu, {int asidx =cpu_asidx_from_attrs (cpu, attrs);CPUAddressSpace *cpuas = &cpu->cpu_ases[asidx]; -AddressSpaceDispatch *d = cpuas->memory_dispatch; +AddressSpaceDispatch *d =address_space_to_dispatch (cpuas->as);int section_index = index & ~TARGET_PAGE_MASK ;MemoryRegionSection *ret;
@@ -2780,9 +2778,6 @@ static void tcg_log_global_after_sync(MemoryListener *listener)static void tcg_commit_cpu (CPUState *cpu,run_on_cpu_data data) { -CPUAddressSpace *cpuas = data.host_ptr; - - cpuas->memory_dispatch =address_space_to_dispatch (cpuas->as);tlb_flush (cpu); }
@@ -2798,11 +2793,7 @@ static void tcg_commit(MemoryListener *listener) cpu = cpuas->cpu;/* -* Defer changes to as->memory_dispatch until the cpu is quiescent. -* Otherwise we race between (1) other cpu threads and (2) ongoing -* i/o for the current cpu thread, with data cached by mmu_lookup(). -* -* In addition, queueing the work function will kick the cpu back to +* Queueing the work function will kick the cpu back to * the main loop, which will end the RCU critical section and reclaim * the memory data structures. *
Signature · 1 line
2.49.0
[PULL 4/9] migration: rename target.c to vfio.c
In reply to Philippe Mathieu-DaudéFrom: Pierrick Bouvier <[email protected]>
Message-ID: <[email protected]>
---
migration/{target.c => vfio.c} | 2 +-
migration/meson.build | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
rename migration/{target.c => vfio.c} (90%)migration/vfio.c renamed from migration/target.c +1 -1
@@ -1,5 +1,5 @@/* -* QEMU live migration - functions that need to be compiled target-specific +* QEMU live migration - VFIO * * This work is licensed under the terms of the GNU GPL, version 2 * or (at your option) any later version.
migration/meson.build +1 -1
@@ -51,4 +51,4 @@ system_ss.add(when: qatzip, if_true: files('multifd-qatzip.c')) specific_ss.add(when: 'CONFIG_SYSTEM_ONLY', if_true: files('ram.c', - 'target.c')) + 'vfio.c'))
Signature · 1 line
2.49.0
[PULL 3/9] hw/vfio/vfio-migration: Remove unnecessary 'qemu/typedefs.h' include
In reply to Philippe Mathieu-Daudé"qemu/typedefs.h" is already included by "qemu/osdep.h".
Message-ID: <[email protected]>
--- hw/vfio/vfio-migration-internal.h | 1 - 1 file changed, 1 deletion(-)
hw/vfio/vfio-migration-internal.h +0 -1
@@ -13,7 +13,6 @@#include <linux/vfio.h> #endif -#include "qemu/typedefs.h" #include "qemu/notify.h" /*
Signature · 1 line
2.49.0
[PULL 8/9] roms/Makefile: fix npcmNxx_bootrom build rules
In reply to Philippe Mathieu-DaudéFrom: Michael Tokarev <[email protected]>
Since commit 70ce076fa6dff60, the actual rom source dirs are subdirs of vbootrom/ submodule, not in top-level of it.
Message-ID: <[email protected]>
--- roms/Makefile | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-)
roms/Makefile +4 -4
@@ -193,12 +193,12 @@ qboot: cp qboot/build/bios.bin ../pc-bios/qboot.rom npcm7xx_bootrom: - $(MAKE) -C vbootrom CROSS_COMPILE=$(arm_cross_prefix) - cp vbootrom/npcm7xx_bootrom.bin ../pc-bios/npcm7xx_bootrom.bin + $(MAKE) -C vbootrom/npcm7xx CROSS_COMPILE=$(arm_cross_prefix) + cp vbootrom/npcm7xx/npcm7xx_bootrom.bin ../pc-bios/npcm7xx_bootrom.bin npcm8xx_bootrom: - $(MAKE) -C vbootrom CROSS_COMPILE=$(aarch64_cross_prefix) - cp vbootrom/npcm8xx_bootrom.bin ../pc-bios/npcm8xx_bootrom.bin + $(MAKE) -C vbootrom/npcm8xx CROSS_COMPILE=$(aarch64_cross_prefix) + cp vbootrom/npcm8xx/npcm8xx_bootrom.bin ../pc-bios/npcm8xx_bootrom.bin hppa-firmware: $(MAKE) -C seabios-hppa parisc
Signature · 1 line
2.49.0
Stefan Hajnoczi
AppliedApplied, thanks.
Please update the changelog at https://wiki.qemu.org/ChangeLog/10.1 for any user-visible changes.