On 07/22/2015 05:38 PM, John Ferlan wrote: > > On 07/17/2015 02:43 PM, Laine Stump wrote: >> This controller can be connected (at domain startup time only - not >> hotpluggable) only to a port on the pcie root complex ("pcie-root" in >> libvirt config), hence the new connect type >> VIR_PCI_CONNECT_TYPE_PCIE_ROOT. It provides a hotpluggable port that >> will accept any PCI or PCIe device. >> >> New attributes must be added to the controller <target> subelement for >> this - chassis and port are guest-visible option values that will be >> set by libvirt with values derived from the controller's index and pci >> address information. >> --- >> docs/formatdomain.html.in | 35 ++++++++++++++++++-- >> docs/schemas/domaincommon.rng | 15 ++++++++- >> src/conf/domain_addr.c | 10 ++++-- >> src/conf/domain_addr.h | 5 ++- >> src/conf/domain_conf.c | 37 ++++++++++++++++++++-- >> src/conf/domain_conf.h | 7 +++- >> src/qemu/qemu_command.c | 1 + >> .../qemuxml2argv-pcie-root-port.xml | 36 +++++++++++++++++++++ >> tests/qemuxml2xmltest.c | 1 + >> 9 files changed, 138 insertions(+), 9 deletions(-) >> create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-pcie-root-port.xml >> > Feels like two things happening in this patch - adding pcie-root and > adding chassis/port attributes. Are they separable - if so this patch > should be further split into two if only to aid bisection Not really. You can't test chassis/port without having a controller type that they are used with. > > >> diff --git a/docs/formatdomain.html.in b/docs/formatdomain.html.in >> index ae0d66a..dcbca75 100644 >> --- a/docs/formatdomain.html.in >> +++ b/docs/formatdomain.html.in >> @@ -3024,10 +3024,11 @@ >> <p> >> PCI controllers have an optional <code>model</code> attribute with >> possible values <code>pci-root</code>, <code>pcie-root</code>, >> - <code>pci-bridge</code>, or <code>dmi-to-pci-bridge</code>. >> + <code>pcie-root-port</code>, <code>pci-bridge</code>, >> + or <code>dmi-to-pci-bridge</code>. >> (pci-root and pci-bridge <span class="since">since 1.0.5</span>, >> pcie-root and dmi-to-pci-bridge <span class="since">since >> - 1.1.2</span>) >> + 1.1.2</span>, pcie-root-port <span class="since">since 1.3.0</span>) > 1.2.18 > >> The root controllers (<code>pci-root</code> and <code>pcie-root</code>) >> have an optional <code>pcihole64</code> element specifying how big >> (in kilobytes, or in the unit specified by <code>pcihole64</code>'s >> @@ -3070,6 +3071,25 @@ >> (normally libvirt automatically sets this to the same value as >> the index attribute of the pci controller). >> </dd> >> + <dt><code>chassis</code></dt> >> + <dd> >> + pcie-root-port controllers can also have >> + a <code>chassis</code> attribute in >> + the <code><model></code> subelement, which is used to >> + control QEMU's "chassis" option for the device (normally >> + libvirt automatically sets this to the same value as the index >> + attribute of the pci controller). >> + </dd> >> + <dt><code>port</code></dt> >> + <dd> >> + pcie-root-port controllers can also have a <code>port</code> >> + attribute in the <code><model></code> subelement, which >> + is used to control QEMU's "port" option for the device >> + (normally libvirt automatically sets this based on the PCI >> + address where the root port is connected using the formula >> + (slot << 3) + function (although this could change in >> + the future). >> + </dd> > I see from the code that this is printed as a hex number - something we > should perhaps document here. I always just figured "a number is a number, and it will be converted as appropriate". I see that bus/slot in PCI addresses are documented as "a hex number", but they have a different type in the RNG which forces input as a hex number (with leading 0x). Interestingly, the parser doesn't enforce that (I think the RNG should lighten up and the parser should stay the same). >> </dl> >> <p> >> For machine types which provide an implicit PCI bus, the pci-root >> @@ -3116,6 +3136,17 @@ >> auto-determined by libvirt will be placed on this pci-bridge >> device. (<span class="since">since 1.1.2</span>). >> </p> >> + <p> >> + Domains with an implicit pcie-root can also add controllers >> + with <code>model='pcie-root-port'</code>. This is a simple type of >> + bridge device that can connect only to one of the 31 slots on >> + the pcie-root bus on its upstream side, and makes a single >> + (PCIe, hotpluggable) port (at slot='0') available on the >> + downstream side. This controller can be used to provide a single >> + slot to later hotplug a PCIe device (but is not itself >> + hotpluggable - it must be in the configuration when the domain >> + is started). (<span class="since">since 1.3.0</span>) > 1.2.18 > > > Seems to me we should state in some way that it's only supported on q35 > machine for qemu 1.2.2 and beyond (where 1.2.2 is the patch 8 comment) > > If added to other machine types, I assume it's ignored... There will be an error because there won't be any bus to plug it into. If qemu came up with another machinetype that had a pcie-root and a device called ioh3420, we *would* automatically support it. Also, I'm not sure about the "qemu 1.2.2" statement. From my point of view "it's in the versions that it's in". I suppose I can add that though. > >> + </p> >> <pre> >> ... >> <devices> >> diff --git a/docs/schemas/domaincommon.rng b/docs/schemas/domaincommon.rng >> index 1b1f592..0efa0f0 100644 >> --- a/docs/schemas/domaincommon.rng >> +++ b/docs/schemas/domaincommon.rng >> @@ -1739,6 +1739,8 @@ >> <value>pci-bridge</value> >> <!-- implementations of 'dmi-to-pci-bridge' --> >> <value>i82801b11-bridge</value> >> + <!-- implementations of 'pcie-root-port' --> >> + <value>ioh3420</value> >> </choice> >> </attribute> >> <empty/> >> @@ -1751,7 +1753,17 @@ >> <ref name='uint8range'/> >> </attribute> >> </optional> >> - <empty/> >> + <optional> >> + <attribute name="chassis"> >> + <ref name='uint8range'/> >> + </attribute> >> + </optional> >> + <optional> >> + <attribute name="port"> >> + <ref name='uint8range'/> >> + </attribute> >> + </optional> >> + <empty/> > Similar to chassisNr - defined in domain_conf.h as 'int's, so limiting > in RNG to 0 to 255 inclusive doesn't seem right. But it *is* right. The registers in the emulated hardware that hold these values are 8 bits, but the struct in libvirt needs to have an int so that (internally only) it can hold -1 to indicate "unspecified". I've added a check on the parsed values to assure that these are all 0 - 255 only. > > Unless of course it is right in which case domain_conf needs changes... The parser needs to check limits, and it now does. > > FWIW: A change to the .xml in this patch and the .args file in the > following patch to change the port to 0x11a "failed" schematest, but > passed libvirt's other tests Not any more :-) > >> </element> >> </optional> >> <!-- *-root controllers have an optional element "pcihole64"--> >> @@ -1774,6 +1786,7 @@ >> <choice> >> <value>pci-bridge</value> >> <value>dmi-to-pci-bridge</value> >> + <value>pcie-root-port</value> >> </choice> >> </attribute> >> </group> >> diff --git a/src/conf/domain_addr.c b/src/conf/domain_addr.c >> index bc09279..fba0eff 100644 >> --- a/src/conf/domain_addr.c >> +++ b/src/conf/domain_addr.c >> @@ -183,9 +183,9 @@ virDomainPCIAddressBusSetModel(virDomainPCIAddressBusPtr bus, >> case VIR_DOMAIN_CONTROLLER_MODEL_PCIE_ROOT: >> /* slots 1 - 31, no hotplug, PCIe only unless the address was >> * specified in user config *and* the particular device being >> - * attached also allows it >> + * attached also allows it. >> */ >> - bus->flags = VIR_PCI_CONNECT_TYPE_PCIE; >> + bus->flags = VIR_PCI_CONNECT_TYPE_PCIE | VIR_PCI_CONNECT_TYPE_PCIE_ROOT; >> bus->minSlot = 1; >> bus->maxSlot = VIR_PCI_ADDRESS_SLOT_LAST; >> break; >> @@ -196,6 +196,12 @@ virDomainPCIAddressBusSetModel(virDomainPCIAddressBusPtr bus, >> bus->minSlot = 1; >> bus->maxSlot = VIR_PCI_ADDRESS_SLOT_LAST; >> break; >> + case VIR_DOMAIN_CONTROLLER_MODEL_PCIE_ROOT_PORT: >> + /* provides one slot which is pcie and hotpluggable */ >> + bus->flags = VIR_PCI_CONNECT_TYPE_PCIE | VIR_PCI_CONNECT_HOTPLUGGABLE; >> + bus->minSlot = 0; >> + bus->maxSlot = 0; >> + break; >> default: >> virReportError(VIR_ERR_INTERNAL_ERROR, >> _("Invalid PCI controller model %d"), model); >> diff --git a/src/conf/domain_addr.h b/src/conf/domain_addr.h >> index dcfd2e5..2a0ff96 100644 >> --- a/src/conf/domain_addr.h >> +++ b/src/conf/domain_addr.h >> @@ -39,6 +39,8 @@ typedef enum { >> /* PCI devices can connect to this bus */ >> VIR_PCI_CONNECT_TYPE_PCIE = 1 << 3, >> /* PCI Express devices can connect to this bus */ >> + VIR_PCI_CONNECT_TYPE_PCIE_ROOT = 1 << 4, >> + /* for devices that can only connect to pcie-root (i.e. root-port) */ >> } virDomainPCIConnectFlags; >> >> typedef struct { >> @@ -70,7 +72,8 @@ typedef virDomainPCIAddressSet *virDomainPCIAddressSetPtr; >> * allowed, e.g. PCI, PCIe, switch >> */ >> # define VIR_PCI_CONNECT_TYPES_MASK \ >> - (VIR_PCI_CONNECT_TYPE_PCI | VIR_PCI_CONNECT_TYPE_PCIE) >> + (VIR_PCI_CONNECT_TYPE_PCI | VIR_PCI_CONNECT_TYPE_PCIE | \ >> + VIR_PCI_CONNECT_TYPE_PCIE_ROOT) >> >> /* combination of all bits that could be used to connect a normal >> * endpoint device (i.e. excluding the connection possible between an >> diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c >> index 17526d4..e02c861 100644 >> --- a/src/conf/domain_conf.c >> +++ b/src/conf/domain_conf.c >> @@ -324,7 +324,8 @@ VIR_ENUM_IMPL(virDomainControllerModelPCI, VIR_DOMAIN_CONTROLLER_MODEL_PCI_LAST, >> "pci-root", >> "pcie-root", >> "pci-bridge", >> - "dmi-to-pci-bridge") >> + "dmi-to-pci-bridge", >> + "pcie-root-port") >> >> VIR_ENUM_IMPL(virDomainControllerModelSCSI, VIR_DOMAIN_CONTROLLER_MODEL_SCSI_LAST, >> "auto", >> @@ -1545,6 +1546,8 @@ virDomainControllerDefNew(virDomainControllerType type) >> break; >> case VIR_DOMAIN_CONTROLLER_TYPE_PCI: >> def->opts.pciopts.chassisNr = -1; >> + def->opts.pciopts.chassis = -1; >> + def->opts.pciopts.port = -1; >> break; >> case VIR_DOMAIN_CONTROLLER_TYPE_IDE: >> case VIR_DOMAIN_CONTROLLER_TYPE_FDC: >> @@ -7641,6 +7644,8 @@ virDomainControllerDefParseXML(xmlNodePtr node, >> char *max_sectors = NULL; >> char *guestModel = NULL; >> char *chassisNr = NULL; >> + char *chassis = NULL; >> + char *port = NULL; >> xmlNodePtr saved = ctxt->node; >> int rc; >> >> @@ -7692,6 +7697,10 @@ virDomainControllerDefParseXML(xmlNodePtr node, >> } else if (xmlStrEqual(cur->name, BAD_CAST "target")) { >> if (!chassisNr) >> chassisNr = virXMLPropString(cur, "chassisNr"); >> + if (!chassis) >> + chassis = virXMLPropString(cur, "chassis"); >> + if (!port) >> + port = virXMLPropString(cur, "port"); > Similar to earlier comments - RNG doesn't allow multiple entries, so is > it necessary to check !chassis and !port? E.G. if they're already > found, then it probably should be an error or at least documented only > the first is consumed. Since the RNG isn't always referenced, we need to do *something*. I've actually changed it to have a "processedTarget" boolean that is set when <target> has been seen once. If it's seen again, an error will be logged. > > Also if there is supposed to be a range, it needs to be checked here. See above. > That is the RNG expects 0 to 255 inclusive, but that's not handled here. > >> } >> } >> cur = cur->next; >> @@ -7811,6 +7820,20 @@ virDomainControllerDefParseXML(xmlNodePtr node, >> chassisNr); >> goto error; >> } >> + if (chassis && virStrToLong_i(chassis, NULL, 0, >> + &def->opts.pciopts.chassis) < 0) { >> + virReportError(VIR_ERR_XML_ERROR, >> + _("Invalid chassis '%s' in PCI controller"), >> + chassis); >> + goto error; >> + } >> + if (port && virStrToLong_i(port, NULL, 0, >> + &def->opts.pciopts.port) < 0) { >> + virReportError(VIR_ERR_XML_ERROR, >> + _("Invalid port '%s' in PCI controller"), >> + port); >> + goto error; >> + } >> break; >> >> default: >> @@ -7838,6 +7861,8 @@ virDomainControllerDefParseXML(xmlNodePtr node, >> VIR_FREE(max_sectors); >> VIR_FREE(guestModel); >> VIR_FREE(chassisNr); >> + VIR_FREE(chassis); >> + VIR_FREE(port); >> >> return def; >> >> @@ -18889,7 +18914,9 @@ virDomainControllerDefFormat(virBufferPtr buf, >> pcihole64 = true; >> if (def->opts.pciopts.type) >> pciModel = true; >> - if (def->opts.pciopts.chassisNr != -1) >> + if (def->opts.pciopts.chassisNr != -1 || >> + def->opts.pciopts.chassis != -1 || >> + def->opts.pciopts.port != -1) >> pciTarget = true; >> break; >> >> @@ -18914,6 +18941,12 @@ virDomainControllerDefFormat(virBufferPtr buf, >> if (def->opts.pciopts.chassisNr != -1) >> virBufferAsprintf(buf, " chassisNr='%d'", >> def->opts.pciopts.chassisNr); >> + if (def->opts.pciopts.chassis != -1) >> + virBufferAsprintf(buf, " chassis='%d'", >> + def->opts.pciopts.chassis); >> + if (def->opts.pciopts.port != -1) >> + virBufferAsprintf(buf, " port='0x%x'", >> + def->opts.pciopts.port); > OH... And this is what I get for not reading ahead... So now my previous > comments are unfounded... <sigh> Which comments are those? There was a comment in a previous patch about not needing the boolean "pciTarget" that wasn't valid, but your comments about the range were certainly valid. > > Also I see that ports is saved as a hex value - that's something we > should document in formatdomain and I noted above. > > ACK as I trust you can handle the nits and range checks that may be > necessary. > > John > -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list