]> xenbits.xensource.com Git - libvirt.git/commitdiff
conf: add new <model> subelement with name attribute to <controller>
authorLaine Stump <laine@laine.org>
Thu, 25 Jun 2015 17:30:23 +0000 (13:30 -0400)
committerLaine Stump <laine@laine.org>
Mon, 10 Aug 2015 01:29:27 +0000 (21:29 -0400)
This new subelement is used in PCI controllers: the toplevel
*attribute* "model" of a controller denotes what kind of PCI
controller is being described, e.g. a "dmi-to-pci-bridge",
"pci-bridge", or "pci-root". But in the future there will be different
implementations of some of those types of PCI controllers, which
behave similarly from libvirt's point of view (and so should have the
same model), but use a different device in qemu (and present
themselves as a different piece of hardware in the guest). In an ideal
world we (i.e. "I") would have thought of that back when the pci
controllers were added, and used some sort of type/class/model
notation (where class was used in the way we are now using model, and
model was used for the actual manufacturer's model number of a
particular family of PCI controller), but that opportunity is long
past, so as an alternative, this patch allows selecting a particular
implementation of a pci controller with the "name" attribute of the
<model> subelement, e.g.:

  <controller type='pci' model='dmi-to-pci-bridge' index='1'>
    <model name='i82801b11-bridge'/>
  </controller>

In this case, "dmi-to-pci-bridge" is the kind of controller (one that
has a single PCIe port upstream, and 32 standard PCI ports downstream,
which are not hotpluggable), and the qemu device to be used to
implement this kind of controller is named "i82801b11-bridge".

Implementing the above now will allow us in the future to add a new
kind of dmi-to-pci-bridge that doesn't use qemu's i82801b11-bridge
device, but instead uses something else (which doesn't yet exist, but
qemu people have been discussing it), all without breaking existing
configs.

(note that for the existing "pci-bridge" type of PCI controller, both
the model attribute and <model> name are 'pci-bridge'. This is just a
coincidence, since it turns out that in this case the device name in
qemu really is a generic 'pci-bridge' rather than being the name of
some real-world chip)

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

index c0a265a49f53f9cb131dee216ef9a07e52c464e2..33db6a5c2063298148eea6d77b4c34a3af08ce61 100644 (file)
       are recent enough to support 64-bit PCI holes, unless this is disabled
       (set to 0). <span class="since">Since 1.1.2 (QEMU only)</span>
     </p>
+    <p>
+      PCI controllers also have an optional
+      subelement <code>&lt;model&gt;</code> with an attribute
+      <code>name</code>. The name attribute holds the name of the
+      specific device that qemu is emulating (e.g. "i82801b11-bridge")
+      rather than simply the class of device ("dmi-to-pci-bridge",
+      "pci-bridge"), which is set in the controller element's
+      model <b>attribute</b>.  In almost all cases, you should not
+      manually add a <code>&lt;model&gt;</code> subelement to a
+      controller, nor should you modify one that is automatically
+      generated by libvirt. <span class="since">Since 1.2.19 (QEMU
+      only).</span>
+    </p>
     <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 112000351811576d1f568c337cbbb73778cffe3d..a4c1c9b578d39506bd3e0224b8a64c8bc27870bb 100644 (file)
             <attribute name="type">
               <value>pci</value>
             </attribute>
+            <optional>
+              <element name="model">
+                <attribute name="name">
+                  <choice>
+                    <!-- implementations of 'pci-bridge' -->
+                    <value>pci-bridge</value>
+                    <!-- implementations of 'dmi-to-pci-bridge' -->
+                    <value>i82801b11-bridge</value>
+                  </choice>
+                </attribute>
+                <empty/>
+              </element>
+            </optional>
             <!-- *-root controllers have an optional element "pcihole64"-->
             <choice>
               <group>
index 18e626985c2e62f5ad65d596a7672b465c07bfca..b04f20503eed605be9fdf6c4bef67d2a9e2d3f1d 100644 (file)
@@ -326,6 +326,12 @@ VIR_ENUM_IMPL(virDomainControllerModelPCI, VIR_DOMAIN_CONTROLLER_MODEL_PCI_LAST,
               "pci-bridge",
               "dmi-to-pci-bridge")
 
+VIR_ENUM_IMPL(virDomainControllerPCIModelName,
+              VIR_DOMAIN_CONTROLLER_PCI_MODEL_NAME_LAST,
+              "none",
+              "pci-bridge",
+              "i82801b11-bridge")
+
 VIR_ENUM_IMPL(virDomainControllerModelSCSI, VIR_DOMAIN_CONTROLLER_MODEL_SCSI_LAST,
               "auto",
               "buslogic",
@@ -7802,6 +7808,8 @@ virDomainControllerDefParseXML(xmlNodePtr node,
     char *queues = NULL;
     char *cmd_per_lun = NULL;
     char *max_sectors = NULL;
+    bool processedModel = false;
+    char *modelName = NULL;
     xmlNodePtr saved = ctxt->node;
     int rc;
 
@@ -7845,6 +7853,15 @@ virDomainControllerDefParseXML(xmlNodePtr node,
                 queues = virXMLPropString(cur, "queues");
                 cmd_per_lun = virXMLPropString(cur, "cmd_per_lun");
                 max_sectors = virXMLPropString(cur, "max_sectors");
+            } else if (xmlStrEqual(cur->name, BAD_CAST "model")) {
+                if (processedModel) {
+                    virReportError(VIR_ERR_XML_ERROR, "%s",
+                                   _("Multiple <model> elements in "
+                                     "controller definition not allowed"));
+                    goto error;
+                }
+                modelName = virXMLPropString(cur, "name");
+                processedModel = true;
             }
         }
         cur = cur->next;
@@ -7953,6 +7970,15 @@ virDomainControllerDefParseXML(xmlNodePtr node,
             def->opts.pciopts.pcihole64size = VIR_DIV_UP(bytes, 1024);
         }
         }
+        if (modelName &&
+            (def->opts.pciopts.modelName
+             = virDomainControllerPCIModelNameTypeFromString(modelName)) <= 0) {
+            virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
+                           _("Unknown PCI controller model name '%s'"),
+                           modelName);
+            goto error;
+        }
+        break;
 
     default:
         break;
@@ -7977,6 +8003,7 @@ virDomainControllerDefParseXML(xmlNodePtr node,
     VIR_FREE(queues);
     VIR_FREE(cmd_per_lun);
     VIR_FREE(max_sectors);
+    VIR_FREE(modelName);
 
     return def;
 
@@ -18988,7 +19015,8 @@ virDomainControllerDefFormat(virBufferPtr buf,
 {
     const char *type = virDomainControllerTypeToString(def->type);
     const char *model = NULL;
-    bool pcihole64 = false;
+    const char *modelName = NULL;
+    bool pcihole64 = false, pciModel = false;
 
     if (!type) {
         virReportError(VIR_ERR_INTERNAL_ERROR,
@@ -19028,17 +19056,31 @@ virDomainControllerDefFormat(virBufferPtr buf,
     case VIR_DOMAIN_CONTROLLER_TYPE_PCI:
         if (def->opts.pciopts.pcihole64)
             pcihole64 = true;
+        if (def->opts.pciopts.modelName != VIR_DOMAIN_CONTROLLER_PCI_MODEL_NAME_NONE)
+            pciModel = true;
         break;
 
     default:
         break;
     }
 
-    if (def->queues || def->cmd_per_lun || def->max_sectors ||
+    if (pciModel ||
+        def->queues || def->cmd_per_lun || def->max_sectors ||
         virDomainDeviceInfoNeedsFormat(&def->info, flags) || pcihole64) {
         virBufferAddLit(buf, ">\n");
         virBufferAdjustIndent(buf, 2);
 
+        if (pciModel) {
+            modelName = virDomainControllerPCIModelNameTypeToString(def->opts.pciopts.modelName);
+            if (!modelName) {
+                virReportError(VIR_ERR_INTERNAL_ERROR,
+                               _("unexpected model name value %d"),
+                               def->opts.pciopts.modelName);
+                return -1;
+            }
+            virBufferAsprintf(buf, "<model name='%s'/>\n", modelName);
+        }
+
         if (def->queues || def->cmd_per_lun || def->max_sectors) {
             virBufferAddLit(buf, "<driver");
             if (def->queues)
index 698a4d245aada382aef7c86e17b4b53676d42512..fa9937bdd017eaa72a16ab01d928bc410bf65487 100644 (file)
@@ -756,6 +756,14 @@ typedef enum {
     VIR_DOMAIN_CONTROLLER_MODEL_PCI_LAST
 } virDomainControllerModelPCI;
 
+typedef enum {
+    VIR_DOMAIN_CONTROLLER_PCI_MODEL_NAME_NONE,
+    VIR_DOMAIN_CONTROLLER_PCI_MODEL_NAME_PCI_BRIDGE,
+    VIR_DOMAIN_CONTROLLER_PCI_MODEL_NAME_I82801B11_BRIDGE,
+
+    VIR_DOMAIN_CONTROLLER_PCI_MODEL_NAME_LAST
+} virDomainControllerPCIModelName;
+
 typedef enum {
     VIR_DOMAIN_CONTROLLER_MODEL_SCSI_AUTO,
     VIR_DOMAIN_CONTROLLER_MODEL_SCSI_BUSLOGIC,
@@ -797,6 +805,13 @@ typedef virDomainPCIControllerOpts *virDomainPCIControllerOptsPtr;
 struct _virDomainPCIControllerOpts {
     bool pcihole64;
     unsigned long pcihole64size;
+
+    /* the exact controller name is in the "model" subelement, e.g.:
+     * <controller type='pci' model='pcie-root-port'>
+     *   <model name='ioh3420''/>
+     *   ...
+     */
+    int modelName; /* the exact name of the device in hypervisor */
 };
 
 /* Stores the virtual disk controller configuration */
@@ -2978,6 +2993,7 @@ VIR_ENUM_DECL(virDomainDiskDiscard)
 VIR_ENUM_DECL(virDomainDiskMirrorState)
 VIR_ENUM_DECL(virDomainController)
 VIR_ENUM_DECL(virDomainControllerModelPCI)
+VIR_ENUM_DECL(virDomainControllerPCIModelName)
 VIR_ENUM_DECL(virDomainControllerModelSCSI)
 VIR_ENUM_DECL(virDomainControllerModelUSB)
 VIR_ENUM_DECL(virDomainFS)
index e5d8437adf4d2884bce98f969cc309fe67b3991a..45f42f5020350cf2e0fc90969c300d43af01faa1 100644 (file)
@@ -192,6 +192,8 @@ virDomainControllerModelSCSITypeFromString;
 virDomainControllerModelSCSITypeToString;
 virDomainControllerModelUSBTypeFromString;
 virDomainControllerModelUSBTypeToString;
+virDomainControllerPCIModelNameTypeFromString;
+virDomainControllerPCIModelNameTypeToString;
 virDomainControllerRemove;
 virDomainControllerTypeToString;
 virDomainCpuPlacementModeTypeFromString;
index 05967a409c44be677010870f0cf2840e06c95dc7..132c15f45274ff2b4c02a3a953d9cdb777652816 100644 (file)
       <address type='drive' controller='0' bus='0' target='0' unit='0'/>
     </disk>
     <controller type='pci' index='0' model='pcie-root'/>
-    <controller type='pci' index='1' model='dmi-to-pci-bridge'/>
-    <controller type='pci' index='2' model='pci-bridge'/>
+    <controller type='pci' index='1' model='dmi-to-pci-bridge'>
+      <model name='i82801b11-bridge'/>
+    </controller>
+    <controller type='pci' index='2' model='pci-bridge'>
+      <model name='pci-bridge'/>
+    </controller>
     <video>
       <model type='qxl' ram='65536' vram='32768' vgamem='8192' heads='1'/>
     </video>
index 9dd41623ed924e2c5dd34790f1363f42aae88d98..4d8fc5f73994ddad8230ab5a33c1aad22b4f809b 100644 (file)
       <address type='drive' controller='0' bus='0' target='0' unit='0'/>
     </disk>
     <controller type='pci' index='0' model='pcie-root'/>
-    <controller type='pci' index='1' model='dmi-to-pci-bridge'/>
-    <controller type='pci' index='2' model='pci-bridge'/>
+    <controller type='pci' index='1' model='dmi-to-pci-bridge'>
+      <model name='i82801b11-bridge'/>
+    </controller>
+    <controller type='pci' index='2' model='pci-bridge'>
+      <model name='pci-bridge'/>
+    </controller>
     <controller type='sata' index='0'/>
     <video>
       <model type='qxl' ram='65536' vram='32768' vgamem='8192' heads='1'/>