diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c index d6a5f44246..96c4f31ccf 100644 --- a/src/qemu/qemu_command.c +++ b/src/qemu/qemu_command.c @@ -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: diff --git a/src/qemu/qemu_command.h b/src/qemu/qemu_command.h index a793fb6c78..0ddaba473c 100644 --- a/src/qemu/qemu_command.h +++ b/src/qemu/qemu_command.h @@ -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 index 0000000000..7abc7f8c4b --- /dev/null +++ b/tests/qemuxml2argvdata/qemuxml2argv-shmem-plain-doorbell.args @@ -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 diff --git a/tests/qemuxml2argvtest.c b/tests/qemuxml2argvtest.c index 90d6aafe56..d025930836 100644 --- a/tests/qemuxml2argvtest.c +++ b/tests/qemuxml2argvtest.c @@ -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);