Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F142653403
D20419.id57929.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
4 KB
Referenced Files
None
Subscribers
None
D20419.id57929.diff
View Options
Index: sys/dev/virtio/random/virtio_random.c
===================================================================
--- sys/dev/virtio/random/virtio_random.c
+++ sys/dev/virtio/random/virtio_random.c
@@ -33,7 +33,10 @@
#include <sys/param.h>
#include <sys/kernel.h>
+#include <sys/lock.h>
+#include <sys/malloc.h>
#include <sys/module.h>
+#include <sys/mutex.h>
#include <sys/sglist.h>
#include <sys/callout.h>
#include <sys/random.h>
@@ -42,13 +45,15 @@
#include <machine/resource.h>
#include <sys/bus.h>
+#include <dev/random/randomdev.h>
+#include <dev/random/random_harvestq.h>
#include <dev/virtio/virtio.h>
#include <dev/virtio/virtqueue.h>
struct vtrnd_softc {
uint64_t vtrnd_features;
- struct callout vtrnd_callout;
struct virtqueue *vtrnd_vq;
+ struct mtx vtrnd_lock;
};
static int vtrnd_probe(device_t);
@@ -57,8 +62,8 @@
static void vtrnd_negotiate_features(device_t);
static int vtrnd_alloc_virtqueue(device_t);
-static void vtrnd_harvest(struct vtrnd_softc *);
-static void vtrnd_timer(void *);
+static int vtrnd_harvest(struct vtrnd_softc *, void *, size_t);
+static unsigned vtrnd_read(void *, unsigned);
#define VTRND_FEATURES 0
@@ -66,6 +71,15 @@
{ 0, NULL }
};
+static struct random_source random_vtrnd = {
+ .rs_ident = "VirtIO Entropy Adapter",
+ .rs_source = RANDOM_PURE_VIRTIO,
+ .rs_read = vtrnd_read,
+};
+
+/* Kludge for API limitations of random(4). */
+static struct vtrnd_softc *g_vtrnd_softc = NULL;
+
static device_method_t vtrnd_methods[] = {
/* Device methods. */
DEVMETHOD(device_probe, vtrnd_probe),
@@ -105,7 +119,7 @@
sc = device_get_softc(dev);
- callout_init(&sc->vtrnd_callout, 1);
+ mtx_init(&sc->vtrnd_lock, "vtrnd lock", NULL, MTX_DEF);
virtio_set_feature_desc(dev, vtrnd_feature_desc);
vtrnd_negotiate_features(dev);
@@ -116,7 +130,11 @@
goto fail;
}
- callout_reset(&sc->vtrnd_callout, 5 * hz, vtrnd_timer, sc);
+ if (g_vtrnd_softc == NULL) {
+ g_vtrnd_softc = sc;
+ wmb();
+ random_source_register(&random_vtrnd);
+ }
fail:
if (error)
@@ -131,8 +149,20 @@
struct vtrnd_softc *sc;
sc = device_get_softc(dev);
-
- callout_drain(&sc->vtrnd_callout);
+ mtx_lock(&sc->vtrnd_lock);
+ if (g_vtrnd_softc == sc) {
+ random_source_deregister(&random_vtrnd);
+ g_vtrnd_softc = NULL;
+ /*
+ * Unfortunately, deregister does not guarantee our source
+ * callback will not be invoked after it returns. Use a kludge
+ * to prevent some, but not all, possible races.
+ */
+ msleep_sbt(&g_vtrnd_softc, &sc->vtrnd_lock, 0, "vtrnddet",
+ mstosbt(50), 0, C_HARDCLOCK);
+ }
+ mtx_unlock(&sc->vtrnd_lock);
+ mtx_destroy(&sc->vtrnd_lock);
return (0);
}
@@ -160,26 +190,29 @@
return (virtio_alloc_virtqueues(dev, 0, 1, &vq_info));
}
-static void
-vtrnd_harvest(struct vtrnd_softc *sc)
+static int
+vtrnd_harvest(struct vtrnd_softc *sc, void *buf, size_t sz)
{
struct sglist_seg segs[1];
struct sglist sg;
struct virtqueue *vq;
- uint32_t value;
+ uint32_t value[HARVESTSIZE] __aligned(sizeof(uint32_t) * HARVESTSIZE);
int error;
- vq = sc->vtrnd_vq;
+ _Static_assert(sizeof(value) < PAGE_SIZE, "sglist assumption");
sglist_init(&sg, 1, segs);
- error = sglist_append(&sg, &value, sizeof(value));
- KASSERT(error == 0 && sg.sg_nseg == 1,
- ("%s: error %d adding buffer to sglist", __func__, error));
+ error = sglist_append(&sg, value, sz);
+ if (error != 0)
+ panic("%s: sglist_append error=%d", __func__, error);
+
+ mtx_lock(&sc->vtrnd_lock);
+ vq = sc->vtrnd_vq;
+ KASSERT(virtqueue_empty(vq), ("%s: non-empty queue", __func__));
- if (!virtqueue_empty(vq))
- return;
- if (virtqueue_enqueue(vq, &value, &sg, 0, 1) != 0)
- return;
+ error = virtqueue_enqueue(vq, buf, &sg, 0, 1);
+ if (error != 0)
+ return (error);
/*
* Poll for the response, but the command is likely already
@@ -187,17 +220,26 @@
*/
virtqueue_notify(vq);
virtqueue_poll(vq, NULL);
+ mtx_unlock(&sc->vtrnd_lock);
- random_harvest_queue(&value, sizeof(value), RANDOM_PURE_VIRTIO);
+ memcpy(buf, value, sz);
+ explicit_bzero(value, sz);
+ return (0);
}
-static void
-vtrnd_timer(void *xsc)
+static unsigned
+vtrnd_read(void *buf, unsigned sz)
{
struct vtrnd_softc *sc;
+ int error;
+
+ sc = g_vtrnd_softc;
+ if (sc == NULL)
+ return (0);
- sc = xsc;
+ error = vtrnd_harvest(sc, buf, sz);
+ if (error != 0)
+ return (0);
- vtrnd_harvest(sc);
- callout_schedule(&sc->vtrnd_callout, 5 * hz);
+ return (sz);
}
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Thu, Jan 22, 9:50 PM (5 h, 2 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
27864399
Default Alt Text
D20419.id57929.diff (4 KB)
Attached To
Mode
D20419: virtio_random(4): Fix random(4) integration
Attached
Detach File
Event Timeline
Log In to Comment