[libvirt] [RFC PATCH 4/5] qemu: Build command line for ivshmem device

Maxime Leroy maxime.leroy at 6wind.com
Tue Aug 5 16:48:04 UTC 2014


This patch implements support for the ivshmem device
in QEMU.

Example from this xml:

    <ivshmem server='yes'' role='master'/>
      <source file='/tmp/socket-ivshmem0'/>
      <size unit='M'>32</size>
      <msi vectors='32' ioeventfd='on'/>
    </ivshmem>

The following QEMU line is built:

   -device ivshmem,size=32m,vectors=32,chardev=charivshmem0,msi=on,
	ioeventfd=on,role=master
   -chardev socket,path=/tmp/socket-ivshmem0,id=charivshmem0

Note: PCI hotpluging has not be implemented.

Signed-off-by: Maxime Leroy <maxime.leroy at 6wind.com>
---
 src/qemu/qemu_command.c | 77 +++++++++++++++++++++++++++++++++++++++++++++++++
 src/qemu/qemu_command.h |  4 +++
 src/qemu/qemu_hotplug.c |  1 +
 3 files changed, 82 insertions(+)

diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c
index a5ff10a..b434023 100644
--- a/src/qemu/qemu_command.c
+++ b/src/qemu/qemu_command.c
@@ -1034,6 +1034,10 @@ qemuAssignDeviceAliases(virDomainDefPtr def, virQEMUCapsPtr qemuCaps)
         if (virAsprintf(&def->hubs[i]->info.alias, "hub%zu", i) < 0)
             return -1;
     }
+    for (i = 0; i < def->nivshmems; i++) {
+        if (virAsprintf(&def->ivshmems[i]->info.alias, "ivshmem%zu", i) < 0)
+            return -1;
+    }
     for (i = 0; i < def->nsmartcards; i++) {
         if (virAsprintf(&def->smartcards[i]->info.alias, "smartcard%zu", i) < 0)
             return -1;
@@ -5032,6 +5036,53 @@ qemuBuildRedirdevDevStr(virDomainDefPtr def,
 }
 
 char *
+qemuBuildIvshmemDevStr(virDomainDefPtr def,
+                       virDomainIvshmemDefPtr dev,
+                       virQEMUCapsPtr qemuCaps)
+{
+    virBuffer buf = VIR_BUFFER_INITIALIZER;
+
+    if (!virQEMUCapsGet(qemuCaps, QEMU_CAPS_DEVICE_IVSHMEM)) {
+        virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+                       _("ivshmem device is not supported by QEMU"));
+        goto error;
+    }
+
+    virBufferAddLit(&buf, "ivshmem");
+    if (dev->size)
+        virBufferAsprintf(&buf, ",size=%llum", dev->size / (1024 * 1024));
+    if (dev->role)
+        virBufferAsprintf(&buf, ",role=%s",
+                          virDomainIvshmemRoleTypeToString(dev->role));
+
+    if (dev->use_server == VIR_DOMAIN_IVSHMEM_SERVER_DISABLED)
+        virBufferAsprintf(&buf, ",shm=%s", dev->file);
+    else {
+        virBufferAsprintf(&buf, ",chardev=char%s", dev->info.alias);
+        if (dev->msi.enabled) {
+            virBufferAddLit(&buf, ",msi=on");
+            if (dev->msi.vectors)
+                virBufferAsprintf(&buf, ",vectors=%u", dev->msi.vectors);
+            if (dev->msi.ioeventfd)
+                virBufferAsprintf(&buf, ",ioeventfd=%s",
+                                  virTristateSwitchTypeToString(dev->msi.ioeventfd));
+        }
+    }
+
+    if (qemuBuildDeviceAddressStr(&buf, def, &dev->info, qemuCaps) < 0)
+        goto error;
+
+    if (virBufferCheckError(&buf) < 0)
+        goto error;
+
+    return virBufferContentAndReset(&buf);
+
+ error:
+    virBufferFreeAndReset(&buf);
+    return NULL;
+}
+
+char *
 qemuBuildUSBHostdevDevStr(virDomainDefPtr def,
                           virDomainHostdevDefPtr dev,
                           virQEMUCapsPtr qemuCaps)
@@ -9317,6 +9368,32 @@ qemuBuildCommandLine(virConnectPtr conn,
         }
     }
 
+    for (i = 0; i < def->nivshmems; i++) {
+        virDomainIvshmemDefPtr ivshmem = def->ivshmems[i];
+        char *devstr;
+
+        virCommandAddArg(cmd, "-device");
+        if (!(devstr = qemuBuildIvshmemDevStr(def, ivshmem, qemuCaps)))
+            goto error;
+        virCommandAddArg(cmd, devstr);
+        VIR_FREE(devstr);
+
+        if (ivshmem->use_server == VIR_DOMAIN_IVSHMEM_SERVER_ENABLED) {
+            virDomainChrSourceDef source;
+
+            source.type = VIR_DOMAIN_CHR_TYPE_UNIX;
+            source.data.nix.path = ivshmem->file;
+            source.data.nix.listen = false;
+
+            virCommandAddArg(cmd, "-chardev");
+            if (!(devstr = qemuBuildChrChardevStr(&source, ivshmem->info.alias,
+                                                  qemuCaps)))
+                goto error;
+            virCommandAddArg(cmd, devstr);
+            VIR_FREE(devstr);
+        }
+    }
+
     if (mlock) {
         unsigned long long memKB;
 
diff --git a/src/qemu/qemu_command.h b/src/qemu/qemu_command.h
index b71e964..f3d301a 100644
--- a/src/qemu/qemu_command.h
+++ b/src/qemu/qemu_command.h
@@ -185,6 +185,10 @@ char * qemuBuildHubDevStr(virDomainDefPtr def,
 char * qemuBuildRedirdevDevStr(virDomainDefPtr def,
                                virDomainRedirdevDefPtr dev,
                                virQEMUCapsPtr qemuCaps);
+char * qemuBuildIvshmemDevStr(virDomainDefPtr def,
+                              virDomainIvshmemDefPtr dev,
+                              virQEMUCapsPtr qemuCaps);
+
 int qemuNetworkIfaceConnect(virDomainDefPtr def,
                             virConnectPtr conn,
                             virQEMUDriverPtr driver,
diff --git a/src/qemu/qemu_hotplug.c b/src/qemu/qemu_hotplug.c
index 004b6a4..7be3a04 100644
--- a/src/qemu/qemu_hotplug.c
+++ b/src/qemu/qemu_hotplug.c
@@ -2824,6 +2824,7 @@ qemuDomainRemoveDevice(virQEMUDriverPtr driver,
     case VIR_DOMAIN_DEVICE_MEMBALLOON:
     case VIR_DOMAIN_DEVICE_NVRAM:
     case VIR_DOMAIN_DEVICE_RNG:
+    case VIR_DOMAIN_DEVICE_IVSHMEM:
     case VIR_DOMAIN_DEVICE_LAST:
         virReportError(VIR_ERR_OPERATION_UNSUPPORTED,
                        _("don't know how to remove a %s device"),
-- 
1.9.3




More information about the libvir-list mailing list