PCI controllers have an optional model attribute with
possible values pci-root, pcie-root,
- pci-bridge, or dmi-to-pci-bridge.
+ pcie-root-port, pci-bridge,
+ or dmi-to-pci-bridge.
(pci-root and pci-bridge since 1.0.5,
pcie-root and dmi-to-pci-bridge since
- 1.1.2)
+ 1.1.2, pcie-root-port since 1.2.19)
The root controllers (pci-root and pcie-root)
have an optional pcihole64 element specifying how big
(in kilobytes, or in the unit specified by pcihole64's
@@ -3079,6 +3080,23 @@
the index attribute of the pci controller). If set, chassisNr
must be between 0 and 255.
+
chassis
+
+ pcie-root-port controllers can also have
+ a chassis attribute in
+ the <target> subelement, which is used to
+ set the controller's "chassis" configuration value, which is
+ visible to the virtual machine. If set, chassis must be
+ between 0 and 255.
+
+
port
+
+ pcie-root-port controllers can also have a port
+ attribute in the <target> subelement, which
+ is used to set the controller's "port" configuration value,
+ which is visible to the virtual machine. If set, port must be
+ between 0 and 255.
+
For machine types which provide an implicit PCI bus, the pci-root
@@ -3125,6 +3143,17 @@
auto-determined by libvirt will be placed on this pci-bridge
device. (since 1.1.2).
+
+ Domains with an implicit pcie-root can also add controllers
+ with model='pcie-root-port'. This is a simple type of
+ bridge device that can connect only to one of the 31 slots on
+ the pcie-root bus on the upstream side, and makes a single
+ (PCIe, hotpluggable) port (at slot='0') available on the
+ downstream side. This controller can be used to provide a single
+ slot to later hotplug a PCIe device (but is not itself
+ hotpluggable - it must be in the configuration when the domain
+ is started). (since 1.2.19)
+
...
<devices>
diff --git a/docs/schemas/domaincommon.rng b/docs/schemas/domaincommon.rng
index a61e209824..7d7f4122f5 100644
--- a/docs/schemas/domaincommon.rng
+++ b/docs/schemas/domaincommon.rng
@@ -1739,6 +1739,8 @@
pci-bridgei82801b11-bridge
+
+ ioh3420
@@ -1751,6 +1753,16 @@
+
+
+
+
+
+
+
+
+
+
@@ -1774,6 +1786,7 @@
pci-bridgedmi-to-pci-bridge
+ pcie-root-port
diff --git a/src/conf/domain_addr.c b/src/conf/domain_addr.c
index 9519f79062..c2a207b73c 100644
--- a/src/conf/domain_addr.c
+++ b/src/conf/domain_addr.c
@@ -183,9 +183,9 @@ virDomainPCIAddressBusSetModel(virDomainPCIAddressBusPtr bus,
case VIR_DOMAIN_CONTROLLER_MODEL_PCIE_ROOT:
/* slots 1 - 31, no hotplug, PCIe only unless the address was
* specified in user config *and* the particular device being
- * attached also allows it
+ * attached also allows it.
*/
- bus->flags = VIR_PCI_CONNECT_TYPE_PCIE;
+ bus->flags = VIR_PCI_CONNECT_TYPE_PCIE | VIR_PCI_CONNECT_TYPE_PCIE_ROOT;
bus->minSlot = 1;
bus->maxSlot = VIR_PCI_ADDRESS_SLOT_LAST;
break;
@@ -196,6 +196,12 @@ virDomainPCIAddressBusSetModel(virDomainPCIAddressBusPtr bus,
bus->minSlot = 1;
bus->maxSlot = VIR_PCI_ADDRESS_SLOT_LAST;
break;
+ case VIR_DOMAIN_CONTROLLER_MODEL_PCIE_ROOT_PORT:
+ /* provides one slot which is pcie and hotpluggable */
+ bus->flags = VIR_PCI_CONNECT_TYPE_PCIE | VIR_PCI_CONNECT_HOTPLUGGABLE;
+ bus->minSlot = 0;
+ bus->maxSlot = 0;
+ break;
default:
virReportError(VIR_ERR_INTERNAL_ERROR,
_("Invalid PCI controller model %d"), model);
diff --git a/src/conf/domain_addr.h b/src/conf/domain_addr.h
index dcfd2e5f72..2a0ff96ea5 100644
--- a/src/conf/domain_addr.h
+++ b/src/conf/domain_addr.h
@@ -39,6 +39,8 @@ typedef enum {
/* PCI devices can connect to this bus */
VIR_PCI_CONNECT_TYPE_PCIE = 1 << 3,
/* PCI Express devices can connect to this bus */
+ VIR_PCI_CONNECT_TYPE_PCIE_ROOT = 1 << 4,
+ /* for devices that can only connect to pcie-root (i.e. root-port) */
} virDomainPCIConnectFlags;
typedef struct {
@@ -70,7 +72,8 @@ typedef virDomainPCIAddressSet *virDomainPCIAddressSetPtr;
* allowed, e.g. PCI, PCIe, switch
*/
# define VIR_PCI_CONNECT_TYPES_MASK \
- (VIR_PCI_CONNECT_TYPE_PCI | VIR_PCI_CONNECT_TYPE_PCIE)
+ (VIR_PCI_CONNECT_TYPE_PCI | VIR_PCI_CONNECT_TYPE_PCIE | \
+ VIR_PCI_CONNECT_TYPE_PCIE_ROOT)
/* combination of all bits that could be used to connect a normal
* endpoint device (i.e. excluding the connection possible between an
diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
index ec5088c349..d92f88cdc9 100644
--- a/src/conf/domain_conf.c
+++ b/src/conf/domain_conf.c
@@ -324,13 +324,15 @@ VIR_ENUM_IMPL(virDomainControllerModelPCI, VIR_DOMAIN_CONTROLLER_MODEL_PCI_LAST,
"pci-root",
"pcie-root",
"pci-bridge",
- "dmi-to-pci-bridge")
+ "dmi-to-pci-bridge",
+ "pcie-root-port")
VIR_ENUM_IMPL(virDomainControllerPCIModelName,
VIR_DOMAIN_CONTROLLER_PCI_MODEL_NAME_LAST,
"none",
"pci-bridge",
- "i82801b11-bridge")
+ "i82801b11-bridge",
+ "ioh3420")
VIR_ENUM_IMPL(virDomainControllerModelSCSI, VIR_DOMAIN_CONTROLLER_MODEL_SCSI_LAST,
"auto",
@@ -1552,6 +1554,8 @@ virDomainControllerDefNew(virDomainControllerType type)
break;
case VIR_DOMAIN_CONTROLLER_TYPE_PCI:
def->opts.pciopts.chassisNr = -1;
+ def->opts.pciopts.chassis = -1;
+ def->opts.pciopts.port = -1;
break;
case VIR_DOMAIN_CONTROLLER_TYPE_IDE:
case VIR_DOMAIN_CONTROLLER_TYPE_FDC:
@@ -7814,6 +7818,8 @@ virDomainControllerDefParseXML(xmlNodePtr node,
char *modelName = NULL;
bool processedTarget = false;
char *chassisNr = NULL;
+ char *chassis = NULL;
+ char *port = NULL;
xmlNodePtr saved = ctxt->node;
int rc;
@@ -7874,6 +7880,8 @@ virDomainControllerDefParseXML(xmlNodePtr node,
goto error;
}
chassisNr = virXMLPropString(cur, "chassisNr");
+ chassis = virXMLPropString(cur, "chassis");
+ port = virXMLPropString(cur, "port");
processedTarget = true;
}
}
@@ -8008,6 +8016,40 @@ virDomainControllerDefParseXML(xmlNodePtr node,
goto error;
}
}
+ if (chassis) {
+ if (virStrToLong_i(chassis, NULL, 0,
+ &def->opts.pciopts.chassis) < 0) {
+ virReportError(VIR_ERR_XML_ERROR,
+ _("Invalid chassis '%s' in PCI controller"),
+ chassis);
+ goto error;
+ }
+ if (def->opts.pciopts.chassis < 0 ||
+ def->opts.pciopts.chassis > 255) {
+ virReportError(VIR_ERR_XML_ERROR,
+ _("PCI controller chassis '%s' out of range "
+ "- must be 0-255"),
+ chassis);
+ goto error;
+ }
+ }
+ if (port) {
+ if (virStrToLong_i(port, NULL, 0,
+ &def->opts.pciopts.port) < 0) {
+ virReportError(VIR_ERR_XML_ERROR,
+ _("Invalid port '%s' in PCI controller"),
+ port);
+ goto error;
+ }
+ if (def->opts.pciopts.port < 0 ||
+ def->opts.pciopts.port > 255) {
+ virReportError(VIR_ERR_XML_ERROR,
+ _("PCI controller port '%s' out of range "
+ "- must be 0-255"),
+ port);
+ goto error;
+ }
+ }
break;
default:
@@ -8035,6 +8077,8 @@ virDomainControllerDefParseXML(xmlNodePtr node,
VIR_FREE(max_sectors);
VIR_FREE(modelName);
VIR_FREE(chassisNr);
+ VIR_FREE(chassis);
+ VIR_FREE(port);
return def;
@@ -19089,7 +19133,9 @@ virDomainControllerDefFormat(virBufferPtr buf,
pcihole64 = true;
if (def->opts.pciopts.modelName != VIR_DOMAIN_CONTROLLER_PCI_MODEL_NAME_NONE)
pciModel = true;
- if (def->opts.pciopts.chassisNr != -1)
+ if (def->opts.pciopts.chassisNr != -1 ||
+ def->opts.pciopts.chassis != -1 ||
+ def->opts.pciopts.port != -1)
pciTarget = true;
break;
@@ -19119,6 +19165,12 @@ virDomainControllerDefFormat(virBufferPtr buf,
if (def->opts.pciopts.chassisNr != -1)
virBufferAsprintf(buf, " chassisNr='%d'",
def->opts.pciopts.chassisNr);
+ if (def->opts.pciopts.chassis != -1)
+ virBufferAsprintf(buf, " chassis='%d'",
+ def->opts.pciopts.chassis);
+ if (def->opts.pciopts.port != -1)
+ virBufferAsprintf(buf, " port='0x%x'",
+ def->opts.pciopts.port);
virBufferAddLit(buf, "/>\n");
}
diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h
index cd0b6a7168..aba55ea307 100644
--- a/src/conf/domain_conf.h
+++ b/src/conf/domain_conf.h
@@ -752,6 +752,7 @@ typedef enum {
VIR_DOMAIN_CONTROLLER_MODEL_PCIE_ROOT,
VIR_DOMAIN_CONTROLLER_MODEL_PCI_BRIDGE,
VIR_DOMAIN_CONTROLLER_MODEL_DMI_TO_PCI_BRIDGE,
+ VIR_DOMAIN_CONTROLLER_MODEL_PCIE_ROOT_PORT,
VIR_DOMAIN_CONTROLLER_MODEL_PCI_LAST
} virDomainControllerModelPCI;
@@ -760,6 +761,7 @@ typedef enum {
VIR_DOMAIN_CONTROLLER_PCI_MODEL_NAME_NONE,
VIR_DOMAIN_CONTROLLER_PCI_MODEL_NAME_PCI_BRIDGE,
VIR_DOMAIN_CONTROLLER_PCI_MODEL_NAME_I82801B11_BRIDGE,
+ VIR_DOMAIN_CONTROLLER_PCI_MODEL_NAME_IOH3420,
VIR_DOMAIN_CONTROLLER_PCI_MODEL_NAME_LAST
} virDomainControllerPCIModelName;
@@ -820,7 +822,11 @@ struct _virDomainPCIControllerOpts {
* compatibility.
*/
int chassisNr; /* used by pci-bridge, -1 == unspecified */
- };
+ /* chassis & port used by
+ * pcie-root-port/pcie-switch-downstream-port, -1 = unspecified */
+ int chassis;
+ int port;
+};
/* Stores the virtual disk controller configuration */
struct _virDomainControllerDef {
diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c
index 49397c1a93..921cec6ef1 100644
--- a/src/qemu/qemu_command.c
+++ b/src/qemu/qemu_command.c
@@ -2283,6 +2283,7 @@ qemuDomainAssignPCIAddresses(virDomainDefPtr def,
if (options->modelName == VIR_DOMAIN_CONTROLLER_PCI_MODEL_NAME_NONE)
options->modelName = VIR_DOMAIN_CONTROLLER_PCI_MODEL_NAME_I82801B11_BRIDGE;
break;
+ case VIR_DOMAIN_CONTROLLER_MODEL_PCIE_ROOT_PORT:
case VIR_DOMAIN_CONTROLLER_MODEL_PCI_ROOT:
case VIR_DOMAIN_CONTROLLER_MODEL_PCIE_ROOT:
case VIR_DOMAIN_CONTROLLER_MODEL_PCI_LAST:
diff --git a/tests/qemuxml2argvdata/qemuxml2argv-pcie-root-port.xml b/tests/qemuxml2argvdata/qemuxml2argv-pcie-root-port.xml
new file mode 100644
index 0000000000..bc28a71484
--- /dev/null
+++ b/tests/qemuxml2argvdata/qemuxml2argv-pcie-root-port.xml
@@ -0,0 +1,36 @@
+
+ q35-test
+ 11dbdcdd-4c3b-482b-8903-9bdb8c0a2774
+ 2097152
+ 2097152
+ 2
+
+ hvm
+
+
+
+ destroy
+ restart
+ destroy
+
+ /usr/libexec/qemu-kvm
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/tests/qemuxml2xmltest.c b/tests/qemuxml2xmltest.c
index 7a41a18704..6b48bf4ab3 100644
--- a/tests/qemuxml2xmltest.c
+++ b/tests/qemuxml2xmltest.c
@@ -567,6 +567,7 @@ mymain(void)
DO_TEST_DIFFERENT("pci-autoadd-idx");
DO_TEST_DIFFERENT("pcie-root");
DO_TEST_DIFFERENT("q35");
+ DO_TEST("pcie-root-port");
DO_TEST("hostdev-scsi-lsi");
DO_TEST("hostdev-scsi-virtio-scsi");