From 538220c3c42cad0adbd818b6a931c69492a572de Mon Sep 17 00:00:00 2001 From: Laine Stump Date: Sun, 7 Aug 2016 17:13:58 -0400 Subject: [PATCH] conf: restrict what type of buses will accept a pci-bridge 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 | 24 ++++++++++++++++-------- src/conf/domain_addr.h | 4 +++- 2 files changed, 19 insertions(+), 9 deletions(-) diff --git a/src/conf/domain_addr.c b/src/conf/domain_addr.c index 0406b50fdb..080d882119 100644 --- a/src/conf/domain_addr.c +++ b/src/conf/domain_addr.c @@ -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; diff --git a/src/conf/domain_addr.h b/src/conf/domain_addr.h index 596cd4cc3d..0072a08303 100644 --- a/src/conf/domain_addr.h +++ b/src/conf/domain_addr.h @@ -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 -- GitLab