]> git.ipfire.org Git - thirdparty/libvirt.git/commitdiff
conf: add new <target> subelement with chassisNr attribute to <controller>
authorLaine Stump <laine@laine.org>
Wed, 1 Jul 2015 16:47:55 +0000 (12:47 -0400)
committerLaine Stump <laine@laine.org>
Mon, 10 Aug 2015 01:35:00 +0000 (21:35 -0400)
There are some configuration options to some types of pci controllers
that are currently automatically derived from other parts of the
controller's configuration. For example, in qemu a pci-bridge
controller has an option that is called "chassis_nr"; up until now
libvirt has always set chassis_nr to the index of the pci-bridge. So
this:

  <controller type='pci' model='pci-bridge' index='2'/>

will always result in:

  -device pci-bridge,chassis_nr=2,...

on the qemu commandline. In the future we may decide there is a better
way to derive that option, but even in that case we will need for
existing domains to retain the same chassis_nr they were using in the
past - that is something that is visible to the guest so it is part of
the guest ABI and changing it would lead to problems for migrating
guests (or just guests with very picky OSes).

The <target> subelement has been added as a place to put the new
"chassisNr" attribute that will be filled in by libvirt when it
auto-generates the chassisNr; it will be saved in the config, then
reused any time the domain is started:

  <controller type='pci' model='pci-bridge' index='2'>
    <model type='pci-bridge'/>
    <target chassisNr='2'/>
  </controller>

The one oddity of all this is that if the controller configuration
is changed (for example to change the index or the pci address
where the controller is plugged in), the items in <target> will
*not* be re-generated, which might lead to conflict. I can't
really see any way around this, but fortunately if there is a
material conflict qemu will let us know and we will pass that on
to the user.

docs/formatdomain.html.in
docs/schemas/domaincommon.rng
src/conf/domain_conf.c
src/conf/domain_conf.h
tests/qemuxml2argvdata/qemuxml2argv-q35.xml
tests/qemuxml2xmloutdata/qemuxml2xmlout-q35.xml

index 33db6a5c2063298148eea6d77b4c34a3af08ce61..6de40e96833e07be2e88128b545d5da85ecef1ed 100644 (file)
       generated by libvirt. <span class="since">Since 1.2.19 (QEMU
       only).</span>
     </p>
+    <p>
+      PCI controllers also have an optional
+      subelement <code>&lt;target&gt;</code> with the attributes
+      listed below. These are configurable items that 1) are visible
+      to the guest OS so must be preserved for guest ABI
+      compatibility, and 2) are usually left to default values or
+      derived automatically by libvirt. In almost all cases, you
+      should not manually add a <code>&lt;target&gt;</code> subelement
+      to a controller, nor should you modify the values in the those
+      that are automatically generated by
+      libvirt. <span class="since">Since 1.2.19 (QEMU only).</span>
+    </p>
+    <dl>
+      <dt><code>chassisNr</code></dt>
+      <dd>
+        PCI controllers that have attribute model="pci-bridge", can
+        also have a <code>chassisNr</code> attribute in
+        the <code>&lt;target&gt;</code> subelement, which is used to
+        control QEMU's "chassis_nr" option for the pci-bridge device
+        (normally libvirt automatically sets this to the same value as
+        the index attribute of the pci controller). If set, chassisNr
+        must be between 0 and 255.
+      </dd>
+    </dl>
     <p>
       For machine types which provide an implicit PCI bus, the pci-root
       controller with index=0 is auto-added and required to use PCI devices.
index a4c1c9b578d39506bd3e0224b8a64c8bc27870bb..a61e209824b7ee9fdd05a7d9fac65a7198fe4234 100644 (file)
                 <empty/>
               </element>
             </optional>
+            <optional>
+              <element name="target">
+                <optional>
+                  <attribute name='chassisNr'>
+                    <ref name='uint8range'/>
+                  </attribute>
+                </optional>
+                <empty/>
+              </element>
+            </optional>
             <!-- *-root controllers have an optional element "pcihole64"-->
             <choice>
               <group>
index b04f20503eed605be9fdf6c4bef67d2a9e2d3f1d..ec5088c349613716c7aec04c9727f94d6dd5b567 100644 (file)
@@ -1551,6 +1551,8 @@ virDomainControllerDefNew(virDomainControllerType type)
         def->opts.vioserial.vectors = -1;
         break;
     case VIR_DOMAIN_CONTROLLER_TYPE_PCI:
+        def->opts.pciopts.chassisNr = -1;
+        break;
     case VIR_DOMAIN_CONTROLLER_TYPE_IDE:
     case VIR_DOMAIN_CONTROLLER_TYPE_FDC:
     case VIR_DOMAIN_CONTROLLER_TYPE_SCSI:
@@ -7810,6 +7812,8 @@ virDomainControllerDefParseXML(xmlNodePtr node,
     char *max_sectors = NULL;
     bool processedModel = false;
     char *modelName = NULL;
+    bool processedTarget = false;
+    char *chassisNr = NULL;
     xmlNodePtr saved = ctxt->node;
     int rc;
 
@@ -7862,6 +7866,15 @@ virDomainControllerDefParseXML(xmlNodePtr node,
                 }
                 modelName = virXMLPropString(cur, "name");
                 processedModel = true;
+            } else if (xmlStrEqual(cur->name, BAD_CAST "target")) {
+                if (processedTarget) {
+                    virReportError(VIR_ERR_XML_ERROR, "%s",
+                                   _("Multiple <target> elements in "
+                                     "controller definition not allowed"));
+                    goto error;
+                }
+                chassisNr = virXMLPropString(cur, "chassisNr");
+                processedTarget = true;
             }
         }
         cur = cur->next;
@@ -7978,6 +7991,23 @@ virDomainControllerDefParseXML(xmlNodePtr node,
                            modelName);
             goto error;
         }
+        if (chassisNr) {
+            if (virStrToLong_i(chassisNr, NULL, 0,
+                               &def->opts.pciopts.chassisNr) < 0) {
+                virReportError(VIR_ERR_XML_ERROR,
+                               _("Invalid chassisNr '%s' in PCI controller"),
+                               chassisNr);
+                goto error;
+            }
+            if (def->opts.pciopts.chassisNr < 0 ||
+                def->opts.pciopts.chassisNr > 255) {
+                virReportError(VIR_ERR_XML_ERROR,
+                               _("PCI controller chassisNr '%s' out of range "
+                                 "- must be 0-255"),
+                               chassisNr);
+                goto error;
+            }
+        }
         break;
 
     default:
@@ -8004,6 +8034,7 @@ virDomainControllerDefParseXML(xmlNodePtr node,
     VIR_FREE(cmd_per_lun);
     VIR_FREE(max_sectors);
     VIR_FREE(modelName);
+    VIR_FREE(chassisNr);
 
     return def;
 
@@ -19016,7 +19047,7 @@ virDomainControllerDefFormat(virBufferPtr buf,
     const char *type = virDomainControllerTypeToString(def->type);
     const char *model = NULL;
     const char *modelName = NULL;
-    bool pcihole64 = false, pciModel = false;
+    bool pcihole64 = false, pciModel = false, pciTarget = false;
 
     if (!type) {
         virReportError(VIR_ERR_INTERNAL_ERROR,
@@ -19058,13 +19089,15 @@ virDomainControllerDefFormat(virBufferPtr buf,
             pcihole64 = true;
         if (def->opts.pciopts.modelName != VIR_DOMAIN_CONTROLLER_PCI_MODEL_NAME_NONE)
             pciModel = true;
+        if (def->opts.pciopts.chassisNr != -1)
+            pciTarget = true;
         break;
 
     default:
         break;
     }
 
-    if (pciModel ||
+    if (pciModel || pciTarget ||
         def->queues || def->cmd_per_lun || def->max_sectors ||
         virDomainDeviceInfoNeedsFormat(&def->info, flags) || pcihole64) {
         virBufferAddLit(buf, ">\n");
@@ -19081,6 +19114,14 @@ virDomainControllerDefFormat(virBufferPtr buf,
             virBufferAsprintf(buf, "<model name='%s'/>\n", modelName);
         }
 
+        if (pciTarget) {
+            virBufferAddLit(buf, "<target");
+            if (def->opts.pciopts.chassisNr != -1)
+                virBufferAsprintf(buf, " chassisNr='%d'",
+                                  def->opts.pciopts.chassisNr);
+            virBufferAddLit(buf, "/>\n");
+        }
+
         if (def->queues || def->cmd_per_lun || def->max_sectors) {
             virBufferAddLit(buf, "<driver");
             if (def->queues)
index fa9937bdd017eaa72a16ab01d928bc410bf65487..cd0b6a71687ae92d7015e746fa0a4b525b0c57f7 100644 (file)
@@ -812,7 +812,15 @@ struct _virDomainPCIControllerOpts {
      *   ...
      */
     int modelName; /* the exact name of the device in hypervisor */
-};
+
+    /* the following items are attributes of the "target" subelement
+     * of controller type='pci'. They are bits of configuration that
+     * are specified on the qemu commandline and are visible to the
+     * guest OS, so they must be preserved to ensure ABI
+     * compatibility.
+     */
+    int chassisNr; /* used by pci-bridge, -1 == unspecified */
+ };
 
 /* Stores the virtual disk controller configuration */
 struct _virDomainControllerDef {
index 132c15f45274ff2b4c02a3a953d9cdb777652816..0c3da859efd5f1096939b92e57ccf9a74466c013 100644 (file)
@@ -25,6 +25,7 @@
     </controller>
     <controller type='pci' index='2' model='pci-bridge'>
       <model name='pci-bridge'/>
+      <target chassisNr='56'/>
     </controller>
     <video>
       <model type='qxl' ram='65536' vram='32768' vgamem='8192' heads='1'/>
index 4d8fc5f73994ddad8230ab5a33c1aad22b4f809b..abb3a0f5c64183d32f74f40acfab567f2e8ad354 100644 (file)
@@ -25,6 +25,7 @@
     </controller>
     <controller type='pci' index='2' model='pci-bridge'>
       <model name='pci-bridge'/>
+      <target chassisNr='56'/>
     </controller>
     <controller type='sata' index='0'/>
     <video>