From: Li Zhang <zhlcindy(a)linux.vnet.ibm.com>
PPC supports VFIO by assigning iommu groups to guests manually. It needs
the QEMU command line to support it. The command line is as the following:
-device spapr-pci-vfio-host-bridge,iommu=1,id=SOMEBUS,index=123
This patch will get the iommu group by XML configuration, and all these
devices in the iommu group need to be detached manually before the guest
is created.
Signed-off-by: Li Zhang <zhlcindy(a)linux.vnet.ibm.com>
---
src/qemu/qemu_command.c | 55 ++++++++++++++++++++++++++++++++++++++++++-------
src/qemu/qemu_command.h | 3 +++
2 files changed, 51 insertions(+), 7 deletions(-)
diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c
index 1521431..64f6ba0 100644
--- a/src/qemu/qemu_command.c
+++ b/src/qemu/qemu_command.c
@@ -5368,6 +5368,35 @@ qemuOpenPCIConfig(virDomainHostdevDefPtr dev)
}
char *
+qemuBuildSPAPRVFIODevStr(virDomainHostdevDefPtr dev,
+ virQEMUCapsPtr qemuCaps)
+{
+ int iommuGroup;
+ virPCIDeviceAddressPtr addr;
+ virBuffer buf = VIR_BUFFER_INITIALIZER;
+
+ addr = (virPCIDeviceAddressPtr)&dev->source.subsys.u.pci.addr;
+ if ((iommuGroup = virPCIDeviceAddressGetIOMMUGroupNum(addr)) < 0)
+ goto cleanup;
+ if (!virQEMUCapsGet(qemuCaps, QEMU_CAPS_SPAPR_VFIO_BRIDGE)) {
+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
+ _("SPAPR_VFIO_BRIDGE is not supported by QEMU"));
+ goto cleanup;
+ }
+
+ virBufferAddLit(&buf, "spapr-pci-vfio-host-bridge");
+ virBufferAsprintf(&buf, ",iommu=%d", iommuGroup);
+ virBufferAsprintf(&buf, ",id=VFIOBUS%d", iommuGroup);
+ virBufferAsprintf(&buf, ",index=%d", iommuGroup + 1);
+
+ return virBufferContentAndReset(&buf);
+
+cleanup:
+ virBufferFreeAndReset(&buf);
+ return NULL;
+}
+
+char *
qemuBuildPCIHostdevDevStr(virDomainDefPtr def,
virDomainHostdevDefPtr dev,
const char *configfd,
@@ -9221,13 +9250,25 @@ qemuBuildCommandLine(virConnectPtr conn,
VIR_COMMAND_PASS_FD_CLOSE_PARENT);
}
}
- virCommandAddArg(cmd, "-device");
- devstr = qemuBuildPCIHostdevDevStr(def, hostdev, configfd_name,
qemuCaps);
- VIR_FREE(configfd_name);
- if (!devstr)
- goto error;
- virCommandAddArg(cmd, devstr);
- VIR_FREE(devstr);
+ if (virQEMUCapsGet(qemuCaps, QEMU_CAPS_SPAPR_VFIO_BRIDGE) &&
+ hostdev->source.subsys.u.pci.backend ==
+ VIR_DOMAIN_HOSTDEV_PCI_BACKEND_VFIO &&
+ def->os.arch == VIR_ARCH_PPC64) {
+ virCommandAddArg(cmd, "-device");
+ devstr = qemuBuildSPAPRVFIODevStr(hostdev, qemuCaps);
+ if (!devstr)
+ goto error;
+ virCommandAddArg(cmd, devstr);
+ VIR_FREE(devstr);
+ } else {
+ virCommandAddArg(cmd, "-device");
+ devstr = qemuBuildPCIHostdevDevStr(def, hostdev, configfd_name,
qemuCaps);
+ VIR_FREE(configfd_name);
+ if (!devstr)
+ goto error;
+ virCommandAddArg(cmd, devstr);
+ VIR_FREE(devstr);
+ }
} else if (virQEMUCapsGet(qemuCaps, QEMU_CAPS_PCIDEVICE)) {
virCommandAddArg(cmd, "-pcidevice");
if (!(devstr = qemuBuildPCIHostdevPCIDevStr(hostdev)))
diff --git a/src/qemu/qemu_command.h b/src/qemu/qemu_command.h
index 2f248eb..c764788 100644
--- a/src/qemu/qemu_command.h
+++ b/src/qemu/qemu_command.h
@@ -153,6 +153,9 @@ char * qemuBuildPCIHostdevDevStr(virDomainDefPtr def,
virDomainHostdevDefPtr dev,
const char *configfd,
virQEMUCapsPtr qemuCaps);
+char *
+qemuBuildSPAPRVFIODevStr(virDomainHostdevDefPtr dev,
+ virQEMUCapsPtr qemuCaps);
int qemuOpenPCIConfig(virDomainHostdevDefPtr dev);
--
1.8.1.4