diff --git a/docs/formatdomain.html.in b/docs/formatdomain.html.in index c0a265a49f..33db6a5c20 100644 --- a/docs/formatdomain.html.in +++ b/docs/formatdomain.html.in @@ -3043,6 +3043,19 @@ are recent enough to support 64-bit PCI holes, unless this is disabled (set to 0). Since 1.1.2 (QEMU only)

+

+ PCI controllers also have an optional + subelement <model> with an attribute + name. 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 attribute. In almost all cases, you should not + manually add a <model> subelement to a + controller, nor should you modify one that is automatically + generated by libvirt. Since 1.2.19 (QEMU + only). +

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. diff --git a/docs/schemas/domaincommon.rng b/docs/schemas/domaincommon.rng index 1120003518..a4c1c9b578 100644 --- a/docs/schemas/domaincommon.rng +++ b/docs/schemas/domaincommon.rng @@ -1731,6 +1731,19 @@ pci + + + + + + pci-bridge + + i82801b11-bridge + + + + + diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c index 18e626985c..b04f20503e 100644 --- a/src/conf/domain_conf.c +++ b/src/conf/domain_conf.c @@ -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 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, "\n", modelName); + } + if (def->queues || def->cmd_per_lun || def->max_sectors) { virBufferAddLit(buf, "queues) diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h index 698a4d245a..fa9937bdd0 100644 --- a/src/conf/domain_conf.h +++ b/src/conf/domain_conf.h @@ -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.: + * + * + * ... + */ + 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) diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index e5d8437adf..45f42f5020 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -192,6 +192,8 @@ virDomainControllerModelSCSITypeFromString; virDomainControllerModelSCSITypeToString; virDomainControllerModelUSBTypeFromString; virDomainControllerModelUSBTypeToString; +virDomainControllerPCIModelNameTypeFromString; +virDomainControllerPCIModelNameTypeToString; virDomainControllerRemove; virDomainControllerTypeToString; virDomainCpuPlacementModeTypeFromString; diff --git a/tests/qemuxml2argvdata/qemuxml2argv-q35.xml b/tests/qemuxml2argvdata/qemuxml2argv-q35.xml index 05967a409c..132c15f452 100644 --- a/tests/qemuxml2argvdata/qemuxml2argv-q35.xml +++ b/tests/qemuxml2argvdata/qemuxml2argv-q35.xml @@ -20,8 +20,12 @@

- - + + + + + + diff --git a/tests/qemuxml2xmloutdata/qemuxml2xmlout-q35.xml b/tests/qemuxml2xmloutdata/qemuxml2xmlout-q35.xml index 9dd41623ed..4d8fc5f739 100644 --- a/tests/qemuxml2xmloutdata/qemuxml2xmlout-q35.xml +++ b/tests/qemuxml2xmloutdata/qemuxml2xmlout-q35.xml @@ -20,8 +20,12 @@
- - + + + + + +