summary refs log tree commit diff stats
path: root/hw/pci.c
diff options
context:
space:
mode:
authorAnthony Liguori <aliguori@us.ibm.com>2012-10-29 14:31:47 -0500
committerAnthony Liguori <aliguori@us.ibm.com>2012-10-29 14:31:47 -0500
commit233926fafa6c4a0fb666e1469524d66dd3b47ddd (patch)
tree2dbe1506ee13fbc7d2d56b317f596114d0f849bb /hw/pci.c
parentb308c82cbda44e138ef990af64d44a5613c16092 (diff)
parent523a59f596a3e62f5a28eb171adba35e71310040 (diff)
downloadfocaccia-qemu-233926fafa6c4a0fb666e1469524d66dd3b47ddd.tar.gz
focaccia-qemu-233926fafa6c4a0fb666e1469524d66dd3b47ddd.zip
Merge remote-tracking branch 'mst/tags/for_anthony' into staging
virtio,pci infrastructure

This includes infrastructure patches that don't do much by themselves
but should help vfio and q35 make progress.
Also included is rework of virtio-net to use iovec APIs
for vector access - helpful to make it more secure
and in preparation for a new feature that will allow
arbitrary s/g layout for guests.
Also included is a pci bridge bugfix by Avi.

Signed-off-by: Michael S. Tsirkin <mst@redhat.com>

* mst/tags/for_anthony: (25 commits)
  pci: avoid destroying bridge address space windows in a transaction
  virtio-net: enable mrg buf header in tap on linux
  virtio-net: test peer header support at init time
  virtio-net: minor code simplification
  virtio-net: simplify rx code
  virtio-net: switch tx to safe iov functions
  virtio-net: first s/g is always at start of buf
  virtio-net: refactor receive_hdr
  virtio-net: use safe iov operations for rx
  virtio-net: avoid sg copy
  iov: add iov_cpy
  virtio-net: track host/guest header length
  pcie: Convert PCIExpressHost to use the QOM.
  pcie: pass pcie window size to pcie_host_mmcfg_update()
  pci: Add class 0xc05 as 'SMBus'
  pci: introduce pci_swizzle_map_irq_fn() for standardized interrupt pin swizzle
  pci_ids: add intel 82801BA pci-to-pci bridge id
  pci: pci capability must be in PCI space
  pci: make each capability DWORD aligned
  qemu: enable PV EOI for qemu 1.3
  ...

Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
Diffstat (limited to 'hw/pci.c')
-rw-r--r--hw/pci.c42
1 files changed, 36 insertions, 6 deletions
diff --git a/hw/pci.c b/hw/pci.c
index d44fd0e10a..dceda0bdc5 100644
--- a/hw/pci.c
+++ b/hw/pci.c
@@ -1117,10 +1117,21 @@ PCIINTxRoute pci_device_route_intx_to_irq(PCIDevice *dev, int pin)
          pin = bus->map_irq(dev, pin);
          dev = bus->parent_dev;
     } while (dev);
-    assert(bus->route_intx_to_irq);
+
+    if (!bus->route_intx_to_irq) {
+        error_report("PCI: Bug - unimplemented PCI INTx routing (%s)\n",
+                     object_get_typename(OBJECT(bus->qbus.parent)));
+        return (PCIINTxRoute) { PCI_INTX_DISABLED, -1 };
+    }
+
     return bus->route_intx_to_irq(bus->irq_opaque, pin);
 }
 
+bool pci_intx_route_changed(PCIINTxRoute *old, PCIINTxRoute *new)
+{
+    return old->mode != new->mode || old->irq != new->irq;
+}
+
 void pci_bus_fire_intx_routing_notifier(PCIBus *bus)
 {
     PCIDevice *dev;
@@ -1144,6 +1155,24 @@ void pci_device_set_intx_routing_notifier(PCIDevice *dev,
     dev->intx_routing_notifier = notifier;
 }
 
+/*
+ * PCI-to-PCI bridge specification
+ * 9.1: Interrupt routing. Table 9-1
+ *
+ * the PCI Express Base Specification, Revision 2.1
+ * 2.2.8.1: INTx interrutp signaling - Rules
+ *          the Implementation Note
+ *          Table 2-20
+ */
+/*
+ * 0 <= pin <= 3 0 = INTA, 1 = INTB, 2 = INTC, 3 = INTD
+ * 0-origin unlike PCI interrupt pin register.
+ */
+int pci_swizzle_map_irq_fn(PCIDevice *pci_dev, int pin)
+{
+    return (pin + PCI_SLOT(pci_dev->devfn)) % PCI_NUM_PINS;
+}
+
 /***********************************************************/
 /* monitor info on PCI */
 
@@ -1208,6 +1237,7 @@ static const pci_class_desc pci_class_descriptions[] =
     { 0x0c02, "SSA controller", "ssa"},
     { 0x0c03, "USB controller", "usb"},
     { 0x0c04, "Fibre channel controller", "fibre-channel"},
+    { 0x0c05, "SMBus"},
     { 0, NULL}
 };
 
@@ -1667,16 +1697,16 @@ PCIDevice *pci_create_simple(PCIBus *bus, int devfn, const char *name)
     return pci_create_simple_multifunction(bus, devfn, false, name);
 }
 
-static int pci_find_space(PCIDevice *pdev, uint8_t size)
+static uint8_t pci_find_space(PCIDevice *pdev, uint8_t size)
 {
-    int config_size = pci_config_size(pdev);
     int offset = PCI_CONFIG_HEADER_SIZE;
     int i;
-    for (i = PCI_CONFIG_HEADER_SIZE; i < config_size; ++i)
+    for (i = PCI_CONFIG_HEADER_SIZE; i < PCI_CONFIG_SPACE_SIZE; ++i) {
         if (pdev->used[i])
             offset = i + 1;
         else if (i - offset + 1 == size)
             return offset;
+    }
     return 0;
 }
 
@@ -1895,7 +1925,7 @@ int pci_add_capability(PCIDevice *pdev, uint8_t cap_id,
     config[PCI_CAP_LIST_NEXT] = pdev->config[PCI_CAPABILITY_LIST];
     pdev->config[PCI_CAPABILITY_LIST] = offset;
     pdev->config[PCI_STATUS] |= PCI_STATUS_CAP_LIST;
-    memset(pdev->used + offset, 0xFF, size);
+    memset(pdev->used + offset, 0xFF, QEMU_ALIGN_UP(size, 4));
     /* Make capability read-only by default */
     memset(pdev->wmask + offset, 0, size);
     /* Check capability by default */
@@ -1915,7 +1945,7 @@ void pci_del_capability(PCIDevice *pdev, uint8_t cap_id, uint8_t size)
     memset(pdev->w1cmask + offset, 0, size);
     /* Clear cmask as device-specific registers can't be checked */
     memset(pdev->cmask + offset, 0, size);
-    memset(pdev->used + offset, 0, size);
+    memset(pdev->used + offset, 0, QEMU_ALIGN_UP(size, 4));
 
     if (!pdev->config[PCI_CAPABILITY_LIST])
         pdev->config[PCI_STATUS] &= ~PCI_STATUS_CAP_LIST;