]> xenbits.xensource.com Git - libvirt.git/commitdiff
conf: restrict what type of buses will accept a pci-bridge
authorLaine Stump <laine@laine.org>
Sun, 7 Aug 2016 21:13:58 +0000 (17:13 -0400)
committerLaine Stump <laine@laine.org>
Fri, 14 Oct 2016 18:32:42 +0000 (14:32 -0400)
A pci-bridge has *almost* the same rules as a legacy PCI endpoint
device for where it can be automatically connected, and until now both
had been considered identical. There is one pairing that is okay when
specifically requested by the user (i.e. manual assignment), but we
want to avoid it when auto-assigning addresses - plugging a pci-bridge
directly into pcie-root (it is cleaner to plug in a dmi-to-pci-bridge,
then plug the pci-bridge into that).

In order to allow that difference, this patch makes a separate
CONNECT_TYPE for pci-bridge, and uses it to restrict auto-assigned
addresses for pci-bridges to be only on pci-root, pci-expander-bus,
dmi-to-pci-bridge, or on another pci-bridge.

NB: As with other discouraged-but-seem-to-work configurations
(e.g. plugging a legacy PCI device into a pcie-root-port) if someone
*really* wants to, they can still force a pci-bridge to be plugged
into pcie-root (by manually specifying its PCI address.)

src/conf/domain_addr.c
src/conf/domain_addr.h

index 0406b50fdbfaf45243a0a6c54195d22d40a78962..080d8821196c49297a51a4c985d7e7444beda005 100644 (file)
@@ -51,11 +51,7 @@ virDomainPCIControllerModelToConnectType(virDomainControllerModelPCI model)
         return 0;
 
     case VIR_DOMAIN_CONTROLLER_MODEL_PCI_BRIDGE:
-        /* pci-bridge is treated like a standard
-         * PCI endpoint device, because it can plug into any
-         * standard PCI slot (it just can't be hotplugged).
-         */
-        return VIR_PCI_CONNECT_TYPE_PCI_DEVICE;
+        return VIR_PCI_CONNECT_TYPE_PCI_BRIDGE;
 
     case VIR_DOMAIN_CONTROLLER_MODEL_PCI_EXPANDER_BUS:
         return VIR_PCI_CONNECT_TYPE_PCI_EXPANDER_BUS;
@@ -110,6 +106,12 @@ virDomainPCIAddressFlagsCompatible(virPCIDeviceAddressPtr addr,
          */
         if (devFlags & VIR_PCI_CONNECT_HOTPLUGGABLE)
             busFlags |= VIR_PCI_CONNECT_HOTPLUGGABLE;
+        /* if the device is a pci-bridge, allow manually
+         * assigning to any bus that would also accept a
+         * standard PCI device.
+         */
+        if (devFlags & VIR_PCI_CONNECT_TYPE_PCI_BRIDGE)
+            devFlags |= VIR_PCI_CONNECT_TYPE_PCI_DEVICE;
     }
 
     /* If this bus doesn't allow the type of connection (PCI
@@ -138,6 +140,8 @@ virDomainPCIAddressFlagsCompatible(virPCIDeviceAddressPtr addr,
             connectStr = "pci-expander-bus";
         } else if (devFlags & VIR_PCI_CONNECT_TYPE_PCIE_EXPANDER_BUS) {
             connectStr = "pcie-expander-bus";
+        } else if (devFlags & VIR_PCI_CONNECT_TYPE_PCI_BRIDGE) {
+            connectStr = "pci-bridge";
         } else {
             /* this should never happen. If it does, there is a
              * bug in the code that sets the flag bits for devices.
@@ -247,19 +251,22 @@ virDomainPCIAddressBusSetModel(virDomainPCIAddressBusPtr bus,
     case VIR_DOMAIN_CONTROLLER_MODEL_PCI_ROOT:
         bus->flags = (VIR_PCI_CONNECT_HOTPLUGGABLE |
                       VIR_PCI_CONNECT_TYPE_PCI_DEVICE |
+                      VIR_PCI_CONNECT_TYPE_PCI_BRIDGE |
                       VIR_PCI_CONNECT_TYPE_PCI_EXPANDER_BUS);
         bus->minSlot = 1;
         bus->maxSlot = VIR_PCI_ADDRESS_SLOT_LAST;
         break;
     case VIR_DOMAIN_CONTROLLER_MODEL_PCI_BRIDGE:
         bus->flags = (VIR_PCI_CONNECT_HOTPLUGGABLE |
-                      VIR_PCI_CONNECT_TYPE_PCI_DEVICE);
+                      VIR_PCI_CONNECT_TYPE_PCI_DEVICE |
+                      VIR_PCI_CONNECT_TYPE_PCI_BRIDGE);
         bus->minSlot = 1;
         bus->maxSlot = VIR_PCI_ADDRESS_SLOT_LAST;
         break;
     case VIR_DOMAIN_CONTROLLER_MODEL_PCI_EXPANDER_BUS:
         bus->flags = (VIR_PCI_CONNECT_HOTPLUGGABLE |
-                      VIR_PCI_CONNECT_TYPE_PCI_DEVICE);
+                      VIR_PCI_CONNECT_TYPE_PCI_DEVICE |
+                      VIR_PCI_CONNECT_TYPE_PCI_BRIDGE);
         bus->minSlot = 0;
         bus->maxSlot = VIR_PCI_ADDRESS_SLOT_LAST;
         break;
@@ -280,7 +287,8 @@ virDomainPCIAddressBusSetModel(virDomainPCIAddressBusPtr bus,
     case VIR_DOMAIN_CONTROLLER_MODEL_DMI_TO_PCI_BRIDGE:
         /* slots 0 - 31, standard PCI slots,
          * but *not* hot-pluggable */
-        bus->flags = VIR_PCI_CONNECT_TYPE_PCI_DEVICE;
+        bus->flags = (VIR_PCI_CONNECT_TYPE_PCI_DEVICE |
+                      VIR_PCI_CONNECT_TYPE_PCI_BRIDGE);
         bus->minSlot = 0;
         bus->maxSlot = VIR_PCI_ADDRESS_SLOT_LAST;
         break;
index 596cd4cc3d821630d40905543fb9e372073a1fbd..0072a08303fe6fd57f5ae2aa5ecd976c5e94aa96 100644 (file)
@@ -43,6 +43,7 @@ typedef enum {
    VIR_PCI_CONNECT_TYPE_DMI_TO_PCI_BRIDGE = 1 << 6,
    VIR_PCI_CONNECT_TYPE_PCI_EXPANDER_BUS = 1 << 7,
    VIR_PCI_CONNECT_TYPE_PCIE_EXPANDER_BUS = 1 << 8,
+   VIR_PCI_CONNECT_TYPE_PCI_BRIDGE = 1 << 9,
 } virDomainPCIConnectFlags;
 
 /* a combination of all bits that describe the type of connections
@@ -55,7 +56,8 @@ typedef enum {
     VIR_PCI_CONNECT_TYPE_PCIE_ROOT_PORT | \
     VIR_PCI_CONNECT_TYPE_DMI_TO_PCI_BRIDGE | \
     VIR_PCI_CONNECT_TYPE_PCI_EXPANDER_BUS | \
-    VIR_PCI_CONNECT_TYPE_PCIE_EXPANDER_BUS)
+    VIR_PCI_CONNECT_TYPE_PCIE_EXPANDER_BUS | \
+    VIR_PCI_CONNECT_TYPE_PCI_BRIDGE)
 
 /* combination of all bits that could be used to connect a normal
  * endpoint device (i.e. excluding the connection possible between an