Commit 43864069 authored by Michael S. Tsirkin's avatar Michael S. Tsirkin
Browse files

pci: add helper to retrieve the 64-bit range

parent c5a22c43
Loading
Loading
Loading
Loading
+50 −0
Original line number Diff line number Diff line
@@ -2257,6 +2257,56 @@ void pci_setup_iommu(PCIBus *bus, PCIIOMMUFunc fn, void *opaque)
    bus->iommu_opaque = opaque;
}

static void pci_dev_get_w64(PCIBus *b, PCIDevice *dev, void *opaque)
{
    Range *range = opaque;
    PCIDeviceClass *pc = PCI_DEVICE_GET_CLASS(dev);
    uint16_t cmd = pci_get_word(dev->config + PCI_COMMAND);
    int r;

    if (!(cmd & PCI_COMMAND_MEMORY)) {
        return;
    }

    if (pc->is_bridge) {
        pcibus_t base = pci_bridge_get_base(dev, PCI_BASE_ADDRESS_MEM_PREFETCH);
        pcibus_t limit = pci_bridge_get_limit(dev, PCI_BASE_ADDRESS_MEM_PREFETCH);

        base = MAX(base, 0x1ULL << 32);

        if (limit >= base) {
            Range pref_range;
            pref_range.begin = base;
            pref_range.end = limit + 1;
            range_extend(range, &pref_range);
        }
    }
    for (r = 0; r < PCI_NUM_REGIONS; ++r) {
        PCIIORegion *region = &dev->io_regions[r];
        Range region_range;

        if (!region->size ||
            (region->type & PCI_BASE_ADDRESS_SPACE_IO) ||
            !(region->type & PCI_BASE_ADDRESS_MEM_TYPE_64)) {
            continue;
        }
        region_range.begin = pci_get_quad(dev->config + pci_bar(dev, r));
        region_range.end = region_range.begin + region->size;

        region_range.begin = MAX(region_range.begin, 0x1ULL << 32);

        if (region_range.end - 1 >= region_range.begin) {
            range_extend(range, &region_range);
        }
    }
}

void pci_bus_get_w64_range(PCIBus *bus, Range *range)
{
    range->begin = range->end = 0;
    pci_for_each_device_under_bus(bus, pci_dev_get_w64, range);
}

static const TypeInfo pci_device_type_info = {
    .name = TYPE_PCI_DEVICE,
    .parent = TYPE_DEVICE,
+1 −0
Original line number Diff line number Diff line
@@ -397,6 +397,7 @@ const char *pci_root_bus_path(PCIDevice *dev);
PCIDevice *pci_find_device(PCIBus *bus, int bus_num, uint8_t devfn);
int pci_qdev_find_device(const char *id, PCIDevice **pdev);
PCIBus *pci_get_bus_devfn(int *devfnp, PCIBus *root, const char *devaddr);
void pci_bus_get_w64_range(PCIBus *bus, Range *range);

int pci_parse_devaddr(const char *addr, int *domp, int *busp,
                      unsigned int *slotp, unsigned int *funcp);