This patch implements support for the ivshmem device in QEMU. Example from this xml: <shmem name='ivshmem0' model='ivshmem'> <server path='/tmp/socket-ivshmem0'/> <size unit='M'>32</size> <msi vectors='32' ioeventfd='on'/> </shmem> The following QEMU line is built: -device ivshmem,size=32m,vectors=32,chardev=charshmem0,msi=on, ioeventfd=on,role=master -chardev socket,path=/tmp/socket-ivshmem0,id=charshmem0 Note: PCI hotpluging is not implemented. Signed-off-by: Maxime Leroy <maxime.leroy@xxxxxxxxx> --- src/qemu/qemu_command.c | 105 +++++++++++++++++++++++++++++++++++++++++++++++- src/qemu/qemu_command.h | 4 ++ src/qemu/qemu_hotplug.c | 1 + 3 files changed, 109 insertions(+), 1 deletion(-) diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c index 0d7b12d..9fcceae 100644 --- a/src/qemu/qemu_command.c +++ b/src/qemu/qemu_command.c @@ -1019,6 +1019,10 @@ qemuAssignDeviceAliases(virDomainDefPtr def, virQEMUCapsPtr qemuCaps) if (virAsprintf(&def->hubs[i]->info.alias, "hub%zu", i) < 0) return -1; } + for (i = 0; i < def->nshmems; i++) { + if (virAsprintf(&def->shmems[i]->info.alias, "shmem%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; @@ -5043,6 +5047,100 @@ qemuBuildRedirdevDevStr(virDomainDefPtr def, return NULL; } +static char * +qemuBuildIvshmemDevStr(virDomainDefPtr def, + virDomainShmemDefPtr dev, + virQEMUCapsPtr qemuCaps) +{ + virBuffer buf = VIR_BUFFER_INITIALIZER; + virDomainIvshmemDefPtr ivshmem = &dev->data.ivshmem; + + 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 (ivshmem->size) + virBufferAsprintf(&buf, ",size=%llum", ivshmem->size / (1024 * 1024)); + + if (!ivshmem->server.enabled) + virBufferAsprintf(&buf, ",shm=%s", dev->name); + else { + virBufferAsprintf(&buf, ",chardev=char%s", dev->info.alias); + if (ivshmem->msi.enabled) { + virBufferAddLit(&buf, ",msi=on"); + if (ivshmem->msi.vectors) + virBufferAsprintf(&buf, ",vectors=%u", ivshmem->msi.vectors); + if (ivshmem->msi.ioeventfd) + virBufferAsprintf(&buf, ",ioeventfd=%s", + virTristateSwitchTypeToString(ivshmem->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; +} + +static int +qemuBuildIvshmemCommandLine(virCommandPtr cmd, + virDomainDefPtr def, + virDomainShmemDefPtr dev, + virQEMUCapsPtr qemuCaps) +{ + char *devstr; + virDomainIvshmemDefPtr ivshmem = &dev->data.ivshmem; + + virCommandAddArg(cmd, "-device"); + if (!(devstr = qemuBuildIvshmemDevStr(def, dev, qemuCaps))) + return -1; + virCommandAddArg(cmd, devstr); + VIR_FREE(devstr); + + if (ivshmem->server.enabled) { + virDomainChrSourceDef source; + + source.type = VIR_DOMAIN_CHR_TYPE_UNIX; + source.data.nix.path = ivshmem->server.path; + source.data.nix.listen = false; + + virCommandAddArg(cmd, "-chardev"); + if (!(devstr = qemuBuildChrChardevStr(&source, dev->info.alias, + qemuCaps))) + return -1; + virCommandAddArg(cmd, devstr); + VIR_FREE(devstr); + } + + return 0; +} + +static int +qemuBuildShmemCommandLine(virCommandPtr cmd, + virDomainDefPtr def, + virDomainShmemDefPtr dev, + virQEMUCapsPtr qemuCaps) +{ + switch (dev->model) { + case VIR_DOMAIN_SHMEM_MODEL_IVSHMEM: + return qemuBuildIvshmemCommandLine(cmd, def, dev, qemuCaps); + default: + virReportError(VIR_ERR_INTERNAL_ERROR, + _("Unexpected shem model %d"), dev->model); + } + return -1; +} + char * qemuBuildUSBHostdevDevStr(virDomainDefPtr def, virDomainHostdevDefPtr dev, @@ -5299,7 +5397,7 @@ qemuBuildSCSIHostdevDevStr(virDomainDefPtr def, /* This function outputs a -chardev command line option which describes only the * host side of the character device */ -static char * +char * qemuBuildChrChardevStr(virDomainChrSourceDefPtr dev, const char *alias, virQEMUCapsPtr qemuCaps) { @@ -9332,6 +9430,11 @@ qemuBuildCommandLine(virConnectPtr conn, } } + for (i = 0; i < def->nshmems; i++) { + if (qemuBuildShmemCommandLine(cmd, def, def->shmems[i], qemuCaps)) + goto error; + } + if (mlock) { unsigned long long memKB; diff --git a/src/qemu/qemu_command.h b/src/qemu/qemu_command.h index 633ff71..3373a59 100644 --- a/src/qemu/qemu_command.h +++ b/src/qemu/qemu_command.h @@ -130,6 +130,10 @@ char *qemuBuildDriveDevStr(virDomainDefPtr def, char *qemuBuildFSDevStr(virDomainDefPtr domainDef, virDomainFSDefPtr fs, virQEMUCapsPtr qemuCaps); + +char * qemuBuildChrChardevStr(virDomainChrSourceDefPtr dev, + const char *alias, + virQEMUCapsPtr qemuCaps); /* Current, best practice */ char *qemuBuildControllerDevStr(virDomainDefPtr domainDef, virDomainControllerDefPtr def, diff --git a/src/qemu/qemu_hotplug.c b/src/qemu/qemu_hotplug.c index a364c52..def442b 100644 --- a/src/qemu/qemu_hotplug.c +++ b/src/qemu/qemu_hotplug.c @@ -2858,6 +2858,7 @@ qemuDomainRemoveDevice(virQEMUDriverPtr driver, case VIR_DOMAIN_DEVICE_MEMBALLOON: case VIR_DOMAIN_DEVICE_NVRAM: case VIR_DOMAIN_DEVICE_RNG: + case VIR_DOMAIN_DEVICE_SHMEM: case VIR_DOMAIN_DEVICE_LAST: virReportError(VIR_ERR_OPERATION_UNSUPPORTED, _("don't know how to remove a %s device"), -- 1.9.3 -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list