Commit 0ffc8f3625 for qemu.org
commit 0ffc8f3625c7bf2d437f2badf53939a3641910e7
Author: Farhan Ali <alifm@linux.ibm.com>
Date: Mon Jan 5 14:20:29 2026 -0800
util/vfio-helper: Fix endianness in PCI config read/write functions
The VFIO pread/pwrite functions use little-endian data format. Currently, the
qemu_vfio_pci_read_config() and qemu_vfio_pci_write_config() don't correctly
convert from CPU native endian format to little-endian (and vice versa) when
using the pread/pwrite functions. Fix this by limiting read/write to 32 bits
and handling endian conversion in qemu_vfio_pci_read_config() and
qemu_vfio_pci_write_config().
Signed-off-by: Farhan Ali <alifm@linux.ibm.com>
Reviewed-by: Cédric Le Goater <clg@redhat.com>
Link: https://lore.kernel.org/qemu-devel/20260105222029.2423-1-alifm@linux.ibm.com
[ clg: Fixed typo in subject ]
Signed-off-by: Cédric Le Goater <clg@redhat.com>
diff --git a/util/vfio-helpers.c b/util/vfio-helpers.c
index c619516163..aab0bf9d48 100644
--- a/util/vfio-helpers.c
+++ b/util/vfio-helpers.c
@@ -233,31 +233,36 @@ int qemu_vfio_pci_init_irq(QEMUVFIOState *s, EventNotifier *e,
return 0;
}
-static int qemu_vfio_pci_read_config(QEMUVFIOState *s, void *buf,
+static int qemu_vfio_pci_read_config(QEMUVFIOState *s, uint32_t *buf,
int size, int ofs)
{
int ret;
+ uint32_t val_le;
trace_qemu_vfio_pci_read_config(buf, ofs, size,
s->config_region_info.offset,
s->config_region_info.size);
assert(QEMU_IS_ALIGNED(s->config_region_info.offset + ofs, size));
ret = RETRY_ON_EINTR(
- pread(s->device, buf, size, s->config_region_info.offset + ofs)
+ pread(s->device, &val_le, size, s->config_region_info.offset + ofs)
);
+
+ *buf = le32_to_cpu(val_le);
return ret == size ? 0 : -errno;
}
-static int qemu_vfio_pci_write_config(QEMUVFIOState *s, void *buf, int size, int ofs)
+static int qemu_vfio_pci_write_config(QEMUVFIOState *s, uint32_t *buf, int size, int ofs)
{
int ret;
+ uint32_t val_le;
+ val_le = cpu_to_le32(*buf);
trace_qemu_vfio_pci_write_config(buf, ofs, size,
s->config_region_info.offset,
s->config_region_info.size);
assert(QEMU_IS_ALIGNED(s->config_region_info.offset + ofs, size));
ret = RETRY_ON_EINTR(
- pwrite(s->device, buf, size, s->config_region_info.offset + ofs)
+ pwrite(s->device, &val_le, size, s->config_region_info.offset + ofs)
);
return ret == size ? 0 : -errno;
}
@@ -296,7 +301,7 @@ static int qemu_vfio_init_pci(QEMUVFIOState *s, const char *device,
{
int ret;
int i;
- uint16_t pci_cmd;
+ uint32_t pci_cmd;
struct vfio_group_status group_status = { .argsz = sizeof(group_status) };
struct vfio_iommu_type1_info *iommu_info = NULL;
size_t iommu_info_size = sizeof(*iommu_info);