format command line of qemu to add pci-bridge like this: -device pci-bridge. and also add a qemu capability to check if qemu support pci-bridge device Signed-off-by: liguang <lig.fnst@xxxxxxxxxxxxxx> --- src/qemu/qemu_capabilities.c | 2 + src/qemu/qemu_capabilities.h | 1 + src/qemu/qemu_command.c | 70 ++++++++++++++++++++++++++++------------- 3 files changed, 51 insertions(+), 22 deletions(-) diff --git a/src/qemu/qemu_capabilities.c b/src/qemu/qemu_capabilities.c index 104a3f8..90c08b9 100644 --- a/src/qemu/qemu_capabilities.c +++ b/src/qemu/qemu_capabilities.c @@ -200,6 +200,7 @@ VIR_ENUM_IMPL(qemuCaps, QEMU_CAPS_LAST, "cirrus-vga", "vmware-svga", "device-video-primary", + "pci-bridge", ); struct _qemuCaps { @@ -1339,6 +1340,7 @@ struct qemuCapsStringFlags qemuCapsObjectTypes[] = { { "VGA", QEMU_CAPS_DEVICE_VGA }, { "cirrus-vga", QEMU_CAPS_DEVICE_CIRRUS_VGA }, { "vmware-svga", QEMU_CAPS_DEVICE_VMWARE_SVGA }, + { "pci-bridge", QEMU_CAPS_DEVICE_PCI_BRIDGE }, }; diff --git a/src/qemu/qemu_capabilities.h b/src/qemu/qemu_capabilities.h index bf4eef8..64fc73d 100644 --- a/src/qemu/qemu_capabilities.h +++ b/src/qemu/qemu_capabilities.h @@ -162,6 +162,7 @@ enum qemuCapsFlags { QEMU_CAPS_DEVICE_VMWARE_SVGA = 122, /* -device vmware-svga */ QEMU_CAPS_DEVICE_VIDEO_PRIMARY = 123, /* safe to use -device XXX for primary video device */ + QEMU_CAPS_DEVICE_PCI_BRIDGE = 124, /* -device pci-bridge */ QEMU_CAPS_LAST, /* this must always be the last item */ }; diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c index 04a9512..48b4f46 100644 --- a/src/qemu/qemu_command.c +++ b/src/qemu/qemu_command.c @@ -966,13 +966,6 @@ static char *qemuPCIAddressAsString(virDomainDeviceInfoPtr dev) { char *addr; - if (dev->addr.pci.domain != 0 || - dev->addr.pci.bus != 0) { - virReportError(VIR_ERR_INTERNAL_ERROR, "%s", - _("Only PCI domain 0 and bus 0 are available")); - return NULL; - } - if (virAsprintf(&addr, "%d:%d:%d.%d", dev->addr.pci.domain, dev->addr.pci.bus, @@ -984,8 +977,24 @@ static char *qemuPCIAddressAsString(virDomainDeviceInfoPtr dev) return addr; } +static int qemuPciBridgeSupport(virDomainDefPtr def) +{ + int i, c = 0; + + for (i = 0; i < def->ncontrollers; i++) { + virDomainControllerDefPtr controller = def->controllers[i]; + + if (controller->type == VIR_DOMAIN_CONTROLLER_TYPE_PCIBRIDGE) + c++; + } -static int qemuCollectPCIAddress(virDomainDefPtr def ATTRIBUTE_UNUSED, + if (c > 1) + return 0; + else + return -1; +} + +static int qemuCollectPCIAddress(virDomainDefPtr def, virDomainDeviceDefPtr device, virDomainDeviceInfoPtr info, void *opaque) @@ -1004,6 +1013,20 @@ static int qemuCollectPCIAddress(virDomainDefPtr def ATTRIBUTE_UNUSED, return 0; } + if (info->addr.pci.domain != 0) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("Only PCI device addresses with " + "domain=0 are supported")); + return -1; + } + + if (info->addr.pci.bus != 0 && qemuPciBridgeSupport(def) < 0) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("Only PCI device addresses with bus=0 are" + " supported without pci-bridge support")); + return -1; + } + addr = qemuPCIAddressAsString(info); if (!addr) goto cleanup; @@ -1012,7 +1035,8 @@ static int qemuCollectPCIAddress(virDomainDefPtr def ATTRIBUTE_UNUSED, if (info->addr.pci.function != 0) { virReportError(VIR_ERR_XML_ERROR, _("Attempted double use of PCI Address '%s' " - "(may need \"multifunction='on'\" for device on function 0)"), + "(may need \"multifunction='on'\" for " + "device on function 0)"), addr); } else { virReportError(VIR_ERR_XML_ERROR, @@ -1047,7 +1071,8 @@ static int qemuCollectPCIAddress(virDomainDefPtr def ATTRIBUTE_UNUSED, goto cleanup; } - VIR_DEBUG("Remembering PCI addr %s (multifunction=off for function 0)", addr); + VIR_DEBUG("Remembering PCI addr %s (multifunction=off" + " for function 0)", addr); if (virHashAddEntry(addrs->used, addr, addr)) goto cleanup; addr = NULL; @@ -1763,16 +1788,6 @@ qemuBuildDeviceAddressStr(virBufferPtr buf, qemuCapsPtr caps) { if (info->type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI) { - if (info->addr.pci.domain != 0) { - virReportError(VIR_ERR_INTERNAL_ERROR, "%s", - _("Only PCI device addresses with domain=0 are supported")); - return -1; - } - if (info->addr.pci.bus != 0) { - virReportError(VIR_ERR_INTERNAL_ERROR, "%s", - _("Only PCI device addresses with bus=0 are supported")); - return -1; - } if (qemuCapsGet(caps, QEMU_CAPS_PCI_MULTIFUNCTION)) { if (info->addr.pci.function > 7) { virReportError(VIR_ERR_INTERNAL_ERROR, "%s", @@ -1787,6 +1802,7 @@ qemuBuildDeviceAddressStr(virBufferPtr buf, "are supported with this QEMU binary")); return -1; } + if (info->addr.pci.multi == VIR_DEVICE_ADDRESS_PCI_MULTI_ON) { virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", _("'multifunction=on' is not supported with " @@ -1797,11 +1813,13 @@ qemuBuildDeviceAddressStr(virBufferPtr buf, /* XXX * When QEMU grows support for > 1 PCI bus, then pci.0 changes - * to pci.1, pci.2, etc + * to pci.1, pci.2, etc, (e.g. when support pci-to-pci bridge) * When QEMU grows support for > 1 PCI domain, then pci.0 change * to pciNN.0 where NN is the domain number */ - if (qemuCapsGet(caps, QEMU_CAPS_PCI_MULTIBUS)) + if (qemuCapsGet(caps, QEMU_CAPS_DEVICE_PCI_BRIDGE)) + virBufferAsprintf(buf, ",bus=pci.%d", info->addr.pci.bus); + else if (qemuCapsGet(caps, QEMU_CAPS_PCI_MULTIBUS)) virBufferAsprintf(buf, ",bus=pci.0"); else virBufferAsprintf(buf, ",bus=pci"); @@ -3064,6 +3082,12 @@ qemuBuildControllerDevStr(virDomainDefPtr domainDef, int model; switch (def->type) { + case VIR_DOMAIN_CONTROLLER_TYPE_PCIBRIDGE: + virBufferAsprintf(&buf, "pci-bridge,chassis_nr=%d", def->idx+1); + virBufferAsprintf(&buf, ",id=pci.%d", def->idx); + if (def->idx == 0) + goto out; + break; case VIR_DOMAIN_CONTROLLER_TYPE_SCSI: model = def->model; if ((qemuSetScsiControllerModel(domainDef, caps, &model)) < 0) @@ -3137,6 +3161,7 @@ qemuBuildControllerDevStr(virDomainDefPtr domainDef, if (qemuBuildDeviceAddressStr(&buf, &def->info, caps) < 0) goto error; +out: if (virBufferError(&buf)) { virReportOOMError(); goto error; @@ -5033,6 +5058,7 @@ qemuBuildCommandLine(virConnectPtr conn, /* We don't add an explicit IDE or FD controller because the * provided PIIX4 device already includes one. It isn't possible to * remove the PIIX4. */ + VIR_DOMAIN_CONTROLLER_TYPE_PCIBRIDGE, VIR_DOMAIN_CONTROLLER_TYPE_USB, VIR_DOMAIN_CONTROLLER_TYPE_SCSI, VIR_DOMAIN_CONTROLLER_TYPE_SATA, -- 1.7.2.5 -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list