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