317 lines
10 KiB
Diff
317 lines
10 KiB
Diff
From 84d44b33a64b6fd7f77d021249d23dc054243ddf Mon Sep 17 00:00:00 2001
|
|
Message-Id: <84d44b33a64b6fd7f77d021249d23dc054243ddf@dist-git>
|
|
From: Yi Min Zhao <zyimin@linux.ibm.com>
|
|
Date: Mon, 8 Apr 2019 10:57:29 +0200
|
|
Subject: [PATCH] qemu: Add hotpluging support for PCI devices on S390 guests
|
|
MIME-Version: 1.0
|
|
Content-Type: text/plain; charset=UTF-8
|
|
Content-Transfer-Encoding: 8bit
|
|
|
|
This commit adds hotplug support for PCI devices on S390 guests.
|
|
There's no need to implement hot unplug for zPCI as QEMU implements
|
|
an unplug callback which will unplug both PCI and zPCI device in a
|
|
cascaded way.
|
|
Currently, the following PCI devices are supported:
|
|
virtio-blk-pci
|
|
virtio-net-pci
|
|
virtio-rng-pci
|
|
virtio-input-host-pci
|
|
virtio-keyboard-pci
|
|
virtio-mouse-pci
|
|
virtio-tablet-pci
|
|
vfio-pci
|
|
SCSIVhost device
|
|
|
|
Signed-off-by: Yi Min Zhao <zyimin@linux.ibm.com>
|
|
Reviewed-by: Boris Fiuczynski <fiuczy@linux.ibm.com>
|
|
Reviewed-by: Stefan Zimmermann <stzi@linux.ibm.com>
|
|
Reviewed-by: Bjoern Walk <bwalk@linux.ibm.com>
|
|
Reviewed-by: Ján Tomko <jtomko@redhat.com>
|
|
Reviewed-by: Andrea Bolognani <abologna@redhat.com>
|
|
|
|
(cherry picked from commit 1d1e264f13d14ed05838bae2fcec2ffef26671f2)
|
|
|
|
https://bugzilla.redhat.com/show_bug.cgi?id=1508149
|
|
|
|
Conflicts:
|
|
|
|
* src/qemu/qemu_hotplug.c
|
|
+ context
|
|
- missing 83fe11e950bc
|
|
|
|
Signed-off-by: Andrea Bolognani <abologna@redhat.com>
|
|
Message-Id: <20190408085732.28684-13-abologna@redhat.com>
|
|
Reviewed-by: Laine Stump <laine@redhat.com>
|
|
Reviewed-by: Ján Tomko <jtomko@redhat.com>
|
|
---
|
|
src/qemu/qemu_hotplug.c | 160 +++++++++++++++++++++++++++++++++++++---
|
|
1 file changed, 151 insertions(+), 9 deletions(-)
|
|
|
|
diff --git a/src/qemu/qemu_hotplug.c b/src/qemu/qemu_hotplug.c
|
|
index 776cd75474..abe2632556 100644
|
|
--- a/src/qemu/qemu_hotplug.c
|
|
+++ b/src/qemu/qemu_hotplug.c
|
|
@@ -154,6 +154,80 @@ qemuHotplugPrepareDiskAccess(virQEMUDriverPtr driver,
|
|
}
|
|
|
|
|
|
+static int
|
|
+qemuDomainAttachZPCIDevice(qemuMonitorPtr mon,
|
|
+ virDomainDeviceInfoPtr info)
|
|
+{
|
|
+ char *devstr_zpci = NULL;
|
|
+ int ret = -1;
|
|
+
|
|
+ if (!(devstr_zpci = qemuBuildZPCIDevStr(info)))
|
|
+ goto cleanup;
|
|
+
|
|
+ if (qemuMonitorAddDevice(mon, devstr_zpci) < 0)
|
|
+ goto cleanup;
|
|
+
|
|
+ ret = 0;
|
|
+
|
|
+ cleanup:
|
|
+ VIR_FREE(devstr_zpci);
|
|
+ return ret;
|
|
+}
|
|
+
|
|
+
|
|
+static int
|
|
+qemuDomainDetachZPCIDevice(qemuMonitorPtr mon,
|
|
+ virDomainDeviceInfoPtr info)
|
|
+{
|
|
+ char *zpciAlias = NULL;
|
|
+ int ret = -1;
|
|
+
|
|
+ if (virAsprintf(&zpciAlias, "zpci%d", info->addr.pci.zpci.uid) < 0)
|
|
+ goto cleanup;
|
|
+
|
|
+ if (qemuMonitorDelDevice(mon, zpciAlias) < 0)
|
|
+ goto cleanup;
|
|
+
|
|
+ ret = 0;
|
|
+
|
|
+ cleanup:
|
|
+ VIR_FREE(zpciAlias);
|
|
+ return ret;
|
|
+}
|
|
+
|
|
+
|
|
+static int
|
|
+qemuDomainAttachExtensionDevice(qemuMonitorPtr mon,
|
|
+ virDomainDeviceInfoPtr info)
|
|
+{
|
|
+ if (info->type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI ||
|
|
+ info->addr.pci.extFlags == VIR_PCI_ADDRESS_EXTENSION_NONE) {
|
|
+ return 0;
|
|
+ }
|
|
+
|
|
+ if (info->addr.pci.extFlags & VIR_PCI_ADDRESS_EXTENSION_ZPCI)
|
|
+ return qemuDomainAttachZPCIDevice(mon, info);
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+
|
|
+static int
|
|
+qemuDomainDetachExtensionDevice(qemuMonitorPtr mon,
|
|
+ virDomainDeviceInfoPtr info)
|
|
+{
|
|
+ if (info->type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI ||
|
|
+ info->addr.pci.extFlags == VIR_PCI_ADDRESS_EXTENSION_NONE) {
|
|
+ return 0;
|
|
+ }
|
|
+
|
|
+ if (info->addr.pci.extFlags & VIR_PCI_ADDRESS_EXTENSION_ZPCI)
|
|
+ return qemuDomainDetachZPCIDevice(mon, info);
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+
|
|
static int
|
|
qemuHotplugWaitForTrayEject(virQEMUDriverPtr driver,
|
|
virDomainObjPtr vm,
|
|
@@ -403,9 +477,14 @@ qemuDomainAttachDiskGeneric(virQEMUDriverPtr driver,
|
|
if (qemuBlockStorageSourceAttachApply(priv->mon, data) < 0)
|
|
goto exit_monitor;
|
|
|
|
- if (qemuMonitorAddDevice(priv->mon, devstr) < 0)
|
|
+ if (qemuDomainAttachExtensionDevice(priv->mon, &disk->info) < 0)
|
|
goto exit_monitor;
|
|
|
|
+ if (qemuMonitorAddDevice(priv->mon, devstr) < 0) {
|
|
+ ignore_value(qemuDomainDetachExtensionDevice(priv->mon, &disk->info));
|
|
+ goto exit_monitor;
|
|
+ }
|
|
+
|
|
if (qemuDomainObjExitMonitor(driver, vm) < 0) {
|
|
ret = -2;
|
|
goto error;
|
|
@@ -519,7 +598,16 @@ int qemuDomainAttachControllerDevice(virQEMUDriverPtr driver,
|
|
goto cleanup;
|
|
|
|
qemuDomainObjEnterMonitor(driver, vm);
|
|
- ret = qemuMonitorAddDevice(priv->mon, devstr);
|
|
+
|
|
+ if ((ret = qemuDomainAttachExtensionDevice(priv->mon,
|
|
+ &controller->info)) < 0) {
|
|
+ goto exit_monitor;
|
|
+ }
|
|
+
|
|
+ if ((ret = qemuMonitorAddDevice(priv->mon, devstr)) < 0)
|
|
+ ignore_value(qemuDomainDetachExtensionDevice(priv->mon, &controller->info));
|
|
+
|
|
+ exit_monitor:
|
|
if (qemuDomainObjExitMonitor(driver, vm) < 0) {
|
|
releaseaddr = false;
|
|
ret = -1;
|
|
@@ -969,6 +1057,7 @@ qemuDomainAttachNetDevice(virQEMUDriverPtr driver,
|
|
}
|
|
|
|
if (qemuDomainIsS390CCW(vm->def) &&
|
|
+ net->info.type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI &&
|
|
virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_CCW)) {
|
|
net->info.type = VIR_DOMAIN_DEVICE_ADDRESS_TYPE_CCW;
|
|
if (!(ccwaddrs = qemuDomainCCWAddrSetCreateFromDomain(vm->def)))
|
|
@@ -1038,7 +1127,15 @@ qemuDomainAttachNetDevice(virQEMUDriverPtr driver,
|
|
goto try_remove;
|
|
|
|
qemuDomainObjEnterMonitor(driver, vm);
|
|
+
|
|
+ if (qemuDomainAttachExtensionDevice(priv->mon, &net->info) < 0) {
|
|
+ ignore_value(qemuDomainObjExitMonitor(driver, vm));
|
|
+ virDomainAuditNet(vm, NULL, net, "attach", false);
|
|
+ goto try_remove;
|
|
+ }
|
|
+
|
|
if (qemuMonitorAddDevice(priv->mon, nicstr) < 0) {
|
|
+ ignore_value(qemuDomainDetachExtensionDevice(priv->mon, &net->info));
|
|
ignore_value(qemuDomainObjExitMonitor(driver, vm));
|
|
virDomainAuditNet(vm, NULL, net, "attach", false);
|
|
goto try_remove;
|
|
@@ -1256,8 +1353,16 @@ qemuDomainAttachHostPCIDevice(virQEMUDriverPtr driver,
|
|
goto error;
|
|
|
|
qemuDomainObjEnterMonitor(driver, vm);
|
|
- ret = qemuMonitorAddDeviceWithFd(priv->mon, devstr,
|
|
- configfd, configfd_name);
|
|
+
|
|
+ if ((ret = qemuDomainAttachExtensionDevice(priv->mon, hostdev->info)) < 0)
|
|
+ goto exit_monitor;
|
|
+
|
|
+ if ((ret = qemuMonitorAddDeviceWithFd(priv->mon, devstr,
|
|
+ configfd, configfd_name)) < 0) {
|
|
+ ignore_value(qemuDomainDetachExtensionDevice(priv->mon, hostdev->info));
|
|
+ }
|
|
+
|
|
+ exit_monitor:
|
|
if (qemuDomainObjExitMonitor(driver, vm) < 0)
|
|
goto error;
|
|
|
|
@@ -1913,9 +2018,14 @@ qemuDomainAttachRNGDevice(virQEMUDriverPtr driver,
|
|
if (qemuMonitorAddObject(priv->mon, &props, &objAlias) < 0)
|
|
goto exit_monitor;
|
|
|
|
- if (qemuMonitorAddDevice(priv->mon, devstr) < 0)
|
|
+ if (qemuDomainAttachExtensionDevice(priv->mon, &rng->info) < 0)
|
|
goto exit_monitor;
|
|
|
|
+ if (qemuMonitorAddDevice(priv->mon, devstr) < 0) {
|
|
+ ignore_value(qemuDomainDetachExtensionDevice(priv->mon, &rng->info));
|
|
+ goto exit_monitor;
|
|
+ }
|
|
+
|
|
if (qemuDomainObjExitMonitor(driver, vm) < 0) {
|
|
releaseaddr = false;
|
|
goto cleanup;
|
|
@@ -2407,8 +2517,16 @@ qemuDomainAttachSCSIVHostDevice(virQEMUDriverPtr driver,
|
|
|
|
qemuDomainObjEnterMonitor(driver, vm);
|
|
|
|
- ret = qemuMonitorAddDeviceWithFd(priv->mon, devstr, vhostfd, vhostfdName);
|
|
+ if ((ret = qemuDomainAttachExtensionDevice(priv->mon, hostdev->info)) < 0)
|
|
+ goto exit_monitor;
|
|
|
|
+ if ((ret = qemuMonitorAddDeviceWithFd(priv->mon, devstr, vhostfd,
|
|
+ vhostfdName)) < 0) {
|
|
+ ignore_value(qemuDomainDetachExtensionDevice(priv->mon, hostdev->info));
|
|
+ goto exit_monitor;
|
|
+ }
|
|
+
|
|
+ exit_monitor:
|
|
if (qemuDomainObjExitMonitor(driver, vm) < 0 || ret < 0)
|
|
goto audit;
|
|
|
|
@@ -2653,9 +2771,14 @@ qemuDomainAttachShmemDevice(virQEMUDriverPtr driver,
|
|
|
|
release_backing = true;
|
|
|
|
- if (qemuMonitorAddDevice(priv->mon, shmstr) < 0)
|
|
+ if (qemuDomainAttachExtensionDevice(priv->mon, &shmem->info) < 0)
|
|
goto exit_monitor;
|
|
|
|
+ if (qemuMonitorAddDevice(priv->mon, shmstr) < 0) {
|
|
+ ignore_value(qemuDomainDetachExtensionDevice(priv->mon, &shmem->info));
|
|
+ goto exit_monitor;
|
|
+ }
|
|
+
|
|
if (qemuDomainObjExitMonitor(driver, vm) < 0) {
|
|
release_address = false;
|
|
goto cleanup;
|
|
@@ -2827,9 +2950,15 @@ qemuDomainAttachInputDevice(virQEMUDriverPtr driver,
|
|
goto cleanup;
|
|
|
|
qemuDomainObjEnterMonitor(driver, vm);
|
|
- if (qemuMonitorAddDevice(priv->mon, devstr) < 0)
|
|
+
|
|
+ if (qemuDomainAttachExtensionDevice(priv->mon, &input->info) < 0)
|
|
goto exit_monitor;
|
|
|
|
+ if (qemuMonitorAddDevice(priv->mon, devstr) < 0) {
|
|
+ ignore_value(qemuDomainDetachExtensionDevice(priv->mon, &input->info));
|
|
+ goto exit_monitor;
|
|
+ }
|
|
+
|
|
if (qemuDomainObjExitMonitor(driver, vm) < 0) {
|
|
releaseaddr = false;
|
|
goto cleanup;
|
|
@@ -2906,9 +3035,15 @@ qemuDomainAttachVsockDevice(virQEMUDriverPtr driver,
|
|
goto cleanup;
|
|
|
|
qemuDomainObjEnterMonitor(driver, vm);
|
|
- if (qemuMonitorAddDeviceWithFd(priv->mon, devstr, vsockPriv->vhostfd, fdname) < 0)
|
|
+
|
|
+ if (qemuDomainAttachExtensionDevice(priv->mon, &vsock->info) < 0)
|
|
goto exit_monitor;
|
|
|
|
+ if (qemuMonitorAddDeviceWithFd(priv->mon, devstr, vsockPriv->vhostfd, fdname) < 0) {
|
|
+ ignore_value(qemuDomainDetachExtensionDevice(priv->mon, &vsock->info));
|
|
+ goto exit_monitor;
|
|
+ }
|
|
+
|
|
if (qemuDomainObjExitMonitor(driver, vm) < 0) {
|
|
releaseaddr = false;
|
|
goto cleanup;
|
|
@@ -4932,10 +5067,17 @@ int qemuDomainDetachControllerDevice(virQEMUDriverPtr driver,
|
|
qemuDomainMarkDeviceForRemoval(vm, &detach->info);
|
|
|
|
qemuDomainObjEnterMonitor(driver, vm);
|
|
+ if (detach->type == VIR_DOMAIN_CONTROLLER_TYPE_PCI &&
|
|
+ qemuDomainDetachExtensionDevice(priv->mon, &detach->info)) {
|
|
+ goto exit_monitor;
|
|
+ }
|
|
+
|
|
if (qemuMonitorDelDevice(priv->mon, detach->info.alias)) {
|
|
ignore_value(qemuDomainObjExitMonitor(driver, vm));
|
|
goto cleanup;
|
|
}
|
|
+
|
|
+ exit_monitor:
|
|
if (qemuDomainObjExitMonitor(driver, vm) < 0)
|
|
goto cleanup;
|
|
|
|
--
|
|
2.22.0
|
|
|