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(a)redhat.com>
---
src/qemu/qemu_command.c | 99 ++++++++++++++++++++++++++++++++++++++++++++++--
src/qemu/qemu_command.h | 10 +++++
tests/qemuxml2argvtest.c | 3 ++
3 files changed, 109 insertions(+), 3 deletions(-)
diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c
index 558122b4cf7e..972cccee25de 100644
--- a/src/qemu/qemu_command.c
+++ b/src/qemu/qemu_command.c
@@ -8443,6 +8443,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;
+ }
+
+ virBufferAsprintf(&buf, "%s",
virDomainShmemModelTypeToString(shmem->model));
+ 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,
@@ -8463,6 +8507,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,
@@ -8505,10 +8593,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:
diff --git a/src/qemu/qemu_command.h b/src/qemu/qemu_command.h
index 2f2a6ff877e7..facc833bf886 100644
--- a/src/qemu/qemu_command.h
+++ b/src/qemu/qemu_command.h
@@ -186,4 +186,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/qemuxml2argvtest.c b/tests/qemuxml2argvtest.c
index 4126388316ea..1fa6b0fdd338 100644
--- a/tests/qemuxml2argvtest.c
+++ b/tests/qemuxml2argvtest.c
@@ -2058,6 +2058,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);
--
2.10.1