This patch implements support for the virtio-rng-pci device and the
rng-random backend in qemu.
Two capabilities bits are added to track support for those:
QEMU_CAPS_DEVICE_VIRTIO_RNG - for the device support and
QEMU_CAPS_OBJECT_RNG_RANDOM - for the backend support.
qemu is invoked with these additional parameters if the device is
enabled:
-object rng-random,id=rng0,filename=/test/phile (to add the backend)
-device virtio-rng-pci,rng=rng0,bus=pci.0,addr=0x4 (to add the device)
---
Notes:
Version 2:
- don't use different error messages for similar issues
src/qemu/qemu_capabilities.c | 5 ++-
src/qemu/qemu_capabilities.h | 3 ++
src/qemu/qemu_command.c | 98 ++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 105 insertions(+), 1 deletion(-)
diff --git a/src/qemu/qemu_capabilities.c b/src/qemu/qemu_capabilities.c
index af52bbf..a3d9e06 100644
--- a/src/qemu/qemu_capabilities.c
+++ b/src/qemu/qemu_capabilities.c
@@ -205,7 +205,8 @@ VIR_ENUM_IMPL(virQEMUCaps, QEMU_CAPS_LAST,
"usb-serial", /* 125 */
"usb-net",
"add-fd",
-
+ "virtio-rng",
+ "rng-random",
);
struct _virQEMUCaps {
@@ -1329,6 +1330,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 e69d558..ee0d0ca 100644
--- a/src/qemu/qemu_capabilities.h
+++ b/src/qemu/qemu_capabilities.h
@@ -166,6 +166,9 @@ enum virQEMUCapsFlags {
QEMU_CAPS_DEVICE_USB_SERIAL = 125, /* -device usb-serial */
QEMU_CAPS_DEVICE_USB_NET = 126, /* -device usb-net */
QEMU_CAPS_ADD_FD = 127, /* -add-fd */
+ QEMU_CAPS_DEVICE_VIRTIO_RNG = 128, /* virtio-rng device */
+ QEMU_CAPS_OBJECT_RNG_RANDOM = 129, /* 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 dee493f..4a51413 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);
--
1.8.1.1