render / rpms / libvirt

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