diff --git a/docs/formatdomain.html.in b/docs/formatdomain.html.in index 49c7c8d71c..6a2e121f42 100644 --- a/docs/formatdomain.html.in +++ b/docs/formatdomain.html.in @@ -2338,27 +2338,40 @@

PCI controllers have an optional model attribute with - possible values pci-root or pci-bridge. - For machine types which provide an implicit pci bus, the pci-root + possible values pci-root, pcie-root + or pci-bridge. + 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-root has no address. 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 configuration. - (since 1.0.5) + (pci-root and pci-bridge since 1.0.5)

   ...
   <devices>
     <controller type='pci' index='0' model='pci-root'/>
     <controller type='pci' index='1' model='pci-bridge'>
-      <address type='pci' domain='0' bus='0' slot='5' function='0' multifunction=off'/>
+      <address type='pci' domain='0' bus='0' slot='5' function='0' multifunction='off'/>
     </controller>
   </devices>
+  ...
+ +

+ For machine types which provide an implicit PCI Express (PCIe) + bus (for example, the machine types based on the Q35 chipset), + 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. (since 1.1.2). +

+
+  ...
+  <devices>
+    <controller type='pci' index='0' model='pcie-root'/>
+  </devices>
   ...

Device leases

diff --git a/docs/schemas/domaincommon.rng b/docs/schemas/domaincommon.rng index 745b959a8f..e04be12337 100644 --- a/docs/schemas/domaincommon.rng +++ b/docs/schemas/domaincommon.rng @@ -1538,6 +1538,7 @@ pci-root + pcie-root pci-bridge diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c index 63350b6eb0..59a96f2d10 100644 --- a/src/conf/domain_conf.c +++ b/src/conf/domain_conf.c @@ -310,6 +310,7 @@ 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") VIR_ENUM_IMPL(virDomainControllerModelSCSI, VIR_DOMAIN_CONTROLLER_MODEL_SCSI_LAST, @@ -5714,16 +5715,17 @@ virDomainControllerDefParseXML(xmlNodePtr node, case VIR_DOMAIN_CONTROLLER_TYPE_PCI: switch (def->model) { case VIR_DOMAIN_CONTROLLER_MODEL_PCI_ROOT: + case VIR_DOMAIN_CONTROLLER_MODEL_PCIE_ROOT: if (def->info.type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_NONE) { virReportError(VIR_ERR_XML_ERROR, "%s", - _("pci-root controller should not " + _("pci-root and pcie-root controllers should not " "have an address")); goto error; } if (def->idx != 0) { virReportError(VIR_ERR_XML_ERROR, "%s", - _("pci-root controller should have " - "index 0")); + _("pci-root and pcie-root controllers " + "should have index 0")); goto error; } diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h index de3b59c690..63a1444780 100644 --- a/src/conf/domain_conf.h +++ b/src/conf/domain_conf.h @@ -768,6 +768,7 @@ enum virDomainControllerType { typedef enum { VIR_DOMAIN_CONTROLLER_MODEL_PCI_ROOT, + VIR_DOMAIN_CONTROLLER_MODEL_PCIE_ROOT, VIR_DOMAIN_CONTROLLER_MODEL_PCI_BRIDGE, VIR_DOMAIN_CONTROLLER_MODEL_PCI_LAST diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c index 2886e013cb..8ac39ff9cc 100644 --- a/src/qemu/qemu_command.c +++ b/src/qemu/qemu_command.c @@ -1453,6 +1453,12 @@ qemuDomainPCIAddressFlagsCompatible(virDevicePCIAddressPtr addr, "device. Device requires a standard PCI slot, " "which is not provided by this bus"), addr->domain, addr->bus); + } else if (devFlags & QEMU_PCI_CONNECT_TYPE_PCIE) { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("PCI bus %.4x:%.2x is not compatible with the " + "device. Device requires a PCI Express slot, " + "which is not provided by this bus"), + addr->domain, addr->bus); } else { /* this should never happen. If it does, there is a * bug in the code that sets the flag bits for devices. @@ -1549,6 +1555,12 @@ qemuDomainPCIAddressBusSetModel(qemuDomainPCIAddressBusPtr bus, bus->minSlot = 1; bus->maxSlot = QEMU_PCI_ADDRESS_SLOT_LAST; break; + case VIR_DOMAIN_CONTROLLER_MODEL_PCIE_ROOT: + /* slots 1 - 31, PCIe devices only, no hotplug */ + bus->flags = QEMU_PCI_CONNECT_TYPE_PCIE; + bus->minSlot = 1; + bus->maxSlot = QEMU_PCI_ADDRESS_SLOT_LAST; + break; default: virReportError(VIR_ERR_INTERNAL_ERROR, _("Invalid PCI controller model %d"), model); @@ -2350,7 +2362,8 @@ qemuAssignDevicePCISlots(virDomainDefPtr def, continue; switch (def->controllers[i]->model) { case VIR_DOMAIN_CONTROLLER_MODEL_PCI_ROOT: - /* pci-root is implicit in the machine, + case VIR_DOMAIN_CONTROLLER_MODEL_PCIE_ROOT: + /* pci-root and pcie-root are implicit in the machine, * and needs no address */ continue; case VIR_DOMAIN_CONTROLLER_MODEL_PCI_BRIDGE: @@ -4339,8 +4352,9 @@ qemuBuildControllerDevStr(virDomainDefPtr domainDef, def->idx, def->idx); break; case VIR_DOMAIN_CONTROLLER_MODEL_PCI_ROOT: + case VIR_DOMAIN_CONTROLLER_MODEL_PCIE_ROOT: virReportError(VIR_ERR_INTERNAL_ERROR, "%s", - _("wrong function called for pci-root")); + _("wrong function called for pci-root/pcie-root")); return NULL; } break; @@ -7618,9 +7632,10 @@ qemuBuildCommandLine(virConnectPtr conn, continue; } - /* Skip pci-root */ + /* Skip pci-root/pcie-root */ if (cont->type == VIR_DOMAIN_CONTROLLER_TYPE_PCI && - cont->model == VIR_DOMAIN_CONTROLLER_MODEL_PCI_ROOT) { + (cont->model == VIR_DOMAIN_CONTROLLER_MODEL_PCI_ROOT || + cont->model == VIR_DOMAIN_CONTROLLER_MODEL_PCIE_ROOT)) { continue; } diff --git a/src/qemu/qemu_command.h b/src/qemu/qemu_command.h index bf4953aeaf..e5111d203e 100644 --- a/src/qemu/qemu_command.h +++ b/src/qemu/qemu_command.h @@ -233,13 +233,15 @@ typedef enum { QEMU_PCI_CONNECT_TYPE_PCI = 1 << 2, /* PCI devices can connect to this bus */ + QEMU_PCI_CONNECT_TYPE_PCIE = 1 << 3, + /* PCI Express devices can connect to this bus */ } qemuDomainPCIConnectFlags; /* a combination of all bit that describe the type of connections * allowed, e.g. PCI, PCIe, switch */ # define QEMU_PCI_CONNECT_TYPES_MASK \ - QEMU_PCI_CONNECT_TYPE_PCI + (QEMU_PCI_CONNECT_TYPE_PCI | QEMU_PCI_CONNECT_TYPE_PCIE) int qemuDomainAssignPCIAddresses(virDomainDefPtr def, diff --git a/src/qemu/qemu_domain.c b/src/qemu/qemu_domain.c index d3da6669b9..4d04609a42 100644 --- a/src/qemu/qemu_domain.c +++ b/src/qemu/qemu_domain.c @@ -701,6 +701,7 @@ qemuDomainDefPostParse(virDomainDefPtr def, { bool addDefaultUSB = true; bool addPCIRoot = false; + bool addPCIeRoot = false; /* check for emulator and create a default one if needed */ if (!def->emulator && @@ -713,12 +714,16 @@ qemuDomainDefPostParse(virDomainDefPtr def, case VIR_ARCH_X86_64: if (!def->os.machine) break; - if (STRPREFIX(def->os.machine, "pc-q35") || - STREQ(def->os.machine, "q35") || - STREQ(def->os.machine, "isapc")) { + if (STREQ(def->os.machine, "isapc")) { addDefaultUSB = false; break; } + if (STRPREFIX(def->os.machine, "pc-q35") || + STREQ(def->os.machine, "q35")) { + addPCIeRoot = true; + addDefaultUSB = false; + break; + } if (!STRPREFIX(def->os.machine, "pc-0.") && !STRPREFIX(def->os.machine, "pc-1.") && !STRPREFIX(def->os.machine, "pc-i440") && @@ -755,6 +760,12 @@ 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) + return -1; + return 0; } @@ -1421,7 +1432,7 @@ qemuDomainDefFormatBuf(virQEMUDriverPtr driver, if (pci && pci->idx == 0 && pci->model == VIR_DOMAIN_CONTROLLER_MODEL_PCI_ROOT) { - VIR_DEBUG("Removing default 'pci-root' from domain '%s'" + VIR_DEBUG("Removing default pci-root from domain '%s'" " for migration compatibility", def->name); toremove++; } else { diff --git a/tests/qemuxml2argvdata/qemuxml2argv-pcie-root.args b/tests/qemuxml2argvdata/qemuxml2argv-pcie-root.args new file mode 100644 index 0000000000..e9371898b0 --- /dev/null +++ b/tests/qemuxml2argvdata/qemuxml2argv-pcie-root.args @@ -0,0 +1,4 @@ +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 diff --git a/tests/qemuxml2argvdata/qemuxml2argv-pcie-root.xml b/tests/qemuxml2argvdata/qemuxml2argv-pcie-root.xml new file mode 100644 index 0000000000..1aa54558de --- /dev/null +++ b/tests/qemuxml2argvdata/qemuxml2argv-pcie-root.xml @@ -0,0 +1,21 @@ + + q35-test + 11dbdcdd-4c3b-482b-8903-9bdb8c0a2774 + 2097152 + 2097152 + 2 + + hvm + + + + destroy + restart + destroy + + /usr/libexec/qemu-kvm + + + + + diff --git a/tests/qemuxml2argvtest.c b/tests/qemuxml2argvtest.c index b7485fc992..57c6989e32 100644 --- a/tests/qemuxml2argvtest.c +++ b/tests/qemuxml2argvtest.c @@ -994,6 +994,8 @@ mymain(void) DO_TEST("pci-autoadd-idx", QEMU_CAPS_DEVICE, QEMU_CAPS_DEVICE_PCI_BRIDGE); 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); DO_TEST("hostdev-scsi-lsi", QEMU_CAPS_DRIVE, QEMU_CAPS_DEVICE, QEMU_CAPS_DRIVE, diff --git a/tests/qemuxml2xmltest.c b/tests/qemuxml2xmltest.c index 66be40e648..ea511b8565 100644 --- a/tests/qemuxml2xmltest.c +++ b/tests/qemuxml2xmltest.c @@ -294,6 +294,7 @@ 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("hostdev-scsi-lsi"); DO_TEST("hostdev-scsi-virtio-scsi");