127bba
From e168fd982d20f1d68d13b210606f646ec937b678 Mon Sep 17 00:00:00 2001
127bba
Message-Id: <e168fd982d20f1d68d13b210606f646ec937b678@dist-git>
127bba
From: Martin Kletzander <mkletzan@redhat.com>
127bba
Date: Fri, 4 Nov 2016 10:29:53 +0100
127bba
Subject: [PATCH] qemu: Support newer ivshmem device variants
127bba
127bba
QEMU added support for ivshmem-plain and ivshmem-doorbell.  Those are
127bba
reworked varians of legacy ivshmem that are compatible from the guest
127bba
POV, but not from host's POV and have sane specification and handling.
127bba
127bba
Details about the newer device type can be found in qemu's commit
127bba
5400c02b90bb:
127bba
127bba
  http://git.qemu.org/?p=qemu.git;a=commit;h=5400c02b90bb
127bba
127bba
Signed-off-by: Martin Kletzander <mkletzan@redhat.com>
127bba
(cherry picked from commit 06524fd52c74a4fc672e9eec2b5a13d540e7ee06)
127bba
127bba
https://bugzilla.redhat.com/show_bug.cgi?id=1392031
127bba
127bba
Signed-off-by: Martin Kletzander <mkletzan@redhat.com>
127bba
---
127bba
 src/qemu/qemu_command.c                            | 99 +++++++++++++++++++++-
127bba
 src/qemu/qemu_command.h                            | 10 +++
127bba
 .../qemuxml2argv-shmem-plain-doorbell.args         | 43 ++++++++++
127bba
 tests/qemuxml2argvtest.c                           |  3 +
127bba
 4 files changed, 152 insertions(+), 3 deletions(-)
127bba
 create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-shmem-plain-doorbell.args
127bba
127bba
diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c
127bba
index e145c9f..dd8f60f 100644
127bba
--- a/src/qemu/qemu_command.c
127bba
+++ b/src/qemu/qemu_command.c
127bba
@@ -8503,6 +8503,50 @@ qemuBuildShmemDevLegacyStr(virDomainDefPtr def,
127bba
     return NULL;
127bba
 }
127bba
 
127bba
+char *
127bba
+qemuBuildShmemDevStr(virDomainDefPtr def,
127bba
+                     virDomainShmemDefPtr shmem,
127bba
+                     virQEMUCapsPtr qemuCaps)
127bba
+{
127bba
+    virBuffer buf = VIR_BUFFER_INITIALIZER;
127bba
+
127bba
+    if ((shmem->model == VIR_DOMAIN_SHMEM_MODEL_IVSHMEM_PLAIN &&
127bba
+         !virQEMUCapsGet(qemuCaps, QEMU_CAPS_DEVICE_IVSHMEM_PLAIN)) ||
127bba
+        (shmem->model == VIR_DOMAIN_SHMEM_MODEL_IVSHMEM_DOORBELL &&
127bba
+         !virQEMUCapsGet(qemuCaps, QEMU_CAPS_DEVICE_IVSHMEM_DOORBELL))) {
127bba
+            virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
127bba
+                           _("shmem model '%s' is not supported "
127bba
+                             "by this QEMU binary"),
127bba
+                           virDomainShmemModelTypeToString(shmem->model));
127bba
+        return NULL;
127bba
+    }
127bba
+
127bba
+    virBufferAdd(&buf, virDomainShmemModelTypeToString(shmem->model), -1);
127bba
+    virBufferAsprintf(&buf, ",id=%s", shmem->info.alias);
127bba
+
127bba
+    if (shmem->server.enabled)
127bba
+        virBufferAsprintf(&buf, ",chardev=char%s", shmem->info.alias);
127bba
+    else
127bba
+        virBufferAsprintf(&buf, ",memdev=shmmem-%s", shmem->info.alias);
127bba
+
127bba
+    if (shmem->msi.vectors)
127bba
+        virBufferAsprintf(&buf, ",vectors=%u", shmem->msi.vectors);
127bba
+    if (shmem->msi.ioeventfd) {
127bba
+        virBufferAsprintf(&buf, ",ioeventfd=%s",
127bba
+                          virTristateSwitchTypeToString(shmem->msi.ioeventfd));
127bba
+    }
127bba
+
127bba
+    if (qemuBuildDeviceAddressStr(&buf, def, &shmem->info, qemuCaps) < 0) {
127bba
+        virBufferFreeAndReset(&buf;;
127bba
+        return NULL;
127bba
+    }
127bba
+
127bba
+    if (virBufferCheckError(&buf) < 0)
127bba
+        return NULL;
127bba
+
127bba
+    return virBufferContentAndReset(&buf;;
127bba
+}
127bba
+
127bba
 static char *
127bba
 qemuBuildShmemBackendChrStr(virLogManagerPtr logManager,
127bba
                             virCommandPtr cmd,
127bba
@@ -8523,6 +8567,50 @@ qemuBuildShmemBackendChrStr(virLogManagerPtr logManager,
127bba
     return devstr;
127bba
 }
127bba
 
127bba
+
127bba
+virJSONValuePtr
127bba
+qemuBuildShmemBackendMemProps(virDomainShmemDefPtr shmem)
127bba
+{
127bba
+    char *mem_path = NULL;
127bba
+    virJSONValuePtr ret = NULL;
127bba
+
127bba
+    if (virAsprintf(&mem_path, "/dev/shm/%s", shmem->name) < 0)
127bba
+        return NULL;
127bba
+
127bba
+    virJSONValueObjectCreate(&ret,
127bba
+                             "s:mem-path", mem_path,
127bba
+                             "U:size", shmem->size,
127bba
+                             NULL);
127bba
+
127bba
+    VIR_FREE(mem_path);
127bba
+    return ret;
127bba
+}
127bba
+
127bba
+
127bba
+static char *
127bba
+qemuBuildShmemBackendMemStr(virDomainShmemDefPtr shmem)
127bba
+{
127bba
+    char *ret = NULL;
127bba
+    char *alias = NULL;
127bba
+    virJSONValuePtr props = qemuBuildShmemBackendMemProps(shmem);
127bba
+
127bba
+    if (!props)
127bba
+        return NULL;
127bba
+
127bba
+    if (virAsprintf(&alias, "shmmem-%s", shmem->info.alias) < 0)
127bba
+        goto cleanup;
127bba
+
127bba
+    ret = virQEMUBuildObjectCommandlineFromJSON("memory-backend-file",
127bba
+                                                alias,
127bba
+                                                props);
127bba
+ cleanup:
127bba
+    VIR_FREE(alias);
127bba
+    virJSONValueFree(props);
127bba
+
127bba
+    return ret;
127bba
+}
127bba
+
127bba
+
127bba
 static int
127bba
 qemuBuildShmemCommandLine(virLogManagerPtr logManager,
127bba
                           virCommandPtr cmd,
127bba
@@ -8565,10 +8653,15 @@ qemuBuildShmemCommandLine(virLogManagerPtr logManager,
127bba
         break;
127bba
 
127bba
     case VIR_DOMAIN_SHMEM_MODEL_IVSHMEM_PLAIN:
127bba
+        if (!(devstr = qemuBuildShmemBackendMemStr(shmem)))
127bba
+            return -1;
127bba
+
127bba
+        virCommandAddArgList(cmd, "-object", devstr, NULL);
127bba
+        VIR_FREE(devstr);
127bba
+
127bba
+        /* fall-through */
127bba
     case VIR_DOMAIN_SHMEM_MODEL_IVSHMEM_DOORBELL:
127bba
-        virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
127bba
-                       _("%s device is not supported with this QEMU binary"),
127bba
-                       virDomainShmemModelTypeToString(shmem->model));
127bba
+        devstr = qemuBuildShmemDevStr(def, shmem, qemuCaps);
127bba
         break;
127bba
 
127bba
     case VIR_DOMAIN_SHMEM_MODEL_LAST:
127bba
diff --git a/src/qemu/qemu_command.h b/src/qemu/qemu_command.h
127bba
index 7f33d83..a633f4e 100644
127bba
--- a/src/qemu/qemu_command.h
127bba
+++ b/src/qemu/qemu_command.h
127bba
@@ -179,4 +179,14 @@ bool qemuCheckCCWS390AddressSupport(const virDomainDef *def,
127bba
 virJSONValuePtr qemuBuildHotpluggableCPUProps(const virDomainVcpuDef *vcpu)
127bba
     ATTRIBUTE_NONNULL(1);
127bba
 
127bba
+virJSONValuePtr qemuBuildShmemBackendMemProps(virDomainShmemDefPtr shmem)
127bba
+    ATTRIBUTE_NONNULL(1);
127bba
+
127bba
+char *qemuBuildShmemDevStr(virDomainDefPtr def,
127bba
+                           virDomainShmemDefPtr shmem,
127bba
+                           virQEMUCapsPtr qemuCaps)
127bba
+    ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2) ATTRIBUTE_NONNULL(3);
127bba
+
127bba
+
127bba
+
127bba
 #endif /* __QEMU_COMMAND_H__*/
127bba
diff --git a/tests/qemuxml2argvdata/qemuxml2argv-shmem-plain-doorbell.args b/tests/qemuxml2argvdata/qemuxml2argv-shmem-plain-doorbell.args
127bba
new file mode 100644
127bba
index 0000000..7abc7f8
127bba
--- /dev/null
127bba
+++ b/tests/qemuxml2argvdata/qemuxml2argv-shmem-plain-doorbell.args
127bba
@@ -0,0 +1,43 @@
127bba
+LC_ALL=C \
127bba
+PATH=/bin \
127bba
+HOME=/home/test \
127bba
+USER=test \
127bba
+LOGNAME=test \
127bba
+QEMU_AUDIO_DRV=none \
127bba
+/usr/bin/qemu \
127bba
+-name QEMUGuest1 \
127bba
+-S \
127bba
+-M pc \
127bba
+-m 214 \
127bba
+-smp 1,sockets=1,cores=1,threads=1 \
127bba
+-uuid c7a5fdbd-edaf-9455-926a-d65c16db1809 \
127bba
+-nographic \
127bba
+-nodefaults \
127bba
+-monitor unix:/tmp/lib/domain--1-QEMUGuest1/monitor.sock,server,nowait \
127bba
+-no-acpi \
127bba
+-boot c \
127bba
+-usb \
127bba
+-object memory-backend-file,id=shmmem-shmem0,mem-path=/dev/shm/shmem0,\
127bba
+size=4194304 \
127bba
+-device ivshmem-plain,id=shmem0,memdev=shmmem-shmem0,bus=pci.0,addr=0x3 \
127bba
+-object memory-backend-file,id=shmmem-shmem1,mem-path=/dev/shm/shmem1,\
127bba
+size=134217728 \
127bba
+-device ivshmem-plain,id=shmem1,memdev=shmmem-shmem1,bus=pci.0,addr=0x5 \
127bba
+-object memory-backend-file,id=shmmem-shmem2,mem-path=/dev/shm/shmem2,\
127bba
+size=268435456 \
127bba
+-device ivshmem-plain,id=shmem2,memdev=shmmem-shmem2,bus=pci.0,addr=0x4 \
127bba
+-device ivshmem-doorbell,id=shmem3,chardev=charshmem3,ioeventfd=on,bus=pci.0,\
127bba
+addr=0x6 \
127bba
+-chardev socket,id=charshmem3,path=/var/lib/libvirt/shmem-shmem3-sock \
127bba
+-device ivshmem-doorbell,id=shmem4,chardev=charshmem4,ioeventfd=on,bus=pci.0,\
127bba
+addr=0x7 \
127bba
+-chardev socket,id=charshmem4,path=/tmp/shmem4-sock \
127bba
+-device ivshmem-doorbell,id=shmem5,chardev=charshmem5,ioeventfd=off,bus=pci.0,\
127bba
+addr=0x8 \
127bba
+-chardev socket,id=charshmem5,path=/tmp/shmem5-sock \
127bba
+-device ivshmem-doorbell,id=shmem6,chardev=charshmem6,vectors=16,ioeventfd=on,\
127bba
+bus=pci.0,addr=0x9 \
127bba
+-chardev socket,id=charshmem6,path=/tmp/shmem6-sock \
127bba
+-device ivshmem-doorbell,id=shmem7,chardev=charshmem7,vectors=32,ioeventfd=on,\
127bba
+bus=pci.0,addr=0xa \
127bba
+-chardev socket,id=charshmem7,path=/tmp/shmem7-sock
127bba
diff --git a/tests/qemuxml2argvtest.c b/tests/qemuxml2argvtest.c
127bba
index df9c832..7ae7f5d 100644
127bba
--- a/tests/qemuxml2argvtest.c
127bba
+++ b/tests/qemuxml2argvtest.c
127bba
@@ -1967,6 +1967,9 @@ mymain(void)
127bba
     DO_TEST("fips-enabled", QEMU_CAPS_ENABLE_FIPS);
127bba
 
127bba
     DO_TEST("shmem", QEMU_CAPS_DEVICE_IVSHMEM);
127bba
+    DO_TEST("shmem-plain-doorbell", QEMU_CAPS_DEVICE_IVSHMEM,
127bba
+            QEMU_CAPS_DEVICE_IVSHMEM_PLAIN,
127bba
+            QEMU_CAPS_DEVICE_IVSHMEM_DOORBELL);
127bba
     DO_TEST_FAILURE("shmem", NONE);
127bba
     DO_TEST_FAILURE("shmem-invalid-size",
127bba
                     QEMU_CAPS_DEVICE_IVSHMEM);
127bba
-- 
127bba
2.10.2
127bba