qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
* [Qemu-devel] [PATCH 0/8] virtio-rng: hardware random number generator device
@ 2012-10-26 11:01 Amit Shah
  2012-10-26 11:01 ` [Qemu-devel] [PATCH 1/8] object: add object_property_add_bool (v2) Amit Shah
                   ` (8 more replies)
  0 siblings, 9 replies; 13+ messages in thread
From: Amit Shah @ 2012-10-26 11:01 UTC (permalink / raw)
  To: Anthony Liguori; +Cc: Amit Shah, qemu list

Hello,

Reviving this series last sent by Anthony to the list.  The
differences are minimal from the time Anthony sent, just rebasing to
the current tree and fixing a couple of minor bugs.

I've not really looked in detail at the object patches -- mostly just
concerned about the device itself.

Please review and apply if appropriate.

Changes from last submission:
- Fix a few typos/whitespaces in rng.h
- Switch to virtqueue_get_avail_bytes(): helps remove the
  savevm/loadvm complexities and provides a cleaner interface
- Remove the older qevent hunks that got left behind
- Rebase to master
- Bugfix: rng_backend_request_entropy() in chr_read() should pass len,
  not size
- Do not request for more entropy in chr_read() once the current
  request is served; there are other ways this notification will go
  out.


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

 Makefile.objs          |    2 +
 backends/Makefile.objs |    1 +
 backends/rng-egd.c     |  215 ++++++++++++++++++++++++++++++++++++++++++++++++
 backends/rng-urandom.c |  144 ++++++++++++++++++++++++++++++++
 backends/rng.c         |   93 +++++++++++++++++++++
 hw/Makefile.objs       |    1 +
 hw/pci.h               |    1 +
 hw/qdev.c              |   36 ++++++++-
 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 +
 include/qemu/object.h  |   16 ++++
 include/qemu/rng.h     |   93 +++++++++++++++++++++
 qemu-config.c          |   20 +++++
 qemu-options.hx        |   20 +++++
 qom/object.c           |   56 +++++++++++++
 vl.c                   |   62 ++++++++++++++
 21 files changed, 1036 insertions(+), 1 deletions(-)
 create mode 100644 backends/Makefile.objs
 create mode 100644 backends/rng-egd.c
 create mode 100644 backends/rng-urandom.c
 create mode 100644 backends/rng.c
 create mode 100644 hw/virtio-rng.c
 create mode 100644 hw/virtio-rng.h
 create mode 100644 include/qemu/rng.h

-- 
1.7.7.6

^ permalink raw reply	[flat|nested] 13+ messages in thread

* [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

end of thread, other threads:[~2012-10-26 17:30 UTC | newest]

Thread overview: 13+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
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 ` [Qemu-devel] [PATCH 3/8] vl: add -object option to create QOM objects from the command line 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
2012-10-26 11:01 ` [Qemu-devel] [PATCH 5/8] rng: add RndBackend abstract object class Amit Shah
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 ` [Qemu-devel] [PATCH 7/8] rng-egd: introduce EGD compliant RNG backend 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
2012-10-26 15:14   ` Anthony Liguori
2012-10-26 15:28     ` Paolo Bonzini
2012-10-26 17:29       ` Anthony Liguori

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).