entropy(9): Lock the per-CPU state in entropy_account_cpu.

This was previously called with the per-CPU state locked, which
worked fine as long as the global entropy lock was a spin lock so
acquiring it would never sleep.  Now it's an adaptive lock, so it's
not safe to take with the per-CPU state lock -- but we still need to
prevent reentrant access to the per-CPU entropy pool by interrupt
handlers while we're extracting from it.  So now the logic for
entering a sample is:

- lock per-CPU state
- entpool_enter
- unlock per-CPU state
- if anything pending on this CPU and it's time to consolidate:
  - lock global entropy state
  - lock per-CPU state
  - transfer
  - unlock per-CPU state
  - unlock global entropy state
This commit is contained in:
riastradh 2022-03-20 13:17:32 +00:00
parent 450311ec18
commit 260710e2b4
1 changed files with 11 additions and 6 deletions

View File

@ -1,4 +1,4 @@
/* $NetBSD: kern_entropy.c,v 1.43 2022/03/20 13:17:09 riastradh Exp $ */
/* $NetBSD: kern_entropy.c,v 1.44 2022/03/20 13:17:32 riastradh Exp $ */
/*-
* Copyright (c) 2019 The NetBSD Foundation, Inc.
@ -75,7 +75,7 @@
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: kern_entropy.c,v 1.43 2022/03/20 13:17:09 riastradh Exp $");
__KERNEL_RCSID(0, "$NetBSD: kern_entropy.c,v 1.44 2022/03/20 13:17:32 riastradh Exp $");
#include <sys/param.h>
#include <sys/types.h>
@ -728,8 +728,9 @@ entropy_ready(void)
static void
entropy_account_cpu(struct entropy_cpu *ec)
{
struct entropy_cpu_lock lock;
struct entropy_cpu *ec0;
unsigned diff;
int s;
KASSERT(E->stage >= ENTROPY_WARM);
@ -742,9 +743,13 @@ entropy_account_cpu(struct entropy_cpu *ec)
__predict_true((time_uptime - E->timestamp) <= 60))
return;
/* Consider consolidation, under the lock. */
/*
* Consider consolidation, under the global lock and with the
* per-CPU state locked.
*/
mutex_enter(&E->lock);
s = splsoftserial();
ec0 = entropy_cpu_get(&lock);
KASSERT(ec0 == ec);
if (E->needed != 0 && E->needed <= ec->ec_pending) {
/*
* If we have not yet attained full entropy but we can
@ -799,7 +804,7 @@ entropy_account_cpu(struct entropy_cpu *ec)
entropy_partial_evcnt.ev_count++;
}
}
splx(s);
entropy_cpu_put(&lock, ec);
mutex_exit(&E->lock);
}