qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Qemu-devel] [RFC v4 11/13] pci: enumerate_slots implementation


From: Eduardo Habkost
Subject: [Qemu-devel] [RFC v4 11/13] pci: enumerate_slots implementation
Date: Mon, 14 Aug 2017 18:57:46 -0300

Enumerate each PCI function as a separate slots, because that's
how QEMU treats multi-function PCI devices.

Example output using "-machine q35" is below.

  {
    "available": true,
    "count": 224,
    "device-types": [ "pci-device" ],
    "hotpluggable": false,
    "opts": [
      { "option": "function", "values": [ [ 0, 7 ] ] },
      { "option": "device-number", "values": [ [ 3, 30 ] ] },
      { "option": "bus", "values": "pcie.0" }
    ],
    "opts-complete": true
  }
  {
    "available": false,
    "count": 1,
    "device": "/machine/unattached/device[30]",
    "device-types": [ "pci-device" ],
    "hotpluggable": false,
    "opts": [
      { "option": "function", "values": 0 },
      { "option": "device-number", "values": 2 },
      { "option": "bus", "values": "pcie.0" }
    ],
    "opts-complete": true
  }
  {
    "available": false,
    "count": 1,
    "device": "/machine/q35/mch",
    "device-types": [ "pci-device" ],
    "hotpluggable": false,
    "opts": [
      { "option": "function", "values": 0 },
      { "option": "device-number", "values": 0 },
      { "option": "bus", "values": "pcie.0" }
    ],
    "opts-complete": true
  }
  {
    "available": false,
    "count": 1,
    "device": "/machine/unattached/device[29]",
    "device-types": [ "pci-device" ],
    "hotpluggable": false,
    "opts": [
      { "option": "function", "values": 0 },
      { "option": "device-number", "values": 1 },
      { "option": "bus", "values": "pcie.0" }
    ],
    "opts-complete": true
  }
  {
    "available": false,
    "count": 1,
    "device": "/machine/unattached/device[3]",
    "device-types": [ "pci-device" ],
    "hotpluggable": false,
    "opts": [
      { "option": "function", "values": 0 },
      { "option": "device-number", "values": 31 },
      { "option": "bus", "values": "pcie.0" }
    ],
    "opts-complete": true
  }
  {
    "available": false,
    "count": 1,
    "device": "/machine/unattached/device[18]",
    "device-types": [ "pci-device" ],
    "hotpluggable": false,
    "opts": [
      { "option": "function", "values": 2 },
      { "option": "device-number", "values": 31 },
      { "option": "bus", "values": "pcie.0" }
    ],
    "opts-complete": true
  }
  {
    "available": false,
    "count": 1,
    "device": "/machine/unattached/device[20]",
    "device-types": [ "pci-device" ],
    "hotpluggable": false,
    "opts": [
      { "option": "function", "values": 3 },
      { "option": "device-number", "values": 31 },
      { "option": "bus", "values": "pcie.0" }
    ],
    "opts-complete": true
  }
  {
    "available": false,
    "count": 21,
    "device-types": [ "pci-device" ],
    "hotpluggable": false,
    "opts": [
      { "option": "function", "values": [ [ 1, 7 ] ] },
      { "option": "device-number", "values": [ [ 0, 2 ] ] },
      { "option": "bus", "values": "pcie.0" }
    ],
    "opts-complete": true
  }
  {
    "available": false,
    "count": 5,
    "device-types": [ "pci-device" ],
    "hotpluggable": false,
    "opts": [
      { "option": "function", "values": [ 1, [ 4, 7 ] ] },
      { "option": "device-number", "values": 31 },
      { "option": "bus", "values": "pcie.0" }
    ],
    "opts-complete": true
  }

Cc: "Michael S. Tsirkin" <address@hidden>
Cc: Marcel Apfelbaum <address@hidden>
Signed-off-by: Eduardo Habkost <address@hidden>
---
 hw/pci/pci.c | 50 ++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 50 insertions(+)

diff --git a/hw/pci/pci.c b/hw/pci/pci.c
index 5753af3..ae268a9 100644
--- a/hw/pci/pci.c
+++ b/hw/pci/pci.c
@@ -27,6 +27,7 @@
 #include "hw/pci/pci_bridge.h"
 #include "hw/pci/pci_bus.h"
 #include "hw/pci/pci_host.h"
+#include "hw/qdev-slotinfo.h"
 #include "monitor/monitor.h"
 #include "net/net.h"
 #include "sysemu/sysemu.h"
@@ -144,6 +145,54 @@ static uint16_t pcibus_numa_node(PCIBus *bus)
     return NUMA_NODE_UNASSIGNED;
 }
 
+
+static bool pci_bus_has_pcie_upstream_port(PCIBus *bus);
+
+static DeviceSlotInfoList *pci_bus_enumerate_slots(BusState *bus)
+{
+    PCIBus *pb = PCI_BUS(bus);
+    int devnr, devnrs;
+    DeviceSlotInfoList *r = NULL;
+
+    if (pci_bus_has_pcie_upstream_port(pb)) {
+        devnrs = 1;
+    } else {
+        devnrs = PCI_SLOT_MAX;
+    }
+
+    /* Each PCI devfn (device number + function) is a separate slot,
+     * because we implement multi-function PCI devices as separate
+     * device objects.
+     */
+    for(devnr = PCI_SLOT(pb->devfn_min); devnr < devnrs; devnr++) {
+        PCIDevice *dev0 = pb->devices[PCI_DEVFN(devnr, 0)];
+        int func;
+
+        for (func = 0; func < PCI_FUNC_MAX; func++) {
+            /*TODO: add info about accepting only bridges on extra PCI root 
buses */
+            PCIDevice *dev = pb->devices[PCI_DEVFN(devnr, func)];
+            DeviceSlotInfo *s = make_slot(bus);
+            slot_add_opt_int(s, "device-number", devnr);
+            slot_add_opt_int(s, "function", func);
+            s->opts_complete = true;
+            s->has_count = true;
+            s->count = 1;
+            /* Conditions that make a devnr unavailable:
+             * - function already occupied
+             * - function 0 already occupied by a device
+             */
+            s->available &= !dev0 && !dev;
+            if (dev) {
+                s->has_device = true;
+                s->device = object_get_canonical_path(OBJECT(dev));
+            }
+            slot_list_add_slot(&r, s);
+        }
+    }
+
+    return r;
+}
+
 static void pci_bus_class_init(ObjectClass *klass, void *data)
 {
     BusClass *k = BUS_CLASS(klass);
@@ -156,6 +205,7 @@ static void pci_bus_class_init(ObjectClass *klass, void 
*data)
     k->unrealize = pci_bus_unrealize;
     k->reset = pcibus_reset;
     k->device_type = TYPE_PCI_DEVICE;
+    k->enumerate_slots = pci_bus_enumerate_slots;
 
     pbc->is_root = pcibus_is_root;
     pbc->bus_num = pcibus_num;
-- 
2.9.4




reply via email to

[Prev in Thread] Current Thread [Next in Thread]