]> xenbits.xensource.com Git - libvirt.git/commitdiff
qemu: Support newer ivshmem device variants
authorMartin Kletzander <mkletzan@redhat.com>
Wed, 10 Aug 2016 09:15:22 +0000 (11:15 +0200)
committerMartin Kletzander <mkletzan@redhat.com>
Wed, 2 Nov 2016 16:36:17 +0000 (17:36 +0100)
QEMU added support for ivshmem-plain and ivshmem-doorbell.  Those are
reworked varians of legacy ivshmem that are compatible from the guest
POV, but not from host's POV and have sane specification and handling.

Details about the newer device type can be found in qemu's commit
5400c02b90bb:

  http://git.qemu.org/?p=qemu.git;a=commit;h=5400c02b90bb

Signed-off-by: Martin Kletzander <mkletzan@redhat.com>
src/qemu/qemu_command.c
src/qemu/qemu_command.h
tests/qemuxml2argvdata/qemuxml2argv-shmem-plain-doorbell.args [new file with mode: 0644]
tests/qemuxml2argvtest.c

index d6a5f442465639c8b20e16de00cb15dc4ed00616..96c4f31ccf0b2d5c2c08722279104530142524af 100644 (file)
@@ -8469,6 +8469,50 @@ qemuBuildShmemDevLegacyStr(virDomainDefPtr def,
     return NULL;
 }
 
+char *
+qemuBuildShmemDevStr(virDomainDefPtr def,
+                     virDomainShmemDefPtr shmem,
+                     virQEMUCapsPtr qemuCaps)
+{
+    virBuffer buf = VIR_BUFFER_INITIALIZER;
+
+    if ((shmem->model == VIR_DOMAIN_SHMEM_MODEL_IVSHMEM_PLAIN &&
+         !virQEMUCapsGet(qemuCaps, QEMU_CAPS_DEVICE_IVSHMEM_PLAIN)) ||
+        (shmem->model == VIR_DOMAIN_SHMEM_MODEL_IVSHMEM_DOORBELL &&
+         !virQEMUCapsGet(qemuCaps, QEMU_CAPS_DEVICE_IVSHMEM_DOORBELL))) {
+            virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
+                           _("shmem model '%s' is not supported "
+                             "by this QEMU binary"),
+                           virDomainShmemModelTypeToString(shmem->model));
+        return NULL;
+    }
+
+    virBufferAdd(&buf, virDomainShmemModelTypeToString(shmem->model), -1);
+    virBufferAsprintf(&buf, ",id=%s", shmem->info.alias);
+
+    if (shmem->server.enabled)
+        virBufferAsprintf(&buf, ",chardev=char%s", shmem->info.alias);
+    else
+        virBufferAsprintf(&buf, ",memdev=shmmem-%s", shmem->info.alias);
+
+    if (shmem->msi.vectors)
+        virBufferAsprintf(&buf, ",vectors=%u", shmem->msi.vectors);
+    if (shmem->msi.ioeventfd) {
+        virBufferAsprintf(&buf, ",ioeventfd=%s",
+                          virTristateSwitchTypeToString(shmem->msi.ioeventfd));
+    }
+
+    if (qemuBuildDeviceAddressStr(&buf, def, &shmem->info, qemuCaps) < 0) {
+        virBufferFreeAndReset(&buf);
+        return NULL;
+    }
+
+    if (virBufferCheckError(&buf) < 0)
+        return NULL;
+
+    return virBufferContentAndReset(&buf);
+}
+
 static char *
 qemuBuildShmemBackendChrStr(virLogManagerPtr logManager,
                             virCommandPtr cmd,
@@ -8489,6 +8533,50 @@ qemuBuildShmemBackendChrStr(virLogManagerPtr logManager,
     return devstr;
 }
 
+
+virJSONValuePtr
+qemuBuildShmemBackendMemProps(virDomainShmemDefPtr shmem)
+{
+    char *mem_path = NULL;
+    virJSONValuePtr ret = NULL;
+
+    if (virAsprintf(&mem_path, "/dev/shm/%s", shmem->name) < 0)
+        return NULL;
+
+    virJSONValueObjectCreate(&ret,
+                             "s:mem-path", mem_path,
+                             "U:size", shmem->size,
+                             NULL);
+
+    VIR_FREE(mem_path);
+    return ret;
+}
+
+
+static char *
+qemuBuildShmemBackendMemStr(virDomainShmemDefPtr shmem)
+{
+    char *ret = NULL;
+    char *alias = NULL;
+    virJSONValuePtr props = qemuBuildShmemBackendMemProps(shmem);
+
+    if (!props)
+        return NULL;
+
+    if (virAsprintf(&alias, "shmmem-%s", shmem->info.alias) < 0)
+        goto cleanup;
+
+    ret = virQEMUBuildObjectCommandlineFromJSON("memory-backend-file",
+                                                alias,
+                                                props);
+ cleanup:
+    VIR_FREE(alias);
+    virJSONValueFree(props);
+
+    return ret;
+}
+
+
 static int
 qemuBuildShmemCommandLine(virLogManagerPtr logManager,
                           virCommandPtr cmd,
@@ -8531,10 +8619,15 @@ qemuBuildShmemCommandLine(virLogManagerPtr logManager,
         break;
 
     case VIR_DOMAIN_SHMEM_MODEL_IVSHMEM_PLAIN:
+        if (!(devstr = qemuBuildShmemBackendMemStr(shmem)))
+            return -1;
+
+        virCommandAddArgList(cmd, "-object", devstr, NULL);
+        VIR_FREE(devstr);
+
+        /* fall-through */
     case VIR_DOMAIN_SHMEM_MODEL_IVSHMEM_DOORBELL:
-        virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
-                       _("%s device is not supported with this QEMU binary"),
-                       virDomainShmemModelTypeToString(shmem->model));
+        devstr = qemuBuildShmemDevStr(def, shmem, qemuCaps);
         break;
 
     case VIR_DOMAIN_SHMEM_MODEL_LAST:
index a793fb6c78b58a46e034219436a30fa12e062b6b..0ddaba473c5767af14b4736c5569e84deb4a71cb 100644 (file)
@@ -187,4 +187,14 @@ bool qemuCheckCCWS390AddressSupport(const virDomainDef *def,
 virJSONValuePtr qemuBuildHotpluggableCPUProps(const virDomainVcpuDef *vcpu)
     ATTRIBUTE_NONNULL(1);
 
+virJSONValuePtr qemuBuildShmemBackendMemProps(virDomainShmemDefPtr shmem)
+    ATTRIBUTE_NONNULL(1);
+
+char *qemuBuildShmemDevStr(virDomainDefPtr def,
+                           virDomainShmemDefPtr shmem,
+                           virQEMUCapsPtr qemuCaps)
+    ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2) ATTRIBUTE_NONNULL(3);
+
+
+
 #endif /* __QEMU_COMMAND_H__*/
diff --git a/tests/qemuxml2argvdata/qemuxml2argv-shmem-plain-doorbell.args b/tests/qemuxml2argvdata/qemuxml2argv-shmem-plain-doorbell.args
new file mode 100644 (file)
index 0000000..7abc7f8
--- /dev/null
@@ -0,0 +1,43 @@
+LC_ALL=C \
+PATH=/bin \
+HOME=/home/test \
+USER=test \
+LOGNAME=test \
+QEMU_AUDIO_DRV=none \
+/usr/bin/qemu \
+-name QEMUGuest1 \
+-S \
+-M pc \
+-m 214 \
+-smp 1,sockets=1,cores=1,threads=1 \
+-uuid c7a5fdbd-edaf-9455-926a-d65c16db1809 \
+-nographic \
+-nodefaults \
+-monitor unix:/tmp/lib/domain--1-QEMUGuest1/monitor.sock,server,nowait \
+-no-acpi \
+-boot c \
+-usb \
+-object memory-backend-file,id=shmmem-shmem0,mem-path=/dev/shm/shmem0,\
+size=4194304 \
+-device ivshmem-plain,id=shmem0,memdev=shmmem-shmem0,bus=pci.0,addr=0x3 \
+-object memory-backend-file,id=shmmem-shmem1,mem-path=/dev/shm/shmem1,\
+size=134217728 \
+-device ivshmem-plain,id=shmem1,memdev=shmmem-shmem1,bus=pci.0,addr=0x5 \
+-object memory-backend-file,id=shmmem-shmem2,mem-path=/dev/shm/shmem2,\
+size=268435456 \
+-device ivshmem-plain,id=shmem2,memdev=shmmem-shmem2,bus=pci.0,addr=0x4 \
+-device ivshmem-doorbell,id=shmem3,chardev=charshmem3,ioeventfd=on,bus=pci.0,\
+addr=0x6 \
+-chardev socket,id=charshmem3,path=/var/lib/libvirt/shmem-shmem3-sock \
+-device ivshmem-doorbell,id=shmem4,chardev=charshmem4,ioeventfd=on,bus=pci.0,\
+addr=0x7 \
+-chardev socket,id=charshmem4,path=/tmp/shmem4-sock \
+-device ivshmem-doorbell,id=shmem5,chardev=charshmem5,ioeventfd=off,bus=pci.0,\
+addr=0x8 \
+-chardev socket,id=charshmem5,path=/tmp/shmem5-sock \
+-device ivshmem-doorbell,id=shmem6,chardev=charshmem6,vectors=16,ioeventfd=on,\
+bus=pci.0,addr=0x9 \
+-chardev socket,id=charshmem6,path=/tmp/shmem6-sock \
+-device ivshmem-doorbell,id=shmem7,chardev=charshmem7,vectors=32,ioeventfd=on,\
+bus=pci.0,addr=0xa \
+-chardev socket,id=charshmem7,path=/tmp/shmem7-sock
index 90d6aafe5639e34a9396d580f689f16e9111c058..d02593083673b617bfabb045a315feff5ad93430 100644 (file)
@@ -2075,6 +2075,9 @@ mymain(void)
     DO_TEST("fips-enabled", QEMU_CAPS_ENABLE_FIPS);
 
     DO_TEST("shmem", QEMU_CAPS_DEVICE_IVSHMEM);
+    DO_TEST("shmem-plain-doorbell", QEMU_CAPS_DEVICE_IVSHMEM,
+            QEMU_CAPS_DEVICE_IVSHMEM_PLAIN,
+            QEMU_CAPS_DEVICE_IVSHMEM_DOORBELL);
     DO_TEST_FAILURE("shmem", NONE);
     DO_TEST_FAILURE("shmem-invalid-size",
                     QEMU_CAPS_DEVICE_IVSHMEM);