From 0ffc8f3625c7bf2d437f2badf53939a3641910e7 Mon Sep 17 00:00:00 2001 From: Farhan Ali Date: Mon, 5 Jan 2026 14:20:29 -0800 Subject: [PATCH] util/vfio-helper: Fix endianness in PCI config read/write functions MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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 Reviewed-by: Cédric Le Goater 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 --- util/vfio-helpers.c | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) 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);