]> git.ipfire.org Git - thirdparty/qemu.git/commitdiff
s390x/pci: Fix endianness for zPCI BAR values.
authorJaehoon Kim <jhkim@linux.ibm.com>
Fri, 6 Feb 2026 16:46:02 +0000 (10:46 -0600)
committerThomas Huth <thuth@redhat.com>
Wed, 11 Feb 2026 07:36:09 +0000 (08:36 +0100)
During zPCI scan, BAR configuration data retrieved via CLP Query was
misinterpreted due to an endianness mismatch between QEMU and the guest
kernel.

The guest kernel's clp_store_query_pci_fn() expects BAR values in
little-endian format and converts them with le32_to_cpu(). However, QEMU
was incorrectly sending them in big-endian format, not following the
architecture specification. This caused incorrect bit-swapping in the
kernel, leading zpci_setup_bus_resources() to perform registration checks
against invalid flags, making the process ineffective.

Observation values for zPCI device (NVMe passthrough):
LPAR from real CLP:
[    0.865595] Resource: PCI Bus 0000:00 -> zdev->bar[0].val: 0x4
[    0.865597]  start: 0x4000000000000000
[    0.865598]  end:   0x4000000000003fff
[    0.865600]  flags: 0x100200

QEMU before fix (wrong):
[    0.601083] Resource: PCI Bus 0001:00 -> zdev->bar[0].val: 0x4000000
[    0.601085]  start: 0x4003000000000000
[    0.601086]  end:   0x4003000000003fff
[    0.601087]  flags: 0x200

QEMU after fix (correct):
[    0.601116] Resource: PCI Bus 0001:00 -> zdev->bar[0].val: 0x4
[    0.601117]  start: 0x4003000000000000
[    0.601118]  end:   0x4003000000003fff
[    0.601119]  flags: 0x100200

Signed-off-by: Jaehoon Kim <jhkim@linux.ibm.com>
Reviewed-by: Matthew Rosato <mjrosato@linux.ibm.com>
Reviewed-by: Farhan Ali <alifm@linux.ibm.com>
Reviewed-by: Eric Farman <farman@linux.ibm.com>
Message-ID: <20260206164645.1845366-1-jhkim@linux.ibm.com>
Signed-off-by: Thomas Huth <thuth@redhat.com>
hw/s390x/s390-pci-inst.c

index 6b67c3c109f6376a08d6b8a8d8aefe2dac38862a..10066ca6180a7af5ec966135665573bcf6319272 100644 (file)
@@ -307,7 +307,7 @@ int clp_service_call(S390CPU *cpu, uint8_t r2, uintptr_t ra)
             uint32_t data = pci_get_long(pbdev->pdev->config +
                 PCI_BASE_ADDRESS_0 + (i * 4));
 
-            stl_be_p(&resquery->bar[i], data);
+            stl_le_p(&resquery->bar[i], data);
             resquery->bar_size[i] = pbdev->pdev->io_regions[i].size ?
                                     ctz64(pbdev->pdev->io_regions[i].size) : 0;
             trace_s390_pci_bar(i,