]> xenbits.xensource.com Git - people/dariof/libvirt.git/commitdiff
qemu: add dmi-to-pci-bridge controller
authorLaine Stump <laine@laine.org>
Wed, 31 Jul 2013 01:37:32 +0000 (21:37 -0400)
committerLaine Stump <laine@laine.org>
Mon, 5 Aug 2013 19:40:49 +0000 (15:40 -0400)
This PCI controller, named "dmi-to-pci-bridge" in the libvirt config,
and implemented with qemu's "i82801b11-bridge" device, connects to a
PCI Express slot (e.g. one of the slots provided by the pcie-root
controller, aka "pcie.0" on the qemu commandline), and provides 31
*non-hot-pluggable* PCI (*not* PCIe) slots, numbered 1-31.

Any time a machine is defined which has a pcie-root controller
(i.e. any q35-based machinetype), libvirt will automatically add a
dmi-to-pci-bridge controller if one doesn't exist, and also add a
pci-bridge controller. The reasoning here is that any useful domain
will have either an immediate (startup time) or eventual (subsequent
hot-plug) need for a standard PCI slot; since the pcie-root controller
only provides PCIe slots, we need to connect a dmi-to-pci-bridge
controller to it in order to get a non-hot-plug PCI slot that we can
then use to connect a pci-bridge - the slots provided by the
pci-bridge will be both standard PCI and hot-pluggable.

Since pci-bridge devices themselves can not be hot-plugged into a
running system (although you can hot-plug other devices into a
pci-bridge's slots), any new pci-bridge controller that is added can
(and will) be plugged into the dmi-to-pci-bridge as long as it has
empty slots available.

This patch is also changing the qemuxml2xml-pcie test from a "DO_TEST"
to a "DO_DIFFERENT_TEST". This is so that the "before" xml can omit
the automatically added dmi-to-pci-bridge and pci-bridge devices, and
the "after" xml can include it - this way we are testing if libvirt is
properly adding these devices.

14 files changed:
docs/formatdomain.html.in
docs/schemas/domaincommon.rng
src/conf/domain_conf.c
src/conf/domain_conf.h
src/qemu/qemu_capabilities.c
src/qemu/qemu_capabilities.h
src/qemu/qemu_command.c
src/qemu/qemu_domain.c
tests/qemuxml2argvdata/qemuxml2argv-pcie-root.args
tests/qemuxml2argvdata/qemuxml2argv-q35.args [new file with mode: 0644]
tests/qemuxml2argvdata/qemuxml2argv-q35.xml [new file with mode: 0644]
tests/qemuxml2argvtest.c
tests/qemuxml2xmloutdata/qemuxml2xmlout-pcie-root.xml [new file with mode: 0644]
tests/qemuxml2xmltest.c

index 6a2e121f4280aea0a70a34a7e60de23cfd8477e4..9d95b7743bf55b4084dc8704b7031666f940e285 100644 (file)
 
     <p>
       PCI controllers have an optional <code>model</code> attribute with
-      possible values <code>pci-root</code>, <code>pcie-root</code>
-      or <code>pci-bridge</code>.
+      possible values <code>pci-root</code>, <code>pcie-root</code>,
+      <code>pci-bridge</code>, or <code>dmi-to-pci-bridge</code>.
       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.
       pci-root has no address.
+      PCI bridges are auto-added if there are too many devices to fit on
+      the one bus provided by pci-root, or a PCI bus number greater than zero
+      was specified.
       PCI bridges can also be specified manually, but their addresses should
       only refer to PCI buses provided by already specified PCI controllers.
       Leaving gaps in the PCI controller indexes might lead to an invalid
       the pcie-root controller with index=0 is auto-added to the
       domain's configuration. pcie-root has also no address, provides
       31 slots (numbered 1-31) and can only be used to attach PCIe
-      devices.  (<span class="since">since 1.1.2</span>).
+      devices. In order to connect standard PCI devices on a system
+      which has a pcie-root controller, a pci controller
+      with <code>model='dmi-to-pci-bridge'</code> is automatically
+      added. A dmi-to-pci-bridge controller plugs into a PCIe slot (as
+      provided by pcie-root), and itself provides 31 standard PCI
+      slots (which are not hot-pluggable). In order to have
+      hot-pluggable PCI slots in the guest system, a pci-bridge
+      controller will also be automatically created and connected to
+      one of the slots of the auto-created dmi-to-pci-bridge
+      controller; all guest devices with PCI addresses that are
+      auto-determined by libvirt will be placed on this pci-bridge
+      device.  (<span class="since">since 1.1.2</span>).
     </p>
 <pre>
   ...
   &lt;devices&gt;
     &lt;controller type='pci' index='0' model='pcie-root'/&gt;
+    &lt;controller type='pci' index='1' model='dmi-to-pci-bridge'&gt;
+      &lt;address type='pci' domain='0' bus='0' slot='0xe' function='0'/&gt;
+    &lt;/controller&gt;
+    &lt;controller type='pci' index='2' model='pci-bridge'&gt;
+      &lt;address type='pci' domain='0' bus='1' slot='1' function='0'/&gt;
+    &lt;/controller&gt;
   &lt;/devices&gt;
   ...</pre>
 
index e04be12337eaa023b27ab6dbb4c068405cb8fa3f..173359cf89ad1dbd9bb4c8c57c54f8f40554982e 100644 (file)
                 <value>pci-root</value>
                 <value>pcie-root</value>
                 <value>pci-bridge</value>
+                <value>dmi-to-pci-bridge</value>
               </choice>
             </attribute>
           </group>
index 59a96f2d106ce9ca12ee873c553179f8bf559924..d17008fc961b20b1ba4a4d9ac153c34494c7c27e 100644 (file)
@@ -311,7 +311,8 @@ VIR_ENUM_IMPL(virDomainController, VIR_DOMAIN_CONTROLLER_TYPE_LAST,
 VIR_ENUM_IMPL(virDomainControllerModelPCI, VIR_DOMAIN_CONTROLLER_MODEL_PCI_LAST,
               "pci-root",
               "pcie-root",
-              "pci-bridge")
+              "pci-bridge",
+              "dmi-to-pci-bridge")
 
 VIR_ENUM_IMPL(virDomainControllerModelSCSI, VIR_DOMAIN_CONTROLLER_MODEL_SCSI_LAST,
               "auto",
index 63a14447800c1a73bd77fd1b03e8978029ab80b9..3e118d63d36bd068f2e714755d8af8d93e646849 100644 (file)
@@ -770,6 +770,7 @@ typedef enum {
     VIR_DOMAIN_CONTROLLER_MODEL_PCI_ROOT,
     VIR_DOMAIN_CONTROLLER_MODEL_PCIE_ROOT,
     VIR_DOMAIN_CONTROLLER_MODEL_PCI_BRIDGE,
+    VIR_DOMAIN_CONTROLLER_MODEL_DMI_TO_PCI_BRIDGE,
 
     VIR_DOMAIN_CONTROLLER_MODEL_PCI_LAST
 } virDomainControllerModelPCI;
index 08406b8b73e7520731dd3547a033deb45902a889..47cc07aeabb2163b1e754fc9732ce4122a7a68c3 100644 (file)
@@ -234,6 +234,7 @@ VIR_ENUM_IMPL(virQEMUCaps, QEMU_CAPS_LAST,
 
               "vnc-share-policy", /* 150 */
               "device-del-event",
+              "dmi-to-pci-bridge",
     );
 
 struct _virQEMUCaps {
@@ -1381,6 +1382,7 @@ struct virQEMUCapsStringFlags virQEMUCapsObjectTypes[] = {
     { "pci-bridge", QEMU_CAPS_DEVICE_PCI_BRIDGE },
     { "vfio-pci", QEMU_CAPS_DEVICE_VFIO_PCI },
     { "scsi-generic", QEMU_CAPS_DEVICE_SCSI_GENERIC },
+    { "i82801b11-bridge", QEMU_CAPS_DEVICE_DMI_TO_PCI_BRIDGE },
 };
 
 static struct virQEMUCapsStringFlags virQEMUCapsObjectPropsVirtioBlk[] = {
index f5f685df26b62a51105a63e80273ad82e5785049..074e55d8690164459bab4b6b72dad6740429a2be 100644 (file)
@@ -190,6 +190,7 @@ enum virQEMUCapsFlags {
     QEMU_CAPS_MLOCK              = 149, /* -realtime mlock=on|off */
     QEMU_CAPS_VNC_SHARE_POLICY   = 150, /* set display sharing policy */
     QEMU_CAPS_DEVICE_DEL_EVENT   = 151, /* DEVICE_DELETED event */
+    QEMU_CAPS_DEVICE_DMI_TO_PCI_BRIDGE  = 152, /* -device i82801b11-bridge */
 
     QEMU_CAPS_LAST,                   /* this must always be the last item */
 };
index 8ac39ff9cc435817e2ce2d9f3aa029fd5eac8c6c..50f37ae5ccf2137de94d2218c471f9dc2c835c29 100644 (file)
@@ -1561,6 +1561,13 @@ qemuDomainPCIAddressBusSetModel(qemuDomainPCIAddressBusPtr bus,
         bus->minSlot = 1;
         bus->maxSlot = QEMU_PCI_ADDRESS_SLOT_LAST;
         break;
+    case VIR_DOMAIN_CONTROLLER_MODEL_DMI_TO_PCI_BRIDGE:
+        /* slots 1 - 31, standard PCI slots,
+         * but *not* hot-pluggable */
+        bus->flags = QEMU_PCI_CONNECT_TYPE_PCI;
+        bus->minSlot = 1;
+        bus->maxSlot = QEMU_PCI_ADDRESS_SLOT_LAST;
+        break;
     default:
         virReportError(VIR_ERR_INTERNAL_ERROR,
                        _("Invalid PCI controller model %d"), model);
@@ -1669,6 +1676,12 @@ qemuCollectPCIAddress(virDomainDefPtr def ATTRIBUTE_UNUSED,
              */
             flags = QEMU_PCI_CONNECT_TYPE_PCI;
             break;
+        case VIR_DOMAIN_CONTROLLER_MODEL_DMI_TO_PCI_BRIDGE:
+            /* pci-bridge needs a PCIe slot, but it isn't
+             * hot-pluggable, so it doesn't need a hot-pluggable slot.
+             */
+            flags = QEMU_PCI_CONNECT_TYPE_PCIE;
+            break;
         default:
             break;
         }
@@ -2372,6 +2385,12 @@ qemuAssignDevicePCISlots(virDomainDefPtr def,
                  */
                 flags = QEMU_PCI_CONNECT_TYPE_PCI;
                 break;
+            case VIR_DOMAIN_CONTROLLER_MODEL_DMI_TO_PCI_BRIDGE:
+                /* dmi-to-pci-bridge requires a non-hotplug PCIe
+                 * slot
+                 */
+                flags = QEMU_PCI_CONNECT_TYPE_PCIE;
+                break;
             default:
                 flags = QEMU_PCI_CONNECT_HOTPLUGGABLE | QEMU_PCI_CONNECT_TYPE_PCI;
                 break;
@@ -4351,6 +4370,20 @@ qemuBuildControllerDevStr(virDomainDefPtr domainDef,
             virBufferAsprintf(&buf, "pci-bridge,chassis_nr=%d,id=pci.%d",
                               def->idx, def->idx);
             break;
+        case VIR_DOMAIN_CONTROLLER_MODEL_DMI_TO_PCI_BRIDGE:
+            if (!virQEMUCapsGet(qemuCaps, QEMU_CAPS_DEVICE_DMI_TO_PCI_BRIDGE)) {
+                virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+                               _("The dmi-to-pci-bridge (i82801b11-bridge) "
+                                 "controller is not supported in this QEMU binary"));
+                goto error;
+            }
+            if (def->idx == 0) {
+                virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+                               _("dmi-to-pci-bridge index should be > 0"));
+                goto error;
+            }
+            virBufferAsprintf(&buf, "i82801b11-bridge,id=pci.%d", def->idx);
+            break;
         case VIR_DOMAIN_CONTROLLER_MODEL_PCI_ROOT:
         case VIR_DOMAIN_CONTROLLER_MODEL_PCIE_ROOT:
             virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
index 4d04609a42c7be34d36790b8c9db19a0c53bdfe0..206d471287ab2bfcb2ab41a2f2c33e5112358c2d 100644 (file)
@@ -760,12 +760,23 @@ qemuDomainDefPostParse(virDomainDefPtr def,
             VIR_DOMAIN_CONTROLLER_MODEL_PCI_ROOT) < 0)
         return -1;
 
-    if (addPCIeRoot &&
-        virDomainDefMaybeAddController(
-            def, VIR_DOMAIN_CONTROLLER_TYPE_PCI, 0,
-            VIR_DOMAIN_CONTROLLER_MODEL_PCIE_ROOT) < 0)
+    /* When a machine has a pcie-root, make sure that there is always
+     * a dmi-to-pci-bridge controller added as bus 1, and a pci-bridge
+     * as bus 2, so that standard PCI devices can be connected
+     */
+    if (addPCIeRoot) {
+        if (virDomainDefMaybeAddController(
+                def, VIR_DOMAIN_CONTROLLER_TYPE_PCI, 0,
+                VIR_DOMAIN_CONTROLLER_MODEL_PCIE_ROOT) < 0 ||
+            virDomainDefMaybeAddController(
+                def, VIR_DOMAIN_CONTROLLER_TYPE_PCI, 1,
+                VIR_DOMAIN_CONTROLLER_MODEL_DMI_TO_PCI_BRIDGE) < 0 ||
+            virDomainDefMaybeAddController(
+                def, VIR_DOMAIN_CONTROLLER_TYPE_PCI, 2,
+                VIR_DOMAIN_CONTROLLER_MODEL_PCI_BRIDGE) < 0) {
         return -1;
-
+        }
+    }
     return 0;
 }
 
index e9371898b036ca3ba4d4ce7fe6d597a867e0c1cd..23db85cbef5baf6cd2d7a9aa574a38492e4dc4dd 100644 (file)
@@ -1,4 +1,5 @@
 LC_ALL=C PATH=/bin HOME=/home/test USER=test LOGNAME=test /usr/libexec/qemu-kvm \
 -S -M q35 -m 2048 -smp 2 -nographic -nodefaults \
 -monitor unix:/tmp/test-monitor,server,nowait -no-acpi -boot c \
--device pci-bridge,chassis_nr=1,id=pci.1,bus=pci.1,addr=0x1 -usb
+-device i82801b11-bridge,id=pci.1,bus=pci.0,addr=0x1 \
+-device pci-bridge,chassis_nr=2,id=pci.2,bus=pci.1,addr=0x1 -usb
diff --git a/tests/qemuxml2argvdata/qemuxml2argv-q35.args b/tests/qemuxml2argvdata/qemuxml2argv-q35.args
new file mode 100644 (file)
index 0000000..ddff6f0
--- /dev/null
@@ -0,0 +1,7 @@
+LC_ALL=C PATH=/bin HOME=/home/test USER=test LOGNAME=test \
+/usr/libexec/qemu-kvm -S -M q35 -m 2048 -smp 2 -nographic -nodefaults \
+-monitor unix:/tmp/test-monitor,server,nowait -no-acpi -boot c \
+-device i82801b11-bridge,id=pci.1,bus=pci.0,addr=0x1 \
+-device pci-bridge,chassis_nr=2,id=pci.2,bus=pci.1,addr=0x1 \
+-usb \
+-vga qxl -global qxl.ram_size=67108864 -global qxl.vram_size=18874368
diff --git a/tests/qemuxml2argvdata/qemuxml2argv-q35.xml b/tests/qemuxml2argvdata/qemuxml2argv-q35.xml
new file mode 100644 (file)
index 0000000..3541b14
--- /dev/null
@@ -0,0 +1,25 @@
+<domain type='qemu'>
+  <name>q35-test</name>
+  <uuid>11dbdcdd-4c3b-482b-8903-9bdb8c0a2774</uuid>
+  <memory unit='KiB'>2097152</memory>
+  <currentMemory unit='KiB'>2097152</currentMemory>
+  <vcpu placement='static' cpuset='0-1'>2</vcpu>
+  <os>
+    <type arch='x86_64' machine='q35'>hvm</type>
+    <boot dev='hd'/>
+  </os>
+  <clock offset='utc'/>
+  <on_poweroff>destroy</on_poweroff>
+  <on_reboot>restart</on_reboot>
+  <on_crash>destroy</on_crash>
+  <devices>
+    <emulator>/usr/libexec/qemu-kvm</emulator>
+    <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'/>
+    <video>
+      <model type='qxl' ram='65536' vram='18432' heads='1'/>
+    </video>
+    <memballoon model='none'/>
+  </devices>
+</domain>
index 57c6989e32c3e459764a9dda2d5efa7fcf3ab690..aba0f88b6697e368f9aa35309f0dbf8b5ff17d1a 100644 (file)
@@ -995,7 +995,13 @@ mymain(void)
     DO_TEST("pci-bridge-many-disks",
             QEMU_CAPS_DEVICE, QEMU_CAPS_DRIVE, QEMU_CAPS_DEVICE_PCI_BRIDGE);
     DO_TEST("pcie-root",
-            QEMU_CAPS_DEVICE, QEMU_CAPS_DEVICE_PCI_BRIDGE);
+            QEMU_CAPS_DEVICE, QEMU_CAPS_DEVICE_PCI_BRIDGE,
+            QEMU_CAPS_DEVICE_DMI_TO_PCI_BRIDGE);
+    DO_TEST("q35",
+            QEMU_CAPS_DEVICE, QEMU_CAPS_DEVICE_PCI_BRIDGE,
+            QEMU_CAPS_DEVICE_DMI_TO_PCI_BRIDGE,
+            QEMU_CAPS_VGA, QEMU_CAPS_DEVICE_VIDEO_PRIMARY,
+            QEMU_CAPS_VGA, QEMU_CAPS_VGA_QXL, QEMU_CAPS_DEVICE_QXL);
 
     DO_TEST("hostdev-scsi-lsi", QEMU_CAPS_DRIVE,
             QEMU_CAPS_DEVICE, QEMU_CAPS_DRIVE,
diff --git a/tests/qemuxml2xmloutdata/qemuxml2xmlout-pcie-root.xml b/tests/qemuxml2xmloutdata/qemuxml2xmlout-pcie-root.xml
new file mode 100644 (file)
index 0000000..25c77f1
--- /dev/null
@@ -0,0 +1,23 @@
+<domain type='qemu'>
+  <name>q35-test</name>
+  <uuid>11dbdcdd-4c3b-482b-8903-9bdb8c0a2774</uuid>
+  <memory unit='KiB'>2097152</memory>
+  <currentMemory unit='KiB'>2097152</currentMemory>
+  <vcpu placement='static' cpuset='0-1'>2</vcpu>
+  <os>
+    <type arch='x86_64' machine='q35'>hvm</type>
+    <boot dev='hd'/>
+  </os>
+  <clock offset='utc'/>
+  <on_poweroff>destroy</on_poweroff>
+  <on_reboot>restart</on_reboot>
+  <on_crash>destroy</on_crash>
+  <devices>
+    <emulator>/usr/libexec/qemu-kvm</emulator>
+    <controller type='pci' index='0' model='pcie-root'/>
+    <controller type='usb' index='0'/>
+    <controller type='pci' index='1' model='dmi-to-pci-bridge'/>
+    <controller type='pci' index='2' model='pci-bridge'/>
+    <memballoon model='none'/>
+  </devices>
+</domain>
index ea511b8565aeafb8a30fec7c53ef740bd270007e..8b4590af28f42b7fa90d270433f8bac366072a47 100644 (file)
@@ -294,7 +294,8 @@ mymain(void)
     DO_TEST_DIFFERENT("pci-bridge-many-disks");
     DO_TEST_DIFFERENT("pci-autoadd-addr");
     DO_TEST_DIFFERENT("pci-autoadd-idx");
-    DO_TEST("pcie-root");
+    DO_TEST_DIFFERENT("pcie-root");
+    DO_TEST("q35");
 
     DO_TEST("hostdev-scsi-lsi");
     DO_TEST("hostdev-scsi-virtio-scsi");