On 2/6/2026 8:46 AM, Jaehoon Kim wrote:
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 <[email protected]>
---
hw/s390x/s390-pci-inst.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/hw/s390x/s390-pci-inst.c b/hw/s390x/s390-pci-inst.c
index 6b67c3c109..10066ca618 100644
--- a/hw/s390x/s390-pci-inst.c
+++ b/hw/s390x/s390-pci-inst.c
@@ -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,
This is indeed correct architecturally, thanks for fixing this.
Reviewed-by: Farhan AliĀ <[email protected]> <mailto:[email protected]>