We have enough patches for hotplug RNG device, maybe we can implement live hotplug of a RNG device. Signed-off-by: Luyao Huang <lhuang@xxxxxxxxxx> --- src/qemu/qemu_driver.c | 8 +++- src/qemu/qemu_hotplug.c | 106 ++++++++++++++++++++++++++++++++++++++++++++++++ src/qemu/qemu_hotplug.h | 3 ++ 3 files changed, 116 insertions(+), 1 deletion(-) diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c index 9eed81d..28fbf15 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -6976,6 +6976,13 @@ qemuDomainAttachDeviceLive(virDomainObjPtr vm, dev->data.chr = NULL; break; + case VIR_DOMAIN_DEVICE_RNG: + ret = qemuDomainAttachRNGDevice(driver, vm, + dev->data.rng); + if (!ret) + dev->data.rng = NULL; + break; + case VIR_DOMAIN_DEVICE_NONE: case VIR_DOMAIN_DEVICE_FS: case VIR_DOMAIN_DEVICE_INPUT: @@ -6987,7 +6994,6 @@ qemuDomainAttachDeviceLive(virDomainObjPtr vm, case VIR_DOMAIN_DEVICE_SMARTCARD: case VIR_DOMAIN_DEVICE_MEMBALLOON: case VIR_DOMAIN_DEVICE_NVRAM: - case VIR_DOMAIN_DEVICE_RNG: case VIR_DOMAIN_DEVICE_SHMEM: 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 6f62345..c20a4ee 100644 --- a/src/qemu/qemu_hotplug.c +++ b/src/qemu/qemu_hotplug.c @@ -1510,6 +1510,112 @@ int qemuDomainAttachChrDevice(virQEMUDriverPtr driver, return ret; } +int qemuDomainAttachRNGDevice(virQEMUDriverPtr driver, + virDomainObjPtr vm, + virDomainRNGDefPtr rng) +{ + int ret = -1; + qemuDomainObjPrivatePtr priv = vm->privateData; + virDomainDefPtr vmdef = vm->def; + char *devstr = NULL; + char *charAlias = NULL; + char *objAlias = NULL; + bool remove_chardev = false; + bool releaseaddr = false; + + if (!virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_DEVICE)) { + virReportError(VIR_ERR_OPERATION_INVALID, "%s", + _("qemu does not support -device")); + return ret; + } + + if (rng->backend == VIR_DOMAIN_RNG_BACKEND_RANDOM && + !virQEMUCapsGet(qemuCaps, QEMU_CAPS_OBJECT_RNG_RANDOM)) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", + _("this qemu doesn't support the rng-random " + "backend")); + return ret; + } else if (rng->backend == VIR_DOMAIN_RNG_BACKEND_EGD && + !virQEMUCapsGet(qemuCaps, QEMU_CAPS_OBJECT_RNG_EGD)) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", + _("this qemu doesn't support the rng-egd " + "backend")); + return ret; + } + + if (qemuAssignDeviceRNGAlias(vmdef, rng, -1) < 0) + return ret; + + if (rng->info.type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_NONE) { + if (STRPREFIX(vm->def->os.machine, "s390-ccw") && + virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_VIRTIO_CCW)) { + rng->info.type = VIR_DOMAIN_DEVICE_ADDRESS_TYPE_CCW; + } else if (virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_VIRTIO_S390)) { + rng->info.type = VIR_DOMAIN_DEVICE_ADDRESS_TYPE_VIRTIO_S390; + } + } + + if (rng->info.type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_NONE || + rng->info.type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI) { + if (virDomainPCIAddressEnsureAddr(priv->pciaddrs, &rng->info) < 0) + return ret; + } else if (rng->info.type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_CCW) { + if (virDomainCCWAddressAssign(&rng->info, priv->ccwaddrs, + !rng->info.addr.ccw.assigned) < 0) + return ret; + } + releaseaddr = true; + if (!(devstr = qemuBuildRNGDevStr(vmdef, rng, priv->qemuCaps))) + goto cleanup; + + if (virAsprintf(&objAlias, "obj%s", rng->info.alias) < 0) + goto cleanup; + + if (rng->backend == VIR_DOMAIN_RNG_BACKEND_EGD) { + if (virAsprintf(&charAlias, "char%s", rng->info.alias) < 0) + goto cleanup; + + qemuDomainObjEnterMonitor(driver, vm); + if (qemuMonitorAttachCharDev(priv->mon, charAlias, rng->source.chardev) < 0) { + qemuDomainObjExitMonitor(driver, vm); + goto audit; + } + remove_chardev = true; + } else { + qemuDomainObjEnterMonitor(driver, vm); + } + + if (qemuMonitorAttachRNGDev(priv->mon, charAlias, objAlias, rng) < 0) { + if (remove_chardev) + qemuMonitorDetachCharDev(priv->mon, charAlias); + qemuDomainObjExitMonitor(driver, vm); + goto audit; + } + + if (devstr && qemuMonitorAddDevice(priv->mon, devstr) < 0) { + qemuMonitorDetachRNGDev(priv->mon, objAlias); + if (remove_chardev) + qemuMonitorDetachCharDev(priv->mon, charAlias); + qemuDomainObjExitMonitor(driver, vm); + goto audit; + } + qemuDomainObjExitMonitor(driver, vm); + + if (virDomainRNGInsert(vmdef, rng) < 0) + goto audit; + + ret = 0; + audit: + virDomainAuditRNG(vm, NULL, rng, "attach", ret == 0); + cleanup: + if (releaseaddr) + qemuDomainReleaseDeviceAddress(vm, &rng->info, NULL); + VIR_FREE(charAlias); + VIR_FREE(objAlias); + VIR_FREE(devstr); + return ret; +} + static int qemuDomainAttachHostUSBDevice(virQEMUDriverPtr driver, virDomainObjPtr vm, diff --git a/src/qemu/qemu_hotplug.h b/src/qemu/qemu_hotplug.h index d13c532..d66853b 100644 --- a/src/qemu/qemu_hotplug.h +++ b/src/qemu/qemu_hotplug.h @@ -98,6 +98,9 @@ int qemuDomainAttachChrDevice(virQEMUDriverPtr driver, int qemuDomainDetachChrDevice(virQEMUDriverPtr driver, virDomainObjPtr vm, virDomainChrDefPtr chr); +int qemuDomainAttachRNGDevice(virQEMUDriverPtr driver, + virDomainObjPtr vm, + virDomainRNGDefPtr rng); int -- 1.8.3.1 -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list