[libvirt] [PATCHv2 3/5] S390: QEMU driver support for CCW addresses

Viktor Mihajlovski mihajlov at linux.vnet.ibm.com
Fri Feb 8 17:32:22 UTC 2013


This commit adds the QEMU driver support for CCW addresses. The
current QEMU only allows virtio devices to be attached to the
CCW bus. We named the new capability indicating that support
QEMU_CAPS_VIRTIO_CCW accordingly.

The fact that CCW devices can only be assigned to domains with a
machine type of s390-ccw-virtio requires a modification in the
capability handling approach.

First, the QEMU binary name alone will not suffice for capability
lookup, we need the machine type as well. For that purpose we
mangle the machine type into the cache lookup key.

The other thing is that the device support probing will
unfortunately always return both the old virtio-*-s390
and the new virtio-*-ccw devices. This makes it impossible to
choose the correct default device address type if the domain
definition XML doesn't contain explict addresses.
Therefore we apply a fix up in the cache lookup: depending
on the machine type we clear either the VIRTIO_S390 or the
VIRTIO_CCW capability.

The rest is more straight-forward, but since it's a new address
type, a bit bulky. The majority of the new functions deals
with CCW address generation and management.

Signed-off-by: Viktor Mihajlovski <mihajlov at linux.vnet.ibm.com>
---
V2 Changes
 - rebase, mainly addressing the rename of qemuCapsXXX to virQEMUCapsXXX 

 src/qemu/qemu_capabilities.c |   47 ++++++--
 src/qemu/qemu_capabilities.h |    8 +-
 src/qemu/qemu_command.c      |  269 ++++++++++++++++++++++++++++++++++++++++--
 src/qemu/qemu_command.h      |    6 +
 src/qemu/qemu_domain.c       |    1 +
 src/qemu/qemu_domain.h       |    3 +
 src/qemu/qemu_driver.c       |   20 +++-
 src/qemu/qemu_process.c      |   12 +-
 8 files changed, 333 insertions(+), 33 deletions(-)

diff --git a/src/qemu/qemu_capabilities.c b/src/qemu/qemu_capabilities.c
index 4efe052..011b88c 100644
--- a/src/qemu/qemu_capabilities.c
+++ b/src/qemu/qemu_capabilities.c
@@ -205,6 +205,7 @@ VIR_ENUM_IMPL(virQEMUCaps, QEMU_CAPS_LAST,
               "usb-serial", /* 125 */
               "usb-net",
               "add-fd",
+              "virtio-ccw",
 
     );
 
@@ -684,7 +685,7 @@ virQEMUCapsInitGuest(virCapsPtr caps,
 
     /* Ignore binary if extracting version info fails */
     if (binary) {
-        if (!(qemubinCaps = virQEMUCapsCacheLookup(cache, binary))) {
+        if (!(qemubinCaps = virQEMUCapsCacheLookup(cache, binary, NULL))) {
             virResetLastError();
             VIR_FREE(binary);
         }
@@ -707,7 +708,7 @@ virQEMUCapsInitGuest(virCapsPtr caps,
             if (!kvmbin)
                 continue;
 
-            if (!(kvmbinCaps = virQEMUCapsCacheLookup(cache, kvmbin))) {
+            if (!(kvmbinCaps = virQEMUCapsCacheLookup(cache, kvmbin, NULL))) {
                 virResetLastError();
                 VIR_FREE(kvmbin);
                 continue;
@@ -1339,6 +1340,7 @@ struct virQEMUCapsStringFlags virQEMUCapsObjectTypes[] = {
     { "usb-hub", QEMU_CAPS_USB_HUB },
     { "ich9-ahci", QEMU_CAPS_ICH9_AHCI },
     { "virtio-blk-s390", QEMU_CAPS_VIRTIO_S390 },
+    { "virtio-blk-ccw", QEMU_CAPS_VIRTIO_CCW },
     { "sclpconsole", QEMU_CAPS_SCLP_S390 },
     { "lsi53c895a", QEMU_CAPS_SCSI_LSI },
     { "virtio-scsi-pci", QEMU_CAPS_VIRTIO_SCSI_PCI },
@@ -1356,7 +1358,6 @@ struct virQEMUCapsStringFlags virQEMUCapsObjectTypes[] = {
     { "usb-net", QEMU_CAPS_DEVICE_USB_NET},
 };
 
-
 static struct virQEMUCapsStringFlags virQEMUCapsObjectPropsVirtioBlk[] = {
     { "multifunction", QEMU_CAPS_PCI_MULTIFUNCTION },
     { "bootindex", QEMU_CAPS_BOOTINDEX },
@@ -1411,6 +1412,10 @@ static struct virQEMUCapsObjectTypeProps virQEMUCapsObjectProps[] = {
       ARRAY_CARDINALITY(virQEMUCapsObjectPropsVirtioBlk) },
     { "virtio-net-pci", virQEMUCapsObjectPropsVirtioNet,
       ARRAY_CARDINALITY(virQEMUCapsObjectPropsVirtioNet) },
+    { "virtio-blk-ccw", virQEMUCapsObjectPropsVirtioBlk,
+      ARRAY_CARDINALITY(virQEMUCapsObjectPropsVirtioBlk) },
+    { "virtio-net-ccw", virQEMUCapsObjectPropsVirtioNet,
+      ARRAY_CARDINALITY(virQEMUCapsObjectPropsVirtioNet) },
     { "virtio-blk-s390", virQEMUCapsObjectPropsVirtioBlk,
       ARRAY_CARDINALITY(virQEMUCapsObjectPropsVirtioBlk) },
     { "virtio-net-s390", virQEMUCapsObjectPropsVirtioNet,
@@ -1662,7 +1667,7 @@ int virQEMUCapsGetDefaultVersion(virCapsPtr caps,
         return -1;
     }
 
-    if (!(qemucaps = virQEMUCapsCacheLookup(capsCache, binary)))
+    if (!(qemucaps = virQEMUCapsCacheLookup(capsCache, binary, NULL)))
         return -1;
 
     *version = virQEMUCapsGetVersion(qemucaps);
@@ -2612,16 +2617,24 @@ error:
 
 
 virQEMUCapsPtr
-virQEMUCapsCacheLookup(virQEMUCapsCachePtr cache, const char *binary)
+virQEMUCapsCacheLookup(virQEMUCapsCachePtr cache, const char *binary,
+                    const char *machine)
 {
     virQEMUCapsPtr ret = NULL;
+    char * cachekey;
+
+    if (virAsprintf(&cachekey, "%s:%s", binary, machine ? machine : "") < 0) {
+        virReportOOMError();
+        goto error;
+    }
+
     virMutexLock(&cache->lock);
-    ret = virHashLookup(cache->binaries, binary);
+    ret = virHashLookup(cache->binaries, cachekey);
     if (ret &&
         !virQEMUCapsIsValid(ret)) {
         VIR_DEBUG("Cached capabilities %p no longer valid for %s",
                   ret, binary);
-        virHashRemoveEntry(cache->binaries, binary);
+        virHashRemoveEntry(cache->binaries, cachekey);
         ret = NULL;
     }
     if (!ret) {
@@ -2632,7 +2645,17 @@ virQEMUCapsCacheLookup(virQEMUCapsCachePtr cache, const char *binary)
         if (ret) {
             VIR_DEBUG("Caching capabilities %p for %s",
                       ret, binary);
-            if (virHashAddEntry(cache->binaries, binary, ret) < 0) {
+
+            /* fix up machine specific capabilities */
+            if (machine) {
+                if (STREQLEN(machine,"s390-ccw",8)) {
+                    virQEMUCapsClear(ret, QEMU_CAPS_VIRTIO_S390);
+                } else if (STREQLEN(machine,"s390",4)) {
+                    virQEMUCapsClear(ret, QEMU_CAPS_VIRTIO_CCW);
+                }
+            }
+
+            if (virHashAddEntry(cache->binaries, cachekey, ret) < 0) {
                 virObjectUnref(ret);
                 ret = NULL;
             }
@@ -2641,14 +2664,18 @@ virQEMUCapsCacheLookup(virQEMUCapsCachePtr cache, const char *binary)
     VIR_DEBUG("Returning caps %p for %s", ret, binary);
     virObjectRef(ret);
     virMutexUnlock(&cache->lock);
+
+error:
+    VIR_FREE(cachekey);
     return ret;
 }
 
 
 virQEMUCapsPtr
-virQEMUCapsCacheLookupCopy(virQEMUCapsCachePtr cache, const char *binary)
+virQEMUCapsCacheLookupCopy(virQEMUCapsCachePtr cache, const char *binary,
+                           const char *machine)
 {
-    virQEMUCapsPtr qemuCaps = virQEMUCapsCacheLookup(cache, binary);
+    virQEMUCapsPtr qemuCaps = virQEMUCapsCacheLookup(cache, binary, machine);
     virQEMUCapsPtr ret;
 
     if (!qemuCaps)
diff --git a/src/qemu/qemu_capabilities.h b/src/qemu/qemu_capabilities.h
index e69d558..1a6df85 100644
--- a/src/qemu/qemu_capabilities.h
+++ b/src/qemu/qemu_capabilities.h
@@ -166,6 +166,7 @@ enum virQEMUCapsFlags {
     QEMU_CAPS_DEVICE_USB_SERIAL  = 125, /* -device usb-serial */
     QEMU_CAPS_DEVICE_USB_NET     = 126, /* -device usb-net */
     QEMU_CAPS_ADD_FD             = 127, /* -add-fd */
+    QEMU_CAPS_VIRTIO_CCW         = 128, /* -device virtio-*-ccw */
 
     QEMU_CAPS_LAST,                   /* this must always be the last item */
 };
@@ -218,13 +219,14 @@ int virQEMUCapsGetMachineTypesCaps(virQEMUCapsPtr qemuCaps,
 
 bool virQEMUCapsIsValid(virQEMUCapsPtr qemuCaps);
 
-
 virQEMUCapsCachePtr virQEMUCapsCacheNew(const char *libDir,
                                         uid_t uid, gid_t gid);
 virQEMUCapsPtr virQEMUCapsCacheLookup(virQEMUCapsCachePtr cache,
-                                      const char *binary);
+                                      const char *binary,
+                                      const char *machine);
 virQEMUCapsPtr virQEMUCapsCacheLookupCopy(virQEMUCapsCachePtr cache,
-                                          const char *binary);
+                                          const char *binary,
+                                          const char *machine);
 void virQEMUCapsCacheFree(virQEMUCapsCachePtr cache);
 
 virCapsPtr virQEMUCapsInit(virQEMUCapsCachePtr cache);
diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c
index 33f2ecd..0bb4a46 100644
--- a/src/qemu/qemu_command.c
+++ b/src/qemu/qemu_command.c
@@ -795,6 +795,100 @@ no_memory:
     return -1;
 }
 
+/* S390 ccw bus support */
+
+struct _qemuDomainCCWAddressSet {
+    virHashTablePtr                 defined;
+    virDomainDeviceCCWAddress next;
+};
+
+static char*
+qemuCCWAddressAsString(virDomainDeviceCCWAddressPtr addr)
+{
+    char *addrstr = NULL;
+
+    if (virAsprintf(&addrstr, "%x.%x.%04x",
+                    addr->cssid,
+                    addr->ssid,
+                    addr->schid) < 0) {
+        virReportOOMError();
+        return NULL;
+    }
+
+    return addrstr;
+}
+
+static int
+qemuCCWAdressIncrement(virDomainDeviceCCWAddressPtr addr)
+{
+    virDomainDeviceCCWAddress ccwaddr = *addr;
+
+    /* We are not touching subchannel sets and channel subsystems */
+    if (++ccwaddr.schid > VIR_DOMAIN_DEVICE_CCW_MAX_SCHID)
+        return -1;
+
+    *addr = ccwaddr;
+    return 0;
+}
+
+static void
+qemuDomainCCWAddressSetFreeEntry(void *payload,
+                                 const void *name ATTRIBUTE_UNUSED)
+{
+    VIR_FREE(payload);
+}
+
+int qemuDomainCCWAddressAssign(virDomainDeviceInfoPtr dev,
+                               qemuDomainCCWAddressSetPtr addrs,
+                               bool autoassign)
+{
+    int ret = -1;
+    char *addr = NULL;
+
+    if (dev->type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_CCW)
+        return 0;
+
+    if (!autoassign && dev->addr.ccw.assigned) {
+        if (!(addr = qemuCCWAddressAsString(&dev->addr.ccw)))
+            goto cleanup;
+
+        if (virHashLookup(addrs->defined, addr)) {
+            virReportError(VIR_ERR_XML_ERROR,
+                           _("The CCW devno '%s' is in use already "),
+                           addr);
+            goto cleanup;
+        }
+    } else if (autoassign && !dev->addr.ccw.assigned) {
+        if (!(addr = qemuCCWAddressAsString(&addrs->next)) < 0)
+            goto cleanup;
+
+        while (virHashLookup(addrs->defined, addr)) {
+            if (qemuCCWAdressIncrement(&addrs->next) < 0) {
+                virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+                               _("There are no more free CCW devnos."));
+                goto cleanup;
+            }
+            VIR_FREE(addr);
+            addr = qemuCCWAddressAsString(&addrs->next);
+        }
+        dev->addr.ccw = addrs->next;
+        dev->addr.ccw.assigned = true;
+    } else {
+        return 0;
+    }
+
+    if (virHashAddEntry(addrs->defined,addr,addr) < 0)
+        goto cleanup;
+    else
+        addr = NULL; /* memory will be freed by hash table */
+
+    ret = 0;
+
+cleanup:
+    VIR_FREE(addr);
+    return ret;
+}
+
 static void
 qemuDomainPrimeS390VirtioDevices(virDomainDefPtr def,
                                  enum virDomainDeviceAddressType type)
@@ -837,13 +931,137 @@ qemuDomainPrimeS390VirtioDevices(virDomainDefPtr def,
         def->memballoon->info.type = type;
 }
 
-static void
-qemuDomainAssignS390Addresses(virDomainDefPtr def, virQEMUCapsPtr qemuCaps)
+static int
+qemuDomainCCWAddressAllocate(virDomainDefPtr def ATTRIBUTE_UNUSED,
+                             virDomainDeviceDefPtr dev ATTRIBUTE_UNUSED,
+                             virDomainDeviceInfoPtr info,
+                             void * data)
+{
+    return qemuDomainCCWAddressAssign(info,
+                                      (qemuDomainCCWAddressSetPtr)data,
+                                      true);
+}
+
+static int
+qemuDomainCCWAddressValidate(virDomainDefPtr def ATTRIBUTE_UNUSED,
+                             virDomainDeviceDefPtr dev ATTRIBUTE_UNUSED,
+                             virDomainDeviceInfoPtr info,
+                             void * data)
+{
+    return qemuDomainCCWAddressAssign(info,(qemuDomainCCWAddressSetPtr)data,
+                                      false);
+}
+
+int qemuDomainCCWAddressReleaseAddr(qemuDomainCCWAddressSetPtr addrs,
+                                    virDomainDeviceInfoPtr dev)
+{
+    char *addr;
+    int ret;
+
+    addr = qemuCCWAddressAsString(&(dev->addr.ccw));
+    if (!addr)
+        return -1;
+
+    if ((ret = virHashRemoveEntry(addrs->defined, addr)) == 0 &&
+        dev->addr.ccw.cssid == addrs->next.cssid &&
+        dev->addr.ccw.ssid == addrs->next.ssid &&
+        dev->addr.ccw.schid < addrs->next.schid) {
+        addrs->next.schid = dev->addr.ccw.schid;
+        addrs->next.assigned = false;
+    }
+
+    VIR_FREE(addr);
+
+    return ret;
+}
+
+void qemuDomainCCWAddressSetFree(qemuDomainCCWAddressSetPtr addrs)
 {
-    /* deal with legacy virtio-s390 */
-    if (virQEMUCapsGet(qemuCaps, QEMU_CAPS_VIRTIO_S390))
+    if (!addrs)
+        return;
+
+    virHashFree(addrs->defined);
+    VIR_FREE(addrs);
+}
+
+static qemuDomainCCWAddressSetPtr
+qemuDomainCCWAddressSetCreate(void)
+{
+     qemuDomainCCWAddressSetPtr addrs = NULL;
+
+    if (VIR_ALLOC(addrs) < 0)
+        goto no_memory;
+
+    if (!(addrs->defined = virHashCreate(10, qemuDomainCCWAddressSetFreeEntry)))
+        goto cleanup;
+
+    /* must use cssid = 0xfe (254) for virtio-ccw devices */
+    addrs->next.cssid = 254;
+    addrs->next.ssid = 0;
+    addrs->next.schid = 0;
+    addrs->next.assigned = 0;
+    return addrs;
+
+no_memory:
+    virReportOOMError();
+cleanup:
+    qemuDomainCCWAddressSetFree(addrs);
+    return addrs;
+}
+
+/*
+ * Three steps populating CCW devnos
+ * 1. Allocate empty address set
+ * 2. Gather addresses with explicit devno
+ * 3. Assign defaults to the rest
+ */
+static int
+qemuDomainAssignS390Addresses(virDomainDefPtr def,
+                              virQEMUCapsPtr qemuCaps,
+                              virDomainObjPtr obj)
+{
+    int ret = -1;
+    qemuDomainCCWAddressSetPtr addrs = NULL;
+    qemuDomainObjPrivatePtr priv = NULL;
+
+    if (virQEMUCapsGet(qemuCaps, QEMU_CAPS_VIRTIO_CCW)) {
+        qemuDomainPrimeS390VirtioDevices(
+            def, VIR_DOMAIN_DEVICE_ADDRESS_TYPE_CCW);
+
+        if (!(addrs = qemuDomainCCWAddressSetCreate()))
+            goto cleanup;
+
+        if (virDomainDeviceInfoIterate(def, qemuDomainCCWAddressValidate,
+                                       addrs) < 0)
+            goto cleanup;
+
+        if (virDomainDeviceInfoIterate(def, qemuDomainCCWAddressAllocate,
+                                       addrs) < 0)
+            goto cleanup;
+    } else if (virQEMUCapsGet(qemuCaps, QEMU_CAPS_VIRTIO_S390)) {
+        /* deal with legacy virtio-s390 */
         qemuDomainPrimeS390VirtioDevices(
             def, VIR_DOMAIN_DEVICE_ADDRESS_TYPE_VIRTIO_S390);
+    }
+
+    if (obj && obj->privateData) {
+        priv = obj->privateData;
+        if (addrs) {
+            /* if this is the live domain object, we persist the CCW addresses*/
+            qemuDomainCCWAddressSetFree(priv->ccwaddrs);
+            priv->persistentAddrs = 1;
+            priv->ccwaddrs = addrs;
+            addrs = NULL;
+        } else {
+            priv->persistentAddrs = 0;
+        }
+    }
+    ret = 0;
+
+cleanup:
+    qemuDomainCCWAddressSetFree(addrs);
+
+    return ret;
 }
 
 static int
@@ -1103,7 +1321,9 @@ int qemuDomainAssignAddresses(virDomainDefPtr def,
     if (rc)
         return rc;
 
-    qemuDomainAssignS390Addresses(def, qemuCaps);
+    rc = qemuDomainAssignS390Addresses(def, qemuCaps, obj);
+    if (rc)
+        return rc;
 
     return qemuDomainAssignPCIAddresses(def, qemuCaps, obj);
 }
@@ -1322,7 +1542,6 @@ void qemuDomainPCIAddressSetFree(qemuDomainPCIAddressSetPtr addrs)
     VIR_FREE(addrs);
 }
 
-
 static int qemuDomainPCIAddressGetNextSlot(qemuDomainPCIAddressSetPtr addrs)
 {
     int i;
@@ -1668,7 +1887,9 @@ qemuAssignDevicePCISlots(virDomainDefPtr def,
         /* don't touch s390 devices */
         if (def->disks[i]->info.type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI ||
             def->disks[i]->info.type ==
-            VIR_DOMAIN_DEVICE_ADDRESS_TYPE_VIRTIO_S390)
+            VIR_DOMAIN_DEVICE_ADDRESS_TYPE_VIRTIO_S390 ||
+            def->disks[i]->info.type ==
+            VIR_DOMAIN_DEVICE_ADDRESS_TYPE_CCW)
             continue;
 
         if (def->disks[i]->info.type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_NONE) {
@@ -1814,6 +2035,12 @@ qemuBuildDeviceAddressStr(virBufferPtr buf,
     } else if (info->type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_SPAPRVIO) {
         if (info->addr.spaprvio.has_reg)
             virBufferAsprintf(buf, ",reg=0x%llx", info->addr.spaprvio.reg);
+    } else if (info->type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_CCW) {
+        if (info->addr.ccw.assigned)
+            virBufferAsprintf(buf, ",devno=%x.%x.%04x",
+                              info->addr.ccw.cssid,
+                              info->addr.ccw.ssid,
+                              info->addr.ccw.schid);
     }
 
     return 0;
@@ -2822,8 +3049,10 @@ qemuBuildDriveDevStr(virDomainDefPtr def,
                           disk->info.addr.drive.unit);
         break;
     case VIR_DOMAIN_DISK_BUS_VIRTIO:
-        if (disk->info.type ==
-            VIR_DOMAIN_DEVICE_ADDRESS_TYPE_VIRTIO_S390) {
+        if (disk->info.type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_CCW) {
+            virBufferAddLit(&opt, "virtio-blk-ccw");
+        } else if (disk->info.type ==
+                   VIR_DOMAIN_DEVICE_ADDRESS_TYPE_VIRTIO_S390) {
             virBufferAddLit(&opt, "virtio-blk-s390");
         } else {
             virBufferAddLit(&opt, "virtio-blk-pci");
@@ -3105,6 +3334,9 @@ qemuBuildControllerDevStr(virDomainDefPtr domainDef,
         if (def->info.type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI) {
             virBufferAddLit(&buf, "virtio-serial-pci");
         } else if (def->info.type ==
+                   VIR_DOMAIN_DEVICE_ADDRESS_TYPE_CCW) {
+            virBufferAddLit(&buf, "virtio-serial-ccw");
+        } else if (def->info.type ==
                    VIR_DOMAIN_DEVICE_ADDRESS_TYPE_VIRTIO_S390) {
             virBufferAddLit(&buf, "virtio-serial-s390");
         } else {
@@ -3202,8 +3434,10 @@ qemuBuildNicDevStr(virDomainNetDefPtr net,
     if (!net->model) {
         nic = "rtl8139";
     } else if (STREQ(net->model, "virtio")) {
-        if (net->info.type ==
-            VIR_DOMAIN_DEVICE_ADDRESS_TYPE_VIRTIO_S390) {
+        if (net->info.type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_CCW) {
+            nic = "virtio-net-ccw";
+        } else if (net->info.type ==
+                   VIR_DOMAIN_DEVICE_ADDRESS_TYPE_VIRTIO_S390) {
             nic = "virtio-net-s390";
         } else  {
             nic = "virtio-net-pci";
@@ -3430,7 +3664,17 @@ qemuBuildMemballoonDevStr(virDomainMemballoonDefPtr dev,
 {
     virBuffer buf = VIR_BUFFER_INITIALIZER;
 
-    virBufferAddLit(&buf, "virtio-balloon-pci");
+    switch (dev->info.type) {
+        case VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI:
+            virBufferAddLit(&buf, "virtio-balloon-pci");
+            break;
+        case VIR_DOMAIN_DEVICE_ADDRESS_TYPE_CCW:
+            virBufferAddLit(&buf, "virtio-balloon-ccw");
+            break;
+        default:
+            goto error;
+    }
+
     virBufferAsprintf(&buf, ",id=%s", dev->info.alias);
     if (qemuBuildDeviceAddressStr(&buf, &dev->info, qemuCaps) < 0)
         goto error;
@@ -4122,6 +4366,7 @@ qemuBuildVirtioSerialPortDevStr(virDomainChrDefPtr dev,
     }
 
     if (dev->info.type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_NONE &&
+        dev->info.type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_CCW &&
         dev->info.type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_VIRTIO_S390) {
         /* Check it's a virtio-serial address */
         if (dev->info.type !=
diff --git a/src/qemu/qemu_command.h b/src/qemu/qemu_command.h
index 7e52c5d..0f3bb5e 100644
--- a/src/qemu/qemu_command.h
+++ b/src/qemu/qemu_command.h
@@ -215,6 +215,12 @@ int  qemuAssignDevicePCISlots(virDomainDefPtr def,
                               virQEMUCapsPtr qemuCaps,
                               qemuDomainPCIAddressSetPtr addrs);
 
+int qemuDomainCCWAddressReleaseAddr(qemuDomainCCWAddressSetPtr addrs,
+                                    virDomainDeviceInfoPtr dev);
+int qemuDomainCCWAddressAssign(virDomainDeviceInfoPtr dev, qemuDomainCCWAddressSetPtr addrs,
+                               bool autoassign);
+void qemuDomainCCWAddressSetFree(qemuDomainCCWAddressSetPtr addrs);
+
 int qemuAssignDeviceAliases(virDomainDefPtr def, virQEMUCapsPtr qemuCaps);
 int qemuDomainNetVLAN(virDomainNetDefPtr def);
 int qemuAssignDeviceNetAlias(virDomainDefPtr def, virDomainNetDefPtr net, int idx);
diff --git a/src/qemu/qemu_domain.c b/src/qemu/qemu_domain.c
index 4917721..749aac0 100644
--- a/src/qemu/qemu_domain.c
+++ b/src/qemu/qemu_domain.c
@@ -234,6 +234,7 @@ static void qemuDomainObjPrivateFree(void *data)
     virObjectUnref(priv->qemuCaps);
 
     qemuDomainPCIAddressSetFree(priv->pciaddrs);
+    qemuDomainCCWAddressSetFree(priv->ccwaddrs);
     virDomainChrSourceDefFree(priv->monConfig);
     qemuDomainObjFreeJob(priv);
     VIR_FREE(priv->vcpupids);
diff --git a/src/qemu/qemu_domain.h b/src/qemu/qemu_domain.h
index 51cd2dc..c9658fc 100644
--- a/src/qemu/qemu_domain.h
+++ b/src/qemu/qemu_domain.h
@@ -119,6 +119,8 @@ typedef qemuDomainPCIAddressSet *qemuDomainPCIAddressSetPtr;
 
 typedef void (*qemuDomainCleanupCallback)(virQEMUDriverPtr driver,
                                           virDomainObjPtr vm);
+typedef struct _qemuDomainCCWAddressSet qemuDomainCCWAddressSet;
+typedef qemuDomainCCWAddressSet *qemuDomainCCWAddressSetPtr;
 
 typedef struct _qemuDomainObjPrivate qemuDomainObjPrivate;
 typedef qemuDomainObjPrivate *qemuDomainObjPrivatePtr;
@@ -143,6 +145,7 @@ struct _qemuDomainObjPrivate {
     int *vcpupids;
 
     qemuDomainPCIAddressSetPtr pciaddrs;
+    qemuDomainCCWAddressSetPtr ccwaddrs;
     int persistentAddrs;
 
     virQEMUCapsPtr qemuCaps;
diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
index 0651bc8..6e73558 100644
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -1538,7 +1538,9 @@ static virDomainPtr qemuDomainCreate(virConnectPtr conn, const char *xml,
     if (virSecurityManagerVerify(driver->securityManager, def) < 0)
         goto cleanup;
 
-    if (!(qemuCaps = virQEMUCapsCacheLookup(driver->qemuCapsCache, def->emulator)))
+    if (!(qemuCaps = virQEMUCapsCacheLookup(driver->qemuCapsCache,
+                                            def->emulator,
+                                            def->os.machine)))
         goto cleanup;
 
     if (qemuCanonicalizeMachine(def, qemuCaps) < 0)
@@ -5353,7 +5355,9 @@ static char *qemuDomainXMLToNative(virConnectPtr conn,
     if (!def)
         goto cleanup;
 
-    if (!(qemuCaps = virQEMUCapsCacheLookup(driver->qemuCapsCache, def->emulator)))
+    if (!(qemuCaps = virQEMUCapsCacheLookup(driver->qemuCapsCache,
+                                            def->emulator,
+                                            def->os.machine)))
         goto cleanup;
 
     /* Since we're just exporting args, we can't do bridge/network/direct
@@ -5634,7 +5638,9 @@ static virDomainPtr qemuDomainDefine(virConnectPtr conn, const char *xml) {
     if (virSecurityManagerVerify(driver->securityManager, def) < 0)
         goto cleanup;
 
-    if (!(qemuCaps = virQEMUCapsCacheLookup(driver->qemuCapsCache, def->emulator)))
+    if (!(qemuCaps = virQEMUCapsCacheLookup(driver->qemuCapsCache,
+                                            def->emulator,
+                                            def->os.machine)))
         goto cleanup;
 
     if (qemuCanonicalizeMachine(def, qemuCaps) < 0)
@@ -6502,7 +6508,9 @@ qemuDomainModifyDeviceFlags(virDomainPtr dom, const char *xml,
 
     if (priv->qemuCaps)
         qemuCaps = virObjectRef(priv->qemuCaps);
-    else if (!(qemuCaps = virQEMUCapsCacheLookup(driver->qemuCapsCache, vm->def->emulator)))
+    else if (!(qemuCaps = virQEMUCapsCacheLookup(driver->qemuCapsCache,
+                                                 vm->def->emulator,
+                                                 vm->def->os.machine)))
         goto cleanup;
 
     if (flags & VIR_DOMAIN_AFFECT_CONFIG) {
@@ -12713,7 +12721,9 @@ static virDomainPtr qemuDomainAttach(virConnectPtr conn,
         goto cleanup;
     }
 
-    if (!(qemuCaps = virQEMUCapsCacheLookup(driver->qemuCapsCache, def->emulator)))
+    if (!(qemuCaps = virQEMUCapsCacheLookup(driver->qemuCapsCache,
+                                            def->emulator,
+                                            def->os.machine)))
         goto cleanup;
 
     if (qemuCanonicalizeMachine(def, qemuCaps) < 0)
diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c
index abbee5e..c36b5c2 100644
--- a/src/qemu/qemu_process.c
+++ b/src/qemu/qemu_process.c
@@ -3311,7 +3311,8 @@ qemuProcessReconnect(void *opaque)
      */
     if (!priv->qemuCaps &&
         !(priv->qemuCaps = virQEMUCapsCacheLookupCopy(driver->qemuCapsCache,
-                                                      obj->def->emulator)))
+                                                      obj->def->emulator,
+                                                      obj->def->os.machine)))
         goto error;
 
     /* In case the domain shutdown while we were not running,
@@ -3811,7 +3812,8 @@ int qemuProcessStart(virConnectPtr conn,
     VIR_DEBUG("Determining emulator version");
     virObjectUnref(priv->qemuCaps);
     if (!(priv->qemuCaps = virQEMUCapsCacheLookupCopy(driver->qemuCapsCache,
-                                                      vm->def->emulator)))
+                                                      vm->def->emulator,
+                                                      vm->def->os.machine)))
         goto cleanup;
 
     if (qemuAssignDeviceAliases(vm->def, priv->qemuCaps) < 0)
@@ -4385,6 +4387,9 @@ void qemuProcessStop(virQEMUDriverPtr driver,
         virDomainDefClearPCIAddresses(vm->def);
         qemuDomainPCIAddressSetFree(priv->pciaddrs);
         priv->pciaddrs = NULL;
+        virDomainDefClearCCWAddresses(vm->def);
+        qemuDomainCCWAddressSetFree(priv->ccwaddrs);
+        priv->ccwaddrs = NULL;
     }
 
     qemuDomainReAttachHostDevices(driver, vm->def);
@@ -4573,7 +4578,8 @@ int qemuProcessAttach(virConnectPtr conn ATTRIBUTE_UNUSED,
     VIR_DEBUG("Determining emulator version");
     virObjectUnref(priv->qemuCaps);
     if (!(priv->qemuCaps = virQEMUCapsCacheLookupCopy(driver->qemuCapsCache,
-                                                      vm->def->emulator)))
+                                                      vm->def->emulator,
+                                                      vm->def->os.machine)))
         goto cleanup;
 
     VIR_DEBUG("Preparing monitor state");
-- 
1.7.9.5




More information about the libvir-list mailing list