This patch will get the iommu group for host devices by XML configuration
of the vfio host bridge controller or from the sysfs.
On pseries, the iommu group can be shared by multiple host devices and
they would share the same spapr-vfio-host-bus controller. A new
controller is added for every new iommu group. Every spapr-vfio-host-bridge
in the cli creates a new pci domain in the guest. For Example,
-device spapr-pci-vfio-host-bridge,iommu=1,id=SOMEDOMAIN,index=1
The "SOMEDOMAIN" is the id for new pci domain inside guest.
spapr-pci-vfio-host-bridge is actually a PCI host bridge with VFIO support.
It hosts pci-bridges, and has all the features/behaviours similar to the
default emulated pci host bridge. The controller can host both pci and pcie
devices. For convenience, this root controller uses model "pci-root".
The sample controller tags would look like below:
<controller type='spapr-vfio-pci' index='0' model='pci-root'
iommuGroupNum='3' domain='1'/>
<controller type='spapr-vfio-pci' index='1' model='pci-bridge'
iommuGroupNum='3' domain='1'>
<address type='pci' domain='0x0001' bus='0x00'
slot='0x02'
function='0x0'/>
</controller>
<controller type='spapr-vfio-pci' index='0' model='pci-root'
iommuGroupNum='13' domain='2'/>
Like other architectures, unassigned and unmanaged devices in the iommu group
need to be detached manually before the guest is created .
The spapr-vfio-pci controllers are removed when there are no corresponding
hostdevices in xml.
Signed-off-by: Shivaprasad G Bhat <sbhat(a)linux.vnet.ibm.com>
Signed-off-by: Pradipta Kumar Banerjee <bpradip(a)in.ibm.com>
Reviewed-by: Prerna Saxena <prerna(a)linux.vnet.ibm.com>
---
docs/schemas/domaincommon.rng | 28 +++++++
src/bhyve/bhyve_domain.c | 2
src/conf/domain_conf.c | 165 +++++++++++++++++++++++++++++++++++++++--
src/conf/domain_conf.h | 19 +++++
src/libvirt_private.syms | 1
src/qemu/qemu_command.c | 4 +
src/qemu/qemu_domain.c | 12 +--
src/qemu/qemu_driver.c | 6 +
8 files changed, 222 insertions(+), 15 deletions(-)
diff --git a/docs/schemas/domaincommon.rng b/docs/schemas/domaincommon.rng
index 6863ec6..580c481 100644
--- a/docs/schemas/domaincommon.rng
+++ b/docs/schemas/domaincommon.rng
@@ -1783,6 +1783,34 @@
</group>
</choice>
</group>
+ <!-- spapr-vfio-pci has a default "model" -->
+ <group>
+ <attribute name="type">
+ <value>spapr-vfio-pci</value>
+ </attribute>
+ <attribute name="iommuGroupNum">
+ <ref name="unsignedInt"/>
+ </attribute>
+ <attribute name="domain">
+ <ref name="unsignedInt"/>
+ </attribute>
+ <choice>
+ <group>
+ <attribute name="model">
+ <choice>
+ <value>pci-root</value>
+ </choice>
+ </attribute>
+ </group>
+ <group>
+ <attribute name="model">
+ <choice>
+ <value>pci-bridge</value>
+ </choice>
+ </attribute>
+ </group>
+ </choice>
+ </group>
<!-- virtio-serial has optional "ports" and "vectors"
-->
<group>
<attribute name="type">
diff --git a/src/bhyve/bhyve_domain.c b/src/bhyve/bhyve_domain.c
index ecb1758..96d30ab 100644
--- a/src/bhyve/bhyve_domain.c
+++ b/src/bhyve/bhyve_domain.c
@@ -63,7 +63,7 @@ bhyveDomainDefPostParse(virDomainDefPtr def,
void *opaque ATTRIBUTE_UNUSED)
{
/* Add an implicit PCI root controller */
- if (virDomainDefMaybeAddController(def, VIR_DOMAIN_CONTROLLER_TYPE_PCI, 0,
+ if (virDomainDefMaybeAddController(def, VIR_DOMAIN_CONTROLLER_TYPE_PCI, 0, 0,
VIR_DOMAIN_CONTROLLER_MODEL_PCI_ROOT) < 0)
return -1;
diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
index 5f4b9f6..6d0d118 100644
--- a/src/conf/domain_conf.c
+++ b/src/conf/domain_conf.c
@@ -34,6 +34,7 @@
#include "datatypes.h"
#include "domain_conf.h"
#include "snapshot_conf.h"
+#include "virpci.h"
#include "viralloc.h"
#include "verify.h"
#include "virxml.h"
@@ -327,7 +328,8 @@ VIR_ENUM_IMPL(virDomainController, VIR_DOMAIN_CONTROLLER_TYPE_LAST,
"virtio-serial",
"ccid",
"usb",
- "pci")
+ "pci",
+ "spapr-vfio-pci")
VIR_ENUM_IMPL(virDomainControllerModelPCI, VIR_DOMAIN_CONTROLLER_MODEL_PCI_LAST,
"pci-root",
@@ -2925,6 +2927,8 @@ virDomainDefRejectDuplicateControllers(virDomainDefPtr def)
/* multiple USB controllers with the same index are allowed */
max_idx[VIR_DOMAIN_CONTROLLER_TYPE_USB] = -1;
+ /* The idx can be same across different pci domains */
+ max_idx[VIR_DOMAIN_CONTROLLER_TYPE_SPAPR_PCI_VFIO] = -1;
for (i = 0; i < VIR_DOMAIN_CONTROLLER_TYPE_LAST; i++) {
if (max_idx[i] >= 0 && !(bitmaps[i] = virBitmapNew(max_idx[i] + 1)))
@@ -6521,6 +6525,8 @@ virDomainControllerModelTypeFromString(const virDomainControllerDef
*def,
return virDomainControllerModelUSBTypeFromString(model);
else if (def->type == VIR_DOMAIN_CONTROLLER_TYPE_PCI)
return virDomainControllerModelPCITypeFromString(model);
+ else if (def->type == VIR_DOMAIN_CONTROLLER_TYPE_SPAPR_PCI_VFIO)
+ return virDomainControllerModelPCITypeFromString(model);
return -1;
}
@@ -6693,7 +6699,48 @@ virDomainControllerDefParseXML(xmlNodePtr node,
def->opts.pciopts.pcihole64size = VIR_DIV_UP(bytes, 1024);
}
}
+ break;
+ case VIR_DOMAIN_CONTROLLER_TYPE_SPAPR_PCI_VFIO: {
+ char *iommuStr = NULL;
+ char *domainStr = NULL;
+
+ def->domain = -1;
+ def->opts.spaprvfio.iommuGroupNum = -1;
+ if (def->model == VIR_DOMAIN_CONTROLLER_MODEL_PCI_ROOT) {
+ if (def->idx != 0) {
+ virReportError(VIR_ERR_XML_ERROR, "%s",
+ _("pci-root and pcie-root controllers "
+ "should have index 0"));
+ goto error;
+ }
+ }
+ domainStr = virXMLPropString(node, "domain");
+ if (domainStr) {
+ int r = virStrToLong_i(domainStr, NULL, 10,
+ &def->domain);
+ if (r != 0 || def->domain <= 0) {
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ _("Invalid domain number: %s"), domainStr);
+ VIR_FREE(domainStr);
+ goto error;
+ }
+ }
+ VIR_FREE(domainStr);
+ iommuStr = virXMLPropString(node, "iommuGroupNum");
+ if (iommuStr) {
+ int r = virStrToLong_i(iommuStr, NULL, 10,
+ &def->opts.spaprvfio.iommuGroupNum);
+ if (r != 0 || def->opts.spaprvfio.iommuGroupNum < 0) {
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ _("Invalid iommu group number: %s"), iommuStr);
+ VIR_FREE(iommuStr);
+ goto error;
+ }
+ }
+ VIR_FREE(iommuStr);
+ break;
+ }
default:
break;
}
@@ -11987,6 +12034,7 @@ virDomainVcpuPinDefParseXML(xmlNodePtr node,
int
virDomainDefMaybeAddController(virDomainDefPtr def,
int type,
+ int domain,
int idx,
int model)
{
@@ -11995,6 +12043,7 @@ virDomainDefMaybeAddController(virDomainDefPtr def,
for (i = 0; i < def->ncontrollers; i++) {
if (def->controllers[i]->type == type &&
+ def->controllers[i]->domain == domain &&
def->controllers[i]->idx == idx)
return 0;
}
@@ -12003,6 +12052,7 @@ virDomainDefMaybeAddController(virDomainDefPtr def,
return -1;
cont->type = type;
+ cont->domain = domain;
cont->idx = idx;
cont->model = model;
@@ -12010,6 +12060,8 @@ virDomainDefMaybeAddController(virDomainDefPtr def,
cont->opts.vioserial.ports = -1;
cont->opts.vioserial.vectors = -1;
}
+ if (cont->type == VIR_DOMAIN_CONTROLLER_TYPE_SPAPR_PCI_VFIO)
+ cont->opts.spaprvfio.iommuGroupNum = -1;
if (VIR_APPEND_ELEMENT(def->controllers, def->ncontrollers, cont) < 0) {
VIR_FREE(cont);
@@ -12113,6 +12165,95 @@ virDomainResourceDefParse(xmlNodePtr node,
return NULL;
}
+int
+virDomainDefMaybeAddHostdevSpaprPCIVfioControllers(virDomainDefPtr def)
+{
+ size_t i, j;
+ virDomainHostdevDefPtr hostdev;
+ virDomainControllerDefPtr controller;
+ int ret = -1;
+ int maxDomainId = 0;
+ int skip;
+
+ if (!(ARCH_IS_PPC64(def->os.arch)) ||
+ !(def->os.machine && STRPREFIX(def->os.machine,
"pseries")))
+ return 0;
+
+ for (i = 0; i < def->nhostdevs; i++) {
+ hostdev = def->hostdevs[i];
+ if (IS_PCI_VFIO_HOSTDEV(hostdev))
+ hostdev->source.subsys.u.pci.iommu = -1;
+ }
+ /* The hostdevs belonging to same iommu are
+ * all part of same domain.
+ */
+ for (i = 0; i < def->ncontrollers; i++) {
+ controller = def->controllers[i];
+ if (controller->type == VIR_DOMAIN_CONTROLLER_TYPE_SPAPR_PCI_VFIO &&
+ controller->model == VIR_DOMAIN_CONTROLLER_MODEL_PCI_ROOT)
+ for (j = 0; j < def->nhostdevs; j++) {
+ hostdev = def->hostdevs[j];
+ if (IS_PCI_VFIO_HOSTDEV(hostdev))
+ if (hostdev->info->addr.pci.domain == controller->domain)
+ hostdev->source.subsys.u.pci.iommu =
controller->opts.spaprvfio.iommuGroupNum;
+ }
+ if (controller->domain > maxDomainId)
+ maxDomainId = controller->domain;
+ }
+ /* If the spapr-vfio controller doesnt exist for the hostdev
+ * add a controller for that iommu group.
+ */
+ for (i = 0; i < def->nhostdevs; i++) {
+ skip = 0;
+ hostdev = def->hostdevs[i];
+ if (IS_PCI_VFIO_HOSTDEV(hostdev)) {
+ virPCIDeviceAddressPtr addr;
+ int iommu = -1;
+ if (hostdev->source.subsys.u.pci.iommu == -1) {
+ addr =
(virPCIDeviceAddressPtr)&hostdev->source.subsys.u.pci.addr;
+ if ((iommu = virPCIDeviceAddressGetIOMMUGroupNum(addr)) < 0)
+ goto error;
+ hostdev->source.subsys.u.pci.iommu = iommu;
+
+ for (j = 0; j < def->ncontrollers; j++) {
+ controller = def->controllers[j];
+ if (controller->type == VIR_DOMAIN_CONTROLLER_TYPE_SPAPR_PCI_VFIO
&&
+ controller->model == VIR_DOMAIN_CONTROLLER_MODEL_PCI_ROOT) {
+ if (iommu == controller->opts.spaprvfio.iommuGroupNum)
+ skip = 1;
+ }
+ }
+ if (skip)
+ continue;
+ if (virDomainDefMaybeAddController(def,
VIR_DOMAIN_CONTROLLER_TYPE_SPAPR_PCI_VFIO,
+ ++maxDomainId, 0,
VIR_DOMAIN_CONTROLLER_MODEL_PCI_ROOT) < 0)
+ goto error;
+
def->controllers[def->ncontrollers-1]->opts.spaprvfio.iommuGroupNum = iommu;
+ }
+ }
+ }
+
+ /* Remove redundant controllers which dont serve any hostdevs. */
+ for (i = 0; i < def->ncontrollers; i++) {
+ controller = def->controllers[i];
+ if (controller->type == VIR_DOMAIN_CONTROLLER_TYPE_SPAPR_PCI_VFIO) {
+ int usedController = 0;
+ for (j = 0; j < def->nhostdevs; j++) {
+ hostdev = def->hostdevs[j];
+ if (IS_PCI_VFIO_HOSTDEV(hostdev))
+ if (hostdev->source.subsys.u.pci.iommu ==
controller->opts.spaprvfio.iommuGroupNum)
+ usedController = 1;
+ }
+ if (!usedController)
+ VIR_DELETE_ELEMENT(def->controllers, i, def->ncontrollers);
+ }
+ }
+
+ ret = 0;
+ error:
+ return ret;
+}
+
static int
virDomainDefMaybeAddHostdevSCSIcontroller(virDomainDefPtr def)
{
@@ -12134,7 +12275,7 @@ virDomainDefMaybeAddHostdevSCSIcontroller(virDomainDefPtr def)
return 0;
for (i = 0; i <= maxController; i++) {
- if (virDomainDefMaybeAddController(def, VIR_DOMAIN_CONTROLLER_TYPE_SCSI, i, -1)
< 0)
+ if (virDomainDefMaybeAddController(def, VIR_DOMAIN_CONTROLLER_TYPE_SCSI, 0, i,
-1) < 0)
return -1;
}
@@ -15592,7 +15733,7 @@ virDomainDefAddDiskControllersForType(virDomainDefPtr def,
return 0;
for (i = 0; i <= maxController; i++) {
- if (virDomainDefMaybeAddController(def, controllerType, i, -1) < 0)
+ if (virDomainDefMaybeAddController(def, controllerType, 0, i, -1) < 0)
return -1;
}
@@ -15615,7 +15756,7 @@ virDomainDefMaybeAddVirtioSerialController(virDomainDefPtr def)
idx = channel->info.addr.vioserial.controller;
if (virDomainDefMaybeAddController(def,
- VIR_DOMAIN_CONTROLLER_TYPE_VIRTIO_SERIAL, idx, -1) < 0)
+ VIR_DOMAIN_CONTROLLER_TYPE_VIRTIO_SERIAL, 0, idx, -1) < 0)
return -1;
}
}
@@ -15630,7 +15771,7 @@ virDomainDefMaybeAddVirtioSerialController(virDomainDefPtr def)
idx = console->info.addr.vioserial.controller;
if (virDomainDefMaybeAddController(def,
- VIR_DOMAIN_CONTROLLER_TYPE_VIRTIO_SERIAL, idx, -1) < 0)
+ VIR_DOMAIN_CONTROLLER_TYPE_VIRTIO_SERIAL, 0, idx, -1) < 0)
return -1;
}
}
@@ -15670,7 +15811,7 @@ virDomainDefMaybeAddSmartcardController(virDomainDefPtr def)
if (virDomainDefMaybeAddController(def,
VIR_DOMAIN_CONTROLLER_TYPE_CCID,
- idx, -1) < 0)
+ 0, idx, -1) < 0)
return -1;
}
@@ -15715,6 +15856,9 @@ virDomainDefAddImplicitControllers(virDomainDefPtr def)
if (virDomainDefMaybeAddHostdevSCSIcontroller(def) < 0)
return -1;
+ if (virDomainDefMaybeAddHostdevSpaprPCIVfioControllers(def) < 0)
+ return -1;
+
return 0;
}
@@ -16521,6 +16665,8 @@ virDomainControllerModelTypeToString(virDomainControllerDefPtr
def,
return virDomainControllerModelUSBTypeToString(model);
else if (def->type == VIR_DOMAIN_CONTROLLER_TYPE_PCI)
return virDomainControllerModelPCITypeToString(model);
+ else if (def->type == VIR_DOMAIN_CONTROLLER_TYPE_SPAPR_PCI_VFIO)
+ return virDomainControllerModelPCITypeToString(model);
return NULL;
}
@@ -16573,7 +16719,12 @@ virDomainControllerDefFormat(virBufferPtr buf,
if (def->opts.pciopts.pcihole64)
pcihole64 = true;
break;
-
+ case VIR_DOMAIN_CONTROLLER_TYPE_SPAPR_PCI_VFIO:
+ virBufferAsprintf(buf, " iommuGroupNum='%d'",
+ def->opts.spaprvfio.iommuGroupNum);
+ virBufferAsprintf(buf, " domain='%d'",
+ def->domain);
+ break;
default:
break;
}
diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h
index 530a3ca..014075c 100644
--- a/src/conf/domain_conf.h
+++ b/src/conf/domain_conf.h
@@ -419,6 +419,7 @@ typedef virDomainHostdevSubsysPCI *virDomainHostdevSubsysPCIPtr;
struct _virDomainHostdevSubsysPCI {
virDevicePCIAddress addr; /* host address */
int backend; /* enum virDomainHostdevSubsysPCIBackendType */
+ int iommu;
};
typedef struct _virDomainHostdevSubsysSCSIHost virDomainHostdevSubsysSCSIHost;
@@ -692,6 +693,7 @@ typedef enum {
VIR_DOMAIN_CONTROLLER_TYPE_CCID,
VIR_DOMAIN_CONTROLLER_TYPE_USB,
VIR_DOMAIN_CONTROLLER_TYPE_PCI,
+ VIR_DOMAIN_CONTROLLER_TYPE_SPAPR_PCI_VFIO,
VIR_DOMAIN_CONTROLLER_TYPE_LAST
} virDomainControllerType;
@@ -749,6 +751,12 @@ struct _virDomainPCIControllerOpts {
unsigned long pcihole64size;
};
+typedef struct _virDomainSPAPRVfioControllerOpts virDomainSPAPRVfioControllerOpts;
+typedef virDomainSPAPRVfioControllerOpts *virDomainiSPAPRVfioControllerOptsPtr;
+struct _virDomainSPAPRVfioControllerOpts {
+ int iommuGroupNum;
+};
+
/* Stores the virtual disk controller configuration */
struct _virDomainControllerDef {
int type;
@@ -757,9 +765,11 @@ struct _virDomainControllerDef {
unsigned int queues;
unsigned int cmd_per_lun;
unsigned int max_sectors;
+ int domain;
union {
virDomainVirtioSerialOpts vioserial;
virDomainPCIControllerOpts pciopts;
+ virDomainSPAPRVfioControllerOpts spaprvfio;
} opts;
virDomainDeviceInfo info;
};
@@ -2817,12 +2827,15 @@ void virDomainListFree(virDomainPtr *list);
int
virDomainDefMaybeAddController(virDomainDefPtr def,
int type,
+ int domain,
int idx,
int model);
int
virDomainDefMaybeAddInput(virDomainDefPtr def,
int type,
int bus);
+int
+virDomainDefMaybeAddHostdevSpaprPCIVfioControllers(virDomainDefPtr def);
char *virDomainDefGetDefaultEmulator(virDomainDefPtr def, virCapsPtr caps);
@@ -2862,6 +2875,12 @@ virDomainParseMemory(const char *xpath,
bool required,
bool capped);
+# define IS_PCI_VFIO_HOSTDEV(dvc) \
+ (((dvc)->mode == VIR_DOMAIN_HOSTDEV_MODE_SUBSYS) && \
+ ((dvc)->source.subsys.type == VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_PCI) && \
+ (((dvc)->source.subsys.u.pci.backend == VIR_DOMAIN_HOSTDEV_PCI_BACKEND_VFIO) ||
\
+ ((dvc)->source.subsys.u.pci.backend == VIR_DOMAIN_HOSTDEV_PCI_BACKEND_DEFAULT)))
+
bool virDomainDefNeedsPlacementAdvice(virDomainDefPtr def)
ATTRIBUTE_NONNULL(1);
diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
index 0864618..e6ff977 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -197,6 +197,7 @@ virDomainDefFree;
virDomainDefGetDefaultEmulator;
virDomainDefGetSecurityLabelDef;
virDomainDefMaybeAddController;
+virDomainDefMaybeAddHostdevSpaprPCIVfioControllers;
virDomainDefMaybeAddInput;
virDomainDefNeedsPlacementAdvice;
virDomainDefNew;
diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c
index 1399ce4..6f10e6d 100644
--- a/src/qemu/qemu_command.c
+++ b/src/qemu/qemu_command.c
@@ -560,6 +560,8 @@ qemuNetworkPrepareDevices(virDomainDefPtr def)
}
if (virDomainHostdevInsert(def, hostdev) < 0)
goto cleanup;
+ if (virDomainDefMaybeAddHostdevSpaprPCIVfioControllers(def) < 0)
+ goto cleanup;
}
}
ret = 0;
@@ -1499,7 +1501,7 @@ qemuDomainAssignPCIAddresses(virDomainDefPtr def,
virDomainPCIAddressBusPtr bus = &addrs->buses[i];
if ((rv = virDomainDefMaybeAddController(
- def, VIR_DOMAIN_CONTROLLER_TYPE_PCI,
+ def, VIR_DOMAIN_CONTROLLER_TYPE_PCI, 0,
i, bus->model)) < 0)
goto cleanup;
/* If we added a new bridge, we will need one more address */
diff --git a/src/qemu/qemu_domain.c b/src/qemu/qemu_domain.c
index 01bf39b..c3c3e89 100644
--- a/src/qemu/qemu_domain.c
+++ b/src/qemu/qemu_domain.c
@@ -998,17 +998,17 @@ qemuDomainDefPostParse(virDomainDefPtr def,
if (addDefaultUSB &&
virDomainDefMaybeAddController(
- def, VIR_DOMAIN_CONTROLLER_TYPE_USB, 0, -1) < 0)
+ def, VIR_DOMAIN_CONTROLLER_TYPE_USB, 0, 0, -1) < 0)
return -1;
if (addImplicitSATA &&
virDomainDefMaybeAddController(
- def, VIR_DOMAIN_CONTROLLER_TYPE_SATA, 0, -1) < 0)
+ def, VIR_DOMAIN_CONTROLLER_TYPE_SATA, 0, 0, -1) < 0)
return -1;
if (addPCIRoot &&
virDomainDefMaybeAddController(
- def, VIR_DOMAIN_CONTROLLER_TYPE_PCI, 0,
+ def, VIR_DOMAIN_CONTROLLER_TYPE_PCI, 0, 0,
VIR_DOMAIN_CONTROLLER_MODEL_PCI_ROOT) < 0)
return -1;
@@ -1018,13 +1018,13 @@ qemuDomainDefPostParse(virDomainDefPtr def,
*/
if (addPCIeRoot) {
if (virDomainDefMaybeAddController(
- def, VIR_DOMAIN_CONTROLLER_TYPE_PCI, 0,
+ def, VIR_DOMAIN_CONTROLLER_TYPE_PCI, 0, 0,
VIR_DOMAIN_CONTROLLER_MODEL_PCIE_ROOT) < 0 ||
virDomainDefMaybeAddController(
- def, VIR_DOMAIN_CONTROLLER_TYPE_PCI, 1,
+ def, VIR_DOMAIN_CONTROLLER_TYPE_PCI, 0, 1,
VIR_DOMAIN_CONTROLLER_MODEL_DMI_TO_PCI_BRIDGE) < 0 ||
virDomainDefMaybeAddController(
- def, VIR_DOMAIN_CONTROLLER_TYPE_PCI, 2,
+ def, VIR_DOMAIN_CONTROLLER_TYPE_PCI, 0, 2,
VIR_DOMAIN_CONTROLLER_MODEL_PCI_BRIDGE) < 0) {
return -1;
}
diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
index 9b19629..e533041 100644
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -7186,6 +7186,9 @@ qemuDomainAttachDeviceConfig(virQEMUCapsPtr qemuCaps,
net =
dev->data.net;
if (virDomainNetInsert(vmdef, net))
return -1;
+ if (dev->data.net->type == VIR_DOMAIN_NET_TYPE_HOSTDEV)
+ if (virDomainDefMaybeAddHostdevSpaprPCIVfioControllers(vmdef) < 0)
+ return -1;
dev->data.net = NULL;
if (qemuDomainAssignAddresses(vmdef, qemuCaps, NULL) < 0)
return -1;
@@ -7200,6 +7203,9 @@ qemuDomainAttachDeviceConfig(virQEMUCapsPtr qemuCaps,
}
if (virDomainHostdevInsert(vmdef, hostdev))
return -1;
+ if (IS_PCI_VFIO_HOSTDEV(hostdev))
+ if (virDomainDefMaybeAddHostdevSpaprPCIVfioControllers(vmdef) < 0)
+ return -1;
dev->data.hostdev = NULL;
if (qemuDomainAssignAddresses(vmdef, qemuCaps, NULL) < 0)
return -1;