aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--sys/dev/random/randomdev.c68
-rw-r--r--sys/kern/kern_intr.c4
-rw-r--r--sys/kern/subr_witness.c2
3 files changed, 58 insertions, 16 deletions
diff --git a/sys/dev/random/randomdev.c b/sys/dev/random/randomdev.c
index 68793e545524..8086841efce8 100644
--- a/sys/dev/random/randomdev.c
+++ b/sys/dev/random/randomdev.c
@@ -78,12 +78,19 @@ static void random_write_internal(void *, int);
MALLOC_DEFINE(M_ENTROPY, "entropy", "Entropy harvesting buffers");
-/* FIFO queues holding harvested entropy */
-static struct harvestfifo {
+/* Lockable FIFO queue holding entropy buffers */
+struct entropyfifo {
struct mtx lock;
int count;
STAILQ_HEAD(harvestlist, harvest) head;
-} harvestfifo[ENTROPYSOURCE];
+};
+
+/* Empty entropy buffers */
+static struct entropyfifo emptyfifo;
+#define EMPTYBUFFERS 1024
+
+/* Harvested entropy */
+static struct entropyfifo harvestfifo[ENTROPYSOURCE];
static struct random_systat {
u_int seeded; /* 0 causes blocking 1 allows normal output */
@@ -239,10 +246,20 @@ random_modevent(module_t mod __unused, int type, void *data __unused)
random_systat.seeded = 1;
/* Initialise the harvest fifos */
+ STAILQ_INIT(&emptyfifo.head);
+ emptyfifo.count = 0;
+ mtx_init(&emptyfifo.lock, "entropy harvest buffers", NULL,
+ MTX_SPIN);
+ for (i = 0; i < EMPTYBUFFERS; i++) {
+ np = malloc(sizeof(struct harvest), M_ENTROPY,
+ M_WAITOK);
+ STAILQ_INSERT_TAIL(&emptyfifo.head, np, next);
+ }
for (i = 0; i < ENTROPYSOURCE; i++) {
STAILQ_INIT(&harvestfifo[i].head);
harvestfifo[i].count = 0;
- mtx_init(&harvestfifo[i].lock, "entropy harvest", NULL, MTX_DEF);
+ mtx_init(&harvestfifo[i].lock, "entropy harvest", NULL,
+ MTX_SPIN);
}
if (bootverbose)
@@ -274,6 +291,12 @@ random_modevent(module_t mod __unused, int type, void *data __unused)
tsleep((void *)&random_kthread_control, PUSER, "term", 0);
/* Destroy the harvest fifos */
+ while (!STAILQ_EMPTY(&emptyfifo.head)) {
+ np = STAILQ_FIRST(&emptyfifo.head);
+ STAILQ_REMOVE_HEAD(&emptyfifo.head, next);
+ free(np, M_ENTROPY);
+ }
+ mtx_destroy(&emptyfifo.lock);
for (i = 0; i < ENTROPYSOURCE; i++) {
while (!STAILQ_EMPTY(&harvestfifo[i].head)) {
np = STAILQ_FIRST(&harvestfifo[i].head);
@@ -318,7 +341,7 @@ random_kthread(void *arg __unused)
found = 0;
/* Lock up queue draining */
- mtx_lock(&harvestfifo[source].lock);
+ mtx_lock_spin(&harvestfifo[source].lock);
if (!STAILQ_EMPTY(&harvestfifo[source].head)) {
@@ -327,17 +350,26 @@ random_kthread(void *arg __unused)
event = STAILQ_FIRST(&harvestfifo[source].head);
STAILQ_REMOVE_HEAD(&harvestfifo[source].head,
next);
+
active = found = 1;
}
/* Unlock the queue */
- mtx_unlock(&harvestfifo[source].lock);
+ mtx_unlock_spin(&harvestfifo[source].lock);
/* Deal with the event and dispose of it */
if (found) {
+
random_process_event(event);
- free(event, M_ENTROPY);
+
+ /* Lock the empty event buffer fifo */
+ mtx_lock_spin(&emptyfifo.lock);
+
+ STAILQ_INSERT_TAIL(&emptyfifo.head, event, next);
+
+ mtx_unlock_spin(&emptyfifo.lock);
+
}
}
@@ -362,14 +394,26 @@ random_harvest_internal(u_int64_t somecounter, void *entropy, u_int count,
struct harvest *event;
/* Lock the particular fifo */
- mtx_lock(&harvestfifo[origin].lock);
+ mtx_lock_spin(&harvestfifo[origin].lock);
- /* Don't make the harvest queues too big - memory is precious */
+ /* Don't make the harvest queues too big - help to prevent
+ * low-grade entropy swamping
+ */
if (harvestfifo[origin].count < RANDOM_FIFO_MAX) {
- event = malloc(sizeof(struct harvest), M_ENTROPY, M_NOWAIT);
+ /* Lock the empty event buffer fifo */
+ mtx_lock_spin(&emptyfifo.lock);
+
+ if (!STAILQ_EMPTY(&emptyfifo.head)) {
+ event = STAILQ_FIRST(&emptyfifo.head);
+ STAILQ_REMOVE_HEAD(&emptyfifo.head, next);
+ }
+ else
+ event = NULL;
+
+ mtx_unlock_spin(&emptyfifo.lock);
- /* If we can't malloc() a buffer, tough */
+ /* If we didn't obtain a buffer, tough */
if (event) {
/* Add the harvested data to the fifo */
@@ -389,7 +433,7 @@ random_harvest_internal(u_int64_t somecounter, void *entropy, u_int count,
}
- mtx_unlock(&harvestfifo[origin].lock);
+ mtx_unlock_spin(&harvestfifo[origin].lock);
}
diff --git a/sys/kern/kern_intr.c b/sys/kern/kern_intr.c
index 87b3c9b9c3a4..e42cd10385cc 100644
--- a/sys/kern/kern_intr.c
+++ b/sys/kern/kern_intr.c
@@ -356,9 +356,7 @@ ok:
int
ithread_schedule(struct ithd *ithread, int do_switch)
{
-#if 0
struct int_entropy entropy;
-#endif
struct thread *td;
struct thread *ctd;
struct proc *p;
@@ -370,7 +368,6 @@ ithread_schedule(struct ithd *ithread, int do_switch)
return (EINVAL);
ctd = curthread;
-#if 0
/*
* If any of the handlers for this ithread claim to be good
* sources of entropy, then gather some.
@@ -381,7 +378,6 @@ ithread_schedule(struct ithd *ithread, int do_switch)
random_harvest(&entropy, sizeof(entropy), 2, 0,
RANDOM_INTERRUPT);
}
-#endif
td = ithread->it_td;
p = td->td_proc;
diff --git a/sys/kern/subr_witness.c b/sys/kern/subr_witness.c
index 28d56059a36a..02ba3a1481a2 100644
--- a/sys/kern/subr_witness.c
+++ b/sys/kern/subr_witness.c
@@ -288,6 +288,8 @@ static struct witness_order_list_entry order_lists[] = {
{ "turnstile chain", &lock_class_mtx_spin },
{ "td_contested", &lock_class_mtx_spin },
{ "callout", &lock_class_mtx_spin },
+ { "entropy harvest", &lock_class_mtx_spin },
+ { "entropy harvest buffers", &lock_class_mtx_spin },
/*
* leaf locks
*/