]> xenbits.xensource.com Git - libvirt.git/commitdiff
conf: Prefer pcie-to-pci-bridge to dmi-to-pci-bridge
authorAndrea Bolognani <abologna@redhat.com>
Wed, 28 Mar 2018 10:48:21 +0000 (12:48 +0200)
committerAndrea Bolognani <abologna@redhat.com>
Fri, 6 Apr 2018 12:12:21 +0000 (14:12 +0200)
Both pcie-to-pci-bridge and dmi-to-pci-bridge can be used to
create a traditional PCI topology in a pure PCIe guest such as
those using the x86_64/q35 or aarch64/virt machine type;
however, the former should be preferred, as it doesn't need to
obey limitation of real hardware and is completely
architecture-agnostic.

Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1520821

Signed-off-by: Andrea Bolognani <abologna@redhat.com>
Reviewed-by: John Ferlan <jferlan@redhat.com>
docs/formatdomain.html.in
src/conf/domain_addr.c

index 84059737d523b1c11b31fb04c0e4c28bf5007976..a5a83f56c3050ba578fe9b6abd2e627afa3c5022 100644 (file)
       devices (although libvirt will never auto-assign a PCI device to
       a PCIe slot, it will allow manual specification of such an
       assignment). Devices connected to pcie-root cannot be
-      hotplugged. In order to make standard PCI slots available on a
-      system which has a pcie-root controller, a pci controller
-      with <code>model='dmi-to-pci-bridge'</code> is automatically
-      added, usually at the defacto standard location of slot=0x1e. A
+      hotplugged. If traditional PCI devices are present in the guest
+      configuration, a <code>pcie-to-pci-bridge</code> controller will
+      automatically be added: this controller, which plugs into a
+      <code>pcie-root-port</code>, provides 31 usable PCI slots (1-31) with
+      hotplug support (<span class="since">since 4.3.0</span>). If the QEMU
+      binary doesn't support the corresponding device, then a
+      <code>dmi-to-pci-bridge</code> controller will be added instead,
+      usually at the defacto standard location of slot=0x1e. A
       dmi-to-pci-bridge controller plugs into a PCIe slot (as provided
       by pcie-root), and itself provides 31 standard PCI slots (which
       also do not support device hotplug). In order to have
index 8065853f033c1b55a8be8dee31c87e756844388d..ca50dc70ce33fd10216aa38e1df1aec155174e53 100644 (file)
@@ -416,6 +416,7 @@ virDomainPCIAddressSetGrow(virDomainPCIAddressSetPtr addrs,
     size_t i;
     int model;
     bool needDMIToPCIBridge = false;
+    bool needPCIeToPCIBridge = false;
 
     add = addr->bus - addrs->nbuses + 1;
     if (add <= 0)
@@ -436,27 +437,41 @@ virDomainPCIAddressSetGrow(virDomainPCIAddressSetPtr addrs,
             model = VIR_DOMAIN_CONTROLLER_MODEL_PCI_BRIDGE;
 
             /* if there aren't yet any buses that will accept a
-             * pci-bridge, and the caller is asking for one, we'll need to
-             * add a dmi-to-pci-bridge first.
+             * pci-bridge, but we need one for the device's PCI address
+             * to make sense, it means the guest only has a PCIe topology
+             * configured so far, and we need to create a traditional PCI
+             * topology to accomodate the new device.
              */
             needDMIToPCIBridge = true;
+            needPCIeToPCIBridge = true;
             for (i = 0; i < addrs->nbuses; i++) {
                 if (addrs->buses[i].flags & VIR_PCI_CONNECT_TYPE_PCI_BRIDGE) {
                     needDMIToPCIBridge = false;
+                    needPCIeToPCIBridge = false;
                     break;
                 }
             }
-            if (needDMIToPCIBridge && add == 1) {
+
+            /* Prefer pcie-to-pci-bridge, fall back to dmi-to-pci-bridge */
+            if (addrs->isPCIeToPCIBridgeSupported)
+                needDMIToPCIBridge = false;
+            else
+                needPCIeToPCIBridge = false;
+
+            if ((needDMIToPCIBridge || needPCIeToPCIBridge) && add == 1) {
                 /* We need to add a single pci-bridge to provide the bus
                  * our legacy PCI device will be plugged into; however, we
                  * have also determined that there isn't yet any proper
-                 * place to connect that pci-bridge we're about to add (on
-                 * a system with pcie-root, that "proper place" would be a
-                 * dmi-to-pci-bridge". So, to give the pci-bridge a place
-                 * to connect, we increase the count of buses to add,
-                 * while also incrementing the bus number in the address
-                 * for the device (since the pci-bridge will now be at an
-                 * index 1 higher than the caller had anticipated).
+                 * place to connect that pci-bridge we're about to add,
+                 * which means we're dealing with a pure PCIe guest. We
+                 * need to create a traditional PCI topology, and for that
+                 * we have two options: dmi-to-pci-bridge + pci-bridge or
+                 * pcie-root-port + pcie-to-pci-bridge (the latter of which
+                 * is pretty much a pci-bridge as far as devices attached
+                 * to it are concerned and as such makes the pci-bridge
+                 * unnecessary). Either way, there's going to be one more
+                 * controller than initially expected, and the 'bus' part
+                 * of the device's address will need to be bumped.
                  */
                 add++;
                 addr->bus++;
@@ -534,6 +549,30 @@ virDomainPCIAddressSetGrow(virDomainPCIAddressSetPtr addrs,
         }
     }
 
+    if (needPCIeToPCIBridge) {
+        /* We need a pcie-root-port to plug pcie-to-pci-bridge into; however,
+         * qemuDomainAssignPCIAddresses() will, in some cases, create a dummy
+         * PCIe device and reserve an address for it in order to leave the
+         * user with an empty pcie-root-port ready for hotplugging, and if
+         * we didn't do anything other than adding the pcie-root-port here
+         * it would be used for that, which we don't want. So we change the
+         * connect flags to make sure only the pcie-to-pci-bridge will be
+         * connected to the pcie-root-port we just added, and another one
+         * will be allocated for the dummy PCIe device later on.
+         */
+        if (virDomainPCIAddressBusSetModel(&addrs->buses[i],
+                                           VIR_DOMAIN_CONTROLLER_MODEL_PCIE_ROOT_PORT) < 0) {
+            return -1;
+        }
+        addrs->buses[i].flags = VIR_PCI_CONNECT_TYPE_PCIE_TO_PCI_BRIDGE;
+        i++;
+
+        if (virDomainPCIAddressBusSetModel(&addrs->buses[i++],
+                                           VIR_DOMAIN_CONTROLLER_MODEL_PCIE_TO_PCI_BRIDGE) < 0) {
+            return -1;
+        }
+    }
+
     for (; i < addrs->nbuses; i++) {
         if (virDomainPCIAddressBusSetModel(&addrs->buses[i], model) < 0)
             return -1;