Page MenuHomeFreeBSD

D38898.diff
No OneTemporary

D38898.diff

diff --git a/sys/dev/virtio/random/virtio_random.c b/sys/dev/virtio/random/virtio_random.c
--- a/sys/dev/virtio/random/virtio_random.c
+++ b/sys/dev/virtio/random/virtio_random.c
@@ -56,7 +56,11 @@
struct virtqueue *vtrnd_vq;
eventhandler_tag eh;
bool inactive;
+ struct sglist_seg vtrnd_segs[1];
+ struct sglist vtrnd_sg;
+ uint32_t vtrnd_value[HARVESTSIZE] __aligned(sizeof(uint32_t) * HARVESTSIZE);
};
+_Static_assert(sizeof(((struct vtrnd_softc *)NULL)->vtrnd_value) < PAGE_SIZE, "sglist assumption");
static int vtrnd_modevent(module_t, int, void *);
@@ -69,6 +73,7 @@
static int vtrnd_setup_features(struct vtrnd_softc *);
static int vtrnd_alloc_virtqueue(struct vtrnd_softc *);
static int vtrnd_harvest(struct vtrnd_softc *, void *, size_t *);
+static void vtrnd_enqueue(struct vtrnd_softc *sc);
static unsigned vtrnd_read(void *, unsigned);
#define VTRND_FEATURES 0
@@ -176,6 +181,8 @@
sc->inactive = false;
random_source_register(&random_vtrnd);
+ vtrnd_enqueue(sc);
+
fail:
if (error)
vtrnd_detach(dev);
@@ -187,6 +194,7 @@
vtrnd_detach(device_t dev)
{
struct vtrnd_softc *sc;
+ uint32_t rdlen;
sc = device_get_softc(dev);
KASSERT(
@@ -199,6 +207,10 @@
sc->eh = NULL;
}
random_source_deregister(&random_vtrnd);
+
+ /* clear the queue */
+ virtqueue_poll(sc->vtrnd_vq, &rdlen);
+
atomic_store_explicit(&g_vtrnd_softc, NULL, memory_order_release);
return (0);
}
@@ -253,49 +265,52 @@
return (virtio_alloc_virtqueues(dev, 0, 1, &vq_info));
}
-static int
-vtrnd_harvest(struct vtrnd_softc *sc, void *buf, size_t *sz)
+static void
+vtrnd_enqueue(struct vtrnd_softc *sc)
{
- struct sglist_seg segs[1];
- struct sglist sg;
struct virtqueue *vq;
- uint32_t value[HARVESTSIZE] __aligned(sizeof(uint32_t) * HARVESTSIZE);
- uint32_t rdlen;
+ struct sglist *sg;
int error;
- _Static_assert(sizeof(value) < PAGE_SIZE, "sglist assumption");
-
- if (sc->inactive)
- return (EDEADLK);
+ sg = &sc->vtrnd_sg;
+ vq = sc->vtrnd_vq;
- sglist_init(&sg, 1, segs);
- error = sglist_append(&sg, value, *sz);
+ sglist_init(sg, 1, sc->vtrnd_segs);
+ error = sglist_append(sg, sc->vtrnd_value, sizeof(sc->vtrnd_value));
if (error != 0)
panic("%s: sglist_append error=%d", __func__, error);
- vq = sc->vtrnd_vq;
KASSERT(virtqueue_empty(vq), ("%s: non-empty queue", __func__));
- error = virtqueue_enqueue(vq, buf, &sg, 0, 1);
- if (error != 0)
- return (error);
+ error = virtqueue_enqueue(vq, sc, sg, 0, 1);
+ KASSERT(error == 0, ("%s: virtqueue_enqueue returned error: %d", __func__, error));
- /*
- * Poll for the response, but the command is likely already
- * done when we return from the notify.
- */
virtqueue_notify(vq);
- virtqueue_poll(vq, &rdlen);
+}
- if (rdlen > *sz)
- panic("%s: random device wrote %zu bytes beyond end of provided"
- " buffer %p:%zu", __func__, (size_t)rdlen - *sz,
- (void *)value, *sz);
- else if (rdlen == 0)
+int
+vtrnd_harvest(struct vtrnd_softc *sc, void *buf, size_t *sz)
+{
+ struct virtqueue *vq;
+ void *cookie;
+ uint32_t rdlen;
+
+ if (sc->inactive)
+ return (EDEADLK);
+
+ vq = sc->vtrnd_vq;
+
+ cookie = virtqueue_dequeue(vq, &rdlen);
+
+ if (cookie == NULL)
return (EAGAIN);
+
*sz = MIN(rdlen, *sz);
- memcpy(buf, value, *sz);
- explicit_bzero(value, *sz);
+ memcpy(buf, sc->vtrnd_value, *sz);
+ explicit_bzero(sc->vtrnd_value, *sz);
+
+ vtrnd_enqueue(sc);
+
return (0);
}

File Metadata

Mime Type
text/plain
Expires
Fri, Dec 27, 10:56 AM (9 h, 50 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
15613559
Default Alt Text
D38898.diff (3 KB)

Event Timeline