Skip to contentSkip to conversation

Misc HW patches for 2025-07-29

GIT PULL Applied Philippe Mathieu-Daudé 2 participants 11 messages Jul 29, 2025 Arm/Amlogic Meson SoC support

lore
Share & tools
lore
#0 lore raw

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
#1 lore raw

[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.

Fixes cfcacbab38e4 (xen/passthrough: use gsi to map pirq when dom0 is PVH)

Message-ID: <[email protected]>

[PMD: Improved commit description, added Fixes: tag]
---
 hw/xen/xen_pt.c | 1 +
 1 file changed, 1 insertion(+)
hw/xen/xen_pt.c +1 -0
index 9d16644d82e..006b5b55f24 100644
@@ -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
#2 lore raw

[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
index eda6d3de37c..c6a9ac1da10 100644
@@ -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
#3 lore raw

[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.

Fixes 4c70e32f05f ("net: cadence_gem: Define access permission for interrupt registers")

Message-ID: <[email protected]>

---
 hw/net/cadence_gem.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
hw/net/cadence_gem.c +1 -1
index 50025d5a6f2..44446666deb 100644
@@ -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
#4 lore raw

[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.

Fixes fa140b9562 ("hw/sm501: allow compiling without PIXMAN")

Message-ID: <[email protected]>

---
 hw/display/sm501.c | 1 +
 1 file changed, 1 insertion(+)
hw/display/sm501.c +1 -0
index 6d2f18684c3..bc091b3c9fb 100644
@@ -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
#5 lore raw

[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.

Reported-by Hansni Bu
Fixes f249412c749 ("mips: Add MT halting and waking of VPEs")

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
index 101b1e65fdd..b69e70d7fcf 100644
@@ -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
#6 lore raw

[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
index 130c148ffb5..e5dd760e0bc 100644
@@ -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
#7 lore raw

[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
similarity index 90%
rename from migration/target.c
rename to migration/vfio.c
index 12fd399f0c5..0b64e49ef06 100644
@@ -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
index 9aa48b290e2..276da3be5a3 100644
@@ -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
#8 lore raw

[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
index 54141e27e6b..814fbd9ebae 100644
@@ -13,7 +13,6 @@
 #include <linux/vfio.h>
 #endif
 
-#include "qemu/typedefs.h"
 #include "qemu/notify.h"
 
 /*
Signature · 1 line
2.49.0
#9 lore raw

[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.

Fixes 70ce076fa6dff60 "roms: Update vbootrom to 1287b6e"
Fixes 269b7effd90 ("pc-bios: Add NPCM8XX vBootrom")

Message-ID: <[email protected]>

---
 roms/Makefile | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)
roms/Makefile +4 -4
index beff58d9d50..6af68a922f3 100644
@@ -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