* [Qemu-devel] [PATCH 1/8] object: add object_property_add_bool (v2)
2012-10-26 11:01 [Qemu-devel] [PATCH 0/8] virtio-rng: hardware random number generator device Amit Shah
@ 2012-10-26 11:01 ` Amit Shah
2012-10-26 11:01 ` [Qemu-devel] [PATCH 2/8] qdev: add realized property and make adding child bus implied by realize Amit Shah
` (7 subsequent siblings)
8 siblings, 0 replies; 13+ messages in thread
From: Amit Shah @ 2012-10-26 11:01 UTC (permalink / raw)
To: Anthony Liguori; +Cc: Anthony Liguori, qemu list
From: Anthony Liguori <aliguori@us.ibm.com>
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
---
include/qemu/object.h | 16 ++++++++++++++
qom/object.c | 56 +++++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 72 insertions(+), 0 deletions(-)
diff --git a/include/qemu/object.h b/include/qemu/object.h
index cc75fee..be707f1 100644
--- a/include/qemu/object.h
+++ b/include/qemu/object.h
@@ -947,6 +947,22 @@ void object_property_add_str(Object *obj, const char *name,
struct Error **errp);
/**
+ * object_property_add_bool:
+ * @obj: the object to add a property to
+ * @name: the name of the property
+ * @get: the getter or NULL if the property is write-only.
+ * @set: the setter or NULL if the property is read-only
+ * @errp: if an error occurs, a pointer to an area to store the error
+ *
+ * Add a bool property using getters/setters. This function will add a
+ * property of type 'bool'.
+ */
+void object_property_add_bool(Object *obj, const char *name,
+ bool (*get)(Object *, struct Error **),
+ void (*set)(Object *, bool, struct Error **),
+ struct Error **errp);
+
+/**
* object_child_foreach:
* @obj: the object whose children will be navigated
* @fn: the iterator function to be called
diff --git a/qom/object.c b/qom/object.c
index e3e9242..d7092b0 100644
--- a/qom/object.c
+++ b/qom/object.c
@@ -1183,6 +1183,62 @@ void object_property_add_str(Object *obj, const char *name,
prop, errp);
}
+typedef struct BoolProperty
+{
+ bool (*get)(Object *, Error **);
+ void (*set)(Object *, bool, Error **);
+} BoolProperty;
+
+static void property_get_bool(Object *obj, Visitor *v, void *opaque,
+ const char *name, Error **errp)
+{
+ BoolProperty *prop = opaque;
+ bool value;
+
+ value = prop->get(obj, errp);
+ visit_type_bool(v, &value, name, errp);
+}
+
+static void property_set_bool(Object *obj, Visitor *v, void *opaque,
+ const char *name, Error **errp)
+{
+ BoolProperty *prop = opaque;
+ bool value;
+ Error *local_err = NULL;
+
+ visit_type_bool(v, &value, name, &local_err);
+ if (local_err) {
+ error_propagate(errp, local_err);
+ return;
+ }
+
+ prop->set(obj, value, errp);
+}
+
+static void property_release_bool(Object *obj, const char *name,
+ void *opaque)
+{
+ BoolProperty *prop = opaque;
+ g_free(prop);
+}
+
+void object_property_add_bool(Object *obj, const char *name,
+ bool (*get)(Object *, Error **),
+ void (*set)(Object *, bool, Error **),
+ Error **errp)
+{
+ BoolProperty *prop = g_malloc0(sizeof(*prop));
+
+ prop->get = get;
+ prop->set = set;
+
+ object_property_add(obj, name, "bool",
+ get ? property_get_bool : NULL,
+ set ? property_set_bool : NULL,
+ property_release_bool,
+ prop, errp);
+}
+
static char *qdev_get_type(Object *obj, Error **errp)
{
return g_strdup(object_get_typename(obj));
--
1.7.7.6
^ permalink raw reply related [flat|nested] 13+ messages in thread
* [Qemu-devel] [PATCH 2/8] qdev: add realized property and make adding child bus implied by realize
2012-10-26 11:01 [Qemu-devel] [PATCH 0/8] virtio-rng: hardware random number generator device Amit Shah
2012-10-26 11:01 ` [Qemu-devel] [PATCH 1/8] object: add object_property_add_bool (v2) Amit Shah
@ 2012-10-26 11:01 ` Amit Shah
2012-10-26 11:01 ` [Qemu-devel] [PATCH 3/8] vl: add -object option to create QOM objects from the command line Amit Shah
` (6 subsequent siblings)
8 siblings, 0 replies; 13+ messages in thread
From: Amit Shah @ 2012-10-26 11:01 UTC (permalink / raw)
To: Anthony Liguori; +Cc: Anthony Liguori, qemu list
From: Anthony Liguori <aliguori@us.ibm.com>
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
---
hw/qdev.c | 36 +++++++++++++++++++++++++++++++++++-
1 files changed, 35 insertions(+), 1 deletions(-)
diff --git a/hw/qdev.c b/hw/qdev.c
index 9b9aba3..5e34c22 100644
--- a/hw/qdev.c
+++ b/hw/qdev.c
@@ -95,7 +95,6 @@ static void bus_add_child(BusState *bus, DeviceState *child)
void qdev_set_parent_bus(DeviceState *dev, BusState *bus)
{
dev->parent_bus = bus;
- bus_add_child(bus, dev);
}
/* Create a new device. This only initializes the device state structure
@@ -151,6 +150,10 @@ int qdev_init(DeviceState *dev)
assert(dev->state == DEV_STATE_CREATED);
+ if (dev->parent_bus) {
+ bus_add_child(dev->parent_bus, dev);
+ }
+
rc = dc->init(dev);
if (rc < 0) {
qdev_free(dev);
@@ -654,6 +657,33 @@ void qdev_property_add_static(DeviceState *dev, Property *prop,
assert_no_error(local_err);
}
+static bool qdev_prop_get_realized(Object *obj, Error **errp)
+{
+ DeviceState *dev = DEVICE(obj);
+
+ return (dev->state == DEV_STATE_INITIALIZED);
+}
+
+static void qdev_prop_set_realized(Object *obj, bool value, Error **errp)
+{
+ DeviceState *dev = DEVICE(obj);
+ bool realized = (dev->state == DEV_STATE_INITIALIZED);
+
+ if (realized == value) {
+ return;
+ }
+
+ if (realized && !value) {
+ error_set(errp, QERR_PERMISSION_DENIED);
+ return;
+ }
+
+ if (qdev_init(dev) < 0) {
+ error_set(errp, QERR_DEVICE_INIT_FAILED, "");
+ return;
+ }
+}
+
static void device_initfn(Object *obj)
{
DeviceState *dev = DEVICE(obj);
@@ -678,6 +708,10 @@ static void device_initfn(Object *obj)
} while (class != object_class_by_name(TYPE_DEVICE));
qdev_prop_set_globals(dev);
+ object_property_add_bool(obj, "realized",
+ qdev_prop_get_realized, qdev_prop_set_realized,
+ NULL);
+
object_property_add_link(OBJECT(dev), "parent_bus", TYPE_BUS,
(Object **)&dev->parent_bus, NULL);
}
--
1.7.7.6
^ permalink raw reply related [flat|nested] 13+ messages in thread
* [Qemu-devel] [PATCH 3/8] vl: add -object option to create QOM objects from the command line
2012-10-26 11:01 [Qemu-devel] [PATCH 0/8] virtio-rng: hardware random number generator device Amit Shah
2012-10-26 11:01 ` [Qemu-devel] [PATCH 1/8] object: add object_property_add_bool (v2) Amit Shah
2012-10-26 11:01 ` [Qemu-devel] [PATCH 2/8] qdev: add realized property and make adding child bus implied by realize Amit Shah
@ 2012-10-26 11:01 ` Amit Shah
2012-10-26 11:01 ` [Qemu-devel] [PATCH 4/8] vl: add -late-object to create QOM objects after machine init Amit Shah
` (5 subsequent siblings)
8 siblings, 0 replies; 13+ messages in thread
From: Amit Shah @ 2012-10-26 11:01 UTC (permalink / raw)
To: Anthony Liguori; +Cc: Anthony Liguori, qemu list
From: Anthony Liguori <aliguori@us.ibm.com>
This will create a new QOM object in the '/objects' path. Note that properties
are set in order which allows for simple objects to be initialized entirely
with this option and then realized.
This option is roughly equivalent to -device but for things that are not
devices.
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
---
qemu-config.c | 10 ++++++++++
qemu-options.hx | 8 ++++++++
vl.c | 54 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 72 insertions(+), 0 deletions(-)
diff --git a/qemu-config.c b/qemu-config.c
index cd1ec21..d695bdf 100644
--- a/qemu-config.c
+++ b/qemu-config.c
@@ -653,6 +653,15 @@ QemuOptsList qemu_boot_opts = {
},
};
+QemuOptsList qemu_object_opts = {
+ .name = "object",
+ .implied_opt_name = "qom-type",
+ .head = QTAILQ_HEAD_INITIALIZER(qemu_object_opts.head),
+ .desc = {
+ { }
+ },
+};
+
static QemuOptsList *vm_config_groups[32] = {
&qemu_drive_opts,
&qemu_chardev_opts,
@@ -669,6 +678,7 @@ static QemuOptsList *vm_config_groups[32] = {
&qemu_boot_opts,
&qemu_iscsi_opts,
&qemu_sandbox_opts,
+ &qemu_object_opts,
NULL,
};
diff --git a/qemu-options.hx b/qemu-options.hx
index 46f0539..b72151e 100644
--- a/qemu-options.hx
+++ b/qemu-options.hx
@@ -2852,6 +2852,14 @@ STEXI
Enable FIPS 140-2 compliance mode.
ETEXI
+DEF("object", HAS_ARG, QEMU_OPTION_object,
+ "-object TYPENAME[,PROP1=VALUE1,...]\n"
+ " create an new object of type TYPENAME setting properties\n"
+ " in the order they are specified. Note that the 'id'\n"
+ " property must be set. These objects are placed in the\n"
+ " '/objects' path.\n",
+ QEMU_ARCH_ALL)
+
HXCOMM This is the last statement. Insert new options before this line!
STEXI
@end table
diff --git a/vl.c b/vl.c
index ee3c43a..eabf47b 100644
--- a/vl.c
+++ b/vl.c
@@ -168,6 +168,7 @@ int main(int argc, char **argv)
#include "osdep.h"
#include "ui/qemu-spice.h"
+#include "qapi/string-input-visitor.h"
//#define DEBUG_NET
//#define DEBUG_SLIRP
@@ -2357,6 +2358,53 @@ static void free_and_trace(gpointer mem)
free(mem);
}
+static int object_set_property(const char *name, const char *value, void *opaque)
+{
+ Object *obj = OBJECT(opaque);
+ StringInputVisitor *siv;
+ Error *local_err = NULL;
+
+ if (strcmp(name, "qom-type") == 0 || strcmp(name, "id") == 0) {
+ return 0;
+ }
+
+ siv = string_input_visitor_new(value);
+ object_property_set(obj, string_input_get_visitor(siv), name, &local_err);
+ string_input_visitor_cleanup(siv);
+
+ if (local_err) {
+ qerror_report_err(local_err);
+ error_free(local_err);
+ return -1;
+ }
+
+ return 0;
+}
+
+static int object_create(QemuOpts *opts, void *opaque)
+{
+ const char *type = qemu_opt_get(opts, "qom-type");
+ const char *id = qemu_opts_id(opts);
+ Object *obj;
+
+ g_assert(type != NULL);
+
+ if (id == NULL) {
+ qerror_report(QERR_MISSING_PARAMETER, "id");
+ return -1;
+ }
+
+ obj = object_new(type);
+ if (qemu_opt_foreach(opts, object_set_property, obj, 1) < 0) {
+ return -1;
+ }
+
+ object_property_add_child(container_get(object_get_root(), "/objects"),
+ id, obj, NULL);
+
+ return 0;
+}
+
int qemu_init_main_loop(void)
{
return main_loop_init();
@@ -3308,6 +3356,9 @@ int main(int argc, char **argv, char **envp)
if (!opts) {
exit(0);
}
+ break;
+ case QEMU_OPTION_object:
+ opts = qemu_opts_parse(qemu_find_opts("object"), optarg, 1);
break;
default:
os_parse_cmd_args(popt->index, optarg);
@@ -3319,6 +3370,9 @@ int main(int argc, char **argv, char **envp)
if (qemu_opts_foreach(qemu_find_opts("sandbox"), parse_sandbox, NULL, 0)) {
exit(1);
}
+ if (qemu_opts_foreach(qemu_find_opts("object"), object_create, NULL, 0) != 0) {
+ exit(1);
+ }
if (machine == NULL) {
fprintf(stderr, "No machine found.\n");
--
1.7.7.6
^ permalink raw reply related [flat|nested] 13+ messages in thread
* [Qemu-devel] [PATCH 4/8] vl: add -late-object to create QOM objects after machine init
2012-10-26 11:01 [Qemu-devel] [PATCH 0/8] virtio-rng: hardware random number generator device Amit Shah
` (2 preceding siblings ...)
2012-10-26 11:01 ` [Qemu-devel] [PATCH 3/8] vl: add -object option to create QOM objects from the command line Amit Shah
@ 2012-10-26 11:01 ` Amit Shah
2012-10-26 11:01 ` [Qemu-devel] [PATCH 5/8] rng: add RndBackend abstract object class Amit Shah
` (4 subsequent siblings)
8 siblings, 0 replies; 13+ messages in thread
From: Amit Shah @ 2012-10-26 11:01 UTC (permalink / raw)
To: Anthony Liguori; +Cc: Anthony Liguori, qemu list
From: Anthony Liguori <aliguori@us.ibm.com>
In order to create qdev objects via -late-object, we almost always have to
specify the parent_bus which is usually created during machine init. Until we
properly support two stage init, introduce a -late-object option that allows for
creation of objects post-machine init.
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
---
qemu-config.c | 10 ++++++++++
qemu-options.hx | 12 ++++++++++++
vl.c | 14 +++++++++++---
3 files changed, 33 insertions(+), 3 deletions(-)
diff --git a/qemu-config.c b/qemu-config.c
index d695bdf..537acd1 100644
--- a/qemu-config.c
+++ b/qemu-config.c
@@ -662,6 +662,15 @@ QemuOptsList qemu_object_opts = {
},
};
+QemuOptsList qemu_late_object_opts = {
+ .name = "late-object",
+ .implied_opt_name = "qom-type",
+ .head = QTAILQ_HEAD_INITIALIZER(qemu_late_object_opts.head),
+ .desc = {
+ { }
+ },
+};
+
static QemuOptsList *vm_config_groups[32] = {
&qemu_drive_opts,
&qemu_chardev_opts,
@@ -679,6 +688,7 @@ static QemuOptsList *vm_config_groups[32] = {
&qemu_iscsi_opts,
&qemu_sandbox_opts,
&qemu_object_opts,
+ &qemu_late_object_opts,
NULL,
};
diff --git a/qemu-options.hx b/qemu-options.hx
index b72151e..a0fe038 100644
--- a/qemu-options.hx
+++ b/qemu-options.hx
@@ -2860,6 +2860,18 @@ DEF("object", HAS_ARG, QEMU_OPTION_object,
" '/objects' path.\n",
QEMU_ARCH_ALL)
+DEF("late-object", HAS_ARG, QEMU_OPTION_late_object,
+ "-late-object TYPENAME[,PROP1=VALUE1,...]\n"
+ " create an new object of type TYPENAME setting properties\n"
+ " in the order they are specified. Note that the 'id'\n"
+ " property must be set. These objects are placed in the\n"
+ " '/objects' path.\n"
+ "\n"
+ " Late objects are made after machine\n"
+ " initialization so they can refer to objects created by\n"
+ " the machine init function.\n",
+ QEMU_ARCH_ALL)
+
HXCOMM This is the last statement. Insert new options before this line!
STEXI
@end table
diff --git a/vl.c b/vl.c
index eabf47b..61b4666 100644
--- a/vl.c
+++ b/vl.c
@@ -2395,13 +2395,14 @@ static int object_create(QemuOpts *opts, void *opaque)
}
obj = object_new(type);
- if (qemu_opt_foreach(opts, object_set_property, obj, 1) < 0) {
- return -1;
- }
object_property_add_child(container_get(object_get_root(), "/objects"),
id, obj, NULL);
+ if (qemu_opt_foreach(opts, object_set_property, obj, 1) < 0) {
+ return -1;
+ }
+
return 0;
}
@@ -3360,6 +3361,9 @@ int main(int argc, char **argv, char **envp)
case QEMU_OPTION_object:
opts = qemu_opts_parse(qemu_find_opts("object"), optarg, 1);
break;
+ case QEMU_OPTION_late_object:
+ opts = qemu_opts_parse(qemu_find_opts("late-object"), optarg, 1);
+ break;
default:
os_parse_cmd_args(popt->index, optarg);
}
@@ -3706,6 +3710,10 @@ int main(int argc, char **argv, char **envp)
current_machine = machine;
+ if (qemu_opts_foreach(qemu_find_opts("late-object"), object_create, NULL, 0) != 0) {
+ exit(1);
+ }
+
/* init USB devices */
if (usb_enabled) {
if (foreach_device_config(DEV_USB, usb_parse) < 0)
--
1.7.7.6
^ permalink raw reply related [flat|nested] 13+ messages in thread
* [Qemu-devel] [PATCH 5/8] rng: add RndBackend abstract object class
2012-10-26 11:01 [Qemu-devel] [PATCH 0/8] virtio-rng: hardware random number generator device Amit Shah
` (3 preceding siblings ...)
2012-10-26 11:01 ` [Qemu-devel] [PATCH 4/8] vl: add -late-object to create QOM objects after machine init Amit Shah
@ 2012-10-26 11:01 ` Amit Shah
2012-10-26 11:01 ` [Qemu-devel] [PATCH 6/8] rng-urandom: add an RNG backend that uses /dev/urandom Amit Shah
` (3 subsequent siblings)
8 siblings, 0 replies; 13+ messages in thread
From: Amit Shah @ 2012-10-26 11:01 UTC (permalink / raw)
To: Anthony Liguori; +Cc: Anthony Liguori, qemu list
From: Anthony Liguori <aliguori@us.ibm.com>
This is the backend used by devices that need to request entropy.
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
---
Makefile.objs | 2 +
backends/Makefile.objs | 1 +
backends/rng.c | 93 ++++++++++++++++++++++++++++++++++++++++++++++++
include/qemu/rng.h | 93 ++++++++++++++++++++++++++++++++++++++++++++++++
4 files changed, 189 insertions(+), 0 deletions(-)
create mode 100644 backends/Makefile.objs
create mode 100644 backends/rng.c
create mode 100644 include/qemu/rng.h
diff --git a/Makefile.objs b/Makefile.objs
index 74b3542..a2decc5 100644
--- a/Makefile.objs
+++ b/Makefile.objs
@@ -100,6 +100,8 @@ common-obj-y += vl.o
common-obj-$(CONFIG_SLIRP) += slirp/
+common-obj-y += backends/
+
######################################################################
# libseccomp
ifeq ($(CONFIG_SECCOMP),y)
diff --git a/backends/Makefile.objs b/backends/Makefile.objs
new file mode 100644
index 0000000..06e08c7
--- /dev/null
+++ b/backends/Makefile.objs
@@ -0,0 +1 @@
+common-obj-y += rng.o
diff --git a/backends/rng.c b/backends/rng.c
new file mode 100644
index 0000000..06f2611
--- /dev/null
+++ b/backends/rng.c
@@ -0,0 +1,93 @@
+/*
+ * QEMU Random Number Generator Backend
+ *
+ * Copyright IBM, Corp. 2012
+ *
+ * Authors:
+ * Anthony Liguori <aliguori@us.ibm.com>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ */
+
+#include "qemu/rng.h"
+#include "qerror.h"
+
+void rng_backend_request_entropy(RngBackend *s, size_t size,
+ EntropyReceiveFunc *receive_entropy,
+ void *opaque)
+{
+ RngBackendClass *k = RNG_BACKEND_GET_CLASS(s);
+
+ if (k->request_entropy) {
+ k->request_entropy(s, size, receive_entropy, opaque);
+ }
+}
+
+void rng_backend_cancel_requests(RngBackend *s)
+{
+ RngBackendClass *k = RNG_BACKEND_GET_CLASS(s);
+
+ if (k->cancel_requests) {
+ k->cancel_requests(s);
+ }
+}
+
+static bool rng_backend_prop_get_opened(Object *obj, Error **errp)
+{
+ RngBackend *s = RNG_BACKEND(obj);
+
+ return s->opened;
+}
+
+void rng_backend_open(RngBackend *s, Error **errp)
+{
+ object_property_set_bool(OBJECT(s), true, "opened", errp);
+}
+
+static void rng_backend_prop_set_opened(Object *obj, bool value, Error **errp)
+{
+ RngBackend *s = RNG_BACKEND(obj);
+ RngBackendClass *k = RNG_BACKEND_GET_CLASS(s);
+
+ if (value == s->opened) {
+ return;
+ }
+
+ if (!value && s->opened) {
+ error_set(errp, QERR_PERMISSION_DENIED);
+ return;
+ }
+
+ if (k->opened) {
+ k->opened(s, errp);
+ }
+
+ if (!error_is_set(errp)) {
+ s->opened = value;
+ }
+}
+
+static void rng_backend_init(Object *obj)
+{
+ object_property_add_bool(obj, "opened",
+ rng_backend_prop_get_opened,
+ rng_backend_prop_set_opened,
+ NULL);
+}
+
+static TypeInfo rng_backend_info = {
+ .name = TYPE_RNG_BACKEND,
+ .parent = TYPE_OBJECT,
+ .instance_size = sizeof(RngBackend),
+ .instance_init = rng_backend_init,
+ .class_size = sizeof(RngBackendClass),
+ .abstract = true,
+};
+
+static void register_types(void)
+{
+ type_register_static(&rng_backend_info);
+}
+
+type_init(register_types);
diff --git a/include/qemu/rng.h b/include/qemu/rng.h
new file mode 100644
index 0000000..9836463
--- /dev/null
+++ b/include/qemu/rng.h
@@ -0,0 +1,93 @@
+/*
+ * QEMU Random Number Generator Backend
+ *
+ * Copyright IBM, Corp. 2012
+ *
+ * Authors:
+ * Anthony Liguori <aliguori@us.ibm.com>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ */
+
+#ifndef QEMU_RNG_H
+#define QEMU_RNG_H
+
+#include "qemu/object.h"
+#include "qemu-common.h"
+#include "error.h"
+
+#define TYPE_RNG_BACKEND "rng-backend"
+#define RNG_BACKEND(obj) \
+ OBJECT_CHECK(RngBackend, (obj), TYPE_RNG_BACKEND)
+#define RNG_BACKEND_GET_CLASS(obj) \
+ OBJECT_GET_CLASS(RngBackendClass, (obj), TYPE_RNG_BACKEND)
+#define RNG_BACKEND_CLASS(klass) \
+ OBJECT_CLASS_CHECK(RngBackendClass, (klass), TYPE_RNG_BACKEND)
+
+typedef struct RngBackendClass RngBackendClass;
+typedef struct RngBackend RngBackend;
+
+typedef void (EntropyReceiveFunc)(void *opaque,
+ const void *data,
+ size_t size);
+
+struct RngBackendClass
+{
+ ObjectClass parent_class;
+
+ void (*request_entropy)(RngBackend *s, size_t size,
+ EntropyReceiveFunc *recieve_entropy, void *opaque);
+ void (*cancel_requests)(RngBackend *s);
+
+ void (*opened)(RngBackend *s, Error **errp);
+};
+
+struct RngBackend
+{
+ Object parent;
+
+ /*< protected >*/
+ bool opened;
+};
+
+/**
+ * rng_backend_request_entropy:
+ * @s: the backend to request entropy from
+ * @size: the number of bytes of data to request
+ * @receive_entropy: a function to be invoked when entropy is available
+ * @opaque: data that should be passed to @receive_entropy
+ *
+ * This function is used by the front-end to request entropy from an entropy
+ * source. This function can be called multiple times before @receive_entropy
+ * is invoked with different values of @receive_entropy and @opaque. The
+ * backend will queue each request and handle appropriately.
+ *
+ * The backend does not need to pass the full amount of data to @receive_entropy
+ * but will pass a a value greater than 0.
+ */
+void rng_backend_request_entropy(RngBackend *s, size_t size,
+ EntropyReceiveFunc *receive_entropy,
+ void *opaque);
+
+/**
+ * rng_backend_cancel_requests:
+ * @s: the backend to cancel all pending requests in
+ *
+ * Cancels all pending requests submitted by @rng_backend_request_entropy. This
+ * should be used by a device during reset or in preparation for live migration
+ * to stop tracking any request.
+ */
+void rng_backend_cancel_requests(RngBackend *s);
+
+/**
+ * rng_backend_open:
+ * @s: the backend to open
+ * @errp: a pointer to return the #Error object if an error occurs.
+ *
+ * This function will open the backend if it is not already open. Calling this
+ * function on an already opened backend will not result in an error.
+ */
+void rng_backend_open(RngBackend *s, Error **errp);
+
+#endif
--
1.7.7.6
^ permalink raw reply related [flat|nested] 13+ messages in thread
* [Qemu-devel] [PATCH 6/8] rng-urandom: add an RNG backend that uses /dev/urandom
2012-10-26 11:01 [Qemu-devel] [PATCH 0/8] virtio-rng: hardware random number generator device Amit Shah
` (4 preceding siblings ...)
2012-10-26 11:01 ` [Qemu-devel] [PATCH 5/8] rng: add RndBackend abstract object class Amit Shah
@ 2012-10-26 11:01 ` Amit Shah
2012-10-26 11:01 ` [Qemu-devel] [PATCH 7/8] rng-egd: introduce EGD compliant RNG backend Amit Shah
` (2 subsequent siblings)
8 siblings, 0 replies; 13+ messages in thread
From: Amit Shah @ 2012-10-26 11:01 UTC (permalink / raw)
To: Anthony Liguori; +Cc: Anthony Liguori, qemu list
From: Anthony Liguori <aliguori@us.ibm.com>
The filename can be overridden but it expects a non-blocking source of entropy.
A typical invocation would be:
qemu -object rng-urandom,id=rng0 -device virtio-rng-pci,rng=rng0
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
---
backends/Makefile.objs | 2 +-
backends/rng-urandom.c | 144 ++++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 145 insertions(+), 1 deletions(-)
create mode 100644 backends/rng-urandom.c
diff --git a/backends/Makefile.objs b/backends/Makefile.objs
index 06e08c7..423c9df 100644
--- a/backends/Makefile.objs
+++ b/backends/Makefile.objs
@@ -1 +1 @@
-common-obj-y += rng.o
+common-obj-y += rng.o rng-urandom.o
diff --git a/backends/rng-urandom.c b/backends/rng-urandom.c
new file mode 100644
index 0000000..7fbe886
--- /dev/null
+++ b/backends/rng-urandom.c
@@ -0,0 +1,144 @@
+/*
+ * QEMU Random Number Generator Backend
+ *
+ * Copyright IBM, Corp. 2012
+ *
+ * Authors:
+ * Anthony Liguori <aliguori@us.ibm.com>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ */
+
+#include "qemu/rng.h"
+#include "qerror.h"
+
+#define TYPE_RNG_URANDOM "rng-urandom"
+#define RNG_URANDOM(obj) OBJECT_CHECK(RndURandom, (obj), TYPE_RNG_URANDOM)
+
+typedef struct RndURandom
+{
+ RngBackend parent;
+
+ int fd;
+ char *filename;
+ GSList *pending_data;
+} RndURandom;
+
+/**
+ * A simple and incomplete backend to request entropy from /dev/urandom.
+ *
+ * This backend exposes an additional "filename" property that can be used to
+ * set the filename to use to open the backend.
+ */
+static void rng_urandom_request_entropy(RngBackend *b, size_t size,
+ EntropyReceiveFunc *receive_entropy,
+ void *opaque)
+{
+ RndURandom *s = RNG_URANDOM(b);
+ uint8_t data[size];
+ ssize_t ret;
+
+ g_assert(s->fd != -1);
+
+ do {
+ ret = read(s->fd, data, size);
+ } while (ret == -1 && errno == EINTR);
+
+ g_assert(ret != -1);
+
+ /* FIXME: needs to be done via a BH */
+ receive_entropy(opaque, data, ret);
+}
+
+static void rng_urandom_opened(RngBackend *b, Error **errp)
+{
+ RndURandom *s = RNG_URANDOM(b);
+
+ if (s->filename == NULL) {
+ error_set(errp, QERR_INVALID_PARAMETER_VALUE,
+ "filename", "a valid filename");
+ } else {
+ s->fd = open(s->filename, O_RDONLY);
+
+ if (s->fd == -1) {
+ error_set(errp, QERR_OPEN_FILE_FAILED, s->filename);
+ }
+ }
+}
+
+static char *rng_urandom_get_filename(Object *obj, Error **errp)
+{
+ RndURandom *s = RNG_URANDOM(obj);
+
+ if (s->filename) {
+ return g_strdup(s->filename);
+ }
+
+ return NULL;
+}
+
+static void rng_urandom_set_filename(Object *obj, const char *filename,
+ Error **errp)
+{
+ RngBackend *b = RNG_BACKEND(obj);
+ RndURandom *s = RNG_URANDOM(obj);
+
+ if (b->opened) {
+ error_set(errp, QERR_PERMISSION_DENIED);
+ return;
+ }
+
+ if (s->filename) {
+ g_free(s->filename);
+ }
+
+ s->filename = g_strdup(filename);
+}
+
+static void rng_urandom_init(Object *obj)
+{
+ RndURandom *s = RNG_URANDOM(obj);
+
+ object_property_add_str(obj, "filename",
+ rng_urandom_get_filename,
+ rng_urandom_set_filename,
+ NULL);
+
+ s->filename = g_strdup("/dev/urandom");
+}
+
+static void rng_urandom_finalize(Object *obj)
+{
+ RndURandom *s = RNG_URANDOM(obj);
+
+ if (s->fd != -1) {
+ close(s->fd);
+ }
+
+ g_free(s->filename);
+}
+
+static void rng_urandom_class_init(ObjectClass *klass, void *data)
+{
+ RngBackendClass *rbc = RNG_BACKEND_CLASS(klass);
+
+ rbc->request_entropy = rng_urandom_request_entropy;
+ rbc->opened = rng_urandom_opened;
+}
+
+static TypeInfo rng_urandom_info = {
+ .name = TYPE_RNG_URANDOM,
+ .parent = TYPE_RNG_BACKEND,
+ .instance_size = sizeof(RndURandom),
+ .class_init = rng_urandom_class_init,
+ .instance_init = rng_urandom_init,
+ .instance_finalize = rng_urandom_finalize,
+};
+
+static void register_types(void)
+{
+ type_register_static(&rng_urandom_info);
+}
+
+type_init(register_types);
--
1.7.7.6
^ permalink raw reply related [flat|nested] 13+ messages in thread
* [Qemu-devel] [PATCH 7/8] rng-egd: introduce EGD compliant RNG backend
2012-10-26 11:01 [Qemu-devel] [PATCH 0/8] virtio-rng: hardware random number generator device Amit Shah
` (5 preceding siblings ...)
2012-10-26 11:01 ` [Qemu-devel] [PATCH 6/8] rng-urandom: add an RNG backend that uses /dev/urandom Amit Shah
@ 2012-10-26 11:01 ` Amit Shah
2012-10-26 11:01 ` [Qemu-devel] [PATCH 8/8] virtio-rng: hardware random number generator device Amit Shah
2012-10-26 14:13 ` [Qemu-devel] [PATCH 0/8] " Paolo Bonzini
8 siblings, 0 replies; 13+ messages in thread
From: Amit Shah @ 2012-10-26 11:01 UTC (permalink / raw)
To: Anthony Liguori; +Cc: Anthony Liguori, qemu list
From: Anthony Liguori <aliguori@us.ibm.com>
This backend talks EGD to a CharDriverState. A typical way to invoke this would
be:
qemu -chardev socket,host=localhost,port=1024,id=chr0 \
-object rng-egd,chardev=chr0,id=egd0 \
-device virtio-rng-pci,rng=egd0
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
---
backends/Makefile.objs | 2 +-
backends/rng-egd.c | 215 ++++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 216 insertions(+), 1 deletions(-)
create mode 100644 backends/rng-egd.c
diff --git a/backends/Makefile.objs b/backends/Makefile.objs
index 423c9df..937e30a 100644
--- a/backends/Makefile.objs
+++ b/backends/Makefile.objs
@@ -1 +1 @@
-common-obj-y += rng.o rng-urandom.o
+common-obj-y += rng.o rng-urandom.o rng-egd.o
diff --git a/backends/rng-egd.c b/backends/rng-egd.c
new file mode 100644
index 0000000..7c459dc
--- /dev/null
+++ b/backends/rng-egd.c
@@ -0,0 +1,215 @@
+/*
+ * QEMU Random Number Generator Backend
+ *
+ * Copyright IBM, Corp. 2012
+ *
+ * Authors:
+ * Anthony Liguori <aliguori@us.ibm.com>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ */
+
+#include "qemu/rng.h"
+#include "qemu-char.h"
+#include "qerror.h"
+#include "hw/qdev.h" // just for DEFINE_PROP_CHR
+
+#define TYPE_RNG_EGD "rng-egd"
+#define RNG_EGD(obj) OBJECT_CHECK(RngEgd, (obj), TYPE_RNG_EGD)
+
+typedef struct RngEgd
+{
+ RngBackend parent;
+
+ CharDriverState *chr;
+ char *chr_name;
+
+ GSList *requests;
+} RngEgd;
+
+typedef struct RngRequest
+{
+ EntropyReceiveFunc *receive_entropy;
+ uint8_t *data;
+ void *opaque;
+ size_t offset;
+ size_t size;
+} RngRequest;
+
+static void rng_egd_request_entropy(RngBackend *b, size_t size,
+ EntropyReceiveFunc *receive_entropy,
+ void *opaque)
+{
+ RngEgd *s = RNG_EGD(b);
+ RngRequest *req;
+
+ req = g_malloc(sizeof(*req));
+
+ req->offset = 0;
+ req->size = size;
+ req->receive_entropy = receive_entropy;
+ req->opaque = opaque;
+ req->data = g_malloc(req->size);
+
+ while (size > 0) {
+ uint8_t header[2];
+ uint8_t len = MIN(size, 255);
+
+ /* synchronous entropy request */
+ header[0] = 0x02;
+ header[1] = len;
+
+ qemu_chr_fe_write(s->chr, header, sizeof(header));
+
+ size -= len;
+ }
+
+ s->requests = g_slist_append(s->requests, req);
+}
+
+static void rng_egd_free_request(RngRequest *req)
+{
+ g_free(req->data);
+ g_free(req);
+}
+
+static int rng_egd_chr_can_read(void *opaque)
+{
+ RngEgd *s = RNG_EGD(opaque);
+ GSList *i;
+ int size = 0;
+
+ for (i = s->requests; i; i = i->next) {
+ RngRequest *req = i->data;
+ size += req->size - req->offset;
+ }
+
+ return size;
+}
+
+static void rng_egd_chr_read(void *opaque, const uint8_t *buf, int size)
+{
+ RngEgd *s = RNG_EGD(opaque);
+
+ while (size > 0 && s->requests) {
+ RngRequest *req = s->requests->data;
+ int len = MIN(size, req->size - req->offset);
+
+ memcpy(req->data + req->offset, buf, len);
+ req->offset += len;
+ size -= len;
+
+ if (req->offset == req->size) {
+ s->requests = g_slist_remove_link(s->requests, s->requests);
+
+ req->receive_entropy(req->opaque, req->data, req->size);
+
+ rng_egd_free_request(req);
+ }
+ }
+}
+
+static void rng_egd_cancel_requests(RngBackend *b)
+{
+ RngEgd *s = RNG_EGD(b);
+
+ /* We simply delete the list of pending requests. If there is data in the
+ * queue waiting to be read, this is okay, because there will always be
+ * more data than we requested originally
+ */
+ g_slist_free_full(s->requests,
+ (GDestroyNotify)rng_egd_free_request);
+ s->requests = NULL;
+}
+
+static void rng_egd_opened(RngBackend *b, Error **errp)
+{
+ RngEgd *s = RNG_EGD(b);
+
+ if (s->chr_name == NULL) {
+ error_set(errp, QERR_INVALID_PARAMETER_VALUE,
+ "chardev", "a valid character device");
+ return;
+ }
+
+ s->chr = qemu_chr_find(s->chr_name);
+ if (s->chr == NULL) {
+ error_set(errp, QERR_DEVICE_NOT_FOUND, s->chr_name);
+ return;
+ }
+
+ /* FIXME we should resubmit pending requests when the CDS reconnects. */
+ qemu_chr_add_handlers(s->chr, rng_egd_chr_can_read, rng_egd_chr_read,
+ NULL, s);
+}
+
+static void rng_egd_set_chardev(Object *obj, const char *value, Error **errp)
+{
+ RngBackend *b = RNG_BACKEND(obj);
+ RngEgd *s = RNG_EGD(b);
+
+ if (b->opened) {
+ error_set(errp, QERR_PERMISSION_DENIED);
+ } else {
+ g_free(s->chr_name);
+ s->chr_name = g_strdup(value);
+ }
+}
+
+static char *rng_egd_get_chardev(Object *obj, Error **errp)
+{
+ RngEgd *s = RNG_EGD(obj);
+
+ if (s->chr && s->chr->label) {
+ return g_strdup(s->chr->label);
+ }
+
+ return NULL;
+}
+
+static void rng_egd_init(Object *obj)
+{
+ object_property_add_str(obj, "chardev",
+ rng_egd_get_chardev, rng_egd_set_chardev,
+ NULL);
+}
+
+static void rng_egd_finalize(Object *obj)
+{
+ RngEgd *s = RNG_EGD(obj);
+
+ if (s->chr) {
+ qemu_chr_add_handlers(s->chr, NULL, NULL, NULL, NULL);
+ }
+
+ g_free(s->chr_name);
+
+ g_slist_free_full(s->requests, (GDestroyNotify)rng_egd_free_request);
+ s->requests = NULL;
+}
+
+static void rng_egd_class_init(ObjectClass *klass, void *data)
+{
+ RngBackendClass *rbc = RNG_BACKEND_CLASS(klass);
+
+ rbc->request_entropy = rng_egd_request_entropy;
+ rbc->cancel_requests = rng_egd_cancel_requests;
+ rbc->opened = rng_egd_opened;
+}
+
+static TypeInfo rng_egd_info = {
+ .name = TYPE_RNG_EGD,
+ .parent = TYPE_RNG_BACKEND,
+ .instance_size = sizeof(RngEgd),
+ .class_init = rng_egd_class_init,
+ .instance_init = rng_egd_init,
+ .instance_finalize = rng_egd_finalize,
+};
+
+static void register_types(void)
+{
+ type_register_static(&rng_egd_info);
+}
+
+type_init(register_types);
--
1.7.7.6
^ permalink raw reply related [flat|nested] 13+ messages in thread
* [Qemu-devel] [PATCH 8/8] virtio-rng: hardware random number generator device
2012-10-26 11:01 [Qemu-devel] [PATCH 0/8] virtio-rng: hardware random number generator device Amit Shah
` (6 preceding siblings ...)
2012-10-26 11:01 ` [Qemu-devel] [PATCH 7/8] rng-egd: introduce EGD compliant RNG backend Amit Shah
@ 2012-10-26 11:01 ` Amit Shah
2012-10-26 14:13 ` [Qemu-devel] [PATCH 0/8] " Paolo Bonzini
8 siblings, 0 replies; 13+ messages in thread
From: Amit Shah @ 2012-10-26 11:01 UTC (permalink / raw)
To: Anthony Liguori; +Cc: Amit Shah, Anthony Liguori, qemu list
The Linux kernel already has a virtio-rng driver, this is the device
implementation.
When the guest asks for entropy from the virtio hwrng, it puts a buffer
in the vq. We then put entropy into that buffer, and push it back to
the guest.
Signed-off-by: Amit Shah <amit.shah@redhat.com>
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
---
hw/Makefile.objs | 1 +
hw/pci.h | 1 +
hw/s390-virtio-bus.c | 37 ++++++++++++
hw/s390-virtio-bus.h | 2 +
hw/virtio-pci.c | 60 ++++++++++++++++++++
hw/virtio-pci.h | 2 +
hw/virtio-rng.c | 149 ++++++++++++++++++++++++++++++++++++++++++++++++++
hw/virtio-rng.h | 24 ++++++++
hw/virtio.h | 3 +
9 files changed, 279 insertions(+), 0 deletions(-)
create mode 100644 hw/virtio-rng.c
create mode 100644 hw/virtio-rng.h
diff --git a/hw/Makefile.objs b/hw/Makefile.objs
index af4ab0c..ea46f81 100644
--- a/hw/Makefile.objs
+++ b/hw/Makefile.objs
@@ -1,6 +1,7 @@
common-obj-y = usb/ ide/
common-obj-y += loader.o
common-obj-$(CONFIG_VIRTIO) += virtio-console.o
+common-obj-$(CONFIG_VIRTIO) += virtio-rng.o
common-obj-$(CONFIG_VIRTIO_PCI) += virtio-pci.o
common-obj-y += fw_cfg.o
common-obj-$(CONFIG_PCI) += pci.o pci_bridge.o pci_bridge_dev.o
diff --git a/hw/pci.h b/hw/pci.h
index 1f902f5..93e2a46 100644
--- a/hw/pci.h
+++ b/hw/pci.h
@@ -76,6 +76,7 @@
#define PCI_DEVICE_ID_VIRTIO_BALLOON 0x1002
#define PCI_DEVICE_ID_VIRTIO_CONSOLE 0x1003
#define PCI_DEVICE_ID_VIRTIO_SCSI 0x1004
+#define PCI_DEVICE_ID_VIRTIO_RNG 0x1005
#define FMT_PCIBUS PRIx64
diff --git a/hw/s390-virtio-bus.c b/hw/s390-virtio-bus.c
index 5849a96..e0ac2d1 100644
--- a/hw/s390-virtio-bus.c
+++ b/hw/s390-virtio-bus.c
@@ -26,6 +26,7 @@
#include "loader.h"
#include "elf.h"
#include "hw/virtio.h"
+#include "hw/virtio-rng.h"
#include "hw/virtio-serial.h"
#include "hw/virtio-net.h"
#include "hw/sysbus.h"
@@ -206,6 +207,18 @@ static int s390_virtio_scsi_init(VirtIOS390Device *dev)
return s390_virtio_device_init(dev, vdev);
}
+static int s390_virtio_rng_init(VirtIOS390Device *dev)
+{
+ VirtIODevice *vdev;
+
+ vdev = virtio_rng_init((DeviceState *)dev, &dev->rng);
+ if (!vdev) {
+ return -1;
+ }
+
+ return s390_virtio_device_init(dev, vdev);
+}
+
static uint64_t s390_virtio_device_vq_token(VirtIOS390Device *dev, int vq)
{
ram_addr_t token_off;
@@ -448,6 +461,29 @@ static TypeInfo s390_virtio_serial = {
.class_init = s390_virtio_serial_class_init,
};
+static void s390_virtio_rng_initfn(Object *obj)
+{
+ VirtIOS390Device *dev = VIRTIO_S390_DEVICE(obj);
+
+ object_property_add_link(obj, "rng", TYPE_RNG_BACKEND,
+ (Object **)&dev->rng.rng, NULL);
+}
+
+static void s390_virtio_rng_class_init(ObjectClass *klass, void *data)
+{
+ VirtIOS390DeviceClass *k = VIRTIO_S390_DEVICE_CLASS(klass);
+
+ k->init = s390_virtio_rng_init;
+}
+
+static TypeInfo s390_virtio_rng = {
+ .name = "virtio-rng-s390",
+ .parent = TYPE_VIRTIO_S390_DEVICE,
+ .instance_size = sizeof(VirtIOS390Device),
+ .instance_init = s390_virtio_rng_initfn,
+ .class_init = s390_virtio_rng_class_init,
+};
+
static int s390_virtio_busdev_init(DeviceState *dev)
{
VirtIOS390Device *_dev = (VirtIOS390Device *)dev;
@@ -528,6 +564,7 @@ static void s390_virtio_register_types(void)
type_register_static(&s390_virtio_blk);
type_register_static(&s390_virtio_net);
type_register_static(&s390_virtio_scsi);
+ type_register_static(&s390_virtio_rng);
type_register_static(&s390_virtio_bridge_info);
}
diff --git a/hw/s390-virtio-bus.h b/hw/s390-virtio-bus.h
index 4873134..a83afe7 100644
--- a/hw/s390-virtio-bus.h
+++ b/hw/s390-virtio-bus.h
@@ -19,6 +19,7 @@
#include "virtio-blk.h"
#include "virtio-net.h"
+#include "virtio-rng.h"
#include "virtio-serial.h"
#include "virtio-scsi.h"
@@ -75,6 +76,7 @@ struct VirtIOS390Device {
virtio_serial_conf serial;
virtio_net_conf net;
VirtIOSCSIConf scsi;
+ VirtIORNGConf rng;
};
typedef struct VirtIOS390Bus {
diff --git a/hw/virtio-pci.c b/hw/virtio-pci.c
index c7f20c3..0dc2a06 100644
--- a/hw/virtio-pci.c
+++ b/hw/virtio-pci.c
@@ -880,6 +880,28 @@ static void virtio_balloon_exit_pci(PCIDevice *pci_dev)
virtio_exit_pci(pci_dev);
}
+static int virtio_rng_init_pci(PCIDevice *pci_dev)
+{
+ VirtIOPCIProxy *proxy = DO_UPCAST(VirtIOPCIProxy, pci_dev, pci_dev);
+ VirtIODevice *vdev;
+
+ vdev = virtio_rng_init(&pci_dev->qdev, &proxy->rng);
+ if (!vdev) {
+ return -1;
+ }
+ virtio_init_pci(proxy, vdev);
+ return 0;
+}
+
+static void virtio_rng_exit_pci(PCIDevice *pci_dev)
+{
+ VirtIOPCIProxy *proxy = DO_UPCAST(VirtIOPCIProxy, pci_dev, pci_dev);
+
+ virtio_pci_stop_ioeventfd(proxy);
+ virtio_rng_exit(proxy->vdev);
+ virtio_exit_pci(pci_dev);
+}
+
static Property virtio_blk_properties[] = {
DEFINE_PROP_HEX32("class", VirtIOPCIProxy, class_code, 0),
DEFINE_BLOCK_PROPERTIES(VirtIOPCIProxy, blk.conf),
@@ -1010,6 +1032,43 @@ static TypeInfo virtio_balloon_info = {
.class_init = virtio_balloon_class_init,
};
+static void virtio_rng_initfn(Object *obj)
+{
+ PCIDevice *pci_dev = PCI_DEVICE(obj);
+ VirtIOPCIProxy *proxy = DO_UPCAST(VirtIOPCIProxy, pci_dev, pci_dev);
+
+ object_property_add_link(obj, "rng", TYPE_RNG_BACKEND,
+ (Object **)&proxy->rng.rng, NULL);
+}
+
+static Property virtio_rng_properties[] = {
+ DEFINE_VIRTIO_COMMON_FEATURES(VirtIOPCIProxy, host_features),
+ DEFINE_PROP_END_OF_LIST(),
+};
+
+static void virtio_rng_class_init(ObjectClass *klass, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(klass);
+ PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
+
+ k->init = virtio_rng_init_pci;
+ k->exit = virtio_rng_exit_pci;
+ k->vendor_id = PCI_VENDOR_ID_REDHAT_QUMRANET;
+ k->device_id = PCI_DEVICE_ID_VIRTIO_RNG;
+ k->revision = VIRTIO_PCI_ABI_VERSION;
+ k->class_id = PCI_CLASS_OTHERS;
+ dc->reset = virtio_pci_reset;
+ dc->props = virtio_rng_properties;
+}
+
+static TypeInfo virtio_rng_info = {
+ .name = "virtio-rng-pci",
+ .parent = TYPE_PCI_DEVICE,
+ .instance_size = sizeof(VirtIOPCIProxy),
+ .instance_init = virtio_rng_initfn,
+ .class_init = virtio_rng_class_init,
+};
+
static int virtio_scsi_init_pci(PCIDevice *pci_dev)
{
VirtIOPCIProxy *proxy = DO_UPCAST(VirtIOPCIProxy, pci_dev, pci_dev);
@@ -1074,6 +1133,7 @@ static void virtio_pci_register_types(void)
type_register_static(&virtio_serial_info);
type_register_static(&virtio_balloon_info);
type_register_static(&virtio_scsi_info);
+ type_register_static(&virtio_rng_info);
}
type_init(virtio_pci_register_types)
diff --git a/hw/virtio-pci.h b/hw/virtio-pci.h
index ac9d522..b58d9a2 100644
--- a/hw/virtio-pci.h
+++ b/hw/virtio-pci.h
@@ -17,6 +17,7 @@
#include "virtio-blk.h"
#include "virtio-net.h"
+#include "virtio-rng.h"
#include "virtio-serial.h"
#include "virtio-scsi.h"
@@ -46,6 +47,7 @@ typedef struct {
virtio_serial_conf serial;
virtio_net_conf net;
VirtIOSCSIConf scsi;
+ VirtIORNGConf rng;
bool ioeventfd_disabled;
bool ioeventfd_started;
VirtIOIRQFD *vector_irqfd;
diff --git a/hw/virtio-rng.c b/hw/virtio-rng.c
new file mode 100644
index 0000000..290b2b6
--- /dev/null
+++ b/hw/virtio-rng.c
@@ -0,0 +1,149 @@
+/*
+ * A virtio device implementing a hardware random number generator.
+ *
+ * Copyright 2012 Red Hat, Inc.
+ * Copyright 2012 Amit Shah <amit.shah@redhat.com>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or
+ * (at your option) any later version. See the COPYING file in the
+ * top-level directory.
+ */
+
+#include "iov.h"
+#include "qdev.h"
+#include "virtio.h"
+#include "virtio-rng.h"
+#include "qemu/rng.h"
+
+typedef struct VirtIORNG {
+ VirtIODevice vdev;
+
+ DeviceState *qdev;
+
+ /* Only one vq - guest puts buffer(s) on it when it needs entropy */
+ VirtQueue *vq;
+
+ VirtIORNGConf *conf;
+
+ RngBackend *rng;
+} VirtIORNG;
+
+static bool is_guest_ready(VirtIORNG *vrng)
+{
+ if (virtio_queue_ready(vrng->vq)
+ && (vrng->vdev.status & VIRTIO_CONFIG_S_DRIVER_OK)) {
+ return true;
+ }
+ return false;
+}
+
+static size_t get_request_size(VirtQueue *vq)
+{
+ unsigned int in, out;
+
+ virtqueue_get_avail_bytes(vq, &in, &out);
+ return in;
+}
+
+/* Send data from a char device over to the guest */
+static void chr_read(void *opaque, const void *buf, size_t size)
+{
+ VirtIORNG *vrng = opaque;
+ VirtQueueElement elem;
+ size_t len;
+ int offset;
+
+ if (!is_guest_ready(vrng)) {
+ return;
+ }
+
+ offset = 0;
+ while (offset < size) {
+ if (!virtqueue_pop(vrng->vq, &elem)) {
+ break;
+ }
+ len = iov_from_buf(elem.in_sg, elem.in_num,
+ 0, buf + offset, size - offset);
+ offset += len;
+
+ virtqueue_push(vrng->vq, &elem, len);
+ }
+ virtio_notify(&vrng->vdev, vrng->vq);
+}
+
+static void handle_input(VirtIODevice *vdev, VirtQueue *vq)
+{
+ VirtIORNG *vrng = DO_UPCAST(VirtIORNG, vdev, vdev);
+ size_t size;
+
+ size = get_request_size(vq);
+ if (size) {
+ rng_backend_request_entropy(vrng->rng, size, chr_read, vrng);
+ }
+}
+
+static uint32_t get_features(VirtIODevice *vdev, uint32_t f)
+{
+ return f;
+}
+
+static void virtio_rng_save(QEMUFile *f, void *opaque)
+{
+ VirtIORNG *vrng = opaque;
+
+ virtio_save(&vrng->vdev, f);
+}
+
+static int virtio_rng_load(QEMUFile *f, void *opaque, int version_id)
+{
+ VirtIORNG *vrng = opaque;
+
+ if (version_id != 1) {
+ return -EINVAL;
+ }
+ virtio_load(&vrng->vdev, f);
+ return 0;
+}
+
+VirtIODevice *virtio_rng_init(DeviceState *dev, VirtIORNGConf *conf)
+{
+ VirtIORNG *vrng;
+ VirtIODevice *vdev;
+ Error *local_err = NULL;
+
+ vdev = virtio_common_init("virtio-rng", VIRTIO_ID_RNG, 0,
+ sizeof(VirtIORNG));
+
+ vrng = DO_UPCAST(VirtIORNG, vdev, vdev);
+
+ vrng->rng = conf->rng;
+ if (vrng->rng == NULL) {
+ qerror_report(QERR_INVALID_PARAMETER_VALUE, "rng", "a valid object");
+ return NULL;
+ }
+
+ rng_backend_open(vrng->rng, &local_err);
+ if (local_err) {
+ qerror_report_err(local_err);
+ error_free(local_err);
+ return NULL;
+ }
+
+ vrng->vq = virtio_add_queue(vdev, 8, handle_input);
+ vrng->vdev.get_features = get_features;
+
+ vrng->qdev = dev;
+ vrng->conf = conf;
+ register_savevm(dev, "virtio-rng", -1, 1, virtio_rng_save,
+ virtio_rng_load, vrng);
+
+ return vdev;
+}
+
+void virtio_rng_exit(VirtIODevice *vdev)
+{
+ VirtIORNG *vrng = DO_UPCAST(VirtIORNG, vdev, vdev);
+
+ unregister_savevm(vrng->qdev, "virtio-rng", vrng);
+ virtio_cleanup(vdev);
+}
diff --git a/hw/virtio-rng.h b/hw/virtio-rng.h
new file mode 100644
index 0000000..fbb0104
--- /dev/null
+++ b/hw/virtio-rng.h
@@ -0,0 +1,24 @@
+/*
+ * Virtio RNG Support
+ *
+ * Copyright Red Hat, Inc. 2012
+ * Copyright Amit Shah <amit.shah@redhat.com>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or
+ * (at your option) any later version. See the COPYING file in the
+ * top-level directory.
+ */
+
+#ifndef _QEMU_VIRTIO_RNG_H
+#define _QEMU_VIRTIO_RNG_H
+
+#include "qemu/rng.h"
+
+/* The Virtio ID for the virtio rng device */
+#define VIRTIO_ID_RNG 4
+
+struct VirtIORNGConf {
+ RngBackend *rng;
+};
+
+#endif
diff --git a/hw/virtio.h b/hw/virtio.h
index ac482be..df8d0f7 100644
--- a/hw/virtio.h
+++ b/hw/virtio.h
@@ -203,6 +203,8 @@ VirtIODevice *virtio_serial_init(DeviceState *dev, virtio_serial_conf *serial);
VirtIODevice *virtio_balloon_init(DeviceState *dev);
typedef struct VirtIOSCSIConf VirtIOSCSIConf;
VirtIODevice *virtio_scsi_init(DeviceState *dev, VirtIOSCSIConf *conf);
+typedef struct VirtIORNGConf VirtIORNGConf;
+VirtIODevice *virtio_rng_init(DeviceState *dev, VirtIORNGConf *conf);
#ifdef CONFIG_LINUX
VirtIODevice *virtio_9p_init(DeviceState *dev, V9fsConf *conf);
#endif
@@ -213,6 +215,7 @@ void virtio_blk_exit(VirtIODevice *vdev);
void virtio_serial_exit(VirtIODevice *vdev);
void virtio_balloon_exit(VirtIODevice *vdev);
void virtio_scsi_exit(VirtIODevice *vdev);
+void virtio_rng_exit(VirtIODevice *vdev);
#define DEFINE_VIRTIO_COMMON_FEATURES(_state, _field) \
DEFINE_PROP_BIT("indirect_desc", _state, _field, \
--
1.7.7.6
^ permalink raw reply related [flat|nested] 13+ messages in thread
* Re: [Qemu-devel] [PATCH 0/8] virtio-rng: hardware random number generator device
2012-10-26 11:01 [Qemu-devel] [PATCH 0/8] virtio-rng: hardware random number generator device Amit Shah
` (7 preceding siblings ...)
2012-10-26 11:01 ` [Qemu-devel] [PATCH 8/8] virtio-rng: hardware random number generator device Amit Shah
@ 2012-10-26 14:13 ` Paolo Bonzini
2012-10-26 15:14 ` Anthony Liguori
8 siblings, 1 reply; 13+ messages in thread
From: Paolo Bonzini @ 2012-10-26 14:13 UTC (permalink / raw)
To: Amit Shah; +Cc: qemu list, Anthony Liguori
Il 26/10/2012 13:01, Amit Shah ha scritto:
> Amit Shah (1):
> virtio-rng: hardware random number generator device
>
> Anthony Liguori (7):
> object: add object_property_add_bool (v2)
> qdev: add realized property and make adding child bus implied by
> realize
> vl: add -object option to create QOM objects from the command line
> vl: add -late-object to create QOM objects after machine init
> rng: add RndBackend abstract object class
> rng-urandom: add an RNG backend that uses /dev/urandom
> rng-egd: introduce EGD compliant RNG backend
Honestly I think this is overengineered.
I would instead have the following:
- a chardev that can read from a file (e.g. -chardev
file,path=/dev/urandom,read=on,id=urandom)
- a device that accepts a chardev and understands both egd and raw (e.g.
-device virtio-rng-pci,chardev=urandom,egd=off or -device
virtio-rng-pci,chardev=egdsock,egd=on).
- optionally, a chardev that can produce an endless stream of data via
rdrand.
And that's it.
Also, even if RngBackend goes in, there is no need for -late-object
right now, so I would not include it in this series.
Paolo
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [Qemu-devel] [PATCH 0/8] virtio-rng: hardware random number generator device
2012-10-26 14:13 ` [Qemu-devel] [PATCH 0/8] " Paolo Bonzini
@ 2012-10-26 15:14 ` Anthony Liguori
2012-10-26 15:28 ` Paolo Bonzini
0 siblings, 1 reply; 13+ messages in thread
From: Anthony Liguori @ 2012-10-26 15:14 UTC (permalink / raw)
To: Paolo Bonzini, Amit Shah; +Cc: qemu list
Paolo Bonzini <pbonzini@redhat.com> writes:
> Il 26/10/2012 13:01, Amit Shah ha scritto:
>> Amit Shah (1):
>> virtio-rng: hardware random number generator device
>>
>> Anthony Liguori (7):
>> object: add object_property_add_bool (v2)
>> qdev: add realized property and make adding child bus implied by
>> realize
>> vl: add -object option to create QOM objects from the command line
>> vl: add -late-object to create QOM objects after machine init
>> rng: add RndBackend abstract object class
>> rng-urandom: add an RNG backend that uses /dev/urandom
>> rng-egd: introduce EGD compliant RNG backend
>
> Honestly I think this is overengineered.
>
> I would instead have the following:
>
> - a chardev that can read from a file (e.g. -chardev
> file,path=/dev/urandom,read=on,id=urandom)
Then your multiplexing lots of logic into the chardev layer.
Three of these patches can be dropped. See the series I sent out.
Regards,
Anthony Liguori
> - a device that accepts a chardev and understands both egd and raw
> (e.g.
> -device virtio-rng-pci,chardev=urandom,egd=off or -device
> virtio-rng-pci,chardev=egdsock,egd=on).
>
> - optionally, a chardev that can produce an endless stream of data via
> rdrand.
>
> And that's it.
>
> Also, even if RngBackend goes in, there is no need for -late-object
> right now, so I would not include it in this series.
>
> Paolo
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [Qemu-devel] [PATCH 0/8] virtio-rng: hardware random number generator device
2012-10-26 15:14 ` Anthony Liguori
@ 2012-10-26 15:28 ` Paolo Bonzini
2012-10-26 17:29 ` Anthony Liguori
0 siblings, 1 reply; 13+ messages in thread
From: Paolo Bonzini @ 2012-10-26 15:28 UTC (permalink / raw)
To: Anthony Liguori; +Cc: Amit Shah, qemu list
Il 26/10/2012 17:14, Anthony Liguori ha scritto:
>> > I would instead have the following:
>> >
>> > - a chardev that can read from a file (e.g. -chardev
>> > file,path=/dev/urandom,read=on,id=urandom)
> Then your multiplexing lots of logic into the chardev layer.
Then call it -chardev filein,path=/dev/urandom,id=urandom. :)
> Three of these patches can be dropped. See the series I sent out.
Same comments apply there...
Paolo
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [Qemu-devel] [PATCH 0/8] virtio-rng: hardware random number generator device
2012-10-26 15:28 ` Paolo Bonzini
@ 2012-10-26 17:29 ` Anthony Liguori
0 siblings, 0 replies; 13+ messages in thread
From: Anthony Liguori @ 2012-10-26 17:29 UTC (permalink / raw)
To: Paolo Bonzini; +Cc: Amit Shah, qemu list
Paolo Bonzini <pbonzini@redhat.com> writes:
> Il 26/10/2012 17:14, Anthony Liguori ha scritto:
>>> > I would instead have the following:
>>> >
>>> > - a chardev that can read from a file (e.g. -chardev
>>> > file,path=/dev/urandom,read=on,id=urandom)
>> Then your multiplexing lots of logic into the chardev layer.
>
> Then call it -chardev filein,path=/dev/urandom,id=urandom. :)
Let's move this to my thread please...
Regards,
Anthony Liguori
>
>> Three of these patches can be dropped. See the series I sent out.
>
> Same comments apply there...
>
> Paolo
^ permalink raw reply [flat|nested] 13+ messages in thread