VIR_FREE(def);
}
+
+/**
+ * virDomainControllerIsPCIHostBridge:
+ * @cont: controller
+ *
+ * Checks whether @cont is a PCI Host Bridge (PHB), a specific type
+ * of PCI controller used by pSeries guests.
+ *
+ * Returns: true if @cont is a PHB, false otherwise.
+ */
+bool
+virDomainControllerIsPCIHostBridge(const virDomainControllerDef *cont)
+{
+ virDomainControllerPCIModelName name;
+
+ /* PHBs are pci-root controllers */
+ if (cont->type != VIR_DOMAIN_CONTROLLER_TYPE_PCI ||
+ cont->model != VIR_DOMAIN_CONTROLLER_MODEL_PCI_ROOT) {
+ return false;
+ }
+
+ name = cont->opts.pciopts.modelName;
+
+ /* The actual device used for PHBs is spapr-pci-host-bridge */
+ if (name != VIR_DOMAIN_CONTROLLER_PCI_MODEL_NAME_SPAPR_PCI_HOST_BRIDGE)
+ return false;
+
+ return true;
+}
+
+
virDomainFSDefPtr
virDomainFSDefNew(void)
{
virDomainDiskDefPtr virDomainDiskFindByBusAndDst(virDomainDefPtr def,
int bus,
char *dst);
+
+virDomainControllerDefPtr virDomainControllerDefNew(virDomainControllerType type);
void virDomainControllerDefFree(virDomainControllerDefPtr def);
+bool virDomainControllerIsPCIHostBridge(const virDomainControllerDef *cont);
+
virDomainFSDefPtr virDomainFSDefNew(void);
-virDomainControllerDefPtr
-virDomainControllerDefNew(virDomainControllerType type);
void virDomainFSDefFree(virDomainFSDefPtr def);
void virDomainActualNetDefFree(virDomainActualNetDefPtr def);
void virDomainNetDefClear(virDomainNetDefPtr def);
virDomainControllerFindUnusedIndex;
virDomainControllerInsert;
virDomainControllerInsertPreAlloced;
+virDomainControllerIsPCIHostBridge;
virDomainControllerModelPCITypeToString;
virDomainControllerModelSCSITypeFromString;
virDomainControllerModelSCSITypeToString;
static void
qemuDomainPCIControllerSetDefaultModelName(virDomainControllerDefPtr cont,
+ virDomainDefPtr def,
virQEMUCapsPtr qemuCaps)
{
int *modelName = &cont->opts.pciopts.modelName;
*modelName = VIR_DOMAIN_CONTROLLER_PCI_MODEL_NAME_PXB_PCIE;
break;
case VIR_DOMAIN_CONTROLLER_MODEL_PCI_ROOT:
+ if (qemuDomainIsPSeries(def))
+ *modelName = VIR_DOMAIN_CONTROLLER_PCI_MODEL_NAME_SPAPR_PCI_HOST_BRIDGE;
+ break;
case VIR_DOMAIN_CONTROLLER_MODEL_PCIE_ROOT:
case VIR_DOMAIN_CONTROLLER_MODEL_PCI_LAST:
break;
}
+/**
+ * qemuDomainAddressFindNewTargetIndex:
+ * @def: domain definition
+ *
+ * Find a target index that can be used for a PCI controller.
+ *
+ * Returns: an unused target index, or -1 if all available target
+ * indexes are already taken.
+ */
+static int
+qemuDomainAddressFindNewTargetIndex(virDomainDefPtr def)
+{
+ int targetIndex;
+ int ret = -1;
+
+ /* Try all indexes between 1 and 31 - QEMU only supports 32
+ * PHBs, and 0 is reserved for the default, implicit one */
+ for (targetIndex = 1; targetIndex <= 31; targetIndex++) {
+ bool found = false;
+ size_t i;
+
+ for (i = 0; i < def->ncontrollers; i++) {
+ virDomainControllerDefPtr cont = def->controllers[i];
+
+ /* Skip everything but PHBs */
+ if (!virDomainControllerIsPCIHostBridge(cont))
+ continue;
+
+ /* Stop looking as soon as we find a PHB that's
+ * already using this specific target index */
+ if (cont->opts.pciopts.targetIndex == targetIndex) {
+ found = true;
+ break;
+ }
+ }
+
+ /* If no existing PCI controller uses this index, great,
+ * it means it's free and we can return it to the caller */
+ if (!found) {
+ ret = targetIndex;
+ break;
+ }
+ }
+
+ return ret;
+}
+
+
static int
qemuDomainAddressFindNewBusNr(virDomainDefPtr def)
{
* device in qemu) for any controller that doesn't yet
* have it set.
*/
- qemuDomainPCIControllerSetDefaultModelName(cont, qemuCaps);
+ qemuDomainPCIControllerSetDefaultModelName(cont, def, qemuCaps);
/* set defaults for any other auto-generated config
* options for this controller that haven't been
goto cleanup;
}
break;
+ case VIR_DOMAIN_CONTROLLER_MODEL_PCI_ROOT:
+ if (!qemuDomainIsPSeries(def))
+ break;
+ if (options->targetIndex == -1) {
+ if (cont->idx == 0) {
+ /* The pci-root controller with controller index 0
+ * must always be assigned target index 0, because
+ * it represents the implicit PHB which is treated
+ * differently than all other PHBs */
+ options->targetIndex = 0;
+ } else {
+ /* For all other PHBs the target index doesn't need
+ * to match the controller index or have any
+ * particular value, really */
+ options->targetIndex = qemuDomainAddressFindNewTargetIndex(def);
+ }
+ }
+ if (options->targetIndex == -1) {
+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
+ _("No usable target index found for %d"),
+ addr->bus);
+ goto cleanup;
+ }
+ break;
case VIR_DOMAIN_CONTROLLER_MODEL_DMI_TO_PCI_BRIDGE:
case VIR_DOMAIN_CONTROLLER_MODEL_PCIE_SWITCH_UPSTREAM_PORT:
- case VIR_DOMAIN_CONTROLLER_MODEL_PCI_ROOT:
case VIR_DOMAIN_CONTROLLER_MODEL_PCIE_ROOT:
case VIR_DOMAIN_CONTROLLER_MODEL_PCI_LAST:
break;
<controller type='usb' index='0'>
<address type='pci' domain='0x0000' bus='0x00' slot='0x01' function='0x0'/>
</controller>
- <controller type='pci' index='0' model='pci-root'/>
+ <controller type='pci' index='0' model='pci-root'>
+ <model name='spapr-pci-host-bridge'/>
+ <target index='0'/>
+ </controller>
<controller type='scsi' index='0'>
<address type='spapr-vio' reg='0x2000'/>
</controller>
<controller type='usb' index='0'>
<address type='pci' domain='0x0000' bus='0x00' slot='0x01' function='0x0'/>
</controller>
- <controller type='pci' index='0' model='pci-root'/>
+ <controller type='pci' index='0' model='pci-root'>
+ <model name='spapr-pci-host-bridge'/>
+ <target index='0'/>
+ </controller>
<memballoon model='none'/>
<nvram>
<address type='spapr-vio' reg='0x4000'/>
<controller type='usb' index='0'>
<address type='pci' domain='0x0000' bus='0x00' slot='0x01' function='0x0'/>
</controller>
- <controller type='pci' index='0' model='pci-root'/>
+ <controller type='pci' index='0' model='pci-root'>
+ <model name='spapr-pci-host-bridge'/>
+ <target index='0'/>
+ </controller>
<serial type='pty'>
<target port='0'/>
<address type='spapr-vio' reg='0x30000000'/>
<controller type='usb' index='0'>
<address type='pci' domain='0x0000' bus='0x00' slot='0x01' function='0x0'/>
</controller>
- <controller type='pci' index='0' model='pci-root'/>
+ <controller type='pci' index='0' model='pci-root'>
+ <model name='spapr-pci-host-bridge'/>
+ <target index='0'/>
+ </controller>
<memballoon model='virtio'>
<address type='pci' domain='0x0000' bus='0x00' slot='0x06' function='0x0'/>
</memballoon>
<controller type='usb' index='0' model='pci-ohci'>
<address type='pci' domain='0x0000' bus='0x00' slot='0x01' function='0x0'/>
</controller>
- <controller type='pci' index='0' model='pci-root'/>
+ <controller type='pci' index='0' model='pci-root'>
+ <model name='spapr-pci-host-bridge'/>
+ <target index='0'/>
+ </controller>
<memballoon model='virtio'>
<address type='pci' domain='0x0000' bus='0x00' slot='0x06' function='0x0'/>
</memballoon>
<controller type='usb' index='0'>
<address type='pci' domain='0x0000' bus='0x00' slot='0x01' function='0x0'/>
</controller>
- <controller type='pci' index='0' model='pci-root'/>
+ <controller type='pci' index='0' model='pci-root'>
+ <model name='spapr-pci-host-bridge'/>
+ <target index='0'/>
+ </controller>
<memballoon model='none'/>
<nvram>
<address type='spapr-vio' reg='0x4000'/>
<controller type='usb' index='0'>
<address type='pci' domain='0x0000' bus='0x00' slot='0x01' function='0x0'/>
</controller>
- <controller type='pci' index='0' model='pci-root'/>
+ <controller type='pci' index='0' model='pci-root'>
+ <model name='spapr-pci-host-bridge'/>
+ <target index='0'/>
+ </controller>
<serial type='pty'>
<target port='0'/>
<address type='spapr-vio' reg='0x30000000'/>
<controller type='usb' index='0'>
<address type='pci' domain='0x0000' bus='0x00' slot='0x01' function='0x0'/>
</controller>
- <controller type='pci' index='0' model='pci-root'/>
+ <controller type='pci' index='0' model='pci-root'>
+ <model name='spapr-pci-host-bridge'/>
+ <target index='0'/>
+ </controller>
<serial type='pty'>
<target port='0'/>
<address type='spapr-vio' reg='0x30000000'/>