Re: [Qemu-devel] [PATCH 4/4] virtio-rng: hardware random number generator device

2012-07-11 Thread Dor Laor

On 07/06/2012 03:06 PM, Amit Shah wrote:

On (Tue) 26 Jun 2012 [08:01:20], Anthony Liguori wrote:

On 06/26/2012 05:48 AM, Amit Shah wrote:

 On (Mon) 25 Jun 2012 [17:59:28], Anthony Liguori wrote:

 On 06/25/2012 05:46 PM, Anthony Liguori wrote:

 From: Amit Shahamit.s...@redhat.com

 

 diff --git a/hw/virtio-pci.c b/hw/virtio-pci.c

 

 +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;

 
 WHQL tends to get very particular about PCI classes.  Do we
 understand the implications of making this CLASS_OTHERS and WHQL?

 
 I've not asked around; will update with info when I get it.


Thanks.

... and I heard back: PCI_CLASS_OTHERS is fine; no problem.



Unclassified device (PCI_CLASS_OTHERS) is the easiest way to pass M$ 
WHQL. It doesn't do any functional tests to the device itself, unlike 
NICs/StorPort devices. If M$ had a specific entropy device type it would 
be good to use it but I doubt such exist.




Re: [Qemu-devel] [PATCH 4/4] virtio-rng: hardware random number generator device

2012-07-06 Thread Amit Shah
On (Tue) 26 Jun 2012 [08:01:20], Anthony Liguori wrote:
 On 06/26/2012 05:48 AM, Amit Shah wrote:
 On (Mon) 25 Jun 2012 [17:59:28], Anthony Liguori wrote:
 On 06/25/2012 05:46 PM, Anthony Liguori wrote:
 From: Amit Shahamit.s...@redhat.com
 
 diff --git a/hw/virtio-pci.c b/hw/virtio-pci.c
 
 +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;
 
 WHQL tends to get very particular about PCI classes.  Do we
 understand the implications of making this CLASS_OTHERS and WHQL?
 
 I've not asked around; will update with info when I get it.
 
 Thanks.

... and I heard back: PCI_CLASS_OTHERS is fine; no problem.

 +/* 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;
 +size_t len;
 +int offset;
 +
 +if (!is_guest_ready(vrng)) {
 +return;
 +}
 +
 +offset = 0;
 +while (offset   size) {
 +if (!pop_an_elem(vrng)) {
 +break;
 +}
 +len = iov_from_buf(vrng-elem.in_sg, vrng-elem.in_num,
 +   buf + offset, 0, size - offset);
 +offset += len;
 +
 +virtqueue_push(vrng-vq,vrng-elem, len);
 +vrng-popped = false;
 +}
 +virtio_notify(vrng-vdev, vrng-vq);
 +
 +/*
 + * Lastly, if we had multiple elems queued by the guest, and we
 + * didn't have enough data to fill them all, indicate we want more
 + * data.
 + */
 +len = pop_an_elem(vrng);
 +if (len) {
 +rng_backend_request_entropy(vrng-rng, size, chr_read, vrng);
 +}
 
 Because of this above while() loop, you won't see entropy requests
 for every request that comes from the guest depending on how data
 gets buffered in the socket.
 
 So the issue is we currently can't get the iov_size without popping
 the elem from the vq.
 
 I think we could split out some of the logic in virtqueue_pop to
 implement a virtqueue_peek().

Just sent out a series that adds virtqueue_get_avail_bytes() which
does this.  A rebased series on top of that eliminates the need for
popping and save/load of the elem.

Amit



Re: [Qemu-devel] [PATCH 4/4] virtio-rng: hardware random number generator device

2012-06-26 Thread Amit Shah
On (Mon) 25 Jun 2012 [17:59:28], Anthony Liguori wrote:
 On 06/25/2012 05:46 PM, Anthony Liguori wrote:
 From: Amit Shahamit.s...@redhat.com

 diff --git a/hw/virtio-pci.c b/hw/virtio-pci.c

 +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;
 
 WHQL tends to get very particular about PCI classes.  Do we
 understand the implications of making this CLASS_OTHERS and WHQL?

I've not asked around; will update with info when I get it.

 diff --git a/hw/virtio-rng.c b/hw/virtio-rng.c
 new file mode 100644
 index 000..a4c2ac1
 --- /dev/null
 +++ b/hw/virtio-rng.c
 @@ -0,0 +1,186 @@
 +/*
 + * A virtio device implementing a hardware random number generator.
 + *
 + * Copyright 2012 Red Hat, Inc.
 + * Copyright 2012 Amit Shahamit.s...@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;
 +VirtQueueElement elem;
 +
 +/* Config data for the device -- currently only chardev */
 +VirtIORNGConf *conf;
 +
 +/* Whether we've popped a vq element into 'elem' above */
 +bool popped;
 +
 +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 pop_an_elem(VirtIORNG *vrng)
 +{
 +size_t size;
 +
 +if (!vrng-popped  !virtqueue_pop(vrng-vq,vrng-elem)) {
 +return 0;
 +}
 +vrng-popped = true;
 +
 +size = iov_size(vrng-elem.in_sg, vrng-elem.in_num);
 +return size;
 +}
 +
 +/* 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;
 +size_t len;
 +int offset;
 +
 +if (!is_guest_ready(vrng)) {
 +return;
 +}
 +
 +offset = 0;
 +while (offset  size) {
 +if (!pop_an_elem(vrng)) {
 +break;
 +}
 +len = iov_from_buf(vrng-elem.in_sg, vrng-elem.in_num,
 +   buf + offset, 0, size - offset);
 +offset += len;
 +
 +virtqueue_push(vrng-vq,vrng-elem, len);
 +vrng-popped = false;
 +}
 +virtio_notify(vrng-vdev, vrng-vq);
 +
 +/*
 + * Lastly, if we had multiple elems queued by the guest, and we
 + * didn't have enough data to fill them all, indicate we want more
 + * data.
 + */
 +len = pop_an_elem(vrng);
 +if (len) {
 +rng_backend_request_entropy(vrng-rng, size, chr_read, vrng);
 +}
 
 Because of this above while() loop, you won't see entropy requests
 for every request that comes from the guest depending on how data
 gets buffered in the socket.

So the issue is we currently can't get the iov_size without popping
the elem from the vq.  If we had that, we would just send out the
request from handle_input(), and the save/load functions wouldn't have
to bother with the elem, too.

Given that we can't do that, restricting chr_read() to one iov seems
fine.

Note that there's a bug introduced in the
rng_backend_request_entropy() call above - it should advertise 'len'
instead of 'size' here.

 Things are simplified now because boundaries will be respected (they
 always would be with qemu_chr_can_read too FWIW).  We should have
 chr_read() process exactly one entropy request.  We should only have
 one pending entropy request at a time too.
 
 That eliminates the need for looping here and should simplify the whole code.
 
 +}
 +
 +static void handle_input(VirtIODevice *vdev, VirtQueue *vq)
 +{
 +VirtIORNG *vrng = DO_UPCAST(VirtIORNG, vdev, vdev);
 +size_t size;
 +
 +size = pop_an_elem(vrng);
 +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);
 +
 +qemu_put_byte(f, vrng-popped);
 +if (vrng-popped) {
 +qemu_put_buffer(f, (unsigned char *)vrng-elem,
 +sizeof(vrng-elem));
 +}
 
 Okay, new rule: if you copy a struct verbatim to savevm, your next 5
 patches will 

Re: [Qemu-devel] [PATCH 4/4] virtio-rng: hardware random number generator device

2012-06-26 Thread Anthony Liguori

On 06/26/2012 05:48 AM, Amit Shah wrote:

On (Mon) 25 Jun 2012 [17:59:28], Anthony Liguori wrote:

On 06/25/2012 05:46 PM, Anthony Liguori wrote:

From: Amit Shahamit.s...@redhat.com



diff --git a/hw/virtio-pci.c b/hw/virtio-pci.c



+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;


WHQL tends to get very particular about PCI classes.  Do we
understand the implications of making this CLASS_OTHERS and WHQL?


I've not asked around; will update with info when I get it.


Thanks.


diff --git a/hw/virtio-rng.c b/hw/virtio-rng.c
new file mode 100644
index 000..a4c2ac1
--- /dev/null
+++ b/hw/virtio-rng.c
@@ -0,0 +1,186 @@
+/*
+ * A virtio device implementing a hardware random number generator.
+ *
+ * Copyright 2012 Red Hat, Inc.
+ * Copyright 2012 Amit Shahamit.s...@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;
+VirtQueueElement elem;
+
+/* Config data for the device -- currently only chardev */
+VirtIORNGConf *conf;
+
+/* Whether we've popped a vq element into 'elem' above */
+bool popped;
+
+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 pop_an_elem(VirtIORNG *vrng)
+{
+size_t size;
+
+if (!vrng-popped   !virtqueue_pop(vrng-vq,vrng-elem)) {
+return 0;
+}
+vrng-popped = true;
+
+size = iov_size(vrng-elem.in_sg, vrng-elem.in_num);
+return size;
+}
+
+/* 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;
+size_t len;
+int offset;
+
+if (!is_guest_ready(vrng)) {
+return;
+}
+
+offset = 0;
+while (offset   size) {
+if (!pop_an_elem(vrng)) {
+break;
+}
+len = iov_from_buf(vrng-elem.in_sg, vrng-elem.in_num,
+   buf + offset, 0, size - offset);
+offset += len;
+
+virtqueue_push(vrng-vq,vrng-elem, len);
+vrng-popped = false;
+}
+virtio_notify(vrng-vdev, vrng-vq);
+
+/*
+ * Lastly, if we had multiple elems queued by the guest, and we
+ * didn't have enough data to fill them all, indicate we want more
+ * data.
+ */
+len = pop_an_elem(vrng);
+if (len) {
+rng_backend_request_entropy(vrng-rng, size, chr_read, vrng);
+}


Because of this above while() loop, you won't see entropy requests
for every request that comes from the guest depending on how data
gets buffered in the socket.


So the issue is we currently can't get the iov_size without popping
the elem from the vq.


I think we could split out some of the logic in virtqueue_pop to implement a 
virtqueue_peek().



If we had that, we would just send out the
request from handle_input(), and the save/load functions wouldn't have
to bother with the elem, too.

Given that we can't do that, restricting chr_read() to one iov seems
fine.

Note that there's a bug introduced in the
rng_backend_request_entropy() call above - it should advertise 'len'
instead of 'size' here.


Ah, good catch.  Thanks.




Things are simplified now because boundaries will be respected (they
always would be with qemu_chr_can_read too FWIW).  We should have
chr_read() process exactly one entropy request.  We should only have
one pending entropy request at a time too.

That eliminates the need for looping here and should simplify the whole code.


+}
+
+static void handle_input(VirtIODevice *vdev, VirtQueue *vq)
+{
+VirtIORNG *vrng = DO_UPCAST(VirtIORNG, vdev, vdev);
+size_t size;
+
+size = pop_an_elem(vrng);
+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);
+
+qemu_put_byte(f, vrng-popped);
+if (vrng-popped) {
+qemu_put_buffer(f, (unsigned char *)vrng-elem,
+sizeof(vrng-elem));
+}


Okay, new rule: if you copy a struct 

Re: [Qemu-devel] [PATCH 4/4] virtio-rng: hardware random number generator device

2012-06-26 Thread Amit Shah
On (Tue) 26 Jun 2012 [08:01:20], Anthony Liguori wrote:

 +/* 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;
 +size_t len;
 +int offset;
 +
 +if (!is_guest_ready(vrng)) {
 +return;
 +}
 +
 +offset = 0;
 +while (offset   size) {
 +if (!pop_an_elem(vrng)) {
 +break;
 +}
 +len = iov_from_buf(vrng-elem.in_sg, vrng-elem.in_num,
 +   buf + offset, 0, size - offset);
 +offset += len;
 +
 +virtqueue_push(vrng-vq,vrng-elem, len);
 +vrng-popped = false;
 +}
 +virtio_notify(vrng-vdev, vrng-vq);
 +
 +/*
 + * Lastly, if we had multiple elems queued by the guest, and we
 + * didn't have enough data to fill them all, indicate we want more
 + * data.
 + */
 +len = pop_an_elem(vrng);
 +if (len) {
 +rng_backend_request_entropy(vrng-rng, size, chr_read, vrng);
 +}
 
 Because of this above while() loop, you won't see entropy requests
 for every request that comes from the guest depending on how data
 gets buffered in the socket.
 
 So the issue is we currently can't get the iov_size without popping
 the elem from the vq.
 
 I think we could split out some of the logic in virtqueue_pop to
 implement a virtqueue_peek().

I remember vaguely I looked at it before, and can't recollect why I
didn't follow through with it.  Will re-look and note it.

 +
 +static void virtio_rng_save(QEMUFile *f, void *opaque)
 +{
 +VirtIORNG *vrng = opaque;
 +
 +virtio_save(vrng-vdev, f);
 +
 +qemu_put_byte(f, vrng-popped);
 +if (vrng-popped) {
 +qemu_put_buffer(f, (unsigned char *)vrng-elem,
 +sizeof(vrng-elem));
 +}
 
 Okay, new rule: if you copy a struct verbatim to savevm, your next 5
 patches will be automatically nacked.
 
 Seriously, this is an awful thing to do.  I don't care if we do it
 in other places in the code.  It's never the right thing to do.]
 
 Err, this came in with virtio-scsi too apparently.
 
 Paolo/Stefan, please fix this in virtio-scsi before the 1.2 release.
 This is really not something we want to have to maintain long term.
 
 This is an unpacked unaligned structure with non-fixed sized types
 in it. that are greater than a byte.  This breaks across endianness,
 compiler versions, etc.
 
 Any ideas how to get it done?  (CC'ed Juan).
 
 Just save the individual fields of the structure using the
 appropriate accessors.  Then you don't have to worry about alignment
 and endianness.

I think we need an accessor for the whole for VirtQueueElem.  That
keeps individual devices agnostic from struct changes.

Then, we would need a way to deal with the individual elements in that
struct, which is tricky.  There are pointers there.

 We can't change the existing devices (sans virtio-scsi) because it's
 now part of the ABI but we can avoid making the same mistakes again.

Yup.

Amit



Re: [Qemu-devel] [PATCH 4/4] virtio-rng: hardware random number generator device

2012-06-25 Thread Anthony Liguori

On 06/25/2012 05:46 PM, Anthony Liguori wrote:

From: Amit Shahamit.s...@redhat.com

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 Shahamit.s...@redhat.com
Signed-off-by: Anthony Liguorialigu...@us.ibm.com
---
aliguori: converted to new RngBackend interface
---
  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  |  186 ++
  hw/virtio-rng.h  |   24 +++
  hw/virtio.h  |3 +
  monitor.c|4 +-
  monitor.h|1 +
  11 files changed, 320 insertions(+), 1 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 3d77259..4634637 100644
--- a/hw/Makefile.objs
+++ b/hw/Makefile.objs
@@ -1,6 +1,7 @@
  hw-obj-y = usb/ ide/
  hw-obj-y += loader.o
  hw-obj-$(CONFIG_VIRTIO) += virtio-console.o
+hw-obj-$(CONFIG_VIRTIO) += virtio-rng.o
  hw-obj-$(CONFIG_VIRTIO_PCI) += virtio-pci.o
  hw-obj-y += fw_cfg.o
  hw-obj-$(CONFIG_PCI) += pci.o pci_bridge.o pci_bridge_dev.o
diff --git a/hw/pci.h b/hw/pci.h
index 7f223c0..cdcbe1d 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_SCSI0x1004
+#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 4d49b96..af7be91 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;
@@ -447,6 +460,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;
@@ -527,6 +563,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 9342eed..fe19830 100644
--- a/hw/virtio-pci.c
+++ b/hw/virtio-pci.c
@@ -933,6 +933,28 @@ static int virtio_balloon_exit_pci(PCIDevice *pci_dev)
  return 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 int virtio_rng_exit_pci(PCIDevice *pci_dev)
+{
+VirtIOPCIProxy *proxy = DO_UPCAST(VirtIOPCIProxy, pci_dev, pci_dev);
+
+