[libvirt] [rebased][PATCH 0/4] add pci-bridge support

Now, it's impossible to arrange devices into multi-pci-bus, for example: <sound model='ac97'> <address type='pci' domain='0x0000' bus='0x00' slot='0x04' function='0x0'/> </sound> <video> <model type='cirrus' vram='9216' heads='1'/> <address type='pci' domain='0x0000' bus='0x1' slot='0x02' function='0x0'/> </video> libvirt will complain about "bus != 0", fortunately, qemu supports pci-to-pci bridge, if we want to use multi-pci-bus, we can define 2 pci bridge controllers, then attach 1 to the other as a subordinate pci-bus, so, 2 pci-buses appear. for example: <controller type='pci-bridge' index='0'/> <controller type='pci-bridge' index='1'> <address type='pci' domain='0x0000' bus='0x00' slot='0x05' function='0x0'/> </controller> <sound model='ac97'> <address type='pci' domain='0x0000' bus='0x01' slot='0x02' function='0x0'/> </sound> <video> <model type='cirrus' vram='9216' heads='1'/> <address type='pci' domain='0x0000' bus='0x00' slot='0x02' function='0x0'/> </video> src/conf/domain_conf.c | 100 ++++- src/conf/domain_conf.h | 1 + docs/schemas/domaincommon.rng | 1 + src/qemu/qemu_capabilities.c | 2 + src/qemu/qemu_capabilities.h | 1 + src/qemu/qemu_command.c | 70 ++++++++++++++++++++----- 6 files changed, 152 insertions(+), 23 deletions(-)

add a new controller type, then one can define a pci-bridge controller like this: <controller type='pci-bridge' index='0'/> <controller type='pci-bridge' index='1'> <address type='pci' domain='0x0000' bus='0x00' slot='0x05' function='0x0'/> </controller> actually, it works as a pci-bus, so as to support multi-pci-bus via pci-to-pci bridge Signed-off-by: liguang <lig.fnst@cn.fujitsu.com> --- src/conf/domain_conf.c | 5 ++++- src/conf/domain_conf.h | 1 + 2 files changed, 5 insertions(+), 1 deletions(-) diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c index 8dbfb96..16d84b6 100644 --- a/src/conf/domain_conf.c +++ b/src/conf/domain_conf.c @@ -269,7 +269,8 @@ VIR_ENUM_IMPL(virDomainController, VIR_DOMAIN_CONTROLLER_TYPE_LAST, "sata", "virtio-serial", "ccid", - "usb") + "usb", + "pci-bridge") VIR_ENUM_IMPL(virDomainControllerModelSCSI, VIR_DOMAIN_CONTROLLER_MODEL_SCSI_LAST, "auto", @@ -4493,6 +4494,8 @@ virDomainControllerDefParseXML(xmlNodePtr node, goto error; switch (def->type) { + case VIR_DOMAIN_CONTROLLER_TYPE_PCIBRIDGE: + break; case VIR_DOMAIN_CONTROLLER_TYPE_VIRTIO_SERIAL: { char *ports = virXMLPropString(node, "ports"); if (ports) { diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h index 9a9e0b1..a93562d 100644 --- a/src/conf/domain_conf.h +++ b/src/conf/domain_conf.h @@ -661,6 +661,7 @@ enum virDomainControllerType { VIR_DOMAIN_CONTROLLER_TYPE_VIRTIO_SERIAL, VIR_DOMAIN_CONTROLLER_TYPE_CCID, VIR_DOMAIN_CONTROLLER_TYPE_USB, + VIR_DOMAIN_CONTROLLER_TYPE_PCIBRIDGE, VIR_DOMAIN_CONTROLLER_TYPE_LAST }; -- 1.7.2.5

On 01/30/13 03:30, liguang wrote:
@@ -4493,6 +4494,8 @@ virDomainControllerDefParseXML(xmlNodePtr node, goto error;
switch (def->type) { + case VIR_DOMAIN_CONTROLLER_TYPE_PCIBRIDGE: + break; case VIR_DOMAIN_CONTROLLER_TYPE_VIRTIO_SERIAL: { char *ports = virXMLPropString(node, "ports"); if (ports) {
This hunk doesn't do anything and can be dropped.
diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h index 9a9e0b1..a93562d 100644 --- a/src/conf/domain_conf.h +++ b/src/conf/domain_conf.h @@ -661,6 +661,7 @@ enum virDomainControllerType { VIR_DOMAIN_CONTROLLER_TYPE_VIRTIO_SERIAL, VIR_DOMAIN_CONTROLLER_TYPE_CCID, VIR_DOMAIN_CONTROLLER_TYPE_USB, + VIR_DOMAIN_CONTROLLER_TYPE_PCIBRIDGE,
VIR_DOMAIN_CONTROLLER_TYPE_LAST };
VIR_DOMAIN_CONTROLLER_TYPE_PCI_BRIDGE would be nicer. Or maybe just VIR_DOMAIN_CONTROLLER_TYPE_PCI would do. Jan

On Tue, Feb 05, 2013 at 05:53:30PM +0100, Ján Tomko wrote:
On 01/30/13 03:30, liguang wrote:
@@ -4493,6 +4494,8 @@ virDomainControllerDefParseXML(xmlNodePtr node, goto error;
switch (def->type) { + case VIR_DOMAIN_CONTROLLER_TYPE_PCIBRIDGE: + break; case VIR_DOMAIN_CONTROLLER_TYPE_VIRTIO_SERIAL: { char *ports = virXMLPropString(node, "ports"); if (ports) {
This hunk doesn't do anything and can be dropped.
diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h index 9a9e0b1..a93562d 100644 --- a/src/conf/domain_conf.h +++ b/src/conf/domain_conf.h @@ -661,6 +661,7 @@ enum virDomainControllerType { VIR_DOMAIN_CONTROLLER_TYPE_VIRTIO_SERIAL, VIR_DOMAIN_CONTROLLER_TYPE_CCID, VIR_DOMAIN_CONTROLLER_TYPE_USB, + VIR_DOMAIN_CONTROLLER_TYPE_PCIBRIDGE,
VIR_DOMAIN_CONTROLLER_TYPE_LAST };
VIR_DOMAIN_CONTROLLER_TYPE_PCI_BRIDGE would be nicer. Or maybe just VIR_DOMAIN_CONTROLLER_TYPE_PCI would do.
FYI, PCI_BRIDGE is better, because in the future we'll have the option of multiple PCI roots, implying a CONTROLLER_TYPE_PCI_ROOT or something like that Daniel -- |: http://berrange.com -o- http://www.flickr.com/photos/dberrange/ :| |: http://libvirt.org -o- http://virt-manager.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: http://entangle-photo.org -o- http://live.gnome.org/gtk-vnc :|

sorry for late reply. 在 2013-02-05二的 16:56 +0000,Daniel P. Berrange写道:
On Tue, Feb 05, 2013 at 05:53:30PM +0100, Ján Tomko wrote:
On 01/30/13 03:30, liguang wrote:
@@ -4493,6 +4494,8 @@ virDomainControllerDefParseXML(xmlNodePtr node, goto error;
switch (def->type) { + case VIR_DOMAIN_CONTROLLER_TYPE_PCIBRIDGE: + break; case VIR_DOMAIN_CONTROLLER_TYPE_VIRTIO_SERIAL: { char *ports = virXMLPropString(node, "ports"); if (ports) {
This hunk doesn't do anything and can be dropped.
diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h index 9a9e0b1..a93562d 100644 --- a/src/conf/domain_conf.h +++ b/src/conf/domain_conf.h @@ -661,6 +661,7 @@ enum virDomainControllerType { VIR_DOMAIN_CONTROLLER_TYPE_VIRTIO_SERIAL, VIR_DOMAIN_CONTROLLER_TYPE_CCID, VIR_DOMAIN_CONTROLLER_TYPE_USB, + VIR_DOMAIN_CONTROLLER_TYPE_PCIBRIDGE,
VIR_DOMAIN_CONTROLLER_TYPE_LAST };
VIR_DOMAIN_CONTROLLER_TYPE_PCI_BRIDGE would be nicer. Or maybe just VIR_DOMAIN_CONTROLLER_TYPE_PCI would do.
FYI, PCI_BRIDGE is better, because in the future we'll have the option of multiple PCI roots, implying a CONTROLLER_TYPE_PCI_ROOT or something like that
I think what you called "multiple PCI roots" is pci root bridge, isn't it? so, do we need a new controller name?
Daniel

sorry for late reply. 在 2013-02-05二的 17:53 +0100,Ján Tomko写道:
On 01/30/13 03:30, liguang wrote:
@@ -4493,6 +4494,8 @@ virDomainControllerDefParseXML(xmlNodePtr node, goto error;
switch (def->type) { + case VIR_DOMAIN_CONTROLLER_TYPE_PCIBRIDGE: + break; case VIR_DOMAIN_CONTROLLER_TYPE_VIRTIO_SERIAL: { char *ports = virXMLPropString(node, "ports"); if (ports) {
This hunk doesn't do anything and can be dropped.
hmm, it's just for showing, compiler will generate nothing for it. so is it necessary to remove it?
diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h index 9a9e0b1..a93562d 100644 --- a/src/conf/domain_conf.h +++ b/src/conf/domain_conf.h @@ -661,6 +661,7 @@ enum virDomainControllerType { VIR_DOMAIN_CONTROLLER_TYPE_VIRTIO_SERIAL, VIR_DOMAIN_CONTROLLER_TYPE_CCID, VIR_DOMAIN_CONTROLLER_TYPE_USB, + VIR_DOMAIN_CONTROLLER_TYPE_PCIBRIDGE,
VIR_DOMAIN_CONTROLLER_TYPE_LAST };
VIR_DOMAIN_CONTROLLER_TYPE_PCI_BRIDGE would be nicer. Or maybe just VIR_DOMAIN_CONTROLLER_TYPE_PCI would do.
I think we should clarify the difference between PCI and PCIBRIDGE.
Jan

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@cn.fujitsu.com> --- src/qemu/qemu_capabilities.c | 6 ++- src/qemu/qemu_capabilities.h | 1 + src/qemu/qemu_command.c | 70 ++++++++++++++++++++++++++++------------- 3 files changed, 53 insertions(+), 24 deletions(-) diff --git a/src/qemu/qemu_capabilities.c b/src/qemu/qemu_capabilities.c index 29693c3..89ae2aa 100644 --- a/src/qemu/qemu_capabilities.c +++ b/src/qemu/qemu_capabilities.c @@ -200,9 +200,10 @@ VIR_ENUM_IMPL(qemuCaps, QEMU_CAPS_LAST, "vmware-svga", "device-video-primary", "s390-sclp", - + "usb-serial", /* 125 */ - "usb-net", + "usb-serial", + "pci-bridge" ); @@ -1351,6 +1352,7 @@ struct qemuCapsStringFlags qemuCapsObjectTypes[] = { { "cirrus-vga", QEMU_CAPS_DEVICE_CIRRUS_VGA }, { "vmware-svga", QEMU_CAPS_DEVICE_VMWARE_SVGA }, { "usb-serial", QEMU_CAPS_DEVICE_USB_SERIAL}, + { "pci-bridge", QEMU_CAPS_DEVICE_PCI_BRIDGE }, { "usb-net", QEMU_CAPS_DEVICE_USB_NET}, }; diff --git a/src/qemu/qemu_capabilities.h b/src/qemu/qemu_capabilities.h index 5279d07..c50bba8 100644 --- a/src/qemu/qemu_capabilities.h +++ b/src/qemu/qemu_capabilities.h @@ -165,6 +165,7 @@ enum qemuCapsFlags { QEMU_CAPS_SCLP_S390 = 124, /* -device sclp* */ QEMU_CAPS_DEVICE_USB_SERIAL = 125, /* -device usb-serial */ QEMU_CAPS_DEVICE_USB_NET = 126, /* -device usb-net */ + QEMU_CAPS_DEVICE_PCI_BRIDGE = 127, /* -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 f6273c1..57dcb2c 100644 --- a/src/qemu/qemu_command.c +++ b/src/qemu/qemu_command.c @@ -956,13 +956,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, @@ -974,8 +967,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) @@ -994,6 +1003,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; @@ -1002,7 +1025,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, @@ -1037,7 +1061,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; @@ -1753,16 +1778,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", @@ -1777,6 +1792,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 " @@ -1787,11 +1803,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"); @@ -3072,6 +3090,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) @@ -3145,6 +3169,7 @@ qemuBuildControllerDevStr(virDomainDefPtr domainDef, if (qemuBuildDeviceAddressStr(&buf, &def->info, caps) < 0) goto error; +out: if (virBufferError(&buf)) { virReportOOMError(); goto error; @@ -5080,6 +5105,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

On 01/30/13 03:30, liguang wrote:
@@ -974,8 +967,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; +} +
This function is pointless if we're going to auto-add the bridges.
@@ -1002,7 +1025,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, @@ -1037,7 +1061,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;
These two long-line wraps belong to a separate patch.
@@ -3072,6 +3090,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)
We should report an error instead of creating a bridge with name 'pci.0' that can't be used.
+ goto out; + break; case VIR_DOMAIN_CONTROLLER_TYPE_SCSI: model = def->model; if ((qemuSetScsiControllerModel(domainDef, caps, &model)) < 0)
Jan

在 2013-02-05二的 17:53 +0100,Ján Tomko写道:
On 01/30/13 03:30, liguang wrote:
@@ -974,8 +967,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; +} +
This function is pointless if we're going to auto-add the bridges.
Yes, good catch!
@@ -1002,7 +1025,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, @@ -1037,7 +1061,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;
These two long-line wraps belong to a separate patch.
OK, will move to another patch for long line wraps.
@@ -3072,6 +3090,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)
We should report an error instead of creating a bridge with name 'pci.0' that can't be used.
OK, Thanks!
+ goto out; + break; case VIR_DOMAIN_CONTROLLER_TYPE_SCSI: model = def->model; if ((qemuSetScsiControllerModel(domainDef, caps, &model)) < 0)
Jan

Signed-off-by: liguang <lig.fnst@cn.fujitsu.com> --- docs/schemas/domaincommon.rng | 1 + 1 files changed, 1 insertions(+), 0 deletions(-) diff --git a/docs/schemas/domaincommon.rng b/docs/schemas/domaincommon.rng index 049f232..205e93a 100644 --- a/docs/schemas/domaincommon.rng +++ b/docs/schemas/domaincommon.rng @@ -1345,6 +1345,7 @@ <value>sata</value> <value>ccid</value> <value>usb</value> + <value>pci-bridge</value> </choice> </attribute> </optional> -- 1.7.2.5

if some devices specify a pci bus number that haven't been defined by a pci-bridge controller then fill the required correct controller info silently. it based on previous add pci-bridge support patches, https://www.redhat.com/archives/libvir-list/2013-January/msg00577.html Signed-off-by: liguang <lig.fnst@cn.fujitsu.com> --- src/conf/domain_conf.c | 95 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 files changed, 95 insertions(+), 0 deletions(-) diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c index 16d84b6..5e72728 100644 --- a/src/conf/domain_conf.c +++ b/src/conf/domain_conf.c @@ -11815,6 +11815,98 @@ virDomainDefMaybeAddSmartcardController(virDomainDefPtr def) } +static int +virDomainDefMaybeAddPcibridgeController(virDomainDefPtr def) +{ + int i, idx = 0; + + for (i = 0; i < def->nnets; i++) { + if (def->nets[i]->info.type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI) + continue; + idx = def->nets[i]->info.addr.pci.bus; + if (virDomainDefMaybeAddController(def, + VIR_DOMAIN_CONTROLLER_TYPE_PCIBRIDGE, + idx) < 0) + return -1; + } + + for (i = 0; i < def->nsounds; i++) { + if (def->sounds[i]->info.type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI) + continue; + idx = def->sounds[i]->info.addr.pci.bus; + if (virDomainDefMaybeAddController(def, + VIR_DOMAIN_CONTROLLER_TYPE_PCIBRIDGE, + idx) < 0) + return -1; + } + + for (i = 0; i < def->nvideos; i++) { + if (def->videos[i]->info.type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI) + continue; + idx = def->videos[i]->info.addr.pci.bus; + if (virDomainDefMaybeAddController(def, + VIR_DOMAIN_CONTROLLER_TYPE_PCIBRIDGE, + idx) < 0) + return -1; + } + + for (i = 0; i < def->ncontrollers; i++) { + if (def->controllers[i]->info.type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI) + continue; + idx = def->controllers[i]->info.addr.pci.bus; + if (virDomainDefMaybeAddController(def, + VIR_DOMAIN_CONTROLLER_TYPE_PCIBRIDGE, + idx) < 0) + return -1; + } + + for (i = 0; i < def->nfss; i++) { + if (def->fss[i]->info.type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI) + continue; + idx = def->fss[i]->info.addr.pci.bus; + if (virDomainDefMaybeAddController(def, + VIR_DOMAIN_CONTROLLER_TYPE_PCIBRIDGE, + idx) < 0) + return -1; + } + + for (i = 0; i < def->nhostdevs; i++) { + if (def->hostdevs[i]->info->type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI) + continue; + idx = def->hostdevs[i]->info->addr.pci.bus; + if (virDomainDefMaybeAddController(def, + VIR_DOMAIN_CONTROLLER_TYPE_PCIBRIDGE, + idx) < 0) + return -1; + } + + for (i = 0; i < def->ndisks; i++) { + if (def->disks[i]->info.type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI) + continue; + idx = def->disks[i]->info.addr.pci.bus; + if (virDomainDefMaybeAddController(def, + VIR_DOMAIN_CONTROLLER_TYPE_PCIBRIDGE, + idx) < 0) + return -1; + } + + if (def->watchdog->info.type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI) + idx = def->watchdog->info.addr.pci.bus; + if (virDomainDefMaybeAddController(def, + VIR_DOMAIN_CONTROLLER_TYPE_PCIBRIDGE, + idx) < 0) + return -1; + + if (def->memballoon->info.type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI) + idx = def->memballoon->info.addr.pci.bus; + if (virDomainDefMaybeAddController(def, + VIR_DOMAIN_CONTROLLER_TYPE_PCIBRIDGE, + idx) < 0) + return -1; + + return 0; +} + /* * Based on the declared <address/> info for any devices, * add necessary drive controllers which are not already present @@ -11849,6 +11941,9 @@ int virDomainDefAddImplicitControllers(virDomainDefPtr def) if (virDomainDefMaybeAddSmartcardController(def) < 0) return -1; + if (virDomainDefMaybeAddPcibridgeController(def) < 0) + return -1; + return 0; } -- 1.7.2.5

ping ... 在 2013-01-30三的 10:30 +0800,liguang写道:
Now, it's impossible to arrange devices into multi-pci-bus, for example: <sound model='ac97'> <address type='pci' domain='0x0000' bus='0x00' slot='0x04' function='0x0'/> </sound> <video> <model type='cirrus' vram='9216' heads='1'/> <address type='pci' domain='0x0000' bus='0x1' slot='0x02' function='0x0'/> </video> libvirt will complain about "bus != 0", fortunately, qemu supports pci-to-pci bridge, if we want to use multi-pci-bus, we can define 2 pci bridge controllers, then attach 1 to the other as a subordinate pci-bus, so, 2 pci-buses appear. for example: <controller type='pci-bridge' index='0'/> <controller type='pci-bridge' index='1'> <address type='pci' domain='0x0000' bus='0x00' slot='0x05' function='0x0'/> </controller> <sound model='ac97'> <address type='pci' domain='0x0000' bus='0x01' slot='0x02' function='0x0'/> </sound> <video> <model type='cirrus' vram='9216' heads='1'/> <address type='pci' domain='0x0000' bus='0x00' slot='0x02' function='0x0'/> </video>
src/conf/domain_conf.c | 100 ++++- src/conf/domain_conf.h | 1 + docs/schemas/domaincommon.rng | 1 + src/qemu/qemu_capabilities.c | 2 + src/qemu/qemu_capabilities.h | 1 + src/qemu/qemu_command.c | 70 ++++++++++++++++++++----- 6 files changed, 152 insertions(+), 23 deletions(-)
participants (4)
-
Daniel P. Berrange
-
Ján Tomko
-
li guang
-
liguang