Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src-draft/trunk]: src/sys/arch/mips/cavium/dev Be a little more judicious wi...
details: https://anonhg.NetBSD.org/src-all/rev/debe22623b19
branches: trunk
changeset: 932658:debe22623b19
user: Taylor R Campbell <riastradh%NetBSD.org@localhost>
date: Wed May 13 16:07:07 2020 +0000
description:
Be a little more judicious with delays in octeon_rnm.
- Use cycle count busy loops, not microsecond delays.
- Yield if requested in the loop.
- Don't load twice as much data as intended!
diffstat:
sys/arch/mips/cavium/dev/octeon_rnm.c | 75 ++++++++++++++++++++++------------
1 files changed, 49 insertions(+), 26 deletions(-)
diffs (139 lines):
diff -r 1b32749f3ec0 -r debe22623b19 sys/arch/mips/cavium/dev/octeon_rnm.c
--- a/sys/arch/mips/cavium/dev/octeon_rnm.c Wed May 13 07:38:50 2020 +0000
+++ b/sys/arch/mips/cavium/dev/octeon_rnm.c Wed May 13 16:07:07 2020 +0000
@@ -105,9 +105,10 @@
//#define OCTEON_RNM_DEBUG
-#define ENT_DELAY_CLOCK 8 /* cycles for each RO sample */
+#define ENT_DELAY_CLOCK 8 /* cycles for each 64-bit RO sample batch */
#define RNG_DELAY_CLOCK 81 /* cycles for each SHA-1 output */
#define NROGROUPS 16
+#define RNG_FIFO_WORDS (512/sizeof(uint64_t))
struct octeon_rnm_softc {
bus_space_tag_t sc_bust;
@@ -126,6 +127,7 @@
static void octeon_rnm_raw_entropy(struct octeon_rnm_softc *, unsigned);
static uint64_t octeon_rnm_load(struct octeon_rnm_softc *);
static void octeon_rnm_iobdma(struct octeon_rnm_softc *, uint64_t *, unsigned);
+static void octeon_rnm_delay(uint32_t);
CFATTACH_DECL_NEW(octeon_rnm, sizeof(struct octeon_rnm_softc),
octeon_rnm_match, octeon_rnm_attach, NULL, NULL);
@@ -173,7 +175,7 @@
/*
* Reset the core, enable the RNG engine without entropy, wait
- * 81 cycles for it to warm up (round up to 1us), and get a
+ * 81 cycles for it to produce a single sample, and draw the
* deterministic sample to test.
*
* XXX Verify that the output matches the SHA-1 computation
@@ -181,7 +183,7 @@
*/
octeon_rnm_reset(sc);
octeon_rnm_conditioned_deterministic(sc);
- delay(1);
+ octeon_rnm_delay(RNG_DELAY_CLOCK*1);
sample = octeon_rnm_load(sc);
if (sample != expected)
aprint_error_dev(self, "self-test: read %016"PRIx64","
@@ -196,6 +198,7 @@
octeon_rnm_reset(sc);
sc->sc_rogroup = 0;
octeon_rnm_raw_entropy(sc, sc->sc_rogroup);
+ octeon_rnm_delay(ENT_DELAY_CLOCK*RNG_FIFO_WORDS);
/* Attach the rndsource. */
rndsource_setcb(&sc->sc_rndsrc, octeon_rnm_rng, sc);
@@ -211,23 +214,20 @@
uint64_t sample[32];
struct octeon_rnm_softc *sc = vsc;
size_t needed = NBBY*nbytes;
+ unsigned i;
- /*
- * Sample all of the ring oscillators at least once, while
- * preventing concurrent access to the FIFO out of paranoia.
- */
+ /* Sample the ring oscillators round-robin. */
mutex_enter(&sc->sc_lock);
- for (; needed; needed -= MIN(needed, NBBY*sizeof(sample)/BPB)) {
+ while (needed) {
/*
- * Make sure the FIFO is full. We need 8 cycles for
- * every 64 bits = 8 bytes, and the FIFO has 512 bytes,
- * for a total of 512 cycles; round that up to 2us,
- * under the assumption that the CPU runs at no less
- * than 256 MHz.
+ * Switch to the next RO group once we drain the FIFO.
+ * By the time rnd_add_data is done, we will have
+ * processed all 512 bytes of the FIFO. We assume it
+ * takes at least one cycle per byte (realistically,
+ * more like ~80cpb to draw from the FIFO and then
+ * process it with rnd_add_data), so there is no need
+ * for any other delays.
*/
- delay(2);
-
- /* Switch to the next RO group once we drain the FIFO. */
sc->sc_rogroup++;
sc->sc_rogroup %= NROGROUPS;
octeon_rnm_raw_entropy(sc, sc->sc_rogroup);
@@ -237,18 +237,24 @@
* 256 bytes because of limits on the CVMSEG buffer.
*/
CTASSERT(sizeof sample == 256);
- octeon_rnm_iobdma(sc, sample, __arraycount(sample));
+ CTASSERT(2*__arraycount(sample) == RNG_FIFO_WORDS);
+ for (i = 0; i < 2; i++) {
+ octeon_rnm_iobdma(sc, sample, __arraycount(sample));
#ifdef OCTEON_RNM_DEBUG
- hexdump(printf, "rnm", sample, sizeof sample);
+ hexdump(printf, "rnm", sample, sizeof sample);
#endif
- rnd_add_data(&sc->sc_rndsrc, sample, sizeof sample,
- NBBY*sizeof(sample)/BPB);
- octeon_rnm_iobdma(sc, sample, __arraycount(sample));
-#ifdef OCTEON_RNM_DEBUG
- hexdump(printf, "rnm", sample, sizeof sample);
-#endif
- rnd_add_data(&sc->sc_rndsrc, sample, sizeof sample,
- NBBY*sizeof(sample)/BPB);
+ rnd_add_data(&sc->sc_rndsrc, sample, sizeof sample,
+ NBBY*sizeof(sample)/BPB);
+ needed -= MIN(needed, MAX(1, NBBY*sizeof(sample)/BPB));
+ }
+
+ /* Yield if requested. */
+ if (__predict_false(curcpu()->ci_schedstate.spc_flags &
+ SPCF_SHOULDYIELD)) {
+ mutex_exit(&sc->sc_lock);
+ preempt();
+ mutex_enter(&sc->sc_lock);
+ }
}
mutex_exit(&sc->sc_lock);
@@ -357,3 +363,20 @@
for (; nwords --> 0; scraddr += 8)
*buf++ = octeon_cvmseg_read_8(scraddr);
}
+
+/*
+ * octeon_rnm_delay(ncycles)
+ *
+ * Wait ncycles, at most UINT32_MAX/2 so we behave reasonably even
+ * if the cycle counter rolls over.
+ */
+static void
+octeon_rnm_delay(uint32_t ncycles)
+{
+ uint32_t deadline = mips3_cp0_count_read() + ncycles;
+
+ KASSERT(ncycles <= UINT32_MAX/2);
+
+ while ((deadline - mips3_cp0_count_read()) < ncycles)
+ continue;
+}
Home |
Main Index |
Thread Index |
Old Index