aboutsummaryrefslogtreecommitdiff
path: root/hw/pci/pci.c
diff options
context:
space:
mode:
authorAnthony Liguori <anthony@codemonkey.ws>2013-09-30 17:15:01 -0500
committerAnthony Liguori <anthony@codemonkey.ws>2013-09-30 17:15:01 -0500
commiteb322b8155120166fa259a8e96040f76ba4fde64 (patch)
tree7ad01ba082b3e4db3ef593377b81cb74ff862652 /hw/pci/pci.c
parent4235d77349e93e7157555f20f1892088f55edff4 (diff)
parente26d3e734650640fabd7d95ace4f3a6f88725e0b (diff)
downloadqemu-eb322b8155120166fa259a8e96040f76ba4fde64.zip
qemu-eb322b8155120166fa259a8e96040f76ba4fde64.tar.gz
qemu-eb322b8155120166fa259a8e96040f76ba4fde64.tar.bz2
Merge remote-tracking branch 'mst/tags/for_anthony' into staging
pc,pci,virtio fixes and cleanups This includes pc and pci cleanups and enhancements, and a virtio-net bugfix related to softmac programming. Signed-off-by: Michael S. Tsirkin <mst@redhat.com> # gpg: Signature made Sun 29 Sep 2013 01:51:16 AM CDT using RSA key ID D28D5469 # gpg: Can't check signature: public key not found # By Michael S. Tsirkin (8) and others # Via Michael S. Tsirkin * mst/tags/for_anthony: smbios: Factor out smbios_maybe_add_str() smbios: Make multiple -smbios type= accumulate sanely smbios: Improve diagnostics for conflicting entries smbios: Convert to QemuOpts smbios: Normalize smbios_entry_add()'s error handling to exit(1) virtio-net: fix up HMP NIC info string on reset pci: remove explicit check to 64K ioport size piix4: disable io on reset piix: use 64 bit window programmed by guest q35: use 64 bit window programmed by guest pci: add helper to retrieve the 64-bit range range: add min/max operations on ranges range: add Range to typedefs q35: make pci window address/size match guest cfg Message-id: 1380437951-21788-1-git-send-email-mst@redhat.com
Diffstat (limited to 'hw/pci/pci.c')
-rw-r--r--hw/pci/pci.c56
1 files changed, 54 insertions, 2 deletions
diff --git a/hw/pci/pci.c b/hw/pci/pci.c
index ad1c1ca..00554a0 100644
--- a/hw/pci/pci.c
+++ b/hw/pci/pci.c
@@ -1028,8 +1028,10 @@ static pcibus_t pci_bar_address(PCIDevice *d,
}
new_addr = pci_get_long(d->config + bar) & ~(size - 1);
last_addr = new_addr + size - 1;
- /* NOTE: we have only 64K ioports on PC */
- if (last_addr <= new_addr || new_addr == 0 || last_addr > UINT16_MAX) {
+ /* Check if 32 bit BAR wraps around explicitly.
+ * TODO: make priorities correct and remove this work around.
+ */
+ if (last_addr <= new_addr || new_addr == 0 || last_addr >= UINT32_MAX) {
return PCI_BAR_UNMAPPED;
}
return new_addr;
@@ -2257,6 +2259,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,