Commit fc67208f authored by Marcel Apfelbaum's avatar Marcel Apfelbaum Committed by Michael S. Tsirkin
Browse files

hw/pci-bridge: fix pcie root port's IO hints capability



The gen_pcie_root_port mem-reserve and pref32-reserve properties are
defined as size (so uint64_t), but passed as uint32_t when building
the 'IO hints' vendor specific capability.
Passing 4G (or more) gets truncated and passed as a zero reservation.
Is not a huge issue since the guest firmware will always compare the
hints with the default value and take the maximum.

Fix it by passing the values as uint64_t and failing to init the
gen_pcie_root_port id invalid values are used.

Signed-off-by: default avatarMarcel Apfelbaum <marcel@redhat.com>
Reviewed-by: default avatarMichael S. Tsirkin <mst@redhat.com>
Signed-off-by: default avatarMichael S. Tsirkin <mst@redhat.com>
parent 293084a7
Loading
Loading
Loading
Loading
+19 −5
Original line number Diff line number Diff line
@@ -412,22 +412,36 @@ void pci_bridge_map_irq(PCIBridge *br, const char* bus_name,

int pci_bridge_qemu_reserve_cap_init(PCIDevice *dev, int cap_offset,
                                     uint32_t bus_reserve, uint64_t io_reserve,
                                     uint32_t mem_non_pref_reserve,
                                     uint32_t mem_pref_32_reserve,
                                     uint64_t mem_non_pref_reserve,
                                     uint64_t mem_pref_32_reserve,
                                     uint64_t mem_pref_64_reserve,
                                     Error **errp)
{
    if (mem_pref_32_reserve != (uint32_t)-1 &&
    if (mem_pref_32_reserve != (uint64_t)-1 &&
        mem_pref_64_reserve != (uint64_t)-1) {
        error_setg(errp,
                   "PCI resource reserve cap: PREF32 and PREF64 conflict");
        return -EINVAL;
    }

    if (mem_non_pref_reserve != (uint64_t)-1 &&
        mem_non_pref_reserve >= (1ULL << 32)) {
        error_setg(errp,
                   "PCI resource reserve cap: mem-reserve must be less than 4G");
        return -EINVAL;
    }

    if (mem_pref_32_reserve != (uint64_t)-1 &&
        mem_pref_32_reserve >= (1ULL << 32)) {
        error_setg(errp,
                   "PCI resource reserve cap: pref32-reserve  must be less than 4G");
        return -EINVAL;
    }

    if (bus_reserve == (uint32_t)-1 &&
        io_reserve == (uint64_t)-1 &&
        mem_non_pref_reserve == (uint32_t)-1 &&
        mem_pref_32_reserve == (uint32_t)-1 &&
        mem_non_pref_reserve == (uint64_t)-1 &&
        mem_pref_32_reserve == (uint64_t)-1 &&
        mem_pref_64_reserve == (uint64_t)-1) {
        return 0;
    }
+2 −2
Original line number Diff line number Diff line
@@ -135,8 +135,8 @@ typedef struct PCIBridgeQemuCap {

int pci_bridge_qemu_reserve_cap_init(PCIDevice *dev, int cap_offset,
                              uint32_t bus_reserve, uint64_t io_reserve,
                              uint32_t mem_non_pref_reserve,
                              uint32_t mem_pref_32_reserve,
                              uint64_t mem_non_pref_reserve,
                              uint64_t mem_pref_32_reserve,
                              uint64_t mem_pref_64_reserve,
                              Error **errp);