render / rpms / libvirt

Forked from rpms/libvirt 11 months ago
Clone
Laine Stump 38c4b7
From 3962198d82ab90d21144479c1d822db5d1f640a4 Mon Sep 17 00:00:00 2001
Laine Stump 38c4b7
From: Laine Stump <laine@laine.org>
Laine Stump 38c4b7
Date: Wed, 28 Sep 2011 14:19:59 -0400
Laine Stump 38c4b7
Subject: [PATCH 2/2] qemu: make PCI multifunction support more manual
Laine Stump 38c4b7
Laine Stump 38c4b7
(This is a merge of cherry-picking upstream commits
Laine Stump 38c4b7
c329db7180d77c8077b9f9cd167a71d7f347227a and
Laine Stump 38c4b7
be7bc4d5ccb502c2da85d3b3db804fd53b70449e (a one liner). There were no
Laine Stump 38c4b7
merge conflicts.)
Laine Stump 38c4b7
Laine Stump 38c4b7
When support for was added for PCI multifunction cards (in commit
Laine Stump 38c4b7
9f8baf, first included in libvirt 0.9.3), it was done by always
Laine Stump 38c4b7
turning on the multifunction bit for all PCI devices. Since that time
Laine Stump 38c4b7
it has been realized that this is not an ideal solution, and that the
Laine Stump 38c4b7
multifunction bit must be selectively turned on. For example, see
Laine Stump 38c4b7
Laine Stump 38c4b7
  https://bugzilla.redhat.com/show_bug.cgi?id=742836
Laine Stump 38c4b7
Laine Stump 38c4b7
and the discussion before and after
Laine Stump 38c4b7
Laine Stump 38c4b7
  https://www.redhat.com/archives/libvir-list/2011-September/msg01036.html
Laine Stump 38c4b7
Laine Stump 38c4b7
This patch modifies multifunction support so that the multifunction=on
Laine Stump 38c4b7
option is only added to the qemu commandline for a device if its PCI
Laine Stump 38c4b7
<address> definition has the attribute "multifunction='on'", e.g.:
Laine Stump 38c4b7
Laine Stump 38c4b7
  
Laine Stump 38c4b7
           slot='0x04' function='0x0' multifunction='on'/>
Laine Stump 38c4b7
Laine Stump 38c4b7
In practice, the multifunction bit should only be turned on if
Laine Stump 38c4b7
function='0' AND other functions will be used in the same slot - it
Laine Stump 38c4b7
usually isn't needed for functions 1-7 (although there are apparently
Laine Stump 38c4b7
some exceptions, e.g. the Intel X53 according to the QEMU source
Laine Stump 38c4b7
code), and should never be set if only function 0 will be used in the
Laine Stump 38c4b7
slot. The test cases have been changed accordingly to illustrate.
Laine Stump 38c4b7
Laine Stump 38c4b7
With this patch in place, if a user attempts to assign multiple
Laine Stump 38c4b7
functions in a slot without setting the multifunction bit for function
Laine Stump 38c4b7
0, libvirt will issue an error when the domain is defined, and the
Laine Stump 38c4b7
define operation will fail. In the future, we may decide to detect
Laine Stump 38c4b7
this situation and automatically add multifunction=on to avoid the
Laine Stump 38c4b7
error; even then it will still be useful to have a manual method of
Laine Stump 38c4b7
turning on multifunction since, as stated above, there are some
Laine Stump 38c4b7
devices that excpect it to be turned on for all functions in a slot.
Laine Stump 38c4b7
Laine Stump 38c4b7
A side effect of this patch is that attempts to use the same PCI
Laine Stump 38c4b7
address for two different devices will now log an error (previously
Laine Stump 38c4b7
this would cause the domain define operation to fail, but there would
Laine Stump 38c4b7
be no log message generated). Because the function doing this log was
Laine Stump 38c4b7
almost completely rewritten, I didn't think it worthwhile to make a
Laine Stump 38c4b7
separate patch for that fix (the entire patch would immediately be
Laine Stump 38c4b7
obsoleted).
Laine Stump 38c4b7
---
Laine Stump 38c4b7
 docs/formatdomain.html.in                          |   29 +++++--
Laine Stump 38c4b7
 docs/schemas/domaincommon.rng                      |    8 ++
Laine Stump 38c4b7
 src/conf/domain_conf.c                             |   22 +++++-
Laine Stump 38c4b7
 src/conf/domain_conf.h                             |   11 +++-
Laine Stump 38c4b7
 src/libvirt_private.syms                           |    2 +
Laine Stump 38c4b7
 src/qemu/qemu_command.c                            |   81 ++++++++++++++++----
Laine Stump 38c4b7
 .../qemuxml2argv-multifunction-pci-device.args     |   18 ++--
Laine Stump 38c4b7
 .../qemuxml2argv-multifunction-pci-device.xml      |    6 +-
Laine Stump 38c4b7
 .../qemuxml2argv-usb-ich9-companion.args           |   15 ++--
Laine Stump 38c4b7
 .../qemuxml2argv-usb-ich9-companion.xml            |    2 +-
Laine Stump 38c4b7
 .../qemuxml2argv-usb-ich9-ehci-addr.args           |    7 ++-
Laine Stump 38c4b7
 .../qemuxml2argv-usb-piix3-controller.args         |    7 ++-
Laine Stump 38c4b7
 tests/qemuxml2argvdata/qemuxml2argv-usb-redir.args |   10 +-
Laine Stump 38c4b7
 tests/qemuxml2argvdata/qemuxml2argv-usb-redir.xml  |    2 +-
Laine Stump 38c4b7
 tests/qemuxml2argvdata/qemuxml2argv-usb1-usb2.args |   25 ++++---
Laine Stump 38c4b7
 tests/qemuxml2argvdata/qemuxml2argv-usb1-usb2.xml  |    4 +-
Laine Stump 38c4b7
 16 files changed, 183 insertions(+), 66 deletions(-)
Laine Stump 38c4b7
Laine Stump 38c4b7
diff --git a/docs/formatdomain.html.in b/docs/formatdomain.html.in
Laine Stump 38c4b7
index 0a7abaf..390476d 100644
Laine Stump 38c4b7
--- a/docs/formatdomain.html.in
Laine Stump 38c4b7
+++ b/docs/formatdomain.html.in
Laine Stump 38c4b7
@@ -1113,10 +1113,14 @@
Laine Stump 38c4b7
         The type attribute is mandatory, and is typically
Laine Stump 38c4b7
         "pci" or "drive".  For a "pci" controller, additional
Laine Stump 38c4b7
         attributes for bus, slot,
Laine Stump 38c4b7
-        and function must be present, as well as an
Laine Stump 38c4b7
-        optional domain.  For a "drive" controller,
Laine Stump 38c4b7
-        additional attributes controller, bus,
Laine Stump 38c4b7
+        and function must be present, as well as
Laine Stump 38c4b7
+        optional domain and multifunction.
Laine Stump 38c4b7
+        Multifunction defaults to 'off'; any other value requires
Laine Stump 38c4b7
+        QEMU 0.1.3 and libvirt 0.9.7.  For a
Laine Stump 38c4b7
+        "drive" controller, additional attributes
Laine Stump 38c4b7
+        controller, bus,
Laine Stump 38c4b7
         and unit are available, each defaulting to 0.
Laine Stump 38c4b7
+
Laine Stump 38c4b7
       
Laine Stump 38c4b7
     
Laine Stump 38c4b7
 
Laine Stump 38c4b7
@@ -1293,7 +1297,7 @@
Laine Stump 38c4b7
     </controller>
Laine Stump 38c4b7
     <controller type='usb' index='0' model='ich9-uhci1'>
Laine Stump 38c4b7
       <master startport='0'/>
Laine Stump 38c4b7
-      <address type='pci' domain='0' bus='0' slot='4' function='0'/>
Laine Stump 38c4b7
+      <address type='pci' domain='0' bus='0' slot='4' function='0' multifunction='on'/>
Laine Stump 38c4b7
     </controller>
Laine Stump 38c4b7
     ...
Laine Stump 38c4b7
   </devices>
Laine Stump 38c4b7
@@ -1413,10 +1417,16 @@
Laine Stump 38c4b7
       with virsh nodedev-list. The
Laine Stump 38c4b7
       bus attribute allows the hexadecimal values 0 to ff, the
Laine Stump 38c4b7
       slot attribute allows the hexadecimal values 0 to 1f, and
Laine Stump 38c4b7
-      the function attribute allows the hexadecimal values 0 to
Laine Stump 38c4b7
-      7. There is also an optional domain attribute for the
Laine Stump 38c4b7
-      PCI domain, with hexadecimal values 0 to ffff, but it is currently
Laine Stump 38c4b7
-      not used by qemu.
Laine Stump 38c4b7
+      the function attribute allows the hexadecimal values 0 to 7.
Laine Stump 38c4b7
+      The multifunction attribute controls turning on the
Laine Stump 38c4b7
+      multifunction bit for a particular slot/function in the PCI
Laine Stump 38c4b7
+      control registersince 0.9.7, requires QEMU
Laine Stump 38c4b7
+      0.13. multifunction defaults to 'off', but
Laine Stump 38c4b7
+      should be set to 'on' for function 0 of a slot that will have
Laine Stump 38c4b7
+      multiple functions used.
Laine Stump 38c4b7
+      There is also an optional domain attribute for
Laine Stump 38c4b7
+      the PCI domain, with hexadecimal values 0 to ffff, but it is
Laine Stump 38c4b7
+      currently not used by qemu.
Laine Stump 38c4b7
     
Laine Stump 38c4b7
 
Laine Stump 38c4b7
     

Redirected devices

Laine Stump 38c4b7
@@ -1584,7 +1594,8 @@
Laine Stump 38c4b7
       the interface to a particular pci slot, with
Laine Stump 38c4b7
       attribute type='pci' and additional
Laine Stump 38c4b7
       attributes domain, bus, slot,
Laine Stump 38c4b7
-      and function as appropriate.
Laine Stump 38c4b7
+      function, and multifunction
Laine Stump 38c4b7
+      since 0.9.7, requires QEMU 0.13 as appropriate.
Laine Stump 38c4b7
     

Laine Stump 38c4b7
 
Laine Stump 38c4b7
     
Virtual network
Laine Stump 38c4b7
diff --git a/docs/schemas/domaincommon.rng b/docs/schemas/domaincommon.rng
Laine Stump 38c4b7
index d0da41c..9f8d292 100644
Laine Stump 38c4b7
--- a/docs/schemas/domaincommon.rng
Laine Stump 38c4b7
+++ b/docs/schemas/domaincommon.rng
Laine Stump 38c4b7
@@ -2106,6 +2106,14 @@
Laine Stump 38c4b7
     <attribute name="function">
Laine Stump 38c4b7
       <ref name="pciFunc"/>
Laine Stump 38c4b7
     </attribute>
Laine Stump 38c4b7
+    <optional>
Laine Stump 38c4b7
+      <attribute name="multifunction">
Laine Stump 38c4b7
+        <choice>
Laine Stump 38c4b7
+          <value>on</value>
Laine Stump 38c4b7
+          <value>off</value>
Laine Stump 38c4b7
+        </choice>
Laine Stump 38c4b7
+      </attribute>
Laine Stump 38c4b7
+    </optional>
Laine Stump 38c4b7
   </define>
Laine Stump 38c4b7
   <define name="driveaddress">
Laine Stump 38c4b7
     <optional>
Laine Stump 38c4b7
diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
Laine Stump 38c4b7
index 7463d7c..318f523 100644
Laine Stump 38c4b7
--- a/src/conf/domain_conf.c
Laine Stump 38c4b7
+++ b/src/conf/domain_conf.c
Laine Stump 38c4b7
@@ -138,6 +138,12 @@ VIR_ENUM_IMPL(virDomainDeviceAddress, VIR_DOMAIN_DEVICE_ADDRESS_TYPE_LAST,
Laine Stump 38c4b7
               "ccid",
Laine Stump 38c4b7
               "usb")
Laine Stump 38c4b7
 
Laine Stump 38c4b7
+VIR_ENUM_IMPL(virDomainDeviceAddressPciMulti,
Laine Stump 38c4b7
+              VIR_DOMAIN_DEVICE_ADDRESS_PCI_MULTI_LAST,
Laine Stump 38c4b7
+              "default",
Laine Stump 38c4b7
+              "on",
Laine Stump 38c4b7
+              "off")
Laine Stump 38c4b7
+
Laine Stump 38c4b7
 VIR_ENUM_IMPL(virDomainDisk, VIR_DOMAIN_DISK_TYPE_LAST,
Laine Stump 38c4b7
               "block",
Laine Stump 38c4b7
               "file",
Laine Stump 38c4b7
@@ -1645,6 +1651,10 @@ virDomainDeviceInfoFormat(virBufferPtr buf,
Laine Stump 38c4b7
                           info->addr.pci.bus,
Laine Stump 38c4b7
                           info->addr.pci.slot,
Laine Stump 38c4b7
                           info->addr.pci.function);
Laine Stump 38c4b7
+        if (info->addr.pci.multi) {
Laine Stump 38c4b7
+           virBufferAsprintf(buf, " multifunction='%s'",
Laine Stump 38c4b7
+                             virDomainDeviceAddressPciMultiTypeToString(info->addr.pci.multi));
Laine Stump 38c4b7
+        }
Laine Stump 38c4b7
         break;
Laine Stump 38c4b7
 
Laine Stump 38c4b7
     case VIR_DOMAIN_DEVICE_ADDRESS_TYPE_DRIVE:
Laine Stump 38c4b7
@@ -1689,7 +1699,7 @@ static int
Laine Stump 38c4b7
 virDomainDevicePCIAddressParseXML(xmlNodePtr node,
Laine Stump 38c4b7
                                   virDomainDevicePCIAddressPtr addr)
Laine Stump 38c4b7
 {
Laine Stump 38c4b7
-    char *domain, *slot, *bus, *function;
Laine Stump 38c4b7
+    char *domain, *slot, *bus, *function, *multi;
Laine Stump 38c4b7
     int ret = -1;
Laine Stump 38c4b7
 
Laine Stump 38c4b7
     memset(addr, 0, sizeof(*addr));
Laine Stump 38c4b7
@@ -1698,6 +1708,7 @@ virDomainDevicePCIAddressParseXML(xmlNodePtr node,
Laine Stump 38c4b7
     bus      = virXMLPropString(node, "bus");
Laine Stump 38c4b7
     slot     = virXMLPropString(node, "slot");
Laine Stump 38c4b7
     function = virXMLPropString(node, "function");
Laine Stump 38c4b7
+    multi    = virXMLPropString(node, "multifunction");
Laine Stump 38c4b7
 
Laine Stump 38c4b7
     if (domain &&
Laine Stump 38c4b7
         virStrToLong_ui(domain, NULL, 0, &addr->domain) < 0) {
Laine Stump 38c4b7
@@ -1727,6 +1738,14 @@ virDomainDevicePCIAddressParseXML(xmlNodePtr node,
Laine Stump 38c4b7
         goto cleanup;
Laine Stump 38c4b7
     }
Laine Stump 38c4b7
 
Laine Stump 38c4b7
+    if (multi &&
Laine Stump 38c4b7
+        ((addr->multi = virDomainDeviceAddressPciMultiTypeFromString(multi)) <= 0)) {
Laine Stump 38c4b7
+        virDomainReportError(VIR_ERR_CONFIG_UNSUPPORTED,
Laine Stump 38c4b7
+                             _("Unknown value '%s' for <address> 'multifunction' attribute"),
Laine Stump 38c4b7
+                             multi);
Laine Stump 38c4b7
+        goto cleanup;
Laine Stump 38c4b7
+
Laine Stump 38c4b7
+    }
Laine Stump 38c4b7
     if (!virDomainDevicePCIAddressIsValid(addr)) {
Laine Stump 38c4b7
         virDomainReportError(VIR_ERR_INTERNAL_ERROR, "%s",
Laine Stump 38c4b7
                              _("Insufficient specification for PCI address"));
Laine Stump 38c4b7
@@ -1740,6 +1759,7 @@ cleanup:
Laine Stump 38c4b7
     VIR_FREE(bus);
Laine Stump 38c4b7
     VIR_FREE(slot);
Laine Stump 38c4b7
     VIR_FREE(function);
Laine Stump 38c4b7
+    VIR_FREE(multi);
Laine Stump 38c4b7
     return ret;
Laine Stump 38c4b7
 }
Laine Stump 38c4b7
 
Laine Stump 38c4b7
diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h
Laine Stump 38c4b7
index 371f270..f4a38fb 100644
Laine Stump 38c4b7
--- a/src/conf/domain_conf.h
Laine Stump 38c4b7
+++ b/src/conf/domain_conf.h
Laine Stump 38c4b7
@@ -74,6 +74,14 @@ enum virDomainDeviceAddressType {
Laine Stump 38c4b7
     VIR_DOMAIN_DEVICE_ADDRESS_TYPE_LAST
Laine Stump 38c4b7
 };
Laine Stump 38c4b7
 
Laine Stump 38c4b7
+enum virDomainDeviceAddressPciMulti {
Laine Stump 38c4b7
+    VIR_DOMAIN_DEVICE_ADDRESS_PCI_MULTI_DEFAULT = 0,
Laine Stump 38c4b7
+    VIR_DOMAIN_DEVICE_ADDRESS_PCI_MULTI_ON,
Laine Stump 38c4b7
+    VIR_DOMAIN_DEVICE_ADDRESS_PCI_MULTI_OFF,
Laine Stump 38c4b7
+
Laine Stump 38c4b7
+    VIR_DOMAIN_DEVICE_ADDRESS_PCI_MULTI_LAST
Laine Stump 38c4b7
+};
Laine Stump 38c4b7
+
Laine Stump 38c4b7
 typedef struct _virDomainDevicePCIAddress virDomainDevicePCIAddress;
Laine Stump 38c4b7
 typedef virDomainDevicePCIAddress *virDomainDevicePCIAddressPtr;
Laine Stump 38c4b7
 struct _virDomainDevicePCIAddress {
Laine Stump 38c4b7
@@ -81,6 +89,7 @@ struct _virDomainDevicePCIAddress {
Laine Stump 38c4b7
     unsigned int bus;
Laine Stump 38c4b7
     unsigned int slot;
Laine Stump 38c4b7
     unsigned int function;
Laine Stump 38c4b7
+    int          multi;  /* enum virDomainDeviceAddressPciMulti */
Laine Stump 38c4b7
 };
Laine Stump 38c4b7
 
Laine Stump 38c4b7
 typedef struct _virDomainDeviceDriveAddress virDomainDeviceDriveAddress;
Laine Stump 38c4b7
@@ -1820,7 +1829,7 @@ VIR_ENUM_DECL(virDomainLifecycle)
Laine Stump 38c4b7
 VIR_ENUM_DECL(virDomainLifecycleCrash)
Laine Stump 38c4b7
 VIR_ENUM_DECL(virDomainDevice)
Laine Stump 38c4b7
 VIR_ENUM_DECL(virDomainDeviceAddress)
Laine Stump 38c4b7
-VIR_ENUM_DECL(virDomainDeviceAddressMode)
Laine Stump 38c4b7
+VIR_ENUM_DECL(virDomainDeviceAddressPciMulti)
Laine Stump 38c4b7
 VIR_ENUM_DECL(virDomainDisk)
Laine Stump 38c4b7
 VIR_ENUM_DECL(virDomainDiskDevice)
Laine Stump 38c4b7
 VIR_ENUM_DECL(virDomainDiskBus)
Laine Stump 38c4b7
diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
Laine Stump 38c4b7
index 8235ea1..da3042e 100644
Laine Stump 38c4b7
--- a/src/libvirt_private.syms
Laine Stump 38c4b7
+++ b/src/libvirt_private.syms
Laine Stump 38c4b7
@@ -269,6 +269,8 @@ virDomainDefParseNode;
Laine Stump 38c4b7
 virDomainDefParseString;
Laine Stump 38c4b7
 virDomainDeleteConfig;
Laine Stump 38c4b7
 virDomainDeviceAddressIsValid;
Laine Stump 38c4b7
+virDomainDeviceAddressPciMultiTypeFromString;
Laine Stump 38c4b7
+virDomainDeviceAddressPciMultiTypeToString;
Laine Stump 38c4b7
 virDomainDeviceAddressTypeToString;
Laine Stump 38c4b7
 virDomainDeviceDefFree;
Laine Stump 38c4b7
 virDomainDeviceDefParse;
Laine Stump 38c4b7
diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c
Laine Stump 38c4b7
index 0adc56a..ee184c2 100644
Laine Stump 38c4b7
--- a/src/qemu/qemu_command.c
Laine Stump 38c4b7
+++ b/src/qemu/qemu_command.c
Laine Stump 38c4b7
@@ -772,22 +772,65 @@ static int qemuCollectPCIAddress(virDomainDefPtr def ATTRIBUTE_UNUSED,
Laine Stump 38c4b7
                                  virDomainDeviceInfoPtr dev,
Laine Stump 38c4b7
                                  void *opaque)
Laine Stump 38c4b7
 {
Laine Stump 38c4b7
+    int ret = -1;
Laine Stump 38c4b7
+    char *addr = NULL;
Laine Stump 38c4b7
     qemuDomainPCIAddressSetPtr addrs = opaque;
Laine Stump 38c4b7
 
Laine Stump 38c4b7
-    if (dev->type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI) {
Laine Stump 38c4b7
-        char *addr = qemuPCIAddressAsString(dev);
Laine Stump 38c4b7
-        if (!addr)
Laine Stump 38c4b7
-            return -1;
Laine Stump 38c4b7
+    if (dev->type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI)
Laine Stump 38c4b7
+        return 0;
Laine Stump 38c4b7
 
Laine Stump 38c4b7
-        VIR_DEBUG("Remembering PCI addr %s", addr);
Laine Stump 38c4b7
+    addr = qemuPCIAddressAsString(dev);
Laine Stump 38c4b7
+    if (!addr)
Laine Stump 38c4b7
+        goto cleanup;
Laine Stump 38c4b7
 
Laine Stump 38c4b7
-        if (virHashAddEntry(addrs->used, addr, addr) < 0) {
Laine Stump 38c4b7
-            VIR_FREE(addr);
Laine Stump 38c4b7
-            return -1;
Laine Stump 38c4b7
+    if (virHashLookup(addrs->used, addr)) {
Laine Stump 38c4b7
+        if (dev->addr.pci.function != 0) {
Laine Stump 38c4b7
+            qemuReportError(VIR_ERR_XML_ERROR,
Laine Stump 38c4b7
+                            _("Attempted double use of PCI Address '%s' "
Laine Stump 38c4b7
+                              "(may need \"multifunction='on'\" for device on function 0"),
Laine Stump 38c4b7
+                            addr);
Laine Stump 38c4b7
+        } else {
Laine Stump 38c4b7
+            qemuReportError(VIR_ERR_XML_ERROR,
Laine Stump 38c4b7
+                            _("Attempted double use of PCI Address '%s'"), addr);
Laine Stump 38c4b7
         }
Laine Stump 38c4b7
+        goto cleanup;
Laine Stump 38c4b7
     }
Laine Stump 38c4b7
 
Laine Stump 38c4b7
-    return 0;
Laine Stump 38c4b7
+    VIR_DEBUG("Remembering PCI addr %s", addr);
Laine Stump 38c4b7
+    if (virHashAddEntry(addrs->used, addr, addr) < 0)
Laine Stump 38c4b7
+        goto cleanup;
Laine Stump 38c4b7
+    addr = NULL;
Laine Stump 38c4b7
+
Laine Stump 38c4b7
+    if ((dev->addr.pci.function == 0) &&
Laine Stump 38c4b7
+        (dev->addr.pci.multi != VIR_DOMAIN_DEVICE_ADDRESS_PCI_MULTI_ON)) {
Laine Stump 38c4b7
+        /* a function 0 w/o multifunction=on must reserve the entire slot */
Laine Stump 38c4b7
+        int function;
Laine Stump 38c4b7
+        virDomainDeviceInfo temp_dev = *dev;
Laine Stump 38c4b7
+
Laine Stump 38c4b7
+        for (function = 1; function < QEMU_PCI_ADDRESS_LAST_FUNCTION; function++) {
Laine Stump 38c4b7
+            temp_dev.addr.pci.function = function;
Laine Stump 38c4b7
+            addr = qemuPCIAddressAsString(&temp_dev);
Laine Stump 38c4b7
+            if (!addr)
Laine Stump 38c4b7
+                goto cleanup;
Laine Stump 38c4b7
+
Laine Stump 38c4b7
+            if (virHashLookup(addrs->used, addr)) {
Laine Stump 38c4b7
+                qemuReportError(VIR_ERR_XML_ERROR,
Laine Stump 38c4b7
+                                _("Attempted double use of PCI Address '%s'"
Laine Stump 38c4b7
+                                  "(need \"multifunction='off'\" for device on function 0)"),
Laine Stump 38c4b7
+                                addr);
Laine Stump 38c4b7
+                goto cleanup;
Laine Stump 38c4b7
+            }
Laine Stump 38c4b7
+
Laine Stump 38c4b7
+            VIR_DEBUG("Remembering PCI addr %s (multifunction=off for function 0)", addr);
Laine Stump 38c4b7
+            if (virHashAddEntry(addrs->used, addr, addr))
Laine Stump 38c4b7
+                goto cleanup;
Laine Stump 38c4b7
+            addr = NULL;
Laine Stump 38c4b7
+        }
Laine Stump 38c4b7
+    }
Laine Stump 38c4b7
+    ret = 0;
Laine Stump 38c4b7
+cleanup:
Laine Stump 38c4b7
+    VIR_FREE(addr);
Laine Stump 38c4b7
+    return ret;
Laine Stump 38c4b7
 }
Laine Stump 38c4b7
 
Laine Stump 38c4b7
 
Laine Stump 38c4b7
@@ -1374,7 +1417,13 @@ qemuBuildDeviceAddressStr(virBufferPtr buf,
Laine Stump 38c4b7
             if (info->addr.pci.function != 0) {
Laine Stump 38c4b7
                 qemuReportError(VIR_ERR_INTERNAL_ERROR, "%s",
Laine Stump 38c4b7
                                 _("Only PCI device addresses with function=0 "
Laine Stump 38c4b7
-                                  "are supported"));
Laine Stump 38c4b7
+                                  "are supported with this QEMU binary"));
Laine Stump 38c4b7
+                return -1;
Laine Stump 38c4b7
+            }
Laine Stump 38c4b7
+            if (info->addr.pci.multi == VIR_DOMAIN_DEVICE_ADDRESS_PCI_MULTI_ON) {
Laine Stump 38c4b7
+                qemuReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
Laine Stump 38c4b7
+                                _("'multifunction=on' is not supported with "
Laine Stump 38c4b7
+                                  "this QEMU binary"));
Laine Stump 38c4b7
                 return -1;
Laine Stump 38c4b7
             }
Laine Stump 38c4b7
         }
Laine Stump 38c4b7
@@ -1389,11 +1438,13 @@ qemuBuildDeviceAddressStr(virBufferPtr buf,
Laine Stump 38c4b7
             virBufferAsprintf(buf, ",bus=pci.0");
Laine Stump 38c4b7
         else
Laine Stump 38c4b7
             virBufferAsprintf(buf, ",bus=pci");
Laine Stump 38c4b7
-        if (qemuCapsGet(qemuCaps, QEMU_CAPS_PCI_MULTIFUNCTION))
Laine Stump 38c4b7
-            virBufferAsprintf(buf, ",multifunction=on,addr=0x%x.0x%x",
Laine Stump 38c4b7
-                              info->addr.pci.slot, info->addr.pci.function);
Laine Stump 38c4b7
-        else
Laine Stump 38c4b7
-            virBufferAsprintf(buf, ",addr=0x%x", info->addr.pci.slot);
Laine Stump 38c4b7
+        if (info->addr.pci.multi == VIR_DOMAIN_DEVICE_ADDRESS_PCI_MULTI_ON)
Laine Stump 38c4b7
+            virBufferAddLit(buf, ",multifunction=on");
Laine Stump 38c4b7
+        else if (info->addr.pci.multi == VIR_DOMAIN_DEVICE_ADDRESS_PCI_MULTI_OFF)
Laine Stump 38c4b7
+            virBufferAddLit(buf, ",multifunction=off");
Laine Stump 38c4b7
+        virBufferAsprintf(buf, ",addr=0x%x", info->addr.pci.slot);
Laine Stump 38c4b7
+        if (info->addr.pci.function != 0)
Laine Stump 38c4b7
+           virBufferAsprintf(buf, ".0x%x", info->addr.pci.function);
Laine Stump 38c4b7
     } else if (info->type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_USB) {
Laine Stump 38c4b7
         virBufferAsprintf(buf, ",bus=");
Laine Stump 38c4b7
         qemuUsbId(buf, info->addr.usb.bus);
Laine Stump 38c4b7
diff --git a/tests/qemuxml2argvdata/qemuxml2argv-multifunction-pci-device.args b/tests/qemuxml2argvdata/qemuxml2argv-multifunction-pci-device.args
Laine Stump 38c4b7
index ff229f2..8a2150e 100644
Laine Stump 38c4b7
--- a/tests/qemuxml2argvdata/qemuxml2argv-multifunction-pci-device.args
Laine Stump 38c4b7
+++ b/tests/qemuxml2argvdata/qemuxml2argv-multifunction-pci-device.args
Laine Stump 38c4b7
@@ -1,15 +1,15 @@
Laine Stump 38c4b7
 LC_ALL=C PATH=/bin HOME=/home/test USER=test LOGNAME=test /usr/bin/qemu -S -M \
Laine Stump 38c4b7
 pc -m 214 -smp 1 -nographic -nodefconfig -nodefaults \
Laine Stump 38c4b7
 -monitor unix:/tmp/test-monitor,server,nowait -no-acpi -boot c \
Laine Stump 38c4b7
--device lsi,id=scsi0,bus=pci.0,multifunction=on,addr=0x3.0x0 \
Laine Stump 38c4b7
--device lsi,id=scsi1,bus=pci.0,multifunction=on,addr=0x4.0x0 \
Laine Stump 38c4b7
+-device lsi,id=scsi0,bus=pci.0,multifunction=off,addr=0x3 \
Laine Stump 38c4b7
+-device lsi,id=scsi1,bus=pci.0,multifunction=on,addr=0x4 \
Laine Stump 38c4b7
 -device lsi,id=scsi2,bus=pci.0,multifunction=on,addr=0x4.0x1 \
Laine Stump 38c4b7
--device lsi,id=scsi3,bus=pci.0,multifunction=on,addr=0x4.0x2 \
Laine Stump 38c4b7
--device lsi,id=scsi4,bus=pci.0,multifunction=on,addr=0x4.0x3 \
Laine Stump 38c4b7
--device lsi,id=scsi5,bus=pci.0,multifunction=on,addr=0x4.0x4 \
Laine Stump 38c4b7
--device lsi,id=scsi6,bus=pci.0,multifunction=on,addr=0x4.0x5 \
Laine Stump 38c4b7
--device lsi,id=scsi7,bus=pci.0,multifunction=on,addr=0x4.0x6 \
Laine Stump 38c4b7
--device lsi,id=scsi8,bus=pci.0,multifunction=on,addr=0x4.0x7 \
Laine Stump 38c4b7
+-device lsi,id=scsi3,bus=pci.0,addr=0x4.0x2 \
Laine Stump 38c4b7
+-device lsi,id=scsi4,bus=pci.0,addr=0x4.0x3 \
Laine Stump 38c4b7
+-device lsi,id=scsi5,bus=pci.0,addr=0x4.0x4 \
Laine Stump 38c4b7
+-device lsi,id=scsi6,bus=pci.0,addr=0x4.0x5 \
Laine Stump 38c4b7
+-device lsi,id=scsi7,bus=pci.0,addr=0x4.0x6 \
Laine Stump 38c4b7
+-device lsi,id=scsi8,bus=pci.0,addr=0x4.0x7 \
Laine Stump 38c4b7
 -drive file=/tmp/scsidisk.img,if=none,id=drive-scsi0-0-0 \
Laine Stump 38c4b7
 -device scsi-disk,bus=scsi0.0,scsi-id=0,drive=drive-scsi0-0-0,id=scsi0-0-0 \
Laine Stump 38c4b7
--usb -device virtio-balloon-pci,id=balloon0,bus=pci.0,multifunction=on,addr=0x5.0x0
Laine Stump 38c4b7
+-usb -device virtio-balloon-pci,id=balloon0,bus=pci.0,addr=0x5
Laine Stump 38c4b7
diff --git a/tests/qemuxml2argvdata/qemuxml2argv-multifunction-pci-device.xml b/tests/qemuxml2argvdata/qemuxml2argv-multifunction-pci-device.xml
Laine Stump 38c4b7
index 672fb61..24b95b8 100644
Laine Stump 38c4b7
--- a/tests/qemuxml2argvdata/qemuxml2argv-multifunction-pci-device.xml
Laine Stump 38c4b7
+++ b/tests/qemuxml2argvdata/qemuxml2argv-multifunction-pci-device.xml
Laine Stump 38c4b7
@@ -20,13 +20,13 @@
Laine Stump 38c4b7
       <address type='drive' controller='0' bus='0' unit='0'/>
Laine Stump 38c4b7
     </disk>
Laine Stump 38c4b7
     <controller type='scsi' index='0'>
Laine Stump 38c4b7
-      <address type='pci' domain='0x0000' bus='0x00' slot='0x03' function='0x0'/>
Laine Stump 38c4b7
+      <address type='pci' domain='0x0000' bus='0x00' slot='0x03' function='0x0' multifunction='off'/>
Laine Stump 38c4b7
     </controller>
Laine Stump 38c4b7
     <controller type='scsi' index='1'>
Laine Stump 38c4b7
-      <address type='pci' domain='0x0000' bus='0x00' slot='0x04' function='0x0'/>
Laine Stump 38c4b7
+      <address type='pci' domain='0x0000' bus='0x00' slot='0x04' function='0x0' multifunction='on'/>
Laine Stump 38c4b7
     </controller>
Laine Stump 38c4b7
     <controller type='scsi' index='2'>
Laine Stump 38c4b7
-      <address type='pci' domain='0x0000' bus='0x00' slot='0x04' function='0x1'/>
Laine Stump 38c4b7
+      <address type='pci' domain='0x0000' bus='0x00' slot='0x04' function='0x1' multifunction='on'/>
Laine Stump 38c4b7
     </controller>
Laine Stump 38c4b7
     <controller type='scsi' index='3'>
Laine Stump 38c4b7
       <address type='pci' domain='0x0000' bus='0x00' slot='0x04' function='0x2'/>
Laine Stump 38c4b7
diff --git a/tests/qemuxml2argvdata/qemuxml2argv-usb-ich9-companion.args b/tests/qemuxml2argvdata/qemuxml2argv-usb-ich9-companion.args
Laine Stump 38c4b7
index 1007544..080d483 100644
Laine Stump 38c4b7
--- a/tests/qemuxml2argvdata/qemuxml2argv-usb-ich9-companion.args
Laine Stump 38c4b7
+++ b/tests/qemuxml2argvdata/qemuxml2argv-usb-ich9-companion.args
Laine Stump 38c4b7
@@ -1,6 +1,9 @@
Laine Stump 38c4b7
-LC_ALL=C PATH=/bin HOME=/home/test USER=test LOGNAME=test /usr/bin/qemu -S -M pc -m 214 -smp 1 -nographic -nodefconfig -nodefaults -chardev socket,id=charmonitor,path=/tmp/test-monitor,server,nowait -mon chardev=charmonitor,id=monitor,mode=readline -no-acpi -boot c \
Laine Stump 38c4b7
--device ich9-usb-ehci1,id=usb,bus=pci.0,multifunction=on,addr=0x4.0x7 \
Laine Stump 38c4b7
--device ich9-usb-uhci1,masterbus=usb.0,firstport=0,bus=pci.0,multifunction=on,addr=0x4.0x0 \
Laine Stump 38c4b7
--device ich9-usb-uhci2,masterbus=usb.0,firstport=2,bus=pci.0,multifunction=on,addr=0x4.0x1 \
Laine Stump 38c4b7
--device ich9-usb-uhci3,masterbus=usb.0,firstport=4,bus=pci.0,multifunction=on,addr=0x4.0x2 \
Laine Stump 38c4b7
--device virtio-balloon-pci,id=balloon0,bus=pci.0,multifunction=on,addr=0x3.0x0
Laine Stump 38c4b7
+LC_ALL=C PATH=/bin HOME=/home/test USER=test LOGNAME=test /usr/bin/qemu -S -M pc \
Laine Stump 38c4b7
+-m 214 -smp 1 -nographic -nodefconfig -nodefaults \
Laine Stump 38c4b7
+-chardev socket,id=charmonitor,path=/tmp/test-monitor,server,nowait \
Laine Stump 38c4b7
+-mon chardev=charmonitor,id=monitor,mode=readline -no-acpi -boot c \
Laine Stump 38c4b7
+-device ich9-usb-ehci1,id=usb,bus=pci.0,addr=0x4.0x7 \
Laine Stump 38c4b7
+-device ich9-usb-uhci1,masterbus=usb.0,firstport=0,bus=pci.0,multifunction=on,addr=0x4 \
Laine Stump 38c4b7
+-device ich9-usb-uhci2,masterbus=usb.0,firstport=2,bus=pci.0,addr=0x4.0x1 \
Laine Stump 38c4b7
+-device ich9-usb-uhci3,masterbus=usb.0,firstport=4,bus=pci.0,addr=0x4.0x2 \
Laine Stump 38c4b7
+-device virtio-balloon-pci,id=balloon0,bus=pci.0,addr=0x3
Laine Stump 38c4b7
diff --git a/tests/qemuxml2argvdata/qemuxml2argv-usb-ich9-companion.xml b/tests/qemuxml2argvdata/qemuxml2argv-usb-ich9-companion.xml
Laine Stump 38c4b7
index 05a6adf..5a43638 100644
Laine Stump 38c4b7
--- a/tests/qemuxml2argvdata/qemuxml2argv-usb-ich9-companion.xml
Laine Stump 38c4b7
+++ b/tests/qemuxml2argvdata/qemuxml2argv-usb-ich9-companion.xml
Laine Stump 38c4b7
@@ -15,7 +15,7 @@
Laine Stump 38c4b7
     </controller>
Laine Stump 38c4b7
     <controller type='usb' index='0' model='ich9-uhci1'>
Laine Stump 38c4b7
       <master startport='0'/>
Laine Stump 38c4b7
-      <address type='pci' domain='0' bus='0' slot='4' function='0'/>
Laine Stump 38c4b7
+      <address type='pci' domain='0' bus='0' slot='4' function='0' multifunction='on'/>
Laine Stump 38c4b7
     </controller>
Laine Stump 38c4b7
     <controller type='usb' index='0' model='ich9-uhci2'>
Laine Stump 38c4b7
       <master startport='2'/>
Laine Stump 38c4b7
diff --git a/tests/qemuxml2argvdata/qemuxml2argv-usb-ich9-ehci-addr.args b/tests/qemuxml2argvdata/qemuxml2argv-usb-ich9-ehci-addr.args
Laine Stump 38c4b7
index 0059ab5..babd4f8 100644
Laine Stump 38c4b7
--- a/tests/qemuxml2argvdata/qemuxml2argv-usb-ich9-ehci-addr.args
Laine Stump 38c4b7
+++ b/tests/qemuxml2argvdata/qemuxml2argv-usb-ich9-ehci-addr.args
Laine Stump 38c4b7
@@ -1 +1,6 @@
Laine Stump 38c4b7
-LC_ALL=C PATH=/bin HOME=/home/test USER=test LOGNAME=test /usr/bin/qemu -S -M pc -m 214 -smp 1 -nographic -nodefconfig -nodefaults -chardev socket,id=charmonitor,path=/tmp/test-monitor,server,nowait -mon chardev=charmonitor,id=monitor,mode=readline -no-acpi -boot c -device ich9-usb-ehci1,id=usb,bus=pci.0,multifunction=on,addr=0x4.0x7 -device virtio-balloon-pci,id=balloon0,bus=pci.0,multifunction=on,addr=0x3.0x0
Laine Stump 38c4b7
+LC_ALL=C PATH=/bin HOME=/home/test USER=test LOGNAME=test /usr/bin/qemu -S \
Laine Stump 38c4b7
+-M pc -m 214 -smp 1 -nographic -nodefconfig -nodefaults \
Laine Stump 38c4b7
+-chardev socket,id=charmonitor,path=/tmp/test-monitor,server,nowait \
Laine Stump 38c4b7
+-mon chardev=charmonitor,id=monitor,mode=readline -no-acpi -boot c \
Laine Stump 38c4b7
+-device ich9-usb-ehci1,id=usb,bus=pci.0,addr=0x4.0x7 \
Laine Stump 38c4b7
+-device virtio-balloon-pci,id=balloon0,bus=pci.0,addr=0x3
Laine Stump 38c4b7
diff --git a/tests/qemuxml2argvdata/qemuxml2argv-usb-piix3-controller.args b/tests/qemuxml2argvdata/qemuxml2argv-usb-piix3-controller.args
Laine Stump 38c4b7
index 06863bb..1b2d5c1 100644
Laine Stump 38c4b7
--- a/tests/qemuxml2argvdata/qemuxml2argv-usb-piix3-controller.args
Laine Stump 38c4b7
+++ b/tests/qemuxml2argvdata/qemuxml2argv-usb-piix3-controller.args
Laine Stump 38c4b7
@@ -1 +1,6 @@
Laine Stump 38c4b7
-LC_ALL=C PATH=/bin HOME=/home/test USER=test LOGNAME=test /usr/bin/qemu -S -M pc -m 214 -smp 1 -nographic -nodefconfig -nodefaults -chardev socket,id=charmonitor,path=/tmp/test-monitor,server,nowait -mon chardev=charmonitor,id=monitor,mode=readline -no-acpi -boot c -device piix3-usb-uhci,id=usb,bus=pci.0,multifunction=on,addr=0x1.0x2 -device virtio-balloon-pci,id=balloon0,bus=pci.0,multifunction=on,addr=0x3.0x0
Laine Stump 38c4b7
+LC_ALL=C PATH=/bin HOME=/home/test USER=test LOGNAME=test /usr/bin/qemu -S \
Laine Stump 38c4b7
+-M pc -m 214 -smp 1 -nographic -nodefconfig -nodefaults \
Laine Stump 38c4b7
+-chardev socket,id=charmonitor,path=/tmp/test-monitor,server,nowait \
Laine Stump 38c4b7
+-mon chardev=charmonitor,id=monitor,mode=readline -no-acpi -boot c \
Laine Stump 38c4b7
+-device piix3-usb-uhci,id=usb,bus=pci.0,addr=0x1.0x2 \
Laine Stump 38c4b7
+-device virtio-balloon-pci,id=balloon0,bus=pci.0,addr=0x3
Laine Stump 38c4b7
diff --git a/tests/qemuxml2argvdata/qemuxml2argv-usb-redir.args b/tests/qemuxml2argvdata/qemuxml2argv-usb-redir.args
Laine Stump 38c4b7
index f6270d5..7d34c2a 100644
Laine Stump 38c4b7
--- a/tests/qemuxml2argvdata/qemuxml2argv-usb-redir.args
Laine Stump 38c4b7
+++ b/tests/qemuxml2argvdata/qemuxml2argv-usb-redir.args
Laine Stump 38c4b7
@@ -1,10 +1,10 @@
Laine Stump 38c4b7
 LC_ALL=C PATH=/bin HOME=/home/test USER=test LOGNAME=test /usr/bin/qemu -S -M pc -m 214 -smp 1 -nographic -nodefconfig -nodefaults -chardev socket,id=charmonitor,path=/tmp/test-monitor,server,nowait -mon chardev=charmonitor,id=monitor,mode=readline -no-acpi -boot c \
Laine Stump 38c4b7
--device ich9-usb-ehci1,id=usb,bus=pci.0,multifunction=on,addr=0x4.0x7 \
Laine Stump 38c4b7
--device ich9-usb-uhci1,masterbus=usb.0,firstport=0,bus=pci.0,multifunction=on,addr=0x4.0x0 \
Laine Stump 38c4b7
--device ich9-usb-uhci2,masterbus=usb.0,firstport=2,bus=pci.0,multifunction=on,addr=0x4.0x1 \
Laine Stump 38c4b7
--device ich9-usb-uhci3,masterbus=usb.0,firstport=4,bus=pci.0,multifunction=on,addr=0x4.0x2 \
Laine Stump 38c4b7
+-device ich9-usb-ehci1,id=usb,bus=pci.0,addr=0x4.0x7 \
Laine Stump 38c4b7
+-device ich9-usb-uhci1,masterbus=usb.0,firstport=0,bus=pci.0,multifunction=on,addr=0x4 \
Laine Stump 38c4b7
+-device ich9-usb-uhci2,masterbus=usb.0,firstport=2,bus=pci.0,addr=0x4.0x1 \
Laine Stump 38c4b7
+-device ich9-usb-uhci3,masterbus=usb.0,firstport=4,bus=pci.0,addr=0x4.0x2 \
Laine Stump 38c4b7
 -chardev socket,id=charredir0,host=localhost,port=4000 \
Laine Stump 38c4b7
 -device usb-redir,chardev=charredir0,id=redir0 \
Laine Stump 38c4b7
 -chardev spicevmc,id=charredir1,name=usbredir \
Laine Stump 38c4b7
 -device usb-redir,chardev=charredir1,id=redir1,bus=usb.0,port=4 \
Laine Stump 38c4b7
--device virtio-balloon-pci,id=balloon0,bus=pci.0,multifunction=on,addr=0x3.0x0
Laine Stump 38c4b7
+-device virtio-balloon-pci,id=balloon0,bus=pci.0,addr=0x3
Laine Stump 38c4b7
diff --git a/tests/qemuxml2argvdata/qemuxml2argv-usb-redir.xml b/tests/qemuxml2argvdata/qemuxml2argv-usb-redir.xml
Laine Stump 38c4b7
index 1dac3fb..a359a3d 100644
Laine Stump 38c4b7
--- a/tests/qemuxml2argvdata/qemuxml2argv-usb-redir.xml
Laine Stump 38c4b7
+++ b/tests/qemuxml2argvdata/qemuxml2argv-usb-redir.xml
Laine Stump 38c4b7
@@ -19,7 +19,7 @@
Laine Stump 38c4b7
     </controller>
Laine Stump 38c4b7
     <controller type='usb' index='0' model='ich9-uhci1'>
Laine Stump 38c4b7
       <master startport='0'/>
Laine Stump 38c4b7
-      <address type='pci' domain='0x0000' bus='0x00' slot='0x04' function='0x0'/>
Laine Stump 38c4b7
+      <address type='pci' domain='0x0000' bus='0x00' slot='0x04' function='0x0' multifunction='on'/>
Laine Stump 38c4b7
     </controller>
Laine Stump 38c4b7
     <controller type='usb' index='0' model='ich9-uhci2'>
Laine Stump 38c4b7
       <master startport='2'/>
Laine Stump 38c4b7
diff --git a/tests/qemuxml2argvdata/qemuxml2argv-usb1-usb2.args b/tests/qemuxml2argvdata/qemuxml2argv-usb1-usb2.args
Laine Stump 38c4b7
index be4a78e..0a61af5 100644
Laine Stump 38c4b7
--- a/tests/qemuxml2argvdata/qemuxml2argv-usb1-usb2.args
Laine Stump 38c4b7
+++ b/tests/qemuxml2argvdata/qemuxml2argv-usb1-usb2.args
Laine Stump 38c4b7
@@ -1,15 +1,18 @@
Laine Stump 38c4b7
-LC_ALL=C PATH=/bin HOME=/home/test USER=test LOGNAME=test /usr/bin/qemu -S -M pc -m 214 -smp 1 -nographic -nodefconfig -nodefaults -chardev socket,id=charmonitor,path=/tmp/test-monitor,server,nowait -mon chardev=charmonitor,id=monitor,mode=readline -no-acpi -boot c \
Laine Stump 38c4b7
--device piix3-usb-uhci,id=usb,bus=pci.0,multifunction=on,addr=0x1.0x2 \
Laine Stump 38c4b7
--device ich9-usb-ehci1,id=usb1,bus=pci.0,multifunction=on,addr=0x4.0x7 \
Laine Stump 38c4b7
--device ich9-usb-uhci1,masterbus=usb1.0,firstport=0,bus=pci.0,multifunction=on,addr=0x4.0x0 \
Laine Stump 38c4b7
--device ich9-usb-uhci2,masterbus=usb1.0,firstport=2,bus=pci.0,multifunction=on,addr=0x4.0x1 \
Laine Stump 38c4b7
--device ich9-usb-uhci3,masterbus=usb1.0,firstport=4,bus=pci.0,multifunction=on,addr=0x4.0x2 \
Laine Stump 38c4b7
--device ich9-usb-ehci1,id=usb2,bus=pci.0,multifunction=on,addr=0x5.0x7 \
Laine Stump 38c4b7
--device ich9-usb-uhci1,masterbus=usb2.0,firstport=0,bus=pci.0,multifunction=on,addr=0x5.0x0 \
Laine Stump 38c4b7
--device ich9-usb-uhci2,masterbus=usb2.0,firstport=2,bus=pci.0,multifunction=on,addr=0x5.0x1 \
Laine Stump 38c4b7
--device ich9-usb-uhci3,masterbus=usb2.0,firstport=4,bus=pci.0,multifunction=on,addr=0x5.0x2 \
Laine Stump 38c4b7
+LC_ALL=C PATH=/bin HOME=/home/test USER=test LOGNAME=test /usr/bin/qemu -S \
Laine Stump 38c4b7
+-M pc -m 214 -smp 1 -nographic -nodefconfig -nodefaults \
Laine Stump 38c4b7
+-chardev socket,id=charmonitor,path=/tmp/test-monitor,server,nowait \
Laine Stump 38c4b7
+-mon chardev=charmonitor,id=monitor,mode=readline -no-acpi -boot c \
Laine Stump 38c4b7
+-device piix3-usb-uhci,id=usb,bus=pci.0,addr=0x1.0x2 \
Laine Stump 38c4b7
+-device ich9-usb-ehci1,id=usb1,bus=pci.0,addr=0x4.0x7 \
Laine Stump 38c4b7
+-device ich9-usb-uhci1,masterbus=usb1.0,firstport=0,bus=pci.0,multifunction=on,addr=0x4 \
Laine Stump 38c4b7
+-device ich9-usb-uhci2,masterbus=usb1.0,firstport=2,bus=pci.0,addr=0x4.0x1 \
Laine Stump 38c4b7
+-device ich9-usb-uhci3,masterbus=usb1.0,firstport=4,bus=pci.0,addr=0x4.0x2 \
Laine Stump 38c4b7
+-device ich9-usb-ehci1,id=usb2,bus=pci.0,addr=0x5.0x7 \
Laine Stump 38c4b7
+-device ich9-usb-uhci1,masterbus=usb2.0,firstport=0,bus=pci.0,multifunction=on,addr=0x5 \
Laine Stump 38c4b7
+-device ich9-usb-uhci2,masterbus=usb2.0,firstport=2,bus=pci.0,addr=0x5.0x1 \
Laine Stump 38c4b7
+-device ich9-usb-uhci3,masterbus=usb2.0,firstport=4,bus=pci.0,addr=0x5.0x2 \
Laine Stump 38c4b7
 -device usb-hub,id=hub0,bus=usb1.0,port=1 \
Laine Stump 38c4b7
 -device usb-tablet,id=input0,bus=usb.0,port=2 \
Laine Stump 38c4b7
 -device usb-host,hostbus=14,hostaddr=6,id=hostdev0,bus=usb2.0,port=1 \
Laine Stump 38c4b7
 -device usb-host,hostbus=14,hostaddr=7,id=hostdev1,bus=usb2.0,port=2 \
Laine Stump 38c4b7
--device virtio-balloon-pci,id=balloon0,bus=pci.0,multifunction=on,addr=0x3.0x0
Laine Stump 38c4b7
+-device virtio-balloon-pci,id=balloon0,bus=pci.0,addr=0x3
Laine Stump 38c4b7
diff --git a/tests/qemuxml2argvdata/qemuxml2argv-usb1-usb2.xml b/tests/qemuxml2argvdata/qemuxml2argv-usb1-usb2.xml
Laine Stump 38c4b7
index e8ada4d..b12b841 100644
Laine Stump 38c4b7
--- a/tests/qemuxml2argvdata/qemuxml2argv-usb1-usb2.xml
Laine Stump 38c4b7
+++ b/tests/qemuxml2argvdata/qemuxml2argv-usb1-usb2.xml
Laine Stump 38c4b7
@@ -21,7 +21,7 @@
Laine Stump 38c4b7
     </controller>
Laine Stump 38c4b7
     <controller type='usb' index='1' model='ich9-uhci1'>
Laine Stump 38c4b7
       <master startport='0'/>
Laine Stump 38c4b7
-      <address type='pci' domain='0' bus='0' slot='4' function='0'/>
Laine Stump 38c4b7
+      <address type='pci' domain='0' bus='0' slot='4' function='0' multifunction='on'/>
Laine Stump 38c4b7
     </controller>
Laine Stump 38c4b7
     <controller type='usb' index='1' model='ich9-uhci2'>
Laine Stump 38c4b7
       <master startport='2'/>
Laine Stump 38c4b7
@@ -37,7 +37,7 @@
Laine Stump 38c4b7
     </controller>
Laine Stump 38c4b7
     <controller type='usb' index='2' model='ich9-uhci1'>
Laine Stump 38c4b7
       <master startport='0'/>
Laine Stump 38c4b7
-      <address type='pci' domain='0' bus='0' slot='5' function='0'/>
Laine Stump 38c4b7
+      <address type='pci' domain='0' bus='0' slot='5' function='0' multifunction='on'/>
Laine Stump 38c4b7
     </controller>
Laine Stump 38c4b7
     <controller type='usb' index='2' model='ich9-uhci2'>
Laine Stump 38c4b7
       <master startport='2'/>
Laine Stump 38c4b7
-- 
Laine Stump 38c4b7
1.7.4.4
Laine Stump 38c4b7