On (Fri) 26 Oct 2012 [09:43:34], Anthony Liguori wrote: > Hi, > > This series implements the backend and frontend infrastructure for virtio-rng. > This is similar to previous series sent out by both Amit and myself although > it > has been trimmed down considerably. > > In terms of backends, a file and EGD backend are supported. The file defaults > to /dev/random based on the feedback from Peter. It's still possible to > support > /dev/urandom though as an entropy source by overriding the file name. > > I think this series is ready to merge.
I have a small diff to this series that I had merged in mine. Please apply to your tree as well. (Gets rid of savevm/loadvm complexities by using the new virtqueue_get_avail_bytes(), fixes typos/whitespace in rng.h) diff --git b/hw/virtio-rng.c a/hw/virtio-rng.c index b7fb5e9..290b2b6 100644 --- b/hw/virtio-rng.c +++ a/hw/virtio-rng.c @@ -22,14 +22,9 @@ typedef struct VirtIORNG { /* 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; @@ -42,23 +37,19 @@ static bool is_guest_ready(VirtIORNG *vrng) return false; } -static size_t pop_an_elem(VirtIORNG *vrng) +static size_t get_request_size(VirtQueue *vq) { - size_t size; + unsigned int in, out; - 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; + 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; @@ -68,27 +59,16 @@ static void chr_read(void *opaque, const void *buf, size_t size) offset = 0; while (offset < size) { - if (!pop_an_elem(vrng)) { + if (!virtqueue_pop(vrng->vq, &elem)) { break; } - len = iov_from_buf(vrng->elem.in_sg, vrng->elem.in_num, + len = iov_from_buf(elem.in_sg, elem.in_num, 0, buf + offset, size - offset); offset += len; - virtqueue_push(vrng->vq, &vrng->elem, len); - vrng->popped = false; + virtqueue_push(vrng->vq, &elem, len); } 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); - } } static void handle_input(VirtIODevice *vdev, VirtQueue *vq) @@ -96,7 +76,7 @@ static void handle_input(VirtIODevice *vdev, VirtQueue *vq) VirtIORNG *vrng = DO_UPCAST(VirtIORNG, vdev, vdev); size_t size; - size = pop_an_elem(vrng); + size = get_request_size(vq); if (size) { rng_backend_request_entropy(vrng->rng, size, chr_read, vrng); } @@ -112,23 +92,6 @@ 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) { - int i; - - qemu_put_be32(f, vrng->elem.index); - - qemu_put_be32(f, vrng->elem.in_num); - for (i = 0; i < vrng->elem.in_num; i++) { - qemu_put_be64(f, vrng->elem.in_addr[i]); - } - - qemu_put_be32(f, vrng->elem.out_num); - for (i = 0; i < vrng->elem.out_num; i++) { - qemu_put_be64(f, vrng->elem.out_addr[i]); - } - } } static int virtio_rng_load(QEMUFile *f, void *opaque, int version_id) @@ -139,30 +102,6 @@ static int virtio_rng_load(QEMUFile *f, void *opaque, int version_id) return -EINVAL; } virtio_load(&vrng->vdev, f); - - vrng->popped = qemu_get_byte(f); - if (vrng->popped) { - int i; - - vrng->elem.index = qemu_get_be32(f); - - vrng->elem.in_num = qemu_get_be32(f); - g_assert(vrng->elem.in_num < VIRTQUEUE_MAX_SIZE); - for (i = 0; i < vrng->elem.in_num; i++) { - vrng->elem.in_addr[i] = qemu_get_be64(f); - } - - vrng->elem.out_num = qemu_get_be32(f); - g_assert(vrng->elem.out_num < VIRTQUEUE_MAX_SIZE); - for (i = 0; i < vrng->elem.out_num; i++) { - vrng->elem.out_addr[i] = qemu_get_be64(f); - } - - virtqueue_map_sg(vrng->elem.in_sg, vrng->elem.in_addr, - vrng->elem.in_num, 1); - virtqueue_map_sg(vrng->elem.out_sg, vrng->elem.out_addr, - vrng->elem.out_num, 0); - } return 0; } @@ -195,7 +134,6 @@ VirtIODevice *virtio_rng_init(DeviceState *dev, VirtIORNGConf *conf) vrng->qdev = dev; vrng->conf = conf; - vrng->popped = false; register_savevm(dev, "virtio-rng", -1, 1, virtio_rng_save, virtio_rng_load, vrng); diff --git b/include/qemu/rng.h a/include/qemu/rng.h index 7e9d672..9836463 100644 --- b/include/qemu/rng.h +++ a/include/qemu/rng.h @@ -61,10 +61,10 @@ struct RngBackend * 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 appropriate. + * 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 at a value greater than 0. + * but will pass a a value greater than 0. */ void rng_backend_request_entropy(RngBackend *s, size_t size, EntropyReceiveFunc *receive_entropy, @@ -87,7 +87,7 @@ void rng_backend_cancel_requests(RngBackend *s); * * 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 Amit