[libvirt] [PATCH 0/7] IVSHMEM round two, this time with cookies
Actually just migration cookie flag. Also this version dropped the role and model to make everything more sunshine-n-unicorns. Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1347049 Martin Kletzander (7): conf: Fix virDomainShmemDefFind qemu: Add capabilities for ivshmem-{plain,doorbell} qemu: Save various defaults for shmem qemu: Add qemuDomainSupportsNonLegacyShmem qemu: Disable migration with legacy ivshmem qemu: Support newer ivshmem device variants qemu: Add support for hot/cold-(un)plug of shmem devices docs/formatdomain.html.in | 6 +- src/conf/domain_conf.c | 4 +- src/qemu/qemu_capabilities.c | 4 + src/qemu/qemu_capabilities.h | 2 + src/qemu/qemu_command.c | 109 +++++++++- src/qemu/qemu_command.h | 10 + src/qemu/qemu_domain.c | 24 +++ src/qemu/qemu_domain.h | 3 + src/qemu/qemu_driver.c | 39 +++- src/qemu/qemu_hotplug.c | 231 ++++++++++++++++++++- src/qemu/qemu_hotplug.h | 6 + src/qemu/qemu_migration.c | 27 ++- .../caps_2.6.0-gicv2.aarch64.xml | 2 + .../caps_2.6.0-gicv3.aarch64.xml | 2 + tests/qemucapabilitiesdata/caps_2.6.0.ppc64le.xml | 2 + tests/qemucapabilitiesdata/caps_2.6.0.x86_64.xml | 2 + tests/qemucapabilitiesdata/caps_2.7.0.x86_64.xml | 2 + tests/qemuhotplugtest.c | 21 ++ .../qemuhotplug-ivshmem-doorbell-detach.xml | 6 + .../qemuhotplug-ivshmem-doorbell.xml | 3 + .../qemuhotplug-ivshmem-plain-detach.xml | 5 + .../qemuhotplug-ivshmem-plain.xml | 1 + ...muhotplug-base-live+ivshmem-doorbell-detach.xml | 1 + .../qemuhotplug-base-live+ivshmem-doorbell.xml | 63 ++++++ .../qemuhotplug-base-live+ivshmem-plain-detach.xml | 1 + .../qemuhotplug-base-live+ivshmem-plain.xml | 57 +++++ .../qemuxml2argv-shmem-plain-doorbell.args | 46 ++++ .../qemuxml2argv-shmem-plain-doorbell.xml | 1 + tests/qemuxml2argvdata/qemuxml2argv-shmem.args | 18 +- tests/qemuxml2argvtest.c | 3 + tests/qemuxml2xmloutdata/qemuxml2xmlout-shmem.xml | 10 +- 31 files changed, 685 insertions(+), 26 deletions(-) create mode 100644 tests/qemuhotplugtestdevices/qemuhotplug-ivshmem-doorbell-detach.xml create mode 100644 tests/qemuhotplugtestdevices/qemuhotplug-ivshmem-doorbell.xml create mode 100644 tests/qemuhotplugtestdevices/qemuhotplug-ivshmem-plain-detach.xml create mode 100644 tests/qemuhotplugtestdevices/qemuhotplug-ivshmem-plain.xml create mode 120000 tests/qemuhotplugtestdomains/qemuhotplug-base-live+ivshmem-doorbell-detach.xml create mode 100644 tests/qemuhotplugtestdomains/qemuhotplug-base-live+ivshmem-doorbell.xml create mode 120000 tests/qemuhotplugtestdomains/qemuhotplug-base-live+ivshmem-plain-detach.xml create mode 100644 tests/qemuhotplugtestdomains/qemuhotplug-base-live+ivshmem-plain.xml create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-shmem-plain-doorbell.args create mode 120000 tests/qemuxml2argvdata/qemuxml2argv-shmem-plain-doorbell.xml -- 2.10.0
Due to the switch of parameters in a call to virDomainShmemDefEquals() no device was found when looking for device with all the information except address. Also fix the indentation. Signed-off-by: Martin Kletzander <mkletzan@redhat.com> --- src/conf/domain_conf.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c index a70be319891e..0ddfef89e762 100644 --- a/src/conf/domain_conf.c +++ b/src/conf/domain_conf.c @@ -14814,8 +14814,8 @@ virDomainShmemDefFind(virDomainDefPtr def, size_t i; for (i = 0; i < def->nshmems; i++) { - if (virDomainShmemDefEquals(def->shmems[i], shmem)) - break; + if (virDomainShmemDefEquals(shmem, def->shmems[i])) + break; } if (i < def->nshmems) -- 2.10.0
Signed-off-by: Martin Kletzander <mkletzan@redhat.com> --- src/qemu/qemu_capabilities.c | 4 ++++ src/qemu/qemu_capabilities.h | 2 ++ tests/qemucapabilitiesdata/caps_2.6.0-gicv2.aarch64.xml | 2 ++ tests/qemucapabilitiesdata/caps_2.6.0-gicv3.aarch64.xml | 2 ++ tests/qemucapabilitiesdata/caps_2.6.0.ppc64le.xml | 2 ++ tests/qemucapabilitiesdata/caps_2.6.0.x86_64.xml | 2 ++ tests/qemucapabilitiesdata/caps_2.7.0.x86_64.xml | 2 ++ 7 files changed, 16 insertions(+) diff --git a/src/qemu/qemu_capabilities.c b/src/qemu/qemu_capabilities.c index c71b4dcf44ca..a4beac351eb0 100644 --- a/src/qemu/qemu_capabilities.c +++ b/src/qemu/qemu_capabilities.c @@ -344,6 +344,8 @@ VIR_ENUM_IMPL(virQEMUCaps, QEMU_CAPS_LAST, "query-hotpluggable-cpus", "virtio-net.rx_queue_size", /* 235 */ + "ivshmem-plain", + "ivshmem-doorbell", ); @@ -1568,6 +1570,8 @@ struct virQEMUCapsStringFlags virQEMUCapsObjectTypes[] = { { "pxb-pcie", QEMU_CAPS_DEVICE_PXB_PCIE }, { "tls-creds-x509", QEMU_CAPS_OBJECT_TLS_CREDS_X509 }, { "intel-iommu", QEMU_CAPS_DEVICE_INTEL_IOMMU }, + { "ivshmem-plain", QEMU_CAPS_DEVICE_IVSHMEM_PLAIN }, + { "ivshmem-doorbell", QEMU_CAPS_DEVICE_IVSHMEM_DOORBELL }, }; static struct virQEMUCapsStringFlags virQEMUCapsObjectPropsVirtioBalloon[] = { diff --git a/src/qemu/qemu_capabilities.h b/src/qemu/qemu_capabilities.h index 26ac1fa6c364..88d1024536d9 100644 --- a/src/qemu/qemu_capabilities.h +++ b/src/qemu/qemu_capabilities.h @@ -378,6 +378,8 @@ typedef enum { /* 235 */ QEMU_CAPS_VIRTIO_NET_RX_QUEUE_SIZE, /* virtio-net-*.rx_queue_size */ + QEMU_CAPS_DEVICE_IVSHMEM_PLAIN, /* -device ivshmem-plain */ + QEMU_CAPS_DEVICE_IVSHMEM_DOORBELL, /* -device ivshmem-doorbell */ QEMU_CAPS_LAST /* this must always be the last item */ } virQEMUCapsFlags; diff --git a/tests/qemucapabilitiesdata/caps_2.6.0-gicv2.aarch64.xml b/tests/qemucapabilitiesdata/caps_2.6.0-gicv2.aarch64.xml index fd14665d5397..0644718ee081 100644 --- a/tests/qemucapabilitiesdata/caps_2.6.0-gicv2.aarch64.xml +++ b/tests/qemucapabilitiesdata/caps_2.6.0-gicv2.aarch64.xml @@ -159,6 +159,8 @@ <flag name='display'/> <flag name='smm'/> <flag name='virtio-pci-disable-legacy'/> + <flag name='ivshmem-plain'/> + <flag name='ivshmem-doorbell'/> <version>2005094</version> <kvmVersion>0</kvmVersion> <package></package> diff --git a/tests/qemucapabilitiesdata/caps_2.6.0-gicv3.aarch64.xml b/tests/qemucapabilitiesdata/caps_2.6.0-gicv3.aarch64.xml index eb708f8a983a..9526ae8b70b9 100644 --- a/tests/qemucapabilitiesdata/caps_2.6.0-gicv3.aarch64.xml +++ b/tests/qemucapabilitiesdata/caps_2.6.0-gicv3.aarch64.xml @@ -159,6 +159,8 @@ <flag name='display'/> <flag name='smm'/> <flag name='virtio-pci-disable-legacy'/> + <flag name='ivshmem-plain'/> + <flag name='ivshmem-doorbell'/> <version>2005094</version> <kvmVersion>0</kvmVersion> <package></package> diff --git a/tests/qemucapabilitiesdata/caps_2.6.0.ppc64le.xml b/tests/qemucapabilitiesdata/caps_2.6.0.ppc64le.xml index 482b3849b50f..f97d2b05ffa7 100644 --- a/tests/qemucapabilitiesdata/caps_2.6.0.ppc64le.xml +++ b/tests/qemucapabilitiesdata/caps_2.6.0.ppc64le.xml @@ -153,6 +153,8 @@ <flag name='display'/> <flag name='smm'/> <flag name='virtio-pci-disable-legacy'/> + <flag name='ivshmem-plain'/> + <flag name='ivshmem-doorbell'/> <version>2005094</version> <kvmVersion>0</kvmVersion> <package></package> diff --git a/tests/qemucapabilitiesdata/caps_2.6.0.x86_64.xml b/tests/qemucapabilitiesdata/caps_2.6.0.x86_64.xml index 60f1fcfe85d5..845a98bafe30 100644 --- a/tests/qemucapabilitiesdata/caps_2.6.0.x86_64.xml +++ b/tests/qemucapabilitiesdata/caps_2.6.0.x86_64.xml @@ -196,6 +196,8 @@ <flag name='intel-iommu'/> <flag name='smm'/> <flag name='virtio-pci-disable-legacy'/> + <flag name='ivshmem-plain'/> + <flag name='ivshmem-doorbell'/> <version>2006000</version> <kvmVersion>0</kvmVersion> <package></package> diff --git a/tests/qemucapabilitiesdata/caps_2.7.0.x86_64.xml b/tests/qemucapabilitiesdata/caps_2.7.0.x86_64.xml index 98f37622bff0..cb6a55a9ec0c 100644 --- a/tests/qemucapabilitiesdata/caps_2.7.0.x86_64.xml +++ b/tests/qemucapabilitiesdata/caps_2.7.0.x86_64.xml @@ -197,6 +197,8 @@ <flag name='smm'/> <flag name='virtio-pci-disable-legacy'/> <flag name='query-hotpluggable-cpus'/> + <flag name='ivshmem-plain'/> + <flag name='ivshmem-doorbell'/> <version>2007000</version> <kvmVersion>0</kvmVersion> <package> (v2.7.0)</package> -- 2.10.0
We're keeping some things at default and that's not something we want to do intentionaly. Let's save some sensible defaults upfront then having problems later. The details for the defaults (of the newer implementation) 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> --- docs/formatdomain.html.in | 1 - src/qemu/qemu_domain.c | 12 ++++++++++++ tests/qemuxml2argvdata/qemuxml2argv-shmem.args | 18 ++++++++++-------- tests/qemuxml2xmloutdata/qemuxml2xmlout-shmem.xml | 10 ++++------ 4 files changed, 26 insertions(+), 15 deletions(-) diff --git a/docs/formatdomain.html.in b/docs/formatdomain.html.in index f48a4d8b813f..b9163584d9f5 100644 --- a/docs/formatdomain.html.in +++ b/docs/formatdomain.html.in @@ -6751,7 +6751,6 @@ qemu-kvm -net nic,model=? /dev/null <size unit='M'>4</size> </shmem> <shmem name='shmem_server'> - <size unit='M'>2</size> <server path='/tmp/socket-shmem'/> <msi vectors='32' ioeventfd='on'/> </shmem> diff --git a/src/qemu/qemu_domain.c b/src/qemu/qemu_domain.c index 177525b0ab81..f533086b8eef 100644 --- a/src/qemu/qemu_domain.c +++ b/src/qemu/qemu_domain.c @@ -2747,6 +2747,18 @@ qemuDomainDeviceDefPostParse(virDomainDeviceDefPtr dev, } } + if (dev->type == VIR_DOMAIN_DEVICE_SHMEM) { + if (!dev->data.shmem->server.enabled) { + if (!dev->data.shmem->size) + dev->data.shmem->size = 4 << 20; + } else { + dev->data.shmem->size = 0; + dev->data.shmem->msi.enabled = true; + if (!dev->data.shmem->msi.ioeventfd) + dev->data.shmem->msi.ioeventfd = VIR_TRISTATE_SWITCH_ON; + } + } + ret = 0; cleanup: diff --git a/tests/qemuxml2argvdata/qemuxml2argv-shmem.args b/tests/qemuxml2argvdata/qemuxml2argv-shmem.args index 99fac119b04c..9dab81219051 100644 --- a/tests/qemuxml2argvdata/qemuxml2argv-shmem.args +++ b/tests/qemuxml2argvdata/qemuxml2argv-shmem.args @@ -17,19 +17,21 @@ QEMU_AUDIO_DRV=none \ -no-acpi \ -boot c \ -usb \ --device ivshmem,id=shmem0,shm=shmem0,bus=pci.0,addr=0x3 \ +-device ivshmem,id=shmem0,size=4m,shm=shmem0,bus=pci.0,addr=0x3 \ -device ivshmem,id=shmem1,size=128m,shm=shmem1,bus=pci.0,addr=0x5 \ -device ivshmem,id=shmem2,size=256m,shm=shmem2,bus=pci.0,addr=0x4 \ --device ivshmem,id=shmem3,size=512m,chardev=charshmem3,bus=pci.0,addr=0x6 \ +-device ivshmem,id=shmem3,chardev=charshmem3,msi=on,ioeventfd=on,bus=pci.0,\ +addr=0x6 \ -chardev socket,id=charshmem3,path=/var/lib/libvirt/shmem-shmem3-sock \ --device ivshmem,id=shmem4,size=1024m,chardev=charshmem4,bus=pci.0,addr=0x7 \ +-device ivshmem,id=shmem4,chardev=charshmem4,msi=on,ioeventfd=on,bus=pci.0,\ +addr=0x7 \ -chardev socket,id=charshmem4,path=/tmp/shmem4-sock \ --device ivshmem,id=shmem5,size=2048m,chardev=charshmem5,msi=on,ioeventfd=off,\ -bus=pci.0,addr=0x8 \ +-device ivshmem,id=shmem5,chardev=charshmem5,msi=on,ioeventfd=off,bus=pci.0,\ +addr=0x8 \ -chardev socket,id=charshmem5,path=/tmp/shmem5-sock \ --device ivshmem,id=shmem6,size=4096m,chardev=charshmem6,msi=on,vectors=16,\ +-device ivshmem,id=shmem6,chardev=charshmem6,msi=on,vectors=16,ioeventfd=on,\ bus=pci.0,addr=0x9 \ -chardev socket,id=charshmem6,path=/tmp/shmem6-sock \ --device ivshmem,id=shmem7,size=8192m,chardev=charshmem7,msi=on,vectors=32,\ -ioeventfd=on,bus=pci.0,addr=0xa \ +-device ivshmem,id=shmem7,chardev=charshmem7,msi=on,vectors=32,ioeventfd=on,\ +bus=pci.0,addr=0xa \ -chardev socket,id=charshmem7,path=/tmp/shmem7-sock diff --git a/tests/qemuxml2xmloutdata/qemuxml2xmlout-shmem.xml b/tests/qemuxml2xmloutdata/qemuxml2xmlout-shmem.xml index 1197f361e3c4..38f14fc4fa9b 100644 --- a/tests/qemuxml2xmloutdata/qemuxml2xmlout-shmem.xml +++ b/tests/qemuxml2xmloutdata/qemuxml2xmlout-shmem.xml @@ -22,6 +22,7 @@ <input type='keyboard' bus='ps2'/> <memballoon model='none'/> <shmem name='shmem0'> + <size unit='M'>4</size> <address type='pci' domain='0x0000' bus='0x00' slot='0x03' function='0x0'/> </shmem> <shmem name='shmem1'> @@ -33,29 +34,26 @@ <address type='pci' domain='0x0000' bus='0x00' slot='0x04' function='0x0'/> </shmem> <shmem name='shmem3'> - <size unit='M'>512</size> <server/> + <msi ioeventfd='on'/> <address type='pci' domain='0x0000' bus='0x00' slot='0x06' function='0x0'/> </shmem> <shmem name='shmem4'> - <size unit='M'>1024</size> <server path='/tmp/shmem4-sock'/> + <msi ioeventfd='on'/> <address type='pci' domain='0x0000' bus='0x00' slot='0x07' function='0x0'/> </shmem> <shmem name='shmem5'> - <size unit='M'>2048</size> <server path='/tmp/shmem5-sock'/> <msi ioeventfd='off'/> <address type='pci' domain='0x0000' bus='0x00' slot='0x08' function='0x0'/> </shmem> <shmem name='shmem6'> - <size unit='M'>4096</size> <server path='/tmp/shmem6-sock'/> - <msi vectors='16'/> + <msi vectors='16' ioeventfd='on'/> <address type='pci' domain='0x0000' bus='0x00' slot='0x09' function='0x0'/> </shmem> <shmem name='shmem7'> - <size unit='M'>8192</size> <server path='/tmp/shmem7-sock'/> <msi vectors='32' ioeventfd='on'/> <address type='pci' domain='0x0000' bus='0x00' slot='0x0a' function='0x0'/> -- 2.10.0
That function checks whether ivshmem_plain/doorbell devices are supported so that we don't decide on the capability on multiple places, it also unifies error reporting. Signed-off-by: Martin Kletzander <mkletzan@redhat.com> --- src/qemu/qemu_domain.c | 12 ++++++++++++ src/qemu/qemu_domain.h | 3 +++ 2 files changed, 15 insertions(+) diff --git a/src/qemu/qemu_domain.c b/src/qemu/qemu_domain.c index f533086b8eef..2ed0187cd49e 100644 --- a/src/qemu/qemu_domain.c +++ b/src/qemu/qemu_domain.c @@ -5994,6 +5994,18 @@ qemuDomainSupportsNetdev(virDomainDefPtr def, } +bool +qemuDomainSupportsNonLegacyShmem(virQEMUCapsPtr qemuCaps, + virDomainShmemDefPtr shmem) +{ + int device_cap = shmem->server.enabled ? + QEMU_CAPS_DEVICE_IVSHMEM_DOORBELL : + QEMU_CAPS_DEVICE_IVSHMEM_PLAIN; + + return virQEMUCapsGet(qemuCaps, device_cap); +} + + int qemuDomainNetVLAN(virDomainNetDefPtr def) { diff --git a/src/qemu/qemu_domain.h b/src/qemu/qemu_domain.h index c2fab3ba3521..7932764c9fe8 100644 --- a/src/qemu/qemu_domain.h +++ b/src/qemu/qemu_domain.h @@ -670,6 +670,9 @@ bool qemuDomainSupportsNetdev(virDomainDefPtr def, virQEMUCapsPtr qemuCaps, virDomainNetDefPtr net); +bool qemuDomainSupportsNonLegacyShmem(virQEMUCapsPtr qemuCaps, + virDomainShmemDefPtr shmem); + int qemuDomainNetVLAN(virDomainNetDefPtr def); int qemuDomainSetPrivatePaths(virQEMUDriverPtr driver, -- 2.10.0
Use migration flag for tracking whether newer ivshmem was used. Restore from old save will not work, but that shouldn't have been enabled in the first place. Signed-off-by: Martin Kletzander <mkletzan@redhat.com> --- src/qemu/qemu_migration.c | 27 +++++++++++++++++++++++++-- 1 file changed, 25 insertions(+), 2 deletions(-) diff --git a/src/qemu/qemu_migration.c b/src/qemu/qemu_migration.c index e734816c4e12..88b722d1c35d 100644 --- a/src/qemu/qemu_migration.c +++ b/src/qemu/qemu_migration.c @@ -93,6 +93,7 @@ enum qemuMigrationCookieFlags { QEMU_MIGRATION_COOKIE_FLAG_STATS, QEMU_MIGRATION_COOKIE_FLAG_MEMORY_HOTPLUG, QEMU_MIGRATION_COOKIE_FLAG_CPU_HOTPLUG, + QEMU_MIGRATION_COOKIE_FLAG_IVSHMEM, QEMU_MIGRATION_COOKIE_FLAG_LAST }; @@ -107,7 +108,8 @@ VIR_ENUM_IMPL(qemuMigrationCookieFlag, "nbd", "statistics", "memory-hotplug", - "cpu-hotplug"); + "cpu-hotplug", + "ivshmem"); enum qemuMigrationCookieFeatures { QEMU_MIGRATION_COOKIE_GRAPHICS = (1 << QEMU_MIGRATION_COOKIE_FLAG_GRAPHICS), @@ -118,6 +120,7 @@ enum qemuMigrationCookieFeatures { QEMU_MIGRATION_COOKIE_STATS = (1 << QEMU_MIGRATION_COOKIE_FLAG_STATS), QEMU_MIGRATION_COOKIE_MEMORY_HOTPLUG = (1 << QEMU_MIGRATION_COOKIE_FLAG_MEMORY_HOTPLUG), QEMU_MIGRATION_COOKIE_CPU_HOTPLUG = (1 << QEMU_MIGRATION_COOKIE_FLAG_CPU_HOTPLUG), + QEMU_MIGRATION_COOKIE_IVSHMEM = (1 << QEMU_MIGRATION_COOKIE_FLAG_IVSHMEM), }; typedef struct _qemuMigrationCookieGraphics qemuMigrationCookieGraphics; @@ -1414,6 +1417,9 @@ qemuMigrationBakeCookie(qemuMigrationCookiePtr mig, if (flags & QEMU_MIGRATION_COOKIE_CPU_HOTPLUG) mig->flagsMandatory |= QEMU_MIGRATION_COOKIE_CPU_HOTPLUG; + if (flags & QEMU_MIGRATION_COOKIE_IVSHMEM) + mig->flagsMandatory |= QEMU_MIGRATION_COOKIE_IVSHMEM; + if (!(*cookieout = qemuMigrationCookieXMLFormatStr(driver, mig))) return -1; @@ -2272,6 +2278,7 @@ qemuMigrationIsAllowed(virQEMUDriverPtr driver, int nsnapshots; int pauseReason; size_t i; + qemuDomainObjPrivatePtr priv = vm->privateData; /* perform these checks only when migrating to remote hosts */ if (remote) { @@ -2346,6 +2353,16 @@ qemuMigrationIsAllowed(virQEMUDriverPtr driver, return false; } } + + for (i = 0; i < vm->def->nshmems; i++) { + if (!qemuDomainSupportsNonLegacyShmem(priv->qemuCaps, + vm->def->shmems[i])) { + virReportError(VIR_ERR_OPERATION_INVALID, "%s", + _("Migration with shmem device is not " + "supported with this QEMU binary")); + return false; + } + } } return true; @@ -3192,6 +3209,11 @@ qemuMigrationBeginPhase(virQEMUDriverPtr driver, } } + /* We need to signal we are using newer ivshmem models, we + * wouldn't get here if we didn't. */ + if (vm->def->nshmems) + cookieFlags |= QEMU_MIGRATION_COOKIE_IVSHMEM; + if (virDomainDefHasMemoryHotplug(vm->def) || ((flags & VIR_MIGRATE_PERSIST_DEST) && vm->newDef && virDomainDefHasMemoryHotplug(vm->newDef))) @@ -3698,7 +3720,8 @@ qemuMigrationPrepareAny(virQEMUDriverPtr driver, QEMU_MIGRATION_COOKIE_LOCKSTATE | QEMU_MIGRATION_COOKIE_NBD | QEMU_MIGRATION_COOKIE_MEMORY_HOTPLUG | - QEMU_MIGRATION_COOKIE_CPU_HOTPLUG))) + QEMU_MIGRATION_COOKIE_CPU_HOTPLUG | + QEMU_MIGRATION_COOKIE_IVSHMEM))) goto cleanup; if (STREQ_NULLABLE(protocol, "rdma") && -- 2.10.0
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> --- docs/formatdomain.html.in | 5 +- src/qemu/qemu_command.c | 109 ++++++++++++++++++++- src/qemu/qemu_command.h | 10 ++ .../qemuxml2argv-shmem-plain-doorbell.args | 46 +++++++++ .../qemuxml2argv-shmem-plain-doorbell.xml | 1 + tests/qemuxml2argvtest.c | 3 + 6 files changed, 172 insertions(+), 2 deletions(-) create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-shmem-plain-doorbell.args create mode 120000 tests/qemuxml2argvdata/qemuxml2argv-shmem-plain-doorbell.xml diff --git a/docs/formatdomain.html.in b/docs/formatdomain.html.in index b9163584d9f5..c614caf5f47f 100644 --- a/docs/formatdomain.html.in +++ b/docs/formatdomain.html.in @@ -6740,7 +6740,10 @@ qemu-kvm -net nic,model=? /dev/null <p> A shared memory device allows to share a memory region between - different virtual machines and the host. + different virtual machines and the host. Note that memory in + this region will be migrated, if that's not desired, the device + needs to be unplugged before migration and plugged back again + after that. <span class="since">Since 1.2.10, QEMU and KVM only</span> </p> diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c index 2130a7e2e8cf..3f7dfc4a46b9 100644 --- a/src/qemu/qemu_command.c +++ b/src/qemu/qemu_command.c @@ -8550,6 +8550,44 @@ qemuBuildShmemDevLegacyStr(virDomainDefPtr def, return NULL; } +char * +qemuBuildShmemDevStr(virDomainDefPtr def, + virDomainShmemDefPtr shmem, + virQEMUCapsPtr qemuCaps) +{ + virBuffer buf = VIR_BUFFER_INITIALIZER; + + if (shmem->server.enabled) { + virBufferAddLit(&buf, "ivshmem-doorbell"); + virBufferAsprintf(&buf, ",id=%s,chardev=char%s", + shmem->info.alias, 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)); + } else { + virBufferAddLit(&buf, "ivshmem-plain"); + virBufferAsprintf(&buf, ",id=%s,memdev=shmmem-%s", + shmem->info.alias, shmem->info.alias); + + /* For now we default to master=on, users are adviced to + * unplug the ivshmem if they don't want to migrate the data + * in the shmem (see docs). */ + virBufferAddLit(&buf, ",master=on"); + } + + 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, @@ -8570,6 +8608,51 @@ 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, + "U:size", shmem->size, + "s:mem-path", mem_path, + 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, @@ -8579,6 +8662,18 @@ qemuBuildShmemCommandLine(virLogManagerPtr logManager, virQEMUCapsPtr qemuCaps) { char *devstr = NULL; + bool legacy = false; + + if (!qemuDomainSupportsNonLegacyShmem(qemuCaps, shmem)) { + if (!virQEMUCapsGet(qemuCaps, QEMU_CAPS_DEVICE_IVSHMEM)) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", + _("shmem device is not supported with this " + "QEMU binary")); + return -1; + } + + legacy = true; + } if (shmem->size) { /* @@ -8606,8 +8701,14 @@ qemuBuildShmemCommandLine(virLogManagerPtr logManager, return -1; } - if (!(devstr = qemuBuildShmemDevLegacyStr(def, shmem, qemuCaps))) + if (legacy) + devstr = qemuBuildShmemDevLegacyStr(def, shmem, qemuCaps); + else + devstr = qemuBuildShmemDevStr(def, shmem, qemuCaps); + + if (!devstr) return -1; + virCommandAddArgList(cmd, "-device", devstr, NULL); VIR_FREE(devstr); @@ -8618,6 +8719,12 @@ qemuBuildShmemCommandLine(virLogManagerPtr logManager, virCommandAddArgList(cmd, "-chardev", devstr, NULL); VIR_FREE(devstr); + } else if (!legacy) { + if (!(devstr = qemuBuildShmemBackendMemStr(shmem))) + return -1; + + virCommandAddArgList(cmd, "-object", devstr, NULL); + VIR_FREE(devstr); } return 0; 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/qemuxml2argvdata/qemuxml2argv-shmem-plain-doorbell.args b/tests/qemuxml2argvdata/qemuxml2argv-shmem-plain-doorbell.args new file mode 100644 index 000000000000..cb57c41ede76 --- /dev/null +++ b/tests/qemuxml2argvdata/qemuxml2argv-shmem-plain-doorbell.args @@ -0,0 +1,46 @@ +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 \ +-device ivshmem-plain,id=shmem0,memdev=shmmem-shmem0,master=on,bus=pci.0,\ +addr=0x3 \ +-object memory-backend-file,id=shmmem-shmem0,size=4194304,\ +mem-path=/dev/shm/shmem0 \ +-device ivshmem-plain,id=shmem1,memdev=shmmem-shmem1,master=on,bus=pci.0,\ +addr=0x5 \ +-object memory-backend-file,id=shmmem-shmem1,size=134217728,\ +mem-path=/dev/shm/shmem1 \ +-device ivshmem-plain,id=shmem2,memdev=shmmem-shmem2,master=on,bus=pci.0,\ +addr=0x4 \ +-object memory-backend-file,id=shmmem-shmem2,size=268435456,\ +mem-path=/dev/shm/shmem2 \ +-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/qemuxml2argvdata/qemuxml2argv-shmem-plain-doorbell.xml b/tests/qemuxml2argvdata/qemuxml2argv-shmem-plain-doorbell.xml new file mode 120000 index 000000000000..8f2f0f71776a --- /dev/null +++ b/tests/qemuxml2argvdata/qemuxml2argv-shmem-plain-doorbell.xml @@ -0,0 +1 @@ +qemuxml2argv-shmem.xml \ No newline at end of file diff --git a/tests/qemuxml2argvtest.c b/tests/qemuxml2argvtest.c index e8540779a4b5..484c36ecc6c7 100644 --- a/tests/qemuxml2argvtest.c +++ b/tests/qemuxml2argvtest.c @@ -1992,6 +1992,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.0
On Wed, Sep 21, 2016 at 03:30:55PM +0200, Martin Kletzander wrote:
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> --- docs/formatdomain.html.in | 5 +- src/qemu/qemu_command.c | 109 ++++++++++++++++++++- src/qemu/qemu_command.h | 10 ++ .../qemuxml2argv-shmem-plain-doorbell.args | 46 +++++++++ .../qemuxml2argv-shmem-plain-doorbell.xml | 1 + tests/qemuxml2argvtest.c | 3 + 6 files changed, 172 insertions(+), 2 deletions(-) create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-shmem-plain-doorbell.args create mode 120000 tests/qemuxml2argvdata/qemuxml2argv-shmem-plain-doorbell.xml
diff --git a/docs/formatdomain.html.in b/docs/formatdomain.html.in index b9163584d9f5..c614caf5f47f 100644 --- a/docs/formatdomain.html.in +++ b/docs/formatdomain.html.in @@ -6740,7 +6740,10 @@ qemu-kvm -net nic,model=? /dev/null
<p> A shared memory device allows to share a memory region between - different virtual machines and the host. + different virtual machines and the host. Note that memory in + this region will be migrated, if that's not desired, the device + needs to be unplugged before migration and plugged back again + after that. <span class="since">Since 1.2.10, QEMU and KVM only</span> </p>
diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c index 2130a7e2e8cf..3f7dfc4a46b9 100644 --- a/src/qemu/qemu_command.c +++ b/src/qemu/qemu_command.c @@ -8550,6 +8550,44 @@ qemuBuildShmemDevLegacyStr(virDomainDefPtr def, return NULL; }
+char * +qemuBuildShmemDevStr(virDomainDefPtr def, + virDomainShmemDefPtr shmem, + virQEMUCapsPtr qemuCaps) +{ + virBuffer buf = VIR_BUFFER_INITIALIZER; + + if (shmem->server.enabled) { + virBufferAddLit(&buf, "ivshmem-doorbell"); + virBufferAsprintf(&buf, ",id=%s,chardev=char%s", + shmem->info.alias, 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)); + } else { + virBufferAddLit(&buf, "ivshmem-plain"); + virBufferAsprintf(&buf, ",id=%s,memdev=shmmem-%s", + shmem->info.alias, shmem->info.alias); + + /* For now we default to master=on, users are adviced to + * unplug the ivshmem if they don't want to migrate the data + * in the shmem (see docs). */ + virBufferAddLit(&buf, ",master=on"); + } + + if (qemuBuildDeviceAddressStr(&buf, def, &shmem->info, qemuCaps) < 0) { + virBufferFreeAndReset(&buf); + return NULL; + } + + if (virBufferCheckError(&buf) < 0) + return NULL; + + return virBufferContentAndReset(&buf); +}
@@ -8579,6 +8662,18 @@ qemuBuildShmemCommandLine(virLogManagerPtr logManager, virQEMUCapsPtr qemuCaps) { char *devstr = NULL; + bool legacy = false; + + if (!qemuDomainSupportsNonLegacyShmem(qemuCaps, shmem)) { + if (!virQEMUCapsGet(qemuCaps, QEMU_CAPS_DEVICE_IVSHMEM)) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", + _("shmem device is not supported with this " + "QEMU binary")); + return -1; + } + + legacy = true; + }
if (shmem->size) { /* @@ -8606,8 +8701,14 @@ qemuBuildShmemCommandLine(virLogManagerPtr logManager, return -1; }
- if (!(devstr = qemuBuildShmemDevLegacyStr(def, shmem, qemuCaps))) + if (legacy) + devstr = qemuBuildShmemDevLegacyStr(def, shmem, qemuCaps); + else + devstr = qemuBuildShmemDevStr(def, shmem, qemuCaps);
I'm not a fan of the idea of silently picking a different device for the guest behind the applications back. By not exposing the different device types with a "model" attribute, we miss a way to report to the application which models are supported by the QEMU they're using - eg via domain capabilities. This in turn means the application doesn't know whether they're getting the new or old version, and so don't know if they're going to have working migration or not. If we expanded the XML to include model, then application can explicitly request the new model (which supports migration) and know that they'll get a startup failure if not supported, as opposed to silently falling back to the non-migratable version. Also, it makes life hard for us if the ivshmem-plain device wants to support use of the 'server' attribute in the future, as we will then not know which to create. We've often been burnt in the past by trying todo magic like this, instead of explicitly representing stuff in the XML, so I think we should be being explicit about ivshmem models here. Of course, if we do add <model> support, we have to allow for it to be missing for sake of upgrades. So there's a question of which model we should select as the default, if not seen in the XML. Regards, Daniel -- |: http://berrange.com -o- http://www.flickr.com/photos/dberrange/ :| |: http://libvirt.org -o- http://virt-manager.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: http://entangle-photo.org -o- http://live.gnome.org/gtk-vnc :|
On Wed, Sep 21, 2016 at 04:01:23PM +0100, Daniel P. Berrange wrote:
I'm not a fan of the idea of silently picking a different device for the guest behind the applications back. By not exposing the different device types with a "model" attribute, we miss a way to report to the application which models are supported by the QEMU they're using - eg via domain capabilities.
This in turn means the application doesn't know whether they're getting the new or old version, and so don't know if they're going to have working migration or not.
If we expanded the XML to include model, then application can explicitly request the new model (which supports migration) and know that they'll get a startup failure if not supported, as opposed to silently falling back to the non-migratable version.
Also, it makes life hard for us if the ivshmem-plain device wants to support use of the 'server' attribute in the future, as we will then not know which to create.
We've often been burnt in the past by trying todo magic like this, instead of explicitly representing stuff in the XML, so I think we should be being explicit about ivshmem models here.
Of course, if we do add <model> support, we have to allow for it to be missing for sake of upgrades. So there's a question of which model we should select as the default, if not seen in the XML.
If selecting the newest one whenever the element is missing is fine, then I'm OK with that. But that would change the device when upgrading libvirt (without user intervention), which you didn't like IIUC.
Regards, Daniel -- |: http://berrange.com -o- http://www.flickr.com/photos/dberrange/ :| |: http://libvirt.org -o- http://virt-manager.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: http://entangle-photo.org -o- http://live.gnome.org/gtk-vnc :|
On Wed, Sep 21, 2016 at 05:10:09PM +0200, Martin Kletzander wrote:
On Wed, Sep 21, 2016 at 04:01:23PM +0100, Daniel P. Berrange wrote:
I'm not a fan of the idea of silently picking a different device for the guest behind the applications back. By not exposing the different device types with a "model" attribute, we miss a way to report to the application which models are supported by the QEMU they're using - eg via domain capabilities.
This in turn means the application doesn't know whether they're getting the new or old version, and so don't know if they're going to have working migration or not.
If we expanded the XML to include model, then application can explicitly request the new model (which supports migration) and know that they'll get a startup failure if not supported, as opposed to silently falling back to the non-migratable version.
Also, it makes life hard for us if the ivshmem-plain device wants to support use of the 'server' attribute in the future, as we will then not know which to create.
We've often been burnt in the past by trying todo magic like this, instead of explicitly representing stuff in the XML, so I think we should be being explicit about ivshmem models here.
Of course, if we do add <model> support, we have to allow for it to be missing for sake of upgrades. So there's a question of which model we should select as the default, if not seen in the XML.
If selecting the newest one whenever the element is missing is fine, then I'm OK with that. But that would change the device when upgrading libvirt (without user intervention), which you didn't like IIUC.
Yes, I don't think we can do that - at least note exactly in the way you do it in this patch. eg Looking at the ivshmem code in QEMU there is this comment about guest interupt setup: * Do nothing unless the device actually uses INTx. Here's how * the device variants signal interrupts, what they put in PCI * config space: * Device variant Interrupt Interrupt Pin MSI-X cap. * ivshmem-plain none 0 no * ivshmem-doorbell MSI-X 1 yes(1) * ivshmem,msi=off INTx 1 no * ivshmem,msi=on MSI-X 1(2) yes(1) * (1) if guest enabled MSI-X * (2) the device lies Note that neither ivshmem-plain or ivshmem-doorbell support use of INTx for interupts. I'm also concerned about the footnote (2) there, as that seems to imply that ivshmem,msi=on, is not in fact the same as ivshmem-doorbell, because ivshmem lies about the interrupt pin (whatever that means). I'm inclined so that that we should do if (ivshmem exists) { use ivshmem } else { if (server) { if(msi) { use ivshmem-doorbell } else { error config unsupported } } else { use ivshmem-plain } } That way if a distro compiles-out 'ivshmem' we'll use one of the new devices if they're available, otherwise we'll stick with the conversative behaviour of using the legacy device for guaranteed bug compatibility. Regards, Daniel -- |: http://berrange.com -o- http://www.flickr.com/photos/dberrange/ :| |: http://libvirt.org -o- http://virt-manager.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: http://entangle-photo.org -o- http://live.gnome.org/gtk-vnc :|
On Wed, Sep 21, 2016 at 04:26:31PM +0100, Daniel P. Berrange wrote:
On Wed, Sep 21, 2016 at 05:10:09PM +0200, Martin Kletzander wrote:
On Wed, Sep 21, 2016 at 04:01:23PM +0100, Daniel P. Berrange wrote:
I'm not a fan of the idea of silently picking a different device for the guest behind the applications back. By not exposing the different device types with a "model" attribute, we miss a way to report to the application which models are supported by the QEMU they're using - eg via domain capabilities.
This in turn means the application doesn't know whether they're getting the new or old version, and so don't know if they're going to have working migration or not.
If we expanded the XML to include model, then application can explicitly request the new model (which supports migration) and know that they'll get a startup failure if not supported, as opposed to silently falling back to the non-migratable version.
Also, it makes life hard for us if the ivshmem-plain device wants to support use of the 'server' attribute in the future, as we will then not know which to create.
We've often been burnt in the past by trying todo magic like this, instead of explicitly representing stuff in the XML, so I think we should be being explicit about ivshmem models here.
Of course, if we do add <model> support, we have to allow for it to be missing for sake of upgrades. So there's a question of which model we should select as the default, if not seen in the XML.
If selecting the newest one whenever the element is missing is fine, then I'm OK with that. But that would change the device when upgrading libvirt (without user intervention), which you didn't like IIUC.
Yes, I don't think we can do that - at least note exactly in the way you do it in this patch. eg Looking at the ivshmem code in QEMU there is this comment about guest interupt setup:
* Do nothing unless the device actually uses INTx. Here's how * the device variants signal interrupts, what they put in PCI * config space: * Device variant Interrupt Interrupt Pin MSI-X cap. * ivshmem-plain none 0 no * ivshmem-doorbell MSI-X 1 yes(1) * ivshmem,msi=off INTx 1 no * ivshmem,msi=on MSI-X 1(2) yes(1) * (1) if guest enabled MSI-X * (2) the device lies
Note that neither ivshmem-plain or ivshmem-doorbell support use of INTx for interupts. I'm also concerned about the footnote (2) there, as that seems to imply that ivshmem,msi=on, is not in fact the same as ivshmem-doorbell, because ivshmem lies about the interrupt pin (whatever that means).
I'm inclined so that that we should do
if (ivshmem exists) { use ivshmem } else { if (server) { if(msi) { use ivshmem-doorbell } else { error config unsupported } } else { use ivshmem-plain } }
That way if a distro compiles-out 'ivshmem' we'll use one of the new devices if they're available, otherwise we'll stick with the conversative behaviour of using the legacy device for guaranteed bug compatibility.
OK, we can do that. But before I go and do this variant, I would like to clarify two more things (so that I can hope that's the last variant I have to post) =) Should we support setting the role to 'peer'/'master' (with ivshmem that maps to role=peer/master and with ivshmem-plain that maps to master=on/off)? Basically master means that the domain can migrate (with the data being copied) and peer (or master=off) has migration disabled in qemu, so we would disable that as well. That's why hotplug is being implemented, basically. Currently we don't use that parameter, which means role=auto. That is special value that ends up being 'master' for non-server, for server it tries to pick correctly. Shouldn't be used, but rather explicitly stated (or just peer for everyone and copy the data yourself). New ivshmem defaults to master=off.
Regards, Daniel -- |: http://berrange.com -o- http://www.flickr.com/photos/dberrange/ :| |: http://libvirt.org -o- http://virt-manager.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: http://entangle-photo.org -o- http://live.gnome.org/gtk-vnc :|
On Thu, Sep 22, 2016 at 01:09:20PM +0200, Martin Kletzander wrote:
On Wed, Sep 21, 2016 at 04:26:31PM +0100, Daniel P. Berrange wrote:
On Wed, Sep 21, 2016 at 05:10:09PM +0200, Martin Kletzander wrote:
On Wed, Sep 21, 2016 at 04:01:23PM +0100, Daniel P. Berrange wrote:
I'm not a fan of the idea of silently picking a different device for the guest behind the applications back. By not exposing the different device types with a "model" attribute, we miss a way to report to the application which models are supported by the QEMU they're using - eg via domain capabilities.
This in turn means the application doesn't know whether they're getting the new or old version, and so don't know if they're going to have working migration or not.
If we expanded the XML to include model, then application can explicitly request the new model (which supports migration) and know that they'll get a startup failure if not supported, as opposed to silently falling back to the non-migratable version.
Also, it makes life hard for us if the ivshmem-plain device wants to support use of the 'server' attribute in the future, as we will then not know which to create.
We've often been burnt in the past by trying todo magic like this, instead of explicitly representing stuff in the XML, so I think we should be being explicit about ivshmem models here.
Of course, if we do add <model> support, we have to allow for it to be missing for sake of upgrades. So there's a question of which model we should select as the default, if not seen in the XML.
If selecting the newest one whenever the element is missing is fine, then I'm OK with that. But that would change the device when upgrading libvirt (without user intervention), which you didn't like IIUC.
Yes, I don't think we can do that - at least note exactly in the way you do it in this patch. eg Looking at the ivshmem code in QEMU there is this comment about guest interupt setup:
* Do nothing unless the device actually uses INTx. Here's how * the device variants signal interrupts, what they put in PCI * config space: * Device variant Interrupt Interrupt Pin MSI-X cap. * ivshmem-plain none 0 no * ivshmem-doorbell MSI-X 1 yes(1) * ivshmem,msi=off INTx 1 no * ivshmem,msi=on MSI-X 1(2) yes(1) * (1) if guest enabled MSI-X * (2) the device lies
Note that neither ivshmem-plain or ivshmem-doorbell support use of INTx for interupts. I'm also concerned about the footnote (2) there, as that seems to imply that ivshmem,msi=on, is not in fact the same as ivshmem-doorbell, because ivshmem lies about the interrupt pin (whatever that means).
I'm inclined so that that we should do
if (ivshmem exists) { use ivshmem } else { if (server) { if(msi) { use ivshmem-doorbell } else { error config unsupported } } else { use ivshmem-plain } }
That way if a distro compiles-out 'ivshmem' we'll use one of the new devices if they're available, otherwise we'll stick with the conversative behaviour of using the legacy device for guaranteed bug compatibility.
OK, we can do that. But before I go and do this variant, I would like to clarify two more things (so that I can hope that's the last variant I have to post) =) Should we support setting the role to 'peer'/'master' (with ivshmem that maps to role=peer/master and with ivshmem-plain that maps to master=on/off)? Basically master means that the domain can migrate (with the data being copied) and peer (or master=off) has migration disabled in qemu, so we would disable that as well. That's why hotplug is being implemented, basically. Currently we don't use that parameter, which means role=auto. That is special value that ends up being 'master' for non-server, for server it tries to pick correctly. Shouldn't be used, but rather explicitly stated (or just peer for everyone and copy the data yourself). New ivshmem defaults to master=off.
Yep, given that the choice of master/peer impacts whether you can migrate or not, I think it is important to give applications the ability to set that, to override the potentially incorrect defaults. Regards, Daniel -- |: http://berrange.com -o- http://www.flickr.com/photos/dberrange/ :| |: http://libvirt.org -o- http://virt-manager.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: http://entangle-photo.org -o- http://live.gnome.org/gtk-vnc :|
This is needed in order to migrate with ivshmem role='peer' as that is not allowed to migrate. Signed-off-by: Martin Kletzander <mkletzan@redhat.com> --- src/qemu/qemu_driver.c | 39 +++- src/qemu/qemu_hotplug.c | 231 ++++++++++++++++++++- src/qemu/qemu_hotplug.h | 6 + tests/qemuhotplugtest.c | 21 ++ .../qemuhotplug-ivshmem-doorbell-detach.xml | 6 + .../qemuhotplug-ivshmem-doorbell.xml | 3 + .../qemuhotplug-ivshmem-plain-detach.xml | 5 + .../qemuhotplug-ivshmem-plain.xml | 1 + ...muhotplug-base-live+ivshmem-doorbell-detach.xml | 1 + .../qemuhotplug-base-live+ivshmem-doorbell.xml | 63 ++++++ .../qemuhotplug-base-live+ivshmem-plain-detach.xml | 1 + .../qemuhotplug-base-live+ivshmem-plain.xml | 57 +++++ 12 files changed, 429 insertions(+), 5 deletions(-) create mode 100644 tests/qemuhotplugtestdevices/qemuhotplug-ivshmem-doorbell-detach.xml create mode 100644 tests/qemuhotplugtestdevices/qemuhotplug-ivshmem-doorbell.xml create mode 100644 tests/qemuhotplugtestdevices/qemuhotplug-ivshmem-plain-detach.xml create mode 100644 tests/qemuhotplugtestdevices/qemuhotplug-ivshmem-plain.xml create mode 120000 tests/qemuhotplugtestdomains/qemuhotplug-base-live+ivshmem-doorbell-detach.xml create mode 100644 tests/qemuhotplugtestdomains/qemuhotplug-base-live+ivshmem-doorbell.xml create mode 120000 tests/qemuhotplugtestdomains/qemuhotplug-base-live+ivshmem-plain-detach.xml create mode 100644 tests/qemuhotplugtestdomains/qemuhotplug-base-live+ivshmem-plain.xml diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c index e29180da4e75..0625df273f2f 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -7522,6 +7522,15 @@ qemuDomainAttachDeviceLive(virDomainObjPtr vm, dev->data.memory = NULL; break; + case VIR_DOMAIN_DEVICE_SHMEM: + ret = qemuDomainAttachShmemDevice(driver, vm, + dev->data.shmem); + if (!ret) { + alias = dev->data.shmem->info.alias; + dev->data.shmem = NULL; + } + break; + case VIR_DOMAIN_DEVICE_NONE: case VIR_DOMAIN_DEVICE_FS: case VIR_DOMAIN_DEVICE_INPUT: @@ -7533,7 +7542,6 @@ qemuDomainAttachDeviceLive(virDomainObjPtr vm, case VIR_DOMAIN_DEVICE_SMARTCARD: case VIR_DOMAIN_DEVICE_MEMBALLOON: case VIR_DOMAIN_DEVICE_NVRAM: - case VIR_DOMAIN_DEVICE_SHMEM: case VIR_DOMAIN_DEVICE_TPM: case VIR_DOMAIN_DEVICE_PANIC: case VIR_DOMAIN_DEVICE_IOMMU: @@ -7611,6 +7619,9 @@ qemuDomainDetachDeviceLive(virDomainObjPtr vm, case VIR_DOMAIN_DEVICE_MEMORY: ret = qemuDomainDetachMemoryDevice(driver, vm, dev->data.memory); break; + case VIR_DOMAIN_DEVICE_SHMEM: + ret = qemuDomainDetachShmemDevice(driver, vm, dev); + break; case VIR_DOMAIN_DEVICE_FS: case VIR_DOMAIN_DEVICE_INPUT: @@ -7622,7 +7633,6 @@ qemuDomainDetachDeviceLive(virDomainObjPtr vm, case VIR_DOMAIN_DEVICE_SMARTCARD: case VIR_DOMAIN_DEVICE_MEMBALLOON: case VIR_DOMAIN_DEVICE_NVRAM: - case VIR_DOMAIN_DEVICE_SHMEM: case VIR_DOMAIN_DEVICE_REDIRDEV: case VIR_DOMAIN_DEVICE_NONE: case VIR_DOMAIN_DEVICE_TPM: @@ -7769,6 +7779,7 @@ qemuDomainAttachDeviceConfig(virDomainDefPtr vmdef, virDomainControllerDefPtr controller; virDomainFSDefPtr fs; virDomainRedirdevDefPtr redirdev; + virDomainShmemDefPtr shmem; switch ((virDomainDeviceType) dev->type) { case VIR_DOMAIN_DEVICE_DISK: @@ -7893,6 +7904,18 @@ qemuDomainAttachDeviceConfig(virDomainDefPtr vmdef, dev->data.redirdev = NULL; break; + case VIR_DOMAIN_DEVICE_SHMEM: + shmem = dev->data.shmem; + if (virDomainShmemDefFind(vmdef, shmem) >= 0) { + virReportError(VIR_ERR_OPERATION_INVALID, "%s", + _("device is already in the domain configuration")); + return -1; + } + if (virDomainShmemDefInsert(vmdef, shmem) < 0) + return -1; + dev->data.shmem = NULL; + break; + case VIR_DOMAIN_DEVICE_INPUT: case VIR_DOMAIN_DEVICE_SOUND: case VIR_DOMAIN_DEVICE_VIDEO: @@ -7902,7 +7925,6 @@ qemuDomainAttachDeviceConfig(virDomainDefPtr vmdef, case VIR_DOMAIN_DEVICE_SMARTCARD: case VIR_DOMAIN_DEVICE_MEMBALLOON: case VIR_DOMAIN_DEVICE_NVRAM: - case VIR_DOMAIN_DEVICE_SHMEM: case VIR_DOMAIN_DEVICE_NONE: case VIR_DOMAIN_DEVICE_TPM: case VIR_DOMAIN_DEVICE_PANIC: @@ -8049,6 +8071,16 @@ qemuDomainDetachDeviceConfig(virDomainDefPtr vmdef, virDomainRedirdevDefFree(virDomainRedirdevDefRemove(vmdef, idx)); break; + case VIR_DOMAIN_DEVICE_SHMEM: + if ((idx = virDomainShmemDefFind(vmdef, dev->data.shmem)) < 0) { + virReportError(VIR_ERR_OPERATION_FAILED, "%s", + _("matching shmem device was not found")); + return -1; + } + + virDomainShmemDefFree(virDomainShmemDefRemove(vmdef, idx)); + break; + case VIR_DOMAIN_DEVICE_INPUT: case VIR_DOMAIN_DEVICE_SOUND: @@ -8059,7 +8091,6 @@ qemuDomainDetachDeviceConfig(virDomainDefPtr vmdef, case VIR_DOMAIN_DEVICE_SMARTCARD: case VIR_DOMAIN_DEVICE_MEMBALLOON: case VIR_DOMAIN_DEVICE_NVRAM: - case VIR_DOMAIN_DEVICE_SHMEM: case VIR_DOMAIN_DEVICE_NONE: case VIR_DOMAIN_DEVICE_TPM: case VIR_DOMAIN_DEVICE_PANIC: diff --git a/src/qemu/qemu_hotplug.c b/src/qemu/qemu_hotplug.c index 72dd93bbe467..f24c75369a31 100644 --- a/src/qemu/qemu_hotplug.c +++ b/src/qemu/qemu_hotplug.c @@ -2242,6 +2242,123 @@ qemuDomainAttachHostDevice(virConnectPtr conn, return -1; } + +int +qemuDomainAttachShmemDevice(virQEMUDriverPtr driver, + virDomainObjPtr vm, + virDomainShmemDefPtr shmem) +{ + int ret = -1; + char *shmstr = NULL; + char *charAlias = NULL; + char *memAlias = NULL; + bool release_backing = false; + bool release_address = true; + virErrorPtr orig_err = NULL; + virJSONValuePtr props = NULL; + qemuDomainObjPrivatePtr priv = vm->privateData; + + if (!qemuDomainSupportsNonLegacyShmem(priv->qemuCaps, shmem)) { + virReportError(VIR_ERR_OPERATION_UNSUPPORTED, "%s", + _("live attach of shmem device is not supported")); + return -1; + } + + if (qemuAssignDeviceShmemAlias(vm->def, shmem, -1) < 0) + return -1; + + if (qemuDomainPrepareShmemChardev(shmem) < 0) + return -1; + + if (VIR_REALLOC_N(vm->def->shmems, vm->def->nshmems + 1) < 0) + return -1; + + if ((shmem->info.type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_NONE || + shmem->info.type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI) && + (virDomainPCIAddressEnsureAddr(priv->pciaddrs, &shmem->info) < 0)) + return -1; + + if (!(shmstr = qemuBuildShmemDevStr(vm->def, shmem, priv->qemuCaps))) + goto cleanup; + + if (shmem->server.enabled) { + if (virAsprintf(&charAlias, "char%s", shmem->info.alias) < 0) + goto cleanup; + } else { + if (!(props = qemuBuildShmemBackendMemProps(shmem))) + goto cleanup; + + if (virAsprintf(&memAlias, "shmmem-%s", shmem->info.alias) < 0) + goto cleanup; + } + + qemuDomainObjEnterMonitor(driver, vm); + + if (shmem->server.enabled) { + if (qemuMonitorAttachCharDev(priv->mon, charAlias, + &shmem->server.chr) < 0) + goto exit_monitor; + } else { + if (qemuMonitorAddObject(priv->mon, "memory-backend-file", + memAlias, props) < 0) { + props = NULL; + goto exit_monitor; + } + props = NULL; + } + + release_backing = true; + + if (qemuMonitorAddDevice(priv->mon, shmstr) < 0) + goto exit_monitor; + + if (qemuDomainObjExitMonitor(driver, vm) < 0) { + release_address = false; + goto cleanup; + } + + /* Doing a copy here just so the pointer doesn't get nullified + * because we need it in the audit function */ + VIR_APPEND_ELEMENT_COPY_INPLACE(vm->def->shmems, vm->def->nshmems, shmem); + + ret = 0; + release_address = false; + + audit: + virDomainAuditShmem(vm, shmem, "attach", ret == 0); + + cleanup: + if (release_address) + qemuDomainReleaseDeviceAddress(vm, &shmem->info, NULL); + + virJSONValueFree(props); + VIR_FREE(memAlias); + VIR_FREE(charAlias); + VIR_FREE(shmstr); + + return ret; + + exit_monitor: + orig_err = virSaveLastError(); + if (release_backing) { + if (shmem->server.enabled) + ignore_value(qemuMonitorDetachCharDev(priv->mon, charAlias)); + else + ignore_value(qemuMonitorDelObject(priv->mon, memAlias)); + } + + if (orig_err) { + virSetError(orig_err); + virFreeError(orig_err); + } + + if (qemuDomainObjExitMonitor(driver, vm) < 0) + release_address = false; + + goto audit; +} + + static int qemuDomainChangeNetBridge(virDomainObjPtr vm, virDomainNetDefPtr olddev, @@ -3486,6 +3603,61 @@ qemuDomainRemoveRNGDevice(virQEMUDriverPtr driver, } +static int +qemuDomainRemoveShmemDevice(virQEMUDriverPtr driver, + virDomainObjPtr vm, + virDomainShmemDefPtr shmem) +{ + int rc; + int ret = -1; + ssize_t idx = -1; + char *charAlias = NULL; + char *memAlias = NULL; + qemuDomainObjPrivatePtr priv = vm->privateData; + virObjectEventPtr event = NULL; + + VIR_DEBUG("Removing shmem device %s from domain %p %s", + shmem->info.alias, vm, vm->def->name); + + if (shmem->server.enabled) { + if (virAsprintf(&charAlias, "char%s", shmem->info.alias) < 0) + return -1; + } else { + if (virAsprintf(&memAlias, "shmmem-%s", shmem->info.alias) < 0) + return -1; + } + + qemuDomainObjEnterMonitor(driver, vm); + + if (shmem->server.enabled) + rc = qemuMonitorDetachCharDev(priv->mon, charAlias); + else + rc = qemuMonitorDelObject(priv->mon, memAlias); + + if (qemuDomainObjExitMonitor(driver, vm) < 0) + goto cleanup; + + virDomainAuditShmem(vm, shmem, "detach", rc == 0); + + if (rc < 0) + goto cleanup; + + event = virDomainEventDeviceRemovedNewFromObj(vm, shmem->info.alias); + qemuDomainEventQueue(driver, event); + + if ((idx = virDomainShmemDefFind(vm->def, shmem)) >= 0) + virDomainShmemDefRemove(vm->def, idx); + qemuDomainReleaseDeviceAddress(vm, &shmem->info, NULL); + + ret = 0; + cleanup: + VIR_FREE(charAlias); + VIR_FREE(memAlias); + + return ret; +} + + int qemuDomainRemoveDevice(virQEMUDriverPtr driver, virDomainObjPtr vm, @@ -3517,6 +3689,10 @@ qemuDomainRemoveDevice(virQEMUDriverPtr driver, ret = qemuDomainRemoveMemoryDevice(driver, vm, dev->data.memory); break; + case VIR_DOMAIN_DEVICE_SHMEM: + ret = qemuDomainRemoveShmemDevice(driver, vm, dev->data.shmem); + break; + case VIR_DOMAIN_DEVICE_NONE: case VIR_DOMAIN_DEVICE_LEASE: case VIR_DOMAIN_DEVICE_FS: @@ -3530,7 +3706,6 @@ qemuDomainRemoveDevice(virQEMUDriverPtr driver, case VIR_DOMAIN_DEVICE_SMARTCARD: case VIR_DOMAIN_DEVICE_MEMBALLOON: case VIR_DOMAIN_DEVICE_NVRAM: - case VIR_DOMAIN_DEVICE_SHMEM: case VIR_DOMAIN_DEVICE_TPM: case VIR_DOMAIN_DEVICE_PANIC: case VIR_DOMAIN_DEVICE_IOMMU: @@ -4105,6 +4280,60 @@ int qemuDomainDetachHostDevice(virQEMUDriverPtr driver, return qemuDomainDetachThisHostDevice(driver, vm, detach); } + +int +qemuDomainDetachShmemDevice(virQEMUDriverPtr driver, + virDomainObjPtr vm, + virDomainDeviceDefPtr dev) +{ + int ret = -1; + ssize_t idx = -1; + virErrorPtr orig_err = NULL; + virDomainShmemDefPtr shmem = NULL; + qemuDomainObjPrivatePtr priv = vm->privateData; + + if ((idx = virDomainShmemDefFind(vm->def, dev->data.shmem) < 0)) { + virReportError(VIR_ERR_OPERATION_INVALID, "%s", + _("device not present in domain configuration")); + return -1; + } + + shmem = vm->def->shmems[idx]; + + if (!qemuDomainSupportsNonLegacyShmem(priv->qemuCaps, shmem)) { + virReportError(VIR_ERR_OPERATION_UNSUPPORTED, "%s", + _("live detach of shmem device is not supported")); + return -1; + } + + qemuDomainMarkDeviceForRemoval(vm, &shmem->info); + qemuDomainObjEnterMonitor(driver, vm); + + ret = qemuMonitorDelDevice(priv->mon, shmem->info.alias); + + if (ret < 0) + orig_err = virSaveLastError(); + + if (qemuDomainObjExitMonitor(driver, vm) < 0) + ret = -1; + + if (ret == 0) { + if ((ret = qemuDomainWaitForDeviceRemoval(vm)) == 1) { + qemuDomainReleaseDeviceAddress(vm, &shmem->info, NULL); + ret = qemuDomainRemoveDevice(driver, vm, dev); + } + } + qemuDomainResetDeviceRemoval(vm); + + if (orig_err) { + virSetError(orig_err); + virFreeError(orig_err); + } + + return ret; +} + + int qemuDomainDetachNetDevice(virQEMUDriverPtr driver, virDomainObjPtr vm, diff --git a/src/qemu/qemu_hotplug.h b/src/qemu/qemu_hotplug.h index b048cf4688a4..12994e7cd468 100644 --- a/src/qemu/qemu_hotplug.h +++ b/src/qemu/qemu_hotplug.h @@ -50,6 +50,9 @@ int qemuDomainAttachHostDevice(virConnectPtr conn, virQEMUDriverPtr driver, virDomainObjPtr vm, virDomainHostdevDefPtr hostdev); +int qemuDomainAttachShmemDevice(virQEMUDriverPtr driver, + virDomainObjPtr vm, + virDomainShmemDefPtr shmem); int qemuDomainFindGraphicsIndex(virDomainDefPtr def, virDomainGraphicsDefPtr dev); int qemuDomainAttachMemory(virQEMUDriverPtr driver, @@ -86,6 +89,9 @@ int qemuDomainDetachNetDevice(virQEMUDriverPtr driver, int qemuDomainDetachHostDevice(virQEMUDriverPtr driver, virDomainObjPtr vm, virDomainDeviceDefPtr dev); +int qemuDomainDetachShmemDevice(virQEMUDriverPtr driver, + virDomainObjPtr vm, + virDomainDeviceDefPtr dev); int qemuDomainAttachLease(virQEMUDriverPtr driver, virDomainObjPtr vm, virDomainLeaseDefPtr lease); diff --git a/tests/qemuhotplugtest.c b/tests/qemuhotplugtest.c index 6a9ed992f31d..dda3917a5034 100644 --- a/tests/qemuhotplugtest.c +++ b/tests/qemuhotplugtest.c @@ -74,6 +74,8 @@ qemuHotplugCreateObjects(virDomainXMLOptionPtr xmlopt, virQEMUCapsSet(priv->qemuCaps, QEMU_CAPS_VIRTIO_SCSI); virQEMUCapsSet(priv->qemuCaps, QEMU_CAPS_DEVICE_USB_STORAGE); virQEMUCapsSet(priv->qemuCaps, QEMU_CAPS_VIRTIO_CCW); + virQEMUCapsSet(priv->qemuCaps, QEMU_CAPS_DEVICE_IVSHMEM_PLAIN); + virQEMUCapsSet(priv->qemuCaps, QEMU_CAPS_DEVICE_IVSHMEM_DOORBELL); if (event) virQEMUCapsSet(priv->qemuCaps, QEMU_CAPS_DEVICE_DEL_EVENT); @@ -119,6 +121,9 @@ testQemuHotplugAttach(virDomainObjPtr vm, case VIR_DOMAIN_DEVICE_CHR: ret = qemuDomainAttachChrDevice(&driver, vm, dev->data.chr); break; + case VIR_DOMAIN_DEVICE_SHMEM: + ret = qemuDomainAttachShmemDevice(&driver, vm, dev->data.shmem); + break; default: VIR_TEST_VERBOSE("device type '%s' cannot be attached\n", virDomainDeviceTypeToString(dev->type)); @@ -141,6 +146,9 @@ testQemuHotplugDetach(virDomainObjPtr vm, case VIR_DOMAIN_DEVICE_CHR: ret = qemuDomainDetachChrDevice(&driver, vm, dev->data.chr); break; + case VIR_DOMAIN_DEVICE_SHMEM: + ret = qemuDomainDetachShmemDevice(&driver, vm, dev); + break; default: VIR_TEST_VERBOSE("device type '%s' cannot be detached\n", virDomainDeviceTypeToString(dev->type)); @@ -560,6 +568,19 @@ mymain(void) "human-monitor-command", HMP("OK\\r\\n"), "device_add", QMP_OK); + DO_TEST_ATTACH("base-live", "ivshmem-plain", false, true, + "object-add", QMP_OK, + "device_add", QMP_OK); + DO_TEST_ATTACH("base-live", "ivshmem-doorbell", false, true, + "chardev-add", QMP_OK, + "device_add", QMP_OK); + DO_TEST_DETACH("base-live+ivshmem-plain", "ivshmem-doorbell-detach", false, true, + "device_del", QMP_OK, + "chardev-remove", QMP_OK); + DO_TEST_DETACH("base-live", "ivshmem-plain-detach", false, false, + "device_del", QMP_OK, + "object-del", QMP_OK); + qemuTestDriverFree(&driver); return (ret == 0) ? EXIT_SUCCESS : EXIT_FAILURE; } diff --git a/tests/qemuhotplugtestdevices/qemuhotplug-ivshmem-doorbell-detach.xml b/tests/qemuhotplugtestdevices/qemuhotplug-ivshmem-doorbell-detach.xml new file mode 100644 index 000000000000..82e98b06e851 --- /dev/null +++ b/tests/qemuhotplugtestdevices/qemuhotplug-ivshmem-doorbell-detach.xml @@ -0,0 +1,6 @@ +<shmem name='shmem1'> + <server path='/var/lib/libvirt/shmem-shmem1-sock'/> + <msi ioeventfd='on'/> + <alias name='shmem1'/> + <address type='pci' domain='0x0000' bus='0x00' slot='0x06' function='0x0'/> +</shmem> diff --git a/tests/qemuhotplugtestdevices/qemuhotplug-ivshmem-doorbell.xml b/tests/qemuhotplugtestdevices/qemuhotplug-ivshmem-doorbell.xml new file mode 100644 index 000000000000..bb1873126053 --- /dev/null +++ b/tests/qemuhotplugtestdevices/qemuhotplug-ivshmem-doorbell.xml @@ -0,0 +1,3 @@ +<shmem name='shmem1'> + <server/> +</shmem> diff --git a/tests/qemuhotplugtestdevices/qemuhotplug-ivshmem-plain-detach.xml b/tests/qemuhotplugtestdevices/qemuhotplug-ivshmem-plain-detach.xml new file mode 100644 index 000000000000..493e65beae88 --- /dev/null +++ b/tests/qemuhotplugtestdevices/qemuhotplug-ivshmem-plain-detach.xml @@ -0,0 +1,5 @@ +<shmem name='shmem0' role='peer'> + <size unit='M'>4</size> + <alias name='shmem0'/> + <address type='pci' domain='0x0000' bus='0x00' slot='0x05' function='0x0'/> +</shmem> diff --git a/tests/qemuhotplugtestdevices/qemuhotplug-ivshmem-plain.xml b/tests/qemuhotplugtestdevices/qemuhotplug-ivshmem-plain.xml new file mode 100644 index 000000000000..383ce6479f60 --- /dev/null +++ b/tests/qemuhotplugtestdevices/qemuhotplug-ivshmem-plain.xml @@ -0,0 +1 @@ +<shmem name='shmem0'/> diff --git a/tests/qemuhotplugtestdomains/qemuhotplug-base-live+ivshmem-doorbell-detach.xml b/tests/qemuhotplugtestdomains/qemuhotplug-base-live+ivshmem-doorbell-detach.xml new file mode 120000 index 000000000000..021e5471d197 --- /dev/null +++ b/tests/qemuhotplugtestdomains/qemuhotplug-base-live+ivshmem-doorbell-detach.xml @@ -0,0 +1 @@ +qemuhotplug-base-live+ivshmem-plain.xml \ No newline at end of file diff --git a/tests/qemuhotplugtestdomains/qemuhotplug-base-live+ivshmem-doorbell.xml b/tests/qemuhotplugtestdomains/qemuhotplug-base-live+ivshmem-doorbell.xml new file mode 100644 index 000000000000..aa0f4bd03618 --- /dev/null +++ b/tests/qemuhotplugtestdomains/qemuhotplug-base-live+ivshmem-doorbell.xml @@ -0,0 +1,63 @@ +<domain type='kvm' id='7'> + <name>hotplug</name> + <uuid>d091ea82-29e6-2e34-3005-f02617b36e87</uuid> + <memory unit='KiB'>4194304</memory> + <currentMemory unit='KiB'>4194304</currentMemory> + <vcpu placement='static'>4</vcpu> + <os> + <type arch='x86_64' machine='pc'>hvm</type> + <boot dev='hd'/> + </os> + <features> + <acpi/> + <apic/> + <pae/> + </features> + <clock offset='utc'/> + <on_poweroff>destroy</on_poweroff> + <on_reboot>restart</on_reboot> + <on_crash>restart</on_crash> + <devices> + <emulator>/usr/libexec/qemu-kvm</emulator> + <controller type='usb' index='0'> + <alias name='usb'/> + <address type='pci' domain='0x0000' bus='0x00' slot='0x01' function='0x2'/> + </controller> + <controller type='ide' index='0'> + <alias name='ide'/> + <address type='pci' domain='0x0000' bus='0x00' slot='0x01' function='0x1'/> + </controller> + <controller type='scsi' index='0' model='virtio-scsi'> + <alias name='scsi0'/> + <address type='pci' domain='0x0000' bus='0x00' slot='0x03' function='0x0'/> + </controller> + <controller type='pci' index='0' model='pci-root'> + <alias name='pci'/> + </controller> + <controller type='virtio-serial' index='0'> + <alias name='virtio-serial0'/> + <address type='pci' domain='0x0000' bus='0x00' slot='0x04' function='0x0'/> + </controller> + <input type='mouse' bus='ps2'> + <alias name='input0'/> + </input> + <input type='keyboard' bus='ps2'> + <alias name='input1'/> + </input> + <memballoon model='none'> + <alias name='balloon0'/> + </memballoon> + <shmem name='shmem0'> + <size unit='M'>4</size> + <alias name='shmem0'/> + <address type='pci' domain='0x0000' bus='0x00' slot='0x05' function='0x0'/> + </shmem> + <shmem name='shmem1'> + <server path='/var/lib/libvirt/shmem-shmem1-sock'/> + <msi ioeventfd='on'/> + <alias name='shmem1'/> + <address type='pci' domain='0x0000' bus='0x00' slot='0x06' function='0x0'/> + </shmem> + </devices> + <seclabel type='none' model='none'/> +</domain> diff --git a/tests/qemuhotplugtestdomains/qemuhotplug-base-live+ivshmem-plain-detach.xml b/tests/qemuhotplugtestdomains/qemuhotplug-base-live+ivshmem-plain-detach.xml new file mode 120000 index 000000000000..48c1b1755a4e --- /dev/null +++ b/tests/qemuhotplugtestdomains/qemuhotplug-base-live+ivshmem-plain-detach.xml @@ -0,0 +1 @@ +qemuhotplug-base-live.xml \ No newline at end of file diff --git a/tests/qemuhotplugtestdomains/qemuhotplug-base-live+ivshmem-plain.xml b/tests/qemuhotplugtestdomains/qemuhotplug-base-live+ivshmem-plain.xml new file mode 100644 index 000000000000..41330b6c3271 --- /dev/null +++ b/tests/qemuhotplugtestdomains/qemuhotplug-base-live+ivshmem-plain.xml @@ -0,0 +1,57 @@ +<domain type='kvm' id='7'> + <name>hotplug</name> + <uuid>d091ea82-29e6-2e34-3005-f02617b36e87</uuid> + <memory unit='KiB'>4194304</memory> + <currentMemory unit='KiB'>4194304</currentMemory> + <vcpu placement='static'>4</vcpu> + <os> + <type arch='x86_64' machine='pc'>hvm</type> + <boot dev='hd'/> + </os> + <features> + <acpi/> + <apic/> + <pae/> + </features> + <clock offset='utc'/> + <on_poweroff>destroy</on_poweroff> + <on_reboot>restart</on_reboot> + <on_crash>restart</on_crash> + <devices> + <emulator>/usr/libexec/qemu-kvm</emulator> + <controller type='usb' index='0'> + <alias name='usb'/> + <address type='pci' domain='0x0000' bus='0x00' slot='0x01' function='0x2'/> + </controller> + <controller type='ide' index='0'> + <alias name='ide'/> + <address type='pci' domain='0x0000' bus='0x00' slot='0x01' function='0x1'/> + </controller> + <controller type='scsi' index='0' model='virtio-scsi'> + <alias name='scsi0'/> + <address type='pci' domain='0x0000' bus='0x00' slot='0x03' function='0x0'/> + </controller> + <controller type='pci' index='0' model='pci-root'> + <alias name='pci'/> + </controller> + <controller type='virtio-serial' index='0'> + <alias name='virtio-serial0'/> + <address type='pci' domain='0x0000' bus='0x00' slot='0x04' function='0x0'/> + </controller> + <input type='mouse' bus='ps2'> + <alias name='input0'/> + </input> + <input type='keyboard' bus='ps2'> + <alias name='input1'/> + </input> + <memballoon model='none'> + <alias name='balloon0'/> + </memballoon> + <shmem name='shmem0'> + <size unit='M'>4</size> + <alias name='shmem0'/> + <address type='pci' domain='0x0000' bus='0x00' slot='0x05' function='0x0'/> + </shmem> + </devices> + <seclabel type='none' model='none'/> +</domain> -- 2.10.0
participants (2)
-
Daniel P. Berrange -
Martin Kletzander