<html>
<head>
<meta content="text/html; charset=utf-8" http-equiv="Content-Type">
</head>
<body bgcolor="#FFFFFF" text="#000000">
<div class="moz-cite-prefix">On 10/13/2016 01:43 PM, Laine Stump
wrote:<br>
</div>
<blockquote
cite="mid:d9c5386d-1d01-a4dc-944a-b7fee729d679@laine.org"
type="cite">On 10/11/2016 05:34 AM, Andrea Bolognani wrote:
<br>
<blockquote type="cite">On Mon, 2016-10-10 at 15:43 -0400, Laine
Stump wrote:
<br>
<blockquote type="cite">
<blockquote type="cite">
<blockquote type="cite">3) Although it is strongly
discouraged, it is legal for a pci-bridge
<br>
to be directly plugged into pcie-root, and we don't
want to
<br>
auto-add a dmi-to-pci-bridge if there is already a
pci-bridge
<br>
that's been forced directly into pcie-root.
Finally, although I
<br>
fail to see the utility of it, it is legal to have
something like
<br>
this in the xml:
<br>
<controller type='pci' model='pcie-root'
index='0'/>
<br>
<controller type='pci' model='pci-bridge'
index='2'/>
<br>
and that will lead to an automatically added
dmi-to-pci-bridge at
<br>
index=1 (to give the unaddressed pci-bridge a
proper place to plug
<br>
in):
<br>
<controller type='pci'
model='dmi-to-pci-bridge' index='1'/>
<br>
(for example, see the existing test case
<br>
"usb-controller-default-q35"). This is handled in
<br>
qemuDomainPCIAddressSetCreate() when it's adding in
controllers to
<br>
fill holes in the indexes.
<br>
</blockquote>
I wonder how this "feature" came to be... It seems to be
the
<br>
reason for quite a bit of convoluted code down below, which
<br>
we could avoid if this had never worked at all. As is so
<br>
often the case, too late for that :(
<br>
</blockquote>
Maybe not. The only place I ever saw that was in the above
test case,
<br>
and another named "usb-controller-explicit-q35", and the
author of both
<br>
of those tests was (wait for it!), no, not Albert Einstein.
Andrea
<br>
Bolognani!
<br>
</blockquote>
Oh, *that* guy! It's always *that* guy, isn't it? :P
<br>
<br>
<blockquote type="cite">The only reason it worked in the past
was because we always
<br>
automatically added the dmi-to-pci-bridge very early in the
post-parse
<br>
processing. This implies that any saved config anywhere will
already
<br>
have the necessary dmi-to-pci-bridge at index='1', so we only
need to
<br>
preserve the behavior for new domain definitions that have a
pci-bridge
<br>
at index='2' but nothing at index='1'.
<br>
Since you're the only person documented to have ever created
a config
<br>
like that, and it would only be problematic if someone tried
to create
<br>
another new config, maybe we should just stop accidentally
supporting it
<br>
and count it as a bug that's being fixed. What's your opinion?
<br>
</blockquote>
Given the evidence you're presenting, I'm all for getting
<br>
rid of it, especially since it will make the code below
<br>
much simpler and hence more maintainable.
<br>
<br>
Considering how critical that part of libvirt is, anything
<br>
we can do to make it leaner and meaner is going to be a huge
<br>
win in the long run.
<br>
</blockquote>
<br>
I'm looking back through the code and wondering how to simplify it
- it may be that the alternate method I had initially used (which
failed that one test) is just as complicated as what I have now;
unfortunately I didn't save it.
<br>
</blockquote>
<br>
Okay, now I've reminded myself of what I did. Basically everything
necessary for that is the changes to qemuDomainPCIAddressSetCreate()
dealing with "lowest*Bridge" (see the patch excerpt below). I would
still need to patch this function even if we didn't support
"auto-adding dmi-to-pci-bridge when a pci-bridge is present in the
config", but it would be slightly simpler.<br>
<br>
I'll split it into a separate patch so that it's more apparent, and
we can decide based on that.<br>
<br>
<br>
<div class="moz-cite-prefix">On 09/20/2016 03:14 PM, Laine Stump
wrote:<br>
</div>
<blockquote
cite="mid:1474398864-9039-16-git-send-email-laine@laine.org"
type="cite">
<pre wrap="">diff --git a/src/qemu/qemu_domain_address.c b/src/qemu/qemu_domain_address.c
index 1ff80e3..a9c4c32 100644
--- a/src/qemu/qemu_domain_address.c
+++ b/src/qemu/qemu_domain_address.c
@@ -797,6 +797,11 @@ qemuDomainPCIAddressSetCreate(virDomainDefPtr def,
{
virDomainPCIAddressSetPtr addrs;
size_t i;
+ bool hasPCIeRoot = false;
+ int lowestDMIToPCIBridge = nbuses;
+ int lowestUnaddressedPCIBridge = nbuses;
+ int lowestAddressedPCIBridge = nbuses;
+ virDomainControllerModelPCI defaultModel;
if ((addrs = virDomainPCIAddressSetAlloc(nbuses)) == NULL)
return NULL;
@@ -804,38 +809,84 @@ qemuDomainPCIAddressSetCreate(virDomainDefPtr def,
addrs->nbuses = nbuses;
addrs->dryRun = dryRun;
- /* As a safety measure, set default model='pci-root' for first pci
- * controller and 'pci-bridge' for all subsequent. After setting
- * those defaults, then scan the config and set the actual model
- * for all addrs[idx]->bus that already have a corresponding
- * controller in the config.
- *
- */
- if (nbuses > 0)
- virDomainPCIAddressBusSetModel(&addrs->buses[0],
- VIR_DOMAIN_CONTROLLER_MODEL_PCI_ROOT);
- for (i = 1; i < nbuses; i++) {
- virDomainPCIAddressBusSetModel(&addrs->buses[i],
- VIR_DOMAIN_CONTROLLER_MODEL_PCI_BRIDGE);
- }
-
for (i = 0; i < def->ncontrollers; i++) {
- size_t idx = def->controllers[i]->idx;
+ virDomainControllerDefPtr cont = def->controllers[i];
+ size_t idx = cont->idx;
- if (def->controllers[i]->type != VIR_DOMAIN_CONTROLLER_TYPE_PCI)
+ if (cont->type != VIR_DOMAIN_CONTROLLER_TYPE_PCI)
continue;
if (idx >= addrs->nbuses) {
virReportError(VIR_ERR_INTERNAL_ERROR,
_("Inappropriate new pci controller index %zu "
- "not found in addrs"), idx);
+ "exceeds addrs array length"), idx);
goto error;
}
- if (virDomainPCIAddressBusSetModel(&addrs->buses[idx],
- def->controllers[i]->model) < 0)
+ if (virDomainPCIAddressBusSetModel(&addrs->buses[idx], cont->model) < 0)
goto error;
+
+ /* we'll use all this info later to determine if we need
+ * to add a dmi-to-pci-bridge due to unaddressed pci-bridge controllers
+ */
+ if (cont->model == VIR_DOMAIN_CONTROLLER_MODEL_PCIE_ROOT) {
+ hasPCIeRoot = true;
+ } else if (cont->model ==
+ VIR_DOMAIN_CONTROLLER_MODEL_DMI_TO_PCI_BRIDGE) {
+ if (lowestDMIToPCIBridge > idx)
+ lowestDMIToPCIBridge = idx;
+ } else if (cont->model == VIR_DOMAIN_CONTROLLER_MODEL_PCI_BRIDGE) {
+ if (virDeviceInfoPCIAddressWanted(&cont->info)) {
+ if (lowestUnaddressedPCIBridge > idx)
+ lowestUnaddressedPCIBridge = idx;
+ } else {
+ if (lowestAddressedPCIBridge > idx)
+ lowestAddressedPCIBridge = idx;
+ }
}
+ }
+
+ if (nbuses > 0 && !addrs->buses[0].model) {
+ if (virDomainPCIAddressBusSetModel(&addrs->buses[0],
+ VIR_DOMAIN_CONTROLLER_MODEL_PCI_ROOT) < 0)
+ goto error;
+ }
+
+ /* Now fill in a reasonable model for all the buses in the set
+ * that don't yet have a corresponding controller in the domain
+ * config. In the rare (and actually fairly idiotic, but still
+ * allowed for some reason) case that a domain has 1) a pcie-root
+ * at index 0, 2) <b class="moz-txt-star"><span class="moz-txt-tag">*</span>no<span class="moz-txt-tag">*</span></b> dmi-to-pci-bridge (or pci-bridge that was
+ * manually addressed to sit directly on pcie-root), and 3) does
+ * have an unaddressed pci-bridge at an index > 1, then we need to
+ * add a dmi-to-pci-bridge.
+ */
+
+ if (!hasPCIeRoot)
+ defaultModel = VIR_DOMAIN_CONTROLLER_MODEL_PCI_BRIDGE;
+
+ else if (lowestUnaddressedPCIBridge < MIN(lowestAddressedPCIBridge,
+ lowestDMIToPCIBridge))
+ defaultModel = VIR_DOMAIN_CONTROLLER_MODEL_DMI_TO_PCI_BRIDGE;
+ else
+ defaultModel = VIR_DOMAIN_CONTROLLER_MODEL_PCIE_ROOT_PORT;
+
+ for (i = 1; i < addrs->nbuses; i++) {
+
+ if (addrs->buses[i].model)
+ continue;
+
+ if (virDomainPCIAddressBusSetModel(&addrs->buses[i], defaultModel) < 0)
+ goto error;
+
+ VIR_DEBUG("Auto-adding <controller type='pci' model='%s' index='%zu'/>",
+ virDomainControllerModelPCITypeToString(defaultModel), i);
+ /* only add a single dmi-to-pci-bridge, then add pcie-root-port
+ * for any other unspecified controller indexes.
+ */
+ if (hasPCIeRoot)
+ defaultModel = VIR_DOMAIN_CONTROLLER_MODEL_PCIE_ROOT_PORT;
+ }</pre>
</blockquote>
<p><br>
</p>
<br>
</body>
</html>