You need to sign in or sign up before continuing.
提交 898edc96 编写于 作者: A Andrea Bolognani

conf: Prefer pcie-to-pci-bridge to dmi-to-pci-bridge

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=1520821Signed-off-by: NAndrea Bolognani <abologna@redhat.com>
Reviewed-by: NJohn Ferlan <jferlan@redhat.com>
上级 9985bb46
...@@ -4114,10 +4114,14 @@ ...@@ -4114,10 +4114,14 @@
devices (although libvirt will never auto-assign a PCI device to devices (although libvirt will never auto-assign a PCI device to
a PCIe slot, it will allow manual specification of such an a PCIe slot, it will allow manual specification of such an
assignment). Devices connected to pcie-root cannot be assignment). Devices connected to pcie-root cannot be
hotplugged. In order to make standard PCI slots available on a hotplugged. If traditional PCI devices are present in the guest
system which has a pcie-root controller, a pci controller configuration, a <code>pcie-to-pci-bridge</code> controller will
with <code>model='dmi-to-pci-bridge'</code> is automatically automatically be added: this controller, which plugs into a
added, usually at the defacto standard location of slot=0x1e. 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 dmi-to-pci-bridge controller plugs into a PCIe slot (as provided
by pcie-root), and itself provides 31 standard PCI slots (which by pcie-root), and itself provides 31 standard PCI slots (which
also do not support device hotplug). In order to have also do not support device hotplug). In order to have
......
...@@ -416,6 +416,7 @@ virDomainPCIAddressSetGrow(virDomainPCIAddressSetPtr addrs, ...@@ -416,6 +416,7 @@ virDomainPCIAddressSetGrow(virDomainPCIAddressSetPtr addrs,
size_t i; size_t i;
int model; int model;
bool needDMIToPCIBridge = false; bool needDMIToPCIBridge = false;
bool needPCIeToPCIBridge = false;
add = addr->bus - addrs->nbuses + 1; add = addr->bus - addrs->nbuses + 1;
if (add <= 0) if (add <= 0)
...@@ -436,27 +437,41 @@ virDomainPCIAddressSetGrow(virDomainPCIAddressSetPtr addrs, ...@@ -436,27 +437,41 @@ virDomainPCIAddressSetGrow(virDomainPCIAddressSetPtr addrs,
model = VIR_DOMAIN_CONTROLLER_MODEL_PCI_BRIDGE; model = VIR_DOMAIN_CONTROLLER_MODEL_PCI_BRIDGE;
/* if there aren't yet any buses that will accept a /* if there aren't yet any buses that will accept a
* pci-bridge, and the caller is asking for one, we'll need to * pci-bridge, but we need one for the device's PCI address
* add a dmi-to-pci-bridge first. * 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; needDMIToPCIBridge = true;
needPCIeToPCIBridge = true;
for (i = 0; i < addrs->nbuses; i++) { for (i = 0; i < addrs->nbuses; i++) {
if (addrs->buses[i].flags & VIR_PCI_CONNECT_TYPE_PCI_BRIDGE) { if (addrs->buses[i].flags & VIR_PCI_CONNECT_TYPE_PCI_BRIDGE) {
needDMIToPCIBridge = false; needDMIToPCIBridge = false;
needPCIeToPCIBridge = false;
break; 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 /* We need to add a single pci-bridge to provide the bus
* our legacy PCI device will be plugged into; however, we * our legacy PCI device will be plugged into; however, we
* have also determined that there isn't yet any proper * have also determined that there isn't yet any proper
* place to connect that pci-bridge we're about to add (on * place to connect that pci-bridge we're about to add,
* a system with pcie-root, that "proper place" would be a * which means we're dealing with a pure PCIe guest. We
* dmi-to-pci-bridge". So, to give the pci-bridge a place * need to create a traditional PCI topology, and for that
* to connect, we increase the count of buses to add, * we have two options: dmi-to-pci-bridge + pci-bridge or
* while also incrementing the bus number in the address * pcie-root-port + pcie-to-pci-bridge (the latter of which
* for the device (since the pci-bridge will now be at an * is pretty much a pci-bridge as far as devices attached
* index 1 higher than the caller had anticipated). * 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++; add++;
addr->bus++; addr->bus++;
...@@ -534,6 +549,30 @@ virDomainPCIAddressSetGrow(virDomainPCIAddressSetPtr addrs, ...@@ -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++) { for (; i < addrs->nbuses; i++) {
if (virDomainPCIAddressBusSetModel(&addrs->buses[i], model) < 0) if (virDomainPCIAddressBusSetModel(&addrs->buses[i], model) < 0)
return -1; return -1;
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册