diff --git a/src/qemu/qemu_capabilities.c b/src/qemu/qemu_capabilities.c index 35a714d426..ece7a239f6 100644 --- a/src/qemu/qemu_capabilities.c +++ b/src/qemu/qemu_capabilities.c @@ -206,6 +206,9 @@ VIR_ENUM_IMPL(virQEMUCaps, QEMU_CAPS_LAST, "usb-net", "add-fd", "nbd-server", + "virtio-rng", + + "rng-random", /* 130 */ ); struct _virQEMUCaps { @@ -1329,6 +1332,8 @@ struct virQEMUCapsStringFlags virQEMUCapsObjectTypes[] = { { "vmware-svga", QEMU_CAPS_DEVICE_VMWARE_SVGA }, { "usb-serial", QEMU_CAPS_DEVICE_USB_SERIAL}, { "usb-net", QEMU_CAPS_DEVICE_USB_NET}, + { "virtio-rng-pci", QEMU_CAPS_DEVICE_VIRTIO_RNG }, + { "rng-random", QEMU_CAPS_OBJECT_RNG_RANDOM }, }; diff --git a/src/qemu/qemu_capabilities.h b/src/qemu/qemu_capabilities.h index 7c55dc8cd1..0feae29783 100644 --- a/src/qemu/qemu_capabilities.h +++ b/src/qemu/qemu_capabilities.h @@ -167,6 +167,9 @@ enum virQEMUCapsFlags { QEMU_CAPS_DEVICE_USB_NET = 126, /* -device usb-net */ QEMU_CAPS_ADD_FD = 127, /* -add-fd */ QEMU_CAPS_NBD_SERVER = 128, /* nbd-server-start QMP command */ + QEMU_CAPS_DEVICE_VIRTIO_RNG = 129, /* virtio-rng device */ + QEMU_CAPS_OBJECT_RNG_RANDOM = 130, /* the rng-random backend for + virtio rng */ QEMU_CAPS_LAST, /* this must always be the last item */ }; diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c index dee493fa38..4a51413609 100644 --- a/src/qemu/qemu_command.c +++ b/src/qemu/qemu_command.c @@ -787,6 +787,10 @@ qemuAssignDeviceAliases(virDomainDefPtr def, virQEMUCapsPtr qemuCaps) if (virAsprintf(&def->memballoon->info.alias, "balloon%d", 0) < 0) goto no_memory; } + if (def->rng) { + if (virAsprintf(&def->rng->info.alias, "rng%d", 0) < 0) + goto no_memory; + } return 0; @@ -1660,6 +1664,14 @@ qemuAssignDevicePCISlots(virDomainDefPtr def, goto error; } + /* VirtIO RNG */ + if (def->rng && + def->rng->model == VIR_DOMAIN_RNG_MODEL_VIRTIO && + def->rng->info.type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_NONE) { + if (qemuDomainPCIAddressSetNextAddr(addrs, &def->rng->info) < 0) + goto error; + } + /* A watchdog - skip IB700, it is not a PCI device */ if (def->watchdog && def->watchdog->model != VIR_DOMAIN_WATCHDOG_MODEL_IB700 && @@ -4165,6 +4177,82 @@ error: return NULL; } + +static int +qemuBuildRNGBackendArgs(virCommandPtr cmd, + virDomainRNGDefPtr dev, + virQEMUCapsPtr qemuCaps) +{ + virBuffer buf = VIR_BUFFER_INITIALIZER; + int ret = -1; + + switch ((enum virDomainRNGBackend) dev->backend) { + case VIR_DOMAIN_RNG_BACKEND_RANDOM: + if (!virQEMUCapsGet(qemuCaps, QEMU_CAPS_OBJECT_RNG_RANDOM)) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", + _("this qemu doesn't support the rng-random " + " backend")); + goto cleanup; + } + + virBufferAsprintf(&buf, "rng-random,id=%s", dev->info.alias); + if (dev->source.file) + virBufferAsprintf(&buf, ",filename=%s", dev->source.file); + + virCommandAddArg(cmd, "-object"); + virCommandAddArgBuffer(cmd, &buf); + break; + + case VIR_DOMAIN_RNG_BACKEND_EGD: + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("egd RNG backend not yet implemented")); + goto cleanup; + break; + + case VIR_DOMAIN_RNG_BACKEND_LAST: + break; + } + + ret = 0; + +cleanup: + virBufferFreeAndReset(&buf); + return ret; +} + + +static int +qemuBuildRNGDeviceArgs(virCommandPtr cmd, + virDomainRNGDefPtr dev, + virQEMUCapsPtr qemuCaps) +{ + virBuffer buf = VIR_BUFFER_INITIALIZER; + int ret = -1; + + if (dev->model != VIR_DOMAIN_RNG_MODEL_VIRTIO || + !virQEMUCapsGet(qemuCaps, QEMU_CAPS_DEVICE_VIRTIO_RNG)) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, + _("this qemu doesn't support RNG device type '%s'"), + virDomainRNGModelTypeToString(dev->model)); + goto cleanup; + } + + virBufferAsprintf(&buf, "virtio-rng-pci,rng=%s", dev->info.alias); + + if (qemuBuildDeviceAddressStr(&buf, &dev->info, qemuCaps) < 0) + goto cleanup; + + virCommandAddArg(cmd, "-device"); + virCommandAddArgBuffer(cmd, &buf); + + ret = 0; + +cleanup: + virBufferFreeAndReset(&buf); + return ret; +} + + static char *qemuBuildSmbiosBiosStr(virSysinfoDefPtr def) { virBuffer buf = VIR_BUFFER_INITIALIZER; @@ -7006,6 +7094,16 @@ qemuBuildCommandLine(virConnectPtr conn, } } + if (def->rng) { + /* add the RNG source backend */ + if (qemuBuildRNGBackendArgs(cmd, def->rng, qemuCaps) < 0) + goto error; + + /* add the device */ + if (qemuBuildRNGDeviceArgs(cmd, def->rng, qemuCaps) < 0) + goto error; + } + if (snapshot) virCommandAddArgList(cmd, "-loadvm", snapshot->def->name, NULL);